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.
This commit is contained in:
con
2011-01-21 10:58:06 +01:00
parent d768008d60
commit eaea867e53
12 changed files with 408 additions and 45 deletions

View File

@@ -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)
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)
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)

View File

@@ -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() {}
}; };

View File

@@ -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:
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:
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:
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();

View File

@@ -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)
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)
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);

View File

@@ -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);

View File

@@ -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) :
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
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)
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
}
}

View File

@@ -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

View File

@@ -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 {
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)
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
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
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)
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
readSettings(tools, &categoryPriorityMap);
QMap<QString, QList<Internal::ExternalTool *> > categoryMap;
QMapIterator<QString, QMultiMap<int, ExternalTool*> > it(categoryPriorityMap);
while (it.hasNext()) { while (it.hasNext()) {
it.next(); it.next();
m_categoryMap.insert(it.key(), it.value().values()); categoryMap.insert(it.key(), it.value().values());
} }
// add all the category menus, QMap is nicely sorted setToolsByCategory(categoryMap);
it.toFront();
while (it.hasNext()) {
it.next();
ActionContainer *container = 0;
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);
action->setToolTip(tool->description());
action->setWhatsThis(tool->description());
action->setData(tool->id());
Command *cmd = am->registerAction(action, Id("Tools.External." + tool->id()), Context(Constants::C_GLOBAL));
connect(action, SIGNAL(triggered()), this, SLOT(menuActivated()));
container->addAction(cmd, Constants::G_DEFAULT_TWO);
}
}
} }
void ExternalToolManager::parseDirectory(const QString &directory, QMap<QString, QMultiMap<int, ExternalTool*> > *categoryMenus, void ExternalToolManager::parseDirectory(const QString &directory,
QMap<QString, QMultiMap<int, Internal::ExternalTool*> > *categoryMenus,
QMap<QString, ExternalTool *> *tools,
bool ignoreDuplicates) bool ignoreDuplicates)
{ {
QTC_ASSERT(categoryMenus, return); QTC_ASSERT(categoryMenus, return);
QTC_ASSERT(tools, return);
QDir dir(directory, QLatin1String("*.xml"), QDir::Unsorted, QDir::Files | QDir::Readable); QDir dir(directory, QLatin1String("*.xml"), QDir::Unsorted, QDir::Files | QDir::Readable);
foreach (const QFileInfo &info, dir.entryInfoList()) { foreach (const QFileInfo &info, dir.entryInfoList()) {
QFile file(info.absoluteFilePath()); QFile file(info.absoluteFilePath());
@@ -517,14 +537,14 @@ void ExternalToolManager::parseDirectory(const QString &directory, QMap<QString,
qDebug() << tr("Error while parsing external tool %1: %2").arg(file.fileName(), error); qDebug() << tr("Error while parsing external tool %1: %2").arg(file.fileName(), error);
continue; continue;
} }
if (m_tools.contains(tool->id())) { if (tools->contains(tool->id())) {
// TODO error handling // TODO error handling
if (!ignoreDuplicates) if (!ignoreDuplicates)
qDebug() << tr("Error: External tool in %1 has duplicate id").arg(file.fileName()); qDebug() << tr("Error: External tool in %1 has duplicate id").arg(file.fileName());
delete tool; delete tool;
continue; continue;
} }
m_tools.insert(tool->id(), tool); tools->insert(tool->id(), tool);
(*categoryMenus)[tool->displayCategory()].insert(tool->order(), tool); (*categoryMenus)[tool->displayCategory()].insert(tool->order(), tool);
} }
} }
@@ -539,8 +559,162 @@ void ExternalToolManager::menuActivated()
new ExternalToolRunner(tool); new ExternalToolRunner(tool);
} }
QMap<QString, QList<Internal::ExternalTool *> > ExternalToolManager::tools() const QMap<QString, QList<Internal::ExternalTool *> > ExternalToolManager::toolsByCategory() const
{ {
return m_categoryMap; return m_categoryMap;
} }
QMap<QString, ExternalTool *> ExternalToolManager::toolsById() const
{
return m_tools;
}
void ExternalToolManager::setToolsByCategory(const QMap<QString, QList<Internal::ExternalTool *> > &tools)
{
// clear menu
ActionManager *am = m_core->actionManager();
ActionContainer *mexternaltools = am->actionContainer(Id(Constants::M_TOOLS_EXTERNAL));
mexternaltools->clear();
// delete old tools and create list of new ones
QMap<QString, ExternalTool *> newTools;
QMap<QString, QAction *> newActions;
QMapIterator<QString, QList<ExternalTool *> > it(tools);
while (it.hasNext()) {
it.next();
foreach (ExternalTool *tool, it.value()) {
const QString &id = tool->id();
if (m_tools.value(id) == tool) {
newActions.insert(id, m_actions.value(id));
// remove from list to prevent deletion
m_tools.remove(id);
m_actions.remove(id);
}
newTools.insert(id, tool);
}
}
qDeleteAll(m_tools);
QMapIterator<QString, QAction *> remainingActions(m_actions);
while (remainingActions.hasNext()) {
remainingActions.next();
am->unregisterAction(remainingActions.value(), Id("Tools.External." + remainingActions.key()));
delete remainingActions.value();
}
m_actions.clear();
// assign the new stuff
m_tools = newTools;
m_actions = newActions;
m_categoryMap = tools;
// create menu structure and remove no-longer used containers
// add all the category menus, QMap is nicely sorted
QMap<QString, ActionContainer *> newContainers;
it.toFront();
while (it.hasNext()) {
it.next();
ActionContainer *container = 0;
const QString &containerName = it.key();
if (containerName == QString()) { // no displayCategory, so put into external tools menu directly
container = mexternaltools;
} else {
if (m_containers.contains(containerName)) {
container = m_containers.take(containerName); // remove to avoid deletion below
} else {
container = am->createMenu(Id("Tools.External.Category." + containerName));
}
newContainers.insert(containerName, container);
mexternaltools->addMenu(container, Constants::G_DEFAULT_ONE);
container->menu()->setTitle(containerName);
}
foreach (ExternalTool *tool, it.value()) {
const QString &toolId = tool->id();
// tool action and command
QAction *action = 0;
Command *command = 0;
if (m_actions.contains(toolId)) {
action = m_actions.value(toolId);
command = am->command(Id("Tools.External." + toolId));
} else {
action = new QAction(tool->displayName(), this);
action->setData(toolId);
m_actions.insert(toolId, action);
connect(action, SIGNAL(triggered()), this, SLOT(menuActivated()));
command = am->registerAction(action, Id("Tools.External." + toolId), Context(Constants::C_GLOBAL));
command->setAttribute(Command::CA_UpdateText);
}
action->setText(tool->displayName());
action->setToolTip(tool->description());
action->setWhatsThis(tool->description());
container->addAction(command, Constants::G_DEFAULT_TWO);
}
}
// delete the unused containers
qDeleteAll(m_containers);
// remember the new containers
m_containers = newContainers;
}
void ExternalToolManager::readSettings(const QMap<QString, ExternalTool *> &tools,
QMap<QString, QMultiMap<int, Internal::ExternalTool*> > *categoryPriorityMap)
{
QSettings *settings = m_core->settings();
settings->beginGroup(QLatin1String("ExternalTools"));
settings->beginGroup(QLatin1String("OverrideDisplayNames"));
foreach (const QString &id, settings->allKeys()) {
if (tools.contains(id)) {
const QString &newName = settings->value(id).toString();
if (tools.value(id)->displayName() != newName)
tools.value(id)->setDisplayName(newName);
}
}
settings->endGroup();
if (categoryPriorityMap) {
settings->beginGroup(QLatin1String("OverrideCategories"));
foreach (const QString &id, settings->allKeys()) {
if (tools.contains(id)) {
const QString &newCategory = settings->value(id).toString();
ExternalTool *tool = tools.value(id);
if (tool->displayCategory() != newCategory) {
(*categoryPriorityMap)[tool->displayCategory()].remove(tool->order(), tool);
(*categoryPriorityMap)[newCategory].insert(tool->order(), tool);
if (categoryPriorityMap->value(tool->displayCategory()).isEmpty())
categoryPriorityMap->remove(tool->displayCategory());
}
}
}
settings->endGroup();
}
settings->endGroup();
}
void ExternalToolManager::writeSettings()
{
QSettings *settings = m_core->settings();
settings->beginGroup(QLatin1String("ExternalTools"));
settings->remove(QLatin1String(""));
settings->beginGroup(QLatin1String("OverrideDisplayNames"));
foreach (ExternalTool *tool, m_tools) {
if (tool->isDisplayNameChanged()) {
settings->setValue(tool->id(), tool->displayName());
}
}
settings->endGroup();
settings->beginGroup(QLatin1String("OverrideCategories"));
QMapIterator<QString, QList<ExternalTool *> > it(m_categoryMap);
while (it.hasNext()) {
it.next();
const QString &category = it.key();
foreach (ExternalTool *tool, it.value()) {
if (tool->displayCategory() != category)
settings->setValue(tool->id(), category);
}
}
settings->endGroup();
settings->endGroup();
}

View File

@@ -33,6 +33,7 @@
#include "icore.h" #include "icore.h"
#include "core_global.h" #include "core_global.h"
#include "actionmanager/command.h" #include "actionmanager/command.h"
#include "actionmanager/actioncontainer.h"
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>
@@ -58,12 +59,13 @@ public:
}; };
ExternalTool(); ExternalTool();
ExternalTool(const ExternalTool *other); explicit ExternalTool(const ExternalTool *other);
~ExternalTool(); ~ExternalTool();
QString id() const; QString id() const;
QString description() const; QString description() const;
QString displayName() const; QString displayName() const;
void setDisplayName(const QString &name);
QString displayCategory() const; QString displayCategory() const;
int order() const; int order() const;
OutputHandling outputHandling() const; OutputHandling outputHandling() const;
@@ -76,6 +78,11 @@ public:
static ExternalTool *createFromXml(const QByteArray &xml, QString *errorMessage = 0, const QString &locale = QString()); static ExternalTool *createFromXml(const QByteArray &xml, QString *errorMessage = 0, const QString &locale = QString());
// if the display name is different from the one in the original xml
bool isDisplayNameChanged() const { return m_isDisplayNameChanged; }
// ignores changed state
bool operator==(const ExternalTool &other);
private: private:
QString m_id; QString m_id;
QString m_description; QString m_description;
@@ -88,6 +95,7 @@ private:
QString m_workingDirectory; QString m_workingDirectory;
OutputHandling m_outputHandling; OutputHandling m_outputHandling;
OutputHandling m_errorHandling; OutputHandling m_errorHandling;
bool m_isDisplayNameChanged;
}; };
class ExternalToolRunner : public QObject class ExternalToolRunner : public QObject
@@ -95,6 +103,7 @@ class ExternalToolRunner : public QObject
Q_OBJECT Q_OBJECT
public: public:
ExternalToolRunner(const ExternalTool *tool); ExternalToolRunner(const ExternalTool *tool);
~ExternalToolRunner();
private slots: private slots:
void started(); void started();
@@ -107,7 +116,7 @@ private:
void run(); void run();
bool resolve(); bool resolve();
const ExternalTool *m_tool; const ExternalTool *m_tool; // is a copy of the tool that was passed in
QString m_resolvedExecutable; QString m_resolvedExecutable;
QString m_resolvedArguments; QString m_resolvedArguments;
QString m_resolvedInput; QString m_resolvedInput;
@@ -132,7 +141,10 @@ public:
ExternalToolManager(Core::ICore *core); ExternalToolManager(Core::ICore *core);
~ExternalToolManager(); ~ExternalToolManager();
QMap<QString, QList<Internal::ExternalTool *> > tools() const; QMap<QString, QList<Internal::ExternalTool *> > toolsByCategory() const;
QMap<QString, Internal::ExternalTool *> toolsById() const;
void setToolsByCategory(const QMap<QString, QList<Internal::ExternalTool *> > &tools);
signals: signals:
void replaceSelectionRequested(const QString &text); void replaceSelectionRequested(const QString &text);
@@ -142,13 +154,20 @@ private slots:
private: private:
void initialize(); void initialize();
void parseDirectory(const QString &directory, QMap<QString, QMultiMap<int, Internal::ExternalTool*> > *categoryMenus, void parseDirectory(const QString &directory,
QMap<QString, QMultiMap<int, Internal::ExternalTool*> > *categoryMenus,
QMap<QString, Internal::ExternalTool *> *tools,
bool ignoreDuplicates = false); bool ignoreDuplicates = false);
void readSettings(const QMap<QString, Internal::ExternalTool *> &tools,
QMap<QString, QMultiMap<int, Internal::ExternalTool*> > *categoryPriorityMap);
void writeSettings();
static ExternalToolManager *m_instance; static ExternalToolManager *m_instance;
Core::ICore *m_core; Core::ICore *m_core;
QMap<QString, Internal::ExternalTool *> m_tools; QMap<QString, Internal::ExternalTool *> m_tools;
QMap<QString, QList<Internal::ExternalTool *> > m_categoryMap; QMap<QString, QList<Internal::ExternalTool *> > m_categoryMap;
QMap<QString, QAction *> m_actions;
QMap<QString, ActionContainer *> m_containers;
// for sending the replaceSelectionRequested signal // for sending the replaceSelectionRequested signal
friend class Core::Internal::ExternalToolRunner; friend class Core::Internal::ExternalToolRunner;

View File

@@ -134,6 +134,7 @@ MainWindow::MainWindow() :
m_printer(0), m_printer(0),
m_actionManager(new ActionManagerPrivate(this)), m_actionManager(new ActionManagerPrivate(this)),
m_editorManager(0), m_editorManager(0),
m_externalToolManager(0),
m_fileManager(new FileManager(this)), m_fileManager(new FileManager(this)),
m_progressManager(new ProgressManagerPrivate()), m_progressManager(new ProgressManagerPrivate()),
m_scriptManager(new ScriptManagerPrivate(this)), m_scriptManager(new ScriptManagerPrivate(this)),
@@ -208,7 +209,7 @@ MainWindow::MainWindow() :
m_messageManager = new MessageManager; m_messageManager = new MessageManager;
m_editorManager = new EditorManager(m_coreImpl, this); m_editorManager = new EditorManager(m_coreImpl, this);
m_editorManager->hide(); m_editorManager->hide();
new ExternalToolManager(m_coreImpl); m_externalToolManager = new ExternalToolManager(m_coreImpl);
setCentralWidget(m_modeStack); setCentralWidget(m_modeStack);
connect(QApplication::instance(), SIGNAL(focusChanged(QWidget*,QWidget*)), connect(QApplication::instance(), SIGNAL(focusChanged(QWidget*,QWidget*)),
@@ -255,6 +256,8 @@ MainWindow::~MainWindow()
pm->removeObject(m_generalSettings); pm->removeObject(m_generalSettings);
pm->removeObject(m_toolSettings); pm->removeObject(m_toolSettings);
pm->removeObject(m_systemEditor); pm->removeObject(m_systemEditor);
delete m_externalToolManager;
m_externalToolManager = 0;
delete m_messageManager; delete m_messageManager;
m_messageManager = 0; m_messageManager = 0;
delete m_shortcutSettings; delete m_shortcutSettings;

View File

@@ -53,6 +53,7 @@ namespace Core {
class ActionManager; class ActionManager;
class StatusBarWidget; class StatusBarWidget;
class EditorManager; class EditorManager;
class ExternalToolManager;
class FileManager; class FileManager;
class HelpManager; class HelpManager;
class IWizard; class IWizard;
@@ -189,6 +190,7 @@ private:
mutable QPrinter *m_printer; mutable QPrinter *m_printer;
ActionManagerPrivate *m_actionManager; ActionManagerPrivate *m_actionManager;
EditorManager *m_editorManager; EditorManager *m_editorManager;
ExternalToolManager *m_externalToolManager;
FileManager *m_fileManager; FileManager *m_fileManager;
MessageManager *m_messageManager; MessageManager *m_messageManager;
ProgressManagerPrivate *m_progressManager; ProgressManagerPrivate *m_progressManager;

View File

@@ -80,7 +80,7 @@ bool ToolSettings::matches(const QString & searchKeyWord) const
QWidget *ToolSettings::createPage(QWidget *parent) QWidget *ToolSettings::createPage(QWidget *parent)
{ {
m_widget = new ExternalToolConfig(parent); m_widget = new ExternalToolConfig(parent);
m_widget->setTools(ExternalToolManager::instance()->tools()); m_widget->setTools(ExternalToolManager::instance()->toolsByCategory());
if (m_searchKeywords.isEmpty()) { if (m_searchKeywords.isEmpty()) {
m_searchKeywords = m_widget->searchKeywords(); m_searchKeywords = m_widget->searchKeywords();
} }
@@ -90,6 +90,30 @@ QWidget *ToolSettings::createPage(QWidget *parent)
void ToolSettings::apply() void ToolSettings::apply()
{ {
if (!m_widget)
return;
QMap<QString, ExternalTool *> originalTools = ExternalToolManager::instance()->toolsById();
QMap<QString, QList<ExternalTool *> > newToolsMap = m_widget->tools();
QMap<QString, QList<ExternalTool *> > resultMap;
QMapIterator<QString, QList<ExternalTool *> > it(newToolsMap);
while (it.hasNext()) {
it.next();
QList<ExternalTool *> items;
foreach (ExternalTool *tool, it.value()) {
ExternalTool *toolToAdd = 0;
if (ExternalTool *originalTool = originalTools.take(tool->id())) {
// check if the tool has changed
if ((*originalTool) == (*tool)) {
toolToAdd = originalTool;
} else {
toolToAdd = new ExternalTool(tool);
}
}
items.append(toolToAdd);
}
resultMap.insert(it.key(), items);
}
ExternalToolManager::instance()->setToolsByCategory(resultMap);
} }