Merge branch 'master' of https://github.com/clementine-player/Clementine
This commit is contained in:
commit
532720ea79
@ -107,7 +107,6 @@ if(LASTFM_INCLUDE_DIRS AND LASTFM1_INCLUDE_DIRS)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
find_library(GROWL Growl)
|
||||
find_library(SPARKLE Sparkle)
|
||||
|
||||
find_library(SPOTIFY libspotify)
|
||||
|
@ -853,7 +853,6 @@ optional_source(HAVE_SPOTIFY_DOWNLOADER
|
||||
# Platform specific - OS X
|
||||
optional_source(APPLE
|
||||
INCLUDE_DIRECTORIES
|
||||
${GROWL}/Headers
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/google-breakpad/client/mac/build/Release/Breakpad.framework
|
||||
SOURCES
|
||||
core/macfslistener.mm
|
||||
@ -1290,7 +1289,6 @@ endif()
|
||||
|
||||
if (APPLE)
|
||||
target_link_libraries(clementine_lib
|
||||
${GROWL}
|
||||
/System/Library/Frameworks/AppKit.framework
|
||||
/System/Library/Frameworks/Carbon.framework
|
||||
/System/Library/Frameworks/CoreAudio.framework
|
||||
@ -1395,9 +1393,6 @@ if (APPLE)
|
||||
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Frameworks/Sparkle.framework")
|
||||
endif (HAVE_SPARKLE)
|
||||
|
||||
install(DIRECTORY "${GROWL}/Versions/Current/Resources"
|
||||
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Frameworks/Growl.framework")
|
||||
|
||||
install(FILES "${QT_QTCORE_LIBRARY_RELEASE}/Contents/Info.plist"
|
||||
DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Frameworks/QtCore.framework/Contents")
|
||||
install(FILES "${QT_QTGUI_LIBRARY_RELEASE}/Contents/Info.plist"
|
||||
|
@ -20,12 +20,14 @@
|
||||
#include "libraryquery.h"
|
||||
#include "groupbydialog.h"
|
||||
#include "ui_libraryfilterwidget.h"
|
||||
#include "core/song.h"
|
||||
#include "ui/iconloader.h"
|
||||
#include "ui/settingsdialog.h"
|
||||
|
||||
#include <QActionGroup>
|
||||
#include <QKeyEvent>
|
||||
#include <QMenu>
|
||||
#include <QRegExp>
|
||||
#include <QSettings>
|
||||
#include <QSignalMapper>
|
||||
#include <QTimer>
|
||||
@ -39,6 +41,13 @@ LibraryFilterWidget::LibraryFilterWidget(QWidget* parent)
|
||||
filter_applies_to_model_(true),
|
||||
delay_behaviour_(DelayedOnLargeLibraries) {
|
||||
ui_->setupUi(this);
|
||||
|
||||
// Add the available fields to the tooltip here instead of the ui
|
||||
// file to prevent that they get translated by mistake.
|
||||
QString available_fields =
|
||||
Song::kFtsColumns.join(", ").replace(QRegExp("\\bfts"), "");
|
||||
ui_->filter->setToolTip(ui_->filter->toolTip().arg(available_fields));
|
||||
|
||||
connect(ui_->filter, SIGNAL(returnPressed()), SIGNAL(ReturnPressed()));
|
||||
connect(filter_delay_, SIGNAL(timeout()), SLOT(FilterDelayTimeout()));
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
<item>
|
||||
<widget class="QSearchField" name="filter" native="true">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Prefix a word with a field name to limit the search to that field, e.g. <span style=" font-weight:600;">artist:</span><span style=" font-style:italic;">Bode</span> searches the library for all artists that contain the word Bode.</p><p><span style=" font-weight:600;">Available fields: </span><span style=" font-style:italic;">title, album, artist, albumartist, composer, performer, grouping, genre, comment</span>.</p></body></html></string>
|
||||
<string><html><head/><body><p>Prefix a word with a field name to limit the search to that field, e.g. <span style=" font-weight:600;">artist:</span><span style=" font-style:italic;">Bode</span> searches the library for all artists that contain the word Bode.</p><p><span style=" font-weight:600;">Available fields: </span><span style=" font-style:italic;">%1</span>.</p></body></html></string>
|
||||
</property>
|
||||
<property name="placeholderText" stdset="0">
|
||||
<string>Enter search terms here</string>
|
||||
|
@ -101,7 +101,8 @@ return_song:
|
||||
}
|
||||
|
||||
void XSPFParser::Save(const SongList& songs, QIODevice* device,
|
||||
const QDir&) const {
|
||||
const QDir& dir) const {
|
||||
QFileInfo file;
|
||||
QXmlStreamWriter writer(device);
|
||||
writer.setAutoFormatting(true);
|
||||
writer.setAutoFormattingIndent(2);
|
||||
@ -112,8 +113,17 @@ void XSPFParser::Save(const SongList& songs, QIODevice* device,
|
||||
|
||||
StreamElement tracklist("trackList", &writer);
|
||||
for (const Song& song : songs) {
|
||||
QString filename_or_url;
|
||||
if (song.url().scheme() == "file") {
|
||||
// Make the filename relative to the directory we're saving the playlist.
|
||||
filename_or_url = dir.relativeFilePath(
|
||||
QFileInfo(song.url().toLocalFile()).absoluteFilePath());
|
||||
} else {
|
||||
filename_or_url = song.url().toEncoded();
|
||||
}
|
||||
|
||||
StreamElement track("track", &writer);
|
||||
writer.writeTextElement("location", song.url().toString());
|
||||
writer.writeTextElement("location", filename_or_url);
|
||||
writer.writeTextElement("title", song.title());
|
||||
if (!song.artist().isEmpty()) {
|
||||
writer.writeTextElement("creator", song.artist());
|
||||
@ -130,11 +140,24 @@ void XSPFParser::Save(const SongList& songs, QIODevice* device,
|
||||
song.art_manual().isEmpty() ? song.art_automatic() : song.art_manual();
|
||||
// Ignore images that are in our resource bundle.
|
||||
if (!art.startsWith(":") && !art.isEmpty()) {
|
||||
// Convert local files to URLs.
|
||||
QString art_filename;
|
||||
if (!art.contains("://")) {
|
||||
art = QUrl::fromLocalFile(art).toString();
|
||||
art_filename = art;
|
||||
} else if (QUrl(art).scheme() == "file") {
|
||||
art_filename = QUrl(art).toLocalFile();
|
||||
}
|
||||
writer.writeTextElement("image", art);
|
||||
|
||||
if (!art_filename.isEmpty()) {
|
||||
// Make this filename relative to the directory we're saving the
|
||||
// playlist.
|
||||
art_filename = dir.relativeFilePath(
|
||||
QFileInfo(art_filename).absoluteFilePath());
|
||||
} else {
|
||||
// Just use whatever URL was in the Song.
|
||||
art_filename = art;
|
||||
}
|
||||
|
||||
writer.writeTextElement("image", art_filename);
|
||||
}
|
||||
}
|
||||
writer.writeEndDocument();
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -296,7 +296,7 @@
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="buffer_min_fill_label">
|
||||
<property name="text">
|
||||
<string>Buffer low fill</string>
|
||||
<string>Minimum buffer fill</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -127,11 +127,6 @@ class OSD : public QObject {
|
||||
QString last_image_uri_;
|
||||
QImage last_image_;
|
||||
|
||||
#ifdef Q_OS_DARWIN
|
||||
class GrowlNotificationWrapper;
|
||||
GrowlNotificationWrapper* wrapper_;
|
||||
#endif // Q_OS_DARWIN
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
std::unique_ptr<OrgFreedesktopNotificationsInterface> interface_;
|
||||
uint notification_id_;
|
||||
|
@ -22,117 +22,8 @@
|
||||
#include <QFile>
|
||||
#include <QtDebug>
|
||||
|
||||
#import <GrowlApplicationBridge.h>
|
||||
|
||||
#include "core/scoped_nsautorelease_pool.h"
|
||||
#include "core/scoped_nsobject.h"
|
||||
|
||||
@interface GrowlInterface : NSObject<GrowlApplicationBridgeDelegate> {
|
||||
}
|
||||
- (void)SendGrowlAlert:(NSString*)message
|
||||
title:(NSString*)title
|
||||
image:(NSData*)image;
|
||||
- (void)ClickCallback; // Called when user clicks on notification.
|
||||
@end
|
||||
|
||||
@implementation GrowlInterface
|
||||
|
||||
- (id)init {
|
||||
if ((self = [super init])) {
|
||||
[GrowlApplicationBridge setGrowlDelegate:self];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSDictionary*)registrationDictionaryForGrowl {
|
||||
NSArray* array = [NSArray
|
||||
arrayWithObjects:@"next_track", nil]; // Valid notification names.
|
||||
NSDictionary* dict = [NSDictionary
|
||||
dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:1], @"TicketVersion",
|
||||
array, @"AllNotifications", array,
|
||||
@"DefaultNotifications",
|
||||
@"com.davidsansome.clementine",
|
||||
@"ApplicationId", nil];
|
||||
return dict;
|
||||
}
|
||||
|
||||
- (void)growlNotificationWasClicked:(id)clickContext {
|
||||
if (clickContext) {
|
||||
[self ClickCallback];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
- (void)SendGrowlAlert:(NSString*)message
|
||||
title:(NSString*)title
|
||||
image:(NSData*)image {
|
||||
[GrowlApplicationBridge
|
||||
notifyWithTitle:title
|
||||
description:message
|
||||
notificationName:@"next_track"
|
||||
iconData:image
|
||||
priority:0
|
||||
isSticky:NO
|
||||
clickContext:@"click_callback"]; // String sent to our callback.
|
||||
}
|
||||
|
||||
- (void)ClickCallback {
|
||||
qDebug() << "Growl notification clicked!";
|
||||
return;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
class OSD::GrowlNotificationWrapper {
|
||||
public:
|
||||
GrowlNotificationWrapper() {
|
||||
growl_interface_ = [[GrowlInterface alloc] init];
|
||||
}
|
||||
|
||||
~GrowlNotificationWrapper() { [growl_interface_ release]; }
|
||||
|
||||
void ShowMessage(const QString& summary, const QString& message,
|
||||
const QImage& image) {
|
||||
|
||||
NSString* mac_message =
|
||||
[[NSString alloc] initWithUTF8String:message.toUtf8().constData()];
|
||||
NSString* mac_summary =
|
||||
[[NSString alloc] initWithUTF8String:summary.toUtf8().constData()];
|
||||
|
||||
NSData* image_data = nil;
|
||||
// Growl expects raw TIFF data.
|
||||
// This is nasty but it keeps the API nice.
|
||||
if (!image.isNull()) {
|
||||
QByteArray tiff_data;
|
||||
QBuffer tiff(&tiff_data);
|
||||
image.save(&tiff, "TIFF");
|
||||
image_data =
|
||||
[NSData dataWithBytes:tiff_data.constData() length:tiff_data.size()];
|
||||
}
|
||||
|
||||
[growl_interface_ SendGrowlAlert:mac_message
|
||||
title:mac_summary
|
||||
image:image_data];
|
||||
|
||||
[mac_message release];
|
||||
[mac_summary release];
|
||||
}
|
||||
|
||||
private:
|
||||
GrowlInterface* growl_interface_;
|
||||
ScopedNSAutoreleasePool pool_;
|
||||
};
|
||||
|
||||
void OSD::Init() { wrapper_ = new GrowlNotificationWrapper; }
|
||||
|
||||
bool OSD::SupportsNativeNotifications() { return true; }
|
||||
|
||||
bool OSD::SupportsTrayPopups() { return false; }
|
||||
|
||||
namespace {
|
||||
|
||||
bool NotificationCenterSupported() {
|
||||
@ -152,17 +43,23 @@ void SendNotificationCenterMessage(NSString* title, NSString* subtitle) {
|
||||
}
|
||||
}
|
||||
|
||||
void OSD::Init() {}
|
||||
|
||||
bool OSD::SupportsNativeNotifications() {
|
||||
return NotificationCenterSupported();
|
||||
}
|
||||
|
||||
bool OSD::SupportsTrayPopups() { return false; }
|
||||
|
||||
|
||||
void OSD::ShowMessageNative(const QString& summary, const QString& message,
|
||||
const QString& icon, const QImage& image) {
|
||||
Q_UNUSED(icon);
|
||||
|
||||
if (NotificationCenterSupported()) {
|
||||
scoped_nsobject<NSString> mac_message(
|
||||
[[NSString alloc] initWithUTF8String:message.toUtf8().constData()]);
|
||||
scoped_nsobject<NSString> mac_summary(
|
||||
[[NSString alloc] initWithUTF8String:summary.toUtf8().constData()]);
|
||||
SendNotificationCenterMessage(mac_summary.get(), mac_message.get());
|
||||
} else {
|
||||
wrapper_->ShowMessage(summary, message, image);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user