GCI2012: Improve Game Configuration Widget
- Refactored mapmodel+datamanager to have two separate map models for static and mission maps, and then three static MapInfos in MapModel for the three special maps (random, maze, drawn).
- Created theme selector dialog.
- Created seed view/edit dialog.
- Enlarged start icon on pagemultiplayer and pagenetgame, and added Start.png.
- Moved "Settings" button on pagemultiplayer and pagenetgame from middle of page to page footer.
- Added "load drawing" button to mapcontainer widget.
- Map preview is no longer the randomize button; The randomize functionality is now in a button of its own.
- Map preview no longer grays out (isn't disabled) when in slave mode.
- Seed is now viewable and copyable when in slave mode -- but not editable.
- You should now use the property master (isMaster() and setMaster()) on gamecfgwidget and mapcontainer instead of the enabled property. This is because some widgets (e.g. "view/edit seed" button and map preview) shouldn't be disabled, when all other widgets should be.
- Added mission map descriptions w/ locale support in INI format in mapname/desc.txt if applicable. Use '|' for line break.
--- a/QTfrontend/hedgewars.qrc Mon Jan 14 12:07:06 2013 +0400
+++ b/QTfrontend/hedgewars.qrc Mon Jan 14 11:19:59 2013 +0100
@@ -131,6 +131,7 @@
<file>res/StatsMostSelfDamage.png</file>
<file>res/StatsSelfKilled.png</file>
<file>res/StatsSkipped.png</file>
+ <file>res/Start.png</file>
<file>res/mapRandom.png</file>
<file>res/mapMaze.png</file>
<file>res/mapMissing.png</file>
--- a/QTfrontend/hwform.cpp Mon Jan 14 12:07:06 2013 +0400
+++ b/QTfrontend/hwform.cpp Mon Jan 14 11:19:59 2013 +0100
@@ -1714,7 +1714,7 @@
void HWForm::NetGameChangeStatus(bool isMaster)
{
- ui.pageNetGame->pGameCFG->setEnabled(isMaster);
+ ui.pageNetGame->pGameCFG->setMaster(isMaster);
ui.pageNetGame->pNetTeamsWidget->setInteractivity(isMaster);
if (isMaster)
@@ -1729,7 +1729,7 @@
ui.pageNetGame->restrictJoins->setChecked(false);
ui.pageNetGame->restrictTeamAdds->setChecked(false);
ui.pageNetGame->pGameCFG->GameSchemes->setModel(ammoSchemeModel);
- ui.pageNetGame->pGameCFG->setEnabled(true);
+ ui.pageNetGame->pGameCFG->setMaster(true);
ui.pageNetGame->pNetTeamsWidget->setInteractivity(true);
if (hwnet)
@@ -1757,7 +1757,7 @@
void HWForm::NetGameSlave()
{
- ui.pageNetGame->pGameCFG->setEnabled(false);
+ ui.pageNetGame->pGameCFG->setMaster(false);
ui.pageNetGame->pNetTeamsWidget->setInteractivity(false);
if (hwnet)
--- a/QTfrontend/model/MapModel.cpp Mon Jan 14 12:07:06 2013 +0400
+++ b/QTfrontend/model/MapModel.cpp Mon Jan 14 11:19:59 2013 +0100
@@ -22,9 +22,15 @@
*/
#include "MapModel.h"
+#include "hwapplication.h"
+#include <QSettings>
-void MapModel::loadMaps()
+MapModel::MapInfo MapModel::MapInfoRandom = {MapModel::GeneratedMap, "+rnd+", "", 0, "", "", ""};
+MapModel::MapInfo MapModel::MapInfoMaze = {MapModel::GeneratedMaze, "+maze+", "", 0, "", "", ""};
+MapModel::MapInfo MapModel::MapInfoDrawn = {MapModel::HandDrawnMap, "+drawn+", "", 0, "", "", ""};
+
+void MapModel::loadMaps(MapType maptype)
{
// this method resets the contents of this model (important to know for views).
beginResetModel();
@@ -39,19 +45,9 @@
// empty list, so that we can (re)fill it
QStandardItemModel::clear();
- QList<QStandardItem *> genMaps;
- QList<QStandardItem *> missionMaps;
- QList<QStandardItem *> staticMaps;
-
- // add generated/handdrawn maps to list
- // TODO: icons for these
-
- 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+"));
+ //QList<QStandardItem *> staticMaps;
+ //QList<QStandardItem *> missionMaps;
+ QList<QStandardItem *> mapList;
// only 2 map relate files are relevant:
// - the cfg file that contains the settings/info of the map
@@ -64,7 +60,7 @@
{
mapCfgFile.setFileName(QString("physfs://Maps/%1/map.cfg").arg(map));
mapLuaFile.setFileName(QString("physfs://Maps/%1/map.lua").arg(map));
-
+ QSettings descSettings(QString("physfs://Maps/%1/desc.txt").arg(map), QSettings::IniFormat);
if (mapCfgFile.open(QFile::ReadOnly))
{
@@ -73,25 +69,36 @@
quint32 limit = 0;
QString scheme;
QString weapons;
+ QString desc;
+
// if there is a lua file for this map, then it's a mission
bool isMission = mapLuaFile.exists();
- MapType type = isMission?MissionMap:StaticMap;
+ MapType type = isMission ? MissionMap : StaticMap;
+
+ // If we're supposed to ignore this type, continue
+ if (type != maptype) continue;
// load map info from file
QTextStream input(&mapCfgFile);
- input >> theme;
- input >> limit;
+ theme = input.readLine();
+ limit = input.readLine().toInt();
if (isMission) { // scheme and weapons are only relevant for missions
- input >> scheme;
- input >> weapons;
+ scheme = input.readLine();
+ weapons = input.readLine();
}
mapCfgFile.close();
+ // Load description (if applicable)
+ if (isMission)
+ {
+ QString locale = HWApplication::keyboardInputLocale().name();
+ desc = descSettings.value(locale, QString()).toString().replace("|", "\n");
+ }
+
// let's use some semi-sane hedgehog limit, rather than none
if (limit == 0)
limit = 18;
-
// the default scheme/weaponset for missions.
// if empty we assume the map sets these internally -> locked
if (isMission)
@@ -107,97 +114,54 @@
weapons.replace("_", " ");
}
- // add a mission caption prefix to missions
- if (isMission)
- {
- // TODO: icon
- caption = QComboBox::tr("Mission") + ": " + map;
- }
- else
- caption = map;
+ // caption
+ caption = map;
// we know everything there is about the map, let's get am item for it
- QStandardItem * item = infoToItem(
- QIcon(), caption, type, map, theme, limit, scheme, weapons);
+ QStandardItem * item = MapModel::infoToItem(
+ QIcon(), caption, type, map, theme, limit, scheme, weapons, desc);
// append item to the list
- if (isMission)
- missionMaps.append(item);
- else
- staticMaps.append(item);
-
+ mapList.append(item);
}
}
-
- // define a separator item
- QStandardItem separator("---");
- separator.setData(QLatin1String("separator"), Qt::AccessibleDescriptionRole);
- separator.setFlags(separator.flags() & ~( Qt::ItemIsEnabled | Qt::ItemIsSelectable ) );
-
- // create list:
- // generated+handdrawn maps, 2 saperators, missions, 1 separator, static maps
- QList<QStandardItem * > items;
- items.append(genMaps);
- items.append(separator.clone());
- items.append(separator.clone());
- items.append(missionMaps);
- items.append(separator.clone());
- items.append(staticMaps);
-
-
- // create row-index lookup table
+ // Create column-index lookup table
m_mapIndexes.clear();
- int count = items.size();
+ int count = mapList.size();
for (int i = 0; i < count; i++)
{
- QStandardItem * si = items.at(i);
+ QStandardItem * si = mapList.at(i);
QVariant v = si->data(Qt::UserRole + 1);
if (v.canConvert<MapInfo>())
m_mapIndexes.insert(v.value<MapInfo>().name, i);
}
-
- // store start-index and count of relevant types
-
- m_typeLoc.insert(GeneratedMap, QPair<int,int>(0, 1));
- m_typeLoc.insert(GeneratedMaze, QPair<int,int>(1, 1));
- m_typeLoc.insert(HandDrawnMap, QPair<int,int>(2, 1));
- // mission maps
- int startIdx = genMaps.size() + 2; // start after genMaps and 2 separators
- count = missionMaps.size();
- m_typeLoc.insert(MissionMap, QPair<int,int>(startIdx, count));
- // static maps
- startIdx += count + 1; // start after missions and 2 separators
- count = staticMaps.size();
- m_typeLoc.insert(StaticMap, QPair<int,int>(startIdx, count));
-
- // store list contents in the item model
- QStandardItemModel::appendColumn(items);
-
+ QStandardItemModel::appendColumn(mapList);
endResetModel();
}
-
-int MapModel::randomMap(MapType type) const
+bool MapModel::mapExists(const QString & map) const
{
- // return a random index for this type or -1 if none available
- QPair<int,int> loc = m_typeLoc.value(type, QPair<int,int>(-1,0));
-
- int startIdx = loc.first;
- int count = loc.second;
-
- if (count < 1)
- return -1;
- else
- return startIdx + (rand() % count);
+ return findMap(map) >= 0;
}
+int MapModel::findMap(const QString & map) const
+{
+ return m_mapIndexes.value(map, -1);
+}
+
+QStandardItem * MapModel::getMap(const QString & map)
+{
+ int loc = findMap(map);
+ if (loc < 0) return NULL;
+ return item(loc);
+}
QStandardItem * MapModel::infoToItem(
const QIcon & icon,
@@ -207,8 +171,8 @@
QString theme,
quint32 limit,
QString scheme,
- QString weapons)
-const
+ QString weapons,
+ QString desc)
{
QStandardItem * item = new QStandardItem(icon, caption);
MapInfo mapInfo;
@@ -220,17 +184,10 @@
mapInfo.limit = limit;
mapInfo.scheme = scheme;
mapInfo.weapons = weapons;
-
+ mapInfo.desc = desc.isEmpty() ? tr("No description available.") : desc;
qvar.setValue(mapInfo);
item->setData(qvar, Qt::UserRole + 1);
return item;
}
-
-
-int MapModel::indexOf(const QString & map) const
-{
- return m_mapIndexes.value(map, -1);
-}
-
--- a/QTfrontend/model/MapModel.h Mon Jan 14 12:07:06 2013 +0400
+++ b/QTfrontend/model/MapModel.h Mon Jan 14 11:19:59 2013 +0100
@@ -63,32 +63,49 @@
quint32 limit; ///< The maximum allowed number of hedgehogs.
QString scheme; ///< Default scheme name or "locked", for mission-maps.
QString weapons; ///< Default weaponset name or "locked", for missions-maps.
+ QString desc; ///< The brief 1-2 sentence description of the mission, for mission-maps.
};
/**
- * @brief Returns the row-index of the given map.
- * @param map map of which to get the row-index of.
- * @return row-index of map or -1 if not available.
+ * @brief Searches maps in model to find out if one exists
+ * @param map map of which to check existence
+ * @return true if it exists
*/
- int indexOf(const QString & map) const;
+ bool mapExists(const QString & map) const;
+
+ /**
+ * @brief Finds a map index (column, row) for a map name
+ * @param map map of which to find index+column
+ * @return QPair<int, int> with column, index, or (-1, -1) if map not found
+ */
+ //QPair<int, int> findMap(const QString & map) const;
/**
- * @brief Returns the row-index of a random map with a specified type.
- * @param type desired type of map.
- * @return row-index of a map with the desired type, -1 if none found.
+ * @brief Finds a map index for a map name
+ * @param map map of which to find index
+ * @return int of index, or -1 if map not found
*/
- int randomMap(MapType type) const;
+ int findMap(const QString & map) const;
+
+ /**
+ * @brief Finds and returns a map item for a map name
+ * @param map map
+ * @return QStandardItem of map, or NULL if map not found
+ */
+ QStandardItem * getMap(const QString & map);
+
+ // Static MapInfos for drawn and generated maps
+ static MapInfo MapInfoRandom, MapInfoMaze, MapInfoDrawn;
public slots:
/// Reloads the maps using the DataManager.
- void loadMaps();
+ /// Accepts two map types: StaticMap or MissionMap.
+ void loadMaps(MapType maptype);
private:
- /// start-index and map count for each map-type.
- QMap<MapType, QPair<int,int> > m_typeLoc;
-
- /// map index lookup table
+ /// map index lookup table. QPair<int, int> contains: <column, index>
+ //QHash<QString, QPair<int, int> > m_mapIndexes;
QHash<QString, int> m_mapIndexes;
/**
@@ -102,9 +119,10 @@
* @param limit the hedgehog limit of the map.
* @param scheme mission map: default scheme name or "locked".
* @param weapons mission map: default weaponset name or "locked".
+ * @param desc mission map: description of mission.
* @return pointer to item representing the map info: at Qt::UserRole + 1.
*/
- QStandardItem * infoToItem(
+ static QStandardItem * infoToItem(
const QIcon & icon,
const QString caption,
MapType type = Invalid,
@@ -112,7 +130,8 @@
QString theme = "",
quint32 limit = 0,
QString scheme = "",
- QString weapons = "") const;
+ QString weapons = "",
+ QString desc = "");
};
Q_DECLARE_METATYPE(MapModel::MapInfo)
--- a/QTfrontend/model/ThemeModel.cpp Mon Jan 14 12:07:06 2013 +0400
+++ b/QTfrontend/model/ThemeModel.cpp Mon Jan 14 11:19:59 2013 +0100
@@ -73,11 +73,16 @@
QMap<int, QVariant> dataset;
+ // set icon path
+ dataset.insert(Qt::UserRole + 1, iconpath);
+
// set name
dataset.insert(Qt::DisplayRole, theme);
// load and set icon
- QIcon icon(iconpath);
+ QIcon icon;
+ icon.addPixmap(QPixmap(iconpath), QIcon::Normal);
+ icon.addPixmap(QPixmap(iconpath), QIcon::Disabled);
dataset.insert(Qt::DecorationRole, icon);
--- a/QTfrontend/model/roomslistmodel.cpp Mon Jan 14 12:07:06 2013 +0400
+++ b/QTfrontend/model/roomslistmodel.cpp Mon Jan 14 11:19:59 2013 +0100
@@ -43,7 +43,8 @@
<< tr("Rules")
<< tr("Weapons");
- m_mapModel = DataManager::instance().mapModel();
+ m_staticMapModel = DataManager::instance().staticMapModel();
+ m_missionMapModel = DataManager::instance().missionMapModel();
}
@@ -134,7 +135,8 @@
}
// prefix ? if map not available
- if ((m_mapModel->indexOf(content) < 0))
+ if (!m_staticMapModel->mapExists(content) &&
+ !m_missionMapModel->mapExists(content))
return QString ("? %1").arg(content);
}
@@ -144,10 +146,14 @@
// dye map names red if map not available
if (role == Qt::ForegroundRole)
{
- if ((m_mapModel->indexOf(content) < 0))
+ if (content == "+rnd+" ||
+ content == "+maze+" ||
+ content == "+drawn+" ||
+ m_staticMapModel->mapExists(content) ||
+ m_missionMapModel->mapExists(content))
+ return QVariant();
+ else
return QBrush(QColor("darkred"));
- else
- return QVariant();
}
if (role == Qt::TextAlignmentRole)
--- a/QTfrontend/model/roomslistmodel.h Mon Jan 14 12:07:06 2013 +0400
+++ b/QTfrontend/model/roomslistmodel.h Mon Jan 14 11:19:59 2013 +0100
@@ -64,7 +64,8 @@
const int c_nColumns;
QList<QStringList> m_data;
QStringList m_headerData;
- MapModel * m_mapModel;
+ MapModel * m_staticMapModel;
+ MapModel * m_missionMapModel;
QStringList roomInfo2RoomRecord(const QStringList & info);
};
Binary file QTfrontend/res/Start.png has changed
--- a/QTfrontend/res/css/qt.css Mon Jan 14 12:07:06 2013 +0400
+++ b/QTfrontend/res/css/qt.css Mon Jan 14 11:19:59 2013 +0100
@@ -45,7 +45,7 @@
QTextBrowser, QSpinBox, QToolBox, QComboBox, QPlainTextEdit,
QComboBox QAbstractItemView, IconedGroupBox,
.QGroupBox, GameCFGWidget, TeamSelWidget, SelWeaponWidget,
-QTabWidget::pane, QTabBar::tab {
+QTabWidget::pane, QTabBar::tab, #mapPreview {
border: solid;
border-width: 3px;
border-color: #ffcc00;
@@ -56,8 +56,20 @@
border-color: yellow;
}
+QToolButton {
+background-color: #11084A;
+}
+
+QToolButton:hover {
+background-color: #150A61;
+}
+
+QToolButton:pressed {
+background-color: #100744;
+}
+
QLineEdit, QListWidget, QListView, QTableView, QTextBrowser,
-QSpinBox, QToolBox, QPlainTextEdit {
+QSpinBox, QToolBox, QPlainTextEdit, QToolButton, #mapPreview {
border-radius: 10px;
}
@@ -97,7 +109,7 @@
background-color: rgba(18, 42, 5, 70%);
}
-QPushButton:pressed{
+QPushButton:pressed, QToolButton:pressed {
border-color: white;
}
--- a/QTfrontend/ui/page/AbstractPage.cpp Mon Jan 14 12:07:06 2013 +0400
+++ b/QTfrontend/ui/page/AbstractPage.cpp Mon Jan 14 11:19:59 2013 +0100
@@ -41,9 +41,10 @@
QGridLayout * pageLayout = new QGridLayout(this);
// stretch grid space for body and footer
- pageLayout->setColumnStretch(0,1);
- pageLayout->setColumnStretch(1,2);
+ pageLayout->setColumnStretch(0,0);
+ pageLayout->setColumnStretch(1,0);
pageLayout->setColumnStretch(2,1);
+ pageLayout->setColumnStretch(3,0);
pageLayout->setRowStretch(0,1);
pageLayout->setRowStretch(1,0);
@@ -53,7 +54,12 @@
pageLayout->addWidget(btnBack, 1, 0, 1, 1, Qt::AlignLeft | Qt::AlignBottom);
// add body layout as defined by the subclass
- pageLayout->addLayout(bodyLayoutDefinition(), 0, 0, 1, 3);
+ pageLayout->addLayout(bodyLayoutDefinition(), 0, 0, 1, 4);
+
+ // add left footer layout
+ QLayout * flld = footerLayoutLeftDefinition();
+ if (flld != NULL)
+ pageLayout->addLayout(flld, 1, 1);
descLabel = new QLabel();
descLabel->setAlignment(Qt::AlignCenter);
@@ -61,12 +67,12 @@
descLabel->setOpenExternalLinks(true);
descLabel->setFixedHeight(50);
descLabel->setStyleSheet("font-size: 16px");
- pageLayout->addWidget(descLabel, 1, 1);
+ pageLayout->addWidget(descLabel, 1, 2);
// add footer layout
QLayout * fld = footerLayoutDefinition();
if (fld != NULL)
- pageLayout->addLayout(fld, 1, 2);
+ pageLayout->addLayout(fld, 1, 3);
// connect signals
connect(btnBack, SIGNAL(clicked()), this, SIGNAL(goBack()));
--- a/QTfrontend/ui/page/AbstractPage.h Mon Jan 14 12:07:06 2013 +0400
+++ b/QTfrontend/ui/page/AbstractPage.h Mon Jan 14 11:19:59 2013 +0100
@@ -121,6 +121,17 @@
* @brief Used during page construction.
* You can implement this method in your subclass.
*
+ * Use it to define layout (not behavior) of the page's footer to the left of the help text.
+ */
+ virtual QLayout * footerLayoutLeftDefinition()
+ {
+ return NULL;
+ };
+
+ /**
+ * @brief Used during page construction.
+ * You can implement this method in your subclass.
+ *
* This is a good place to connect signals within your page in order
* to get the desired page behavior.<br />
* Keep in mind not to expose twidgets as public!
--- a/QTfrontend/ui/page/pagemultiplayer.cpp Mon Jan 14 12:07:06 2013 +0400
+++ b/QTfrontend/ui/page/pagemultiplayer.cpp Mon Jan 14 11:19:59 2013 +0100
@@ -36,10 +36,6 @@
gameCFG = new GameCFGWidget(this);
pageLayout->addWidget(gameCFG, 0, 0, 1, 2);
- btnSetup = new QPushButton(this);
- btnSetup->setText(QPushButton::tr("Setup"));
- pageLayout->addWidget(btnSetup, 1, 0, 1, 2);
-
pageLayout->setRowStretch(2, 1);
teamsSelect = new TeamSelWidget(this);
@@ -48,12 +44,30 @@
return pageLayout;
}
+QLayout * PageMultiplayer::footerLayoutLeftDefinition()
+{
+ QHBoxLayout * bottomLeftLayout = new QHBoxLayout();
+
+ btnSetup = addButton(":/res/Settings.png", bottomLeftLayout, 0, true);
+ btnSetup->setWhatsThis(tr("Edit game preferences"));
+
+ return bottomLeftLayout;
+}
+
QLayout * PageMultiplayer::footerLayoutDefinition()
{
QHBoxLayout * footerLayout = new QHBoxLayout();
- BtnStartMPGame = formattedButton(tr("Start"));
- BtnStartMPGame->setMinimumWidth(180);
+ const QIcon& lp = QIcon(":/res/Start.png");
+ QSize sz = lp.actualSize(QSize(65535, 65535));
+ BtnStartMPGame = new QPushButton();
+ BtnStartMPGame->setText(tr("Start"));
+ BtnStartMPGame->setMinimumWidth(sz.width() + 60);
+ BtnStartMPGame->setIcon(lp);
+ BtnStartMPGame->setFixedHeight(50);
+ BtnStartMPGame->setIconSize(sz);
+ BtnStartMPGame->setFlat(true);
+ BtnStartMPGame->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
footerLayout->addStretch();
footerLayout->addWidget(BtnStartMPGame);
--- a/QTfrontend/ui/page/pagemultiplayer.h Mon Jan 14 12:07:06 2013 +0400
+++ b/QTfrontend/ui/page/pagemultiplayer.h Mon Jan 14 11:19:59 2013 +0100
@@ -41,6 +41,7 @@
private:
QLayout * bodyLayoutDefinition();
QLayout * footerLayoutDefinition();
+ QLayout * footerLayoutLeftDefinition();
void connectSignals();
QPushButton * btnSetup;
--- a/QTfrontend/ui/page/pagenetgame.cpp Mon Jan 14 12:07:06 2013 +0400
+++ b/QTfrontend/ui/page/pagenetgame.cpp Mon Jan 14 11:19:59 2013 +0100
@@ -40,24 +40,31 @@
chatWidget = new HWChatWidget(this, true);
chatWidget->setShowFollow(false); // don't show follow in nicks' context menus
chatWidget->setIgnoreListKick(true); // kick ignored players automatically
- pageLayout->addWidget(chatWidget, 2, 0, 1, 2);
- pageLayout->setRowStretch(1, 100);
- pageLayout->setRowStretch(2, 100);
+ pageLayout->addWidget(chatWidget, 1, 0, 1, 2);
+ pageLayout->setRowStretch(0, 0);
+ pageLayout->setRowStretch(1, 0);
pGameCFG = new GameCFGWidget(this);
pageLayout->addWidget(pGameCFG, 0, 0);
- btnSetup = new QPushButton(this);
- btnSetup->setText(QPushButton::tr("Setup"));
- pageLayout->addWidget(btnSetup, 1, 0);
-
pNetTeamsWidget = new TeamSelWidget(this);
pNetTeamsWidget->setAcceptOuter(true);
- pageLayout->addWidget(pNetTeamsWidget, 0, 1, 2, 1);
+ pNetTeamsWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
+ pageLayout->addWidget(pNetTeamsWidget, 0, 1, 1, 1);
return pageLayout;
}
+QLayout * PageNetGame::footerLayoutLeftDefinition()
+{
+ QHBoxLayout * bottomLeftLayout = new QHBoxLayout();
+
+ btnSetup = addButton(":/res/Settings.png", bottomLeftLayout, 0, true);
+ btnSetup->setWhatsThis(tr("Edit game preferences"));
+
+ return bottomLeftLayout;
+}
+
QLayout * PageNetGame::footerLayoutDefinition()
{
QHBoxLayout * bottomLayout = new QHBoxLayout;
@@ -84,7 +91,17 @@
BtnMaster = addButton(tr("Control"), bottomLayout, 3);
bottomLayout->insertStretch(3, 100);
- BtnStart = addButton(QAction::tr("Start"), bottomLayout, 3);
+ const QIcon& lp = QIcon(":/res/Start.png");
+ QSize sz = lp.actualSize(QSize(65535, 65535));
+ BtnStart = new QPushButton();
+ BtnStart->setText(tr("Start"));
+ BtnStart->setMinimumWidth(sz.width() + 60);
+ BtnStart->setIcon(lp);
+ BtnStart->setFixedHeight(50);
+ BtnStart->setIconSize(sz);
+ BtnStart->setFlat(true);
+ BtnStart->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ bottomLayout->addWidget(BtnStart);
return bottomLayout;
}
--- a/QTfrontend/ui/page/pagenetgame.h Mon Jan 14 12:07:06 2013 +0400
+++ b/QTfrontend/ui/page/pagenetgame.h Mon Jan 14 11:19:59 2013 +0100
@@ -70,6 +70,7 @@
private:
QLayout * bodyLayoutDefinition();
QLayout * footerLayoutDefinition();
+ QLayout * footerLayoutLeftDefinition();
void connectSignals();
HistoryLineEdit * leRoomName;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/flowlayout.cpp Mon Jan 14 11:19:59 2013 +0100
@@ -0,0 +1,190 @@
+ /****************************************************************************
+ **
+ ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ ** All rights reserved.
+ ** Contact: Nokia Corporation (qt-info@nokia.com)
+ **
+ ** This file is part of the examples of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:BSD$
+ ** You may use this file under the terms of the BSD license as follows:
+ **
+ ** "Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions are
+ ** met:
+ ** * Redistributions of source code must retain the above copyright
+ ** notice, this list of conditions and the following disclaimer.
+ ** * Redistributions in binary form must reproduce the above copyright
+ ** notice, this list of conditions and the following disclaimer in
+ ** the documentation and/or other materials provided with the
+ ** distribution.
+ ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+ ** the names of its contributors may be used to endorse or promote
+ ** products derived from this software without specific prior written
+ ** permission.
+ **
+ ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+ #include <QtGui>
+
+ #include "flowlayout.h"
+
+ FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing)
+ : QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
+ {
+ setContentsMargins(margin, margin, margin, margin);
+ }
+
+ FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing)
+ : m_hSpace(hSpacing), m_vSpace(vSpacing)
+ {
+ setContentsMargins(margin, margin, margin, margin);
+ }
+
+ FlowLayout::~FlowLayout()
+ {
+ QLayoutItem *item;
+ while ((item = takeAt(0)))
+ delete item;
+ }
+
+ void FlowLayout::addItem(QLayoutItem *item)
+ {
+ itemList.append(item);
+ }
+
+ int FlowLayout::horizontalSpacing() const
+ {
+ if (m_hSpace >= 0) {
+ return m_hSpace;
+ } else {
+ return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
+ }
+ }
+
+ int FlowLayout::verticalSpacing() const
+ {
+ if (m_vSpace >= 0) {
+ return m_vSpace;
+ } else {
+ return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
+ }
+ }
+
+ int FlowLayout::count() const
+ {
+ return itemList.size();
+ }
+
+ QLayoutItem *FlowLayout::itemAt(int index) const
+ {
+ return itemList.value(index);
+ }
+
+ QLayoutItem *FlowLayout::takeAt(int index)
+ {
+ if (index >= 0 && index < itemList.size())
+ return itemList.takeAt(index);
+ else
+ return 0;
+ }
+
+ Qt::Orientations FlowLayout::expandingDirections() const
+ {
+ return 0;
+ }
+
+ bool FlowLayout::hasHeightForWidth() const
+ {
+ return true;
+ }
+
+ int FlowLayout::heightForWidth(int width) const
+ {
+ int height = doLayout(QRect(0, 0, width, 0), true);
+ return height;
+ }
+
+ void FlowLayout::setGeometry(const QRect &rect)
+ {
+ QLayout::setGeometry(rect);
+ doLayout(rect, false);
+ }
+
+ QSize FlowLayout::sizeHint() const
+ {
+ return minimumSize();
+ }
+
+ QSize FlowLayout::minimumSize() const
+ {
+ QSize size;
+ QLayoutItem *item;
+ foreach (item, itemList)
+ size = size.expandedTo(item->minimumSize());
+
+ size += QSize(2*margin(), 2*margin());
+ return size;
+ }
+
+ int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
+ {
+ int left, top, right, bottom;
+ getContentsMargins(&left, &top, &right, &bottom);
+ QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
+ int x = effectiveRect.x();
+ int y = effectiveRect.y();
+ int lineHeight = 0;
+
+ QLayoutItem *item;
+ foreach (item, itemList) {
+ QWidget *wid = item->widget();
+ int spaceX = horizontalSpacing();
+ if (spaceX == -1)
+ spaceX = wid->style()->layoutSpacing(
+ QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
+ int spaceY = verticalSpacing();
+ if (spaceY == -1)
+ spaceY = wid->style()->layoutSpacing(
+ QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
+ int nextX = x + item->sizeHint().width() + spaceX;
+ if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
+ x = effectiveRect.x();
+ y = y + lineHeight + spaceY;
+ nextX = x + item->sizeHint().width() + spaceX;
+ lineHeight = 0;
+ }
+
+ if (!testOnly)
+ item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
+
+ x = nextX;
+ lineHeight = qMax(lineHeight, item->sizeHint().height());
+ }
+ return y + lineHeight - rect.y() + bottom;
+ }
+ int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
+ {
+ QObject *parent = this->parent();
+ if (!parent) {
+ return -1;
+ } else if (parent->isWidgetType()) {
+ QWidget *pw = static_cast<QWidget *>(parent);
+ return pw->style()->pixelMetric(pm, 0, pw);
+ } else {
+ return static_cast<QLayout *>(parent)->spacing();
+ }
+ }
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/flowlayout.h Mon Jan 14 11:19:59 2013 +0100
@@ -0,0 +1,77 @@
+ /****************************************************************************
+ **
+ ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ ** All rights reserved.
+ ** Contact: Nokia Corporation (qt-info@nokia.com)
+ **
+ ** This file is part of the examples of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:BSD$
+ ** You may use this file under the terms of the BSD license as follows:
+ **
+ ** "Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions are
+ ** met:
+ ** * Redistributions of source code must retain the above copyright
+ ** notice, this list of conditions and the following disclaimer.
+ ** * Redistributions in binary form must reproduce the above copyright
+ ** notice, this list of conditions and the following disclaimer in
+ ** the documentation and/or other materials provided with the
+ ** distribution.
+ ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+ ** the names of its contributors may be used to endorse or promote
+ ** products derived from this software without specific prior written
+ ** permission.
+ **
+ ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+ #ifndef FLOWLAYOUT_H
+ #define FLOWLAYOUT_H
+
+ #include <QLayout>
+ #include <QRect>
+ #include <QStyle>
+ #include <QWidgetItem>
+ class FlowLayout : public QLayout
+ {
+ public:
+ FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
+ FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
+ ~FlowLayout();
+
+ void addItem(QLayoutItem *item);
+ int horizontalSpacing() const;
+ int verticalSpacing() const;
+ Qt::Orientations expandingDirections() const;
+ bool hasHeightForWidth() const;
+ int heightForWidth(int) const;
+ int count() const;
+ QLayoutItem *itemAt(int index) const;
+ QSize minimumSize() const;
+ void setGeometry(const QRect &rect);
+ QSize sizeHint() const;
+ QLayoutItem *takeAt(int index);
+
+ private:
+ int doLayout(const QRect &rect, bool testOnly) const;
+ int smartSpacing(QStyle::PixelMetric pm) const;
+
+ QList<QLayoutItem *> itemList;
+ int m_hSpace;
+ int m_vSpace;
+ };
+
+ #endif
\ No newline at end of file
--- a/QTfrontend/ui/widget/gamecfgwidget.cpp Mon Jan 14 12:07:06 2013 +0400
+++ b/QTfrontend/ui/widget/gamecfgwidget.cpp Mon Jan 14 11:19:59 2013 +0100
@@ -25,6 +25,8 @@
#include <QMessageBox>
#include <QTableView>
#include <QPushButton>
+#include <QDebug>
+#include <QList>
#include "gamecfgwidget.h"
#include "igbox.h"
@@ -33,6 +35,7 @@
#include "ammoSchemeModel.h"
#include "proto.h"
#include "GameStyleModel.h"
+#include "themeprompt.h"
GameCFGWidget::GameCFGWidget(QWidget* parent) :
QGroupBox(parent)
@@ -40,13 +43,16 @@
, seedRegexp("\\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\}")
{
mainLayout.setMargin(0);
-// mainLayout.setSizeConstraint(QLayout::SetMinimumSize);
pMapContainer = new HWMapContainer(this);
- mainLayout.addWidget(pMapContainer, 0, 0);
+ mainLayout.addWidget(pMapContainer, 0, 0, Qt::AlignHCenter | Qt::AlignTop);
+ pMapContainer->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ pMapContainer->setFixedSize(460, 275);
IconedGroupBox *GBoxOptions = new IconedGroupBox(this);
- GBoxOptions->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+ m_childWidgets << GBoxOptions;
+ GBoxOptions->setFixedWidth(pMapContainer->width());
+ GBoxOptions->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
mainLayout.addWidget(GBoxOptions, 1, 0);
QGridLayout *GBoxOptionsLayout = new QGridLayout(GBoxOptions);
@@ -174,7 +180,7 @@
if (schemeData(18).toBool())
result |= 0x00080000; // ai survival
if (schemeData(19).toBool())
- result |= 0x00100000; // infinite attacks
+ result |= 0x00100000; // infinite attacks
if (schemeData(20).toBool())
result |= 0x00200000; // reset weaps
if (schemeData(21).toBool())
@@ -186,7 +192,7 @@
if (schemeData(24).toBool())
result |= 0x02000000; // tag team
if (schemeData(25).toBool())
- result |= 0x04000000; // bottom border
+ result |= 0x04000000; // bottom
return result;
}
@@ -235,6 +241,8 @@
bcfg << QString("e$template_filter %1").arg(pMapContainer->getTemplateFilter()).toUtf8();
bcfg << QString("e$mapgen %1").arg(mapgen).toUtf8();
+
+
switch (mapgen)
{
case MAPGEN_MAZE:
@@ -271,7 +279,7 @@
bool illegal = ammo.size() != cDefaultAmmoStore->size();
if (illegal)
{
- QMessageBox illegalMsg(this);
+ QMessageBox illegalMsg(parentWidget());
illegalMsg.setIcon(QMessageBox::Warning);
illegalMsg.setWindowTitle(QMessageBox::tr("Error"));
illegalMsg.setText(QMessageBox::tr("Cannot use the ammo '%1'!").arg(name));
@@ -325,10 +333,6 @@
if (param == "SEED")
{
pMapContainer->setSeed(value);
- if (!seedRegexp.exactMatch(value))
- {
- pMapContainer->seedEdit->setVisible(true);
- }
return;
}
if (param == "THEME")
@@ -377,8 +381,6 @@
if (param == "FULLMAPCONFIG")
{
QString seed = slValue[3];
- if (!seedRegexp.exactMatch(seed))
- pMapContainer->seedEdit->setVisible(true);
pMapContainer->setAllMapParameters(
slValue[0],
@@ -586,3 +588,19 @@
Scripts->setCurrentIndex(0);
}
}
+
+bool GameCFGWidget::isMaster()
+{
+ return m_master;
+}
+
+void GameCFGWidget::setMaster(bool master)
+{
+ if (master == m_master) return;
+ m_master = master;
+
+ pMapContainer->setMaster(master);
+
+ foreach (QWidget *widget, m_childWidgets)
+ widget->setEnabled(master);
+}
--- a/QTfrontend/ui/widget/gamecfgwidget.h Mon Jan 14 12:07:06 2013 +0400
+++ b/QTfrontend/ui/widget/gamecfgwidget.h Mon Jan 14 11:19:59 2013 +0100
@@ -36,6 +36,8 @@
{
Q_OBJECT
+ Q_PROPERTY(bool master READ isMaster WRITE setMaster)
+
public:
GameCFGWidget(QWidget* parent);
quint32 getGameFlags() const;
@@ -47,11 +49,13 @@
HWMapContainer* pMapContainer;
QTableView * tv;
QVariant schemeData(int column) const;
+ bool isMaster();
public slots:
void setParam(const QString & param, const QStringList & value);
void fullNetConfig();
void resendSchemeData();
+ void setMaster(bool master);
signals:
void paramChanged(const QString & param, const QStringList & value);
@@ -81,6 +85,8 @@
QString curNetAmmo;
QRegExp seedRegexp;
QString m_curScript;
+ bool m_master;
+ QList<QWidget *> m_childWidgets;
void setNetAmmo(const QString& name, const QString& ammo);
--- a/QTfrontend/ui/widget/mapContainer.cpp Mon Jan 14 12:07:06 2013 +0400
+++ b/QTfrontend/ui/widget/mapContainer.cpp Mon Jan 14 11:19:59 2013 +0100
@@ -30,13 +30,24 @@
#include <QIcon>
#include <QLineEdit>
#include <QStringListModel>
+#include <QListWidget>
+#include <QListWidgetItem>
+#include <QDebug>
+#include <QFile>
+#include <QFileDialog>
+#include <QInputDialog>
+#include <QMessageBox>
#include "hwconsts.h"
#include "mapContainer.h"
+#include "themeprompt.h"
+#include "seedprompt.h"
#include "igbox.h"
#include "HWApplication.h"
#include "ThemeModel.h"
+
+
HWMapContainer::HWMapContainer(QWidget * parent) :
QWidget(parent),
mainLayout(this),
@@ -47,6 +58,7 @@
hhSmall.load(":/res/hh_small.png");
hhLimit = 18;
templateFilter = 0;
+ m_master = true;
linearGrad = QLinearGradient(QPoint(128, 0), QPoint(128, 128));
linearGrad.setColorAt(1, QColor(0, 0, 192));
@@ -57,135 +69,192 @@
HWApplication::style()->pixelMetric(QStyle::PM_LayoutRightMargin),
HWApplication::style()->pixelMetric(QStyle::PM_LayoutBottomMargin));
- QWidget* mapWidget = new QWidget(this);
- mainLayout.addWidget(mapWidget, 0, 0, Qt::AlignHCenter);
-
- QGridLayout* mapLayout = new QGridLayout(mapWidget);
- mapLayout->setMargin(0);
+ m_staticMapModel = DataManager::instance().staticMapModel();
+ m_missionMapModel = DataManager::instance().missionMapModel();
+ m_themeModel = DataManager::instance().themeModel();
- imageButt = new QPushButton(mapWidget);
- imageButt->setObjectName("imageButt");
- imageButt->setFixedSize(256 + 6, 128 + 6);
- imageButt->setFlat(true);
- imageButt->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);//QSizePolicy::Minimum, QSizePolicy::Minimum);
- mapLayout->addWidget(imageButt, 0, 0, 1, 2);
- connect(imageButt, SIGNAL(clicked()), this, SLOT(setRandomMap()));
+ /* Layouts */
- chooseMap = new QComboBox(mapWidget);
- chooseMap->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
- m_mapModel = DataManager::instance().mapModel();
- chooseMap->setEditable(false);
- chooseMap->setModel(m_mapModel);
+ QHBoxLayout * typeLayout = new QHBoxLayout();
+ QHBoxLayout * seedLayout = new QHBoxLayout();
+ QHBoxLayout * twoColumnLayout = new QHBoxLayout();
+ QVBoxLayout * leftLayout = new QVBoxLayout();
+ QVBoxLayout * rightLayout = new QVBoxLayout();
+ twoColumnLayout->addLayout(leftLayout, 0);
+ twoColumnLayout->addStretch(1);
+ twoColumnLayout->addLayout(rightLayout, 0);
+ QVBoxLayout * drawnControls = new QVBoxLayout();
+ leftLayout->addLayout(typeLayout, 0);
+ rightLayout->addLayout(seedLayout, 0);
+
+ /* Map type combobox */
- mapLayout->addWidget(chooseMap, 1, 1);
+ typeLayout->setSpacing(10);
+ typeLayout->addWidget(new QLabel(tr("Map type:")), 0);
+ cType = new QComboBox(this);
+ typeLayout->addWidget(cType, 1);
+ cType->insertItem(0, tr("Image map"), MapModel::StaticMap);
+ cType->insertItem(1, tr("Mission map"), MapModel::MissionMap);
+ cType->insertItem(2, tr("Hand-drawn"), MapModel::HandDrawnMap);
+ cType->insertItem(3, tr("Randomly generated"), MapModel::GeneratedMap);
+ cType->insertItem(4, tr("Random maze"), MapModel::GeneratedMaze);
+ connect(cType, SIGNAL(currentIndexChanged(int)), this, SLOT(mapTypeChanged(int)));
+ m_childWidgets << cType;
- QLabel * lblMap = new QLabel(tr("Map"), mapWidget);
- mapLayout->addWidget(lblMap, 1, 0);
-
- lblFilter = new QLabel(tr("Filter"), mapWidget);
- mapLayout->addWidget(lblFilter, 2, 0);
+ /* Randomize button */
- cbTemplateFilter = new QComboBox(mapWidget);
- cbTemplateFilter->addItem(tr("All"), 0);
- cbTemplateFilter->addItem(tr("Small"), 1);
- cbTemplateFilter->addItem(tr("Medium"), 2);
- cbTemplateFilter->addItem(tr("Large"), 3);
- cbTemplateFilter->addItem(tr("Cavern"), 4);
- cbTemplateFilter->addItem(tr("Wacky"), 5);
- mapLayout->addWidget(cbTemplateFilter, 2, 1);
+ seedLayout->addStretch(1);
+ const QIcon& lp = QIcon(":/res/dice.png");
+ QSize sz = lp.actualSize(QSize(65535, 65535));
+ btnRandomize = new QPushButton();
+ btnRandomize->setText(tr("Random"));
+ btnRandomize->setIcon(lp);
+ btnRandomize->setFixedHeight(30);
+ btnRandomize->setIconSize(sz);
+ btnRandomize->setFlat(true);
+ btnRandomize->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ connect(btnRandomize, SIGNAL(clicked()), this, SLOT(setRandomMap()));
+ m_childWidgets << btnRandomize;
+ btnRandomize->setStyleSheet("padding: 5px;");
+ btnRandomize->setFixedHeight(cType->height());
+ seedLayout->addWidget(btnRandomize, 1);
- connect(cbTemplateFilter, SIGNAL(activated(int)), this, SLOT(setTemplateFilter(int)));
+ /* Seed button */
+ btnSeed = new QPushButton(parentWidget()->parentWidget());
+ btnSeed->setText(tr("Seed"));
+ btnSeed->setStyleSheet("padding: 5px;");
+ btnSeed->setFixedHeight(cType->height());
+ connect(btnSeed, SIGNAL(clicked()), this, SLOT(showSeedPrompt()));
+ seedLayout->addWidget(btnSeed, 0);
- maze_size_label = new QLabel(tr("Type"), mapWidget);
- mapLayout->addWidget(maze_size_label, 2, 0);
- maze_size_label->hide();
- cbMazeSize = new QComboBox(mapWidget);
- cbMazeSize->addItem(tr("Small tunnels"), 0);
- cbMazeSize->addItem(tr("Medium tunnels"), 1);
- cbMazeSize->addItem(tr("Large tunnels"), 2);
- cbMazeSize->addItem(tr("Small floating islands"), 3);
- cbMazeSize->addItem(tr("Medium floating islands"), 4);
- cbMazeSize->addItem(tr("Large floating islands"), 5);
- cbMazeSize->setCurrentIndex(1);
+ /* Map preview label */
+
+ QLabel * lblMapPreviewText = new QLabel(this);
+ lblMapPreviewText->setText(tr("Map preview:"));
+ leftLayout->addWidget(lblMapPreviewText, 0, Qt::AlignLeft);
+
+ /* Map Preview */
- mapLayout->addWidget(cbMazeSize, 2, 1);
- cbMazeSize->hide();
- connect(cbMazeSize, SIGNAL(activated(int)), this, SLOT(setMazeSize(int)));
+ mapPreview = new QLabel(this);
+ mapPreview->setObjectName("mapPreview");
+ mapPreview->setFixedSize(256, 128);
+ leftLayout->addWidget(mapPreview, 0);
+
+ /* Bottom-Left layout */
- gbThemes = new IconedGroupBox(mapWidget);
- gbThemes->setTitleTextPadding(80);
- gbThemes->setContentTopPadding(15);
- gbThemes->setTitle(tr("Themes"));
+ QVBoxLayout * bottomLeftLayout = new QVBoxLayout();
+ leftLayout->addLayout(bottomLeftLayout, 1);
+
+ /* Map list label */
+
+ lblMapList = new QLabel();
+ rightLayout->addWidget(lblMapList, 0);
+
+ /* Static maps list */
- //gbThemes->setStyleSheet("padding: 0px"); // doesn't work - stylesheet is set with icon
- mapLayout->addWidget(gbThemes, 0, 2, 3, 1);
- // disallow row to be collapsed (so it can't get ignored when Qt applies rowSpan of gbThemes)
- mapLayout->setRowMinimumHeight(2, 13);
- QVBoxLayout * gbTLayout = new QVBoxLayout(gbThemes);
- gbTLayout->setContentsMargins(0, 0, 0 ,0);
- gbTLayout->setSpacing(0);
- lvThemes = new QListView(mapWidget);
- lvThemes->setMinimumHeight(30);
- lvThemes->setFixedWidth(140);
- m_themeModel = DataManager::instance().themeModel();
- lvThemes->setModel(m_themeModel);
- lvThemes->setIconSize(QSize(16, 16));
- lvThemes->setEditTriggers(QListView::NoEditTriggers);
+ staticMapList = new QListView;
+ staticMapList->setModel(m_staticMapModel);
+ rightLayout->addWidget(staticMapList, 1);
+ staticMapList->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ m_childWidgets << staticMapList;
+ QItemSelectionModel * staticSelectionModel = staticMapList->selectionModel();
+ connect(staticSelectionModel,
+ SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)),
+ this,
+ SLOT(staticMapChanged(const QModelIndex &, const QModelIndex &)));
- connect(lvThemes->selectionModel(), SIGNAL(currentRowChanged( const QModelIndex &, const QModelIndex &)), this, SLOT(themeSelected( const QModelIndex &, const QModelIndex &)));
+ /* Mission maps list */
- // override default style to tighten up theme scroller
- lvThemes->setStyleSheet(QString(
- "QListView{"
- "border: solid;"
- "border-width: 0px;"
- "border-radius: 0px;"
- "border-color: transparent;"
- "background-color: #0d0544;"
- "color: #ffcc00;"
- "font: bold 13px;"
- "}"
- )
- );
+ missionMapList = new QListView;
+ missionMapList->setModel(m_missionMapModel);
+ missionMapList->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ rightLayout->addWidget(missionMapList, 1);
+ m_childWidgets << missionMapList;
+ QItemSelectionModel * missionSelectionModel = missionMapList->selectionModel();
+ connect(missionSelectionModel,
+ SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)),
+ this,
+ SLOT(missionMapChanged(const QModelIndex &, const QModelIndex &)));
+
+ /* Map load and edit buttons */
+
+ drawnControls->addStretch(1);
- gbTLayout->addWidget(lvThemes);
- lvThemes->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Minimum);
+ btnLoadMap = new QPushButton(tr("Load map drawing"));
+ btnLoadMap->setStyleSheet("padding: 20px;");
+ drawnControls->addWidget(btnLoadMap, 0);
+ m_childWidgets << btnLoadMap;
+ connect(btnLoadMap, SIGNAL(clicked()), this, SLOT(loadDrawing()));
+
+ btnEditMap = new QPushButton(tr("Edit map drawing"));
+ btnEditMap->setStyleSheet("padding: 20px;");
+ drawnControls->addWidget(btnEditMap, 0);
+ m_childWidgets << btnEditMap;
+ connect(btnEditMap, SIGNAL(clicked()), this, SIGNAL(drawMapRequested()));
+
+ drawnControls->addStretch(1);
+
+ rightLayout->addLayout(drawnControls);
+
+ /* Generator style list */
- mapLayout->setSizeConstraint(QLayout::SetFixedSize);
+ generationStyles = new QListWidget();
+ new QListWidgetItem(tr("All"), generationStyles);
+ new QListWidgetItem(tr("Small"), generationStyles);
+ new QListWidgetItem(tr("Medium"), generationStyles);
+ new QListWidgetItem(tr("Large"), generationStyles);
+ new QListWidgetItem(tr("Cavern"), generationStyles);
+ new QListWidgetItem(tr("Wacky"), generationStyles);
+ connect(generationStyles, SIGNAL(currentRowChanged(int)), this, SLOT(setTemplateFilter(int)));
+ m_childWidgets << generationStyles;
+ rightLayout->addWidget(generationStyles, 1);
+
+ /* Maze style list */
- QWidget* seedWidget = new QWidget(this);
- mainLayout.addWidget(seedWidget, 1, 0);
+ mazeStyles = new QListWidget();
+ new QListWidgetItem(tr("Small tunnels"), mazeStyles);
+ new QListWidgetItem(tr("Medium tunnels"), mazeStyles);
+ new QListWidgetItem(tr("Largetunnels"), mazeStyles);
+ new QListWidgetItem(tr("Small islands"), mazeStyles);
+ new QListWidgetItem(tr("Medium islands"), mazeStyles);
+ new QListWidgetItem(tr("Large islands"), mazeStyles);
+ connect(mazeStyles, SIGNAL(currentRowChanged(int)), this, SLOT(setMazeSize(int)));
+ m_childWidgets << mazeStyles;
+ rightLayout->addWidget(mazeStyles, 1);
- QGridLayout* seedLayout = new QGridLayout(seedWidget);
- seedLayout->setMargin(0);
+ /* Mission description */
- seedLabel = new QLabel(tr("Seed"), seedWidget);
- seedLayout->addWidget(seedLabel, 3, 0);
- seedEdit = new QLineEdit(seedWidget);
- seedEdit->setMaxLength(54);
- connect(seedEdit, SIGNAL(returnPressed()), this, SLOT(seedEdited()));
- seedLayout->addWidget(seedEdit, 3, 1);
- seedLayout->setColumnStretch(1, 5);
- seedSet = new QPushButton(seedWidget);
- seedSet->setText(QPushButton::tr("more"));
- connect(seedSet, SIGNAL(clicked()), this, SLOT(seedEdited()));
- seedLayout->setColumnStretch(2, 1);
- seedLayout->addWidget(seedSet, 3, 2);
+ lblDesc = new QLabel();
+ lblDesc->setWordWrap(true);
+ lblDesc->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ lblDesc->setAlignment(Qt::AlignTop | Qt::AlignLeft);
+ bottomLeftLayout->addWidget(lblDesc, 100);
+
+ /* Spacing above theme chooser */
+
+ bottomLeftLayout->addStretch(1);
+
+ /* Theme chooser */
- seedLabel->setVisible(false);
- seedEdit->setVisible(false);
+ btnTheme = new QPushButton();
+ connect(btnTheme, SIGNAL(clicked()), this, SLOT(showThemePrompt()));
+ m_childWidgets << btnTheme;
+ bottomLeftLayout->addWidget(btnTheme, 1);
- setRandomSeed();
- setRandomTheme();
+ /* Add everything to main layout */
+
+ mainLayout.addLayout(twoColumnLayout, 0);
- chooseMap->setCurrentIndex(0);
- mapChanged(0);
- // use signal "activated" rather than currentIndexChanged
- // because index is somtimes changed a few times in a row programmatically
- connect(chooseMap, SIGNAL(activated(int)), this, SLOT(mapChanged(int)));
+ /* Set defaults */
- // update model views after model changes (to e.g. re-adjust separators)
- connect(&DataManager::instance(), SIGNAL(updated()), this, SLOT(updateModelViews()));
+ setRandomTheme();
+ setRandomSeed();
+ setMazeSize(0);
+ setTemplateFilter(0);
+ staticMapChanged(m_staticMapModel->index(0, 0));
+ missionMapChanged(m_missionMapModel->index(0, 0));
+ updateTheme(m_themeModel->index(0, 0));
+ mapTypeChanged(0);
}
void HWMapContainer::setImage(const QImage newImage)
@@ -202,8 +271,9 @@
p.drawPixmap(QPoint(0, 0), px);
addInfoToPreview(pxres);
- //chooseMap->setCurrentIndex(mapgen);
pMap = 0;
+
+ cType->setEnabled(isMaster());
}
void HWMapContainer::setHHLimit(int newHHLimit)
@@ -211,70 +281,6 @@
hhLimit = newHHLimit;
}
-void HWMapContainer::mapChanged(int index)
-{
- if (chooseMap->currentIndex() != index)
- chooseMap->setCurrentIndex(index);
-
- if (index < 0)
- {
- m_mapInfo.type = MapModel::Invalid;
- updatePreview();
- return;
- }
-
- Q_ASSERT(chooseMap->itemData(index, Qt::UserRole + 1).canConvert<MapModel::MapInfo>());
- m_mapInfo = chooseMap->itemData(index, Qt::UserRole + 1).value<MapModel::MapInfo>();
- m_curMap = m_mapInfo.name;
-
- switch(m_mapInfo.type)
- {
- case MapModel::GeneratedMap:
- mapgen = MAPGEN_REGULAR;
- gbThemes->show();
- lblFilter->show();
- cbTemplateFilter->show();
- maze_size_label->hide();
- cbMazeSize->hide();
- break;
- case MapModel::GeneratedMaze:
- mapgen = MAPGEN_MAZE;
- gbThemes->show();
- lblFilter->hide();
- cbTemplateFilter->hide();
- maze_size_label->show();
- cbMazeSize->show();
- break;
- case MapModel::HandDrawnMap:
- mapgen = MAPGEN_DRAWN;
- gbThemes->show();
- lblFilter->hide();
- cbTemplateFilter->hide();
- maze_size_label->hide();
- cbMazeSize->hide();
- break;
- default:
- mapgen = MAPGEN_MAP;
- gbThemes->hide();
- lblFilter->hide();
- cbTemplateFilter->hide();
- maze_size_label->hide();
- cbMazeSize->hide();
- m_theme = m_mapInfo.theme;
- }
-
- // the map has no pre-defined theme, so let's use the selected one
- if (m_mapInfo.theme.isEmpty())
- {
- m_theme = lvThemes->currentIndex().data().toString();
- emit themeChanged(m_theme);
- }
-
- updatePreview();
- emit mapChanged(m_curMap);
- emit mapgenChanged(mapgen);
-}
-
// Should this add text to identify map size?
void HWMapContainer::addInfoToPreview(QPixmap image)
{
@@ -292,8 +298,7 @@
p.drawText(image.rect().width() - hhSmall.rect().width() - 14 - (hhLimit > 9 ? 10 : 0), 18, text);
p.drawPixmap(image.rect().width() - hhSmall.rect().width() - 5, 5, hhSmall.rect().width(), hhSmall.rect().height(), hhSmall);
- imageButt->setIcon(finalImage);
- imageButt->setIconSize(image.size());
+ mapPreview->setPixmap(finalImage);
}
void HWMapContainer::askForGeneratedPreview()
@@ -322,14 +327,8 @@
p.drawPixmap(QPoint(x, y), waitIcon);
addInfoToPreview(waitImage);
-}
-void HWMapContainer::themeSelected(const QModelIndex & current, const QModelIndex &)
-{
- m_theme = current.data().toString();
-
- gbThemes->setIcon(qVariantValue<QIcon>(current.data(Qt::UserRole)));
- emit themeChanged(m_theme);
+ cType->setEnabled(false);
}
QString HWMapContainer::getCurrentSeed() const
@@ -339,8 +338,14 @@
QString HWMapContainer::getCurrentMap() const
{
- if(chooseMap->currentIndex() < MAPGEN_MAP) return QString();
- return(m_curMap);
+ switch (m_mapInfo.type)
+ {
+ case MapModel::StaticMap:
+ case MapModel::MissionMap:
+ return m_curMap;
+ default:
+ return QString();
+ }
}
QString HWMapContainer::getCurrentTheme() const
@@ -370,20 +375,17 @@
quint32 HWMapContainer::getTemplateFilter() const
{
- return cbTemplateFilter->itemData(cbTemplateFilter->currentIndex()).toInt();
+ return generationStyles->currentRow();
}
void HWMapContainer::resizeEvent ( QResizeEvent * event )
{
Q_UNUSED(event);
- //imageButt->setIconSize(imageButt->size());
}
void HWMapContainer::intSetSeed(const QString & seed)
{
m_seed = seed;
- if (seed != seedEdit->text())
- seedEdit->setText(seed);
}
void HWMapContainer::setSeed(const QString & seed)
@@ -395,11 +397,29 @@
void HWMapContainer::intSetMap(const QString & map)
{
- m_curMap = map;
-
- int id = m_mapModel->indexOf(map);
-
- mapChanged(id);
+ if (map == "+rnd+")
+ {
+ changeMapType(MapModel::GeneratedMap);
+ }
+ else if (map == "+maze+")
+ {
+ changeMapType(MapModel::GeneratedMaze);
+ }
+ else if (map == "+drawn+")
+ {
+ changeMapType(MapModel::HandDrawnMap);
+ }
+ else if (m_staticMapModel->mapExists(map))
+ {
+ changeMapType(MapModel::StaticMap, m_staticMapModel->index(m_staticMapModel->findMap(map), 0));
+ }
+ else if (m_missionMapModel->mapExists(map))
+ {
+ changeMapType(MapModel::MissionMap, m_missionMapModel->index(m_missionMapModel->findMap(map), 0));
+ } else
+ {
+ qDebug() << "HWMapContainer::intSetMap: Map doesn't exist: " << map;
+ }
}
void HWMapContainer::setMap(const QString & map)
@@ -413,13 +433,11 @@
QModelIndexList mdl = m_themeModel->match(m_themeModel->index(0), Qt::DisplayRole, theme);
if(mdl.size())
- lvThemes->setCurrentIndex(mdl.at(0));
+ updateTheme(mdl.at(0));
}
void HWMapContainer::setRandomMap()
{
- int idx;
-
setRandomSeed();
switch(m_mapInfo.type)
{
@@ -427,17 +445,14 @@
case MapModel::GeneratedMaze:
setRandomTheme();
break;
- case MapModel::HandDrawnMap:
- emit drawMapRequested();
+ case MapModel::MissionMap:
+ missionMapChanged(m_missionMapModel->index(rand() % m_missionMapModel->rowCount(), 0));
break;
- case MapModel::MissionMap:
case MapModel::StaticMap:
- // get random map of same type
- idx = m_mapModel->randomMap(m_mapInfo.type);
- mapChanged(idx);
+ staticMapChanged(m_staticMapModel->index(rand() % m_staticMapModel->rowCount(), 0));
break;
- case MapModel::Invalid:
- mapChanged(0);
+ default:
+ break;
}
}
@@ -452,12 +467,12 @@
{
if(!m_themeModel->rowCount()) return;
quint32 themeNum = rand() % m_themeModel->rowCount();
- lvThemes->setCurrentIndex(m_themeModel->index(themeNum));
+ updateTheme(m_themeModel->index(themeNum));
}
void HWMapContainer::intSetTemplateFilter(int filter)
{
- cbTemplateFilter->setCurrentIndex(filter);
+ generationStyles->setCurrentRow(filter);
emit newTemplateFilter(filter);
}
@@ -475,12 +490,12 @@
int HWMapContainer::getMazeSize(void) const
{
- return cbMazeSize->currentIndex();
+ return mazeStyles->currentRow();
}
void HWMapContainer::intSetMazeSize(int size)
{
- cbMazeSize->setCurrentIndex(size);
+ mazeStyles->setCurrentRow(size);
emit mazeSizeChanged(size);
}
@@ -521,9 +536,6 @@
break;
}
- if(m != MAPGEN_MAP)
- chooseMap->setCurrentIndex(m);
-
emit mapgenChanged(m);
}
}
@@ -546,23 +558,10 @@
return drawMapScene.encode();
}
-void HWMapContainer::seedEdited()
+void HWMapContainer::setNewSeed(const QString & newSeed)
{
- if (seedLabel->isVisible() == false )
- {
- seedLabel->setVisible(true);
- seedEdit->setVisible(true);
- seedSet->setText(tr("Set"));
- return;
- }
-
- if (seedEdit->text().isEmpty())
- seedEdit->setText(m_seed);
- else
- {
- setSeed(seedEdit->text());
- emit seedChanged(seedEdit->text());
- }
+ setSeed(newSeed);
+ emit seedChanged(newSeed);
}
DrawMapScene * HWMapContainer::getDrawMapScene()
@@ -592,8 +591,7 @@
{
case MapModel::Invalid:
failIcon = QPixmap(":/res/btnDisabled.png");
- imageButt->setIcon(failIcon);
- imageButt->setIconSize(failIcon.size());
+ mapPreview->setPixmap(failIcon);
break;
case MapModel::GeneratedMap:
askForGeneratedPreview();
@@ -610,7 +608,7 @@
if(!success)
{
- imageButt->setIcon(QIcon());
+ mapPreview->setPixmap(QPixmap());
return;
}
@@ -638,13 +636,13 @@
{
QModelIndexList mdl = m_themeModel->match(m_themeModel->index(0), Qt::DisplayRole, m_theme);
if (mdl.size() > 0)
- lvThemes->setCurrentIndex(mdl.at(0));
+ updateTheme(mdl.at(0));
else
setRandomTheme();
}
// restore map selection
- if ((!m_curMap.isEmpty()) && (chooseMap->currentIndex() < 0))
+ if (!m_curMap.isEmpty())
intSetMap(m_curMap);
else
updatePreview();
@@ -656,3 +654,227 @@
if (map == pMap)
pMap = 0;
}
+
+void HWMapContainer::mapTypeChanged(int index)
+{
+ changeMapType((MapModel::MapType)cType->itemData(index).toInt());
+}
+
+void HWMapContainer::changeMapType(MapModel::MapType type, const QModelIndex & newMap)
+{
+ staticMapList->hide();
+ missionMapList->hide();
+ lblMapList->hide();
+ generationStyles->hide();
+ mazeStyles->hide();
+ lblDesc->hide();
+ btnTheme->hide();
+ btnLoadMap->hide();
+ btnEditMap->hide();
+ btnRandomize->hide();
+
+ switch (type)
+ {
+ case MapModel::GeneratedMap:
+ mapgen = MAPGEN_REGULAR;
+ setMapInfo(MapModel::MapInfoRandom);
+ lblMapList->setText(tr("Map size:"));
+ lblMapList->show();
+ generationStyles->show();
+ btnRandomize->show();
+ btnTheme->show();
+ break;
+ case MapModel::GeneratedMaze:
+ mapgen = MAPGEN_MAZE;
+ setMapInfo(MapModel::MapInfoMaze);
+ lblMapList->setText(tr("Maze style:"));
+ lblMapList->show();
+ mazeStyles->show();
+ btnRandomize->show();
+ btnTheme->show();
+ break;
+ case MapModel::HandDrawnMap:
+ mapgen = MAPGEN_DRAWN;
+ setMapInfo(MapModel::MapInfoDrawn);
+ btnTheme->show();
+ btnLoadMap->show();
+ btnEditMap->show();
+ break;
+ case MapModel::MissionMap:
+ mapgen = MAPGEN_MAP;
+ missionMapChanged(newMap.isValid() ? newMap : missionMapList->currentIndex());
+ lblMapList->setText(tr("Mission:"));
+ lblMapList->show();
+ missionMapList->show();
+ lblDesc->setText(m_mapInfo.desc);
+ lblDesc->show();
+ btnRandomize->show();
+ emit mapChanged(m_curMap);
+ break;
+ case MapModel::StaticMap:
+ mapgen = MAPGEN_MAP;
+ staticMapChanged(newMap.isValid() ? newMap : staticMapList->currentIndex());
+ lblMapList->setText(tr("Map:"));
+ lblMapList->show();
+ staticMapList->show();
+ btnRandomize->show();
+ emit mapChanged(m_curMap);
+ break;
+ default:
+ break;
+ }
+
+ // Update cType combobox
+ for (int i = 0; i < cType->count(); i++)
+ {
+ if ((MapModel::MapType)cType->itemData(i).toInt() == type)
+ {
+ cType->setCurrentIndex(i);
+ break;
+ }
+ }
+
+ emit mapgenChanged(mapgen);
+}
+
+void HWMapContainer::showThemePrompt()
+{
+ ThemePrompt prompt(this);
+ int theme = prompt.exec() - 1; // Since 0 means canceled, so all indexes are +1'd
+ if (theme < 0) return;
+
+ QModelIndex current = m_themeModel->index(theme, 0);
+ updateTheme(current);
+
+ emit themeChanged(m_theme);
+}
+
+void HWMapContainer::updateTheme(const QModelIndex & current)
+{
+ m_theme = selectedTheme = current.data().toString();
+ QIcon icon = qVariantValue<QIcon>(current.data(Qt::UserRole));
+ QSize iconSize = icon.actualSize(QSize(65535, 65535));
+ btnTheme->setFixedHeight(iconSize.height());
+ btnTheme->setIconSize(iconSize);
+ btnTheme->setIcon(icon);
+ btnTheme->setText(tr("Theme: ") + current.data(Qt::DisplayRole).toString());
+ emit themeChanged(m_theme);
+}
+
+void HWMapContainer::staticMapChanged(const QModelIndex & map, const QModelIndex & old)
+{
+ mapChanged(map, 0, old);
+}
+
+void HWMapContainer::missionMapChanged(const QModelIndex & map, const QModelIndex & old)
+{
+ mapChanged(map, 1, old);
+}
+
+// Type: 0 = static, 1 = mission
+void HWMapContainer::mapChanged(const QModelIndex & map, int type, const QModelIndex & old)
+{
+ QListView * mapList;
+
+ if (type == 0) mapList = staticMapList;
+ else if (type == 1) mapList = missionMapList;
+ else return;
+
+ // Make sure it is a valid index
+ if (!map.isValid())
+ {
+ if (old.isValid())
+ {
+ mapList->setCurrentIndex(old);
+ mapList->scrollTo(old);
+ }
+ else
+ {
+ m_mapInfo.type = MapModel::Invalid;
+ updatePreview();
+ }
+
+ return;
+ }
+
+ // If map changed, update list selection
+ if (mapList->currentIndex() != map)
+ {
+ mapList->setCurrentIndex(map);
+ mapList->scrollTo(map);
+ }
+
+ if (map.data(Qt::UserRole + 1).canConvert<MapModel::MapInfo>())
+ setMapInfo(map.data(Qt::UserRole + 1).value<MapModel::MapInfo>());
+ else
+ Q_ASSERT(false); // Houston, we have a problem.
+
+}
+
+void HWMapContainer::setMapInfo(MapModel::MapInfo mapInfo)
+{
+ m_mapInfo = mapInfo;
+ m_curMap = m_mapInfo.name;
+ m_theme = m_mapInfo.theme;
+
+ // the map has no pre-defined theme, so let's use the selected one
+ if (m_mapInfo.theme.isEmpty())
+ {
+ m_theme = selectedTheme;
+ emit themeChanged(m_theme);
+ }
+
+ lblDesc->setText(mapInfo.desc);
+
+ updatePreview();
+ emit mapChanged(m_curMap);
+}
+
+void HWMapContainer::loadDrawing()
+{
+
+
+ QString fileName = QFileDialog::getOpenFileName(NULL, tr("Load drawn map"), ".", tr("Drawn Maps") + " (*.hwmap);;" + tr("All files") + " (*)");
+
+ if(fileName.isEmpty()) return;
+
+
+
+ QFile f(fileName);
+
+ if(!f.open(QIODevice::ReadOnly))
+ {
+ QMessageBox errorMsg(parentWidget());
+ errorMsg.setIcon(QMessageBox::Warning);
+ errorMsg.setWindowTitle(QMessageBox::tr("File error"));
+ errorMsg.setText(QMessageBox::tr("Cannot open '%1' for reading").arg(fileName));
+ errorMsg.setWindowModality(Qt::WindowModal);
+ errorMsg.exec();
+ }
+ else
+ {
+ drawMapScene.decode(qUncompress(QByteArray::fromBase64(f.readAll())));
+ mapDrawingFinished();
+ }
+}
+
+void HWMapContainer::showSeedPrompt()
+{
+ SeedPrompt prompt(parentWidget()->parentWidget(), getCurrentSeed(), isMaster());
+ connect(&prompt, SIGNAL(seedSelected(const QString &)), this, SLOT(setNewSeed(const QString &)));
+ prompt.exec();
+}
+
+bool HWMapContainer::isMaster()
+{
+ return m_master;
+}
+
+void HWMapContainer::setMaster(bool master)
+{
+ if (master == m_master) return;
+ m_master = master;
+
+ foreach (QWidget *widget, m_childWidgets)
+ widget->setEnabled(master);
+}
--- a/QTfrontend/ui/widget/mapContainer.h Mon Jan 14 12:07:06 2013 +0400
+++ b/QTfrontend/ui/widget/mapContainer.h Mon Jan 14 11:19:59 2013 +0100
@@ -22,6 +22,7 @@
#include <QWidget>
#include <QGridLayout>
+#include <QVBoxLayout>
#include <QComboBox>
#include <QLabel>
#include <QByteArray>
@@ -37,6 +38,7 @@
class IconedGroupBox;
class QListView;
class SeparatorPainter;
+class QListWidget;
class MapFileErrorException
{
@@ -46,6 +48,8 @@
{
Q_OBJECT
+ Q_PROPERTY(bool master READ isMaster WRITE setMaster)
+
public:
HWMapContainer(QWidget * parent=0);
QString getCurrentSeed() const;
@@ -62,6 +66,7 @@
DrawMapScene * getDrawMapScene();
void mapDrawingFinished();
QLineEdit* seedEdit;
+ bool isMaster();
public slots:
void askForGeneratedPreview();
@@ -75,6 +80,7 @@
void setAllMapParameters(const QString & map, MapGenerator m, int mazesize, const QString & seed, int tmpl);
void updateModelViews();
void onPreviewMapDestroyed(QObject * map);
+ void setMaster(bool master);
signals:
void seedChanged(const QString & seed);
@@ -89,22 +95,28 @@
private slots:
void setImage(const QImage newImage);
void setHHLimit(int hhLimit);
- void mapChanged(int index);
void setRandomSeed();
void setRandomTheme();
void setRandomMap();
- void themeSelected(const QModelIndex & current, const QModelIndex &);
void addInfoToPreview(QPixmap image);
- void seedEdited();
+ void setNewSeed(const QString & newSeed);
+ void mapTypeChanged(int);
+ void showThemePrompt();
+ void updateTheme(const QModelIndex & current);
+ void staticMapChanged(const QModelIndex & map, const QModelIndex & old = QModelIndex());
+ void missionMapChanged(const QModelIndex & map, const QModelIndex & old = QModelIndex());
+ void loadDrawing();
+ void showSeedPrompt();
protected:
virtual void resizeEvent ( QResizeEvent * event );
private:
- QGridLayout mainLayout;
- QPushButton* imageButt;
+ QVBoxLayout mainLayout;
+ QLabel* mapPreview;
QComboBox* chooseMap;
- MapModel * m_mapModel;
+ MapModel * m_staticMapModel;
+ MapModel * m_missionMapModel;
IconedGroupBox* gbThemes;
QListView* lvThemes;
ThemeModel * m_themeModel;
@@ -121,12 +133,30 @@
QComboBox *cbMazeSize;
MapGenerator mapgen;
DrawMapScene drawMapScene;
+ QComboBox * cType;
+ QListView * staticMapList;
+ QListView * missionMapList;
+ QListWidget * generationStyles;
+ QListWidget * mazeStyles;
+ QLabel * lblMapList;
+ QLabel * lblDesc;
+ QPushButton * btnTheme;
+ QPushButton * btnLoadMap;
+ QPushButton * btnEditMap;
+ QPushButton * btnRandomize;
+ QString selectedTheme;
+ QPushButton * btnSeed;
+ bool m_master;
+ QList<QWidget *> m_childWidgets;
void intSetSeed(const QString & seed);
void intSetMap(const QString & map);
void intSetMapgen(MapGenerator m);
void intSetTemplateFilter(int);
void intSetMazeSize(int size);
+ void mapChanged(const QModelIndex & map, int type, const QModelIndex & old = QModelIndex());
+ void setMapInfo(MapModel::MapInfo mapInfo);
+ void changeMapType(MapModel::MapType type, const QModelIndex & newMap = QModelIndex());
void updatePreview();
MapModel::MapInfo m_mapInfo;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/seedprompt.cpp Mon Jan 14 11:19:59 2013 +0100
@@ -0,0 +1,85 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-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
+ */
+
+#include <QDialog>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QPushButton>
+#include <QLineEdit>
+#include <QLabel>
+#include <QDebug>
+
+#include "seedprompt.h"
+
+SeedPrompt::SeedPrompt(QWidget* parent, const QString & seed, bool editable) : QDialog(parent)
+{
+ setModal(true);
+ setWindowFlags(Qt::Sheet);
+ setWindowModality(Qt::WindowModal);
+ setMinimumSize(360, 160);
+ resize(360, 160);
+ setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+
+ // Layout
+ QVBoxLayout * dialogLayout = new QVBoxLayout(this);
+
+ // Label
+ QLabel * label = new QLabel(tr("The map seed is the basis for all random values generated by the game."));
+ label->setWordWrap(true);
+ dialogLayout->addWidget(label, 0);
+
+ // Input box
+ editBox = new QLineEdit();
+ editBox->setText(seed);
+ editBox->setReadOnly(!editable);
+ editBox->setStyleSheet("QLineEdit { padding: 3px; }");
+ dialogLayout->addWidget(editBox, 1);
+
+ dialogLayout->addStretch(1);
+
+ // Buttons
+ QHBoxLayout * buttonLayout = new QHBoxLayout();
+ buttonLayout->addStretch(1);
+ dialogLayout->addLayout(buttonLayout);
+ if (editable)
+ {
+ QPushButton * btnCancel = new QPushButton(tr("Cancel"));
+ QPushButton * btnOkay = new QPushButton(tr("Set seed"));
+ connect(btnCancel, SIGNAL(clicked()), this, SLOT(reject()));
+ connect(btnOkay, SIGNAL(clicked()), this, SLOT(accept()));
+ buttonLayout->addWidget(btnCancel);
+ buttonLayout->addWidget(btnOkay);
+ btnOkay->setDefault(true);
+ }
+ else
+ {
+ QPushButton * btnClose = new QPushButton(tr("Close"));
+ connect(btnClose, SIGNAL(clicked()), this, SLOT(reject()));
+ buttonLayout->addWidget(btnClose);
+ btnClose->setDefault(true);
+ }
+
+ setStyleSheet("QPushButton { padding: 5px; }");
+
+ connect(this, SIGNAL(accepted()), this, SLOT(setSeed()));
+}
+
+void SeedPrompt::setSeed()
+{
+ emit seedSelected(editBox->text());
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/seedprompt.h Mon Jan 14 11:19:59 2013 +0100
@@ -0,0 +1,43 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-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
+ */
+
+#ifndef SEEDPROMPT_H
+#define SEEDPROMPT_H
+
+#include <QDialog>
+
+class QLineEdit;
+
+class SeedPrompt : public QDialog
+{
+ Q_OBJECT
+
+ public:
+ SeedPrompt(QWidget* parent, const QString & seed, bool editable);
+
+ signals:
+ void seedSelected(const QString & seed);
+
+ private slots:
+ void setSeed();
+
+ private:
+ QLineEdit * editBox;
+};
+
+#endif // SEEDPROMPT_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/themeprompt.cpp Mon Jan 14 11:19:59 2013 +0100
@@ -0,0 +1,100 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-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
+ */
+
+#include <QDialog>
+#include <QVBoxLayout>
+#include <QScrollArea>
+#include <QPushButton>
+#include <QToolButton>
+#include <QWidgetItem>
+#include <QModelIndex>
+#include <QLabel>
+
+#include "flowlayout.h"
+#include "datamanager.h"
+#include "thememodel.h"
+#include "themeprompt.h"
+
+ThemePrompt::ThemePrompt(QWidget* parent) : QDialog(parent)
+{
+ setModal(true);
+ setWindowFlags(Qt::Sheet);
+ setWindowModality(Qt::WindowModal);
+ setMinimumSize(550, 430);
+ resize(550, 430);
+ setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+
+ // Grid
+ QVBoxLayout * dialogLayout = new QVBoxLayout(this);
+ dialogLayout->setSpacing(0);
+
+ // Help/prompt message at top
+ QLabel * lblDesc = new QLabel(tr("Select a theme for this map"));
+ lblDesc->setStyleSheet("color: #130F2A; background: #F6CB1C; border: solid 4px #F6CB1C; border-top-left-radius: 10px; border-top-right-radius: 10px; padding: auto 20px;");
+ lblDesc->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ lblDesc->setFixedHeight(24);
+ lblDesc->setMinimumWidth(0);
+
+ // Scroll area and container for theme icons
+ QWidget * themesContainer = new QWidget();
+ FlowLayout * themesGrid = new FlowLayout();
+ themesContainer->setLayout(themesGrid);
+ QScrollArea * scrollArea = new QScrollArea();
+ scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ scrollArea->setObjectName("scrollArea");
+ scrollArea->setStyleSheet("QScrollBar, #scrollArea { background-color: #130F2A; } #scrollArea { border-color: #F6CB1C; border-width: 3px; border-top-width: 0; border-style: solid; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; }");
+ scrollArea->setWidgetResizable(true);
+ scrollArea->setFrameShape(QFrame::NoFrame);
+ scrollArea->setWidget(themesContainer);
+
+ // Cancel button (closes dialog)
+ QPushButton * btnCancel = new QPushButton(tr("Cancel"));
+ btnCancel->setStyleSheet("padding: 5px; margin-top: 10px;");
+ connect(btnCancel, SIGNAL(clicked()), this, SLOT(reject()));
+
+ // Add elements to layouts
+ dialogLayout->addWidget(lblDesc, 0);
+ dialogLayout->addWidget(scrollArea, 1);
+ dialogLayout->addWidget(btnCancel, 0, Qt::AlignLeft);
+
+ // Tooltip label for theme name
+ lblToolTip = new QLabel(this);
+
+ // Add theme buttons
+ ThemeModel * themes = DataManager::instance().themeModel();
+ for (int i = 0; i < themes->rowCount(); i++)
+ {
+ QModelIndex index = themes->index(i, 0);
+ QToolButton * btn = new QToolButton();
+ btn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
+ btn->setIcon(qVariantValue<QIcon>(themes->data(index, Qt::UserRole)));
+ btn->setText(themes->data(index, Qt::DisplayRole).toString());
+ btn->setIconSize(QSize(60, 60));
+ btn->setProperty("themeID", QVariant(i));
+ btn->setStyleSheet("padding: 2px;");
+ connect(btn, SIGNAL(clicked()), this, SLOT(themeClicked()));
+ themesGrid->addWidget(btn);
+ }
+}
+
+// When a theme is selected
+void ThemePrompt::themeClicked()
+{
+ QWidget * btn = (QWidget*)sender();
+ done(btn->property("themeID").toInt() + 1); // Since returning 0 means canceled
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/themeprompt.h Mon Jan 14 11:19:59 2013 +0100
@@ -0,0 +1,41 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-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
+ */
+
+#ifndef THEMEPROMPT_H
+#define THEMEPROMPT_H
+
+#include <QWidget>
+#include <QDialog>
+
+class QLabel;
+
+class ThemePrompt : public QDialog
+{
+ Q_OBJECT
+
+ public:
+ ThemePrompt(QWidget* parent);
+
+ private:
+ QLabel * lblToolTip;
+
+ private slots:
+ void themeClicked();
+};
+
+#endif // THEMEPROMPT_H
--- a/QTfrontend/util/DataManager.cpp Mon Jan 14 12:07:06 2013 +0400
+++ b/QTfrontend/util/DataManager.cpp Mon Jan 14 11:19:59 2013 +0100
@@ -40,7 +40,8 @@
DataManager::DataManager()
{
m_hatModel = NULL;
- m_mapModel = NULL;
+ m_staticMapModel = NULL;
+ m_missionMapModel = NULL;
m_themeModel = NULL;
m_colorsModel = NULL;
m_bindsModel = NULL;
@@ -92,13 +93,22 @@
return m_hatModel;
}
-MapModel * DataManager::mapModel()
+MapModel * DataManager::staticMapModel()
{
- if (m_mapModel == NULL) {
- m_mapModel = new MapModel();
- m_mapModel->loadMaps();
+ if (m_staticMapModel == NULL) {
+ m_staticMapModel = new MapModel();
+ m_staticMapModel->loadMaps(MapModel::StaticMap);
}
- return m_mapModel;
+ return m_staticMapModel;
+}
+
+MapModel * DataManager::missionMapModel()
+{
+ if (m_missionMapModel == NULL) {
+ m_missionMapModel = new MapModel();
+ m_missionMapModel->loadMaps(MapModel::MissionMap);
+ }
+ return m_missionMapModel;
}
ThemeModel * DataManager::themeModel()
--- a/QTfrontend/util/DataManager.h Mon Jan 14 12:07:06 2013 +0400
+++ b/QTfrontend/util/DataManager.h Mon Jan 14 11:19:59 2013 +0100
@@ -88,13 +88,22 @@
HatModel * hatModel();
/**
- * @brief Returns pointer to a model of available maps.
+ * @brief Returns pointer to a model of available static maps.
*
* The model is updated automatically on data reload.
*
* @return map model pointer.
*/
- MapModel * mapModel();
+ MapModel * staticMapModel();
+
+ /**
+ * @brief Returns pointer to a model of available mission maps.
+ *
+ * The model is updated automatically on data reload.
+ *
+ * @return map model pointer.
+ */
+ MapModel * missionMapModel();
/**
* @brief Returns pointer to a model of available themes.
@@ -132,7 +141,8 @@
GameStyleModel * m_gameStyleModel; ///< game style model instance
HatModel * m_hatModel; ///< hat model instance
- MapModel * m_mapModel; ///< map model instance
+ MapModel * m_staticMapModel; ///< static map model instance
+ MapModel * m_missionMapModel; ///< mission map model instance
ThemeModel * m_themeModel; ///< theme model instance
QStandardItemModel * m_colorsModel;
QStandardItemModel * m_bindsModel;
--- a/share/hedgewars/Data/Maps/Basketball/CMakeLists.txt Mon Jan 14 12:07:06 2013 +0400
+++ b/share/hedgewars/Data/Maps/Basketball/CMakeLists.txt Mon Jan 14 11:19:59 2013 +0100
@@ -4,4 +4,5 @@
map.lua
mask.png
preview.png
+ desc.txt
DESTINATION ${SHAREPATH}Data/Maps/Basketball)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Maps/Basketball/desc.txt Mon Jan 14 11:19:59 2013 +0100
@@ -0,0 +1,1 @@
+en_US=Please give me a description.|Multiline is supported.|See Basketball/desc.txt
\ No newline at end of file
--- a/share/hedgewars/Data/Maps/Basketball/map.cfg Mon Jan 14 12:07:06 2013 +0400
+++ b/share/hedgewars/Data/Maps/Basketball/map.cfg Mon Jan 14 11:19:59 2013 +0100
@@ -1,2 +1,2 @@
Nature
-12
+12
\ No newline at end of file
--- a/share/hedgewars/Data/Maps/CTF_Blizzard/CMakeLists.txt Mon Jan 14 12:07:06 2013 +0400
+++ b/share/hedgewars/Data/Maps/CTF_Blizzard/CMakeLists.txt Mon Jan 14 11:19:59 2013 +0100
@@ -2,4 +2,5 @@
map.cfg
map.lua
preview.png
+ desc.txt
DESTINATION ${SHAREPATH}Data/Maps/CTF_Blizzard)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Maps/CTF_Blizzard/desc.txt Mon Jan 14 11:19:59 2013 +0100
@@ -0,0 +1,1 @@
+en_US=Please give me a description.|Multiline is supported.|See TrophyRace/desc.txt
\ No newline at end of file
--- a/share/hedgewars/Data/Maps/Control/CMakeLists.txt Mon Jan 14 12:07:06 2013 +0400
+++ b/share/hedgewars/Data/Maps/Control/CMakeLists.txt Mon Jan 14 11:19:59 2013 +0100
@@ -3,4 +3,5 @@
map.lua
map.png
preview.png
+ desc.txt
DESTINATION ${SHAREPATH}Data/Maps/Control)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Maps/Control/desc.txt Mon Jan 14 11:19:59 2013 +0100
@@ -0,0 +1,1 @@
+en_US=Please give me a description.|Multiline is supported.|See TrophyRace/desc.txt
\ No newline at end of file
--- a/share/hedgewars/Data/Maps/Control/map.cfg Mon Jan 14 12:07:06 2013 +0400
+++ b/share/hedgewars/Data/Maps/Control/map.cfg Mon Jan 14 11:19:59 2013 +0100
@@ -1,4 +1,4 @@
Deepspace
48
Default
-Crazy
+Crazy
\ No newline at end of file
--- a/share/hedgewars/Data/Maps/Knockball/CMakeLists.txt Mon Jan 14 12:07:06 2013 +0400
+++ b/share/hedgewars/Data/Maps/Knockball/CMakeLists.txt Mon Jan 14 11:19:59 2013 +0100
@@ -3,4 +3,5 @@
map.cfg
map.lua
preview.png
+ desc.txt
DESTINATION ${SHAREPATH}Data/Maps/Knockball)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Maps/Knockball/desc.txt Mon Jan 14 11:19:59 2013 +0100
@@ -0,0 +1,1 @@
+en_US=Please give me a description.|Multiline is supported.|See TrophyRace/desc.txt
\ No newline at end of file
--- a/share/hedgewars/Data/Maps/TrophyRace/CMakeLists.txt Mon Jan 14 12:07:06 2013 +0400
+++ b/share/hedgewars/Data/Maps/TrophyRace/CMakeLists.txt Mon Jan 14 11:19:59 2013 +0100
@@ -4,4 +4,5 @@
map.png
mask.png
preview.png
+ desc.txt
DESTINATION ${SHAREPATH}Data/Maps/TrophyRace)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Maps/TrophyRace/desc.txt Mon Jan 14 11:19:59 2013 +0100
@@ -0,0 +1,1 @@
+en_US=Please give me a description.|Multiline is supported.|See TrophyRace/desc.txt
\ No newline at end of file