1 /* This file is part of the KDE libraries
2    Copyright (C) 2007 Aurélien Gâteau <agateau@kde.org>
3    Copyright (C) 2012 Jean-Nicolas Artaud <jeannicolasartaud@gmail.com>
4    Copyright (C) 2012-2016 Jarosław Staniek <staniek@kde.org>
5 
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public
8    License version 2 as published by the Free Software Foundation.
9 
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14 
15    You should have received a copy of the GNU Library General Public License
16    along with this library; see the file COPYING.LIB.  If not, write to
17    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18    Boston, MA 02110-1301, USA.
19 */
20 
21 #include "KexiGroupButton.h"
22 
23 // Qt
24 #include <QAction>
25 #include <QStyleOptionToolButton>
26 #include <QStylePainter>
27 #include <QToolButton>
28 
29 // KF5
30 #include <KLocalizedString>
31 
32 class Q_DECL_HIDDEN KexiGroupButton::Private
33 {
34 public:
Private(KexiGroupButton * qq,const GroupPosition position)35     Private(KexiGroupButton *qq, const GroupPosition position) : groupPosition(position)
36     {
37         // Make the policy closer to QPushButton's default but horizontal shouldn't be Fixed,
38         // otherwise spacing gets broken
39         qq->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
40     }
41     GroupPosition groupPosition;
42 };
43 
KexiGroupButton(GroupPosition position,QWidget * parent)44 KexiGroupButton::KexiGroupButton(GroupPosition position, QWidget* parent)
45  : QToolButton(parent), d(new Private(this, position))
46 {
47 }
48 
KexiGroupButton(QWidget * parent)49 KexiGroupButton::KexiGroupButton(QWidget* parent)
50  : QToolButton(parent), d(new Private(this, NoGroup))
51 {
52 }
53 
~KexiGroupButton()54 KexiGroupButton::~KexiGroupButton()
55 {
56     delete d;
57 }
58 
setGroupPosition(KexiGroupButton::GroupPosition groupPosition)59 void KexiGroupButton::setGroupPosition(KexiGroupButton::GroupPosition groupPosition)
60 {
61     d->groupPosition = groupPosition;
62 }
63 
groupPosition() const64 KexiGroupButton::GroupPosition KexiGroupButton::groupPosition() const
65 {
66     return d->groupPosition;
67 }
68 
paintEvent(QPaintEvent * event)69 void KexiGroupButton::paintEvent(QPaintEvent* event)
70 {
71     if (groupPosition() == NoGroup) {
72         QToolButton::paintEvent(event);
73         return;
74     }
75     QStylePainter painter(this);
76     QStyleOptionToolButton opt;
77     initStyleOption(&opt);
78     QStyleOptionToolButton panelOpt = opt;
79     panelOpt.state |= QStyle::State_MouseOver; // force border
80 
81     // Panel
82     QRect& panelRect = panelOpt.rect;
83     switch (groupPosition()) {
84     case GroupLeft:
85         panelRect.setWidth(panelRect.width() * 2);
86         break;
87     case GroupCenter:
88         panelRect.setLeft(panelRect.left() - panelRect.width());
89         panelRect.setWidth(panelRect.width() * 3);
90         break;
91     case GroupRight:
92         panelRect.setLeft(panelRect.left() - panelRect.width());
93         break;
94     case NoGroup:
95         Q_ASSERT(0);
96     }
97     if (autoRaise()) {
98         if (!isChecked() && !isDown() && !(panelOpt.state & QStyle::State_MouseOver)) {
99             // Use 'pushed' appearance for all buttons, but those that are not really pushed
100             // are drawn with less contrast and are toned down.
101             panelOpt.state |= (QStyle::State_On | QStyle::State_Sunken);
102             QPalette panelPal(panelOpt.palette);
103             QColor c;
104             c = panelPal.color(QPalette::Button);
105             c.setAlpha(50);
106             panelPal.setColor(QPalette::Button, c);
107             c = panelPal.color(QPalette::Window);
108             c.setAlpha(50);
109             panelPal.setColor(QPalette::Window, c);
110             panelOpt.palette = panelPal;
111             painter.setOpacity(0.5);
112         }
113     }
114     painter.drawPrimitive(QStyle::PE_PanelButtonTool, panelOpt);
115     painter.setOpacity(1.0);
116 
117     // Separator
118     //! @todo make specific fixes for styles such as Plastique, Cleanlooks if there's practical no alernative
119     const int y1 = opt.rect.top() + 1;
120     const int y2 = opt.rect.bottom() - 1;
121     painter.setOpacity(0.4);
122     if (d->groupPosition != GroupRight) {
123         const int x = opt.rect.right();
124         painter.setPen(opt.palette.color(QPalette::Dark));
125         painter.drawLine(x, y1, x, y2);
126     }
127     painter.setOpacity(1.0);
128 
129     // Text
130     painter.drawControl(QStyle::CE_ToolButtonLabel, opt);
131 
132     // Filtering message on tooltip text for CJK to remove accelerators.
133     // Quoting ktoolbar.cpp:
134     // """
135     // CJK languages use more verbose accelerator marker: they add a Latin
136     // letter in parenthesis, and put accelerator on that. Hence, the default
137     // removal of ampersand only may not be enough there, instead the whole
138     // parenthesis construct should be removed. Provide these filtering i18n
139     // messages so that translators can use Transcript for custom removal.
140     // """
141     if (!actions().isEmpty()) {
142         QAction* action = actions().first();
143         setToolTip(i18nc("@info:tooltip of custom triple button", "%1", action->toolTip()));
144     }
145 }
146 
mousePressEvent(QMouseEvent * e)147 void KexiGroupButton::mousePressEvent(QMouseEvent *e)
148 {
149     if (!isChecked()) { // only allow clicking to check; unchecking happens automatically
150         QToolButton::mousePressEvent(e);
151     }
152 }
153