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