1 /***************************************************************************
2 * Copyright (C) 2008 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
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. *
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. *
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 ***************************************************************************/
20 #include "profilesdialog.h"
21 #include "kdenlivesettings.h"
23 #include <KStandardDirs>
25 #include <KMessageBox>
26 #include <KIO/NetAccess>
29 #include <QCloseEvent>
31 ProfilesDialog::ProfilesDialog(QWidget * parent) :
33 m_profileIsModified(false),
34 m_isCustomProfile(false)
38 QStringList profilesFilter;
39 profilesFilter << "*";
41 m_view.button_delete->setIcon(KIcon("trash-empty"));
42 m_view.button_delete->setToolTip(i18n("Delete profile"));
43 m_view.button_save->setIcon(KIcon("document-save"));
44 m_view.button_save->setToolTip(i18n("Save profile"));
45 m_view.button_create->setIcon(KIcon("document-new"));
46 m_view.button_create->setToolTip(i18n("Create new profile"));
50 connect(m_view.profiles_list, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateDisplay()));
51 connect(m_view.button_create, SIGNAL(clicked()), this, SLOT(slotCreateProfile()));
52 connect(m_view.button_save, SIGNAL(clicked()), this, SLOT(slotSaveProfile()));
53 connect(m_view.button_delete, SIGNAL(clicked()), this, SLOT(slotDeleteProfile()));
54 connect(m_view.button_default, SIGNAL(clicked()), this, SLOT(slotSetDefaultProfile()));
56 connect(m_view.description, SIGNAL(textChanged(const QString &)), this, SLOT(slotProfileEdited()));
57 connect(m_view.frame_num, SIGNAL(valueChanged(int)), this, SLOT(slotProfileEdited()));
58 connect(m_view.frame_den, SIGNAL(valueChanged(int)), this, SLOT(slotProfileEdited()));
59 connect(m_view.aspect_num, SIGNAL(valueChanged(int)), this, SLOT(slotProfileEdited()));
60 connect(m_view.aspect_den, SIGNAL(valueChanged(int)), this, SLOT(slotProfileEdited()));
61 connect(m_view.display_num, SIGNAL(valueChanged(int)), this, SLOT(slotProfileEdited()));
62 connect(m_view.display_den, SIGNAL(valueChanged(int)), this, SLOT(slotProfileEdited()));
63 connect(m_view.progressive, SIGNAL(stateChanged(int)), this, SLOT(slotProfileEdited()));
64 connect(m_view.size_h, SIGNAL(valueChanged(int)), this, SLOT(slotProfileEdited()));
65 connect(m_view.size_w, SIGNAL(valueChanged(int)), this, SLOT(slotProfileEdited()));
68 void ProfilesDialog::slotProfileEdited()
70 m_profileIsModified = true;
73 void ProfilesDialog::fillList(const QString selectedProfile)
75 // List the Mlt profiles
76 m_view.profiles_list->clear();
77 QMap <QString, QString> profilesInfo = ProfilesDialog::getProfilesInfo();
78 QMapIterator<QString, QString> i(profilesInfo);
81 m_view.profiles_list->addItem(i.key(), i.value());
84 if(!KdenliveSettings::default_profile().isEmpty()) {
85 for(int i = 0; i < m_view.profiles_list->count(); i++) {
86 if(m_view.profiles_list->itemData(i).toString() == KdenliveSettings::default_profile()) {
87 m_view.profiles_list->setCurrentIndex(i);
92 int ix = m_view.profiles_list->findText(selectedProfile);
93 if(ix != -1) m_view.profiles_list->setCurrentIndex(ix);
94 m_selectedProfileIndex = m_view.profiles_list->currentIndex();
97 void ProfilesDialog::accept()
99 if(askForSave()) QDialog::accept();
102 void ProfilesDialog::closeEvent(QCloseEvent *event)
111 bool ProfilesDialog::askForSave()
113 if(!m_profileIsModified) return true;
114 if(KMessageBox::questionYesNo(this, i18n("The custom profile was modified, do you want to save it?")) != KMessageBox::Yes) return true;
115 return slotSaveProfile();
118 void ProfilesDialog::slotCreateProfile()
120 m_view.button_delete->setEnabled(false);
121 m_view.button_create->setEnabled(false);
122 m_view.button_save->setEnabled(true);
123 m_view.properties->setEnabled(true);
126 void ProfilesDialog::slotSetDefaultProfile()
128 int ix = m_view.profiles_list->currentIndex();
129 QString path = m_view.profiles_list->itemData(ix).toString();
130 if(!path.isEmpty()) KdenliveSettings::setDefault_profile(path);
133 bool ProfilesDialog::slotSaveProfile()
135 const QString profileDesc = m_view.description->text();
136 int ix = m_view.profiles_list->findText(profileDesc);
138 // this profile name already exists
139 const QString path = m_view.profiles_list->itemData(ix).toString();
140 if(!path.contains('/')) {
141 KMessageBox::sorry(this, i18n("A profile with same name already exists in MLT's default profiles, please choose another description for your custom profile."));
147 QString customName = "profiles/customprofile";
148 QString profilePath = KStandardDirs::locateLocal("appdata", customName + QString::number(i));
149 kDebug() << " TYING PROFILE FILE: " << profilePath;
150 while(KIO::NetAccess::exists(KUrl(profilePath), KIO::NetAccess::SourceSide, this)) {
152 profilePath = KStandardDirs::locateLocal("appdata", customName + QString::number(i));
154 saveProfile(profilePath);
156 m_profileIsModified = false;
157 fillList(profileDesc);
158 m_view.button_create->setEnabled(true);
162 void ProfilesDialog::saveProfile(const QString path)
165 if(!file.open(QIODevice::WriteOnly)) {
166 KMessageBox::sorry(this, i18n("Cannot write to file %1", path));
169 QTextStream out(&file);
170 out << "description=" << m_view.description->text() << "\n" << "frame_rate_num=" << m_view.frame_num->value() << "\n" << "frame_rate_den=" << m_view.frame_den->value() << "\n" << "width=" << m_view.size_w->value() << "\n" << "height=" << m_view.size_h->value() << "\n" << "progressive=" << m_view.progressive->isChecked() << "\n" << "sample_aspect_num=" << m_view.aspect_num->value() << "\n" << "sample_aspect_den=" << m_view.aspect_den->value() << "\n" << "display_aspect_num=" << m_view.display_num->value() << "\n" << "display_aspect_den=" << m_view.display_den->value() << "\n";
171 if(file.error() != QFile::NoError) {
172 KMessageBox::error(this, i18n("Cannot write to file %1", path));
177 void ProfilesDialog::slotDeleteProfile()
179 const QString path = m_view.profiles_list->itemData(m_view.profiles_list->currentIndex()).toString();
180 if(path.contains('/')) {
181 KIO::NetAccess::del(KUrl(path), this);
183 } else kDebug() << "//// Cannot delete profile " << path << ", does not seem to be custom one";
187 MltVideoProfile ProfilesDialog::getVideoProfile(QString name)
189 MltVideoProfile result;
190 QStringList profilesNames;
191 QStringList profilesFiles;
192 QStringList profilesFilter;
193 profilesFilter << "*";
195 bool isCustom = false;
196 if(name.contains('/')) isCustom = true;
199 // List the Mlt profiles
200 profilesFiles = QDir(KdenliveSettings::mltpath()).entryList(profilesFilter, QDir::Files);
201 if(profilesFiles.contains(name)) path = KdenliveSettings::mltpath() + name;
203 if(isCustom || path.isEmpty()) {
207 if(path.isEmpty() || !QFile::exists(path)) {
208 if(name == "dv_pal") {
209 kDebug() << "!!! WARNING, COULD NOT FIND DEFAULT MLT PROFILE";
212 if(name == KdenliveSettings::default_profile()) KdenliveSettings::setDefault_profile("dv_pal");
213 kDebug() << "// WARNING, COULD NOT FIND PROFILE " << name;
216 KConfig confFile(path, KConfig::SimpleConfig);
218 result.description = confFile.entryMap().value("description");
219 result.frame_rate_num = confFile.entryMap().value("frame_rate_num").toInt();
220 result.frame_rate_den = confFile.entryMap().value("frame_rate_den").toInt();
221 result.width = confFile.entryMap().value("width").toInt();
222 result.height = confFile.entryMap().value("height").toInt();
223 result.progressive = confFile.entryMap().value("progressive").toInt();
224 result.sample_aspect_num = confFile.entryMap().value("sample_aspect_num").toInt();
225 result.sample_aspect_den = confFile.entryMap().value("sample_aspect_den").toInt();
226 result.display_aspect_num = confFile.entryMap().value("display_aspect_num").toInt();
227 result.display_aspect_den = confFile.entryMap().value("display_aspect_den").toInt();
232 double ProfilesDialog::getStringEval(const MltVideoProfile &profile, QString eval)
235 eval.replace("%width", QString::number(profile.width));
236 eval.replace("%height", QString::number(profile.height));
237 if(eval.contains('/')) result = (double) eval.section('/', 0, 0).toInt() / eval.section('/', 1, 1).toInt();
238 else if(eval.contains('*')) result = (double) eval.section('*', 0, 0).toInt() * eval.section('*', 1, 1).toInt();
239 else if(eval.contains('+')) result = (double) eval.section('+', 0, 0).toInt() + eval.section('+', 1, 1).toInt();
240 else if(eval.contains('-')) result = (double) eval.section('-', 0, 0).toInt() - eval.section('-', 1, 1).toInt();
241 else result = eval.toDouble();
247 bool ProfilesDialog::existingProfileDescription(const QString &desc)
249 QStringList profilesFilter;
250 profilesFilter << "*";
252 // List the Mlt profiles
253 QStringList profilesFiles = QDir(KdenliveSettings::mltpath()).entryList(profilesFilter, QDir::Files);
254 for(int i = 0; i < profilesFiles.size(); ++i) {
255 KConfig confFile(KdenliveSettings::mltpath() + profilesFiles.at(i), KConfig::SimpleConfig);
256 if(desc == confFile.entryMap().value("description")) return true;
259 // List custom profiles
260 QStringList customProfiles = KGlobal::dirs()->findDirs("appdata", "profiles");
261 for(int i = 0; i < customProfiles.size(); ++i) {
262 profilesFiles = QDir(customProfiles.at(i)).entryList(profilesFilter, QDir::Files);
263 for(int j = 0; j < profilesFiles.size(); ++j) {
264 KConfig confFile(customProfiles.at(i) + profilesFiles.at(j), KConfig::SimpleConfig);
265 if(desc == confFile.entryMap().value("description")) return true;
272 QString ProfilesDialog::existingProfile(MltVideoProfile profile)
274 // Check if the profile has a matching entry in existing ones
275 QStringList profilesFilter;
276 profilesFilter << "*";
278 // Check the Mlt profiles
279 QStringList profilesFiles = QDir(KdenliveSettings::mltpath()).entryList(profilesFilter, QDir::Files);
280 for(int i = 0; i < profilesFiles.size(); ++i) {
281 KConfig confFile(KdenliveSettings::mltpath() + profilesFiles.at(i), KConfig::SimpleConfig);
282 if(profile.display_aspect_den != confFile.entryMap().value("display_aspect_den").toInt()) continue;
283 if(profile.display_aspect_num != confFile.entryMap().value("display_aspect_num").toInt()) continue;
284 if(profile.sample_aspect_den != confFile.entryMap().value("sample_aspect_den").toInt()) continue;
285 if(profile.sample_aspect_num != confFile.entryMap().value("sample_aspect_num").toInt()) continue;
286 if(profile.width != confFile.entryMap().value("width").toInt()) continue;
287 if(profile.height != confFile.entryMap().value("height").toInt()) continue;
288 if(profile.frame_rate_den != confFile.entryMap().value("frame_rate_den").toInt()) continue;
289 if(profile.frame_rate_num != confFile.entryMap().value("frame_rate_num").toInt()) continue;
290 if(profile.progressive != confFile.entryMap().value("progressive").toInt()) continue;
291 return profilesFiles.at(i);
294 // Check custom profiles
295 QStringList customProfiles = KGlobal::dirs()->findDirs("appdata", "profiles");
296 for(int i = 0; i < customProfiles.size(); ++i) {
297 profilesFiles = QDir(customProfiles.at(i)).entryList(profilesFilter, QDir::Files);
298 for(int j = 0; j < profilesFiles.size(); ++j) {
299 KConfig confFile(customProfiles.at(i) + profilesFiles.at(j), KConfig::SimpleConfig);
300 if(profile.display_aspect_den != confFile.entryMap().value("display_aspect_den").toInt()) continue;
301 if(profile.display_aspect_num != confFile.entryMap().value("display_aspect_num").toInt()) continue;
302 if(profile.sample_aspect_den != confFile.entryMap().value("sample_aspect_den").toInt()) continue;
303 if(profile.sample_aspect_num != confFile.entryMap().value("sample_aspect_num").toInt()) continue;
304 if(profile.width != confFile.entryMap().value("width").toInt()) continue;
305 if(profile.height != confFile.entryMap().value("height").toInt()) continue;
306 if(profile.frame_rate_den != confFile.entryMap().value("frame_rate_den").toInt()) continue;
307 if(profile.frame_rate_num != confFile.entryMap().value("frame_rate_num").toInt()) continue;
308 if(profile.progressive != confFile.entryMap().value("progressive").toInt()) continue;
309 return customProfiles.at(i) + profilesFiles.at(j);
316 QMap <QString, QString> ProfilesDialog::getProfilesInfo()
318 QMap <QString, QString> result;
319 QStringList profilesFilter;
320 profilesFilter << "*";
322 // List the Mlt profiles
323 QStringList profilesFiles = QDir(KdenliveSettings::mltpath()).entryList(profilesFilter, QDir::Files);
324 for(int i = 0; i < profilesFiles.size(); ++i) {
325 KConfig confFile(KdenliveSettings::mltpath() + profilesFiles.at(i), KConfig::SimpleConfig);
326 QString desc = confFile.entryMap().value("description");
327 if(!desc.isEmpty()) result.insert(desc, profilesFiles.at(i));
330 // List custom profiles
331 QStringList customProfiles = KGlobal::dirs()->findDirs("appdata", "profiles");
332 for(int i = 0; i < customProfiles.size(); ++i) {
333 profilesFiles = QDir(customProfiles.at(i)).entryList(profilesFilter, QDir::Files);
334 for(int j = 0; j < profilesFiles.size(); ++j) {
335 KConfig confFile(customProfiles.at(i) + profilesFiles.at(j), KConfig::SimpleConfig);
336 QString desc = confFile.entryMap().value("description");
337 if(!desc.isEmpty()) result.insert(desc, customProfiles.at(i) + profilesFiles.at(j));
344 QMap< QString, QString > ProfilesDialog::getSettingsFromFile(const QString path)
346 QStringList profilesNames;
347 QStringList profilesFiles;
348 QStringList profilesFilter;
349 profilesFilter << "*";
351 if(!path.contains('/')) {
352 // This is an MLT profile
353 KConfig confFile(KdenliveSettings::mltpath() + path, KConfig::SimpleConfig);
354 return confFile.entryMap();
356 // This is a custom profile
357 KConfig confFile(path, KConfig::SimpleConfig);
358 return confFile.entryMap();
363 QMap< QString, QString > ProfilesDialog::getSettingsForProfile(const QString profileName)
365 QStringList profilesNames;
366 QStringList profilesFiles;
367 QStringList profilesFilter;
368 profilesFilter << "*";
370 // List the Mlt profiles
371 profilesFiles = QDir(KdenliveSettings::mltpath()).entryList(profilesFilter, QDir::Files);
372 for(int i = 0; i < profilesFiles.size(); ++i) {
373 KConfig confFile(KdenliveSettings::mltpath() + profilesFiles.at(i), KConfig::SimpleConfig);
374 QMap< QString, QString > values = confFile.entryMap();
375 if(values.value("description") == profileName) {
376 values.insert("path", profilesFiles.at(i));
381 // List custom profiles
382 QStringList customProfiles = KGlobal::dirs()->findDirs("appdata", "profiles");
383 for(int i = 0; i < customProfiles.size(); ++i) {
384 QStringList profiles = QDir(customProfiles.at(i)).entryList(profilesFilter, QDir::Files);
385 for(int j = 0; j < profiles.size(); ++j) {
386 KConfig confFile(customProfiles.at(i) + profiles.at(j), KConfig::SimpleConfig);
387 QMap< QString, QString > values = confFile.entryMap();
388 if(values.value("description") == profileName) {
389 values.insert("path", customProfiles.at(i) + profiles.at(j));
394 return QMap< QString, QString >();
398 QString ProfilesDialog::getPathFromProperties(int width, int height, double fps, double par, double dar)
400 QStringList profilesNames;
401 QStringList profilesFiles;
402 QStringList profilesFilter;
403 profilesFilter << "*";
404 // List the Mlt profiles
405 profilesFiles = QDir(KdenliveSettings::mltpath()).entryList(profilesFilter, QDir::Files);
406 for(int i = 0; i < profilesFiles.size(); ++i) {
407 KConfig confFile(KdenliveSettings::mltpath() + profilesFiles.at(i), KConfig::SimpleConfig);
408 QMap< QString, QString > values = confFile.entryMap();
409 if(values.value("width").toInt() == width && values.value("height").toInt() == height) {
410 double profile_fps = values.value("frame_rate_num").toDouble() / values.value("frame_rate_den").toDouble();
411 if(qAbs(profile_fps - fps) < 0.5)
412 return profilesFiles.at(i);
416 // List custom profiles
417 QStringList customProfiles = KGlobal::dirs()->findDirs("appdata", "profiles");
418 for(int i = 0; i < customProfiles.size(); ++i) {
419 QStringList profiles = QDir(customProfiles.at(i)).entryList(profilesFilter, QDir::Files);
420 for(int j = 0; j < profiles.size(); j++) {
421 KConfig confFile(customProfiles.at(i) + profiles.at(j), KConfig::SimpleConfig);
422 QMap< QString, QString > values = confFile.entryMap();
423 if(values.value("width").toInt() == width && values.value("height").toInt() == height) {
424 double profile_fps = values.value("frame_rate_num").toDouble() / values.value("frame_rate_den").toDouble();
425 if(qAbs(profile_fps - fps) < 0.5)
426 return customProfiles.at(i) + profiles.at(j);
434 QString ProfilesDialog::getPathFromDescription(const QString profileDesc)
436 QStringList profilesNames;
437 QStringList profilesFiles;
438 QStringList profilesFilter;
439 profilesFilter << "*";
441 // List the Mlt profiles
442 profilesFiles = QDir(KdenliveSettings::mltpath()).entryList(profilesFilter, QDir::Files);
443 for(int i = 0; i < profilesFiles.size(); ++i) {
444 KConfig confFile(KdenliveSettings::mltpath() + profilesFiles.at(i), KConfig::SimpleConfig);
445 QMap< QString, QString > values = confFile.entryMap();
446 if(values.value("description") == profileDesc) return profilesFiles.at(i);
449 // List custom profiles
450 QStringList customProfiles = KGlobal::dirs()->findDirs("appdata", "profiles");
451 for(int i = 0; i < customProfiles.size(); ++i) {
452 QStringList profiles = QDir(customProfiles.at(i)).entryList(profilesFilter, QDir::Files);
453 for(int j = 0; j < profiles.size(); ++j) {
454 KConfig confFile(customProfiles.at(i) + profiles.at(j), KConfig::SimpleConfig);
455 QMap< QString, QString > values = confFile.entryMap();
456 if(values.value("description") == profileDesc) return customProfiles.at(i) + profiles.at(j);
463 void ProfilesDialog::saveProfile(MltVideoProfile &profile)
466 QString customName = "profiles/customprofile";
467 QString profilePath = KStandardDirs::locateLocal("appdata", customName + QString::number(i));
468 kDebug() << " TYING PROFILE FILE: " << profilePath;
469 while(KIO::NetAccess::exists(KUrl(profilePath), KIO::NetAccess::SourceSide, 0)) {
471 profilePath = KStandardDirs::locateLocal("appdata", customName + QString::number(i));
473 QFile file(profilePath);
474 if(!file.open(QIODevice::WriteOnly)) {
475 KMessageBox::sorry(0, i18n("Cannot write to file %1", profilePath));
478 QTextStream out(&file);
479 out << "description=" << profile.description << "\n" << "frame_rate_num=" << profile.frame_rate_num << "\n" << "frame_rate_den=" << profile.frame_rate_den << "\n" << "width=" << profile.width << "\n" << "height=" << profile.height << "\n" << "progressive=" << profile.progressive << "\n" << "sample_aspect_num=" << profile.sample_aspect_num << "\n" << "sample_aspect_den=" << profile.sample_aspect_den << "\n" << "display_aspect_num=" << profile.display_aspect_num << "\n" << "display_aspect_den=" << profile.display_aspect_den << "\n";
480 if(file.error() != QFile::NoError) {
481 KMessageBox::error(0, i18n("Cannot write to file %1", profilePath));
484 profile.path = profilePath;
488 void ProfilesDialog::slotUpdateDisplay()
490 if(askForSave() == false) {
491 m_view.profiles_list->blockSignals(true);
492 m_view.profiles_list->setCurrentIndex(m_selectedProfileIndex);
493 m_view.profiles_list->blockSignals(false);
497 m_selectedProfileIndex = m_view.profiles_list->currentIndex();
498 QString currentProfile = m_view.profiles_list->itemData(m_view.profiles_list->currentIndex()).toString();
499 m_isCustomProfile = currentProfile.contains('/');
500 m_view.button_create->setEnabled(true);
501 m_view.button_delete->setEnabled(m_isCustomProfile);
502 m_view.properties->setEnabled(m_isCustomProfile);
503 m_view.button_save->setEnabled(m_isCustomProfile);
504 QMap< QString, QString > values = ProfilesDialog::getSettingsFromFile(currentProfile);
505 m_view.description->setText(values.value("description"));
506 m_view.size_w->setValue(values.value("width").toInt());
507 m_view.size_h->setValue(values.value("height").toInt());
508 m_view.aspect_num->setValue(values.value("sample_aspect_num").toInt());
509 m_view.aspect_den->setValue(values.value("sample_aspect_den").toInt());
510 m_view.display_num->setValue(values.value("display_aspect_num").toInt());
511 m_view.display_den->setValue(values.value("display_aspect_den").toInt());
512 m_view.frame_num->setValue(values.value("frame_rate_num").toInt());
513 m_view.frame_den->setValue(values.value("frame_rate_den").toInt());
514 m_view.progressive->setChecked(values.value("progressive").toInt());
515 if(values.value("progressive").toInt()) {
516 m_view.fields->setText(QString::number((double)values.value("frame_rate_num").toInt() / values.value("frame_rate_den").toInt(), 'f', 2));
518 m_view.fields->setText(QString::number((double)2 * values.value("frame_rate_num").toInt() / values.value("frame_rate_den").toInt(), 'f', 2));
520 m_profileIsModified = false;
524 #include "profilesdialog.moc"