diff --git a/src/plugins/coreplugin/dialogs/externaltoolconfig.cpp b/src/plugins/coreplugin/dialogs/externaltoolconfig.cpp index 02f33d7c249fcc7c546cf57fcf1ecae28c7289e5..ae4b4681d2dad8b96780c02efc8abbd593c20513 100644 --- a/src/plugins/coreplugin/dialogs/externaltoolconfig.cpp +++ b/src/plugins/coreplugin/dialogs/externaltoolconfig.cpp @@ -36,8 +36,13 @@ #include <utils/qtcassert.h> +#include <coreplugin/coreconstants.h> + #include <QtCore/QTextStream> +#include <QtCore/QFile> +#include <QtGui/QMessageBox> +using namespace Core; using namespace Core::Internal; ExternalToolConfig::ExternalToolConfig(QWidget *parent) : @@ -50,8 +55,24 @@ ExternalToolConfig::ExternalToolConfig(QWidget *parent) : this, SLOT(handleCurrentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*))); connect(ui->toolTree, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(updateItemName(QTreeWidgetItem *))); + connect(ui->description, SIGNAL(editingFinished()), this, SLOT(updateCurrentItem())); + connect(ui->executable, SIGNAL(editingFinished()), this, SLOT(updateCurrentItem())); + connect(ui->executable, SIGNAL(browsingFinished()), this, SLOT(updateCurrentItem())); + connect(ui->arguments, SIGNAL(editingFinished()), this, SLOT(updateCurrentItem())); + connect(ui->workingDirectory, SIGNAL(editingFinished()), this, SLOT(updateCurrentItem())); + connect(ui->workingDirectory, SIGNAL(browsingFinished()), this, SLOT(updateCurrentItem())); + connect(ui->outputBehavior, SIGNAL(activated(int)), this, SLOT(updateCurrentItem())); + connect(ui->errorOutputBehavior, SIGNAL(activated(int)), this, SLOT(updateCurrentItem())); + connect(ui->modifiesDocumentCheckbox, SIGNAL(clicked()), this, SLOT(updateCurrentItem())); + connect(ui->inputText, SIGNAL(textChanged()), this, SLOT(updateCurrentItem())); + + ui->addButton->setIcon(QIcon(QLatin1String(Constants::ICON_PLUS))); + ui->removeButton->setIcon(QIcon(QLatin1String(Constants::ICON_MINUS))); + ui->revertButton->setIcon(QIcon(QLatin1String(Constants::ICON_RESET))); + connect(ui->revertButton, SIGNAL(clicked()), this, SLOT(revertCurrentItem())); showInfoForItem(0); + updateButtons(ui->toolTree->currentItem()); } ExternalToolConfig::~ExternalToolConfig() @@ -115,6 +136,32 @@ void ExternalToolConfig::handleCurrentItemChanged(QTreeWidgetItem *now, QTreeWid showInfoForItem(now); } +void ExternalToolConfig::updateButtons(QTreeWidgetItem *item) +{ + ExternalTool *tool = 0; + if (item) + tool = item->data(0, Qt::UserRole).value<ExternalTool *>(); + if (!tool) { + ui->removeButton->setEnabled(false); + ui->revertButton->setEnabled(false); + return; + } + if (!tool->preset()) { + ui->removeButton->setEnabled(true); + ui->revertButton->setEnabled(false); + } else { + ui->removeButton->setEnabled(false); + ui->revertButton->setEnabled((*tool) != (*(tool->preset()))); + } +} + +void ExternalToolConfig::updateCurrentItem() +{ + QTreeWidgetItem *item = ui->toolTree->currentItem(); + updateItem(item); + updateButtons(item); +} + void ExternalToolConfig::updateItem(QTreeWidgetItem *item) { ExternalTool *tool = 0; @@ -125,12 +172,12 @@ void ExternalToolConfig::updateItem(QTreeWidgetItem *item) tool->setDescription(ui->description->text()); QStringList executables = tool->executables(); if (executables.size() > 0) - executables[0] = ui->executable->path(); + executables[0] = ui->executable->rawPath(); else - executables << ui->executable->path(); + executables << ui->executable->rawPath(); tool->setExecutables(executables); tool->setArguments(ui->arguments->text()); - tool->setWorkingDirectory(ui->workingDirectory->path()); + tool->setWorkingDirectory(ui->workingDirectory->rawPath()); tool->setOutputHandling((ExternalTool::OutputHandling)ui->outputBehavior->currentIndex()); tool->setErrorHandling((ExternalTool::OutputHandling)ui->errorOutputBehavior->currentIndex()); tool->setModifiesCurrentDocument(ui->modifiesDocumentCheckbox->checkState()); @@ -139,6 +186,7 @@ void ExternalToolConfig::updateItem(QTreeWidgetItem *item) void ExternalToolConfig::showInfoForItem(QTreeWidgetItem *item) { + updateButtons(item); ExternalTool *tool = 0; if (item) tool = item->data(0, Qt::UserRole).value<ExternalTool *>(); @@ -159,7 +207,9 @@ void ExternalToolConfig::showInfoForItem(QTreeWidgetItem *item) ui->outputBehavior->setCurrentIndex((int)tool->outputHandling()); ui->errorOutputBehavior->setCurrentIndex((int)tool->errorHandling()); ui->modifiesDocumentCheckbox->setChecked(tool->modifiesCurrentDocument()); + bool blocked = ui->inputText->blockSignals(true); ui->inputText->setPlainText(tool->input()); + ui->inputText->blockSignals(blocked); ui->description->setCursorPosition(0); ui->arguments->setCursorPosition(0); } @@ -210,6 +260,7 @@ void ExternalToolConfig::updateItemName(QTreeWidgetItem *item) ui->toolTree->expand(ui->toolTree->model()->index(newIndex, 0)); ui->toolTree->blockSignals(blocked); // unblock itemChanged } + updateButtons(item); } QMap<QString, QList<ExternalTool *> > ExternalToolConfig::tools() const @@ -220,4 +271,31 @@ QMap<QString, QList<ExternalTool *> > ExternalToolConfig::tools() const void ExternalToolConfig::apply() { updateItem(ui->toolTree->currentItem()); + updateButtons(ui->toolTree->currentItem()); +} + +void ExternalToolConfig::revertCurrentItem() +{ + QTreeWidgetItem *currentItem = ui->toolTree->currentItem(); + QTC_ASSERT(currentItem, return); + ExternalTool *tool = currentItem->data(0, Qt::UserRole).value<ExternalTool *>(); + QTC_ASSERT(tool, return); + QTC_ASSERT(tool->preset() && !tool->preset()->fileName().isEmpty(), return); + ExternalTool *resetTool = new ExternalTool(tool->preset().data()); + resetTool->setPreset(tool->preset()); + bool blocked = ui->toolTree->blockSignals(true); // block itemChanged + currentItem->setData(0, Qt::UserRole, qVariantFromValue(resetTool)); + currentItem->setData(0, Qt::DisplayRole, resetTool->displayName()); + ui->toolTree->blockSignals(blocked); // unblock itemChanged + showInfoForItem(currentItem); + QMutableMapIterator<QString, QList<ExternalTool *> > it(m_tools); + while (it.hasNext()) { + it.next(); + QList<ExternalTool *> &items = it.value(); + int index = items.indexOf(tool); + if (index != -1) { + items[index] = resetTool; + } + } + delete tool; } diff --git a/src/plugins/coreplugin/dialogs/externaltoolconfig.h b/src/plugins/coreplugin/dialogs/externaltoolconfig.h index 0cf6669e0891be85b306d9cf5bc415cae025b288..cfe939e44d1b0d5c211c2c095adb83251247b274 100644 --- a/src/plugins/coreplugin/dialogs/externaltoolconfig.h +++ b/src/plugins/coreplugin/dialogs/externaltoolconfig.h @@ -65,6 +65,9 @@ private slots: void showInfoForItem(QTreeWidgetItem *item); void updateItem(QTreeWidgetItem *item); void updateItemName(QTreeWidgetItem *item); + void revertCurrentItem(); + void updateButtons(QTreeWidgetItem *item); + void updateCurrentItem(); private: Ui::ExternalToolConfig *ui; diff --git a/src/plugins/coreplugin/dialogs/externaltoolconfig.ui b/src/plugins/coreplugin/dialogs/externaltoolconfig.ui index 0ef84c4aed5cc8c02e4b5e8d431a211784219f7c..9e8495e9b732292d2c9b3304ca6db29fdc8e0b68 100644 --- a/src/plugins/coreplugin/dialogs/externaltoolconfig.ui +++ b/src/plugins/coreplugin/dialogs/externaltoolconfig.ui @@ -13,18 +13,81 @@ <property name="windowTitle"> <string>Form</string> </property> - <layout class="QHBoxLayout" name="horizontalLayout"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> <item> - <widget class="QTreeWidget" name="toolTree"> - <attribute name="headerVisible"> - <bool>false</bool> - </attribute> - <column> - <property name="text"> - <string notr="true">1</string> - </property> - </column> - </widget> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QTreeWidget" name="toolTree"> + <attribute name="headerVisible"> + <bool>false</bool> + </attribute> + <column> + <property name="text"> + <string notr="true">1</string> + </property> + </column> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QToolButton" name="addButton"> + <property name="toolTip"> + <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Lucida Grande'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Add tool</p></body></html></string> + </property> + <property name="text"> + <string>+</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="removeButton"> + <property name="toolTip"> + <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Lucida Grande'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Remove tool</p></body></html></string> + </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="QToolButton" name="revertButton"> + <property name="toolTip"> + <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Lucida Grande'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Revert tool to preset</p></body></html></string> + </property> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> </item> <item> <widget class="QWidget" name="infoWidget" native="true"> @@ -61,7 +124,7 @@ <item row="1" column="1"> <widget class="Utils::PathChooser" name="executable"> <property name="expectedKind"> - <enum>Utils::PathChooser::ExistingCommand</enum> + <enum>Utils::PathChooser::Command</enum> </property> </widget> </item> @@ -83,7 +146,11 @@ </widget> </item> <item row="3" column="1"> - <widget class="Utils::PathChooser" name="workingDirectory"/> + <widget class="Utils::PathChooser" name="workingDirectory"> + <property name="expectedKind"> + <enum>Utils::PathChooser::Command</enum> + </property> + </widget> </item> <item row="4" column="0"> <widget class="QLabel" name="outputLabel"> @@ -193,6 +260,11 @@ p, li { white-space: pre-wrap; } <class>Utils::PathChooser</class> <extends>QWidget</extends> <header location="global">utils/pathchooser.h</header> + <container>1</container> + <slots> + <signal>editingFinished()</signal> + <signal>browsingFinished()</signal> + </slots> </customwidget> </customwidgets> <resources/> diff --git a/src/plugins/coreplugin/externaltool.cpp b/src/plugins/coreplugin/externaltool.cpp index dac798e2210305890b84d730d1138584b804a8c0..95e1bbf8972097fecb0956fda1e132104b13abb2 100644 --- a/src/plugins/coreplugin/externaltool.cpp +++ b/src/plugins/coreplugin/externaltool.cpp @@ -105,7 +105,7 @@ ExternalTool::ExternalTool(const ExternalTool *other) m_errorHandling(other->m_errorHandling), m_modifiesCurrentDocument(other->m_modifiesCurrentDocument), m_fileName(other->m_fileName), - m_presetFileName(other->m_presetFileName) + m_presetTool(other->m_presetTool) { } @@ -178,9 +178,9 @@ void ExternalTool::setFileName(const QString &fileName) m_fileName = fileName; } -void ExternalTool::setPresetFileName(const QString &fileName) +void ExternalTool::setPreset(QSharedPointer<ExternalTool> preset) { - m_presetFileName = fileName; + m_presetTool = preset; } QString ExternalTool::fileName() const @@ -188,9 +188,9 @@ QString ExternalTool::fileName() const return m_fileName; } -QString ExternalTool::presetFileName() const +QSharedPointer<ExternalTool> ExternalTool::preset() const { - return m_presetFileName; + return m_presetTool; } void ExternalTool::setDisplayName(const QString &name) @@ -394,7 +394,7 @@ ExternalTool * ExternalTool::createFromXml(const QByteArray &xml, QString *error return tool; } -ExternalTool * ExternalTool::createFromFile(const QString &fileName, QString *errorMessage, const QString &locale, bool isPreset) +ExternalTool * ExternalTool::createFromFile(const QString &fileName, QString *errorMessage, const QString &locale) { QFileInfo info(fileName); QFile file(info.absoluteFilePath()); @@ -410,9 +410,6 @@ ExternalTool * ExternalTool::createFromFile(const QString &fileName, QString *er return 0; } tool->m_fileName = file.fileName(); - if (isPreset) { - tool->setPresetFileName(file.fileName()); - } return tool; } @@ -468,6 +465,7 @@ bool ExternalTool::save(QString *errorMessage) const out.writeEndDocument(); file.close(); + return true; } bool ExternalTool::operator==(const ExternalTool &other) @@ -483,7 +481,8 @@ bool ExternalTool::operator==(const ExternalTool &other) && m_workingDirectory == other.m_workingDirectory && m_outputHandling == other.m_outputHandling && m_modifiesCurrentDocument == other.m_modifiesCurrentDocument - && m_errorHandling == other.m_errorHandling; + && m_errorHandling == other.m_errorHandling + && m_fileName == other.m_fileName; } // #pragma mark -- ExternalToolRunner @@ -690,21 +689,26 @@ void ExternalToolManager::parseDirectory(const QString &directory, foreach (const QFileInfo &info, dir.entryInfoList()) { const QString &fileName = info.absoluteFilePath(); QString error; - ExternalTool *tool = ExternalTool::createFromFile(fileName, &error, m_core->userInterfaceLanguage(), isPreset); + ExternalTool *tool = ExternalTool::createFromFile(fileName, &error, m_core->userInterfaceLanguage()); if (!tool) { qWarning() << tr("Error while parsing external tool %1: %2").arg(fileName, error); continue; } if (tools->contains(tool->id())) { if (isPreset) { + // preset that was changed ExternalTool *other = tools->value(tool->id()); - other->setPresetFileName(fileName); + other->setPreset(QSharedPointer<ExternalTool>(tool)); } else { qWarning() << tr("Error: External tool in %1 has duplicate id").arg(fileName); + delete tool; } - delete tool; continue; } + if (isPreset) { + // preset that wasn't changed --> save original values + tool->setPreset(QSharedPointer<ExternalTool>(new ExternalTool(tool))); + } tools->insert(tool->id(), tool); (*categoryMenus)[tool->displayCategory()].insert(tool->order(), tool); } diff --git a/src/plugins/coreplugin/externaltool.h b/src/plugins/coreplugin/externaltool.h index a51fe2ba319c35b027dfd665904735a5c2dbe04f..1fa13e929c4cf153556d4599b13995d2500b60fb 100644 --- a/src/plugins/coreplugin/externaltool.h +++ b/src/plugins/coreplugin/externaltool.h @@ -41,6 +41,7 @@ #include <QtCore/QString> #include <QtCore/QStringList> #include <QtCore/QProcess> +#include <QtCore/QSharedPointer> #include <QtCore/QTextCodec> namespace Core { @@ -76,18 +77,19 @@ public: QString workingDirectory() const; void setFileName(const QString &fileName); - void setPresetFileName(const QString &fileName); + void setPreset(QSharedPointer<ExternalTool> preset); QString fileName() const; - QString presetFileName() const; + // all tools that are preset (changed or unchanged) have the original value here: + QSharedPointer<ExternalTool> preset() const; static ExternalTool *createFromXml(const QByteArray &xml, QString *errorMessage = 0, const QString &locale = QString()); static ExternalTool *createFromFile(const QString &fileName, QString *errorMessage = 0, - const QString &locale = QString(), bool isPreset = false); + const QString &locale = QString()); bool save(QString *errorMessage = 0) const; - // ignores changed state bool operator==(const ExternalTool &other); + bool operator!=(const ExternalTool &other) { return !((*this) == other); } // display category and order are handled specially void setDisplayName(const QString &name); @@ -116,8 +118,7 @@ private: QString m_fileName; QString m_presetFileName; - - mutable bool m_isChanged; + QSharedPointer<ExternalTool> m_presetTool; }; class ExternalToolRunner : public QObject diff --git a/src/plugins/coreplugin/toolsettings.cpp b/src/plugins/coreplugin/toolsettings.cpp index d38a3352898d320f581942f26619f8dcf5e8ffc8..22ac4ee74c7dacf18de5560a3877ad9d45826edb 100644 --- a/src/plugins/coreplugin/toolsettings.cpp +++ b/src/plugins/coreplugin/toolsettings.cpp @@ -109,20 +109,38 @@ void ToolSettings::apply() if ((*originalTool) == (*tool)) { toolToAdd = originalTool; } else { - // save the new tool description and make it be added - if (!tool->presetFileName().isEmpty() && tool->fileName() == tool->presetFileName()) { - // we don't overwrite the preset, so give it a new file name in user resources - // TODO avoid overwriting a tool xml file of another existing tool? - const QString &fileName = QFileInfo(tool->presetFileName()).fileName(); - QDir resourceDir(ICore::instance()->userResourcePath()); - if (!resourceDir.exists(QLatin1String("externaltools"))) - resourceDir.mkpath(QLatin1String("externaltools")); - const QString &newFilePath = ICore::instance()->userResourcePath() - + QLatin1String("/externaltools/") + fileName; - tool->setFileName(newFilePath); + // case 1: tool is changed preset + if (tool->preset() && (*tool) != (*(tool->preset()))) { + // check if we need to choose a new file name + if (tool->preset()->fileName() == tool->fileName()) { + // TODO avoid overwriting a tool xml file of another existing tool? + const QString &fileName = QFileInfo(tool->preset()->fileName()).fileName(); + QDir resourceDir(ICore::instance()->userResourcePath()); + if (!resourceDir.exists(QLatin1String("externaltools"))) + resourceDir.mkpath(QLatin1String("externaltools")); + const QString &newFilePath = ICore::instance()->userResourcePath() + + QLatin1String("/externaltools/") + fileName; + tool->setFileName(newFilePath); + } + // TODO error handling + tool->save(); + // case 2: tool is previously changed preset but now same as preset + } else if (tool->preset() && (*tool) == (*(tool->preset()))) { + // check if we need to delete the changed description + if (originalTool->fileName() != tool->preset()->fileName() + && QFile::exists(originalTool->fileName())) { + // TODO error handling + QFile::remove(originalTool->fileName()); + } + tool->setFileName(tool->preset()->fileName()); + // no need to save, it's the same as the preset + // case 3: tool is custom tool + } else { + // TODO error handling + tool->save(); } - // TODO error handling - tool->save(); + + // 'tool' is deleted by config page, 'originalTool' is deleted by setToolsByCategory toolToAdd = new ExternalTool(tool); } }