Merge pull request #25614 from garbear/show-version
[xbmc.git] / xbmc / pvr / dialogs / GUIDialogPVRGuideSearch.cpp
blobb5cb4cf64a78ad5c49894b6d35960391ae9fe4b1
1 /*
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.
7 */
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"
25 #include <string>
26 #include <utility>
27 #include <vector>
29 using namespace PVR;
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;
54 static constexpr int CONTROL_BTN_START_ANY_TIME = 32;
55 static constexpr int CONTROL_BTN_END_ANY_TIME = 33;
57 CGUIDialogPVRGuideSearch::CGUIDialogPVRGuideSearch()
58 : CGUIDialog(WINDOW_DIALOG_PVR_GUIDE_SEARCH, "DialogPVRGuideSearch.xml")
62 void CGUIDialogPVRGuideSearch::SetFilterData(
63 const std::shared_ptr<CPVREpgSearchFilter>& searchFilter)
65 m_searchFilter = searchFilter;
68 void CGUIDialogPVRGuideSearch::UpdateChannelSpin()
70 int iChannelGroup = GetSpinValue(CONTROL_SPIN_GROUPS);
72 std::vector< std::pair<std::string, int> > labels;
73 if (m_searchFilter->IsRadio())
74 labels.emplace_back(g_localizeStrings.Get(19216), EPG_SEARCH_UNSET); // All radio channels
75 else
76 labels.emplace_back(g_localizeStrings.Get(19217), EPG_SEARCH_UNSET); // All TV channels
78 std::shared_ptr<CPVRChannelGroup> group;
79 if (iChannelGroup != EPG_SEARCH_UNSET)
80 group = CServiceBroker::GetPVRManager().ChannelGroups()->GetByIdFromAll(iChannelGroup);
82 if (!group)
83 group = CServiceBroker::GetPVRManager().ChannelGroups()->GetGroupAll(m_searchFilter->IsRadio());
85 m_channelsMap.clear();
86 const std::vector<std::shared_ptr<CPVRChannelGroupMember>> groupMembers =
87 group->GetMembers(CPVRChannelGroup::Include::ONLY_VISIBLE);
88 int iIndex = 0;
89 int iSelectedChannel = EPG_SEARCH_UNSET;
90 for (const auto& groupMember : groupMembers)
92 labels.emplace_back(groupMember->Channel()->ChannelName(), iIndex);
93 m_channelsMap.insert(std::make_pair(iIndex, groupMember));
95 if (iSelectedChannel == EPG_SEARCH_UNSET &&
96 groupMember->ChannelUID() == m_searchFilter->GetChannelUID() &&
97 groupMember->ChannelClientID() == m_searchFilter->GetClientID())
98 iSelectedChannel = iIndex;
100 ++iIndex;
103 SET_CONTROL_LABELS(CONTROL_SPIN_CHANNELS, iSelectedChannel, &labels);
106 void CGUIDialogPVRGuideSearch::UpdateGroupsSpin()
108 std::vector<std::pair<std::string, int>> labels;
109 const std::vector<std::shared_ptr<CPVRChannelGroup>> groups =
110 CServiceBroker::GetPVRManager().ChannelGroups()->Get(m_searchFilter->IsRadio())->GetMembers();
111 int selectedGroup = EPG_SEARCH_UNSET;
112 for (const auto& group : groups)
114 labels.emplace_back(group->GroupName(), group->GroupID());
116 if (selectedGroup == EPG_SEARCH_UNSET &&
117 group->GroupID() == m_searchFilter->GetChannelGroupID())
118 selectedGroup = group->GroupID();
121 SET_CONTROL_LABELS(CONTROL_SPIN_GROUPS, selectedGroup, &labels);
124 void CGUIDialogPVRGuideSearch::UpdateGenreSpin()
126 std::vector< std::pair<std::string, int> > labels;
127 labels.emplace_back(g_localizeStrings.Get(593), EPG_SEARCH_UNSET);
128 labels.emplace_back(g_localizeStrings.Get(19500), EPG_EVENT_CONTENTMASK_MOVIEDRAMA);
129 labels.emplace_back(g_localizeStrings.Get(19516), EPG_EVENT_CONTENTMASK_NEWSCURRENTAFFAIRS);
130 labels.emplace_back(g_localizeStrings.Get(19532), EPG_EVENT_CONTENTMASK_SHOW);
131 labels.emplace_back(g_localizeStrings.Get(19548), EPG_EVENT_CONTENTMASK_SPORTS);
132 labels.emplace_back(g_localizeStrings.Get(19564), EPG_EVENT_CONTENTMASK_CHILDRENYOUTH);
133 labels.emplace_back(g_localizeStrings.Get(19580), EPG_EVENT_CONTENTMASK_MUSICBALLETDANCE);
134 labels.emplace_back(g_localizeStrings.Get(19596), EPG_EVENT_CONTENTMASK_ARTSCULTURE);
135 labels.emplace_back(g_localizeStrings.Get(19612), EPG_EVENT_CONTENTMASK_SOCIALPOLITICALECONOMICS);
136 labels.emplace_back(g_localizeStrings.Get(19628), EPG_EVENT_CONTENTMASK_EDUCATIONALSCIENCE);
137 labels.emplace_back(g_localizeStrings.Get(19644), EPG_EVENT_CONTENTMASK_LEISUREHOBBIES);
138 labels.emplace_back(g_localizeStrings.Get(19660), EPG_EVENT_CONTENTMASK_SPECIAL);
139 labels.emplace_back(g_localizeStrings.Get(19499), EPG_EVENT_CONTENTMASK_USERDEFINED);
141 SET_CONTROL_LABELS(CONTROL_SPIN_GENRE, m_searchFilter->GetGenreType(), &labels);
144 void CGUIDialogPVRGuideSearch::UpdateDurationSpin()
146 /* minimum duration */
147 std::vector< std::pair<std::string, int> > labels;
149 labels.emplace_back("-", EPG_SEARCH_UNSET);
150 for (int i = 1; i < 12*60/5; ++i)
151 labels.emplace_back(StringUtils::Format(g_localizeStrings.Get(14044), i * 5), i * 5);
153 SET_CONTROL_LABELS(CONTROL_SPIN_MIN_DURATION, m_searchFilter->GetMinimumDuration(), &labels);
155 /* maximum duration */
156 labels.clear();
158 labels.emplace_back("-", EPG_SEARCH_UNSET);
159 for (int i = 1; i < 12*60/5; ++i)
160 labels.emplace_back(StringUtils::Format(g_localizeStrings.Get(14044), i * 5), i * 5);
162 SET_CONTROL_LABELS(CONTROL_SPIN_MAX_DURATION, m_searchFilter->GetMaximumDuration(), &labels);
165 bool CGUIDialogPVRGuideSearch::OnMessage(CGUIMessage& message)
167 CGUIDialog::OnMessage(message);
169 switch (message.GetMessage())
171 case GUI_MSG_CLICKED:
173 int iControl = message.GetSenderId();
174 if (iControl == CONTROL_BTN_SEARCH)
176 // Read data from controls, update m_searchfilter accordingly
177 UpdateSearchFilter();
179 m_result = Result::SEARCH;
180 Close();
181 return true;
183 else if (iControl == CONTROL_BTN_CANCEL)
185 m_result = Result::CANCEL;
186 Close();
187 return true;
189 else if (iControl == CONTROL_BTN_DEFAULTS)
191 if (m_searchFilter)
193 m_searchFilter->Reset();
194 Update();
196 return true;
198 else if (iControl == CONTROL_BTN_SAVE)
200 // Read data from controls, update m_searchfilter accordingly
201 UpdateSearchFilter();
203 std::string title = m_searchFilter->GetTitle();
204 if (title.empty())
206 title = m_searchFilter->GetSearchTerm();
207 if (title.empty())
208 title = g_localizeStrings.Get(137); // "Search"
209 else
210 StringUtils::Trim(title, "\"");
212 if (!CGUIKeyboardFactory::ShowAndGetInput(
213 title, CVariant{g_localizeStrings.Get(528)}, // "Enter title"
214 false))
216 return false;
218 m_searchFilter->SetTitle(title);
221 m_result = Result::SAVE;
222 Close();
223 return true;
225 else if (iControl == CONTROL_SPIN_GROUPS)
227 UpdateChannelSpin();
228 return true;
230 else if (iControl == CONTROL_BTN_START_ANY_TIME || iControl == CONTROL_BTN_END_ANY_TIME)
232 UpdateSearchFilter();
233 Update();
234 return true;
237 break;
240 return false;
243 void CGUIDialogPVRGuideSearch::OnInitWindow()
245 CGUIDialog::OnInitWindow();
247 m_result = Result::CANCEL;
250 void CGUIDialogPVRGuideSearch::OnWindowLoaded()
252 Update();
253 return CGUIDialog::OnWindowLoaded();
256 CDateTime CGUIDialogPVRGuideSearch::ReadDateTime(const std::string& strDate, const std::string& strTime) const
258 CDateTime dateTime;
259 int iHours, iMinutes;
260 sscanf(strTime.c_str(), "%d:%d", &iHours, &iMinutes);
261 dateTime.SetFromDBDate(strDate);
262 dateTime.SetDateTime(dateTime.GetYear(), dateTime.GetMonth(), dateTime.GetDay(), iHours, iMinutes, 0);
263 return dateTime.GetAsUTCDateTime();
266 bool CGUIDialogPVRGuideSearch::IsRadioSelected(int controlID)
268 CGUIMessage msg(GUI_MSG_IS_SELECTED, GetID(), controlID);
269 OnMessage(msg);
270 return (msg.GetParam1() == 1);
273 int CGUIDialogPVRGuideSearch::GetSpinValue(int controlID)
275 CGUIMessage msg(GUI_MSG_ITEM_SELECTED, GetID(), controlID);
276 OnMessage(msg);
277 return msg.GetParam1();
280 std::string CGUIDialogPVRGuideSearch::GetEditValue(int controlID)
282 CGUIMessage msg(GUI_MSG_ITEM_SELECTED, GetID(), controlID);
283 OnMessage(msg);
284 return msg.GetLabel();
287 void CGUIDialogPVRGuideSearch::UpdateSearchFilter()
289 if (!m_searchFilter)
290 return;
292 m_searchFilter->SetSearchTerm(GetEditValue(CONTROL_EDIT_SEARCH));
294 m_searchFilter->SetSearchInDescription(IsRadioSelected(CONTROL_BTN_INC_DESC));
295 m_searchFilter->SetCaseSensitive(IsRadioSelected(CONTROL_BTN_CASE_SENS));
296 m_searchFilter->SetFreeToAirOnly(IsRadioSelected(CONTROL_BTN_FTA_ONLY));
297 m_searchFilter->SetIncludeUnknownGenres(IsRadioSelected(CONTROL_BTN_UNK_GENRE));
298 m_searchFilter->SetIgnorePresentRecordings(IsRadioSelected(CONTROL_BTN_IGNORE_REC));
299 m_searchFilter->SetIgnorePresentTimers(IsRadioSelected(CONTROL_BTN_IGNORE_TMR));
300 m_searchFilter->SetRemoveDuplicates(IsRadioSelected(CONTROL_SPIN_NO_REPEATS));
301 m_searchFilter->SetIgnoreFinishedBroadcasts(IsRadioSelected(CONTROL_BTN_IGNORE_FINISHED));
302 m_searchFilter->SetIgnoreFutureBroadcasts(IsRadioSelected(CONTROL_BTN_IGNORE_FUTURE));
303 m_searchFilter->SetGenreType(GetSpinValue(CONTROL_SPIN_GENRE));
304 m_searchFilter->SetMinimumDuration(GetSpinValue(CONTROL_SPIN_MIN_DURATION));
305 m_searchFilter->SetMaximumDuration(GetSpinValue(CONTROL_SPIN_MAX_DURATION));
307 auto it = m_channelsMap.find(GetSpinValue(CONTROL_SPIN_CHANNELS));
308 m_searchFilter->SetClientID(it == m_channelsMap.end() ? PVR_CLIENT_INVALID_UID
309 : (*it).second->ChannelClientID());
310 m_searchFilter->SetChannelUID(it == m_channelsMap.end() ? -1 : (*it).second->ChannelUID());
311 m_searchFilter->SetChannelGroupID(GetSpinValue(CONTROL_SPIN_GROUPS));
313 const CDateTime start =
314 ReadDateTime(GetEditValue(CONTROL_EDIT_START_DATE), GetEditValue(CONTROL_EDIT_START_TIME));
315 if (start != m_startDateTime)
317 m_searchFilter->SetStartDateTime(start);
318 m_startDateTime = start;
320 const CDateTime end =
321 ReadDateTime(GetEditValue(CONTROL_EDIT_STOP_DATE), GetEditValue(CONTROL_EDIT_STOP_TIME));
322 if (end != m_endDateTime)
324 m_searchFilter->SetEndDateTime(end);
325 m_endDateTime = end;
328 m_searchFilter->SetStartAnyTime(IsRadioSelected(CONTROL_BTN_START_ANY_TIME));
329 m_searchFilter->SetEndAnyTime(IsRadioSelected(CONTROL_BTN_END_ANY_TIME));
332 void CGUIDialogPVRGuideSearch::Update()
334 if (!m_searchFilter)
335 return;
337 SET_CONTROL_LABEL2(CONTROL_EDIT_SEARCH, m_searchFilter->GetSearchTerm());
339 CGUIMessage msg(GUI_MSG_SET_TYPE, GetID(), CONTROL_EDIT_SEARCH, CGUIEditControl::INPUT_TYPE_TEXT, 16017);
340 OnMessage(msg);
343 SET_CONTROL_SELECTED(GetID(), CONTROL_BTN_CASE_SENS, m_searchFilter->IsCaseSensitive());
344 SET_CONTROL_SELECTED(GetID(), CONTROL_BTN_INC_DESC, m_searchFilter->ShouldSearchInDescription());
345 SET_CONTROL_SELECTED(GetID(), CONTROL_BTN_FTA_ONLY, m_searchFilter->IsFreeToAirOnly());
346 SET_CONTROL_SELECTED(GetID(), CONTROL_BTN_UNK_GENRE, m_searchFilter->ShouldIncludeUnknownGenres());
347 SET_CONTROL_SELECTED(GetID(), CONTROL_BTN_IGNORE_REC, m_searchFilter->ShouldIgnorePresentRecordings());
348 SET_CONTROL_SELECTED(GetID(), CONTROL_BTN_IGNORE_TMR, m_searchFilter->ShouldIgnorePresentTimers());
349 SET_CONTROL_SELECTED(GetID(), CONTROL_SPIN_NO_REPEATS, m_searchFilter->ShouldRemoveDuplicates());
350 SET_CONTROL_SELECTED(GetID(), CONTROL_BTN_IGNORE_FINISHED,
351 m_searchFilter->ShouldIgnoreFinishedBroadcasts());
352 SET_CONTROL_SELECTED(GetID(), CONTROL_BTN_IGNORE_FUTURE,
353 m_searchFilter->ShouldIgnoreFutureBroadcasts());
354 SET_CONTROL_SELECTED(GetID(), CONTROL_BTN_START_ANY_TIME, m_searchFilter->IsStartAnyTime());
355 SET_CONTROL_SELECTED(GetID(), CONTROL_BTN_END_ANY_TIME, m_searchFilter->IsEndAnyTime());
356 CONTROL_ENABLE_ON_CONDITION(CONTROL_EDIT_START_TIME, !m_searchFilter->IsStartAnyTime());
357 CONTROL_ENABLE_ON_CONDITION(CONTROL_EDIT_STOP_TIME, !m_searchFilter->IsEndAnyTime());
359 // Set start/end datetime fields
360 m_startDateTime = m_searchFilter->GetStartDateTime();
361 m_endDateTime = m_searchFilter->GetEndDateTime();
362 if (!m_startDateTime.IsValid() || !m_endDateTime.IsValid())
364 const auto dates = CServiceBroker::GetPVRManager().EpgContainer().GetFirstAndLastEPGDate();
365 if (!m_startDateTime.IsValid())
366 m_startDateTime = dates.first;
367 if (!m_endDateTime.IsValid())
368 m_endDateTime = dates.second;
371 if (!m_startDateTime.IsValid())
372 m_startDateTime = CDateTime::GetUTCDateTime();
374 if (!m_endDateTime.IsValid())
375 m_endDateTime = m_startDateTime + CDateTimeSpan(10, 0, 0, 0); // default to start + 10 days
377 CDateTime startLocal;
378 startLocal.SetFromUTCDateTime(m_startDateTime);
379 CDateTime endLocal;
380 endLocal.SetFromUTCDateTime(m_endDateTime);
382 SET_CONTROL_LABEL2(CONTROL_EDIT_START_TIME, startLocal.GetAsLocalizedTime("", false));
384 CGUIMessage msg(GUI_MSG_SET_TYPE, GetID(), CONTROL_EDIT_START_TIME, CGUIEditControl::INPUT_TYPE_TIME, 14066);
385 OnMessage(msg);
387 SET_CONTROL_LABEL2(CONTROL_EDIT_STOP_TIME, endLocal.GetAsLocalizedTime("", false));
389 CGUIMessage msg(GUI_MSG_SET_TYPE, GetID(), CONTROL_EDIT_STOP_TIME, CGUIEditControl::INPUT_TYPE_TIME, 14066);
390 OnMessage(msg);
392 SET_CONTROL_LABEL2(CONTROL_EDIT_START_DATE, startLocal.GetAsDBDate());
394 CGUIMessage msg(GUI_MSG_SET_TYPE, GetID(), CONTROL_EDIT_START_DATE, CGUIEditControl::INPUT_TYPE_DATE, 14067);
395 OnMessage(msg);
397 SET_CONTROL_LABEL2(CONTROL_EDIT_STOP_DATE, endLocal.GetAsDBDate());
399 CGUIMessage msg(GUI_MSG_SET_TYPE, GetID(), CONTROL_EDIT_STOP_DATE, CGUIEditControl::INPUT_TYPE_DATE, 14067);
400 OnMessage(msg);
403 UpdateDurationSpin();
404 UpdateGroupsSpin();
405 UpdateChannelSpin();
406 UpdateGenreSpin();