2018-02-27 18:06:05 +01:00
/*
* Strawberry Music Player
* This file was part of Clementine .
* Copyright 2010 , David Sansome < me @ davidsansome . com >
2022-08-20 14:51:19 +02:00
* Copyright 2019 - 2022 , Jonas Kvinge < jonas @ jkvinge . net >
2018-02-27 18:06:05 +01:00
*
* 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/>.
2018-08-09 18:39:44 +02:00
*
2018-02-27 18:06:05 +01:00
*/
# include "config.h"
2024-04-23 17:15:42 +02:00
# include <utility>
2021-06-21 15:40:25 +02:00
# include <memory>
2018-05-01 00:41:33 +02:00
# include <QApplication>
# include <QWidget>
# include <QObject>
# include <QDataStream>
# include <QIODevice>
# include <QAction>
2018-02-27 18:06:05 +01:00
# include <QActionGroup>
2018-05-01 00:41:33 +02:00
# include <QByteArray>
# include <QVariant>
# include <QString>
# include <QStringList>
2020-07-18 04:05:07 +02:00
# include <QRegularExpression>
2018-02-27 18:06:05 +01:00
# include <QInputDialog>
2018-05-01 00:41:33 +02:00
# include <QList>
# include <QTimer>
2018-02-27 18:06:05 +01:00
# include <QMenu>
# include <QSettings>
2018-05-01 00:41:33 +02:00
# include <QToolButton>
# include <QtEvents>
2018-02-27 18:06:05 +01:00
2018-05-01 00:41:33 +02:00
# include "core/iconloader.h"
# include "core/song.h"
2018-08-29 21:42:24 +02:00
# include "core/logging.h"
2024-04-11 02:56:01 +02:00
# include "core/settings.h"
2023-01-08 15:40:54 +01:00
# include "collectionfilteroptions.h"
2018-02-27 18:06:05 +01:00
# include "collectionmodel.h"
2018-05-01 00:41:33 +02:00
# include "savedgroupingmanager.h"
# include "collectionfilterwidget.h"
2018-02-27 18:06:05 +01:00
# include "groupbydialog.h"
# include "ui_collectionfilterwidget.h"
2020-02-08 03:40:30 +01:00
# include "widgets/qsearchfield.h"
2023-03-18 00:59:34 +01:00
# include "settings/collectionsettingspage.h"
2020-06-28 18:36:48 +02:00
# include "settings/appearancesettingspage.h"
2018-02-27 18:06:05 +01:00
CollectionFilterWidget : : CollectionFilterWidget ( QWidget * parent )
: QWidget ( parent ) ,
ui_ ( new Ui_CollectionFilterWidget ) ,
model_ ( nullptr ) ,
2022-08-20 14:51:19 +02:00
group_by_dialog_ ( new GroupByDialog ( this ) ) ,
groupings_manager_ ( nullptr ) ,
filter_age_menu_ ( nullptr ) ,
group_by_menu_ ( nullptr ) ,
collection_menu_ ( nullptr ) ,
group_by_group_ ( nullptr ) ,
2018-02-27 18:06:05 +01:00
filter_delay_ ( new QTimer ( this ) ) ,
filter_applies_to_model_ ( true ) ,
2023-02-18 14:09:27 +01:00
delay_behaviour_ ( DelayBehaviour : : DelayedOnLargeLibraries ) {
2018-08-29 21:42:24 +02:00
2018-02-27 18:06:05 +01:00
ui_ - > setupUi ( this ) ;
2024-04-09 23:20:26 +02:00
QString available_fields = Song : : kFtsColumns . join ( QStringLiteral ( " , " ) ) . replace ( QRegularExpression ( QStringLiteral ( " \\ bfts " ) ) , QLatin1String ( " " ) ) ;
available_fields + = QStringLiteral ( " , " ) + Song : : kNumericalColumns . join ( QStringLiteral ( " , " ) ) ;
2019-12-29 23:37:48 +01:00
2021-06-28 00:11:45 +02:00
ui_ - > search_field - > setToolTip (
2024-04-09 23:20:26 +02:00
QStringLiteral ( " <html><head/><body><p> " ) +
2022-03-22 21:09:05 +01:00
tr ( " Prefix a word with a field name to limit the search to that field, e.g.: " ) +
2024-04-09 23:20:26 +02:00
QStringLiteral ( " " ) +
QStringLiteral ( " <span style= \" font-weight:600; \" > " ) +
2022-03-22 21:09:05 +01:00
tr ( " artist " ) +
2024-04-09 23:20:26 +02:00
QStringLiteral ( " :</span><span style= \" font-style:italic; \" >Strawbs</span> " ) +
tr ( " searches the collection for all artists that contain the word %1. " ) . arg ( QStringLiteral ( " Strawbs " ) ) +
QStringLiteral ( " </p><p> " ) +
2023-07-31 13:44:08 +02:00
tr ( " Search terms for numerical fields can be prefixed with %1 or %2 to refine the search, e.g.: " )
2024-04-11 02:56:01 +02:00
. arg ( QStringLiteral ( " =, !=, <, >, <= " ) , QStringLiteral ( " >= " ) ) +
2024-04-09 23:20:26 +02:00
QStringLiteral ( " <span style= \" font-weight:600; \" > " ) +
2023-07-31 13:44:08 +02:00
tr ( " rating " ) +
2024-04-09 23:20:26 +02:00
QStringLiteral ( " </span> " ) +
QStringLiteral ( " :>= " ) +
QStringLiteral ( " <span style= \" font-weight:italic; \" >4</span> " ) +
2023-07-31 13:44:08 +02:00
2024-04-09 23:20:26 +02:00
QStringLiteral ( " </p><p><span style= \" font-weight:600; \" > " ) +
2022-03-22 21:09:05 +01:00
tr ( " Available fields " ) +
2024-04-09 23:20:26 +02:00
QStringLiteral ( " : " ) +
QStringLiteral ( " </span> " ) +
QStringLiteral ( " <span style= \" font-style:italic; \" > " ) +
2022-03-22 21:09:05 +01:00
available_fields +
2024-04-09 23:20:26 +02:00
QStringLiteral ( " </span>. " ) +
QStringLiteral ( " </p></body></html> " )
2023-07-31 13:44:08 +02:00
) ;
2018-02-27 18:06:05 +01:00
2021-06-28 00:11:45 +02:00
QObject : : connect ( ui_ - > search_field , & QSearchField : : returnPressed , this , & CollectionFilterWidget : : ReturnPressed ) ;
2021-01-26 16:48:04 +01:00
QObject : : connect ( filter_delay_ , & QTimer : : timeout , this , & CollectionFilterWidget : : FilterDelayTimeout ) ;
2018-02-27 18:06:05 +01:00
filter_delay_ - > setInterval ( kFilterDelay ) ;
filter_delay_ - > setSingleShot ( true ) ;
// Icons
2024-04-09 23:20:26 +02:00
ui_ - > options - > setIcon ( IconLoader : : Load ( QStringLiteral ( " configure " ) ) ) ;
2018-02-27 18:06:05 +01:00
// Filter by age
QActionGroup * filter_age_group = new QActionGroup ( this ) ;
filter_age_group - > addAction ( ui_ - > filter_age_all ) ;
filter_age_group - > addAction ( ui_ - > filter_age_today ) ;
filter_age_group - > addAction ( ui_ - > filter_age_week ) ;
filter_age_group - > addAction ( ui_ - > filter_age_month ) ;
filter_age_group - > addAction ( ui_ - > filter_age_three_months ) ;
filter_age_group - > addAction ( ui_ - > filter_age_year ) ;
filter_age_menu_ = new QMenu ( tr ( " Show " ) , this ) ;
filter_age_menu_ - > addActions ( filter_age_group - > actions ( ) ) ;
2019-07-08 22:27:45 +02:00
filter_ages_ [ ui_ - > filter_age_all ] = - 1 ;
filter_ages_ [ ui_ - > filter_age_today ] = 60 * 60 * 24 ;
filter_ages_ [ ui_ - > filter_age_week ] = 60 * 60 * 24 * 7 ;
filter_ages_ [ ui_ - > filter_age_month ] = 60 * 60 * 24 * 30 ;
filter_ages_ [ ui_ - > filter_age_three_months ] = 60 * 60 * 24 * 30 * 3 ;
filter_ages_ [ ui_ - > filter_age_year ] = 60 * 60 * 24 * 365 ;
2018-02-27 18:06:05 +01:00
group_by_menu_ = new QMenu ( tr ( " Group by " ) , this ) ;
2021-01-26 16:48:04 +01:00
QObject : : connect ( ui_ - > save_grouping , & QAction : : triggered , this , & CollectionFilterWidget : : SaveGroupBy ) ;
QObject : : connect ( ui_ - > manage_groupings , & QAction : : triggered , this , & CollectionFilterWidget : : ShowGroupingManager ) ;
2018-02-27 18:06:05 +01:00
// Collection config menu
collection_menu_ = new QMenu ( tr ( " Display options " ) , this ) ;
collection_menu_ - > setIcon ( ui_ - > options - > icon ( ) ) ;
collection_menu_ - > addMenu ( filter_age_menu_ ) ;
collection_menu_ - > addMenu ( group_by_menu_ ) ;
collection_menu_ - > addAction ( ui_ - > save_grouping ) ;
collection_menu_ - > addAction ( ui_ - > manage_groupings ) ;
collection_menu_ - > addSeparator ( ) ;
ui_ - > options - > setMenu ( collection_menu_ ) ;
2021-06-28 00:11:45 +02:00
QObject : : connect ( ui_ - > search_field , & QSearchField : : textChanged , this , & CollectionFilterWidget : : FilterTextChanged ) ;
2022-01-10 22:51:27 +01:00
QObject : : connect ( ui_ - > options , & QToolButton : : clicked , ui_ - > options , & QToolButton : : showMenu ) ;
2018-02-27 18:06:05 +01:00
2020-06-28 18:36:48 +02:00
ReloadSettings ( ) ;
2018-02-27 18:06:05 +01:00
}
CollectionFilterWidget : : ~ CollectionFilterWidget ( ) { delete ui_ ; }
2021-06-28 00:14:16 +02:00
void CollectionFilterWidget : : Init ( CollectionModel * model ) {
if ( model_ ) {
QObject : : disconnect ( model_ , nullptr , this , nullptr ) ;
2022-08-20 14:51:19 +02:00
QObject : : disconnect ( model_ , nullptr , group_by_dialog_ , nullptr ) ;
QObject : : disconnect ( group_by_dialog_ , nullptr , model_ , nullptr ) ;
2024-04-23 17:15:42 +02:00
const QList < QAction * > filter_ages = filter_ages_ . keys ( ) ;
2021-06-28 00:14:16 +02:00
for ( QAction * action : filter_ages ) {
QObject : : disconnect ( action , & QAction : : triggered , model_ , nullptr ) ;
}
}
model_ = model ;
// Connect signals
2022-08-20 14:51:19 +02:00
QObject : : connect ( model_ , & CollectionModel : : GroupingChanged , group_by_dialog_ , & GroupByDialog : : CollectionGroupingChanged ) ;
2021-06-28 00:14:16 +02:00
QObject : : connect ( model_ , & CollectionModel : : GroupingChanged , this , & CollectionFilterWidget : : GroupingChanged ) ;
2022-08-20 14:51:19 +02:00
QObject : : connect ( group_by_dialog_ , & GroupByDialog : : Accepted , model_ , & CollectionModel : : SetGroupBy ) ;
2021-06-28 00:14:16 +02:00
2024-04-23 17:15:42 +02:00
const QList < QAction * > filter_ages = filter_ages_ . keys ( ) ;
2021-06-28 00:14:16 +02:00
for ( QAction * action : filter_ages ) {
int age = filter_ages_ [ action ] ;
2021-08-25 02:55:00 +02:00
QObject : : connect ( action , & QAction : : triggered , this , [ this , age ] ( ) { model_ - > SetFilterAge ( age ) ; } ) ;
2021-06-28 00:14:16 +02:00
}
// Load settings
if ( ! settings_group_ . isEmpty ( ) ) {
2024-04-11 02:56:01 +02:00
Settings s ;
2021-06-28 00:14:16 +02:00
s . beginGroup ( settings_group_ ) ;
int version = 0 ;
if ( s . contains ( group_by_version ( ) ) ) version = s . value ( group_by_version ( ) , 0 ) . toInt ( ) ;
if ( version = = 1 ) {
model_ - > SetGroupBy ( CollectionModel : : Grouping (
2023-02-18 14:09:27 +01:00
static_cast < CollectionModel : : GroupBy > ( s . value ( group_by_key ( 1 ) , static_cast < int > ( CollectionModel : : GroupBy : : AlbumArtist ) ) . toInt ( ) ) ,
static_cast < CollectionModel : : GroupBy > ( s . value ( group_by_key ( 2 ) , static_cast < int > ( CollectionModel : : GroupBy : : AlbumDisc ) ) . toInt ( ) ) ,
static_cast < CollectionModel : : GroupBy > ( s . value ( group_by_key ( 3 ) , static_cast < int > ( CollectionModel : : GroupBy : : None ) ) . toInt ( ) ) ) ,
s . value ( separate_albums_by_grouping_key ( ) , false ) . toBool ( ) ) ;
2021-06-28 00:14:16 +02:00
}
else {
2023-02-18 14:09:27 +01:00
model_ - > SetGroupBy ( CollectionModel : : Grouping ( CollectionModel : : GroupBy : : AlbumArtist , CollectionModel : : GroupBy : : AlbumDisc , CollectionModel : : GroupBy : : None ) , false ) ;
2021-06-28 00:14:16 +02:00
}
s . endGroup ( ) ;
}
2022-08-20 14:51:19 +02:00
}
void CollectionFilterWidget : : SetSettingsGroup ( const QString & settings_group ) {
settings_group_ = settings_group ;
saved_groupings_settings_group_ = SavedGroupingManager : : GetSavedGroupingsSettingsGroup ( settings_group ) ;
UpdateGroupByActions ( ) ;
}
void CollectionFilterWidget : : SetSettingsPrefix ( const QString & prefix ) {
settings_prefix_ = prefix ;
2021-06-28 00:14:16 +02:00
}
2020-06-28 18:36:48 +02:00
void CollectionFilterWidget : : ReloadSettings ( ) {
2024-04-11 02:56:01 +02:00
Settings s ;
2020-06-28 18:36:48 +02:00
s . beginGroup ( AppearanceSettingsPage : : kSettingsGroup ) ;
int iconsize = s . value ( AppearanceSettingsPage : : kIconSizeConfigureButtons , 20 ) . toInt ( ) ;
s . endGroup ( ) ;
ui_ - > options - > setIconSize ( QSize ( iconsize , iconsize ) ) ;
2021-06-28 00:11:45 +02:00
ui_ - > search_field - > setIconSize ( iconsize ) ;
2020-06-28 18:36:48 +02:00
}
2022-08-20 14:51:19 +02:00
QString CollectionFilterWidget : : group_by_version ( ) const {
2019-06-08 00:15:54 +02:00
if ( settings_prefix_ . isEmpty ( ) ) {
2024-04-09 23:20:26 +02:00
return QStringLiteral ( " group_by_version " ) ;
2019-06-08 00:15:54 +02:00
}
else {
2024-04-09 23:20:26 +02:00
return QStringLiteral ( " %1_group_by_version " ) . arg ( settings_prefix_ ) ;
2019-06-08 00:15:54 +02:00
}
}
2022-08-20 14:51:19 +02:00
QString CollectionFilterWidget : : group_by_key ( ) const {
2020-09-12 00:18:08 +02:00
if ( settings_prefix_ . isEmpty ( ) ) {
2024-04-09 23:20:26 +02:00
return QStringLiteral ( " group_by " ) ;
2020-09-12 00:18:08 +02:00
}
else {
2024-04-09 23:20:26 +02:00
return QStringLiteral ( " %1_group_by " ) . arg ( settings_prefix_ ) ;
2020-09-12 00:18:08 +02:00
}
}
2022-08-20 14:51:19 +02:00
QString CollectionFilterWidget : : group_by_key ( const int number ) const { return group_by_key ( ) + QString : : number ( number ) ; }
QString CollectionFilterWidget : : separate_albums_by_grouping_key ( ) const {
if ( settings_prefix_ . isEmpty ( ) ) {
2024-04-09 23:20:26 +02:00
return QStringLiteral ( " separate_albums_by_grouping " ) ;
2022-08-20 14:51:19 +02:00
}
else {
2024-04-09 23:20:26 +02:00
return QStringLiteral ( " %1_separate_albums_by_grouping " ) . arg ( settings_prefix_ ) ;
2022-08-20 14:51:19 +02:00
}
}
2019-06-08 00:15:54 +02:00
2018-02-27 18:06:05 +01:00
void CollectionFilterWidget : : UpdateGroupByActions ( ) {
if ( group_by_group_ ) {
2021-01-26 16:48:04 +01:00
QObject : : disconnect ( group_by_group_ , nullptr , this , nullptr ) ;
2018-02-27 18:06:05 +01:00
delete group_by_group_ ;
}
2022-08-20 14:51:19 +02:00
group_by_group_ = CreateGroupByActions ( saved_groupings_settings_group_ , this ) ;
2018-02-27 18:06:05 +01:00
group_by_menu_ - > clear ( ) ;
group_by_menu_ - > addActions ( group_by_group_ - > actions ( ) ) ;
2021-01-26 16:48:04 +01:00
QObject : : connect ( group_by_group_ , & QActionGroup : : triggered , this , & CollectionFilterWidget : : GroupByClicked ) ;
2018-02-27 18:06:05 +01:00
if ( model_ ) {
CheckCurrentGrouping ( model_ - > GetGroupBy ( ) ) ;
}
}
2022-08-20 14:51:19 +02:00
QActionGroup * CollectionFilterWidget : : CreateGroupByActions ( const QString & saved_groupings_settings_group , QObject * parent ) {
2018-02-27 18:06:05 +01:00
QActionGroup * ret = new QActionGroup ( parent ) ;
2019-08-05 19:17:31 +02:00
2023-02-18 14:09:27 +01:00
ret - > addAction ( CreateGroupByAction ( tr ( " Group by Album artist/Album " ) , parent , CollectionModel : : Grouping ( CollectionModel : : GroupBy : : AlbumArtist , CollectionModel : : GroupBy : : Album ) ) ) ;
ret - > addAction ( CreateGroupByAction ( tr ( " Group by Album artist/Album - Disc " ) , parent , CollectionModel : : Grouping ( CollectionModel : : GroupBy : : AlbumArtist , CollectionModel : : GroupBy : : AlbumDisc ) ) ) ;
ret - > addAction ( CreateGroupByAction ( tr ( " Group by Album artist/Year - Album " ) , parent , CollectionModel : : Grouping ( CollectionModel : : GroupBy : : AlbumArtist , CollectionModel : : GroupBy : : YearAlbum ) ) ) ;
ret - > addAction ( CreateGroupByAction ( tr ( " Group by Album artist/Year - Album - Disc " ) , parent , CollectionModel : : Grouping ( CollectionModel : : GroupBy : : AlbumArtist , CollectionModel : : GroupBy : : YearAlbumDisc ) ) ) ;
2019-08-05 19:17:31 +02:00
2023-02-18 14:09:27 +01:00
ret - > addAction ( CreateGroupByAction ( tr ( " Group by Artist/Album " ) , parent , CollectionModel : : Grouping ( CollectionModel : : GroupBy : : Artist , CollectionModel : : GroupBy : : Album ) ) ) ;
ret - > addAction ( CreateGroupByAction ( tr ( " Group by Artist/Album - Disc " ) , parent , CollectionModel : : Grouping ( CollectionModel : : GroupBy : : Artist , CollectionModel : : GroupBy : : AlbumDisc ) ) ) ;
ret - > addAction ( CreateGroupByAction ( tr ( " Group by Artist/Year - Album " ) , parent , CollectionModel : : Grouping ( CollectionModel : : GroupBy : : Artist , CollectionModel : : GroupBy : : YearAlbum ) ) ) ;
ret - > addAction ( CreateGroupByAction ( tr ( " Group by Artist/Year - Album - Disc " ) , parent , CollectionModel : : Grouping ( CollectionModel : : GroupBy : : Artist , CollectionModel : : GroupBy : : YearAlbumDisc ) ) ) ;
2019-08-05 19:17:31 +02:00
2023-02-18 14:09:27 +01:00
ret - > addAction ( CreateGroupByAction ( tr ( " Group by Genre/Album artist/Album " ) , parent , CollectionModel : : Grouping ( CollectionModel : : GroupBy : : Genre , CollectionModel : : GroupBy : : AlbumArtist , CollectionModel : : GroupBy : : Album ) ) ) ;
ret - > addAction ( CreateGroupByAction ( tr ( " Group by Genre/Artist/Album " ) , parent , CollectionModel : : Grouping ( CollectionModel : : GroupBy : : Genre , CollectionModel : : GroupBy : : Artist , CollectionModel : : GroupBy : : Album ) ) ) ;
2019-08-05 19:17:31 +02:00
2023-02-18 14:09:27 +01:00
ret - > addAction ( CreateGroupByAction ( tr ( " Group by Album Artist " ) , parent , CollectionModel : : Grouping ( CollectionModel : : GroupBy : : AlbumArtist ) ) ) ;
ret - > addAction ( CreateGroupByAction ( tr ( " Group by Artist " ) , parent , CollectionModel : : Grouping ( CollectionModel : : GroupBy : : Artist ) ) ) ;
2019-08-05 19:17:31 +02:00
2023-02-18 14:09:27 +01:00
ret - > addAction ( CreateGroupByAction ( tr ( " Group by Album " ) , parent , CollectionModel : : Grouping ( CollectionModel : : GroupBy : : Album ) ) ) ;
ret - > addAction ( CreateGroupByAction ( tr ( " Group by Genre/Album " ) , parent , CollectionModel : : Grouping ( CollectionModel : : GroupBy : : Genre , CollectionModel : : GroupBy : : Album ) ) ) ;
2018-02-27 18:06:05 +01:00
QAction * sep1 = new QAction ( parent ) ;
sep1 - > setSeparator ( true ) ;
ret - > addAction ( sep1 ) ;
2022-08-20 14:51:19 +02:00
// Read saved groupings
2024-04-11 02:56:01 +02:00
Settings s ;
2022-08-20 14:51:19 +02:00
s . beginGroup ( saved_groupings_settings_group ) ;
2020-09-10 22:09:24 +02:00
int version = s . value ( " version " ) . toInt ( ) ;
if ( version = = 1 ) {
QStringList saved = s . childKeys ( ) ;
for ( int i = 0 ; i < saved . size ( ) ; + + i ) {
2024-04-11 02:56:01 +02:00
if ( saved . at ( i ) = = QStringLiteral ( " version " ) ) continue ;
2020-09-10 22:09:24 +02:00
QByteArray bytes = s . value ( saved . at ( i ) ) . toByteArray ( ) ;
QDataStream ds ( & bytes , QIODevice : : ReadOnly ) ;
CollectionModel : : Grouping g ;
ds > > g ;
ret - > addAction ( CreateGroupByAction ( saved . at ( i ) , parent , g ) ) ;
}
}
else {
QStringList saved = s . childKeys ( ) ;
for ( int i = 0 ; i < saved . size ( ) ; + + i ) {
2024-04-11 02:56:01 +02:00
if ( saved . at ( i ) = = QStringLiteral ( " version " ) ) continue ;
2020-09-10 22:09:24 +02:00
s . remove ( saved . at ( i ) ) ;
}
2018-02-27 18:06:05 +01:00
}
2020-09-10 22:09:24 +02:00
s . endGroup ( ) ;
2018-02-27 18:06:05 +01:00
QAction * sep2 = new QAction ( parent ) ;
sep2 - > setSeparator ( true ) ;
ret - > addAction ( sep2 ) ;
ret - > addAction ( CreateGroupByAction ( tr ( " Advanced grouping... " ) , parent , CollectionModel : : Grouping ( ) ) ) ;
return ret ;
}
2021-06-20 19:04:08 +02:00
QAction * CollectionFilterWidget : : CreateGroupByAction ( const QString & text , QObject * parent , const CollectionModel : : Grouping grouping ) {
2018-02-27 18:06:05 +01:00
QAction * ret = new QAction ( text , parent ) ;
ret - > setCheckable ( true ) ;
2023-02-18 14:09:27 +01:00
if ( grouping . first ! = CollectionModel : : GroupBy : : None ) {
2018-02-27 18:06:05 +01:00
ret - > setProperty ( " group_by " , QVariant : : fromValue ( grouping ) ) ;
}
return ret ;
}
void CollectionFilterWidget : : SaveGroupBy ( ) {
2022-08-20 14:51:19 +02:00
if ( ! model_ ) return ;
QString name = QInputDialog : : getText ( this , tr ( " Grouping Name " ) , tr ( " Grouping name: " ) ) ;
if ( name . isEmpty ( ) ) return ;
qLog ( Debug ) < < " Saving current grouping to " < < name ;
2024-04-11 02:56:01 +02:00
Settings s ;
if ( settings_group_ . isEmpty ( ) | | settings_group_ = = QLatin1String ( CollectionSettingsPage : : kSettingsGroup ) ) {
2022-08-20 14:51:19 +02:00
s . beginGroup ( SavedGroupingManager : : kSavedGroupingsSettingsGroup ) ;
}
else {
2024-04-11 02:56:01 +02:00
s . beginGroup ( QLatin1String ( SavedGroupingManager : : kSavedGroupingsSettingsGroup ) + QLatin1Char ( ' _ ' ) + settings_group_ ) ;
2018-02-27 18:06:05 +01:00
}
2022-08-20 14:51:19 +02:00
QByteArray buffer ;
QDataStream datastream ( & buffer , QIODevice : : WriteOnly ) ;
datastream < < model_ - > GetGroupBy ( ) ;
2024-04-11 02:56:01 +02:00
s . setValue ( " version " , QStringLiteral ( " 1 " ) ) ;
2022-08-20 14:51:19 +02:00
s . setValue ( name , buffer ) ;
s . endGroup ( ) ;
UpdateGroupByActions ( ) ;
2018-02-27 18:06:05 +01:00
}
void CollectionFilterWidget : : ShowGroupingManager ( ) {
if ( ! groupings_manager_ ) {
2022-08-20 14:51:19 +02:00
groupings_manager_ = new SavedGroupingManager ( saved_groupings_settings_group_ , this ) ;
QObject : : connect ( groupings_manager_ , & SavedGroupingManager : : UpdateGroupByActions , this , & CollectionFilterWidget : : UpdateGroupByActions ) ;
2018-02-27 18:06:05 +01:00
}
2022-08-20 14:51:19 +02:00
2018-02-27 18:06:05 +01:00
groupings_manager_ - > UpdateModel ( ) ;
groupings_manager_ - > show ( ) ;
}
2021-09-27 21:42:30 +02:00
bool CollectionFilterWidget : : SearchFieldHasFocus ( ) const {
return ui_ - > search_field - > hasFocus ( ) ;
}
void CollectionFilterWidget : : FocusSearchField ( ) {
ui_ - > search_field - > setFocus ( ) ;
}
2018-02-27 18:06:05 +01:00
void CollectionFilterWidget : : FocusOnFilter ( QKeyEvent * event ) {
2021-06-28 00:11:45 +02:00
ui_ - > search_field - > setFocus ( ) ;
QApplication : : sendEvent ( ui_ - > search_field , event ) ;
2018-02-27 18:06:05 +01:00
}
void CollectionFilterWidget : : GroupByClicked ( QAction * action ) {
2020-04-20 18:03:18 +02:00
2018-02-27 18:06:05 +01:00
if ( action - > property ( " group_by " ) . isNull ( ) ) {
group_by_dialog_ - > show ( ) ;
return ;
}
CollectionModel : : Grouping g = action - > property ( " group_by " ) . value < CollectionModel : : Grouping > ( ) ;
2022-08-20 16:47:09 +02:00
model_ - > SetGroupBy ( g ) ;
2020-04-20 18:03:18 +02:00
2018-02-27 18:06:05 +01:00
}
2022-08-20 14:51:19 +02:00
void CollectionFilterWidget : : GroupingChanged ( const CollectionModel : : Grouping g , const bool separate_albums_by_grouping ) {
2018-02-27 18:06:05 +01:00
if ( ! settings_group_ . isEmpty ( ) ) {
2024-04-11 02:56:01 +02:00
Settings s ;
2018-02-27 18:06:05 +01:00
s . beginGroup ( settings_group_ ) ;
2020-09-12 00:18:08 +02:00
s . setValue ( group_by_version ( ) , 1 ) ;
2022-08-20 14:51:19 +02:00
s . setValue ( group_by_key ( 1 ) , static_cast < int > ( g [ 0 ] ) ) ;
s . setValue ( group_by_key ( 2 ) , static_cast < int > ( g [ 1 ] ) ) ;
s . setValue ( group_by_key ( 3 ) , static_cast < int > ( g [ 2 ] ) ) ;
s . setValue ( separate_albums_by_grouping_key ( ) , separate_albums_by_grouping ) ;
2020-09-10 22:09:24 +02:00
s . endGroup ( ) ;
2018-02-27 18:06:05 +01:00
}
// Now make sure the correct action is checked
CheckCurrentGrouping ( g ) ;
}
2021-06-21 19:54:42 +02:00
void CollectionFilterWidget : : CheckCurrentGrouping ( const CollectionModel : : Grouping g ) {
2018-02-27 18:06:05 +01:00
2022-08-20 14:51:19 +02:00
if ( ! group_by_group_ ) {
UpdateGroupByActions ( ) ;
}
2024-04-23 17:15:42 +02:00
const QList < QAction * > actions = group_by_group_ - > actions ( ) ;
for ( QAction * action : actions ) {
2018-02-27 18:06:05 +01:00
if ( action - > property ( " group_by " ) . isNull ( ) ) continue ;
if ( g = = action - > property ( " group_by " ) . value < CollectionModel : : Grouping > ( ) ) {
action - > setChecked ( true ) ;
return ;
}
}
// Check the advanced action
2021-03-21 04:47:11 +01:00
QAction * action = actions . last ( ) ;
action - > setChecked ( true ) ;
2018-02-27 18:06:05 +01:00
}
void CollectionFilterWidget : : SetFilterHint ( const QString & hint ) {
2021-06-28 00:11:45 +02:00
ui_ - > search_field - > setPlaceholderText ( hint ) ;
2018-02-27 18:06:05 +01:00
}
2023-01-08 15:40:54 +01:00
void CollectionFilterWidget : : SetFilterMode ( CollectionFilterOptions : : FilterMode filter_mode ) {
2018-02-27 18:06:05 +01:00
2021-06-28 00:11:45 +02:00
ui_ - > search_field - > clear ( ) ;
2023-02-18 14:09:27 +01:00
ui_ - > search_field - > setEnabled ( filter_mode = = CollectionFilterOptions : : FilterMode : : All ) ;
2018-02-27 18:06:05 +01:00
2023-01-08 15:40:54 +01:00
model_ - > SetFilterMode ( filter_mode ) ;
2018-02-27 18:06:05 +01:00
}
void CollectionFilterWidget : : ShowInCollection ( const QString & search ) {
2021-06-28 00:11:45 +02:00
ui_ - > search_field - > setText ( search ) ;
2018-02-27 18:06:05 +01:00
}
void CollectionFilterWidget : : SetAgeFilterEnabled ( bool enabled ) {
filter_age_menu_ - > setEnabled ( enabled ) ;
}
void CollectionFilterWidget : : SetGroupByEnabled ( bool enabled ) {
group_by_menu_ - > setEnabled ( enabled ) ;
}
void CollectionFilterWidget : : AddMenuAction ( QAction * action ) {
collection_menu_ - > addAction ( action ) ;
}
void CollectionFilterWidget : : keyReleaseEvent ( QKeyEvent * e ) {
switch ( e - > key ( ) ) {
case Qt : : Key_Up :
emit UpPressed ( ) ;
e - > accept ( ) ;
break ;
case Qt : : Key_Down :
emit DownPressed ( ) ;
e - > accept ( ) ;
break ;
case Qt : : Key_Escape :
2021-06-28 00:11:45 +02:00
ui_ - > search_field - > clear ( ) ;
2018-02-27 18:06:05 +01:00
e - > accept ( ) ;
break ;
}
QWidget : : keyReleaseEvent ( e ) ;
}
void CollectionFilterWidget : : FilterTextChanged ( const QString & text ) {
2018-05-01 00:41:33 +02:00
// Searching with one or two characters can be very expensive on the database even with FTS,
// so if there are a large number of songs in the database introduce a small delay before actually filtering the model,
// so if the user is typing the first few characters of something it will be quicker.
2023-02-18 14:09:27 +01:00
const bool delay = ( delay_behaviour_ = = DelayBehaviour : : AlwaysDelayed ) | | ( delay_behaviour_ = = DelayBehaviour : : DelayedOnLargeLibraries & & ! text . isEmpty ( ) & & text . length ( ) < 3 & & model_ - > total_song_count ( ) > = 100000 ) ;
2018-02-27 18:06:05 +01:00
if ( delay ) {
filter_delay_ - > start ( ) ;
}
else {
filter_delay_ - > stop ( ) ;
FilterDelayTimeout ( ) ;
}
}
void CollectionFilterWidget : : FilterDelayTimeout ( ) {
2021-06-28 00:11:45 +02:00
emit Filter ( ui_ - > search_field - > text ( ) ) ;
2018-02-27 18:06:05 +01:00
if ( filter_applies_to_model_ ) {
2021-06-28 00:11:45 +02:00
model_ - > SetFilterText ( ui_ - > search_field - > text ( ) ) ;
2018-02-27 18:06:05 +01:00
}
}