Merge pull request #25922 from sarbes/shader-cleanup
[xbmc.git] / xbmc / dialogs / GUIDialogSmartPlaylistEditor.cpp
blobddfd0d9d0a1e9dee32d9a9eefaa0b2ee1e9385be
1 /*
2 * Copyright (C) 2005-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 "GUIDialogSmartPlaylistEditor.h"
11 #include "FileItem.h"
12 #include "FileItemList.h"
13 #include "GUIDialogContextMenu.h"
14 #include "GUIDialogSelect.h"
15 #include "GUIDialogSmartPlaylistRule.h"
16 #include "ServiceBroker.h"
17 #include "Util.h"
18 #include "filesystem/File.h"
19 #include "guilib/GUIComponent.h"
20 #include "guilib/GUIKeyboardFactory.h"
21 #include "guilib/GUIWindowManager.h"
22 #include "guilib/LocalizeStrings.h"
23 #include "input/actions/ActionIDs.h"
24 #include "profiles/ProfileManager.h"
25 #include "settings/Settings.h"
26 #include "settings/SettingsComponent.h"
27 #include "utils/SortUtils.h"
28 #include "utils/StringUtils.h"
29 #include "utils/URIUtils.h"
30 #include "utils/Variant.h"
32 #include <utility>
34 using namespace KODI;
36 #define CONTROL_HEADING 2
37 #define CONTROL_RULE_LIST 10
38 #define CONTROL_NAME 12
39 #define CONTROL_RULE_ADD 13
40 #define CONTROL_RULE_REMOVE 14
41 #define CONTROL_RULE_EDIT 15
42 #define CONTROL_MATCH 16
43 #define CONTROL_LIMIT 17
44 #define CONTROL_ORDER_FIELD 18
45 #define CONTROL_ORDER_DIRECTION 19
46 #define CONTROL_GROUP_BY 23
47 #define CONTROL_GROUP_MIXED 24
49 #define CONTROL_OK 20
50 #define CONTROL_CANCEL 21
51 #define CONTROL_TYPE 22
53 typedef struct
55 CGUIDialogSmartPlaylistEditor::PLAYLIST_TYPE type;
56 char string[13];
57 int localizedString;
58 } translateType;
60 static const translateType types[] = { { CGUIDialogSmartPlaylistEditor::TYPE_SONGS, "songs", 134 },
61 { CGUIDialogSmartPlaylistEditor::TYPE_ALBUMS, "albums", 132 },
62 { CGUIDialogSmartPlaylistEditor::TYPE_ARTISTS, "artists", 133 },
63 { CGUIDialogSmartPlaylistEditor::TYPE_MIXED, "mixed", 20395 },
64 { CGUIDialogSmartPlaylistEditor::TYPE_MUSICVIDEOS, "musicvideos", 20389 },
65 { CGUIDialogSmartPlaylistEditor::TYPE_MOVIES, "movies", 20342 },
66 { CGUIDialogSmartPlaylistEditor::TYPE_TVSHOWS, "tvshows", 20343 },
67 { CGUIDialogSmartPlaylistEditor::TYPE_EPISODES, "episodes", 20360 }
70 CGUIDialogSmartPlaylistEditor::CGUIDialogSmartPlaylistEditor(void)
71 : CGUIDialog(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR, "SmartPlaylistEditor.xml")
73 m_cancelled = false;
74 m_ruleLabels = new CFileItemList;
75 m_loadType = KEEP_IN_MEMORY;
78 CGUIDialogSmartPlaylistEditor::~CGUIDialogSmartPlaylistEditor()
80 delete m_ruleLabels;
83 bool CGUIDialogSmartPlaylistEditor::OnBack(int actionID)
85 m_cancelled = true;
86 return CGUIDialog::OnBack(actionID);
89 bool CGUIDialogSmartPlaylistEditor::OnMessage(CGUIMessage& message)
91 switch ( message.GetMessage() )
93 case GUI_MSG_CLICKED:
95 int iControl = message.GetSenderId();
96 int iAction = message.GetParam1();
97 if (iControl == CONTROL_RULE_LIST && (iAction == ACTION_SELECT_ITEM || iAction == ACTION_MOUSE_LEFT_CLICK))
98 OnRuleList(GetSelectedItem());
99 else if (iControl == CONTROL_RULE_ADD)
100 OnRuleAdd();
101 else if (iControl == CONTROL_RULE_EDIT)
102 OnRuleList(GetSelectedItem());
103 else if (iControl == CONTROL_RULE_REMOVE)
104 OnRuleRemove(GetSelectedItem());
105 else if (iControl == CONTROL_NAME)
106 OnName();
107 else if (iControl == CONTROL_OK)
108 OnOK();
109 else if (iControl == CONTROL_CANCEL)
110 OnCancel();
111 else if (iControl == CONTROL_MATCH)
112 OnMatch();
113 else if (iControl == CONTROL_LIMIT)
114 OnLimit();
115 else if (iControl == CONTROL_ORDER_FIELD)
116 OnOrder();
117 else if (iControl == CONTROL_ORDER_DIRECTION)
118 OnOrderDirection();
119 else if (iControl == CONTROL_TYPE)
120 OnType();
121 else if (iControl == CONTROL_GROUP_BY)
122 OnGroupBy();
123 else if (iControl == CONTROL_GROUP_MIXED)
124 OnGroupMixed();
125 else if (iControl == CONTROL_RULE_LIST && (iAction == ACTION_CONTEXT_MENU || iAction == ACTION_MOUSE_RIGHT_CLICK))
126 OnPopupMenu(GetSelectedItem());
127 else
128 return CGUIDialog::OnMessage(message);
129 return true;
131 break;
132 case GUI_MSG_FOCUSED:
133 if (message.GetControlId() == CONTROL_RULE_REMOVE ||
134 message.GetControlId() == CONTROL_RULE_EDIT)
135 HighlightItem(GetSelectedItem());
136 else
138 if (message.GetControlId() == CONTROL_RULE_LIST)
139 UpdateRuleControlButtons();
141 HighlightItem(-1);
143 break;
144 case GUI_MSG_WINDOW_INIT:
146 const std::string& startupList = message.GetStringParam(0);
147 if (!startupList.empty())
149 int party = 0;
150 if (URIUtils::PathEquals(startupList, CServiceBroker::GetSettingsComponent()->GetProfileManager()->GetUserDataItem("PartyMode.xsp")))
151 party = 1;
152 else if (URIUtils::PathEquals(startupList, CServiceBroker::GetSettingsComponent()->GetProfileManager()->GetUserDataItem("PartyMode-Video.xsp")))
153 party = 2;
155 if ((party && !XFILE::CFile::Exists(startupList)) ||
156 m_playlist.Load(startupList))
158 m_path = startupList;
160 if (party == 1)
161 m_mode = "partymusic";
162 else if (party == 2)
163 m_mode = "partyvideo";
164 else
166 PLAYLIST_TYPE type = ConvertType(m_playlist.GetType());
167 if (type == TYPE_SONGS || type == TYPE_ALBUMS || type == TYPE_ARTISTS)
168 m_mode = "music";
169 else
170 m_mode = "video";
173 else
174 return false;
177 break;
178 case GUI_MSG_WINDOW_DEINIT:
180 m_playlist.Reset();
182 break;
184 return CGUIDialog::OnMessage(message);
187 void CGUIDialogSmartPlaylistEditor::OnPopupMenu(int item)
189 if (item < 0 || static_cast<size_t>(item) >= m_playlist.m_ruleCombination.m_rules.size())
190 return;
191 // highlight the item
192 m_ruleLabels->Get(item)->Select(true);
194 CContextButtons choices;
195 choices.Add(1, 15015);
197 int button = CGUIDialogContextMenu::ShowAndGetChoice(choices);
199 // unhighlight the item
200 m_ruleLabels->Get(item)->Select(false);
202 if (button == 1)
203 OnRuleRemove(item);
206 void CGUIDialogSmartPlaylistEditor::OnRuleList(int item)
208 if (item < 0 || item > static_cast<int>(m_playlist.m_ruleCombination.m_rules.size()))
209 return;
210 if (item == static_cast<int>(m_playlist.m_ruleCombination.m_rules.size()))
211 OnRuleAdd();
212 else
214 auto rule = *std::static_pointer_cast<PLAYLIST::CSmartPlaylistRule>(
215 m_playlist.m_ruleCombination.m_rules[item]);
216 if (CGUIDialogSmartPlaylistRule::EditRule(rule, m_playlist.GetType()))
217 *m_playlist.m_ruleCombination.m_rules[item] = rule;
219 UpdateButtons();
222 void CGUIDialogSmartPlaylistEditor::OnOK()
224 std::string systemPlaylistsPath = CServiceBroker::GetSettingsComponent()->GetSettings()->GetString(CSettings::SETTING_SYSTEM_PLAYLISTSPATH);
225 // save our playlist
226 if (m_path.empty())
228 std::string filename(CUtil::MakeLegalFileName(m_playlist.m_playlistName));
229 std::string path;
230 if (CGUIKeyboardFactory::ShowAndGetInput(filename, CVariant{g_localizeStrings.Get(16013)}, false))
232 path = URIUtils::AddFileToFolder(systemPlaylistsPath, m_playlist.GetSaveLocation(),
233 CUtil::MakeLegalFileName(std::move(filename)));
235 else
236 return;
237 if (!URIUtils::HasExtension(path, ".xsp"))
238 path += ".xsp";
240 // should we check whether we should overwrite?
241 m_path = path;
243 else
245 // check if we need to actually change the save location for this playlist
246 // this occurs if the user switches from music video <> songs <> mixed
247 if (StringUtils::StartsWith(m_path, systemPlaylistsPath))
249 std::string filename = URIUtils::GetFileName(m_path);
250 std::string strFolder = m_path.substr(systemPlaylistsPath.size(), m_path.size() - filename.size() - systemPlaylistsPath.size() - 1);
251 if (strFolder != m_playlist.GetSaveLocation())
252 { // move to the correct folder
253 XFILE::CFile::Delete(m_path);
254 m_path = URIUtils::AddFileToFolder(systemPlaylistsPath, m_playlist.GetSaveLocation(), filename);
259 m_playlist.Save(m_path);
261 m_cancelled = false;
262 Close();
265 void CGUIDialogSmartPlaylistEditor::OnCancel()
267 m_cancelled = true;
268 Close();
271 void CGUIDialogSmartPlaylistEditor::OnMatch()
273 // toggle between AND and OR setting
274 if (m_playlist.m_ruleCombination.GetType() ==
275 PLAYLIST::CSmartPlaylistRuleCombination::CombinationOr)
276 m_playlist.m_ruleCombination.SetType(PLAYLIST::CSmartPlaylistRuleCombination::CombinationAnd);
277 else
278 m_playlist.m_ruleCombination.SetType(PLAYLIST::CSmartPlaylistRuleCombination::CombinationOr);
279 UpdateButtons();
282 void CGUIDialogSmartPlaylistEditor::OnName()
284 std::string name = m_playlist.m_playlistName;
285 if (CGUIKeyboardFactory::ShowAndGetInput(name, CVariant{16012}, false))
287 m_playlist.m_playlistName = name;
288 UpdateButtons();
292 void CGUIDialogSmartPlaylistEditor::OnLimit()
294 std::vector<int> limits = {0, 10, 25, 50, 100, 250, 500, 1000};
295 CGUIDialogSelect* dialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogSelect>(WINDOW_DIALOG_SELECT);
296 dialog->Reset();
297 int selected = -1;
298 for (auto limit = limits.begin(); limit != limits.end(); limit++)
300 if (*limit == static_cast<int>(m_playlist.m_limit))
301 selected = std::distance(limits.begin(), limit);
302 if (*limit == 0)
303 dialog->Add(g_localizeStrings.Get(21428));
304 else
305 dialog->Add(StringUtils::Format(g_localizeStrings.Get(21436), *limit));
307 dialog->SetHeading(CVariant{ 21427 });
308 dialog->SetSelected(selected);
309 dialog->Open();
310 int newSelected = dialog->GetSelectedItem();
311 if (!dialog->IsConfirmed() || newSelected < 0 || limits[newSelected] == static_cast<int>(m_playlist.m_limit))
312 return;
313 m_playlist.m_limit = limits[newSelected];
314 UpdateButtons();
317 void CGUIDialogSmartPlaylistEditor::OnType()
319 std::vector<PLAYLIST_TYPE> allowedTypes = GetAllowedTypes(m_mode);
320 CGUIDialogSelect* dialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogSelect>(WINDOW_DIALOG_SELECT);
321 dialog->Reset();
322 for (auto allowedType: allowedTypes)
323 dialog->Add(GetLocalizedType(allowedType));
324 dialog->SetHeading(CVariant{ 564 });
325 dialog->SetSelected(GetLocalizedType(ConvertType(m_playlist.GetType())));
326 dialog->Open();
327 int newSelected = dialog->GetSelectedItem();
328 if (!dialog->IsConfirmed() || newSelected < 0 || allowedTypes[newSelected] == ConvertType(m_playlist.GetType()))
329 return;
331 m_playlist.SetType(ConvertType(allowedTypes[newSelected]));
333 // Remove any invalid grouping left over when changing the type
334 Field currentGroup = PLAYLIST::CSmartPlaylistRule::TranslateGroup(m_playlist.GetGroup().c_str());
335 if (currentGroup != FieldNone && currentGroup != FieldUnknown)
337 std::vector<Field> groups = PLAYLIST::CSmartPlaylistRule::GetGroups(m_playlist.GetType());
338 if (std::find(groups.begin(), groups.end(), currentGroup) == groups.end())
339 m_playlist.SetGroup(PLAYLIST::CSmartPlaylistRule::TranslateGroup(FieldUnknown));
342 UpdateButtons();
345 void CGUIDialogSmartPlaylistEditor::OnOrder()
347 std::vector<SortBy> orders = PLAYLIST::CSmartPlaylistRule::GetOrders(m_playlist.GetType());
348 CGUIDialogSelect* dialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogSelect>(WINDOW_DIALOG_SELECT);
349 dialog->Reset();
350 for (auto order: orders)
351 dialog->Add(g_localizeStrings.Get(SortUtils::GetSortLabel(order)));
352 dialog->SetHeading(CVariant{ 21429 });
353 dialog->SetSelected(g_localizeStrings.Get(SortUtils::GetSortLabel(m_playlist.m_orderField)));
354 dialog->Open();
355 int newSelected = dialog->GetSelectedItem();
356 if (!dialog->IsConfirmed() || newSelected < 0 || orders[newSelected] == m_playlist.m_orderField)
357 return;
358 m_playlist.m_orderField = orders[newSelected];
359 UpdateButtons();
362 void CGUIDialogSmartPlaylistEditor::OnOrderDirection()
364 if (m_playlist.m_orderDirection == SortOrderDescending)
365 m_playlist.m_orderDirection = SortOrderAscending;
366 else
367 m_playlist.m_orderDirection = SortOrderDescending;
368 UpdateButtons();
371 void CGUIDialogSmartPlaylistEditor::OnGroupBy()
373 std::vector<Field> groups = PLAYLIST::CSmartPlaylistRule::GetGroups(m_playlist.GetType());
374 Field currentGroup = PLAYLIST::CSmartPlaylistRule::TranslateGroup(m_playlist.GetGroup().c_str());
375 CGUIDialogSelect* dialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogSelect>(WINDOW_DIALOG_SELECT);
376 dialog->Reset();
377 for (auto group : groups)
378 dialog->Add(PLAYLIST::CSmartPlaylistRule::GetLocalizedGroup(group));
379 dialog->SetHeading(CVariant{ 21458 });
380 dialog->SetSelected(PLAYLIST::CSmartPlaylistRule::GetLocalizedGroup(currentGroup));
381 dialog->Open();
382 int newSelected = dialog->GetSelectedItem();
383 // check if selection has changed
384 if (!dialog->IsConfirmed() || newSelected < 0 || groups[newSelected] == currentGroup)
385 return;
386 m_playlist.SetGroup(PLAYLIST::CSmartPlaylistRule::TranslateGroup(groups[newSelected]));
388 if (m_playlist.IsGroupMixed() && !PLAYLIST::CSmartPlaylistRule::CanGroupMix(currentGroup))
389 m_playlist.SetGroupMixed(false);
391 UpdateButtons();
394 void CGUIDialogSmartPlaylistEditor::OnGroupMixed()
396 m_playlist.SetGroupMixed(!m_playlist.IsGroupMixed());
397 UpdateButtons();
400 void CGUIDialogSmartPlaylistEditor::UpdateButtons()
402 CONTROL_ENABLE(CONTROL_OK); // always enabled since we can have no rules -> match everything (as we do with default partymode playlists)
404 if (m_mode == "partyvideo" || m_mode == "partymusic")
406 SET_CONTROL_LABEL2(CONTROL_NAME, g_localizeStrings.Get(16035));
407 CONTROL_DISABLE(CONTROL_NAME);
409 else
410 SET_CONTROL_LABEL2(CONTROL_NAME, m_playlist.m_playlistName);
412 UpdateRuleControlButtons();
414 if (m_playlist.m_ruleCombination.GetType() ==
415 PLAYLIST::CSmartPlaylistRuleCombination::CombinationOr)
416 SET_CONTROL_LABEL2(CONTROL_MATCH, g_localizeStrings.Get(21426)); // one or more of the rules
417 else
418 SET_CONTROL_LABEL2(CONTROL_MATCH, g_localizeStrings.Get(21425)); // all of the rules
419 CONTROL_ENABLE_ON_CONDITION(CONTROL_MATCH, m_playlist.m_ruleCombination.m_rules.size() > 1);
420 if (m_playlist.m_limit == 0)
421 SET_CONTROL_LABEL2(CONTROL_LIMIT, g_localizeStrings.Get(21428)); // no limit
422 else
423 SET_CONTROL_LABEL2(CONTROL_LIMIT,
424 StringUtils::Format(g_localizeStrings.Get(21436), m_playlist.m_limit));
425 int currentItem = GetSelectedItem();
426 CGUIMessage msgReset(GUI_MSG_LABEL_RESET, GetID(), CONTROL_RULE_LIST);
427 OnMessage(msgReset);
428 m_ruleLabels->Clear();
429 for (const auto& rule: m_playlist.m_ruleCombination.m_rules)
431 CFileItemPtr item(new CFileItem("", false));
432 item->SetLabel(
433 std::static_pointer_cast<PLAYLIST::CSmartPlaylistRule>(rule)->GetLocalizedRule());
434 m_ruleLabels->Add(item);
436 CFileItemPtr item(new CFileItem("", false));
437 item->SetLabel(g_localizeStrings.Get(21423));
438 m_ruleLabels->Add(item);
439 CGUIMessage msg(GUI_MSG_LABEL_BIND, GetID(), CONTROL_RULE_LIST, 0, 0, m_ruleLabels);
440 OnMessage(msg);
441 SendMessage(GUI_MSG_ITEM_SELECT, GetID(), CONTROL_RULE_LIST, currentItem);
443 if (m_playlist.m_orderDirection != SortOrderDescending)
445 SET_CONTROL_LABEL2(CONTROL_ORDER_DIRECTION, g_localizeStrings.Get(21430));
447 else
449 SET_CONTROL_LABEL2(CONTROL_ORDER_DIRECTION, g_localizeStrings.Get(21431));
452 SET_CONTROL_LABEL2(CONTROL_ORDER_FIELD, g_localizeStrings.Get(SortUtils::GetSortLabel(m_playlist.m_orderField)));
453 SET_CONTROL_LABEL2(CONTROL_TYPE, GetLocalizedType(ConvertType(m_playlist.GetType())));
455 // setup groups
456 std::vector<Field> groups = PLAYLIST::CSmartPlaylistRule::GetGroups(m_playlist.GetType());
457 Field currentGroup = PLAYLIST::CSmartPlaylistRule::TranslateGroup(m_playlist.GetGroup().c_str());
458 SET_CONTROL_LABEL2(CONTROL_GROUP_BY,
459 PLAYLIST::CSmartPlaylistRule::GetLocalizedGroup(currentGroup));
460 if (m_playlist.IsGroupMixed())
461 CONTROL_SELECT(CONTROL_GROUP_MIXED);
462 else
463 CONTROL_DESELECT(CONTROL_GROUP_MIXED);
465 // disable the group controls if there's no group
466 // or only one group which can't be mixed
467 if (groups.empty() ||
468 (groups.size() == 1 && !PLAYLIST::CSmartPlaylistRule::CanGroupMix(groups[0])))
470 CONTROL_DISABLE(CONTROL_GROUP_BY);
471 CONTROL_DISABLE(CONTROL_GROUP_MIXED);
473 else
475 CONTROL_ENABLE(CONTROL_GROUP_BY);
476 CONTROL_ENABLE_ON_CONDITION(CONTROL_GROUP_MIXED,
477 PLAYLIST::CSmartPlaylistRule::CanGroupMix(currentGroup));
481 void CGUIDialogSmartPlaylistEditor::UpdateRuleControlButtons()
483 int iSize = m_playlist.m_ruleCombination.m_rules.size();
484 int iItem = GetSelectedItem();
485 // only enable the remove control if ...
486 CONTROL_ENABLE_ON_CONDITION(CONTROL_RULE_REMOVE,
487 iSize > 0 && // there is at least one item
488 iItem >= 0 && iItem < iSize && // and a valid item is selected
489 m_playlist.m_ruleCombination.m_rules[iItem]->m_field != FieldNone); // and it is not be empty
492 void CGUIDialogSmartPlaylistEditor::OnInitWindow()
494 m_cancelled = false;
496 std::vector<PLAYLIST_TYPE> allowedTypes = GetAllowedTypes(m_mode);
497 // check if our playlist type is allowed
498 PLAYLIST_TYPE type = ConvertType(m_playlist.GetType());
499 bool allowed = false;
500 for (auto allowedType: allowedTypes)
502 if (type == allowedType)
503 allowed = true;
505 if (!allowed && allowedTypes.size())
506 m_playlist.SetType(ConvertType(allowedTypes[0]));
508 UpdateButtons();
510 SET_CONTROL_LABEL(CONTROL_HEADING, 21432);
512 CGUIDialog::OnInitWindow();
515 void CGUIDialogSmartPlaylistEditor::OnDeinitWindow(int nextWindowID)
517 CGUIDialog::OnDeinitWindow(nextWindowID);
518 SendMessage(GUI_MSG_LABEL_RESET, CONTROL_RULE_LIST);
519 SendMessage(GUI_MSG_LABEL_RESET, CONTROL_TYPE);
520 m_ruleLabels->Clear();
523 CGUIDialogSmartPlaylistEditor::PLAYLIST_TYPE CGUIDialogSmartPlaylistEditor::ConvertType(const std::string &type)
525 for (const translateType& t : types)
526 if (type == t.string)
527 return t.type;
528 assert(false);
529 return TYPE_SONGS;
532 std::string CGUIDialogSmartPlaylistEditor::GetLocalizedType(PLAYLIST_TYPE type)
534 for (const translateType& t : types)
535 if (t.type == type)
536 return g_localizeStrings.Get(t.localizedString);
537 assert(false);
538 return "";
541 std::string CGUIDialogSmartPlaylistEditor::ConvertType(PLAYLIST_TYPE type)
543 for (const translateType& t : types)
544 if (t.type == type)
545 return t.string;
546 assert(false);
547 return "songs";
550 int CGUIDialogSmartPlaylistEditor::GetSelectedItem()
552 CGUIMessage message(GUI_MSG_ITEM_SELECTED, GetID(), CONTROL_RULE_LIST);
553 OnMessage(message);
554 return message.GetParam1();
557 void CGUIDialogSmartPlaylistEditor::HighlightItem(int item)
559 for (int i = 0; i < m_ruleLabels->Size(); i++)
560 (*m_ruleLabels)[i]->Select(false);
561 if (item >= 0 && item < m_ruleLabels->Size())
562 (*m_ruleLabels)[item]->Select(true);
563 CGUIMessage msg(GUI_MSG_ITEM_SELECT, GetID(), CONTROL_RULE_LIST, item);
564 OnMessage(msg);
567 std::vector<CGUIDialogSmartPlaylistEditor::PLAYLIST_TYPE> CGUIDialogSmartPlaylistEditor::GetAllowedTypes(const std::string& mode)
569 std::vector<PLAYLIST_TYPE> allowedTypes;
570 if (mode == "partymusic")
572 allowedTypes.push_back(TYPE_SONGS);
573 allowedTypes.push_back(TYPE_MIXED);
575 else if (mode == "partyvideo")
577 allowedTypes.push_back(TYPE_MUSICVIDEOS);
578 allowedTypes.push_back(TYPE_MIXED);
580 else if (mode == "music")
581 { // music types + mixed
582 allowedTypes.push_back(TYPE_SONGS);
583 allowedTypes.push_back(TYPE_ALBUMS);
584 allowedTypes.push_back(TYPE_ARTISTS);
585 allowedTypes.push_back(TYPE_MIXED);
587 else if (mode == "video")
588 { // general category for videos
589 allowedTypes.push_back(TYPE_MOVIES);
590 allowedTypes.push_back(TYPE_TVSHOWS);
591 allowedTypes.push_back(TYPE_EPISODES);
592 allowedTypes.push_back(TYPE_MUSICVIDEOS);
593 allowedTypes.push_back(TYPE_MIXED);
595 return allowedTypes;
598 void CGUIDialogSmartPlaylistEditor::OnRuleRemove(int item)
600 if (item < 0 || item >= (int)m_playlist.m_ruleCombination.m_rules.size()) return;
601 m_playlist.m_ruleCombination.m_rules.erase(m_playlist.m_ruleCombination.m_rules.begin() + item);
603 UpdateButtons();
604 if (item >= m_ruleLabels->Size())
605 HighlightItem(m_ruleLabels->Size() - 1);
606 else
607 HighlightItem(item);
610 void CGUIDialogSmartPlaylistEditor::OnRuleAdd()
612 PLAYLIST::CSmartPlaylistRule rule;
613 if (CGUIDialogSmartPlaylistRule::EditRule(rule,m_playlist.GetType()))
614 m_playlist.m_ruleCombination.AddRule(rule);
615 UpdateButtons();
618 bool CGUIDialogSmartPlaylistEditor::NewPlaylist(const std::string &type)
620 CGUIDialogSmartPlaylistEditor *editor = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogSmartPlaylistEditor>(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
621 if (!editor) return false;
623 editor->m_path = "";
624 editor->m_playlist = PLAYLIST::CSmartPlaylist();
625 editor->m_mode = type;
626 editor->Initialize();
627 editor->Open();
628 return !editor->m_cancelled;
631 bool CGUIDialogSmartPlaylistEditor::EditPlaylist(const std::string &path, const std::string &type)
633 CGUIDialogSmartPlaylistEditor *editor = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogSmartPlaylistEditor>(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR);
634 if (!editor) return false;
636 editor->m_mode = type;
637 if (URIUtils::PathEquals(path, CServiceBroker::GetSettingsComponent()->GetProfileManager()->GetUserDataItem("PartyMode.xsp")))
638 editor->m_mode = "partymusic";
639 if (URIUtils::PathEquals(path, CServiceBroker::GetSettingsComponent()->GetProfileManager()->GetUserDataItem("PartyMode-Video.xsp")))
640 editor->m_mode = "partyvideo";
642 PLAYLIST::CSmartPlaylist playlist;
643 bool loaded(playlist.Load(path));
644 if (!loaded)
645 { // failed to load
646 if (!StringUtils::StartsWithNoCase(editor->m_mode, "party"))
647 return false; // only edit normal playlists that exist
648 // party mode playlists can be edited even if they don't exist
649 playlist.SetType(editor->m_mode == "partymusic" ? "songs" : "musicvideos");
652 editor->m_playlist = playlist;
653 editor->m_path = path;
654 editor->Initialize();
655 editor->Open();
656 return !editor->m_cancelled;