OSDN Git Service

Added "Cue Sheet" importer to GUI. Actual Cue Sheet parsing and splitting not yet...
[lamexp/LameXP.git] / src / Model_CueSheet.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // LameXP - Audio Encoder Front-End
3 // Copyright (C) 2004-2011 LoRd_MuldeR <MuldeR2@GMX.de>
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 //
19 // http://www.gnu.org/licenses/gpl-2.0.txt
20 ///////////////////////////////////////////////////////////////////////////////
21
22 #include "Model_CueSheet.h"
23 #include "Genres.h"
24
25 #include <QMessageBox>
26 #include <QInputDialog>
27 #include <QFileInfo>
28
29 #include <float.h>
30 #include <limits>
31
32 ////////////////////////////////////////////////////////////
33 // Helper Classes
34 ////////////////////////////////////////////////////////////
35
36 class CueSheetItem
37 {
38 public:
39         virtual const char* type(void) = 0;
40 };
41
42 class CueSheetTrack : public CueSheetItem
43 {
44 public:
45         CueSheetTrack(CueSheetFile *parent, int trackNo)
46         :
47                 m_parent(parent),
48                 m_trackNo(trackNo)
49         {
50                 m_startIndex = std::numeric_limits<double>::quiet_NaN();
51         }
52         int trackNo(void) { return m_trackNo; }
53         double startIndex(void) { return m_startIndex; }
54         QString title(void) { return m_title; }
55         QString performer(void) { return m_performer; }
56         CueSheetFile *parent(void) { return m_parent; }
57         void setStartIndex(double startIndex) { m_startIndex = startIndex; }
58         void setTitle(const QString &title) { m_title = title; }
59         void setPerformer(const QString &performer) { m_performer = performer; }
60         bool isValid(void) { return !(_isnan(m_startIndex) || (m_trackNo < 0)); }
61         virtual const char* type(void) { return "CueSheetTrack"; }
62 private:
63         int m_trackNo;
64         double m_startIndex;
65         QString m_title;
66         QString m_performer;
67         CueSheetFile *m_parent;
68 };
69
70 class CueSheetFile : public CueSheetItem
71 {
72 public:
73         CueSheetFile(const QString &fileName) : m_fileName(fileName) {}
74         ~CueSheetFile(void) { while(!m_tracks.isEmpty()) delete m_tracks.takeLast(); }
75         QString fileName(void) { return m_fileName; }
76         void addTrack(CueSheetTrack *track) { m_tracks.append(track); }
77         void clearTracks(void) { while(!m_tracks.isEmpty()) delete m_tracks.takeLast(); }
78         CueSheetTrack *track(int index) { return m_tracks.at(index); }
79         int trackCount(void) { return m_tracks.count(); }
80         virtual const char* type(void) { return "CueSheetFile"; }
81 private:
82         const QString m_fileName;
83         QList<CueSheetTrack*> m_tracks;
84 };
85
86 ////////////////////////////////////////////////////////////
87 // Constructor & Destructor
88 ////////////////////////////////////////////////////////////
89
90 CueSheetModel::CueSheetModel()
91 {
92         int trackNo = 0;
93         
94         for(int i = 0; i < 5; i++)
95         {
96                 CueSheetFile *currentFile = new CueSheetFile(QString().sprintf("File %02d.wav", i+1));
97                 for(int j = 0; j < 8; j++)
98                 {
99                         CueSheetTrack *currentTrack = new CueSheetTrack(currentFile, trackNo++);
100                         currentTrack->setTitle("ATWA (Air Trees Water Animals)");
101                         currentTrack->setPerformer("System of a Down");
102                         currentFile->addTrack(currentTrack);
103                 }
104                 m_files.append(currentFile);
105         }
106 }
107
108 CueSheetModel::~CueSheetModel(void)
109 {
110         while(!m_files.isEmpty()) delete m_files.takeLast();
111 }
112
113 ////////////////////////////////////////////////////////////
114 // Model Functions
115 ////////////////////////////////////////////////////////////
116
117 QModelIndex CueSheetModel::index(int row, int column, const QModelIndex &parent) const
118 {
119         if(!parent.isValid())
120         {
121                 return createIndex(row, column, m_files.at(row));
122         }
123
124         CueSheetItem *parentItem = static_cast<CueSheetItem*>(parent.internalPointer());
125         if(CueSheetFile *filePtr = dynamic_cast<CueSheetFile*>(parentItem))
126         {
127                 return createIndex(row, column, filePtr->track(row));
128         }
129
130         return QModelIndex();
131 }
132
133 int CueSheetModel::columnCount(const QModelIndex &parent) const
134 {
135         return 3;
136 }
137
138 int CueSheetModel::rowCount(const QModelIndex &parent) const
139 {
140         if(!parent.isValid())
141         {
142                 return m_files.count();
143         }
144
145         CueSheetItem *parentItem = static_cast<CueSheetItem*>(parent.internalPointer());
146         if(CueSheetFile *filePtr = dynamic_cast<CueSheetFile*>(parentItem))
147         {
148                 return filePtr->trackCount();
149         }
150
151         return 0;
152 }
153
154 QModelIndex CueSheetModel::parent(const QModelIndex &child) const
155 {
156         if(child.isValid())
157         {
158                 CueSheetItem *childItem = static_cast<CueSheetItem*>(child.internalPointer());
159                 if(CueSheetTrack *trackPtr = dynamic_cast<CueSheetTrack*>(childItem))
160                 {
161                         return createIndex(m_files.indexOf(trackPtr->parent()), 0, trackPtr->parent());
162                 }
163         }
164
165         return QModelIndex();
166 }
167
168 QVariant CueSheetModel::headerData (int section, Qt::Orientation orientation, int role) const
169 {
170         if(role == Qt::DisplayRole)
171         {
172                 switch(section)
173                 {
174                 case 0:
175                         return tr("No.");
176                         break;
177                 case 1:
178                         return tr("File / Track");
179                         break;
180                 case 2:
181                         return tr("Index");
182                         break;
183                 default:
184                         return QVariant();
185                         break;
186                 }
187         }
188         else
189         {
190                 return QVariant();
191         }
192 }
193
194 QVariant CueSheetModel::data(const QModelIndex &index, int role) const
195 {
196         if(role == Qt::DisplayRole)
197         {
198                 CueSheetItem *item = reinterpret_cast<CueSheetItem*>(index.internalPointer());
199
200                 if(CueSheetFile *filePtr = dynamic_cast<CueSheetFile*>(item))
201                 {
202                         switch(index.column())
203                         {
204                         case 0:
205                                 return tr("File %1").arg(QString().sprintf("%02d", index.row() + 1)).append(" ");
206                                 break;
207                         case 1:
208                                 return QString("[%1]").arg(QFileInfo(filePtr->fileName()).fileName());
209                                 break;
210                         default:
211                                 return QVariant();
212                                 break;
213                         }
214                 }
215                 else if(CueSheetTrack *trackPtr = dynamic_cast<CueSheetTrack*>(item))
216                 {
217                         switch(index.column())
218                         {
219                         case 0:
220                                 return tr("Track %1").arg(QString().sprintf("%02d", trackPtr->trackNo() + 1)).append(" ");
221                                 break;
222                         case 1:
223                                 if(!trackPtr->title().isEmpty() && !trackPtr->performer().isEmpty())
224                                 {
225                                         return QString("%1 / %2").arg(trackPtr->performer(), trackPtr->title());
226                                 }
227                                 else if(!trackPtr->title().isEmpty())
228                                 {
229                                         return trackPtr->title();
230                                 }
231                                 else if(!trackPtr->performer().isEmpty())
232                                 {
233                                         return trackPtr->performer();
234                                 }
235                                 return QVariant();
236                                 break;
237                         case 2:
238                                 return QString().sprintf("%07.2f", trackPtr->startIndex());
239                                 break;
240                         default:
241                                 return QVariant();
242                                 break;
243                         }
244                 }
245         }
246
247         return QVariant();
248 }
249
250 void CueSheetModel::clearData(void)
251 {
252         beginResetModel();
253         while(!m_files.isEmpty()) delete m_files.takeLast();
254         endResetModel();
255 }