Skip to content

Commit

Permalink
Add file open / save prompts in scripting API (#3782)
Browse files Browse the repository at this point in the history
Closes #3537

Co-authored-by: Thorbjørn Lindeijer <bjorn@lindeijer.nl>
  • Loading branch information
dogboydog and bjorn committed Jul 29, 2023
1 parent 2613ed6 commit 17a56ff
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 7 deletions.
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Removed Space and Ctrl+Space shortcuts from Layers view to avoid conflict with panning (#3672)
* Display the image base name for unnamed tile objects referring to single images
* Scripting: Added API for editing tile layers using terrain sets (with a-morphous, #3758)
* Scripting: Added file dialog API (with dogboydog, #3782)
* Scripting: Support erasing tiles in Tool.preview and TileMap.merge
* Scripting: Added WangSet.effectiveTypeForColor
* Fixed crash when changing file property of custom class (#3783)
Expand Down
57 changes: 50 additions & 7 deletions docs/scripting-doc/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,19 @@ interface size {
*/
type Polygon = point[];

/**
* A string used to show only certain types of files when prompting the user to select a file path.
*
* Used in {@link FileEdit} and in {@link tiled.promptOpenFile} and related methods.
* The filter is given in a format like `"Images (*.png *.xpm *.jpg)"`.
*
* If you want multiple filters, separate them with ';;', for example:
* ```
* "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
* ```
*/
type FileFilter = string;

/**
* The value of a property of type 'object', which refers to a
* {@link MapObject} by its ID.
Expand Down Expand Up @@ -3924,6 +3937,42 @@ declare namespace tiled {
*/
export function prompt(label: string, text?: string, title?: string): string;

/**
* Shows a dialog which asks the user to choose an existing directory.
* Optionally override the starting directory of the dialog or its title.
*
* Returns the absolute path of the chosen directory, or an empty string if the user cancels the dialog.
*/
export function promptDirectory(defaultDir?: string, title?: string): string;

/**
* Shows a dialog which asks the user to choose one or more existing files.
* Optionally override the starting directory of the dialog or its title.
* You can also restrict to only certain file types by specifying {@link FileFilter|filters}.
*
* Returns an array of the absolute paths of the chosen files, or an empty array if the user cancels the dialog.
*/
export function promptOpenFiles(defaultDir?: string, filters?: FileFilter, title?: string): string[];

/**
* Shows a dialog which asks the user to choose an existing file.
* Optionally override the starting directory of the dialog or its title.
* You can also restrict to only certain file types by specifying {@link FileFilter|filters}.
*
* Returns the absolute path of the chosen file, or an empty string if the user cancels the dialog.
*/
export function promptOpenFile(defaultDir?: string, filters?: FileFilter, title?: string): string;

/**
* Shows a dialog which asks the user to choose a destination for saving a file.
* If the user chooses a file path which already exists, they will be asked to confirm that they want to overwrite the file.
* Optionally override the starting directory of the dialog or its title.
* You can also restrict to only certain file types by specifying {@link FileFilter|filters}.
*
* Returns the absolute path of the chosen file, or an empty string if the user cancels the dialog.
*/
export function promptSaveFile(defaultDir?: string, filters?: string, title?: string): string;

/**
* Outputs the given text in the Console window as regular text.
*/
Expand Down Expand Up @@ -4378,14 +4427,8 @@ declare class FileEdit extends Qt.QWidget {

/**
* When specified, only files that match the filter are shown.
* The filter is given in a format like `"Images (*.png *.xpm *.jpg)"`.
*
* If you want multiple filters, separate them with ';;', for example:
* ```
* "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
* ```
*/
filter: string;
filter: FileFilter;
}
/**
* A widget that displays an {@link Image} on your dialog.
Expand Down
6 changes: 6 additions & 0 deletions src/tiled/scriptdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,12 @@ void ScriptDialog::setNewRowMode(NewRowMode mode)
m_newRowMode = mode;
}

int ScriptDialog::exec()
{
ScriptManager::ResetBlocker blocker;
return QDialog::exec();
}

QWidget *ScriptDialog::addDialogWidget(QWidget *widget, const QString &label)
{
determineWidgetGrouping(widget);
Expand Down
2 changes: 2 additions & 0 deletions src/tiled/scriptdialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ class ScriptDialog : public QDialog
NewRowMode newRowMode() const;
void setNewRowMode(NewRowMode mode);

int exec() override;

static void deleteAllDialogs();

private:
Expand Down
35 changes: 35 additions & 0 deletions src/tiled/scriptmodule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

#include <QAction>
#include <QCoreApplication>
#include <QFileDialog>
#include <QInputDialog>
#include <QLibraryInfo>
#include <QMenu>
Expand Down Expand Up @@ -539,6 +540,7 @@ QByteArray ScriptModule::decompress(const QByteArray &data, CompressionMethod me
return Tiled::decompress(data, data.size(), static_cast<Tiled::CompressionMethod>(method));
}


void ScriptModule::trigger(const QByteArray &actionName) const
{
if (QAction *action = ActionManager::findAction(actionName))
Expand Down Expand Up @@ -596,6 +598,39 @@ QString ScriptModule::prompt(const QString &label, const QString &text, const QS
return QInputDialog::getText(MainWindow::maybeInstance(), title, label, QLineEdit::Normal, text);
}

QString ScriptModule::promptDirectory(const QString &defaultDir, const QString &title) const
{
ScriptManager::ResetBlocker blocker;
return QFileDialog::getExistingDirectory(MainWindow::maybeInstance(),
title.isEmpty() ? tr("Open Directory") : title,
defaultDir,
QFileDialog::ShowDirsOnly);
}

QStringList ScriptModule::promptOpenFiles(const QString &defaultDir, const QString &filters, const QString &title) const
{
ScriptManager::ResetBlocker blocker;
return QFileDialog::getOpenFileNames(MainWindow::maybeInstance(),
title.isEmpty() ? tr("Open Files") : title,
defaultDir, filters);
}

QString ScriptModule::promptOpenFile(const QString &defaultDir, const QString &filters, const QString &title) const
{
ScriptManager::ResetBlocker blocker;
return QFileDialog::getOpenFileName(MainWindow::maybeInstance(),
title.isEmpty() ? tr("Open File") : title,
defaultDir, filters);
}

QString ScriptModule::promptSaveFile(const QString &defaultDir, const QString &filters, const QString &title) const
{
ScriptManager::ResetBlocker blocker;
return QFileDialog::getSaveFileName(MainWindow::maybeInstance(),
title.isEmpty() ? tr("Save File") : title,
defaultDir, filters);
}

void ScriptModule::log(const QString &text) const
{
Tiled::INFO(text);
Expand Down
4 changes: 4 additions & 0 deletions src/tiled/scriptmodule.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ class ScriptModule : public QObject

Q_INVOKABLE QByteArray compress(const QByteArray &data, CompressionMethod method = Zlib, int compressionLevel = -1);
Q_INVOKABLE QByteArray decompress(const QByteArray &data, CompressionMethod method = Zlib);
Q_INVOKABLE QString promptDirectory(const QString &defaultDir = QString(), const QString &title = QString()) const;
Q_INVOKABLE QStringList promptOpenFiles(const QString &defaultDir = QString(), const QString &filters = QString(), const QString &title = QString()) const;
Q_INVOKABLE QString promptOpenFile(const QString &defaultDir = QString(), const QString &filters = QString(), const QString &title = QString()) const;
Q_INVOKABLE QString promptSaveFile(const QString &defaultDir = QString(), const QString &filters = QString(), const QString &title = QString()) const;

signals:
void assetCreated(Tiled::EditableAsset *asset);
Expand Down

0 comments on commit 17a56ff

Please sign in to comment.