2015-09-01 10:05:33 +05:30
// Copyright 2015 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
# pragma once
2019-08-20 17:27:33 +05:30
# include <algorithm>
2018-04-16 04:12:58 +05:30
# include <map>
# include <unordered_map>
2018-08-24 20:44:09 +05:30
# include <utility>
2018-04-19 01:31:45 +05:30
# include <QCoreApplication>
2018-04-20 06:26:24 +05:30
# include <QFileInfo>
2016-04-14 02:34:05 +05:30
# include <QImage>
2018-04-16 04:12:58 +05:30
# include <QObject>
2015-09-01 10:05:33 +05:30
# include <QRunnable>
# include <QStandardItem>
# include <QString>
2018-07-23 16:13:34 +05:30
# include <QWidget>
2019-08-15 10:08:54 +05:30
# include "citra_qt/uisettings.h"
2015-09-01 10:05:33 +05:30
# include "citra_qt/util/util.h"
2018-05-19 14:51:26 +05:30
# include "common/file_util.h"
2018-04-16 04:12:58 +05:30
# include "common/logging/log.h"
2016-09-18 06:08:01 +05:30
# include "common/string_util.h"
2016-05-18 05:12:45 +05:30
# include "core/loader/smdh.h"
2016-04-14 02:34:05 +05:30
2018-04-20 06:26:24 +05:30
enum class GameListItemType {
Game = QStandardItem : : UserType + 1 ,
CustomDir = QStandardItem : : UserType + 2 ,
InstalledDir = QStandardItem : : UserType + 3 ,
SystemDir = QStandardItem : : UserType + 4 ,
AddDir = QStandardItem : : UserType + 5
} ;
Q_DECLARE_METATYPE ( GameListItemType ) ;
2016-04-14 02:34:05 +05:30
/**
2017-02-27 07:28:51 +05:30
* Gets the game icon from SMDH data .
* @ param smdh SMDH data
2016-04-14 02:34:05 +05:30
* @ param large If true , returns large icon ( 48 x48 ) , otherwise returns small icon ( 24 x24 )
* @ return QPixmap game icon
*/
2016-05-18 05:12:45 +05:30
static QPixmap GetQPixmapFromSMDH ( const Loader : : SMDH & smdh , bool large ) {
std : : vector < u16 > icon_data = smdh . GetIcon ( large ) ;
const uchar * data = reinterpret_cast < const uchar * > ( icon_data . data ( ) ) ;
int size = large ? 48 : 24 ;
QImage icon ( data , size , size , QImage : : Format : : Format_RGB16 ) ;
2016-04-14 02:34:05 +05:30
return QPixmap : : fromImage ( icon ) ;
}
/**
* Gets the default icon ( for games without valid SMDH )
* @ param large If true , returns large icon ( 48 x48 ) , otherwise returns small icon ( 24 x24 )
* @ return QPixmap default icon
*/
static QPixmap GetDefaultIcon ( bool large ) {
int size = large ? 48 : 24 ;
QPixmap icon ( size , size ) ;
icon . fill ( Qt : : transparent ) ;
return icon ;
}
/**
2017-02-27 07:28:51 +05:30
* Gets the short game title from SMDH data .
* @ param smdh SMDH data
2016-04-14 02:34:05 +05:30
* @ param language title language
* @ return QString short title
*/
2016-09-18 06:08:01 +05:30
static QString GetQStringShortTitleFromSMDH ( const Loader : : SMDH & smdh ,
Loader : : SMDH : : TitleLanguage language ) {
2016-05-18 05:12:45 +05:30
return QString : : fromUtf16 ( smdh . GetShortTitle ( language ) . data ( ) ) ;
2016-04-14 02:34:05 +05:30
}
2015-09-01 10:05:33 +05:30
2019-09-05 07:45:37 +05:30
/**
* Gets the long game title from SMDH data .
* @ param smdh SMDH data
* @ param language title language
* @ return QString long title
*/
static QString GetQStringLongTitleFromSMDH ( const Loader : : SMDH & smdh ,
2019-09-06 07:24:39 +05:30
Loader : : SMDH : : TitleLanguage language ) {
2019-09-05 07:45:37 +05:30
return QString : : fromUtf16 ( smdh . GetLongTitle ( language ) . data ( ) ) ;
}
2018-05-01 23:27:01 +05:30
/**
* Gets the game region from SMDH data .
* @ param smdh SMDH data
* @ return QString region
*/
static QString GetRegionFromSMDH ( const Loader : : SMDH & smdh ) {
2019-08-11 17:22:08 +05:30
using GameRegion = Loader : : SMDH : : GameRegion ;
2019-08-11 20:14:54 +05:30
static const std : : map < GameRegion , const char * > regions_map = {
2020-03-01 04:59:36 +05:30
{ GameRegion : : Japan , QT_TRANSLATE_NOOP ( " GameRegion " , " Japan " ) } ,
{ GameRegion : : NorthAmerica , QT_TRANSLATE_NOOP ( " GameRegion " , " North America " ) } ,
{ GameRegion : : Europe , QT_TRANSLATE_NOOP ( " GameRegion " , " Europe " ) } ,
{ GameRegion : : Australia , QT_TRANSLATE_NOOP ( " GameRegion " , " Australia " ) } ,
{ GameRegion : : China , QT_TRANSLATE_NOOP ( " GameRegion " , " China " ) } ,
{ GameRegion : : Korea , QT_TRANSLATE_NOOP ( " GameRegion " , " Korea " ) } ,
{ GameRegion : : Taiwan , QT_TRANSLATE_NOOP ( " GameRegion " , " Taiwan " ) } } ;
2018-05-01 23:27:01 +05:30
2019-08-11 17:22:08 +05:30
std : : vector < GameRegion > regions = smdh . GetRegions ( ) ;
if ( regions . empty ( ) ) {
2020-03-01 04:59:36 +05:30
return QCoreApplication : : translate ( " GameRegion " , " Invalid region " ) ;
2019-08-11 17:22:08 +05:30
}
2019-08-20 18:33:41 +05:30
const bool region_free =
2019-08-20 17:27:33 +05:30
std : : all_of ( regions_map . begin ( ) , regions_map . end ( ) , [ & regions ] ( const auto & it ) {
return std : : find ( regions . begin ( ) , regions . end ( ) , it . first ) ! = regions . end ( ) ;
} ) ;
2019-08-20 18:33:41 +05:30
if ( region_free ) {
2020-03-01 04:59:36 +05:30
return QCoreApplication : : translate ( " GameRegion " , " Region free " ) ;
2019-08-20 17:27:33 +05:30
}
2019-08-20 17:33:15 +05:30
const QString separator =
UISettings : : values . game_list_single_line_mode ? QStringLiteral ( " , " ) : QStringLiteral ( " \n " ) ;
2020-03-01 04:59:36 +05:30
QString result = QCoreApplication : : translate ( " GameRegion " , regions_map . at ( regions . front ( ) ) ) ;
2019-08-11 17:22:08 +05:30
for ( auto region = + + regions . begin ( ) ; region ! = regions . end ( ) ; + + region ) {
2020-03-01 04:59:36 +05:30
result + = separator + QCoreApplication : : translate ( " GameRegion " , regions_map . at ( * region ) ) ;
2019-08-11 17:22:08 +05:30
}
return result ;
2018-05-01 23:27:01 +05:30
}
2018-04-16 04:12:58 +05:30
class GameListItem : public QStandardItem {
2015-09-01 10:05:33 +05:30
public :
2018-04-20 06:26:24 +05:30
// used to access type from item index
2020-09-09 20:36:15 +05:30
static constexpr int TypeRole = Qt : : UserRole + 1 ;
static constexpr int SortRole = Qt : : UserRole + 2 ;
2018-08-24 20:44:09 +05:30
GameListItem ( ) = default ;
explicit GameListItem ( const QString & string ) : QStandardItem ( string ) {
2018-04-20 06:26:24 +05:30
setData ( string , SortRole ) ;
}
2015-09-01 10:05:33 +05:30
} ;
2018-10-12 20:00:08 +05:30
/// Game list icon sizes (in px)
static const std : : unordered_map < UISettings : : GameListIconSize , int > IconSizes {
{ UISettings : : GameListIconSize : : NoIcon , 0 } ,
{ UISettings : : GameListIconSize : : SmallIcon , 24 } ,
{ UISettings : : GameListIconSize : : LargeIcon , 48 } ,
} ;
2015-09-01 10:05:33 +05:30
/**
* A specialization of GameListItem for path values .
* This class ensures that for every full path value it holds , a correct string representation
* of just the filename ( with no extension ) will be displayed to the user .
2016-10-20 19:56:59 +05:30
* If this class receives valid SMDH data , it will also display game icons and titles .
2015-09-01 10:05:33 +05:30
*/
class GameListItemPath : public GameListItem {
public :
2020-09-09 20:36:15 +05:30
static constexpr int TitleRole = SortRole + 1 ;
static constexpr int FullPathRole = SortRole + 2 ;
static constexpr int ProgramIdRole = SortRole + 3 ;
static constexpr int ExtdataIdRole = SortRole + 4 ;
static constexpr int LongTitleRole = SortRole + 5 ;
2015-09-01 10:05:33 +05:30
2018-08-24 20:44:09 +05:30
GameListItemPath ( ) = default ;
2018-09-16 10:18:39 +05:30
GameListItemPath ( const QString & game_path , const std : : vector < u8 > & smdh_data , u64 program_id ,
u64 extdata_id ) {
2018-04-20 06:26:24 +05:30
setData ( type ( ) , TypeRole ) ;
2015-09-01 10:05:33 +05:30
setData ( game_path , FullPathRole ) ;
2016-12-15 15:25:03 +05:30
setData ( qulonglong ( program_id ) , ProgramIdRole ) ;
2018-09-16 10:18:39 +05:30
setData ( qulonglong ( extdata_id ) , ExtdataIdRole ) ;
2016-04-14 02:34:05 +05:30
2018-10-12 20:00:08 +05:30
if ( UISettings : : values . game_list_icon_size = = UISettings : : GameListIconSize : : NoIcon ) {
2018-09-23 08:52:44 +05:30
// Do not display icons
setData ( QPixmap ( ) , Qt : : DecorationRole ) ;
}
2018-10-12 20:00:08 +05:30
bool large =
UISettings : : values . game_list_icon_size = = UISettings : : GameListIconSize : : LargeIcon ;
2018-09-23 08:52:44 +05:30
2018-01-24 09:02:27 +05:30
if ( ! Loader : : IsValidSMDH ( smdh_data ) ) {
2016-04-14 02:34:05 +05:30
// SMDH is not valid, set a default icon
2018-10-12 20:00:08 +05:30
if ( UISettings : : values . game_list_icon_size ! = UISettings : : GameListIconSize : : NoIcon )
2018-09-23 08:52:44 +05:30
setData ( GetDefaultIcon ( large ) , Qt : : DecorationRole ) ;
2016-04-14 02:34:05 +05:30
return ;
}
2018-01-24 21:47:04 +05:30
2018-01-24 21:46:40 +05:30
Loader : : SMDH smdh ;
2018-01-24 09:02:27 +05:30
memcpy ( & smdh , smdh_data . data ( ) , sizeof ( Loader : : SMDH ) ) ;
2016-04-14 02:34:05 +05:30
// Get icon from SMDH
2020-09-09 20:36:15 +05:30
if ( UISettings : : values . game_list_icon_size ! = UISettings : : GameListIconSize : : NoIcon ) {
2018-09-23 08:52:44 +05:30
setData ( GetQPixmapFromSMDH ( smdh , large ) , Qt : : DecorationRole ) ;
2020-09-09 20:36:15 +05:30
}
2016-04-14 02:34:05 +05:30
2018-01-20 23:03:14 +05:30
// Get title from SMDH
2016-09-18 06:08:01 +05:30
setData ( GetQStringShortTitleFromSMDH ( smdh , Loader : : SMDH : : TitleLanguage : : English ) ,
TitleRole ) ;
2019-09-05 07:45:37 +05:30
// Get long title from SMDH
setData ( GetQStringLongTitleFromSMDH ( smdh , Loader : : SMDH : : TitleLanguage : : English ) ,
LongTitleRole ) ;
2015-09-01 10:05:33 +05:30
}
2018-04-20 06:26:24 +05:30
int type ( ) const override {
return static_cast < int > ( GameListItemType : : Game ) ;
}
2016-04-14 02:34:05 +05:30
QVariant data ( int role ) const override {
2019-09-28 06:45:20 +05:30
if ( role = = Qt : : DisplayRole | | role = = SortRole ) {
2018-05-19 14:51:26 +05:30
std : : string path , filename , extension ;
Common : : SplitPath ( data ( FullPathRole ) . toString ( ) . toStdString ( ) , & path , & filename ,
& extension ) ;
2018-09-23 08:52:44 +05:30
2018-10-12 20:00:08 +05:30
const std : : unordered_map < UISettings : : GameListText , QString > display_texts {
{ UISettings : : GameListText : : FileName , QString : : fromStdString ( filename + extension ) } ,
{ UISettings : : GameListText : : FullPath , data ( FullPathRole ) . toString ( ) } ,
{ UISettings : : GameListText : : TitleName , data ( TitleRole ) . toString ( ) } ,
2019-09-05 07:45:37 +05:30
{ UISettings : : GameListText : : LongTitleName , data ( LongTitleRole ) . toString ( ) } ,
2018-10-12 20:00:08 +05:30
{ UISettings : : GameListText : : TitleID ,
QString : : fromStdString ( fmt : : format ( " {:016X} " , data ( ProgramIdRole ) . toULongLong ( ) ) ) } ,
} ;
2018-09-23 08:52:44 +05:30
2019-09-05 07:45:37 +05:30
const QString & row1 = display_texts . at ( UISettings : : values . game_list_row_1 ) . simplified ( ) ;
2018-09-23 08:52:44 +05:30
2019-10-26 03:19:13 +05:30
if ( role = = SortRole )
return row1 . toLower ( ) ;
2018-09-23 08:52:44 +05:30
QString row2 ;
2018-10-12 20:00:08 +05:30
auto row_2_id = UISettings : : values . game_list_row_2 ;
if ( row_2_id ! = UISettings : : GameListText : : NoText ) {
2019-08-20 17:33:15 +05:30
if ( ! row1 . isEmpty ( ) ) {
row2 = UISettings : : values . game_list_single_line_mode
? QStringLiteral ( " " )
: QStringLiteral ( " \n " ) ;
}
2019-09-09 01:36:19 +05:30
row2 + = display_texts . at ( row_2_id ) . simplified ( ) ;
2018-05-19 14:51:26 +05:30
}
2019-04-16 03:20:27 +05:30
return QString ( row1 + row2 ) ;
2015-09-01 10:05:33 +05:30
} else {
2016-04-14 02:34:05 +05:30
return GameListItem : : data ( role ) ;
2015-09-01 10:05:33 +05:30
}
}
} ;
2018-04-16 04:12:58 +05:30
class GameListItemCompat : public GameListItem {
2018-09-01 05:12:07 +05:30
Q_DECLARE_TR_FUNCTIONS ( GameListItemCompat )
2018-04-16 04:12:58 +05:30
public :
2020-09-09 20:36:15 +05:30
static constexpr int CompatNumberRole = SortRole ;
2018-04-16 04:12:58 +05:30
GameListItemCompat ( ) = default ;
2018-09-17 15:01:27 +05:30
explicit GameListItemCompat ( const QString & compatibility ) {
2018-04-20 06:26:24 +05:30
setData ( type ( ) , TypeRole ) ;
2018-09-01 05:12:07 +05:30
struct CompatStatus {
QString color ;
const char * text ;
const char * tooltip ;
} ;
// clang-format off
static const std : : map < QString , CompatStatus > status_data = {
2019-11-09 07:16:23 +05:30
{ QStringLiteral ( " 0 " ) , { QStringLiteral ( " #5c93ed " ) , QT_TR_NOOP ( " Perfect " ) , QT_TR_NOOP ( " Game functions flawless with no audio or graphical glitches, all tested functionality works as intended without \n any workarounds needed. " ) } } ,
{ QStringLiteral ( " 1 " ) , { QStringLiteral ( " #47d35c " ) , QT_TR_NOOP ( " Great " ) , QT_TR_NOOP ( " Game functions with minor graphical or audio glitches and is playable from start to finish. May require some \n workarounds. " ) } } ,
{ QStringLiteral ( " 2 " ) , { QStringLiteral ( " #94b242 " ) , QT_TR_NOOP ( " Okay " ) , QT_TR_NOOP ( " Game functions with major graphical or audio glitches, but game is playable from start to finish with \n workarounds. " ) } } ,
{ QStringLiteral ( " 3 " ) , { QStringLiteral ( " #f2d624 " ) , QT_TR_NOOP ( " Bad " ) , QT_TR_NOOP ( " Game functions, but with major graphical or audio glitches. Unable to progress in specific areas due to glitches \n even with workarounds. " ) } } ,
{ QStringLiteral ( " 4 " ) , { QStringLiteral ( " #ff0000 " ) , QT_TR_NOOP ( " Intro/Menu " ) , QT_TR_NOOP ( " Game is completely unplayable due to major graphical or audio glitches. Unable to progress past the Start \n Screen. " ) } } ,
{ QStringLiteral ( " 5 " ) , { QStringLiteral ( " #828282 " ) , QT_TR_NOOP ( " Won't Boot " ) , QT_TR_NOOP ( " The game crashes when attempting to startup. " ) } } ,
{ QStringLiteral ( " 99 " ) , { QStringLiteral ( " #000000 " ) , QT_TR_NOOP ( " Not Tested " ) , QT_TR_NOOP ( " The game has not yet been tested. " ) } } } ;
2018-09-01 05:12:07 +05:30
// clang-format on
2018-09-17 15:01:27 +05:30
auto iterator = status_data . find ( compatibility ) ;
2018-04-16 04:12:58 +05:30
if ( iterator = = status_data . end ( ) ) {
2018-09-17 15:01:27 +05:30
LOG_WARNING ( Frontend , " Invalid compatibility number {} " , compatibility . toStdString ( ) ) ;
2018-04-16 04:12:58 +05:30
return ;
}
2018-09-17 15:00:09 +05:30
const CompatStatus & status = iterator - > second ;
2018-09-17 15:01:27 +05:30
setData ( compatibility , CompatNumberRole ) ;
2018-09-01 05:12:07 +05:30
setText ( QObject : : tr ( status . text ) ) ;
setToolTip ( QObject : : tr ( status . tooltip ) ) ;
2018-04-16 04:12:58 +05:30
setData ( CreateCirclePixmapFromColor ( status . color ) , Qt : : DecorationRole ) ;
}
2018-04-20 06:26:24 +05:30
int type ( ) const override {
return static_cast < int > ( GameListItemType : : Game ) ;
}
2018-04-16 04:12:58 +05:30
bool operator < ( const QStandardItem & other ) const override {
2020-12-06 02:08:55 +05:30
return data ( CompatNumberRole ) . value < QString > ( ) <
other . data ( CompatNumberRole ) . value < QString > ( ) ;
2018-04-16 04:12:58 +05:30
}
} ;
2018-05-01 23:27:01 +05:30
class GameListItemRegion : public GameListItem {
public :
GameListItemRegion ( ) = default ;
explicit GameListItemRegion ( const std : : vector < u8 > & smdh_data ) {
2018-04-20 06:26:24 +05:30
setData ( type ( ) , TypeRole ) ;
2018-05-01 23:27:01 +05:30
if ( ! Loader : : IsValidSMDH ( smdh_data ) ) {
setText ( QObject : : tr ( " Invalid region " ) ) ;
return ;
}
Loader : : SMDH smdh ;
memcpy ( & smdh , smdh_data . data ( ) , sizeof ( Loader : : SMDH ) ) ;
setText ( GetRegionFromSMDH ( smdh ) ) ;
2018-04-20 06:26:24 +05:30
setData ( GetRegionFromSMDH ( smdh ) , SortRole ) ;
}
int type ( ) const override {
return static_cast < int > ( GameListItemType : : Game ) ;
2018-05-01 23:27:01 +05:30
}
} ;
2015-09-01 10:05:33 +05:30
/**
* A specialization of GameListItem for size values .
* This class ensures that for every numerical size value it holds ( in bytes ) , a correct
* human - readable string representation will be displayed to the user .
*/
class GameListItemSize : public GameListItem {
public :
2020-09-09 20:36:15 +05:30
static constexpr int SizeRole = SortRole ;
2015-09-01 10:05:33 +05:30
2018-08-24 20:44:09 +05:30
GameListItemSize ( ) = default ;
explicit GameListItemSize ( const qulonglong size_bytes ) {
2018-04-20 06:26:24 +05:30
setData ( type ( ) , TypeRole ) ;
2015-09-01 10:05:33 +05:30
setData ( size_bytes , SizeRole ) ;
}
2016-09-18 06:08:01 +05:30
void setData ( const QVariant & value , int role ) override {
2015-09-01 10:05:33 +05:30
// By specializing setData for SizeRole, we can ensure that the numerical and string
// representations of the data are always accurate and in the correct format.
if ( role = = SizeRole ) {
qulonglong size_bytes = value . toULongLong ( ) ;
GameListItem : : setData ( ReadableByteSize ( size_bytes ) , Qt : : DisplayRole ) ;
GameListItem : : setData ( value , SizeRole ) ;
} else {
GameListItem : : setData ( value , role ) ;
}
}
2018-04-20 06:26:24 +05:30
int type ( ) const override {
return static_cast < int > ( GameListItemType : : Game ) ;
}
2015-09-01 10:05:33 +05:30
/**
* This operator is , in practice , only used by the TreeView sorting systems .
2016-09-18 06:08:01 +05:30
* Override it so that it will correctly sort by numerical value instead of by string
* representation .
2015-09-01 10:05:33 +05:30
*/
2016-09-18 06:08:01 +05:30
bool operator < ( const QStandardItem & other ) const override {
2015-09-01 10:05:33 +05:30
return data ( SizeRole ) . toULongLong ( ) < other . data ( SizeRole ) . toULongLong ( ) ;
}
} ;
2018-04-20 06:26:24 +05:30
class GameListDir : public GameListItem {
public :
2020-09-09 20:36:15 +05:30
static constexpr int GameDirRole = Qt : : UserRole + 2 ;
2018-04-20 06:26:24 +05:30
explicit GameListDir ( UISettings : : GameDir & directory ,
GameListItemType dir_type = GameListItemType : : CustomDir )
: dir_type { dir_type } {
setData ( type ( ) , TypeRole ) ;
UISettings : : GameDir * game_dir = & directory ;
2020-05-10 08:06:40 +05:30
setData ( QVariant ( UISettings : : values . game_dirs . indexOf ( directory ) ) , GameDirRole ) ;
2018-09-23 08:52:44 +05:30
2019-09-22 20:57:01 +05:30
const int icon_size = IconSizes . at ( UISettings : : values . game_list_icon_size ) ;
2018-04-20 06:26:24 +05:30
switch ( dir_type ) {
case GameListItemType : : InstalledDir :
2019-09-22 20:57:01 +05:30
setData ( QIcon : : fromTheme ( QStringLiteral ( " sd_card " ) ) . pixmap ( icon_size ) ,
Qt : : DecorationRole ) ;
setData ( QObject : : tr ( " Installed Titles " ) , Qt : : DisplayRole ) ;
2018-04-20 06:26:24 +05:30
break ;
case GameListItemType : : SystemDir :
2019-09-22 20:57:01 +05:30
setData ( QIcon : : fromTheme ( QStringLiteral ( " chip " ) ) . pixmap ( icon_size ) , Qt : : DecorationRole ) ;
setData ( QObject : : tr ( " System Titles " ) , Qt : : DisplayRole ) ;
2018-04-20 06:26:24 +05:30
break ;
2019-11-02 23:26:23 +05:30
case GameListItemType : : CustomDir : {
2019-09-22 20:57:01 +05:30
QString icon_name = QFileInfo : : exists ( game_dir - > path ) ? QStringLiteral ( " folder " )
: QStringLiteral ( " bad_folder " ) ;
2018-09-23 08:52:44 +05:30
setData ( QIcon : : fromTheme ( icon_name ) . pixmap ( icon_size ) , Qt : : DecorationRole ) ;
2018-04-20 06:26:24 +05:30
setData ( game_dir - > path , Qt : : DisplayRole ) ;
break ;
2019-11-02 23:26:23 +05:30
}
default :
break ;
}
}
2018-04-20 06:26:24 +05:30
int type ( ) const override {
return static_cast < int > ( dir_type ) ;
}
2019-09-28 06:45:20 +05:30
/**
* Override to prevent automatic sorting .
*/
bool operator < ( const QStandardItem & other ) const override {
return false ;
}
2018-04-20 06:26:24 +05:30
private :
GameListItemType dir_type ;
} ;
class GameListAddDir : public GameListItem {
public :
explicit GameListAddDir ( ) {
setData ( type ( ) , TypeRole ) ;
2018-09-23 08:52:44 +05:30
2018-10-12 20:00:08 +05:30
int icon_size = IconSizes . at ( UISettings : : values . game_list_icon_size ) ;
2019-09-22 20:57:01 +05:30
setData ( QIcon : : fromTheme ( QStringLiteral ( " plus " ) ) . pixmap ( icon_size ) , Qt : : DecorationRole ) ;
setData ( QObject : : tr ( " Add New Game Directory " ) , Qt : : DisplayRole ) ;
2018-04-20 06:26:24 +05:30
}
int type ( ) const override {
return static_cast < int > ( GameListItemType : : AddDir ) ;
}
2019-09-28 06:45:20 +05:30
bool operator < ( const QStandardItem & other ) const override {
return false ;
}
2018-04-20 06:26:24 +05:30
} ;
2018-07-23 16:13:34 +05:30
class GameList ;
class QHBoxLayout ;
class QTreeView ;
class QLabel ;
class QLineEdit ;
class QToolButton ;
class GameListSearchField : public QWidget {
Q_OBJECT
public :
explicit GameListSearchField ( GameList * parent = nullptr ) ;
void setFilterResult ( int visible , int total ) ;
void clear ( ) ;
void setFocus ( ) ;
private :
class KeyReleaseEater : public QObject {
public :
2020-10-04 08:44:49 +05:30
explicit KeyReleaseEater ( GameList * gamelist , QObject * parent = nullptr ) ;
2018-07-23 16:13:34 +05:30
private :
GameList * gamelist = nullptr ;
QString edit_filter_text_old ;
protected :
// EventFilter in order to process systemkeys while editing the searchfield
bool eventFilter ( QObject * obj , QEvent * event ) override ;
} ;
2019-09-22 20:57:01 +05:30
int visible ;
int total ;
2018-07-23 16:13:34 +05:30
QHBoxLayout * layout_filter = nullptr ;
QTreeView * tree_view = nullptr ;
QLabel * label_filter = nullptr ;
QLineEdit * edit_filter = nullptr ;
QLabel * label_filter_result = nullptr ;
QToolButton * button_filter_close = nullptr ;
} ;