File indexing completed on 2024-05-12 16:14:35
0001 // SPDX-FileCopyrightText: 2021 Han Young <hanyoung@protonmail.com> 0002 // SPDX-License-Identifier: LGPL-2.0-or-later 0003 0004 #include "soundspickermodel.h" 0005 0006 #include <vector> 0007 0008 #include <QDirIterator> 0009 #include <QStandardPaths> 0010 0011 class SoundsPickerModel::Private 0012 { 0013 public: 0014 QStringList defaultAudio; 0015 std::vector<QString> soundsVec; 0016 bool notification = false; 0017 QString theme = QStringLiteral("plasma-mobile"); 0018 }; 0019 0020 SoundsPickerModel::SoundsPickerModel(QObject *parent) 0021 : QAbstractListModel(parent) 0022 , d(std::make_unique<Private>()) 0023 { 0024 loadFiles(); 0025 } 0026 0027 void SoundsPickerModel::loadFiles() 0028 { 0029 d->soundsVec.clear(); 0030 const auto locations = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); 0031 const QString path = QStringLiteral("/sounds/") + d->theme + QStringLiteral("/stereo/"); 0032 0033 for (const auto &directory : locations) { 0034 if (QDir(directory + path).exists()) { 0035 QString subPath = directory + path; 0036 if (!d->notification && QDir(subPath + QStringLiteral("ringtone")).exists()) { 0037 subPath += QStringLiteral("ringtone"); 0038 } else if (d->notification && QDir(subPath + QStringLiteral("notification")).exists()) { 0039 subPath += QStringLiteral("notification"); 0040 } 0041 0042 QDirIterator it(subPath, QDir::Files, QDirIterator::Subdirectories); 0043 while (it.hasNext()) { 0044 d->soundsVec.push_back(it.next()); 0045 } 0046 } 0047 } 0048 } 0049 0050 SoundsPickerModel::~SoundsPickerModel() = default; 0051 0052 QHash<int, QByteArray> SoundsPickerModel::roleNames() const 0053 { 0054 return { 0055 {Roles::NameRole, QByteArrayLiteral("ringtoneName")}, 0056 {Roles::UrlRole, QByteArrayLiteral("sourceUrl")} 0057 }; 0058 } 0059 0060 bool SoundsPickerModel::notification() const 0061 { 0062 return d->notification; 0063 } 0064 0065 void SoundsPickerModel::setNotification(bool notification) 0066 { 0067 if (d->notification == notification) { 0068 return; 0069 } 0070 d->notification = notification; 0071 0072 bool needReset = false; 0073 QString path = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/") + d->theme + QStringLiteral("/stereo/"); 0074 if (!d->notification && QDir(path + QStringLiteral("ringtone")).exists()) { 0075 needReset = true; 0076 } else if (d->notification && QDir(path + QStringLiteral("notification")).exists()) { 0077 needReset = true; 0078 } 0079 0080 if (needReset) { 0081 beginResetModel(); 0082 loadFiles(); 0083 endResetModel(); 0084 rearrangeRingtoneOrder(); 0085 } 0086 } 0087 0088 QString SoundsPickerModel::initialSourceUrl(int index) 0089 { 0090 if (index >= 0 && index < (int)d->soundsVec.size()) { 0091 return d->soundsVec.at(index); 0092 } 0093 return {}; 0094 } 0095 0096 QVariant SoundsPickerModel::data(const QModelIndex &index, int role) const 0097 { 0098 if (!index.isValid() || index.row() < 0 || index.row() >= (int)d->soundsVec.size()) { 0099 return {}; 0100 } 0101 0102 if (role == NameRole) { 0103 auto ret = d->soundsVec.at(index.row()); 0104 int suffixPos = ret.lastIndexOf(QLatin1Char('.')); 0105 if (suffixPos > 0) { 0106 ret.truncate(suffixPos); 0107 } 0108 int pathPos = ret.lastIndexOf(QLatin1Char('/')); 0109 if (pathPos >= 0) { 0110 ret.remove(0, pathPos + 1); 0111 } 0112 return ret; 0113 } 0114 return d->soundsVec.at(index.row()); 0115 } 0116 int SoundsPickerModel::rowCount(const QModelIndex& parent) const { 0117 Q_UNUSED(parent) 0118 return d->soundsVec.size(); 0119 } 0120 0121 const QStringList &SoundsPickerModel::defaultAudio() const 0122 { 0123 return d->defaultAudio; 0124 } 0125 0126 void SoundsPickerModel::setDefaultAudio(const QStringList &audio) 0127 { 0128 d->defaultAudio = audio; 0129 rearrangeRingtoneOrder(); 0130 } 0131 0132 const QString &SoundsPickerModel::theme() const 0133 { 0134 return d->theme; 0135 } 0136 0137 void SoundsPickerModel::setTheme(const QString &theme) 0138 { 0139 if (d->theme == theme) { 0140 return; 0141 } 0142 d->theme = theme; 0143 0144 beginResetModel(); 0145 loadFiles(); 0146 endResetModel(); 0147 rearrangeRingtoneOrder(); 0148 } 0149 0150 void SoundsPickerModel::rearrangeRingtoneOrder() 0151 { 0152 auto i {0}; 0153 for (int j = 0; j < (int)d->soundsVec.size(); j++) { 0154 if (d->defaultAudio.contains(data(index(j), NameRole).toString())) { 0155 std::swap(d->soundsVec[j], d->soundsVec[i]); 0156 Q_EMIT dataChanged(index(j), index(j)); 0157 Q_EMIT dataChanged(index(i), index(i)); 0158 i++; 0159 } 0160 } 0161 } 0162 0163 #include "moc_soundspickermodel.cpp"