Core: Apply new settings page pattern to Tool settings page

Since the code "belonging" to the widget was split across two
classes, but isn't now, a bit of moving was necessary.

Use the opportunity to remove now-unneeded undirections to the
model and ui members.

Change-Id: I25bb96de05c67d9116f28ae342d4aebd3c4419e6
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
hjk
2020-01-28 13:11:46 +01:00
parent 439bd2f090
commit 95623ae011
8 changed files with 322 additions and 457 deletions

View File

@@ -144,7 +144,6 @@ add_qtc_plugin(Core
systemsettings.cpp systemsettings.h systemsettings.ui systemsettings.cpp systemsettings.h systemsettings.ui
textdocument.cpp textdocument.h textdocument.cpp textdocument.h
themechooser.cpp themechooser.h themechooser.cpp themechooser.h
toolsettings.cpp toolsettings.h
variablechooser.cpp variablechooser.h variablechooser.cpp variablechooser.h
vcsmanager.cpp vcsmanager.h vcsmanager.cpp vcsmanager.h
versiondialog.cpp versiondialog.h versiondialog.cpp versiondialog.h

View File

@@ -88,7 +88,6 @@ SOURCES += corejsextensions.cpp \
externaltool.cpp \ externaltool.cpp \
dialogs/externaltoolconfig.cpp \ dialogs/externaltoolconfig.cpp \
dialogs/filepropertiesdialog.cpp \ dialogs/filepropertiesdialog.cpp \
toolsettings.cpp \
variablechooser.cpp \ variablechooser.cpp \
mimetypemagicdialog.cpp \ mimetypemagicdialog.cpp \
mimetypesettings.cpp \ mimetypesettings.cpp \
@@ -204,7 +203,6 @@ HEADERS += corejsextensions.h \
externaltool.h \ externaltool.h \
dialogs/externaltoolconfig.h \ dialogs/externaltoolconfig.h \
dialogs/filepropertiesdialog.h \ dialogs/filepropertiesdialog.h \
toolsettings.h \
variablechooser.h \ variablechooser.h \
mimetypemagicdialog.h \ mimetypemagicdialog.h \
mimetypesettings.h \ mimetypesettings.h \

View File

@@ -178,8 +178,6 @@ Project {
"textdocument.h", "textdocument.h",
"themechooser.cpp", "themechooser.cpp",
"themechooser.h", "themechooser.h",
"toolsettings.cpp",
"toolsettings.h",
"variablechooser.cpp", "variablechooser.cpp",
"variablechooser.h", "variablechooser.h",
"vcsmanager.cpp", "vcsmanager.cpp",

View File

@@ -24,6 +24,8 @@
****************************************************************************/ ****************************************************************************/
#include "externaltoolconfig.h" #include "externaltoolconfig.h"
#include "ioptionspage.h"
#include "ui_externaltoolconfig.h" #include "ui_externaltoolconfig.h"
#include <utils/algorithm.h> #include <utils/algorithm.h>
@@ -36,25 +38,69 @@
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>
#include <coreplugin/coreconstants.h> #include <coreplugin/coreconstants.h>
#include <coreplugin/externaltool.h>
#include <coreplugin/externaltoolmanager.h>
#include <coreplugin/icore.h>
#include <coreplugin/variablechooser.h> #include <coreplugin/variablechooser.h>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QDir>
#include <QFileInfo>
#include <QMenu> #include <QMenu>
#include <QMimeData> #include <QMimeData>
#include <QPlainTextEdit> #include <QPlainTextEdit>
#include <QTextStream> #include <QTextStream>
using namespace Core; using namespace Utils;
using namespace Core::Internal;
static const Qt::ItemFlags TOOLSMENU_ITEM_FLAGS = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDropEnabled; namespace Core {
static const Qt::ItemFlags CATEGORY_ITEM_FLAGS = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable; namespace Internal {
static const Qt::ItemFlags TOOL_ITEM_FLAGS = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsEditable;
ExternalToolModel::ExternalToolModel(QObject *parent) const Qt::ItemFlags TOOLSMENU_ITEM_FLAGS = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDropEnabled;
: QAbstractItemModel(parent) const Qt::ItemFlags CATEGORY_ITEM_FLAGS = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable;
const Qt::ItemFlags TOOL_ITEM_FLAGS = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsEditable;
class ExternalToolModel final : public QAbstractItemModel
{ {
} Q_DECLARE_TR_FUNCTIONS(Core::ExternalToolConfig)
public:
ExternalToolModel() = default;
~ExternalToolModel() final;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &modelIndex, int role = Qt::DisplayRole) const override;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &child) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
Qt::ItemFlags flags(const QModelIndex &modelIndex) const override;
bool setData(const QModelIndex &modelIndex, const QVariant &value, int role = Qt::EditRole) override;
QMimeData *mimeData(const QModelIndexList &indexes) const override;
bool dropMimeData(const QMimeData *data,
Qt::DropAction action,
int row,
int column,
const QModelIndex &parent) override;
QStringList mimeTypes() const override;
void setTools(const QMap<QString, QList<ExternalTool *> > &tools);
QMap<QString, QList<ExternalTool *> > tools() const { return m_tools; }
ExternalTool *toolForIndex(const QModelIndex &modelIndex) const;
QString categoryForIndex(const QModelIndex &modelIndex, bool *found) const;
void revertTool(const QModelIndex &modelIndex);
QModelIndex addCategory();
QModelIndex addTool(const QModelIndex &atIndex);
void removeTool(const QModelIndex &modelIndex);
Qt::DropActions supportedDropActions() const override { return Qt::MoveAction; }
private:
QVariant data(ExternalTool *tool, int role = Qt::DisplayRole) const;
QVariant data(const QString &category, int role = Qt::DisplayRole) const;
QMap<QString, QList<ExternalTool *> > m_tools;
};
ExternalToolModel::~ExternalToolModel() ExternalToolModel::~ExternalToolModel()
{ {
@@ -62,11 +108,6 @@ ExternalToolModel::~ExternalToolModel()
qDeleteAll(toolInCategory); qDeleteAll(toolInCategory);
} }
Qt::DropActions ExternalToolModel::supportedDropActions() const
{
return Qt::MoveAction;
}
int ExternalToolModel::columnCount(const QModelIndex &parent) const int ExternalToolModel::columnCount(const QModelIndex &parent) const
{ {
bool categoryFound; bool categoryFound;
@@ -273,11 +314,6 @@ void ExternalToolModel::setTools(const QMap<QString, QList<ExternalTool *> > &to
endResetModel(); endResetModel();
} }
QMap<QString, QList<ExternalTool *> > ExternalToolModel::tools() const
{
return m_tools;
}
ExternalTool *ExternalToolModel::toolForIndex(const QModelIndex &index) const ExternalTool *ExternalToolModel::toolForIndex(const QModelIndex &index) const
{ {
return static_cast<ExternalTool *>(index.internalPointer()); return static_cast<ExternalTool *>(index.internalPointer());
@@ -341,7 +377,7 @@ QModelIndex ExternalToolModel::addTool(const QModelIndex &atIndex)
tool->setDescription(tr("This tool prints a line of useful text")); tool->setDescription(tr("This tool prints a line of useful text"));
//: Sample external tool text //: Sample external tool text
const QString text = tr("Useful text"); const QString text = tr("Useful text");
if (Utils::HostOsInfo::isWindowsHost()) { if (HostOsInfo::isWindowsHost()) {
tool->setExecutables({"cmd"}); tool->setExecutables({"cmd"});
tool->setArguments("/c echo " + text); tool->setArguments("/c echo " + text);
} else { } else {
@@ -388,64 +424,93 @@ static void fillBaseEnvironmentComboBox(QComboBox *box)
{ {
box->clear(); box->clear();
box->addItem(ExternalTool::tr("System Environment"), QByteArray()); box->addItem(ExternalTool::tr("System Environment"), QByteArray());
for (const Utils::EnvironmentProvider &provider : Utils::EnvironmentProvider::providers()) for (const EnvironmentProvider &provider : EnvironmentProvider::providers())
box->addItem(provider.displayName, Id::fromName(provider.id).toSetting()); box->addItem(provider.displayName, Id::fromName(provider.id).toSetting());
} }
ExternalToolConfig::ExternalToolConfig() : class ExternalToolConfig final : public IOptionsPageWidget
ui(new Ui::ExternalToolConfig),
m_model(new ExternalToolModel(this))
{ {
ui->setupUi(this); Q_DECLARE_TR_FUNCTIONS(Core::ExternalToolConfig)
ui->executable->setExpectedKind(Utils::PathChooser::ExistingCommand);
ui->scrollArea->viewport()->setAutoFillBackground(false);
ui->scrollAreaWidgetContents->setAutoFillBackground(false);
ui->toolTree->setModel(m_model);
ui->toolTree->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed);
connect(ui->toolTree->selectionModel(), &QItemSelectionModel::currentChanged, public:
ExternalToolConfig();
void setTools(const QMap<QString, QList<ExternalTool *> > &tools);
QMap<QString, QList<ExternalTool *> > tools() const { return m_model.tools(); }
void apply() final;
private:
void handleCurrentChanged(const QModelIndex &now, const QModelIndex &previous);
void showInfoForItem(const QModelIndex &index);
void updateItem(const QModelIndex &index);
void revertCurrentItem();
void updateButtons(const QModelIndex &index);
void updateCurrentItem();
void addTool();
void removeTool();
void addCategory();
void updateEffectiveArguments();
void editEnvironmentChanges();
void updateEnvironmentLabel();
Ui::ExternalToolConfig m_ui;
EnvironmentItems m_environment;
ExternalToolModel m_model;
};
ExternalToolConfig::ExternalToolConfig()
{
m_ui.setupUi(this);
m_ui.executable->setExpectedKind(PathChooser::ExistingCommand);
m_ui.scrollArea->viewport()->setAutoFillBackground(false);
m_ui.scrollAreaWidgetContents->setAutoFillBackground(false);
m_ui.toolTree->setModel(&m_model);
m_ui.toolTree->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed);
connect(m_ui.toolTree->selectionModel(), &QItemSelectionModel::currentChanged,
this, &ExternalToolConfig::handleCurrentChanged); this, &ExternalToolConfig::handleCurrentChanged);
auto chooser = new VariableChooser(this); auto chooser = new VariableChooser(this);
chooser->addSupportedWidget(ui->executable->lineEdit()); chooser->addSupportedWidget(m_ui.executable->lineEdit());
chooser->addSupportedWidget(ui->arguments); chooser->addSupportedWidget(m_ui.arguments);
chooser->addSupportedWidget(ui->workingDirectory->lineEdit()); chooser->addSupportedWidget(m_ui.workingDirectory->lineEdit());
chooser->addSupportedWidget(ui->inputText); chooser->addSupportedWidget(m_ui.inputText);
fillBaseEnvironmentComboBox(ui->baseEnvironment); fillBaseEnvironmentComboBox(m_ui.baseEnvironment);
connect(ui->description, &QLineEdit::editingFinished, connect(m_ui.description, &QLineEdit::editingFinished,
this, &ExternalToolConfig::updateCurrentItem); this, &ExternalToolConfig::updateCurrentItem);
connect(ui->executable, &Utils::PathChooser::editingFinished, connect(m_ui.executable, &PathChooser::editingFinished,
this, &ExternalToolConfig::updateCurrentItem); this, &ExternalToolConfig::updateCurrentItem);
connect(ui->executable, &Utils::PathChooser::browsingFinished, connect(m_ui.executable, &PathChooser::browsingFinished,
this, &ExternalToolConfig::updateCurrentItem); this, &ExternalToolConfig::updateCurrentItem);
connect(ui->arguments, &QLineEdit::editingFinished, connect(m_ui.arguments, &QLineEdit::editingFinished,
this, &ExternalToolConfig::updateCurrentItem); this, &ExternalToolConfig::updateCurrentItem);
connect(ui->arguments, &QLineEdit::editingFinished, connect(m_ui.arguments, &QLineEdit::editingFinished,
this, &ExternalToolConfig::updateEffectiveArguments); this, &ExternalToolConfig::updateEffectiveArguments);
connect(ui->workingDirectory, &Utils::PathChooser::editingFinished, connect(m_ui.workingDirectory, &PathChooser::editingFinished,
this, &ExternalToolConfig::updateCurrentItem); this, &ExternalToolConfig::updateCurrentItem);
connect(ui->workingDirectory, &Utils::PathChooser::browsingFinished, connect(m_ui.workingDirectory, &PathChooser::browsingFinished,
this, &ExternalToolConfig::updateCurrentItem); this, &ExternalToolConfig::updateCurrentItem);
connect(ui->environmentButton, &QAbstractButton::clicked, connect(m_ui.environmentButton, &QAbstractButton::clicked,
this, &ExternalToolConfig::editEnvironmentChanges); this, &ExternalToolConfig::editEnvironmentChanges);
connect(ui->outputBehavior, QOverload<int>::of(&QComboBox::activated), connect(m_ui.outputBehavior, QOverload<int>::of(&QComboBox::activated),
this, &ExternalToolConfig::updateCurrentItem); this, &ExternalToolConfig::updateCurrentItem);
connect(ui->errorOutputBehavior, QOverload<int>::of(&QComboBox::activated), connect(m_ui.errorOutputBehavior, QOverload<int>::of(&QComboBox::activated),
this, &ExternalToolConfig::updateCurrentItem); this, &ExternalToolConfig::updateCurrentItem);
connect(ui->modifiesDocumentCheckbox, &QAbstractButton::clicked, connect(m_ui.modifiesDocumentCheckbox, &QAbstractButton::clicked,
this, &ExternalToolConfig::updateCurrentItem); this, &ExternalToolConfig::updateCurrentItem);
connect(ui->inputText, &QPlainTextEdit::textChanged, connect(m_ui.inputText, &QPlainTextEdit::textChanged,
this, &ExternalToolConfig::updateCurrentItem); this, &ExternalToolConfig::updateCurrentItem);
connect(ui->revertButton, &QAbstractButton::clicked, connect(m_ui.revertButton, &QAbstractButton::clicked,
this, &ExternalToolConfig::revertCurrentItem); this, &ExternalToolConfig::revertCurrentItem);
connect(ui->removeButton, &QAbstractButton::clicked, connect(m_ui.removeButton, &QAbstractButton::clicked,
this, &ExternalToolConfig::removeTool); this, &ExternalToolConfig::removeTool);
auto menu = new QMenu(ui->addButton); auto menu = new QMenu(m_ui.addButton);
ui->addButton->setMenu(menu); m_ui.addButton->setMenu(menu);
auto addTool = new QAction(tr("Add Tool"), this); auto addTool = new QAction(tr("Add Tool"), this);
menu->addAction(addTool); menu->addAction(addTool);
connect(addTool, &QAction::triggered, this, &ExternalToolConfig::addTool); connect(addTool, &QAction::triggered, this, &ExternalToolConfig::addTool);
@@ -454,11 +519,8 @@ ExternalToolConfig::ExternalToolConfig() :
connect(addCategory, &QAction::triggered, this, &ExternalToolConfig::addCategory); connect(addCategory, &QAction::triggered, this, &ExternalToolConfig::addCategory);
showInfoForItem(QModelIndex()); showInfoForItem(QModelIndex());
}
ExternalToolConfig::~ExternalToolConfig() setTools(ExternalToolManager::toolsByCategory());
{
delete ui;
} }
void ExternalToolConfig::setTools(const QMap<QString, QList<ExternalTool *> > &tools) void ExternalToolConfig::setTools(const QMap<QString, QList<ExternalTool *> > &tools)
@@ -472,8 +534,8 @@ void ExternalToolConfig::setTools(const QMap<QString, QList<ExternalTool *> > &t
} }
if (!toolsCopy.contains(QString())) if (!toolsCopy.contains(QString()))
toolsCopy.insert(QString(), QList<ExternalTool *>()); toolsCopy.insert(QString(), QList<ExternalTool *>());
m_model->setTools(toolsCopy); m_model.setTools(toolsCopy);
ui->toolTree->expandAll(); m_ui.toolTree->expandAll();
} }
void ExternalToolConfig::handleCurrentChanged(const QModelIndex &now, const QModelIndex &previous) void ExternalToolConfig::handleCurrentChanged(const QModelIndex &now, const QModelIndex &previous)
@@ -484,145 +546,265 @@ void ExternalToolConfig::handleCurrentChanged(const QModelIndex &now, const QMod
void ExternalToolConfig::updateButtons(const QModelIndex &index) void ExternalToolConfig::updateButtons(const QModelIndex &index)
{ {
ExternalTool *tool = m_model->toolForIndex(index); ExternalTool *tool = m_model.toolForIndex(index);
if (!tool) { if (!tool) {
ui->removeButton->setEnabled(false); m_ui.removeButton->setEnabled(false);
ui->revertButton->setEnabled(false); m_ui.revertButton->setEnabled(false);
return; return;
} }
if (!tool->preset()) { if (!tool->preset()) {
ui->removeButton->setEnabled(true); m_ui.removeButton->setEnabled(true);
ui->revertButton->setEnabled(false); m_ui.revertButton->setEnabled(false);
} else { } else {
ui->removeButton->setEnabled(false); m_ui.removeButton->setEnabled(false);
ui->revertButton->setEnabled((*tool) != (*(tool->preset()))); m_ui.revertButton->setEnabled((*tool) != (*(tool->preset())));
} }
} }
void ExternalToolConfig::updateCurrentItem() void ExternalToolConfig::updateCurrentItem()
{ {
QModelIndex index = ui->toolTree->selectionModel()->currentIndex(); const QModelIndex index = m_ui.toolTree->selectionModel()->currentIndex();
updateItem(index); updateItem(index);
updateButtons(index); updateButtons(index);
} }
void ExternalToolConfig::updateItem(const QModelIndex &index) void ExternalToolConfig::updateItem(const QModelIndex &index)
{ {
ExternalTool *tool = m_model->toolForIndex(index); ExternalTool *tool = m_model.toolForIndex(index);
if (!tool) if (!tool)
return; return;
tool->setDescription(ui->description->text()); tool->setDescription(m_ui.description->text());
QStringList executables = tool->executables(); QStringList executables = tool->executables();
if (executables.size() > 0) if (executables.size() > 0)
executables[0] = ui->executable->rawPath(); executables[0] = m_ui.executable->rawPath();
else else
executables << ui->executable->rawPath(); executables << m_ui.executable->rawPath();
tool->setExecutables(executables); tool->setExecutables(executables);
tool->setArguments(ui->arguments->text()); tool->setArguments(m_ui.arguments->text());
tool->setWorkingDirectory(ui->workingDirectory->rawPath()); tool->setWorkingDirectory(m_ui.workingDirectory->rawPath());
tool->setBaseEnvironmentProviderId(Id::fromSetting(ui->baseEnvironment->currentData())); tool->setBaseEnvironmentProviderId(Id::fromSetting(m_ui.baseEnvironment->currentData()));
tool->setEnvironmentUserChanges(m_environment); tool->setEnvironmentUserChanges(m_environment);
tool->setOutputHandling(ExternalTool::OutputHandling(ui->outputBehavior->currentIndex())); tool->setOutputHandling(ExternalTool::OutputHandling(m_ui.outputBehavior->currentIndex()));
tool->setErrorHandling(ExternalTool::OutputHandling(ui->errorOutputBehavior->currentIndex())); tool->setErrorHandling(ExternalTool::OutputHandling(m_ui.errorOutputBehavior->currentIndex()));
tool->setModifiesCurrentDocument(ui->modifiesDocumentCheckbox->checkState()); tool->setModifiesCurrentDocument(m_ui.modifiesDocumentCheckbox->checkState());
tool->setInput(ui->inputText->toPlainText()); tool->setInput(m_ui.inputText->toPlainText());
} }
void ExternalToolConfig::showInfoForItem(const QModelIndex &index) void ExternalToolConfig::showInfoForItem(const QModelIndex &index)
{ {
updateButtons(index); updateButtons(index);
ExternalTool *tool = m_model->toolForIndex(index); ExternalTool *tool = m_model.toolForIndex(index);
if (!tool) { if (!tool) {
ui->description->clear(); m_ui.description->clear();
ui->executable->setPath(QString()); m_ui.executable->setPath(QString());
ui->arguments->clear(); m_ui.arguments->clear();
ui->workingDirectory->setPath(QString()); m_ui.workingDirectory->setPath(QString());
ui->inputText->clear(); m_ui.inputText->clear();
ui->infoWidget->setEnabled(false); m_ui.infoWidget->setEnabled(false);
m_environment.clear(); m_environment.clear();
return; return;
} }
ui->infoWidget->setEnabled(true); m_ui.infoWidget->setEnabled(true);
ui->description->setText(tool->description()); m_ui.description->setText(tool->description());
ui->executable->setPath(tool->executables().isEmpty() ? QString() m_ui.executable->setPath(tool->executables().isEmpty() ? QString()
: tool->executables().constFirst()); : tool->executables().constFirst());
ui->arguments->setText(tool->arguments()); m_ui.arguments->setText(tool->arguments());
ui->workingDirectory->setPath(tool->workingDirectory()); m_ui.workingDirectory->setPath(tool->workingDirectory());
ui->outputBehavior->setCurrentIndex(int(tool->outputHandling())); m_ui.outputBehavior->setCurrentIndex(int(tool->outputHandling()));
ui->errorOutputBehavior->setCurrentIndex(int(tool->errorHandling())); m_ui.errorOutputBehavior->setCurrentIndex(int(tool->errorHandling()));
ui->modifiesDocumentCheckbox->setChecked(tool->modifiesCurrentDocument()); m_ui.modifiesDocumentCheckbox->setChecked(tool->modifiesCurrentDocument());
const int baseEnvironmentIndex = ui->baseEnvironment->findData( const int baseEnvironmentIndex = m_ui.baseEnvironment->findData(
tool->baseEnvironmentProviderId().toSetting()); tool->baseEnvironmentProviderId().toSetting());
ui->baseEnvironment->setCurrentIndex(std::max(0, baseEnvironmentIndex)); m_ui.baseEnvironment->setCurrentIndex(std::max(0, baseEnvironmentIndex));
m_environment = tool->environmentUserChanges(); m_environment = tool->environmentUserChanges();
{ {
QSignalBlocker blocker(ui->inputText); QSignalBlocker blocker(m_ui.inputText);
ui->inputText->setPlainText(tool->input()); m_ui.inputText->setPlainText(tool->input());
} }
ui->description->setCursorPosition(0); m_ui.description->setCursorPosition(0);
ui->arguments->setCursorPosition(0); m_ui.arguments->setCursorPosition(0);
updateEnvironmentLabel(); updateEnvironmentLabel();
updateEffectiveArguments(); updateEffectiveArguments();
} }
QMap<QString, QList<ExternalTool *> > ExternalToolConfig::tools() const static QString getUserFilePath(const QString &proposalFileName)
{ {
return m_model->tools(); const QDir resourceDir(ICore::userResourcePath());
if (!resourceDir.exists(QLatin1String("externaltools")))
resourceDir.mkpath(QLatin1String("externaltools"));
const QFileInfo fi(proposalFileName);
const QString &suffix = QLatin1Char('.') + fi.completeSuffix();
const QString &newFilePath = ICore::userResourcePath()
+ QLatin1String("/externaltools/") + fi.baseName();
int count = 0;
QString tryPath = newFilePath + suffix;
while (QFile::exists(tryPath)) {
if (++count > 15)
return QString();
// add random number
const int number = qrand() % 1000;
tryPath = newFilePath + QString::number(number) + suffix;
}
return tryPath;
}
static QString idFromDisplayName(const QString &displayName)
{
QString id = displayName;
id.remove(QRegExp(QLatin1String("&(?!&)")));
QChar *c = id.data();
while (!c->isNull()) {
if (!c->isLetterOrNumber())
*c = QLatin1Char('_');
++c;
}
return id;
}
static QString findUnusedId(const QString &proposal, const QMap<QString, QList<ExternalTool *> > &tools)
{
int number = 0;
QString result;
bool found = false;
do {
result = proposal + (number > 0 ? QString::number(number) : QString::fromLatin1(""));
++number;
found = false;
for (auto it = tools.cbegin(), end = tools.cend(); it != end; ++it) {
foreach (ExternalTool *tool, it.value()) {
if (tool->id() == result) {
found = true;
break;
}
}
}
} while (found);
return result;
} }
void ExternalToolConfig::apply() void ExternalToolConfig::apply()
{ {
QModelIndex index = ui->toolTree->selectionModel()->currentIndex(); QModelIndex index = m_ui.toolTree->selectionModel()->currentIndex();
updateItem(index); updateItem(index);
updateButtons(index); updateButtons(index);
QMap<QString, ExternalTool *> originalTools = ExternalToolManager::toolsById();
QMap<QString, QList<ExternalTool *> > newToolsMap = tools();
QMap<QString, QList<ExternalTool *> > resultMap;
for (auto it = newToolsMap.cbegin(), end = newToolsMap.cend(); it != end; ++it) {
QList<ExternalTool *> items;
foreach (ExternalTool *tool, it.value()) {
ExternalTool *toolToAdd = nullptr;
if (ExternalTool *originalTool = originalTools.take(tool->id())) {
// check if it has different category and is custom tool
if (tool->displayCategory() != it.key() && !tool->preset())
tool->setDisplayCategory(it.key());
// check if the tool has changed
if ((*originalTool) == (*tool)) {
toolToAdd = originalTool;
} else {
// 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()) {
const QString &fileName = FilePath::fromString(tool->preset()->fileName()).fileName();
const QString &newFilePath = getUserFilePath(fileName);
// TODO error handling if newFilePath.isEmpty() (i.e. failed to find a unused name)
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();
}
// 'tool' is deleted by config page, 'originalTool' is deleted by setToolsByCategory
toolToAdd = new ExternalTool(tool);
}
} else {
// new tool. 'tool' is deleted by config page
QString id = idFromDisplayName(tool->displayName());
id = findUnusedId(id, newToolsMap);
tool->setId(id);
// TODO error handling if newFilePath.isEmpty() (i.e. failed to find a unused name)
tool->setFileName(getUserFilePath(id + QLatin1String(".xml")));
// TODO error handling
tool->save();
toolToAdd = new ExternalTool(tool);
}
items.append(toolToAdd);
}
if (!items.isEmpty())
resultMap.insert(it.key(), items);
}
// Remove tools that have been deleted from the settings (and are no preset)
foreach (ExternalTool *tool, originalTools) {
QTC_ASSERT(!tool->preset(), continue);
// TODO error handling
QFile::remove(tool->fileName());
}
ExternalToolManager::setToolsByCategory(resultMap);
} }
void ExternalToolConfig::revertCurrentItem() void ExternalToolConfig::revertCurrentItem()
{ {
QModelIndex index = ui->toolTree->selectionModel()->currentIndex(); QModelIndex index = m_ui.toolTree->selectionModel()->currentIndex();
m_model->revertTool(index); m_model.revertTool(index);
showInfoForItem(index); showInfoForItem(index);
} }
void ExternalToolConfig::addTool() void ExternalToolConfig::addTool()
{ {
QModelIndex currentIndex = ui->toolTree->selectionModel()->currentIndex(); QModelIndex currentIndex = m_ui.toolTree->selectionModel()->currentIndex();
if (!currentIndex.isValid()) // default to Uncategorized if (!currentIndex.isValid()) // default to Uncategorized
currentIndex = m_model->index(0, 0); currentIndex = m_model.index(0, 0);
QModelIndex index = m_model->addTool(currentIndex); QModelIndex index = m_model.addTool(currentIndex);
ui->toolTree->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Clear); m_ui.toolTree->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Clear);
ui->toolTree->selectionModel()->setCurrentIndex(index, QItemSelectionModel::SelectCurrent); m_ui.toolTree->selectionModel()->setCurrentIndex(index, QItemSelectionModel::SelectCurrent);
ui->toolTree->edit(index); m_ui.toolTree->edit(index);
} }
void ExternalToolConfig::removeTool() void ExternalToolConfig::removeTool()
{ {
QModelIndex currentIndex = ui->toolTree->selectionModel()->currentIndex(); QModelIndex currentIndex = m_ui.toolTree->selectionModel()->currentIndex();
ui->toolTree->selectionModel()->setCurrentIndex(QModelIndex(), QItemSelectionModel::Clear); m_ui.toolTree->selectionModel()->setCurrentIndex(QModelIndex(), QItemSelectionModel::Clear);
m_model->removeTool(currentIndex); m_model.removeTool(currentIndex);
} }
void ExternalToolConfig::addCategory() void ExternalToolConfig::addCategory()
{ {
QModelIndex index = m_model->addCategory(); QModelIndex index = m_model.addCategory();
ui->toolTree->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Clear); m_ui.toolTree->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Clear);
ui->toolTree->selectionModel()->setCurrentIndex(index, QItemSelectionModel::SelectCurrent); m_ui.toolTree->selectionModel()->setCurrentIndex(index, QItemSelectionModel::SelectCurrent);
ui->toolTree->edit(index); m_ui.toolTree->edit(index);
} }
void ExternalToolConfig::updateEffectiveArguments() void ExternalToolConfig::updateEffectiveArguments()
{ {
ui->arguments->setToolTip(Utils::globalMacroExpander()->expandProcessArgs(ui->arguments->text())); m_ui.arguments->setToolTip(Utils::globalMacroExpander()->expandProcessArgs(m_ui.arguments->text()));
} }
void ExternalToolConfig::editEnvironmentChanges() void ExternalToolConfig::editEnvironmentChanges()
{ {
const QString placeholderText = Utils::HostOsInfo::isWindowsHost() const QString placeholderText = HostOsInfo::isWindowsHost()
? tr("PATH=C:\\dev\\bin;${PATH}") ? tr("PATH=C:\\dev\\bin;${PATH}")
: tr("PATH=/opt/bin:${PATH}"); : tr("PATH=/opt/bin:${PATH}");
const auto newItems = Utils::EnvironmentDialog::getEnvironmentItems(ui->environmentLabel, const auto newItems = EnvironmentDialog::getEnvironmentItems(m_ui.environmentLabel,
m_environment, m_environment,
placeholderText); placeholderText);
if (newItems) { if (newItems) {
@@ -633,8 +815,21 @@ void ExternalToolConfig::editEnvironmentChanges()
void ExternalToolConfig::updateEnvironmentLabel() void ExternalToolConfig::updateEnvironmentLabel()
{ {
QString shortSummary = Utils::EnvironmentItem::toStringList(m_environment).join("; "); QString shortSummary = EnvironmentItem::toStringList(m_environment).join("; ");
QFontMetrics fm(ui->environmentLabel->font()); QFontMetrics fm(m_ui.environmentLabel->font());
shortSummary = fm.elidedText(shortSummary, Qt::ElideRight, ui->environmentLabel->width()); shortSummary = fm.elidedText(shortSummary, Qt::ElideRight, m_ui.environmentLabel->width());
ui->environmentLabel->setText(shortSummary.isEmpty() ? tr("No changes to apply.") : shortSummary); m_ui.environmentLabel->setText(shortSummary.isEmpty() ? tr("No changes to apply.") : shortSummary);
} }
// ToolSettingsPage
ToolSettings::ToolSettings()
{
setId(Constants::SETTINGS_ID_TOOLS);
setDisplayName(ExternalToolConfig::tr("External Tools"));
setCategory(Constants::SETTINGS_CATEGORY_CORE);
setWidgetCreator([] { return new ExternalToolConfig; });
}
} // Internal
} // Core

View File

@@ -25,92 +25,16 @@
#pragma once #pragma once
#include "../externaltool.h" #include "ioptionspage.h"
#include <utils/environmentfwd.h>
#include <QAbstractItemModel>
#include <QDialog>
#include <QWidget>
QT_FORWARD_DECLARE_CLASS(QPlainTextEdit)
namespace Core { namespace Core {
namespace Internal { namespace Internal {
namespace Ui { class ExternalToolConfig; } class ToolSettings final : public IOptionsPage
class ExternalToolModel : public QAbstractItemModel
{ {
Q_OBJECT
public: public:
explicit ExternalToolModel(QObject *parent); ToolSettings();
~ExternalToolModel() override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &modelIndex, int role = Qt::DisplayRole) const override;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &child) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
Qt::ItemFlags flags(const QModelIndex &modelIndex) const override;
bool setData(const QModelIndex &modelIndex, const QVariant &value, int role = Qt::EditRole) override;
QMimeData *mimeData(const QModelIndexList &indexes) const override;
bool dropMimeData(const QMimeData *data,
Qt::DropAction action,
int row,
int column,
const QModelIndex &parent) override;
QStringList mimeTypes() const override;
void setTools(const QMap<QString, QList<ExternalTool *> > &tools);
QMap<QString, QList<ExternalTool *> > tools() const;
ExternalTool *toolForIndex(const QModelIndex &modelIndex) const;
QString categoryForIndex(const QModelIndex &modelIndex, bool *found) const;
void revertTool(const QModelIndex &modelIndex);
QModelIndex addCategory();
QModelIndex addTool(const QModelIndex &atIndex);
void removeTool(const QModelIndex &modelIndex);
Qt::DropActions supportedDropActions() const override;
private:
QVariant data(ExternalTool *tool, int role = Qt::DisplayRole) const;
QVariant data(const QString &category, int role = Qt::DisplayRole) const;
QMap<QString, QList<ExternalTool *> > m_tools;
};
class ExternalToolConfig : public QWidget
{
Q_OBJECT
public:
ExternalToolConfig();
~ExternalToolConfig() override;
void setTools(const QMap<QString, QList<ExternalTool *> > &tools);
QMap<QString, QList<ExternalTool *> > tools() const;
void apply();
private:
void handleCurrentChanged(const QModelIndex &now, const QModelIndex &previous);
void showInfoForItem(const QModelIndex &index);
void updateItem(const QModelIndex &index);
void revertCurrentItem();
void updateButtons(const QModelIndex &index);
void updateCurrentItem();
void addTool();
void removeTool();
void addCategory();
void updateEffectiveArguments();
void editEnvironmentChanges();
void updateEnvironmentLabel();
Ui::ExternalToolConfig *ui;
Utils::EnvironmentItems m_environment;
ExternalToolModel *m_model;
}; };
} // Internal } // Internal
} // namespace Core } // Core

View File

@@ -27,7 +27,6 @@
#include "icore.h" #include "icore.h"
#include "jsexpander.h" #include "jsexpander.h"
#include "toolsettings.h"
#include "mimetypesettings.h" #include "mimetypesettings.h"
#include "fancytabwidget.h" #include "fancytabwidget.h"
#include "documentmanager.h" #include "documentmanager.h"
@@ -56,6 +55,7 @@
#include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actionmanager_p.h> #include <coreplugin/actionmanager/actionmanager_p.h>
#include <coreplugin/actionmanager/command.h> #include <coreplugin/actionmanager/command.h>
#include <coreplugin/dialogs/externaltoolconfig.h>
#include <coreplugin/dialogs/newdialog.h> #include <coreplugin/dialogs/newdialog.h>
#include <coreplugin/dialogs/shortcutsettings.h> #include <coreplugin/dialogs/shortcutsettings.h>
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>

View File

@@ -1,196 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "toolsettings.h"
#include "dialogs/externaltoolconfig.h"
#include "externaltool.h"
#include "externaltoolmanager.h"
#include "coreconstants.h"
#include "icore.h"
#include <utils/qtcassert.h>
#include <QCoreApplication>
#include <QFileInfo>
#include <QDir>
#include <QRegExp>
#include <QDebug>
using namespace Core;
using namespace Core::Internal;
ToolSettings::ToolSettings()
{
setId(Constants::SETTINGS_ID_TOOLS);
setDisplayName(tr("External Tools"));
setCategory(Constants::SETTINGS_CATEGORY_CORE);
}
QWidget *ToolSettings::widget()
{
if (!m_widget) {
m_widget = new ExternalToolConfig;
m_widget->setTools(ExternalToolManager::toolsByCategory());
}
return m_widget;
}
static QString getUserFilePath(const QString &proposalFileName)
{
const QDir resourceDir(ICore::userResourcePath());
if (!resourceDir.exists(QLatin1String("externaltools")))
resourceDir.mkpath(QLatin1String("externaltools"));
const QFileInfo fi(proposalFileName);
const QString &suffix = QLatin1Char('.') + fi.completeSuffix();
const QString &newFilePath = ICore::userResourcePath()
+ QLatin1String("/externaltools/") + fi.baseName();
int count = 0;
QString tryPath = newFilePath + suffix;
while (QFile::exists(tryPath)) {
if (++count > 15)
return QString();
// add random number
const int number = qrand() % 1000;
tryPath = newFilePath + QString::number(number) + suffix;
}
return tryPath;
}
static QString idFromDisplayName(const QString &displayName)
{
QString id = displayName;
id.remove(QRegExp(QLatin1String("&(?!&)")));
QChar *c = id.data();
while (!c->isNull()) {
if (!c->isLetterOrNumber())
*c = QLatin1Char('_');
++c;
}
return id;
}
static QString findUnusedId(const QString &proposal, const QMap<QString, QList<ExternalTool *> > &tools)
{
int number = 0;
QString result;
bool found = false;
do {
result = proposal + (number > 0 ? QString::number(number) : QString::fromLatin1(""));
++number;
found = false;
for (auto it = tools.cbegin(), end = tools.cend(); it != end; ++it) {
foreach (ExternalTool *tool, it.value()) {
if (tool->id() == result) {
found = true;
break;
}
}
}
} while (found);
return result;
}
void ToolSettings::apply()
{
if (!m_widget)
return;
m_widget->apply();
QMap<QString, ExternalTool *> originalTools = ExternalToolManager::toolsById();
QMap<QString, QList<ExternalTool *> > newToolsMap = m_widget->tools();
QMap<QString, QList<ExternalTool *> > resultMap;
for (auto it = newToolsMap.cbegin(), end = newToolsMap.cend(); it != end; ++it) {
QList<ExternalTool *> items;
foreach (ExternalTool *tool, it.value()) {
ExternalTool *toolToAdd = nullptr;
if (ExternalTool *originalTool = originalTools.take(tool->id())) {
// check if it has different category and is custom tool
if (tool->displayCategory() != it.key() && !tool->preset())
tool->setDisplayCategory(it.key());
// check if the tool has changed
if ((*originalTool) == (*tool)) {
toolToAdd = originalTool;
} else {
// 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()) {
const QString &fileName = Utils::FilePath::fromString(tool->preset()->fileName()).fileName();
const QString &newFilePath = getUserFilePath(fileName);
// TODO error handling if newFilePath.isEmpty() (i.e. failed to find a unused name)
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();
}
// 'tool' is deleted by config page, 'originalTool' is deleted by setToolsByCategory
toolToAdd = new ExternalTool(tool);
}
} else {
// new tool. 'tool' is deleted by config page
QString id = idFromDisplayName(tool->displayName());
id = findUnusedId(id, newToolsMap);
tool->setId(id);
// TODO error handling if newFilePath.isEmpty() (i.e. failed to find a unused name)
tool->setFileName(getUserFilePath(id + QLatin1String(".xml")));
// TODO error handling
tool->save();
toolToAdd = new ExternalTool(tool);
}
items.append(toolToAdd);
}
if (!items.isEmpty())
resultMap.insert(it.key(), items);
}
// Remove tools that have been deleted from the settings (and are no preset)
foreach (ExternalTool *tool, originalTools) {
QTC_ASSERT(!tool->preset(), continue);
// TODO error handling
QFile::remove(tool->fileName());
}
ExternalToolManager::setToolsByCategory(resultMap);
}
void ToolSettings::finish()
{
delete m_widget;
}

View File

@@ -1,53 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <coreplugin/dialogs/ioptionspage.h>
#include <QPointer>
namespace Core {
namespace Internal {
class ExternalToolConfig;
class ToolSettings : public IOptionsPage
{
Q_OBJECT
public:
ToolSettings();
QWidget *widget() override;
void apply() override;
void finish() override;
private:
QPointer<ExternalToolConfig> m_widget;
};
} // namespace Internal
} // namespace Core