QTfrontend/ui/widget/keybinder.cpp
changeset 8346 3443e0de2c9d
child 8434 4821897a0f10
equal deleted inserted replaced
8344:3d18f7f71d65 8346:3443e0de2c9d
       
     1 /*
       
     2  * Hedgewars, a free turn based strategy game
       
     3  * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU General Public License as published by
       
     7  * the Free Software Foundation; version 2 of the License
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
       
    17  */
       
    18 
       
    19 #include "keybinder.h"
       
    20 #include "HWApplication.h"
       
    21 #include "DataManager.h"
       
    22 #include <QHBoxLayout>
       
    23 #include <QScrollArea>
       
    24 #include <QTableWidget>
       
    25 #include <QTableWidgetItem>
       
    26 #include <QStandardItemModel>
       
    27 #include <QAbstractItemModel>
       
    28 #include <QListWidget>
       
    29 #include <QListWidgetItem>
       
    30 #include <QPushButton>
       
    31 #include <QHeaderView>
       
    32 #include <QComboBox>
       
    33 #include <QLabel>
       
    34 #include <QFrame>
       
    35 #include <QDebug>
       
    36 
       
    37 KeyBinder::KeyBinder(QWidget * parent, const QString & helpText, const QString & defaultText, const QString & resetButtonText) : QWidget(parent)
       
    38 {
       
    39     this->defaultText = defaultText;
       
    40     enableSignal = false;
       
    41     
       
    42     // Two-column tab layout
       
    43     QHBoxLayout * pageKeysLayout = new QHBoxLayout(this);
       
    44     pageKeysLayout->setSpacing(0);
       
    45     pageKeysLayout->setContentsMargins(0, 0, 0, 0);
       
    46     
       
    47     // Table for category list
       
    48     QVBoxLayout * catListContainer = new QVBoxLayout();
       
    49     catListContainer->setContentsMargins(10, 10, 10, 10);
       
    50     catList = new QListWidget();
       
    51     catList->setFixedWidth(180);
       
    52     catList->setStyleSheet("QListWidget::item { font-size: 14px; } QListWidget:hover { border-color: #F6CB1C; } QListWidget::item:selected { background: #150A61; color: yellow; }");
       
    53     catList->setFocusPolicy(Qt::NoFocus);
       
    54     connect(catList, SIGNAL(currentRowChanged(int)), this, SLOT(changeBindingsPage(int)));
       
    55     catListContainer->addWidget(catList);
       
    56     pageKeysLayout->addLayout(catListContainer);
       
    57 
       
    58     // Reset all binds button
       
    59     if (!resetButtonText.isEmpty())
       
    60     {
       
    61         QPushButton * btnResetAll = new QPushButton(resetButtonText);
       
    62         catListContainer->addWidget(btnResetAll);
       
    63         btnResetAll->setFixedHeight(40);
       
    64         catListContainer->setStretch(1, 0);
       
    65         catListContainer->setSpacing(10);
       
    66         connect(btnResetAll, SIGNAL(clicked()), this, SIGNAL(resetAllBinds()));
       
    67     }
       
    68 
       
    69     // Container for pages of key bindings
       
    70     QWidget * bindingsPagesContainer = new QWidget();
       
    71     QVBoxLayout * rightLayout = new QVBoxLayout(bindingsPagesContainer);
       
    72 
       
    73     // Scroll area for key bindings
       
    74     QScrollArea * scrollArea = new QScrollArea();
       
    75     scrollArea->setContentsMargins(0, 0, 0, 0);
       
    76     scrollArea->setWidget(bindingsPagesContainer);
       
    77     scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
       
    78     scrollArea->setWidgetResizable(true);
       
    79     scrollArea->setFrameShape(QFrame::NoFrame);
       
    80     scrollArea->setStyleSheet("background: #130F2A;");
       
    81 
       
    82     // Add key binding pages to bindings tab
       
    83     pageKeysLayout->addWidget(scrollArea);
       
    84     pageKeysLayout->setStretch(1, 1);
       
    85 
       
    86     // Custom help text
       
    87     QLabel * helpLabel = new QLabel();
       
    88     helpLabel->setText(helpText);
       
    89     helpLabel->setStyleSheet("color: #130F2A; background: #F6CB1C; border: solid 4px #F6CB1C; border-radius: 10px; padding: auto 20px;");
       
    90     helpLabel->setFixedHeight(24);
       
    91     rightLayout->addWidget(helpLabel, 0, Qt::AlignCenter);
       
    92 
       
    93     // Category list and bind table row heights
       
    94     const int rowHeight = 20;
       
    95     QSize catSize, headerSize;
       
    96     catSize.setHeight(36);
       
    97     headerSize.setHeight(24);
       
    98 
       
    99     // Category list header
       
   100     QListWidgetItem * catListHeader = new QListWidgetItem(tr("Category"));
       
   101     catListHeader->setSizeHint(headerSize);
       
   102     catListHeader->setFlags(Qt::NoItemFlags);
       
   103     catListHeader->setForeground(QBrush(QColor("#130F2A")));
       
   104     catListHeader->setBackground(QBrush(QColor("#F6CB1C")));
       
   105     catListHeader->setTextAlignment(Qt::AlignCenter);
       
   106     catList->addItem(catListHeader);
       
   107 
       
   108     // Populate
       
   109     bindingsPages = new QHBoxLayout();
       
   110     bindingsPages->setContentsMargins(0, 0, 0, 0);
       
   111     rightLayout->addLayout(bindingsPages);
       
   112     QWidget * curPage = NULL;
       
   113     QVBoxLayout * curLayout = NULL;
       
   114     QTableWidget * curTable = NULL;
       
   115     bool bFirstPage = true;
       
   116     selectedBindTable = NULL;
       
   117     bindComboBoxCellMappings = new QHash<QObject *, QTableWidgetItem *>();
       
   118     bindCellComboBoxMappings = new QHash<QTableWidgetItem *, QComboBox *>();
       
   119     for (int i = 0; i < BINDS_NUMBER; i++)
       
   120     {
       
   121         if (cbinds[i].category != NULL)
       
   122         {
       
   123             // Add stretch at end of previous layout
       
   124             if (curLayout != NULL) curLayout->insertStretch(-1, 1);
       
   125             
       
   126             // Category list item
       
   127             QListWidgetItem * catItem = new QListWidgetItem(HWApplication::translate("binds (categories)", cbinds[i].category));
       
   128             catItem->setSizeHint(catSize);
       
   129             catList->addItem(catItem);
       
   130             
       
   131             // Create new page
       
   132             curPage = new QWidget();
       
   133             curLayout = new QVBoxLayout(curPage);
       
   134             curLayout->setSpacing(2);
       
   135             bindingsPages->addWidget(curPage);
       
   136             if (!bFirstPage) curPage->setVisible(false);
       
   137         }
       
   138 
       
   139         // Description
       
   140         if (cbinds[i].description != NULL)
       
   141         {
       
   142             QLabel * desc = new QLabel(HWApplication::translate("binds (descriptions)", cbinds[i].description));
       
   143             curLayout->addWidget(desc, 0);
       
   144             QFrame * divider = new QFrame();
       
   145             divider->setFrameShape(QFrame::HLine);
       
   146             divider->setFrameShadow(QFrame::Plain);
       
   147             curLayout->addWidget(divider, 0);
       
   148         }
       
   149 
       
   150         // New table
       
   151         if (cbinds[i].category != NULL || cbinds[i].description != NULL)
       
   152         {
       
   153             curTable = new QTableWidget(0, 2);
       
   154             curTable->verticalHeader()->setVisible(false);
       
   155             curTable->horizontalHeader()->setVisible(false);
       
   156             curTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
       
   157             curTable->verticalHeader()->setDefaultSectionSize(rowHeight);
       
   158             curTable->setShowGrid(false);
       
   159             curTable->setStyleSheet("QTableWidget { border: none; } ");
       
   160             curTable->setSelectionBehavior(QAbstractItemView::SelectRows);
       
   161             curTable->setSelectionMode(QAbstractItemView::SingleSelection);
       
   162             curTable->setFocusPolicy(Qt::NoFocus);
       
   163             connect(curTable, SIGNAL(itemSelectionChanged()), this, SLOT(bindSelectionChanged()));
       
   164             connect(curTable, SIGNAL(itemClicked(QTableWidgetItem *)), this, SLOT(bindCellClicked(QTableWidgetItem *)));
       
   165             curLayout->addWidget(curTable, 0);
       
   166         }
       
   167 
       
   168         // Hidden combo box
       
   169         QComboBox * comboBox = CBBind[i] = new QComboBox(curTable);
       
   170         comboBox->setModel((QAbstractItemModel*)DataManager::instance().bindsModel());
       
   171         comboBox->setVisible(false);
       
   172         comboBox->setFixedWidth(200);
       
   173         
       
   174         // Table row
       
   175         int row = curTable->rowCount();
       
   176         QTableWidgetItem * nameCell = new QTableWidgetItem(HWApplication::translate("binds", cbinds[i].name));
       
   177         nameCell->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
       
   178         curTable->insertRow(row);
       
   179         curTable->setItem(row, 0, nameCell);
       
   180         QTableWidgetItem * bindCell = new QTableWidgetItem(comboBox->currentText());
       
   181         bindCell->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
       
   182         curTable->setItem(row, 1, bindCell);
       
   183         curTable->resizeColumnsToContents();
       
   184         curTable->setFixedHeight(curTable->verticalHeader()->length() + 10);
       
   185 
       
   186         // Updates the text in the table cell
       
   187         connect(comboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(bindChanged(const QString &)));
       
   188 
       
   189         // Map combo box and that row's cells to each other
       
   190         bindComboBoxCellMappings->insert(comboBox, bindCell);
       
   191         bindCellComboBoxMappings->insert(nameCell, comboBox);
       
   192         bindCellComboBoxMappings->insert(bindCell, comboBox);
       
   193     }
       
   194 
       
   195     // Add stretch at end of last layout
       
   196     if (curLayout != NULL) curLayout->insertStretch(-1, 1);
       
   197 
       
   198     // Go to first page
       
   199     catList->setCurrentItem(catList->item(1));
       
   200 
       
   201     enableSignal = true;
       
   202 }
       
   203 
       
   204 KeyBinder::~KeyBinder()
       
   205 {
       
   206     delete bindComboBoxCellMappings;
       
   207     delete bindCellComboBoxMappings;
       
   208 }
       
   209 
       
   210 // Switches between different pages of key binds
       
   211 void KeyBinder::changeBindingsPage(int page)
       
   212 {
       
   213     page--; // Disregard first item (the list header)
       
   214     int pages = bindingsPages->count();
       
   215     for (int i = 0; i < pages; i++)
       
   216         bindingsPages->itemAt(i)->widget()->setVisible(false);
       
   217     bindingsPages->itemAt(page)->widget()->setVisible(true);
       
   218 }
       
   219 
       
   220 // When a key bind combobox value is changed, updates the table cell text
       
   221 void KeyBinder::bindChanged(const QString & text)
       
   222 {
       
   223     bindComboBoxCellMappings->value(sender())->setText(text);
       
   224 
       
   225     if (enableSignal)
       
   226     {
       
   227         for (int i = 0; i < BINDS_NUMBER; i++)
       
   228         {
       
   229             if (CBBind[i] == sender())
       
   230             {
       
   231                 emit bindUpdate(i);
       
   232                 break;
       
   233             }
       
   234         }
       
   235     }
       
   236 }
       
   237 
       
   238 // When a row in a key bind table is clicked, this shows the popup
       
   239 void KeyBinder::bindCellClicked(QTableWidgetItem * item)
       
   240 {
       
   241     QComboBox * box = bindCellComboBoxMappings->value(item);
       
   242     QTableWidget * table = item->tableWidget();
       
   243     QFrame * frame = box->findChild<QFrame*>();
       
   244     
       
   245     box->showPopup();
       
   246     frame->move(
       
   247         frame->x() + table->horizontalHeader()->sectionSize(0),
       
   248         frame->y() + (table->verticalHeader()->defaultSectionSize() * item->row())
       
   249     );
       
   250 }
       
   251 
       
   252 // When a new row in a bind table is *selected*, this clears selection in any other table
       
   253 void KeyBinder::bindSelectionChanged()
       
   254 {
       
   255     QTableWidget * theSender = (QTableWidget*)sender();
       
   256     if (theSender != selectedBindTable)
       
   257     {
       
   258         if (selectedBindTable != NULL)
       
   259             selectedBindTable->clearSelection();
       
   260         selectedBindTable = theSender;
       
   261     }
       
   262 }
       
   263 
       
   264 // Set a combobox's index
       
   265 void KeyBinder::setBindIndex(int keyIndex, int bindIndex)
       
   266 {
       
   267     enableSignal = false;
       
   268     CBBind[keyIndex]->setCurrentIndex(bindIndex);
       
   269     enableSignal = true;
       
   270 }
       
   271 
       
   272 // Return a combobox's selected index
       
   273 int KeyBinder::bindIndex(int keyIndex)
       
   274 {
       
   275     return CBBind[keyIndex]->currentIndex();
       
   276 }
       
   277 
       
   278 // Clears selection and goes to first category
       
   279 void KeyBinder::resetInterface()
       
   280 {
       
   281     enableSignal = false;
       
   282     
       
   283     catList->setCurrentItem(catList->item(1));
       
   284     changeBindingsPage(1);
       
   285     if (selectedBindTable != NULL)
       
   286     {
       
   287         selectedBindTable->clearSelection();
       
   288         selectedBindTable = NULL;
       
   289     }
       
   290     
       
   291     // Default bind text
       
   292     DataManager::instance().bindsModel()->item(0)->setData(defaultText, Qt::DisplayRole);
       
   293     for (int i = 0; i < BINDS_NUMBER; i++)
       
   294     {
       
   295         CBBind[i]->setModel(DataManager::instance().bindsModel());
       
   296         CBBind[i]->setCurrentIndex(0);
       
   297         bindComboBoxCellMappings->value(CBBind[i])->setText(defaultText);
       
   298     }
       
   299 
       
   300     enableSignal = true;
       
   301 }