1) Changed queue and addon vector to use SynchronisedVector in order

to hide more pthread calls.
2) Started to work on screen layout.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@7401 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2011-01-14 00:58:11 +00:00
parent 9c0dd7c079
commit dbe6395c1e
7 changed files with 107 additions and 122 deletions

View File

@ -1,27 +1,22 @@
<stkgui> <stkgui>
<div x="5%" y="0%" width="90%" height="80%" layout="horizontal-row" > <div x="5%" width="90%" height="90%" layout="vertical-row">
<div width="50%" height="90%" layout="vertical-row" > <label x="0" width="100%" id="name" align="center" width="100%" text="Name:" proportion="1" />
<spacer height="22%" /> <div x="5%" y="0%" width="90%" height="80%" layout="horizontal-row" >
<div width="50%" height="100%" layout="vertical-row" >
<icon id="icon" align="center" proportion="8" width="100%" icon="gui/loading.png"/> <icon id="icon" align="center" proportion="8" width="100%" icon="gui/loading.png"/>
<spacer proportion="1" />
<button id="install" width="70%" I18N="Addons" text="Install" align="center"/>
</div> </div>
<div width="50%" height="90%" layout="vertical-row" > <spacer proportion="1" />
<label id="name" width="100%" text="Name:" proportion="1" /> <div width="50%" height="100%" layout="vertical-row" >
<label word_wrap="true" id="description" width="100%" text="Description:" proportion="1" /> <label word_wrap="true" id="description" width="100%" text="Description:" proportion="1" />
<label id="version" width="100%" text="Version:" proportion="1" /> <label id="version" width="100%" text="Version:" proportion="1" />
<spacer proportion="1" />
<button id="cancel" width="70%" I18N="Addons" text="Back" align="center"/>
</div> </div>
</div>
</div> <spacer proportion="1" />
<progressbar id="progress" width="100%" height="35"/>
<div x="5%" y="80%" width="40%" height="10%" layout="horizontal-row">
<spacer proportion="1" />
<button id="cancel" width="70%" I18N="Addons" text="Back" align="center"/>
<spacer proportion="1" />
</div>
<div x="50%" y="80%" width="40%" height="10%" layout="horizontal-row" >
<spacer proportion="1" />
<button id="install" width="70%" I18N="Addons" text="Install" align="center"/>
<spacer proportion="1" />
</div> </div>
</stkgui> </stkgui>

View File

@ -28,11 +28,12 @@
#include "io/xml_node.hpp" #include "io/xml_node.hpp"
#include "utils/string_utils.hpp" #include "utils/string_utils.hpp"
Addon::Addon(const XMLNode &xml, bool installed) Addon::Addon(const XMLNode &xml)
{ {
m_installed = installed;
m_installed_version = 0;
m_name = ""; m_name = "";
m_id = "";
m_installed = false;
m_installed_version = 0;
m_version = 0 ; m_version = 0 ;
m_zip_file = ""; m_zip_file = "";
m_description = ""; m_description = "";
@ -40,27 +41,19 @@ Addon::Addon(const XMLNode &xml, bool installed)
m_icon_basename = ""; m_icon_basename = "";
m_icon_version = 0; m_icon_version = 0;
m_icon_ready = false; m_icon_ready = false;
m_id = "";
m_type = xml.getName(); m_type = xml.getName();
xml.get("name", &m_name); xml.get("name", &m_name );
if(m_installed) m_id = StringUtils::toLowerCase(m_name);
{ xml.get("id", &m_id);
xml.get("installed-version", &m_installed_version); xml.get("installed", &m_installed );
xml.get("id", &m_id ); xml.get("installed-version", &m_installed_version);
xml.get("icon-version", &m_icon_version ); xml.get("version", &m_version );
} xml.get("file", &m_zip_file );
else // not installed xml.get("description", &m_description );
{ xml.get("icon", &m_icon_url );
xml.get("file", &m_zip_file ); xml.get("icon-version", &m_icon_version );
xml.get("description", &m_description); m_icon_basename = StringUtils::getBasename(m_icon_url);
xml.get("icon", &m_icon_url );
xml.get("version", &m_version );
// The online list has a numeric id, which is not used.
// So ignore it.
m_id = StringUtils::toLowerCase(m_name);
m_icon_basename = StringUtils::getBasename(m_icon_url);
} // if installed
}; // Addon(const XML&) }; // Addon(const XML&)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@ -57,7 +57,7 @@ public:
Addon() {}; Addon() {};
/** Initialises the object from an XML node. */ /** Initialises the object from an XML node. */
Addon(const XMLNode &xml, bool installed=false); Addon(const XMLNode &xml);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void writeXML(std::ofstream *out_stram); void writeXML(std::ofstream *out_stram);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

View File

@ -45,10 +45,12 @@ AddonsManager* addons_manager = 0;
* the list of already installed addons). The online component is initialised * the list of already installed addons). The online component is initialised
* later from a separate thread in network_http (once network_http is setup). * later from a separate thread in network_http (once network_http is setup).
*/ */
AddonsManager::AddonsManager() : m_state(STATE_INIT) AddonsManager::AddonsManager() : m_state(STATE_INIT),
m_icon_queue(std::vector<std::string>() ),
m_addons_list(std::vector<Addon>() )
{ {
m_file_installed = file_manager->getAddonsFile("addons_installed.xml"); m_file_installed = file_manager->getAddonsFile("addons_installed.xml");
loadInstalledAddons();
} // AddonsManager } // AddonsManager
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -61,6 +63,10 @@ AddonsManager::AddonsManager() : m_state(STATE_INIT)
*/ */
void AddonsManager::initOnline(const XMLNode *xml) void AddonsManager::initOnline(const XMLNode *xml)
{ {
m_addons_list.lock();
loadInstalledAddons();
m_addons_list.unlock();
for(unsigned int i=0; i<xml->getNumNodes(); i++) for(unsigned int i=0; i<xml->getNumNodes(); i++)
{ {
const XMLNode *node = xml->getNode(i); const XMLNode *node = xml->getNode(i);
@ -105,13 +111,15 @@ void AddonsManager::initOnline(const XMLNode *xml)
continue; continue;
} }
m_addons_list.lock();
if(index>=0) if(index>=0)
m_addons_list[index].copyInstallData(addon); m_addons_list.getData()[index].copyInstallData(addon);
else else
{ {
m_addons_list.push_back(addon); m_addons_list.getData().push_back(addon);
index = m_addons_list.size()-1; index = m_addons_list.getData().size()-1;
} }
m_addons_list.unlock();
} }
else else
{ {
@ -125,8 +133,6 @@ void AddonsManager::initOnline(const XMLNode *xml)
m_state.set(STATE_READY); m_state.set(STATE_READY);
pthread_mutex_init(&m_mutex_icon, NULL);
pthread_t id; pthread_t id;
pthread_attr_t attr; pthread_attr_t attr;
pthread_attr_init(&attr); pthread_attr_init(&attr);
@ -141,42 +147,44 @@ void AddonsManager::initOnline(const XMLNode *xml)
void *AddonsManager::downloadIcons(void *obj) void *AddonsManager::downloadIcons(void *obj)
{ {
AddonsManager *me=(AddonsManager*)obj; AddonsManager *me=(AddonsManager*)obj;
me->m_icon_queue.lock();
me->m_icon_queue.getData().clear();
me->m_icon_queue.unlock();
me->m_icon_queue.clear(); for(unsigned int i=0; i<me->m_addons_list.getData().size(); i++)
for(unsigned int i=0; i<me->m_addons_list.size(); i++)
{ {
const Addon &addon = me->m_addons_list[i]; const Addon &addon = me->m_addons_list.getData()[i];
const std::string &icon = addon.getIconBasename(); const std::string &icon = addon.getIconBasename();
if(addon.iconNeedsUpdate()) if(addon.iconNeedsUpdate())
{ {
pthread_mutex_lock(&(me->m_mutex_icon)); me->m_icon_queue.lock();
me->m_icon_queue.push_back(addon.getId()); me->m_icon_queue.getData().push_back(addon.getId());
pthread_mutex_unlock(&(me->m_mutex_icon)); me->m_icon_queue.unlock();
continue; continue;
} }
std::string icon_path=file_manager->getAddonsFile("icons/"+icon); std::string icon_path=file_manager->getAddonsFile("icons/"+icon);
if(!file_manager->fileExists(icon_path)) if(!file_manager->fileExists(icon_path))
{ {
pthread_mutex_lock(&(me->m_mutex_icon)); me->m_icon_queue.lock();
me->m_icon_queue.push_back(addon.getId()); me->m_icon_queue.getData().push_back(addon.getId());
pthread_mutex_unlock(&(me->m_mutex_icon)); me->m_icon_queue.unlock();
continue; continue;
} }
me->m_addons_list[i].setIconReady(); me->m_addons_list.getData()[i].setIconReady();
} // for i<m_addons_list.size() } // for i<m_addons_list.size()
pthread_mutex_lock(&(me->m_mutex_icon)); me->m_icon_queue.lock();
int count = me->m_icon_queue.size(); int count = me->m_icon_queue.getData().size();
pthread_mutex_unlock(&(me->m_mutex_icon)); me->m_icon_queue.unlock();
while(count!=0) while(count!=0)
{ {
pthread_mutex_lock(&(me->m_mutex_icon)); me->m_icon_queue.lock();
unsigned int indx = me->getAddonIndex(me->m_icon_queue[0]); std::vector<std::string> &icon_queue = me->m_icon_queue.getData();
Addon *addon = &(me->m_addons_list[indx]); unsigned int indx = me->getAddonIndex(icon_queue[0]);
me->m_icon_queue.erase(me->m_icon_queue.begin()); Addon *addon = &(me->m_addons_list.getData()[indx]);
icon_queue.erase(icon_queue.begin());
count --; count --;
pthread_mutex_unlock(&(me->m_mutex_icon)); me->m_icon_queue.unlock();
const std::string &url = addon->getIconURL(); const std::string &url = addon->getIconURL();
const std::string &icon = addon->getIconBasename(); const std::string &icon = addon->getIconBasename();
@ -191,10 +199,14 @@ void *AddonsManager::downloadIcons(void *obj)
icon.c_str(), url.c_str()); icon.c_str(), url.c_str());
} }
} // while count!=0 } // while count!=0
for(unsigned int i=0; i<me->m_addons_list.size(); i++)
// Now check if we have any entries in m_addons_list, that is not
// in the online list anymore
for(unsigned int i=0; i<me->m_addons_list.getData().size(); i++)
{ {
if(!me->m_addons_list[i].iconReady()) if(!me->m_addons_list.getData()[i].iconReady())
printf("No icon for '%s'.\n", me->m_addons_list[i].getId().c_str()); printf("No icon for '%s'.\n",
me->m_addons_list.getData()[i].getId().c_str());
} }
me->saveInstalled(); me->saveInstalled();
return NULL; return NULL;
@ -230,8 +242,8 @@ void AddonsManager::loadInstalledAddons()
if(node->getName()=="kart" || if(node->getName()=="kart" ||
node->getName()=="track" ) node->getName()=="track" )
{ {
Addon addon(*node, /*installed*/ true); Addon addon(*node);
m_addons_list.push_back(addon); m_addons_list.getData().push_back(addon);
} }
} // for i <= xml->getNumNodes() } // for i <= xml->getNumNodes()
@ -246,15 +258,15 @@ void AddonsManager::loadInstalledAddons()
const Addon* AddonsManager::getAddon(const std::string &id) const const Addon* AddonsManager::getAddon(const std::string &id) const
{ {
int i = getAddonIndex(id); int i = getAddonIndex(id);
return (i<0) ? NULL : &(m_addons_list[i]); return (i<0) ? NULL : &(m_addons_list.getData()[i]);
} // getAddon } // getAddon
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
int AddonsManager::getAddonIndex(const std::string &id) const int AddonsManager::getAddonIndex(const std::string &id) const
{ {
for(unsigned int i = 0; i < m_addons_list.size(); i++) for(unsigned int i = 0; i < m_addons_list.getData().size(); i++)
{ {
if(m_addons_list[i].getId()== id) if(m_addons_list.getData()[i].getId()== id)
{ {
return i; return i;
} }
@ -285,8 +297,8 @@ void AddonsManager::install(const Addon &addon)
} }
int index = getAddonIndex(addon.getId()); int index = getAddonIndex(addon.getId());
assert(index>=0 && index < (int)m_addons_list.size()); assert(index>=0 && index < (int)m_addons_list.getData().size());
m_addons_list[index].setInstalled(true); m_addons_list.getData()[index].setInstalled(true);
if(addon.getType()=="kart") if(addon.getType()=="kart")
{ {
@ -319,11 +331,11 @@ void AddonsManager::saveInstalled(const std::string &type)
xml_installed << "<addons xmlns='http://stkaddons.tuxfamily.org/'>" xml_installed << "<addons xmlns='http://stkaddons.tuxfamily.org/'>"
<< std::endl; << std::endl;
for(unsigned int i = 0; i < m_addons_list.size(); i++) for(unsigned int i = 0; i < m_addons_list.getData().size(); i++)
{ {
//if(m_addons_list[i].m_installed) //if(m_addons_list[i].m_installed)
{ {
m_addons_list[i].writeXML(&xml_installed); m_addons_list.getData()[i].writeXML(&xml_installed);
} }
} }
xml_installed << "</addons>" << std::endl; xml_installed << "</addons>" << std::endl;
@ -346,8 +358,8 @@ void AddonsManager::uninstall(const Addon &addon)
// addon is a const reference, and to avoid removing the const, we // addon is a const reference, and to avoid removing the const, we
// find the proper index again to modify the installed state // find the proper index again to modify the installed state
int index = getAddonIndex(addon.getId()); int index = getAddonIndex(addon.getId());
assert(index>=0 && index < (int)m_addons_list.size()); assert(index>=0 && index < (int)m_addons_list.getData().size());
m_addons_list[index].setInstalled(false); m_addons_list.getData()[index].setInstalled(false);
//write the xml file with the informations about installed karts //write the xml file with the informations about installed karts
std::string name=addon.getType()+"s/"+addon.getId(); std::string name=addon.getType()+"s/"+addon.getId();

View File

@ -24,8 +24,6 @@
#include <map> #include <map>
#include <vector> #include <vector>
#include <pthread.h>
#include "addons/addon.hpp" #include "addons/addon.hpp"
#include "io/xml_node.hpp" #include "io/xml_node.hpp"
#include "utils/synchronised.hpp" #include "utils/synchronised.hpp"
@ -33,22 +31,21 @@
class AddonsManager class AddonsManager
{ {
private: private:
std::vector<Addon> m_addons_list; /** The list of all addons - installed or uninstalled. The list is
std::string m_file_installed; * combined from the addons_installed.xml file first, then information
void saveInstalled(const std::string &type=""); * from the downloaded list of items is merged/added to that. */
void loadInstalledAddons(); Synchronised<std::vector<Addon> > m_addons_list;
std::string m_type; /** Full filename of the addons_installed.xml file. */
int m_download_state; std::string m_file_installed;
std::string m_type;
int m_download_state;
/** List of loaded icons. */ /** List of loaded icons. */
std::vector<std::string> m_icon_list; std::vector<std::string> m_icon_list;
/** Queue of icons to download. This queue is used by the /** Queue of icons to download. This queue is used by the
* GUI to increase priority of icons that are needed now. */ * GUI to increase priority of icons that are needed now. */
std::vector<std::string> m_icon_queue; Synchronised<std::vector<std::string> > m_icon_queue;
/** Mutex to protect access to icon_list. */
pthread_mutex_t m_mutex_icon;
/** Which state the addons manager is: /** Which state the addons manager is:
* INIT: Waiting to download the list of addons. * INIT: Waiting to download the list of addons.
@ -58,6 +55,8 @@ private:
// Synchronise the state between threads (e.g. GUI and update thread) // Synchronise the state between threads (e.g. GUI and update thread)
Synchronised<STATE_TYPE> m_state; Synchronised<STATE_TYPE> m_state;
void saveInstalled(const std::string &type="");
void loadInstalledAddons();
static void *downloadIcons(void *obj); static void *downloadIcons(void *obj);
public: public:
@ -68,10 +67,13 @@ public:
void setErrorState() { m_state.set(STATE_ERROR); } void setErrorState() { m_state.set(STATE_ERROR); }
/** Returns the list of addons (installed and uninstalled). */ /** Returns the list of addons (installed and uninstalled). */
unsigned int getNumAddons() const { return m_addons_list.size(); } unsigned int getNumAddons() const
{
return m_addons_list.getData().size();
}
/** Returns the i-th addons. */ /** Returns the i-th addons. */
const Addon& getAddon(unsigned int i) { return m_addons_list[i];} const Addon& getAddon(unsigned int i) { return m_addons_list.getData()[i];}
const Addon* getAddon(const std::string &id) const; const Addon* getAddon(const std::string &id) const;
int getAddonIndex(const std::string &id) const; int getAddonIndex(const std::string &id) const;

View File

@ -42,13 +42,13 @@ AddonsLoading::AddonsLoading(const float w, const float h,
{ {
loadFromFile("addons_view_dialog.stkgui"); loadFromFile("addons_view_dialog.stkgui");
m_addon = *(addons_manager->getAddon(id)); m_addon = *(addons_manager->getAddon(id));
m_progress = NULL;
m_can_install = false;
m_percent_update = false;
m_icon_shown = false; m_icon_shown = false;
/*Init the icon here to be able to load a single image*/ /*Init the icon here to be able to load a single image*/
m_icon = getWidget<IconButtonWidget>("icon"); m_icon = getWidget<IconButtonWidget>("icon");
m_progress = getWidget<ProgressBarWidget>("progress");
if(m_progress)
m_progress->setVisible(false);
if(m_addon.isInstalled()) if(m_addon.isInstalled())
{ {
@ -88,16 +88,8 @@ GUIEngine::EventPropagation
// not uninstalling an addon. // not uninstalling an addon.
if(!m_addon.isInstalled() || m_addon.needsUpdate()) if(!m_addon.isInstalled() || m_addon.needsUpdate())
{ {
assert(m_progress==NULL); m_progress->setValue(0);
m_progress = new ProgressBarWidget(); m_progress->setVisible(true);
m_progress->m_x = 180;
m_progress->m_y = m_area.getHeight()-45;
m_progress->m_w = 250;
m_progress->m_h = 35;
m_progress->setParent(m_irrlicht_window);
m_widgets.push_back(m_progress);
m_progress->add();
/*This widget will show some text as "downloading..." or "installing".*/ /*This widget will show some text as "downloading..." or "installing".*/
m_state = new LabelWidget(); m_state = new LabelWidget();
@ -112,9 +104,7 @@ GUIEngine::EventPropagation
m_widgets.push_back(m_state); m_widgets.push_back(m_state);
m_state->add(); m_state->add();
getWidget<ButtonWidget>("cancel")->setDeactivated();
getWidget<ButtonWidget>("install")->setDeactivated(); getWidget<ButtonWidget>("install")->setDeactivated();
m_percent_update = true;
startDownload(); startDownload();
} }
else // uninstall else // uninstall
@ -129,7 +119,7 @@ GUIEngine::EventPropagation
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void AddonsLoading::onUpdate(float delta) void AddonsLoading::onUpdate(float delta)
{ {
if(m_progress) if(m_progress->isVisible())
{ {
float progress = network_http->getProgress(); float progress = network_http->getProgress();
m_progress->setValue((int)(progress*100.0f)); m_progress->setValue((int)(progress*100.0f));

View File

@ -47,13 +47,6 @@ private:
void startDownload(); void startDownload();
void doInstall(); void doInstall();
/* These three bool are some flags.
* m_can_install : when the installation is finidhed, onUpdate close the
* dialog.
* m_percent_update : to reload the download percent */
bool m_can_install;
bool m_percent_update;
/** True if the icon is being displayed. */ /** True if the icon is being displayed. */
bool m_icon_shown; bool m_icon_shown;
@ -66,8 +59,8 @@ public:
GUIEngine::EventPropagation processEvent(const std::string& event_source); GUIEngine::EventPropagation processEvent(const std::string& event_source);
/** This function is called by the GUI, all the frame (or somthing like /** This function is called by the GUI, all the frame (or somthing like
* that). It checks the flags (m_can_install, m_can_load_icon and * that). It checks the flags (m_can_load_icon and
* m_percent_update) and do the necessary. * and do the necessary.
* */ * */
void onUpdate(float delta); void onUpdate(float delta);