kcheckaccelerators.cpp
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 1997 Matthias Kalle Dalheimer (kalle@kde.org) 00003 Copyright (C) 1998, 1999, 2000 KDE Team 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 00019 */ 00020 00021 // $Id: kcheckaccelerators.cpp 589161 2006-09-27 17:34:20Z kling $ 00022 00023 #define INCLUDE_MENUITEM_DEF 00024 #include <qmenudata.h> 00025 00026 #include "config.h" 00027 00028 #include "kcheckaccelerators.h" 00029 #include "kaccelmanager.h" 00030 #include <qpopupmenu.h> 00031 #include <qapplication.h> 00032 #include <qdialog.h> 00033 #include <qlayout.h> 00034 #include <qtextview.h> 00035 #include <qobjectlist.h> 00036 #include <qmenubar.h> 00037 #include <qtabbar.h> 00038 #include <qpushbutton.h> 00039 #include <qmetaobject.h> 00040 #include <qcheckbox.h> 00041 00042 #include <kconfig.h> 00043 #include <kdebug.h> 00044 #include <kglobal.h> 00045 #include <kshortcut.h> 00046 #include <klocale.h> 00047 00048 /* 00049 00050 HOWTO: 00051 00052 This class allows translators (and application developers) to check for accelerator 00053 conflicts in menu and widgets. Put the following in your kdeglobals (or the config 00054 file for the application you're testing): 00055 00056 [Development] 00057 CheckAccelerators=F12 00058 AutoCheckAccelerators=false 00059 AlwaysShowCheckAccelerators=false 00060 00061 The checking can be either manual or automatic. To perform manual check, press 00062 the keyboard shortcut set to 'CheckAccelerators' (here F12). If automatic checking 00063 is enabled by setting 'AutoCheckAccelerators' to true, check will be performed every 00064 time the GUI changes. It's possible that in certain cases the check will be 00065 done also when no visible changes in the GUI happen or the check won't be done 00066 even if the GUI changed (in the latter case, use manual check ). Automatic 00067 checks can be anytime disabled by the checkbox in the dialog presenting 00068 the results of the check. If you set 'AlwaysShowCheckAccelerators' to true, 00069 the dialog will be shown even if the automatic check didn't find any conflicts, 00070 and all submenus will be shown, even those without conflicts. 00071 00072 The dialog first lists the name of the window, then all results for all menus 00073 (if the window has a menubar) and then result for all controls in the active 00074 window (if there are any checkboxes etc.). For every submenu and all controls 00075 there are shown all conflicts grouped by accelerator, and a list of all used 00076 accelerators. 00077 */ 00078 00079 KCheckAccelerators::KCheckAccelerators( QObject* parent ) 00080 : QObject( parent, "kapp_accel_filter" ), key(0), block( false ), drklash(0) 00081 { 00082 parent->installEventFilter( this ); 00083 KConfigGroupSaver saver( KGlobal::config(), "Development" ); 00084 QString sKey = KGlobal::config()->readEntry( "CheckAccelerators" ).stripWhiteSpace(); 00085 if( !sKey.isEmpty() ) { 00086 KShortcut cuts( sKey ); 00087 if( cuts.count() > 0 ) 00088 key = int(cuts.seq(0).qt()); 00089 } 00090 alwaysShow = KGlobal::config()->readBoolEntry( "AlwaysShowCheckAccelerators", false ); 00091 autoCheck = KGlobal::config()->readBoolEntry( "AutoCheckAccelerators", true ); 00092 connect( &autoCheckTimer, SIGNAL( timeout()), SLOT( autoCheckSlot())); 00093 } 00094 00095 bool KCheckAccelerators::eventFilter( QObject * , QEvent * e) 00096 { 00097 if ( block ) 00098 return false; 00099 00100 switch ( e->type() ) { // just simplify debuggin 00101 case QEvent::Accel: 00102 if ( key && (static_cast<QKeyEvent *>(e)->key() == key) ) { 00103 block = true; 00104 checkAccelerators( false ); 00105 block = false; 00106 static_cast<QKeyEvent *>(e)->accept(); 00107 return true; 00108 } 00109 break; 00110 case QEvent::ChildInserted: 00111 case QEvent::ChildRemoved: 00112 case QEvent::Resize: 00113 case QEvent::LayoutHint: 00114 case QEvent::WindowActivate: 00115 case QEvent::WindowDeactivate: 00116 if( autoCheck ) 00117 autoCheckTimer.start( 20, true ); // 20 ms 00118 break; 00119 case QEvent::Timer: 00120 case QEvent::MouseMove: 00121 case QEvent::Paint: 00122 return false; 00123 default: 00124 // kdDebug(125) << "KCheckAccelerators::eventFilter " << e->type() << " " << autoCheck << endl; 00125 break; 00126 } 00127 return false; 00128 } 00129 00130 void KCheckAccelerators::autoCheckSlot() 00131 { 00132 if( block ) 00133 { 00134 autoCheckTimer.start( 20, true ); 00135 return; 00136 } 00137 block = true; 00138 checkAccelerators( !alwaysShow ); 00139 block = false; 00140 } 00141 00142 void KCheckAccelerators::createDialog(QWidget *actWin, bool automatic) 00143 { 00144 if ( drklash ) 00145 return; 00146 00147 drklash = new QDialog( actWin, "kapp_accel_check_dlg", false, Qt::WDestructiveClose); 00148 drklash->setCaption( i18n( "Dr. Klash' Accelerator Diagnosis" )); 00149 drklash->resize( 500, 460 ); 00150 QVBoxLayout* layout = new QVBoxLayout( drklash, 11, 6 ); 00151 layout->setAutoAdd( true ); 00152 drklash_view = new QTextView( drklash ); 00153 QCheckBox* disableAutoCheck = NULL; 00154 if( automatic ) { 00155 disableAutoCheck = new QCheckBox( i18n( "&Disable automatic checking" ), drklash ); 00156 connect(disableAutoCheck, SIGNAL(toggled(bool)), SLOT(slotDisableCheck(bool))); 00157 } 00158 QPushButton* btnClose = new QPushButton( i18n( "&Close" ), drklash ); 00159 btnClose->setDefault( true ); 00160 connect( btnClose, SIGNAL( clicked() ), drklash, SLOT( close() ) ); 00161 if (disableAutoCheck) 00162 disableAutoCheck->setFocus(); 00163 else 00164 drklash_view->setFocus(); 00165 } 00166 00167 void KCheckAccelerators::slotDisableCheck(bool on) 00168 { 00169 autoCheck = !on; 00170 if (!on) 00171 autoCheckSlot(); 00172 } 00173 00174 void KCheckAccelerators::checkAccelerators( bool automatic ) 00175 { 00176 QWidget* actWin = qApp->activeWindow(); 00177 if ( !actWin ) 00178 return; 00179 00180 KAcceleratorManager::manage(actWin); 00181 QString a, c, r; 00182 KAcceleratorManager::last_manage(a, c, r); 00183 00184 if (automatic) // for now we only show dialogs on F12 checks 00185 return; 00186 00187 if (c.isEmpty() && r.isEmpty() && (automatic || a.isEmpty())) 00188 return; 00189 00190 QString s; 00191 00192 if ( ! c.isEmpty() ) { 00193 s += i18n("<h2>Accelerators changed</h2>"); 00194 s += "<table border><tr><th><b>Old Text</b></th><th><b>New Text</b></th></tr>" 00195 + c + "</table>"; 00196 } 00197 00198 if ( ! r.isEmpty() ) { 00199 s += i18n("<h2>Accelerators removed</h2>"); 00200 s += "<table border><tr><th><b>Old Text</b></th></tr>" + r + "</table>"; 00201 } 00202 00203 if ( ! a.isEmpty() ) { 00204 s += i18n("<h2>Accelerators added (just for your info)</h2>"); 00205 s += "<table border><tr><th><b>New Text</b></th></tr>" + a + "</table>"; 00206 } 00207 00208 createDialog(actWin, automatic); 00209 drklash_view->setText(s); 00210 drklash->show(); 00211 drklash->raise(); 00212 00213 // dlg will be destroyed before returning 00214 } 00215 00216 #include "kcheckaccelerators.moc"