1 /*
2 SPDX-FileCopyrightText: 2010 Michal Malek <michalm@jabster.pl>
3 SPDX-FileCopyrightText: 1998-2010 Sebastian Trueg <trueg@k3b.org>
4
5 SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8 #include "k3bvideodvdaudiomodel.h"
9 #include "k3bvideodvd.h"
10 #include "k3bvideodvdtitle.h"
11
12 #include <KLocalizedString>
13
14 #include <QHash>
15 #include <QLocale>
16 #include <QSize>
17
18 namespace K3b {
19
20 class VideoDVDAudioModel::Private
21 {
22 public:
Private(const VideoDVD::VideoDVD & d,const QList<int> & t)23 Private( const VideoDVD::VideoDVD& d, const QList<int>& t )
24 : dvd( d ), titles( t ) {}
25
26 VideoDVD::VideoDVD dvd;
27 QList<int> titles;
28 QHash< const VideoDVD::AudioStream*, const VideoDVD::Title* > parents;
29 QHash< const VideoDVD::Title*, QSize > videoSizes;
30 QHash< const VideoDVD::Title*, KIO::filesize_t > fileSizes;
31 QHash< const VideoDVD::Title*, QString > fileNames;
32 QHash< const VideoDVD::Title*, int > chosenAudio;
33 };
34
35
VideoDVDAudioModel(const VideoDVD::VideoDVD & dvd,const QList<int> & titles,QObject * parent)36 VideoDVDAudioModel::VideoDVDAudioModel( const VideoDVD::VideoDVD& dvd, const QList<int>& titles, QObject* parent )
37 : QAbstractItemModel( parent ),
38 d( new Private( dvd, titles ) )
39 {
40 Q_FOREACH( int titleNum, titles ) {
41 if( titleNum > 0 && titleNum <= static_cast<int>( d->dvd.numTitles() ) ) {
42 const VideoDVD::Title& title = d->dvd[ titleNum-1 ];
43
44 d->videoSizes.insert( &title, QSize( title.videoStream().realPictureWidth(),
45 title.videoStream().realPictureHeight() ) );
46 d->fileSizes.insert( &title, 0 );
47 d->fileNames.insert( &title, QString() );
48 d->chosenAudio.insert( &title, 0 );
49
50 for( int i = 0; i < static_cast<int>( title.numAudioStreams() ); ++i ) {
51 const VideoDVD::AudioStream& audio = title.audioStream( i );
52 d->parents.insert( &audio, &title );
53 if( QLocale( audio.langCode() ).language() == QLocale().language() &&
54 audio.format() != K3b::VideoDVD::AUDIO_FORMAT_DTS ) {
55 d->chosenAudio[ &title ] = i;
56 }
57 }
58 }
59 }
60 }
61
62
~VideoDVDAudioModel()63 VideoDVDAudioModel::~VideoDVDAudioModel()
64 {
65 delete d;
66 }
67
68
titleForIndex(const QModelIndex & index) const69 const VideoDVD::Title* VideoDVDAudioModel::titleForIndex( const QModelIndex& index ) const
70 {
71 if( index.isValid() && !index.internalPointer() && index.row() >= 0 && index.row() < d->titles.size() )
72 {
73 const int title = d->titles.at( index.row() ) - 1;
74 if( title >= 0 && title < static_cast<int>( d->dvd.numTitles() ) )
75 return &d->dvd[ title ];
76 }
77 return 0;
78 }
79
80
indexForTitle(const VideoDVD::Title & title,int column) const81 QModelIndex VideoDVDAudioModel::indexForTitle( const VideoDVD::Title& title, int column ) const
82 {
83 int row = d->titles.indexOf( title.titleNumber() );
84 if( row >= 0 )
85 return createIndex( row, column, nullptr );
86 else
87 return QModelIndex();
88 }
89
90
audioForIndex(const QModelIndex & index) const91 const VideoDVD::AudioStream* VideoDVDAudioModel::audioForIndex( const QModelIndex& index ) const
92 {
93 if( index.isValid() && index.internalPointer() )
94 return static_cast<VideoDVD::AudioStream*>( index.internalPointer() );
95 else
96 return 0;
97 }
98
99
indexForAudio(const VideoDVD::AudioStream & audio,int column) const100 QModelIndex VideoDVDAudioModel::indexForAudio( const VideoDVD::AudioStream& audio, int column ) const
101 {
102 if( const VideoDVD::Title* title = d->parents[ &audio ] ) {
103 for( int i = 0; i < static_cast<int>( title->numAudioStreams() ); ++i ) {
104 if( &title->audioStream( i ) == &audio ) {
105 return createIndex( i, column, const_cast<void*>( reinterpret_cast<const void*>( &audio ) ) );
106 }
107 }
108 }
109 return QModelIndex();
110 }
111
112
setVideoSize(const VideoDVD::Title & title,const QSize & videoSize)113 void VideoDVDAudioModel::setVideoSize( const VideoDVD::Title& title, const QSize& videoSize )
114 {
115 d->videoSizes[ &title ] = videoSize;
116 QModelIndex index = indexForTitle( title, VideoSizeColumn );
117 Q_EMIT dataChanged( index, index );
118 }
119
120
setFileSize(const VideoDVD::Title & title,KIO::filesize_t fileSize)121 void VideoDVDAudioModel::setFileSize( const VideoDVD::Title& title, KIO::filesize_t fileSize )
122 {
123 d->fileSizes[ &title ] = fileSize;
124 QModelIndex index = indexForTitle( title, FileSizeColumn );
125 Q_EMIT dataChanged( index, index );
126 }
127
128
setFileName(const VideoDVD::Title & title,const QString & fileName)129 void VideoDVDAudioModel::setFileName( const VideoDVD::Title& title, const QString& fileName )
130 {
131 d->fileNames[ &title ] = fileName;
132 QModelIndex index = indexForTitle( title, FileNameColumn );
133 Q_EMIT dataChanged( index, index );
134 }
135
136
chosenAudio(const VideoDVD::Title & title) const137 int VideoDVDAudioModel::chosenAudio( const VideoDVD::Title& title ) const
138 {
139 return d->chosenAudio[ &title ];
140 }
141
142
data(const QModelIndex & index,int role) const143 QVariant VideoDVDAudioModel::data( const QModelIndex& index, int role ) const
144 {
145 if( const VideoDVD::Title* title = titleForIndex( index ) ) {
146 if( Qt::DisplayRole == role ) {
147 switch( index.column() ) {
148 case TitleColumn:
149 return i18n("Title %1 (%2)",
150 title->titleNumber(),
151 title->playbackTime().toString() );
152 case VideoSizeColumn:
153 return QString("%1x%2")
154 .arg( d->videoSizes[ title ].width() )
155 .arg( d->videoSizes[ title ].height() );
156 case FileSizeColumn:
157 return KIO::convertSize( d->fileSizes[ title ] );
158 case FileNameColumn:
159 return d->fileNames[ title ];
160 default:
161 break;
162 }
163 }
164 else if( Qt::ToolTipRole == role && index.column() == FileNameColumn ) {
165 return d->fileNames[ title ];
166 }
167 }
168 else if( const VideoDVD::AudioStream* audio = audioForIndex( index ) ) {
169 if( Qt::DisplayRole == role && index.column() == TitleColumn ) {
170 QString text = i18n("%1 %2Ch (%3%4)",
171 K3b::VideoDVD::audioFormatString( audio->format() ),
172 audio->channels(),
173 ( audio->langCode().isEmpty()
174 ? i18n("unknown language")
175 : QLocale( audio->langCode() ).nativeLanguageName() ),
176 ( audio->codeExtension() != K3b::VideoDVD::AUDIO_CODE_EXT_UNSPECIFIED
177 ? QString(" ") + K3b::VideoDVD::audioCodeExtensionString( audio->codeExtension() )
178 : QString() ) );
179
180 if( audio->format() == K3b::VideoDVD::AUDIO_FORMAT_DTS )
181 return i18n( "%1 (not supported)", text );
182 else
183 return text;
184 }
185 else if( Qt::CheckStateRole == role && index.column() == TitleColumn ) {
186 if( d->chosenAudio[ d->parents[ audio ] ] == index.row() )
187 return Qt::Checked;
188 else
189 return Qt::Unchecked;
190 }
191 }
192 return QVariant();
193 }
194
195
columnCount(const QModelIndex &) const196 int VideoDVDAudioModel::columnCount( const QModelIndex& /*parent*/ ) const
197 {
198 return NumColumns;
199 }
200
201
rowCount(const QModelIndex & parent) const202 int VideoDVDAudioModel::rowCount( const QModelIndex& parent ) const
203 {
204 if( !parent.isValid() )
205 return d->titles.count();
206 else if( const VideoDVD::Title* title = titleForIndex( parent ) )
207 return title->numAudioStreams();
208 else
209 return 0;
210 }
211
212
parent(const QModelIndex & child) const213 QModelIndex VideoDVDAudioModel::parent( const QModelIndex& child ) const
214 {
215 if( const VideoDVD::AudioStream* audio = audioForIndex( child ) ) {
216 if( const VideoDVD::Title* title = d->parents[ audio ] ) {
217 return indexForTitle( *title );
218 }
219 }
220 return QModelIndex();
221 }
222
223
index(int row,int column,const QModelIndex & parent) const224 QModelIndex VideoDVDAudioModel::index( int row, int column, const QModelIndex& parent ) const
225 {
226 if( !hasIndex( row, column, parent ) ) {
227 return QModelIndex();
228 }
229 else if( !parent.isValid() ) {
230 if( row >= 0 && row < d->titles.size() )
231 return createIndex( row, column, nullptr );
232 else
233 return QModelIndex();
234 }
235 else if( const VideoDVD::Title* title = titleForIndex( parent ) ) {
236 if( row >= 0 && row < static_cast<int>( title->numAudioStreams() ) )
237 return createIndex( row, column, const_cast<void*>( reinterpret_cast<const void*>( &title->audioStream( row ) ) ) );
238 else
239 return QModelIndex();
240 }
241 else {
242 return QModelIndex();
243 }
244 }
245
246
headerData(int section,Qt::Orientation orientation,int role) const247 QVariant VideoDVDAudioModel::headerData( int section, Qt::Orientation orientation, int role ) const
248 {
249 if( orientation == Qt::Horizontal && Qt::DisplayRole == role ) {
250 switch( section ) {
251 case TitleColumn: return i18n("Title");
252 case VideoSizeColumn: return i18n("Video Size");
253 case FileSizeColumn: return i18n("File Size");
254 case FileNameColumn: return i18n("Filename");
255 default: break;
256 }
257 }
258 return QVariant();
259 }
260
261
setData(const QModelIndex & index,const QVariant & value,int role)262 bool VideoDVDAudioModel::setData( const QModelIndex& index, const QVariant& value, int role )
263 {
264 if( role == Qt::CheckStateRole && value.toBool() ) {
265 if( const VideoDVD::AudioStream* audio = audioForIndex( index ) ) {
266 if( const VideoDVD::Title* title = d->parents[ audio ] ) {
267 d->chosenAudio[ title ] = index.row();
268 QModelIndex titleIndex = indexForTitle( *title );
269 Q_EMIT dataChanged( VideoDVDAudioModel::index( 0, TitleColumn, titleIndex ),
270 VideoDVDAudioModel::index( rowCount( titleIndex )-1, TitleColumn, titleIndex ) );
271 }
272 }
273 }
274 return false;
275 }
276
277
flags(const QModelIndex & index) const278 Qt::ItemFlags VideoDVDAudioModel::flags( const QModelIndex& index ) const
279 {
280 if( audioForIndex( index ) != 0 )
281 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
282 else if( titleForIndex( index ) != 0 )
283 return Qt::ItemIsEnabled;
284 else
285 return Qt::NoItemFlags;
286 }
287
288 } // namespace K3b
289
290
291
292