Commit eaea867e authored by con's avatar con
Browse files

Implement renaming of tools and categories.

Not possible to reset them yet.
Saves the change in the settings instead of writing new tools xml files.
This probably needs to be adapted for tools that are "local" from the
beginning.
parent d768008d
...@@ -268,10 +268,32 @@ void ActionContainerPrivate::addMenu(ActionContainer *menu, const QString &group ...@@ -268,10 +268,32 @@ void ActionContainerPrivate::addMenu(ActionContainer *menu, const QString &group
QAction *beforeAction = insertLocation(groupIt); QAction *beforeAction = insertLocation(groupIt);
m_groups[groupIt-m_groups.constBegin()].items.append(menu); m_groups[groupIt-m_groups.constBegin()].items.append(menu);
connect(menu, SIGNAL(destroyed()), this, SLOT(itemDestroyed()));
insertMenu(beforeAction, container->menu()); insertMenu(beforeAction, container->menu());
scheduleUpdate(); scheduleUpdate();
} }
void ActionContainerPrivate::clear()
{
QMutableListIterator<Group> it(m_groups);
while (it.hasNext()) {
Group &group = it.next();
foreach (QObject *item, group.items) {
if (Command *command = qobject_cast<Command *>(item)) {
removeAction(command->action());
disconnect(command, SIGNAL(activeStateChanged()), this, SLOT(scheduleUpdate()));
disconnect(command, SIGNAL(destroyed()), this, SLOT(itemDestroyed()));
} else if (ActionContainer *container = qobject_cast<ActionContainer *>(item)) {
container->clear();
disconnect(container, SIGNAL(destroyed()), this, SLOT(itemDestroyed()));
removeMenu(container->menu());
}
}
group.items.clear();
}
scheduleUpdate();
}
void ActionContainerPrivate::itemDestroyed() void ActionContainerPrivate::itemDestroyed()
{ {
QObject *obj = sender(); QObject *obj = sender();
...@@ -350,6 +372,16 @@ void MenuActionContainer::insertMenu(QAction *before, QMenu *menu) ...@@ -350,6 +372,16 @@ void MenuActionContainer::insertMenu(QAction *before, QMenu *menu)
m_menu->insertMenu(before, menu); m_menu->insertMenu(before, menu);
} }
void MenuActionContainer::removeAction(QAction *action)
{
m_menu->removeAction(action);
}
void MenuActionContainer::removeMenu(QMenu *menu)
{
m_menu->removeAction(menu->menuAction());
}
bool MenuActionContainer::updateInternal() bool MenuActionContainer::updateInternal()
{ {
if (onAllDisabledBehavior() == Show) if (onAllDisabledBehavior() == Show)
...@@ -442,6 +474,16 @@ void MenuBarActionContainer::insertMenu(QAction *before, QMenu *menu) ...@@ -442,6 +474,16 @@ void MenuBarActionContainer::insertMenu(QAction *before, QMenu *menu)
m_menuBar->insertMenu(before, menu); m_menuBar->insertMenu(before, menu);
} }
void MenuBarActionContainer::removeAction(QAction *action)
{
m_menuBar->removeAction(action);
}
void MenuBarActionContainer::removeMenu(QMenu *menu)
{
m_menuBar->removeAction(menu->menuAction());
}
bool MenuBarActionContainer::updateInternal() bool MenuBarActionContainer::updateInternal()
{ {
if (onAllDisabledBehavior() == Show) if (onAllDisabledBehavior() == Show)
......
...@@ -70,6 +70,9 @@ public: ...@@ -70,6 +70,9 @@ public:
virtual void addAction(Core::Command *action, const QString &group = QString()) = 0; virtual void addAction(Core::Command *action, const QString &group = QString()) = 0;
virtual void addMenu(Core::ActionContainer *menu, const QString &group = QString()) = 0; virtual void addMenu(Core::ActionContainer *menu, const QString &group = QString()) = 0;
// clears this menu and submenus from all actions and submenus
// doesn't destroy the submenus and commands, just removes them from their parents
virtual void clear() = 0;
virtual ~ActionContainer() {} virtual ~ActionContainer() {}
}; };
......
...@@ -63,6 +63,7 @@ public: ...@@ -63,6 +63,7 @@ public:
void appendGroup(const QString &id); void appendGroup(const QString &id);
void addAction(Command *action, const QString &group = QString()); void addAction(Command *action, const QString &group = QString());
void addMenu(ActionContainer *menu, const QString &group = QString()); void addMenu(ActionContainer *menu, const QString &group = QString());
virtual void clear();
int id() const; int id() const;
...@@ -72,6 +73,9 @@ public: ...@@ -72,6 +73,9 @@ public:
virtual void insertAction(QAction *before, QAction *action) = 0; virtual void insertAction(QAction *before, QAction *action) = 0;
virtual void insertMenu(QAction *before, QMenu *menu) = 0; virtual void insertMenu(QAction *before, QMenu *menu) = 0;
virtual void removeAction(QAction *action) = 0;
virtual void removeMenu(QMenu *menu) = 0;
virtual bool updateInternal() = 0; virtual bool updateInternal() = 0;
protected: protected:
...@@ -107,6 +111,9 @@ public: ...@@ -107,6 +111,9 @@ public:
void insertAction(QAction *before, QAction *action); void insertAction(QAction *before, QAction *action);
void insertMenu(QAction *before, QMenu *menu); void insertMenu(QAction *before, QMenu *menu);
void removeAction(QAction *action);
void removeMenu(QMenu *menu);
protected: protected:
bool canBeAddedToMenu() const; bool canBeAddedToMenu() const;
bool updateInternal(); bool updateInternal();
...@@ -126,6 +133,9 @@ public: ...@@ -126,6 +133,9 @@ public:
void insertAction(QAction *before, QAction *action); void insertAction(QAction *before, QAction *action);
void insertMenu(QAction *before, QMenu *menu); void insertMenu(QAction *before, QMenu *menu);
void removeAction(QAction *action);
void removeMenu(QMenu *menu);
protected: protected:
bool canBeAddedToMenu() const; bool canBeAddedToMenu() const;
bool updateInternal(); bool updateInternal();
......
...@@ -248,6 +248,8 @@ ActionManagerPrivate::ActionManagerPrivate(MainWindow *mainWnd) ...@@ -248,6 +248,8 @@ ActionManagerPrivate::ActionManagerPrivate(MainWindow *mainWnd)
ActionManagerPrivate::~ActionManagerPrivate() ActionManagerPrivate::~ActionManagerPrivate()
{ {
// first delete containers to avoid them reacting to command deletion // first delete containers to avoid them reacting to command deletion
foreach (ActionContainerPrivate *container, m_idContainerMap)
disconnect(container, SIGNAL(destroyed()), this, SLOT(containerDestroyed()));
qDeleteAll(m_idContainerMap.values()); qDeleteAll(m_idContainerMap.values());
qDeleteAll(m_idCmdMap.values()); qDeleteAll(m_idCmdMap.values());
} }
...@@ -314,6 +316,7 @@ ActionContainer *ActionManagerPrivate::createMenu(const Id &id) ...@@ -314,6 +316,7 @@ ActionContainer *ActionManagerPrivate::createMenu(const Id &id)
mc->setMenu(m); mc->setMenu(m);
m_idContainerMap.insert(uid, mc); m_idContainerMap.insert(uid, mc);
connect(mc, SIGNAL(destroyed()), this, SLOT(containerDestroyed()));
return mc; return mc;
} }
...@@ -332,10 +335,17 @@ ActionContainer *ActionManagerPrivate::createMenuBar(const Id &id) ...@@ -332,10 +335,17 @@ ActionContainer *ActionManagerPrivate::createMenuBar(const Id &id)
mbc->setMenuBar(mb); mbc->setMenuBar(mb);
m_idContainerMap.insert(uid, mbc); m_idContainerMap.insert(uid, mbc);
connect(mbc, SIGNAL(destroyed()), this, SLOT(containerDestroyed()));
return mbc; return mbc;
} }
void ActionManagerPrivate::containerDestroyed()
{
ActionContainerPrivate *container = static_cast<ActionContainerPrivate *>(sender());
m_idContainerMap.remove(m_idContainerMap.key(container));
}
Command *ActionManagerPrivate::registerAction(QAction *action, const Id &id, const Context &context, bool scriptable) Command *ActionManagerPrivate::registerAction(QAction *action, const Id &id, const Context &context, bool scriptable)
{ {
Action *a = overridableAction(id); Action *a = overridableAction(id);
......
...@@ -93,6 +93,8 @@ public: ...@@ -93,6 +93,8 @@ public:
void unregisterAction(QAction *action, const Id &id); void unregisterAction(QAction *action, const Id &id);
void unregisterShortcut(const Id &id); void unregisterShortcut(const Id &id);
private slots:
void containerDestroyed();
private: private:
bool hasContext(const Context &context) const; bool hasContext(const Context &context) const;
Action *overridableAction(const Id &id); Action *overridableAction(const Id &id);
......
...@@ -34,6 +34,8 @@ ...@@ -34,6 +34,8 @@
#include "externaltoolconfig.h" #include "externaltoolconfig.h"
#include "ui_externaltoolconfig.h" #include "ui_externaltoolconfig.h"
#include <utils/qtcassert.h>
#include <QtCore/QTextStream> #include <QtCore/QTextStream>
using namespace Core::Internal; using namespace Core::Internal;
...@@ -43,13 +45,21 @@ ExternalToolConfig::ExternalToolConfig(QWidget *parent) : ...@@ -43,13 +45,21 @@ ExternalToolConfig::ExternalToolConfig(QWidget *parent) :
ui(new Ui::ExternalToolConfig) ui(new Ui::ExternalToolConfig)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->toolTree->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed);
connect(ui->toolTree, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), connect(ui->toolTree, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
this, SLOT(showInfoForItem(QTreeWidgetItem*))); this, SLOT(showInfoForItem(QTreeWidgetItem*)));
connect(ui->toolTree, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
this, SLOT(updateItem(QTreeWidgetItem *)));
showInfoForItem(0); showInfoForItem(0);
} }
ExternalToolConfig::~ExternalToolConfig() ExternalToolConfig::~ExternalToolConfig()
{ {
QMapIterator<QString, QList<ExternalTool *> > it(m_tools);
while (it.hasNext()) {
it.next();
qDeleteAll(it.value());
}
delete ui; delete ui;
} }
...@@ -69,19 +79,32 @@ QString ExternalToolConfig::searchKeywords() const ...@@ -69,19 +79,32 @@ QString ExternalToolConfig::searchKeywords() const
void ExternalToolConfig::setTools(const QMap<QString, QList<ExternalTool *> > &tools) void ExternalToolConfig::setTools(const QMap<QString, QList<ExternalTool *> > &tools)
{ {
// TODO make copy of tools QMapIterator<QString, QList<ExternalTool *> > it(tools);
while (it.hasNext()) {
it.next();
QList<ExternalTool *> itemCopy;
foreach (ExternalTool *tool, it.value())
itemCopy.append(new ExternalTool(tool));
m_tools.insert(it.key(), itemCopy);
}
QMapIterator<QString, QList<ExternalTool *> > categories(tools); bool blocked = ui->toolTree->blockSignals(true); // block itemChanged
Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable;
QMapIterator<QString, QList<ExternalTool *> > categories(m_tools);
while (categories.hasNext()) { while (categories.hasNext()) {
categories.next(); categories.next();
QString name = (categories.key().isEmpty() ? tr("External Tools Menu") : categories.key()); QString name = (categories.key().isEmpty() ? tr("External Tools Menu") : categories.key());
QTreeWidgetItem *category = new QTreeWidgetItem(ui->toolTree, QStringList() << name); QTreeWidgetItem *category = new QTreeWidgetItem(ui->toolTree, QStringList() << name);
category->setFlags(flags);
category->setData(0, Qt::UserRole, name); // save the name in case of category being renamed by user
foreach (ExternalTool *tool, categories.value()) { foreach (ExternalTool *tool, categories.value()) {
QTreeWidgetItem *item = new QTreeWidgetItem(category, QStringList() << tool->displayName()); QTreeWidgetItem *item = new QTreeWidgetItem(category, QStringList() << tool->displayName());
item->setFlags(flags);
item->setData(0, Qt::UserRole, qVariantFromValue(tool)); item->setData(0, Qt::UserRole, qVariantFromValue(tool));
} }
} }
ui->toolTree->expandAll(); ui->toolTree->expandAll();
ui->toolTree->blockSignals(blocked); // unblock itemChanged
} }
void ExternalToolConfig::showInfoForItem(QTreeWidgetItem *item) void ExternalToolConfig::showInfoForItem(QTreeWidgetItem *item)
...@@ -110,3 +133,51 @@ void ExternalToolConfig::showInfoForItem(QTreeWidgetItem *item) ...@@ -110,3 +133,51 @@ void ExternalToolConfig::showInfoForItem(QTreeWidgetItem *item)
ui->description->setCursorPosition(0); ui->description->setCursorPosition(0);
ui->arguments->setCursorPosition(0); ui->arguments->setCursorPosition(0);
} }
void ExternalToolConfig::updateItem(QTreeWidgetItem *item)
{
ExternalTool *tool = 0;
if (item)
tool = item->data(0, Qt::UserRole).value<ExternalTool *>();
if (tool) {
// tool was renamed
const QString &newName = item->data(0, Qt::DisplayRole).toString();
if (newName == tool->displayName())
return;
if (newName.isEmpty()) {
// prevent empty names
bool blocked = ui->toolTree->blockSignals(true); // block itemChanged
item->setData(0, Qt::DisplayRole, tool->displayName());
ui->toolTree->blockSignals(blocked); // unblock itemChanged
return;
}
tool->setDisplayName(item->data(0, Qt::DisplayRole).toString());
} else {
// category was renamed
const QString &oldName = item->data(0, Qt::UserRole).toString();
const QString &newName = item->data(0, Qt::DisplayRole).toString();
if (oldName == newName)
return;
if (newName.isEmpty() && m_tools.contains(newName)) {
// prevent empty or duplicate names
bool blocked = ui->toolTree->blockSignals(true); // block itemChanged
item->setData(0, Qt::DisplayRole, oldName);
ui->toolTree->blockSignals(blocked); // unblock itemChanged
return;
}
QTC_ASSERT(m_tools.contains(oldName), return);
m_tools.insert(newName, m_tools.value(oldName));
m_tools.remove(oldName);
bool blocked = ui->toolTree->blockSignals(true); // block itemChanged
item->setData(0, Qt::UserRole, newName);
int currentIndex = ui->toolTree->indexOfTopLevelItem(item);
bool wasExpanded = ui->toolTree->isExpanded(ui->toolTree->model()->index(currentIndex, 0));
ui->toolTree->takeTopLevelItem(currentIndex);
int newIndex = m_tools.keys().indexOf(newName);
ui->toolTree->insertTopLevelItem(newIndex, item);
if (wasExpanded)
ui->toolTree->expand(ui->toolTree->model()->index(newIndex, 0));
ui->toolTree->blockSignals(blocked); // unblock itemChanged
}
}
...@@ -55,14 +55,17 @@ public: ...@@ -55,14 +55,17 @@ public:
~ExternalToolConfig(); ~ExternalToolConfig();
void setTools(const QMap<QString, QList<ExternalTool *> > &tools); void setTools(const QMap<QString, QList<ExternalTool *> > &tools);
QMap<QString, QList<ExternalTool *> > tools() const { return m_tools; }
QString searchKeywords() const; QString searchKeywords() const;
private slots: private slots:
void showInfoForItem(QTreeWidgetItem *item); void showInfoForItem(QTreeWidgetItem *item);
void updateItem(QTreeWidgetItem *item);
private: private:
Ui::ExternalToolConfig *ui; Ui::ExternalToolConfig *ui;
QMap<QString, QList<ExternalTool *> > m_tools;
}; };
} // Internal } // Internal
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include "externaltool.h" #include "externaltool.h"
#include "actionmanager/actionmanager.h" #include "actionmanager/actionmanager.h"
#include "actionmanager/actioncontainer.h"
#include "coreconstants.h" #include "coreconstants.h"
#include "variablemanager.h" #include "variablemanager.h"
...@@ -80,7 +79,8 @@ namespace { ...@@ -80,7 +79,8 @@ namespace {
ExternalTool::ExternalTool() : ExternalTool::ExternalTool() :
m_order(-1), m_order(-1),
m_outputHandling(ShowInPane), m_outputHandling(ShowInPane),
m_errorHandling(ShowInPane) m_errorHandling(ShowInPane),
m_isDisplayNameChanged(false)
{ {
} }
...@@ -95,7 +95,8 @@ ExternalTool::ExternalTool(const ExternalTool *other) ...@@ -95,7 +95,8 @@ ExternalTool::ExternalTool(const ExternalTool *other)
m_input(other->m_input), m_input(other->m_input),
m_workingDirectory(other->m_workingDirectory), m_workingDirectory(other->m_workingDirectory),
m_outputHandling(other->m_outputHandling), m_outputHandling(other->m_outputHandling),
m_errorHandling(other->m_errorHandling) m_errorHandling(other->m_errorHandling),
m_isDisplayNameChanged(other->m_isDisplayNameChanged)
{ {
} }
...@@ -118,6 +119,14 @@ QString ExternalTool::displayName() const ...@@ -118,6 +119,14 @@ QString ExternalTool::displayName() const
return m_displayName; return m_displayName;
} }
void ExternalTool::setDisplayName(const QString &name)
{
if (name == m_displayName)
return;
m_isDisplayNameChanged = true;
m_displayName = name;
}
QString ExternalTool::displayCategory() const QString ExternalTool::displayCategory() const
{ {
return m_displayCategory; return m_displayCategory;
...@@ -298,16 +307,37 @@ ExternalTool * ExternalTool::createFromXml(const QByteArray &xml, QString *error ...@@ -298,16 +307,37 @@ ExternalTool * ExternalTool::createFromXml(const QByteArray &xml, QString *error
return tool; return tool;
} }
bool ExternalTool::operator==(const ExternalTool &other)
{
return m_id == other.m_id
&& m_description == other.m_description
&& m_displayName == other.m_displayName
&& m_displayCategory == other.m_displayCategory
&& m_order == other.m_order
&& m_executables == other.m_executables
&& m_arguments == other.m_arguments
&& m_input == other.m_input
&& m_workingDirectory == other.m_workingDirectory
&& m_outputHandling == other.m_outputHandling
&& m_errorHandling == other.m_errorHandling;
}
// #pragma mark -- ExternalToolRunner // #pragma mark -- ExternalToolRunner
ExternalToolRunner::ExternalToolRunner(const ExternalTool *tool) ExternalToolRunner::ExternalToolRunner(const ExternalTool *tool)
: m_tool(tool), : m_tool(new ExternalTool(tool)),
m_process(0), m_process(0),
m_outputCodec(QTextCodec::codecForLocale()) m_outputCodec(QTextCodec::codecForLocale())
{ {
run(); run();
} }
ExternalToolRunner::~ExternalToolRunner()
{
if (m_tool)
delete m_tool;
}
bool ExternalToolRunner::resolve() bool ExternalToolRunner::resolve()
{ {
if (!m_tool) if (!m_tool)
...@@ -450,60 +480,50 @@ ExternalToolManager::ExternalToolManager(Core::ICore *core) ...@@ -450,60 +480,50 @@ ExternalToolManager::ExternalToolManager(Core::ICore *core)
ExternalToolManager::~ExternalToolManager() ExternalToolManager::~ExternalToolManager()
{ {
writeSettings();
// TODO kill running tools // TODO kill running tools
qDeleteAll(m_tools); qDeleteAll(m_tools);
} }
void ExternalToolManager::initialize() void ExternalToolManager::initialize()
{ {
// add the external tools menu
ActionManager *am = m_core->actionManager(); ActionManager *am = m_core->actionManager();
ActionContainer *mexternaltools = am->createMenu(Id(Constants::M_TOOLS_EXTERNAL)); ActionContainer *mexternaltools = am->createMenu(Id(Constants::M_TOOLS_EXTERNAL));
mexternaltools->menu()->setTitle(tr("External")); mexternaltools->menu()->setTitle(tr("External"));
ActionContainer *mtools = am->actionContainer(Constants::M_TOOLS); ActionContainer *mtools = am->actionContainer(Constants::M_TOOLS);
mtools->addMenu(mexternaltools, Constants::G_DEFAULT_THREE); mtools->addMenu(mexternaltools, Constants::G_DEFAULT_THREE);
QMap<QString, QMultiMap<int, ExternalTool*> > categoryMap; QMap<QString, QMultiMap<int, ExternalTool*> > categoryPriorityMap;
QMap<QString, ExternalTool *> tools;
parseDirectory(m_core->userResourcePath() + QLatin1String("/externaltools"), parseDirectory(m_core->userResourcePath() + QLatin1String("/externaltools"),
&categoryMap); &categoryPriorityMap,
&tools);
parseDirectory(m_core->resourcePath() + QLatin1String("/externaltools"), parseDirectory(m_core->resourcePath() + QLatin1String("/externaltools"),
&categoryMap, true); &categoryPriorityMap,
&tools,
true);
QMapIterator<QString, QMultiMap<int, ExternalTool*> > it(categoryMap); // adapt overridden names and categories etc
while (it.hasNext()) { readSettings(tools, &categoryPriorityMap);
it.next();
m_categoryMap.insert(it.key(), it.value().values());
}
// add all the category menus, QMap is nicely sorted QMap<QString, QList<Internal::ExternalTool *> > categoryMap;
it.toFront(); QMapIterator<QString, QMultiMap<int, ExternalTool*> > it(categoryPriorityMap);
while (it.hasNext()) { while (it.hasNext()) {
it.next(); it.next();
ActionContainer *container = 0; categoryMap.insert(it.key(), it.value().values());
if (it.key() == QString()) { // no displayCategory, so put into external tools menu directly
container = mexternaltools;
} else {
container = am->createMenu(Id("Tools.External.Category." + it.key()));
mexternaltools->addMenu(container, Constants::G_DEFAULT_ONE);
container->menu()->setTitle(it.key());
}
foreach (ExternalTool *tool, it.value().values()) {
// tool action and command
QAction *action = new QAction(tool->displayName(), this);