Back to index

salome-gui  6.5.0
QtxShortcutEdit.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00018 //
00019 
00020 #include "QtxShortcutEdit.h"
00021 
00022 #include <QWidget>
00023 #include <QLayout>
00024 #include <QList>
00025 
00026 #include <QToolButton>
00027 #include <QLineEdit>
00028 #include <QTableWidgetItem>
00029 #include <QMessageBox>
00030 
00031 #include <QKeyEvent>
00032 #include <QKeySequence>
00033 
00034 #define COLUMN_SIZE  500
00035 
00036 static const char* delete_icon[] = {
00037 "16 16 3 1",
00038 "` c #810000",
00039 "  c none",
00040 "# c #ffffff",
00041 "                ",
00042 "                ",
00043 " ``#        ``# ",
00044 " ````#     ``#  ",
00045 "  ````#   ``#   ",
00046 "    ```# `#     ",
00047 "     `````#     ",
00048 "      ```#      ",
00049 "     `````#     ",
00050 "    ```# ``#    ",
00051 "   ```#   ``#   ",
00052 "  ```#     `#   ",
00053 "  ```#      `#  ",
00054 "   `#        `# ",
00055 "                ",
00056 "                "
00057 };
00058 
00063 QtxShortcutEdit::QtxShortcutEdit( QWidget* parent )
00064 : QFrame( parent )
00065 {
00066   initialize();
00067   myShortcut->installEventFilter(this);
00068 }
00069 
00073 QtxShortcutEdit::~QtxShortcutEdit()
00074 {
00075 }
00076 
00082 void QtxShortcutEdit::setShortcut( const QKeySequence& seq )
00083 {
00084   QString txt = seq.toString(); 
00085   myPrevShortcutText = txt;
00086   myShortcut->setText( txt ); 
00087 }
00088 
00094 QKeySequence QtxShortcutEdit::shortcut()
00095 {
00096   return QKeySequence::fromString( myShortcut->text() );
00097 }
00098 
00104 QString QtxShortcutEdit::parseEvent( QKeyEvent* e )
00105 {
00106   bool isShiftPressed = e->modifiers() & Qt::ShiftModifier;
00107   bool isControlPressed = e->modifiers() & Qt::ControlModifier;
00108   bool isAltPressed = e->modifiers() & Qt::AltModifier;
00109   bool isMetaPressed = e->modifiers() & Qt::MetaModifier;
00110   bool isModifiersPressed = isShiftPressed || isControlPressed || isAltPressed || isMetaPressed;
00111   int result=0;
00112   if( isControlPressed )
00113     result += Qt::CTRL;
00114   if( isAltPressed )
00115     result += Qt::ALT;
00116   if( isShiftPressed )
00117     result += Qt::SHIFT;
00118   if( isMetaPressed )
00119     result += Qt::META;
00120 
00121   int aKey = e->key();
00122   if ( ( isValidKey( aKey ) && isModifiersPressed ) || ( ( aKey >= Qt::Key_F1 ) && ( aKey <= Qt::Key_F12 ) ) )
00123     result += aKey;
00124 
00125   return QKeySequence( result ).toString();
00126 }
00127 
00134 bool QtxShortcutEdit::isValidKey( int aKey )
00135 {
00136   if ( aKey == Qt::Key_Underscore || aKey == Qt::Key_Escape || 
00137      ( aKey >= Qt::Key_Backspace && aKey <= Qt::Key_Delete ) || 
00138      ( aKey >= Qt::Key_Home && aKey <= Qt::Key_PageDown ) || 
00139      ( aKey >= Qt::Key_F1 && aKey <= Qt::Key_F12 )  ||
00140      ( aKey >= Qt::Key_Space && aKey <= Qt::Key_Asterisk ) ||
00141      ( aKey >= Qt::Key_Comma && aKey <= Qt::Key_Question ) ||
00142      ( aKey >= Qt::Key_A && aKey <= Qt::Key_AsciiTilde ) )
00143     return true;
00144   return false;
00145 }
00146 
00150 void QtxShortcutEdit::onCliked() 
00151 {
00152   myShortcut->setText( "" );
00153 }
00154 
00158 void QtxShortcutEdit::onEditingFinished() 
00159 {
00160   if ( myShortcut->text().endsWith("+") )
00161     myShortcut->setText( myPrevShortcutText );
00162 }
00163 
00170 bool QtxShortcutEdit::eventFilter(QObject* obj, QEvent* event) 
00171 { 
00172   if ( obj == myShortcut ) { 
00173     if (event->type() == QEvent::KeyPress ) {
00174       QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
00175       QString text = parseEvent( keyEvent );
00176       if ( keyEvent->key() == Qt::Key_Delete || keyEvent->key() == Qt::Key_Backspace )
00177         onCliked();
00178       if ( text != "" )
00179         myShortcut->setText( text );
00180       return true;
00181     }
00182     if ( event->type() == QEvent::KeyRelease ) {
00183       if ( myShortcut->text().endsWith("+") )
00184         myShortcut->setText( myPrevShortcutText );
00185       else myPrevShortcutText = myShortcut->text();
00186 
00187       return true;
00188     }
00189   } 
00190   return false;
00191 }
00192 
00193 /*
00194   \brief Perform internal intialization.
00195 */
00196 void QtxShortcutEdit::initialize()
00197 {
00198   myPrevShortcutText = QString();
00199 
00200   QHBoxLayout* base = new QHBoxLayout( this );
00201   base->setMargin( 0 );
00202   base->setSpacing( 5 );
00203 
00204   base->addWidget( myShortcut = new QLineEdit( this ) );
00205 
00206   QToolButton* deleteBtn = new QToolButton();
00207   deleteBtn->setIcon( QPixmap( delete_icon ) );
00208   base->addWidget( deleteBtn );
00209  
00210   myShortcut->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed );
00211   deleteBtn->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
00212 
00213   connect( deleteBtn, SIGNAL( clicked() ), this, SLOT( onCliked() ) );
00214   connect( myShortcut, SIGNAL( editingFinished() ), this, SLOT( onEditingFinished() ) );
00215 }
00216 
00221 QtxShortcutTree::QtxShortcutTree( QWidget * parent ) : QTreeWidget( parent )
00222 {
00223   setColumnCount( 2 );
00224   setSelectionMode( QAbstractItemView::SingleSelection );
00225   setColumnWidth ( 0, COLUMN_SIZE);
00226   setSortingEnabled(false);
00227   headerItem()->setHidden ( true ); 
00228 
00229   this->installEventFilter(this);
00230   connect( this, SIGNAL( currentItemChanged ( QTreeWidgetItem*, QTreeWidgetItem* ) ), this, SLOT( onCurrentItemChanged ( QTreeWidgetItem*, QTreeWidgetItem* ) ) );
00231 
00232 }
00233 
00237 QtxShortcutTree::~QtxShortcutTree(){}
00238 
00245 bool QtxShortcutTree::eventFilter(QObject* obj, QEvent* event) 
00246 { 
00247   if ( currentItem() && currentItem()->isSelected() ) {
00248     
00249     if (event->type() == QEvent::KeyPress ) {
00250       QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
00251       QString text = QtxShortcutEdit::parseEvent( keyEvent );
00252       if ( keyEvent->key() == Qt::Key_Delete || keyEvent->key() == Qt::Key_Backspace )
00253         currentItem()->setText( 1, "" );
00254       if ( text != "" ) {
00255        if ( text.endsWith( "+" ) || checkUniqueness( currentItem(), text ) )
00256           currentItem()->setText( 1, text );
00257       }
00258       return true;
00259     }
00260     if ( event->type() == QEvent::KeyRelease ) {
00261       if ( currentItem()->text( 1 ).endsWith( "+" ) )
00262        currentItem()->setText( 1, myPrevBindings[ currentItem()->parent()->text( 0 ) ][ currentItem()->text( 0 ) ] );
00263       else myPrevBindings[ currentItem()->parent()->text( 0 ) ][ currentItem()->text( 0 ) ] = currentItem()->text( 1 );
00264 
00265       return true;
00266     }    
00267   } 
00268   return false;
00269 }
00270 
00276 void QtxShortcutTree::onCurrentItemChanged( QTreeWidgetItem* cur, QTreeWidgetItem* prev )
00277 {
00278   if ( prev && prev->text( 1 ).endsWith( "+" ) )
00279       prev->setText( 1, myPrevBindings[ prev->parent()->text( 0 ) ][ prev->text( 0 ) ] );
00280 }
00281 
00287 void QtxShortcutTree::setBindings( const QString& title, const ShortcutMap& theShortcutMap )
00288 {
00289   QTreeWidgetItem* item= new QTreeWidgetItem();
00290   QFont font = item->font(0);
00291   font.setBold(true);
00292   
00293   if ( findItems( title, Qt::MatchFixedString ).isEmpty()  ) {
00294     item->setText( 0, title );
00295     item->setFont( 0, font );
00296     addTopLevelItem( item );
00297     item->setFlags( Qt::ItemIsEnabled );
00298   } else {
00299     item = findItems( title, Qt::MatchFixedString ).first();
00300     item->takeChildren();
00301   }
00302   for( ShortcutMap::const_iterator it = theShortcutMap.constBegin(); it != theShortcutMap.constEnd(); ++it )
00303       item->addChild( new QTreeWidgetItem( QStringList() << it.key() << it.value() ) );
00304   myPrevBindings.insert( title, theShortcutMap);
00305 }
00306 
00311 QStringList QtxShortcutTree::sections() const
00312 {
00313   QStringList lst;
00314   for( int i = 0; i < topLevelItemCount(); i++ )
00315     lst << topLevelItem( i )->text( 0 ); 
00316   return lst;
00317 }
00318 
00319 ShortcutMap* QtxShortcutTree::bindings( const QString& sec ) const
00320 {
00321   ShortcutMap* aMap = new ShortcutMap();
00322   QTreeWidgetItem* item = findItems( sec, Qt::MatchFixedString ).first();
00323   int nbChildren = item->childCount();
00324 
00325   for( int i = 0; i < nbChildren; i++ ) {
00326     QTreeWidgetItem* child =  item->child(i);
00327     aMap->insert( child->text( 0 ), child->text( 1 ) );
00328   }
00329 
00330   return aMap;
00331 }
00332 
00333 void QtxShortcutTree::focusOutEvent ( QFocusEvent* event )
00334 {
00335   QWidget::focusOutEvent( event );
00336   if ( currentItem() && currentItem()->isSelected() )
00337     currentItem()->setText( 1, myPrevBindings[ currentItem()->parent()->text( 0 ) ][ currentItem()->text( 0 ) ] );
00338 }
00339 
00348 void QtxShortcutTree::setGeneralSections( const QStringList& sectionsList )
00349 {
00350   myGeneralSections = sectionsList;
00351 }
00352 
00359 bool QtxShortcutTree::checkUniqueness( QTreeWidgetItem* item, const QString& shortcut )
00360 {
00361   // List of sections to check shortcut intersections
00362   QStringList sectionsList;
00363 
00364   // Current section
00365   QString currentSection = currentItem()->parent()->text( 0 );
00366 
00367   // If the current section is general 
00368   if ( myGeneralSections.contains(currentSection) ) {
00369     sectionsList = sections();
00370     int currentSectionIndex = sectionsList.indexOf(currentSection);
00371     sectionsList.move( currentSectionIndex, 0);
00372   } 
00373   else {
00374     sectionsList = myGeneralSections;
00375     sectionsList.prepend(currentSection);
00376   }
00377 
00378   // Iterate on sections
00379   QStringList::const_iterator it;
00380   for( it = sectionsList.constBegin(); it != sectionsList.constEnd(); ++it ) {
00381     QString section = *it;
00382 
00383     // Iterate on actual section
00384     QTreeWidgetItem* sectionRoot = findItems( section, Qt::MatchFixedString ).first();
00385     int nbChildren = sectionRoot->childCount();
00386 
00387     for( int i = 0; i < nbChildren; i++ ) {
00388       QTreeWidgetItem* child =  sectionRoot->child(i);
00389       
00390       if ( (child != item) && (shortcut == child->text( 1 )) ) {
00391        bool res = QMessageBox::warning( parentWidget(), tr("Warning"), 
00392                                     tr("The \"%1\" shortcut has already used by the \"%2\" action.\n")
00393                                     .arg(shortcut, section + ":" + child->text( 0 ) ) +
00394                                     tr("Do you want to reassign it from that action to the current one?"),
00395                                     QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes;
00396        if (res) 
00397          child->setText( 1, "" );
00398        return res;   
00399       }
00400     }
00401   }
00402 
00403   return true;
00404 }