2 // Copyright (C) 2009 Ingo Ruhnke <grumbel@gmail.com>
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "supertux/menu/addon_menu.hpp"
21 #include <boost/format.hpp>
23 #include "addon/addon.hpp"
24 #include "addon/addon_manager.hpp"
25 #include "gui/menu.hpp"
26 #include "gui/menu_item.hpp"
27 #include "gui/menu_manager.hpp"
28 #include "supertux/menu/download_dialog.hpp"
29 #include "util/gettext.hpp"
33 #define IS_REPOSITORY_MENU_ID(idx) ((idx - MNID_ADDON_LIST_START) % 2 == 0)
34 #define IS_INSTALLED_MENU_ID(idx) ((idx - MNID_ADDON_LIST_START) % 2 == 1)
36 #define MAKE_REPOSITORY_MENU_ID(idx) (MNID_ADDON_LIST_START + 2*idx+0)
37 #define MAKE_INSTALLED_MENU_ID(idx) (MNID_ADDON_LIST_START + 2*idx+1)
39 #define UNPACK_REPOSITORY_MENU_ID(idx) (((idx - MNID_ADDON_LIST_START) - 0) / 2)
40 #define UNPACK_INSTALLED_MENU_ID(idx) (((idx - MNID_ADDON_LIST_START) - 1) / 2)
42 std::string addon_type_to_translated_string(Addon::Type type)
60 std::string generate_menu_item_text(const Addon& addon)
63 std::string type = addon_type_to_translated_string(addon.get_type());
65 if(!addon.get_author().empty())
67 text = str(boost::format(_("%s \"%s\" by \"%s\""))
68 % type % addon.get_title() % addon.get_author());
72 // Only addon type and name, no need for translation.
73 text = str(boost::format("%s \"%s\"")
74 % type % addon.get_title());
82 AddonMenu::AddonMenu() :
83 m_addon_manager(*AddonManager::current()),
93 m_installed_addons = m_addon_manager.get_installed_addons();
94 m_repository_addons = m_addon_manager.get_repository_addons();
100 AddonMenu::rebuild_menu()
103 add_label(_("Add-ons"));
107 if (m_installed_addons.empty())
109 add_inactive(MNID_NOTHING_NEW, _("No Addons installed"));
114 for (const auto& addon_id : m_installed_addons)
116 const Addon& addon = m_addon_manager.get_installed_addon(addon_id);
117 std::string text = generate_menu_item_text(addon);
118 add_toggle(MAKE_INSTALLED_MENU_ID(idx), text, addon.is_enabled());
126 bool have_new_stuff = false;
128 for (const auto& addon_id : m_repository_addons)
130 const Addon& addon = m_addon_manager.get_repository_addon(addon_id);
133 // addon is already installed, so check if they are the same
134 Addon& installed_addon = m_addon_manager.get_installed_addon(addon_id);
135 if (installed_addon.get_md5() == addon.get_md5() ||
136 installed_addon.get_version() > addon.get_version())
138 log_debug << "ignoring already installed addon " << installed_addon.get_id() << std::endl;
142 log_debug << installed_addon.get_id() << " is installed, but updated: '"
143 << installed_addon.get_md5() << "' vs '" << addon.get_md5() << "' '"
144 << installed_addon.get_version() << "' vs '" << addon.get_version() << "'"
146 std::string text = generate_menu_item_text(addon);
147 add_entry(MAKE_REPOSITORY_MENU_ID(idx), str(boost::format( _("Install %s *NEW*") ) % text));
148 have_new_stuff = true;
151 catch(const std::exception& err)
153 // addon is not installed
154 std::string text = generate_menu_item_text(addon);
155 add_entry(MAKE_REPOSITORY_MENU_ID(idx), str(boost::format( _("Install %s") ) % text));
156 have_new_stuff = true;
161 if (!have_new_stuff && m_addon_manager.has_been_updated())
163 add_inactive(MNID_NOTHING_NEW, _("No new Addons found"));
167 if (!m_addon_manager.has_online_support())
169 add_inactive(MNID_CHECK_ONLINE, std::string(_("Check Online (disabled)")));
173 add_entry(MNID_CHECK_ONLINE, std::string(_("Check Online")));
181 AddonMenu::menu_action(MenuItem* item)
183 if (item->id == MNID_CHECK_ONLINE) // check if "Check Online" was chosen
187 TransferStatusPtr status = m_addon_manager.request_check_online();
196 std::unique_ptr<DownloadDialog> dialog(new DownloadDialog(status));
197 dialog->set_title("Downloading Add-On Repository Index");
198 MenuManager::instance().set_dialog(std::move(dialog));
200 catch (std::exception& e)
202 log_warning << "Check for available Add-ons failed: " << e.what() << std::endl;
205 else if (MNID_ADDON_LIST_START <= item->id)
207 if (IS_INSTALLED_MENU_ID(item->id))
209 int idx = UNPACK_INSTALLED_MENU_ID(item->id);
210 if (0 <= idx && idx < static_cast<int>(m_installed_addons.size()))
212 const Addon& addon = m_addon_manager.get_installed_addon(m_installed_addons[idx]);
213 if(addon.is_enabled())
215 m_addon_manager.disable_addon(addon.get_id());
216 set_toggled(item->id, addon.is_enabled());
220 m_addon_manager.enable_addon(addon.get_id());
221 set_toggled(item->id, addon.is_enabled());
225 else if (IS_REPOSITORY_MENU_ID(item->id))
227 int idx = UNPACK_REPOSITORY_MENU_ID(item->id);
228 if (0 <= idx && idx < static_cast<int>(m_repository_addons.size()))
230 const Addon& addon = m_addon_manager.get_repository_addon(m_repository_addons[idx]);
231 auto addon_id = addon.get_id();
232 TransferStatusPtr status = m_addon_manager.request_install_addon(addon_id);
235 [this, addon_id](bool success)
241 m_addon_manager.enable_addon(addon_id);
243 catch(const std::exception& err)
245 log_warning << "Enabling addon failed: " << err.what() << std::endl;
251 std::unique_ptr<DownloadDialog> dialog(new DownloadDialog(status));
252 dialog->set_title("Downloading " + generate_menu_item_text(addon));
253 MenuManager::instance().set_dialog(std::move(dialog));
259 log_warning << "Unknown menu item clicked: " << item->id << std::endl;