diff --git a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_de.ts b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_de.ts index 554a8c5c7..1e431f98f 100644 --- a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_de.ts +++ b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_de.ts @@ -2146,7 +2146,7 @@ p, li { white-space: pre-wrap; } - Notify Plugin + Notification diff --git a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_es.ts b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_es.ts index 32554073c..183101e99 100644 --- a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_es.ts +++ b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_es.ts @@ -2147,7 +2147,7 @@ p, li { white-space: pre-wrap; } - Notify Plugin + Notification diff --git a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_fr.ts b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_fr.ts index 529fd4f7a..7463d76bf 100644 --- a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_fr.ts +++ b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_fr.ts @@ -2175,8 +2175,8 @@ p, li { white-space: pre-wrap; } - Notify Plugin - Plugin de Notification + Notification + Notification diff --git a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_ru.ts b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_ru.ts index 611533c3e..e26c74211 100644 --- a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_ru.ts +++ b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_ru.ts @@ -2256,7 +2256,7 @@ p, li { white-space: pre-wrap; } - Notify Plugin + Notification Оповещения diff --git a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_zh_CN.ts b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_zh_CN.ts index a27bc2920..4d92f3c34 100644 --- a/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_zh_CN.ts +++ b/ground/openpilotgcs/share/openpilotgcs/translations/openpilotgcs_zh_CN.ts @@ -3189,7 +3189,7 @@ p, li { white-space: pre-wrap; } - Notify Plugin + Notification diff --git a/ground/openpilotgcs/src/plugins/coreplugin/dialogs/settingsdialog.cpp b/ground/openpilotgcs/src/plugins/coreplugin/dialogs/settingsdialog.cpp index fd772b0bb..d5581ff75 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/dialogs/settingsdialog.cpp +++ b/ground/openpilotgcs/src/plugins/coreplugin/dialogs/settingsdialog.cpp @@ -32,7 +32,6 @@ #include "icore.h" #include "coreplugin/uavgadgetinstancemanager.h" #include "coreplugin/uavgadgetoptionspagedecorator.h" -// #include "coreimpl.h" #include #include @@ -40,49 +39,58 @@ #include #include +using namespace Core; +using namespace Core::Internal; + namespace { -struct PageData { - int index; - QString category; - QString id; -}; + + struct PageData { + int index; + QString category; + QString id; + + }; + + // helper to sort by translated category and name + bool compareOptionsPageByCategoryAndNameTr(const IOptionsPage *p1, const IOptionsPage *p2) + { + const UAVGadgetOptionsPageDecorator *gp1 = qobject_cast(p1); + const UAVGadgetOptionsPageDecorator *gp2 = qobject_cast(p2); + if (gp1 && !gp2) { + return false; + } + if (gp2 && !gp1) { + return true; + } + if (const int cc = QString::localeAwareCompare(p1->trCategory(), p2->trCategory())) { + return cc < 0; + } + return QString::localeAwareCompare(p1->trName(), p2->trName()) < 0; + } + + // helper to sort by category and id + bool compareOptionsPageByCategoryAndId(const IOptionsPage *p1, const IOptionsPage *p2) + { + const UAVGadgetOptionsPageDecorator *gp1 = qobject_cast(p1); + const UAVGadgetOptionsPageDecorator *gp2 = qobject_cast(p2); + if (gp1 && !gp2) { + return false; + } + if (gp2 && !gp1) { + return true; + } + if (const int cc = QString::localeAwareCompare(p1->category(), p2->category())) { + return cc < 0; + } + return QString::localeAwareCompare(p1->id(), p2->id()) < 0; + } + } Q_DECLARE_METATYPE(::PageData) -using namespace Core; -using namespace Core::Internal; - -// Helpers to sort by category. id -bool optionsPageLessThan(const IOptionsPage *p1, const IOptionsPage *p2) -{ - const UAVGadgetOptionsPageDecorator *gp1 = qobject_cast(p1); - const UAVGadgetOptionsPageDecorator *gp2 = qobject_cast(p2); - - if (gp1 && (gp2 == NULL)) { - return false; - } - - if (gp2 && (gp1 == NULL)) { - return true; - } - - if (const int cc = QString::localeAwareCompare(p1->trCategory(), p2->trCategory())) { - return cc < 0; - } - - return QString::localeAwareCompare(p1->trName(), p2->trName()) < 0; -} - -static inline QList sortedOptionsPages() -{ - QList rc = ExtensionSystem::PluginManager::instance()->getObjects(); - qStableSort(rc.begin(), rc.end(), optionsPageLessThan); - return rc; -} - -SettingsDialog::SettingsDialog(QWidget *parent, const QString &categoryId, const QString &pageId) - : QDialog(parent), m_applied(false) +SettingsDialog::SettingsDialog(QWidget *parent, const QString &categoryId, const QString &pageId) : + QDialog(parent), m_applied(false) { setupUi(this); #ifdef Q_OS_MAC @@ -92,6 +100,7 @@ SettingsDialog::SettingsDialog(QWidget *parent, const QString &categoryId, const #endif QSettings *settings = ICore::instance()->settings(); + settings->beginGroup("General"); // restore last displayed category and page @@ -104,6 +113,7 @@ SettingsDialog::SettingsDialog(QWidget *parent, const QString &categoryId, const initialPage = settings->value("LastPreferencePage", QVariant(QString())).toString(); qDebug() << "SettingsDialog settings initial category:" << initialCategory << ", initial page: " << initialPage; } + // restore window size int windowWidth = settings->value("SettingsWindowWidth", 0).toInt(); int windowHeight = settings->value("SettingsWindowHeight", 0).toInt(); @@ -111,114 +121,99 @@ SettingsDialog::SettingsDialog(QWidget *parent, const QString &categoryId, const if (windowWidth > 0 && windowHeight > 0) { resize(windowWidth, windowHeight); } + + // restore splitter size + int size0 = settings->value("SettingsSplitterSize0", 0).toInt(); + int size1 = settings->value("SettingsSplitterSize1", 0).toInt(); + qDebug() << "SettingsDialog splitter size0:" << size0 << ", size1:" << size1; + QList sizes; + if (size0 > 0 && size1 > 0) { + sizes << size0 << size1; + } + else { + sizes << 150 << 300; + } + splitter->setSizes(sizes); + settings->endGroup(); + // all extra space must go to the option page and none to the tree + splitter->setStretchFactor(splitter->indexOf(pageTree), 0); + splitter->setStretchFactor(splitter->indexOf(layoutWidget), 1); + buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(apply())); m_instanceManager = Core::ICore::instance()->uavGadgetInstanceManager(); - connect(this, SIGNAL(settingsDialogShown(Core::Internal::SettingsDialog *)), m_instanceManager, SLOT(settingsDialogShown(Core::Internal::SettingsDialog *))); + connect(this, SIGNAL(settingsDialogShown(Core::Internal::SettingsDialog *)), m_instanceManager, + SLOT(settingsDialogShown(Core::Internal::SettingsDialog *))); connect(this, SIGNAL(settingsDialogRemoved()), m_instanceManager, SLOT(settingsDialogRemoved())); - connect(this, SIGNAL(categoryItemSelected()), this, SLOT(categoryItemSelectedShowChildInstead()), Qt::QueuedConnection); + connect(this, SIGNAL(categoryItemSelected()), this, SLOT(categoryItemSelectedShowChildInstead()), + Qt::QueuedConnection); splitter->setCollapsible(0, false); splitter->setCollapsible(1, false); pageTree->header()->setVisible(false); -// pageTree->setIconSize(QSize(24, 24)); - connect(pageTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), - this, SLOT(pageSelected())); + connect(pageTree, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), this, SLOT(pageSelected())); - QMap categories; + QList pluginPages; + QList gadgetPages; - QList pages = sortedOptionsPages(); + // get all pages and split them between plugin and gadget list + QList pages = ExtensionSystem::PluginManager::instance()->getObjects(); + foreach(IOptionsPage *page, pages) { + if (qobject_cast(page)) { + gadgetPages.append(page); + } else { + pluginPages.append(page); + } + } - int index = 0; - bool firstUavGadgetOptionsPageFound = false; + // the plugin options page list sorted by untranslated names to facilitate access to the language settings when GCS + // is not running in a language understood by the user. + qStableSort(pluginPages.begin(), pluginPages.end(), compareOptionsPageByCategoryAndId); + // the plugin options page list sorted is sorted by translated names + qStableSort(gadgetPages.begin(), gadgetPages.end(), compareOptionsPageByCategoryAndNameTr); + + // will hold the initially selected item if any QTreeWidgetItem *initialItem = 0; - foreach(IOptionsPage * page, pages) { - PageData pageData; - pageData.index = index; - pageData.category = page->category(); - pageData.id = page->id(); - - QTreeWidgetItem *item = new QTreeWidgetItem; - item->setText(0, page->trName()); - item->setData(0, Qt::UserRole, qVariantFromValue(pageData)); - - QString trCategories = page->trCategory(); - QString currentCategory = page->category(); - - QTreeWidgetItem *categoryItem; - if (!categories.contains(currentCategory)) { - // Above the first gadget option we insert a separator - if (!firstUavGadgetOptionsPageFound) { - UAVGadgetOptionsPageDecorator *pd = qobject_cast(page); - if (pd) { - firstUavGadgetOptionsPageFound = true; - QTreeWidgetItem *separator = new QTreeWidgetItem(pageTree); - separator->setFlags(separator->flags() & ~Qt::ItemIsSelectable & ~Qt::ItemIsEnabled); - separator->setText(0, QString(30, 0xB7)); - } - } - categoryItem = new QTreeWidgetItem(pageTree); - categoryItem->setIcon(0, page->icon()); - categoryItem->setText(0, trCategories); - categoryItem->setData(0, Qt::UserRole, qVariantFromValue(pageData)); - categories.insert(currentCategory, categoryItem); - } - - QList *categoryItemList = m_categoryItemsMap.value(currentCategory); - if (!categoryItemList) { - categoryItemList = new QList(); - m_categoryItemsMap.insert(currentCategory, categoryItemList); - } - categoryItemList->append(item); - - m_pages.append(page); - - // creating all option pages upfront is slow, so we create place holder widgets instead - // the real option page widget will be created later when the user selects it - // the place holder is a QLabel and we assume that no option page will be a QLabel... - QLabel *placeholderWidget = new QLabel(stackedPages); - stackedPages->addWidget(placeholderWidget); - - if (page->id() == initialPage && currentCategory == initialCategory) { + // add plugin pages + foreach(IOptionsPage *page, pluginPages) { + QTreeWidgetItem *item = addPage(page); + // to automatically expand all plugin categories, uncomment next line + //item->parent()->setExpanded(true); + if (page->id() == initialPage && page->category() == initialCategory) { initialItem = item; } - - index++; } - foreach(QString category, m_categoryItemsMap.keys()) { - QList *categoryItemList = m_categoryItemsMap.value(category); - if (categoryItemList->size() > 1) { - foreach(QTreeWidgetItem * item, *categoryItemList) { - QTreeWidgetItem *categoryItem = categories.value(category); + // insert separator bewteen plugin and gadget pages + QTreeWidgetItem *separator = new QTreeWidgetItem(pageTree); + separator->setFlags(separator->flags() & ~Qt::ItemIsSelectable & ~Qt::ItemIsEnabled); + separator->setText(0, QString(30, 0xB7)); - categoryItem->addChild(item); - } + // add gadget pages + foreach(IOptionsPage *page, gadgetPages) { + QTreeWidgetItem *item = addPage(page); + if (page->id() == initialPage && page->category() == initialCategory) { + initialItem = item; } } + // handle initially selected item if (initialItem) { - if (!initialItem->parent()) { - // item has no parent, meaning it is single child - // so select category item instead as single child are not added to the tree - initialItem = categories.value(initialCategory); + if (initialItem->isHidden()) { + // item is hidden, meaning it is single child + // so select parent category item instead + initialItem = initialItem->parent(); } pageTree->setCurrentItem(initialItem); } - QList sizes; - sizes << 150 << 300; - splitter->setSizes(sizes); - - splitter->setStretchFactor(splitter->indexOf(pageTree), 0); - splitter->setStretchFactor(splitter->indexOf(layoutWidget), 1); } SettingsDialog::~SettingsDialog() @@ -236,6 +231,64 @@ SettingsDialog::~SettingsDialog() } } +QTreeWidgetItem *SettingsDialog::addPage(IOptionsPage *page) { + PageData pageData; + pageData.index = m_pages.count(); + pageData.category = page->category(); + pageData.id = page->id(); + + QString category = page->category(); + + QList *categoryItemList = m_categoryItemsMap.value(category); + if (!categoryItemList) { + categoryItemList = new QList(); + m_categoryItemsMap.insert(category, categoryItemList); + } + + QTreeWidgetItem *categoryItem = NULL; + for (int i = 0; i < pageTree->topLevelItemCount(); ++i) { + QTreeWidgetItem *tw = pageTree->topLevelItem(i); + PageData data = tw->data(0, Qt::UserRole).value(); + if (data.category == page->category()) { + categoryItem = tw; + break; + } + } + if (!categoryItem) { + categoryItem = new QTreeWidgetItem(pageTree); + categoryItem->setIcon(0, page->icon()); + categoryItem->setText(0, page->trCategory()); + categoryItem->setData(0, Qt::UserRole, qVariantFromValue(pageData)); + } + + QTreeWidgetItem *item = new QTreeWidgetItem(categoryItem); + item->setText(0, page->trName()); + item->setData(0, Qt::UserRole, qVariantFromValue(pageData)); + + switch (categoryItemList->size()) { + case 0: + item->setHidden(true); + break; + case 1: + categoryItemList->at(0)->setHidden(false); + break; + default: + break; + } + + categoryItemList->append(item); + + m_pages.append(page); + + // creating all option pages upfront is slow, so we create place holder widgets instead + // the real option page widget will be created later when the user selects it + // the place holder is a QLabel and we assume that no option page will be a QLabel... + QLabel *placeholderWidget = new QLabel(stackedPages); + stackedPages->addWidget(placeholderWidget); + + return item; +} + void SettingsDialog::pageSelected() { QTreeWidgetItem *item = pageTree->currentItem(); @@ -281,15 +334,18 @@ void SettingsDialog::deletePage() QString category = data.category; QList *categoryItemList = m_categoryItemsMap.value(category); - QTreeWidgetItem *parentItem = item->parent(); - parentItem->removeChild(item); - categoryItemList->removeOne(item); - if (parentItem->childCount() == 1) { - parentItem->removeChild(parentItem->child(0)); + if (categoryItemList) { + categoryItemList->removeOne(item); + QTreeWidgetItem *parentItem = item->parent(); + parentItem->removeChild(item); + if (parentItem->childCount() == 1) { + parentItem->child(0)->setHidden(true); + } } pageSelected(); } +// TODO duplicates a lot of the addPage code... void SettingsDialog::insertPage(IOptionsPage *page) { PageData pageData; @@ -314,9 +370,9 @@ void SettingsDialog::insertPage(IOptionsPage *page) // If this category has no child right now // we need to add the "default child" QList *categoryItemList = m_categoryItemsMap.value(page->category()); - if (categoryItem->childCount() == 0) { + if (categoryItem->childCount() == 1) { QTreeWidgetItem *defaultItem = categoryItemList->at(0); - categoryItem->addChild(defaultItem); + defaultItem->setHidden(false); } QTreeWidgetItem *item = new QTreeWidgetItem; @@ -396,10 +452,18 @@ bool SettingsDialog::execDialog() void SettingsDialog::done(int val) { QSettings *settings = ICore::instance()->settings(); + settings->beginGroup("General"); + + settings->setValue("LastPreferenceCategory", m_currentCategory); + settings->setValue("LastPreferencePage", m_currentPage); + settings->setValue("SettingsWindowWidth", this->width()); + settings->setValue("SettingsWindowHeight", this->height()); + QList sizes = splitter->sizes(); + qDebug() << "SettingsDialog splitter saving size0:" << sizes[0] << ", size1:" << sizes[1]; + settings->setValue("SettingsSplitterSize0", sizes[0]); + settings->setValue("SettingsSplitterSize1", sizes[1]); + + settings->endGroup(); - settings->setValue("General/LastPreferenceCategory", m_currentCategory); - settings->setValue("General/LastPreferencePage", m_currentPage); - settings->setValue("General/SettingsWindowWidth", this->width()); - settings->setValue("General/SettingsWindowHeight", this->height()); QDialog::done(val); } diff --git a/ground/openpilotgcs/src/plugins/coreplugin/dialogs/settingsdialog.h b/ground/openpilotgcs/src/plugins/coreplugin/dialogs/settingsdialog.h index ade61b525..7333844a4 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/dialogs/settingsdialog.h +++ b/ground/openpilotgcs/src/plugins/coreplugin/dialogs/settingsdialog.h @@ -36,9 +36,11 @@ #include "coreplugin/dialogs/ioptionspage.h" namespace Core { + class UAVGadgetInstanceManager; namespace Internal { + class SettingsDialog : public QDialog, public::Ui::SettingsDialog { Q_OBJECT @@ -75,8 +77,12 @@ private: bool m_applied; QString m_currentCategory; QString m_currentPage; + + QTreeWidgetItem *addPage(IOptionsPage *page); }; + } // namespace Internal + } // namespace Core #endif // SETTINGSDIALOG_H diff --git a/ground/openpilotgcs/src/plugins/coreplugin/workspacesettings.cpp b/ground/openpilotgcs/src/plugins/coreplugin/workspacesettings.cpp index 62279fd1a..43d552f44 100644 --- a/ground/openpilotgcs/src/plugins/coreplugin/workspacesettings.cpp +++ b/ground/openpilotgcs/src/plugins/coreplugin/workspacesettings.cpp @@ -60,12 +60,12 @@ QString WorkspaceSettings::trName() const QString WorkspaceSettings::category() const { - return QLatin1String("GCS"); + return QLatin1String("Environment"); } QString WorkspaceSettings::trCategory() const { - return tr("GCS"); + return tr("Environment"); } QWidget *WorkspaceSettings::createPage(QWidget *parent) diff --git a/ground/openpilotgcs/src/plugins/ipconnection/ipconnectionoptionspage.h b/ground/openpilotgcs/src/plugins/ipconnection/ipconnectionoptionspage.h index d0110339c..b00c585f4 100644 --- a/ground/openpilotgcs/src/plugins/ipconnection/ipconnectionoptionspage.h +++ b/ground/openpilotgcs/src/plugins/ipconnection/ipconnectionoptionspage.h @@ -58,7 +58,7 @@ public: } QString category() const { - return "IP Network Telemetry"; + return "Telemetry - IP Network"; }; QString trCategory() const { diff --git a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h index adeadde9a..9c39639e5 100644 --- a/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h +++ b/ground/openpilotgcs/src/plugins/notify/notifypluginoptionspage.h @@ -76,7 +76,7 @@ public: } QString trCategory() const { - return tr("Notify Plugin"); + return tr("Notification"); } QWidget *createPage(QWidget *parent); diff --git a/ground/openpilotgcs/src/plugins/serialconnection/serialpluginoptionspage.h b/ground/openpilotgcs/src/plugins/serialconnection/serialpluginoptionspage.h index 1a0475f48..28e6b94b3 100644 --- a/ground/openpilotgcs/src/plugins/serialconnection/serialpluginoptionspage.h +++ b/ground/openpilotgcs/src/plugins/serialconnection/serialpluginoptionspage.h @@ -62,7 +62,7 @@ public: } QString category() const { - return "Serial Telemetry"; + return "Telemetry - Serial"; } QString trCategory() const {