2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
22 #include "GUIDialogContextMenu.h"
23 #include "guilib/GUIButtonControl.h"
24 #include "guilib/GUIControlGroupList.h"
25 #include "GUIDialogFileBrowser.h"
26 #include "GUIUserMessages.h"
28 #include "GUIPassword.h"
30 #include "utils/URIUtils.h"
31 #include "settings/MediaSourceSettings.h"
32 #include "settings/Settings.h"
33 #include "GUIDialogMediaSource.h"
34 #include "profiles/ProfilesManager.h"
35 #include "profiles/dialogs/GUIDialogLockSettings.h"
36 #include "storage/MediaManager.h"
37 #include "guilib/GUIWindowManager.h"
38 #include "guilib/Key.h"
39 #include "GUIDialogYesNo.h"
40 #include "addons/AddonManager.h"
42 #include "filesystem/File.h"
43 #include "guilib/LocalizeStrings.h"
44 #include "TextureCache.h"
45 #include "video/windows/GUIWindowVideoBase.h"
47 #include "utils/StringUtils.h"
50 #include "WIN32Util.h"
55 #define BACKGROUND_IMAGE 999
56 #if PRE_SKIN_VERSION_11_COMPATIBILITY
57 #define BACKGROUND_BOTTOM 998
58 #define BACKGROUND_TOP 997
59 #define SPACE_BETWEEN_BUTTONS 2
61 #define GROUP_LIST 996
62 #define BUTTON_TEMPLATE 1000
63 #define BUTTON_START 1001
64 #define BUTTON_END (BUTTON_START + (int)m_buttons.size() - 1)
66 void CContextButtons::Add(unsigned int button, const CStdString &label)
68 push_back(pair<unsigned int, CStdString>(button, label));
71 void CContextButtons::Add(unsigned int button, int label)
73 push_back(pair<unsigned int, CStdString>(button, g_localizeStrings.Get(label)));
76 CGUIDialogContextMenu::CGUIDialogContextMenu(void)
77 : CGUIDialog(WINDOW_DIALOG_CONTEXT_MENU, "DialogContextMenu.xml")
80 m_backgroundImageSize = 0;
81 m_loadType = KEEP_IN_MEMORY;
84 CGUIDialogContextMenu::~CGUIDialogContextMenu(void)
88 bool CGUIDialogContextMenu::OnMessage(CGUIMessage &message)
90 if (message.GetMessage() == GUI_MSG_CLICKED)
91 { // someone has been clicked - deinit...
92 if (message.GetSenderId() >= BUTTON_START && message.GetSenderId() <= BUTTON_END)
93 m_clickedButton = (int)m_buttons[message.GetSenderId() - BUTTON_START].first;
97 return CGUIDialog::OnMessage(message);
100 bool CGUIDialogContextMenu::OnAction(const CAction& action)
102 if (action.GetID() == ACTION_CONTEXT_MENU)
108 return CGUIDialog::OnAction(action);
111 void CGUIDialogContextMenu::OnInitWindow()
113 m_clickedButton = -1;
114 // set initial control focus
115 m_lastControlID = BUTTON_START;
116 CGUIDialog::OnInitWindow();
119 void CGUIDialogContextMenu::SetupButtons()
121 if (!m_buttons.size())
124 // disable the template button control
125 CGUIButtonControl *pButtonTemplate = (CGUIButtonControl *)GetFirstFocusableControl(BUTTON_TEMPLATE);
126 if (!pButtonTemplate) pButtonTemplate = (CGUIButtonControl *)GetControl(BUTTON_TEMPLATE);
127 if (!pButtonTemplate)
129 pButtonTemplate->SetVisible(false);
131 CGUIControlGroupList* pGroupList = NULL;
133 const CGUIControl* pControl = GetControl(GROUP_LIST);
134 if (pControl && pControl->GetControlType() == GUICONTROL_GROUPLIST)
135 pGroupList = (CGUIControlGroupList*)pControl;
139 for (unsigned int i = 0; i < m_buttons.size(); i++)
141 CGUIButtonControl *pButton = new CGUIButtonControl(*pButtonTemplate);
143 { // set the button's ID and position
144 int id = BUTTON_START + i;
146 pButton->SetVisible(true);
147 pButton->SetLabel(m_buttons[i].second);
150 pButton->SetPosition(pButtonTemplate->GetXPosition(), pButtonTemplate->GetYPosition());
151 // try inserting context buttons at position specified by template
152 // button, if template button is not in grouplist fallback to adding
153 // new buttons at the end of grouplist
154 if (!pGroupList->InsertControl(pButton, pButtonTemplate))
155 pGroupList->AddControl(pButton);
157 #if PRE_SKIN_VERSION_11_COMPATIBILITY
160 pButton->SetPosition(pButtonTemplate->GetXPosition(), i*(pButtonTemplate->GetHeight() + SPACE_BETWEEN_BUTTONS));
161 pButton->SetNavigation(id - 1, id + 1, id, id);
168 CGUIControl *pControl = NULL;
169 #if PRE_SKIN_VERSION_11_COMPATIBILITY
172 // if we don't have grouplist update the navigation of the first and last buttons
173 pControl = (CGUIControl *)GetControl(BUTTON_START);
175 pControl->SetNavigation(BUTTON_END, pControl->GetControlIdDown(), pControl->GetControlIdLeft(), pControl->GetControlIdRight());
176 pControl = (CGUIControl *)GetControl(BUTTON_END);
178 pControl->SetNavigation(pControl->GetControlIdUp(), BUTTON_START, pControl->GetControlIdLeft(), pControl->GetControlIdRight());
182 // fix up background images placement and size
183 pControl = (CGUIControl *)GetControl(BACKGROUND_IMAGE);
186 // first set size of background image
189 if (pGroupList->GetOrientation() == VERTICAL)
191 // keep gap between bottom edges of grouplist and background image
192 pControl->SetHeight(m_backgroundImageSize - pGroupList->Size() + pGroupList->GetHeight());
196 // keep gap between right edges of grouplist and background image
197 pControl->SetWidth(m_backgroundImageSize - pGroupList->Size() + pGroupList->GetWidth());
200 #if PRE_SKIN_VERSION_11_COMPATIBILITY
202 pControl->SetHeight(m_buttons.size() * (pButtonTemplate->GetHeight() + SPACE_BETWEEN_BUTTONS));
204 if (pGroupList && pGroupList->GetOrientation() == HORIZONTAL)
206 // if there is grouplist control with horizontal orientation - adjust width of top and bottom background
207 CGUIControl* pControl2 = (CGUIControl *)GetControl(BACKGROUND_TOP);
209 pControl2->SetWidth(pControl->GetWidth());
211 pControl2 = (CGUIControl *)GetControl(BACKGROUND_BOTTOM);
213 pControl2->SetWidth(pControl->GetWidth());
217 // adjust position of bottom background
218 CGUIControl* pControl2 = (CGUIControl *)GetControl(BACKGROUND_BOTTOM);
220 pControl2->SetPosition(pControl2->GetXPosition(), pControl->GetYPosition() + pControl->GetHeight());
225 // update our default control
227 m_defaultControl = pGroupList->GetID();
228 #if PRE_SKIN_VERSION_11_COMPATIBILITY
231 if (m_defaultControl < BUTTON_START || m_defaultControl > BUTTON_END)
232 m_defaultControl = BUTTON_START;
233 while (m_defaultControl <= BUTTON_END && !(GetControl(m_defaultControl)->CanFocus()))
239 void CGUIDialogContextMenu::SetPosition(float posX, float posY)
241 if (posY + GetHeight() > m_coordsRes.iHeight)
242 posY = m_coordsRes.iHeight - GetHeight();
243 if (posY < 0) posY = 0;
244 if (posX + GetWidth() > m_coordsRes.iWidth)
245 posX = m_coordsRes.iWidth - GetWidth();
246 if (posX < 0) posX = 0;
247 #if PRE_SKIN_VERSION_11_COMPATIBILITY
248 // we currently hack the positioning of the buttons from y position 0, which
249 // forces skinners to place the top image at a negative y value. Thus, we offset
250 // the y coordinate by the height of the top image.
251 const CGUIControl *top = GetControl(BACKGROUND_TOP);
253 posY += top->GetHeight();
255 CGUIDialog::SetPosition(posX, posY);
258 float CGUIDialogContextMenu::GetHeight() const
260 const CGUIControl *backMain = GetControl(BACKGROUND_IMAGE);
262 #if PRE_SKIN_VERSION_11_COMPATIBILITY
264 float height = backMain->GetHeight();
265 const CGUIControl *backBottom = GetControl(BACKGROUND_BOTTOM);
267 height += backBottom->GetHeight();
268 const CGUIControl *backTop = GetControl(BACKGROUND_TOP);
270 height += backTop->GetHeight();
274 return backMain->GetHeight();
277 return CGUIDialog::GetHeight();
280 float CGUIDialogContextMenu::GetWidth() const
282 CGUIControl *pControl = (CGUIControl *)GetControl(BACKGROUND_IMAGE);
284 return pControl->GetWidth();
286 return CGUIDialog::GetWidth();
289 bool CGUIDialogContextMenu::SourcesMenu(const CStdString &strType, const CFileItemPtr item, float posX, float posY)
291 // TODO: This should be callable even if we don't have any valid items
295 // grab our context menu
296 CContextButtons buttons;
297 GetContextButtons(strType, item, buttons);
299 int button = ShowAndGetChoice(buttons);
301 return OnContextButton(strType, item, (CONTEXT_BUTTON)button);
305 void CGUIDialogContextMenu::GetContextButtons(const CStdString &type, const CFileItemPtr item, CContextButtons &buttons)
307 // Add buttons to the ContextMenu that should be visible for both sources and autosourced items
308 if (item && item->IsRemovable())
310 if (item->IsDVD() || item->IsCDDA())
312 // We need to check if there is a detected is inserted!
313 buttons.Add(CONTEXT_BUTTON_PLAY_DISC, 341); // Play CD/DVD!
314 if (CGUIWindowVideoBase::HasResumeItemOffset(item.get()))
315 buttons.Add(CONTEXT_BUTTON_RESUME_DISC, CGUIWindowVideoBase::GetResumeString(*(item.get()))); // Resume Disc
317 buttons.Add(CONTEXT_BUTTON_EJECT_DISC, 13391); // Eject/Load CD/DVD!
321 buttons.Add(CONTEXT_BUTTON_EJECT_DRIVE, 13420); // Eject Removable HDD!
326 // Next, Add buttons to the ContextMenu that should ONLY be visible for sources and not autosourced items
327 CMediaSource *share = GetShare(type, item.get());
329 if (CProfilesManager::Get().GetCurrentProfile().canWriteSources() || g_passwordManager.bMasterUser)
333 // Note. from now on, remove source & disable plugin should mean the same thing
334 //TODO might be smart to also combine editing source & plugin settings into one concept/dialog
335 // Note. Temporarily disabled ability to remove plugin sources until installer is operational
337 CURL url(share->strPath);
338 bool isAddon = ADDON::TranslateContent(url.GetProtocol()) != CONTENT_NONE;
339 if (!share->m_ignore && !isAddon)
340 buttons.Add(CONTEXT_BUTTON_EDIT_SOURCE, 1027); // Edit Source
343 ADDON::AddonPtr plugin;
344 if (ADDON::CAddonMgr::Get().GetAddon(url.GetHostName(), plugin))
345 if (plugin->HasSettings())
346 buttons.Add(CONTEXT_BUTTON_PLUGIN_SETTINGS, 1045); // Plugin Settings
349 buttons.Add(CONTEXT_BUTTON_SET_DEFAULT, 13335); // Set as Default
350 if (!share->m_ignore && !isAddon)
351 buttons.Add(CONTEXT_BUTTON_REMOVE_SOURCE, 522); // Remove Source
353 buttons.Add(CONTEXT_BUTTON_SET_THUMB, 20019);
355 if (!GetDefaultShareNameByType(type).IsEmpty())
356 buttons.Add(CONTEXT_BUTTON_CLEAR_DEFAULT, 13403); // Clear Default
358 buttons.Add(CONTEXT_BUTTON_ADD_SOURCE, 1026); // Add Source
360 if (share && LOCK_MODE_EVERYONE != CProfilesManager::Get().GetMasterProfile().getLockMode())
362 if (share->m_iHasLock == 0 && (CProfilesManager::Get().GetCurrentProfile().canWriteSources() || g_passwordManager.bMasterUser))
363 buttons.Add(CONTEXT_BUTTON_ADD_LOCK, 12332);
364 else if (share->m_iHasLock == 1)
365 buttons.Add(CONTEXT_BUTTON_REMOVE_LOCK, 12335);
366 else if (share->m_iHasLock == 2)
368 buttons.Add(CONTEXT_BUTTON_REMOVE_LOCK, 12335);
370 bool maxRetryExceeded = false;
371 if (CSettings::Get().GetInt("masterlock.maxretries") != 0)
372 maxRetryExceeded = (share->m_iBadPwdCount >= CSettings::Get().GetInt("masterlock.maxretries"));
374 if (maxRetryExceeded)
375 buttons.Add(CONTEXT_BUTTON_RESET_LOCK, 12334);
377 buttons.Add(CONTEXT_BUTTON_CHANGE_LOCK, 12356);
380 if (share && !g_passwordManager.bMasterUser && item->m_iHasLock == 1)
381 buttons.Add(CONTEXT_BUTTON_REACTIVATE_LOCK, 12353);
384 bool CGUIDialogContextMenu::OnContextButton(const CStdString &type, const CFileItemPtr item, CONTEXT_BUTTON button)
386 // Add Source doesn't require a valid share
387 if (button == CONTEXT_BUTTON_ADD_SOURCE)
389 if (CProfilesManager::Get().IsMasterProfile())
391 if (!g_passwordManager.IsMasterLockUnlocked(true))
394 else if (!CProfilesManager::Get().GetCurrentProfile().canWriteSources() && !g_passwordManager.IsProfileLockUnlocked())
397 return CGUIDialogMediaSource::ShowAndAddMediaSource(type);
400 // buttons that are available on both sources and autosourced items
401 if (!item) return false;
405 case CONTEXT_BUTTON_EJECT_DRIVE:
406 return g_mediaManager.Eject(item->GetPath());
409 case CONTEXT_BUTTON_PLAY_DISC:
410 return MEDIA_DETECT::CAutorun::PlayDisc(item->GetPath(), true, true); // restart
412 case CONTEXT_BUTTON_RESUME_DISC:
413 return MEDIA_DETECT::CAutorun::PlayDisc(item->GetPath(), true, false); // resume
415 case CONTEXT_BUTTON_EJECT_DISC:
416 g_mediaManager.ToggleTray(g_mediaManager.TranslateDevicePath(item->GetPath())[0]);
423 // the rest of the operations require a valid share
424 CMediaSource *share = GetShare(type, item.get());
425 if (!share) return false;
428 case CONTEXT_BUTTON_EDIT_SOURCE:
429 if (CProfilesManager::Get().IsMasterProfile())
431 if (!g_passwordManager.IsMasterLockUnlocked(true))
434 else if (!g_passwordManager.IsProfileLockUnlocked())
437 return CGUIDialogMediaSource::ShowAndEditMediaSource(type, *share);
439 case CONTEXT_BUTTON_REMOVE_SOURCE:
441 if (CProfilesManager::Get().IsMasterProfile())
443 if (!g_passwordManager.IsMasterLockUnlocked(true))
448 if (!CProfilesManager::Get().GetCurrentProfile().canWriteSources() && !g_passwordManager.IsMasterLockUnlocked(false))
450 if (CProfilesManager::Get().GetCurrentProfile().canWriteSources() && !g_passwordManager.IsProfileLockUnlocked())
453 // prompt user if they want to really delete the source
454 if (CGUIDialogYesNo::ShowAndGetInput(751, 0, 750, 0))
455 { // check default before we delete, as deletion will kill the share object
456 CStdString defaultSource(GetDefaultShareNameByType(type));
457 if (!defaultSource.IsEmpty())
459 if (share->strName.Equals(defaultSource))
462 CMediaSourceSettings::Get().DeleteSource(type, share->strName, share->strPath);
466 case CONTEXT_BUTTON_SET_DEFAULT:
467 if (CProfilesManager::Get().GetCurrentProfile().canWriteSources() && !g_passwordManager.IsProfileLockUnlocked())
469 else if (!g_passwordManager.IsMasterLockUnlocked(true))
472 // make share default
473 SetDefault(type, share->strName);
476 case CONTEXT_BUTTON_CLEAR_DEFAULT:
477 if (CProfilesManager::Get().GetCurrentProfile().canWriteSources() && !g_passwordManager.IsProfileLockUnlocked())
479 else if (!g_passwordManager.IsMasterLockUnlocked(true))
481 // remove share default
485 case CONTEXT_BUTTON_SET_THUMB:
487 if (CProfilesManager::Get().GetCurrentProfile().canWriteSources() && !g_passwordManager.IsProfileLockUnlocked())
489 else if (!g_passwordManager.IsMasterLockUnlocked(true))
492 // setup our thumb list
495 // add the current thumb, if available
496 if (!share->m_strThumbnailImage.IsEmpty())
498 CFileItemPtr current(new CFileItem("thumb://Current", false));
499 current->SetArt("thumb", share->m_strThumbnailImage);
500 current->SetLabel(g_localizeStrings.Get(20016));
503 else if (item->HasArt("thumb"))
504 { // already have a thumb that the share doesn't know about - must be a local one, so we mayaswell reuse it.
505 CFileItemPtr current(new CFileItem("thumb://Current", false));
506 current->SetArt("thumb", item->GetArt("thumb"));
507 current->SetLabel(g_localizeStrings.Get(20016));
510 // see if there's a local thumb for this item
511 CStdString folderThumb = item->GetFolderThumb();
512 if (XFILE::CFile::Exists(folderThumb))
514 CFileItemPtr local(new CFileItem("thumb://Local", false));
515 local->SetArt("thumb", folderThumb);
516 local->SetLabel(g_localizeStrings.Get(20017));
519 // and add a "no thumb" entry as well
520 CFileItemPtr nothumb(new CFileItem("thumb://None", false));
521 nothumb->SetIconImage(item->GetIconImage());
522 nothumb->SetLabel(g_localizeStrings.Get(20018));
527 g_mediaManager.GetLocalDrives(shares);
528 if (!CGUIDialogFileBrowser::ShowAndGetImage(items, shares, g_localizeStrings.Get(1030), strThumb))
531 if (strThumb == "thumb://Current")
534 if (strThumb == "thumb://Local")
535 strThumb = folderThumb;
537 if (strThumb == "thumb://None")
540 if (!share->m_ignore)
542 CMediaSourceSettings::Get().UpdateSource(type,share->strName,"thumbnail",strThumb);
543 CMediaSourceSettings::Get().Save();
545 else if (!strThumb.IsEmpty())
546 { // this is some sort of an auto-share, so store in the texture database
549 db.SetTextureForPath(item->GetPath(), "thumb", strThumb);
552 CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES);
553 g_windowManager.SendThreadMessage(msg);
557 case CONTEXT_BUTTON_ADD_LOCK:
559 // prompt user for mastercode when changing lock settings) only for default user
560 if (!g_passwordManager.IsMasterLockUnlocked(true))
563 CStdString strNewPassword = "";
564 if (!CGUIDialogLockSettings::ShowAndGetLock(share->m_iLockMode,strNewPassword))
566 // password entry and re-entry succeeded, write out the lock data
567 share->m_iHasLock = 2;
568 CMediaSourceSettings::Get().UpdateSource(type, share->strName, "lockcode", strNewPassword);
569 strNewPassword = StringUtils::Format("%i", share->m_iLockMode);
570 CMediaSourceSettings::Get().UpdateSource(type, share->strName, "lockmode", strNewPassword);
571 CMediaSourceSettings::Get().UpdateSource(type, share->strName, "badpwdcount", "0");
572 CMediaSourceSettings::Get().Save();
574 CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES);
575 g_windowManager.SendThreadMessage(msg);
578 case CONTEXT_BUTTON_RESET_LOCK:
580 // prompt user for profile lock when changing lock settings
581 if (!g_passwordManager.IsMasterLockUnlocked(true))
584 CMediaSourceSettings::Get().UpdateSource(type, share->strName, "badpwdcount", "0");
585 CMediaSourceSettings::Get().Save();
586 CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES);
587 g_windowManager.SendThreadMessage(msg);
590 case CONTEXT_BUTTON_REMOVE_LOCK:
592 if (!g_passwordManager.IsMasterLockUnlocked(true))
595 if (!CGUIDialogYesNo::ShowAndGetInput(12335, 0, 750, 0))
598 share->m_iHasLock = 0;
599 CMediaSourceSettings::Get().UpdateSource(type, share->strName, "lockmode", "0");
600 CMediaSourceSettings::Get().UpdateSource(type, share->strName, "lockcode", "0");
601 CMediaSourceSettings::Get().UpdateSource(type, share->strName, "badpwdcount", "0");
602 CMediaSourceSettings::Get().Save();
603 CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES);
604 g_windowManager.SendThreadMessage(msg);
607 case CONTEXT_BUTTON_REACTIVATE_LOCK:
609 bool maxRetryExceeded = false;
610 if (CSettings::Get().GetInt("masterlock.maxretries") != 0)
611 maxRetryExceeded = (share->m_iBadPwdCount >= CSettings::Get().GetInt("masterlock.maxretries"));
612 if (!maxRetryExceeded)
614 // don't prompt user for mastercode when reactivating a lock
615 g_passwordManager.LockSource(type, share->strName, true);
620 case CONTEXT_BUTTON_CHANGE_LOCK:
622 if (!g_passwordManager.IsMasterLockUnlocked(true))
626 CStdString strNewLockMode;
627 if (CGUIDialogLockSettings::ShowAndGetLock(share->m_iLockMode,strNewPW))
628 strNewLockMode = StringUtils::Format("%i",share->m_iLockMode);
631 // password ReSet and re-entry succeeded, write out the lock data
632 CMediaSourceSettings::Get().UpdateSource(type, share->strName, "lockcode", strNewPW);
633 CMediaSourceSettings::Get().UpdateSource(type, share->strName, "lockmode", strNewLockMode);
634 CMediaSourceSettings::Get().UpdateSource(type, share->strName, "badpwdcount", "0");
635 CMediaSourceSettings::Get().Save();
636 CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES);
637 g_windowManager.SendThreadMessage(msg);
646 CMediaSource *CGUIDialogContextMenu::GetShare(const CStdString &type, const CFileItem *item)
648 VECSOURCES *shares = CMediaSourceSettings::Get().GetSources(type);
649 if (!shares || !item) return NULL;
650 for (unsigned int i = 0; i < shares->size(); i++)
652 CMediaSource &testShare = shares->at(i);
653 if (URIUtils::IsDVD(testShare.strPath))
660 if (!URIUtils::CompareWithoutSlashAtEnd(testShare.strPath, item->GetPath()))
663 // paths match, what about share name - only match the leftmost
664 // characters as the label may contain other info (status for instance)
665 if (item->GetLabel().Left(testShare.strName.size()).Equals(testShare.strName))
673 void CGUIDialogContextMenu::OnWindowLoaded()
678 const CGUIControlGroupList* pGroupList = NULL;
679 const CGUIControl* pControl = GetControl(GROUP_LIST);
680 if (pControl && pControl->GetControlType() == GUICONTROL_GROUPLIST)
681 pGroupList = (CGUIControlGroupList*)pControl;
683 pControl = (CGUIControl *)GetControl(BACKGROUND_IMAGE);
684 if (pControl && pGroupList)
686 if (pGroupList->GetOrientation() == VERTICAL)
687 m_backgroundImageSize = pControl->GetHeight();
689 m_backgroundImageSize = pControl->GetWidth();
692 CGUIDialog::OnWindowLoaded();
695 void CGUIDialogContextMenu::OnDeinitWindow(int nextWindowID)
697 //we can't be sure that controls are removed on window unload
698 //we have to remove them to be sure that they won't stay for next use of context menu
699 for (unsigned int i = 0; i < m_buttons.size(); i++)
701 const CGUIControl *control = GetControl(BUTTON_START + i);
703 RemoveControl(control);
707 CGUIDialog::OnDeinitWindow(nextWindowID);
710 CStdString CGUIDialogContextMenu::GetDefaultShareNameByType(const CStdString &strType)
712 VECSOURCES *pShares = CMediaSourceSettings::Get().GetSources(strType);
713 CStdString strDefault = CMediaSourceSettings::Get().GetDefaultSource(strType);
715 if (!pShares) return "";
717 bool bIsSourceName(false);
718 int iIndex = CUtil::GetMatchingSource(strDefault, *pShares, bIsSourceName);
719 if (iIndex < 0 || iIndex >= (int)pShares->size())
722 return pShares->at(iIndex).strName;
725 void CGUIDialogContextMenu::SetDefault(const CStdString &strType, const CStdString &strDefault)
727 CMediaSourceSettings::Get().SetDefaultSource(strType, strDefault);
728 CMediaSourceSettings::Get().Save();
731 void CGUIDialogContextMenu::ClearDefault(const CStdString &strType)
733 SetDefault(strType, "");
736 void CGUIDialogContextMenu::SwitchMedia(const CStdString& strType, const CStdString& strPath)
739 CContextButtons choices;
740 if (!strType.Equals("music"))
741 choices.Add(WINDOW_MUSIC_FILES, 2);
742 if (!strType.Equals("video"))
743 choices.Add(WINDOW_VIDEO_FILES, 3);
744 if (!strType.Equals("pictures"))
745 choices.Add(WINDOW_PICTURES, 1);
746 if (!strType.Equals("files"))
747 choices.Add(WINDOW_FILES, 7);
749 int window = ShowAndGetChoice(choices);
752 CUtil::DeleteDirectoryCache();
753 g_windowManager.ChangeActiveWindow(window, strPath);
757 int CGUIDialogContextMenu::ShowAndGetChoice(const CContextButtons &choices)
759 if (choices.size() == 0)
762 CGUIDialogContextMenu *pMenu = (CGUIDialogContextMenu *)g_windowManager.GetWindow(WINDOW_DIALOG_CONTEXT_MENU);
765 if (pMenu->IsDialogRunning())
768 pMenu->m_buttons = choices;
770 pMenu->SetInitialVisibility();
771 pMenu->SetupButtons();
772 pMenu->PositionAtCurrentFocus();
774 return pMenu->m_clickedButton;
779 void CGUIDialogContextMenu::PositionAtCurrentFocus()
781 CGUIWindow *window = g_windowManager.GetWindow(g_windowManager.GetFocusedWindow());
784 const CGUIControl *focusedControl = window->GetFocusedControl();
787 CPoint pos = focusedControl->GetRenderPosition() + CPoint(focusedControl->GetWidth() * 0.5f, focusedControl->GetHeight() * 0.5f)
788 + window->GetRenderPosition();
789 SetPosition(m_coordX + pos.x - GetWidth() * 0.5f, m_coordY + pos.y - GetHeight() * 0.5f);
793 // no control to center at, so just center the window