📄 qmshortcutpage.cpp
字号:
/* qmshortcutpage.cpp * * $Id: qmshortcutpage.cpp,v 1.21.2.1 2002/09/23 19:26:51 kyllingstad Exp $ * * Apollo sound player: http://www.apolloplayer.org * Copyright(C) 2000-2002 Apollo Team. See CREDITS file. * * 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; either version 2 * of the License, or (at your option) any later version. * * 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. * * The GNU General Public License is also available online at: * * http://www.gnu.org/copyleft/gpl.html */#include "qmshortcutpage.h"#include "qmaccelmanager.h"#include <qaccel.h>#include <qapplication.h>#include <qcheckbox.h>#include <qframe.h>#include <qhgroupbox.h>#include <qlabel.h>#include <qlayout.h>#include <qlistview.h>#include <qpushbutton.h>#include <qradiobutton.h>#include <qstringlist.h>#include <qtimer.h>#include <qvgroupbox.h>#include <qhbuttongroup.h>#include <qmessagebox.h>#include <iostream>/*! \file qmshortcutpage.cpp \brief Keyboard short cuts preferences page*//*! \class QmShortcutPage qmshortcutpage.h \brief Represents the shortcut key settings page. This configuration page allows the user to bind shortcut keys to various actions. This widget grabs the keyboard. This is a dangerous operation, so the widget uses a timer in case there is a bug somewhere which leaves the keyboard in "grabbed" state. When the timer runs out (20 seconds), the keyboard is released.*//*!*/QmShortcutPage::QmShortcutPage( QmConfigDialog *parent, const char *name) : QmConfigPage(parent, name){ m_pAm = QmAccelManager::instance(); m_pTimer = new QTimer(this); connect(m_pTimer, SIGNAL(timeout()), this, SLOT(timeoutRelease())); m_pDelayTimer = new QTimer(this); connect(m_pDelayTimer, SIGNAL(timeout()), this, SLOT(delayTimeout())); QVBoxLayout *top = new QVBoxLayout(this, 4); QVGroupBox *group1 = new QVGroupBox(tr("Shortcut keys"), this); m_pKeyList = new QListView(group1); m_pKeyList->addColumn(tr("Action")); m_pKeyList->addColumn(tr("Key")); connect(m_pKeyList, SIGNAL(selectionChanged()), this, SLOT(selectionChanged())); connect(m_pKeyList, SIGNAL(doubleClicked(QListViewItem*)), this, SLOT(grabShortcut(QListViewItem*))); connect(m_pKeyList, SIGNAL(returnPressed(QListViewItem*)), this, SLOT(grabDelayedShortcut(QListViewItem*))); m_pDesc = new QLabel("\n\n", group1); m_pDesc->setFixedHeight(m_pDesc->sizeHint().height()); m_pDesc->setFrameStyle(QFrame::Panel | QFrame::Sunken); addKeys( m_pAm->groups(), 0 ); m_pKeyGroup = new QHButtonGroup(tr("Grab key"), this); m_pNoKey = new QRadioButton(tr("&No Key"), m_pKeyGroup); m_pDefKey = new QRadioButton(tr("&Default Key"), m_pKeyGroup); m_pCustKey = new QRadioButton(tr("&Custom Key"), m_pKeyGroup); m_pGrab = new QPushButton(tr("&Grab"), m_pKeyGroup); m_pGrab->setToggleButton(true); connect(m_pGrab, SIGNAL(clicked()), this, SLOT(grabShortcut())); connect(m_pKeyGroup, SIGNAL(clicked(int)), this, SLOT(keyTypeChange(int))); QAccel *ac = new QAccel(this); ac->connectItem(ac->insertItem(Key_Delete), this, SLOT(removeKey())); top->addWidget(group1, 2); top->addWidget(m_pKeyGroup); // Make sure the various widgets are sensibly enabled/disabled. selectionChanged();}/*!*/QmShortcutPage::~QmShortcutPage(){ releaseKeyboard();}/*! Adds the keys/groups for group \a g to the parent \a parent. If parent is 0 then all keys and groups are added to the root.*/voidQmShortcutPage::addKeys( const Group *g, QListViewItem *parent ){ const QList<Group> &grps = g->groups(); for ( QListIterator<Group> g_it( grps ); g_it.current(); ++g_it ) { QListViewItem *item = 0; if ( parent ) item = new QListViewItem( parent, g_it.current()->name() ); else item = new QListViewItem( m_pKeyList, g_it.current()->name() ); item->setSelectable( false ); item->setOpen( true ); addKeys( g_it.current(), item ); } const QStringList &keys = g->keys(); for ( QStringList::ConstIterator it = keys.begin(); it != keys.end(); ++it ) { const QString &command = *it; QListViewItem *item = 0; if ( parent ) item = new QListViewItem( parent, m_pAm->desc( command ), m_pAm->keyName( command ) ); else item = new QListViewItem( m_pKeyList, m_pAm->desc( command ), m_pAm->keyName( command ) ); m_ItemCommandMap.insert( item, command ); m_CommandItemMap.insert( command, item ); }}/*! Will receive the shortcut key when we grab the keyboard.*/voidQmShortcutPage::keyPressEvent( QKeyEvent *e){ int mod = 0; if ( e->state() & Qt::ShiftButton ) mod |= Qt::SHIFT; if ( e->state() & Qt::ControlButton ) mod |= Qt::CTRL; if ( e->state() & Qt::AltButton ) mod |= Qt::ALT; if( ! m_pGrab->isOn()) { QmConfigPage::keyPressEvent(e); return; } if(e->key() == Key_Escape) { releaseKeyboard(); e->accept(); m_pGrab->setOn(false); m_pTimer->stop(); } else if(e->key() != Key_Shift && e->key() != Key_Control && e->key() != Key_Alt) { int key = e->key(); key |= mod; releaseKeyboard(); e->accept(); checkKey( key ); }}voidQmShortcutPage::checkKey( int key ){ m_pGrab->setOn(false); m_pTimer->stop(); QString keyName = m_pAm->keyName(key); QString command; QListViewItem *item = m_pKeyList->currentItem(); if( item ) command = commandForItem( item ); if ( m_pAm->setp( key, command ) ) {// m_pKeyList->clearSelection();// m_pDesc->setText(tr("*** Key %1 already bound to %2. ***").arg(keyName).arg(other_desc)); if ( askAboutKeyBound( key, command, keyName ) ) { QString other_command = m_pAm->commandName( key ); QListViewItem *other_item = itemForCommand( other_command ); if ( other_item ) removeKey( other_item ); } else return; } if(item == 0) return; if (m_pAm->set( command, key, false)) { item->setText(1, keyName); changed(); m_pKeyGroup->blockSignals(true); QmAccelManager::KeyType type = m_pAm->keyType( command ); if ( type == QmAccelManager::CustomKey ) m_pKeyGroup->setButton( 2 ); else if ( type == QmAccelManager::DefaultKey ) m_pKeyGroup->setButton( 1 ); else m_pKeyGroup->setButton( 0 ); m_pKeyGroup->blockSignals(false); } else m_pDesc->setText(tr("Setting %1 for %2 failed for some reason") .arg( keyName ) .arg( command ));}/*! Asks the user whether the key \a key should bound to the command \a command. The \a keyName specifies the string representation of the key \a key. Returns true if the key should be moved to new command.*/boolQmShortcutPage::askAboutKeyBound( int key, const QString &command, const QString &keyName ){ QString other_desc = m_pAm->setTo(key); QString desc = m_pAm->desc(command); int but = QMessageBox::information( this, tr( "Key already bound" ), tr( "The key %1 is already bound to the action *%2*\n" "Do you wish to move the key to the new action *%3*?" ) .arg( keyName ) .arg( other_desc ) .arg( desc ), tr( "&Yes" ), tr( "&No" ), QString::null, 0, 1 ); return but == 0;}/* \return the command string for the QListViewItem \a item, or QString::null if no command for that item.*/QStringQmShortcutPage::commandForItem( QListViewItem *item ) const{ if ( m_ItemCommandMap.find( item ) != m_ItemCommandMap.end() ) return m_ItemCommandMap[item]; else return QString::null;}/* \return the QListViewItem for the command string \a command, or 0 if no item for that command exists.*/QListViewItem *QmShortcutPage::itemForCommand( const QString &command ) const{ if ( m_CommandItemMap.find( command ) != m_CommandItemMap.end() ) return m_CommandItemMap[command]; else return 0;}/*! Grabs the keyboard in order to get the shortcut key from the user.*/voidQmShortcutPage::grabShortcut(){ // When we get in here, the button will already be 'on' if it wasn't and // vice versa. That is, if it's on now, we need to grab the keyboard. // If it's not on, we'll release it.// save(); if(m_pGrab->isOn()) { m_pTimer->start(20 * 1000, true); grabKeyboard(); } else { m_pTimer->stop(); releaseKeyboard(); }}/*! Updates the various widgets according to the selection. */voidQmShortcutPage::selectionChanged(){ QListViewItem *item = m_pKeyList->currentItem(); if( item == 0 || m_ItemCommandMap.find( item ) == m_ItemCommandMap.end() ) { m_pDesc->setText( tr("No description.") ); m_pNoKey->setEnabled(false); m_pDefKey->setEnabled(false); m_pCustKey->setEnabled(false); m_pGrab->setEnabled(false); } else { m_pDesc->setText( item->text(0) ); QString command = commandForItem( item );; m_pNoKey->setEnabled(true); m_pDefKey->setEnabled( m_pAm->defaultKey( command ) > 0 ); m_pCustKey->setEnabled(true); m_pGrab->setEnabled(true); QmAccelManager::KeyType type = m_pAm->keyType( command ); m_pKeyGroup->blockSignals(true); if ( type == QmAccelManager::CustomKey ) { m_pKeyGroup->setButton( 2 ); } else if ( type == QmAccelManager::DefaultKey ) { m_pKeyGroup->setButton( 1 ); } else { m_pKeyGroup->setButton( 0 ); } m_pKeyGroup->blockSignals(false); }}/*! Called when the key type is changed by the user.*/voidQmShortcutPage::keyTypeChange( int num ){ switch ( num ) { case 0: removeKey(); break; case 1: defaultKey(); break; case 2: m_pGrab->setOn( true ); grabShortcut(); break; default: break; }}/*! Grabs the shortcut for the current QListViewItem, calls grabShortcut().*/voidQmShortcutPage::grabShortcut( QListViewItem * ){ m_pGrab->setOn( true ); grabShortcut();}/*! Grabs the shortcut for the current QListViewItem but has a delay before the grab is started, calls grabShortcut().*/voidQmShortcutPage::grabDelayedShortcut( QListViewItem * ){ m_pDelayTimer->start( 200, true );}/*! Removes the key for the current item.*/voidQmShortcutPage::removeKey(){ removeKey( m_pKeyList->currentItem() );}/*! Removes the key for the item \a i.*/voidQmShortcutPage::removeKey( QListViewItem *i ){ if( ! m_pGrab->isOn() && i != 0) { const QString &command = commandForItem( i ); if (m_pAm->remove(command, false)) { changed(); } i->setText(1, m_pAm->keyName(command)); }}/*! Resets the default key for the current item.*/voidQmShortcutPage::defaultKey(){ if( ! m_pGrab->isOn() && m_pKeyList->currentItem() != 0) { const QString &command = commandForItem( m_pKeyList->currentItem() ); int key = m_pAm->defaultKey( command ); if ( key > 0 && m_pAm->setp( key, command ) ) { QString keyName = m_pAm->keyName(key);// m_pDesc->setText(tr("*** Key %1 already bound to %2. ***").arg(keyName).arg(m_pAm->setTo(key))); if ( askAboutKeyBound( key, command, keyName ) ) { QString other_command = m_pAm->commandName( key ); QListViewItem *other_item = itemForCommand( other_command ); if ( other_item ) removeKey( other_item ); } else { m_pKeyGroup->blockSignals(true); QmAccelManager::KeyType type = m_pAm->keyType( command ); if ( type == QmAccelManager::CustomKey ) m_pKeyGroup->setButton( 2 ); else if ( type == QmAccelManager::DefaultKey ) m_pKeyGroup->setButton( 1 ); else m_pKeyGroup->setButton( 0 ); m_pKeyGroup->blockSignals(false); return; } } if (m_pAm->setDefault(command, false)) { changed(); } m_pKeyList->currentItem()->setText(1, m_pAm->keyName(command)); }}/*! */voidQmShortcutPage::load(){ QListViewItemIterator it(m_pKeyList); for (; it.current(); ++it) it.current()->setText(1, m_pAm->keyName( commandForItem( it.current() ) ));}voidQmShortcutPage::save(){ m_pAm->apply();}voidQmShortcutPage::discard(){ m_pAm->cancel();}/*! Called after about 20 ms after the enter key is pressed on an item, starts the grab key routine. \sa grabShortcut(), grabDelayedShortcut()*/voidQmShortcutPage::delayTimeout(){ m_pGrab->setOn( true ); grabShortcut();}/*! Called by the timer 20 seconds after the keyboard is grabbed. This is for safety reasons. */voidQmShortcutPage::timeoutRelease(){ releaseKeyboard(); m_pGrab->setOn(false); m_pDesc->setText(tr("*** Grab timed out. ***")); qApp->beep();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -