Marble

SpeakersModel.cpp
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2012 Dennis Nienhüser <[email protected]>
4 //
5 
6 #include "SpeakersModel.h"
7 
8 #include "MarbleDirs.h"
9 #include "NewstuffModel.h"
10 
11 namespace Marble
12 {
13 
14 class SpeakersModelItem
15 {
16 public:
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 
26 class SpeakersModelPrivate
27 {
28 public:
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 
46 SpeakersModelItem::SpeakersModelItem() : m_newstuffIndex( -1 )
47 {
48  // nothing to do
49 }
50 
51 bool SpeakersModelItem::lessThan( const SpeakersModelItem& one, const SpeakersModelItem& two )
52 {
53  return one.m_file.fileName() < two.m_file.fileName();
54 }
55 
56 SpeakersModelPrivate::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 
67 void 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 
111 void 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 
123 void 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 
132 SpeakersModel::SpeakersModel( QObject *parent ) :
133  QAbstractListModel( parent ), d( new SpeakersModelPrivate( this ) )
134 {
135  QHash<int,QByteArray> roles;
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 
145 SpeakersModel::~SpeakersModel()
146 {
147  delete d;
148 }
149 
150 int SpeakersModel::rowCount ( const QModelIndex &parent ) const
151 {
152  if ( !parent.isValid() ) {
153  return d->m_speakers.size();
154  }
155 
156  return 0;
157 }
158 
159 QVariant 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 
174 QHash<int, QByteArray> SpeakersModel::roleNames() const
175 {
176  return d->m_roleNames;
177 }
178 
179 int 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 
189 QString 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 
197 void 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 
206 bool SpeakersModel::isLocal( int idx ) const
207 {
208  return data( index( idx ), IsLocal ).toBool();
209 }
210 
211 bool SpeakersModel::isRemote( int idx ) const
212 {
213  return data( index( idx ), IsRemote ).toBool();
214 }
215 
216 int SpeakersModel::count() const
217 {
218  return rowCount();
219 }
220 
221 }
222 
223 #include "moc_SpeakersModel.cpp"
DisplayRole
typedef Filters
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QFileInfoList entryInfoList(QDir::Filters filters, QDir::SortFlags sort) const const
QFuture< void > filter(Sequence &sequence, KeepFunctor filterFunction)
Binds a QML item to a specific geodetic location in screen coordinates.
bool isValid() const const
int row() const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString path(const QString &relativePath)
const char * name(StandardAction id)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Thu Sep 21 2023 04:12:28 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.