Compare commits

...

13 Commits

Author SHA1 Message Date
Jonas Kvinge
df0ec6b709 Release 1.2.2 2024-11-23 17:25:42 +01:00
Jonas Kvinge
376af26f0e Playlist: Move new QMimeData 2024-11-23 15:19:31 +01:00
Jonas Kvinge
9bff55e1ee PlaylistView: Ignore invalid QHeaderView::sectionResized
Workaround a possible Qt bug: moving a song in the playlist triggers `QHeaderView::sectionResized` with the state reset for each column, this causes an an invalid state for the last column since SetHeaderState is called before the last column state is restored, which again is used when restoring the playlist columns after switching to different playlist. To workaround this, only call SetHeaderState when the new column size is not zero.
2024-11-23 11:07:15 +01:00
Jonas Kvinge
8f7e29f503 PlaylistView: Use constants 2024-11-23 10:56:29 +01:00
Jonas Kvinge
c3aa885a0f SmartPlaylistSearchPreview: Remove early SetItemDelegates
It's called too early before MoodbarLoader is set, Init() already calls SetItemDelegates.

Fixes #1609
2024-11-22 17:04:42 +01:00
Jonas Kvinge
77ea5729c3 Turn on git revision 2024-11-21 18:34:29 +01:00
Jonas Kvinge
fac323a4a5 Release 1.2.1 2024-11-21 16:05:21 +01:00
Jonas Kvinge
a26066d70f Disconnect tagreader reply metaobject connection in lambda
Otherwise the tagreader reply is deleted to early causing crashes.
2024-11-21 15:59:07 +01:00
Strawberry Bot
d500d38e63 Update translations 2024-11-20 19:10:59 +01:00
Jonas Kvinge
295d4d9d05 Update strawberry_en_US.ts 2024-11-20 19:09:45 +01:00
Jonas Kvinge
01aaa0ba0b Disable SPMediaKeyTap
Workaround issue #1606
2024-11-20 18:12:20 +01:00
Jonas Kvinge
7b23118475 BehaviourSettingsPage: Disable song progress on taskbar for macOS 2024-11-19 06:52:23 +01:00
Jonas Kvinge
0c7806ab0a Turn on git revision 2024-11-17 07:34:18 +01:00
22 changed files with 444 additions and 474 deletions

View File

@@ -271,9 +271,9 @@ else()
add_definitions(-DKDSINGLEAPPLICATION_STATIC_BUILD)
endif()
if(APPLE)
find_package(SPMediaKeyTap REQUIRED)
endif()
# if(APPLE)
# find_package(SPMediaKeyTap REQUIRED)
# endif()
if(WIN32)
find_package(getopt-win REQUIRED)
@@ -1537,7 +1537,6 @@ if(APPLE)
"-framework DiskArbitration"
"-framework IOKit"
"-framework ScriptingBridge"
SPMediaKeyTap
)
endif()

View File

@@ -2,7 +2,14 @@ Strawberry Music Player
=======================
ChangeLog
Version 1.2.1-rc1 (2024.11.16):
Version 1.2.2 (2024.11.23):
Bugfixes:
* Fixed crash when creating a new smart playlist (#1609).
* Fixed last playlist column being added when dragging a song and switching playlists.
Version 1.2.1 (2024.11.21):
This release features major restructuring of the codebase, moving source files,
rewriting CMake build files, dropping Qt 5 support, external tagreader,
@@ -19,6 +26,8 @@ and dropping some unmaintained parts such as VLC.
* Fixed crash when enabling Tidal, Spotify, Qobuz or Subsonic services.
* Fixed passing filenames to strawberry on command line not resolving to absolute paths.
* (macOS) Fixed program not starting for users with long usernames.
* (macoS) Fixed crash when pressing caps lock (#1606).
* (macOS) Remove "song progress on taskbar" option in behaviour settings.
Enhancements:

View File

@@ -1,7 +1,7 @@
set(STRAWBERRY_VERSION_MAJOR 1)
set(STRAWBERRY_VERSION_MINOR 2)
set(STRAWBERRY_VERSION_PATCH 1)
set(STRAWBERRY_VERSION_PRERELEASE rc1)
set(STRAWBERRY_VERSION_PATCH 2)
#set(STRAWBERRY_VERSION_PRERELEASE rc1)
set(INCLUDE_GIT_REVISION OFF)

View File

@@ -51,6 +51,8 @@
</screenshots>
<update_contact>eclipseo@fedoraproject.org</update_contact>
<releases>
<release version="1.2.2" date="2024-11-23"/>
<release version="1.2.1" date="2024-11-21"/>
<release version="1.1.3" date="2024-09-21"/>
<release version="1.1.2" date="2024-09-12"/>
<release version="1.1.1" date="2024-07-22"/>

View File

@@ -41,7 +41,7 @@
#import <QuartzCore/CALayer.h>
#import <SPMediaKeyTap.h>
//#import <SPMediaKeyTap.h>
#include "config.h"
@@ -145,18 +145,18 @@ QDebug operator<<(QDebug dbg, NSObject *object) {
[[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleURLEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL];
key_tap_ = [[SPMediaKeyTap alloc] initWithDelegate:self];
if ([SPMediaKeyTap usesGlobalMediaKeyTap]) {
if ([key_tap_ startWatchingMediaKeys]) {
qLog(Debug) << "Media key monitoring started";
}
else {
qLog(Warning) << "Failed to start media key monitoring";
}
}
else {
qLog(Warning) << "Media key monitoring disabled";
}
// key_tap_ = [[SPMediaKeyTap alloc] initWithDelegate:self];
// if ([SPMediaKeyTap usesGlobalMediaKeyTap]) {
// if ([key_tap_ startWatchingMediaKeys]) {
// qLog(Debug) << "Media key monitoring started";
// }
// else {
// qLog(Warning) << "Failed to start media key monitoring";
// }
// }
// else {
// qLog(Warning) << "Media key monitoring disabled";
// }
}
@@ -192,10 +192,10 @@ QDebug operator<<(QDebug dbg, NSObject *object) {
}
- (void) mediaKeyTap: (SPMediaKeyTap*)keyTap receivedMediaKeyEvent:(NSEvent*)event {
#pragma unused(keyTap)
[self handleMediaEvent:event];
}
// - (void) mediaKeyTap: (SPMediaKeyTap*)keyTap receivedMediaKeyEvent:(NSEvent*)event {
// #pragma unused(keyTap)
// [self handleMediaEvent:event];
// }
- (BOOL) handleMediaEvent:(NSEvent*)event {
// if it is not a media key event, then ignore

View File

@@ -2197,7 +2197,11 @@ void MainWindow::RenumberTracks() {
song.set_track(track);
TagReaderReplyPtr reply = app_->tagreader_client()->WriteFileAsync(song.url().toLocalFile(), song);
QPersistentModelIndex persistent_index = QPersistentModelIndex(source_index);
QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, persistent_index]() { SongSaveComplete(reply, persistent_index); }, Qt::QueuedConnection);
SharedPtr<QMetaObject::Connection> connection = make_shared<QMetaObject::Connection>();
*connection = QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, persistent_index, connection]() {
SongSaveComplete(reply, persistent_index);
QObject::disconnect(*connection);
}, Qt::QueuedConnection);
}
++track;
}
@@ -2228,7 +2232,11 @@ void MainWindow::SelectionSetValue() {
if (song.url().isLocalFile() && Playlist::set_column_value(song, column, column_value)) {
TagReaderReplyPtr reply = app_->tagreader_client()->WriteFileAsync(song.url().toLocalFile(), song);
QPersistentModelIndex persistent_index = QPersistentModelIndex(source_index);
QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, persistent_index]() { SongSaveComplete(reply, persistent_index); }, Qt::QueuedConnection);
SharedPtr<QMetaObject::Connection> connection = make_shared<QMetaObject::Connection>();
*connection = QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, persistent_index, connection]() {
SongSaveComplete(reply, persistent_index);
QObject::disconnect(*connection);
}, Qt::QueuedConnection);
}
else if (song.source() == Song::Source::Stream) {
app_->playlist_manager()->current()->setData(source_index, column_value, 0);

View File

@@ -22,6 +22,7 @@
#include "config.h"
#include <utility>
#include <memory>
#include <QtGlobal>
#include <QGuiApplication>
@@ -79,6 +80,7 @@
#include "coverfromurldialog.h"
#include "currentalbumcoverloader.h"
using std::make_shared;
using namespace Qt::Literals::StringLiterals;
QSet<QString> *AlbumCoverChoiceController::sImageExtensions = nullptr;
@@ -743,7 +745,11 @@ void AlbumCoverChoiceController::SaveCoverEmbeddedToSong(const Song &song, const
cover_save_tasks_.append(song);
const bool art_embedded = !image_data.isNull();
TagReaderReplyPtr reply = tagreader_client_->SaveCoverAsync(song.url().toLocalFile(), SaveTagCoverData(cover_filename, image_data, mime_type));
QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, song, art_embedded]() { SaveEmbeddedCoverFinished(reply, song, art_embedded); });
SharedPtr<QMetaObject::Connection> connection = make_shared<QMetaObject::Connection>();
*connection = QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, song, art_embedded, connection]() {
SaveEmbeddedCoverFinished(reply, song, art_embedded);
QObject::disconnect(*connection);
});
}

View File

@@ -24,6 +24,7 @@
#include <algorithm>
#include <utility>
#include <chrono>
#include <memory>
#include <QObject>
#include <QMainWindow>
@@ -96,6 +97,7 @@
using namespace std::literals::chrono_literals;
using namespace Qt::Literals::StringLiterals;
using std::make_shared;
namespace {
constexpr char kSettingsGroup[] = "CoverManager";
@@ -855,8 +857,10 @@ void AlbumCoverManager::SaveImageToAlbums(Song *song, const AlbumCoverImageResul
for (const QUrl &url : std::as_const(album_item->urls)) {
const bool art_embedded = !result.image_data.isEmpty();
TagReaderReplyPtr reply = tagreader_client_->SaveCoverAsync(url.toLocalFile(), SaveTagCoverData(result.image_data, result.mime_type));
QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, album_item, url, art_embedded]() {
SharedPtr<QMetaObject::Connection> connection = make_shared<QMetaObject::Connection>();
*connection = QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, album_item, url, art_embedded, connection]() {
SaveEmbeddedCoverFinished(reply, album_item, url, art_embedded);
QObject::disconnect(*connection);
});
cover_save_tasks_.insert(album_item, url);
}
@@ -1005,8 +1009,10 @@ void AlbumCoverManager::SaveAndSetCover(AlbumItem *album_item, const AlbumCoverI
for (const QUrl &url : urls) {
const bool art_embedded = !result.image_data.isEmpty();
TagReaderReplyPtr reply = tagreader_client_->SaveCoverAsync(url.toLocalFile(), SaveTagCoverData(result.cover_url.isValid() ? result.cover_url.toLocalFile() : QString(), result.image_data, result.mime_type));
QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, album_item, url, art_embedded]() {
SharedPtr<QMetaObject::Connection> connection = std::make_shared<QMetaObject::Connection>();
*connection = QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, album_item, url, art_embedded, connection]() {
SaveEmbeddedCoverFinished(reply, album_item, url, art_embedded);
QObject::disconnect(*connection);
});
cover_save_tasks_.insert(album_item, url);
}

View File

@@ -26,6 +26,7 @@
#include <functional>
#include <iterator>
#include <limits>
#include <memory>
#include <QtGlobal>
#include <QtConcurrentRun>
@@ -99,6 +100,7 @@
#include "edittagdialog.h"
#include "ui_edittagdialog.h"
using std::make_shared;
using namespace Qt::Literals::StringLiterals;
namespace {
@@ -1311,7 +1313,11 @@ void EditTagDialog::SaveData() {
save_tags_options |= TagReaderClient::SaveOption::Cover;
}
TagReaderReplyPtr reply = tagreader_client_->WriteFileAsync(ref.current_.url().toLocalFile(), ref.current_, save_tags_options, save_tag_cover_data);
QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, ref]() { SongSaveTagsComplete(reply, ref.current_.url().toLocalFile(), ref.current_, ref.cover_action_); }, Qt::QueuedConnection);
SharedPtr<QMetaObject::Connection> connection = make_shared<QMetaObject::Connection>();
*connection = QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, ref, connection]() {
SongSaveTagsComplete(reply, ref.current_.url().toLocalFile(), ref.current_, ref.cover_action_);
QObject::disconnect(*connection);
}, Qt::QueuedConnection);
}
// If the cover was changed, but no tags written, make sure to update the collection.
else if (ref.cover_action_ != UpdateCoverAction::None && !ref.current_.effective_albumartist().isEmpty() && !ref.current_.album().isEmpty()) {

View File

@@ -4,13 +4,13 @@
#include "globalshortcuts/globalshortcutsbackend-macos.h"
class PlatformInterface;
@class SPMediaKeyTap;
//@class SPMediaKeyTap;
@interface AppDelegate : NSObject<NSApplicationDelegate, NSUserNotificationCenterDelegate> {
PlatformInterface *application_handler_;
NSMenu *dock_menu_;
GlobalShortcutsBackendMacOS *shortcut_handler_;
SPMediaKeyTap *key_tap_;
//SPMediaKeyTap *key_tap_;
}
@@ -29,5 +29,5 @@ class PlatformInterface;
- (void) setDockMenu: (NSMenu*)menu;
- (GlobalShortcutsBackendMacOS*) shortcut_handler;
- (void) setShortcutHandler: (GlobalShortcutsBackendMacOS*)backend;
- (void) mediaKeyTap: (SPMediaKeyTap*)keyTap receivedMediaKeyEvent:(NSEvent*)event;
//- (void) mediaKeyTap: (SPMediaKeyTap*)keyTap receivedMediaKeyEvent:(NSEvent*)event;
@end

View File

@@ -434,7 +434,11 @@ bool Playlist::setData(const QModelIndex &idx, const QVariant &value, const int
if (song.url().isLocalFile()) {
TagReaderReplyPtr reply = tagreader_client_->WriteFileAsync(song.url().toLocalFile(), song);
QPersistentModelIndex persistent_index = QPersistentModelIndex(idx);
QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, persistent_index, item]() { SongSaveComplete(reply, persistent_index, item->OriginalMetadata()); }, Qt::QueuedConnection);
SharedPtr<QMetaObject::Connection> connection = make_shared<QMetaObject::Connection>();
*connection = QObject::connect(&*reply, &TagReaderReply::Finished, this, [this, reply, persistent_index, item, connection]() {
SongSaveComplete(reply, persistent_index, item->OriginalMetadata());
QObject::disconnect(*connection);
}, Qt::QueuedConnection);
}
else if (song.is_radio()) {
item->SetMetadata(song);
@@ -1291,8 +1295,6 @@ QMimeData *Playlist::mimeData(const QModelIndexList &indexes) const {
// We only want one index per row, but we can't just take column 0 because the user might have hidden it.
const int first_column = indexes.first().column();
QMimeData *mimedata = new QMimeData;
QList<QUrl> urls;
QList<int> rows;
for (const QModelIndex &idx : indexes) {
@@ -1304,7 +1306,6 @@ QMimeData *Playlist::mimeData(const QModelIndexList &indexes) const {
QBuffer buf;
if (!buf.open(QIODevice::WriteOnly)) {
delete mimedata;
return nullptr;
}
QDataStream stream(&buf);
@@ -1317,6 +1318,7 @@ QMimeData *Playlist::mimeData(const QModelIndexList &indexes) const {
stream.writeRawData(reinterpret_cast<const char*>(&pid), sizeof(pid));
buf.close();
QMimeData *mimedata = new QMimeData;
mimedata->setUrls(urls);
mimedata->setData(QLatin1String(kRowsMimetype), buf.data());

View File

@@ -150,7 +150,7 @@ PlaylistView::PlaylistView(QWidget *parent)
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
#endif
QObject::connect(header_, &PlaylistHeader::sectionResized, this, &PlaylistView::SetHeaderState);
QObject::connect(header_, &PlaylistHeader::sectionResized, this, &PlaylistView::HeaderSectionResized);
QObject::connect(header_, &PlaylistHeader::sectionMoved, this, &PlaylistView::SetHeaderState);
QObject::connect(header_, &PlaylistHeader::sortIndicatorChanged, this, &PlaylistView::SetHeaderState);
QObject::connect(header_, &PlaylistHeader::SectionVisibilityChanged, this, &PlaylistView::SetHeaderState);
@@ -423,6 +423,17 @@ void PlaylistView::RestoreHeaderState() {
}
void PlaylistView::HeaderSectionResized(const int logical_index, const int old_size, const int new_size) {
Q_UNUSED(logical_index)
Q_UNUSED(old_size)
if (new_size != 0) {
SetHeaderState();
}
}
void PlaylistView::ReloadBarPixmaps() {
currenttrack_bar_left_ = LoadBarPixmap(u":/pictures/currenttrack_bar_left.png"_s, true);
@@ -1294,9 +1305,9 @@ void PlaylistView::SaveSettings() {
Settings s;
s.beginGroup(PlaylistSettings::kSettingsGroup);
s.setValue("state_version", header_state_version_);
s.setValue("state", header_->SaveState());
s.setValue("column_alignments", QVariant::fromValue<ColumnAlignmentMap>(column_alignment_));
s.setValue(PlaylistSettings::kStateVersion, header_state_version_);
s.setValue(PlaylistSettings::kState, header_->SaveState());
s.setValue(PlaylistSettings::kColumnAlignments, QVariant::fromValue<ColumnAlignmentMap>(column_alignment_));
s.setValue(PlaylistSettings::kRatingLocked, rating_locked_);
s.endGroup();

View File

@@ -160,6 +160,7 @@ class PlaylistView : public QTreeView {
private Q_SLOTS:
void Update() { update(); }
void SetHeaderState();
void HeaderSectionResized(const int logical_index, const int old_size, const int new_size);
void InhibitAutoscrollTimeout();
void MaybeAutoscroll(const Playlist::AutoScroll autoscroll);
void InvalidateCachedCurrentPixmap();

View File

@@ -72,10 +72,10 @@ BehaviourSettingsPage::BehaviourSettingsPage(SettingsDialog *dialog, QWidget *pa
ui_->checkbox_showtrayicon->hide();
ui_->checkbox_trayicon_progress->hide();
ui_->groupbox_startup->hide();
#else
# ifndef HAVE_DBUS
#endif
#if !defined(HAVE_DBUS) || defined(Q_OS_MACOS)
ui_->checkbox_taskbar_progress->hide();
# endif
#endif
#ifdef HAVE_TRANSLATIONS
@@ -161,9 +161,10 @@ void BehaviourSettingsPage::Load() {
ui_->checkbox_trayicon_progress->setEnabled(systemtray_available && ui_->checkbox_showtrayicon->isChecked());
ui_->checkbox_trayicon_progress->setChecked(systemtray_available && ui_->checkbox_showtrayicon->isChecked() && s.value(kTrayIconProgress, false).toBool());
ui_->radiobutton_hide->setEnabled(systemtray_available && ui_->checkbox_showtrayicon->isChecked());
#ifdef HAVE_DBUS
ui_->checkbox_taskbar_progress->setChecked(s.value(kTaskbarProgress, true).toBool());
#endif
#if defined(HAVE_DBUS) && !defined(Q_OS_MACOS)
ui_->checkbox_taskbar_progress->setChecked(s.value(kTaskbarProgress, true).toBool());
#endif
ui_->checkbox_resumeplayback->setChecked(s.value(kResumePlayback, false).toBool());

View File

@@ -75,7 +75,6 @@ void SmartPlaylistSearchPreview::Init(const SharedPtr<Player> player,
model_ = new Playlist(nullptr, nullptr, nullptr, collection_backend_, nullptr, -1, QString(), false, this);
ui_->tree->setModel(model_);
ui_->tree->SetPlaylist(model_);
ui_->tree->SetItemDelegates();
ui_->tree->Init(player,
playlist_manager,

View File

@@ -384,8 +384,7 @@ void TagReaderClient::SaveSongsPlaycountAsync(const SongList &songs) {
Q_ASSERT(QThread::currentThread() != thread());
for (const Song &song : songs) {
TagReaderReplyPtr reply = SaveSongPlaycountAsync(song.url().toLocalFile(), song.playcount());
QObject::connect(&*reply, &TagReaderReply::Finished, &*reply, &TagReaderReply::deleteLater);
SaveSongPlaycountAsync(song.url().toLocalFile(), song.playcount());
}
}
@@ -418,8 +417,7 @@ void TagReaderClient::SaveSongsRatingAsync(const SongList &songs) {
Q_ASSERT(QThread::currentThread() != thread());
for (const Song &song : songs) {
TagReaderReplyPtr reply = SaveSongRatingAsync(song.url().toLocalFile(), song.rating());
QObject::connect(&*reply, &TagReaderReply::Finished, &*reply, &TagReaderReply::deleteLater);
SaveSongRatingAsync(song.url().toLocalFile(), song.rating());
}
}

View File

@@ -40,7 +40,4 @@ void TagReaderLoadCoverDataReply::EmitFinished() {
Q_EMIT TagReaderReply::Finished(filename_, result_);
Q_EMIT TagReaderLoadCoverDataReply::Finished(filename_, data_, result_);
QObject::disconnect(this, &TagReaderReply::Finished, nullptr, nullptr);
QObject::disconnect(this, &TagReaderLoadCoverDataReply::Finished, nullptr, nullptr);
}

View File

@@ -40,7 +40,4 @@ void TagReaderLoadCoverImageReply::EmitFinished() {
Q_EMIT TagReaderReply::Finished(filename_, result_);
Q_EMIT TagReaderLoadCoverImageReply::Finished(filename_, image_, result_);
QObject::disconnect(this, &TagReaderReply::Finished, nullptr, nullptr);
QObject::disconnect(this, &TagReaderLoadCoverImageReply::Finished, nullptr, nullptr);
}

View File

@@ -40,7 +40,4 @@ void TagReaderReadFileReply::EmitFinished() {
Q_EMIT TagReaderReply::Finished(filename_, result_);
Q_EMIT TagReaderReadFileReply::Finished(filename_, song_, result_);
QObject::disconnect(this, &TagReaderReply::Finished, nullptr, nullptr);
QObject::disconnect(this, &TagReaderReadFileReply::Finished, nullptr, nullptr);
}

View File

@@ -52,6 +52,4 @@ void TagReaderReply::EmitFinished() {
Q_EMIT TagReaderReply::Finished(filename_, result_);
QObject::disconnect(this, &TagReaderReply::Finished, nullptr, nullptr);
}

View File

@@ -77,18 +77,6 @@
</context>
<context>
<name>AlbumCoverChoiceController</name>
<message>
<source>Images (*.png *.jpg *.jpeg *.bmp *.gif *.xpm *.pbm *.pgm *.ppm *.xbm)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Images (*.png *.jpg *.jpeg *.bmp *.xpm *.pbm *.ppm *.xbm)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>All files (*)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Load cover from disk...</source>
<translation type="unfinished"></translation>
@@ -551,10 +539,6 @@
<source>Output</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Engine</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>ALSA plugin:</source>
<translation type="unfinished"></translation>
@@ -1004,6 +988,13 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>CollectionLibrary</name>
<message>
<source>Saving playcounts and ratings</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>CollectionModel</name>
<message>
@@ -2703,22 +2694,10 @@ If there are no matches then it will use the largest image in the directory.</so
<source>Global Shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Use Gnome (GSD) shortcuts when available</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Open...</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Use MATE shortcuts when available</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Use KDE (KGlobalAccel) shortcuts when available</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Use X11 shortcuts when available</source>
<translation type="unfinished"></translation>
@@ -2757,27 +2736,11 @@ If there are no matches then it will use the largest image in the directory.</so
<translation type="unfinished"></translation>
</message>
<message>
<source>The &quot;%1&quot; command could not be started.</source>
<source>Use KGlobalAccel shortcuts when available</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Using X11 shortcuts on %1 is not recommended and can cause keyboard to become unresponsive!</source>
<translation type="unfinished"></translation>
</message>
<message>
<source> Shortcuts on %1 are usually used through MPRIS and KGlobalAccel.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source> Shortcuts on %1 are usually used through Gnome Settings Daemon and should be configured in gnome-settings-daemon instead.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source> Shortcuts on %1 are usually used through Gnome Settings Daemon and should be configured in cinnamon-settings-daemon instead.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source> Shortcuts on %1 are usually used through MATE Settings Daemon and should be configured there instead.</source>
<source>Using X11 shortcuts is not recommended and can cause keyboard to become unresponsive! Shortcuts on should usually be used through MPRIS2 / KGlobalAccel.</source>
<translation type="unfinished"></translation>
</message>
</context>
@@ -3374,10 +3337,6 @@ If there are no matches then it will use the largest image in the directory.</so
<source>Import data from last.fm...</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>All Files (*)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Context</source>
<translation type="unfinished"></translation>
@@ -4565,14 +4524,6 @@ If there are no matches then it will use the largest image in the directory.</so
<numerusform></numerusform>
</translation>
</message>
<message>
<source>Unknown</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Various artists</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PlaylistParser</name>
@@ -4826,50 +4777,6 @@ Are you sure you want to continue?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PlaylistUndoCommands::InsertItems</name>
<message numerus="yes">
<source>add %n songs</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
</context>
<context>
<name>PlaylistUndoCommands::MoveItems</name>
<message numerus="yes">
<source>move %n songs</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
</context>
<context>
<name>PlaylistUndoCommands::RemoveItems</name>
<message numerus="yes">
<source>remove %n songs</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
</context>
<context>
<name>PlaylistUndoCommands::ShuffleItems</name>
<message>
<source>shuffle songs</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PlaylistUndoCommands::SortItems</name>
<message>
<source>sort songs</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PlaylistView</name>
<message>
@@ -5311,6 +5218,43 @@ Are you sure you want to continue?</source>
<source>System colors</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Playlist</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Various artists</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<source>add %n songs</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>remove %n songs</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message numerus="yes">
<source>move %n songs</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
<message>
<source>sort songs</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>shuffle songs</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QWidget</name>
@@ -5597,13 +5541,6 @@ Are you sure you want to continue?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SCollection</name>
<message>
<source>Saving playcounts and ratings</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SavePlaylistsDialog</name>
<message>
@@ -6229,10 +6166,6 @@ Are you sure you want to continue?</source>
</context>
<context>
<name>SongLoader</name>
<message>
<source>You need GStreamer for this URL.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Preload function was not set for blocking operation.</source>
<translation type="unfinished"></translation>
@@ -6241,10 +6174,6 @@ Are you sure you want to continue?</source>
<source>File %1 does not exist.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>CD playback is only available with the GStreamer engine.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Could not open file %1 for reading: %2</source>
<translation type="unfinished"></translation>
@@ -6273,6 +6202,10 @@ Are you sure you want to continue?</source>
<source>Couldn&apos;t link GStreamer source, typefind and fakesink elements for %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Missing CDDA playback.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SongLoaderInserter</name>

File diff suppressed because it is too large Load Diff