diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index e2412c0c6d..3b6bb31bc8 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -322,6 +322,7 @@ set(Gui_MOC_HDRS DlgSettingsColorGradientImp.h DlgSettingsDocumentImp.h DlgSettingsImageImp.h + DlgSettingsLazyLoadedImp.h DlgSettingsMacroImp.h DlgSettingsUnitsImp.h DlgCheckableMessageBox.h @@ -450,6 +451,7 @@ SET(Gui_UIC_SRCS DlgSettingsColorGradient.ui DlgSettingsDocument.ui DlgSettingsImage.ui + DlgSettingsLazyLoaded.ui DlgSettingsMacro.ui DlgCheckableMessageBox.ui DlgToolbars.ui @@ -681,6 +683,7 @@ SET(Dialog_Settings_CPP_SRCS DlgSettingsColorGradientImp.cpp DlgSettingsDocumentImp.cpp DlgSettingsImageImp.cpp + DlgSettingsLazyLoadedImp.cpp DlgSettingsMacroImp.cpp ) SET(Dialog_Settings_HPP_SRCS @@ -697,6 +700,7 @@ SET(Dialog_Settings_HPP_SRCS DlgSettingsColorGradientImp.h DlgSettingsDocumentImp.h DlgSettingsImageImp.h + DlgSettingsLazyLoadedImp.h DlgSettingsMacroImp.h ) SET(Dialog_Settings_SRCS @@ -715,6 +719,7 @@ SET(Dialog_Settings_SRCS DlgSettingsColorGradient.ui DlgSettingsDocument.ui DlgSettingsImage.ui + DlgSettingsLazyLoaded.ui DlgSettingsMacro.ui ) SOURCE_GROUP("Dialog\\Settings" FILES ${Dialog_Settings_SRCS}) diff --git a/src/Gui/DlgPreferencesImp.cpp b/src/Gui/DlgPreferencesImp.cpp index 6ac6bd973f..d0be413089 100644 --- a/src/Gui/DlgPreferencesImp.cpp +++ b/src/Gui/DlgPreferencesImp.cpp @@ -48,16 +48,18 @@ #include "BitmapFactory.h" #include "MainWindow.h" - using namespace Gui::Dialog; +const int DlgPreferencesImp::GroupNameRole = Qt::UserRole; + /* TRANSLATOR Gui::Dialog::DlgPreferencesImp */ std::list DlgPreferencesImp::_pages; +DlgPreferencesImp* DlgPreferencesImp::_activeDialog = nullptr; /** - * Constructs a DlgPreferencesImp which is a child of 'parent', with the - * name 'name' and widget flags set to 'f' + * Constructs a DlgPreferencesImp which is a child of 'parent', with + * widget flags set to 'fl' * * The dialog will by default be modeless, unless you set 'modal' to * true to construct a modal dialog. @@ -67,8 +69,8 @@ DlgPreferencesImp::DlgPreferencesImp(QWidget* parent, Qt::WindowFlags fl) invalidParameter(false), canEmbedScrollArea(true) { ui->setupUi(this); - ui->listBox->setFixedWidth(130); - ui->listBox->setGridSize(QSize(108, 120)); + ui->listBox->setFixedWidth(108); + ui->listBox->setGridSize(QSize(90, 75)); connect(ui->buttonBox, SIGNAL (helpRequested()), getMainWindow(), SLOT (whatsThis())); @@ -76,6 +78,11 @@ DlgPreferencesImp::DlgPreferencesImp(QWidget* parent, Qt::WindowFlags fl) this, SLOT(changeGroup(QListWidgetItem *, QListWidgetItem*))); setupPages(); + + // Maintain a static pointer to the current active dialog (if there is one) so that + // if the static page manipulation functions are called while the dialog is showing + // it can update its content. + DlgPreferencesImp::_activeDialog = this; } /** @@ -83,50 +90,19 @@ DlgPreferencesImp::DlgPreferencesImp(QWidget* parent, Qt::WindowFlags fl) */ DlgPreferencesImp::~DlgPreferencesImp() { - // no need to delete child widgets, Qt does it all for us - delete ui; + if (DlgPreferencesImp::_activeDialog == this) { + DlgPreferencesImp::_activeDialog = nullptr; + } } void DlgPreferencesImp::setupPages() { // make sure that pages are ready to create GetWidgetFactorySupplier(); - for (std::list::iterator it = _pages.begin(); it != _pages.end(); ++it) { - QTabWidget* tabWidget = new QTabWidget; - ui->tabWidgetStack->addWidget(tabWidget); - - QByteArray group = it->first.c_str(); - QListWidgetItem *item = new QListWidgetItem(ui->listBox); - item->setData(Qt::UserRole, QVariant(group)); - item->setText(QObject::tr(group.constData())); - std::string fileName = it->first; - for (std::string::iterator ch = fileName.begin(); ch != fileName.end(); ++ch) { - if (*ch == ' ') *ch = '_'; - else *ch = tolower(*ch); - } - fileName = std::string("preferences-") + fileName; - QPixmap icon = Gui::BitmapFactory().pixmapFromSvg(fileName.c_str(), QSize(96,96)); - if (icon.isNull()) { - icon = Gui::BitmapFactory().pixmap(fileName.c_str()); - if (icon.isNull()) { - qWarning() << "No group icon found for " << fileName.c_str(); - } - else if (icon.size() != QSize(96,96)) { - qWarning() << "Group icon for " << fileName.c_str() << " is not of size 96x96"; - } - } - item->setIcon(icon); - item->setTextAlignment(Qt::AlignHCenter); - item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); - for (std::list::iterator jt = it->second.begin(); jt != it->second.end(); ++jt) { - PreferencePage* page = WidgetFactory().createPreferencePage(jt->c_str()); - if (page) { - tabWidget->addTab(page, page->windowTitle()); - page->loadSettings(); - } - else { - Base::Console().Warning("%s is not a preference page\n", jt->c_str()); - } + for (const auto &group : _pages) { + QTabWidget* groupTab = createTabForGroup(group.first); + for (const auto &page : group.second) { + createPageInGroup(groupTab, page); } } @@ -134,6 +110,63 @@ void DlgPreferencesImp::setupPages() ui->listBox->setCurrentRow(0); } +/** + * Create the necessary widgets for a new group named \a groupName. Returns a + * pointer to the group's QTabWidget: that widget's lifetime is managed by the + * tabWidgetStack, do not manually deallocate. + */ +QTabWidget* DlgPreferencesImp::createTabForGroup(const std::string &groupName) +{ + QString groupNameQString = QString::fromStdString(groupName); + + QTabWidget* tabWidget = new QTabWidget; + ui->tabWidgetStack->addWidget(tabWidget); + tabWidget->setProperty("GroupName", QVariant(groupNameQString)); + + QListWidgetItem* item = new QListWidgetItem(ui->listBox); + item->setData(GroupNameRole, QVariant(groupNameQString)); + item->setText(QObject::tr(groupNameQString.toLatin1())); + std::string fileName = groupName; + for (auto & ch : fileName) { + if (ch == ' ') ch = '_'; + else ch = tolower(ch); + } + fileName = std::string("preferences-") + fileName; + QPixmap icon = Gui::BitmapFactory().pixmapFromSvg(fileName.c_str(), QSize(48, 48)); + if (icon.isNull()) { + icon = Gui::BitmapFactory().pixmap(fileName.c_str()); + if (icon.isNull()) { + qWarning() << "No group icon found for " << fileName.c_str(); + } + else if (icon.size() != QSize(48, 48)) { + icon = Gui::BitmapFactory().resize(48, 48, icon, Qt::TransparentMode); + qWarning() << "Group icon for " << fileName.c_str() << " is not of size 48x48, so it was scaled"; + } + } + item->setIcon(icon); + item->setTextAlignment(Qt::AlignHCenter); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + + return tabWidget; +} + +/** + * Create a new preference page called \a pageName on the group tab \a tabWidget. + */ +void DlgPreferencesImp::createPageInGroup(QTabWidget *tabWidget, const std::string &pageName) +{ + PreferencePage* page = WidgetFactory().createPreferencePage(pageName.c_str()); + if (page) { + tabWidget->addTab(page, page->windowTitle()); + page->loadSettings(); + page->setProperty("GroupName", tabWidget->property("GroupName")); + page->setProperty("PageName", QVariant(QString::fromStdString(pageName))); + } + else { + Base::Console().Warning("%s is not a preference page\n", pageName.c_str()); + } +} + void DlgPreferencesImp::changeGroup(QListWidgetItem *current, QListWidgetItem *previous) { if (!current) @@ -160,6 +193,10 @@ void DlgPreferencesImp::addPage(const std::string& className, const std::string& std::list pages; pages.push_back(className); _pages.push_back(std::make_pair(group, pages)); + + if (DlgPreferencesImp::_activeDialog != nullptr) { + _activeDialog->reloadPages(); + } } void DlgPreferencesImp::removePage(const std::string& className, const std::string& group) @@ -193,7 +230,7 @@ void DlgPreferencesImp::activateGroupPage(const QString& group, int index) int ct = ui->listBox->count(); for (int i=0; ilistBox->item(i); - if (item->data(Qt::UserRole).toString() == group) { + if (item->data(GroupNameRole).toString() == group) { ui->listBox->setCurrentItem(item); QTabWidget* tabWidget = (QTabWidget*)ui->tabWidgetStack->widget(i); tabWidget->setCurrentIndex(index); @@ -250,6 +287,57 @@ void DlgPreferencesImp::restoreDefaults() } } +/** + * If the dialog is currently showing and the static variable _pages changed, this function + * will rescan that list of pages and add any that are new to the current dialog. It will not + * remove any pages that are no longer in the list, and will not change the user's current + * active page. + */ +void DlgPreferencesImp::reloadPages() +{ + // Make sure that pages are ready to create + GetWidgetFactorySupplier(); + + for (const auto &group : _pages) { + QString groupName = QString::fromStdString(group.first); + + // First, does this group already exist? + QTabWidget* tabWidget = nullptr; + for (int tabNumber = 0; tabNumber < ui->tabWidgetStack->count(); ++tabNumber) { + auto thisTabWidget = qobject_cast(ui->tabWidgetStack->widget(tabNumber)); + if (thisTabWidget->property("GroupName").toString() == groupName) { + tabWidget = thisTabWidget; + break; + } + } + + // This is a new tab that wasn't there when we started this instance of the dialog: + if (!tabWidget) { + tabWidget = createTabForGroup(group.first); + } + + // Move on to the pages in the group to see if we need to add any + for (const auto& page : group.second) { + + // Does this page already exist? + QString pageName = QString::fromStdString(page); + bool pageExists = false; + for (int pageNumber = 0; pageNumber < tabWidget->count(); ++pageNumber) { + PreferencePage* prefPage = qobject_cast(tabWidget->widget(pageNumber)); + if (prefPage && prefPage->property("PageName").toString() == pageName) { + pageExists = true; + break; + } + } + + // This is a new page that wasn't there when we started this instance of the dialog: + if (!pageExists) { + createPageInGroup(tabWidget, page); + } + } + } +} + void DlgPreferencesImp::applyChanges() { // Checks if any of the classes that represent several pages of settings @@ -366,7 +454,7 @@ void DlgPreferencesImp::changeEvent(QEvent *e) // update the items' text for (int i=0; ilistBox->count(); i++) { QListWidgetItem *item = ui->listBox->item(i); - QByteArray group = item->data(Qt::UserRole).toByteArray(); + QByteArray group = item->data(GroupNameRole).toByteArray(); item->setText(QObject::tr(group.constData())); } } else { diff --git a/src/Gui/DlgPreferencesImp.h b/src/Gui/DlgPreferencesImp.h index 6b6ff17ee4..172baba36d 100644 --- a/src/Gui/DlgPreferencesImp.h +++ b/src/Gui/DlgPreferencesImp.h @@ -25,9 +25,11 @@ #define GUI_DIALOG_DLGPREFERENCESIMP_H #include +#include class QAbstractButton; class QListWidgetItem; +class QTabWidget; namespace Gui { namespace Dialog { @@ -123,6 +125,7 @@ protected: void showEvent(QShowEvent*); void resizeEvent(QResizeEvent*); + protected Q_SLOTS: void changeGroup(QListWidgetItem *current, QListWidgetItem *previous); void on_buttonBox_clicked(QAbstractButton*); @@ -132,16 +135,23 @@ private: /** @name for internal use only */ //@{ void setupPages(); + QTabWidget* createTabForGroup(const std::string& groupName); + void createPageInGroup(QTabWidget* tabWidget, const std::string& pageName); void applyChanges(); void restoreDefaults(); + void reloadPages(); //@} private: - typedef std::pair > TGroupPages; + typedef std::pair> TGroupPages; static std::list _pages; /**< Name of all registered preference pages */ - Ui_DlgPreferences* ui; + std::unique_ptr ui; bool invalidParameter; bool canEmbedScrollArea; + + static const int GroupNameRole; /**< A name for our Qt::UserRole, used when storing user data in a list item */ + + static DlgPreferencesImp* _activeDialog; /**< Defaults to the nullptr, points to the current instance if there is one */ }; } // namespace Dialog diff --git a/src/Gui/DlgSettingsLazyLoaded.ui b/src/Gui/DlgSettingsLazyLoaded.ui new file mode 100644 index 0000000000..3bfd0e9490 --- /dev/null +++ b/src/Gui/DlgSettingsLazyLoaded.ui @@ -0,0 +1,106 @@ + + + Gui::Dialog::DlgSettingsLazyLoaded + + + + 0 + 0 + 607 + 859 + + + + Unloaded Workbenches + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + <html><head/><body><p>Load the selected workbenches, adding their preference windows to the preferences dialog.</p></body></html> + + + Load Selected + + + + + + + + + + 0 + 0 + + + + + 0 + 150 + + + + <html><head/><body><p>Available unloaded workbenches</p></body></html> + + + QAbstractItemView::ExtendedSelection + + + + + + + + 0 + 0 + + + + + 0 + 50 + + + + <html><head/><body><p>To preserve resources, FreeCAD does not load workbenches until they are used. Loading them may provide access to additional preferences related to their functionality.</p><p>The following workbenches are available in your installation, but are not yet loaded:</p></body></html> + + + true + + + + + + + Qt::Vertical + + + + 429 + 37 + + + + + + + + + + diff --git a/src/Gui/DlgSettingsLazyLoadedImp.cpp b/src/Gui/DlgSettingsLazyLoadedImp.cpp new file mode 100644 index 0000000000..5f2a625d34 --- /dev/null +++ b/src/Gui/DlgSettingsLazyLoadedImp.cpp @@ -0,0 +1,118 @@ +/*************************************************************************** + * Copyright (c) 2020 Chris Hennes (chennes@pioneerlibrarysystem.org) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#include "DlgSettingsLazyLoadedImp.h" +#include "ui_DlgSettingsLazyLoaded.h" +#include "PrefWidgets.h" +#include "AutoSaver.h" + +#include "Application.h" +#include "WorkbenchManager.h" +#include "Workbench.h" + +using namespace Gui::Dialog; + +const uint DlgSettingsLazyLoadedImp::WorkbenchNameRole = Qt::UserRole; + +/* TRANSLATOR Gui::Dialog::DlgSettingsLazyLoadedImp */ + +/** + * Constructs a DlgSettingsLazyLoadedImp + */ +DlgSettingsLazyLoadedImp::DlgSettingsLazyLoadedImp( QWidget* parent ) + : PreferencePage( parent ) + , ui(new Ui_DlgSettingsLazyLoaded) +{ + ui->setupUi(this); + buildUnloadedWorkbenchList(); + connect(ui->loadButton, SIGNAL(clicked()), this, SLOT(onLoadClicked())); +} + +/** + * Destroys the object and frees any allocated resources + */ +DlgSettingsLazyLoadedImp::~DlgSettingsLazyLoadedImp() +{ +} + + +void DlgSettingsLazyLoadedImp::saveSettings() +{ + +} + +void DlgSettingsLazyLoadedImp::loadSettings() +{ + +} + +void DlgSettingsLazyLoadedImp::onLoadClicked() +{ + Workbench* originalActiveWB = WorkbenchManager::instance()->active(); + auto selection = ui->workbenchList->selectedItems(); + for (const auto& item : selection) { + auto name = item->data(WorkbenchNameRole).toString().toStdString(); + Application::Instance->activateWorkbench(name.c_str()); + } + Application::Instance->activateWorkbench(originalActiveWB->name().c_str()); + buildUnloadedWorkbenchList(); +} + + +/** +Build the list of unloaded workbenches. +*/ +void DlgSettingsLazyLoadedImp::buildUnloadedWorkbenchList() +{ + ui->workbenchList->clear(); + QStringList workbenches = Application::Instance->workbenches(); + for (const auto& wbName : workbenches) { + const auto& wb = WorkbenchManager::instance()->getWorkbench(wbName.toStdString()); + if (!wb) { + auto wbIcon = Application::Instance->workbenchIcon(wbName); + auto wbDisplayName = Application::Instance->workbenchMenuText(wbName); + auto wbTooltip = Application::Instance->workbenchToolTip(wbName); + QListWidgetItem *wbRow = new QListWidgetItem(wbIcon, wbDisplayName); + wbRow->setData(WorkbenchNameRole, QVariant(wbName)); // Store the actual internal name for easier loading + wbRow->setToolTip(wbTooltip); + ui->workbenchList->addItem(wbRow); // Transfers ownership to the QListWidget + } + } +} + +/** + * Sets the strings of the subwidgets using the current language. + */ +void DlgSettingsLazyLoadedImp::changeEvent(QEvent *e) +{ + if (e->type() == QEvent::LanguageChange) { + ui->retranslateUi(this); + } + else { + QWidget::changeEvent(e); + } +} + +#include "moc_DlgSettingsLazyLoadedImp.cpp" \ No newline at end of file diff --git a/src/Gui/DlgSettingsLazyLoadedImp.h b/src/Gui/DlgSettingsLazyLoadedImp.h new file mode 100644 index 0000000000..71c9ae07d0 --- /dev/null +++ b/src/Gui/DlgSettingsLazyLoadedImp.h @@ -0,0 +1,66 @@ +/*************************************************************************** + * Copyright (c) 2020 Chris Hennes (chennes@pioneerlibrarysystem.org) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef GUI_DIALOG_DLGSETTINGSLAZYLOADED_IMP_H +#define GUI_DIALOG_DLGSETTINGSLAZYLOADED_IMP_H + +#include "PropertyPage.h" +#include + +namespace Gui { +namespace Dialog { +class Ui_DlgSettingsLazyLoaded; + + +/** + * The DlgSettingsLazyLoadedImp class implements a pseudo-preference page explain why + * the remaining preference pages aren't loaded yet, and to help the user do so on demand. + * \author Jürgen Riegel + */ +class DlgSettingsLazyLoadedImp : public PreferencePage +{ + Q_OBJECT + +public: + DlgSettingsLazyLoadedImp( QWidget* parent = 0 ); + ~DlgSettingsLazyLoadedImp(); + + void saveSettings(); + void loadSettings(); + +protected Q_SLOTS: + void onLoadClicked(); + +protected: + void buildUnloadedWorkbenchList(); + void changeEvent(QEvent *e); + +private: + std::unique_ptr ui; + static const uint WorkbenchNameRole; +}; + +} // namespace Dialog +} // namespace Gui + +#endif // GUI_DIALOG_DLGSETTINGSLAZYLOADED_IMP_H diff --git a/src/Gui/Icons/preferences-workbenches.svg b/src/Gui/Icons/preferences-workbenches.svg new file mode 100644 index 0000000000..370abc9f77 --- /dev/null +++ b/src/Gui/Icons/preferences-workbenches.svg @@ -0,0 +1,831 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + 2005-10-15 + + + Andreas Nilsson + + + + + edit + copy + + + + + + Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Gui/Icons/resource.qrc b/src/Gui/Icons/resource.qrc index b626752ac7..28d9c0b170 100644 --- a/src/Gui/Icons/resource.qrc +++ b/src/Gui/Icons/resource.qrc @@ -26,6 +26,7 @@ preferences-display.svg preferences-general.svg preferences-import-export.svg + preferences-workbenches.svg utilities-terminal.svg ClassBrowser/const_member.png ClassBrowser/member.png diff --git a/src/Gui/resource.cpp b/src/Gui/resource.cpp index d3d3647690..099539a5a1 100644 --- a/src/Gui/resource.cpp +++ b/src/Gui/resource.cpp @@ -27,7 +27,7 @@ #include "WidgetFactory.h" #include "Workbench.h" -// INCLUDE YOUR PREFERENCFE PAGES HERE +// INCLUDE YOUR PREFERENCE PAGES HERE // #include "DlgPreferencesImp.h" #include "DlgSettings3DViewImp.h" @@ -41,6 +41,7 @@ #include "DlgSettingsDocumentImp.h" //#include "DlgOnlineHelpImp.h" #include "DlgReportViewImp.h" +#include "DlgSettingsLazyLoadedImp.h" #include "DlgToolbarsImp.h" #include "DlgWorkbenchesImp.h" @@ -64,17 +65,18 @@ WidgetFactorySupplier::WidgetFactorySupplier() // ADD YOUR PREFERENCE PAGES HERE // // - new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","General") ); - //new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","General") ); - new PrefPageProducer( QT_TRANSLATE_NOOP("QObject","General") ); - new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","General") ); - new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","General") ); - new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","General") ); - new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","General") ); - new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","General") ); - new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","Display") ); - new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","Display") ); - new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","Display") ); + new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","General") ); + //new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","General") ); + new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","General") ); + new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","General") ); + new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","General") ); + new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","General") ); + new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","General") ); + new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","General") ); + new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","Display") ); + new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","Display") ); + new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","Display") ); + new PrefPageProducer ( QT_TRANSLATE_NOOP("QObject","Workbenches") ); // ADD YOUR CUSTOMIZE PAGES HERE //