aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortamland <thomas.amland@gmail.com>2015-08-08 12:49:49 +0200
committertamland <thomas.amland@gmail.com>2015-08-08 12:49:49 +0200
commite32987a697f1cfbecfe2043ede0db4e0bf234d29 (patch)
tree1a20fd4aca95d8d9574ee266b46ba3bf0c710d21
parent5f938e2b7b093379a35d0f51f616b38227e68d35 (diff)
parentb2dfa4ed125cdc8cd2ce602eadf99328ad99b302 (diff)
Merge pull request #7544 from tamland/context_menu_groups
[addons] extend context menu system
-rw-r--r--Kodi.xcodeproj/project.pbxproj30
-rw-r--r--addons/resource.language.en_gb/resources/strings.po2
-rw-r--r--addons/xbmc.python/contextitem.xsd28
-rw-r--r--project/VS2010Express/XBMC.vcxproj6
-rw-r--r--project/VS2010Express/XBMC.vcxproj.filters6
-rw-r--r--xbmc/ContextMenuItem.cpp106
-rw-r--r--xbmc/ContextMenuItem.h63
-rw-r--r--xbmc/ContextMenuManager.cpp120
-rw-r--r--xbmc/ContextMenuManager.h41
-rw-r--r--xbmc/Makefile.in1
-rw-r--r--xbmc/addons/Addon.cpp10
-rw-r--r--xbmc/addons/AddonManager.cpp6
-rw-r--r--xbmc/addons/ContextItemAddon.cpp72
-rw-r--r--xbmc/addons/ContextItemAddon.h66
-rw-r--r--xbmc/addons/ContextMenuAddon.cpp129
-rw-r--r--xbmc/addons/ContextMenuAddon.h47
-rw-r--r--xbmc/addons/Makefile2
-rw-r--r--xbmc/dialogs/GUIDialogFavourites.cpp2
-rw-r--r--xbmc/video/dialogs/GUIDialogVideoInfo.cpp4
-rw-r--r--xbmc/windows/GUIMediaWindow.cpp2
-rw-r--r--xbmc/windows/GUIWindowLoginScreen.cpp2
21 files changed, 515 insertions, 230 deletions
diff --git a/Kodi.xcodeproj/project.pbxproj b/Kodi.xcodeproj/project.pbxproj
index 1ca94d7f27..ebfd42935b 100644
--- a/Kodi.xcodeproj/project.pbxproj
+++ b/Kodi.xcodeproj/project.pbxproj
@@ -214,9 +214,6 @@
395C2A191A9F074C00EBC7AD /* Locale.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395C2A171A9F074C00EBC7AD /* Locale.cpp */; };
395C2A1A1A9F074C00EBC7AD /* Locale.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395C2A171A9F074C00EBC7AD /* Locale.cpp */; };
395C2A1B1A9F074C00EBC7AD /* Locale.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395C2A171A9F074C00EBC7AD /* Locale.cpp */; };
- 395C2A1F1A9F96A700EBC7AD /* ContextItemAddon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395C2A1D1A9F96A700EBC7AD /* ContextItemAddon.cpp */; };
- 395C2A201A9F96A700EBC7AD /* ContextItemAddon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395C2A1D1A9F96A700EBC7AD /* ContextItemAddon.cpp */; };
- 395C2A211A9F96A700EBC7AD /* ContextItemAddon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395C2A1D1A9F96A700EBC7AD /* ContextItemAddon.cpp */; };
395C2A241AA4C32100EBC7AD /* AudioDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395C2A221AA4C32100EBC7AD /* AudioDecoder.cpp */; };
395C2A251AA4C32100EBC7AD /* AudioDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395C2A221AA4C32100EBC7AD /* AudioDecoder.cpp */; };
395C2A261AA4C32100EBC7AD /* AudioDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 395C2A221AA4C32100EBC7AD /* AudioDecoder.cpp */; };
@@ -891,6 +888,12 @@
DF527736151BAF4C00B5B63B /* WebSocketV13.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF52772F151BAF4C00B5B63B /* WebSocketV13.cpp */; };
DF527737151BAF4C00B5B63B /* WebSocketV8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF527731151BAF4C00B5B63B /* WebSocketV8.cpp */; };
DF529BAE1741697B00523FB4 /* Environment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF529BAC1741697B00523FB4 /* Environment.cpp */; };
+ DF54F7FE1B6580AD000FCBA4 /* ContextMenuItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF54F7FC1B6580AC000FCBA4 /* ContextMenuItem.cpp */; };
+ DF54F7FF1B6580AD000FCBA4 /* ContextMenuItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF54F7FC1B6580AC000FCBA4 /* ContextMenuItem.cpp */; };
+ DF54F8001B6580AD000FCBA4 /* ContextMenuItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF54F7FC1B6580AC000FCBA4 /* ContextMenuItem.cpp */; };
+ DF54F8031B6580C8000FCBA4 /* ContextMenuAddon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF54F8011B6580C8000FCBA4 /* ContextMenuAddon.cpp */; };
+ DF54F8041B6580C8000FCBA4 /* ContextMenuAddon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF54F8011B6580C8000FCBA4 /* ContextMenuAddon.cpp */; };
+ DF54F8051B6580C8000FCBA4 /* ContextMenuAddon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF54F8011B6580C8000FCBA4 /* ContextMenuAddon.cpp */; };
DF56EF1F1A798A3F00CAAEFB /* HTTPFileHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF56EF1D1A798A3F00CAAEFB /* HTTPFileHandler.cpp */; };
DF56EF201A798A3F00CAAEFB /* HTTPFileHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF56EF1D1A798A3F00CAAEFB /* HTTPFileHandler.cpp */; };
DF56EF211A798A3F00CAAEFB /* HTTPFileHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF56EF1D1A798A3F00CAAEFB /* HTTPFileHandler.cpp */; };
@@ -3590,8 +3593,6 @@
395C2A101A9F072400EBC7AD /* ResourceFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResourceFile.h; sourceTree = "<group>"; };
395C2A171A9F074C00EBC7AD /* Locale.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Locale.cpp; sourceTree = "<group>"; };
395C2A181A9F074C00EBC7AD /* Locale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Locale.h; sourceTree = "<group>"; };
- 395C2A1D1A9F96A700EBC7AD /* ContextItemAddon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ContextItemAddon.cpp; sourceTree = "<group>"; };
- 395C2A1E1A9F96A700EBC7AD /* ContextItemAddon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContextItemAddon.h; sourceTree = "<group>"; };
395C2A221AA4C32100EBC7AD /* AudioDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AudioDecoder.cpp; sourceTree = "<group>"; };
395C2A231AA4C32100EBC7AD /* AudioDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioDecoder.h; sourceTree = "<group>"; };
395F6DDB1A8133360088CC74 /* GUIDialogSimpleMenu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogSimpleMenu.cpp; sourceTree = "<group>"; };
@@ -4521,6 +4522,10 @@
DF527732151BAF4C00B5B63B /* WebSocketV8.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSocketV8.h; sourceTree = "<group>"; };
DF529BAC1741697B00523FB4 /* Environment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Environment.cpp; sourceTree = "<group>"; };
DF529BAD1741697B00523FB4 /* Environment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Environment.h; sourceTree = "<group>"; };
+ DF54F7FC1B6580AC000FCBA4 /* ContextMenuItem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ContextMenuItem.cpp; sourceTree = "<group>"; };
+ DF54F7FD1B6580AC000FCBA4 /* ContextMenuItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContextMenuItem.h; sourceTree = "<group>"; };
+ DF54F8011B6580C8000FCBA4 /* ContextMenuAddon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ContextMenuAddon.cpp; sourceTree = "<group>"; };
+ DF54F8021B6580C8000FCBA4 /* ContextMenuAddon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContextMenuAddon.h; sourceTree = "<group>"; };
DF56EF1D1A798A3F00CAAEFB /* HTTPFileHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTTPFileHandler.cpp; sourceTree = "<group>"; };
DF56EF1E1A798A3F00CAAEFB /* HTTPFileHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTTPFileHandler.h; sourceTree = "<group>"; };
DF56EF221A798A5E00CAAEFB /* HttpRangeUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HttpRangeUtils.cpp; sourceTree = "<group>"; };
@@ -5927,8 +5932,8 @@
395C2A231AA4C32100EBC7AD /* AudioDecoder.h */,
7CF34D9D1930264A00D543C5 /* AudioEncoder.cpp */,
7CF34D9E1930264A00D543C5 /* AudioEncoder.h */,
- 395C2A1D1A9F96A700EBC7AD /* ContextItemAddon.cpp */,
- 395C2A1E1A9F96A700EBC7AD /* ContextItemAddon.h */,
+ DF54F8011B6580C8000FCBA4 /* ContextMenuAddon.cpp */,
+ DF54F8021B6580C8000FCBA4 /* ContextMenuAddon.h */,
18B49FF61152BFA5001AF8A6 /* DllAddon.h */,
18B7C38612942090009E7A26 /* GUIDialogAddonInfo.cpp */,
18B7C38712942090009E7A26 /* GUIDialogAddonInfo.h */,
@@ -8272,6 +8277,8 @@
E38E14720D25F9F900618676 /* BackgroundInfoLoader.cpp */,
E38E14730D25F9F900618676 /* BackgroundInfoLoader.h */,
F5B413131065900C0035D105 /* config.h */,
+ DF54F7FC1B6580AC000FCBA4 /* ContextMenuItem.cpp */,
+ DF54F7FD1B6580AC000FCBA4 /* ContextMenuItem.h */,
395C29F91A9CD20C00EBC7AD /* ContextMenuManager.cpp */,
395C29FA1A9CD20C00EBC7AD /* ContextMenuManager.h */,
E38E167E0D25F9FA00618676 /* CueDocument.cpp */,
@@ -10288,6 +10295,7 @@
E38E20510D25F9FD00618676 /* PluginDirectory.cpp in Sources */,
E38E20520D25F9FD00618676 /* RarDirectory.cpp in Sources */,
E38E20530D25F9FD00618676 /* RarManager.cpp in Sources */,
+ DF54F7FE1B6580AD000FCBA4 /* ContextMenuItem.cpp in Sources */,
395C29C51A98A0E100EBC7AD /* ILanguageInvoker.cpp in Sources */,
E38E20580D25F9FD00618676 /* SmartPlaylistDirectory.cpp in Sources */,
E38E205B0D25F9FD00618676 /* StackDirectory.cpp in Sources */,
@@ -10875,6 +10883,7 @@
C84828C8156CFCD8005A996F /* GUIDialogPVRChannelManager.cpp in Sources */,
C84828C9156CFCD8005A996F /* GUIDialogPVRChannelsOSD.cpp in Sources */,
C84828CC156CFCD8005A996F /* GUIDialogPVRGroupManager.cpp in Sources */,
+ DF54F8031B6580C8000FCBA4 /* ContextMenuAddon.cpp in Sources */,
C84828CD156CFCD8005A996F /* GUIDialogPVRGuideInfo.cpp in Sources */,
C84828CE156CFCD8005A996F /* GUIDialogPVRGuideOSD.cpp in Sources */,
C84828CF156CFCD8005A996F /* GUIDialogPVRGuideSearch.cpp in Sources */,
@@ -11078,7 +11087,6 @@
7C1409A9184015C9009F9411 /* InfoExpression.cpp in Sources */,
AE32174218313ADF0003FAFC /* XSLTUtils.cpp in Sources */,
7C15DCBC1892481400FCE564 /* InfoBool.cpp in Sources */,
- 395C2A1F1A9F96A700EBC7AD /* ContextItemAddon.cpp in Sources */,
F5CC228B1814F7E9006B5E91 /* AESinkDARWINOSX.cpp in Sources */,
F5CC22EB1814FF3B006B5E91 /* ActiveAE.cpp in Sources */,
F5CC22EC1814FF3B006B5E91 /* ActiveAEBuffer.cpp in Sources */,
@@ -11583,6 +11591,7 @@
DFF0F28217528350002DA3A4 /* GUIControlFactory.cpp in Sources */,
DFF0F28317528350002DA3A4 /* GUIControlGroup.cpp in Sources */,
DFF0F28417528350002DA3A4 /* GUIControlGroupList.cpp in Sources */,
+ DF54F8001B6580AD000FCBA4 /* ContextMenuItem.cpp in Sources */,
DFF0F28517528350002DA3A4 /* GUIControlProfiler.cpp in Sources */,
DFF0F28617528350002DA3A4 /* GUIDialog.cpp in Sources */,
DFF0F28717528350002DA3A4 /* GUIEditControl.cpp in Sources */,
@@ -11749,7 +11758,6 @@
DFF0F32417528350002DA3A4 /* HTTPVfsHandler.cpp in Sources */,
DFF0F32517528350002DA3A4 /* HTTPWebinterfaceAddonsHandler.cpp in Sources */,
DFF0F32617528350002DA3A4 /* HTTPWebinterfaceHandler.cpp in Sources */,
- 395C2A211A9F96A700EBC7AD /* ContextItemAddon.cpp in Sources */,
DFF0F32717528350002DA3A4 /* IHTTPRequestHandler.cpp in Sources */,
DFF0F32817528350002DA3A4 /* NetworkLinux.cpp in Sources */,
DFF0F32917528350002DA3A4 /* ZeroconfBrowserOSX.cpp in Sources */,
@@ -11816,6 +11824,7 @@
DFF0F36117528350002DA3A4 /* PlayListM3U.cpp in Sources */,
DF4BF0191A4EF31F0053AC56 /* cc_decoder.c in Sources */,
DFF0F36217528350002DA3A4 /* PlayListPLS.cpp in Sources */,
+ DF54F8051B6580C8000FCBA4 /* ContextMenuAddon.cpp in Sources */,
DFF0F36317528350002DA3A4 /* PlayListURL.cpp in Sources */,
DFF0F36417528350002DA3A4 /* PlayListWPL.cpp in Sources */,
DFEA4B5B1B52721300562321 /* GUIDialogAudioDSPManager.cpp in Sources */,
@@ -12605,7 +12614,6 @@
E49912C9174E5DA000741B6D /* DirectoryNodeRecentlyAddedMusicVideos.cpp in Sources */,
E49912CA174E5DA000741B6D /* DirectoryNodeRoot.cpp in Sources */,
E49912CB174E5DA000741B6D /* DirectoryNodeSeasons.cpp in Sources */,
- 395C2A201A9F96A700EBC7AD /* ContextItemAddon.cpp in Sources */,
E49912CC174E5DA000741B6D /* DirectoryNodeTitleMovies.cpp in Sources */,
E49912CD174E5DA000741B6D /* DirectoryNodeTitleMusicVideos.cpp in Sources */,
DFDE5D521AE5658200EE53AD /* PictureScalingAlgorithm.cpp in Sources */,
@@ -12771,6 +12779,7 @@
E499137C174E5F0E00741B6D /* GUIDialogKaraokeSongSelector.cpp in Sources */,
E499137D174E5F0E00741B6D /* GUIWindowKaraokeLyrics.cpp in Sources */,
E499137E174E5F0E00741B6D /* karaokelyrics.cpp in Sources */,
+ DF54F8041B6580C8000FCBA4 /* ContextMenuAddon.cpp in Sources */,
E499137F174E5F0E00741B6D /* karaokelyricscdg.cpp in Sources */,
E4991380174E5F0E00741B6D /* karaokelyricsfactory.cpp in Sources */,
E4991381174E5F0E00741B6D /* karaokelyricsmanager.cpp in Sources */,
@@ -13223,6 +13232,7 @@
7CCDA187192753E30074CF51 /* PltTaskManager.cpp in Sources */,
7CCDA190192753E30074CF51 /* PltThreadTask.cpp in Sources */,
7CCDA199192753E30074CF51 /* PltUPnP.cpp in Sources */,
+ DF54F7FF1B6580AD000FCBA4 /* ContextMenuItem.cpp in Sources */,
7CCDA1A2192753E30074CF51 /* PltMediaConnect.cpp in Sources */,
7CCDA1AB192753E30074CF51 /* PltXbox360.cpp in Sources */,
7CCDA1B0192753E30074CF51 /* X_MS_MediaReceiverRegistrarSCPD.cpp in Sources */,
diff --git a/addons/resource.language.en_gb/resources/strings.po b/addons/resource.language.en_gb/resources/strings.po
index 10c39b9fe5..3fa1dbc367 100644
--- a/addons/resource.language.en_gb/resources/strings.po
+++ b/addons/resource.language.en_gb/resources/strings.po
@@ -13110,7 +13110,7 @@ msgstr ""
#. Used as the type name for context item addons
#: xbmc/addons/Addons.cpp
msgctxt "#24025"
-msgid "Context items"
+msgid "Context menus"
msgstr ""
#: xbmc/addons/Addon.cpp
diff --git a/addons/xbmc.python/contextitem.xsd b/addons/xbmc.python/contextitem.xsd
index 3c7c671528..0baa6f999a 100644
--- a/addons/xbmc.python/contextitem.xsd
+++ b/addons/xbmc.python/contextitem.xsd
@@ -4,26 +4,30 @@
<xs:element name="extension">
<xs:complexType>
<xs:sequence>
- <xs:element name="item">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="label" type="xs:string"/>
- <xs:element name="visible" type="xs:string"/>
- <xs:element name="parent" type="xs:string"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
+ <xs:element name="menu" type="menuType" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="point" type="xs:string" use="required"/>
<xs:attribute name="id" type="simpleIdentifier"/>
- <xs:attribute name="name" type="xs:string"/>
- <xs:attribute name="library" type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
+ <xs:complexType name="itemType">
+ <xs:sequence>
+ <xs:element name="label" type="xs:string"/>
+ <xs:element name="visible" type="xs:string"/>
+ </xs:sequence>
+ <xs:attribute name="library" type="xs:string" use="required"/>
+ </xs:complexType>
+ <xs:complexType name="menuType">
+ <xs:sequence>
+ <xs:element name="label" type="xs:string" minOccurs="0"/>
+ <xs:element name="item" type="itemType" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="menu" type="menuType" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="id" type="xs:string"/>
+ </xs:complexType>
<xs:simpleType name="simpleIdentifier">
<xs:restriction base="xs:string">
<xs:pattern value="[^.]+"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
-
diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj
index bf000da93a..93a1ec7162 100644
--- a/project/VS2010Express/XBMC.vcxproj
+++ b/project/VS2010Express/XBMC.vcxproj
@@ -190,7 +190,7 @@
<ClCompile Include="..\..\xbmc\addons\AddonDatabase.cpp" />
<ClCompile Include="..\..\xbmc\addons\AddonInstaller.cpp" />
<ClCompile Include="..\..\xbmc\addons\AddonVersion.cpp" />
- <ClCompile Include="..\..\xbmc\addons\ContextItemAddon.cpp" />
+ <ClCompile Include="..\..\xbmc\addons\ContextMenuAddon.cpp" />
<ClCompile Include="..\..\xbmc\addons\AudioDecoder.cpp" />
<ClCompile Include="..\..\xbmc\addons\GUIDialogAddonInfo.cpp" />
<ClCompile Include="..\..\xbmc\addons\GUIDialogAddonSettings.cpp" />
@@ -211,6 +211,7 @@
<ClCompile Include="..\..\xbmc\AutoSwitch.cpp" />
<ClCompile Include="..\..\xbmc\BackgroundInfoLoader.cpp" />
<ClCompile Include="..\..\xbmc\CompileInfo.cpp" />
+ <ClCompile Include="..\..\xbmc\ContextMenuItem.cpp" />
<ClCompile Include="..\..\xbmc\ContextMenuManager.cpp" />
<ClCompile Include="..\..\xbmc\contrib\kissfft\kiss_fft.c">
<CompileAs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CompileAsCpp</CompileAs>
@@ -857,7 +858,7 @@
<ClInclude Include="..\..\xbmc\addons\AddonCallbacksAudioDSP.h" />
<ClInclude Include="..\..\xbmc\addons\AddonCallbacksCodec.h" />
<ClInclude Include="..\..\xbmc\addons\AudioDecoder.h" />
- <ClInclude Include="..\..\xbmc\addons\ContextItemAddon.h" />
+ <ClInclude Include="..\..\xbmc\addons\ContextMenuAddon.h" />
<ClInclude Include="..\..\xbmc\addons\ImageResource.h" />
<ClInclude Include="..\..\xbmc\addons\Webinterface.h" />
<ClInclude Include="..\..\xbmc\addons\UISoundsResource.h" />
@@ -1726,6 +1727,7 @@
<ClInclude Include="..\..\xbmc\Autorun.h" />
<ClInclude Include="..\..\xbmc\AutoSwitch.h" />
<ClInclude Include="..\..\xbmc\BackgroundInfoLoader.h" />
+ <ClInclude Include="..\..\xbmc\ContextMenuItem.h" />
<ClInclude Include="..\..\xbmc\ContextMenuManager.h" />
<ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDDemuxers\DVDDemuxPVRClient.h" />
<ClInclude Include="..\..\xbmc\cores\dvdplayer\DVDInputStreams\DVDInputStreamBluray.h" />
diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters
index 44a8402a2b..e37e781f64 100644
--- a/project/VS2010Express/XBMC.vcxproj.filters
+++ b/project/VS2010Express/XBMC.vcxproj.filters
@@ -744,7 +744,7 @@
<ClCompile Include="..\..\xbmc\addons\AudioEncoder.cpp">
<Filter>addons</Filter>
</ClCompile>
- <ClCompile Include="..\..\xbmc\addons\ContextItemAddon.cpp">
+ <ClCompile Include="..\..\xbmc\addons\ContextMenuAddon.cpp">
<Filter>addons</Filter>
</ClCompile>
<ClCompile Include="..\..\xbmc\addons\Scraper.cpp">
@@ -2227,6 +2227,7 @@
<ClCompile Include="..\..\xbmc\AutoSwitch.cpp" />
<ClCompile Include="..\..\xbmc\DynamicDll.cpp" />
<ClCompile Include="..\..\xbmc\CueDocument.cpp" />
+ <ClCompile Include="..\..\xbmc\ContextMenuItem.cpp" />
<ClCompile Include="..\..\xbmc\ContextMenuManager.cpp" />
<ClCompile Include="..\..\xbmc\FileItem.cpp" />
<ClCompile Include="..\..\xbmc\GUIInfoManager.cpp" />
@@ -3622,7 +3623,7 @@
<ClInclude Include="..\..\xbmc\addons\AudioEncoder.h">
<Filter>addons</Filter>
</ClInclude>
- <ClInclude Include="..\..\xbmc\addons\ContextItemAddon.h">
+ <ClInclude Include="..\..\xbmc\addons\ContextMenuAddon.h">
<Filter>addons</Filter>
</ClInclude>
<ClInclude Include="..\..\xbmc\addons\DllAddon.h">
@@ -5243,6 +5244,7 @@
<ClInclude Include="..\..\xbmc\AutoSwitch.h" />
<ClInclude Include="..\..\xbmc\DynamicDll.h" />
<ClInclude Include="..\..\xbmc\CueDocument.h" />
+ <ClInclude Include="..\..\xbmc\ContextMenuItem.h" />
<ClInclude Include="..\..\xbmc\ContextMenuManager.h" />
<ClInclude Include="..\..\xbmc\FileItem.h" />
<ClInclude Include="..\..\xbmc\GUIInfoManager.h" />
diff --git a/xbmc/ContextMenuItem.cpp b/xbmc/ContextMenuItem.cpp
new file mode 100644
index 0000000000..c9a382e863
--- /dev/null
+++ b/xbmc/ContextMenuItem.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2015 Team XBMC
+ * http://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 "ContextMenuItem.h"
+#include "addons/Addon.h"
+#include "addons/AddonManager.h"
+#include "addons/ContextMenuAddon.h"
+#include "addons/IAddon.h"
+#include "interfaces/generic/ScriptInvocationManager.h"
+#include "interfaces/python/ContextItemAddonInvoker.h"
+#include "interfaces/python/XBPython.h"
+#include "utils/StringUtils.h"
+#include <boost/lexical_cast.hpp>
+
+
+std::string CContextMenuItem::GetLabel() const
+{
+ if (!m_addon)
+ return "";
+
+ if (StringUtils::IsNaturalNumber(m_label))
+ return m_addon->GetString(boost::lexical_cast<int>(m_label.c_str()));
+
+ return m_label;
+}
+
+bool CContextMenuItem::IsVisible(const CFileItemPtr& item) const
+{
+ return IsGroup() || (item && m_condition && m_condition->Get(item.get()));
+}
+
+bool CContextMenuItem::IsParentOf(const CContextMenuItem& other) const
+{
+ return !m_groupId.empty() && (m_groupId == other.m_parent);
+}
+
+bool CContextMenuItem::IsGroup() const
+{
+ return !m_groupId.empty();
+}
+
+bool CContextMenuItem::Execute(const CFileItemPtr& item) const
+{
+ if (!item || !m_addon || m_library.empty() || IsGroup())
+ return false;
+
+ LanguageInvokerPtr invoker(new CContextItemAddonInvoker(&g_pythonParser, item));
+ return (CScriptInvocationManager::Get().ExecuteAsync(m_library, invoker, m_addon) != -1);
+}
+
+bool CContextMenuItem::operator==(const CContextMenuItem& other) const
+{
+ if (IsGroup() && other.IsGroup())
+ return (m_groupId == other.m_groupId && m_parent == other.m_parent);
+
+ return (IsGroup() == other.IsGroup())
+ && (m_parent == other.m_parent)
+ && (m_library == other.m_library)
+ && ((!m_addon && !other.m_addon) || (m_addon && other.m_addon && m_addon->ID() == other.m_addon->ID()));
+}
+
+std::string CContextMenuItem::ToString() const
+{
+ if (IsGroup())
+ return StringUtils::Format("CContextMenuItem[group, id=%s, parent=%s, addon=%s]",
+ m_groupId.c_str(), m_parent.c_str(), m_addon ? m_addon->ID().c_str() : "null");
+ else
+ return StringUtils::Format("CContextMenuItem[item, parent=%s, library=%s, addon=%s]",
+ m_parent.c_str(), m_library.c_str(), m_addon ? m_addon->ID().c_str() : "null");
+}
+
+CContextMenuItem CContextMenuItem::CreateGroup(const std::string& label, const std::string& parent, const std::string& groupId)
+{
+ CContextMenuItem menuItem;
+ menuItem.m_label = label;
+ menuItem.m_parent = parent;
+ menuItem.m_groupId = groupId;
+ return menuItem;
+}
+
+CContextMenuItem CContextMenuItem::CreateItem(const std::string& label, const std::string& parent, const std::string& library, const INFO::InfoPtr& condition)
+{
+ CContextMenuItem menuItem;
+ menuItem.m_label = label;
+ menuItem.m_parent = parent;
+ menuItem.m_library = library;
+ menuItem.m_condition = condition;
+ return menuItem;
+}
diff --git a/xbmc/ContextMenuItem.h b/xbmc/ContextMenuItem.h
new file mode 100644
index 0000000000..b1e57bc6d0
--- /dev/null
+++ b/xbmc/ContextMenuItem.h
@@ -0,0 +1,63 @@
+#pragma once
+/*
+ * Copyright (C) 2015 Team XBMC
+ * http://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 "addons/ContextMenuAddon.h"
+#include "addons/IAddon.h"
+#include "dialogs/GUIDialogContextMenu.h"
+
+namespace ADDON
+{
+ class CContextMenuAddon;
+}
+
+class CContextMenuItem
+{
+public:
+ std::string GetLabel() const;
+ bool IsVisible(const CFileItemPtr& item) const;
+ bool IsParentOf(const CContextMenuItem& menuItem) const;
+ bool IsGroup() const;
+ bool Execute(const CFileItemPtr& item) const;
+ bool operator==(const CContextMenuItem& other) const;
+ std::string ToString() const;
+
+ static CContextMenuItem CreateGroup(
+ const std::string& label,
+ const std::string& parent,
+ const std::string& groupId);
+
+ static CContextMenuItem CreateItem(
+ const std::string& label,
+ const std::string& parent,
+ const std::string& library,
+ const INFO::InfoPtr& condition);
+
+ friend class ADDON::CContextMenuAddon;
+
+private:
+ std::string m_label;
+ std::string m_parent;
+ std::string m_groupId;
+ std::string m_library;
+ INFO::InfoPtr m_condition;
+ ADDON::AddonPtr m_addon;
+};
diff --git a/xbmc/ContextMenuManager.cpp b/xbmc/ContextMenuManager.cpp
index 4f9f88dc2f..b4d05d8473 100644
--- a/xbmc/ContextMenuManager.cpp
+++ b/xbmc/ContextMenuManager.cpp
@@ -19,21 +19,26 @@
*/
#include "ContextMenuManager.h"
+#include "ContextMenuItem.h"
#include "addons/Addon.h"
#include "addons/AddonManager.h"
-#include "addons/ContextItemAddon.h"
+#include "addons/ContextMenuAddon.h"
#include "addons/IAddon.h"
#include "interfaces/generic/ScriptInvocationManager.h"
#include "interfaces/python/ContextItemAddonInvoker.h"
#include "interfaces/python/XBPython.h"
+#include "utils/log.h"
using namespace ADDON;
-typedef std::map<unsigned int, ContextItemAddonPtr>::value_type ValueType;
+typedef std::pair<unsigned int, CContextMenuItem> Item;
+
+const CContextMenuItem CContextMenuManager::MAIN = CContextMenuItem::CreateGroup("", "", "kodi.core.main");
+const CContextMenuItem CContextMenuManager::MANAGE = CContextMenuItem::CreateGroup("", "", "kodi.core.manage");
CContextMenuManager::CContextMenuManager()
- : m_iCurrentContextId(CONTEXT_BUTTON_FIRST_ADDON)
+ : m_nextButtonId(CONTEXT_BUTTON_FIRST_ADDON)
{
Init();
}
@@ -46,20 +51,32 @@ CContextMenuManager& CContextMenuManager::Get()
void CContextMenuManager::Init()
{
- //Make sure we load all context items on first usage...
VECADDONS addons;
if (CAddonMgr::Get().GetAddons(ADDON_CONTEXT_ITEM, addons))
- {
for (const auto& addon : addons)
- Register(std::static_pointer_cast<CContextItemAddon>(addon));
- }
+ Register(std::static_pointer_cast<CContextMenuAddon>(addon));
}
void CContextMenuManager::Register(const ContextItemAddonPtr& cm)
{
if (!cm)
return;
- m_contextAddons[m_iCurrentContextId++] = cm;
+
+ for (const auto& menuItem : cm->GetItems())
+ {
+ auto existing = std::find_if(m_items.begin(), m_items.end(),
+ [&](const Item& kv){ return kv.second == menuItem; });
+ if (existing != m_items.end())
+ {
+ if (!menuItem.GetLabel().empty())
+ existing->second = menuItem;
+ }
+ else
+ {
+ m_items.push_back(std::make_pair(m_nextButtonId, menuItem));
+ ++m_nextButtonId;
+ }
+ }
}
bool CContextMenuManager::Unregister(const ContextItemAddonPtr& cm)
@@ -67,47 +84,88 @@ bool CContextMenuManager::Unregister(const ContextItemAddonPtr& cm)
if (!cm)
return false;
- auto it = std::find_if(m_contextAddons.begin(), m_contextAddons.end(),
- [&](const ValueType& value){ return value.second->ID() == cm->ID(); });
-
- if (it != m_contextAddons.end())
- {
- m_contextAddons.erase(it);
- return true;
- }
- return false;
+ const auto menuItems = cm->GetItems();
+
+ auto it = std::remove_if(m_items.begin(), m_items.end(),
+ [&](const Item& kv)
+ {
+ if (kv.second.IsGroup())
+ return false; //keep in case other items use them
+ return std::find(menuItems.begin(), menuItems.end(), kv.second) != menuItems.end();
+ }
+ );
+ m_items.erase(it, m_items.end());
+ return true;
}
-ContextItemAddonPtr CContextMenuManager::GetContextItemByID(unsigned int id)
+bool CContextMenuManager::IsVisible(
+ const CContextMenuItem& menuItem, const CContextMenuItem& root, const CFileItemPtr& fileItem)
{
- auto it = m_contextAddons.find(id);
- if (it != m_contextAddons.end())
- return it->second;
- return ContextItemAddonPtr();
+ if (menuItem.GetLabel().empty() || !root.IsParentOf(menuItem))
+ return false;
+
+ if (menuItem.IsGroup())
+ return std::any_of(m_items.begin(), m_items.end(),
+ [&](const Item& kv){ return menuItem.IsParentOf(kv.second) && kv.second.IsVisible(fileItem); });
+
+ return menuItem.IsVisible(fileItem);
}
-void CContextMenuManager::AddVisibleItems(const CFileItemPtr& item, CContextButtons& list, const std::string& parent /* = "" */)
+void CContextMenuManager::AddVisibleItems(
+ const CFileItemPtr& item, CContextButtons& list, const CContextMenuItem& root /* = CContextMenuItem::MAIN */)
{
if (!item)
return;
- for (const auto& kv : m_contextAddons)
+ const int initialSize = list.size();
+
+ for (const auto& kv : m_items)
+ if (IsVisible(kv.second, root, item))
+ list.push_back(std::make_pair(kv.first, kv.second.GetLabel()));
+
+ if (root == MAIN || root == MANAGE)
{
- if (kv.second->GetParent() == parent && kv.second->IsVisible(item))
- list.push_back(std::make_pair(kv.first, kv.second->GetLabel()));
+ std::stable_sort(list.begin() + initialSize, list.end(),
+ [](const std::pair<int, std::string>& lhs, const std::pair<int, std::string>& rhs)
+ {
+ return lhs.second < rhs.second;
+ }
+ );
}
}
-bool CContextMenuManager::Execute(unsigned int id, const CFileItemPtr& item)
+
+bool CContextMenuManager::OnClick(unsigned int id, const CFileItemPtr& item)
{
if (!item)
return false;
- const ContextItemAddonPtr addon = GetContextItemByID(id);
- if (!addon || !addon->IsVisible(item))
+ auto it = std::find_if(m_items.begin(), m_items.end(),
+ [id](const Item& kv){ return kv.first == id; });
+ if (it == m_items.end())
+ {
+ CLog::Log(LOGERROR, "CContextMenuManager: unknown button id '%u'", id);
return false;
+ }
+
+ CContextMenuItem menuItem = it->second;
+ if (menuItem.IsGroup())
+ {
+ CLog::Log(LOGDEBUG, "CContextMenuManager: showing group '%s'", menuItem.ToString().c_str());
+ CContextButtons choices;
+ AddVisibleItems(item, choices, menuItem);
+ if (choices.empty())
+ {
+ CLog::Log(LOGERROR, "CContextMenuManager: no items in group '%s'", menuItem.ToString().c_str());
+ return false;
+ }
+ int choice = CGUIDialogContextMenu::ShowAndGetChoice(choices);
+ if (choice == -1)
+ return false;
+
+ return OnClick(choice, item);
+ }
- LanguageInvokerPtr invoker(new CContextItemAddonInvoker(&g_pythonParser, item));
- return (CScriptInvocationManager::Get().ExecuteAsync(addon->LibPath(), invoker, addon) != -1);
+ return menuItem.Execute(item);
}
diff --git a/xbmc/ContextMenuManager.h b/xbmc/ContextMenuManager.h
index 2dff9dce87..84d135036b 100644
--- a/xbmc/ContextMenuManager.h
+++ b/xbmc/ContextMenuManager.h
@@ -19,33 +19,37 @@
*
*/
-#include <map>
-#include "addons/ContextItemAddon.h"
+#include <vector>
+#include "ContextMenuItem.h"
+#include "addons/ContextMenuAddon.h"
#include "dialogs/GUIDialogContextMenu.h"
-#define CONTEXT_MENU_GROUP_MANAGE "kodi.core.manage"
class CContextMenuManager
{
public:
+ static const CContextMenuItem MAIN;
+ static const CContextMenuItem MANAGE;
+
static CContextMenuManager& Get();
/*!
- * \brief Executes a context menu item.
- * \param id - id of the context button to execute.
- * \param item - the currently selected item.
- * \return true if executed successfully, false otherwise
+ * \param id - id of the context button clicked on.
+ * \param item - the selected file item.
+ * \return true on success, otherwise false.
*/
- bool Execute(unsigned int id, const CFileItemPtr& item);
+ bool OnClick(unsigned int id, const CFileItemPtr& item);
/*!
* \brief Adds all registered context item to the list.
* \param item - the currently selected item.
* \param list - the context menu.
- * \param parent - the ID of the context menu. Empty string if the root menu.
- * CONTEXT_MENU_GROUP_MANAGE if the 'manage' submenu.
+ * \param root - the context menu responsible for this call.
*/
- void AddVisibleItems(const CFileItemPtr& item, CContextButtons& list, const std::string& parent = "");
+ void AddVisibleItems(
+ const CFileItemPtr& item,
+ CContextButtons& list,
+ const CContextMenuItem& root = MAIN);
/*!
* \brief Adds a context item to this manager.
@@ -65,14 +69,11 @@ private:
virtual ~CContextMenuManager() {}
void Init();
+ bool IsVisible(
+ const CContextMenuItem& menuItem,
+ const CContextMenuItem& root,
+ const CFileItemPtr& fileItem);
- /*!
- * \brief Get a context menu item by its assigned id.
- * \param id - the button id of the context item.
- * \return the addon or NULL if no item with given id is registered.
- */
- ADDON::ContextItemAddonPtr GetContextItemByID(const unsigned int id);
-
- std::map<unsigned int, ADDON::ContextItemAddonPtr> m_contextAddons;
- unsigned int m_iCurrentContextId;
+ std::vector<std::pair<unsigned int, CContextMenuItem>> m_items;
+ unsigned int m_nextButtonId;
};
diff --git a/xbmc/Makefile.in b/xbmc/Makefile.in
index 265920d361..e73a1d467d 100644
--- a/xbmc/Makefile.in
+++ b/xbmc/Makefile.in
@@ -4,6 +4,7 @@ SRCS=Application.cpp \
Autorun.cpp \
AutoSwitch.cpp \
BackgroundInfoLoader.cpp \
+ ContextMenuItem.cpp \
ContextMenuManager.cpp \
CompileInfo.cpp \
CueDocument.cpp \
diff --git a/xbmc/addons/Addon.cpp b/xbmc/addons/Addon.cpp
index 69859abc65..a3b66cd1a5 100644
--- a/xbmc/addons/Addon.cpp
+++ b/xbmc/addons/Addon.cpp
@@ -646,7 +646,7 @@ void OnEnabled(const std::string& id)
std::static_pointer_cast<CService>(addon)->Start();
if (CAddonMgr::Get().GetAddon(id, addon, ADDON_CONTEXT_ITEM))
- CContextMenuManager::Get().Register(std::static_pointer_cast<CContextItemAddon>(addon));
+ CContextMenuManager::Get().Register(std::static_pointer_cast<CContextMenuAddon>(addon));
}
void OnDisabled(const std::string& id)
@@ -660,7 +660,7 @@ void OnDisabled(const std::string& id)
std::static_pointer_cast<CService>(addon)->Stop();
if (CAddonMgr::Get().GetAddon(id, addon, ADDON_CONTEXT_ITEM, false))
- CContextMenuManager::Get().Unregister(std::static_pointer_cast<CContextItemAddon>(addon));
+ CContextMenuManager::Get().Unregister(std::static_pointer_cast<CContextMenuAddon>(addon));
}
void OnPreInstall(const AddonPtr& addon)
@@ -672,7 +672,7 @@ void OnPreInstall(const AddonPtr& addon)
std::static_pointer_cast<CService>(localAddon)->Stop();
if (CAddonMgr::Get().GetAddon(addon->ID(), localAddon, ADDON_CONTEXT_ITEM))
- CContextMenuManager::Get().Unregister(std::static_pointer_cast<CContextItemAddon>(localAddon));
+ CContextMenuManager::Get().Unregister(std::static_pointer_cast<CContextMenuAddon>(localAddon));
//Fallback to the pre-install callback in the addon.
//BUG: If primary extension point have changed we're calling the wrong method.
@@ -686,7 +686,7 @@ void OnPostInstall(const AddonPtr& addon, bool update, bool modal)
std::static_pointer_cast<CService>(localAddon)->Start();
if (CAddonMgr::Get().GetAddon(addon->ID(), localAddon, ADDON_CONTEXT_ITEM))
- CContextMenuManager::Get().Register(std::static_pointer_cast<CContextItemAddon>(localAddon));
+ CContextMenuManager::Get().Register(std::static_pointer_cast<CContextMenuAddon>(localAddon));
addon->OnPostInstall(update, modal);
}
@@ -698,7 +698,7 @@ void OnPreUnInstall(const AddonPtr& addon)
std::static_pointer_cast<CService>(localAddon)->Stop();
if (CAddonMgr::Get().GetAddon(addon->ID(), localAddon, ADDON_CONTEXT_ITEM))
- CContextMenuManager::Get().Unregister(std::static_pointer_cast<CContextItemAddon>(localAddon));
+ CContextMenuManager::Get().Unregister(std::static_pointer_cast<CContextMenuAddon>(localAddon));
addon->OnPreUnInstall();
}
diff --git a/xbmc/addons/AddonManager.cpp b/xbmc/addons/AddonManager.cpp
index 4abeb2c812..9b4aede1f1 100644
--- a/xbmc/addons/AddonManager.cpp
+++ b/xbmc/addons/AddonManager.cpp
@@ -53,7 +53,7 @@
#include "Repository.h"
#include "Skin.h"
#include "Service.h"
-#include "ContextItemAddon.h"
+#include "ContextMenuAddon.h"
#include "Util.h"
#include "addons/Webinterface.h"
@@ -193,7 +193,7 @@ AddonPtr CAddonMgr::Factory(const cp_extension_t *props)
case ADDON_REPOSITORY:
return AddonPtr(new CRepository(props));
case ADDON_CONTEXT_ITEM:
- return AddonPtr(new CContextItemAddon(props));
+ return AddonPtr(new CContextMenuAddon(props));
default:
break;
}
@@ -871,7 +871,7 @@ AddonPtr CAddonMgr::AddonFromProps(AddonProps& addonProps)
case ADDON_REPOSITORY:
return AddonPtr(new CRepository(addonProps));
case ADDON_CONTEXT_ITEM:
- return AddonPtr(new CContextItemAddon(addonProps));
+ return AddonPtr(new CContextMenuAddon(addonProps));
default:
break;
}
diff --git a/xbmc/addons/ContextItemAddon.cpp b/xbmc/addons/ContextItemAddon.cpp
deleted file mode 100644
index c3b1289846..0000000000
--- a/xbmc/addons/ContextItemAddon.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Team XBMC
- * http://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 "ContextItemAddon.h"
-#include "AddonManager.h"
-#include "ContextMenuManager.h"
-#include "GUIInfoManager.h"
-#include "interfaces/info/InfoBool.h"
-#include "utils/StringUtils.h"
-#include <boost/lexical_cast.hpp>
-
-using namespace std;
-
-namespace ADDON
-{
-
-CContextItemAddon::CContextItemAddon(const AddonProps &props)
- : CAddon(props)
-{ }
-
-CContextItemAddon::~CContextItemAddon()
-{ }
-
-CContextItemAddon::CContextItemAddon(const cp_extension_t *ext)
- : CAddon(ext)
-{
- ELEMENTS items;
- if (CAddonMgr::Get().GetExtElements(ext->configuration, "item", items))
- {
- cp_cfg_element_t *item = items[0];
-
- m_label = CAddonMgr::Get().GetExtValue(item, "label");
- m_parent = CAddonMgr::Get().GetExtValue(item, "parent");
-
- string visible = CAddonMgr::Get().GetExtValue(item, "visible");
- if (visible.empty())
- visible = "false";
-
- m_visCondition = g_infoManager.Register(visible, 0);
- }
-}
-
-std::string CContextItemAddon::GetLabel()
-{
- if (StringUtils::IsNaturalNumber(m_label))
- return GetString(boost::lexical_cast<int>(m_label.c_str()));
- return m_label;
-}
-
-bool CContextItemAddon::IsVisible(const CFileItemPtr& item) const
-{
- return item && m_visCondition && m_visCondition->Get(item.get());
-}
-
-}
diff --git a/xbmc/addons/ContextItemAddon.h b/xbmc/addons/ContextItemAddon.h
deleted file mode 100644
index 49fa909a5b..0000000000
--- a/xbmc/addons/ContextItemAddon.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#pragma once
-/*
- * Copyright (C) 2013-2015 Team XBMC
- * http://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 <list>
-#include <memory>
-#include "Addon.h"
-
-class CFileItem;
-typedef std::shared_ptr<CFileItem> CFileItemPtr;
-
-namespace INFO
-{
- class InfoBool;
- typedef std::shared_ptr<InfoBool> InfoPtr;
-}
-
-namespace ADDON
-{
- class CContextItemAddon : public CAddon
- {
- public:
- CContextItemAddon(const cp_extension_t *ext);
- CContextItemAddon(const AddonProps &props);
- virtual ~CContextItemAddon();
-
- std::string GetLabel();
-
- /*!
- * \brief Get the parent category of this context item.
- *
- * \details Returns empty string if at root level or
- * CONTEXT_MENU_GROUP_MANAGE when it should be in the 'manage' submenu.
- */
- const std::string& GetParent() const { return m_parent; }
-
- /*!
- * \brief Returns true if this contex menu should be visible for given item.
- */
- bool IsVisible(const CFileItemPtr& item) const;
-
- private:
- std::string m_label;
- std::string m_parent;
- INFO::InfoPtr m_visCondition;
- };
-
- typedef std::shared_ptr<CContextItemAddon> ContextItemAddonPtr;
-}
diff --git a/xbmc/addons/ContextMenuAddon.cpp b/xbmc/addons/ContextMenuAddon.cpp
new file mode 100644
index 0000000000..f9fedd09b7
--- /dev/null
+++ b/xbmc/addons/ContextMenuAddon.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2013-2015 Team XBMC
+ * http://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 "ContextMenuAddon.h"
+#include "AddonManager.h"
+#include "ContextMenuManager.h"
+#include "ContextMenuItem.h"
+#include "GUIInfoManager.h"
+#include "interfaces/info/InfoBool.h"
+#include "utils/StringUtils.h"
+#include "utils/URIUtils.h"
+#include <sstream>
+
+
+namespace ADDON
+{
+
+CContextMenuAddon::CContextMenuAddon(const AddonProps &props)
+ : CAddon(props)
+{ }
+
+CContextMenuAddon::~CContextMenuAddon()
+{ }
+
+CContextMenuAddon::CContextMenuAddon(const cp_extension_t *ext)
+ : CAddon(ext)
+{
+ cp_cfg_element_t* menu = CAddonMgr::Get().GetExtElement(ext->configuration, "menu");
+ if (menu)
+ {
+ int tmp = 0;
+ ParseMenu(menu, "", tmp);
+ }
+ else
+ {
+ //backwards compatibility. add first item definition
+ ELEMENTS items;
+ if (CAddonMgr::Get().GetExtElements(ext->configuration, "item", items))
+ {
+ cp_cfg_element_t *item = items[0];
+
+ std::string visCondition = CAddonMgr::Get().GetExtValue(item, "visible");
+ if (visCondition.empty())
+ visCondition = "false";
+
+ std::string parent = CAddonMgr::Get().GetExtValue(item, "parent") == "kodi.core.manage"
+ ? CContextMenuManager::MANAGE.m_groupId : CContextMenuManager::MAIN.m_groupId;
+
+ CContextMenuItem menuItem = CContextMenuItem::CreateItem(
+ CAddonMgr::Get().GetExtValue(item, "label"),
+ parent,
+ LibPath(),
+ g_infoManager.Register(visCondition, 0));
+
+ m_items.push_back(menuItem);
+ }
+ }
+}
+
+void CContextMenuAddon::ParseMenu(cp_cfg_element_t* elem, const std::string& parent, int& anonGroupCount)
+{
+ auto menuLabel = CAddonMgr::Get().GetExtValue(elem, "label");
+ auto menuId = CAddonMgr::Get().GetExtValue(elem, "@id");
+
+ if (menuId.empty())
+ {
+ //anonymous group. create a new unique internal id.
+ std::stringstream ss;
+ ss << ID() << ++anonGroupCount;
+ menuId = ss.str();
+ }
+
+ m_items.push_back(CContextMenuItem::CreateGroup(menuLabel, parent, menuId));
+
+ ELEMENTS subMenus;
+ if (CAddonMgr::Get().GetExtElements(elem, "menu", subMenus))
+ for (const auto& subMenu : subMenus)
+ ParseMenu(subMenu, menuId, anonGroupCount);
+
+ ELEMENTS items;
+ if (CAddonMgr::Get().GetExtElements(elem, "item", items))
+ {
+ for (const auto& item : items)
+ {
+ auto label = CAddonMgr::Get().GetExtValue(item, "label");
+ auto visCondition = CAddonMgr::Get().GetExtValue(item, "visible");
+ auto library = CAddonMgr::Get().GetExtValue(item, "@library");
+
+ if (!label.empty() && !library.empty() && !visCondition.empty())
+ {
+ auto menu = CContextMenuItem::CreateItem(
+ label,
+ menuId,
+ URIUtils::AddFileToFolder(Path(), library),
+ g_infoManager.Register(visCondition, 0));
+
+ m_items.push_back(menu);
+ }
+ }
+ }
+}
+
+std::vector<CContextMenuItem> CContextMenuAddon::GetItems()
+{
+ //Return a copy which owns `this`
+ std::vector<CContextMenuItem> ret = m_items;
+ for (CContextMenuItem& menuItem : ret)
+ menuItem.m_addon = this->shared_from_this();
+ return ret;
+}
+
+}
diff --git a/xbmc/addons/ContextMenuAddon.h b/xbmc/addons/ContextMenuAddon.h
new file mode 100644
index 0000000000..887a9fc310
--- /dev/null
+++ b/xbmc/addons/ContextMenuAddon.h
@@ -0,0 +1,47 @@
+#pragma once
+/*
+ * Copyright (C) 2013-2015 Team XBMC
+ * http://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 <list>
+#include <memory>
+#include "Addon.h"
+
+class CContextMenuItem;
+typedef struct cp_cfg_element_t cp_cfg_element_t;
+
+
+namespace ADDON
+{
+ class CContextMenuAddon : public CAddon
+ {
+ public:
+ CContextMenuAddon(const cp_extension_t *ext);
+ CContextMenuAddon(const AddonProps &props);
+ virtual ~CContextMenuAddon();
+
+ std::vector<CContextMenuItem> GetItems();
+
+ private:
+ void ParseMenu(cp_cfg_element_t* elem, const std::string& parent, int& anonGroupCount);
+ std::vector<CContextMenuItem> m_items;
+ };
+
+ typedef std::shared_ptr<CContextMenuAddon> ContextItemAddonPtr;
+}
diff --git a/xbmc/addons/Makefile b/xbmc/addons/Makefile
index d8c0860880..29926f27ea 100644
--- a/xbmc/addons/Makefile
+++ b/xbmc/addons/Makefile
@@ -11,7 +11,7 @@ SRCS=Addon.cpp \
AddonStatusHandler.cpp \
AddonVersion.cpp \
AudioEncoder.cpp \
- ContextItemAddon.cpp \
+ ContextMenuAddon.cpp \
AudioDecoder.cpp \
GUIDialogAddonInfo.cpp \
GUIDialogAddonSettings.cpp \
diff --git a/xbmc/dialogs/GUIDialogFavourites.cpp b/xbmc/dialogs/GUIDialogFavourites.cpp
index f92fe7565f..d49b774b10 100644
--- a/xbmc/dialogs/GUIDialogFavourites.cpp
+++ b/xbmc/dialogs/GUIDialogFavourites.cpp
@@ -151,7 +151,7 @@ void CGUIDialogFavourites::OnPopupMenu(int item)
else if (button == 5)
OnSetThumb(item);
else if (button >= CONTEXT_BUTTON_FIRST_ADDON)
- CContextMenuManager::Get().Execute(button, itemPtr);
+ CContextMenuManager::Get().OnClick(button, itemPtr);
}
void CGUIDialogFavourites::OnMoveItem(int item, int amount)
diff --git a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp
index 07ebd764d3..e9e1969a74 100644
--- a/xbmc/video/dialogs/GUIDialogVideoInfo.cpp
+++ b/xbmc/video/dialogs/GUIDialogVideoInfo.cpp
@@ -1006,7 +1006,7 @@ int CGUIDialogVideoInfo::ManageVideoItem(const CFileItemPtr &item)
buttons.Add(CONTEXT_BUTTON_DELETE, 646);
- CContextMenuManager::Get().AddVisibleItems(item, buttons, CONTEXT_MENU_GROUP_MANAGE);
+ CContextMenuManager::Get().AddVisibleItems(item, buttons, CContextMenuManager::MANAGE);
bool result = false;
int button = CGUIDialogContextMenu::ShowAndGetChoice(buttons);
@@ -1070,7 +1070,7 @@ int CGUIDialogVideoInfo::ManageVideoItem(const CFileItemPtr &item)
break;
default:
- result = CContextMenuManager::Get().Execute(button, item);
+ result = CContextMenuManager::Get().OnClick(button, item);
break;
}
}
diff --git a/xbmc/windows/GUIMediaWindow.cpp b/xbmc/windows/GUIMediaWindow.cpp
index 91bb3aa335..f2d870c86d 100644
--- a/xbmc/windows/GUIMediaWindow.cpp
+++ b/xbmc/windows/GUIMediaWindow.cpp
@@ -1617,7 +1617,7 @@ bool CGUIMediaWindow::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
break;
}
if (button >= CONTEXT_BUTTON_FIRST_ADDON)
- return CContextMenuManager::Get().Execute(button, m_vecItems->Get(itemNumber));
+ return CContextMenuManager::Get().OnClick(button, m_vecItems->Get(itemNumber));
return false;
}
diff --git a/xbmc/windows/GUIWindowLoginScreen.cpp b/xbmc/windows/GUIWindowLoginScreen.cpp
index 00e39450c0..80e9dd3209 100644
--- a/xbmc/windows/GUIWindowLoginScreen.cpp
+++ b/xbmc/windows/GUIWindowLoginScreen.cpp
@@ -257,7 +257,7 @@ bool CGUIWindowLoginScreen::OnPopupMenu(int iItem)
m_vecItems->Get(iItem)->Select(bSelect);
if (choice >= CONTEXT_BUTTON_FIRST_ADDON)
- return CContextMenuManager::Get().Execute(choice, pItem);
+ return CContextMenuManager::Get().OnClick(choice, pItem);
return false;
}