Merge pull request #9534 from Ondsel-Development/fix_wb_index_issue
Core: rework WorkbenchGroup & WorkbenchComboBox
This commit is contained in:
@@ -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<int>(&WorkbenchComboBox::activated),
|
||||
this, qOverload<int>(&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<QAction*> 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<int>(&WorkbenchComboBox::activated), this, [this](int index) {
|
||||
actions()[index]->trigger();
|
||||
});
|
||||
};
|
||||
if (widget->inherits("QToolBar")) {
|
||||
auto* box = new WorkbenchComboBox(widget);
|
||||
setupBox(box);
|
||||
|
||||
qobject_cast<QToolBar*>(widget)->addWidget(box);
|
||||
}
|
||||
else if (widget->inherits("QMenuBar")) {
|
||||
auto* box = new WorkbenchComboBox(widget);
|
||||
setupBox(box);
|
||||
|
||||
bool left = WorkbenchSwitcher::isLeftCorner(WorkbenchSwitcher::getValue());
|
||||
qobject_cast<QMenuBar*>(widget)->setCornerWidget(box, left ? Qt::TopLeftCorner : Qt::TopRightCorner);
|
||||
}
|
||||
else if (widget->inherits("QMenu")) {
|
||||
auto menu = qobject_cast<QMenu*>(widget);
|
||||
menu = menu->addMenu(action()->text());
|
||||
menu->addActions(actions());
|
||||
|
||||
connect(this, &WorkbenchGroup::workbenchListRefreshed, this, [menu](QList<QAction*> 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<QAction*> act = actions();
|
||||
for (QList<QAction*>::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<QAction*>(&WorkbenchComboBox::onActivated));
|
||||
};
|
||||
if (widget->inherits("QToolBar")) {
|
||||
auto* box = new WorkbenchComboBox(this, widget);
|
||||
setupBox(box);
|
||||
|
||||
qobject_cast<QToolBar*>(widget)->addWidget(box);
|
||||
}
|
||||
else if (widget->inherits("QMenuBar")) {
|
||||
auto* box = new WorkbenchComboBox(this, widget);
|
||||
setupBox(box);
|
||||
|
||||
bool left = WorkbenchSwitcher::isLeftCorner(WorkbenchSwitcher::getValue());
|
||||
qobject_cast<QMenuBar*>(widget)->setCornerWidget(box, left ? Qt::TopLeftCorner : Qt::TopRightCorner);
|
||||
}
|
||||
else if (widget->inherits("QMenu")) {
|
||||
auto menu = qobject_cast<QMenu*>(widget);
|
||||
menu = menu->addMenu(action()->text());
|
||||
menu->addActions(groupAction()->actions());
|
||||
}
|
||||
}
|
||||
|
||||
void WorkbenchGroup::setWorkbenchData(int index, const QString& wb)
|
||||
{
|
||||
QList<QAction*> 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<QAction*> workbenches = groupAction()->actions();
|
||||
int numActions = workbenches.size();
|
||||
int extend = enabled_wbs_list.size() - numActions;
|
||||
if (extend > 0) {
|
||||
for (int i=0; i<extend; i++) {
|
||||
QAction* action = groupAction()->addAction(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<Gui::WorkbenchActionEvent*>(event);
|
||||
ce->action()->trigger();
|
||||
}
|
||||
}
|
||||
|
||||
void WorkbenchGroup::slotActivateWorkbench(const char* /*name*/)
|
||||
{
|
||||
}
|
||||
|
||||
void WorkbenchGroup::slotAddWorkbench(const char* name)
|
||||
{
|
||||
QList<QAction*> 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<QAction*> 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
|
||||
|
||||
@@ -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<QAction*>);
|
||||
|
||||
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<QAction*>);
|
||||
|
||||
protected Q_SLOTS:
|
||||
void onWorkbenchActivated(const QString&);
|
||||
|
||||
private:
|
||||
void setWorkbenchData(int index, const QString& wb);
|
||||
|
||||
Q_DISABLE_COPY(WorkbenchGroup)
|
||||
};
|
||||
|
||||
|
||||
@@ -126,10 +126,8 @@ public:
|
||||
boost::signals2::signal<void (const Gui::ViewProvider&)> signalActivatedObject;
|
||||
/// signal on activated workbench
|
||||
boost::signals2::signal<void (const char*)> signalActivateWorkbench;
|
||||
/// signal on added workbench
|
||||
boost::signals2::signal<void (const char*)> signalAddWorkbench;
|
||||
/// signal on removed workbench
|
||||
boost::signals2::signal<void (const char*)> signalRemoveWorkbench;
|
||||
/// signal on added/removed workbench
|
||||
boost::signals2::signal<void ()> signalRefreshWorkbenches;
|
||||
/// signal on show hidden items
|
||||
boost::signals2::signal<void (const Gui::Document&)> signalShowHidden;
|
||||
/// signal on activating view
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<wbListItem*>(ui->wbList->itemWidget(ui->wbList->item(i)));
|
||||
if (wbItem) {
|
||||
|
||||
Reference in New Issue
Block a user