File indexing completed on 2024-04-28 03:49:31
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 // 0003 // SPDX-FileCopyrightText: 2012 Dennis Nienhüser <nienhueser@kde.org> 0004 // 0005 0006 #include "SpeakersModel.h" 0007 0008 #include "MarbleDirs.h" 0009 #include "NewstuffModel.h" 0010 0011 namespace Marble 0012 { 0013 0014 class SpeakersModelItem 0015 { 0016 public: 0017 QFileInfo m_file; 0018 0019 int m_newstuffIndex; 0020 0021 SpeakersModelItem(); 0022 0023 static bool lessThan( const SpeakersModelItem& one, const SpeakersModelItem& two ); 0024 }; 0025 0026 class SpeakersModelPrivate 0027 { 0028 public: 0029 SpeakersModel* m_parent; 0030 0031 QList<SpeakersModelItem> m_speakers; 0032 0033 NewstuffModel m_newstuffModel; 0034 0035 explicit SpeakersModelPrivate( SpeakersModel* parent ); 0036 0037 void fillModel(); 0038 0039 void handleInstallationProgress( int row, qreal progress ); 0040 0041 void handleInstallation( int ); 0042 0043 QHash<int, QByteArray> m_roleNames; 0044 }; 0045 0046 SpeakersModelItem::SpeakersModelItem() : m_newstuffIndex( -1 ) 0047 { 0048 // nothing to do 0049 } 0050 0051 bool SpeakersModelItem::lessThan( const SpeakersModelItem& one, const SpeakersModelItem& two ) 0052 { 0053 return one.m_file.fileName() < two.m_file.fileName(); 0054 } 0055 0056 SpeakersModelPrivate::SpeakersModelPrivate( SpeakersModel* parent ) : 0057 m_parent( parent ) 0058 { 0059 m_newstuffModel.setTargetDirectory(MarbleDirs::localPath() + QLatin1String("/audio/speakers")); 0060 m_newstuffModel.setProvider( "http://edu.kde.org/marble/newstuff/speakers.xml" ); 0061 QObject::connect( &m_newstuffModel, SIGNAL(modelReset()), m_parent, SLOT(fillModel()) ); 0062 QObject::connect( &m_newstuffModel, SIGNAL(installationProgressed(int,qreal)), 0063 m_parent, SLOT(handleInstallationProgress(int,qreal)) ); 0064 QObject::connect( &m_newstuffModel, SIGNAL(installationFinished(int)), m_parent, SLOT(handleInstallation(int)) ); 0065 } 0066 0067 void SpeakersModelPrivate::fillModel() 0068 { 0069 m_speakers.clear(); 0070 0071 QStringList const baseDirs = QStringList() << MarbleDirs::systemPath() << MarbleDirs::localPath(); 0072 for ( const QString &baseDir: baseDirs ) { 0073 const QString base = baseDir + QLatin1String("/audio/speakers/"); 0074 0075 QDir::Filters filter = QDir::Readable | QDir::Dirs | QDir::NoDotAndDotDot; 0076 QFileInfoList subdirs = QDir( base ).entryInfoList( filter, QDir::Name ); 0077 for( const QFileInfo &file: subdirs ) { 0078 SpeakersModelItem item; 0079 item.m_file = file; 0080 m_speakers << item; 0081 } 0082 } 0083 0084 for ( int i=0; i<m_newstuffModel.rowCount(); ++i ) { 0085 QModelIndex const index = m_newstuffModel.index( i ); 0086 QString const name = m_newstuffModel.data( index ).toString(); 0087 bool exists = false; 0088 for ( int j=0; j<m_speakers.size() && !exists; ++j ) { 0089 SpeakersModelItem &item = m_speakers[j]; 0090 if ( item.m_file.fileName() == name ) { 0091 item.m_newstuffIndex = i; 0092 exists = true; 0093 } 0094 } 0095 0096 if ( !exists ) { 0097 SpeakersModelItem item; 0098 QString const path = "%1/audio/speakers/%2"; 0099 item.m_file = QFileInfo( path.arg( MarbleDirs::localPath(), name ) ); 0100 item.m_newstuffIndex = i; 0101 m_speakers << item; 0102 } 0103 } 0104 0105 std::sort(m_speakers.begin(), m_speakers.end(), SpeakersModelItem::lessThan); 0106 m_parent->beginResetModel(); 0107 m_parent->endResetModel(); 0108 emit m_parent->countChanged(); 0109 } 0110 0111 void SpeakersModelPrivate::handleInstallation( int row ) 0112 { 0113 for ( int j=0; j<m_speakers.size(); ++j ) { 0114 if ( m_speakers[j].m_newstuffIndex == row ) { 0115 m_speakers[j].m_file.refresh(); 0116 QModelIndex const affected = m_parent->index( j ); 0117 emit m_parent->dataChanged( affected, affected ); 0118 emit m_parent->installationFinished( j ); 0119 } 0120 } 0121 } 0122 0123 void SpeakersModelPrivate::handleInstallationProgress( int row, qreal progress ) 0124 { 0125 for ( int j=0; j<m_speakers.size(); ++j ) { 0126 if ( m_speakers[j].m_newstuffIndex == row ) { 0127 emit m_parent->installationProgressed( j, progress ); 0128 } 0129 } 0130 } 0131 0132 SpeakersModel::SpeakersModel( QObject *parent ) : 0133 QAbstractListModel( parent ), d( new SpeakersModelPrivate( this ) ) 0134 { 0135 QHash<int,QByteArray> roles; 0136 roles[Path] = "path"; 0137 roles[Name] = "name"; 0138 roles[IsLocal] = "isLocal"; 0139 roles[IsRemote] = "isRemote"; 0140 d->m_roleNames = roles; 0141 0142 d->fillModel(); 0143 } 0144 0145 SpeakersModel::~SpeakersModel() 0146 { 0147 delete d; 0148 } 0149 0150 int SpeakersModel::rowCount ( const QModelIndex &parent ) const 0151 { 0152 if ( !parent.isValid() ) { 0153 return d->m_speakers.size(); 0154 } 0155 0156 return 0; 0157 } 0158 0159 QVariant SpeakersModel::data ( const QModelIndex &index, int role ) const 0160 { 0161 if ( index.isValid() && index.row() >= 0 && index.row() < d->m_speakers.size() ) { 0162 switch ( role ) { 0163 case Qt::DisplayRole: return d->m_speakers.at( index.row() ).m_file.fileName(); 0164 case Path: return d->m_speakers.at( index.row() ).m_file.absoluteFilePath(); 0165 case Name: return d->m_speakers.at( index.row() ).m_file.fileName(); 0166 case IsLocal: return d->m_speakers.at( index.row() ).m_file.exists(); 0167 case IsRemote: return d->m_speakers.at( index.row() ).m_newstuffIndex >= 0; 0168 } 0169 } 0170 0171 return QVariant(); 0172 } 0173 0174 QHash<int, QByteArray> SpeakersModel::roleNames() const 0175 { 0176 return d->m_roleNames; 0177 } 0178 0179 int SpeakersModel::indexOf( const QString &name ) 0180 { 0181 for( int i=0; i<d->m_speakers.size(); ++i ) { 0182 if ( d->m_speakers[i].m_file.absoluteFilePath() == name || d->m_speakers[i].m_file.fileName() == name ) { 0183 return i; 0184 } 0185 } 0186 return -1; 0187 } 0188 0189 QString SpeakersModel::path( int index ) 0190 { 0191 if ( index >= 0 && index <= d->m_speakers.size() ) { 0192 return d->m_speakers[index].m_file.absoluteFilePath(); 0193 } 0194 return QString(); 0195 } 0196 0197 void SpeakersModel::install( int index ) 0198 { 0199 if ( index >= 0 && index < d->m_speakers.size() ) { 0200 if ( d->m_speakers[index].m_newstuffIndex >= 0 ) { 0201 d->m_newstuffModel.install( d->m_speakers[index].m_newstuffIndex ); 0202 } 0203 } 0204 } 0205 0206 bool SpeakersModel::isLocal( int idx ) const 0207 { 0208 return data( index( idx ), IsLocal ).toBool(); 0209 } 0210 0211 bool SpeakersModel::isRemote( int idx ) const 0212 { 0213 return data( index( idx ), IsRemote ).toBool(); 0214 } 0215 0216 int SpeakersModel::count() const 0217 { 0218 return rowCount(); 0219 } 0220 0221 } 0222 0223 #include "moc_SpeakersModel.cpp"