File indexing completed on 2024-04-28 04:37:32

0001 /*
0002     SPDX-FileCopyrightText: 2007 Roberto Raggi <roberto@kdevelop.org>
0003     SPDX-FileCopyrightText: 2007 Hamish Rodda <rodda@kde.org>
0004     SPDX-FileCopyrightText: 2011 Alexander Dymo <adymo@kdevelop.org>
0005     SPDX-FileCopyrightText: 2018 Amish Naidu <amhndu@gmail.com>
0006 
0007     SPDX-License-Identifier: LicenseRef-MIT-KDevelop-Ideal
0008 */
0009 
0010 #include "idealtoolbutton.h"
0011 #include <KAcceleratorManager>
0012 #include <QStyleOption>
0013 #include <QStylePainter>
0014 #include <QApplication>
0015 
0016 IdealToolButton::IdealToolButton(Qt::DockWidgetArea area, QWidget *parent)
0017     : QToolButton(parent), _area(area)
0018 {
0019     setFocusPolicy(Qt::NoFocus);
0020     KAcceleratorManager::setNoAccel(this);
0021     setCheckable(true);
0022     setAutoRaise(true);
0023     setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
0024 
0025     setContextMenuPolicy(Qt::CustomContextMenu);
0026 
0027     QSizePolicy sizePolicy = this->sizePolicy();
0028     if (orientation() == Qt::Horizontal) {
0029         sizePolicy.setHorizontalPolicy(QSizePolicy::Maximum);
0030     } else {
0031         sizePolicy.setVerticalPolicy(QSizePolicy::Maximum);
0032     }
0033     setSizePolicy(sizePolicy);
0034 }
0035 
0036 Qt::Orientation IdealToolButton::orientation() const
0037 {
0038     if (_area == Qt::LeftDockWidgetArea || _area == Qt::RightDockWidgetArea)
0039         return Qt::Vertical;
0040 
0041     return Qt::Horizontal;
0042 }
0043 
0044 QSize IdealToolButton::sizeHint() const
0045 {
0046     ensurePolished();
0047 
0048     QStyleOptionToolButton opt;
0049     initStyleOption(&opt);
0050 
0051     QFontMetrics fm = fontMetrics();
0052 
0053     const int charWidth = fm.horizontalAdvance(QLatin1Char('x'));
0054     QSize textSize;
0055     // Use text size only if we request text
0056     if (toolButtonStyle() != Qt::ToolButtonIconOnly || opt.icon.isNull()) {
0057         textSize = fm.size(Qt::TextShowMnemonic, opt.text);
0058         textSize.rwidth() += 2 * charWidth;
0059     }
0060 
0061     int iconwidth = 0, iconheight = 0;
0062     // Use icon size only if it's requested and the icon is valid
0063     if (toolButtonStyle() != Qt::ToolButtonTextOnly && !opt.icon.isNull()) {
0064         if (_area == Qt::TopDockWidgetArea || _area == Qt::BottomDockWidgetArea) {
0065             iconwidth = opt.iconSize.width();
0066             iconheight = opt.iconSize.height();
0067         } else {
0068             iconwidth = opt.iconSize.height();
0069             iconheight = opt.iconSize.width();
0070         }
0071     }
0072     // adding +4 to be consistent with qtoolbutton
0073     int width = textSize.width() + iconwidth + 4;
0074     int height = qMax(textSize.height(), iconheight);
0075     QSize size = style()->sizeFromContents(QStyle::CT_ToolButton, &opt, QSize(width, height), this);
0076 
0077     if (orientation() == Qt::Vertical) {
0078         return QSize(size.height(), size.width()); // transposed
0079     } else {
0080         return size;
0081     }
0082 }
0083 
0084 QSize IdealToolButton::minimumSizeHint() const
0085 {
0086     ensurePolished();
0087 
0088     QStyleOptionToolButton opt;
0089     initStyleOption(&opt);
0090 
0091     QSize minimumSize;
0092     // if style has icons, minimumSize is the size of the icon
0093     if (toolButtonStyle() != Qt::ToolButtonTextOnly && !opt.icon.isNull()) {
0094         minimumSize = opt.iconSize;
0095         if (_area == Qt::LeftDockWidgetArea || _area == Qt::RightDockWidgetArea) {
0096             minimumSize.transpose();
0097         }
0098     } else {
0099         // if no icon, set an arbitrary minimum size
0100         QFontMetrics fm = fontMetrics();
0101         minimumSize = fm.size(Qt::TextShowMnemonic, opt.text.left(4));
0102     }
0103 
0104     minimumSize = style()->sizeFromContents(QStyle::CT_ToolButton, &opt, minimumSize, this);
0105 
0106     if (_area == Qt::TopDockWidgetArea || _area == Qt::BottomDockWidgetArea) {
0107         return minimumSize;
0108     }
0109     return minimumSize.transposed();
0110 }
0111 
0112 
0113 void IdealToolButton::paintEvent(QPaintEvent *event)
0114 {
0115     Q_UNUSED(event);
0116 
0117     QStylePainter painter(this);
0118     QStyleOptionToolButton option;
0119     initStyleOption(&option);
0120 
0121     if (_area == Qt::TopDockWidgetArea || _area == Qt::BottomDockWidgetArea) {
0122         // elide text
0123         int iconWidth = 0;
0124         if (toolButtonStyle() != Qt::ToolButtonTextOnly && !option.icon.isNull()) {
0125             iconWidth = option.iconSize.width();
0126         }
0127 
0128         // subtract 4 to be consistent with the size calculated by sizeHint, which adds 4,
0129         // again to be consistent with QToolButton
0130         option.text = fontMetrics().elidedText(text(), Qt::ElideRight, contentsRect().width() - iconWidth - 4);
0131         painter.drawComplexControl(QStyle::CC_ToolButton, option);
0132     } else {
0133         // rotated paint
0134         // elide text
0135         int iconHeight = 0;
0136         if (toolButtonStyle() != Qt::ToolButtonTextOnly && !option.icon.isNull()) {
0137             iconHeight = option.iconSize.height();
0138         }
0139         QString textToDraw = fontMetrics().elidedText(text(), Qt::ElideRight, contentsRect().height() - iconHeight - 4);
0140         // first draw normal frame and not text/icon
0141         option.text = QString();
0142         option.icon = QIcon();
0143         painter.drawComplexControl(QStyle::CC_ToolButton, option);
0144 
0145         // rotate the options
0146         QSize size( option.rect.size() );
0147         size.transpose();
0148         option.rect.setSize( size );
0149 
0150         // rotate the painter
0151         if(_area == Qt::LeftDockWidgetArea) {
0152             painter.translate( 0, height() );
0153             painter.rotate( -90 );
0154         } else {
0155             painter.translate( width(), 0 );
0156             painter.rotate( 90 );
0157         }
0158 
0159         // paint text and icon
0160         option.text = textToDraw;
0161 
0162         QIcon::Mode iconMode = (option.state & QStyle::State_MouseOver) ? QIcon::Active : QIcon::Normal;
0163         QPixmap ic = icon().pixmap(option.iconSize, iconMode, QIcon::On);
0164         QTransform tf;
0165         if(_area == Qt::LeftDockWidgetArea) {
0166             tf.rotate(90);
0167         } else {
0168             tf.rotate(-90);
0169         }
0170         option.icon = ic.transformed( tf, Qt::SmoothTransformation );
0171         painter.drawControl(QStyle::CE_ToolButtonLabel, option);
0172         painter.end();
0173     }
0174 }
0175 
0176 #include "moc_idealtoolbutton.cpp"