]> git.sesse.net Git - kdenlive/commitdiff
Allow changing advanced properties of several clips at once (aspect ratio, ...)
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Tue, 15 Dec 2009 10:45:50 +0000 (10:45 +0000)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Tue, 15 Dec 2009 10:45:50 +0000 (10:45 +0000)
svn path=/trunk/kdenlive/; revision=4182

src/clipitem.cpp
src/clipproperties.cpp
src/clipproperties.h
src/customtrackview.cpp
src/mainwindow.cpp
src/mainwindow.h
src/projectlist.cpp
src/projectlist.h
src/widgets/clipproperties_ui.ui

index d907666ef54fdeeb159a7b199e3e943e7f5fd98f..05dbb2feb156e75e99f70051f7f3ef9fbc1fd5ed 100644 (file)
@@ -1341,8 +1341,7 @@ EffectsParameterList ClipItem::addEffect(const QDomElement effect, bool /*animat
                 parameters.addParam("factor", e.attribute("factor", "1"));
                 parameters.addParam("starttag", e.attribute("starttag", "start"));
                 parameters.addParam("endtag", e.attribute("endtag", "end"));
-            }
-            else if (e.attribute("factor", "1") == "1") {
+            } else if (e.attribute("factor", "1") == "1") {
                 parameters.addParam(e.attribute("name"), e.attribute("value"));
 
                 // check if it is a fade effect
index 02fa956017c2dfc74242d26227f2db7699059b76..8c058c6fe419f0bdfaef466b7ab9c0381a5d11fd 100644 (file)
@@ -269,6 +269,87 @@ ClipProperties::ClipProperties(DocClipBase *clip, Timecode tc, double fps, QWidg
     //adjustSize();
 }
 
+
+// Used for multiple clips editing
+ClipProperties::ClipProperties(QList <DocClipBase *>cliplist, QMap <QString, QString> commonproperties, QWidget * parent) :
+        QDialog(parent),
+        m_clip(NULL),
+        m_fps(0),
+        m_count(0),
+        m_clipNeedsRefresh(false),
+        m_clipNeedsReLoad(false)
+{
+    setFont(KGlobalSettings::toolBarFont());
+    m_view.setupUi(this);
+    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) {
+        m_view.clip_force_ar->setChecked(true);
+        m_view.clip_ar->setEnabled(true);
+        m_view.clip_ar->setValue(commonproperties.value("force_aspect_ratio").toDouble());
+    }
+
+    if (commonproperties.contains("force_progressive") && !commonproperties.value("force_progressive").isEmpty()) {
+        m_view.clip_force_progressive->setChecked(true);
+        m_view.clip_progressive->setEnabled(true);
+        m_view.clip_progressive->setValue(commonproperties.value("force_progressive").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);
+        m_view.clip_threads->setValue(commonproperties.value("threads").toInt());
+    }
+
+    if (commonproperties.contains("video_index") && !commonproperties.value("video_index").isEmpty() && commonproperties.value("video_index").toInt() != 0) {
+        m_view.clip_force_vindex->setChecked(true);
+        m_view.clip_vindex->setEnabled(true);
+        m_view.clip_vindex->setValue(commonproperties.value("video_index").toInt());
+    }
+
+    if (commonproperties.contains("audio_index") && !commonproperties.value("audio_index").isEmpty() && commonproperties.value("audio_index").toInt() != 0) {
+        m_view.clip_force_aindex->setChecked(true);
+        m_view.clip_aindex->setEnabled(true);
+        m_view.clip_aindex->setValue(commonproperties.value("audio_index").toInt());
+    }
+
+    if (props.contains("audio_max")) {
+        m_view.clip_aindex->setMaximum(props.value("audio_max").toInt());
+    }
+
+    if (props.contains("video_max")) {
+        m_view.clip_vindex->setMaximum(props.value("video_max").toInt());
+    }
+
+    connect(m_view.clip_force_ar, SIGNAL(toggled(bool)), m_view.clip_ar, 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)));
+
+    m_view.tabWidget->removeTab(METATAB);
+    m_view.tabWidget->removeTab(MARKERTAB);
+    m_view.tabWidget->removeTab(IMAGETAB);
+    m_view.tabWidget->removeTab(SLIDETAB);
+    m_view.tabWidget->removeTab(COLORTAB);
+    m_view.tabWidget->removeTab(AUDIOTAB);
+    m_view.tabWidget->removeTab(VIDEOTAB);
+
+    m_view.clip_path->setHidden(true);
+    m_view.label_path->setHidden(true);
+    m_view.label_description->setHidden(true);
+    m_view.label_duration->setHidden(true);
+    m_view.label_size->setHidden(true);
+    m_view.clip_filesize->setHidden(true);
+    m_view.clip_filesize->setHidden(true);
+    m_view.clip_duration->setHidden(true);
+    m_view.clip_path->setHidden(true);
+    m_view.clip_description->setHidden(true);
+}
+
+
+
 void ClipProperties::slotEnableLuma(int state)
 {
     bool enable = false;
@@ -345,62 +426,68 @@ const QString &ClipProperties::clipId() const
 QMap <QString, QString> ClipProperties::properties()
 {
     QMap <QString, QString> props;
-    CLIPTYPE t = m_clip->clipType();
-    QMap <QString, QString> old_props = m_clip->properties();
-
-    if (old_props.value("description") != m_view.clip_description->text())
-        props["description"] = m_view.clip_description->text();
+    CLIPTYPE t;
+    if (m_clip != NULL) {
+        t = m_clip->clipType();
+        m_old_props = m_clip->properties();
+    }
 
     double aspect = m_view.clip_ar->value();
     if (m_view.clip_force_ar->isChecked()) {
-        if (aspect != old_props.value("force_aspect_ratio").toDouble()) {
+        if (aspect != m_old_props.value("force_aspect_ratio").toDouble()) {
             props["force_aspect_ratio"] = QString::number(aspect);
             m_clipNeedsRefresh = true;
         }
-    } else if (old_props.contains("force_aspect_ratio")) {
+    } else if (m_old_props.contains("force_aspect_ratio")) {
         props["force_aspect_ratio"].clear();
         m_clipNeedsRefresh = true;
     }
 
     int progressive = m_view.clip_progressive->value();
     if (m_view.clip_force_progressive->isChecked()) {
-        if (progressive != old_props.value("force_progressive").toInt()) {
+        if (progressive != m_old_props.value("force_progressive").toInt()) {
             props["force_progressive"] = QString::number(progressive);
         }
-    } else if (old_props.contains("force_progressive")) {
+    } else if (m_old_props.contains("force_progressive")) {
         props["force_progressive"].clear();
     }
 
     int threads = m_view.clip_threads->value();
     if (m_view.clip_force_threads->isChecked()) {
-        if (threads != old_props.value("threads").toInt()) {
+        if (threads != m_old_props.value("threads").toInt()) {
             props["threads"] = QString::number(threads);
         }
-    } else if (old_props.contains("threads")) {
+    } else if (m_old_props.contains("threads")) {
         props["threads"].clear();
     }
 
     int vindex = m_view.clip_vindex->value();
     if (m_view.clip_force_vindex->isChecked()) {
-        if (vindex != old_props.value("video_index").toInt()) {
+        if (vindex != m_old_props.value("video_index").toInt()) {
             props["video_index"] = QString::number(vindex);
         }
-    } else if (old_props.contains("video_index")) {
+    } else if (m_old_props.contains("video_index")) {
         props["video_index"].clear();
     }
 
     int aindex = m_view.clip_aindex->value();
     if (m_view.clip_force_aindex->isChecked()) {
-        if (aindex != old_props.value("audio_index").toInt()) {
+        if (aindex != m_old_props.value("audio_index").toInt()) {
             props["audio_index"] = QString::number(aindex);
         }
-    } else if (old_props.contains("audio_index")) {
+    } else if (m_old_props.contains("audio_index")) {
         props["audio_index"].clear();
     }
 
+    // If we adjust several clips, return now
+    if (m_clip == NULL) return props;
+
+    if (m_old_props.value("description") != m_view.clip_description->text())
+        props["description"] = m_view.clip_description->text();
+
     if (t == COLOR) {
         QString new_color = m_view.clip_color->color().name();
-        if (new_color != QString('#' + old_props.value("colour").right(8).left(6))) {
+        if (new_color != QString('#' + m_old_props.value("colour").right(8).left(6))) {
             m_clipNeedsRefresh = true;
             props["colour"] = "0x" + new_color.right(6) + "ff";
         }
@@ -409,7 +496,7 @@ QMap <QString, QString> ClipProperties::properties()
             props["out"] = QString::number(duration);
         }
     } else if (t == IMAGE) {
-        if ((int) m_view.image_transparency->isChecked() != old_props.value("transparency").toInt()) {
+        if ((int) m_view.image_transparency->isChecked() != m_old_props.value("transparency").toInt()) {
             props["transparency"] = QString::number((int)m_view.image_transparency->isChecked());
             //m_clipNeedsRefresh = true;
         }
@@ -419,30 +506,30 @@ QMap <QString, QString> ClipProperties::properties()
         }
     } else if (t == SLIDESHOW) {
         QString value = QString::number((int) m_view.slide_loop->isChecked());
-        if (old_props.value("loop") != value) props["loop"] = value;
+        if (m_old_props.value("loop") != value) props["loop"] = value;
         value = QString::number((int) m_view.slide_fade->isChecked());
-        if (old_props.value("fade") != value) props["fade"] = value;
+        if (m_old_props.value("fade") != value) props["fade"] = value;
         value = QString::number((int) m_view.luma_softness->value());
-        if (old_props.value("softness") != value) props["softness"] = value;
+        if (m_old_props.value("softness") != value) props["softness"] = value;
 
         QString extension = "/.all." + m_view.image_type->itemData(m_view.image_type->currentIndex()).toString();
         QString new_path = m_view.clip_path->text() + extension;
-        if (new_path != old_props.value("resource")) {
+        if (new_path != m_old_props.value("resource")) {
             m_clipNeedsReLoad = true;
             props["resource"] = new_path;
-            kDebug() << "////  SLIDE EDIT, NEW:" << new_path << ", OLD; " << old_props.value("resource");
+            kDebug() << "////  SLIDE EDIT, NEW:" << new_path << ", OLD; " << m_old_props.value("resource");
         }
         int duration;
         if (m_view.slide_duration_format->currentIndex() == 1) {
             // we are in frames mode
             duration = m_view.slide_duration_frames->value();
         } else duration = m_tc.getFrameCount(m_view.slide_duration->text());
-        if (duration != old_props.value("ttl").toInt()) {
+        if (duration != m_old_props.value("ttl").toInt()) {
             m_clipNeedsRefresh = true;
             props["ttl"] = QString::number(duration);
             props["out"] = QString::number(duration * m_count);
         }
-        if (duration * m_count != old_props.value("out").toInt()) {
+        if (duration * m_count != m_old_props.value("out").toInt()) {
             m_clipNeedsRefresh = true;
             props["out"] = QString::number(duration * m_count);
         }
@@ -452,19 +539,19 @@ QMap <QString, QString> ClipProperties::properties()
                 // we are in frames mode
                 luma_duration = m_view.luma_duration_frames->value();
             } else luma_duration = m_tc.getFrameCount(m_view.luma_duration->text());
-            if (luma_duration != old_props.value("luma_duration").toInt()) {
+            if (luma_duration != m_old_props.value("luma_duration").toInt()) {
                 m_clipNeedsRefresh = true;
                 props["luma_duration"] = QString::number(luma_duration);
             }
             QString lumaFile;
             if (m_view.slide_luma->isChecked())
                 lumaFile = m_view.luma_file->itemData(m_view.luma_file->currentIndex()).toString();
-            if (lumaFile != old_props.value("luma_file")) {
+            if (lumaFile != m_old_props.value("luma_file")) {
                 m_clipNeedsRefresh = true;
                 props["luma_file"] = lumaFile;
             }
         } else {
-            if (!old_props.value("luma_file").isEmpty()) {
+            if (!m_old_props.value("luma_file").isEmpty()) {
                 props["luma_file"].clear();
             }
         }
index b32517e4506443b4f0d6ce2513452611b28a8c8f..33975a0056ed0a3841b20f495eef0b8d28e71b28 100644 (file)
@@ -33,6 +33,7 @@ class ClipProperties : public QDialog
 
 public:
     ClipProperties(DocClipBase *clip, Timecode tc, double fps, QWidget * parent = 0);
+    ClipProperties(QList <DocClipBase *>cliplist, QMap <QString, QString> commonproperties, QWidget * parent);
     QMap <QString, QString> properties();
     const QString &clipId() const;
     bool needsTimelineRefresh() const;
@@ -51,6 +52,7 @@ private slots:
 
 private:
     Ui::ClipProperties_UI m_view;
+    QMap <QString, QString> m_old_props;
     DocClipBase *m_clip;
     Timecode m_tc;
     double m_fps;
index c1d4b07415f731c502ab481006e6e8b8f6b3caa6..48eb268763003d22d3d175d5ea8b30e9a2dacaf2 100644 (file)
@@ -2305,8 +2305,8 @@ void CustomTrackView::addTrack(TrackInfo type, int ix)
             ItemInfo clipinfo = item->info();
             if (item->type() == AVWIDGET) {
                 ClipItem *clip = static_cast <ClipItem *>(item);
-               // slowmotion clips are not track dependant, so no need to update them
-               if (clip->speed() != 1.0) continue;
+                // slowmotion clips are not track dependant, so no need to update them
+                if (clip->speed() != 1.0) continue;
                 // We add a move clip command so that we get the correct producer for new track number
                 if (clip->clipType() == AV || clip->clipType() == AUDIO) {
                     Mlt::Producer *prod;
index 4a95de14abb492b1f8c532b88713dc00c0210207..f52755cbe105dd465204307d03a4e8b79ddf13a9 100644 (file)
@@ -692,6 +692,7 @@ 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(showClipProperties(DocClipBase *)), this, SLOT(slotShowClipProperties(DocClipBase *)));
+    connect(m_projectList, SIGNAL(showClipProperties(QList <DocClipBase *>, QMap<QString, QString>)), this, SLOT(slotShowClipProperties(QList <DocClipBase *>, QMap<QString, QString>)));
     connect(m_projectList, SIGNAL(getFileProperties(const QDomElement, const QString &, int, bool)), m_projectMonitor->render, SLOT(getFileProperties(const QDomElement, const QString &, int, 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)));
@@ -2589,6 +2590,24 @@ void MainWindow::slotShowClipProperties(DocClipBase *clip)
     }
 }
 
+
+void MainWindow::slotShowClipProperties(QList <DocClipBase *> cliplist, QMap<QString, QString> commonproperties)
+{
+    ClipProperties dia(cliplist, commonproperties, this);
+    if (dia.exec() == QDialog::Accepted) {
+        QUndoCommand *command = new QUndoCommand();
+        command->setText(i18n("Edit clips"));
+        for (int i = 0; i < cliplist.count(); i++) {
+            DocClipBase *clip = cliplist.at(i);
+            new EditClipCommand(m_projectList, clip->getId(), clip->properties(), dia.properties(), true, command);
+        }
+        m_activeDocument->commandStack()->push(command);
+        for (int i = 0; i < cliplist.count(); i++) {
+            m_activeTimeline->projectView()->slotUpdateClip(cliplist.at(i)->getId(), dia.needsTimelineReload());
+        }
+    }
+}
+
 void MainWindow::customEvent(QEvent* e)
 {
     if (e->type() == QEvent::User) {
index c439c2e4f7afa59e18b20a88e8c9d93f7db05405..7c8deb4723f787768f070862d954dba00f369ab8 100644 (file)
@@ -266,6 +266,7 @@ private slots:
     void slotShuttleButton(int code);
 #endif /* NO_JOGSHUTTLE */
     void slotShowClipProperties(DocClipBase *clip);
+    void slotShowClipProperties(QList <DocClipBase *>cliplist, QMap<QString, QString> commonproperties);
     void slotActivateEffectStackView();
     void slotActivateTransitionView(Transition *);
     void slotChangeTool(QAction * action);
index 51ccf0245911eb48f08c9069b4783d70e9d5f51e..99d6dcad02de27f6419ea3c39ca35eaeff58e687 100644 (file)
@@ -204,6 +204,11 @@ void ProjectList::setHeaderInfo(const QByteArray &state)
 
 void ProjectList::slotEditClip()
 {
+    QList<QTreeWidgetItem *> list = m_listView->selectedItems();
+    if (list.count() > 1) {
+        editClipSelection(list);
+        return;
+    }
     ProjectItem *item;
     if (!m_listView->currentItem() || m_listView->currentItem()->type() == PROJECTFOLDERTYPE) return;
     if (m_listView->currentItem()->type() == PROJECTSUBCLIPTYPE) {
@@ -216,6 +221,50 @@ void ProjectList::slotEditClip()
     }
 }
 
+void ProjectList::editClipSelection(QList<QTreeWidgetItem *> list)
+{
+    // Gather all common properties
+    QMap <QString, QString> commonproperties;
+    QList <DocClipBase *> clipList;
+    commonproperties.insert("force_aspect_ratio", "-");
+    commonproperties.insert("force_progressive", "-");
+    commonproperties.insert("threads", "-");
+    commonproperties.insert("video_index", "-");
+    commonproperties.insert("audio_index", "-");
+
+    ProjectItem *item;
+    for (int i = 0; i < list.count(); i++) {
+        item = NULL;
+        if (list.at(i)->type() == PROJECTFOLDERTYPE) continue;
+        if (list.at(i)->type() == PROJECTSUBCLIPTYPE) {
+            item = static_cast <ProjectItem*>(list.at(i)->parent());
+        } else item = static_cast <ProjectItem*>(list.at(i));
+        if (!(item->flags() & Qt::ItemIsDragEnabled)) continue;
+        if (item) {
+            // check properties
+            DocClipBase *clip = item->referencedClip();
+            if (clipList.contains(clip)) continue;
+            clipList.append(clip);
+            QMap <QString, QString> clipprops = clip->properties();
+            QMapIterator<QString, QString> p(commonproperties);
+            while (p.hasNext()) {
+                p.next();
+                if (p.value().isEmpty()) continue;
+                if (clipprops.contains(p.key())) {
+                    if (p.value() == "-") commonproperties.insert(p.key(), clipprops.value(p.key()));
+                    else if (p.value() != clipprops.value(p.key())) commonproperties.insert(p.key(), QString());
+                } else commonproperties.insert(p.key(), QString());
+            }
+        }
+    }
+    QMapIterator<QString, QString> p(commonproperties);
+    while (p.hasNext()) {
+        p.next();
+        kDebug() << "Result: " << p.key() << " = " << p.value();
+    }
+    emit showClipProperties(clipList, commonproperties);
+}
+
 void ProjectList::slotOpenClip()
 {
     ProjectItem *item;
index aa03597d46e64ce91fca462f72b723fed5c5a241..4747c377892fa6234c323ddabfad5e6d604bcc9e 100644 (file)
@@ -202,6 +202,7 @@ private:
     void editFolder(const QString folderName, const QString oldfolderName, const QString &clipId);
     QStringList getGroup() const;
     void regenerateTemplate(ProjectItem *clip);
+    void editClipSelection(QList<QTreeWidgetItem *> list);
 
 private slots:
     void slotClipSelected();
@@ -224,6 +225,7 @@ signals:
     void getFileProperties(const QDomElement, const QString &, int pixHeight, bool);
     void receivedClipDuration(const QString &);
     void showClipProperties(DocClipBase *);
+    void showClipProperties(QList <DocClipBase *>, QMap<QString, QString> commonproperties);
     void projectModified();
     void loadingIsOver();
     void displayMessage(const QString, int progress);
index a8367473772702660b6ce5a8afd071eee6943aab..dc82651a960730e5f4cf5164870bb435c8921f92 100644 (file)
@@ -28,7 +28,7 @@
     </spacer>
    </item>
    <item row="1" column="0" colspan="4">
-    <widget class="QLabel" name="label_5">
+    <widget class="QLabel" name="label_path">
      <property name="text">
       <string>Path</string>
      </property>
@@ -42,7 +42,7 @@
     </widget>
    </item>
    <item row="3" column="0" colspan="4">
-    <widget class="QLabel" name="label_3">
+    <widget class="QLabel" name="label_description">
      <property name="text">
       <string>Description</string>
      </property>
@@ -52,7 +52,7 @@
     <widget class="KLineEdit" name="clip_description"/>
    </item>
    <item row="5" column="0">
-    <widget class="QLabel" name="clip_filesize_2">
+    <widget class="QLabel" name="label_duration">
      <property name="text">
       <string>Duration</string>
      </property>
@@ -66,7 +66,7 @@
     </widget>
    </item>
    <item row="5" column="2">
-    <widget class="QLabel" name="clip_filesize_3">
+    <widget class="QLabel" name="label_size">
      <property name="text">
       <string>Size:</string>
      </property>
    <item row="6" column="0" colspan="4">
     <widget class="QTabWidget" name="tabWidget">
      <property name="currentIndex">
-      <number>0</number>
+      <number>1</number>
      </property>
      <widget class="QWidget" name="tab_video">
       <attribute name="title">
          </property>
         </widget>
        </item>
-       <item row="3" column="2">
-        <spacer name="verticalSpacer_3">
-         <property name="orientation">
-          <enum>Qt::Vertical</enum>
-         </property>
-         <property name="sizeHint" stdset="0">
-          <size>
-           <width>77</width>
-           <height>52</height>
-          </size>
-         </property>
-        </spacer>
-       </item>
        <item row="1" column="1" colspan="2">
         <widget class="KLineEdit" name="clip_channels">
          <property name="readOnly">
          </property>
         </widget>
        </item>
+       <item row="3" column="1">
+        <spacer name="verticalSpacer_8">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
       </layout>
-      <zorder>clip_acodec</zorder>
-      <zorder>clip_frequency</zorder>
-      <zorder>verticalSpacer_3</zorder>
-      <zorder>clip_channels</zorder>
-      <zorder>label_9</zorder>
-      <zorder>label_11</zorder>
-      <zorder>label_10</zorder>
      </widget>
      <widget class="QWidget" name="tab">
       <attribute name="title">