mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-23 18:32:49 +00:00
1435 lines
47 KiB
C++
1435 lines
47 KiB
C++
/* This file is part of the KDE libraries
|
|
Copyright
|
|
(C) 2000 Reginald Stadlbauer (reggie@kde.org)
|
|
(C) 1997, 1998 Stephan Kulow (coolo@kde.org)
|
|
(C) 1997, 1998 Mark Donohoe (donohoe@kde.org)
|
|
(C) 1997, 1998 Sven Radej (radej@kde.org)
|
|
(C) 1997, 1998 Matthias Ettrich (ettrich@kde.org)
|
|
(C) 1999 Chris Schlaeger (cs@kde.org)
|
|
(C) 1999 Kurt Granroth (granroth@kde.org)
|
|
(C) 2005-2006 Hamish Rodda (rodda@kde.org)
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License version 2 as published by the Free Software Foundation.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "ktoolbar.h"
|
|
|
|
#include <config.h>
|
|
|
|
#include <QtCore/QPointer>
|
|
#include <QtGui/QDesktopWidget>
|
|
#include <QtGui/QFrame>
|
|
#include <QtGui/QLayout>
|
|
#include <QtGui/QMouseEvent>
|
|
#include <QtGui/QToolButton>
|
|
#include <QtXml/QDomElement>
|
|
|
|
#include <kaction.h>
|
|
#include <kactioncollection.h>
|
|
#include <kapplication.h>
|
|
#include <kauthorized.h>
|
|
#include <kconfig.h>
|
|
#include <kdebug.h>
|
|
#include <kedittoolbar.h>
|
|
#include <kglobalsettings.h>
|
|
#include <kguiitem.h>
|
|
#include <kicon.h>
|
|
#include <kiconloader.h>
|
|
#include <klocale.h>
|
|
#include <kxmlguiwindow.h>
|
|
#include <kmenu.h>
|
|
#include <kstandardaction.h>
|
|
#include <ktoggleaction.h>
|
|
#include <kxmlguifactory.h>
|
|
|
|
#include <kconfiggroup.h>
|
|
|
|
/*
|
|
Toolbar settings (e.g. icon size or toolButtonStyle)
|
|
=====================================================
|
|
|
|
We have the following stack of settings (in order of priority) :
|
|
- user-specified settings (loaded/saved in KConfig)
|
|
- developer-specified settings in the XMLGUI file (if using xmlgui) (cannot change at runtime)
|
|
- KDE-global default (user-configurable; can change at runtime)
|
|
and when switching between kparts, they are saved as xml in memory,
|
|
which, in the unlikely case of no-kmainwindow-autosaving, could be
|
|
different from the user-specified settings saved in KConfig and would have
|
|
priority over it.
|
|
|
|
So, in summary, without XML:
|
|
Global config / User settings (loaded/saved in kconfig)
|
|
and with XML:
|
|
Global config / App-XML attributes / User settings (loaded/saved in kconfig)
|
|
|
|
And all those settings (except the KDE-global defaults) have to be stored in memory
|
|
since we cannot retrieve them at random points in time, not knowing the xml document
|
|
nor config file that holds these settings. Hence the iconSizeSettings and toolButtonStyleSettings arrays.
|
|
|
|
For instance, if you change the KDE-global default, whether this makes a change
|
|
on a given toolbar depends on whether there are settings at Level_AppXML or Level_UserSettings.
|
|
Only if there are no settings at those levels, should the change of KDEDefault make a difference.
|
|
*/
|
|
enum SettingLevel { Level_KDEDefault, Level_AppXML, Level_UserSettings,
|
|
NSettingLevels };
|
|
enum { Unset = -1 };
|
|
|
|
class KToolBar::Private
|
|
{
|
|
public:
|
|
Private(KToolBar *qq)
|
|
: q(qq),
|
|
isMainToolBar(false),
|
|
#ifndef KDE_NO_DEPRECATED
|
|
enableContext(true),
|
|
#endif
|
|
unlockedMovable(true),
|
|
contextOrient(0),
|
|
contextMode(0),
|
|
contextSize(0),
|
|
contextButtonTitle(0),
|
|
contextShowText(0),
|
|
contextButtonAction(0),
|
|
contextTop(0),
|
|
contextLeft(0),
|
|
contextRight(0),
|
|
contextBottom(0),
|
|
contextIcons(0),
|
|
contextTextRight(0),
|
|
contextText(0),
|
|
contextTextUnder(0),
|
|
contextLockAction(0),
|
|
dropIndicatorAction(0),
|
|
context(0),
|
|
dragAction(0)
|
|
{
|
|
}
|
|
|
|
void slotAppearanceChanged();
|
|
void slotContextAboutToShow();
|
|
void slotContextAboutToHide();
|
|
void slotContextLeft();
|
|
void slotContextRight();
|
|
void slotContextShowText();
|
|
void slotContextTop();
|
|
void slotContextBottom();
|
|
void slotContextIcons();
|
|
void slotContextText();
|
|
void slotContextTextRight();
|
|
void slotContextTextUnder();
|
|
void slotContextIconSize();
|
|
void slotLockToolBars(bool lock);
|
|
|
|
void init(bool readConfig = true, bool isMainToolBar = false);
|
|
QString getPositionAsString() const;
|
|
KMenu *contextMenu(const QPoint &globalPos);
|
|
void setLocked(bool locked);
|
|
void adjustSeparatorVisibility();
|
|
void loadKDESettings();
|
|
void applyCurrentSettings();
|
|
|
|
QAction *findAction(const QString &actionName, KXMLGUIClient **client = 0) const;
|
|
|
|
static Qt::ToolButtonStyle toolButtonStyleFromString(const QString& style);
|
|
static QString toolButtonStyleToString(Qt::ToolButtonStyle);
|
|
static Qt::ToolBarArea positionFromString(const QString& position);
|
|
|
|
KToolBar *q;
|
|
bool isMainToolBar : 1;
|
|
#ifndef KDE_NO_DEPRECATED
|
|
bool enableContext : 1;
|
|
#endif
|
|
bool unlockedMovable : 1;
|
|
static bool s_editable;
|
|
static bool s_locked;
|
|
|
|
QSet<KXMLGUIClient *> xmlguiClients;
|
|
|
|
QMenu* contextOrient;
|
|
QMenu* contextMode;
|
|
QMenu* contextSize;
|
|
|
|
QAction* contextButtonTitle;
|
|
QAction* contextShowText;
|
|
QAction* contextButtonAction;
|
|
QAction* contextTop;
|
|
QAction* contextLeft;
|
|
QAction* contextRight;
|
|
QAction* contextBottom;
|
|
QAction* contextIcons;
|
|
QAction* contextTextRight;
|
|
QAction* contextText;
|
|
QAction* contextTextUnder;
|
|
KToggleAction* contextLockAction;
|
|
QMap<QAction*,int> contextIconSizes;
|
|
|
|
class IntSetting
|
|
{
|
|
public:
|
|
IntSetting() {
|
|
for (int level = 0; level < NSettingLevels; ++level) {
|
|
values[level] = Unset;
|
|
}
|
|
}
|
|
int currentValue() const {
|
|
int val = Unset;
|
|
for (int level = 0; level < NSettingLevels; ++level) {
|
|
if (values[level] != Unset)
|
|
val = values[level];
|
|
}
|
|
return val;
|
|
}
|
|
// Default value as far as the user is concerned is kde-global + app-xml.
|
|
// If currentValue()==defaultValue() then nothing to write into kconfig.
|
|
int defaultValue() const {
|
|
int val = Unset;
|
|
for (int level = 0; level < Level_UserSettings; ++level) {
|
|
if (values[level] != Unset)
|
|
val = values[level];
|
|
}
|
|
return val;
|
|
}
|
|
QString toString() const {
|
|
QString str;
|
|
for (int level = 0; level < NSettingLevels; ++level) {
|
|
str += QString::number(values[level]) + ' ';
|
|
}
|
|
return str;
|
|
}
|
|
int& operator[](int index) { return values[index]; }
|
|
private:
|
|
int values[NSettingLevels];
|
|
};
|
|
IntSetting iconSizeSettings;
|
|
IntSetting toolButtonStyleSettings; // either Qt::ToolButtonStyle or -1, hence "int".
|
|
|
|
QList<QAction*> actionsBeingDragged;
|
|
QAction* dropIndicatorAction;
|
|
|
|
KMenu* context;
|
|
KAction* dragAction;
|
|
QPoint dragStartPosition;
|
|
};
|
|
|
|
bool KToolBar::Private::s_editable = false;
|
|
bool KToolBar::Private::s_locked = true;
|
|
|
|
void KToolBar::Private::init(bool readConfig, bool _isMainToolBar)
|
|
{
|
|
isMainToolBar = _isMainToolBar;
|
|
loadKDESettings();
|
|
|
|
// also read in our configurable settings (for non-xmlgui toolbars)
|
|
// KDE5: we can probably remove this, if people save settings then they load them too, e.g. using KMainWindow's autosave.
|
|
if (readConfig) {
|
|
KConfigGroup cg(KGlobal::config(), QString());
|
|
q->applySettings(cg);
|
|
}
|
|
|
|
if (q->mainWindow()) {
|
|
// Get notified when settings change
|
|
connect(q, SIGNAL(allowedAreasChanged(Qt::ToolBarAreas)),
|
|
q->mainWindow(), SLOT(setSettingsDirty()));
|
|
connect(q, SIGNAL(iconSizeChanged(QSize)),
|
|
q->mainWindow(), SLOT(setSettingsDirty()));
|
|
connect(q, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
|
|
q->mainWindow(), SLOT(setSettingsDirty()));
|
|
connect(q, SIGNAL(movableChanged(bool)),
|
|
q->mainWindow(), SLOT(setSettingsDirty()));
|
|
connect(q, SIGNAL(orientationChanged(Qt::Orientation)),
|
|
q->mainWindow(), SLOT(setSettingsDirty()));
|
|
}
|
|
|
|
if (!KAuthorized::authorize("movable_toolbars"))
|
|
q->setMovable(false);
|
|
else
|
|
q->setMovable(!KToolBar::toolBarsLocked());
|
|
|
|
connect(q, SIGNAL(movableChanged(bool)),
|
|
q, SLOT(slotMovableChanged(bool)));
|
|
|
|
q->setAcceptDrops(true);
|
|
|
|
connect(KGlobalSettings::self(), SIGNAL(toolbarAppearanceChanged(int)),
|
|
q, SLOT(slotAppearanceChanged()));
|
|
connect(KIconLoader::global(), SIGNAL(iconLoaderSettingsChanged()),
|
|
q, SLOT(slotAppearanceChanged()));
|
|
}
|
|
|
|
QString KToolBar::Private::getPositionAsString() const
|
|
{
|
|
// get all of the stuff to save
|
|
switch (q->mainWindow()->toolBarArea(const_cast<KToolBar*>(q))) {
|
|
case Qt::BottomToolBarArea:
|
|
return "Bottom";
|
|
case Qt::LeftToolBarArea:
|
|
return "Left";
|
|
case Qt::RightToolBarArea:
|
|
return "Right";
|
|
case Qt::TopToolBarArea:
|
|
default:
|
|
return "Top";
|
|
}
|
|
}
|
|
|
|
KMenu *KToolBar::Private::contextMenu(const QPoint &globalPos)
|
|
{
|
|
if (!context) {
|
|
context = new KMenu(q);
|
|
|
|
contextButtonTitle = context->addTitle(i18nc("@title:menu", "Show Text"));
|
|
contextShowText = context->addAction(QString(), q, SLOT(slotContextShowText()));
|
|
|
|
context->addTitle(i18nc("@title:menu", "Toolbar Settings"));
|
|
|
|
contextOrient = new KMenu(i18nc("Toolbar orientation", "Orientation"), context);
|
|
|
|
contextTop = contextOrient->addAction(i18nc("toolbar position string", "Top"), q, SLOT(slotContextTop()));
|
|
contextTop->setChecked(true);
|
|
contextLeft = contextOrient->addAction(i18nc("toolbar position string", "Left"), q, SLOT(slotContextLeft()));
|
|
contextRight = contextOrient->addAction(i18nc("toolbar position string", "Right"), q, SLOT(slotContextRight()));
|
|
contextBottom = contextOrient->addAction(i18nc("toolbar position string", "Bottom"), q, SLOT(slotContextBottom()));
|
|
|
|
QActionGroup* positionGroup = new QActionGroup(contextOrient);
|
|
foreach (QAction* action, contextOrient->actions()) {
|
|
action->setActionGroup(positionGroup);
|
|
action->setCheckable(true);
|
|
}
|
|
|
|
contextMode = new KMenu(i18n("Text Position"), context);
|
|
|
|
contextIcons = contextMode->addAction(i18n("Icons Only"), q, SLOT(slotContextIcons()));
|
|
contextText = contextMode->addAction(i18n("Text Only"), q, SLOT(slotContextText()));
|
|
contextTextRight = contextMode->addAction(i18n("Text Alongside Icons"), q, SLOT(slotContextTextRight()));
|
|
contextTextUnder = contextMode->addAction(i18n("Text Under Icons"), q, SLOT(slotContextTextUnder()));
|
|
|
|
QActionGroup* textGroup = new QActionGroup(contextMode);
|
|
foreach (QAction* action, contextMode->actions()) {
|
|
action->setActionGroup(textGroup);
|
|
action->setCheckable(true);
|
|
}
|
|
|
|
contextSize = new KMenu(i18n("Icon Size"), context);
|
|
|
|
contextIconSizes.insert(contextSize->addAction(i18nc("@item:inmenu Icon size", "Default"), q, SLOT(slotContextIconSize())),
|
|
iconSizeSettings.defaultValue());
|
|
|
|
// Query the current theme for available sizes
|
|
KIconTheme *theme = KIconLoader::global()->theme();
|
|
QList<int> avSizes;
|
|
if (theme) {
|
|
avSizes = theme->querySizes(isMainToolBar ? KIconLoader::MainToolbar : KIconLoader::Toolbar);
|
|
}
|
|
|
|
qSort(avSizes);
|
|
|
|
if (avSizes.count() < 10) {
|
|
// Fixed or threshold type icons
|
|
foreach (int it, avSizes) {
|
|
QString text;
|
|
if (it < 19)
|
|
text = i18n("Small (%1x%2)", it, it);
|
|
else if (it < 25)
|
|
text = i18n("Medium (%1x%2)", it, it);
|
|
else if (it < 35)
|
|
text = i18n("Large (%1x%2)", it, it);
|
|
else
|
|
text = i18n("Huge (%1x%2)", it, it);
|
|
|
|
// save the size in the contextIconSizes map
|
|
contextIconSizes.insert(contextSize->addAction(text, q, SLOT(slotContextIconSize())), it);
|
|
}
|
|
} else {
|
|
// Scalable icons.
|
|
const int progression[] = { 16, 22, 32, 48, 64, 96, 128, 192, 256 };
|
|
|
|
for (uint i = 0; i < 9; i++) {
|
|
foreach (int it, avSizes) {
|
|
if (it >= progression[ i ]) {
|
|
QString text;
|
|
if (it < 19)
|
|
text = i18n("Small (%1x%2)", it, it);
|
|
else if (it < 25)
|
|
text = i18n("Medium (%1x%2)", it, it);
|
|
else if (it < 35)
|
|
text = i18n("Large (%1x%2)", it, it);
|
|
else
|
|
text = i18n("Huge (%1x%2)", it, it);
|
|
|
|
// save the size in the contextIconSizes map
|
|
contextIconSizes.insert(contextSize->addAction(text, q, SLOT(slotContextIconSize())), it);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
QActionGroup* sizeGroup = new QActionGroup(contextSize);
|
|
foreach (QAction* action, contextSize->actions()) {
|
|
action->setActionGroup(sizeGroup);
|
|
action->setCheckable(true);
|
|
}
|
|
|
|
if (!q->toolBarsLocked() && !q->isMovable())
|
|
unlockedMovable = false;
|
|
|
|
delete contextLockAction;
|
|
contextLockAction = new KToggleAction(KIcon("system-lock-screen"), i18n("Lock Toolbar Positions"), q);
|
|
contextLockAction->setChecked(q->toolBarsLocked());
|
|
connect(contextLockAction, SIGNAL(toggled(bool)), q, SLOT(slotLockToolBars(bool)));
|
|
|
|
// Now add the actions to the menu
|
|
context->addMenu(contextMode);
|
|
context->addMenu(contextSize);
|
|
context->addMenu(contextOrient);
|
|
context->addSeparator();
|
|
|
|
connect(context, SIGNAL(aboutToShow()), q, SLOT(slotContextAboutToShow()));
|
|
}
|
|
|
|
contextButtonAction = q->actionAt(q->mapFromGlobal(globalPos));
|
|
if (contextButtonAction) {
|
|
contextShowText->setText(contextButtonAction->text());
|
|
contextShowText->setIcon(contextButtonAction->icon());
|
|
contextShowText->setCheckable(true);
|
|
}
|
|
|
|
contextOrient->menuAction()->setVisible(!q->toolBarsLocked());
|
|
// Unplugging a submenu from abouttohide leads to the popupmenu floating around
|
|
// So better simply call that code from after exec() returns (DF)
|
|
//connect(context, SIGNAL(aboutToHide()), this, SLOT(slotContextAboutToHide()));
|
|
|
|
return context;
|
|
}
|
|
|
|
void KToolBar::Private::setLocked(bool locked)
|
|
{
|
|
if (unlockedMovable)
|
|
q->setMovable(!locked);
|
|
}
|
|
|
|
void KToolBar::Private::adjustSeparatorVisibility()
|
|
{
|
|
bool visibleNonSeparator = false;
|
|
int separatorToShow = -1;
|
|
|
|
for (int index = 0; index < q->actions().count(); ++index) {
|
|
QAction* action = q->actions()[ index ];
|
|
if (action->isSeparator()) {
|
|
if (visibleNonSeparator) {
|
|
separatorToShow = index;
|
|
visibleNonSeparator = false;
|
|
} else {
|
|
action->setVisible(false);
|
|
}
|
|
} else if (!visibleNonSeparator) {
|
|
if (action->isVisible()) {
|
|
visibleNonSeparator = true;
|
|
if (separatorToShow != -1) {
|
|
q->actions()[ separatorToShow ]->setVisible(true);
|
|
separatorToShow = -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (separatorToShow != -1)
|
|
q->actions()[ separatorToShow ]->setVisible(false);
|
|
}
|
|
|
|
Qt::ToolButtonStyle KToolBar::Private::toolButtonStyleFromString(const QString & _style)
|
|
{
|
|
QString style = _style.toLower();
|
|
if (style == "textbesideicon" || style == "icontextright")
|
|
return Qt::ToolButtonTextBesideIcon;
|
|
else if (style == "textundericon" || style == "icontextbottom")
|
|
return Qt::ToolButtonTextUnderIcon;
|
|
else if (style == "textonly")
|
|
return Qt::ToolButtonTextOnly;
|
|
else
|
|
return Qt::ToolButtonIconOnly;
|
|
}
|
|
|
|
QString KToolBar::Private::toolButtonStyleToString(Qt::ToolButtonStyle style)
|
|
{
|
|
switch(style)
|
|
{
|
|
case Qt::ToolButtonIconOnly:
|
|
default:
|
|
return "IconOnly";
|
|
case Qt::ToolButtonTextBesideIcon:
|
|
return "TextBesideIcon";
|
|
case Qt::ToolButtonTextOnly:
|
|
return "TextOnly";
|
|
case Qt::ToolButtonTextUnderIcon:
|
|
return "TextUnderIcon";
|
|
}
|
|
}
|
|
|
|
Qt::ToolBarArea KToolBar::Private::positionFromString(const QString& position)
|
|
{
|
|
Qt::ToolBarArea newposition = Qt::TopToolBarArea;
|
|
if (position == QLatin1String("left")) {
|
|
newposition = Qt::LeftToolBarArea;
|
|
} else if (position == QLatin1String("bottom")) {
|
|
newposition = Qt::BottomToolBarArea;
|
|
} else if (position == QLatin1String("right")) {
|
|
newposition = Qt::RightToolBarArea;
|
|
}
|
|
return newposition;
|
|
}
|
|
|
|
// Global setting was changed
|
|
void KToolBar::Private::slotAppearanceChanged()
|
|
{
|
|
loadKDESettings();
|
|
applyCurrentSettings();
|
|
}
|
|
|
|
void KToolBar::Private::loadKDESettings()
|
|
{
|
|
iconSizeSettings[Level_KDEDefault] = q->iconSizeDefault();
|
|
|
|
if (isMainToolBar) {
|
|
toolButtonStyleSettings[Level_KDEDefault] = q->toolButtonStyleSetting();
|
|
} else {
|
|
const QString fallBack = toolButtonStyleToString(Qt::ToolButtonTextBesideIcon);
|
|
/**
|
|
TODO: if we get complaints about text beside icons on small screens,
|
|
try the following code out on such systems - aseigo.
|
|
// if we are on a small screen with a non-landscape ratio, then
|
|
// we revert to text under icons since width is probably not our
|
|
// friend in such cases
|
|
QDesktopWidget *desktop = QApplication::desktop();
|
|
QRect screenGeom = desktop->screenGeometry(desktop->primaryScreen());
|
|
qreal ratio = screenGeom.width() / qreal(screenGeom.height());
|
|
|
|
if (screenGeom.width() < 1024 && ratio <= 1.4) {
|
|
fallBack = "TextUnderIcon";
|
|
}
|
|
**/
|
|
|
|
KConfigGroup group(KGlobal::config(), "Toolbar style");
|
|
const QString value = group.readEntry("ToolButtonStyleOtherToolbars", fallBack);
|
|
toolButtonStyleSettings[Level_KDEDefault] = KToolBar::Private::toolButtonStyleFromString(value);
|
|
}
|
|
}
|
|
|
|
// Call this after changing something in d->iconSizeSettings or d->toolButtonStyleSettings
|
|
void KToolBar::Private::applyCurrentSettings()
|
|
{
|
|
//kDebug() << q->objectName() << "iconSizeSettings:" << iconSizeSettings.toString() << "->" << iconSizeSettings.currentValue();
|
|
const int currentIconSize = iconSizeSettings.currentValue();
|
|
q->setIconSize(QSize(currentIconSize, currentIconSize));
|
|
//kDebug() << q->objectName() << "toolButtonStyleSettings:" << toolButtonStyleSettings.toString() << "->" << toolButtonStyleSettings.currentValue();
|
|
q->setToolButtonStyle(static_cast<Qt::ToolButtonStyle>(toolButtonStyleSettings.currentValue()));
|
|
|
|
// And remember to save the new look later
|
|
KMainWindow *kmw = q->mainWindow();
|
|
if (kmw)
|
|
kmw->setSettingsDirty();
|
|
}
|
|
|
|
QAction *KToolBar::Private::findAction(const QString &actionName, KXMLGUIClient **clientOut) const
|
|
{
|
|
foreach (KXMLGUIClient* client, xmlguiClients) {
|
|
QAction* action = client->actionCollection()->action(actionName);
|
|
if (action) {
|
|
if (clientOut) {
|
|
*clientOut = client;
|
|
}
|
|
return action;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void KToolBar::Private::slotContextAboutToShow()
|
|
{
|
|
/**
|
|
* The idea here is to reuse the "static" part of the menu to save time.
|
|
* But the "Toolbars" action is dynamic (can be a single action or a submenu)
|
|
* and ToolBarHandler::setupActions() deletes it, so better not keep it around.
|
|
* So we currently plug/unplug the last two actions of the menu.
|
|
* Another way would be to keep around the actions and plug them all into a (new each time) popupmenu.
|
|
*/
|
|
|
|
KXmlGuiWindow *kmw = qobject_cast<KXmlGuiWindow *>(q->mainWindow());
|
|
|
|
// try to find "configure toolbars" action
|
|
QAction *configureAction = 0;
|
|
const char* actionName = KStandardAction::name(KStandardAction::ConfigureToolbars);
|
|
configureAction = findAction(actionName);
|
|
|
|
if (!configureAction && kmw) {
|
|
configureAction = kmw->actionCollection()->action(actionName);
|
|
}
|
|
|
|
if (configureAction) {
|
|
context->addAction(configureAction);
|
|
}
|
|
|
|
context->addAction(contextLockAction);
|
|
|
|
if (kmw) {
|
|
kmw->setupToolbarMenuActions();
|
|
// Only allow hiding a toolbar if the action is also plugged somewhere else (e.g. menubar)
|
|
QAction *tbAction = kmw->toolBarMenuAction();
|
|
if (!q->toolBarsLocked() && tbAction && tbAction->associatedWidgets().count() > 0)
|
|
context->addAction(tbAction);
|
|
}
|
|
|
|
KEditToolBar::setGlobalDefaultToolBar(q->QObject::objectName().toLatin1().constData());
|
|
|
|
// Check the actions that should be checked
|
|
switch (q->toolButtonStyle()) {
|
|
case Qt::ToolButtonIconOnly:
|
|
default:
|
|
contextIcons->setChecked(true);
|
|
break;
|
|
case Qt::ToolButtonTextBesideIcon:
|
|
contextTextRight->setChecked(true);
|
|
break;
|
|
case Qt::ToolButtonTextOnly:
|
|
contextText->setChecked(true);
|
|
break;
|
|
case Qt::ToolButtonTextUnderIcon:
|
|
contextTextUnder->setChecked(true);
|
|
break;
|
|
}
|
|
|
|
QMapIterator< QAction*, int > it = contextIconSizes;
|
|
while (it.hasNext()) {
|
|
it.next();
|
|
if (it.value() == q->iconSize().width()) {
|
|
it.key()->setChecked(true);
|
|
break;
|
|
}
|
|
}
|
|
|
|
switch (q->mainWindow()->toolBarArea(q)) {
|
|
case Qt::BottomToolBarArea:
|
|
contextBottom->setChecked(true);
|
|
break;
|
|
case Qt::LeftToolBarArea:
|
|
contextLeft->setChecked(true);
|
|
break;
|
|
case Qt::RightToolBarArea:
|
|
contextRight->setChecked(true);
|
|
break;
|
|
default:
|
|
case Qt::TopToolBarArea:
|
|
contextTop->setChecked(true);
|
|
break;
|
|
}
|
|
|
|
const bool showButtonSettings = contextButtonAction
|
|
&& !contextShowText->text().isEmpty()
|
|
&& contextTextRight->isChecked();
|
|
contextButtonTitle->setVisible(showButtonSettings);
|
|
contextShowText->setVisible(showButtonSettings);
|
|
if (showButtonSettings) {
|
|
contextShowText->setChecked(contextButtonAction->priority() >= QAction::NormalPriority);
|
|
}
|
|
}
|
|
|
|
void KToolBar::Private::slotContextAboutToHide()
|
|
{
|
|
// We have to unplug whatever slotContextAboutToShow plugged into the menu.
|
|
// Unplug the toolbar menu action
|
|
KXmlGuiWindow *kmw = qobject_cast<KXmlGuiWindow *>(q->mainWindow());
|
|
if (kmw && kmw->toolBarMenuAction()) {
|
|
if (kmw->toolBarMenuAction()->associatedWidgets().count() > 1) {
|
|
context->removeAction(kmw->toolBarMenuAction());
|
|
}
|
|
}
|
|
|
|
// Unplug the configure toolbars action too, since it's afterwards anyway
|
|
QAction *configureAction = 0;
|
|
const char* actionName = KStandardAction::name(KStandardAction::ConfigureToolbars);
|
|
configureAction = findAction(actionName);
|
|
|
|
if (!configureAction && kmw) {
|
|
configureAction = kmw->actionCollection()->action(actionName);
|
|
}
|
|
|
|
if (configureAction) {
|
|
context->removeAction(configureAction);
|
|
}
|
|
|
|
context->removeAction(contextLockAction);
|
|
}
|
|
|
|
void KToolBar::Private::slotContextLeft()
|
|
{
|
|
q->mainWindow()->addToolBar(Qt::LeftToolBarArea, q);
|
|
}
|
|
|
|
void KToolBar::Private::slotContextRight()
|
|
{
|
|
q->mainWindow()->addToolBar(Qt::RightToolBarArea, q);
|
|
}
|
|
|
|
void KToolBar::Private::slotContextShowText()
|
|
{
|
|
Q_ASSERT(contextButtonAction);
|
|
const QAction::Priority priority = contextShowText->isChecked()
|
|
? QAction::NormalPriority : QAction::LowPriority;
|
|
contextButtonAction->setPriority(priority);
|
|
|
|
// Find to which xml file and componentData the action belongs to
|
|
KComponentData componentData;
|
|
QString filename;
|
|
KXMLGUIClient *client;
|
|
if (findAction(contextButtonAction->objectName(), &client)) {
|
|
componentData = client->componentData();
|
|
filename = client->xmlFile();
|
|
}
|
|
if (filename.isEmpty()) {
|
|
componentData = KGlobal::mainComponent();
|
|
filename = componentData.componentName() + "ui.rc";
|
|
}
|
|
|
|
// Save the priority state of the action
|
|
const QString configFile = KXMLGUIFactory::readConfigFile(filename, componentData);
|
|
|
|
QDomDocument document;
|
|
document.setContent(configFile);
|
|
QDomElement elem = KXMLGUIFactory::actionPropertiesElement(document);
|
|
QDomElement actionElem = KXMLGUIFactory::findActionByName(elem, contextButtonAction->objectName(), true);
|
|
actionElem.setAttribute("priority", priority);
|
|
KXMLGUIFactory::saveConfigFile(document, filename, componentData);
|
|
}
|
|
|
|
void KToolBar::Private::slotContextTop()
|
|
{
|
|
q->mainWindow()->addToolBar(Qt::TopToolBarArea, q);
|
|
}
|
|
|
|
void KToolBar::Private::slotContextBottom()
|
|
{
|
|
q->mainWindow()->addToolBar(Qt::BottomToolBarArea, q);
|
|
}
|
|
|
|
void KToolBar::Private::slotContextIcons()
|
|
{
|
|
q->setToolButtonStyle(Qt::ToolButtonIconOnly);
|
|
toolButtonStyleSettings[Level_UserSettings] = q->toolButtonStyle();
|
|
}
|
|
|
|
void KToolBar::Private::slotContextText()
|
|
{
|
|
q->setToolButtonStyle(Qt::ToolButtonTextOnly);
|
|
toolButtonStyleSettings[Level_UserSettings] = q->toolButtonStyle();
|
|
}
|
|
|
|
void KToolBar::Private::slotContextTextUnder()
|
|
{
|
|
q->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
|
|
toolButtonStyleSettings[Level_UserSettings] = q->toolButtonStyle();
|
|
}
|
|
|
|
void KToolBar::Private::slotContextTextRight()
|
|
{
|
|
q->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
|
toolButtonStyleSettings[Level_UserSettings] = q->toolButtonStyle();
|
|
}
|
|
|
|
void KToolBar::Private::slotContextIconSize()
|
|
{
|
|
QAction* action = qobject_cast<QAction*>(q->sender());
|
|
if (action && contextIconSizes.contains(action)) {
|
|
const int iconSize = contextIconSizes.value(action);
|
|
q->setIconDimensions(iconSize);
|
|
}
|
|
}
|
|
|
|
void KToolBar::Private::slotLockToolBars(bool lock)
|
|
{
|
|
q->setToolBarsLocked(lock);
|
|
}
|
|
|
|
|
|
|
|
KToolBar::KToolBar(QWidget *parent, bool isMainToolBar, bool readConfig)
|
|
: QToolBar(parent),
|
|
d(new Private(this))
|
|
{
|
|
d->init(readConfig, isMainToolBar);
|
|
|
|
// KToolBar is auto-added to the top area of the main window if parent is a QMainWindow
|
|
if (QMainWindow* mw = qobject_cast<QMainWindow*>(parent))
|
|
mw->addToolBar(this);
|
|
}
|
|
|
|
KToolBar::KToolBar(const QString& objectName, QWidget *parent, bool readConfig)
|
|
: QToolBar(parent),
|
|
d(new Private(this))
|
|
{
|
|
setObjectName(objectName);
|
|
// mainToolBar -> isMainToolBar = true -> buttonStyle is configurable
|
|
// others -> isMainToolBar = false -> ### hardcoded default for buttonStyle !!! should be configurable? -> hidden key added
|
|
d->init(readConfig, objectName == "mainToolBar");
|
|
|
|
// KToolBar is auto-added to the top area of the main window if parent is a QMainWindow
|
|
if (QMainWindow* mw = qobject_cast<QMainWindow*>(parent))
|
|
mw->addToolBar(this);
|
|
}
|
|
|
|
KToolBar::KToolBar(const QString& objectName, QMainWindow* parent, Qt::ToolBarArea area,
|
|
bool newLine, bool isMainToolBar, bool readConfig)
|
|
: QToolBar(parent),
|
|
d(new Private(this))
|
|
{
|
|
setObjectName(objectName);
|
|
d->init(readConfig, isMainToolBar);
|
|
|
|
if (newLine)
|
|
mainWindow()->addToolBarBreak(area);
|
|
|
|
mainWindow()->addToolBar(area, this);
|
|
|
|
if (newLine)
|
|
mainWindow()->addToolBarBreak(area);
|
|
}
|
|
|
|
KToolBar::~KToolBar()
|
|
{
|
|
delete d->contextLockAction;
|
|
delete d;
|
|
}
|
|
|
|
#ifndef KDE_NO_DEPRECATED
|
|
void KToolBar::setContextMenuEnabled(bool enable)
|
|
{
|
|
d->enableContext = enable;
|
|
}
|
|
#endif
|
|
|
|
#ifndef KDE_NO_DEPRECATED
|
|
bool KToolBar::contextMenuEnabled() const
|
|
{
|
|
return d->enableContext;
|
|
}
|
|
#endif
|
|
|
|
void KToolBar::saveSettings(KConfigGroup &cg)
|
|
{
|
|
Q_ASSERT(!cg.name().isEmpty());
|
|
|
|
if (cg.hasKey("Hidden")) {
|
|
cg.deleteEntry("Hidden"); // remove old key to avoid bugs from the compat code in applySettings. KDE5: remove.
|
|
}
|
|
|
|
const int currentIconSize = iconSize().width();
|
|
//kDebug() << objectName() << currentIconSize << d->iconSizeSettings.toString() << "defaultValue=" << d->iconSizeSettings.defaultValue();
|
|
if (!cg.hasDefault("IconSize") && currentIconSize == d->iconSizeSettings.defaultValue()) {
|
|
cg.revertToDefault("IconSize");
|
|
d->iconSizeSettings[Level_UserSettings] = Unset;
|
|
} else {
|
|
cg.writeEntry("IconSize", currentIconSize);
|
|
d->iconSizeSettings[Level_UserSettings] = currentIconSize;
|
|
}
|
|
|
|
const Qt::ToolButtonStyle currentToolButtonStyle = toolButtonStyle();
|
|
if (!cg.hasDefault("ToolButtonStyle") && currentToolButtonStyle == d->toolButtonStyleSettings.defaultValue()) {
|
|
cg.revertToDefault("ToolButtonStyle");
|
|
d->toolButtonStyleSettings[Level_UserSettings] = Unset;
|
|
} else {
|
|
cg.writeEntry("ToolButtonStyle", d->toolButtonStyleToString(currentToolButtonStyle));
|
|
d->toolButtonStyleSettings[Level_UserSettings] = currentToolButtonStyle;
|
|
}
|
|
}
|
|
|
|
#ifndef KDE_NO_DEPRECATED
|
|
void KToolBar::setXMLGUIClient(KXMLGUIClient *client)
|
|
{
|
|
d->xmlguiClients.clear();
|
|
d->xmlguiClients << client;
|
|
}
|
|
#endif
|
|
|
|
void KToolBar::addXMLGUIClient( KXMLGUIClient *client )
|
|
{
|
|
d->xmlguiClients << client;
|
|
}
|
|
|
|
void KToolBar::removeXMLGUIClient( KXMLGUIClient *client )
|
|
{
|
|
d->xmlguiClients.remove(client);
|
|
}
|
|
|
|
void KToolBar::contextMenuEvent(QContextMenuEvent* event)
|
|
{
|
|
#ifndef KDE_NO_DEPRECATED
|
|
if (mainWindow() && d->enableContext) {
|
|
QPointer<KToolBar> guard(this);
|
|
const QPoint globalPos = event->globalPos();
|
|
d->contextMenu(globalPos)->exec(globalPos);
|
|
|
|
// "Configure Toolbars" recreates toolbars, so we might not exist anymore.
|
|
if (guard) {
|
|
d->slotContextAboutToHide();
|
|
}
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
QToolBar::contextMenuEvent(event);
|
|
}
|
|
|
|
Qt::ToolButtonStyle KToolBar::toolButtonStyleSetting()
|
|
{
|
|
KConfigGroup group(KGlobal::config(), "Toolbar style");
|
|
const QString fallback = Private::toolButtonStyleToString(Qt::ToolButtonTextBesideIcon);
|
|
return KToolBar::Private::toolButtonStyleFromString(group.readEntry("ToolButtonStyle", fallback));
|
|
}
|
|
|
|
void KToolBar::loadState(const QDomElement &element)
|
|
{
|
|
QMainWindow *mw = mainWindow();
|
|
if (!mw)
|
|
return;
|
|
|
|
{
|
|
QDomNode textNode = element.namedItem("text");
|
|
QByteArray text;
|
|
QByteArray context;
|
|
if (textNode.isElement())
|
|
{
|
|
QDomElement textElement = textNode.toElement();
|
|
text = textElement.text().toUtf8();
|
|
context = textElement.attribute("context").toUtf8();
|
|
}
|
|
else
|
|
{
|
|
textNode = element.namedItem("Text");
|
|
if (textNode.isElement())
|
|
{
|
|
QDomElement textElement = textNode.toElement();
|
|
text = textElement.text().toUtf8();
|
|
context = textElement.attribute("context").toUtf8();
|
|
}
|
|
}
|
|
|
|
QString i18nText;
|
|
if (!text.isEmpty() && !context.isEmpty())
|
|
i18nText = i18nc(context, text);
|
|
else if (!text.isEmpty())
|
|
i18nText = i18n(text);
|
|
|
|
if (!i18nText.isEmpty())
|
|
setWindowTitle(i18nText);
|
|
}
|
|
|
|
/*
|
|
This method is called in order to load toolbar settings from XML.
|
|
However this can be used in two rather different cases:
|
|
- for the initial loading of the app's XML. In that case the settings
|
|
are only the defaults (Level_AppXML), the user's KConfig settings will override them
|
|
|
|
- for later re-loading when switching between parts in KXMLGUIFactory.
|
|
In that case the XML contains the final settings, not the defaults.
|
|
We do need the defaults, and the toolbar might have been completely
|
|
deleted and recreated meanwhile. So we store the app-default settings
|
|
into the XML.
|
|
*/
|
|
bool loadingAppDefaults = true;
|
|
if (element.hasAttribute("tempXml")) {
|
|
// this isn't the first time, so the app-xml defaults have been saved into the (in-memory) XML
|
|
loadingAppDefaults = false;
|
|
const QString iconSizeDefault = element.attribute("iconSizeDefault");
|
|
if (!iconSizeDefault.isEmpty()) {
|
|
d->iconSizeSettings[Level_AppXML] = iconSizeDefault.toInt();
|
|
}
|
|
const QString toolButtonStyleDefault = element.attribute("toolButtonStyleDefault");
|
|
if (!toolButtonStyleDefault.isEmpty()) {
|
|
d->toolButtonStyleSettings[Level_AppXML] = d->toolButtonStyleFromString(toolButtonStyleDefault);
|
|
}
|
|
} else {
|
|
// loading app defaults
|
|
bool newLine = false;
|
|
QString attrNewLine = element.attribute("newline").toLower();
|
|
if (!attrNewLine.isEmpty())
|
|
newLine = attrNewLine == "true";
|
|
if (newLine && mw)
|
|
mw->insertToolBarBreak(this);
|
|
}
|
|
|
|
int newIconSize = -1;
|
|
if (element.hasAttribute("iconSize")) {
|
|
bool ok;
|
|
newIconSize = element.attribute("iconSize").trimmed().toInt(&ok);
|
|
if (!ok)
|
|
newIconSize = -1;
|
|
}
|
|
if (newIconSize != -1)
|
|
d->iconSizeSettings[loadingAppDefaults ? Level_AppXML : Level_UserSettings] = newIconSize;
|
|
|
|
const QString newToolButtonStyle = element.attribute("iconText");
|
|
if (!newToolButtonStyle.isEmpty())
|
|
d->toolButtonStyleSettings[loadingAppDefaults ? Level_AppXML : Level_UserSettings] = d->toolButtonStyleFromString(newToolButtonStyle);
|
|
|
|
bool hidden = false;
|
|
{
|
|
QString attrHidden = element.attribute("hidden").toLower();
|
|
if (!attrHidden.isEmpty())
|
|
hidden = attrHidden == "true";
|
|
}
|
|
|
|
Qt::ToolBarArea pos = Qt::NoToolBarArea;
|
|
{
|
|
QString attrPosition = element.attribute("position").toLower();
|
|
if (!attrPosition.isEmpty())
|
|
pos = KToolBar::Private::positionFromString(attrPosition);
|
|
}
|
|
if (pos != Qt::NoToolBarArea)
|
|
mw->addToolBar(pos, this);
|
|
|
|
setVisible(!hidden);
|
|
|
|
d->applyCurrentSettings();
|
|
}
|
|
|
|
// Called when switching between xmlgui clients, in order to find any unsaved settings
|
|
// again when switching back to the current xmlgui client.
|
|
void KToolBar::saveState(QDomElement ¤t) const
|
|
{
|
|
Q_ASSERT(!current.isNull());
|
|
|
|
current.setAttribute("tempXml", "true");
|
|
|
|
current.setAttribute("noMerge", "1");
|
|
current.setAttribute("position", d->getPositionAsString().toLower());
|
|
current.setAttribute("hidden", isHidden() ? "true" : "false");
|
|
|
|
const int currentIconSize = iconSize().width();
|
|
if (currentIconSize == d->iconSizeSettings.defaultValue())
|
|
current.removeAttribute("iconSize");
|
|
else
|
|
current.setAttribute("iconSize", iconSize().width());
|
|
|
|
if (toolButtonStyle() == d->toolButtonStyleSettings.defaultValue())
|
|
current.removeAttribute("iconText");
|
|
else
|
|
current.setAttribute("iconText", d->toolButtonStyleToString(toolButtonStyle()));
|
|
|
|
// Note: if this method is used by more than KXMLGUIBuilder, e.g. to save XML settings to *disk*,
|
|
// then the stuff below shouldn't always be done. This is not the case currently though.
|
|
if (d->iconSizeSettings[Level_AppXML] != Unset) {
|
|
current.setAttribute("iconSizeDefault", d->iconSizeSettings[Level_AppXML]);
|
|
}
|
|
if (d->toolButtonStyleSettings[Level_AppXML] != Unset) {
|
|
const Qt::ToolButtonStyle bs = static_cast<Qt::ToolButtonStyle>(d->toolButtonStyleSettings[Level_AppXML]);
|
|
current.setAttribute("toolButtonStyleDefault", d->toolButtonStyleToString(bs));
|
|
}
|
|
}
|
|
|
|
// called by KMainWindow::applyMainWindowSettings to read from the user settings
|
|
void KToolBar::applySettings(const KConfigGroup &cg, bool forceGlobal)
|
|
{
|
|
Q_ASSERT(!cg.name().isEmpty());
|
|
Q_UNUSED(forceGlobal); // KDE5: remove
|
|
|
|
// a small leftover from kde3: separate bool for hidden/shown. But it's also part of saveMainWindowSettings,
|
|
// it is not really useful anymore, except in the unlikely case where someone would call this by hand.
|
|
// KDE5: remove the block below
|
|
if (cg.hasKey("Hidden")) {
|
|
const bool hidden = cg.readEntry("Hidden", false);
|
|
if (hidden)
|
|
hide();
|
|
else {
|
|
show();
|
|
}
|
|
}
|
|
|
|
if (cg.hasKey("IconSize")) {
|
|
d->iconSizeSettings[Level_UserSettings] = cg.readEntry("IconSize", 0);
|
|
}
|
|
if (cg.hasKey("ToolButtonStyle")) {
|
|
d->toolButtonStyleSettings[Level_UserSettings] = d->toolButtonStyleFromString(cg.readEntry("ToolButtonStyle", QString()));
|
|
}
|
|
|
|
d->applyCurrentSettings();
|
|
}
|
|
|
|
KMainWindow * KToolBar::mainWindow() const
|
|
{
|
|
return qobject_cast<KMainWindow*>(const_cast<QObject*>(parent()));
|
|
}
|
|
|
|
void KToolBar::setIconDimensions(int size)
|
|
{
|
|
QToolBar::setIconSize(QSize(size, size));
|
|
d->iconSizeSettings[Level_UserSettings] = size;
|
|
}
|
|
|
|
int KToolBar::iconSizeDefault() const
|
|
{
|
|
return KIconLoader::global()->currentSize(d->isMainToolBar ? KIconLoader::MainToolbar : KIconLoader::Toolbar);
|
|
}
|
|
|
|
void KToolBar::slotMovableChanged(bool movable)
|
|
{
|
|
if (movable && !KAuthorized::authorize("movable_toolbars"))
|
|
setMovable(false);
|
|
}
|
|
|
|
void KToolBar::dragEnterEvent(QDragEnterEvent *event)
|
|
{
|
|
if (toolBarsEditable() && event->proposedAction() & (Qt::CopyAction | Qt::MoveAction) &&
|
|
event->mimeData()->hasFormat("application/x-kde-action-list")) {
|
|
QByteArray data = event->mimeData()->data("application/x-kde-action-list");
|
|
|
|
QDataStream stream(data);
|
|
|
|
QStringList actionNames;
|
|
|
|
stream >> actionNames;
|
|
|
|
foreach (const QString& actionName, actionNames) {
|
|
foreach (KActionCollection* ac, KActionCollection::allCollections()) {
|
|
QAction* newAction = ac->action(actionName.toLatin1().constData());
|
|
if (newAction) {
|
|
d->actionsBeingDragged.append(newAction);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (d->actionsBeingDragged.count()) {
|
|
QAction* overAction = actionAt(event->pos());
|
|
|
|
QFrame* dropIndicatorWidget = new QFrame(this);
|
|
dropIndicatorWidget->resize(8, height() - 4);
|
|
dropIndicatorWidget->setFrameShape(QFrame::VLine);
|
|
dropIndicatorWidget->setLineWidth(3);
|
|
|
|
d->dropIndicatorAction = insertWidget(overAction, dropIndicatorWidget);
|
|
|
|
insertAction(overAction, d->dropIndicatorAction);
|
|
|
|
event->acceptProposedAction();
|
|
return;
|
|
}
|
|
}
|
|
|
|
QToolBar::dragEnterEvent(event);
|
|
}
|
|
|
|
void KToolBar::dragMoveEvent(QDragMoveEvent *event)
|
|
{
|
|
if (toolBarsEditable())
|
|
forever {
|
|
if (d->dropIndicatorAction) {
|
|
QAction* overAction = 0L;
|
|
foreach (QAction* action, actions()) {
|
|
// want to make it feel that half way across an action you're dropping on the other side of it
|
|
QWidget* widget = widgetForAction(action);
|
|
if (event->pos().x() < widget->pos().x() + (widget->width() / 2)) {
|
|
overAction = action;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (overAction != d->dropIndicatorAction) {
|
|
// Check to see if the indicator is already in the right spot
|
|
int dropIndicatorIndex = actions().indexOf(d->dropIndicatorAction);
|
|
if (dropIndicatorIndex + 1 < actions().count()) {
|
|
if (actions()[ dropIndicatorIndex + 1 ] == overAction)
|
|
break;
|
|
} else if (!overAction) {
|
|
break;
|
|
}
|
|
|
|
insertAction(overAction, d->dropIndicatorAction);
|
|
}
|
|
|
|
event->accept();
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
|
|
QToolBar::dragMoveEvent(event);
|
|
}
|
|
|
|
void KToolBar::dragLeaveEvent(QDragLeaveEvent *event)
|
|
{
|
|
// Want to clear this even if toolBarsEditable was changed mid-drag (unlikey)
|
|
delete d->dropIndicatorAction;
|
|
d->dropIndicatorAction = 0L;
|
|
d->actionsBeingDragged.clear();
|
|
|
|
if (toolBarsEditable()) {
|
|
event->accept();
|
|
return;
|
|
}
|
|
|
|
QToolBar::dragLeaveEvent(event);
|
|
}
|
|
|
|
void KToolBar::dropEvent(QDropEvent *event)
|
|
{
|
|
if (toolBarsEditable()) {
|
|
foreach (QAction* action, d->actionsBeingDragged) {
|
|
if (actions().contains(action))
|
|
removeAction(action);
|
|
insertAction(d->dropIndicatorAction, action);
|
|
}
|
|
}
|
|
|
|
// Want to clear this even if toolBarsEditable was changed mid-drag (unlikey)
|
|
delete d->dropIndicatorAction;
|
|
d->dropIndicatorAction = 0L;
|
|
d->actionsBeingDragged.clear();
|
|
|
|
if (toolBarsEditable()) {
|
|
event->accept();
|
|
return;
|
|
}
|
|
|
|
QToolBar::dropEvent(event);
|
|
}
|
|
|
|
void KToolBar::mousePressEvent(QMouseEvent *event)
|
|
{
|
|
if (toolBarsEditable() && event->button() == Qt::LeftButton) {
|
|
if (KAction* action = qobject_cast<KAction*>(actionAt(event->pos()))) {
|
|
d->dragAction = action;
|
|
d->dragStartPosition = event->pos();
|
|
event->accept();
|
|
return;
|
|
}
|
|
}
|
|
|
|
QToolBar::mousePressEvent(event);
|
|
}
|
|
|
|
void KToolBar::mouseMoveEvent(QMouseEvent *event)
|
|
{
|
|
if (!toolBarsEditable() || !d->dragAction)
|
|
return QToolBar::mouseMoveEvent(event);
|
|
|
|
if ((event->pos() - d->dragStartPosition).manhattanLength() < QApplication::startDragDistance()) {
|
|
event->accept();
|
|
return;
|
|
}
|
|
|
|
QDrag *drag = new QDrag(this);
|
|
QMimeData *mimeData = new QMimeData;
|
|
|
|
QByteArray data;
|
|
{
|
|
QDataStream stream(&data, QIODevice::WriteOnly);
|
|
|
|
QStringList actionNames;
|
|
actionNames << d->dragAction->objectName();
|
|
|
|
stream << actionNames;
|
|
}
|
|
|
|
mimeData->setData("application/x-kde-action-list", data);
|
|
|
|
drag->setMimeData(mimeData);
|
|
|
|
Qt::DropAction dropAction = drag->start(Qt::MoveAction);
|
|
|
|
if (dropAction == Qt::MoveAction)
|
|
// Only remove from this toolbar if it was moved to another toolbar
|
|
// Otherwise the receiver moves it.
|
|
if (drag->target() != this)
|
|
removeAction(d->dragAction);
|
|
|
|
d->dragAction = 0L;
|
|
event->accept();
|
|
}
|
|
|
|
void KToolBar::mouseReleaseEvent(QMouseEvent *event)
|
|
{
|
|
// Want to clear this even if toolBarsEditable was changed mid-drag (unlikey)
|
|
if (d->dragAction) {
|
|
d->dragAction = 0L;
|
|
event->accept();
|
|
return;
|
|
}
|
|
|
|
QToolBar::mouseReleaseEvent(event);
|
|
}
|
|
|
|
bool KToolBar::eventFilter(QObject * watched, QEvent * event)
|
|
{
|
|
// Generate context menu events for disabled buttons too...
|
|
if (event->type() == QEvent::MouseButtonPress) {
|
|
QMouseEvent* me = static_cast<QMouseEvent*>(event);
|
|
if (me->buttons() & Qt::RightButton)
|
|
if (QWidget* ww = qobject_cast<QWidget*>(watched))
|
|
if (ww->parent() == this && !ww->isEnabled())
|
|
QCoreApplication::postEvent(this, new QContextMenuEvent(QContextMenuEvent::Mouse, me->pos(), me->globalPos()));
|
|
|
|
} else if (event->type() == QEvent::ParentChange) {
|
|
// Make sure we're not leaving stale event filters around,
|
|
// when a child is reparented somewhere else
|
|
if (QWidget* ww = qobject_cast<QWidget*>(watched)) {
|
|
if (!this->isAncestorOf(ww)) {
|
|
// New parent is not a subwidget - remove event filter
|
|
ww->removeEventFilter(this);
|
|
foreach (QWidget* child, ww->findChildren<QWidget*>())
|
|
child->removeEventFilter(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
QToolButton* tb;
|
|
if ((tb = qobject_cast<QToolButton*>(watched))) {
|
|
const QList<QAction*> tbActions = tb->actions();
|
|
if (!tbActions.isEmpty()) {
|
|
// Handle MMB on toolbar buttons
|
|
if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease) {
|
|
QMouseEvent* me = static_cast<QMouseEvent*>(event);
|
|
if (me->button() == Qt::MidButton /*&&
|
|
act->receivers(SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)))*/) {
|
|
QAction* act = tbActions.first();
|
|
if (me->type() == QEvent::MouseButtonPress)
|
|
tb->setDown(act->isEnabled());
|
|
else {
|
|
tb->setDown(false);
|
|
if (act->isEnabled()) {
|
|
QMetaObject::invokeMethod(act, "triggered", Qt::DirectConnection,
|
|
Q_ARG(Qt::MouseButtons, me->button()),
|
|
Q_ARG(Qt::KeyboardModifiers, QApplication::keyboardModifiers()));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// CJK languages use more verbose accelerator marker: they add a Latin
|
|
// letter in parenthesis, and put accelerator on that. Hence, the default
|
|
// removal of ampersand only may not be enough there, instead the whole
|
|
// parenthesis construct should be removed. Use KLocale's method to do this.
|
|
if (event->type() == QEvent::Show || event->type() == QEvent::Paint || event->type() == QEvent::EnabledChange) {
|
|
QAction *act = tb->defaultAction();
|
|
if (act) {
|
|
const QString text = KGlobal::locale()->removeAcceleratorMarker(act->iconText().isEmpty() ? act->text() : act->iconText());
|
|
const QString toolTip = KGlobal::locale()->removeAcceleratorMarker(act->toolTip());
|
|
// Filtering messages requested by translators (scripting).
|
|
tb->setText(i18nc("@action:intoolbar Text label of toolbar button", "%1", text));
|
|
tb->setToolTip(i18nc("@info:tooltip Tooltip of toolbar button", "%1", toolTip));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Redirect mouse events to the toolbar when drag + drop editing is enabled
|
|
if (toolBarsEditable()) {
|
|
if (QWidget* ww = qobject_cast<QWidget*>(watched)) {
|
|
switch (event->type()) {
|
|
case QEvent::MouseButtonPress: {
|
|
QMouseEvent* me = static_cast<QMouseEvent*>(event);
|
|
QMouseEvent newEvent(me->type(), mapFromGlobal(ww->mapToGlobal(me->pos())), me->globalPos(),
|
|
me->button(), me->buttons(), me->modifiers());
|
|
mousePressEvent(&newEvent);
|
|
return true;
|
|
}
|
|
case QEvent::MouseMove: {
|
|
QMouseEvent* me = static_cast<QMouseEvent*>(event);
|
|
QMouseEvent newEvent(me->type(), mapFromGlobal(ww->mapToGlobal(me->pos())), me->globalPos(),
|
|
me->button(), me->buttons(), me->modifiers());
|
|
mouseMoveEvent(&newEvent);
|
|
return true;
|
|
}
|
|
case QEvent::MouseButtonRelease: {
|
|
QMouseEvent* me = static_cast<QMouseEvent*>(event);
|
|
QMouseEvent newEvent(me->type(), mapFromGlobal(ww->mapToGlobal(me->pos())), me->globalPos(),
|
|
me->button(), me->buttons(), me->modifiers());
|
|
mouseReleaseEvent(&newEvent);
|
|
return true;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return QToolBar::eventFilter(watched, event);
|
|
}
|
|
|
|
void KToolBar::actionEvent(QActionEvent * event)
|
|
{
|
|
if (event->type() == QEvent::ActionRemoved) {
|
|
QWidget* widget = widgetForAction(event->action());
|
|
if (widget) {
|
|
widget->removeEventFilter(this);
|
|
|
|
foreach (QWidget* child, widget->findChildren<QWidget*>())
|
|
child->removeEventFilter(this);
|
|
}
|
|
}
|
|
|
|
QToolBar::actionEvent(event);
|
|
|
|
if (event->type() == QEvent::ActionAdded) {
|
|
QWidget* widget = widgetForAction(event->action());
|
|
if (widget) {
|
|
widget->installEventFilter(this);
|
|
|
|
foreach (QWidget* child, widget->findChildren<QWidget*>())
|
|
child->installEventFilter(this);
|
|
// Center widgets that do not have any use for more space. See bug 165274
|
|
if (!(widget->sizePolicy().horizontalPolicy() & QSizePolicy::GrowFlag)
|
|
// ... but do not center when using text besides icon in vertical toolbar. See bug 243196
|
|
&& !(orientation() == Qt::Vertical && toolButtonStyle() == Qt::ToolButtonTextBesideIcon)) {
|
|
const int index = layout()->indexOf(widget);
|
|
if (index != -1) {
|
|
layout()->itemAt(index)->setAlignment(Qt::AlignJustify);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
d->adjustSeparatorVisibility();
|
|
}
|
|
|
|
bool KToolBar::toolBarsEditable()
|
|
{
|
|
return KToolBar::Private::s_editable;
|
|
}
|
|
|
|
void KToolBar::setToolBarsEditable(bool editable)
|
|
{
|
|
if (KToolBar::Private::s_editable != editable) {
|
|
KToolBar::Private::s_editable = editable;
|
|
}
|
|
}
|
|
|
|
void KToolBar::setToolBarsLocked(bool locked)
|
|
{
|
|
if (KToolBar::Private::s_locked != locked) {
|
|
KToolBar::Private::s_locked = locked;
|
|
|
|
foreach (KMainWindow* mw, KMainWindow::memberList()) {
|
|
foreach (KToolBar* toolbar, mw->findChildren<KToolBar*>()) {
|
|
toolbar->d->setLocked(locked);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool KToolBar::toolBarsLocked()
|
|
{
|
|
return KToolBar::Private::s_locked;
|
|
}
|
|
|
|
#include "ktoolbar.moc"
|