some more cleanups/refactoring/blahblah, some button positions may are a bit off atm. also I added a new picture for one of the buttons
authorsheepluva
Tue, 27 Sep 2011 00:38:39 +0200 (2011-09-26)
changeset 6042 8b5345758f62
parent 6040 a740069c21e3
child 6044 728ce9acbaf7
some more cleanups/refactoring/blahblah, some button positions may are a bit off atm. also I added a new picture for one of the buttons
QTfrontend/AbstractPage.cpp
QTfrontend/AbstractPage.h
QTfrontend/hedgewars.qrc
QTfrontend/hwform.cpp
QTfrontend/hwform.h
QTfrontend/pageadmin.cpp
QTfrontend/pageadmin.h
QTfrontend/pagecampaign.cpp
QTfrontend/pagecampaign.h
QTfrontend/pageconnecting.cpp
QTfrontend/pageconnecting.h
QTfrontend/pagedata.cpp
QTfrontend/pagedata.h
QTfrontend/pagedrawmap.cpp
QTfrontend/pagedrawmap.h
QTfrontend/pageeditteam.cpp
QTfrontend/pageeditteam.h
QTfrontend/pagegamestats.cpp
QTfrontend/pagegamestats.h
QTfrontend/pageinfo.cpp
QTfrontend/pageinfo.h
QTfrontend/pageingame.cpp
QTfrontend/pageingame.h
QTfrontend/pagemain.cpp
QTfrontend/pagemain.h
QTfrontend/pagemultiplayer.cpp
QTfrontend/pagemultiplayer.h
QTfrontend/pagenet.cpp
QTfrontend/pagenet.h
QTfrontend/pagenetgame.cpp
QTfrontend/pagenetgame.h
QTfrontend/pagenetserver.cpp
QTfrontend/pagenetserver.h
QTfrontend/pagenettype.cpp
QTfrontend/pagenettype.h
QTfrontend/pageoptions.cpp
QTfrontend/pageoptions.h
QTfrontend/pageplayrecord.cpp
QTfrontend/pageplayrecord.h
QTfrontend/pageroomslist.cpp
QTfrontend/pageroomslist.h
QTfrontend/pagescheme.cpp
QTfrontend/pagescheme.h
QTfrontend/pageselectweapon.cpp
QTfrontend/pageselectweapon.h
QTfrontend/pagesingleplayer.cpp
QTfrontend/pagesingleplayer.h
QTfrontend/pagetraining.cpp
QTfrontend/pagetraining.h
QTfrontend/res/Load.png
--- a/QTfrontend/AbstractPage.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/AbstractPage.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -25,9 +25,36 @@
     font14 = new QFont("MS Shell Dlg", 14);
 }
 
+void AbstractPage::initPage()
+{
+    QGridLayout * pageLayout = new QGridLayout(this);
+
+    // stretch grid space for body and footer
+    pageLayout->setColumnStretch(0,0);
+    pageLayout->setColumnStretch(1,1);
+    pageLayout->setRowStretch(0,1);
+    pageLayout->setRowStretch(1,0);
+
+    // add back/exit button
+    btnBack = formattedButton(":/res/Exit.png", true);
+    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, 2);
+
+    // add footer layout
+    QLayout * fld = footerLayoutDefinition();
+    if (fld != NULL)
+        pageLayout->addLayout(fld, 1, 1);
+
+    // connect signals
+    connect(btnBack, SIGNAL(clicked()), this, SIGNAL(goBack()));
+    connectSignals();
+}
+
 QPushButton * AbstractPage::formattedButton(const QString & btname, bool hasIcon)
 {
-    QPushButton* btn = new QPushButton(this);
+    QPushButton * btn = new QPushButton(this);
 
     if (hasIcon)
     {
@@ -49,22 +76,26 @@
 
 QPushButton * AbstractPage::addButton(const QString & btname, QGridLayout* grid, int wy, int wx, bool hasIcon)
 {
-    QPushButton* btn = formattedButton(btname, hasIcon);
+    QPushButton * btn = formattedButton(btname, hasIcon);
     grid->addWidget(btn, wy, wx);
     return btn;
 }
 
 QPushButton * AbstractPage::addButton(const QString & btname, QGridLayout* grid, int wy, int wx, int rowSpan, int columnSpan, bool hasIcon)
 {
-    QPushButton* btn = formattedButton(btname, hasIcon);
+    QPushButton * btn = formattedButton(btname, hasIcon);
     grid->addWidget(btn, wy, wx, rowSpan, columnSpan);
     return btn;
 }
 
 QPushButton * AbstractPage::addButton(const QString & btname, QBoxLayout* box, int where, bool hasIcon)
 {
-    QPushButton* btn = formattedButton(btname, hasIcon);
+    QPushButton * btn = formattedButton(btname, hasIcon);
     box->addWidget(btn, where);
     return btn;
 }
 
+void AbstractPage::setBackButtonVisible(bool visible)
+{
+    btnBack->setVisible(visible);
+}
--- a/QTfrontend/AbstractPage.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/AbstractPage.h	Tue Sep 27 00:38:39 2011 +0200
@@ -56,17 +56,43 @@
 
     protected:
         // constructor and virtual destructor
-        AbstractPage(QWidget* parent = 0);
+        AbstractPage(QWidget * parent = 0);
+
+        // call this in the constructor of your subclass
+        void initPage();
+
+        // the following methods are used during page construction
+
+            // you MUST implement this method in your subclass
+            // only define layout, not behavior in here
+            virtual QLayout * bodyLayoutDefinition() = 0;
+
+            // you CAN implement this method in your subclass
+            virtual QLayout * footerLayoutDefinition() { return NULL; };
+
+            // you CAN but most likely want to implement this method in your subclass
+            // keep in mind not to expose twidgets as public!
+            // instead define a signal with a meaningful name and connect the widget
+            // signals to your page signals
+            virtual void connectSignals() {};
+/*
+virtual QLayout * bodyLayoutDefinition()\n{\n    return new QGridLayout(); //TODO\n}\n\nvirtual QLayout * footerLayoutDefinition()\n{\n    // return NULL;\n}\n\nvirtual void connectSignals()\n{\n    //TODO\n}\n\n
+*/
+
         virtual ~AbstractPage() {};
 
-        QPushButton * addButton(const QString & btname, QGridLayout* grid, int wy, int wx, bool hasIcon = false);
-        QPushButton * addButton(const QString & btname, QGridLayout* grid, int wy, int wx, int rowSpan, int columnSpan, bool hasIcon = false);
-        QPushButton * addButton(const QString & btname, QBoxLayout* box, int where, bool hasIcon = false);
+        QPushButton * addButton(const QString & btname, QGridLayout * grid, int wy, int wx, bool hasIcon = false);
+        QPushButton * addButton(const QString & btname, QGridLayout * grid, int wy, int wx, int rowSpan, int columnSpan, bool hasIcon = false);
+        QPushButton * addButton(const QString & btname, QBoxLayout * box, int where, bool hasIcon = false);
+
+        void setBackButtonVisible(bool visible = true);
 
         QFont * font14;
 
     private:
         QPushButton * formattedButton(const QString & btname, bool hasIcon);
+
+        QPushButton * btnBack;
 };
 
 #endif
--- a/QTfrontend/hedgewars.qrc	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/hedgewars.qrc	Tue Sep 27 00:38:39 2011 +0200
@@ -45,6 +45,7 @@
         <file>res/unchecked.png</file>
         <file>res/graphicsicon.png</file>
         <file>res/miscicon.png</file>
+        <file>res/Load.png</file>
         <file>res/Save.png</file>
         <file>res/Record.png</file>
         <file>res/weaponsicon.png</file>
--- a/QTfrontend/hwform.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/hwform.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -165,8 +165,8 @@
     connect(ui.pageMain->BtnDataDownload, SIGNAL(clicked()), pageSwitchMapper, SLOT(map()));
     pageSwitchMapper->setMapping(ui.pageMain->BtnDataDownload, ID_PAGE_DATADOWNLOAD);
 
-    connect(ui.pageMain->BtnExit, SIGNAL(pressed()), this, SLOT(btnExitPressed()));
-    connect(ui.pageMain->BtnExit, SIGNAL(clicked()), this, SLOT(btnExitClicked()));
+    //connect(ui.pageMain->BtnExit, SIGNAL(pressed()), this, SLOT(btnExitPressed()));
+    //connect(ui.pageMain->BtnExit, SIGNAL(clicked()), this, SLOT(btnExitClicked()));
 
     connect(ui.pageEditTeam, SIGNAL(teamEdited()), this, SLOT(AfterTeamEdit()));
 
@@ -186,8 +186,8 @@
     connect(ui.pageOptions, SIGNAL(newTeamRequested()), this, SLOT(NewTeam()));
     connect(ui.pageOptions, SIGNAL(editTeamRequested(const QString&)), this, SLOT(EditTeam(const QString&)));
     connect(ui.pageOptions, SIGNAL(deleteTeamRequested(const QString&)), this, SLOT(DeleteTeam(const QString&)));
-    connect(ui.pageOptions->BtnSaveOptions, SIGNAL(clicked()), config, SLOT(SaveOptions()));
-    connect(ui.pageOptions->BtnSaveOptions, SIGNAL(clicked()), this, SLOT(GoBack()));
+    connect(ui.pageOptions->btnSave, SIGNAL(clicked()), config, SLOT(SaveOptions()));
+    connect(ui.pageOptions->btnSave, SIGNAL(clicked()), this, SLOT(GoBack()));
     connect(ui.pageOptions->BtnAssociateFiles, SIGNAL(clicked()), this, SLOT(AssociateFiles()));
 
     connect(ui.pageOptions->WeaponEdit, SIGNAL(clicked()), this, SLOT(GoToSelectWeapon()));
@@ -533,8 +533,11 @@
 
 void HWForm::GoBack()
 {
+    int curid = ui.Pages->currentIndex();
+    if (curid == ID_PAGE_MAIN)
+        exit();
+
     int id = PagesStack.isEmpty() ? ID_PAGE_MAIN : PagesStack.pop();
-    int curid = ui.Pages->currentIndex();
     ui.Pages->setCurrentIndex(id);
     OnPageShown(id, curid);
 
@@ -569,14 +572,15 @@
     eggTimer.start();
 }
 
-void HWForm::btnExitClicked()
+void HWForm::exit()
 {
-    if (eggTimer.elapsed() < 3000){
+//   if (eggTimer.elapsed() < 3000){
 #ifdef __APPLE__
         panel->showInstallController();
 #endif
         close();
-    }
+// TODO reactivate egg
+/*    }
     else
     {
         QPushButton * btn = findChild<QPushButton *>("imageButt");
@@ -584,7 +588,7 @@
         {
             btn->setIcon(QIcon(":/res/bonus.png"));
         }
-    }
+    } */
 }
 
 void HWForm::IntermediateSetup()
--- a/QTfrontend/hwform.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/hwform.h	Tue Sep 27 00:38:39 2011 +0200
@@ -59,6 +59,7 @@
     QSettings * gameSettings; // Same file GameUIConfig points to but without the baggage.  Needs sync() calls if you want to get GameUIConfig changes though
     void updateXfire();
     void PlayDemoQuick(const QString & demofilename);
+    void exit();
 
 private slots:
     void GoToSaves();
@@ -76,7 +77,6 @@
     QString getDemoArguments();
     void AssociateFiles();
     void btnExitPressed();
-    void btnExitClicked();
     void IntermediateSetup();
     void NewTeam();
     void EditTeam(const QString & teamName);
--- a/QTfrontend/pageadmin.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pageadmin.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -26,14 +26,12 @@
 #include "pageadmin.h"
 #include "chatwidget.h"
 
-PageAdmin::PageAdmin(QWidget* parent) :
-    AbstractPage(parent)
+QLayout * PageAdmin::bodyLayoutDefinition()
 {
-    QGridLayout * pageLayout = new QGridLayout(this);
+    QGridLayout * pageLayout = new QGridLayout();
 
     // 0
     pbAsk = addButton(tr("Fetch data"), pageLayout, 0, 0, 1, 3);
-    connect(pbAsk, SIGNAL(clicked()), this, SIGNAL(askServerVars()));
     
     // 1
     QLabel * lblSMN = new QLabel(this);
@@ -68,21 +66,28 @@
     tb->setOpenExternalLinks(true);
     tb->document()->setDefaultStyleSheet(HWChatWidget::STYLE);
     pageLayout->addWidget(tb, 4, 1, 1, 2);
-    connect(leServerMessageNew, SIGNAL(textEdited(const QString &)), tb, SLOT(setHtml(const QString &)));
-    connect(leServerMessageOld, SIGNAL(textEdited(const QString &)), tb, SLOT(setHtml(const QString &)));
     
     // 5
     pbClearAccountsCache = addButton(tr("Clear Accounts Cache"), pageLayout, 5, 0);
-    connect(pbClearAccountsCache, SIGNAL(clicked()), this, SIGNAL(clearAccountsCache()));
     
     // 6
     pbSetSM = addButton(tr("Set data"), pageLayout, 6, 0, 1, 3);
-    connect(pbSetSM, SIGNAL(clicked()), this, SLOT(smChanged()));
 
+    return pageLayout;
+}
 
-    // 7
-    BtnBack = addButton(":/res/Exit.png", pageLayout, 7, 0, true);
-    connect(BtnBack, SIGNAL(clicked()), this, SIGNAL(goBack()));
+void PageAdmin::connectSignals()
+{
+    connect(pbAsk, SIGNAL(clicked()), this, SIGNAL(askServerVars()));
+    connect(leServerMessageNew, SIGNAL(textEdited(const QString &)), tb, SLOT(setHtml(const QString &)));
+    connect(leServerMessageOld, SIGNAL(textEdited(const QString &)), tb, SLOT(setHtml(const QString &)));
+    connect(pbClearAccountsCache, SIGNAL(clicked()), this, SIGNAL(clearAccountsCache()));
+    connect(pbSetSM, SIGNAL(clicked()), this, SLOT(smChanged()));
+}
+
+PageAdmin::PageAdmin(QWidget* parent) : AbstractPage(parent)
+{
+    initPage();
 }
 
 void PageAdmin::smChanged()
--- a/QTfrontend/pageadmin.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pageadmin.h	Tue Sep 27 00:38:39 2011 +0200
@@ -28,19 +28,6 @@
 public:
     PageAdmin(QWidget* parent = 0);
 
-private:
-    QLineEdit * leServerMessageNew;
-    QLineEdit * leServerMessageOld;
-    QPushButton * pbSetSM;
-    QPushButton * pbAsk;
-    QSpinBox * sbProtocol;
-    QTextBrowser * tb;
-    QPushButton * BtnBack;
-    QPushButton * pbClearAccountsCache;
-
-private slots:
-    void smChanged();
-
 public slots:
     void serverMessageNew(const QString & str);
     void serverMessageOld(const QString & str);
@@ -52,6 +39,22 @@
     void setProtocol(int proto);
     void askServerVars();
     void clearAccountsCache();
+
+protected:
+    QLayout * bodyLayoutDefinition();
+    void connectSignals();
+
+private:
+    QLineEdit * leServerMessageNew;
+    QLineEdit * leServerMessageOld;
+    QPushButton * pbSetSM;
+    QPushButton * pbAsk;
+    QSpinBox * sbProtocol;
+    QTextBrowser * tb;
+    QPushButton * pbClearAccountsCache;
+
+private slots:
+    void smChanged();
 };
 
 #endif
--- a/QTfrontend/pagecampaign.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagecampaign.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -22,9 +22,9 @@
 
 #include "pagecampaign.h"
 
-PageCampaign::PageCampaign(QWidget* parent) : AbstractPage(parent)
+QLayout * PageCampaign::bodyLayoutDefinition()
 {
-    QGridLayout * pageLayout = new QGridLayout(this);
+    QGridLayout * pageLayout = new QGridLayout();
     pageLayout->setColumnStretch(0, 1);
     pageLayout->setColumnStretch(1, 2);
     pageLayout->setColumnStretch(2, 1);
@@ -42,7 +42,12 @@
     BtnStartCampaign->setText(QPushButton::tr("Go!"));
     pageLayout->addWidget(BtnStartCampaign, 2, 2);
 
+    return pageLayout;
+}
 
-    BtnBack = addButton(":/res/Exit.png", pageLayout, 4, 0, true);
-    connect(BtnBack, SIGNAL(clicked()), this, SIGNAL(goBack()));
+PageCampaign::PageCampaign(QWidget* parent) : AbstractPage(parent)
+{
+    initPage();
 }
+
+
--- a/QTfrontend/pagecampaign.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagecampaign.h	Tue Sep 27 00:38:39 2011 +0200
@@ -32,8 +32,8 @@
     QComboBox   *CBSelect;
     QComboBox   *CBTeam;
 
-private:
-    QPushButton *BtnBack;
+protected:
+    QLayout * bodyLayoutDefinition();
 };
 
 #endif
--- a/QTfrontend/pageconnecting.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pageconnecting.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -16,22 +16,28 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  */
 
-#include <QGridLayout>
+#include <QVBoxLayout>
 #include <QLabel>
 
 #include "pageconnecting.h"
 
-PageConnecting::PageConnecting(QWidget* parent) :
-    AbstractPage(parent)
+QLayout * PageConnecting::bodyLayoutDefinition()
 {
-    QGridLayout * pageLayout = new QGridLayout(this);
+    QVBoxLayout * pageLayout = new QVBoxLayout();
 
     QLabel * lblConnecting = new QLabel(this);
     lblConnecting->setText(tr("Connecting..."));
     pageLayout->addWidget(lblConnecting);
 
-    QPushButton * pbCancel = new QPushButton(this);
-    pbCancel->setText(tr("Cancel"));
-    pageLayout->addWidget(pbCancel);
-    connect(pbCancel, SIGNAL(clicked()), this, SIGNAL(cancelConnection()));
+    return pageLayout;
 }
+
+void PageConnecting::connectSignals()
+{
+    connect(this, SIGNAL(goBack()), this, SIGNAL(cancelConnection()));
+}
+
+PageConnecting::PageConnecting(QWidget* parent) :  AbstractPage(parent)
+{
+    initPage();
+}
--- a/QTfrontend/pageconnecting.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pageconnecting.h	Tue Sep 27 00:38:39 2011 +0200
@@ -30,6 +30,10 @@
 
 signals:
     void cancelConnection();
+
+protected:
+    QLayout * bodyLayoutDefinition();
+    void connectSignals();
 };
 
 #endif
--- a/QTfrontend/pagedata.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagedata.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -34,27 +34,32 @@
 #include "quazip.h"
 #include "quazipfile.h"
 
-PageDataDownload::PageDataDownload(QWidget* parent) : AbstractPage(parent)
+QLayout * PageDataDownload::bodyLayoutDefinition()
 {
-    QGridLayout * pageLayout = new QGridLayout(this);
+    QGridLayout * pageLayout = new QGridLayout();
     pageLayout->setColumnStretch(0, 1);
     pageLayout->setColumnStretch(1, 1);
     pageLayout->setColumnStretch(2, 1);
 
-
     web = new DataBrowser(this);
-    connect(web, SIGNAL(anchorClicked(QUrl)), this, SLOT(request(const QUrl&)));
-    web->setOpenLinks(false);
     pageLayout->addWidget(web, 0, 0, 1, 3);
 
     progressBarsLayout = new QVBoxLayout();
     pageLayout->addLayout(progressBarsLayout, 1, 0, 1, 3);
-
-    fetchList();
+    return pageLayout;
+}
 
+void PageDataDownload::connectSignals()
+{
+    connect(web, SIGNAL(anchorClicked(QUrl)), this, SLOT(request(const QUrl&)));
+}
 
-    BtnBack = addButton(":/res/Exit.png", pageLayout, 2, 0, true);
-    connect(BtnBack, SIGNAL(clicked()), this, SIGNAL(goBack()));
+PageDataDownload::PageDataDownload(QWidget* parent) : AbstractPage(parent)
+{
+    initPage();
+
+    web->setOpenLinks(false);
+    fetchList();
 }
 
 void PageDataDownload::request(const QUrl &url)
--- a/QTfrontend/pagedata.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagedata.h	Tue Sep 27 00:38:39 2011 +0200
@@ -37,8 +37,11 @@
 public slots:
     void fetchList();
 
+protected:
+    QLayout * bodyLayoutDefinition();
+    void connectSignals();
+
 private:
-    QPushButton *BtnBack;
     DataBrowser *web;
     QHash<QNetworkReply*, QProgressBar *> progressBars;
     QVBoxLayout *progressBarsLayout;
--- a/QTfrontend/pagedrawmap.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagedrawmap.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -23,29 +23,35 @@
 #include "pagedrawmap.h"
 #include "drawmapwidget.h"
 
-PageDrawMap::PageDrawMap(QWidget* parent) : AbstractPage(parent)
+
+QLayout * PageDrawMap::bodyLayoutDefinition()
 {
-    QGridLayout * pageLayout = new QGridLayout(this);
+    QGridLayout * pageLayout = new QGridLayout();
 
-    QPushButton * pbUndo = addButton(tr("Undo"), pageLayout, 0, 0);
-    QPushButton * pbClear = addButton(tr("Clear"), pageLayout, 1, 0);
-    QPushButton * pbLoad = addButton(tr("Load"), pageLayout, 2, 0);
-    QPushButton * pbSave = addButton(tr("Save"), pageLayout, 3, 0);
-
-
-    BtnBack = addButton(":/res/Exit.png", pageLayout, 5, 0, true);
-    connect(BtnBack, SIGNAL(clicked()), this, SIGNAL(goBack()));
-
+    pbUndo = addButton(tr("Undo"), pageLayout, 0, 0);
+    pbClear = addButton(tr("Clear"), pageLayout, 1, 0);
+    pbLoad = addButton(tr("Load"), pageLayout, 2, 0);
+    pbSave = addButton(tr("Save"), pageLayout, 3, 0);
 
     drawMapWidget = new DrawMapWidget(this);
     pageLayout->addWidget(drawMapWidget, 0, 1, 5, 1);
 
+    return pageLayout;
+}
+
+void PageDrawMap::connectSignals()
+{
     connect(pbUndo, SIGNAL(clicked()), drawMapWidget, SLOT(undo()));
     connect(pbClear, SIGNAL(clicked()), drawMapWidget, SLOT(clear()));
     connect(pbLoad, SIGNAL(clicked()), this, SLOT(load()));
     connect(pbSave, SIGNAL(clicked()), this, SLOT(save()));
 }
 
+PageDrawMap::PageDrawMap(QWidget* parent) : AbstractPage(parent)
+{
+    initPage();
+}
+
 void PageDrawMap::load()
 {
     QString fileName = QFileDialog::getOpenFileName(NULL, tr("Load drawn map"), ".", tr("Drawn Maps") + " (*.hwmap);;" + tr("All files") + " (*)");
--- a/QTfrontend/pagedrawmap.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagedrawmap.h	Tue Sep 27 00:38:39 2011 +0200
@@ -32,8 +32,15 @@
 
     DrawMapWidget * drawMapWidget;
 
+protected:
+    QLayout * bodyLayoutDefinition();
+    void connectSignals();
+
 private:
-    QPushButton * BtnBack;
+    QPushButton * pbUndo;
+    QPushButton * pbClear;
+    QPushButton * pbLoad;
+    QPushButton * pbSave;
 
 private slots:
     void load();
--- a/QTfrontend/pageeditteam.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pageeditteam.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -17,6 +17,7 @@
  */
 
 #include <QGridLayout>
+#include <QHBoxLayout>
 #include <QPushButton>
 #include <QComboBox>
 #include <QLabel>
@@ -32,28 +33,16 @@
 #include "hats.h"
 #include "HWApplication.h"
 
-PageEditTeam::PageEditTeam(QWidget* parent, SDLInteraction * sdli) :
-  AbstractPage(parent)
+QLayout * PageEditTeam::bodyLayoutDefinition()
 {
-    m_playerHash = "0000000000000000000000000000000000000000";
-    mySdli = sdli;
-    QGridLayout * pageLayout = new QGridLayout(this);
-    QTabWidget * tbw = new QTabWidget(this);
+    QGridLayout * pageLayout = new QGridLayout();
+    QTabWidget * tbw = new QTabWidget();
     QWidget * page1 = new QWidget(this);
     QWidget * page2 = new QWidget(this);
     tbw->addTab(page1, tr("General"));
     tbw->addTab(page2, tr("Advanced"));
     pageLayout->addWidget(tbw, 0, 0, 1, 3);
 
-    BtnTeamSave = addButton(":/res/Save.png", pageLayout, 1, 2, true);;
-    BtnTeamSave->setStyleSheet("QPushButton{margin: 12px 0px 12px 0px;}");
-    connect(BtnTeamSave, SIGNAL(clicked()), this, SLOT(saveTeam()));
-
-    BtnTeamDiscard = addButton(":/res/Exit.png", pageLayout, 1, 0, true);
-    BtnTeamDiscard->setFixedHeight(BtnTeamSave->height());
-    BtnTeamDiscard->setStyleSheet("QPushButton{margin-top: 31px;}");
-    connect(BtnTeamDiscard, SIGNAL(clicked()), this, SIGNAL(goBack()));
-
     QHBoxLayout * page1Layout = new QHBoxLayout(page1);
     page1Layout->setAlignment(Qt::AlignTop);
     QGridLayout * page2Layout = new QGridLayout(page2);
@@ -69,12 +58,6 @@
     GBoxHedgehogs->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
     QGridLayout * GBHLayout = new QGridLayout(GBoxHedgehogs);
 
-    signalMapper1 = new QSignalMapper(this);
-    signalMapper2 = new QSignalMapper(this);
-
-    connect(signalMapper1, SIGNAL(mapped(int)), this, SLOT(fixHHname(int)));
-    connect(signalMapper2, SIGNAL(mapped(int)), this, SLOT(setRandomName(int)));
-
     HatsModel * hatsModel = new HatsModel(GBoxHedgehogs);
     for(int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
     {
@@ -91,21 +74,13 @@
         HHNameEdit[i]->setMinimumWidth(120);
         GBHLayout->addWidget(HHNameEdit[i], i, 1);
 
-        connect(HHNameEdit[i], SIGNAL(editingFinished()), signalMapper1, SLOT(map()));
-            signalMapper1->setMapping(HHNameEdit[i], i);
-
-        randButton[i] = addButton(":/res/dice.png", GBHLayout, i, 3, true);
-
-        connect(randButton[i], SIGNAL(clicked()), signalMapper2, SLOT(map()));
-            signalMapper2->setMapping(randButton[i], i);
+        btnRandomHogName[i] = addButton(":/res/dice.png", GBHLayout, i, 3, true);
     }
 
-    randTeamButton = addButton(QPushButton::tr("Random Team"), GBHLayout, 9, false);
-    connect(randTeamButton, SIGNAL(clicked()), this, SLOT(setRandomNames()));
+    btnRandomTeam = addButton(QPushButton::tr("Random Team"), GBHLayout, 9, false);
 
     vbox1->addWidget(GBoxHedgehogs);
 
-
     GBoxTeam = new QGroupBox(this);
     GBoxTeam->setTitle(QGroupBox::tr("Team Settings"));
     GBoxTeam->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
@@ -126,7 +101,6 @@
     tmpLabel->setText(QLabel::tr("Voice"));
     GBTLayout->addWidget(tmpLabel, 4, 0);
 
-
     TeamNameEdit = new QLineEdit(GBoxTeam);
     TeamNameEdit->setMaxLength(64);
     GBTLayout->addWidget(TeamNameEdit, 0, 1);
@@ -152,34 +126,14 @@
     CBFlag->setIconSize(QSize(22, 15));
     GBTLayout->addWidget(CBFlag, 3, 1);
 
-    {
-        QHBoxLayout * hbox = new QHBoxLayout();
-        CBVoicepack = new QComboBox(GBoxTeam);
-        {
-            QDir tmpdir;
-            QStringList list;
-            tmpdir.cd(cfgdir->absolutePath());
-            if (tmpdir.cd("Data/Sounds/voices")) 
-            {
-                list = tmpdir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name);
-                CBVoicepack->addItems(list);
-            }
+    QHBoxLayout * hbox = new QHBoxLayout();
+    CBVoicepack = new QComboBox(GBoxTeam);
 
-            tmpdir.cd(datadir->absolutePath());
-            tmpdir.cd("Sounds/voices");
-            QStringList tmplist = tmpdir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name);
-            QStringList tmplist2;
-            for (QStringList::Iterator it = tmplist.begin(); it != tmplist.end(); ++it)
-                if (!list.contains(*it,Qt::CaseInsensitive)) tmplist2.append(*it);
+    hbox->addWidget(CBVoicepack, 100);
+    btnTestSound = addButton(":/res/PlaySound.png", hbox, 1, true);
+    hbox->setStretchFactor(btnTestSound, 1);
 
-            CBVoicepack->addItems(tmplist2);
-        }
-        hbox->addWidget(CBVoicepack, 100);
-        BtnTestSound = addButton(":/res/PlaySound.png", hbox, 1, true);
-        hbox->setStretchFactor(BtnTestSound, 1);
-        connect(BtnTestSound, SIGNAL(clicked()), this, SLOT(testSound()));
-        GBTLayout->addLayout(hbox, 4, 1);
-    }
+    GBTLayout->addLayout(hbox, 4, 1);
 
     GBoxFort = new QGroupBox(this);
     GBoxFort->setTitle(QGroupBox::tr("Fort"));
@@ -196,7 +150,123 @@
     GBFLayout->addWidget(FortPreview, 1, 0);
     vbox2->addWidget(GBoxFort);
 
+    vbox1->addStretch();
+    vbox2->addStretch();
+
+// ====== Page 2 ======
+    GBoxBinds = new QGroupBox(this);
+    GBoxBinds->setTitle(QGroupBox::tr("Key binds"));
+    QGridLayout * GBBLayout = new QGridLayout(GBoxBinds);
+    BindsBox = new QToolBox(GBoxBinds);
+    BindsBox->setLineWidth(0);
+    GBBLayout->addWidget(BindsBox);
+    page2Layout->addWidget(GBoxBinds, 0, 0);
+
+    quint16 i = 0;
+    quint16 num = 0;
+    QWidget * curW = NULL;
+    QGridLayout * pagelayout = NULL;
+    QLabel* l = NULL;
+    while (i < BINDS_NUMBER) {
+        if(cbinds[i].category != NULL)
+        {
+            if(curW != NULL)
+            {
+                l = new QLabel(curW);
+                l->setText("");
+                pagelayout->addWidget(l, num++, 0, 1, 2);
+            }
+            curW = new QWidget(this);
+            BindsBox->addItem(curW, HWApplication::translate("binds (categories)", cbinds[i].category));
+            pagelayout = new QGridLayout(curW);
+            num = 0;
+        }
+        if(cbinds[i].description != NULL)
+        {
+            l = new QLabel(curW);
+            l->setText((num > 0 ? QString("\n") : QString("")) + HWApplication::translate("binds (descriptions)", cbinds[i].description));
+            pagelayout->addWidget(l, num++, 0, 1, 2);
+        }
+
+        l = new QLabel(curW);
+        l->setText(HWApplication::translate("binds", cbinds[i].name));
+        l->setAlignment(Qt::AlignRight);
+        pagelayout->addWidget(l, num, 0);
+        CBBind[i] = new QComboBox(curW);
+        for(int j = 0; sdlkeys[j][1][0] != '\0'; j++)
+            CBBind[i]->addItem(HWApplication::translate("binds (keys)", sdlkeys[j][1]).contains(": ") ? HWApplication::translate("binds (keys)", sdlkeys[j][1]) : HWApplication::translate("binds (keys)", "Keyboard") + QString(": ") + HWApplication::translate("binds (keys)", sdlkeys[j][1]), sdlkeys[j][0]);
+        pagelayout->addWidget(CBBind[i++], num++, 1);
+    }
+
+    return pageLayout;
+}
+
+QLayout * PageEditTeam::footerLayoutDefinition()
+{
+    QHBoxLayout * bottomLayout = new QHBoxLayout();
+
+    btnSave = addButton(":/res/Save.png", bottomLayout, 0, true);;
+    btnSave->setStyleSheet("QPushButton{margin: 24px 0 0 0;}");
+    bottomLayout->setAlignment(btnSave, Qt::AlignRight | Qt::AlignBottom);
+
+    return bottomLayout;
+}
+
+void PageEditTeam::connectSignals()
+{
+    connect(btnSave, SIGNAL(clicked()), this, SLOT(saveTeam()));
+
+    signalMapper1 = new QSignalMapper(this);
+    signalMapper2 = new QSignalMapper(this);
+
+    connect(signalMapper1, SIGNAL(mapped(int)), this, SLOT(fixHHname(int)));
+    connect(signalMapper2, SIGNAL(mapped(int)), this, SLOT(setRandomName(int)));
+
+    for(int i = 0; i < HEDGEHOGS_PER_TEAM; i++)
+    {
+        connect(HHNameEdit[i], SIGNAL(editingFinished()), signalMapper1, SLOT(map()));
+            signalMapper1->setMapping(HHNameEdit[i], i);
+
+        connect(btnRandomHogName[i], SIGNAL(clicked()), signalMapper2, SLOT(map()));
+            signalMapper2->setMapping(btnRandomHogName[i], i);
+    }
+
+    connect(btnRandomTeam, SIGNAL(clicked()), this, SLOT(setRandomNames()));
+    
+    connect(btnTestSound, SIGNAL(clicked()), this, SLOT(testSound()));
+
+    connect(CBFort, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(CBFort_activated(const QString &)));
+}
+
+PageEditTeam::PageEditTeam(QWidget* parent, SDLInteraction * sdli) :
+  AbstractPage(parent)
+{
+    initPage();
+
+    m_playerHash = "0000000000000000000000000000000000000000";
+    mySdli = sdli;
+
     QDir tmpdir;
+    QStringList list;
+    tmpdir.cd(cfgdir->absolutePath());
+    if (tmpdir.cd("Data/Sounds/voices")) 
+    {
+        list = tmpdir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name);
+        CBVoicepack->addItems(list);
+    }
+
+    tmpdir.cd(datadir->absolutePath());
+    tmpdir.cd("Sounds/voices");
+    QStringList tmplist = tmpdir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name);
+    QStringList tmplist2;
+    foreach (const QString & line, tmplist)
+    {
+        if (!list.contains(line,Qt::CaseInsensitive))
+            tmplist2.append(line);
+    }
+
+    CBVoicepack->addItems(tmplist2);
+
     QStringList userforts;
     tmpdir.cd(cfgdir->absolutePath());
     if (tmpdir.cd("Data/Forts"))
@@ -219,22 +289,26 @@
     tmpdir.cd("Forts");
     tmpdir.setFilter(QDir::Files);
 
-    QStringList tmplist = tmpdir.entryList(QStringList("*L.png")).replaceInStrings(QRegExp("^(.*)L\\.png"), "\\1");
+    tmplist = tmpdir.entryList(QStringList("*L.png")).replaceInStrings(QRegExp("^(.*)L\\.png"), "\\1");
     QStringList dataforts;
-    for (QStringList::Iterator it = tmplist.begin(); it != tmplist.end(); ++it)
-        if (!userforts.contains(*it,Qt::CaseInsensitive)) dataforts.append(*it);
+    foreach (const QString & line, tmplist)
+    {
+        if (!userforts.contains(line,Qt::CaseInsensitive))
+            dataforts.append(line);
+    }
 
     CBFort->addItems(dataforts);
-    connect(CBFort, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(CBFort_activated(const QString &)));
 
     tmpdir.cd("../Graphics/Graves");
     QStringList datalist = tmpdir.entryList(QStringList("*.png"));
-    for (QStringList::Iterator it = datalist.begin(); it != datalist.end(); ++it )
+    foreach (const QString & line, datalist)
     {
-        if (userlist.contains(*it,Qt::CaseInsensitive)) continue;
-        QPixmap pix(datadir->absolutePath() + "/Graphics/Graves/" + *it);
+        if (userlist.contains(line,Qt::CaseInsensitive)) continue;
+        QPixmap pix(datadir->absolutePath() + "/Graphics/Graves/" + line);
         QIcon icon(pix.copy(0, 0, 32, 32));
-        CBGrave->addItem(icon, (*it).replace(QRegExp("^(.*)\\.png"), "\\1"));
+        QString grave = line;
+        grave = grave.replace(QRegExp("^(.*)\\.png"), "\\1");
+        CBGrave->addItem(icon, grave);
     }
 
     // add the default flag
@@ -246,14 +320,16 @@
     userlist = tmpdir.entryList(QStringList("*.png"));
     
     // add all country flags
-    for (QStringList::Iterator it = userlist.begin(); it != userlist.end(); ++it )
+    foreach (const QString & line, userlist)
     {
-        QPixmap pix(cfgdir->absolutePath() + "/Data/Graphics/Flags/" + *it);
+        QPixmap pix(cfgdir->absolutePath() + "/Data/Graphics/Flags/" + line);
         QIcon icon(pix.copy(0, 0, 22, 15));
-        if(it->compare("cpu.png") && it->compare("hedgewars.png") && (it->indexOf("cm_") == -1)) // skip cpu and hedgewars flags as well as all community flags
+        // TODO improve readablility
+        if(line.compare("cpu.png") && line.compare("hedgewars.png") && (line.indexOf("cm_") == -1)) // skip cpu and hedgewars flags as well as all community flags
         {
-            QString flag = QString(*it).replace(QRegExp("^(.*)\\.png"), "\\1");
-            CBFlag->addItem(icon, QString(flag).replace("_", " "), flag);
+            QString flag = line;
+            flag = flag.replace(QRegExp("^(.*)\\.png"), "\\1");
+            CBFlag->addItem(icon, flag.replace("_", " "), flag);
         }
     }
 
@@ -304,55 +380,6 @@
             CBFlag->addItem(icon, QString(flag).replace("cm_", QComboBox::tr("Community") + ": "), flag);
         }
     }
-
-    vbox1->addStretch();
-    vbox2->addStretch();
-
-// ====== Page 2 ======
-    GBoxBinds = new QGroupBox(this);
-    GBoxBinds->setTitle(QGroupBox::tr("Key binds"));
-    QGridLayout * GBBLayout = new QGridLayout(GBoxBinds);
-    BindsBox = new QToolBox(GBoxBinds);
-    BindsBox->setLineWidth(0);
-    GBBLayout->addWidget(BindsBox);
-    page2Layout->addWidget(GBoxBinds, 0, 0);
-
-    quint16 i = 0;
-    quint16 num = 0;
-    QWidget * curW = NULL;
-    QGridLayout * pagelayout = NULL;
-    QLabel* l = NULL;
-    while (i < BINDS_NUMBER) {
-        if(cbinds[i].category != NULL)
-        {
-            if(curW != NULL)
-            {
-                l = new QLabel(curW);
-                l->setText("");
-                pagelayout->addWidget(l, num++, 0, 1, 2);
-            }
-            curW = new QWidget(this);
-            BindsBox->addItem(curW, HWApplication::translate("binds (categories)", cbinds[i].category));
-            pagelayout = new QGridLayout(curW);
-            num = 0;
-        }
-        if(cbinds[i].description != NULL)
-        {
-            l = new QLabel(curW);
-            l->setText((num > 0 ? QString("\n") : QString("")) + HWApplication::translate("binds (descriptions)", cbinds[i].description));
-            pagelayout->addWidget(l, num++, 0, 1, 2);
-        }
-
-        l = new QLabel(curW);
-        l->setText(HWApplication::translate("binds", cbinds[i].name));
-        l->setAlignment(Qt::AlignRight);
-        pagelayout->addWidget(l, num, 0);
-        CBBind[i] = new QComboBox(curW);
-        for(int j = 0; sdlkeys[j][1][0] != '\0'; j++)
-            CBBind[i]->addItem(HWApplication::translate("binds (keys)", sdlkeys[j][1]).contains(": ") ? HWApplication::translate("binds (keys)", sdlkeys[j][1]) : HWApplication::translate("binds (keys)", "Keyboard") + QString(": ") + HWApplication::translate("binds (keys)", sdlkeys[j][1]), sdlkeys[j][0]);
-        pagelayout->addWidget(CBBind[i++], num++, 1);
-    }
-
 }
 
 void PageEditTeam::fixHHname(int idx)
@@ -494,4 +521,3 @@
     data().saveToFile();
     emit teamEdited();
 }
-
--- a/QTfrontend/pageeditteam.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pageeditteam.h	Tue Sep 27 00:38:39 2011 +0200
@@ -47,7 +47,6 @@
     void CBFort_activated(const QString & gravename);
 
 private:
-    QPushButton * randTeamButton;
     QSignalMapper* signalMapper1;
     QSignalMapper* signalMapper2;
     QGroupBox *GBoxHedgehogs;
@@ -61,20 +60,28 @@
     QComboBox *CBVoicepack;
     QGroupBox *GBoxBinds;
     QToolBox *BindsBox;
-    QPushButton *BtnTeamDiscard;
-    QPushButton *BtnTeamSave;
-    QPushButton * BtnTestSound;
     QLineEdit * TeamNameEdit;
     QLineEdit * HHNameEdit[HEDGEHOGS_PER_TEAM];
     QComboBox * HHHats[HEDGEHOGS_PER_TEAM];
-    QPushButton * randButton[HEDGEHOGS_PER_TEAM];
     QComboBox * CBBind[BINDS_NUMBER];
     SDLInteraction * mySdli;
     HWTeam data();
     QString m_playerHash;
 
+    QLayout * bodyLayoutDefinition();
+    QLayout * footerLayoutDefinition();
+    void connectSignals();
+
     void loadTeam(const HWTeam & team);
 
+    // page 1
+    QPushButton * btnRandomHogName[HEDGEHOGS_PER_TEAM];
+    QPushButton * btnRandomTeam;
+    QPushButton * btnTestSound;
+
+    // footer
+    QPushButton * btnSave;
+
 private slots:
     void saveTeam();
     void setRandomNames();
--- a/QTfrontend/pagegamestats.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagegamestats.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -18,6 +18,7 @@
 
 #include <QLabel>
 #include <QGridLayout>
+#include <QHBoxLayout>
 #include <QGraphicsScene>
 #include <QGroupBox>
 #include <QSizePolicy>
@@ -37,26 +38,14 @@
     fitInView(sceneRect());
 }
 
-PageGameStats::PageGameStats(QWidget* parent) : AbstractPage(parent)
+QLayout * PageGameStats::bodyLayoutDefinition()
 {
-    QGridLayout * pageLayout = new QGridLayout(this);
+    QGridLayout * pageLayout = new QGridLayout();
     pageLayout->setSpacing(20);
     pageLayout->setColumnStretch(0, 1);
     pageLayout->setColumnStretch(1, 1);
     pageLayout->setContentsMargins(7, 7, 7, 0);
 
-    BtnSave = addButton(":/res/Save.png", pageLayout, 3, 2, true);
-    BtnSave->setStyleSheet("QPushButton{margin: 12px 0px 12px 0px;}");
-    connect(BtnSave, SIGNAL(clicked()), this, SIGNAL(saveDemoRequested()));
-
-
-    BtnBack = addButton(":/res/Exit.png", pageLayout, 3, 0, true);
-    BtnBack->setFixedHeight(BtnSave->height());
-    BtnBack->setFixedWidth(BtnBack->width()+2);
-    BtnBack->setStyleSheet("QPushButton{margin: 22px 0 9px 2px;}");
-    connect(BtnBack, SIGNAL(clicked()), this, SIGNAL(goBack()));
-
-
     QGroupBox * gb = new QGroupBox(this);
     QVBoxLayout * gbl = new QVBoxLayout;
 
@@ -104,6 +93,29 @@
     labelGameRank->setTextFormat(Qt::RichText);
     labelGameRank->setAlignment(Qt::AlignTop);
     pageLayout->addWidget(gb, 1, 0);
+
+    return pageLayout;
+}
+
+QLayout * PageGameStats::footerLayoutDefinition()
+{
+    QHBoxLayout * bottomLayout = new QHBoxLayout();
+
+    btnSave = addButton(":/res/Save.png", bottomLayout, 0, true);
+    btnSave->setStyleSheet("QPushButton{margin: 24px 0 0 0;}");
+    bottomLayout->setAlignment(btnSave, Qt::AlignRight | Qt::AlignBottom);
+
+    return bottomLayout;
+}
+
+void PageGameStats::connectSignals()
+{
+    connect(btnSave, SIGNAL(clicked()), this, SIGNAL(saveDemoRequested()));
+}
+
+PageGameStats::PageGameStats(QWidget* parent) : AbstractPage(parent)
+{
+    initPage();
 }
 
 void PageGameStats::AddStatText(const QString & msg)
--- a/QTfrontend/pagegamestats.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagegamestats.h	Tue Sep 27 00:38:39 2011 +0200
@@ -43,7 +43,7 @@
 public:
     PageGameStats(QWidget* parent = 0);
 
-    QPushButton *BtnSave;
+    QPushButton *btnSave;
     QLabel *labelGameStats;
     QLabel *labelGameWin;
     QLabel *labelGameRank;
@@ -64,7 +64,10 @@
     unsigned int playerPosition;
     quint32 lastColor;
 
-    QPushButton *BtnBack;
+protected:
+    QLayout * bodyLayoutDefinition();
+    QLayout * footerLayoutDefinition();
+    void connectSignals();
 };
 
 #endif // STATSPAGE_H
--- a/QTfrontend/pageinfo.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pageinfo.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -22,9 +22,10 @@
 #include "pageinfo.h"
 #include "about.h"
 
-PageInfo::PageInfo(QWidget* parent) : AbstractPage(parent)
+QLayout * PageInfo::bodyLayoutDefinition()
 {
-    QGridLayout * pageLayout = new QGridLayout(this);
+    QGridLayout * pageLayout = new QGridLayout();
+
     pageLayout->setColumnStretch(0, 1);
     pageLayout->setColumnStretch(1, 1);
     pageLayout->setColumnStretch(2, 1);
@@ -34,7 +35,21 @@
     about = new About(this);
     pageLayout->addWidget(about, 0, 0, 1, 3);
 
+    return pageLayout;
+}
 
-    BtnBack = addButton(":/res/Exit.png", pageLayout, 1, 0, true);
-    connect(BtnBack, SIGNAL(clicked()), this, SIGNAL(goBack()));
+QLayout * PageInfo::footerLayoutDefinition()
+{
+   return NULL; // TODO: move screenshot button here
 }
+
+void PageInfo::connectSignals()
+{
+    //TODO
+}
+
+PageInfo::PageInfo(QWidget* parent) : AbstractPage(parent)
+{
+    initPage();
+}
+
--- a/QTfrontend/pageinfo.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pageinfo.h	Tue Sep 27 00:38:39 2011 +0200
@@ -34,7 +34,9 @@
     About *about;
 
 private:
-    QPushButton *BtnBack;
+    QLayout * bodyLayoutDefinition();
+    QLayout * footerLayoutDefinition();
+    void connectSignals();
 };
 
 #endif
--- a/QTfrontend/pageingame.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pageingame.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -16,14 +16,25 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  */
 
+#include <QHBoxLayout>
 #include <QLabel>
 
 #include "pageingame.h"
 
-PageInGame::PageInGame(QWidget* parent) :
-  AbstractPage(parent)
+QLayout * PageInGame::bodyLayoutDefinition()
 {
+    QHBoxLayout * pageLayout = new QHBoxLayout();
+
     QLabel * label = new QLabel(this);
-    label->setText("In game...");
+    label->setText(tr("In game..."));
+    pageLayout->addWidget(label);
+
+    setBackButtonVisible(false);
+
+    return pageLayout;
 }
 
+PageInGame::PageInGame(QWidget * parent) :  AbstractPage(parent)
+{
+    initPage();
+}
--- a/QTfrontend/pageingame.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pageingame.h	Tue Sep 27 00:38:39 2011 +0200
@@ -25,8 +25,10 @@
 {
     Q_OBJECT
 
-public:
-    PageInGame(QWidget* parent = 0);
+    public:
+        PageInGame(QWidget * parent = 0);
+
+        QLayout * bodyLayoutDefinition();
 };
 
 #endif
--- a/QTfrontend/pagemain.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagemain.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -17,6 +17,7 @@
  */
  
 #include <QGridLayout>
+#include <QHBoxLayout>
 #include <QPushButton>
 #include <QLabel>
 #include <QTime>
@@ -25,11 +26,9 @@
 #include "hwconsts.h"
 #include "hwform.h"
 
-PageMain::PageMain(QWidget* parent) :
-  AbstractPage(parent)
+QLayout * PageMain::bodyLayoutDefinition()
 {
-    if(frontendEffects) setAttribute(Qt::WA_NoSystemBackground, true);
-    QGridLayout * pageLayout = new QGridLayout(this);
+    QGridLayout * pageLayout = new QGridLayout();
     //pageLayout->setColumnStretch(0, 1);
     //pageLayout->setColumnStretch(1, 2);
     //pageLayout->setColumnStretch(2, 1);
@@ -41,7 +40,11 @@
     pageLayout->setRowStretch(2, 0);
     pageLayout->setRowStretch(3, 1);
     pageLayout->setRowStretch(4, 1);
-    pageLayout->setRowStretch(5, 1);
+
+    //BtnInfo = addButton(":/res/About.png", pageLayout, 3, 1, 1, 2, true);
+    BtnInfo = addButton(":/res/HedgewarsTitle.png", pageLayout, 0, 0, 1, 4, true);
+    BtnInfo->setStyleSheet("border: transparent;background: transparent;");
+    pageLayout->setAlignment(BtnInfo, Qt::AlignHCenter);
 
     BtnSinglePlayer = addButton(":/res/LocalPlay.png", pageLayout, 2, 0, 1, 2, true);
     BtnSinglePlayer->setToolTip(tr("Local Game (Play a game on a single computer)"));
@@ -54,14 +57,50 @@
     BtnDataDownload = addButton(tr("Downloadable Content"), pageLayout, 4, 0, 1, 4, false);
     pageLayout->setAlignment(BtnDataDownload, Qt::AlignHCenter);
 
+    return pageLayout;
+}
+
+QLayout * PageMain::footerLayoutDefinition()
+{
+    QHBoxLayout * bottomLayout = new QHBoxLayout();
+
     mainNote = new QLabel(this);
     mainNote->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
     mainNote->setWordWrap(true);
+    
+    bottomLayout->addWidget(mainNote, 0);
+    bottomLayout->setStretch(0,1);
+
+    BtnSetup = addButton(":/res/Settings.png", bottomLayout, 1, true);
+    bottomLayout->setStretch(1,0);
+
+    return bottomLayout;
+}
+
+void PageMain::connectSignals()
+{
+    //TODO
+}
+
+PageMain::PageMain(QWidget* parent) : AbstractPage(parent)
+{
+    initPage();
+
+    if(frontendEffects) setAttribute(Qt::WA_NoSystemBackground, true);
     mainNote->setOpenExternalLinks(true);
 
     if(!isDevBuild)
     {
-        QStringList Tips;
+        mainNote->setText(QLabel::tr("Tip: ") + randomTip());
+    }
+    else
+        mainNote->setText(QLabel::tr("This development build is 'work in progress' and may not be compatible with other versions of the game. Some features might be broken or incomplete. Use at your own risk!"));
+
+}
+
+QString PageMain::randomTip() const
+{
+    QStringList Tips;
         Tips << tr("Simply pick the same color as a friend to play together as a team. Each of you will still control his or her own hedgehogs but they'll win or lose together.", "Tips");
         Tips << tr("Some weapons might do only low damage but they can be a lot more devastating in the right situation. Try to use the Desert Eagle to knock multiple hedgehogs into the water.", "Tips");
         Tips << tr("If you're unsure what to do and don't want to waste ammo, skip one round. But don't let too much time pass as there will be Sudden Death!", "Tips");
@@ -115,25 +154,9 @@
         Tips << tr("You can find your Hedgewars configuration files under \"My Documents\\Hedgewars\". Create backups or take the files with you, but don't edit them by hand.", "Tips");
 #elif defined __APPLE__
         Tips << tr("You can find your Hedgewars configuration files under \"Library/Application Support/Hedgewars\" in your home directory. Create backups or take the files with you, but don't edit them by hand.", "Tips");
-#else  
+#else
         Tips << tr("You can find your Hedgewars configuration files under \".hedgewars\" in your home directory. Create backups or take the files with you, but don't edit them by hand.", "Tips");
 #endif
-        mainNote->setText(QLabel::tr("Tip: ") + Tips[QTime(0, 0, 0).secsTo(QTime::currentTime()) % Tips.length()]);
-    }
-    else
-        mainNote->setText(QLabel::tr("This development build is 'work in progress' and may not be compatible with other versions of the game. Some features might be broken or incomplete. Use at your own risk!"));
 
-    pageLayout->addWidget(mainNote, 5, 1, 1, 2);
-
-    BtnSetup = addButton(":/res/Settings.png", pageLayout, 5, 3, true);
-
-    //BtnInfo = addButton(":/res/About.png", pageLayout, 3, 1, 1, 2, true);
-    BtnInfo = addButton(":/res/HedgewarsTitle.png", pageLayout, 0, 0, 1, 4, true);
-    BtnInfo->setStyleSheet("border: transparent;background: transparent;");
-    pageLayout->setAlignment(BtnInfo, Qt::AlignHCenter);
-    //pageLayout->setAlignment(BtnInfo, Qt::AlignHCenter);
-
-    BtnExit = addButton(":/res/Exit.png", pageLayout, 5, 0, 1, 1, true);
-    BtnExit->setFixedHeight(BtnSetup->height());
-    BtnExit->setStyleSheet("QPushButton{margin-top: 2px;}");
+        return Tips[QTime(0, 0, 0).secsTo(QTime::currentTime()) % Tips.length()];
 }
--- a/QTfrontend/pagemain.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagemain.h	Tue Sep 27 00:38:39 2011 +0200
@@ -26,15 +26,21 @@
     Q_OBJECT
 
 public:
-    PageMain(QWidget* parent = 0);
+    PageMain(QWidget * parent = 0);
 
-    QPushButton *BtnSinglePlayer;
-    QPushButton *BtnNet;
-    QPushButton *BtnSetup;
-    QPushButton *BtnInfo;
-    QPushButton *BtnExit;
-    QPushButton *BtnDataDownload;
-    QLabel *mainNote;
+    QPushButton * BtnSinglePlayer;
+    QPushButton * BtnNet;
+    QPushButton * BtnSetup;
+    QPushButton * BtnInfo;
+    QPushButton * BtnDataDownload;
+    QLabel * mainNote;
+
+private:
+    QLayout * bodyLayoutDefinition();
+    QLayout * footerLayoutDefinition();
+    void connectSignals();
+
+    QString randomTip() const;
 };
 
 #endif
--- a/QTfrontend/pagemultiplayer.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagemultiplayer.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -23,17 +23,15 @@
 #include "gamecfgwidget.h"
 #include "teamselect.h"
 
-PageMultiplayer::PageMultiplayer(QWidget* parent) :
-  AbstractPage(parent)
+QLayout * PageMultiplayer::bodyLayoutDefinition()
 {
-    QGridLayout * pageLayout = new QGridLayout(this);
+    QGridLayout * pageLayout = new QGridLayout();
 
     gameCFG = new GameCFGWidget(this);
     pageLayout->addWidget(gameCFG, 0, 0, 1, 2);
 
-    QPushButton * btnSetup = new QPushButton(this);
+    btnSetup = new QPushButton(this);
     btnSetup->setText(QPushButton::tr("Setup"));
-    connect(btnSetup, SIGNAL(clicked()), this, SIGNAL(SetupClicked()));
     pageLayout->addWidget(btnSetup, 1, 0, 1, 2);
 
     pageLayout->setRowStretch(2, 1);
@@ -43,7 +41,15 @@
 
     BtnStartMPGame = addButton(tr("Start"), pageLayout, 3, 3);
 
+    return pageLayout;
+}
 
-    BtnBack = addButton(":/res/Exit.png", pageLayout, 3, 0, true);
-    connect(BtnBack, SIGNAL(clicked()), this, SIGNAL(goBack()));
+void PageMultiplayer::connectSignals()
+{
+    PageMultiplayer::connect(btnSetup, SIGNAL(clicked()), this, SIGNAL(SetupClicked()));
 }
+
+PageMultiplayer::PageMultiplayer(QWidget* parent) : AbstractPage(parent)
+{
+    initPage();
+}
--- a/QTfrontend/pagemultiplayer.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagemultiplayer.h	Tue Sep 27 00:38:39 2011 +0200
@@ -35,11 +35,14 @@
     TeamSelWidget *teamsSelect;
     QPushButton *BtnStartMPGame;
 
-private:
-    QPushButton *BtnBack;
-
 signals:
     void SetupClicked();
+
+private:
+    QLayout * bodyLayoutDefinition();
+    void connectSignals();
+
+    QPushButton * btnSetup;
 };
 
 #endif
--- a/QTfrontend/pagenet.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagenet.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -27,10 +27,10 @@
 #include "hwconsts.h"
 #include "netudpwidget.h"
 
-PageNet::PageNet(QWidget* parent) : AbstractPage(parent)
+QLayout * PageNet::bodyLayoutDefinition()
 {
-    QFont * font14 = new QFont("MS Shell Dlg", 14);
-    QGridLayout * pageLayout = new QGridLayout(this);
+    QGridLayout * pageLayout = new QGridLayout();
+
     pageLayout->setColumnStretch(0, 1);
     pageLayout->setColumnStretch(1, 1);
     pageLayout->setColumnStretch(2, 1);
@@ -41,11 +41,6 @@
     BtnNetSvrStart->setVisible(haveServer);
     pageLayout->addWidget(BtnNetSvrStart, 4, 2);
 
-
-    BtnBack = addButton(":/res/Exit.png", pageLayout, 4, 0, true);
-    connect(BtnBack, SIGNAL(clicked()), this, SIGNAL(goBack()));
-
-
     ConnGroupBox = new QGroupBox(this);
     ConnGroupBox->setTitle(QGroupBox::tr("Net game"));
     pageLayout->addWidget(ConnGroupBox, 2, 0, 1, 3);
@@ -73,9 +68,19 @@
     BtnSpecifyServer->setText(QPushButton::tr("Specify"));
     GBClayout->addWidget(BtnSpecifyServer, 2, 1);
 
+    return pageLayout;
+}
+
+void PageNet::connectSignals()
+{
     connect(BtnNetConnect, SIGNAL(clicked()), this, SLOT(slotConnect()));
 }
 
+PageNet::PageNet(QWidget* parent) : AbstractPage(parent)
+{
+    initPage();
+}
+
 void PageNet::updateServersList()
 {
     tvServersList->setModel(new HWNetUdpModel(tvServersList));
--- a/QTfrontend/pagenet.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagenet.h	Tue Sep 27 00:38:39 2011 +0200
@@ -34,19 +34,21 @@
     QPushButton * BtnNetSvrStart;
     QPushButton * BtnSpecifyServer;
 
-private:
-    QGroupBox * ConnGroupBox;
-    QGridLayout * GBClayout;
-    QPushButton * BtnBack;
-
-private slots:
-    void slotConnect();
-
 public slots:
     void updateServersList();
 
 signals:
     void connectClicked(const QString & host, quint16 port);
+
+private:
+    QLayout * bodyLayoutDefinition();
+    void connectSignals();
+
+    QGroupBox * ConnGroupBox;
+    QGridLayout * GBClayout;
+
+private slots:
+    void slotConnect();
 };
 
 #endif
--- a/QTfrontend/pagenetgame.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagenetgame.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -27,16 +27,16 @@
 #include "teamselect.h"
 #include "chatwidget.h"
 
-PageNetGame::PageNetGame(QWidget* parent, QSettings * gameSettings, SDLInteraction * sdli) : AbstractPage(parent)
+QLayout * PageNetGame::bodyLayoutDefinition()
 {
-    QGridLayout * pageLayout = new QGridLayout(this);
+    QGridLayout * pageLayout = new QGridLayout();
     pageLayout->setSizeConstraint(QLayout::SetMinimumSize);
     //pageLayout->setSpacing(1);
     pageLayout->setColumnStretch(0, 50);
     pageLayout->setColumnStretch(1, 50);
 
     // chatwidget
-    pChatWidget = new HWChatWidget(this, gameSettings, sdli, true);
+    pChatWidget = new HWChatWidget(this, m_gameSettings, m_sdli, true);
     pChatWidget->setShowReady(true); // show status bulbs by default
     pChatWidget->setShowFollow(false); // don't show follow in nicks' context menus
     pageLayout->addWidget(pChatWidget, 2, 0, 1, 2);
@@ -46,30 +46,25 @@
     pGameCFG = new GameCFGWidget(this);
     pageLayout->addWidget(pGameCFG, 0, 0);
 
-    QPushButton * btnSetup = new QPushButton(this);
+    btnSetup = new QPushButton(this);
     btnSetup->setText(QPushButton::tr("Setup"));
-    connect(btnSetup, SIGNAL(clicked()), this, SIGNAL(SetupClicked()));
     pageLayout->addWidget(btnSetup, 1, 0);
 
     pNetTeamsWidget = new TeamSelWidget(this);
     pNetTeamsWidget->setAcceptOuter(true);
     pageLayout->addWidget(pNetTeamsWidget, 0, 1, 2, 1);
 
-
-    QHBoxLayout * bottomLayout = new QHBoxLayout;
-    pageLayout->addLayout(bottomLayout, 4, 0, 1, 2);
+    return pageLayout;
+}
 
-
-    BtnBack = addButton(":/res/Exit.png", bottomLayout, 0, true);
-    connect(BtnBack, SIGNAL(clicked()), this, SIGNAL(goBack()));
-
+QLayout * PageNetGame::footerLayoutDefinition()
+{
+    QHBoxLayout * bottomLayout = new QHBoxLayout;
 
     leRoomName = new QLineEdit(this);
     leRoomName->setMaxLength(60);
     leRoomName->setMinimumWidth(200);
     leRoomName->setMaximumWidth(400);
-    bottomLayout->addWidget(leRoomName, 8,0);
-    BtnUpdate = addButton(QAction::tr("Update"), bottomLayout, 1, false);
 
     BtnGo = new QPushButton(this);
     BtnGo->setToolTip(QPushButton::tr("Ready"));
@@ -77,11 +72,36 @@
     BtnGo->setIconSize(QSize(25, 34));
     BtnGo->setMinimumWidth(50);
     BtnGo->setMinimumHeight(50);
-    bottomLayout->addWidget(BtnGo, 4);
 
 
-    BtnMaster = addButton(tr("Control"), bottomLayout, 2);
+    bottomLayout->addWidget(leRoomName);
+    BtnUpdate = addButton(QAction::tr("Update"), bottomLayout, 1, false);
+    bottomLayout->addWidget(BtnGo);
+
+    BtnMaster = addButton(tr("Control"), bottomLayout, 3);
+    bottomLayout->insertStretch(3, 100);
+
+    BtnStart = addButton(QAction::tr("Start"), bottomLayout, 3);
+
+    return bottomLayout;
+}
+
+void PageNetGame::connectSignals()
+{
+    connect(btnSetup, SIGNAL(clicked()), this, SIGNAL(SetupClicked()));
+
+    connect(BtnUpdate, SIGNAL(clicked()), this, SLOT(onUpdateClick()));
+}
+
+PageNetGame::PageNetGame(QWidget* parent, QSettings * gameSettings, SDLInteraction * sdli) : AbstractPage(parent)
+{
+    m_gameSettings = gameSettings;
+    m_sdli = sdli;
+
+    initPage();
+
     QMenu * menu = new QMenu(BtnMaster);
+
     restrictJoins = new QAction(QAction::tr("Restrict Joins"), menu);
     restrictJoins->setCheckable(true);
     restrictTeamAdds = new QAction(QAction::tr("Restrict Team Additions"), menu);
@@ -92,11 +112,6 @@
 
     BtnMaster->setMenu(menu);
 
-    BtnStart = addButton(QAction::tr("Start"), bottomLayout, 3);
-
-    bottomLayout->insertStretch(3, 100);
-
-    connect(BtnUpdate, SIGNAL(clicked()), this, SLOT(onUpdateClick()));
 }
 
 void PageNetGame::setReadyStatus(bool isReady)
--- a/QTfrontend/pagenetgame.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagenetgame.h	Tue Sep 27 00:38:39 2011 +0200
@@ -31,7 +31,7 @@
     Q_OBJECT
 
 public:
-    PageNetGame(QWidget* parent, QSettings * config, SDLInteraction * sdli);
+    PageNetGame(QWidget* parent, QSettings * gameSettings, SDLInteraction * sdli);
 
     QPushButton *BtnGo;
     QPushButton *BtnMaster;
@@ -48,9 +48,6 @@
     TeamSelWidget* pNetTeamsWidget;
     GameCFGWidget* pGameCFG;
 
-private:
-    QPushButton *BtnBack;
-
 public slots:
     void setReadyStatus(bool isReady);
     void onUpdateClick();
@@ -59,6 +56,16 @@
 signals:
     void SetupClicked();
     void askForUpdateRoomName(const QString &);
+
+private:
+    QLayout * bodyLayoutDefinition();
+    QLayout * footerLayoutDefinition();
+    void connectSignals();
+
+    QSettings * m_gameSettings;
+    SDLInteraction * m_sdli;
+
+    QPushButton * btnSetup;
 };
 
 #endif
--- a/QTfrontend/pagenetserver.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagenetserver.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -17,6 +17,8 @@
  */
 
 #include <QGridLayout>
+#include <QHBoxLayout>
+#include <QVBoxLayout>
 #include <QPushButton>
 #include <QGroupBox>
 #include <QLabel>
@@ -25,29 +27,12 @@
 
 #include "pagenetserver.h"
 
-PageNetServer::PageNetServer(QWidget* parent) : AbstractPage(parent)
+QLayout * PageNetServer::bodyLayoutDefinition()
 {
-    QFont * font14 = new QFont("MS Shell Dlg", 14);
-    QGridLayout * pageLayout = new QGridLayout(this);
-    pageLayout->setColumnStretch(0, 1);
-    pageLayout->setColumnStretch(1, 1);
-    pageLayout->setColumnStretch(2, 1);
-
-    pageLayout->setRowStretch(0, 1);
-    pageLayout->setRowStretch(1, 0);
-
-
-    BtnBack =addButton(":/res/Exit.png", pageLayout, 1, 0, true);
-    connect(BtnBack, SIGNAL(clicked()), this, SIGNAL(goBack()));
-
-
-    BtnStart = new QPushButton(this);
-    BtnStart->setFont(*font14);
-    BtnStart->setText(QPushButton::tr("Start"));
-    pageLayout->addWidget(BtnStart, 1, 2);
+    QVBoxLayout * pageLayout = new QVBoxLayout();
 
     QWidget * wg = new QWidget(this);
-    pageLayout->addWidget(wg, 0, 0, 1, 3);
+    pageLayout->addWidget(wg);
 
     QGridLayout * wgLayout = new QGridLayout(wg);
     wgLayout->setColumnStretch(0, 1);
@@ -82,9 +67,33 @@
     BtnDefault->setText(QPushButton::tr("default"));
     gbLayout->addWidget(BtnDefault, 1, 2);
 
+    return pageLayout;
+}
+
+QLayout * PageNetServer::footerLayoutDefinition()
+{
+    QHBoxLayout * bottomLayout = new QHBoxLayout();
+
+    BtnStart = new QPushButton(this);
+    BtnStart->setFont(*font14);
+    BtnStart->setText(QPushButton::tr("Start"));
+
+    bottomLayout->addStretch();
+    bottomLayout->addWidget(BtnStart);
+
+    return bottomLayout;
+}
+
+void PageNetServer::connectSignals()
+{
     connect(BtnDefault, SIGNAL(clicked()), this, SLOT(setDefaultPort()));
 }
 
+PageNetServer::PageNetServer(QWidget* parent) : AbstractPage(parent)
+{
+    initPage();
+}
+
 void PageNetServer::setDefaultPort()
 {
     sbPort->setValue(46631);
--- a/QTfrontend/pagenetserver.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagenetserver.h	Tue Sep 27 00:38:39 2011 +0200
@@ -35,8 +35,10 @@
     QLabel *labelPort;
     QSpinBox *sbPort;
 
-private:
-    QPushButton *BtnBack;
+protected:
+    QLayout * bodyLayoutDefinition();
+    QLayout * footerLayoutDefinition();
+    void connectSignals();
 
 private slots:
     void setDefaultPort();
--- a/QTfrontend/pagenettype.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagenettype.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -21,9 +21,10 @@
 
 #include "pagenettype.h"
 
-PageNetType::PageNetType(QWidget* parent) : AbstractPage(parent)
+
+QLayout * PageNetType::bodyLayoutDefinition()
 {
-    QGridLayout * pageLayout = new QGridLayout(this);
+    QGridLayout * pageLayout = new QGridLayout();
     pageLayout->setRowStretch(0, 10);
     pageLayout->setRowStretch(3, 10);
 
@@ -37,7 +38,10 @@
     // hack: temporary deactivated - requires server modifications that aren't backward compatible (yet)
     //BtnOfficialServer->setEnabled(false);
 
+    return pageLayout;
+}
 
-    BtnBack = addButton(":/res/Exit.png", pageLayout, 4, 0, true);
-    connect(BtnBack, SIGNAL(clicked()), this, SIGNAL(goBack()));
+PageNetType::PageNetType(QWidget* parent) : AbstractPage(parent)
+{
+    initPage();
 }
--- a/QTfrontend/pagenettype.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagenettype.h	Tue Sep 27 00:38:39 2011 +0200
@@ -31,8 +31,8 @@
     QPushButton * BtnLAN;
     QPushButton * BtnOfficialServer;
 
-private:
-    QPushButton * BtnBack;
+protected:
+    QLayout * bodyLayoutDefinition();
 };
 
 #endif
--- a/QTfrontend/pageoptions.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pageoptions.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -17,6 +17,7 @@
  */
 
 #include <QGridLayout>
+#include <QHBoxLayout>
 #include <QPushButton>
 #include <QGroupBox>
 #include <QComboBox>
@@ -33,10 +34,10 @@
 #include "fpsedit.h"
 #include "igbox.h"
 
-PageOptions::PageOptions(QWidget* parent) :
-  AbstractPage(parent)
+// TODO cleanup
+QLayout * PageOptions::bodyLayoutDefinition()
 {
-    QGridLayout * pageLayout = new QGridLayout(this);
+    QGridLayout * pageLayout = new QGridLayout();
     pageLayout->setColumnStretch(0, 100);
     pageLayout->setColumnStretch(1, 100);
     pageLayout->setColumnStretch(2, 100);
@@ -298,12 +299,10 @@
             CBResolution = new QComboBox(AGGroupBox);
             GBAreslayout->addWidget(CBResolution);
             GBAlayout->addLayout(GBAreslayout);
-            connect(CBResolution, SIGNAL(currentIndexChanged(int)), this, SLOT(setResolution(int)));
 
             CBFullscreen = new QCheckBox(AGGroupBox);
             CBFullscreen->setText(QCheckBox::tr("Fullscreen"));
             GBAlayout->addWidget(CBFullscreen);
-            connect(CBFullscreen, SIGNAL(stateChanged(int)), this, SLOT(setFullscreen(int)));
 
             QLabel * quality = new QLabel(AGGroupBox);
             quality->setText(QLabel::tr("Quality"));
@@ -317,7 +316,6 @@
             SLQuality->setFixedWidth(150);
             GBAqualayout->addWidget(SLQuality);
             GBAlayout->addLayout(GBAqualayout);
-            connect(SLQuality, SIGNAL(valueChanged(int)), this, SLOT(setQuality(int)));
 
             QLabel * stereo = new QLabel(AGGroupBox);
             stereo->setText(QLabel::tr("Stereo rendering"));
@@ -401,19 +399,32 @@
             gbTBLayout->addWidget(AGGroupBox, 0, 1, 3, 1);
         }
 
-    BtnSaveOptions = addButton(":/res/Save.png", pageLayout, 2, 2, true);
-    BtnSaveOptions->setStyleSheet("QPushButton{margin: 12px 0px 12px 0px;}");
-
-
-    BtnBack = addButton(":/res/Exit.png", pageLayout, 2, 0, true);
-    BtnBack->setFixedHeight(BtnSaveOptions->height());
-    BtnBack->setFixedWidth(BtnBack->width()+2);
-    BtnBack->setStyleSheet("QPushButton{margin: 22px 0 9px 2px;}");
-    connect(BtnBack, SIGNAL(clicked()), this, SIGNAL(goBack()));
-
     previousQuality = this->SLQuality->value();
     previousResolutionIndex = this->CBResolution->currentIndex();
     previousFullscreenValue = this->CBFullscreen->isChecked();
+
+    return pageLayout;
+}
+
+QLayout * PageOptions::footerLayoutDefinition()
+{
+    QHBoxLayout * bottomLayout = new QHBoxLayout();
+    btnSave = addButton(":/res/Save.png", bottomLayout, 0, true);
+    btnSave->setStyleSheet("QPushButton{margin: 24px 0 0 0;}");
+    bottomLayout->setAlignment(btnSave, Qt::AlignRight | Qt::AlignBottom);
+    return bottomLayout;
+}
+
+void PageOptions::connectSignals()
+{
+    connect(CBResolution, SIGNAL(currentIndexChanged(int)), this, SLOT(setResolution(int)));
+    connect(CBFullscreen, SIGNAL(stateChanged(int)), this, SLOT(setFullscreen(int)));
+    connect(SLQuality, SIGNAL(valueChanged(int)), this, SLOT(setQuality(int)));
+}
+
+PageOptions::PageOptions(QWidget* parent) : AbstractPage(parent)
+{
+    initPage();
 }
 
 void PageOptions::forceFullscreen(int index)
@@ -479,4 +490,3 @@
     CBTeamName->setVisible(enabled);
     LblNoEditTeam->setVisible(!enabled);
 }
-
--- a/QTfrontend/pageoptions.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pageoptions.h	Tue Sep 27 00:38:39 2011 +0200
@@ -63,7 +63,7 @@
 #endif
 
     FPSEdit *fpsedit;
-    QPushButton *BtnSaveOptions;
+    QPushButton *btnSave;
     QLabel *labelNN;
     QLabel *labelNetPassword;
     QSpinBox * volumeBox;
@@ -81,6 +81,10 @@
 
 
 private:
+    QLayout * bodyLayoutDefinition();
+    QLayout * footerLayoutDefinition();
+    void connectSignals();
+
     bool previousFullscreenValue;
     int previousResolutionIndex;
     int previousQuality;
@@ -88,7 +92,6 @@
     QPushButton *BtnNewTeam;
     QPushButton *BtnEditTeam;
     QPushButton *BtnDeleteTeam;
-    QPushButton *BtnBack;
 
 private slots:
     void forceFullscreen(int index);
--- a/QTfrontend/pageplayrecord.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pageplayrecord.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -28,10 +28,10 @@
 #include "hwconsts.h"
 #include "pageplayrecord.h"
 
-PagePlayDemo::PagePlayDemo(QWidget* parent) : AbstractPage(parent)
+QLayout * PagePlayDemo::bodyLayoutDefinition()
 {
-    QFont * font14 = new QFont("MS Shell Dlg", 14);
-    QGridLayout * pageLayout = new QGridLayout(this);
+    QGridLayout * pageLayout = new QGridLayout();
+    
     pageLayout->setColumnStretch(0, 1);
     pageLayout->setColumnStretch(1, 2);
     pageLayout->setColumnStretch(2, 1);
@@ -54,12 +54,18 @@
     DemosList->setGeometry(QRect(170, 10, 311, 311));
     pageLayout->addWidget(DemosList, 0, 1, 3, 1);
 
+    return pageLayout;
+}
+
+void PagePlayDemo::connectSignals()
+{
     connect(BtnRenameRecord, SIGNAL(clicked()), this, SLOT(renameRecord()));
     connect(BtnRemoveRecord, SIGNAL(clicked()), this, SLOT(removeRecord()));
-
+}
 
-    BtnBack = addButton(":/res/Exit.png", pageLayout, 3, 0, true);
-    connect(BtnBack, SIGNAL(clicked()), this, SIGNAL(goBack()));
+PagePlayDemo::PagePlayDemo(QWidget* parent) : AbstractPage(parent)
+{
+    initPage();
 }
 
 void PagePlayDemo::FillFromDir(RecordType rectype)
--- a/QTfrontend/pageplayrecord.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pageplayrecord.h	Tue Sep 27 00:38:39 2011 +0200
@@ -47,8 +47,10 @@
     QListWidget *DemosList;
 
 private:
+    QLayout * bodyLayoutDefinition();
+    void connectSignals();
+
     RecordType recType;
-    QPushButton *BtnBack;
 
 private slots:
     void renameRecord();
--- a/QTfrontend/pageroomslist.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pageroomslist.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -30,10 +30,9 @@
 #include "hwconsts.h"
 #include "chatwidget.h"
 
-PageRoomsList::PageRoomsList(QWidget* parent, QSettings * gameSettings, SDLInteraction * sdli) :
-  AbstractPage(parent)
+QLayout * PageRoomsList::bodyLayoutDefinition()
 {
-    QGridLayout * pageLayout = new QGridLayout(this);
+    QGridLayout * pageLayout = new QGridLayout();
 
     QHBoxLayout * newRoomLayout = new QHBoxLayout();
     QLabel * roomNameLabel = new QLabel(this);
@@ -57,11 +56,8 @@
     QHBoxLayout * filterLayout = new QHBoxLayout();
 
     QLabel * stateLabel = new QLabel(this);
-    stateLabel->setText(tr("State:"));
     CBState = new QComboBox(this);
-    CBState->addItem(QComboBox::tr("Any"));
-    CBState->addItem(QComboBox::tr("In lobby"));
-    CBState->addItem(QComboBox::tr("In progress"));
+
     filterLayout->addWidget(stateLabel);
     filterLayout->addWidget(CBState);
     filterLayout->addSpacing(30);
@@ -69,11 +65,7 @@
     QLabel * ruleLabel = new QLabel(this);
     ruleLabel->setText(tr("Rules:"));
     CBRules = new QComboBox(this);
-    CBRules->addItem(QComboBox::tr("Any"));
-    // not the most elegant solution but it works
-    ammoSchemeModel = new AmmoSchemeModel(this, NULL);
-    for (int i = 0; i < ammoSchemeModel->predefSchemesNames.count(); i++)
-        CBRules->addItem(ammoSchemeModel->predefSchemesNames.at(i).toAscii().constData());
+
     filterLayout->addWidget(ruleLabel);
     filterLayout->addWidget(CBRules);
     filterLayout->addSpacing(30);
@@ -81,11 +73,7 @@
     QLabel * weaponLabel = new QLabel(this);
     weaponLabel->setText(tr("Weapons:"));
     CBWeapons = new QComboBox(this);
-    CBWeapons->addItem(QComboBox::tr("Any"));
-    for (int i = 0; i < cDefaultAmmos.count(); i++) {
-        QPair<QString,QString> ammo = cDefaultAmmos.at(i);
-        CBWeapons->addItem(ammo.first.toAscii().constData());
-    }
+
     filterLayout->addWidget(weaponLabel);
     filterLayout->addWidget(CBWeapons);
     filterLayout->addSpacing(30);
@@ -99,7 +87,7 @@
 
     pageLayout->addLayout(filterLayout, 4, 0, 1, 2);
 
-    chatWidget = new HWChatWidget(this, gameSettings, sdli, false);
+    chatWidget = new HWChatWidget(this, m_gameSettings, m_sdli, false);
     pageLayout->addWidget(chatWidget, 5, 0, 1, 3);
     pageLayout->setRowStretch(5, 350);
 
@@ -108,19 +96,31 @@
     BtnRefresh = addButton(tr("Refresh"), pageLayout, 3, 2);
     BtnClear = addButton(tr("Clear"), pageLayout, 4, 2);
 
+    CBRules->addItem(QComboBox::tr("Any"));
+    CBState->addItem(QComboBox::tr("Any"));
+    CBState->addItem(QComboBox::tr("In lobby"));
+    CBState->addItem(QComboBox::tr("In progress"));
 
-    BtnBack = addButton(":/res/Exit.png", pageLayout, 6, 0, true);
-    connect(BtnBack, SIGNAL(clicked()), this, SIGNAL(goBack()));
+    return pageLayout;
+}
 
+QLayout * PageRoomsList::footerLayoutDefinition()
+{
+    QGridLayout * bottomLayout = new QGridLayout();
 
     lblCount = new QLabel(this);
-    pageLayout->addWidget(lblCount, 6, 1, Qt::AlignHCenter);
+    bottomLayout->addWidget(lblCount, 0, 0, Qt::AlignHCenter);
     lblCount->setText("?");
     lblCount->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
 
-    connect(chatWidget, SIGNAL(nickCountUpdate(const int)), this, SLOT(updateNickCounter(const int)));
+    BtnAdmin = addButton(tr("Admin features"), bottomLayout, 6, 2);
 
-    BtnAdmin = addButton(tr("Admin features"), pageLayout, 6, 2);
+    return bottomLayout;
+}
+
+void PageRoomsList::connectSignals()
+{
+    connect(chatWidget, SIGNAL(nickCountUpdate(const int)), this, SLOT(updateNickCounter(const int)));
 
     connect(BtnCreate, SIGNAL(clicked()), this, SLOT(onCreateClick()));
     connect(BtnJoin, SIGNAL(clicked()), this, SLOT(onJoinClick()));
@@ -132,6 +132,27 @@
     connect(CBWeapons, SIGNAL(currentIndexChanged (int)), this, SLOT(onRefreshClick()));
     connect(searchText, SIGNAL(textChanged (const QString &)), this, SLOT(onRefreshClick()));
     connect(this, SIGNAL(askJoinConfirmation (const QString &)), this, SLOT(onJoinConfirmation(const QString &)), Qt::QueuedConnection);
+}
+
+
+PageRoomsList::PageRoomsList(QWidget* parent, QSettings * gameSettings, SDLInteraction * sdli) :
+  AbstractPage(parent)
+{
+    m_gameSettings = gameSettings;
+    m_sdli = sdli;
+
+    initPage();
+
+    // not the most elegant solution but it works
+    ammoSchemeModel = new AmmoSchemeModel(this, NULL);
+    for (int i = 0; i < ammoSchemeModel->predefSchemesNames.count(); i++)
+        CBRules->addItem(ammoSchemeModel->predefSchemesNames.at(i).toAscii().constData());
+
+    CBWeapons->addItem(QComboBox::tr("Any"));
+    for (int i = 0; i < cDefaultAmmos.count(); i++) {
+        QPair<QString,QString> ammo = cDefaultAmmos.at(i);
+        CBWeapons->addItem(ammo.first.toAscii().constData());
+    }
 
     gameInLobby = false;
 }
@@ -396,4 +417,3 @@
 {
     lblCount->setText(tr("%1 players online", 0, cnt).arg(cnt));
 }
-
--- a/QTfrontend/pageroomslist.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pageroomslist.h	Tue Sep 27 00:38:39 2011 +0200
@@ -46,18 +46,22 @@
     HWChatWidget * chatWidget;
     QLabel * lblCount;
 
-private:
-    bool gameInLobby;
-    QString gameInLobbyName;
-    QStringList listFromServer;
-    AmmoSchemeModel * ammoSchemeModel;
-    QPushButton * BtnBack;
-
 public slots:
     void setRoomsList(const QStringList & list);
     void setAdmin(bool);
     void updateNickCounter(int cnt);
 
+signals:
+    void askForCreateRoom(const QString &);
+    void askForJoinRoom(const QString &);
+    void askForRoomList();
+    void askJoinConfirmation(const QString &);
+
+protected:
+    QLayout * bodyLayoutDefinition();
+    QLayout * footerLayoutDefinition();
+    void connectSignals();
+
 private slots:
     void onCreateClick();
     void onJoinClick();
@@ -65,11 +69,15 @@
     void onClearClick();
     void onJoinConfirmation(const QString &);
 
-signals:
-    void askForCreateRoom(const QString &);
-    void askForJoinRoom(const QString &);
-    void askForRoomList();
-    void askJoinConfirmation(const QString &);
+private:
+    QSettings * m_gameSettings;
+    SDLInteraction * m_sdli;
+
+    bool gameInLobby;
+    QString gameInLobbyName;
+    QStringList listFromServer;
+    AmmoSchemeModel * ammoSchemeModel;
+
 };
 
 #endif
--- a/QTfrontend/pagescheme.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagescheme.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -17,6 +17,7 @@
  */
 
 #include <QGridLayout>
+#include <QHBoxLayout>
 #include <QPushButton>
 #include <QGroupBox>
 #include <QComboBox>
@@ -30,10 +31,10 @@
 #include "pagescheme.h"
 #include "misc.h"
 
-PageScheme::PageScheme(QWidget* parent) :
-    AbstractPage(parent)
+
+QLayout * PageScheme::bodyLayoutDefinition()
 {
-    QGridLayout * pageLayout = new QGridLayout(this);
+    QGridLayout * pageLayout = new QGridLayout();
     QGroupBox * gb = new QGroupBox(this);
 
     QGridLayout * gl = new QGridLayout();
@@ -47,6 +48,7 @@
     gbGameModes = new QGroupBox(QGroupBox::tr("Game Modifiers"), gb);
     gbBasicSettings = new QGroupBox(QGroupBox::tr("Basic Settings"), gb);
 
+    // TODO name stuff and put CSS into main style sheet
     gbGameModes->setStyleSheet(".QGroupBox {"
             "background-color: #130f2c; background-image:url();"
             "}");
@@ -388,27 +390,41 @@
     gl->addWidget(LE_name,15,1,1,5);
     gl->addWidget(l,15,0,1,1);
 
-    mapper = new QDataWidgetMapper(this);
-
+    return pageLayout;
+}
 
-    BtnBack = addButton(":/res/Exit.png", pageLayout, 16, 0, true);
-    connect(BtnBack, SIGNAL(clicked()), this, SIGNAL(goBack()));
-
+QLayout * PageScheme::footerLayoutDefinition()
+{
+    QHBoxLayout * bottomLayout = new QHBoxLayout();
+    selectScheme = new QComboBox(this);
 
-    BtnCopy = addButton(tr("Copy"), pageLayout, 16, 2);
-    BtnNew = addButton(tr("New"), pageLayout, 16, 3);
-    BtnDelete = addButton(tr("Delete"), pageLayout, 16, 4);
+    bottomLayout->addWidget(selectScheme, 0);
+    BtnCopy = addButton(tr("Copy"), bottomLayout, 1);
+    BtnNew = addButton(tr("New"), bottomLayout, 2);
+    BtnDelete = addButton(tr("Delete"), bottomLayout, 3);
 
-    selectScheme = new QComboBox(this);
-    pageLayout->addWidget(selectScheme, 16, 1);
+    bottomLayout->setStretch(1,1);
+    bottomLayout->setStretch(2,1);
+    bottomLayout->setStretch(3,1);
 
+    return bottomLayout;
+}
+
+void PageScheme::connectSignals()
+{
     connect(BtnCopy, SIGNAL(clicked()), this, SLOT(copyRow()));
     connect(BtnNew, SIGNAL(clicked()), this, SLOT(newRow()));
     connect(BtnDelete, SIGNAL(clicked()), this, SLOT(deleteRow()));
+    mapper = new QDataWidgetMapper(this);
     connect(selectScheme, SIGNAL(currentIndexChanged(int)), mapper, SLOT(setCurrentIndex(int)));
     connect(selectScheme, SIGNAL(currentIndexChanged(int)), this, SLOT(schemeSelected(int)));
 }
 
+PageScheme::PageScheme(QWidget* parent) : AbstractPage(parent)
+{
+    initPage();
+}
+
 void PageScheme::setModel(QAbstractItemModel * model)
 {
     mapper->setModel(model);
@@ -490,3 +506,5 @@
     gbBasicSettings->setEnabled(n >= c);
     LE_name->setEnabled(n >= c);
 }
+
+
--- a/QTfrontend/pagescheme.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagescheme.h	Tue Sep 27 00:38:39 2011 +0200
@@ -34,7 +34,7 @@
     QPushButton * BtnCopy;
     QPushButton * BtnNew;
     QPushButton * BtnDelete;
-    QPushButton * BtnSave;
+    QPushButton * btnSave;
     QComboBox * selectScheme;
 
     void setModel(QAbstractItemModel * model);
@@ -44,9 +44,12 @@
     void copyRow();
     void deleteRow();
 
+protected:
+    QLayout * bodyLayoutDefinition();
+    QLayout * footerLayoutDefinition();
+    void connectSignals();
+
 private:
-    QPushButton * BtnBack;
-
     QDataWidgetMapper * mapper;
     ToggleButtonWidget * TBW_mode_Forts;
     ToggleButtonWidget * TBW_teamsDivide;
@@ -96,7 +99,6 @@
 
 private slots:
     void schemeSelected(int);
-
 };
 
 #endif
--- a/QTfrontend/pageselectweapon.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pageselectweapon.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -17,6 +17,7 @@
  */
 
 #include <QGridLayout>
+#include <QHBoxLayout>
 #include <QPushButton>
 #include <QComboBox>
 
@@ -24,34 +25,51 @@
 #include "hwconsts.h"
 #include "selectWeapon.h"
 
-PageSelectWeapon::PageSelectWeapon(QWidget* parent) :
-  AbstractPage(parent)
+QLayout * PageSelectWeapon::bodyLayoutDefinition()
 {
-    QGridLayout * pageLayout = new QGridLayout(this);
+    QGridLayout * pageLayout = new QGridLayout();
 
     pWeapons = new SelWeaponWidget(cAmmoNumber, this);
-    pageLayout->addWidget(pWeapons, 0, 0, 1, 5);
-
-
-    BtnBack = addButton(":/res/Exit.png", pageLayout, 1, 0, 2, 1, true);
-    connect(BtnBack, SIGNAL(clicked()), this, SIGNAL(goBack()));
-
+    pageLayout->addWidget(pWeapons);
 
-    BtnDefault = addButton(tr("Default"), pageLayout, 1, 3);
-    BtnNew = addButton(tr("New"), pageLayout, 1, 2);
-    BtnCopy = addButton(tr("Copy"), pageLayout, 2, 2);
-    BtnDelete = addButton(tr("Delete"), pageLayout, 2, 3);
-    BtnSave = addButton(":/res/Save.png", pageLayout, 1, 4, 2, 1, true);
-    BtnSave->setStyleSheet("QPushButton{margin: 24px 0px 0px 0px;}");
-    BtnBack->setFixedHeight(BtnSave->height());
-    BtnBack->setStyleSheet("QPushButton{margin-top: 31px;}");
+    return pageLayout;
+}
+
+QLayout * PageSelectWeapon::footerLayoutDefinition()
+{
+    QGridLayout * bottomLayout = new QGridLayout();
 
     selectWeaponSet = new QComboBox(this);
-    pageLayout->addWidget(selectWeaponSet, 1, 1, 2, 1);
+    bottomLayout->addWidget(selectWeaponSet, 0, 0, 2, 1);
+
+    // first row
+    BtnNew = addButton(tr("New"), bottomLayout, 0, 1);
+    BtnDefault = addButton(tr("Default"), bottomLayout, 0, 2);
+
+    // second row
+    BtnCopy = addButton(tr("Copy"), bottomLayout, 1, 1);
+    BtnDelete = addButton(tr("Delete"), bottomLayout, 1, 2);
 
+    bottomLayout->setColumnStretch(1,1);
+    bottomLayout->setColumnStretch(2,1);
+
+    btnSave = addButton(":/res/Save.png", bottomLayout, 0, 3, 2, 1, true);
+    btnSave->setStyleSheet("QPushButton{margin: 24px 0 0 0;}");
+    bottomLayout->setAlignment(btnSave, Qt::AlignRight | Qt::AlignBottom);
+
+    return bottomLayout;
+}
+
+void PageSelectWeapon::connectSignals()
+{
     connect(BtnDefault, SIGNAL(clicked()), pWeapons, SLOT(setDefault()));
-    connect(BtnSave, SIGNAL(clicked()), pWeapons, SLOT(save()));
+    connect(btnSave, SIGNAL(clicked()), pWeapons, SLOT(save()));
     connect(BtnNew, SIGNAL(clicked()), pWeapons, SLOT(newWeaponsName()));
     connect(BtnCopy, SIGNAL(clicked()), pWeapons, SLOT(copy()));
     connect(selectWeaponSet, SIGNAL(currentIndexChanged(const QString&)), pWeapons, SLOT(setWeaponsName(const QString&)));
 }
+
+PageSelectWeapon::PageSelectWeapon(QWidget* parent) :  AbstractPage(parent)
+{
+    initPage();
+}
--- a/QTfrontend/pageselectweapon.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pageselectweapon.h	Tue Sep 27 00:38:39 2011 +0200
@@ -30,7 +30,7 @@
 public:
     PageSelectWeapon(QWidget* parent = 0);
 
-    QPushButton *BtnSave;
+    QPushButton *btnSave;
     QPushButton *BtnDefault;
     QPushButton *BtnDelete;
     QPushButton *BtnNew;
@@ -38,8 +38,10 @@
     SelWeaponWidget* pWeapons;
     QComboBox* selectWeaponSet;
 
-private:
-    QPushButton *BtnBack;
+protected:
+    QLayout * bodyLayoutDefinition();
+    QLayout * footerLayoutDefinition();
+    void connectSignals();
 };
 
 #endif
--- a/QTfrontend/pagesingleplayer.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagesingleplayer.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -22,18 +22,17 @@
 #include "pagesingleplayer.h"
 #include "gamecfgwidget.h"
 
-PageSinglePlayer::PageSinglePlayer(QWidget* parent) : AbstractPage(parent)
+QLayout * PageSinglePlayer::bodyLayoutDefinition()
 {
-    QVBoxLayout * vLayout = new QVBoxLayout(this);
+    QVBoxLayout * vLayout = new QVBoxLayout();
+
     QHBoxLayout * topLine = new QHBoxLayout();
     QHBoxLayout * middleLine = new QHBoxLayout();
-    QHBoxLayout * bottomLine = new QHBoxLayout();
     vLayout->addStretch();
     vLayout->addLayout(topLine);
     vLayout->addSpacing(30);
     vLayout->addLayout(middleLine);
     vLayout->addStretch();
-    vLayout->addLayout(bottomLine);
 
     topLine->addStretch();
     BtnSimpleGamePage = addButton(":/res/SimpleGame.png", topLine, 0, true);
@@ -51,18 +50,34 @@
     BtnTrainPage = addButton(":/res/Trainings.png", middleLine, 1, true);
     BtnTrainPage->setToolTip(tr("Training Mode (Practice your skills in a range of training missions). IN DEVELOPMENT"));
 
+    return vLayout;
+}
 
-    BtnBack = addButton(":/res/Exit.png", bottomLine, 0, true);
-    connect(BtnBack, SIGNAL(clicked()), this, SIGNAL(goBack()));
-
-
+QLayout * PageSinglePlayer::footerLayoutDefinition()
+{
+    QHBoxLayout * bottomLine = new QHBoxLayout();
     bottomLine->addStretch();
 
     BtnDemos = addButton(":/res/Record.png", bottomLine, 1, true);
     BtnDemos->setToolTip(tr("Demos (Watch recorded demos)"));
-    BtnLoad = addButton(":/res/Save.png", bottomLine, 2, true);
-    BtnLoad->setStyleSheet("QPushButton{margin: 12px 0px 12px 0px;}");
+    BtnLoad = addButton(":/res/Load.png", bottomLine, 2, true);
+    BtnLoad->setStyleSheet("QPushButton{margin: 24px 0 0 0;}");
     BtnLoad->setToolTip(tr("Load (Load a previously saved game)"));
-    BtnBack->setFixedHeight(BtnLoad->height());
-    BtnBack->setStyleSheet("QPushButton{margin-top: 31px;}");
+
+    bottomLine->setStretch(1,0);
+    bottomLine->setStretch(2,0);
+    bottomLine->setAlignment(BtnDemos, Qt::AlignRight | Qt::AlignBottom);
+    bottomLine->setAlignment(BtnLoad, Qt::AlignRight | Qt::AlignBottom);
+
+    return bottomLine;
 }
+
+void PageSinglePlayer::connectSignals()
+{
+    //TODO
+}
+
+PageSinglePlayer::PageSinglePlayer(QWidget* parent) : AbstractPage(parent)
+{
+    initPage();
+}
--- a/QTfrontend/pagesingleplayer.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagesingleplayer.h	Tue Sep 27 00:38:39 2011 +0200
@@ -39,7 +39,9 @@
     GameCFGWidget *gameCFG;
 
 private:
-    QPushButton *BtnBack;
+    QLayout * bodyLayoutDefinition();
+    QLayout * footerLayoutDefinition();
+    void connectSignals();
 };
 
 #endif
--- a/QTfrontend/pagetraining.cpp	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagetraining.cpp	Tue Sep 27 00:38:39 2011 +0200
@@ -23,9 +23,10 @@
 #include "pagetraining.h"
 #include "hwconsts.h"
 
-PageTraining::PageTraining(QWidget* parent) : AbstractPage(parent)
+QLayout * PageTraining::bodyLayoutDefinition()
 {
-    QGridLayout * pageLayout = new QGridLayout(this);
+    QGridLayout * pageLayout = new QGridLayout();
+
     pageLayout->setColumnStretch(0, 1);
     pageLayout->setColumnStretch(1, 2);
     pageLayout->setColumnStretch(2, 1);
@@ -34,28 +35,6 @@
 
     CBSelect = new QComboBox(this);
 
-    QDir tmpdir;
-    tmpdir.cd(cfgdir->absolutePath());
-    tmpdir.cd("Data/Missions/Training");
-    tmpdir.setFilter(QDir::Files);
-    QStringList userlist = tmpdir.entryList(QStringList("*.lua")).replaceInStrings(QRegExp("^(.*)\\.lua"), "\\1");
-    CBSelect->addItems(userlist);
-
-    tmpdir.cd(datadir->absolutePath());
-    tmpdir.cd("Missions/Training");
-    tmpdir.setFilter(QDir::Files);
-    QStringList tmplist = tmpdir.entryList(QStringList("*.lua")).replaceInStrings(QRegExp("^(.*)\\.lua"), "\\1");
-    QStringList datalist;
-    for (QStringList::Iterator it = tmplist.begin(); it != tmplist.end(); ++it)
-        if (!userlist.contains(*it,Qt::CaseInsensitive)) datalist.append(*it);
-    CBSelect->addItems(datalist);
-
-    for(int i = 0; i < CBSelect->count(); i++)
-    {
-        CBSelect->setItemData(i, CBSelect->itemText(i));
-        CBSelect->setItemText(i, CBSelect->itemText(i).replace("_", " "));
-    }
-
     pageLayout->addWidget(CBSelect, 1, 1);
     
     BtnStartTrain = new QPushButton(this);
@@ -63,7 +42,49 @@
     BtnStartTrain->setText(QPushButton::tr("Go!"));
     pageLayout->addWidget(BtnStartTrain, 1, 2);
 
+    return pageLayout;
+}
 
-    BtnBack = addButton(":/res/Exit.png", pageLayout, 3, 0, true);
-    connect(BtnBack, SIGNAL(clicked()), this, SIGNAL(goBack()));
+void PageTraining::connectSignals()
+{
+    //TODO
 }
+
+PageTraining::PageTraining(QWidget* parent) : AbstractPage(parent)
+{
+    initPage();
+
+    QDir tmpdir;
+    tmpdir.cd(cfgdir->absolutePath());
+    tmpdir.cd("Data/Missions/Training");
+    QStringList userlist = scriptList(tmpdir);
+
+    tmpdir.cd(datadir->absolutePath());
+    tmpdir.cd("Missions/Training");
+    QStringList defaultlist = scriptList(tmpdir);
+
+    CBSelect->addItems(userlist);
+
+    // add only default scripts that have names different from detected user scripts
+    foreach (const QString & line, defaultlist)
+    {
+        if (!userlist.contains(line,Qt::CaseInsensitive)) CBSelect->addItem(line);
+    }
+
+    // replace underscores with spaces in the displayed that
+    for(int i = 0; i < CBSelect->count(); i++)
+    {
+        QString text = CBSelect->itemText(i);
+        CBSelect->setItemData(i, text);
+        CBSelect->setItemText(i, text.replace("_", " "));
+//        if (userlist.contains(text))
+//            CBSelect->setItemText(i, text + " (" + AbstractPage::tr("custom") + ")");
+    }
+}
+
+QStringList PageTraining::scriptList(const QDir & scriptDir) const
+{
+    QDir dir = scriptDir;
+    dir.setFilter(QDir::Files);
+    return dir.entryList(QStringList("*.lua")).replaceInStrings(QRegExp("^(.*)\\.lua"), "\\1");
+}
--- a/QTfrontend/pagetraining.h	Mon Sep 26 21:45:33 2011 +0400
+++ b/QTfrontend/pagetraining.h	Tue Sep 27 00:38:39 2011 +0200
@@ -19,6 +19,8 @@
 #ifndef PAGE_TRAINING_H
 #define PAGE_TRAINING_H
 
+#include <QDir>
+
 #include "AbstractPage.h"
 
 class PageTraining : public AbstractPage
@@ -31,8 +33,12 @@
     QPushButton *BtnStartTrain;
     QComboBox   *CBSelect;
 
+protected:
+    QLayout * bodyLayoutDefinition();
+    void connectSignals();
+
 private:
-    QPushButton *BtnBack;
+    QStringList scriptList(const QDir & scriptDir) const;
 };
 
 #endif
Binary file QTfrontend/res/Load.png has changed