]> git.sesse.net Git - kdenlive/blob - src/dvdwizardvob.cpp
Updated DVD wizard (added load/save dvd projects)
[kdenlive] / src / dvdwizardvob.cpp
1 /***************************************************************************
2  *   Copyright (C) 2009 by Jean-Baptiste Mardelle (jb@kdenlive.org)        *
3  *                                                                         *
4  *   This program is free software; you can redistribute it and/or modify  *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program; if not, write to the                         *
16  *   Free Software Foundation, Inc.,                                       *
17  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
18  ***************************************************************************/
19
20 #include "dvdwizardvob.h"
21 #include "kthumb.h"
22 #include "timecode.h"
23
24 #include <mlt++/Mlt.h>
25
26 #include <KUrlRequester>
27 #include <KDebug>
28 #include <KStandardDirs>
29 #include <KFileItem>
30 #include <KFileDialog>
31
32 #include <QHBoxLayout>
33 #include <QDomDocument>
34 #include <QTreeWidgetItem>
35
36 DvdWizardVob::DvdWizardVob(const QString &profile, QWidget *parent) :
37         QWizardPage(parent)
38 {
39     m_view.setupUi(this);
40     m_view.intro_vob->setEnabled(false);
41     m_view.intro_vob->setFilter("video/mpeg");
42     m_view.button_add->setIcon(KIcon("document-new"));
43     m_view.button_delete->setIcon(KIcon("edit-delete"));
44     m_view.button_up->setIcon(KIcon("go-up"));
45     m_view.button_down->setIcon(KIcon("go-down"));
46     connect(m_view.use_intro, SIGNAL(toggled(bool)), m_view.intro_vob, SLOT(setEnabled(bool)));
47     connect(m_view.button_add, SIGNAL(clicked()), this, SLOT(slotAddVobFile()));
48     connect(m_view.button_delete, SIGNAL(clicked()), this, SLOT(slotDeleteVobFile()));
49     connect(m_view.button_up, SIGNAL(clicked()), this, SLOT(slotItemUp()));
50     connect(m_view.button_down, SIGNAL(clicked()), this, SLOT(slotItemDown()));
51     connect(m_view.vobs_list, SIGNAL(itemSelectionChanged()), this, SLOT(slotCheckVobList()));
52     m_view.vobs_list->setIconSize(QSize(60, 45));
53
54     if (KStandardDirs::findExe("dvdauthor").isEmpty()) m_errorMessage.append(i18n("<strong>Program %1 is required for the DVD wizard.", i18n("dvdauthor")));
55     if (KStandardDirs::findExe("mkisofs").isEmpty()) m_errorMessage.append(i18n("<strong>Program %1 is required for the DVD wizard.", i18n("mkisofs")));
56     if (m_errorMessage.isEmpty()) m_view.error_message->setVisible(false);
57     else m_view.error_message->setText(m_errorMessage);
58
59     m_view.dvd_profile->addItems(QStringList() << i18n("PAL 4:3") << i18n("PAL 16:9") << i18n("NTSC 4:3") << i18n("NTSC 16:9"));
60     if (profile == "dv_pal_wide") m_view.dvd_profile->setCurrentIndex(1);
61     else if (profile == "dv_ntsc") m_view.dvd_profile->setCurrentIndex(2);
62     else if (profile == "dv_ntsc_wide") m_view.dvd_profile->setCurrentIndex(3);
63
64     connect(m_view.dvd_profile, SIGNAL(activated(int)), this, SLOT(changeFormat()));
65     m_view.vobs_list->header()->setStretchLastSection(false);
66     m_view.vobs_list->header()->setResizeMode(0, QHeaderView::Stretch);
67     m_view.vobs_list->header()->setResizeMode(1, QHeaderView::Custom);
68     m_view.vobs_list->header()->setResizeMode(2, QHeaderView::Custom);
69
70 #if KDE_IS_VERSION(4,2,0)
71     m_capacityBar = new KCapacityBar(KCapacityBar::DrawTextInline, this);
72     QHBoxLayout *layout = new QHBoxLayout;
73     layout->addWidget(m_capacityBar);
74     m_view.size_box->setLayout(layout);
75 #else
76     m_view.size_box->setHidden(true);
77 #endif
78     slotCheckVobList();
79 }
80
81 DvdWizardVob::~DvdWizardVob()
82 {
83 #if KDE_IS_VERSION(4,2,0)
84     delete m_capacityBar;
85 #endif
86 }
87
88
89 void DvdWizardVob::slotAddVobFile(KUrl url, const QString &chapters)
90 {
91     if (url.isEmpty()) url = KFileDialog::getOpenUrl(KUrl("kfiledialog:///projectfolder"), "video/mpeg", this, i18n("Add new video file"));
92     if (url.isEmpty()) return;
93     QFile f(url.path());
94     qint64 fileSize = f.size();
95     QString profilename;
96     switch (m_view.dvd_profile->currentIndex()) {
97     case 1:
98         profilename = "dv_pal_wide";
99         break;
100     case 2:
101         profilename = "dv_ntsc";
102         break;
103     case 3:
104         profilename = "dv_ntsc_wide";
105         break;
106     default:
107         profilename = "dv_pal";
108         break;
109     }
110
111     char *tmp = (char*) qstrdup(profilename.toUtf8().data());
112     Mlt::Profile profile(tmp);
113     delete[] tmp;
114     QTreeWidgetItem *item = new QTreeWidgetItem(m_view.vobs_list, QStringList() << url.path() << QString() << KIO::convertSize(fileSize));
115     item->setData(0, Qt::UserRole, fileSize);
116     item->setIcon(0, KIcon("video-x-generic"));
117
118     QPixmap pix(60, 45);
119
120     tmp = (char *) qstrdup(url.path().toUtf8().data());
121     Mlt::Producer *producer = new Mlt::Producer(profile, tmp);
122     delete[] tmp;
123
124     if (producer->is_blank() == false) {
125         pix = KThumb::getFrame(producer, 0, 60, 45);
126         item->setIcon(0, pix);
127         int playTime = producer->get_playtime();
128         item->setText(1, Timecode::getStringTimecode(playTime, profile.fps()));
129         item->setData(1, Qt::UserRole, playTime);
130     }
131     delete producer;
132
133     if (chapters.isEmpty() == false) {
134         item->setData(1, Qt::UserRole + 1, chapters);
135     } else if (QFile::exists(url.path() + ".dvdchapter")) {
136         // insert chapters as children
137         QFile file(url.path() + ".dvdchapter");
138         if (file.open(QIODevice::ReadOnly)) {
139             QDomDocument doc;
140             doc.setContent(&file);
141             file.close();
142             QDomNodeList chapters = doc.elementsByTagName("chapter");
143             QStringList chaptersList;
144             for (int j = 0; j < chapters.count(); j++) {
145                 chaptersList.append(QString::number(chapters.at(j).toElement().attribute("time").toInt()));
146             }
147             item->setData(1, Qt::UserRole + 1, chaptersList.join(";"));
148         }
149     }
150
151     slotCheckVobList();
152 }
153
154 void DvdWizardVob::changeFormat()
155 {
156     int max = m_view.vobs_list->topLevelItemCount();
157     QString profilename;
158     switch (m_view.dvd_profile->currentIndex()) {
159     case 1:
160         profilename = "dv_pal_wide";
161         break;
162     case 2:
163         profilename = "dv_ntsc";
164         break;
165     case 3:
166         profilename = "dv_ntsc_wide";
167         break;
168     default:
169         profilename = "dv_pal";
170         break;
171     }
172
173     char *tmp = (char*) qstrdup(profilename.toUtf8().data());
174     Mlt::Profile profile(tmp);
175     delete[] tmp;
176     QPixmap pix(180, 135);
177
178     for (int i = 0; i < max; i++) {
179         QTreeWidgetItem *item = m_view.vobs_list->topLevelItem(i);
180         tmp = (char *) qstrdup(item->text(0).toUtf8().data());
181         Mlt::Producer *producer = new Mlt::Producer(profile, tmp);
182         delete[] tmp;
183
184         if (producer->is_blank() == false) {
185             //pix = KThumb::getFrame(producer, 0, 180, 135);
186             //item->setIcon(0, pix);
187             item->setText(1, Timecode::getStringTimecode(producer->get_playtime(), profile.fps()));
188         }
189         delete producer;
190         int submax = item->childCount();
191         for (int j = 0; j < submax; j++) {
192             QTreeWidgetItem *subitem = item->child(j);
193             subitem->setText(1, Timecode::getStringTimecode(subitem->data(1, Qt::UserRole).toInt(), profile.fps()));
194         }
195     }
196     slotCheckVobList();
197 }
198
199 void DvdWizardVob::slotDeleteVobFile()
200 {
201     QTreeWidgetItem *item = m_view.vobs_list->currentItem();
202     if (item == NULL) return;
203     delete item;
204     slotCheckVobList();
205 }
206
207
208 // virtual
209 bool DvdWizardVob::isComplete() const
210 {
211     if (!m_view.error_message->text().isEmpty()) return false;
212     if (m_view.vobs_list->topLevelItemCount() == 0) return false;
213     return true;
214 }
215
216 void DvdWizardVob::setUrl(const QString &url)
217 {
218     slotAddVobFile(KUrl(url));
219 }
220
221 QStringList DvdWizardVob::selectedUrls() const
222 {
223     QStringList result;
224     QString path;
225     int max = m_view.vobs_list->topLevelItemCount();
226     for (int i = 0; i < max; i++) {
227         QTreeWidgetItem *item = m_view.vobs_list->topLevelItem(i);
228         if (item) result.append(item->text(0));
229     }
230     return result;
231 }
232
233
234 QStringList DvdWizardVob::durations() const
235 {
236     QStringList result;
237     QString path;
238     int max = m_view.vobs_list->topLevelItemCount();
239     for (int i = 0; i < max; i++) {
240         QTreeWidgetItem *item = m_view.vobs_list->topLevelItem(i);
241         if (item) result.append(QString::number(item->data(1, Qt::UserRole).toInt()));
242     }
243     return result;
244 }
245
246 QStringList DvdWizardVob::chapters() const
247 {
248     QStringList result;
249     QString path;
250     int max = m_view.vobs_list->topLevelItemCount();
251     for (int i = 0; i < max; i++) {
252         QTreeWidgetItem *item = m_view.vobs_list->topLevelItem(i);
253         if (item) result.append(item->data(1, Qt::UserRole + 1).toString());
254     }
255     return result;
256 }
257
258 void DvdWizardVob::updateChapters(QMap <QString, QString> chaptersdata)
259 {
260     int max = m_view.vobs_list->topLevelItemCount();
261     for (int i = 0; i < max; i++) {
262         QTreeWidgetItem *item = m_view.vobs_list->topLevelItem(i);
263         item->setData(1, Qt::UserRole + 1, chaptersdata.value(item->text(0)));
264     }
265 }
266
267 int DvdWizardVob::duration(int ix) const
268 {
269     int result = -1;
270     QTreeWidgetItem *item = m_view.vobs_list->topLevelItem(ix);
271     if (item) {
272         result = item->data(1, Qt::UserRole).toInt();
273     }
274     return result;
275 }
276
277
278 QString DvdWizardVob::introMovie() const
279 {
280     if (!m_view.use_intro->isChecked()) return QString();
281     return m_view.intro_vob->url().path();
282 }
283
284 void DvdWizardVob::setIntroMovie(const QString path)
285 {
286     m_view.intro_vob->setPath(path);
287     m_view.use_intro->setChecked(path.isEmpty() == false);
288 }
289
290
291 void DvdWizardVob::slotCheckVobList()
292 {
293     emit completeChanged();
294     int max = m_view.vobs_list->topLevelItemCount();
295     QTreeWidgetItem *item = m_view.vobs_list->currentItem();
296     bool hasItem = true;
297     if (item == NULL) hasItem = false;
298     m_view.button_delete->setEnabled(hasItem);
299     if (hasItem && m_view.vobs_list->indexOfTopLevelItem(item) == 0) m_view.button_up->setEnabled(false);
300     else m_view.button_up->setEnabled(hasItem);
301     if (hasItem && m_view.vobs_list->indexOfTopLevelItem(item) == max - 1) m_view.button_down->setEnabled(false);
302     else m_view.button_down->setEnabled(hasItem);
303
304 #if KDE_IS_VERSION(4,2,0)
305     qint64 totalSize = 0;
306     for (int i = 0; i < max; i++) {
307         item = m_view.vobs_list->topLevelItem(i);
308         if (item) totalSize += (qint64) item->data(0, Qt::UserRole).toInt();
309     }
310
311     qint64 maxSize = (qint64) 47000 * 100000;
312     m_capacityBar->setValue(100 * totalSize / maxSize);
313     m_capacityBar->setText(KIO::convertSize(totalSize));
314 #endif
315 }
316
317 void DvdWizardVob::slotItemUp()
318 {
319     QTreeWidgetItem *item = m_view.vobs_list->currentItem();
320     if (item == NULL) return;
321     int index = m_view.vobs_list->indexOfTopLevelItem(item);
322     if (index == 0) return;
323     m_view.vobs_list->insertTopLevelItem(index - 1, m_view.vobs_list->takeTopLevelItem(index));
324 }
325
326 void DvdWizardVob::slotItemDown()
327 {
328     int max = m_view.vobs_list->topLevelItemCount();
329     QTreeWidgetItem *item = m_view.vobs_list->currentItem();
330     if (item == NULL) return;
331     int index = m_view.vobs_list->indexOfTopLevelItem(item);
332     if (index == max - 1) return;
333     m_view.vobs_list->insertTopLevelItem(index + 1, m_view.vobs_list->takeTopLevelItem(index));
334 }
335
336 bool DvdWizardVob::isPal() const
337 {
338     return m_view.dvd_profile->currentIndex() < 2;
339 }
340
341 bool DvdWizardVob::isWide() const
342 {
343     return (m_view.dvd_profile->currentIndex() == 1 || m_view.dvd_profile->currentIndex() == 3);
344 }
345
346 void DvdWizardVob::setProfile(const QString profile)
347 {
348     if (profile == "dv_pal") m_view.dvd_profile->setCurrentIndex(0);
349     else if (profile == "dv_pal_wide") m_view.dvd_profile->setCurrentIndex(1);
350     else if (profile == "dv_ntsc") m_view.dvd_profile->setCurrentIndex(2);
351     else if (profile == "dv_ntsc_wide") m_view.dvd_profile->setCurrentIndex(3);
352 }
353
354 void DvdWizardVob::clear()
355 {
356     m_view.vobs_list->clear();
357 }