diff --git a/src/Gui/Action.cpp b/src/Gui/Action.cpp index 32f5ecb0aa..3105ad1ca7 100644 --- a/src/Gui/Action.cpp +++ b/src/Gui/Action.cpp @@ -59,6 +59,7 @@ #include "WhatsThis.h" #include "Widgets.h" #include "Workbench.h" +#include "WorkbenchManager.h" #include "ShortcutManager.h" #include "Tools.h" @@ -602,34 +603,8 @@ void ActionGroup::onHovered (QAction *act) // -------------------------------------------------------------------- -namespace Gui { - -/** - * The WorkbenchActionEvent class is used to send an event of which workbench must be activated. - * We cannot activate the workbench directly as we will destroy the widget that emits the signal. - * @author Werner Mayer - */ -class WorkbenchActionEvent : public QEvent +WorkbenchComboBox::WorkbenchComboBox(QWidget* parent) : QComboBox(parent) { -public: - explicit WorkbenchActionEvent(QAction* act) - : QEvent(QEvent::User), act(act) - { } - QAction* action() const - { return act; } -private: - QAction* act; - - Q_DISABLE_COPY(WorkbenchActionEvent) -}; -} - -WorkbenchComboBox::WorkbenchComboBox(WorkbenchGroup* wb, QWidget* parent) : QComboBox(parent), group(wb) -{ - connect(this, qOverload(&WorkbenchComboBox::activated), - this, qOverload(&WorkbenchComboBox::onActivated)); - connect(getMainWindow(), &MainWindow::workbenchActivated, - this, &WorkbenchComboBox::onWorkbenchActivated); } void WorkbenchComboBox::showPopup() @@ -644,71 +619,122 @@ void WorkbenchComboBox::showPopup() QComboBox::showPopup(); } -void WorkbenchComboBox::actionEvent ( QActionEvent* qae ) +void WorkbenchComboBox::refreshList(QList actionList) { - QAction *action = qae->action(); - switch (qae->type()) { - case QEvent::ActionAdded: - { - if (action->isVisible()) { - QIcon icon = action->icon(); - if (icon.isNull()) { - this->addItem(action->text(), action->data()); - } - else { - this->addItem(icon, action->text(), action->data()); - } - if (action->isChecked()) { - this->setCurrentIndex(action->data().toInt()); - } - } - break; + clear(); + + for (QAction* action : actionList) { + QIcon icon = action->icon(); + if (icon.isNull()) { + this->addItem(action->text()); } - case QEvent::ActionChanged: - { - QVariant data = action->data(); - int index = this->findData(data); - // added a workbench - if (index < 0 && action->isVisible()) { - QIcon icon = action->icon(); - if (icon.isNull()) - this->addItem(action->text(), data); - else - this->addItem(icon, action->text(), data); - } - // removed a workbench - else if (index >=0 && !action->isVisible()) { - this->removeItem(index); - } - break; + else { + this->addItem(icon, action->text()); } - case QEvent::ActionRemoved: - { - //Nothing needs to be done - break; + + if (action->isChecked()) { + this->setCurrentIndex(this->count() - 1); } - default: - break; } } -void WorkbenchComboBox::onActivated(int item) +/* TRANSLATOR Gui::WorkbenchGroup */ +WorkbenchGroup::WorkbenchGroup ( Command* pcCmd, QObject * parent ) + : ActionGroup( pcCmd, parent ) { - // Send the event to the workbench group to delay the destruction of the emitting widget. - int index = itemData(item).toInt(); - auto ev = new WorkbenchActionEvent(this->actions().at(index)); - QApplication::postEvent(this->group, ev); + refreshWorkbenchList(); + + Application::Instance->signalRefreshWorkbenches.connect(boost::bind(&WorkbenchGroup::refreshWorkbenchList, this)); + + connect(getMainWindow(), &MainWindow::workbenchActivated, + this, &WorkbenchGroup::onWorkbenchActivated); } -void WorkbenchComboBox::onActivated(QAction* action) +void WorkbenchGroup::addTo(QWidget *widget) { - // set the according item to the action - QVariant data = action->data(); - int index = this->findData(data); - setCurrentIndex(index); + auto setupBox = [&](WorkbenchComboBox* box) { + box->setIconSize(QSize(16, 16)); + box->setToolTip(toolTip()); + box->setStatusTip(action()->statusTip()); + box->setWhatsThis(action()->whatsThis()); + box->refreshList(actions()); + connect(this, &WorkbenchGroup::workbenchListRefreshed, box, &WorkbenchComboBox::refreshList); + connect(groupAction(), &QActionGroup::triggered, box, [this, box](QAction* action) { + box->setCurrentIndex(actions().indexOf(action)); + }); + connect(box, qOverload(&WorkbenchComboBox::activated), this, [this](int index) { + actions()[index]->trigger(); + }); + }; + if (widget->inherits("QToolBar")) { + auto* box = new WorkbenchComboBox(widget); + setupBox(box); + + qobject_cast(widget)->addWidget(box); + } + else if (widget->inherits("QMenuBar")) { + auto* box = new WorkbenchComboBox(widget); + setupBox(box); + + bool left = WorkbenchSwitcher::isLeftCorner(WorkbenchSwitcher::getValue()); + qobject_cast(widget)->setCornerWidget(box, left ? Qt::TopLeftCorner : Qt::TopRightCorner); + } + else if (widget->inherits("QMenu")) { + auto menu = qobject_cast(widget); + menu = menu->addMenu(action()->text()); + menu->addActions(actions()); + + connect(this, &WorkbenchGroup::workbenchListRefreshed, this, [menu](QList actions) { + menu->clear(); + menu->addActions(actions); + }); + } } -void WorkbenchComboBox::onWorkbenchActivated(const QString& name) +void WorkbenchGroup::refreshWorkbenchList() +{ + QStringList enabled_wbs_list = DlgSettingsWorkbenchesImp::getEnabledWorkbenches(); + + // Clear the actions. + for (QAction* action : actions()) { + groupAction()->removeAction(action); + delete action; + } + + std::string activeWbName = ""; + Workbench* activeWB = WorkbenchManager::instance()->active(); + if (activeWB) + activeWbName = activeWB->name(); + + // Create action list of enabled wb + int index = 0; + for (const auto& wbName : enabled_wbs_list) { + QString name = Application::Instance->workbenchMenuText(wbName); + QPixmap px = Application::Instance->workbenchIcon(wbName); + QString tip = Application::Instance->workbenchToolTip(wbName); + + QAction* action = groupAction()->addAction(name); + action->setCheckable(true); + action->setData(QVariant(index)); // set the index + action->setObjectName(wbName); + action->setIcon(px); + action->setToolTip(tip); + action->setStatusTip(tr("Select the '%1' workbench").arg(name)); + if (index < 9) { + action->setShortcut(QKeySequence(QString::fromUtf8("W,%1").arg(index + 1))); + } + if (wbName.toStdString() == activeWbName) { + action->setChecked(true); + } + + index++; + } + + // Signal to the widgets (WorkbenchComboBox & menu) to update the wb list + workbenchListRefreshed(actions()); +} + +void WorkbenchGroup::onWorkbenchActivated(const QString& name) { // There might be more than only one instance of WorkbenchComboBox there. // However, all of them share the same QAction objects. Thus, if the user @@ -720,166 +746,17 @@ void WorkbenchComboBox::onWorkbenchActivated(const QString& name) // activateWorkbench the method refreshWorkbenchList() shouldn't set the // checked item. //QVariant item = itemData(currentIndex()); - QList act = actions(); - for (QList::Iterator it = act.begin(); it != act.end(); ++it) { - if ((*it)->objectName() == name) { - if (/*(*it)->data() != item*/!(*it)->isChecked()) { - (*it)->trigger(); + + for (QAction* action : actions()) { + if (action->objectName() == name) { + if (!action->isChecked()) { + action->trigger(); } break; } } } -/* TRANSLATOR Gui::WorkbenchGroup */ -WorkbenchGroup::WorkbenchGroup ( Command* pcCmd, QObject * parent ) - : ActionGroup( pcCmd, parent ) -{ - // Start a list with 50 elements but extend it when requested - for (int i=0; i<50; i++) { - QAction* action = groupAction()->addAction(QLatin1String("")); - action->setVisible(false); - action->setCheckable(true); - action->setData(QVariant(i)); // set the index - } - - Application::Instance->signalActivateWorkbench.connect(boost::bind(&WorkbenchGroup::slotActivateWorkbench, this, bp::_1)); - Application::Instance->signalAddWorkbench.connect(boost::bind(&WorkbenchGroup::slotAddWorkbench, this, bp::_1)); - Application::Instance->signalRemoveWorkbench.connect(boost::bind(&WorkbenchGroup::slotRemoveWorkbench, this, bp::_1)); -} - -void WorkbenchGroup::addTo(QWidget *widget) -{ - refreshWorkbenchList(); - - auto setupBox = [&](WorkbenchComboBox* box) { - box->setIconSize(QSize(16, 16)); - box->setToolTip(toolTip()); - box->setStatusTip(action()->statusTip()); - box->setWhatsThis(action()->whatsThis()); - box->addActions(groupAction()->actions()); - connect(groupAction(), &QActionGroup::triggered, box, qOverload(&WorkbenchComboBox::onActivated)); - }; - if (widget->inherits("QToolBar")) { - auto* box = new WorkbenchComboBox(this, widget); - setupBox(box); - - qobject_cast(widget)->addWidget(box); - } - else if (widget->inherits("QMenuBar")) { - auto* box = new WorkbenchComboBox(this, widget); - setupBox(box); - - bool left = WorkbenchSwitcher::isLeftCorner(WorkbenchSwitcher::getValue()); - qobject_cast(widget)->setCornerWidget(box, left ? Qt::TopLeftCorner : Qt::TopRightCorner); - } - else if (widget->inherits("QMenu")) { - auto menu = qobject_cast(widget); - menu = menu->addMenu(action()->text()); - menu->addActions(groupAction()->actions()); - } -} - -void WorkbenchGroup::setWorkbenchData(int index, const QString& wb) -{ - QList workbenches = groupAction()->actions(); - QString name = Application::Instance->workbenchMenuText(wb); - QPixmap px = Application::Instance->workbenchIcon(wb); - QString tip = Application::Instance->workbenchToolTip(wb); - - workbenches[index]->setObjectName(wb); - workbenches[index]->setIcon(px); - workbenches[index]->setText(name); - workbenches[index]->setToolTip(tip); - workbenches[index]->setStatusTip(tr("Select the '%1' workbench").arg(name)); - workbenches[index]->setVisible(true); - if (index < 9) { - workbenches[index]->setShortcut(QKeySequence(QString::fromUtf8("W,%1").arg(index+1))); - } -} - -void WorkbenchGroup::refreshWorkbenchList() -{ - QStringList enabled_wbs_list = DlgSettingsWorkbenchesImp::getEnabledWorkbenches(); - - // Resize the action group. - QList workbenches = groupAction()->actions(); - int numActions = workbenches.size(); - int extend = enabled_wbs_list.size() - numActions; - if (extend > 0) { - for (int i=0; iaddAction(QLatin1String("")); - action->setCheckable(true); - action->setData(QVariant(numActions++)); // set the index - } - } - - // Show all enabled wb - int index = 0; - for (const auto& it : enabled_wbs_list) { - setWorkbenchData(index++, it); - } -} - -void WorkbenchGroup::customEvent( QEvent* event ) -{ - if (event->type() == QEvent::User) { - auto ce = static_cast(event); - ce->action()->trigger(); - } -} - -void WorkbenchGroup::slotActivateWorkbench(const char* /*name*/) -{ -} - -void WorkbenchGroup::slotAddWorkbench(const char* name) -{ - QList workbenches = groupAction()->actions(); - QAction* action = nullptr; - for (auto it : workbenches) { - if (!it->isVisible()) { - action = it; - break; - } - } - - if (!action) { - int index = workbenches.size(); - action = groupAction()->addAction(QLatin1String("")); - action->setCheckable(true); - action->setData(QVariant(index)); // set the index - } - - QString wb = QString::fromLatin1(name); - QPixmap px = Application::Instance->workbenchIcon(wb); - QString text = Application::Instance->workbenchMenuText(wb); - QString tip = Application::Instance->workbenchToolTip(wb); - action->setIcon(px); - action->setObjectName(wb); - action->setText(text); - action->setToolTip(tip); - action->setStatusTip(tr("Select the '%1' workbench").arg(wb)); - action->setVisible(true); // do this at last -} - -void WorkbenchGroup::slotRemoveWorkbench(const char* name) -{ - QString workbench = QString::fromLatin1(name); - QList workbenches = groupAction()->actions(); - for (auto it : workbenches) { - if (it->objectName() == workbench) { - it->setObjectName(QString()); - it->setIcon(QIcon()); - it->setText(QString()); - it->setToolTip(QString()); - it->setStatusTip(QString()); - it->setVisible(false); // do this at last - break; - } - } -} - // -------------------------------------------------------------------- class RecentFilesAction::Private: public ParameterGrp::ObserverType diff --git a/src/Gui/Action.h b/src/Gui/Action.h index 684a653cfc..4be36fa8e7 100644 --- a/src/Gui/Action.h +++ b/src/Gui/Action.h @@ -177,29 +177,18 @@ private: }; // -------------------------------------------------------------------- - -class WorkbenchGroup; class GuiExport WorkbenchComboBox : public QComboBox { Q_OBJECT public: - explicit WorkbenchComboBox(WorkbenchGroup* wb, QWidget* parent=nullptr); + explicit WorkbenchComboBox(QWidget* parent=nullptr); void showPopup() override; public Q_SLOTS: - void onActivated(int); - void onActivated(QAction*); - -protected Q_SLOTS: - void onWorkbenchActivated(const QString&); - -protected: - void actionEvent (QActionEvent*) override; + void refreshList(QList); private: - WorkbenchGroup* group; - Q_DISABLE_COPY(WorkbenchComboBox) }; @@ -222,15 +211,14 @@ public: void refreshWorkbenchList(); void slotActivateWorkbench(const char*); - void slotAddWorkbench(const char*); - void slotRemoveWorkbench(const char*); -protected: - void customEvent(QEvent* event) override; +Q_SIGNALS: + void workbenchListRefreshed(QList); + +protected Q_SLOTS: + void onWorkbenchActivated(const QString&); private: - void setWorkbenchData(int index, const QString& wb); - Q_DISABLE_COPY(WorkbenchGroup) }; diff --git a/src/Gui/Application.h b/src/Gui/Application.h index ba2b46601b..4ce5701f97 100644 --- a/src/Gui/Application.h +++ b/src/Gui/Application.h @@ -126,10 +126,8 @@ public: boost::signals2::signal signalActivatedObject; /// signal on activated workbench boost::signals2::signal signalActivateWorkbench; - /// signal on added workbench - boost::signals2::signal signalAddWorkbench; - /// signal on removed workbench - boost::signals2::signal signalRemoveWorkbench; + /// signal on added/removed workbench + boost::signals2::signal signalRefreshWorkbenches; /// signal on show hidden items boost::signals2::signal signalShowHidden; /// signal on activating view diff --git a/src/Gui/ApplicationPy.cpp b/src/Gui/ApplicationPy.cpp index 82154fc7f3..d9a43af0bf 100644 --- a/src/Gui/ApplicationPy.cpp +++ b/src/Gui/ApplicationPy.cpp @@ -976,7 +976,7 @@ PyObject* Application::sAddWorkbenchHandler(PyObject * /*self*/, PyObject *args) } PyDict_SetItemString(Instance->_pcWorkbenchDictionary,item.c_str(),object.ptr()); - Instance->signalAddWorkbench(item.c_str()); + Instance->signalRefreshWorkbenches(); } catch (const Py::Exception&) { return nullptr; @@ -997,9 +997,9 @@ PyObject* Application::sRemoveWorkbenchHandler(PyObject * /*self*/, PyObject *ar return nullptr; } - Instance->signalRemoveWorkbench(psKey); WorkbenchManager::instance()->removeWorkbench(psKey); PyDict_DelItemString(Instance->_pcWorkbenchDictionary,psKey); + Instance->signalRefreshWorkbenches(); Py_Return; } diff --git a/src/Gui/DlgSettingsWorkbenchesImp.cpp b/src/Gui/DlgSettingsWorkbenchesImp.cpp index 84269b6a18..aea9e7b60c 100644 --- a/src/Gui/DlgSettingsWorkbenchesImp.cpp +++ b/src/Gui/DlgSettingsWorkbenchesImp.cpp @@ -293,6 +293,9 @@ void DlgSettingsWorkbenchesImp::saveSettings() hGrp->SetASCII("Ordered", orderedStr.str().c_str()); hGrp->SetASCII("Disabled", disabledStr.str().c_str()); + //Update the list of workbenches in the WorkbenchGroup and in the WorkbenchComboBox & workbench QMenu + Application::Instance->signalRefreshWorkbenches(); + App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/General")-> SetASCII("BackgroundAutoloadModules", autoloadStr.str().c_str()); @@ -477,8 +480,6 @@ void DlgSettingsWorkbenchesImp::loadWorkbenchSelector() void DlgSettingsWorkbenchesImp::wbToggled(const QString& wbName, bool enabled) { - requireRestart(); - setStartWorkbenchComboItems(); //reorder the list of items. @@ -551,7 +552,6 @@ void DlgSettingsWorkbenchesImp::setStartWorkbenchComboItems() void DlgSettingsWorkbenchesImp::wbItemMoved() { - requireRestart(); for (int i = 0; i < ui->wbList->count(); i++) { wbListItem* wbItem = dynamic_cast(ui->wbList->itemWidget(ui->wbList->item(i))); if (wbItem) {