From 020cc303b46b4dc96c33d4e89bff1d6c2f125d87 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 24 May 2016 14:27:27 +0200 Subject: Polish the player example. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Port it to use URLs and mime types. - Introduce QCommandLineParser. - Resize according to screen size. - Add some bells and whistles, set window file paths, always display duration and file name, handle drop. Change-Id: I75aa101d32cfde0c0c75a0686a50c2d7d5dce827 Reviewed-by: Topi Reiniƶ Reviewed-by: Joerg Bornemann --- examples/winextras/musicplayer/main.cpp | 71 ++++++++++----- examples/winextras/musicplayer/musicplayer.cpp | 110 +++++++++++++++++------- examples/winextras/musicplayer/musicplayer.h | 40 +++++---- examples/winextras/musicplayer/volumebutton.cpp | 2 +- examples/winextras/musicplayer/volumebutton.h | 8 +- 5 files changed, 158 insertions(+), 73 deletions(-) (limited to 'examples') diff --git a/examples/winextras/musicplayer/main.cpp b/examples/winextras/musicplayer/main.cpp index 5cace0d..0502015 100644 --- a/examples/winextras/musicplayer/main.cpp +++ b/examples/winextras/musicplayer/main.cpp @@ -41,50 +41,79 @@ #include "musicplayer.h" #include +#include +#include +#include #include +#include #include #include #include +#include //! [0] -static void associateFileTypes(const QStringList &fileTypes) +static bool associateFileTypes() { QString displayName = QGuiApplication::applicationDisplayName(); QString filePath = QCoreApplication::applicationFilePath(); QString fileName = QFileInfo(filePath).fileName(); - QSettings settings("HKEY_CURRENT_USER\\Software\\Classes\\Applications\\" + fileName, QSettings::NativeFormat); - settings.setValue("FriendlyAppName", displayName); + const QString key = QStringLiteral("HKEY_CURRENT_USER\\Software\\Classes\\Applications\\") + fileName; + QSettings settings(key, QSettings::NativeFormat); + if (settings.status() != QSettings::NoError) { + qWarning() << "Cannot access registry key" << key; + return false; + } + settings.setValue(QStringLiteral("FriendlyAppName"), displayName); - settings.beginGroup("SupportedTypes"); - foreach (const QString& fileType, fileTypes) - settings.setValue(fileType, QString()); + settings.beginGroup(QStringLiteral("SupportedTypes")); + QMimeDatabase mimeDatabase; + foreach (const QString &fileType, MusicPlayer::supportedMimeTypes()) { + foreach (QString suffix, mimeDatabase.mimeTypeForName(fileType).suffixes()) { + suffix.prepend('.'); + settings.setValue(suffix, QString()); + } + } settings.endGroup(); - settings.beginGroup("shell"); - settings.beginGroup("open"); - settings.setValue("FriendlyAppName", displayName); - settings.beginGroup("Command"); - settings.setValue(".", QChar('"') + QDir::toNativeSeparators(filePath) + QString("\" \"%1\"")); + settings.beginGroup(QStringLiteral("shell")); + settings.beginGroup(QStringLiteral("open")); + settings.setValue(QStringLiteral("FriendlyAppName"), displayName); + settings.beginGroup(QStringLiteral("Command")); + settings.setValue(QStringLiteral("."), + QLatin1Char('"') + QDir::toNativeSeparators(filePath) + QStringLiteral("\" \"%1\"")); + + return true; } //! [0] int main(int argc, char *argv[]) { QApplication app(argc, argv); - app.setApplicationName("MusicPlayer"); - app.setOrganizationName("QtWinExtras"); - app.setOrganizationDomain("qt-project.org"); - app.setApplicationDisplayName("QtWinExtras Music Player"); - app.setWindowIcon(QIcon(":/logo.png")); + QCoreApplication::setApplicationName(QStringLiteral("MusicPlayer")); + QCoreApplication::setApplicationVersion( QLatin1String(QT_VERSION_STR)); + QCoreApplication::setOrganizationName(QStringLiteral("QtWinExtras")); + QCoreApplication::setOrganizationDomain("qt-project.org"); + QGuiApplication::setApplicationDisplayName(QStringLiteral("QtWinExtras Music Player")); + QApplication::setWindowIcon(QIcon(QStringLiteral(":/logo.png"))); + + if (!associateFileTypes()) + return -1; - associateFileTypes(QStringList(".mp3")); + QCommandLineParser parser; + parser.setApplicationDescription(QGuiApplication::applicationDisplayName()); + parser.addHelpOption(); + parser.addVersionOption(); + parser.addPositionalArgument(QStringLiteral("url"), MusicPlayer::tr("The URL to open.")); + parser.process(app); MusicPlayer player; - const QStringList arguments = QCoreApplication::arguments(); - if (arguments.size() > 1) - player.playFile(arguments.at(1)); - player.resize(300, 60); + + if (!parser.positionalArguments().isEmpty()) + player.playUrl(QUrl::fromUserInput(parser.positionalArguments().constFirst(), QDir::currentPath(), QUrl::AssumeLocalFile)); + + const QRect availableGeometry = QApplication::desktop()->availableGeometry(&player); + player.resize(availableGeometry.width() / 6, availableGeometry.height() / 17); player.show(); return app.exec(); diff --git a/examples/winextras/musicplayer/musicplayer.cpp b/examples/winextras/musicplayer/musicplayer.cpp index 26b6fa8..6093976 100644 --- a/examples/winextras/musicplayer/musicplayer.cpp +++ b/examples/winextras/musicplayer/musicplayer.cpp @@ -44,11 +44,7 @@ #include #include -MusicPlayer::MusicPlayer(QWidget *parent) : QWidget(parent), - taskbarButton(0), taskbarProgress(0), thumbnailToolBar(0), - playToolButton(0), forwardToolButton(0), backwardToolButton(0), - mediaPlayer(0), playButton(0), volumeButton(0), - positionSlider(0), positionLabel(0), infoLabel(0) +MusicPlayer::MusicPlayer(QWidget *parent) : QWidget(parent) { createWidgets(); createShortcuts(); @@ -67,25 +63,42 @@ MusicPlayer::MusicPlayer(QWidget *parent) : QWidget(parent), this, &MusicPlayer::updateState); stylize(); + setAcceptDrops(true); +} + +QStringList MusicPlayer::supportedMimeTypes() +{ + QStringList result = QMediaPlayer::supportedMimeTypes(); + if (result.isEmpty()) + result.append(QStringLiteral("audio/mpeg")); + return result; } void MusicPlayer::openFile() { - const QStringList musicPaths = QStandardPaths::standardLocations(QStandardPaths::MusicLocation); - const QString filePath = - QFileDialog::getOpenFileName(this, tr("Open File"), - musicPaths.isEmpty() ? QDir::homePath() : musicPaths.first(), - tr("MP3 files (*.mp3);;All files (*.*)")); - if (!filePath.isEmpty()) - playFile(filePath); + QFileDialog fileDialog(this); + fileDialog.setAcceptMode(QFileDialog::AcceptOpen); + fileDialog.setWindowTitle(tr("Open File")); + fileDialog.setMimeTypeFilters(MusicPlayer::supportedMimeTypes()); + fileDialog.setDirectory(QStandardPaths::standardLocations(QStandardPaths::MusicLocation).value(0, QDir::homePath())); + if (fileDialog.exec() == QDialog::Accepted) + playUrl(fileDialog.selectedUrls().constFirst()); } -void MusicPlayer::playFile(const QString &filePath) +void MusicPlayer::playUrl(const QUrl &url) { playButton->setEnabled(true); - infoLabel->setText(QFileInfo(filePath).fileName()); - - mediaPlayer.setMedia(QUrl::fromLocalFile(filePath)); + if (url.isLocalFile()) { + const QString filePath = url.toLocalFile(); + setWindowFilePath(filePath); + infoLabel->setText(QDir::toNativeSeparators(filePath)); + fileName = QFileInfo(filePath).fileName(); + } else { + setWindowFilePath(QString()); + infoLabel->setText(url.toString()); + fileName.clear(); + } + mediaPlayer.setMedia(url); mediaPlayer.play(); } @@ -118,6 +131,27 @@ bool MusicPlayer::event(QEvent *event) } //! [0] +static bool canHandleDrop(const QDropEvent *event) +{ + const QList urls = event->mimeData()->urls(); + if (urls.size() != 1) + return false; + QMimeDatabase mimeDatabase; + return MusicPlayer::supportedMimeTypes(). + contains(mimeDatabase.mimeTypeForUrl(urls.constFirst()).name()); +} + +void MusicPlayer::dragEnterEvent(QDragEnterEvent *event) +{ + event->setAccepted(canHandleDrop(event)); +} + +void MusicPlayer::dropEvent(QDropEvent *event) +{ + event->accept(); + playUrl(event->mimeData()->urls().constFirst()); +} + void MusicPlayer::mousePressEvent(QMouseEvent *event) { offset = event->globalPos() - pos(); @@ -143,11 +177,11 @@ void MusicPlayer::stylize() QtWin::extendFrameIntoClientArea(this, -1, -1, -1, -1); setAttribute(Qt::WA_TranslucentBackground, true); setAttribute(Qt::WA_NoSystemBackground, false); - setStyleSheet("MusicPlayer { background: transparent; }"); + setStyleSheet(QStringLiteral("MusicPlayer { background: transparent; }")); } else { QtWin::resetExtendedFrame(this); setAttribute(Qt::WA_TranslucentBackground, false); - setStyleSheet(QString("MusicPlayer { background: %1; }").arg(QtWin::realColorizationColor().name())); + setStyleSheet(QStringLiteral("MusicPlayer { background: %1; }").arg(QtWin::realColorizationColor().name())); } volumeButton->stylize(); } @@ -164,12 +198,20 @@ void MusicPlayer::updateState(QMediaPlayer::State state) } } +static QString formatTime(qint64 timeMilliSeconds) +{ + qint64 seconds = timeMilliSeconds / 1000; + const qint64 minutes = seconds / 60; + seconds -= minutes * 60; + return QStringLiteral("%1:%2") + .arg(minutes, 2, 10, QLatin1Char('0')) + .arg(seconds, 2, 10, QLatin1Char('0')); +} + void MusicPlayer::updatePosition(qint64 position) { positionSlider->setValue(position); - - QTime duration(0, position / 60000, qRound((position % 60000) / 1000.0)); - positionLabel->setText(duration.toString(tr("mm:ss"))); + positionLabel->setText(formatTime(position)); } void MusicPlayer::updateDuration(qint64 duration) @@ -177,6 +219,7 @@ void MusicPlayer::updateDuration(qint64 duration) positionSlider->setRange(0, duration); positionSlider->setEnabled(duration > 0); positionSlider->setPageStep(duration / 10); + updateInfo(); } void MusicPlayer::setPosition(int position) @@ -189,20 +232,27 @@ void MusicPlayer::setPosition(int position) void MusicPlayer::updateInfo() { QStringList info; - QString author = mediaPlayer.metaData("Author").toString(); - if (!author.isEmpty()) - info += author; - QString title = mediaPlayer.metaData("Title").toString(); - if (!title.isEmpty()) - info += title; - if (!info.isEmpty()) - infoLabel->setText(info.join(tr(" - "))); + if (!fileName.isEmpty()) + info.append(fileName); + if (mediaPlayer.isMetaDataAvailable()) { + QString author = mediaPlayer.metaData(QStringLiteral("Author")).toString(); + if (!author.isEmpty()) + info.append(author); + QString title = mediaPlayer.metaData(QStringLiteral("Title")).toString(); + if (!title.isEmpty()) + info.append(title); + } + info.append(formatTime(mediaPlayer.duration())); + infoLabel->setText(info.join(tr(" - "))); } void MusicPlayer::handleError() { playButton->setEnabled(false); - infoLabel->setText(tr("Error: %1").arg(mediaPlayer.errorString())); + const QString errorString = mediaPlayer.errorString(); + infoLabel->setText(errorString.isEmpty() + ? tr("Unknown error #%1").arg(int(mediaPlayer.error())) + : tr("Error: %1").arg(errorString)); } //! [2] diff --git a/examples/winextras/musicplayer/musicplayer.h b/examples/winextras/musicplayer/musicplayer.h index b848840..567aeb7 100644 --- a/examples/winextras/musicplayer/musicplayer.h +++ b/examples/winextras/musicplayer/musicplayer.h @@ -58,20 +58,25 @@ class MusicPlayer : public QWidget { Q_OBJECT public: - MusicPlayer(QWidget *parent = 0); + explicit MusicPlayer(QWidget *parent = nullptr); + + static QStringList supportedMimeTypes(); + static QStringList supportedSuffixes(); public slots: void openFile(); - void playFile(const QString& filePath); + void playUrl(const QUrl& url); void togglePlayback(); void seekForward(); void seekBackward(); protected: - bool event(QEvent *event); - void mousePressEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); + bool event(QEvent *event) override; + void dragEnterEvent(QDragEnterEvent *event) override; + void dropEvent(QDropEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; private slots: void stylize(); @@ -92,20 +97,21 @@ private: void createTaskbar(); void createThumbnailToolBar(); - QWinTaskbarButton* taskbarButton; - QWinTaskbarProgress* taskbarProgress; - QWinThumbnailToolBar* thumbnailToolBar; - QWinThumbnailToolButton *playToolButton; - QWinThumbnailToolButton *forwardToolButton; - QWinThumbnailToolButton *backwardToolButton; + QWinTaskbarButton *taskbarButton = nullptr; + QWinTaskbarProgress *taskbarProgress = nullptr; + QWinThumbnailToolBar *thumbnailToolBar = nullptr; + QWinThumbnailToolButton *playToolButton = nullptr; + QWinThumbnailToolButton *forwardToolButton = nullptr; + QWinThumbnailToolButton *backwardToolButton = nullptr; QMediaPlayer mediaPlayer; - QAbstractButton *playButton; - VolumeButton *volumeButton; - QSlider *positionSlider; - QLabel *positionLabel; - QLabel *infoLabel; + QAbstractButton *playButton = nullptr; + VolumeButton *volumeButton = nullptr; + QSlider *positionSlider = nullptr; + QLabel *positionLabel = nullptr; + QLabel *infoLabel = nullptr; QPoint offset; + QString fileName; }; #endif // MUSICPLAYER_H diff --git a/examples/winextras/musicplayer/volumebutton.cpp b/examples/winextras/musicplayer/volumebutton.cpp index 37eb0c1..44be5cf 100644 --- a/examples/winextras/musicplayer/volumebutton.cpp +++ b/examples/winextras/musicplayer/volumebutton.cpp @@ -44,7 +44,7 @@ #include VolumeButton::VolumeButton(QWidget *parent) : - QToolButton(parent), menu(0), label(0), slider(0) + QToolButton(parent) { setIcon(style()->standardIcon(QStyle::SP_MediaVolume)); setPopupMode(QToolButton::InstantPopup); diff --git a/examples/winextras/musicplayer/volumebutton.h b/examples/winextras/musicplayer/volumebutton.h index 99d6da9..3fc3c87 100644 --- a/examples/winextras/musicplayer/volumebutton.h +++ b/examples/winextras/musicplayer/volumebutton.h @@ -53,7 +53,7 @@ class VolumeButton : public QToolButton Q_PROPERTY(int volume READ volume WRITE setVolume NOTIFY volumeChanged) public: - VolumeButton(QWidget *parent = 0); + explicit VolumeButton(QWidget *parent = nullptr); int volume() const; @@ -67,9 +67,9 @@ signals: void volumeChanged(int volume); private: - QMenu *menu; - QLabel *label; - QSlider *slider; + QMenu *menu = nullptr; + QLabel *label = nullptr; + QSlider *slider = nullptr; }; #endif // VOLUMEBUTTON_H -- cgit v1.2.3