]> git.sesse.net Git - kdenlive/blob - src/renderwidget.cpp
Set window title for render dialog
[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 #include <QItemDelegate>
23 #include <QTreeWidgetItem>
24 #include <QHeaderView>
25
26 #include <KStandardDirs>
27 #include <KDebug>
28 #include <KMessageBox>
29 #include <KComboBox>
30
31 #include "kdenlivesettings.h"
32 #include "renderwidget.h"
33 #include "ui_saveprofile_ui.h"
34
35 const int GroupRole = Qt::UserRole;
36 const int ExtensionRole = GroupRole + 1;
37 const int StandardRole = GroupRole + 2;
38 const int RenderRole = GroupRole + 3;
39 const int ParamsRole = GroupRole + 4;
40 const int EditableRole = GroupRole + 5;
41
42 RenderWidget::RenderWidget(QWidget * parent): QDialog(parent) {
43     m_view.setupUi(this);
44     setWindowTitle(i18n("Rendering"));
45     m_view.buttonDelete->setIcon(KIcon("trash-empty"));
46     m_view.buttonDelete->setToolTip(i18n("Delete profile"));
47     m_view.buttonDelete->setEnabled(false);
48
49     m_view.buttonEdit->setIcon(KIcon("document-properties"));
50     m_view.buttonEdit->setToolTip(i18n("Edit profile"));
51     m_view.buttonEdit->setEnabled(false);
52
53     m_view.buttonSave->setIcon(KIcon("document-new"));
54     m_view.buttonSave->setToolTip(i18n("Create new profile"));
55
56     m_view.buttonInfo->setIcon(KIcon("help-about"));
57
58     if (KdenliveSettings::showrenderparams()) {
59         m_view.buttonInfo->setDown(true);
60     } else m_view.advanced_params->hide();
61
62     m_view.experimentalrender->setChecked(KdenliveSettings::experimentalrender());
63
64     m_view.experimentalrender->setToolTip(i18n("Changing the size of video when rendering\nis not fully supported, you may have problems\nwith some effects or title clips, so the export\nprofiles that resize your video are marked as\nexperimental"));
65
66     connect(m_view.buttonInfo, SIGNAL(clicked()), this, SLOT(showInfoPanel()));
67
68     connect(m_view.buttonSave, SIGNAL(clicked()), this, SLOT(slotSaveProfile()));
69     connect(m_view.buttonEdit, SIGNAL(clicked()), this, SLOT(slotEditProfile()));
70     connect(m_view.buttonDelete, SIGNAL(clicked()), this, SLOT(slotDeleteProfile()));
71     connect(m_view.buttonStart, SIGNAL(clicked()), this, SLOT(slotExport()));
72     connect(m_view.abort_job, SIGNAL(clicked()), this, SLOT(slotAbortCurrentJob()));
73     connect(m_view.buttonClose, SIGNAL(clicked()), this, SLOT(hide()));
74     connect(m_view.buttonClose2, SIGNAL(clicked()), this, SLOT(hide()));
75     connect(m_view.out_file, SIGNAL(textChanged(const QString &)), this, SLOT(slotUpdateButtons()));
76     connect(m_view.format_list, SIGNAL(currentRowChanged(int)), this, SLOT(refreshView()));
77     connect(m_view.size_list, SIGNAL(currentRowChanged(int)), this, SLOT(refreshParams()));
78
79     connect(m_view.render_guide, SIGNAL(clicked(bool)), this, SLOT(slotUpdateGuideBox()));
80     connect(m_view.render_zone, SIGNAL(clicked(bool)), this, SLOT(slotUpdateGuideBox()));
81     connect(m_view.render_full, SIGNAL(clicked(bool)), this, SLOT(slotUpdateGuideBox()));
82
83     connect(m_view.guide_end, SIGNAL(activated(int)), this, SLOT(slotCheckStartGuidePosition()));
84     connect(m_view.guide_start, SIGNAL(activated(int)), this, SLOT(slotCheckEndGuidePosition()));
85
86     connect(m_view.format_selection, SIGNAL(activated(int)), this, SLOT(refreshView()));
87     connect(m_view.experimentalrender, SIGNAL(stateChanged(int)), this, SLOT(slotUpdateExperimentalRendering()));
88
89     m_view.buttonStart->setEnabled(false);
90     m_view.guides_box->setVisible(false);
91     parseProfiles();
92     m_view.splitter->setStretchFactor(1, 5);
93     m_view.splitter->setStretchFactor(0, 2);
94
95     m_view.out_file->setMode(KFile::File);
96
97     m_view.running_jobs->setItemDelegate(new RenderViewDelegate(this));
98     QHeaderView *header = m_view.running_jobs->header();
99     QFontMetrics fm = fontMetrics();
100     //header->resizeSection(0, fm.width("typical-name-for-a-torrent.torrent"));
101     header->setResizeMode(0, QHeaderView::Interactive);
102     header->resizeSection(0, fm.width("typical-name-for-a-file.torrent"));
103     header->setResizeMode(1, QHeaderView::Fixed);
104     header->resizeSection(0, width() * 2 / 3);
105     header->setResizeMode(1, QHeaderView::Interactive);
106     //header->setResizeMode(1, QHeaderView::Fixed);
107
108     focusFirstVisibleItem();
109 }
110
111 void RenderWidget::slotUpdateExperimentalRendering() {
112     KdenliveSettings::setExperimentalrender(m_view.experimentalrender->isChecked());
113     refreshView();
114 }
115
116
117 void RenderWidget::showInfoPanel() {
118     if (m_view.advanced_params->isVisible()) {
119         m_view.advanced_params->setVisible(false);
120         m_view.buttonInfo->setDown(false);
121         KdenliveSettings::setShowrenderparams(false);
122     } else {
123         m_view.advanced_params->setVisible(true);
124         m_view.buttonInfo->setDown(true);
125         KdenliveSettings::setShowrenderparams(true);
126     }
127 }
128
129 void RenderWidget::slotUpdateGuideBox() {
130     m_view.guides_box->setVisible(m_view.render_guide->isChecked());
131 }
132
133 void RenderWidget::slotCheckStartGuidePosition() {
134     if (m_view.guide_start->currentIndex() > m_view.guide_end->currentIndex())
135         m_view.guide_start->setCurrentIndex(m_view.guide_end->currentIndex());
136 }
137
138 void RenderWidget::slotCheckEndGuidePosition() {
139     if (m_view.guide_end->currentIndex() < m_view.guide_start->currentIndex())
140         m_view.guide_end->setCurrentIndex(m_view.guide_start->currentIndex());
141 }
142
143 void RenderWidget::setGuides(QDomElement guidesxml, double duration) {
144     m_view.guide_start->clear();
145     m_view.guide_end->clear();
146     QDomNodeList nodes = guidesxml.elementsByTagName("guide");
147     if (nodes.count() > 0) {
148         m_view.guide_start->addItem(i18n("Render"), "0");
149         m_view.render_guide->setEnabled(true);
150     } else m_view.render_guide->setEnabled(false);
151     for (int i = 0; i < nodes.count(); i++) {
152         QDomElement e = nodes.item(i).toElement();
153         if (!e.isNull()) {
154             m_view.guide_start->addItem(e.attribute("comment"), e.attribute("time").toDouble());
155             m_view.guide_end->addItem(e.attribute("comment"), e.attribute("time").toDouble());
156         }
157     }
158     if (nodes.count() > 0)
159         m_view.guide_end->addItem(i18n("End"), QString::number(duration));
160 }
161
162 void RenderWidget::slotUpdateButtons() {
163     if (m_view.out_file->url().isEmpty()) m_view.buttonStart->setEnabled(false);
164     else m_view.buttonStart->setEnabled(true);
165 }
166
167 void RenderWidget::slotSaveProfile() {
168     Ui::SaveProfile_UI ui;
169     QDialog *d = new QDialog(this);
170     ui.setupUi(d);
171     QString customGroup = i18n("Custom");
172     QStringList groupNames;
173     for (int i = 0; i < m_view.format_list->count(); i++)
174         groupNames.append(m_view.format_list->item(i)->text());
175     if (!groupNames.contains(customGroup)) groupNames.prepend(customGroup);
176     ui.group_name->addItems(groupNames);
177     int pos = ui.group_name->findText(customGroup);
178     ui.group_name->setCurrentIndex(pos);
179
180     ui.parameters->setText(m_view.advanced_params->toPlainText());
181     ui.extension->setText(m_view.size_list->currentItem()->data(ExtensionRole).toString());
182     ui.profile_name->setFocus();
183     if (d->exec() == QDialog::Accepted && !ui.profile_name->text().simplified().isEmpty()) {
184         QString exportFile = KStandardDirs::locateLocal("appdata", "export/customprofiles.xml");
185         QDomDocument doc;
186         QFile file(exportFile);
187         doc.setContent(&file, false);
188         file.close();
189
190         QDomElement documentElement;
191         bool groupExists = false;
192         QString groupName;
193         QString newProfileName = ui.profile_name->text().simplified();
194         QString newGroupName = ui.group_name->currentText();
195         QDomNodeList groups = doc.elementsByTagName("group");
196         int i = 0;
197         if (groups.count() == 0) {
198             QDomElement profiles = doc.createElement("profiles");
199             doc.appendChild(profiles);
200         } else while (!groups.item(i).isNull()) {
201                 documentElement = groups.item(i).toElement();
202                 groupName = documentElement.attribute("name");
203                 kDebug() << "// SAVE, PARSING FROUP: " << i << ", name: " << groupName << ", LOOK FR: " << newGroupName;
204                 if (groupName == newGroupName) {
205                     groupExists = true;
206                     break;
207                 }
208                 i++;
209             }
210         if (!groupExists) {
211             documentElement = doc.createElement("group");
212             documentElement.setAttribute("name", ui.group_name->currentText());
213             documentElement.setAttribute("renderer", "avformat");
214             doc.documentElement().appendChild(documentElement);
215         }
216         QDomElement profileElement = doc.createElement("profile");
217         profileElement.setAttribute("name", newProfileName);
218         profileElement.setAttribute("extension", ui.extension->text().simplified());
219         profileElement.setAttribute("args", ui.parameters->toPlainText().simplified());
220         documentElement.appendChild(profileElement);
221
222         //QCString save = doc.toString().utf8();
223
224         if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
225             KMessageBox::sorry(this, i18n("Unable to write to file %1", exportFile));
226             delete d;
227             return;
228         }
229         QTextStream out(&file);
230         out << doc.toString();
231         file.close();
232         parseProfiles(newGroupName, newProfileName);
233     }
234     delete d;
235 }
236
237 void RenderWidget::slotEditProfile() {
238     QListWidgetItem *item = m_view.size_list->currentItem();
239     if (!item) return;
240     QString currentGroup = m_view.format_list->currentItem()->text();
241
242     QString params = item->data(ParamsRole).toString();
243     QString extension = item->data(ExtensionRole).toString();
244     QString currentProfile = item->text();
245
246     Ui::SaveProfile_UI ui;
247     QDialog *d = new QDialog(this);
248     ui.setupUi(d);
249     QStringList groupNames;
250     for (int i = 0; i < m_view.format_list->count(); i++)
251         groupNames.append(m_view.format_list->item(i)->text());
252     if (!groupNames.contains(currentGroup)) groupNames.prepend(currentGroup);
253     ui.group_name->addItems(groupNames);
254     int pos = ui.group_name->findText(currentGroup);
255     ui.group_name->setCurrentIndex(pos);
256     ui.profile_name->setText(currentProfile);
257     ui.extension->setText(extension);
258     ui.parameters->setText(params);
259     ui.profile_name->setFocus();
260
261     if (d->exec() == QDialog::Accepted) {
262         slotDeleteProfile();
263         QString exportFile = KStandardDirs::locateLocal("appdata", "export/customprofiles.xml");
264         QDomDocument doc;
265         QFile file(exportFile);
266         doc.setContent(&file, false);
267         file.close();
268
269         QDomElement documentElement;
270         bool groupExists = false;
271         QString groupName;
272         QString newProfileName = ui.profile_name->text();
273         QString newGroupName = ui.group_name->currentText();
274         QDomNodeList groups = doc.elementsByTagName("group");
275         int i = 0;
276         if (groups.count() == 0) {
277             QDomElement profiles = doc.createElement("profiles");
278             doc.appendChild(profiles);
279         } else while (!groups.item(i).isNull()) {
280                 documentElement = groups.item(i).toElement();
281                 groupName = documentElement.attribute("name");
282                 kDebug() << "// SAVE, PARSING FROUP: " << i << ", name: " << groupName << ", LOOK FR: " << newGroupName;
283                 if (groupName == newGroupName) {
284                     groupExists = true;
285                     break;
286                 }
287                 i++;
288             }
289         if (!groupExists) {
290             documentElement = doc.createElement("group");
291             documentElement.setAttribute("name", ui.group_name->currentText());
292             documentElement.setAttribute("renderer", "avformat");
293             doc.documentElement().appendChild(documentElement);
294         }
295         QDomElement profileElement = doc.createElement("profile");
296         profileElement.setAttribute("name", newProfileName);
297         profileElement.setAttribute("extension", ui.extension->text().simplified());
298         profileElement.setAttribute("args", ui.parameters->toPlainText().simplified());
299         documentElement.appendChild(profileElement);
300
301         //QCString save = doc.toString().utf8();
302
303         if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
304             KMessageBox::sorry(this, i18n("Unable to write to file %1", exportFile));
305             delete d;
306             return;
307         }
308         QTextStream out(&file);
309         out << doc.toString();
310         file.close();
311         parseProfiles(newGroupName, newProfileName);
312     }
313     delete d;
314 }
315
316 void RenderWidget::slotDeleteProfile() {
317     QString currentGroup = m_view.format_list->currentItem()->text();
318     QString currentProfile = m_view.size_list->currentItem()->text();
319
320     QString exportFile = KStandardDirs::locateLocal("appdata", "export/customprofiles.xml");
321     QDomDocument doc;
322     QFile file(exportFile);
323     doc.setContent(&file, false);
324     file.close();
325
326     QDomElement documentElement;
327     bool groupExists = false;
328     QString groupName;
329     QDomNodeList groups = doc.elementsByTagName("group");
330     int i = 0;
331
332     while (!groups.item(i).isNull()) {
333         documentElement = groups.item(i).toElement();
334         groupName = documentElement.attribute("name");
335         if (groupName == currentGroup) {
336             QDomNodeList children = documentElement.childNodes();
337             for (int j = 0; j < children.count(); j++) {
338                 QDomElement pro = children.at(j).toElement();
339                 if (pro.attribute("name") == currentProfile) {
340                     groups.item(i).removeChild(children.at(j));
341                     if (groups.item(i).childNodes().isEmpty())
342                         doc.documentElement().removeChild(groups.item(i));
343                     break;
344                 }
345             }
346             break;
347         }
348         i++;
349     }
350
351     if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
352         KMessageBox::sorry(this, i18n("Unable to write to file %1", exportFile));
353         return;
354     }
355     QTextStream out(&file);
356     out << doc.toString();
357     file.close();
358     parseProfiles(currentGroup);
359     focusFirstVisibleItem();
360 }
361
362 void RenderWidget::updateButtons() {
363     if (!m_view.size_list->currentItem() || m_view.size_list->currentItem()->isHidden()) {
364         m_view.buttonSave->setEnabled(false);
365         m_view.buttonDelete->setEnabled(false);
366         m_view.buttonEdit->setEnabled(false);
367     } else {
368         m_view.buttonSave->setEnabled(true);
369         if (m_view.size_list->currentItem()->data(EditableRole).toString().isEmpty()) {
370             m_view.buttonDelete->setEnabled(false);
371             m_view.buttonEdit->setEnabled(false);
372         } else {
373             m_view.buttonDelete->setEnabled(true);
374             m_view.buttonEdit->setEnabled(true);
375         }
376     }
377 }
378
379
380 void RenderWidget::focusFirstVisibleItem() {
381     if (m_view.size_list->currentItem() && !m_view.size_list->currentItem()->isHidden()) {
382         updateButtons();
383         return;
384     }
385     for (uint ix = 0; ix < m_view.size_list->count(); ix++) {
386         QListWidgetItem *item = m_view.size_list->item(ix);
387         if (item && !item->isHidden()) {
388             m_view.size_list->setCurrentRow(ix);
389             break;
390         }
391     }
392     if (!m_view.size_list->currentItem()) m_view.size_list->setCurrentRow(0);
393     updateButtons();
394 }
395
396 void RenderWidget::slotExport() {
397     QListWidgetItem *item = m_view.size_list->currentItem();
398     if (!item) return;
399     QFile f(m_view.out_file->url().path());
400     if (f.exists()) {
401         if (KMessageBox::warningYesNo(this, i18n("File already exists. Do you want to overwrite it ?")) != KMessageBox::Yes)
402             return;
403     }
404     QStringList overlayargs;
405     if (m_view.tc_overlay->isChecked()) {
406         QString filterFile = KStandardDirs::locate("appdata", "metadata.properties");
407         overlayargs << "meta.attr.timecode=1" << "meta.attr.timecode.markup=#timecode";
408         overlayargs << "-attach" << "data_feed:attr_check" << "-attach";
409         overlayargs << "data_show:" + filterFile << "_fezzik=1" << "dynamic=1";
410     }
411     double startPos = -1;
412     double endPos = -1;
413     if (m_view.render_guide->isChecked()) {
414         startPos = m_view.guide_start->itemData(m_view.guide_start->currentIndex()).toDouble();
415         endPos = m_view.guide_end->itemData(m_view.guide_end->currentIndex()).toDouble();
416     }
417     QString renderArgs = m_view.advanced_params->toPlainText();
418     renderArgs.replace("%width", QString::number(m_profile.width));
419     renderArgs.replace("%height", QString::number(m_profile.height));
420     renderArgs.replace("%dar", "@" + QString::number(m_profile.display_aspect_num) + "/" + QString::number(m_profile.display_aspect_den));
421     if (m_view.force_progressive->checkState() == Qt::Checked) renderArgs.append(" progressive=1");
422     else if (m_view.force_progressive->checkState() == Qt::Unchecked) renderArgs.append(" progressive=0");
423
424     // Check if the rendering profile is different from project profile,
425     // in which case we need to use the producer_comsumer from MLT
426     bool resizeProfile = false;
427
428     QString std = item->data(ParamsRole).toString();
429     if (resizeProfile == false && std.contains(" s=")) {
430         QString subsize = std.section(" s=", 1, 1);
431         subsize = subsize.section(' ', 0, 0).toLower();
432         if (subsize != "%widthx%height") {
433             const QString currentSize = QString::number(m_profile.width) + 'x' + QString::number(m_profile.height);
434             if (subsize != currentSize) resizeProfile = true;
435         }
436     }
437
438     emit doRender(m_view.out_file->url().path(), item->data(RenderRole).toString(), overlayargs, renderArgs.simplified().split(' '), m_view.render_zone->isChecked(), m_view.play_after->isChecked(), startPos, endPos, resizeProfile);
439     m_view.tabWidget->setCurrentIndex(1);
440 }
441
442 void RenderWidget::setProfile(MltVideoProfile profile) {
443     m_profile = profile;
444     //WARNING: this way to tell the video standard is a bit hackish...
445     if (m_profile.description.contains("pal", Qt::CaseInsensitive) || m_profile.description.contains("25", Qt::CaseInsensitive) || m_profile.description.contains("50", Qt::CaseInsensitive)) m_view.format_selection->setCurrentIndex(0);
446     else m_view.format_selection->setCurrentIndex(1);
447     m_view.force_progressive->setCheckState(Qt::PartiallyChecked);
448     refreshView();
449 }
450
451 void RenderWidget::refreshView() {
452     m_view.size_list->blockSignals(true);
453     QListWidgetItem *item = m_view.format_list->currentItem();
454     if (!item) {
455         m_view.format_list->setCurrentRow(0);
456         item = m_view.format_list->currentItem();
457     }
458     if (!item) return;
459     QString std;
460     QString group = item->text();
461     QListWidgetItem *sizeItem;
462     bool firstSelected = false;
463     const QStringList formatsList = KdenliveSettings::supportedformats();
464     const QStringList vcodecsList = KdenliveSettings::videocodecs();
465     const QStringList acodecsList = KdenliveSettings::audiocodecs();
466     for (int i = 0; i < m_view.size_list->count(); i++) {
467         sizeItem = m_view.size_list->item(i);
468         if (sizeItem->data(GroupRole) == group) {
469             std = sizeItem->data(StandardRole).toString();
470             if (!std.isEmpty()) {
471                 if (std.contains("PAL", Qt::CaseInsensitive)) sizeItem->setHidden(m_view.format_selection->currentIndex() != 0);
472                 else if (std.contains("NTSC", Qt::CaseInsensitive)) sizeItem->setHidden(m_view.format_selection->currentIndex() != 1);
473             } else {
474                 sizeItem->setHidden(false);
475                 if (!firstSelected) m_view.size_list->setCurrentItem(sizeItem);
476                 firstSelected = true;
477             }
478             if (!KdenliveSettings::experimentalrender() && !sizeItem->isHidden()) {
479                 // hide experimental codecs (which do resize the video)
480                 std = sizeItem->data(ParamsRole).toString();
481                 if (std.contains(" s=")) {
482                     QString subsize = std.section(" s=", 1, 1);
483                     subsize = subsize.section(' ', 0, 0).toLower();
484                     if (subsize != "%widthx%height") {
485                         const QString currentSize = QString::number(m_profile.width) + 'x' + QString::number(m_profile.height);
486                         if (subsize != currentSize) sizeItem->setHidden(true);
487                     }
488                 }
489             }
490             if (!sizeItem->isHidden()) {
491                 // Make sure the selected profile uses an installed avformat codec / format
492                 std = sizeItem->data(ParamsRole).toString();
493
494                 if (!formatsList.isEmpty()) {
495                     QString format;
496                     if (std.startsWith("f=")) format = std.section("f=", 1, 1);
497                     else if (std.contains(" f=")) format = std.section(" f=", 1, 1);
498                     if (!format.isEmpty()) {
499                         format = format.section(' ', 0, 0).toLower();
500                         if (!formatsList.contains(format)) {
501                             kDebug() << "*****  UNSUPPORTED F: " << format;
502                             sizeItem->setHidden(true);
503                         }
504                     }
505                 }
506                 if (!acodecsList.isEmpty() && !sizeItem->isHidden()) {
507                     QString format;
508                     if (std.startsWith("acodec=")) format = std.section("acodec=", 1, 1);
509                     else if (std.contains(" acodec=")) format = std.section(" acodec=", 1, 1);
510                     if (!format.isEmpty()) {
511                         format = format.section(' ', 0, 0).toLower();
512                         if (!acodecsList.contains(format)) {
513                             kDebug() << "*****  UNSUPPORTED ACODEC: " << format;
514                             sizeItem->setHidden(true);
515                         }
516                     }
517                 }
518                 if (!vcodecsList.isEmpty() && !sizeItem->isHidden()) {
519                     QString format;
520                     if (std.startsWith("vcodec=")) format = std.section("vcodec=", 1, 1);
521                     else if (std.contains(" vcodec=")) format = std.section(" vcodec=", 1, 1);
522                     if (!format.isEmpty()) {
523                         format = format.section(' ', 0, 0).toLower();
524                         if (!vcodecsList.contains(format)) {
525                             kDebug() << "*****  UNSUPPORTED VCODEC: " << format;
526                             sizeItem->setHidden(true);
527                         }
528                     }
529                 }
530             }
531         } else sizeItem->setHidden(true);
532     }
533     focusFirstVisibleItem();
534     m_view.size_list->blockSignals(false);
535     refreshParams();
536 }
537
538 void RenderWidget::refreshParams() {
539     QListWidgetItem *item = m_view.size_list->currentItem();
540     if (!item || item->isHidden()) {
541         m_view.advanced_params->clear();
542         m_view.buttonStart->setEnabled(false);
543         return;
544     }
545     QString params = item->data(ParamsRole).toString();
546     QString extension = item->data(ExtensionRole).toString();
547     m_view.advanced_params->setPlainText(params);
548     m_view.advanced_params->setToolTip(params);
549     KUrl url = m_view.out_file->url();
550     if (!url.isEmpty()) {
551         QString path = url.path();
552         int pos = path.lastIndexOf('.') + 1;
553         if (pos == 0) path.append('.') + extension;
554         else path = path.left(pos) + extension;
555         m_view.out_file->setUrl(KUrl(path));
556     } else {
557         m_view.out_file->setUrl(KUrl(QDir::homePath() + "/untitled." + extension));
558     }
559     m_view.out_file->setFilter("*." + extension);
560
561     if (item->data(EditableRole).toString().isEmpty()) {
562         m_view.buttonDelete->setEnabled(false);
563         m_view.buttonEdit->setEnabled(false);
564     } else {
565         m_view.buttonDelete->setEnabled(true);
566         m_view.buttonEdit->setEnabled(true);
567     }
568     m_view.buttonStart->setEnabled(true);
569 }
570
571 void RenderWidget::parseProfiles(QString group, QString profile) {
572     m_view.size_list->clear();
573     m_view.format_list->clear();
574     QString exportFile = KStandardDirs::locate("appdata", "export/profiles.xml");
575     parseFile(exportFile, false);
576     exportFile = KStandardDirs::locateLocal("appdata", "export/customprofiles.xml");
577     if (QFile::exists(exportFile)) parseFile(exportFile, true);
578     refreshView();
579     QList<QListWidgetItem *> child;
580     child = m_view.format_list->findItems(group, Qt::MatchExactly);
581     if (!child.isEmpty()) m_view.format_list->setCurrentItem(child.at(0));
582     child = m_view.size_list->findItems(profile, Qt::MatchExactly);
583     if (!child.isEmpty()) m_view.size_list->setCurrentItem(child.at(0));
584 }
585
586 void RenderWidget::parseFile(QString exportFile, bool editable) {
587     QDomDocument doc;
588     QFile file(exportFile);
589     doc.setContent(&file, false);
590     file.close();
591     QDomElement documentElement;
592     QDomElement profileElement;
593     QDomNodeList groups = doc.elementsByTagName("group");
594
595     if (groups.count() == 0) {
596         kDebug() << "// Export file: " << exportFile << " IS BROKEN";
597         return;
598     }
599
600     int i = 0;
601     QString groupName;
602     QString profileName;
603     QString extension;
604     QString prof_extension;
605     QString renderer;
606     QString params;
607     QString standard;
608     QListWidgetItem *item;
609     while (!groups.item(i).isNull()) {
610         documentElement = groups.item(i).toElement();
611         groupName = documentElement.attribute("name", QString::null);
612         extension = documentElement.attribute("extension", QString::null);
613         renderer = documentElement.attribute("renderer", QString::null);
614         if (m_view.format_list->findItems(groupName, Qt::MatchExactly).isEmpty())
615             new QListWidgetItem(groupName, m_view.format_list);
616
617         QDomNode n = groups.item(i).firstChild();
618         while (!n.isNull()) {
619             profileElement = n.toElement();
620             profileName = profileElement.attribute("name");
621             standard = profileElement.attribute("standard");
622             params = profileElement.attribute("args");
623             prof_extension = profileElement.attribute("extension");
624             if (!prof_extension.isEmpty()) extension = prof_extension;
625             item = new QListWidgetItem(profileName, m_view.size_list);
626             item->setData(GroupRole, groupName);
627             item->setData(ExtensionRole, extension);
628             item->setData(RenderRole, renderer);
629             item->setData(StandardRole, standard);
630             item->setData(ParamsRole, params);
631             if (editable) item->setData(EditableRole, "true");
632             n = n.nextSibling();
633         }
634
635         i++;
636     }
637 }
638
639 void RenderWidget::setRenderJob(const QString &dest, int progress) {
640     QList<QTreeWidgetItem *> existing = m_view.running_jobs->findItems(dest, Qt::MatchExactly);
641     if (!existing.isEmpty()) {
642         if (progress == -1) {
643             // Job finished successfully
644             existing.at(0)->setIcon(0, KIcon("dialog-ok"));
645             existing.at(0)->setData(1, Qt::UserRole, 100);
646         } else if (progress == -2) {
647             // Rendering crashed
648             existing.at(0)->setIcon(0, KIcon("dialog-close"));
649             existing.at(0)->setData(1, Qt::UserRole, 0);
650         } else if (progress == -3) {
651             // User aborted job
652             existing.at(0)->setIcon(0, KIcon("dialog-close"));
653             existing.at(0)->setData(1, Qt::UserRole, 100);
654         } else existing.at(0)->setData(1, Qt::UserRole, progress);
655         return;
656     }
657     QTreeWidgetItem *item = new QTreeWidgetItem(m_view.running_jobs, QStringList() << dest << QString());
658     if (progress == -1) {
659         // Job finished successfully
660         item->setIcon(0, KIcon("dialog-ok"));
661         item->setData(1, Qt::UserRole, 100);
662     } else if (progress == -2) {
663         // Rendering crashed
664         item->setIcon(0, KIcon("dialog-close"));
665         item->setData(1, Qt::UserRole, 0);
666     } else if (progress == -3) {
667         // User aborted job
668         item->setIcon(0, KIcon("dialog-close"));
669         item->setData(1, Qt::UserRole, 100);
670     } else item->setData(1, Qt::UserRole, progress);
671
672 }
673
674 void RenderWidget::slotAbortCurrentJob() {
675     QTreeWidgetItem *current = m_view.running_jobs->currentItem();
676     if (current) emit abortProcess(current->text(0));
677 }
678
679 #include "renderwidget.moc"