Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set/reset the world modified flag and 'DEF' fields #6686

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
5 changes: 5 additions & 0 deletions src/webots/gui/WbMainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "WbNewProjectWizard.hpp"
#include "WbNewProtoWizard.hpp"
#include "WbNewWorldWizard.hpp"
#include "WbNodeEditor.hpp"
#include "WbNodeOperations.hpp"
#include "WbNodeUtilities.hpp"
#include "WbOdeDebugger.hpp"
Expand Down Expand Up @@ -1343,6 +1344,10 @@ void WbMainWindow::updateAfterWorldLoading(bool reloading, bool firstLoad) {
if (world->fileName() != WbProject::newWorldPath())
mRecentFiles->makeRecent(world->fileName());

connect(this, &WbMainWindow::worldCreated, WbNodeEditor::instance(), &WbNodeEditor::tryConnectToWorld);
emit worldCreated();
disconnect(this, &WbMainWindow::worldCreated, WbNodeEditor::instance(), &WbNodeEditor::tryConnectToWorld);

mSimulationView->setWorld(WbSimulationWorld::instance());

// update 'view' menu
Expand Down
1 change: 1 addition & 0 deletions src/webots/gui/WbMainWindow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class WbMainWindow : public QMainWindow {
signals:
void restartRequested();
void splashScreenCloseRequested();
void worldCreated();

public slots:
void loadDifferentWorld(const QString &fileName);
Expand Down
18 changes: 11 additions & 7 deletions src/webots/nodes/utils/WbWorld.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,17 +225,21 @@ bool WbWorld::needSaving() const {
}

void WbWorld::setModifiedFromSceneTree() {
if (!mIsModifiedFromSceneTree) {
mIsModifiedFromSceneTree = true;
setModified();
mIsModifiedFromSceneTree = true;

if (isModifiedFromSceneTreeRestarted) {
mIsModifiedFromSceneTree = false;
isModifiedFromSceneTreeRestarted = false;
}
}

void WbWorld::resetModifiedFromSceneTree() {
mIsModifiedFromSceneTree = false;
isModifiedFromSceneTreeRestarted = true;
}

void WbWorld::setModified(bool isModified) {
if (mIsModified != isModified) {
mIsModified = isModified;
emit modificationChanged(isModified);
}
emit checkDefDiff();
}

bool WbWorld::saveAs(const QString &fileName) {
Expand Down
3 changes: 3 additions & 0 deletions src/webots/nodes/utils/WbWorld.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,14 @@ class WbWorld : public QObject {
void robotAdded(WbRobot *robot);
void robotRemoved(WbRobot *robot);
void resetRequested(bool restartControllers);
void checkDefDiff();

public slots:
void awake();
void updateVideoRecordingStatus(int status) {
mIsVideoRecording = (status == WB_SUPERVISOR_MOVIE_RECORDING || status == WB_SUPERVISOR_MOVIE_SAVING);
}
void resetModifiedFromSceneTree();

protected:
// collecting contact and immersion geometries
Expand Down Expand Up @@ -199,6 +201,7 @@ protected slots:
bool mIsLoading;
bool mIsCleaning;
bool mIsVideoRecording;
bool isModifiedFromSceneTreeRestarted = false;

void checkPresenceOfMandatoryNodes();
WbNode *findTopLevelNode(const QString &modelName, int preferredPosition) const;
Expand Down
13 changes: 11 additions & 2 deletions src/webots/scene_tree/WbFieldEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,18 @@ WbFieldEditor::WbFieldEditor(QWidget *parent) :
connect(stringEditor, &WbExtendedStringEditor::editRequested, this, &WbFieldEditor::editRequested);

WbNodePane *const nodePane = new WbNodePane(this);
const WbNodeEditor *nodeEditor = nodePane->nodeEditor();
const WbNodeEditor *nodeEditor = WbNodeEditor::instance(nodePane);
connect(nodeEditor, &WbNodeEditor::dictionaryUpdateRequested, this, &WbFieldEditor::dictionaryUpdateRequested);

connect(nodeEditor, &WbNodeEditor::defNameChanged, WbActionManager::instance()->action(WbAction::SAVE_WORLD),
&QAction::setEnabled);
connect(WbActionManager::instance()->action(WbAction::SAVE_WORLD), &QAction::setEnabled, nodeEditor,
&WbNodeEditor::resetDefNamesToInitial);
connect(WbActionManager::instance()->action(WbAction::SAVE_WORLD_AS), &QAction::setEnabled, nodeEditor,
&WbNodeEditor::resetDefNamesToInitial);
connect(WbActionManager::instance()->action(WbAction::SAVE_WORLD), &QAction::triggered, nodeEditor,
&WbNodeEditor::switchInitialCurrentDef);
connect(WbActionManager::instance()->action(WbAction::SAVE_WORLD_AS), &QAction::triggered, nodeEditor,
&WbNodeEditor::switchInitialCurrentDef);
// create editors
mEditors.insert(WB_NO_FIELD, new WbEmptyEditor(this));
mEditors.insert(WB_SF_BOOL, new WbBoolEditor(this));
Expand Down
99 changes: 99 additions & 0 deletions src/webots/scene_tree/WbNodeEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "WbNodeEditor.hpp"

#include "WbActionManager.hpp"
#include "WbBaseNode.hpp"
#include "WbField.hpp"
#include "WbFieldLineEdit.hpp"
Expand All @@ -32,9 +33,11 @@
#include "WbTransform.hpp"
#include "WbViewpoint.hpp"
#include "WbVrmlNodeUtilities.hpp"
#include "WbWorld.hpp"
#include "WbWorldInfo.hpp"

#include <QtCore/QDir>
#include <QtCore/QTimer>
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QFileDialog>
Expand All @@ -43,6 +46,14 @@
#include <QtWidgets/QPushButton>
#include <QtWidgets/QStackedWidget>

WbNodeEditor *WbNodeEditor::cInstance = nullptr;

WbNodeEditor *WbNodeEditor::instance(QWidget *parent) {
if (!cInstance)
cInstance = new WbNodeEditor(parent);
return cInstance;
}

WbNodeEditor::WbNodeEditor(QWidget *parent) :
WbValueEditor(parent),
mNode(NULL),
Expand Down Expand Up @@ -87,6 +98,14 @@ WbNodeEditor::WbNodeEditor(QWidget *parent) :
connect(mPrintUrl, &QPushButton::pressed, this, &WbNodeEditor::printUrl);
connect(mShowResizeHandlesCheckBox, &QAbstractButton::toggled, WbSelection::instance(),
&WbSelection::showResizeManipulatorFromSceneTree, Qt::UniqueConnection);
state = WbSimulationState::instance();
}

void WbNodeEditor::tryConnectToWorld() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot have a timer here, we need a cleaner solution

world = WbWorld::instance();
connect(world, &WbWorld::checkDefDiff, this, &WbNodeEditor::resetDefNamesToInitial);
connect(this, &WbNodeEditor::resetModifiedFromSceneTree, world, &WbWorld::resetModifiedFromSceneTree);
mInitialCurrentDefMap.clear();
}

void WbNodeEditor::printUrl() {
Expand Down Expand Up @@ -131,6 +150,9 @@ void WbNodeEditor::edit(bool copyOriginalValue) {
mShowResizeHandlesCheckBox->setChecked(g->isResizeManipulatorAttached());
}
}

if (mNode && !mInitialCurrentDefMap.contains(mNode))
mInitialCurrentDefMap[mNode] = QPair<QString, QString>(mNode->defName(), QString());
}

update();
Expand Down Expand Up @@ -198,6 +220,12 @@ void WbNodeEditor::apply() {
QString newDef = mDefEdit->text();
const QString &previousDef = mNode->defName();

mInitialCurrentDefMap[mNode].second = newDef;

bool hasStarted = state->hasStarted();
if (!hasStarted)
this->compareInitialCurrentDef();

if (newDef == previousDef)
return;

Expand Down Expand Up @@ -259,3 +287,74 @@ void WbNodeEditor::apply() {
if (dictionaryUpdateRequest)
emit dictionaryUpdateRequested();
}

void WbNodeEditor::compareInitialCurrentDef() {
if (!mInitialCurrentDefMap.isEmpty()) {
bool foundDifference = false;
// Iterate through the QMap
for (auto it = mInitialCurrentDefMap.constBegin(); it != mInitialCurrentDefMap.constEnd(); ++it) {
const QString &initialDef = it.value().first; // First QString (initial)
const QString &currentDef = it.value().second; // Second QString (current)

// Compare the two QStrings
if (initialDef != currentDef) {
foundDifference = true; // Mark that a difference is found
break;
}
}
if (foundDifference)
emit defNameChanged(true); // Emit true if any difference is found
else {
emit resetModifiedFromSceneTree();
emit defNameChanged(false); // Emit false if no differences were found
}
} else
emit defNameChanged(false); // If all QStrings are the same, return false
}

void WbNodeEditor::resetDefNamesToInitial() {
// Check if the map is empty
if (mInitialCurrentDefMap.isEmpty()) {
emit defNameChanged(false);
return;
}

// Iterate through the map and reset each node's DEF name to its initial value
for (auto it = mInitialCurrentDefMap.begin(); it != mInitialCurrentDefMap.end(); ++it) {
WbNode *node = it.key();
const QString &initialDef = it.value().first; // Access initial DEF name

// Only reset if node exists and the current DEF differs from the initial one
if (node && node->defName() != initialDef)
node->setDefName(initialDef); // Set the DEF name back to the initial one
}

update();

emit defNameChanged(false);
emit resetModifiedFromSceneTree();
}

void WbNodeEditor::switchInitialCurrentDef() {
// Check if the map is empty
if (mInitialCurrentDefMap.isEmpty()) {
emit defNameChanged(false);
return;
}

// Iterate through the map and switch the initial DEF to the current one
for (auto it = mInitialCurrentDefMap.begin(); it != mInitialCurrentDefMap.end(); ++it) {
const WbNode *node = it.key();

// Switch the initial DEF to the current DEF
if (node) {
QString &initialDef = it.value().first; // Reference to initial DEF name
const QString &currentDef = node->defName(); // Get the current DEF name of the node
initialDef = currentDef; // Update the initial DEF with the current one
}
}

update();

emit defNameChanged(false);
}
15 changes: 14 additions & 1 deletion src/webots/scene_tree/WbNodeEditor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
// Description: editor for editing a WbSFNode or a WbMFNode item
//

#include "WbSimulationState.hpp"
#include "WbValueEditor.hpp"
#include "WbWorld.hpp"

class WbFieldLineEdit;
class WbNode;
Expand All @@ -33,7 +35,7 @@ class WbNodeEditor : public WbValueEditor {
Q_OBJECT

public:
explicit WbNodeEditor(QWidget *parent = NULL);
static WbNodeEditor *instance(QWidget *parent = nullptr);

void recursiveBlockSignals(bool block) override;

Expand All @@ -47,10 +49,15 @@ class WbNodeEditor : public WbValueEditor {

signals:
void dictionaryUpdateRequested();
void defNameChanged(bool changed);
void resetModifiedFromSceneTree();

public slots:
void apply() override;
void cleanValue() override;
void resetDefNamesToInitial();
void switchInitialCurrentDef();
void tryConnectToWorld();

protected:
enum PaneType { DEF_PANE, EMPTY_PANE };
Expand All @@ -63,14 +70,20 @@ public slots:
QLabel *mNbTriangles;
QStackedWidget *mStackedWidget;
bool mMessageBox;
QMap<WbNode *, QPair<QString, QString>> mInitialCurrentDefMap;
const WbWorld *world = nullptr;
WbSimulationState *state = nullptr;
static WbNodeEditor *cInstance;

// actions buttons
QLabel *mShowResizeHandlesLabel;
QCheckBox *mShowResizeHandlesCheckBox;

explicit WbNodeEditor(QWidget *parent = nullptr);
void setTransformActionVisibile(bool visible);
void takeKeyboardFocus() override {}
void printUrl();
void compareInitialCurrentDef();
};

#endif
2 changes: 1 addition & 1 deletion src/webots/scene_tree/WbNodePane.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ static const QStringList cTabNames = QStringList() << "Node"
WbNodePane::WbNodePane(QWidget *parent) :
WbValueEditor(parent),
mTabs(new QTabWidget(this)),
mNodeEditor(new WbNodeEditor()),
mNodeEditor(WbNodeEditor::instance()),
mPhysicsViewer(new WbPhysicsViewer()),
mPositionViewer(new WbPositionViewer()),
mVelocityViewer(new WbVelocityViewer()),
Expand Down
Loading