kdecore Library API Documentation

kaccelmanager.cpp

00001 /* This file is part of the KDE project 00002 Copyright (C) 2002 Matthias Hölzer-Klüpfel <mhk@kde.org> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00017 Boston, MA 02111-1307, USA. 00018 */ 00019 00020 00021 #include <qapplication.h> 00022 #include <qcheckbox.h> 00023 #include <qcombobox.h> 00024 #include <qgroupbox.h> 00025 #include <qlabel.h> 00026 #include <qlineedit.h> 00027 #include <qmenubar.h> 00028 #include <qmemarray.h> 00029 #include <qmetaobject.h> 00030 #include <qmainwindow.h> 00031 #include <qobjectlist.h> 00032 #include <qpopupmenu.h> 00033 #include <qptrlist.h> 00034 #include <qpushbutton.h> 00035 #include <qradiobutton.h> 00036 #include <qspinbox.h> 00037 #include <qtabbar.h> 00038 #include <qtextview.h> 00039 #include <qwidget.h> 00040 #include <qwidgetstack.h> 00041 00042 #include <kstdaction.h> 00043 #include <kstaticdeleter.h> 00044 #include <kdebug.h> 00045 00046 00047 #include "kaccelmanager_private.h" 00048 #include "../kdeui/kstdaction_p.h" 00049 00050 #include "kaccelmanager.h" 00051 00052 // Default control weight 00053 const int KAccelManagerAlgorithm::DEFAULT_WEIGHT = 50; 00054 // Additional weight for first character in string 00055 const int KAccelManagerAlgorithm::FIRST_CHARACTER_EXTRA_WEIGHT = 50; 00056 // Additional weight for the beginning of a word 00057 const int KAccelManagerAlgorithm::WORD_BEGINNING_EXTRA_WEIGHT = 50; 00058 // Additional weight for the dialog buttons (large, we basically never want these reassigned) 00059 const int KAccelManagerAlgorithm::DIALOG_BUTTON_EXTRA_WEIGHT = 300; 00060 // Additional weight for a 'wanted' accelerator 00061 const int KAccelManagerAlgorithm::WANTED_ACCEL_EXTRA_WEIGHT = 150; 00062 // Default weight for an 'action' widget (ie, pushbuttons) 00063 const int KAccelManagerAlgorithm::ACTION_ELEMENT_WEIGHT = 50; 00064 // Default weight for group boxes (low priority) 00065 const int KAccelManagerAlgorithm::GROUP_BOX_WEIGHT = 0; 00066 // Default weight for menu titles 00067 const int KAccelManagerAlgorithm::MENU_TITLE_WEIGHT = 250; 00068 // Additional weight for KDE standard accelerators 00069 const int KAccelManagerAlgorithm::STANDARD_ACCEL = 300; 00070 00071 /********************************************************************* 00072 00073 class Item - helper class containing widget information 00074 00075 This class stores information about the widgets the need accelerators, 00076 as well as about their relationship. 00077 00078 *********************************************************************/ 00079 00080 00081 00082 /********************************************************************* 00083 00084 class KAcceleratorManagerPrivate - internal helper class 00085 00086 This class does all the work to find accelerators for a hierarchy of 00087 widgets. 00088 00089 *********************************************************************/ 00090 00091 00092 class KAcceleratorManagerPrivate 00093 { 00094 public: 00095 00096 static void manage(QWidget *widget); 00097 static bool programmers_mode; 00098 static bool standardName(const QString &str); 00099 00100 static bool checkChange(const KAccelString &as) { 00101 QString t2 = as.accelerated(); 00102 QString t1 = as.originalText(); 00103 if (t1 != t2) 00104 { 00105 if (as.accel() == -1) { 00106 removed_string += "<tr><td>" + t1 + "</td></tr>"; 00107 } else if (as.originalAccel() == -1) { 00108 added_string += "<tr><td>" + t2 + "</td></tr>"; 00109 } else { 00110 changed_string += "<tr><td>" + t1 + "</td>"; 00111 changed_string += "<td>" + t2 + "</td></tr>"; 00112 } 00113 return true; 00114 } 00115 return false; 00116 } 00117 static QString changed_string; 00118 static QString added_string; 00119 static QString removed_string; 00120 00121 private: 00122 class Item; 00123 public: 00124 typedef QPtrList<Item> ItemList; 00125 00126 private: 00127 static void traverseChildren(QWidget *widget, Item *item); 00128 00129 static void manageWidget(QWidget *widget, Item *item); 00130 static void manageMenuBar(QMenuBar *mbar, Item *item); 00131 static void manageTabBar(QTabBar *bar, Item *item); 00132 00133 static void calculateAccelerators(Item *item, QString &used); 00134 00135 class Item 00136 { 00137 public: 00138 00139 Item() : m_widget(0), m_children(0), m_index(-1) {}; 00140 ~Item(); 00141 00142 void addChild(Item *item); 00143 00144 QWidget *m_widget; 00145 KAccelString m_content; 00146 ItemList *m_children; 00147 int m_index; 00148 00149 }; 00150 }; 00151 00152 00153 bool KAcceleratorManagerPrivate::programmers_mode = false; 00154 QString KAcceleratorManagerPrivate::changed_string; 00155 QString KAcceleratorManagerPrivate::added_string; 00156 QString KAcceleratorManagerPrivate::removed_string; 00157 static QStringList *kaccmp_sns = 0; 00158 static KStaticDeleter<QStringList> kaccmp_sns_d; 00159 00160 bool KAcceleratorManagerPrivate::standardName(const QString &str) 00161 { 00162 if (!kaccmp_sns) 00163 kaccmp_sns_d.setObject(kaccmp_sns, new QStringList(KStdAction::internal_stdNames())); 00164 return kaccmp_sns->contains(str); 00165 } 00166 00167 KAcceleratorManagerPrivate::Item::~Item() 00168 { 00169 delete m_children; 00170 } 00171 00172 00173 void KAcceleratorManagerPrivate::Item::addChild(Item *item) 00174 { 00175 if (!m_children) { 00176 m_children = new ItemList; 00177 m_children->setAutoDelete(true); 00178 } 00179 00180 m_children->append(item); 00181 } 00182 00183 void KAcceleratorManagerPrivate::manage(QWidget *widget) 00184 { 00185 if (dynamic_cast<QPopupMenu*>(widget)) 00186 { 00187 // create a popup accel manager that can deal with dynamic menus 00188 KPopupAccelManager::manage(static_cast<QPopupMenu*>(widget)); 00189 return; 00190 } 00191 00192 Item *root = new Item; 00193 00194 manageWidget(widget, root); 00195 00196 QString used; 00197 calculateAccelerators(root, used); 00198 delete root; 00199 } 00200 00201 00202 void KAcceleratorManagerPrivate::calculateAccelerators(Item *item, QString &used) 00203 { 00204 if (!item->m_children) 00205 return; 00206 00207 // collect the contents 00208 KAccelStringList contents; 00209 for (Item *it = item->m_children->first(); it != 0; 00210 it = item->m_children->next()) 00211 { 00212 contents << it->m_content; 00213 } 00214 00215 // find the right accelerators 00216 KAccelManagerAlgorithm::findAccelerators(contents, used); 00217 00218 // write them back into the widgets 00219 int cnt = -1; 00220 for (Item *it = item->m_children->first(); it != 0; 00221 it = item->m_children->next()) 00222 { 00223 cnt++; 00224 00225 QTabBar *tabBar = dynamic_cast<QTabBar*>(it->m_widget); 00226 if (tabBar) 00227 { 00228 if (checkChange(contents[cnt])) 00229 tabBar->tabAt(it->m_index)->setText(contents[cnt].accelerated()); 00230 continue; 00231 } 00232 QMenuBar *menuBar = dynamic_cast<QMenuBar*>(it->m_widget); 00233 if (menuBar) 00234 { 00235 if (it->m_index >= 0) 00236 { 00237 QMenuItem *mitem = menuBar->findItem(menuBar->idAt(it->m_index)); 00238 if (mitem) 00239 { 00240 checkChange(contents[cnt]); 00241 mitem->setText(contents[cnt].accelerated()); 00242 } 00243 continue; 00244 } 00245 } 00246 int tprop = it->m_widget->metaObject()->findProperty("text", true); 00247 if (tprop != -1) { 00248 if (checkChange(contents[cnt])) 00249 it->m_widget->setProperty("text", contents[cnt].accelerated()); 00250 } else { 00251 tprop = it->m_widget->metaObject()->findProperty("title", true); 00252 if (tprop != -1 && checkChange(contents[cnt])) 00253 it->m_widget->setProperty("title", contents[cnt].accelerated()); 00254 } 00255 } 00256 00257 // calculate the accelerators for the children 00258 for (Item *it = item->m_children->first(); it != 0; 00259 it = item->m_children->next()) 00260 { 00261 if (it->m_widget && it->m_widget->isVisibleTo( item->m_widget )) 00262 calculateAccelerators(it, used); 00263 } 00264 } 00265 00266 00267 void KAcceleratorManagerPrivate::traverseChildren(QWidget *widget, Item *item) 00268 { 00269 QObjectList *childList = widget->queryList("QWidget", 0, false, false); 00270 for ( QObject *it = childList->first(); it; it = childList->next() ) 00271 { 00272 QWidget *w = static_cast<QWidget*>(it); 00273 00274 if ( !w->isVisibleTo( widget ) ) 00275 continue; 00276 00277 manageWidget(w, item); 00278 } 00279 delete childList; 00280 } 00281 00282 void KAcceleratorManagerPrivate::manageWidget(QWidget *w, Item *item) 00283 { 00284 // first treat the special cases 00285 00286 QTabBar *tabBar = dynamic_cast<QTabBar*>(w); 00287 if (tabBar) 00288 { 00289 manageTabBar(tabBar, item); 00290 return; 00291 } 00292 00293 QPopupMenu *popupMenu = dynamic_cast<QPopupMenu*>(w); 00294 if (popupMenu) 00295 { 00296 // create a popup accel manager that can deal with dynamic menus 00297 KPopupAccelManager::manage(popupMenu); 00298 return; 00299 } 00300 00301 QMenuBar *menuBar = dynamic_cast<QMenuBar*>(w); 00302 if (menuBar) 00303 { 00304 manageMenuBar(menuBar, item); 00305 return; 00306 } 00307 00308 if (dynamic_cast<QComboBox*>(w) || dynamic_cast<QLineEdit*>(w) || 00309 dynamic_cast<QTextEdit*>(w) || dynamic_cast<QTextView*>(w) || 00310 dynamic_cast<QSpinBox*>(w)) 00311 return; 00312 00313 // now treat 'ordinary' widgets 00314 QLabel *label = dynamic_cast<QLabel*>(w); 00315 if (w->isFocusEnabled() || (label && label->buddy()) || dynamic_cast<QGroupBox*>(w)) 00316 { 00317 QString content; 00318 QVariant variant; 00319 int tprop = w->metaObject()->findProperty("text", true); 00320 if (tprop != -1) { 00321 const QMetaProperty* p = w->metaObject()->property( tprop, true ); 00322 if ( p && p->isValid() ) 00323 w->qt_property( tprop, 1, &variant ); 00324 else 00325 tprop = -1; 00326 } 00327 00328 if (tprop == -1) { 00329 tprop = w->metaObject()->findProperty("title", true); 00330 if (tprop != -1) { 00331 const QMetaProperty* p = w->metaObject()->property( tprop, true ); 00332 if ( p && p->isValid() ) 00333 w->qt_property( tprop, 1, &variant ); 00334 } 00335 } 00336 00337 if (variant.isValid()) 00338 content = variant.toString(); 00339 00340 if (!content.isEmpty()) 00341 { 00342 Item *i = new Item; 00343 i->m_widget = w; 00344 00345 // put some more weight on the usual action elements 00346 int weight = KAccelManagerAlgorithm::DEFAULT_WEIGHT; 00347 if (dynamic_cast<QPushButton*>(w) || dynamic_cast<QCheckBox*>(w) || dynamic_cast<QRadioButton*>(w) || dynamic_cast<QLabel*>(w)) 00348 weight = KAccelManagerAlgorithm::ACTION_ELEMENT_WEIGHT; 00349 00350 // don't put weight on group boxes, as usually the contents are more important 00351 if (dynamic_cast<QGroupBox*>(w)) 00352 weight = KAccelManagerAlgorithm::GROUP_BOX_WEIGHT; 00353 00354 // put a lot of extra weight on the KDialogBaseButton's 00355 if (w->inherits("KDialogBaseButton")) 00356 weight += KAccelManagerAlgorithm::DIALOG_BUTTON_EXTRA_WEIGHT; 00357 00358 i->m_content = KAccelString(content, weight); 00359 item->addChild(i); 00360 } 00361 } 00362 traverseChildren(w, item); 00363 } 00364 00365 void KAcceleratorManagerPrivate::manageTabBar(QTabBar *bar, Item *item) 00366 { 00367 for (int i=0; i<bar->count(); i++) 00368 { 00369 QString content = bar->tabAt(i)->text(); 00370 if (content.isEmpty()) 00371 continue; 00372 00373 Item *it = new Item; 00374 item->addChild(it); 00375 it->m_widget = bar; 00376 it->m_index = i; 00377 it->m_content = KAccelString(content); 00378 } 00379 } 00380 00381 00382 void KAcceleratorManagerPrivate::manageMenuBar(QMenuBar *mbar, Item *item) 00383 { 00384 QMenuItem *mitem; 00385 QString s; 00386 00387 for (uint i=0; i<mbar->count(); ++i) 00388 { 00389 mitem = mbar->findItem(mbar->idAt(i)); 00390 if (!mitem) 00391 continue; 00392 00393 // nothing to do for separators 00394 if (mitem->isSeparator()) 00395 continue; 00396 00397 s = mitem->text(); 00398 if (!s.isEmpty()) 00399 { 00400 Item *it = new Item; 00401 item->addChild(it); 00402 it->m_content = 00403 KAccelString(s, 00404 // menu titles are important, so raise the weight 00405 KAccelManagerAlgorithm::MENU_TITLE_WEIGHT); 00406 00407 it->m_widget = mbar; 00408 it->m_index = i; 00409 } 00410 00411 // have a look at the popup as well, if present 00412 if (mitem->popup()) 00413 KPopupAccelManager::manage(mitem->popup()); 00414 } 00415 } 00416 00417 00418 /********************************************************************* 00419 00420 class KAcceleratorManager - main entry point 00421 00422 This class is just here to provide a clean public API... 00423 00424 *********************************************************************/ 00425 00426 void KAcceleratorManager::manage(QWidget *widget) 00427 { 00428 KAcceleratorManager::manage(widget, false); 00429 } 00430 00431 void KAcceleratorManager::manage(QWidget *widget, bool programmers_mode) 00432 { 00433 KAcceleratorManagerPrivate::changed_string = QString::null; 00434 KAcceleratorManagerPrivate::added_string = QString::null; 00435 KAcceleratorManagerPrivate::removed_string = QString::null; 00436 KAcceleratorManagerPrivate::programmers_mode = programmers_mode; 00437 KAcceleratorManagerPrivate::manage(widget); 00438 } 00439 00440 void KAcceleratorManager::last_manage(QString &added, QString &changed, QString &removed) 00441 { 00442 added = KAcceleratorManagerPrivate::added_string; 00443 changed = KAcceleratorManagerPrivate::changed_string; 00444 removed = KAcceleratorManagerPrivate::removed_string; 00445 } 00446 00447 00448 /********************************************************************* 00449 00450 class KAccelString - a string with weighted characters 00451 00452 *********************************************************************/ 00453 00454 KAccelString::KAccelString(const QString &input, int initialWeight) 00455 : m_pureText(input), m_origText(input), m_weight() 00456 { 00457 if (m_pureText.contains('\t')) 00458 m_pureText = m_pureText.left(m_pureText.find('\t')); 00459 m_orig_accel = m_pureText.find("(!)&"); 00460 m_pureText.replace(m_orig_accel, 4, ""); 00461 m_orig_accel = m_pureText.find("(&&)"); 00462 if (m_orig_accel != -1) 00463 m_pureText.replace(m_orig_accel, 4, "&"); 00464 m_orig_accel = m_accel = stripAccelerator(m_pureText); 00465 00466 kdDebug(125) << input << " " << m_orig_accel << " " << m_accel << " " << m_pureText << endl; 00467 if (initialWeight == -1) 00468 initialWeight = KAccelManagerAlgorithm::DEFAULT_WEIGHT; 00469 00470 calculateWeights(initialWeight); 00471 00472 // dump(); 00473 } 00474 00475 00476 QString KAccelString::accelerated() const 00477 { 00478 QString result = m_origText; 00479 if (result.isEmpty()) 00480 return result; 00481 00482 if (KAcceleratorManagerPrivate::programmers_mode) 00483 { 00484 int oa = m_orig_accel; 00485 00486 if (m_accel >= 0) { 00487 if (m_accel != m_orig_accel) { 00488 result.insert(m_accel, "(!)&"); 00489 if (m_accel < m_orig_accel) 00490 oa += 4; 00491 } else { 00492 result.insert(m_accel, "&"); 00493 if (m_accel < m_orig_accel) 00494 oa++; 00495 } 00496 } 00497 00498 if (m_accel != m_orig_accel && m_orig_accel >= 0) 00499 result.insert(oa, "(&&)"); 00500 } else { 00501 if (m_accel >= 0 && m_orig_accel != m_accel) { 00502 result.remove(m_orig_accel, 1); 00503 result.insert(m_accel, "&"); 00504 } 00505 } 00506 return result; 00507 } 00508 00509 00510 QChar KAccelString::accelerator() const 00511 { 00512 if ((m_accel < 0) || (m_accel > (int)m_pureText.length())) 00513 return QChar(); 00514 00515 return m_pureText[m_accel].lower(); 00516 } 00517 00518 00519 void KAccelString::calculateWeights(int initialWeight) 00520 { 00521 m_weight.resize(m_pureText.length()); 00522 00523 uint pos = 0; 00524 bool start_character = true; 00525 00526 while (pos<m_pureText.length()) 00527 { 00528 QChar c = m_pureText[pos]; 00529 00530 int weight = initialWeight+1; 00531 00532 // add special weight to first character 00533 if (pos == 0) 00534 weight += KAccelManagerAlgorithm::FIRST_CHARACTER_EXTRA_WEIGHT; 00535 00536 // add weight to word beginnings 00537 if (start_character) 00538 { 00539 weight += KAccelManagerAlgorithm::WORD_BEGINNING_EXTRA_WEIGHT; 00540 start_character = false; 00541 } 00542 00543 // add decreasing weight to left characters 00544 if (pos < 50) 00545 weight += (50-pos); 00546 00547 // try to preserve the wanted accelarators 00548 if ((int)pos == accel()) { 00549 weight += KAccelManagerAlgorithm::WANTED_ACCEL_EXTRA_WEIGHT; 00550 // kdDebug() << "wanted " << m_pureText << " " << KAcceleratorManagerPrivate::standardName(m_origText) << endl; 00551 if (KAcceleratorManagerPrivate::standardName(m_origText)) { 00552 weight += KAccelManagerAlgorithm::STANDARD_ACCEL; 00553 } 00554 } 00555 00556 // skip non typeable characters 00557 if (!c.isLetterOrNumber()) 00558 { 00559 weight = 0; 00560 start_character = true; 00561 } 00562 00563 m_weight[pos] = weight; 00564 00565 ++pos; 00566 } 00567 } 00568 00569 00570 int KAccelString::stripAccelerator(QString &text) 00571 { 00572 // Note: this code is derived from QAccel::shortcutKey 00573 int p = 0; 00574 00575 while (p >= 0) 00576 { 00577 p = text.find('&', p)+1; 00578 00579 if (p <= 0 || p >= (int)text.length()) 00580 return -1; 00581 00582 if (text[p] != '&') 00583 { 00584 QChar c = text[p]; 00585 if (c.isPrint()) 00586 { 00587 text.remove(p-1,1); 00588 return p-1; 00589 } 00590 } 00591 00592 p++; 00593 } 00594 00595 return -1; 00596 } 00597 00598 00599 int KAccelString::maxWeight(int &index, const QString &used) 00600 { 00601 int max = 0; 00602 index = -1; 00603 00604 for (uint pos=0; pos<m_pureText.length(); ++pos) 00605 if (used.find(m_pureText[pos], 0, FALSE) == -1 && m_pureText[pos].latin1() != 0) 00606 if (m_weight[pos] > max) 00607 { 00608 max = m_weight[pos]; 00609 index = pos; 00610 } 00611 00612 return max; 00613 } 00614 00615 00616 void KAccelString::dump() 00617 { 00618 QString s; 00619 for (uint i=0; i<m_weight.count(); ++i) 00620 s += QString("%1(%2) ").arg(pure()[i]).arg(m_weight[i]); 00621 kdDebug() << "s " << s << endl; 00622 } 00623 00624 00625 /********************************************************************* 00626 00627 findAccelerators - the algorithm determining the new accelerators 00628 00629 The algorithm is very crude: 00630 00631 * each character in each widget text is assigned a weight 00632 * the character with the highest weight over all is picked 00633 * that widget is removed from the list 00634 * the weights are recalculated 00635 * the process is repeated until no more accelerators can be found 00636 00637 The algorithm has some advantages: 00638 00639 * it favors 'nice' accelerators (first characters in a word, etc.) 00640 * it is quite fast, O(N²) 00641 * it is easy to understand :-) 00642 00643 The disadvantages: 00644 00645 * it does not try to find as many accelerators as possible 00646 00647 TODO: 00648 00649 * The result is always correct, but not neccesarily optimal. Perhaps 00650 it would be a good idea to add another algorithm with higher complexity 00651 that gets used when this one fails, i.e. leaves widgets without 00652 accelerators. 00653 00654 * The weights probably need some tweaking so they make more sense. 00655 00656 *********************************************************************/ 00657 00658 void KAccelManagerAlgorithm::findAccelerators(KAccelStringList &result, QString &used) 00659 { 00660 KAccelStringList accel_strings = result; 00661 00662 // initally remove all accelerators 00663 for (KAccelStringList::Iterator it = result.begin(); it != result.end(); ++it) 00664 (*it).setAccel(-1); 00665 00666 // pick the highest bids 00667 for (uint cnt=0; cnt<accel_strings.count(); ++cnt) 00668 { 00669 int max = 0, index = -1, accel = -1; 00670 00671 // find maximum weight 00672 for (uint i=0; i<accel_strings.count(); ++i) 00673 { 00674 int a; 00675 int m = accel_strings[i].maxWeight(a, used); 00676 if (m>max) 00677 { 00678 max = m; 00679 index = i; 00680 accel = a; 00681 } 00682 } 00683 00684 // stop if no more accelerators can be found 00685 if (index < 0) 00686 return; 00687 00688 // insert the accelerator 00689 if (accel >= 0) 00690 { 00691 result[index].setAccel(accel); 00692 used.append(result[index].accelerator()); 00693 } 00694 00695 // make sure we don't visit this one again 00696 accel_strings[index] = KAccelString(); 00697 } 00698 } 00699 00700 00701 /********************************************************************* 00702 00703 class KPopupAccelManager - managing QPopupMenu widgets dynamically 00704 00705 *********************************************************************/ 00706 00707 KPopupAccelManager::KPopupAccelManager(QPopupMenu *popup) 00708 : QObject(popup), m_popup(popup), m_count(-1) 00709 { 00710 aboutToShow(); // do one check and then connect to show 00711 connect(popup, SIGNAL(aboutToShow()), SLOT(aboutToShow())); 00712 } 00713 00714 00715 void KPopupAccelManager::aboutToShow() 00716 { 00717 // Note: we try to be smart and avoid recalculating the accelerators 00718 // whenever possible. Unfortunately, there is no way to know if an 00719 // item has been added or removed, so we can not do much more than 00720 // to compare the items each time the menu is shown :-( 00721 00722 if (m_count != (int)m_popup->count()) 00723 { 00724 findMenuEntries(m_entries); 00725 calculateAccelerators(); 00726 m_count = m_popup->count(); 00727 } 00728 else 00729 { 00730 KAccelStringList entries; 00731 findMenuEntries(entries); 00732 if (entries != m_entries) 00733 { 00734 m_entries = entries; 00735 calculateAccelerators(); 00736 } 00737 } 00738 } 00739 00740 00741 void KPopupAccelManager::calculateAccelerators() 00742 { 00743 // find the new accelerators 00744 QString used; 00745 KAccelManagerAlgorithm::findAccelerators(m_entries, used); 00746 00747 // change the menu entries 00748 setMenuEntries(m_entries); 00749 } 00750 00751 00752 void KPopupAccelManager::findMenuEntries(KAccelStringList &list) 00753 { 00754 QMenuItem *mitem; 00755 QString s; 00756 00757 list.clear(); 00758 00759 // read out the menu entries 00760 for (uint i=0; i<m_popup->count(); i++) 00761 { 00762 mitem = m_popup->findItem(m_popup->idAt(i)); 00763 if (mitem->isSeparator()) 00764 continue; 00765 00766 s = mitem->text(); 00767 00768 // in full menus, look at entries with global accelerators last 00769 int weight = 50; 00770 if (s.contains('\t')) 00771 weight = 0; 00772 00773 list.append(KAccelString(s, weight)); 00774 00775 // have a look at the popup as well, if present 00776 if (mitem->popup()) 00777 KPopupAccelManager::manage(mitem->popup()); 00778 } 00779 } 00780 00781 00782 void KPopupAccelManager::setMenuEntries(const KAccelStringList &list) 00783 { 00784 QMenuItem *mitem; 00785 00786 uint cnt = 0; 00787 for (uint i=0; i<m_popup->count(); i++) 00788 { 00789 mitem = m_popup->findItem(m_popup->idAt(i)); 00790 if (mitem->isSeparator()) 00791 continue; 00792 00793 if (KAcceleratorManagerPrivate::checkChange(list[cnt])) 00794 mitem->setText(list[cnt].accelerated()); 00795 cnt++; 00796 } 00797 } 00798 00799 00800 void KPopupAccelManager::manage(QPopupMenu *popup) 00801 { 00802 // don't add more than one manager to a popup 00803 if (popup->child(0, "KPopupAccelManager", false) == 0 ) 00804 new KPopupAccelManager(popup); 00805 } 00806 00807 00808 #include "kaccelmanager_private.moc"
KDE Logo
This file is part of the documentation for kdecore Library Version 3.3.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Oct 17 11:26:05 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003