KDEUI
ktoolbar.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 Copyright 00003 (C) 2000 Reginald Stadlbauer (reggie@kde.org) 00004 (C) 1997, 1998 Stephan Kulow (coolo@kde.org) 00005 (C) 1997, 1998 Mark Donohoe (donohoe@kde.org) 00006 (C) 1997, 1998 Sven Radej (radej@kde.org) 00007 (C) 1997, 1998 Matthias Ettrich (ettrich@kde.org) 00008 (C) 1999 Chris Schlaeger (cs@kde.org) 00009 (C) 1999 Kurt Granroth (granroth@kde.org) 00010 (C) 2005-2006 Hamish Rodda (rodda@kde.org) 00011 00012 This library is free software; you can redistribute it and/or 00013 modify it under the terms of the GNU Library General Public 00014 License version 2 as published by the Free Software Foundation. 00015 00016 This library is distributed in the hope that it will be useful, 00017 but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 Library General Public License for more details. 00020 00021 You should have received a copy of the GNU Library General Public License 00022 along with this library; see the file COPYING.LIB. If not, write to 00023 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00024 Boston, MA 02110-1301, USA. 00025 */ 00026 00027 #include "ktoolbar.h" 00028 00029 #include <config.h> 00030 00031 #include <QtCore/QPointer> 00032 #include <QtGui/QDesktopWidget> 00033 #include <QtGui/QFrame> 00034 #include <QtGui/QLayout> 00035 #include <QtGui/QMouseEvent> 00036 #include <QtGui/QToolButton> 00037 #include <QtXml/QDomElement> 00038 00039 #include <kaction.h> 00040 #include <kactioncollection.h> 00041 #include <kapplication.h> 00042 #include <kauthorized.h> 00043 #include <kconfig.h> 00044 #include <kdebug.h> 00045 #include <kedittoolbar.h> 00046 #include <kglobalsettings.h> 00047 #include <kguiitem.h> 00048 #include <kicon.h> 00049 #include <kiconloader.h> 00050 #include <klocale.h> 00051 #include <kxmlguiwindow.h> 00052 #include <kmenu.h> 00053 #include <kstandardaction.h> 00054 #include <ktoggleaction.h> 00055 #include <kxmlguifactory.h> 00056 00057 #include <kconfiggroup.h> 00058 00059 /* 00060 Toolbar settings (e.g. icon size or toolButtonStyle) 00061 ===================================================== 00062 00063 We have the following stack of settings (in order of priority) : 00064 - user-specified settings (loaded/saved in KConfig) 00065 - developer-specified settings in the XMLGUI file (if using xmlgui) (cannot change at runtime) 00066 - KDE-global default (user-configurable; can change at runtime) 00067 and when switching between kparts, they are saved as xml in memory, 00068 which, in the unlikely case of no-kmainwindow-autosaving, could be 00069 different from the user-specified settings saved in KConfig and would have 00070 priority over it. 00071 00072 So, in summary, without XML: 00073 Global config / User settings (loaded/saved in kconfig) 00074 and with XML: 00075 Global config / App-XML attributes / User settings (loaded/saved in kconfig) 00076 00077 And all those settings (except the KDE-global defaults) have to be stored in memory 00078 since we cannot retrieve them at random points in time, not knowing the xml document 00079 nor config file that holds these settings. Hence the iconSizeSettings and toolButtonStyleSettings arrays. 00080 00081 For instance, if you change the KDE-global default, whether this makes a change 00082 on a given toolbar depends on whether there are settings at Level_AppXML or Level_UserSettings. 00083 Only if there are no settings at those levels, should the change of KDEDefault make a difference. 00084 */ 00085 enum SettingLevel { Level_KDEDefault, Level_AppXML, Level_UserSettings, 00086 NSettingLevels }; 00087 enum { Unset = -1 }; 00088 00089 class KToolBar::Private 00090 { 00091 public: 00092 Private(KToolBar *qq) 00093 : q(qq), 00094 isMainToolBar(false), 00095 #ifndef KDE_NO_DEPRECATED 00096 enableContext(true), 00097 #endif 00098 unlockedMovable(true), 00099 contextOrient(0), 00100 contextMode(0), 00101 contextSize(0), 00102 contextButtonTitle(0), 00103 contextShowText(0), 00104 contextButtonAction(0), 00105 contextTop(0), 00106 contextLeft(0), 00107 contextRight(0), 00108 contextBottom(0), 00109 contextIcons(0), 00110 contextTextRight(0), 00111 contextText(0), 00112 contextTextUnder(0), 00113 contextLockAction(0), 00114 dropIndicatorAction(0), 00115 context(0), 00116 dragAction(0) 00117 { 00118 } 00119 00120 void slotAppearanceChanged(); 00121 void slotContextAboutToShow(); 00122 void slotContextAboutToHide(); 00123 void slotContextLeft(); 00124 void slotContextRight(); 00125 void slotContextShowText(); 00126 void slotContextTop(); 00127 void slotContextBottom(); 00128 void slotContextIcons(); 00129 void slotContextText(); 00130 void slotContextTextRight(); 00131 void slotContextTextUnder(); 00132 void slotContextIconSize(); 00133 void slotLockToolBars(bool lock); 00134 00135 void init(bool readConfig = true, bool isMainToolBar = false); 00136 QString getPositionAsString() const; 00137 KMenu *contextMenu(const QPoint &globalPos); 00138 void setLocked(bool locked); 00139 void adjustSeparatorVisibility(); 00140 void loadKDESettings(); 00141 void applyCurrentSettings(); 00142 00143 QAction *findAction(const QString &actionName, KXMLGUIClient **client = 0) const; 00144 00145 static Qt::ToolButtonStyle toolButtonStyleFromString(const QString& style); 00146 static QString toolButtonStyleToString(Qt::ToolButtonStyle); 00147 static Qt::ToolBarArea positionFromString(const QString& position); 00148 00149 KToolBar *q; 00150 bool isMainToolBar : 1; 00151 #ifndef KDE_NO_DEPRECATED 00152 bool enableContext : 1; 00153 #endif 00154 bool unlockedMovable : 1; 00155 static bool s_editable; 00156 static bool s_locked; 00157 00158 QSet<KXMLGUIClient *> xmlguiClients; 00159 00160 QMenu* contextOrient; 00161 QMenu* contextMode; 00162 QMenu* contextSize; 00163 00164 QAction* contextButtonTitle; 00165 QAction* contextShowText; 00166 QAction* contextButtonAction; 00167 QAction* contextTop; 00168 QAction* contextLeft; 00169 QAction* contextRight; 00170 QAction* contextBottom; 00171 QAction* contextIcons; 00172 QAction* contextTextRight; 00173 QAction* contextText; 00174 QAction* contextTextUnder; 00175 KToggleAction* contextLockAction; 00176 QMap<QAction*,int> contextIconSizes; 00177 00178 class IntSetting 00179 { 00180 public: 00181 IntSetting() { 00182 for (int level = 0; level < NSettingLevels; ++level) { 00183 values[level] = Unset; 00184 } 00185 } 00186 int currentValue() const { 00187 int val = Unset; 00188 for (int level = 0; level < NSettingLevels; ++level) { 00189 if (values[level] != Unset) 00190 val = values[level]; 00191 } 00192 return val; 00193 } 00194 // Default value as far as the user is concerned is kde-global + app-xml. 00195 // If currentValue()==defaultValue() then nothing to write into kconfig. 00196 int defaultValue() const { 00197 int val = Unset; 00198 for (int level = 0; level < Level_UserSettings; ++level) { 00199 if (values[level] != Unset) 00200 val = values[level]; 00201 } 00202 return val; 00203 } 00204 QString toString() const { 00205 QString str; 00206 for (int level = 0; level < NSettingLevels; ++level) { 00207 str += QString::number(values[level]) + ' '; 00208 } 00209 return str; 00210 } 00211 int& operator[](int index) { return values[index]; } 00212 private: 00213 int values[NSettingLevels]; 00214 }; 00215 IntSetting iconSizeSettings; 00216 IntSetting toolButtonStyleSettings; // either Qt::ToolButtonStyle or -1, hence "int". 00217 00218 QList<QAction*> actionsBeingDragged; 00219 QAction* dropIndicatorAction; 00220 00221 KMenu* context; 00222 KAction* dragAction; 00223 QPoint dragStartPosition; 00224 }; 00225 00226 bool KToolBar::Private::s_editable = false; 00227 bool KToolBar::Private::s_locked = true; 00228 00229 void KToolBar::Private::init(bool readConfig, bool _isMainToolBar) 00230 { 00231 isMainToolBar = _isMainToolBar; 00232 loadKDESettings(); 00233 00234 // also read in our configurable settings (for non-xmlgui toolbars) 00235 // KDE5: we can probably remove this, if people save settings then they load them too, e.g. using KMainWindow's autosave. 00236 if (readConfig) { 00237 KConfigGroup cg(KGlobal::config(), QString()); 00238 q->applySettings(cg); 00239 } 00240 00241 if (q->mainWindow()) { 00242 // Get notified when settings change 00243 connect(q, SIGNAL(allowedAreasChanged(Qt::ToolBarAreas)), 00244 q->mainWindow(), SLOT(setSettingsDirty())); 00245 connect(q, SIGNAL(iconSizeChanged(QSize)), 00246 q->mainWindow(), SLOT(setSettingsDirty())); 00247 connect(q, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)), 00248 q->mainWindow(), SLOT(setSettingsDirty())); 00249 connect(q, SIGNAL(movableChanged(bool)), 00250 q->mainWindow(), SLOT(setSettingsDirty())); 00251 connect(q, SIGNAL(orientationChanged(Qt::Orientation)), 00252 q->mainWindow(), SLOT(setSettingsDirty())); 00253 } 00254 00255 if (!KAuthorized::authorize("movable_toolbars")) 00256 q->setMovable(false); 00257 else 00258 q->setMovable(!KToolBar::toolBarsLocked()); 00259 00260 connect(q, SIGNAL(movableChanged(bool)), 00261 q, SLOT(slotMovableChanged(bool))); 00262 00263 q->setAcceptDrops(true); 00264 00265 connect(KGlobalSettings::self(), SIGNAL(toolbarAppearanceChanged(int)), 00266 q, SLOT(slotAppearanceChanged())); 00267 connect(KIconLoader::global(), SIGNAL(iconLoaderSettingsChanged()), 00268 q, SLOT(slotAppearanceChanged())); 00269 } 00270 00271 QString KToolBar::Private::getPositionAsString() const 00272 { 00273 // get all of the stuff to save 00274 switch (q->mainWindow()->toolBarArea(const_cast<KToolBar*>(q))) { 00275 case Qt::BottomToolBarArea: 00276 return "Bottom"; 00277 case Qt::LeftToolBarArea: 00278 return "Left"; 00279 case Qt::RightToolBarArea: 00280 return "Right"; 00281 case Qt::TopToolBarArea: 00282 default: 00283 return "Top"; 00284 } 00285 } 00286 00287 KMenu *KToolBar::Private::contextMenu(const QPoint &globalPos) 00288 { 00289 if (!context) { 00290 context = new KMenu(q); 00291 00292 contextButtonTitle = context->addTitle(i18nc("@title:menu", "Show Text")); 00293 contextShowText = context->addAction(QString(), q, SLOT(slotContextShowText())); 00294 00295 context->addTitle(i18nc("@title:menu", "Toolbar Settings")); 00296 00297 contextOrient = new KMenu(i18n("Orientation"), context); 00298 00299 contextTop = contextOrient->addAction(i18nc("toolbar position string", "Top"), q, SLOT(slotContextTop())); 00300 contextTop->setChecked(true); 00301 contextLeft = contextOrient->addAction(i18nc("toolbar position string", "Left"), q, SLOT(slotContextLeft())); 00302 contextRight = contextOrient->addAction(i18nc("toolbar position string", "Right"), q, SLOT(slotContextRight())); 00303 contextBottom = contextOrient->addAction(i18nc("toolbar position string", "Bottom"), q, SLOT(slotContextBottom())); 00304 00305 QActionGroup* positionGroup = new QActionGroup(contextOrient); 00306 foreach (QAction* action, contextOrient->actions()) { 00307 action->setActionGroup(positionGroup); 00308 action->setCheckable(true); 00309 } 00310 00311 contextMode = new KMenu(i18n("Text Position"), context); 00312 00313 contextIcons = contextMode->addAction(i18n("Icons Only"), q, SLOT(slotContextIcons())); 00314 contextText = contextMode->addAction(i18n("Text Only"), q, SLOT(slotContextText())); 00315 contextTextRight = contextMode->addAction(i18n("Text Alongside Icons"), q, SLOT(slotContextTextRight())); 00316 contextTextUnder = contextMode->addAction(i18n("Text Under Icons"), q, SLOT(slotContextTextUnder())); 00317 00318 QActionGroup* textGroup = new QActionGroup(contextMode); 00319 foreach (QAction* action, contextMode->actions()) { 00320 action->setActionGroup(textGroup); 00321 action->setCheckable(true); 00322 } 00323 00324 contextSize = new KMenu(i18n("Icon Size"), context); 00325 00326 contextIconSizes.insert(contextSize->addAction(i18nc("@item:inmenu Icon size", "Default"), q, SLOT(slotContextIconSize())), 00327 iconSizeSettings.defaultValue()); 00328 00329 // Query the current theme for available sizes 00330 KIconTheme *theme = KIconLoader::global()->theme(); 00331 QList<int> avSizes; 00332 if (theme) { 00333 avSizes = theme->querySizes(isMainToolBar ? KIconLoader::MainToolbar : KIconLoader::Toolbar); 00334 } 00335 00336 qSort(avSizes); 00337 00338 if (avSizes.count() < 10) { 00339 // Fixed or threshold type icons 00340 foreach (int it, avSizes) { 00341 QString text; 00342 if (it < 19) 00343 text = i18n("Small (%1x%2)", it, it); 00344 else if (it < 25) 00345 text = i18n("Medium (%1x%2)", it, it); 00346 else if (it < 35) 00347 text = i18n("Large (%1x%2)", it, it); 00348 else 00349 text = i18n("Huge (%1x%2)", it, it); 00350 00351 // save the size in the contextIconSizes map 00352 contextIconSizes.insert(contextSize->addAction(text, q, SLOT(slotContextIconSize())), it); 00353 } 00354 } else { 00355 // Scalable icons. 00356 const int progression[] = { 16, 22, 32, 48, 64, 96, 128, 192, 256 }; 00357 00358 for (uint i = 0; i < 9; i++) { 00359 foreach (int it, avSizes) { 00360 if (it >= progression[ i ]) { 00361 QString text; 00362 if (it < 19) 00363 text = i18n("Small (%1x%2)", it, it); 00364 else if (it < 25) 00365 text = i18n("Medium (%1x%2)", it, it); 00366 else if (it < 35) 00367 text = i18n("Large (%1x%2)", it, it); 00368 else 00369 text = i18n("Huge (%1x%2)", it, it); 00370 00371 // save the size in the contextIconSizes map 00372 contextIconSizes.insert(contextSize->addAction(text, q, SLOT(slotContextIconSize())), it); 00373 break; 00374 } 00375 } 00376 } 00377 } 00378 00379 QActionGroup* sizeGroup = new QActionGroup(contextSize); 00380 foreach (QAction* action, contextSize->actions()) { 00381 action->setActionGroup(sizeGroup); 00382 action->setCheckable(true); 00383 } 00384 00385 if (!q->toolBarsLocked() && !q->isMovable()) 00386 unlockedMovable = false; 00387 00388 delete contextLockAction; 00389 contextLockAction = new KToggleAction(KIcon("system-lock-screen"), i18n("Lock Toolbar Positions"), q); 00390 contextLockAction->setChecked(q->toolBarsLocked()); 00391 connect(contextLockAction, SIGNAL(toggled(bool)), q, SLOT(slotLockToolBars(bool))); 00392 00393 // Now add the actions to the menu 00394 context->addMenu(contextMode); 00395 context->addMenu(contextSize); 00396 context->addMenu(contextOrient); 00397 context->addSeparator(); 00398 00399 connect(context, SIGNAL(aboutToShow()), q, SLOT(slotContextAboutToShow())); 00400 } 00401 00402 contextButtonAction = q->actionAt(q->mapFromGlobal(globalPos)); 00403 if (contextButtonAction) { 00404 contextShowText->setText(contextButtonAction->text()); 00405 contextShowText->setIcon(contextButtonAction->icon()); 00406 contextShowText->setCheckable(true); 00407 } 00408 00409 contextOrient->menuAction()->setVisible(!q->toolBarsLocked()); 00410 // Unplugging a submenu from abouttohide leads to the popupmenu floating around 00411 // So better simply call that code from after exec() returns (DF) 00412 //connect(context, SIGNAL(aboutToHide()), this, SLOT(slotContextAboutToHide())); 00413 00414 return context; 00415 } 00416 00417 void KToolBar::Private::setLocked(bool locked) 00418 { 00419 if (unlockedMovable) 00420 q->setMovable(!locked); 00421 } 00422 00423 void KToolBar::Private::adjustSeparatorVisibility() 00424 { 00425 bool visibleNonSeparator = false; 00426 int separatorToShow = -1; 00427 00428 for (int index = 0; index < q->actions().count(); ++index) { 00429 QAction* action = q->actions()[ index ]; 00430 if (action->isSeparator()) { 00431 if (visibleNonSeparator) { 00432 separatorToShow = index; 00433 visibleNonSeparator = false; 00434 } else { 00435 action->setVisible(false); 00436 } 00437 } else if (!visibleNonSeparator) { 00438 if (action->isVisible()) { 00439 visibleNonSeparator = true; 00440 if (separatorToShow != -1) { 00441 q->actions()[ separatorToShow ]->setVisible(true); 00442 separatorToShow = -1; 00443 } 00444 } 00445 } 00446 } 00447 00448 if (separatorToShow != -1) 00449 q->actions()[ separatorToShow ]->setVisible(false); 00450 } 00451 00452 Qt::ToolButtonStyle KToolBar::Private::toolButtonStyleFromString(const QString & _style) 00453 { 00454 QString style = _style.toLower(); 00455 if (style == "textbesideicon" || style == "icontextright") 00456 return Qt::ToolButtonTextBesideIcon; 00457 else if (style == "textundericon" || style == "icontextbottom") 00458 return Qt::ToolButtonTextUnderIcon; 00459 else if (style == "textonly") 00460 return Qt::ToolButtonTextOnly; 00461 else 00462 return Qt::ToolButtonIconOnly; 00463 } 00464 00465 QString KToolBar::Private::toolButtonStyleToString(Qt::ToolButtonStyle style) 00466 { 00467 switch(style) 00468 { 00469 case Qt::ToolButtonIconOnly: 00470 default: 00471 return "IconOnly"; 00472 case Qt::ToolButtonTextBesideIcon: 00473 return "TextBesideIcon"; 00474 case Qt::ToolButtonTextOnly: 00475 return "TextOnly"; 00476 case Qt::ToolButtonTextUnderIcon: 00477 return "TextUnderIcon"; 00478 } 00479 } 00480 00481 Qt::ToolBarArea KToolBar::Private::positionFromString(const QString& position) 00482 { 00483 Qt::ToolBarArea newposition = Qt::TopToolBarArea; 00484 if (position == QLatin1String("left")) { 00485 newposition = Qt::LeftToolBarArea; 00486 } else if (position == QLatin1String("bottom")) { 00487 newposition = Qt::BottomToolBarArea; 00488 } else if (position == QLatin1String("right")) { 00489 newposition = Qt::RightToolBarArea; 00490 } 00491 return newposition; 00492 } 00493 00494 // Global setting was changed 00495 void KToolBar::Private::slotAppearanceChanged() 00496 { 00497 loadKDESettings(); 00498 applyCurrentSettings(); 00499 } 00500 00501 void KToolBar::Private::loadKDESettings() 00502 { 00503 iconSizeSettings[Level_KDEDefault] = q->iconSizeDefault(); 00504 00505 if (isMainToolBar) { 00506 toolButtonStyleSettings[Level_KDEDefault] = q->toolButtonStyleSetting(); 00507 } else { 00508 const QString fallBack = toolButtonStyleToString(Qt::ToolButtonTextBesideIcon); 00524 KConfigGroup group(KGlobal::config(), "Toolbar style"); 00525 const QString value = group.readEntry("ToolButtonStyleOtherToolbars", fallBack); 00526 toolButtonStyleSettings[Level_KDEDefault] = KToolBar::Private::toolButtonStyleFromString(value); 00527 } 00528 } 00529 00530 // Call this after changing something in d->iconSizeSettings or d->toolButtonStyleSettings 00531 void KToolBar::Private::applyCurrentSettings() 00532 { 00533 //kDebug() << q->objectName() << "iconSizeSettings:" << iconSizeSettings.toString() << "->" << iconSizeSettings.currentValue(); 00534 const int currentIconSize = iconSizeSettings.currentValue(); 00535 q->setIconSize(QSize(currentIconSize, currentIconSize)); 00536 //kDebug() << q->objectName() << "toolButtonStyleSettings:" << toolButtonStyleSettings.toString() << "->" << toolButtonStyleSettings.currentValue(); 00537 q->setToolButtonStyle(static_cast<Qt::ToolButtonStyle>(toolButtonStyleSettings.currentValue())); 00538 00539 // And remember to save the new look later 00540 KMainWindow *kmw = q->mainWindow(); 00541 if (kmw) 00542 kmw->setSettingsDirty(); 00543 } 00544 00545 QAction *KToolBar::Private::findAction(const QString &actionName, KXMLGUIClient **clientOut) const 00546 { 00547 foreach (KXMLGUIClient* client, xmlguiClients) { 00548 QAction* action = client->actionCollection()->action(actionName); 00549 if (action) { 00550 if (clientOut) { 00551 *clientOut = client; 00552 } 00553 return action; 00554 } 00555 } 00556 return 0; 00557 } 00558 00559 void KToolBar::Private::slotContextAboutToShow() 00560 { 00569 KXmlGuiWindow *kmw = qobject_cast<KXmlGuiWindow *>(q->mainWindow()); 00570 00571 // try to find "configure toolbars" action 00572 QAction *configureAction = 0; 00573 const char* actionName = KStandardAction::name(KStandardAction::ConfigureToolbars); 00574 configureAction = findAction(actionName); 00575 00576 if (!configureAction && kmw) { 00577 configureAction = kmw->actionCollection()->action(actionName); 00578 } 00579 00580 if (configureAction) { 00581 context->addAction(configureAction); 00582 } 00583 00584 context->addAction(contextLockAction); 00585 00586 if (kmw) { 00587 kmw->setupToolbarMenuActions(); 00588 // Only allow hiding a toolbar if the action is also plugged somewhere else (e.g. menubar) 00589 QAction *tbAction = kmw->toolBarMenuAction(); 00590 if (!q->toolBarsLocked() && tbAction && tbAction->associatedWidgets().count() > 0) 00591 context->addAction(tbAction); 00592 } 00593 00594 KEditToolBar::setGlobalDefaultToolBar(q->QObject::objectName().toLatin1().constData()); 00595 00596 // Check the actions that should be checked 00597 switch (q->toolButtonStyle()) { 00598 case Qt::ToolButtonIconOnly: 00599 default: 00600 contextIcons->setChecked(true); 00601 break; 00602 case Qt::ToolButtonTextBesideIcon: 00603 contextTextRight->setChecked(true); 00604 break; 00605 case Qt::ToolButtonTextOnly: 00606 contextText->setChecked(true); 00607 break; 00608 case Qt::ToolButtonTextUnderIcon: 00609 contextTextUnder->setChecked(true); 00610 break; 00611 } 00612 00613 QMapIterator< QAction*, int > it = contextIconSizes; 00614 while (it.hasNext()) { 00615 it.next(); 00616 if (it.value() == q->iconSize().width()) { 00617 it.key()->setChecked(true); 00618 break; 00619 } 00620 } 00621 00622 switch (q->mainWindow()->toolBarArea(q)) { 00623 case Qt::BottomToolBarArea: 00624 contextBottom->setChecked(true); 00625 break; 00626 case Qt::LeftToolBarArea: 00627 contextLeft->setChecked(true); 00628 break; 00629 case Qt::RightToolBarArea: 00630 contextRight->setChecked(true); 00631 break; 00632 default: 00633 case Qt::TopToolBarArea: 00634 contextTop->setChecked(true); 00635 break; 00636 } 00637 00638 const bool showButtonSettings = contextButtonAction 00639 && !contextShowText->text().isEmpty() 00640 && contextTextRight->isChecked(); 00641 contextButtonTitle->setVisible(showButtonSettings); 00642 contextShowText->setVisible(showButtonSettings); 00643 if (showButtonSettings) { 00644 contextShowText->setChecked(contextButtonAction->priority() >= QAction::NormalPriority); 00645 } 00646 } 00647 00648 void KToolBar::Private::slotContextAboutToHide() 00649 { 00650 // We have to unplug whatever slotContextAboutToShow plugged into the menu. 00651 // Unplug the toolbar menu action 00652 KXmlGuiWindow *kmw = qobject_cast<KXmlGuiWindow *>(q->mainWindow()); 00653 if (kmw && kmw->toolBarMenuAction()) { 00654 if (kmw->toolBarMenuAction()->associatedWidgets().count() > 1) { 00655 context->removeAction(kmw->toolBarMenuAction()); 00656 } 00657 } 00658 00659 // Unplug the configure toolbars action too, since it's afterwards anyway 00660 QAction *configureAction = 0; 00661 const char* actionName = KStandardAction::name(KStandardAction::ConfigureToolbars); 00662 configureAction = findAction(actionName); 00663 00664 if (!configureAction && kmw) { 00665 configureAction = kmw->actionCollection()->action(actionName); 00666 } 00667 00668 if (configureAction) { 00669 context->removeAction(configureAction); 00670 } 00671 00672 context->removeAction(contextLockAction); 00673 } 00674 00675 void KToolBar::Private::slotContextLeft() 00676 { 00677 q->mainWindow()->addToolBar(Qt::LeftToolBarArea, q); 00678 } 00679 00680 void KToolBar::Private::slotContextRight() 00681 { 00682 q->mainWindow()->addToolBar(Qt::RightToolBarArea, q); 00683 } 00684 00685 void KToolBar::Private::slotContextShowText() 00686 { 00687 Q_ASSERT(contextButtonAction); 00688 const QAction::Priority priority = contextShowText->isChecked() 00689 ? QAction::NormalPriority : QAction::LowPriority; 00690 contextButtonAction->setPriority(priority); 00691 00692 // Find to which xml file and componentData the action belongs to 00693 KComponentData componentData; 00694 QString filename; 00695 KXMLGUIClient *client; 00696 if (findAction(contextButtonAction->objectName(), &client)) { 00697 componentData = client->componentData(); 00698 filename = client->xmlFile(); 00699 } 00700 if (filename.isEmpty()) { 00701 componentData = KGlobal::mainComponent(); 00702 filename = componentData.componentName() + "ui.rc"; 00703 } 00704 00705 // Save the priority state of the action 00706 const QString configFile = KXMLGUIFactory::readConfigFile(filename, componentData); 00707 00708 QDomDocument document; 00709 document.setContent(configFile); 00710 QDomElement elem = KXMLGUIFactory::actionPropertiesElement(document); 00711 QDomElement actionElem = KXMLGUIFactory::findActionByName(elem, contextButtonAction->objectName(), true); 00712 actionElem.setAttribute("priority", priority); 00713 KXMLGUIFactory::saveConfigFile(document, filename, componentData); 00714 } 00715 00716 void KToolBar::Private::slotContextTop() 00717 { 00718 q->mainWindow()->addToolBar(Qt::TopToolBarArea, q); 00719 } 00720 00721 void KToolBar::Private::slotContextBottom() 00722 { 00723 q->mainWindow()->addToolBar(Qt::BottomToolBarArea, q); 00724 } 00725 00726 void KToolBar::Private::slotContextIcons() 00727 { 00728 q->setToolButtonStyle(Qt::ToolButtonIconOnly); 00729 toolButtonStyleSettings[Level_UserSettings] = q->toolButtonStyle(); 00730 } 00731 00732 void KToolBar::Private::slotContextText() 00733 { 00734 q->setToolButtonStyle(Qt::ToolButtonTextOnly); 00735 toolButtonStyleSettings[Level_UserSettings] = q->toolButtonStyle(); 00736 } 00737 00738 void KToolBar::Private::slotContextTextUnder() 00739 { 00740 q->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); 00741 toolButtonStyleSettings[Level_UserSettings] = q->toolButtonStyle(); 00742 } 00743 00744 void KToolBar::Private::slotContextTextRight() 00745 { 00746 q->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 00747 toolButtonStyleSettings[Level_UserSettings] = q->toolButtonStyle(); 00748 } 00749 00750 void KToolBar::Private::slotContextIconSize() 00751 { 00752 QAction* action = qobject_cast<QAction*>(q->sender()); 00753 if (action && contextIconSizes.contains(action)) { 00754 const int iconSize = contextIconSizes.value(action); 00755 q->setIconDimensions(iconSize); 00756 } 00757 } 00758 00759 void KToolBar::Private::slotLockToolBars(bool lock) 00760 { 00761 q->setToolBarsLocked(lock); 00762 } 00763 00764 00765 00766 KToolBar::KToolBar(QWidget *parent, bool isMainToolBar, bool readConfig) 00767 : QToolBar(parent), 00768 d(new Private(this)) 00769 { 00770 d->init(readConfig, isMainToolBar); 00771 00772 // KToolBar is auto-added to the top area of the main window if parent is a QMainWindow 00773 if (QMainWindow* mw = qobject_cast<QMainWindow*>(parent)) 00774 mw->addToolBar(this); 00775 } 00776 00777 KToolBar::KToolBar(const QString& objectName, QWidget *parent, bool readConfig) 00778 : QToolBar(parent), 00779 d(new Private(this)) 00780 { 00781 setObjectName(objectName); 00782 // mainToolBar -> isMainToolBar = true -> buttonStyle is configurable 00783 // others -> isMainToolBar = false -> ### hardcoded default for buttonStyle !!! should be configurable? -> hidden key added 00784 d->init(readConfig, objectName == "mainToolBar"); 00785 00786 // KToolBar is auto-added to the top area of the main window if parent is a QMainWindow 00787 if (QMainWindow* mw = qobject_cast<QMainWindow*>(parent)) 00788 mw->addToolBar(this); 00789 } 00790 00791 KToolBar::KToolBar(const QString& objectName, QMainWindow* parent, Qt::ToolBarArea area, 00792 bool newLine, bool isMainToolBar, bool readConfig) 00793 : QToolBar(parent), 00794 d(new Private(this)) 00795 { 00796 setObjectName(objectName); 00797 d->init(readConfig, isMainToolBar); 00798 00799 if (newLine) 00800 mainWindow()->addToolBarBreak(area); 00801 00802 mainWindow()->addToolBar(area, this); 00803 00804 if (newLine) 00805 mainWindow()->addToolBarBreak(area); 00806 } 00807 00808 KToolBar::~KToolBar() 00809 { 00810 delete d->contextLockAction; 00811 delete d; 00812 } 00813 00814 #ifndef KDE_NO_DEPRECATED 00815 void KToolBar::setContextMenuEnabled(bool enable) 00816 { 00817 d->enableContext = enable; 00818 } 00819 #endif 00820 00821 #ifndef KDE_NO_DEPRECATED 00822 bool KToolBar::contextMenuEnabled() const 00823 { 00824 return d->enableContext; 00825 } 00826 #endif 00827 00828 void KToolBar::saveSettings(KConfigGroup &cg) 00829 { 00830 Q_ASSERT(!cg.name().isEmpty()); 00831 00832 cg.deleteEntry("Hidden"); // remove old key to avoid bugs from the compat code in applySettings. KDE5: remove. 00833 00834 const int currentIconSize = iconSize().width(); 00835 //kDebug() << objectName() << currentIconSize << d->iconSizeSettings.toString() << "defaultValue=" << d->iconSizeSettings.defaultValue(); 00836 if (!cg.hasDefault("IconSize") && currentIconSize == d->iconSizeSettings.defaultValue()) { 00837 cg.revertToDefault("IconSize"); 00838 d->iconSizeSettings[Level_UserSettings] = Unset; 00839 } else { 00840 cg.writeEntry("IconSize", currentIconSize); 00841 d->iconSizeSettings[Level_UserSettings] = currentIconSize; 00842 } 00843 00844 const Qt::ToolButtonStyle currentToolButtonStyle = toolButtonStyle(); 00845 if (!cg.hasDefault("ToolButtonStyle") && currentToolButtonStyle == d->toolButtonStyleSettings.defaultValue()) { 00846 cg.revertToDefault("ToolButtonStyle"); 00847 d->toolButtonStyleSettings[Level_UserSettings] = Unset; 00848 } else { 00849 cg.writeEntry("ToolButtonStyle", d->toolButtonStyleToString(currentToolButtonStyle)); 00850 d->toolButtonStyleSettings[Level_UserSettings] = currentToolButtonStyle; 00851 } 00852 } 00853 00854 #ifndef KDE_NO_DEPRECATED 00855 void KToolBar::setXMLGUIClient(KXMLGUIClient *client) 00856 { 00857 d->xmlguiClients.clear(); 00858 d->xmlguiClients << client; 00859 } 00860 #endif 00861 00862 void KToolBar::addXMLGUIClient( KXMLGUIClient *client ) 00863 { 00864 d->xmlguiClients << client; 00865 } 00866 00867 void KToolBar::contextMenuEvent(QContextMenuEvent* event) 00868 { 00869 #ifndef KDE_NO_DEPRECATED 00870 if (mainWindow() && d->enableContext) { 00871 QPointer<KToolBar> guard(this); 00872 const QPoint globalPos = event->globalPos(); 00873 d->contextMenu(globalPos)->exec(globalPos); 00874 00875 // "Configure Toolbars" recreates toolbars, so we might not exist anymore. 00876 if (guard) { 00877 d->slotContextAboutToHide(); 00878 } 00879 return; 00880 } 00881 #endif 00882 00883 QToolBar::contextMenuEvent(event); 00884 } 00885 00886 Qt::ToolButtonStyle KToolBar::toolButtonStyleSetting() 00887 { 00888 KConfigGroup group(KGlobal::config(), "Toolbar style"); 00889 const QString fallback = Private::toolButtonStyleToString(Qt::ToolButtonTextBesideIcon); 00890 return KToolBar::Private::toolButtonStyleFromString(group.readEntry("ToolButtonStyle", fallback)); 00891 } 00892 00893 void KToolBar::loadState(const QDomElement &element) 00894 { 00895 QMainWindow *mw = mainWindow(); 00896 if (!mw) 00897 return; 00898 00899 { 00900 QDomNode textNode = element.namedItem("text"); 00901 QByteArray text; 00902 QByteArray context; 00903 if (textNode.isElement()) 00904 { 00905 QDomElement textElement = textNode.toElement(); 00906 text = textElement.text().toUtf8(); 00907 context = textElement.attribute("context").toUtf8(); 00908 } 00909 else 00910 { 00911 textNode = element.namedItem("Text"); 00912 if (textNode.isElement()) 00913 { 00914 QDomElement textElement = textNode.toElement(); 00915 text = textElement.text().toUtf8(); 00916 context = textElement.attribute("context").toUtf8(); 00917 } 00918 } 00919 00920 QString i18nText; 00921 if (!text.isEmpty() && !context.isEmpty()) 00922 i18nText = i18nc(context, text); 00923 else if (!text.isEmpty()) 00924 i18nText = i18n(text); 00925 00926 if (!i18nText.isEmpty()) 00927 setWindowTitle(i18nText); 00928 } 00929 00930 /* 00931 This method is called in order to load toolbar settings from XML. 00932 However this can be used in two rather different cases: 00933 - for the initial loading of the app's XML. In that case the settings 00934 are only the defaults (Level_AppXML), the user's KConfig settings will override them 00935 00936 - for later re-loading when switching between parts in KXMLGUIFactory. 00937 In that case the XML contains the final settings, not the defaults. 00938 We do need the defaults, and the toolbar might have been completely 00939 deleted and recreated meanwhile. So we store the app-default settings 00940 into the XML. 00941 */ 00942 bool loadingAppDefaults = true; 00943 if (element.hasAttribute("tempXml")) { 00944 // this isn't the first time, so the app-xml defaults have been saved into the (in-memory) XML 00945 loadingAppDefaults = false; 00946 const QString iconSizeDefault = element.attribute("iconSizeDefault"); 00947 if (!iconSizeDefault.isEmpty()) { 00948 d->iconSizeSettings[Level_AppXML] = iconSizeDefault.toInt(); 00949 } 00950 const QString toolButtonStyleDefault = element.attribute("toolButtonStyleDefault"); 00951 if (!toolButtonStyleDefault.isEmpty()) { 00952 d->toolButtonStyleSettings[Level_AppXML] = d->toolButtonStyleFromString(toolButtonStyleDefault); 00953 } 00954 } else { 00955 // loading app defaults 00956 bool newLine = false; 00957 QString attrNewLine = element.attribute("newline").toLower(); 00958 if (!attrNewLine.isEmpty()) 00959 newLine = attrNewLine == "true"; 00960 if (newLine && mw) 00961 mw->insertToolBarBreak(this); 00962 } 00963 00964 int newIconSize = -1; 00965 if (element.hasAttribute("iconSize")) { 00966 bool ok; 00967 newIconSize = element.attribute("iconSize").trimmed().toInt(&ok); 00968 if (!ok) 00969 newIconSize = -1; 00970 } 00971 if (newIconSize != -1) 00972 d->iconSizeSettings[loadingAppDefaults ? Level_AppXML : Level_UserSettings] = newIconSize; 00973 00974 const QString newToolButtonStyle = element.attribute("iconText"); 00975 if (!newToolButtonStyle.isEmpty()) 00976 d->toolButtonStyleSettings[loadingAppDefaults ? Level_AppXML : Level_UserSettings] = d->toolButtonStyleFromString(newToolButtonStyle); 00977 00978 bool hidden = false; 00979 { 00980 QString attrHidden = element.attribute("hidden").toLower(); 00981 if (!attrHidden.isEmpty()) 00982 hidden = attrHidden == "true"; 00983 } 00984 00985 Qt::ToolBarArea pos = Qt::NoToolBarArea; 00986 { 00987 QString attrPosition = element.attribute("position").toLower(); 00988 if (!attrPosition.isEmpty()) 00989 pos = KToolBar::Private::positionFromString(attrPosition); 00990 } 00991 if (pos != Qt::NoToolBarArea) 00992 mw->addToolBar(pos, this); 00993 00994 setVisible(!hidden); 00995 00996 d->applyCurrentSettings(); 00997 } 00998 00999 // Called when switching between xmlgui clients, in order to find any unsaved settings 01000 // again when switching back to the current xmlgui client. 01001 void KToolBar::saveState(QDomElement ¤t) const 01002 { 01003 Q_ASSERT(!current.isNull()); 01004 01005 current.setAttribute("tempXml", "true"); 01006 01007 current.setAttribute("noMerge", "1"); 01008 current.setAttribute("position", d->getPositionAsString().toLower()); 01009 current.setAttribute("hidden", isHidden() ? "true" : "false"); 01010 01011 const int currentIconSize = iconSize().width(); 01012 if (currentIconSize == d->iconSizeSettings.defaultValue()) 01013 current.removeAttribute("iconSize"); 01014 else 01015 current.setAttribute("iconSize", iconSize().width()); 01016 01017 if (toolButtonStyle() == d->toolButtonStyleSettings.defaultValue()) 01018 current.removeAttribute("iconText"); 01019 else 01020 current.setAttribute("iconText", d->toolButtonStyleToString(toolButtonStyle())); 01021 01022 // Note: if this method is used by more than KXMLGUIBuilder, e.g. to save XML settings to *disk*, 01023 // then the stuff below shouldn't always be done. This is not the case currently though. 01024 if (d->iconSizeSettings[Level_AppXML] != Unset) { 01025 current.setAttribute("iconSizeDefault", d->iconSizeSettings[Level_AppXML]); 01026 } 01027 if (d->toolButtonStyleSettings[Level_AppXML] != Unset) { 01028 const Qt::ToolButtonStyle bs = static_cast<Qt::ToolButtonStyle>(d->toolButtonStyleSettings[Level_AppXML]); 01029 current.setAttribute("toolButtonStyleDefault", d->toolButtonStyleToString(bs)); 01030 } 01031 } 01032 01033 // called by KMainWindow::applyMainWindowSettings to read from the user settings 01034 void KToolBar::applySettings(const KConfigGroup &cg, bool forceGlobal) 01035 { 01036 Q_ASSERT(!cg.name().isEmpty()); 01037 Q_UNUSED(forceGlobal); // KDE5: remove 01038 01039 // a small leftover from kde3: separate bool for hidden/shown. But it's also part of saveMainWindowSettings, 01040 // it is not really useful anymore, except in the unlikely case where someone would call this by hand. 01041 // KDE5: remove the block below 01042 if (cg.hasKey("Hidden")) { 01043 const bool hidden = cg.readEntry("Hidden", false); 01044 if (hidden) 01045 hide(); 01046 else { 01047 show(); 01048 } 01049 } 01050 01051 if (cg.hasKey("IconSize")) { 01052 d->iconSizeSettings[Level_UserSettings] = cg.readEntry("IconSize", 0); 01053 } 01054 if (cg.hasKey("ToolButtonStyle")) { 01055 d->toolButtonStyleSettings[Level_UserSettings] = d->toolButtonStyleFromString(cg.readEntry("ToolButtonStyle", QString())); 01056 } 01057 01058 d->applyCurrentSettings(); 01059 } 01060 01061 KMainWindow * KToolBar::mainWindow() const 01062 { 01063 return qobject_cast<KMainWindow*>(const_cast<QObject*>(parent())); 01064 } 01065 01066 void KToolBar::setIconDimensions(int size) 01067 { 01068 QToolBar::setIconSize(QSize(size, size)); 01069 d->iconSizeSettings[Level_UserSettings] = size; 01070 } 01071 01072 int KToolBar::iconSizeDefault() const 01073 { 01074 return KIconLoader::global()->currentSize(d->isMainToolBar ? KIconLoader::MainToolbar : KIconLoader::Toolbar); 01075 } 01076 01077 void KToolBar::slotMovableChanged(bool movable) 01078 { 01079 if (movable && !KAuthorized::authorize("movable_toolbars")) 01080 setMovable(false); 01081 } 01082 01083 void KToolBar::dragEnterEvent(QDragEnterEvent *event) 01084 { 01085 if (toolBarsEditable() && event->proposedAction() & (Qt::CopyAction | Qt::MoveAction) && 01086 event->mimeData()->hasFormat("application/x-kde-action-list")) { 01087 QByteArray data = event->mimeData()->data("application/x-kde-action-list"); 01088 01089 QDataStream stream(data); 01090 01091 QStringList actionNames; 01092 01093 stream >> actionNames; 01094 01095 foreach (const QString& actionName, actionNames) { 01096 foreach (KActionCollection* ac, KActionCollection::allCollections()) { 01097 QAction* newAction = ac->action(actionName.toAscii().constData()); 01098 if (newAction) { 01099 d->actionsBeingDragged.append(newAction); 01100 break; 01101 } 01102 } 01103 } 01104 01105 if (d->actionsBeingDragged.count()) { 01106 QAction* overAction = actionAt(event->pos()); 01107 01108 QFrame* dropIndicatorWidget = new QFrame(this); 01109 dropIndicatorWidget->resize(8, height() - 4); 01110 dropIndicatorWidget->setFrameShape(QFrame::VLine); 01111 dropIndicatorWidget->setLineWidth(3); 01112 01113 d->dropIndicatorAction = insertWidget(overAction, dropIndicatorWidget); 01114 01115 insertAction(overAction, d->dropIndicatorAction); 01116 01117 event->acceptProposedAction(); 01118 return; 01119 } 01120 } 01121 01122 QToolBar::dragEnterEvent(event); 01123 } 01124 01125 void KToolBar::dragMoveEvent(QDragMoveEvent *event) 01126 { 01127 if (toolBarsEditable()) 01128 forever { 01129 if (d->dropIndicatorAction) { 01130 QAction* overAction = 0L; 01131 foreach (QAction* action, actions()) { 01132 // want to make it feel that half way across an action you're dropping on the other side of it 01133 QWidget* widget = widgetForAction(action); 01134 if (event->pos().x() < widget->pos().x() + (widget->width() / 2)) { 01135 overAction = action; 01136 break; 01137 } 01138 } 01139 01140 if (overAction != d->dropIndicatorAction) { 01141 // Check to see if the indicator is already in the right spot 01142 int dropIndicatorIndex = actions().indexOf(d->dropIndicatorAction); 01143 if (dropIndicatorIndex + 1 < actions().count()) { 01144 if (actions()[ dropIndicatorIndex + 1 ] == overAction) 01145 break; 01146 } else if (!overAction) { 01147 break; 01148 } 01149 01150 insertAction(overAction, d->dropIndicatorAction); 01151 } 01152 01153 event->accept(); 01154 return; 01155 } 01156 break; 01157 } 01158 01159 QToolBar::dragMoveEvent(event); 01160 } 01161 01162 void KToolBar::dragLeaveEvent(QDragLeaveEvent *event) 01163 { 01164 // Want to clear this even if toolBarsEditable was changed mid-drag (unlikey) 01165 delete d->dropIndicatorAction; 01166 d->dropIndicatorAction = 0L; 01167 d->actionsBeingDragged.clear(); 01168 01169 if (toolBarsEditable()) { 01170 event->accept(); 01171 return; 01172 } 01173 01174 QToolBar::dragLeaveEvent(event); 01175 } 01176 01177 void KToolBar::dropEvent(QDropEvent *event) 01178 { 01179 if (toolBarsEditable()) { 01180 foreach (QAction* action, d->actionsBeingDragged) { 01181 if (actions().contains(action)) 01182 removeAction(action); 01183 insertAction(d->dropIndicatorAction, action); 01184 } 01185 } 01186 01187 // Want to clear this even if toolBarsEditable was changed mid-drag (unlikey) 01188 delete d->dropIndicatorAction; 01189 d->dropIndicatorAction = 0L; 01190 d->actionsBeingDragged.clear(); 01191 01192 if (toolBarsEditable()) { 01193 event->accept(); 01194 return; 01195 } 01196 01197 QToolBar::dropEvent(event); 01198 } 01199 01200 void KToolBar::mousePressEvent(QMouseEvent *event) 01201 { 01202 if (toolBarsEditable() && event->button() == Qt::LeftButton) { 01203 if (KAction* action = qobject_cast<KAction*>(actionAt(event->pos()))) { 01204 d->dragAction = action; 01205 d->dragStartPosition = event->pos(); 01206 event->accept(); 01207 return; 01208 } 01209 } 01210 01211 QToolBar::mousePressEvent(event); 01212 } 01213 01214 void KToolBar::mouseMoveEvent(QMouseEvent *event) 01215 { 01216 if (!toolBarsEditable() || !d->dragAction) 01217 return QToolBar::mouseMoveEvent(event); 01218 01219 if ((event->pos() - d->dragStartPosition).manhattanLength() < QApplication::startDragDistance()) { 01220 event->accept(); 01221 return; 01222 } 01223 01224 QDrag *drag = new QDrag(this); 01225 QMimeData *mimeData = new QMimeData; 01226 01227 QByteArray data; 01228 { 01229 QDataStream stream(&data, QIODevice::WriteOnly); 01230 01231 QStringList actionNames; 01232 actionNames << d->dragAction->objectName(); 01233 01234 stream << actionNames; 01235 } 01236 01237 mimeData->setData("application/x-kde-action-list", data); 01238 01239 drag->setMimeData(mimeData); 01240 01241 Qt::DropAction dropAction = drag->start(Qt::MoveAction); 01242 01243 if (dropAction == Qt::MoveAction) 01244 // Only remove from this toolbar if it was moved to another toolbar 01245 // Otherwise the receiver moves it. 01246 if (drag->target() != this) 01247 removeAction(d->dragAction); 01248 01249 d->dragAction = 0L; 01250 event->accept(); 01251 } 01252 01253 void KToolBar::mouseReleaseEvent(QMouseEvent *event) 01254 { 01255 // Want to clear this even if toolBarsEditable was changed mid-drag (unlikey) 01256 if (d->dragAction) { 01257 d->dragAction = 0L; 01258 event->accept(); 01259 return; 01260 } 01261 01262 QToolBar::mouseReleaseEvent(event); 01263 } 01264 01265 bool KToolBar::eventFilter(QObject * watched, QEvent * event) 01266 { 01267 // Generate context menu events for disabled buttons too... 01268 if (event->type() == QEvent::MouseButtonPress) { 01269 QMouseEvent* me = static_cast<QMouseEvent*>(event); 01270 if (me->buttons() & Qt::RightButton) 01271 if (QWidget* ww = qobject_cast<QWidget*>(watched)) 01272 if (ww->parent() == this && !ww->isEnabled()) 01273 QCoreApplication::postEvent(this, new QContextMenuEvent(QContextMenuEvent::Mouse, me->pos(), me->globalPos())); 01274 01275 } else if (event->type() == QEvent::ParentChange) { 01276 // Make sure we're not leaving stale event filters around, 01277 // when a child is reparented somewhere else 01278 if (QWidget* ww = qobject_cast<QWidget*>(watched)) { 01279 if (!this->isAncestorOf(ww)) { 01280 // New parent is not a subwidget - remove event filter 01281 ww->removeEventFilter(this); 01282 foreach (QWidget* child, ww->findChildren<QWidget*>()) 01283 child->removeEventFilter(this); 01284 } 01285 } 01286 } 01287 01288 QToolButton* tb; 01289 if ((tb = qobject_cast<QToolButton*>(watched))) { 01290 const QList<QAction*> tbActions = tb->actions(); 01291 if (!tbActions.isEmpty()) { 01292 // Handle MMB on toolbar buttons 01293 if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease) { 01294 QMouseEvent* me = static_cast<QMouseEvent*>(event); 01295 if (me->button() == Qt::MidButton /*&& 01296 act->receivers(SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)))*/) { 01297 QAction* act = tbActions.first(); 01298 if (me->type() == QEvent::MouseButtonPress) 01299 tb->setDown(act->isEnabled()); 01300 else { 01301 tb->setDown(false); 01302 if (act->isEnabled()) { 01303 QMetaObject::invokeMethod(act, "triggered", Qt::DirectConnection, 01304 Q_ARG(Qt::MouseButtons, me->button()), 01305 Q_ARG(Qt::KeyboardModifiers, QApplication::keyboardModifiers())); 01306 } 01307 } 01308 } 01309 } 01310 01311 // CJK languages use more verbose accelerator marker: they add a Latin 01312 // letter in parenthesis, and put accelerator on that. Hence, the default 01313 // removal of ampersand only may not be enough there, instead the whole 01314 // parenthesis construct should be removed. Use KLocale's method to do this. 01315 if (event->type() == QEvent::Show || event->type() == QEvent::Paint || event->type() == QEvent::EnabledChange) { 01316 QAction *act = tb->defaultAction(); 01317 if (act) { 01318 const QString text = KGlobal::locale()->removeAcceleratorMarker(act->iconText().isEmpty() ? act->text() : act->iconText()); 01319 const QString toolTip = KGlobal::locale()->removeAcceleratorMarker(act->toolTip()); 01320 // Filtering messages requested by translators (scripting). 01321 tb->setText(i18nc("@action:intoolbar Text label of toolbar button", "%1", text)); 01322 tb->setToolTip(i18nc("@info:tooltip Tooltip of toolbar button", "%1", toolTip)); 01323 } 01324 } 01325 } 01326 } 01327 01328 // Redirect mouse events to the toolbar when drag + drop editing is enabled 01329 if (toolBarsEditable()) { 01330 if (QWidget* ww = qobject_cast<QWidget*>(watched)) { 01331 switch (event->type()) { 01332 case QEvent::MouseButtonPress: { 01333 QMouseEvent* me = static_cast<QMouseEvent*>(event); 01334 QMouseEvent newEvent(me->type(), mapFromGlobal(ww->mapToGlobal(me->pos())), me->globalPos(), 01335 me->button(), me->buttons(), me->modifiers()); 01336 mousePressEvent(&newEvent); 01337 return true; 01338 } 01339 case QEvent::MouseMove: { 01340 QMouseEvent* me = static_cast<QMouseEvent*>(event); 01341 QMouseEvent newEvent(me->type(), mapFromGlobal(ww->mapToGlobal(me->pos())), me->globalPos(), 01342 me->button(), me->buttons(), me->modifiers()); 01343 mouseMoveEvent(&newEvent); 01344 return true; 01345 } 01346 case QEvent::MouseButtonRelease: { 01347 QMouseEvent* me = static_cast<QMouseEvent*>(event); 01348 QMouseEvent newEvent(me->type(), mapFromGlobal(ww->mapToGlobal(me->pos())), me->globalPos(), 01349 me->button(), me->buttons(), me->modifiers()); 01350 mouseReleaseEvent(&newEvent); 01351 return true; 01352 } 01353 default: 01354 break; 01355 } 01356 } 01357 } 01358 01359 return QToolBar::eventFilter(watched, event); 01360 } 01361 01362 void KToolBar::actionEvent(QActionEvent * event) 01363 { 01364 if (event->type() == QEvent::ActionRemoved) { 01365 QWidget* widget = widgetForAction(event->action()); 01366 if (widget) { 01367 widget->removeEventFilter(this); 01368 01369 foreach (QWidget* child, widget->findChildren<QWidget*>()) 01370 child->removeEventFilter(this); 01371 } 01372 } 01373 01374 QToolBar::actionEvent(event); 01375 01376 if (event->type() == QEvent::ActionAdded) { 01377 QWidget* widget = widgetForAction(event->action()); 01378 if (widget) { 01379 widget->installEventFilter(this); 01380 01381 foreach (QWidget* child, widget->findChildren<QWidget*>()) 01382 child->installEventFilter(this); 01383 // Center widgets that do not have any use for more space. See bug 165274 01384 if (!(widget->sizePolicy().horizontalPolicy() & QSizePolicy::GrowFlag) 01385 // ... but do not center when using text besides icon in vertical toolbar. See bug 243196 01386 && !(orientation() == Qt::Vertical && toolButtonStyle() == Qt::ToolButtonTextBesideIcon)) { 01387 const int index = layout()->indexOf(widget); 01388 if (index != -1) { 01389 layout()->itemAt(index)->setAlignment(Qt::AlignJustify); 01390 } 01391 } 01392 } 01393 } 01394 01395 d->adjustSeparatorVisibility(); 01396 } 01397 01398 bool KToolBar::toolBarsEditable() 01399 { 01400 return KToolBar::Private::s_editable; 01401 } 01402 01403 void KToolBar::setToolBarsEditable(bool editable) 01404 { 01405 if (KToolBar::Private::s_editable != editable) { 01406 KToolBar::Private::s_editable = editable; 01407 } 01408 } 01409 01410 void KToolBar::setToolBarsLocked(bool locked) 01411 { 01412 if (KToolBar::Private::s_locked != locked) { 01413 KToolBar::Private::s_locked = locked; 01414 01415 foreach (KMainWindow* mw, KMainWindow::memberList()) { 01416 foreach (KToolBar* toolbar, mw->findChildren<KToolBar*>()) { 01417 toolbar->d->setLocked(locked); 01418 } 01419 } 01420 } 01421 } 01422 01423 bool KToolBar::toolBarsLocked() 01424 { 01425 return KToolBar::Private::s_locked; 01426 } 01427 01428 #include "ktoolbar.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Wed May 2 2012 17:57:56 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Wed May 2 2012 17:57:56 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.