From c4cb5ea76452b2f175e78e149381474a2d5c8952 Mon Sep 17 00:00:00 2001 From: Gary Wang Date: Tue, 23 Jul 2024 23:08:09 +0800 Subject: [PATCH] quick: same-folder playlist support --- player/playlistmanager.cpp | 30 ++++++++-------- player/playlistmanager.h | 9 +++-- quick/main.cpp | 3 ++ quick/main.qml | 73 +++++++++++++++++++++++++++++++++++++- 4 files changed, 97 insertions(+), 18 deletions(-) diff --git a/player/playlistmanager.cpp b/player/playlistmanager.cpp index 9070ca5..895997a 100644 --- a/player/playlistmanager.cpp +++ b/player/playlistmanager.cpp @@ -34,7 +34,7 @@ QModelIndex PlaylistModel::loadPlaylist(const QList & urls) return loadPlaylist(urls.constFirst()); } else { setPlaylist(urls); - return createIndex(0); + return index(0); } } @@ -45,8 +45,8 @@ QModelIndex PlaylistModel::loadPlaylist(const QUrl &url) QString && currentFileName = info.fileName(); if (dir.path() == m_currentDir) { - int index = indexOf(url); - return index == -1 ? appendToPlaylist(url) : createIndex(index); + int idx = indexOf(url); + return idx == -1 ? appendToPlaylist(url) : index(idx); } QStringList entryList = dir.entryList( @@ -60,25 +60,25 @@ QModelIndex PlaylistModel::loadPlaylist(const QUrl &url) QList playlist; - int index = -1; + 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) { - index = i; + idx = i; } } - if (index == -1) { - index = playlist.count(); + if (idx == -1) { + idx = playlist.count(); playlist.append(url); } m_currentDir = dir.path(); setPlaylist(playlist); - return createIndex(index); + return index(idx); } QModelIndex PlaylistModel::appendToPlaylist(const QUrl &url) @@ -87,7 +87,7 @@ QModelIndex PlaylistModel::appendToPlaylist(const QUrl &url) beginInsertRows(QModelIndex(), lastIndex, lastIndex); m_playlist.append(url); endInsertRows(); - return createIndex(lastIndex); + return index(lastIndex); } bool PlaylistModel::removeAt(int index) @@ -114,9 +114,11 @@ QStringList PlaylistModel::autoLoadFilterSuffixes() const return m_autoLoadSuffixes; } -QModelIndex PlaylistModel::createIndex(int row) const +QHash PlaylistModel::roleNames() const { - return QAbstractItemModel::createIndex(row, 0, nullptr); + QHash result = QAbstractListModel::roleNames(); + result.insert(UrlRole, "url"); + return result; } int PlaylistModel::rowCount(const QModelIndex &parent) const @@ -196,7 +198,7 @@ QModelIndex PlaylistManager::previousIndex() const int count = totalCount(); if (count == 0) return QModelIndex(); - return m_model.createIndex(m_currentIndex - 1 < 0 ? count - 1 : m_currentIndex - 1); + return m_model.index(m_currentIndex - 1 < 0 ? count - 1 : m_currentIndex - 1); } QModelIndex PlaylistManager::nextIndex() const @@ -204,12 +206,12 @@ QModelIndex PlaylistManager::nextIndex() const int count = totalCount(); if (count == 0) return QModelIndex(); - return m_model.createIndex(m_currentIndex + 1 == count ? 0 : m_currentIndex + 1); + return m_model.index(m_currentIndex + 1 == count ? 0 : m_currentIndex + 1); } QModelIndex PlaylistManager::curIndex() const { - return m_model.createIndex(m_currentIndex); + return m_model.index(m_currentIndex); } void PlaylistManager::setCurrentIndex(const QModelIndex &index) diff --git a/player/playlistmanager.h b/player/playlistmanager.h index dd31be8..cdcdb52 100644 --- a/player/playlistmanager.h +++ b/player/playlistmanager.h @@ -4,6 +4,7 @@ #pragma once +#include #include class PlaylistModel : public QAbstractListModel @@ -28,7 +29,7 @@ class PlaylistModel : public QAbstractListModel QUrl urlByIndex(int index) const; QStringList autoLoadFilterSuffixes() const; - QModelIndex createIndex(int row) const; + QHash roleNames() const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; @@ -49,6 +50,8 @@ 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(); @@ -56,8 +59,8 @@ class PlaylistManager : public QObject PlaylistModel * model(); void setPlaylist(const QList & url); - QModelIndex loadPlaylist(const QList & urls); - QModelIndex loadPlaylist(const QUrl & url); + Q_INVOKABLE QModelIndex loadPlaylist(const QList & urls); + Q_INVOKABLE QModelIndex loadPlaylist(const QUrl & url); int totalCount() const; QModelIndex previousIndex() const; diff --git a/quick/main.cpp b/quick/main.cpp index 4d7f21f..cc4c4d8 100644 --- a/quick/main.cpp +++ b/quick/main.cpp @@ -1,4 +1,5 @@ #include "player.h" +#include "playlistmanager.h" #include "util.h" #include @@ -28,6 +29,8 @@ int main(int argc, char *argv[]) QStringList urlStrList = parser.positionalArguments(); QList urlsToLoad = Util::convertToUrlList(urlStrList); + qmlRegisterUncreatableType("Pineapple.TrackerPlayer", 1, 0, "PlaylistModel", "managed by PlaylistManager"); + qmlRegisterType("Pineapple.TrackerPlayer", 1, 0, "PlaylistManager"); qmlRegisterType("Pineapple.TrackerPlayer", 1, 0, "TrackerPlayer"); QQmlApplicationEngine engine; diff --git a/quick/main.qml b/quick/main.qml index 6fb27e0..237af8e 100644 --- a/quick/main.qml +++ b/quick/main.qml @@ -2,7 +2,6 @@ import QtQuick 2.4 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 import QtQuick.Dialogs -//import Qt.labs.platform 1 as Platform import Pineapple.TrackerPlayer 1 ApplicationWindow { @@ -44,6 +43,17 @@ ApplicationWindow { } } } + + Menu { + title: qsTr("&Help") + + Action { + text: qsTr("About") + onTriggered: () => { + aboutDialog.open() + } + } + } } DropArea { @@ -54,6 +64,7 @@ ApplicationWindow { } onDropped: (drop) => { if (drop.urls.length <= 0) return; + playlistManager.loadPlaylist(drop.urls) player.load(drop.urls[0]); player.play(); } @@ -117,6 +128,15 @@ ApplicationWindow { Item { Layout.fillWidth: true } + Label { + text: "Playlist" + MouseArea { + anchors.fill: parent + onClicked: { + stackLayout.currentIndex = 3 + } + } + } Label { text: "Message" MouseArea { @@ -174,6 +194,20 @@ ApplicationWindow { id: instrumentsContainer instruments: player.qml_instrumentNames } + ListView { + id: playlistView + model: playlistManager.model + clip: true + delegate: ItemDelegate { + width: parent.width + text: model.display + onClicked: function() { + playlistManager.currentIndex = index + player.load(model.url); + player.play(); + } + } + } } } } @@ -212,8 +246,14 @@ ApplicationWindow { } } + PlaylistManager { + id: playlistManager + autoLoadFilterSuffixes: ["*.xm", "*.it", "*.mod", "*.s3m", "*.mptm"] + } + Component.onCompleted: { if (fileList.length > 0) { + playlistManager.loadPlaylist(fileList) player.load(fileList[0]); player.play(); } @@ -226,6 +266,7 @@ ApplicationWindow { "Module Files (*.xm *.it *.mod *.s3m *.mptm)" ] onAccepted: { + playlistManager.loadPlaylist(fileDialog.currentFile) player.load(fileDialog.currentFile); player.play(); } @@ -236,4 +277,34 @@ ApplicationWindow { selectedFont.family: monoFontFamily options: FontDialog.MonospacedFonts } + + Dialog { + id: aboutDialog + title: qsTr("About") + anchors.centerIn: parent + ColumnLayout { + Label { + textFormat: Text.MarkdownText + text: `Pineapple Tracker Player + +Based on the following free software libraries: + +- [Qt](https://www.qt.io/) +- [PortAudio](https://www.portaudio.com/) +- [libopenmpt](https://lib.openmpt.org/libopenmpt/) + +[Source Code](https://github.com/BLumia/pineapple-tracker-player) + +Copyright © 2024 [BLumia](https://github.com/BLumia/) +` + onLinkActivated: function(link) { + Qt.openUrlExternally(link) + } + } + DialogButtonBox { + standardButtons: DialogButtonBox.Ok + onAccepted: aboutDialog.close() + } + } + } }