QTfrontend/ui/widget/mapContainer.cpp
changeset 8377 869f80966a77
parent 8070 66bc20d089fc
child 8393 85bd6c7b2641
equal deleted inserted replaced
8376:c11cc7246df7 8377:869f80966a77
    28 #include <QListView>
    28 #include <QListView>
    29 #include <QVBoxLayout>
    29 #include <QVBoxLayout>
    30 #include <QIcon>
    30 #include <QIcon>
    31 #include <QLineEdit>
    31 #include <QLineEdit>
    32 #include <QStringListModel>
    32 #include <QStringListModel>
       
    33 #include <QListWidget>
       
    34 #include <QListWidgetItem>
       
    35 #include <QDebug>
       
    36 #include <QFile>
       
    37 #include <QFileDialog>
       
    38 #include <QInputDialog>
       
    39 #include <QMessageBox>
    33 
    40 
    34 #include "hwconsts.h"
    41 #include "hwconsts.h"
    35 #include "mapContainer.h"
    42 #include "mapContainer.h"
       
    43 #include "themeprompt.h"
       
    44 #include "seedprompt.h"
    36 #include "igbox.h"
    45 #include "igbox.h"
    37 #include "HWApplication.h"
    46 #include "HWApplication.h"
    38 #include "ThemeModel.h"
    47 #include "ThemeModel.h"
       
    48 
       
    49 
    39 
    50 
    40 HWMapContainer::HWMapContainer(QWidget * parent) :
    51 HWMapContainer::HWMapContainer(QWidget * parent) :
    41     QWidget(parent),
    52     QWidget(parent),
    42     mainLayout(this),
    53     mainLayout(this),
    43     pMap(0),
    54     pMap(0),
    45     m_previewSize(256, 128)
    56     m_previewSize(256, 128)
    46 {
    57 {
    47     hhSmall.load(":/res/hh_small.png");
    58     hhSmall.load(":/res/hh_small.png");
    48     hhLimit = 18;
    59     hhLimit = 18;
    49     templateFilter = 0;
    60     templateFilter = 0;
       
    61     m_master = true;
    50 
    62 
    51     linearGrad = QLinearGradient(QPoint(128, 0), QPoint(128, 128));
    63     linearGrad = QLinearGradient(QPoint(128, 0), QPoint(128, 128));
    52     linearGrad.setColorAt(1, QColor(0, 0, 192));
    64     linearGrad.setColorAt(1, QColor(0, 0, 192));
    53     linearGrad.setColorAt(0, QColor(66, 115, 225));
    65     linearGrad.setColorAt(0, QColor(66, 115, 225));
    54 
    66 
    55     mainLayout.setContentsMargins(HWApplication::style()->pixelMetric(QStyle::PM_LayoutLeftMargin),
    67     mainLayout.setContentsMargins(HWApplication::style()->pixelMetric(QStyle::PM_LayoutLeftMargin),
    56                                   1,
    68                                   1,
    57                                   HWApplication::style()->pixelMetric(QStyle::PM_LayoutRightMargin),
    69                                   HWApplication::style()->pixelMetric(QStyle::PM_LayoutRightMargin),
    58                                   HWApplication::style()->pixelMetric(QStyle::PM_LayoutBottomMargin));
    70                                   HWApplication::style()->pixelMetric(QStyle::PM_LayoutBottomMargin));
    59 
    71 
    60     QWidget* mapWidget = new QWidget(this);
    72     m_staticMapModel = DataManager::instance().staticMapModel();
    61     mainLayout.addWidget(mapWidget, 0, 0, Qt::AlignHCenter);
    73     m_missionMapModel = DataManager::instance().missionMapModel();
    62 
       
    63     QGridLayout* mapLayout = new QGridLayout(mapWidget);
       
    64     mapLayout->setMargin(0);
       
    65 
       
    66     imageButt = new QPushButton(mapWidget);
       
    67     imageButt->setObjectName("imageButt");
       
    68     imageButt->setFixedSize(256 + 6, 128 + 6);
       
    69     imageButt->setFlat(true);
       
    70     imageButt->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);//QSizePolicy::Minimum, QSizePolicy::Minimum);
       
    71     mapLayout->addWidget(imageButt, 0, 0, 1, 2);
       
    72     connect(imageButt, SIGNAL(clicked()), this, SLOT(setRandomMap()));
       
    73 
       
    74     chooseMap = new QComboBox(mapWidget);
       
    75     chooseMap->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
       
    76     m_mapModel = DataManager::instance().mapModel();
       
    77     chooseMap->setEditable(false);
       
    78     chooseMap->setModel(m_mapModel);
       
    79 
       
    80     mapLayout->addWidget(chooseMap, 1, 1);
       
    81 
       
    82     QLabel * lblMap = new QLabel(tr("Map"), mapWidget);
       
    83     mapLayout->addWidget(lblMap, 1, 0);
       
    84 
       
    85     lblFilter = new QLabel(tr("Filter"), mapWidget);
       
    86     mapLayout->addWidget(lblFilter, 2, 0);
       
    87 
       
    88     cbTemplateFilter = new QComboBox(mapWidget);
       
    89     cbTemplateFilter->addItem(tr("All"), 0);
       
    90     cbTemplateFilter->addItem(tr("Small"), 1);
       
    91     cbTemplateFilter->addItem(tr("Medium"), 2);
       
    92     cbTemplateFilter->addItem(tr("Large"), 3);
       
    93     cbTemplateFilter->addItem(tr("Cavern"), 4);
       
    94     cbTemplateFilter->addItem(tr("Wacky"), 5);
       
    95     mapLayout->addWidget(cbTemplateFilter, 2, 1);
       
    96 
       
    97     connect(cbTemplateFilter, SIGNAL(activated(int)), this, SLOT(setTemplateFilter(int)));
       
    98 
       
    99     maze_size_label = new QLabel(tr("Type"), mapWidget);
       
   100     mapLayout->addWidget(maze_size_label, 2, 0);
       
   101     maze_size_label->hide();
       
   102     cbMazeSize = new QComboBox(mapWidget);
       
   103     cbMazeSize->addItem(tr("Small tunnels"), 0);
       
   104     cbMazeSize->addItem(tr("Medium tunnels"), 1);
       
   105     cbMazeSize->addItem(tr("Large tunnels"), 2);
       
   106     cbMazeSize->addItem(tr("Small floating islands"), 3);
       
   107     cbMazeSize->addItem(tr("Medium floating islands"), 4);
       
   108     cbMazeSize->addItem(tr("Large floating islands"), 5);
       
   109     cbMazeSize->setCurrentIndex(1);
       
   110 
       
   111     mapLayout->addWidget(cbMazeSize, 2, 1);
       
   112     cbMazeSize->hide();
       
   113     connect(cbMazeSize, SIGNAL(activated(int)), this, SLOT(setMazeSize(int)));
       
   114 
       
   115     gbThemes = new IconedGroupBox(mapWidget);
       
   116     gbThemes->setTitleTextPadding(80);
       
   117     gbThemes->setContentTopPadding(15);
       
   118     gbThemes->setTitle(tr("Themes"));
       
   119 
       
   120     //gbThemes->setStyleSheet("padding: 0px"); // doesn't work - stylesheet is set with icon
       
   121     mapLayout->addWidget(gbThemes, 0, 2, 3, 1);
       
   122     // disallow row to be collapsed (so it can't get ignored when Qt applies rowSpan of gbThemes)
       
   123     mapLayout->setRowMinimumHeight(2, 13);
       
   124     QVBoxLayout * gbTLayout = new QVBoxLayout(gbThemes);
       
   125     gbTLayout->setContentsMargins(0, 0, 0 ,0);
       
   126     gbTLayout->setSpacing(0);
       
   127     lvThemes = new QListView(mapWidget);
       
   128     lvThemes->setMinimumHeight(30);
       
   129     lvThemes->setFixedWidth(140);
       
   130     m_themeModel = DataManager::instance().themeModel();
    74     m_themeModel = DataManager::instance().themeModel();
   131     lvThemes->setModel(m_themeModel);
    75 
   132     lvThemes->setIconSize(QSize(16, 16));
    76     /* Layouts */
   133     lvThemes->setEditTriggers(QListView::NoEditTriggers);
    77 
   134 
    78     QHBoxLayout * typeLayout = new QHBoxLayout();
   135     connect(lvThemes->selectionModel(), SIGNAL(currentRowChanged( const QModelIndex &, const QModelIndex &)), this, SLOT(themeSelected( const QModelIndex &, const QModelIndex &)));
    79     QHBoxLayout * seedLayout = new QHBoxLayout();
   136 
    80     QHBoxLayout * twoColumnLayout = new QHBoxLayout();
   137     // override default style to tighten up theme scroller
    81     QVBoxLayout * leftLayout = new QVBoxLayout();
   138     lvThemes->setStyleSheet(QString(
    82     QVBoxLayout * rightLayout = new QVBoxLayout();
   139                                 "QListView{"
    83     twoColumnLayout->addLayout(leftLayout, 0);
   140                                 "border: solid;"
    84     twoColumnLayout->addStretch(1);
   141                                 "border-width: 0px;"
    85     twoColumnLayout->addLayout(rightLayout, 0);
   142                                 "border-radius: 0px;"
    86     QVBoxLayout * drawnControls = new QVBoxLayout();
   143                                 "border-color: transparent;"
    87     leftLayout->addLayout(typeLayout, 0);
   144                                 "background-color: #0d0544;"
    88     rightLayout->addLayout(seedLayout, 0);
   145                                 "color: #ffcc00;"
    89 
   146                                 "font: bold 13px;"
    90     /* Map type combobox */
   147                                 "}"
    91 
   148                             )
    92     typeLayout->setSpacing(10);
   149                            );
    93     typeLayout->addWidget(new QLabel(tr("Map type:")), 0);
   150 
    94     cType = new QComboBox(this);
   151     gbTLayout->addWidget(lvThemes);
    95     typeLayout->addWidget(cType, 1);
   152     lvThemes->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Minimum);
    96     cType->insertItem(0, tr("Image map"), MapModel::StaticMap);
   153 
    97     cType->insertItem(1, tr("Mission map"), MapModel::MissionMap);
   154     mapLayout->setSizeConstraint(QLayout::SetFixedSize);
    98     cType->insertItem(2, tr("Hand-drawn"), MapModel::HandDrawnMap);
   155 
    99     cType->insertItem(3, tr("Randomly generated"), MapModel::GeneratedMap);
   156     QWidget* seedWidget = new QWidget(this);
   100     cType->insertItem(4, tr("Random maze"), MapModel::GeneratedMaze);
   157     mainLayout.addWidget(seedWidget, 1, 0);
   101     connect(cType, SIGNAL(currentIndexChanged(int)), this, SLOT(mapTypeChanged(int)));
   158 
   102     m_childWidgets << cType;
   159     QGridLayout* seedLayout = new QGridLayout(seedWidget);
   103 
   160     seedLayout->setMargin(0);
   104     /* Randomize button */
   161 
   105 
   162     seedLabel = new QLabel(tr("Seed"), seedWidget);
   106     seedLayout->addStretch(1);
   163     seedLayout->addWidget(seedLabel, 3, 0);
   107     const QIcon& lp = QIcon(":/res/dice.png");
   164     seedEdit = new QLineEdit(seedWidget);
   108     QSize sz = lp.actualSize(QSize(65535, 65535));
   165     seedEdit->setMaxLength(54);
   109     btnRandomize = new QPushButton();
   166     connect(seedEdit, SIGNAL(returnPressed()), this, SLOT(seedEdited()));
   110     btnRandomize->setText(tr("Random"));
   167     seedLayout->addWidget(seedEdit, 3, 1);
   111     btnRandomize->setIcon(lp);
   168     seedLayout->setColumnStretch(1, 5);
   112     btnRandomize->setFixedHeight(30);
   169     seedSet = new QPushButton(seedWidget);
   113     btnRandomize->setIconSize(sz);
   170     seedSet->setText(QPushButton::tr("more"));
   114     btnRandomize->setFlat(true);
   171     connect(seedSet, SIGNAL(clicked()), this, SLOT(seedEdited()));
   115     btnRandomize->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
   172     seedLayout->setColumnStretch(2, 1);
   116     connect(btnRandomize, SIGNAL(clicked()), this, SLOT(setRandomMap()));
   173     seedLayout->addWidget(seedSet, 3, 2);
   117     m_childWidgets << btnRandomize;
   174 
   118     btnRandomize->setStyleSheet("padding: 5px;");
   175     seedLabel->setVisible(false);
   119     btnRandomize->setFixedHeight(cType->height());
   176     seedEdit->setVisible(false);
   120     seedLayout->addWidget(btnRandomize, 1);
   177 
   121 
       
   122     /* Seed button */
       
   123     btnSeed = new QPushButton(parentWidget()->parentWidget());
       
   124     btnSeed->setText(tr("Seed"));
       
   125     btnSeed->setStyleSheet("padding: 5px;");
       
   126     btnSeed->setFixedHeight(cType->height());
       
   127     connect(btnSeed, SIGNAL(clicked()), this, SLOT(showSeedPrompt()));
       
   128     seedLayout->addWidget(btnSeed, 0);
       
   129 
       
   130     /* Map preview label */
       
   131 
       
   132     QLabel * lblMapPreviewText = new QLabel(this);
       
   133     lblMapPreviewText->setText(tr("Map preview:"));
       
   134     leftLayout->addWidget(lblMapPreviewText, 0, Qt::AlignLeft);
       
   135 
       
   136     /* Map Preview */
       
   137 
       
   138     mapPreview = new QLabel(this);
       
   139     mapPreview->setObjectName("mapPreview");
       
   140     mapPreview->setFixedSize(256, 128);
       
   141     leftLayout->addWidget(mapPreview, 0);
       
   142 
       
   143     /* Bottom-Left layout */
       
   144 
       
   145     QVBoxLayout * bottomLeftLayout = new QVBoxLayout();
       
   146     leftLayout->addLayout(bottomLeftLayout, 1);
       
   147 
       
   148     /* Map list label */
       
   149 
       
   150     lblMapList = new QLabel();
       
   151     rightLayout->addWidget(lblMapList, 0);
       
   152 
       
   153     /* Static maps list */
       
   154 
       
   155     staticMapList = new QListView;
       
   156     staticMapList->setModel(m_staticMapModel);
       
   157     rightLayout->addWidget(staticMapList, 1);
       
   158     staticMapList->setEditTriggers(QAbstractItemView::NoEditTriggers);
       
   159     m_childWidgets << staticMapList;
       
   160     QItemSelectionModel * staticSelectionModel = staticMapList->selectionModel();
       
   161     connect(staticSelectionModel,
       
   162             SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)),
       
   163             this,
       
   164             SLOT(staticMapChanged(const QModelIndex &, const QModelIndex &)));
       
   165 
       
   166     /* Mission maps list */
       
   167 
       
   168     missionMapList = new QListView;
       
   169     missionMapList->setModel(m_missionMapModel);
       
   170     missionMapList->setEditTriggers(QAbstractItemView::NoEditTriggers);
       
   171     rightLayout->addWidget(missionMapList, 1);
       
   172     m_childWidgets << missionMapList;
       
   173     QItemSelectionModel * missionSelectionModel = missionMapList->selectionModel();
       
   174     connect(missionSelectionModel,
       
   175             SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)),
       
   176             this,
       
   177             SLOT(missionMapChanged(const QModelIndex &, const QModelIndex &)));
       
   178 
       
   179     /* Map load and edit buttons */
       
   180 
       
   181     drawnControls->addStretch(1);
       
   182 
       
   183     btnLoadMap = new QPushButton(tr("Load map drawing"));
       
   184     btnLoadMap->setStyleSheet("padding: 20px;");
       
   185     drawnControls->addWidget(btnLoadMap, 0);
       
   186     m_childWidgets << btnLoadMap;
       
   187     connect(btnLoadMap, SIGNAL(clicked()), this, SLOT(loadDrawing()));
       
   188 
       
   189     btnEditMap = new QPushButton(tr("Edit map drawing"));
       
   190     btnEditMap->setStyleSheet("padding: 20px;");
       
   191     drawnControls->addWidget(btnEditMap, 0);
       
   192     m_childWidgets << btnEditMap;
       
   193     connect(btnEditMap, SIGNAL(clicked()), this, SIGNAL(drawMapRequested()));
       
   194 
       
   195     drawnControls->addStretch(1);
       
   196 
       
   197     rightLayout->addLayout(drawnControls);
       
   198 
       
   199     /* Generator style list */
       
   200 
       
   201     generationStyles = new QListWidget();
       
   202     new QListWidgetItem(tr("All"), generationStyles);
       
   203     new QListWidgetItem(tr("Small"), generationStyles);
       
   204     new QListWidgetItem(tr("Medium"), generationStyles);
       
   205     new QListWidgetItem(tr("Large"), generationStyles);
       
   206     new QListWidgetItem(tr("Cavern"), generationStyles);
       
   207     new QListWidgetItem(tr("Wacky"), generationStyles);
       
   208     connect(generationStyles, SIGNAL(currentRowChanged(int)), this, SLOT(setTemplateFilter(int)));
       
   209     m_childWidgets << generationStyles;
       
   210     rightLayout->addWidget(generationStyles, 1);
       
   211 
       
   212     /* Maze style list */
       
   213 
       
   214     mazeStyles = new QListWidget();
       
   215     new QListWidgetItem(tr("Small tunnels"), mazeStyles);
       
   216     new QListWidgetItem(tr("Medium tunnels"), mazeStyles);
       
   217     new QListWidgetItem(tr("Largetunnels"), mazeStyles);
       
   218     new QListWidgetItem(tr("Small islands"), mazeStyles);
       
   219     new QListWidgetItem(tr("Medium islands"), mazeStyles);
       
   220     new QListWidgetItem(tr("Large islands"), mazeStyles);
       
   221     connect(mazeStyles, SIGNAL(currentRowChanged(int)), this, SLOT(setMazeSize(int)));
       
   222     m_childWidgets << mazeStyles;
       
   223     rightLayout->addWidget(mazeStyles, 1);
       
   224 
       
   225     /* Mission description */
       
   226 
       
   227     lblDesc = new QLabel();
       
   228     lblDesc->setWordWrap(true);
       
   229     lblDesc->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
       
   230     lblDesc->setAlignment(Qt::AlignTop | Qt::AlignLeft);
       
   231     bottomLeftLayout->addWidget(lblDesc, 100);
       
   232 
       
   233     /* Spacing above theme chooser */
       
   234 
       
   235     bottomLeftLayout->addStretch(1);
       
   236 
       
   237     /* Theme chooser */
       
   238 
       
   239     btnTheme = new QPushButton();
       
   240     connect(btnTheme, SIGNAL(clicked()), this, SLOT(showThemePrompt()));
       
   241     m_childWidgets << btnTheme;
       
   242     bottomLeftLayout->addWidget(btnTheme, 1);
       
   243 
       
   244     /* Add everything to main layout */
       
   245 
       
   246     mainLayout.addLayout(twoColumnLayout, 0);
       
   247 
       
   248     /* Set defaults */
       
   249 
       
   250     setRandomTheme();
   178     setRandomSeed();
   251     setRandomSeed();
   179     setRandomTheme();
   252     setMazeSize(0);
   180 
   253     setTemplateFilter(0);
   181     chooseMap->setCurrentIndex(0);
   254     staticMapChanged(m_staticMapModel->index(0, 0));
   182     mapChanged(0);
   255     missionMapChanged(m_missionMapModel->index(0, 0));
   183     // use signal "activated" rather than currentIndexChanged
   256     updateTheme(m_themeModel->index(0, 0));
   184     // because index is somtimes changed a few times in a row programmatically
   257     mapTypeChanged(0);
   185     connect(chooseMap, SIGNAL(activated(int)), this, SLOT(mapChanged(int)));
       
   186 
       
   187     // update model views after model changes (to e.g. re-adjust separators)
       
   188     connect(&DataManager::instance(), SIGNAL(updated()), this, SLOT(updateModelViews()));
       
   189 }
   258 }
   190 
   259 
   191 void HWMapContainer::setImage(const QImage newImage)
   260 void HWMapContainer::setImage(const QImage newImage)
   192 {
   261 {
   193     QPixmap px(m_previewSize);
   262     QPixmap px(m_previewSize);
   200 
   269 
   201     p.fillRect(pxres.rect(), linearGrad);
   270     p.fillRect(pxres.rect(), linearGrad);
   202     p.drawPixmap(QPoint(0, 0), px);
   271     p.drawPixmap(QPoint(0, 0), px);
   203 
   272 
   204     addInfoToPreview(pxres);
   273     addInfoToPreview(pxres);
   205     //chooseMap->setCurrentIndex(mapgen);
       
   206     pMap = 0;
   274     pMap = 0;
       
   275 
       
   276     cType->setEnabled(isMaster());
   207 }
   277 }
   208 
   278 
   209 void HWMapContainer::setHHLimit(int newHHLimit)
   279 void HWMapContainer::setHHLimit(int newHHLimit)
   210 {
   280 {
   211     hhLimit = newHHLimit;
   281     hhLimit = newHHLimit;
   212 }
       
   213 
       
   214 void HWMapContainer::mapChanged(int index)
       
   215 {
       
   216     if (chooseMap->currentIndex() != index)
       
   217         chooseMap->setCurrentIndex(index);
       
   218 
       
   219     if (index < 0)
       
   220     {
       
   221         m_mapInfo.type = MapModel::Invalid;
       
   222         updatePreview();
       
   223         return;
       
   224     }
       
   225 
       
   226     Q_ASSERT(chooseMap->itemData(index, Qt::UserRole + 1).canConvert<MapModel::MapInfo>());
       
   227     m_mapInfo = chooseMap->itemData(index, Qt::UserRole + 1).value<MapModel::MapInfo>();
       
   228     m_curMap = m_mapInfo.name;
       
   229 
       
   230     switch(m_mapInfo.type)
       
   231     {
       
   232         case MapModel::GeneratedMap:
       
   233             mapgen = MAPGEN_REGULAR;
       
   234             gbThemes->show();
       
   235             lblFilter->show();
       
   236             cbTemplateFilter->show();
       
   237             maze_size_label->hide();
       
   238             cbMazeSize->hide();
       
   239             break;
       
   240         case MapModel::GeneratedMaze:
       
   241             mapgen = MAPGEN_MAZE;
       
   242             gbThemes->show();
       
   243             lblFilter->hide();
       
   244             cbTemplateFilter->hide();
       
   245             maze_size_label->show();
       
   246             cbMazeSize->show();
       
   247             break;
       
   248         case MapModel::HandDrawnMap:
       
   249             mapgen = MAPGEN_DRAWN;
       
   250             gbThemes->show();
       
   251             lblFilter->hide();
       
   252             cbTemplateFilter->hide();
       
   253             maze_size_label->hide();
       
   254             cbMazeSize->hide();
       
   255             break;
       
   256         default:
       
   257             mapgen = MAPGEN_MAP;
       
   258             gbThemes->hide();
       
   259             lblFilter->hide();
       
   260             cbTemplateFilter->hide();
       
   261             maze_size_label->hide();
       
   262             cbMazeSize->hide();
       
   263             m_theme = m_mapInfo.theme;
       
   264     }
       
   265 
       
   266     // the map has no pre-defined theme, so let's use the selected one
       
   267     if (m_mapInfo.theme.isEmpty())
       
   268     {
       
   269         m_theme = lvThemes->currentIndex().data().toString();
       
   270         emit themeChanged(m_theme);
       
   271     }
       
   272 
       
   273     updatePreview();
       
   274     emit mapChanged(m_curMap);
       
   275     emit mapgenChanged(mapgen);
       
   276 }
   282 }
   277 
   283 
   278 // Should this add text to identify map size?
   284 // Should this add text to identify map size?
   279 void HWMapContainer::addInfoToPreview(QPixmap image)
   285 void HWMapContainer::addInfoToPreview(QPixmap image)
   280 {
   286 {
   290     p.setFont(QFont("MS Shell Dlg", 10));
   296     p.setFont(QFont("MS Shell Dlg", 10));
   291     QString text = (hhLimit > 0) ? QString::number(hhLimit) : "?";
   297     QString text = (hhLimit > 0) ? QString::number(hhLimit) : "?";
   292     p.drawText(image.rect().width() - hhSmall.rect().width() - 14 - (hhLimit > 9 ? 10 : 0), 18, text);
   298     p.drawText(image.rect().width() - hhSmall.rect().width() - 14 - (hhLimit > 9 ? 10 : 0), 18, text);
   293     p.drawPixmap(image.rect().width() - hhSmall.rect().width() - 5, 5, hhSmall.rect().width(), hhSmall.rect().height(), hhSmall);
   299     p.drawPixmap(image.rect().width() - hhSmall.rect().width() - 5, 5, hhSmall.rect().width(), hhSmall.rect().height(), hhSmall);
   294 
   300 
   295     imageButt->setIcon(finalImage);
   301     mapPreview->setPixmap(finalImage);
   296     imageButt->setIconSize(image.size());
       
   297 }
   302 }
   298 
   303 
   299 void HWMapContainer::askForGeneratedPreview()
   304 void HWMapContainer::askForGeneratedPreview()
   300 {
   305 {
   301     pMap = new HWMap(this);
   306     pMap = new HWMap(this);
   320     int x = (waitImage.width() - waitIcon.width()) / 2;
   325     int x = (waitImage.width() - waitIcon.width()) / 2;
   321     int y = (waitImage.height() - waitIcon.height()) / 2;
   326     int y = (waitImage.height() - waitIcon.height()) / 2;
   322     p.drawPixmap(QPoint(x, y), waitIcon);
   327     p.drawPixmap(QPoint(x, y), waitIcon);
   323 
   328 
   324     addInfoToPreview(waitImage);
   329     addInfoToPreview(waitImage);
   325 }
   330 
   326 
   331     cType->setEnabled(false);
   327 void HWMapContainer::themeSelected(const QModelIndex & current, const QModelIndex &)
       
   328 {
       
   329     m_theme = current.data().toString();
       
   330 
       
   331     gbThemes->setIcon(qVariantValue<QIcon>(current.data(Qt::UserRole)));
       
   332     emit themeChanged(m_theme);
       
   333 }
   332 }
   334 
   333 
   335 QString HWMapContainer::getCurrentSeed() const
   334 QString HWMapContainer::getCurrentSeed() const
   336 {
   335 {
   337     return m_seed;
   336     return m_seed;
   338 }
   337 }
   339 
   338 
   340 QString HWMapContainer::getCurrentMap() const
   339 QString HWMapContainer::getCurrentMap() const
   341 {
   340 {
   342     if(chooseMap->currentIndex() < MAPGEN_MAP) return QString();
   341     switch (m_mapInfo.type)
   343     return(m_curMap);
   342     {
       
   343         case MapModel::StaticMap:
       
   344         case MapModel::MissionMap:
       
   345             return m_curMap;
       
   346         default:
       
   347             return QString();
       
   348     }
   344 }
   349 }
   345 
   350 
   346 QString HWMapContainer::getCurrentTheme() const
   351 QString HWMapContainer::getCurrentTheme() const
   347 {
   352 {
   348     return(m_theme);
   353     return(m_theme);
   368     return(m_mapInfo.weapons);
   373     return(m_mapInfo.weapons);
   369 }
   374 }
   370 
   375 
   371 quint32 HWMapContainer::getTemplateFilter() const
   376 quint32 HWMapContainer::getTemplateFilter() const
   372 {
   377 {
   373     return cbTemplateFilter->itemData(cbTemplateFilter->currentIndex()).toInt();
   378     return generationStyles->currentRow();
   374 }
   379 }
   375 
   380 
   376 void HWMapContainer::resizeEvent ( QResizeEvent * event )
   381 void HWMapContainer::resizeEvent ( QResizeEvent * event )
   377 {
   382 {
   378     Q_UNUSED(event);
   383     Q_UNUSED(event);
   379     //imageButt->setIconSize(imageButt->size());
       
   380 }
   384 }
   381 
   385 
   382 void HWMapContainer::intSetSeed(const QString & seed)
   386 void HWMapContainer::intSetSeed(const QString & seed)
   383 {
   387 {
   384     m_seed = seed;
   388     m_seed = seed;
   385     if (seed != seedEdit->text())
       
   386         seedEdit->setText(seed);
       
   387 }
   389 }
   388 
   390 
   389 void HWMapContainer::setSeed(const QString & seed)
   391 void HWMapContainer::setSeed(const QString & seed)
   390 {
   392 {
   391     intSetSeed(seed);
   393     intSetSeed(seed);
   393         updatePreview();
   395         updatePreview();
   394 }
   396 }
   395 
   397 
   396 void HWMapContainer::intSetMap(const QString & map)
   398 void HWMapContainer::intSetMap(const QString & map)
   397 {
   399 {
   398     m_curMap = map;
   400     if (map == "+rnd+")
   399 
   401     {
   400     int id = m_mapModel->indexOf(map);
   402         changeMapType(MapModel::GeneratedMap);
   401 
   403     }
   402     mapChanged(id);
   404     else if (map == "+maze+")
       
   405     {
       
   406         changeMapType(MapModel::GeneratedMaze);
       
   407     }
       
   408     else if (map == "+drawn+")
       
   409     {
       
   410         changeMapType(MapModel::HandDrawnMap);
       
   411     }
       
   412     else if (m_staticMapModel->mapExists(map))
       
   413     {
       
   414         changeMapType(MapModel::StaticMap, m_staticMapModel->index(m_staticMapModel->findMap(map), 0));
       
   415     }
       
   416     else if (m_missionMapModel->mapExists(map))
       
   417     {
       
   418         changeMapType(MapModel::MissionMap, m_missionMapModel->index(m_missionMapModel->findMap(map), 0));
       
   419     } else
       
   420     {
       
   421         qDebug() << "HWMapContainer::intSetMap: Map doesn't exist: " << map;
       
   422     }
   403 }
   423 }
   404 
   424 
   405 void HWMapContainer::setMap(const QString & map)
   425 void HWMapContainer::setMap(const QString & map)
   406 {
   426 {
   407     if ((m_mapInfo.type == MapModel::Invalid) || (map != m_mapInfo.name))
   427     if ((m_mapInfo.type == MapModel::Invalid) || (map != m_mapInfo.name))
   411 void HWMapContainer::setTheme(const QString & theme)
   431 void HWMapContainer::setTheme(const QString & theme)
   412 {
   432 {
   413     QModelIndexList mdl = m_themeModel->match(m_themeModel->index(0), Qt::DisplayRole, theme);
   433     QModelIndexList mdl = m_themeModel->match(m_themeModel->index(0), Qt::DisplayRole, theme);
   414 
   434 
   415     if(mdl.size())
   435     if(mdl.size())
   416         lvThemes->setCurrentIndex(mdl.at(0));
   436         updateTheme(mdl.at(0));
   417 }
   437 }
   418 
   438 
   419 void HWMapContainer::setRandomMap()
   439 void HWMapContainer::setRandomMap()
   420 {
   440 {
   421     int idx;
       
   422 
       
   423     setRandomSeed();
   441     setRandomSeed();
   424     switch(m_mapInfo.type)
   442     switch(m_mapInfo.type)
   425     {
   443     {
   426         case MapModel::GeneratedMap:
   444         case MapModel::GeneratedMap:
   427         case MapModel::GeneratedMaze:
   445         case MapModel::GeneratedMaze:
   428             setRandomTheme();
   446             setRandomTheme();
   429             break;
   447             break;
   430         case MapModel::HandDrawnMap:
       
   431             emit drawMapRequested();
       
   432             break;
       
   433         case MapModel::MissionMap:
   448         case MapModel::MissionMap:
       
   449             missionMapChanged(m_missionMapModel->index(rand() % m_missionMapModel->rowCount(), 0));
       
   450             break;
   434         case MapModel::StaticMap:
   451         case MapModel::StaticMap:
   435             // get random map of same type
   452             staticMapChanged(m_staticMapModel->index(rand() % m_staticMapModel->rowCount(), 0));
   436             idx = m_mapModel->randomMap(m_mapInfo.type);
   453             break;
   437             mapChanged(idx);
   454         default:
   438             break;
   455             break;
   439         case MapModel::Invalid:
       
   440             mapChanged(0);
       
   441     }
   456     }
   442 }
   457 }
   443 
   458 
   444 
   459 
   445 void HWMapContainer::setRandomSeed()
   460 void HWMapContainer::setRandomSeed()
   450 
   465 
   451 void HWMapContainer::setRandomTheme()
   466 void HWMapContainer::setRandomTheme()
   452 {
   467 {
   453     if(!m_themeModel->rowCount()) return;
   468     if(!m_themeModel->rowCount()) return;
   454     quint32 themeNum = rand() % m_themeModel->rowCount();
   469     quint32 themeNum = rand() % m_themeModel->rowCount();
   455     lvThemes->setCurrentIndex(m_themeModel->index(themeNum));
   470     updateTheme(m_themeModel->index(themeNum));
   456 }
   471 }
   457 
   472 
   458 void HWMapContainer::intSetTemplateFilter(int filter)
   473 void HWMapContainer::intSetTemplateFilter(int filter)
   459 {
   474 {
   460     cbTemplateFilter->setCurrentIndex(filter);
   475     generationStyles->setCurrentRow(filter);
   461     emit newTemplateFilter(filter);
   476     emit newTemplateFilter(filter);
   462 }
   477 }
   463 
   478 
   464 void HWMapContainer::setTemplateFilter(int filter)
   479 void HWMapContainer::setTemplateFilter(int filter)
   465 {
   480 {
   473     return mapgen;
   488     return mapgen;
   474 }
   489 }
   475 
   490 
   476 int HWMapContainer::getMazeSize(void) const
   491 int HWMapContainer::getMazeSize(void) const
   477 {
   492 {
   478     return cbMazeSize->currentIndex();
   493     return mazeStyles->currentRow();
   479 }
   494 }
   480 
   495 
   481 void HWMapContainer::intSetMazeSize(int size)
   496 void HWMapContainer::intSetMazeSize(int size)
   482 {
   497 {
   483     cbMazeSize->setCurrentIndex(size);
   498     mazeStyles->setCurrentRow(size);
   484     emit mazeSizeChanged(size);
   499     emit mazeSizeChanged(size);
   485 }
   500 }
   486 
   501 
   487 void HWMapContainer::setMazeSize(int size)
   502 void HWMapContainer::setMazeSize(int size)
   488 {
   503 {
   519                         break;
   534                         break;
   520                 }
   535                 }
   521                 break;
   536                 break;
   522         }
   537         }
   523 
   538 
   524         if(m != MAPGEN_MAP)
       
   525             chooseMap->setCurrentIndex(m);
       
   526 
       
   527         emit mapgenChanged(m);
   539         emit mapgenChanged(m);
   528     }
   540     }
   529 }
   541 }
   530 
   542 
   531 void HWMapContainer::setMapgen(MapGenerator m)
   543 void HWMapContainer::setMapgen(MapGenerator m)
   544 QByteArray HWMapContainer::getDrawnMapData()
   556 QByteArray HWMapContainer::getDrawnMapData()
   545 {
   557 {
   546     return drawMapScene.encode();
   558     return drawMapScene.encode();
   547 }
   559 }
   548 
   560 
   549 void HWMapContainer::seedEdited()
   561 void HWMapContainer::setNewSeed(const QString & newSeed)
   550 {
   562 {
   551     if (seedLabel->isVisible() == false )
   563     setSeed(newSeed);
   552     {
   564     emit seedChanged(newSeed);
   553         seedLabel->setVisible(true);
       
   554         seedEdit->setVisible(true);
       
   555         seedSet->setText(tr("Set"));
       
   556         return;
       
   557     }
       
   558 
       
   559     if (seedEdit->text().isEmpty())
       
   560         seedEdit->setText(m_seed);
       
   561     else
       
   562     {
       
   563         setSeed(seedEdit->text());
       
   564         emit seedChanged(seedEdit->text());
       
   565     }
       
   566 }
   565 }
   567 
   566 
   568 DrawMapScene * HWMapContainer::getDrawMapScene()
   567 DrawMapScene * HWMapContainer::getDrawMapScene()
   569 {
   568 {
   570     return &drawMapScene;
   569     return &drawMapScene;
   590 
   589 
   591     switch(m_mapInfo.type)
   590     switch(m_mapInfo.type)
   592     {
   591     {
   593         case MapModel::Invalid:
   592         case MapModel::Invalid:
   594             failIcon = QPixmap(":/res/btnDisabled.png");
   593             failIcon = QPixmap(":/res/btnDisabled.png");
   595             imageButt->setIcon(failIcon);
   594             mapPreview->setPixmap(failIcon);
   596             imageButt->setIconSize(failIcon.size());
       
   597             break;
   595             break;
   598         case MapModel::GeneratedMap:
   596         case MapModel::GeneratedMap:
   599             askForGeneratedPreview();
   597             askForGeneratedPreview();
   600             break;
   598             break;
   601         case MapModel::GeneratedMaze:
   599         case MapModel::GeneratedMaze:
   608             QPixmap mapImage;
   606             QPixmap mapImage;
   609             bool success = mapImage.load("physfs://Maps/" + m_mapInfo.name + "/preview.png");
   607             bool success = mapImage.load("physfs://Maps/" + m_mapInfo.name + "/preview.png");
   610 
   608 
   611             if(!success)
   609             if(!success)
   612             {
   610             {
   613                 imageButt->setIcon(QIcon());
   611                 mapPreview->setPixmap(QPixmap());
   614                 return;
   612                 return;
   615             }
   613             }
   616 
   614 
   617             hhLimit = m_mapInfo.limit;
   615             hhLimit = m_mapInfo.limit;
   618             addInfoToPreview(mapImage);
   616             addInfoToPreview(mapImage);
   636     // do this before map selection restore, because map may overwrite theme
   634     // do this before map selection restore, because map may overwrite theme
   637     if (!m_theme.isEmpty())
   635     if (!m_theme.isEmpty())
   638     {
   636     {
   639         QModelIndexList mdl = m_themeModel->match(m_themeModel->index(0), Qt::DisplayRole, m_theme);
   637         QModelIndexList mdl = m_themeModel->match(m_themeModel->index(0), Qt::DisplayRole, m_theme);
   640         if (mdl.size() > 0)
   638         if (mdl.size() > 0)
   641             lvThemes->setCurrentIndex(mdl.at(0));
   639             updateTheme(mdl.at(0));
   642         else
   640         else
   643             setRandomTheme();
   641             setRandomTheme();
   644     }
   642     }
   645 
   643 
   646     // restore map selection
   644     // restore map selection
   647     if ((!m_curMap.isEmpty()) && (chooseMap->currentIndex() < 0))
   645     if (!m_curMap.isEmpty())
   648         intSetMap(m_curMap);
   646         intSetMap(m_curMap);
   649     else
   647     else
   650         updatePreview();
   648         updatePreview();
   651 }
   649 }
   652 
   650 
   654 void HWMapContainer::onPreviewMapDestroyed(QObject * map)
   652 void HWMapContainer::onPreviewMapDestroyed(QObject * map)
   655 {
   653 {
   656     if (map == pMap)
   654     if (map == pMap)
   657         pMap = 0;
   655         pMap = 0;
   658 }
   656 }
       
   657 
       
   658 void HWMapContainer::mapTypeChanged(int index)
       
   659 {
       
   660     changeMapType((MapModel::MapType)cType->itemData(index).toInt());
       
   661 }
       
   662 
       
   663 void HWMapContainer::changeMapType(MapModel::MapType type, const QModelIndex & newMap)
       
   664 {
       
   665     staticMapList->hide();
       
   666     missionMapList->hide();
       
   667     lblMapList->hide();
       
   668     generationStyles->hide();
       
   669     mazeStyles->hide();
       
   670     lblDesc->hide();
       
   671     btnTheme->hide();
       
   672     btnLoadMap->hide();
       
   673     btnEditMap->hide();
       
   674     btnRandomize->hide();
       
   675 
       
   676     switch (type)
       
   677     {
       
   678         case MapModel::GeneratedMap:
       
   679             mapgen = MAPGEN_REGULAR;
       
   680             setMapInfo(MapModel::MapInfoRandom);
       
   681             lblMapList->setText(tr("Map size:"));
       
   682             lblMapList->show();
       
   683             generationStyles->show();
       
   684             btnRandomize->show();
       
   685             btnTheme->show();
       
   686             break;
       
   687         case MapModel::GeneratedMaze:
       
   688             mapgen = MAPGEN_MAZE;
       
   689             setMapInfo(MapModel::MapInfoMaze);
       
   690             lblMapList->setText(tr("Maze style:"));
       
   691             lblMapList->show();
       
   692             mazeStyles->show();
       
   693             btnRandomize->show();
       
   694             btnTheme->show();
       
   695             break;
       
   696         case MapModel::HandDrawnMap:
       
   697             mapgen = MAPGEN_DRAWN;
       
   698             setMapInfo(MapModel::MapInfoDrawn);
       
   699             btnTheme->show();
       
   700             btnLoadMap->show();
       
   701             btnEditMap->show();
       
   702             break;
       
   703         case MapModel::MissionMap:
       
   704             mapgen = MAPGEN_MAP;
       
   705             missionMapChanged(newMap.isValid() ? newMap : missionMapList->currentIndex());
       
   706             lblMapList->setText(tr("Mission:"));
       
   707             lblMapList->show();
       
   708             missionMapList->show();
       
   709             lblDesc->setText(m_mapInfo.desc);
       
   710             lblDesc->show();
       
   711             btnRandomize->show();
       
   712             emit mapChanged(m_curMap);
       
   713             break;
       
   714         case MapModel::StaticMap:
       
   715             mapgen = MAPGEN_MAP;
       
   716             staticMapChanged(newMap.isValid() ? newMap : staticMapList->currentIndex());
       
   717             lblMapList->setText(tr("Map:"));
       
   718             lblMapList->show();
       
   719             staticMapList->show();
       
   720             btnRandomize->show();
       
   721             emit mapChanged(m_curMap);
       
   722             break;
       
   723         default:
       
   724             break;
       
   725     }
       
   726 
       
   727     // Update cType combobox
       
   728     for (int i = 0; i < cType->count(); i++)
       
   729     {
       
   730         if ((MapModel::MapType)cType->itemData(i).toInt() == type)
       
   731         {
       
   732             cType->setCurrentIndex(i);
       
   733             break;
       
   734         }
       
   735     }
       
   736 
       
   737     emit mapgenChanged(mapgen);
       
   738 }
       
   739 
       
   740 void HWMapContainer::showThemePrompt()
       
   741 {
       
   742     ThemePrompt prompt(this);
       
   743     int theme = prompt.exec() - 1; // Since 0 means canceled, so all indexes are +1'd
       
   744     if (theme < 0) return;
       
   745 
       
   746     QModelIndex current = m_themeModel->index(theme, 0);
       
   747     updateTheme(current);
       
   748     
       
   749     emit themeChanged(m_theme);
       
   750 }
       
   751 
       
   752 void HWMapContainer::updateTheme(const QModelIndex & current)
       
   753 {
       
   754     m_theme = selectedTheme = current.data().toString();
       
   755     QIcon icon = qVariantValue<QIcon>(current.data(Qt::UserRole));
       
   756     QSize iconSize = icon.actualSize(QSize(65535, 65535));
       
   757     btnTheme->setFixedHeight(iconSize.height());
       
   758     btnTheme->setIconSize(iconSize);
       
   759     btnTheme->setIcon(icon);
       
   760     btnTheme->setText(tr("Theme: ") + current.data(Qt::DisplayRole).toString());
       
   761     emit themeChanged(m_theme);
       
   762 }
       
   763 
       
   764 void HWMapContainer::staticMapChanged(const QModelIndex & map, const QModelIndex & old)
       
   765 {
       
   766     mapChanged(map, 0, old);
       
   767 }
       
   768 
       
   769 void HWMapContainer::missionMapChanged(const QModelIndex & map, const QModelIndex & old)
       
   770 {
       
   771     mapChanged(map, 1, old);
       
   772 }
       
   773 
       
   774 // Type: 0 = static, 1 = mission
       
   775 void HWMapContainer::mapChanged(const QModelIndex & map, int type, const QModelIndex & old)
       
   776 {
       
   777     QListView * mapList;
       
   778 
       
   779     if (type == 0)      mapList = staticMapList;
       
   780     else if (type == 1) mapList = missionMapList;
       
   781     else                return;
       
   782 
       
   783     // Make sure it is a valid index
       
   784     if (!map.isValid())
       
   785     {
       
   786         if (old.isValid())
       
   787         {
       
   788             mapList->setCurrentIndex(old);
       
   789             mapList->scrollTo(old);
       
   790         }
       
   791         else
       
   792         {
       
   793             m_mapInfo.type = MapModel::Invalid;
       
   794             updatePreview();
       
   795         }
       
   796 
       
   797         return;
       
   798     }
       
   799 
       
   800     // If map changed, update list selection
       
   801     if (mapList->currentIndex() != map)
       
   802     {
       
   803         mapList->setCurrentIndex(map);
       
   804         mapList->scrollTo(map);
       
   805     }
       
   806 
       
   807     if (map.data(Qt::UserRole + 1).canConvert<MapModel::MapInfo>())
       
   808         setMapInfo(map.data(Qt::UserRole + 1).value<MapModel::MapInfo>());
       
   809     else
       
   810         Q_ASSERT(false); // Houston, we have a problem.
       
   811 
       
   812 }
       
   813 
       
   814 void HWMapContainer::setMapInfo(MapModel::MapInfo mapInfo)
       
   815 {
       
   816     m_mapInfo = mapInfo;
       
   817     m_curMap = m_mapInfo.name;
       
   818     m_theme = m_mapInfo.theme;
       
   819 
       
   820     // the map has no pre-defined theme, so let's use the selected one
       
   821     if (m_mapInfo.theme.isEmpty())
       
   822     {
       
   823         m_theme = selectedTheme;
       
   824         emit themeChanged(m_theme);
       
   825     }
       
   826 
       
   827     lblDesc->setText(mapInfo.desc);
       
   828 
       
   829     updatePreview();
       
   830     emit mapChanged(m_curMap);
       
   831 }
       
   832 
       
   833 void HWMapContainer::loadDrawing()
       
   834 {
       
   835 
       
   836 
       
   837     QString fileName = QFileDialog::getOpenFileName(NULL, tr("Load drawn map"), ".", tr("Drawn Maps") + " (*.hwmap);;" + tr("All files") + " (*)");
       
   838 
       
   839     if(fileName.isEmpty()) return;
       
   840 
       
   841 
       
   842 
       
   843     QFile f(fileName);
       
   844 
       
   845     if(!f.open(QIODevice::ReadOnly))
       
   846     {
       
   847         QMessageBox errorMsg(parentWidget());
       
   848         errorMsg.setIcon(QMessageBox::Warning);
       
   849         errorMsg.setWindowTitle(QMessageBox::tr("File error"));
       
   850         errorMsg.setText(QMessageBox::tr("Cannot open '%1' for reading").arg(fileName));
       
   851         errorMsg.setWindowModality(Qt::WindowModal);
       
   852         errorMsg.exec();
       
   853     }
       
   854     else
       
   855     {
       
   856         drawMapScene.decode(qUncompress(QByteArray::fromBase64(f.readAll())));
       
   857         mapDrawingFinished();
       
   858     }
       
   859 }
       
   860 
       
   861 void HWMapContainer::showSeedPrompt()
       
   862 {
       
   863     SeedPrompt prompt(parentWidget()->parentWidget(), getCurrentSeed(), isMaster());
       
   864     connect(&prompt, SIGNAL(seedSelected(const QString &)), this, SLOT(setNewSeed(const QString &)));
       
   865     prompt.exec();
       
   866 }
       
   867 
       
   868 bool HWMapContainer::isMaster()
       
   869 {
       
   870     return m_master;
       
   871 }
       
   872 
       
   873 void HWMapContainer::setMaster(bool master)
       
   874 {
       
   875     if (master == m_master) return;
       
   876     m_master = master;
       
   877     
       
   878     foreach (QWidget *widget, m_childWidgets)
       
   879         widget->setEnabled(master);
       
   880 }