bool CGUIDialogContextMenu::OnContextButton(const std::string &type, const CFileItemPtr& item, CONTEXT_BUTTON button) { // buttons that are available on both sources and autosourced items if (!item) return false; // the rest of the operations require a valid share CMediaSource *share = GetShare(type, item.get()); if (!share) return false; switch (button) { case CONTEXT_BUTTON_EDIT_SOURCE: if (CServiceBroker::GetProfileManager().IsMasterProfile()) { if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; } else if (!g_passwordManager.IsProfileLockUnlocked()) return false; return CGUIDialogMediaSource::ShowAndEditMediaSource(type, *share); case CONTEXT_BUTTON_REMOVE_SOURCE: { if (CServiceBroker::GetProfileManager().IsMasterProfile()) { if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; } else { if (!CServiceBroker::GetProfileManager().GetCurrentProfile().canWriteSources() && !g_passwordManager.IsMasterLockUnlocked(false)) return false; if (CServiceBroker::GetProfileManager().GetCurrentProfile().canWriteSources() && !g_passwordManager.IsProfileLockUnlocked()) return false; } // prompt user if they want to really delete the source if (!CGUIDialogYesNo::ShowAndGetInput(CVariant{751}, CVariant{750})) return false; // check default before we delete, as deletion will kill the share object std::string defaultSource(GetDefaultShareNameByType(type)); if (!defaultSource.empty()) { if (share->strName == defaultSource) ClearDefault(type); } CMediaSourceSettings::GetInstance().DeleteSource(type, share->strName, share->strPath); return true; } case CONTEXT_BUTTON_SET_DEFAULT: if (CServiceBroker::GetProfileManager().GetCurrentProfile().canWriteSources() && !g_passwordManager.IsProfileLockUnlocked()) return false; else if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; // make share default SetDefault(type, share->strName); return true; case CONTEXT_BUTTON_CLEAR_DEFAULT: if (CServiceBroker::GetProfileManager().GetCurrentProfile().canWriteSources() && !g_passwordManager.IsProfileLockUnlocked()) return false; else if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; // remove share default ClearDefault(type); return true; case CONTEXT_BUTTON_SET_THUMB: { if (CServiceBroker::GetProfileManager().GetCurrentProfile().canWriteSources() && !g_passwordManager.IsProfileLockUnlocked()) return false; else if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; // setup our thumb list CFileItemList items; // add the current thumb, if available if (!share->m_strThumbnailImage.empty()) { CFileItemPtr current(new CFileItem("thumb://Current", false)); current->SetArt("thumb", share->m_strThumbnailImage); current->SetLabel(g_localizeStrings.Get(20016)); items.Add(current); } else if (item->HasArt("thumb")) { // already have a thumb that the share doesn't know about - must be a local one, so we mayaswell reuse it. CFileItemPtr current(new CFileItem("thumb://Current", false)); current->SetArt("thumb", item->GetArt("thumb")); current->SetLabel(g_localizeStrings.Get(20016)); items.Add(current); } // see if there's a local thumb for this item std::string folderThumb = item->GetFolderThumb(); if (XFILE::CFile::Exists(folderThumb)) { CFileItemPtr local(new CFileItem("thumb://Local", false)); local->SetArt("thumb", folderThumb); local->SetLabel(g_localizeStrings.Get(20017)); items.Add(local); } // and add a "no thumb" entry as well CFileItemPtr nothumb(new CFileItem("thumb://None", false)); nothumb->SetIconImage(item->GetIconImage()); nothumb->SetLabel(g_localizeStrings.Get(20018)); items.Add(nothumb); std::string strThumb; VECSOURCES shares; g_mediaManager.GetLocalDrives(shares); if (!CGUIDialogFileBrowser::ShowAndGetImage(items, shares, g_localizeStrings.Get(1030), strThumb)) return false; if (strThumb == "thumb://Current") return true; if (strThumb == "thumb://Local") strThumb = folderThumb; if (strThumb == "thumb://None") strThumb = ""; if (!share->m_ignore) { CMediaSourceSettings::GetInstance().UpdateSource(type,share->strName,"thumbnail",strThumb); CMediaSourceSettings::GetInstance().Save(); } else if (!strThumb.empty()) { // this is some sort of an auto-share, so store in the texture database CTextureDatabase db; if (db.Open()) db.SetTextureForPath(item->GetPath(), "thumb", strThumb); } CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES); CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg); return true; } case CONTEXT_BUTTON_ADD_LOCK: { // prompt user for mastercode when changing lock settings) only for default user if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; std::string strNewPassword = ""; if (!CGUIDialogLockSettings::ShowAndGetLock(share->m_iLockMode,strNewPassword)) return false; // password entry and re-entry succeeded, write out the lock data share->m_iHasLock = 2; CMediaSourceSettings::GetInstance().UpdateSource(type, share->strName, "lockcode", strNewPassword); strNewPassword = StringUtils::Format("%i", share->m_iLockMode); CMediaSourceSettings::GetInstance().UpdateSource(type, share->strName, "lockmode", strNewPassword); CMediaSourceSettings::GetInstance().UpdateSource(type, share->strName, "badpwdcount", "0"); CMediaSourceSettings::GetInstance().Save(); CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES); CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg); return true; } case CONTEXT_BUTTON_RESET_LOCK: { // prompt user for profile lock when changing lock settings if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; CMediaSourceSettings::GetInstance().UpdateSource(type, share->strName, "badpwdcount", "0"); CMediaSourceSettings::GetInstance().Save(); CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES); CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg); return true; } case CONTEXT_BUTTON_REMOVE_LOCK: { if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; if (!CGUIDialogYesNo::ShowAndGetInput(CVariant{12335}, CVariant{750})) return false; share->m_iHasLock = 0; CMediaSourceSettings::GetInstance().UpdateSource(type, share->strName, "lockmode", "0"); CMediaSourceSettings::GetInstance().UpdateSource(type, share->strName, "lockcode", "0"); CMediaSourceSettings::GetInstance().UpdateSource(type, share->strName, "badpwdcount", "0"); CMediaSourceSettings::GetInstance().Save(); CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES); CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg); return true; } case CONTEXT_BUTTON_REACTIVATE_LOCK: { bool maxRetryExceeded = false; if (CServiceBroker::GetSettings().GetInt(CSettings::SETTING_MASTERLOCK_MAXRETRIES) != 0) maxRetryExceeded = (share->m_iBadPwdCount >= CServiceBroker::GetSettings().GetInt(CSettings::SETTING_MASTERLOCK_MAXRETRIES)); if (!maxRetryExceeded) { // don't prompt user for mastercode when reactivating a lock g_passwordManager.LockSource(type, share->strName, true); return true; } return false; } case CONTEXT_BUTTON_CHANGE_LOCK: { if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; std::string strNewPW; std::string strNewLockMode; if (CGUIDialogLockSettings::ShowAndGetLock(share->m_iLockMode,strNewPW)) strNewLockMode = StringUtils::Format("%i",share->m_iLockMode); else return false; // password ReSet and re-entry succeeded, write out the lock data CMediaSourceSettings::GetInstance().UpdateSource(type, share->strName, "lockcode", strNewPW); CMediaSourceSettings::GetInstance().UpdateSource(type, share->strName, "lockmode", strNewLockMode); CMediaSourceSettings::GetInstance().UpdateSource(type, share->strName, "badpwdcount", "0"); CMediaSourceSettings::GetInstance().Save(); CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES); CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg); return true; } default: break; } return false; }
void CPictureThumbLoader::ProcessFoldersAndArchives(CFileItem *pItem) { if (pItem->HasArt("thumb")) return; CTextureDatabase db; db.Open(); if (pItem->IsCBR() || pItem->IsCBZ()) { CStdString strTBN(URIUtils::ReplaceExtension(pItem->GetPath(),".tbn")); if (CFile::Exists(strTBN)) { db.SetTextureForPath(pItem->GetPath(), "thumb", strTBN); CTextureCache::Get().BackgroundCacheImage(strTBN); pItem->SetArt("thumb", strTBN); return; } } if ((pItem->m_bIsFolder || pItem->IsCBR() || pItem->IsCBZ()) && !pItem->m_bIsShareOrDrive && !pItem->IsParentFolder()) { // first check for a folder.jpg CStdString thumb = "folder.jpg"; CStdString strPath = pItem->GetPath(); if (pItem->IsCBR()) { URIUtils::CreateArchivePath(strPath,"rar",pItem->GetPath(),""); thumb = "cover.jpg"; } if (pItem->IsCBZ()) { URIUtils::CreateArchivePath(strPath,"zip",pItem->GetPath(),""); thumb = "cover.jpg"; } if (pItem->IsMultiPath()) strPath = CMultiPathDirectory::GetFirstPath(pItem->GetPath()); thumb = URIUtils::AddFileToFolder(strPath, thumb); if (CFile::Exists(thumb)) { db.SetTextureForPath(pItem->GetPath(), "thumb", thumb); CTextureCache::Get().BackgroundCacheImage(thumb); pItem->SetArt("thumb", thumb); return; } if (!pItem->IsPlugin()) { // we load the directory, grab 4 random thumb files (if available) and then generate // the thumb. CFileItemList items; CDirectory::GetDirectory(strPath, items, g_advancedSettings.m_pictureExtensions, DIR_FLAG_NO_FILE_DIRS); // create the folder thumb by choosing 4 random thumbs within the folder and putting // them into one thumb. // count the number of images for (int i=0; i < items.Size();) { if (!items[i]->IsPicture() || items[i]->IsZIP() || items[i]->IsRAR() || items[i]->IsPlayList()) { items.Remove(i); } else i++; } if (items.IsEmpty()) { if (pItem->IsCBZ() || pItem->IsCBR()) { CDirectory::GetDirectory(strPath, items, g_advancedSettings.m_pictureExtensions, DIR_FLAG_NO_FILE_DIRS); for (int i=0;i<items.Size();++i) { CFileItemPtr item = items[i]; if (item->m_bIsFolder) { ProcessFoldersAndArchives(item.get()); pItem->SetArt("thumb", items[i]->GetArt("thumb")); pItem->SetIconImage(items[i]->GetIconImage()); return; } } } return; // no images in this folder } // randomize them items.Randomize(); if (items.Size() < 4 || pItem->IsCBR() || pItem->IsCBZ()) { // less than 4 items, so just grab the first thumb items.Sort(SORT_METHOD_LABEL, SortOrderAscending); CStdString thumb = CTextureCache::GetWrappedThumbURL(items[0]->GetPath()); db.SetTextureForPath(pItem->GetPath(), "thumb", thumb); CTextureCache::Get().BackgroundCacheImage(thumb); pItem->SetArt("thumb", thumb); } else { // ok, now we've got the files to get the thumbs from, lets create it... // we basically load the 4 images and combine them vector<string> files; for (int thumb = 0; thumb < 4; thumb++) files.push_back(items[thumb]->GetPath()); CStdString thumb = CTextureCache::GetWrappedImageURL(pItem->GetPath(), "picturefolder"); CStdString relativeCacheFile = CTextureCache::GetCacheFile(thumb) + ".png"; if (CPicture::CreateTiledThumb(files, CTextureCache::GetCachedPath(relativeCacheFile))) { CTextureDetails details; details.file = relativeCacheFile; details.width = g_advancedSettings.GetThumbSize(); details.height = g_advancedSettings.GetThumbSize(); CTextureCache::Get().AddCachedTexture(thumb, details); db.SetTextureForPath(pItem->GetPath(), "thumb", thumb); pItem->SetArt("thumb", CTextureCache::GetCachedPath(relativeCacheFile)); } } } // refill in the icon to get it to update pItem->FillInDefaultIcon(); } }
void CThumbLoader::SetCachedImage(const CFileItem &item, const CStdString &type, const CStdString &image) { CTextureDatabase db; if (db.Open()) db.SetTextureForPath(item.GetPath(), type, image); }
bool CVideoLibraryRefreshingJob::Work(CVideoDatabase &db) { if (m_item == nullptr) return false; // determine the scraper for the item's path VIDEO::SScanSettings scanSettings; ADDON::ScraperPtr scraper = db.GetScraperForPath(m_item->GetPath(), scanSettings); if (scraper == nullptr) return false; // copy the scraper in case we need it again ADDON::ScraperPtr originalScraper(scraper); // get the item's correct title std::string itemTitle = m_searchTitle; if (itemTitle.empty()) itemTitle = m_item->GetMovieName(scanSettings.parent_name); CScraperUrl scraperUrl; VIDEO::CVideoInfoScanner scanner; bool needsRefresh = m_forceRefresh; bool hasDetails = false; bool ignoreNfo = m_ignoreNfo; // run this in a loop in case we need to refresh again bool failure = false; do { if (!ignoreNfo) { // check if there's an NFO for the item CNfoFile::NFOResult nfoResult = scanner.CheckForNFOFile(m_item.get(), scanSettings.parent_name_root, scraper, scraperUrl); // if there's no NFO remember it in case we have to refresh again if (nfoResult == CNfoFile::ERROR_NFO) ignoreNfo = true; else if (nfoResult != CNfoFile::NO_NFO) hasDetails = true; // if we are performing a forced refresh ask the user to choose between using a valid NFO and a valid scraper if (needsRefresh && IsModal() && !scraper->IsNoop() && nfoResult != CNfoFile::ERROR_NFO) { int heading = 20159; if (scraper->Content() == CONTENT_MOVIES) heading = 13346; else if (scraper->Content() == CONTENT_TVSHOWS) heading = m_item->m_bIsFolder ? 20351 : 20352; else if (scraper->Content() == CONTENT_MUSICVIDEOS) heading = 20393; if (CGUIDialogYesNo::ShowAndGetInput(heading, 20446)) { hasDetails = false; ignoreNfo = true; scraperUrl.Clear(); scraper = originalScraper; } } } // no need to re-fetch the episode guide for episodes if (scraper->Content() == CONTENT_TVSHOWS && !m_item->m_bIsFolder) hasDetails = true; // if we don't have an url or need to refresh anyway do the web search if (!hasDetails && (needsRefresh || scraperUrl.m_url.empty())) { SetTitle(StringUtils::Format(g_localizeStrings.Get(197).c_str(), scraper->Name().c_str())); SetText(itemTitle); SetProgress(0); // clear any cached data from the scraper scraper->ClearCache(); // create the info downloader for the scraper CVideoInfoDownloader infoDownloader(scraper); // try to find a matching item MOVIELIST itemResultList; int result = infoDownloader.FindMovie(itemTitle, itemResultList, GetProgressDialog()); // close the progress dialog MarkFinished(); if (result > 0) { // there are multiple matches for the item if (!itemResultList.empty()) { // choose the first match if (!IsModal()) scraperUrl = itemResultList.at(0); else { // ask the user what to do CGUIDialogSelect* selectDialog = g_windowManager.GetWindow<CGUIDialogSelect>(WINDOW_DIALOG_SELECT); selectDialog->Reset(); selectDialog->SetHeading(scraper->Content() == CONTENT_TVSHOWS ? 20356 : 196); for (const auto& itemResult : itemResultList) selectDialog->Add(itemResult.strTitle); selectDialog->EnableButton(true, 413); // "Manual" selectDialog->Open(); // check if the user has chosen one of the results int selectedItem = selectDialog->GetSelectedItem(); if (selectedItem >= 0) scraperUrl = itemResultList.at(selectedItem); // the user hasn't chosen one of the results and but has chosen to manually enter a title to use else if (selectDialog->IsButtonPressed()) { // ask the user to input a title to use if (!CGUIKeyboardFactory::ShowAndGetInput(itemTitle, g_localizeStrings.Get(scraper->Content() == CONTENT_TVSHOWS ? 20357 : 16009), false)) return false; // go through the whole process again needsRefresh = true; continue; } // nothing else we can do else return false; } CLog::Log(LOGDEBUG, "CVideoLibraryRefreshingJob: user selected item '%s' with URL '%s'", scraperUrl.strTitle.c_str(), scraperUrl.m_url.at(0).m_url.c_str()); } } else if (result < 0 || !VIDEO::CVideoInfoScanner::DownloadFailed(GetProgressDialog())) { failure = true; break; } } // if the URL is still empty, check whether or not we're allowed // to prompt and ask the user to input a new search title if (!hasDetails && scraperUrl.m_url.empty()) { if (IsModal()) { // ask the user to input a title to use if (!CGUIKeyboardFactory::ShowAndGetInput(itemTitle, g_localizeStrings.Get(scraper->Content() == CONTENT_TVSHOWS ? 20357 : 16009), false)) return false; // go through the whole process again needsRefresh = true; continue; } // nothing else we can do failure = true; break; } // before we start downloading all the necessary information cleanup any existing artwork and hashes CTextureDatabase textureDb; if (textureDb.Open()) { for (const auto& artwork : m_item->GetArt()) textureDb.InvalidateCachedTexture(artwork.second); textureDb.Close(); } m_item->ClearArt(); // put together the list of items to refresh std::string path = m_item->GetPath(); CFileItemList items; if (m_item->HasVideoInfoTag() && m_item->GetVideoInfoTag()->m_iDbId > 0) { // for a tvshow we need to handle all paths of it std::vector<std::string> tvshowPaths; if (CMediaTypes::IsMediaType(m_item->GetVideoInfoTag()->m_type, MediaTypeTvShow) && m_refreshAll && db.GetPathsLinkedToTvShow(m_item->GetVideoInfoTag()->m_iDbId, tvshowPaths)) { for (const auto& tvshowPath : tvshowPaths) { CFileItemPtr tvshowItem(new CFileItem(*m_item->GetVideoInfoTag())); tvshowItem->SetPath(tvshowPath); items.Add(tvshowItem); } } // otherwise just add a copy of the item else items.Add(CFileItemPtr(new CFileItem(*m_item->GetVideoInfoTag()))); // update the path to the real path (instead of a videodb:// one) path = m_item->GetVideoInfoTag()->m_strPath; } else items.Add(CFileItemPtr(new CFileItem(*m_item))); // set the proper path of the list of items to lookup items.SetPath(m_item->m_bIsFolder ? URIUtils::GetParentPath(path) : URIUtils::GetDirectory(path)); int headingLabel = 198; if (scraper->Content() == CONTENT_TVSHOWS) { if (m_item->m_bIsFolder) headingLabel = 20353; else headingLabel = 20361; } else if (scraper->Content() == CONTENT_MUSICVIDEOS) headingLabel = 20394; // prepare the progress dialog for downloading all the necessary information SetTitle(g_localizeStrings.Get(headingLabel)); SetText(scraperUrl.strTitle); SetProgress(0); // remove any existing data for the item we're going to refresh if (m_item->GetVideoInfoTag()->m_iDbId > 0) { int dbId = m_item->GetVideoInfoTag()->m_iDbId; if (scraper->Content() == CONTENT_MOVIES) db.DeleteMovie(dbId); else if (scraper->Content() == CONTENT_MUSICVIDEOS) db.DeleteMusicVideo(dbId); else if (scraper->Content() == CONTENT_TVSHOWS) { if (!m_item->m_bIsFolder) db.DeleteEpisode(dbId); else if (m_refreshAll) db.DeleteTvShow(dbId); else db.DeleteDetailsForTvShow(dbId); } } // finally download the information for the item if (!scanner.RetrieveVideoInfo(items, scanSettings.parent_name, scraper->Content(), !ignoreNfo, scraperUrl.m_url.empty() ? NULL : &scraperUrl, m_refreshAll, GetProgressDialog())) { // something went wrong MarkFinished(); // check if the user cancelled if (!IsCancelled() && IsModal()) CGUIDialogOK::ShowAndGetInput(195, itemTitle); return false; } // retrieve the updated information from the database if (scraper->Content() == CONTENT_MOVIES) db.GetMovieInfo(m_item->GetPath(), *m_item->GetVideoInfoTag()); else if (scraper->Content() == CONTENT_MUSICVIDEOS) db.GetMusicVideoInfo(m_item->GetPath(), *m_item->GetVideoInfoTag()); else if (scraper->Content() == CONTENT_TVSHOWS) { // update tvshow info to get updated episode numbers if (m_item->m_bIsFolder) db.GetTvShowInfo(m_item->GetPath(), *m_item->GetVideoInfoTag()); else db.GetEpisodeInfo(m_item->GetPath(), *m_item->GetVideoInfoTag()); } // we're finally done MarkFinished(); break; } while (needsRefresh); if (failure && IsModal()) CGUIDialogOK::ShowAndGetInput(195, itemTitle); return true; }
bool CRepositoryUpdateJob::DoWork() { CLog::Log(LOGDEBUG, "CRepositoryUpdateJob[%s] checking for updates.", m_repo->ID().c_str()); CAddonDatabase database; database.Open(); std::string oldChecksum; if (database.GetRepoChecksum(m_repo->ID(), oldChecksum) == -1) oldChecksum = ""; std::string newChecksum; VECADDONS addons; auto status = m_repo->FetchIfChanged(oldChecksum, newChecksum, addons); database.SetLastChecked(m_repo->ID(), m_repo->Version(), CDateTime::GetCurrentDateTime().GetAsDBDateTime()); MarkFinished(); if (status == CRepository::STATUS_ERROR) return false; if (status == CRepository::STATUS_NOT_MODIFIED) { CLog::Log(LOGDEBUG, "CRepositoryUpdateJob[%s] checksum not changed.", m_repo->ID().c_str()); return true; } //Invalidate art. { CTextureDatabase textureDB; textureDB.Open(); textureDB.BeginMultipleExecute(); for (const auto& addon : addons) { AddonPtr oldAddon; if (database.GetAddon(addon->ID(), oldAddon) && addon->Version() > oldAddon->Version()) { if (!oldAddon->Icon().empty() || !oldAddon->FanArt().empty() || !oldAddon->Screenshots().empty()) CLog::Log(LOGDEBUG, "CRepository: invalidating cached art for '%s'", addon->ID().c_str()); if (!oldAddon->Icon().empty()) textureDB.InvalidateCachedTexture(oldAddon->Icon()); if (!oldAddon->FanArt().empty()) textureDB.InvalidateCachedTexture(oldAddon->Icon()); for (const auto& path : oldAddon->Screenshots()) textureDB.InvalidateCachedTexture(path); } } textureDB.CommitMultipleExecute(); } database.UpdateRepositoryContent(m_repo->ID(), m_repo->Version(), newChecksum, addons); //Notify about broken status changes for (const auto& addon : addons) { AddonPtr localAddon; if (!CAddonMgr::GetInstance().GetAddon(addon->ID(), localAddon)) continue; if (localAddon && localAddon->Version() > addon->Version()) //We have a newer version locally continue; AddonPtr oldAddon; database.GetAddon(addon->ID(), oldAddon); if (database.GetAddonVersion(addon->ID()).first > addon->Version()) //Newer version in db (ie. in a different repo) continue; std::string broken = addon->Broken(); bool isBroken = !addon->Broken().empty(); bool isBrokenInDb = oldAddon && !oldAddon->Broken().empty(); if (isBroken && !isBrokenInDb) { //newly broken if (HELPERS::ShowYesNoDialogLines(CVariant{addon->Name()}, CVariant{24096}, CVariant{24097}, CVariant{""}) == DialogResponse::YES) { CAddonMgr::GetInstance().DisableAddon(addon->ID()); } CLog::Log(LOGDEBUG, "CRepositoryUpdateJob[%s] addon '%s' marked broken. reason: \"%s\"", m_repo->ID().c_str(), addon->ID().c_str(), broken.c_str()); CEventLog::GetInstance().Add(EventPtr(new CAddonManagementEvent(addon, 24096))); } else if (!isBroken && isBrokenInDb) { //Unbroken CLog::Log(LOGDEBUG, "CRepositoryUpdateJob[%s] addon '%s' unbroken", m_repo->ID().c_str(), addon->ID().c_str()); } } return true; }
bool CGUIDialogContextMenu::OnContextButton(const CStdString &type, const CFileItemPtr item, CONTEXT_BUTTON button) { // Add Source doesn't require a valid share if (button == CONTEXT_BUTTON_ADD_SOURCE) { if (g_settings.IsMasterUser()) { if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; } else if (!g_settings.GetCurrentProfile().canWriteSources() && !g_passwordManager.IsProfileLockUnlocked()) return false; return CGUIDialogMediaSource::ShowAndAddMediaSource(type); } // buttons that are available on both sources and autosourced items if (!item) return false; switch (button) { case CONTEXT_BUTTON_EJECT_DRIVE: return g_mediaManager.Eject(item->m_strPath); #ifdef HAS_DVD_DRIVE case CONTEXT_BUTTON_PLAY_DISC: return MEDIA_DETECT::CAutorun::PlayDisc(); case CONTEXT_BUTTON_EJECT_DISC: #ifdef _WIN32 CWIN32Util::ToggleTray(g_mediaManager.TranslateDevicePath(item->m_strPath)[0]); #else CIoSupport::ToggleTray(); #endif #endif return true; default: break; } // the rest of the operations require a valid share CMediaSource *share = GetShare(type, item.get()); if (!share) return false; switch (button) { case CONTEXT_BUTTON_EDIT_SOURCE: if (g_settings.IsMasterUser()) { if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; } else if (!g_passwordManager.IsProfileLockUnlocked()) return false; return CGUIDialogMediaSource::ShowAndEditMediaSource(type, *share); case CONTEXT_BUTTON_REMOVE_SOURCE: { if (g_settings.IsMasterUser()) { if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; } else { if (!g_settings.GetCurrentProfile().canWriteSources() && !g_passwordManager.IsMasterLockUnlocked(false)) return false; if (g_settings.GetCurrentProfile().canWriteSources() && !g_passwordManager.IsProfileLockUnlocked()) return false; } // prompt user if they want to really delete the source if (CGUIDialogYesNo::ShowAndGetInput(751, 0, 750, 0)) { // check default before we delete, as deletion will kill the share object CStdString defaultSource(GetDefaultShareNameByType(type)); if (!defaultSource.IsEmpty()) { if (share->strName.Equals(defaultSource)) ClearDefault(type); } g_settings.DeleteSource(type, share->strName, share->strPath); } return true; } case CONTEXT_BUTTON_SET_DEFAULT: if (g_settings.GetCurrentProfile().canWriteSources() && !g_passwordManager.IsProfileLockUnlocked()) return false; else if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; // make share default SetDefault(type, share->strName); return true; case CONTEXT_BUTTON_CLEAR_DEFAULT: if (g_settings.GetCurrentProfile().canWriteSources() && !g_passwordManager.IsProfileLockUnlocked()) return false; else if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; // remove share default ClearDefault(type); return true; case CONTEXT_BUTTON_SET_THUMB: { if (g_settings.GetCurrentProfile().canWriteSources() && !g_passwordManager.IsProfileLockUnlocked()) return false; else if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; // setup our thumb list CFileItemList items; // add the current thumb, if available if (!share->m_strThumbnailImage.IsEmpty()) { CFileItemPtr current(new CFileItem("thumb://Current", false)); current->SetThumbnailImage(share->m_strThumbnailImage); current->SetLabel(g_localizeStrings.Get(20016)); items.Add(current); } else if (item->HasThumbnail()) { // already have a thumb that the share doesn't know about - must be a local one, so we mayaswell reuse it. CFileItemPtr current(new CFileItem("thumb://Current", false)); current->SetThumbnailImage(item->GetThumbnailImage()); current->SetLabel(g_localizeStrings.Get(20016)); items.Add(current); } // see if there's a local thumb for this item CStdString folderThumb = item->GetFolderThumb(); if (XFILE::CFile::Exists(folderThumb)) { CFileItemPtr local(new CFileItem("thumb://Local", false)); local->SetThumbnailImage(folderThumb); local->SetLabel(g_localizeStrings.Get(20017)); items.Add(local); } // and add a "no thumb" entry as well CFileItemPtr nothumb(new CFileItem("thumb://None", false)); nothumb->SetIconImage(item->GetIconImage()); nothumb->SetLabel(g_localizeStrings.Get(20018)); items.Add(nothumb); CStdString strThumb; VECSOURCES shares; g_mediaManager.GetLocalDrives(shares); if (!CGUIDialogFileBrowser::ShowAndGetImage(items, shares, g_localizeStrings.Get(1030), strThumb)) return false; if (strThumb == "thumb://Current") return true; if (strThumb == "thumb://Local") strThumb = folderThumb; if (strThumb == "thumb://None") strThumb = ""; if (!share->m_ignore) { g_settings.UpdateSource(type,share->strName,"thumbnail",strThumb); g_settings.SaveSources(); } else if (!strThumb.IsEmpty()) { // this is some sort of an auto-share, so we have to cache it based on the criteria we use to retrieve them CStdString cachedThumb; if (type == "music") { cachedThumb = item->m_strPath; URIUtils::RemoveSlashAtEnd(cachedThumb); cachedThumb = CUtil::GetCachedMusicThumb(cachedThumb); } else if (type == "video") cachedThumb = item->GetCachedVideoThumb(); else // assume "programs" { // store the thumb for this share CTextureDatabase db; if (db.Open()) { cachedThumb = CTextureCache::GetUniqueImage(item->m_strPath, URIUtils::GetExtension(strThumb)); db.SetTextureForPath(item->m_strPath, cachedThumb); } } XFILE::CFile::Cache(strThumb, cachedThumb); } CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES); g_windowManager.SendThreadMessage(msg); return true; } case CONTEXT_BUTTON_ADD_LOCK: { // prompt user for mastercode when changing lock settings) only for default user if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; CStdString strNewPassword = ""; if (!CGUIDialogLockSettings::ShowAndGetLock(share->m_iLockMode,strNewPassword)) return false; // password entry and re-entry succeeded, write out the lock data share->m_iHasLock = 2; g_settings.UpdateSource(type, share->strName, "lockcode", strNewPassword); strNewPassword.Format("%i",share->m_iLockMode); g_settings.UpdateSource(type, share->strName, "lockmode", strNewPassword); g_settings.UpdateSource(type, share->strName, "badpwdcount", "0"); g_settings.SaveSources(); CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES); g_windowManager.SendThreadMessage(msg); return true; } case CONTEXT_BUTTON_RESET_LOCK: { // prompt user for profile lock when changing lock settings if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; g_settings.UpdateSource(type, share->strName, "badpwdcount", "0"); g_settings.SaveSources(); CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES); g_windowManager.SendThreadMessage(msg); return true; } case CONTEXT_BUTTON_REMOVE_LOCK: { if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; if (!CGUIDialogYesNo::ShowAndGetInput(12335, 0, 750, 0)) return false; share->m_iHasLock = 0; g_settings.UpdateSource(type, share->strName, "lockmode", "0"); g_settings.UpdateSource(type, share->strName, "lockcode", "0"); g_settings.UpdateSource(type, share->strName, "badpwdcount", "0"); g_settings.SaveSources(); CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES); g_windowManager.SendThreadMessage(msg); return true; } case CONTEXT_BUTTON_REACTIVATE_LOCK: { bool maxRetryExceeded = false; if (g_guiSettings.GetInt("masterlock.maxretries") != 0) maxRetryExceeded = (share->m_iBadPwdCount >= g_guiSettings.GetInt("masterlock.maxretries")); if (!maxRetryExceeded) { // don't prompt user for mastercode when reactivating a lock g_passwordManager.LockSource(type, share->strName, true); return true; } return false; } case CONTEXT_BUTTON_CHANGE_LOCK: { if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; CStdString strNewPW; CStdString strNewLockMode; if (CGUIDialogLockSettings::ShowAndGetLock(share->m_iLockMode,strNewPW)) strNewLockMode.Format("%i",share->m_iLockMode); else return false; // password ReSet and re-entry succeeded, write out the lock data g_settings.UpdateSource(type, share->strName, "lockcode", strNewPW); g_settings.UpdateSource(type, share->strName, "lockmode", strNewLockMode); g_settings.UpdateSource(type, share->strName, "badpwdcount", "0"); g_settings.SaveSources(); CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES); g_windowManager.SendThreadMessage(msg); return true; } default: break; } return false; }