1 /*
2  *  Copyright (C) 2012-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #pragma once
10 
11 #include "DatabaseUtils.h"
12 #include "LabelFormatter.h"
13 #include "SortFileItem.h"
14 
15 #include <map>
16 #include <memory>
17 #include <string>
18 #include <vector>
19 
20 typedef enum {
21   SortOrderNone = 0,
22   SortOrderAscending,
23   SortOrderDescending
24 } SortOrder;
25 
26 typedef enum {
27   SortAttributeNone           = 0x0,
28   SortAttributeIgnoreArticle  = 0x1,
29   SortAttributeIgnoreFolders  = 0x2,
30   SortAttributeUseArtistSortName = 0x4,
31   SortAttributeIgnoreLabel = 0x8
32 } SortAttribute;
33 
34 typedef enum {
35   SortSpecialNone     = 0,
36   SortSpecialOnTop    = 1,
37   SortSpecialOnBottom = 2
38 } SortSpecial;
39 
40 ///
41 /// \defgroup List_of_sort_methods List of sort methods
42 /// \addtogroup List_of_sort_methods
43 ///
44 /// \brief These ID's can be used with the \ref built_in_functions_6 "Container.SetSortMethod(id)" function
45 /// \note The on field named part with <b>String</b> shows the string used on
46 /// GUI to set this sort type.
47 ///
48 ///@{
49 typedef enum {
50   /// __0__  :
51   SortByNone = 0,
52   /// __1__  : Sort by Name                       <em>(String: <b><c>Label</c></b>)</em>
53   SortByLabel,
54   /// __2__  : Sort by Date                       <em>(String: <b><c>Date</c></b>)</em>
55   SortByDate,
56   /// __3__  : Sort by Size                       <em>(String: <b><c>Size</c></b>)</em>
57   SortBySize,
58   /// __4__  : Sort by filename                   <em>(String: <b><c>File</c></b>)</em>
59   SortByFile,
60   /// __5__  : Sort by path                       <em>(String: <b><c>Path</c></b>)</em>
61   SortByPath,
62   /// __6__  : Sort by drive type                 <em>(String: <b><c>DriveType</c></b>)</em>
63   SortByDriveType,
64   /// __7__  : Sort by title                      <em>(String: <b><c>Title</c></b>)</em>
65   SortByTitle,
66   /// __8__  : Sort by track number               <em>(String: <b><c>TrackNumber</c></b>)</em>
67   SortByTrackNumber,
68   /// __9__  : Sort by time                       <em>(String: <b><c>Time</c></b>)</em>
69   SortByTime,
70   /// __10__ : Sort by artist                     <em>(String: <b><c>Artist</c></b>)</em>
71   SortByArtist,
72   /// __11__ : Sort by first artist then year     <em>(String: <b><c>ArtistYear</c></b>)</em>
73   SortByArtistThenYear,
74   /// __12__ : Sort by album                      <em>(String: <b><c>Album</c></b>)</em>
75   SortByAlbum,
76   /// __13__ : Sort by album type                 <em>(String: <b><c>AlbumType</c></b>)</em>
77   SortByAlbumType,
78   /// __14__ : Sort by genre                      <em>(String: <b><c>Genre</c></b>)</em>
79   SortByGenre,
80   /// __15__ : Sort by country                     <em>(String: <b><c>Country</c></b>)</em>
81   SortByCountry,
82   /// __16__ : Sort by year                       <em>(String: <b><c>Year</c></b>)</em>
83   SortByYear,
84   /// __17__ : Sort by rating                     <em>(String: <b><c>Rating</c></b>)</em>
85   SortByRating,
86   /// __18__ : Sort by user rating                <em>(String: <b><c>UserRating</c></b>)</em>
87   SortByUserRating,
88   /// __19__ : Sort by votes                      <em>(String: <b><c>Votes</c></b>)</em>
89   SortByVotes,
90   /// __20__ : Sort by top 250                    <em>(String: <b><c>Top250</c></b>)</em>
91   SortByTop250,
92   /// __21__ : Sort by program count              <em>(String: <b><c>ProgramCount</c></b>)</em>
93   SortByProgramCount,
94   /// __22__ : Sort by playlist order             <em>(String: <b><c>Playlist</c></b>)</em>
95   SortByPlaylistOrder,
96   /// __23__ : Sort by episode number             <em>(String: <b><c>Episode</c></b>)</em>
97   SortByEpisodeNumber,
98   /// __24__ : Sort by season                     <em>(String: <b><c>Season</c></b>)</em>
99   SortBySeason,
100   /// __25__ : Sort by number of episodes         <em>(String: <b><c>TotalEpisodes</c></b>)</em>
101   SortByNumberOfEpisodes,
102   /// __26__ : Sort by number of watched episodes <em>(String: <b><c>WatchedEpisodes</c></b>)</em>
103   SortByNumberOfWatchedEpisodes,
104   /// __27__ : Sort by TV show status             <em>(String: <b><c>TvShowStatus</c></b>)</em>
105   SortByTvShowStatus,
106   /// __28__ : Sort by TV show title              <em>(String: <b><c>TvShowTitle</c></b>)</em>
107   SortByTvShowTitle,
108   /// __29__ : Sort by sort title                 <em>(String: <b><c>SortTitle</c></b>)</em>
109   SortBySortTitle,
110   /// __30__ : Sort by production code            <em>(String: <b><c>ProductionCode</c></b>)</em>
111   SortByProductionCode,
112   /// __31__ : Sort by MPAA                       <em>(String: <b><c>MPAA</c></b>)</em>
113   SortByMPAA,
114   /// __32__ : Sort by video resolution           <em>(String: <b><c>VideoResolution</c></b>)</em>
115   SortByVideoResolution,
116   /// __33__ : Sort by video codec                <em>(String: <b><c>VideoCodec</c></b>)</em>
117   SortByVideoCodec,
118   /// __34__ : Sort by video aspect ratio         <em>(String: <b><c>VideoAspectRatio</c></b>)</em>
119   SortByVideoAspectRatio,
120   /// __35__ : Sort by audio channels             <em>(String: <b><c>AudioChannels</c></b>)</em>
121   SortByAudioChannels,
122   /// __36__ : Sort by audio codec                <em>(String: <b><c>AudioCodec</c></b>)</em>
123   SortByAudioCodec,
124   /// __37__ : Sort by audio language             <em>(String: <b><c>AudioLanguage</c></b>)</em>
125   SortByAudioLanguage,
126   /// __38__ : Sort by subtitle language          <em>(String: <b><c>SubtitleLanguage</c></b>)</em>
127   SortBySubtitleLanguage,
128   /// __39__ : Sort by studio                     <em>(String: <b><c>Studio</c></b>)</em>
129   SortByStudio,
130   /// __40__ : Sort by date added                 <em>(String: <b><c>DateAdded</c></b>)</em>
131   SortByDateAdded,
132   /// __41__ : Sort by last played                <em>(String: <b><c>LastPlayed</c></b>)</em>
133   SortByLastPlayed,
134   /// __42__ : Sort by playcount                  <em>(String: <b><c>PlayCount</c></b>)</em>
135   SortByPlaycount,
136   /// __43__ : Sort by listener                   <em>(String: <b><c>Listeners</c></b>)</em>
137   SortByListeners,
138   /// __44__ : Sort by bitrate                    <em>(String: <b><c>Bitrate</c></b>)</em>
139   SortByBitrate,
140   /// __45__ : Sort by random                     <em>(String: <b><c>Random</c></b>)</em>
141   SortByRandom,
142   /// __46__ : Sort by channel                    <em>(String: <b><c>Channel</c></b>)</em>
143   SortByChannel,
144   /// __47__ : Sort by channel number             <em>(String: <b><c>ChannelNumber</c></b>)</em>
145   SortByChannelNumber,
146   /// __48__ : Sort by date taken                 <em>(String: <b><c>DateTaken</c></b>)</em>
147   SortByDateTaken,
148   /// __49__ : Sort by relevance
149   SortByRelevance,
150   /// __50__ : Sort by installation date          <en>(String: <b><c>installdate</c></b>)</em>
151   SortByInstallDate,
152   /// __51__ : Sort by last updated               <en>(String: <b><c>lastupdated</c></b>)</em>
153   SortByLastUpdated,
154   /// __52__ : Sort by last used                  <em>(String: <b><c>lastused</c></b>)</em>
155   SortByLastUsed,
156   /// __53__ : Sort by client channel order       <em>(String: <b><c>ClientChannelOrder</c></b>)</em>
157   SortByClientChannelOrder,
158   /// __54__ : Sort by total number of discs      <em>(String: <b><c>totaldiscs</c></b>)</em>
159   SortByTotalDiscs,
160   /// __55__ : Sort by original release date      <em>(String: <b><c>Originaldate</c></b>)</em>
161   SortByOrigDate,
162   /// __56__ : Sort by BPM                        <em>(String: <b><c>bpm</c></b>)</em>
163   SortByBPM,
164 } SortBy;
165 ///@}
166 
167 typedef struct SortDescription {
168   SortBy sortBy = SortByNone;
169   SortOrder sortOrder = SortOrderAscending;
170   SortAttribute sortAttributes = SortAttributeNone;
171   int limitStart = 0;
172   int limitEnd = -1;
173 } SortDescription;
174 
175 typedef struct GUIViewSortDetails
176 {
177   SortDescription m_sortDescription;
178   int m_buttonLabel;
179   LABEL_MASKS m_labelMasks;
180 } GUIViewSortDetails;
181 
182 typedef DatabaseResult SortItem;
183 typedef std::shared_ptr<SortItem> SortItemPtr;
184 typedef std::vector<SortItemPtr> SortItems;
185 
186 class SortUtils
187 {
188 public:
189   static SORT_METHOD TranslateOldSortMethod(SortBy sortBy, bool ignoreArticle);
190   static SortDescription TranslateOldSortMethod(SORT_METHOD sortBy);
191 
192   static SortBy SortMethodFromString(const std::string& sortMethod);
193   static const std::string& SortMethodToString(SortBy sortMethod);
194   static SortOrder SortOrderFromString(const std::string& sortOrder);
195   static const std::string& SortOrderToString(SortOrder sortOrder);
196 
197   /*! \brief retrieve the label id associated with a sort method for displaying in the UI.
198    \param sortBy the sort method in question.
199    \return the label id of the sort method.
200    */
201   static int GetSortLabel(SortBy sortBy);
202 
203   static void Sort(SortBy sortBy, SortOrder sortOrder, SortAttribute attributes, DatabaseResults& items, int limitEnd = -1, int limitStart = 0);
204   static void Sort(SortBy sortBy, SortOrder sortOrder, SortAttribute attributes, SortItems& items, int limitEnd = -1, int limitStart = 0);
205   static void Sort(const SortDescription &sortDescription, DatabaseResults& items);
206   static void Sort(const SortDescription &sortDescription, SortItems& items);
207   static bool SortFromDataset(const SortDescription &sortDescription, const MediaType &mediaType, const std::unique_ptr<dbiplus::Dataset> &dataset, DatabaseResults &results);
208 
209   static void GetFieldsForSQLSort(const MediaType& mediaType, SortBy sortMethod, FieldList& fields);
210   static const Fields& GetFieldsForSorting(SortBy sortBy);
211   static std::string RemoveArticles(const std::string &label);
212 
213   typedef std::string (*SortPreparator) (SortAttribute, const SortItem&);
214   typedef bool (*Sorter) (const DatabaseResult &, const DatabaseResult &);
215   typedef bool (*SorterIndirect) (const SortItemPtr &, const SortItemPtr &);
216 
217 private:
218   static const SortPreparator& getPreparator(SortBy sortBy);
219   static Sorter getSorter(SortOrder sortOrder, SortAttribute attributes);
220   static SorterIndirect getSorterIndirect(SortOrder sortOrder, SortAttribute attributes);
221 
222   static std::map<SortBy, SortPreparator> m_preparators;
223   static std::map<SortBy, Fields> m_sortingFields;
224 };
225