X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmainwindow.cpp;h=e4cc0fbb6c9c8dc1753c4fc60976062197dd74df;hb=2950bfaa74c8dbc91e72634a8c2efbc107f571ae;hp=46f0fd9c81338a378f28e377d2a4aeb4f3d1c1eb;hpb=98b9fcdb9c5a4e84489b37d253a7491d6a4d17ef;p=kdenlive diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 46f0fd9c..e4cc0fbb 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -51,6 +51,7 @@ #include "interfaces.h" #include "kdenlive-config.h" #include "cliptranscode.h" +#include "ui_templateclip_ui.h" #include #include @@ -70,6 +71,7 @@ #include #include #include +#include #include #include #include @@ -79,11 +81,13 @@ #include #include #include +#include #include #include #include #include +#include #include @@ -148,6 +152,9 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, QWidget *parent m_projectListDock->setWidget(m_projectList); addDockWidget(Qt::TopDockWidgetArea, m_projectListDock); + m_shortcutRemoveFocus = new QShortcut(QKeySequence("Esc"), this); + connect(m_shortcutRemoveFocus, SIGNAL(activated()), this, SLOT(slotRemoveFocus())); + m_effectListDock = new QDockWidget(i18n("Effect List"), this); m_effectListDock->setObjectName("effect_list"); m_effectList = new EffectsListView(); @@ -173,19 +180,22 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, QWidget *parent actionCollection()); readOptions(); + //slotDetectAudioDriver(); + m_clipMonitorDock = new QDockWidget(i18n("Clip Monitor"), this); m_clipMonitorDock->setObjectName("clip_monitor"); - m_clipMonitor = new Monitor("clip", m_monitorManager, this); + m_clipMonitor = new Monitor("clip", m_monitorManager, QString(), this); m_clipMonitorDock->setWidget(m_clipMonitor); addDockWidget(Qt::TopDockWidgetArea, m_clipMonitorDock); //m_clipMonitor->stop(); m_projectMonitorDock = new QDockWidget(i18n("Project Monitor"), this); m_projectMonitorDock->setObjectName("project_monitor"); - m_projectMonitor = new Monitor("project", m_monitorManager, this); + m_projectMonitor = new Monitor("project", m_monitorManager, QString(), this); m_projectMonitorDock->setWidget(m_projectMonitor); addDockWidget(Qt::TopDockWidgetArea, m_projectMonitorDock); +#ifndef Q_WS_MAC m_recMonitorDock = new QDockWidget(i18n("Record Monitor"), this); m_recMonitorDock->setObjectName("record_monitor"); m_recMonitor = new RecMonitor("record", this); @@ -194,6 +204,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, QWidget *parent connect(m_recMonitor, SIGNAL(addProjectClip(KUrl)), this, SLOT(slotAddProjectClip(KUrl))); connect(m_recMonitor, SIGNAL(showConfigDialog(int, int)), this, SLOT(slotPreferences(int, int))); +#endif m_undoViewDock = new QDockWidget(i18n("Undo History"), this); m_undoViewDock->setObjectName("undo_history"); @@ -218,11 +229,14 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, QWidget *parent tabifyDockWidget(m_clipMonitorDock, m_projectMonitorDock); +#ifndef Q_WS_MAC tabifyDockWidget(m_clipMonitorDock, m_recMonitorDock); +#endif setCentralWidget(m_timelineArea); setupGUI(); + /*ScriptingPart* sp = new ScriptingPart(this, QStringList()); guiFactory()->addClient(sp);*/ @@ -323,7 +337,6 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, QWidget *parent m_timelineContextMenu->addAction(actionCollection()->action(KStandardAction::name(KStandardAction::Paste))); m_timelineContextClipMenu->addAction(actionCollection()->action("delete_timeline_clip")); - m_timelineContextClipMenu->addAction(actionCollection()->action("change_clip_speed")); m_timelineContextClipMenu->addAction(actionCollection()->action("group_clip")); m_timelineContextClipMenu->addAction(actionCollection()->action("ungroup_clip")); m_timelineContextClipMenu->addAction(actionCollection()->action("cut_timeline_clip")); @@ -348,7 +361,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, QWidget *parent connect(m_clipMonitorDock, SIGNAL(visibilityChanged(bool)), m_clipMonitor, SLOT(refreshMonitor(bool))); //connect(m_monitorManager, SIGNAL(connectMonitors()), this, SLOT(slotConnectMonitors())); connect(m_monitorManager, SIGNAL(raiseClipMonitor(bool)), this, SLOT(slotRaiseMonitor(bool))); - connect(m_effectList, SIGNAL(addEffect(QDomElement)), this, SLOT(slotAddEffect(QDomElement))); + connect(m_effectList, SIGNAL(addEffect(const QDomElement)), this, SLOT(slotAddEffect(const QDomElement))); connect(m_effectList, SIGNAL(reloadEffects()), this, SLOT(slotReloadEffects())); m_monitorManager->initMonitors(m_clipMonitor, m_projectMonitor); @@ -376,13 +389,42 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, QWidget *parent void MainWindow::queryQuit() { - kDebug() << "----- SAVING CONFUIG"; - if (queryClose()) kapp->quit(); + if (queryClose()) { + if (m_projectMonitor) m_projectMonitor->stop(); + if (m_clipMonitor) m_clipMonitor->stop(); + delete m_effectStack; + delete m_activeTimeline; +#ifndef Q_WS_MAC + // This sometimes causes crash on exit on OS X for some reason. + delete m_projectMonitor; + delete m_clipMonitor; +#endif + delete m_activeDocument; + delete m_shortcutRemoveFocus; + Mlt::Factory::close(); + kapp->quit(); + } } //virtual bool MainWindow::queryClose() { + if (m_renderWidget) { + int waitingJobs = m_renderWidget->waitingJobsCount(); + if (waitingJobs > 0) { + switch (KMessageBox::warningYesNoCancel(this, i18np("You have 1 rendering job waiting in the queue.\nWhat do you want to do with this job?", "You have %1 rendering jobs waiting in the queue.\nWhat do you want to do with these jobs?", waitingJobs), QString(), KGuiItem(i18n("Start them now")), KGuiItem(i18n("Delete them")))) { + case KMessageBox::Yes : + // create script with waiting jobs and start it + if (m_renderWidget->startWaitingRenderJobs() == false) return false; + break; + case KMessageBox::No : + // Don't do anything, jobs will be deleted + break; + default: + return false; + } + } + } saveOptions(); if (m_monitorManager) m_monitorManager->stopActiveMonitor(); if (m_activeDocument && m_activeDocument->isModified()) { @@ -471,25 +513,30 @@ void MainWindow::generateClip() } } -void MainWindow::saveProperties(KConfig*) +void MainWindow::saveProperties(KConfigGroup &config) { // save properties here,used by session management saveFile(); + KMainWindow::saveProperties(config); } -void MainWindow::readProperties(KConfig *config) +void MainWindow::readProperties(const KConfigGroup &config) { // read properties here,used by session management - QString Lastproject = config->group("Recent Files").readPathEntry("File1", QString()); + KMainWindow::readProperties(config); + QString Lastproject = config.group("Recent Files").readPathEntry("File1", QString()); openFile(KUrl(Lastproject)); } void MainWindow::slotReloadEffects() { - initEffects::parseCustomEffectsFile(); + kDebug() << "START RELOAD; COUNR: " << m_customEffectsMenu->actions().count(); m_customEffectsMenu->clear(); + kDebug() << "START RELOAD; CLR: " << m_customEffectsMenu->actions().count(); + initEffects::parseCustomEffectsFile(); const QStringList effects = customEffects.effectNames(); + kDebug() << "NEW EFFS: " << effects; QAction *action; if (effects.isEmpty()) m_customEffectsMenu->setEnabled(false); else m_customEffectsMenu->setEnabled(true); @@ -563,14 +610,15 @@ void MainWindow::slotFullScreen() KToggleFullScreenAction::setFullScreen(this, actionCollection()->action("fullscreen")->isChecked()); } -void MainWindow::slotAddEffect(QDomElement effect, GenTime pos, int track) +void MainWindow::slotAddEffect(const QDomElement effect, GenTime pos, int track) { if (!m_activeDocument) return; if (effect.isNull()) { kDebug() << "--- ERROR, TRYING TO APPEND NULL EFFECT"; return; } - m_activeTimeline->projectView()->slotAddEffect(effect.cloneNode().toElement(), pos, track); + QDomElement effectToAdd = effect.cloneNode().toElement(); + m_activeTimeline->projectView()->slotAddEffect(effectToAdd, pos, track); } void MainWindow::slotRaiseMonitor(bool clipMonitor) @@ -589,9 +637,9 @@ void MainWindow::slotConnectMonitors() { m_projectList->setRenderer(m_projectMonitor->render); - connect(m_projectList, SIGNAL(receivedClipDuration(const QString &)), this, SLOT(slotUpdateClip(const QString &))); + //connect(m_projectList, SIGNAL(receivedClipDuration(const QString &)), this, SLOT(slotUpdateClip(const QString &))); connect(m_projectList, SIGNAL(showClipProperties(DocClipBase *)), this, SLOT(slotShowClipProperties(DocClipBase *))); - connect(m_projectList, SIGNAL(getFileProperties(const QDomElement &, const QString &, bool)), m_projectMonitor->render, SLOT(getFileProperties(const QDomElement &, const QString &, bool))); + connect(m_projectList, SIGNAL(getFileProperties(const QDomElement, const QString &, bool)), m_projectMonitor->render, SLOT(getFileProperties(const QDomElement, const QString &, bool))); connect(m_projectMonitor->render, SIGNAL(replyGetImage(const QString &, const QPixmap &)), m_projectList, SLOT(slotReplyGetImage(const QString &, const QPixmap &))); connect(m_projectMonitor->render, SIGNAL(replyGetFileProperties(const QString &, Mlt::Producer*, const QMap < QString, QString > &, const QMap < QString, QString > &, bool)), m_projectList, SLOT(slotReplyGetFileProperties(const QString &, Mlt::Producer*, const QMap < QString, QString > &, const QMap < QString, QString > &, bool))); @@ -627,6 +675,8 @@ void MainWindow::setupActions() 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); @@ -634,29 +684,26 @@ void MainWindow::setupActions() m_statusProgressBar->setMaximumWidth(150); m_statusProgressBar->setVisible(false); - QWidget *w = new QWidget; - - QHBoxLayout *layout = new QHBoxLayout; - w->setLayout(layout); - layout->setContentsMargins(5, 0, 5, 0); - QToolBar *toolbar = new QToolBar("statusToolBar", this); - - + KToolBar *toolbar = new KToolBar("statusToolBar", this, Qt::BottomToolBarArea); + toolbar->setMovable(false); m_toolGroup = new QActionGroup(this); - - QString style1 = "QToolButton {background-color: rgba(230, 230, 230, 220); border-style: inset; border:1px solid #999999;border-radius: 3px;margin: 0px 3px;padding: 0px;} QToolButton:checked { background-color: rgba(224, 224, 0, 100); border-style: inset; border:1px solid #cc6666;border-radius: 3px;}"; + statusBar()->setStyleSheet(QString("QStatusBar QLabel {font-size:%1pt;} QStatusBar::item { border: 0px; font-size:%1pt;padding:0px; }").arg(statusBar()->font().pointSize())); + QString style1 = "QToolBar { border: 0px } QToolButton {background-color: rgba(230, 230, 230, 220); border-style: inset; border:1px solid #999999;border-radius: 3px;margin: 0px 3px;padding: 0px;} QToolButton:checked { background-color: rgba(224, 224, 0, 100); border-style: inset; border:1px solid #cc6666;border-radius: 3px;}"; m_buttonSelectTool = new KAction(KIcon("kdenlive-select-tool"), i18n("Selection tool"), this); + m_buttonSelectTool->setShortcut(i18nc("Selection tool shortcut", "s")); toolbar->addAction(m_buttonSelectTool); m_buttonSelectTool->setCheckable(true); m_buttonSelectTool->setChecked(true); m_buttonRazorTool = new KAction(KIcon("edit-cut"), i18n("Razor tool"), this); + m_buttonRazorTool->setShortcut(i18nc("Razor tool shortcut", "x")); toolbar->addAction(m_buttonRazorTool); m_buttonRazorTool->setCheckable(true); m_buttonRazorTool->setChecked(false); m_buttonSpacerTool = new KAction(KIcon("kdenlive-spacer-tool"), i18n("Spacer tool"), this); + m_buttonSpacerTool->setShortcut(i18nc("Spacer tool shortcut", "m")); toolbar->addAction(m_buttonSpacerTool); m_buttonSpacerTool->setCheckable(true); m_buttonSpacerTool->setChecked(false); @@ -668,17 +715,18 @@ void MainWindow::setupActions() toolbar->setToolButtonStyle(Qt::ToolButtonIconOnly); QWidget * actionWidget; + int max = toolbar->iconSizeDefault() + 2; actionWidget = toolbar->widgetForAction(m_buttonSelectTool); - actionWidget->setMaximumWidth(24); - actionWidget->setMinimumHeight(18); + actionWidget->setMaximumWidth(max); + actionWidget->setMaximumHeight(max - 4); actionWidget = toolbar->widgetForAction(m_buttonRazorTool); - actionWidget->setMaximumWidth(24); - actionWidget->setMinimumHeight(18); + actionWidget->setMaximumWidth(max); + actionWidget->setMaximumHeight(max - 4); actionWidget = toolbar->widgetForAction(m_buttonSpacerTool); - actionWidget->setMaximumWidth(24); - actionWidget->setMinimumHeight(18); + actionWidget->setMaximumWidth(max); + actionWidget->setMaximumHeight(max - 4); toolbar->setStyleSheet(style1); connect(m_toolGroup, SIGNAL(triggered(QAction *)), this, SLOT(slotChangeTool(QAction *))); @@ -690,8 +738,8 @@ void MainWindow::setupActions() connect(m_buttonFitZoom, SIGNAL(triggered()), this, SLOT(slotFitZoom())); actionWidget = toolbar->widgetForAction(m_buttonFitZoom); - actionWidget->setMaximumWidth(24); - actionWidget->setMinimumHeight(18); + actionWidget->setMaximumWidth(max); + actionWidget->setMaximumHeight(max - 4); m_zoomSlider = new QSlider(Qt::Horizontal, this); m_zoomSlider->setMaximum(13); @@ -699,18 +747,6 @@ void MainWindow::setupActions() m_zoomSlider->setMaximumWidth(150); m_zoomSlider->setMinimumWidth(100); - - const int contentHeight = QFontMetrics(w->font()).height() + 8; - - QString style = "QSlider::groove:horizontal { background-color: rgba(230, 230, 230, 220);border: 1px solid #999999;height: 8px;border-radius: 3px;margin-top:3px }"; - style.append("QSlider::handle:horizontal { background-color: white; border: 1px solid #999999;width: 9px;margin: -2px 0;border-radius: 3px; }"); - - m_zoomSlider->setStyleSheet(style); - - //m_zoomSlider->height() + 5; - statusBar()->setMinimumHeight(contentHeight); - - toolbar->addWidget(m_zoomSlider); m_buttonVideoThumbs = new KAction(KIcon("kdenlive-show-videothumb"), i18n("Show video thumbnails"), this); @@ -736,35 +772,32 @@ void MainWindow::setupActions() m_buttonSnap->setCheckable(true); m_buttonSnap->setChecked(KdenliveSettings::snaptopoints()); connect(m_buttonSnap, SIGNAL(triggered()), this, SLOT(slotSwitchSnap())); - layout->addWidget(toolbar); - actionWidget = toolbar->widgetForAction(m_buttonVideoThumbs); - actionWidget->setMaximumWidth(24); - actionWidget->setMinimumHeight(18); + actionWidget->setMaximumWidth(max); + actionWidget->setMaximumHeight(max - 4); actionWidget = toolbar->widgetForAction(m_buttonAudioThumbs); - actionWidget->setMaximumWidth(24); - actionWidget->setMinimumHeight(18); + actionWidget->setMaximumWidth(max); + actionWidget->setMaximumHeight(max - 4); actionWidget = toolbar->widgetForAction(m_buttonShowMarkers); - actionWidget->setMaximumWidth(24); - actionWidget->setMinimumHeight(18); + actionWidget->setMaximumWidth(max); + actionWidget->setMaximumHeight(max - 4); actionWidget = toolbar->widgetForAction(m_buttonSnap); - actionWidget->setMaximumWidth(24); - actionWidget->setMinimumHeight(18); + actionWidget->setMaximumWidth(max); + actionWidget->setMaximumHeight(max - 4); m_messageLabel = new StatusBarMessageLabel(this); m_messageLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding); statusBar()->addWidget(m_messageLabel, 10); statusBar()->addWidget(m_statusProgressBar, 0); - statusBar()->addPermanentWidget(w); + statusBar()->addPermanentWidget(toolbar); statusBar()->insertPermanentFixedItem("00:00:00:00", ID_TIMELINE_POS); statusBar()->addPermanentWidget(m_timecodeFormat); - statusBar()->setMaximumHeight(statusBar()->font().pointSize() * 4); - m_messageLabel->hide(); + //statusBar()->setMaximumHeight(statusBar()->font().pointSize() * 3); collection->addAction("select_tool", m_buttonSelectTool); collection->addAction("razor_tool", m_buttonRazorTool); @@ -801,7 +834,7 @@ void MainWindow::setupActions() collection->addAction("manage_profiles", profilesAction); connect(profilesAction, SIGNAL(triggered(bool)), this, SLOT(slotEditProfiles())); - KNS::standardAction(i18n("Download New Lumas..."), this, SLOT(slotGetNewLumaStuff()), actionCollection(), "get_new_lumas"); + KNS::standardAction(i18n("Download New Wipes..."), this, SLOT(slotGetNewLumaStuff()), actionCollection(), "get_new_lumas"); KNS::standardAction(i18n("Download New Render Profiles..."), this, SLOT(slotGetNewRenderStuff()), actionCollection(), "get_new_profiles"); @@ -820,6 +853,10 @@ void MainWindow::setupActions() projectRender->setShortcut(Qt::CTRL + Qt::Key_Return); connect(projectRender, SIGNAL(triggered(bool)), this, SLOT(slotRenderProject())); + KAction* projectClean = new KAction(KIcon("edit-clear"), i18n("Clean Project"), this); + collection->addAction("project_clean", projectClean); + connect(projectClean, SIGNAL(triggered(bool)), this, SLOT(slotCleanProject())); + KAction* monitorPlay = new KAction(KIcon("media-playback-start"), i18n("Play"), this); KShortcut playShortcut; playShortcut.setPrimary(Qt::Key_Space); @@ -921,10 +958,10 @@ void MainWindow::setupActions() collection->addAction("delete_timeline_clip", deleteTimelineClip); connect(deleteTimelineClip, SIGNAL(triggered(bool)), this, SLOT(slotDeleteTimelineClip())); - KAction* editTimelineClipSpeed = new KAction(i18n("Change Clip Speed"), this); + /*KAction* editTimelineClipSpeed = new KAction(i18n("Change Clip Speed"), this); collection->addAction("change_clip_speed", editTimelineClipSpeed); editTimelineClipSpeed->setData("change_speed"); - connect(editTimelineClipSpeed, SIGNAL(triggered(bool)), this, SLOT(slotChangeClipSpeed())); + connect(editTimelineClipSpeed, SIGNAL(triggered(bool)), this, SLOT(slotChangeClipSpeed()));*/ KAction *stickTransition = collection->addAction("auto_transition"); stickTransition->setData(QString("auto")); @@ -934,11 +971,13 @@ void MainWindow::setupActions() connect(stickTransition, SIGNAL(triggered(bool)), this, SLOT(slotAutoTransition())); KAction* groupClip = new KAction(KIcon("object-group"), i18n("Group Clips"), this); + groupClip->setShortcut(Qt::CTRL + Qt::Key_G); collection->addAction("group_clip", groupClip); connect(groupClip, SIGNAL(triggered(bool)), this, SLOT(slotGroupClips())); KAction* ungroupClip = new KAction(KIcon("object-ungroup"), i18n("Ungroup Clips"), this); collection->addAction("ungroup_clip", ungroupClip); + ungroupClip->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_G); ungroupClip->setData("ungroup_clip"); connect(ungroupClip, SIGNAL(triggered(bool)), this, SLOT(slotUnGroupClips())); @@ -1095,6 +1134,10 @@ void MainWindow::setupActions() collection->addAction("add_text_clip", addTitleClip); connect(addTitleClip , SIGNAL(triggered()), m_projectList, SLOT(slotAddTitleClip())); + QAction *addTitleTemplateClip = new KAction(KIcon("kdenlive-add-text-clip"), i18n("Add Template Title"), this); + collection->addAction("add_text_template_clip", addTitleTemplateClip); + connect(addTitleTemplateClip , SIGNAL(triggered()), m_projectList, SLOT(slotAddTitleTemplateClip())); + QAction *addFolderButton = new KAction(KIcon("folder-new"), i18n("Create Folder"), this); collection->addAction("add_folder", addFolderButton); connect(addFolderButton , SIGNAL(triggered()), m_projectList, SLOT(slotAddFolder())); @@ -1128,6 +1171,7 @@ void MainWindow::setupActions() addClips->addAction(addColorClip); addClips->addAction(addSlideClip); addClips->addAction(addTitleClip); + addClips->addAction(addTitleTemplateClip); addClips->addAction(addFolderButton); addClips->addAction(reloadClip); @@ -1162,15 +1206,17 @@ void MainWindow::readOptions() KConfigGroup initialGroup(config, "version"); bool upgrade = false; if (initialGroup.exists()) { - if (initialGroup.readEntry("version", QString()).section(' ', 0, 0) != QString(version).section(' ', 0, 0)) + if (initialGroup.readEntry("version", QString()).section(' ', 0, 0) != QString(version).section(' ', 0, 0)) { upgrade = true; + } if (initialGroup.readEntry("version") == "0.7") { //Add new settings from 0.7.1 if (KdenliveSettings::defaultprojectfolder().isEmpty()) { QString path = QDir::homePath() + "/kdenlive"; - if (KStandardDirs::makeDir(path) == false) kDebug() << "/// ERROR CREATING PROJECT FOLDER: " << path; - KdenliveSettings::setDefaultprojectfolder(path); + if (KStandardDirs::makeDir(path) == false) { + kDebug() << "/// ERROR CREATING PROJECT FOLDER: " << path; + } else KdenliveSettings::setDefaultprojectfolder(path); } } @@ -1204,14 +1250,16 @@ void MainWindow::slotRunWizard() void MainWindow::newFile(bool showProjectSettings) { + if (!m_timelineArea->isEnabled()) return; QString profileName; KUrl projectFolder; QPoint projectTracks(KdenliveSettings::videotracks(), KdenliveSettings::audiotracks()); if (!showProjectSettings && m_timelineArea->count() == 0) { if (!KdenliveSettings::activatetabs()) closeCurrentDocument(); profileName = KdenliveSettings::default_profile(); + projectFolder = KdenliveSettings::defaultprojectfolder(); } else { - ProjectSettings *w = new ProjectSettings(projectTracks.x(), projectTracks.y(), KdenliveSettings::defaultprojectfolder(), false, this); + ProjectSettings *w = new ProjectSettings(NULL, projectTracks.x(), projectTracks.y(), KdenliveSettings::defaultprojectfolder(), false, true, this); if (w->exec() != QDialog::Accepted) return; if (!KdenliveSettings::activatetabs()) closeCurrentDocument(); KdenliveSettings::setVideothumbnails(w->enableVideoThumbs()); @@ -1225,8 +1273,17 @@ void MainWindow::newFile(bool showProjectSettings) } KdenliveDoc *doc = new KdenliveDoc(KUrl(), projectFolder, m_commandStack, profileName, projectTracks, m_projectMonitor->render, this); doc->m_autosave = new KAutoSaveFile(KUrl(), doc); - TrackView *trackView = new TrackView(doc, this); + bool ok; + TrackView *trackView = new TrackView(doc, &ok, this); m_timelineArea->addTab(trackView, KIcon("kdenlive"), doc->description()); + if (!ok) { + // MLT is broken + m_timelineArea->setEnabled(false); + m_projectList->setEnabled(false); + m_monitorManager->slotBlockMonitors(); + slotPreferences(6); + return; + } if (m_timelineArea->count() == 1) { connectDocumentInfo(doc); connectDocument(trackView, doc); @@ -1236,7 +1293,7 @@ void MainWindow::newFile(bool showProjectSettings) void MainWindow::activateDocument() { - if (m_timelineArea->currentWidget() == NULL) return; + if (m_timelineArea->currentWidget() == NULL || !m_timelineArea->isEnabled()) return; TrackView *currentTab = (TrackView *) m_timelineArea->currentWidget(); KdenliveDoc *currentDoc = currentTab->document(); connectDocumentInfo(currentDoc); @@ -1261,6 +1318,7 @@ void MainWindow::closeCurrentDocument() break; case KMessageBox::Cancel : return; + break; default: break; } @@ -1270,13 +1328,16 @@ void MainWindow::closeCurrentDocument() m_timelineArea->setTabBarHidden(true); m_closeAction->setEnabled(false); } - delete docToClose; - delete w; - if (m_timelineArea->count() == 0) { + if (docToClose == m_activeDocument) { + delete m_activeDocument; m_activeDocument = NULL; m_effectStack->clear(); - m_transitionConfig->slotTransitionItemSelected(NULL, false); - } + m_transitionConfig->slotTransitionItemSelected(NULL, 0, QPoint(), false); + } else delete docToClose; + if (w == m_activeTimeline) { + delete m_activeTimeline; + m_activeTimeline = NULL; + } else delete w; } bool MainWindow::saveFileAs(const QString &outputFileName) @@ -1398,7 +1459,8 @@ void MainWindow::openFile(const KUrl &url) void MainWindow::doOpenFile(const KUrl &url, KAutoSaveFile *stale) { - KdenliveDoc *doc = new KdenliveDoc(url, KUrl(), m_commandStack, QString(), QPoint(3, 2), m_projectMonitor->render, this); + if (!m_timelineArea->isEnabled()) return; + KdenliveDoc *doc = new KdenliveDoc(url, KdenliveSettings::defaultprojectfolder(), m_commandStack, KdenliveSettings::default_profile(), QPoint(KdenliveSettings::videotracks(), KdenliveSettings::audiotracks()), m_projectMonitor->render, this); if (stale == NULL) { stale = new KAutoSaveFile(url, doc); doc->m_autosave = stale; @@ -1409,8 +1471,16 @@ void MainWindow::doOpenFile(const KUrl &url, KAutoSaveFile *stale) stale->setParent(doc); } connectDocumentInfo(doc); - TrackView *trackView = new TrackView(doc, this); + bool ok; + TrackView *trackView = new TrackView(doc, &ok, this); m_timelineArea->setCurrentIndex(m_timelineArea->addTab(trackView, KIcon("kdenlive"), doc->description())); + if (!ok) { + m_timelineArea->setEnabled(false); + m_projectList->setEnabled(false); + m_monitorManager->slotBlockMonitors(); + slotPreferences(6); + return; + } m_timelineArea->setTabToolTip(m_timelineArea->currentIndex(), doc->url().path()); trackView->setDuration(trackView->duration()); trackView->projectView()->initCursorPos(m_projectMonitor->render->seekPosition().frames(doc->fps())); @@ -1482,7 +1552,7 @@ void MainWindow::parseProfiles(const QString &mltPath) KUrl mltPath = getUrl->selectedUrl(); delete getUrl; if (mltPath.isEmpty()) ::exit(0); - KdenliveSettings::setMltpath(mltPath.path()); + KdenliveSettings::setMltpath(mltPath.path(KUrl::AddTrailingSlash)); QStringList profilesList = QDir(KdenliveSettings::mltpath()).entryList(profilesFilter, QDir::Files); } } @@ -1516,200 +1586,101 @@ void MainWindow::slotEditProfiles() delete w; } +void MainWindow::slotDetectAudioDriver() +{ + /* WARNING: do not use this method because sometimes detects wrong driver (pulse instead of alsa), + leading to no audio output, see bug #934 */ + + //decide which audio driver is really best, in some cases SDL is wrong + if (KdenliveSettings::audiodrivername().isEmpty()) { + QString driver; + KProcess readProcess; + //PulseAudio needs to be selected if it exists, the ALSA pulse pcm device is not fast enough. + if (!KStandardDirs::findExe("pactl").isEmpty()) { + readProcess.setOutputChannelMode(KProcess::OnlyStdoutChannel); + readProcess.setProgram("pactl", QStringList() << "stat"); + readProcess.execute(2000); // Kill it after 2 seconds + + QString result = QString(readProcess.readAllStandardOutput()); + kDebug() << "// / / / / / READING PACTL: "; + kDebug() << result; + if (!result.isEmpty()) { + driver = "pulse"; + kDebug() << "// / / / / PULSEAUDIO DETECTED"; + } + } + //put others here + KdenliveSettings::setAutoaudiodrivername(driver); + } +} + void MainWindow::slotEditProjectSettings() { QPoint p = m_activeDocument->getTracksCount(); - ProjectSettings *w = new ProjectSettings(p.x(), p.y(), m_activeDocument->projectFolder().path(), true, this); + ProjectSettings *w = new ProjectSettings(m_activeDocument->clipManager(), p.x(), p.y(), m_activeDocument->projectFolder().path(), true, !m_activeDocument->isModified(), this); if (w->exec() == QDialog::Accepted) { + if (w->deleteUnused()) { + // we are going to trash the unused clips + m_projectList->trashUnusedClips(); + } QString profile = w->selectedProfile(); m_activeDocument->setProjectFolder(w->selectedFolder()); - if (m_renderWidget) m_renderWidget->setDocumentPath(w->selectedFolder().path()); + if (m_renderWidget) m_renderWidget->setDocumentPath(w->selectedFolder().path(KUrl::AddTrailingSlash)); if (m_activeDocument->profilePath() != profile) { // Profile was changed - m_activeDocument->setProfilePath(profile); + double dar = m_activeDocument->dar(); + + // Deselect current effect / transition + m_effectStack->slotClipItemSelected(NULL, 0); + m_transitionConfig->slotTransitionItemSelected(NULL, 0, QPoint(), false); + m_clipMonitor->slotSetXml(NULL, 0); + bool updateFps = m_activeDocument->setProfilePath(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_activeTimeline->tracksNumber()); + m_effectStack->updateProjectFormat(m_activeDocument->mltProfile(), m_activeDocument->timecode()); if (m_renderWidget) m_renderWidget->setProfile(m_activeDocument->mltProfile()); m_timelineArea->setTabText(m_timelineArea->currentIndex(), m_activeDocument->description()); - m_activeDocument->clipManager()->resetProducersList(m_projectMonitor->render->producersList()); - + //m_activeDocument->clipManager()->resetProducersList(m_projectMonitor->render->producersList()); + if (dar != m_activeDocument->dar()) m_projectList->reloadClipThumbnails(); + if (updateFps) m_activeTimeline->updateProjectFps(); + m_activeDocument->setModified(true); + m_commandStack->activeStack()->clear(); // We need to desactivate & reactivate monitors to get a refresh - m_monitorManager->switchMonitors(); + //m_monitorManager->switchMonitors(); } } delete w; } + void MainWindow::slotRenderProject() { if (!m_renderWidget) { - QString projectfolder = m_activeDocument ? m_activeDocument->projectFolder().path() : KdenliveSettings::defaultprojectfolder(); + QString projectfolder = m_activeDocument ? m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash) : KdenliveSettings::defaultprojectfolder(); m_renderWidget = new RenderWidget(projectfolder, this); - connect(m_renderWidget, SIGNAL(doRender(const QStringList&, const QStringList&)), this, SLOT(slotDoRender(const QStringList&, const QStringList&))); + connect(m_renderWidget, SIGNAL(selectedRenderProfile(const QString &, const QString &, const QString&)), this, SLOT(slotSetDocumentRenderProfile(const QString &, const QString &, const QString&))); + 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 &))); if (m_activeDocument) { m_renderWidget->setProfile(m_activeDocument->mltProfile()); m_renderWidget->setGuides(m_activeDocument->guidesXml(), m_activeDocument->projectDuration()); + m_renderWidget->setDocumentPath(m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash)); + m_renderWidget->setRenderProfile(m_activeDocument->getDocumentProperty("renderdestination"), m_activeDocument->getDocumentProperty("renderprofile"), m_activeDocument->getDocumentProperty("renderurl")); } } /*TrackView *currentTab = (TrackView *) m_timelineArea->currentWidget(); if (currentTab) m_renderWidget->setTimeline(currentTab); m_renderWidget->setDocument(m_activeDocument);*/ m_renderWidget->show(); -} - -void MainWindow::slotDoRender(const QStringList args, const QStringList overlay_args) -{ - QString dest = args.at(0); - QString render = args.at(1); - QStringList avformat_args = args.at(2).split(' '); - bool zoneOnly = args.at(3).toInt(); - bool playAfter = args.at(4).toInt(); - double guideStart = args.at(5).toDouble(); - double guideEnd = args.at(6).toDouble(); - bool resizeProfile = args.at(7).toInt(); - QString scriptExport = args.at(8); - bool createChapterFile = args.at(9).toInt(); - - if (dest.isEmpty()) return; - int in = 0; - int out = 0; - - if (m_activeTimeline && zoneOnly) { - in = m_activeTimeline->inPoint(); - out = m_activeTimeline->outPoint(); - } - - KTemporaryFile temp; - temp.setAutoRemove(false); - temp.setSuffix(".mlt"); - if (!scriptExport.isEmpty() || temp.open()) { - if (KdenliveSettings::dropbframes()) { - KdenliveSettings::setDropbframes(false); - m_activeDocument->clipManager()->updatePreviewSettings(); - if (!scriptExport.isEmpty()) m_projectMonitor->saveSceneList(scriptExport + ".mlt"); - else m_projectMonitor->saveSceneList(temp.fileName()); - KdenliveSettings::setDropbframes(true); - m_activeDocument->clipManager()->updatePreviewSettings(); - } else { - if (!scriptExport.isEmpty()) m_projectMonitor->saveSceneList(scriptExport + ".mlt"); - else m_projectMonitor->saveSceneList(temp.fileName()); - } - - QStringList args; - if (scriptExport.isEmpty()) args << "-erase"; - if (KdenliveSettings::usekuiserver()) args << "-kuiserver"; - if (zoneOnly) args << "in=" + QString::number(in) << "out=" + QString::number(out); - else if (guideStart != -1) { - args << "in=" + QString::number(GenTime(guideStart).frames(m_activeDocument->fps())) << "out=" + QString::number(GenTime(guideEnd).frames(m_activeDocument->fps())); - } - if (!overlay_args.isEmpty()) args << "preargs=" + overlay_args.join(" "); - QString videoPlayer = "-"; - if (playAfter) { - videoPlayer = KdenliveSettings::defaultplayerapp(); - if (videoPlayer.isEmpty()) KMessageBox::sorry(this, i18n("Cannot play video after rendering because the default video player application is not set.\nPlease define it in Kdenlive settings dialog.")); - } - if (!QFile::exists(KdenliveSettings::rendererpath())) { - KMessageBox::sorry(this, i18n("Cannot find the melt program required for rendering (part of Mlt)")); - setRenderingProgress(dest, -3); - return; - } - args << KdenliveSettings::rendererpath() << m_activeDocument->profilePath() << render << videoPlayer; - - for (int i = 0; i < avformat_args.count(); i++) { - if (avformat_args.at(i).startsWith("profile=")) { - if (avformat_args.at(i).section('=', 1) != m_activeDocument->profilePath()) resizeProfile = true; - break; - } - } - - if (resizeProfile) { - // The rendering profile is different from project profile, so use MLT's special producer_consumer - if (scriptExport.isEmpty()) args << "consumer:" + temp.fileName(); - else args << "consumer:$SOURCE"; - } else { - if (scriptExport.isEmpty()) args << temp.fileName(); - else args << "$SOURCE"; - } - if (scriptExport.isEmpty()) args << dest; - else args << "$TARGET"; - args << avformat_args; - QString renderer = QCoreApplication::applicationDirPath() + QString("/kdenlive_render"); - if (!QFile::exists(renderer)) renderer = "kdenlive_render"; - if (scriptExport.isEmpty()) { - QProcess::startDetached(renderer, args); - KNotification::event("RenderStarted", i18n("Rendering %1 started", dest), QPixmap(), this); - } else { - // Generate script file - QFile file(scriptExport); - if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { - KMessageBox::error(this, i18n("Cannot write to file %1", scriptExport)); - return; - } - - QTextStream outStream(&file); - outStream << "#! /bin/sh" << "\n" << "\n"; - outStream << "SOURCE=" << "\"" + scriptExport + ".westley\"" << "\n"; - outStream << "TARGET=" << "\"" + dest + "\"" << "\n"; - outStream << renderer << " " << args.join(" ") << "\n" << "\n"; - if (file.error() != QFile::NoError) { - KMessageBox::error(this, i18n("Cannot write to file %1", scriptExport)); - file.close(); - return; - } - file.close(); - QFile::setPermissions(scriptExport, file.permissions() | QFile::ExeUser); - } - - if (createChapterFile) { - QDomDocument doc; - QDomElement chapters = doc.createElement("chapters"); - chapters.setAttribute("fps", m_activeDocument->fps()); - doc.appendChild(chapters); - - QDomElement guidesxml = m_activeDocument->guidesXml(); - if (!zoneOnly) out = (int) GenTime(m_activeDocument->projectDuration()).frames(m_activeDocument->fps()); - - QDomNodeList nodes = guidesxml.elementsByTagName("guide"); - for (int i = 0; i < nodes.count(); i++) { - QDomElement e = nodes.item(i).toElement(); - if (!e.isNull()) { - QString comment = e.attribute("comment"); - int time = (int) GenTime(e.attribute("time").toDouble()).frames(m_activeDocument->fps()); - if (time >= in && time < out) { - if (zoneOnly) time = time - in; - QDomElement chapter = doc.createElement("chapter"); - chapters.appendChild(chapter); - chapter.setAttribute("title", comment); - chapter.setAttribute("time", time); - } - } - } - if (chapters.childNodes().count() > 0) { - if (m_activeTimeline->projectView()->hasGuide(out, 0) == -1) { - // Always insert a guide in pos 0 - QDomElement chapter = doc.createElement("chapter"); - chapters.insertBefore(chapter, QDomNode()); - chapter.setAttribute("title", i18n("Start")); - chapter.setAttribute("time", "0"); - } - // save chapters file - QFile file(dest + ".dvdchapter"); - if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { - kWarning() << "////// ERROR writing DVD CHAPTER file: " << dest + ".dvdchapter"; - } else { - file.write(doc.toString().toUtf8()); - if (file.error() != QFile::NoError) - kWarning() << "////// ERROR writing DVD CHAPTER file: " << dest + ".dvdchapter"; - file.close(); - } - } - } - } + m_renderWidget->showNormal(); } void MainWindow::setRenderingProgress(const QString &url, int progress) @@ -1722,6 +1693,12 @@ void MainWindow::setRenderingFinished(const QString &url, int status, const QStr if (m_renderWidget) m_renderWidget->setRenderStatus(url, status, error); } +void MainWindow::slotCleanProject() +{ + if (KMessageBox::warningContinueCancel(this, i18n("This will remove all unused clips from your project."), i18n("Clean up project")) == KMessageBox::Cancel) return; + m_projectList->cleanup(); +} + void MainWindow::slotUpdateMousePosition(int pos) { if (m_activeDocument) @@ -1771,7 +1748,6 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha disconnect(m_projectList, SIGNAL(projectModified()), m_activeDocument, SLOT(setModified())); disconnect(m_projectMonitor->render, SIGNAL(refreshDocumentProducers()), m_activeDocument, SLOT(checkProjectClips())); - 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(resetProjectList()), m_projectList, SLOT(slotResetProjectList())); @@ -1781,8 +1757,8 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha disconnect(m_activeDocument, SIGNAL(deleteTimelineClip(const QString &)), m_activeTimeline, SLOT(slotDeleteClip(const QString &))); disconnect(m_activeTimeline->projectView(), SIGNAL(clipItemSelected(ClipItem*, int)), m_effectStack, SLOT(slotClipItemSelected(ClipItem*, int))); disconnect(m_activeTimeline->projectView(), SIGNAL(clipItemSelected(ClipItem*, int)), this, SLOT(slotActivateEffectStackView())); - disconnect(m_activeTimeline, SIGNAL(transitionItemSelected(Transition*, bool)), m_transitionConfig, SLOT(slotTransitionItemSelected(Transition*, bool))); - disconnect(m_activeTimeline, SIGNAL(transitionItemSelected(Transition*, bool)), this, SLOT(slotActivateTransitionView(Transition *))); + 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_zoomSlider, SIGNAL(valueChanged(int)), m_activeTimeline, SLOT(slotChangeZoom(int))); disconnect(m_activeTimeline->projectView(), SIGNAL(displayMessage(const QString&, MessageType)), m_messageLabel, SLOT(setMessage(const QString&, MessageType))); disconnect(m_activeTimeline->projectView(), SIGNAL(showClipFrame(DocClipBase *, const int)), m_clipMonitor, SLOT(slotSetXml(DocClipBase *, const int))); @@ -1802,10 +1778,12 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha disconnect(m_activeTimeline->projectView(), SIGNAL(activateDocumentMonitor()), m_projectMonitor, SLOT(activateMonitor())); 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(displayMessage(const QString&, MessageType)), m_messageLabel, SLOT(setMessage(const QString&, MessageType))); m_effectStack->clear(); } //m_activeDocument->setRenderer(NULL); disconnect(m_projectList, SIGNAL(clipSelected(DocClipBase *)), m_clipMonitor, SLOT(slotSetXml(DocClipBase *))); + disconnect(m_projectList, SIGNAL(refreshClip()), m_clipMonitor, SLOT(refreshMonitor())); m_clipMonitor->stop(); } KdenliveSettings::setCurrent_profile(doc->profilePath()); @@ -1815,6 +1793,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha m_transitionConfig->updateProjectFormat(doc->mltProfile(), doc->timecode(), trackView->tracksNumber()); m_effectStack->updateProjectFormat(doc->mltProfile(), doc->timecode()); connect(m_projectList, SIGNAL(clipSelected(DocClipBase *)), m_clipMonitor, SLOT(slotSetXml(DocClipBase *))); + connect(m_projectList, SIGNAL(refreshClip()), m_clipMonitor, SLOT(refreshMonitor())); 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))); @@ -1828,6 +1807,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha connect(m_projectMonitor, SIGNAL(zoneUpdated(QPoint)), trackView, SLOT(slotSetZone(QPoint))); connect(m_projectMonitor, SIGNAL(durationChanged(int)), trackView, SLOT(setDuration(int))); connect(m_projectMonitor->render, SIGNAL(refreshDocumentProducers()), doc, SLOT(checkProjectClips())); + 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 &)), m_projectList, SLOT(slotDeleteClip(const QString &))); @@ -1840,13 +1820,16 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha connect(trackView->projectView(), SIGNAL(clipItemSelected(ClipItem*, int)), m_effectStack, SLOT(slotClipItemSelected(ClipItem*, int))); + connect(trackView->projectView(), SIGNAL(updateClipMarkers(DocClipBase *)), this, SLOT(slotUpdateClipMarkers(DocClipBase*))); + connect(trackView->projectView(), SIGNAL(clipItemSelected(ClipItem*, int)), this, SLOT(slotActivateEffectStackView())); - connect(trackView, SIGNAL(transitionItemSelected(Transition*, bool)), m_transitionConfig, SLOT(slotTransitionItemSelected(Transition*, bool))); - connect(trackView, SIGNAL(transitionItemSelected(Transition*, bool)), this, SLOT(slotActivateTransitionView(Transition *))); - m_zoomSlider->setValue(doc->zoom()); + 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(m_zoomSlider, SIGNAL(valueChanged(int)), trackView, SLOT(slotChangeZoom(int))); 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(showClipFrame(DocClipBase *, const int)), m_clipMonitor, SLOT(slotSetXml(DocClipBase *, const int))); @@ -1864,17 +1847,20 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha connect(trackView->projectView(), SIGNAL(activateDocumentMonitor()), m_projectMonitor, SLOT(activateMonitor())); connect(trackView, SIGNAL(zoneMoved(int, int)), this, SLOT(slotZoneMoved(int, int))); connect(m_projectList, SIGNAL(loadingIsOver()), trackView->projectView(), SLOT(slotUpdateAllThumbs())); + connect(m_projectList, SIGNAL(displayMessage(const QString&, MessageType)), m_messageLabel, SLOT(setMessage(const QString&, MessageType))); + trackView->projectView()->setContextMenu(m_timelineContextMenu, m_timelineContextClipMenu, m_timelineContextTransitionMenu, m_clipTypeGroup); m_activeTimeline = trackView; if (m_renderWidget) { m_renderWidget->setProfile(doc->mltProfile()); - m_renderWidget->setDocumentPath(doc->projectFolder().path()); + m_renderWidget->setGuides(doc->guidesXml(), doc->projectDuration()); + m_renderWidget->setDocumentPath(doc->projectFolder().path(KUrl::AddTrailingSlash)); + m_renderWidget->setRenderProfile(doc->getDocumentProperty("renderdestination"), doc->getDocumentProperty("renderprofile"), doc->getDocumentProperty("renderurl")); } //doc->setRenderer(m_projectMonitor->render); m_commandStack->setActiveStack(doc->commandStack()); KdenliveSettings::setProject_display_ratio(doc->dar()); - m_projectList->updateAllClips(); //doc->clipManager()->checkAudioThumbs(); //m_overView->setScene(trackView->projectScene()); @@ -1884,6 +1870,8 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha setCaption(doc->description(), doc->isModified()); m_saveAction->setEnabled(doc->isModified()); m_activeDocument = doc; + m_activeTimeline->updateProjectFps(); + m_projectList->updateAllClips(); if (KdenliveSettings::dropbframes()) slotUpdatePreviewSettings(); // set tool to select tool @@ -1916,9 +1904,12 @@ void MainWindow::slotPreferences(int page, int option) // create it : KdenliveSettingsDialog* dialog = new KdenliveSettingsDialog(this); connect(dialog, SIGNAL(settingsChanged(const QString&)), this, SLOT(updateConfiguration())); + //connect(dialog, SIGNAL(doResetProfile()), this, SLOT(slotDetectAudioDriver())); connect(dialog, SIGNAL(doResetProfile()), m_monitorManager, SLOT(slotResetProfiles())); connect(dialog, SIGNAL(updatePreviewSettings()), this, SLOT(slotUpdatePreviewSettings())); +#ifndef Q_WS_MAC connect(dialog, SIGNAL(updateCaptureFolder()), m_recMonitor, SLOT(slotUpdateCaptureFolder())); +#endif //connect(dialog, SIGNAL(updatePreviewSettings()), this, SLOT(slotUpdatePreviewSettings())); dialog->show(); if (page != -1) dialog->showPage(page, option); @@ -1943,6 +1934,9 @@ void MainWindow::updateConfiguration() } m_buttonAudioThumbs->setChecked(KdenliveSettings::audiothumbnails()); m_buttonVideoThumbs->setChecked(KdenliveSettings::videothumbnails()); + + // Update list of transcoding profiles + loadTranscoders(); #ifndef NO_JOGSHUTTLE activateShuttleDevice(); #endif /* NO_JOGSHUTTLE */ @@ -1994,11 +1988,10 @@ void MainWindow::slotDeleteTimelineClip() } } -void MainWindow::slotChangeClipSpeed() +void MainWindow::slotUpdateClipMarkers(DocClipBase *clip) { - if (m_activeTimeline) { - m_activeTimeline->projectView()->changeClipSpeed(); - } + if (m_clipMonitor->isActive()) m_clipMonitor->checkOverlay(); + m_clipMonitor->updateMarkers(clip); } void MainWindow::slotAddClipMarker() @@ -2009,7 +2002,7 @@ void MainWindow::slotAddClipMarker() if (m_activeTimeline) { ClipItem *item = m_activeTimeline->projectView()->getActiveClipUnderCursor(); if (item) { - pos = m_projectMonitor->position() - item->startPos() + item->cropStart(); + pos = GenTime((int)((m_projectMonitor->position() - item->startPos() + item->cropStart()).frames(m_activeDocument->fps()) * item->speed() + 0.5), m_activeDocument->fps()); clip = item->baseClip(); } } @@ -2027,7 +2020,6 @@ void MainWindow::slotAddClipMarker() if (d.exec() == QDialog::Accepted) { m_activeTimeline->projectView()->slotAddClipMarker(id, d.newMarker().time(), d.newMarker().comment()); } - if (m_clipMonitor->isActive()) m_clipMonitor->checkOverlay(); } void MainWindow::slotDeleteClipMarker() @@ -2038,7 +2030,7 @@ void MainWindow::slotDeleteClipMarker() if (m_activeTimeline) { ClipItem *item = m_activeTimeline->projectView()->getActiveClipUnderCursor(); if (item) { - pos = m_projectMonitor->position() - item->startPos() + item->cropStart(); + pos = (m_projectMonitor->position() - item->startPos() + item->cropStart()) / item->speed(); clip = item->baseClip(); } } @@ -2058,8 +2050,6 @@ void MainWindow::slotDeleteClipMarker() return; } m_activeTimeline->projectView()->slotDeleteClipMarker(comment, id, pos); - if (m_clipMonitor->isActive()) m_clipMonitor->checkOverlay(); - } void MainWindow::slotDeleteAllClipMarkers() @@ -2080,7 +2070,6 @@ void MainWindow::slotDeleteAllClipMarkers() return; } m_activeTimeline->projectView()->slotDeleteAllClipMarkers(clip->getId()); - if (m_clipMonitor->isActive()) m_clipMonitor->checkOverlay(); } void MainWindow::slotEditClipMarker() @@ -2091,7 +2080,7 @@ void MainWindow::slotEditClipMarker() if (m_activeTimeline) { ClipItem *item = m_activeTimeline->projectView()->getActiveClipUnderCursor(); if (item) { - pos = m_projectMonitor->position() - item->startPos() + item->cropStart(); + pos = (m_projectMonitor->position() - item->startPos() + item->cropStart()) / item->speed(); clip = item->baseClip(); } } @@ -2119,7 +2108,6 @@ void MainWindow::slotEditClipMarker() // remove old marker m_activeTimeline->projectView()->slotAddClipMarker(id, pos, QString()); } - if (m_clipMonitor->isActive()) m_clipMonitor->checkOverlay(); } } @@ -2262,6 +2250,11 @@ void MainWindow::slotFitZoom() } } +void MainWindow::slotSetZoom(int value) +{ + m_zoomSlider->setValue(value); +} + void MainWindow::slotGotProgressInfo(const QString &message, int progress) { m_statusProgressBar->setValue(progress); @@ -2277,22 +2270,72 @@ void MainWindow::slotGotProgressInfo(const QString &message, int progress) void MainWindow::slotShowClipProperties(DocClipBase *clip) { if (clip->clipType() == TEXT) { - QString titlepath = m_activeDocument->projectFolder().path() + "/titles/"; + QString titlepath = m_activeDocument->projectFolder().path(KUrl::AddTrailingSlash) + "titles/"; + if (!clip->getProperty("resource").isEmpty() && clip->getProperty("xmldata").isEmpty()) { + // template text clip + + // Get the list of existing templates + QStringList filter; + filter << "*.kdenlivetitle"; + QStringList templateFiles = QDir(titlepath).entryList(filter, QDir::Files); + + QDialog *dia = new QDialog(this); + Ui::TemplateClip_UI dia_ui; + dia_ui.setupUi(dia); + int ix = -1; + const QString templatePath = clip->getProperty("resource"); + for (int i = 0; i < templateFiles.size(); ++i) { + dia_ui.template_list->comboBox()->addItem(templateFiles.at(i), titlepath + templateFiles.at(i)); + if (templatePath == KUrl(titlepath + templateFiles.at(i)).path()) ix = i; + } + if (ix != -1) dia_ui.template_list->comboBox()->setCurrentIndex(ix); + else dia_ui.template_list->comboBox()->insertItem(0, templatePath); + dia_ui.template_list->fileDialog()->setFilter("*.kdenlivetitle"); + //warning: setting base directory doesn't work?? + KUrl startDir(titlepath); + dia_ui.template_list->fileDialog()->setUrl(startDir); + 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(); + + QMap newprops; + + if (KUrl(textTemplate).path() != templatePath) { + // The template was changed + newprops.insert("resource", textTemplate); + } + + if (dia_ui.description->toPlainText() != clip->getProperty("description")) { + newprops.insert("description", dia_ui.description->toPlainText()); + } + + QString newtemplate = newprops.value("xmltemplate"); + 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); + //newprops.insert("xmldata", m_projectList->generateTemplateXml(newtemplate, description).toString()); + + EditClipCommand *command = new EditClipCommand(m_projectList, clip->getId(), clip->properties(), newprops, true); + m_activeDocument->commandStack()->push(command); + } + return; + } QString path = clip->getProperty("resource"); - TitleWidget *dia_ui = new TitleWidget(KUrl(), titlepath, m_projectMonitor->render, this); + TitleWidget *dia_ui = new TitleWidget(KUrl(), m_activeDocument->timecode(), titlepath, m_projectMonitor->render, this); QDomDocument doc; doc.setContent(clip->getProperty("xmldata")); dia_ui->setXml(doc); if (dia_ui->exec() == QDialog::Accepted) { - QImage pix = dia_ui->renderedPixmap(); - pix.save(path); - //slotAddClipFile(KUrl("/tmp/kdenlivetitle.png"), QString(), -1); - //m_clipManager->slotEditTextClipFile(id, dia_ui->xml().toString()); QMap newprops; newprops.insert("xmldata", dia_ui->xml().toString()); + newprops.insert("out", QString::number(dia_ui->duration())); EditClipCommand *command = new EditClipCommand(m_projectList, clip->getId(), clip->properties(), newprops, true); m_activeDocument->commandStack()->push(command); - m_clipMonitor->refreshMonitor(true); + m_activeTimeline->projectView()->slotUpdateClip(clip->getId()); m_activeDocument->setModified(true); } delete dia_ui; @@ -2303,13 +2346,12 @@ void MainWindow::slotShowClipProperties(DocClipBase *clip) ClipProperties dia(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))); if (dia.exec() == QDialog::Accepted) { - EditClipCommand *command = new EditClipCommand(m_projectList, dia.clipId(), clip->properties(), dia.properties(), true); + EditClipCommand *command = new EditClipCommand(m_projectList, clip->getId(), clip->properties(), dia.properties(), true); m_activeDocument->commandStack()->push(command); - //m_projectList->slotUpdateClipProperties(dia.clipId(), dia.properties()); if (dia.needsTimelineRefresh()) { // update clip occurences in timeline - m_activeTimeline->projectView()->slotUpdateClip(dia.clipId()); + m_activeTimeline->projectView()->slotUpdateClip(clip->getId(), dia.needsTimelineReload()); } } } @@ -2317,8 +2359,7 @@ void MainWindow::slotShowClipProperties(DocClipBase *clip) void MainWindow::customEvent(QEvent* e) { if (e->type() == QEvent::User) { - // The timeline playing position changed... - kDebug() << "RECEIVED JOG EVEMNT!!!"; + m_messageLabel->setMessage(static_cast (e)->message(), MltError); } } void MainWindow::slotActivateEffectStackView() @@ -2498,6 +2539,7 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *event) } } + void MainWindow::slotSaveZone(Render *render, QPoint zone) { KDialog *dialog = new KDialog(this); @@ -2554,6 +2596,7 @@ void MainWindow::slotGetNewLumaStuff() } qDeleteAll(entries); initEffects::refreshLumas(); + m_activeTimeline->projectView()->reloadTransitionLumas(); } void MainWindow::slotGetNewRenderStuff() @@ -2624,8 +2667,8 @@ void MainWindow::slotUpdateClipType(QAction *action) void MainWindow::slotDvdWizard(const QString &url, const QString &profile) { - DvdWizard *w = new DvdWizard(url, profile, this); - w->exec(); + DvdWizard w(url, profile, this); + w.exec(); } void MainWindow::slotShowTimeline(bool show) @@ -2661,7 +2704,8 @@ void MainWindow::loadTranscoders() { QMenu *transMenu = static_cast(factory()->container("transcoders", this)); transMenu->clear(); - KSharedConfigPtr config = KGlobal::config(); + + KSharedConfigPtr config = KSharedConfig::openConfig("kdenlivetranscodingrc"); KConfigGroup transConfig(config, "Transcoding"); // read the entries QMap< QString, QString > profiles = transConfig.entryMap(); @@ -2674,17 +2718,16 @@ void MainWindow::loadTranscoders() } } -void MainWindow::slotTranscode(QString url) +void MainWindow::slotTranscode(KUrl::List urls) { QString params; - if (url.isEmpty()) { - url = m_projectList->currentClipUrl(); + if (urls.isEmpty()) { + urls.append(m_projectList->currentClipUrl()); QAction *action = qobject_cast(sender()); params = action->data().toString(); - } - if (url.isEmpty()) return; - ClipTranscode *d = new ClipTranscode(url, params); + if (urls.isEmpty()) return; + ClipTranscode *d = new ClipTranscode(urls, params); connect(d, SIGNAL(addClip(KUrl)), this, SLOT(slotAddProjectClip(KUrl))); d->show(); //QProcess::startDetached("ffmpeg", parameters); @@ -2692,9 +2735,117 @@ void MainWindow::slotTranscode(QString url) void MainWindow::slotTranscodeClip() { - KUrl url = KFileDialog::getOpenUrl(KUrl("kfiledialog:///projectfolder")); - if (url.isEmpty()) return; - slotTranscode(url.path()); + KUrl::List urls = KFileDialog::getOpenUrls(KUrl("kfiledialog:///projectfolder")); + if (urls.isEmpty()) return; + slotTranscode(urls); +} + +void MainWindow::slotSetDocumentRenderProfile(const QString &dest, const QString &name, const QString &file) +{ + if (m_activeDocument == NULL) return; + m_activeDocument->setDocumentProperty("renderdestination", dest); + m_activeDocument->setDocumentProperty("renderprofile", name); + m_activeDocument->setDocumentProperty("renderurl", file); + m_activeDocument->setModified(true); +} + + +void MainWindow::slotPrepareRendering(bool scriptExport, bool zoneOnly, const QString &chapterFile) +{ + if (m_activeDocument == NULL || m_renderWidget == NULL) return; + QString scriptPath; + QString playlistPath; + if (scriptExport) { + bool ok; + QString scriptsFolder = m_activeDocument->projectFolder().path() + "/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); + QFile f(scriptPath); + if (f.exists()) { + if (KMessageBox::warningYesNo(this, i18n("Script file already exists. Do you want to overwrite it?")) != KMessageBox::Yes) + return; + } + playlistPath = scriptPath + ".mlt"; + m_projectMonitor->saveSceneList(playlistPath); + } else { + KTemporaryFile temp; + temp.setAutoRemove(false); + temp.setSuffix(".mlt"); + temp.open(); + playlistPath = temp.fileName(); + m_projectMonitor->saveSceneList(playlistPath); + } + + if (!chapterFile.isEmpty()) { + int in = 0; + int out; + if (!zoneOnly) out = (int) GenTime(m_activeDocument->projectDuration()).frames(m_activeDocument->fps()); + else { + in = m_activeTimeline->inPoint(); + out = m_activeTimeline->outPoint(); + } + QDomDocument doc; + QDomElement chapters = doc.createElement("chapters"); + chapters.setAttribute("fps", m_activeDocument->fps()); + doc.appendChild(chapters); + + QDomElement guidesxml = m_activeDocument->guidesXml(); + QDomNodeList nodes = guidesxml.elementsByTagName("guide"); + for (int i = 0; i < nodes.count(); i++) { + QDomElement e = nodes.item(i).toElement(); + if (!e.isNull()) { + QString comment = e.attribute("comment"); + int time = (int) GenTime(e.attribute("time").toDouble()).frames(m_activeDocument->fps()); + if (time >= in && time < out) { + if (zoneOnly) time = time - in; + QDomElement chapter = doc.createElement("chapter"); + chapters.appendChild(chapter); + chapter.setAttribute("title", comment); + chapter.setAttribute("time", time); + } + } + } + if (chapters.childNodes().count() > 0) { + if (m_activeTimeline->projectView()->hasGuide(out, 0) == -1) { + // Always insert a guide in pos 0 + QDomElement chapter = doc.createElement("chapter"); + chapters.insertBefore(chapter, QDomNode()); + chapter.setAttribute("title", i18n("Start")); + chapter.setAttribute("time", "0"); + } + // save chapters file + QFile file(chapterFile); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + kWarning() << "////// ERROR writing DVD CHAPTER file: " << chapterFile; + } else { + file.write(doc.toString().toUtf8()); + if (file.error() != QFile::NoError) { + kWarning() << "////// ERROR writing DVD CHAPTER file: " << chapterFile; + } + file.close(); + } + } + } + + m_renderWidget->slotExport(scriptExport, m_activeTimeline->inPoint(), m_activeTimeline->outPoint(), playlistPath, scriptPath); } +void MainWindow::slotUpdateTimecodeFormat(int ix) +{ + KdenliveSettings::setFrametimecode(ix == 1); + m_clipMonitor->updateTimecodeFormat(); + m_projectMonitor->updateTimecodeFormat(); +} + +void MainWindow::slotRemoveFocus() +{ + statusBar()->setFocus(); + statusBar()->clearFocus(); +} + + + + #include "mainwindow.moc"