Skip to content

Commit

Permalink
Project: Added project-specific extensions folder
Browse files Browse the repository at this point in the history
By default a folder called "extensions" in the same folder as the
.tiled-project file will be added to the extensions path. This folder
can be changed in the new Project Properties dialog.

The script engine will reset when switching projects also causes a
change in the extensions path, as well as when changing the extensions
path of the current project.

Issue #1665
  • Loading branch information
bjorn committed Apr 10, 2020
1 parent 5f233e7 commit dc2a108
Show file tree
Hide file tree
Showing 21 changed files with 424 additions and 91 deletions.
13 changes: 5 additions & 8 deletions src/tiled/documentmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1062,20 +1062,17 @@ void DocumentManager::tabContextMenuRequested(const QPoint &pos)

menu.addSeparator();

QAction *closeTab = menu.addAction(tr("Close"));
closeTab->setIcon(QIcon(QStringLiteral(":/images/16/window-close.png")));
Utils::setThemeIcon(closeTab, "window-close");
connect(closeTab, &QAction::triggered, [this, index] {
QAction *closeTab = menu.addAction(tr("Close"), [this, index] {
documentCloseRequested(index);
});
closeTab->setIcon(QIcon(QStringLiteral(":/images/16/window-close.png")));
Utils::setThemeIcon(closeTab, "window-close");

QAction *closeOtherTabs = menu.addAction(tr("Close Other Tabs"));
connect(closeOtherTabs, &QAction::triggered, [this, index] {
menu.addAction(tr("Close Other Tabs"), [this, index] {
closeOtherDocuments(index);
});

QAction *closeTabsToRight = menu.addAction(tr("Close Tabs to the Right"));
connect(closeTabsToRight, &QAction::triggered, [this, index] {
menu.addAction(tr("Close Tabs to the Right"), [this, index] {
closeDocumentsToRight(index);
});

Expand Down
34 changes: 26 additions & 8 deletions src/tiled/fileedit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ FileEdit::FileEdit(QWidget *parent)
QToolButton *button = new QToolButton(this);
button->setText(QLatin1String("..."));
button->setAutoRaise(true);
button->setToolTip(tr("Choose"));
layout->addWidget(mLineEdit);
layout->addWidget(button);

Expand Down Expand Up @@ -111,23 +112,40 @@ void FileEdit::validate()
const QUrl url(fileUrl());

QColor textColor = mOkTextColor;
if (url.isLocalFile() && !QFile::exists(url.toLocalFile()))
textColor = mErrorTextColor;
if (url.isLocalFile()) {
const QString localFile = url.toLocalFile();
if (!QFile::exists(localFile) || (mIsDirectory && !QFileInfo(localFile).isDir()))
textColor = mErrorTextColor;
}

QPalette palette = mLineEdit->palette();
palette.setColor(QPalette::Active, QPalette::Text, textColor);
palette.setColor(QPalette::Text, textColor);
mLineEdit->setPalette(palette);
}

void FileEdit::buttonClicked()
{
QUrl url = QFileDialog::getOpenFileUrl(window(),
tr("Choose a File"),
fileUrl(),
mFilter);
if (url.isEmpty())
QUrl url;

if (mIsDirectory) {
url = QFileDialog::getExistingDirectoryUrl(window(),
tr("Choose a Folder"),
fileUrl());
} else {
url = QFileDialog::getOpenFileUrl(window(),
tr("Choose a File"),
fileUrl(),
mFilter);
}

if (url.isEmpty()) {
validate();
return;
}

setFileUrl(url);
validate(); // validate even if url didn't change, since directory may have been created

emit fileUrlChanged(url);
}

Expand Down
15 changes: 15 additions & 0 deletions src/tiled/fileedit.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ class FileEdit : public QWidget
void setFilter(const QString &filter) { mFilter = filter; }
QString filter() const { return mFilter; }

void setIsDirectory(bool isDirectory);
bool isDirectory() const;

signals:
void fileUrlChanged(const QUrl &url);

Expand All @@ -60,8 +63,20 @@ class FileEdit : public QWidget

QLineEdit *mLineEdit;
QString mFilter;
bool mIsDirectory = false;
QColor mOkTextColor;
QColor mErrorTextColor;
};


inline void FileEdit::setIsDirectory(bool isDirectory)
{
mIsDirectory = isDirectory;
}

inline bool FileEdit::isDirectory() const
{
return mIsDirectory;
}

} // namespace Tiled
2 changes: 1 addition & 1 deletion src/tiled/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ int main(int argc, char *argv[])
QObject::connect(&a, &TiledApplication::fileOpenRequest,
&w, [&] (const QString &file) { w.openFile(file); });

initializePluginsAndExtensions();
PluginManager::instance()->loadPlugins();

w.initializeSession();

Expand Down
39 changes: 29 additions & 10 deletions src/tiled/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@
#include "objecttypeseditor.h"
#include "offsetmapdialog.h"
#include "projectdock.h"
#include "projectpropertiesdialog.h"
#include "resizedialog.h"
#include "scriptmanager.h"
#include "templatesdock.h"
#include "terrain.h"
#include "tile.h"
Expand Down Expand Up @@ -274,17 +276,18 @@ MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags flags)
ActionManager::registerAction(mUi->actionLabelsForAllObjects, "LabelsForAllObjects");
ActionManager::registerAction(mUi->actionLabelsForSelectedObjects, "LabelsForSelectedObjects");
ActionManager::registerAction(mUi->actionLoadWorld, "LoadWorld");
ActionManager::registerAction(mUi->actionNewWorld, "NewWorld");
ActionManager::registerAction(mUi->actionMapProperties, "MapProperties");
ActionManager::registerAction(mUi->actionNewMap, "NewMap");
ActionManager::registerAction(mUi->actionNewTileset, "NewTileset");
ActionManager::registerAction(mUi->actionNewWorld, "NewWorld");
ActionManager::registerAction(mUi->actionNoLabels, "NoLabels");
ActionManager::registerAction(mUi->actionOffsetMap, "OffsetMap");
ActionManager::registerAction(mUi->actionOpen, "Open");
ActionManager::registerAction(mUi->actionOpenProject, "OpenProject");
ActionManager::registerAction(mUi->actionPaste, "Paste");
ActionManager::registerAction(mUi->actionPasteInPlace, "PasteInPlace");
ActionManager::registerAction(mUi->actionPreferences, "Preferences");
ActionManager::registerAction(mUi->actionProjectProperties, "ProjectProperties");
ActionManager::registerAction(mUi->actionQuit, "Quit");
ActionManager::registerAction(mUi->actionRefreshProjectFolders, "RefreshProjectFolders");
ActionManager::registerAction(mUi->actionReload, "Reload");
Expand Down Expand Up @@ -655,6 +658,7 @@ MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags flags)
connect(mUi->actionAddFolderToProject, &QAction::triggered, mProjectDock, &ProjectDock::addFolderToProject);
connect(mUi->actionRefreshProjectFolders, &QAction::triggered, mProjectDock, &ProjectDock::refreshProjectFolders);
connect(mUi->actionClearRecentProjects, &QAction::triggered, preferences, &Preferences::clearRecentProjects);
connect(mUi->actionProjectProperties, &QAction::triggered, this, &MainWindow::projectProperties);

connect(mUi->actionDocumentation, &QAction::triggered, this, &MainWindow::openDocumentation);
connect(mUi->actionForum, &QAction::triggered, this, &MainWindow::openForum);
Expand Down Expand Up @@ -700,6 +704,7 @@ MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags flags)
setThemeIcon(mUi->actionCloseProject, "window-close");
setThemeIcon(mUi->actionAddFolderToProject, "folder-new");
setThemeIcon(mUi->actionRefreshProjectFolders, "view-refresh");
setThemeIcon(mUi->actionProjectProperties, "document-properties");
setThemeIcon(mUi->actionDocumentation, "help-contents");
setThemeIcon(mUi->actionAbout, "help-about");

Expand Down Expand Up @@ -909,10 +914,7 @@ void MainWindow::newMap()

void MainWindow::initializeSession()
{
auto prefs = Preferences::instance();
if (!prefs->restoreSessionOnStartup())
return;

const auto prefs = Preferences::instance();
const auto &session = prefs->session();

// Restore associated project if applicable
Expand All @@ -922,7 +924,13 @@ void MainWindow::initializeSession()
updateWindowTitle();
}

restoreSession();
// Script manager initialization is delayed until after the project has
// been loaded, to avoid immediately having to reset the engine again after
// adding the project's extension path.
ScriptManager::instance().initialize();

if (prefs->restoreSessionOnStartup())
restoreSession();
}

bool MainWindow::openFile(const QString &fileName, FileFormat *fileFormat)
Expand Down Expand Up @@ -956,6 +964,11 @@ bool MainWindow::openFile(const QString &fileName, FileFormat *fileFormat)
return true;
}

Project &MainWindow::project() const
{
return mProjectDock->project();
}

void MainWindow::openFileDialog()
{
SessionOption<QString> lastUsedOpenFilter { "file.lastUsedOpenFilter" };
Expand Down Expand Up @@ -1333,6 +1346,8 @@ void MainWindow::switchProject(Project project)
mProjectDock->setProject(std::move(project));
prefs->switchSession(std::move(session));

ScriptManager::instance().refreshExtensionsPaths();

restoreSession();
updateWindowTitle();
updateActions();
Expand All @@ -1355,6 +1370,12 @@ void MainWindow::restoreSession()
mProjectDock->setExpandedPaths(session.expandedProjectPaths);
}

void MainWindow::projectProperties()
{
if (ProjectPropertiesDialog(mProjectDock->project(), this).exec() == QDialog::Accepted)
ScriptManager::instance().refreshExtensionsPaths();
}

void MainWindow::cut()
{
if (auto editor = mDocumentManager->currentEditor())
Expand Down Expand Up @@ -1965,14 +1986,12 @@ void MainWindow::updateWindowTitle()

void MainWindow::showDonationDialog()
{
DonationDialog donationDialog(this);
donationDialog.exec();
DonationDialog(this).exec();
}

void MainWindow::aboutTiled()
{
AboutDialog aboutDialog(this);
aboutDialog.exec();
AboutDialog(this).exec();
}

void MainWindow::retranslateUi()
Expand Down
3 changes: 3 additions & 0 deletions src/tiled/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ class MainWindow : public QMainWindow
*/
bool openFile(const QString &fileName, FileFormat *fileFormat = nullptr);

Project &project() const;

static MainWindow *instance();

protected:
Expand Down Expand Up @@ -125,6 +127,7 @@ class MainWindow : public QMainWindow
void closeProject();
void switchProject(Project project);
void restoreSession();
void projectProperties();

void cut();
void copy();
Expand Down
13 changes: 12 additions & 1 deletion src/tiled/mainwindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@
</widget>
<addaction name="actionAddExternalTileset"/>
<addaction name="separator"/>
<addaction name="actionNewWorld" />
<addaction name="actionNewWorld"/>
<addaction name="actionLoadWorld"/>
<addaction name="menuUnloadWorld"/>
<addaction name="menuSaveWorld"/>
Expand Down Expand Up @@ -214,6 +214,8 @@
<addaction name="separator"/>
<addaction name="actionAddFolderToProject"/>
<addaction name="actionRefreshProjectFolders"/>
<addaction name="separator"/>
<addaction name="actionProjectProperties"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuEdit"/>
Expand Down Expand Up @@ -760,6 +762,15 @@
<string>Ctrl+Shift+M</string>
</property>
</action>
<action name="actionProjectProperties">
<property name="icon">
<iconset resource="tiled.qrc">
<normaloff>:/images/16/document-properties.png</normaloff>:/images/16/document-properties.png</iconset>
</property>
<property name="text">
<string>Project &amp;Properties...</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>
Expand Down
10 changes: 4 additions & 6 deletions src/tiled/newsbutton.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,10 @@ void NewsButton::showNewsMenu()
auto &feed = NewsFeed::instance();

for (const NewsItem &newsItem : feed.newsItems()) {
QAction *action = newsFeedMenu->addAction(newsItem.title);
QAction *action = newsFeedMenu->addAction(newsItem.title, [=] {
QDesktopServices::openUrl(newsItem.link);
NewsFeed::instance().markRead(newsItem);
});

if (feed.isUnread(newsItem)) {
QFont f = action->font();
Expand All @@ -116,11 +119,6 @@ void NewsButton::showNewsMenu()
} else {
action->setIcon(mReadIcon);
}

connect(action, &QAction::triggered, [=] {
QDesktopServices::openUrl(newsItem.link);
NewsFeed::instance().markRead(newsItem);
});
}

newsFeedMenu->addSeparator();
Expand Down
10 changes: 10 additions & 0 deletions src/tiled/project.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ Project::Project()

bool Project::save(const QString &fileName)
{
QString extensionsPath = mExtensionsPath;

// Initialize extensions path to its default value
if (mFileName.isEmpty() && extensionsPath.isEmpty())
extensionsPath = QFileInfo(fileName).dir().filePath(QLatin1String("extensions"));

QJsonObject project;

const QDir dir = QFileInfo(fileName).dir();
Expand All @@ -51,6 +57,7 @@ bool Project::save(const QString &fileName)
folders.append(relative(dir, folder));

project.insert(QLatin1String("folders"), folders);
project.insert(QLatin1String("extensionsPath"), relative(dir, extensionsPath));

QJsonDocument document(project);

Expand All @@ -63,6 +70,7 @@ bool Project::save(const QString &fileName)
return false;

mFileName = fileName;
mExtensionsPath = extensionsPath;
return true;
}

Expand All @@ -85,6 +93,8 @@ bool Project::load(const QString &fileName)

QJsonObject project = document.object();

mExtensionsPath = QDir::cleanPath(dir.absoluteFilePath(project.value(QLatin1String("extensionsFolder")).toString(QLatin1String("extensions"))));

const QJsonArray folders = project.value(QLatin1String("folders")).toArray();
for (const QJsonValue &folderValue : folders)
mFolders.append(QDir::cleanPath(dir.absoluteFilePath(folderValue.toString())));
Expand Down
4 changes: 2 additions & 2 deletions src/tiled/project.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ class Project

void addFolder(const QString &folder);
void removeFolder(int index);
void refreshFolders();

const QStringList &folders() const;

QString mExtensionsPath;

private:
QString mFileName;
QStringList mFolders;
Expand Down
Loading

0 comments on commit dc2a108

Please sign in to comment.