diff --git a/src/Gui/ToolBarManager.cpp b/src/Gui/ToolBarManager.cpp index 185aa45d92..12c3b862cb 100644 --- a/src/Gui/ToolBarManager.cpp +++ b/src/Gui/ToolBarManager.cpp @@ -37,11 +37,11 @@ using namespace Gui; -ToolBarItem::ToolBarItem() : visibility(HideStyle::VISIBLE) +ToolBarItem::ToolBarItem() : visibilityPolicy(DefaultVisibility::Visible) { } -ToolBarItem::ToolBarItem(ToolBarItem* item, HideStyle visibility) : visibility(visibility) +ToolBarItem::ToolBarItem(ToolBarItem* item, DefaultVisibility visibilityPolicy) : visibilityPolicy(visibilityPolicy) { if (item) { item->appendItem(this); @@ -248,11 +248,31 @@ void ToolBarManager::setup(ToolBarItem* toolBarItems) toolbars.removeAt(index); } - bool visible = hPref->GetBool(toolbarName.c_str(), (*it)->visibility == ToolBarItem::HideStyle::VISIBLE); - visible &= (*it)->visibility != ToolBarItem::HideStyle::FORCE_HIDE; + bool visible = false; + + // If visibility policy is custom, the toolbar is initialised as not visible, and the + // toggleViewAction to control its visibility is not visible either. + // + // Both are managed under the responsibility of the client code + if((*it)->visibilityPolicy != ToolBarItem::DefaultVisibility::Unavailable) { + bool defaultvisibility = (*it)->visibilityPolicy == ToolBarItem::DefaultVisibility::Visible; + + visible = hPref->GetBool(toolbarName.c_str(), defaultvisibility); + + // Enable automatic handling of visibility via, for example, (contextual) menu + toolbar->toggleViewAction()->setVisible(true); + } + else { // ToolBarItem::DefaultVisibility::Unavailable + // Prevent that the action to show/hide a toolbar appears on the (contextual) menus. + // This is also managed by the client code for a toolbar with custom policy + toolbar->toggleViewAction()->setVisible(false); + } + + // Initialise toolbar item visibility toolbar->setVisible(visible); - toolbar->toggleViewAction()->setVisible((*it)->visibility != ToolBarItem::HideStyle::FORCE_HIDE); - toolbar->toggleViewAction()->setProperty("HideStyle", static_cast((*it)->visibility)); + + // Store item visibility policy within the action + toolbar->toggleViewAction()->setProperty("DefaultVisibility", static_cast((*it)->visibilityPolicy)); // setup the toolbar setup(*it, toolbar); @@ -350,15 +370,15 @@ void ToolBarManager::saveState() const return true; } - QVariant property = action->property("HideStyle"); + QVariant property = action->property("DefaultVisibility"); if (property.isNull()) { return false; } - // If hide style is FORCE_HIDE then never save the state because it's - // always controlled by the application. - auto value = static_cast(property.toInt()); - return value == ToolBarItem::HideStyle::FORCE_HIDE; + // If DefaultVisibility is Unavailable then never save the state because it's + // always controlled by the client code. + auto value = static_cast(property.toInt()); + return value == ToolBarItem::DefaultVisibility::Unavailable; }; ParameterGrp::handle hPref = App::GetApplication().GetUserParameter().GetGroup("BaseApp") @@ -450,26 +470,82 @@ QList ToolBarManager::toolBars() const return tb; } -void ToolBarManager::setToolbarVisibility(bool show, const QList& names) { +ToolBarItem::DefaultVisibility ToolBarManager::getToolbarPolicy(const QToolBar* toolbar) const +{ + auto* action = toolbar->toggleViewAction(); + + QVariant property = action->property("DefaultVisibility"); + if (property.isNull()) { + return ToolBarItem::DefaultVisibility::Visible; + } + + return static_cast(property.toInt()); +} + +void ToolBarManager::setState(const QList& names, State state) +{ for (auto& name : names) { - setToolbarVisibility(show, name); + setState(name, state); } } -void ToolBarManager::setToolbarVisibility(bool show, const QString& name) { - +void ToolBarManager::setState(const QString& name, State state) +{ ParameterGrp::handle hPref = App::GetApplication().GetUserParameter().GetGroup("BaseApp")->GetGroup("MainWindow")->GetGroup("Toolbars"); + auto visibility = [hPref, name](bool defaultvalue) { + return hPref->GetBool(name.toStdString().c_str(), defaultvalue); + }; + + auto saveVisibility = [hPref, name](bool value) { + hPref->SetBool(name.toStdString().c_str(), value); + }; + + auto showhide = [visibility](QToolBar* toolbar, ToolBarItem::DefaultVisibility policy) { + + auto show = visibility( policy == ToolBarItem::DefaultVisibility::Visible ); + + if(show) { + toolbar->show(); + } + else { + toolbar->hide(); + } + }; + QToolBar* tb = findToolBar(toolBars(), name); if (tb) { - if (show) { - if(hPref->GetBool(name.toStdString().c_str(), true)) - tb->show(); - tb->toggleViewAction()->setVisible(true); + + if (state == State::RestoreDefault) { + + auto policy = getToolbarPolicy(tb); + + if(policy == ToolBarItem::DefaultVisibility::Unavailable) { + tb->hide(); + tb->toggleViewAction()->setVisible(false); + } + else { + tb->toggleViewAction()->setVisible(true); + + showhide(tb, policy); + } } - else { - tb->hide(); - tb->toggleViewAction()->setVisible(false); + else if (state == State::ForceAvailable) { + + auto policy = getToolbarPolicy(tb); + + tb->toggleViewAction()->setVisible(true); + + showhide(tb, policy); + } + else if (state == State::ForceHidden) { + tb->toggleViewAction()->setVisible(false); // not visible in context menus + tb->hide(); // toolbar not visible + + } + else if (state == State::SaveState) { + auto show = tb->isVisible(); + saveVisibility(show); } } } diff --git a/src/Gui/ToolBarManager.h b/src/Gui/ToolBarManager.h index 15af96ab2d..1aa631ea94 100644 --- a/src/Gui/ToolBarManager.h +++ b/src/Gui/ToolBarManager.h @@ -36,14 +36,19 @@ namespace Gui { class GuiExport ToolBarItem { public: - enum class HideStyle { - VISIBLE, - HIDDEN, // toolbar hidden by default - FORCE_HIDE // Force a toolbar to be hidden. For when all elements are disabled at some point in a workbench. + /** Manages the default visibility status of a toolbar item, as well as the default status + * of the toggleViewAction usable by the contextual menu to enable and disable its visibility + */ + enum class DefaultVisibility { + Visible, // toolbar is hidden by default, visibility toggle action is enabled + Hidden, // toolbar hidden by default, visibility toggle action is enabled + Unavailable, // toolbar visibility is managed independently by client code and defaults to + // hidden, visibility toggle action is disabled by default (it is unavailable + // to the UI). }; ToolBarItem(); - explicit ToolBarItem(ToolBarItem* item, HideStyle visibility = HideStyle::VISIBLE); + explicit ToolBarItem(ToolBarItem* item, DefaultVisibility visibilityPolicy = DefaultVisibility::Visible); ~ToolBarItem(); void setCommand(const std::string&); @@ -63,7 +68,7 @@ public: ToolBarItem& operator << (const std::string& command); QList getItems() const; - HideStyle visibility; + DefaultVisibility visibilityPolicy; private: std::string _name; @@ -80,6 +85,14 @@ private: class GuiExport ToolBarManager { public: + + enum class State { + ForceHidden, // Forces a toolbar to hide and hides the toggle action + ForceAvailable, // Forces a toolbar toggle action to show, visibility depends on user config + RestoreDefault, // Restores a toolbar toggle action default, visibility as user config + SaveState, // Saves the state of the toolbars + }; + /// The one and only instance. static ToolBarManager* getInstance(); static void destruct(); @@ -90,11 +103,15 @@ public: void retranslate() const; void setMovable(bool movable) const; - void setToolbarVisibility(bool show, const QList& names); - void setToolbarVisibility(bool show, const QString& name); + + void setState(const QList& names, State state); + void setState (const QString& name, State state); protected: void setup(ToolBarItem*, QToolBar*) const; + + ToolBarItem::DefaultVisibility getToolbarPolicy(const QToolBar *) const; + /** Returns a list of all currently existing toolbars. */ QList toolBars() const; QToolBar* findToolBar(const QList&, const QString&) const; diff --git a/src/Gui/Workbench.cpp b/src/Gui/Workbench.cpp index cf20dcfe27..e94a3e9fc9 100644 --- a/src/Gui/Workbench.cpp +++ b/src/Gui/Workbench.cpp @@ -774,7 +774,7 @@ ToolBarItem* StdWorkbench::setupToolBars() const << "Separator" << "Std_Refresh"; // Clipboard - auto clipboard = new ToolBarItem( root , ToolBarItem::HideStyle::HIDDEN ); + auto clipboard = new ToolBarItem( root , ToolBarItem::DefaultVisibility::Hidden ); clipboard->setCommand("Clipboard"); *clipboard << "Std_Cut" << "Std_Copy" << "Std_Paste"; diff --git a/src/Mod/Sketcher/Gui/Workbench.cpp b/src/Mod/Sketcher/Gui/Workbench.cpp index c107f14052..32dc53216b 100644 --- a/src/Mod/Sketcher/Gui/Workbench.cpp +++ b/src/Mod/Sketcher/Gui/Workbench.cpp @@ -24,8 +24,10 @@ #include "Utils.h" #include "Workbench.h" +#include #include #include +#include #include using namespace SketcherGui; @@ -106,34 +108,37 @@ Gui::ToolBarItem* Workbench::setupToolBars() const addSketcherWorkbenchSketchActions(*sketcher); Gui::ToolBarItem* sketcherEditMode = - new Gui::ToolBarItem(root, Gui::ToolBarItem::HideStyle::FORCE_HIDE); + new Gui::ToolBarItem(root, Gui::ToolBarItem::DefaultVisibility::Unavailable); sketcherEditMode->setCommand("Sketcher Edit Mode"); addSketcherWorkbenchSketchEditModeActions(*sketcherEditMode); - Gui::ToolBarItem* geom = new Gui::ToolBarItem(root, Gui::ToolBarItem::HideStyle::FORCE_HIDE); + Gui::ToolBarItem* geom = + new Gui::ToolBarItem(root, Gui::ToolBarItem::DefaultVisibility::Unavailable); geom->setCommand("Sketcher geometries"); addSketcherWorkbenchGeometries(*geom); - Gui::ToolBarItem* cons = new Gui::ToolBarItem(root, Gui::ToolBarItem::HideStyle::FORCE_HIDE); + Gui::ToolBarItem* cons = + new Gui::ToolBarItem(root, Gui::ToolBarItem::DefaultVisibility::Unavailable); cons->setCommand("Sketcher constraints"); addSketcherWorkbenchConstraints(*cons); Gui::ToolBarItem* consaccel = - new Gui::ToolBarItem(root, Gui::ToolBarItem::HideStyle::FORCE_HIDE); + new Gui::ToolBarItem(root, Gui::ToolBarItem::DefaultVisibility::Unavailable); consaccel->setCommand("Sketcher tools"); addSketcherWorkbenchTools(*consaccel); - Gui::ToolBarItem* bspline = new Gui::ToolBarItem(root, Gui::ToolBarItem::HideStyle::FORCE_HIDE); + Gui::ToolBarItem* bspline = + new Gui::ToolBarItem(root, Gui::ToolBarItem::DefaultVisibility::Unavailable); bspline->setCommand("Sketcher B-spline tools"); addSketcherWorkbenchBSplines(*bspline); Gui::ToolBarItem* virtualspace = - new Gui::ToolBarItem(root, Gui::ToolBarItem::HideStyle::FORCE_HIDE); + new Gui::ToolBarItem(root, Gui::ToolBarItem::DefaultVisibility::Unavailable); virtualspace->setCommand("Sketcher virtual space"); addSketcherWorkbenchVirtualSpace(*virtualspace); Gui::ToolBarItem* edittools = - new Gui::ToolBarItem(root, Gui::ToolBarItem::HideStyle::FORCE_HIDE); + new Gui::ToolBarItem(root, Gui::ToolBarItem::DefaultVisibility::Unavailable); edittools->setCommand("Sketcher edit tools"); addSketcherWorkbenchEditTools(*edittools); @@ -147,13 +152,6 @@ Gui::ToolBarItem* Workbench::setupCommandBars() const return root; } -void Workbench::activated() -{ - Gui::Document* doc = Gui::Application::Instance->activeDocument(); - if (isSketchInEdit(doc)) { - enterEditMode(); - } -} namespace { @@ -174,28 +172,64 @@ inline const QStringList nonEditModeToolbarNames() } }// namespace +void Workbench::activated() +{ + /* When the workbench is activated, it may happen that we are in edit mode or not. + * If we are not in edit mode, the function enterEditMode (called by the ViewProvider) takes + * care to save the state of toolbars outside of edit mode. We cannot do it here, as we are + * coming from another WB. + * + * If we moved to another WB from edit mode, the new WB was activated before deactivating this. + * Therefore we had no chance to tidy up the save state. We assume a loss of any CHANGE to + * toolbar configuration since last entering edit mode in this case (for any change in + * configuration to be stored, the edit mode must be left while the selected Workbench is the + * sketcher WB). + * + * However, now that we are back (from another WB), we need to make the toolbars available. + * These correspond to the last saved state. + */ + Base::Console().Log("Sketch WB: Activated\n"); + Gui::Document* doc = Gui::Application::Instance->activeDocument(); + if (isSketchInEdit(doc)) { + Gui::ToolBarManager::getInstance()->setState(editModeToolbarNames(), + Gui::ToolBarManager::State::ForceAvailable); + } +} + void Workbench::enterEditMode() { - /*Modify toolbars dynamically. - First save state of toolbars in case user changed visibility of a toolbar but he's not changing - the wb. This happens in someone works directly from sketcher, changing from edit mode to - not-edit-mode*/ - Gui::ToolBarManager::getInstance()->saveState(); + /* Ensure the state left by the non-edit mode toolbars is saved (in case of changing to edit + * mode) without changing workbench + */ + Gui::ToolBarManager::getInstance()->setState(nonEditModeToolbarNames(), + Gui::ToolBarManager::State::SaveState); - Gui::ToolBarManager::getInstance()->setToolbarVisibility(true, editModeToolbarNames()); - Gui::ToolBarManager::getInstance()->setToolbarVisibility(false, nonEditModeToolbarNames()); + Gui::ToolBarManager::getInstance()->setState(editModeToolbarNames(), + Gui::ToolBarManager::State::ForceAvailable); + Gui::ToolBarManager::getInstance()->setState(nonEditModeToolbarNames(), + Gui::ToolBarManager::State::ForceHidden); } void Workbench::leaveEditMode() { - /*Modify toolbars dynamically. - First save state of toolbars in case user changed visibility of a toolbar but he's not changing - the wb. This happens in someone works directly from sketcher, changing from edit mode to - not-edit-mode*/ - Gui::ToolBarManager::getInstance()->saveState(); + /* Ensure the state left by the edit mode toolbars is saved (in case of changing to edit mode) + * without changing workbench. + * + * However, do not save state if the current workbench is not the Sketcher WB, because otherwise + * we would be saving the state of the currently activated workbench, and the toolbars would + * disappear (as the toolbars of that other WB are only visible). + */ + auto* workbench = Gui::WorkbenchManager::instance()->active(); - Gui::ToolBarManager::getInstance()->setToolbarVisibility(false, editModeToolbarNames()); - Gui::ToolBarManager::getInstance()->setToolbarVisibility(true, nonEditModeToolbarNames()); + if (workbench->name() == "SketcherWorkbench") { + Gui::ToolBarManager::getInstance()->setState(editModeToolbarNames(), + Gui::ToolBarManager::State::SaveState); + } + + Gui::ToolBarManager::getInstance()->setState(editModeToolbarNames(), + Gui::ToolBarManager::State::RestoreDefault); + Gui::ToolBarManager::getInstance()->setState(nonEditModeToolbarNames(), + Gui::ToolBarManager::State::RestoreDefault); } namespace SketcherGui