Skip to content

Commit

Permalink
Allow setting working directory (#1580)
Browse files Browse the repository at this point in the history
Also separated arguments and executable and added %executablepath variable
  • Loading branch information
ketanhwr authored and bjorn committed Jun 3, 2017
1 parent 925b7ca commit f59b10c
Show file tree
Hide file tree
Showing 7 changed files with 189 additions and 48 deletions.
69 changes: 53 additions & 16 deletions src/tiled/command.cpp
Expand Up @@ -30,39 +30,64 @@
using namespace Tiled;
using namespace Tiled::Internal;

QString Command::finalWorkingDirectory() const
{
QString finalWorkingDirectory = workingDirectory;

finalWorkingDirectory = replaceVariables(finalWorkingDirectory, false);

QString finalExecutable = replaceVariables(executable);
QFileInfo mFile(finalExecutable);

finalWorkingDirectory.replace(QLatin1String("%executablepath"), mFile.absolutePath());

return finalWorkingDirectory;
}

QString Command::finalCommand() const
{
QString finalCommand = command;
QString finalCommand = QString(QLatin1String("%1 %2")).arg(executable, arguments);

return replaceVariables(finalCommand);
}

QString Command::replaceVariables(const QString &string, bool quoteValues) const
{
QString finalString = string;

QString replaceString = (quoteValues) ? QString(QLatin1String("\"%1\"")) :
QString(QLatin1String("%1"));

// Perform variable replacement
if (Document *document = DocumentManager::instance()->currentDocument()) {
const QString fileName = document->fileName();

finalCommand.replace(QLatin1String("%mapfile"),
QString(QLatin1String("\"%1\"")).arg(fileName));
finalString.replace(QLatin1String("%mapfile"),
replaceString.arg(fileName));

QFileInfo fileInfo(fileName);
QString mapPath = fileInfo.absolutePath();
finalCommand.replace(

finalString.replace(
QLatin1String("%mappath"),
QString(QLatin1String("\"%1\"")).arg(mapPath));
replaceString.arg(mapPath));

if (MapDocument *mapDocument = qobject_cast<MapDocument*>(document)) {
if (const Layer *layer = mapDocument->currentLayer()) {
finalCommand.replace(QLatin1String("%layername"),
QString(QLatin1String("\"%1\"")).arg(layer->name()));
finalString.replace(QLatin1String("%layername"),
replaceString.arg(layer->name()));
}
}

if (MapObject *currentObject = dynamic_cast<MapObject *>(document->currentObject())) {
finalCommand.replace(QLatin1String("%objecttype"),
QString(QLatin1String("\"%1\"")).arg(currentObject->type()));
finalCommand.replace(QLatin1String("%objectid"),
QString(QLatin1String("\"%1\"")).arg(currentObject->id()));
finalString.replace(QLatin1String("%objecttype"),
replaceString.arg(currentObject->type()));
finalString.replace(QLatin1String("%objectid"),
replaceString.arg(currentObject->id()));
}
}

return finalCommand;
return finalString;
}

void Command::execute(bool inTerminal) const
Expand All @@ -82,7 +107,9 @@ QVariant Command::toQVariant() const
QHash<QString, QVariant> hash;
hash[QLatin1String("Enabled")] = isEnabled;
hash[QLatin1String("Name")] = name;
hash[QLatin1String("Command")] = command;
hash[QLatin1String("Command")] = executable;
hash[QLatin1String("Arguments")] = arguments;
hash[QLatin1String("WorkingDirectory")] = workingDirectory;
hash[QLatin1String("Shortcut")] = shortcut;
hash[QLatin1String("SaveBeforeExecute")] = saveBeforeExecute;
return hash;
Expand All @@ -93,7 +120,9 @@ Command Command::fromQVariant(const QVariant &variant)
const QHash<QString, QVariant> hash = variant.toHash();

const QString namePref = QLatin1String("Name");
const QString commandPref = QLatin1String("Command");
const QString executablePref = QLatin1String("Command");
const QString argumentsPref = QLatin1String("Arguments");
const QString workingDirectoryPref = QLatin1String("WorkingDirectory");
const QString enablePref = QLatin1String("Enabled");
const QString shortcutPref = QLatin1String("Shortcut");
const QString saveBeforeExecutePref = QLatin1String("SaveBeforeExecute");
Expand All @@ -103,8 +132,12 @@ Command Command::fromQVariant(const QVariant &variant)
command.isEnabled = hash[enablePref].toBool();
if (hash.contains(namePref))
command.name = hash[namePref].toString();
if (hash.contains(commandPref))
command.command = hash[commandPref].toString();
if (hash.contains(executablePref))
command.executable = hash[executablePref].toString();
if (hash.contains(argumentsPref))
command.arguments = hash[argumentsPref].toString();
if (hash.contains(workingDirectoryPref))
command.workingDirectory = hash[workingDirectoryPref].toString();
if (hash.contains(shortcutPref))
command.shortcut = hash[shortcutPref].value<QKeySequence>();
if (hash.contains(saveBeforeExecutePref))
Expand All @@ -117,6 +150,7 @@ CommandProcess::CommandProcess(const Command &command, bool inTerminal)
: QProcess(DocumentManager::instance())
, mName(command.name)
, mFinalCommand(command.finalCommand())
, mFinalWorkingDirectory(command.finalWorkingDirectory())
#ifdef Q_OS_MAC
, mFile(QDir::tempPath() + QLatin1String("/tiledXXXXXX.command"))
#endif
Expand Down Expand Up @@ -175,6 +209,9 @@ CommandProcess::CommandProcess(const Command &command, bool inTerminal)

connect(this, SIGNAL(finished(int)), SLOT(deleteLater()));

if (!mFinalWorkingDirectory.trimmed().isEmpty())
setWorkingDirectory(mFinalWorkingDirectory);

start(mFinalCommand);
}

Expand Down
17 changes: 14 additions & 3 deletions src/tiled/command.h
Expand Up @@ -36,18 +36,24 @@ struct Command
{
Command(bool isEnabled = true,
QString name = QString(),
QString command = QString(),
QString executable = QString(),
QString arguments = QString(),
QString workingDirectory = QString(),
QKeySequence shortcut = QKeySequence(),
bool saveBeforeExecute = true)
: isEnabled(isEnabled)
, name(std::move(name))
, command(std::move(command))
, executable(std::move(executable))
, arguments(std::move(arguments))
, workingDirectory(std::move(workingDirectory))
, shortcut(shortcut)
, saveBeforeExecute(saveBeforeExecute) {}

bool isEnabled;
QString name;
QString command;
QString executable;
QString arguments;
QString workingDirectory;
QKeySequence shortcut;
bool saveBeforeExecute;

Expand All @@ -56,6 +62,10 @@ struct Command
*/
QString finalCommand() const;

QString finalWorkingDirectory() const;

QString replaceVariables(const QString &string, bool quoteValues = true) const;

/**
* Executes the command in the operating system shell or terminal
* application.
Expand Down Expand Up @@ -88,6 +98,7 @@ private slots:

QString mName;
QString mFinalCommand;
QString mFinalWorkingDirectory;

#ifdef Q_OS_MAC
QTemporaryFile mFile;
Expand Down
30 changes: 24 additions & 6 deletions src/tiled/commanddatamodel.cpp
Expand Up @@ -49,11 +49,13 @@ CommandDataModel::CommandDataModel(QObject *parent)
// warning when clicking the command button for the first time
Command command(false);
#ifdef Q_OS_LINUX
command.command = QLatin1String("gedit %mapfile");
command.executable = QLatin1String("gedit");
command.arguments = QLatin1String("%mapfile");
#elif defined(Q_OS_MAC)
command.command = QLatin1String("open -t %mapfile");
command.executable = QLatin1String("open");
command.arguments = QLatin1String("-t %mapfile");
#endif
if (!command.command.isEmpty()) {
if (!command.executable.isEmpty()) {
command.name = tr("Open in text editor");
mCommands.push_back(command);
}
Expand Down Expand Up @@ -400,7 +402,7 @@ bool CommandDataModel::dropMimeData(const QMimeData *data, Qt::DropAction, int,
if (dstRow == mCommands.size()) {
append(Command(addr->isEnabled,
tr("%1 (copy)").arg(addr->name),
addr->command));
addr->executable, addr->arguments));
return true;
}
}
Expand All @@ -423,12 +425,28 @@ bool CommandDataModel::dropMimeData(const QMimeData *data, Qt::DropAction, int,
return false;
}

void CommandDataModel::setCommand(const QModelIndex &index, const QString &value)
void CommandDataModel::setExecutable(const QModelIndex &index, const QString &value)
{
const bool isNormalRow = index.row() < mCommands.size();

if (isNormalRow)
mCommands[index.row()].command = value;
mCommands[index.row()].executable = value;
}

void CommandDataModel::setArguments(const QModelIndex &index, const QString &value)
{
const bool isNormalRow = index.row() < mCommands.size();

if (isNormalRow)
mCommands[index.row()].arguments = value;
}

void CommandDataModel::setWorkingDirectory(const QModelIndex &index, const QString &value)
{
const bool isNormalRow = index.row() < mCommands.size();

if (isNormalRow)
mCommands[index.row()].workingDirectory = value;
}

void CommandDataModel::setShortcut(const QModelIndex &index, const QKeySequence &value)
Expand Down
4 changes: 3 additions & 1 deletion src/tiled/commanddatamodel.h
Expand Up @@ -127,7 +127,9 @@ class CommandDataModel : public QAbstractTableModel
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row,
int column, const QModelIndex &parent) override;

void setCommand(const QModelIndex &index, const QString &value);
void setExecutable(const QModelIndex &index, const QString &value);
void setArguments(const QModelIndex &index, const QString &value);
void setWorkingDirectory(const QModelIndex &index, const QString &value);
void setShortcut(const QModelIndex &index, const QKeySequence &value);
void setSaveBeforeExecute(const QModelIndex &index, bool value);

Expand Down
64 changes: 52 additions & 12 deletions src/tiled/commanddialog.cpp
Expand Up @@ -52,14 +52,23 @@ CommandDialog::CommandDialog(QWidget *parent)
connect(mUi->keySequenceEdit, &QKeySequenceEdit::keySequenceChanged,
this, &CommandDialog::setShortcut);

connect(mUi->commandEdit, &QLineEdit::textChanged,
this, &CommandDialog::setCommand);
connect(mUi->executableEdit, &QLineEdit::textChanged,
this, &CommandDialog::setExecutable);

connect(mUi->argumentsEdit, &QLineEdit::textChanged,
this, &CommandDialog::setArguments);

connect(mUi->workingDirectoryEdit, &QLineEdit::textChanged,
this, &CommandDialog::setWorkingDirectory);

connect(mUi->treeView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &CommandDialog::updateWidgets);

connect(mUi->browseButton, &QPushButton::clicked,
this, &CommandDialog::openFileDialog);
connect(mUi->exBrowseButton, &QPushButton::clicked,
this, &CommandDialog::browseExecutable);

connect(mUi->wdBrowseButton, &QPushButton::clicked,
this, &CommandDialog::browseWorkingDirectory);
}

CommandDialog::~CommandDialog()
Expand Down Expand Up @@ -91,43 +100,74 @@ void CommandDialog::setSaveBeforeExecute(int state)
mUi->treeView->model()->setSaveBeforeExecute(current, state);
}

void CommandDialog::setCommand(const QString &text)
void CommandDialog::setExecutable(const QString &text)
{
const QModelIndex &current = mUi->treeView->currentIndex();
if (current.row() < mUi->treeView->model()->rowCount())
mUi->treeView->model()->setCommand(current, text);
mUi->treeView->model()->setExecutable(current, text);
}

void CommandDialog::setArguments(const QString &text)
{
const QModelIndex &current = mUi->treeView->currentIndex();
if (current.row() < mUi->treeView->model()->rowCount())
mUi->treeView->model()->setArguments(current, text);
}

void CommandDialog::setWorkingDirectory(const QString &text)
{
const QModelIndex &current = mUi->treeView->currentIndex();
if (current.row() < mUi->treeView->model()->rowCount())
mUi->treeView->model()->setWorkingDirectory(current, text);
}

void CommandDialog::updateWidgets(const QModelIndex &current, const QModelIndex &)
{
bool enable = (current.row() < mUi->treeView->model()->rowCount() - 1);

mUi->saveBox->setEnabled(enable);
mUi->commandEdit->setEnabled(enable);
mUi->browseButton->setEnabled(enable);
mUi->executableEdit->setEnabled(enable);
mUi->argumentsEdit->setEnabled(enable);
mUi->workingDirectoryEdit->setEnabled(enable);
mUi->exBrowseButton->setEnabled(enable);
mUi->keySequenceEdit->setEnabled(enable);
mUi->clearButton->setEnabled(enable);
mUi->saveBox->setEnabled(enable);

if (enable) {
const Command command = mUi->treeView->model()->command(current);
mUi->commandEdit->setText(command.command);
mUi->executableEdit->setText(command.executable);
mUi->argumentsEdit->setText(command.arguments);
mUi->workingDirectoryEdit->setText(command.workingDirectory);
mUi->keySequenceEdit->setKeySequence(command.shortcut);
mUi->saveBox->setChecked(command.saveBeforeExecute);
} else {
mUi->commandEdit->clear();
mUi->executableEdit->clear();
mUi->argumentsEdit->clear();
mUi->workingDirectoryEdit->clear();
mUi->keySequenceEdit->clear();
}
}

void CommandDialog::openFileDialog()
void CommandDialog::browseExecutable()
{
QString caption = tr("Select Executable");
QString dir = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation);
QString executableName = QFileDialog::getOpenFileName(this, caption, dir);

if (!executableName.isEmpty())
mUi->commandEdit->setText(executableName);
mUi->executableEdit->setText(executableName);
}

void CommandDialog::browseWorkingDirectory()
{
QString caption = tr("Select Working Directory");
QString dir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
QString workingDirectoryName = QFileDialog::getExistingDirectory(this, caption, dir,
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);

if (!workingDirectoryName.isEmpty())
mUi->workingDirectoryEdit->setText(workingDirectoryName);
}

CommandTreeView::CommandTreeView(QWidget *parent)
Expand Down
10 changes: 8 additions & 2 deletions src/tiled/commanddialog.h
Expand Up @@ -51,11 +51,17 @@ public slots:

void setSaveBeforeExecute(int state);

void setCommand(const QString &text);
void setExecutable(const QString &text);

void setArguments(const QString &text);

void setWorkingDirectory(const QString &text);

void updateWidgets(const QModelIndex &current, const QModelIndex&);

void openFileDialog();
void browseExecutable();

void browseWorkingDirectory();

private:
Ui::CommandDialog *mUi;
Expand Down

0 comments on commit f59b10c

Please sign in to comment.