1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-03-21 16:29:43 +01:00
This commit is contained in:
Alejandro Wainzinger 2011-08-12 19:45:52 -07:00
commit 7eaed053f5
80 changed files with 1630 additions and 484 deletions

View File

@ -1,6 +1,6 @@
PROJECT( tomahawk )
CMAKE_MINIMUM_REQUIRED( VERSION 2.8 )
SET( CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_SOURCE_DIR}/CMakeModules" )
SET( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules" )
IF( ${CMAKE_VERSION} VERSION_GREATER 2.8.3 )
CMAKE_POLICY(SET CMP0017 NEW)
@ -15,10 +15,10 @@ SET( TOMAHAWK_APPLICATION_NAME "Tomahawk" )
SET( TOMAHAWK_DESCRIPTION_SUMMARY "The social media player" )
SET( TOMAHAWK_VERSION_MAJOR 0 )
SET( TOMAHAWK_VERSION_MINOR 1 )
SET( TOMAHAWK_VERSION_MINOR 2 )
SET( TOMAHAWK_VERSION_PATCH 0 )
# SET( TOMAHAWK_VERSION_RC 0 )
SET( TOMAHAWK_VERSION_RC 1 )
# build options
@ -28,9 +28,9 @@ option(BUILD_GUI "Build Tomahawk with GUI" ON)
# generate version string
IF( NOT CMAKE_BUILD_TYPE STREQUAL "Release" )
# Use the date as the tweak level.
INCLUDE( ${CMAKE_MODULE_PATH}/CMakeDateStamp.cmake )
INCLUDE( CMakeDateStamp )
SET( TOMAHAWK_VERSION_TWEAK "${CMAKE_DATESTAMP_YEAR}${CMAKE_DATESTAMP_MONTH}${CMAKE_DATESTAMP_DAY}" )
INCLUDE( ${CMAKE_MODULE_PATH}/CMakeVersionSource.cmake )
INCLUDE( CMakeVersionSource )
ENDIF()
SET( TOMAHAWK_VERSION ${TOMAHAWK_VERSION_MAJOR}.${TOMAHAWK_VERSION_MINOR}.${TOMAHAWK_VERSION_PATCH} )
@ -54,7 +54,7 @@ SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" )
SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" )
# installer creation
INCLUDE( CPack.cmake )
INCLUDE( CPack )
#deps
INCLUDE( MacroOptionalFindPackage )
@ -67,11 +67,11 @@ IF( NOT BUILD_GUI )
MESSAGE( STATUS "Building Tomahawk ${TOMAHAWK_VERSION} in HEADLESS mode ***" )
ELSE()
MESSAGE( STATUS "Building Tomahawk ${TOMAHAWK_VERSION} full GUI version ***" )
LIST(APPEND NEEDED_QT4_COMPONENTS "QtGui")
LIST(APPEND NEEDED_QT4_COMPONENTS "QtGui" "QtWebkit" )
ENDIF()
macro_optional_find_package(Qt4 4.7.0 COMPONENTS ${NEEDED_QT4_COMPONENTS} )
macro_log_feature(QT4_FOUND "Qt" "A cross-platform application and UI framework" "http://qt.nokia.com" TRUE "" "")
macro_log_feature(QT4_FOUND "Qt" "A cross-platform application and UI framework" "http://qt.nokia.com" TRUE "" "If you see this, although libqt4-devel is installed, check whether \n the qtwebkit-devel package is installed as well")
macro_optional_find_package(Phonon 4.5.0)
macro_log_feature(PHONON_FOUND "Phonon" "The Phonon multimedia library" "http://phonon.kde.org" TRUE "" "")
@ -93,6 +93,11 @@ macro_log_feature(TAGLIB_FOUND "TagLib" "Audio Meta-Data Library" "http://develo
include( CheckTagLibFileName )
check_taglib_filename( COMPLEX_TAGLIB_FILENAME )
macro_optional_find_package(Boost)
macro_log_feature(Boost_FOUND "Boost" "Provides free peer-reviewed portable C++ source libraries" "http://www.boost.org" TRUE "" "") #FIXME: give useful explaination
# required
#While we distribute our own liblastfm2, don't need to look for it
#macro_optional_find_package(LibLastFm 0.3.3)
@ -111,7 +116,7 @@ IF( INTERNAL_JREEN )
ELSE( INTERNAL_JREEN )
macro_optional_find_package(Jreen)
ENDIF( INTERNAL_JREEN )
macro_log_feature(LIBJREEN_FOUND "Jreen" "Qt XMPP Library" "http://gitorious.org/jreen/jreen" FALSE "" "Jreen is needed for the Jabber SIP plugin. \n\n Use -DINTERNAL_JREEN=ON to build the git submodule inside Tomahawk \n Be aware this installs a full jreen with headers and everything!\n")
macro_log_feature(LIBJREEN_FOUND "Jreen" "Qt XMPP Library" "https://github.com/euroelessar/jreen" FALSE "" "Jreen is needed for the Jabber SIP plugin. \n\n Use -DINTERNAL_JREEN=ON to build the git submodule inside Tomahawk \n Be aware this installs a full jreen with headers and everything!\n")
# this installs headers and such and should really be handled in a separate package by packagers
IF( INTERNAL_QTWEETLIB )

View File

@ -1,3 +1,5 @@
SET(WINDRES_EXECUTABLE ${CMAKE_RC_COMPILER})
# This macro is taken from kdelibs/cmake/modules/KDE4Macros.cmake.
#
# Copyright (c) 2006-2009 Alexander Neundorf, <neundorf@kde.org>
@ -76,9 +78,9 @@ macro (KDE4_ADD_APP_ICON appsources pattern)
file(GLOB_RECURSE files "${pattern}")
# we can only test for the 128-icon like that - we don't use patterns anymore
foreach (it ${files})
if (it MATCHES ".*512.*" )
if (it MATCHES ".*128.*" )
set (_icon ${it})
endif (it MATCHES ".*512.*")
endif (it MATCHES ".*128.*")
endforeach (it)
if (_icon)
@ -101,8 +103,8 @@ macro (KDE4_ADD_APP_ICON appsources pattern)
set_source_files_properties(${_outfilename}.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
else(_icon)
# TODO - try to scale a non-512 icon...? Try to convert an SVG on the fly?
message(STATUS "Unable to find an 512x512 icon that matches pattern ${pattern} for variable ${appsources} - application will not have an application icon!")
# TODO - try to scale a non-128 icon...? Try to convert an SVG on the fly?
message(STATUS "Unable to find an 128x128 icon that matches pattern ${pattern} for variable ${appsources} - application will not have an application icon!")
endif(_icon)
else(SIPS_EXECUTABLE AND TIFF2ICNS_EXECUTABLE)

View File

@ -1,4 +1,20 @@
Version 0.2.0:
* Fix inability to create Echonest playlists based solely on style or mood.
* Created new Album page (that shows other albums from that artist available in your Super Collection)
* Update playlists in dashboard to keep them in sync
* Added support for "playing" Rdio track URLs and ability to drag/drop them into Tomahawk
* Change "Recently Played" page to "Dashboard"
* Prioritize resolving newer queries to make GUI more responsive
* Automatically expand local collection node in sidebar on launch
* Display spinner animation while searching for tracks
* Fix for occasionally flashing play control buttons
* Remove horizontal scrollbars when they aren't needed
* Let headless-Tomahawk users trigger a rescan with --filescan
* Removed "test login" button from Last.fm settings (OS X only)
* Fix font and image sizes from being too big/small on some OSes
* Include Stations and Automatic Playlists in News Stations and Playlists widget
* When click through to station or playlist ensure that sidebar navigation reflects it
* Even more design tweaks, new placeholder icons (and use them in right places)
* Show search and artist page temporary navigation in sidebar when on those pages
* Fixed bug where drop indicator wouldn't show under last track if that was drop zone
* Fixed cross-wiring of Previous and Next song in "Music Player" menu (OS X)
@ -19,8 +35,7 @@ Version 0.2.0:
* Fixed a few crashes that could occur when fetching data from Last.fm.
* Made Twitter dialog more readable/understandable.
* Added Artist pages (and links to them from now playing metadata and from collection track list views)
with artist bio snippet, related artists, top tracks and view of all tracks/albums from that
artist in user's Super Collection
with artist bio snippet, related artists, top tracks and view of all tracks/albums from that artist in user's Super Collection
* Fixed streaming from https:// links
* Desktop notifications for now playing (Linux only)
* Implement new javascript resolver API and ability to present configuration options for resolvers
@ -47,11 +62,11 @@ Version 0.2.0:
* Don't require @foo.com domains for jabber and google
* Added global search function that searches all available sources (super collection and all enabled resolvers)
* Cleaned up Preference Window and styling
* Collection scanner now can now run automatically, watching files and
* Collection scanner now can run automatically, watching files and
directories for changes. On by default.
* Added Pipeline view window
* Allow seeking in songs - if possible
* Added ability to make a copy of a sources' playlists and add to your own playlists
* Added ability to make a copy of a peer's playlists and add to your own playlists
* Added MediaKey support on OS X
* Shuffle and Repeat settings are stored on a playlist by playlist basis

View File

@ -1,64 +0,0 @@
#!/bin/sh
# author: max@last.fm
# usage: Run from inside the bundle root directory, eg. Last.fm.app
# The first parameter should be the QtFrameworks to copy.
# Remaining parameters are plugins to copy, directories and files are
# valid.
# eg: add-Qt-to-bundle.sh 'QtCore QtGui QtXml' \
# imageformats \
# sqldrivers/libsqlite.dylib
################################################################################
QT_FRAMEWORKS_DIR="$QTDIR/lib"
QT_PLUGINS_DIR="$QTDIR/plugins"
if [[ ! -d "$QTDIR/lib/QtCore.framework" ]]
then
# this dir is the location of install for the official Trolltech dmg
if [[ -d /Library/Frameworks/QtCore.framework ]]
then
QT_FRAMEWORKS_DIR=/Library/Frameworks
QT_PLUGINS_DIR=/Developer/Applications/Qt/plugins
fi
fi
echo "Plugins go to: $QT_PLUGINS_DIR"
if [ -z $QTDIR ]
then
echo QTDIR must be set, or install the official Qt dmg
exit 1
fi
################################################################################
#first frameworks
mkdir -p Contents/Frameworks
for x in $1
do
echo "C $x"
cp -R $QT_FRAMEWORKS_DIR/$x.framework Contents/Frameworks/
chmod -R u+rw Contents/Frameworks/
done
#plugins
shift
mkdir -p Contents/MacOS
mkdir -p Contents/MacOS/sqldrivers
mkdir -p Contents/MacOS/imageformats
mkdir -p Contents/MacOS/phonon_backend
mkdir -p Contents/MacOS/crypto
cp -R $QT_PLUGINS_DIR/sqldrivers/libqsqlite.dylib Contents/MacOS/sqldrivers/
cp -R $QT_PLUGINS_DIR/imageformats/libqgif.dylib Contents/MacOS/imageformats/
cp -R $QT_PLUGINS_DIR/imageformats/libqjpeg.dylib Contents/MacOS/imageformats/
cp -R $QT_PLUGINS_DIR/imageformats/libqico.dylib Contents/MacOS/imageformats/
cp -R $QT_PLUGINS_DIR/imageformats/libqmng.dylib Contents/MacOS/imageformats/
#cp -R $QT_PLUGINS_DIR/imageformats/libqsvg.dylib Contents/MacOS/imageformats/
#cp -R $QT_PLUGINS_DIR/imageformats/libqtiff.dylib Contents/MacOS/imageformats/
cp -R $QT_PLUGINS_DIR/crypto/libqca-ossl.dylib Contents/MacOS/crypto/
cp -R $QT_PLUGINS_DIR/phonon_backend/phonon_vlc.so Contents/MacOS/phonon_backend/
#cleanup
find Contents/Frameworks -name Headers -o -name \*.prl -o -name \*_debug | xargs rm -rf
find Contents -name \*_debug -o -name \*_debug.dylib | xargs rm

View File

@ -1,16 +0,0 @@
#!/bin/sh
# author: lfranchi@kde.org
# usage: Run from inside the bundle root directory, eg. Tomahawk.app
# The first parameter should be the spotify resolver binary to copy.
# eg: add-spotify.sh /path/to/spotify_tomahawkresolver
################################################################################
mkdir -p Contents/Frameworks
cp -R /Library/Frameworks/libspotify.framework Contents/Frameworks
install_name_tool -change /usr/local/Cellar/qt/4.7.3/lib/QtCore.framework/Versions/4/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore $1
install_name_tool -change /usr/local/Cellar/qt/4.7.3/lib/QtNetwork.framework/Versions/4/QtNetwork @executable_path/../Frameworks/QtNetwork.framework/Versions/4/QtNetwork $1
install_name_tool -change libqjson.0.dylib @executable_path/libqjson.0.7.1.dylib $1
install_name_tool -change /usr/local/Cellar/qjson/0.7.1/lib/libqjson.0.7.1.dylib @executable_path/libqjson.0.7.1.dylib $1
mkdir -p Contents/MacOS
cp $1 Contents/MacOS/

View File

@ -23,65 +23,26 @@ then
fi
ROOT=`pwd`
QTDIR=`which qmake`
LINKDIR=`readlink $QTDIR`
QTDIR=`dirname $QTDIR`
QTDIR=$QTDIR/`dirname $LINKDIR`
QTDIR=`dirname $QTDIR`
test -L "$QTDIR" && QTDIR=`readlink $QTDIR`
echo "Goes here: $QTDIR"
export QMAKESPEC='macx-g++'
export QTDIR
export VERSION
export QTVERSION='4.7.3'
################################################################################
CLEAN='1'
BUILD='1'
NOTQUICK='1'
CREATEDMG='1'
VERSION=$1
header "Adding Qt to app bundle"
cd tomahawk.app
$ROOT/../admin/mac/add-Qt-to-bundle.sh \
'QtCore QtGui QtXml QtNetwork QtSql QtXmlPatterns QtWebKit phonon'
# 'QtCore QtGui QtXml QtNetwork QtSql QtXmlPatterns QtWebKit QtDbus phonon'
################################################################################
header "Renaming files"
mv tomahawk.app Tomahawk.app
mv Tomahawk.app/Contents/MacOS/tomahawk Tomahawk.app/Contents/MacOS/Tomahawk
header "Fixing and copying libraries"
$ROOT/../admin/mac/macdeploy.py Tomahawk.app quiet
cd Tomahawk.app
header "Renaming icon"
mv Contents/Resources/tomahawkSources.icns Contents/Resources/Tomahawk.icns
mv Contents/MacOS/tomahawk Contents/MacOS/Tomahawk
# cp $ROOT/../admin/mac/Info.plist Contents/Info.plist
cp $ROOT/../admin/mac/qt.conf Contents/Resources/qt.conf
header "Copying VLC plugins into bundle"
mkdir -p Contents/plugins
cp -R /usr/local/Cellar/vlc-git/HEAD/lib/vlc/plugins/ Contents/plugins
rm -rf Contents/plugins/video_* Contents/plugins/gui Contents/plugins/*/libold* Contents/plugins/*/libvcd* Contents/plugins/*/libdvd* \
Contents/plugins/*/liblibass* Contents/plugins/*/libx264* Contents/plugins/*/libschroe* Contents/plugins/*/liblibmpeg2* \
Contents/plugins/*/libstream_out_* Contents/plugins/*/libmjpeg_plugin* Contents/plugins/*/libh264_plugin* Contents/plugins/*/libzvbi_plugin* Contents/plugins/*/lib*sub*
header "Running install_name_tool"
$ROOT/../admin/mac/deposx.sh
header "Copying Sparkle pubkey & framework, and qt.conf"
cp $ROOT/../admin/mac/sparkle_pub.pem Contents/Resources
cp -R /Library/Frameworks/Sparkle.framework Contents/Frameworks
cp $ROOT/../admin/mac/qt.conf Contents/Resources
header "Adding spotify resolver to bundle if spotify_tomahawkresolver found in $ROOT"
if [ -e $ROOT/spotify_tomahawkresolver ]
then
header "Found, so adding spotify resolver."ac
$ROOT/../admin/mac/add-spotify.sh $ROOT/spotify_tomahawkresolver
fi
header "Creating DMG"
cd ..
mv tomahawk.app Tomahawk.app
$ROOT/../admin/mac/create-dmg.sh Tomahawk.app
mv Tomahawk.dmg Tomahawk-$VERSION.dmg

View File

@ -1,169 +0,0 @@
#!/bin/sh
# author: max@last.fm, chris@last.fm
################################################################################
if [ -z $QTDIR ]
then
echo QTDIR must be set
exit 1
fi
if [ -z $QTVERSION ]
then
echo QTVERSION must be set
exit 1
fi
cd ..
ORIGROOT=`pwd`
cd -
cd Contents
QTLIBS=`ls Frameworks | cut -d. -f1`
LIBS=`cd MacOS && ls -fR1 | grep dylib`
PLUGINFOLDERS=`ls plugins | cut -d. -f1`
################################################################################
function import_lib
{
echo "L \`$1'"
cp -R -L $1 MacOS/`basename $1`
chmod u+rw MacOS/`basename $1`
deplib_change MacOS/`basename $1`
deposx_change MacOS/`basename $1`
}
function deposx_change
{
echo "D \`$1'"
echo $QTDIR
for y in $QTLIBS
do
install_name_tool -change $QTDIR/lib/$y.framework/Versions/4/$y \
@executable_path/../Frameworks/$y.framework/Versions/4/$y \
"$1"
install_name_tool -change /usr/local/Cellar/qt/$QTVERSION/lib/$y.framework/Versions/4/$y \
@executable_path/../Frameworks/$y.framework/Versions/4/$y \
"$1"
install_name_tool -change /usr/X11/lib/libpng12.0.dylib \
@executable_path/libpng12.0.dylib \
"$1"
done
for y in $LIBS
do
install_name_tool -change $y \
@executable_path/$y \
"$1"
done
}
function deplib_change
{
install_name_tool -change /usr/local/Cellar/qjson/0.7.1/lib/libqjson.0.7.1.dylib @executable_path/libqjson.0.7.1.dylib $1
install_name_tool -change /usr/local/lib/libechonest.1.1.dylib @executable_path/libechonest.1.1.dylib $1
install_name_tool -change /usr/local/lib/libclucene-core.1.dylib @executable_path/libclucene-core.1.dylib $1
install_name_tool -change /usr/local/lib/libclucene-shared.1.dylib @executable_path/libclucene-shared.1.dylib $1
install_name_tool -change /usr/local/Cellar/taglib/1.7/lib/libtag.1.7.0.dylib @executable_path/libtag.1.7.0.dylib $1
# install_name_tool -change /usr/local/Cellar/gloox/1.0/lib/libgloox.8.dylib @executable_path/libgloox.8.dylib $1
# install_name_tool -change /usr/local/Cellar/libogg/1.2.0/lib/libogg.0.dylib @executable_path/libogg.0.dylib $1
# install_name_tool -change /usr/local/Cellar/libvorbis/1.3.1/lib/libvorbis.0.dylib @executable_path/libvorbis.0.dylib $1
# install_name_tool -change /usr/local/Cellar/libvorbis/1.3.1/lib/libvorbisfile.3.dylib @executable_path/libvorbisfile.3.dylib $1
# install_name_tool -change /usr/local/Cellar/mad/0.15.1b/lib/libmad.0.dylib @executable_path/libmad.0.dylib $1
# install_name_tool -change /usr/local/Cellar/flac/1.2.1/lib/libFLAC++.6.dylib @executable_path/libFLAC++.6.dylib $1
# install_name_tool -change /usr/local/Cellar/flac/1.2.1/lib/libFLAC.8.dylib @executable_path/libFLAC.8.dylib $1
install_name_tool -change /usr/local/Cellar/kde-phonon/4.5.0/lib/libphonon.4.dylib @executable_path/libphonon.4.dylib $1
install_name_tool -change /usr/local/Cellar/kde-phonon/4.5.0/lib/libphonon.4.5.0.dylib @executable_path/libphonon.4.dylib $1
install_name_tool -change $ORIGROOT/libtomahawklib.dylib @executable_path/libtomahawklib.dylib $1
install_name_tool -change $ORIGROOT/libtomahawk_sipjabber.dylib @executable_path/libtomahawk_sipjabber.dylib $1
install_name_tool -change $ORIGROOT/libtomahawk_sipgoogle.dylib @executable_path/libtomahawk_sipgoogle.dylib $1
install_name_tool -change $ORIGROOT/libtomahawk_siptwitter.dylib @executable_path/libtomahawk_siptwitter.dylib $1
install_name_tool -change $ORIGROOT/libtomahawk_sipzeroconf.dylib @executable_path/libtomahawk_sipzeroconf.dylib $1
install_name_tool -change $ORIGROOT/libtomahawk_qtweetlib.dylib @executable_path/libtomahawk_qtweetlib.dylib $1
install_name_tool -change $ORIGROOT/libtomahawk_portfwd.dylib @executable_path/libtomahawk_portfwd.dylib $1
install_name_tool -change $ORIGROOT/libjreen.dylib @executable_path/libjreen.dylib $1
install_name_tool -change /usr/local/Cellar/jreen/HEAD/lib/libjreen.dylib @executable_path/libjreen.dylib $1
install_name_tool -change /usr/local/Cellar/qca/2.0.2/lib/qca.framework/Versions/2/qca @executable_path/../Frameworks/qca.framework/Versions/2/qca $1
install_name_tool -change /usr/local/Cellar/gettext/0.18.1.1/lib/libintl.8.dylib @executable_path/libintl.8.dylib $1
install_name_tool -change /usr/local/Cellar/vlc-git/HEAD/lib/libvlc.5.dylib @executable_path/libvlc.5.dylib $1
install_name_tool -change /usr/local/Cellar/vlc-git/HEAD/lib/libvlccore.4.dylib @executable_path/libvlccore.4.dylib $1
install_name_tool -change libqjson.0.dylib @executable_path/libqjson.0.7.1.dylib $1
install_name_tool -change libechonest.1.1.dylib @executable_path/libechonest.1.1.dylib $1
install_name_tool -change libclucene-core.1.dylib @executable_path/libclucene-core.1.dylib $1
install_name_tool -change libclucene-shared.1.dylib @executable_path/libclucene-shared.1.dylib $1
}
################################################################################
# first all libraries and executables
find MacOS -type f -a -perm -100 | while read x
do
echo $x
y=$(file "$x" | grep 'Mach-O')
deposx_change "$x"
deplib_change "$x"
done
import_lib /usr/local/Cellar/qjson/0.7.1/lib/libqjson.0.7.1.dylib
import_lib /usr/local/Cellar/taglib/1.7/lib/libtag.1.7.0.dylib
#import_lib /usr/local/Cellar/gloox/1.0/lib/libgloox.8.dylib
#import_lib /usr/local/Cellar/libogg/1.2.0/lib/libogg.0.dylib
#import_lib /usr/local/Cellar/libvorbis/1.3.1/lib/libvorbis.0.dylib
#import_lib /usr/local/Cellar/libvorbis/1.3.1/lib/libvorbisfile.3.dylib
#import_lib /usr/local/Cellar/mad/0.15.1b/lib/libmad.0.dylib
#import_lib /usr/local/Cellar/flac/1.2.1/lib/libFLAC++.6.dylib
#import_lib /usr/local/Cellar/flac/1.2.1/lib/libFLAC.8.dylib
import_lib /usr/local/lib/libechonest.1.1.dylib
import_lib /usr/local/lib/libclucene-core.1.dylib
import_lib /usr/local/lib/libclucene-shared.1.dylib
import_lib /usr/local/Cellar/kde-phonon/4.5.0/lib/libphonon.4.dylib
import_lib /usr/local/Cellar/vlc-git/HEAD/lib/libvlc.5.dylib
import_lib /usr/local/Cellar/vlc-git/HEAD/lib/libvlccore.4.dylib
import_lib /usr/local/Cellar/gettext/0.18.1.1/lib/libintl.8.dylib
import_lib /usr/X11/lib/libpng12.0.dylib
import_lib $ORIGROOT/libjreen.dylib
import_lib $ORIGROOT/libtomahawklib.dylib
import_lib $ORIGROOT/libtomahawk_sipjabber.dylib
import_lib $ORIGROOT/libtomahawk_sipgoogle.dylib
import_lib $ORIGROOT/libtomahawk_siptwitter.dylib
import_lib $ORIGROOT/libtomahawk_sipzeroconf.dylib
import_lib $ORIGROOT/libtomahawk_qtweetlib.dylib
import_lib $ORIGROOT/libtomahawk_portfwd.dylib
cp -R /usr/local/Cellar/qca/2.0.2/lib/qca.framework Frameworks/
chmod 644 Frameworks/qca.framework/Versions/2/qca
deplib_change Frameworks/qca.framework/Versions/2/qca
deposx_change Frameworks/qca.framework/Versions/2/qca
# now Qt
for x in $QTLIBS
do
echo `pwd`
# ls -l Frameworks/$x.framework/Versions/4/$x
deposx_change Frameworks/$x.framework/Versions/4/$x
install_name_tool -id @executable_path/../Frameworks/$x.framework/Versions/4/$x \
Frameworks/$x.framework/Versions/4/$x
deplib_change "Frameworks/$x.framework/Versions/4/$x"
done
# now VLC plugins
for x in plugins/$PLUGINFOLDERS
do
for plugin in `ls plugins/$x | cut -f1`
do
echo "Fixing VLC plugin: $plugin"
chmod 644 plugins/$x/$plugin
deplib_change plugins/$x/$plugin
done
done

517
admin/mac/macdeploy.py Executable file
View File

@ -0,0 +1,517 @@
#!/usr/bin/python
# This file is part of Clementine.
#
# Clementine 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.
#
# Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
import os
import re
import subprocess
import sys
FRAMEWORK_SEARCH_PATH=[
'/Library/Frameworks',
os.path.join(os.environ['HOME'], 'Library/Frameworks')
]
LIBRARY_SEARCH_PATH=['/usr/local/lib', '/usr/local/Cellar/gettext/0.18.1.1/lib', '.']
VLC_PLUGINS=[
'access/libaccess_attachment_plugin.dylib',
#'access/libaccess_avio_plugin.dylib',
'access/libaccess_fake_plugin.dylib',
'access/libaccess_ftp_plugin.dylib',
'access/libaccess_http_plugin.dylib',
'access/libaccess_imem_plugin.dylib',
'access/libaccess_mmap_plugin.dylib',
'access/libaccess_mms_plugin.dylib',
'access/libaccess_realrtsp_plugin.dylib',
'access/libaccess_tcp_plugin.dylib',
'access/libaccess_udp_plugin.dylib',
'access/libcdda_plugin.dylib',
'access/libfilesystem_plugin.dylib',
'access/libqtcapture_plugin.dylib',
'access/librtp_plugin.dylib',
'access/libzip_plugin.dylib',
'access_output/libaccess_output_dummy_plugin.dylib',
'access_output/libaccess_output_file_plugin.dylib',
'access_output/libaccess_output_http_plugin.dylib',
'access_output/libaccess_output_shout_plugin.dylib',
'access_output/libaccess_output_udp_plugin.dylib',
'audio_filter/liba52tofloat32_plugin.dylib',
'audio_filter/liba52tospdif_plugin.dylib',
'audio_filter/libaudio_format_plugin.dylib',
'audio_filter/libaudiobargraph_a_plugin.dylib',
'audio_filter/libchorus_flanger_plugin.dylib',
'audio_filter/libconverter_fixed_plugin.dylib',
'audio_filter/libdolby_surround_decoder_plugin.dylib',
'audio_filter/libdtstofloat32_plugin.dylib',
'audio_filter/libdtstospdif_plugin.dylib',
'audio_filter/libequalizer_plugin.dylib',
'audio_filter/libheadphone_channel_mixer_plugin.dylib',
'audio_filter/libmono_plugin.dylib',
'audio_filter/libmpgatofixed32_plugin.dylib',
'audio_filter/libnormvol_plugin.dylib',
'audio_filter/libparam_eq_plugin.dylib',
'audio_filter/libscaletempo_plugin.dylib',
'audio_filter/libsimple_channel_mixer_plugin.dylib',
'audio_filter/libspatializer_plugin.dylib',
'audio_filter/libtrivial_channel_mixer_plugin.dylib',
'audio_filter/libugly_resampler_plugin.dylib',
'audio_mixer/libfloat32_mixer_plugin.dylib',
'audio_mixer/libspdif_mixer_plugin.dylib',
'audio_mixer/libtrivial_mixer_plugin.dylib',
'audio_output/libaout_file_plugin.dylib',
'audio_output/libauhal_plugin.dylib',
'codec/liba52_plugin.dylib',
'codec/libadpcm_plugin.dylib',
'codec/libaes3_plugin.dylib',
'codec/libaraw_plugin.dylib',
'codec/libavcodec_plugin.dylib',
'codec/libcc_plugin.dylib',
'codec/libcdg_plugin.dylib',
'codec/libdts_plugin.dylib',
'codec/libfaad_plugin.dylib',
'codec/libfake_plugin.dylib',
'codec/libflac_plugin.dylib',
'codec/libfluidsynth_plugin.dylib',
'codec/libinvmem_plugin.dylib',
'codec/liblpcm_plugin.dylib',
'codec/libmpeg_audio_plugin.dylib',
'codec/libpng_plugin.dylib',
'codec/librawvideo_plugin.dylib',
'codec/libspeex_plugin.dylib',
'codec/libspudec_plugin.dylib',
'codec/libtheora_plugin.dylib',
'codec/libtwolame_plugin.dylib',
'codec/libvorbis_plugin.dylib',
'control/libgestures_plugin.dylib',
'control/libhotkeys_plugin.dylib',
'control/libmotion_plugin.dylib',
'control/libnetsync_plugin.dylib',
'control/libsignals_plugin.dylib',
'demux/libaiff_plugin.dylib',
'demux/libasf_plugin.dylib',
'demux/libau_plugin.dylib',
#'demux/libavformat_plugin.dylib',
'demux/libavi_plugin.dylib',
'demux/libdemux_cdg_plugin.dylib',
'demux/libdemuxdump_plugin.dylib',
'demux/libdirac_plugin.dylib',
'demux/libes_plugin.dylib',
'demux/libflacsys_plugin.dylib',
'demux/liblive555_plugin.dylib',
'demux/libmkv_plugin.dylib',
'demux/libmod_plugin.dylib',
'demux/libmp4_plugin.dylib',
'demux/libmpc_plugin.dylib',
'demux/libmpgv_plugin.dylib',
'demux/libnsc_plugin.dylib',
'demux/libnsv_plugin.dylib',
'demux/libnuv_plugin.dylib',
'demux/libogg_plugin.dylib',
'demux/libplaylist_plugin.dylib',
'demux/libps_plugin.dylib',
'demux/libpva_plugin.dylib',
'demux/librawaud_plugin.dylib',
'demux/librawdv_plugin.dylib',
'demux/librawvid_plugin.dylib',
'demux/libreal_plugin.dylib',
'demux/libsmf_plugin.dylib',
'demux/libts_plugin.dylib',
'demux/libtta_plugin.dylib',
'demux/libty_plugin.dylib',
'demux/libvc1_plugin.dylib',
'demux/libvoc_plugin.dylib',
'demux/libwav_plugin.dylib',
'demux/libxa_plugin.dylib',
'meta_engine/libfolder_plugin.dylib',
'meta_engine/libtaglib_plugin.dylib',
'misc/libaudioscrobbler_plugin.dylib',
'misc/libdummy_plugin.dylib',
'misc/libexport_plugin.dylib',
'misc/libfreetype_plugin.dylib',
'misc/libgnutls_plugin.dylib',
'misc/liblogger_plugin.dylib',
'misc/liblua_plugin.dylib',
'misc/libosd_parser_plugin.dylib',
'misc/libquartztext_plugin.dylib',
'misc/libstats_plugin.dylib',
'misc/libvod_rtsp_plugin.dylib',
'misc/libxml_plugin.dylib',
'misc/libxtag_plugin.dylib',
'mmx/libi420_rgb_mmx_plugin.dylib',
'mmx/libi420_yuy2_mmx_plugin.dylib',
'mmx/libi422_yuy2_mmx_plugin.dylib',
'mmx/libmemcpymmx_plugin.dylib',
'mmxext/libmemcpymmxext_plugin.dylib',
'mux/libmux_asf_plugin.dylib',
'mux/libmux_avi_plugin.dylib',
'mux/libmux_dummy_plugin.dylib',
'mux/libmux_mp4_plugin.dylib',
'mux/libmux_mpjpeg_plugin.dylib',
'mux/libmux_ogg_plugin.dylib',
'mux/libmux_ps_plugin.dylib',
'mux/libmux_ts_plugin.dylib',
'mux/libmux_wav_plugin.dylib',
'packetizer/libpacketizer_copy_plugin.dylib',
'packetizer/libpacketizer_dirac_plugin.dylib',
'packetizer/libpacketizer_flac_plugin.dylib',
'packetizer/libpacketizer_h264_plugin.dylib',
'packetizer/libpacketizer_mlp_plugin.dylib',
'packetizer/libpacketizer_mpeg4audio_plugin.dylib',
'packetizer/libpacketizer_mpeg4video_plugin.dylib',
'packetizer/libpacketizer_mpegvideo_plugin.dylib',
'packetizer/libpacketizer_vc1_plugin.dylib',
'sse2/libi420_rgb_sse2_plugin.dylib',
'sse2/libi420_yuy2_sse2_plugin.dylib',
'sse2/libi422_yuy2_sse2_plugin.dylib',
'stream_filter/libdecomp_plugin.dylib',
'stream_filter/libstream_filter_rar_plugin.dylib',
'stream_filter/libstream_filter_record_plugin.dylib',
'visualization/libvisual_plugin.dylib',
]
VLC_SEARCH_PATH=[
'/usr/local/lib/vlc/plugins/',
]
QT_PLUGINS = [
'crypto/libqca-ossl.dylib',
'phonon_backend/phonon_vlc.so',
'sqldrivers/libqsqlite.dylib',
'imageformats/libqgif.dylib',
'imageformats/libqico.dylib',
'imageformats/libqjpeg.dylib',
'imageformats/libqmng.dylib',
]
TOMAHAWK_PLUGINS = [
'libtomahawk_sipjabber.dylib',
'libtomahawk_sipgoogle.dylib',
'libtomahawk_siptwitter.dylib',
'libtomahawk_sipzeroconf.dylib',
'libtomahawk_qtweetlib.dylib',
]
QT_PLUGINS_SEARCH_PATH=[
'/usr/local/Cellar/qt/4.7.3/plugins',
]
class Error(Exception):
pass
class CouldNotFindQtPluginErrorFindFrameworkError(Error):
pass
class InstallNameToolError(Error):
pass
class CouldNotFindQtPluginError(Error):
pass
class CouldNotFindVLCPluginError(Error):
pass
class CouldNotFindScriptPluginError(Error):
pass
if len(sys.argv) < 2:
print 'Usage: %s <bundle.app>' % sys.argv[0]
bundle_dir = sys.argv[1]
bundle_name = os.path.basename(bundle_dir).split('.')[0]
commands = []
binary_dir = os.path.join(bundle_dir, 'Contents', 'MacOS')
frameworks_dir = os.path.join(bundle_dir, 'Contents', 'Frameworks')
commands.append(['mkdir', '-p', frameworks_dir])
resources_dir = os.path.join(bundle_dir, 'Contents', 'Resources')
commands.append(['mkdir', '-p', resources_dir])
plugins_dir = os.path.join(bundle_dir, 'Contents', 'PlugIns')
binary = os.path.join(bundle_dir, 'Contents', 'MacOS', bundle_name)
fixed_libraries = []
fixed_frameworks = []
def GetBrokenLibraries(binary):
#print "Checking libs for binary: %s" % binary
output = subprocess.Popen(['otool', '-L', binary], stdout=subprocess.PIPE).communicate()[0]
broken_libs = {
'frameworks': [],
'libs': []}
for line in [x.split(' ')[0].lstrip() for x in output.split('\n')[1:]]:
#print "Checking line: %s" % line
if not line: # skip empty lines
continue
if os.path.basename(binary) == os.path.basename(line):
#print "mnope %s-%s" % (os.path.basename(binary), os.path.basename(line))
continue
if re.match(r'^\s*/System/', line):
continue # System framework
elif re.match(r'^\s*/usr/lib/', line):
#print "unix style system lib"
continue # unix style system library
elif re.match(r'Breakpad', line):
continue # Manually added by cmake.
elif re.match(r'^\s*@executable_path', line) or re.match(r'^\s*@loader_path', line):
# Potentially already fixed library
if '.framework' in line:
relative_path = os.path.join(*line.split('/')[3:])
if not os.path.exists(os.path.join(frameworks_dir, relative_path)):
broken_libs['frameworks'].append(relative_path)
else:
relative_path = os.path.join(*line.split('/')[1:])
#print "RELPATH %s %s" % (relative_path, os.path.join(binary_dir, relative_path))
if not os.path.exists(os.path.join(binary_dir, relative_path)):
broken_libs['libs'].append(relative_path)
elif re.search(r'\w+\.framework', line):
broken_libs['frameworks'].append(line)
else:
broken_libs['libs'].append(line)
return broken_libs
def FindFramework(path):
for search_path in FRAMEWORK_SEARCH_PATH:
abs_path = os.path.join(search_path, path)
if os.path.exists(abs_path):
return abs_path
raise CouldNotFindFrameworkError(path)
def FindLibrary(path):
if os.path.exists(path):
return path
for search_path in LIBRARY_SEARCH_PATH:
abs_path = os.path.join(search_path, path)
if os.path.exists(abs_path):
return abs_path
else: # try harder---look for lib name in library folders
newpath = os.path.join(search_path,os.path.basename(path))
if os.path.exists(newpath):
return newpath
return ""
#raise CouldNotFindFrameworkError(path)
def FixAllLibraries(broken_libs):
for framework in broken_libs['frameworks']:
FixFramework(framework)
for lib in broken_libs['libs']:
FixLibrary(lib)
def FixFramework(path):
if path in fixed_libraries:
return
else:
fixed_libraries.append(path)
abs_path = FindFramework(path)
broken_libs = GetBrokenLibraries(abs_path)
FixAllLibraries(broken_libs)
new_path = CopyFramework(abs_path)
id = os.sep.join(new_path.split(os.sep)[3:])
FixFrameworkId(new_path, id)
for framework in broken_libs['frameworks']:
FixFrameworkInstallPath(framework, new_path)
for library in broken_libs['libs']:
FixLibraryInstallPath(library, new_path)
def FixLibrary(path):
if path in fixed_libraries or FindSystemLibrary(os.path.basename(path)) is not None:
return
else:
fixed_libraries.append(path)
abs_path = FindLibrary(path)
if abs_path == "":
print "Could not resolve %s, not fixing!" % path
return
broken_libs = GetBrokenLibraries(abs_path)
FixAllLibraries(broken_libs)
new_path = CopyLibrary(abs_path)
FixLibraryId(new_path)
for framework in broken_libs['frameworks']:
FixFrameworkInstallPath(framework, new_path)
for library in broken_libs['libs']:
FixLibraryInstallPath(library, new_path)
def FixVLCPlugin(abs_path, subdir):
broken_libs = GetBrokenLibraries(abs_path)
FixAllLibraries(broken_libs)
#print "Copying plugin....%s %s %s" % (plugins_dir, subdir, os.path.join(abs_path.split('/')[-2:]))
plugindir = abs_path.split('/')[-2]
new_path = os.path.join(plugins_dir, subdir, plugindir, os.path.basename(abs_path))
args = ['mkdir', '-p', os.path.dirname(new_path)]
commands.append(args)
args = ['ditto', '--arch=i386', '--arch=x86_64', abs_path, new_path]
commands.append(args)
args = ['chmod', 'u+w', new_path]
commands.append(args)
for framework in broken_libs['frameworks']:
FixFrameworkInstallPath(framework, new_path)
for library in broken_libs['libs']:
FixLibraryInstallPath(library, new_path)
def FixPlugin(abs_path, subdir):
broken_libs = GetBrokenLibraries(abs_path)
FixAllLibraries(broken_libs)
new_path = CopyPlugin(abs_path, subdir)
for framework in broken_libs['frameworks']:
FixFrameworkInstallPath(framework, new_path)
for library in broken_libs['libs']:
FixLibraryInstallPath(library, new_path)
def FixBinary(path):
broken_libs = GetBrokenLibraries(path)
FixAllLibraries(broken_libs)
for framework in broken_libs['frameworks']:
FixFrameworkInstallPath(framework, path)
for library in broken_libs['libs']:
FixLibraryInstallPath(library, path)
def CopyLibrary(path):
new_path = os.path.join(frameworks_dir, os.path.basename(path))
args = ['ditto', '--arch=i386', '--arch=x86_64', path, new_path]
commands.append(args)
args = ['chmod', 'u+w', new_path]
commands.append(args)
return new_path
def CopyPlugin(path, subdir):
new_path = os.path.join(plugins_dir, subdir, os.path.basename(path))
args = ['mkdir', '-p', os.path.dirname(new_path)]
commands.append(args)
args = ['ditto', '--arch=i386', '--arch=x86_64', path, new_path]
commands.append(args)
args = ['chmod', 'u+w', new_path]
commands.append(args)
return new_path
def CopyFramework(path):
parts = path.split(os.sep)
for i, part in enumerate(parts):
if re.match(r'\w+\.framework', part):
full_path = os.path.join(frameworks_dir, *parts[i:-1])
break
args = ['mkdir', '-p', full_path]
commands.append(args)
args = ['ditto', '--arch=i386', '--arch=x86_64', path, full_path]
commands.append(args)
args = ['chmod', 'u+w', os.path.join(full_path, parts[-1])]
commands.append(args)
menu_nib = os.path.join(os.path.split(path)[0], 'Resources', 'qt_menu.nib')
if os.path.exists(menu_nib):
args = ['cp', '-r', menu_nib, resources_dir]
commands.append(args)
return os.path.join(full_path, parts[-1])
def FixId(path, library_name):
id = '@executable_path/../Frameworks/%s' % library_name
args = ['install_name_tool', '-id', id, path]
commands.append(args)
def FixLibraryId(path):
library_name = os.path.basename(path)
FixId(path, library_name)
def FixFrameworkId(path, id):
FixId(path, id)
def FixInstallPath(library_path, library, new_path):
args = ['install_name_tool', '-change', library_path, new_path, library]
commands.append(args)
def FindSystemLibrary(library_name):
for path in ['/lib', '/usr/lib']:
full_path = os.path.join(path, library_name)
if os.path.exists(full_path):
return full_path
return None
def FixLibraryInstallPath(library_path, library):
system_library = FindSystemLibrary(os.path.basename(library_path))
if system_library is None:
new_path = '@executable_path/../Frameworks/%s' % os.path.basename(library_path)
FixInstallPath(library_path, library, new_path)
else:
FixInstallPath(library_path, library, system_library)
def FixFrameworkInstallPath(library_path, library):
parts = library_path.split(os.sep)
for i, part in enumerate(parts):
if re.match(r'\w+\.framework', part):
full_path = os.path.join(*parts[i:])
break
new_path = '@executable_path/../Frameworks/%s' % full_path
FixInstallPath(library_path, library, new_path)
def FindQtPlugin(name):
for path in QT_PLUGINS_SEARCH_PATH:
if os.path.exists(path):
if os.path.exists(os.path.join(path, name)):
return os.path.join(path, name)
raise CouldNotFindQtPluginError(name)
def FindVLCPlugin(name):
for path in VLC_SEARCH_PATH:
if os.path.exists(path):
if os.path.exists(os.path.join(path, name)):
return os.path.join(path, name)
raise CouldNotFindVLCPluginError(name)
FixBinary(binary)
for plugin in VLC_PLUGINS:
FixVLCPlugin(FindVLCPlugin(plugin), '.')
for plugin in TOMAHAWK_PLUGINS:
FixPlugin(plugin, '../MacOS')
try:
FixPlugin('spotify_tomahawkresolver', '../MacOS')
except:
print 'Failed to find spotify resolver'
for plugin in QT_PLUGINS:
FixPlugin(FindQtPlugin(plugin), os.path.dirname(plugin))
if len(sys.argv) <= 2:
print 'Would run %d commands:' % len(commands)
for command in commands:
print ' '.join(command)
print 'OK?'
raw_input()
for command in commands:
p = subprocess.Popen(command)
os.waitpid(p.pid, 0)

View File

@ -1,2 +1,2 @@
[Paths]
Plugins = plugins
Plugins = PlugIns

View File

@ -1,20 +1,27 @@
SET(MINGW_PREFIX "i686-w64-mingw32")
# this one is important
SET(CMAKE_SYSTEM_NAME Windows)
# specify the cross compiler
SET(CMAKE_C_COMPILER ccache i686-w64-mingw32-gcc)
SET(CMAKE_CXX_COMPILER ccache i686-w64-mingw32-g++)
SET(CMAKE_C_COMPILER ccache ${MINGW_PREFIX}-gcc)
SET(CMAKE_CXX_COMPILER ccache ${MINGW_PREFIX}-g++)
SET(CMAKE_RC_COMPILER /usr/bin/${MINGW_PREFIX}-windres)
# where is the target environment containing libraries
SET(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32/sys-root/mingw)
SET(CMAKE_FIND_ROOT_PATH /usr/${MINGW_PREFIX}/sys-root/mingw)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# windres executable for application icon support
SET(WINDRES_EXECUTABLE /usr/bin/i686-w64-mingw32-windres)
# libs with broken find modules
SET(TAGLIB_FOUND true)
SET(TAGLIB_LIBRARIES ${CMAKE_FIND_ROOT_PATH}/lib/libtag.dll.a)
SET(TAGLIB_INCLUDES ${CMAKE_FIND_ROOT_PATH}/include/taglib)
SET(QT_PLUGINS_DIR ${CMAKE_FIND_ROOT_PATH}/lib/qt4/plugins/)
SET(QT_QTUITOOLS_LIBRARY_RELEASE ${CMAKE_FIND_ROOT_PATH}/lib/libQtUiTools.a)
SET(QT_QTUITOOLS_LIBRARY_DEBUG ${CMAKE_FIND_ROOT_PATH}/lib/libQtUiToolsd.a)
SET(QT_QTUITOOLS_LIBRARY ${QT_QTUITOOLS_LIBRARY_RELEASE})

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -10,6 +10,7 @@
<file>data/images/not-loved.png</file>
<file>data/images/no-album-art-placeholder.png</file>
<file>data/images/no-artist-image-placeholder.png</file>
<file>data/images/track-placeholder.png</file>
<file>data/images/now-playing-panel.png</file>
<file>data/images/now-playing-speaker.png</file>
<file>data/images/pause-pressed.png</file>
@ -85,6 +86,7 @@
<file>data/images/station.png</file>
<file>data/images/new-additions.png</file>
<file>data/images/loved_playlist.png</file>
<file>data/images/dashboard.png</file>
<file>data/stylesheets/topbar-radiobuttons.css</file>
<file>data/icons/tomahawk-icon-16x16.png</file>
<file>data/icons/tomahawk-icon-32x32.png</file>

View File

@ -49,4 +49,8 @@ if (APPLE)
)
ENDIF()
FILE( WRITE ${CMAKE_BINARY_DIR}/Info.plist "${edited_plist}" )
FILE(COPY ${CMAKE_SOURCE_DIR}/admin/mac/sparkle_pub.pem
DESTINATION "${CMAKE_BINARY_DIR}/tomahawk.app/Contents/Resources")
endif (APPLE)

View File

@ -14,7 +14,7 @@ SET( QT_USE_QTXML TRUE )
SET( QT_USE_QTWEBKIT TRUE )
INCLUDE( ${QT_USE_FILE} )
INCLUDE( ${CMAKE_MODULE_PATH}/AddAppIconMacro.cmake )
INCLUDE( AddAppIconMacro )
#SET( CMAKE_BUILD_TYPE "Release" )
SET( CMAKE_VERBOSE_MAKEFILE ON )

View File

@ -43,6 +43,7 @@ PipelineStatusView::PipelineStatusView( AnimatedSplitter* parent )
headers << tr( "Searching For" ) << tr( "Pending" );
m_tree->setHeaderLabels( headers );
m_tree->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
m_tree->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Ignored );
m_tree->setColumnCount( 2 );
m_tree->setColumnWidth( 0, 200 );
@ -59,6 +60,17 @@ PipelineStatusView::PipelineStatusView( AnimatedSplitter* parent )
connect( Pipeline::instance(), SIGNAL( resolving( Tomahawk::query_ptr ) ), SLOT( onPipelineUpdate( Tomahawk::query_ptr ) ) );
connect( Pipeline::instance(), SIGNAL( idle() ), SLOT( onPipelineUpdate() ) );
#ifndef Q_WS_WIN
QFont f = font();
f.setPointSize( f.pointSize() - 1 );
setFont( f );
#endif
#ifdef Q_WS_MAC
f.setPointSize( f.pointSize() - 2 );
setFont( f );
#endif
onPipelineUpdate();
}

View File

@ -50,8 +50,6 @@ AudioControls::AudioControls( QWidget* parent )
ui->setupUi( this );
setAcceptDrops( true );
ui->buttonAreaLayout->setSpacing( 2 );
QFont font( ui->artistTrackLabel->font() );
font.setPixelSize( 12 );
@ -181,6 +179,15 @@ AudioControls::AudioControls( QWidget* parent )
connect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ), SLOT( infoSystemFinished( QString ) ) );
ui->buttonAreaLayout->setSpacing( 0 );
ui->stackedLayout->setSpacing( 0 );
ui->stackedLayout->setContentsMargins( 0, 0, 0, 0 );
ui->stackedLayout->setMargin( 0 );
ui->playPauseButton->setContentsMargins( 0, 0, 0, 0 );
ui->pauseButton->setContentsMargins( 0, 0, 0, 0 );
ui->stackedLayout->setSizeConstraint( QLayout::SetFixedSize );
onPlaybackStopped(); // initial state
}
@ -301,10 +308,8 @@ AudioControls::onPlaybackLoading( const Tomahawk::result_ptr& result )
/* m_playAction->setEnabled( false );
m_pauseAction->setEnabled( true ); */
ui->pauseButton->setEnabled( true );
ui->pauseButton->setVisible( true );
ui->playPauseButton->setVisible( false );
ui->playPauseButton->setEnabled( false );
ui->stackedLayout->setCurrentWidget( ui->pauseButton );
ui->loveButton->setEnabled( true );
ui->loveButton->setVisible( true );
@ -341,23 +346,16 @@ AudioControls::onPlaybackPaused()
/* m_pauseAction->setEnabled( false );
m_playAction->setEnabled( true ); */
ui->pauseButton->setVisible( false );
ui->pauseButton->setEnabled( false );
ui->playPauseButton->setEnabled( true );
ui->playPauseButton->setVisible( true );
ui->stackedLayout->setCurrentWidget( ui->playPauseButton );
}
void
AudioControls::onPlaybackResumed()
{
/* m_playAction->setEnabled( false );
m_pauseAction->setEnabled( true ); */
ui->playPauseButton->setVisible( false );
ui->playPauseButton->setEnabled( false );
ui->pauseButton->setVisible( true );
ui->pauseButton->setEnabled( true );
ui->stackedLayout->setCurrentWidget( ui->pauseButton );
ui->loveButton->setVisible( true );
}
@ -375,10 +373,7 @@ AudioControls::onPlaybackStopped()
ui->coverImage->setPixmap( QPixmap() );
ui->seekSlider->setVisible( false );
ui->pauseButton->setVisible( false );
ui->pauseButton->setEnabled( false );
ui->playPauseButton->setEnabled( true );
ui->playPauseButton->setVisible( true );
ui->stackedLayout->setCurrentWidget( ui->playPauseButton );
ui->loveButton->setEnabled( false );
ui->loveButton->setVisible( false );

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>939</width>
<width>929</width>
<height>80</height>
</rect>
</property>
@ -60,7 +60,7 @@
</property>
<layout class="QHBoxLayout" name="buttonAreaLayout">
<item>
<spacer name="horizontalSpacer">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
@ -80,18 +80,25 @@
</widget>
</item>
<item>
<widget class="ImageButton" name="playPauseButton">
<property name="text">
<string>Play</string>
<layout class="QStackedLayout" name="stackedLayout">
<property name="spacing">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="ImageButton" name="pauseButton">
<property name="text">
<string>Pause</string>
</property>
</widget>
<item>
<widget class="ImageButton" name="playPauseButton">
<property name="text">
<string>Play</string>
</property>
</widget>
</item>
<item>
<widget class="ImageButton" name="pauseButton">
<property name="text">
<string>Pause</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="ImageButton" name="nextButton">
@ -101,7 +108,7 @@
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>

View File

@ -173,6 +173,7 @@ set( libSources
utils/xspfgenerator.cpp
utils/jspfloader.cpp
utils/spotifyparser.cpp
utils/rdioparser.cpp
utils/shortenedlinkparser.cpp
widgets/newplaylistwidget.cpp
@ -185,6 +186,7 @@ set( libSources
widgets/SocialPlaylistWidget.cpp
widgets/infowidgets/sourceinfowidget.cpp
widgets/infowidgets/ArtistInfoWidget.cpp
widgets/infowidgets/AlbumInfoWidget.cpp
kdsingleapplicationguard/kdsingleapplicationguard.cpp
kdsingleapplicationguard/kdsharedmemorylocker.cpp
@ -352,6 +354,7 @@ set( libHeaders
utils/xspfgenerator.h
utils/jspfloader.h
utils/spotifyparser.h
utils/rdioparser.h
utils/shortenedlinkparser.h
widgets/newplaylistwidget.h
@ -364,6 +367,7 @@ set( libHeaders
widgets/SocialPlaylistWidget.h
widgets/infowidgets/sourceinfowidget.h
widgets/infowidgets/ArtistInfoWidget.h
widgets/infowidgets/AlbumInfoWidget.h
kdsingleapplicationguard/kdsingleapplicationguard.h
)
@ -387,6 +391,7 @@ set( libUI ${libUI}
widgets/SocialPlaylistWidget.ui
widgets/infowidgets/sourceinfowidget.ui
widgets/infowidgets/ArtistInfoWidget.ui
widgets/infowidgets/AlbumInfoWidget.ui
playlist/topbar/topbar.ui
playlist/infobar/infobar.ui
)
@ -488,7 +493,9 @@ target_link_libraries( tomahawklib
${TAGLIB_LIBRARIES}
${CLUCENE_LIBRARIES}
${LIBECHONEST_LIBRARY}
${QT_QTUITOOLS_LIBRARY}
${QT_LIBRARIES}
${QT_QTUITOOLS_LIBRARY} # We really need to link twice against it for windows, maybe QTBUG-20498 is related
${OS_SPECIFIC_LINK_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
${LINK_LIBRARIES}

View File

@ -46,6 +46,7 @@
#include "utils/jspfloader.h"
#include "utils/spotifyparser.h"
#include "utils/shortenedlinkparser.h"
#include "utils/rdioparser.h"
GlobalActionManager* GlobalActionManager::s_instance = 0;
@ -791,14 +792,20 @@ GlobalActionManager::acceptsMimeData( const QMimeData* data, bool tracksOnly )
// crude check for spotify tracks
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "spotify" ) &&
( tracksOnly ? data->data( "text/plain" ).contains( "track" ) : true ) )
( tracksOnly ? data->data( "text/plain" ).contains( "track" ) : true ) )
return true;
// crude check for rdio tracks
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "rdio.com" ) &&
( tracksOnly ? data->data( "text/plain" ).contains( "track" ) : true ) )
return true;
// We whitelist t.co and bit.ly (and j.mp) since they do some link checking. Often playable (e.g. spotify..) links hide behind them,
// so we do an extra level of lookup
if ( ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "bit.ly" ) ) ||
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "j.mp" ) ) ||
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "t.co" ) ) )
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "t.co" ) ) ||
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "rd.io" ) ) )
return true;
return false;
@ -831,9 +838,18 @@ GlobalActionManager::handleTrackUrls( const QString& urls )
tDebug() << "Got a list of spotify urls!" << tracks;
SpotifyParser* spot = new SpotifyParser( tracks, this );
connect( spot, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ) );
} else if ( urls.contains( "rdio.com" ) )
{
QStringList tracks = urls.split( "\n" );
tDebug() << "Got a list of rdio urls!" << tracks;
RdioParser* rdio = new RdioParser( this );
connect( rdio, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ) );
rdio->parse( tracks );
} else if ( urls.contains( "bit.ly" ) ||
urls.contains( "j.mp" ) ||
urls.contains( "t.co" ) )
urls.contains( "t.co" ) ||
urls.contains( "rd.io" ) )
{
QStringList tracks = urls.split( "\n" );
@ -909,3 +925,14 @@ GlobalActionManager::openSpotifyLink( const QString& link )
return true;
}
bool
GlobalActionManager::openRdioLink( const QString& link )
{
RdioParser* rdio = new RdioParser( this );
connect( rdio, SIGNAL( track( Tomahawk::query_ptr ) ), this, SLOT( handleOpenTrack( Tomahawk::query_ptr ) ) );
rdio->parse( link );
return true;
}

View File

@ -44,6 +44,9 @@ public:
/// Takes a spotify link and performs the default open action on it
bool openSpotifyLink( const QString& link );
/// Takes a spotify link and performs the default open action on it
bool openRdioLink( const QString& link );
void copyToClipboard( const Tomahawk::query_ptr& query ) const;
QString copyPlaylistToClipboard( const Tomahawk::dynplaylist_ptr& playlist );
void savePlaylistToFile( const Tomahawk::playlist_ptr& playlist, const QString& filename );

View File

@ -66,9 +66,9 @@ public:
}
public slots:
void resolve( const query_ptr& q, bool prioritized = false, bool temporaryQuery = false );
void resolve( const QList<query_ptr>& qlist, bool prioritized = false, bool temporaryQuery = false );
void resolve( QID qid, bool prioritized = false, bool temporaryQuery = false );
void resolve( const query_ptr& q, bool prioritized = true, bool temporaryQuery = false );
void resolve( const QList<query_ptr>& qlist, bool prioritized = true, bool temporaryQuery = false );
void resolve( QID qid, bool prioritized = true, bool temporaryQuery = false );
void start();
void stop();

View File

@ -43,6 +43,7 @@ CustomPlaylistView::CustomPlaylistView( CustomPlaylistView::PlaylistType type, c
connect( m_source.data(), SIGNAL( socialAttributesChanged() ), this, SLOT( reload() ) );
else if ( m_type == AllLovedTracks )
{
connect( SourceList::instance()->getLocal().data(), SIGNAL( socialAttributesChanged() ), this, SLOT( reload() ) );
foreach ( const source_ptr& s, SourceList::instance()->sources( true ) )
connect( s.data(), SIGNAL( socialAttributesChanged() ), this, SLOT( reload() ) );

View File

@ -219,4 +219,6 @@ private:
}; // namespace
Q_DECLARE_METATYPE( QSharedPointer< Tomahawk::DynamicPlaylist > )
#endif

View File

@ -401,8 +401,8 @@ EchonestGenerator::appendRadioType( Echonest::DynamicPlaylist::PlaylistParams& p
params.append( Echonest::DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Type, Echonest::DynamicPlaylist::ArtistRadioType ) );
else if( onlyThisArtistType( Echonest::DynamicPlaylist::SongRadioType ) )
params.append( Echonest::DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Type, Echonest::DynamicPlaylist::SongRadioType ) );
else // no artist or song or description types. default to song-radio
params.append( Echonest::DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Type, Echonest::DynamicPlaylist::SongRadioType ) );
else // no artist or song or description types. default to artist-description
params.append( Echonest::DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Type, Echonest::DynamicPlaylist::ArtistDescriptionType ) );
return static_cast< Echonest::DynamicPlaylist::ArtistTypeEnum >( params.last().second.toInt() );
}

View File

@ -427,6 +427,17 @@ DynamicWidget::paintRoundedFilledRect( QPainter& p, QPalette& pal, QRect& r, qre
p.drawRoundedRect( r, 10, 10 );
}
QPixmap
DynamicWidget::pixmap() const
{
if ( m_playlist->mode() == OnDemand )
return QPixmap( RESPATH "images/station.png" );
else if ( m_playlist->mode() == Static )
return QPixmap( RESPATH "images/automatic-playlist.png" );
else
return QPixmap();
}
bool
DynamicWidget::jumpToCurrentTrack()

View File

@ -77,7 +77,7 @@ public:
virtual QString title() const { return m_model->title(); }
virtual QString description() const { return m_model->description(); }
virtual QPixmap pixmap() const { return QPixmap( RESPATH "images/playlist-icon.png" ); }
virtual QPixmap pixmap() const;
virtual bool jumpToCurrentTrack();

View File

@ -57,6 +57,8 @@ PlaylistItemDelegate::PlaylistItemDelegate( TrackView* parent, TrackProxyModel*
m_centerOption = QTextOption( Qt::AlignVCenter );
m_centerOption.setWrapMode( QTextOption::NoWrap );
m_defaultAvatar = TomahawkUtils::createAvatarFrame( QPixmap( RESPATH "images/user-avatar.png" ) );
}
@ -75,7 +77,7 @@ PlaylistItemDelegate::sizeHint( const QStyleOptionViewItem& option, const QModel
if ( index.isValid() )
{
int style = index.data( TrackModel::StyleRole ).toInt();
if ( style == TrackModel::Short )
if ( style == TrackModel::Short || style == TrackModel::ShortWithAvatars )
size.setHeight( 44 );
}
@ -135,12 +137,14 @@ PlaylistItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& opti
case TrackModel::Short:
paintShort( painter, option, index );
break;
case TrackModel::ShortWithAvatars:
paintShort( painter, option, index, true );
}
}
void
PlaylistItemDelegate::paintShort( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
PlaylistItemDelegate::paintShort( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index, bool useAvatars ) const
{
TrackModelItem* item = m_model->itemFromIndex( m_model->mapToSource( index ) );
Q_ASSERT( item );
@ -184,11 +188,14 @@ PlaylistItemDelegate::paintShort( QPainter* painter, const QStyleOptionViewItem&
else
lowerText = QString( "played %1 ago by %2" ).arg( playtime ).arg( source->friendlyName() );
pixmap = source->avatar();
if ( useAvatars )
pixmap = source->avatar( Source::FancyStyle );
}
if ( pixmap.isNull() )
pixmap = QPixmap( RESPATH "images/user-avatar.png" );
if ( pixmap.isNull() && !useAvatars )
pixmap = QPixmap( RESPATH "images/track-placeholder.png" );
else if ( pixmap.isNull() && useAvatars )
pixmap = m_defaultAvatar;
painter->save();
{
@ -227,7 +234,8 @@ PlaylistItemDelegate::paintShort( QPainter* painter, const QStyleOptionViewItem&
QString text = painter->fontMetrics().elidedText( upperText, Qt::ElideRight, r.width() );
painter->drawText( r.adjusted( 0, 1, 0, 0 ), text, m_topOption );
painter->setFont( opt.font );
painter->setFont( opt.font);
text = painter->fontMetrics().elidedText( lowerText, Qt::ElideRight, r.width() );
painter->drawText( r.adjusted( 0, 1, 0, 0 ), text, m_bottomOption );
}
@ -261,11 +269,7 @@ PlaylistItemDelegate::paintDetailed( QPainter* painter, const QStyleOptionViewIt
if ( index.column() == TrackModel::Score )
{
#ifdef Q_OS_MAC // On Mac, highlight color is very bright and stands out a lot
QColor barColor( 167, 183, 211 ); // This matches the sidebar (sourcetreeview.cpp:672)
#else
QColor barColor = opt.palette.highlight().color();
#endif
if ( opt.state & QStyle::State_Selected )
painter->setPen( opt.palette.brightText().color() );
else

View File

@ -50,12 +50,12 @@ private:
void prepareStyleOption( QStyleOptionViewItemV4* option, const QModelIndex& index, TrackModelItem* item ) const;
void paintDetailed( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
void paintShort( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
void paintShort( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index, bool useAvatars = false ) const;
unsigned int m_removalProgress;
mutable QHash< qint64, QPixmap > m_cache;
QPixmap m_nowPlayingIcon;
QPixmap m_nowPlayingIcon, m_defaultAvatar;
mutable QPixmap m_arrowIcon;
QTextOption m_topOption;

View File

@ -116,7 +116,7 @@ PlaylistModel::loadPlaylist( const Tomahawk::playlist_ptr& playlist, bool loadEn
m_waitingForResolved.clear();
foreach( const plentry_ptr& entry, entries )
{
qDebug() << entry->query()->toString();
// qDebug() << entry->query()->toString();
plitem = new TrackModelItem( entry, m_rootItem );
plitem->index = createIndex( m_rootItem->children.count() - 1, 0, plitem );

View File

@ -34,7 +34,7 @@ Q_OBJECT
public:
enum TrackItemStyle
{ Detailed = 0, Short = 1 };
{ Detailed = 0, Short = 1, ShortWithAvatars = 2 };
enum TrackModelRole
{ StyleRole = Qt::UserRole + 1 };

View File

@ -56,6 +56,7 @@ explicit TrackView( QWidget* parent = 0 );
TrackHeader* header() const { return m_header; }
OverlayWidget* overlay() const { return m_overlay; }
Tomahawk::ContextMenu* contextMenu() const { return m_contextMenu; }
LoadingSpinner* loadingSpinner() const { return m_loadingSpinner; }
QModelIndex hoveredIndex() const { return m_hoveredIndex; }
QModelIndex contextMenuIndex() const { return m_contextMenuIndex; }

View File

@ -38,9 +38,12 @@ using namespace Tomahawk;
query_ptr
Query::get( const QString& artist, const QString& track, const QString& album, const QID& qid, bool autoResolve )
{
if ( qid.isEmpty() )
autoResolve = false;
query_ptr q = query_ptr( new Query( artist, track, album, qid, autoResolve ) );
if ( autoResolve && !qid.isEmpty() )
if ( autoResolve )
Pipeline::instance()->resolve( q );
return q;
}

View File

@ -127,10 +127,17 @@ Source::setAvatar( const QPixmap& avatar )
QPixmap
Source::avatar() const
Source::avatar( AvatarStyle style ) const
{
if( !m_avatar.isNull() )
return TomahawkUtils::createAvatarFrame( m_avatar );
if ( style == FancyStyle &&
!m_avatar.isNull() &&
m_fancyAvatar.isNull() )
m_fancyAvatar = TomahawkUtils::createAvatarFrame( m_avatar );
if ( style == Original && !m_avatar.isNull() )
return m_avatar;
else if ( style == FancyStyle && !m_fancyAvatar.isNull() )
return m_fancyAvatar;
else
return QPixmap();
}

View File

@ -45,6 +45,8 @@ friend class ::DBSyncConnection;
friend class ::DatabaseCommand_SocialAction;
public:
enum AvatarStyle { Original, FancyStyle };
explicit Source( int id, const QString& username = QString() );
virtual ~Source();
@ -58,7 +60,7 @@ public:
void setFriendlyName( const QString& fname );
void setAvatar( const QPixmap& avatar );
QPixmap avatar() const;
QPixmap avatar( AvatarStyle style = Original ) const;
collection_ptr collection() const;
void addCollection( const Tomahawk::collection_ptr& c );
@ -132,6 +134,7 @@ private:
ControlConnection* m_cc;
QPixmap m_avatar;
mutable QPixmap m_fancyAvatar;
Tomahawk::playlistinterface_ptr m_playlistInterface;
};

View File

@ -80,6 +80,13 @@ ProxyStyle::drawControl( ControlElement ce, const QStyleOption* opt, QPainter* p
p->setPen( QColor( 0x8c, 0x8c, 0x8c ) );
p->drawLine( opt->rect.topLeft(), opt->rect.bottomRight() );
}
#ifndef Q_WS_MAC
else
{
p->setPen( QColor( 0xff, 0xff, 0xff ) );
p->drawLine( opt->rect.topLeft(), opt->rect.bottomRight() );
}
#endif
}
else
QProxyStyle::drawControl( ce, opt, p, w );

View File

@ -0,0 +1,101 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
*
* Tomahawk 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.
*
* Tomahawk 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 Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "rdioparser.h"
#include <QUrl>
#include <QStringList>
using namespace Tomahawk;
RdioParser::RdioParser( QObject* parent )
: QObject( parent )
, m_count( 0 )
{
}
RdioParser::~RdioParser()
{
}
void
RdioParser::parse( const QString& url )
{
m_multi = false;
m_total = 1;
parseUrl( url );
}
void
RdioParser::parse( const QStringList& urls )
{
m_multi = true;
m_total = urls.count();
foreach( const QString& url, urls )
parseUrl( url );
}
void
RdioParser::parseUrl( const QString& url )
{
query_ptr query;
m_count++;
if ( url.contains( "artist" ) && url.contains( "album" ) )
{
// this is a "full" url, no redirection needed
QString realUrl = QUrl::fromUserInput( url ).toString().replace( "_", " " );
QString artist, trk, album;
QString matchStr = "/%1/([^/]*)/";
QRegExp r( QString( matchStr ).arg( "artist" ) );
int loc = r.indexIn( realUrl );
if ( loc >= 0 )
artist = r.cap( 1 );
r = QRegExp( QString( matchStr ).arg( "album" ) );
loc = r.indexIn( realUrl );
if ( loc >= 0 )
album = r.cap( 1 );
r = QRegExp( QString( matchStr ).arg( "track" ) );
loc = r.indexIn( realUrl );
if ( loc >= 0 )
trk = r.cap( 1 );
if ( !trk.isEmpty() && !artist.isEmpty() )
{
query = Query::get( artist, trk, album, uuid(), true );
}
}
if ( m_multi )
{
if ( !query.isNull() )
m_queries << query;
if ( m_count == m_total )
emit tracks( m_queries );
}
if ( !m_multi && !query.isNull() )
emit track( query );
}

View File

@ -0,0 +1,62 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
*
* Tomahawk 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.
*
* Tomahawk 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 Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef RDIOPARSER_H
#define RDIOPARSER_H
#include <QtCore/QObject>
#include <QStringList>
#include "query.h"
#include "source.h"
class QNetworkReply;
namespace Tomahawk
{
/**
* Small class to parse spotify links into query_ptrs
*
* Connect to the signals to get the results
*/
class RdioParser : public QObject
{
Q_OBJECT
public:
explicit RdioParser( QObject* parent = 0 );
virtual ~RdioParser();
void parse( const QString& url );
void parse( const QStringList& urls );
signals:
void track( const Tomahawk::query_ptr& track );
void tracks( const QList< Tomahawk::query_ptr > tracks );
private:
void parseUrl( const QString& url );
bool m_multi;
int m_count, m_total;
QList< query_ptr > m_queries;
};
}
#endif // RDIOPARSER_H

View File

@ -44,7 +44,8 @@ ShortenedLinkParser::lengthenUrl( const QString& url )
// Whitelisted links
if ( !( url.contains( "t.co" ) ||
url.contains( "bit.ly" ) ||
url.contains( "j.mp" ) ) )
url.contains( "j.mp" ) ||
url.contains( "rd.io" ) ) )
return;
tDebug() << "Looking up..." << url;

View File

@ -349,6 +349,46 @@ createDragPixmap( int itemCount )
return dragPixmap;
}
void
drawBackgroundAndNumbers( QPainter* painter, const QString& text, const QRect& figRectIn )
{
QRect figRect = figRectIn;
if ( text.length() == 1 )
figRect.adjust( -painter->fontMetrics().averageCharWidth(), 0, 0, 0 );
QPen origpen = painter->pen();
QPen pen = origpen;
pen.setWidth( 1.0 );
painter->setPen( pen );
painter->drawRect( figRect );
// circles look bad. make it an oval. (thanks, apple)
const int bulgeWidth = 8;
const int offset = 0; // number of pixels to begin, counting inwards from figRect.x() and figRect.width(). 0 means start at each end, negative means start inside the rect.
QPainterPath ppath;
ppath.moveTo( QPoint( figRect.x() + offset, figRect.y() + figRect.height() / 2 ) );
QRect leftArcRect( figRect.x() + offset - bulgeWidth, figRect.y(), 2*bulgeWidth, figRect.height() );
ppath.arcTo( leftArcRect, 90, 180 );
painter->drawPath( ppath );
ppath = QPainterPath();
ppath.moveTo( figRect.x() + figRect.width() - offset, figRect.y() + figRect.height() / 2 );
leftArcRect = QRect( figRect.x() + figRect.width() - offset - bulgeWidth, figRect.y(), 2*bulgeWidth, figRect.height() );
ppath.arcTo( leftArcRect, 270, 180 );
painter->drawPath( ppath );
painter->setPen( origpen );
#ifdef Q_OS_MAC
figRect.adjust( -1, 0, 0, 0 );
#endif
QTextOption to( Qt::AlignCenter );
painter->setPen( Qt::white );
painter->drawText( figRect.adjusted( -5, 0, 6, 0 ), text, to );
}
void
unmarginLayout( QLayout* layout )

View File

@ -25,9 +25,11 @@
#include <QThread>
#include <QNetworkProxy>
#include <QStringList>
#include <QRect>
#define RESPATH ":/data/"
class QPainter;
class QColor;
class QDir;
class QDateTime;
@ -74,6 +76,8 @@ namespace TomahawkUtils
DLLEXPORT QColor alphaBlend( const QColor& colorFrom, const QColor& colorTo, float opacity );
DLLEXPORT QPixmap createDragPixmap( int itemCount = 1 );
DLLEXPORT void drawBackgroundAndNumbers( QPainter* p, const QString& text, const QRect& rect );
DLLEXPORT void unmarginLayout( QLayout* layout );
DLLEXPORT NetworkProxyFactory* proxyFactory();

View File

@ -46,6 +46,7 @@
#include "widgets/welcomewidget.h"
#include "widgets/infowidgets/sourceinfowidget.h"
#include "widgets/infowidgets/ArtistInfoWidget.h"
#include "widgets/infowidgets/AlbumInfoWidget.h"
#include "widgets/newplaylistwidget.h"
#include "utils/logger.h"
@ -79,10 +80,12 @@ ViewManager::ViewManager( QObject* parent )
m_infobar = new InfoBar();
m_stack = new QStackedWidget();
#ifdef Q_OS_MAC
QFrame* line = new QFrame();
line->setFrameStyle( QFrame::HLine );
line->setStyleSheet( "border: 1px solid gray;" );
line->setMaximumHeight( 1 );
#endif
m_splitter = new AnimatedSplitter();
m_splitter->setOrientation( Qt::Vertical );
@ -100,7 +103,9 @@ ViewManager::ViewManager( QObject* parent )
m_widget->layout()->addWidget( m_infobar );
m_widget->layout()->addWidget( m_topbar );
#ifdef Q_OS_MAC
m_widget->layout()->addWidget( line );
#endif
m_widget->layout()->addWidget( m_splitter );
m_superCollectionView = new ArtistView();
@ -237,27 +242,19 @@ ViewManager::show( const Tomahawk::artist_ptr& artist )
Tomahawk::ViewPage*
ViewManager::show( const Tomahawk::album_ptr& album )
{
PlaylistView* view;
AlbumInfoWidget* swidget;
if ( !m_albumViews.contains( album ) )
{
view = new PlaylistView();
PlaylistModel* model = new PlaylistModel();
model->append( album );
view->setPlaylistModel( model );
view->setFrameShape( QFrame::NoFrame );
view->setAttribute( Qt::WA_MacShowFocusRect, 0 );
m_albumViews.insert( album, view );
swidget = new AlbumInfoWidget( album );
m_albumViews.insert( album, swidget );
}
else
{
view = m_albumViews.value( album );
swidget = m_albumViews.value( album );
}
setPage( view );
emit numSourcesChanged( 1 );
return view;
setPage( swidget );
return swidget;
}

View File

@ -33,6 +33,7 @@
class AnimatedSplitter;
class AlbumModel;
class AlbumView;
class AlbumInfoWidget;
class ArtistInfoWidget;
class ArtistView;
class CollectionModel;
@ -188,7 +189,7 @@ private:
QHash< Tomahawk::collection_ptr, ArtistView* > m_treeViews;
QHash< Tomahawk::collection_ptr, AlbumView* > m_collectionAlbumViews;
QHash< Tomahawk::artist_ptr, ArtistInfoWidget* > m_artistViews;
QHash< Tomahawk::album_ptr, PlaylistView* > m_albumViews;
QHash< Tomahawk::album_ptr, AlbumInfoWidget* > m_albumViews;
QHash< Tomahawk::playlist_ptr, PlaylistView* > m_playlistViews;
QHash< Tomahawk::source_ptr, SourceInfoWidget* > m_sourceViews;

View File

@ -0,0 +1,162 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
*
* Tomahawk 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.
*
* Tomahawk 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 Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AlbumInfoWidget.h"
#include "ui_AlbumInfoWidget.h"
#include "viewmanager.h"
#include "playlist/treemodel.h"
#include "playlist/albummodel.h"
#include "database/databasecommand_alltracks.h"
#include "database/databasecommand_allalbums.h"
#include "utils/tomahawkutils.h"
#include "utils/logger.h"
#include "widgets/overlaywidget.h"
static QString s_aiInfoIdentifier = QString( "AlbumInfoWidget" );
using namespace Tomahawk;
AlbumInfoWidget::AlbumInfoWidget( const Tomahawk::album_ptr& album, QWidget* parent )
: QWidget( parent )
, ui( new Ui::AlbumInfoWidget )
, m_album( album )
{
ui->setupUi( this );
ui->albumsView->setFrameShape( QFrame::NoFrame );
ui->albumsView->setAttribute( Qt::WA_MacShowFocusRect, 0 );
ui->tracksView->setFrameShape( QFrame::NoFrame );
ui->tracksView->setAttribute( Qt::WA_MacShowFocusRect, 0 );
TomahawkUtils::unmarginLayout( layout() );
m_albumsModel = new AlbumModel( ui->albumsView );
ui->albumsView->setAlbumModel( m_albumsModel );
m_tracksModel = new TreeModel( ui->tracksView );
ui->tracksView->setTreeModel( m_tracksModel );
m_pixmap = QPixmap( RESPATH "images/no-album-art-placeholder.png" ).scaledToWidth( 48, Qt::SmoothTransformation );
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
connect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ), SLOT( infoSystemFinished( QString ) ) );
load( album );
}
AlbumInfoWidget::~AlbumInfoWidget()
{
delete ui;
}
void
AlbumInfoWidget::load( const album_ptr& album )
{
m_title = album->name();
m_description = album->artist()->name();
m_tracksModel->addTracks( album, QModelIndex() );
QList<album_ptr> al;
al << album;
m_albumsModel->addAlbums( al );
Tomahawk::InfoSystem::InfoCriteriaHash trackInfo;
trackInfo["artist"] = album->artist()->name();
trackInfo["album"] = album->name();
Tomahawk::InfoSystem::InfoRequestData requestData;
requestData.caller = s_aiInfoIdentifier;
requestData.type = Tomahawk::InfoSystem::InfoAlbumCoverArt;
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo );
requestData.customData = QVariantMap();
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
}
void
AlbumInfoWidget::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
{
if ( requestData.caller != s_aiInfoIdentifier )
{
return;
}
InfoSystem::InfoCriteriaHash trackInfo;
trackInfo = requestData.input.value< InfoSystem::InfoCriteriaHash >();
if ( output.canConvert< QVariantMap >() )
{
if ( trackInfo["album"] != m_album->name() )
{
qDebug() << "Returned info was for:" << trackInfo["album"] << "- was looking for:" << m_album->name();
return;
}
}
QVariantMap returnedData = output.value< QVariantMap >();
switch ( requestData.type )
{
case Tomahawk::InfoSystem::InfoAlbumCoverArt:
{
QVariantMap returnedData = output.value< QVariantMap >();
const QByteArray ba = returnedData["imgbytes"].toByteArray();
if ( ba.length() )
{
m_pixmap.loadFromData( ba );
emit pixmapChanged( m_pixmap );
}
}
default:
return;
}
}
void
AlbumInfoWidget::infoSystemFinished( QString target )
{
Q_UNUSED( target );
}
void
AlbumInfoWidget::changeEvent( QEvent* e )
{
QWidget::changeEvent( e );
switch ( e->type() )
{
case QEvent::LanguageChange:
ui->retranslateUi( this );
break;
default:
break;
}
}

View File

@ -0,0 +1,106 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
*
* Tomahawk 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.
*
* Tomahawk 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 Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* \class AlbumInfoWidget
* \brief ViewPage, which displays an album for an artist and recommends others.
*
* This Tomahawk ViewPage displays the tracks of any given album
* It is our default ViewPage when showing an artist via ViewManager.
*
*/
#ifndef ALBUMINFOWIDGET_H
#define ALBUMINFOWIDGET_H
#include <QWidget>
#include "artist.h"
#include "result.h"
#include "playlistinterface.h"
#include "viewpage.h"
#include "infosystem/infosystem.h"
#include "dllmacro.h"
class AlbumModel;
class TreeModel;
namespace Ui
{
class AlbumInfoWidget;
}
class DLLEXPORT AlbumInfoWidget : public QWidget, public Tomahawk::ViewPage
{
Q_OBJECT
public:
AlbumInfoWidget( const Tomahawk::album_ptr& album, QWidget* parent = 0 );
~AlbumInfoWidget();
/** \brief Loads information for a given album.
* \param album The album that you want to load information for.
*
* Calling this method will make AlbumInfoWidget load information about
* an album, and related other albums. This method will be automatically
* called by the constructor, but you can use it to load another album's
* information at any point.
*/
void load( const Tomahawk::album_ptr& album );
virtual QWidget* widget() { return this; }
virtual Tomahawk::PlaylistInterface* playlistInterface() const { return 0; }
virtual QString title() const { return m_title; }
virtual QString description() const { return m_description; }
virtual QString longDescription() const { return m_longDescription; }
virtual QPixmap pixmap() const { if ( m_pixmap.isNull() ) return Tomahawk::ViewPage::pixmap(); else return m_pixmap; }
virtual bool isTemporaryPage() const { return true; }
virtual bool showStatsBar() const { return false; }
virtual bool jumpToCurrentTrack() { return false; }
signals:
void longDescriptionChanged( const QString& description );
void descriptionChanged( const QString& description );
void pixmapChanged( const QPixmap& pixmap );
protected:
void changeEvent( QEvent* e );
private slots:
void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
void infoSystemFinished( QString target );
private:
Ui::AlbumInfoWidget *ui;
Tomahawk::album_ptr m_album;
AlbumModel* m_albumsModel;
TreeModel* m_tracksModel;
QString m_title;
QString m_description;
QString m_longDescription;
QPixmap m_pixmap;
};
#endif // ALBUMINFOWIDGET_H

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AlbumInfoWidget</class>
<widget class="QWidget" name="AlbumInfoWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>902</width>
<height>696</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="ArtistView" name="tracksView"/>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="HeaderLabel" name="albumsLabel">
<property name="text">
<string>Other Albums by Artist</string>
</property>
</widget>
</item>
<item>
<widget class="AlbumView" name="albumsView"/>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>HeaderLabel</class>
<extends>QLabel</extends>
<header location="global">widgets/HeaderLabel.h</header>
</customwidget>
<customwidget>
<class>ArtistView</class>
<extends>QTreeView</extends>
<header location="global">artistview.h</header>
</customwidget>
<customwidget>
<class>AlbumView</class>
<extends>QListView</extends>
<header>playlist/albumview.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -59,6 +59,8 @@ ArtistInfoWidget::ArtistInfoWidget( const Tomahawk::artist_ptr& artist, QWidget*
m_relatedModel = new TreeModel( ui->relatedArtists );
ui->relatedArtists->setTreeModel( m_relatedModel );
ui->relatedArtists->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
ui->relatedArtists->header()->setVisible( false );
m_topHitsModel = new PlaylistModel( ui->topHits );
m_topHitsModel->setStyle( TrackModel::Short );
@ -72,12 +74,10 @@ ArtistInfoWidget::ArtistInfoWidget( const Tomahawk::artist_ptr& artist, QWidget*
connect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ), SLOT( infoSystemFinished( QString ) ) );
// Apparently headers can only be removed when it's already visible / layed-out
QTimer::singleShot( 0, this ,SLOT( removeHeaders() ) );
load( artist );
}
ArtistInfoWidget::~ArtistInfoWidget()
{
delete ui;
@ -125,7 +125,6 @@ ArtistInfoWidget::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestD
// qDebug() << "Info of wrong type or not with our identifier";
return;
}
qDebug() << Q_FUNC_INFO << requestData.caller << requestData.type << s_aiInfoIdentifier;
InfoSystem::InfoCriteriaHash trackInfo;
trackInfo = requestData.input.value< InfoSystem::InfoCriteriaHash >();
@ -207,7 +206,6 @@ void
ArtistInfoWidget::infoSystemFinished( QString target )
{
Q_UNUSED( target );
qDebug() << Q_FUNC_INFO;
}
@ -225,10 +223,3 @@ ArtistInfoWidget::changeEvent( QEvent* e )
break;
}
}
void
ArtistInfoWidget::removeHeaders()
{
for ( int i = 1; i < ui->relatedArtists->header()->count(); i++ )
ui->relatedArtists->header()->hideSection( ui->relatedArtists->header()->logicalIndex( i ) );
}

View File

@ -90,7 +90,6 @@ private slots:
void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
void infoSystemFinished( QString target );
void removeHeaders();
private:
Ui::ArtistInfoWidget *ui;
@ -106,4 +105,4 @@ private:
QPixmap m_pixmap;
};
#endif // SOURCEINFOWIDGET_H
#endif // ARTISTINFOWIDGET_H

View File

@ -51,7 +51,7 @@
<item>
<widget class="HeaderLabel" name="label">
<property name="text">
<string>Latest Additions to their Collection</string>
<string>Latest Additions</string>
</property>
</widget>
</item>
@ -65,7 +65,7 @@
<item>
<widget class="HeaderLabel" name="label_3">
<property name="text">
<string>Recently played Tracks</string>
<string>Recently Played Tracks</string>
</property>
</widget>
</item>

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>985</width>
<width>729</width>
<height>460</height>
</rect>
</property>
@ -16,11 +16,6 @@
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_2">
<property name="font">
<font>
<pointsize>13</pointsize>
</font>
</property>
<property name="text">
<string>Enter a title for the new playlist:</string>
</property>
@ -38,11 +33,6 @@
</item>
<item>
<widget class="QLabel" name="label">
<property name="font">
<font>
<pointsize>13</pointsize>
</font>
</property>
<property name="text">
<string>Tomahawk offers a variety of ways to help you create playlists and find music you enjoy!</string>
</property>
@ -53,14 +43,12 @@
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="font">
<font>
<pointsize>13</pointsize>
</font>
</property>
<property name="text">
<string>Just enter a genre or tag name and Tomahawk will suggest a few songs to get you started with your new playlist:</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>

View File

@ -24,6 +24,7 @@
#include "sourcelist.h"
#include "viewmanager.h"
#include "dynamic/widgets/LoadingSpinner.h"
#include "playlist/playlistmodel.h"
#include "widgets/overlaywidget.h"
@ -48,11 +49,13 @@ SearchWidget::SearchWidget( const QString& search, QWidget* parent )
ui->resultsView->setFrameShape( QFrame::NoFrame );
ui->resultsView->setAttribute( Qt::WA_MacShowFocusRect, 0 );
ui->resultsView->loadingSpinner()->fadeIn();
m_queries << Tomahawk::Query::get( search, uuid() );
foreach ( const Tomahawk::query_ptr& query, m_queries )
{
connect( query.data(), SIGNAL( resultsAdded( QList<Tomahawk::result_ptr> ) ), SLOT( onResultsFound( QList<Tomahawk::result_ptr> ) ) );
connect( query.data(), SIGNAL( resolvingFinished( bool ) ), SLOT( onQueryFinished() ) );
}
}
@ -91,9 +94,17 @@ SearchWidget::onResultsFound( const QList<Tomahawk::result_ptr>& results )
rl << result;
Tomahawk::query_ptr q = result->toQuery();
q->setResolveFinished( true );
q->addResults( rl );
qDebug() << result->toString();
m_resultsModel->append( q );
}
}
void
SearchWidget::onQueryFinished()
{
ui->resultsView->loadingSpinner()->fadeOut();
}

View File

@ -63,6 +63,7 @@ signals:
private slots:
void onResultsFound( const QList<Tomahawk::result_ptr>& results );
void onQueryFinished();
private:
Ui::SearchWidget *ui;

View File

@ -70,7 +70,13 @@ WelcomePlaylistModel::loadFromSettings()
m_recplaylists << pl;
if( !m_cached.contains( playlist_guids[i] ) )
{
if ( pl.dynamicCast< DynamicPlaylist >().isNull() )
connect( pl.data(), SIGNAL(revisionLoaded(Tomahawk::PlaylistRevision)), this, SLOT(playlistRevisionLoaded()) );
else
connect( pl.data(), SIGNAL(dynamicRevisionLoaded(Tomahawk::DynamicPlaylistRevision)), this, SLOT(playlistRevisionLoaded()) );
m_cached[playlist_guids[i]] = pl;
}
} else
m_waitingForSome = true;
}
@ -110,21 +116,78 @@ WelcomePlaylistModel::data( const QModelIndex& index, int role ) const
return m_artists[pl];
}
case PlaylistTypeRole:
{
if ( !pl.dynamicCast< Tomahawk::DynamicPlaylist >().isNull() )
{
dynplaylist_ptr dynp = pl.dynamicCast< Tomahawk::DynamicPlaylist >();
if ( dynp->mode() == Static )
return AutoPlaylist;
else if ( dynp->mode() == OnDemand )
return Station;
} else
{
return StaticPlaylist;
}
}
case DynamicPlaylistRole:
{
dynplaylist_ptr dynp = pl.dynamicCast< Tomahawk::DynamicPlaylist >();
return QVariant::fromValue< Tomahawk::dynplaylist_ptr >( dynp );
}
case TrackCountRole:
return pl->entries().count();
{
if ( !pl.dynamicCast< Tomahawk::DynamicPlaylist >().isNull() && pl.dynamicCast< Tomahawk::DynamicPlaylist >()->mode() == OnDemand )
return QString( QChar( 0x221E ) );
else
return pl->entries().count();
}
default:
return QVariant();
}
}
void
WelcomePlaylistModel::playlistRevisionLoaded()
{
Playlist* p = qobject_cast< Playlist* >( sender() );
Q_ASSERT( p );
for ( int i = 0; i < m_recplaylists.size(); i++ )
{
if ( m_recplaylists[ i ]->guid() == p->guid() )
{
QModelIndex idx = index( i, 0, QModelIndex() );
emit dataChanged( idx, idx );
}
}
}
void
WelcomePlaylistModel::onSourceAdded( const Tomahawk::source_ptr& source )
{
connect( source.data(), SIGNAL( online() ), this, SLOT( sourceOnline() ) );
connect( source->collection().data(), SIGNAL( playlistsAdded( QList<Tomahawk::playlist_ptr> ) ), SLOT( loadFromSettings() ) );
connect( source->collection().data(), SIGNAL( playlistsDeleted( QList<Tomahawk::playlist_ptr> ) ), SLOT( onPlaylistsRemoved( QList<Tomahawk::playlist_ptr> ) ) );
}
void
WelcomePlaylistModel::sourceOnline()
{
Source* s = qobject_cast< Source* >( sender() );
Q_ASSERT( s );
for ( int i = 0; i < m_recplaylists.size(); i++ )
{
if ( m_recplaylists[ i ]->author().data() == s )
{
QModelIndex idx = index( i, 0, QModelIndex() );
emit dataChanged( idx, idx );
}
}
}
void
WelcomePlaylistModel::onPlaylistsRemoved( QList< playlist_ptr > playlists )

View File

@ -30,7 +30,9 @@ class WelcomePlaylistModel : public QAbstractListModel
Q_OBJECT
public:
enum ItemRoles
{ ArtistRole = Qt::UserRole, TrackCountRole, PlaylistRole };
{ ArtistRole = Qt::UserRole, TrackCountRole, PlaylistRole, PlaylistTypeRole, DynamicPlaylistRole };
enum PlaylistTypes
{ StaticPlaylist, AutoPlaylist, Station };
explicit WelcomePlaylistModel( QObject* parent = 0 );
@ -49,6 +51,7 @@ private slots:
void loadFromSettings();
void plAdded( const Tomahawk::playlist_ptr& );
void playlistRevisionLoaded();
private:
QList< Tomahawk::playlist_ptr > m_recplaylists;
@ -57,6 +60,8 @@ private:
unsigned int m_maxPlaylists;
bool m_waitingForSome;
public slots:
void sourceOnline();
};
#endif // WELCOMEPLAYLISTMODEL_H

View File

@ -32,9 +32,10 @@
#include "widgets/overlaywidget.h"
#include "utils/tomahawkutils.h"
#include "utils/logger.h"
#include <dynamic/GeneratorInterface.h>
#define HISTORY_TRACK_ITEMS 25
#define HISTORY_PLAYLIST_ITEMS 5
#define HISTORY_PLAYLIST_ITEMS 10
#define HISTORY_RESOLVING_TIMEOUT 2500
using namespace Tomahawk;
@ -70,13 +71,18 @@ WelcomeWidget::WelcomeWidget( QWidget* parent )
ui->playlistWidget->setItemDelegate( new PlaylistDelegate() );
ui->playlistWidget->setModel( model );
ui->playlistWidget->overlay()->resize( 380, 86 );
#ifdef Q_OS_MAC
ui->playlistWidget->setVerticalScrollMode( QAbstractItemView::ScrollPerPixel );
#endif
connect( model, SIGNAL( emptinessChanged( bool) ), this, SLOT( updatePlaylists() ) );
m_tracksModel = new PlaylistModel( ui->tracksView );
m_tracksModel->setStyle( TrackModel::Short );
m_tracksModel->setStyle( TrackModel::ShortWithAvatars );
ui->tracksView->overlay()->setEnabled( false );
ui->tracksView->setPlaylistModel( m_tracksModel );
ui->tracksView->setHeaderHidden( true );
ui->tracksView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
m_recentAlbumsModel = new AlbumModel( ui->additionsView );
ui->additionsView->setAlbumModel( m_recentAlbumsModel );
@ -189,6 +195,7 @@ WelcomeWidget::changeEvent( QEvent* e )
}
}
QSize
PlaylistDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
@ -217,23 +224,82 @@ PlaylistDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
QTextOption to;
to.setAlignment( Qt::AlignCenter );
QFont font = opt.font;
QFont boldFont = opt.font;
#ifdef Q_OS_MAC
font.setPointSize( font.pointSize() - 2 );
#endif
QFont boldFont = font;
boldFont.setBold( true );
QFont italicFont = opt.font;
italicFont.setItalic( true );
painter->drawPixmap( option.rect.adjusted( 10, 13, -option.rect.width() + 48, -13 ), m_playlistIcon );
QPixmap icon;
WelcomePlaylistModel::PlaylistTypes type = (WelcomePlaylistModel::PlaylistTypes)index.data( WelcomePlaylistModel::PlaylistTypeRole ).toInt();
if( type == WelcomePlaylistModel::StaticPlaylist )
icon = m_playlistIcon;
else if( type == WelcomePlaylistModel::AutoPlaylist )
icon = m_autoIcon;
else if( type == WelcomePlaylistModel::Station )
icon = m_stationIcon;
painter->drawText( option.rect.adjusted( 56, 26, -100, -8 ), index.data( WelcomePlaylistModel::ArtistRole ).toString() );
QRect pixmapRect = option.rect.adjusted( 10, 13, -option.rect.width() + 48, -13 );
icon = icon.scaled( pixmapRect.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation );
QString trackCount = tr( "%1 tracks" ).arg( index.data( WelcomePlaylistModel::TrackCountRole ).toString() );
painter->drawText( option.rect.adjusted( option.rect.width() - 96, 12, 0, -2 - opt.rect.height() / 2 ), trackCount, to );
painter->drawPixmap( pixmapRect, icon );
QString author = index.data( WelcomePlaylistModel::PlaylistRole ).value< Tomahawk::playlist_ptr >()->author()->friendlyName();
QRect r = option.rect.adjusted( option.rect.width() - 96, 2 + opt.rect.height() / 2, 0, -12);
painter->setFont( italicFont );
author = painter->fontMetrics().elidedText( author, Qt::ElideRight, r.width() );
painter->drawText( r, author, to );
QString descText;
if ( type == WelcomePlaylistModel::Station )
{
descText = index.data( WelcomePlaylistModel::DynamicPlaylistRole ).value< Tomahawk::dynplaylist_ptr >()->generator()->sentenceSummary();
} else
{
descText = index.data( WelcomePlaylistModel::ArtistRole ).toString();
}
QColor c = painter->pen().color();
painter->setPen( QColor( Qt::gray ).darker() );
QFont font2 = font;
#ifdef Q_OS_MAC
font2.setPointSize( font2.pointSize() - 1 );
#endif
painter->setFont( font2 );
QRect rectText = option.rect.adjusted( 66, 20, -100, -8 );
#ifdef Q_OS_MAC
rectText.adjust( 0, 1, 0, 0 );
#elif Q_OS_WIN
rectText.adjust( 0, 2, 0, 0 );
#endif
painter->drawText( rectText, descText );
painter->setPen( c );
painter->setFont( font );
if ( type != WelcomePlaylistModel::Station )
{
painter->save();
QString tracks = index.data( WelcomePlaylistModel::TrackCountRole ).toString();
int width = painter->fontMetrics().width( tracks );
// int bottomEdge = pixmapRect
// right edge 10px past right edge of pixmapRect
// bottom edge flush with bottom of pixmap
QRect rect( pixmapRect.right() - width , 0, width - 8, 0 );
rect.adjust( -1, 0, 0, 0 );
rect.setTop( pixmapRect.bottom() - painter->fontMetrics().height() - 1 );
rect.setBottom( pixmapRect.bottom() + 1 );
QColor figColor( 153, 153, 153 );
painter->setPen( figColor );
painter->setBrush( figColor );
painter->setFont( boldFont );
TomahawkUtils::drawBackgroundAndNumbers( painter, tracks, rect );
painter->restore();
}
QPixmap avatar = index.data( WelcomePlaylistModel::PlaylistRole ).value< Tomahawk::playlist_ptr >()->author()->avatar( Source::FancyStyle );
if ( avatar.isNull() )
avatar = m_defaultAvatar;
QRect r( option.rect.width() - avatar.width() - 10, option.rect.top() + option.rect.height()/2 - avatar.height()/2, avatar.width(), avatar.height() );
painter->drawPixmap( r, avatar );
painter->setFont( boldFont );
painter->drawText( option.rect.adjusted( 56, 6, -100, -option.rect.height() + 20 ), index.data().toString() );

View File

@ -50,6 +50,9 @@ public:
PlaylistDelegate()
{
m_playlistIcon = QPixmap( RESPATH "images/playlist-icon.png" );
m_autoIcon = QPixmap( RESPATH "images/automatic-playlist.png" );
m_stationIcon = QPixmap( RESPATH "images/station.png" );
m_defaultAvatar = TomahawkUtils::createAvatarFrame( QPixmap( RESPATH "images/user-avatar.png" ) );
}
protected:
@ -57,7 +60,7 @@ protected:
QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const;
private:
QPixmap m_playlistIcon;
QPixmap m_playlistIcon, m_autoIcon, m_stationIcon, m_defaultAvatar;
};
class DLLEXPORT PlaylistWidget : public QListView

View File

@ -325,6 +325,12 @@ JabberPlugin::onDisconnect( Jreen::Client::DisconnectReason reason )
}
}
void
JabberPlugin::onError( const Jreen::Connection::SocketError& e )
{
tLog() << "JABBER error:" << e;
}
QString
JabberPlugin::errorMessage( Jreen::Client::DisconnectReason reason )
{

View File

@ -111,10 +111,7 @@ private slots:
void onSubscriptionRequestConfirmed( int result );
void onNewMessage( const Jreen::Message& message );
void onError( const Jreen::Connection::SocketError& e )
{
qDebug() << e;
}
void onError( const Jreen::Connection::SocketError& e );
void onNewIq( const Jreen::IQ &iq );
void onNewAvatar( const QString &jid );
void onCheckJidExists( QString jid );

View File

@ -1,4 +1,6 @@
/*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
*
* This program 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 2 of the License, or
@ -56,7 +58,7 @@ CollectionItem::CollectionItem( SourcesModel* mdl, SourceTreeItem* parent, cons
connect( ViewManager::instance(), SIGNAL( tempPageActivated( Tomahawk::ViewPage*) ), this, SLOT( tempPageActivated( Tomahawk::ViewPage* ) ) );
// add misc children of root node
GenericPageItem* recent = new GenericPageItem( model(), this, tr( "Recently Played" ), QIcon( RESPATH "images/recently-played.png" ),
GenericPageItem* recent = new GenericPageItem( model(), this, tr( "Dashboard" ), QIcon( RESPATH "images/dashboard.png" ),
boost::bind( &ViewManager::showWelcomePage, ViewManager::instance() ),
boost::bind( &ViewManager::welcomeWidget, ViewManager::instance() )
);
@ -69,6 +71,7 @@ CollectionItem::CollectionItem( SourcesModel* mdl, SourceTreeItem* parent, cons
// );
// m_coolPlaylistsItem->setSortValue( 200 );
m_superCol = TomahawkUtils::createAvatarFrame( QPixmap( RESPATH "images/supercollection.png" ) );
return;
}
@ -99,6 +102,8 @@ CollectionItem::CollectionItem( SourcesModel* mdl, SourceTreeItem* parent, cons
if( ViewManager::instance()->pageForCollection( source->collection() ) )
model()->linkSourceItemToPage( this, ViewManager::instance()->pageForCollection( source->collection() ) );
m_defaultAvatar = TomahawkUtils::createAvatarFrame( QPixmap( RESPATH "images/user-avatar.png" ) );
// load auto playlists and stations!
connect( source.data(), SIGNAL( stats( QVariantMap ) ), this, SIGNAL( updated() ) );
@ -114,6 +119,9 @@ CollectionItem::CollectionItem( SourcesModel* mdl, SourceTreeItem* parent, cons
SLOT( onAutoPlaylistsAdded( QList<Tomahawk::dynplaylist_ptr> ) ), Qt::QueuedConnection );
connect( source->collection().data(), SIGNAL( stationsAdded( QList<Tomahawk::dynplaylist_ptr> ) ),
SLOT( onStationsAdded( QList<Tomahawk::dynplaylist_ptr> ) ), Qt::QueuedConnection );
if ( m_source->isLocal() )
QTimer::singleShot(0, this, SLOT(requestExpanding()));
}
@ -160,13 +168,13 @@ QIcon
CollectionItem::icon() const
{
if( m_source.isNull() )
return QIcon( RESPATH "images/supercollection.png" );
return m_superCol;
else
{
if( m_source->avatar().isNull() )
return QIcon( RESPATH "images/user-avatar.png" );
return m_defaultAvatar;
else
return QIcon( m_source->avatar() );
return m_source->avatar( Source::FancyStyle );
}
}
@ -341,6 +349,13 @@ CollectionItem::onStationDeleted( const dynplaylist_ptr& station )
}
void
CollectionItem::requestExpanding()
{
emit expandRequest(this);
}
void
CollectionItem::tempPageActivated( Tomahawk::ViewPage* v )
{

View File

@ -1,4 +1,6 @@
/*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
*
* This program 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 2 of the License, or
@ -51,6 +53,8 @@ private slots:
void onStationsAdded( const QList<Tomahawk::dynplaylist_ptr>& stations );
void onStationDeleted( const Tomahawk::dynplaylist_ptr& stations );
void requestExpanding();
void tempPageActivated( Tomahawk::ViewPage* );
Tomahawk::ViewPage* tempItemClicked();
Tomahawk::ViewPage* getTempPage() const;
@ -70,6 +74,7 @@ private:
void playlistDeletedInternal( SourceTreeItem* parent, const T& playlists );
Tomahawk::source_ptr m_source;
QPixmap m_superCol, m_defaultAvatar;
CategoryItem* m_playlists;
CategoryItem* m_stations;

View File

@ -1,4 +1,6 @@
/*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
*
* This program 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 2 of the License, or

View File

@ -1,4 +1,6 @@
/*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
*
* This program 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 2 of the License, or

View File

@ -1,4 +1,7 @@
/*
*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
*
* This program 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 2 of the License, or

View File

@ -1,4 +1,6 @@
/*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
*
* This program 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 2 of the License, or

View File

@ -1,4 +1,6 @@
/*
Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
This program 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 2 of the License, or
@ -33,6 +35,7 @@ SourceTreeItem::SourceTreeItem( SourcesModel* model, SourceTreeItem* parent, Sou
connect( this, SIGNAL( childRowsRemoved() ), m_model, SLOT( onItemRowsRemovedDone() ) );
connect( this, SIGNAL( updated() ), m_model, SLOT( itemUpdated() ) );
connect( this, SIGNAL( selectRequest( SourceTreeItem* ) ), m_model, SLOT( itemSelectRequest( SourceTreeItem* ) ) );
connect( this, SIGNAL( expandRequest( SourceTreeItem* ) ), m_model, SLOT( itemExpandRequest( SourceTreeItem* ) ) );
if( !m_parent )
return;

View File

@ -1,4 +1,6 @@
/*
Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
This program 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 2 of the License, or
@ -63,6 +65,7 @@ public:
signals:
void updated();
void selectRequest( SourceTreeItem* );
void expandRequest( SourceTreeItem* );
void beginChildRowsAdded( int fromRow, int toRow );
void childRowsAdded();

View File

@ -493,3 +493,10 @@ SourcesModel::itemSelectRequest( SourceTreeItem* item )
{
emit selectRequest( indexFromItem( item ) );
}
void
SourcesModel::itemExpandRequest( SourceTreeItem *item )
{
qDebug() << "expanding source" << indexFromItem( item ) << item;
emit expandRequest( indexFromItem( item ) );
}

View File

@ -102,8 +102,11 @@ public slots:
void viewPageActivated( Tomahawk::ViewPage* );
void itemSelectRequest( SourceTreeItem* item );
void itemExpandRequest( SourceTreeItem* item );
signals:
void selectRequest( const QModelIndex& idx );
void expandRequest( const QModelIndex& idx );
private slots:
void onSourcesAdded( const QList<Tomahawk::source_ptr>& sources );

View File

@ -1,6 +1,6 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -37,8 +37,8 @@ SourcesProxyModel::SourcesProxyModel( SourcesModel* model, QObject* parent )
setSourceModel( model );
if ( model && model->metaObject()->indexOfSignal( "trackCountChanged(QModelIndex)" ) > -1 )
connect( model, SIGNAL( askForExpand( QModelIndex ) ), this, SLOT( askedToExpand( QModelIndex ) ) );
if ( model && model->metaObject()->indexOfSignal( "expandRequest(QModelIndex)" ) > -1 )
connect( model, SIGNAL( expandRequest( QModelIndex ) ), this, SLOT( expandRequested( QModelIndex ) ) );
if ( model && model->metaObject()->indexOfSignal( "selectRequest(QModelIndex)" ) > -1 )
connect( model, SIGNAL( selectRequest( QModelIndex ) ), this, SLOT( selectRequested( QModelIndex ) ) );
}
@ -73,6 +73,14 @@ SourcesProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourcePar
void
SourcesProxyModel::selectRequested( const QModelIndex& idx )
{
qDebug() << "selectRequested for idx" << idx << idx.data(Qt::DisplayRole).toString() << mapFromSource( idx );
emit selectRequest( mapFromSource( idx ) );
}
void
SourcesProxyModel::expandRequested( const QModelIndex& idx )
{
qDebug() << "emitting expand for idx" << idx << idx.data(Qt::DisplayRole).toString() << mapFromSource( idx );
emit expandRequest( mapFromSource( idx ) );
}

View File

@ -1,6 +1,6 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -34,9 +34,11 @@ public slots:
void showOfflineSources( bool offlineSourcesShown );
void selectRequested( const QModelIndex& );
void expandRequested( const QModelIndex& );
signals:
void selectRequest( const QModelIndex& idx );
void expandRequest( const QModelIndex& idx );
protected:
bool filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const;

View File

@ -108,6 +108,7 @@ SourceTreeView::SourceTreeView( QWidget* parent )
m_model = new SourcesModel( this );
m_proxyModel = new SourcesProxyModel( m_model, this );
connect( m_proxyModel, SIGNAL( selectRequest( QModelIndex ) ), this, SLOT( selectRequest( QModelIndex ) ), Qt::QueuedConnection );
connect( m_proxyModel, SIGNAL( expandRequest( QModelIndex ) ), this, SLOT( expandRequest( QModelIndex ) ), Qt::QueuedConnection );
setModel( m_proxyModel );
@ -246,6 +247,13 @@ SourceTreeView::selectRequest( const QModelIndex& idx )
}
}
void
SourceTreeView::expandRequest( const QModelIndex &idx )
{
qDebug() << "Expanding idx" << idx;
expand( idx );
}
void
SourceTreeView::loadPlaylist()
@ -665,34 +673,19 @@ SourceDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, co
{
painter->setRenderHint( QPainter::Antialiasing );
QRect figRect = o.rect.adjusted( o.rect.width() - figWidth - 18, 0, -10, -o.rect.height() + 16 );
QRect figRect = o.rect.adjusted( o.rect.width() - figWidth - 8, 0, -13, -o.rect.height() + 16 );
int hd = ( option.rect.height() - figRect.height() ) / 2;
figRect.adjust( 0, hd, 0, hd );
#ifdef Q_OS_WIN
figRect.adjust( -3, 0, 3, 0 );
#endif
painter->setFont( bold );
QColor figColor( 167, 183, 211 );
painter->setPen( figColor );
painter->setBrush( figColor );
QPen origpen = painter->pen();
QPen pen = origpen;
pen.setWidth( 1.0 );
painter->setPen( pen );
painter->drawRect( figRect );
QPainterPath ppath;
ppath.moveTo( QPoint( figRect.x(), figRect.y() ) );
ppath.quadTo( QPoint( figRect.x() - 8, figRect.y() + figRect.height() / 2 ), QPoint( figRect.x(), figRect.y() + figRect.height() ) );
painter->drawPath( ppath );
ppath.moveTo( QPoint( figRect.x() + figRect.width(), figRect.y() ) );
ppath.quadTo( QPoint( figRect.x() + figRect.width() + 8, figRect.y() + figRect.height() / 2 ), QPoint( figRect.x() + figRect.width(), figRect.y() + figRect.height() ) );
painter->drawPath( ppath );
painter->setPen( origpen );
QTextOption to( Qt::AlignCenter );
painter->setFont( bold );
painter->setPen( Qt::white );
painter->drawText( figRect, tracks, to );
TomahawkUtils::drawBackgroundAndNumbers( painter, tracks, figRect );
}
painter->restore();

View File

@ -49,6 +49,7 @@ private slots:
void onItemExpanded( const QModelIndex& idx );
void onItemActivated( const QModelIndex& index );
void selectRequest( const QModelIndex& idx );
void expandRequest( const QModelIndex& idx );
void loadPlaylist();
void deletePlaylist( const QModelIndex& = QModelIndex() );

View File

@ -124,6 +124,12 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] )
void
TomahawkApp::init()
{
if ( arguments().contains( "--help" ) || arguments().contains( "-h" ) )
{
printHelp();
::exit(0);
}
Logger::setupLogfile();
qsrand( QTime( 0, 0, 0 ).secsTo( QTime::currentTime() ) );
@ -241,6 +247,11 @@ TomahawkApp::init()
tDebug() << "Init Scrobbler.";
m_scrobbler = new Scrobbler( this );
#endif
if ( arguments().contains( "--filescan" ) )
{
m_scanManager.data()->runScan( true );
}
}
@ -292,6 +303,20 @@ TomahawkApp::instance()
return (TomahawkApp*)TOMAHAWK_APPLICATION::instance();
}
void
TomahawkApp::printHelp()
{
std::cout << QString( "usage: " + arguments().at( 0 ) + " [options] [url]\n" ).toAscii().data();
std::cout << QString( "options are:\n" ).toAscii().data();
std::cout << QString( " --help Show this help\n" ).toAscii().data();
std::cout << QString( " --http Initialize HTTP server\n" ).toAscii().data();
std::cout << QString( " --filescan Scan for files on startup\n" ).toAscii().data();
std::cout << QString( " --testdb Use a test database instead of real collection\n" ).toAscii().data();
std::cout << QString( " --noupnp Disable UPNP\n" ).toAscii().data();
std::cout << QString( " --nosip Disable SIP\n" ).toAscii().data();
std::cout << QString( "\nurl is a tomahawk:// command or alternatively a url that Tomahawk can recognize.\n" ).toAscii().data();
std::cout << QString( "For more documentation, see http://wiki.tomahawk-player.org/mediawiki/index.php/Tomahawk://_Links\n" ).toAscii().data();
}
#ifndef TOMAHAWK_HEADLESS
AudioControls*
@ -520,6 +545,8 @@ TomahawkApp::loadUrl( const QString& url )
return GlobalActionManager::instance()->parseTomahawkLink( url );
else if ( url.contains( "open.spotify.com" ) || url.contains( "spotify:track" ) )
return GlobalActionManager::instance()->openSpotifyLink( url );
else if ( url.contains( "www.rdio.com" ) )
return GlobalActionManager::instance()->openRdioLink( url );
else
{
QFile f( url );

View File

@ -108,6 +108,8 @@ private slots:
private:
void registerMetaTypes();
void printHelp();
// Start-up order: database, collection, pipeline, servent, http
void initDatabase();
void initLocalCollection();

View File

@ -93,6 +93,7 @@ TomahawkWindow::TomahawkWindow( QWidget* parent )
ui->centralWidget->setContentsMargins( 0, 0, 0, 0 );
ui->centralWidget->layout()->setContentsMargins( 0, 0, 0, 0 );
ui->centralWidget->layout()->setMargin( 0 );
ui->centralWidget->layout()->setSpacing( 0 );
setupSideBar();
setupToolBar();
@ -174,6 +175,16 @@ TomahawkWindow::applyPlatformTweaks()
#ifdef Q_WS_MAC
setUnifiedTitleAndToolBarOnMac( true );
#endif
#ifdef Q_OS_MAC
ui->hline1->setMaximumHeight( 0 );
ui->hline2->setMaximumHeight( 0 );
ui->hline1->hide();
ui->hline2->hide();
#else
ui->hline1->setStyleSheet( "border: 1px solid gray;" );
ui->hline2->setStyleSheet( "border: 1px solid gray;" );
#endif
}

View File

@ -15,6 +15,22 @@
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QFrame" name="hline1">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>1</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
@ -27,6 +43,22 @@
<widget class="QWidget" name="playlistWidget" native="true"/>
</widget>
</item>
<item>
<widget class="QFrame" name="hline2">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>1</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
@ -35,7 +67,7 @@
<x>0</x>
<y>0</y>
<width>1000</width>
<height>22</height>
<height>20</height>
</rect>
</property>
<widget class="QMenu" name="menuSettings">

View File

@ -47,6 +47,7 @@ TransferView::TransferView( AnimatedSplitter* parent )
headers << tr( "Peer" ) << tr( "Rate" ) << tr( "Track" );
m_tree->setHeaderLabels( headers );
m_tree->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
m_tree->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Ignored );
m_tree->setColumnCount( 3 );
m_tree->setColumnWidth( 0, 80 );
@ -58,6 +59,17 @@ TransferView::TransferView( AnimatedSplitter* parent )
m_tree->setFrameShape( QFrame::NoFrame );
m_tree->setAttribute( Qt::WA_MacShowFocusRect, 0 );
#ifndef Q_WS_WIN
QFont f = font();
f.setPointSize( f.pointSize() - 1 );
setFont( f );
#endif
#ifdef Q_WS_MAC
f.setPointSize( f.pointSize() - 2 );
setFont( f );
#endif
}