X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmainwindow.cpp;h=9ae246b65759157181e79435e1e128ce5c760eaf;hb=059d57d43c93efb5a862ae150425922678810ad7;hp=34ecc812b61d0503cc81c3a026dd4aed4e90208a;hpb=f12ae5f3dcb20734eb005ab3ad032b6aa996ff56;p=kdenlive diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 34ecc812..9ae246b6 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -61,6 +61,8 @@ #include "colorscopes/histogram.h" #include "audiospectrum.h" #include "spectrogram.h" +#include "archivewidget.h" +#include "databackup/backupwidget.h" #include #include @@ -138,6 +140,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & KXmlGuiWindow(parent), m_activeDocument(NULL), m_activeTimeline(NULL), + m_recMonitor(NULL), m_renderWidget(NULL), #ifndef NO_JOGSHUTTLE m_jogProcess(NULL), @@ -156,6 +159,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & if (!KdenliveSettings::colortheme().isEmpty()) slotChangePalette(NULL, KdenliveSettings::colortheme()); setFont(KGlobalSettings::toolBarFont()); parseProfiles(MltPath); + KdenliveSettings::setCurrent_profile(KdenliveSettings::default_profile()); m_commandStack = new QUndoGroup; setDockNestingEnabled(true); m_timelineArea = new KTabWidget(this); @@ -197,30 +201,32 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_clipMonitorDock->setObjectName("clip_monitor"); m_clipMonitor = new Monitor("clip", m_monitorManager, QString(), m_timelineArea); m_clipMonitorDock->setWidget(m_clipMonitor); - addDockWidget(Qt::TopDockWidgetArea, m_clipMonitorDock); - + connect(m_projectList, SIGNAL(clipSelected(DocClipBase *, QPoint)), m_clipMonitor, SLOT(slotSetXml(DocClipBase *, QPoint))); + m_projectMonitorDock = new QDockWidget(i18n("Project Monitor"), this); m_projectMonitorDock->setObjectName("project_monitor"); m_projectMonitor = new Monitor("project", m_monitorManager, QString()); m_projectMonitorDock->setWidget(m_projectMonitor); - addDockWidget(Qt::TopDockWidgetArea, m_projectMonitorDock); #ifndef Q_WS_MAC m_recMonitorDock = new QDockWidget(i18n("Record Monitor"), this); m_recMonitorDock->setObjectName("record_monitor"); - m_recMonitor = new RecMonitor("record"); + m_recMonitor = new RecMonitor("record", m_monitorManager); m_recMonitorDock->setWidget(m_recMonitor); - addDockWidget(Qt::TopDockWidgetArea, m_recMonitorDock); connect(m_recMonitor, SIGNAL(addProjectClip(KUrl)), this, SLOT(slotAddProjectClip(KUrl))); connect(m_recMonitor, SIGNAL(showConfigDialog(int, int)), this, SLOT(slotPreferences(int, int))); #endif + m_monitorManager->initMonitors(m_clipMonitor, m_projectMonitor, m_recMonitor); m_notesDock = new QDockWidget(i18n("Project Notes"), this); m_notesDock->setObjectName("notes_widget"); - m_notesWidget = new KTextEdit(); + m_notesWidget = new NotesWidget(); + connect(m_notesWidget, SIGNAL(insertNotesTimecode()), this, SLOT(slotInsertNotesTimecode())); + connect(m_notesWidget, SIGNAL(seekProject(int)), m_projectMonitor->render, SLOT(seekToFrame(int))); + m_notesWidget->setTabChangesFocus(true); #if KDE_IS_VERSION(4,4,0) - m_notesWidget->setClickMessage(i18n("Enter your project notes here...")); + m_notesWidget->setClickMessage(i18n("Enter your project notes here ...")); #endif m_notesDock->setWidget(m_notesWidget); addDockWidget(Qt::TopDockWidgetArea, m_notesDock); @@ -243,7 +249,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_effectListDock->setWidget(m_effectList); addDockWidget(Qt::TopDockWidgetArea, m_effectListDock); - m_vectorscope = new Vectorscope(m_projectMonitor, m_clipMonitor); + m_vectorscope = new Vectorscope(m_monitorManager); m_vectorscopeDock = new QDockWidget(i18n("Vectorscope"), this); m_vectorscopeDock->setObjectName(m_vectorscope->widgetName()); m_vectorscopeDock->setWidget(m_vectorscope); @@ -253,7 +259,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & connect(m_vectorscope, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest())); m_gfxScopesList.append(m_vectorscopeDock); - m_waveform = new Waveform(m_projectMonitor, m_clipMonitor); + m_waveform = new Waveform(m_monitorManager); m_waveformDock = new QDockWidget(i18n("Waveform"), this); m_waveformDock->setObjectName(m_waveform->widgetName()); m_waveformDock->setWidget(m_waveform); @@ -263,7 +269,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & connect(m_waveform, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest())); m_gfxScopesList.append(m_waveformDock); - m_RGBParade = new RGBParade(m_projectMonitor, m_clipMonitor); + m_RGBParade = new RGBParade(m_monitorManager); m_RGBParadeDock = new QDockWidget(i18n("RGB Parade"), this); m_RGBParadeDock->setObjectName(m_RGBParade->widgetName()); m_RGBParadeDock->setWidget(m_RGBParade); @@ -273,7 +279,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & connect(m_RGBParade, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest())); m_gfxScopesList.append(m_RGBParadeDock); - m_histogram = new Histogram(m_projectMonitor, m_clipMonitor); + m_histogram = new Histogram(m_monitorManager); m_histogramDock = new QDockWidget(i18n("Histogram"), this); m_histogramDock->setObjectName(m_histogram->widgetName()); m_histogramDock->setWidget(m_histogram); @@ -289,7 +295,6 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_audiosignalDock->setObjectName("audiosignal"); m_audiosignalDock->setWidget(m_audiosignal); addDockWidget(Qt::TopDockWidgetArea, m_audiosignalDock); -// connect(m_audiosignal, SIGNAL(updateAudioMonitoring()), m_monitorManager, SLOT(slotUpdateAudioMonitoring())); connect(m_audiosignalDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateAudioScopeFrameRequest())); connect(m_audiosignal, SIGNAL(updateAudioMonitoring()), this, SLOT(slotUpdateAudioScopeFrameRequest())); @@ -334,6 +339,15 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & // Ensure connections were set up correctly Q_ASSERT(b); + + + // Add monitors here to keep them at the right of the window + addDockWidget(Qt::TopDockWidgetArea, m_clipMonitorDock); + addDockWidget(Qt::TopDockWidgetArea, m_projectMonitorDock); +#ifndef Q_WS_MAC + addDockWidget(Qt::TopDockWidgetArea, m_recMonitorDock); +#endif + m_undoViewDock = new QDockWidget(i18n("Undo History"), this); m_undoViewDock->setObjectName("undo_history"); m_undoView = new QUndoView(); @@ -343,37 +357,41 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_undoView->setGroup(m_commandStack); addDockWidget(Qt::TopDockWidgetArea, m_undoViewDock); - //overviewDock = new QDockWidget(i18n("Project Overview"), this); - //overviewDock->setObjectName("project_overview"); - //m_overView = new CustomTrackView(NULL, NULL, this); - //overviewDock->setWidget(m_overView); - //addDockWidget(Qt::TopDockWidgetArea, overviewDock); - setupActions(); + + // Close non-general docks for the initial layout + // only show important ones + m_histogramDock->close(); + m_RGBParadeDock->close(); + m_waveformDock->close(); + m_vectorscopeDock->close(); + + m_audioSpectrumDock->close(); + m_spectrogramDock->close(); + m_audiosignalDock->close(); + + m_undoViewDock->close(); + + + /// Tabify Widgets /// - tabifyDockWidget(m_projectListDock, m_effectStackDock); - tabifyDockWidget(m_projectListDock, m_transitionConfigDock); + tabifyDockWidget(m_effectListDock, m_effectStackDock); + tabifyDockWidget(m_effectListDock, m_transitionConfigDock); tabifyDockWidget(m_projectListDock, m_notesDock); - tabifyDockWidget(m_clipMonitorDock, m_projectMonitorDock); #ifndef Q_WS_MAC tabifyDockWidget(m_clipMonitorDock, m_recMonitorDock); #endif - tabifyDockWidget(m_vectorscopeDock, m_waveformDock); - tabifyDockWidget(m_vectorscopeDock, m_RGBParadeDock); - tabifyDockWidget(m_vectorscopeDock, m_histogramDock); - tabifyDockWidget(m_vectorscopeDock, m_undoViewDock); - tabifyDockWidget(m_vectorscopeDock, m_effectListDock); + setCentralWidget(m_timelineArea); - KdenliveSettings::setCurrent_profile(KdenliveSettings::default_profile()); m_fileOpenRecent = KStandardAction::openRecent(this, SLOT(openFile(const KUrl &)), actionCollection()); readOptions(); m_fileRevert = KStandardAction::revert(this, SLOT(slotRevert()), actionCollection()); @@ -398,7 +416,6 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & // Stop motion actions. Beware of the order, we MUST use the same order in stopmotion/stopmotion.cpp m_stopmotion_actions = new KActionCategory(i18n("Stop Motion"), actionCollection()); action = new KAction(KIcon("media-record"), i18n("Capture frame"), this); - action->setShortcut(Qt::Key_Space); //action->setShortcutContext(Qt::WidgetWithChildrenShortcut); m_stopmotion_actions->addAction("stopmotion_capture", action); action = new KAction(i18n("Switch live / captured frame"), this); @@ -408,8 +425,14 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & action->setCheckable(true); action->setChecked(false); m_stopmotion_actions->addAction("stopmotion_overlay", action); - setupGUI(); + // Build effects menu + m_effectsMenu = new QMenu(i18n("Add Effect")); + m_effectActions = new KActionCategory(i18n("Effects"), actionCollection()); + m_effectList->reloadEffectList(m_effectsMenu, m_effectActions); + m_effectsActionCollection->readSettings(); + + setupGUI(); // Find QDockWidget tab bars and show / hide widget title bars on right click QList tabs = findChildren(); @@ -431,7 +454,6 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & loadPlugins(); loadTranscoders(); - //kDebug() << factory() << " " << factory()->container("video_effects_menu", this); m_projectMonitor->setupMenu(static_cast(factory()->container("monitor_go", this)), m_playZone, m_loopZone, NULL, m_loopClip); m_clipMonitor->setupMenu(static_cast(factory()->container("monitor_go", this)), m_playZone, m_loopZone, static_cast(factory()->container("marker_menu", this))); @@ -486,33 +508,21 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & connect(themesMenu, SIGNAL(triggered(QAction *)), this, SLOT(slotChangePalette(QAction*))); // Setup and fill effects and transitions menus. - m_videoEffectsMenu = static_cast(factory()->container("video_effects_menu", this)); - for (int i = 0; i < videoEffects.count(); ++i) - m_videoEffectsMenu->addAction(m_videoEffects[i]); - m_audioEffectsMenu = static_cast(factory()->container("audio_effects_menu", this)); - for (int i = 0; i < audioEffects.count(); ++i) - m_audioEffectsMenu->addAction(m_audioEffects[i]); - m_customEffectsMenu = static_cast(factory()->container("custom_effects_menu", this)); - if (customEffects.isEmpty()) - m_customEffectsMenu->setEnabled(false); - else - m_customEffectsMenu->setEnabled(true); - for (int i = 0; i < customEffects.count(); ++i) - m_customEffectsMenu->addAction(m_customEffects[i]); + + + QMenu *m = static_cast(factory()->container("video_effects_menu", this)); + m->addActions(m_effectsMenu->actions()); + + m_transitionsMenu = new QMenu(i18n("Add Transition"), this); for (int i = 0; i < transitions.count(); ++i) m_transitionsMenu->addAction(m_transitions[i]); - connect(m_videoEffectsMenu, SIGNAL(triggered(QAction *)), this, SLOT(slotAddVideoEffect(QAction *))); - connect(m_audioEffectsMenu, SIGNAL(triggered(QAction *)), this, SLOT(slotAddAudioEffect(QAction *))); - connect(m_customEffectsMenu, SIGNAL(triggered(QAction *)), this, SLOT(slotAddCustomEffect(QAction *))); + connect(m, SIGNAL(triggered(QAction *)), this, SLOT(slotAddVideoEffect(QAction *))); + connect(m_effectsMenu, SIGNAL(triggered(QAction *)), this, SLOT(slotAddVideoEffect(QAction *))); connect(m_transitionsMenu, SIGNAL(triggered(QAction *)), this, SLOT(slotAddTransition(QAction *))); - QMenu *newEffect = new QMenu(this); - newEffect->addMenu(m_videoEffectsMenu); - newEffect->addMenu(m_audioEffectsMenu); - newEffect->addMenu(m_customEffectsMenu); - m_effectStack->setMenu(newEffect); + m_effectStack->setMenu(m_effectsMenu); QMenu *viewMenu = static_cast(factory()->container("dockwindows", this)); const QList viewActions = createPopupMenu()->actions(); @@ -544,9 +554,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_timelineContextClipMenu->addMenu(markersMenu); m_timelineContextClipMenu->addSeparator(); m_timelineContextClipMenu->addMenu(m_transitionsMenu); - m_timelineContextClipMenu->addMenu(m_videoEffectsMenu); - m_timelineContextClipMenu->addMenu(m_audioEffectsMenu); - m_timelineContextClipMenu->addMenu(m_customEffectsMenu); + m_timelineContextClipMenu->addMenu(m_effectsMenu); m_timelineContextTransitionMenu->addAction(actionCollection()->action("edit_item_duration")); m_timelineContextTransitionMenu->addAction(actionCollection()->action("delete_item")); @@ -557,12 +565,12 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & connect(m_projectMonitorDock, SIGNAL(visibilityChanged(bool)), m_projectMonitor, SLOT(refreshMonitor(bool))); connect(m_clipMonitorDock, SIGNAL(visibilityChanged(bool)), m_clipMonitor, SLOT(refreshMonitor(bool))); //connect(m_monitorManager, SIGNAL(connectMonitors()), this, SLOT(slotConnectMonitors())); - connect(m_monitorManager, SIGNAL(raiseClipMonitor(bool)), this, SLOT(slotRaiseMonitor(bool))); + connect(m_monitorManager, SIGNAL(raiseMonitor(AbstractMonitor *)), this, SLOT(slotRaiseMonitor(AbstractMonitor *))); connect(m_monitorManager, SIGNAL(checkColorScopes()), this, SLOT(slotUpdateColorScopes())); + connect(m_monitorManager, SIGNAL(clearScopes()), this, SLOT(slotClearColorScopes())); connect(m_effectList, SIGNAL(addEffect(const QDomElement)), this, SLOT(slotAddEffect(const QDomElement))); connect(m_effectList, SIGNAL(reloadEffects()), this, SLOT(slotReloadEffects())); - m_monitorManager->initMonitors(m_clipMonitor, m_projectMonitor); slotConnectMonitors(); // Open or create a file. Command line argument passed in Url has @@ -615,16 +623,10 @@ MainWindow::~MainWindow() delete m_projectMonitor; delete m_clipMonitor; delete m_shortcutRemoveFocus; + delete[] m_transitions; Mlt::Factory::close(); } -void MainWindow::queryQuit() -{ - if (queryClose()) { - close(); - } -} - //virtual bool MainWindow::queryClose() { @@ -768,26 +770,8 @@ void MainWindow::readProperties(const KConfigGroup &config) void MainWindow::slotReloadEffects() { - m_customEffectsMenu->clear(); initEffects::parseCustomEffectsFile(); - QAction *action; - QStringList effectInfo; - QMap effectsList; - for (int ix = 0; ix < customEffects.count(); ix++) { - effectInfo = customEffects.effectIdInfo(ix); - effectsList.insert(effectInfo.at(0).toLower(), effectInfo); - } - if (effectsList.isEmpty()) - m_customEffectsMenu->setEnabled(false); - else - m_customEffectsMenu->setEnabled(true); - - foreach(const QStringList & value, effectsList) { - action = new QAction(value.at(0), this); - action->setData(value); - m_customEffectsMenu->addAction(action); - } - m_effectList->reloadEffectList(); + m_effectList->reloadEffectList(m_effectsMenu, m_effectActions); } #ifndef NO_JOGSHUTTLE @@ -844,10 +828,10 @@ void MainWindow::slotAddEffect(const QDomElement effect) else m_activeTimeline->projectView()->slotAddEffect(effectToAdd, GenTime(), -1); } -void MainWindow::slotRaiseMonitor(bool clipMonitor) +void MainWindow::slotRaiseMonitor(AbstractMonitor *monitor) { - if (clipMonitor) m_clipMonitorDock->raise(); - else m_projectMonitorDock->raise(); + if (monitor == m_clipMonitor) m_clipMonitorDock->raise(); + else if (monitor == m_projectMonitor) m_projectMonitorDock->raise(); } void MainWindow::slotUpdateClip(const QString &id) @@ -863,21 +847,24 @@ void MainWindow::slotConnectMonitors() connect(m_projectList, SIGNAL(deleteProjectClips(QStringList, QMap)), this, SLOT(slotDeleteProjectClips(QStringList, QMap))); connect(m_projectList, SIGNAL(showClipProperties(DocClipBase *)), this, SLOT(slotShowClipProperties(DocClipBase *))); connect(m_projectList, SIGNAL(showClipProperties(QList , QMap)), this, SLOT(slotShowClipProperties(QList , QMap))); - connect(m_projectList, SIGNAL(getFileProperties(const QDomElement, const QString &, int, bool)), m_projectMonitor->render, SLOT(getFileProperties(const QDomElement, const QString &, int, bool))); + connect(m_projectList, SIGNAL(getFileProperties(const QDomElement, const QString &, int, bool, bool)), m_projectMonitor->render, SLOT(getFileProperties(const QDomElement, const QString &, int, bool, bool))); connect(m_projectMonitor->render, SIGNAL(replyGetImage(const QString &, const QPixmap &)), m_projectList, SLOT(slotReplyGetImage(const QString &, const QPixmap &))); - connect(m_projectMonitor->render, SIGNAL(replyGetFileProperties(const QString &, Mlt::Producer*, const QMap < QString, QString > &, const QMap < QString, QString > &, bool)), m_projectList, SLOT(slotReplyGetFileProperties(const QString &, Mlt::Producer*, const QMap < QString, QString > &, const QMap < QString, QString > &, bool))); + connect(m_projectMonitor->render, SIGNAL(replyGetFileProperties(const QString &, Mlt::Producer*, const QMap < QString, QString > &, const QMap < QString, QString > &, bool, bool)), m_projectList, SLOT(slotReplyGetFileProperties(const QString &, Mlt::Producer*, const QMap < QString, QString > &, const QMap < QString, QString > &, bool, bool))); connect(m_projectMonitor->render, SIGNAL(removeInvalidClip(const QString &, bool)), m_projectList, SLOT(slotRemoveInvalidClip(const QString &, bool))); + + connect(m_projectMonitor->render, SIGNAL(blockClipMonitor(const QString)), this, SLOT(slotBlockClipMonitor(const QString))); + connect(m_projectMonitor->render, SIGNAL(removeInvalidProxy(const QString &, bool)), m_projectList, SLOT(slotRemoveInvalidProxy(const QString &, bool))); - connect(m_clipMonitor, SIGNAL(refreshClipThumbnail(const QString &)), m_projectList, SLOT(slotRefreshClipThumbnail(const QString &))); + connect(m_clipMonitor, SIGNAL(refreshClipThumbnail(const QString &, bool)), m_projectList, SLOT(slotRefreshClipThumbnail(const QString &, bool))); connect(m_clipMonitor, SIGNAL(adjustMonitorSize()), this, SLOT(slotAdjustClipMonitor())); connect(m_projectMonitor, SIGNAL(adjustMonitorSize()), this, SLOT(slotAdjustProjectMonitor())); connect(m_projectMonitor, SIGNAL(requestFrameForAnalysis(bool)), this, SLOT(slotMonitorRequestRenderFrame(bool))); - connect(m_clipMonitor, SIGNAL(saveZone(Render *, QPoint)), this, SLOT(slotSaveZone(Render *, QPoint))); - connect(m_projectMonitor, SIGNAL(saveZone(Render *, QPoint)), this, SLOT(slotSaveZone(Render *, QPoint))); + connect(m_clipMonitor, SIGNAL(saveZone(Render *, QPoint, DocClipBase *)), this, SLOT(slotSaveZone(Render *, QPoint, DocClipBase *))); + connect(m_projectMonitor, SIGNAL(saveZone(Render *, QPoint, DocClipBase *)), this, SLOT(slotSaveZone(Render *, QPoint, DocClipBase *))); } void MainWindow::slotAdjustClipMonitor() @@ -1178,6 +1165,10 @@ void MainWindow::setupActions() collection.addAction("project_settings", projectAction); connect(projectAction, SIGNAL(triggered(bool)), this, SLOT(slotEditProjectSettings())); + KAction* backupAction = new KAction(KIcon("edit-undo"), i18n("Open Backup File"), this); + collection.addAction("open_backup", backupAction); + connect(backupAction, SIGNAL(triggered(bool)), this, SLOT(slotOpenBackupDialog())); + KAction* projectRender = new KAction(KIcon("media-record"), i18n("Render"), this); collection.addAction("project_render", projectRender); projectRender->setShortcut(Qt::CTRL + Qt::Key_Return); @@ -1226,6 +1217,11 @@ void MainWindow::setupActions() collection.addAction("transcode_clip", transcodeClip); connect(transcodeClip, SIGNAL(triggered(bool)), this, SLOT(slotTranscodeClip())); + KAction *archiveProject = new KAction(KIcon("file-save"), i18n("Archive Project"), this); + collection.addAction("archive_project", archiveProject); + connect(archiveProject, SIGNAL(triggered(bool)), this, SLOT(slotArchiveProject())); + + KAction *markIn = collection.addAction("mark_in"); markIn->setText(i18n("Set Zone In")); markIn->setShortcut(Qt::Key_I); @@ -1429,6 +1425,7 @@ void MainWindow::setupActions() connect(deleteAllClipMarkers, SIGNAL(triggered(bool)), this, SLOT(slotDeleteAllClipMarkers())); KAction* editClipMarker = new KAction(KIcon("document-properties"), i18n("Edit Marker"), this); + editClipMarker->setData(QString("edit_marker")); collection.addAction("edit_clip_marker", editClipMarker); connect(editClipMarker, SIGNAL(triggered(bool)), this, SLOT(slotEditClipMarker())); @@ -1517,17 +1514,8 @@ void MainWindow::setupActions() showTitleBar->setChecked(KdenliveSettings::showtitlebars()); slotShowTitleBars(KdenliveSettings::showtitlebars()); - - //const QByteArray state = layoutGroup.readEntry("layout1", QByteArray()); - - /*QAction *maxCurrent = new KAction(i18n("Maximize Current Widget"), this); - collection.addAction("maximize_current", maxCurrent); - maxCurrent->setCheckable(true); - maxCurrent->setChecked(false); - connect(maxCurrent, SIGNAL(triggered(bool)), this, SLOT(slotMaximizeCurrent(bool)));*/ - m_closeAction = KStandardAction::close(this, SLOT(closeCurrentDocument()), collection); - KStandardAction::quit(this, SLOT(queryQuit()), collection); + KStandardAction::quit(this, SLOT(close()), collection); KStandardAction::open(this, SLOT(openFile()), collection); m_saveAction = KStandardAction::save(this, SLOT(saveFile()), collection); KStandardAction::saveAs(this, SLOT(saveFileAs()), collection); @@ -1622,36 +1610,6 @@ void MainWindow::setupActions() // Setup effects and transitions actions. m_effectsActionCollection = new KActionCollection(this, KGlobal::mainComponent()); - //KActionCategory *videoEffectActions = new KActionCategory(i18n("Video Effects"), m_effectsActionCollection); - KActionCategory *videoEffectActions = new KActionCategory(i18n("Video Effects"), collection); - m_videoEffects = new KAction*[videoEffects.count()]; - for (int i = 0; i < videoEffects.count(); ++i) { - QStringList effectInfo = videoEffects.effectIdInfo(i); - m_videoEffects[i] = new KAction(KIcon("kdenlive-show-video"), effectInfo.at(0), this); - m_videoEffects[i]->setData(effectInfo); - m_videoEffects[i]->setIconVisibleInMenu(false); - videoEffectActions->addAction("video_effect_" + effectInfo.at(0), m_videoEffects[i]); - } - //KActionCategory *audioEffectActions = new KActionCategory(i18n("Audio Effects"), m_effectsActionCollection); - KActionCategory *audioEffectActions = new KActionCategory(i18n("Audio Effects"), collection); - m_audioEffects = new KAction*[audioEffects.count()]; - for (int i = 0; i < audioEffects.count(); ++i) { - QStringList effectInfo = audioEffects.effectIdInfo(i); - m_audioEffects[i] = new KAction(KIcon("kdenlive-show-audio"), effectInfo.at(0), this); - m_audioEffects[i]->setData(effectInfo); - m_audioEffects[i]->setIconVisibleInMenu(false); - audioEffectActions->addAction("audio_effect_" + effectInfo.at(0), m_audioEffects[i]); - } - //KActionCategory *customEffectActions = new KActionCategory(i18n("Custom Effects"), m_effectsActionCollection); - KActionCategory *customEffectActions = new KActionCategory(i18n("Custom Effects"), collection); - m_customEffects = new KAction*[customEffects.count()]; - for (int i = 0; i < customEffects.count(); ++i) { - QStringList effectInfo = customEffects.effectIdInfo(i); - m_customEffects[i] = new KAction(KIcon("kdenlive-custom-effect"), effectInfo.at(0), this); - m_customEffects[i]->setData(effectInfo); - m_customEffects[i]->setIconVisibleInMenu(false); - customEffectActions->addAction("custom_effect_" + effectInfo.at(0), m_customEffects[i]); - } //KActionCategory *transitionActions = new KActionCategory(i18n("Transitions"), m_effectsActionCollection); KActionCategory *transitionActions = new KActionCategory(i18n("Transitions"), collection); m_transitions = new KAction*[transitions.count()]; @@ -1660,12 +1618,12 @@ void MainWindow::setupActions() m_transitions[i] = new KAction(effectInfo.at(0), this); m_transitions[i]->setData(effectInfo); m_transitions[i]->setIconVisibleInMenu(false); - transitionActions->addAction("transition_" + effectInfo.at(0), m_transitions[i]); + QString id = effectInfo.at(2); + if (id.isEmpty()) id = effectInfo.at(1); + transitionActions->addAction("transition_" + id, m_transitions[i]); } - m_effectsActionCollection->readSettings(); + //m_effectsActionCollection->readSettings(); - //connect(collection, SIGNAL( clearStatusText() ), - //statusBar(), SLOT( clear() ) ); } void MainWindow::slotDisplayActionMessage(QAction *a) @@ -1714,9 +1672,7 @@ void MainWindow::slotLoadLayout(QAction *action) if (layoutId.isEmpty()) return; KSharedConfigPtr config = KGlobal::config(); KConfigGroup layouts(config, "Layouts"); - //QByteArray geom = QByteArray::fromBase64(layouts.readEntry(layoutId).toAscii()); QByteArray state = QByteArray::fromBase64(layouts.readEntry(layoutId).toAscii()); - //restoreGeometry(geom); restoreState(state); } @@ -1803,8 +1759,17 @@ void MainWindow::newFile(bool showProjectSettings, bool force) m_fileRevert->setEnabled(false); QString profileName = KdenliveSettings::default_profile(); KUrl projectFolder = KdenliveSettings::defaultprojectfolder(); + QMap documentProperties; QPoint projectTracks(KdenliveSettings::videotracks(), KdenliveSettings::audiotracks()); if (!showProjectSettings) { + // set up default properties + documentProperties.insert("enableproxy", QString::number((int) KdenliveSettings::enableproxy())); + documentProperties.insert("generateproxy", QString::number((int) KdenliveSettings::generateproxy())); + documentProperties.insert("proxyminsize", QString::number(KdenliveSettings::proxyminsize())); + documentProperties.insert("proxyparams", KdenliveSettings::proxyparams()); + documentProperties.insert("proxyextension", KdenliveSettings::proxyextension()); + documentProperties.insert("generateimageproxy", QString::number((int) KdenliveSettings::generateimageproxy())); + documentProperties.insert("proxyimageminsize", QString::number(KdenliveSettings::proxyimageminsize())); if (!KdenliveSettings::activatetabs()) if (!closeCurrentDocument()) return; @@ -1822,11 +1787,19 @@ void MainWindow::newFile(bool showProjectSettings, bool force) profileName = w->selectedProfile(); projectFolder = w->selectedFolder(); projectTracks = w->tracks(); + documentProperties.insert("enableproxy", QString::number((int) w->useProxy())); + documentProperties.insert("generateproxy", QString::number((int) w->generateProxy())); + documentProperties.insert("proxyminsize", QString::number(w->proxyMinSize())); + documentProperties.insert("proxyparams", w->proxyParams()); + documentProperties.insert("proxyextension", w->proxyExtension()); + documentProperties.insert("generateimageproxy", QString::number((int) w->generateImageProxy())); + documentProperties.insert("proxyimageminsize", QString::number(w->proxyImageMinSize())); delete w; } m_timelineArea->setEnabled(true); m_projectList->setEnabled(true); - KdenliveDoc *doc = new KdenliveDoc(KUrl(), projectFolder, m_commandStack, profileName, projectTracks, m_projectMonitor->render, m_notesWidget, this); + bool openBackup; + KdenliveDoc *doc = new KdenliveDoc(KUrl(), projectFolder, m_commandStack, profileName, documentProperties, projectTracks, m_projectMonitor->render, m_notesWidget, &openBackup, this); doc->m_autosave = new KAutoSaveFile(KUrl(), doc); bool ok; TrackView *trackView = new TrackView(doc, &ok, this); @@ -1912,7 +1885,7 @@ bool MainWindow::saveFileAs(const QString &outputFileName) QString currentSceneList; m_monitorManager->stopActiveMonitor(); - if (m_activeDocument->saveSceneList(outputFileName, m_projectMonitor->sceneList()) == false) + if (m_activeDocument->saveSceneList(outputFileName, m_projectMonitor->sceneList(), m_projectList->expandedFolders()) == false) return false; // Save timeline thumbnails @@ -1932,7 +1905,7 @@ bool MainWindow::saveFileAs(const QString &outputFileName) bool MainWindow::saveFileAs() { - QString outputFile = KFileDialog::getSaveFileName(m_activeDocument->projectFolder(), getMimeType()); + QString outputFile = KFileDialog::getSaveFileName(m_activeDocument->projectFolder(), getMimeType(false)); if (outputFile.isEmpty()) { return false; } @@ -1980,6 +1953,22 @@ void MainWindow::openLastFile() void MainWindow::openFile(const KUrl &url) { + // Make sure the url is a Kdenlive project file + KMimeType::Ptr mime = KMimeType::findByUrl(url); + if (mime.data()->is("application/x-compressed-tar")) { + // Opening a compressed project file, we need to process it + kDebug()<<"Opening archive, processing"; + ArchiveWidget *ar = new ArchiveWidget(url); + if (ar->exec() == QDialog::Accepted) openFile(KUrl(ar->extractedProjectFile())); + delete ar; + return; + } + if (!url.fileName().endsWith(".kdenlive")) { + // This is not a Kdenlive project file, abort loading + KMessageBox::sorry(this, i18n("File %1 is not a Kdenlive project file", url.path())); + return; + } + // Check if the document is already opened const int ct = m_timelineArea->count(); bool isOpened = false; @@ -2039,7 +2028,8 @@ void MainWindow::doOpenFile(const KUrl &url, KAutoSaveFile *stale) progressDialog.progressBar()->setValue(0); qApp->processEvents(); - KdenliveDoc *doc = new KdenliveDoc(url, KdenliveSettings::defaultprojectfolder(), m_commandStack, KdenliveSettings::default_profile(), QPoint(KdenliveSettings::videotracks(), KdenliveSettings::audiotracks()), m_projectMonitor->render, m_notesWidget, this, &progressDialog); + bool openBackup; + KdenliveDoc *doc = new KdenliveDoc(url, KdenliveSettings::defaultprojectfolder(), m_commandStack, KdenliveSettings::default_profile(), QMap (), QPoint(KdenliveSettings::videotracks(), KdenliveSettings::audiotracks()), m_projectMonitor->render, m_notesWidget, &openBackup, this, &progressDialog); progressDialog.progressBar()->setValue(1); progressDialog.progressBar()->setMaximum(4); @@ -2086,6 +2076,7 @@ void MainWindow::doOpenFile(const KUrl &url, KAutoSaveFile *stale) m_clipMonitor->refreshMonitor(true); progressDialog.progressBar()->setValue(4); + if (openBackup) slotOpenBackupDialog(url); } void MainWindow::recoverFiles(QList staleFiles) @@ -2209,6 +2200,7 @@ void MainWindow::slotEditProjectSettings() { QPoint p = m_activeDocument->getTracksCount(); ProjectSettings *w = new ProjectSettings(m_projectList, m_activeTimeline->projectView()->extractTransitionsLumas(), p.x(), p.y(), m_activeDocument->projectFolder().path(), true, !m_activeDocument->isModified(), this); + connect(w, SIGNAL(disableProxies()), this, SLOT(slotDisableProxies())); if (w->exec() == QDialog::Accepted) { QString profile = w->selectedProfile(); @@ -2220,14 +2212,52 @@ void MainWindow::slotEditProjectSettings() if (KdenliveSettings::videothumbnails() != w->enableVideoThumbs()) slotSwitchVideoThumbs(); if (KdenliveSettings::audiothumbnails() != w->enableAudioThumbs()) slotSwitchAudioThumbs(); if (m_activeDocument->profilePath() != profile) slotUpdateProjectProfile(profile); + if (m_activeDocument->getDocumentProperty("proxyparams") != w->proxyParams()) { + m_activeDocument->setModified(); + m_activeDocument->setDocumentProperty("proxyparams", w->proxyParams()); + if (m_activeDocument->clipManager()->clipsCount() > 0 && KMessageBox::questionYesNo(this, i18n("You have changed the proxy parameters. Do you want to recreate all proxy clips for this project?")) == KMessageBox::Yes) { + //TODO: rebuild all proxies + //m_projectList->rebuildProxies(); + } + } + if (m_activeDocument->getDocumentProperty("proxyextension") != w->proxyExtension()) { + m_activeDocument->setModified(); + m_activeDocument->setDocumentProperty("proxyextension", w->proxyExtension()); + } + if (m_activeDocument->getDocumentProperty("generateproxy") != QString::number((int) w->generateProxy())) { + m_activeDocument->setModified(); + m_activeDocument->setDocumentProperty("generateproxy", QString::number((int) w->generateProxy())); + } + if (m_activeDocument->getDocumentProperty("proxyminsize") != QString::number(w->proxyMinSize())) { + m_activeDocument->setModified(); + m_activeDocument->setDocumentProperty("proxyminsize", QString::number(w->proxyMinSize())); + } + if (m_activeDocument->getDocumentProperty("generateimageproxy") != QString::number((int) w->generateImageProxy())) { + m_activeDocument->setModified(); + m_activeDocument->setDocumentProperty("generateimageproxy", QString::number((int) w->generateImageProxy())); + } + if (m_activeDocument->getDocumentProperty("proxyimageminsize") != QString::number(w->proxyImageMinSize())) { + m_activeDocument->setModified(); + m_activeDocument->setDocumentProperty("proxyimageminsize", QString::number(w->proxyImageMinSize())); + } + if (QString::number((int) w->useProxy()) != m_activeDocument->getDocumentProperty("enableproxy")) { + m_activeDocument->setDocumentProperty("enableproxy", QString::number((int) w->useProxy())); + m_activeDocument->setModified(); + slotUpdateProxySettings(); + } } delete w; } -void MainWindow::slotUpdateProjectProfile(const QString &profile) +void MainWindow::slotDisableProxies() { - double dar = m_activeDocument->dar(); + m_activeDocument->setDocumentProperty("enableproxy", QString::number((int) false)); + m_activeDocument->setModified(); + slotUpdateProxySettings(); +} +void MainWindow::slotUpdateProjectProfile(const QString &profile) +{ // Recreate the stopmotion widget if profile changes if (m_stopmotion) { delete m_stopmotion; @@ -2250,8 +2280,6 @@ void MainWindow::slotUpdateProjectProfile(const QString &profile) m_projectList->updateProjectFormat(m_activeDocument->timecode()); if (m_renderWidget) m_renderWidget->setProfile(m_activeDocument->mltProfile()); m_timelineArea->setTabText(m_timelineArea->currentIndex(), m_activeDocument->description()); - //m_activeDocument->clipManager()->resetProducersList(m_projectMonitor->render->producersList()); - if (dar != m_activeDocument->dar()) m_projectList->reloadClipThumbnails(); if (updateFps) m_activeTimeline->updateProjectFps(); m_activeDocument->setModified(true); m_commandStack->activeStack()->clear(); @@ -2266,7 +2294,7 @@ void MainWindow::slotRenderProject() { if (!m_renderWidget) { QString projectfolder = m_activeDocument ? m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash) : KdenliveSettings::defaultprojectfolder(); - m_renderWidget = new RenderWidget(projectfolder, this); + m_renderWidget = new RenderWidget(projectfolder, m_projectList->useProxy(), this); connect(m_renderWidget, SIGNAL(shutdown()), this, SLOT(slotShutdown())); connect(m_renderWidget, SIGNAL(selectedRenderProfile(QMap )), this, SLOT(slotSetDocumentRenderProfile(QMap ))); connect(m_renderWidget, SIGNAL(prepareRenderingData(bool, bool, const QString&)), this, SLOT(slotPrepareRendering(bool, bool, const QString&))); @@ -2366,7 +2394,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha disconnect(m_projectList, SIGNAL(projectModified()), m_activeDocument, SLOT(setModified())); disconnect(m_projectList, SIGNAL(updateProfile(const QString &)), this, SLOT(slotUpdateProjectProfile(const QString &))); - disconnect(m_projectMonitor->render, SIGNAL(refreshDocumentProducers()), m_activeDocument, SLOT(checkProjectClips())); + disconnect(m_projectMonitor->render, SIGNAL(refreshDocumentProducers(bool, bool)), m_activeDocument, SLOT(checkProjectClips(bool, bool))); disconnect(m_activeDocument, SIGNAL(guidesUpdated()), this, SLOT(slotGuidesUpdated())); disconnect(m_activeDocument, SIGNAL(addProjectClip(DocClipBase *, bool)), m_projectList, SLOT(slotAddClip(DocClipBase *, bool))); @@ -2374,10 +2402,9 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha disconnect(m_activeDocument, SIGNAL(signalDeleteProjectClip(const QString &)), this, SLOT(slotDeleteClip(const QString &))); disconnect(m_activeDocument, SIGNAL(updateClipDisplay(const QString &)), m_projectList, SLOT(slotUpdateClip(const QString &))); disconnect(m_activeDocument, SIGNAL(selectLastAddedClip(const QString &)), m_projectList, SLOT(slotSelectClip(const QString &))); - disconnect(m_activeDocument, SIGNAL(deleteTimelineClip(const QString &)), m_activeTimeline, SLOT(slotDeleteClip(const QString &))); - disconnect(m_activeTimeline->projectView(), SIGNAL(clipItemSelected(ClipItem*, int)), m_effectStack, SLOT(slotClipItemSelected(ClipItem*, int))); - disconnect(m_activeTimeline->projectView(), SIGNAL(clipItemSelected(ClipItem*, int)), this, SLOT(slotActivateEffectStackView())); - disconnect(m_activeTimeline->projectView(), SIGNAL(clipItemSelected(ClipItem*, int)), m_projectMonitor, SLOT(slotSetSelectedClip(ClipItem*))); + disconnect(m_activeTimeline->projectView(), SIGNAL(clipItemSelected(ClipItem*, int, bool)), m_effectStack, SLOT(slotClipItemSelected(ClipItem*, int))); + disconnect(m_activeTimeline->projectView(), SIGNAL(clipItemSelected(ClipItem*, int, bool)), this, SLOT(slotActivateEffectStackView(ClipItem*, int, bool))); + disconnect(m_activeTimeline->projectView(), SIGNAL(clipItemSelected(ClipItem*, int, bool)), m_projectMonitor, SLOT(slotSetSelectedClip(ClipItem*))); disconnect(m_activeTimeline->projectView(), SIGNAL(transitionItemSelected(Transition*, int, QPoint, bool)), m_transitionConfig, SLOT(slotTransitionItemSelected(Transition*, int, QPoint, bool))); disconnect(m_activeTimeline->projectView(), SIGNAL(transitionItemSelected(Transition*, int, QPoint, bool)), this, SLOT(slotActivateTransitionView(Transition *))); disconnect(m_activeTimeline->projectView(), SIGNAL(transitionItemSelected(Transition*, int, QPoint, bool)), m_projectMonitor, SLOT(slotSetSelectedClip(Transition*))); @@ -2404,11 +2431,11 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha disconnect(m_projectList, SIGNAL(displayMessage(const QString&, int)), this, SLOT(slotGotProgressInfo(const QString&, int))); disconnect(m_projectList, SIGNAL(updateRenderStatus()), this, SLOT(slotCheckRenderStatus())); disconnect(m_projectList, SIGNAL(clipNeedsReload(const QString&, bool)), m_activeTimeline->projectView(), SLOT(slotUpdateClip(const QString &, bool))); + disconnect(m_projectList, SIGNAL(refreshClip(const QString &)), m_activeTimeline->projectView(), SLOT(slotRefreshThumbs(const QString &))); m_effectStack->clear(); } //m_activeDocument->setRenderer(NULL); - disconnect(m_projectList, SIGNAL(clipSelected(DocClipBase *)), m_clipMonitor, SLOT(slotSetXml(DocClipBase *))); - disconnect(m_projectList, SIGNAL(refreshClip()), m_monitorManager, SLOT(slotRefreshCurrentMonitor())); + disconnect(m_projectList, SIGNAL(refreshClip(const QString &, bool)), m_monitorManager, SLOT(slotRefreshCurrentMonitor())); m_clipMonitor->stop(); } KdenliveSettings::setCurrent_profile(doc->profilePath()); @@ -2417,8 +2444,8 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha m_projectList->setDocument(doc); m_transitionConfig->updateProjectFormat(doc->mltProfile(), doc->timecode(), doc->tracksList()); m_effectStack->updateProjectFormat(doc->mltProfile(), doc->timecode()); - connect(m_projectList, SIGNAL(clipSelected(DocClipBase *, QPoint)), m_clipMonitor, SLOT(slotSetXml(DocClipBase *, QPoint))); - connect(m_projectList, SIGNAL(refreshClip()), m_monitorManager, SLOT(slotRefreshCurrentMonitor())); + connect(m_projectList, SIGNAL(refreshClip(const QString &, bool)), m_monitorManager, SLOT(slotRefreshCurrentMonitor())); + connect(m_projectList, SIGNAL(refreshClip(const QString &, bool)), trackView->projectView(), SLOT(slotRefreshThumbs(const QString &, bool))); connect(m_projectList, SIGNAL(clipNeedsReload(const QString&, bool)), trackView->projectView(), SLOT(slotUpdateClip(const QString &, bool))); connect(m_projectList, SIGNAL(projectModified()), doc, SLOT(setModified())); @@ -2428,7 +2455,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha connect(m_projectList, SIGNAL(findInTimeline(const QString&)), this, SLOT(slotClipInTimeline(const QString&))); - connect(trackView, SIGNAL(cursorMoved()), m_projectMonitor, SLOT(activateMonitor())); + //connect(trackView, SIGNAL(cursorMoved()), m_projectMonitor, SLOT(activateMonitor())); connect(trackView, SIGNAL(insertTrack(int)), this, SLOT(slotInsertTrack(int))); connect(trackView, SIGNAL(deleteTrack(int)), this, SLOT(slotDeleteTrack(int))); connect(trackView, SIGNAL(configTrack(int)), this, SLOT(slotConfigTrack(int))); @@ -2441,7 +2468,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha connect(m_projectMonitor, SIGNAL(zoneUpdated(QPoint)), doc, SLOT(setModified())); connect(m_clipMonitor, SIGNAL(zoneUpdated(QPoint)), doc, SLOT(setModified())); connect(m_projectMonitor, SIGNAL(durationChanged(int)), trackView, SLOT(setDuration(int))); - connect(m_projectMonitor->render, SIGNAL(refreshDocumentProducers()), doc, SLOT(checkProjectClips())); + connect(m_projectMonitor->render, SIGNAL(refreshDocumentProducers(bool, bool)), doc, SLOT(checkProjectClips(bool, bool))); connect(doc, SIGNAL(addProjectClip(DocClipBase *, bool)), m_projectList, SLOT(slotAddClip(DocClipBase *, bool))); connect(doc, SIGNAL(resetProjectList()), m_projectList, SLOT(slotResetProjectList())); @@ -2449,17 +2476,18 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha connect(doc, SIGNAL(updateClipDisplay(const QString &)), m_projectList, SLOT(slotUpdateClip(const QString &))); connect(doc, SIGNAL(selectLastAddedClip(const QString &)), m_projectList, SLOT(slotSelectClip(const QString &))); - connect(doc, SIGNAL(deleteTimelineClip(const QString &)), trackView, SLOT(slotDeleteClip(const QString &))); connect(doc, SIGNAL(docModified(bool)), this, SLOT(slotUpdateDocumentState(bool))); connect(doc, SIGNAL(guidesUpdated()), this, SLOT(slotGuidesUpdated())); + connect(doc, SIGNAL(saveTimelinePreview(const QString)), trackView, SLOT(slotSaveTimelinePreview(const QString))); + connect(m_notesWidget, SIGNAL(textChanged()), doc, SLOT(setModified())); - connect(trackView->projectView(), SIGNAL(clipItemSelected(ClipItem*, int)), m_effectStack, SLOT(slotClipItemSelected(ClipItem*, int))); + connect(trackView->projectView(), SIGNAL(clipItemSelected(ClipItem*, int, bool)), m_effectStack, SLOT(slotClipItemSelected(ClipItem*, int))); connect(trackView->projectView(), SIGNAL(updateClipMarkers(DocClipBase *)), this, SLOT(slotUpdateClipMarkers(DocClipBase*))); connect(trackView, SIGNAL(showTrackEffects(int, TrackInfo)), m_effectStack, SLOT(slotTrackItemSelected(int, TrackInfo))); connect(trackView, SIGNAL(showTrackEffects(int, TrackInfo)), this, SLOT(slotActivateEffectStackView())); - connect(trackView->projectView(), SIGNAL(clipItemSelected(ClipItem*, int)), this, SLOT(slotActivateEffectStackView())); + connect(trackView->projectView(), SIGNAL(clipItemSelected(ClipItem*, int, bool)), this, SLOT(slotActivateEffectStackView(ClipItem*, int, bool))); connect(trackView->projectView(), SIGNAL(transitionItemSelected(Transition*, int, QPoint, bool)), m_transitionConfig, SLOT(slotTransitionItemSelected(Transition*, int, QPoint, bool))); connect(trackView->projectView(), SIGNAL(transitionItemSelected(Transition*, int, QPoint, bool)), this, SLOT(slotActivateTransitionView(Transition *))); m_zoomSlider->setValue(doc->zoom().x()); @@ -2471,7 +2499,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha connect(trackView->projectView(), SIGNAL(showClipFrame(DocClipBase *, QPoint, const int)), m_clipMonitor, SLOT(slotSetXml(DocClipBase *, QPoint, const int))); connect(trackView->projectView(), SIGNAL(playMonitor()), m_projectMonitor, SLOT(slotPlay())); - connect(trackView->projectView(), SIGNAL(clipItemSelected(ClipItem*, int)), m_projectMonitor, SLOT(slotSetSelectedClip(ClipItem*))); + connect(trackView->projectView(), SIGNAL(clipItemSelected(ClipItem*, int, bool)), m_projectMonitor, SLOT(slotSetSelectedClip(ClipItem*))); connect(trackView->projectView(), SIGNAL(transitionItemSelected(Transition*, int, QPoint, bool)), m_projectMonitor, SLOT(slotSetSelectedClip(Transition*))); connect(m_effectStack, SIGNAL(updateEffect(ClipItem*, int, QDomElement, QDomElement, int)), trackView->projectView(), SLOT(slotUpdateClipEffect(ClipItem*, int, QDomElement, QDomElement, int))); @@ -2572,7 +2600,6 @@ void MainWindow::slotPreferences(int page, int option) KdenliveSettingsDialog* dialog = new KdenliveSettingsDialog(actions, this); connect(dialog, SIGNAL(settingsChanged(const QString&)), this, SLOT(updateConfiguration())); - connect(dialog, SIGNAL(updateProxySettings()), this, SLOT(slotUpdateProxySettings())); connect(dialog, SIGNAL(doResetProfile()), m_monitorManager, SLOT(slotResetProfiles())); #ifndef Q_WS_MAC connect(dialog, SIGNAL(updateCaptureFolder()), this, SLOT(slotUpdateCaptureFolder())); @@ -2972,29 +2999,22 @@ void MainWindow::slotAddTransition(QAction *result) void MainWindow::slotAddVideoEffect(QAction *result) { if (!result) return; + const int EFFECT_VIDEO = 1; + const int EFFECT_AUDIO = 2; QStringList info = result->data().toStringList(); - if (info.isEmpty()) return; - QDomElement effect = videoEffects.getEffectByTag(info.at(1), info.at(2)); - slotAddEffect(effect); -} -void MainWindow::slotAddAudioEffect(QAction *result) -{ - if (!result) return; - QStringList info = result->data().toStringList(); - if (info.isEmpty()) return; - QDomElement effect = audioEffects.getEffectByTag(info.at(1), info.at(2)); - slotAddEffect(effect); + if (info.isEmpty() || info.size() < 3) return; + QDomElement effect ; + if (info.at(2) == QString::number((int) EFFECT_VIDEO)) + effect = videoEffects.getEffectByTag(info.at(0), info.at(1)); + else if (info.at(2) == QString::number((int) EFFECT_AUDIO)) + effect = audioEffects.getEffectByTag(info.at(0), info.at(1)); + else + effect = customEffects.getEffectByTag(info.at(0), info.at(1)); + if (!effect.isNull()) slotAddEffect(effect); + else m_messageLabel->setMessage(i18n("Cannot find effect %1 / %2").arg(info.at(0)).arg(info.at(1)), ErrorMessage); } -void MainWindow::slotAddCustomEffect(QAction *result) -{ - if (!result) return; - QStringList info = result->data().toStringList(); - if (info.isEmpty()) return; - QDomElement effect = customEffects.getEffectByTag(info.at(1), info.at(2)); - slotAddEffect(effect); -} void MainWindow::slotZoomIn() { @@ -3134,6 +3154,10 @@ void MainWindow::slotShowClipProperties(DocClipBase *clip) if (dia_ui->outPoint() != clip->duration().frames(m_activeDocument->fps()) - 1) { // duration changed, we need to update duration newprops.insert("out", QString::number(dia_ui->outPoint())); + int currentLength = QString(clip->producerProperty("length")).toInt(); + if (currentLength <= dia_ui->outPoint()) + newprops.insert("length", QString::number(dia_ui->outPoint() + 1)); + else newprops.insert("length", clip->producerProperty("length")); } if (!path.isEmpty()) { // we are editing an external file, asked if we want to detach from that file or save the result to that title file. @@ -3156,6 +3180,7 @@ void MainWindow::slotShowClipProperties(DocClipBase *clip) // any type of clip but a title ClipProperties *dia = new ClipProperties(clip, m_activeDocument->timecode(), m_activeDocument->fps(), this); connect(dia, SIGNAL(addMarker(const QString &, GenTime, QString)), m_activeTimeline->projectView(), SLOT(slotAddClipMarker(const QString &, GenTime, QString))); + connect(dia, SIGNAL(deleteProxy(const QString)), m_projectList, SLOT(slotDeleteProxy(const QString))); connect(dia, SIGNAL(applyNewClipProperties(const QString, QMap , QMap , bool, bool)), this, SLOT(slotApplyNewClipProperties(const QString, QMap , QMap , bool, bool))); dia->show(); } @@ -3181,9 +3206,17 @@ void MainWindow::slotShowClipProperties(QList cliplist, QMapsetText(i18n("Edit clips")); + QMap newImageProps = dia.properties(); + // Transparency setting applies only for images + QMap newProps = newImageProps; + newProps.remove("transparency"); + for (int i = 0; i < cliplist.count(); i++) { DocClipBase *clip = cliplist.at(i); - new EditClipCommand(m_projectList, clip->getId(), clip->properties(), dia.properties(), true, command); + if (clip->clipType() == IMAGE) + new EditClipCommand(m_projectList, clip->getId(), clip->properties(), newImageProps, true, command); + else + new EditClipCommand(m_projectList, clip->getId(), clip->properties(), newProps, true, command); } m_activeDocument->commandStack()->push(command); for (int i = 0; i < cliplist.count(); i++) @@ -3196,9 +3229,13 @@ void MainWindow::customEvent(QEvent* e) if (e->type() == QEvent::User) m_messageLabel->setMessage(static_cast (e)->message(), MltError); } -void MainWindow::slotActivateEffectStackView() +void MainWindow::slotActivateEffectStackView(ClipItem* item, int ix, bool raise) { - m_effectStack->raiseWindow(m_effectStackDock); + Q_UNUSED(item) + Q_UNUSED(ix) + + if (raise) + m_effectStack->raiseWindow(m_effectStackDock); } void MainWindow::slotActivateTransitionView(Transition *t) @@ -3489,7 +3526,7 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *event) } -void MainWindow::slotSaveZone(Render *render, QPoint zone) +void MainWindow::slotSaveZone(Render *render, QPoint zone, DocClipBase *baseClip, KUrl path) { KDialog *dialog = new KDialog(this); dialog->setCaption("Save clip zone"); @@ -3500,9 +3537,15 @@ void MainWindow::slotSaveZone(Render *render, QPoint zone) QVBoxLayout *vbox = new QVBoxLayout(widget); QLabel *label1 = new QLabel(i18n("Save clip zone as:"), this); - QString path = m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash); - path.append("untitled.mlt"); - KUrlRequester *url = new KUrlRequester(KUrl(path), this); + if (path.isEmpty()) { + QString tmppath = m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash); + if (baseClip == NULL) tmppath.append("untitled.mlt"); + else { + tmppath.append((baseClip->name().isEmpty() ? baseClip->fileURL().fileName() : baseClip->name()) + "-" + QString::number(zone.x()).rightJustified(4, '0') + ".mlt"); + } + path = KUrl(tmppath); + } + KUrlRequester *url = new KUrlRequester(path, this); url->setFilter("video/mlt-playlist"); QLabel *label2 = new QLabel(i18n("Description:"), this); KLineEdit *edit = new KLineEdit(this); @@ -3510,27 +3553,54 @@ void MainWindow::slotSaveZone(Render *render, QPoint zone) vbox->addWidget(url); vbox->addWidget(label2); vbox->addWidget(edit); - if (dialog->exec() == QDialog::Accepted) - render->saveZone(url->url(), edit->text(), zone); + if (dialog->exec() == QDialog::Accepted) { + if (QFile::exists(url->url().path())) { + if (KMessageBox::questionYesNo(this, i18n("File %1 already exists.\nDo you want to overwrite it?", url->url().path())) == KMessageBox::No) { + slotSaveZone(render, zone, baseClip, url->url()); + return; + } + } + if (baseClip && !baseClip->fileURL().isEmpty()) { + // create zone from clip url, so that we don't have problems with proxy clips + QProcess p; +#if QT_VERSION >= 0x040600 + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + env.remove("MLT_PROFILE"); + p.setProcessEnvironment(env); +#else + QStringList env = QProcess::systemEnvironment(); + env << "MLT_PROFILE='\0'"; + p.setEnvironment(env); +#endif + p.start(KdenliveSettings::rendererpath(), QStringList() << baseClip->fileURL().path() << "in=" + QString::number(zone.x()) << "out=" + QString::number(zone.y()) << "-consumer" << "xml:" + url->url().path()); + if (!p.waitForStarted(3000)) { + KMessageBox::sorry(this, i18n("Cannot start MLT's renderer:\n%1", KdenliveSettings::rendererpath())); + } + else if (!p.waitForFinished(5000)) { + KMessageBox::sorry(this, i18n("Timeout while creating xml output")); + } + } + else render->saveZone(url->url(), edit->text(), zone); + } } void MainWindow::slotSetInPoint() { - if (m_clipMonitor->isActive()) + if (m_clipMonitor->isActive()) { m_clipMonitor->slotSetZoneStart(); - else + } else { m_projectMonitor->slotSetZoneStart(); - //else m_activeTimeline->projectView()->setInPoint(); + } } void MainWindow::slotSetOutPoint() { - if (m_clipMonitor->isActive()) + if (m_clipMonitor->isActive()) { m_clipMonitor->slotSetZoneEnd(); - else + } else { m_projectMonitor->slotSetZoneEnd(); - // else m_activeTimeline->projectView()->setOutPoint(); + } } void MainWindow::slotResizeItemStart() @@ -3641,21 +3711,15 @@ void MainWindow::slotShowTimeline(bool show) } } -void MainWindow::slotMaximizeCurrent(bool /*show*/) +void MainWindow::slotMaximizeCurrent(bool) { //TODO: is there a way to maximize current widget? - //if (show == true) - { - m_timelineState = saveState(); - QWidget *par = focusWidget()->parentWidget(); - while (par->parentWidget() && par->parentWidget() != this) - par = par->parentWidget(); - kDebug() << "CURRENT WIDGET: " << par->objectName(); - } - /*else { - //centralWidget()->setHidden(false); - //restoreState(m_timelineState); - }*/ + + m_timelineState = saveState(); + QWidget *par = focusWidget()->parentWidget(); + while (par->parentWidget() && par->parentWidget() != this) + par = par->parentWidget(); + kDebug() << "CURRENT WIDGET: " << par->objectName(); } void MainWindow::loadTranscoders() @@ -3804,15 +3868,53 @@ void MainWindow::slotPrepareRendering(bool scriptExport, bool zoneOnly, const QS } else exportAudio = m_renderWidget->selectedAudioExport(); // Do we want proxy rendering - if (KdenliveSettings::enableproxy() && !m_renderWidget->proxyRendering()) { + if (m_projectList->useProxy() && !m_renderWidget->proxyRendering()) { + QDomDocument doc; + doc.setContent(playlistContent); + QString root = doc.documentElement().attribute("root"); + // replace proxy clips with originals QMap proxies = m_projectList->getProxies(); - QMapIterator i(proxies); + + QDomNodeList producers = doc.elementsByTagName("producer"); + QString producerResource; + QString suffix; + for (uint n = 0; n < producers.length(); n++) { + QDomElement e = producers.item(n).toElement(); + producerResource = EffectsList::property(e, "resource"); + if (producerResource.isEmpty()) continue; + if (!producerResource.startsWith("/")) { + producerResource.prepend(root + "/"); + } + if (producerResource.contains('?')) { + // slowmotion producer + suffix = "?" + producerResource.section('?', 1); + producerResource = producerResource.section('?', 0, 0); + } + else suffix.clear(); + if (!producerResource.isEmpty()) { + if (proxies.contains(producerResource)) { + EffectsList::setProperty(e, "resource", proxies.value(producerResource) + suffix); + // We need to delete the "aspect_ratio" property because proxy clips + // sometimes have different ratio than original clips + EffectsList::removeProperty(e, "aspect_ratio"); + } + } + } + + /*QMapIterator i(proxies); while (i.hasNext()) { i.next(); // Replace all keys with their values (proxy path with original path) - playlistContent.replace(i.key(), i.value()); - } + QString key = i.key(); + playlistContent.replace(key, i.value()); + if (!root.isEmpty() && key.startsWith(root)) { + // in case the resource path in MLT playlist is relative + key.remove(0, root.count() + 1); + playlistContent.replace(key, i.value()); + } + }*/ + playlistContent = doc.toString(); } // Do save scenelist @@ -3885,12 +3987,51 @@ void MainWindow::slotChangePalette(QAction *action, const QString &themename) else theme = action->data().toString(); KdenliveSettings::setColortheme(theme); // Make palette for all widgets. - QPalette plt; - if (theme.isEmpty()) + QPalette plt = kapp->palette(); + if (theme.isEmpty()) { plt = QApplication::desktop()->palette(); - else { + } else { KSharedConfigPtr config = KSharedConfig::openConfig(theme); - plt = KGlobalSettings::createApplicationPalette(config); + +#if KDE_IS_VERSION(4,6,3) + plt = KGlobalSettings::createNewApplicationPalette(config); +#else + // Since there was a bug in createApplicationPalette in KDE < 4.6.3 we need + // to do the palette loading stuff ourselves. (https://bugs.kde.org/show_bug.cgi?id=263497) + QPalette::ColorGroup states[3] = { QPalette::Active, QPalette::Inactive, + QPalette::Disabled }; + // TT thinks tooltips shouldn't use active, so we use our active colors for all states + KColorScheme schemeTooltip(QPalette::Active, KColorScheme::Tooltip, config); + + for ( int i = 0; i < 3 ; i++ ) { + QPalette::ColorGroup state = states[i]; + KColorScheme schemeView(state, KColorScheme::View, config); + KColorScheme schemeWindow(state, KColorScheme::Window, config); + KColorScheme schemeButton(state, KColorScheme::Button, config); + KColorScheme schemeSelection(state, KColorScheme::Selection, config); + + plt.setBrush( state, QPalette::WindowText, schemeWindow.foreground() ); + plt.setBrush( state, QPalette::Window, schemeWindow.background() ); + plt.setBrush( state, QPalette::Base, schemeView.background() ); + plt.setBrush( state, QPalette::Text, schemeView.foreground() ); + plt.setBrush( state, QPalette::Button, schemeButton.background() ); + plt.setBrush( state, QPalette::ButtonText, schemeButton.foreground() ); + plt.setBrush( state, QPalette::Highlight, schemeSelection.background() ); + plt.setBrush( state, QPalette::HighlightedText, schemeSelection.foreground() ); + plt.setBrush( state, QPalette::ToolTipBase, schemeTooltip.background() ); + plt.setBrush( state, QPalette::ToolTipText, schemeTooltip.foreground() ); + + plt.setColor( state, QPalette::Light, schemeWindow.shade( KColorScheme::LightShade ) ); + plt.setColor( state, QPalette::Midlight, schemeWindow.shade( KColorScheme::MidlightShade ) ); + plt.setColor( state, QPalette::Mid, schemeWindow.shade( KColorScheme::MidShade ) ); + plt.setColor( state, QPalette::Dark, schemeWindow.shade( KColorScheme::DarkShade ) ); + plt.setColor( state, QPalette::Shadow, schemeWindow.shade( KColorScheme::ShadowShade ) ); + + plt.setBrush( state, QPalette::AlternateBase, schemeView.background( KColorScheme::AlternateBackground) ); + plt.setBrush( state, QPalette::Link, schemeView.foreground( KColorScheme::LinkText ) ); + plt.setBrush( state, QPalette::LinkVisited, schemeView.foreground( KColorScheme::VisitedText ) ); + } +#endif } kapp->setPalette(plt); @@ -4014,11 +4155,15 @@ void MainWindow::slotSwitchTitles() slotShowTitleBars(!KdenliveSettings::showtitlebars()); } -QString MainWindow::getMimeType() +QString MainWindow::getMimeType(bool open) { QString mimetype = "application/x-kdenlive"; KMimeType::Ptr mime = KMimeType::mimeType(mimetype); - if (!mime) mimetype = "*.kdenlive"; + if (!mime) { + mimetype = "*.kdenlive"; + if (open) mimetype.append(" *.tar.gz"); + } + else if (open) mimetype.append(" application/x-compressed-tar"); return mimetype; } @@ -4065,9 +4210,13 @@ void MainWindow::slotDoUpdateGfxScopeFrameRequest() m_projectMonitor->render->sendFrameForAnalysis = false; } m_clipMonitor->render->sendFrameForAnalysis = false; + if (m_recMonitor) + m_recMonitor->analyseFrames(false); } else { m_projectMonitor->render->sendFrameForAnalysis = true; m_clipMonitor->render->sendFrameForAnalysis = true; + if (m_recMonitor) + m_recMonitor->analyseFrames(true); } } @@ -4101,28 +4250,35 @@ void MainWindow::slotDoUpdateAudioScopeFrameRequest() void MainWindow::slotUpdateColorScopes() { bool request = false; + kDebug()<<"// UPDATE SCOPES"; for (int i = 0; i < m_gfxScopesList.count(); i++) { // Check if we need the renderer to send a new frame for update if (!m_gfxScopesList.at(i)->widget()->visibleRegion().isEmpty() && !(static_cast(m_gfxScopesList.at(i)->widget())->autoRefreshEnabled())) request = true; - static_cast(m_gfxScopesList.at(i)->widget())->slotActiveMonitorChanged(m_clipMonitor->isActive()); + static_cast(m_gfxScopesList.at(i)->widget())->slotActiveMonitorChanged(); } - if (request) { - if (m_clipMonitor->isActive()) m_clipMonitor->render->sendFrameUpdate(); - else m_projectMonitor->render->sendFrameUpdate(); + if (request && m_monitorManager->activeRenderer()) { + m_monitorManager->activeRenderer()->sendFrameUpdate(); + } +} + +void MainWindow::slotClearColorScopes() +{ + for (int i = 0; i < m_gfxScopesList.count(); i++) { + static_cast(m_gfxScopesList.at(i)->widget())->slotClearMonitor(); } } void MainWindow::slotOpenStopmotion() { if (m_stopmotion == NULL) { - m_stopmotion = new StopmotionWidget(m_activeDocument->projectFolder(), m_stopmotion_actions->actions(), this); + m_stopmotion = new StopmotionWidget(m_monitorManager, m_activeDocument->projectFolder(), m_stopmotion_actions->actions(), this); connect(m_stopmotion, SIGNAL(addOrUpdateSequence(const QString)), m_projectList, SLOT(slotAddOrUpdateSequence(const QString))); - for (int i = 0; i < m_gfxScopesList.count(); i++) { + //for (int i = 0; i < m_gfxScopesList.count(); i++) { // Check if we need the renderer to send a new frame for update /*if (!m_scopesList.at(i)->widget()->visibleRegion().isEmpty() && !(static_cast(m_scopesList.at(i)->widget())->autoRefreshEnabled())) request = true;*/ - connect(m_stopmotion, SIGNAL(gotFrame(QImage)), static_cast(m_gfxScopesList.at(i)->widget()), SLOT(slotRenderZoneUpdated(QImage))); + //connect(m_stopmotion, SIGNAL(gotFrame(QImage)), static_cast(m_gfxScopesList.at(i)->widget()), SLOT(slotRenderZoneUpdated(QImage))); //static_cast(m_scopesList.at(i)->widget())->slotMonitorCapture(); - } + //} } m_stopmotion->show(); } @@ -4138,12 +4294,65 @@ void MainWindow::slotDeleteClip(const QString &id) void MainWindow::slotUpdateProxySettings() { - if (m_renderWidget) m_renderWidget->updateProxyConfig(); + if (m_renderWidget) m_renderWidget->updateProxyConfig(m_projectList->useProxy()); if (KdenliveSettings::enableproxy()) KStandardDirs::makeDir(m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash) + "proxy/"); m_projectList->updateProxyConfig(); } +void MainWindow::slotInsertNotesTimecode() +{ + int frames = m_projectMonitor->render->seekPosition().frames(m_activeDocument->fps()); + QString position = m_activeDocument->timecode().getTimecodeFromFrames(frames); + m_notesWidget->insertHtml("" + position + " "); +} + +void MainWindow::slotArchiveProject() +{ + QList list = m_projectList->documentClipList(); + QDomDocument doc = m_activeDocument->xmlSceneList(m_projectMonitor->sceneList(), m_projectList->expandedFolders()); + ArchiveWidget *d = new ArchiveWidget(m_activeDocument->url().fileName(), doc, list, m_activeTimeline->projectView()->extractTransitionsLumas(), this); + d->exec(); +} + + +void MainWindow::slotOpenBackupDialog(const KUrl url) +{ + KUrl projectFile; + KUrl projectFolder; + QString projectId; + kDebug()<<"// BACKUP URL: "<projectFolder(); + projectFile = m_activeDocument->url(); + projectId = m_activeDocument->getDocumentProperty("documentid"); + } + + BackupWidget *dia = new BackupWidget(projectFile, projectFolder, projectId, this); + if (dia->exec() == QDialog::Accepted) { + QString requestedBackup = dia->selectedFile(); + m_activeDocument->backupLastSavedVersion(projectFile.path()); + closeCurrentDocument(false); + doOpenFile(KUrl(requestedBackup), NULL); + m_activeDocument->setUrl(projectFile); + m_activeDocument->setModified(true); + setCaption(m_activeDocument->description()); + } + delete dia; +} + +void MainWindow::slotBlockClipMonitor(const QString id) +{ + if (m_clipMonitor->activeClip() && m_clipMonitor->activeClip()->getId() == id) m_clipMonitor->slotSetXml(NULL); +} + + + #include "mainwindow.moc" #ifdef DEBUG_MAINW