2018-08-09 18:10:03 +02:00
/*
* Strawberry Music Player
* This code was part of Clementine ( GlobalSearch )
* Copyright 2012 , David Sansome < me @ davidsansome . com >
* Copyright 2018 , Jonas Kvinge < jonas @ jkvinge . net >
*
* Strawberry is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* Strawberry is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with Strawberry . If not , see < http : //www.gnu.org/licenses/>.
*
*/
# include "config.h"
# include <QtGlobal>
# include <QWidget>
# include <QTimer>
# include <QList>
# include <QString>
# include <QPixmap>
# include <QPalette>
# include <QColor>
# include <QFont>
# include <QStandardItem>
2019-05-27 21:10:37 +02:00
# include <QMenu>
2018-08-09 18:10:03 +02:00
# include <QAction>
2019-05-27 21:10:37 +02:00
# include <QSettings>
2018-08-09 18:10:03 +02:00
# include <QtEvents>
# include "core/application.h"
# include "core/mimedata.h"
# include "core/iconloader.h"
# include "internet/internetsongmimedata.h"
# include "collection/collectionfilterwidget.h"
# include "collection/collectionmodel.h"
# include "collection/groupbydialog.h"
2018-10-17 21:18:39 +02:00
# include "internetsearch.h"
# include "internetsearchitemdelegate.h"
# include "internetsearchmodel.h"
# include "internetsearchsortmodel.h"
# include "internetsearchview.h"
# include "ui_internetsearchview.h"
2018-08-09 18:10:03 +02:00
using std : : placeholders : : _1 ;
using std : : placeholders : : _2 ;
using std : : swap ;
2018-10-17 21:18:39 +02:00
const int InternetSearchView : : kSwapModelsTimeoutMsec = 250 ;
2018-08-09 18:10:03 +02:00
2019-05-27 21:10:37 +02:00
InternetSearchView : : InternetSearchView ( QWidget * parent )
2018-08-09 18:10:03 +02:00
: QWidget ( parent ) ,
2019-05-27 21:10:37 +02:00
app_ ( nullptr ) ,
engine_ ( nullptr ) ,
2018-10-17 21:18:39 +02:00
ui_ ( new Ui_InternetSearchView ) ,
2018-08-09 18:10:03 +02:00
context_menu_ ( nullptr ) ,
last_search_id_ ( 0 ) ,
2019-05-27 21:10:37 +02:00
front_model_ ( nullptr ) ,
back_model_ ( nullptr ) ,
current_model_ ( nullptr ) ,
2018-10-17 21:18:39 +02:00
front_proxy_ ( new InternetSearchSortModel ( this ) ) ,
back_proxy_ ( new InternetSearchSortModel ( this ) ) ,
2018-08-09 18:10:03 +02:00
current_proxy_ ( front_proxy_ ) ,
swap_models_timer_ ( new QTimer ( this ) ) ,
2018-10-17 21:18:39 +02:00
error_ ( false )
{
2018-08-09 18:10:03 +02:00
ui_ - > setupUi ( this ) ;
2019-05-27 21:10:37 +02:00
2018-09-06 17:39:26 +02:00
ui_ - > progressbar - > hide ( ) ;
ui_ - > progressbar - > reset ( ) ;
2018-08-09 18:10:03 +02:00
ui_ - > search - > installEventFilter ( this ) ;
ui_ - > results_stack - > installEventFilter ( this ) ;
ui_ - > settings - > setIcon ( IconLoader : : Load ( " configure " ) ) ;
// Set the appearance of the results list
2018-10-17 21:18:39 +02:00
ui_ - > results - > setItemDelegate ( new InternetSearchItemDelegate ( this ) ) ;
2018-08-09 18:10:03 +02:00
ui_ - > results - > setAttribute ( Qt : : WA_MacShowFocusRect , false ) ;
ui_ - > results - > setStyleSheet ( " QTreeView::item{padding-top:1px;} " ) ;
// Show the help page initially
ui_ - > results_stack - > setCurrentWidget ( ui_ - > help_page ) ;
ui_ - > help_frame - > setBackgroundRole ( QPalette : : Base ) ;
// Set the colour of the help text to the disabled window text colour
QPalette help_palette = ui_ - > label_helptext - > palette ( ) ;
const QColor help_color = help_palette . color ( QPalette : : Disabled , QPalette : : WindowText ) ;
help_palette . setColor ( QPalette : : Normal , QPalette : : WindowText , help_color ) ;
help_palette . setColor ( QPalette : : Inactive , QPalette : : WindowText , help_color ) ;
ui_ - > label_helptext - > setPalette ( help_palette ) ;
// Make it bold
QFont help_font = ui_ - > label_helptext - > font ( ) ;
help_font . setBold ( true ) ;
ui_ - > label_helptext - > setFont ( help_font ) ;
2019-05-27 21:10:37 +02:00
}
InternetSearchView : : ~ InternetSearchView ( ) { delete ui_ ; }
2019-06-20 16:33:28 +02:00
void InternetSearchView : : Init ( Application * app , InternetSearch * engine , const QString & settings_group , const SettingsDialog : : Page settings_page , const bool artists , const bool albums , const bool songs ) {
2019-05-27 21:10:37 +02:00
app_ = app ;
engine_ = engine ;
settings_group_ = settings_group ;
settings_page_ = settings_page ;
2019-06-07 20:23:05 +02:00
artists_ = artists ;
albums_ = albums ;
songs_ = songs ;
2019-05-27 21:10:37 +02:00
front_model_ = new InternetSearchModel ( engine_ , this ) ;
back_model_ = new InternetSearchModel ( engine_ , this ) ;
front_proxy_ = new InternetSearchSortModel ( this ) ;
back_proxy_ = new InternetSearchSortModel ( this ) ;
front_model_ - > set_proxy ( front_proxy_ ) ;
back_model_ - > set_proxy ( back_proxy_ ) ;
current_model_ = front_model_ ;
current_proxy_ = front_proxy_ ;
// Must be a queued connection to ensure the InternetSearch handles it first.
connect ( app_ , SIGNAL ( SettingsChanged ( ) ) , SLOT ( ReloadSettings ( ) ) , Qt : : QueuedConnection ) ;
2018-08-09 18:10:03 +02:00
// Set up the sorting proxy model
front_proxy_ - > setSourceModel ( front_model_ ) ;
front_proxy_ - > setDynamicSortFilter ( true ) ;
front_proxy_ - > sort ( 0 ) ;
back_proxy_ - > setSourceModel ( back_model_ ) ;
back_proxy_ - > setDynamicSortFilter ( true ) ;
back_proxy_ - > sort ( 0 ) ;
// Add actions to the settings menu
group_by_actions_ = CollectionFilterWidget : : CreateGroupByActions ( this ) ;
QMenu * settings_menu = new QMenu ( this ) ;
settings_menu - > addActions ( group_by_actions_ - > actions ( ) ) ;
settings_menu - > addSeparator ( ) ;
2019-02-22 20:24:38 +01:00
settings_menu - > addAction ( IconLoader : : Load ( " configure " ) , tr ( " Configure %1... " ) . arg ( Song : : TextForSource ( engine - > source ( ) ) ) , this , SLOT ( OpenSettingsDialog ( ) ) ) ;
2018-08-09 18:10:03 +02:00
ui_ - > settings - > setMenu ( settings_menu ) ;
2019-05-27 21:10:37 +02:00
swap_models_timer_ - > setSingleShot ( true ) ;
swap_models_timer_ - > setInterval ( kSwapModelsTimeoutMsec ) ;
connect ( swap_models_timer_ , SIGNAL ( timeout ( ) ) , SLOT ( SwapModels ( ) ) ) ;
2019-02-12 21:58:03 +01:00
connect ( ui_ - > radiobutton_search_artists , SIGNAL ( clicked ( bool ) ) , SLOT ( SearchArtistsClicked ( bool ) ) ) ;
connect ( ui_ - > radiobutton_search_albums , SIGNAL ( clicked ( bool ) ) , SLOT ( SearchAlbumsClicked ( bool ) ) ) ;
connect ( ui_ - > radiobutton_search_songs , SIGNAL ( clicked ( bool ) ) , SLOT ( SearchSongsClicked ( bool ) ) ) ;
2018-08-09 18:10:03 +02:00
connect ( group_by_actions_ , SIGNAL ( triggered ( QAction * ) ) , SLOT ( GroupByClicked ( QAction * ) ) ) ;
2019-05-27 21:10:37 +02:00
connect ( ui_ - > search , SIGNAL ( textChanged ( QString ) ) , SLOT ( TextEdited ( QString ) ) ) ;
connect ( ui_ - > results , SIGNAL ( AddToPlaylistSignal ( QMimeData * ) ) , SIGNAL ( AddToPlaylist ( QMimeData * ) ) ) ;
connect ( ui_ - > results , SIGNAL ( FocusOnFilterSignal ( QKeyEvent * ) ) , SLOT ( FocusOnFilter ( QKeyEvent * ) ) ) ;
2018-08-09 18:10:03 +02:00
// These have to be queued connections because they may get emitted before our call to Search() (or whatever) returns and we add the ID to the map.
2018-09-06 17:39:26 +02:00
2019-06-20 16:33:28 +02:00
connect ( engine_ , SIGNAL ( UpdateStatus ( const int , const QString & ) ) , SLOT ( UpdateStatus ( const int , const QString & ) ) ) ;
connect ( engine_ , SIGNAL ( ProgressSetMaximum ( const int , const int ) ) , SLOT ( ProgressSetMaximum ( const int , const int ) ) , Qt : : QueuedConnection ) ;
connect ( engine_ , SIGNAL ( UpdateProgress ( const int , const int ) ) , SLOT ( UpdateProgress ( const int , const int ) ) , Qt : : QueuedConnection ) ;
2018-09-06 17:39:26 +02:00
2019-06-20 16:33:28 +02:00
connect ( engine_ , SIGNAL ( AddResults ( const int , InternetSearch : : ResultList ) ) , SLOT ( AddResults ( const int , const InternetSearch : : ResultList ) ) , Qt : : QueuedConnection ) ;
connect ( engine_ , SIGNAL ( SearchError ( const int , const QString & ) ) , SLOT ( SearchError ( const int , const QString & ) ) , Qt : : QueuedConnection ) ;
2019-07-07 21:14:24 +02:00
connect ( engine_ , SIGNAL ( AlbumCoverLoaded ( const int , const QPixmap & ) ) , SLOT ( AlbumCoverLoaded ( const int , const QPixmap & ) ) , Qt : : QueuedConnection ) ;
2018-08-09 18:10:03 +02:00
ReloadSettings ( ) ;
}
2018-10-17 21:18:39 +02:00
void InternetSearchView : : ReloadSettings ( ) {
2018-08-09 18:10:03 +02:00
QSettings s ;
// Collection settings
2018-10-17 21:18:39 +02:00
s . beginGroup ( settings_group_ ) ;
2018-08-09 18:10:03 +02:00
const bool pretty = s . value ( " pretty_covers " , true ) . toBool ( ) ;
front_model_ - > set_use_pretty_covers ( pretty ) ;
back_model_ - > set_use_pretty_covers ( pretty ) ;
2018-10-17 21:18:39 +02:00
// Internet search settings
2018-08-09 18:10:03 +02:00
2019-02-12 21:58:03 +01:00
search_type_ = InternetSearch : : SearchType ( s . value ( " type " , int ( InternetSearch : : SearchType_Artists ) ) . toInt ( ) ) ;
switch ( search_type_ ) {
case InternetSearch : : SearchType_Artists :
ui_ - > radiobutton_search_artists - > setChecked ( true ) ;
2018-08-09 18:10:03 +02:00
break ;
2019-02-12 21:58:03 +01:00
case InternetSearch : : SearchType_Albums :
ui_ - > radiobutton_search_albums - > setChecked ( true ) ;
break ;
case InternetSearch : : SearchType_Songs :
ui_ - > radiobutton_search_songs - > setChecked ( true ) ;
2018-08-09 18:10:03 +02:00
break ;
}
SetGroupBy ( CollectionModel : : Grouping (
2019-06-08 00:15:54 +02:00
CollectionModel : : GroupBy ( s . value ( " search_group_by1 " , int ( CollectionModel : : GroupBy_AlbumArtist ) ) . toInt ( ) ) ,
CollectionModel : : GroupBy ( s . value ( " search_group_by2 " , int ( CollectionModel : : GroupBy_Album ) ) . toInt ( ) ) ,
CollectionModel : : GroupBy ( s . value ( " search_group_by3 " , int ( CollectionModel : : GroupBy_None ) ) . toInt ( ) ) ) ) ;
2018-08-09 18:10:03 +02:00
s . endGroup ( ) ;
}
2018-10-17 21:18:39 +02:00
void InternetSearchView : : StartSearch ( const QString & query ) {
2018-08-09 18:10:03 +02:00
ui_ - > search - > setText ( query ) ;
TextEdited ( query ) ;
// Swap models immediately
swap_models_timer_ - > stop ( ) ;
SwapModels ( ) ;
}
2018-10-17 21:18:39 +02:00
void InternetSearchView : : TextEdited ( const QString & text ) {
2018-08-09 18:10:03 +02:00
const QString trimmed ( text . trimmed ( ) ) ;
error_ = false ;
// Add results to the back model, switch models after some delay.
back_model_ - > Clear ( ) ;
current_model_ = back_model_ ;
current_proxy_ = back_proxy_ ;
swap_models_timer_ - > start ( ) ;
// Cancel the last search (if any) and start the new one.
engine_ - > CancelSearch ( last_search_id_ ) ;
// If text query is empty, don't start a new search
if ( trimmed . isEmpty ( ) ) {
last_search_id_ = - 1 ;
ui_ - > label_helptext - > setText ( " Enter search terms above to find music " ) ;
2018-09-06 17:39:26 +02:00
ui_ - > label_status - > clear ( ) ;
ui_ - > progressbar - > hide ( ) ;
ui_ - > progressbar - > reset ( ) ;
2018-08-09 18:10:03 +02:00
}
else {
2018-09-06 17:39:26 +02:00
ui_ - > progressbar - > reset ( ) ;
2019-02-12 21:58:03 +01:00
last_search_id_ = engine_ - > SearchAsync ( trimmed , search_type_ ) ;
2018-08-09 18:10:03 +02:00
}
}
2019-06-20 16:33:28 +02:00
void InternetSearchView : : AddResults ( const int id , const InternetSearch : : ResultList & results ) {
2019-05-27 21:10:37 +02:00
2018-08-09 18:10:03 +02:00
if ( id ! = last_search_id_ ) return ;
if ( results . isEmpty ( ) ) return ;
2018-09-06 17:39:26 +02:00
ui_ - > label_status - > clear ( ) ;
ui_ - > progressbar - > reset ( ) ;
ui_ - > progressbar - > hide ( ) ;
2018-08-09 18:10:03 +02:00
current_model_ - > AddResults ( results ) ;
2019-05-27 21:10:37 +02:00
2018-08-09 18:10:03 +02:00
}
2019-06-20 16:33:28 +02:00
void InternetSearchView : : SearchError ( const int id , const QString & error ) {
2019-05-27 21:10:37 +02:00
2019-06-20 16:33:28 +02:00
if ( id ! = last_search_id_ ) return ;
2018-08-09 18:10:03 +02:00
error_ = true ;
ui_ - > label_helptext - > setText ( error ) ;
2018-09-06 17:39:26 +02:00
ui_ - > label_status - > clear ( ) ;
ui_ - > progressbar - > reset ( ) ;
ui_ - > progressbar - > hide ( ) ;
2018-08-09 18:10:03 +02:00
ui_ - > results_stack - > setCurrentWidget ( ui_ - > help_page ) ;
2019-05-27 21:10:37 +02:00
2018-08-09 18:10:03 +02:00
}
2018-10-17 21:18:39 +02:00
void InternetSearchView : : SwapModels ( ) {
2018-08-09 18:10:03 +02:00
art_requests_ . clear ( ) ;
std : : swap ( front_model_ , back_model_ ) ;
std : : swap ( front_proxy_ , back_proxy_ ) ;
ui_ - > results - > setModel ( front_proxy_ ) ;
if ( ui_ - > search - > text ( ) . trimmed ( ) . isEmpty ( ) | | error_ ) {
ui_ - > results_stack - > setCurrentWidget ( ui_ - > help_page ) ;
}
else {
ui_ - > results_stack - > setCurrentWidget ( ui_ - > results_page ) ;
}
}
2019-07-07 21:14:24 +02:00
void InternetSearchView : : LazyLoadAlbumCover ( const QModelIndex & proxy_index ) {
2018-09-10 21:58:57 +02:00
2018-08-09 18:10:03 +02:00
if ( ! proxy_index . isValid ( ) | | proxy_index . model ( ) ! = front_proxy_ ) {
return ;
}
// Already loading art for this item?
2018-10-17 21:18:39 +02:00
if ( proxy_index . data ( InternetSearchModel : : Role_LazyLoadingArt ) . isValid ( ) ) {
2018-08-09 18:10:03 +02:00
return ;
}
// Should we even load art at all?
if ( ! app_ - > collection_model ( ) - > use_pretty_covers ( ) ) {
return ;
}
// Is this an album?
const CollectionModel : : GroupBy container_type = CollectionModel : : GroupBy ( proxy_index . data ( CollectionModel : : Role_ContainerType ) . toInt ( ) ) ;
if ( container_type ! = CollectionModel : : GroupBy_Album & &
container_type ! = CollectionModel : : GroupBy_YearAlbum & &
container_type ! = CollectionModel : : GroupBy_OriginalYearAlbum ) {
return ;
}
// Mark the item as loading art
const QModelIndex source_index = front_proxy_ - > mapToSource ( proxy_index ) ;
QStandardItem * item = front_model_ - > itemFromIndex ( source_index ) ;
2018-10-17 21:18:39 +02:00
item - > setData ( true , InternetSearchModel : : Role_LazyLoadingArt ) ;
2018-08-09 18:10:03 +02:00
// Walk down the item's children until we find a track
while ( item - > rowCount ( ) ) {
item = item - > child ( 0 ) ;
}
// Get the track's Result
2018-10-17 21:18:39 +02:00
const InternetSearch : : Result result = item - > data ( InternetSearchModel : : Role_Result ) . value < InternetSearch : : Result > ( ) ;
2018-08-09 18:10:03 +02:00
// Load the art.
2019-07-07 21:14:24 +02:00
int id = engine_ - > LoadAlbumCoverAsync ( result ) ;
2018-08-09 18:10:03 +02:00
art_requests_ [ id ] = source_index ;
}
2019-07-07 21:14:24 +02:00
void InternetSearchView : : AlbumCoverLoaded ( const int id , const QPixmap & pixmap ) {
2018-08-09 18:10:03 +02:00
if ( ! art_requests_ . contains ( id ) ) return ;
QModelIndex index = art_requests_ . take ( id ) ;
if ( ! pixmap . isNull ( ) ) {
front_model_ - > itemFromIndex ( index ) - > setData ( pixmap , Qt : : DecorationRole ) ;
}
}
2018-10-17 21:18:39 +02:00
MimeData * InternetSearchView : : SelectedMimeData ( ) {
2018-08-09 18:10:03 +02:00
if ( ! ui_ - > results - > selectionModel ( ) ) return nullptr ;
// Get all selected model indexes
QModelIndexList indexes = ui_ - > results - > selectionModel ( ) - > selectedRows ( ) ;
if ( indexes . isEmpty ( ) ) {
// There's nothing selected - take the first thing in the model that isn't a divider.
for ( int i = 0 ; i < front_proxy_ - > rowCount ( ) ; + + i ) {
QModelIndex index = front_proxy_ - > index ( i , 0 ) ;
if ( ! index . data ( CollectionModel : : Role_IsDivider ) . toBool ( ) ) {
indexes < < index ;
ui_ - > results - > setCurrentIndex ( index ) ;
break ;
}
}
}
// Still got nothing? Give up.
if ( indexes . isEmpty ( ) ) {
return nullptr ;
}
// Get items for these indexes
QList < QStandardItem * > items ;
for ( const QModelIndex & index : indexes ) {
items < < ( front_model_ - > itemFromIndex ( front_proxy_ - > mapToSource ( index ) ) ) ;
}
// Get a MimeData for these items
return engine_ - > LoadTracks ( front_model_ - > GetChildResults ( items ) ) ;
}
2018-10-17 21:18:39 +02:00
bool InternetSearchView : : eventFilter ( QObject * object , QEvent * event ) {
2018-08-09 18:10:03 +02:00
if ( object = = ui_ - > search & & event - > type ( ) = = QEvent : : KeyRelease ) {
if ( SearchKeyEvent ( static_cast < QKeyEvent * > ( event ) ) ) {
return true ;
}
}
else if ( object = = ui_ - > results_stack & & event - > type ( ) = = QEvent : : ContextMenu ) {
if ( ResultsContextMenuEvent ( static_cast < QContextMenuEvent * > ( event ) ) ) {
return true ;
}
}
return QWidget : : eventFilter ( object , event ) ;
}
2018-10-17 21:18:39 +02:00
bool InternetSearchView : : SearchKeyEvent ( QKeyEvent * event ) {
2018-08-09 18:10:03 +02:00
switch ( event - > key ( ) ) {
case Qt : : Key_Up :
ui_ - > results - > UpAndFocus ( ) ;
break ;
case Qt : : Key_Down :
ui_ - > results - > DownAndFocus ( ) ;
break ;
case Qt : : Key_Escape :
ui_ - > search - > clear ( ) ;
break ;
case Qt : : Key_Return :
2018-09-06 17:39:26 +02:00
TextEdited ( ui_ - > search - > text ( ) ) ;
2018-08-09 18:10:03 +02:00
break ;
default :
return false ;
}
event - > accept ( ) ;
return true ;
}
2018-10-17 21:18:39 +02:00
bool InternetSearchView : : ResultsContextMenuEvent ( QContextMenuEvent * event ) {
2018-08-09 18:10:03 +02:00
context_menu_ = new QMenu ( this ) ;
2019-10-20 00:17:28 +02:00
context_actions_ < < context_menu_ - > addAction ( IconLoader : : Load ( " media-playback-start " ) , tr ( " Append to current playlist " ) , this , SLOT ( AddSelectedToPlaylist ( ) ) ) ;
context_actions_ < < context_menu_ - > addAction ( IconLoader : : Load ( " media-playback-start " ) , tr ( " Replace current playlist " ) , this , SLOT ( LoadSelected ( ) ) ) ;
2018-08-09 18:10:03 +02:00
context_actions_ < < context_menu_ - > addAction ( IconLoader : : Load ( " document-new " ) , tr ( " Open in new playlist " ) , this , SLOT ( OpenSelectedInNewPlaylist ( ) ) ) ;
context_menu_ - > addSeparator ( ) ;
context_actions_ < < context_menu_ - > addAction ( IconLoader : : Load ( " go-next " ) , tr ( " Queue track " ) , this , SLOT ( AddSelectedToPlaylistEnqueue ( ) ) ) ;
context_menu_ - > addSeparator ( ) ;
2019-06-07 20:23:05 +02:00
if ( artists_ | | albums_ | | songs_ ) {
if ( artists_ )
2019-06-08 00:15:54 +02:00
context_actions_ < < context_menu_ - > addAction ( IconLoader : : Load ( " folder-new " ) , tr ( " Add to artists " ) , this , SLOT ( AddArtists ( ) ) ) ;
2019-06-07 20:23:05 +02:00
if ( albums_ )
2019-06-08 00:15:54 +02:00
context_actions_ < < context_menu_ - > addAction ( IconLoader : : Load ( " folder-new " ) , tr ( " Add to albums " ) , this , SLOT ( AddAlbums ( ) ) ) ;
2019-06-07 20:23:05 +02:00
if ( songs_ )
2019-06-08 00:15:54 +02:00
context_actions_ < < context_menu_ - > addAction ( IconLoader : : Load ( " folder-new " ) , tr ( " Add to songs " ) , this , SLOT ( AddSongs ( ) ) ) ;
2019-06-07 20:23:05 +02:00
context_menu_ - > addSeparator ( ) ;
}
2018-08-09 18:10:03 +02:00
if ( ui_ - > results - > selectionModel ( ) & & ui_ - > results - > selectionModel ( ) - > selectedRows ( ) . length ( ) = = 1 ) {
2018-08-09 21:04:30 +02:00
context_actions_ < < context_menu_ - > addAction ( IconLoader : : Load ( " search " ) , tr ( " Search for this " ) , this , SLOT ( SearchForThis ( ) ) ) ;
2018-08-09 18:10:03 +02:00
}
context_menu_ - > addSeparator ( ) ;
context_menu_ - > addMenu ( tr ( " Group by " ) ) - > addActions ( group_by_actions_ - > actions ( ) ) ;
2018-10-20 22:33:23 +02:00
2019-02-22 20:24:38 +01:00
context_menu_ - > addAction ( IconLoader : : Load ( " configure " ) , tr ( " Configure %1... " ) . arg ( Song : : TextForSource ( engine_ - > source ( ) ) ) , this , SLOT ( OpenSettingsDialog ( ) ) ) ;
2018-08-09 18:10:03 +02:00
const bool enable_context_actions = ui_ - > results - > selectionModel ( ) & & ui_ - > results - > selectionModel ( ) - > hasSelection ( ) ;
for ( QAction * action : context_actions_ ) {
action - > setEnabled ( enable_context_actions ) ;
}
context_menu_ - > popup ( event - > globalPos ( ) ) ;
return true ;
}
2018-10-17 21:18:39 +02:00
void InternetSearchView : : AddSelectedToPlaylist ( ) {
2018-08-09 18:10:03 +02:00
emit AddToPlaylist ( SelectedMimeData ( ) ) ;
}
2018-10-17 21:18:39 +02:00
void InternetSearchView : : LoadSelected ( ) {
2018-08-09 18:10:03 +02:00
MimeData * data = SelectedMimeData ( ) ;
if ( ! data ) return ;
data - > clear_first_ = true ;
emit AddToPlaylist ( data ) ;
}
2018-10-17 21:18:39 +02:00
void InternetSearchView : : AddSelectedToPlaylistEnqueue ( ) {
2018-08-09 18:10:03 +02:00
MimeData * data = SelectedMimeData ( ) ;
if ( ! data ) return ;
data - > enqueue_now_ = true ;
emit AddToPlaylist ( data ) ;
}
2018-10-17 21:18:39 +02:00
void InternetSearchView : : OpenSelectedInNewPlaylist ( ) {
2018-08-09 18:10:03 +02:00
MimeData * data = SelectedMimeData ( ) ;
if ( ! data ) return ;
data - > open_in_new_playlist_ = true ;
emit AddToPlaylist ( data ) ;
}
2018-10-17 21:18:39 +02:00
void InternetSearchView : : SearchForThis ( ) {
2018-08-09 18:10:03 +02:00
StartSearch ( ui_ - > results - > selectionModel ( ) - > selectedRows ( ) . first ( ) . data ( ) . toString ( ) ) ;
}
2018-10-17 21:18:39 +02:00
void InternetSearchView : : showEvent ( QShowEvent * e ) {
2018-08-09 18:10:03 +02:00
QWidget : : showEvent ( e ) ;
FocusSearchField ( ) ;
}
2018-10-17 21:18:39 +02:00
void InternetSearchView : : FocusSearchField ( ) {
2018-08-09 18:10:03 +02:00
ui_ - > search - > setFocus ( ) ;
ui_ - > search - > selectAll ( ) ;
}
2018-10-17 21:18:39 +02:00
void InternetSearchView : : hideEvent ( QHideEvent * e ) {
2018-08-09 18:10:03 +02:00
QWidget : : hideEvent ( e ) ;
}
2018-10-17 21:18:39 +02:00
void InternetSearchView : : FocusOnFilter ( QKeyEvent * event ) {
2018-08-09 18:10:03 +02:00
ui_ - > search - > setFocus ( ) ;
QApplication : : sendEvent ( ui_ - > search , event ) ;
}
2018-10-17 21:18:39 +02:00
void InternetSearchView : : OpenSettingsDialog ( ) {
app_ - > OpenSettingsDialogAtPage ( settings_page_ ) ;
2018-08-09 18:10:03 +02:00
}
2018-10-17 21:18:39 +02:00
void InternetSearchView : : GroupByClicked ( QAction * action ) {
2018-08-09 18:10:03 +02:00
if ( action - > property ( " group_by " ) . isNull ( ) ) {
if ( ! group_by_dialog_ ) {
group_by_dialog_ . reset ( new GroupByDialog ) ;
connect ( group_by_dialog_ . data ( ) , SIGNAL ( Accepted ( CollectionModel : : Grouping ) ) , SLOT ( SetGroupBy ( CollectionModel : : Grouping ) ) ) ;
}
group_by_dialog_ - > show ( ) ;
return ;
}
SetGroupBy ( action - > property ( " group_by " ) . value < CollectionModel : : Grouping > ( ) ) ;
}
2018-10-17 21:18:39 +02:00
void InternetSearchView : : SetGroupBy ( const CollectionModel : : Grouping & g ) {
2018-08-09 18:10:03 +02:00
// Clear requests: changing "group by" on the models will cause all the items to be removed/added again,
// so all the QModelIndex here will become invalid. New requests will be created for those
2019-07-07 21:14:24 +02:00
// songs when they will be displayed again anyway (when InternetSearchItemDelegate::paint will call LazyLoadAlbumCover)
2018-08-09 18:10:03 +02:00
art_requests_ . clear ( ) ;
// Update the models
front_model_ - > SetGroupBy ( g , true ) ;
back_model_ - > SetGroupBy ( g , false ) ;
// Save the setting
QSettings s ;
2018-10-17 21:18:39 +02:00
s . beginGroup ( settings_group_ ) ;
2019-06-08 00:15:54 +02:00
s . setValue ( " search_group_by1 " , int ( g . first ) ) ;
s . setValue ( " search_group_by2 " , int ( g . second ) ) ;
s . setValue ( " search_group_by3 " , int ( g . third ) ) ;
2018-08-09 18:10:03 +02:00
s . endGroup ( ) ;
// Make sure the correct action is checked.
for ( QAction * action : group_by_actions_ - > actions ( ) ) {
if ( action - > property ( " group_by " ) . isNull ( ) ) continue ;
if ( g = = action - > property ( " group_by " ) . value < CollectionModel : : Grouping > ( ) ) {
action - > setChecked ( true ) ;
return ;
}
}
// Check the advanced action
group_by_actions_ - > actions ( ) . last ( ) - > setChecked ( true ) ;
}
2019-02-12 21:58:03 +01:00
void InternetSearchView : : SearchArtistsClicked ( bool checked ) {
2019-09-15 20:27:32 +02:00
Q_UNUSED ( checked ) ;
2019-02-12 21:58:03 +01:00
SetSearchType ( InternetSearch : : SearchType_Artists ) ;
}
void InternetSearchView : : SearchAlbumsClicked ( bool checked ) {
2019-09-15 20:27:32 +02:00
Q_UNUSED ( checked ) ;
2019-02-12 21:58:03 +01:00
SetSearchType ( InternetSearch : : SearchType_Albums ) ;
2018-08-09 18:10:03 +02:00
}
2019-02-12 21:58:03 +01:00
void InternetSearchView : : SearchSongsClicked ( bool checked ) {
2019-09-15 20:27:32 +02:00
Q_UNUSED ( checked ) ;
2019-02-12 21:58:03 +01:00
SetSearchType ( InternetSearch : : SearchType_Songs ) ;
2018-08-09 18:10:03 +02:00
}
2019-06-20 17:09:07 +02:00
void InternetSearchView : : SetSearchType ( const InternetSearch : : SearchType type ) {
2019-02-12 21:58:03 +01:00
search_type_ = type ;
2018-08-09 18:10:03 +02:00
QSettings s ;
2018-10-17 21:18:39 +02:00
s . beginGroup ( settings_group_ ) ;
2019-02-12 21:58:03 +01:00
s . setValue ( " type " , int ( search_type_ ) ) ;
2018-08-09 18:10:03 +02:00
s . endGroup ( ) ;
TextEdited ( ui_ - > search - > text ( ) ) ;
}
2018-09-06 17:39:26 +02:00
2019-06-20 16:33:28 +02:00
void InternetSearchView : : UpdateStatus ( const int id , const QString & text ) {
if ( id ! = last_search_id_ ) return ;
2018-09-06 17:39:26 +02:00
ui_ - > progressbar - > show ( ) ;
ui_ - > label_status - > setText ( text ) ;
2019-06-20 16:33:28 +02:00
2018-09-06 17:39:26 +02:00
}
2019-06-20 16:33:28 +02:00
void InternetSearchView : : ProgressSetMaximum ( const int id , const int max ) {
if ( id ! = last_search_id_ ) return ;
2018-09-06 17:39:26 +02:00
ui_ - > progressbar - > setMaximum ( max ) ;
2019-06-20 16:33:28 +02:00
2018-09-06 17:39:26 +02:00
}
2019-06-20 16:33:28 +02:00
void InternetSearchView : : UpdateProgress ( const int id , const int progress ) {
if ( id ! = last_search_id_ ) return ;
2018-09-06 17:39:26 +02:00
ui_ - > progressbar - > setValue ( progress ) ;
2019-06-20 16:33:28 +02:00
2018-09-06 17:39:26 +02:00
}
2019-06-07 20:23:05 +02:00
void InternetSearchView : : AddArtists ( ) {
MimeData * data = SelectedMimeData ( ) ;
if ( ! data ) return ;
if ( const InternetSongMimeData * internet_song_data = qobject_cast < const InternetSongMimeData * > ( data ) ) {
emit AddArtistsSignal ( internet_song_data - > songs ) ;
}
}
void InternetSearchView : : AddAlbums ( ) {
MimeData * data = SelectedMimeData ( ) ;
if ( ! data ) return ;
if ( const InternetSongMimeData * internet_song_data = qobject_cast < const InternetSongMimeData * > ( data ) ) {
emit AddAlbumsSignal ( internet_song_data - > songs ) ;
}
}
void InternetSearchView : : AddSongs ( ) {
MimeData * data = SelectedMimeData ( ) ;
if ( ! data ) return ;
if ( const InternetSongMimeData * internet_song_data = qobject_cast < const InternetSongMimeData * > ( data ) ) {
emit AddSongsSignal ( internet_song_data - > songs ) ;
}
}