Warning, file /utilities/kairo/src/circuitlistmodel.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* This file is part of Kairo Timer 0002 0003 SPDX-FileCopyrightText: 2016 (c) Kevin Ottens <ervin@kde.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0006 0007 */ 0008 0009 #include "circuitlistmodel.h" 0010 0011 #include <QDebug> 0012 #include <QFileSystemWatcher> 0013 #include <QStandardPaths> 0014 0015 #include <memory> 0016 0017 #include "circuitreader.h" 0018 0019 #ifdef Q_OS_ANDROID 0020 #include <QStorageInfo> 0021 #endif 0022 0023 CircuitListModel::CircuitListModel(QObject *parent) 0024 : QAbstractListModel{parent}, 0025 m_watcher{new QFileSystemWatcher{this}} 0026 { 0027 auto dir = storageDir(); 0028 if (!dir.exists()) 0029 dir.mkpath("."); 0030 0031 connect(m_watcher, &QFileSystemWatcher::directoryChanged, 0032 this, &CircuitListModel::onDirectoryContentChanged); 0033 connect(m_watcher, &QFileSystemWatcher::fileChanged, 0034 this, &CircuitListModel::onDirectoryContentChanged); 0035 m_watcher->addPath(dir.path()); 0036 0037 onDirectoryContentChanged(); 0038 } 0039 0040 QHash<int, QByteArray> CircuitListModel::roleNames() const 0041 { 0042 auto roles = QAbstractListModel::roleNames(); 0043 roles.insert(FilePathRole, "filePath"); 0044 return roles; 0045 } 0046 0047 int CircuitListModel::rowCount(const QModelIndex &parent) const 0048 { 0049 if (!parent.isValid()) 0050 return m_circuits.size(); 0051 else 0052 return 0; 0053 } 0054 0055 QVariant CircuitListModel::data(const QModelIndex &index, int role) const 0056 { 0057 if (index.parent().isValid() 0058 || index.row() < 0 0059 || index.row() >= rowCount() 0060 || index.column() != 0) { 0061 return {}; 0062 } 0063 0064 auto circuitFile = m_circuits.at(index.row()); 0065 0066 switch (role) { 0067 case Qt::DisplayRole: 0068 return circuitFile.name; 0069 case FilePathRole: 0070 return circuitFile.filePath; 0071 default: 0072 return {}; 0073 } 0074 } 0075 0076 CircuitModel CircuitListModel::loadCircuit(int index) 0077 { 0078 if (index < 0 || index >= m_circuits.size()) { 0079 qWarning() << "Wrong index passed to loadCircuit"; 0080 return {}; 0081 } 0082 0083 const auto path = m_circuits.at(index).filePath; 0084 auto file = std::unique_ptr<QFile>(new QFile(path)); 0085 auto reader = CircuitReader{file.get()}; 0086 return reader.readCircuit(); 0087 } 0088 0089 QString CircuitListModel::path() const 0090 { 0091 #ifndef Q_OS_ANDROID 0092 return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation); 0093 #else 0094 auto volumes = QStorageInfo::mountedVolumes(); 0095 auto paths = QStringList(); 0096 paths.reserve(volumes.size()); 0097 std::transform(volumes.constBegin(), volumes.constEnd(), 0098 std::back_inserter(paths), 0099 [] (const QStorageInfo &volume) { 0100 return volume.rootPath(); 0101 }); 0102 auto validPaths = QStringList(); 0103 std::copy_if(paths.constBegin(), paths.constEnd(), 0104 std::back_inserter(validPaths), 0105 [] (const QString &path) { 0106 return path.startsWith("/storage/") && !path.startsWith("/storage/emulated"); 0107 }); 0108 return validPaths.first() + "/Android/Kairo"; 0109 #endif 0110 } 0111 0112 void CircuitListModel::onDirectoryContentChanged() 0113 { 0114 const auto entries = storageDir().entryInfoList({"*.kairo"}, QDir::Files|QDir::Readable); 0115 auto circuits = QVector<CircuitFile>{}; 0116 std::transform(entries.constBegin(), entries.constEnd(), 0117 std::back_inserter(circuits), 0118 [] (const QFileInfo &entry) { 0119 const auto path = entry.absoluteFilePath(); 0120 auto file = std::unique_ptr<QFile>(new QFile(path)); 0121 auto reader = CircuitReader{file.get()}; 0122 const auto metaData = reader.readMetaData(); 0123 return CircuitFile{path, metaData.value("name").toString()}; 0124 }); 0125 std::sort(circuits.begin(), circuits.end()); 0126 0127 if (m_circuits != circuits) { 0128 beginResetModel(); 0129 m_circuits = circuits; 0130 endResetModel(); 0131 } 0132 } 0133 0134 QDir CircuitListModel::storageDir() 0135 { 0136 return {path()}; 0137 } 0138 0139 bool CircuitListModel::CircuitFile::operator<(const CircuitListModel::CircuitFile &other) const 0140 { 0141 return name < other.name; 0142 } 0143 0144 bool CircuitListModel::CircuitFile::operator==(const CircuitListModel::CircuitFile &other) const 0145 { 0146 return name == other.name 0147 && filePath == other.filePath; 0148 }