123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695 |
- /*
- Minetest
- Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, 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 Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
- #include <iostream>
- #include <string>
- #include <map>
- #include "guiConfigureWorld.h"
- #include "guiMessageMenu.h"
- #include <IGUIButton.h>
- #include <IGUICheckBox.h>
- #include <IGUIListBox.h>
- #include <IGUIStaticText.h>
- #include <IGUITreeView.h>
- #include "gettext.h"
- #include "util/string.h"
- #include "settings.h"
- #include "filesys.h"
- enum
- {
- GUI_ID_MOD_TREEVIEW = 101,
- GUI_ID_ENABLED_CHECKBOX,
- GUI_ID_ENABLEALL,
- GUI_ID_DISABLEALL,
- GUI_ID_DEPENDS_LISTBOX,
- GUI_ID_RDEPENDS_LISTBOX,
- GUI_ID_CANCEL,
- GUI_ID_SAVE
- };
- #define QUESTIONMARK_STR L"?"
- #define CHECKMARK_STR L"\411"
- #define CROSS_STR L"\403"
- GUIConfigureWorld::GUIConfigureWorld(gui::IGUIEnvironment* env,
- gui::IGUIElement* parent, s32 id,
- IMenuManager *menumgr, WorldSpec wspec):
- GUIModalMenu(env, parent, id, menumgr),
- m_wspec(wspec),
- m_gspec(findWorldSubgame(m_wspec.path)),
- m_menumgr(menumgr)
- {
- //will be initialized in regenerateGUI()
- m_treeview=NULL;
- // game mods
- m_gamemods = flattenModTree(getModsInPath(m_gspec.gamemods_path));
- // world mods
- std::string worldmods_path = wspec.path + DIR_DELIM + "worldmods";
- m_worldmods = flattenModTree(getModsInPath(worldmods_path));
- // fill m_addontree with add-on mods
- std::set<std::string> paths = m_gspec.addon_mods_paths;
- for(std::set<std::string>::iterator it=paths.begin();
- it != paths.end(); ++it)
- {
- std::map<std::string,ModSpec> mods = getModsInPath(*it);
- m_addontree.insert(mods.begin(), mods.end());
- }
- // expand modpacks
- m_addonmods = flattenModTree(m_addontree);
- // collect reverse dependencies
- for(std::map<std::string, ModSpec>::iterator it = m_addonmods.begin();
- it != m_addonmods.end(); ++it)
- {
- std::string modname = (*it).first;
- ModSpec mod = (*it).second;
- for(std::set<std::string>::iterator dep_it = mod.depends.begin();
- dep_it != mod.depends.end(); ++dep_it)
- {
- m_reverse_depends.insert(std::make_pair((*dep_it),modname));
- }
- }
- m_settings.readConfigFile((m_wspec.path + DIR_DELIM + "world.mt").c_str());
- std::vector<std::string> names = m_settings.getNames();
- // mod_names contains the names of mods mentioned in the world.mt file
- std::set<std::string> mod_names;
- for(std::vector<std::string>::iterator it = names.begin();
- it != names.end(); ++it)
- {
- std::string name = *it;
- if (name.compare(0,9,"load_mod_")==0)
- mod_names.insert(name.substr(9));
- }
- // find new mods (installed but not mentioned in world.mt)
- for(std::map<std::string, ModSpec>::iterator it = m_addonmods.begin();
- it != m_addonmods.end(); ++it)
- {
- std::string modname = (*it).first;
- ModSpec mod = (*it).second;
- // a mod is new if it is not a modpack, and does not occur in
- // mod_names
- if(!mod.is_modpack &&
- mod_names.count(modname) == 0)
- m_settings.setBool("load_mod_"+modname, false);
- }
- // find missing mods (mentioned in world.mt, but not installed)
- for(std::set<std::string>::iterator it = mod_names.begin();
- it != mod_names.end(); ++it)
- {
- std::string modname = *it;
- if(m_addonmods.count(modname) == 0)
- m_settings.remove("load_mod_"+modname);
- }
- std::string worldmtfile = m_wspec.path+DIR_DELIM+"world.mt";
- m_settings.updateConfigFile(worldmtfile.c_str());
- }
- void GUIConfigureWorld::drawMenu()
- {
- gui::IGUISkin* skin = Environment->getSkin();
- if (!skin)
- return;
- video::IVideoDriver* driver = Environment->getVideoDriver();
-
- video::SColor bgcolor(140,0,0,0);
- driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);
- gui::IGUIElement::draw();
- }
- void GUIConfigureWorld::regenerateGui(v2u32 screensize)
- {
- /*
- Remove stuff
- */
- removeChildren();
-
- /*
- Calculate new sizes and positions
- */
- core::rect<s32> rect(
- screensize.X/2 - 580/2,
- screensize.Y/2 - 300/2,
- screensize.X/2 + 580/2,
- screensize.Y/2 + 300/2
- );
-
- DesiredRect = rect;
- recalculateAbsolutePosition(false);
- v2s32 size = rect.getSize();
- v2s32 topleft = v2s32(10, 10);
- /*
- Add stuff
- */
- changeCtype("");
- {
- core::rect<s32> rect(0, 0, 200, 20);
- rect += topleft;
- //proper text is set below, when a mod is selected
- m_modname_text = Environment->addStaticText(L"Mod: N/A", rect, false,
- false, this, -1);
- }
- {
- core::rect<s32> rect(0, 0, 200, 20);
- rect += v2s32(0, 25) + topleft;
- wchar_t* text = wgettext("enabled");
- m_enabled_checkbox =
- Environment->addCheckBox(false, rect, this, GUI_ID_ENABLED_CHECKBOX,
- text);
- delete[] text;
- m_enabled_checkbox->setVisible(false);
- }
- {
- core::rect<s32> rect(0, 0, 85, 30);
- rect = rect + v2s32(0, 25) + topleft;
- wchar_t* text = wgettext("Enable All");
- m_enableall = Environment->addButton(rect, this, GUI_ID_ENABLEALL,
- text);
- delete[] text;
- m_enableall->setVisible(false);
- }
- {
- core::rect<s32> rect(0, 0, 85, 30);
- rect = rect + v2s32(115, 25) + topleft;
- wchar_t* text = wgettext("Disable All");
- m_disableall = Environment->addButton(rect, this, GUI_ID_DISABLEALL, text );
- delete[] text;
- m_disableall->setVisible(false);
- }
- {
- core::rect<s32> rect(0, 0, 200, 20);
- rect += v2s32(0, 60) + topleft;
- wchar_t* text = wgettext("depends on:");
- Environment->addStaticText(text, rect, false, false, this, -1);
- delete[] text;
- }
- {
- core::rect<s32> rect(0, 0, 200, 85);
- rect += v2s32(0, 80) + topleft;
- m_dependencies_listbox =
- Environment->addListBox(rect, this, GUI_ID_DEPENDS_LISTBOX, true);
- }
- {
- core::rect<s32> rect(0, 0, 200, 20);
- rect += v2s32(0, 175) + topleft;
- wchar_t* text = wgettext("is required by:");
- Environment->addStaticText( text, rect, false, false, this, -1);
- delete[] text;
- }
- {
- core::rect<s32> rect(0, 0, 200, 85);
- rect += v2s32(0, 195) + topleft;
- m_rdependencies_listbox =
- Environment->addListBox(rect,this, GUI_ID_RDEPENDS_LISTBOX,true);
- }
- {
- core::rect<s32> rect(0, 0, 340, 250);
- rect += v2s32(220, 0) + topleft;
- m_treeview = Environment->addTreeView(rect, this,
- GUI_ID_MOD_TREEVIEW,true);
- gui::IGUITreeViewNode* node
- = m_treeview->getRoot()->addChildBack(L"Add-Ons");
- buildTreeView(m_addontree, node);
- }
- {
- core::rect<s32> rect(0, 0, 120, 30);
- rect = rect + v2s32(330, 270) - topleft;
- wchar_t* text = wgettext("Cancel");
- Environment->addButton(rect, this, GUI_ID_CANCEL, text);
- delete[] text;
- }
- {
- core::rect<s32> rect(0, 0, 120, 30);
- rect = rect + v2s32(460, 270) - topleft;
- wchar_t* text = wgettext("Save");
- Environment->addButton(rect, this, GUI_ID_SAVE, text);
- delete[] text;
- }
- changeCtype("C");
- // at start, none of the treeview nodes is selected, so we select
- // the first element in the treeview of mods manually here.
- if(m_treeview->getRoot()->hasChilds())
- {
- m_treeview->getRoot()->getFirstChild()->setExpanded(true);
- m_treeview->getRoot()->getFirstChild()->setSelected(true);
- // Because a manual ->setSelected() doesn't cause an event, we
- // have to do this here:
- adjustSidebar();
- }
- }
- bool GUIConfigureWorld::OnEvent(const SEvent& event)
- {
- gui::IGUITreeViewNode* selected_node = NULL;
- if(m_treeview != NULL)
- selected_node = m_treeview->getSelected();
- if(event.EventType==EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown)
- {
- switch (event.KeyInput.Key) {
- case KEY_ESCAPE: {
- quitMenu();
- return true;
- }
- // irrlicht's built-in TreeView gui has no keyboard control,
- // so we do it here: up/down to select prev/next node,
- // left/right to collapse/expand nodes, space to toggle
- // enabled/disabled.
- case KEY_DOWN: {
- if(selected_node != NULL)
- {
- gui::IGUITreeViewNode* node = selected_node->getNextVisible();
- if(node != NULL)
- {
- node->setSelected(true);
- adjustSidebar();
- }
- }
- return true;
- }
- case KEY_UP: {
- if(selected_node != NULL)
- {
- gui::IGUITreeViewNode* node = selected_node->getPrevSibling();
- if(node!=NULL)
- {
- node->setSelected(true);
- adjustSidebar();
- }
- else
- {
- gui::IGUITreeViewNode* parent = selected_node->getParent();
- if(selected_node == parent->getFirstChild() &&
- parent != m_treeview->getRoot())
- {
- parent->setSelected(true);
- adjustSidebar();
- }
- }
- }
- return true;
- }
- case KEY_RIGHT: {
- if(selected_node != NULL && selected_node->hasChilds())
- selected_node->setExpanded(true);
- return true;
- }
- case KEY_LEFT: {
- if(selected_node != NULL && selected_node->hasChilds())
- selected_node->setExpanded(false);
- return true;
- }
- case KEY_SPACE: {
- if(selected_node != NULL && !selected_node->hasChilds() &&
- selected_node->getText() != NULL)
- {
- std::string modname = wide_to_narrow(selected_node->getText());
- bool checked = m_enabled_checkbox->isChecked();
- m_enabled_checkbox->setChecked(!checked);
- setEnabled(modname,!checked);
- }
- return true;
- }
- default: {}
- }
- }
- if(event.EventType==EET_GUI_EVENT)
- {
- if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
- && isVisible())
- {
- if(!canTakeFocus(event.GUIEvent.Element))
- {
- dstream<<"GUIConfigureWorld: Not allowing focus change."
- <<std::endl;
- // Returning true disables focus change
- return true;
- }
- }
- if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED){
- switch(event.GUIEvent.Caller->getID()){
- case GUI_ID_CANCEL: {
- quitMenu();
- return true;
- }
- case GUI_ID_SAVE: {
- std::string worldmtfile = m_wspec.path+DIR_DELIM+"world.mt";
- m_settings.updateConfigFile(worldmtfile.c_str());
- // The trailing spaces are because there seems to be a
- // bug in the text-size calculation. if the trailing
- // spaces are removed from the message text, the
- // message gets wrapped and parts of it are cut off:
- wchar_t* text = wgettext("Configuration saved. ");
- GUIMessageMenu *menu =
- new GUIMessageMenu(Environment, Parent, -1, m_menumgr,
- text );
- delete[] text;
- menu->drop();
- try
- {
- ModConfiguration modconf(m_wspec.path);
- if(!modconf.isConsistent())
- {
- wchar_t* text = wgettext("Warning: Configuration not consistent. ");
- GUIMessageMenu *menu =
- new GUIMessageMenu(Environment, Parent, -1, m_menumgr,
- text );
- delete[] text;
- menu->drop();
- }
- }
- catch(ModError &err)
- {
- errorstream<<err.what()<<std::endl;
- std::wstring text = narrow_to_wide(err.what()) + wgettext("\nCheck debug.txt for details.");
- GUIMessageMenu *menu =
- new GUIMessageMenu(Environment, Parent, -1, m_menumgr,
- text );
- menu->drop();
- }
- quitMenu();
- return true;
- }
- case GUI_ID_ENABLEALL: {
- if(selected_node != NULL && selected_node->getParent() == m_treeview->getRoot())
- {
- enableAllMods(m_addonmods,true);
- }
- else if(selected_node != NULL && selected_node->getText() != NULL)
- {
- std::string modname = wide_to_narrow(selected_node->getText());
- std::map<std::string, ModSpec>::iterator mod_it = m_addonmods.find(modname);
- if(mod_it != m_addonmods.end())
- enableAllMods(mod_it->second.modpack_content,true);
- }
- return true;
- }
- case GUI_ID_DISABLEALL: {
- if(selected_node != NULL && selected_node->getParent() == m_treeview->getRoot())
- {
- enableAllMods(m_addonmods,false);
- }
- if(selected_node != NULL && selected_node->getText() != NULL)
- {
- std::string modname = wide_to_narrow(selected_node->getText());
- std::map<std::string, ModSpec>::iterator mod_it = m_addonmods.find(modname);
- if(mod_it != m_addonmods.end())
- enableAllMods(mod_it->second.modpack_content,false);
- }
- return true;
- }
- }
- }
- if(event.GUIEvent.EventType==gui::EGET_CHECKBOX_CHANGED &&
- event.GUIEvent.Caller->getID() == GUI_ID_ENABLED_CHECKBOX)
- {
- if(selected_node != NULL && !selected_node->hasChilds() &&
- selected_node->getText() != NULL)
- {
- std::string modname = wide_to_narrow(selected_node->getText());
- setEnabled(modname, m_enabled_checkbox->isChecked());
- }
- return true;
- }
- if(event.GUIEvent.EventType==gui::EGET_TREEVIEW_NODE_SELECT &&
- event.GUIEvent.Caller->getID() == GUI_ID_MOD_TREEVIEW)
- {
- selecting_dep = -1;
- selecting_rdep = -1;
- adjustSidebar();
- return true;
- }
- if(event.GUIEvent.EventType==gui::EGET_LISTBOX_CHANGED &&
- event.GUIEvent.Caller->getID() == GUI_ID_DEPENDS_LISTBOX)
- {
- selecting_dep = m_dependencies_listbox->getSelected();
- selecting_rdep = -1;
- return true;
- }
- if(event.GUIEvent.EventType==gui::EGET_LISTBOX_CHANGED &&
- event.GUIEvent.Caller->getID() == GUI_ID_RDEPENDS_LISTBOX)
- {
- selecting_dep = -1;
- selecting_rdep = m_rdependencies_listbox->getSelected();
- return true;
- }
- //double click in a dependency listbox: find corresponding
- //treeviewnode and select it:
- if(event.GUIEvent.EventType==gui::EGET_LISTBOX_SELECTED_AGAIN)
- {
- gui::IGUIListBox* box = NULL;
- if(event.GUIEvent.Caller->getID() == GUI_ID_DEPENDS_LISTBOX)
- {
- box = m_dependencies_listbox;
- if(box->getSelected() != selecting_dep)
- return true;
- }
- if(event.GUIEvent.Caller->getID() == GUI_ID_RDEPENDS_LISTBOX)
- {
- box = m_rdependencies_listbox;
- if(box->getSelected() != selecting_rdep)
- return true;
- }
- if(box != NULL && box->getSelected() != -1 &&
- box->getListItem(box->getSelected()) != NULL)
- {
- std::string modname =
- wide_to_narrow(box->getListItem(box->getSelected()));
- std::map<std::string, gui::IGUITreeViewNode*>::iterator it =
- m_nodes.find(modname);
- if(it != m_nodes.end())
- {
- // select node and make sure node is visible by
- // expanding all parents
- gui::IGUITreeViewNode* node = (*it).second;
- node->setSelected(true);
- while(!node->isVisible() &&
- node->getParent() != m_treeview->getRoot())
- {
- node = node->getParent();
- node->setExpanded(true);
- }
- adjustSidebar();
- }
- }
- return true;
- }
- }
- return Parent ? Parent->OnEvent(event) : false;
- }
- void GUIConfigureWorld::buildTreeView(std::map<std::string, ModSpec> mods,
- gui::IGUITreeViewNode* node)
- {
- for(std::map<std::string,ModSpec>::iterator it = mods.begin();
- it != mods.end(); ++it)
- {
- std::string modname = (*it).first;
- ModSpec mod = (*it).second;
- gui::IGUITreeViewNode* new_node =
- node->addChildBack(narrow_to_wide(modname).c_str());
- m_nodes.insert(std::make_pair(modname, new_node));
- if(mod.is_modpack)
- buildTreeView(mod.modpack_content, new_node);
- else
- {
- // set icon for node: x for disabled mods, checkmark for enabled mods
- bool mod_enabled = false;
- if(m_settings.exists("load_mod_"+modname))
- mod_enabled = m_settings.getBool("load_mod_"+modname);
- if(mod_enabled)
- new_node->setIcon(CHECKMARK_STR);
- else
- new_node->setIcon(CROSS_STR);
- }
- }
- }
- void GUIConfigureWorld::adjustSidebar()
- {
- gui::IGUITreeViewNode* node = m_treeview->getSelected();
- std::wstring modname_w;
- if(node->getText() != NULL)
- modname_w = node->getText();
- else
- modname_w = L"N/A";
- std::string modname = wide_to_narrow(modname_w);
- ModSpec mspec;
- std::map<std::string, ModSpec>::iterator it = m_addonmods.find(modname);
- if(it != m_addonmods.end())
- mspec = it->second;
- m_dependencies_listbox->clear();
- m_rdependencies_listbox->clear();
- // if no mods installed, there is nothing to enable/disable, so we
- // don't show buttons or checkbox on the sidebar
- if(node->getParent() == m_treeview->getRoot() && !node->hasChilds())
- {
- m_disableall->setVisible(false);
- m_enableall->setVisible(false);
- m_enabled_checkbox->setVisible(false);
- return;
- }
-
- // a modpack is not enabled/disabled by itself, only its cotnents
- // are. so we show show enable/disable all buttons, but hide the
- // checkbox
- if(node->getParent() == m_treeview->getRoot() ||
- mspec.is_modpack)
- {
- m_enabled_checkbox->setVisible(false);
- m_disableall->setVisible(true);
- m_enableall->setVisible(true);
- m_modname_text->setText((L"Modpack: "+modname_w).c_str());
- return;
- }
- // for a normal mod, we hide the enable/disable all buttons, but show the checkbox.
- m_disableall->setVisible(false);
- m_enableall->setVisible(false);
- m_enabled_checkbox->setVisible(true);
- m_modname_text->setText((L"Mod: "+modname_w).c_str());
- // the mod is enabled unless it is disabled in the world.mt settings.
- bool mod_enabled = true;
- if(m_settings.exists("load_mod_"+modname))
- mod_enabled = m_settings.getBool("load_mod_"+modname);
- m_enabled_checkbox->setChecked(mod_enabled);
- for(std::set<std::string>::iterator it=mspec.depends.begin();
- it != mspec.depends.end(); ++it)
- {
- // check if it is an add-on mod or a game/world mod. We only
- // want to show add-ons
- std::string dependency = (*it);
- if(m_gamemods.count(dependency) > 0)
- dependency += " (" + m_gspec.id + ")";
- else if(m_worldmods.count(dependency) > 0)
- dependency += " (" + m_wspec.name + ")";
- else if(m_addonmods.count(dependency) == 0)
- dependency += " (missing)";
- m_dependencies_listbox->addItem(narrow_to_wide(dependency).c_str());
- }
- // reverse dependencies of this mod:
- std::pair< std::multimap<std::string, std::string>::iterator,
- std::multimap<std::string, std::string>::iterator > rdep =
- m_reverse_depends.equal_range(modname);
- for(std::multimap<std::string,std::string>::iterator it = rdep.first;
- it != rdep.second; ++it)
- {
- // check if it is an add-on mod or a game/world mod. We only
- // want to show add-ons
- std::string rdependency = (*it).second;
- if(m_addonmods.count(rdependency) > 0)
- m_rdependencies_listbox->addItem(narrow_to_wide(rdependency).c_str());
- }
- }
- void GUIConfigureWorld::enableAllMods(std::map<std::string, ModSpec> mods,bool enable)
- {
- for(std::map<std::string, ModSpec>::iterator it = mods.begin();
- it != mods.end(); ++it)
- {
- ModSpec mod = (*it).second;
- if(mod.is_modpack)
- // a modpack, recursively enable all mods in it
- enableAllMods(mod.modpack_content,enable);
- else // not a modpack
- setEnabled(mod.name, enable);
- }
- }
- void GUIConfigureWorld::enableMod(std::string modname)
- {
- std::map<std::string, ModSpec>::iterator mod_it = m_addonmods.find(modname);
- if(mod_it == m_addonmods.end()){
- errorstream << "enableMod() called with invalid mod name \"" << modname << "\"" << std::endl;
- return;
- }
- ModSpec mspec = mod_it->second;
- m_settings.setBool("load_mod_"+modname,true);
- std::map<std::string,gui::IGUITreeViewNode*>::iterator it =
- m_nodes.find(modname);
- if(it != m_nodes.end())
- (*it).second->setIcon(CHECKMARK_STR);
- //also enable all dependencies
- for(std::set<std::string>::iterator it=mspec.depends.begin();
- it != mspec.depends.end(); ++it)
- {
- std::string dependency = *it;
- // only enable it if it is an add-on mod
- if(m_addonmods.count(dependency) > 0)
- enableMod(dependency);
- }
- }
- void GUIConfigureWorld::disableMod(std::string modname)
- {
- std::map<std::string, ModSpec>::iterator mod_it = m_addonmods.find(modname);
- if(mod_it == m_addonmods.end()){
- errorstream << "disableMod() called with invalid mod name \"" << modname << "\"" << std::endl;
- return;
- }
- m_settings.setBool("load_mod_"+modname,false);
- std::map<std::string,gui::IGUITreeViewNode*>::iterator it =
- m_nodes.find(modname);
- if(it != m_nodes.end())
- (*it).second->setIcon(CROSS_STR);
- //also disable all mods that depend on this one
- std::pair<std::multimap<std::string, std::string>::iterator,
- std::multimap<std::string, std::string>::iterator > rdep =
- m_reverse_depends.equal_range(modname);
- for(std::multimap<std::string,std::string>::iterator it = rdep.first;
- it != rdep.second; ++it)
- {
- std::string rdependency = (*it).second;
- // only disable it if it is an add-on mod
- if(m_addonmods.count(rdependency) > 0)
- disableMod(rdependency);
- }
- }
|