]> git.sesse.net Git - kdenlive/blob - src/renderwidget.cpp
* Change screen grab parameter format so that the program name (arecord) is not visib...
[kdenlive] / src / renderwidget.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 <QDomDocument>
22
23 #include <KStandardDirs>
24 #include <KDebug>
25 #include <KMessageBox>
26 #include <KComboBox>
27
28 #include "kdenlivesettings.h"
29 #include "renderwidget.h"
30 #include "ui_saveprofile_ui.h"
31
32 const int GroupRole = Qt::UserRole;
33 const int ExtensionRole = GroupRole + 1;
34 const int StandardRole = GroupRole + 2;
35 const int RenderRole = GroupRole + 3;
36 const int ParamsRole = GroupRole + 4;
37 const int EditableRole = GroupRole + 5;
38
39 RenderWidget::RenderWidget(QWidget * parent): QDialog(parent), m_standard("PAL") {
40     m_view.setupUi(this);
41     m_view.buttonDelete->setIcon(KIcon("trash-empty"));
42     m_view.buttonDelete->setToolTip(i18n("Delete profile"));
43     m_view.buttonDelete->setEnabled(false);
44
45     m_view.buttonEdit->setIcon(KIcon("document-properties"));
46     m_view.buttonEdit->setToolTip(i18n("Edit profile"));
47     m_view.buttonEdit->setEnabled(false);
48
49     m_view.buttonSave->setIcon(KIcon("document-new"));
50     m_view.buttonSave->setToolTip(i18n("Create new profile"));
51
52     m_view.buttonInfo->setIcon(KIcon("help-about"));
53
54     if (KdenliveSettings::showrenderparams()) {
55         m_view.buttonInfo->setDown(true);
56     } else m_view.advanced_params->hide();
57
58     connect(m_view.buttonInfo, SIGNAL(clicked()), this, SLOT(showInfoPanel()));
59
60     connect(m_view.buttonSave, SIGNAL(clicked()), this, SLOT(slotSaveProfile()));
61     connect(m_view.buttonEdit, SIGNAL(clicked()), this, SLOT(slotEditProfile()));
62     connect(m_view.buttonDelete, SIGNAL(clicked()), this, SLOT(slotDeleteProfile()));
63     connect(m_view.buttonStart, SIGNAL(clicked()), this, SLOT(slotExport()));
64     connect(m_view.out_file, SIGNAL(textChanged(const QString &)), this, SLOT(slotUpdateButtons()));
65     connect(m_view.format_list, SIGNAL(currentRowChanged(int)), this, SLOT(refreshView()));
66     connect(m_view.size_list, SIGNAL(currentRowChanged(int)), this, SLOT(refreshParams()));
67
68     connect(m_view.render_guide, SIGNAL(clicked(bool)), this, SLOT(slotUpdateGuideBox()));
69     connect(m_view.render_zone, SIGNAL(clicked(bool)), this, SLOT(slotUpdateGuideBox()));
70     connect(m_view.render_full, SIGNAL(clicked(bool)), this, SLOT(slotUpdateGuideBox()));
71
72     connect(m_view.guide_end, SIGNAL(activated(int)), this, SLOT(slotCheckStartGuidePosition()));
73     connect(m_view.guide_start, SIGNAL(activated(int)), this, SLOT(slotCheckEndGuidePosition()));
74
75
76     m_view.buttonStart->setEnabled(false);
77     m_view.guides_box->setVisible(false);
78     parseProfiles();
79     m_view.splitter->setStretchFactor(1, 5);
80     m_view.splitter->setStretchFactor(0, 2);
81 }
82
83 void RenderWidget::showInfoPanel() {
84     if (m_view.advanced_params->isVisible()) {
85         m_view.advanced_params->setVisible(false);
86         m_view.buttonInfo->setDown(false);
87         KdenliveSettings::setShowrenderparams(false);
88     } else {
89         m_view.advanced_params->setVisible(true);
90         m_view.buttonInfo->setDown(true);
91         KdenliveSettings::setShowrenderparams(true);
92     }
93 }
94
95 void RenderWidget::slotUpdateGuideBox() {
96     m_view.guides_box->setVisible(m_view.render_guide->isChecked());
97 }
98
99 void RenderWidget::slotCheckStartGuidePosition() {
100     if (m_view.guide_start->currentIndex() > m_view.guide_end->currentIndex())
101         m_view.guide_start->setCurrentIndex(m_view.guide_end->currentIndex());
102 }
103
104 void RenderWidget::slotCheckEndGuidePosition() {
105     if (m_view.guide_end->currentIndex() < m_view.guide_start->currentIndex())
106         m_view.guide_end->setCurrentIndex(m_view.guide_start->currentIndex());
107 }
108
109 void RenderWidget::setGuides(QDomElement guidesxml, double duration) {
110     m_view.guide_start->clear();
111     m_view.guide_end->clear();
112     QDomNodeList nodes = guidesxml.elementsByTagName("guide");
113     if (nodes.count() > 0) {
114         m_view.guide_start->addItem(i18n("Render"), "0");
115         m_view.render_guide->setEnabled(true);
116     } else m_view.render_guide->setEnabled(false);
117     for (int i = 0; i < nodes.count(); i++) {
118         QDomElement e = nodes.item(i).toElement();
119         if (!e.isNull()) {
120             m_view.guide_start->addItem(e.attribute("comment"), e.attribute("time").toDouble());
121             m_view.guide_end->addItem(e.attribute("comment"), e.attribute("time").toDouble());
122         }
123     }
124     if (nodes.count() > 0)
125         m_view.guide_end->addItem(i18n("End"), QString::number(duration));
126 }
127
128 void RenderWidget::slotUpdateButtons() {
129     if (m_view.out_file->url().isEmpty()) m_view.buttonStart->setEnabled(false);
130     else m_view.buttonStart->setEnabled(true);
131 }
132
133 void RenderWidget::slotSaveProfile() {
134     Ui::SaveProfile_UI ui;
135     QDialog *d = new QDialog(this);
136     ui.setupUi(d);
137     QString customGroup = i18n("Custom");
138     QStringList groupNames;
139     for (int i = 0; i < m_view.format_list->count(); i++)
140         groupNames.append(m_view.format_list->item(i)->text());
141     if (!groupNames.contains(customGroup)) groupNames.prepend(customGroup);
142     ui.group_name->addItems(groupNames);
143     int pos = ui.group_name->findText(customGroup);
144     ui.group_name->setCurrentIndex(pos);
145
146     ui.parameters->setText(m_view.advanced_params->toPlainText());
147     ui.extension->setText(m_view.size_list->currentItem()->data(ExtensionRole).toString());
148     ui.profile_name->setFocus();
149     if (d->exec() == QDialog::Accepted) {
150         QString exportFile = KStandardDirs::locateLocal("appdata", "export/customprofiles.xml");
151         QDomDocument doc;
152         QFile file(exportFile);
153         doc.setContent(&file, false);
154         file.close();
155
156         QDomElement documentElement;
157         bool groupExists = false;
158         QString groupName;
159         QString newProfileName = ui.profile_name->text();
160         QString newGroupName = ui.group_name->currentText();
161         QDomNodeList groups = doc.elementsByTagName("group");
162         int i = 0;
163         if (groups.count() == 0) {
164             QDomElement profiles = doc.createElement("profiles");
165             doc.appendChild(profiles);
166         } else while (!groups.item(i).isNull()) {
167                 documentElement = groups.item(i).toElement();
168                 groupName = documentElement.attribute("name");
169                 kDebug() << "// SAVE, PARSING FROUP: " << i << ", name: " << groupName << ", LOOK FR: " << newGroupName;
170                 if (groupName == newGroupName) {
171                     groupExists = true;
172                     break;
173                 }
174                 i++;
175             }
176         if (!groupExists) {
177             documentElement = doc.createElement("group");
178             documentElement.setAttribute("name", ui.group_name->currentText());
179             documentElement.setAttribute("renderer", "avformat");
180             doc.documentElement().appendChild(documentElement);
181         }
182         QDomElement profileElement = doc.createElement("profile");
183         profileElement.setAttribute("name", newProfileName);
184         profileElement.setAttribute("extension", ui.extension->text().simplified());
185         profileElement.setAttribute("args", ui.parameters->toPlainText().simplified());
186         documentElement.appendChild(profileElement);
187
188         //QCString save = doc.toString().utf8();
189
190         if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
191             KMessageBox::sorry(this, i18n("Unable to write to file %1", exportFile));
192             delete d;
193             return;
194         }
195         QTextStream out(&file);
196         out << doc.toString();
197         file.close();
198         parseProfiles(newGroupName, newProfileName);
199     }
200     delete d;
201 }
202
203 void RenderWidget::slotEditProfile() {
204     QListWidgetItem *item = m_view.size_list->currentItem();
205     if (!item) return;
206     QString currentGroup = m_view.format_list->currentItem()->text();
207
208     QString params = item->data(ParamsRole).toString();
209     QString extension = item->data(ExtensionRole).toString();
210     QString currentProfile = item->text();
211
212     Ui::SaveProfile_UI ui;
213     QDialog *d = new QDialog(this);
214     ui.setupUi(d);
215     QStringList groupNames;
216     for (int i = 0; i < m_view.format_list->count(); i++)
217         groupNames.append(m_view.format_list->item(i)->text());
218     if (!groupNames.contains(currentGroup)) groupNames.prepend(currentGroup);
219     ui.group_name->addItems(groupNames);
220     int pos = ui.group_name->findText(currentGroup);
221     ui.group_name->setCurrentIndex(pos);
222     ui.profile_name->setText(currentProfile);
223     ui.extension->setText(extension);
224     ui.parameters->setText(params);
225     ui.profile_name->setFocus();
226
227     if (d->exec() == QDialog::Accepted) {
228         slotDeleteProfile();
229         QString exportFile = KStandardDirs::locateLocal("appdata", "export/customprofiles.xml");
230         QDomDocument doc;
231         QFile file(exportFile);
232         doc.setContent(&file, false);
233         file.close();
234
235         QDomElement documentElement;
236         bool groupExists = false;
237         QString groupName;
238         QString newProfileName = ui.profile_name->text();
239         QString newGroupName = ui.group_name->currentText();
240         QDomNodeList groups = doc.elementsByTagName("group");
241         int i = 0;
242         if (groups.count() == 0) {
243             QDomElement profiles = doc.createElement("profiles");
244             doc.appendChild(profiles);
245         } else while (!groups.item(i).isNull()) {
246                 documentElement = groups.item(i).toElement();
247                 groupName = documentElement.attribute("name");
248                 kDebug() << "// SAVE, PARSING FROUP: " << i << ", name: " << groupName << ", LOOK FR: " << newGroupName;
249                 if (groupName == newGroupName) {
250                     groupExists = true;
251                     break;
252                 }
253                 i++;
254             }
255         if (!groupExists) {
256             documentElement = doc.createElement("group");
257             documentElement.setAttribute("name", ui.group_name->currentText());
258             documentElement.setAttribute("renderer", "avformat");
259             doc.documentElement().appendChild(documentElement);
260         }
261         QDomElement profileElement = doc.createElement("profile");
262         profileElement.setAttribute("name", newProfileName);
263         profileElement.setAttribute("extension", ui.extension->text().simplified());
264         profileElement.setAttribute("args", ui.parameters->toPlainText().simplified());
265         documentElement.appendChild(profileElement);
266
267         //QCString save = doc.toString().utf8();
268
269         if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
270             KMessageBox::sorry(this, i18n("Unable to write to file %1", exportFile));
271             delete d;
272             return;
273         }
274         QTextStream out(&file);
275         out << doc.toString();
276         file.close();
277         parseProfiles(newGroupName, newProfileName);
278     }
279     delete d;
280 }
281
282 void RenderWidget::slotDeleteProfile() {
283     QString currentGroup = m_view.format_list->currentItem()->text();
284     QString currentProfile = m_view.size_list->currentItem()->text();
285
286     QString exportFile = KStandardDirs::locateLocal("appdata", "export/customprofiles.xml");
287     QDomDocument doc;
288     QFile file(exportFile);
289     doc.setContent(&file, false);
290     file.close();
291
292     QDomElement documentElement;
293     bool groupExists = false;
294     QString groupName;
295     QDomNodeList groups = doc.elementsByTagName("group");
296     int i = 0;
297
298     while (!groups.item(i).isNull()) {
299         documentElement = groups.item(i).toElement();
300         groupName = documentElement.attribute("name");
301         if (groupName == currentGroup) {
302             QDomNodeList children = documentElement.childNodes();
303             for (int j = 0; j < children.count(); j++) {
304                 QDomElement pro = children.at(j).toElement();
305                 if (pro.attribute("name") == currentProfile) {
306                     groups.item(i).removeChild(children.at(j));
307                     if (groups.item(i).childNodes().isEmpty())
308                         doc.documentElement().removeChild(groups.item(i));
309                     break;
310                 }
311             }
312             break;
313         }
314         i++;
315     }
316
317     if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
318         KMessageBox::sorry(this, i18n("Unable to write to file %1", exportFile));
319         return;
320     }
321     QTextStream out(&file);
322     out << doc.toString();
323     file.close();
324     parseProfiles(currentGroup);
325 }
326
327 void RenderWidget::slotExport() {
328     QListWidgetItem *item = m_view.size_list->currentItem();
329     if (!item) return;
330     QFile f(m_view.out_file->url().path());
331     if (f.exists()) {
332         if (KMessageBox::warningYesNo(this, i18n("File already exists. Do you want to overwrite it ?")) != KMessageBox::Yes)
333             return;
334     }
335     QStringList overlayargs;
336     if (m_view.tc_overlay->isChecked()) {
337         QString filterFile = KStandardDirs::locate("appdata", "metadata.properties");
338         overlayargs << "meta.attr.timecode=1" << "meta.attr.timecode.markup=#timecode";
339         overlayargs << "-attach" << "data_feed:attr_check" << "-attach";
340         overlayargs << "data_show:" + filterFile << "_fezzik=1" << "dynamic=1";
341     }
342     double startPos = -1;
343     double endPos = -1;
344     if (m_view.render_guide->isChecked()) {
345         startPos = m_view.guide_start->itemData(m_view.guide_start->currentIndex()).toDouble();
346         endPos = m_view.guide_end->itemData(m_view.guide_end->currentIndex()).toDouble();
347     }
348     emit doRender(m_view.out_file->url().path(), item->data(RenderRole).toString(), overlayargs, m_view.advanced_params->toPlainText().split(' '), m_view.render_zone->isChecked(), m_view.play_after->isChecked(), startPos, endPos);
349 }
350
351 void RenderWidget::setDocumentStandard(QString std) {
352     m_standard = std;
353     refreshView();
354 }
355
356 void RenderWidget::refreshView() {
357     QListWidgetItem *item = m_view.format_list->currentItem();
358     if (!item) {
359         m_view.format_list->setCurrentRow(0);
360         item = m_view.format_list->currentItem();
361     }
362     if (!item) return;
363     QString std;
364     QString group = item->text();
365     QListWidgetItem *sizeItem;
366     bool firstSelected = false;
367     for (int i = 0; i < m_view.size_list->count(); i++) {
368         sizeItem = m_view.size_list->item(i);
369         std = sizeItem->data(StandardRole).toString();
370         if (!std.isEmpty() && !std.contains(m_standard, Qt::CaseInsensitive)) sizeItem->setHidden(true);
371         else if (sizeItem->data(GroupRole) == group) {
372             sizeItem->setHidden(false);
373             if (!firstSelected) m_view.size_list->setCurrentItem(sizeItem);
374             firstSelected = true;
375         } else sizeItem->setHidden(true);
376     }
377
378 }
379
380 void RenderWidget::refreshParams() {
381     QListWidgetItem *item = m_view.size_list->currentItem();
382     if (!item) return;
383     QString params = item->data(ParamsRole).toString();
384     QString extension = item->data(ExtensionRole).toString();
385     m_view.advanced_params->setPlainText(params);
386     m_view.advanced_params->setToolTip(params);
387     KUrl url = m_view.out_file->url();
388     if (!url.isEmpty()) {
389         QString path = url.path();
390         int pos = path.lastIndexOf('.') + 1;
391         if (pos == 0) path.append('.') + extension;
392         else path = path.left(pos) + extension;
393         m_view.out_file->setUrl(KUrl(path));
394     } else {
395         m_view.out_file->setUrl(KUrl(QDir::homePath() + "/untitled." + extension));
396     }
397
398     if (item->data(EditableRole).toString().isEmpty()) {
399         m_view.buttonDelete->setEnabled(false);
400         m_view.buttonEdit->setEnabled(false);
401     } else {
402         m_view.buttonDelete->setEnabled(true);
403         m_view.buttonEdit->setEnabled(true);
404     }
405 }
406
407 void RenderWidget::parseProfiles(QString group, QString profile) {
408     m_view.size_list->clear();
409     m_view.format_list->clear();
410     QString exportFile = KStandardDirs::locate("appdata", "export/profiles.xml");
411     parseFile(exportFile, false);
412     exportFile = KStandardDirs::locateLocal("appdata", "export/customprofiles.xml");
413     if (QFile::exists(exportFile)) parseFile(exportFile, true);
414     refreshView();
415     QList<QListWidgetItem *> child;
416     child = m_view.format_list->findItems(group, Qt::MatchExactly);
417     if (!child.isEmpty()) m_view.format_list->setCurrentItem(child.at(0));
418     child = m_view.size_list->findItems(profile, Qt::MatchExactly);
419     if (!child.isEmpty()) m_view.size_list->setCurrentItem(child.at(0));
420 }
421
422 void RenderWidget::parseFile(QString exportFile, bool editable) {
423     QDomDocument doc;
424     QFile file(exportFile);
425     doc.setContent(&file, false);
426     file.close();
427     QDomElement documentElement;
428     QDomElement profileElement;
429     QDomNodeList groups = doc.elementsByTagName("group");
430
431     if (groups.count() == 0) {
432         kDebug() << "// Export file: " << exportFile << " IS BROKEN";
433         return;
434     }
435
436     int i = 0;
437     QString groupName;
438     QString profileName;
439     QString extension;
440     QString prof_extension;
441     QString renderer;
442     QString params;
443     QString standard;
444     QListWidgetItem *item;
445     while (!groups.item(i).isNull()) {
446         documentElement = groups.item(i).toElement();
447         groupName = documentElement.attribute("name", QString::null);
448         extension = documentElement.attribute("extension", QString::null);
449         renderer = documentElement.attribute("renderer", QString::null);
450         if (m_view.format_list->findItems(groupName, Qt::MatchExactly).isEmpty())
451             new QListWidgetItem(groupName, m_view.format_list);
452
453         QDomNode n = groups.item(i).firstChild();
454         while (!n.isNull()) {
455             profileElement = n.toElement();
456             profileName = profileElement.attribute("name");
457             standard = profileElement.attribute("standard");
458             params = profileElement.attribute("args");
459             prof_extension = profileElement.attribute("extension");
460             if (!prof_extension.isEmpty()) extension = prof_extension;
461             item = new QListWidgetItem(profileName, m_view.size_list);
462             item->setData(GroupRole, groupName);
463             item->setData(ExtensionRole, extension);
464             item->setData(RenderRole, renderer);
465             item->setData(StandardRole, standard);
466             item->setData(ParamsRole, params);
467             if (editable) item->setData(EditableRole, "true");
468             n = n.nextSibling();
469         }
470
471         i++;
472     }
473 }
474
475
476
477 #include "renderwidget.moc"
478
479