File indexing completed on 2024-04-14 14:20:24

0001 /* This file is part of the KDE libraries
0002     Copyright (C) 2000 Carsten Pfeiffer <pfeiffer@kde.org>
0003 
0004     This library is free software; you can redistribute it and/or
0005     modify it under the terms of the GNU Library General Public
0006     License as published by the Free Software Foundation; either
0007     version 2 of the License, or (at your option) any later version.
0008 
0009     This library is distributed in the hope that it will be useful,
0010     but WITHOUT ANY WARRANTY; without even the implied warranty of
0011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012     Library General Public License for more details.
0013 
0014     You should have received a copy of the GNU Library General Public License
0015     along with this library; see the file COPYING.LIB.  If not, write to
0016     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017     Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #include "kpushbutton.h"
0021 #include <QStyleOptionToolButton>
0022 #include <QStylePainter>
0023 
0024 #include <QDrag>
0025 #include <QActionEvent>
0026 #include <QMenu>
0027 #include <QPointer>
0028 #include <QStyle>
0029 #include <QTimer>
0030 #include <QApplication>
0031 
0032 #include <kguiitem.h>
0033 
0034 #include <kauth/objectdecorator.h>
0035 
0036 class Q_DECL_HIDDEN KPushButton::KPushButtonPrivate
0037 {
0038 public:
0039     KPushButtonPrivate(KPushButton *_parent) : parent(_parent), m_dragEnabled(false), decorator(nullptr)
0040     {
0041     }
0042 
0043     KPushButton *parent;
0044 
0045     KStandardGuiItem::StandardItem itemType;
0046     QPointer<QMenu> delayedMenu;
0047     QTimer *delayedMenuTimer;
0048     bool m_dragEnabled;
0049     QPoint startPos;
0050     KAuth::ObjectDecorator *decorator;
0051 
0052     void slotPressedInternal();
0053     void slotClickedInternal();
0054     void authStatusChanged(KAuth::Action::AuthStatus status);
0055     void slotDelayedMenuTimeout();
0056 };
0057 
0058 void KPushButton::KPushButtonPrivate::slotPressedInternal()
0059 {
0060     if (!delayedMenu.isNull()) {
0061         if (delayedMenuTimer == nullptr) {
0062             delayedMenuTimer = new QTimer(parent);
0063             delayedMenuTimer->setSingleShot(true);
0064             connect(delayedMenuTimer, SIGNAL(timeout()), parent, SLOT(slotDelayedMenuTimeout()));
0065         }
0066         const int delay = parent->style()->styleHint(QStyle::SH_ToolButton_PopupDelay, nullptr, parent);
0067         delayedMenuTimer->start((delay <= 0) ? 150 : delay);
0068     }
0069 }
0070 
0071 void KPushButton::KPushButtonPrivate::slotClickedInternal()
0072 {
0073     if (delayedMenuTimer) {
0074         delayedMenuTimer->stop();
0075     }
0076 }
0077 
0078 void KPushButton::KPushButtonPrivate::slotDelayedMenuTimeout()
0079 {
0080     delayedMenuTimer->stop();
0081     if (!delayedMenu.isNull()) {
0082         parent->setMenu(delayedMenu);
0083         parent->showMenu();
0084         parent->setMenu(nullptr);
0085     }
0086 }
0087 
0088 KPushButton::KPushButton(QWidget *parent)
0089     : QPushButton(parent), d(new KPushButtonPrivate(this))
0090 {
0091     initWidget(KGuiItem(""));
0092 }
0093 
0094 KPushButton::KPushButton(const QString &text, QWidget *parent)
0095     : QPushButton(parent), d(new KPushButtonPrivate(this))
0096 {
0097     initWidget(KGuiItem(text));
0098 }
0099 
0100 KPushButton::KPushButton(const QIcon &icon, const QString &text,
0101                          QWidget *parent)
0102     : QPushButton(text, parent), d(new KPushButtonPrivate(this))
0103 {
0104     initWidget(KGuiItem(text, icon));
0105 }
0106 
0107 KPushButton::KPushButton(const KGuiItem &item, QWidget *parent)
0108     : QPushButton(parent), d(new KPushButtonPrivate(this))
0109 {
0110     initWidget(item);
0111 }
0112 
0113 KPushButton::~KPushButton()
0114 {
0115     delete d;
0116 }
0117 
0118 void KPushButton::initWidget(const KGuiItem &item)
0119 {
0120     d->decorator = new KAuth::ObjectDecorator(this);
0121     connect(d->decorator, SIGNAL(authorized(KAuth::Action)),
0122             this, SIGNAL(authorized(KAuth::Action)));
0123 
0124     d->itemType = (KStandardGuiItem::StandardItem) 0;
0125     d->delayedMenuTimer = nullptr;
0126 
0127     connect(this, SIGNAL(pressed()), this, SLOT(slotPressedInternal()));
0128     connect(this, SIGNAL(clicked()), this, SLOT(slotClickedInternal()));
0129     KGuiItem::assign(this, item);
0130 }
0131 
0132 bool KPushButton::isDragEnabled() const
0133 {
0134     return d->m_dragEnabled;
0135 }
0136 
0137 void KPushButton::setGuiItem(const KGuiItem &item)
0138 {
0139     KGuiItem::assign(this, item);
0140 }
0141 
0142 void KPushButton::setGuiItem(KStandardGuiItem::StandardItem item)
0143 {
0144     setGuiItem(KStandardGuiItem::guiItem(item));
0145     d->itemType = item;
0146 }
0147 
0148 KStandardGuiItem::StandardItem KPushButton::guiItem() const
0149 {
0150     return d->itemType;
0151 }
0152 
0153 void KPushButton::setText(const QString &text)
0154 {
0155     QPushButton::setText(text);
0156 }
0157 
0158 void KPushButton::setIcon(const QIcon &icon)
0159 {
0160     const bool useIcons = style()->styleHint(QStyle::SH_DialogButtonBox_ButtonsHaveIcons, nullptr, this);
0161     if (useIcons || text().isEmpty()) {
0162         QPushButton::setIcon(icon);
0163     } else {
0164         QPushButton::setIcon(QIcon());
0165     }
0166 }
0167 
0168 void KPushButton::setDragEnabled(bool enable)
0169 {
0170     d->m_dragEnabled = enable;
0171 }
0172 
0173 void KPushButton::mousePressEvent(QMouseEvent *e)
0174 {
0175     if (d->m_dragEnabled) {
0176         d->startPos = e->pos();
0177     }
0178     QPushButton::mousePressEvent(e);
0179 }
0180 
0181 void KPushButton::mouseMoveEvent(QMouseEvent *e)
0182 {
0183     if (!d->m_dragEnabled) {
0184         QPushButton::mouseMoveEvent(e);
0185         return;
0186     }
0187 
0188     if ((e->buttons() & Qt::LeftButton) &&
0189             (e->pos() - d->startPos).manhattanLength() >
0190             QApplication::startDragDistance()) {
0191         startDrag();
0192         setDown(false);
0193     }
0194 }
0195 
0196 QDrag *KPushButton::dragObject()
0197 {
0198     return nullptr;
0199 }
0200 
0201 void KPushButton::startDrag()
0202 {
0203     QDrag *d = dragObject();
0204     if (d) {
0205         d->start();
0206     }
0207 }
0208 
0209 void KPushButton::setDelayedMenu(QMenu *delayedMenu)
0210 {
0211     d->delayedMenu = delayedMenu;
0212 }
0213 
0214 QMenu *KPushButton::delayedMenu()
0215 {
0216     return d->delayedMenu;
0217 }
0218 
0219 KAuth::Action KPushButton::authAction() const
0220 {
0221     return d->decorator->authAction();
0222 }
0223 
0224 void KPushButton::setAuthAction(const QString &actionName)
0225 {
0226     d->decorator->setAuthAction(actionName);
0227 }
0228 
0229 void KPushButton::setAuthAction(const KAuth::Action &action)
0230 {
0231     d->decorator->setAuthAction(action);
0232 }
0233 
0234 QSize KPushButton::sizeHint() const
0235 {
0236     const bool tempSetMenu = !menu() && d->delayedMenu;
0237     if (tempSetMenu) {
0238         const_cast<KPushButton *>(this)->setMenu(d->delayedMenu);
0239     }
0240     const QSize sz = QPushButton::sizeHint();
0241     if (tempSetMenu) {
0242         const_cast<KPushButton *>(this)->setMenu(nullptr);
0243     }
0244     return sz;
0245 }
0246 
0247 void KPushButton::paintEvent(QPaintEvent *)
0248 {
0249     QStylePainter p(this);
0250     QStyleOptionButton option;
0251     initStyleOption(&option);
0252 
0253     if (d->delayedMenu) {
0254         option.features |= QStyleOptionButton::HasMenu;
0255     }
0256 
0257     p.drawControl(QStyle::CE_PushButton, option);
0258 }
0259 
0260 #include "moc_kpushbutton.cpp"