1 /*
2  * mainwindow.h
3  * Copyright 2008-2015, Thorbjørn Lindeijer <thorbjorn@lindeijer.nl>
4  * Copyright 2008, Roderic Morris <roderic@ccs.neu.edu>
5  * Copyright 2009-2010, Jeff Bland <jksb@member.fsf.org>
6  * Copyright 2010-2011, Stefan Beller <stefanbeller@googlemail.com>
7  *
8  * This file is part of Tiled.
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License as published by the Free
12  * Software Foundation; either version 2 of the License, or (at your option)
13  * any later version.
14  *
15  * This program is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18  * more details.
19  *
20  * You should have received a copy of the GNU General Public License along with
21  * this program. If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #pragma once
25 
26 #include "clipboardmanager.h"
27 #include "document.h"
28 #include "preferences.h"
29 #include "preferencesdialog.h"
30 #include "project.h"
31 #include "session.h"
32 
33 #include <QMainWindow>
34 #include <QPointer>
35 #include <QSessionManager>
36 
37 class QComboBox;
38 class QLabel;
39 
40 namespace Ui {
41 class MainWindow;
42 }
43 
44 namespace Tiled {
45 
46 class FileFormat;
47 class TileLayer;
48 
49 class AutomappingManager;
50 class ConsoleDock;
51 class DocumentManager;
52 class Editor;
53 class IssuesDock;
54 class LocatorWidget;
55 class MapDocument;
56 class MapDocumentActionHandler;
57 class MapEditor;
58 class MapScene;
59 class MapView;
60 class ObjectTypesEditor;
61 class ProjectDock;
62 class ProjectModel;
63 class TilesetDocument;
64 class TilesetEditor;
65 class Zoomable;
66 
67 /**
68  * The main editor window.
69  *
70  * Represents the main user interface, including the menu bar. It keeps track
71  * of the current file and is also the entry point of all menu actions.
72  */
73 class MainWindow : public QMainWindow
74 {
75     Q_OBJECT
76 
77 public:
78     MainWindow(QWidget *parent = nullptr, Qt::WindowFlags flags = {});
79     ~MainWindow() override;
80 
81     void commitData(QSessionManager &manager);
82 
83     void initializeSession();
84 
85     /**
86      * Opens the given file. When opened successfully, the file is added to the
87      * list of recent files.
88      *
89      * When a \a format is given, it is used to open the file. Otherwise, a
90      * format is searched using MapFormat::supportsFile.
91      *
92      * @return whether the file was successfully opened
93      */
94     bool openFile(const QString &fileName, FileFormat *fileFormat = nullptr);
95 
96     bool addRecentProjectsActions(QMenu *menu) const;
97 
98     static MainWindow *instance();
99 
100 protected:
101     bool event(QEvent *event) override;
102 
103     void closeEvent(QCloseEvent *event) override;
104     void changeEvent(QEvent *event) override;
105 
106     void keyPressEvent(QKeyEvent *) override;
107     void keyReleaseEvent(QKeyEvent *) override;
108 
109     void dragEnterEvent(QDragEnterEvent *) override;
110     void dropEvent(QDropEvent *) override;
111 
112     void resizeEvent(QResizeEvent *) override;
113 
114 private:
115     void newMap();
116     void openFileDialog();
117     void openFileInProject();
118     bool saveFile();
119     bool saveFileAs();
120     void saveAll();
121     void export_(); // 'export' is a reserved word
122     bool exportDocument(Document *document);
123     void exportAs();
124     void exportAsImage();
125     void reload();
126     void closeFile();
127     bool closeAllFiles();
128 
129     void openProject();
130     bool openProjectFile(const QString &fileName);
131     void saveProjectAs();
132     void closeProject();
133     bool switchProject(Project project);
134     void restoreSession();
135     void projectProperties();
136 
137     void cut();
138     void copy();
139     void paste();
140     void pasteInPlace();
141     void delete_();
142     void openPreferences();
143     void openCrashReporterPopup();
144     void openProjectExtensionsPopup();
145 
146     void showPopup(QWidget *widget);
147     void updatePopupGeometry(QSize size);
148 
149     void labelVisibilityActionTriggered(QAction *action);
150     void zoomIn();
151     void zoomOut();
152     void zoomNormal();
153     void fitInView();
154     void setFullScreen(bool fullScreen);
155     void toggleClearView(bool clearView);
156     void setLayoutLocked(bool locked);
157     void resetToDefaultLayout();
158 
159     bool newTileset(const QString &path = QString());
160     void reloadTilesetImages();
161     void addExternalTileset();
162     void resizeMap();
163     void offsetMap();
164     void editMapProperties();
165 
166     void editTilesetProperties();
167 
168     void updateWindowTitle();
169     void updateActions();
170     void updateZoomable();
171     void updateZoomActions();
172     void openDocumentation();
173     void openForum();
174     void showDonationPopup();
175     void aboutTiled();
176     void openRecentFile();
177     void reopenClosedFile();
178     void openRecentProject();
179 
180     void documentChanged(Document *document);
181     void documentSaved(Document *document);
182     void closeDocument(int index);
183 
184     void currentEditorChanged(Editor *editor);
185 
186     void reloadError(const QString &error);
187     void autoMappingError(bool automatic);
188     void autoMappingWarning(bool automatic);
189 
190     void onObjectTypesEditorClosed();
191 
192     void ensureHasBorderInFullScreen();
193 
194     /**
195       * Asks the user whether the given \a mapDocument should be saved, when
196       * necessary. If it needs to ask, also makes sure that it is the current
197       * document.
198       *
199       * @return <code>true</code> when any unsaved data is either discarded or
200       *         saved, <code>false</code> when the user cancelled or saving
201       *         failed.
202       */
203     bool confirmSave(Document *document);
204 
205     /**
206       * Checks all maps for changes, if so, ask if to save these changes.
207       *
208       * @return <code>true</code> when any unsaved data is either discarded or
209       *         saved, <code>false</code> when the user cancelled or saving
210       *         failed.
211       */
212     bool confirmAllSave();
213 
214     bool confirmSaveWorld(const QString &fileName);
215 
216     void writeSettings();
217     void readSettings();
218 
219     void updateRecentFilesMenu();
220     void updateRecentProjectsMenu();
221     void updateViewsAndToolbarsMenu();
222 
223     void retranslateUi();
224 
225     void exportMapAs(MapDocument *mapDocument);
226     void exportTilesetAs(TilesetDocument *tilesetDocument);
227 
228     QList<QDockWidget*> allDockWidgets() const;
229     QList<QToolBar*> allToolBars() const;
230 
231     Ui::MainWindow *mUi;
232     Document *mDocument = nullptr;
233     Zoomable *mZoomable = nullptr;
234     MapDocumentActionHandler *mActionHandler;
235     ConsoleDock *mConsoleDock;
236     ProjectDock *mProjectDock;
237     IssuesDock *mIssuesDock;
238     ObjectTypesEditor *mObjectTypesEditor;
239     QPointer<LocatorWidget> mLocatorWidget;
240     QPointer<QWidget> mPopupWidget;
241     double mPopupWidgetShowProgress = 1.0;
242 
243     QAction *mRecentFiles[Preferences::MaxRecentFiles];
244 
245     QMenu *mLayerMenu;
246     QMenu *mNewLayerMenu;
247     QMenu *mGroupLayerMenu;
248     QMenu *mViewsAndToolbarsMenu;
249     QAction *mViewsAndToolbarsAction;
250     QAction *mShowObjectTypesEditor;
251 
252     QAction *mResetToDefaultLayout;
253     QAction *mLockLayout;
254 
255     void setupQuickStamps();
256 
257     AutomappingManager *mAutomappingManager;
258     DocumentManager *mDocumentManager;
259     MapEditor *mMapEditor;
260     TilesetEditor *mTilesetEditor;
261     QList<QWidget*> mEditorStatusBarWidgets;
262 
263     QPointer<PreferencesDialog> mPreferencesDialog;
264 
265     QMap<QMainWindow*, QByteArray> mMainWindowStates;
266 
267     SessionOption<QStringList> mLoadedWorlds { "loadedWorlds" };
268 
269     static MainWindow *mInstance;
270 };
271 
instance()272 inline MainWindow *MainWindow::instance()
273 {
274     Q_ASSERT(mInstance);
275     return mInstance;
276 }
277 
278 } // namespace Tiled
279