]> git.sesse.net Git - kdenlive/blobdiff - src/mainwindow.cpp
Fix View menu not updated when closing a dock: http://kdenlive.org/mantis/view.php...
[kdenlive] / src / mainwindow.cpp
index 60bb5fa1c3de1aa8dc9915ef58747a176489957c..a308439498866d2206bcd30e6ade12c190493650 100644 (file)
@@ -142,6 +142,11 @@ EffectsList MainWindow::transitions;
 
 QMap <QString,QImage> MainWindow::m_lumacache;
 
+static bool sortByNames(const QPair<QString, KAction*> &a, const QPair<QString, KAction*> &b)
+{
+    return a.first < b.first;
+}
+
 MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & clipsToLoad, QWidget *parent) :
     KXmlGuiWindow(parent),
     m_activeDocument(NULL),
@@ -467,12 +472,12 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
 
     QMenu *clipInTimeline = static_cast<QMenu*>(factory()->container("clip_in_timeline", this));
     clipInTimeline->setIcon(KIcon("go-jump"));
-       QHash<QString,QMenu*> menus;
-       menus.insert("addMenu",static_cast<QMenu*>(factory()->container("generators", this)));
-        menus.insert("extractAudioMenu",static_cast<QMenu*>(factory()->container("extract_audio", this)));
-       menus.insert("transcodeMenu",static_cast<QMenu*>(factory()->container("transcoders", this)));
-       menus.insert("clipActionsMenu",static_cast<QMenu*>(factory()->container("clip_actions", this)));
-       menus.insert("inTimelineMenu",clipInTimeline);
+    QHash<QString,QMenu*> menus;
+    menus.insert("addMenu",static_cast<QMenu*>(factory()->container("generators", this)));
+    menus.insert("extractAudioMenu",static_cast<QMenu*>(factory()->container("extract_audio", this)));
+    menus.insert("transcodeMenu",static_cast<QMenu*>(factory()->container("transcoders", this)));
+    menus.insert("clipActionsMenu",static_cast<QMenu*>(factory()->container("clip_actions", this)));
+    menus.insert("inTimelineMenu",clipInTimeline);
     m_projectList->setupGeneratorMenu(menus);
 
     // build themes menus
@@ -574,29 +579,6 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
 
     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 <QUrl> 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
@@ -605,33 +587,41 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
     actionCollection()->addAssociatedWidget(m_clipMonitor->container());
     actionCollection()->addAssociatedWidget(m_projectMonitor->container());
 
-    QMap <QString, KAction *> viewActions;
+    QList<QPair<QString, KAction *> > viewActions;
+    QPair <QString, KAction *> 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<KMenu*>(factory()->container("dockwindows", this));
+    pair.first = showTimeline->text();
+    pair.second = showTimeline;
+    viewActions.append(pair);
     
     QList <QDockWidget *> docks = findChildren<QDockWidget *>();
     for (int i = 0; i < docks.count(); i++) {
         QDockWidget* dock = docks.at(i);
+       QAction * a = dock->toggleViewAction();
+       if (!a) continue;
        KAction* dockInformations = new KAction(this);
-       dockInformations->setText(dock->windowTitle());
+       dockInformations->setText(a->text());
        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<KMenu*>(factory()->container("dockwindows", this));
-    //const QList<QAction *> viewActions = createPopupMenu()->actions();
-    QMap<QString, KAction *>::const_iterator i = viewActions.constBegin();
-    while (i != viewActions.constEnd()) {
-       viewMenu->addAction(guiActions->addAction(i.key(), i.value()));
-       ++i;
+       // 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");
     if (KdenliveSettings::proxyparams().isEmpty() || KdenliveSettings::proxyextension().isEmpty()) {
@@ -669,6 +659,30 @@ 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 <QUrl> urls;
+        foreach(const QString &path, list) {
+            kDebug() << QDir::current().absoluteFilePath(path);
+            urls << QUrl::fromLocalFile(QDir::current().absoluteFilePath(path));
+        }
+        m_projectList->slotAddClip(urls);
+    }
+    
 }
 
 MainWindow::~MainWindow()
@@ -676,6 +690,12 @@ MainWindow::~MainWindow()
     if (m_stopmotion) {
         delete m_stopmotion;
     }
+
+#ifdef USE_JOGSHUTTLE
+    if (m_jogProcess)
+       delete m_jogProcess;
+#endif
+
     m_effectStack->slotClipItemSelected(NULL);
     m_transitionConfig->slotTransitionItemSelected(NULL, 0, QPoint(), false);
 
@@ -919,7 +939,6 @@ void MainWindow::slotConnectMonitors()
     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 &)));
 
-    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(removeInvalidClip(const QString &, bool)), m_projectList, SLOT(slotRemoveInvalidClip(const QString &, bool)));
@@ -1248,14 +1267,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()));
 
@@ -1510,14 +1527,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);
@@ -2058,11 +2081,14 @@ void MainWindow::openFile()
 
 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)
@@ -2184,7 +2210,6 @@ 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);
     slotGotProgressInfo(QString(), -1);
@@ -2574,7 +2599,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc)   //cha
     connect(trackView->projectView(), SIGNAL(forceClipProcessing(const QString &)), m_projectList, SLOT(slotForceProcessing(const QString &)));
 
     connect(trackView->projectView(), SIGNAL(importKeyframes(GRAPHICSRECTITEM, const QString&, int)), this, SLOT(slotProcessImportKeyframes(GRAPHICSRECTITEM, const 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()));
@@ -3295,12 +3320,12 @@ void MainWindow::slotShowClipProperties(DocClipBase *clip)
         if (dia_ui->exec() == QDialog::Accepted) {
             QMap <QString, QString> 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));
+                if (currentLength <= dia_ui->duration())
+                        newprops.insert("length", QString::number(dia_ui->duration()));
                 else newprops.insert("length", clip->producerProperty("length"));
             }
             if (!path.isEmpty()) {
@@ -3917,24 +3942,39 @@ void MainWindow::loadClipActions()
                Mlt::Profile profile;
                Mlt::Filter *filter = Mlt::Factory::filter(profile,(char*)"videostab");
                if (filter) {
-                       delete filter;
-                       QAction *action=actionMenu->addAction(i18n("Stabilize (vstab)"));
-                       action->setData("videostab");
-                       connect(action,SIGNAL(triggered()), this, SLOT(slotStartClipAction()));
+                       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) {
-                       delete filter;
-                       QAction *action=actionMenu->addAction(i18n("Stabilize (transcode)"));
-                       action->setData("videostab2");
-                       connect(action,SIGNAL(triggered()), this, SLOT(slotStartClipAction()));
+                       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) {
-                       delete filter;
-                       QAction *action=actionMenu->addAction(i18n("Automatic scene split"));
-                       action->setData("motion_est");
-                       connect(action,SIGNAL(triggered()), this, SLOT(slotStartClipAction()));
+                       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()));
+                       }
                }
        }