X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmainwindow.cpp;h=dd1d83c94587c9c460ff0e36ffad29afec2a9228;hb=a3eee7be24126f5a3458d488f44cd61c66135e17;hp=e1ab4dc9f4e961297dda7bf46973e1cceeea4252;hpb=525c7c608d9f74d569ecbe88f8565eee5d3bfec4;p=kdenlive diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index e1ab4dc9..dd1d83c9 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -37,7 +37,7 @@ #include "effectslistview.h" #include "effectstack/effectstackview2.h" #include "transitionsettings.h" -#include "renderwidget.h" +#include "widgets/renderwidget.h" #include "renderer.h" #ifdef USE_JOGSHUTTLE #include "jogshuttle.h" @@ -47,7 +47,7 @@ #include "clipproperties.h" #include "wizard.h" #include "commands/editclipcommand.h" -#include "titlewidget.h" +#include "widgets/titlewidget.h" #include "markerdialog.h" #include "clipitem.h" #include "interfaces.h" @@ -62,14 +62,14 @@ #include "scopes/audioscopes/audiosignal.h" #include "scopes/audioscopes/audiospectrum.h" #include "scopes/audioscopes/spectrogram.h" -#include "archivewidget.h" +#include "widgets/archivewidget.h" #include "databackup/backupwidget.h" #include "utils/resourcewidget.h" #include #include -#include +#include #include #include #include @@ -113,6 +113,8 @@ #include #include #include +#include +#include #include #include @@ -126,7 +128,6 @@ static const char version[] = VERSION; -static const int ID_TIMELINE_POS = 0; namespace Mlt { class Producer; @@ -142,8 +143,14 @@ EffectsList MainWindow::transitions; QMap MainWindow::m_lumacache; +static bool sortByNames(const QPair &a, const QPair &b) +{ + return a.first < b.first; +} + MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & clipsToLoad, QWidget *parent) : KXmlGuiWindow(parent), + m_glContext(NULL), m_activeDocument(NULL), m_activeTimeline(NULL), m_projectList(NULL), @@ -153,12 +160,13 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_projectMonitor(NULL), m_recMonitor(NULL), m_renderWidget(NULL), -#ifdef USE_JOGSHUTTLE + #ifdef USE_JOGSHUTTLE m_jogProcess(NULL), m_jogShuttle(NULL), -#endif + #endif m_findActivated(false), - m_stopmotion(NULL) + m_stopmotion(NULL), + m_mainClip(NULL) { qRegisterMetaType > (); qRegisterMetaType ("stringMap"); @@ -171,9 +179,9 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & if (separator != systemLocale.decimalPoint()) { kDebug()<<"------\n!!! system locale is not similar to Qt's locale... be prepared for bugs!!!\n------"; // HACK: There is a locale conflict, so set locale to C - // Make sure to override exported values or it won't work - setenv("LANG", "C", 1); - setlocale(LC_NUMERIC, "C"); + // Make sure to override exported values or it won't work + setenv("LANG", "C", 1); + setlocale(LC_NUMERIC, "C"); systemLocale = QLocale::c(); } @@ -189,6 +197,12 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & setFont(KGlobalSettings::toolBarFont()); parseProfiles(MltPath); KdenliveSettings::setCurrent_profile(KdenliveSettings::default_profile()); + + // Create OpenGL context, to have a common context all the other contexts + // can share with. + m_glContext = new QGLWidget(this); + m_glContext->resize(0, 0); + m_commandStack = new QUndoGroup; setDockNestingEnabled(true); m_timelineArea = new KTabWidget(this); @@ -222,41 +236,41 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_projectListDock = new QDockWidget(i18n("Project Tree"), this); m_projectListDock->setObjectName("project_tree"); - m_projectList = new ProjectList(); + m_projectList = new ProjectList(m_glContext); m_projectListDock->setWidget(m_projectList); addDockWidget(Qt::TopDockWidgetArea, m_projectListDock); m_clipMonitorDock = new QDockWidget(i18n("Clip Monitor"), this); m_clipMonitorDock->setObjectName("clip_monitor"); - m_clipMonitor = new Monitor(Kdenlive::clipMonitor, m_monitorManager, QString(), m_timelineArea); + m_clipMonitor = new Monitor(Kdenlive::ClipMonitor, m_monitorManager, m_glContext, QString(), m_timelineArea); m_clipMonitorDock->setWidget(m_clipMonitor); // Connect the project list - connect(m_projectList, SIGNAL(clipSelected(DocClipBase *, QPoint, bool)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint, bool))); - connect(m_projectList, SIGNAL(raiseClipMonitor()), m_clipMonitor, SLOT(slotActivateMonitor())); + connect(m_projectList, SIGNAL(clipSelected(DocClipBase*,QPoint,bool)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase*,QPoint,bool))); + connect(m_projectList, SIGNAL(raiseClipMonitor(bool)), m_clipMonitor, SLOT(slotActivateMonitor(bool))); connect(m_projectList, SIGNAL(loadingIsOver()), this, SLOT(slotElapsedTime())); - connect(m_projectList, SIGNAL(displayMessage(const QString&, int)), this, SLOT(slotGotProgressInfo(const QString&, int))); + connect(m_projectList, SIGNAL(displayMessage(QString,int,MessageType)), this, SLOT(slotGotProgressInfo(QString,int,MessageType))); connect(m_projectList, SIGNAL(updateRenderStatus()), this, SLOT(slotCheckRenderStatus())); - connect(m_projectList, SIGNAL(clipNeedsReload(const QString&)),this, SLOT(slotUpdateClip(const QString &))); - connect(m_projectList, SIGNAL(updateProfile(const QString &)), this, SLOT(slotUpdateProjectProfile(const QString &))); - connect(m_projectList, SIGNAL(refreshClip(const QString &, bool)), m_monitorManager, SLOT(slotRefreshCurrentMonitor(const QString &))); - connect(m_projectList, SIGNAL(findInTimeline(const QString&)), this, SLOT(slotClipInTimeline(const QString&))); + connect(m_projectList, SIGNAL(clipNeedsReload(QString)),this, SLOT(slotUpdateClip(QString))); + connect(m_projectList, SIGNAL(updateProfile(QString)), this, SLOT(slotUpdateProjectProfile(QString))); + connect(m_projectList, SIGNAL(refreshClip(QString,bool)), m_monitorManager, SLOT(slotRefreshCurrentMonitor(QString))); + connect(m_projectList, SIGNAL(findInTimeline(QString)), this, SLOT(slotClipInTimeline(QString))); connect(m_clipMonitor, SIGNAL(zoneUpdated(QPoint)), m_projectList, SLOT(slotUpdateClipCut(QPoint))); - connect(m_clipMonitor, SIGNAL(extractZone(const QString &, QPoint)), m_projectList, SLOT(slotCutClipJob(const QString &, QPoint))); + connect(m_clipMonitor, SIGNAL(extractZone(QString,QPoint)), m_projectList, SLOT(slotCutClipJob(QString,QPoint))); m_projectMonitorDock = new QDockWidget(i18n("Project Monitor"), this); m_projectMonitorDock->setObjectName("project_monitor"); - m_projectMonitor = new Monitor(Kdenlive::projectMonitor, m_monitorManager, QString()); + m_projectMonitor = new Monitor(Kdenlive::ProjectMonitor, m_monitorManager, m_glContext, QString()); m_projectMonitorDock->setWidget(m_projectMonitor); #ifndef Q_WS_MAC m_recMonitorDock = new QDockWidget(i18n("Record Monitor"), this); m_recMonitorDock->setObjectName("record_monitor"); - m_recMonitor = new RecMonitor(Kdenlive::recordMonitor, m_monitorManager); + m_recMonitor = new RecMonitor(Kdenlive::RecordMonitor, m_monitorManager); m_recMonitorDock->setWidget(m_recMonitor); connect(m_recMonitor, SIGNAL(addProjectClip(KUrl)), this, SLOT(slotAddProjectClip(KUrl))); connect(m_recMonitor, SIGNAL(addProjectClipList(KUrl::List)), this, SLOT(slotAddProjectClipList(KUrl::List))); - connect(m_recMonitor, SIGNAL(showConfigDialog(int, int)), this, SLOT(slotPreferences(int, int))); + connect(m_recMonitor, SIGNAL(showConfigDialog(int,int)), this, SLOT(slotPreferences(int,int))); #endif /* ! Q_WS_MAC */ m_monitorManager->initMonitors(m_clipMonitor, m_projectMonitor, m_recMonitor); @@ -279,7 +293,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_effectStack = new EffectStackView2(m_projectMonitor); m_effectStackDock->setWidget(m_effectStack); addDockWidget(Qt::TopDockWidgetArea, m_effectStackDock); - connect(m_effectStack, SIGNAL(startFilterJob(ItemInfo, const QString&,const QString&,const QString&,const QString&,const QString&,const QString&,const QString&)), m_projectList, SLOT(slotStartFilterJob(ItemInfo, const QString&,const QString&,const QString&,const QString&,const QString&,const QString&,const QString&))); + connect(m_effectStack, SIGNAL(startFilterJob(ItemInfo,QString,QString,QString,QString,QString,QMap)), m_projectList, SLOT(slotStartFilterJob(ItemInfo,QString,QString,QString,QString,QString,QMap))); m_transitionConfigDock = new QDockWidget(i18n("Transition"), this); m_transitionConfigDock->setObjectName("transition"); @@ -390,7 +404,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & #endif setCentralWidget(m_timelineArea); - m_fileOpenRecent = KStandardAction::openRecent(this, SLOT(openFile(const KUrl &)), actionCollection()); + m_fileOpenRecent = KStandardAction::openRecent(this, SLOT(openFile(KUrl)), actionCollection()); readOptions(); m_fileRevert = KStandardAction::revert(this, SLOT(slotRevert()), actionCollection()); m_fileRevert->setEnabled(false); @@ -398,10 +412,10 @@ 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++) { + for (int i = 1; i < 5; ++i) { KAction *load = new KAction(KIcon(), i18n("Layout %1", 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", i), this); save->setData('_' + QString::number(i)); @@ -431,16 +445,16 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_effectList->reloadEffectList(m_effectsMenu, m_effectActions); m_effectsActionCollection->readSettings(); - // Populate View menu with show / hide actions for dock widgets + // Populate View menu with show / hide actions for dock widgets KActionCategory *guiActions = new KActionCategory(i18n("Interface"), actionCollection()); setupGUI(); // Find QDockWidget tab bars and show / hide widget title bars on right click QList tabs = findChildren(); - for (int i = 0; i < tabs.count(); i++) { + for (int i = 0; i < tabs.count(); ++i) { tabs.at(i)->setContextMenuPolicy(Qt::CustomContextMenu); - connect(tabs.at(i), SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(slotSwitchTitles())); + connect(tabs.at(i), SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(slotSwitchTitles())); } /*ScriptingPart* sp = new ScriptingPart(this, QStringList()); @@ -459,19 +473,19 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & loadPlugins(); loadTranscoders(); - loadStabilize(); + loadClipActions(); 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))); QMenu *clipInTimeline = static_cast(factory()->container("clip_in_timeline", this)); clipInTimeline->setIcon(KIcon("go-jump")); - QHash menus; - menus.insert("addMenu",static_cast(factory()->container("generators", this))); - menus.insert("extractAudioMenu",static_cast(factory()->container("extract_audio", this))); - menus.insert("transcodeMenu",static_cast(factory()->container("transcoders", this))); - menus.insert("stabilizeMenu",static_cast(factory()->container("stabilize", this))); - menus.insert("inTimelineMenu",clipInTimeline); + QHash menus; + menus.insert("addMenu",static_cast(factory()->container("generators", this))); + menus.insert("extractAudioMenu",static_cast(factory()->container("extract_audio", this))); + menus.insert("transcodeMenu",static_cast(factory()->container("transcoders", this))); + menus.insert("clipActionsMenu",static_cast(factory()->container("clip_actions", this))); + menus.insert("inTimelineMenu",clipInTimeline); m_projectList->setupGeneratorMenu(menus); // build themes menus @@ -515,7 +529,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & if (KdenliveSettings::colortheme() == *it) action->setChecked(true); }*/ themesMenu->addActions(themegroup->actions()); - connect(themesMenu, SIGNAL(triggered(QAction *)), this, SLOT(slotChangePalette(QAction*))); + connect(themesMenu, SIGNAL(triggered(QAction*)), this, SLOT(slotChangePalette(QAction*))); // Setup and fill effects and transitions menus. @@ -528,9 +542,9 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & for (int i = 0; i < transitions.count(); ++i) m_transitionsMenu->addAction(m_transitions[i]); - 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 *))); + 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*))); m_timelineContextMenu = new QMenu(this); m_timelineContextClipMenu = new QMenu(this); @@ -542,7 +556,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_timelineContextClipMenu->addAction(actionCollection()->action("clip_in_project_tree")); //m_timelineContextClipMenu->addAction(actionCollection()->action("clip_to_project_tree")); - m_timelineContextClipMenu->addAction(actionCollection()->action("delete_item")); + m_timelineContextClipMenu->addAction(actionCollection()->action("delete_timeline_clip")); m_timelineContextClipMenu->addSeparator(); m_timelineContextClipMenu->addAction(actionCollection()->action("group_clip")); m_timelineContextClipMenu->addAction(actionCollection()->action("ungroup_clip")); @@ -561,41 +575,18 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & m_timelineContextClipMenu->addMenu(m_transitionsMenu); m_timelineContextClipMenu->addMenu(m_effectsMenu); - m_timelineContextTransitionMenu->addAction(actionCollection()->action("delete_item")); + m_timelineContextTransitionMenu->addAction(actionCollection()->action("delete_timeline_clip")); m_timelineContextTransitionMenu->addAction(actionCollection()->action(KStandardAction::name(KStandardAction::Copy))); m_timelineContextTransitionMenu->addAction(actionCollection()->action("auto_transition")); connect(m_projectMonitorDock, SIGNAL(visibilityChanged(bool)), m_projectMonitor, SLOT(refreshMonitor(bool))); connect(m_clipMonitorDock, SIGNAL(visibilityChanged(bool)), m_clipMonitor, SLOT(refreshMonitor(bool))); - connect(m_effectList, SIGNAL(addEffect(const QDomElement)), this, SLOT(slotAddEffect(const QDomElement))); + connect(m_effectList, SIGNAL(addEffect(QDomElement)), this, SLOT(slotAddEffect(QDomElement))); connect(m_effectList, SIGNAL(reloadEffects()), this, SLOT(slotReloadEffects())); slotConnectMonitors(); - // 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. - if (!Url.isEmpty()) { - // delay loading so that the window shows up - m_startUrl = Url; - QTimer::singleShot(500, this, SLOT(openFile())); - } else if (KdenliveSettings::openlastproject()) { - QTimer::singleShot(500, this, SLOT(openLastFile())); - } else { //if (m_timelineArea->count() == 0) { - newFile(false); - } - - if (!clipsToLoad.isEmpty() && m_activeDocument) { - QStringList list = clipsToLoad.split(','); - QList urls; - foreach(const QString &path, list) { - kDebug() << QDir::current().absoluteFilePath(path); - urls << QUrl::fromLocalFile(QDir::current().absoluteFilePath(path)); - } - m_projectList->slotAddClip(urls); - } - #ifdef USE_JOGSHUTTLE activateShuttleDevice(); #endif @@ -604,35 +595,43 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & actionCollection()->addAssociatedWidget(m_clipMonitor->container()); actionCollection()->addAssociatedWidget(m_projectMonitor->container()); - QMap viewActions; + QList > viewActions; + QPair pair; KAction *showTimeline = new KAction(i18n("Timeline"), this); showTimeline->setCheckable(true); showTimeline->setChecked(true); connect(showTimeline, SIGNAL(triggered(bool)), this, SLOT(slotShowTimeline(bool))); - viewActions.insert(showTimeline->text(), showTimeline); + + KMenu *viewMenu = static_cast(factory()->container("dockwindows", this)); + pair.first = showTimeline->text(); + pair.second = showTimeline; + viewActions.append(pair); QList docks = findChildren(); - for (int i = 0; i < docks.count(); i++) { + for (int i = 0; i < docks.count(); ++i) { QDockWidget* dock = docks.at(i); - KAction* dockInformations = new KAction(this); - dockInformations->setText(dock->windowTitle()); - dockInformations->setCheckable(true); - dockInformations->setChecked(!dock->isHidden()); - connect(dockInformations,SIGNAL(toggled(bool)), dock, SLOT(setVisible(bool))); - viewActions.insert(dockInformations->text(), dockInformations); - } - - - KMenu *viewMenu = static_cast(factory()->container("dockwindows", this)); - //const QList viewActions = createPopupMenu()->actions(); - QMap::const_iterator i = viewActions.constBegin(); - while (i != viewActions.constEnd()) { - viewMenu->addAction(guiActions->addAction(i.key(), i.value())); - ++i; + QAction * a = dock->toggleViewAction(); + if (!a) continue; + KAction* dockInformations = new KAction(this); + dockInformations->setText(a->text()); + dockInformations->setCheckable(true); + dockInformations->setChecked(!dock->isHidden()); + // HACK: since QActions cannot be used in KActionCategory to allow shortcut, we create a duplicate KAction of the dock QAction and link them + connect(a,SIGNAL(toggled(bool)), dockInformations, SLOT(setChecked(bool))); + connect(dockInformations,SIGNAL(triggered(bool)), a, SLOT(trigger())); + pair.first = dockInformations->text(); + pair.second = dockInformations; + viewActions.append(pair); } + // Sort dock view action by name + qSort(viewActions.begin(), viewActions.end(), sortByNames); + // Populate view menu + for (int i = 0; i < viewActions.count(); ++i) + viewMenu->addAction(guiActions->addAction(viewActions.at(i).first, viewActions.at(i).second)); + // Populate encoding profiles - KConfig conf("encodingprofiles.rc", KConfig::FullConfig, "appdata"); + KConfig conf("encodingprofiles.rc", KConfig::CascadeConfig, "appdata"); if (KdenliveSettings::proxyparams().isEmpty() || KdenliveSettings::proxyextension().isEmpty()) { KConfigGroup group(&conf, "proxy"); QMap< QString, QString > values = group.entryMap(); @@ -655,6 +654,17 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & KdenliveSettings::setV4l_extension(data.section(';', 1, 1)); } } + if (KdenliveSettings::grab_parameters().isEmpty() || KdenliveSettings::grab_extension().isEmpty()) { + KConfigGroup group(&conf, "screengrab"); + QMap< QString, QString > values = group.entryMap(); + QMapIterator i(values); + if (i.hasNext()) { + i.next(); + QString data = i.value(); + KdenliveSettings::setGrab_parameters(data.section(';', 0, 0)); + KdenliveSettings::setGrab_extension(data.section(';', 1, 1)); + } + } if (KdenliveSettings::decklink_parameters().isEmpty() || KdenliveSettings::decklink_extension().isEmpty()) { KConfigGroup group(&conf, "decklink"); QMap< QString, QString > values = group.entryMap(); @@ -668,13 +678,39 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & } connect (KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()), this, SLOT(slotChangePalette())); + + // 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. + if (!Url.isEmpty()) { + // delay loading so that the window shows up + m_startUrl = Url; + QTimer::singleShot(500, this, SLOT(openFile())); + } else if (KdenliveSettings::openlastproject()) { + QTimer::singleShot(500, this, SLOT(openLastFile())); + } else { //if (m_timelineArea->count() == 0) { + newFile(false); + } + + if (!clipsToLoad.isEmpty() && m_activeDocument) { + QStringList list = clipsToLoad.split(','); + QList urls; + foreach(const QString &path, list) { + kDebug() << QDir::current().absoluteFilePath(path); + urls << QUrl::fromLocalFile(QDir::current().absoluteFilePath(path)); + } + m_projectList->slotAddClip(urls); + } } MainWindow::~MainWindow() { - if (m_stopmotion) { - delete m_stopmotion; - } + delete m_stopmotion; + +#ifdef USE_JOGSHUTTLE + delete m_jogProcess; +#endif + m_effectStack->slotClipItemSelected(NULL); m_transitionConfig->slotTransitionItemSelected(NULL, 0, QPoint(), false); @@ -692,6 +728,7 @@ MainWindow::~MainWindow() delete m_monitorManager; delete m_scopeManager; Mlt::Factory::close(); + delete m_glContext; } //virtual @@ -714,7 +751,10 @@ bool MainWindow::queryClose() } } saveOptions(); - if (m_monitorManager) m_monitorManager->stopActiveMonitor(); + if (m_monitorManager) { + m_monitorManager->stopActiveMonitor(); + } + // warn the user to save if document is modified and we have clips in our project list if (m_activeDocument && m_activeDocument->isModified() && ((m_projectList->documentClipList().isEmpty() && !m_activeDocument->url().isEmpty()) || @@ -722,10 +762,11 @@ bool MainWindow::queryClose() raise(); activateWindow(); QString message; - if (m_activeDocument->url().fileName().isEmpty()) + if (m_activeDocument->url().fileName().isEmpty()) { message = i18n("Save changes to document?"); - else + } else { message = i18n("The project \"%1\" has been changed.\nDo you want to save your changes?", m_activeDocument->url().fileName()); + } switch (KMessageBox::warningYesNoCancel(this, message)) { case KMessageBox::Yes : // save document here. If saving fails, return false; @@ -812,8 +853,8 @@ void MainWindow::generateClip() QAction *action = qobject_cast(sender()); ClipGenerator *iGenerator = qobject_cast(action->parent()); - KUrl clipUrl = iGenerator->generatedClip(action->data().toString(), m_activeDocument->projectFolder(), - QStringList(), QStringList(), m_activeDocument->fps(), m_activeDocument->width(), m_activeDocument->height()); + KUrl clipUrl = iGenerator->generatedClip(KdenliveSettings::rendererpath(), action->data().toString(), m_activeDocument->projectFolder(), + QStringList(), QStringList(), m_activeDocument->fps(), m_activeDocument->width(), m_activeDocument->height()); if (!clipUrl.isEmpty()) { m_projectList->slotAddClip(QList () << clipUrl); } @@ -850,14 +891,14 @@ void MainWindow::activateShuttleDevice() m_jogProcess = NULL; if (KdenliveSettings::enableshuttle() == false) return; - m_jogProcess = new JogShuttle(KdenliveSettings::shuttledevice()); + m_jogProcess = new JogShuttle(JogShuttle::canonicalDevice(KdenliveSettings::shuttledevice())); 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&))); + connect(m_jogShuttle, SIGNAL(action(QString)), this, SLOT(slotDoAction(QString))); } #endif /* USE_JOGSHUTTLE */ @@ -881,7 +922,7 @@ void MainWindow::slotFullScreen() KToggleFullScreenAction::setFullScreen(this, actionCollection()->action("fullscreen")->isChecked()); } -void MainWindow::slotAddEffect(const QDomElement effect) +void MainWindow::slotAddEffect(const QDomElement &effect) { if (!m_activeDocument) return; if (effect.isNull()) { @@ -897,10 +938,16 @@ void MainWindow::slotAddEffect(const QDomElement effect) void MainWindow::slotUpdateClip(const QString &id) { - if (!m_activeDocument) return; + if (!m_activeDocument) { + return; + } DocClipBase *clip = m_activeDocument->clipManager()->getClipById(id); - if (!clip) return; - if (clip->numReferences() > 0) m_activeTimeline->projectView()->slotUpdateClip(id); + if (!clip) { + return; + } + if (clip->numReferences() > 0) { + m_activeTimeline->projectView()->slotUpdateClip(id); + } if (m_clipMonitor->activeClip() && m_clipMonitor->activeClip()->getId() == id) { Mlt::Producer *monitorProducer = clip->getCloneProducer(); m_clipMonitor->updateClipProducer(monitorProducer); @@ -911,28 +958,28 @@ void MainWindow::slotUpdateClip(const QString &id) void MainWindow::slotConnectMonitors() { m_projectList->setRenderer(m_projectMonitor->render); - 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_projectMonitor->render, SIGNAL(replyGetImage(const QString &, const QString &, int, int)), m_projectList, SLOT(slotReplyGetImage(const QString &, const QString &, int, int))); - connect(m_projectMonitor->render, SIGNAL(replyGetImage(const QString &, const QImage &)), m_projectList, SLOT(slotReplyGetImage(const QString &, const QImage &))); + connect(m_projectList, SIGNAL(pauseMonitor()), m_monitorManager, SLOT(slotPause())); + 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_projectMonitor->render, SIGNAL(replyGetImage(QString,QString,int,int)), m_projectList, SLOT(slotReplyGetImage(QString,QString,int,int))); + connect(m_projectMonitor->render, SIGNAL(replyGetImage(QString,QImage)), m_projectList, SLOT(slotReplyGetImage(QString,QImage))); - kDebug()<<" - - - - - -\n CONNECTED REPLY"; - connect(m_projectMonitor->render, SIGNAL(replyGetFileProperties(const QString &, Mlt::Producer*, const stringMap &, const stringMap &, bool)), m_projectList, SLOT(slotReplyGetFileProperties(const QString &, Mlt::Producer*, const stringMap &, const stringMap &, bool))); + connect(m_projectMonitor->render, SIGNAL(replyGetFileProperties(QString,Mlt::Producer*,stringMap,stringMap,bool)), m_projectList, SLOT(slotReplyGetFileProperties(QString,Mlt::Producer*,stringMap,stringMap,bool))); - connect(m_projectMonitor->render, SIGNAL(removeInvalidClip(const QString &, bool)), m_projectList, SLOT(slotRemoveInvalidClip(const QString &, bool))); + connect(m_projectMonitor->render, SIGNAL(removeInvalidClip(QString,bool)), m_projectList, SLOT(slotRemoveInvalidClip(QString,bool))); - connect(m_projectMonitor->render, SIGNAL(removeInvalidProxy(const QString &, bool)), m_projectList, SLOT(slotRemoveInvalidProxy(const QString &, bool))); + connect(m_projectMonitor->render, SIGNAL(removeInvalidProxy(QString,bool)), m_projectList, SLOT(slotRemoveInvalidProxy(QString,bool))); - connect(m_clipMonitor, SIGNAL(refreshClipThumbnail(const QString &, bool)), m_projectList, SLOT(slotRefreshClipThumbnail(const QString &, bool))); + connect(m_clipMonitor, SIGNAL(refreshClipThumbnail(QString,bool)), m_projectList, SLOT(slotRefreshClipThumbnail(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, DocClipBase *)), this, SLOT(slotSaveZone(Render *, QPoint, DocClipBase *))); - connect(m_projectMonitor, SIGNAL(saveZone(Render *, QPoint, DocClipBase *)), this, SLOT(slotSaveZone(Render *, QPoint, DocClipBase *))); + 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() @@ -952,35 +999,28 @@ void MainWindow::slotAdjustProjectMonitor() 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; } + 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; + KActionCollection* m_collection; + QStringList& m_action_names; }; void MainWindow::setupActions() { - NameGrabbingKActionCollection collection(actionCollection(), m_action_names); - m_timecodeFormat = new KComboBox(this); - 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))); - m_statusProgressBar = new QProgressBar(this); m_statusProgressBar->setMinimum(0); m_statusProgressBar->setMaximum(100); @@ -992,7 +1032,7 @@ void MainWindow::setupActions() setStatusBarStyleSheet(palette()); QString styleBorderless = "QToolButton { border-width: 0px;margin: 1px 3px 0px;padding: 0px;}"; - + //create edit mode buttons m_normalEditTool = new KAction(KIcon("kdenlive-normal-edit"), i18n("Normal mode"), this); m_normalEditTool->setShortcut(i18nc("Normal editing", "n")); @@ -1019,7 +1059,7 @@ void MainWindow::setupActions() editGroup->addAction(m_overwriteEditTool); editGroup->addAction(m_insertEditTool); editGroup->setExclusive(true); - connect(editGroup, SIGNAL(triggered(QAction *)), this, SLOT(slotChangeEdit(QAction *))); + connect(editGroup, SIGNAL(triggered(QAction*)), this, SLOT(slotChangeEdit(QAction*))); //connect(m_overwriteEditTool, SIGNAL(toggled(bool)), this, SLOT(slotSetOverwriteMode(bool))); toolbar->addSeparator(); @@ -1076,7 +1116,7 @@ void MainWindow::setupActions() actionWidget->setMaximumWidth(max); actionWidget->setMaximumHeight(max - 4); - connect(toolGroup, SIGNAL(triggered(QAction *)), this, SLOT(slotChangeTool(QAction *))); + connect(toolGroup, SIGNAL(triggered(QAction*)), this, SLOT(slotChangeTool(QAction*))); toolbar->addSeparator(); m_buttonFitZoom = new KAction(KIcon("zoom-fit-best"), i18n("Fit zoom to project"), this); @@ -1180,9 +1220,21 @@ void MainWindow::setupActions() statusBar()->addWidget(m_messageLabel, 10); statusBar()->addWidget(m_statusProgressBar, 0); statusBar()->addPermanentWidget(toolbar); - statusBar()->insertPermanentFixedItem("00:00:00:00", ID_TIMELINE_POS); - statusBar()->addPermanentWidget(m_timecodeFormat); - //statusBar()->setMaximumHeight(statusBar()->font().pointSize() * 3); + + m_timeFormatButton = new KSelectAction("00:00:00:00 / 00:00:00:00", this); + m_timeFormatButton->addAction(i18n("hh:mm:ss:ff")); + m_timeFormatButton->addAction(i18n("Frames")); + if (KdenliveSettings::frametimecode()) m_timeFormatButton->setCurrentItem(1); + else m_timeFormatButton->setCurrentItem(0); + connect(m_timeFormatButton, SIGNAL(triggered(int)), this, SLOT(slotUpdateTimecodeFormat(int))); + m_timeFormatButton->setToolBarMode(KSelectAction::MenuMode); + toolbar->addAction(m_timeFormatButton); + + const QFontMetrics metric(statusBar()->font()); + int requiredWidth = metric.boundingRect("00:00:00:00 / 00:00:00:00").width() + 20; + actionWidget = toolbar->widgetForAction(m_timeFormatButton); + actionWidget->setObjectName("timecode"); + actionWidget->setMinimumWidth(requiredWidth); collection.addAction("normal_mode", m_normalEditTool); collection.addAction("overwrite_mode", m_overwriteEditTool); @@ -1246,14 +1298,12 @@ void MainWindow::setupActions() connect(projectAdjust, SIGNAL(triggered(bool)), m_projectList, SLOT(adjustProjectProfileToItem())); KAction* monitorPlay = new KAction(KIcon("media-playback-start"), i18n("Play"), this); - KShortcut playShortcut; - playShortcut.setPrimary(Qt::Key_Space); - playShortcut.setAlternate(Qt::Key_K); - monitorPlay->setShortcut(playShortcut); + monitorPlay->setShortcut(Qt::Key_Space); 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); + monitorPause->setShortcut(Qt::Key_K); collection.addAction("monitor_pause", monitorPause); connect(monitorPause, SIGNAL(triggered(bool)), m_monitorManager, SLOT(slotPause())); @@ -1304,6 +1354,30 @@ void MainWindow::setupActions() fullMon->setText(i18n("Switch monitor fullscreen")); fullMon->setIcon(KIcon("view-fullscreen")); connect(fullMon, SIGNAL(triggered(bool)), m_monitorManager, SLOT(slotSwitchFullscreen())); + + KSelectAction *interlace = new KSelectAction(i18n("Deinterlacer"), this); + interlace->addAction(i18n("One Field (fast)")); + interlace->addAction(i18n("Linear Blend (fast)")); + interlace->addAction(i18n("YADIF - temporal only (good)")); + interlace->addAction(i18n("YADIF - temporal + spacial (best)")); + if (KdenliveSettings::mltdeinterlacer() == "linearblend") interlace->setCurrentItem(1); + else if (KdenliveSettings::mltdeinterlacer() == "yadif-temporal") interlace->setCurrentItem(2); + else if (KdenliveSettings::mltdeinterlacer() == "yadif") interlace->setCurrentItem(3); + else interlace->setCurrentItem(0); + collection.addAction("mlt_interlace", interlace); + connect(interlace, SIGNAL(triggered(int)), this, SLOT(slotSetDeinterlacer(int))); + + KSelectAction *interpol = new KSelectAction(i18n("Interpolation"), this); + interpol->addAction(i18n("Nearest Neighbor (fast)")); + interpol->addAction(i18n("Bilinear (good)")); + interpol->addAction(i18n("Bicubic (better)")); + interpol->addAction(i18n("Hyper/Lanczos (best)")); + if (KdenliveSettings::mltinterpolation() == "bilinear") interpol->setCurrentItem(1); + else if (KdenliveSettings::mltinterpolation() == "bicubic") interpol->setCurrentItem(2); + else if (KdenliveSettings::mltinterpolation() == "hyper") interpol->setCurrentItem(3); + else interpol->setCurrentItem(0); + collection.addAction("mlt_interpolation", interpol); + connect(interpol, SIGNAL(triggered(int)), this, SLOT(slotSetInterpolation(int))); KAction *insertTree = collection.addAction("insert_project_tree"); insertTree->setText(i18n("Insert zone in project tree")); @@ -1400,6 +1474,11 @@ void MainWindow::setupActions() collection.addAction("delete_timeline_clip", deleteItem); connect(deleteItem, SIGNAL(triggered(bool)), this, SLOT(slotDeleteItem())); + KAction* alignPlayhead = new KAction(i18n("Align Playhead to Mouse Position"), this); + alignPlayhead->setShortcut(Qt::Key_P); + collection.addAction("align_playhead", alignPlayhead); + connect(alignPlayhead, SIGNAL(triggered(bool)), this, SLOT(slotAlignPlayheadToMousePos())); + /*KAction* editTimelineClipSpeed = new KAction(i18n("Change Clip Speed"), this); collection.addAction("change_clip_speed", editTimelineClipSpeed); editTimelineClipSpeed->setData("change_speed"); @@ -1503,14 +1582,20 @@ void MainWindow::setupActions() KAction* splitAudio = new KAction(KIcon("document-new"), i18n("Split Audio"), this); collection.addAction("split_audio", splitAudio); + // "A+V" as data means this action should only be available for clips with audio AND video + splitAudio->setData("A+V"); connect(splitAudio, SIGNAL(triggered(bool)), this, SLOT(slotSplitAudio())); KAction* setAudioAlignReference = new KAction(i18n("Set Audio Reference"), this); collection.addAction("set_audio_align_ref", setAudioAlignReference); + // "A" as data means this action should only be available for clips with audio + setAudioAlignReference->setData("A"); connect(setAudioAlignReference, SIGNAL(triggered()), this, SLOT(slotSetAudioAlignReference())); KAction* alignAudio = new KAction(i18n("Align Audio to Reference"), this); collection.addAction("align_audio", alignAudio); + // "A" as data means this action should only be available for clips with audio + alignAudio->setData("A"); connect(alignAudio, SIGNAL(triggered()), this, SLOT(slotAlignAudio())); KAction* audioOnly = new KAction(KIcon("document-new"), i18n("Audio Only"), this); @@ -1532,7 +1617,7 @@ void MainWindow::setupActions() m_clipTypeGroup->addAction(audioOnly); m_clipTypeGroup->addAction(videoOnly); m_clipTypeGroup->addAction(audioAndVideo); - connect(m_clipTypeGroup, SIGNAL(triggered(QAction *)), this, SLOT(slotUpdateClipType(QAction *))); + connect(m_clipTypeGroup, SIGNAL(triggered(QAction*)), this, SLOT(slotUpdateClipType(QAction*))); m_clipTypeGroup->setEnabled(false); KAction *insertSpace = new KAction(KIcon(), i18n("Insert Space"), this); @@ -1706,7 +1791,7 @@ void MainWindow::setupActions() //KActionCategory *transitionActions = new KActionCategory(i18n("Transitions"), m_effectsActionCollection); KActionCategory *transitionActions = new KActionCategory(i18n("Transitions"), collection); m_transitions = new KAction*[transitions.count()]; - for (int i = 0; i < transitions.count(); i++) { + for (int i = 0; i < transitions.count(); ++i) { QStringList effectInfo = transitions.effectIdInfo(i); m_transitions[i] = new KAction(effectInfo.at(0), this); m_transitions[i]->setData(effectInfo); @@ -1731,7 +1816,7 @@ void MainWindow::setStatusBarStyleSheet(const QPalette &p) QColor buttonBord = scheme.foreground(KColorScheme::LinkText).color(); QColor buttonBord2 = scheme.shade(KColorScheme::LightShade); statusBar()->setStyleSheet(QString("QStatusBar QLabel {font-size:%1pt;} QStatusBar::item { border: 0px; font-size:%1pt;padding:0px; }").arg(statusBar()->font().pointSize())); - QString style1 = QString("QToolBar { border: 0px } QToolButton { border-style: inset; border:1px solid transparent;border-radius: 3px;margin: 0px 3px;padding: 0px;} QToolButton:hover { background: %3;border-style: inset; border:1px solid %3;border-radius: 3px;} QToolButton:checked { background-color: %1; border-style: inset; border:1px solid %2;border-radius: 3px;}").arg(buttonBg.name()).arg(buttonBord.name()).arg(buttonBord2.name()); + QString style1 = QString("QToolBar { border: 0px } QToolButton { border-style: inset; border:1px solid transparent;border-radius: 3px;margin: 0px 3px;padding: 0px;} QToolButton#timecode {padding-right:10px;} QToolButton:hover { background: %3;border-style: inset; border:1px solid %3;border-radius: 3px;} QToolButton:checked { background-color: %1; border-style: inset; border:1px solid %2;border-radius: 3px;}").arg(buttonBg.name()).arg(buttonBord.name()).arg(buttonBord2.name()); statusBar()->setStyleSheet(style1); } @@ -1744,7 +1829,7 @@ void MainWindow::loadLayouts() QStringList entries = layoutGroup.keyList(); QList loadActions = m_loadLayout->actions(); QList saveActions = saveLayout->actions(); - for (int i = 1; i < 5; i++) { + for (int i = 1; i < 5; ++i) { // Rename the layouts actions foreach(const QString & key, entries) { if (key.endsWith(QString("_%1").arg(i))) { @@ -1771,9 +1856,15 @@ void MainWindow::loadLayouts() void MainWindow::slotLoadLayout(QAction *action) { - if (!action) return; + if (!action) { + return; + } + QString layoutId = action->data().toString(); - if (layoutId.isEmpty()) return; + if (layoutId.isEmpty()) { + return; + } + KSharedConfigPtr config = KGlobal::config(); KConfigGroup layouts(config, "Layouts"); QByteArray state = QByteArray::fromBase64(layouts.readEntry(layoutId).toAscii()); @@ -1786,7 +1877,9 @@ void MainWindow::slotSaveLayout(QAction *action) int layoutId = originallayoutName.section('_', -1).toInt(); QString layoutName = QInputDialog::getText(this, i18n("Save Layout"), i18n("Layout name:"), QLineEdit::Normal, originallayoutName.section('_', 0, -2)); - if (layoutName.isEmpty()) return; + if (layoutName.isEmpty()) { + return; + } KSharedConfigPtr config = KGlobal::config(); KConfigGroup layouts(config, "Layouts"); layouts.deleteEntry(originallayoutName); @@ -1824,12 +1917,17 @@ void MainWindow::readOptions() QString path = QDir::homePath() + "/kdenlive"; if (KStandardDirs::makeDir(path) == false) { kDebug() << "/// ERROR CREATING PROJECT FOLDER: " << path; - } else KdenliveSettings::setDefaultprojectfolder(path); + } else { + KdenliveSettings::setDefaultprojectfolder(path); + } } } + } + if (KdenliveSettings::ffmpegpath().isEmpty() || KdenliveSettings::ffplaypath().isEmpty()) { + upgrade = true; } - if (KdenliveSettings::ffmpegpath().isEmpty() || KdenliveSettings::ffplaypath().isEmpty()) upgrade = true; + if (!initialGroup.exists() || upgrade) { // this is our first run, show Wizard QPointer w = new Wizard(upgrade, this); @@ -1842,10 +1940,12 @@ void MainWindow::readOptions() ::exit(1); } } + KConfigGroup treecolumns(config, "Project Tree"); const QByteArray state = treecolumns.readEntry("columns", QByteArray()); - if (!state.isEmpty()) + if (!state.isEmpty()) { m_projectList->setHeaderInfo(state); + } } void MainWindow::slotRunWizard() @@ -1859,8 +1959,9 @@ void MainWindow::slotRunWizard() void MainWindow::newFile(bool showProjectSettings, bool force) { - if (!m_timelineArea->isEnabled() && !force) + if (!m_timelineArea->isEnabled() && !force) { return; + } m_fileRevert->setEnabled(false); QString profileName = KdenliveSettings::default_profile(); KUrl projectFolder = KdenliveSettings::defaultprojectfolder(); @@ -1868,24 +1969,29 @@ void MainWindow::newFile(bool showProjectSettings, bool force) QMap documentMetadata; QPoint projectTracks(KdenliveSettings::videotracks(), KdenliveSettings::audiotracks()); if (!showProjectSettings) { - if (!KdenliveSettings::activatetabs()) - if (!closeCurrentDocument()) + if (!KdenliveSettings::activatetabs()) { + if (!closeCurrentDocument()) { return; + } + } } else { QPointer w = new ProjectSettings(NULL, QMap (), QStringList(), projectTracks.x(), projectTracks.y(), KdenliveSettings::defaultprojectfolder(), false, true, this); if (w->exec() != QDialog::Accepted) { delete w; return; } - if (!KdenliveSettings::activatetabs()) + if (!KdenliveSettings::activatetabs()) { if (!closeCurrentDocument()) { delete w; return; } - if (KdenliveSettings::videothumbnails() != w->enableVideoThumbs()) + } + if (KdenliveSettings::videothumbnails() != w->enableVideoThumbs()) { slotSwitchVideoThumbs(); - if (KdenliveSettings::audiothumbnails() != w->enableAudioThumbs()) + } + if (KdenliveSettings::audiothumbnails() != w->enableAudioThumbs()) { slotSwitchAudioThumbs(); + } profileName = w->selectedProfile(); projectFolder = w->selectedFolder(); projectTracks = w->tracks(); @@ -1902,7 +2008,7 @@ void MainWindow::newFile(bool showProjectSettings, bool force) m_timelineArea->setEnabled(true); m_projectList->setEnabled(true); bool openBackup; - KdenliveDoc *doc = new KdenliveDoc(KUrl(), projectFolder, m_commandStack, profileName, documentProperties, documentMetadata, projectTracks, m_projectMonitor->render, m_notesWidget, &openBackup, this); + KdenliveDoc *doc = new KdenliveDoc(KUrl(), projectFolder, m_commandStack, profileName, documentProperties, documentMetadata, projectTracks, m_projectMonitor->render, m_notesWidget, &openBackup, m_glContext, this); doc->m_autosave = new KAutoSaveFile(KUrl(), doc); bool ok; TrackView *trackView = new TrackView(doc, m_tracksActionCollection->actions(), &ok, this); @@ -1917,15 +2023,18 @@ void MainWindow::newFile(bool showProjectSettings, bool force) if (m_timelineArea->count() == 1) { connectDocumentInfo(doc); connectDocument(trackView, doc); - } else + } else { m_timelineArea->setTabBarHidden(false); - m_monitorManager->activateMonitor(Kdenlive::clipMonitor); + } + m_monitorManager->activateMonitor(Kdenlive::ClipMonitor); m_closeAction->setEnabled(m_timelineArea->count() > 1); } void MainWindow::activateDocument() { - if (m_timelineArea->currentWidget() == NULL || !m_timelineArea->isEnabled()) return; + if (m_timelineArea->currentWidget() == NULL || !m_timelineArea->isEnabled()) { + return; + } TrackView *currentTab = (TrackView *) m_timelineArea->currentWidget(); KdenliveDoc *currentDoc = currentTab->document(); connectDocumentInfo(currentDoc); @@ -1935,19 +2044,25 @@ void MainWindow::activateDocument() bool MainWindow::closeCurrentDocument(bool saveChanges) { QWidget *w = m_timelineArea->currentWidget(); - if (!w) return true; + if (!w) { + return true; + } // closing current document int ix = m_timelineArea->currentIndex() + 1; - if (ix == m_timelineArea->count()) ix = 0; + if (ix == m_timelineArea->count()) { + ix = 0; + } m_timelineArea->setCurrentIndex(ix); TrackView *tabToClose = (TrackView *) w; KdenliveDoc *docToClose = tabToClose->document(); if (docToClose && docToClose->isModified() && saveChanges) { QString message; - if (m_activeDocument->url().fileName().isEmpty()) + if (m_activeDocument->url().fileName().isEmpty()) { message = i18n("Save changes to document?"); - else + } else { message = i18n("The project \"%1\" has been changed.\nDo you want to save your changes?", m_activeDocument->url().fileName()); + } + switch (KMessageBox::warningYesNoCancel(this, message)) { case KMessageBox::Yes : // save document here. If saving fails, return false; @@ -1960,6 +2075,8 @@ bool MainWindow::closeCurrentDocument(bool saveChanges) break; } } + + slotTimelineClipSelected(NULL, false); m_clipMonitor->slotSetClipProducer(NULL); m_projectList->slotResetProjectList(); m_timelineArea->removeTab(m_timelineArea->indexOf(w)); @@ -1967,30 +2084,34 @@ bool MainWindow::closeCurrentDocument(bool saveChanges) m_timelineArea->setTabBarHidden(true); m_closeAction->setEnabled(false); } + if (docToClose == m_activeDocument) { delete m_activeDocument; m_activeDocument = NULL; + m_monitorManager->setDocument(m_activeDocument); m_effectStack->clear(); m_transitionConfig->slotTransitionItemSelected(NULL, 0, QPoint(), false); } else { delete docToClose; } + if (w == m_activeTimeline) { delete m_activeTimeline; m_activeTimeline = NULL; } else { delete w; } + return true; } bool MainWindow::saveFileAs(const QString &outputFileName) { - QString currentSceneList; m_monitorManager->stopActiveMonitor(); - if (m_activeDocument->saveSceneList(outputFileName, m_projectMonitor->sceneList(), m_projectList->expandedFolders()) == false) + if (m_activeDocument->saveSceneList(outputFileName, m_projectMonitor->sceneList(), m_projectList->expandedFolders()) == false) { return false; + } // Save timeline thumbnails m_activeTimeline->projectView()->saveThumbnails(); @@ -1998,7 +2119,10 @@ bool MainWindow::saveFileAs(const QString &outputFileName) QByteArray hash = QCryptographicHash::hash(KUrl(outputFileName).encodedPath(), QCryptographicHash::Md5).toHex(); if (m_activeDocument->m_autosave == NULL) { m_activeDocument->m_autosave = new KAutoSaveFile(KUrl(hash), this); - } else m_activeDocument->m_autosave->setManagedFile(KUrl(hash)); + } else { + m_activeDocument->m_autosave->setManagedFile(KUrl(hash)); + } + setCaption(m_activeDocument->description()); m_timelineArea->setTabText(m_timelineArea->currentIndex(), m_activeDocument->description()); m_timelineArea->setTabToolTip(m_timelineArea->currentIndex(), m_activeDocument->url().path()); @@ -2006,6 +2130,7 @@ bool MainWindow::saveFileAs(const QString &outputFileName) m_fileOpenRecent->addUrl(KUrl(outputFileName)); m_fileRevert->setEnabled(true); m_undoView->stack()->setClean(); + return true; } @@ -2015,17 +2140,23 @@ bool MainWindow::saveFileAs() if (outputFile.isEmpty()) { return false; } + if (QFile::exists(outputFile)) { // Show the file dialog again if the user does not want to overwrite the file - if (KMessageBox::questionYesNo(this, i18n("File %1 already exists.\nDo you want to overwrite it?", outputFile)) == KMessageBox::No) + if (KMessageBox::questionYesNo(this, i18n("File %1 already exists.\nDo you want to overwrite it?", outputFile)) == KMessageBox::No) { return saveFileAs(); + } } + return saveFileAs(outputFile); } bool MainWindow::saveFile() { - if (!m_activeDocument) return true; + if (!m_activeDocument) { + return true; + } + if (m_activeDocument->url().isEmpty()) { return saveFileAs(); } else { @@ -2043,18 +2174,28 @@ void MainWindow::openFile() return; } KUrl url = KFileDialog::getOpenUrl(KUrl("kfiledialog:///projectfolder"), getMimeType()); - if (url.isEmpty()) return; + if (url.isEmpty()) { + return; + } + m_fileOpenRecent->addUrl(url); openFile(url); } void MainWindow::openLastFile() { - KSharedConfigPtr config = KGlobal::config(); - KUrl::List urls = m_fileOpenRecent->urls(); - //WARNING: this is buggy, we get a random url, not the last one. Bug in KRecentFileAction? - if (urls.isEmpty()) newFile(false); - else openFile(urls.last()); + if (m_fileOpenRecent->selectableActionGroup()->actions().isEmpty()) { + // No files in history + newFile(false); + return; + } + + QAction *firstUrlAction = m_fileOpenRecent->selectableActionGroup()->actions().last(); + if (firstUrlAction) { + firstUrlAction->trigger(); + } else { + newFile(false); + } } void MainWindow::openFile(const KUrl &url) @@ -2065,13 +2206,23 @@ void MainWindow::openFile(const KUrl &url) // Opening a compressed project file, we need to process it kDebug()<<"Opening archive, processing"; QPointer ar = new ArchiveWidget(url); - if (ar->exec() == QDialog::Accepted) openFile(KUrl(ar->extractedProjectFile())); + if (ar->exec() == QDialog::Accepted) { + openFile(KUrl(ar->extractedProjectFile())); + } else if (!m_startUrl.isEmpty()) { + // we tried to open an invalid file from command line, init new project + newFile(false); + } 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())); + if (!m_startUrl.isEmpty()) { + // we tried to open an invalid file from command line, init new project + newFile(false); + } return; } @@ -2079,7 +2230,7 @@ void MainWindow::openFile(const KUrl &url) const int ct = m_timelineArea->count(); bool isOpened = false; int i; - for (i = 0; i < ct; i++) { + for (i = 0; i < ct; ++i) { TrackView *tab = (TrackView *) m_timelineArea->widget(i); KdenliveDoc *doc = tab->document(); if (doc->url() == url) { @@ -2087,12 +2238,17 @@ void MainWindow::openFile(const KUrl &url) break; } } + if (isOpened) { m_timelineArea->setCurrentIndex(i); return; } - if (!KdenliveSettings::activatetabs()) if (!closeCurrentDocument()) return; + if (!KdenliveSettings::activatetabs()) { + if (!closeCurrentDocument()) { + return; + } + } // Check for backup file QByteArray hash = QCryptographicHash::hash(url.encodedPath(), QCryptographicHash::Md5).toHex(); @@ -2134,15 +2290,14 @@ void MainWindow::doOpenFile(const KUrl &url, KAutoSaveFile *stale) progressDialog.progressBar()->setMaximum(4); progressDialog.show(); progressDialog.progressBar()->setValue(0); - qApp->processEvents(); bool openBackup; - KdenliveDoc *doc = new KdenliveDoc(stale ? KUrl(stale->fileName()) : url, KdenliveSettings::defaultprojectfolder(), m_commandStack, KdenliveSettings::default_profile(), QMap (), QMap (), QPoint(KdenliveSettings::videotracks(), KdenliveSettings::audiotracks()), m_projectMonitor->render, m_notesWidget, &openBackup, this, &progressDialog); + KdenliveDoc *doc = new KdenliveDoc(stale ? KUrl(stale->fileName()) : url, KdenliveSettings::defaultprojectfolder(), m_commandStack, KdenliveSettings::default_profile(), QMap (), QMap (), QPoint(KdenliveSettings::videotracks(), KdenliveSettings::audiotracks()), m_projectMonitor->render, m_notesWidget, &openBackup, m_glContext, this, &progressDialog); progressDialog.progressBar()->setValue(1); progressDialog.progressBar()->setMaximum(4); progressDialog.setLabelText(i18n("Loading project")); - qApp->processEvents(); + progressDialog.repaint(); if (stale == NULL) { QByteArray hash = QCryptographicHash::hash(url.encodedPath(), QCryptographicHash::Md5).toHex(); @@ -2157,13 +2312,13 @@ void MainWindow::doOpenFile(const KUrl &url, KAutoSaveFile *stale) connectDocumentInfo(doc); progressDialog.progressBar()->setValue(2); - qApp->processEvents(); + progressDialog.repaint(); bool ok; TrackView *trackView = new TrackView(doc, m_tracksActionCollection->actions(), &ok, this); connectDocument(trackView, doc); progressDialog.progressBar()->setValue(3); - qApp->processEvents(); + progressDialog.repaint(); m_timelineArea->setCurrentIndex(m_timelineArea->addTab(trackView, KIcon("kdenlive"), doc->description())); if (!ok) { @@ -2176,17 +2331,21 @@ void MainWindow::doOpenFile(const KUrl &url, KAutoSaveFile *stale) } m_timelineArea->setTabToolTip(m_timelineArea->currentIndex(), doc->url().path()); trackView->setDuration(trackView->duration()); - trackView->projectView()->initCursorPos(m_projectMonitor->render->seekPosition().frames(doc->fps())); - if (m_timelineArea->count() > 1) m_timelineArea->setTabBarHidden(false); + if (m_timelineArea->count() > 1) { + m_timelineArea->setTabBarHidden(false); + } + slotGotProgressInfo(QString(), -1); m_projectMonitor->adjustRulerSize(trackView->duration()); m_projectMonitor->slotZoneMoved(trackView->inPoint(), trackView->outPoint()); progressDialog.progressBar()->setValue(4); - if (openBackup) slotOpenBackupDialog(url); + if (openBackup) { + slotOpenBackupDialog(url); + } } -void MainWindow::recoverFiles(QList staleFiles, const KUrl &originUrl) +void MainWindow::recoverFiles(const QList &staleFiles, const KUrl &originUrl) { foreach(KAutoSaveFile * stale, staleFiles) { /*if (!stale->open(QIODevice::QIODevice::ReadOnly)) { @@ -2197,8 +2356,11 @@ void MainWindow::recoverFiles(QList staleFiles, const KUrl &ori }*/ kDebug() << "// OPENING RECOVERY: " << stale->fileName() << "\nMANAGED: " << stale->managedFile().path(); // the stalefiles also contain ".lock" files so we must ignore them... bug in KAutoSaveFile? - if (!stale->fileName().endsWith(".lock")) doOpenFile(originUrl, stale); - else KIO::NetAccess::del(KUrl(stale->fileName()), this); + if (!stale->fileName().endsWith(".lock")) { + doOpenFile(originUrl, stale); + } else { + KIO::NetAccess::del(KUrl(stale->fileName()), this); + } } } @@ -2210,13 +2372,15 @@ void MainWindow::parseProfiles(const QString &mltPath) KdenliveSettings::setRendererpath(mltPath + "/bin/melt"); } - if (KdenliveSettings::mltpath().isEmpty()) + if (KdenliveSettings::mltpath().isEmpty()) { KdenliveSettings::setMltpath(QString(MLT_PREFIX) + QString("/share/mlt/profiles/")); + } if (KdenliveSettings::rendererpath().isEmpty() || KdenliveSettings::rendererpath().endsWith("inigo")) { QString meltPath = QString(MLT_PREFIX) + QString("/bin/melt"); - if (!QFile::exists(meltPath)) + if (!QFile::exists(meltPath)) { meltPath = KStandardDirs::findExe("melt"); + } KdenliveSettings::setRendererpath(meltPath); } @@ -2263,7 +2427,9 @@ void MainWindow::parseProfiles(const QString &mltPath) kDebug() << "RESULTING MLT PATH: " << KdenliveSettings::mltpath(); // Parse again MLT profiles to build a list of available video formats - if (profilesList.isEmpty()) parseProfiles(); + if (profilesList.isEmpty()) { + parseProfiles(); + } } @@ -2272,7 +2438,9 @@ void MainWindow::slotEditProfiles() ProfilesDialog *w = new ProfilesDialog; if (w->exec() == QDialog::Accepted) { KdenliveSettingsDialog* d = static_cast (KConfigDialog::exists("settings")); - if (d) d->checkProfile(); + if (d) { + d->checkProfile(); + } } delete w; } @@ -2317,10 +2485,18 @@ void MainWindow::slotEditProjectSettings() #ifndef Q_WS_MAC m_recMonitor->slotUpdateCaptureFolder(m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash)); #endif - if (m_renderWidget) m_renderWidget->setDocumentPath(m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash)); - if (KdenliveSettings::videothumbnails() != w->enableVideoThumbs()) slotSwitchVideoThumbs(); - if (KdenliveSettings::audiothumbnails() != w->enableAudioThumbs()) slotSwitchAudioThumbs(); - if (m_activeDocument->profilePath() != profile) slotUpdateProjectProfile(profile); + if (m_renderWidget) { + m_renderWidget->setDocumentPath(m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash)); + } + 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()); @@ -2354,7 +2530,9 @@ void MainWindow::slotEditProjectSettings() m_activeDocument->setModified(); slotUpdateProxySettings(); } - m_activeDocument->setMetadata(w->metadata()); + if (w->metadata() != m_activeDocument->metadata()) { + m_activeDocument->setMetadata(w->metadata()); + } } delete w; } @@ -2382,21 +2560,25 @@ void MainWindow::slotUpdateProjectProfile(const QString &profile) KdenliveSettings::setCurrent_profile(profile); KdenliveSettings::setProject_fps(m_activeDocument->fps()); setCaption(m_activeDocument->description(), m_activeDocument->isModified()); - m_activeDocument->clipManager()->clearUnusedProducers(); m_monitorManager->resetProfiles(m_activeDocument->timecode()); m_transitionConfig->updateProjectFormat(m_activeDocument->mltProfile(), m_activeDocument->timecode(), m_activeDocument->tracksList()); m_effectStack->updateProjectFormat(m_activeDocument->mltProfile(), m_activeDocument->timecode()); m_projectList->updateProjectFormat(m_activeDocument->timecode()); - if (m_renderWidget) m_renderWidget->setProfile(m_activeDocument->mltProfile()); + if (m_renderWidget) { + m_renderWidget->setProfile(m_activeDocument->mltProfile()); + } m_timelineArea->setTabText(m_timelineArea->currentIndex(), m_activeDocument->description()); - if (updateFps) m_activeTimeline->updateProjectFps(); + if (updateFps) { + m_activeTimeline->updateProjectFps(); + } m_activeDocument->clipManager()->clearCache(); m_activeTimeline->updateProfile(); m_activeDocument->setModified(true); m_commandStack->activeStack()->clear(); //Update the mouse position display so it will display in DF/NDF format by default based on the project setting. slotUpdateMousePosition(0); + m_projectList->slotReloadClip(); // We need to desactivate & reactivate monitors to get a refresh //m_monitorManager->switchMonitors(); } @@ -2407,13 +2589,15 @@ void MainWindow::slotRenderProject() if (!m_renderWidget) { QString projectfolder = m_activeDocument ? m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash) : KdenliveSettings::defaultprojectfolder(); MltVideoProfile profile; - if (m_activeDocument) profile = m_activeDocument->mltProfile(); + if (m_activeDocument) { + profile = m_activeDocument->mltProfile(); + } m_renderWidget = new RenderWidget(projectfolder, m_projectList->useProxy(), profile, 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&))); - connect(m_renderWidget, SIGNAL(abortProcess(const QString &)), this, SIGNAL(abortRenderJob(const QString &))); - connect(m_renderWidget, SIGNAL(openDvdWizard(const QString &, const QString &)), this, SLOT(slotDvdWizard(const QString &, const QString &))); + connect(m_renderWidget, SIGNAL(selectedRenderProfile(QMap)), this, SLOT(slotSetDocumentRenderProfile(QMap))); + connect(m_renderWidget, SIGNAL(prepareRenderingData(bool,bool,QString)), this, SLOT(slotPrepareRendering(bool,bool,QString))); + connect(m_renderWidget, SIGNAL(abortProcess(QString)), this, SIGNAL(abortRenderJob(QString))); + connect(m_renderWidget, SIGNAL(openDvdWizard(QString)), this, SLOT(slotDvdWizard(QString))); if (m_activeDocument) { m_renderWidget->setProfile(m_activeDocument->mltProfile()); m_renderWidget->setGuides(m_activeDocument->guidesXml(), m_activeDocument->projectDuration()); @@ -2458,14 +2642,23 @@ void MainWindow::slotCleanProject() void MainWindow::slotUpdateMousePosition(int pos) { - if (m_activeDocument) - switch (m_timecodeFormat->currentIndex()) { + if (m_activeDocument) { + switch (m_timeFormatButton->currentItem()) { case 0: - statusBar()->changeItem(m_activeDocument->timecode().getTimecodeFromFrames(pos), ID_TIMELINE_POS); + m_timeFormatButton->setText(m_activeDocument->timecode().getTimecodeFromFrames(pos) + " / " + m_activeDocument->timecode().getTimecodeFromFrames(m_activeTimeline->duration())); break; default: - statusBar()->changeItem(QString::number(pos), ID_TIMELINE_POS); + m_timeFormatButton->setText(QString::number(pos) + " / " + QString::number(m_activeTimeline->duration())); } + } +} + +void MainWindow::slotUpdateProjectDuration(int pos) +{ + if (m_activeDocument) { + m_activeTimeline->setDuration(pos); + slotUpdateMousePosition(m_activeTimeline->projectView()->getMousePos()); + } } void MainWindow::slotUpdateDocumentState(bool modified) @@ -2486,9 +2679,9 @@ void MainWindow::connectDocumentInfo(KdenliveDoc *doc) { if (m_activeDocument) { if (m_activeDocument == doc) return; - disconnect(m_activeDocument, SIGNAL(progressInfo(const QString &, int)), this, SLOT(slotGotProgressInfo(const QString &, int))); + disconnect(m_activeDocument, SIGNAL(progressInfo(QString,int)), this, SLOT(slotGotProgressInfo(QString,int))); } - connect(doc, SIGNAL(progressInfo(const QString &, int)), this, SLOT(slotGotProgressInfo(const QString &, int))); + connect(doc, SIGNAL(progressInfo(QString,int)), this, SLOT(slotGotProgressInfo(QString,int))); } void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //changed @@ -2497,7 +2690,9 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha m_closeAction->setEnabled(m_timelineArea->count() > 1); kDebug() << "/////////////////// CONNECTING DOC TO PROJECT VIEW ////////////////"; if (m_activeDocument) { - if (m_activeDocument == doc) return; + if (m_activeDocument == doc) { + return; + } if (m_activeTimeline) { disconnect(m_projectMonitor, SIGNAL(renderPosition(int)), m_activeTimeline, SLOT(moveCursorPos(int))); disconnect(m_projectMonitor, SIGNAL(zoneUpdated(QPoint)), m_activeTimeline, SLOT(slotSetZone(QPoint))); @@ -2507,39 +2702,42 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha disconnect(m_clipMonitor, SIGNAL(zoneUpdated(QPoint)), m_activeDocument, SLOT(setModified())); disconnect(m_projectList, SIGNAL(projectModified()), m_activeDocument, SLOT(setModified())); - disconnect(m_projectMonitor->render, SIGNAL(refreshDocumentProducers(bool, bool)), m_activeDocument, SLOT(checkProjectClips(bool, bool))); + 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))); + disconnect(m_activeDocument, SIGNAL(addProjectClip(DocClipBase*,bool)), m_projectList, SLOT(slotAddClip(DocClipBase*,bool))); disconnect(m_activeDocument, SIGNAL(resetProjectList()), m_projectList, SLOT(slotResetProjectList())); - 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_activeTimeline->projectView(), SIGNAL(clipItemSelected(ClipItem*, bool)), this, SLOT(slotTimelineClipSelected(ClipItem*, bool))); - 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_activeDocument, SIGNAL(signalDeleteProjectClip(QString)), this, SLOT(slotDeleteClip(QString))); + disconnect(m_activeDocument, SIGNAL(updateClipDisplay(QString)), m_projectList, SLOT(slotUpdateClip(QString))); + disconnect(m_activeDocument, SIGNAL(selectLastAddedClip(QString)), m_projectList, SLOT(slotSelectClip(QString))); + disconnect(m_activeTimeline->projectView(), SIGNAL(clipItemSelected(ClipItem*,bool)), this, SLOT(slotTimelineClipSelected(ClipItem*,bool))); + 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(playMonitor()), m_projectMonitor, SLOT(slotPlay())); - disconnect(m_activeTimeline->projectView(), SIGNAL(displayMessage(const QString&, MessageType)), m_messageLabel, SLOT(setMessage(const QString&, MessageType))); - disconnect(m_activeTimeline->projectView(), SIGNAL(showClipFrame(DocClipBase *, QPoint, bool, const int)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint, bool, const int))); - disconnect(m_projectList, SIGNAL(gotFilterJobResults(const QString &, int, int, const QString &, stringMap)), m_activeTimeline->projectView(), SLOT(slotGotFilterJobResults(const QString &, int, int, const QString &, stringMap))); + disconnect(m_activeTimeline->projectView(), SIGNAL(displayMessage(QString,MessageType)), m_messageLabel, SLOT(setMessage(QString,MessageType))); + disconnect(m_activeTimeline->projectView(), SIGNAL(showClipFrame(DocClipBase*,QPoint,bool,int)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase*,QPoint,bool,int))); + disconnect(m_projectList, SIGNAL(gotFilterJobResults(QString,int,int,stringMap,stringMap)), m_activeTimeline->projectView(), SLOT(slotGotFilterJobResults(QString,int,int,stringMap,stringMap))); disconnect(m_activeTimeline, SIGNAL(cursorMoved()), m_projectMonitor, SLOT(slotActivateMonitor())); disconnect(m_activeTimeline, SIGNAL(configTrack(int)), this, SLOT(slotConfigTrack(int))); disconnect(m_activeDocument, SIGNAL(docModified(bool)), this, SLOT(slotUpdateDocumentState(bool))); - disconnect(m_effectStack, SIGNAL(updateEffect(ClipItem*, int, QDomElement, QDomElement, int,bool)), m_activeTimeline->projectView(), SLOT(slotUpdateClipEffect(ClipItem*, int, QDomElement, QDomElement, int,bool))); - disconnect(m_effectStack, SIGNAL(removeEffect(ClipItem*, int, QDomElement)), m_activeTimeline->projectView(), SLOT(slotDeleteEffect(ClipItem*, int, QDomElement))); - disconnect(m_effectStack, SIGNAL(addEffect(ClipItem*, QDomElement)), trackView->projectView(), SLOT(slotAddEffect(ClipItem*, QDomElement))); - disconnect(m_effectStack, SIGNAL(changeEffectState(ClipItem*, int, QList , bool)), m_activeTimeline->projectView(), SLOT(slotChangeEffectState(ClipItem*, int, QList , bool))); - disconnect(m_effectStack, SIGNAL(changeEffectPosition(ClipItem*, int, QList, int)), m_activeTimeline->projectView(), SLOT(slotChangeEffectPosition(ClipItem*, int, QList , int))); + disconnect(m_effectStack, SIGNAL(updateEffect(ClipItem*,int,QDomElement,QDomElement,int,bool)), m_activeTimeline->projectView(), SLOT(slotUpdateClipEffect(ClipItem*,int,QDomElement,QDomElement,int,bool))); + disconnect(m_effectStack, SIGNAL(removeEffect(ClipItem*,int,QDomElement)), m_activeTimeline->projectView(), SLOT(slotDeleteEffect(ClipItem*,int,QDomElement))); + disconnect(m_effectStack, SIGNAL(addEffect(ClipItem*,QDomElement)), trackView->projectView(), SLOT(slotAddEffect(ClipItem*,QDomElement))); + disconnect(m_effectStack, SIGNAL(changeEffectState(ClipItem*,int,QList,bool)), m_activeTimeline->projectView(), SLOT(slotChangeEffectState(ClipItem*,int,QList,bool))); + disconnect(m_effectStack, SIGNAL(changeEffectPosition(ClipItem*,int,QList,int)), m_activeTimeline->projectView(), SLOT(slotChangeEffectPosition(ClipItem*,int,QList,int))); disconnect(m_effectStack, SIGNAL(refreshEffectStack(ClipItem*)), m_activeTimeline->projectView(), SLOT(slotRefreshEffects(ClipItem*))); disconnect(m_effectStack, SIGNAL(reloadEffects()), this, SLOT(slotReloadEffects())); - disconnect(m_effectStack, SIGNAL(displayMessage(const QString&, int)), this, SLOT(slotGotProgressInfo(const QString&, int))); - disconnect(m_transitionConfig, SIGNAL(transitionUpdated(Transition *, QDomElement)), m_activeTimeline->projectView() , SLOT(slotTransitionUpdated(Transition *, QDomElement))); + disconnect(m_effectStack, SIGNAL(displayMessage(QString,int)), this, SLOT(slotGotProgressInfo(QString,int))); + disconnect(m_transitionConfig, SIGNAL(transitionUpdated(Transition*,QDomElement)), m_activeTimeline->projectView() , SLOT(slotTransitionUpdated(Transition*,QDomElement))); disconnect(m_transitionConfig, SIGNAL(seekTimeline(int)), m_activeTimeline->projectView() , SLOT(setCursorPos(int))); + disconnect(m_transitionConfig, SIGNAL(importClipKeyframes(GraphicsRectItem)), m_activeTimeline->projectView() , SLOT(slotImportClipKeyframes(GraphicsRectItem))); + disconnect(m_activeTimeline->projectView(), SIGNAL(activateDocumentMonitor()), m_projectMonitor, SLOT(slotActivateMonitor())); - disconnect(m_activeTimeline, SIGNAL(zoneMoved(int, int)), this, SLOT(slotZoneMoved(int, int))); + disconnect(m_activeTimeline, SIGNAL(zoneMoved(int,int)), this, SLOT(slotZoneMoved(int,int))); disconnect(m_projectList, SIGNAL(loadingIsOver()), m_activeTimeline->projectView(), SLOT(slotUpdateAllThumbs())); - disconnect(m_projectList, SIGNAL(refreshClip(const QString &)), m_activeTimeline->projectView(), SLOT(slotRefreshThumbs(const QString &))); + disconnect(m_projectList, SIGNAL(refreshClip(QString)), m_activeTimeline->projectView(), SLOT(slotRefreshThumbs(QString))); + disconnect(m_projectList, SIGNAL(addMarkers(QString,QList)), m_activeTimeline->projectView(), SLOT(slotAddClipMarker(QString,QList))); m_effectStack->clear(); } //m_activeDocument->setRenderer(NULL); @@ -2552,71 +2750,78 @@ 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(refreshClip(const QString &, bool)), trackView->projectView(), SLOT(slotRefreshThumbs(const QString &, bool))); + connect(m_projectList, SIGNAL(refreshClip(QString,bool)), trackView->projectView(), SLOT(slotRefreshThumbs(QString,bool))); connect(m_projectList, SIGNAL(projectModified()), doc, SLOT(setModified())); - connect(m_projectList, SIGNAL(clipNameChanged(const QString, const QString)), trackView->projectView(), SLOT(clipNameChanged(const QString, const QString))); + connect(m_projectList, SIGNAL(clipNameChanged(QString,QString)), trackView->projectView(), SLOT(clipNameChanged(QString,QString))); connect(trackView, SIGNAL(configTrack(int)), this, SLOT(slotConfigTrack(int))); connect(trackView, SIGNAL(updateTracksInfo()), this, SLOT(slotUpdateTrackInfo())); connect(trackView, SIGNAL(mousePosition(int)), this, SLOT(slotUpdateMousePosition(int))); - connect(trackView->projectView(), SIGNAL(forceClipProcessing(const QString &)), m_projectList, SLOT(slotForceProcessing(const QString &))); + connect(trackView->projectView(), SIGNAL(forceClipProcessing(QString)), m_projectList, SLOT(slotForceProcessing(QString))); + + connect(trackView->projectView(), SIGNAL(importKeyframes(GraphicsRectItem,QString,int)), this, SLOT(slotProcessImportKeyframes(GraphicsRectItem,QString,int))); + connect(m_projectMonitor, SIGNAL(renderPosition(int)), trackView, SLOT(moveCursorPos(int))); connect(m_projectMonitor, SIGNAL(zoneUpdated(QPoint)), trackView, SLOT(slotSetZone(QPoint))); 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(bool, bool)), doc, SLOT(checkProjectClips(bool, bool))); + 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(addProjectClip(DocClipBase*,bool)), m_projectList, SLOT(slotAddClip(DocClipBase*,bool))); connect(doc, SIGNAL(resetProjectList()), m_projectList, SLOT(slotResetProjectList())); - connect(doc, SIGNAL(signalDeleteProjectClip(const QString &)), this, SLOT(slotDeleteClip(const QString &))); - 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(signalDeleteProjectClip(QString)), this, SLOT(slotDeleteClip(QString))); + connect(doc, SIGNAL(updateClipDisplay(QString)), m_projectList, SLOT(slotUpdateClip(QString))); + connect(doc, SIGNAL(selectLastAddedClip(QString)), m_projectList, SLOT(slotSelectClip(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(doc, SIGNAL(saveTimelinePreview(QString)), trackView, SLOT(slotSaveTimelinePreview(QString))); connect(m_notesWidget, SIGNAL(textChanged()), doc, SLOT(setModified())); - connect(trackView->projectView(), SIGNAL(updateClipMarkers(DocClipBase *)), this, SLOT(slotUpdateClipMarkers(DocClipBase*))); - connect(trackView, SIGNAL(showTrackEffects(int, TrackInfo)), this, SLOT(slotTrackSelected(int, TrackInfo))); + connect(trackView->projectView(), SIGNAL(updateClipMarkers(DocClipBase*)), this, SLOT(slotUpdateClipMarkers(DocClipBase*))); + connect(trackView, SIGNAL(showTrackEffects(int,TrackInfo)), this, SLOT(slotTrackSelected(int,TrackInfo))); - connect(trackView->projectView(), SIGNAL(clipItemSelected(ClipItem*, bool)), this, SLOT(slotTimelineClipSelected(ClipItem*, 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 *))); + connect(trackView->projectView(), SIGNAL(clipItemSelected(ClipItem*,bool)), this, SLOT(slotTimelineClipSelected(ClipItem*,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()); connect(trackView->projectView(), SIGNAL(zoomIn()), this, SLOT(slotZoomIn())); connect(trackView->projectView(), SIGNAL(zoomOut()), this, SLOT(slotZoomOut())); connect(trackView, SIGNAL(setZoom(int)), this, SLOT(slotSetZoom(int))); - connect(trackView->projectView(), SIGNAL(displayMessage(const QString&, MessageType)), m_messageLabel, SLOT(setMessage(const QString&, MessageType))); + connect(trackView->projectView(), SIGNAL(displayMessage(QString,MessageType)), m_messageLabel, SLOT(setMessage(QString,MessageType))); - connect(trackView->projectView(), SIGNAL(showClipFrame(DocClipBase *, QPoint, bool, const int)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint, bool, const int))); + connect(trackView->projectView(), SIGNAL(showClipFrame(DocClipBase*,QPoint,bool,int)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase*,QPoint,bool,int))); connect(trackView->projectView(), SIGNAL(playMonitor()), m_projectMonitor, SLOT(slotPlay())); - connect(trackView->projectView(), SIGNAL(transitionItemSelected(Transition*, int, QPoint, bool)), m_projectMonitor, SLOT(slotSetSelectedClip(Transition*))); + connect(trackView->projectView(), SIGNAL(transitionItemSelected(Transition*,int,QPoint,bool)), m_projectMonitor, SLOT(slotSetSelectedClip(Transition*))); + + connect(m_projectList, SIGNAL(gotFilterJobResults(QString,int,int,stringMap,stringMap)), trackView->projectView(), SLOT(slotGotFilterJobResults(QString,int,int,stringMap,stringMap))); - connect(m_projectList, SIGNAL(gotFilterJobResults(const QString &, int, int, const QString &, stringMap)), trackView->projectView(), SLOT(slotGotFilterJobResults(const QString &, int, int, const QString &, stringMap))); + connect(m_projectList, SIGNAL(addMarkers(QString,QList)), trackView->projectView(), SLOT(slotAddClipMarker(QString,QList))); // Effect stack signals - connect(m_effectStack, SIGNAL(updateEffect(ClipItem*, int, QDomElement, QDomElement, int,bool)), trackView->projectView(), SLOT(slotUpdateClipEffect(ClipItem*, int, QDomElement, QDomElement, int,bool))); - connect(m_effectStack, SIGNAL(updateClipRegion(ClipItem*, int, QString)), trackView->projectView(), SLOT(slotUpdateClipRegion(ClipItem*, int, QString))); - connect(m_effectStack, SIGNAL(removeEffect(ClipItem*, int, QDomElement)), trackView->projectView(), SLOT(slotDeleteEffect(ClipItem*, int, QDomElement))); - connect(m_effectStack, SIGNAL(addEffect(ClipItem*, QDomElement)), trackView->projectView(), SLOT(slotAddEffect(ClipItem*, QDomElement))); - connect(m_effectStack, SIGNAL(changeEffectState(ClipItem*, int, QList , bool)), trackView->projectView(), SLOT(slotChangeEffectState(ClipItem*, int, QList , bool))); - connect(m_effectStack, SIGNAL(changeEffectPosition(ClipItem*, int, QList , int)), trackView->projectView(), SLOT(slotChangeEffectPosition(ClipItem*, int, QList , int))); + connect(m_effectStack, SIGNAL(updateEffect(ClipItem*,int,QDomElement,QDomElement,int,bool)), trackView->projectView(), SLOT(slotUpdateClipEffect(ClipItem*,int,QDomElement,QDomElement,int,bool))); + connect(m_effectStack, SIGNAL(updateClipRegion(ClipItem*,int,QString)), trackView->projectView(), SLOT(slotUpdateClipRegion(ClipItem*,int,QString))); + connect(m_effectStack, SIGNAL(removeEffect(ClipItem*,int,QDomElement)), trackView->projectView(), SLOT(slotDeleteEffect(ClipItem*,int,QDomElement))); + connect(m_effectStack, SIGNAL(addEffect(ClipItem*,QDomElement)), trackView->projectView(), SLOT(slotAddEffect(ClipItem*,QDomElement))); + connect(m_effectStack, SIGNAL(changeEffectState(ClipItem*,int,QList,bool)), trackView->projectView(), SLOT(slotChangeEffectState(ClipItem*,int,QList,bool))); + connect(m_effectStack, SIGNAL(changeEffectPosition(ClipItem*,int,QList,int)), trackView->projectView(), SLOT(slotChangeEffectPosition(ClipItem*,int,QList,int))); + connect(m_effectStack, SIGNAL(refreshEffectStack(ClipItem*)), trackView->projectView(), SLOT(slotRefreshEffects(ClipItem*))); - connect(m_effectStack, SIGNAL(seekTimeline(int)), trackView->projectView() , SLOT(seekCursorPos(int))); + connect(m_effectStack, SIGNAL(seekTimeline(int)), trackView->projectView(), SLOT(seekCursorPos(int))); + connect(m_effectStack, SIGNAL(importClipKeyframes(GraphicsRectItem)), trackView->projectView(), SLOT(slotImportClipKeyframes(GraphicsRectItem))); connect(m_effectStack, SIGNAL(reloadEffects()), this, SLOT(slotReloadEffects())); - connect(m_effectStack, SIGNAL(displayMessage(const QString&, int)), this, SLOT(slotGotProgressInfo(const QString&, int))); + connect(m_effectStack, SIGNAL(displayMessage(QString,int)), this, SLOT(slotGotProgressInfo(QString,int))); // Transition config signals - connect(m_transitionConfig, SIGNAL(transitionUpdated(Transition *, QDomElement)), trackView->projectView() , SLOT(slotTransitionUpdated(Transition *, QDomElement))); + connect(m_transitionConfig, SIGNAL(transitionUpdated(Transition*,QDomElement)), trackView->projectView() , SLOT(slotTransitionUpdated(Transition*,QDomElement))); + connect(m_transitionConfig, SIGNAL(importClipKeyframes(GraphicsRectItem)), trackView->projectView() , SLOT(slotImportClipKeyframes(GraphicsRectItem))); connect(m_transitionConfig, SIGNAL(seekTimeline(int)), trackView->projectView() , SLOT(seekCursorPos(int))); connect(trackView->projectView(), SIGNAL(activateDocumentMonitor()), m_projectMonitor, SLOT(slotActivateMonitor())); - connect(trackView, SIGNAL(zoneMoved(int, int)), this, SLOT(slotZoneMoved(int, int))); + connect(trackView, SIGNAL(zoneMoved(int,int)), this, SLOT(slotZoneMoved(int,int))); connect(m_projectList, SIGNAL(loadingIsOver()), trackView->projectView(), SLOT(slotUpdateAllThumbs())); trackView->projectView()->setContextMenu(m_timelineContextMenu, m_timelineContextClipMenu, m_timelineContextTransitionMenu, m_clipTypeGroup, static_cast(factory()->container("marker_menu", this))); m_activeTimeline = trackView; @@ -2640,6 +2845,8 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha m_saveAction->setEnabled(doc->isModified()); m_normalEditTool->setChecked(true); m_activeDocument = doc; + connect(m_projectMonitor, SIGNAL(durationChanged(int)), this, SLOT(slotUpdateProjectDuration(int))); + m_monitorManager->setDocument(m_activeDocument); m_activeTimeline->updateProjectFps(); m_activeDocument->checkProjectClips(); #ifndef Q_WS_MAC @@ -2647,7 +2854,10 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha #endif //Update the mouse position display so it will display in DF/NDF format by default based on the project setting. slotUpdateMousePosition(0); - m_monitorManager->activateMonitor(Kdenlive::clipMonitor); + + // Make sure monitor is visible so that it is painted black on startup + show(); + m_monitorManager->activateMonitor(Kdenlive::ClipMonitor, true); // set tool to select tool m_buttonSelectTool->setChecked(true); } @@ -2680,7 +2890,10 @@ 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 (m_stopmotion) { + m_stopmotion->slotLive(false); + } + if (KConfigDialog::showDialog("settings")) { KdenliveSettingsDialog* d = static_cast (KConfigDialog::exists("settings")); if (page != -1) d->showPage(page, option); @@ -2698,13 +2911,15 @@ 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(settingsChanged(QString)), this, SLOT(updateConfiguration())); connect(dialog, SIGNAL(doResetProfile()), m_monitorManager, SLOT(slotResetProfiles())); #ifndef Q_WS_MAC connect(dialog, SIGNAL(updateCaptureFolder()), this, SLOT(slotUpdateCaptureFolder())); #endif dialog->show(); - if (page != -1) dialog->showPage(page, option); + if (page != -1) { + dialog->showPage(page, option); + } } void MainWindow::slotUpdateCaptureFolder() @@ -2733,7 +2948,7 @@ void MainWindow::updateConfiguration() // Update list of transcoding profiles loadTranscoders(); - loadStabilize(); + loadClipActions(); #ifdef USE_JOGSHUTTLE activateShuttleDevice(); #endif @@ -2749,8 +2964,9 @@ void MainWindow::slotSwitchSplitAudio() void MainWindow::slotSwitchVideoThumbs() { KdenliveSettings::setVideothumbnails(!KdenliveSettings::videothumbnails()); - if (m_activeTimeline) + if (m_activeTimeline) { m_activeTimeline->projectView()->slotUpdateAllThumbs(); + } m_buttonVideoThumbs->setChecked(KdenliveSettings::videothumbnails()); } @@ -2760,8 +2976,9 @@ void MainWindow::slotSwitchAudioThumbs() if (m_activeTimeline) { m_activeTimeline->refresh(); m_activeTimeline->projectView()->checkAutoScroll(); - if (m_activeDocument) + if (m_activeDocument) { m_activeDocument->clipManager()->checkAudioThumbs(); + } } m_buttonAudioThumbs->setChecked(KdenliveSettings::audiothumbnails()); } @@ -2769,8 +2986,9 @@ void MainWindow::slotSwitchAudioThumbs() void MainWindow::slotSwitchMarkersComments() { KdenliveSettings::setShowmarkers(!KdenliveSettings::showmarkers()); - if (m_activeTimeline) + if (m_activeTimeline) { m_activeTimeline->refresh(); + } m_buttonShowMarkers->setChecked(KdenliveSettings::showmarkers()); } @@ -2800,15 +3018,17 @@ void MainWindow::slotDeleteItem() } // effect stack has no focus - if (m_activeTimeline) + if (m_activeTimeline) { m_activeTimeline->projectView()->deleteSelectedClips(); + } } } void MainWindow::slotUpdateClipMarkers(DocClipBase *clip) { - if (m_clipMonitor->isActive()) + if (m_clipMonitor->isActive()) { m_clipMonitor->checkOverlay(); + } m_clipMonitor->updateMarkers(clip); } @@ -2833,11 +3053,14 @@ void MainWindow::slotAddClipMarker() return; } QString id = clip->getId(); - CommentedTime marker(pos, i18n("Marker")); + CommentedTime marker(pos, i18n("Marker"), KdenliveSettings::default_marker_type()); QPointer d = new MarkerDialog(clip, marker, - m_activeDocument->timecode(), i18n("Add Marker"), this); - if (d->exec() == QDialog::Accepted) - m_activeTimeline->projectView()->slotAddClipMarker(id, d->newMarker().time(), d->newMarker().comment()); + m_activeDocument->timecode(), i18n("Add Marker"), this); + if (d->exec() == QDialog::Accepted) { + m_activeTimeline->projectView()->slotAddClipMarker(id, QList () << d->newMarker()); + QString hash = clip->getClipHash(); + if (!hash.isEmpty()) m_activeDocument->cacheImage(hash + '#' + QString::number(d->newMarker().time().frames(m_activeDocument->fps())), d->markerImage()); + } delete d; } @@ -2913,20 +3136,22 @@ void MainWindow::slotEditClipMarker() } QString id = clip->getId(); - QString oldcomment = clip->markerComment(pos); - if (oldcomment.isEmpty()) { + CommentedTime oldMarker = clip->markerAt(pos); + if (oldMarker == CommentedTime()) { m_messageLabel->setMessage(i18n("No marker found at cursor time"), ErrorMessage); return; } - CommentedTime marker(pos, oldcomment); - QPointer d = new MarkerDialog(clip, marker, - m_activeDocument->timecode(), i18n("Edit Marker"), this); + QPointer d = new MarkerDialog(clip, oldMarker, + m_activeDocument->timecode(), i18n("Edit Marker"), this); if (d->exec() == QDialog::Accepted) { - m_activeTimeline->projectView()->slotAddClipMarker(id, d->newMarker().time(), d->newMarker().comment()); + m_activeTimeline->projectView()->slotAddClipMarker(id, QList () <newMarker()); + QString hash = clip->getClipHash(); + if (!hash.isEmpty()) m_activeDocument->cacheImage(hash + '#' + QString::number(d->newMarker().time().frames(m_activeDocument->fps())), d->markerImage()); if (d->newMarker().time() != pos) { // remove old marker - m_activeTimeline->projectView()->slotAddClipMarker(id, pos, QString()); + oldMarker.setMarkerType(-1); + m_activeTimeline->projectView()->slotAddClipMarker(id, QList () <setMessage(i18n("Cannot find clip to add marker"), ErrorMessage); return; } - - m_activeTimeline->projectView()->slotAddClipMarker(clip->getId(), pos, m_activeDocument->timecode().getDisplayTimecode(pos, false)); + //TODO: allow user to set default marker category + CommentedTime marker(pos, m_activeDocument->timecode().getDisplayTimecode(pos, false), KdenliveSettings::default_marker_type()); + m_activeTimeline->projectView()->slotAddClipMarker(clip->getId(), QList () <projectView()->slotAddGuide(false); } @@ -2972,29 +3198,35 @@ void MainWindow::slotRemoveSpace() void MainWindow::slotInsertTrack(int ix) { - m_projectMonitor->slotActivateMonitor(); + m_monitorManager->activateMonitor(Kdenlive::ProjectMonitor); if (m_activeTimeline) { - if (ix == -1) ix = m_activeTimeline->projectView()->selectedTrack(); + if (ix == -1) { + ix = m_activeTimeline->projectView()->selectedTrack(); + } m_activeTimeline->projectView()->slotInsertTrack(ix); } - if (m_activeDocument) + if (m_activeDocument) { m_transitionConfig->updateProjectFormat(m_activeDocument->mltProfile(), m_activeDocument->timecode(), m_activeDocument->tracksList()); + } } void MainWindow::slotDeleteTrack(int ix) { - m_projectMonitor->slotActivateMonitor(); + m_monitorManager->activateMonitor(Kdenlive::ProjectMonitor); if (m_activeTimeline) { - if (ix == -1) ix = m_activeTimeline->projectView()->selectedTrack(); + if (ix == -1) { + ix = m_activeTimeline->projectView()->selectedTrack(); + } m_activeTimeline->projectView()->slotDeleteTrack(ix); } - if (m_activeDocument) + if (m_activeDocument) { m_transitionConfig->updateProjectFormat(m_activeDocument->mltProfile(), m_activeDocument->timecode(), m_activeDocument->tracksList()); + } } void MainWindow::slotConfigTrack(int ix) { - m_projectMonitor->slotActivateMonitor(); + m_monitorManager->activateMonitor(Kdenlive::ProjectMonitor); if (m_activeTimeline) m_activeTimeline->projectView()->slotConfigTracks(ix); if (m_activeDocument) @@ -3003,7 +3235,7 @@ void MainWindow::slotConfigTrack(int ix) void MainWindow::slotSelectTrack() { - m_projectMonitor->slotActivateMonitor(); + m_monitorManager->activateMonitor(Kdenlive::ProjectMonitor); if (m_activeTimeline) { m_activeTimeline->projectView()->slotSelectClipsInTrack(); } @@ -3011,7 +3243,7 @@ void MainWindow::slotSelectTrack() void MainWindow::slotSelectAllTracks() { - m_projectMonitor->slotActivateMonitor(); + m_monitorManager->activateMonitor(Kdenlive::ProjectMonitor); if (m_activeTimeline) m_activeTimeline->projectView()->slotSelectAllClips(); } @@ -3102,14 +3334,14 @@ void MainWindow::slotEditItemDuration() m_activeTimeline->projectView()->editItemDuration(); } -void MainWindow::slotAddProjectClip(KUrl url, QMap data) +void MainWindow::slotAddProjectClip(const KUrl &url, const stringMap &data) { if (m_activeDocument) { m_activeDocument->slotAddClipFile(url, data); } } -void MainWindow::slotAddProjectClipList(KUrl::List urls) +void MainWindow::slotAddProjectClipList(const KUrl::List &urls) { if (m_activeDocument) m_activeDocument->slotAddClipList(urls); @@ -3128,21 +3360,30 @@ void MainWindow::slotAddTransition(QAction *result) void MainWindow::slotAddVideoEffect(QAction *result) { - if (!result) return; - const int EFFECT_VIDEO = 1; - const int EFFECT_AUDIO = 2; + if (!result) { + return; + } + const int VideoEffect = 1; + const int AudioEffect = 2; QStringList info = result->data().toStringList(); - if (info.isEmpty() || info.size() < 3) return; + if (info.isEmpty() || info.size() < 3) { + return; + } QDomElement effect ; - if (info.last() == QString::number((int) EFFECT_VIDEO)) - effect = videoEffects.getEffectByTag(info.at(0), info.at(1)); - else if (info.last() == 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", info.at(0), info.at(1)), ErrorMessage); + if (info.last() == QString::number((int) VideoEffect)) { + effect = videoEffects.getEffectByTag(info.at(0), info.at(1)); + } else if (info.last() == QString::number((int) AudioEffect)) { + 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", info.at(0), info.at(1)), ErrorMessage); + } } @@ -3169,8 +3410,9 @@ void MainWindow::slotSetZoom(int value) value = qMax(m_zoomSlider->minimum(), value); value = qMin(m_zoomSlider->maximum(), value); - if (m_activeTimeline) + if (m_activeTimeline) { m_activeTimeline->slotChangeZoom(value); + } m_zoomOut->setEnabled(value < m_zoomSlider->maximum()); m_zoomIn->setEnabled(value > m_zoomSlider->minimum()); @@ -3183,8 +3425,9 @@ void MainWindow::slotSetZoom(int value) void MainWindow::slotShowZoomSliderToolTip(int zoomlevel) { - if (zoomlevel != -1) + if (zoomlevel != -1) { slotUpdateZoomSliderToolTip(zoomlevel); + } QPoint global = m_zoomSlider->rect().topLeft(); global.ry() += m_zoomSlider->height() / 2; @@ -3197,26 +3440,24 @@ void MainWindow::slotUpdateZoomSliderToolTip(int zoomlevel) m_zoomSlider->setToolTip(i18n("Zoom Level: %1/13", (13 - zoomlevel))); } -void MainWindow::slotGotProgressInfo(const QString &message, int progress) +void MainWindow::slotGotProgressInfo(const QString &message, int progress, MessageType type) { - m_statusProgressBar->setValue(progress); + if (type == DefaultMessage) { + m_statusProgressBar->setValue(progress); + } + m_messageLabel->setMessage(message, type); if (progress >= 0) { - if (!message.isEmpty()) - m_messageLabel->setMessage(message, InformationMessage);//statusLabel->setText(message); - m_statusProgressBar->setVisible(true); - } else if (progress == -2) { - if (!message.isEmpty()) - m_messageLabel->setMessage(message, ErrorMessage); - m_statusProgressBar->setVisible(false); + if (type == DefaultMessage) { + m_statusProgressBar->setVisible(true); + } } else { - m_messageLabel->setMessage(QString(), DefaultMessage); m_statusProgressBar->setVisible(false); } } void MainWindow::slotShowClipProperties(DocClipBase *clip) { - if (clip->clipType() == TEXT) { + if (clip->clipType() == Text) { QString titlepath = m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash) + "titles/"; if (!clip->getProperty("resource").isEmpty() && clip->getProperty("xmldata").isEmpty()) { // template text clip @@ -3244,7 +3485,9 @@ void MainWindow::slotShowClipProperties(DocClipBase *clip) dia_ui.description->setText(clip->getProperty("description")); if (dia->exec() == QDialog::Accepted) { QString textTemplate = dia_ui.template_list->comboBox()->itemData(dia_ui.template_list->comboBox()->currentIndex()).toString(); - if (textTemplate.isEmpty()) textTemplate = dia_ui.template_list->comboBox()->currentText(); + if (textTemplate.isEmpty()) { + textTemplate = dia_ui.template_list->comboBox()->currentText(); + } QMap newprops; @@ -3258,12 +3501,18 @@ void MainWindow::slotShowClipProperties(DocClipBase *clip) } QString newtemplate = newprops.value("xmltemplate"); - if (newtemplate.isEmpty()) newtemplate = templatePath; + if (newtemplate.isEmpty()) { + newtemplate = templatePath; + } // template modified we need to update xmldata QString description = newprops.value("description"); - if (description.isEmpty()) description = clip->getProperty("description"); - else newprops.insert("templatetext", description); + if (description.isEmpty()) { + description = clip->getProperty("description"); + } else { + newprops.insert("templatetext", description); + } + //newprops.insert("xmldata", m_projectList->generateTemplateXml(newtemplate, description).toString()); if (!newprops.isEmpty()) { EditClipCommand *command = new EditClipCommand(m_projectList, clip->getId(), clip->currentProperties(newprops), newprops, true); @@ -3281,20 +3530,24 @@ void MainWindow::slotShowClipProperties(DocClipBase *clip) if (dia_ui->exec() == QDialog::Accepted) { QMap newprops; newprops.insert("xmldata", dia_ui->xml().toString()); - if (dia_ui->outPoint() != clip->duration().frames(m_activeDocument->fps())) { + if (dia_ui->duration() != clip->duration().frames(m_activeDocument->fps())) { // duration changed, we need to update duration - newprops.insert("out", QString::number(dia_ui->outPoint())); + newprops.insert("out", QString::number(dia_ui->duration() - 1)); 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 (currentLength <= dia_ui->duration()) { + newprops.insert("length", QString::number(dia_ui->duration())); + } 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()); + } else { + newprops.insert("resource", QString()); + } } EditClipCommand *command = new EditClipCommand(m_projectList, clip->getId(), clip->currentProperties(newprops), newprops, true); m_activeDocument->commandStack()->push(command); @@ -3306,19 +3559,46 @@ void MainWindow::slotShowClipProperties(DocClipBase *clip) //m_activeDocument->editTextClip(clip->getProperty("xml"), clip->getId()); return; } + + // Check if we already have a properties dialog opened for that clip + QList list = findChildren(); + for (int i = 0; i < list.size(); ++i) { + if (list.at(i)->clipId() == clip->getId()) { + // We have one dialog, show it + list.at(i)->raise(); + return; + } + } // 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))); + + if (clip->clipType() == AV || clip->clipType() == Video || clip->clipType() == Playlist || clip->clipType() == SlideShow) { + // request clip thumbnails + connect(m_activeDocument->clipManager(), SIGNAL(gotClipPropertyThumbnail(QString,QImage)), dia, SLOT(slotGotThumbnail(QString,QImage))); + connect(dia, SIGNAL(requestThumb(QString,QList)), m_activeDocument->clipManager(), SLOT(slotRequestThumbs(QString,QList))); + m_activeDocument->clipManager()->slotRequestThumbs(QString('?' + clip->getId()), QList() << clip->getClipThumbFrame()); + } + + connect(dia, SIGNAL(addMarkers(QString,QList)), m_activeTimeline->projectView(), SLOT(slotAddClipMarker(QString,QList))); + connect(dia, SIGNAL(editAnalysis(QString,QString,QString)), m_activeTimeline->projectView(), SLOT(slotAddClipExtraData(QString,QString,QString))); + connect(m_activeTimeline->projectView(), SIGNAL(updateClipMarkers(DocClipBase*)), dia, SLOT(slotFillMarkersList(DocClipBase*))); + connect(m_activeTimeline->projectView(), SIGNAL(updateClipExtraData(DocClipBase*)), dia, SLOT(slotUpdateAnalysisData(DocClipBase*))); + connect(m_projectList, SIGNAL(updateAnalysisData(DocClipBase*)), dia, SLOT(slotUpdateAnalysisData(DocClipBase*))); + connect(dia, SIGNAL(loadMarkers(QString)), m_activeTimeline->projectView(), SLOT(slotLoadClipMarkers(QString))); + connect(dia, SIGNAL(saveMarkers(QString)), m_activeTimeline->projectView(), SLOT(slotSaveClipMarkers(QString))); + connect(dia, SIGNAL(deleteProxy(QString)), m_projectList, SLOT(slotDeleteProxy(QString))); + connect(dia, SIGNAL(applyNewClipProperties(QString,QMap,QMap,bool,bool)), this, SLOT(slotApplyNewClipProperties(QString,QMap,QMap,bool,bool))); dia->show(); } -void MainWindow::slotApplyNewClipProperties(const QString id, QMap props, QMap newprops, bool refresh, bool reload) +void MainWindow::slotApplyNewClipProperties(const QString &id, const QMap &props, const QMap &newprops, bool refresh, bool reload) { - if (newprops.isEmpty()) return; + if (newprops.isEmpty()) { + return; + } + EditClipCommand *command = new EditClipCommand(m_projectList, id, props, newprops, true); m_activeDocument->commandStack()->push(command); m_activeDocument->setModified(); @@ -3330,10 +3610,10 @@ void MainWindow::slotApplyNewClipProperties(const QString id, QMap cliplist, QMap commonproperties) +void MainWindow::slotShowClipProperties(const QList &cliplist, const QMap &commonproperties) { QPointer dia = new ClipProperties(cliplist, - m_activeDocument->timecode(), commonproperties, this); + m_activeDocument->timecode(), commonproperties, this); if (dia->exec() == QDialog::Accepted) { QUndoCommand *command = new QUndoCommand(); command->setText(i18n("Edit clips")); @@ -3342,16 +3622,17 @@ void MainWindow::slotShowClipProperties(QList cliplist, QMap newProps = newImageProps; newProps.remove("transparency"); - for (int i = 0; i < cliplist.count(); i++) { + for (int i = 0; i < cliplist.count(); ++i) { DocClipBase *clip = cliplist.at(i); - if (clip->clipType() == IMAGE) + if (clip->clipType() == Image) new EditClipCommand(m_projectList, clip->getId(), clip->currentProperties(newImageProps), newImageProps, true, command); else new EditClipCommand(m_projectList, clip->getId(), clip->currentProperties(newProps), newProps, true, command); } m_activeDocument->commandStack()->push(command); - for (int i = 0; i < cliplist.count(); i++) + for (int i = 0; i < cliplist.count(); ++i) { m_activeTimeline->projectView()->slotUpdateClip(cliplist.at(i)->getId(), dia->needsTimelineReload()); + } } delete dia; } @@ -3364,30 +3645,43 @@ void MainWindow::customEvent(QEvent* e) void MainWindow::slotTimelineClipSelected(ClipItem* item, bool raise) { + if (item != m_mainClip) { + if (m_mainClip) { + m_mainClip->setMainSelectedClip(false); + } + if (item) { + item->setMainSelectedClip(true); + } + m_mainClip = item; + } + m_effectStack->slotClipItemSelected(item); m_projectMonitor->slotSetSelectedClip(item); - if (raise) + if (raise) { m_effectStack->raiseWindow(m_effectStackDock); + } } -void MainWindow::slotTrackSelected(int index, TrackInfo info, bool raise) +void MainWindow::slotTrackSelected(int index, const TrackInfo &info, bool raise) { m_effectStack->slotTrackItemSelected(index, info); - if (raise) + if (raise) { m_effectStack->raiseWindow(m_effectStackDock); + } } -void MainWindow::slotActivateTransitionView(Transition *t) +void MainWindow::slotActivateTransitionView(Transition *transition) { - if (t) + if (transition) m_transitionConfig->raiseWindow(m_transitionConfigDock); } void MainWindow::slotSnapRewind() { if (m_projectMonitor->isActive()) { - if (m_activeTimeline) + if (m_activeTimeline) { m_activeTimeline->projectView()->slotSeekToPreviousSnap(); + } } else { m_clipMonitor->slotSeekToPreviousSnap(); } @@ -3396,8 +3690,9 @@ void MainWindow::slotSnapRewind() void MainWindow::slotSnapForward() { if (m_projectMonitor->isActive()) { - if (m_activeTimeline) + if (m_activeTimeline) { m_activeTimeline->projectView()->slotSeekToNextSnap(); + } } else { m_clipMonitor->slotSeekToNextSnap(); } @@ -3406,16 +3701,18 @@ void MainWindow::slotSnapForward() void MainWindow::slotClipStart() { if (m_projectMonitor->isActive()) { - if (m_activeTimeline) + if (m_activeTimeline) { m_activeTimeline->projectView()->clipStart(); + } } } void MainWindow::slotClipEnd() { if (m_projectMonitor->isActive()) { - if (m_activeTimeline) + if (m_activeTimeline) { m_activeTimeline->projectView()->clipEnd(); + } } } @@ -3438,11 +3735,11 @@ void MainWindow::slotZoneEnd() void MainWindow::slotChangeTool(QAction * action) { if (action == m_buttonSelectTool) - slotSetTool(SELECTTOOL); + slotSetTool(SelectTool); else if (action == m_buttonRazorTool) - slotSetTool(RAZORTOOL); + slotSetTool(RazorTool); else if (action == m_buttonSpacerTool) - slotSetTool(SPACERTOOL); + slotSetTool(SpacerTool); } void MainWindow::slotChangeEdit(QAction * action) @@ -3451,23 +3748,23 @@ void MainWindow::slotChangeEdit(QAction * action) return; if (action == m_overwriteEditTool) - m_activeTimeline->projectView()->setEditMode(OVERWRITEEDIT); + m_activeTimeline->projectView()->setEditMode(OverwriteEdit); else if (action == m_insertEditTool) - m_activeTimeline->projectView()->setEditMode(INSERTEDIT); + m_activeTimeline->projectView()->setEditMode(InsertEdit); else - m_activeTimeline->projectView()->setEditMode(NORMALEDIT); + m_activeTimeline->projectView()->setEditMode(NormalEdit); } -void MainWindow::slotSetTool(PROJECTTOOL tool) +void MainWindow::slotSetTool(ProjectTool tool) { if (m_activeDocument && m_activeTimeline) { //m_activeDocument->setTool(tool); QString message; switch (tool) { - case SPACERTOOL: + case SpacerTool: message = i18n("Ctrl + click to use spacer on current track only"); break; - case RAZORTOOL: + case RazorTool: message = i18n("Click on a clip to cut it"); break; default: @@ -3499,7 +3796,10 @@ void MainWindow::slotPasteEffects() void MainWindow::slotFind() { - if (!m_activeDocument || !m_activeTimeline) return; + if (!m_activeDocument || !m_activeTimeline) { + return; + } + m_projectSearch->setEnabled(false); m_findActivated = true; m_findString.clear(); @@ -3511,10 +3811,11 @@ void MainWindow::slotFind() void MainWindow::slotFindNext() { - if (m_activeTimeline && m_activeTimeline->projectView()->findNextString(m_findString)) + if (m_activeTimeline && m_activeTimeline->projectView()->findNextString(m_findString)) { statusBar()->showMessage(i18n("Found: %1", m_findString)); - else + } else { statusBar()->showMessage(i18n("Reached end of project")); + } m_findTimer.start(4000); } @@ -3565,24 +3866,31 @@ void MainWindow::slotClipInTimeline(const QString &clipId) } inTimelineMenu->addActions(actionList); - if (matching.empty()) + if (matching.empty()) { inTimelineMenu->setEnabled(false); - else + } else { inTimelineMenu->setEnabled(true); + } } } void MainWindow::slotClipInProjectTree() { if (m_activeTimeline) { - const QStringList &clipIds = m_activeTimeline->projectView()->selectedClips(); - if (clipIds.isEmpty()) + QStringList clipIds; + if (m_mainClip) { + clipIds << m_mainClip->clipProducer(); + } else { + clipIds = m_activeTimeline->projectView()->selectedClips(); + } + if (clipIds.isEmpty()) { return; + } m_projectListDock->raise(); - for (int i = 0; i < clipIds.count(); i++) - m_projectList->selectItemById(clipIds.at(i)); - if (m_projectMonitor->isActive()) + m_projectList->selectItemById(clipIds.at(0)); + if (m_projectMonitor->isActive()) { slotSwitchMonitors(); + } } } @@ -3591,7 +3899,7 @@ void MainWindow::slotClipInProjectTree() if (m_activeTimeline) { const QList clips = m_activeTimeline->projectView()->selectedClipItems(); if (clips.isEmpty()) return; - for (int i = 0; i < clips.count(); i++) { + for (int i = 0; i < clips.count(); ++i) { m_projectList->slotAddXmlClip(clips.at(i)->itemXml()); } //m_projectList->selectItemById(clipIds.at(i)); @@ -3613,10 +3921,11 @@ void MainWindow::keyPressEvent(QKeyEvent *ke) if (ke->key() == Qt::Key_Backspace) { m_findString = m_findString.left(m_findString.length() - 1); - if (!m_findString.isEmpty()) + if (!m_findString.isEmpty()) { findAhead(); - else + } else { findTimeout(); + } m_findTimer.start(4000); ke->accept(); @@ -3665,7 +3974,7 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *event) } -void MainWindow::slotSaveZone(Render *render, QPoint zone, DocClipBase *baseClip, KUrl path) +void MainWindow::slotSaveZone(Render *render, const QPoint &zone, DocClipBase *baseClip, KUrl path) { KDialog *dialog = new KDialog(this); dialog->setCaption("Save clip zone"); @@ -3678,8 +3987,9 @@ void MainWindow::slotSaveZone(Render *render, QPoint zone, DocClipBase *baseClip QLabel *label1 = new QLabel(i18n("Save clip zone as:"), this); if (path.isEmpty()) { QString tmppath = m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash); - if (baseClip == NULL) tmppath.append("untitled.mlt"); - else { + 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); @@ -3696,6 +4006,7 @@ void MainWindow::slotSaveZone(Render *render, QPoint zone, DocClipBase *baseClip 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()); + delete dialog; return; } } @@ -3721,6 +4032,7 @@ void MainWindow::slotSaveZone(Render *render, QPoint zone, DocClipBase *baseClip } else render->saveZone(url->url(), edit->text(), zone); } + delete dialog; } @@ -3759,8 +4071,7 @@ int MainWindow::getNewStuff(const QString &configFile) KNS3::Entry::List entries; #if KDE_IS_VERSION(4,3,80) QPointer dialog = new KNS3::DownloadDialog(configFile); - dialog->exec(); - if (dialog) entries = dialog->changedEntries(); + if (dialog->exec()) entries = dialog->changedEntries(); foreach(const KNS3::Entry & entry, entries) { if (entry.status() == KNS3::Entry::Installed) kDebug() << "// Installed files: " << entry.installedFiles(); @@ -3844,15 +4155,14 @@ void MainWindow::slotUpdateClipType(QAction *action) } } -void MainWindow::slotDvdWizard(const QString &url, const QString &profile) +void MainWindow::slotDvdWizard(const QString &url) { // We must stop the monitors since we create a new on in the dvd wizard - m_clipMonitor->stop(); - m_projectMonitor->stop(); - QPointer w = new DvdWizard(url, profile, this); + m_monitorManager->activateMonitor(Kdenlive::DvdMonitor); + QPointer w = new DvdWizard(m_monitorManager, url, this); w->exec(); - m_projectMonitor->start(); delete w; + m_monitorManager->activateMonitor(Kdenlive::ClipMonitor); } void MainWindow::slotShowTimeline(bool show) @@ -3877,24 +4187,54 @@ void MainWindow::slotMaximizeCurrent(bool) kDebug() << "CURRENT WIDGET: " << par->objectName(); } -void MainWindow::loadStabilize() +void MainWindow::loadClipActions() { - QMenu* stabMenu= static_cast(factory()->container("stabilize", this)); - if (stabMenu){ - stabMenu->clear(); - Mlt::Profile profile; - if (Mlt::Factory::filter(profile,(char*)"videostab")){ - QAction *action=stabMenu->addAction("Videostab (vstab)"); - action->setData("videostab"); - connect(action,SIGNAL(triggered()), this, SLOT(slotStabilize())); - } - if (Mlt::Factory::filter(profile,(char*)"videostab2")){ - QAction *action=stabMenu->addAction("Videostab (transcode)"); - action->setData("videostab2"); - connect(action,SIGNAL(triggered()), this, SLOT(slotStabilize())); - } - } - + QMenu* actionMenu= static_cast(factory()->container("clip_actions", this)); + if (actionMenu){ + actionMenu->clear(); + Mlt::Profile profile; + Mlt::Filter *filter = Mlt::Factory::filter(profile,(char*)"videostab"); + if (filter) { + if (!filter->is_valid()) { + delete filter; + } + else { + delete filter; + QAction *action=actionMenu->addAction(i18n("Stabilize (vstab)")); + action->setData("videostab"); + connect(action,SIGNAL(triggered()), this, SLOT(slotStartClipAction())); + } + } + filter = Mlt::Factory::filter(profile,(char*)"videostab2"); + if (filter) { + if (!filter->is_valid()) { + delete filter; + } + else { + delete filter; + QAction *action=actionMenu->addAction(i18n("Stabilize (transcode)")); + action->setData("videostab2"); + connect(action,SIGNAL(triggered()), this, SLOT(slotStartClipAction())); + } + } + filter = Mlt::Factory::filter(profile,(char*)"motion_est"); + if (filter) { + if (!filter->is_valid()) { + delete filter; + } + else { + delete filter; + QAction *action=actionMenu->addAction(i18n("Automatic scene split")); + action->setData("motion_est"); + connect(action,SIGNAL(triggered()), this, SLOT(slotStartClipAction())); + } + } + if (KdenliveSettings::producerslist().contains("framebuffer")) { + QAction *action=actionMenu->addAction(i18n("Reverse clip")); + action->setData("framebuffer"); + connect(action,SIGNAL(triggered()), this, SLOT(slotStartClipAction())); + } + } } @@ -3906,7 +4246,7 @@ void MainWindow::loadTranscoders() QMenu *extractAudioMenu = static_cast(factory()->container("extract_audio", this)); extractAudioMenu->clear(); - KSharedConfigPtr config = KSharedConfig::openConfig("kdenlivetranscodingrc"); + KSharedConfigPtr config = KSharedConfig::openConfig("kdenlivetranscodingrc", KConfig::CascadeConfig); KConfigGroup transConfig(config, "Transcoding"); // read the entries QMap< QString, QString > profiles = transConfig.entryMap(); @@ -3928,7 +4268,7 @@ void MainWindow::loadTranscoders() } } -void MainWindow::slotStabilize() +void MainWindow::slotStartClipAction() { QString condition,filtername; QStringList ids; @@ -3939,25 +4279,9 @@ void MainWindow::slotStabilize() filtername=action->data().toString(); } m_projectList->startClipFilterJob(filtername, condition); - /* - if (ids.isEmpty()) { - m_messageLabel->setMessage(i18n("No clip to transcode"), ErrorMessage); - return; - } - QString destination; - ProjectItem *item = m_projectList->getClipById(ids.at(0)); - if (ids.count() == 1) { - - } - ClipStabilize *d = new ClipStabilize(destination, ids.count(), filtername); - //connect(d, SIGNAL(addClip(KUrl)), this, SLOT(slotAddProjectClip(KUrl))); - if (d->exec() == QDialog::Accepted) { - m_projectList->slotStabilizeClipJob(ids, d->autoAddClip(), d->params(), d->desc()); - } - delete d;*/ } -void MainWindow::slotTranscode(KUrl::List urls) +void MainWindow::slotTranscode(const KUrl::List &urls) { QString params; QString desc; @@ -3966,8 +4290,10 @@ void MainWindow::slotTranscode(KUrl::List urls) QAction *action = qobject_cast(sender()); QStringList data = action->data().toStringList(); params = data.at(0); - if (data.count() > 1) desc = data.at(1); - if (data.count() > 3) condition = data.at(3); + if (data.count() > 1) + desc = data.at(1); + if (data.count() > 3) + condition = data.at(3); m_projectList->slotTranscodeClipJob(condition, params, desc); return; } @@ -3975,7 +4301,7 @@ void MainWindow::slotTranscode(KUrl::List urls) m_messageLabel->setMessage(i18n("No clip to transcode"), ErrorMessage); return; } - ClipTranscode *d = new ClipTranscode(urls, params, desc); + ClipTranscode *d = new ClipTranscode(urls, params, QStringList(), desc); connect(d, SIGNAL(addClip(KUrl)), this, SLOT(slotAddProjectClip(KUrl))); d->show(); } @@ -3987,7 +4313,7 @@ void MainWindow::slotTranscodeClip() slotTranscode(urls); } -void MainWindow::slotSetDocumentRenderProfile(QMap props) +void MainWindow::slotSetDocumentRenderProfile(const QMap &props) { if (m_activeDocument == NULL) return; QMapIterator i(props); @@ -4005,12 +4331,17 @@ void MainWindow::slotPrepareRendering(bool scriptExport, bool zoneOnly, const QS QString scriptPath; QString playlistPath; if (scriptExport) { - bool ok; - QString scriptsFolder = m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash) + "scripts/"; - QString path = m_renderWidget->getFreeScriptName(); - scriptPath = QInputDialog::getText(this, i18n("Create Render Script"), i18n("Script name (will be saved in: %1)", scriptsFolder), QLineEdit::Normal, KUrl(path).fileName(), &ok); - if (!ok || scriptPath.isEmpty()) return; - scriptPath.prepend(scriptsFolder); + //QString scriptsFolder = m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash) + "scripts/"; + QString path = m_renderWidget->getFreeScriptName(m_activeDocument->url()); + QPointer getUrl = new KUrlRequesterDialog(path, i18n("Create Render Script"), this); + getUrl->fileDialog()->setMode(KFile::File); + getUrl->fileDialog()->setOperationMode(KFileDialog::Saving); + if (getUrl->exec() == QDialog::Rejected) { + delete getUrl; + return; + } + scriptPath = getUrl->selectedUrl().path(); + delete getUrl; QFile f(scriptPath); if (f.exists()) { if (KMessageBox::warningYesNo(this, i18n("Script file already exists. Do you want to overwrite it?")) != KMessageBox::Yes) @@ -4040,7 +4371,7 @@ void MainWindow::slotPrepareRendering(bool scriptExport, bool zoneOnly, const QS QDomElement guidesxml = m_activeDocument->guidesXml(); QDomNodeList nodes = guidesxml.elementsByTagName("guide"); - for (int i = 0; i < nodes.count(); i++) { + for (int i = 0; i < nodes.count(); ++i) { QDomElement e = nodes.item(i).toElement(); if (!e.isNull()) { QString comment = e.attribute("comment"); @@ -4059,7 +4390,7 @@ void MainWindow::slotPrepareRendering(bool scriptExport, bool zoneOnly, const QS // Always insert a guide in pos 0 QDomElement chapter = doc.createElement("chapter"); chapters.insertBefore(chapter, QDomNode()); - chapter.setAttribute("title", i18n("Start")); + chapter.setAttribute("title", i18nc("the first in a list of chapters", "Start")); chapter.setAttribute("time", "0"); } // save chapters file @@ -4086,7 +4417,7 @@ void MainWindow::slotPrepareRendering(bool scriptExport, bool zoneOnly, const QS QDomElement tractor = doc.documentElement().firstChildElement("tractor"); if (!tractor.isNull()) { QDomNodeList props = tractor.elementsByTagName("property"); - for (int i = 0; i < props.count(); i++) { + for (int i = 0; i < props.count(); ++i) { if (props.at(i).toElement().attribute("name") == "meta.volume") { props.at(i).firstChild().setNodeValue("1"); break; @@ -4168,6 +4499,7 @@ void MainWindow::slotUpdateTimecodeFormat(int ix) m_effectStack->updateTimecodeFormat(); //m_activeTimeline->projectView()->clearSelection(); m_activeTimeline->updateRuler(); + slotUpdateMousePosition(m_activeTimeline->projectView()->getMousePos()); } void MainWindow::slotRemoveFocus() @@ -4225,11 +4557,11 @@ void MainWindow::slotChangePalette(QAction *action, const QString &themename) // 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 }; + 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++ ) { + for ( int i = 0; i < 3 ; ++i ) { QPalette::ColorGroup state = states[i]; KColorScheme schemeView(state, KColorScheme::View, config); KColorScheme schemeWindow(state, KColorScheme::Window, config); @@ -4338,7 +4670,7 @@ void MainWindow::slotInsertZoneToTimeline() } -void MainWindow::slotDeleteProjectClips(QStringList ids, QMap folderids) +void MainWindow::slotDeleteProjectClips(const QStringList &ids, const QMap &folderids) { if (m_activeDocument && m_activeTimeline) { if (!ids.isEmpty()) { @@ -4355,7 +4687,7 @@ void MainWindow::slotDeleteProjectClips(QStringList ids, QMap void MainWindow::slotShowTitleBars(bool show) { QList docks = findChildren(); - for (int i = 0; i < docks.count(); i++) { + for (int i = 0; i < docks.count(); ++i) { QDockWidget* dock = docks.at(i); if (show) { dock->setTitleBarWidget(0); @@ -4391,7 +4723,7 @@ void MainWindow::slotMonitorRequestRenderFrame(bool request) m_projectMonitor->render->sendFrameForAnalysis = true; return; } else { - for (int i = 0; i < m_gfxScopesList.count(); i++) { + 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; @@ -4411,12 +4743,12 @@ void MainWindow::slotOpenStopmotion() { if (m_stopmotion == NULL) { 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++) { - // 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(); + connect(m_stopmotion, SIGNAL(addOrUpdateSequence(QString)), m_projectList, SLOT(slotAddOrUpdateSequence(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(); @@ -4451,11 +4783,13 @@ 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(); + if (d->exec()) { + m_messageLabel->setMessage(i18n("Archiving project"), OperationCompletedMessage); + } } -void MainWindow::slotOpenBackupDialog(const KUrl url) +void MainWindow::slotOpenBackupDialog(const KUrl &url) { KUrl projectFile; KUrl projectFolder; @@ -4497,7 +4831,7 @@ void MainWindow::slotDownloadResources() if (m_activeDocument) currentFolder = m_activeDocument->projectFolder().path(); else currentFolder = KdenliveSettings::defaultprojectfolder(); ResourceWidget *d = new ResourceWidget(currentFolder); - connect(d, SIGNAL(addClip(KUrl, QMap )), this, SLOT(slotAddProjectClip(KUrl, QMap ))); + connect(d, SIGNAL(addClip(KUrl,stringMap)), this, SLOT(slotAddProjectClip(KUrl,stringMap))); d->show(); } @@ -4520,16 +4854,77 @@ void MainWindow::slotChangePalette() void MainWindow::slotSaveTimelineClip() { if (m_activeTimeline && m_projectMonitor->render) { - ClipItem *clip = m_activeTimeline->projectView()->getActiveClipUnderCursor(true); - if (!clip) { - m_messageLabel->setMessage(i18n("Select a clip to save"), InformationMessage); - return; - } - KUrl url = KFileDialog::getSaveUrl(m_activeDocument->projectFolder(), "video/mlt-playlist"); - if (!url.isEmpty()) m_projectMonitor->render->saveClip(m_activeDocument->tracksCount() - clip->track(), clip->startPos(), url); + ClipItem *clip = m_activeTimeline->projectView()->getActiveClipUnderCursor(true); + if (!clip) { + m_messageLabel->setMessage(i18n("Select a clip to save"), InformationMessage); + return; + } + KUrl url = KFileDialog::getSaveUrl(m_activeDocument->projectFolder(), "video/mlt-playlist"); + if (!url.isEmpty()) m_projectMonitor->render->saveClip(m_activeDocument->tracksCount() - clip->track(), clip->startPos(), url); } } +void MainWindow::slotProcessImportKeyframes(GraphicsRectItem type, const QString& data, int maximum) +{ + if (type == AVWidget) { + // This data should be sent to the effect stack + m_effectStack->setKeyframes(data, maximum); + } + else if (type == TransitionWidget) { + // This data should be sent to the transition stack + m_transitionConfig->setKeyframes(data, maximum); + } + else { + // Error + } +} + +void MainWindow::slotAlignPlayheadToMousePos() +{ + m_monitorManager->activateMonitor(Kdenlive::ProjectMonitor); + m_activeTimeline->projectView()->slotAlignPlayheadToMousePos(); +} + +void MainWindow::slotSetDeinterlacer(int ix) +{ + QString value; + switch (ix) { + + case 1: + value = "linearblend"; + break; + case 2: + value = "yadif-nospatial"; + break; + case 3: + value = "yadif"; + break; + default: + value = "onefield"; + } + KdenliveSettings::setMltdeinterlacer(value); + m_monitorManager->setConsumerProperty("deinterlace_method", value); +} + +void MainWindow::slotSetInterpolation(int ix) +{ + QString value; + switch (ix) { + case 1: + value = "bilinear"; + break; + case 2: + value = "bicubic"; + break; + case 3: + value = "hyper"; + break; + default: + value = "nearest"; + } + KdenliveSettings::setMltinterpolation(value); + m_monitorManager->setConsumerProperty("rescale", value); +} #include "mainwindow.moc"