QTfrontend/ui/widget/keybinder.cpp
changeset 8346 3443e0de2c9d
child 8434 4821897a0f10
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/QTfrontend/ui/widget/keybinder.cpp	Sat Dec 29 22:50:10 2012 +0100
@@ -0,0 +1,301 @@
+/*
+ * 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 "keybinder.h"
+#include "HWApplication.h"
+#include "DataManager.h"
+#include <QHBoxLayout>
+#include <QScrollArea>
+#include <QTableWidget>
+#include <QTableWidgetItem>
+#include <QStandardItemModel>
+#include <QAbstractItemModel>
+#include <QListWidget>
+#include <QListWidgetItem>
+#include <QPushButton>
+#include <QHeaderView>
+#include <QComboBox>
+#include <QLabel>
+#include <QFrame>
+#include <QDebug>
+
+KeyBinder::KeyBinder(QWidget * parent, const QString & helpText, const QString & defaultText, const QString & resetButtonText) : QWidget(parent)
+{
+    this->defaultText = defaultText;
+    enableSignal = false;
+    
+    // Two-column tab layout
+    QHBoxLayout * pageKeysLayout = new QHBoxLayout(this);
+    pageKeysLayout->setSpacing(0);
+    pageKeysLayout->setContentsMargins(0, 0, 0, 0);
+    
+    // Table for category list
+    QVBoxLayout * catListContainer = new QVBoxLayout();
+    catListContainer->setContentsMargins(10, 10, 10, 10);
+    catList = new QListWidget();
+    catList->setFixedWidth(180);
+    catList->setStyleSheet("QListWidget::item { font-size: 14px; } QListWidget:hover { border-color: #F6CB1C; } QListWidget::item:selected { background: #150A61; color: yellow; }");
+    catList->setFocusPolicy(Qt::NoFocus);
+    connect(catList, SIGNAL(currentRowChanged(int)), this, SLOT(changeBindingsPage(int)));
+    catListContainer->addWidget(catList);
+    pageKeysLayout->addLayout(catListContainer);
+
+    // Reset all binds button
+    if (!resetButtonText.isEmpty())
+    {
+        QPushButton * btnResetAll = new QPushButton(resetButtonText);
+        catListContainer->addWidget(btnResetAll);
+        btnResetAll->setFixedHeight(40);
+        catListContainer->setStretch(1, 0);
+        catListContainer->setSpacing(10);
+        connect(btnResetAll, SIGNAL(clicked()), this, SIGNAL(resetAllBinds()));
+    }
+
+    // Container for pages of key bindings
+    QWidget * bindingsPagesContainer = new QWidget();
+    QVBoxLayout * rightLayout = new QVBoxLayout(bindingsPagesContainer);
+
+    // Scroll area for key bindings
+    QScrollArea * scrollArea = new QScrollArea();
+    scrollArea->setContentsMargins(0, 0, 0, 0);
+    scrollArea->setWidget(bindingsPagesContainer);
+    scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+    scrollArea->setWidgetResizable(true);
+    scrollArea->setFrameShape(QFrame::NoFrame);
+    scrollArea->setStyleSheet("background: #130F2A;");
+
+    // Add key binding pages to bindings tab
+    pageKeysLayout->addWidget(scrollArea);
+    pageKeysLayout->setStretch(1, 1);
+
+    // Custom help text
+    QLabel * helpLabel = new QLabel();
+    helpLabel->setText(helpText);
+    helpLabel->setStyleSheet("color: #130F2A; background: #F6CB1C; border: solid 4px #F6CB1C; border-radius: 10px; padding: auto 20px;");
+    helpLabel->setFixedHeight(24);
+    rightLayout->addWidget(helpLabel, 0, Qt::AlignCenter);
+
+    // Category list and bind table row heights
+    const int rowHeight = 20;
+    QSize catSize, headerSize;
+    catSize.setHeight(36);
+    headerSize.setHeight(24);
+
+    // Category list header
+    QListWidgetItem * catListHeader = new QListWidgetItem(tr("Category"));
+    catListHeader->setSizeHint(headerSize);
+    catListHeader->setFlags(Qt::NoItemFlags);
+    catListHeader->setForeground(QBrush(QColor("#130F2A")));
+    catListHeader->setBackground(QBrush(QColor("#F6CB1C")));
+    catListHeader->setTextAlignment(Qt::AlignCenter);
+    catList->addItem(catListHeader);
+
+    // Populate
+    bindingsPages = new QHBoxLayout();
+    bindingsPages->setContentsMargins(0, 0, 0, 0);
+    rightLayout->addLayout(bindingsPages);
+    QWidget * curPage = NULL;
+    QVBoxLayout * curLayout = NULL;
+    QTableWidget * curTable = NULL;
+    bool bFirstPage = true;
+    selectedBindTable = NULL;
+    bindComboBoxCellMappings = new QHash<QObject *, QTableWidgetItem *>();
+    bindCellComboBoxMappings = new QHash<QTableWidgetItem *, QComboBox *>();
+    for (int i = 0; i < BINDS_NUMBER; i++)
+    {
+        if (cbinds[i].category != NULL)
+        {
+            // Add stretch at end of previous layout
+            if (curLayout != NULL) curLayout->insertStretch(-1, 1);
+            
+            // Category list item
+            QListWidgetItem * catItem = new QListWidgetItem(HWApplication::translate("binds (categories)", cbinds[i].category));
+            catItem->setSizeHint(catSize);
+            catList->addItem(catItem);
+            
+            // Create new page
+            curPage = new QWidget();
+            curLayout = new QVBoxLayout(curPage);
+            curLayout->setSpacing(2);
+            bindingsPages->addWidget(curPage);
+            if (!bFirstPage) curPage->setVisible(false);
+        }
+
+        // Description
+        if (cbinds[i].description != NULL)
+        {
+            QLabel * desc = new QLabel(HWApplication::translate("binds (descriptions)", cbinds[i].description));
+            curLayout->addWidget(desc, 0);
+            QFrame * divider = new QFrame();
+            divider->setFrameShape(QFrame::HLine);
+            divider->setFrameShadow(QFrame::Plain);
+            curLayout->addWidget(divider, 0);
+        }
+
+        // New table
+        if (cbinds[i].category != NULL || cbinds[i].description != NULL)
+        {
+            curTable = new QTableWidget(0, 2);
+            curTable->verticalHeader()->setVisible(false);
+            curTable->horizontalHeader()->setVisible(false);
+            curTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
+            curTable->verticalHeader()->setDefaultSectionSize(rowHeight);
+            curTable->setShowGrid(false);
+            curTable->setStyleSheet("QTableWidget { border: none; } ");
+            curTable->setSelectionBehavior(QAbstractItemView::SelectRows);
+            curTable->setSelectionMode(QAbstractItemView::SingleSelection);
+            curTable->setFocusPolicy(Qt::NoFocus);
+            connect(curTable, SIGNAL(itemSelectionChanged()), this, SLOT(bindSelectionChanged()));
+            connect(curTable, SIGNAL(itemClicked(QTableWidgetItem *)), this, SLOT(bindCellClicked(QTableWidgetItem *)));
+            curLayout->addWidget(curTable, 0);
+        }
+
+        // Hidden combo box
+        QComboBox * comboBox = CBBind[i] = new QComboBox(curTable);
+        comboBox->setModel((QAbstractItemModel*)DataManager::instance().bindsModel());
+        comboBox->setVisible(false);
+        comboBox->setFixedWidth(200);
+        
+        // Table row
+        int row = curTable->rowCount();
+        QTableWidgetItem * nameCell = new QTableWidgetItem(HWApplication::translate("binds", cbinds[i].name));
+        nameCell->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
+        curTable->insertRow(row);
+        curTable->setItem(row, 0, nameCell);
+        QTableWidgetItem * bindCell = new QTableWidgetItem(comboBox->currentText());
+        bindCell->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
+        curTable->setItem(row, 1, bindCell);
+        curTable->resizeColumnsToContents();
+        curTable->setFixedHeight(curTable->verticalHeader()->length() + 10);
+
+        // Updates the text in the table cell
+        connect(comboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(bindChanged(const QString &)));
+
+        // Map combo box and that row's cells to each other
+        bindComboBoxCellMappings->insert(comboBox, bindCell);
+        bindCellComboBoxMappings->insert(nameCell, comboBox);
+        bindCellComboBoxMappings->insert(bindCell, comboBox);
+    }
+
+    // Add stretch at end of last layout
+    if (curLayout != NULL) curLayout->insertStretch(-1, 1);
+
+    // Go to first page
+    catList->setCurrentItem(catList->item(1));
+
+    enableSignal = true;
+}
+
+KeyBinder::~KeyBinder()
+{
+    delete bindComboBoxCellMappings;
+    delete bindCellComboBoxMappings;
+}
+
+// Switches between different pages of key binds
+void KeyBinder::changeBindingsPage(int page)
+{
+    page--; // Disregard first item (the list header)
+    int pages = bindingsPages->count();
+    for (int i = 0; i < pages; i++)
+        bindingsPages->itemAt(i)->widget()->setVisible(false);
+    bindingsPages->itemAt(page)->widget()->setVisible(true);
+}
+
+// When a key bind combobox value is changed, updates the table cell text
+void KeyBinder::bindChanged(const QString & text)
+{
+    bindComboBoxCellMappings->value(sender())->setText(text);
+
+    if (enableSignal)
+    {
+        for (int i = 0; i < BINDS_NUMBER; i++)
+        {
+            if (CBBind[i] == sender())
+            {
+                emit bindUpdate(i);
+                break;
+            }
+        }
+    }
+}
+
+// When a row in a key bind table is clicked, this shows the popup
+void KeyBinder::bindCellClicked(QTableWidgetItem * item)
+{
+    QComboBox * box = bindCellComboBoxMappings->value(item);
+    QTableWidget * table = item->tableWidget();
+    QFrame * frame = box->findChild<QFrame*>();
+    
+    box->showPopup();
+    frame->move(
+        frame->x() + table->horizontalHeader()->sectionSize(0),
+        frame->y() + (table->verticalHeader()->defaultSectionSize() * item->row())
+    );
+}
+
+// When a new row in a bind table is *selected*, this clears selection in any other table
+void KeyBinder::bindSelectionChanged()
+{
+    QTableWidget * theSender = (QTableWidget*)sender();
+    if (theSender != selectedBindTable)
+    {
+        if (selectedBindTable != NULL)
+            selectedBindTable->clearSelection();
+        selectedBindTable = theSender;
+    }
+}
+
+// Set a combobox's index
+void KeyBinder::setBindIndex(int keyIndex, int bindIndex)
+{
+    enableSignal = false;
+    CBBind[keyIndex]->setCurrentIndex(bindIndex);
+    enableSignal = true;
+}
+
+// Return a combobox's selected index
+int KeyBinder::bindIndex(int keyIndex)
+{
+    return CBBind[keyIndex]->currentIndex();
+}
+
+// Clears selection and goes to first category
+void KeyBinder::resetInterface()
+{
+    enableSignal = false;
+    
+    catList->setCurrentItem(catList->item(1));
+    changeBindingsPage(1);
+    if (selectedBindTable != NULL)
+    {
+        selectedBindTable->clearSelection();
+        selectedBindTable = NULL;
+    }
+    
+    // Default bind text
+    DataManager::instance().bindsModel()->item(0)->setData(defaultText, Qt::DisplayRole);
+    for (int i = 0; i < BINDS_NUMBER; i++)
+    {
+        CBBind[i]->setModel(DataManager::instance().bindsModel());
+        CBBind[i]->setCurrentIndex(0);
+        bindComboBoxCellMappings->value(CBBind[i])->setText(defaultText);
+    }
+
+    enableSignal = true;
+}