]> git.sesse.net Git - kdenlive/blobdiff - src/renderwidget.cpp
Allow retrieval of metadata created by Magic Lantern for canon cams
[kdenlive] / src / renderwidget.cpp
index 8937fd0aea19d2900def432a5e0a458f765b1b13..c800c0437164e136bc1e59dfee0f1fabb87e25e9 100644 (file)
@@ -47,6 +47,8 @@
 #include <QThread>
 #include <QScriptEngine>
 
+#include "locale.h"
+
 
 // Render profiles roles
 const int GroupRole = Qt::UserRole;
@@ -166,6 +168,8 @@ RenderWidget::RenderWidget(const QString &projectfolder, bool enableProxy, MltVi
     m_view.buttonFavorite->setIcon(KIcon("favorites"));
     m_view.buttonFavorite->setToolTip(i18n("Copy profile to favorites"));
     
+    m_view.show_all_profiles->setToolTip(i18n("Show profiles with different framerate"));
+    
     m_view.advanced_params->setMaximumHeight(QFontMetrics(font()).lineSpacing() * 5);
     
     m_view.buttonRender->setEnabled(false);
@@ -255,6 +259,7 @@ RenderWidget::RenderWidget(const QString &projectfolder, bool enableProxy, MltVi
     connect(m_view.out_file, SIGNAL(urlSelected(const KUrl &)), this, SLOT(slotUpdateButtons(const KUrl &)));
     connect(m_view.format_list, SIGNAL(currentRowChanged(int)), this, SLOT(refreshView()));
     connect(m_view.size_list, SIGNAL(currentRowChanged(int)), this, SLOT(refreshParams()));
+    connect(m_view.show_all_profiles, SIGNAL(stateChanged(int)), this, SLOT(refreshView()));
 
     connect(m_view.size_list, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT(slotEditItem(QListWidgetItem *)));
 
@@ -271,6 +276,7 @@ RenderWidget::RenderWidget(const QString &projectfolder, bool enableProxy, MltVi
     m_view.splitter->setStretchFactor(0, 2);
 
     m_view.out_file->setMode(KFile::File);
+    m_view.out_file->setFocusPolicy(Qt::ClickFocus);
 
     m_view.running_jobs->setHeaderLabels(QStringList() << QString() << i18n("File"));
     m_jobsDelegate = new RenderViewDelegate(this);
@@ -454,7 +460,7 @@ void RenderWidget::slotSaveProfile()
     if (customGroup.isEmpty()) customGroup = i18nc("Group Name", "Custom");
     ui.group_name->setText(customGroup);
 
-    QStringList arguments = m_view.advanced_params->toPlainText().split(" ", QString::SkipEmptyParts);
+    QStringList arguments = m_view.advanced_params->toPlainText().split(' ', QString::SkipEmptyParts);
     ui.parameters->setText(arguments.join(" "));
     ui.extension->setText(m_view.size_list->currentItem()->data(ExtensionRole).toString());
     ui.profile_name->setFocus();
@@ -793,8 +799,12 @@ void RenderWidget::updateButtons()
 }
 
 
-void RenderWidget::focusFirstVisibleItem()
+void RenderWidget::focusFirstVisibleItem(const QString &profile)
 {
+    if (!profile.isEmpty()) {
+       QList <QListWidgetItem *> child = m_view.size_list->findItems(profile, Qt::MatchExactly);
+       if (!child.isEmpty()) m_view.size_list->setCurrentItem(child.at(0));
+    }
     if (m_view.size_list->currentItem()) {
         updateButtons();
         return;
@@ -838,7 +848,7 @@ void RenderWidget::slotExport(bool scriptExport, int zoneIn, int zoneOut, const
     QString extension = item->data(ExtensionRole).toString();
     if (!dest.endsWith(extension, Qt::CaseInsensitive)) {
         if (KMessageBox::questionYesNo(this, i18n("File has no extension. Add extension (%1)?", extension)) == KMessageBox::Yes) {
-            dest.append("." + extension);
+            dest.append('.' + extension);
         }
     }
 
@@ -866,7 +876,8 @@ void RenderWidget::slotExport(bool scriptExport, int zoneIn, int zoneOut, const
 
     // Set locale for render process if required
     if (QLocale().decimalPoint() != QLocale::system().decimalPoint()) {
-        render_process_args << QString("-locale:%1").arg(QLocale().name());
+       const QString currentLocale = setlocale(LC_NUMERIC, NULL);
+        render_process_args << QString("-locale:%1").arg(currentLocale);
     }
 
     double guideStart = 0;
@@ -946,7 +957,7 @@ void RenderWidget::slotExport(bool scriptExport, int zoneIn, int zoneOut, const
         renderArgs.append(subsize);
     }
     bool resizeProfile = (subsize != currentSize);
-    QStringList paramsList = renderArgs.split(" ", QString::SkipEmptyParts);
+    QStringList paramsList = renderArgs.split(' ', QString::SkipEmptyParts);
 
     QScriptEngine sEngine;
     sEngine.globalObject().setProperty("bitrate", m_view.comboBitrates->currentText());
@@ -973,6 +984,7 @@ void RenderWidget::slotExport(bool scriptExport, int zoneIn, int zoneOut, const
         render_process_args << "consumer:" + (scriptExport ? "$SOURCE" : playlistPath);
     else
         render_process_args <<  (scriptExport ? "$SOURCE" : playlistPath);
+
     render_process_args << (scriptExport ? "$TARGET" : KUrl(dest).url());
     render_process_args << paramsList;
 
@@ -988,8 +1000,8 @@ void RenderWidget::slotExport(bool scriptExport, int zoneIn, int zoneOut, const
         }
         QTextStream outStream(&file);
         outStream << "#! /bin/sh" << "\n" << "\n";
-        outStream << "SOURCE=" << "\"" + playlistPath + "\"" << "\n";
-        outStream << "TARGET=" << "\"" + KUrl(dest).url() + "\"" << "\n";
+        outStream << "SOURCE=" << "\"" + QUrl(playlistPath).toEncoded() + "\"" << "\n";
+        outStream << "TARGET=" << "\"" + QUrl(dest).toEncoded() + "\"" << "\n";
         outStream << "RENDERER=" << "\"" + m_renderer + "\"" << "\n";
         outStream << "MELT=" << "\"" + KdenliveSettings::rendererpath() + "\"" << "\n";
         outStream << "PARAMETERS=" << "\"" + render_process_args.join(" ") + "\"" << "\n";
@@ -1079,6 +1091,7 @@ void RenderWidget::slotExport(bool scriptExport, int zoneIn, int zoneOut, const
             renderItem->setMetadata(url);
         }
     }
+
     renderItem->setData(1, ParametersRole, render_process_args);
     if (exportAudio == false) renderItem->setData(1, ExtraInfoRole, i18n("Video without audio track"));
     else  renderItem->setData(1, ExtraInfoRole, QString());
@@ -1101,7 +1114,7 @@ void RenderWidget::checkRenderStatus()
     item = static_cast<RenderJobItem*> (m_view.running_jobs->topLevelItem(0));
     bool waitingJob = false;
     
-    // Find first aiting job
+    // Find first waiting job
     while (item) {
         if (item->status() == WAITINGJOB) {
             item->setData(1, TimeRole, QTime::currentTime());
@@ -1127,7 +1140,7 @@ void RenderWidget::startRendering(RenderJobItem *item)
     } else if (item->type() == ScriptRenderType){
         // Script item
         kDebug()<<"// SCRIPT process: "<<item->data(1, ParametersRole).toString();
-        if (QProcess::startDetached(item->data(1, ParametersRole).toString()) == false) {
+        if (QProcess::startDetached('"' + item->data(1, ParametersRole).toString() + '"') == false) {
             item->setStatus(FAILEDJOB);
         }
     }
@@ -1160,17 +1173,18 @@ void RenderWidget::setProfile(MltVideoProfile profile)
     }
 }
 
-void RenderWidget::refreshCategory()
+
+
+void RenderWidget::refreshCategory(const QString &group, const QString &profile)
 {
     m_view.format_list->blockSignals(true);
     m_view.format_list->clear();
     QListWidgetItem *sizeItem;
-
+    
     QString destination;
     if (m_view.destination_list->currentIndex() > 0)
         destination = m_view.destination_list->itemData(m_view.destination_list->currentIndex()).toString();
 
-
     if (destination == "dvd") {
         m_view.open_dvd->setVisible(true);
         m_view.create_chapter->setVisible(true);
@@ -1193,12 +1207,15 @@ void RenderWidget::refreshCategory()
         }
     }
 
-    // activate first visible item
+    // activate requested item or first visible
+    QList<QListWidgetItem *> child;
+    if (!group.isEmpty()) child = m_view.format_list->findItems(group, Qt::MatchExactly);
+    if (!child.isEmpty()) {
+       m_view.format_list->setCurrentItem(child.at(0));
+       child.clear();
+    } else m_view.format_list->setCurrentRow(0);
     QListWidgetItem * item = m_view.format_list->currentItem();
-    if (!item) {
-        m_view.format_list->setCurrentRow(0);
-        item = m_view.format_list->currentItem();
-    }
+    m_view.format_list->blockSignals(false);
     if (!item) {
         m_view.format_list->setEnabled(false);
         m_view.format_list->clear();
@@ -1216,10 +1233,11 @@ void RenderWidget::refreshCategory()
         m_view.format_list->setVisible(true);
     else
         m_view.format_list->setVisible(false);
-    refreshView();
+
+    refreshView(profile);
 }
 
-void RenderWidget::refreshView()
+void RenderWidget::refreshView(const QString &profile)
 {
     if (!m_view.format_list->currentItem()) return;
     m_view.size_list->blockSignals(true);
@@ -1233,9 +1251,14 @@ void RenderWidget::refreshView()
     KIcon brokenIcon("dialog-close");
     KIcon warningIcon("dialog-warning");
 
-    const QStringList formatsList = KdenliveSettings::supportedformats();
-    const QStringList vcodecsList = KdenliveSettings::videocodecs();
-    const QStringList acodecsList = KdenliveSettings::audiocodecs();
+    QStringList formatsList;
+    QStringList vcodecsList;
+    QStringList acodecsList;
+    if (!KdenliveSettings::bypasscodeccheck()) {
+       formatsList= KdenliveSettings::supportedformats();
+       vcodecsList = KdenliveSettings::videocodecs();
+       acodecsList = KdenliveSettings::audiocodecs();
+    }
 
     KColorScheme scheme(palette().currentColorGroup(), KColorScheme::Window);
     const QColor disabled = scheme.foreground(KColorScheme::InactiveText).color();
@@ -1247,7 +1270,7 @@ void RenderWidget::refreshView()
         QListWidgetItem *dupItem = NULL;
         if ((sizeItem->data(GroupRole).toString() == group || sizeItem->data(GroupRole).toString().isEmpty()) && sizeItem->data(MetaGroupRole).toString() == destination) {
             std = sizeItem->data(StandardRole).toString();
-            if (!std.isEmpty()) {
+            if (!m_view.show_all_profiles->isChecked() && !std.isEmpty()) {
                 if ((std.contains("PAL", Qt::CaseInsensitive) && m_profile.frame_rate_num == 25 && m_profile.frame_rate_den == 1) ||
                     (std.contains("NTSC", Qt::CaseInsensitive) && m_profile.frame_rate_num == 30000 && m_profile.frame_rate_den == 1001))
                     dupItem = sizeItem->clone();
@@ -1259,7 +1282,7 @@ void RenderWidget::refreshView()
                 m_view.size_list->addItem(dupItem);
                 std = dupItem->data(ParamsRole).toString();
                 // Make sure the selected profile uses the same frame rate as project profile
-                if (std.contains("mlt_profile=")) {
+                if (!m_view.show_all_profiles->isChecked() && std.contains("mlt_profile=")) {
                     QString profile = std.section("mlt_profile=", 1, 1).section(' ', 0, 0);
                     MltVideoProfile p = ProfilesDialog::getVideoProfile(profile);
                     if (p.frame_rate_den > 0) {
@@ -1331,11 +1354,8 @@ void RenderWidget::refreshView()
             }
         }
     }
-    // m_view.size_list->sortItems();
-    focusFirstVisibleItem();
-    m_view.size_list->setVisible(m_view.size_list->count() > 1 || m_view.format_list->count() <= 1);
+    focusFirstVisibleItem(profile);
     m_view.size_list->blockSignals(false);
-    m_view.format_list->blockSignals(false);
     if (m_view.size_list->count() > 0) {
         refreshParams();
     }
@@ -1421,7 +1441,7 @@ void RenderWidget::refreshParams()
         m_view.bitrateLabel->setEnabled(true);
         if ( item->data(BitratesRole).canConvert(QVariant::StringList) && item->data(BitratesRole).toStringList().count()) {
             QStringList bitrates = item->data(BitratesRole).toStringList();
-            foreach (QString bitrate, bitrates)
+            foreach (const QString &bitrate, bitrates)
                 m_view.comboBitrates->addItem(bitrate);
             if (item->data(DefaultBitrateRole).canConvert(QVariant::String))
                 m_view.comboBitrates->setCurrentIndex(bitrates.indexOf(item->data(DefaultBitrateRole).toString()));
@@ -1438,7 +1458,7 @@ void RenderWidget::refreshParams()
         m_view.audiobitrateLabel->setEnabled(true);
         if ( item->data(AudioBitratesRole).canConvert(QVariant::StringList) && item->data(AudioBitratesRole).toStringList().count()) {
             QStringList audiobitrates = item->data(AudioBitratesRole).toStringList();
-            foreach (QString bitrate, audiobitrates)
+            foreach (const QString &bitrate, audiobitrates)
                 m_view.comboAudioBitrates->addItem(bitrate);
             if (item->data(DefaultAudioBitrateRole).canConvert(QVariant::String))
                 m_view.comboAudioBitrates->setCurrentIndex(audiobitrates.indexOf(item->data(DefaultAudioBitrateRole).toString()));
@@ -1463,10 +1483,7 @@ void RenderWidget::reloadProfiles()
 
 void RenderWidget::parseProfiles(QString meta, QString group, QString profile)
 {
-    m_view.size_list->blockSignals(true);
-    m_view.format_list->blockSignals(true);
-    m_view.size_list->clear();
-    m_view.format_list->clear();
+    m_view.destination_list->blockSignals(true);
     m_view.destination_list->clear();
     qDeleteAll(m_renderItems);
     qDeleteAll(m_renderCategory);
@@ -1497,27 +1514,11 @@ void RenderWidget::parseProfiles(QString meta, QString group, QString profile)
         parseFile(exportFolder + filename, true);
     if (QFile::exists(exportFolder + "customprofiles.xml")) parseFile(exportFolder + "customprofiles.xml", true);
 
-    if (!meta.isEmpty()) {
-        m_view.destination_list->blockSignals(true);
-        m_view.destination_list->setCurrentIndex(m_view.destination_list->findData(meta));
-        m_view.destination_list->blockSignals(false);
-    }
-    refreshCategory();
-    QList<QListWidgetItem *> child;
-    if (!group.isEmpty()) child = m_view.format_list->findItems(group, Qt::MatchExactly);
-    if (!child.isEmpty()) {
-        for (int i = 0; i < child.count(); i++) {
-            if (child.at(i)->data(MetaGroupRole).toString() == meta) {
-                m_view.format_list->setCurrentItem(child.at(i));
-                break;
-            }
-        }
-    }
-    child.clear();
-    m_view.size_list->blockSignals(false);
-    m_view.format_list->blockSignals(false);
-    if (!profile.isEmpty()) child = m_view.size_list->findItems(profile, Qt::MatchExactly);
-    if (!child.isEmpty()) m_view.size_list->setCurrentItem(child.at(0));
+    int categoryIndex = m_view.destination_list->findData(meta);
+    if (categoryIndex == -1) categoryIndex = 0;
+    m_view.destination_list->setCurrentIndex(categoryIndex);
+    m_view.destination_list->blockSignals(false);
+    refreshCategory(group, profile);
 }
 
 void RenderWidget::parseFile(QString exportFile, bool editable)
@@ -1539,7 +1540,6 @@ void RenderWidget::parseFile(QString exportFile, bool editable)
     bool replaceLibfaacCodec = false;
     if (!acodecsList.contains("aac") && acodecsList.contains("libfaac")) replaceLibfaacCodec = true;
 
-
     if (editable || groups.count() == 0) {
         QDomElement profiles = doc.documentElement();
         if (editable && profiles.attribute("version", 0).toInt() < 1) {
@@ -1789,7 +1789,7 @@ void RenderWidget::setRenderStatus(const QString &dest, int status, const QStrin
         item->setData(1, Qt::UserRole, t);
         QString itemGroup = item->data(0, Qt::UserRole).toString();
         if (itemGroup == "dvd") {
-            emit openDvdWizard(item->text(1), item->metadata());
+            emit openDvdWizard(item->text(1));
         } else if (itemGroup == "websites") {
             QString url = item->metadata();
             if (!url.isEmpty()) new KRun(url, this);
@@ -1888,7 +1888,7 @@ void RenderWidget::parseScriptFiles()
             QTextStream stream(&file);
             while (!stream.atEnd()) {
                 QString line = stream.readLine();
-                kDebug()<<"# :"<<line;
+                //kDebug()<<"# :"<<line;
                 if (line.startsWith("TARGET=")) {
                     target = line.section("TARGET=\"", 1);
                     target = target.section('"', 0, 0);
@@ -1903,7 +1903,7 @@ void RenderWidget::parseScriptFiles()
             file.close();
         }
         if (target.isEmpty()) continue;
-        kDebug()<<"ScRIPT RENDERER: "<<renderer<<"\n++++++++++++++++++++++++++";
+        //kDebug()<<"ScRIPT RENDERER: "<<renderer<<"\n++++++++++++++++++++++++++";
         item = new QTreeWidgetItem(m_view.scripts_list, QStringList() << QString() << scriptpath.fileName());
         if (!renderer.isEmpty() && renderer.contains('/') && !QFile::exists(renderer)) {
             item->setIcon(0, KIcon("dialog-cancel"));
@@ -1915,18 +1915,14 @@ void RenderWidget::parseScriptFiles()
             item->setData(0, Qt::UserRole, '1');
         } else item->setIcon(0, KIcon("application-x-executable-script"));
         item->setSizeHint(0, QSize(m_view.scripts_list->columnWidth(0), fontMetrics().height() * 2));
-        item->setData(1, Qt::UserRole, KUrl(target).path());
+        item->setData(1, Qt::UserRole, KUrl(QUrl::fromEncoded(target.toUtf8())).pathOrUrl());
         item->setData(1, Qt::UserRole + 1, scriptpath.path());
     }
-//     bool activate = false;
     QTreeWidgetItem *script = m_view.scripts_list->topLevelItem(0);
     if (script) {
         m_view.scripts_list->setCurrentItem(script);
         script->setSelected(true);
-//         activate = true;
     }
-//    m_view.start_script->setEnabled(activate);
-//    m_view.delete_script->setEnabled(activate);
 }
 
 void RenderWidget::slotCheckScript()
@@ -2000,8 +1996,6 @@ void RenderWidget::slotHideLog()
 
 void RenderWidget::setRenderProfile(QMap <QString, QString> props)
 {
-    m_view.destination_list->blockSignals(true);
-    m_view.format_list->blockSignals(true);
     m_view.scanning_list->setCurrentIndex(props.value("renderscanning").toInt());
     int exportAudio = props.value("renderexportaudio").toInt();
     switch (exportAudio) {
@@ -2035,41 +2029,20 @@ void RenderWidget::setRenderProfile(QMap <QString, QString> props)
     if (!url.isEmpty()) m_view.out_file->setUrl(KUrl(url));
 
     // set destination
-    for (int i = 0; i < m_view.destination_list->count(); i++) {
-        if (m_view.destination_list->itemData(i, Qt::UserRole) == props.value("renderdestination")) {
-            m_view.destination_list->setCurrentIndex(i);
-            break;
-        }
-    }
-    refreshCategory();
-
-    // set category
-    QString group = props.value("rendercategory");
-    if (!group.isEmpty()) {
-        QList<QListWidgetItem *> childs = m_view.format_list->findItems(group, Qt::MatchExactly);
-        if (!childs.isEmpty()) {
-            m_view.format_list->setCurrentItem(childs.at(0));
-            m_view.format_list->scrollToItem(childs.at(0));
-        }
-        refreshView();
-    }
-
-    // set profile
-    QList<QListWidgetItem *> childs = m_view.size_list->findItems(props.value("renderprofile"), Qt::MatchExactly);
-    if (!childs.isEmpty()) {
-        m_view.size_list->setCurrentItem(childs.at(0));
-        m_view.size_list->scrollToItem(childs.at(0));
-    }
-    //refreshView();
+    int categoryIndex = m_view.destination_list->findData(props.value("renderdestination"));
+    if (categoryIndex == -1) categoryIndex = 0;
+    m_view.destination_list->blockSignals(true);
+    m_view.destination_list->setCurrentIndex(categoryIndex);
     m_view.destination_list->blockSignals(false);
-    m_view.format_list->blockSignals(false);
-
+    
+    // Clear previous error messages
+    refreshCategory(props.value("rendercategory"), props.value("renderprofile"));
 }
 
 bool RenderWidget::startWaitingRenderJobs()
 {
     m_blockProcessing = true;
-    QString autoscriptFile = getFreeScriptName("auto");
+    QString autoscriptFile = getFreeScriptName(KUrl(), "auto");
     QFile file(autoscriptFile);
     if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
         kWarning() << "//////  ERROR writing to file: " << autoscriptFile;
@@ -2107,15 +2080,18 @@ bool RenderWidget::startWaitingRenderJobs()
     return true;
 }
 
-QString RenderWidget::getFreeScriptName(const QString &prefix)
+QString RenderWidget::getFreeScriptName(const KUrl &projectName, const QString &prefix)
 {
     int ix = 0;
     QString scriptsFolder = m_projectFolder + "scripts/";
     KStandardDirs::makeDir(scriptsFolder);
     QString path;
+    QString fileName;
+    if (projectName.isEmpty()) fileName = i18n("script");
+    else fileName = projectName.fileName().section('.', 0, -2) + "_";
     while (path.isEmpty() || QFile::exists(path)) {
         ix++;
-        path = scriptsFolder + prefix + i18n("script") + QString::number(ix).rightJustified(3, '0', false) + ".sh";
+        path = scriptsFolder + prefix + fileName + QString::number(ix).rightJustified(3, '0', false) + ".sh";
     }
     return path;
 }
@@ -2143,7 +2119,12 @@ void RenderWidget::errorMessage(const QString &message)
 #if KDE_IS_VERSION(4,7,0)
         m_infoMessage->setMessageType(KMessageWidget::Warning);
         m_infoMessage->setText(message);
+#if KDE_IS_VERSION(4,10,0)
         m_infoMessage->animatedShow();
+#else
+       // Workaround KDE bug in KMessageWidget
+       QTimer::singleShot(0, m_infoMessage, SLOT(animatedShow()));
+#endif
 #else
         m_view.errorLabel->setText(message);
         m_view.errorBox->setHidden(false);
@@ -2151,10 +2132,19 @@ void RenderWidget::errorMessage(const QString &message)
     }
     else {
 #if KDE_IS_VERSION(4,7,0)
-        m_infoMessage->animatedHide();
+       if (m_view.tabWidget->currentIndex() == 0 && m_infoMessage->isVisible())  {
+#if KDE_IS_VERSION(4,10,0)
+           m_infoMessage->animatedHide();
 #else
-        m_view.errorBox->setHidden(true);
-        m_view.errorLabel->setText(QString());
+           QTimer::singleShot(0, m_infoMessage, SLOT(animatedHide()));
+#endif
+       } else {
+           // Seems like animated hide does not work when page is not visible
+           m_infoMessage->hide();
+       }
+#else
+       m_view.errorBox->setHidden(true);
+       m_view.errorLabel->setText(QString());
 #endif
 
     }
@@ -2227,3 +2217,20 @@ void RenderWidget::setRescaleEnabled(bool enable)
     }   
 }
 
+void RenderWidget::keyPressEvent(QKeyEvent *e) {
+    if(e->key()==Qt::Key_Return || e->key()==Qt::Key_Enter) {
+       switch (m_view.tabWidget->currentIndex()) {
+         case 1:
+           if (m_view.start_job->isEnabled()) slotStartCurrentJob();
+           break;
+         case 2:
+           if (m_view.start_script->isEnabled()) slotStartScript();
+           break;
+         default:
+           if (m_view.buttonRender->isEnabled()) slotPrepareExport();
+           break;
+       }
+    }
+    else QDialog::keyPressEvent(e);
+}
+