File indexing completed on 2024-05-05 04:50:49

0001 /*
0002  * SPDX-FileCopyrightText: 2021 George Florea Bănuș <georgefb899@gmail.com>
0003  *
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  */
0006 
0007 #include "recentfilesmodel.h"
0008 
0009 #include <KSharedConfig>
0010 
0011 #include <QJsonDocument>
0012 #include <QMenu>
0013 #include <QProcess>
0014 
0015 #include "application.h"
0016 #include "generalsettings.h"
0017 #include "global.h"
0018 
0019 RecentFilesModel::RecentFilesModel(QObject *parent)
0020     : QAbstractListModel(parent)
0021 {
0022     auto config = KSharedConfig::openConfig(Global::instance()->appConfigFilePath(Global::ConfigFile::RecentFiles));
0023     m_recentFilesConfigGroup = config->group(QStringLiteral("RecentFiles"));
0024     setMaxRecentFiles(GeneralSettings::maxRecentFiles());
0025     populate();
0026 }
0027 
0028 int RecentFilesModel::rowCount(const QModelIndex &parent) const
0029 {
0030     if (parent.isValid()) {
0031         return 0;
0032     }
0033 
0034     return m_urls.count();
0035 }
0036 
0037 QVariant RecentFilesModel::data(const QModelIndex &index, int role) const
0038 {
0039     if (!index.isValid()) {
0040         return QVariant();
0041     }
0042 
0043     RecentFile recentFile = m_urls.at(index.row());
0044 
0045     switch (role) {
0046     case PathRole:
0047         return QVariant(recentFile.url);
0048     case NameRole:
0049         return QVariant(recentFile.name);
0050     }
0051 
0052     return QVariant();
0053 }
0054 
0055 QHash<int, QByteArray> RecentFilesModel::roleNames() const
0056 {
0057     QHash<int, QByteArray> roles;
0058     roles[PathRole] = "path";
0059     roles[NameRole] = "name";
0060 
0061     return roles;
0062 }
0063 
0064 void RecentFilesModel::populate()
0065 {
0066     if (GeneralSettings::maxRecentFiles() <= 0) {
0067         deleteEntries();
0068         return;
0069     }
0070 
0071     clear();
0072     setMaxRecentFiles(GeneralSettings::maxRecentFiles());
0073 
0074     for (int i = 0; i < maxRecentFiles(); i++) {
0075         auto file = m_recentFilesConfigGroup.readPathEntry(QStringLiteral("File%1").arg(i + 1), QString());
0076         auto name = m_recentFilesConfigGroup.readPathEntry(QStringLiteral("Name%1").arg(i + 1), QString());
0077         if (file.isEmpty()) {
0078             break;
0079         }
0080         QUrl url(file);
0081         if (!url.isLocalFile() && url.scheme().isEmpty()) {
0082             url.setScheme(QStringLiteral("file"));
0083         }
0084         RecentFile recentFile;
0085         recentFile.url = url;
0086         recentFile.name = name;
0087 
0088         beginInsertRows(QModelIndex(), i, i);
0089         m_urls.append(recentFile);
0090         endInsertRows();
0091     }
0092 }
0093 
0094 void RecentFilesModel::addUrl(const QString &path, const QString &name)
0095 {
0096     if (maxRecentFiles() == 0) {
0097         return;
0098     }
0099 
0100     auto url = QUrl::fromUserInput(path);
0101     if (!url.isValid()) {
0102         return;
0103     }
0104 
0105     if (url.scheme().startsWith(QStringLiteral("http")) && name.isEmpty()) {
0106         getHttpItemInfo(url);
0107     }
0108 
0109     auto _name = name == QString() ? url.fileName() : name;
0110 
0111     for (int i{0}; i < m_urls.count(); ++i) {
0112         if (url == m_urls[i].url) {
0113             beginRemoveRows(QModelIndex(), i, i);
0114             m_urls.takeAt(i);
0115             endRemoveRows();
0116             break;
0117         }
0118     }
0119 
0120     RecentFile recentFile;
0121     recentFile.url = url;
0122     recentFile.name = _name;
0123 
0124     if (m_urls.count() == maxRecentFiles()) {
0125         beginRemoveRows(QModelIndex(), m_urls.count() - 1, m_urls.count() - 1);
0126         m_urls.removeLast();
0127         endRemoveRows();
0128     }
0129 
0130     beginInsertRows(QModelIndex(), 0, 0);
0131     m_urls.prepend(recentFile);
0132     endInsertRows();
0133 
0134     saveEntries();
0135 }
0136 
0137 void RecentFilesModel::clear()
0138 {
0139     beginResetModel();
0140     m_urls.clear();
0141     endResetModel();
0142 }
0143 
0144 void RecentFilesModel::deleteEntries()
0145 {
0146     clear();
0147     m_recentFilesConfigGroup.deleteGroup();
0148     m_recentFilesConfigGroup.sync();
0149 }
0150 
0151 void RecentFilesModel::saveEntries()
0152 {
0153     m_recentFilesConfigGroup.deleteGroup();
0154     int i = 1;
0155     for (const auto &[url, name] : std::as_const(m_urls)) {
0156         m_recentFilesConfigGroup.writePathEntry(QStringLiteral("File%1").arg(i), url.toDisplayString(QUrl::PreferLocalFile));
0157         m_recentFilesConfigGroup.writePathEntry(QStringLiteral("Name%1").arg(i), name);
0158 
0159         ++i;
0160     }
0161     m_recentFilesConfigGroup.sync();
0162 }
0163 
0164 int RecentFilesModel::maxRecentFiles() const
0165 {
0166     return m_maxRecentFiles;
0167 }
0168 
0169 void RecentFilesModel::setMaxRecentFiles(int _maxRecentFiles)
0170 {
0171     m_maxRecentFiles = _maxRecentFiles;
0172 }
0173 
0174 void RecentFilesModel::getHttpItemInfo(const QUrl &url)
0175 {
0176     auto ytdlProcess = new QProcess();
0177     ytdlProcess->setProgram(Application::youtubeDlExecutable());
0178     ytdlProcess->setArguments(QStringList() << QStringLiteral("-j") << url.toString());
0179     ytdlProcess->start();
0180 
0181     connect(ytdlProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [=](int, QProcess::ExitStatus) {
0182         QString json = QString::fromUtf8(ytdlProcess->readAllStandardOutput());
0183         QString title = QJsonDocument::fromJson(json.toUtf8())[QStringLiteral("title")].toString();
0184         if (title.isEmpty()) {
0185             return;
0186         }
0187 
0188         addUrl(url.toString(), title);
0189     });
0190 }
0191 
0192 #include "moc_recentfilesmodel.cpp"