Skip to content

Commit

Permalink
Refs #7614 - Add "Manage Interface Category" dialog.
Browse files Browse the repository at this point in the history
Tried to move things around and make the relevant code in
ApplicationWindow a bit better.

Removed the ability to add interfaces to custom menus.  That dialog is now
solely for Adding python scripts.
  • Loading branch information
PeterParker committed Oct 24, 2013
1 parent 757eb65 commit 6ccc7f6
Show file tree
Hide file tree
Showing 10 changed files with 575 additions and 193 deletions.
3 changes: 3 additions & 0 deletions Code/Mantid/Framework/Properties/Mantid.properties.template
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions Code/Mantid/MantidPlot/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
)

Expand Down
218 changes: 123 additions & 95 deletions Code/Mantid/MantidPlot/src/ApplicationWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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.
Expand All @@ -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.
{
Expand All @@ -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();
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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 );

Expand Down Expand Up @@ -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");
Expand All @@ -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);
}
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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);
Expand Down
15 changes: 13 additions & 2 deletions Code/Mantid/MantidPlot/src/ApplicationWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -1132,6 +1132,7 @@ public slots:
void tableMenuAboutToShow();
void windowsMenuAboutToShow();
void windowsMenuActivated( int id );
void interfaceMenuAboutToShow();

//! \name Font Format Functions
//@{
Expand All @@ -1150,6 +1151,7 @@ public slots:
//@}

void showCustomActionDialog();
void showInterfaceCategoriesDialog();
void showUserDirectoryDialog();
void performCustomAction(QAction *);

Expand Down Expand Up @@ -1329,8 +1331,6 @@ public slots:
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
//@{
Expand All @@ -1345,7 +1345,18 @@ public slots:
//! 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);
Expand Down

0 comments on commit 6ccc7f6

Please sign in to comment.