File indexing completed on 2024-05-05 04:04:30

0001 /***************************************************************************
0002                           onu.cpp  -  description
0003                              -------------------
0004     begin                : Wed Jul 18 2001
0005     copyright            : (C) 2001-2006 by Gael de Chalendar (aka Kleag)
0006     email                : kleag@free.fr
0007  ***************************************************************************/
0008 
0009 /***************************************************************************
0010  *                                                                         *
0011  *   This program is free software; you can redistribute it and/or modify  *
0012  *   it under the terms of the GNU General Public License as published by  *
0013  *   the Free Software Foundation; either either version 2
0014    of the License, or (at your option) any later version.of the License, or     *
0015  *   (at your option) any later version.                                   *
0016  *                                                                         *
0017  *   You should have received a copy of the GNU General Public License
0018  *   along with this program; if not, write to the Free Software
0019  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
0020  *   02110-1301, USA
0021  ***************************************************************************/
0022 #include "onu.h"
0023 #include "Sprites/skinSpritesData.h"
0024 #include "goal.h"
0025 
0026 #include <QApplication>
0027 #include <QFile>
0028 #include <qdom.h>
0029 #include <QPainter>
0030 #include <QPixmapCache>
0031 #include <QMenuBar>
0032 #include <KLocalizedString>
0033 #include "ksirk_debug.h"
0034 #include <KMessageBox>
0035 #include <KConfig>
0036 #include <KConfigGroup>
0037 
0038 namespace Ksirk
0039 {
0040 
0041 namespace GameLogic
0042 {
0043 
0044 ONU::ONU(GameAutomaton* automaton,
0045   const QString& configFileName):
0046   QObject(automaton),
0047   m_automaton(automaton),
0048   m_configFileName(configFileName),
0049   countries(),
0050   nationalities(),
0051   m_continents(),
0052   m_skin(),
0053   m_zoom(1.0),
0054   m_zoomArena(1.0),
0055   m_nbZooms(0),
0056   m_zoomFactorFinal(1)
0057 {
0058   qCDebug(KSIRK_LOG) << "ONU constructor: " << m_configFileName;
0059   m_font.family = "URW Chancery L";
0060   m_font.size = (int)(13*m_zoom);
0061   m_font.weight = QFont::Bold;
0062   m_font.italic = true;
0063   m_font.foregroundColor = "black";
0064   m_font.backgroundColor = "white";
0065   
0066   m_timerFast=new QTimer(this);     //instanciation of the timer
0067   QObject::connect(m_timerFast,&QTimer::timeout, this, &ONU::changingZoom); //connect the timer to the good slot
0068   
0069   Sprites::SkinSpritesData::changeable().init();
0070 //   unsigned int nationalityId = 0;
0071 //   unsigned int continentId = 0;
0072   KConfig config(configFileName);
0073 
0074   KConfigGroup onugroup = config.group(QStringLiteral("onu"));
0075 
0076   qCDebug(KSIRK_LOG) << "ONU XML format version: " << onugroup.readEntry("format-version");
0077   QString formatVersion = onugroup.readEntry("format-version");
0078 
0079   if (formatVersion != ONU_FILE_FORMAT_VERSION)
0080   {
0081     qCCritical(KSIRK_LOG) << "Error - Invalid skin definition file format. Expected "<<QString(ONU_FILE_FORMAT_VERSION)<<" and got " << formatVersion << "in" << m_configFileName << ". You should remove this skin folder";
0082 //     KMessageBox::error(0,
0083 //                         i18n("Error - Invalid skin definition file format. Expected %1 and got %2",QString(ONU_FILE_FORMAT_VERSION),formatVersion) + "<br>" + m_configFileName,
0084 //                         i18n("Fatal Error"));
0085     return;
0086   }
0087 
0088   m_name = onugroup.readEntry("name");
0089   m_skin = onugroup.readEntry("skinpath");
0090 
0091   qCDebug(KSIRK_LOG) << "skin snapshot file: " << QStandardPaths::locate(QStandardPaths::AppDataLocation, m_skin + "/Images/snapshot.jpg");
0092   const QString snapshotCacheId = m_skin + QLatin1String("snapshot");
0093   if (!QPixmapCache::find(snapshotCacheId, &m_snapshot))
0094   {
0095     // Pixmap isn't in the cache, create it and insert to cache
0096     m_snapshot = QPixmap(QStandardPaths::locate(QStandardPaths::AppDataLocation, m_skin + "/Images/snapshot.jpg"));
0097     if (m_snapshot.isNull())
0098     {
0099       qCCritical(KSIRK_LOG) << "Was not able to load the snapshot image: " << QStandardPaths::locate(QStandardPaths::AppDataLocation, m_skin + "/Images/snapshot.jpg");
0100     }
0101     QPixmapCache::insert(snapshotCacheId, m_snapshot);
0102   }
0103   m_width  = onugroup.readEntry("width",0);
0104   m_height  = onugroup.readEntry("height",0);
0105   m_description = onugroup.readEntry("desc");
0106 //   countries.resize(onugroup.readEntry("nb-countries",0));
0107 //   nationalities.resize(onugroup.readEntry("nb-nationalities",0));
0108 //   m_continents.resize(onugroup.readEntry("nb-continents",0));
0109 //    root.attribute("map");
0110   QString poolString = onugroup.readEntry("pool");
0111   qCDebug(KSIRK_LOG) << "Pool path: " << poolString;
0112   qCDebug(KSIRK_LOG) << "Searching resource: " << (m_skin + '/' + poolString);
0113 
0114   QString poolFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, m_skin + '/' + poolString);
0115   qCDebug(KSIRK_LOG) << "Pool file name: " << poolFileName;
0116   if (poolFileName.isEmpty())
0117   {
0118       KMessageBox::error(nullptr, 
0119                          i18n("Pool filename not found\nProgram cannot continue"),
0120                          i18n("Error!"));
0121       exit(2);
0122   }
0123   m_map = QPixmap();
0124   qCDebug(KSIRK_LOG) << m_skin << "before pool loading";
0125   if (!m_automaton->rendererFor(m_skin).isValid())
0126     m_automaton->rendererFor(m_skin).load(poolFileName);
0127   if (m_automaton->svgDomFor(m_skin).svgFilename().isNull())
0128     m_automaton->svgDomFor(m_skin).load(poolFileName);
0129   qCDebug(KSIRK_LOG) << m_skin << "after pool loading";
0130   
0131   QString mapMaskFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, m_skin + '/' + onugroup.readEntry("map-mask"));
0132   qCDebug(KSIRK_LOG) << "Map mask file name: " << mapMaskFileName;
0133   if (mapMaskFileName.isNull())
0134   {
0135       KMessageBox::error(nullptr, 
0136                          i18n("Map mask image not found\nProgram cannot continue"),
0137                          i18n("Error!"));
0138       exit(2);
0139   }
0140   qCDebug(KSIRK_LOG) << "Loading map mask file: " << mapMaskFileName;
0141   QPixmap countriesMaskPix;
0142   const QString mapMaskCacheId = m_skin + QLatin1String("mapmask");
0143   if (!QPixmapCache::find(mapMaskCacheId, &countriesMaskPix))
0144   {
0145     // Pixmap isn't in the cache, create it and insert to cache
0146     countriesMaskPix = QPixmap(mapMaskFileName);
0147     if (countriesMaskPix.isNull())
0148     {
0149       qCCritical(KSIRK_LOG) << "Was not able to load the map mask image: " << mapMaskFileName ;
0150     }
0151     QPixmapCache::insert(mapMaskCacheId, countriesMaskPix);
0152   }
0153 //   countriesMask = QImage(mapMaskFileName);
0154   countriesMask = countriesMaskPix.toImage();
0155   
0156   Sprites::SkinSpritesData::changeable().intData("width-between-flag-and-fighter", onugroup.readEntry("width-between-flag-and-fighter",0));
0157 
0158   Sprites::SkinSpritesData::changeable().intData("flag-width", config.group(QStringLiteral("flag")).readEntry("width",0));
0159   Sprites::SkinSpritesData::changeable().intData("flag-height", config.group(QStringLiteral("flag")).readEntry("height",0));
0160   Sprites::SkinSpritesData::changeable().intData("flag-frames", config.group(QStringLiteral("flag")).readEntry("frames",0));
0161   Sprites::SkinSpritesData::changeable().intData("flag-versions", config.group(QStringLiteral("flag")).readEntry("versions",0));
0162 
0163 //   Sprites::SkinSpritesData::changeable().strData("infantry-id", config.group(QStringLiteral("infantry")).readEntry("id"));
0164   Sprites::SkinSpritesData::changeable().intData("infantry-width", config.group(QStringLiteral("infantry")).readEntry("width",0));
0165   Sprites::SkinSpritesData::changeable().intData("infantry-height", config.group(QStringLiteral("infantry")).readEntry("height",0));
0166   Sprites::SkinSpritesData::changeable().intData("infantry-frames", config.group(QStringLiteral("infantry")).readEntry("frames",0));
0167   Sprites::SkinSpritesData::changeable().intData("infantry-versions", config.group(QStringLiteral("infantry")).readEntry("versions",0));
0168 
0169 //   Sprites::SkinSpritesData::changeable().strData("infantry1-id", config.group(QStringLiteral("infantry1")).readEntry("id"));
0170   Sprites::SkinSpritesData::changeable().intData("infantry1-width", config.group(QStringLiteral("infantry1")).readEntry("width",0));
0171   Sprites::SkinSpritesData::changeable().intData("infantry1-height", config.group(QStringLiteral("infantry1")).readEntry("height",0));
0172   Sprites::SkinSpritesData::changeable().intData("infantry1-frames", config.group(QStringLiteral("infantry1")).readEntry("frames",0));
0173   Sprites::SkinSpritesData::changeable().intData("infantry1-versions", config.group(QStringLiteral("infantry1")).readEntry("versions",0));
0174 
0175 //   Sprites::SkinSpritesData::changeable().strData("infantry2-id", config.group(QStringLiteral("infantry2")).readEntry("id"));
0176   Sprites::SkinSpritesData::changeable().intData("infantry2-width", config.group(QStringLiteral("infantry2")).readEntry("width",0));
0177   Sprites::SkinSpritesData::changeable().intData("infantry2-height", config.group(QStringLiteral("infantry2")).readEntry("height",0));
0178   Sprites::SkinSpritesData::changeable().intData("infantry2-frames", config.group(QStringLiteral("infantry2")).readEntry("frames",0));
0179   Sprites::SkinSpritesData::changeable().intData("infantry2-versions", config.group(QStringLiteral("infantry2")).readEntry("versions",0));
0180 
0181 //   Sprites::SkinSpritesData::changeable().strData("infantry3-id", config.group(QStringLiteral("infantry3")).readEntry("id"));
0182   Sprites::SkinSpritesData::changeable().intData("infantry3-width", config.group(QStringLiteral("infantry3")).readEntry("width",0));
0183   Sprites::SkinSpritesData::changeable().intData("infantry3-height", config.group(QStringLiteral("infantry3")).readEntry("height",0));
0184   Sprites::SkinSpritesData::changeable().intData("infantry3-frames", config.group(QStringLiteral("infantry3")).readEntry("frames",0));
0185   Sprites::SkinSpritesData::changeable().intData("infantry3-versions", config.group(QStringLiteral("infantry3")).readEntry("versions",0));
0186 
0187 //   Sprites::SkinSpritesData::changeable().strData("cavalry-id", config.group(QStringLiteral("cavalry")).readEntry("id"));
0188   Sprites::SkinSpritesData::changeable().intData("cavalry-width", config.group(QStringLiteral("cavalry")).readEntry("width",0));
0189   Sprites::SkinSpritesData::changeable().intData("cavalry-height", config.group(QStringLiteral("cavalry")).readEntry("height",0));
0190   Sprites::SkinSpritesData::changeable().intData("cavalry-frames", config.group(QStringLiteral("cavalry")).readEntry("frames",0));
0191   Sprites::SkinSpritesData::changeable().intData("cavalry-versions", config.group(QStringLiteral("cavalry")).readEntry("versions",0));
0192 
0193 //   Sprites::SkinSpritesData::changeable().strData("cannon-id", config.group(QStringLiteral("cannon")).readEntry("id"));
0194   Sprites::SkinSpritesData::changeable().intData("cannon-width", config.group(QStringLiteral("cannon")).readEntry("width",0));
0195   Sprites::SkinSpritesData::changeable().intData("cannon-height", config.group(QStringLiteral("cannon")).readEntry("height",0));
0196   Sprites::SkinSpritesData::changeable().intData("cannon-frames", config.group(QStringLiteral("cannon")).readEntry("frames",0));
0197   Sprites::SkinSpritesData::changeable().intData("cannon-versions", config.group(QStringLiteral("cannon")).readEntry("versions",0));
0198 
0199 //   Sprites::SkinSpritesData::changeable().strData("firing-id", config.group(QStringLiteral("firing")).readEntry("id"));
0200   Sprites::SkinSpritesData::changeable().intData("firing-width", config.group(QStringLiteral("firing")).readEntry("width",0));
0201   Sprites::SkinSpritesData::changeable().intData("firing-height", config.group(QStringLiteral("firing")).readEntry("height",0));
0202   Sprites::SkinSpritesData::changeable().intData("firing-frames", config.group(QStringLiteral("firing")).readEntry("frames",0));
0203   Sprites::SkinSpritesData::changeable().intData("firing-versions", config.group(QStringLiteral("firing")).readEntry("versions",0));
0204 
0205 //   Sprites::SkinSpritesData::changeable().strData("exploding-id", config.group(QStringLiteral("exploding")).readEntry("id"));
0206   Sprites::SkinSpritesData::changeable().intData("exploding-width", config.group(QStringLiteral("exploding")).readEntry("width",0));
0207   Sprites::SkinSpritesData::changeable().intData("exploding-height", config.group(QStringLiteral("exploding")).readEntry("height",0));
0208   Sprites::SkinSpritesData::changeable().intData("exploding-frames", config.group(QStringLiteral("exploding")).readEntry("frames",0));
0209   Sprites::SkinSpritesData::changeable().intData("exploding-versions", config.group(QStringLiteral("exploding")).readEntry("versions",0));
0210 
0211   KConfigGroup fontgroup = config.group(QStringLiteral("font"));
0212   m_font.family = fontgroup.readEntry("family","URW Chancery L");
0213   m_font.size = fontgroup.readEntry("size",(int)(13*m_zoom));
0214   QString w = fontgroup.readEntry("weight", "bold");;
0215   if (w == "normal")
0216   {
0217     m_font.weight = QFont::Normal;
0218   }
0219   else if (w == "light")
0220   {
0221     m_font.weight = QFont::Light;
0222   }
0223   else if (w == "demibold")
0224   {
0225     m_font.weight = QFont::DemiBold;
0226   }
0227   else if (w == "bold")
0228   {
0229     m_font.weight = QFont::Bold;
0230   }
0231   else if (w == "black")
0232   {
0233     m_font.weight = QFont::Black;
0234   }
0235   m_font.italic = fontgroup.readEntry("italic", true);
0236   m_font.foregroundColor = fontgroup.readEntry("foreground-color", "black");
0237   m_font.backgroundColor = fontgroup.readEntry("background-color", "white");
0238 
0239   QStringList countriesList = onugroup.readEntry("countries", QStringList());
0240   foreach (const QString &country, countriesList)
0241   { 
0242     KConfigGroup countryGroup = config.group(country);
0243 //     unsigned int id = countryGroup.readEntry("id",0);
0244     QString name = country;
0245     QPointF anchorPoint = countryGroup.readEntry("anchor-point",QPointF())*m_zoom;
0246     QPointF centralPoint = countryGroup.readEntry("central-point",QPointF())*m_zoom;
0247     QPointF flagPoint = countryGroup.readEntry("flag-point",QPointF())*m_zoom;
0248     QPointF cannonPoint = countryGroup.readEntry("cannon-point",QPointF())*m_zoom;
0249     QPointF cavalryPoint = countryGroup.readEntry("cavalry-point",QPointF())*m_zoom;
0250     QPointF infantryPoint = countryGroup.readEntry("infantry-point",QPointF())*m_zoom;
0251 
0252 //     qCDebug(KSIRK_LOG) << "Creating country " << name;
0253 //     qCDebug(KSIRK_LOG) << "\tflag point: " << flagPoint;
0254 //     qCDebug(KSIRK_LOG) << "\tcentral point: " << centralPoint;
0255 //     qCDebug(KSIRK_LOG) << "\tcannon point: " << cannonPoint;
0256 //     qCDebug(KSIRK_LOG) << "\tcavalry point: " << cavalryPoint;
0257 //     qCDebug(KSIRK_LOG) << "\tinfantry point: " << infantryPoint;
0258     countries.push_back(new Country(automaton, name, anchorPoint, centralPoint,
0259         flagPoint, cannonPoint, cavalryPoint, infantryPoint));
0260   }
0261   QStringList nationalitiesList = onugroup.readEntry("nationalities", QStringList());
0262   foreach (const QString &nationality, nationalitiesList)
0263   {
0264 //     qCDebug(KSIRK_LOG) << "Creating nationality " << nationality;
0265     KConfigGroup nationalityGroup = config.group(nationality);
0266     QString leader = nationalityGroup.readEntry("leader","");
0267     QString flag = nationalityGroup.readEntry("flag","");
0268 //         qCDebug(KSIRK_LOG) << "Creating nationality " << name << " ; flag: " << flag;
0269     nationalities.push_back(new Nationality(nationality, flag, leader));
0270 //     nationalityId++;
0271   }
0272 
0273 
0274   QStringList continentsList = onugroup.readEntry("continents", QStringList());
0275   foreach (const QString &continent, continentsList)
0276   {
0277     KConfigGroup continentGroup = config.group(continent);
0278 
0279 //     unsigned int id = continentGroup.readEntry("id",0);
0280     unsigned int bonus = continentGroup.readEntry("bonus",0);
0281     QList<QString> countryIdList = continentGroup.readEntry("continent-countries",QList<QString>());
0282 //     int countryId;
0283     QList<Country*> continentList;
0284     foreach(const QString& countryId, countryIdList)
0285     {
0286 //       qCDebug(KSIRK_LOG) << "Adding" << countryId << "to" << continent << "list";
0287       Country *c = countryNamed(countryId);
0288       if (c)
0289       {
0290         continentList.push_back(c);
0291       }
0292     }
0293 //       qCDebug(KSIRK_LOG) << "Creating continent " << name;
0294     m_continents.push_back(new Continent(continent, continentList, bonus));
0295   }
0296 
0297   QStringList goalsList = onugroup.readEntry("goals", QStringList());
0298   foreach (const QString &_goal, goalsList)
0299   {
0300 //     qCDebug(KSIRK_LOG) << "init goal " << _goal;
0301     KConfigGroup goalGroup = config.group(_goal);
0302 
0303     Goal* goal = new Goal(automaton);
0304     goal->description(goalGroup.readEntry("desc",""));
0305     QString goalType = goalGroup.readEntry("type","");
0306     if (goalType == "countries")
0307     {
0308       goal->type(Goal::Countries);
0309       goal->nbCountries(goalGroup.readEntry("nbCountries",0));
0310       goal->nbArmiesByCountry(goalGroup.readEntry("nbArmiesByCountry",0));
0311 //       qCDebug(KSIRK_LOG) << "  nb countries: **********************************" << goal->nbCountries();
0312 //       qCDebug(KSIRK_LOG) << "  nbarmies countries: **********************************" << goal->nbArmiesByCountry();
0313     }
0314     else if (goalType == "continents" )
0315     {
0316       goal->type(Goal::Continents);
0317       QList<QString> contList = goalGroup.readEntry("continents",QList<QString>());
0318       foreach(const QString& continentId, contList)
0319       {
0320         // Bug 308527. Use only known continents.
0321         if (continentsList.contains(continentId))
0322           goal->continents().push_back(continentId);
0323         else
0324         {
0325           qCDebug(KSIRK_LOG) << "Unknown continent " << continentId << " in skin " << m_skin ;
0326         }
0327       }
0328     }
0329     else if (goalType == "player" )
0330     {
0331       goal->type(Goal::GoalPlayer);
0332       unsigned int nb = goalGroup.readEntry("nbCountriesFallback",0);
0333       goal->nbCountries(nb);
0334     }
0335     automaton->goals().push_back(goal);
0336   }
0337 
0338   foreach (const QString &countryName, countriesList)
0339   {
0340     Country *country = countryNamed(countryName);
0341 
0342     if (!country)
0343     {
0344       continue;
0345     }
0346 
0347 //     qCDebug(KSIRK_LOG) << "building neighbours list of " << countryName;
0348     QList< Country* > theNeighbours;
0349     KConfigGroup countryGroup = config.group(countryName);
0350     QList<QString> theNeighboursIds = countryGroup.readEntry("neighbours",QList<QString>());
0351 //     int neighbourId;
0352     foreach(const QString& neighbourId, theNeighboursIds)
0353     {
0354       Country *c = countryNamed(neighbourId);
0355       if (c)
0356       {
0357         theNeighbours.push_back(c);
0358       }
0359     }
0360 
0361     country-> neighbours(theNeighbours);
0362   }
0363   buildMap();
0364 
0365   qCDebug(KSIRK_LOG) << "OUT";
0366 }
0367 
0368 ONU::~ONU()
0369 {
0370   delete m_timerFast;
0371 
0372   QList<Country*>::iterator countriesIt, countriesIt_end;
0373   countriesIt = countries.begin(); countriesIt_end = countries.end();
0374   for (; countriesIt != countriesIt_end; countriesIt++)
0375   {
0376     delete *countriesIt;
0377   }
0378 
0379   QList<Nationality*>::iterator nationalitiesIt, nationalitiesIt_end;
0380   nationalitiesIt = nationalities.begin(); nationalitiesIt_end = nationalities.end();
0381   for (; nationalitiesIt != nationalitiesIt_end; nationalitiesIt++)
0382   {
0383     delete *nationalitiesIt;
0384   }
0385   
0386   QList<Continent*>::iterator continentsIt, continentsIt_end;
0387   continentsIt = m_continents.begin(); continentsIt_end = m_continents.end();
0388   for (; continentsIt != continentsIt_end; continentsIt++)
0389   {
0390     delete *continentsIt;
0391   }
0392 
0393 }
0394 
0395 
0396 /** This method returns a pointer to the country that contains the point (x,y).
0397 If there is no country at (x,y), the functions returns 0. */
0398 Country* ONU::countryAt(const QPointF& point)
0399 {
0400 //    qCDebug(KSIRK_LOG) << "ONU::countryAt x y " << x << " " << y;
0401     QPointF norm = point;
0402     norm /= m_zoom;
0403     if ( norm.x() < 0 || norm.x() >= countriesMask.width()
0404       || norm.y() < 0 || norm.y() >= countriesMask.height() )
0405       return nullptr;
0406 
0407     int index = qBlue(countriesMask.pixel(norm.toPoint()));
0408 //    qCDebug(KSIRK_LOG) << "OUT ONU::countryAt: " << index;
0409     if (index >= countries.size()) return nullptr;
0410     return countries.at(index);
0411 }
0412 
0413 void ONU::reset()
0414 {
0415   qCDebug(KSIRK_LOG);
0416   foreach (Country* country, countries)
0417   {
0418     country-> reset();
0419   }
0420 }
0421 
0422 
0423 QList<Country*>& ONU::getCountries()
0424 {
0425   return countries;
0426 }
0427 
0428 QList<Nationality*>& ONU::getNationalities()
0429 {
0430   return nationalities;
0431 }
0432 
0433 /** Read property of QList<Continent*> continents. */
0434 const QList<Continent*>& ONU::getContinents() const
0435 {
0436   return m_continents;
0437 }
0438 
0439 QList<Continent*>& ONU::getContinents()
0440 {
0441   return m_continents;
0442 }
0443 
0444 /**
0445   * Returns the list of countries neighbours of this country that does not
0446   * belongs to the argument player.
0447   */
0448 QList<Country*> ONU::neighboursBelongingTo(const Country& country, const Player* player)
0449 {
0450   QList<Country*> list;
0451   foreach (Country *c,  country.neighbours())
0452   {
0453     if ((country.communicateWith(c)) && (c-> owner() == player))
0454       {list.push_back(c);}
0455   }
0456   return list;
0457 }
0458 
0459 /**
0460   * Returns the list of countries neighbours of this country that does not
0461   * belongs to the argument player.
0462   */
0463 QList<Country*> ONU::neighboursNotBelongingTo(const Country& country, const Player* player)
0464 {
0465   QList<Country*> list;
0466   foreach (Country *c,  country.neighbours())
0467   {
0468     if ((country.communicateWith(c)) && (c-> owner() != player))
0469       {list.push_back(c);}
0470   }
0471   return list;
0472 }
0473 
0474 /**
0475   * Returns the country named "name" ; 0 in case there is no such country
0476   */
0477 Country* ONU::countryNamed(const QString& name)
0478 {
0479   if (name.isEmpty())
0480   {
0481 //     qCDebug(KSIRK_LOG) << "request for country with empty name";
0482     return nullptr;
0483   }
0484 
0485   foreach (Country *c, countries)
0486   {
0487     if (c-> name() == name)
0488       return c;
0489   }
0490 
0491 //   qCDebug(KSIRK_LOG) << "request for country" << name << "which doesn't seem to exist.";
0492   return nullptr;
0493 }
0494 
0495 /** @return the number of countries in the world */
0496 unsigned int ONU::getNbCountries() const
0497 {
0498     return(countries.size());
0499 }
0500 
0501 void ONU::saveXml(QTextStream& xmlStream)
0502 {
0503   xmlStream << "<ONU file=\"" << m_configFileName << "\" >";
0504 
0505   xmlStream << "<countries>";
0506   foreach (Country *c, countries)
0507   {
0508       c->saveXml(xmlStream);
0509   }
0510   xmlStream << "</countries>";
0511   xmlStream << "</ONU>";  
0512 }
0513 
0514 unsigned int ONU::width() const
0515 {
0516   return m_width;
0517 }
0518 
0519 unsigned int ONU::height() const
0520 {
0521   return m_height;
0522 }
0523 
0524 /** Returns the nation named "name" ; 0 in case there is no such nation */
0525 Nationality* ONU::nationNamed(const QString& name)
0526 {
0527   foreach (Nationality *n, nationalities)
0528   {
0529     if (n->name() == name)
0530     {
0531       return n;
0532     }
0533   }
0534   return nullptr;
0535 }
0536 
0537 void ONU::sendCountries(QDataStream& stream)
0538 {
0539   stream << quint32(countries.size());
0540   foreach (Country* country, countries)
0541   {
0542 //     qCDebug(KSIRK_LOG) << "Sending country " << country->name();
0543     country->send(stream);
0544   }
0545 }
0546 
0547 /*const Continent* ONU::continentWithId(const unsigned int id) const
0548 {
0549   for (unsigned int i = 0; i < m_continents.size(); i++)
0550   {
0551     if ( m_continents.at(i)->id() == id)
0552     {
0553       return m_continents.at(i);
0554     }
0555   }
0556   return 0;
0557 }
0558 */
0559 Continent* ONU::continentNamed(const QString& name)
0560 {
0561   foreach (Continent *c, m_continents)
0562   {
0563     if (c-> name() == name)
0564       return c;
0565   }
0566   return nullptr;
0567 }
0568 
0569 void ONU::buildMap()
0570 {
0571   qCDebug(KSIRK_LOG) << "with zoom="<< m_zoom;
0572   //QSize size((int)(m_automaton->rendererFor(m_skin).defaultSize().width()*m_zoom),(int)(m_automaton->rendererFor(m_skin).defaultSize().height()*m_zoom));
0573   const qreal dpr = qApp->devicePixelRatio();
0574   const int mapDeviceWidth = m_width * dpr;
0575   const int mapDeviceHeight = m_height * dpr;
0576   const QString mapCacheId = m_skin + QLatin1String("map") + QString::number(mapDeviceWidth) + QLatin1Char('x') + QString::number(mapDeviceHeight);
0577   if (!QPixmapCache::find(mapCacheId, &m_map))
0578   {
0579     // Pixmap isn't in the cache, create it and insert to cache
0580     m_map = QPixmap(mapDeviceWidth, mapDeviceHeight);
0581     m_map.fill(Qt::transparent);
0582     QPainter painter(&m_map);
0583     m_automaton->rendererFor(m_skin).render(&painter, "map");
0584 
0585     QFont foregroundFont(m_font.family, m_font.size, m_font.weight, m_font.italic);
0586     QFont backgroundFont(m_font.family, m_font.size, QFont::Normal, m_font.italic);
0587 
0588     painter.scale(dpr, dpr);
0589     foreach (Country* country, countries)
0590     {
0591       const QString& countryName = i18n(country->name().toUtf8().data());
0592       if (m_font.backgroundColor != "none")
0593       {
0594         painter.setPen(m_font.backgroundColor);
0595         painter.setFont(backgroundFont);
0596         QRect countryNameRect = painter.fontMetrics().boundingRect(countryName);
0597         painter.drawText(
0598           int( (country->centralPoint().x()*m_zoom) - (countryNameRect.width()/2) + 1 ),
0599          // HACK HACK see the same below
0600           int( (country->centralPoint().y()*m_zoom) + 4/*(countryNameRect.height()/2)*/ + 1 ),
0601           countryName);
0602       }
0603       painter.setPen(m_font.foregroundColor);
0604       painter.setFont(foregroundFont);
0605       QRect countryNameRect = painter.fontMetrics().boundingRect(countryName);
0606 //       qCDebug(KSIRK_LOG) << countryName << "countryNameRect=" << countryNameRect;
0607 //       qCDebug(KSIRK_LOG) << "draw at" << int( (country->centralPoint().x()*m_zoom) - (countryNameRect.width()/2) ) <<
0608 //      int( (country->centralPoint().y()*m_zoom) - (countryNameRect.height()/2) );
0609       
0610       painter.drawText(
0611         int( (country->centralPoint().x()*m_zoom) - (countryNameRect.width()/2) ),
0612         // HACK HACK why is this 4 necessary below instead of the commented correction ???
0613         int( (country->centralPoint().y()*m_zoom) + 4/*- (countryNameRect.height()/2)*/ ),
0614         countryName);
0615     }
0616     m_map.setDevicePixelRatio(dpr);
0617 
0618     QPixmapCache::insert(mapCacheId, m_map);
0619   }
0620 }
0621 
0622 void ONU::applyZoomFactor(qreal zoomFactor)
0623 {
0624 /** Zoom 1: First method (take a long time to zoom) :
0625 */
0626 //   qCDebug(KSIRK_LOG) << "zoomFactor=" << zoomFactor << "old zoom=" << m_zoom;
0627 //   qCDebug(KSIRK_LOG) << "new zoom=" << m_zoom;
0628 
0629   m_zoom *= zoomFactor;
0630 
0631   //m_font.size = (int)(m_font.size*m_zoom);
0632   //m_width = (unsigned int)(m_width *m_zoom);
0633   //m_height = (unsigned int)(m_height *m_zoom);
0634 
0635   buildMap();
0636 
0637   foreach (Country* country, countries)
0638   {
0639     country->createArmiesSprites();
0640   }
0641  
0642 }
0643 
0644 void ONU::applyZoomFactorFast(qreal zoomFactor)     //benj
0645 {
0646 
0647 /** Zoom 2 : Second method , Very performent.  Carefull ! Can cause the game to lag. 
0648  To try this, comment all the first method and uncomment these lines
0649 */
0650   qCDebug(KSIRK_LOG) << "zoomFactor FASTTTTTTT";
0651   int nbLimitZooms = 6;
0652 
0653   //Application of zoom
0654   if (zoomFactor > 1 && m_nbZooms < nbLimitZooms)
0655   {
0656     m_font.size = (int)(m_font.size*zoomFactor);
0657     m_width = (unsigned int)(m_width *zoomFactor);
0658     m_height = (unsigned int)(m_height *zoomFactor);
0659 
0660       m_nbZooms++; // zoom forward
0661       m_automaton->game()->frame()->scale(zoomFactor, zoomFactor);
0662       m_zoomFactorFinal *= zoomFactor;
0663 
0664       //starting timer
0665       /*if  (m_timerFast->isActive())
0666       {
0667         m_timerFast->stop();
0668       }
0669       m_timerFast->start(4000);
0670       m_timerFast->setSingleShot(true);*/
0671 
0672   }
0673   else if (zoomFactor < 1 && m_nbZooms > -nbLimitZooms)
0674   {
0675     m_font.size = (int)(m_font.size*zoomFactor);
0676     m_width = (unsigned int)(m_width *zoomFactor);
0677     m_height = (unsigned int)(m_height *zoomFactor);
0678 
0679       m_nbZooms--; // zoom backward
0680       m_automaton->game()->frame()->scale(zoomFactor, zoomFactor);
0681       m_zoomFactorFinal *= zoomFactor;
0682 
0683       //starting timer
0684       /*if  (m_timerFast->isActive())
0685       {
0686         m_timerFast->stop();
0687       }
0688       m_timerFast->start(4000);
0689       m_timerFast->setSingleShot(true);*/
0690   }
0691 }
0692 
0693 double ONU::zoom() const
0694 {
0695   if (m_automaton->game()->currentWidgetType() == KGameWindow::Map) {
0696     return m_zoom;
0697   }
0698   return m_zoomArena;
0699 }
0700 
0701 
0702 QSvgRenderer* ONU::renderer()
0703 {
0704   return &m_automaton->rendererFor(m_skin);
0705 }
0706 
0707 
0708 KGameSvgDocument* ONU::svgDom()
0709 {
0710   return &m_automaton->svgDomFor(m_skin);
0711 }
0712 
0713 unsigned int ONU::indexOfCountry(Country* c) const
0714 {
0715   return countries.indexOf(c);
0716 }
0717 
0718 
0719 /** the SLOTS METHODS FOR THE ONU CLASS*/
0720 void ONU::changingZoom()
0721 {
0722 /*
0723   m_automaton->game()->frame()->resetTransform();
0724   qreal m_zo=m_zoomFactorFinal;
0725   m_zoomFactorFinal=1;
0726   applyZoomFactor(m_zo);*/
0727 
0728  // m_automaton->game()->frame()->scale(1/m_zoomFactorFinal, 1/m_zoomFactorFinal);
0729 
0730   m_automaton->game()->frame()->resetTransform();
0731   applyZoomFactor(m_zoomFactorFinal);
0732   m_zoomFactorFinal=1.0;
0733 }
0734 
0735 /**END OF SLOTS METHODS FOR THE ONU*/
0736 } // closing namespace GameLogic
0737 } // closing namespace Ksirk
0738 
0739 #include "moc_onu.cpp"