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