diff --git a/Code/Mantid/Framework/Properties/Mantid.properties.template b/Code/Mantid/Framework/Properties/Mantid.properties.template index 571566ff52e10b23a97125d240b6439993d2c4c9..2121e46aa0ad4b9af77ac837110d566991665c94 100644 --- a/Code/Mantid/Framework/Properties/Mantid.properties.template +++ b/Code/Mantid/Framework/Properties/Mantid.properties.template @@ -190,6 +190,9 @@ loading.multifilelimit=100 # Hide algorithms that use a Property Manager by default. algorithms.categories.hidden=Workflow\\Inelastic\\UsesPropertyManager;Workflow\\SANS\\UsesPropertyManager;DataHandling\\LiveData\\Support;Deprecated;Utility\\Development;Remote +# All interface categories are shown by default. +interfaces.categories.hidden = + # ScriptRepository Properties: # Url for the WebServer that support the upload of the files that the users want to share diff --git a/Code/Mantid/MantidPlot/CMakeLists.txt b/Code/Mantid/MantidPlot/CMakeLists.txt index 5d3ed7a7666035afcfff2b82d35f138a6ac0444e..b4eb89583dbaa2187e1ae72e63b9002fc9e02e34 100644 --- a/Code/Mantid/MantidPlot/CMakeLists.txt +++ b/Code/Mantid/MantidPlot/CMakeLists.txt @@ -166,6 +166,7 @@ set ( MANTID_SRCS src/Mantid/AlgorithmMonitor.cpp src/Mantid/InputHistory.cpp src/Mantid/LoadDAEDlg.cpp src/Mantid/ManageCustomMenus.cpp + src/Mantid/ManageInterfaceCategories.cpp src/Mantid/MantidAbout.cpp src/Mantid/MantidApplication.cpp src/Mantid/MantidCurve.cpp @@ -396,6 +397,7 @@ set ( MANTID_HDRS src/Mantid/AlgorithmMonitor.h src/Mantid/InputHistory.h src/Mantid/LoadDAEDlg.h src/Mantid/ManageCustomMenus.h + src/Mantid/ManageInterfaceCategories.h src/Mantid/MantidAbout.h src/Mantid/MantidApplication.h src/Mantid/MantidCurve.h @@ -663,6 +665,7 @@ set ( MANTID_MOC_FILES src/Mantid/AlgorithmMonitor.h src/Mantid/ImportWorkspaceDlg.h src/Mantid/LoadDAEDlg.h src/Mantid/ManageCustomMenus.h + src/Mantid/ManageInterfaceCategories.h src/Mantid/MantidAbout.h src/Mantid/MantidApplication.h src/Mantid/MantidCurve.h @@ -711,6 +714,7 @@ set ( UI_FILES src/SendToProgramDialog.ui src/Mantid/RemoveErrorsDialog.ui src/Mantid/SetUpParaview.ui src/Mantid/ManageCustomMenus.ui + src/Mantid/ManageInterfaceCategories.ui src/Mantid/MantidMDCurveDialog.ui ) diff --git a/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp b/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp index 85cef2de76ecc22f4c3a85b5dd56395a5148508d..a74fc922582d5c6bb3f7c881855578ca57302c61 100644 --- a/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp +++ b/Code/Mantid/MantidPlot/src/ApplicationWindow.cpp @@ -184,6 +184,7 @@ #include "Mantid/MantidAbout.h" #include "Mantid/PeakPickerTool.h" #include "Mantid/ManageCustomMenus.h" +#include "Mantid/ManageInterfaceCategories.h" #include "Mantid/FirstTimeSetup.h" #include "Mantid/SetUpParaview.h" @@ -454,12 +455,14 @@ void ApplicationWindow::init(bool factorySettings, const QStringList& args) scriptingWindow = NULL; d_text_editor = NULL; + const QString scriptsDir = QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("mantidqt.python_interfaces_directory")); + // Parse the list of registered PyQt interfaces and their respective categories. QString pyQtInterfacesProperty = QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("mantidqt.python_interfaces")); foreach(const QString pyQtInterfaceInfo, QStringList::split(" ", pyQtInterfacesProperty)) { - QString interfaceName; - QSet<QString> interfaceCategories; + QString pyQtInterfaceFile; + QSet<QString> pyQtInterfaceCategories; const QStringList tokens = QStringList::split("/", pyQtInterfaceInfo); if( tokens.size() == 0 ) // Empty token - ignore. @@ -468,13 +471,13 @@ void ApplicationWindow::init(bool factorySettings, const QStringList& args) } else if( tokens.size() == 1 ) // Assume missing category. { - interfaceCategories += "Uncatagorised"; - interfaceName = tokens[0]; + pyQtInterfaceCategories += "Uncatagorised"; + pyQtInterfaceFile = tokens[0]; } else if( tokens.size() == 2 ) // Assume correct interface name and categories. { - interfaceCategories += QStringList::split(";", tokens[0]).toSet(); - interfaceName = tokens[1]; + pyQtInterfaceCategories += QStringList::split(";", tokens[0]).toSet(); + pyQtInterfaceFile = tokens[1]; } else // Too many forward slashes, or no space between two interfaces. Warn user and move on. { @@ -483,7 +486,34 @@ void ApplicationWindow::init(bool factorySettings, const QStringList& args) continue; } - m_pyQtInterfaceToCategoriesMap[interfaceName] = interfaceCategories; + const QString scriptPath = scriptsDir + '/' + pyQtInterfaceFile; + + if( QFileInfo(scriptPath).exists() ) + { + const QString pyQtInterfaceName = QFileInfo(scriptPath).baseName().replace("_", " "); + m_interfaceNameDataPairs.append(qMakePair(pyQtInterfaceName, scriptPath)); + + // Keep track of the interface's categories as we go. + m_interfaceCategories[pyQtInterfaceName] = pyQtInterfaceCategories; + m_allCategories += pyQtInterfaceCategories; + } + else + { + Mantid::Kernel::Logger& g_log = Mantid::Kernel::Logger::get("ConfigService"); + g_log.warning() << "Could not find interface script: " << scriptPath.ascii() << "\n"; + } + } + + MantidQt::API::InterfaceManager interfaceManager; + // Add all interfaces inherited from UserSubWindow. + foreach(const QString userSubWindowName, interfaceManager.getUserSubWindowKeys()) + { + m_interfaceNameDataPairs.append(qMakePair(userSubWindowName, userSubWindowName)); + + const QSet<QString> categories = UserSubWindowFactory::Instance().getInterfaceCategories(userSubWindowName); + + m_interfaceCategories[userSubWindowName] = categories; + m_allCategories += categories; } renamedTables = QStringList(); @@ -1235,6 +1265,10 @@ void ApplicationWindow::initMainMenu() windowsMenu->setCheckable(true); connect(windowsMenu, SIGNAL(aboutToShow()), this, SLOT(windowsMenuAboutToShow())); + interfaceMenu = new QMenu(this); + interfaceMenu->setObjectName("interfaceMenu"); + connect(interfaceMenu, SIGNAL(aboutToShow()), this, SLOT(interfaceMenuAboutToShow())); + foldersMenu = new QMenu(this); foldersMenu->setCheckable(true); @@ -1547,90 +1581,8 @@ void ApplicationWindow::customMenu(MdiSubWindow* w) myMenuBar()->insertItem(tr("&Catalog"),icat); // -- INTERFACE MENU -- - - interfaceMenu = new QMenu(this); - interfaceMenu->setObjectName("interfaceMenu"); myMenuBar()->insertItem(tr("&Interfaces"), interfaceMenu); - m_interfaceActions.clear(); - - MantidQt::API::InterfaceManager interfaceManager; - const QString scriptsDir = QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("mantidqt.python_interfaces_directory")); - - // A collection of the names of each interface as they appear in the menu and also "data" - // relating to how each interface can be opened. Elsewhere, the data is expected to be a - // python file name, or else just the name of the interface as known to the InterfaceManager. - QList<QPair<QString, QString>> interfaceNameDataPairs; - - // Keeping track of all unique categories. - QSet<QString> allCategories; - - // Map interfaces to their categories. - QMap<QString, QSet<QString>> interfaceCategories; - - // Add all interfaces inherited from UserSubWindow to the collection. - foreach(const QString userSubWindowName, interfaceManager.getUserSubWindowKeys()) - { - interfaceNameDataPairs.append(qMakePair(userSubWindowName, userSubWindowName)); - - const QSet<QString> categories = UserSubWindowFactory::Instance().getInterfaceCategories(userSubWindowName); - - interfaceCategories[userSubWindowName] = categories; - allCategories += categories; - } - - // Add all PyQt interfaces to the collection. - foreach(const QString pyQtInterfaceFile, m_pyQtInterfaceToCategoriesMap.keys()) - { - const QString scriptPath = scriptsDir + '/' + pyQtInterfaceFile; - - if( QFileInfo(scriptPath).exists() ) - { - const QString pyQtInterfaceName = QFileInfo(scriptPath).baseName().replace("_", " "); - interfaceNameDataPairs.append(qMakePair(pyQtInterfaceName, scriptPath)); - - // Keep track of the interface's categories as we go. - auto categories = m_pyQtInterfaceToCategoriesMap[pyQtInterfaceFile]; - interfaceCategories[pyQtInterfaceName] = categories; - allCategories += categories; - } - else - { - Mantid::Kernel::Logger& g_log = Mantid::Kernel::Logger::get("ConfigService"); - g_log.warning() << "Could not find interface script: " << scriptPath.ascii() << "\n"; - } - } - - // Create a submenu for each category. Make sure submenus are in alphabetical order. - QMap<QString, QMenu *> categoryMenus; - auto sortedCategories = allCategories.toList(); - qSort(sortedCategories); - foreach(const QString category, sortedCategories) - { - QMenu * categoryMenu = new QMenu(interfaceMenu); - categoryMenu->setObjectName(category + "Menu"); - interfaceMenu->insertItem(tr(category), categoryMenu); - categoryMenus[category] = categoryMenu; - } - - // Turn the name/data pairs into QActions with which we populate the menus. - foreach(const auto interfaceNameDataPair, interfaceNameDataPairs) - { - const QString name = interfaceNameDataPair.first; - const QString data = interfaceNameDataPair.second; - - foreach(const QString category, interfaceCategories[name]) - { - QAction * openInterface = new QAction(tr(name), interfaceMenu); - openInterface->setData(data); - assert(categoryMenus.contains(category)); - categoryMenus[category]->addAction(openInterface); - - // Update separate list containing all interface actions. - m_interfaceActions.append(openInterface); - } - } - - connect(interfaceMenu, SIGNAL(triggered(QAction*)), this, SLOT(performCustomAction(QAction*))); + interfaceMenuAboutToShow(); myMenuBar()->insertItem(tr("&Help"), help ); @@ -5349,7 +5301,7 @@ void ApplicationWindow::readSettings() // Mantid bool warning_shown = settings.value("/DuplicationDialogShown", false).toBool(); - + //Check for user defined scripts in settings and create menus for them //Top level scripts group settings.beginGroup("CustomScripts"); @@ -5363,18 +5315,24 @@ void ApplicationWindow::readSettings() foreach(QString menu, settings.childGroups()) { + // Specifically disallow the use of the Interfaces menu to users looking to + // customise their own menus, since it is managed separately. Also, there + // may well be some left-over QSettings values from previous installations + // that we do not want used. + if( menu == "Interfaces" || menu == "&Interfaces" ) + continue; + addUserMenu(menu); settings.beginGroup(menu); foreach(QString keyName, settings.childKeys()) { QFileInfo fi(settings.value(keyName).toString()); QString baseName = fi.fileName(); - const QStringList pyQtInferfaces = m_pyQtInterfaceToCategoriesMap.keys(); - if (pyQtInferfaces.contains(baseName)) + const QStringList pyQtInterfaces = m_interfaceCategories.keys(); + if (pyQtInterfaces.contains(baseName)) continue; - if ( menu.contains("Interfaces")==0 && - (user_windows.grep(keyName).size() > 0 || pyQtInferfaces.grep(keyName).size() > 0) ) + if ( user_windows.grep(keyName).size() > 0 || pyQtInterfaces.grep(keyName).size() > 0 ) { duplicated_custom_menu.append(menu+"/"+keyName); } @@ -9363,6 +9321,62 @@ void ApplicationWindow::windowsMenuAboutToShow() reloadCustomActions(); } +void ApplicationWindow::interfaceMenuAboutToShow() +{ + interfaceMenu->clear(); + m_interfaceActions.clear(); + + // Create a submenu for each category. Make sure submenus are in alphabetical order, + // and ignore any hidden categories. + const QString hiddenProp = QString::fromStdString( + Mantid::Kernel::ConfigService::Instance().getString("interfaces.categories.hidden") + ); + auto hiddenCategories = hiddenProp.split(";", QString::SkipEmptyParts).toSet(); + QMap<QString, QMenu *> categoryMenus; + auto sortedCategories = m_allCategories.toList(); + qSort(sortedCategories); + foreach(const QString category, sortedCategories) + { + if( hiddenCategories.contains(category) ) + continue; + QMenu * categoryMenu = new QMenu(interfaceMenu); + categoryMenu->setObjectName(category + "Menu"); + interfaceMenu->insertItem(tr(category), categoryMenu); + categoryMenus[category] = categoryMenu; + } + + // Turn the name/data pairs into QActions with which we populate the menus. + foreach(const auto interfaceNameDataPair, m_interfaceNameDataPairs) + { + const QString name = interfaceNameDataPair.first; + const QString data = interfaceNameDataPair.second; + + foreach(const QString category, m_interfaceCategories[name]) + { + if(!categoryMenus.contains(category)) + continue; + QAction * openInterface = new QAction(tr(name), interfaceMenu); + openInterface->setData(data); + categoryMenus[category]->addAction(openInterface); + + // Update separate list containing all interface actions. + m_interfaceActions.append(openInterface); + } + } + + foreach( auto categoryMenu, categoryMenus.values() ) + { + connect(categoryMenu, SIGNAL(triggered(QAction*)), this, SLOT(performCustomAction(QAction*))); + } + + interfaceMenu->insertSeparator(); + + // Allow user to customise categories. + QAction * customiseCategoriesAction = new QAction(tr("Add/Remove Categories"), this); + connect(customiseCategoriesAction, SIGNAL(activated()), this, SLOT(showInterfaceCategoriesDialog())); + interfaceMenu->addAction(customiseCategoriesAction); +} + void ApplicationWindow::showMarkerPopupMenu() { MultiLayer *plot = dynamic_cast<MultiLayer*>(activeWindow(MultiLayerWindow)); @@ -16964,6 +16978,20 @@ void ApplicationWindow::showCustomActionDialog() ad->setFocus(); } +void ApplicationWindow::showInterfaceCategoriesDialog() +{ + auto existingWindow = this->findChild<ManageInterfaceCategories *>(); + if( !existingWindow ) + { + auto * diag = new ManageInterfaceCategories(this); + diag->setAttribute(Qt::WA_DeleteOnClose); + diag->show(); + diag->setFocus(); + } + else + existingWindow->activateWindow(); +} + void ApplicationWindow::showUserDirectoryDialog() { MantidQt::API::ManageUserDirectories *ad = new MantidQt::API::ManageUserDirectories(this); diff --git a/Code/Mantid/MantidPlot/src/ApplicationWindow.h b/Code/Mantid/MantidPlot/src/ApplicationWindow.h index afbe600692e4d904c8205f9f4932724b640ec09e..93bcd45b370a0e814cb7977ce533927db6605283 100644 --- a/Code/Mantid/MantidPlot/src/ApplicationWindow.h +++ b/Code/Mantid/MantidPlot/src/ApplicationWindow.h @@ -1132,6 +1132,7 @@ private: void tableMenuAboutToShow(); void windowsMenuAboutToShow(); void windowsMenuActivated( int id ); + void interfaceMenuAboutToShow(); //! \name Font Format Functions //@{ @@ -1150,6 +1151,7 @@ private: //@} void showCustomActionDialog(); + void showInterfaceCategoriesDialog(); void showUserDirectoryDialog(); void performCustomAction(QAction *); @@ -1329,8 +1331,6 @@ public: QStringList renamedTables; // List of removed interfaces QStringList removed_interfaces; - // Map PyQt interfaces that are to be added to the Interfaces menu to their respective categories. - QMap<QString, QSet<QString>> m_pyQtInterfaceToCategoriesMap; //! \name variables used when user copy/paste markers //@{ @@ -1345,7 +1345,18 @@ public: //! The scripting language to use for new projects. QString defaultScriptingLang; + QSet<QString> allCategories() const { return m_allCategories; } + private: + // A collection of the names of each interface as they appear in the menu and also "data" + // relating to how each interface can be opened. Elsewhere, the data is expected to be a + // python file name, or else just the name of the interface as known to the InterfaceManager. + QList<QPair<QString, QString>> m_interfaceNameDataPairs; + // Keeping track of all unique categories. + QSet<QString> m_allCategories; + // Map interfaces to their categories. + QMap<QString, QSet<QString>> m_interfaceCategories; + mutable MdiSubWindow *d_active_window; MdiSubWindow* getActiveWindow() const; void setActiveWindow(MdiSubWindow* w); diff --git a/Code/Mantid/MantidPlot/src/Mantid/ManageCustomMenus.cpp b/Code/Mantid/MantidPlot/src/Mantid/ManageCustomMenus.cpp index 5636c436d9a44d36f7a23058ba43d52069a1b368..c506fcc2535fd68013de971590fbe6cfd1a7fb96 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/ManageCustomMenus.cpp +++ b/Code/Mantid/MantidPlot/src/Mantid/ManageCustomMenus.cpp @@ -10,7 +10,7 @@ * @param parent :: pointer to the main MantidPlot ApplicationWindow object */ ManageCustomMenus::ManageCustomMenus(QWidget *parent) : QDialog(parent), -m_scriptsTree(0), m_customInterfacesTree(0), m_menusTree(0) +m_scriptsTree(0), m_menusTree(0) { m_uiForm.setupUi(this); m_appWindow = static_cast<ApplicationWindow*>(parent); @@ -22,11 +22,9 @@ m_scriptsTree(0), m_customInterfacesTree(0), m_menusTree(0) void ManageCustomMenus::initLayout() { m_scriptsTree = m_uiForm.twScripts; - m_customInterfacesTree = m_uiForm.twCustomInterfaces; m_menusTree = m_uiForm.twMenus; m_scriptsTree->setHeaderLabel("Python Scripts"); - m_customInterfacesTree->setHeaderLabel("Custom Interfaces"); m_menusTree->setHeaderLabel("Custom Menus"); // create qt connections @@ -38,7 +36,6 @@ void ManageCustomMenus::initLayout() connect(m_uiForm.pbHelp, SIGNAL(clicked()), this, SLOT(helpClicked())); connect(m_uiForm.pbConfirm, SIGNAL(clicked()), this, SLOT(close())); // Perform subsequent setups - getCustomInterfaceList(); populateMenuTree(); } /** @@ -71,23 +68,7 @@ void ManageCustomMenus::populateMenuTree() m_menusTree->addTopLevelItem(menu); } } -/** -* Gets the list of Custom Interfaces that have been registered with Mantid. -*/ -void ManageCustomMenus::getCustomInterfaceList() -{ - MantidQt::API::InterfaceManager interfaceManager; - QStringList user_windows = interfaceManager.getUserSubWindowKeys(); - QStringListIterator itr(user_windows); - while( itr.hasNext() ) - { - QString name = itr.next(); - QTreeWidgetItem *item = new QTreeWidgetItem(QStringList(name)); - item->setData(0, Qt::UserRole, name); - item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable ); - m_customInterfacesTree->addTopLevelItem(item); - } -} + /** * Returns a list of pointers to the selected items in the Scripts and Custom Interfaces trees. * @return list of selected items @@ -95,7 +76,7 @@ void ManageCustomMenus::getCustomInterfaceList() QList<QTreeWidgetItem*> ManageCustomMenus::getCurrentSelection() { QList<QTreeWidgetItem*> result; - result = m_scriptsTree->selectedItems() + m_customInterfacesTree->selectedItems(); + result = m_scriptsTree->selectedItems(); return result; } /** diff --git a/Code/Mantid/MantidPlot/src/Mantid/ManageCustomMenus.h b/Code/Mantid/MantidPlot/src/Mantid/ManageCustomMenus.h index e1ebad7e8545316319c1136404d86329ea6fa130..65c42f62b6ad9199c7e5d2ee8506605276f73d75 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/ManageCustomMenus.h +++ b/Code/Mantid/MantidPlot/src/Mantid/ManageCustomMenus.h @@ -40,7 +40,6 @@ public: private: void initLayout(); void populateMenuTree(); - void getCustomInterfaceList(); QList<QTreeWidgetItem*> getCurrentSelection(); QTreeWidgetItem* getCurrentMenuSelection(); private slots: diff --git a/Code/Mantid/MantidPlot/src/Mantid/ManageCustomMenus.ui b/Code/Mantid/MantidPlot/src/Mantid/ManageCustomMenus.ui index ce08ce5e735796ac5b1d7f162c009463ce8f10eb..b895b17aea9ebf4feaa6aef66ba932159b470322 100644 --- a/Code/Mantid/MantidPlot/src/Mantid/ManageCustomMenus.ui +++ b/Code/Mantid/MantidPlot/src/Mantid/ManageCustomMenus.ui @@ -1,7 +1,8 @@ -<ui version="4.0" > +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> <class>ManageCustomMenus</class> - <widget class="QDialog" name="ManageCustomMenus" > - <property name="geometry" > + <widget class="QDialog" name="ManageCustomMenus"> + <property name="geometry"> <rect> <x>0</x> <y>0</y> @@ -9,32 +10,32 @@ <height>386</height> </rect> </property> - <property name="windowTitle" > + <property name="windowTitle"> <string>Manage Custom Menus</string> </property> - <layout class="QVBoxLayout" name="verticalLayout_2" > + <layout class="QVBoxLayout" name="verticalLayout_2"> <item> - <layout class="QHBoxLayout" name="horizontalLayout" > + <layout class="QHBoxLayout" name="horizontalLayout"> <item> - <layout class="QVBoxLayout" name="verticalLayout" > + <layout class="QVBoxLayout" name="verticalLayout"> <item> - <layout class="QHBoxLayout" name="horizontalLayout_3" > + <layout class="QHBoxLayout" name="horizontalLayout_3"> <item> - <widget class="QPushButton" name="pbAddScript" > - <property name="toolTip" > + <widget class="QPushButton" name="pbAddScript"> + <property name="toolTip"> <string>Add Python Script file to menu.</string> </property> - <property name="text" > + <property name="text"> <string>Add Script</string> </property> </widget> </item> <item> - <widget class="QPushButton" name="pbRemoveScript" > - <property name="toolTip" > + <widget class="QPushButton" name="pbRemoveScript"> + <property name="toolTip"> <string>Remove selected Python script(s).</string> </property> - <property name="text" > + <property name="text"> <string>Remove Script</string> </property> </widget> @@ -42,24 +43,12 @@ </layout> </item> <item> - <widget class="QTreeWidget" name="twScripts" > - <property name="selectionMode" > + <widget class="QTreeWidget" name="twScripts"> + <property name="selectionMode"> <enum>QAbstractItemView::MultiSelection</enum> </property> <column> - <property name="text" > - <string>1</string> - </property> - </column> - </widget> - </item> - <item> - <widget class="QTreeWidget" name="twCustomInterfaces" > - <property name="selectionMode" > - <enum>QAbstractItemView::MultiSelection</enum> - </property> - <column> - <property name="text" > + <property name="text"> <string>1</string> </property> </column> @@ -68,13 +57,13 @@ </layout> </item> <item> - <layout class="QVBoxLayout" name="verticalLayout_3" > + <layout class="QVBoxLayout" name="verticalLayout_3"> <item> - <spacer name="verticalSpacer_2" > - <property name="orientation" > + <spacer name="verticalSpacer_2"> + <property name="orientation"> <enum>Qt::Vertical</enum> </property> - <property name="sizeHint" stdset="0" > + <property name="sizeHint" stdset="0"> <size> <width>20</width> <height>40</height> @@ -83,30 +72,30 @@ </spacer> </item> <item> - <widget class="QPushButton" name="pbAddItem" > - <property name="maximumSize" > + <widget class="QPushButton" name="pbAddItem"> + <property name="maximumSize"> <size> <width>45</width> <height>16777215</height> </size> </property> - <property name="toolTip" > + <property name="toolTip"> <string>Add item to menu.</string> </property> - <property name="text" > - <string>>></string> + <property name="text"> + <string>>></string> </property> </widget> </item> <item> - <spacer name="verticalSpacer_3" > - <property name="orientation" > + <spacer name="verticalSpacer_3"> + <property name="orientation"> <enum>Qt::Vertical</enum> </property> - <property name="sizeType" > + <property name="sizeType"> <enum>QSizePolicy::Fixed</enum> </property> - <property name="sizeHint" stdset="0" > + <property name="sizeHint" stdset="0"> <size> <width>20</width> <height>30</height> @@ -115,27 +104,27 @@ </spacer> </item> <item> - <widget class="QPushButton" name="pbRemoveItem" > - <property name="maximumSize" > + <widget class="QPushButton" name="pbRemoveItem"> + <property name="maximumSize"> <size> <width>45</width> <height>16777215</height> </size> </property> - <property name="toolTip" > + <property name="toolTip"> <string>Remove item from menu.</string> </property> - <property name="text" > + <property name="text"> <string><<</string> </property> </widget> </item> <item> - <spacer name="verticalSpacer" > - <property name="orientation" > + <spacer name="verticalSpacer"> + <property name="orientation"> <enum>Qt::Vertical</enum> </property> - <property name="sizeHint" stdset="0" > + <property name="sizeHint" stdset="0"> <size> <width>20</width> <height>40</height> @@ -146,15 +135,15 @@ </layout> </item> <item> - <layout class="QVBoxLayout" name="verticalLayout_4" > + <layout class="QVBoxLayout" name="verticalLayout_4"> <item> - <layout class="QHBoxLayout" name="horizontalLayout_4" > + <layout class="QHBoxLayout" name="horizontalLayout_4"> <item> - <spacer name="horizontalSpacer_2" > - <property name="orientation" > + <spacer name="horizontalSpacer_2"> + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <property name="sizeHint" stdset="0" > + <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> @@ -163,11 +152,11 @@ </spacer> </item> <item> - <widget class="QPushButton" name="pbAddMenu" > - <property name="toolTip" > + <widget class="QPushButton" name="pbAddMenu"> + <property name="toolTip"> <string>Add new top-level menu.</string> </property> - <property name="text" > + <property name="text"> <string>Add Menu</string> </property> </widget> @@ -175,12 +164,12 @@ </layout> </item> <item> - <widget class="QTreeWidget" name="twMenus" > - <property name="headerHidden" > + <widget class="QTreeWidget" name="twMenus"> + <property name="headerHidden"> <bool>false</bool> </property> <column> - <property name="text" > + <property name="text"> <string>1</string> </property> </column> @@ -191,29 +180,29 @@ </layout> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout_2" > + <layout class="QHBoxLayout" name="horizontalLayout_2"> <item> - <widget class="QPushButton" name="pbHelp" > - <property name="maximumSize" > + <widget class="QPushButton" name="pbHelp"> + <property name="maximumSize"> <size> <width>35</width> <height>16777215</height> </size> </property> - <property name="toolTip" > - <string>Open "Help" page in web browser.</string> + <property name="toolTip"> + <string>Open "Help" page in web browser.</string> </property> - <property name="text" > + <property name="text"> <string>?</string> </property> </widget> </item> <item> - <spacer name="horizontalSpacer" > - <property name="orientation" > + <spacer name="horizontalSpacer"> + <property name="orientation"> <enum>Qt::Horizontal</enum> </property> - <property name="sizeHint" stdset="0" > + <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> @@ -222,11 +211,11 @@ </spacer> </item> <item> - <widget class="QPushButton" name="pbConfirm" > - <property name="toolTip" > + <widget class="QPushButton" name="pbConfirm"> + <property name="toolTip"> <string>Close this dialog.</string> </property> - <property name="text" > + <property name="text"> <string>Ok</string> </property> </widget> @@ -239,7 +228,6 @@ <tabstop>pbAddScript</tabstop> <tabstop>pbRemoveScript</tabstop> <tabstop>twScripts</tabstop> - <tabstop>twCustomInterfaces</tabstop> <tabstop>pbAddItem</tabstop> <tabstop>pbRemoveItem</tabstop> <tabstop>pbAddMenu</tabstop> diff --git a/Code/Mantid/MantidPlot/src/Mantid/ManageInterfaceCategories.cpp b/Code/Mantid/MantidPlot/src/Mantid/ManageInterfaceCategories.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e50ed7f95944413aec6f3b442af6a4bf0f37d41f --- /dev/null +++ b/Code/Mantid/MantidPlot/src/Mantid/ManageInterfaceCategories.cpp @@ -0,0 +1,185 @@ +#include "MantidKernel/ConfigService.h" +#include "ManageInterfaceCategories.h" +#include "../ApplicationWindow.h" + +#include <QtGui> +#include <QtAlgorithms> + +///////////////////////////////////////////////////// +// InterfaceCategoryModel +///////////////////////////////////////////////////// + +/** + * Constructor. + * + * @param allCategories :: the set of all categories to be used in the model. + */ +InterfaceCategoryModel::InterfaceCategoryModel(const QSet<QString> & allCategories) : QAbstractListModel(), + m_allCategories(allCategories.toList()) +{ + qSort(m_allCategories); + loadHiddenCategories(); +} + +/** + * The total number of categories. Overrides virtual method of parent class. + * + * @param parent :: unused. + */ +int InterfaceCategoryModel::rowCount(const QModelIndex & parent) const +{ + UNUSED_ARG(parent); + + return m_allCategories.size(); +} + +/** + * The data to be put in the given header item. Overrides virtual method of parent class. + * + * @param section :: unused + * @param orientation :: either the top (horizontal) or left-hand (vertical) header. + * @param role :: the "role" of the data, which can be one of several enum values. See Qt docs for more info. + */ +QVariant InterfaceCategoryModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + UNUSED_ARG(section); + + if( role == Qt::DisplayRole && orientation == Qt::Horizontal ) + return QString("Show Interface Categories"); + + return QVariant(); +} + +/** + * The data assigned to a given item. Overrides virtual method of parent class. + * + * @param index :: the index of the item. + * @param role :: the "role" of the data, which can be one of several enum values. See Qt docs for more info. + */ +QVariant InterfaceCategoryModel::data(const QModelIndex & index, int role) const +{ + if( !index.isValid() ) + return QVariant(); + + if( role == Qt::DisplayRole ) + { + return m_allCategories[index.row()]; + } + if( role == Qt::CheckStateRole ) + { + QString category = m_allCategories[index.row()]; + if( m_hiddenCategories.contains(category) ) + return Qt::Unchecked; + else + return Qt::Checked; + } + + return QVariant(); +} + +/** + * Assigns data to the given item. Overrides virtual method of parent class. + * + * @param index :: the index of the item. + * @param value :: the data to assign to the item. + * @param role :: the "role" of the data, which can be one of several enum values. See Qt docs for more info. + */ +bool InterfaceCategoryModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if( !index.isValid() ) + return false; + + if (index.isValid() && role == Qt::CheckStateRole) + { + auto category = m_allCategories[index.row()]; + + if( value == Qt::Unchecked ) + m_hiddenCategories.insert(category); + else + m_hiddenCategories.remove(category); + + emit dataChanged(index, index); + return true; + } + + return false; +} + +/** + * The total number of categories. Overrides virtual method of parent class. + */ +Qt::ItemFlags InterfaceCategoryModel::flags(const QModelIndex & index) const +{ + return Qt::ItemIsUserCheckable | QAbstractListModel::flags(index); +} + +/** + * Persist this model's data to the user preferences file. + */ +void InterfaceCategoryModel::saveHiddenCategories() +{ + QString propValue = static_cast<QStringList>(m_hiddenCategories.toList()).join(";"); + + auto & config = Mantid::Kernel::ConfigService::Instance(); + config.setString("interfaces.categories.hidden", propValue.toStdString()); + config.saveConfig(config.getUserFilename()); +} + +/** + * Load this model's data from the user preferences file. + */ +void InterfaceCategoryModel::loadHiddenCategories() +{ + const QString propValue = QString::fromStdString( + Mantid::Kernel::ConfigService::Instance().getString("interfaces.categories.hidden") + ); + m_hiddenCategories = propValue.split(";", QString::SkipEmptyParts).toSet(); +} + +///////////////////////////////////////////////////// +// ManageInterfaceCategories +///////////////////////////////////////////////////// + +/** + * Constructor. + * + * @param parent :: the main MantidPlot ApplicationWindow object. + */ +ManageInterfaceCategories::ManageInterfaceCategories(ApplicationWindow * parent) : QDialog(parent), + m_model(parent->allCategories()) +{ + initLayout(); +} + +/** + * Set up the dialog. + */ +void ManageInterfaceCategories::initLayout() +{ + m_uiForm.setupUi(this); + + m_uiForm.categoryTreeView->setModel( &m_model ); + m_uiForm.categoryTreeView->show(); + + // OK button should save any changes and then exit. + connect(m_uiForm.okButton, SIGNAL(pressed()), + &m_model, SLOT(saveHiddenCategories())); + connect(m_uiForm.okButton, SIGNAL(pressed()), + this, SLOT(close())); + + // Cancel should just exit. + connect(m_uiForm.cancelButton, SIGNAL(pressed()), + this, SLOT(close())); + + connect(m_uiForm.helpButton, SIGNAL(pressed()), + this, SLOT(helpClicked())); +} + +/** + * Opens a web browser showing the wiki page for this dialog. + */ +void ManageInterfaceCategories::helpClicked() +{ + QUrl helpUrl("http://www.mantidproject.org/ManageInterfaceCategories"); + QDesktopServices::openUrl(helpUrl); +} diff --git a/Code/Mantid/MantidPlot/src/Mantid/ManageInterfaceCategories.h b/Code/Mantid/MantidPlot/src/Mantid/ManageInterfaceCategories.h new file mode 100644 index 0000000000000000000000000000000000000000..1f19823a1477e298684ba411e6fdbf182e3506a4 --- /dev/null +++ b/Code/Mantid/MantidPlot/src/Mantid/ManageInterfaceCategories.h @@ -0,0 +1,109 @@ +#ifndef MANTID_MANAGE_INTERFACE_CATEGORIES_H +#define MANTID_MANAGE_INTERFACE_CATEGORIES_H + +#include <QAbstractListModel> +#include <QDialog> +#include <QSet> +#include <QString> + +#include "ui_ManageInterfaceCategories.h" + +class ApplicationWindow; + +/** + * Copyright © 2013 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + * + * This file is part of Mantid. + * + * Mantid is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Mantid 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * File change history is stored at: <https://github.com/mantidproject/mantid> + * Code Documentation is available at: <http://doxygen.mantidproject.org> + */ + +/** + * This is a Model class that wraps the available interface categories along + * with the user's preferences about which categories to display. It + * interacts with the View in the ManageInterfaceCategories dialog, and + * persists its data using the user preferences file via the ConfigService. + + * See the Qt documentation for more information on how this class fits in to + * their implementation of Model-View programming. + */ +class InterfaceCategoryModel : public QAbstractListModel +{ + Q_OBJECT + +public: + /// Constructor. + InterfaceCategoryModel(const QSet<QString> & allCategories = QSet<QString>()); + + /// Required overloaded methods for an editable Qt data model: + + /// The total number of categories. + virtual int rowCount(const QModelIndex & parent) const; + /// Returns the information to be displayed in the column header. + virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + /// Returns the data used to fill each item in the model. + virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; + /// Used to set the data for each item in the model. + virtual bool setData(const QModelIndex &index, const QVariant &value, int role); + /// Flagging up the fact that this model contains checkable items. + virtual Qt::ItemFlags flags ( const QModelIndex & index ) const; + +public slots: + /// Persist this model's data to the user preferences file. + void saveHiddenCategories(); + +private: + /// Load this model's data from the user preferences file. + void loadHiddenCategories(); + + /// The set of all categories to be hidden. + QSet<QString> m_hiddenCategories; + /// A list of all categories. (Effectively a set, but implemented as a list so it can be sorted. + QList<QString> m_allCategories; +}; + +/** + * This class handles the "Manage Interface Categories" dialog in MantidPlot, in + * which users can add or remove the various interface categories listed in the + * "Interface" menu. + */ +class ManageInterfaceCategories : public QDialog +{ + Q_OBJECT + +public: + /// Only constructor. We insist on seeing the ApplicationWindow. + ManageInterfaceCategories(ApplicationWindow * parent); + +private slots: + /// Slot to open the help web page. + void helpClicked(); + +private: + /// Disallow default constructor. + ManageInterfaceCategories(); + + /// Set up the dialog. + void initLayout(); + + /// The widget form. + Ui::ManageInterfaceCategories m_uiForm; + /// The model used by the View of this dialog. + InterfaceCategoryModel m_model; +}; + +#endif /* MANTID_MANAGE_INTERFACE_CATEGORIES_H */ diff --git a/Code/Mantid/MantidPlot/src/Mantid/ManageInterfaceCategories.ui b/Code/Mantid/MantidPlot/src/Mantid/ManageInterfaceCategories.ui new file mode 100644 index 0000000000000000000000000000000000000000..04469f1b420e0aa41149087168eebf86697e0e59 --- /dev/null +++ b/Code/Mantid/MantidPlot/src/Mantid/ManageInterfaceCategories.ui @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ManageInterfaceCategories</class> + <widget class="QDialog" name="ManageInterfaceCategories"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>258</width> + <height>274</height> + </rect> + </property> + <property name="windowTitle"> + <string>Manage Interface Categories</string> + </property> + <property name="modal"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QTreeView" name="categoryTreeView"/> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="sizeConstraint"> + <enum>QLayout::SetDefaultConstraint</enum> + </property> + <item> + <widget class="QPushButton" name="helpButton"> + <property name="maximumSize"> + <size> + <width>35</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>?</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="okButton"> + <property name="text"> + <string>OK</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="cancelButton"> + <property name="text"> + <string>Cancel</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui>