X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmainwindow.cpp;h=e3151e18e359103ef3956371228796bcac31bf81;hb=08902b01f367c2545c6e453604f8ecbd2009b6bd;hp=6da2cacaffb174b85b3a4dc9ccdde1e8409f7977;hpb=23b97051124400cc52ec2b3dfc579d1033d73907;p=kdenlive diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 6da2caca..e3151e18 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -42,6 +42,8 @@ #include "audiosignal.h" #ifndef NO_JOGSHUTTLE #include "jogshuttle.h" +#include "jogaction.h" +#include "jogshuttleconfig.h" #endif /* NO_JOGSHUTTLE */ #include "clipproperties.h" #include "wizard.h" @@ -53,10 +55,12 @@ #include "kdenlive-config.h" #include "cliptranscode.h" #include "ui_templateclip_ui.h" -#include "vectorscope.h" -#include "waveform.h" -#include "rgbparade.h" -#include "histogram.h" +#include "colorscopes/vectorscope.h" +#include "colorscopes/waveform.h" +#include "colorscopes/rgbparade.h" +#include "colorscopes/histogram.h" +#include "audiospectrum.h" +#include "spectrogram.h" #include #include @@ -108,15 +112,23 @@ #include +// Uncomment for deeper debugging +//#define DEBUG_MAINW + +#ifdef DEBUG_MAINW +#include +#endif + static const char version[] = VERSION; static const int ID_TIMELINE_POS = 0; - namespace Mlt { class Producer; }; +Q_DECLARE_METATYPE(QVector) + EffectsList MainWindow::videoEffects; EffectsList MainWindow::audioEffects; EffectsList MainWindow::customEffects; @@ -129,11 +141,12 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_renderWidget(NULL), #ifndef NO_JOGSHUTTLE m_jogProcess(NULL), + m_jogShuttle(NULL), #endif /* NO_JOGSHUTTLE */ m_findActivated(false), m_stopmotion(NULL) { - + qRegisterMetaType > (); // Create DBus interface new MainWindowAdaptor(this); QDBusConnection dbus = QDBusConnection::sessionBus(); @@ -143,6 +156,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); @@ -184,20 +198,17 @@ 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); 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_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 @@ -207,7 +218,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_notesWidget = new KTextEdit(); 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); @@ -236,9 +247,9 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_vectorscopeDock->setWidget(m_vectorscope); addDockWidget(Qt::TopDockWidgetArea, m_vectorscopeDock); connect(m_vectorscopeDock, SIGNAL(visibilityChanged(bool)), m_vectorscope, SLOT(forceUpdate(bool))); - connect(m_vectorscopeDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateScopeFrameRequest())); - connect(m_vectorscope, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateScopeFrameRequest())); - m_scopesList.append(m_vectorscopeDock); + connect(m_vectorscopeDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest())); + connect(m_vectorscope, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest())); + m_gfxScopesList.append(m_vectorscopeDock); m_waveform = new Waveform(m_projectMonitor, m_clipMonitor); m_waveformDock = new QDockWidget(i18n("Waveform"), this); @@ -246,9 +257,9 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_waveformDock->setWidget(m_waveform); addDockWidget(Qt::TopDockWidgetArea, m_waveformDock); connect(m_waveformDock, SIGNAL(visibilityChanged(bool)), m_waveform, SLOT(forceUpdate(bool))); - connect(m_waveformDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateScopeFrameRequest())); - connect(m_waveform, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateScopeFrameRequest())); - m_scopesList.append(m_waveformDock); + connect(m_waveformDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest())); + connect(m_waveform, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest())); + m_gfxScopesList.append(m_waveformDock); m_RGBParade = new RGBParade(m_projectMonitor, m_clipMonitor); m_RGBParadeDock = new QDockWidget(i18n("RGB Parade"), this); @@ -256,9 +267,9 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_RGBParadeDock->setWidget(m_RGBParade); addDockWidget(Qt::TopDockWidgetArea, m_RGBParadeDock); connect(m_RGBParadeDock, SIGNAL(visibilityChanged(bool)), m_RGBParade, SLOT(forceUpdate(bool))); - connect(m_RGBParadeDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateScopeFrameRequest())); - connect(m_RGBParade, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateScopeFrameRequest())); - m_scopesList.append(m_RGBParadeDock); + connect(m_RGBParadeDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest())); + connect(m_RGBParade, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest())); + m_gfxScopesList.append(m_RGBParadeDock); m_histogram = new Histogram(m_projectMonitor, m_clipMonitor); m_histogramDock = new QDockWidget(i18n("Histogram"), this); @@ -266,9 +277,9 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_histogramDock->setWidget(m_histogram); addDockWidget(Qt::TopDockWidgetArea, m_histogramDock); connect(m_histogramDock, SIGNAL(visibilityChanged(bool)), m_histogram, SLOT(forceUpdate(bool))); - connect(m_histogramDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateScopeFrameRequest())); - connect(m_histogram, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateScopeFrameRequest())); - m_scopesList.append(m_histogramDock); + connect(m_histogramDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest())); + connect(m_histogram, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateGfxScopeFrameRequest())); + m_gfxScopesList.append(m_histogramDock); m_audiosignal = new AudioSignal; @@ -276,14 +287,58 @@ 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_audiosignalDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateAudioScopeFrameRequest())); + connect(m_audiosignal, SIGNAL(updateAudioMonitoring()), this, SLOT(slotUpdateAudioScopeFrameRequest())); + + m_audioSpectrum = new AudioSpectrum(); + m_audioSpectrumDock = new QDockWidget(i18n("AudioSpectrum"), this); + m_audioSpectrumDock->setObjectName(m_audioSpectrum->widgetName()); + m_audioSpectrumDock->setWidget(m_audioSpectrum); + addDockWidget(Qt::TopDockWidgetArea, m_audioSpectrumDock); + m_audioScopesList.append(m_audioSpectrum); + connect(m_audioSpectrumDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateAudioScopeFrameRequest())); + connect(m_audioSpectrum, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateAudioScopeFrameRequest())); + + m_spectrogram = new Spectrogram(); + m_spectrogramDock = new QDockWidget(i18n("Spectrogram"), this); + m_spectrogramDock->setObjectName(m_spectrogram->widgetName()); + m_spectrogramDock->setWidget(m_spectrogram); + addDockWidget(Qt::TopDockWidgetArea, m_spectrogramDock); + m_audioScopesList.append(m_spectrogram); + connect(m_audioSpectrumDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateAudioScopeFrameRequest())); + connect(m_audioSpectrum, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateAudioScopeFrameRequest())); + + // Connect the audio signal to the audio scope slots + bool b = true; if (m_projectMonitor) { - connect(m_projectMonitor->render, SIGNAL(showAudioSignal(const QByteArray&)), m_audiosignal, SLOT(showAudio(const QByteArray&))); + qDebug() << "project monitor connected"; + b &= connect(m_projectMonitor->render, SIGNAL(audioSamplesSignal(QVector, int, int, int)), + m_audioSpectrum, SLOT(slotReceiveAudio(QVector, int, int, int))); + b &= connect(m_projectMonitor->render, SIGNAL(audioSamplesSignal(const QVector&, const int&, const int&, const int&)), + m_audiosignal, SLOT(slotReceiveAudio(const QVector&, const int&, const int&, const int&))); + b &= connect(m_projectMonitor->render, SIGNAL(audioSamplesSignal(QVector,int,int,int)), + m_spectrogram, SLOT(slotReceiveAudio(QVector,int,int,int))); } if (m_clipMonitor) { - connect(m_clipMonitor->render, SIGNAL(showAudioSignal(const QByteArray&)), m_audiosignal, SLOT(showAudio(const QByteArray&))); + qDebug() << "clip monitor connected"; + b &= connect(m_clipMonitor->render, SIGNAL(audioSamplesSignal(QVector, int, int, int)), + m_audioSpectrum, SLOT(slotReceiveAudio(QVector, int, int, int))); + b &= connect(m_clipMonitor->render, SIGNAL(audioSamplesSignal(const QVector&, int, int, int)), + m_audiosignal, SLOT(slotReceiveAudio(const QVector&, int, int, int))); + b &= connect(m_clipMonitor->render, SIGNAL(audioSamplesSignal(QVector,int,int,int)), + m_spectrogram, SLOT(slotReceiveAudio(QVector,int,int,int))); } - //connect(m_histogramDock, SIGNAL(visibilityChanged(bool)), this, SLOT(slotUpdateScopeFrameRequest())); - //connect(m_histogram, SIGNAL(requestAutoRefresh(bool)), this, SLOT(slotUpdateScopeFrameRequest())); + // 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"); @@ -294,37 +349,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()); @@ -332,15 +391,39 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & // Prepare layout actions KActionCategory *layoutActions = new KActionCategory(i18n("Layouts"), actionCollection()); + m_loadLayout = new KSelectAction(i18n("Load Layout"), actionCollection()); for (int i = 1; i < 5; i++) { - KAction *load = new KAction(KIcon(), i18n("Load Layout %1").arg(i), this); + KAction *load = new KAction(KIcon(), i18n("Layout %1").arg(i), this); load->setData("_" + QString::number(i)); - layoutActions->addAction("load_layout" + QString::number(i), load); + layoutActions->addAction("load_layout" + QString::number(i), load); + m_loadLayout->addAction(load); KAction *save = new KAction(KIcon(), i18n("Save As Layout %1").arg(i), this); save->setData("_" + QString::number(i)); layoutActions->addAction("save_layout" + QString::number(i), save); } + layoutActions->addAction("load_layouts", m_loadLayout); + connect(m_loadLayout, SIGNAL(triggered(QAction*)), this, SLOT(slotLoadLayout(QAction*))); + + KAction *action; + // 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->setShortcutContext(Qt::WidgetWithChildrenShortcut); + m_stopmotion_actions->addAction("stopmotion_capture", action); + action = new KAction(i18n("Switch live / captured frame"), this); + //action->setShortcutContext(Qt::WidgetWithChildrenShortcut); + m_stopmotion_actions->addAction("stopmotion_switch", action); + action = new KAction(KIcon("edit-paste"), i18n("Show last frame over video"), this); + action->setCheckable(true); + action->setChecked(false); + m_stopmotion_actions->addAction("stopmotion_overlay", action); + // 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(); @@ -354,10 +437,6 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & /*ScriptingPart* sp = new ScriptingPart(this, QStringList()); guiFactory()->addClient(sp);*/ - - QMenu *loadLayout = (QMenu*)(factory()->container("layout_load", this)); - if (loadLayout) - connect(loadLayout, SIGNAL(triggered(QAction*)), this, SLOT(slotLoadLayout(QAction*))); QMenu *saveLayout = (QMenu*)(factory()->container("layout_save_as", this)); if (saveLayout) connect(saveLayout, SIGNAL(triggered(QAction*)), this, SLOT(slotSaveLayout(QAction*))); @@ -379,7 +458,6 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & static_cast(factory()->container("transcoders", this)), clipInTimeline); - KAction *action; // build themes menus QMenu *themesMenu = static_cast(factory()->container("themes_menu", this)); QActionGroup *themegroup = new QActionGroup(this); @@ -424,33 +502,20 @@ 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 = m_effectsMenu; + + 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_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(); @@ -482,9 +547,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")); @@ -503,9 +566,6 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_monitorManager->initMonitors(m_clipMonitor, m_projectMonitor); slotConnectMonitors(); - // Disable drop B frames, see Kdenlive issue #1330, see also kdenlivesettingsdialog.cpp - KdenliveSettings::setDropbframes(false); - // Open or create a file. Command line argument passed in Url has // precedence, then "openlastproject", then just a plain empty file. // If opening Url fails, openlastproject will _not_ be used. @@ -540,6 +600,9 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & MainWindow::~MainWindow() { + if (m_stopmotion) { + delete m_stopmotion; + } m_effectStack->slotClipItemSelected(NULL, 0); m_transitionConfig->slotTransitionItemSelected(NULL, 0, QPoint(), false); @@ -553,16 +616,10 @@ MainWindow::~MainWindow() delete m_projectMonitor; delete m_clipMonitor; delete m_shortcutRemoveFocus; + delete[] m_transitions; Mlt::Factory::close(); } -void MainWindow::queryQuit() -{ - if (queryClose()) { - kapp->quit(); - } -} - //virtual bool MainWindow::queryClose() { @@ -706,78 +763,39 @@ 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 void MainWindow::activateShuttleDevice() { + delete m_jogShuttle; + m_jogShuttle = NULL; delete m_jogProcess; m_jogProcess = NULL; if (KdenliveSettings::enableshuttle() == false) return; + m_jogProcess = new JogShuttle(KdenliveSettings::shuttledevice()); - connect(m_jogProcess, SIGNAL(rewind1()), m_monitorManager, SLOT(slotRewindOneFrame())); - connect(m_jogProcess, SIGNAL(forward1()), m_monitorManager, SLOT(slotForwardOneFrame())); - connect(m_jogProcess, SIGNAL(rewind(double)), m_monitorManager, SLOT(slotRewind(double))); - connect(m_jogProcess, SIGNAL(forward(double)), m_monitorManager, SLOT(slotForward(double))); - connect(m_jogProcess, SIGNAL(stop()), m_monitorManager, SLOT(slotPlay())); - connect(m_jogProcess, SIGNAL(button(int)), this, SLOT(slotShuttleButton(int))); -} - -void MainWindow::slotShuttleButton(int code) -{ - switch (code) { - case 5: - slotShuttleAction(KdenliveSettings::shuttle1()); - break; - case 6: - slotShuttleAction(KdenliveSettings::shuttle2()); - break; - case 7: - slotShuttleAction(KdenliveSettings::shuttle3()); - break; - case 8: - slotShuttleAction(KdenliveSettings::shuttle4()); - break; - case 9: - slotShuttleAction(KdenliveSettings::shuttle5()); - break; - } -} - -void MainWindow::slotShuttleAction(int code) -{ - switch (code) { - case 0: + m_jogShuttle = new JogShuttleAction(m_jogProcess, JogShuttleConfig::actionMap(KdenliveSettings::shuttlebuttons())); + + connect(m_jogShuttle, SIGNAL(rewindOneFrame()), m_monitorManager, SLOT(slotRewindOneFrame())); + connect(m_jogShuttle, SIGNAL(forwardOneFrame()), m_monitorManager, SLOT(slotForwardOneFrame())); + connect(m_jogShuttle, SIGNAL(rewind(double)), m_monitorManager, SLOT(slotRewind(double))); + connect(m_jogShuttle, SIGNAL(forward(double)), m_monitorManager, SLOT(slotForward(double))); + connect(m_jogShuttle, SIGNAL(action(const QString&)), this, SLOT(slotDoAction(const QString&))); +} +#endif /* NO_JOGSHUTTLE */ + +void MainWindow::slotDoAction(const QString& action_name) +{ + QAction* action = actionCollection()->action(action_name); + if (!action) { + fprintf(stderr, "%s", QString("shuttle action '%1' unknown\n").arg(action_name).toAscii().constData()); return; - case 1: - m_monitorManager->slotPlay(); - break; - default: - m_monitorManager->slotPlay(); - break; } + action->trigger(); } -#endif /* NO_JOGSHUTTLE */ void MainWindow::configureNotifications() { @@ -822,13 +840,14 @@ 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(removeInvalidProxy(const QString &)), m_projectList, SLOT(slotRemoveInvalidProxy(const QString &))); - 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())); @@ -853,12 +872,34 @@ void MainWindow::slotAdjustProjectMonitor() m_projectMonitor->resetSize(); } + +class NameGrabbingKActionCollection { +public: + NameGrabbingKActionCollection(KActionCollection* collection, QStringList& action_names) + : m_collection(collection), m_action_names(action_names) { + m_action_names.clear(); + } + KAction* addAction(const QString& action_name) { + m_action_names << action_name; + return m_collection->addAction(action_name); + } + void addAction(const QString& action_name, QAction* action) { + m_action_names << action_name; + m_collection->addAction(action_name, action); + } + operator KActionCollection*() { return m_collection; } + const QStringList& actionNames() const { return m_action_names; } +private: + KActionCollection* m_collection; + QStringList& m_action_names; +}; + void MainWindow::setupActions() { - KActionCollection* collection = actionCollection(); + NameGrabbingKActionCollection collection(actionCollection(), m_action_names); m_timecodeFormat = new KComboBox(this); - m_timecodeFormat->addItem(i18n("hh:mm:ss::ff")); + m_timecodeFormat->addItem(i18n("hh:mm:ss:ff")); m_timecodeFormat->addItem(i18n("Frames")); if (KdenliveSettings::frametimecode()) m_timecodeFormat->setCurrentIndex(1); connect(m_timecodeFormat, SIGNAL(activated(int)), this, SLOT(slotUpdateTimecodeFormat(int))); @@ -1071,35 +1112,35 @@ void MainWindow::setupActions() statusBar()->addPermanentWidget(m_timecodeFormat); //statusBar()->setMaximumHeight(statusBar()->font().pointSize() * 3); - collection->addAction("normal_mode", m_normalEditTool); - collection->addAction("overwrite_mode", m_overwriteEditTool); - collection->addAction("insert_mode", m_insertEditTool); - collection->addAction("select_tool", m_buttonSelectTool); - collection->addAction("razor_tool", m_buttonRazorTool); - collection->addAction("spacer_tool", m_buttonSpacerTool); - - collection->addAction("automatic_split_audio", m_buttonAutomaticSplitAudio); - collection->addAction("show_video_thumbs", m_buttonVideoThumbs); - collection->addAction("show_audio_thumbs", m_buttonAudioThumbs); - collection->addAction("show_markers", m_buttonShowMarkers); - collection->addAction("snap", m_buttonSnap); - collection->addAction("zoom_fit", m_buttonFitZoom); - collection->addAction("zoom_in", m_zoomIn); - collection->addAction("zoom_out", m_zoomOut); + collection.addAction("normal_mode", m_normalEditTool); + collection.addAction("overwrite_mode", m_overwriteEditTool); + collection.addAction("insert_mode", m_insertEditTool); + collection.addAction("select_tool", m_buttonSelectTool); + collection.addAction("razor_tool", m_buttonRazorTool); + collection.addAction("spacer_tool", m_buttonSpacerTool); + + collection.addAction("automatic_split_audio", m_buttonAutomaticSplitAudio); + collection.addAction("show_video_thumbs", m_buttonVideoThumbs); + collection.addAction("show_audio_thumbs", m_buttonAudioThumbs); + collection.addAction("show_markers", m_buttonShowMarkers); + collection.addAction("snap", m_buttonSnap); + collection.addAction("zoom_fit", m_buttonFitZoom); + collection.addAction("zoom_in", m_zoomIn); + collection.addAction("zoom_out", m_zoomOut); m_projectSearch = new KAction(KIcon("edit-find"), i18n("Find"), this); - collection->addAction("project_find", m_projectSearch); + collection.addAction("project_find", m_projectSearch); connect(m_projectSearch, SIGNAL(triggered(bool)), this, SLOT(slotFind())); m_projectSearch->setShortcut(Qt::Key_Slash); m_projectSearchNext = new KAction(KIcon("go-down-search"), i18n("Find Next"), this); - collection->addAction("project_find_next", m_projectSearchNext); + collection.addAction("project_find_next", m_projectSearchNext); connect(m_projectSearchNext, SIGNAL(triggered(bool)), this, SLOT(slotFindNext())); m_projectSearchNext->setShortcut(Qt::Key_F3); m_projectSearchNext->setEnabled(false); KAction* profilesAction = new KAction(KIcon("document-new"), i18n("Manage Project Profiles"), this); - collection->addAction("manage_profiles", profilesAction); + collection.addAction("manage_profiles", profilesAction); connect(profilesAction, SIGNAL(triggered(bool)), this, SLOT(slotEditProfiles())); KNS3::standardAction(i18n("Download New Wipes..."), this, SLOT(slotGetNewLumaStuff()), actionCollection(), "get_new_lumas"); @@ -1108,24 +1149,24 @@ void MainWindow::setupActions() KNS3::standardAction(i18n("Download New Title Templates..."), this, SLOT(slotGetNewTitleStuff()), actionCollection(), "get_new_titles"); KAction* wizAction = new KAction(KIcon("configure"), i18n("Run Config Wizard"), this); - collection->addAction("run_wizard", wizAction); + collection.addAction("run_wizard", wizAction); connect(wizAction, SIGNAL(triggered(bool)), this, SLOT(slotRunWizard())); KAction* projectAction = new KAction(KIcon("configure"), i18n("Project Settings"), this); - collection->addAction("project_settings", projectAction); + collection.addAction("project_settings", projectAction); connect(projectAction, SIGNAL(triggered(bool)), this, SLOT(slotEditProjectSettings())); KAction* projectRender = new KAction(KIcon("media-record"), i18n("Render"), this); - collection->addAction("project_render", projectRender); + collection.addAction("project_render", projectRender); projectRender->setShortcut(Qt::CTRL + Qt::Key_Return); connect(projectRender, SIGNAL(triggered(bool)), this, SLOT(slotRenderProject())); KAction* projectClean = new KAction(KIcon("edit-clear"), i18n("Clean Project"), this); - collection->addAction("project_clean", projectClean); + collection.addAction("project_clean", projectClean); connect(projectClean, SIGNAL(triggered(bool)), this, SLOT(slotCleanProject())); KAction* projectAdjust = new KAction(KIcon(), i18n("Adjust Profile to Current Clip"), this); - collection->addAction("project_adjust_profile", projectAdjust); + collection.addAction("project_adjust_profile", projectAdjust); connect(projectAdjust, SIGNAL(triggered(bool)), m_projectList, SLOT(adjustProjectProfileToItem())); KAction* monitorPlay = new KAction(KIcon("media-playback-start"), i18n("Play"), this); @@ -1133,153 +1174,157 @@ void MainWindow::setupActions() playShortcut.setPrimary(Qt::Key_Space); playShortcut.setAlternate(Qt::Key_K); monitorPlay->setShortcut(playShortcut); - collection->addAction("monitor_play", monitorPlay); + collection.addAction("monitor_play", monitorPlay); connect(monitorPlay, SIGNAL(triggered(bool)), m_monitorManager, SLOT(slotPlay())); + KAction* monitorPause = new KAction(KIcon("media-playback-stop"), i18n("Pause"), this); + collection.addAction("monitor_pause", monitorPause); + connect(monitorPause, SIGNAL(triggered(bool)), m_monitorManager, SLOT(slotPause())); + m_playZone = new KAction(KIcon("media-playback-start"), i18n("Play Zone"), this); m_playZone->setShortcut(Qt::CTRL + Qt::Key_Space); - collection->addAction("monitor_play_zone", m_playZone); + collection.addAction("monitor_play_zone", m_playZone); connect(m_playZone, SIGNAL(triggered(bool)), m_monitorManager, SLOT(slotPlayZone())); m_loopZone = new KAction(KIcon("media-playback-start"), i18n("Loop Zone"), this); m_loopZone->setShortcut(Qt::ALT + Qt::Key_Space); - collection->addAction("monitor_loop_zone", m_loopZone); + collection.addAction("monitor_loop_zone", m_loopZone); connect(m_loopZone, SIGNAL(triggered(bool)), m_monitorManager, SLOT(slotLoopZone())); m_loopClip = new KAction(KIcon("media-playback-start"), i18n("Loop selected clip"), this); m_loopClip->setEnabled(false); - collection->addAction("monitor_loop_clip", m_loopClip); + collection.addAction("monitor_loop_clip", m_loopClip); connect(m_loopClip, SIGNAL(triggered(bool)), m_projectMonitor, SLOT(slotLoopClip())); KAction *dvdWizard = new KAction(KIcon("media-optical"), i18n("DVD Wizard"), this); - collection->addAction("dvd_wizard", dvdWizard); + collection.addAction("dvd_wizard", dvdWizard); connect(dvdWizard, SIGNAL(triggered(bool)), this, SLOT(slotDvdWizard())); KAction *transcodeClip = new KAction(KIcon("edit-copy"), i18n("Transcode Clips"), this); - collection->addAction("transcode_clip", transcodeClip); + collection.addAction("transcode_clip", transcodeClip); connect(transcodeClip, SIGNAL(triggered(bool)), this, SLOT(slotTranscodeClip())); - KAction *markIn = collection->addAction("mark_in"); + KAction *markIn = collection.addAction("mark_in"); markIn->setText(i18n("Set Zone In")); markIn->setShortcut(Qt::Key_I); connect(markIn, SIGNAL(triggered(bool)), this, SLOT(slotSetInPoint())); - KAction *markOut = collection->addAction("mark_out"); + KAction *markOut = collection.addAction("mark_out"); markOut->setText(i18n("Set Zone Out")); markOut->setShortcut(Qt::Key_O); connect(markOut, SIGNAL(triggered(bool)), this, SLOT(slotSetOutPoint())); - KAction *switchMon = collection->addAction("switch_monitor"); + KAction *switchMon = collection.addAction("switch_monitor"); switchMon->setText(i18n("Switch monitor")); switchMon->setShortcut(Qt::Key_T); connect(switchMon, SIGNAL(triggered(bool)), this, SLOT(slotSwitchMonitors())); - KAction *fullMon = collection->addAction("monitor_fullscreen"); + KAction *fullMon = collection.addAction("monitor_fullscreen"); fullMon->setText(i18n("Switch monitor fullscreen")); fullMon->setIcon(KIcon("view-fullscreen")); connect(fullMon, SIGNAL(triggered(bool)), this, SLOT(slotSwitchFullscreen())); - KAction *insertTree = collection->addAction("insert_project_tree"); + KAction *insertTree = collection.addAction("insert_project_tree"); insertTree->setText(i18n("Insert zone in project tree")); insertTree->setShortcut(Qt::CTRL + Qt::Key_I); connect(insertTree, SIGNAL(triggered(bool)), this, SLOT(slotInsertZoneToTree())); - KAction *insertTimeline = collection->addAction("insert_timeline"); + KAction *insertTimeline = collection.addAction("insert_timeline"); insertTimeline->setText(i18n("Insert zone in timeline")); insertTimeline->setShortcut(Qt::SHIFT + Qt::CTRL + Qt::Key_I); connect(insertTimeline, SIGNAL(triggered(bool)), this, SLOT(slotInsertZoneToTimeline())); KAction *resizeStart = new KAction(KIcon(), i18n("Resize Item Start"), this); - collection->addAction("resize_timeline_clip_start", resizeStart); + collection.addAction("resize_timeline_clip_start", resizeStart); resizeStart->setShortcut(Qt::Key_1); connect(resizeStart, SIGNAL(triggered(bool)), this, SLOT(slotResizeItemStart())); KAction *resizeEnd = new KAction(KIcon(), i18n("Resize Item End"), this); - collection->addAction("resize_timeline_clip_end", resizeEnd); + collection.addAction("resize_timeline_clip_end", resizeEnd); resizeEnd->setShortcut(Qt::Key_2); connect(resizeEnd, SIGNAL(triggered(bool)), this, SLOT(slotResizeItemEnd())); KAction* monitorSeekBackward = new KAction(KIcon("media-seek-backward"), i18n("Rewind"), this); monitorSeekBackward->setShortcut(Qt::Key_J); - collection->addAction("monitor_seek_backward", monitorSeekBackward); + collection.addAction("monitor_seek_backward", monitorSeekBackward); connect(monitorSeekBackward, SIGNAL(triggered(bool)), m_monitorManager, SLOT(slotRewind())); KAction* monitorSeekBackwardOneFrame = new KAction(KIcon("media-skip-backward"), i18n("Rewind 1 Frame"), this); monitorSeekBackwardOneFrame->setShortcut(Qt::Key_Left); - collection->addAction("monitor_seek_backward-one-frame", monitorSeekBackwardOneFrame); + collection.addAction("monitor_seek_backward-one-frame", monitorSeekBackwardOneFrame); connect(monitorSeekBackwardOneFrame, SIGNAL(triggered(bool)), m_monitorManager, SLOT(slotRewindOneFrame())); KAction* monitorSeekBackwardOneSecond = new KAction(KIcon("media-skip-backward"), i18n("Rewind 1 Second"), this); monitorSeekBackwardOneSecond->setShortcut(Qt::SHIFT + Qt::Key_Left); - collection->addAction("monitor_seek_backward-one-second", monitorSeekBackwardOneSecond); + collection.addAction("monitor_seek_backward-one-second", monitorSeekBackwardOneSecond); connect(monitorSeekBackwardOneSecond, SIGNAL(triggered(bool)), m_monitorManager, SLOT(slotRewindOneSecond())); KAction* monitorSeekSnapBackward = new KAction(KIcon("media-seek-backward"), i18n("Go to Previous Snap Point"), this); monitorSeekSnapBackward->setShortcut(Qt::ALT + Qt::Key_Left); - collection->addAction("monitor_seek_snap_backward", monitorSeekSnapBackward); + collection.addAction("monitor_seek_snap_backward", monitorSeekSnapBackward); connect(monitorSeekSnapBackward, SIGNAL(triggered(bool)), this, SLOT(slotSnapRewind())); KAction* monitorSeekForward = new KAction(KIcon("media-seek-forward"), i18n("Forward"), this); monitorSeekForward->setShortcut(Qt::Key_L); - collection->addAction("monitor_seek_forward", monitorSeekForward); + collection.addAction("monitor_seek_forward", monitorSeekForward); connect(monitorSeekForward, SIGNAL(triggered(bool)), m_monitorManager, SLOT(slotForward())); KAction* clipStart = new KAction(KIcon("media-seek-backward"), i18n("Go to Clip Start"), this); clipStart->setShortcut(Qt::Key_Home); - collection->addAction("seek_clip_start", clipStart); + collection.addAction("seek_clip_start", clipStart); connect(clipStart, SIGNAL(triggered(bool)), this, SLOT(slotClipStart())); KAction* clipEnd = new KAction(KIcon("media-seek-forward"), i18n("Go to Clip End"), this); clipEnd->setShortcut(Qt::Key_End); - collection->addAction("seek_clip_end", clipEnd); + collection.addAction("seek_clip_end", clipEnd); connect(clipEnd, SIGNAL(triggered(bool)), this, SLOT(slotClipEnd())); KAction* zoneStart = new KAction(KIcon("media-seek-backward"), i18n("Go to Zone Start"), this); zoneStart->setShortcut(Qt::SHIFT + Qt::Key_I); - collection->addAction("seek_zone_start", zoneStart); + collection.addAction("seek_zone_start", zoneStart); connect(zoneStart, SIGNAL(triggered(bool)), this, SLOT(slotZoneStart())); KAction* zoneEnd = new KAction(KIcon("media-seek-forward"), i18n("Go to Zone End"), this); zoneEnd->setShortcut(Qt::SHIFT + Qt::Key_O); - collection->addAction("seek_zone_end", zoneEnd); + collection.addAction("seek_zone_end", zoneEnd); connect(zoneEnd, SIGNAL(triggered(bool)), this, SLOT(slotZoneEnd())); KAction* projectStart = new KAction(KIcon("go-first"), i18n("Go to Project Start"), this); projectStart->setShortcut(Qt::CTRL + Qt::Key_Home); - collection->addAction("seek_start", projectStart); + collection.addAction("seek_start", projectStart); connect(projectStart, SIGNAL(triggered(bool)), m_monitorManager, SLOT(slotStart())); KAction* projectEnd = new KAction(KIcon("go-last"), i18n("Go to Project End"), this); projectEnd->setShortcut(Qt::CTRL + Qt::Key_End); - collection->addAction("seek_end", projectEnd); + collection.addAction("seek_end", projectEnd); connect(projectEnd, SIGNAL(triggered(bool)), m_monitorManager, SLOT(slotEnd())); KAction* monitorSeekForwardOneFrame = new KAction(KIcon("media-skip-forward"), i18n("Forward 1 Frame"), this); monitorSeekForwardOneFrame->setShortcut(Qt::Key_Right); - collection->addAction("monitor_seek_forward-one-frame", monitorSeekForwardOneFrame); + collection.addAction("monitor_seek_forward-one-frame", monitorSeekForwardOneFrame); connect(monitorSeekForwardOneFrame, SIGNAL(triggered(bool)), m_monitorManager, SLOT(slotForwardOneFrame())); KAction* monitorSeekForwardOneSecond = new KAction(KIcon("media-skip-forward"), i18n("Forward 1 Second"), this); monitorSeekForwardOneSecond->setShortcut(Qt::SHIFT + Qt::Key_Right); - collection->addAction("monitor_seek_forward-one-second", monitorSeekForwardOneSecond); + collection.addAction("monitor_seek_forward-one-second", monitorSeekForwardOneSecond); connect(monitorSeekForwardOneSecond, SIGNAL(triggered(bool)), m_monitorManager, SLOT(slotForwardOneSecond())); KAction* monitorSeekSnapForward = new KAction(KIcon("media-seek-forward"), i18n("Go to Next Snap Point"), this); monitorSeekSnapForward->setShortcut(Qt::ALT + Qt::Key_Right); - collection->addAction("monitor_seek_snap_forward", monitorSeekSnapForward); + collection.addAction("monitor_seek_snap_forward", monitorSeekSnapForward); connect(monitorSeekSnapForward, SIGNAL(triggered(bool)), this, SLOT(slotSnapForward())); KAction* deleteItem = new KAction(KIcon("edit-delete"), i18n("Delete Selected Item"), this); deleteItem->setShortcut(Qt::Key_Delete); - collection->addAction("delete_timeline_clip", deleteItem); + collection.addAction("delete_timeline_clip", deleteItem); connect(deleteItem, SIGNAL(triggered(bool)), this, SLOT(slotDeleteItem())); /*KAction* editTimelineClipSpeed = new KAction(i18n("Change Clip Speed"), this); - collection->addAction("change_clip_speed", editTimelineClipSpeed); + collection.addAction("change_clip_speed", editTimelineClipSpeed); editTimelineClipSpeed->setData("change_speed"); connect(editTimelineClipSpeed, SIGNAL(triggered(bool)), this, SLOT(slotChangeClipSpeed()));*/ - KAction *stickTransition = collection->addAction("auto_transition"); + KAction *stickTransition = collection.addAction("auto_transition"); stickTransition->setData(QString("auto")); stickTransition->setCheckable(true); stickTransition->setEnabled(false); @@ -1288,104 +1333,105 @@ void MainWindow::setupActions() KAction* groupClip = new KAction(KIcon("object-group"), i18n("Group Clips"), this); groupClip->setShortcut(Qt::CTRL + Qt::Key_G); - collection->addAction("group_clip", groupClip); + collection.addAction("group_clip", groupClip); connect(groupClip, SIGNAL(triggered(bool)), this, SLOT(slotGroupClips())); KAction* ungroupClip = new KAction(KIcon("object-ungroup"), i18n("Ungroup Clips"), this); - collection->addAction("ungroup_clip", ungroupClip); + collection.addAction("ungroup_clip", ungroupClip); ungroupClip->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_G); ungroupClip->setData("ungroup_clip"); connect(ungroupClip, SIGNAL(triggered(bool)), this, SLOT(slotUnGroupClips())); KAction* editItemDuration = new KAction(KIcon("measure"), i18n("Edit Duration"), this); - collection->addAction("edit_item_duration", editItemDuration); + collection.addAction("edit_item_duration", editItemDuration); connect(editItemDuration, SIGNAL(triggered(bool)), this, SLOT(slotEditItemDuration())); KAction* clipInProjectTree = new KAction(KIcon("go-jump-definition"), i18n("Clip in Project Tree"), this); - collection->addAction("clip_in_project_tree", clipInProjectTree); + collection.addAction("clip_in_project_tree", clipInProjectTree); connect(clipInProjectTree, SIGNAL(triggered(bool)), this, SLOT(slotClipInProjectTree())); /*KAction* clipToProjectTree = new KAction(KIcon("go-jump-definition"), i18n("Add Clip to Project Tree"), this); - collection->addAction("clip_to_project_tree", clipToProjectTree); + collection.addAction("clip_to_project_tree", clipToProjectTree); connect(clipToProjectTree, SIGNAL(triggered(bool)), this, SLOT(slotClipToProjectTree()));*/ KAction* insertOvertwrite = new KAction(KIcon(), i18n("Insert Clip Zone in Timeline (Overwrite)"), this); insertOvertwrite->setShortcut(Qt::Key_V); - collection->addAction("overwrite_to_in_point", insertOvertwrite); + collection.addAction("overwrite_to_in_point", insertOvertwrite); connect(insertOvertwrite, SIGNAL(triggered(bool)), this, SLOT(slotInsertClipOverwrite())); KAction* selectTimelineClip = new KAction(KIcon("edit-select"), i18n("Select Clip"), this); selectTimelineClip->setShortcut(Qt::Key_Plus); - collection->addAction("select_timeline_clip", selectTimelineClip); + collection.addAction("select_timeline_clip", selectTimelineClip); connect(selectTimelineClip, SIGNAL(triggered(bool)), this, SLOT(slotSelectTimelineClip())); KAction* deselectTimelineClip = new KAction(KIcon("edit-select"), i18n("Deselect Clip"), this); deselectTimelineClip->setShortcut(Qt::Key_Minus); - collection->addAction("deselect_timeline_clip", deselectTimelineClip); + collection.addAction("deselect_timeline_clip", deselectTimelineClip); connect(deselectTimelineClip, SIGNAL(triggered(bool)), this, SLOT(slotDeselectTimelineClip())); KAction* selectAddTimelineClip = new KAction(KIcon("edit-select"), i18n("Add Clip To Selection"), this); selectAddTimelineClip->setShortcut(Qt::ALT + Qt::Key_Plus); - collection->addAction("select_add_timeline_clip", selectAddTimelineClip); + collection.addAction("select_add_timeline_clip", selectAddTimelineClip); connect(selectAddTimelineClip, SIGNAL(triggered(bool)), this, SLOT(slotSelectAddTimelineClip())); KAction* selectTimelineTransition = new KAction(KIcon("edit-select"), i18n("Select Transition"), this); selectTimelineTransition->setShortcut(Qt::SHIFT + Qt::Key_Plus); - collection->addAction("select_timeline_transition", selectTimelineTransition); + collection.addAction("select_timeline_transition", selectTimelineTransition); connect(selectTimelineTransition, SIGNAL(triggered(bool)), this, SLOT(slotSelectTimelineTransition())); KAction* deselectTimelineTransition = new KAction(KIcon("edit-select"), i18n("Deselect Transition"), this); deselectTimelineTransition->setShortcut(Qt::SHIFT + Qt::Key_Minus); - collection->addAction("deselect_timeline_transition", deselectTimelineTransition); + collection.addAction("deselect_timeline_transition", deselectTimelineTransition); connect(deselectTimelineTransition, SIGNAL(triggered(bool)), this, SLOT(slotDeselectTimelineTransition())); KAction* selectAddTimelineTransition = new KAction(KIcon("edit-select"), i18n("Add Transition To Selection"), this); selectAddTimelineTransition->setShortcut(Qt::ALT + Qt::SHIFT + Qt::Key_Plus); - collection->addAction("select_add_timeline_transition", selectAddTimelineTransition); + collection.addAction("select_add_timeline_transition", selectAddTimelineTransition); connect(selectAddTimelineTransition, SIGNAL(triggered(bool)), this, SLOT(slotSelectAddTimelineTransition())); KAction* cutTimelineClip = new KAction(KIcon("edit-cut"), i18n("Cut Clip"), this); cutTimelineClip->setShortcut(Qt::SHIFT + Qt::Key_R); - collection->addAction("cut_timeline_clip", cutTimelineClip); + collection.addAction("cut_timeline_clip", cutTimelineClip); connect(cutTimelineClip, SIGNAL(triggered(bool)), this, SLOT(slotCutTimelineClip())); KAction* addClipMarker = new KAction(KIcon("bookmark-new"), i18n("Add Marker"), this); - collection->addAction("add_clip_marker", addClipMarker); + collection.addAction("add_clip_marker", addClipMarker); connect(addClipMarker, SIGNAL(triggered(bool)), this, SLOT(slotAddClipMarker())); KAction* deleteClipMarker = new KAction(KIcon("edit-delete"), i18n("Delete Marker"), this); - collection->addAction("delete_clip_marker", deleteClipMarker); + collection.addAction("delete_clip_marker", deleteClipMarker); connect(deleteClipMarker, SIGNAL(triggered(bool)), this, SLOT(slotDeleteClipMarker())); KAction* deleteAllClipMarkers = new KAction(KIcon("edit-delete"), i18n("Delete All Markers"), this); - collection->addAction("delete_all_clip_markers", deleteAllClipMarkers); + collection.addAction("delete_all_clip_markers", deleteAllClipMarkers); connect(deleteAllClipMarkers, SIGNAL(triggered(bool)), this, SLOT(slotDeleteAllClipMarkers())); KAction* editClipMarker = new KAction(KIcon("document-properties"), i18n("Edit Marker"), this); - collection->addAction("edit_clip_marker", editClipMarker); + editClipMarker->setData(QString("edit_marker")); + collection.addAction("edit_clip_marker", editClipMarker); connect(editClipMarker, SIGNAL(triggered(bool)), this, SLOT(slotEditClipMarker())); KAction *addMarkerGuideQuickly = new KAction(KIcon("bookmark-new"), i18n("Add Marker/Guide quickly"), this); addMarkerGuideQuickly->setShortcut(Qt::Key_Asterisk); - collection->addAction("add_marker_guide_quickly", addMarkerGuideQuickly); + collection.addAction("add_marker_guide_quickly", addMarkerGuideQuickly); connect(addMarkerGuideQuickly, SIGNAL(triggered(bool)), this, SLOT(slotAddMarkerGuideQuickly())); KAction* splitAudio = new KAction(KIcon("document-new"), i18n("Split Audio"), this); - collection->addAction("split_audio", splitAudio); + collection.addAction("split_audio", splitAudio); connect(splitAudio, SIGNAL(triggered(bool)), this, SLOT(slotSplitAudio())); KAction* audioOnly = new KAction(KIcon("document-new"), i18n("Audio Only"), this); - collection->addAction("clip_audio_only", audioOnly); + collection.addAction("clip_audio_only", audioOnly); audioOnly->setData("clip_audio_only"); audioOnly->setCheckable(true); KAction* videoOnly = new KAction(KIcon("document-new"), i18n("Video Only"), this); - collection->addAction("clip_video_only", videoOnly); + collection.addAction("clip_video_only", videoOnly); videoOnly->setData("clip_video_only"); videoOnly->setCheckable(true); KAction* audioAndVideo = new KAction(KIcon("document-new"), i18n("Audio and Video"), this); - collection->addAction("clip_audio_and_video", audioAndVideo); + collection.addAction("clip_audio_and_video", audioAndVideo); audioAndVideo->setData("clip_audio_and_video"); audioAndVideo->setCheckable(true); @@ -1397,54 +1443,54 @@ void MainWindow::setupActions() m_clipTypeGroup->setEnabled(false); KAction *insertSpace = new KAction(KIcon(), i18n("Insert Space"), this); - collection->addAction("insert_space", insertSpace); + collection.addAction("insert_space", insertSpace); connect(insertSpace, SIGNAL(triggered()), this, SLOT(slotInsertSpace())); KAction *removeSpace = new KAction(KIcon(), i18n("Remove Space"), this); - collection->addAction("delete_space", removeSpace); + collection.addAction("delete_space", removeSpace); connect(removeSpace, SIGNAL(triggered()), this, SLOT(slotRemoveSpace())); KAction *insertTrack = new KAction(KIcon(), i18n("Insert Track"), this); - collection->addAction("insert_track", insertTrack); + collection.addAction("insert_track", insertTrack); connect(insertTrack, SIGNAL(triggered()), this, SLOT(slotInsertTrack())); KAction *deleteTrack = new KAction(KIcon(), i18n("Delete Track"), this); - collection->addAction("delete_track", deleteTrack); + collection.addAction("delete_track", deleteTrack); connect(deleteTrack, SIGNAL(triggered()), this, SLOT(slotDeleteTrack())); KAction *configTracks = new KAction(KIcon("configure"), i18n("Configure Tracks"), this); - collection->addAction("config_tracks", configTracks); + collection.addAction("config_tracks", configTracks); connect(configTracks, SIGNAL(triggered()), this, SLOT(slotConfigTrack())); KAction *addGuide = new KAction(KIcon("document-new"), i18n("Add Guide"), this); - collection->addAction("add_guide", addGuide); + collection.addAction("add_guide", addGuide); connect(addGuide, SIGNAL(triggered()), this, SLOT(slotAddGuide())); QAction *delGuide = new KAction(KIcon("edit-delete"), i18n("Delete Guide"), this); - collection->addAction("delete_guide", delGuide); + collection.addAction("delete_guide", delGuide); connect(delGuide, SIGNAL(triggered()), this, SLOT(slotDeleteGuide())); QAction *editGuide = new KAction(KIcon("document-properties"), i18n("Edit Guide"), this); - collection->addAction("edit_guide", editGuide); + collection.addAction("edit_guide", editGuide); connect(editGuide, SIGNAL(triggered()), this, SLOT(slotEditGuide())); QAction *delAllGuides = new KAction(KIcon("edit-delete"), i18n("Delete All Guides"), this); - collection->addAction("delete_all_guides", delAllGuides); + collection.addAction("delete_all_guides", delAllGuides); connect(delAllGuides, SIGNAL(triggered()), this, SLOT(slotDeleteAllGuides())); QAction *pasteEffects = new KAction(KIcon("edit-paste"), i18n("Paste Effects"), this); - collection->addAction("paste_effects", pasteEffects); + collection.addAction("paste_effects", pasteEffects); pasteEffects->setData("paste_effects"); connect(pasteEffects , SIGNAL(triggered()), this, SLOT(slotPasteEffects())); QAction *showTimeline = new KAction(i18n("Show Timeline"), this); - collection->addAction("show_timeline", showTimeline); + collection.addAction("show_timeline", showTimeline); showTimeline->setCheckable(true); showTimeline->setChecked(true); connect(showTimeline, SIGNAL(triggered(bool)), this, SLOT(slotShowTimeline(bool))); QAction *showTitleBar = new KAction(i18n("Show Title Bars"), this); - collection->addAction("show_titlebars", showTitleBar); + collection.addAction("show_titlebars", showTitleBar); showTitleBar->setCheckable(true); connect(showTitleBar, SIGNAL(triggered(bool)), this, SLOT(slotShowTitleBars(bool))); showTitleBar->setChecked(KdenliveSettings::showtitlebars()); @@ -1454,13 +1500,13 @@ void MainWindow::setupActions() //const QByteArray state = layoutGroup.readEntry("layout1", QByteArray()); /*QAction *maxCurrent = new KAction(i18n("Maximize Current Widget"), this); - collection->addAction("maximize_current", maxCurrent); + 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); @@ -1488,55 +1534,55 @@ void MainWindow::setupActions() QAction *addClip = new KAction(KIcon("kdenlive-add-clip"), i18n("Add Clip"), this); - collection->addAction("add_clip", addClip); + collection.addAction("add_clip", addClip); connect(addClip , SIGNAL(triggered()), m_projectList, SLOT(slotAddClip())); QAction *addColorClip = new KAction(KIcon("kdenlive-add-color-clip"), i18n("Add Color Clip"), this); - collection->addAction("add_color_clip", addColorClip); + collection.addAction("add_color_clip", addColorClip); connect(addColorClip , SIGNAL(triggered()), m_projectList, SLOT(slotAddColorClip())); QAction *addSlideClip = new KAction(KIcon("kdenlive-add-slide-clip"), i18n("Add Slideshow Clip"), this); - collection->addAction("add_slide_clip", addSlideClip); + collection.addAction("add_slide_clip", addSlideClip); connect(addSlideClip , SIGNAL(triggered()), m_projectList, SLOT(slotAddSlideshowClip())); QAction *addTitleClip = new KAction(KIcon("kdenlive-add-text-clip"), i18n("Add Title Clip"), this); - collection->addAction("add_text_clip", addTitleClip); + collection.addAction("add_text_clip", addTitleClip); connect(addTitleClip , SIGNAL(triggered()), m_projectList, SLOT(slotAddTitleClip())); QAction *addTitleTemplateClip = new KAction(KIcon("kdenlive-add-text-clip"), i18n("Add Template Title"), this); - collection->addAction("add_text_template_clip", addTitleTemplateClip); + collection.addAction("add_text_template_clip", addTitleTemplateClip); connect(addTitleTemplateClip , SIGNAL(triggered()), m_projectList, SLOT(slotAddTitleTemplateClip())); QAction *addFolderButton = new KAction(KIcon("folder-new"), i18n("Create Folder"), this); - collection->addAction("add_folder", addFolderButton); + collection.addAction("add_folder", addFolderButton); connect(addFolderButton , SIGNAL(triggered()), m_projectList, SLOT(slotAddFolder())); QAction *clipProperties = new KAction(KIcon("document-edit"), i18n("Clip Properties"), this); - collection->addAction("clip_properties", clipProperties); + collection.addAction("clip_properties", clipProperties); clipProperties->setData("clip_properties"); connect(clipProperties , SIGNAL(triggered()), m_projectList, SLOT(slotEditClip())); clipProperties->setEnabled(false); QAction *openClip = new KAction(KIcon("document-open"), i18n("Edit Clip"), this); - collection->addAction("edit_clip", openClip); + collection.addAction("edit_clip", openClip); openClip->setData("edit_clip"); connect(openClip , SIGNAL(triggered()), m_projectList, SLOT(slotOpenClip())); openClip->setEnabled(false); QAction *deleteClip = new KAction(KIcon("edit-delete"), i18n("Delete Clip"), this); - collection->addAction("delete_clip", deleteClip); + collection.addAction("delete_clip", deleteClip); deleteClip->setData("delete_clip"); connect(deleteClip , SIGNAL(triggered()), m_projectList, SLOT(slotRemoveClip())); deleteClip->setEnabled(false); QAction *reloadClip = new KAction(KIcon("view-refresh"), i18n("Reload Clip"), this); - collection->addAction("reload_clip", reloadClip); + collection.addAction("reload_clip", reloadClip); reloadClip->setData("reload_clip"); connect(reloadClip , SIGNAL(triggered()), m_projectList, SLOT(slotReloadClip())); reloadClip->setEnabled(false); - QAction *stopMotion = new KAction(KIcon("image-x-generic"), i18n("Stopmotion Animation"), this); - collection->addAction("stopmotion", stopMotion); + QAction *stopMotion = new KAction(KIcon("image-x-generic"), i18n("Stop Motion Capture"), this); + collection.addAction("stopmotion", stopMotion); connect(stopMotion , SIGNAL(triggered()), this, SLOT(slotOpenStopmotion())); QMenu *addClips = new QMenu(); @@ -1555,36 +1601,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()]; @@ -1593,9 +1609,11 @@ 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() ) ); @@ -1609,12 +1627,11 @@ void MainWindow::slotDisplayActionMessage(QAction *a) void MainWindow::loadLayouts() { QMenu *saveLayout = (QMenu*)(factory()->container("layout_save_as", this)); - QMenu *loadLayout = (QMenu*)(factory()->container("layout_load", this)); - if (loadLayout == NULL || saveLayout == NULL) return; + if (m_loadLayout == NULL || saveLayout == NULL) return; KSharedConfigPtr config = KGlobal::config(); KConfigGroup layoutGroup(config, "Layouts"); QStringList entries = layoutGroup.keyList(); - QList loadActions = loadLayout->actions(); + QList loadActions = m_loadLayout->actions(); QList saveActions = saveLayout->actions(); for (int i = 1; i < 5; i++) { // Rename the layouts actions @@ -1631,7 +1648,7 @@ void MainWindow::loadLayouts() } for (int j = 0; j < saveActions.count(); j++) { if (saveActions.at(j)->data().toString().endsWith("_" + QString::number(i))) { - saveActions[j]->setText(layoutName); + saveActions[j]->setText(i18n("Save as %1").arg(layoutName)); saveActions[j]->setData(key); break; } @@ -1737,8 +1754,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; @@ -1756,11 +1782,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); + + KdenliveDoc *doc = new KdenliveDoc(KUrl(), projectFolder, m_commandStack, profileName, documentProperties, projectTracks, m_projectMonitor->render, m_notesWidget, this); doc->m_autosave = new KAutoSaveFile(KUrl(), doc); bool ok; TrackView *trackView = new TrackView(doc, &ok, this); @@ -1845,15 +1879,8 @@ bool MainWindow::saveFileAs(const QString &outputFileName) { QString currentSceneList; m_monitorManager->stopActiveMonitor(); - if (KdenliveSettings::dropbframes()) { - KdenliveSettings::setDropbframes(false); - m_activeDocument->clipManager()->updatePreviewSettings(); - currentSceneList = m_projectMonitor->sceneList(); - KdenliveSettings::setDropbframes(true); - m_activeDocument->clipManager()->updatePreviewSettings(); - } else currentSceneList = m_projectMonitor->sceneList(); - - if (m_activeDocument->saveSceneList(outputFileName, currentSceneList) == false) + + if (m_activeDocument->saveSceneList(outputFileName, m_projectMonitor->sceneList(), m_projectList->expandedFolders()) == false) return false; // Save timeline thumbnails @@ -1967,6 +1994,12 @@ void MainWindow::doOpenFile(const KUrl &url, KAutoSaveFile *stale) if (!m_timelineArea->isEnabled()) return; m_fileRevert->setEnabled(true); + // Recreate stopmotion widget on document change + if (m_stopmotion) { + delete m_stopmotion; + m_stopmotion = NULL; + } + KProgressDialog progressDialog(this, i18n("Loading project"), i18n("Loading project")); progressDialog.setAllowCancel(false); progressDialog.progressBar()->setMaximum(4); @@ -1974,7 +2007,7 @@ 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); + KdenliveDoc *doc = new KdenliveDoc(url, KdenliveSettings::defaultprojectfolder(), m_commandStack, KdenliveSettings::default_profile(), QMap (), QPoint(KdenliveSettings::videotracks(), KdenliveSettings::audiotracks()), m_projectMonitor->render, m_notesWidget, this, &progressDialog); progressDialog.progressBar()->setValue(1); progressDialog.progressBar()->setMaximum(4); @@ -2155,6 +2188,39 @@ 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_activeDocument->rebuildAllProxies(); + } + } + 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; } @@ -2163,6 +2229,12 @@ void MainWindow::slotUpdateProjectProfile(const QString &profile) { double dar = m_activeDocument->dar(); + // Recreate the stopmotion widget if profile changes + if (m_stopmotion) { + delete m_stopmotion; + m_stopmotion = NULL; + } + // Deselect current effect / transition m_effectStack->slotClipItemSelected(NULL, 0); m_transitionConfig->slotTransitionItemSelected(NULL, 0, QPoint(), false); @@ -2195,7 +2267,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&))); @@ -2333,11 +2405,12 @@ 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()); @@ -2347,7 +2420,8 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha 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())); @@ -2449,7 +2523,6 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha #ifndef Q_WS_MAC m_recMonitor->slotUpdateCaptureFolder(m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash)); #endif - if (KdenliveSettings::dropbframes()) slotUpdatePreviewSettings(); //Update the mouse position display so it will display in DF/NDF format by default based on the project setting. slotUpdateMousePosition(0); // set tool to select tool @@ -2483,6 +2556,7 @@ void MainWindow::slotPreferences(int page, int option) * cached, in which case you want to display the cached dialog * instead of creating another one */ + if (m_stopmotion) m_stopmotion->slotLive(false); if (KConfigDialog::showDialog("settings")) { KdenliveSettingsDialog* d = static_cast (KConfigDialog::exists("settings")); if (page != -1) d->showPage(page, option); @@ -2491,15 +2565,20 @@ void MainWindow::slotPreferences(int page, int option) // KConfigDialog didn't find an instance of this dialog, so lets // create it : - KdenliveSettingsDialog* dialog = new KdenliveSettingsDialog(this); + + // Get the mappable actions in localized form + QMap actions; + KActionCollection* collection = actionCollection(); + foreach (const QString& action_name, m_action_names) { + actions[collection->action(action_name)->text()] = action_name; + } + + KdenliveSettingsDialog* dialog = new KdenliveSettingsDialog(actions, this); connect(dialog, SIGNAL(settingsChanged(const QString&)), this, SLOT(updateConfiguration())); - //connect(dialog, SIGNAL(doResetProfile()), this, SLOT(slotDetectAudioDriver())); connect(dialog, SIGNAL(doResetProfile()), m_monitorManager, SLOT(slotResetProfiles())); - connect(dialog, SIGNAL(updatePreviewSettings()), this, SLOT(slotUpdatePreviewSettings())); #ifndef Q_WS_MAC connect(dialog, SIGNAL(updateCaptureFolder()), this, SLOT(slotUpdateCaptureFolder())); #endif - //connect(dialog, SIGNAL(updatePreviewSettings()), this, SLOT(slotUpdatePreviewSettings())); dialog->show(); if (page != -1) dialog->showPage(page, option); } @@ -2513,14 +2592,6 @@ void MainWindow::slotUpdateCaptureFolder() #endif } -void MainWindow::slotUpdatePreviewSettings() -{ - if (m_activeDocument) { - m_clipMonitor->slotSetXml(NULL); - m_activeDocument->updatePreviewSettings(); - } -} - void MainWindow::updateConfiguration() { //TODO: we should apply settings to all projects, not only the current one @@ -2903,10 +2974,20 @@ 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); + + 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::slotAddAudioEffect(QAction *result) @@ -3065,6 +3146,17 @@ 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. + if (KMessageBox::questionYesNo(this, i18n("You are editing an external title clip (%1). Do you want to save your changes to the title file or save the changes for this project only?", path), i18n("Save Title"), KGuiItem(i18n("Save to title file")), KGuiItem(i18n("Save in project only"))) == KMessageBox::Yes) { + // save to external file + dia_ui->saveTitle(path); + } else newprops.insert("resource", QString()); } EditClipCommand *command = new EditClipCommand(m_projectList, clip->getId(), clip->properties(), newprops, true); m_activeDocument->commandStack()->push(command); @@ -3105,9 +3197,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++) @@ -3664,16 +3764,14 @@ void MainWindow::slotPrepareRendering(bool scriptExport, bool zoneOnly, const QS return; } playlistPath = scriptPath + ".mlt"; - m_projectMonitor->saveSceneList(playlistPath); } else { KTemporaryFile temp; temp.setAutoRemove(false); temp.setSuffix(".mlt"); temp.open(); playlistPath = temp.fileName(); - m_projectMonitor->saveSceneList(playlistPath); } - + QString playlistContent = m_projectMonitor->sceneList(); if (!chapterFile.isEmpty()) { int in = 0; int out; @@ -3728,6 +3826,32 @@ void MainWindow::slotPrepareRendering(bool scriptExport, bool zoneOnly, const QS if (m_renderWidget->automaticAudioExport()) { exportAudio = m_activeTimeline->checkProjectAudio(); } else exportAudio = m_renderWidget->selectedAudioExport(); + + // Do we want proxy rendering + if (m_projectList->useProxy() && !m_renderWidget->proxyRendering()) { + // replace proxy clips with originals + QMap proxies = m_projectList->getProxies(); + 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()); + } + } + + // Do save scenelist + QFile file(playlistPath); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + m_messageLabel->setMessage(i18n("Cannot write to file %1").arg(playlistPath), ErrorMessage); + return; + } + file.write(playlistContent.toUtf8()); + if (file.error() != QFile::NoError) { + m_messageLabel->setMessage(i18n("Cannot write to file %1").arg(playlistPath), ErrorMessage); + file.close(); + return; + } + file.close(); m_renderWidget->slotExport(scriptExport, m_activeTimeline->inPoint(), m_activeTimeline->outPoint(), playlistPath, scriptPath, exportAudio); } @@ -3786,9 +3910,9 @@ void MainWindow::slotChangePalette(QAction *action, const QString &themename) KdenliveSettings::setColortheme(theme); // Make palette for all widgets. QPalette plt; - if (theme.isEmpty()) + if (theme.isEmpty()) { plt = QApplication::desktop()->palette(); - else { + } else { KSharedConfigPtr config = KSharedConfig::openConfig(theme); plt = KGlobalSettings::createApplicationPalette(config); } @@ -3928,38 +4052,42 @@ void MainWindow::slotMonitorRequestRenderFrame(bool request) m_projectMonitor->render->sendFrameForAnalysis = true; return; } else { - for (int i = 0; i < m_scopesList.count(); i++) { - if (m_scopesList.at(i)->isVisible() && tabifiedDockWidgets(m_scopesList.at(i)).isEmpty() && static_cast(m_scopesList.at(i)->widget())->autoRefreshEnabled()) { + for (int i = 0; i < m_gfxScopesList.count(); i++) { + if (m_gfxScopesList.at(i)->isVisible() && tabifiedDockWidgets(m_gfxScopesList.at(i)).isEmpty() && static_cast(m_gfxScopesList.at(i)->widget())->autoRefreshEnabled()) { request = true; break; } } } +#ifdef DEBUG_MAINW + qDebug() << "Any scope accepting new frames? " << request; +#endif if (!request) { m_projectMonitor->render->sendFrameForAnalysis = false; } } -void MainWindow::slotUpdateScopeFrameRequest() +void MainWindow::slotUpdateGfxScopeFrameRequest() { // We need a delay to make sure widgets are hidden after a close event for example - QTimer::singleShot(500, this, SLOT(slotDoUpdateScopeFrameRequest())); + QTimer::singleShot(500, this, SLOT(slotDoUpdateGfxScopeFrameRequest())); } -void MainWindow::slotDoUpdateScopeFrameRequest() +void MainWindow::slotDoUpdateGfxScopeFrameRequest() { // Check scopes bool request = false; - for (int i = 0; i < m_scopesList.count(); i++) { - if (!m_scopesList.at(i)->widget()->visibleRegion().isEmpty() && static_cast(m_scopesList.at(i)->widget())->autoRefreshEnabled()) { - kDebug() << "SCOPE VISIBLE: " << static_cast(m_scopesList.at(i)->widget())->widgetName(); + for (int i = 0; i < m_gfxScopesList.count(); i++) { + if (!m_gfxScopesList.at(i)->widget()->visibleRegion().isEmpty() && static_cast(m_gfxScopesList.at(i)->widget())->autoRefreshEnabled()) { + kDebug() << "SCOPE VISIBLE: " << static_cast(m_gfxScopesList.at(i)->widget())->widgetName(); request = true; break; } } if (!request) { - if (!m_projectMonitor->effectSceneDisplayed()) + if (!m_projectMonitor->effectSceneDisplayed()) { m_projectMonitor->render->sendFrameForAnalysis = false; + } m_clipMonitor->render->sendFrameForAnalysis = false; } else { m_projectMonitor->render->sendFrameForAnalysis = true; @@ -3967,13 +4095,40 @@ void MainWindow::slotDoUpdateScopeFrameRequest() } } +void MainWindow::slotUpdateAudioScopeFrameRequest() +{ + QTimer::singleShot(500, this, SLOT(slotDoUpdateAudioScopeFrameRequest())); +} + +void MainWindow::slotDoUpdateAudioScopeFrameRequest() +{ + bool request = false; + for (int i = 0; i < m_audioScopesList.count(); i++) { + if (!m_audioScopesList.at(i)->visibleRegion().isEmpty() && m_audioScopesList.at(i)->autoRefreshEnabled()) { + kDebug() << "AUDIO SCOPE VISIBLE: " << m_audioScopesList.at(i)->widgetName(); + request = true; + break; + } + } + // Handle audio signal separately (no common interface) + if (!m_audiosignal->visibleRegion().isEmpty() && m_audiosignal->monitoringEnabled()) { + kDebug() << "AUDIO SCOPE VISIBLE: " << "audiosignal"; + request = true; + } +#ifdef DEBUG_MAINW + qDebug() << "Scopes Requesting Audio data: " << request; +#endif + KdenliveSettings::setMonitor_audio(request); + m_monitorManager->slotUpdateAudioMonitoring(); +} + void MainWindow::slotUpdateColorScopes() { bool request = false; - for (int i = 0; i < m_scopesList.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; - static_cast(m_scopesList.at(i)->widget())->slotActiveMonitorChanged(m_clipMonitor->isActive()); + 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()); } if (request) { if (m_clipMonitor->isActive()) m_clipMonitor->render->sendFrameUpdate(); @@ -3984,13 +4139,18 @@ void MainWindow::slotUpdateColorScopes() void MainWindow::slotOpenStopmotion() { if (m_stopmotion == NULL) { - m_stopmotion = new StopmotionWidget(m_activeDocument->projectFolder(), this); + m_stopmotion = new StopmotionWidget(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++) { + // 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))); + //static_cast(m_scopesList.at(i)->widget())->slotMonitorCapture(); + } } m_stopmotion->show(); } - void MainWindow::slotDeleteClip(const QString &id) { QList list = findChildren(); @@ -4000,5 +4160,16 @@ void MainWindow::slotDeleteClip(const QString &id) m_projectList->slotDeleteClip(id); } +void MainWindow::slotUpdateProxySettings() +{ + if (m_renderWidget) m_renderWidget->updateProxyConfig(m_projectList->useProxy()); + if (KdenliveSettings::enableproxy()) + KStandardDirs::makeDir(m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash) + "proxy/"); + m_projectList->updateProxyConfig(); +} + #include "mainwindow.moc" +#ifdef DEBUG_MAINW +#undef DEBUG_MAINW +#endif