From ffca21f2743a7b367fa212799c6e2fea6190dd5d Mon Sep 17 00:00:00 2001 From: manuel Date: Tue, 3 Mar 2015 16:53:59 +0100 Subject: initial commit for kodi master --- xbmc/addons/GUIDialogAddonInfo.cpp | 458 +++++++++++++++++++++++++++++++++++++ 1 file changed, 458 insertions(+) create mode 100644 xbmc/addons/GUIDialogAddonInfo.cpp (limited to 'xbmc/addons/GUIDialogAddonInfo.cpp') diff --git a/xbmc/addons/GUIDialogAddonInfo.cpp b/xbmc/addons/GUIDialogAddonInfo.cpp new file mode 100644 index 0000000..fe3484f --- /dev/null +++ b/xbmc/addons/GUIDialogAddonInfo.cpp @@ -0,0 +1,458 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include "GUIDialogAddonInfo.h" +#include "dialogs/GUIDialogYesNo.h" +#include "dialogs/GUIDialogOK.h" +#include "addons/AddonManager.h" +#include "AddonDatabase.h" +#include "FileItem.h" +#include "filesystem/Directory.h" +#include "filesystem/SpecialProtocol.h" +#include "GUIDialogAddonSettings.h" +#include "dialogs/GUIDialogContextMenu.h" +#include "dialogs/GUIDialogTextViewer.h" +#include "GUIUserMessages.h" +#include "guilib/GUIWindowManager.h" +#include "input/Key.h" +#include "utils/JobManager.h" +#include "utils/FileOperationJob.h" +#include "utils/StringUtils.h" +#include "utils/URIUtils.h" +#include "utils/log.h" +#include "addons/AddonInstaller.h" +#include "pvr/PVRManager.h" +#include "Util.h" +#include "interfaces/Builtins.h" + +#define CONTROL_BTN_INSTALL 6 +#define CONTROL_BTN_ENABLE 7 +#define CONTROL_BTN_UPDATE 8 +#define CONTROL_BTN_SETTINGS 9 +#define CONTROL_BTN_CHANGELOG 10 +#define CONTROL_BTN_ROLLBACK 11 +#define CONTROL_BTN_SELECT 12 + +using namespace std; +using namespace ADDON; +using namespace XFILE; + +CGUIDialogAddonInfo::CGUIDialogAddonInfo(void) + : CGUIDialog(WINDOW_DIALOG_ADDON_INFO, "DialogAddonInfo.xml"), m_jobid(0) +{ + m_item = CFileItemPtr(new CFileItem); + m_loadType = KEEP_IN_MEMORY; +} + +CGUIDialogAddonInfo::~CGUIDialogAddonInfo(void) +{ +} + +bool CGUIDialogAddonInfo::OnMessage(CGUIMessage& message) +{ + switch ( message.GetMessage() ) + { + case GUI_MSG_WINDOW_DEINIT: + { + if (m_jobid) + CJobManager::GetInstance().CancelJob(m_jobid); + } + break; + + case GUI_MSG_CLICKED: + { + int iControl = message.GetSenderId(); + if (iControl == CONTROL_BTN_UPDATE) + { + OnUpdate(); + return true; + } + if (iControl == CONTROL_BTN_INSTALL) + { + if (!m_localAddon) + { + OnInstall(); + return true; + } + else + { + OnUninstall(); + return true; + } + } + else if (iControl == CONTROL_BTN_SELECT) + { + OnLaunch(); + return true; + } + else if (iControl == CONTROL_BTN_ENABLE) + { + OnEnable(!m_item->GetProperty("Addon.Enabled").asBoolean()); + return true; + } + else if (iControl == CONTROL_BTN_SETTINGS) + { + OnSettings(); + return true; + } + else if (iControl == CONTROL_BTN_CHANGELOG) + { + OnChangeLog(); + return true; + } + else if (iControl == CONTROL_BTN_ROLLBACK) + { + OnRollback(); + return true; + } + } + break; +default: + break; + } + + return CGUIDialog::OnMessage(message); +} + +bool CGUIDialogAddonInfo::OnAction(const CAction &action) +{ + if (action.GetID() == ACTION_SHOW_INFO) + { + Close(); + return true; + } + return CGUIDialog::OnAction(action); +} + +void CGUIDialogAddonInfo::OnInitWindow() +{ + UpdateControls(); + CGUIDialog::OnInitWindow(); + m_changelog = false; +} + +void CGUIDialogAddonInfo::UpdateControls() +{ + bool isInstalled = NULL != m_localAddon.get(); + bool isEnabled = isInstalled && m_item->GetProperty("Addon.Enabled").asBoolean(); + bool isUpdatable = isInstalled && m_item->GetProperty("Addon.UpdateAvail").asBoolean(); + bool isExecutable = isInstalled && (m_localAddon->Type() == ADDON_PLUGIN || m_localAddon->Type() == ADDON_SCRIPT); + if (isInstalled) + GrabRollbackVersions(); + + bool canDisable = isInstalled && CAddonMgr::Get().CanAddonBeDisabled(m_localAddon->ID()); + bool canInstall = !isInstalled && m_item->GetProperty("Addon.Broken").empty(); + bool isRepo = (isInstalled && m_localAddon->Type() == ADDON_REPOSITORY) || (m_addon && m_addon->Type() == ADDON_REPOSITORY); + + CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_INSTALL, canDisable || canInstall); + SET_CONTROL_LABEL(CONTROL_BTN_INSTALL, isInstalled ? 24037 : 24038); + + CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_ENABLE, canDisable); + SET_CONTROL_LABEL(CONTROL_BTN_ENABLE, isEnabled ? 24021 : 24022); + + CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_UPDATE, isUpdatable); + CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_SETTINGS, isInstalled && m_localAddon->HasSettings()); + CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_SELECT, isExecutable); + CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_CHANGELOG, !isRepo); + CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_ROLLBACK, m_rollbackVersions.size() > 1); +} + +void CGUIDialogAddonInfo::OnUpdate() +{ + std::string referer = StringUtils::Format("Referer=%s-%s.zip",m_localAddon->ID().c_str(),m_localAddon->Version().asString().c_str()); + CAddonInstaller::Get().Install(m_addon->ID(), true, referer); // force install + Close(); +} + +void CGUIDialogAddonInfo::OnInstall() +{ + CAddonInstaller::Get().Install(m_addon->ID()); + Close(); +} + +void CGUIDialogAddonInfo::OnLaunch() +{ + if (!m_localAddon) + return; + + CBuiltins::Execute("RunAddon(" + m_localAddon->ID() + ")"); + Close(); +} + +bool CGUIDialogAddonInfo::PromptIfDependency(int heading, int line2) +{ + if (!m_localAddon) + return false; + + VECADDONS addons; + vector deps; + CAddonMgr::Get().GetAllAddons(addons); + for (VECADDONS::const_iterator it = addons.begin(); + it != addons.end();++it) + { + ADDONDEPS::const_iterator i = (*it)->GetDeps().find(m_localAddon->ID()); + if (i != (*it)->GetDeps().end() && !i->second.second) // non-optional dependency + deps.push_back((*it)->Name()); + } + + if (!deps.empty()) + { + string line0 = StringUtils::Format(g_localizeStrings.Get(24046).c_str(), m_localAddon->Name().c_str()); + string line1 = StringUtils::Join(deps, ", "); + CGUIDialogOK::ShowAndGetInput(heading, line0, line1, line2); + return true; + } + return false; +} + +void CGUIDialogAddonInfo::OnUninstall() +{ + if (!m_localAddon.get()) + return; + + if (!g_passwordManager.CheckMenuLock(WINDOW_ADDON_BROWSER)) + return; + + // ensure the addon is not a dependency of other installed addons + if (PromptIfDependency(24037, 24047)) + return; + + // prompt user to be sure + if (!CGUIDialogYesNo::ShowAndGetInput(24037, 750, 0, 0)) + return; + + // ensure the addon isn't disabled in our database + CAddonMgr::Get().DisableAddon(m_localAddon->ID(), false); + + CJobManager::GetInstance().AddJob(new CAddonUnInstallJob(m_localAddon), + &CAddonInstaller::Get()); + CAddonMgr::Get().RemoveAddon(m_localAddon->ID()); + Close(); +} + +void CGUIDialogAddonInfo::OnEnable(bool enable) +{ + if (!m_localAddon.get()) + return; + + if (!g_passwordManager.CheckMenuLock(WINDOW_ADDON_BROWSER)) + return; + + if (!enable && PromptIfDependency(24075, 24091)) + return; + + CAddonMgr::Get().DisableAddon(m_localAddon->ID(), !enable); + SetItem(m_item); + UpdateControls(); + g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE); +} + +void CGUIDialogAddonInfo::OnSettings() +{ + CGUIDialogAddonSettings::ShowAndGetInput(m_localAddon); +} + +void CGUIDialogAddonInfo::OnChangeLog() +{ + CGUIDialogTextViewer* pDlgInfo = (CGUIDialogTextViewer*)g_windowManager.GetWindow(WINDOW_DIALOG_TEXT_VIEWER); + std::string name; + if (m_addon) + name = m_addon->Name(); + else if (m_localAddon) + name = m_localAddon->Name(); + pDlgInfo->SetHeading(g_localizeStrings.Get(24054)+" - "+name); + if (m_item->GetProperty("Addon.Changelog").empty()) + { + pDlgInfo->SetText(g_localizeStrings.Get(13413)); + CFileItemList items; + if (m_localAddon && + !m_item->GetProperty("Addon.UpdateAvail").asBoolean()) + { + items.Add(CFileItemPtr(new CFileItem(m_localAddon->ChangeLog(),false))); + } + else + items.Add(CFileItemPtr(new CFileItem(m_addon->ChangeLog(),false))); + items[0]->Select(true); + m_jobid = CJobManager::GetInstance().AddJob( + new CFileOperationJob(CFileOperationJob::ActionCopy,items, + "special://temp/"),this); + } + else + pDlgInfo->SetText(m_item->GetProperty("Addon.Changelog").asString()); + + m_changelog = true; + pDlgInfo->DoModal(); + m_changelog = false; +} + +void CGUIDialogAddonInfo::OnRollback() +{ + if (!g_passwordManager.CheckMenuLock(WINDOW_ADDON_BROWSER)) + return; + + CGUIDialogContextMenu* dlg = (CGUIDialogContextMenu*)g_windowManager.GetWindow(WINDOW_DIALOG_CONTEXT_MENU); + CAddonDatabase database; + database.Open(); + + CContextButtons buttons; + for (unsigned int i=0;iVersion().asString()) + label += " "+g_localizeStrings.Get(24094); + if (database.IsAddonBlacklisted(m_localAddon->ID(),label)) + label += " "+g_localizeStrings.Get(24095); + + buttons.Add(i,label); + } + int choice; + if ((choice=dlg->ShowAndGetChoice(buttons)) > -1) + { + // blacklist everything newer + for (unsigned int j=choice+1;jID(),m_rollbackVersions[j]); + std::string path = "special://home/addons/packages/"; + path += m_localAddon->ID()+"-"+m_rollbackVersions[choice]+".zip"; + // needed as cpluff won't downgrade + if (!m_localAddon->IsType(ADDON_SERVICE)) + //we will handle this for service addons in CAddonInstallJob::OnPostInstall + CAddonMgr::Get().RemoveAddon(m_localAddon->ID()); + CAddonInstaller::Get().InstallFromZip(path); + database.RemoveAddonFromBlacklist(m_localAddon->ID(),m_rollbackVersions[choice]); + Close(); + } +} + +bool CGUIDialogAddonInfo::ShowForItem(const CFileItemPtr& item) +{ + CGUIDialogAddonInfo* dialog = (CGUIDialogAddonInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_ADDON_INFO); + if (!dialog) + return false; + if (!dialog->SetItem(item)) + return false; + + dialog->DoModal(); + return true; +} + +bool CGUIDialogAddonInfo::SetItem(const CFileItemPtr& item) +{ + *m_item = *item; + m_rollbackVersions.clear(); + + // grab the local addon, if it's available + m_localAddon.reset(); + m_addon.reset(); + if (CAddonMgr::Get().GetAddon(item->GetProperty("Addon.ID").asString(), m_localAddon)) // sets m_localAddon if installed regardless of enabled state + m_item->SetProperty("Addon.Enabled", "true"); + else + m_item->SetProperty("Addon.Enabled", "false"); + m_item->SetProperty("Addon.Installed", m_localAddon ? "true" : "false"); + + CAddonDatabase database; + database.Open(); + database.GetAddon(item->GetProperty("Addon.ID").asString(),m_addon); + + if (TranslateType(item->GetProperty("Addon.intType").asString()) == ADDON_REPOSITORY) + { + CAddonDatabase database; + database.Open(); + VECADDONS addons; + if (m_addon) + database.GetRepository(m_addon->ID(), addons); + else if (m_localAddon) // sanity + database.GetRepository(m_localAddon->ID(), addons); + int tot=0; + for (int i = ADDON_UNKNOWN+1;iType() == (TYPE)i) + ++num; + } + m_item->SetProperty("Repo." + TranslateType((TYPE)i), num); + tot += num; + } + m_item->SetProperty("Repo.Addons", tot); + } + return true; +} + +void CGUIDialogAddonInfo::OnJobComplete(unsigned int jobID, bool success, + CJob* job) +{ + if (!m_changelog) + return; + + CGUIDialogTextViewer* pDlgInfo = (CGUIDialogTextViewer*)g_windowManager.GetWindow(WINDOW_DIALOG_TEXT_VIEWER); + + m_jobid = 0; + if (!success) + { + pDlgInfo->SetText(g_localizeStrings.Get(195)); + } + else + { + CFile file; + XFILE::auto_buffer buf; + if (file.LoadFile("special://temp/" + + URIUtils::GetFileName(((CFileOperationJob*)job)->GetItems()[0]->GetPath()), buf) > 0) + { + std::string str(buf.get(), buf.length()); + m_item->SetProperty("Addon.Changelog", str); + pDlgInfo->SetText(str); + } + } + CGUIMessage msg(GUI_MSG_NOTIFY_ALL, WINDOW_DIALOG_TEXT_VIEWER, 0, GUI_MSG_UPDATE); + g_windowManager.SendThreadMessage(msg); +} + +void CGUIDialogAddonInfo::GrabRollbackVersions() +{ + CFileItemList items; + XFILE::CDirectory::GetDirectory("special://home/addons/packages/",items,".zip",DIR_FLAG_NO_FILE_DIRS); + items.Sort(SortByLabel, SortOrderAscending); + CAddonDatabase db; + db.Open(); + for (int i=0;im_bIsFolder) + continue; + std::string ID, version; + AddonVersion::SplitFileName(ID,version,items[i]->GetLabel()); + if (ID == m_localAddon->ID()) + { + std::string hash, path(items[i]->GetPath()); + if (db.GetPackageHash(m_localAddon->ID(), path, hash)) + { + std::string md5 = CUtil::GetFileMD5(path); + if (md5 == hash) + m_rollbackVersions.push_back(version); + else /* The package has been corrupted */ + { + CLog::Log(LOGWARNING, "%s: Removing corrupt addon package %s.", __FUNCTION__, path.c_str()); + CFile::Delete(path); + db.RemovePackage(path); + } + } + } + } +} -- cgit v1.2.3