Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #1399 from Montellese/gsoc_advanced_filter

[GSoC] Advanced Library Filtering
  • Loading branch information...
commit 39ab944a45b51499854516a3efbdc623211fa998 2 parents 13c4fa3 + 7c46f10
@Montellese Montellese authored
Showing with 2,564 additions and 286 deletions.
  1. +6 −0 XBMC-ATV2.xcodeproj/project.pbxproj
  2. +6 −0 XBMC-IOS.xcodeproj/project.pbxproj
  3. +6 −0 XBMC.xcodeproj/project.pbxproj
  4. +184 −0 addons/skin.confluence/720p/DialogMediaFilter.xml
  5. +9 −0 addons/skin.confluence/720p/MyMusicNav.xml
  6. +9 −0 addons/skin.confluence/720p/MyMusicSongs.xml
  7. +8 −0 addons/skin.confluence/720p/MyPics.xml
  8. +8 −0 addons/skin.confluence/720p/MyPrograms.xml
  9. +9 −0 addons/skin.confluence/720p/MyVideoNav.xml
  10. +1 −1  addons/skin.confluence/720p/includes.xml
  11. +23 −1 language/English/strings.po
  12. +2 −0  project/VS2010Express/XBMC.vcxproj
  13. +6 −0 project/VS2010Express/XBMC.vcxproj.filters
  14. +4 −0 xbmc/Application.cpp
  15. +1 −0  xbmc/DbUrl.h
  16. +22 −1 xbmc/GUIInfoManager.cpp
  17. +4 −0 xbmc/GUIInfoManager.h
  18. +5 −0 xbmc/dbwrappers/Database.cpp
  19. +2 −1  xbmc/dbwrappers/Database.h
  20. +913 −0 xbmc/dialogs/GUIDialogMediaFilter.cpp
  21. +82 −0 xbmc/dialogs/GUIDialogMediaFilter.h
  22. +1 −0  xbmc/dialogs/Makefile
  23. +63 −34 xbmc/filesystem/SmartPlaylistDirectory.cpp
  24. +1 −1  xbmc/filesystem/SmartPlaylistDirectory.h
  25. +267 −80 xbmc/guilib/GUISliderControl.cpp
  26. +26 −12 xbmc/guilib/GUISliderControl.h
  27. +3 −0  xbmc/guilib/Key.h
  28. +3 −1 xbmc/input/ButtonTranslator.cpp
  29. +2 −2 xbmc/interfaces/json-rpc/AudioLibrary.cpp
  30. +197 −26 xbmc/music/MusicDatabase.cpp
  31. +9 −6 xbmc/music/MusicDatabase.h
  32. +37 −1 xbmc/music/windows/GUIWindowMusicBase.cpp
  33. +2 −0  xbmc/music/windows/GUIWindowMusicBase.h
  34. +1 −1  xbmc/music/windows/GUIWindowMusicNav.cpp
  35. +36 −6 xbmc/playlists/SmartPlayList.cpp
  36. +6 −0 xbmc/playlists/SmartPlayList.h
  37. +90 −17 xbmc/settings/GUIDialogSettings.cpp
  38. +10 −3 xbmc/settings/GUIDialogSettings.h
  39. +16 −0 xbmc/utils/URIUtils.cpp
  40. +39 −0 xbmc/utils/UrlOptions.cpp
  41. +6 −0 xbmc/utils/UrlOptions.h
  42. +157 −37 xbmc/video/VideoDatabase.cpp
  43. +11 −11 xbmc/video/VideoDatabase.h
  44. +38 −2 xbmc/video/windows/GUIWindowVideoBase.cpp
  45. +2 −0  xbmc/video/windows/GUIWindowVideoBase.h
  46. +17 −1 xbmc/video/windows/GUIWindowVideoNav.cpp
  47. +196 −41 xbmc/windows/GUIMediaWindow.cpp
  48. +18 −0 xbmc/windows/GUIMediaWindow.h
View
6 XBMC-ATV2.xcodeproj/project.pbxproj
@@ -26,6 +26,7 @@
36A9468815CF214300727135 /* VideoDbUrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9468615CF214300727135 /* VideoDbUrl.cpp */; };
36A9468B15CF215300727135 /* UrlOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9468915CF215300727135 /* UrlOptions.cpp */; };
36A9468E15CF217400727135 /* MusicDbUrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9468C15CF217400727135 /* MusicDbUrl.cpp */; };
+ 36A95DB41624898700727135 /* GUIDialogMediaFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A95DB21624898700727135 /* GUIDialogMediaFilter.cpp */; };
4D5D2E131301753F006ABC13 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D5D2E121301753F006ABC13 /* CFNetwork.framework */; };
7C0A7ECD13A5DBF900AFC2BD /* AppParamParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C0A7ECB13A5DBF900AFC2BD /* AppParamParser.cpp */; };
7C0A7FC813A9E75400AFC2BD /* DirtyRegionSolvers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C0A7FC413A9E75400AFC2BD /* DirtyRegionSolvers.cpp */; };
@@ -1031,6 +1032,8 @@
36A9468A15CF215300727135 /* UrlOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UrlOptions.h; sourceTree = "<group>"; };
36A9468C15CF217400727135 /* MusicDbUrl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MusicDbUrl.cpp; sourceTree = "<group>"; };
36A9468D15CF217400727135 /* MusicDbUrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MusicDbUrl.h; sourceTree = "<group>"; };
+ 36A95DB21624898700727135 /* GUIDialogMediaFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogMediaFilter.cpp; sourceTree = "<group>"; };
+ 36A95DB31624898700727135 /* GUIDialogMediaFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogMediaFilter.h; sourceTree = "<group>"; };
4D5D2E121301753F006ABC13 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
7C0A7ECB13A5DBF900AFC2BD /* AppParamParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppParamParser.cpp; sourceTree = "<group>"; };
7C0A7ECC13A5DBF900AFC2BD /* AppParamParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppParamParser.h; sourceTree = "<group>"; };
@@ -4601,6 +4604,8 @@
F56C7374131EC151000AD0F6 /* GUIDialogKaiToast.h */,
DF830D4915BB2D2300602BE6 /* GUIDialogKeyboardGeneric.cpp */,
DF830D4A15BB2D2300602BE6 /* GUIDialogKeyboardGeneric.h */,
+ 36A95DB21624898700727135 /* GUIDialogMediaFilter.cpp */,
+ 36A95DB31624898700727135 /* GUIDialogMediaFilter.h */,
F56C7377131EC151000AD0F6 /* GUIDialogMediaSource.cpp */,
F56C7378131EC151000AD0F6 /* GUIDialogMediaSource.h */,
F56C7379131EC151000AD0F6 /* GUIDialogMuteBug.cpp */,
@@ -7568,6 +7573,7 @@
7C4458DB161E209100A905F6 /* Screenshot.cpp in Sources */,
1D638118161E20AC003603ED /* PeripheralImon.cpp in Sources */,
DF24EAC71621E58D00034265 /* DVDDemuxBXA.cpp in Sources */,
+ 36A95DB41624898700727135 /* GUIDialogMediaFilter.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
6 XBMC-IOS.xcodeproj/project.pbxproj
@@ -27,6 +27,7 @@
36A9467815CF20A500727135 /* UrlOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9467615CF20A500727135 /* UrlOptions.cpp */; };
36A9467B15CF20BD00727135 /* VideoDbUrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9467915CF20BD00727135 /* VideoDbUrl.cpp */; };
36A9467E15CF20E100727135 /* DbUrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9467C15CF20E100727135 /* DbUrl.cpp */; };
+ 36A95DAD1624896C00727135 /* GUIDialogMediaFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A95DAB1624896C00727135 /* GUIDialogMediaFilter.cpp */; };
4D5D2E1E1301758F006ABC13 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D5D2E1D1301758F006ABC13 /* CFNetwork.framework */; };
7C0A7EDE13A5DC2800AFC2BD /* AppParamParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C0A7EDC13A5DC2800AFC2BD /* AppParamParser.cpp */; };
7C0A7F9D13A9E70800AFC2BD /* GUIWindowDebugInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C0A7F9B13A9E70800AFC2BD /* GUIWindowDebugInfo.cpp */; };
@@ -1035,6 +1036,8 @@
36A9467A15CF20BD00727135 /* VideoDbUrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VideoDbUrl.h; sourceTree = "<group>"; };
36A9467C15CF20E100727135 /* DbUrl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DbUrl.cpp; sourceTree = "<group>"; };
36A9467D15CF20E100727135 /* DbUrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DbUrl.h; sourceTree = "<group>"; };
+ 36A95DAB1624896C00727135 /* GUIDialogMediaFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogMediaFilter.cpp; sourceTree = "<group>"; };
+ 36A95DAC1624896C00727135 /* GUIDialogMediaFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogMediaFilter.h; sourceTree = "<group>"; };
4D5D2E1D1301758F006ABC13 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
7C0A7EDC13A5DC2800AFC2BD /* AppParamParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AppParamParser.cpp; sourceTree = "<group>"; };
7C0A7EDD13A5DC2800AFC2BD /* AppParamParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppParamParser.h; sourceTree = "<group>"; };
@@ -4962,6 +4965,8 @@
F56C8357131F42E8000AD0F6 /* GUIDialogKaiToast.h */,
DF830C9315BB20FC00602BE6 /* GUIDialogKeyboardGeneric.cpp */,
DF830C9415BB20FC00602BE6 /* GUIDialogKeyboardGeneric.h */,
+ 36A95DAB1624896C00727135 /* GUIDialogMediaFilter.cpp */,
+ 36A95DAC1624896C00727135 /* GUIDialogMediaFilter.h */,
F56C835A131F42E8000AD0F6 /* GUIDialogMediaSource.cpp */,
F56C835B131F42E8000AD0F6 /* GUIDialogMediaSource.h */,
F56C835C131F42E8000AD0F6 /* GUIDialogMuteBug.cpp */,
@@ -7603,6 +7608,7 @@
7C4458C8161E206100A905F6 /* Screenshot.cpp in Sources */,
1D638120161E20F2003603ED /* PeripheralImon.cpp in Sources */,
DF24EADE1621E67200034265 /* DVDDemuxBXA.cpp in Sources */,
+ 36A95DAD1624896C00727135 /* GUIDialogMediaFilter.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
6 XBMC.xcodeproj/project.pbxproj
@@ -183,6 +183,7 @@
36A9466715CF1FD200727135 /* MusicDbUrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9466515CF1FD200727135 /* MusicDbUrl.cpp */; };
36A9466A15CF1FED00727135 /* UrlOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9466815CF1FED00727135 /* UrlOptions.cpp */; };
36A9466D15CF201F00727135 /* VideoDbUrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9466B15CF201F00727135 /* VideoDbUrl.cpp */; };
+ 36A95DA51624894400727135 /* GUIDialogMediaFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A95DA31624894400727135 /* GUIDialogMediaFilter.cpp */; };
3802709A13D5A653009493DD /* SystemClock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3802709813D5A653009493DD /* SystemClock.cpp */; };
384718D81325BA04000486D6 /* XBDateTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 384718D61325BA04000486D6 /* XBDateTime.cpp */; };
38F4E57013CCCB3B00664821 /* Implementation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 38F4E56C13CCCB3B00664821 /* Implementation.cpp */; };
@@ -1361,6 +1362,8 @@
36A9466915CF1FED00727135 /* UrlOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UrlOptions.h; sourceTree = "<group>"; };
36A9466B15CF201F00727135 /* VideoDbUrl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VideoDbUrl.cpp; sourceTree = "<group>"; };
36A9466C15CF201F00727135 /* VideoDbUrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VideoDbUrl.h; sourceTree = "<group>"; };
+ 36A95DA31624894400727135 /* GUIDialogMediaFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogMediaFilter.cpp; sourceTree = "<group>"; };
+ 36A95DA41624894400727135 /* GUIDialogMediaFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogMediaFilter.h; sourceTree = "<group>"; };
3802709713D5A62D009493DD /* ThreadLocal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadLocal.h; sourceTree = "<group>"; };
3802709813D5A653009493DD /* SystemClock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SystemClock.cpp; sourceTree = "<group>"; };
3802709913D5A653009493DD /* SystemClock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SystemClock.h; sourceTree = "<group>"; };
@@ -3865,6 +3868,8 @@
E38A06CD0D95AA5500FF8227 /* GUIDialogKaiToast.h */,
DF830D0A15BB260C00602BE6 /* GUIDialogKeyboardGeneric.cpp */,
DF830D0B15BB260C00602BE6 /* GUIDialogKeyboardGeneric.h */,
+ 36A95DA31624894400727135 /* GUIDialogMediaFilter.cpp */,
+ 36A95DA41624894400727135 /* GUIDialogMediaFilter.h */,
E38E17B80D25F9FA00618676 /* GUIDialogMediaSource.cpp */,
E38E17B90D25F9FA00618676 /* GUIDialogMediaSource.h */,
E38E17BE0D25F9FA00618676 /* GUIDialogMuteBug.cpp */,
@@ -7636,6 +7641,7 @@
7C4458BD161E203800A905F6 /* Screenshot.cpp in Sources */,
1D638128161E211E003603ED /* PeripheralImon.cpp in Sources */,
AE89ACA61621DAB800E17DBC /* DVDDemuxBXA.cpp in Sources */,
+ 36A95DA51624894400727135 /* GUIDialogMediaFilter.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
184 addons/skin.confluence/720p/DialogMediaFilter.xml
@@ -0,0 +1,184 @@
+<window id="151">
+ <defaultcontrol always="true">5</defaultcontrol>
+ <coordinates>
+ <system>1</system>
+ <posx>240</posx>
+ <posy>100</posy>
+ </coordinates>
+ <include>dialogeffect</include>
+ <controls>
+ <control type="image">
+ <description>background image</description>
+ <posx>0</posx>
+ <posy>0</posy>
+ <width>800</width>
+ <height>500</height>
+ <texture border="40">DialogBack.png</texture>
+ </control>
+ <control type="image">
+ <description>Dialog Header image</description>
+ <posx>40</posx>
+ <posy>16</posy>
+ <width>720</width>
+ <height>40</height>
+ <texture>dialogheader.png</texture>
+ </control>
+ <control type="label" id="2">
+ <description>header label</description>
+ <posx>40</posx>
+ <posy>20</posy>
+ <width>720</width>
+ <height>30</height>
+ <font>font13_title</font>
+ <label>587</label>
+ <align>center</align>
+ <aligny>center</aligny>
+ <textcolor>selected</textcolor>
+ <shadowcolor>black</shadowcolor>
+ </control>
+ <control type="button">
+ <description>Close Window button</description>
+ <posx>710</posx>
+ <posy>15</posy>
+ <width>64</width>
+ <height>32</height>
+ <label>-</label>
+ <font>-</font>
+ <onclick>PreviousMenu</onclick>
+ <texturefocus>DialogCloseButton-focus.png</texturefocus>
+ <texturenofocus>DialogCloseButton.png</texturenofocus>
+ <onleft>10</onleft>
+ <onright>10</onright>
+ <onup>10</onup>
+ <ondown>10</ondown>
+ <visible>system.getbool(input.enablemouse)</visible>
+ </control>
+
+ <control type="grouplist" id="5">
+ <description>control area</description>
+ <posx>30</posx>
+ <posy>70</posy>
+ <width>720</width>
+ <height>350</height>
+ <itemgap>4</itemgap>
+ <pagecontrol>6</pagecontrol>
+ <onup>9001</onup>
+ <ondown>9001</ondown>
+ <onleft>9001</onleft>
+ <onright>6</onright>
+ </control>
+ <control type="scrollbar" id="6">
+ <posx>755</posx>
+ <posy>70</posy>
+ <width>25</width>
+ <height>350</height>
+ <texturesliderbackground border="0,14,0,14">ScrollBarV.png</texturesliderbackground>
+ <texturesliderbar border="2,16,2,16">ScrollBarV_bar.png</texturesliderbar>
+ <texturesliderbarfocus border="2,16,2,16">ScrollBarV_bar_focus.png</texturesliderbarfocus>
+ <textureslidernib>ScrollBarNib.png</textureslidernib>
+ <textureslidernibfocus>ScrollBarNib.png</textureslidernibfocus>
+ <onleft>5</onleft>
+ <onright>9001</onright>
+ <showonepage>false</showonepage>
+ <orientation>vertical</orientation>
+ </control>
+
+ <control type="button" id="7">
+ <description>Default Button</description>
+ <posx>0</posx>
+ <posy>0</posy>
+ <height>40</height>
+ <font>font13</font>
+ <textcolor>grey2</textcolor>
+ <focusedcolor>white</focusedcolor>
+ <texturenofocus border="5">button-nofocus.png</texturenofocus>
+ <texturefocus border="5">button-focus2.png</texturefocus>
+ </control>
+ <control type="radiobutton" id="8">
+ <description>Default RadioButton</description>
+ <posx>0</posx>
+ <posy>0</posy>
+ <height>40</height>
+ <font>font13</font>
+ <textcolor>grey2</textcolor>
+ <focusedcolor>white</focusedcolor>
+ <texturenofocus border="5">button-nofocus.png</texturenofocus>
+ <texturefocus border="5">button-focus2.png</texturefocus>
+ </control>
+ <control type="spincontrolex" id="9">
+ <description>Default SpinControlex</description>
+ <posx>0</posx>
+ <posy>0</posy>
+ <height>40</height>
+ <font>font13</font>
+ <textcolor>grey2</textcolor>
+ <focusedcolor>white</focusedcolor>
+ <texturenofocus border="5">button-nofocus.png</texturenofocus>
+ <texturefocus border="5">button-focus2.png</texturefocus>
+ <aligny>center</aligny>
+ <reverse>yes</reverse>
+ </control>
+ <control type="sliderex" id="10">
+ <description>Default Slider</description>
+ <posx>0</posx>
+ <posy>0</posy>
+ <height>40</height>
+ <font>font13</font>
+ <textcolor>grey2</textcolor>
+ <focusedcolor>white</focusedcolor>
+ <texturenofocus border="5">button-nofocus.png</texturenofocus>
+ <texturefocus border="5">button-focus2.png</texturefocus>
+ <aligny>center</aligny>
+ </control>
+ <control type="edit" id="12">
+ <description>Default Edit</description>
+ <posx>0</posx>
+ <posy>0</posy>
+ <height>40</height>
+ <font>font13</font>
+ <textcolor>grey2</textcolor>
+ <focusedcolor>white</focusedcolor>
+ <texturenofocus border="5">button-nofocus.png</texturenofocus>
+ <texturefocus border="5">button-focus2.png</texturefocus>
+ </control>
+
+ <control type="group" id="9001">
+ <posx>190</posx>
+ <posy>435</posy>
+ <control type="button" id="28">
+ <description>Ok Button</description>
+ <posx>0</posx>
+ <posy>0</posy>
+ <width>200</width>
+ <height>40</height>
+ <align>center</align>
+ <aligny>center</aligny>
+ <texturenofocus border="5">button-nofocus.png</texturenofocus>
+ <texturefocus border="5">button-focus.png</texturefocus>
+ <label>186</label>
+ <font>font12_title</font>
+ <onup>5</onup>
+ <onleft>27</onleft>
+ <onright>27</onright>
+ <ondown>5</ondown>
+ </control>
+ <control type="button" id="27">
+ <description>Clear Button</description>
+ <posx>210</posx>
+ <posy>0</posy>
+ <width>200</width>
+ <height>40</height>
+ <align>center</align>
+ <aligny>center</aligny>
+ <texturenofocus border="5">button-nofocus.png</texturenofocus>
+ <texturefocus border="5">button-focus.png</texturefocus>
+ <label>192</label>
+ <font>font12_title</font>
+ <onup>5</onup>
+ <onleft>28</onleft>
+ <onright>28</onright>
+ <ondown>5</ondown>
+ </control>
+ </control>
+ </controls>
+</window>
View
9 addons/skin.confluence/720p/MyMusicNav.xml
@@ -101,11 +101,20 @@
<include>ButtonCommonValues</include>
</control>
<control type="edit" id="19">
+ <visible>Container.CanFilter + !Container.CanFilterAdvanced</visible>
<description>Filter</description>
<textwidth>230</textwidth>
<include>ButtonCommonValues</include>
<label>587</label>
</control>
+ <control type="radiobutton" id="20">
+ <visible>Container.CanFilterAdvanced</visible>
+ <description>Filter</description>
+ <include>ButtonCommonValues</include>
+ <label>587</label>
+ <selected>Container.Filtered</selected>
+ <onclick>Filter</onclick>
+ </control>
<control type="radiobutton" id="100">
<description>Show Info Toggle</description>
<textwidth>170</textwidth>
View
9 addons/skin.confluence/720p/MyMusicSongs.xml
@@ -98,11 +98,20 @@
<enable>Library.HasContent(Music)</enable>
</control>
<control type="edit" id="19">
+ <visible>Container.CanFilter + !Container.CanFilterAdvanced</visible>
<description>Filter</description>
<textwidth>230</textwidth>
<include>ButtonCommonValues</include>
<label>587</label>
</control>
+ <control type="radiobutton" id="20">
+ <visible>Container.CanFilterAdvanced</visible>
+ <description>Filter</description>
+ <include>ButtonCommonValues</include>
+ <label>587</label>
+ <selected>Container.Filtered</selected>
+ <onclick>Filter</onclick>
+ </control>
<include>CommonNowPlaying_Controls</include>
</control>
</control>
View
8 addons/skin.confluence/720p/MyPics.xml
@@ -103,11 +103,19 @@
<usealttexture>Container.SortDirection(Ascending)</usealttexture>
</control>
<control type="edit" id="19">
+ <visible>Container.CanFilter + !Container.CanFilterAdvanced</visible>
<description>Filter</description>
<textwidth>230</textwidth>
<include>ButtonCommonValues</include>
<label>587</label>
</control>
+ <control type="radiobutton" id="20">
+ <visible>Container.CanFilterAdvanced</visible>
+ <description>Filter</description>
+ <include>ButtonCommonValues</include>
+ <label>587</label>
+ <onclick>Filter</onclick>
+ </control>
<control type="label" id="201">
<width>250</width>
<height>35</height>
View
8 addons/skin.confluence/720p/MyPrograms.xml
@@ -89,11 +89,19 @@
<usealttexture>Container.SortDirection(Ascending)</usealttexture>
</control>
<control type="edit" id="19">
+ <visible>Container.CanFilter + !Container.CanFilterAdvanced</visible>
<description>Filter</description>
<textwidth>230</textwidth>
<include>ButtonCommonValues</include>
<label>587</label>
</control>
+ <control type="radiobutton" id="20">
+ <visible>Container.CanFilterAdvanced</visible>
+ <description>Filter</description>
+ <include>ButtonCommonValues</include>
+ <label>587</label>
+ <onclick>Filter</onclick>
+ </control>
<include>CommonNowPlaying_Controls</include>
</control>
</control>
View
9 addons/skin.confluence/720p/MyVideoNav.xml
@@ -98,11 +98,20 @@
<usealttexture>Container.SortDirection(Ascending)</usealttexture>
</control>
<control type="edit" id="19">
+ <visible>Container.CanFilter + !Container.CanFilterAdvanced</visible>
<description>Filter</description>
<textwidth>230</textwidth>
<include>ButtonCommonValues</include>
<label>587</label>
</control>
+ <control type="radiobutton" id="20">
+ <visible>Container.CanFilterAdvanced</visible>
+ <description>Filter</description>
+ <include>ButtonCommonValues</include>
+ <label>587</label>
+ <selected>Container.Filtered</selected>
+ <onclick>Filter</onclick>
+ </control>
<control type="radiobutton" id="99">
<description>Show Info Toggle</description>
<textwidth>170</textwidth>
View
2  addons/skin.confluence/720p/includes.xml
@@ -332,7 +332,7 @@
<scroll>false</scroll>
<align>right</align>
<aligny>center</aligny>
- <label>$INFO[Window.Property(filter),$LOCALIZE[587] ([COLOR=blue],[/COLOR]) - ]$INFO[Container.NumItems,([COLOR=blue],[/COLOR]) $LOCALIZE[31025]]$INFO[Container.CurrentPage, - $LOCALIZE[31024] ([COLOR=blue]]$INFO[Container.NumPages,/,[/COLOR])]</label>
+ <label>$INFO[Container.NumItems,([COLOR=blue],[/COLOR]) $LOCALIZE[31025]]$INFO[Container.CurrentPage, - $LOCALIZE[31024] ([COLOR=blue]]$INFO[Container.NumPages,/,[/COLOR])]</label>
<include>Window_OpenClose_Animation</include>
</control>
<control type="label">
View
24 language/English/strings.po
@@ -3201,6 +3201,12 @@ msgctxt "#1273"
msgid "AirPlay"
msgstr ""
+#empty string id 1274
+
+msgctxt "#1275"
+msgid "Filter %s"
+msgstr ""
+
#empty strings from id 1274 to 1299
msgctxt "#1300"
@@ -9400,7 +9406,23 @@ msgctxt "#21465"
msgid "Above video"
msgstr ""
-#empty strings from id 21466 to 21799
+msgctxt "#21466"
+msgid "between"
+msgstr ""
+
+msgctxt "#21467"
+msgid "%.1f to %.1f"
+msgstr ""
+
+msgctxt "#21468"
+msgid "%d to %d"
+msgstr ""
+
+msgctxt "#21469"
+msgid "%s to %s"
+msgstr ""
+
+#empty strings from id 21470 to 21799
msgctxt "#21800"
msgid "File name"
View
2  project/VS2010Express/XBMC.vcxproj
@@ -419,6 +419,7 @@
<ClCompile Include="..\..\xbmc\dialogs\GUIDialogGamepad.cpp" />
<ClCompile Include="..\..\xbmc\dialogs\GUIDialogKaiToast.cpp" />
<ClCompile Include="..\..\xbmc\dialogs\GUIDialogKeyboardGeneric.cpp" />
+ <ClCompile Include="..\..\xbmc\dialogs\GUIDialogMediaFilter.cpp" />
<ClCompile Include="..\..\xbmc\dialogs\GUIDialogMediaSource.cpp" />
<ClCompile Include="..\..\xbmc\dialogs\GUIDialogMuteBug.cpp" />
<ClCompile Include="..\..\xbmc\dialogs\GUIDialogNumeric.cpp" />
@@ -1015,6 +1016,7 @@
<ClInclude Include="..\..\xbmc\cores\paplayer\PCMCodec.h" />
<ClInclude Include="..\..\xbmc\dialogs\GUIDialogKeyboardGeneric.h" />
<ClInclude Include="..\..\xbmc\DbUrl.h" />
+ <ClInclude Include="..\..\xbmc\dialogs\GUIDialogMediaFilter.h" />
<ClInclude Include="..\..\xbmc\filesystem\ImageFile.h" />
<ClInclude Include="..\..\xbmc\filesystem\VideoDatabaseDirectory\DirectoryNodeTags.h" />
<ClInclude Include="..\..\xbmc\filesystem\windows\WINFileSMB.h" />
View
6 project/VS2010Express/XBMC.vcxproj.filters
@@ -2933,6 +2933,9 @@
<ClCompile Include="..\..\xbmc\cores\dvdplayer\DVDDemuxers\DVDDemuxBXA.cpp">
<Filter>cores\dvdplayer\DVDDemuxers</Filter>
</ClCompile>
+ <ClCompile Include="..\..\xbmc\dialogs\GUIDialogMediaFilter.cpp">
+ <Filter>dialogs</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\xbmc\win32\pch.h">
@@ -5734,6 +5737,9 @@
<ClInclude Include="..\..\xbmc\utils\Screenshot.h">
<Filter>utils</Filter>
</ClInclude>
+ <ClInclude Include="..\..\xbmc\dialogs\GUIDialogMediaFilter.h">
+ <Filter>dialogs</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\xbmc\win32\XBMC_PC.rc">
View
4 xbmc/Application.cpp
@@ -286,6 +286,7 @@
#include "guilib/GUIControlFactory.h"
#include "dialogs/GUIDialogCache.h"
#include "dialogs/GUIDialogPlayEject.h"
+#include "dialogs/GUIDialogMediaFilter.h"
#include "utils/XMLUtils.h"
#include "addons/AddonInstaller.h"
@@ -1298,6 +1299,8 @@ bool CApplication::Initialize()
g_windowManager.Add(new CGUIDialogPeripheralManager);
g_windowManager.Add(new CGUIDialogPeripheralSettings);
+
+ g_windowManager.Add(new CGUIDialogMediaFilter); // window id = 151
g_windowManager.Add(new CGUIWindowMusicPlayList); // window id = 500
g_windowManager.Add(new CGUIWindowMusicSongs); // window id = 501
@@ -3475,6 +3478,7 @@ bool CApplication::Cleanup()
g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
+ g_windowManager.Delete(WINDOW_DIALOG_MEDIA_FILTER);
/* Delete PVR related windows and dialogs */
g_windowManager.Delete(WINDOW_PVR);
View
1  xbmc/DbUrl.h
@@ -39,6 +39,7 @@ class CDbUrl : public CUrlOptions
const std::string& GetType() const { return m_type; }
void AppendPath(const std::string &subPath);
+ virtual void AddOption(const std::string &key, const char *value) { CUrlOptions::AddOption(key, value); updateOptions(); }
virtual void AddOption(const std::string &key, const std::string &value) { CUrlOptions::AddOption(key, value); updateOptions(); }
virtual void AddOption(const std::string &key, int value) { CUrlOptions::AddOption(key, value); updateOptions(); }
virtual void AddOption(const std::string &key, float value) { CUrlOptions::AddOption(key, value); updateOptions(); }
View
23 xbmc/GUIInfoManager.cpp
@@ -431,7 +431,10 @@ const infomap container_bools[] ={{ "onnext", CONTAINER_MOVE_NEXT },
{ "currentpage", CONTAINER_CURRENT_PAGE },
{ "scrolling", CONTAINER_SCROLLING },
{ "hasnext", CONTAINER_HAS_NEXT },
- { "hasprevious", CONTAINER_HAS_PREVIOUS }};
+ { "hasprevious", CONTAINER_HAS_PREVIOUS },
+ { "canfilter", CONTAINER_CAN_FILTER },
+ { "canfilteradvanced",CONTAINER_CAN_FILTERADVANCED },
+ { "filtered", CONTAINER_FILTERED }};
const infomap container_ints[] = {{ "row", CONTAINER_ROW },
{ "column", CONTAINER_COLUMN },
@@ -2204,6 +2207,24 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI
bReturn = control->GetCondition(condition, 0);
}
}
+ else if (condition == CONTAINER_CAN_FILTER)
+ {
+ CGUIWindow *window = GetWindowWithCondition(contextWindow, WINDOW_CONDITION_IS_MEDIA_WINDOW);
+ if (window)
+ bReturn = !((CGUIMediaWindow*)window)->CanFilterAdvanced();
+ }
+ else if (condition == CONTAINER_CAN_FILTERADVANCED)
+ {
+ CGUIWindow *window = GetWindowWithCondition(contextWindow, WINDOW_CONDITION_IS_MEDIA_WINDOW);
+ if (window)
+ bReturn = ((CGUIMediaWindow*)window)->CanFilterAdvanced();
+ }
+ else if (condition == CONTAINER_FILTERED)
+ {
+ CGUIWindow *window = GetWindowWithCondition(contextWindow, WINDOW_CONDITION_IS_MEDIA_WINDOW);
+ if (window)
+ bReturn = ((CGUIMediaWindow*)window)->IsFiltered();
+ }
else if (condition == VIDEOPLAYER_HAS_INFO)
bReturn = ((m_currentFile->HasVideoInfoTag() && !m_currentFile->GetVideoInfoTag()->IsEmpty()) ||
(m_currentFile->HasPVRChannelInfoTag() && !m_currentFile->GetPVRChannelInfoTag()->IsEmpty()));
View
4 xbmc/GUIInfoManager.h
@@ -289,6 +289,10 @@ namespace INFO
#define LASTFM_CANLOVE 331
#define LASTFM_CANBAN 332
+#define CONTAINER_CAN_FILTER 342
+#define CONTAINER_CAN_FILTERADVANCED 343
+#define CONTAINER_FILTERED 344
+
#define CONTAINER_SCROLL_PREVIOUS 345 // NOTE: These 5 must be kept in this consecutive order
#define CONTAINER_MOVE_PREVIOUS 346
#define CONTAINER_STATIC 347
View
5 xbmc/dbwrappers/Database.cpp
@@ -203,6 +203,11 @@ CStdString CDatabase::GetSingleValue(const CStdString &strTable, const CStdStrin
return GetSingleValue(query, m_pDS);
}
+CStdString CDatabase::GetSingleValue(const CStdString &query)
+{
+ return GetSingleValue(query, m_pDS);
+}
+
bool CDatabase::DeleteValues(const CStdString &strTable, const CStdString &strWhereClause /* = CStdString() */)
{
bool bReturn = true;
View
3  xbmc/dbwrappers/Database.h
@@ -83,6 +83,7 @@ class CDatabase
* @return The requested value or an empty string if it wasn't found.
*/
CStdString GetSingleValue(const CStdString &strTable, const CStdString &strColumn, const CStdString &strWhereClause = CStdString(), const CStdString &strOrderBy = CStdString());
+ CStdString GetSingleValue(const CStdString &query);
/*! \brief Get a single value from a query on a dataset.
\param query the query in question.
@@ -134,7 +135,7 @@ class CDatabase
*/
bool CommitInsertQueries();
- virtual bool GetFilter(const CDbUrl &dbUrl, Filter &filter) { return true; }
+ virtual bool GetFilter(CDbUrl &dbUrl, Filter &filter) { return true; }
virtual bool BuildSQL(const CStdString &strBaseDir, const CStdString &strQuery, Filter &filter, CStdString &strSQL, CDbUrl &dbUrl);
protected:
View
913 xbmc/dialogs/GUIDialogMediaFilter.cpp
@@ -0,0 +1,913 @@
+/*
+ * Copyright (C) 2012 Team XBMC
+ * http://www.xbmc.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, or (at your option)
+ * any later version.
+ *
+ * This Program 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "GUIDialogMediaFilter.h"
+#include "FileItem.h"
+#include "GUIUserMessages.h"
+#include "XBDateTime.h"
+#include "dialogs/GUIDialogSelect.h"
+#include "guilib/GUIWindowManager.h"
+#include "guilib/LocalizeStrings.h"
+#include "music/MusicDatabase.h"
+#include "playlists/SmartPlayList.h"
+#include "utils/MathUtils.h"
+#include "video/VideoDatabase.h"
+
+// list of controls
+#define CONTROL_HEADING 2
+// list of controls from CGUIDialogSettings
+#define CONTROL_GROUP_LIST 5
+#define CONTROL_DEFAULT_BUTTON 7
+#define CONTROL_DEFAULT_RADIOBUTTON 8
+#define CONTROL_DEFAULT_SPIN 9
+#define CONTROL_DEFAULT_SLIDER 10
+
+#define CONTROL_CLEAR_BUTTON 27
+#define CONTROL_OKAY_BUTTON 28
+#define CONTROL_CANCEL_BUTTON 29
+#define CONTROL_START 30
+
+#define CHECK_ALL -1
+#define CHECK_NO 0
+#define CHECK_YES 1
+#define CHECK_LABEL_ALL 593
+#define CHECK_LABEL_NO 106
+#define CHECK_LABEL_YES 107
+
+using namespace std;
+
+static const CGUIDialogMediaFilter::Filter filterList[] = {
+ { "movies", FieldTitle, 556, SettingInfo::EDIT, CSmartPlaylistRule::OPERATOR_CONTAINS },
+ { "movies", FieldRating, 563, SettingInfo::RANGE, CSmartPlaylistRule::OPERATOR_BETWEEN },
+ //{ "movies", FieldTime, 180, SettingInfo::TODO, CSmartPlaylistRule::TODO },
+ { "movies", FieldInProgress, 575, SettingInfo::CHECK, CSmartPlaylistRule::OPERATOR_FALSE },
+ { "movies", FieldYear, 562, SettingInfo::RANGE, CSmartPlaylistRule::OPERATOR_BETWEEN },
+ { "movies", FieldTag, 20459, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ { "movies", FieldGenre, 515, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ { "movies", FieldActor, 20337, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ { "movies", FieldDirector, 20339, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ { "movies", FieldStudio, 572, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ //{ "movies", FieldLastPlayed, 568, SettingInfo::TODO, CSmartPlaylistRule::TODO },
+ //{ "movies", FieldDateAdded, 570, SettingInfo::TODO, CSmartPlaylistRule::TODO },
+
+ { "tvshows", FieldTitle, 556, SettingInfo::EDIT, CSmartPlaylistRule::OPERATOR_CONTAINS },
+ //{ "tvshows", FieldTvShowStatus, 126, SettingInfo::TODO, CSmartPlaylistRule::TODO },
+ { "tvshows", FieldRating, 563, SettingInfo::RANGE, CSmartPlaylistRule::OPERATOR_BETWEEN },
+ { "tvshows", FieldInProgress, 575, SettingInfo::CHECK, CSmartPlaylistRule::OPERATOR_FALSE },
+ { "tvshows", FieldYear, 562, SettingInfo::RANGE, CSmartPlaylistRule::OPERATOR_BETWEEN },
+ { "tvshows", FieldGenre, 515, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ { "tvshows", FieldActor, 20337, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ { "tvshows", FieldDirector, 20339, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ { "tvshows", FieldStudio, 572, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ //{ "tvshows", FieldDateAdded, 570, SettingInfo::TODO, CSmartPlaylistRule::TODO },
+
+ { "episodes", FieldTitle, 556, SettingInfo::EDIT, CSmartPlaylistRule::OPERATOR_CONTAINS },
+ { "episodes", FieldRating, 563, SettingInfo::RANGE, CSmartPlaylistRule::OPERATOR_BETWEEN },
+ { "episodes", FieldAirDate, 20416, SettingInfo::RANGE, CSmartPlaylistRule::OPERATOR_BETWEEN },
+ { "episodes", FieldInProgress, 575, SettingInfo::CHECK, CSmartPlaylistRule::OPERATOR_FALSE },
+ { "episodes", FieldActor, 20337, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ { "episodes", FieldDirector, 20339, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ //{ "episodes", FieldLastPlayed, 568, SettingInfo::TODO, CSmartPlaylistRule::TODO },
+ //{ "episodes", FieldDateAdded, 570, SettingInfo::TODO, CSmartPlaylistRule::TODO },
+
+ { "musicvideos", FieldTitle, 556, SettingInfo::EDIT, CSmartPlaylistRule::OPERATOR_CONTAINS },
+ { "musicvideos", FieldArtist, 557, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ { "musicvideos", FieldAlbum, 558, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ //{ "musicvideos", FieldTime, 180, SettingInfo::TODO, CSmartPlaylistRule::TODO },
+ { "musicvideos", FieldYear, 562, SettingInfo::RANGE, CSmartPlaylistRule::OPERATOR_BETWEEN },
+ { "musicvideos", FieldGenre, 515, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ { "musicvideos", FieldDirector, 20339, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ { "musicvideos", FieldStudio, 572, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ //{ "musicvideos", FieldLastPlayed, 568, SettingInfo::TODO, CSmartPlaylistRule::TODO },
+ //{ "musicvideos", FieldDateAdded, 570, SettingInfo::TODO, CSmartPlaylistRule::TODO },
+
+ { "artists", FieldArtist, 557, SettingInfo::EDIT, CSmartPlaylistRule::OPERATOR_CONTAINS },
+ { "artists", FieldGenre, 515, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+
+ { "albums", FieldAlbum, 556, SettingInfo::EDIT, CSmartPlaylistRule::OPERATOR_CONTAINS },
+ { "albums", FieldArtist, 557, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ { "albums", FieldRating, 563, SettingInfo::RANGE, CSmartPlaylistRule::OPERATOR_BETWEEN },
+ { "albums", FieldAlbumType, 564, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ { "albums", FieldYear, 562, SettingInfo::RANGE, CSmartPlaylistRule::OPERATOR_BETWEEN },
+ { "albums", FieldGenre, 515, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ { "albums", FieldMusicLabel, 21899, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+
+ { "songs", FieldTitle, 556, SettingInfo::EDIT, CSmartPlaylistRule::OPERATOR_CONTAINS },
+ { "songs", FieldAlbum, 558, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ { "songs", FieldArtist, 557, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ { "songs", FieldTime, 180, SettingInfo::RANGE, CSmartPlaylistRule::OPERATOR_BETWEEN },
+ { "songs", FieldRating, 563, SettingInfo::RANGE, CSmartPlaylistRule::OPERATOR_BETWEEN },
+ { "songs", FieldYear, 562, SettingInfo::RANGE, CSmartPlaylistRule::OPERATOR_BETWEEN },
+ { "songs", FieldGenre, 515, SettingInfo::BUTTON, CSmartPlaylistRule::OPERATOR_EQUALS },
+ { "songs", FieldPlaycount, 567, SettingInfo::RANGE, CSmartPlaylistRule::OPERATOR_BETWEEN },
+ //{ "songs", FieldLastPlayed, 568, SettingInfo::TODO, CSmartPlaylistRule::TODO },
+ //{ "songs", FieldDateAdded, 570, SettingInfo::TODO, CSmartPlaylistRule::TODO },
+};
+
+#define NUM_FILTERS sizeof(filterList) / sizeof(CGUIDialogMediaFilter::Filter)
+
+CGUIDialogMediaFilter::CGUIDialogMediaFilter()
+ : CGUIDialogSettings(WINDOW_DIALOG_MEDIA_FILTER, "DialogMediaFilter.xml"),
+ m_dbUrl(NULL),
+ m_filter(NULL)
+{ }
+
+CGUIDialogMediaFilter::~CGUIDialogMediaFilter()
+{
+ Reset();
+}
+
+bool CGUIDialogMediaFilter::OnMessage(CGUIMessage& message)
+{
+ switch (message.GetMessage())
+ {
+ case GUI_MSG_CLICKED:
+ {
+ int control = message.GetSenderId();
+
+ if (control == CONTROL_CLEAR_BUTTON)
+ {
+ m_filter->Reset();
+ m_filter->SetType(m_mediaType);
+
+ for (map<uint32_t, Filter>::iterator filter = m_filters.begin(); filter != m_filters.end(); filter++)
+ {
+ filter->second.rule = NULL;
+
+ switch (filter->second.type)
+ {
+ case SettingInfo::STRING:
+ case SettingInfo::EDIT:
+ ((CStdString *)filter->second.data)->clear();
+ break;
+
+ case SettingInfo::CHECK:
+ *(int *)filter->second.data = CHECK_ALL;
+ break;
+
+ case SettingInfo::BUTTON:
+ ((CStdString *)filter->second.data)->clear();
+ SET_CONTROL_LABEL2(filter->second.controlIndex, *(CStdString *)filter->second.data);
+ break;
+
+ case SettingInfo::RANGE:
+ *(((float **)filter->second.data)[0]) = m_settings[filter->second.controlIndex - CONTROL_START].min;
+ *(((float **)filter->second.data)[1]) = m_settings[filter->second.controlIndex - CONTROL_START].max;
+ break;
+
+ default:
+ continue;
+ }
+
+ UpdateSetting(filter->first);
+ }
+
+ CGUIMessage message(GUI_MSG_NOTIFY_ALL, GetID(), 0, GUI_MSG_FILTER_ITEMS, 10); // 10 for advanced
+ g_windowManager.SendMessage(message);
+ return true;
+ }
+ break;
+ }
+
+ case GUI_MSG_WINDOW_DEINIT:
+ {
+ Reset();
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return CGUIDialogSettings::OnMessage(message);
+}
+
+void CGUIDialogMediaFilter::ShowAndEditMediaFilter(const std::string &path, CSmartPlaylist &filter)
+{
+ CGUIDialogMediaFilter *dialog = (CGUIDialogMediaFilter *)g_windowManager.GetWindow(WINDOW_DIALOG_MEDIA_FILTER);
+ if (dialog == NULL)
+ return;
+
+ // initialize and show the dialog
+ dialog->Initialize();
+ dialog->m_filter = &filter;
+ // must be called after setting the filter/smartplaylist
+ if (!dialog->SetPath(path))
+ return;
+
+ dialog->DoModal();
+}
+
+void CGUIDialogMediaFilter::OnWindowLoaded()
+{
+ CGUIDialogSettings::OnWindowLoaded();
+ // we don't need the cancel button so let's hide it
+ SET_CONTROL_HIDDEN(CONTROL_CANCEL_BUTTON);
+}
+
+void CGUIDialogMediaFilter::CreateSettings()
+{
+ if (m_filter == NULL)
+ return;
+
+ m_settings.clear();
+ int handledRules = 0;
+ for (unsigned int index = 0; index < NUM_FILTERS; index++)
+ {
+ if (filterList[index].mediaType != m_mediaType)
+ continue;
+
+ Filter filter = filterList[index];
+ filter.controlIndex = CONTROL_START + m_settings.size();
+
+ // check the smartplaylist if it contains a matching rule
+ for (vector<CSmartPlaylistRule>::iterator rule = m_filter->m_ruleCombination.m_rules.begin(); rule != m_filter->m_ruleCombination.m_rules.end(); rule++)
+ {
+ if (rule->m_field == filter.field)
+ {
+ filter.rule = &(*rule);
+ handledRules++;
+ break;
+ }
+ }
+
+ switch (filter.type)
+ {
+ case SettingInfo::STRING:
+ case SettingInfo::EDIT:
+ {
+ if (filter.rule != NULL && filter.rule->m_parameter.size() == 1)
+ filter.data = new CStdString(filter.rule->m_parameter.at(0));
+ else
+ filter.data = new CStdString();
+
+ if (filter.type == SettingInfo::STRING)
+ AddString(filter.field, filter.label, (CStdString *)filter.data);
+ else
+ AddEdit(filter.field, filter.label, (CStdString *)filter.data);
+ break;
+ }
+
+ case SettingInfo::CHECK:
+ {
+ if (filter.rule == NULL)
+ filter.data = new int(CHECK_ALL);
+ else
+ filter.data = new int(filter.rule->m_operator == CSmartPlaylistRule::OPERATOR_TRUE ? CHECK_YES : CHECK_NO);
+
+ vector<pair<int, int> > entries;
+ entries.push_back(pair<int, int>(CHECK_ALL, CHECK_LABEL_ALL));
+ entries.push_back(pair<int, int>(CHECK_NO, CHECK_LABEL_NO));
+ entries.push_back(pair<int, int>(CHECK_YES, CHECK_LABEL_YES));
+ AddSpin(filter.field, filter.label, (int *)filter.data, entries);
+ break;
+ }
+
+ case SettingInfo::BUTTON:
+ {
+ CStdString *values = new CStdString();
+ if (filter.rule != NULL && filter.rule->m_parameter.size() > 0)
+ *values = filter.rule->GetLocalizedParameter(m_mediaType);
+ filter.data = values;
+
+ AddButton(filter.field, filter.label);
+ break;
+ }
+
+ case SettingInfo::RANGE:
+ {
+ float min, interval, max;
+ RANGEFORMATFUNCTION format;
+ GetRange(filter, min, interval, max, format);
+
+ // don't create the filter if there's no real range
+ if (min == max)
+ break;
+
+ float *valueLower = new float();
+ float *valueUpper = new float();
+ if (filter.rule != NULL && filter.rule->m_parameter.size() == 2)
+ {
+ *valueLower = (float)strtod(filter.rule->m_parameter.at(0), NULL);
+ *valueUpper = (float)strtod(filter.rule->m_parameter.at(1), NULL);
+ }
+ else
+ {
+ *valueLower = min;
+ *valueUpper = max;
+
+ if (filter.rule != NULL)
+ {
+ DeleteRule(filter.field);
+ filter.rule = NULL;
+ }
+ }
+
+ AddRangeSlider(filter.field, filter.label, valueLower, valueUpper, min, interval, max, format);
+ filter.data = m_settings[filter.controlIndex - CONTROL_START].data;
+ break;
+ }
+
+ default:
+ filter.controlIndex = -1;
+ if (filter.rule != NULL)
+ handledRules--;
+ continue;
+ }
+
+ m_filters[filter.field] = filter;
+ }
+
+ // make sure that no change in capacity size is needed when adding new rules
+ // which would copy around the rules and our pointers in the Filter struct
+ // wouldn't work anymore
+ m_filter->m_ruleCombination.m_rules.reserve(m_filters.size() + (m_filter->m_ruleCombination.m_rules.size() - handledRules));
+}
+
+void CGUIDialogMediaFilter::SetupPage()
+{
+ CGUIDialogSettings::SetupPage();
+
+ // set the heading label based on the media type
+ uint32_t localizedMediaId = 0;
+ if (m_mediaType == "movies")
+ localizedMediaId = 20342;
+ else if (m_mediaType == "tvshows")
+ localizedMediaId = 20343;
+ else if (m_mediaType == "episodes")
+ localizedMediaId = 20360;
+ else if (m_mediaType == "musicvideos")
+ localizedMediaId = 20389;
+ else if (m_mediaType == "artists")
+ localizedMediaId = 133;
+ else if (m_mediaType == "albums")
+ localizedMediaId = 132;
+ else if (m_mediaType == "songs")
+ localizedMediaId = 134;
+
+ CStdString format;
+ format.Format(g_localizeStrings.Get(1275).c_str(), g_localizeStrings.Get(localizedMediaId).c_str());
+ SET_CONTROL_LABEL(CONTROL_HEADING, format);
+
+ // now we can finally set the label/values of the button settings (genre, actors etc)
+ for (map<uint32_t, Filter>::const_iterator filter = m_filters.begin(); filter != m_filters.end(); filter++)
+ {
+ if (filter->second.type == SettingInfo::BUTTON &&
+ filter->second.controlIndex >= 0 && filter->second.data != NULL)
+ SET_CONTROL_LABEL2(filter->second.controlIndex, *(CStdString *)filter->second.data);
+ }
+
+ UpdateControls();
+}
+
+void CGUIDialogMediaFilter::OnSettingChanged(SettingInfo &setting)
+{
+ map<uint32_t, Filter>::iterator it = m_filters.find(setting.id);
+ if (it == m_filters.end())
+ return;
+
+ bool changed = true;
+ bool remove = false;
+ Filter& filter = it->second;
+
+ switch (filter.type)
+ {
+ case SettingInfo::STRING:
+ case SettingInfo::EDIT:
+ {
+ CStdString *str = static_cast<CStdString*>(filter.data);
+ if (!str->empty())
+ {
+ if (filter.rule == NULL)
+ filter.rule = AddRule(filter.field, filter.ruleOperator);
+ filter.rule->m_parameter.clear();
+ filter.rule->m_parameter.push_back(*str);
+ }
+ else
+ remove = true;
+
+ break;
+ }
+
+ case SettingInfo::CHECK:
+ {
+ int choice = *(int *)setting.data;
+ if (choice > CHECK_ALL)
+ {
+ CSmartPlaylistRule::SEARCH_OPERATOR ruleOperator = choice == CHECK_YES ? CSmartPlaylistRule::OPERATOR_TRUE : CSmartPlaylistRule::OPERATOR_FALSE;
+ if (filter.rule == NULL)
+ filter.rule = AddRule(filter.field, ruleOperator);
+ else
+ filter.rule->m_operator = ruleOperator;
+ }
+ else
+ remove = true;
+
+ break;
+ }
+
+ case SettingInfo::BUTTON:
+ {
+ CFileItemList items;
+ OnBrowse(filter, items);
+
+ if (items.Size() > 0)
+ {
+ if (filter.rule == NULL)
+ filter.rule = AddRule(filter.field, filter.ruleOperator);
+
+ filter.rule->m_parameter.clear();
+ for (int index = 0; index < items.Size(); index++)
+ filter.rule->m_parameter.push_back(items[index]->GetLabel());
+
+ *(CStdString *)filter.data = filter.rule->GetLocalizedParameter(m_mediaType);
+ }
+ else
+ {
+ remove = true;
+ *(CStdString *)filter.data = "";
+ }
+
+ SET_CONTROL_LABEL2(filter.controlIndex, *(CStdString *)filter.data);
+ break;
+ }
+
+ case SettingInfo::RANGE:
+ {
+ SettingInfo &setting = m_settings[filter.controlIndex - CONTROL_START];
+ float *valueLower = ((float **)filter.data)[0];
+ float *valueUpper = ((float **)filter.data)[1];
+
+ if (*valueLower > setting.min || *valueUpper < setting.max)
+ {
+ if (filter.rule == NULL)
+ filter.rule = AddRule(filter.field, filter.ruleOperator);
+
+ filter.rule->m_parameter.clear();
+ if (filter.field == FieldAirDate)
+ {
+ CDateTime lower = (time_t)*valueLower;
+ CDateTime upper = (time_t)*valueUpper;
+ filter.rule->m_parameter.push_back(lower.GetAsDBDate());
+ filter.rule->m_parameter.push_back(upper.GetAsDBDate());
+ }
+ else
+ {
+ CStdString tmp;
+ tmp.Format("%.1f", *valueLower);
+ filter.rule->m_parameter.push_back(tmp);
+ tmp.clear();
+ tmp.Format("%.1f", *valueUpper);
+ filter.rule->m_parameter.push_back(tmp);
+ }
+ }
+ else
+ {
+ remove = true;
+ *((float **)filter.data)[0] = setting.min;
+ *((float **)filter.data)[1] = setting.max;
+ }
+ break;
+ }
+
+ default:
+ changed = false;
+ break;
+ }
+
+ // we need to remove the existing rule for the title
+ if (remove && filter.rule != NULL)
+ {
+ DeleteRule(filter.field);
+ filter.rule = NULL;
+ }
+
+ if (changed)
+ {
+ CGUIMessage message(GUI_MSG_NOTIFY_ALL, GetID(), 0, GUI_MSG_FILTER_ITEMS, 10); // 10 for advanced
+ g_windowManager.SendMessage(message);
+
+ UpdateControls();
+ }
+}
+
+void CGUIDialogMediaFilter::Reset()
+{
+ delete m_dbUrl;
+ m_dbUrl = NULL;
+
+ // delete all the setting's data
+ for (map<uint32_t, Filter>::iterator filter = m_filters.begin(); filter != m_filters.end(); filter++)
+ delete filter->second.data;
+
+ m_filters.clear();
+}
+
+bool CGUIDialogMediaFilter::SetPath(const std::string &path)
+{
+ if (path.empty() || m_filter == NULL)
+ return false;
+
+ delete m_dbUrl;
+ bool video = false;
+ if (path.find("videodb://") == 0)
+ {
+ m_dbUrl = new CVideoDbUrl();
+ video = true;
+ }
+ else if (path.find("musicdb://") == 0)
+ m_dbUrl = new CMusicDbUrl();
+ else
+ return false;
+
+ if (!m_dbUrl->FromString(path) ||
+ (video && m_dbUrl->GetType() != "movies" && m_dbUrl->GetType() != "tvshows" && m_dbUrl->GetType() != "episodes" && m_dbUrl->GetType() != "musicvideos") ||
+ (!video && m_dbUrl->GetType() != "artists" && m_dbUrl->GetType() != "albums" && m_dbUrl->GetType() != "songs"))
+ return false;
+
+ // remove "filter" option
+ if (m_dbUrl->HasOption("filter"))
+ m_dbUrl->AddOption("filter", "");
+
+ if (video)
+ m_mediaType = ((CVideoDbUrl*)m_dbUrl)->GetItemType();
+ else
+ m_mediaType = m_dbUrl->GetType();
+
+ m_filter->SetType(m_mediaType);
+ return true;
+}
+
+void CGUIDialogMediaFilter::UpdateControls()
+{
+ for (map<uint32_t, Filter>::iterator itFilter = m_filters.begin(); itFilter != m_filters.end(); itFilter++)
+ {
+ if (itFilter->second.type == SettingInfo::BUTTON)
+ {
+ CFileItemList items;
+ OnBrowse(itFilter->second, items, true);
+
+ int size = items.Size();
+ if (items.Size() == 1 && items[0]->HasProperty("total"))
+ size = (int)items[0]->GetProperty("total").asInteger();
+
+ CStdString label = g_localizeStrings.Get(itFilter->second.label);
+ if (size <= 1)
+ CONTROL_DISABLE(itFilter->second.controlIndex);
+ else
+ {
+ CONTROL_ENABLE(itFilter->second.controlIndex);
+ label.Format("%s [%d]", label, size);
+ }
+ SET_CONTROL_LABEL(itFilter->second.controlIndex, label);
+ }
+ }
+}
+
+void CGUIDialogMediaFilter::OnBrowse(const Filter &filter, CFileItemList &items, bool countOnly /* = false */)
+{
+ CFileItemList selectItems;
+ if (m_mediaType == "movies" || m_mediaType == "tvshows" || m_mediaType == "episodes" || m_mediaType == "musicvideos")
+ {
+ CVideoDatabase videodb;
+ if (!videodb.Open())
+ return;
+
+ CSmartPlaylist tmpFilter = *m_filter;
+ for (vector<CSmartPlaylistRule>::iterator rule = tmpFilter.m_ruleCombination.m_rules.begin(); rule != tmpFilter.m_ruleCombination.m_rules.end(); rule++)
+ {
+ if (rule->m_field == filter.field)
+ {
+ tmpFilter.m_ruleCombination.m_rules.erase(rule);
+ break;
+ }
+ }
+
+ std::set<CStdString> playlists;
+ CDatabase::Filter dbfilter;
+ dbfilter.where = tmpFilter.GetWhereClause(videodb, playlists);
+
+ VIDEODB_CONTENT_TYPE type = VIDEODB_CONTENT_MOVIES;
+ if (m_mediaType == "tvshows")
+ type = VIDEODB_CONTENT_TVSHOWS;
+ else if (m_mediaType == "episodes")
+ type = VIDEODB_CONTENT_EPISODES;
+ else if (m_mediaType == "musicvideos")
+ type = VIDEODB_CONTENT_MUSICVIDEOS;
+
+ if (filter.field == FieldGenre)
+ videodb.GetGenresNav(m_dbUrl->ToString(), selectItems, type, dbfilter, countOnly);
+ else if (filter.field == FieldActor || filter.field == FieldArtist)
+ videodb.GetActorsNav(m_dbUrl->ToString(), selectItems, type, dbfilter, countOnly);
+ else if (filter.field == FieldDirector)
+ videodb.GetDirectorsNav(m_dbUrl->ToString(), selectItems, type, dbfilter, countOnly);
+ else if (filter.field == FieldStudio)
+ videodb.GetStudiosNav(m_dbUrl->ToString(), selectItems, type, dbfilter, countOnly);
+ else if (filter.field == FieldAlbum)
+ videodb.GetMusicVideoAlbumsNav(m_dbUrl->ToString(), selectItems, -1, dbfilter, countOnly);
+ else if (filter.field == FieldTag)
+ videodb.GetTagsNav(m_dbUrl->ToString(), selectItems, type, dbfilter, countOnly);
+ }
+ else if (m_mediaType == "artists" || m_mediaType == "albums" || m_mediaType == "songs")
+ {
+ CMusicDatabase musicdb;
+ if (!musicdb.Open())
+ return;
+
+ CSmartPlaylist tmpFilter = *m_filter;
+ for (vector<CSmartPlaylistRule>::iterator rule = tmpFilter.m_ruleCombination.m_rules.begin(); rule != tmpFilter.m_ruleCombination.m_rules.end(); rule++)
+ {
+ if (rule->m_field == filter.field)
+ {
+ tmpFilter.m_ruleCombination.m_rules.erase(rule);
+ break;
+ }
+ }
+
+ std::set<CStdString> playlists;
+ CDatabase::Filter dbfilter;
+ dbfilter.where = tmpFilter.GetWhereClause(musicdb, playlists);
+
+ if (filter.field == FieldGenre)
+ musicdb.GetGenresNav(m_dbUrl->ToString(), selectItems, dbfilter, countOnly);
+ else if (filter.field == FieldArtist)
+ musicdb.GetArtistsNav(m_dbUrl->ToString(), selectItems, m_mediaType == "albums", -1, -1, -1, dbfilter, SortDescription(), countOnly);
+ else if (filter.field == FieldAlbum)
+ musicdb.GetAlbumsNav(m_dbUrl->ToString(), selectItems, -1, -1, dbfilter, SortDescription(), countOnly);
+ else if (filter.field == FieldAlbumType)
+ musicdb.GetAlbumTypesNav(m_dbUrl->ToString(), selectItems, dbfilter, countOnly);
+ else if (filter.field == FieldMusicLabel)
+ musicdb.GetMusicLabelsNav(m_dbUrl->ToString(), selectItems, dbfilter, countOnly);
+ }
+
+ if (selectItems.Size() <= 0)
+ return;
+
+ if (countOnly)
+ {
+ items.Copy(selectItems);
+ return;
+ }
+
+ // sort the items
+ selectItems.Sort(SORT_METHOD_LABEL, SortOrderAscending);
+
+ CGUIDialogSelect* pDialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT);
+ pDialog->Reset();
+ pDialog->SetItems(&selectItems);
+ CStdString strHeading;
+ strHeading.Format(g_localizeStrings.Get(13401), g_localizeStrings.Get(filter.label));
+ pDialog->SetHeading(strHeading);
+ pDialog->SetMultiSelection(true);
+
+ if (filter.rule != NULL && !filter.rule->m_parameter.empty())
+ pDialog->SetSelected(filter.rule->m_parameter);
+
+ pDialog->DoModal();
+ if (pDialog->IsConfirmed())
+ items.Copy(pDialog->GetSelectedItems());
+ else
+ items.Clear();
+ pDialog->Reset();
+}
+
+CSmartPlaylistRule* CGUIDialogMediaFilter::AddRule(Field field, CSmartPlaylistRule::SEARCH_OPERATOR ruleOperator /* = CSmartPlaylistRule::OPERATOR_CONTAINS */)
+{
+ CSmartPlaylistRule rule;
+ rule.m_field = field;
+ rule.m_operator = ruleOperator;
+
+ m_filter->m_ruleCombination.m_rules.push_back(rule);
+ return &m_filter->m_ruleCombination.m_rules.at(m_filter->m_ruleCombination.m_rules.size() - 1);
+}
+
+void CGUIDialogMediaFilter::DeleteRule(Field field)
+{
+ for (vector<CSmartPlaylistRule>::iterator rule = m_filter->m_ruleCombination.m_rules.begin(); rule != m_filter->m_ruleCombination.m_rules.end(); rule++)
+ {
+ if (rule->m_field == field)
+ {
+ m_filter->m_ruleCombination.m_rules.erase(rule);
+ break;
+ }
+ }
+}
+
+void CGUIDialogMediaFilter::GetRange(const Filter &filter, float &min, float &interval, float &max, RANGEFORMATFUNCTION &formatFunction)
+{
+ if (filter.field == FieldRating)
+ {
+ if (m_mediaType == "movies" || m_mediaType == "tvshows" || m_mediaType == "episodes")
+ {
+ min = 0.0f;
+ interval = 0.1f;
+ max = 10.0f;
+ formatFunction = RangeAsFloat;
+ }
+ else if (m_mediaType == "albums" || m_mediaType == "songs")
+ {
+ min = 0.0f;
+ interval = 1.0f;
+ max = 5.0f;
+ formatFunction = RangeAsInt;
+ }
+ }
+ else if (filter.field == FieldYear)
+ {
+ formatFunction = RangeAsInt;
+ min = 0.0f;
+ interval = 1.0f;
+ max = 0.0f;
+
+ if (m_mediaType == "movies" || m_mediaType == "tvshows" || m_mediaType == "musicvideos")
+ {
+ CStdString table;
+ CStdString year;
+ if (m_mediaType == "movies")
+ {
+ table = "movieview";
+ year.Format("c%02d", VIDEODB_ID_YEAR);
+ }
+ else if (m_mediaType == "tvshows")
+ {
+ table = "tvshowview";
+ year.Format("strftime(\"%%Y\", c%02d)", VIDEODB_ID_TV_PREMIERED);
+ }
+ else if (m_mediaType == "musicvideos")
+ {
+ table = "musicvideoview";
+ year.Format("c%02d", VIDEODB_ID_MUSICVIDEO_YEAR);
+ }
+
+ GetMinMax(table, year, min, max);
+ }
+ else if (m_mediaType == "albums" || m_mediaType == "songs")
+ {
+ CStdString table;
+ if (m_mediaType == "albums")
+ table = "albumview";
+ else if (m_mediaType == "songs")
+ table = "songview";
+
+ CDatabase::Filter filter;
+ filter.where = "iYear > 0";
+ GetMinMax(table, "iYear", min, max, filter);
+ }
+ }
+ else if (filter.field == FieldAirDate)
+ {
+ formatFunction = RangeAsDate;
+ min = 0.0f;
+ interval = 1.0f;
+ max = 0.0f;
+
+ if (m_mediaType == "episodes")
+ {
+ CStdString field; field.Format("CAST(strftime(\"%%s\", c%02d) AS INTEGER)", VIDEODB_ID_EPISODE_AIRED);
+
+ GetMinMax("episodeview", field, min, max);
+ interval = 60 * 60 * 24 * 7; // 1 week
+ }
+ }
+ else if (filter.field == FieldTime)
+ {
+ formatFunction = RangeAsTime;
+ min = 0.0f;
+ interval = 10.0f;
+ max = 0.0f;
+
+ if (m_mediaType == "songs")
+ GetMinMax("songview", "iDuration", min, max);
+ }
+ else if (filter.field == FieldPlaycount)
+ {
+ formatFunction = RangeAsInt;
+ min = 0.0f;
+ interval = 1.0f;
+ max = 0.0f;
+
+ if (m_mediaType == "songs")
+ GetMinMax("songview", "iTimesPlayed", min, max);
+ }
+}
+
+bool CGUIDialogMediaFilter::GetMinMax(const CStdString &table, const CStdString &field, float &min, float &max, const CDatabase::Filter &filter /* = CDatabase::Filter() */)
+{
+ if (table.empty() || field.empty())
+ return false;
+
+ CDatabase *db = NULL;
+ CDbUrl *dbUrl = NULL;
+ if (m_mediaType == "movies" || m_mediaType == "tvshows" || m_mediaType == "episodes" || m_mediaType == "musicvideos")
+ {
+ CVideoDatabase *videodb = new CVideoDatabase();
+ if (!videodb->Open())
+ {
+ delete videodb;
+ return false;
+ }
+
+ db = videodb;
+ dbUrl = new CVideoDbUrl();
+ }
+ else if (m_mediaType == "artists" || m_mediaType == "albums" || m_mediaType == "songs")
+ {
+ CMusicDatabase *musicdb = new CMusicDatabase();
+ if (!musicdb->Open())
+ {
+ delete musicdb;
+ return false;
+ }
+
+ db = musicdb;
+ dbUrl = new CMusicDbUrl();
+ }
+
+ if (db == NULL || !db->IsOpen() || dbUrl == NULL)
+ {
+ delete db;
+ delete dbUrl;
+ return false;
+ }
+
+ CDatabase::Filter extFilter = filter;
+ CStdString strSQLExtra;
+ if (!db->BuildSQL(m_dbUrl->ToString(), strSQLExtra, extFilter, strSQLExtra, *dbUrl))
+ {
+ delete db;
+ delete dbUrl;
+ return false;
+ }
+
+ CStdString strSQL = "SELECT %s FROM %s ";
+
+ min = (float)strtod(db->GetSingleValue(db->PrepareSQL(strSQL, CStdString("MIN(" + field + ")").c_str(), table.c_str()) + strSQLExtra).c_str(), NULL);
+ max = (float)strtod(db->GetSingleValue(db->PrepareSQL(strSQL, CStdString("MAX(" + field + ")").c_str(), table.c_str()) + strSQLExtra).c_str(), NULL);
+
+ db->Close();
+ delete db;
+ delete dbUrl;
+
+ return true;
+}
+
+CStdString CGUIDialogMediaFilter::RangeAsFloat(float valueLower, float valueUpper, float minimum)
+{
+ CStdString text;
+ if (valueLower != valueUpper)
+ text.Format(g_localizeStrings.Get(21467).c_str(), valueLower, valueUpper);
+ else
+ text.Format("%.1f", valueLower);
+ return text;
+}
+
+CStdString CGUIDialogMediaFilter::RangeAsInt(float valueLower, float valueUpper, float minimum)
+{
+ CStdString text;
+ if (valueLower != valueUpper)
+ text.Format(g_localizeStrings.Get(21468).c_str(), MathUtils::round_int((double)valueLower), MathUtils::round_int((double)valueUpper));
+ else
+ text.Format("%d", MathUtils::round_int((double)valueLower));
+ return text;
+}
+
+CStdString CGUIDialogMediaFilter::RangeAsDate(float valueLower, float valueUpper, float minimum)
+{
+ CDateTime from = (time_t)valueLower;
+ CDateTime to = (time_t)valueUpper;
+ CStdString text;
+ if (valueLower != valueUpper)
+ text.Format(g_localizeStrings.Get(21469).c_str(), from.GetAsLocalizedDate(), to.GetAsLocalizedDate());
+ else
+ text.Format("%s", from.GetAsLocalizedDate());
+ return text;
+}
+
+CStdString CGUIDialogMediaFilter::RangeAsTime(float valueLower, float valueUpper, float minimum)
+{
+ CDateTime from = (time_t)valueLower;
+ CDateTime to = (time_t)valueUpper;
+ CStdString text;
+ if (valueLower != valueUpper)
+ text.Format(g_localizeStrings.Get(21469).c_str(), from.GetAsLocalizedTime("mm:ss"), to.GetAsLocalizedTime("mm:ss"));
+ else
+ text.Format("%s", from.GetAsLocalizedTime("mm:ss"));
+ return text;
+}
View
82 xbmc/dialogs/GUIDialogMediaFilter.h
@@ -0,0 +1,82 @@
+#pragma once
+/*
+ * Copyright (C) 2012 Team XBMC
+ * http://www.xbmc.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, or (at your option)
+ * any later version.
+ *
+ * This Program 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <map>
+#include <string>
+
+#include "DbUrl.h"
+#include "dbwrappers/Database.h"
+#include "playlists/SmartPlayList.h"
+#include "settings/GUIDialogSettings.h"
+#include "utils/DatabaseUtils.h"
+#include "utils/StdString.h"
+
+class CFileItemList;
+
+class CGUIDialogMediaFilter : public CGUIDialogSettings
+{
+public:
+ CGUIDialogMediaFilter();
+ virtual ~CGUIDialogMediaFilter();
+
+ virtual bool OnMessage(CGUIMessage& message);
+
+ static void ShowAndEditMediaFilter(const std::string &path, CSmartPlaylist &filter);
+
+ typedef struct {
+ std::string mediaType;
+ Field field;
+ uint32_t label;
+ SettingInfo::SETTING_TYPE type;
+ CSmartPlaylistRule::SEARCH_OPERATOR ruleOperator;
+ void *data;
+ CSmartPlaylistRule *rule;
+ int controlIndex;
+ } Filter;
+
+protected:
+ virtual void OnWindowLoaded();
+
+ virtual void CreateSettings();
+ virtual void SetupPage();
+ virtual void OnSettingChanged(SettingInfo &setting);
+
+ void Reset();
+ bool SetPath(const std::string &path);
+ void UpdateControls();
+
+ void OnBrowse(const Filter &filter, CFileItemList &items, bool countOnly = false);
+ CSmartPlaylistRule* AddRule(Field field, CSmartPlaylistRule::SEARCH_OPERATOR ruleOperator = CSmartPlaylistRule::OPERATOR_CONTAINS);
+ void DeleteRule(Field field);
+ void GetRange(const Filter &filter, float &min, float &interval, float &max, RANGEFORMATFUNCTION &formatFunction);
+
+ bool GetMinMax(const CStdString &table, const CStdString &field, float &min, float &max, const CDatabase::Filter &filter = CDatabase::Filter());
+
+ static CStdString RangeAsFloat(float valueLower, float valueUpper, float minimum);
+ static CStdString RangeAsInt(float valueLower, float valueUpper, float minimum);
+ static CStdString RangeAsDate(float valueLower, float valueUpper, float minimum);
+ static CStdString RangeAsTime(float valueLower, float valueUpper, float minimum);
+
+ CDbUrl* m_dbUrl;
+ std::string m_mediaType;
+ CSmartPlaylist *m_filter;
+ std::map<uint32_t, Filter> m_filters;
+};
View
1  xbmc/dialogs/Makefile
@@ -9,6 +9,7 @@ SRCS=GUIDialogBoxBase.cpp \
GUIDialogGamepad.cpp \
GUIDialogKaiToast.cpp \
GUIDialogKeyboardGeneric.cpp \
+ GUIDialogMediaFilter.cpp \
GUIDialogMediaSource.cpp \
GUIDialogMuteBug.cpp \
GUIDialogNumeric.cpp \
View
97 xbmc/filesystem/SmartPlaylistDirectory.cpp
@@ -50,7 +50,7 @@ namespace XFILE
return GetDirectory(playlist, items);
}
- bool CSmartPlaylistDirectory::GetDirectory(const CSmartPlaylist &playlist, CFileItemList& items)
+ bool CSmartPlaylistDirectory::GetDirectory(const CSmartPlaylist &playlist, CFileItemList& items, const CStdString &strBaseDir /* = "" */, bool filter /* = false */)
{
bool success = false, success2 = false;
std::set<CStdString> playlists;
@@ -62,6 +62,8 @@ namespace XFILE
if (g_guiSettings.GetBool("filelists.ignorethewhensorting"))
sorting.sortAttributes = SortAttributeIgnoreArticle;
+ std::string option = !filter ? "xsp" : "filter";
+
if (playlist.GetType().Equals("movies") ||
playlist.GetType().Equals("tvshows") ||
playlist.GetType().Equals("episodes"))
@@ -71,32 +73,40 @@ namespace XFILE
{
MediaType mediaType = DatabaseUtils::MediaTypeFromString(playlist.GetType());
- CStdString strBaseDir;
- switch (mediaType)
+ CStdString baseDir = strBaseDir;
+ if (strBaseDir.empty())
{
- case MediaTypeTvShow:
- case MediaTypeEpisode:
- strBaseDir = "videodb://2/2/";
- break;
+ switch (mediaType)
+ {
+ case MediaTypeTvShow:
+ case MediaTypeEpisode:
+ baseDir = "videodb://2/2/";
+ break;
- case MediaTypeMovie:
- strBaseDir = "videodb://1/2/";
- break;
+ case MediaTypeMovie:
+ baseDir = "videodb://1/2/";
+ break;
- default:
- return false;
+ default:
+ return false;
+ }
}
CVideoDbUrl videoUrl;
- CStdString xsp;
- if (!videoUrl.FromString(strBaseDir) || !playlist.SaveAsJson(xsp, false))
+ if (!videoUrl.FromString(baseDir))
return false;
// store the smartplaylist as JSON in the URL as well
- videoUrl.AddOption("xsp", xsp);
+ CStdString xsp;
+ if (!playlist.IsEmpty())
+ {
+ if (!playlist.SaveAsJson(xsp, false))
+ return false;
+ }
+ videoUrl.AddOption(option, xsp);
- CDatabase::Filter filter;
- success = db.GetSortedVideos(mediaType, videoUrl.ToString(), sorting, items, filter, true);
+ CDatabase::Filter dbfilter;
+ success = db.GetSortedVideos(mediaType, videoUrl.ToString(), sorting, items, dbfilter, true);
db.Close();
}
}
@@ -106,15 +116,20 @@ namespace XFILE
if (db.Open())
{
CMusicDbUrl musicUrl;
- CStdString xsp;
- if (!musicUrl.FromString("musicdb://3/") || !playlist.SaveAsJson(xsp, false))
+ if (!musicUrl.FromString(!strBaseDir.empty() ? strBaseDir : "musicdb://3/"))
return false;
// store the smartplaylist as JSON in the URL as well
- musicUrl.AddOption("xsp", xsp);
+ CStdString xsp;
+ if (!playlist.IsEmpty())
+ {
+ if (!playlist.SaveAsJson(xsp, false))
+ return false;
+ }
+ musicUrl.AddOption(option, xsp);
- CDatabase::Filter filter;
- success = db.GetAlbumsByWhere(musicUrl.ToString(), filter, items, sorting);
+ CDatabase::Filter dbfilter;
+ success = db.GetAlbumsByWhere(musicUrl.ToString(), dbfilter, items, sorting);
items.SetContent("albums");
db.Close();
}
@@ -125,13 +140,17 @@ namespace XFILE
if (db.Open())
{
CMusicDbUrl musicUrl;
- CStdString xsp;
-
- if (!musicUrl.FromString("musicdb://2/") || !playlist.SaveAsJson(xsp, false))
+ if (!musicUrl.FromString("musicdb://2/"))
return false;
// store the smartplaylist as JSON in the URL as well
- musicUrl.AddOption("xsp", xsp);
+ CStdString xsp;
+ if (!playlist.IsEmpty())
+ {
+ if (!playlist.SaveAsJson(xsp, false))
+ return false;
+ }
+ musicUrl.AddOption(option, xsp);
CDatabase::Filter filter;
success = db.GetArtistsByWhere(musicUrl.ToString(), filter, items, sorting);
@@ -150,15 +169,20 @@ namespace XFILE
songPlaylist.SetType("songs");
CMusicDbUrl musicUrl;
- CStdString xsp;
- if (!musicUrl.FromString("musicdb://4/") || !songPlaylist.SaveAsJson(xsp, false))
+ if (!musicUrl.FromString(!strBaseDir.empty() ? strBaseDir : "musicdb://4/"))
return false;
// store the smartplaylist as JSON in the URL as well
- musicUrl.AddOption("xsp", xsp);
+ CStdString xsp;
+ if (!songPlaylist.IsEmpty())
+ {
+ if (!songPlaylist.SaveAsJson(xsp, false))
+ return false;
+ }
+ musicUrl.AddOption(option, xsp);
- CDatabase::Filter filter;
- success = db.GetSongsByWhere(musicUrl.ToString(), filter, items, sorting);
+ CDatabase::Filter dbfilter;
+ success = db.GetSongsByWhere(musicUrl.ToString(), dbfilter, items, sorting);
items.SetContent("songs");
db.Close();
}
@@ -173,12 +197,17 @@ namespace XFILE
mvidPlaylist.SetType("musicvideos");
CVideoDbUrl videoUrl;
- CStdString xsp;
- if (!videoUrl.FromString("videodb://3/2/") || !mvidPlaylist.SaveAsJson(xsp, false))
+ if (!videoUrl.FromString(!strBaseDir.empty() ? strBaseDir : "videodb://3/2/"))
return false;
// store the smartplaylist as JSON in the URL as well
- videoUrl.AddOption("xsp", xsp);
+ CStdString xsp;
+ if (!mvidPlaylist.IsEmpty())
+ {
+ if (!mvidPlaylist.SaveAsJson(xsp, false))
+ return false;
+ }
+ videoUrl.AddOption(option, xsp);
CFileItemList items2;
success2 = db.GetSortedVideos(MediaTypeMusicVideo, videoUrl.ToString(), sorting, items2);
View
2  xbmc/filesystem/SmartPlaylistDirectory.h
@@ -36,7 +36,7 @@ namespace XFILE
virtual bool ContainsFiles(const CStdString& strPath);
virtual bool Remove(const char *strPath);
- static bool GetDirectory(const CSmartPlaylist &playlist, CFileItemList& items);
+ static bool GetDirectory(const CSmartPlaylist &playlist, CFileItemList& items, const CStdString &strBaseDir = "", bool filter = false);
static CStdString GetPlaylistByName(const CStdString& name, const CStdString& playlistType);
};
View
347 xbmc/guilib/GUISliderControl.cpp
@@ -32,19 +32,26 @@ static const SliderAction actions[] = {
CGUISliderControl::CGUISliderControl(int parentID, int controlID, float posX, float posY, float width, float height, const CTextureInfo& backGroundTexture, const CTextureInfo& nibTexture, const CTextureInfo& nibTextureFocus, int iType)
: CGUIControl(parentID, controlID, posX, posY, width, height)
, m_guiBackground(posX, posY, width, height, backGroundTexture)
- , m_guiMid(posX, posY, width, height, nibTexture)
- , m_guiMidFocus(posX, posY, width, height, nibTextureFocus)
+ , m_guiSelectorLower(posX, posY, width, height, nibTexture)
+ , m_guiSelectorUpper(posX, posY, width, height, nibTexture)
+ , m_guiSelectorLowerFocus(posX, posY, width, height, nibTextureFocus)
+ , m_guiSelectorUpperFocus(posX, posY, width, height, nibTextureFocus)
{
m_iType = iType;
- m_iPercent = 0;
+ m_rangeSelection = false;
+ m_currentSelector = RangeSelectorLower; // use lower selector by default
+ m_iPercent[0] = 0;
+ m_iPercent[1] = 100;
m_iStart = 0;
m_iEnd = 100;
m_iInterval = 1;
m_fStart = 0.0f;
m_fEnd = 1.0f;
m_fInterval = 0.1f;
- m_iValue = 0;
- m_fValue = 0.0;
+ m_iValue[0] = m_iStart;
+ m_iValue[1] = m_iEnd;
+ m_fValue[0] = m_fStart;
+ m_fValue[1] = m_fEnd;
ControlType = GUICONTROL_SLIDER;
m_iInfoCode = 0;
m_dragging = false;
@@ -76,35 +83,53 @@ void CGUISliderControl::Process(unsigned int currentTime, CDirtyRegionList &dirt
dirty |= m_guiBackground.SetWidth(m_width);
dirty |= m_guiBackground.Process(currentTime);
+ CGUITexture &nibLower = (m_bHasFocus && !IsDisabled() && m_currentSelector == RangeSelectorLower) ? m_guiSelectorLowerFocus : m_guiSelectorLower;
+ dirty |= ProcessSelector(nibLower, currentTime, fScaleY, RangeSelectorLower);
+ if (m_rangeSelection)
+ {
+ CGUITexture &nibUpper = (m_bHasFocus && !IsDisabled() && m_currentSelector == RangeSelectorUpper) ? m_guiSelectorUpperFocus : m_guiSelectorUpper;
+ dirty |= ProcessSelector(nibUpper, currentTime, fScaleY, RangeSelectorUpper);
+ }
+
+ if (dirty)
+ MarkDirtyRegion();
+
+ CGUIControl::Process(currentTime, dirtyregions);
+}
+
+bool CGUISliderControl::ProcessSelector(CGUITexture &nib, unsigned int currentTime, float fScaleY, RangeSelector selector)
+{
+ bool dirty = false;
// we render the nib centered at the appropriate percentage, except where the nib
// would overflow the background image
- CGUITexture &nib = (m_bHasFocus && !IsDisabled()) ? m_guiMidFocus : m_guiMid;
-
dirty |= nib.SetHeight(nib.GetTextureHeight() * fScaleY);
dirty |= nib.SetWidth(nib.GetHeight() * 2);
- CAspectRatio ratio(CAspectRatio::AR_KEEP); ratio.align = ASPECT_ALIGN_LEFT | ASPECT_ALIGNY_CENTER;
+ CAspectRatio ratio(CAspectRatio::AR_KEEP);
+ ratio.align = ASPECT_ALIGN_LEFT | ASPECT_ALIGNY_CENTER;
dirty |= nib.SetAspectRatio(ratio);
CRect rect = nib.GetRenderRect();
- float offset = GetProportion() * m_width - rect.Width() / 2;
+ float offset = GetProportion(selector) * m_width - rect.Width() / 2;
if (offset > m_width - rect.Width())
offset = m_width - rect.Width();
if (offset < 0)
offset = 0;
- dirty |= nib.SetPosition(m_guiBackground.GetXPosition() + offset, m_guiBackground.GetYPosition() );
+ dirty |= nib.SetPosition(m_guiBackground.GetXPosition() + offset, m_guiBackground.GetYPosition());
dirty |= nib.Process(currentTime);
- if (dirty)
- MarkDirtyRegion();
-
- CGUIControl::Process(currentTime, dirtyregions);
+ return dirty;
}
void CGUISliderControl::Render()
{
m_guiBackground.Render();
- CGUITexture &nib = (m_bHasFocus && !IsDisabled()) ? m_guiMidFocus : m_guiMid;
- nib.Render();
+ CGUITexture &nibLower = (m_bHasFocus && !IsDisabled() && m_currentSelector == RangeSelectorLower) ? m_guiSelectorLowerFocus : m_guiSelectorLower;
+ nibLower.Render();
+ if (m_rangeSelection)
+ {
+ CGUITexture &nibUpper = (m_bHasFocus && !IsDisabled() && m_currentSelector == RangeSelectorUpper) ? m_guiSelectorUpperFocus : m_guiSelectorUpper;
+ nibUpper.Render();
+ }
CGUIControl::Render();
}
@@ -121,7 +146,8 @@ bool CGUISliderControl::OnMessage(CGUIMessage& message)
case GUI_MSG_LABEL_RESET:
{
- SetPercentage(0);
+ SetPercentage(0, RangeSelectorLower);
+ SetPercentage(100, RangeSelectorUpper);
return true;
}
break;
@@ -137,42 +163,83 @@ bool CGUISliderControl::OnAction(const CAction &action)
{
case ACTION_MOVE_LEFT:
//case ACTION_OSD_SHOW_VALUE_MIN:
- Move( -1);
+ Move(-1);
return true;
- break;
case ACTION_MOVE_RIGHT:
//case ACTION_OSD_SHOW_VALUE_PLUS:
Move(1);
return true;
- break;
+
+ case ACTION_SELECT_ITEM:
+ // switch between the two sliders
+ SwitchRangeSelector();
+ return true;
+
default:
- return CGUIControl::OnAction(action);
+ break;
}
+
+ return CGUIControl::OnAction(action);
}
void CGUISliderControl::Move(int iNumSteps)
{
+ bool rangeSwap = false;
switch (m_iType)
{
case SPIN_CONTROL_TYPE_FLOAT:
- m_fValue += m_fInterval * iNumSteps;
- if (m_fValue < m_fStart) m_fValue = m_fStart;
- if (m_fValue > m_fEnd) m_fValue = m_fEnd;
- break;
+ {
+ float &value = m_fValue[m_currentSelector];
+ value += m_fInterval * iNumSteps;
+ if (value < m_fStart) value = m_fStart;
+ if (value > m_fEnd) value = m_fEnd;
+ if (m_fValue[0] > m_fValue[1])
+ {
+ float valueLower = m_fValue[0];
+ m_fValue[0] = m_fValue[1];
+ m_fValue[1] = valueLower;
+ rangeSwap = true;
+ }
+ break;
+ }
case SPIN_CONTROL_TYPE_INT:
- m_iValue += m_iInterval * iNumSteps;
- if (m_iValue < m_iStart) m_iValue = m_iStart;
- if (m_iValue > m_iEnd) m_iValue = m_iEnd;
- break;
+ {
+ int &value = m_iValue[m_currentSelector];
+ value += m_iInterval * iNumSteps;
+ if (value < m_iStart) value = m_iStart;
+ if (value > m_iEnd) value = m_iEnd;
+ if (m_iValue[0] > m_iValue[1])
+ {
+ int valueLower = m_iValue[0];
+ m_iValue[0] = m_iValue[1];
+ m_iValue[1] = valueLower;
+ rangeSwap = true;
+ }
+ break;
+ }
default:
- m_iPercent += m_iInterval * iNumSteps;
- if (m_iPercent < 0) m_iPercent = 0;
- if (m_iPercent > 100) m_iPercent = 100;
- break;
+ {
+ int &value = m_iPercent[m_currentSelector];
+ value += m_iInterval * iNumSteps;
+ if (value < 0) value = 0;
+ if (value > 100) value = 100;
+ if (m_iPercent[0] > m_iPercent[1])
+ {
+ int valueLower = m_iPercent[0];
+ m_iPercent[0] = m_iPercent[1];
+ m_iPercent[1] = valueLower;
+ rangeSwap = true;
+ }
+ break;
+ }
}
+
+ if (rangeSwap)
+ SwitchRangeSelector();
+
SendClick();
}
@@ -190,56 +257,130 @@ void CGUISliderControl::SendClick()
}
}
-void CGUISliderControl::SetPercentage(int iPercent)
+void CGUISliderControl::SetRangeSelection(bool rangeSelection)
+{
+ if (m_rangeSelection == rangeSelection)
+ return;
+
+ m_rangeSelection = rangeSelection;
+ SetRangeSelector(RangeSelectorLower);
+ SetInvalid();
+}
+
+void CGUISliderControl::SetRangeSelector(RangeSelector selector)
+{
+ if (m_currentSelector == selector)
+ return;
+
+ m_currentSelector = selector;
+ SetInvalid();
+}
+
+void CGUISliderControl::SwitchRangeSelector()
+{
+ if (m_currentSelector == RangeSelectorLower)
+ SetRangeSelector(RangeSelectorUpper);
+ else
+ SetRangeSelector(RangeSelectorLower);
+}
+
+void CGUISliderControl::SetPercentage(int iPercent, RangeSelector selector /* = RangeSelectorLower */)
{
if (iPercent > 100) iPercent = 100;
- if (iPercent < 0) iPercent = 0;
- m_iPercent = iPercent;
+ else if (iPercent < 0) iPercent = 0;
+
+ int iPercentLower = selector == RangeSelectorLower ? iPercent : m_iPercent[0];
+ int iPercentUpper = selector == RangeSelectorUpper ? iPercent : m_iPercent[1];
+
+ if (!m_rangeSelection || iPercentLower <= iPercentUpper)
+ {
+ m_iPercent[0] = iPercentLower;
+ m_iPercent[1] = iPercentUpper;
+ }
+ else
+ {
+ m_iPercent[0] = iPercentUpper;
+ m_iPercent[1] = iPercentLower;
+ }
}
-int CGUISliderControl::GetPercentage() const
+int CGUISliderControl::GetPercentage(RangeSelector selector /* = RangeSelectorLower */) const
{
- return m_iPercent;
+ return m_iPercent[selector];
}
-void CGUISliderControl::SetIntValue(int iValue)
+void CGUISliderControl::SetIntValue(int iValue, RangeSelector selector /* = RangeSelectorLower */)
{
if (m_iType == SPIN_CONTROL_TYPE_FLOAT)
- m_fValue = (float)iValue;
+ SetFloatValue((float)iValue);
else if (m_iType == SPIN_CONTROL_TYPE_INT)
- m_iValue = iValue;
+ {
+ if (iValue > m_iEnd) iValue = m_iEnd;
+ else if (iValue < m_iStart) iValue = m_iStart;
+
+ int iValueLower = selector == RangeSelectorLower ? iValue : m_iValue[0];
+ int iValueUpper = selector == RangeSelectorUpper ? iValue : m_iValue[1];
+
+ if (!m_rangeSelection || iValueLower <= iValueUpper)
+ {
+ m_iValue[0] = iValueLower;
+ m_iValue[1] = iValueUpper;
+ }
+ else
+ {
+ m_iValue[0] = iValueUpper;
+ m_iValue[1] = iValueLower;
+ }
+ }
else
SetPercentage(iValue);
}
-int CGUISliderControl::GetIntValue() const
+int CGUISliderControl::GetIntValue(RangeSelector selector /* = RangeSelectorLower */) const
{
if (m_iType == SPIN_CONTROL_TYPE_FLOAT)
- return (int)m_fValue;
+ return (int)m_fValue[selector];
else if (m_iType == SPIN_CONTROL_TYPE_INT)
- return m_iValue;
+ return m_iValue[selector];
else
- return m_iPercent;
+ return m_iPercent[selector];
}
-void CGUISliderControl::SetFloatValue(float fValue)
+void CGUISliderControl::SetFloatValue(float fValue, RangeSelector selector /* = RangeSelectorLower */)
{
if (m_iType == SPIN_CONTROL_TYPE_FLOAT)
- m_fValue = fValue;
+ {
+ if (fValue > m_fEnd) fValue = m_fEnd;
+ else if (fValue < m_fStart) fValue = m_fStart;
+
+ float fValueLower = selector == RangeSelectorLower ? fValue : m_fValue[0];
+ float fValueUpper = selector == RangeSelectorUpper ? fValue : m_fValue[1];
+
+ if (!m_rangeSelection || fValueLower <= fValueUpper)
+ {
+ m_fValue[0] = fValueLower;
+ m_fValue[1] = fValueUpper;
+ }
+ else
+ {
+ m_fValue[0] = fValueUpper;
+ m_fValue[1] = fValueLower;
+ }
+ }
else if (m_iType == SPIN_CONTROL_TYPE_INT)
- m_iValue = (int)fValue;
+ SetIntValue((int)fValue);
else
SetPercentage((int)fValue);
}
-float CGUISliderControl::GetFloatValue() const
+float CGUISliderControl::GetFloatValue(RangeSelector selector /* = RangeSelectorLower */) const
{
if (m_iType == SPIN_CONTROL_TYPE_FLOAT)
- return m_fValue;
+ return m_fValue[selector];
else if (m_iType == SPIN_CONTROL_TYPE_INT)
- return (float)m_iValue;
+ return (float)m_iValue[selector];
else
- return (float)m_iPercent;
+ return (float)m_iPercent[selector];
}
void CGUISliderControl::SetIntInterval(int iInterval)
@@ -264,8 +405,8 @@ void CGUISliderControl::SetRange(int iStart, int iEnd)
SetFloatRange((float)iStart,(float)iEnd);
else
{
- m_iStart = iStart;
- m_iEnd = iEnd;
+ m_iValue[0] = m_iStart = iStart;
+ m_iValue[1] = m_iEnd = iEnd;
}