]> git.sesse.net Git - kdenlive/blobdiff - src/clipproperties.cpp
Fix scripts with special chars in render name:
[kdenlive] / src / clipproperties.cpp
index 157250c0e03c04eae8a48dfc2185f345a7ba3133..d75400fa8bff16a301d9944cbd5facf0b2db8b17 100644 (file)
@@ -47,53 +47,105 @@ ClipProperties::ClipProperties(DocClipBase *clip, Timecode tc, double fps, QWidg
     m_fps(fps),
     m_count(0),
     m_clipNeedsRefresh(false),
-    m_clipNeedsReLoad(false)
+    m_clipNeedsReLoad(false),
+    m_propsDelegate(NULL)
 {
+    setAttribute(Qt::WA_DeleteOnClose, true);
     setFont(KGlobalSettings::toolBarFont());
     m_view.setupUi(this);
     KUrl url = m_clip->fileURL();
     m_view.clip_path->setText(url.path());
     m_view.clip_description->setText(m_clip->description());
-    QMap <QString, QString> props = m_clip->properties();
+    connect(m_view.clip_description, SIGNAL(textChanged(QString)), this, SLOT(slotModified()));
 
+    QMap <QString, QString> props = m_clip->properties();
     m_view.clip_force_out->setHidden(true);
     m_view.clip_out->setHidden(true);
 
-    if (props.contains("force_aspect_ratio") && props.value("force_aspect_ratio").toDouble() > 0) {
+    // New display aspect ratio support
+    if (props.contains("force_aspect_num") && props.value("force_aspect_num").toInt() > 0 &&
+        props.contains("force_aspect_den") && props.value("force_aspect_den").toInt() > 0) {
         m_view.clip_force_ar->setChecked(true);
-        m_view.clip_ar->setEnabled(true);
-        m_view.clip_ar->setValue(props.value("force_aspect_ratio").toDouble());
+        m_view.clip_ar_num->setEnabled(true);
+        m_view.clip_ar_den->setEnabled(true);
+        m_view.clip_ar_num->setValue(props.value("force_aspect_num").toInt());
+        m_view.clip_ar_den->setValue(props.value("force_aspect_den").toInt());
+    }
+    // Legacy support for pixel aspect ratio
+    else if (props.contains("force_aspect_ratio") && props.value("force_aspect_ratio").toDouble() > 0) {
+        m_view.clip_force_ar->setChecked(true);
+        m_view.clip_ar_num->setEnabled(true);
+        m_view.clip_ar_den->setEnabled(true);
+        if (props.contains("frame_size")) {
+            int width = props.value("force_aspect_ratio").toDouble() * props.value("frame_size").section('x', 0, 0).toInt();
+            int height = props.value("frame_size").section('x', 1, 1).toInt();
+            if (width > 0 && height > 0) {
+                if ((width / height * 100) == 133) {
+                    width = 4;
+                    height = 3;
+                }
+                else if (int(width / height * 100) == 177) {
+                    width = 16;
+                    height = 9;
+                }
+                m_view.clip_ar_num->setValue(width);
+                m_view.clip_ar_den->setValue(height);
+            }
+        }
     }
+    connect(m_view.clip_force_ar, SIGNAL(toggled(bool)), this, SLOT(slotModified()));
+    connect(m_view.clip_ar_num, SIGNAL(valueChanged(int)), this, SLOT(slotModified()));
+    connect(m_view.clip_ar_den, SIGNAL(valueChanged(int)), this, SLOT(slotModified()));
 
     if (props.contains("force_fps") && props.value("force_fps").toDouble() > 0) {
         m_view.clip_force_framerate->setChecked(true);
         m_view.clip_framerate->setEnabled(true);
         m_view.clip_framerate->setValue(props.value("force_fps").toDouble());
     }
+    connect(m_view.clip_force_framerate, SIGNAL(toggled(bool)), this, SLOT(slotModified()));
+    connect(m_view.clip_framerate, SIGNAL(valueChanged(double)), this, SLOT(slotModified()));
 
     if (props.contains("force_progressive")) {
         m_view.clip_force_progressive->setChecked(true);
         m_view.clip_progressive->setEnabled(true);
         m_view.clip_progressive->setValue(props.value("force_progressive").toInt());
     }
+    connect(m_view.clip_force_progressive, SIGNAL(toggled(bool)), this, SLOT(slotModified()));
+    connect(m_view.clip_progressive, SIGNAL(valueChanged(int)), this, SLOT(slotModified()));
 
+    m_view.clip_fieldorder->addItem(i18n("Bottom first"), 0);
+    m_view.clip_fieldorder->addItem(i18n("Top first"), 1);
+    if (props.contains("force_tff")) {
+        m_view.clip_force_fieldorder->setChecked(true);
+        m_view.clip_fieldorder->setEnabled(true);
+        m_view.clip_fieldorder->setCurrentIndex(props.value("force_tff").toInt());
+    }
+    connect(m_view.clip_force_fieldorder, SIGNAL(toggled(bool)), this, SLOT(slotModified()));
+    connect(m_view.clip_fieldorder, SIGNAL(currentIndexChanged(int)), this, SLOT(slotModified()));
+    
     if (props.contains("threads") && props.value("threads").toInt() != 1) {
         m_view.clip_force_threads->setChecked(true);
         m_view.clip_threads->setEnabled(true);
         m_view.clip_threads->setValue(props.value("threads").toInt());
     }
+    connect(m_view.clip_force_threads, SIGNAL(toggled(bool)), this, SLOT(slotModified()));
+    connect(m_view.clip_threads, SIGNAL(valueChanged(int)), this, SLOT(slotModified()));
 
     if (props.contains("video_index") && props.value("video_index").toInt() != 0) {
         m_view.clip_force_vindex->setChecked(true);
         m_view.clip_vindex->setEnabled(true);
         m_view.clip_vindex->setValue(props.value("video_index").toInt());
     }
+    connect(m_view.clip_force_vindex, SIGNAL(toggled(bool)), this, SLOT(slotModified()));
+    connect(m_view.clip_vindex, SIGNAL(valueChanged(int)), this, SLOT(slotModified()));
 
     if (props.contains("audio_index") && props.value("audio_index").toInt() != 0) {
         m_view.clip_force_aindex->setChecked(true);
         m_view.clip_aindex->setEnabled(true);
         m_view.clip_aindex->setValue(props.value("audio_index").toInt());
     }
+    connect(m_view.clip_force_aindex, SIGNAL(toggled(bool)), this, SLOT(slotModified()));
+    connect(m_view.clip_aindex, SIGNAL(valueChanged(int)), this, SLOT(slotModified()));
 
     if (props.contains("audio_max")) {
         m_view.clip_aindex->setMaximum(props.value("audio_max").toInt());
@@ -102,6 +154,24 @@ ClipProperties::ClipProperties(DocClipBase *clip, Timecode tc, double fps, QWidg
     if (props.contains("video_max")) {
         m_view.clip_vindex->setMaximum(props.value("video_max").toInt());
     }
+    
+    m_view.clip_colorspace->addItem(ProfilesDialog::getColorspaceDescription(601), 601);
+    m_view.clip_colorspace->addItem(ProfilesDialog::getColorspaceDescription(709), 709);
+    m_view.clip_colorspace->addItem(ProfilesDialog::getColorspaceDescription(240), 240);
+    if (props.contains("force_colorspace")) {
+        m_view.clip_force_colorspace->setChecked(true);
+        m_view.clip_colorspace->setEnabled(true);
+        m_view.clip_colorspace->setCurrentIndex(m_view.clip_colorspace->findData(props.value("force_colorspace").toInt()));
+    } else if (props.contains("colorspace")) {
+        m_view.clip_colorspace->setCurrentIndex(m_view.clip_colorspace->findData(props.value("colorspace").toInt()));
+    }
+    connect(m_view.clip_force_colorspace, SIGNAL(toggled(bool)), this, SLOT(slotModified()));
+    connect(m_view.clip_colorspace, SIGNAL(currentIndexChanged(int)), this, SLOT(slotModified()));
+    
+    if (props.contains("full_luma")) {
+        m_view.clip_full_luma->setChecked(true);
+    }
+    connect(m_view.clip_full_luma, SIGNAL(toggled(bool)), this, SLOT(slotModified()));
 
     // Check for Metadata
     QMap<QString, QString> meta = m_clip->metadata();
@@ -113,12 +183,15 @@ ClipProperties::ClipProperties(DocClipBase *clip, Timecode tc, double fps, QWidg
         ++i;
     }
 
-    connect(m_view.clip_force_ar, SIGNAL(toggled(bool)), m_view.clip_ar, SLOT(setEnabled(bool)));
+    connect(m_view.clip_force_ar, SIGNAL(toggled(bool)), m_view.clip_ar_num, SLOT(setEnabled(bool)));
+    connect(m_view.clip_force_ar, SIGNAL(toggled(bool)), m_view.clip_ar_den, SLOT(setEnabled(bool)));
     connect(m_view.clip_force_framerate, SIGNAL(toggled(bool)), m_view.clip_framerate, SLOT(setEnabled(bool)));
     connect(m_view.clip_force_progressive, SIGNAL(toggled(bool)), m_view.clip_progressive, SLOT(setEnabled(bool)));
+    connect(m_view.clip_force_fieldorder, SIGNAL(toggled(bool)), m_view.clip_fieldorder, SLOT(setEnabled(bool)));
     connect(m_view.clip_force_threads, SIGNAL(toggled(bool)), m_view.clip_threads, SLOT(setEnabled(bool)));
     connect(m_view.clip_force_vindex, SIGNAL(toggled(bool)), m_view.clip_vindex, SLOT(setEnabled(bool)));
     connect(m_view.clip_force_aindex, SIGNAL(toggled(bool)), m_view.clip_aindex, SLOT(setEnabled(bool)));
+    connect(m_view.clip_force_colorspace, SIGNAL(toggled(bool)), m_view.clip_colorspace, SLOT(setEnabled(bool)));
 
     if (props.contains("audiocodec"))
         QTreeWidgetItem *item = new QTreeWidgetItem(m_view.clip_aproperties, QStringList() << i18n("Audio codec") << props.value("audiocodec"));
@@ -147,6 +220,7 @@ ClipProperties::ClipProperties(DocClipBase *clip, Timecode tc, double fps, QWidg
             m_view.image_size->setText(props.value("frame_size"));
         if (props.contains("transparency"))
             m_view.image_transparency->setChecked(props.value("transparency").toInt());
+        connect(m_view.image_transparency, SIGNAL(toggled(bool)), this, SLOT(slotModified()));
         int width = 180.0 * KdenliveSettings::project_display_ratio();
         if (width % 2 == 1) width++;
         m_view.clip_thumb->setPixmap(QPixmap(url.path()).scaled(QSize(width, 180), Qt::KeepAspectRatio));
@@ -159,6 +233,7 @@ ClipProperties::ClipProperties(DocClipBase *clip, Timecode tc, double fps, QWidg
         m_view.tabWidget->removeTab(VIDEOTAB);
         m_view.clip_thumb->setHidden(true);
         m_view.clip_color->setColor(QColor('#' + props.value("colour").right(8).left(6)));
+        connect(m_view.clip_color, SIGNAL(changed(QColor)), this, SLOT(slotModified()));
     } else if (t == SLIDESHOW) {
         bool isMime = true;
         if (url.fileName().startsWith(".all.")) {
@@ -185,6 +260,7 @@ ClipProperties::ClipProperties(DocClipBase *clip, Timecode tc, double fps, QWidg
         m_view.image_type->addItem("BMP (*.bmp)", "bmp");
         m_view.image_type->addItem("GIF (*.gif)", "gif");
         m_view.image_type->addItem("TGA (*.tga)", "tga");
+        m_view.image_type->addItem("TIF (*.tif)", "tif");
         m_view.image_type->addItem("TIFF (*.tiff)", "tiff");
         m_view.image_type->addItem("Open EXR (*.exr)", "exr");
         m_view.animation->addItem(i18n("None"), QString());
@@ -213,7 +289,7 @@ ClipProperties::ClipProperties(DocClipBase *clip, Timecode tc, double fps, QWidg
         }
         m_view.slide_duration->setText(tc.getTimecodeFromFrames(props.value("ttl").toInt()));
 
-        m_view.slide_duration_format->addItem(i18n("hh:mm:ss::ff"));
+        m_view.slide_duration_format->addItem(i18n("hh:mm:ss:ff"));
         m_view.slide_duration_format->addItem(i18n("Frames"));
         connect(m_view.slide_duration_format, SIGNAL(activated(int)), this, SLOT(slotUpdateDurationFormat(int)));
         m_view.slide_duration_frames->setHidden(true);
@@ -254,10 +330,23 @@ ClipProperties::ClipProperties(DocClipBase *clip, Timecode tc, double fps, QWidg
         } else m_view.luma_file->setEnabled(false);
         slotEnableLuma(m_view.slide_fade->checkState());
         slotEnableLumaFile(m_view.slide_luma->checkState());
+
+        connect(m_view.slide_fade, SIGNAL(toggled(bool)), this, SLOT(slotModified()));
+        connect(m_view.slide_luma, SIGNAL(toggled(bool)), this, SLOT(slotModified()));
+        connect(m_view.slide_loop, SIGNAL(toggled(bool)), this, SLOT(slotModified()));
+        connect(m_view.slide_crop, SIGNAL(toggled(bool)), this, SLOT(slotModified()));
+        connect(m_view.slide_duration, SIGNAL(textChanged(QString)), this, SLOT(slotModified()));
+        connect(m_view.slide_duration_frames, SIGNAL(valueChanged(int)), this, SLOT(slotModified()));
+        connect(m_view.luma_duration, SIGNAL(textChanged(QString)), this, SLOT(slotModified()));
+        connect(m_view.luma_softness, SIGNAL(valueChanged(int)), this, SLOT(slotModified()));
+        connect(m_view.luma_file, SIGNAL(currentIndexChanged(int)), this, SLOT(slotModified()));
+        connect(m_view.animation, SIGNAL(currentIndexChanged(int)), this, SLOT(slotModified()));
+
+
         connect(m_view.slide_fade, SIGNAL(stateChanged(int)), this, SLOT(slotEnableLuma(int)));
         connect(m_view.slide_luma, SIGNAL(stateChanged(int)), this, SLOT(slotEnableLumaFile(int)));
-
         connect(m_view.image_type, SIGNAL(currentIndexChanged(int)), this, SLOT(parseFolder()));
+
     } else if (t != AUDIO) {
         m_view.tabWidget->removeTab(IMAGETAB);
         m_view.tabWidget->removeTab(SLIDETAB);
@@ -330,6 +419,9 @@ ClipProperties::ClipProperties(DocClipBase *clip, Timecode tc, double fps, QWidg
     connect(m_view.marker_delete, SIGNAL(clicked()), this, SLOT(slotDeleteMarker()));
     connect(m_view.markers_list, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(slotEditMarker()));
 
+    connect(this, SIGNAL(accepted()), this, SLOT(slotApplyProperties()));
+    connect(m_view.buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(slotApplyProperties()));
+    m_view.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
     //adjustSize();
 }
 
@@ -349,10 +441,12 @@ ClipProperties::ClipProperties(QList <DocClipBase *>cliplist, Timecode tc, QMap
     QMap <QString, QString> props = cliplist.at(0)->properties();
     m_old_props = commonproperties;
 
-    if (commonproperties.contains("force_aspect_ratio") && !commonproperties.value("force_aspect_ratio").isEmpty() && commonproperties.value("force_aspect_ratio").toDouble() > 0) {
+    if (commonproperties.contains("force_aspect_num") && !commonproperties.value("force_aspect_num").isEmpty() && commonproperties.value("force_aspect_den").toInt() > 0) {
         m_view.clip_force_ar->setChecked(true);
-        m_view.clip_ar->setEnabled(true);
-        m_view.clip_ar->setValue(commonproperties.value("force_aspect_ratio").toDouble());
+        m_view.clip_ar_num->setEnabled(true);
+        m_view.clip_ar_den->setEnabled(true);
+        m_view.clip_ar_num->setValue(commonproperties.value("force_aspect_num").toInt());
+        m_view.clip_ar_den->setValue(commonproperties.value("force_aspect_den").toInt());
     }
 
     if (commonproperties.contains("force_fps") && !commonproperties.value("force_fps").isEmpty() && commonproperties.value("force_fps").toDouble() > 0) {
@@ -367,6 +461,12 @@ ClipProperties::ClipProperties(QList <DocClipBase *>cliplist, Timecode tc, QMap
         m_view.clip_progressive->setValue(commonproperties.value("force_progressive").toInt());
     }
 
+    if (commonproperties.contains("force_tff") && !commonproperties.value("force_tff").isEmpty()) {
+        m_view.clip_force_fieldorder->setChecked(true);
+        m_view.clip_fieldorder->setEnabled(true);
+        m_view.clip_fieldorder->setCurrentIndex(commonproperties.value("force_tff").toInt());
+    }
+    
     if (commonproperties.contains("threads") && !commonproperties.value("threads").isEmpty() && commonproperties.value("threads").toInt() != 1) {
         m_view.clip_force_threads->setChecked(true);
         m_view.clip_threads->setEnabled(true);
@@ -392,13 +492,25 @@ ClipProperties::ClipProperties(QList <DocClipBase *>cliplist, Timecode tc, QMap
     if (props.contains("video_max")) {
         m_view.clip_vindex->setMaximum(props.value("video_max").toInt());
     }
+    
+    if (commonproperties.contains("force_colorspace") && !commonproperties.value("force_colorspace").isEmpty() && commonproperties.value("force_colorspace").toInt() != 0) {
+        m_view.clip_force_colorspace->setChecked(true);
+        m_view.clip_colorspace->setEnabled(true);
+        m_view.clip_colorspace->setCurrentIndex(m_view.clip_colorspace->findData(commonproperties.value("force_colorspace").toInt()));
+    }
+    
+    if (commonproperties.contains("full_luma") && !commonproperties.value("full_luma").isEmpty()) {
+        m_view.clip_full_luma->setChecked(true);
+    }
 
-    connect(m_view.clip_force_ar, SIGNAL(toggled(bool)), m_view.clip_ar, SLOT(setEnabled(bool)));
+    connect(m_view.clip_force_ar, SIGNAL(toggled(bool)), m_view.clip_ar_num, SLOT(setEnabled(bool)));
+    connect(m_view.clip_force_ar, SIGNAL(toggled(bool)), m_view.clip_ar_den, SLOT(setEnabled(bool)));
     connect(m_view.clip_force_progressive, SIGNAL(toggled(bool)), m_view.clip_progressive, SLOT(setEnabled(bool)));
     connect(m_view.clip_force_threads, SIGNAL(toggled(bool)), m_view.clip_threads, SLOT(setEnabled(bool)));
     connect(m_view.clip_force_vindex, SIGNAL(toggled(bool)), m_view.clip_vindex, SLOT(setEnabled(bool)));
     connect(m_view.clip_force_aindex, SIGNAL(toggled(bool)), m_view.clip_aindex, SLOT(setEnabled(bool)));
     connect(m_view.clip_force_out, SIGNAL(toggled(bool)), m_view.clip_out, SLOT(setEnabled(bool)));
+    connect(m_view.clip_force_colorspace, SIGNAL(toggled(bool)), m_view.clip_colorspace, SLOT(setEnabled(bool)));
 
     m_view.tabWidget->removeTab(METATAB);
     m_view.tabWidget->removeTab(MARKERTAB);
@@ -433,9 +545,32 @@ ClipProperties::ClipProperties(QList <DocClipBase *>cliplist, Timecode tc, QMap
 
 ClipProperties::~ClipProperties()
 {
-    delete m_propsDelegate;
+    if (m_propsDelegate) delete m_propsDelegate;
 }
 
+void ClipProperties::slotApplyProperties()
+{
+    if (m_clip != NULL)
+        emit applyNewClipProperties(m_clip->getId(), m_clip->properties(), properties(), needsTimelineRefresh(), needsTimelineReload());
+    m_view.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
+}
+
+void ClipProperties::disableClipId(const QString &id)
+{
+    if (m_clip && m_view.buttonBox->button(QDialogButtonBox::Ok)->isEnabled()) {
+        if (m_clip->getId() == id) {
+            // clip was removed from project, close this properties dialog
+            close();
+        }
+    }
+}
+
+void ClipProperties::slotModified()
+{
+    m_view.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(true);
+}
+
+
 void ClipProperties::slotEnableLuma(int state)
 {
     bool enable = false;
@@ -518,15 +653,25 @@ QMap <QString, QString> ClipProperties::properties()
         m_old_props = m_clip->properties();
     }
 
-    double aspect = m_view.clip_ar->value();
+    int aspectNumerator = m_view.clip_ar_num->value();
+    int aspectDenominator = m_view.clip_ar_den->value();
     if (m_view.clip_force_ar->isChecked()) {
-        if (aspect != m_old_props.value("force_aspect_ratio").toDouble()) {
-            props["force_aspect_ratio"] = QString::number(aspect);
+        if (aspectNumerator != m_old_props.value("force_aspect_num").toInt() ||
+            aspectDenominator != m_old_props.value("force_aspect_den").toInt()) {
+            props["force_aspect_num"] = QString::number(aspectNumerator);
+            props["force_aspect_den"] = QString::number(aspectDenominator);
+            props["force_aspect_ratio"].clear();
+            m_clipNeedsRefresh = true;
+        }
+    } else {
+        if (m_old_props.contains("force_aspect_num")) {
+            props["force_aspect_num"].clear();
+            m_clipNeedsRefresh = true;
+        }
+        if (m_old_props.contains("force_aspect_den")) {
+            props["force_aspect_den"].clear();
             m_clipNeedsRefresh = true;
         }
-    } else if (m_old_props.contains("force_aspect_ratio")) {
-        props["force_aspect_ratio"].clear();
-        m_clipNeedsRefresh = true;
     }
 
     double fps = m_view.clip_framerate->value();
@@ -549,6 +694,15 @@ QMap <QString, QString> ClipProperties::properties()
         props["force_progressive"].clear();
     }
 
+    int fieldOrder = m_view.clip_fieldorder->currentIndex();
+    if (m_view.clip_force_fieldorder->isChecked()) {
+        if (fieldOrder != m_old_props.value("force_tff").toInt()) {
+            props["force_tff"] = QString::number(fieldOrder);
+        }
+    } else if (m_old_props.contains("force_tff")) {
+        props["force_tff"].clear();
+    }
+
     int threads = m_view.clip_threads->value();
     if (m_view.clip_force_threads->isChecked()) {
         if (threads != m_old_props.value("threads").toInt()) {
@@ -575,6 +729,25 @@ QMap <QString, QString> ClipProperties::properties()
     } else if (m_old_props.contains("audio_index")) {
         props["audio_index"].clear();
     }
+    
+    int colorspace = m_view.clip_colorspace->itemData(m_view.clip_colorspace->currentIndex()).toInt();
+    if (m_view.clip_force_colorspace->isChecked()) {
+        if (colorspace != m_old_props.value("force_colorspace").toInt()) {
+            props["force_colorspace"] = QString::number(colorspace);
+            m_clipNeedsRefresh = true;
+        }
+    } else if (m_old_props.contains("force_colorspace")) {
+        props["force_colorspace"].clear();
+        m_clipNeedsRefresh = true;
+    }
+
+    if (m_view.clip_full_luma->isChecked()) {
+        props["full_luma"] = QString::number(1);
+        m_clipNeedsRefresh = true;
+    } else if (m_old_props.contains("full_luma")) {
+        props["full_luma"].clear();
+        m_clipNeedsRefresh = true;
+    }
 
     // If we adjust several clips, return now
     if (m_clip == NULL) {
@@ -725,6 +898,7 @@ void ClipProperties::parseFolder()
     }
 
     m_count = result.count();
+    m_view.buttonBox->button(QDialogButtonBox::Apply)->setEnabled(m_count > 0);
     if (m_count == 0) {
         // no images, do not accept that
         m_view.slide_info->setText(i18n("No image found"));