# HG changeset patch # User dag10 # Date 1358158799 -3600 # Node ID 869f80966a777216116316a22a685ca73e180182 # Parent c11cc7246df7bd0f1e0cff4e52fe700a60837058 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. diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/hedgewars.qrc --- 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 @@ res/StatsMostSelfDamage.png res/StatsSelfKilled.png res/StatsSkipped.png + res/Start.png res/mapRandom.png res/mapMaze.png res/mapMissing.png diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/hwform.cpp --- 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) diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/model/MapModel.cpp --- 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 -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 genMaps; - QList missionMaps; - QList 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 staticMaps; + //QList missionMaps; + QList 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 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()) m_mapIndexes.insert(v.value().name, i); } - - // store start-index and count of relevant types - - m_typeLoc.insert(GeneratedMap, QPair(0, 1)); - m_typeLoc.insert(GeneratedMaze, QPair(1, 1)); - m_typeLoc.insert(HandDrawnMap, QPair(2, 1)); - // mission maps - int startIdx = genMaps.size() + 2; // start after genMaps and 2 separators - count = missionMaps.size(); - m_typeLoc.insert(MissionMap, QPair(startIdx, count)); - // static maps - startIdx += count + 1; // start after missions and 2 separators - count = staticMaps.size(); - m_typeLoc.insert(StaticMap, QPair(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 loc = m_typeLoc.value(type, QPair(-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); -} - diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/model/MapModel.h --- 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 with column, index, or (-1, -1) if map not found + */ + //QPair 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 > m_typeLoc; - - /// map index lookup table + /// map index lookup table. QPair contains: + //QHash > m_mapIndexes; QHash 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) diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/model/ThemeModel.cpp --- 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 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); diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/model/roomslistmodel.cpp --- 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) diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/model/roomslistmodel.h --- 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 m_data; QStringList m_headerData; - MapModel * m_mapModel; + MapModel * m_staticMapModel; + MapModel * m_missionMapModel; QStringList roomInfo2RoomRecord(const QStringList & info); }; diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/res/Start.png Binary file QTfrontend/res/Start.png has changed diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/res/css/qt.css --- 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; } diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/ui/page/AbstractPage.cpp --- 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())); diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/ui/page/AbstractPage.h --- 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.
* Keep in mind not to expose twidgets as public! diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/ui/page/pagemultiplayer.cpp --- 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); diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/ui/page/pagemultiplayer.h --- 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; diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/ui/page/pagenetgame.cpp --- 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; } diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/ui/page/pagenetgame.h --- 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; diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/ui/widget/flowlayout.cpp --- /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 + + #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(parent); + return pw->style()->pixelMetric(pm, 0, pw); + } else { + return static_cast(parent)->spacing(); + } + } \ No newline at end of file diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/ui/widget/flowlayout.h --- /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 + #include + #include + #include + 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 itemList; + int m_hSpace; + int m_vSpace; + }; + + #endif \ No newline at end of file diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/ui/widget/gamecfgwidget.cpp --- 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 #include #include +#include +#include #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); +} diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/ui/widget/gamecfgwidget.h --- 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 m_childWidgets; void setNetAmmo(const QString& name, const QString& ammo); diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/ui/widget/mapContainer.cpp --- 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 #include #include +#include +#include +#include +#include +#include +#include +#include #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()); - m_mapInfo = chooseMap->itemData(index, Qt::UserRole + 1).value(); - 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(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(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()) + setMapInfo(map.data(Qt::UserRole + 1).value()); + 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); +} diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/ui/widget/mapContainer.h --- 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 #include +#include #include #include #include @@ -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 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; diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/ui/widget/seedprompt.cpp --- /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 + * + * 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 +#include +#include +#include +#include +#include +#include + +#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 diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/ui/widget/seedprompt.h --- /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 + * + * 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 + +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 diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/ui/widget/themeprompt.cpp --- /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 + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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(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 diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/ui/widget/themeprompt.h --- /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 + * + * 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 +#include + +class QLabel; + +class ThemePrompt : public QDialog +{ + Q_OBJECT + + public: + ThemePrompt(QWidget* parent); + + private: + QLabel * lblToolTip; + + private slots: + void themeClicked(); +}; + +#endif // THEMEPROMPT_H diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/util/DataManager.cpp --- 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() diff -r c11cc7246df7 -r 869f80966a77 QTfrontend/util/DataManager.h --- 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; diff -r c11cc7246df7 -r 869f80966a77 share/hedgewars/Data/Maps/Basketball/CMakeLists.txt --- 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) diff -r c11cc7246df7 -r 869f80966a77 share/hedgewars/Data/Maps/Basketball/desc.txt --- /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 diff -r c11cc7246df7 -r 869f80966a77 share/hedgewars/Data/Maps/Basketball/map.cfg --- 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 diff -r c11cc7246df7 -r 869f80966a77 share/hedgewars/Data/Maps/CTF_Blizzard/CMakeLists.txt --- 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) diff -r c11cc7246df7 -r 869f80966a77 share/hedgewars/Data/Maps/CTF_Blizzard/desc.txt --- /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 diff -r c11cc7246df7 -r 869f80966a77 share/hedgewars/Data/Maps/Control/CMakeLists.txt --- 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) diff -r c11cc7246df7 -r 869f80966a77 share/hedgewars/Data/Maps/Control/desc.txt --- /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 diff -r c11cc7246df7 -r 869f80966a77 share/hedgewars/Data/Maps/Control/map.cfg --- 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 diff -r c11cc7246df7 -r 869f80966a77 share/hedgewars/Data/Maps/Knockball/CMakeLists.txt --- 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) diff -r c11cc7246df7 -r 869f80966a77 share/hedgewars/Data/Maps/Knockball/desc.txt --- /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 diff -r c11cc7246df7 -r 869f80966a77 share/hedgewars/Data/Maps/TrophyRace/CMakeLists.txt --- 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) diff -r c11cc7246df7 -r 869f80966a77 share/hedgewars/Data/Maps/TrophyRace/desc.txt --- /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