From b6a64a2495d9670ae9afc1b73b2a2744327f280c Mon Sep 17 00:00:00 2001 From: Gary Wang Date: Sun, 9 Feb 2025 13:12:37 +0800 Subject: [PATCH] chore: tidy code and hello 2025 :) --- mainwindow.cpp | 2 +- playlistmanager.cpp | 508 ++++++++++++++++++++++---------------------- playlistmanager.h | 170 +++++++-------- seekableslider.h | 48 ++--- 4 files changed, 363 insertions(+), 365 deletions(-) diff --git a/mainwindow.cpp b/mainwindow.cpp index 755f1c2..ceaf97e 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -678,7 +678,7 @@ void MainWindow::on_actionHelp_triggered() "\n" "[Source Code](https://github.com/BLumia/pineapple-music)\n" "\n" - "Copyright © 2024 [BLumia](https://github.com/BLumia/)" + "Copyright © 2025 [BLumia](https://github.com/BLumia/)" ); infoBox.setTextFormat(Qt::MarkdownText); infoBox.exec(); diff --git a/playlistmanager.cpp b/playlistmanager.cpp index c9aa1e6..c3a17ac 100644 --- a/playlistmanager.cpp +++ b/playlistmanager.cpp @@ -1,255 +1,253 @@ -// SPDX-FileCopyrightText: 2024 Gary Wang -// -// SPDX-License-Identifier: MIT - -#include "playlistmanager.h" - -#include -#include -#include -#include - -PlaylistModel::PlaylistModel(QObject *parent) - : QAbstractListModel(parent) -{ - -} - -PlaylistModel::~PlaylistModel() -{ - -} - -void PlaylistModel::setPlaylist(const QList &urls) -{ - beginResetModel(); - m_playlist = urls; - endResetModel(); -} - -QModelIndex PlaylistModel::loadPlaylist(const QList & urls) -{ - if (urls.isEmpty()) return QModelIndex(); - if (urls.count() == 1) { - return loadPlaylist(urls.constFirst()); - } else { - setPlaylist(urls); - return index(0); - } -} - -QModelIndex PlaylistModel::loadPlaylist(const QUrl &url) -{ - QFileInfo info(url.toLocalFile()); - QDir dir(info.path()); - QString && currentFileName = info.fileName(); - - if (dir.path() == m_currentDir) { - int idx = indexOf(url); - return idx == -1 ? appendToPlaylist(url) : index(idx); - } - - QStringList entryList = dir.entryList( - m_autoLoadSuffixes, - QDir::Files | QDir::NoSymLinks, QDir::NoSort); - - QCollator collator; - collator.setNumericMode(true); - - std::sort(entryList.begin(), entryList.end(), collator); - - QList playlist; - - int idx = -1; - for (int i = 0; i < entryList.count(); i++) { - const QString & fileName = entryList.at(i); - const QString & oneEntry = dir.absoluteFilePath(fileName); - const QUrl & url = QUrl::fromLocalFile(oneEntry); - playlist.append(url); - if (fileName == currentFileName) { - idx = i; - } - } - if (idx == -1) { - idx = playlist.count(); - playlist.append(url); - } - m_currentDir = dir.path(); - - setPlaylist(playlist); - - return index(idx); -} - -QModelIndex PlaylistModel::appendToPlaylist(const QUrl &url) -{ - const int lastIndex = rowCount(); - beginInsertRows(QModelIndex(), lastIndex, lastIndex); - m_playlist.append(url); - endInsertRows(); - return index(lastIndex); -} - -bool PlaylistModel::removeAt(int index) -{ - if (index < 0 || index >= rowCount()) return false; - beginRemoveRows(QModelIndex(), index, index); - m_playlist.removeAt(index); - endRemoveRows(); - return true; -} - -int PlaylistModel::indexOf(const QUrl &url) const -{ - return m_playlist.indexOf(url); -} - -QUrl PlaylistModel::urlByIndex(int index) const -{ - return m_playlist.value(index); -} - -QStringList PlaylistModel::autoLoadFilterSuffixes() const -{ - return m_autoLoadSuffixes; -} - -QHash PlaylistModel::roleNames() const -{ - QHash result = QAbstractListModel::roleNames(); - result.insert(UrlRole, "url"); - return result; -} - -int PlaylistModel::rowCount(const QModelIndex &parent) const -{ - return m_playlist.count(); -} - -QVariant PlaylistModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid()) return QVariant(); - - switch (role) { - case Qt::DisplayRole: - return m_playlist.at(index.row()).fileName(); - case UrlRole: - return m_playlist.at(index.row()); - } - - return QVariant(); -} - -PlaylistManager::PlaylistManager(QObject *parent) - : QObject(parent) -{ - connect(&m_model, &PlaylistModel::rowsRemoved, this, - [this](const QModelIndex &, int, int) { - if (m_model.rowCount() <= m_currentIndex) { - setProperty("currentIndex", m_currentIndex - 1); - } - }); - - auto onRowCountChanged = [this](){ - emit totalCountChanged(m_model.rowCount()); - }; - - connect(&m_model, &PlaylistModel::rowsInserted, this, onRowCountChanged); - connect(&m_model, &PlaylistModel::rowsRemoved, this, onRowCountChanged); - connect(&m_model, &PlaylistModel::modelReset, this, onRowCountChanged); -} - -PlaylistManager::~PlaylistManager() -{ - -} - -PlaylistModel *PlaylistManager::model() -{ - return &m_model; -} - -void PlaylistManager::setPlaylist(const QList &urls) -{ - m_model.setPlaylist(urls); -} - -QModelIndex PlaylistManager::loadPlaylist(const QList &urls) -{ - QModelIndex idx = m_model.loadPlaylist(urls); - setProperty("currentIndex", idx.row()); - return idx; -} - -QModelIndex PlaylistManager::loadPlaylist(const QUrl &url) -{ - QModelIndex idx = m_model.loadPlaylist(url); - setProperty("currentIndex", idx.row()); - return idx; -} - -int PlaylistManager::totalCount() const -{ - return m_model.rowCount(); -} - -QModelIndex PlaylistManager::previousIndex() const -{ - int count = totalCount(); - if (count == 0) return QModelIndex(); - - return m_model.index(m_currentIndex - 1 < 0 ? count - 1 : m_currentIndex - 1); -} - -QModelIndex PlaylistManager::nextIndex() const -{ - int count = totalCount(); - if (count == 0) return QModelIndex(); - - return m_model.index(m_currentIndex + 1 == count ? 0 : m_currentIndex + 1); -} - -QModelIndex PlaylistManager::curIndex() const -{ - return m_model.index(m_currentIndex); -} - -void PlaylistManager::setCurrentIndex(const QModelIndex &index) -{ - if (index.isValid() && index.row() >= 0 && index.row() < totalCount()) { - setProperty("currentIndex", index.row()); - } -} - -QUrl PlaylistManager::urlByIndex(const QModelIndex &index) -{ - return m_model.urlByIndex(index.row()); -} - -QString PlaylistManager::localFileByIndex(const QModelIndex &index) -{ - return urlByIndex(index).toLocalFile(); -} - -bool PlaylistManager::removeAt(const QModelIndex &index) -{ - return m_model.removeAt(index.row()); -} - -void PlaylistManager::setAutoLoadFilterSuffixes(const QStringList &nameFilters) -{ - m_model.setProperty("autoLoadFilterSuffixes", nameFilters); -} - -QList PlaylistManager::convertToUrlList(const QStringList &files) -{ - QList urlList; - for (const QString & str : std::as_const(files)) { - QUrl url = QUrl::fromLocalFile(str); - if (url.isValid()) { - urlList.append(url); - } - } - - return urlList; -} +// SPDX-FileCopyrightText: 2025 Gary Wang +// +// SPDX-License-Identifier: MIT + +#include "playlistmanager.h" + +#include +#include +#include +#include + +PlaylistModel::PlaylistModel(QObject *parent) + : QAbstractListModel(parent) +{ + +} + +PlaylistModel::~PlaylistModel() += default; + +void PlaylistModel::setPlaylist(const QList &urls) +{ + beginResetModel(); + m_playlist = urls; + endResetModel(); +} + +QModelIndex PlaylistModel::loadPlaylist(const QList & urls) +{ + if (urls.isEmpty()) return {}; + if (urls.count() == 1) { + return loadPlaylist(urls.constFirst()); + } else { + setPlaylist(urls); + return index(0); + } +} + +QModelIndex PlaylistModel::loadPlaylist(const QUrl &url) +{ + QFileInfo info(url.toLocalFile()); + QDir dir(info.path()); + QString && currentFileName = info.fileName(); + + if (dir.path() == m_currentDir) { + int idx = indexOf(url); + return idx == -1 ? appendToPlaylist(url) : index(idx); + } + + QStringList entryList = dir.entryList( + m_autoLoadSuffixes, + QDir::Files | QDir::NoSymLinks, QDir::NoSort); + + QCollator collator; + collator.setNumericMode(true); + + std::sort(entryList.begin(), entryList.end(), collator); + + QList playlist; + + int idx = -1; + for (int i = 0; i < entryList.count(); i++) { + const QString & fileName = entryList.at(i); + const QString & oneEntry = dir.absoluteFilePath(fileName); + const QUrl & url = QUrl::fromLocalFile(oneEntry); + playlist.append(url); + if (fileName == currentFileName) { + idx = i; + } + } + if (idx == -1) { + idx = playlist.count(); + playlist.append(url); + } + m_currentDir = dir.path(); + + setPlaylist(playlist); + + return index(idx); +} + +QModelIndex PlaylistModel::appendToPlaylist(const QUrl &url) +{ + const int lastIndex = rowCount(); + beginInsertRows(QModelIndex(), lastIndex, lastIndex); + m_playlist.append(url); + endInsertRows(); + return index(lastIndex); +} + +bool PlaylistModel::removeAt(int index) +{ + if (index < 0 || index >= rowCount()) return false; + beginRemoveRows(QModelIndex(), index, index); + m_playlist.removeAt(index); + endRemoveRows(); + return true; +} + +int PlaylistModel::indexOf(const QUrl &url) const +{ + return m_playlist.indexOf(url); +} + +QUrl PlaylistModel::urlByIndex(int index) const +{ + return m_playlist.value(index); +} + +QStringList PlaylistModel::autoLoadFilterSuffixes() const +{ + return m_autoLoadSuffixes; +} + +QHash PlaylistModel::roleNames() const +{ + QHash result = QAbstractListModel::roleNames(); + result.insert(UrlRole, "url"); + return result; +} + +int PlaylistModel::rowCount(const QModelIndex &parent) const +{ + return m_playlist.count(); +} + +QVariant PlaylistModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) return {}; + + switch (role) { + case Qt::DisplayRole: + return m_playlist.at(index.row()).fileName(); + case UrlRole: + return m_playlist.at(index.row()); + } + + return {}; +} + +PlaylistManager::PlaylistManager(QObject *parent) + : QObject(parent) +{ + connect(&m_model, &PlaylistModel::rowsRemoved, this, + [this](const QModelIndex &, int, int) { + if (m_model.rowCount() <= m_currentIndex) { + setProperty("currentIndex", m_currentIndex - 1); + } + }); + + auto onRowCountChanged = [this](){ + emit totalCountChanged(m_model.rowCount()); + }; + + connect(&m_model, &PlaylistModel::rowsInserted, this, onRowCountChanged); + connect(&m_model, &PlaylistModel::rowsRemoved, this, onRowCountChanged); + connect(&m_model, &PlaylistModel::modelReset, this, onRowCountChanged); +} + +PlaylistManager::~PlaylistManager() +{ + +} + +PlaylistModel *PlaylistManager::model() +{ + return &m_model; +} + +void PlaylistManager::setPlaylist(const QList &urls) +{ + m_model.setPlaylist(urls); +} + +QModelIndex PlaylistManager::loadPlaylist(const QList &urls) +{ + QModelIndex idx = m_model.loadPlaylist(urls); + setProperty("currentIndex", idx.row()); + return idx; +} + +QModelIndex PlaylistManager::loadPlaylist(const QUrl &url) +{ + QModelIndex idx = m_model.loadPlaylist(url); + setProperty("currentIndex", idx.row()); + return idx; +} + +int PlaylistManager::totalCount() const +{ + return m_model.rowCount(); +} + +QModelIndex PlaylistManager::previousIndex() const +{ + int count = totalCount(); + if (count == 0) return {}; + + return m_model.index(m_currentIndex - 1 < 0 ? count - 1 : m_currentIndex - 1); +} + +QModelIndex PlaylistManager::nextIndex() const +{ + int count = totalCount(); + if (count == 0) return {}; + + return m_model.index(m_currentIndex + 1 == count ? 0 : m_currentIndex + 1); +} + +QModelIndex PlaylistManager::curIndex() const +{ + return m_model.index(m_currentIndex); +} + +void PlaylistManager::setCurrentIndex(const QModelIndex &index) +{ + if (index.isValid() && index.row() >= 0 && index.row() < totalCount()) { + setProperty("currentIndex", index.row()); + } +} + +QUrl PlaylistManager::urlByIndex(const QModelIndex &index) +{ + return m_model.urlByIndex(index.row()); +} + +QString PlaylistManager::localFileByIndex(const QModelIndex &index) +{ + return urlByIndex(index).toLocalFile(); +} + +bool PlaylistManager::removeAt(const QModelIndex &index) +{ + return m_model.removeAt(index.row()); +} + +void PlaylistManager::setAutoLoadFilterSuffixes(const QStringList &nameFilters) +{ + m_model.setProperty("autoLoadFilterSuffixes", nameFilters); +} + +QList PlaylistManager::convertToUrlList(const QStringList &files) +{ + QList urlList; + for (const QString & str : std::as_const(files)) { + QUrl url = QUrl::fromLocalFile(str); + if (url.isValid()) { + urlList.append(url); + } + } + + return urlList; +} diff --git a/playlistmanager.h b/playlistmanager.h index 73c7549..9fe8b5b 100644 --- a/playlistmanager.h +++ b/playlistmanager.h @@ -1,85 +1,85 @@ -// SPDX-FileCopyrightText: 2024 Gary Wang -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include -#include - -class PlaylistModel : public QAbstractListModel -{ - Q_OBJECT -public: - enum PlaylistRole { - UrlRole = Qt::UserRole - }; - Q_ENUM(PlaylistRole) - Q_PROPERTY(QStringList autoLoadFilterSuffixes MEMBER m_autoLoadSuffixes NOTIFY autoLoadFilterSuffixesChanged) - - explicit PlaylistModel(QObject *parent = nullptr); - ~PlaylistModel(); - - void setPlaylist(const QList & urls); - QModelIndex loadPlaylist(const QList & urls); - QModelIndex loadPlaylist(const QUrl & url); - QModelIndex appendToPlaylist(const QUrl & url); - bool removeAt(int index); - int indexOf(const QUrl & url) const; - QUrl urlByIndex(int index) const; - QStringList autoLoadFilterSuffixes() const; - - QHash roleNames() const override; - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - -signals: - void autoLoadFilterSuffixesChanged(QStringList suffixes); - -private: - // model data - QList m_playlist; - // properties - QStringList m_autoLoadSuffixes = {}; - // internal - QString m_currentDir; -}; - -class PlaylistManager : public QObject -{ - Q_OBJECT -public: - Q_PROPERTY(int currentIndex MEMBER m_currentIndex NOTIFY currentIndexChanged) - Q_PROPERTY(QStringList autoLoadFilterSuffixes WRITE setAutoLoadFilterSuffixes) - Q_PROPERTY(PlaylistModel * model READ model CONSTANT) - - explicit PlaylistManager(QObject *parent = nullptr); - ~PlaylistManager(); - - PlaylistModel * model(); - - void setPlaylist(const QList & url); - Q_INVOKABLE QModelIndex loadPlaylist(const QList & urls); - Q_INVOKABLE QModelIndex loadPlaylist(const QUrl & url); - - int totalCount() const; - QModelIndex previousIndex() const; - QModelIndex nextIndex() const; - QModelIndex curIndex() const; - void setCurrentIndex(const QModelIndex & index); - QUrl urlByIndex(const QModelIndex & index); - QString localFileByIndex(const QModelIndex & index); - bool removeAt(const QModelIndex & index); - - void setAutoLoadFilterSuffixes(const QStringList &nameFilters); - - static QList convertToUrlList(const QStringList & files); - -signals: - void currentIndexChanged(int index); - void totalCountChanged(int count); - -private: - int m_currentIndex = -1; - PlaylistModel m_model; -}; +// SPDX-FileCopyrightText: 2025 Gary Wang +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +class PlaylistModel : public QAbstractListModel +{ + Q_OBJECT +public: + enum PlaylistRole { + UrlRole = Qt::UserRole + }; + Q_ENUM(PlaylistRole) + Q_PROPERTY(QStringList autoLoadFilterSuffixes MEMBER m_autoLoadSuffixes NOTIFY autoLoadFilterSuffixesChanged) + + explicit PlaylistModel(QObject *parent = nullptr); + ~PlaylistModel() override; + + void setPlaylist(const QList & urls); + QModelIndex loadPlaylist(const QList & urls); + QModelIndex loadPlaylist(const QUrl & url); + QModelIndex appendToPlaylist(const QUrl & url); + bool removeAt(int index); + int indexOf(const QUrl & url) const; + QUrl urlByIndex(int index) const; + QStringList autoLoadFilterSuffixes() const; + + QHash roleNames() const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + +signals: + void autoLoadFilterSuffixesChanged(QStringList suffixes); + +private: + // model data + QList m_playlist; + // properties + QStringList m_autoLoadSuffixes = {}; + // internal + QString m_currentDir; +}; + +class PlaylistManager : public QObject +{ + Q_OBJECT +public: + Q_PROPERTY(int currentIndex MEMBER m_currentIndex NOTIFY currentIndexChanged) + Q_PROPERTY(QStringList autoLoadFilterSuffixes WRITE setAutoLoadFilterSuffixes) + Q_PROPERTY(PlaylistModel * model READ model CONSTANT) + + explicit PlaylistManager(QObject *parent = nullptr); + ~PlaylistManager(); + + PlaylistModel * model(); + + void setPlaylist(const QList & url); + Q_INVOKABLE QModelIndex loadPlaylist(const QList & urls); + Q_INVOKABLE QModelIndex loadPlaylist(const QUrl & url); + + int totalCount() const; + QModelIndex previousIndex() const; + QModelIndex nextIndex() const; + QModelIndex curIndex() const; + void setCurrentIndex(const QModelIndex & index); + QUrl urlByIndex(const QModelIndex & index); + QString localFileByIndex(const QModelIndex & index); + bool removeAt(const QModelIndex & index); + + void setAutoLoadFilterSuffixes(const QStringList &nameFilters); + + static QList convertToUrlList(const QStringList & files); + +signals: + void currentIndexChanged(int index); + void totalCountChanged(int count); + +private: + int m_currentIndex = -1; + PlaylistModel m_model; +}; diff --git a/seekableslider.h b/seekableslider.h index 92a5a44..38bc2c5 100644 --- a/seekableslider.h +++ b/seekableslider.h @@ -1,24 +1,24 @@ -// SPDX-FileCopyrightText: 2024 Gary Wang -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include -#include - -class SeekableSlider : public QSlider -{ - Q_OBJECT -public: - explicit SeekableSlider(QWidget *parent = nullptr); - ~SeekableSlider() = default; - -signals: - -public slots: - -protected: - void mouseReleaseEvent(QMouseEvent *event) override; -}; - +// SPDX-FileCopyrightText: 2025 Gary Wang +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +class SeekableSlider : public QSlider +{ + Q_OBJECT +public: + explicit SeekableSlider(QWidget *parent = nullptr); + ~SeekableSlider() override = default; + +signals: + +public slots: + +protected: + void mouseReleaseEvent(QMouseEvent *event) override; +}; +