/* * 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 bindsvoid 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 textvoid 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 popupvoid 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 tablevoid KeyBinder::bindSelectionChanged(){ QTableWidget * theSender = (QTableWidget*)sender(); if (theSender != selectedBindTable) { if (selectedBindTable != NULL) selectedBindTable->clearSelection(); selectedBindTable = theSender; }}// Set a combobox's indexvoid KeyBinder::setBindIndex(int keyIndex, int bindIndex){ enableSignal = false; CBBind[keyIndex]->setCurrentIndex(bindIndex); enableSignal = true;}// Return a combobox's selected indexint KeyBinder::bindIndex(int keyIndex){ return CBBind[keyIndex]->currentIndex();}// Clears selection and goes to first categoryvoid 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;}