1 /*
2 * documentmanager.h
3 * Copyright 2010, Stefan Beller <stefanbeller@googlemail.com>
4 * Copyright 2010, Thorbjørn Lindeijer <thorbjorn@lindeijer.nl>
5 *
6 * This file is part of Tiled.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #pragma once
23
24 #include "mapdocument.h"
25 #include "tilesetdocument.h"
26
27 #include <QHash>
28 #include <QList>
29 #include <QObject>
30 #include <QPointF>
31 #include <QPointer>
32 #include <QVector>
33
34 class QTabWidget;
35 class QUndoGroup;
36 class QStackedLayout;
37 class QTabBar;
38
39 namespace Tiled {
40
41 class FileSystemWatcher;
42
43 class AbstractTool;
44 class BrokenLinksModel;
45 class BrokenLinksWidget;
46 class Document;
47 class Editor;
48 class FileChangedWarning;
49 class MainWindow;
50 class MapDocument;
51 class MapEditor;
52 class MapView;
53 class TilesetDocument;
54 class TilesetDocumentsModel;
55 class WorldDocument;
56
57 /**
58 * This class controls the open documents.
59 */
60 class DocumentManager : public QObject
61 {
62 Q_OBJECT
63
64 Q_PROPERTY(Document *currentDocument READ currentDocument NOTIFY currentDocumentChanged)
65
66 DocumentManager(QObject *parent = nullptr);
67 ~DocumentManager() override;
68
69 friend class MainWindow;
70
71 public:
72 static DocumentManager *instance();
73 static DocumentManager *maybeInstance();
74
75 QWidget *widget() const;
76
77 void setEditor(Document::DocumentType documentType, Editor *editor);
78 Editor *editor(Document::DocumentType documentType) const;
79 void deleteEditors();
80 QList<Editor*> editors() const;
81
82 Editor *currentEditor() const;
83
84 void saveState();
85 void restoreState();
86
87 QUndoGroup *undoGroup() const;
88
89 Document *currentDocument() const;
90
91 MapView *currentMapView() const;
92 MapView *viewForDocument(MapDocument *mapDocument) const;
93
94 int findDocument(const QString &fileName) const;
95 int findDocument(Document *document) const;
96
97 void switchToDocument(int index);
98 bool switchToDocument(const QString &fileName);
99 bool switchToDocument(Document *document);
100 void switchToDocument(MapDocument *mapDocument, QPointF viewCenter, qreal scale);
101 void switchToDocumentAndHandleSimiliarTileset(MapDocument *mapDocument, QPointF viewCenter, qreal scale);
102
103 void addDocument(const DocumentPtr &document);
104 void insertDocument(int index, const DocumentPtr &document);
105
106 bool isDocumentModified(Document *document) const;
107
108 DocumentPtr loadDocument(const QString &fileName,
109 FileFormat *fileFormat = nullptr,
110 QString *error = nullptr);
111
112 bool saveDocument(Document *document, const QString &fileName);
113 bool saveDocumentAs(Document *document);
114
115 void closeCurrentDocument();
116 void closeAllDocuments();
117
118 void closeOtherDocuments(int index);
119 void closeDocumentsToRight(int index);
120 void closeDocumentAt(int index);
121
122 bool reloadCurrentDocument();
123 bool reloadDocumentAt(int index);
124
125 void checkTilesetColumns(MapDocument *mapDocument);
126 bool checkTilesetColumns(TilesetDocument *tilesetDocument);
127
128 const QVector<DocumentPtr> &documents() const;
129
130 TilesetDocumentsModel *tilesetDocumentsModel() const;
131
132 TilesetDocument *findTilesetDocument(const SharedTileset &tileset) const;
133 TilesetDocument *findTilesetDocument(const QString &fileName) const;
134
135 void openTileset(const SharedTileset &tileset);
136
137 void abortMultiDocumentClose();
138
139 WorldDocument *ensureWorldDocument(const QString &fileName);
140 bool isAnyWorldModified() const;
141 bool isWorldModified(const QString &fileName) const;
142
143 QString fileDialogStartLocation() const;
144
145 signals:
146 void documentCreated(Document *document);
147 void documentOpened(Document *document);
148 void documentAboutToBeSaved(Document *document);
149 void documentSaved(Document *document);
150
151 void fileOpenDialogRequested();
152 void fileOpenRequested(const QString &path);
153 void fileSaveRequested();
154 void templateOpenRequested(const QString &path);
155 void selectCustomPropertyRequested(const QString &name);
156 void templateTilesetReplaced();
157
158 /**
159 * Emitted when the current displayed map document changed.
160 */
161 void currentDocumentChanged(Document *document);
162
163 /**
164 * Emitted when the user requested the document at \a index to be closed.
165 */
166 void documentCloseRequested(int index);
167
168 /**
169 * Emitted when a document is about to be closed.
170 */
171 void documentAboutToClose(Document *document);
172
173 void currentEditorChanged(Editor *editor);
174
175 /**
176 * Emitted when an error occurred while reloading the map.
177 */
178 void reloadError(const QString &error);
179
180 void tilesetDocumentAdded(TilesetDocument *tilesetDocument);
181 void tilesetDocumentRemoved(TilesetDocument *tilesetDocument);
182
183 public slots:
184 void switchToLeftDocument();
185 void switchToRightDocument();
186
187 void openFileDialog();
188 void openFile(const QString &path);
189 void saveFile();
190
191 private:
192 void onWorldUnloaded(const QString &worldFile);
193
194 void currentIndexChanged();
195 void fileNameChanged(const QString &fileName,
196 const QString &oldFileName);
197 void updateDocumentTab(Document *document);
198 void onDocumentSaved();
199 void documentTabMoved(int from, int to);
200 void tabContextMenuRequested(const QPoint &pos);
201
202 void tilesetAdded(int index, Tileset *tileset);
203 void tilesetRemoved(Tileset *tileset);
204
205 void tilesetNameChanged(Tileset *tileset);
206
207 void filesChanged(const QStringList &fileNames);
208 void fileChanged(const QString &fileName);
209 void hideChangedWarning();
210
211 void tilesetImagesChanged(Tileset *tileset);
212
213 bool askForAdjustment(const Tileset &tileset);
214
215 void addToTilesetDocument(const SharedTileset &tileset, MapDocument *mapDocument);
216 void removeFromTilesetDocument(const SharedTileset &tileset, MapDocument *mapDocument);
217
218 void updateSession() const;
219
220 MapDocument *openMapFile(const QString &path);
221 TilesetDocument *openTilesetFile(const QString &path);
222
223 QVector<DocumentPtr> mDocuments;
224 QMap<QString, WorldDocument*> mWorldDocuments;
225 TilesetDocumentsModel *mTilesetDocumentsModel;
226
227 // Pointer becomes null when deleted as part of the UI, to prevent double-deletion
228 QPointer<QWidget> mWidget;
229 QWidget *mNoEditorWidget;
230 QTabBar *mTabBar;
231 FileChangedWarning *mFileChangedWarning;
232 BrokenLinksModel *mBrokenLinksModel;
233 BrokenLinksWidget *mBrokenLinksWidget;
234 QStackedLayout *mEditorStack;
235 MapEditor *mMapEditor;
236
237 QHash<Document::DocumentType, Editor*> mEditorForType;
238
239 QUndoGroup *mUndoGroup;
240 FileSystemWatcher *mFileSystemWatcher;
241
242 static DocumentManager *mInstance;
243
244 bool mMultiDocumentClose;
245 };
246
247 /**
248 * Returns the undo group that combines the undo stacks of all opened
249 * documents.
250 *
251 * @see Document::undoStack()
252 */
undoGroup()253 inline QUndoGroup *DocumentManager::undoGroup() const
254 {
255 return mUndoGroup;
256 }
257
258 /**
259 * Returns all open documents.
260 */
documents()261 inline const QVector<DocumentPtr> &DocumentManager::documents() const
262 {
263 return mDocuments;
264 }
265
tilesetDocumentsModel()266 inline TilesetDocumentsModel *DocumentManager::tilesetDocumentsModel() const
267 {
268 return mTilesetDocumentsModel;
269 }
270
271 } // namespace Tiled
272