MapModel converted to QStandardItemList; separators fixed; changed used data format (human-readable struct instead of magic list) for map info in HwMapContainer (+ various small cleanups in that class)
authorsheepluva
Fri, 27 Apr 2012 22:22:04 +0200
changeset 6939 970389573788
parent 6938 217ed62e872c
child 6940 211aca8c1f4f
MapModel converted to QStandardItemList; separators fixed; changed used data format (human-readable struct instead of magic list) for map info in HwMapContainer (+ various small cleanups in that class)
QTfrontend/model/MapModel.cpp
QTfrontend/model/MapModel.h
QTfrontend/model/ThemeModel.cpp
QTfrontend/model/ThemeModel.h
QTfrontend/ui/widget/mapContainer.cpp
--- a/QTfrontend/model/MapModel.cpp	Fri Apr 27 11:47:37 2012 +0200
+++ b/QTfrontend/model/MapModel.cpp	Fri Apr 27 22:22:04 2012 +0200
@@ -1,67 +1,29 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2006-2007 Igor Ulyanov <iulyanov@gmail.com>
+ * Copyright (c) 2007-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * 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; version 2 of the License
+ *
+ * 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+/**
+ * @file
+ * @brief MapModel class implementation
+ */
 
 #include "MapModel.h"
 
-MapModel::MapInfo MapModel::mapInfoFromData(const QVariant data)
-{
-    MapInfo mapInfo;
-
-    mapInfo.type = Invalid;
-    mapInfo.name = "";
-    mapInfo.theme = "";
-    mapInfo.limit = 0;
-    mapInfo.scheme = "";
-    mapInfo.weapons = "";
-
-    if (data.isValid())
-    {
-        QList<QVariant> list = data.toList();
-        if (list.size() < 1) {
-            mapInfo.type = Invalid;
-            return mapInfo;
-        }
-        mapInfo.type = (MapType)list[0].toInt();
-        switch (mapInfo.type)
-        {
-            case GeneratedMap:
-            case GeneratedMaze:
-            case HandDrawnMap:
-                return mapInfo;
-
-            default:
-                mapInfo.name = list[1].toString();
-                mapInfo.theme = list[2].toString();
-                mapInfo.limit = list[3].toInt();
-                mapInfo.scheme = list[4].toString();
-                mapInfo.weapons = list[5].toString();
-        }
-    }
-
-    return mapInfo;
-}
-
-MapModel::MapModel(QObject *parent) :
-    QAbstractListModel(parent)
-{
-    m_data = QList<QMap<int, QVariant> >();
-}
-
-int MapModel::rowCount(const QModelIndex &parent) const
-{
-    if(parent.isValid())
-        return 0;
-    else
-        return m_data.size();
-}
-
-
-QVariant MapModel::data(const QModelIndex &index, int role) const
-{
-    if(index.column() > 0 || index.row() >= m_data.size())
-        return QVariant();
-    else
-        return m_data.at(index.row()).value(role, QVariant());
-}
-
 
 void MapModel::loadMaps()
 {
@@ -73,34 +35,22 @@
     QStringList maps =
         datamgr.entryList("Maps", QDir::AllDirs | QDir::NoDotAndDotDot);
 
-    m_data.clear();
+    QStandardItemModel::clear();
 
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
-    m_data.reserve(maps.size());
-#endif
-
-    QMap<int, QVariant> tmp;
-    QList<QVariant> mapInfo;
+    QList<QStandardItem *> genMaps;
+    QList<QStandardItem *> missionMaps;
+    QList<QStandardItem *> staticMaps;
 
     // TODO: icons for these
-    tmp.insert(Qt::DisplayRole, QComboBox::tr("generated map..."));
-    mapInfo.append(GeneratedMap);
-    tmp.insert(Qt::UserRole, mapInfo);
-    m_data.append(tmp);
-    tmp.insert(Qt::DisplayRole, QComboBox::tr("generated maze..."));
-    mapInfo.replace(0, GeneratedMaze);
-    tmp.insert(Qt::UserRole, mapInfo);
-    m_data.append(tmp);
-    tmp.insert(Qt::DisplayRole, QComboBox::tr("hand drawn map..."));
-    mapInfo.replace(0, HandDrawnMap);
-    tmp.insert(Qt::UserRole, mapInfo);
-    m_data.append(tmp);
 
-    m_nGenerators = 3;
+    genMaps.append(
+        infoToItem(QIcon(), QComboBox::tr("generated map..."), GeneratedMap, "+rnd+"));
+    genMaps.append(
+        infoToItem(QIcon(), QComboBox::tr("generated maze..."), GeneratedMaze, "+maze+"));
+    genMaps.append(
+        infoToItem(QIcon(), QComboBox::tr("hand drawn map..."), HandDrawnMap, "+drawn+"));
 
 
-    m_nMissions = 0;
-
     QFile mapLuaFile;
     QFile mapCfgFile;
 
@@ -111,80 +61,113 @@
         mapLuaFile.setFileName(
             datamgr.findFileForRead(QString("Maps/%1/map.lua").arg(map)));
 
-        QMap<int, QVariant> dataset;
-
 
         if (mapCfgFile.open(QFile::ReadOnly))
         {
+            QString caption;
             QString theme;
             quint32 limit = 0;
             QString scheme;
             QString weapons;
-            QList<QVariant> mapInfo;
             bool isMission = mapLuaFile.exists();
-            int type = isMission?MissionMap:StaticMap;
+            MapType type = isMission?MissionMap:StaticMap;
 
             QTextStream input(&mapCfgFile);
             input >> theme;
             input >> limit;
             input >> scheme;
             input >> weapons;
-            mapInfo.push_back(type);
-            mapInfo.push_back(map);
-            mapInfo.push_back(theme);
-            if (limit)
-                mapInfo.push_back(limit);
-            else
-                mapInfo.push_back(18);
+            mapCfgFile.close();
+
+            if (limit == 0)
+                limit = 18;
 
 
             if (scheme.isEmpty())
                 scheme = "locked";
-            scheme.replace("_", " ");
+            else
+                scheme.replace("_", " ");
 
             if (weapons.isEmpty())
                 weapons = "locked";
-            weapons.replace("_", " ");
+            else
+                weapons.replace("_", " ");
 
-            mapInfo.push_back(scheme);
-            mapInfo.push_back(weapons);
-
-            if(isMission)
+            if (isMission)
             {
                 // TODO: icon
-                map = QComboBox::tr("Mission") + ": " + map;
+                caption = QComboBox::tr("Mission") + ": " + map;
                 m_nMissions++;
             }
-
-            mapCfgFile.close();
-
-            // set name
-            dataset.insert(Qt::DisplayRole, map);
+            else
+                caption = map;
 
-            // TODO
-            // dataset.insert(Qt::DecorationRole, icon);
+            QStandardItem * item = infoToItem(
+                QIcon(), caption, type, map, theme, limit, scheme, weapons);
 
-            // set mapinfo
-            dataset.insert(Qt::UserRole, mapInfo);
-
-            if (isMission) // insert missions before regular maps
-                m_data.insert(m_nGenerators + m_nMissions, dataset);
+            if (isMission)
+                missionMaps.append(item);
             else
-                m_data.append(dataset);
+                staticMaps.append(item);
         
         }
 
     }
 
+    m_nMissions = missionMaps.size();
+
+    QStandardItem separator("---");
+    separator.setData(QLatin1String("separator"), Qt::AccessibleDescriptionRole);
+    separator.setFlags(separator.flags() & ~( Qt::ItemIsEnabled | Qt::ItemIsSelectable ) );
+
+    QList<QStandardItem * > items;
+    items.append(genMaps);
+    items.append(separator.clone());
+    items.append(separator.clone());
+    items.append(missionMaps);
+    items.append(separator.clone());
+    items.append(staticMaps);
+
+    QStandardItemModel::appendColumn(items);
+
     endResetModel();
 }
 
-int MapModel::generatorCount() const
-{
-    return m_nGenerators;
-}
 
 int MapModel::missionCount() const
 {
     return m_nMissions;
 }
+
+
+QStandardItem * MapModel::infoToItem(
+    const QIcon & icon,
+    const QString caption,
+    MapType type,
+    QString name,
+    QString theme,
+    quint32 limit,
+    QString scheme,
+    QString weapons)
+const
+{
+    QStandardItem * item = new QStandardItem(icon, caption);
+    MapInfo mapInfo;
+    QVariant qvar(QVariant::UserType);
+
+    mapInfo.type = type;
+    mapInfo.name = name;
+    mapInfo.theme = theme;
+    mapInfo.limit = limit;
+    mapInfo.scheme = scheme;
+    mapInfo.weapons = weapons;
+
+
+    qvar.setValue(mapInfo);
+    item->setData(qvar, Qt::UserRole + 1);
+
+    if (mapInfo.type == Invalid)
+            Q_ASSERT(false);
+
+    return item;
+}
--- a/QTfrontend/model/MapModel.h	Fri Apr 27 11:47:37 2012 +0200
+++ b/QTfrontend/model/MapModel.h	Fri Apr 27 22:22:04 2012 +0200
@@ -25,7 +25,7 @@
 #ifndef HEDGEWARS_MAPMODEL_H
 #define HEDGEWARS_MAPMODEL_H
 
-#include <QAbstractListModel>
+#include <QStandardItemModel>
 #include <QStringList>
 #include <QTextStream>
 #include <QMap>
@@ -40,7 +40,7 @@
  * @author sheepluva
  * @since 0.9.18
  */
-class MapModel : public QAbstractListModel
+class MapModel : public QStandardItemModel
 {
         Q_OBJECT
 
@@ -64,13 +64,6 @@
             QString weapons;
         };
 
-        static MapInfo mapInfoFromData(const QVariant data); 
-
-        explicit MapModel(QObject *parent = 0);
-
-        int rowCount(const QModelIndex &parent = QModelIndex()) const;
-        QVariant data(const QModelIndex &index, int role) const;
-        int generatorCount() const;
         int missionCount() const;
 
 
@@ -80,9 +73,19 @@
 
 
     private:
-        QList<QMap<int, QVariant> > m_data;
-        int m_nGenerators;
         int m_nMissions;
+
+        QStandardItem * infoToItem(
+            const QIcon & icon,
+            const QString caption,
+            MapType type = Invalid,
+            QString name = "",
+            QString theme = "",
+            quint32 limit = 0,
+            QString scheme = "",
+            QString weapons = "") const;
 };
 
+Q_DECLARE_METATYPE(MapModel::MapInfo)
+
 #endif // HEDGEWARS_MAPMODEL_H
--- a/QTfrontend/ui/widget/mapContainer.cpp	Fri Apr 27 11:47:37 2012 +0200
+++ b/QTfrontend/ui/widget/mapContainer.cpp	Fri Apr 27 22:22:04 2012 +0200
@@ -69,6 +69,7 @@
     chooseMap = new QComboBox(mapWidget);
     chooseMap->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
     m_mapModel = DataManager::instance().mapModel();
+    chooseMap->setEditable(false);
     chooseMap->setModel(m_mapModel);
 
     // update model views after model changes (to e.g. re-adjust separators)
@@ -175,7 +176,6 @@
     setRandomTheme();
 
     chooseMap->setCurrentIndex(0);
-    m_mapInfo = MapModel::mapInfoFromData(chooseMap->itemData(0));
     mapChanged(0);
     connect(chooseMap, SIGNAL(activated(int)), this, SLOT(mapChanged(int)));
 
@@ -210,7 +210,8 @@
 
 void HWMapContainer::mapChanged(int index)
 {
-    m_mapInfo = MapModel::mapInfoFromData(chooseMap->itemData(chooseMap->currentIndex()));
+    Q_ASSERT(chooseMap->itemData(index, Qt::UserRole + 1).canConvert<MapModel::MapInfo>());
+    m_mapInfo = chooseMap->itemData(chooseMap->currentIndex(), Qt::UserRole + 1).value<MapModel::MapInfo>();
 
     switch(m_mapInfo.type)
     {
@@ -222,8 +223,6 @@
             cbTemplateFilter->show();
             maze_size_label->hide();
             cbMazeSize->hide();
-            emit mapChanged("+rnd+");
-            emit themeChanged(m_mapInfo.theme);
             break;
         case MapModel::GeneratedMaze:
             mapgen = MAPGEN_MAZE;
@@ -233,8 +232,6 @@
             cbTemplateFilter->hide();
             maze_size_label->show();
             cbMazeSize->show();
-            emit mapChanged("+maze+");
-            emit themeChanged(m_mapInfo.theme);
             break;
         case MapModel::HandDrawnMap:
             mapgen = MAPGEN_DRAWN;
@@ -244,8 +241,6 @@
             cbTemplateFilter->hide();
             maze_size_label->hide();
             cbMazeSize->hide();
-            emit mapChanged("+drawn+");
-            emit themeChanged(m_mapInfo.theme);
             break;
         default:
             mapgen = MAPGEN_MAP;
@@ -255,9 +250,11 @@
             cbTemplateFilter->hide();
             maze_size_label->hide();
             cbMazeSize->hide();
-            emit mapChanged(m_mapInfo.name);
     }
 
+    if (m_mapInfo.theme.isEmpty())
+        emit themeChanged(lvThemes->currentIndex().data().toString());
+    emit mapChanged(m_mapInfo.name);
     emit mapgenChanged(mapgen);
 }
 
@@ -303,20 +300,10 @@
 
 void HWMapContainer::themeSelected(const QModelIndex & current, const QModelIndex &)
 {
-    QString theme = current.data().toString();
-    QList<QVariant> mapInfo;
-    mapInfo.push_back(QString("+rnd+"));
-    mapInfo.push_back(theme);
-    mapInfo.push_back(18);
-    mapInfo.push_back(false);
-    chooseMap->setItemData(0, mapInfo);
-    mapInfo[0] = QString("+maze+");
-    chooseMap->setItemData(1, mapInfo);
-    mapInfo[0] = QString("+drawn+");
-    chooseMap->setItemData(2, mapInfo);
+    m_mapInfo.theme = current.data().toString();
 
     gbThemes->setIcon(qVariantValue<QIcon>(current.data(Qt::UserRole)));
-    emit themeChanged(theme);
+    emit themeChanged(m_mapInfo.theme);
 }
 
 QString HWMapContainer::getCurrentSeed() const
@@ -326,6 +313,7 @@
 
 QString HWMapContainer::getCurrentMap() const
 {
+    if(chooseMap->currentIndex() < MAPGEN_MAP) return QString();
     return(m_mapInfo.name);
 }
 
@@ -384,9 +372,13 @@
     int id = 0;
     for(int i = 0; i < chooseMap->count(); i++)
     {
-        MapModel::MapInfo mapInfo = MapModel::mapInfoFromData(chooseMap->itemData(i));
+        // skip separators
+        if (chooseMap->itemData(i, Qt::AccessibleDescriptionRole) == QLatin1String("separator"))
+            continue;
+        Q_ASSERT(chooseMap->itemData(i, Qt::UserRole + 1).canConvert<MapModel::MapInfo>());
+        MapModel::MapInfo mapInfo = chooseMap->itemData(i, Qt::UserRole + 1).value<MapModel::MapInfo>();
 
-        if (mapInfo.name == map) 
+        if (mapInfo.name == map)
         {
             id = i;
             break;
@@ -576,10 +568,12 @@
             break;
         default:
             QPixmap mapImage;
-            QFile tmpfile;
-            tmpfile.setFileName(cfgdir->absolutePath() + "/Data/Maps/" + m_mapInfo.name + "/preview.png");
-            if (!tmpfile.exists()) tmpfile.setFileName(datadir->absolutePath() + "/Maps/" + m_mapInfo.name + "/preview.png");
-            if(!mapImage.load(QFileInfo(tmpfile).absoluteFilePath()))
+            bool success = mapImage.load(
+                DataManager::instance().findFileForRead(
+                    "Maps/" + m_mapInfo.name + "/preview.png")
+            );
+
+            if(!success)
             {
                 imageButt->setIcon(QIcon());
                 return;
@@ -606,16 +600,6 @@
 {
     numMissions = m_mapModel->missionCount();
 
-    intSetMap(m_mapInfo.name);
-
-/*
-    int nGenMaps = m_mapModel->generatorCount();
-
-    // insert double separator after random maps/mazes/etc
-    chooseMap->insertSeparator(nGenMaps);
-    chooseMap->insertSeparator(nGenMaps);
-
-    // separator between missions and regular maps
-    chooseMap->insertSeparator(nGenMaps + m_mapModel->missionCount());
-*/
+    if (!m_mapInfo.name.isEmpty())
+        intSetMap(m_mapInfo.name);
 }