]> git.sesse.net Git - kdenlive/blob - src/kdenlivedoc.cpp
more icons
[kdenlive] / src / kdenlivedoc.cpp
1 /***************************************************************************
2  *   Copyright (C) 2007 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 #include <KDebug>
21 #include <KStandardDirs>
22 #include <KMessageBox>
23 #include <KLocale>
24 #include <KFileDialog>
25 #include <KIO/NetAccess>
26 #include <KApplication>
27
28 #include "kdenlivedoc.h"
29 #include "docclipbase.h"
30 #include "profilesdialog.h"
31 #include "kdenlivesettings.h"
32 #include "renderer.h"
33 #include "clipmanager.h"
34 #include "addfoldercommand.h"
35 #include "editfoldercommand.h"
36 #include "titlewidget.h"
37 #include "mainwindow.h"
38
39 KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, MltVideoProfile profile, QUndoGroup *undoGroup, MainWindow *parent): QObject(parent), m_render(NULL), m_url(url), m_projectFolder(projectFolder), m_profile(profile), m_fps((double)profile.frame_rate_num / profile.frame_rate_den), m_width(profile.width), m_height(profile.height), m_commandStack(new KUndoStack(undoGroup)), m_modified(false), m_documentLoadingProgress(0), m_documentLoadingStep(0.0), m_startPos(0) {
40     m_clipManager = new ClipManager(this);
41     if (!url.isEmpty()) {
42         QString tmpFile;
43         if (KIO::NetAccess::download(url.path(), tmpFile, parent)) {
44             QFile file(tmpFile);
45             m_document.setContent(&file, false);
46             file.close();
47             QDomNode infoXmlNode = m_document.elementsByTagName("kdenlivedoc").at(0);
48             QDomNode westley = m_document.elementsByTagName("westley").at(0);
49             if (!infoXmlNode.isNull()) {
50                 QDomElement infoXml = infoXmlNode.toElement();
51                 QString profilePath = infoXml.attribute("profile");
52                 m_startPos = infoXml.attribute("position").toInt();
53                 if (!profilePath.isEmpty()) setProfilePath(profilePath);
54                 double version = infoXml.attribute("version").toDouble();
55                 if (version < 0.7) convertDocument(version);
56                 else {
57                     //delete all mlt producers and instead, use Kdenlive saved producers
58                     QDomNodeList prods = m_document.elementsByTagName("producer");
59                     int maxprod = prods.count();
60                     int pos = 0;
61                     for (int i = 0; i < maxprod; i++) {
62                         QDomNode m = prods.at(pos);
63                         if (m.toElement().attribute("id") == "black")
64                             pos = 1;
65                         else westley.removeChild(m);
66                     }
67                     prods = m_document.elementsByTagName("kdenlive_producer");
68                     maxprod = prods.count();
69                     for (int i = 0; i < maxprod; i++) {
70                         prods.at(0).toElement().setTagName("producer");
71                         westley.insertBefore(prods.at(0), QDomNode());
72                     }
73                 }
74                 QDomElement e;
75                 QDomNodeList producers = m_document.elementsByTagName("producer");
76                 const int max = producers.count();
77                 if (max > 0) {
78                     m_documentLoadingStep = 100.0 / (max + m_document.elementsByTagName("entry").count());
79                     parent->slotGotProgressInfo(i18n("Loading project clips"), (int) m_documentLoadingProgress);
80                 }
81
82                 for (int i = 0; i < max; i++) {
83                     e = producers.item(i).cloneNode().toElement();
84                     if (m_documentLoadingStep > 0) {
85                         m_documentLoadingProgress += m_documentLoadingStep;
86                         parent->slotGotProgressInfo(QString(), (int) m_documentLoadingProgress);
87                         qApp->processEvents();
88                     }
89                     if (!e.isNull() && e.attribute("id") != "black") {
90                         addClip(e, e.attribute("id").toInt());
91                     }
92                 }
93
94                 QDomNode markers = m_document.elementsByTagName("markers").at(0);
95                 if (!markers.isNull()) {
96                     QDomNodeList markerslist = markers.childNodes();
97                     int maxchild = markerslist.count();
98                     for (int k = 0; k < maxchild; k++) {
99                         e = markerslist.at(k).toElement();
100                         if (e.tagName() == "marker") {
101                             int id = e.attribute("id").toInt();
102                             m_clipManager->getClipById(id)->addSnapMarker(GenTime(e.attribute("time").toDouble()), e.attribute("comment"));
103                         }
104                     }
105                     m_document.removeChild(markers);
106                 }
107                 m_document.removeChild(infoXmlNode);
108
109                 kDebug() << "Reading file: " << url.path() << ", found clips: " << producers.count();
110             } else kWarning() << "  NO KDENLIVE INFO FOUND IN FILE: " << url.path();
111             KIO::NetAccess::removeTempFile(tmpFile);
112         } else {
113             KMessageBox::error(parent, KIO::NetAccess::lastErrorString());
114         }
115     } else {
116         // Creating new document
117         QDomElement westley = m_document.createElement("westley");
118         m_document.appendChild(westley);
119
120         QDomElement tractor = m_document.createElement("tractor");
121         tractor.setAttribute("id", "maintractor");
122         QDomElement multitrack = m_document.createElement("multitrack");
123         QDomElement playlist = m_document.createElement("playlist");
124         playlist.setAttribute("id", "black_track");
125         westley.appendChild(playlist);
126
127
128         // create playlists
129         int audiotracks = 2;
130         int videotracks = 3;
131         int total = audiotracks + videotracks + 1;
132
133         for (int i = 1; i < total; i++) {
134             QDomElement playlist = m_document.createElement("playlist");
135             playlist.setAttribute("id", "playlist" + QString::number(i));
136             westley.appendChild(playlist);
137         }
138
139         QDomElement track0 = m_document.createElement("track");
140         track0.setAttribute("producer", "black_track");
141         tractor.appendChild(track0);
142
143         // create audio tracks
144         for (int i = 1; i < audiotracks + 1; i++) {
145             QDomElement track = m_document.createElement("track");
146             track.setAttribute("producer", "playlist" + QString::number(i));
147             track.setAttribute("hide", "video");
148             tractor.appendChild(track);
149         }
150
151         // create video tracks
152         for (int i = audiotracks + 1; i < total; i++) {
153             QDomElement track = m_document.createElement("track");
154             track.setAttribute("producer", "playlist" + QString::number(i));
155             tractor.appendChild(track);
156         }
157
158         for (uint i = 2; i < total ; i++) {
159             QDomElement transition = m_document.createElement("transition");
160             transition.setAttribute("in", "0");
161             //TODO: Make audio mix last for all project duration
162             transition.setAttribute("out", "15000");
163
164             QDomElement property = m_document.createElement("property");
165             property.setAttribute("name", "a_track");
166             QDomText value = m_document.createTextNode(QString::number(1));
167             property.appendChild(value);
168             transition.appendChild(property);
169
170             property = m_document.createElement("property");
171             property.setAttribute("name", "b_track");
172             value = m_document.createTextNode(QString::number(i));
173             property.appendChild(value);
174             transition.appendChild(property);
175
176             property = m_document.createElement("property");
177             property.setAttribute("name", "mlt_service");
178             value = m_document.createTextNode("mix");
179             property.appendChild(value);
180             transition.appendChild(property);
181
182             property = m_document.createElement("property");
183             property.setAttribute("name", "combine");
184             value = m_document.createTextNode("1");
185             property.appendChild(value);
186             transition.appendChild(property);
187
188             property = m_document.createElement("property");
189             property.setAttribute("name", "internal_added");
190             value = m_document.createTextNode("237");
191             property.appendChild(value);
192             transition.appendChild(property);
193             tractor.appendChild(transition);
194         }
195         westley.appendChild(tractor);
196     }
197     m_scenelist = m_document.toString();
198     // kDebug() << "scenelist" << m_scenelist;
199     if (m_fps == 30000.0 / 1001.0) m_timecode.setFormat(30, true);
200     else m_timecode.setFormat((int) m_fps);
201 }
202
203 KdenliveDoc::~KdenliveDoc() {
204     delete m_commandStack;
205     delete m_clipManager;
206 }
207
208 void KdenliveDoc::convertDocument(double version) {
209     // Opening a old Kdenlive document
210     QDomNode westley = m_document.elementsByTagName("westley").at(1);
211     QDomNode tractor = m_document.elementsByTagName("tractor").at(0);
212     QDomNode kdenlivedoc = m_document.elementsByTagName("kdenlivedoc").at(0);
213     QDomNode multitrack = m_document.elementsByTagName("multitrack").at(0);
214     QDomNodeList playlists = m_document.elementsByTagName("playlist");
215
216     QDomNode props = m_document.elementsByTagName("properties").at(0).toElement();
217     QString profile = props.toElement().attribute("videoprofile");
218     if (profile == "dv_wide") profile = "dv_pal_wide";
219     if (!profile.isEmpty()) {
220         setProfilePath(profile);
221     } else setProfilePath("dv_pal");
222
223     // move playlists outside of tractor and add the tracks instead
224     int max = playlists.count();
225     for (int i = 0; i < max; i++) {
226         QDomNode n = playlists.at(i);
227         westley.insertBefore(n, QDomNode());
228         QDomElement pl = n.toElement();
229         QDomElement track = m_document.createElement("track");
230         QString trackType = pl.attribute("hide");
231         if (!trackType.isEmpty()) track.setAttribute("hide", trackType);
232         QString playlist_id =  pl.attribute("id");
233         if (playlist_id.isEmpty()) {
234             playlist_id = "black_track";
235             pl.setAttribute("id", playlist_id);
236         }
237         track.setAttribute("producer", playlist_id);
238         tractor.appendChild(track);
239     }
240     tractor.removeChild(multitrack);
241
242     // audio track mixing transitions should not be added to track view, so add required attribute
243     QDomNodeList transitions = m_document.elementsByTagName("transition");
244     max = transitions.count();
245     for (int i = 0; i < max; i++) {
246         QDomElement tr = transitions.at(i).toElement();
247         if (tr.attribute("combine") == "1" && tr.attribute("mlt_service") == "mix") {
248             QDomElement property = m_document.createElement("property");
249             property.setAttribute("name", "internal_added");
250             QDomText value = m_document.createTextNode("237");
251             property.appendChild(value);
252             tr.appendChild(property);
253         } else {
254             // convert transition
255             QDomNamedNodeMap attrs = tr.attributes();
256             for (unsigned int j = 0; j < attrs.count(); j++) {
257                 QString attrName = attrs.item(j).nodeName();
258                 if (attrName != "in" && attrName != "out" && attrName != "id") {
259                     QDomElement property = m_document.createElement("property");
260                     property.setAttribute("name", attrName);
261                     QDomText value = m_document.createTextNode(attrs.item(j).nodeValue());
262                     property.appendChild(value);
263                     tr.appendChild(property);
264                 }
265             }
266         }
267     }
268
269     // move transitions after tracks
270     for (int i = 0; i < max; i++) {
271         tractor.insertAfter(transitions.at(0), QDomNode());
272     }
273
274     QDomElement markers = m_document.createElement("markers");
275
276     // change producer names
277     QDomNodeList producers = m_document.elementsByTagName("producer");
278     max = producers.count();
279     for (int i = 0; i < max; i++) {
280         QDomElement prod = producers.at(0).toElement();
281         QDomNode m = prod.firstChild();
282         if (!m.isNull() && m.toElement().tagName() == "markers") {
283             QDomNodeList prodchilds = m.childNodes();
284             int maxchild = prodchilds.count();
285             for (int k = 0; k < maxchild; k++) {
286                 QDomElement mark = prodchilds.at(0).toElement();
287                 mark.setAttribute("id", prod.attribute("id"));
288                 markers.insertAfter(mark, QDomNode());
289             }
290             prod.removeChild(m);
291         }
292         int duration = prod.attribute("duration").toInt();
293         if (duration > 0) prod.setAttribute("out", QString::number(duration));
294         westley.insertBefore(prod, QDomNode());
295     }
296
297     QDomNode westley0 = m_document.elementsByTagName("westley").at(0);
298     if (!markers.firstChild().isNull()) westley0.appendChild(markers);
299     westley0.removeChild(kdenlivedoc);
300
301     QDomNodeList elements = westley.childNodes();
302     max = elements.count();
303     for (int i = 0; i < max; i++) {
304         QDomElement prod = elements.at(0).toElement();
305         westley0.insertAfter(prod, QDomNode());
306     }
307
308     westley0.removeChild(westley);
309
310     //kDebug() << "/////////////////  CONVERTED DOC:";
311     //kDebug() << m_document.toString();
312     //kDebug() << "/////////////////  END CONVERTED DOC:";
313 }
314
315 QDomElement KdenliveDoc::documentInfoXml(QDomElement timelineInfo) {
316     QDomDocument doc;
317     QDomElement e;
318     QDomElement addedXml = doc.createElement("kdenlivedoc");
319     QDomElement markers = doc.createElement("markers");
320     addedXml.setAttribute("version", "0.7");
321     addedXml.setAttribute("profile", profilePath());
322     addedXml.setAttribute("position", m_render->seekPosition().frames(m_fps));
323     QList <DocClipBase*> list = m_clipManager->documentClipList();
324     for (int i = 0; i < list.count(); i++) {
325         e = list.at(i)->toXML();
326         e.setTagName("kdenlive_producer");
327         addedXml.appendChild(doc.importNode(e, true));
328         QList < CommentedTime > marks = list.at(i)->commentedSnapMarkers();
329         for (int j = 0; j < marks.count(); j++) {
330             QDomElement marker = doc.createElement("marker");
331             marker.setAttribute("time", marks.at(j).time().ms() / 1000);
332             marker.setAttribute("comment", marks.at(j).comment());
333             marker.setAttribute("id", e.attribute("id"));
334             markers.appendChild(marker);
335         }
336     }
337     addedXml.appendChild(markers);
338     addedXml.appendChild(doc.importNode(timelineInfo, true));
339     //kDebug() << m_document.toString();
340     return addedXml;
341 }
342
343
344 ClipManager *KdenliveDoc::clipManager() {
345     return m_clipManager;
346 }
347
348 KUrl KdenliveDoc::projectFolder() const {
349     if (m_projectFolder.isEmpty()) return KUrl(KStandardDirs::locateLocal("appdata", "/projects/"));
350     return m_projectFolder;
351 }
352
353 QString KdenliveDoc::getDocumentStandard() {
354     //WARNING: this way to tell the video standard is a bit hackish...
355     if (m_profile.description.contains("pal", Qt::CaseInsensitive) || m_profile.description.contains("25", Qt::CaseInsensitive) || m_profile.description.contains("50", Qt::CaseInsensitive)) return "PAL";
356     return "NTSC";
357 }
358
359 QString KdenliveDoc::profilePath() const {
360     return m_profile.path;
361 }
362
363 void KdenliveDoc::setProfilePath(QString path) {
364     KdenliveSettings::setCurrent_profile(path);
365     m_profile = ProfilesDialog::getVideoProfile(path);
366     m_fps = (double) m_profile.frame_rate_num / m_profile.frame_rate_den;
367     m_width = m_profile.width;
368     m_height = m_profile.height;
369     if (m_fps == 30000.0 / 1001.0) m_timecode.setFormat(30, true);
370     else m_timecode.setFormat((int) m_fps);
371 }
372
373 void KdenliveDoc::setThumbsProgress(const QString &message, int progress) {
374     emit progressInfo(message, progress);
375 }
376
377 void KdenliveDoc::loadingProgressed() {
378     m_documentLoadingProgress += m_documentLoadingStep;
379     emit progressInfo(QString(), (int) m_documentLoadingProgress);
380 }
381
382 KUndoStack *KdenliveDoc::commandStack() {
383     return m_commandStack;
384 }
385
386 void KdenliveDoc::setRenderer(Render *render) {
387     m_render = render;
388     emit progressInfo(i18n("Loading playlist..."), 0);
389     qApp->processEvents();
390     if (m_render) m_render->setSceneList(m_scenelist, m_startPos);
391     emit progressInfo(QString(), -1);
392 }
393
394 Render *KdenliveDoc::renderer() {
395     return m_render;
396 }
397
398 void KdenliveDoc::updateClip(int id) {
399     emit updateClipDisplay(id);
400 }
401
402 int KdenliveDoc::getFramePos(QString duration) {
403     return m_timecode.getFrameCount(duration, m_fps);
404 }
405
406 QString KdenliveDoc::producerName(int id) {
407     QString result = "unnamed";
408     QDomNodeList prods = producersList();
409     int ct = prods.count();
410     for (int i = 0; i <  ct ; i++) {
411         QDomElement e = prods.item(i).toElement();
412         if (e.attribute("id") != "black" && e.attribute("id").toInt() == id) {
413             result = e.attribute("name");
414             if (result.isEmpty()) result = KUrl(e.attribute("resource")).fileName();
415             break;
416         }
417     }
418     return result;
419 }
420
421 void KdenliveDoc::setProducerDuration(int id, int duration) {
422     QDomNodeList prods = producersList();
423     int ct = prods.count();
424     for (int i = 0; i <  ct ; i++) {
425         QDomElement e = prods.item(i).toElement();
426         if (e.attribute("id") != "black" && e.attribute("id").toInt() == id) {
427             e.setAttribute("duration", QString::number(duration));
428             break;
429         }
430     }
431 }
432
433 int KdenliveDoc::getProducerDuration(int id) {
434     int result = 0;
435     QDomNodeList prods = producersList();
436     int ct = prods.count();
437     for (int i = 0; i <  ct ; i++) {
438         QDomElement e = prods.item(i).toElement();
439         if (e.attribute("id") != "black" && e.attribute("id").toInt() == id) {
440             result = e.attribute("duration").toInt();
441             break;
442         }
443     }
444     return result;
445 }
446
447
448 QDomDocument KdenliveDoc::generateSceneList() {
449     QDomDocument doc;
450     QDomElement westley = doc.createElement("westley");
451     doc.appendChild(westley);
452     QDomElement prod = doc.createElement("producer");
453 }
454
455 QDomDocument KdenliveDoc::toXml() const {
456     return m_document;
457 }
458
459 Timecode KdenliveDoc::timecode() const {
460     return m_timecode;
461 }
462
463 QDomNodeList KdenliveDoc::producersList() {
464     return m_document.elementsByTagName("producer");
465 }
466
467 void KdenliveDoc::backupMltPlaylist() {
468     if (m_render) m_scenelist = m_render->sceneList();
469 }
470
471 double KdenliveDoc::fps() const {
472     return m_fps;
473 }
474
475 int KdenliveDoc::width() const {
476     return m_width;
477 }
478
479 int KdenliveDoc::height() const {
480     return m_height;
481 }
482
483 KUrl KdenliveDoc::url() const {
484     return m_url;
485 }
486
487 void KdenliveDoc::setUrl(KUrl url) {
488     m_url = url;
489 }
490
491 void KdenliveDoc::setModified(bool mod) {
492     if (mod == m_modified) return;
493     m_modified = mod;
494     emit docModified(m_modified);
495 }
496
497 bool KdenliveDoc::isModified() const {
498     return m_modified;
499 }
500
501 QString KdenliveDoc::description() const {
502     if (m_url.isEmpty())
503         return i18n("Untitled") + " / " + m_profile.description;
504     else
505         return m_url.fileName() + " / " + m_profile.description;
506 }
507
508 void KdenliveDoc::addClip(const QDomElement &elem, const int clipId) {
509     DocClipBase *clip = new DocClipBase(m_clipManager, elem, clipId);
510     kDebug() << "/////////  DOCUM, CREATING NEW CLIP, ID:" << clipId << ", PAR ID:" << elem.attribute("groupid");
511     m_clipManager->addClip(clip);
512     emit addProjectClip(clip);
513 }
514
515 void KdenliveDoc::addFolder(const QString foldername, int clipId, bool edit) {
516     emit addProjectFolder(foldername, clipId, false, edit);
517 }
518
519 void KdenliveDoc::deleteFolder(const QString foldername, int clipId) {
520     emit addProjectFolder(foldername, clipId, true);
521 }
522
523 void KdenliveDoc::deleteProjectClip(QList <int> ids) {
524     for (int i = 0; i < ids.size(); ++i) {
525         emit deletTimelineClip(ids.at(i));
526         m_clipManager->slotDeleteClip(ids.at(i));
527     }
528     setModified(true);
529 }
530
531 void KdenliveDoc::deleteProjectFolder(QMap <QString, int> map) {
532     QMapIterator<QString, int> i(map);
533     while (i.hasNext()) {
534         i.next();
535         slotDeleteFolder(i.key(), i.value());
536     }
537     setModified(true);
538 }
539
540 void KdenliveDoc::deleteClip(const uint clipId) {
541     emit signalDeleteProjectClip(clipId);
542     m_clipManager->deleteClip(clipId);
543 }
544
545 void KdenliveDoc::slotAddClipFile(const KUrl url, const QString group, const int groupId) {
546     kDebug() << "/////////  DOCUM, ADD CLP: " << url;
547     m_clipManager->slotAddClipFile(url, group, groupId);
548     setModified(true);
549 }
550
551 void KdenliveDoc::slotAddTextClipFile(const QString path, const QString group, const int groupId) {
552     kDebug() << "/////////  DOCUM, ADD TXT CLP: " << path;
553     m_clipManager->slotAddTextClipFile(path, group, groupId);
554     setModified(true);
555 }
556
557 void KdenliveDoc::slotAddFolder(const QString folderName) {
558     AddFolderCommand *command = new AddFolderCommand(this, folderName, m_clipManager->getFreeClipId(), true);
559     commandStack()->push(command);
560     setModified(true);
561 }
562
563 void KdenliveDoc::slotDeleteFolder(const QString folderName, const int id) {
564     AddFolderCommand *command = new AddFolderCommand(this, folderName, id, false);
565     commandStack()->push(command);
566     setModified(true);
567 }
568
569 void KdenliveDoc::slotEditFolder(const QString newfolderName, const QString oldfolderName, int clipId) {
570     EditFolderCommand *command = new EditFolderCommand(this, newfolderName, oldfolderName, clipId, false);
571     commandStack()->push(command);
572     setModified(true);
573 }
574
575 int KdenliveDoc::getFreeClipId() {
576     return m_clipManager->getFreeClipId();
577 }
578
579 DocClipBase *KdenliveDoc::getBaseClip(int clipId) {
580     return m_clipManager->getClipById(clipId);
581 }
582
583 void KdenliveDoc::slotAddColorClipFile(const QString name, const QString color, QString duration, const QString group, const int groupId) {
584     m_clipManager->slotAddColorClipFile(name, color, duration, group, groupId);
585     setModified(true);
586 }
587
588 void KdenliveDoc::slotAddSlideshowClipFile(const QString name, const QString path, int count, const QString duration, bool loop, const QString group, const int groupId) {
589     m_clipManager->slotAddSlideshowClipFile(name, path, count, duration, loop, group, groupId);
590     setModified(true);
591 }
592
593 void KdenliveDoc::slotCreateTextClip(QString group, int groupId) {
594     QString titlesFolder = projectFolder().path() + "/titles/";
595     KStandardDirs::makeDir(titlesFolder);
596     TitleWidget *dia_ui = new TitleWidget(KUrl(), titlesFolder, m_render, kapp->activeWindow());
597     if (dia_ui->exec() == QDialog::Accepted) {
598         QString titleName = "title";
599         int counter = 0;
600         QString path = titlesFolder + titleName + QString::number(counter).rightJustified(3, '0', false);
601         while (QFile::exists(path + ".kdenlivetitle")) {
602             counter++;
603             path = titlesFolder + titleName + QString::number(counter).rightJustified(3, '0', false);
604         }
605         QPixmap pix = dia_ui->renderedPixmap();
606         pix.save(path + ".png");
607         dia_ui->saveTitle(path + ".kdenlivetitle");
608         slotAddTextClipFile(path, QString(), -1);
609     }
610     delete dia_ui;
611 }
612
613 void KdenliveDoc::editTextClip(QString path, int id) {
614     TitleWidget *dia_ui = new TitleWidget(KUrl(path + ".kdenlivetitle"), path, m_render, kapp->activeWindow());
615     if (dia_ui->exec() == QDialog::Accepted) {
616         QPixmap pix = dia_ui->renderedPixmap();
617         pix.save(path + ".png");
618         dia_ui->saveTitle(path + ".kdenlivetitle");
619         //slotAddClipFile(KUrl("/tmp/kdenlivetitle.png"), QString(), -1);
620         emit refreshClipThumbnail(id);
621     }
622     delete dia_ui;
623 }
624
625
626 #include "kdenlivedoc.moc"
627