]> git.sesse.net Git - kdenlive/blob - src/clipproperties.cpp
* Allow transcoding of several clips (selected in project tree):
[kdenlive] / src / clipproperties.cpp
1 /***************************************************************************
2  *   Copyright (C) 2008 by Jean-Baptiste Mardelle (jb@kdenlive.org)        *
3  *                                                                         *
4  *   This program is free software; you can redistribute it and/or modify  *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program; if not, write to the                         *
16  *   Free Software Foundation, Inc.,                                       *
17  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
18  ***************************************************************************/
19
20
21 #include "clipproperties.h"
22 #include "kdenlivesettings.h"
23 #include "kthumb.h"
24 #include "markerdialog.h"
25
26 #include <KStandardDirs>
27 #include <KDebug>
28 #include <KFileItem>
29
30 #include <QDir>
31
32 static const int VIDEOTAB = 0;
33 static const int AUDIOTAB = 1;
34 static const int COLORTAB = 2;
35 static const int SLIDETAB = 3;
36 static const int IMAGETAB = 4;
37 static const int MARKERTAB = 5;
38 static const int METATAB = 6;
39 static const int ADVANCEDTAB = 7;
40
41 ClipProperties::ClipProperties(DocClipBase *clip, Timecode tc, double fps, QWidget * parent) :
42         QDialog(parent),
43         m_clip(clip),
44         m_tc(tc),
45         m_fps(fps),
46         m_count(0),
47         m_clipNeedsRefresh(false),
48         m_clipNeedsReLoad(false)
49 {
50     setFont(KGlobalSettings::toolBarFont());
51     m_view.setupUi(this);
52     KUrl url = m_clip->fileURL();
53     m_view.clip_path->setText(url.path());
54     m_view.clip_description->setText(m_clip->description());
55     QMap <QString, QString> props = m_clip->properties();
56
57     if (props.contains("force_aspect_ratio") && props.value("force_aspect_ratio").toDouble() > 0) {
58         m_view.clip_force_ar->setChecked(true);
59         m_view.clip_ar->setEnabled(true);
60         m_view.clip_ar->setValue(props.value("force_aspect_ratio").toDouble());
61     }
62
63     if (props.contains("force_fps") && props.value("force_fps").toDouble() > 0) {
64         m_view.clip_force_framerate->setChecked(true);
65         m_view.clip_framerate->setEnabled(true);
66         m_view.clip_framerate->setValue(props.value("force_fps").toDouble());
67     }
68
69     if (props.contains("force_progressive")) {
70         m_view.clip_force_progressive->setChecked(true);
71         m_view.clip_progressive->setEnabled(true);
72         m_view.clip_progressive->setValue(props.value("force_progressive").toInt());
73     }
74
75     if (props.contains("threads") && props.value("threads").toInt() != 1) {
76         m_view.clip_force_threads->setChecked(true);
77         m_view.clip_threads->setEnabled(true);
78         m_view.clip_threads->setValue(props.value("threads").toInt());
79     }
80
81     if (props.contains("video_index") && props.value("video_index").toInt() != 0) {
82         m_view.clip_force_vindex->setChecked(true);
83         m_view.clip_vindex->setEnabled(true);
84         m_view.clip_vindex->setValue(props.value("video_index").toInt());
85     }
86
87     if (props.contains("audio_index") && props.value("audio_index").toInt() != 0) {
88         m_view.clip_force_aindex->setChecked(true);
89         m_view.clip_aindex->setEnabled(true);
90         m_view.clip_aindex->setValue(props.value("audio_index").toInt());
91     }
92
93     if (props.contains("audio_max")) {
94         m_view.clip_aindex->setMaximum(props.value("audio_max").toInt());
95     }
96
97     if (props.contains("video_max")) {
98         m_view.clip_vindex->setMaximum(props.value("video_max").toInt());
99     }
100
101     // Check for Metadata
102     QMap<QString, QString> meta = m_clip->metadata();
103     QMap<QString, QString>::const_iterator i = meta.constBegin();
104     while (i != meta.constEnd()) {
105         QTreeWidgetItem *metaitem = new QTreeWidgetItem(m_view.metadata_list);
106         metaitem->setText(0, i.key()); //i18n(i.key().section('.', 2, 3).toUtf8().data()));
107         metaitem->setText(1, i.value());
108         ++i;
109     }
110
111     connect(m_view.clip_force_ar, SIGNAL(toggled(bool)), m_view.clip_ar, SLOT(setEnabled(bool)));
112     connect(m_view.clip_force_framerate, SIGNAL(toggled(bool)), m_view.clip_framerate, SLOT(setEnabled(bool)));
113     connect(m_view.clip_force_progressive, SIGNAL(toggled(bool)), m_view.clip_progressive, SLOT(setEnabled(bool)));
114     connect(m_view.clip_force_threads, SIGNAL(toggled(bool)), m_view.clip_threads, SLOT(setEnabled(bool)));
115     connect(m_view.clip_force_vindex, SIGNAL(toggled(bool)), m_view.clip_vindex, SLOT(setEnabled(bool)));
116     connect(m_view.clip_force_aindex, SIGNAL(toggled(bool)), m_view.clip_aindex, SLOT(setEnabled(bool)));
117
118     if (props.contains("audiocodec"))
119         m_view.clip_acodec->setText(props.value("audiocodec"));
120     if (props.contains("frequency"))
121         m_view.clip_frequency->setText(props.value("frequency"));
122     if (props.contains("channels"))
123         m_view.clip_channels->setText(props.value("channels"));
124
125     CLIPTYPE t = m_clip->clipType();
126     if (t != AUDIO && t != AV) {
127         m_view.clip_force_aindex->setEnabled(false);
128     }
129
130     if (t != VIDEO && t != AV) {
131         m_view.clip_force_vindex->setEnabled(false);
132     }
133
134     if (t == IMAGE) {
135         m_view.tabWidget->removeTab(SLIDETAB);
136         m_view.tabWidget->removeTab(COLORTAB);
137         m_view.tabWidget->removeTab(AUDIOTAB);
138         m_view.tabWidget->removeTab(VIDEOTAB);
139         if (props.contains("frame_size"))
140             m_view.image_size->setText(props.value("frame_size"));
141         if (props.contains("transparency"))
142             m_view.image_transparency->setChecked(props.value("transparency").toInt());
143         int width = 180.0 * KdenliveSettings::project_display_ratio();
144         if (width % 2 == 1) width++;
145         m_view.clip_thumb->setPixmap(QPixmap(url.path()).scaled(QSize(width, 180), Qt::KeepAspectRatio));
146     } else if (t == COLOR) {
147         m_view.clip_path->setEnabled(false);
148         m_view.tabWidget->removeTab(METATAB);
149         m_view.tabWidget->removeTab(IMAGETAB);
150         m_view.tabWidget->removeTab(SLIDETAB);
151         m_view.tabWidget->removeTab(AUDIOTAB);
152         m_view.tabWidget->removeTab(VIDEOTAB);
153         m_view.clip_thumb->setHidden(true);
154         m_view.clip_color->setColor(QColor('#' + props.value("colour").right(8).left(6)));
155     } else if (t == SLIDESHOW) {
156         m_view.clip_path->setText(url.directory());
157         m_view.tabWidget->removeTab(METATAB);
158         m_view.tabWidget->removeTab(IMAGETAB);
159         m_view.tabWidget->removeTab(COLORTAB);
160         m_view.tabWidget->removeTab(AUDIOTAB);
161         m_view.tabWidget->removeTab(VIDEOTAB);
162
163         //WARNING: Keep in sync with slideshowclip.cpp
164         m_view.image_type->addItem("JPG (*.jpg)", "jpg");
165         m_view.image_type->addItem("JPEG (*.jpeg)", "jpeg");
166         m_view.image_type->addItem("PNG (*.png)", "png");
167         m_view.image_type->addItem("BMP (*.bmp)", "bmp");
168         m_view.image_type->addItem("GIF (*.gif)", "gif");
169         m_view.image_type->addItem("TGA (*.tga)", "tga");
170         m_view.image_type->addItem("TIFF (*.tiff)", "tiff");
171         m_view.image_type->addItem("Open EXR (*.exr)", "exr");
172
173         m_view.slide_loop->setChecked(props.value("loop").toInt());
174         m_view.slide_fade->setChecked(props.value("fade").toInt());
175         m_view.luma_softness->setValue(props.value("softness").toInt());
176         QString path = props.value("resource");
177         QString ext = path.section('.', -1);
178         for (int i = 0; i < m_view.image_type->count(); i++) {
179             if (m_view.image_type->itemData(i).toString() == ext) {
180                 m_view.image_type->setCurrentIndex(i);
181                 break;
182             }
183         }
184         m_view.slide_duration->setText(tc.getTimecodeFromFrames(props.value("ttl").toInt()));
185
186         m_view.slide_duration_format->addItem(i18n("hh:mm:ss::ff"));
187         m_view.slide_duration_format->addItem(i18n("Frames"));
188         connect(m_view.slide_duration_format, SIGNAL(activated(int)), this, SLOT(slotUpdateDurationFormat(int)));
189         m_view.slide_duration_frames->setHidden(true);
190         m_view.luma_duration_frames->setHidden(true);
191
192         parseFolder();
193
194         m_view.luma_duration->setText(tc.getTimecodeFromFrames(props.value("luma_duration").toInt()));
195         QString lumaFile = props.value("luma_file");
196
197         // Check for Kdenlive installed luma files
198         QStringList filters;
199         filters << "*.pgm" << "*.png";
200
201         QStringList customLumas = KGlobal::dirs()->findDirs("appdata", "lumas");
202         foreach(const QString &folder, customLumas) {
203             QStringList filesnames = QDir(folder).entryList(filters, QDir::Files);
204             foreach(const QString &fname, filesnames) {
205                 QString filePath = KUrl(folder).path(KUrl::AddTrailingSlash) + fname;
206                 m_view.luma_file->addItem(KIcon(filePath), fname, filePath);
207             }
208         }
209
210         // Check for MLT lumas
211         QString profilePath = KdenliveSettings::mltpath();
212         QString folder = profilePath.section('/', 0, -3);
213         folder.append("/lumas/PAL"); // TODO: cleanup the PAL / NTSC mess in luma files
214         QDir lumafolder(folder);
215         QStringList filesnames = lumafolder.entryList(filters, QDir::Files);
216         foreach(const QString &fname, filesnames) {
217             QString filePath = KUrl(folder).path(KUrl::AddTrailingSlash) + fname;
218             m_view.luma_file->addItem(KIcon(filePath), fname, filePath);
219         }
220
221         if (!lumaFile.isEmpty()) {
222             m_view.slide_luma->setChecked(true);
223             m_view.luma_file->setCurrentIndex(m_view.luma_file->findData(lumaFile));
224         } else m_view.luma_file->setEnabled(false);
225         slotEnableLuma(m_view.slide_fade->checkState());
226         slotEnableLumaFile(m_view.slide_luma->checkState());
227         connect(m_view.slide_fade, SIGNAL(stateChanged(int)), this, SLOT(slotEnableLuma(int)));
228         connect(m_view.slide_luma, SIGNAL(stateChanged(int)), this, SLOT(slotEnableLumaFile(int)));
229
230         connect(m_view.image_type, SIGNAL(currentIndexChanged(int)), this, SLOT(parseFolder()));
231     } else if (t != AUDIO) {
232         m_view.tabWidget->removeTab(IMAGETAB);
233         m_view.tabWidget->removeTab(SLIDETAB);
234         m_view.tabWidget->removeTab(COLORTAB);
235         if (props.contains("frame_size"))
236             m_view.clip_size->setText(props.value("frame_size"));
237         if (props.contains("videocodec"))
238             m_view.clip_vcodec->setText(props.value("videocodec"));
239         if (props.contains("fps")) {
240             m_view.clip_fps->setText(props.value("fps"));
241             if (!m_view.clip_framerate->isEnabled()) m_view.clip_framerate->setValue(props.value("fps").toDouble());
242         }
243         if (props.contains("aspect_ratio"))
244             m_view.clip_ratio->setText(props.value("aspect_ratio"));
245         int width = 180.0 * KdenliveSettings::project_display_ratio();
246         if (width % 2 == 1) width++;
247         QPixmap pix = m_clip->thumbProducer()->getImage(url, m_clip->getClipThumbFrame(), width, 180);
248         m_view.clip_thumb->setPixmap(pix);
249         if (t == IMAGE || t == VIDEO) m_view.tabWidget->removeTab(AUDIOTAB);
250     } else {
251         m_view.tabWidget->removeTab(IMAGETAB);
252         m_view.tabWidget->removeTab(SLIDETAB);
253         m_view.tabWidget->removeTab(COLORTAB);
254         m_view.tabWidget->removeTab(VIDEOTAB);
255         m_view.clip_thumb->setHidden(true);
256     }
257
258     if (t != SLIDESHOW && t != COLOR) {
259         KFileItem f(KFileItem::Unknown, KFileItem::Unknown, url, true);
260         m_view.clip_filesize->setText(KIO::convertSize(f.size()));
261     } else {
262         m_view.clip_filesize->setHidden(true);
263         m_view.label_size->setHidden(true);
264     }
265     m_view.clip_duration->setText(tc.getTimecode(m_clip->duration()));
266     if (t != IMAGE && t != COLOR && t != TEXT) m_view.clip_duration->setReadOnly(true);
267     else connect(m_view.clip_duration, SIGNAL(editingFinished()), this, SLOT(slotCheckMaxLength()));
268
269     // markers
270     m_view.marker_new->setIcon(KIcon("document-new"));
271     m_view.marker_new->setToolTip(i18n("Add marker"));
272     m_view.marker_edit->setIcon(KIcon("document-properties"));
273     m_view.marker_edit->setToolTip(i18n("Edit marker"));
274     m_view.marker_delete->setIcon(KIcon("trash-empty"));
275     m_view.marker_delete->setToolTip(i18n("Delete marker"));
276
277     slotFillMarkersList();
278     connect(m_view.marker_new, SIGNAL(clicked()), this, SLOT(slotAddMarker()));
279     connect(m_view.marker_edit, SIGNAL(clicked()), this, SLOT(slotEditMarker()));
280     connect(m_view.marker_delete, SIGNAL(clicked()), this, SLOT(slotDeleteMarker()));
281     connect(m_view.markers_list, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(slotEditMarker()));
282
283     //adjustSize();
284 }
285
286
287 // Used for multiple clips editing
288 ClipProperties::ClipProperties(QList <DocClipBase *>cliplist, QMap <QString, QString> commonproperties, QWidget * parent) :
289         QDialog(parent),
290         m_clip(NULL),
291         m_fps(0),
292         m_count(0),
293         m_clipNeedsRefresh(false),
294         m_clipNeedsReLoad(false)
295 {
296     setFont(KGlobalSettings::toolBarFont());
297     m_view.setupUi(this);
298     QMap <QString, QString> props = cliplist.at(0)->properties();
299     m_old_props = commonproperties;
300
301     if (commonproperties.contains("force_aspect_ratio") && !commonproperties.value("force_aspect_ratio").isEmpty() && commonproperties.value("force_aspect_ratio").toDouble() > 0) {
302         m_view.clip_force_ar->setChecked(true);
303         m_view.clip_ar->setEnabled(true);
304         m_view.clip_ar->setValue(commonproperties.value("force_aspect_ratio").toDouble());
305     }
306
307     if (commonproperties.contains("force_fps") && !commonproperties.value("force_fps").isEmpty() && commonproperties.value("force_fps").toDouble() > 0) {
308         m_view.clip_force_framerate->setChecked(true);
309         m_view.clip_framerate->setEnabled(true);
310         m_view.clip_framerate->setValue(commonproperties.value("force_fps").toDouble());
311     }
312
313     if (commonproperties.contains("force_progressive") && !commonproperties.value("force_progressive").isEmpty()) {
314         m_view.clip_force_progressive->setChecked(true);
315         m_view.clip_progressive->setEnabled(true);
316         m_view.clip_progressive->setValue(commonproperties.value("force_progressive").toInt());
317     }
318
319     if (commonproperties.contains("threads") && !commonproperties.value("threads").isEmpty() && commonproperties.value("threads").toInt() != 1) {
320         m_view.clip_force_threads->setChecked(true);
321         m_view.clip_threads->setEnabled(true);
322         m_view.clip_threads->setValue(commonproperties.value("threads").toInt());
323     }
324
325     if (commonproperties.contains("video_index") && !commonproperties.value("video_index").isEmpty() && commonproperties.value("video_index").toInt() != 0) {
326         m_view.clip_force_vindex->setChecked(true);
327         m_view.clip_vindex->setEnabled(true);
328         m_view.clip_vindex->setValue(commonproperties.value("video_index").toInt());
329     }
330
331     if (commonproperties.contains("audio_index") && !commonproperties.value("audio_index").isEmpty() && commonproperties.value("audio_index").toInt() != 0) {
332         m_view.clip_force_aindex->setChecked(true);
333         m_view.clip_aindex->setEnabled(true);
334         m_view.clip_aindex->setValue(commonproperties.value("audio_index").toInt());
335     }
336
337     if (props.contains("audio_max")) {
338         m_view.clip_aindex->setMaximum(props.value("audio_max").toInt());
339     }
340
341     if (props.contains("video_max")) {
342         m_view.clip_vindex->setMaximum(props.value("video_max").toInt());
343     }
344
345     connect(m_view.clip_force_ar, SIGNAL(toggled(bool)), m_view.clip_ar, SLOT(setEnabled(bool)));
346     connect(m_view.clip_force_progressive, SIGNAL(toggled(bool)), m_view.clip_progressive, SLOT(setEnabled(bool)));
347     connect(m_view.clip_force_threads, SIGNAL(toggled(bool)), m_view.clip_threads, SLOT(setEnabled(bool)));
348     connect(m_view.clip_force_vindex, SIGNAL(toggled(bool)), m_view.clip_vindex, SLOT(setEnabled(bool)));
349     connect(m_view.clip_force_aindex, SIGNAL(toggled(bool)), m_view.clip_aindex, SLOT(setEnabled(bool)));
350
351     m_view.tabWidget->removeTab(METATAB);
352     m_view.tabWidget->removeTab(MARKERTAB);
353     m_view.tabWidget->removeTab(IMAGETAB);
354     m_view.tabWidget->removeTab(SLIDETAB);
355     m_view.tabWidget->removeTab(COLORTAB);
356     m_view.tabWidget->removeTab(AUDIOTAB);
357     m_view.tabWidget->removeTab(VIDEOTAB);
358
359     m_view.clip_path->setHidden(true);
360     m_view.label_path->setHidden(true);
361     m_view.label_description->setHidden(true);
362     m_view.label_duration->setHidden(true);
363     m_view.label_size->setHidden(true);
364     m_view.clip_filesize->setHidden(true);
365     m_view.clip_filesize->setHidden(true);
366     m_view.clip_duration->setHidden(true);
367     m_view.clip_path->setHidden(true);
368     m_view.clip_description->setHidden(true);
369 }
370
371
372
373 void ClipProperties::slotEnableLuma(int state)
374 {
375     bool enable = false;
376     if (state == Qt::Checked) enable = true;
377     m_view.luma_duration->setEnabled(enable);
378     m_view.luma_duration_frames->setEnabled(enable);
379     m_view.slide_luma->setEnabled(enable);
380     if (enable) {
381         m_view.luma_file->setEnabled(m_view.slide_luma->isChecked());
382     } else m_view.luma_file->setEnabled(false);
383     m_view.label_softness->setEnabled(m_view.slide_luma->isChecked() && enable);
384     m_view.luma_softness->setEnabled(m_view.label_softness->isEnabled());
385 }
386
387 void ClipProperties::slotEnableLumaFile(int state)
388 {
389     bool enable = false;
390     if (state == Qt::Checked) enable = true;
391     m_view.luma_file->setEnabled(enable);
392     m_view.luma_softness->setEnabled(enable);
393     m_view.label_softness->setEnabled(enable);
394 }
395
396 void ClipProperties::slotFillMarkersList()
397 {
398     m_view.markers_list->clear();
399     QList < CommentedTime > marks = m_clip->commentedSnapMarkers();
400     for (int count = 0; count < marks.count(); ++count) {
401         QString time = m_tc.getTimecode(marks[count].time());
402         QStringList itemtext;
403         itemtext << time << marks[count].comment();
404         (void) new QTreeWidgetItem(m_view.markers_list, itemtext);
405     }
406 }
407
408 void ClipProperties::slotAddMarker()
409 {
410     CommentedTime marker(GenTime(), i18n("Marker"));
411     MarkerDialog d(m_clip, marker, m_tc, i18n("Add Marker"), this);
412     if (d.exec() == QDialog::Accepted) {
413         emit addMarker(m_clip->getId(), d.newMarker().time(), d.newMarker().comment());
414     }
415     QTimer::singleShot(500, this, SLOT(slotFillMarkersList()));
416 }
417
418 void ClipProperties::slotEditMarker()
419 {
420     QList < CommentedTime > marks = m_clip->commentedSnapMarkers();
421     int pos = m_view.markers_list->currentIndex().row();
422     if (pos < 0 || pos > marks.count() - 1) return;
423     MarkerDialog d(m_clip, marks.at(pos), m_tc, i18n("Edit Marker"), this);
424     if (d.exec() == QDialog::Accepted) {
425         emit addMarker(m_clip->getId(), d.newMarker().time(), d.newMarker().comment());
426     }
427     QTimer::singleShot(500, this, SLOT(slotFillMarkersList()));
428 }
429
430 void ClipProperties::slotDeleteMarker()
431 {
432     QList < CommentedTime > marks = m_clip->commentedSnapMarkers();
433     int pos = m_view.markers_list->currentIndex().row();
434     if (pos < 0 || pos > marks.count() - 1) return;
435     emit addMarker(m_clip->getId(), marks.at(pos).time(), QString());
436
437     QTimer::singleShot(500, this, SLOT(slotFillMarkersList()));
438 }
439
440 const QString &ClipProperties::clipId() const
441 {
442     return m_clip->getId();
443 }
444
445
446 QMap <QString, QString> ClipProperties::properties()
447 {
448     QMap <QString, QString> props;
449     CLIPTYPE t;
450     if (m_clip != NULL) {
451         t = m_clip->clipType();
452         m_old_props = m_clip->properties();
453     }
454
455     double aspect = m_view.clip_ar->value();
456     if (m_view.clip_force_ar->isChecked()) {
457         if (aspect != m_old_props.value("force_aspect_ratio").toDouble()) {
458             props["force_aspect_ratio"] = QString::number(aspect);
459             m_clipNeedsRefresh = true;
460         }
461     } else if (m_old_props.contains("force_aspect_ratio")) {
462         props["force_aspect_ratio"].clear();
463         m_clipNeedsRefresh = true;
464     }
465
466     double fps = m_view.clip_framerate->value();
467     if (m_view.clip_force_framerate->isChecked()) {
468         if (fps != m_old_props.value("force_fps").toDouble()) {
469             props["force_fps"] = QString::number(fps);
470             m_clipNeedsRefresh = true;
471         }
472     } else if (m_old_props.contains("force_fps")) {
473         props["force_fps"].clear();
474         m_clipNeedsRefresh = true;
475     }
476
477     int progressive = m_view.clip_progressive->value();
478     if (m_view.clip_force_progressive->isChecked()) {
479         if (progressive != m_old_props.value("force_progressive").toInt()) {
480             props["force_progressive"] = QString::number(progressive);
481         }
482     } else if (m_old_props.contains("force_progressive")) {
483         props["force_progressive"].clear();
484     }
485
486     int threads = m_view.clip_threads->value();
487     if (m_view.clip_force_threads->isChecked()) {
488         if (threads != m_old_props.value("threads").toInt()) {
489             props["threads"] = QString::number(threads);
490         }
491     } else if (m_old_props.contains("threads")) {
492         props["threads"].clear();
493     }
494
495     int vindex = m_view.clip_vindex->value();
496     if (m_view.clip_force_vindex->isChecked()) {
497         if (vindex != m_old_props.value("video_index").toInt()) {
498             props["video_index"] = QString::number(vindex);
499         }
500     } else if (m_old_props.contains("video_index")) {
501         props["video_index"].clear();
502     }
503
504     int aindex = m_view.clip_aindex->value();
505     if (m_view.clip_force_aindex->isChecked()) {
506         if (aindex != m_old_props.value("audio_index").toInt()) {
507             props["audio_index"] = QString::number(aindex);
508         }
509     } else if (m_old_props.contains("audio_index")) {
510         props["audio_index"].clear();
511     }
512
513     // If we adjust several clips, return now
514     if (m_clip == NULL) return props;
515
516     if (m_old_props.value("description") != m_view.clip_description->text())
517         props["description"] = m_view.clip_description->text();
518
519     if (t == COLOR) {
520         QString new_color = m_view.clip_color->color().name();
521         if (new_color != QString('#' + m_old_props.value("colour").right(8).left(6))) {
522             m_clipNeedsRefresh = true;
523             props["colour"] = "0x" + new_color.right(6) + "ff";
524         }
525         int duration = m_tc.getFrameCount(m_view.clip_duration->text());
526         if (duration != m_clip->duration().frames(m_fps)) {
527             props["out"] = QString::number(duration);
528         }
529     } else if (t == IMAGE) {
530         if ((int) m_view.image_transparency->isChecked() != m_old_props.value("transparency").toInt()) {
531             props["transparency"] = QString::number((int)m_view.image_transparency->isChecked());
532             //m_clipNeedsRefresh = true;
533         }
534         int duration = m_tc.getFrameCount(m_view.clip_duration->text());
535         if (duration != m_clip->duration().frames(m_fps)) {
536             props["out"] = QString::number(duration);
537         }
538     } else if (t == SLIDESHOW) {
539         QString value = QString::number((int) m_view.slide_loop->isChecked());
540         if (m_old_props.value("loop") != value) props["loop"] = value;
541         value = QString::number((int) m_view.slide_fade->isChecked());
542         if (m_old_props.value("fade") != value) props["fade"] = value;
543         value = QString::number((int) m_view.luma_softness->value());
544         if (m_old_props.value("softness") != value) props["softness"] = value;
545
546         QString extension = "/.all." + m_view.image_type->itemData(m_view.image_type->currentIndex()).toString();
547         QString new_path = m_view.clip_path->text() + extension;
548         if (new_path != m_old_props.value("resource")) {
549             m_clipNeedsReLoad = true;
550             props["resource"] = new_path;
551             kDebug() << "////  SLIDE EDIT, NEW:" << new_path << ", OLD; " << m_old_props.value("resource");
552         }
553         int duration;
554         if (m_view.slide_duration_format->currentIndex() == 1) {
555             // we are in frames mode
556             duration = m_view.slide_duration_frames->value();
557         } else duration = m_tc.getFrameCount(m_view.slide_duration->text());
558         if (duration != m_old_props.value("ttl").toInt()) {
559             m_clipNeedsRefresh = true;
560             props["ttl"] = QString::number(duration);
561             props["out"] = QString::number(duration * m_count);
562         }
563         if (duration * m_count - 1 != m_old_props.value("out").toInt()) {
564             m_clipNeedsRefresh = true;
565             props["out"] = QString::number(duration * m_count - 1);
566         }
567         if (m_view.slide_fade->isChecked()) {
568             int luma_duration;
569             if (m_view.slide_duration_format->currentIndex() == 1) {
570                 // we are in frames mode
571                 luma_duration = m_view.luma_duration_frames->value();
572             } else luma_duration = m_tc.getFrameCount(m_view.luma_duration->text());
573             if (luma_duration != m_old_props.value("luma_duration").toInt()) {
574                 m_clipNeedsRefresh = true;
575                 props["luma_duration"] = QString::number(luma_duration);
576             }
577             QString lumaFile;
578             if (m_view.slide_luma->isChecked())
579                 lumaFile = m_view.luma_file->itemData(m_view.luma_file->currentIndex()).toString();
580             if (lumaFile != m_old_props.value("luma_file")) {
581                 m_clipNeedsRefresh = true;
582                 props["luma_file"] = lumaFile;
583             }
584         } else {
585             if (!m_old_props.value("luma_file").isEmpty()) {
586                 props["luma_file"].clear();
587             }
588         }
589
590     }
591     return props;
592 }
593
594 bool ClipProperties::needsTimelineRefresh() const
595 {
596     return m_clipNeedsRefresh;
597 }
598
599 bool ClipProperties::needsTimelineReload() const
600 {
601     return m_clipNeedsReLoad;
602 }
603
604 void ClipProperties::parseFolder()
605 {
606
607     QDir dir(m_view.clip_path->text());
608     QStringList filters;
609     filters << "*." + m_view.image_type->itemData(m_view.image_type->currentIndex()).toString();
610     QString extension = "/.all." + m_view.image_type->itemData(m_view.image_type->currentIndex()).toString();
611
612     dir.setNameFilters(filters);
613     QStringList result = dir.entryList(QDir::Files);
614     m_count = result.count();
615     if (m_count == 0) {
616         // no images, do not accept that
617         m_view.slide_info->setText(i18n("No image found"));
618         m_view.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
619         return;
620     }
621     m_view.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
622     m_view.slide_info->setText(i18np("1 image found", "%1 images found", m_count));
623     QDomElement xml = m_clip->toXML();
624     xml.setAttribute("resource", m_view.clip_path->text() + extension);
625     int width = 180.0 * KdenliveSettings::project_display_ratio();
626     if (width % 2 == 1) width++;
627     QPixmap pix = m_clip->thumbProducer()->getImage(KUrl(m_view.clip_path->text() + extension), 1, width, 180);
628     QMap <QString, QString> props = m_clip->properties();
629     m_view.clip_duration->setText(m_tc.getTimecodeFromFrames(props.value("ttl").toInt() * m_count));
630     m_view.clip_thumb->setPixmap(pix);
631 }
632
633 void ClipProperties::slotCheckMaxLength()
634 {
635     if (m_clip->maxDuration() == GenTime()) return;
636     int duration = m_tc.getFrameCount(m_view.clip_duration->text());
637     if (duration > m_clip->maxDuration().frames(m_fps)) {
638         m_view.clip_duration->setText(m_tc.getTimecode(m_clip->maxDuration()));
639     }
640 }
641
642 void ClipProperties::slotUpdateDurationFormat(int ix)
643 {
644     bool framesFormat = ix == 1;
645     if (framesFormat) {
646         // switching to frames count, update widget
647         m_view.slide_duration_frames->setValue(m_tc.getFrameCount(m_view.slide_duration->text()));
648         m_view.luma_duration_frames->setValue(m_tc.getFrameCount(m_view.luma_duration->text()));
649         m_view.slide_duration->setHidden(true);
650         m_view.luma_duration->setHidden(true);
651         m_view.slide_duration_frames->setHidden(false);
652         m_view.luma_duration_frames->setHidden(false);
653     } else {
654         // switching to timecode format
655         m_view.slide_duration->setText(m_tc.getTimecodeFromFrames(m_view.slide_duration_frames->value()));
656         m_view.luma_duration->setText(m_tc.getTimecodeFromFrames(m_view.luma_duration_frames->value()));
657         m_view.slide_duration_frames->setHidden(true);
658         m_view.luma_duration_frames->setHidden(true);
659         m_view.slide_duration->setHidden(false);
660         m_view.luma_duration->setHidden(false);
661     }
662 }
663
664 #include "clipproperties.moc"
665
666