Hat selection reworked
authordag10
Sun, 13 Jan 2013 10:46:01 +0400
changeset 8374 3a1708759c4f
parent 8372 3c193ec03e09
child 8375 af2d2f56bc45
Hat selection reworked
QTfrontend/hedgewars.qrc
QTfrontend/model/HatModel.cpp
QTfrontend/model/HatModel.h
QTfrontend/res/css/qt.css
QTfrontend/res/inverse-corner-bl.png
QTfrontend/ui/page/pageeditteam.cpp
QTfrontend/ui/page/pageeditteam.h
QTfrontend/ui/widget/hatbutton.cpp
QTfrontend/ui/widget/hatbutton.h
QTfrontend/ui/widget/hatprompt.cpp
QTfrontend/ui/widget/hatprompt.h
QTfrontend/ui/widget/lineeditcursor.cpp
QTfrontend/ui/widget/lineeditcursor.h
project_files/hedgewars.pro
--- a/QTfrontend/hedgewars.qrc	Sun Jan 13 01:02:08 2013 +0400
+++ b/QTfrontend/hedgewars.qrc	Sun Jan 13 10:46:01 2013 +0400
@@ -103,6 +103,7 @@
         <file>res/iconRope.png</file>
         <file>res/dice.png</file>
         <file>res/Star.png</file>
+        <file>res/inverse-corner-bl.png</file>
         <file>res/Flake.png</file>
         <file>res/Egg.png</file>
         <file>res/Confetti.png</file>
--- a/QTfrontend/model/HatModel.cpp	Sun Jan 13 01:02:08 2013 +0400
+++ b/QTfrontend/model/HatModel.cpp	Sun Jan 13 10:46:01 2013 +0400
@@ -26,26 +26,28 @@
 #include <QDir>
 #include <QPixmap>
 #include <QPainter>
+#include <QList>
 #include "hwform.h" // player hash
 
 #include "DataManager.h"
 
 HatModel::HatModel(QObject* parent) :
-    QAbstractListModel(parent)
-{
-    hats = QVector<QPair<QString, QIcon> >();
-}
+    QStandardItemModel(parent)
+{}
 
 void HatModel::loadHats()
 {
     // this method resets the contents of this model (important to know for views).
-    beginResetModel();
+    QStandardItemModel::beginResetModel();
+    QStandardItemModel::clear();
 
-    // prepare hats Vector
-    hats.clear();
+    // New hats to add to model
+    QList<QStandardItem *> hats;
 
+    // we'll need the DataManager a few times, so let's get a reference to it
     DataManager & dataMgr = DataManager::instance();
 
+    // Default hat icon
     QPixmap hhpix = QPixmap("physfs://Graphics/Hedgehog/Idle.png").copy(0, 0, 32, 32);
 
     // my reserved hats
@@ -54,7 +56,6 @@
                                QDir::Files,
                                QStringList(playerHash+"*.png")
                            );
-
     int nReserved = hatsList.size();
 
     // regular hats
@@ -64,14 +65,15 @@
                         QStringList("*.png")
                     )
                    );
-
-
     int nHats = hatsList.size();
 
+    // Add each hat
     for (int i = 0; i < nHats; i++)
     {
         bool isReserved = (i < nReserved);
 
+        if (isReserved) continue; // For some reason, reserved hats were added in 9.19-dev, so this will hide them. Uncomment to show them.
+
         QString str = hatsList.at(i);
         str = str.remove(QRegExp("\\.png$"));
         QPixmap pix(            
@@ -94,51 +96,11 @@
         painter.end();
 
         if (str == "NoHat")
-            hats.prepend(qMakePair(str, QIcon(tmppix)));
+            hats.prepend(new QStandardItem(QIcon(tmppix), str));
         else
-            hats.append(qMakePair(str, QIcon(tmppix)));
+            hats.append(new QStandardItem(QIcon(tmppix), str));
     }
 
-
-    endResetModel();
-}
-
-QVariant HatModel::headerData(int section,
-                               Qt::Orientation orientation, int role) const
-{
-    Q_UNUSED(section);
-    Q_UNUSED(orientation);
-    Q_UNUSED(role);
-
-    return QVariant();
-}
-
-int HatModel::rowCount(const QModelIndex &parent) const
-{
-    if (parent.isValid())
-        return 0;
-    else
-        return hats.size();
-}
-
-/*int HatModel::columnCount(const QModelIndex & parent) const
-{
-    if (parent.isValid())
-        return 0;
-    else
-        return 2;
-}
-*/
-QVariant HatModel::data(const QModelIndex &index,
-                         int role) const
-{
-    if (!index.isValid() || index.row() < 0
-            || index.row() >= hats.size()
-            || (role != Qt::DisplayRole && role != Qt::DecorationRole))
-        return QVariant();
-
-    if (role == Qt::DisplayRole)
-        return hats.at(index.row()).first;
-    else // role == Qt::DecorationRole
-        return hats.at(index.row()).second;
-}
+    QStandardItemModel::appendColumn(hats);
+    QStandardItemModel::endResetModel();
+}
\ No newline at end of file
--- a/QTfrontend/model/HatModel.h	Sun Jan 13 01:02:08 2013 +0400
+++ b/QTfrontend/model/HatModel.h	Sun Jan 13 10:46:01 2013 +0400
@@ -24,30 +24,22 @@
 #ifndef HEDGEWARS_HATMODEL_H
 #define HEDGEWARS_HATMODEL_H
 
-#include <QAbstractListModel>
+#include <QStandardItemModel>
 #include <QStringList>
 #include <QVector>
 #include <QPair>
 #include <QIcon>
 
-class HatModel : public QAbstractListModel
+class HatModel : public QStandardItemModel
 {
         Q_OBJECT
 
     public:
         HatModel(QObject *parent = 0);
 
-        QVariant headerData(int section, Qt::Orientation orientation, int role) const;
-        int rowCount(const QModelIndex & parent) const;
-        //int columnCount(const QModelIndex & parent) const;
-
     public slots:
         /// Reloads hats using the DataManager.
         void loadHats();
-
-        QVariant data(const QModelIndex &index, int role) const;
-    protected:
-        QVector<QPair<QString, QIcon> > hats;
 };
 
 #endif // HEDGEWARS_HATMODEL_H
--- a/QTfrontend/res/css/qt.css	Sun Jan 13 01:02:08 2013 +0400
+++ b/QTfrontend/res/css/qt.css	Sun Jan 13 10:46:01 2013 +0400
@@ -246,3 +246,42 @@
 width: 8px;
 }
 
+HatButton {
+text-align: left;
+}
+
+#hatList, #hatList:hover {
+border-color: #F6CB1C;
+}
+
+#hatList QScrollBar {
+background-color: #130F2A;
+border-top-right-radius: 10px;
+border-bottom-right-radius: 10px;
+}
+
+#hatList {
+border-color: #F6CB1C;
+border-width: 3px;
+border-style: solid;
+border-radius: 10px;
+border-top-left-radius: 0px;
+}
+
+#hatList::item {
+background-color: #11084A;
+padding: 4px;
+border-radius: 10px;
+color: #ffcc00 !important;
+font: 8px;
+border-width: 2px;
+border-color: #11084A;
+}
+
+#hatList::item:hover {
+background-color: #150A61;
+}
+
+#hatList::item:selected {
+background-color: #150A61;
+}
\ No newline at end of file
Binary file QTfrontend/res/inverse-corner-bl.png has changed
--- a/QTfrontend/ui/page/pageeditteam.cpp	Sun Jan 13 01:02:08 2013 +0400
+++ b/QTfrontend/ui/page/pageeditteam.cpp	Sun Jan 13 10:46:01 2013 +0400
@@ -33,7 +33,7 @@
 #include "keybinder.h"
 
 #include "DataManager.h"
-#include "HatModel.h"
+#include "hatbutton.h"
 
 #include "pageeditteam.h"
 
@@ -64,25 +64,32 @@
 
     HatModel * hatModel = DataManager::instance().hatModel();
 
+    GBHLayout->addWidget(new QLabel(tr("Hat")), 0, 0);
+    GBHLayout->addWidget(new QLabel(tr("Name")), 0, 1);
+
     for(int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
     {
-        HHHats[i] = new QComboBox(GBoxHedgehogs);
-        HHHats[i]->setModel(hatModel);
-        HHHats[i]->setIconSize(QSize(32, 37));
-        //HHHats[i]->setSizeAdjustPolicy(QComboBox::AdjustToContents);
-        //HHHats[i]->setModelColumn(1);
-        //HHHats[i]->setMinimumWidth(132);
-        GBHLayout->addWidget(HHHats[i], i, 0);
+        HHHats[i] = new HatButton(GBoxHedgehogs);
+        GBHLayout->addWidget(HHHats[i], i + 1, 0);
 
         HHNameEdit[i] = new QLineEdit(GBoxHedgehogs);
         HHNameEdit[i]->setMaxLength(64);
         HHNameEdit[i]->setMinimumWidth(120);
-        GBHLayout->addWidget(HHNameEdit[i], i, 1);
+        HHNameEdit[i]->setFixedHeight(36);
+        HHNameEdit[i]->setWhatsThis(tr("This hedgehog's name"));
+        HHNameEdit[i]->setStyleSheet("padding: 6px;");
+        GBHLayout->addWidget(HHNameEdit[i], i + 1, 1);
 
-        btnRandomHogName[i] = addButton(":/res/dice.png", GBHLayout, i, 3, 1, 1, true);
+        btnRandomHogName[i] = addButton(":/res/dice.png", GBHLayout, i + 1, 3, 1, 1, true);
+        btnRandomHogName[i]->setFixedHeight(HHNameEdit[i]->height());
+        btnRandomHogName[i]->setWhatsThis(tr("Randomize this hedgehog's name"));
     }
 
-    btnRandomTeam = addButton(QPushButton::tr("Random Team"), GBHLayout, 9, 0);
+    btnRandomTeam = new QPushButton();
+    btnRandomTeam->setText(tr("Random Team"));
+    btnRandomTeam->setStyleSheet("padding: 6px 10px;");
+    GBHLayout->addWidget(btnRandomTeam, 9, 0, 1, 4, Qt::AlignCenter);
+    btnRandomTeam->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
 
     vbox1->addWidget(GBoxHedgehogs);
 
@@ -377,7 +384,7 @@
         if (hh.Hat.startsWith("Reserved"))
             hh.Hat = "Reserved "+hh.Hat.remove(0,40);
 
-        HHHats[i]->setCurrentIndex(HHHats[i]->findData(hh.Hat, Qt::DisplayRole));
+        HHHats[i]->setCurrentHat(hh.Hat);
     }
 
     CBGrave->setCurrentIndex(CBGrave->findText(team.grave()));
@@ -409,7 +416,7 @@
     {
         HWHog hh;
         hh.Name = HHNameEdit[i]->text();
-        hh.Hat = HHHats[i]->currentText();
+        hh.Hat = HHHats[i]->currentHat();
 
         if (hh.Hat.startsWith("Reserved"))
             hh.Hat = "Reserved"+m_playerHash+hh.Hat.remove(0,9);
--- a/QTfrontend/ui/page/pageeditteam.h	Sun Jan 13 01:02:08 2013 +0400
+++ b/QTfrontend/ui/page/pageeditteam.h	Sun Jan 13 10:46:01 2013 +0400
@@ -29,6 +29,7 @@
 
 class SquareLabel;
 class KeyBinder;
+class HatButton;
 
 class PageEditTeam : public AbstractPage
 {
@@ -61,7 +62,7 @@
         QToolBox *BindsBox;
         QLineEdit * TeamNameEdit;
         QLineEdit * HHNameEdit[HEDGEHOGS_PER_TEAM];
-        QComboBox * HHHats[HEDGEHOGS_PER_TEAM];
+        HatButton * HHHats[HEDGEHOGS_PER_TEAM];
         HWTeam data();
         QString m_playerHash;
         KeyBinder * binder;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/hatbutton.cpp	Sun Jan 13 10:46:01 2013 +0400
@@ -0,0 +1,72 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <QDebug>
+
+#include "hatprompt.h"
+#include "DataManager.h"
+#include "hatmodel.h"
+#include "hatbutton.h"
+
+HatButton::HatButton(QWidget* parent) : QPushButton(parent)
+{
+	setIconSize(QSize(32, 37));
+	setFixedSize(44, 44);
+
+	m_hatModel = DataManager::instance().hatModel();
+	connect(this, SIGNAL(clicked()), this, SLOT(showPrompt()));
+
+	setCurrentIndex(0);
+}
+
+void HatButton::setCurrentIndex(int index)
+{
+	m_hat = m_hatModel->index(index, 0);
+	setWhatsThis(QString(tr("Change hat (%1)")).arg(m_hat.data(Qt::DisplayRole).toString()));
+	setToolTip(m_hat.data(Qt::DisplayRole).toString());
+	setIcon(m_hat.data(Qt::DecorationRole).value<QIcon>());
+}
+
+int HatButton::currentIndex()
+{
+	return m_hat.row();
+}
+
+void HatButton::setCurrentHat(const QString & name)
+{
+	QList<QStandardItem *> hats = m_hatModel->findItems(name);
+
+	if (hats.count() > 0)
+		setCurrentIndex(hats[0]->row());
+}
+
+QString HatButton::currentHat() const
+{
+	return m_hat.data(Qt::DisplayRole).toString();
+}
+
+void HatButton::showPrompt()
+{
+	HatPrompt prompt(currentIndex(), this);
+	int hatID = prompt.exec() - 1; // Since 0 means canceled, so all indexes are +1'd
+	if (hatID < 0) return;
+
+	setCurrentIndex(hatID);
+	emit currentIndexChanged(hatID);
+	emit currentHatChanged(currentHat());
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/hatbutton.h	Sun Jan 13 10:46:01 2013 +0400
@@ -0,0 +1,55 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef HATBUTTON_H
+#define HATBUTTON_H
+
+#include <QPushButton>
+#include <QString>
+#include <QModelIndex>
+
+class HatModel;
+
+class HatButton : public QPushButton
+{
+        Q_OBJECT
+        Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex)
+        Q_PROPERTY(QString currentHat READ currentHat WRITE setCurrentHat)
+
+    public:
+        HatButton(QWidget* parent);
+        int currentIndex();
+        QString currentHat() const;
+
+    private:
+    	QModelIndex m_hat;
+    	HatModel * m_hatModel;
+
+    signals:
+    	void currentIndexChanged(int);
+    	void currentHatChanged(const QString &);
+
+    public slots:
+    	void setCurrentIndex(int index);
+    	void setCurrentHat(const QString & name);
+
+    private slots:
+        void showPrompt();
+};
+
+#endif // HATBUTTON_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/hatprompt.cpp	Sun Jan 13 10:46:01 2013 +0400
@@ -0,0 +1,169 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <QDialog>
+#include <QGridLayout>
+#include <QHBoxLayout>
+#include <QScrollArea>
+#include <QPushButton>
+#include <QToolButton>
+#include <QWidgetItem>
+#include <QModelIndex>
+#include <QListView>
+#include <QLineEdit>
+#include <QLabel>
+#include <QSortFilterProxyModel>
+#include <QDebug>
+
+#include "datamanager.h"
+#include "lineeditcursor.h"
+#include "hatmodel.h"
+#include "hatprompt.h"
+
+HatPrompt::HatPrompt(int currentIndex, QWidget* parent) : QDialog(parent)
+{
+	setModal(true);
+	setWindowFlags(Qt::Sheet);
+	setWindowModality(Qt::WindowModal);
+	setMinimumSize(550, 430);
+	resize(550, 430);
+	setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+
+	setStyleSheet("QPushButton { padding: 5px; margin-top: 10px; }");
+
+	// Hat model, and a model for setting a filter
+	HatModel * hatModel = DataManager::instance().hatModel();
+	filterModel = new QSortFilterProxyModel();
+	filterModel->setSourceModel(hatModel);
+	filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
+
+	// Grid
+	QGridLayout * dialogLayout = new QGridLayout(this);
+	dialogLayout->setSpacing(0);
+	dialogLayout->setColumnStretch(1, 1);
+
+	QHBoxLayout * topLayout = new QHBoxLayout();
+
+	// Help/prompt message at top
+	QLabel * lblDesc = new QLabel(tr("Select a hat"));
+	lblDesc->setObjectName("lblDesc");
+    lblDesc->setStyleSheet("#lblDesc { color: #130F2A; background: #F6CB1C; border: solid 4px #F6CB1C; border-top-left-radius: 10px; padding: 4px 10px;}");
+    lblDesc->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+    lblDesc->setFixedHeight(24);
+    lblDesc->setMinimumWidth(0);
+
+    // Filter text box
+    QWidget * filterContainer = new QWidget();
+    filterContainer->setFixedHeight(24);
+    filterContainer->setObjectName("filterContainer");
+    filterContainer->setStyleSheet("#filterContainer { background: #F6CB1C; border-top-right-radius: 10px; padding: 3px; }");
+    filterContainer->setFixedWidth(250);
+    txtFilter = new LineEditCursor(filterContainer);
+    txtFilter->setFixedWidth(250);
+    txtFilter->setFocus();
+    txtFilter->setFixedHeight(22);
+    connect(txtFilter, SIGNAL(textChanged(const QString &)), this, SLOT(filterChanged(const QString &)));
+    connect(txtFilter, SIGNAL(moveUp()), this, SLOT(moveUp()));
+    connect(txtFilter, SIGNAL(moveDown()), this, SLOT(moveDown()));
+    connect(txtFilter, SIGNAL(moveLeft()), this, SLOT(moveLeft()));
+    connect(txtFilter, SIGNAL(moveRight()), this, SLOT(moveRight()));
+
+    // Filter label
+    QLabel * lblFilter = new QLabel(tr("Filter: "), txtFilter);
+    lblFilter->setStyleSheet(QString("background: none; margin-left: -%1px; margin-top: 4px;").arg(lblFilter->width() / 2 - 3));
+    txtFilter->setStyleSheet(QString("border-width: 0px; background-color: rgb(13, 5, 68); border-radius: 6px; margin-top: 3px; margin-right: 3px; padding-left: %1px; padding-bottom: 2px;").arg(lblFilter->width() / 2));
+
+    // Corner widget
+    QLabel * corner = new QLabel();
+    corner->setPixmap(QPixmap(QString::fromUtf8(":/res/inverse-corner-bl.png")));
+    corner->setFixedSize(10, 10);
+
+    // Add widgets to top layout
+    topLayout->addWidget(lblDesc);
+    topLayout->addWidget(filterContainer);
+    topLayout->addWidget(corner, 0, Qt::AlignBottom);
+    topLayout->addStretch(1);
+
+	// Cancel button (closes dialog)
+	QPushButton * btnCancel = new QPushButton(tr("Cancel"));
+	connect(btnCancel, SIGNAL(clicked()), this, SLOT(reject()));
+
+	// Select button
+	QPushButton * btnSelect = new QPushButton(tr("Use selected hat"));
+	btnSelect->setDefault(true);
+	connect(btnSelect, SIGNAL(clicked()), this, SLOT(onAccepted()));
+
+	// Add hats
+	list = new HatListView();
+	list->setModel(filterModel);
+	list->setViewMode(QListView::IconMode);
+	list->setResizeMode(QListView::Adjust);
+	list->setMovement(QListView::Static);
+	list->setEditTriggers(QAbstractItemView::NoEditTriggers);
+	list->setSpacing(8);
+	list->setWordWrap(true);
+	list->setSelectionMode(QAbstractItemView::SingleSelection);
+	list->setObjectName("hatList");
+	list->setCurrentIndex(filterModel->index(currentIndex, 0));
+	connect(list, SIGNAL(activated(const QModelIndex &)), this, SLOT(hatChosen(const QModelIndex &)));
+	connect(list, SIGNAL(clicked(const QModelIndex &)), this, SLOT(hatChosen(const QModelIndex &)));
+
+	// Add elements to layouts
+	dialogLayout->addLayout(topLayout, 0, 0, 1, 3);
+	dialogLayout->addWidget(list, 1, 0, 1, 3);
+	dialogLayout->addWidget(btnCancel, 2, 0, 1, 1, Qt::AlignLeft);
+	dialogLayout->addWidget(btnSelect, 2, 2, 1, 1, Qt::AlignRight);
+}
+
+void HatPrompt::moveUp()
+{
+	list->setCurrentIndex(list->moveCursor(QAbstractItemView::MoveUp, Qt::NoModifier));
+}
+
+void HatPrompt::moveDown()
+{
+	list->setCurrentIndex(list->moveCursor(QAbstractItemView::MoveDown, Qt::NoModifier));
+}
+
+void HatPrompt::moveLeft()
+{
+	list->setCurrentIndex(list->moveCursor(QAbstractItemView::MoveLeft, Qt::NoModifier));
+}
+
+void HatPrompt::moveRight()
+{
+	list->setCurrentIndex(list->moveCursor(QAbstractItemView::MoveRight, Qt::NoModifier));
+}
+
+void HatPrompt::onAccepted()
+{
+	hatChosen(list->currentIndex());
+}
+
+// When a hat is selected
+void HatPrompt::hatChosen(const QModelIndex & index)
+{
+	done(filterModel->mapToSource(index).row() + 1); // Since returning 0 means canceled
+}
+
+// When the text in the filter text box is changed
+void HatPrompt::filterChanged(const QString & text)
+{
+	filterModel->setFilterFixedString(text);
+	list->setCurrentIndex(filterModel->index(0, 0));
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/hatprompt.h	Sun Jan 13 10:46:01 2013 +0400
@@ -0,0 +1,61 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef HATPROMPT_H
+#define HATPROMPT_H
+
+#include <QWidget>
+#include <QDialog>
+#include <QListView>
+
+class QLineEdit;
+class QModelIndex;
+class QSortFilterProxyModel;
+class LineEditCursor;
+
+class HatListView : public QListView
+{
+	friend class HatPrompt;
+
+	public:
+		HatListView(QWidget* parent = 0) {};
+};
+
+class HatPrompt : public QDialog
+{
+        Q_OBJECT
+
+    public:
+        HatPrompt(int currentIndex = 0, QWidget* parent = 0);
+
+    private:
+        LineEditCursor * txtFilter;
+        HatListView * list;
+        QSortFilterProxyModel * filterModel;
+
+    private slots:
+    	void onAccepted();
+        void hatChosen(const QModelIndex & index);
+        void filterChanged(const QString & text);
+        void moveUp();
+        void moveDown();
+        void moveLeft();
+        void moveRight();
+};
+
+#endif // HATPROMPT_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/lineeditcursor.cpp	Sun Jan 13 10:46:01 2013 +0400
@@ -0,0 +1,35 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <QKeyEvent>
+
+#include "lineeditcursor.h"
+
+void LineEditCursor::keyPressEvent(QKeyEvent * event)
+{
+	if (event->key() == Qt::Key_Up)
+		emit moveUp();
+	else if (event->key() == Qt::Key_Down)
+		emit moveDown();
+	else if (event->key() == Qt::Key_Left)
+		emit moveLeft();
+	else if (event->key() == Qt::Key_Right)
+		emit moveRight();
+	else
+		QLineEdit::keyPressEvent(event);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/lineeditcursor.h	Sun Jan 13 10:46:01 2013 +0400
@@ -0,0 +1,41 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifndef LINEEDITCURSOR_H
+#define LINEEDITCURSOR_H
+
+#include <QLineEdit>
+
+class LineEditCursor : public QLineEdit
+{
+        Q_OBJECT
+
+    public:
+        LineEditCursor(QWidget* parent = 0) : QLineEdit(parent) {};
+
+    signals:
+        void moveUp();
+        void moveDown();
+        void moveLeft();
+        void moveRight();
+
+    private:
+        void keyPressEvent(QKeyEvent * event);
+};
+
+#endif // LINEEDITCURSOR_H
\ No newline at end of file
--- a/project_files/hedgewars.pro	Sun Jan 13 01:02:08 2013 +0400
+++ b/project_files/hedgewars.pro	Sun Jan 13 10:46:01 2013 +0400
@@ -189,6 +189,8 @@
     ../QTfrontend/model/roomslistmodel.cpp \
     ../QTfrontend/ui/dialog/input_password.cpp \
     ../QTfrontend/ui/widget/colorwidget.cpp \
+    ../QTfrontend/ui/widget/hatbutton.cpp \
+    ../QTfrontend/ui/widget/hatprompt.cpp \
     ../QTfrontend/model/HatModel.cpp \
     ../QTfrontend/model/GameStyleModel.cpp \
     ../QTfrontend/ui/page/pagevideos.cpp \