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 "GUIDialogPVRGuideSearch.h"
11 #include "ServiceBroker.h"
12 #include "guilib/GUIEditControl.h"
13 #include "guilib/GUIKeyboardFactory.h"
14 #include "guilib/GUIMessage.h"
15 #include "guilib/LocalizeStrings.h"
16 #include "pvr/PVRManager.h"
17 #include "pvr/channels/PVRChannel.h"
18 #include "pvr/channels/PVRChannelGroupMember.h"
19 #include "pvr/channels/PVRChannelGroups.h"
20 #include "pvr/channels/PVRChannelGroupsContainer.h"
21 #include "pvr/epg/EpgContainer.h"
22 #include "pvr/epg/EpgSearchFilter.h"
23 #include "utils/StringUtils.h"
31 #define CONTROL_EDIT_SEARCH 9
32 #define CONTROL_BTN_INC_DESC 10
33 #define CONTROL_BTN_CASE_SENS 11
34 #define CONTROL_SPIN_MIN_DURATION 12
35 #define CONTROL_SPIN_MAX_DURATION 13
36 #define CONTROL_EDIT_START_DATE 14
37 #define CONTROL_EDIT_STOP_DATE 15
38 #define CONTROL_EDIT_START_TIME 16
39 #define CONTROL_EDIT_STOP_TIME 17
40 #define CONTROL_SPIN_GENRE 18
41 #define CONTROL_SPIN_NO_REPEATS 19
42 #define CONTROL_BTN_UNK_GENRE 20
43 #define CONTROL_SPIN_GROUPS 21
44 #define CONTROL_BTN_FTA_ONLY 22
45 #define CONTROL_SPIN_CHANNELS 23
46 #define CONTROL_BTN_IGNORE_TMR 24
47 #define CONTROL_BTN_CANCEL 25
48 #define CONTROL_BTN_SEARCH 26
49 #define CONTROL_BTN_IGNORE_REC 27
50 #define CONTROL_BTN_DEFAULTS 28
51 static constexpr int CONTROL_BTN_SAVE
= 29;
52 static constexpr int CONTROL_BTN_IGNORE_FINISHED
= 30;
53 static constexpr int CONTROL_BTN_IGNORE_FUTURE
= 31;
55 CGUIDialogPVRGuideSearch::CGUIDialogPVRGuideSearch()
56 : CGUIDialog(WINDOW_DIALOG_PVR_GUIDE_SEARCH
, "DialogPVRGuideSearch.xml")
60 void CGUIDialogPVRGuideSearch::SetFilterData(
61 const std::shared_ptr
<CPVREpgSearchFilter
>& searchFilter
)
63 m_searchFilter
= searchFilter
;
66 void CGUIDialogPVRGuideSearch::UpdateChannelSpin()
68 int iChannelGroup
= GetSpinValue(CONTROL_SPIN_GROUPS
);
70 std::vector
< std::pair
<std::string
, int> > labels
;
71 if (m_searchFilter
->IsRadio())
72 labels
.emplace_back(g_localizeStrings
.Get(19216), EPG_SEARCH_UNSET
); // All radio channels
74 labels
.emplace_back(g_localizeStrings
.Get(19217), EPG_SEARCH_UNSET
); // All TV channels
76 std::shared_ptr
<CPVRChannelGroup
> group
;
77 if (iChannelGroup
!= EPG_SEARCH_UNSET
)
78 group
= CServiceBroker::GetPVRManager().ChannelGroups()->GetByIdFromAll(iChannelGroup
);
81 group
= CServiceBroker::GetPVRManager().ChannelGroups()->GetGroupAll(m_searchFilter
->IsRadio());
83 m_channelsMap
.clear();
84 const std::vector
<std::shared_ptr
<CPVRChannelGroupMember
>> groupMembers
=
85 group
->GetMembers(CPVRChannelGroup::Include::ONLY_VISIBLE
);
87 int iSelectedChannel
= EPG_SEARCH_UNSET
;
88 for (const auto& groupMember
: groupMembers
)
90 labels
.emplace_back(groupMember
->Channel()->ChannelName(), iIndex
);
91 m_channelsMap
.insert(std::make_pair(iIndex
, groupMember
));
93 if (iSelectedChannel
== EPG_SEARCH_UNSET
&&
94 groupMember
->ChannelUID() == m_searchFilter
->GetChannelUID() &&
95 groupMember
->ChannelClientID() == m_searchFilter
->GetClientID())
96 iSelectedChannel
= iIndex
;
101 SET_CONTROL_LABELS(CONTROL_SPIN_CHANNELS
, iSelectedChannel
, &labels
);
104 void CGUIDialogPVRGuideSearch::UpdateGroupsSpin()
106 std::vector
<std::pair
<std::string
, int>> labels
;
107 const std::vector
<std::shared_ptr
<CPVRChannelGroup
>> groups
=
108 CServiceBroker::GetPVRManager().ChannelGroups()->Get(m_searchFilter
->IsRadio())->GetMembers();
109 int selectedGroup
= EPG_SEARCH_UNSET
;
110 for (const auto& group
: groups
)
112 labels
.emplace_back(group
->GroupName(), group
->GroupID());
114 if (selectedGroup
== EPG_SEARCH_UNSET
&&
115 group
->GroupID() == m_searchFilter
->GetChannelGroupID())
116 selectedGroup
= group
->GroupID();
119 SET_CONTROL_LABELS(CONTROL_SPIN_GROUPS
, selectedGroup
, &labels
);
122 void CGUIDialogPVRGuideSearch::UpdateGenreSpin()
124 std::vector
< std::pair
<std::string
, int> > labels
;
125 labels
.emplace_back(g_localizeStrings
.Get(593), EPG_SEARCH_UNSET
);
126 labels
.emplace_back(g_localizeStrings
.Get(19500), EPG_EVENT_CONTENTMASK_MOVIEDRAMA
);
127 labels
.emplace_back(g_localizeStrings
.Get(19516), EPG_EVENT_CONTENTMASK_NEWSCURRENTAFFAIRS
);
128 labels
.emplace_back(g_localizeStrings
.Get(19532), EPG_EVENT_CONTENTMASK_SHOW
);
129 labels
.emplace_back(g_localizeStrings
.Get(19548), EPG_EVENT_CONTENTMASK_SPORTS
);
130 labels
.emplace_back(g_localizeStrings
.Get(19564), EPG_EVENT_CONTENTMASK_CHILDRENYOUTH
);
131 labels
.emplace_back(g_localizeStrings
.Get(19580), EPG_EVENT_CONTENTMASK_MUSICBALLETDANCE
);
132 labels
.emplace_back(g_localizeStrings
.Get(19596), EPG_EVENT_CONTENTMASK_ARTSCULTURE
);
133 labels
.emplace_back(g_localizeStrings
.Get(19612), EPG_EVENT_CONTENTMASK_SOCIALPOLITICALECONOMICS
);
134 labels
.emplace_back(g_localizeStrings
.Get(19628), EPG_EVENT_CONTENTMASK_EDUCATIONALSCIENCE
);
135 labels
.emplace_back(g_localizeStrings
.Get(19644), EPG_EVENT_CONTENTMASK_LEISUREHOBBIES
);
136 labels
.emplace_back(g_localizeStrings
.Get(19660), EPG_EVENT_CONTENTMASK_SPECIAL
);
137 labels
.emplace_back(g_localizeStrings
.Get(19499), EPG_EVENT_CONTENTMASK_USERDEFINED
);
139 SET_CONTROL_LABELS(CONTROL_SPIN_GENRE
, m_searchFilter
->GetGenreType(), &labels
);
142 void CGUIDialogPVRGuideSearch::UpdateDurationSpin()
144 /* minimum duration */
145 std::vector
< std::pair
<std::string
, int> > labels
;
147 labels
.emplace_back("-", EPG_SEARCH_UNSET
);
148 for (int i
= 1; i
< 12*60/5; ++i
)
149 labels
.emplace_back(StringUtils::Format(g_localizeStrings
.Get(14044), i
* 5), i
* 5);
151 SET_CONTROL_LABELS(CONTROL_SPIN_MIN_DURATION
, m_searchFilter
->GetMinimumDuration(), &labels
);
153 /* maximum duration */
156 labels
.emplace_back("-", EPG_SEARCH_UNSET
);
157 for (int i
= 1; i
< 12*60/5; ++i
)
158 labels
.emplace_back(StringUtils::Format(g_localizeStrings
.Get(14044), i
* 5), i
* 5);
160 SET_CONTROL_LABELS(CONTROL_SPIN_MAX_DURATION
, m_searchFilter
->GetMaximumDuration(), &labels
);
163 bool CGUIDialogPVRGuideSearch::OnMessage(CGUIMessage
& message
)
165 CGUIDialog::OnMessage(message
);
167 switch (message
.GetMessage())
169 case GUI_MSG_CLICKED
:
171 int iControl
= message
.GetSenderId();
172 if (iControl
== CONTROL_BTN_SEARCH
)
174 // Read data from controls, update m_searchfilter accordingly
175 UpdateSearchFilter();
177 m_result
= Result::SEARCH
;
181 else if (iControl
== CONTROL_BTN_CANCEL
)
183 m_result
= Result::CANCEL
;
187 else if (iControl
== CONTROL_BTN_DEFAULTS
)
191 m_searchFilter
->Reset();
196 else if (iControl
== CONTROL_BTN_SAVE
)
198 // Read data from controls, update m_searchfilter accordingly
199 UpdateSearchFilter();
201 std::string title
= m_searchFilter
->GetTitle();
204 title
= m_searchFilter
->GetSearchTerm();
206 title
= g_localizeStrings
.Get(137); // "Search"
208 StringUtils::Trim(title
, "\"");
210 if (!CGUIKeyboardFactory::ShowAndGetInput(
211 title
, CVariant
{g_localizeStrings
.Get(528)}, // "Enter title"
216 m_searchFilter
->SetTitle(title
);
219 m_result
= Result::SAVE
;
223 else if (iControl
== CONTROL_SPIN_GROUPS
)
235 void CGUIDialogPVRGuideSearch::OnInitWindow()
237 CGUIDialog::OnInitWindow();
239 m_result
= Result::CANCEL
;
242 void CGUIDialogPVRGuideSearch::OnWindowLoaded()
245 return CGUIDialog::OnWindowLoaded();
248 CDateTime
CGUIDialogPVRGuideSearch::ReadDateTime(const std::string
& strDate
, const std::string
& strTime
) const
251 int iHours
, iMinutes
;
252 sscanf(strTime
.c_str(), "%d:%d", &iHours
, &iMinutes
);
253 dateTime
.SetFromDBDate(strDate
);
254 dateTime
.SetDateTime(dateTime
.GetYear(), dateTime
.GetMonth(), dateTime
.GetDay(), iHours
, iMinutes
, 0);
255 return dateTime
.GetAsUTCDateTime();
258 bool CGUIDialogPVRGuideSearch::IsRadioSelected(int controlID
)
260 CGUIMessage
msg(GUI_MSG_IS_SELECTED
, GetID(), controlID
);
262 return (msg
.GetParam1() == 1);
265 int CGUIDialogPVRGuideSearch::GetSpinValue(int controlID
)
267 CGUIMessage
msg(GUI_MSG_ITEM_SELECTED
, GetID(), controlID
);
269 return msg
.GetParam1();
272 std::string
CGUIDialogPVRGuideSearch::GetEditValue(int controlID
)
274 CGUIMessage
msg(GUI_MSG_ITEM_SELECTED
, GetID(), controlID
);
276 return msg
.GetLabel();
279 void CGUIDialogPVRGuideSearch::UpdateSearchFilter()
284 m_searchFilter
->SetSearchTerm(GetEditValue(CONTROL_EDIT_SEARCH
));
286 m_searchFilter
->SetSearchInDescription(IsRadioSelected(CONTROL_BTN_INC_DESC
));
287 m_searchFilter
->SetCaseSensitive(IsRadioSelected(CONTROL_BTN_CASE_SENS
));
288 m_searchFilter
->SetFreeToAirOnly(IsRadioSelected(CONTROL_BTN_FTA_ONLY
));
289 m_searchFilter
->SetIncludeUnknownGenres(IsRadioSelected(CONTROL_BTN_UNK_GENRE
));
290 m_searchFilter
->SetIgnorePresentRecordings(IsRadioSelected(CONTROL_BTN_IGNORE_REC
));
291 m_searchFilter
->SetIgnorePresentTimers(IsRadioSelected(CONTROL_BTN_IGNORE_TMR
));
292 m_searchFilter
->SetRemoveDuplicates(IsRadioSelected(CONTROL_SPIN_NO_REPEATS
));
293 m_searchFilter
->SetIgnoreFinishedBroadcasts(IsRadioSelected(CONTROL_BTN_IGNORE_FINISHED
));
294 m_searchFilter
->SetIgnoreFutureBroadcasts(IsRadioSelected(CONTROL_BTN_IGNORE_FUTURE
));
295 m_searchFilter
->SetGenreType(GetSpinValue(CONTROL_SPIN_GENRE
));
296 m_searchFilter
->SetMinimumDuration(GetSpinValue(CONTROL_SPIN_MIN_DURATION
));
297 m_searchFilter
->SetMaximumDuration(GetSpinValue(CONTROL_SPIN_MAX_DURATION
));
299 auto it
= m_channelsMap
.find(GetSpinValue(CONTROL_SPIN_CHANNELS
));
300 m_searchFilter
->SetClientID(it
== m_channelsMap
.end() ? -1 : (*it
).second
->ChannelClientID());
301 m_searchFilter
->SetChannelUID(it
== m_channelsMap
.end() ? -1 : (*it
).second
->ChannelUID());
302 m_searchFilter
->SetChannelGroupID(GetSpinValue(CONTROL_SPIN_GROUPS
));
304 const CDateTime start
=
305 ReadDateTime(GetEditValue(CONTROL_EDIT_START_DATE
), GetEditValue(CONTROL_EDIT_START_TIME
));
306 if (start
!= m_startDateTime
)
308 m_searchFilter
->SetStartDateTime(start
);
309 m_startDateTime
= start
;
311 const CDateTime end
=
312 ReadDateTime(GetEditValue(CONTROL_EDIT_STOP_DATE
), GetEditValue(CONTROL_EDIT_STOP_TIME
));
313 if (end
!= m_endDateTime
)
315 m_searchFilter
->SetEndDateTime(end
);
320 void CGUIDialogPVRGuideSearch::Update()
325 SET_CONTROL_LABEL2(CONTROL_EDIT_SEARCH
, m_searchFilter
->GetSearchTerm());
327 CGUIMessage
msg(GUI_MSG_SET_TYPE
, GetID(), CONTROL_EDIT_SEARCH
, CGUIEditControl::INPUT_TYPE_TEXT
, 16017);
331 SET_CONTROL_SELECTED(GetID(), CONTROL_BTN_CASE_SENS
, m_searchFilter
->IsCaseSensitive());
332 SET_CONTROL_SELECTED(GetID(), CONTROL_BTN_INC_DESC
, m_searchFilter
->ShouldSearchInDescription());
333 SET_CONTROL_SELECTED(GetID(), CONTROL_BTN_FTA_ONLY
, m_searchFilter
->IsFreeToAirOnly());
334 SET_CONTROL_SELECTED(GetID(), CONTROL_BTN_UNK_GENRE
, m_searchFilter
->ShouldIncludeUnknownGenres());
335 SET_CONTROL_SELECTED(GetID(), CONTROL_BTN_IGNORE_REC
, m_searchFilter
->ShouldIgnorePresentRecordings());
336 SET_CONTROL_SELECTED(GetID(), CONTROL_BTN_IGNORE_TMR
, m_searchFilter
->ShouldIgnorePresentTimers());
337 SET_CONTROL_SELECTED(GetID(), CONTROL_SPIN_NO_REPEATS
, m_searchFilter
->ShouldRemoveDuplicates());
338 SET_CONTROL_SELECTED(GetID(), CONTROL_BTN_IGNORE_FINISHED
,
339 m_searchFilter
->ShouldIgnoreFinishedBroadcasts());
340 SET_CONTROL_SELECTED(GetID(), CONTROL_BTN_IGNORE_FUTURE
,
341 m_searchFilter
->ShouldIgnoreFutureBroadcasts());
343 // Set start/end datetime fields
344 m_startDateTime
= m_searchFilter
->GetStartDateTime();
345 m_endDateTime
= m_searchFilter
->GetEndDateTime();
346 if (!m_startDateTime
.IsValid() || !m_endDateTime
.IsValid())
348 const auto dates
= CServiceBroker::GetPVRManager().EpgContainer().GetFirstAndLastEPGDate();
349 if (!m_startDateTime
.IsValid())
350 m_startDateTime
= dates
.first
;
351 if (!m_endDateTime
.IsValid())
352 m_endDateTime
= dates
.second
;
355 if (!m_startDateTime
.IsValid())
356 m_startDateTime
= CDateTime::GetUTCDateTime();
358 if (!m_endDateTime
.IsValid())
359 m_endDateTime
= m_startDateTime
+ CDateTimeSpan(10, 0, 0, 0); // default to start + 10 days
361 CDateTime startLocal
;
362 startLocal
.SetFromUTCDateTime(m_startDateTime
);
364 endLocal
.SetFromUTCDateTime(m_endDateTime
);
366 SET_CONTROL_LABEL2(CONTROL_EDIT_START_TIME
, startLocal
.GetAsLocalizedTime("", false));
368 CGUIMessage
msg(GUI_MSG_SET_TYPE
, GetID(), CONTROL_EDIT_START_TIME
, CGUIEditControl::INPUT_TYPE_TIME
, 14066);
371 SET_CONTROL_LABEL2(CONTROL_EDIT_STOP_TIME
, endLocal
.GetAsLocalizedTime("", false));
373 CGUIMessage
msg(GUI_MSG_SET_TYPE
, GetID(), CONTROL_EDIT_STOP_TIME
, CGUIEditControl::INPUT_TYPE_TIME
, 14066);
376 SET_CONTROL_LABEL2(CONTROL_EDIT_START_DATE
, startLocal
.GetAsDBDate());
378 CGUIMessage
msg(GUI_MSG_SET_TYPE
, GetID(), CONTROL_EDIT_START_DATE
, CGUIEditControl::INPUT_TYPE_DATE
, 14067);
381 SET_CONTROL_LABEL2(CONTROL_EDIT_STOP_DATE
, endLocal
.GetAsDBDate());
383 CGUIMessage
msg(GUI_MSG_SET_TYPE
, GetID(), CONTROL_EDIT_STOP_DATE
, CGUIEditControl::INPUT_TYPE_DATE
, 14067);
387 UpdateDurationSpin();