Marble

SpeakersModel.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2012 Dennis Nienhüser <nienhueser@kde.org>
4//
5
6#include "SpeakersModel.h"
7
8#include "MarbleDirs.h"
9#include "NewstuffModel.h"
10
11namespace Marble
12{
13
14class SpeakersModelItem
15{
16public:
17 QFileInfo m_file;
18
19 int m_newstuffIndex;
20
21 SpeakersModelItem();
22
23 static bool lessThan( const SpeakersModelItem& one, const SpeakersModelItem& two );
24};
25
26class SpeakersModelPrivate
27{
28public:
29 SpeakersModel* m_parent;
30
31 QList<SpeakersModelItem> m_speakers;
32
33 NewstuffModel m_newstuffModel;
34
35 explicit SpeakersModelPrivate( SpeakersModel* parent );
36
37 void fillModel();
38
39 void handleInstallationProgress( int row, qreal progress );
40
41 void handleInstallation( int );
42
43 QHash<int, QByteArray> m_roleNames;
44};
45
46SpeakersModelItem::SpeakersModelItem() : m_newstuffIndex( -1 )
47{
48 // nothing to do
49}
50
51bool SpeakersModelItem::lessThan( const SpeakersModelItem& one, const SpeakersModelItem& two )
52{
53 return one.m_file.fileName() < two.m_file.fileName();
54}
55
56SpeakersModelPrivate::SpeakersModelPrivate( SpeakersModel* parent ) :
57 m_parent( parent )
58{
59 m_newstuffModel.setTargetDirectory(MarbleDirs::localPath() + QLatin1String("/audio/speakers"));
60 m_newstuffModel.setProvider( "http://edu.kde.org/marble/newstuff/speakers.xml" );
61 QObject::connect( &m_newstuffModel, SIGNAL(modelReset()), m_parent, SLOT(fillModel()) );
62 QObject::connect( &m_newstuffModel, SIGNAL(installationProgressed(int,qreal)),
63 m_parent, SLOT(handleInstallationProgress(int,qreal)) );
64 QObject::connect( &m_newstuffModel, SIGNAL(installationFinished(int)), m_parent, SLOT(handleInstallation(int)) );
65}
66
67void SpeakersModelPrivate::fillModel()
68{
69 m_speakers.clear();
70
71 QStringList const baseDirs = QStringList() << MarbleDirs::systemPath() << MarbleDirs::localPath();
72 for ( const QString &baseDir: baseDirs ) {
73 const QString base = baseDir + QLatin1String("/audio/speakers/");
74
76 QFileInfoList subdirs = QDir( base ).entryInfoList( filter, QDir::Name );
77 for( const QFileInfo &file: subdirs ) {
78 SpeakersModelItem item;
79 item.m_file = file;
80 m_speakers << item;
81 }
82 }
83
84 for ( int i=0; i<m_newstuffModel.rowCount(); ++i ) {
85 QModelIndex const index = m_newstuffModel.index( i );
86 QString const name = m_newstuffModel.data( index ).toString();
87 bool exists = false;
88 for ( int j=0; j<m_speakers.size() && !exists; ++j ) {
89 SpeakersModelItem &item = m_speakers[j];
90 if ( item.m_file.fileName() == name ) {
91 item.m_newstuffIndex = i;
92 exists = true;
93 }
94 }
95
96 if ( !exists ) {
97 SpeakersModelItem item;
98 QString const path = "%1/audio/speakers/%2";
99 item.m_file = QFileInfo( path.arg( MarbleDirs::localPath(), name ) );
100 item.m_newstuffIndex = i;
101 m_speakers << item;
102 }
103 }
104
105 std::sort(m_speakers.begin(), m_speakers.end(), SpeakersModelItem::lessThan);
106 m_parent->beginResetModel();
107 m_parent->endResetModel();
108 emit m_parent->countChanged();
109}
110
111void SpeakersModelPrivate::handleInstallation( int row )
112{
113 for ( int j=0; j<m_speakers.size(); ++j ) {
114 if ( m_speakers[j].m_newstuffIndex == row ) {
115 m_speakers[j].m_file.refresh();
116 QModelIndex const affected = m_parent->index( j );
117 emit m_parent->dataChanged( affected, affected );
118 emit m_parent->installationFinished( j );
119 }
120 }
121}
122
123void SpeakersModelPrivate::handleInstallationProgress( int row, qreal progress )
124{
125 for ( int j=0; j<m_speakers.size(); ++j ) {
126 if ( m_speakers[j].m_newstuffIndex == row ) {
127 emit m_parent->installationProgressed( j, progress );
128 }
129 }
130}
131
132SpeakersModel::SpeakersModel( QObject *parent ) :
133 QAbstractListModel( parent ), d( new SpeakersModelPrivate( this ) )
134{
136 roles[Path] = "path";
137 roles[Name] = "name";
138 roles[IsLocal] = "isLocal";
139 roles[IsRemote] = "isRemote";
140 d->m_roleNames = roles;
141
142 d->fillModel();
143}
144
145SpeakersModel::~SpeakersModel()
146{
147 delete d;
148}
149
150int SpeakersModel::rowCount ( const QModelIndex &parent ) const
151{
152 if ( !parent.isValid() ) {
153 return d->m_speakers.size();
154 }
155
156 return 0;
157}
158
159QVariant SpeakersModel::data ( const QModelIndex &index, int role ) const
160{
161 if ( index.isValid() && index.row() >= 0 && index.row() < d->m_speakers.size() ) {
162 switch ( role ) {
163 case Qt::DisplayRole: return d->m_speakers.at( index.row() ).m_file.fileName();
164 case Path: return d->m_speakers.at( index.row() ).m_file.absoluteFilePath();
165 case Name: return d->m_speakers.at( index.row() ).m_file.fileName();
166 case IsLocal: return d->m_speakers.at( index.row() ).m_file.exists();
167 case IsRemote: return d->m_speakers.at( index.row() ).m_newstuffIndex >= 0;
168 }
169 }
170
171 return QVariant();
172}
173
174QHash<int, QByteArray> SpeakersModel::roleNames() const
175{
176 return d->m_roleNames;
177}
178
179int SpeakersModel::indexOf( const QString &name )
180{
181 for( int i=0; i<d->m_speakers.size(); ++i ) {
182 if ( d->m_speakers[i].m_file.absoluteFilePath() == name || d->m_speakers[i].m_file.fileName() == name ) {
183 return i;
184 }
185 }
186 return -1;
187}
188
189QString SpeakersModel::path( int index )
190{
191 if ( index >= 0 && index <= d->m_speakers.size() ) {
192 return d->m_speakers[index].m_file.absoluteFilePath();
193 }
194 return QString();
195}
196
197void SpeakersModel::install( int index )
198{
199 if ( index >= 0 && index < d->m_speakers.size() ) {
200 if ( d->m_speakers[index].m_newstuffIndex >= 0 ) {
201 d->m_newstuffModel.install( d->m_speakers[index].m_newstuffIndex );
202 }
203 }
204}
205
206bool SpeakersModel::isLocal( int idx ) const
207{
208 return data( index( idx ), IsLocal ).toBool();
209}
210
211bool SpeakersModel::isRemote( int idx ) const
212{
213 return data( index( idx ), IsRemote ).toBool();
214}
215
216int SpeakersModel::count() const
217{
218 return rowCount();
219}
220
221}
222
223#include "moc_SpeakersModel.cpp"
QString path(const QString &relativePath)
QString name(StandardAction id)
Binds a QML item to a specific geodetic location in screen coordinates.
typedef Filters
QFileInfoList entryInfoList(Filters filters, SortFlags sort) const const
qsizetype size() const const
bool isValid() const const
int row() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString arg(Args &&... args) const const
QChar * data()
DisplayRole
QFuture< void > filter(QThreadPool *pool, Sequence &sequence, KeepFunctor &&filterFunction)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jun 14 2024 11:54:17 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.