2 * Copyright (C) 2012-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "GUIDialogPVRChannelManager.h"
12 #include "FileItemList.h"
13 #include "GUIPassword.h"
14 #include "ServiceBroker.h"
15 #include "TextureCache.h"
16 #include "dialogs/GUIDialogFileBrowser.h"
17 #include "dialogs/GUIDialogProgress.h"
18 #include "dialogs/GUIDialogSelect.h"
19 #include "dialogs/GUIDialogYesNo.h"
20 #include "guilib/GUIComponent.h"
21 #include "guilib/GUIEditControl.h"
22 #include "guilib/GUIMessage.h"
23 #include "guilib/GUISpinControlEx.h"
24 #include "guilib/GUIWindowManager.h"
25 #include "guilib/LocalizeStrings.h"
26 #include "input/actions/Action.h"
27 #include "input/actions/ActionIDs.h"
28 #include "messaging/helpers/DialogOKHelper.h"
29 #include "profiles/ProfileManager.h"
30 #include "pvr/PVRManager.h"
31 #include "pvr/addons/PVRClient.h"
32 #include "pvr/addons/PVRClients.h"
33 #include "pvr/channels/PVRChannel.h"
34 #include "pvr/channels/PVRChannelGroupMember.h"
35 #include "pvr/channels/PVRChannelGroups.h"
36 #include "pvr/channels/PVRChannelGroupsContainer.h"
37 #include "pvr/dialogs/GUIDialogPVRGroupManager.h"
38 #include "pvr/guilib/PVRGUIActionsParentalControl.h"
39 #include "settings/Settings.h"
40 #include "settings/SettingsComponent.h"
41 #include "storage/MediaManager.h"
42 #include "utils/StringUtils.h"
43 #include "utils/Variant.h"
52 #define BUTTON_APPLY 5
53 #define BUTTON_CANCEL 6
54 #define RADIOBUTTON_ACTIVE 7
56 #define BUTTON_CHANNEL_LOGO 9
57 #define IMAGE_CHANNEL_LOGO 10
58 #define RADIOBUTTON_USEEPG 12
59 #define SPIN_EPGSOURCE_SELECTION 13
60 #define RADIOBUTTON_PARENTAL_LOCK 14
61 #define CONTROL_LIST_CHANNELS 20
62 #define BUTTON_GROUP_MANAGER 30
63 #define BUTTON_NEW_CHANNEL 31
64 #define BUTTON_RADIO_TV 34
65 #define BUTTON_REFRESH_LOGOS 35
69 constexpr const char* LABEL_CHANNEL_DISABLED
= "0";
71 // Note: strings must not be changed; they are part of the public skinning API for this dialog.
72 constexpr const char* PROPERTY_CHANNEL_NUMBER
= "Number";
73 constexpr const char* PROPERTY_CHANNEL_ENABLED
= "ActiveChannel";
74 constexpr const char* PROPERTY_CHANNEL_USER_SET_HIDDEN
= "UserSetHidden";
75 constexpr const char* PROPERTY_CHANNEL_USER_SET_NAME
= "UserSetName";
76 constexpr const char* PROPERTY_CHANNEL_LOCKED
= "ParentalLocked";
77 constexpr const char* PROPERTY_CHANNEL_ICON
= "Icon";
78 constexpr const char* PROPERTY_CHANNEL_CUSTOM_ICON
= "UserSetIcon";
79 constexpr const char* PROPERTY_CHANNEL_NAME
= "Name";
80 constexpr const char* PROPERTY_CHANNEL_EPG_ENABLED
= "UseEPG";
81 constexpr const char* PROPERTY_CHANNEL_EPG_SOURCE
= "EPGSource";
82 constexpr const char* PROPERTY_CLIENT_SUPPORTS_SETTINGS
= "SupportsSettings";
83 constexpr const char* PROPERTY_CLIENT_NAME
= "ClientName";
84 constexpr const char* PROPERTY_ITEM_CHANGED
= "Changed";
89 using namespace KODI::MESSAGING
;
91 CGUIDialogPVRChannelManager::CGUIDialogPVRChannelManager() :
92 CGUIDialog(WINDOW_DIALOG_PVR_CHANNEL_MANAGER
, "DialogPVRChannelManager.xml"),
93 m_channelItems(new CFileItemList
)
98 CGUIDialogPVRChannelManager::~CGUIDialogPVRChannelManager()
100 delete m_channelItems
;
103 bool CGUIDialogPVRChannelManager::OnActionMove(const CAction
& action
)
106 int iActionId
= action
.GetID();
108 if (GetFocusedControlID() == CONTROL_LIST_CHANNELS
)
110 if (iActionId
== ACTION_MOUSE_MOVE
)
112 int iSelected
= m_viewControl
.GetSelectedItem();
113 if (m_iSelected
< iSelected
)
115 iActionId
= ACTION_MOVE_DOWN
;
117 else if (m_iSelected
> iSelected
)
119 iActionId
= ACTION_MOVE_UP
;
127 if (iActionId
== ACTION_MOVE_DOWN
|| iActionId
== ACTION_MOVE_UP
||
128 iActionId
== ACTION_PAGE_DOWN
|| iActionId
== ACTION_PAGE_UP
||
129 iActionId
== ACTION_FIRST_PAGE
|| iActionId
== ACTION_LAST_PAGE
)
131 CGUIDialog::OnAction(action
);
132 int iSelected
= m_viewControl
.GetSelectedItem();
137 if (iSelected
!= m_iSelected
)
139 m_iSelected
= iSelected
;
140 SetData(m_iSelected
);
145 bool bMoveUp
= iActionId
== ACTION_PAGE_UP
|| iActionId
== ACTION_MOVE_UP
|| iActionId
== ACTION_FIRST_PAGE
;
146 unsigned int iLines
= bMoveUp
? abs(m_iSelected
- iSelected
) : 1;
147 bool bOutOfBounds
= bMoveUp
? m_iSelected
<= 0 : m_iSelected
>= m_channelItems
->Size() - 1;
151 iLines
= m_channelItems
->Size() - 1;
153 for (unsigned int iLine
= 0; iLine
< iLines
; ++iLine
)
155 unsigned int iNewSelect
= bMoveUp
? m_iSelected
- 1 : m_iSelected
+ 1;
157 const CFileItemPtr newItem
= m_channelItems
->Get(iNewSelect
);
158 const std::string number
= newItem
->GetProperty(PROPERTY_CHANNEL_NUMBER
).asString();
159 if (number
!= LABEL_CHANNEL_DISABLED
)
161 // Swap channel numbers
162 const CFileItemPtr item
= m_channelItems
->Get(m_iSelected
);
163 newItem
->SetProperty(PROPERTY_CHANNEL_NUMBER
,
164 item
->GetProperty(PROPERTY_CHANNEL_NUMBER
));
165 SetItemChanged(newItem
);
166 item
->SetProperty(PROPERTY_CHANNEL_NUMBER
, number
);
167 SetItemChanged(item
);
171 m_channelItems
->Swap(iNewSelect
, m_iSelected
);
172 m_iSelected
= iNewSelect
;
175 m_viewControl
.SetItems(*m_channelItems
);
176 m_viewControl
.SetSelectedItem(m_iSelected
);
184 bool CGUIDialogPVRChannelManager::OnAction(const CAction
& action
)
186 return OnActionMove(action
) ||
187 CGUIDialog::OnAction(action
);
190 void CGUIDialogPVRChannelManager::OnInitWindow()
192 CGUIDialog::OnInitWindow();
195 m_bMovingMode
= false;
196 m_bAllowNewChannel
= false;
198 EnableChannelOptions(false);
199 CONTROL_DISABLE(BUTTON_APPLY
);
201 // prevent resorting channels if backend channel numbers or backend channel order shall be used
202 const std::shared_ptr
<CSettings
> settings
= CServiceBroker::GetSettingsComponent()->GetSettings();
203 m_bAllowRenumber
= !settings
->GetBool(CSettings::SETTING_PVRMANAGER_USEBACKENDCHANNELNUMBERS
);
205 m_bAllowRenumber
&& !settings
->GetBool(CSettings::SETTING_PVRMANAGER_BACKENDCHANNELORDER
);
209 if (m_initialSelection
)
211 // set initial selection
212 const std::shared_ptr
<const CPVRChannel
> channel
= m_initialSelection
->GetPVRChannelInfoTag();
213 for (int i
= 0; i
< m_channelItems
->Size(); ++i
)
215 if (m_channelItems
->Get(i
)->GetPVRChannelInfoTag() == channel
)
218 m_viewControl
.SetSelectedItem(m_iSelected
);
222 m_initialSelection
.reset();
224 SetData(m_iSelected
);
227 void CGUIDialogPVRChannelManager::OnDeinitWindow(int nextWindowID
)
231 CGUIDialog::OnDeinitWindow(nextWindowID
);
234 void CGUIDialogPVRChannelManager::SetRadio(bool bIsRadio
)
236 m_bIsRadio
= bIsRadio
;
237 SetProperty("IsRadio", m_bIsRadio
? "true" : "");
240 void CGUIDialogPVRChannelManager::Open(const std::shared_ptr
<CFileItem
>& initialSelection
)
242 m_initialSelection
= initialSelection
;
246 bool CGUIDialogPVRChannelManager::OnClickListChannels(const CGUIMessage
& message
)
250 int iAction
= message
.GetParam1();
251 int iItem
= m_viewControl
.GetSelectedItem();
253 /* Check file item is in list range and get his pointer */
254 if (iItem
< 0 || iItem
>= m_channelItems
->Size()) return true;
256 /* Process actions */
257 if (iAction
== ACTION_SELECT_ITEM
|| iAction
== ACTION_CONTEXT_MENU
|| iAction
== ACTION_MOUSE_RIGHT_CLICK
)
259 /* Show Contextmenu */
267 CFileItemPtr pItem
= m_channelItems
->Get(m_iSelected
);
270 pItem
->Select(false);
271 m_bMovingMode
= false;
272 SetItemChanged(pItem
);
280 bool CGUIDialogPVRChannelManager::OnClickButtonOK()
287 bool CGUIDialogPVRChannelManager::OnClickButtonApply()
293 bool CGUIDialogPVRChannelManager::OnClickButtonCancel()
299 bool CGUIDialogPVRChannelManager::OnClickButtonRadioTV()
304 m_bMovingMode
= false;
305 m_bAllowNewChannel
= false;
306 m_bIsRadio
= !m_bIsRadio
;
307 SetProperty("IsRadio", m_bIsRadio
? "true" : "");
312 bool CGUIDialogPVRChannelManager::OnClickButtonRadioActive()
314 CGUIMessage
msg(GUI_MSG_IS_SELECTED
, GetID(), RADIOBUTTON_ACTIVE
);
317 CFileItemPtr pItem
= m_channelItems
->Get(m_iSelected
);
320 const bool selected
= (msg
.GetParam1() == 1);
321 if (pItem
->GetProperty(PROPERTY_CHANNEL_ENABLED
).asBoolean() != selected
)
323 pItem
->SetProperty(PROPERTY_CHANNEL_ENABLED
, selected
);
324 pItem
->SetProperty(PROPERTY_CHANNEL_USER_SET_HIDDEN
, true);
325 SetItemChanged(pItem
);
335 bool CGUIDialogPVRChannelManager::OnClickButtonRadioParentalLocked()
337 CGUIMessage
msg(GUI_MSG_IS_SELECTED
, GetID(), RADIOBUTTON_PARENTAL_LOCK
);
341 bool selected(msg
.GetParam1() == 1);
344 if (CServiceBroker::GetPVRManager().Get
<PVR::GUI::Parental
>().CheckParentalPIN() !=
345 ParentalCheckResult::SUCCESS
)
346 { // failed - reset to previous
347 SET_CONTROL_SELECTED(GetID(), RADIOBUTTON_PARENTAL_LOCK
, !selected
);
351 CFileItemPtr pItem
= m_channelItems
->Get(m_iSelected
);
354 if (pItem
->GetProperty(PROPERTY_CHANNEL_LOCKED
).asBoolean() != selected
)
356 pItem
->SetProperty(PROPERTY_CHANNEL_LOCKED
, selected
);
357 SetItemChanged(pItem
);
366 bool CGUIDialogPVRChannelManager::OnClickButtonEditName()
368 CGUIMessage
msg(GUI_MSG_ITEM_SELECTED
, GetID(), EDIT_NAME
);
371 CFileItemPtr pItem
= m_channelItems
->Get(m_iSelected
);
374 const std::string
& label
= msg
.GetLabel();
375 if (pItem
->GetProperty(PROPERTY_CHANNEL_NAME
).asString() != label
)
377 pItem
->SetProperty(PROPERTY_CHANNEL_NAME
, label
);
378 pItem
->SetProperty(PROPERTY_CHANNEL_USER_SET_NAME
, true);
379 SetItemChanged(pItem
);
388 bool CGUIDialogPVRChannelManager::OnClickButtonChannelLogo()
390 CFileItemPtr pItem
= m_channelItems
->Get(m_iSelected
);
394 const std::shared_ptr
<CProfileManager
> profileManager
= CServiceBroker::GetSettingsComponent()->GetProfileManager();
396 if (profileManager
->GetCurrentProfile().canWriteSources() && !g_passwordManager
.IsProfileLockUnlocked())
399 // setup our thumb list
402 // add the current thumb, if available
403 if (!pItem
->GetProperty(PROPERTY_CHANNEL_ICON
).asString().empty())
405 CFileItemPtr
current(new CFileItem("thumb://Current", false));
406 current
->SetArt("thumb", pItem
->GetPVRChannelInfoTag()->IconPath());
407 current
->SetLabel(g_localizeStrings
.Get(19282));
410 else if (pItem
->HasArt("thumb"))
411 { // already have a thumb that the share doesn't know about - must be a local one, so we mayaswell reuse it.
412 CFileItemPtr
current(new CFileItem("thumb://Current", false));
413 current
->SetArt("thumb", pItem
->GetArt("thumb"));
414 current
->SetLabel(g_localizeStrings
.Get(19282));
418 // and add a "no thumb" entry as well
419 CFileItemPtr
nothumb(new CFileItem("thumb://None", false));
420 nothumb
->SetArt("icon", pItem
->GetArt("icon"));
421 nothumb
->SetLabel(g_localizeStrings
.Get(19283));
424 std::string strThumb
;
426 const std::shared_ptr
<CSettings
> settings
= CServiceBroker::GetSettingsComponent()->GetSettings();
427 if (settings
->GetString(CSettings::SETTING_PVRMENU_ICONPATH
) != "")
430 share1
.strPath
= settings
->GetString(CSettings::SETTING_PVRMENU_ICONPATH
);
431 share1
.strName
= g_localizeStrings
.Get(19066);
432 shares
.push_back(share1
);
434 CServiceBroker::GetMediaManager().GetLocalDrives(shares
);
435 if (!CGUIDialogFileBrowser::ShowAndGetImage(items
, shares
, g_localizeStrings
.Get(19285), strThumb
, NULL
, 19285))
438 if (strThumb
== "thumb://Current")
441 if (strThumb
== "thumb://None")
444 if (pItem
->GetProperty(PROPERTY_CHANNEL_ICON
).asString() != strThumb
)
446 pItem
->SetProperty(PROPERTY_CHANNEL_ICON
, strThumb
);
447 pItem
->SetProperty(PROPERTY_CHANNEL_CUSTOM_ICON
, true);
448 SetItemChanged(pItem
);
454 bool CGUIDialogPVRChannelManager::OnClickButtonUseEPG()
456 CGUIMessage
msg(GUI_MSG_IS_SELECTED
, GetID(), RADIOBUTTON_USEEPG
);
459 CFileItemPtr pItem
= m_channelItems
->Get(m_iSelected
);
462 const bool selected
= (msg
.GetParam1() == 1);
463 if (pItem
->GetProperty(PROPERTY_CHANNEL_EPG_ENABLED
).asBoolean() != selected
)
465 pItem
->SetProperty(PROPERTY_CHANNEL_EPG_ENABLED
, selected
);
466 SetItemChanged(pItem
);
475 bool CGUIDialogPVRChannelManager::OnClickEPGSourceSpin()
477 //! @todo Add EPG scraper support
479 // CGUISpinControlEx* pSpin = static_cast<CGUISpinControlEx*>(GetControl(SPIN_EPGSOURCE_SELECTION));
482 // CFileItemPtr pItem = m_channelItems->Get(m_iSelected);
485 // if (pItem->GetProperty(PROPERTY_CHANNEL_EPG_SOURCE).asInteger() != 0)
487 // pItem->SetProperty(PROPERTY_CHANNEL_EPG_SOURCE, static_cast<int>(0));
488 // SetItemChanged(pItem);
495 bool CGUIDialogPVRChannelManager::OnClickButtonGroupManager()
499 /* Load group manager dialog */
500 CGUIDialogPVRGroupManager
* pDlgInfo
= CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogPVRGroupManager
>(WINDOW_DIALOG_PVR_GROUP_MANAGER
);
504 pDlgInfo
->SetRadio(m_bIsRadio
);
506 /* Open dialog window */
513 bool CGUIDialogPVRChannelManager::OnClickButtonNewChannel()
518 if (m_clientsWithSettingsList
.size() > 1)
520 CGUIDialogSelect
* pDlgSelect
= CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogSelect
>(WINDOW_DIALOG_SELECT
);
524 pDlgSelect
->SetHeading(CVariant
{19213}); // Select Client
526 for (const auto& client
: m_clientsWithSettingsList
)
527 pDlgSelect
->Add(client
->Name());
530 iSelection
= pDlgSelect
->GetSelectedItem();
533 if (iSelection
>= 0 && iSelection
< static_cast<int>(m_clientsWithSettingsList
.size()))
535 int iClientID
= m_clientsWithSettingsList
[iSelection
]->GetID();
537 std::shared_ptr
<CPVRChannel
> channel(new CPVRChannel(m_bIsRadio
));
538 channel
->SetChannelName(g_localizeStrings
.Get(19204)); // New channel
539 channel
->SetClientID(iClientID
);
541 PVR_ERROR ret
= PVR_ERROR_UNKNOWN
;
542 const std::shared_ptr
<CPVRClient
> client
= CServiceBroker::GetPVRManager().GetClient(iClientID
);
545 channel
->SetEPGEnabled(client
->GetClientCapabilities().SupportsEPG());
546 ret
= client
->OpenDialogChannelAdd(channel
);
549 if (ret
== PVR_ERROR_NO_ERROR
)
551 CFileItemList prevChannelItems
;
552 prevChannelItems
.Assign(*m_channelItems
);
556 for (int index
= 0; index
< m_channelItems
->Size(); ++index
)
558 if (!prevChannelItems
.Contains(m_channelItems
->Get(index
)->GetPath()))
561 m_viewControl
.SetSelectedItem(m_iSelected
);
562 SetData(m_iSelected
);
567 else if (ret
== PVR_ERROR_NOT_IMPLEMENTED
)
568 HELPERS::ShowOKDialogText(CVariant
{19033}, CVariant
{19038}); // "Information", "Not supported by the PVR backend."
570 HELPERS::ShowOKDialogText(CVariant
{2103}, CVariant
{16029}); // "Add-on error", "Check the log for more information about this message."
575 bool CGUIDialogPVRChannelManager::OnClickButtonRefreshChannelLogos()
577 for (const auto& item
: *m_channelItems
)
579 const std::string thumb
= item
->GetArt("thumb");
582 // clear current cached image
583 CServiceBroker::GetTextureCache()->ClearCachedImage(thumb
);
584 item
->SetArt("thumb", "");
591 CGUIMessage
msg(GUI_MSG_NOTIFY_ALL
, 0, 0, GUI_MSG_REFRESH_THUMBS
);
592 CServiceBroker::GetGUI()->GetWindowManager().SendMessage(msg
);
597 bool CGUIDialogPVRChannelManager::OnMessageClick(const CGUIMessage
& message
)
599 int iControl
= message
.GetSenderId();
602 case CONTROL_LIST_CHANNELS
:
603 return OnClickListChannels(message
);
605 return OnClickButtonOK();
607 return OnClickButtonApply();
609 return OnClickButtonCancel();
610 case BUTTON_RADIO_TV
:
611 return OnClickButtonRadioTV();
612 case RADIOBUTTON_ACTIVE
:
613 return OnClickButtonRadioActive();
614 case RADIOBUTTON_PARENTAL_LOCK
:
615 return OnClickButtonRadioParentalLocked();
617 return OnClickButtonEditName();
618 case BUTTON_CHANNEL_LOGO
:
619 return OnClickButtonChannelLogo();
620 case RADIOBUTTON_USEEPG
:
621 return OnClickButtonUseEPG();
622 case SPIN_EPGSOURCE_SELECTION
:
623 return OnClickEPGSourceSpin();
624 case BUTTON_GROUP_MANAGER
:
625 return OnClickButtonGroupManager();
626 case BUTTON_NEW_CHANNEL
:
627 return OnClickButtonNewChannel();
628 case BUTTON_REFRESH_LOGOS
:
629 return OnClickButtonRefreshChannelLogos();
635 bool CGUIDialogPVRChannelManager::OnMessage(CGUIMessage
& message
)
637 unsigned int iMessage
= message
.GetMessage();
641 case GUI_MSG_CLICKED
:
642 return OnMessageClick(message
);
645 return CGUIDialog::OnMessage(message
);
648 void CGUIDialogPVRChannelManager::OnWindowLoaded()
650 CGUIDialog::OnWindowLoaded();
652 m_viewControl
.Reset();
653 m_viewControl
.SetParentWindow(GetID());
654 m_viewControl
.AddView(GetControl(CONTROL_LIST_CHANNELS
));
657 void CGUIDialogPVRChannelManager::OnWindowUnload()
659 CGUIDialog::OnWindowUnload();
660 m_viewControl
.Reset();
663 CFileItemPtr
CGUIDialogPVRChannelManager::GetCurrentListItem(int offset
)
665 return m_channelItems
->Get(m_iSelected
);
668 bool CGUIDialogPVRChannelManager::OnPopupMenu(int iItem
)
670 // popup the context menu
671 // grab our context menu
672 CContextButtons buttons
;
675 if (iItem
>= 0 && iItem
< m_channelItems
->Size())
676 m_channelItems
->Get(iItem
)->Select(true);
680 CFileItemPtr pItem
= m_channelItems
->Get(iItem
);
684 if (m_bAllowReorder
&&
685 pItem
->GetProperty(PROPERTY_CHANNEL_NUMBER
).asString() != LABEL_CHANNEL_DISABLED
)
686 buttons
.Add(CONTEXT_BUTTON_MOVE
, 116); /* Move channel up or down */
688 if (pItem
->GetProperty(PROPERTY_CLIENT_SUPPORTS_SETTINGS
).asBoolean())
690 buttons
.Add(CONTEXT_BUTTON_SETTINGS
, 10004); /* Open add-on channel settings dialog */
691 buttons
.Add(CONTEXT_BUTTON_DELETE
, 117); /* Delete add-on channel */
694 int choice
= CGUIDialogContextMenu::ShowAndGetChoice(buttons
);
697 if (iItem
>= 0 && iItem
< m_channelItems
->Size())
698 m_channelItems
->Get(iItem
)->Select(false);
703 return OnContextButton(iItem
, (CONTEXT_BUTTON
)choice
);
706 bool CGUIDialogPVRChannelManager::OnContextButton(int itemNumber
, CONTEXT_BUTTON button
)
708 /* Check file item is in list range and get his pointer */
709 if (itemNumber
< 0 || itemNumber
>= m_channelItems
->Size()) return false;
711 CFileItemPtr pItem
= m_channelItems
->Get(itemNumber
);
715 if (button
== CONTEXT_BUTTON_MOVE
)
717 m_bMovingMode
= true;
720 else if (button
== CONTEXT_BUTTON_SETTINGS
)
724 const std::shared_ptr
<CPVRClient
> client
= CServiceBroker::GetPVRManager().GetClient(*pItem
);
725 PVR_ERROR ret
= PVR_ERROR_UNKNOWN
;
727 ret
= client
->OpenDialogChannelSettings(pItem
->GetPVRChannelInfoTag());
729 if (ret
== PVR_ERROR_NO_ERROR
)
732 SetData(m_iSelected
);
734 else if (ret
== PVR_ERROR_NOT_IMPLEMENTED
)
735 HELPERS::ShowOKDialogText(CVariant
{19033}, CVariant
{19038}); // "Information", "Not supported by the PVR backend."
737 HELPERS::ShowOKDialogText(CVariant
{2103}, CVariant
{16029}); // "Add-on error", "Check the log for more information about this message."
739 else if (button
== CONTEXT_BUTTON_DELETE
)
741 CGUIDialogYesNo
* pDialog
= CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogYesNo
>(WINDOW_DIALOG_YES_NO
);
745 pDialog
->SetHeading(CVariant
{19211}); // Delete channel
746 pDialog
->SetText(CVariant
{750}); // Are you sure?
749 if (pDialog
->IsConfirmed())
751 const std::shared_ptr
<CPVRClient
> client
= CServiceBroker::GetPVRManager().GetClient(*pItem
);
754 const std::shared_ptr
<const CPVRChannel
> channel
= pItem
->GetPVRChannelInfoTag();
755 PVR_ERROR ret
= client
->DeleteChannel(channel
);
756 if (ret
== PVR_ERROR_NO_ERROR
)
758 CPVRChannelGroups
* groups
=
759 CServiceBroker::GetPVRManager().ChannelGroups()->Get(m_bIsRadio
);
762 groups
->UpdateFromClients({});
766 else if (ret
== PVR_ERROR_NOT_IMPLEMENTED
)
767 HELPERS::ShowOKDialogText(CVariant
{19033}, CVariant
{19038}); // "Information", "Not supported by the PVR backend."
769 HELPERS::ShowOKDialogText(CVariant
{2103}, CVariant
{16029}); // "Add-on error", "Check the log for more information about this message."
776 void CGUIDialogPVRChannelManager::SetData(int iItem
)
778 if (iItem
< 0 || iItem
>= m_channelItems
->Size())
780 ClearChannelOptions();
781 EnableChannelOptions(false);
785 CFileItemPtr pItem
= m_channelItems
->Get(iItem
);
789 SET_CONTROL_LABEL2(EDIT_NAME
, pItem
->GetProperty(PROPERTY_CHANNEL_NAME
).asString());
790 CGUIMessage
msg(GUI_MSG_SET_TYPE
, GetID(), EDIT_NAME
, CGUIEditControl::INPUT_TYPE_TEXT
, 19208);
793 SET_CONTROL_SELECTED(GetID(), RADIOBUTTON_ACTIVE
,
794 pItem
->GetProperty(PROPERTY_CHANNEL_ENABLED
).asBoolean());
795 SET_CONTROL_SELECTED(GetID(), RADIOBUTTON_USEEPG
,
796 pItem
->GetProperty(PROPERTY_CHANNEL_EPG_ENABLED
).asBoolean());
797 SET_CONTROL_SELECTED(GetID(), RADIOBUTTON_PARENTAL_LOCK
,
798 pItem
->GetProperty(PROPERTY_CHANNEL_LOCKED
).asBoolean());
800 EnableChannelOptions(true);
803 void CGUIDialogPVRChannelManager::Update()
805 m_viewControl
.SetCurrentView(CONTROL_LIST_CHANNELS
);
807 // empty the lists ready for population
810 std::shared_ptr
<CPVRChannelGroup
> channels
= CServiceBroker::GetPVRManager().ChannelGroups()->GetGroupAll(m_bIsRadio
);
812 // No channels available, nothing to do.
816 channels
->UpdateFromClients({});
818 const std::vector
<std::shared_ptr
<CPVRChannelGroupMember
>> groupMembers
= channels
->GetMembers();
819 std::shared_ptr
<CFileItem
> channelFile
;
820 for (const auto& member
: groupMembers
)
822 channelFile
= std::make_shared
<CFileItem
>(member
);
825 const std::shared_ptr
<const CPVRChannel
> channel(channelFile
->GetPVRChannelInfoTag());
827 channelFile
->SetProperty(PROPERTY_CHANNEL_ENABLED
, !channel
->IsHidden());
828 channelFile
->SetProperty(PROPERTY_CHANNEL_USER_SET_HIDDEN
, channel
->IsUserSetHidden());
829 channelFile
->SetProperty(PROPERTY_CHANNEL_USER_SET_NAME
, channel
->IsUserSetName());
830 channelFile
->SetProperty(PROPERTY_CHANNEL_NAME
, channel
->ChannelName());
831 channelFile
->SetProperty(PROPERTY_CHANNEL_EPG_ENABLED
, channel
->EPGEnabled());
832 channelFile
->SetProperty(PROPERTY_CHANNEL_ICON
, channel
->IconPath());
833 channelFile
->SetProperty(PROPERTY_CHANNEL_CUSTOM_ICON
, channel
->IsUserSetIcon());
834 channelFile
->SetProperty(PROPERTY_CHANNEL_EPG_SOURCE
, 0);
835 channelFile
->SetProperty(PROPERTY_CHANNEL_LOCKED
, channel
->IsLocked());
836 channelFile
->SetProperty(PROPERTY_CHANNEL_NUMBER
,
837 member
->ChannelNumber().FormattedChannelNumber());
839 const std::shared_ptr
<const CPVRClient
> client
=
840 CServiceBroker::GetPVRManager().GetClient(*channelFile
);
843 channelFile
->SetProperty(PROPERTY_CLIENT_NAME
, client
->GetFullClientName());
844 channelFile
->SetProperty(PROPERTY_CLIENT_SUPPORTS_SETTINGS
,
845 client
->GetClientCapabilities().SupportsChannelSettings());
848 m_channelItems
->Add(channelFile
);
852 std::vector
< std::pair
<std::string
, int> > labels
;
853 labels
.emplace_back(g_localizeStrings
.Get(19210), 0);
854 //! @todo Add Labels for EPG scrapers here
855 SET_CONTROL_LABELS(SPIN_EPGSOURCE_SELECTION
, 0, &labels
);
858 m_clientsWithSettingsList
= CServiceBroker::GetPVRManager().Clients()->GetClientsSupportingChannelSettings(m_bIsRadio
);
859 if (!m_clientsWithSettingsList
.empty())
860 m_bAllowNewChannel
= true;
862 if (m_bAllowNewChannel
)
863 CONTROL_ENABLE(BUTTON_NEW_CHANNEL
);
865 CONTROL_DISABLE(BUTTON_NEW_CHANNEL
);
868 m_viewControl
.SetItems(*m_channelItems
);
869 if (m_iSelected
>= m_channelItems
->Size())
870 m_iSelected
= m_channelItems
->Size() - 1;
871 m_viewControl
.SetSelectedItem(m_iSelected
);
872 SetData(m_iSelected
);
875 void CGUIDialogPVRChannelManager::Clear()
877 m_viewControl
.Clear();
878 m_channelItems
->Clear();
880 ClearChannelOptions();
881 EnableChannelOptions(false);
883 CONTROL_DISABLE(BUTTON_APPLY
);
886 void CGUIDialogPVRChannelManager::ClearChannelOptions()
888 CONTROL_DESELECT(RADIOBUTTON_ACTIVE
);
889 SET_CONTROL_LABEL2(EDIT_NAME
, "");
890 SET_CONTROL_FILENAME(BUTTON_CHANNEL_LOGO
, "");
891 CONTROL_DESELECT(RADIOBUTTON_USEEPG
);
893 std::vector
<std::pair
<std::string
, int>> labels
= {{g_localizeStrings
.Get(19210), 0}};
894 SET_CONTROL_LABELS(SPIN_EPGSOURCE_SELECTION
, 0, &labels
);
896 CONTROL_DESELECT(RADIOBUTTON_PARENTAL_LOCK
);
899 void CGUIDialogPVRChannelManager::EnableChannelOptions(bool bEnable
)
903 CONTROL_ENABLE(RADIOBUTTON_ACTIVE
);
904 CONTROL_ENABLE(EDIT_NAME
);
905 CONTROL_ENABLE(BUTTON_CHANNEL_LOGO
);
906 CONTROL_ENABLE(IMAGE_CHANNEL_LOGO
);
907 CONTROL_ENABLE(RADIOBUTTON_USEEPG
);
908 CONTROL_ENABLE(SPIN_EPGSOURCE_SELECTION
);
909 CONTROL_ENABLE(RADIOBUTTON_PARENTAL_LOCK
);
913 CONTROL_DISABLE(RADIOBUTTON_ACTIVE
);
914 CONTROL_DISABLE(EDIT_NAME
);
915 CONTROL_DISABLE(BUTTON_CHANNEL_LOGO
);
916 CONTROL_DISABLE(IMAGE_CHANNEL_LOGO
);
917 CONTROL_DISABLE(RADIOBUTTON_USEEPG
);
918 CONTROL_DISABLE(SPIN_EPGSOURCE_SELECTION
);
919 CONTROL_DISABLE(RADIOBUTTON_PARENTAL_LOCK
);
923 void CGUIDialogPVRChannelManager::RenameChannel(const CFileItemPtr
& pItem
)
925 std::string strChannelName
= pItem
->GetProperty(PROPERTY_CHANNEL_NAME
).asString();
926 if (strChannelName
!= pItem
->GetPVRChannelInfoTag()->ChannelName())
928 const std::shared_ptr
<CPVRChannel
> channel
= pItem
->GetPVRChannelInfoTag();
929 channel
->SetChannelName(strChannelName
);
931 const std::shared_ptr
<CPVRClient
> client
= CServiceBroker::GetPVRManager().GetClient(*pItem
);
932 if (!client
|| (client
->RenameChannel(channel
) != PVR_ERROR_NO_ERROR
))
933 HELPERS::ShowOKDialogText(CVariant
{2103}, CVariant
{16029}); // Add-on error;Check the log file for details.
937 bool CGUIDialogPVRChannelManager::UpdateChannelData(const std::shared_ptr
<CFileItem
>& pItem
,
938 const std::shared_ptr
<CPVRChannelGroup
>& group
)
940 if (!pItem
|| !group
)
943 const auto groupMember
= pItem
->GetPVRChannelGroupMemberInfoTag();
945 if (pItem
->GetProperty(PROPERTY_CHANNEL_ENABLED
).asBoolean()) // enabled == not hidden
947 if (m_bAllowRenumber
)
949 groupMember
->SetChannelNumber(CPVRChannelNumber(
950 static_cast<unsigned int>(pItem
->GetProperty(PROPERTY_CHANNEL_NUMBER
).asInteger()), 0));
953 // make sure the channel is part of the group
954 group
->AppendToGroup(groupMember
);
958 // remove the hidden channel from the group
959 group
->RemoveFromGroup(groupMember
);
962 const auto channel
= groupMember
->Channel();
964 channel
->SetChannelName(pItem
->GetProperty(PROPERTY_CHANNEL_NAME
).asString(),
965 pItem
->GetProperty(PROPERTY_CHANNEL_USER_SET_NAME
).asBoolean());
966 channel
->SetHidden(!pItem
->GetProperty(PROPERTY_CHANNEL_ENABLED
).asBoolean(),
967 pItem
->GetProperty(PROPERTY_CHANNEL_USER_SET_HIDDEN
).asBoolean());
968 channel
->SetLocked(pItem
->GetProperty(PROPERTY_CHANNEL_LOCKED
).asBoolean());
969 channel
->SetIconPath(pItem
->GetProperty(PROPERTY_CHANNEL_ICON
).asString(),
970 pItem
->GetProperty(PROPERTY_CHANNEL_CUSTOM_ICON
).asBoolean());
972 //! @todo add other scrapers
973 if (pItem
->GetProperty(PROPERTY_CHANNEL_EPG_SOURCE
).asInteger() == 0)
974 channel
->SetEPGScraper("client");
976 channel
->SetEPGEnabled(pItem
->GetProperty(PROPERTY_CHANNEL_EPG_ENABLED
).asBoolean());
981 void CGUIDialogPVRChannelManager::PromptAndSaveList()
983 if (!HasChangedItems())
986 CGUIDialogYesNo
* pDialogYesNo
=
987 CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogYesNo
>(WINDOW_DIALOG_YES_NO
);
990 pDialogYesNo
->SetHeading(CVariant
{20052});
991 pDialogYesNo
->SetLine(0, CVariant
{""});
992 pDialogYesNo
->SetLine(1, CVariant
{19212});
993 pDialogYesNo
->SetLine(2, CVariant
{20103});
994 pDialogYesNo
->Open();
996 if (pDialogYesNo
->IsConfirmed())
1003 void CGUIDialogPVRChannelManager::SaveList()
1005 if (!HasChangedItems())
1008 /* display the progress dialog */
1009 CGUIDialogProgress
* pDlgProgress
= CServiceBroker::GetGUI()->GetWindowManager().GetWindow
<CGUIDialogProgress
>(WINDOW_DIALOG_PROGRESS
);
1010 pDlgProgress
->SetHeading(CVariant
{190});
1011 pDlgProgress
->SetLine(0, CVariant
{""});
1012 pDlgProgress
->SetLine(1, CVariant
{328});
1013 pDlgProgress
->SetLine(2, CVariant
{""});
1014 pDlgProgress
->Open();
1015 pDlgProgress
->Progress();
1016 pDlgProgress
->SetPercentage(0);
1018 /* persist all channels */
1019 std::shared_ptr
<CPVRChannelGroup
> group
= CServiceBroker::GetPVRManager().ChannelGroups()->GetGroupAll(m_bIsRadio
);
1023 for (int iListPtr
= 0; iListPtr
< m_channelItems
->Size(); ++iListPtr
)
1025 CFileItemPtr pItem
= m_channelItems
->Get(iListPtr
);
1026 if (pItem
&& pItem
->GetProperty(PROPERTY_ITEM_CHANGED
).asBoolean())
1028 if (pItem
->GetProperty(PROPERTY_CLIENT_SUPPORTS_SETTINGS
).asBoolean())
1029 RenameChannel(pItem
);
1031 if (pItem
->GetProperty(PROPERTY_CHANNEL_USER_SET_NAME
).asBoolean() &&
1032 pItem
->GetProperty(PROPERTY_CHANNEL_NAME
).asString().empty())
1034 // if the user changes the name manually to an empty string we reset the
1035 // userset name flag and change the name to the name from the client
1036 pItem
->SetProperty(PROPERTY_CHANNEL_USER_SET_NAME
, false);
1038 const std::string newName
= pItem
->GetPVRChannelInfoTag()->ClientChannelName();
1039 pItem
->SetProperty(PROPERTY_CHANNEL_NAME
, newName
);
1040 SET_CONTROL_LABEL2(EDIT_NAME
, newName
);
1043 // Write the changes made in this dialog back to the actual channel instance
1044 if (UpdateChannelData(pItem
, group
))
1045 pItem
->SetProperty(PROPERTY_ITEM_CHANGED
, false);
1048 pDlgProgress
->SetPercentage(iListPtr
* 100 / m_channelItems
->Size());
1051 group
->SortAndRenumber();
1053 auto channelGroups
= CServiceBroker::GetPVRManager().ChannelGroups()->Get(m_bIsRadio
);
1054 channelGroups
->UpdateChannelNumbersFromAllChannelsGroup();
1055 channelGroups
->PersistAll();
1056 pDlgProgress
->Close();
1058 CONTROL_DISABLE(BUTTON_APPLY
);
1061 bool CGUIDialogPVRChannelManager::HasChangedItems() const
1063 return std::any_of(m_channelItems
->cbegin(), m_channelItems
->cend(), [](const auto& item
) {
1064 return item
&& item
->GetProperty(PROPERTY_ITEM_CHANGED
).asBoolean();
1071 bool IsItemChanged(const std::shared_ptr
<CFileItem
>& item
)
1073 const std::shared_ptr
<const CPVRChannelGroupMember
> member
=
1074 item
->GetPVRChannelGroupMemberInfoTag();
1075 const std::shared_ptr
<const CPVRChannel
> channel
= member
->Channel();
1077 return item
->GetProperty(PROPERTY_CHANNEL_ENABLED
).asBoolean() == channel
->IsHidden() ||
1078 item
->GetProperty(PROPERTY_CHANNEL_USER_SET_HIDDEN
).asBoolean() !=
1079 channel
->IsUserSetHidden() ||
1080 item
->GetProperty(PROPERTY_CHANNEL_USER_SET_NAME
).asBoolean() !=
1081 channel
->IsUserSetName() ||
1082 item
->GetProperty(PROPERTY_CHANNEL_NAME
).asString() != channel
->ChannelName() ||
1083 item
->GetProperty(PROPERTY_CHANNEL_EPG_ENABLED
).asBoolean() != channel
->EPGEnabled() ||
1084 item
->GetProperty(PROPERTY_CHANNEL_ICON
).asString() != channel
->IconPath() ||
1085 item
->GetProperty(PROPERTY_CHANNEL_CUSTOM_ICON
).asBoolean() != channel
->IsUserSetIcon() ||
1086 item
->GetProperty(PROPERTY_CHANNEL_EPG_SOURCE
).asInteger() != 0 ||
1087 item
->GetProperty(PROPERTY_CHANNEL_LOCKED
).asBoolean() != channel
->IsLocked() ||
1088 item
->GetProperty(PROPERTY_CHANNEL_NUMBER
).asString() !=
1089 member
->ChannelNumber().FormattedChannelNumber();
1094 void CGUIDialogPVRChannelManager::SetItemChanged(const CFileItemPtr
& pItem
)
1096 const bool changed
= IsItemChanged(pItem
);
1097 pItem
->SetProperty(PROPERTY_ITEM_CHANGED
, changed
);
1099 if (changed
|| HasChangedItems())
1100 CONTROL_ENABLE(BUTTON_APPLY
);
1102 CONTROL_DISABLE(BUTTON_APPLY
);
1105 void CGUIDialogPVRChannelManager::Renumber()
1107 if (!m_bAllowRenumber
)
1110 int iNextChannelNumber
= 0;
1111 for (const auto& item
: *m_channelItems
)
1113 const std::string number
= item
->GetProperty(PROPERTY_CHANNEL_ENABLED
).asBoolean()
1114 ? std::to_string(++iNextChannelNumber
)
1115 : LABEL_CHANNEL_DISABLED
;
1117 if (item
->GetProperty(PROPERTY_CHANNEL_NUMBER
).asString() != number
)
1119 item
->SetProperty(PROPERTY_CHANNEL_NUMBER
, number
);
1120 SetItemChanged(item
);