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$ 00022 00023 #define INCLUDE_MENUITEM_DEF 00024 #include <tqmenudata.h> 00025 00026 #include "config.h" 00027 00028 #include "kcheckaccelerators.h" 00029 #include "kaccelmanager.h" 00030 #include <tqpopupmenu.h> 00031 #include <tqapplication.h> 00032 #include <tqdialog.h> 00033 #include <tqlayout.h> 00034 #include <tqtextview.h> 00035 #include <tqobjectlist.h> 00036 #include <tqmenubar.h> 00037 #include <tqtabbar.h> 00038 #include <tqpushbutton.h> 00039 #include <tqmetaobject.h> 00040 #include <tqcheckbox.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( TQObject* parent ) 00080 : TQObject( parent, "kapp_accel_filter" ), key(0), block( false ), drklash(0) 00081 { 00082 parent->installEventFilter( this ); 00083 KConfigGroupSaver saver( KGlobal::config(), "Development" ); 00084 TQString 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, TQT_SIGNAL( timeout()), TQT_SLOT( autoCheckSlot())); 00093 } 00094 00095 bool KCheckAccelerators::eventFilter( TQObject * , TQEvent * e) 00096 { 00097 if ( block ) 00098 return false; 00099 00100 switch ( e->type() ) { // just simplify debuggin 00101 case TQEvent::Accel: 00102 if ( key && (TQT_TQKEYEVENT(e)->key() == key) ) { 00103 block = true; 00104 checkAccelerators( false ); 00105 block = false; 00106 TQT_TQKEYEVENT(e)->accept(); 00107 return true; 00108 } 00109 break; 00110 case TQEvent::ChildInserted: 00111 case TQEvent::ChildRemoved: 00112 case TQEvent::Resize: 00113 case TQEvent::LayoutHint: 00114 case TQEvent::WindowActivate: 00115 case TQEvent::WindowDeactivate: 00116 if( autoCheck ) 00117 autoCheckTimer.start( 20, true ); // 20 ms 00118 break; 00119 case TQEvent::Timer: 00120 case TQEvent::MouseMove: 00121 case TQEvent::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(TQWidget *actWin, bool automatic) 00143 { 00144 if ( drklash ) 00145 return; 00146 00147 drklash = new TQDialog( actWin, "kapp_accel_check_dlg", false, (WFlags)TQt::WDestructiveClose); 00148 drklash->setCaption( i18n( "Dr. Klash' Accelerator Diagnosis" )); 00149 drklash->resize( 500, 460 ); 00150 TQVBoxLayout* layout = new TQVBoxLayout( drklash, 11, 6 ); 00151 layout->setAutoAdd( true ); 00152 drklash_view = new TQTextView( drklash ); 00153 TQCheckBox* disableAutoCheck = NULL; 00154 if( automatic ) { 00155 disableAutoCheck = new TQCheckBox( i18n( "&Disable automatic checking" ), drklash ); 00156 connect(disableAutoCheck, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotDisableCheck(bool))); 00157 } 00158 TQPushButton* btnClose = new TQPushButton( i18n( "&Close" ), drklash ); 00159 btnClose->setDefault( true ); 00160 connect( btnClose, TQT_SIGNAL( clicked() ), drklash, TQT_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 TQWidget* actWin = TQT_TQWIDGET(tqApp->activeWindow()); 00177 if ( !actWin ) 00178 return; 00179 00180 KAcceleratorManager::manage(actWin); 00181 TQString 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 TQString 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"