MapModel, various cleanups. TODO/FIXME: QComboBox separator not working with custom models
authorsheepluva
Fri, 27 Apr 2012 11:47:37 +0200
changeset 6938 217ed62e872c
parent 6937 7f77fa908a4e
child 6939 970389573788
MapModel, various cleanups. TODO/FIXME: QComboBox separator not working with custom models
QTfrontend/model/MapModel.cpp
QTfrontend/model/MapModel.h
QTfrontend/model/ThemeModel.cpp
QTfrontend/model/ThemeModel.h
QTfrontend/ui/widget/mapContainer.cpp
QTfrontend/ui/widget/mapContainer.h
QTfrontend/util/DataManager.cpp
QTfrontend/util/DataManager.h
project_files/hedgewars.pro
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/model/MapModel.cpp	Fri Apr 27 11:47:37 2012 +0200
@@ -0,0 +1,190 @@
+
+#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()
+{
+    beginResetModel();
+
+
+    DataManager & datamgr = DataManager::instance();
+
+    QStringList maps =
+        datamgr.entryList("Maps", QDir::AllDirs | QDir::NoDotAndDotDot);
+
+    m_data.clear();
+
+#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
+    m_data.reserve(maps.size());
+#endif
+
+    QMap<int, QVariant> tmp;
+    QList<QVariant> mapInfo;
+
+    // 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;
+
+
+    m_nMissions = 0;
+
+    QFile mapLuaFile;
+    QFile mapCfgFile;
+
+    foreach (QString map, maps)
+    {
+        mapCfgFile.setFileName(
+            datamgr.findFileForRead(QString("Maps/%1/map.cfg").arg(map)));
+        mapLuaFile.setFileName(
+            datamgr.findFileForRead(QString("Maps/%1/map.lua").arg(map)));
+
+        QMap<int, QVariant> dataset;
+
+
+        if (mapCfgFile.open(QFile::ReadOnly))
+        {
+            QString theme;
+            quint32 limit = 0;
+            QString scheme;
+            QString weapons;
+            QList<QVariant> mapInfo;
+            bool isMission = mapLuaFile.exists();
+            int 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);
+
+
+            if (scheme.isEmpty())
+                scheme = "locked";
+            scheme.replace("_", " ");
+
+            if (weapons.isEmpty())
+                weapons = "locked";
+            weapons.replace("_", " ");
+
+            mapInfo.push_back(scheme);
+            mapInfo.push_back(weapons);
+
+            if(isMission)
+            {
+                // TODO: icon
+                map = QComboBox::tr("Mission") + ": " + map;
+                m_nMissions++;
+            }
+
+            mapCfgFile.close();
+
+            // set name
+            dataset.insert(Qt::DisplayRole, map);
+
+            // TODO
+            // dataset.insert(Qt::DecorationRole, icon);
+
+            // set mapinfo
+            dataset.insert(Qt::UserRole, mapInfo);
+
+            if (isMission) // insert missions before regular maps
+                m_data.insert(m_nGenerators + m_nMissions, dataset);
+            else
+                m_data.append(dataset);
+        
+        }
+
+    }
+
+    endResetModel();
+}
+
+int MapModel::generatorCount() const
+{
+    return m_nGenerators;
+}
+
+int MapModel::missionCount() const
+{
+    return m_nMissions;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/model/MapModel.h	Fri Apr 27 11:47:37 2012 +0200
@@ -0,0 +1,88 @@
+/*
+ * 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 definition
+ */
+
+#ifndef HEDGEWARS_MAPMODEL_H
+#define HEDGEWARS_MAPMODEL_H
+
+#include <QAbstractListModel>
+#include <QStringList>
+#include <QTextStream>
+#include <QMap>
+#include <QIcon>
+#include <QComboBox>
+
+#include "DataManager.h"
+
+/**
+ * @brief A model listing available themes
+ *
+ * @author sheepluva
+ * @since 0.9.18
+ */
+class MapModel : public QAbstractListModel
+{
+        Q_OBJECT
+
+    public:
+        enum MapType {
+            Invalid,
+            GeneratedMap,
+            GeneratedMaze,
+            HandDrawnMap,
+            MissionMap,
+            StaticMap
+        };
+
+        struct MapInfo
+        {
+            MapType type;
+            QString name;
+            QString theme;
+            quint32 limit;
+            QString scheme;
+            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;
+
+
+    public slots:
+        /// reloads the maps from the DataManager
+        void loadMaps();
+
+
+    private:
+        QList<QMap<int, QVariant> > m_data;
+        int m_nGenerators;
+        int m_nMissions;
+};
+
+#endif // HEDGEWARS_MAPMODEL_H
--- a/QTfrontend/ui/widget/mapContainer.cpp	Thu Apr 26 16:15:37 2012 +0200
+++ b/QTfrontend/ui/widget/mapContainer.cpp	Fri Apr 27 11:47:37 2012 +0200
@@ -68,11 +68,12 @@
 
     chooseMap = new QComboBox(mapWidget);
     chooseMap->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+    m_mapModel = DataManager::instance().mapModel();
+    chooseMap->setModel(m_mapModel);
 
-    loadMapList();
-    connect(&DataManager::instance(), SIGNAL(updated()), this, SLOT(loadMapList()));
+    // update model views after model changes (to e.g. re-adjust separators)
+    connect(&DataManager::instance(), SIGNAL(updated()), this, SLOT(updateModelViews()));
 
-    connect(chooseMap, SIGNAL(activated(int)), this, SLOT(mapChanged(int)));
     mapLayout->addWidget(chooseMap, 1, 1);
 
     QLabel * lblMap = new QLabel(tr("Map"), mapWidget);
@@ -172,6 +173,13 @@
 
     setRandomSeed();
     setRandomTheme();
+
+    chooseMap->setCurrentIndex(0);
+    m_mapInfo = MapModel::mapInfoFromData(chooseMap->itemData(0));
+    mapChanged(0);
+    connect(chooseMap, SIGNAL(activated(int)), this, SLOT(mapChanged(int)));
+
+    updateModelViews();
 }
 
 void HWMapContainer::setImage(const QImage newImage)
@@ -202,9 +210,11 @@
 
 void HWMapContainer::mapChanged(int index)
 {
-    switch(index)
+    m_mapInfo = MapModel::mapInfoFromData(chooseMap->itemData(chooseMap->currentIndex()));
+
+    switch(m_mapInfo.type)
     {
-        case MAPGEN_REGULAR:
+        case MapModel::GeneratedMap:
             mapgen = MAPGEN_REGULAR;
             updatePreview();
             gbThemes->show();
@@ -213,9 +223,9 @@
             maze_size_label->hide();
             cbMazeSize->hide();
             emit mapChanged("+rnd+");
-            emit themeChanged(chooseMap->itemData(index).toList()[1].toString());
+            emit themeChanged(m_mapInfo.theme);
             break;
-        case MAPGEN_MAZE:
+        case MapModel::GeneratedMaze:
             mapgen = MAPGEN_MAZE;
             updatePreview();
             gbThemes->show();
@@ -224,9 +234,9 @@
             maze_size_label->show();
             cbMazeSize->show();
             emit mapChanged("+maze+");
-            emit themeChanged(chooseMap->itemData(index).toList()[1].toString());
+            emit themeChanged(m_mapInfo.theme);
             break;
-        case MAPGEN_DRAWN:
+        case MapModel::HandDrawnMap:
             mapgen = MAPGEN_DRAWN;
             updatePreview();
             gbThemes->show();
@@ -235,7 +245,7 @@
             maze_size_label->hide();
             cbMazeSize->hide();
             emit mapChanged("+drawn+");
-            emit themeChanged(chooseMap->itemData(index).toList()[1].toString());
+            emit themeChanged(m_mapInfo.theme);
             break;
         default:
             mapgen = MAPGEN_MAP;
@@ -245,7 +255,7 @@
             cbTemplateFilter->hide();
             maze_size_label->hide();
             cbMazeSize->hide();
-            emit mapChanged(chooseMap->itemData(index).toList()[0].toString());
+            emit mapChanged(m_mapInfo.name);
     }
 
     emit mapgenChanged(mapgen);
@@ -316,19 +326,17 @@
 
 QString HWMapContainer::getCurrentMap() const
 {
-    if(chooseMap->currentIndex() < MAPGEN_MAP) return QString();
-    return chooseMap->itemData(chooseMap->currentIndex()).toList()[0].toString();
+    return(m_mapInfo.name);
 }
 
 QString HWMapContainer::getCurrentTheme() const
 {
-    return chooseMap->itemData(chooseMap->currentIndex()).toList()[1].toString();
+    return(m_mapInfo.theme);
 }
 
 bool HWMapContainer::getCurrentIsMission() const
 {
-    if(!chooseMap->currentIndex()) return false;
-    return chooseMap->itemData(chooseMap->currentIndex()).toList()[3].toBool();
+    return(m_mapInfo.type == MapModel::MissionMap);
 }
 
 int HWMapContainer::getCurrentHHLimit() const
@@ -338,12 +346,12 @@
 
 QString HWMapContainer::getCurrentScheme() const
 {
-    return chooseMap->itemData(chooseMap->currentIndex()).toList()[4].toString();
+    return(m_mapInfo.scheme);
 }
 
 QString HWMapContainer::getCurrentWeapons() const
 {
-    return chooseMap->itemData(chooseMap->currentIndex()).toList()[5].toString();
+    return(m_mapInfo.weapons);
 }
 
 quint32 HWMapContainer::getTemplateFilter() const
@@ -367,7 +375,7 @@
 void HWMapContainer::setSeed(const QString & seed)
 {
     intSetSeed(seed);
-    if (chooseMap->currentIndex() < MAPGEN_DRAWN)
+    if ((m_mapInfo.type == MapModel::GeneratedMap) || (m_mapInfo.type == MapModel::GeneratedMaze))
         updatePreview();
 }
 
@@ -375,11 +383,15 @@
 {
     int id = 0;
     for(int i = 0; i < chooseMap->count(); i++)
-        if(!chooseMap->itemData(i).isNull() && chooseMap->itemData(i).toList()[0].toString() == map)
+    {
+        MapModel::MapInfo mapInfo = MapModel::mapInfoFromData(chooseMap->itemData(i));
+
+        if (mapInfo.name == map) 
         {
             id = i;
             break;
         }
+    }
 
     if(id > 0)
     {
@@ -410,21 +422,23 @@
 void HWMapContainer::setRandomMap()
 {
     setRandomSeed();
-    switch(chooseMap->currentIndex())
+    switch(m_mapInfo.type)
     {
-        case MAPGEN_REGULAR:
-        case MAPGEN_MAZE:
+        case MapModel::GeneratedMap:
+        case MapModel::GeneratedMaze:
             setRandomTheme();
             break;
-        case MAPGEN_DRAWN:
+        case MapModel::HandDrawnMap:
             emit drawMapRequested();
             break;
-        default:
-            if(chooseMap->currentIndex() <= numMissions + MAPGEN_MAP + 1)
-                setRandomMission();
-            else
-                setRandomStatic();
+        case MapModel::MissionMap:
+            setRandomMission();
             break;
+        case MapModel::StaticMap:
+            setRandomStatic();
+            break;
+        case MapModel::Invalid:
+            Q_ASSERT(false);
     }
 }
 
@@ -444,11 +458,8 @@
 
 void HWMapContainer::setRandomSeed()
 {
-    m_seed = QUuid::createUuid().toString();
-    seedEdit->setText(m_seed);
+    setSeed(QUuid::createUuid().toString());
     emit seedChanged(m_seed);
-    if (chooseMap->currentIndex() < MAPGEN_MAP)
-        updatePreview();
 }
 
 void HWMapContainer::setRandomTheme()
@@ -552,31 +563,29 @@
 
 void HWMapContainer::updatePreview()
 {
-    int curIndex = chooseMap->currentIndex();
-
-    switch(curIndex)
+    switch(m_mapInfo.type)
     {
-        case MAPGEN_REGULAR:
+        case MapModel::GeneratedMap:
             askForGeneratedPreview();
             break;
-        case MAPGEN_MAZE:
+        case MapModel::GeneratedMaze:
             askForGeneratedPreview();
             break;
-        case MAPGEN_DRAWN:
+        case MapModel::HandDrawnMap:
             askForGeneratedPreview();
             break;
         default:
             QPixmap mapImage;
             QFile tmpfile;
-            tmpfile.setFileName(cfgdir->absolutePath() + "/Data/Maps/" + chooseMap->itemData(curIndex).toList()[0].toString() + "/preview.png");
-            if (!tmpfile.exists()) tmpfile.setFileName(datadir->absolutePath() + "/Maps/" + chooseMap->itemData(curIndex).toList()[0].toString() + "/preview.png");
+            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()))
             {
                 imageButt->setIcon(QIcon());
                 return;
             }
 
-            hhLimit = chooseMap->itemData(curIndex).toList()[2].toInt();
+            hhLimit = m_mapInfo.limit;
             addInfoToPreview(mapImage);
     }
 }
@@ -593,104 +602,20 @@
 }
 
 
-void HWMapContainer::loadMapList()
+void HWMapContainer::updateModelViews()
 {
-    // TODO: convert to model
-
-    // remember previous selection
-    QString selMap = getCurrentMap();
-
-    chooseMap->clear();
-
-    chooseMap->addItem(
-// FIXME - need real icons. Disabling until then
-//QIcon(":/res/mapRandom.png"),
-        QComboBox::tr("generated map..."));
-    chooseMap->addItem(
-// FIXME - need real icons. Disabling until then
-//QIcon(":/res/mapMaze.png"),
-        QComboBox::tr("generated maze..."));
-
-    chooseMap->addItem(QComboBox::tr("hand drawn map..."));
-
-    chooseMap->insertSeparator(chooseMap->count()); // separator between generators and missions
-    chooseMap->insertSeparator(chooseMap->count()); // separator between generators and missions
+    numMissions = m_mapModel->missionCount();
 
-    int missionindex = chooseMap->count();
-    numMissions = 0;
-    QFile mapLuaFile;
-    QFile mapCfgFile;
-
-    DataManager & dataMgr = DataManager::instance();
-
-    QStringList mapList = dataMgr.entryList(
-                              QString("Maps"),
-                              QDir::Dirs | QDir::NoDotAndDotDot
-                          );
+    intSetMap(m_mapInfo.name);
 
-    foreach (QString map, mapList)
-    {
-        mapCfgFile.setFileName(
-            dataMgr.findFileForRead(QString("Maps/%1/map.cfg").arg(map)));
-        mapLuaFile.setFileName(
-            dataMgr.findFileForRead(QString("Maps/%1/map.lua").arg(map)));
-
-        if (mapCfgFile.open(QFile::ReadOnly))
-        {
-            QString theme;
-            quint32 limit = 0;
-            QString scheme;
-            QString weapons;
-            QList<QVariant> mapInfo;
-            bool isMission = mapLuaFile.exists();
+/*
+    int nGenMaps = m_mapModel->generatorCount();
 
-            QTextStream input(&mapCfgFile);
-            input >> theme;
-            input >> limit;
-            input >> scheme;
-            input >> weapons;
-            mapInfo.push_back(map);
-            mapInfo.push_back(theme);
-            if (limit)
-                mapInfo.push_back(limit);
-            else
-                mapInfo.push_back(18);
-
-
-            mapInfo.push_back(isMission);
-
-            if (scheme.isEmpty())
-                scheme = "locked";
-            scheme.replace("_", " ");
-
-            if (weapons.isEmpty())
-                weapons = "locked";
-            weapons.replace("_", " ");
+    // insert double separator after random maps/mazes/etc
+    chooseMap->insertSeparator(nGenMaps);
+    chooseMap->insertSeparator(nGenMaps);
 
-            mapInfo.push_back(scheme);
-            mapInfo.push_back(weapons);
-
-            if(isMission)
-            {
-                chooseMap->insertItem(missionindex++,
-// FIXME - need real icons. Disabling until then
-//QIcon(":/res/mapMission.png"),
-                                      QComboBox::tr("Mission") + ": " + map, mapInfo);
-                numMissions++;
-            }
-            else
-                chooseMap->addItem(
-// FIXME - need real icons. Disabling until then
-//QIcon(":/res/mapCustom.png"),
-                    map, mapInfo);
-            mapCfgFile.close();
-        }
-    }
-
-    chooseMap->insertSeparator(missionindex); // separator between missions and maps
-
-    // if a map was selected already let's reselect it after reloading the map list
-    if (!selMap.isEmpty()) {
-        setMap(selMap);
-    }
+    // separator between missions and regular maps
+    chooseMap->insertSeparator(nGenMaps + m_mapModel->missionCount());
+*/
 }
--- a/QTfrontend/ui/widget/mapContainer.h	Thu Apr 26 16:15:37 2012 +0200
+++ b/QTfrontend/ui/widget/mapContainer.h	Fri Apr 27 11:47:37 2012 +0200
@@ -35,6 +35,7 @@
 class QPushButton;
 class IconedGroupBox;
 class QListView;
+class SeparatorPainter;
 
 class MapFileErrorException
 {
@@ -71,6 +72,7 @@
         void setMazeSize(int size);
         void setDrawnMapData(const QByteArray & ar);
         void setAllMapParameters(const QString & map, MapGenerator m, int mazesize, const QString & seed, int tmpl);
+        void updateModelViews();
 
     signals:
         void seedChanged(const QString & seed);
@@ -94,7 +96,6 @@
         void themeSelected(const QModelIndex & current, const QModelIndex &);
         void addInfoToPreview(QPixmap image);
         void seedEdited();
-        void loadMapList();
 
     protected:
         virtual void resizeEvent ( QResizeEvent * event );
@@ -103,6 +104,7 @@
         QGridLayout mainLayout;
         QPushButton* imageButt;
         QComboBox* chooseMap;
+        MapModel * m_mapModel;
         IconedGroupBox* gbThemes;
         QListView* lvThemes;
         ThemeModel * m_themeModel;
@@ -127,6 +129,8 @@
         void intSetTemplateFilter(int);
         void intSetMazeSize(int size);
         void updatePreview();
+
+        MapModel::MapInfo m_mapInfo;
 };
 
 #endif // _HWMAP_CONTAINER_INCLUDED
--- a/QTfrontend/util/DataManager.cpp	Thu Apr 26 16:15:37 2012 +0200
+++ b/QTfrontend/util/DataManager.cpp	Fri Apr 27 11:47:37 2012 +0200
@@ -40,6 +40,7 @@
 
     m_defaultData = new QDir(datadir->absolutePath());
 
+    m_mapModel = NULL;
     m_themeModel = NULL;
 }
 
@@ -117,6 +118,15 @@
     return "";
 }
 
+MapModel * DataManager::mapModel()
+{
+    if (m_mapModel == NULL) {
+        m_mapModel = new MapModel();
+        m_mapModel->loadMaps();
+    }
+    return m_mapModel;
+}
+
 ThemeModel * DataManager::themeModel()
 {
     if (m_themeModel == NULL) {
@@ -128,6 +138,7 @@
 
 void DataManager::reload()
 {
+    m_mapModel->loadMaps();
     m_themeModel->loadThemes();
     emit updated();
 }
--- a/QTfrontend/util/DataManager.h	Thu Apr 26 16:15:37 2012 +0200
+++ b/QTfrontend/util/DataManager.h	Fri Apr 27 11:47:37 2012 +0200
@@ -30,11 +30,13 @@
 
 #include <QStringList>
 
+#include "MapModel.h"
 #include "ThemeModel.h"
 
 class QDir;
 class QFile;
 class QStringList;
+class MapModel;
 class ThemeModel;
 
 /**
@@ -94,11 +96,20 @@
         QString findFileForWrite(const QString & relativeDataFilePath) const;
 
         /**
+         * @brief Returns pointer to a model for the available maps.
+         *
+         * The model is kept up to date automatically.
+         *
+         * @return map model pointer.
+         */
+        MapModel * mapModel();
+
+        /**
          * @brief Returns pointer to a model for the available themes.
          *
          * The model is kept up to date automatically.
          *
-         * @return theme model pointer
+         * @return theme model pointer.
          */
         ThemeModel * themeModel();
 
@@ -130,7 +141,8 @@
         QDir * m_defaultData; ///< directory of the installed data
         QDir * m_userData;    ///< directory of custom data in the user's directory
 
-        ThemeModel * m_themeModel; ///< themes model instance
+        MapModel * m_mapModel; ///< map model instance
+        ThemeModel * m_themeModel; ///< theme model instance
 };
 
 #endif // HEDGEWARS_DATAMANAGER_H
--- a/project_files/hedgewars.pro	Thu Apr 26 16:15:37 2012 +0200
+++ b/project_files/hedgewars.pro	Fri Apr 27 11:47:37 2012 +0200
@@ -23,6 +23,7 @@
 QT += webkit
 
 HEADERS += ../QTfrontend/model/ThemeModel.h \
+    ../QTfrontend/model/MapModel.h \
     ../QTfrontend/model/ammoSchemeModel.h \
     ../QTfrontend/model/netserverslist.h \
     ../QTfrontend/model/hats.h \
@@ -104,6 +105,7 @@
     ../QTfrontend/ui/dialog/input_password.h
 
 SOURCES += ../QTfrontend/model/ammoSchemeModel.cpp \
+    ../QTfrontend/model/MapModel.cpp \
     ../QTfrontend/model/ThemeModel.cpp \
     ../QTfrontend/model/hats.cpp \
     ../QTfrontend/model/netserverslist.cpp \