X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmainwindow.cpp;h=014bb9a5e2b6dc0679d517e51f111f187e9af980;hb=1ef74c09dfc9a0df968407638134667bf3dc153c;hp=95b00560e59af1460bff02229bc44c301b66b738;hpb=5ed1c89abce62e3babf51749b554d17b05727ac1;p=kdenlive diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 95b00560..014bb9a5 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -126,7 +126,6 @@ static const char version[] = VERSION; -static const int ID_TIMELINE_POS = 0; namespace Mlt { class Producer; @@ -623,7 +622,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & 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(); @@ -646,6 +645,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(); @@ -682,7 +692,6 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString & } m_projectList->slotAddClip(urls); } - } MainWindow::~MainWindow() @@ -994,14 +1003,7 @@ private: 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); @@ -1013,7 +1015,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")); @@ -1201,9 +1203,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); @@ -1323,6 +1337,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")); @@ -1761,7 +1799,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); } @@ -2001,6 +2039,7 @@ bool MainWindow::closeCurrentDocument(bool saveChanges) 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 { @@ -2099,13 +2138,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; } @@ -2386,7 +2435,7 @@ 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; } @@ -2414,7 +2463,6 @@ 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()); @@ -2429,6 +2477,7 @@ void MainWindow::slotUpdateProjectProfile(const QString &profile) 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(); } @@ -2491,15 +2540,23 @@ void MainWindow::slotCleanProject() void MainWindow::slotUpdateMousePosition(int pos) { if (m_activeDocument) - switch (m_timecodeFormat->currentIndex()) { + 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) { if (!m_activeDocument) return; @@ -2603,7 +2660,6 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha 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(doc, SIGNAL(addProjectClip(DocClipBase *, bool)), m_projectList, SLOT(slotAddClip(DocClipBase *, bool))); @@ -2683,6 +2739,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 @@ -2690,7 +2748,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); } @@ -2879,8 +2940,11 @@ void MainWindow::slotAddClipMarker() 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) + 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; } @@ -2966,6 +3030,8 @@ void MainWindow::slotEditClipMarker() m_activeDocument->timecode(), i18n("Edit Marker"), this); if (d->exec() == QDialog::Accepted) { 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 oldMarker.setMarkerType(-1); @@ -3344,14 +3410,25 @@ 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); if (clip->clipType() == AV || clip->clipType() == VIDEO || clip->clipType() == PLAYLIST || clip->clipType() == SLIDESHOW) { // request clip thumbnails - m_activeDocument->clipManager()->requestThumbs(QString('?' + clip->getId()), QList() << clip->getClipThumbFrame()); connect(m_activeDocument->clipManager(), SIGNAL(gotClipPropertyThumbnail(const QString&,QImage)), dia, SLOT(slotGotThumbnail(const QString&,QImage))); + connect(dia, SIGNAL(requestThumb(const QString, QList )), m_activeDocument->clipManager(), SLOT(slotRequestThumbs(QString,QList))); + m_activeDocument->clipManager()->slotRequestThumbs(QString('?' + clip->getId()), QList() << clip->getClipThumbFrame()); } connect(dia, SIGNAL(addMarkers(const QString &, QList )), m_activeTimeline->projectView(), SLOT(slotAddClipMarker(const QString &, QList ))); @@ -3631,12 +3708,13 @@ void MainWindow::slotClipInTimeline(const QString &clipId) void MainWindow::slotClipInProjectTree() { if (m_activeTimeline) { - const QStringList &clipIds = m_activeTimeline->projectView()->selectedClips(); + 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)); + m_projectList->selectItemById(clipIds.at(0)); if (m_projectMonitor->isActive()) slotSwitchMonitors(); } @@ -3903,12 +3981,11 @@ void MainWindow::slotUpdateClipType(QAction *action) 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, 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) @@ -4020,22 +4097,6 @@ void MainWindow::slotStartClipAction() 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) @@ -4086,12 +4147,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 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) @@ -4140,7 +4206,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 @@ -4249,6 +4315,7 @@ void MainWindow::slotUpdateTimecodeFormat(int ix) m_effectStack->updateTimecodeFormat(); //m_activeTimeline->projectView()->clearSelection(); m_activeTimeline->updateRuler(); + slotUpdateMousePosition(m_activeTimeline->projectView()->getMousePos()); } void MainWindow::slotRemoveFocus() @@ -4632,6 +4699,47 @@ void MainWindow::slotAlignPlayheadToMousePos() 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" #ifdef DEBUG_MAINW