1 /*
2  * Copyright (c) 2011-2021 Meltytech, LLC
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef MAINWINDOW_H
19 #define MAINWINDOW_H
20 
21 #include <QMainWindow>
22 #include <QMutex>
23 #include <QTimer>
24 #include <QUrl>
25 #include <QNetworkAccessManager>
26 #include <QScopedPointer>
27 #include <QSharedPointer>
28 #include "mltcontroller.h"
29 #include "mltxmlchecker.h"
30 
31 #define EXIT_RESTART (42)
32 
33 namespace Ui {
34     class MainWindow;
35 }
36 class Player;
37 class RecentDock;
38 class EncodeDock;
39 class JobsDock;
40 class PlaylistDock;
41 class QUndoStack;
42 class QActionGroup;
43 class FilterController;
44 class ScopeController;
45 class FiltersDock;
46 class TimelineDock;
47 class AutoSaveFile;
48 class QNetworkReply;
49 class KeyframesDock;
50 
51 class MainWindow : public QMainWindow
52 {
53     Q_OBJECT
54 
55 public:
56     enum LayoutMode {
57         Custom = 0,
58         Logging,
59         Editing,
60         Effects,
61         Color,
62         Audio,
63         PlayerOnly
64     };
65 
66     static MainWindow& singleton();
67     ~MainWindow();
68     void open(Mlt::Producer* producer);
69     bool continueModified();
70     bool continueJobsRunning();
71     QUndoStack* undoStack() const;
72     bool saveXML(const QString& filename, bool withRelativePaths = true);
73     static void changeTheme(const QString& theme);
playlistDock()74     PlaylistDock* playlistDock() const { return m_playlistDock; }
filterController()75     FilterController* filterController() const { return m_filterController; }
76     Mlt::Playlist* playlist() const;
77     bool isPlaylistValid() const;
78     Mlt::Producer* multitrack() const;
79     bool isMultitrackValid() const;
80     void doAutosave();
81     void setFullScreen(bool isFullScreen);
82     QString removeFileScheme(QUrl& url);
83     QString untitledFileName() const;
84     void setProfile(const QString& profile_name);
fileName()85     QString fileName() const { return m_currentFile; }
86     bool isSourceClipMyProject(QString resource = MLT.resource(), bool withDialog = true);
87     bool keyframesDockIsVisible() const;
88 
89     void keyPressEvent(QKeyEvent*);
90     void keyReleaseEvent(QKeyEvent *);
91     void hideSetDataDirectory();
customProfileMenu()92     QMenu* customProfileMenu() const { return m_customProfileMenu; }
93     QAction* actionAddCustomProfile() const;
94     QAction* actionProfileRemove() const;
profileGroup()95     QActionGroup* profileGroup() const { return m_profileGroup; }
96     void buildVideoModeMenu(QMenu *topMenu, QMenu *&customMenu, QActionGroup* group, QAction *addAction, QAction *removeAction);
97     void newProject(const QString& filename, bool isProjectFolder = false);
98     void addCustomProfile(const QString& name, QMenu* menu, QAction* action, QActionGroup* group);
99     void removeCustomProfiles(const QStringList& profiles, QDir &dir, QMenu* menu, QAction* action);
100     QUuid timelineClipUuid(int trackIndex, int clipIndex);
101     void replaceInTimeline(const QUuid& uuid, Mlt::Producer& producer);
102     Mlt::ClipInfo* timelineClipInfoByUuid(const QUuid& uuid, int& trackIndex, int& clipIndex);
103     void replaceAllByHash(const QString& hash, Mlt::Producer& producer, bool isProxy = false);
104 
105 signals:
106     void audioChannelsChanged();
107     void producerOpened(bool withReopen = true);
108     void profileChanged();
109     void openFailed(QString);
110     void aboutToShutDown();
111     void renameRequested();
112 
113 protected:
114     MainWindow();
115     bool eventFilter(QObject* target, QEvent* event);
116     void dragEnterEvent(QDragEnterEvent*);
117     void dropEvent(QDropEvent*);
118     void closeEvent(QCloseEvent*);
119     void showEvent(QShowEvent*);
120 
121 private:
122     void setupSettingsMenu();
123     void setupOpenOtherMenu();
124     QAction *addProfile(QActionGroup* actionGroup, const QString& desc, const QString& name);
125     QAction *addLayout(QActionGroup* actionGroup, const QString& name);
126     void readPlayerSettings();
127     void readWindowSettings();
128     void writeSettings();
129     void configureVideoWidget();
130     void setCurrentFile(const QString &filename);
131     void changeAudioChannels(bool checked, int channels);
132     void changeDeinterlacer(bool checked, const char* method);
133     void changeInterpolation(bool checked, const char* method);
134     bool checkAutoSave(QString &url);
135     void stepLeftBySeconds(int sec);
136     bool saveRepairedXmlFile(MltXmlChecker& checker, QString& fileName);
137     void setAudioChannels(int channels);
138     void showSaveError();
139     void setPreviewScale(int scale);
140     void setVideoModeMenu();
141     void resetVideoModeMenu();
142     void resetDockCorners();
143     void showIncompatibleProjectMessage(const QString& shotcutVersion);
144 
145     Ui::MainWindow* ui;
146     Player* m_player;
147     QDockWidget* m_propertiesDock;
148     RecentDock* m_recentDock;
149     EncodeDock* m_encodeDock;
150     JobsDock* m_jobsDock;
151     PlaylistDock* m_playlistDock;
152     TimelineDock* m_timelineDock;
153     QString m_currentFile;
154     bool m_isKKeyPressed;
155     QUndoStack* m_undoStack;
156     QDockWidget* m_historyDock;
157     QActionGroup* m_profileGroup;
158     QActionGroup* m_externalGroup;
159     QActionGroup* m_keyerGroup;
160     QActionGroup* m_layoutGroup;
161     QActionGroup* m_previewScaleGroup;
162     FiltersDock* m_filtersDock;
163     FilterController* m_filterController;
164     ScopeController* m_scopeController;
165     QMenu* m_customProfileMenu;
166     QMenu* m_keyerMenu;
167     QStringList m_multipleFiles;
168     bool m_isPlaylistLoaded;
169     QActionGroup* m_languagesGroup;
170     QSharedPointer<AutoSaveFile> m_autosaveFile;
171     QMutex m_autosaveMutex;
172     QTimer m_autosaveTimer;
173     int m_exitCode;
174     int m_navigationPosition;
175     QScopedPointer<QAction> m_statusBarAction;
176     QNetworkAccessManager m_network;
177     QString m_upgradeUrl;
178     KeyframesDock* m_keyframesDock;
179 
180 #ifdef WITH_LIBLEAP
181     LeapListener m_leapListener;
182 #endif
183 
184 public slots:
185     bool isCompatibleWithGpuMode(MltXmlChecker& checker);
186     bool isXmlRepaired(MltXmlChecker& checker, QString& fileName);
187     void open(QString url, const Mlt::Properties* = nullptr, bool play = true);
188     void openMultiple(const QStringList& paths);
189     void openMultiple(const QList<QUrl>& urls);
190     void openVideo();
191     void openCut(Mlt::Producer* producer, bool play = false);
192     void hideProducer();
193     void closeProducer();
194     void showStatusMessage(QAction* action, int timeoutSeconds = 5);
195     void showStatusMessage(const QString& message, int timeoutSeconds = 5);
196     void seekPlaylist(int start);
197     void seekTimeline(int position, bool seekPlayer = true);
198     void seekKeyframes(int position);
199     QWidget* loadProducerWidget(Mlt::Producer* producer);
200     void onProducerOpened(bool withReopen = true);
201     void onGpuNotSupported();
202     void stepLeftOneFrame();
203     void stepRightOneFrame();
204     void stepLeftOneSecond();
205     void stepRightOneSecond();
206     void setInToCurrent(bool ripple);
207     void setOutToCurrent(bool ripple);
208     void onShuttle(float x);
209     void onPropertiesDockTriggered(bool checked = true);
210     bool on_actionSave_triggered();
211 
212 private slots:
213     void showUpgradePrompt();
214     void on_actionAbout_Shotcut_triggered();
215     void on_actionOpenOther_triggered();
216     void onProducerChanged();
217     bool on_actionSave_As_triggered();
218     void onEncodeTriggered(bool checked = true);
219     void onCaptureStateChanged(bool started);
220     void onJobsDockTriggered(bool = true);
221     void onRecentDockTriggered(bool checked = true);
222     void onPlaylistDockTriggered(bool checked = true);
223     void onTimelineDockTriggered(bool checked = true);
224     void onHistoryDockTriggered(bool checked = true);
225     void onFiltersDockTriggered(bool checked = true);
226     void onKeyframesDockTriggered(bool checked = true);
227     void onPlaylistCreated();
228     void onPlaylistLoaded();
229     void onPlaylistCleared();
230     void onPlaylistClosed();
231     void onPlaylistModified();
232     void onMultitrackCreated();
233     void onMultitrackClosed();
234     void onMultitrackModified();
235     void onMultitrackDurationChanged();
236     void onCutModified();
237     void onProducerModified();
238     void onFilterModelChanged();
239     void updateMarkers();
240     void updateThumbnails();
241     void on_actionUndo_triggered();
242     void on_actionRedo_triggered();
243     void on_actionFAQ_triggered();
244     void on_actionForum_triggered();
245     void on_actionEnter_Full_Screen_triggered();
246     void on_actionRealtime_triggered(bool checked);
247     void on_actionProgressive_triggered(bool checked);
248     void on_actionChannels1_triggered(bool checked);
249     void on_actionChannels2_triggered(bool checked);
250     void on_actionChannels6_triggered(bool checked);
251     void on_actionOneField_triggered(bool checked);
252     void on_actionLinearBlend_triggered(bool checked);
253     void on_actionYadifTemporal_triggered(bool checked);
254     void on_actionYadifSpatial_triggered(bool checked);
255     void on_actionNearest_triggered(bool checked);
256     void on_actionBilinear_triggered(bool checked);
257     void on_actionBicubic_triggered(bool checked);
258     void on_actionHyper_triggered(bool checked);
259     void on_actionJack_triggered(bool checked);
260     void on_actionGPU_triggered(bool checked);
261     void onExternalTriggered(QAction*);
262     void onKeyerTriggered(QAction*);
263     void onProfileTriggered(QAction*);
264     void onProfileChanged();
265     void on_actionAddCustomProfile_triggered();
266     void processMultipleFiles();
267     void onLanguageTriggered(QAction*);
268     void on_actionSystemTheme_triggered();
269     void on_actionFusionDark_triggered();
270     void on_actionFusionLight_triggered();
271     void on_actionTutorials_triggered();
272     void on_actionRestoreLayout_triggered();
273     void on_actionShowTitleBars_triggered(bool checked);
274     void on_actionShowToolbar_triggered(bool checked);
275     void onToolbarVisibilityChanged(bool visible);
276     void on_menuExternal_aboutToShow();
277     void on_actionUpgrade_triggered();
278     void on_actionOpenXML_triggered();
279     void onAutosaveTimeout();
280     void on_actionGammaSRGB_triggered(bool checked);
281     void on_actionGammaRec709_triggered(bool checked);
282     void onFocusChanged(QWidget *old, QWidget * now) const;
283     void onFocusObjectChanged(QObject *obj) const;
284     void onFocusWindowChanged(QWindow *window) const;
285     void onTimelineClipSelected();
286     void onAddAllToTimeline(Mlt::Playlist* playlist, bool skipProxy);
287     void on_actionScrubAudio_triggered(bool checked);
288 #if !defined(Q_OS_MAC)
289     void onDrawingMethodTriggered(QAction*);
290 #endif
291     void on_actionApplicationLog_triggered();
292     void on_actionClose_triggered();
293     void onPlayerTabIndexChanged(int index);
294     void onUpgradeCheckFinished(QNetworkReply* reply);
295     void onUpgradeTriggered();
296     void onTimelineSelectionChanged();
297     void on_actionCut_triggered();
298     void on_actionCopy_triggered();
299     void on_actionPaste_triggered();
300     void onClipCopied();
301     void on_actionExportEDL_triggered();
302     void on_actionExportFrame_triggered();
303     void onGLWidgetImageReady();
304     void on_actionAppDataSet_triggered();
305     void on_actionAppDataShow_triggered();
306     void on_actionNew_triggered();
307     void on_actionKeyboardShortcuts_triggered();
308     void on_actionLayoutLogging_triggered();
309     void on_actionLayoutEditing_triggered();
310     void on_actionLayoutEffects_triggered();
311     void on_actionLayoutColor_triggered();
312     void on_actionLayoutAudio_triggered();
313     void on_actionLayoutPlayer_triggered();
314     void on_actionLayoutPlaylist_triggered();
315     void on_actionLayoutClip_triggered();
316     void on_actionLayoutAdd_triggered();
317     void onLayoutTriggered(QAction*);
318     void on_actionProfileRemove_triggered();
319     void on_actionLayoutRemove_triggered();
320     void on_actionOpenOther2_triggered();
321     void onOpenOtherTriggered(QWidget* widget);
322     void onOpenOtherTriggered();
323     void on_actionClearRecentOnExit_toggled(bool arg1);
324     void onSceneGraphInitialized();
325     void on_actionShowTextUnderIcons_toggled(bool b);
326     void on_actionShowSmallIcons_toggled(bool b);
327     void onPlaylistInChanged(int in);
328     void onPlaylistOutChanged(int out);
329     void on_actionPreviewNone_triggered(bool checked);
330     void on_actionPreview360_triggered(bool checked);
331     void on_actionPreview540_triggered(bool checked);
332     void on_actionPreview720_triggered(bool checked);
333     void on_actionTopics_triggered();
334     void on_actionSync_triggered();
335     void on_actionUseProxy_triggered(bool checked);
336     void on_actionProxyStorageSet_triggered();
337     void on_actionProxyStorageShow_triggered();
338     void on_actionProxyUseProjectFolder_triggered(bool checked);
339     void on_actionProxyUseHardware_triggered(bool checked);
340     void on_actionProxyConfigureHardware_triggered();
341     void updateLayoutSwitcher();
342     void clearCurrentLayout();
343 };
344 
345 #define MAIN MainWindow::singleton()
346 
347 #endif // MAINWINDOW_H
348