]> git.sesse.net Git - kdenlive/blob - src/renderwidget.cpp
Allow editing of custom rendering profiles
[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     connect(m_view.buttonSave, SIGNAL(clicked()), this, SLOT(slotSaveProfile()));
53     connect(m_view.buttonEdit, SIGNAL(clicked()), this, SLOT(slotEditProfile()));
54     connect(m_view.buttonDelete, SIGNAL(clicked()), this, SLOT(slotDeleteProfile()));
55     connect(m_view.buttonStart, SIGNAL(clicked()), this, SLOT(slotExport()));
56     connect(m_view.out_file, SIGNAL(textChanged(const QString &)), this, SLOT(slotUpdateButtons()));
57     connect(m_view.format_list, SIGNAL(currentRowChanged(int)), this, SLOT(refreshView()));
58     connect(m_view.size_list, SIGNAL(currentRowChanged(int)), this, SLOT(refreshParams()));
59
60     m_view.buttonStart->setEnabled(false);
61     parseProfiles();
62 }
63
64 void RenderWidget::slotUpdateButtons() {
65     if (m_view.out_file->url().isEmpty()) m_view.buttonStart->setEnabled(false);
66     else m_view.buttonStart->setEnabled(true);
67 }
68
69 void RenderWidget::slotSaveProfile() {
70     Ui::SaveProfile_UI ui;
71     QDialog *d = new QDialog(this);
72     ui.setupUi(d);
73     QString customGroup = i18n("Custom");
74     QStringList groupNames;
75     for (int i = 0; i < m_view.format_list->count(); i++)
76         groupNames.append(m_view.format_list->item(i)->text());
77     if (!groupNames.contains(customGroup)) groupNames.prepend(customGroup);
78     ui.group_name->addItems(groupNames);
79     int pos = ui.group_name->findText(customGroup);
80     ui.group_name->setCurrentIndex(pos);
81
82     ui.parameters->setText(m_view.advanced_params->text());
83     ui.extension->setText(m_view.size_list->currentItem()->data(ExtensionRole).toString());
84     ui.profile_name->setFocus();
85     if (d->exec() == QDialog::Accepted) {
86         QString exportFile = KStandardDirs::locateLocal("data", "kdenlive/export/customprofiles.xml");
87         QDomDocument doc;
88         QFile file(exportFile);
89         doc.setContent(&file, false);
90         file.close();
91
92         QDomElement documentElement;
93         bool groupExists = false;
94         QString groupName;
95         QString newProfileName = ui.profile_name->text();
96         QString newGroupName = ui.group_name->currentText();
97         QDomNodeList groups = doc.elementsByTagName("group");
98         int i = 0;
99         if (groups.count() == 0) {
100             QDomElement profiles = doc.createElement("profiles");
101             doc.appendChild(profiles);
102         } else while (!groups.item(i).isNull()) {
103                 documentElement = groups.item(i).toElement();
104                 groupName = documentElement.attribute("name");
105                 kDebug() << "// SAVE, PARSING FROUP: " << i << ", name: " << groupName << ", LOOK FR: " << newGroupName;
106                 if (groupName == newGroupName) {
107                     groupExists = true;
108                     break;
109                 }
110                 i++;
111             }
112         if (!groupExists) {
113             documentElement = doc.createElement("group");
114             documentElement.setAttribute("name", ui.group_name->currentText());
115             documentElement.setAttribute("renderer", "avformat");
116             doc.documentElement().appendChild(documentElement);
117         }
118         QDomElement profileElement = doc.createElement("profile");
119         profileElement.setAttribute("name", newProfileName);
120         profileElement.setAttribute("extension", ui.extension->text().simplified());
121         profileElement.setAttribute("args", ui.parameters->text().simplified());
122         documentElement.appendChild(profileElement);
123
124         //QCString save = doc.toString().utf8();
125
126         if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
127             KMessageBox::sorry(this, i18n("Unable to write to file %1", exportFile));
128             delete d;
129             return;
130         }
131         QTextStream out(&file);
132         out << doc.toString();
133         file.close();
134         parseProfiles(newGroupName, newProfileName);
135     }
136     delete d;
137 }
138
139 void RenderWidget::slotEditProfile() {
140     QListWidgetItem *item = m_view.size_list->currentItem();
141     if (!item) return;
142     QString currentGroup = m_view.format_list->currentItem()->text();
143
144     QString params = item->data(ParamsRole).toString();
145     QString extension = item->data(ExtensionRole).toString();
146     QString currentProfile = item->text();
147
148     Ui::SaveProfile_UI ui;
149     QDialog *d = new QDialog(this);
150     ui.setupUi(d);
151     QStringList groupNames;
152     for (int i = 0; i < m_view.format_list->count(); i++)
153         groupNames.append(m_view.format_list->item(i)->text());
154     if (!groupNames.contains(currentGroup)) groupNames.prepend(currentGroup);
155     ui.group_name->addItems(groupNames);
156     int pos = ui.group_name->findText(currentGroup);
157     ui.group_name->setCurrentIndex(pos);
158     ui.profile_name->setText(currentProfile);
159     ui.extension->setText(extension);
160     ui.parameters->setText(params);
161     ui.profile_name->setFocus();
162
163     if (d->exec() == QDialog::Accepted) {
164         slotDeleteProfile();
165         QString exportFile = KStandardDirs::locateLocal("data", "kdenlive/export/customprofiles.xml");
166         QDomDocument doc;
167         QFile file(exportFile);
168         doc.setContent(&file, false);
169         file.close();
170
171         QDomElement documentElement;
172         bool groupExists = false;
173         QString groupName;
174         QString newProfileName = ui.profile_name->text();
175         QString newGroupName = ui.group_name->currentText();
176         QDomNodeList groups = doc.elementsByTagName("group");
177         int i = 0;
178         if (groups.count() == 0) {
179             QDomElement profiles = doc.createElement("profiles");
180             doc.appendChild(profiles);
181         } else while (!groups.item(i).isNull()) {
182                 documentElement = groups.item(i).toElement();
183                 groupName = documentElement.attribute("name");
184                 kDebug() << "// SAVE, PARSING FROUP: " << i << ", name: " << groupName << ", LOOK FR: " << newGroupName;
185                 if (groupName == newGroupName) {
186                     groupExists = true;
187                     break;
188                 }
189                 i++;
190             }
191         if (!groupExists) {
192             documentElement = doc.createElement("group");
193             documentElement.setAttribute("name", ui.group_name->currentText());
194             documentElement.setAttribute("renderer", "avformat");
195             doc.documentElement().appendChild(documentElement);
196         }
197         QDomElement profileElement = doc.createElement("profile");
198         profileElement.setAttribute("name", newProfileName);
199         profileElement.setAttribute("extension", ui.extension->text().simplified());
200         profileElement.setAttribute("args", ui.parameters->text().simplified());
201         documentElement.appendChild(profileElement);
202
203         //QCString save = doc.toString().utf8();
204
205         if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
206             KMessageBox::sorry(this, i18n("Unable to write to file %1", exportFile));
207             delete d;
208             return;
209         }
210         QTextStream out(&file);
211         out << doc.toString();
212         file.close();
213         parseProfiles(newGroupName, newProfileName);
214     }
215     delete d;
216 }
217
218 void RenderWidget::slotDeleteProfile() {
219     QString currentGroup = m_view.format_list->currentItem()->text();
220     QString currentProfile = m_view.size_list->currentItem()->text();
221
222     QString exportFile = KStandardDirs::locateLocal("data", "kdenlive/export/customprofiles.xml");
223     QDomDocument doc;
224     QFile file(exportFile);
225     doc.setContent(&file, false);
226     file.close();
227
228     QDomElement documentElement;
229     bool groupExists = false;
230     QString groupName;
231     QDomNodeList groups = doc.elementsByTagName("group");
232     int i = 0;
233
234     while (!groups.item(i).isNull()) {
235         documentElement = groups.item(i).toElement();
236         groupName = documentElement.attribute("name");
237         if (groupName == currentGroup) {
238             QDomNodeList children = documentElement.childNodes();
239             for (int j = 0; j < children.count(); j++) {
240                 QDomElement pro = children.at(j).toElement();
241                 if (pro.attribute("name") == currentProfile) {
242                     groups.item(i).removeChild(children.at(j));
243                     if (groups.item(i).childNodes().isEmpty())
244                         doc.documentElement().removeChild(groups.item(i));
245                     break;
246                 }
247             }
248             break;
249         }
250         i++;
251     }
252
253     if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
254         KMessageBox::sorry(this, i18n("Unable to write to file %1", exportFile));
255         return;
256     }
257     QTextStream out(&file);
258     out << doc.toString();
259     file.close();
260     parseProfiles(currentGroup);
261 }
262
263 void RenderWidget::slotExport() {
264     QListWidgetItem *item = m_view.size_list->currentItem();
265     if (!item) return;
266     QFile f(m_view.out_file->url().path());
267     if (f.exists()) {
268         if (KMessageBox::warningYesNo(this, i18n("File already exists. Doy you want to overwrite it ?")) != KMessageBox::Yes)
269             return;
270     }
271     emit doRender(m_view.out_file->url().path(), item->data(RenderRole).toString(), m_view.advanced_params->text().split(' '), m_view.zone_only->isChecked(), m_view.play_after->isChecked());
272 }
273
274 void RenderWidget::setDocumentStandard(QString std) {
275     m_standard = std;
276     refreshView();
277 }
278
279 void RenderWidget::refreshView() {
280     QListWidgetItem *item = m_view.format_list->currentItem();
281     if (!item) {
282         m_view.format_list->setCurrentRow(0);
283         item = m_view.format_list->currentItem();
284     }
285     if (!item) return;
286     QString std;
287     QString group = item->text();
288     QListWidgetItem *sizeItem;
289     bool firstSelected = false;
290     for (int i = 0; i < m_view.size_list->count(); i++) {
291         sizeItem = m_view.size_list->item(i);
292         std = sizeItem->data(StandardRole).toString();
293         if (!std.isEmpty() && !std.contains(m_standard, Qt::CaseInsensitive)) sizeItem->setHidden(true);
294         else if (sizeItem->data(GroupRole) == group) {
295             sizeItem->setHidden(false);
296             if (!firstSelected) m_view.size_list->setCurrentItem(sizeItem);
297             firstSelected = true;
298         } else sizeItem->setHidden(true);
299     }
300
301 }
302
303 void RenderWidget::refreshParams() {
304     QListWidgetItem *item = m_view.size_list->currentItem();
305     if (!item) return;
306     QString params = item->data(ParamsRole).toString();
307     QString extension = item->data(ExtensionRole).toString();
308     m_view.advanced_params->setText(params);
309     m_view.advanced_params->setToolTip(params);
310     KUrl url = m_view.out_file->url();
311     if (!url.isEmpty()) {
312         QString path = url.path();
313         int pos = path.lastIndexOf('.') + 1;
314         if (pos == 0) path.append('.') + extension;
315         else path = path.left(pos) + extension;
316         m_view.out_file->setUrl(KUrl(path));
317     } else {
318         m_view.out_file->setUrl(KUrl(QDir::homePath() + "/untitled." + extension));
319     }
320
321     if (item->data(EditableRole).toString().isEmpty()) {
322         m_view.buttonDelete->setEnabled(false);
323         m_view.buttonEdit->setEnabled(false);
324     }
325     else {
326         m_view.buttonDelete->setEnabled(true);
327         m_view.buttonEdit->setEnabled(true);
328     }
329 }
330
331 void RenderWidget::parseProfiles(QString group, QString profile) {
332     m_view.size_list->clear();
333     m_view.format_list->clear();
334     QString exportFile = KStandardDirs::locate("data", "kdenlive/export/profiles.xml");
335     parseFile(exportFile, false);
336     exportFile = KStandardDirs::locateLocal("data", "kdenlive/export/customprofiles.xml");
337     parseFile(exportFile, true);
338     refreshView();
339     QList<QListWidgetItem *> child;
340     child = m_view.format_list->findItems(group, Qt::MatchExactly);
341     if (!child.isEmpty()) m_view.format_list->setCurrentItem(child.at(0));
342     child = m_view.size_list->findItems(profile, Qt::MatchExactly);
343     if (!child.isEmpty()) m_view.size_list->setCurrentItem(child.at(0));
344 }
345
346 void RenderWidget::parseFile(QString exportFile, bool editable) {
347     QDomDocument doc;
348     QFile file(exportFile);
349     doc.setContent(&file, false);
350     file.close();
351     QDomElement documentElement;
352     QDomElement profileElement;
353     QDomNodeList groups = doc.elementsByTagName("group");
354
355     if (groups.count() == 0) {
356         kDebug() << "// Export file: " << exportFile << " IS BROKEN";
357         return;
358     }
359
360     int i = 0;
361     QString groupName;
362     QString profileName;
363     QString extension;
364     QString prof_extension;
365     QString renderer;
366     QString params;
367     QString standard;
368     QListWidgetItem *item;
369     while (!groups.item(i).isNull()) {
370         documentElement = groups.item(i).toElement();
371         groupName = documentElement.attribute("name", QString::null);
372         extension = documentElement.attribute("extension", QString::null);
373         renderer = documentElement.attribute("renderer", QString::null);
374         if (m_view.format_list->findItems(groupName, Qt::MatchExactly).isEmpty())
375             new QListWidgetItem(groupName, m_view.format_list);
376
377         QDomNode n = groups.item(i).firstChild();
378         while (!n.isNull()) {
379             profileElement = n.toElement();
380             profileName = profileElement.attribute("name");
381             standard = profileElement.attribute("standard");
382             params = profileElement.attribute("args");
383             prof_extension = profileElement.attribute("extension");
384             if (!prof_extension.isEmpty()) extension = prof_extension;
385             item = new QListWidgetItem(profileName, m_view.size_list);
386             item->setData(GroupRole, groupName);
387             item->setData(ExtensionRole, extension);
388             item->setData(RenderRole, renderer);
389             item->setData(StandardRole, standard);
390             item->setData(ParamsRole, params);
391             if (editable) item->setData(EditableRole, "true");
392             n = n.nextSibling();
393         }
394
395         i++;
396     }
397 }
398
399
400
401 #include "renderwidget.moc"
402
403