Includes, comments and bugfixes
- Fix includes - Use common regex (Song::kCoverRemoveDisc) for removing Disc/CD from album - Remove Disc/CD from album when creating hash - Make imobiledevice support compile - Fix setting device on windows
This commit is contained in:
@@ -20,11 +20,16 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "appearance.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
#include <QPalette>
|
||||
#include <QColor>
|
||||
#include <QSettings>
|
||||
|
||||
#include "appearance.h"
|
||||
#include "settings/appearancesettingspage.h"
|
||||
|
||||
const char *Appearance::kUseCustomColorSet = "use-custom-set";
|
||||
|
||||
@@ -29,17 +29,17 @@
|
||||
|
||||
class Appearance : public QObject {
|
||||
public:
|
||||
explicit Appearance(QObject* parent = nullptr);
|
||||
explicit Appearance(QObject *parent = nullptr);
|
||||
// Load the user preferred theme, which could the default system theme or a custom set of colors that user has chosen
|
||||
void LoadUserTheme();
|
||||
void ResetToSystemDefaultTheme();
|
||||
void ChangeForegroundColor(const QColor& color);
|
||||
void ChangeBackgroundColor(const QColor& color);
|
||||
void ChangeForegroundColor(const QColor &color);
|
||||
void ChangeBackgroundColor(const QColor &color);
|
||||
|
||||
static const char* kSettingsGroup;
|
||||
static const char* kUseCustomColorSet;
|
||||
static const char* kForegroundColor;
|
||||
static const char* kBackgroundColor;
|
||||
static const char *kSettingsGroup;
|
||||
static const char *kUseCustomColorSet;
|
||||
static const char *kForegroundColor;
|
||||
static const char *kBackgroundColor;
|
||||
static const QPalette kDefaultPalette;
|
||||
|
||||
private:
|
||||
|
||||
@@ -18,20 +18,27 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "application.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "core/appearance.h"
|
||||
#include "core/database.h"
|
||||
#include "application.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include <QString>
|
||||
|
||||
#include "core/closure.h"
|
||||
#include "core/lazy.h"
|
||||
#include "core/player.h"
|
||||
#include "core/tagreaderclient.h"
|
||||
#include "core/taskmanager.h"
|
||||
#include "engine/enginetype.h"
|
||||
|
||||
#include "database.h"
|
||||
#include "taskmanager.h"
|
||||
#include "player.h"
|
||||
#include "appearance.h"
|
||||
|
||||
#include "engine/enginedevice.h"
|
||||
#include "device/devicemanager.h"
|
||||
#include "collection/collectionbackend.h"
|
||||
#include "collection/collection.h"
|
||||
#include "playlist/playlistbackend.h"
|
||||
#include "playlist/playlistmanager.h"
|
||||
@@ -40,7 +47,7 @@
|
||||
#include "covermanager/currentartloader.h"
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
#include "covermanager/lastfmcoverprovider.h"
|
||||
#endif // HAVE_LIBLASTFM
|
||||
#endif
|
||||
#include "covermanager/amazoncoverprovider.h"
|
||||
#include "covermanager/discogscoverprovider.h"
|
||||
#include "covermanager/musicbrainzcoverprovider.h"
|
||||
@@ -77,9 +84,9 @@ class ApplicationImpl {
|
||||
cover_providers_([=]() {
|
||||
CoverProviders *cover_providers = new CoverProviders(app);
|
||||
// Initialize the repository of cover providers.
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
cover_providers->AddProvider(new LastFmCoverProvider(app));
|
||||
#endif
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
cover_providers->AddProvider(new LastFmCoverProvider(app));
|
||||
#endif
|
||||
cover_providers->AddProvider(new AmazonCoverProvider(app));
|
||||
cover_providers->AddProvider(new DiscogsCoverProvider(app));
|
||||
cover_providers->AddProvider(new MusicbrainzCoverProvider(app));
|
||||
@@ -121,8 +128,7 @@ Application::Application(QObject *parent)
|
||||
Application::~Application() {
|
||||
|
||||
// It's important that the device manager is deleted before the database.
|
||||
// Deleting the database deletes all objects that have been created in its
|
||||
// thread, including some device collection backends.
|
||||
// Deleting the database deletes all objects that have been created in its thread, including some device collection backends.
|
||||
p_->device_manager_.reset();
|
||||
|
||||
for (QThread *thread : threads_) {
|
||||
@@ -151,14 +157,6 @@ void Application::MoveToThread(QObject *object, QThread *thread) {
|
||||
|
||||
void Application::AddError(const QString& message) { emit ErrorAdded(message); }
|
||||
|
||||
QString Application::language_without_region() const {
|
||||
const int underscore = language_name_.indexOf('_');
|
||||
if (underscore != -1) {
|
||||
return language_name_.left(underscore);
|
||||
}
|
||||
return language_name_;
|
||||
}
|
||||
|
||||
void Application::ReloadSettings() { emit SettingsChanged(); }
|
||||
|
||||
void Application::OpenSettingsDialogAtPage(SettingsDialog::Page page) {
|
||||
|
||||
@@ -24,29 +24,31 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <memory>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QThread>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
#include "settings/settingsdialog.h"
|
||||
|
||||
class TaskManager;
|
||||
class ApplicationImpl;
|
||||
class TagReaderClient;
|
||||
class Database;
|
||||
class Appearance;
|
||||
class TaskManager;
|
||||
class EngineDevice;
|
||||
class Player;
|
||||
class DeviceManager;
|
||||
class Appearance;
|
||||
class Collection;
|
||||
class PlaylistBackend;
|
||||
class PlaylistManager;
|
||||
class AlbumCoverLoader;
|
||||
class CoverProviders;
|
||||
class CurrentArtLoader;
|
||||
class CollectionBackend;
|
||||
class CollectionModel;
|
||||
class EngineDevice;
|
||||
class PlaylistBackend;
|
||||
class PlaylistManager;
|
||||
class DeviceManager;
|
||||
class CoverProviders;
|
||||
class AlbumCoverLoader;
|
||||
class CurrentArtLoader;
|
||||
|
||||
class Application : public QObject {
|
||||
Q_OBJECT
|
||||
@@ -57,11 +59,6 @@ class Application : public QObject {
|
||||
explicit Application(QObject *parent = nullptr);
|
||||
~Application();
|
||||
|
||||
const QString &language_name() const { return language_name_; }
|
||||
// Same as language_name, but remove the region code at the end if there is one
|
||||
QString language_without_region() const;
|
||||
void set_language_name(const QString &name) { language_name_ = name; }
|
||||
|
||||
TagReaderClient *tag_reader_client() const;
|
||||
Database *database() const;
|
||||
Appearance *appearance() const;
|
||||
@@ -96,7 +93,6 @@ signals:
|
||||
void SettingsDialogRequested(SettingsDialog::Page page);
|
||||
|
||||
private:
|
||||
QString language_name_;
|
||||
std::unique_ptr<ApplicationImpl> p_;
|
||||
QList<QThread*> threads_;
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QDateTime>
|
||||
#include <QSettings>
|
||||
|
||||
|
||||
@@ -19,19 +19,25 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "commandlineoptions.h"
|
||||
#include "version.h"
|
||||
#include "core/logging.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <getopt.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QIODevice>
|
||||
#include <QDataStream>
|
||||
#include <QBuffer>
|
||||
#include <QCoreApplication>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
#include "commandlineoptions.h"
|
||||
#include "core/logging.h"
|
||||
|
||||
const char *CommandlineOptions::kHelpText =
|
||||
"%1: strawberry [%2] [%3]\n"
|
||||
@@ -93,7 +99,7 @@ CommandlineOptions::CommandlineOptions(int argc, char* *argv)
|
||||
RemoveArg("-session", 2);
|
||||
}
|
||||
|
||||
void CommandlineOptions::RemoveArg(const QString& starts_with, int count) {
|
||||
void CommandlineOptions::RemoveArg(const QString &starts_with, int count) {
|
||||
|
||||
for (int i = 0; i < argc_; ++i) {
|
||||
QString opt(argv_[i]);
|
||||
|
||||
@@ -23,9 +23,13 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QUrl>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
class CommandlineOptions {
|
||||
friend QDataStream &operator<<(QDataStream &s, const CommandlineOptions &a);
|
||||
|
||||
@@ -20,27 +20,36 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "database.h"
|
||||
#include "scopedtransaction.h"
|
||||
#include "core/application.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/taskmanager.h"
|
||||
|
||||
#include <sqlite3.h>
|
||||
#include <boost/scope_exit.hpp>
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QStandardPaths>
|
||||
#include <QDir>
|
||||
#include <QLibrary>
|
||||
#include <QLibraryInfo>
|
||||
#include <QSqlDriver>
|
||||
#include <QSqlQuery>
|
||||
#include <QtDebug>
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include <QUrl>
|
||||
#include <QMutex>
|
||||
#include <QIODevice>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QChar>
|
||||
#include <QList>
|
||||
#include <QByteArray>
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
#include <QStringBuilder>
|
||||
#include <QStringList>
|
||||
#include <QRegExp>
|
||||
#include <QUrl>
|
||||
#include <QSqlDriver>
|
||||
#include <QSqlDatabase>
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlError>
|
||||
#include <QStandardPaths>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "taskmanager.h"
|
||||
#include "database.h"
|
||||
#include "application.h"
|
||||
#include "scopedtransaction.h"
|
||||
|
||||
const char *Database::kDatabaseFilename = "strawberry.db";
|
||||
const int Database::kSchemaVersion = 0;
|
||||
@@ -269,7 +278,8 @@ QSqlDatabase Database::Connect() {
|
||||
{
|
||||
|
||||
#ifdef SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER
|
||||
// In case sqlite>=3.12 is compiled without -DSQLITE_ENABLE_FTS3_TOKENIZER (generally a good idea due to security reasons) the fts3 support should be enabled explicitly.
|
||||
// In case sqlite>=3.12 is compiled without -DSQLITE_ENABLE_FTS3_TOKENIZER
|
||||
// (generally a good idea due to security reasons) the fts3 support should be enabled explicitly.
|
||||
QVariant v = db.driver()->handle();
|
||||
if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*") == 0) {
|
||||
sqlite3 *handle = *static_cast<sqlite3**>(v.data());
|
||||
@@ -283,8 +293,7 @@ QSqlDatabase Database::Connect() {
|
||||
if (!set_fts_tokenizer.exec()) {
|
||||
qLog(Warning) << "Couldn't register FTS3 tokenizer : " << set_fts_tokenizer.lastError();
|
||||
}
|
||||
// Implicit invocation of ~QSqlQuery() when leaving the scope
|
||||
// to release any remaining database locks!
|
||||
// Implicit invocation of ~QSqlQuery() when leaving the scope to release any remaining database locks!
|
||||
}
|
||||
|
||||
if (db.tables().count() == 0) {
|
||||
@@ -313,8 +322,7 @@ QSqlDatabase Database::Connect() {
|
||||
UpdateMainSchema(&db);
|
||||
}
|
||||
|
||||
// We might have to initialise the schema in some attached databases now, if
|
||||
// they were deleted and don't match up with the main schema version.
|
||||
// We might have to initialise the schema in some attached databases now, if they were deleted and don't match up with the main schema version.
|
||||
for (const QString &key : attached_databases_.keys()) {
|
||||
if (attached_databases_[key].is_temporary_ && attached_databases_[key].schema_.isEmpty())
|
||||
continue;
|
||||
@@ -338,8 +346,7 @@ void Database::UpdateMainSchema(QSqlDatabase *db) {
|
||||
{
|
||||
QSqlQuery q("SELECT version FROM schema_version", *db);
|
||||
if (q.next()) schema_version = q.value(0).toInt();
|
||||
// Implicit invocation of ~QSqlQuery() when leaving the scope
|
||||
// to release any remaining database locks!
|
||||
// Implicit invocation of ~QSqlQuery() when leaving the scope to release any remaining database locks!
|
||||
}
|
||||
|
||||
startup_schema_version_ = schema_version;
|
||||
@@ -382,9 +389,8 @@ void Database::RecreateAttachedDb(const QString &database_name) {
|
||||
}
|
||||
}
|
||||
|
||||
// We can't just re-attach the database now because it needs to be done for
|
||||
// each thread. Close all the database connections, so each thread will
|
||||
// re-attach it when they next connect.
|
||||
// We can't just re-attach the database now because it needs to be done for each thread.
|
||||
// Close all the database connections, so each thread will re-attach it when they next connect.
|
||||
for (const QString &name : QSqlDatabase::connectionNames()) {
|
||||
QSqlDatabase::removeDatabase(name);
|
||||
}
|
||||
@@ -482,12 +488,9 @@ void Database::ExecSchemaCommands(QSqlDatabase &db, const QString &schema, int s
|
||||
// Run each command
|
||||
const QStringList commands(schema.split(QRegExp("; *\n\n")));
|
||||
|
||||
// We don't want this list to reflect possible DB schema changes
|
||||
// so we initialize it before executing any statements.
|
||||
// If no outer transaction is provided the song tables need to
|
||||
// be queried before beginning an inner transaction! Otherwise
|
||||
// DROP TABLE commands on song tables may fail due to database
|
||||
// locks.
|
||||
// We don't want this list to reflect possible DB schema changes so we initialize it before executing any statements.
|
||||
// If no outer transaction is provided the song tables need to be queried before beginning an inner transaction! Otherwise
|
||||
// DROP TABLE commands on song tables may fail due to database locks.
|
||||
const QStringList song_tables(SongsTables(db, schema_version));
|
||||
|
||||
if (!in_transaction) {
|
||||
@@ -505,12 +508,10 @@ void Database::ExecSongTablesCommands(QSqlDatabase &db, const QStringList &song_
|
||||
|
||||
for (const QString &command : commands) {
|
||||
// There are now lots of "songs" tables that need to have the same schema:
|
||||
// songs, magnatune_songs, and device_*_songs. We allow a magic value
|
||||
// in the schema files to update all songs tables at once.
|
||||
// songs, magnatune_songs, and device_*_songs. We allow a magic value in the schema files to update all songs tables at once.
|
||||
if (command.contains(kMagicAllSongsTables)) {
|
||||
for (const QString &table : song_tables) {
|
||||
// Another horrible hack: device songs tables don't have matching _fts
|
||||
// tables, so if this command tries to touch one, ignore it.
|
||||
// Another horrible hack: device songs tables don't have matching _fts tables, so if this command tries to touch one, ignore it.
|
||||
if (table.startsWith("device_") &&
|
||||
command.contains(QString(kMagicAllSongsTables) + "_fts")) {
|
||||
continue;
|
||||
|
||||
@@ -23,15 +23,20 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QMutex>
|
||||
#include <QObject>
|
||||
#include <QSqlDatabase>
|
||||
#include <QSqlError>
|
||||
#include <QStringList>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QSqlDatabase>
|
||||
#include <QSqlQuery>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
extern "C" {
|
||||
|
||||
struct sqlite3_tokenizer;
|
||||
|
||||
@@ -20,11 +20,13 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "dbusscreensaver.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QObject>
|
||||
#include <QDBusInterface>
|
||||
#include <QDBusReply>
|
||||
#include <QString>
|
||||
|
||||
#include "dbusscreensaver.h"
|
||||
|
||||
DBusScreensaver::DBusScreensaver(const QString &service, const QString &path, const QString &interface)
|
||||
: service_(service), path_(path), interface_(interface) {}
|
||||
|
||||
@@ -23,8 +23,10 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QString>
|
||||
|
||||
#include "config.h"
|
||||
#include "screensaver.h"
|
||||
|
||||
class DBusScreensaver : public Screensaver {
|
||||
|
||||
@@ -20,19 +20,21 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "deletefiles.h"
|
||||
|
||||
#include <QStringList>
|
||||
#include <QTimer>
|
||||
#include <QtGlobal>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QUrl>
|
||||
|
||||
#include "musicstorage.h"
|
||||
#include "taskmanager.h"
|
||||
#include "song.h"
|
||||
#include "deletefiles.h"
|
||||
#include "musicstorage.h"
|
||||
|
||||
const int DeleteFiles::kBatchSize = 50;
|
||||
|
||||
DeleteFiles::DeleteFiles(TaskManager* task_manager, std::shared_ptr<MusicStorage> storage)
|
||||
DeleteFiles::DeleteFiles(TaskManager *task_manager, std::shared_ptr<MusicStorage> storage)
|
||||
: thread_(nullptr),
|
||||
task_manager_(task_manager),
|
||||
storage_(storage),
|
||||
@@ -91,8 +93,7 @@ void DeleteFiles::ProcessSomeFiles() {
|
||||
|
||||
emit Finished(songs_with_errors_);
|
||||
|
||||
// Move back to the original thread so deleteLater() can get called in
|
||||
// the main thread's event loop
|
||||
// Move back to the original thread so deleteLater() can get called in the main thread's event loop
|
||||
moveToThread(original_thread_);
|
||||
deleteLater();
|
||||
|
||||
|
||||
@@ -24,13 +24,17 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <memory>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
#include "song.h"
|
||||
|
||||
class MusicStorage;
|
||||
class TaskManager;
|
||||
class MusicStorage;
|
||||
|
||||
class DeleteFiles : public QObject {
|
||||
Q_OBJECT
|
||||
@@ -41,11 +45,11 @@ class DeleteFiles : public QObject {
|
||||
|
||||
static const int kBatchSize;
|
||||
|
||||
void Start(const SongList& songs);
|
||||
void Start(const QStringList& filenames);
|
||||
void Start(const SongList &songs);
|
||||
void Start(const QStringList &filenames);
|
||||
|
||||
signals:
|
||||
void Finished(const SongList& songs_with_errors);
|
||||
void Finished(const SongList &songs_with_errors);
|
||||
|
||||
private slots:
|
||||
void ProcessSomeFiles();
|
||||
@@ -67,4 +71,3 @@ signals:
|
||||
};
|
||||
|
||||
#endif // DELETEFILES_H
|
||||
|
||||
|
||||
@@ -20,13 +20,21 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "filesystemmusicstorage.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/utilities.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "utilities.h"
|
||||
#include "song.h"
|
||||
#include "musicstorage.h"
|
||||
|
||||
#include "filesystemmusicstorage.h"
|
||||
|
||||
FilesystemMusicStorage::FilesystemMusicStorage(const QString &root)
|
||||
: root_(root) {}
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <QString>
|
||||
|
||||
#include "musicstorage.h"
|
||||
|
||||
class FilesystemMusicStorage : public virtual MusicStorage {
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "filesystemwatcherinterface.h"
|
||||
#include <QObject>
|
||||
|
||||
#include "filesystemwatcherinterface.h"
|
||||
#include "qtfslistener.h"
|
||||
|
||||
#ifdef Q_OS_DARWIN
|
||||
@@ -43,4 +44,3 @@ FileSystemWatcherInterface *FileSystemWatcherInterface::Create(QObject *parent)
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -24,17 +24,18 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
class FileSystemWatcherInterface : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FileSystemWatcherInterface(QObject *parent = nullptr);
|
||||
virtual void Init() {}
|
||||
virtual void AddPath(const QString& path) = 0;
|
||||
virtual void RemovePath(const QString& path) = 0;
|
||||
virtual void AddPath(const QString &path) = 0;
|
||||
virtual void RemovePath(const QString &path) = 0;
|
||||
virtual void Clear() = 0;
|
||||
|
||||
static FileSystemWatcherInterface* Create(QObject *parent = nullptr);
|
||||
static FileSystemWatcherInterface *Create(QObject *parent = nullptr);
|
||||
|
||||
signals:
|
||||
void PathChanged(const QString &path);
|
||||
|
||||
@@ -38,9 +38,19 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QWidget>
|
||||
#include <QObject>
|
||||
#include <QLayout>
|
||||
#include <QLayoutItem>
|
||||
#include <QStyle>
|
||||
#include <QSize>
|
||||
#include <QPoint>
|
||||
#include <QRect>
|
||||
#include <QSizePolicy>
|
||||
|
||||
#include "flowlayout.h"
|
||||
|
||||
//! [1]
|
||||
FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing)
|
||||
: QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
|
||||
@@ -144,12 +154,10 @@ int FlowLayout::doLayout(const QRect& rect, bool testOnly) const {
|
||||
QWidget* wid = item->widget();
|
||||
int spaceX = horizontalSpacing();
|
||||
if (spaceX == -1)
|
||||
spaceX = wid->style()->layoutSpacing(
|
||||
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
|
||||
spaceX = wid->style()->layoutSpacing(QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
|
||||
int spaceY = verticalSpacing();
|
||||
if (spaceY == -1)
|
||||
spaceY = wid->style()->layoutSpacing(
|
||||
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
|
||||
spaceY = wid->style()->layoutSpacing(QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
|
||||
//! [10]
|
||||
//! [11]
|
||||
int nextX = x + item->sizeHint().width() + spaceX;
|
||||
@@ -173,10 +181,12 @@ int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const {
|
||||
QObject* parent = this->parent();
|
||||
if (!parent) {
|
||||
return -1;
|
||||
} else if (parent->isWidgetType()) {
|
||||
}
|
||||
else if (parent->isWidgetType()) {
|
||||
QWidget *pw = static_cast<QWidget *>(parent);
|
||||
return pw->style()->pixelMetric(pm, 0, pw);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return static_cast<QLayout *>(parent)->spacing();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,15 +41,20 @@
|
||||
#ifndef FLOWLAYOUT_H
|
||||
#define FLOWLAYOUT_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QLayout>
|
||||
#include <QRect>
|
||||
#include <QWidget>
|
||||
#include <QStyle>
|
||||
#include <QWidgetItem>
|
||||
#include <QList>
|
||||
#include <QSize>
|
||||
#include <QLayoutItem>
|
||||
#include <QRect>
|
||||
|
||||
//! [0]
|
||||
class FlowLayout : public QLayout {
|
||||
public:
|
||||
FlowLayout(QWidget* parent, int margin = -1, int hSpacing = -1,
|
||||
int vSpacing = -1);
|
||||
FlowLayout(QWidget* parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
|
||||
FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
|
||||
~FlowLayout();
|
||||
|
||||
|
||||
@@ -22,20 +22,19 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QIcon>
|
||||
#include <QSize>
|
||||
#include <QtDebug>
|
||||
#include <QSettings>
|
||||
|
||||
#include "iconloader.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/appearance.h"
|
||||
#include "iconloader.h"
|
||||
|
||||
QList<int> IconLoader::sizes_;
|
||||
QString IconDefault(":/icons/64x64/strawberry.png");
|
||||
|
||||
void IconLoader::Init() {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
sizes_.clear();
|
||||
sizes_ << 22 << 32 << 48 << 64;
|
||||
@@ -50,8 +49,6 @@ QIcon IconLoader::Load(const QString &name) {
|
||||
|
||||
QIcon ret;
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__ << name;
|
||||
|
||||
if (name.isEmpty()) {
|
||||
qLog(Warning) << "Icon name is empty!";
|
||||
ret.addFile(IconDefault, QSize(64, 64));
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#ifndef ICONLOADER_H
|
||||
#define ICONLOADER_H
|
||||
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QIcon>
|
||||
|
||||
class IconLoader {
|
||||
|
||||
@@ -3,17 +3,19 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QKeySequence>
|
||||
|
||||
class MacGlobalShortcutBackend;
|
||||
class QObject;
|
||||
class QWidget;
|
||||
|
||||
class MacGlobalShortcutBackend;
|
||||
|
||||
class PlatformInterface {
|
||||
public:
|
||||
// Called when the application should show itself.
|
||||
virtual void Activate() = 0;
|
||||
virtual bool LoadUrl(const QString& url) = 0;
|
||||
virtual bool LoadUrl(const QString &url) = 0;
|
||||
|
||||
virtual ~PlatformInterface() {}
|
||||
};
|
||||
@@ -21,8 +23,8 @@ class PlatformInterface {
|
||||
namespace mac {
|
||||
|
||||
void MacMain();
|
||||
void SetShortcutHandler(MacGlobalShortcutBackend* handler);
|
||||
void SetApplicationHandler(PlatformInterface* handler);
|
||||
void SetShortcutHandler(MacGlobalShortcutBackend *handler);
|
||||
void SetApplicationHandler(PlatformInterface *handler);
|
||||
void CheckForUpdates();
|
||||
|
||||
QString GetBundlePath();
|
||||
@@ -30,7 +32,7 @@ QString GetResourcesPath();
|
||||
QString GetApplicationSupportPath();
|
||||
QString GetMusicDirectory();
|
||||
|
||||
void EnableFullScreen(const QWidget& main_window);
|
||||
void EnableFullScreen(const QWidget &main_window);
|
||||
|
||||
} // namespace mac
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#import "3rdparty/SPMediaKeyTap/SPMediaKeyTap.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "globalshortcuts.h"
|
||||
#include "mac_delegate.h"
|
||||
#include "mac_startup.h"
|
||||
@@ -49,8 +50,8 @@
|
||||
#include "macglobalshortcutbackend.h"
|
||||
#include "utilities.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/scoped_cftyperef.h"
|
||||
#include "core/scoped_nsautorelease_pool.h"
|
||||
#include "scoped_cftyperef.h"
|
||||
#include "scoped_nsautorelease_pool.h"
|
||||
|
||||
#ifdef HAVE_SPARKLE
|
||||
#import <Sparkle/SUUpdater.h>
|
||||
@@ -58,11 +59,11 @@
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCoreApplication>
|
||||
#include <QWidget>
|
||||
#include <QDir>
|
||||
#include <QEvent>
|
||||
#include <QFile>
|
||||
#include <QSettings>
|
||||
#include <QWidget>
|
||||
|
||||
#include <QtDebug>
|
||||
|
||||
@@ -78,8 +79,7 @@ QDebug operator<<(QDebug dbg, NSObject* object) {
|
||||
@interface MacApplication : NSApplication {
|
||||
PlatformInterface* application_handler_;
|
||||
AppDelegate* delegate_;
|
||||
// shortcut_handler_ only used to temporarily save it
|
||||
// AppDelegate does all the heavy-shortcut-lifting
|
||||
// shortcut_handler_ only used to temporarily save it AppDelegate does all the heavy-shortcut-lifting
|
||||
MacGlobalShortcutBackend* shortcut_handler_;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QKeySequence>
|
||||
|
||||
#include <CoreFoundation/CFDictionary.h>
|
||||
@@ -34,5 +35,5 @@ namespace mac {
|
||||
|
||||
QKeySequence KeySequenceFromNSEvent(NSEvent* event);
|
||||
void DumpDictionary(CFDictionaryRef dict);
|
||||
float GetDevicePixelRatio(QWidget* widget);
|
||||
float GetDevicePixelRatio(QWidget *widget);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <CoreServices/CoreServices.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QSet>
|
||||
#include <QTimer>
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include <Foundation/NSString.h>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "core/scoped_nsobject.h"
|
||||
#include "scoped_nsobject.h"
|
||||
|
||||
MacFSListener::MacFSListener(QObject* parent)
|
||||
: FileSystemWatcherInterface(parent), run_loop_(nullptr), stream_(nullptr) {
|
||||
|
||||
@@ -25,6 +25,10 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QObject>
|
||||
#include <QAction>
|
||||
#include <QPixmap>
|
||||
|
||||
#include "systemtrayicon.h"
|
||||
|
||||
class MacSystemTrayIconPrivate;
|
||||
|
||||
@@ -22,13 +22,12 @@
|
||||
|
||||
#include "macsystemtrayicon.h"
|
||||
|
||||
#include "core/mac_delegate.h"
|
||||
#include "core/song.h"
|
||||
#include "mac_delegate.h"
|
||||
#include "song.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QApplication>
|
||||
#include <QAction>
|
||||
#include <QIcon>
|
||||
|
||||
#include <QtDebug>
|
||||
|
||||
#include <AppKit/NSMenu.h>
|
||||
|
||||
@@ -21,16 +21,27 @@
|
||||
#include "config.h"
|
||||
#include "version.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <memory>
|
||||
#include <time.h>
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <glib.h>
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
#include <unistd.h>
|
||||
#endif // Q_OS_UNIX
|
||||
#include <QObject>
|
||||
#include <QCoreApplication>
|
||||
#include <QFileDevice>
|
||||
#include <QIODevice>
|
||||
#include <QByteArray>
|
||||
#include <QNetworkProxy>
|
||||
#include <QFile>
|
||||
#include <QString>
|
||||
#include <QImage>
|
||||
#include <QSettings>
|
||||
#include <QtDebug>
|
||||
#ifdef HAVE_DBUS
|
||||
# include <QDBusArgument>
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_DARWIN
|
||||
#include <sys/resource.h>
|
||||
@@ -45,53 +56,26 @@
|
||||
#include <iostream>
|
||||
#endif // Q_OS_WIN32
|
||||
|
||||
#include <QObject>
|
||||
#include <QFile>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QDir>
|
||||
#include <QFont>
|
||||
#include <QLibraryInfo>
|
||||
#include <QNetworkProxyFactory>
|
||||
#include <QSslSocket>
|
||||
#include <QSqlDatabase>
|
||||
#include <QSqlQuery>
|
||||
#include <QSysInfo>
|
||||
#include <QTextCodec>
|
||||
#include <QtConcurrentRun>
|
||||
#include <QtDebug>
|
||||
#include <QSettings>
|
||||
#ifdef HAVE_DBUS
|
||||
#include <QDBusArgument>
|
||||
#include <QImage>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
#include "core/mpris.h"
|
||||
#include "core/mpris2.h"
|
||||
#endif
|
||||
#include "core/application.h"
|
||||
#include "core/mainwindow.h"
|
||||
#include "core/commandlineoptions.h"
|
||||
#include "core/database.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/mac_startup.h"
|
||||
#include "core/metatypes.h"
|
||||
#include "core/network.h"
|
||||
#include "core/networkproxyfactory.h"
|
||||
#include "core/song.h"
|
||||
#include "core/utilities.h"
|
||||
#include "core/iconloader.h"
|
||||
#include "core/systemtrayicon.h"
|
||||
#include "core/scangiomodulepath.h"
|
||||
|
||||
#include "widgets/osd.h"
|
||||
|
||||
#include "tagreadermessages.pb.h"
|
||||
|
||||
#include "qtsingleapplication.h"
|
||||
#include "qtsinglecoreapplication.h"
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
#include "mpris.h"
|
||||
#endif
|
||||
#include "utilities.h"
|
||||
#include "metatypes.h"
|
||||
#include "iconloader.h"
|
||||
#include "mainwindow.h"
|
||||
#include "commandlineoptions.h"
|
||||
#include "systemtrayicon.h"
|
||||
#include "application.h"
|
||||
#include "networkproxyfactory.h"
|
||||
#include "scangiomodulepath.h"
|
||||
|
||||
#include "widgets/osd.h"
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
QDBusArgument &operator<<(QDBusArgument &arg, const QImage &image);
|
||||
const QDBusArgument &operator>>(const QDBusArgument &arg, QImage &image);
|
||||
|
||||
@@ -20,102 +20,112 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "version.h"
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <cmath>
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QApplication>
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QByteArray>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
#include <QFontMetrics>
|
||||
#include <QList>
|
||||
#include <QSet>
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QUrl>
|
||||
#include <QIcon>
|
||||
#include <QMimeData>
|
||||
#include <QPalette>
|
||||
#include <QTimer>
|
||||
#include <QtAlgorithms>
|
||||
#include <QKeySequence>
|
||||
#include <QMenu>
|
||||
#include <QAction>
|
||||
#include <QActionGroup>
|
||||
#include <QShortcut>
|
||||
#include <QMessageBox>
|
||||
#include <QtEvents>
|
||||
#include <QSettings>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "core/closure.h"
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
#include <memory>
|
||||
#include <cmath>
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QCloseEvent>
|
||||
#include <QDir>
|
||||
#include <QFileDialog>
|
||||
#include <QFileSystemModel>
|
||||
#include <QLinearGradient>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include <QSettings>
|
||||
#include <QShortcut>
|
||||
#include <QSignalMapper>
|
||||
#include <QStatusBar>
|
||||
#include <QtDebug>
|
||||
#include <QTimer>
|
||||
#include <QUndoStack>
|
||||
#include <QSystemTrayIcon>
|
||||
#include <QAction>
|
||||
#include <QList>
|
||||
#include <QModelIndex>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
#include "core/appearance.h"
|
||||
#include "core/application.h"
|
||||
#include "core/commandlineoptions.h"
|
||||
#include "core/database.h"
|
||||
#include "core/filesystemmusicstorage.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/mac_startup.h"
|
||||
#include "core/mergedproxymodel.h"
|
||||
#include "core/mimedata.h"
|
||||
#include "core/mpris_common.h"
|
||||
#include "core/network.h"
|
||||
#include "core/player.h"
|
||||
#include "core/songloader.h"
|
||||
#include "core/stylesheetloader.h"
|
||||
#include "core/taskmanager.h"
|
||||
#include "core/timeconstants.h"
|
||||
#include "core/utilities.h"
|
||||
#include "core/iconloader.h"
|
||||
#include "core/qtsystemtrayicon.h"
|
||||
#include "core/systemtrayicon.h"
|
||||
#include "core/windows7thumbbar.h"
|
||||
#include "globalshortcuts/globalshortcuts.h"
|
||||
#include "widgets/statusview.h"
|
||||
#include "utilities.h"
|
||||
#include "timeconstants.h"
|
||||
#include "commandlineoptions.h"
|
||||
#include "mimedata.h"
|
||||
#include "iconloader.h"
|
||||
#include "taskmanager.h"
|
||||
#include "song.h"
|
||||
#include "stylesheetloader.h"
|
||||
#include "systemtrayicon.h"
|
||||
#include "windows7thumbbar.h"
|
||||
#include "application.h"
|
||||
#include "database.h"
|
||||
#include "player.h"
|
||||
#include "appearance.h"
|
||||
#include "engine/enginebase.h"
|
||||
#include "engine/gstengine.h"
|
||||
#include "collection/groupbydialog.h"
|
||||
#include "dialogs/errordialog.h"
|
||||
#include "dialogs/about.h"
|
||||
#include "dialogs/console.h"
|
||||
#include "dialogs/trackselectiondialog.h"
|
||||
#include "dialogs/edittagdialog.h"
|
||||
#ifdef HAVE_GSTREAMER
|
||||
#include "dialogs/organisedialog.h"
|
||||
#endif
|
||||
#include "widgets/fancytabwidget.h"
|
||||
#include "widgets/playingwidget.h"
|
||||
#include "widgets/sliderwidget.h"
|
||||
#include "widgets/statusview.h"
|
||||
#include "widgets/fileview.h"
|
||||
#include "widgets/multiloadingindicator.h"
|
||||
#include "widgets/osd.h"
|
||||
#include "widgets/stylehelper.h"
|
||||
#include "widgets/trackslider.h"
|
||||
#include "collection/collection.h"
|
||||
#include "collection/collectionbackend.h"
|
||||
#include "collection/collectiondirectorymodel.h"
|
||||
#include "collection/collectionfilterwidget.h"
|
||||
#include "collection/collectionmodel.h"
|
||||
#include "collection/collectionquery.h"
|
||||
#include "collection/collectionview.h"
|
||||
#include "collection/collectionviewcontainer.h"
|
||||
#include "playlist/playlistbackend.h"
|
||||
#include "playlist/playlist.h"
|
||||
#include "playlist/playlistbackend.h"
|
||||
#include "playlist/playlistcontainer.h"
|
||||
#include "playlist/playlistlistcontainer.h"
|
||||
#include "playlist/playlistmanager.h"
|
||||
#include "playlist/playlistsequence.h"
|
||||
#include "playlist/playlistview.h"
|
||||
#include "playlist/queue.h"
|
||||
#include "playlist/queuemanager.h"
|
||||
#include "playlist/songplaylistitem.h"
|
||||
#include "playlistparsers/playlistparser.h"
|
||||
#include "analyzer/analyzercontainer.h"
|
||||
#include "equalizer/equalizer.h"
|
||||
#include "globalshortcuts/globalshortcuts.h"
|
||||
#include "musicbrainz/tagfetcher.h"
|
||||
#include "covermanager/albumcovermanager.h"
|
||||
#include "device/devicemanager.h"
|
||||
#include "device/devicestatefiltermodel.h"
|
||||
#include "device/deviceview.h"
|
||||
#include "device/deviceviewcontainer.h"
|
||||
#include "musicbrainz/tagfetcher.h"
|
||||
#include "equalizer/equalizer.h"
|
||||
#include "transcoder/transcodedialog.h"
|
||||
#include "dialogs/about.h"
|
||||
#include "dialogs/console.h"
|
||||
#include "dialogs/edittagdialog.h"
|
||||
#ifdef HAVE_GSTREAMER
|
||||
#include "dialogs/organisedialog.h"
|
||||
#include "dialogs/organiseerrordialog.h"
|
||||
#endif
|
||||
#include "dialogs/trackselectiondialog.h"
|
||||
#include "dialogs/errordialog.h"
|
||||
#include "widgets/fileview.h"
|
||||
#include "widgets/multiloadingindicator.h"
|
||||
#include "widgets/osd.h"
|
||||
#include "widgets/stylehelper.h"
|
||||
#include "widgets/trackslider.h"
|
||||
#include "settings/settingsdialog.h"
|
||||
#include "covermanager/albumcovermanager.h"
|
||||
|
||||
#include "settings/behavioursettingspage.h"
|
||||
#include "settings/playlistsettingspage.h"
|
||||
#include "settings/settingsdialog.h"
|
||||
|
||||
#ifdef Q_OS_DARWIN
|
||||
#include "ui/macsystemtrayicon.h"
|
||||
@@ -151,7 +161,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
device_view_(device_view_container_->view()),
|
||||
settings_dialog_(std::bind(&MainWindow::CreateSettingsDialog, this)),
|
||||
cover_manager_([=]() {
|
||||
AlbumCoverManager* cover_manager = new AlbumCoverManager(app, app->collection_backend());
|
||||
AlbumCoverManager *cover_manager = new AlbumCoverManager(app, app->collection_backend());
|
||||
cover_manager->Init();
|
||||
|
||||
// Cover manager connections
|
||||
@@ -163,13 +173,13 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
equalizer_(new Equalizer),
|
||||
#ifdef HAVE_GSTREAMER
|
||||
organise_dialog_([=]() {
|
||||
OrganiseDialog* dialog = new OrganiseDialog(app->task_manager());
|
||||
OrganiseDialog *dialog = new OrganiseDialog(app->task_manager());
|
||||
dialog->SetDestinationModel(app->collection()->model()->directory_model());
|
||||
return dialog;
|
||||
}),
|
||||
#endif
|
||||
queue_manager_([=]() {
|
||||
QueueManager* manager = new QueueManager;
|
||||
QueueManager *manager = new QueueManager;
|
||||
manager->SetPlaylistManager(app->playlist_manager());
|
||||
return manager;
|
||||
}),
|
||||
@@ -345,9 +355,6 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
connect(ui_->action_add_folder, SIGNAL(triggered()), SLOT(AddFolder()));
|
||||
connect(ui_->action_cover_manager, SIGNAL(triggered()), SLOT(ShowCoverManager()));
|
||||
connect(ui_->action_equalizer, SIGNAL(triggered()), equalizer_.get(), SLOT(show()));
|
||||
#ifdef HAVE_GSTREAMER
|
||||
//connect(ui_->action_transcode, SIGNAL(triggered()), SLOT(ShowTranscodeDialog()));
|
||||
#endif
|
||||
connect(ui_->action_jump, SIGNAL(triggered()), ui_->playlist->view(), SLOT(JumpToCurrentlyPlayingTrack()));
|
||||
connect(ui_->action_update_collection, SIGNAL(triggered()), app_->collection(), SLOT(IncrementalScan()));
|
||||
connect(ui_->action_full_collection_scan, SIGNAL(triggered()), app_->collection(), SLOT(FullScan()));
|
||||
@@ -375,7 +382,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
ui_->action_repeat_mode->setMenu(ui_->playlist_sequence->repeat_menu());
|
||||
|
||||
// Stop actions
|
||||
QMenu* stop_menu = new QMenu(this);
|
||||
QMenu *stop_menu = new QMenu(this);
|
||||
stop_menu->addAction(ui_->action_stop);
|
||||
stop_menu->addAction(ui_->action_stop_after_this_track);
|
||||
ui_->stop_button->setMenu(stop_menu);
|
||||
@@ -439,7 +446,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
connect(device_view_, SIGNAL(AddToPlaylistSignal(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
|
||||
|
||||
// Collection filter widget
|
||||
QActionGroup* collection_view_group = new QActionGroup(this);
|
||||
QActionGroup *collection_view_group = new QActionGroup(this);
|
||||
|
||||
collection_show_all_ = collection_view_group->addAction(tr("Show all songs"));
|
||||
collection_show_duplicates_ = collection_view_group->addAction(tr("Show only duplicates"));
|
||||
@@ -452,12 +459,12 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
|
||||
connect(collection_view_group, SIGNAL(triggered(QAction*)), SLOT(ChangeCollectionQueryMode(QAction*)));
|
||||
|
||||
QAction* collection_config_action = new QAction(IconLoader::Load("configure"), tr("Configure collection..."), this);
|
||||
QAction *collection_config_action = new QAction(IconLoader::Load("configure"), tr("Configure collection..."), this);
|
||||
connect(collection_config_action, SIGNAL(triggered()), SLOT(ShowCollectionConfig()));
|
||||
collection_view_->filter()->SetSettingsGroup(kSettingsGroup);
|
||||
collection_view_->filter()->SetCollectionModel(app_->collection()->model());
|
||||
|
||||
QAction* separator = new QAction(this);
|
||||
QAction *separator = new QAction(this);
|
||||
separator->setSeparator(true);
|
||||
|
||||
collection_view_->filter()->AddMenuAction(collection_show_all_);
|
||||
@@ -509,11 +516,10 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
ui_->action_shuffle->setShortcut(QKeySequence());
|
||||
#endif
|
||||
|
||||
// We have to add the actions on the playlist menu to this QWidget otherwise
|
||||
// their shortcut keys don't work
|
||||
// We have to add the actions on the playlist menu to this QWidget otherwise their shortcut keys don't work
|
||||
addActions(playlist_menu_->actions());
|
||||
|
||||
connect(ui_->playlist, SIGNAL(UndoRedoActionsChanged(QAction*,QAction*)), SLOT(PlaylistUndoRedoChanged(QAction*,QAction*)));
|
||||
connect(ui_->playlist, SIGNAL(UndoRedoActionsChanged(QAction*, QAction*)), SLOT(PlaylistUndoRedoChanged(QAction*, QAction*)));
|
||||
|
||||
#ifdef HAVE_GSTREAMER
|
||||
playlist_copy_to_device_->setDisabled(app_->device_manager()->connected_devices_model()->rowCount() == 0);
|
||||
@@ -539,7 +545,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
|
||||
#if (defined(Q_OS_DARWIN) && defined(HAVE_SPARKLE)) || defined(Q_OS_WIN32)
|
||||
// Add check for updates item to application menu.
|
||||
QAction* check_updates = ui_->menu_tools->addAction(tr("Check for updates..."));
|
||||
QAction *check_updates = ui_->menu_tools->addAction(tr("Check for updates..."));
|
||||
check_updates->setMenuRole(QAction::ApplicationSpecificRole);
|
||||
connect(check_updates, SIGNAL(triggered(bool)), SLOT(CheckForUpdates()));
|
||||
#endif
|
||||
@@ -602,11 +608,11 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
PlayingWidgetPositionChanged();
|
||||
|
||||
// Load theme
|
||||
// This is tricky: we need to save the default/system palette now, before
|
||||
// loading user preferred theme (which will overide it), to be able to restore it later
|
||||
// This is tricky: we need to save the default/system palette now,
|
||||
// before loading user preferred theme (which will overide it), to be able to restore it later
|
||||
const_cast<QPalette&>(Appearance::kDefaultPalette) = QApplication::palette();
|
||||
app_->appearance()->LoadUserTheme();
|
||||
StyleSheetLoader* css_loader = new StyleSheetLoader(this);
|
||||
StyleSheetLoader *css_loader = new StyleSheetLoader(this);
|
||||
css_loader->SetStyleSheet(this, ":style/mainwindow.css");
|
||||
RefreshStyleSheet();
|
||||
|
||||
@@ -643,8 +649,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
file_view_->SetPath(settings_.value("file_path", QDir::homePath()).toString());
|
||||
TabSwitched();
|
||||
|
||||
// Users often collapse one side of the splitter by mistake and don't know
|
||||
// how to restore it. This must be set after the state is restored above.
|
||||
// Users often collapse one side of the splitter by mistake and don't know how to restore it. This must be set after the state is restored above.
|
||||
ui_->splitter->setChildrenCollapsible(false);
|
||||
|
||||
ReloadSettings();
|
||||
@@ -703,8 +708,6 @@ MainWindow::~MainWindow() {
|
||||
}
|
||||
|
||||
void MainWindow::ReloadSettings() {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
QSettings settings;
|
||||
|
||||
@@ -809,8 +812,9 @@ void MainWindow::VolumeChanged(int volume) {
|
||||
}
|
||||
|
||||
void MainWindow::SongChanged(const Song &song) {
|
||||
|
||||
setWindowTitle(song.PrettyTitleWithArtist() + " --- Strawberry Music Player");
|
||||
|
||||
//setWindowTitle(song.PrettyTitleWithArtist() + " --- Strawberry Music Player");
|
||||
setWindowTitle(song.PrettyTitleWithArtist());
|
||||
tray_icon_->SetProgress(0);
|
||||
|
||||
}
|
||||
@@ -837,8 +841,6 @@ void MainWindow::TrackSkipped(PlaylistItemPtr item) {
|
||||
void MainWindow::resizeEvent(QResizeEvent*) { SaveGeometry(); }
|
||||
|
||||
void MainWindow::TabSwitched() {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__ << ui_->tabs->current_index() ;
|
||||
|
||||
if (ui_->tabs->current_index() > 0)
|
||||
ui_->now_playing->SetEnabled();
|
||||
@@ -850,8 +852,6 @@ void MainWindow::TabSwitched() {
|
||||
}
|
||||
|
||||
void MainWindow::SaveGeometry() {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
was_maximized_ = isMaximized();
|
||||
settings_.setValue("maximized", was_maximized_);
|
||||
@@ -866,8 +866,6 @@ void MainWindow::SaveGeometry() {
|
||||
}
|
||||
|
||||
void MainWindow::SavePlaybackStatus() {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
QSettings settings;
|
||||
|
||||
@@ -885,8 +883,6 @@ void MainWindow::SavePlaybackStatus() {
|
||||
}
|
||||
|
||||
void MainWindow::LoadPlaybackStatus() {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
QSettings settings;
|
||||
|
||||
@@ -933,8 +929,7 @@ void MainWindow::PlayIndex(const QModelIndex &index) {
|
||||
|
||||
int row = index.row();
|
||||
if (index.model() == app_->playlist_manager()->current()->proxy()) {
|
||||
// The index was in the proxy model (might've been filtered), so we need
|
||||
// to get the actual row in the source model.
|
||||
// The index was in the proxy model (might've been filtered), so we need to get the actual row in the source model.
|
||||
row = app_->playlist_manager()->current()->proxy()->mapToSource(index).row();
|
||||
}
|
||||
|
||||
@@ -947,10 +942,8 @@ void MainWindow::PlaylistDoubleClick(const QModelIndex &index) {
|
||||
|
||||
int row = index.row();
|
||||
if (index.model() == app_->playlist_manager()->current()->proxy()) {
|
||||
// The index was in the proxy model (might've been filtered), so we need
|
||||
// to get the actual row in the source model.
|
||||
row =
|
||||
app_->playlist_manager()->current()->proxy()->mapToSource(index).row();
|
||||
// The index was in the proxy model (might've been filtered), so we need to get the actual row in the source model.
|
||||
row = app_->playlist_manager()->current()->proxy()->mapToSource(index).row();
|
||||
}
|
||||
|
||||
QModelIndexList dummyIndexList;
|
||||
@@ -1028,8 +1021,7 @@ void MainWindow::SetHiddenInTray(bool hidden) {
|
||||
|
||||
settings_.setValue("hidden", hidden);
|
||||
|
||||
// Some window managers don't remember maximized state between calls to
|
||||
// hide() and show(), so we have to remember it ourself.
|
||||
// Some window managers don't remember maximized state between calls to hide() and show(), so we have to remember it ourself.
|
||||
if (hidden) {
|
||||
//was_maximized_ = isMaximized();
|
||||
hide();
|
||||
@@ -1053,11 +1045,9 @@ void MainWindow::Seeked(qlonglong microseconds) {
|
||||
}
|
||||
|
||||
void MainWindow::UpdateTrackPosition() {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
// Track position in seconds
|
||||
//Playlist* playlist = app_->playlist_manager()->active();
|
||||
//Playlist *playlist = app_->playlist_manager()->active();
|
||||
|
||||
PlaylistItemPtr item(app_->player()->GetCurrentItem());
|
||||
const int position = std::floor(float(app_->player()->engine()->position_nanosec()) / kNsecPerSec + 0.5);
|
||||
@@ -1086,7 +1076,7 @@ void MainWindow::UpdateTrackSliderPosition() {
|
||||
ui_->track_slider->SetValue(slider_position, slider_length);
|
||||
}
|
||||
|
||||
void MainWindow::ApplyAddBehaviour(MainWindow::AddBehaviour b, MimeData* data) const {
|
||||
void MainWindow::ApplyAddBehaviour(MainWindow::AddBehaviour b, MimeData *data) const {
|
||||
|
||||
switch (b) {
|
||||
case AddBehaviour_Append:
|
||||
@@ -1110,9 +1100,7 @@ void MainWindow::ApplyAddBehaviour(MainWindow::AddBehaviour b, MimeData* data) c
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::ApplyPlayBehaviour(MainWindow::PlayBehaviour b, MimeData* data) const {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
void MainWindow::ApplyPlayBehaviour(MainWindow::PlayBehaviour b, MimeData *data) const {
|
||||
|
||||
switch (b) {
|
||||
case PlayBehaviour_Always:
|
||||
@@ -1129,9 +1117,7 @@ void MainWindow::ApplyPlayBehaviour(MainWindow::PlayBehaviour b, MimeData* data)
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::AddToPlaylist(QMimeData* data) {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
void MainWindow::AddToPlaylist(QMimeData *data) {
|
||||
|
||||
if (!data) return;
|
||||
|
||||
@@ -1157,15 +1143,13 @@ void MainWindow::AddToPlaylist(QMimeData* data) {
|
||||
delete data;
|
||||
}
|
||||
|
||||
void MainWindow::AddToPlaylist(QAction* action) {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
void MainWindow::AddToPlaylist(QAction *action) {
|
||||
|
||||
int destination = action->data().toInt();
|
||||
PlaylistItemList items;
|
||||
|
||||
// get the selected playlist items
|
||||
for (const QModelIndex& index : ui_->playlist->view()->selectionModel()->selection().indexes()) {
|
||||
for (const QModelIndex &index : ui_->playlist->view()->selectionModel()->selection().indexes()) {
|
||||
if (index.column() != 0) continue;
|
||||
int row = app_->playlist_manager()->current()->proxy()->mapToSource(index).row();
|
||||
items << app_->playlist_manager()->current()->item_at(row);
|
||||
@@ -1198,8 +1182,6 @@ void MainWindow::AddToPlaylist(QAction* action) {
|
||||
|
||||
void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex &index) {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
QModelIndex source_index = app_->playlist_manager()->current()->proxy()->mapToSource(index);
|
||||
|
||||
playlist_menu_index_ = source_index;
|
||||
@@ -1374,10 +1356,10 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
|
||||
QMenu *add_to_another_menu = new QMenu(tr("Add to another playlist"), this);
|
||||
add_to_another_menu->setIcon(IconLoader::Load("list-add"));
|
||||
|
||||
for (const PlaylistBackend::Playlist& playlist : app_->playlist_backend()->GetAllOpenPlaylists()) {
|
||||
for (const PlaylistBackend::Playlist &playlist : app_->playlist_backend()->GetAllOpenPlaylists()) {
|
||||
// don't add the current playlist
|
||||
if (playlist.id != app_->playlist_manager()->current()->id()) {
|
||||
QAction* existing_playlist = new QAction(this);
|
||||
QAction *existing_playlist = new QAction(this);
|
||||
existing_playlist->setText(playlist.name);
|
||||
existing_playlist->setData(playlist.id);
|
||||
add_to_another_menu->addAction(existing_playlist);
|
||||
@@ -1386,7 +1368,7 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
|
||||
|
||||
add_to_another_menu->addSeparator();
|
||||
// add to a new playlist
|
||||
QAction* new_playlist = new QAction(this);
|
||||
QAction *new_playlist = new QAction(this);
|
||||
new_playlist->setText(tr("New playlist"));
|
||||
new_playlist->setData(-1); // fake id
|
||||
add_to_another_menu->addAction(new_playlist);
|
||||
@@ -1414,7 +1396,7 @@ void MainWindow::EditTracks() {
|
||||
SongList songs;
|
||||
PlaylistItemList items;
|
||||
|
||||
for (const QModelIndex& index : ui_->playlist->view()->selectionModel()->selection().indexes()) {
|
||||
for (const QModelIndex &index : ui_->playlist->view()->selectionModel()->selection().indexes()) {
|
||||
if (index.column() != 0) continue;
|
||||
int row =app_->playlist_manager()->current()->proxy()->mapToSource(index).row();
|
||||
PlaylistItemPtr item(app_->playlist_manager()->current()->item_at(row));
|
||||
@@ -1456,7 +1438,7 @@ void MainWindow::RenumberTracks() {
|
||||
if (first_song.track() > 0) track = first_song.track();
|
||||
}
|
||||
|
||||
for (const QModelIndex& index : indexes) {
|
||||
for (const QModelIndex &index : indexes) {
|
||||
if (index.column() != 0) continue;
|
||||
|
||||
const QModelIndex source_index =app_->playlist_manager()->current()->proxy()->mapToSource(index);
|
||||
@@ -1466,7 +1448,7 @@ void MainWindow::RenumberTracks() {
|
||||
if (song.IsEditable()) {
|
||||
song.set_track(track);
|
||||
|
||||
TagReaderReply* reply =TagReaderClient::Instance()->SaveFile(song.url().toLocalFile(), song);
|
||||
TagReaderReply *reply =TagReaderClient::Instance()->SaveFile(song.url().toLocalFile(), song);
|
||||
|
||||
NewClosure(reply, SIGNAL(Finished(bool)), this, SLOT(SongSaveComplete(TagReaderReply*, QPersistentModelIndex)),reply, QPersistentModelIndex(source_index));
|
||||
}
|
||||
@@ -1474,7 +1456,7 @@ void MainWindow::RenumberTracks() {
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::SongSaveComplete(TagReaderReply* reply,const QPersistentModelIndex& index) {
|
||||
void MainWindow::SongSaveComplete(TagReaderReply *reply,const QPersistentModelIndex &index) {
|
||||
if (reply->is_successful() && index.isValid()) {
|
||||
app_->playlist_manager()->current()->ReloadItems(QList<int>()<< index.row());
|
||||
}
|
||||
@@ -1487,7 +1469,7 @@ void MainWindow::SelectionSetValue() {
|
||||
|
||||
QModelIndexList indexes =ui_->playlist->view()->selectionModel()->selection().indexes();
|
||||
|
||||
for (const QModelIndex& index : indexes) {
|
||||
for (const QModelIndex &index : indexes) {
|
||||
if (index.column() != 0) continue;
|
||||
|
||||
const QModelIndex source_index =app_->playlist_manager()->current()->proxy()->mapToSource(index);
|
||||
@@ -1495,7 +1477,7 @@ void MainWindow::SelectionSetValue() {
|
||||
Song song = app_->playlist_manager()->current()->item_at(row)->Metadata();
|
||||
|
||||
if (Playlist::set_column_value(song, column, column_value)) {
|
||||
TagReaderReply* reply =TagReaderClient::Instance()->SaveFile(song.url().toLocalFile(), song);
|
||||
TagReaderReply *reply =TagReaderClient::Instance()->SaveFile(song.url().toLocalFile(), song);
|
||||
|
||||
NewClosure(reply, SIGNAL(Finished(bool)), this, SLOT(SongSaveComplete(TagReaderReply*, QPersistentModelIndex)),reply, QPersistentModelIndex(source_index));
|
||||
}
|
||||
@@ -1507,8 +1489,7 @@ void MainWindow::EditValue() {
|
||||
|
||||
if (!current.isValid()) return;
|
||||
|
||||
// Edit the last column that was right-clicked on. If nothing's ever been
|
||||
// right clicked then look for the first editable column.
|
||||
// Edit the last column that was right-clicked on. If nothing's ever been right clicked then look for the first editable column.
|
||||
int column = playlist_menu_index_.column();
|
||||
if (column == -1) {
|
||||
for (int i = 0; i < ui_->playlist->view()->model()->columnCount(); ++i) {
|
||||
@@ -1524,15 +1505,13 @@ void MainWindow::EditValue() {
|
||||
|
||||
void MainWindow::AddFile() {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
// Last used directory
|
||||
QString directory =settings_.value("add_media_path", QDir::currentPath()).toString();
|
||||
|
||||
PlaylistParser parser(app_->collection_backend());
|
||||
|
||||
// Show dialog
|
||||
QStringList file_names = QFileDialog::getOpenFileNames(this, tr("Add file"), directory,QString("%1 (%2);;%3;;%4").arg(tr("Music"), FileView::kFileFilter,parser.filters(),tr(kAllFilesFilterSpec)));
|
||||
QStringList file_names = QFileDialog::getOpenFileNames(this, tr("Add file"), directory, QString("%1 (%2);;%3;;%4").arg(tr("Music"), FileView::kFileFilter, parser.filters(), tr(kAllFilesFilterSpec)));
|
||||
|
||||
if (file_names.isEmpty()) return;
|
||||
|
||||
@@ -1541,11 +1520,11 @@ void MainWindow::AddFile() {
|
||||
|
||||
// Convert to URLs
|
||||
QList<QUrl> urls;
|
||||
for (const QString& path : file_names) {
|
||||
for (const QString &path : file_names) {
|
||||
urls << QUrl::fromLocalFile(QFileInfo(path).canonicalFilePath());
|
||||
}
|
||||
|
||||
MimeData* data = new MimeData;
|
||||
MimeData *data = new MimeData;
|
||||
data->setUrls(urls);
|
||||
AddToPlaylist(data);
|
||||
}
|
||||
@@ -1562,15 +1541,14 @@ void MainWindow::AddFolder() {
|
||||
settings_.setValue("add_folder_path", directory);
|
||||
|
||||
// Add media
|
||||
MimeData* data = new MimeData;
|
||||
MimeData *data = new MimeData;
|
||||
data->setUrls(QList<QUrl>() << QUrl::fromLocalFile(QFileInfo(directory).canonicalFilePath()));
|
||||
AddToPlaylist(data);
|
||||
}
|
||||
|
||||
void MainWindow::AddCDTracks() {
|
||||
MimeData* data = new MimeData;
|
||||
// We are putting empty data, but we specify cdda mimetype to indicate that
|
||||
// we want to load audio cd tracks
|
||||
MimeData *data = new MimeData;
|
||||
// We are putting empty data, but we specify cdda mimetype to indicate that we want to load audio cd tracks
|
||||
data->open_in_new_playlist_ = true;
|
||||
data->setData(Playlist::kCddaMimeType, QByteArray());
|
||||
AddToPlaylist(data);
|
||||
@@ -1582,7 +1560,7 @@ void MainWindow::ShowInCollection() {
|
||||
QModelIndexList proxy_indexes =ui_->playlist->view()->selectionModel()->selectedRows();
|
||||
SongList songs;
|
||||
|
||||
for (const QModelIndex& proxy_index : proxy_indexes) {
|
||||
for (const QModelIndex &proxy_index : proxy_indexes) {
|
||||
QModelIndex index =app_->playlist_manager()->current()->proxy()->mapToSource(proxy_index);
|
||||
if (app_->playlist_manager()->current()->item_at(index.row())->IsLocalCollectionItem()) {
|
||||
songs << app_->playlist_manager()->current()->item_at(index.row())->Metadata();
|
||||
@@ -1600,11 +1578,11 @@ void MainWindow::PlaylistRemoveCurrent() {
|
||||
ui_->playlist->view()->RemoveSelected(false);
|
||||
}
|
||||
|
||||
void MainWindow::PlaylistEditFinished(const QModelIndex& index) {
|
||||
void MainWindow::PlaylistEditFinished(const QModelIndex &index) {
|
||||
if (index == playlist_menu_index_) SelectionSetValue();
|
||||
}
|
||||
|
||||
void MainWindow::CommandlineOptionsReceived(const QString& string_options) {
|
||||
void MainWindow::CommandlineOptionsReceived(const QString &string_options) {
|
||||
|
||||
CommandlineOptions options;
|
||||
options.Load(string_options.toLatin1());
|
||||
@@ -1617,7 +1595,7 @@ void MainWindow::CommandlineOptionsReceived(const QString& string_options) {
|
||||
CommandlineOptionsReceived(options);
|
||||
}
|
||||
|
||||
void MainWindow::CommandlineOptionsReceived(const CommandlineOptions& options) {
|
||||
void MainWindow::CommandlineOptionsReceived(const CommandlineOptions &options) {
|
||||
switch (options.player_action()) {
|
||||
case CommandlineOptions::Player_Play:
|
||||
if (options.urls().empty()) {
|
||||
@@ -1651,7 +1629,7 @@ void MainWindow::CommandlineOptionsReceived(const CommandlineOptions& options) {
|
||||
}
|
||||
|
||||
if (!options.urls().empty()) {
|
||||
MimeData* data = new MimeData;
|
||||
MimeData *data = new MimeData;
|
||||
data->setUrls(options.urls());
|
||||
// Behaviour depends on command line options, so set it here
|
||||
data->override_user_settings_ = true;
|
||||
@@ -1698,7 +1676,7 @@ void MainWindow::CommandlineOptionsReceived(const CommandlineOptions& options) {
|
||||
if (options.toggle_pretty_osd()) app_->player()->TogglePrettyOSD();
|
||||
}
|
||||
|
||||
void MainWindow::ForceShowOSD(const Song& song, const bool toggle) {
|
||||
void MainWindow::ForceShowOSD(const Song &song, const bool toggle) {
|
||||
if (toggle) {
|
||||
osd_->SetPrettyOSDToggleMode(toggle);
|
||||
}
|
||||
@@ -1709,11 +1687,11 @@ void MainWindow::Activate() {
|
||||
show();
|
||||
}
|
||||
|
||||
bool MainWindow::LoadUrl(const QString& url) {
|
||||
bool MainWindow::LoadUrl(const QString &url) {
|
||||
|
||||
if (!QFile::exists(url)) return false;
|
||||
|
||||
MimeData* data = new MimeData;
|
||||
MimeData *data = new MimeData;
|
||||
data->setUrls(QList<QUrl>() << QUrl::fromLocalFile(url));
|
||||
AddToPlaylist(data);
|
||||
|
||||
@@ -1726,7 +1704,7 @@ void MainWindow::CheckForUpdates() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::PlaylistUndoRedoChanged(QAction* undo, QAction* redo) {
|
||||
void MainWindow::PlaylistUndoRedoChanged(QAction *undo, QAction *redo) {
|
||||
|
||||
playlist_menu_->insertAction(playlist_undoredo_, undo);
|
||||
playlist_menu_->insertAction(playlist_undoredo_, redo);
|
||||
@@ -1737,7 +1715,7 @@ void MainWindow::AddFilesToTranscoder() {
|
||||
|
||||
QStringList filenames;
|
||||
|
||||
for (const QModelIndex& index : ui_->playlist->view()->selectionModel()->selection().indexes()) {
|
||||
for (const QModelIndex &index : ui_->playlist->view()->selectionModel()->selection().indexes()) {
|
||||
if (index.column() != 0) continue;
|
||||
int row =app_->playlist_manager()->current()->proxy()->mapToSource(index).row();
|
||||
PlaylistItemPtr item(app_->playlist_manager()->current()->item_at(row));
|
||||
@@ -1775,37 +1753,36 @@ void MainWindow::PlayingWidgetPositionChanged() {
|
||||
}
|
||||
|
||||
#ifdef HAVE_GSTREAMER
|
||||
void MainWindow::CopyFilesToCollection(const QList<QUrl>& urls) {
|
||||
void MainWindow::CopyFilesToCollection(const QList<QUrl> &urls) {
|
||||
organise_dialog_->SetDestinationModel(app_->collection_model()->directory_model());
|
||||
organise_dialog_->SetUrls(urls);
|
||||
organise_dialog_->SetCopy(true);
|
||||
organise_dialog_->show();
|
||||
}
|
||||
|
||||
void MainWindow::MoveFilesToCollection(const QList<QUrl>& urls) {
|
||||
void MainWindow::MoveFilesToCollection(const QList<QUrl> &urls) {
|
||||
organise_dialog_->SetDestinationModel(app_->collection_model()->directory_model());
|
||||
organise_dialog_->SetUrls(urls);
|
||||
organise_dialog_->SetCopy(false);
|
||||
organise_dialog_->show();
|
||||
}
|
||||
|
||||
void MainWindow::CopyFilesToDevice(const QList<QUrl>& urls) {
|
||||
void MainWindow::CopyFilesToDevice(const QList<QUrl> &urls) {
|
||||
organise_dialog_->SetDestinationModel(app_->device_manager()->connected_devices_model(), true);
|
||||
organise_dialog_->SetCopy(true);
|
||||
if (organise_dialog_->SetUrls(urls))
|
||||
organise_dialog_->show();
|
||||
else {
|
||||
QMessageBox::warning(this, tr("Error"),
|
||||
tr("None of the selected songs were suitable for copying to a device"));
|
||||
QMessageBox::warning(this, tr("Error"), tr("None of the selected songs were suitable for copying to a device"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void MainWindow::EditFileTags(const QList<QUrl>& urls) {
|
||||
void MainWindow::EditFileTags(const QList<QUrl> &urls) {
|
||||
//EnsureEditTagDialogCreated();
|
||||
|
||||
SongList songs;
|
||||
for (const QUrl& url : urls) {
|
||||
for (const QUrl &url : urls) {
|
||||
Song song;
|
||||
song.set_url(url);
|
||||
song.set_valid(true);
|
||||
@@ -1831,9 +1808,8 @@ void MainWindow::PlaylistOrganiseSelected(bool copy) {
|
||||
QModelIndexList proxy_indexes = ui_->playlist->view()->selectionModel()->selectedRows();
|
||||
SongList songs;
|
||||
|
||||
for (const QModelIndex& proxy_index : proxy_indexes) {
|
||||
for (const QModelIndex &proxy_index : proxy_indexes) {
|
||||
QModelIndex index =app_->playlist_manager()->current()->proxy()->mapToSource(proxy_index);
|
||||
|
||||
songs << app_->playlist_manager()->current()->item_at(index.row())->Metadata();
|
||||
}
|
||||
|
||||
@@ -1859,7 +1835,7 @@ void MainWindow::PlaylistDelete() {
|
||||
// Get selected songs
|
||||
SongList selected_songs;
|
||||
QModelIndexList proxy_indexes = ui_->playlist->view()->selectionModel()->selectedRows();
|
||||
for (const QModelIndex& proxy_index : proxy_indexes) {
|
||||
for (const QModelIndex &proxy_index : proxy_indexes) {
|
||||
QModelIndex index = app_->playlist_manager()->current()->proxy()->mapToSource(proxy_index);
|
||||
selected_songs << app_->playlist_manager()->current()->item_at(index.row())->Metadata();
|
||||
}
|
||||
@@ -1879,7 +1855,7 @@ void MainWindow::PlaylistDelete() {
|
||||
|
||||
ui_->playlist->view()->RemoveSelected(true);
|
||||
|
||||
DeleteFiles* delete_files = new DeleteFiles(app_->task_manager(), storage);
|
||||
DeleteFiles *delete_files = new DeleteFiles(app_->task_manager(), storage);
|
||||
connect(delete_files, SIGNAL(Finished(SongList)), SLOT(DeleteFinished(SongList)));
|
||||
delete_files->Start(selected_songs);
|
||||
}
|
||||
@@ -1890,7 +1866,7 @@ void MainWindow::PlaylistOpenInBrowser() {
|
||||
QList<QUrl> urls;
|
||||
QModelIndexList proxy_indexes = ui_->playlist->view()->selectionModel()->selectedRows();
|
||||
|
||||
for (const QModelIndex& proxy_index : proxy_indexes) {
|
||||
for (const QModelIndex &proxy_index : proxy_indexes) {
|
||||
const QModelIndex index = app_->playlist_manager()->current()->proxy()->mapToSource(proxy_index);
|
||||
urls << QUrl(index.sibling(index.row(), Playlist::Column_Filename).data().toString());
|
||||
}
|
||||
@@ -1899,10 +1875,10 @@ void MainWindow::PlaylistOpenInBrowser() {
|
||||
}
|
||||
|
||||
#if 0
|
||||
void MainWindow::DeleteFinished(const SongList& songs_with_errors) {
|
||||
void MainWindow::DeleteFinished(const SongList &songs_with_errors) {
|
||||
if (songs_with_errors.isEmpty()) return;
|
||||
|
||||
OrganiseErrorDialog* dialog = new OrganiseErrorDialog(this);
|
||||
OrganiseErrorDialog *dialog = new OrganiseErrorDialog(this);
|
||||
dialog->Show(OrganiseErrorDialog::Type_Delete, songs_with_errors);
|
||||
// It deletes itself when the user closes it
|
||||
}
|
||||
@@ -1911,7 +1887,7 @@ void MainWindow::DeleteFinished(const SongList& songs_with_errors) {
|
||||
void MainWindow::PlaylistQueue() {
|
||||
|
||||
QModelIndexList indexes;
|
||||
for (const QModelIndex& proxy_index : ui_->playlist->view()->selectionModel()->selectedRows()) {
|
||||
for (const QModelIndex &proxy_index : ui_->playlist->view()->selectionModel()->selectedRows()) {
|
||||
indexes << app_->playlist_manager()->current()->proxy()->mapToSource(proxy_index);
|
||||
}
|
||||
|
||||
@@ -1936,7 +1912,7 @@ void MainWindow::PlaylistCopyToDevice() {
|
||||
QModelIndexList proxy_indexes = ui_->playlist->view()->selectionModel()->selectedRows();
|
||||
SongList songs;
|
||||
|
||||
for (const QModelIndex& proxy_index : proxy_indexes) {
|
||||
for (const QModelIndex &proxy_index : proxy_indexes) {
|
||||
QModelIndex index = app_->playlist_manager()->current()->proxy()->mapToSource(proxy_index);
|
||||
|
||||
songs << app_->playlist_manager()->current()->item_at(index.row())->Metadata();
|
||||
@@ -1953,7 +1929,7 @@ void MainWindow::PlaylistCopyToDevice() {
|
||||
}
|
||||
#endif
|
||||
|
||||
void MainWindow::ChangeCollectionQueryMode(QAction* action) {
|
||||
void MainWindow::ChangeCollectionQueryMode(QAction *action) {
|
||||
if (action == collection_show_duplicates_) {
|
||||
collection_view_->filter()->SetQueryMode(QueryOptions::QueryMode_Duplicates);
|
||||
}
|
||||
@@ -1979,9 +1955,9 @@ void MainWindow::ShowCoverManager() {
|
||||
|
||||
}
|
||||
|
||||
SettingsDialog* MainWindow::CreateSettingsDialog() {
|
||||
SettingsDialog *MainWindow::CreateSettingsDialog() {
|
||||
|
||||
SettingsDialog* settings_dialog = new SettingsDialog(app_);
|
||||
SettingsDialog *settings_dialog = new SettingsDialog(app_);
|
||||
settings_dialog->SetGlobalShortcutManager(global_shortcuts_);
|
||||
//settings_dialog->SetSongInfoView(song_info_view_);
|
||||
|
||||
@@ -2022,7 +1998,7 @@ void MainWindow::OpenSettingsDialogAtPage(SettingsDialog::Page page) {
|
||||
settings_dialog_->OpenAtPage(page);
|
||||
}
|
||||
|
||||
EditTagDialog* MainWindow::CreateEditTagDialog() {
|
||||
EditTagDialog *MainWindow::CreateEditTagDialog() {
|
||||
|
||||
EditTagDialog *edit_tag_dialog = new EditTagDialog(app_);
|
||||
connect(edit_tag_dialog, SIGNAL(accepted()), SLOT(EditTagDialogAccepted()));
|
||||
@@ -2062,7 +2038,7 @@ void MainWindow::ShowTranscodeDialog() {
|
||||
}
|
||||
#endif
|
||||
|
||||
void MainWindow::ShowErrorDialog(const QString& message) {
|
||||
void MainWindow::ShowErrorDialog(const QString &message) {
|
||||
//if (!error_dialog_) {
|
||||
// error_dialog_.reset(new ErrorDialog);
|
||||
//}
|
||||
@@ -2074,13 +2050,12 @@ void MainWindow::CheckFullRescanRevisions() {
|
||||
int from = app_->database()->startup_schema_version();
|
||||
int to = app_->database()->current_schema_version();
|
||||
|
||||
// if we're restoring DB from scratch or nothing has
|
||||
// changed, do nothing
|
||||
// if we're restoring DB from scratch or nothing has changed, do nothing
|
||||
if (from == 0 || from == to) {
|
||||
return;
|
||||
}
|
||||
|
||||
// collect all reasons
|
||||
// Collect all reasons
|
||||
QSet<QString> reasons;
|
||||
for (int i = from; i <= to; i++) {
|
||||
QString reason = app_->collection()->full_rescan_reason(i);
|
||||
@@ -2093,7 +2068,7 @@ void MainWindow::CheckFullRescanRevisions() {
|
||||
// if we have any...
|
||||
if (!reasons.isEmpty()) {
|
||||
QString message = tr("The version of Strawberry you've just updated to requires a full collection rescan because of the new features listed below:") + "<ul>";
|
||||
for(const QString& reason : reasons) {
|
||||
for(const QString &reason : reasons) {
|
||||
message += ("<li>" + reason + "</li>");
|
||||
}
|
||||
message += "</ul>" + tr("Would you like to run a full rescan right now?");
|
||||
@@ -2142,12 +2117,10 @@ void MainWindow::ShowSongInfoConfig() {
|
||||
|
||||
void MainWindow::PlaylistViewSelectionModelChanged() {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
connect(ui_->playlist->view()->selectionModel(),SIGNAL(currentChanged(QModelIndex, QModelIndex)), SLOT(PlaylistCurrentChanged(QModelIndex)));
|
||||
}
|
||||
|
||||
void MainWindow::PlaylistCurrentChanged(const QModelIndex& proxy_current) {
|
||||
void MainWindow::PlaylistCurrentChanged(const QModelIndex &proxy_current) {
|
||||
const QModelIndex source_current =app_->playlist_manager()->current()->proxy()->mapToSource(proxy_current);
|
||||
|
||||
// If the user moves the current index using the keyboard and then presses
|
||||
@@ -2161,7 +2134,7 @@ void MainWindow::Raise() {
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
bool MainWindow::winEvent(MSG* msg, long*) {
|
||||
bool MainWindow::winEvent(MSG *msg, long*) {
|
||||
thumbbar_->HandleWinEvent(msg);
|
||||
return false;
|
||||
}
|
||||
@@ -2169,8 +2142,6 @@ bool MainWindow::winEvent(MSG* msg, long*) {
|
||||
|
||||
void MainWindow::Exit() {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
SavePlaybackStatus();
|
||||
//settings_.setValue("show_sidebar", ui_->action_toggle_show_sidebar->isChecked());
|
||||
|
||||
@@ -2185,10 +2156,6 @@ void MainWindow::Exit() {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_GSTREAMER
|
||||
//gst_deinit();
|
||||
#endif
|
||||
|
||||
qApp->quit();
|
||||
|
||||
}
|
||||
@@ -2212,7 +2179,7 @@ void MainWindow::AutoCompleteTags() {
|
||||
// Get the selected songs and start fetching tags for them
|
||||
SongList songs;
|
||||
autocomplete_tag_items_.clear();
|
||||
for (const QModelIndex& index : ui_->playlist->view()->selectionModel()->selection().indexes()) {
|
||||
for (const QModelIndex &index : ui_->playlist->view()->selectionModel()->selection().indexes()) {
|
||||
if (index.column() != 0) continue;
|
||||
int row = app_->playlist_manager()->current()->proxy()->mapToSource(index).row();
|
||||
PlaylistItemPtr item(app_->playlist_manager()->current()->item_at(row));
|
||||
@@ -2269,11 +2236,11 @@ void MainWindow::FocusCollectionTab() {
|
||||
}
|
||||
|
||||
void MainWindow::ShowConsole() {
|
||||
Console* console = new Console(app_, this);
|
||||
Console *console = new Console(app_, this);
|
||||
console->show();
|
||||
}
|
||||
|
||||
void MainWindow::keyPressEvent(QKeyEvent* event) {
|
||||
void MainWindow::keyPressEvent(QKeyEvent *event) {
|
||||
if (event->key() == Qt::Key_Space) {
|
||||
app_->player()->PlayPause();
|
||||
event->accept();
|
||||
|
||||
@@ -24,38 +24,43 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <memory>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include <QMainWindow>
|
||||
#include <QSettings>
|
||||
#include <QSystemTrayIcon>
|
||||
#include <QAction>
|
||||
#include <QTimer>
|
||||
#include <QMenu>
|
||||
#include <QList>
|
||||
#include <QModelIndex>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QAbstractItemModel>
|
||||
#include <QModelIndex>
|
||||
#include <QPersistentModelIndex>
|
||||
#include <QMenu>
|
||||
#include <QAction>
|
||||
#include <QPoint>
|
||||
#include <QMimeData>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include <QPixmap>
|
||||
#include <QTimer>
|
||||
#include <QSettings>
|
||||
#include <QtEvents>
|
||||
|
||||
#include "core/lazy.h"
|
||||
#include "core/mac_startup.h"
|
||||
#include "core/tagreaderclient.h"
|
||||
#include "engine/engine_fwd.h"
|
||||
#include "mac_startup.h"
|
||||
#include "widgets/osd.h"
|
||||
#include "collection/collectionmodel.h"
|
||||
#include "playlist/playlistitem.h"
|
||||
#ifdef HAVE_GSTREAMER
|
||||
#include "dialogs/organisedialog.h"
|
||||
#endif
|
||||
#include "settings/settingsdialog.h"
|
||||
|
||||
class StatusView;
|
||||
class About;
|
||||
class AlbumCoverManager;
|
||||
class Appearance;
|
||||
class AlbumCoverManager;;
|
||||
class Application;
|
||||
class ArtistInfoView;
|
||||
class CollectionViewContainer;
|
||||
class CommandlineOptions;
|
||||
class CoverProviders;
|
||||
class Database;
|
||||
class DeviceManager;
|
||||
class DeviceView;
|
||||
class DeviceViewContainer;
|
||||
class EditTagDialog;
|
||||
@@ -63,35 +68,26 @@ class Equalizer;
|
||||
class ErrorDialog;
|
||||
class FileView;
|
||||
class GlobalShortcuts;
|
||||
class GroupByDialog;
|
||||
class Collection;
|
||||
class CollectionViewContainer;
|
||||
class MimeData;
|
||||
class MultiLoadingIndicator;
|
||||
class OSD;
|
||||
class Player;
|
||||
class PlaylistBackend;
|
||||
class OrganiseDialog;
|
||||
class PlaylistListContainer;
|
||||
class PlaylistManager;
|
||||
class QueueManager;
|
||||
class Song;
|
||||
class StatusView;
|
||||
class SystemTrayIcon;
|
||||
class TagFetcher;
|
||||
class TaskManager;
|
||||
class TrackSelectionDialog;
|
||||
#ifdef HAVE_GSTREAMER
|
||||
class TranscodeDialog;
|
||||
#endif
|
||||
class Windows7ThumbBar;
|
||||
class Ui_MainWindow;
|
||||
|
||||
class QSortFilterProxyModel;
|
||||
class Windows7ThumbBar;
|
||||
|
||||
class MainWindow : public QMainWindow, public PlatformInterface {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MainWindow(Application *app, SystemTrayIcon* tray_icon, OSD* osd, const CommandlineOptions& options, QWidget* parent = nullptr);
|
||||
MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, const CommandlineOptions& options, QWidget *parent = nullptr);
|
||||
~MainWindow();
|
||||
|
||||
static const char *kSettingsGroup;
|
||||
@@ -129,12 +125,12 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
||||
void CommandlineOptionsReceived(const CommandlineOptions& options);
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
void resizeEvent(QResizeEvent* event);
|
||||
void closeEvent(QCloseEvent* event);
|
||||
void keyPressEvent(QKeyEvent *event);
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
void closeEvent(QCloseEvent *event);
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
bool winEvent(MSG* message, long* result);
|
||||
bool winEvent(MSG *message, long *result);
|
||||
#endif
|
||||
|
||||
// PlatformInterface
|
||||
@@ -174,7 +170,7 @@ signals:
|
||||
void AutoCompleteTags();
|
||||
void AutoCompleteTagsAccepted();
|
||||
#endif
|
||||
void PlaylistUndoRedoChanged(QAction* undo, QAction* redo);
|
||||
void PlaylistUndoRedoChanged(QAction *undo, QAction *redo);
|
||||
#ifdef HAVE_GSTREAMER
|
||||
void AddFilesToTranscoder();
|
||||
#endif
|
||||
@@ -189,7 +185,7 @@ signals:
|
||||
void PlaylistOpenInBrowser();
|
||||
void ShowInCollection();
|
||||
|
||||
void ChangeCollectionQueryMode(QAction* action);
|
||||
void ChangeCollectionQueryMode(QAction *action);
|
||||
|
||||
void PlayIndex(const QModelIndex& index);
|
||||
void PlaylistDoubleClick(const QModelIndex& index);
|
||||
@@ -205,8 +201,8 @@ signals:
|
||||
#endif
|
||||
void EditFileTags(const QList<QUrl>& urls);
|
||||
|
||||
void AddToPlaylist(QMimeData* data);
|
||||
void AddToPlaylist(QAction* action);
|
||||
void AddToPlaylist(QMimeData *data);
|
||||
void AddToPlaylist(QAction *action);
|
||||
|
||||
void VolumeWheelEvent(int delta);
|
||||
void ToggleShowHide();
|
||||
@@ -245,8 +241,8 @@ signals:
|
||||
void ShowQueueManager();
|
||||
void EnsureSettingsDialogCreated();
|
||||
void EnsureEditTagDialogCreated();
|
||||
SettingsDialog* CreateSettingsDialog();
|
||||
EditTagDialog* CreateEditTagDialog();
|
||||
SettingsDialog *CreateSettingsDialog();
|
||||
EditTagDialog *CreateEditTagDialog();
|
||||
void OpenSettingsDialog();
|
||||
void OpenSettingsDialogAtPage(SettingsDialog::Page page);
|
||||
|
||||
@@ -281,12 +277,12 @@ signals:
|
||||
Windows7ThumbBar *thumbbar_;
|
||||
|
||||
Application *app_;
|
||||
SystemTrayIcon * tray_icon_;
|
||||
OSD* osd_;
|
||||
SystemTrayIcon *tray_icon_;
|
||||
OSD *osd_;
|
||||
Lazy<EditTagDialog> edit_tag_dialog_;
|
||||
Lazy<About> about_dialog_;
|
||||
|
||||
GlobalShortcuts* global_shortcuts_;
|
||||
GlobalShortcuts *global_shortcuts_;
|
||||
|
||||
CollectionViewContainer *collection_view_;
|
||||
StatusView *status_view_;
|
||||
|
||||
@@ -20,21 +20,32 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "mergedproxymodel.h"
|
||||
#include "core/logging.h"
|
||||
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
|
||||
#include <QObject>
|
||||
#include <QMimeData>
|
||||
#include <QStringList>
|
||||
#include <QtAlgorithms>
|
||||
#include <QAbstractItemModel>
|
||||
#include <QAbstractProxyModel>
|
||||
|
||||
#include "mergedproxymodel.h"
|
||||
|
||||
// boost::multi_index still relies on these being in the global namespace.
|
||||
using std::placeholders::_1;
|
||||
using std::placeholders::_2;
|
||||
|
||||
#include <boost/multi_index_container.hpp>
|
||||
#include <boost/multi_index/member.hpp>
|
||||
#include <boost/multi_index/detail/bidir_node_iterator.hpp>
|
||||
#include <boost/multi_index/detail/hash_index_iterator.hpp>
|
||||
#include <boost/multi_index/hashed_index.hpp>
|
||||
#include <boost/multi_index/identity.hpp>
|
||||
#include <boost/multi_index/indexed_by.hpp>
|
||||
#include <boost/multi_index/member.hpp>
|
||||
#include <boost/multi_index/ordered_index.hpp>
|
||||
#include <boost/multi_index/tag.hpp>
|
||||
#include <boost/multi_index_container.hpp>
|
||||
#include <boost/operators.hpp>
|
||||
|
||||
using boost::multi_index::hashed_unique;
|
||||
using boost::multi_index::identity;
|
||||
@@ -44,12 +55,12 @@ using boost::multi_index::multi_index_container;
|
||||
using boost::multi_index::ordered_unique;
|
||||
using boost::multi_index::tag;
|
||||
|
||||
std::size_t hash_value(const QModelIndex& index) { return qHash(index); }
|
||||
std::size_t hash_value(const QModelIndex &index) { return qHash(index); }
|
||||
|
||||
namespace {
|
||||
|
||||
struct Mapping {
|
||||
explicit Mapping(const QModelIndex& _source_index) : source_index(_source_index) {}
|
||||
explicit Mapping(const QModelIndex &_source_index) : source_index(_source_index) {}
|
||||
|
||||
QModelIndex source_index;
|
||||
};
|
||||
@@ -73,7 +84,7 @@ class MergedProxyModelPrivate {
|
||||
MappingContainer mappings_;
|
||||
};
|
||||
|
||||
MergedProxyModel::MergedProxyModel(QObject* parent)
|
||||
MergedProxyModel::MergedProxyModel(QObject *parent)
|
||||
: QAbstractProxyModel(parent),
|
||||
resetting_model_(nullptr),
|
||||
p_(new MergedProxyModelPrivate) {}
|
||||
@@ -81,12 +92,12 @@ MergedProxyModel::MergedProxyModel(QObject* parent)
|
||||
MergedProxyModel::~MergedProxyModel() { DeleteAllMappings(); }
|
||||
|
||||
void MergedProxyModel::DeleteAllMappings() {
|
||||
const auto& begin = p_->mappings_.get<tag_by_pointer>().begin();
|
||||
const auto& end = p_->mappings_.get<tag_by_pointer>().end();
|
||||
const auto &begin = p_->mappings_.get<tag_by_pointer>().begin();
|
||||
const auto &end = p_->mappings_.get<tag_by_pointer>().end();
|
||||
qDeleteAll(begin, end);
|
||||
}
|
||||
|
||||
void MergedProxyModel::AddSubModel(const QModelIndex& source_parent, QAbstractItemModel* submodel) {
|
||||
void MergedProxyModel::AddSubModel(const QModelIndex &source_parent, QAbstractItemModel *submodel) {
|
||||
|
||||
connect(submodel, SIGNAL(modelReset()), this, SLOT(SubModelReset()));
|
||||
connect(submodel, SIGNAL(rowsAboutToBeInserted(QModelIndex, int, int)), this, SLOT(RowsAboutToBeInserted(QModelIndex, int, int)));
|
||||
@@ -105,13 +116,13 @@ void MergedProxyModel::AddSubModel(const QModelIndex& source_parent, QAbstractIt
|
||||
if (rows) endInsertRows();
|
||||
}
|
||||
|
||||
void MergedProxyModel::RemoveSubModel(const QModelIndex& source_parent) {
|
||||
void MergedProxyModel::RemoveSubModel(const QModelIndex &source_parent) {
|
||||
|
||||
// Find the submodel that the parent corresponded to
|
||||
QAbstractItemModel* submodel = merge_points_.key(source_parent);
|
||||
QAbstractItemModel *submodel = merge_points_.key(source_parent);
|
||||
merge_points_.remove(submodel);
|
||||
|
||||
// The submodel might have been deleted already so we must be careful not
|
||||
// to dereference it.
|
||||
// The submodel might have been deleted already so we must be careful not to dereference it.
|
||||
|
||||
// Remove all the children of the item that got deleted
|
||||
QModelIndex proxy_parent = mapFromSource(source_parent);
|
||||
@@ -129,13 +140,15 @@ void MergedProxyModel::RemoveSubModel(const QModelIndex& source_parent) {
|
||||
if ((*it)->source_index.model() == submodel) {
|
||||
delete *it;
|
||||
it = p_->mappings_.get<tag_by_pointer>().erase(it);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MergedProxyModel::setSourceModel(QAbstractItemModel* source_model) {
|
||||
void MergedProxyModel::setSourceModel(QAbstractItemModel *source_model) {
|
||||
|
||||
if (sourceModel()) {
|
||||
disconnect(sourceModel(), SIGNAL(modelReset()), this, SLOT(SourceModelReset()));
|
||||
@@ -179,11 +192,10 @@ void MergedProxyModel::SourceModelReset() {
|
||||
|
||||
void MergedProxyModel::SubModelReset() {
|
||||
|
||||
QAbstractItemModel* submodel = static_cast<QAbstractItemModel*>(sender());
|
||||
QAbstractItemModel *submodel = static_cast<QAbstractItemModel*>(sender());
|
||||
|
||||
// TODO: When we require Qt 4.6, use beginResetModel() and endResetModel()
|
||||
// in CollectionModel and catch those here - that will let us do away with this
|
||||
// std::numeric_limits<int>::max() hack.
|
||||
// TODO: When we require Qt 4.6, use beginResetModel() and endResetModel() in CollectionModel and catch those here
|
||||
// that will let us do away with this std::numeric_limits<int>::max() hack.
|
||||
|
||||
// Remove all the children of the item that got deleted
|
||||
QModelIndex source_parent = merge_points_.value(submodel);
|
||||
@@ -202,7 +214,8 @@ void MergedProxyModel::SubModelReset() {
|
||||
if ((*it)->source_index.model() == submodel) {
|
||||
delete *it;
|
||||
it = p_->mappings_.get<tag_by_pointer>().erase(it);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
@@ -218,7 +231,7 @@ void MergedProxyModel::SubModelReset() {
|
||||
|
||||
}
|
||||
|
||||
QModelIndex MergedProxyModel::GetActualSourceParent(const QModelIndex& source_parent, QAbstractItemModel* model) const {
|
||||
QModelIndex MergedProxyModel::GetActualSourceParent(const QModelIndex &source_parent, QAbstractItemModel *model) const {
|
||||
|
||||
if (!source_parent.isValid() && model != sourceModel())
|
||||
return merge_points_.value(model);
|
||||
@@ -226,7 +239,7 @@ QModelIndex MergedProxyModel::GetActualSourceParent(const QModelIndex& source_pa
|
||||
|
||||
}
|
||||
|
||||
void MergedProxyModel::RowsAboutToBeInserted(const QModelIndex& source_parent, int start, int end) {
|
||||
void MergedProxyModel::RowsAboutToBeInserted(const QModelIndex &source_parent, int start, int end) {
|
||||
beginInsertRows(mapFromSource(GetActualSourceParent(source_parent, static_cast<QAbstractItemModel*>(sender()))), start, end);
|
||||
}
|
||||
|
||||
@@ -234,7 +247,7 @@ void MergedProxyModel::RowsInserted(const QModelIndex&, int, int) {
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void MergedProxyModel::RowsAboutToBeRemoved(const QModelIndex& source_parent, int start, int end) {
|
||||
void MergedProxyModel::RowsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end) {
|
||||
beginRemoveRows(mapFromSource(GetActualSourceParent(source_parent, static_cast<QAbstractItemModel*>(sender()))), start, end);
|
||||
}
|
||||
|
||||
@@ -242,13 +255,12 @@ void MergedProxyModel::RowsRemoved(const QModelIndex&, int, int) {
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
QModelIndex MergedProxyModel::mapToSource(const QModelIndex& proxy_index) const {
|
||||
QModelIndex MergedProxyModel::mapToSource(const QModelIndex &proxy_index) const {
|
||||
|
||||
if (!proxy_index.isValid()) return QModelIndex();
|
||||
|
||||
Mapping* mapping = static_cast<Mapping*>(proxy_index.internalPointer());
|
||||
if (p_->mappings_.get<tag_by_pointer>().find(mapping) ==
|
||||
p_->mappings_.get<tag_by_pointer>().end())
|
||||
Mapping *mapping = static_cast<Mapping*>(proxy_index.internalPointer());
|
||||
if (p_->mappings_.get<tag_by_pointer>().find(mapping) == p_->mappings_.get<tag_by_pointer>().end())
|
||||
return QModelIndex();
|
||||
if (mapping->source_index.model() == resetting_model_) return QModelIndex();
|
||||
|
||||
@@ -256,17 +268,18 @@ QModelIndex MergedProxyModel::mapToSource(const QModelIndex& proxy_index) const
|
||||
|
||||
}
|
||||
|
||||
QModelIndex MergedProxyModel::mapFromSource(const QModelIndex& source_index) const {
|
||||
QModelIndex MergedProxyModel::mapFromSource(const QModelIndex &source_index) const {
|
||||
|
||||
if (!source_index.isValid()) return QModelIndex();
|
||||
if (source_index.model() == resetting_model_) return QModelIndex();
|
||||
|
||||
// Add a mapping if we don't have one already
|
||||
const auto& it = p_->mappings_.get<tag_by_source>().find(source_index);
|
||||
Mapping* mapping;
|
||||
const auto &it = p_->mappings_.get<tag_by_source>().find(source_index);
|
||||
Mapping *mapping;
|
||||
if (it != p_->mappings_.get<tag_by_source>().end()) {
|
||||
mapping = *it;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
mapping = new Mapping(source_index);
|
||||
const_cast<MergedProxyModel*>(this)->p_->mappings_.insert(mapping);
|
||||
}
|
||||
@@ -284,7 +297,7 @@ QModelIndex MergedProxyModel::index(int row, int column, const QModelIndex &pare
|
||||
}
|
||||
else {
|
||||
QModelIndex source_parent = mapToSource(parent);
|
||||
const QAbstractItemModel* child_model = merge_points_.key(source_parent);
|
||||
const QAbstractItemModel *child_model = merge_points_.key(source_parent);
|
||||
|
||||
if (child_model)
|
||||
source_index = child_model->index(row, column, QModelIndex());
|
||||
@@ -296,7 +309,7 @@ QModelIndex MergedProxyModel::index(int row, int column, const QModelIndex &pare
|
||||
|
||||
}
|
||||
|
||||
QModelIndex MergedProxyModel::parent(const QModelIndex& child) const {
|
||||
QModelIndex MergedProxyModel::parent(const QModelIndex &child) const {
|
||||
|
||||
QModelIndex source_child = mapToSource(child);
|
||||
if (source_child.model() == sourceModel())
|
||||
@@ -310,17 +323,16 @@ QModelIndex MergedProxyModel::parent(const QModelIndex& child) const {
|
||||
|
||||
}
|
||||
|
||||
int MergedProxyModel::rowCount(const QModelIndex& parent) const {
|
||||
int MergedProxyModel::rowCount(const QModelIndex &parent) const {
|
||||
|
||||
if (!parent.isValid()) return sourceModel()->rowCount(QModelIndex());
|
||||
|
||||
QModelIndex source_parent = mapToSource(parent);
|
||||
if (!IsKnownModel(source_parent.model())) return 0;
|
||||
|
||||
const QAbstractItemModel* child_model = merge_points_.key(source_parent);
|
||||
const QAbstractItemModel *child_model = merge_points_.key(source_parent);
|
||||
if (child_model) {
|
||||
// Query the source model but disregard what it says, so it gets a chance
|
||||
// to lazy load
|
||||
// Query the source model but disregard what it says, so it gets a chance to lazy load
|
||||
source_parent.model()->rowCount(source_parent);
|
||||
|
||||
return child_model->rowCount(QModelIndex());
|
||||
@@ -330,34 +342,34 @@ int MergedProxyModel::rowCount(const QModelIndex& parent) const {
|
||||
|
||||
}
|
||||
|
||||
int MergedProxyModel::columnCount(const QModelIndex& parent) const {
|
||||
int MergedProxyModel::columnCount(const QModelIndex &parent) const {
|
||||
|
||||
if (!parent.isValid()) return sourceModel()->columnCount(QModelIndex());
|
||||
|
||||
QModelIndex source_parent = mapToSource(parent);
|
||||
if (!IsKnownModel(source_parent.model())) return 0;
|
||||
|
||||
const QAbstractItemModel* child_model = merge_points_.key(source_parent);
|
||||
const QAbstractItemModel *child_model = merge_points_.key(source_parent);
|
||||
if (child_model) return child_model->columnCount(QModelIndex());
|
||||
return source_parent.model()->columnCount(source_parent);
|
||||
|
||||
}
|
||||
|
||||
bool MergedProxyModel::hasChildren(const QModelIndex& parent) const {
|
||||
bool MergedProxyModel::hasChildren(const QModelIndex &parent) const {
|
||||
|
||||
if (!parent.isValid()) return sourceModel()->hasChildren(QModelIndex());
|
||||
|
||||
QModelIndex source_parent = mapToSource(parent);
|
||||
if (!IsKnownModel(source_parent.model())) return false;
|
||||
|
||||
const QAbstractItemModel* child_model = merge_points_.key(source_parent);
|
||||
const QAbstractItemModel *child_model = merge_points_.key(source_parent);
|
||||
|
||||
if (child_model) return child_model->hasChildren(QModelIndex()) || source_parent.model()->hasChildren(source_parent);
|
||||
return source_parent.model()->hasChildren(source_parent);
|
||||
|
||||
}
|
||||
|
||||
QVariant MergedProxyModel::data(const QModelIndex& proxyIndex, int role) const {
|
||||
QVariant MergedProxyModel::data(const QModelIndex &proxyIndex, int role) const {
|
||||
|
||||
QModelIndex source_index = mapToSource(proxyIndex);
|
||||
if (!IsKnownModel(source_index.model())) return QVariant();
|
||||
@@ -366,7 +378,7 @@ QVariant MergedProxyModel::data(const QModelIndex& proxyIndex, int role) const {
|
||||
|
||||
}
|
||||
|
||||
QMap<int, QVariant> MergedProxyModel::itemData(const QModelIndex& proxy_index) const {
|
||||
QMap<int, QVariant> MergedProxyModel::itemData(const QModelIndex &proxy_index) const {
|
||||
|
||||
QModelIndex source_index = mapToSource(proxy_index);
|
||||
|
||||
@@ -375,7 +387,7 @@ QMap<int, QVariant> MergedProxyModel::itemData(const QModelIndex& proxy_index) c
|
||||
|
||||
}
|
||||
|
||||
Qt::ItemFlags MergedProxyModel::flags(const QModelIndex& index) const {
|
||||
Qt::ItemFlags MergedProxyModel::flags(const QModelIndex &index) const {
|
||||
|
||||
QModelIndex source_index = mapToSource(index);
|
||||
|
||||
@@ -384,7 +396,7 @@ Qt::ItemFlags MergedProxyModel::flags(const QModelIndex& index) const {
|
||||
|
||||
}
|
||||
|
||||
bool MergedProxyModel::setData(const QModelIndex& index, const QVariant& value, int role) {
|
||||
bool MergedProxyModel::setData(const QModelIndex &index, const QVariant &value, int role) {
|
||||
|
||||
QModelIndex source_index = mapToSource(index);
|
||||
|
||||
@@ -399,7 +411,7 @@ QStringList MergedProxyModel::mimeTypes() const {
|
||||
QStringList ret;
|
||||
ret << sourceModel()->mimeTypes();
|
||||
|
||||
for (const QAbstractItemModel* model : merge_points_.keys()) {
|
||||
for (const QAbstractItemModel *model : merge_points_.keys()) {
|
||||
ret << model->mimeTypes();
|
||||
}
|
||||
|
||||
@@ -407,12 +419,12 @@ QStringList MergedProxyModel::mimeTypes() const {
|
||||
|
||||
}
|
||||
|
||||
QMimeData* MergedProxyModel::mimeData(const QModelIndexList& indexes) const {
|
||||
QMimeData *MergedProxyModel::mimeData(const QModelIndexList &indexes) const {
|
||||
|
||||
if (indexes.isEmpty()) return 0;
|
||||
|
||||
// Only ask the first index's model
|
||||
const QAbstractItemModel* model = mapToSource(indexes[0]).model();
|
||||
const QAbstractItemModel *model = mapToSource(indexes[0]).model();
|
||||
if (!model) {
|
||||
return 0;
|
||||
}
|
||||
@@ -420,7 +432,7 @@ QMimeData* MergedProxyModel::mimeData(const QModelIndexList& indexes) const {
|
||||
// Only ask about the indexes that are actually in that model
|
||||
QModelIndexList indexes_in_model;
|
||||
|
||||
for (const QModelIndex& proxy_index : indexes) {
|
||||
for (const QModelIndex &proxy_index : indexes) {
|
||||
QModelIndex source_index = mapToSource(proxy_index);
|
||||
if (source_index.model() != model) continue;
|
||||
indexes_in_model << source_index;
|
||||
@@ -430,7 +442,7 @@ QMimeData* MergedProxyModel::mimeData(const QModelIndexList& indexes) const {
|
||||
|
||||
}
|
||||
|
||||
bool MergedProxyModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) {
|
||||
bool MergedProxyModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) {
|
||||
|
||||
if (!parent.isValid()) {
|
||||
return false;
|
||||
@@ -440,7 +452,7 @@ bool MergedProxyModel::dropMimeData(const QMimeData* data, Qt::DropAction action
|
||||
|
||||
}
|
||||
|
||||
QModelIndex MergedProxyModel::FindSourceParent(const QModelIndex& proxy_index) const {
|
||||
QModelIndex MergedProxyModel::FindSourceParent(const QModelIndex &proxy_index) const {
|
||||
|
||||
if (!proxy_index.isValid()) return QModelIndex();
|
||||
|
||||
@@ -450,7 +462,7 @@ QModelIndex MergedProxyModel::FindSourceParent(const QModelIndex& proxy_index) c
|
||||
|
||||
}
|
||||
|
||||
bool MergedProxyModel::canFetchMore(const QModelIndex& parent) const {
|
||||
bool MergedProxyModel::canFetchMore(const QModelIndex &parent) const {
|
||||
|
||||
QModelIndex source_index = mapToSource(parent);
|
||||
|
||||
@@ -460,7 +472,7 @@ bool MergedProxyModel::canFetchMore(const QModelIndex& parent) const {
|
||||
|
||||
}
|
||||
|
||||
void MergedProxyModel::fetchMore(const QModelIndex& parent) {
|
||||
void MergedProxyModel::fetchMore(const QModelIndex &parent) {
|
||||
|
||||
QModelIndex source_index = mapToSource(parent);
|
||||
|
||||
@@ -471,27 +483,26 @@ void MergedProxyModel::fetchMore(const QModelIndex& parent) {
|
||||
|
||||
}
|
||||
|
||||
QAbstractItemModel* MergedProxyModel::GetModel(const QModelIndex& source_index) const {
|
||||
QAbstractItemModel *MergedProxyModel::GetModel(const QModelIndex &source_index) const {
|
||||
|
||||
// This is essentially const_cast<QAbstractItemModel*>(source_index.model()),
|
||||
// but without the const_cast
|
||||
const QAbstractItemModel* const_model = source_index.model();
|
||||
// This is essentially const_cast<QAbstractItemModel*>(source_index.model()), but without the const_cast
|
||||
const QAbstractItemModel *const_model = source_index.model();
|
||||
if (const_model == sourceModel()) return sourceModel();
|
||||
for (QAbstractItemModel* submodel : merge_points_.keys()) {
|
||||
for (QAbstractItemModel *submodel : merge_points_.keys()) {
|
||||
if (submodel == const_model) return submodel;
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
|
||||
void MergedProxyModel::DataChanged(const QModelIndex& top_left, const QModelIndex& bottom_right) {
|
||||
void MergedProxyModel::DataChanged(const QModelIndex &top_left, const QModelIndex &bottom_right) {
|
||||
emit dataChanged(mapFromSource(top_left), mapFromSource(bottom_right));
|
||||
}
|
||||
|
||||
void MergedProxyModel::LayoutAboutToBeChanged() {
|
||||
|
||||
old_merge_points_.clear();
|
||||
for (QAbstractItemModel* key : merge_points_.keys()) {
|
||||
for (QAbstractItemModel *key : merge_points_.keys()) {
|
||||
old_merge_points_[key] = merge_points_.value(key);
|
||||
}
|
||||
|
||||
@@ -499,7 +510,7 @@ void MergedProxyModel::LayoutAboutToBeChanged() {
|
||||
|
||||
void MergedProxyModel::LayoutChanged() {
|
||||
|
||||
for (QAbstractItemModel* key : merge_points_.keys()) {
|
||||
for (QAbstractItemModel *key : merge_points_.keys()) {
|
||||
if (!old_merge_points_.contains(key)) continue;
|
||||
|
||||
const int old_row = old_merge_points_[key].row();
|
||||
@@ -514,29 +525,28 @@ void MergedProxyModel::LayoutChanged() {
|
||||
|
||||
}
|
||||
|
||||
bool MergedProxyModel::IsKnownModel(const QAbstractItemModel* model) const {
|
||||
bool MergedProxyModel::IsKnownModel(const QAbstractItemModel *model) const {
|
||||
|
||||
if (model == this || model == sourceModel() ||
|
||||
merge_points_.contains(const_cast<QAbstractItemModel*>(model)))
|
||||
if (model == this || model == sourceModel() || merge_points_.contains(const_cast<QAbstractItemModel*>(model)))
|
||||
return true;
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
QModelIndexList MergedProxyModel::mapFromSource(const QModelIndexList& source_indexes) const {
|
||||
QModelIndexList MergedProxyModel::mapFromSource(const QModelIndexList &source_indexes) const {
|
||||
|
||||
QModelIndexList ret;
|
||||
for (const QModelIndex& index : source_indexes) {
|
||||
for (const QModelIndex &index : source_indexes) {
|
||||
ret << mapFromSource(index);
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
QModelIndexList MergedProxyModel::mapToSource(const QModelIndexList& proxy_indexes) const {
|
||||
QModelIndexList MergedProxyModel::mapToSource(const QModelIndexList &proxy_indexes) const {
|
||||
|
||||
QModelIndexList ret;
|
||||
for (const QModelIndex& index : proxy_indexes) {
|
||||
for (const QModelIndex &index : proxy_indexes) {
|
||||
ret << mapToSource(index);
|
||||
}
|
||||
return ret;
|
||||
|
||||
@@ -24,10 +24,21 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <memory>
|
||||
#include <cstddef>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QMimeData>
|
||||
#include <QModelIndex>
|
||||
#include <QAbstractItemModel>
|
||||
#include <QAbstractProxyModel>
|
||||
#include <QPersistentModelIndex>
|
||||
#include <QMap>
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
std::size_t hash_value(const QModelIndex& index);
|
||||
std::size_t hash_value(const QModelIndex &index);
|
||||
|
||||
class MergedProxyModelPrivate;
|
||||
|
||||
@@ -35,71 +46,68 @@ class MergedProxyModel : public QAbstractProxyModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MergedProxyModel(QObject* parent = nullptr);
|
||||
explicit MergedProxyModel(QObject *parent = nullptr);
|
||||
~MergedProxyModel();
|
||||
|
||||
// Make another model appear as a child of the given item in the source model.
|
||||
void AddSubModel(const QModelIndex& source_parent, QAbstractItemModel* submodel);
|
||||
void RemoveSubModel(const QModelIndex& source_parent);
|
||||
void AddSubModel(const QModelIndex &source_parent, QAbstractItemModel *submodel);
|
||||
void RemoveSubModel(const QModelIndex &source_parent);
|
||||
|
||||
// Find the item in the source model that is the parent of the model
|
||||
// containing proxy_index. If proxy_index is in the source model, then
|
||||
// this just returns mapToSource(proxy_index).
|
||||
QModelIndex FindSourceParent(const QModelIndex& proxy_index) const;
|
||||
// Find the item in the source model that is the parent of the model containing proxy_index.
|
||||
// If proxy_index is in the source model, then this just returns mapToSource(proxy_index).
|
||||
QModelIndex FindSourceParent(const QModelIndex &proxy_index) const;
|
||||
|
||||
// QAbstractItemModel
|
||||
QModelIndex index(int row, int column, const QModelIndex& parent) const;
|
||||
QModelIndex parent(const QModelIndex& child) const;
|
||||
int rowCount(const QModelIndex& parent) const;
|
||||
int columnCount(const QModelIndex& parent) const;
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent) const;
|
||||
QModelIndex parent(const QModelIndex &child) const;
|
||||
int rowCount(const QModelIndex &parent) const;
|
||||
int columnCount(const QModelIndex &parent) const;
|
||||
QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const;
|
||||
bool hasChildren(const QModelIndex& parent) const;
|
||||
QMap<int, QVariant> itemData(const QModelIndex& proxyIndex) const;
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const;
|
||||
bool setData(const QModelIndex& index, const QVariant& value, int role);
|
||||
bool hasChildren(const QModelIndex &parent) const;
|
||||
QMap<int, QVariant> itemData(const QModelIndex &proxyIndex) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||
QStringList mimeTypes() const;
|
||||
QMimeData* mimeData(const QModelIndexList& indexes) const;
|
||||
bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent);
|
||||
bool canFetchMore(const QModelIndex& parent) const;
|
||||
void fetchMore(const QModelIndex& parent);
|
||||
QMimeData *mimeData(const QModelIndexList &indexes) const;
|
||||
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
|
||||
bool canFetchMore(const QModelIndex &parent) const;
|
||||
void fetchMore(const QModelIndex &parent);
|
||||
|
||||
// QAbstractProxyModel
|
||||
// Note that these implementations of map{To,From}Source will not always
|
||||
// give you an index in sourceModel(), you might get an index in one of the
|
||||
// child models instead.
|
||||
QModelIndex mapFromSource(const QModelIndex& sourceIndex) const;
|
||||
QModelIndex mapToSource(const QModelIndex& proxyIndex) const;
|
||||
void setSourceModel(QAbstractItemModel* sourceModel);
|
||||
// Note that these implementations of map{To,From}Source will not always give you an index in sourceModel(),
|
||||
// you might get an index in one of the child models instead.
|
||||
QModelIndex mapFromSource(const QModelIndex &sourceIndex) const;
|
||||
QModelIndex mapToSource(const QModelIndex &proxyIndex) const;
|
||||
void setSourceModel(QAbstractItemModel *sourceModel);
|
||||
|
||||
// Convenience functions that call map{To,From}Source multiple times.
|
||||
QModelIndexList mapFromSource(const QModelIndexList& source_indexes) const;
|
||||
QModelIndexList mapToSource(const QModelIndexList& proxy_indexes) const;
|
||||
QModelIndexList mapFromSource(const QModelIndexList &source_indexes) const;
|
||||
QModelIndexList mapToSource(const QModelIndexList &proxy_indexes) const;
|
||||
|
||||
signals:
|
||||
void SubModelReset(const QModelIndex& root, QAbstractItemModel* model);
|
||||
void SubModelReset(const QModelIndex &root, QAbstractItemModel *model);
|
||||
|
||||
private slots:
|
||||
void SourceModelReset();
|
||||
void SubModelReset();
|
||||
|
||||
void RowsAboutToBeInserted(const QModelIndex& source_parent, int start, int end);
|
||||
void RowsInserted(const QModelIndex& source_parent, int start, int end);
|
||||
void RowsAboutToBeRemoved(const QModelIndex& source_parent, int start, int end);
|
||||
void RowsRemoved(const QModelIndex& source_parent, int start, int end);
|
||||
void DataChanged(const QModelIndex& top_left, const QModelIndex& bottom_right);
|
||||
void RowsAboutToBeInserted(const QModelIndex &source_parent, int start, int end);
|
||||
void RowsInserted(const QModelIndex &source_parent, int start, int end);
|
||||
void RowsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end);
|
||||
void RowsRemoved(const QModelIndex &source_parent, int start, int end);
|
||||
void DataChanged(const QModelIndex &top_left, const QModelIndex &bottom_right);
|
||||
|
||||
void LayoutAboutToBeChanged();
|
||||
void LayoutChanged();
|
||||
|
||||
private:
|
||||
QModelIndex GetActualSourceParent(const QModelIndex& source_parent,
|
||||
QAbstractItemModel* model) const;
|
||||
QAbstractItemModel* GetModel(const QModelIndex& source_index) const;
|
||||
QModelIndex GetActualSourceParent(const QModelIndex &source_parent, QAbstractItemModel *model) const;
|
||||
QAbstractItemModel *GetModel(const QModelIndex &source_index) const;
|
||||
void DeleteAllMappings();
|
||||
bool IsKnownModel(const QAbstractItemModel* model) const;
|
||||
bool IsKnownModel(const QAbstractItemModel *model) const;
|
||||
|
||||
QMap<QAbstractItemModel*, QPersistentModelIndex> merge_points_;
|
||||
QAbstractItemModel* resetting_model_;
|
||||
QAbstractItemModel *resetting_model_;
|
||||
|
||||
QMap<QAbstractItemModel*, QModelIndex> old_merge_points_;
|
||||
|
||||
|
||||
@@ -18,48 +18,70 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "metatypes.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkCookie>
|
||||
|
||||
#include "metatypes.h"
|
||||
|
||||
#ifdef HAVE_GSTREAMER
|
||||
# include <gst/gstbuffer.h>
|
||||
# include <gst/gstelement.h>
|
||||
#endif
|
||||
|
||||
#include <QAbstractSocket>
|
||||
#include <QMetaType>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QByteArray>
|
||||
#include <QUrl>
|
||||
#include <QImage>
|
||||
#include <QNetworkCookie>
|
||||
#include <QNetworkReply>
|
||||
#ifdef HAVE_DBUS
|
||||
# include <QDBusMetaType>
|
||||
#endif
|
||||
|
||||
#include "song.h"
|
||||
|
||||
#include "engine/engine_fwd.h"
|
||||
#include "engine/enginebase.h"
|
||||
#include "engine/enginetype.h"
|
||||
#ifdef HAVE_GSTREAMER
|
||||
# include "engine/gstengine.h"
|
||||
# include "engine/gstenginepipeline.h"
|
||||
#endif
|
||||
#include "collection/directory.h"
|
||||
#include "playlist/playlist.h"
|
||||
#include "equalizer/equalizer.h"
|
||||
#include "playlist/playlistitem.h"
|
||||
#include "playlist/playlistsequence.h"
|
||||
#include "covermanager/albumcoverfetcher.h"
|
||||
#include "equalizer/equalizer.h"
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
#include <QDBusMetaType>
|
||||
#include "core/mpris2.h"
|
||||
#include "dbus/metatypes.h"
|
||||
#endif
|
||||
|
||||
class QNetworkReply;
|
||||
#ifdef HAVE_GSTREAMER
|
||||
class GstEnginePipeline;
|
||||
# include "mpris2.h"
|
||||
# include "dbus/metatypes.h"
|
||||
#endif
|
||||
|
||||
void RegisterMetaTypes() {
|
||||
//qRegisterMetaType<CollapsibleInfoPane::Data>("CollapsibleInfoPane::Data");
|
||||
|
||||
qRegisterMetaType<const char*>("const char*");
|
||||
qRegisterMetaType<CoverSearchResult>("CoverSearchResult");
|
||||
qRegisterMetaType<CoverSearchResults>("CoverSearchResults");
|
||||
qRegisterMetaType<QList<int>>("QList<int>");
|
||||
qRegisterMetaType<QList<QUrl>>("QList<QUrl>");
|
||||
qRegisterMetaType<QAbstractSocket::SocketState>();
|
||||
qRegisterMetaType<QAbstractSocket::SocketState>("QAbstractSocket::SocketState");
|
||||
qRegisterMetaType<QNetworkCookie>("QNetworkCookie");
|
||||
qRegisterMetaType<QList<QNetworkCookie> >("QList<QNetworkCookie>");
|
||||
qRegisterMetaType<QNetworkReply*>("QNetworkReply*");
|
||||
qRegisterMetaType<QNetworkReply**>("QNetworkReply**");
|
||||
qRegisterMetaTypeStreamOperators<QMap<int, int> >("ColumnAlignmentMap");
|
||||
qRegisterMetaType<Directory>("Directory");
|
||||
qRegisterMetaType<DirectoryList>("DirectoryList");
|
||||
qRegisterMetaType<Subdirectory>("Subdirectory");
|
||||
qRegisterMetaType<SubdirectoryList>("SubdirectoryList");
|
||||
qRegisterMetaType<Song>("Song");
|
||||
qRegisterMetaType<QList<Song> >("QList<Song>");
|
||||
qRegisterMetaType<SongList>("SongList");
|
||||
qRegisterMetaType<Engine::EngineType>("EngineType");
|
||||
qRegisterMetaType<Engine::SimpleMetaBundle>("Engine::SimpleMetaBundle");
|
||||
qRegisterMetaType<Engine::State>("Engine::State");
|
||||
qRegisterMetaType<Engine::TrackChangeFlags>("Engine::TrackChangeFlags");
|
||||
qRegisterMetaType<Equalizer::Params>("Equalizer::Params");
|
||||
qRegisterMetaType<EngineBase::OutputDetails>("EngineBase::OutputDetails");
|
||||
#ifdef HAVE_GSTREAMER
|
||||
qRegisterMetaType<GstBuffer*>("GstBuffer*");
|
||||
@@ -68,36 +90,22 @@ void RegisterMetaTypes() {
|
||||
#endif
|
||||
qRegisterMetaType<PlaylistItemList>("PlaylistItemList");
|
||||
qRegisterMetaType<PlaylistItemPtr>("PlaylistItemPtr");
|
||||
qRegisterMetaType<QList<CoverSearchResult> >("QList<CoverSearchResult>");
|
||||
qRegisterMetaType<QList<int>>("QList<int>");
|
||||
qRegisterMetaType<QList<PlaylistItemPtr> >("QList<PlaylistItemPtr>");
|
||||
qRegisterMetaType<PlaylistSequence::RepeatMode>("PlaylistSequence::RepeatMode");
|
||||
qRegisterMetaType<PlaylistSequence::ShuffleMode>("PlaylistSequence::ShuffleMode");
|
||||
qRegisterMetaType<QAbstractSocket::SocketState>("QAbstractSocket::SocketState");
|
||||
qRegisterMetaType<QList<QNetworkCookie> >("QList<QNetworkCookie>");
|
||||
qRegisterMetaType<QList<Song> >("QList<Song>");
|
||||
qRegisterMetaType<QNetworkCookie>("QNetworkCookie");
|
||||
qRegisterMetaType<QNetworkReply*>("QNetworkReply*");
|
||||
qRegisterMetaType<QNetworkReply**>("QNetworkReply**");
|
||||
qRegisterMetaType<SongList>("SongList");
|
||||
qRegisterMetaType<Song>("Song");
|
||||
qRegisterMetaType<CoverSearchResult>("CoverSearchResult");
|
||||
qRegisterMetaType<QList<CoverSearchResult> >("QList<CoverSearchResult>");
|
||||
qRegisterMetaType<CoverSearchResults>("CoverSearchResults");
|
||||
qRegisterMetaType<Equalizer::Params>("Equalizer::Params");
|
||||
qRegisterMetaTypeStreamOperators<Equalizer::Params>("Equalizer::Params");
|
||||
qRegisterMetaTypeStreamOperators<QMap<int, int> >("ColumnAlignmentMap");
|
||||
qRegisterMetaType<SubdirectoryList>("SubdirectoryList");
|
||||
qRegisterMetaType<Subdirectory>("Subdirectory");
|
||||
qRegisterMetaType<QList<QUrl>>("QList<QUrl>");
|
||||
qRegisterMetaType<QAbstractSocket::SocketState>();
|
||||
|
||||
qRegisterMetaType<Engine::EngineType>("EngineType");
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
qDBusRegisterMetaType<QList<QByteArray>>();
|
||||
qDBusRegisterMetaType<QImage>();
|
||||
qDBusRegisterMetaType<TrackMetadata>();
|
||||
qDBusRegisterMetaType<TrackIds>();
|
||||
qDBusRegisterMetaType<QList<QByteArray>>();
|
||||
qDBusRegisterMetaType<MprisPlaylist>();
|
||||
qDBusRegisterMetaType<MaybePlaylist>();
|
||||
qDBusRegisterMetaType<MprisPlaylistList>();
|
||||
qDBusRegisterMetaType<MaybePlaylist>();
|
||||
qDBusRegisterMetaType<InterfacesAndProperties>();
|
||||
qDBusRegisterMetaType<ManagedObjectList>();
|
||||
#endif
|
||||
|
||||
@@ -23,7 +23,9 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QMimeData>
|
||||
#include <QString>
|
||||
|
||||
class MimeData : public QMimeData {
|
||||
Q_OBJECT
|
||||
@@ -41,13 +43,11 @@ class MimeData : public QMimeData {
|
||||
// If this is set then MainWindow will not touch any of the other flags.
|
||||
bool override_user_settings_;
|
||||
|
||||
// If this is set then the playlist will be cleared before these songs
|
||||
// are inserted.
|
||||
// If this is set then the playlist will be cleared before these songs are inserted.
|
||||
bool clear_first_;
|
||||
|
||||
// If this is set then the first item that is inserted will start playing
|
||||
// immediately. Note: this is always overridden with the user's preference
|
||||
// if the MimeData goes via MainWindow, unless you set override_user_settings_.
|
||||
// If this is set then the first item that is inserted will start playing immediately.
|
||||
// Note: this is always overridden with the user's preference if the MimeData goes via MainWindow, unless you set override_user_settings_.
|
||||
bool play_now_;
|
||||
|
||||
// If this is set then the items are added to the queue after being inserted.
|
||||
@@ -59,14 +59,12 @@ class MimeData : public QMimeData {
|
||||
// This serves as a name for the new playlist in 'open_in_new_playlist_' mode.
|
||||
QString name_for_new_playlist_;
|
||||
|
||||
// This can be set if this MimeData goes via MainWindow (ie. it is created
|
||||
// manually in a double-click). The MainWindow will set the above flags to
|
||||
// the defaults set by the user.
|
||||
// This can be set if this MimeData goes via MainWindow (ie. it is created manually in a double-click).
|
||||
// The MainWindow will set the above flags to the defaults set by the user.
|
||||
bool from_doubleclick_;
|
||||
|
||||
// Returns a pretty name for a playlist containing songs described by this MimeData
|
||||
// object. By pretty name we mean the value of 'name_for_new_playlist_' or generic
|
||||
// "Playlist" string if the 'name_for_new_playlist_' attribute is empty.
|
||||
// Returns a pretty name for a playlist containing songs described by this MimeData object.
|
||||
// By pretty name we mean the value of 'name_for_new_playlist_' or generic "Playlist" string if the 'name_for_new_playlist_' attribute is empty.
|
||||
QString get_name_for_new_playlist() {
|
||||
return name_for_new_playlist_.isEmpty() ? tr("Playlist") : name_for_new_playlist_;
|
||||
}
|
||||
|
||||
@@ -18,15 +18,16 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "mpris.h"
|
||||
#include "mpris2.h"
|
||||
|
||||
namespace mpris {
|
||||
|
||||
Mpris::Mpris(Application* app, QObject* parent) : QObject(parent), mpris2_(new mpris::Mpris2(app, this)) {
|
||||
Mpris::Mpris(Application *app, QObject *parent) : QObject(parent), mpris2_(new mpris::Mpris2(app, this)) {
|
||||
connect(mpris2_, SIGNAL(RaiseMainWindow()), SIGNAL(RaiseMainWindow()));
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
class Application;
|
||||
|
||||
|
||||
@@ -20,30 +20,48 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCoreApplication>
|
||||
#include <QObject>
|
||||
#include <QFile>
|
||||
#include <QList>
|
||||
#include <QJsonArray>
|
||||
#include <QVariant>
|
||||
#include <QVariantMap>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QUrl>
|
||||
#include <QDBusConnection>
|
||||
#include <QtConcurrentRun>
|
||||
#include <QDBusMessage>
|
||||
#include <QDBusArgument>
|
||||
#include <QDBusObjectPath>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "core/logging.h"
|
||||
|
||||
#include "mpris_common.h"
|
||||
#include "mpris2.h"
|
||||
|
||||
#include "core/application.h"
|
||||
#include "core/mainwindow.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/mpris_common.h"
|
||||
#include "core/mpris2_player.h"
|
||||
#include "core/mpris2_playlists.h"
|
||||
#include "core/mpris2_root.h"
|
||||
#include "core/mpris2_tracklist.h"
|
||||
#include "core/player.h"
|
||||
#include "core/timeconstants.h"
|
||||
#include "timeconstants.h"
|
||||
#include "song.h"
|
||||
#include "application.h"
|
||||
#include "player.h"
|
||||
#include "engine/enginebase.h"
|
||||
#include "playlist/playlist.h"
|
||||
#include "playlist/playlistitem.h"
|
||||
#include "playlist/playlistmanager.h"
|
||||
#include "playlist/playlistsequence.h"
|
||||
#include "covermanager/currentartloader.h"
|
||||
|
||||
#include <core/mpris2_player.h>
|
||||
#include <core/mpris2_playlists.h>
|
||||
#include <core/mpris2_root.h>
|
||||
#include <core/mpris2_tracklist.h>
|
||||
|
||||
QDBusArgument &operator<<(QDBusArgument &arg, const MprisPlaylist &playlist) {
|
||||
arg.beginStructure();
|
||||
arg << playlist.id << playlist.name << playlist.icon;
|
||||
@@ -75,11 +93,11 @@ const QDBusArgument &operator>> (const QDBusArgument &arg, MaybePlaylist &playli
|
||||
|
||||
namespace mpris {
|
||||
|
||||
const char* Mpris2::kMprisObjectPath = "/org/mpris/MediaPlayer2";
|
||||
const char* Mpris2::kServiceName = "org.mpris.MediaPlayer2.strawberry";
|
||||
const char* Mpris2::kFreedesktopPath = "org.freedesktop.DBus.Properties";
|
||||
const char *Mpris2::kMprisObjectPath = "/org/mpris/MediaPlayer2";
|
||||
const char *Mpris2::kServiceName = "org.mpris.MediaPlayer2.strawberry";
|
||||
const char *Mpris2::kFreedesktopPath = "org.freedesktop.DBus.Properties";
|
||||
|
||||
Mpris2::Mpris2(Application* app, QObject* parent) : QObject(parent), app_(app) {
|
||||
Mpris2::Mpris2(Application *app, QObject *parent) : QObject(parent), app_(app) {
|
||||
|
||||
new Mpris2Root(this);
|
||||
new Mpris2TrackList(this);
|
||||
@@ -184,8 +202,7 @@ QString Mpris2::DesktopEntryAbsolutePath() const {
|
||||
xdg_data_dirs.append("/usr/share/");
|
||||
|
||||
for (const QString &directory : xdg_data_dirs) {
|
||||
QString path = QString("%1/applications/%2.desktop").arg(
|
||||
directory, QApplication::applicationName().toLower());
|
||||
QString path = QString("%1/applications/%2.desktop").arg(directory, QApplication::applicationName().toLower());
|
||||
if (QFile::exists(path)) return path;
|
||||
}
|
||||
return QString();
|
||||
@@ -276,9 +293,11 @@ void Mpris2::SetLoopStatus(const QString &value) {
|
||||
|
||||
if (value == "None") {
|
||||
mode = PlaylistSequence::Repeat_Off;
|
||||
} else if (value == "Track") {
|
||||
}
|
||||
else if (value == "Track") {
|
||||
mode = PlaylistSequence::Repeat_Track;
|
||||
} else if (value == "Playlist") {
|
||||
}
|
||||
else if (value == "Playlist") {
|
||||
mode = PlaylistSequence::Repeat_Playlist;
|
||||
}
|
||||
|
||||
@@ -312,8 +331,7 @@ QString Mpris2::current_track_id() const {
|
||||
return QString("/org/strawberry/strawberrymusicplayer/Track/%1").arg(QString::number(app_->playlist_manager()->active()->current_row()));
|
||||
}
|
||||
|
||||
// We send Metadata change notification as soon as the process of
|
||||
// changing song starts...
|
||||
// We send Metadata change notification as soon as the process of changing song starts...
|
||||
void Mpris2::CurrentSongChanged(const Song &song) {
|
||||
|
||||
ArtLoaded(song, "");
|
||||
@@ -367,8 +385,7 @@ bool Mpris2::CanPlay() const {
|
||||
return app_->playlist_manager()->active() && app_->playlist_manager()->active()->rowCount() != 0 && !(app_->player()->GetState() == Engine::Playing);
|
||||
}
|
||||
|
||||
// This one's a bit different than MPRIS 1 - we want this to be true even when
|
||||
// the song is already paused or stopped.
|
||||
// This one's a bit different than MPRIS 1 - we want this to be true even when the song is already paused or stopped.
|
||||
bool Mpris2::CanPause() const {
|
||||
return (app_->player()->GetCurrentItem() && app_->player()->GetState() == Engine::Playing && !(app_->player()->GetCurrentItem()->options() & PlaylistItem::PauseDisabled)) || PlaybackStatus() == "Paused" || PlaybackStatus() == "Stopped";
|
||||
}
|
||||
@@ -474,7 +491,7 @@ QDBusObjectPath MakePlaylistPath(int id) {
|
||||
MaybePlaylist Mpris2::ActivePlaylist() const {
|
||||
|
||||
MaybePlaylist maybe_playlist;
|
||||
Playlist* current_playlist = app_->playlist_manager()->current();
|
||||
Playlist *current_playlist = app_->playlist_manager()->current();
|
||||
maybe_playlist.valid = current_playlist;
|
||||
if (!current_playlist) {
|
||||
return maybe_playlist;
|
||||
@@ -511,7 +528,7 @@ void Mpris2::ActivatePlaylist(const QDBusObjectPath &playlist_id) {
|
||||
MprisPlaylistList Mpris2::GetPlaylists(quint32 index, quint32 max_count, const QString &order, bool reverse_order) {
|
||||
|
||||
MprisPlaylistList ret;
|
||||
for (Playlist* p : app_->playlist_manager()->GetAllPlaylists()) {
|
||||
for (Playlist *p : app_->playlist_manager()->GetAllPlaylists()) {
|
||||
MprisPlaylist mpris_playlist;
|
||||
mpris_playlist.id = MakePlaylistPath(p->id());
|
||||
mpris_playlist.name = app_->playlist_manager()->GetPlaylistName(p->id());
|
||||
@@ -526,7 +543,7 @@ MprisPlaylistList Mpris2::GetPlaylists(quint32 index, quint32 max_count, const Q
|
||||
|
||||
}
|
||||
|
||||
void Mpris2::PlaylistChanged(Playlist* playlist) {
|
||||
void Mpris2::PlaylistChanged(Playlist *playlist) {
|
||||
|
||||
MprisPlaylist mpris_playlist;
|
||||
mpris_playlist.id = MakePlaylistPath(playlist->id());
|
||||
@@ -535,9 +552,8 @@ void Mpris2::PlaylistChanged(Playlist* playlist) {
|
||||
|
||||
}
|
||||
|
||||
void Mpris2::PlaylistCollectionChanged(Playlist* playlist) {
|
||||
void Mpris2::PlaylistCollectionChanged(Playlist *playlist) {
|
||||
EmitNotification("PlaylistCount", "", "org.mpris.MediaPlayer2.Playlists");
|
||||
}
|
||||
|
||||
} // namespace mpris
|
||||
|
||||
|
||||
@@ -23,14 +23,28 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "playlist/playlistitem.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QMetaObject>
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QSet>
|
||||
#include <QMetaType>
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QImage>
|
||||
#include <QVector>
|
||||
#include <QtDBus>
|
||||
#include <QDBusArgument>
|
||||
#include <qdbusextratypes.h>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "engine/engine_fwd.h"
|
||||
|
||||
class Application;
|
||||
class MainWindow;
|
||||
class Song;
|
||||
class Playlist;
|
||||
|
||||
typedef QList<QVariantMap> TrackMetadata;
|
||||
|
||||
@@ -23,10 +23,11 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
#include <QVariantMap>
|
||||
#include <QDateTime>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
namespace mpris {
|
||||
|
||||
|
||||
@@ -20,12 +20,16 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "multisortfilterproxy.h"
|
||||
#include "core/logging.h"
|
||||
|
||||
#include <QDate>
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QModelIndex>
|
||||
#include <QMetaType>
|
||||
#include <QDateTime>
|
||||
#include <QTime>
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
|
||||
#include "multisortfilterproxy.h"
|
||||
|
||||
MultiSortFilterProxy::MultiSortFilterProxy(QObject *parent)
|
||||
: QSortFilterProxyModel(parent) {}
|
||||
@@ -62,8 +66,7 @@ static inline int DoCompare(T left, T right) {
|
||||
|
||||
int MultiSortFilterProxy::Compare(const QVariant &left, const QVariant &right) const {
|
||||
|
||||
// Copied from the QSortFilterProxyModel::lessThan implementation, but returns
|
||||
// -1, 0 or 1 instead of true or false.
|
||||
// Copied from the QSortFilterProxyModel::lessThan implementation, but returns -1, 0 or 1 instead of true or false.
|
||||
switch (left.userType()) {
|
||||
case QVariant::Invalid: return (right.type() != QVariant::Invalid) ? -1 : 0;
|
||||
case QVariant::Int: return DoCompare(left.toInt(), right.toInt());
|
||||
|
||||
@@ -23,7 +23,14 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QModelIndex>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QList>
|
||||
#include <QVariant>
|
||||
#include <QPair>
|
||||
|
||||
class MultiSortFilterProxy : public QSortFilterProxyModel {
|
||||
public:
|
||||
|
||||
@@ -18,11 +18,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "musicstorage.h"
|
||||
|
||||
MusicStorage::MusicStorage()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -23,12 +23,15 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "song.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
|
||||
#include "song.h"
|
||||
|
||||
class MusicStorage {
|
||||
public:
|
||||
|
||||
@@ -20,17 +20,23 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "network.h"
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QCoreApplication>
|
||||
#include <QObject>
|
||||
#include <QStandardPaths>
|
||||
#include <QDir>
|
||||
#include <QMutex>
|
||||
#include <QIODevice>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkDiskCache>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkDiskCache>
|
||||
#include <QNetworkCacheMetaData>
|
||||
#include <QAbstractNetworkCache>
|
||||
|
||||
#include "core/closure.h"
|
||||
#include "core/logging.h"
|
||||
#include "network.h"
|
||||
|
||||
QMutex ThreadSafeNetworkDiskCache::sMutex;
|
||||
QNetworkDiskCache *ThreadSafeNetworkDiskCache::sCache = nullptr;
|
||||
|
||||
@@ -23,12 +23,26 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QAbstractNetworkCache>
|
||||
#include <QMutex>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <stdbool.h>
|
||||
|
||||
class QNetworkDiskCache;
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
#include <QIODevice>
|
||||
#include <QMap>
|
||||
#include <QByteArray>
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkDiskCache>
|
||||
#include <QNetworkCacheMetaData>
|
||||
#include <QAbstractNetworkCache>
|
||||
#include <QtEvents>
|
||||
|
||||
class QTimerEvent;
|
||||
|
||||
class ThreadSafeNetworkDiskCache : public QAbstractNetworkCache {
|
||||
public:
|
||||
|
||||
@@ -20,16 +20,20 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "networkproxyfactory.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <QMutexLocker>
|
||||
#include <QSettings>
|
||||
#include <QtGlobal>
|
||||
#include <QMutex>
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QUrl>
|
||||
#include <QNetworkProxy>
|
||||
#include <QtDebug>
|
||||
#include <QSettings>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "networkproxyfactory.h"
|
||||
|
||||
NetworkProxyFactory *NetworkProxyFactory::sInstance = nullptr;
|
||||
const char *NetworkProxyFactory::kSettingsGroup = "NetworkProxy";
|
||||
@@ -40,8 +44,7 @@ NetworkProxyFactory::NetworkProxyFactory()
|
||||
port_(8080),
|
||||
use_authentication_(false) {
|
||||
#ifdef Q_OS_LINUX
|
||||
// Linux uses environment variables to pass proxy configuration information,
|
||||
// which systemProxyForQuery doesn't support for some reason.
|
||||
// Linux uses environment variables to pass proxy configuration information, which systemProxyForQuery doesn't support for some reason.
|
||||
|
||||
QStringList urls;
|
||||
urls << QString::fromLocal8Bit(getenv("HTTP_PROXY"));
|
||||
|
||||
@@ -23,9 +23,15 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QMutex>
|
||||
#include <QNetworkProxyFactory>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include <QNetworkProxy>
|
||||
#include <QNetworkProxyFactory>
|
||||
|
||||
class NetworkProxyFactory : public QNetworkProxyFactory {
|
||||
public:
|
||||
|
||||
@@ -18,23 +18,26 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "organise.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <QDir>
|
||||
#include <QtGlobal>
|
||||
#include <QThread>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QTimer>
|
||||
#include <QThread>
|
||||
#include <QString>
|
||||
#include <QStringBuilder>
|
||||
#include <QUrl>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "musicstorage.h"
|
||||
#include "taskmanager.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/tagreaderclient.h"
|
||||
#include "core/utilities.h"
|
||||
#include "utilities.h"
|
||||
#include "taskmanager.h"
|
||||
#include "musicstorage.h"
|
||||
#include "organise.h"
|
||||
#include "transcoder/transcoder.h"
|
||||
|
||||
class OrganiseFormat;
|
||||
|
||||
using std::placeholders::_1;
|
||||
|
||||
@@ -112,8 +115,7 @@ void Organise::ProcessSomeFiles() {
|
||||
|
||||
emit Finished(files_with_errors_);
|
||||
|
||||
// Move back to the original thread so deleteLater() can get called in
|
||||
// the main thread's event loop
|
||||
// Move back to the original thread so deleteLater() can get called in the main thread's event loop
|
||||
moveToThread(original_thread_);
|
||||
deleteLater();
|
||||
|
||||
@@ -165,9 +167,8 @@ void Organise::ProcessSomeFiles() {
|
||||
|
||||
qLog(Debug) << "Transcoding to" << task.transcoded_filename_;
|
||||
|
||||
// Start the transcoding - this will happen in the background and
|
||||
// FileTranscoded() will get called when it's done. At that point the
|
||||
// task will get re-added to the pending queue with the new filename.
|
||||
// Start the transcoding - this will happen in the background and FileTranscoded() will get called when it's done.
|
||||
// At that point the task will get re-added to the pending queue with the new filename.
|
||||
transcoder_->AddJob(task.song_info_.song_.url().toLocalFile(), preset, task.transcoded_filename_);
|
||||
transcoder_->Start();
|
||||
continue;
|
||||
@@ -223,9 +224,7 @@ Song::FileType Organise::CheckTranscode(Song::FileType original_type) const {
|
||||
|
||||
if (format != Song::Type_Unknown) return format;
|
||||
|
||||
// The user hasn't visited the device properties page yet to set a
|
||||
// preferred format for the device, so we have to pick the best
|
||||
// available one.
|
||||
// The user hasn't visited the device properties page yet to set a preferred format for the device, so we have to pick the best available one.
|
||||
return Transcoder::PickBestFormat(supported_filetypes_);
|
||||
}
|
||||
return Song::Type_Unknown;
|
||||
@@ -251,9 +250,8 @@ void Organise::UpdateProgress() {
|
||||
tasks_transcoding_[filename].transcode_progress_ = transcode_progress[filename];
|
||||
}
|
||||
|
||||
// Count the progress of all tasks that are in the queue. Files that need
|
||||
// transcoding total 50 for the transcode and 50 for the copy, files that
|
||||
// only need to be copied total 100.
|
||||
// Count the progress of all tasks that are in the queue.
|
||||
// Files that need transcoding total 50 for the transcode and 50 for the copy, files that only need to be copied total 100.
|
||||
int progress = tasks_complete_ * 100;
|
||||
|
||||
for (const Task &task : tasks_pending_) {
|
||||
|
||||
@@ -24,16 +24,27 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <memory>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QBasicTimer>
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include <QTemporaryFile>
|
||||
#include <QBasicTimer>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QSet>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QVector>
|
||||
|
||||
#include "core/song.h"
|
||||
#include "organiseformat.h"
|
||||
#include "transcoder/transcoder.h"
|
||||
|
||||
class QTimerEvent;
|
||||
|
||||
class MusicStorage;
|
||||
class TaskManager;
|
||||
class Transcoder;
|
||||
|
||||
class Organise : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
@@ -20,17 +20,30 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "organiseformat.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QApplication>
|
||||
#include <QFileInfo>
|
||||
#include <QPalette>
|
||||
#include <QList>
|
||||
#include <QChar>
|
||||
#include <QString>
|
||||
#include <QStringBuilder>
|
||||
#include <QStringList>
|
||||
#include <QRegExp>
|
||||
#include <QUrl>
|
||||
#include <QColor>
|
||||
#include <QPalette>
|
||||
#include <QValidator>
|
||||
#include <QTextEdit>
|
||||
#include <QTextFormat>
|
||||
|
||||
#include "core/arraysize.h"
|
||||
#include "core/timeconstants.h"
|
||||
#include "core/utilities.h"
|
||||
#include "core/logging.h"
|
||||
|
||||
#include "timeconstants.h"
|
||||
#include "utilities.h"
|
||||
#include "song.h"
|
||||
#include "organiseformat.h"
|
||||
|
||||
class QTextDocument;
|
||||
|
||||
const char *OrganiseFormat::kTagPattern = "\\%([a-zA-Z]*)";
|
||||
const char *OrganiseFormat::kBlockPattern = "\\{([^{}]+)\\}";
|
||||
@@ -95,11 +108,8 @@ QString OrganiseFormat::GetFilenameForSong(const Song &song) const {
|
||||
QString filename = ParseBlock(format_, song);
|
||||
|
||||
if (QFileInfo(filename).completeBaseName().isEmpty()) {
|
||||
// Avoid having empty filenames, or filenames with extension only: in this
|
||||
// case, keep the original filename.
|
||||
// We remove the extension from "filename" if it exists, as
|
||||
// song.basefilename()
|
||||
// also contains the extension.
|
||||
// Avoid having empty filenames, or filenames with extension only: in this case, keep the original filename.
|
||||
// We remove the extension from "filename" if it exists, as song.basefilename() also contains the extension.
|
||||
filename =
|
||||
Utilities::PathWithoutFilenameExtension(filename) + song.basefilename();
|
||||
}
|
||||
@@ -112,7 +122,8 @@ QString OrganiseFormat::GetFilenameForSong(const Song &song) const {
|
||||
const QCharRef c = filename[i];
|
||||
if (c < 128) {
|
||||
stripped.append(c);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
const QString decomposition = c.decomposition();
|
||||
if (!decomposition.isEmpty() && decomposition[0] < 128)
|
||||
stripped.append(decomposition[0]);
|
||||
|
||||
@@ -23,19 +23,26 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QColor>
|
||||
#include <QTextDocument>
|
||||
#include <QTextEdit>
|
||||
#include <QSyntaxHighlighter>
|
||||
#include <QValidator>
|
||||
#include <QTextEdit>
|
||||
|
||||
#include "core/song.h"
|
||||
class Song;
|
||||
|
||||
class OrganiseFormat {
|
||||
|
||||
public:
|
||||
explicit OrganiseFormat(const QString &format = QString());
|
||||
|
||||
static const char* kTagPattern;
|
||||
static const char* kBlockPattern;
|
||||
static const char *kTagPattern;
|
||||
static const char *kBlockPattern;
|
||||
static const QStringList kKnownTags;
|
||||
static const char kInvalidFatCharacters[];
|
||||
static const int kInvalidFatCharactersCount;
|
||||
@@ -57,7 +64,7 @@ class OrganiseFormat {
|
||||
|
||||
class Validator : public QValidator {
|
||||
public:
|
||||
explicit Validator(QObject* parent = nullptr);
|
||||
explicit Validator(QObject *parent = nullptr);
|
||||
QValidator::State validate(QString &format, int &pos) const;
|
||||
};
|
||||
|
||||
@@ -70,14 +77,14 @@ class OrganiseFormat {
|
||||
static const QRgb kInvalidTagColorDark;
|
||||
static const QRgb kBlockColorDark;
|
||||
|
||||
explicit SyntaxHighlighter(QObject* parent = nullptr);
|
||||
explicit SyntaxHighlighter(QTextEdit* parent);
|
||||
explicit SyntaxHighlighter(QTextDocument* parent);
|
||||
explicit SyntaxHighlighter(QObject *parent = nullptr);
|
||||
explicit SyntaxHighlighter(QTextEdit *parent);
|
||||
explicit SyntaxHighlighter(QTextDocument *parent);
|
||||
void highlightBlock(const QString &format);
|
||||
};
|
||||
|
||||
private:
|
||||
QString ParseBlock(QString block, const Song &song, bool* any_empty = nullptr) const;
|
||||
QString ParseBlock(QString block, const Song &song, bool *any_empty = nullptr) const;
|
||||
QString TagValue(const QString &tag, const Song &song) const;
|
||||
|
||||
QString format_;
|
||||
|
||||
@@ -18,23 +18,33 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "player.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "player.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include <QDateTime>
|
||||
#include <QSettings>
|
||||
#include <QtDebug>
|
||||
#include <QtConcurrentRun>
|
||||
|
||||
#include "core/application.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/urlhandler.h"
|
||||
#include "core/timeconstants.h"
|
||||
#include "engine/enginetype.h"
|
||||
|
||||
#include "song.h"
|
||||
#include "timeconstants.h"
|
||||
#include "urlhandler.h"
|
||||
#include "application.h"
|
||||
|
||||
#include "engine/enginebase.h"
|
||||
#include "engine/enginedevice.h"
|
||||
#include "engine/enginetype.h"
|
||||
|
||||
#ifdef HAVE_GSTREAMER
|
||||
# include "engine/gstengine.h"
|
||||
@@ -53,10 +63,9 @@
|
||||
#include "playlist/playlist.h"
|
||||
#include "playlist/playlistitem.h"
|
||||
#include "playlist/playlistmanager.h"
|
||||
|
||||
#include "analyzer/analyzercontainer.h"
|
||||
#include "playlist/playlistsequence.h"
|
||||
#include "equalizer/equalizer.h"
|
||||
|
||||
#include "analyzer/analyzercontainer.h"
|
||||
#include "settings/backendsettingspage.h"
|
||||
#include "settings/behavioursettingspage.h"
|
||||
#include "settings/playlistsettingspage.h"
|
||||
@@ -76,8 +85,6 @@ Player::Player(Application *app, QObject *parent)
|
||||
menu_previousmode_(PreviousBehaviour_DontRestart),
|
||||
seek_step_sec_(10)
|
||||
{
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
QSettings s;
|
||||
s.beginGroup(BackendSettingsPage::kSettingsGroup);
|
||||
@@ -101,8 +108,6 @@ Player::Player(Application *app, QObject *parent)
|
||||
Player::~Player() {}
|
||||
|
||||
EngineBase *Player::CreateEngine(Engine::EngineType enginetype) {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
bool engine = false;
|
||||
EngineBase *enginebase = nullptr;
|
||||
@@ -170,8 +175,6 @@ EngineBase *Player::CreateEngine(Engine::EngineType enginetype) {
|
||||
|
||||
void Player::Init() {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
connect(engine_.get(), SIGNAL(Error(QString)), SIGNAL(Error(QString)));
|
||||
connect(engine_.get(), SIGNAL(ValidSongRequested(QUrl)), SLOT(ValidSongRequested(QUrl)));
|
||||
connect(engine_.get(), SIGNAL(InvalidSongRequested(QUrl)), SLOT(InvalidSongRequested(QUrl)));
|
||||
@@ -213,8 +216,6 @@ void Player::SetEqualizer(Equalizer *equalizer) {
|
||||
|
||||
void Player::ReloadSettings() {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
QSettings s;
|
||||
|
||||
s.beginGroup(PlaylistSettingsPage::kSettingsGroup);
|
||||
@@ -230,8 +231,6 @@ void Player::ReloadSettings() {
|
||||
}
|
||||
|
||||
void Player::HandleLoadResult(const UrlHandler::LoadResult &result) {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
// Might've been an async load, so check we're still on the same item
|
||||
shared_ptr<PlaylistItem> item = app_->playlist_manager()->active()->current_item();
|
||||
@@ -254,8 +253,7 @@ void Player::HandleLoadResult(const UrlHandler::LoadResult &result) {
|
||||
|
||||
qLog(Debug) << "URL handler for" << result.original_url_ << "returned" << result.media_url_;
|
||||
|
||||
// If there was no length info in song's metadata, use the one provided by
|
||||
// URL handler, if there is one
|
||||
// If there was no length info in song's metadata, use the one provided by URL handler, if there is one
|
||||
if (item->Metadata().length_nanosec() <= 0 && result.length_nanosec_ != -1) {
|
||||
Song song = item->Metadata();
|
||||
song.set_length_nanosec(result.length_nanosec_);
|
||||
@@ -281,8 +279,6 @@ void Player::HandleLoadResult(const UrlHandler::LoadResult &result) {
|
||||
void Player::Next() { NextInternal(Engine::Manual); }
|
||||
|
||||
void Player::NextInternal(Engine::TrackChangeFlags change) {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
if (HandleStopAfter()) return;
|
||||
|
||||
@@ -303,8 +299,6 @@ void Player::NextInternal(Engine::TrackChangeFlags change) {
|
||||
}
|
||||
|
||||
void Player::NextItem(Engine::TrackChangeFlags change) {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
Playlist *active_playlist = app_->playlist_manager()->active();
|
||||
|
||||
@@ -313,8 +307,7 @@ void Player::NextItem(Engine::TrackChangeFlags change) {
|
||||
const PlaylistSequence::RepeatMode repeat_mode = active_playlist->sequence()->repeat_mode();
|
||||
if (repeat_mode != PlaylistSequence::Repeat_Off) {
|
||||
if ((repeat_mode == PlaylistSequence::Repeat_Track && nb_errors_received_ >= 3) || (nb_errors_received_ >= app_->playlist_manager()->active()->proxy()->rowCount())) {
|
||||
// We received too many "Error" state changes: probably looping over a
|
||||
// playlist which contains only unavailable elements: stop now.
|
||||
// We received too many "Error" state changes: probably looping over a playlist which contains only unavailable elements: stop now.
|
||||
nb_errors_received_ = 0;
|
||||
Stop();
|
||||
return;
|
||||
@@ -338,12 +331,9 @@ void Player::NextItem(Engine::TrackChangeFlags change) {
|
||||
}
|
||||
|
||||
bool Player::HandleStopAfter() {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
if (app_->playlist_manager()->active()->stop_after_current()) {
|
||||
// Find what the next track would've been, and mark that one as current
|
||||
// so it plays next time the user presses Play.
|
||||
// Find what the next track would've been, and mark that one as current so it plays next time the user presses Play.
|
||||
const int next_row = app_->playlist_manager()->active()->next_row();
|
||||
if (next_row != -1) {
|
||||
app_->playlist_manager()->active()->set_current_row(next_row, true);
|
||||
@@ -358,8 +348,6 @@ bool Player::HandleStopAfter() {
|
||||
}
|
||||
|
||||
void Player::TrackEnded() {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
if (HandleStopAfter()) return;
|
||||
|
||||
@@ -372,8 +360,6 @@ void Player::TrackEnded() {
|
||||
|
||||
void Player::PlayPause() {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
switch (engine_->state()) {
|
||||
case Engine::Paused:
|
||||
engine_->Unpause();
|
||||
@@ -504,7 +490,7 @@ void Player::PlayAt(int index, Engine::TrackChangeFlags change, bool reshuffle)
|
||||
|
||||
if (change == Engine::Manual && engine_->position_nanosec() != engine_->length_nanosec()) {
|
||||
emit TrackSkipped(current_item_);
|
||||
const QUrl& url = current_item_->Url();
|
||||
const QUrl &url = current_item_->Url();
|
||||
if (url_handlers_.contains(url.scheme())) {
|
||||
url_handlers_[url.scheme()]->TrackSkipped();
|
||||
}
|
||||
@@ -541,8 +527,7 @@ void Player::PlayAt(int index, Engine::TrackChangeFlags change, bool reshuffle)
|
||||
}
|
||||
|
||||
void Player::CurrentMetadataChanged(const Song &metadata) {
|
||||
// those things might have changed (especially when a previously invalid
|
||||
// song was reloaded) so we push the latest version into Engine
|
||||
// those things might have changed (especially when a previously invalid song was reloaded) so we push the latest version into Engine
|
||||
engine_->RefreshMarkers(metadata.beginning_nanosec(), metadata.end_nanosec());
|
||||
|
||||
}
|
||||
@@ -551,8 +536,7 @@ void Player::SeekTo(int seconds) {
|
||||
|
||||
const qint64 length_nanosec = engine_->length_nanosec();
|
||||
|
||||
// If the length is 0 then either there is no song playing, or the song isn't
|
||||
// seekable.
|
||||
// If the length is 0 then either there is no song playing, or the song isn't seekable.
|
||||
if (length_nanosec <= 0) {
|
||||
return;
|
||||
}
|
||||
@@ -581,8 +565,7 @@ void Player::EngineMetadataReceived(const Engine::SimpleMetaBundle &bundle) {
|
||||
|
||||
Engine::SimpleMetaBundle bundle_copy = bundle;
|
||||
|
||||
// Maybe the metadata is from icycast and has "Artist - Title" shoved
|
||||
// together in the title field.
|
||||
// Maybe the metadata is from icycast and has "Artist - Title" shoved together in the title field.
|
||||
const int dash_pos = bundle_copy.title.indexOf('-');
|
||||
if (dash_pos != -1 && bundle_copy.artist.isEmpty()) {
|
||||
// Split on " - " if it exists, otherwise split on "-".
|
||||
@@ -654,10 +637,8 @@ void Player::TogglePrettyOSD() {
|
||||
|
||||
void Player::TrackAboutToEnd() {
|
||||
|
||||
// If the current track was from a URL handler then it might have special
|
||||
// behaviour to queue up a subsequent track. We don't want to preload (and
|
||||
// scrobble) the next item in the playlist if it's just going to be stopped
|
||||
// again immediately after.
|
||||
// If the current track was from a URL handler then it might have special behaviour to queue up a subsequent track.
|
||||
// We don't want to preload (and scrobble) the next item in the playlist if it's just going to be stopped again immediately after.
|
||||
if (app_->playlist_manager()->active()->current_item()) {
|
||||
const QUrl url = app_->playlist_manager()->active()->current_item()->Url();
|
||||
if (url_handlers_.contains(url.scheme())) {
|
||||
@@ -674,24 +655,20 @@ void Player::TrackAboutToEnd() {
|
||||
}
|
||||
|
||||
if (engine_->is_autocrossfade_enabled()) {
|
||||
// Crossfade is on, so just start playing the next track. The current one
|
||||
// will fade out, and the new one will fade in
|
||||
// Crossfade is on, so just start playing the next track. The current one will fade out, and the new one will fade in
|
||||
|
||||
// But, if there's no next track and we don't want to fade out, then do
|
||||
// nothing and just let the track finish to completion.
|
||||
// But, if there's no next track and we don't want to fade out, then do nothing and just let the track finish to completion.
|
||||
if (!engine_->is_fadeout_enabled() && !has_next_row) return;
|
||||
|
||||
// If the next track is on the same album (or same cue file), and the
|
||||
// user doesn't want to crossfade between tracks on the same album, then
|
||||
// don't do this automatic crossfading.
|
||||
// If the next track is on the same album (or same cue file),
|
||||
// and the user doesn't want to crossfade between tracks on the same album, then don't do this automatic crossfading.
|
||||
if (engine_->crossfade_same_album() || !has_next_row || !next_item || !current_item_->Metadata().IsOnSameAlbum(next_item->Metadata())) {
|
||||
TrackEnded();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Crossfade is off, so start preloading the next track so we don't get a
|
||||
// gap between songs.
|
||||
// Crossfade is off, so start preloading the next track so we don't get a gap between songs.
|
||||
if (!has_next_row || !next_item) return;
|
||||
|
||||
QUrl url = next_item->Url();
|
||||
@@ -726,8 +703,8 @@ void Player::InvalidSongRequested(const QUrl &url) {
|
||||
|
||||
// first send the notification to others...
|
||||
emit SongChangeRequestProcessed(url, false);
|
||||
// ... and now when our listeners have completed their processing of the
|
||||
// current item we can change the current item by skipping to the next song
|
||||
// ... and now when our listeners have completed their processing of the current item we can change
|
||||
// the current item by skipping to the next song
|
||||
//NextItem(Engine::Auto);
|
||||
|
||||
}
|
||||
|
||||
@@ -24,26 +24,30 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <memory>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
#include <QDateTime>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include <QSettings>
|
||||
|
||||
#include "config.h"
|
||||
#include "core/song.h"
|
||||
#include "core/urlhandler.h"
|
||||
#include "covermanager/albumcoverloader.h"
|
||||
#include "urlhandler.h"
|
||||
#include "engine/engine_fwd.h"
|
||||
#include "engine/enginetype.h"
|
||||
#include "engine/enginedevice.h"
|
||||
#include "playlist/playlistitem.h"
|
||||
#include "analyzer/analyzercontainer.h"
|
||||
#include "equalizer/equalizer.h"
|
||||
|
||||
class Application;
|
||||
class Song;
|
||||
class AnalyzerContainer;
|
||||
class Equalizer;
|
||||
|
||||
namespace Engine {
|
||||
struct SimpleMetaBundle;
|
||||
} // namespace Engine
|
||||
|
||||
class PlayerInterface : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
@@ -66,8 +70,7 @@ class PlayerInterface : public QObject {
|
||||
// Manual track change to the specified track
|
||||
virtual void PlayAt(int i, Engine::TrackChangeFlags change, bool reshuffle) = 0;
|
||||
|
||||
// If there's currently a song playing, pause it, otherwise play the track
|
||||
// that was playing last, or the first one on the playlist
|
||||
// If there's currently a song playing, pause it, otherwise play the track that was playing last, or the first one on the playlist
|
||||
virtual void PlayPause() = 0;
|
||||
virtual void RestartOrPrevious() = 0;
|
||||
|
||||
@@ -103,8 +106,8 @@ signals:
|
||||
// Emitted when there's a manual change to the current's track position.
|
||||
void Seeked(qlonglong microseconds);
|
||||
|
||||
// Emitted when Player has processed a request to play another song. This contains
|
||||
// the URL of the song and a flag saying whether it was able to play the song.
|
||||
// Emitted when Player has processed a request to play another song.
|
||||
// This contains the URL of the song and a flag saying whether it was able to play the song.
|
||||
void SongChangeRequestProcessed(const QUrl &url, bool valid);
|
||||
|
||||
// The toggle parameter is true when user requests to toggle visibility for Pretty OSD
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2012, David Sansome <me@davidsansome.com>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Strawberry is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QHASH_QURL_H
|
||||
#define QHASH_QURL_H
|
||||
|
||||
#include <QUrl>
|
||||
|
||||
#if QT_VERSION < 0x040700
|
||||
inline uint qHash(const QUrl& url) { return qHash(url.toEncoded()); }
|
||||
#endif
|
||||
|
||||
#endif // QHASH_QURL_H
|
||||
|
||||
@@ -20,9 +20,10 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "qtfslistener.h"
|
||||
#include <QString>
|
||||
|
||||
#include <QStringList>
|
||||
#include "filesystemwatcherinterface.h"
|
||||
#include "qtfslistener.h"
|
||||
|
||||
QtFSListener::QtFSListener(QObject *parent) : FileSystemWatcherInterface(parent), watcher_(this) {
|
||||
|
||||
@@ -40,4 +41,3 @@ void QtFSListener::Clear() {
|
||||
watcher_.removePaths(watcher_.directories());
|
||||
watcher_.removePaths(watcher_.files());
|
||||
}
|
||||
|
||||
|
||||
@@ -23,9 +23,11 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "filesystemwatcherinterface.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QString>
|
||||
|
||||
#include "filesystemwatcherinterface.h"
|
||||
|
||||
class QtFSListener : public FileSystemWatcherInterface {
|
||||
Q_OBJECT
|
||||
|
||||
@@ -20,19 +20,22 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "iconloader.h"
|
||||
#include "qtsystemtrayicon.h"
|
||||
|
||||
#include "core/song.h"
|
||||
#include "core/logging.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QCoreApplication>
|
||||
#include <QTextDocument>
|
||||
#include <QStringBuilder>
|
||||
#include <QMenu>
|
||||
#include <QFile>
|
||||
#include <QSystemTrayIcon>
|
||||
#include <QWheelEvent>
|
||||
#include <QAction>
|
||||
#include <QIODevice>
|
||||
#include <QFile>
|
||||
#include <QMenu>
|
||||
#include <QIcon>
|
||||
#include <QString>
|
||||
#include <QtEvents>
|
||||
|
||||
#include "song.h"
|
||||
#include "iconloader.h"
|
||||
|
||||
#include "systemtrayicon.h"
|
||||
#include "qtsystemtrayicon.h"
|
||||
|
||||
QtSystemTrayIcon::QtSystemTrayIcon(QObject *parent)
|
||||
: SystemTrayIcon(parent),
|
||||
@@ -44,8 +47,6 @@ QtSystemTrayIcon::QtSystemTrayIcon(QObject *parent)
|
||||
action_mute_(nullptr)
|
||||
{
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
QIcon theme_icon = IconLoader::Load("strawberry-panel");
|
||||
QIcon theme_icon_grey = IconLoader::Load("strawberry-panel-grey");
|
||||
|
||||
@@ -79,8 +80,6 @@ QtSystemTrayIcon::~QtSystemTrayIcon() {
|
||||
|
||||
bool QtSystemTrayIcon::eventFilter(QObject *object, QEvent *event) {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
if (QObject::eventFilter(object, event)) return true;
|
||||
|
||||
if (object != tray_) return false;
|
||||
@@ -90,7 +89,8 @@ bool QtSystemTrayIcon::eventFilter(QObject *object, QEvent *event) {
|
||||
if (e->modifiers() == Qt::ShiftModifier) {
|
||||
if (e->delta() > 0) {
|
||||
emit SeekForward();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
emit SeekBackward();
|
||||
}
|
||||
}
|
||||
@@ -113,12 +113,9 @@ bool QtSystemTrayIcon::eventFilter(QObject *object, QEvent *event) {
|
||||
}
|
||||
|
||||
void QtSystemTrayIcon::SetupMenu(QAction *previous, QAction *play, QAction *stop, QAction *stop_after, QAction *next, QAction *mute, QAction *quit) {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
// Creating new actions and connecting them to old ones. This allows us to
|
||||
// use old actions without displaying shortcuts that can not be used when
|
||||
// Strawberry's window is hidden
|
||||
// Creating new actions and connecting them to old ones.
|
||||
// This allows us to use old actions without displaying shortcuts that can not be used when Strawberry's window is hidden
|
||||
menu_->addAction(previous->icon(), previous->text(), previous, SLOT(trigger()));
|
||||
action_play_pause_ = menu_->addAction(play->icon(), play->text(), play, SLOT(trigger()));
|
||||
action_stop_ = menu_->addAction(stop->icon(), stop->text(), stop, SLOT(trigger()));
|
||||
@@ -140,8 +137,6 @@ void QtSystemTrayIcon::SetupMenu(QAction *previous, QAction *play, QAction *stop
|
||||
|
||||
void QtSystemTrayIcon::Clicked(QSystemTrayIcon::ActivationReason reason) {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
switch (reason) {
|
||||
case QSystemTrayIcon::DoubleClick:
|
||||
case QSystemTrayIcon::Trigger:
|
||||
|
||||
@@ -23,24 +23,36 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QSystemTrayIcon>
|
||||
#include <QString>
|
||||
#include <QPixmap>
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
#include <QtEvents>
|
||||
|
||||
#include "systemtrayicon.h"
|
||||
|
||||
#include <QSystemTrayIcon>
|
||||
class QEvent;
|
||||
|
||||
class Song;
|
||||
|
||||
class QtSystemTrayIcon : public SystemTrayIcon {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QtSystemTrayIcon(QObject* parent = nullptr);
|
||||
QtSystemTrayIcon(QObject *parent = nullptr);
|
||||
~QtSystemTrayIcon();
|
||||
|
||||
void SetupMenu(QAction* previous, QAction *play, QAction *stop, QAction *stop_after, QAction *next, QAction *mute, QAction *quit);
|
||||
void SetupMenu(QAction *previous, QAction *play, QAction *stop, QAction *stop_after, QAction *next, QAction *mute, QAction *quit);
|
||||
bool IsVisible() const;
|
||||
void SetVisible(bool visible);
|
||||
|
||||
void ShowPopup(const QString &summary, const QString &message, int timeout);
|
||||
|
||||
void SetNowPlaying(const Song& song, const QString& image_path);
|
||||
void SetNowPlaying(const Song &song, const QString &image_path);
|
||||
void ClearNowPlaying();
|
||||
|
||||
protected:
|
||||
|
||||
@@ -18,23 +18,24 @@
|
||||
*
|
||||
*/
|
||||
|
||||
//#ifdef HAVE_GIO
|
||||
//#undef signals // Clashes with GIO, and not needed in this file
|
||||
#include "config.h"
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "core/logging.h"
|
||||
|
||||
//namespace {
|
||||
|
||||
void ScanGIOModulePath() {
|
||||
QString gio_module_path;
|
||||
|
||||
#if defined(Q_OS_WIN32)
|
||||
gio_module_path = QCoreApplication::applicationDirPath() + "/gio-modules";
|
||||
gio_module_path = QDir::toNativeSeparators(QCoreApplication::applicationDirPath() + "/gio-modules");
|
||||
#endif
|
||||
|
||||
if (!gio_module_path.isEmpty()) {
|
||||
@@ -43,6 +44,3 @@ void ScanGIOModulePath() {
|
||||
g_io_modules_scan_all_in_directory(bytes.data());
|
||||
}
|
||||
}
|
||||
|
||||
//} // namespace
|
||||
//#endif // HAVE_GIO
|
||||
|
||||
@@ -20,11 +20,11 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "scopedtransaction.h"
|
||||
#include "core/logging.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <QSqlDatabase>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "scopedtransaction.h"
|
||||
|
||||
ScopedTransaction::ScopedTransaction(QSqlDatabase* db)
|
||||
: db_(db), pending_(true) {
|
||||
|
||||
@@ -23,22 +23,22 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
class QSqlDatabase;
|
||||
#include <QSqlDatabase>
|
||||
|
||||
// Opens a transaction on a database.
|
||||
// Rolls back the transaction if the object goes out of scope before Commit()
|
||||
// is called.
|
||||
// Rolls back the transaction if the object goes out of scope before Commit() is called.
|
||||
class ScopedTransaction : boost::noncopyable {
|
||||
public:
|
||||
ScopedTransaction(QSqlDatabase* db);
|
||||
ScopedTransaction(QSqlDatabase *db);
|
||||
~ScopedTransaction();
|
||||
|
||||
void Commit();
|
||||
|
||||
private:
|
||||
QSqlDatabase* db_;
|
||||
QSqlDatabase *db_;
|
||||
bool pending_;
|
||||
};
|
||||
|
||||
|
||||
@@ -20,22 +20,19 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QtGlobal>
|
||||
#ifdef HAVE_DBUS
|
||||
# include <QDBusConnection>
|
||||
# include <QDBusConnectionInterface>
|
||||
# include <QDBusReply>
|
||||
# include "dbusscreensaver.h"
|
||||
#endif
|
||||
|
||||
#include "screensaver.h"
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
#include "dbusscreensaver.h"
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusConnectionInterface>
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_DARWIN
|
||||
#include "macscreensaver.h"
|
||||
#endif
|
||||
|
||||
#include <QtDebug>
|
||||
|
||||
const char *Screensaver::kGnomeService = "org.gnome.ScreenSaver";
|
||||
const char *Screensaver::kGnomePath = "/";
|
||||
const char *Screensaver::kGnomeInterface = "org.gnome.ScreenSaver";
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
#include <QSettings>
|
||||
|
||||
class SettingsProvider {
|
||||
@@ -59,4 +60,3 @@ class DefaultSettingsProvider : public SettingsProvider {
|
||||
};
|
||||
|
||||
#endif // SETTINGSPROVIDER_H
|
||||
|
||||
|
||||
@@ -22,9 +22,12 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "signalchecker.h"
|
||||
#include <glib-object.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include <QtGlobal>
|
||||
|
||||
#include "signalchecker.h"
|
||||
|
||||
gulong CheckedGConnect(gpointer source, const char *signal, GCallback callback, gpointer data, const int callback_param_count) {
|
||||
|
||||
@@ -38,8 +41,7 @@ gulong CheckedGConnect(gpointer source, const char *signal, GCallback callback,
|
||||
|
||||
GSignalQuery query;
|
||||
g_signal_query(signal_id, &query);
|
||||
// The signature for a signal callback is always:
|
||||
// return_type callback(gpointer data1, params..., gpointer data2);
|
||||
// The signature for a signal callback is always: return_type callback(gpointer data1, params..., gpointer data2);
|
||||
int signal_params = query.n_params + 2;
|
||||
if (signal_params != callback_param_count) {
|
||||
qFatal("Connecting callback to signal with different parameters counts");
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#include <boost/function_types/function_arity.hpp>
|
||||
|
||||
@@ -23,10 +23,11 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "simpletreemodel.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
#include "simpletreemodel.h"
|
||||
|
||||
template <typename T>
|
||||
class SimpleTreeItem {
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
class QModelIndex;
|
||||
#include <QModelIndex>
|
||||
|
||||
template <typename T>
|
||||
class SimpleTreeModel : public QAbstractItemModel {
|
||||
|
||||
@@ -20,24 +20,28 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "song.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include "tstring.h"
|
||||
#include <taglib/id3v1genres.h>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QObject>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QLatin1Literal>
|
||||
#include <QSharedData>
|
||||
#include <QSqlQuery>
|
||||
#include <QTextCodec>
|
||||
#include <QTime>
|
||||
#include <QtAlgorithms>
|
||||
#include <QHash>
|
||||
#include <QByteArray>
|
||||
#include <QVariant>
|
||||
#include <QtConcurrentRun>
|
||||
#include <QString>
|
||||
|
||||
#include <id3v1genres.h>
|
||||
#include <QStringList>
|
||||
#include <QRegExp>
|
||||
#include <QUrl>
|
||||
#include <QImage>
|
||||
#include <QTextCodec>
|
||||
#include <QSqlQuery>
|
||||
#include <QtDebug>
|
||||
|
||||
#ifdef HAVE_LIBGPOD
|
||||
#include <gpod/itdb.h>
|
||||
@@ -47,17 +51,18 @@
|
||||
#include <libmtp.h>
|
||||
#endif
|
||||
|
||||
#include "core/application.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/messagehandler.h"
|
||||
#include "core/mpris_common.h"
|
||||
#include "core/timeconstants.h"
|
||||
#include "core/utilities.h"
|
||||
|
||||
#include "engine/enginebase.h"
|
||||
#include "timeconstants.h"
|
||||
#include "utilities.h"
|
||||
#include "song.h"
|
||||
#include "application.h"
|
||||
#include "mpris_common.h"
|
||||
#include "collection/sqlrow.h"
|
||||
#include "tagreadermessages.pb.h"
|
||||
#include "widgets/trackslider.h"
|
||||
#include "covermanager/albumcoverloader.h"
|
||||
#include "tagreadermessages.pb.h"
|
||||
|
||||
const QStringList Song::kColumns = QStringList() << "title"
|
||||
<< "album"
|
||||
@@ -129,6 +134,8 @@ const QString Song::kFtsUpdateSpec = Utilities::Updateify(Song::kFtsColumns).joi
|
||||
const QString Song::kManuallyUnsetCover = "(unset)";
|
||||
const QString Song::kEmbeddedCover = "(embedded)";
|
||||
|
||||
const QRegExp Song::kCoverRemoveDisc(" ?-? ((\\(|\\[)?)(Disc|CD) ?([0-9]{1,2})((\\)|\\])?)$");
|
||||
|
||||
struct Song::Private : public QSharedData {
|
||||
|
||||
Private();
|
||||
@@ -438,8 +445,6 @@ QString Song::Decode(const QString &tag, const QTextCodec *codec) {
|
||||
|
||||
void Song::InitFromProtobuf(const pb::tagreader::SongMetadata &pb) {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
d->init_from_file_ = true;
|
||||
d->valid_ = pb.valid();
|
||||
d->title_ = QStringFromStdString(pb.title());
|
||||
@@ -484,8 +489,6 @@ void Song::InitFromProtobuf(const pb::tagreader::SongMetadata &pb) {
|
||||
|
||||
void Song::ToProtobuf(pb::tagreader::SongMetadata *pb) const {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
const QByteArray url(d->url_.toEncoded());
|
||||
|
||||
pb->set_valid(d->valid_);
|
||||
@@ -684,9 +687,8 @@ void Song::InitFromFilePartial(const QString &filename) {
|
||||
|
||||
set_url(QUrl::fromLocalFile(filename));
|
||||
// We currently rely on filename suffix to know if it's a music file or not.
|
||||
// TODO: I know this is not satisfying, but currently, we rely on TagLib
|
||||
// which seems to have the behavior (filename checks). Someday, it would be
|
||||
// nice to perform some magic tests everywhere.
|
||||
// TODO: I know this is not satisfying, but currently, we rely on TagLib which seems to have the behavior (filename checks).
|
||||
// Someday, it would be nice to perform some magic tests everywhere.
|
||||
QFileInfo info(filename);
|
||||
d->basefilename_ = info.fileName();
|
||||
QString suffix = info.suffix().toLower();
|
||||
@@ -704,9 +706,14 @@ void Song::InitFromFilePartial(const QString &filename) {
|
||||
|
||||
void Song::InitArtManual() {
|
||||
|
||||
QString album2 = d->album_;
|
||||
album2.remove(Song::kCoverRemoveDisc);
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__ << d->artist_ << d->album_ << album2;
|
||||
|
||||
// If we don't have an art, check if we have one in the cache
|
||||
if (d->art_manual_.isEmpty() && d->art_automatic_.isEmpty()) {
|
||||
QString filename(Utilities::Sha1CoverHash(d->artist_, d->album_).toHex() + ".jpg");
|
||||
QString filename(Utilities::Sha1CoverHash(d->artist_, album2).toHex() + ".jpg");
|
||||
QString path(AlbumCoverLoader::ImageCacheDir() + "/" + filename);
|
||||
if (QFile::exists(path)) {
|
||||
d->art_manual_ = path;
|
||||
@@ -718,8 +725,6 @@ void Song::InitArtManual() {
|
||||
#ifdef HAVE_LIBGPOD
|
||||
void Song::InitFromItdb(const Itdb_Track *track, const QString &prefix) {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
d->valid_ = true;
|
||||
|
||||
d->title_ = QString::fromUtf8(track->title);
|
||||
@@ -799,8 +804,6 @@ void Song::ToItdb(Itdb_Track *track) const {
|
||||
#ifdef HAVE_LIBMTP
|
||||
void Song::InitFromMTP(const LIBMTP_track_t *track, const QString &host) {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
d->valid_ = true;
|
||||
|
||||
d->title_ = QString::fromUtf8(track->title);
|
||||
@@ -841,8 +844,6 @@ void Song::InitFromMTP(const LIBMTP_track_t *track, const QString &host) {
|
||||
|
||||
void Song::ToMTP(LIBMTP_track_t *track) const {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
track->item_id = 0;
|
||||
track->parent_id = 0;
|
||||
track->storage_id = 0;
|
||||
@@ -886,12 +887,9 @@ void Song::ToMTP(LIBMTP_track_t *track) const {
|
||||
|
||||
void Song::MergeFromSimpleMetaBundle(const Engine::SimpleMetaBundle &bundle) {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
if (d->init_from_file_ || d->url_.scheme() == "file") {
|
||||
// This Song was already loaded using taglib. Our tags are probably better
|
||||
// than the engine's. Note: init_from_file_ is used for non-file:// URLs
|
||||
// when the metadata is known to be good, like from Jamendo.
|
||||
// This Song was already loaded using taglib. Our tags are probably better than the engine's.
|
||||
// Note: init_from_file_ is used for non-file:// URLs when the metadata is known to be good, like from Jamendo.
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1051,8 +1049,6 @@ QString Song::SampleRateBitDepthToText() const {
|
||||
|
||||
bool Song::IsMetadataEqual(const Song &other) const {
|
||||
|
||||
//qLog(Debug) << __PRETTY_FUNCTION__;
|
||||
|
||||
return d->title_ == other.d->title_ &&
|
||||
d->album_ == other.d->album_ &&
|
||||
d->artist_ == other.d->artist_ &&
|
||||
|
||||
@@ -21,14 +21,28 @@
|
||||
#ifndef SONG_H
|
||||
#define SONG_H
|
||||
|
||||
#include <QFuture>
|
||||
#include <QImage>
|
||||
#include <QMetaType>
|
||||
#include <QSharedDataPointer>
|
||||
#include <QVariantMap>
|
||||
|
||||
#include "config.h"
|
||||
#include "engine/engine_fwd.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QSharedData>
|
||||
#include <QSharedDataPointer>
|
||||
#include <QMetaType>
|
||||
#include <QList>
|
||||
#include <QSet>
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QRegExp>
|
||||
#include <QUrl>
|
||||
#include <QImage>
|
||||
#include <QTextCodec>
|
||||
#include <QSqlQuery>
|
||||
|
||||
namespace Engine {
|
||||
struct SimpleMetaBundle;
|
||||
} // namespace Engine
|
||||
|
||||
namespace pb {
|
||||
namespace tagreader {
|
||||
@@ -36,9 +50,6 @@ class SongMetadata;
|
||||
} // namespace tagreader
|
||||
} // namespace pb
|
||||
|
||||
class QSqlQuery;
|
||||
class QUrl;
|
||||
|
||||
#ifdef HAVE_LIBGPOD
|
||||
struct _Itdb_Track;
|
||||
#endif
|
||||
@@ -75,11 +86,12 @@ class Song {
|
||||
|
||||
static const QString kManuallyUnsetCover;
|
||||
static const QString kEmbeddedCover;
|
||||
|
||||
static const QRegExp kCoverRemoveDisc;
|
||||
|
||||
static QString JoinSpec(const QString &table);
|
||||
|
||||
// Don't change these values - they're stored in the database, and defined
|
||||
// in the tag reader protobuf.
|
||||
// Don't change these values - they're stored in the database, and defined in the tag reader protobuf.
|
||||
// If a new lossless file is added, also add it to IsFileLossless().
|
||||
enum FileType {
|
||||
Type_Unknown = 0,
|
||||
@@ -129,9 +141,8 @@ class Song {
|
||||
void ToMTP(LIBMTP_track_struct *track) const;
|
||||
#endif
|
||||
|
||||
// Copies important statistics from the other song to this one, overwriting
|
||||
// any data that already exists. Useful when you want updated tags from disk
|
||||
// but you want to keep user stats.
|
||||
// Copies important statistics from the other song to this one, overwriting any data that already exists.
|
||||
// Useful when you want updated tags from disk but you want to keep user stats.
|
||||
void MergeUserSetData(const Song &other);
|
||||
|
||||
static QString Decode(const QString &tag, const QTextCodec *codec = nullptr);
|
||||
@@ -204,8 +215,7 @@ class Song {
|
||||
|
||||
// Returns true if this Song had it's cover manually unset by user.
|
||||
bool has_manually_unset_cover() const;
|
||||
// This method represents an explicit request to unset this song's
|
||||
// cover.
|
||||
// This method represents an explicit request to unset this song's cover.
|
||||
void manually_unset_cover();
|
||||
|
||||
// Returns true if this song (it's media file) has an embedded cover.
|
||||
@@ -288,15 +298,15 @@ class Song {
|
||||
|
||||
bool operator==(const Song &other) const;
|
||||
|
||||
// Two songs that are on the same album will have the same AlbumKey. It is
|
||||
// more efficient to use IsOnSameAlbum, but this function can be used when
|
||||
// you need to hash the key to do fast lookups.
|
||||
// Two songs that are on the same album will have the same AlbumKey.
|
||||
// It is more efficient to use IsOnSameAlbum, but this function can be used when you need to hash the key to do fast lookups.
|
||||
QString AlbumKey() const;
|
||||
|
||||
Song &operator=(const Song &other);
|
||||
|
||||
private:
|
||||
struct Private;
|
||||
|
||||
QSharedDataPointer<Private> d;
|
||||
};
|
||||
Q_DECLARE_METATYPE(Song);
|
||||
|
||||
@@ -20,36 +20,46 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "songloader.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <memory>
|
||||
|
||||
#if defined(HAVE_GSTREAMER) && defined(HAVE_AUDIOCD)
|
||||
#include <gst/audio/gstaudiocdsrc.h>
|
||||
#ifdef HAVE_GSTREAMER
|
||||
# include <gst/gst.h>
|
||||
#endif
|
||||
|
||||
#include <QObject>
|
||||
#include <QIODevice>
|
||||
#include <QBuffer>
|
||||
#include <QByteArray>
|
||||
#include <QtAlgorithms>
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QList>
|
||||
#include <QSet>
|
||||
#include <QTimer>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include <QEventLoop>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "config.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/player.h"
|
||||
#include "core/signalchecker.h"
|
||||
#include "core/song.h"
|
||||
#include "core/tagreaderclient.h"
|
||||
#include "core/timeconstants.h"
|
||||
|
||||
#include "signalchecker.h"
|
||||
#include "player.h"
|
||||
#include "song.h"
|
||||
#include "songloader.h"
|
||||
#include "tagreaderclient.h"
|
||||
#include "collection/collectionbackend.h"
|
||||
#include "collection/collectionquery.h"
|
||||
#include "collection/sqlrow.h"
|
||||
#include "playlistparsers/cueparser.h"
|
||||
#include "playlistparsers/parserbase.h"
|
||||
#include "playlistparsers/playlistparser.h"
|
||||
|
||||
#if defined(HAVE_AUDIOCD) && defined(HAVE_GSTREAMER)
|
||||
#include "device/cddasongloader.h"
|
||||
# include "device/cddasongloader.h"
|
||||
#endif
|
||||
|
||||
using std::placeholders::_1;
|
||||
@@ -98,7 +108,7 @@ SongLoader::~SongLoader() {
|
||||
}
|
||||
|
||||
SongLoader::Result SongLoader::Load(const QUrl &url) {
|
||||
|
||||
|
||||
url_ = url;
|
||||
|
||||
if (url_.scheme() == "file") {
|
||||
@@ -106,7 +116,8 @@ SongLoader::Result SongLoader::Load(const QUrl &url) {
|
||||
}
|
||||
|
||||
if (sRawUriSchemes.contains(url_.scheme()) || player_->HandlerForUrl(url) != nullptr) {
|
||||
// The URI scheme indicates that it can't possibly be a playlist, or we have a custom handler for the URL, so add it as a raw stream. AddAsRawStream();
|
||||
// The URI scheme indicates that it can't possibly be a playlist,
|
||||
// or we have a custom handler for the URL, so add it as a raw stream. AddAsRawStream();
|
||||
return Success;
|
||||
}
|
||||
|
||||
@@ -181,7 +192,7 @@ SongLoader::Result SongLoader::LoadLocal(const QString &filename) {
|
||||
query.AddWhere("filename", url.toEncoded());
|
||||
|
||||
if (collection_->ExecQuery(&query) && query.Next()) {
|
||||
// we may have many results when the file has many sections
|
||||
// We may have many results when the file has many sections
|
||||
do {
|
||||
Song song;
|
||||
song.InitFromQuery(query, true);
|
||||
@@ -195,8 +206,7 @@ SongLoader::Result SongLoader::LoadLocal(const QString &filename) {
|
||||
}
|
||||
|
||||
// It's not in the database, load it asynchronously.
|
||||
preload_func_ =
|
||||
std::bind(&SongLoader::LoadLocalAsync, this, filename);
|
||||
preload_func_ = std::bind(&SongLoader::LoadLocalAsync, this, filename);
|
||||
return BlockingLoadRequired;
|
||||
}
|
||||
|
||||
@@ -215,8 +225,7 @@ void SongLoader::LoadLocalAsync(const QString &filename) {
|
||||
|
||||
ParserBase *parser = playlist_parser_->ParserForMagic(data);
|
||||
if (!parser) {
|
||||
// Check the file extension as well, maybe the magic failed, or it was a
|
||||
// basic M3U file which is just a plain list of filenames.
|
||||
// Check the file extension as well, maybe the magic failed, or it was a basic M3U file which is just a plain list of filenames.
|
||||
parser = playlist_parser_->ParserForExtension(QFileInfo(filename).suffix().toLower());
|
||||
}
|
||||
|
||||
@@ -307,10 +316,10 @@ void SongLoader::LoadLocalDirectory(const QString &filename) {
|
||||
|
||||
qStableSort(songs_.begin(), songs_.end(), CompareSongs);
|
||||
|
||||
// Load the first song: all songs will be loaded async, but we want the first
|
||||
// one in our list to be fully loaded, so if the user has the "Start playing
|
||||
// when adding to playlist" preference behaviour set, it can enjoy the first
|
||||
// song being played (seek it, have moodbar, etc.)
|
||||
// Load the first song:
|
||||
// all songs will be loaded async, but we want the first one in our list to be fully loaded,
|
||||
// so if the user has the "Start playing when adding to playlist" preference behaviour set,
|
||||
// it can enjoy the first song being played (seek it, have moodbar, etc.)
|
||||
if (!songs_.isEmpty()) EffectiveSongLoad(&(*songs_.begin()));
|
||||
|
||||
}
|
||||
@@ -357,15 +366,11 @@ void SongLoader::LoadRemote() {
|
||||
|
||||
qLog(Debug) << "Loading remote file" << url_;
|
||||
|
||||
// It's not a local file so we have to fetch it to see what it is. We use
|
||||
// gstreamer to do this since it handles funky URLs for us (http://, ssh://,
|
||||
// etc) and also has typefinder plugins.
|
||||
// First we wait for typefinder to tell us what it is. If it's not text/plain
|
||||
// or text/uri-list assume it's a song and return success.
|
||||
// Otherwise wait to get 512 bytes of data and do magic on it - if the magic
|
||||
// fails then we don't know what it is so return failure.
|
||||
// If the magic succeeds then we know for sure it's a playlist - so read the
|
||||
// rest of the file, parse the playlist and return success.
|
||||
// It's not a local file so we have to fetch it to see what it is.
|
||||
// We use gstreamer to do this since it handles funky URLs for us (http://, ssh://, etc) and also has typefinder plugins.
|
||||
// First we wait for typefinder to tell us what it is. If it's not text/plain or text/uri-list assume it's a song and return success.
|
||||
// Otherwise wait to get 512 bytes of data and do magic on it - if the magic fails then we don't know what it is so return failure.
|
||||
// If the magic succeeds then we know for sure it's a playlist - so read the rest of the file, parse the playlist and return success.
|
||||
|
||||
timeout_timer_->start(timeout_);
|
||||
|
||||
|
||||
@@ -23,26 +23,32 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <glib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef HAVE_GSTREAMER
|
||||
#include <gst/gst.h>
|
||||
# include <gst/gst.h>
|
||||
#endif
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QThreadPool>
|
||||
#include <QByteArray>
|
||||
#include <QSet>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include <QTimer>
|
||||
|
||||
#include "song.h"
|
||||
#include "core/tagreaderclient.h"
|
||||
#include "musicbrainz/musicbrainzclient.h"
|
||||
|
||||
class CueParser;
|
||||
class CollectionBackendInterface;
|
||||
class ParserBase;
|
||||
class Player;
|
||||
class CollectionBackendInterface;
|
||||
class PlaylistParser;
|
||||
class ParserBase;
|
||||
class CueParser;
|
||||
|
||||
#if defined(HAVE_AUDIOCD) && defined(HAVE_GSTREAMER)
|
||||
class CddaSongLoader;
|
||||
#endif
|
||||
@@ -67,16 +73,13 @@ class SongLoader : public QObject {
|
||||
int timeout() const { return timeout_; }
|
||||
void set_timeout(int msec) { timeout_ = msec; }
|
||||
|
||||
// If Success is returned the songs are fully loaded. If BlockingLoadRequired
|
||||
// is returned LoadFilenamesBlocking() needs to be called next.
|
||||
// If Success is returned the songs are fully loaded. If BlockingLoadRequired is returned LoadFilenamesBlocking() needs to be called next.
|
||||
Result Load(const QUrl &url);
|
||||
// Loads the files with only filenames. When finished, songs() contains a
|
||||
// complete list of all Song objects, but without metadata. This method is
|
||||
// blocking, do not call it from the UI thread.
|
||||
// Loads the files with only filenames. When finished, songs() contains a complete list of all Song objects, but without metadata.
|
||||
// This method is blocking, do not call it from the UI thread.
|
||||
void LoadFilenamesBlocking();
|
||||
// Completely load songs previously loaded with LoadFilenamesBlocking(). When
|
||||
// finished, the Song objects in songs() contain metadata now. This method is
|
||||
// blocking, do not call it from the UI thread.
|
||||
// Completely load songs previously loaded with LoadFilenamesBlocking().
|
||||
// When finished, the Song objects in songs() contain metadata now. This method is blocking, do not call it from the UI thread.
|
||||
void LoadMetadataBlocking();
|
||||
Result LoadAudioCD();
|
||||
|
||||
@@ -91,7 +94,7 @@ signals:
|
||||
#if defined(HAVE_AUDIOCD) && defined(HAVE_GSTREAMER)
|
||||
void AudioCDTracksLoadedSlot(const SongList &songs);
|
||||
void AudioCDTracksTagsLoaded(const SongList &songs);
|
||||
#endif // HAVE_AUDIOCD
|
||||
#endif // HAVE_AUDIOCD && HAVE_GSTREAMER
|
||||
|
||||
private:
|
||||
enum State { WaitingForType, WaitingForMagic, WaitingForData, Finished };
|
||||
@@ -105,7 +108,7 @@ signals:
|
||||
|
||||
#ifdef HAVE_GSTREAMER
|
||||
void LoadRemote();
|
||||
|
||||
|
||||
// GStreamer callbacks
|
||||
static void TypeFound(GstElement *typefind, uint probability, GstCaps *caps, void *self);
|
||||
static GstPadProbeReturn DataReady(GstPad*, GstPadProbeInfo *buf, gpointer self);
|
||||
@@ -117,7 +120,6 @@ signals:
|
||||
void EndOfStreamReached();
|
||||
void MagicReady();
|
||||
bool IsPipelinePlaying();
|
||||
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
@@ -20,12 +20,21 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QSet>
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QModelIndex>
|
||||
#include <QStandardItem>
|
||||
#include <QStandardItemModel>
|
||||
#include <QAbstractItemModel>
|
||||
#include <QMap>
|
||||
#include <QSet>
|
||||
#include <QString>
|
||||
#include <QImage>
|
||||
#include <QPixmap>
|
||||
#include <QIcon>
|
||||
|
||||
#include "standarditemiconloader.h"
|
||||
#include "covermanager/albumcoverloader.h"
|
||||
#include "standarditemiconloader.h"
|
||||
|
||||
StandardItemIconLoader::StandardItemIconLoader(AlbumCoverLoader *cover_loader, QObject *parent)
|
||||
: QObject(parent),
|
||||
@@ -34,13 +43,13 @@ StandardItemIconLoader::StandardItemIconLoader(AlbumCoverLoader *cover_loader, Q
|
||||
{
|
||||
cover_options_.desired_height_ = 16;
|
||||
|
||||
connect(cover_loader_, SIGNAL(ImageLoaded(quint64,QImage)), SLOT(ImageLoaded(quint64,QImage)));
|
||||
connect(cover_loader_, SIGNAL(ImageLoaded(quint64, QImage)), SLOT(ImageLoaded(quint64, QImage)));
|
||||
}
|
||||
|
||||
void StandardItemIconLoader::SetModel(QAbstractItemModel *model) {
|
||||
|
||||
if (model_) {
|
||||
disconnect(model_, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(RowsAboutToBeRemoved(QModelIndex,int,int)));
|
||||
disconnect(model_, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)), this, SLOT(RowsAboutToBeRemoved(QModelIndex, int, int)));
|
||||
}
|
||||
|
||||
model_ = model;
|
||||
@@ -50,19 +59,19 @@ void StandardItemIconLoader::SetModel(QAbstractItemModel *model) {
|
||||
|
||||
}
|
||||
|
||||
void StandardItemIconLoader::LoadIcon(const QString& art_automatic, const QString& art_manual, QStandardItem *for_item) {
|
||||
void StandardItemIconLoader::LoadIcon(const QString &art_automatic, const QString &art_manual, QStandardItem *for_item) {
|
||||
|
||||
const quint64 id = cover_loader_->LoadImageAsync(cover_options_, art_automatic, art_manual);
|
||||
pending_covers_[id] = for_item;
|
||||
|
||||
}
|
||||
|
||||
void StandardItemIconLoader::LoadIcon(const Song& song, QStandardItem *for_item) {
|
||||
void StandardItemIconLoader::LoadIcon(const Song &song, QStandardItem *for_item) {
|
||||
const quint64 id = cover_loader_->LoadImageAsync(cover_options_, song);
|
||||
pending_covers_[id] = for_item;
|
||||
}
|
||||
|
||||
void StandardItemIconLoader::RowsAboutToBeRemoved(const QModelIndex& parent, int begin, int end) {
|
||||
void StandardItemIconLoader::RowsAboutToBeRemoved(const QModelIndex &parent, int begin, int end) {
|
||||
|
||||
for (QMap<quint64, QStandardItem*>::iterator it = pending_covers_.begin() ; it != pending_covers_.end() ; ) {
|
||||
const QStandardItem *item = it.value();
|
||||
@@ -86,7 +95,7 @@ void StandardItemIconLoader::ModelReset() {
|
||||
|
||||
}
|
||||
|
||||
void StandardItemIconLoader::ImageLoaded(quint64 id, const QImage& image) {
|
||||
void StandardItemIconLoader::ImageLoaded(quint64 id, const QImage &image) {
|
||||
|
||||
QStandardItem *item = pending_covers_.take(id);
|
||||
if (!item) return;
|
||||
|
||||
@@ -23,17 +23,20 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QImage>
|
||||
#include <QStandardItem>
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
#include "covermanager/albumcoverloaderoptions.h"
|
||||
|
||||
class AlbumCoverLoader;
|
||||
class Song;
|
||||
class AlbumCoverLoader;
|
||||
|
||||
class QAbstractItemModel;
|
||||
class QModelIndex;
|
||||
class QStandardItem;
|
||||
|
||||
// Uses an AlbumCoverLoader to asynchronously load and set an icon on a QStandardItem.
|
||||
class StandardItemIconLoader : public QObject {
|
||||
@@ -46,8 +49,7 @@ class StandardItemIconLoader : public QObject {
|
||||
|
||||
void SetModel(QAbstractItemModel *model);
|
||||
|
||||
void LoadIcon(const QString &art_automatic, const QString &art_manual,
|
||||
QStandardItem *for_item);
|
||||
void LoadIcon(const QString &art_automatic, const QString &art_manual, QStandardItem *for_item);
|
||||
void LoadIcon(const Song &song, QStandardItem *for_item);
|
||||
|
||||
private slots:
|
||||
|
||||
@@ -20,11 +20,17 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "stylesheetloader.h"
|
||||
#include "core/logging.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include <QIODevice>
|
||||
#include <QFile>
|
||||
#include <QEvent>
|
||||
#include <QString>
|
||||
#include <QColor>
|
||||
#include <QPalette>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "stylesheetloader.h"
|
||||
|
||||
StyleSheetLoader::StyleSheetLoader(QObject *parent) : QObject(parent) {}
|
||||
|
||||
|
||||
@@ -23,18 +23,21 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QPalette>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include <QEvent>
|
||||
#include <QMap>
|
||||
#include <QPalette>
|
||||
#include <QString>
|
||||
|
||||
class StyleSheetLoader : public QObject {
|
||||
public:
|
||||
explicit StyleSheetLoader(QObject *parent = nullptr);
|
||||
|
||||
// Sets the given stylesheet on the given widget.
|
||||
// If the stylesheet contains strings like %palette-[role], these get replaced
|
||||
// with actual palette colours.
|
||||
// If the stylesheet contains strings like %palette-[role], these get replaced with actual palette colours.
|
||||
// The stylesheet is reloaded when the widget's palette changes.
|
||||
void SetStyleSheet(QWidget *widget, const QString& filename);
|
||||
|
||||
@@ -43,7 +46,7 @@ class StyleSheetLoader : public QObject {
|
||||
|
||||
private:
|
||||
void UpdateStyleSheet(QWidget *widget);
|
||||
void ReplaceColor(QString *css, const QString& name, const QPalette& palette, QPalette::ColorRole role) const;
|
||||
void ReplaceColor(QString *css, const QString& name, const QPalette &palette, QPalette::ColorRole role) const;
|
||||
|
||||
private:
|
||||
QMap<QWidget *, QString> filenames_;
|
||||
|
||||
@@ -22,14 +22,14 @@
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QEvent>
|
||||
#include <QWheelEvent>
|
||||
#include <QObject>
|
||||
#include <QPixmap>
|
||||
#include <QPainter>
|
||||
#include <QWidget>
|
||||
#include <QtDebug>
|
||||
#include <QPoint>
|
||||
#include <QPolygon>
|
||||
#include <QRect>
|
||||
#include <QVector>
|
||||
|
||||
#include "macsystemtrayicon.h"
|
||||
#include "qtsystemtrayicon.h"
|
||||
#include "systemtrayicon.h"
|
||||
|
||||
|
||||
@@ -23,10 +23,13 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QPixmap>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QPixmap>
|
||||
#include <QAction>
|
||||
|
||||
class QAction;
|
||||
class Song;
|
||||
|
||||
class SystemTrayIcon : public QObject {
|
||||
@@ -43,10 +46,7 @@ class SystemTrayIcon : public QObject {
|
||||
|
||||
// Called by the OSD
|
||||
virtual void ShowPopup(const QString &summary, const QString &message, int timeout) {}
|
||||
/**
|
||||
* If this get's invoked with image_path equal to nullptr, the tooltip should
|
||||
* still be shown - just without the cover art.
|
||||
*/
|
||||
// If this get's invoked with image_path equal to nullptr, the tooltip should still be shown - just without the cover art.
|
||||
virtual void SetNowPlaying(const Song &song, const QString &image_path) {}
|
||||
virtual void ClearNowPlaying() {}
|
||||
|
||||
|
||||
@@ -20,14 +20,21 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "tagreaderclient.h"
|
||||
#include <string>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QFile>
|
||||
#include <QProcess>
|
||||
#include <QTcpServer>
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include <QUrl>
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QImage>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "core/workerpool.h"
|
||||
|
||||
#include "song.h"
|
||||
#include "tagreaderclient.h"
|
||||
|
||||
const char *TagReaderClient::kWorkerExecutableName = "strawberry-tagreader";
|
||||
TagReaderClient *TagReaderClient::sInstance = nullptr;
|
||||
|
||||
@@ -23,15 +23,21 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "song.h"
|
||||
#include "tagreadermessages.pb.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QImage>
|
||||
|
||||
#include "core/messagehandler.h"
|
||||
#include "core/workerpool.h"
|
||||
|
||||
#include <QStringList>
|
||||
#include "song.h"
|
||||
#include "tagreadermessages.pb.h"
|
||||
|
||||
class QLocalServer;
|
||||
class QProcess;
|
||||
class Song;
|
||||
template <typename HandlerType> class WorkerPool;
|
||||
|
||||
class TagReaderClient : public QObject {
|
||||
Q_OBJECT
|
||||
@@ -51,9 +57,8 @@ class TagReaderClient : public QObject {
|
||||
ReplyType *IsMediaFile(const QString &filename);
|
||||
ReplyType *LoadEmbeddedArt(const QString &filename);
|
||||
|
||||
// Convenience functions that call the above functions and wait for a
|
||||
// response. These block the calling thread with a semaphore, and must NOT
|
||||
// be called from the TagReaderClient's thread.
|
||||
// Convenience functions that call the above functions and wait for a response.
|
||||
// These block the calling thread with a semaphore, and must NOT be called from the TagReaderClient's thread.
|
||||
void ReadFileBlocking(const QString &filename, Song *song);
|
||||
bool SaveFileBlocking(const QString &filename, const Song &metadata);
|
||||
bool IsMediaFileBlocking(const QString &filename);
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
#include "taskmanager.h"
|
||||
|
||||
TaskManager::TaskManager(QObject *parent) : QObject(parent), next_task_id_(1) {}
|
||||
|
||||
@@ -23,9 +23,14 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QMutex>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
|
||||
class TaskManager : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QThread>
|
||||
|
||||
#include "thread.h"
|
||||
#include "utilities.h"
|
||||
|
||||
void Thread::run() {
|
||||
Utilities::SetThreadIOPriority(io_priority_);
|
||||
|
||||
@@ -20,8 +20,10 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include "core/utilities.h"
|
||||
|
||||
#include "utilities.h"
|
||||
|
||||
// Improve QThread by adding a SetIoPriority function
|
||||
class Thread : public QThread {
|
||||
|
||||
@@ -17,8 +17,14 @@
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QUrl>
|
||||
#include <QIcon>
|
||||
|
||||
#include "urlhandler.h"
|
||||
|
||||
UrlHandler::LoadResult::LoadResult(const QUrl &original_url, Type type, const QUrl &media_url, qint64 length_nanosec) : original_url_(original_url), type_(type), media_url_(media_url), length_nanosec_(length_nanosec) {}
|
||||
|
||||
@@ -23,9 +23,11 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QIcon>
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include <QIcon>
|
||||
|
||||
class UrlHandler : public QObject {
|
||||
Q_OBJECT
|
||||
@@ -37,17 +39,14 @@ class UrlHandler : public QObject {
|
||||
virtual QString scheme() const = 0;
|
||||
virtual QIcon icon() const;
|
||||
|
||||
// Returned by StartLoading() and LoadNext(), indicates what the player
|
||||
// should do when it wants to load a URL.
|
||||
// Returned by StartLoading() and LoadNext(), indicates what the player should do when it wants to load a URL.
|
||||
struct LoadResult {
|
||||
enum Type {
|
||||
// There wasn't a track available, and the player should move on to the
|
||||
// next playlist item.
|
||||
// There wasn't a track available, and the player should move on to the next playlist item.
|
||||
NoMoreTracks,
|
||||
|
||||
// There might be another track available but the handler needs to do some
|
||||
// work (eg. fetching a remote playlist) to find out. AsyncLoadComplete
|
||||
// will be emitted later with the same original_url.
|
||||
// There might be another track available but the handler needs to do some work (eg. fetching a remote playlist) to find out.
|
||||
// AsyncLoadComplete will be emitted later with the same original_url.
|
||||
WillLoadAsynchronously,
|
||||
|
||||
// There was a track available. Its url is in media_url.
|
||||
@@ -69,12 +68,10 @@ class UrlHandler : public QObject {
|
||||
qint64 length_nanosec_;
|
||||
};
|
||||
|
||||
// Called by the Player when a song starts loading - gives the handler
|
||||
// a chance to do something clever to get a playable track.
|
||||
// Called by the Player when a song starts loading - gives the handler a chance to do something clever to get a playable track.
|
||||
virtual LoadResult StartLoading(const QUrl &url) { return LoadResult(url); }
|
||||
|
||||
// Called by the player when a song finishes - gives the handler a chance to
|
||||
// get another track to play.
|
||||
// Called by the player when a song finishes - gives the handler a chance to get another track to play.
|
||||
virtual LoadResult LoadNext(const QUrl &url) { return LoadResult(url); }
|
||||
|
||||
// Functions to be warned when something happen to a track handled by UrlHandler.
|
||||
@@ -86,4 +83,3 @@ signals:
|
||||
};
|
||||
|
||||
#endif // URLHANDLER_H
|
||||
|
||||
|
||||
@@ -23,22 +23,40 @@
|
||||
#include <memory>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QApplication>
|
||||
#include <QCoreApplication>
|
||||
#include <QWidget>
|
||||
#include <QObject>
|
||||
#include <QIODevice>
|
||||
#include <QByteArray>
|
||||
#include <QMetaObject>
|
||||
#include <QChar>
|
||||
#include <QCryptographicHash>
|
||||
#include <QDate>
|
||||
#include <QDateTime>
|
||||
#include <QDesktopServices>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QIODevice>
|
||||
#include <QMetaEnum>
|
||||
#include <QMouseEvent>
|
||||
#include <QFileInfo>
|
||||
#include <QHostAddress>
|
||||
#include <QPoint>
|
||||
#include <QRect>
|
||||
#include <QSize>
|
||||
#include <QMap>
|
||||
#include <QList>
|
||||
#include <QSet>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QRegExp>
|
||||
#include <QTcpServer>
|
||||
#include <QtDebug>
|
||||
#include <QTemporaryFile>
|
||||
#include <QtGlobal>
|
||||
#include <QUrl>
|
||||
#include <QWidget>
|
||||
#include <QMetaEnum>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QSettings>
|
||||
#include <QtEvents>
|
||||
#include <QtDebug>
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
#include <unistd.h>
|
||||
@@ -56,23 +74,25 @@
|
||||
|
||||
#ifdef Q_OS_DARWIN
|
||||
#include <QProcess>
|
||||
|
||||
#include "CoreServices/CoreServices.h"
|
||||
#include "IOKit/ps/IOPowerSources.h"
|
||||
#include "IOKit/ps/IOPSKeys.h"
|
||||
#include "IOKit/ps/IOPowerSources.h"
|
||||
#elif defined(Q_OS_WIN32)
|
||||
#include <QProcess>
|
||||
#endif
|
||||
|
||||
#include "utilities.h"
|
||||
#include "core/application.h"
|
||||
#include "core/logging.h"
|
||||
#include "timeconstants.h"
|
||||
|
||||
#include "utilities.h"
|
||||
#include "sha2.h"
|
||||
#include "timeconstants.h"
|
||||
#include "application.h"
|
||||
|
||||
#ifdef Q_OS_DARWIN
|
||||
#include "core/mac_startup.h"
|
||||
#include "core/mac_utilities.h"
|
||||
#include "core/scoped_cftyperef.h"
|
||||
#include "mac_startup.h"
|
||||
#include "mac_utilities.h"
|
||||
#include "scoped_cftyperef.h"
|
||||
#endif
|
||||
|
||||
namespace Utilities {
|
||||
@@ -379,8 +399,7 @@ void OpenInFileBrowser(const QList<QUrl> &urls) {
|
||||
dirs.insert(directory);
|
||||
qLog(Debug) << path;
|
||||
#ifdef Q_OS_DARWIN
|
||||
// revealing multiple files in the finder only opens one window,
|
||||
// so it also makes sense to reveal at most one per directory
|
||||
// Revealing multiple files in the finder only opens one window, so it also makes sense to reveal at most one per directory
|
||||
RevealFileInFinder(path);
|
||||
#elif defined(Q_OS_WIN32)
|
||||
ShowFileInExplorer(path);
|
||||
@@ -407,8 +426,7 @@ QByteArray Hmac(const QByteArray &key, const QByteArray &data, HashFunction meth
|
||||
return QCryptographicHash::hash(outer_padding + QCryptographicHash::hash(inner_padding + data, QCryptographicHash::Md5), QCryptographicHash::Md5);
|
||||
}
|
||||
else if (Sha1_Algo == method) {
|
||||
return
|
||||
QCryptographicHash::hash(outer_padding + QCryptographicHash::hash(inner_padding + data, QCryptographicHash::Sha1), QCryptographicHash::Sha1);
|
||||
return QCryptographicHash::hash(outer_padding + QCryptographicHash::hash(inner_padding + data, QCryptographicHash::Sha1), QCryptographicHash::Sha1);
|
||||
}
|
||||
else { // Sha256_Algo, currently default
|
||||
return Sha256(outer_padding + Sha256(inner_padding + data));
|
||||
@@ -473,6 +491,8 @@ QByteArray Sha1CoverHash(const QString &artist, const QString &album) {
|
||||
QCryptographicHash hash(QCryptographicHash::Sha1);
|
||||
hash.addData(artist.toLower().toUtf8().constData());
|
||||
hash.addData(album.toLower().toUtf8().constData());
|
||||
|
||||
//qLog(Debug) << artist << album << hash.result();
|
||||
|
||||
return hash.result();
|
||||
|
||||
@@ -538,8 +558,7 @@ bool ParseUntilElement(QXmlStreamReader *reader, const QString &name) {
|
||||
|
||||
QDateTime ParseRFC822DateTime(const QString &text) {
|
||||
|
||||
QRegExp regexp(
|
||||
"(\\d{1,2}) (\\w{3,12}) (\\d+) (\\d{1,2}):(\\d{1,2}):(\\d{1,2})");
|
||||
QRegExp regexp("(\\d{1,2}) (\\w{3,12}) (\\d+) (\\d{1,2}):(\\d{1,2}):(\\d{1,2})");
|
||||
if (regexp.indexIn(text) == -1) {
|
||||
return QDateTime();
|
||||
}
|
||||
@@ -622,11 +641,9 @@ QString DecodeHtmlEntities(const QString &text) {
|
||||
int SetThreadIOPriority(IoPriority priority) {
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
return syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, GetThreadId(),
|
||||
4 | priority << IOPRIO_CLASS_SHIFT);
|
||||
return syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, GetThreadId(), 4 | priority << IOPRIO_CLASS_SHIFT);
|
||||
#elif defined(Q_OS_DARWIN)
|
||||
return setpriority(PRIO_DARWIN_THREAD, 0,
|
||||
priority == IOPRIO_CLASS_IDLE ? PRIO_DARWIN_BG : 0);
|
||||
return setpriority(PRIO_DARWIN_THREAD, 0, priority == IOPRIO_CLASS_IDLE ? PRIO_DARWIN_BG : 0);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
@@ -24,19 +24,24 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <memory>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QColor>
|
||||
#include <QtGlobal>
|
||||
#include <QWidget>
|
||||
#include <QIODevice>
|
||||
#include <QByteArray>
|
||||
#include <QFile>
|
||||
#include <QLocale>
|
||||
#include <QCryptographicHash>
|
||||
#include <QSize>
|
||||
#include <QDateTime>
|
||||
#include <QLocale>
|
||||
#include <QList>
|
||||
#include <QMetaObject>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QUrl>
|
||||
|
||||
class QIODevice;
|
||||
class QMouseEvent;
|
||||
class QXmlStreamReader;
|
||||
struct QMetaObject;
|
||||
#include <QColor>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QtEvents>
|
||||
|
||||
namespace Utilities {
|
||||
QString PrettyTime(int seconds);
|
||||
@@ -77,25 +82,21 @@ QByteArray Sha256(const QByteArray &data);
|
||||
QByteArray Sha1File(QFile &file);
|
||||
QByteArray Sha1CoverHash(const QString &artist, const QString &album);
|
||||
|
||||
// Picks an unused ephemeral port number. Doesn't hold the port open so
|
||||
// there's the obvious race condition
|
||||
// Picks an unused ephemeral port number. Doesn't hold the port open so there's the obvious race condition
|
||||
quint16 PickUnusedPort();
|
||||
|
||||
// Forwards a mouse event to a different widget, remapping the event's widget
|
||||
// coordinates relative to those of the target widget.
|
||||
// Forwards a mouse event to a different widget, remapping the event's widget coordinates relative to those of the target widget.
|
||||
void ForwardMouseEvent(const QMouseEvent *e, QWidget *target);
|
||||
|
||||
// Checks if the mouse event was inside the widget's rectangle.
|
||||
bool IsMouseEventInWidget(const QMouseEvent *e, const QWidget *widget);
|
||||
|
||||
// Reads all children of the current element, and returns with the stream
|
||||
// reader either on the EndElement for the current element, or the end of the
|
||||
// file - whichever came first.
|
||||
// Reads all children of the current element,
|
||||
// and returns with the stream reader either on the EndElement for the current element, or the end of the file - whichever came first.
|
||||
void ConsumeCurrentElement(QXmlStreamReader *reader);
|
||||
|
||||
// Advances the stream reader until it finds an element with the given name.
|
||||
// Returns false if the end of the document was reached before finding a
|
||||
// matching element.
|
||||
// Returns false if the end of the document was reached before finding a matching element.
|
||||
bool ParseUntilElement(QXmlStreamReader *reader, const QString &name);
|
||||
|
||||
// Parses a string containing an RFC822 time and date.
|
||||
@@ -105,8 +106,7 @@ QDateTime ParseRFC822DateTime(const QString &text);
|
||||
QString DecodeHtmlEntities(const QString &text);
|
||||
|
||||
// Shortcut for getting a Qt-aware enum value as a string.
|
||||
// Pass in the QMetaObject of the class that owns the enum, the string name of
|
||||
// the enum and a valid value from that enum.
|
||||
// Pass in the QMetaObject of the class that owns the enum, the string name of the enum and a valid value from that enum.
|
||||
const char *EnumToString(const QMetaObject &meta, const char *name, int value);
|
||||
|
||||
QStringList Prepend(const QString &text, const QStringList &list);
|
||||
@@ -172,4 +172,3 @@ class ScopedWCharArray {
|
||||
};
|
||||
|
||||
#endif // UTILITIES_H
|
||||
|
||||
|
||||
@@ -20,13 +20,13 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include <QList>
|
||||
#include <QPixmap>
|
||||
#include <QAction>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "windows7thumbbar.h"
|
||||
|
||||
#include "core/logging.h"
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0600
|
||||
@@ -34,13 +34,15 @@
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#include <shobjidl.h>
|
||||
extern HICON qt_pixmapToWinHICON(const QPixmap &p);
|
||||
extern HICON qt_pixmapToWinHICON(const QPixmap &p);
|
||||
#endif // Q_OS_WIN32
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "windows7thumbbar.h"
|
||||
|
||||
const int Windows7ThumbBar::kIconSize = 16;
|
||||
const int Windows7ThumbBar::kMaxButtonCount = 7;
|
||||
|
||||
|
||||
Windows7ThumbBar::Windows7ThumbBar(QWidget *widget)
|
||||
: QObject(widget),
|
||||
widget_(widget),
|
||||
|
||||
@@ -23,8 +23,11 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QAction>
|
||||
|
||||
#ifndef Q_OS_WIN32
|
||||
typedef void MSG;
|
||||
@@ -34,15 +37,13 @@ class Windows7ThumbBar : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
// Creates a list of buttons in the taskbar icon for this window. Does
|
||||
// nothing and is safe to use on other operating systems too.
|
||||
// Creates a list of buttons in the taskbar icon for this window. Does nothing and is safe to use on other operating systems too.
|
||||
Windows7ThumbBar(QWidget *widget = 0);
|
||||
|
||||
static const int kIconSize;
|
||||
static const int kMaxButtonCount;
|
||||
|
||||
// You must call this in the parent widget's constructor before returning
|
||||
// to the event loop. If an action is nullptr it becomes a spacer.
|
||||
// You must call this in the parent widget's constructor before returning to the event loop. If an action is nullptr it becomes a spacer.
|
||||
void SetActions(const QList<QAction*> &actions);
|
||||
|
||||
// Call this from the parent's winEvent() function.
|
||||
@@ -58,7 +59,7 @@ private:
|
||||
unsigned int button_created_message_id_;
|
||||
|
||||
// Really an ITaskbarList3* but I don't want to have to include windows.h here
|
||||
void* taskbar_list_;
|
||||
void *taskbar_list_;
|
||||
};
|
||||
|
||||
#endif // WINDOWS7THUMBBAR_H
|
||||
|
||||
Reference in New Issue
Block a user