]> git.sesse.net Git - kdenlive/blob - src/dvdwizardchapters.cpp
Fix possible crash in DVD wizard chapters:
[kdenlive] / src / dvdwizardchapters.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 "dvdwizardchapters.h"
21
22 #include <KDebug>
23
24 #include <QFile>
25
26 DvdWizardChapters::DvdWizardChapters(bool isPal, QWidget *parent) :
27         QWizardPage(parent),
28         m_isPal(isPal),
29         m_monitor(NULL)
30
31 {
32     m_view.setupUi(this);
33     connect(m_view.vob_list, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateChaptersList()));
34     connect(m_view.button_add, SIGNAL(clicked()), this, SLOT(slotAddChapter()));
35     connect(m_view.button_delete, SIGNAL(clicked()), this, SLOT(slotRemoveChapter()));
36     connect(m_view.chapters_list, SIGNAL(itemSelectionChanged()), this, SLOT(slotGoToChapter()));
37
38     // Build monitor for chapters
39
40     if (m_isPal) m_tc.setFormat(25);
41     else m_tc.setFormat(30000.0 / 1001);
42
43     m_manager = new MonitorManager(this);
44     m_manager->resetProfiles(m_tc);
45     //m_view.monitor_frame->setVisible(false);
46 }
47
48 DvdWizardChapters::~DvdWizardChapters()
49 {
50     if (m_monitor) {
51         m_monitor->stop();
52         delete m_monitor;
53     }
54     delete m_manager;
55 }
56
57 // virtual
58
59 bool DvdWizardChapters::isComplete() const
60 {
61     return true;
62 }
63
64 void DvdWizardChapters::stopMonitor()
65 {
66     if (m_monitor) m_monitor->stop();
67 }
68
69 void DvdWizardChapters::slotUpdateChaptersList()
70 {
71     m_monitor->slotOpenFile(m_view.vob_list->currentText());
72     m_monitor->adjustRulerSize(m_view.vob_list->itemData(m_view.vob_list->currentIndex(), Qt::UserRole).toInt());
73     QStringList currentChaps = m_view.vob_list->itemData(m_view.vob_list->currentIndex(), Qt::UserRole + 1).toStringList();
74
75     // insert chapters
76     QStringList chaptersString;
77     for (int i = 0; i < currentChaps.count(); i++) {
78         chaptersString.append(Timecode::getStringTimecode(currentChaps.at(i).toInt(), m_tc.fps()));
79     }
80     m_view.chapters_list->clear();
81     m_view.chapters_list->addItems(chaptersString);
82
83     //bool modified = m_view.vob_list->itemData(m_view.vob_list->currentIndex(), Qt::UserRole + 2).toInt();
84 }
85
86 void DvdWizardChapters::slotAddChapter()
87 {
88     int pos = m_monitor->position().frames(m_tc.fps());
89     QStringList currentChaps = m_view.vob_list->itemData(m_view.vob_list->currentIndex(), Qt::UserRole + 1).toStringList();
90     if (currentChaps.contains(QString::number(pos))) return;
91     else currentChaps.append(QString::number(pos));
92     QList <int> chapterTimes;
93     for (int i = 0; i < currentChaps.count(); i++)
94         chapterTimes.append(currentChaps.at(i).toInt());
95     qSort(chapterTimes);
96
97     // rebuild chapters
98     QStringList chaptersString;
99     currentChaps.clear();
100     for (int i = 0; i < chapterTimes.count(); i++) {
101         chaptersString.append(Timecode::getStringTimecode(chapterTimes.at(i), m_tc.fps()));
102         currentChaps.append(QString::number(chapterTimes.at(i)));
103     }
104     // Save item chapters
105     m_view.vob_list->setItemData(m_view.vob_list->currentIndex(), currentChaps, Qt::UserRole + 1);
106     // Mark item as modified
107     m_view.vob_list->setItemData(m_view.vob_list->currentIndex(), 1, Qt::UserRole + 2);
108     m_view.chapters_list->clear();
109     m_view.chapters_list->addItems(chaptersString);
110 }
111
112 void DvdWizardChapters::slotRemoveChapter()
113 {
114     int ix = m_view.chapters_list->currentRow();
115     QStringList currentChaps = m_view.vob_list->itemData(m_view.vob_list->currentIndex(), Qt::UserRole + 1).toStringList();
116     currentChaps.removeAt(ix);
117
118     // Save item chapters
119     m_view.vob_list->setItemData(m_view.vob_list->currentIndex(), currentChaps, Qt::UserRole + 1);
120     // Mark item as modified
121     m_view.vob_list->setItemData(m_view.vob_list->currentIndex(), 1, Qt::UserRole + 2);
122
123     // rebuild chapters
124     QStringList chaptersString;
125     for (int i = 0; i < currentChaps.count(); i++) {
126         chaptersString.append(Timecode::getStringTimecode(currentChaps.at(i).toInt(), m_tc.fps()));
127     }
128     m_view.chapters_list->clear();
129     m_view.chapters_list->addItems(chaptersString);
130 }
131
132 void DvdWizardChapters::slotGoToChapter()
133 {
134     if (m_view.chapters_list->currentItem()) m_monitor->setTimePos(m_tc.reformatSeparators(m_view.chapters_list->currentItem()->text() + ":00"));
135 }
136
137 void DvdWizardChapters::setVobFiles(bool isPal, bool isWide, const QStringList movies, const QStringList durations, const QStringList chapters)
138 {
139     m_isPal = isPal;
140     QString profile;
141     if (m_isPal) {
142         m_tc.setFormat(25);
143         profile = "dv_pal";
144     } else {
145         m_tc.setFormat(30000.0 / 1001);
146         profile = "dv_ntsc";
147     }
148     if (isWide) profile.append("_wide");
149     m_manager->resetProfiles(m_tc);
150     if (m_monitor == NULL) {
151         m_monitor = new Monitor("chapter", m_manager, profile, this);
152         //m_monitor->start();
153         QVBoxLayout *vbox = new QVBoxLayout;
154         vbox->addWidget(m_monitor);
155         m_view.monitor_frame->setLayout(vbox);
156         /*updateGeometry();
157         m_view.monitor_frame->adjustSize();*/
158     } else m_monitor->resetProfile(profile);
159
160     m_view.vob_list->blockSignals(true);
161     m_view.vob_list->clear();
162     for (int i = 0; i < movies.count(); i++) {
163         m_view.vob_list->addItem(movies.at(i), durations.at(i));
164         m_view.vob_list->setItemData(i, chapters.at(i).split(';'), Qt::UserRole + 1);
165     }
166     m_view.vob_list->blockSignals(false);
167     slotUpdateChaptersList();
168 }
169
170 QMap <QString, QString> DvdWizardChapters::chaptersData() const
171 {
172     QMap <QString, QString> result;
173     int max = m_view.vob_list->count();
174     for (int i = 0; i < max; i++) {
175         QString chapters = m_view.vob_list->itemData(i, Qt::UserRole + 1).toStringList().join(";");
176         result.insert(m_view.vob_list->itemText(i), chapters);
177     }
178     return result;
179 }
180
181 QStringList DvdWizardChapters::selectedTitles() const
182 {
183     QStringList result;
184     int max = m_view.vob_list->count();
185     for (int i = 0; i < max; i++) {
186         result.append(m_view.vob_list->itemText(i));
187         QStringList chapters = m_view.vob_list->itemData(i, Qt::UserRole + 1).toStringList();
188         for (int j = 0; j < chapters.count(); j++) {
189             result.append(Timecode::getStringTimecode(chapters.at(j).toInt(), m_tc.fps()));
190         }
191     }
192     return result;
193 }
194
195 QStringList DvdWizardChapters::chapters(int ix) const
196 {
197     QStringList result;
198     QStringList chapters = m_view.vob_list->itemData(ix, Qt::UserRole + 1).toStringList();
199     for (int j = 0; j < chapters.count(); j++) {
200         result.append(Timecode::getStringTimecode(chapters.at(j).toInt(), m_tc.fps()));
201     }
202     return result;
203 }
204
205 QStringList DvdWizardChapters::selectedTargets() const
206 {
207     QStringList result;
208     int max = m_view.vob_list->count();
209     for (int i = 0; i < max; i++) {
210         // rightJustified: fill with 0s to make menus with more than 9 buttons work (now up to 99 buttons possible)
211         result.append("jump title " + QString::number(i + 1).rightJustified(2, '0'));
212         QStringList chapters = m_view.vob_list->itemData(i, Qt::UserRole + 1).toStringList();
213         for (int j = 0; j < chapters.count(); j++) {
214             result.append("jump title " + QString::number(i + 1).rightJustified(2, '0') + " chapter " + QString::number(j + 1).rightJustified(2, '0'));
215         }
216     }
217     return result;
218 }
219
220
221 QDomElement DvdWizardChapters::toXml() const
222 {
223     QDomDocument doc;
224     QDomElement xml = doc.createElement("xml");
225     doc.appendChild(xml);
226     for (int i = 0; i < m_view.vob_list->count(); i++) {
227         QDomElement vob = doc.createElement("vob");
228         vob.setAttribute("file", m_view.vob_list->itemText(i));
229         vob.setAttribute("chapters", m_view.vob_list->itemData(i, Qt::UserRole + 1).toStringList().join(";"));
230         xml.appendChild(vob);
231     }
232     return doc.documentElement();
233 }