1 /**************************************************************************
2 * Otter Browser: Web browser controlled by the user, not vice-versa.
3 * Copyright (C) 2015 - 2018 Michal Dutkiewicz aka Emdek <michal@emdek.pl>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program 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
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 **************************************************************************/
19
20 #include "ToolButtonWidget.h"
21 #include "Action.h"
22 #include "MainWindow.h"
23 #include "Menu.h"
24 #include "ToolBarWidget.h"
25 #include "../core/Application.h"
26 #include "../core/ThemesManager.h"
27
28 #include <QtCore/QEvent>
29 #include <QtGui/QActionEvent>
30 #include <QtWidgets/QStyleOptionToolButton>
31 #include <QtWidgets/QStylePainter>
32
33 namespace Otter
34 {
35
ToolButtonWidget(const ToolBarsManager::ToolBarDefinition::Entry & definition,QWidget * parent)36 ToolButtonWidget::ToolButtonWidget(const ToolBarsManager::ToolBarDefinition::Entry &definition, QWidget *parent) : QToolButton(parent),
37 m_parameters(definition.parameters),
38 m_isCustomized(false)
39 {
40 setAutoRaise(true);
41 setContextMenuPolicy(Qt::NoContextMenu);
42 setOptions(definition.options);
43
44 Menu *menu(nullptr);
45
46 if (!definition.entries.isEmpty())
47 {
48 menu = new Menu(Menu::UnknownMenu, this);
49
50 addMenu(menu, definition.entries);
51 setMenu(menu);
52 }
53 else if (definition.action == QLatin1String("OptionMenu") && definition.options.contains(QLatin1String("option")))
54 {
55 menu = new Menu(Menu::UnknownMenu, this);
56 menu->load(SettingsManager::getOptionIdentifier(definition.options[QLatin1String("option")].toString()));
57
58 setDefaultAction(menu->menuAction());
59 }
60 else if (definition.action.endsWith(QLatin1String("Menu")))
61 {
62 menu = new Menu(Menu::getMenuRoleIdentifier(definition.action), this);
63
64 setDefaultAction(menu->menuAction());
65 }
66
67 if (menu)
68 {
69 menu->setActionParameters(definition.parameters);
70 menu->setMenuOptions(definition.options);
71
72 setPopupMode(QToolButton::InstantPopup);
73 setText(getText());
74 setToolTip(getText());
75 setIcon(getIcon());
76 }
77
78 const ToolBarWidget *toolBar(qobject_cast<ToolBarWidget*>(parent));
79
80 if (toolBar)
81 {
82 setButtonStyle(toolBar->getButtonStyle());
83 setIconSize(toolBar->getIconSize());
84 setMaximumButtonSize(toolBar->getMaximumButtonSize());
85
86 connect(toolBar, &ToolBarWidget::buttonStyleChanged, this, &ToolButtonWidget::setButtonStyle);
87 connect(toolBar, &ToolBarWidget::iconSizeChanged, this, &ToolButtonWidget::setIconSize);
88 connect(toolBar, &ToolBarWidget::maximumButtonSizeChanged, this, &ToolButtonWidget::setMaximumButtonSize);
89 }
90 }
91
actionEvent(QActionEvent * event)92 void ToolButtonWidget::actionEvent(QActionEvent *event)
93 {
94 QToolButton::actionEvent(event);
95
96 if (event->type() == QEvent::ActionChanged || event->type() == QEvent::ActionAdded)
97 {
98 setText(getText());
99 setIcon(getIcon());
100 }
101 }
102
paintEvent(QPaintEvent * event)103 void ToolButtonWidget::paintEvent(QPaintEvent *event)
104 {
105 Q_UNUSED(event)
106
107 QStylePainter painter(this);
108 QStyleOptionToolButton option;
109
110 initStyleOption(&option);
111
112 option.text = option.fontMetrics.elidedText(option.text, (isLeftToRight() ? Qt::ElideRight : Qt::ElideLeft), (option.rect.width() - (option.fontMetrics.width(QLatin1Char(' ')) * 2) - ((toolButtonStyle() == Qt::ToolButtonTextBesideIcon) ? iconSize().width() : 0)));
113
114 painter.drawComplexControl(QStyle::CC_ToolButton, option);
115 }
116
addMenu(Menu * menu,const QVector<ToolBarsManager::ToolBarDefinition::Entry> & entries)117 void ToolButtonWidget::addMenu(Menu *menu, const QVector<ToolBarsManager::ToolBarDefinition::Entry> &entries)
118 {
119 const ToolBarWidget *toolBar(qobject_cast<ToolBarWidget*>(parentWidget()));
120 ActionExecutor::Object executor(Application::getInstance(), Application::getInstance());
121
122 if (toolBar && toolBar->getMainWindow())
123 {
124 executor = ActionExecutor::Object(toolBar->getMainWindow(), toolBar->getMainWindow());
125 }
126
127 for (int i = 0; i < entries.count(); ++i)
128 {
129 const ToolBarsManager::ToolBarDefinition::Entry entry(entries.at(i));
130
131 if (entry.entries.isEmpty())
132 {
133 if (entry.action.isEmpty() || entry.action == QLatin1String("separator"))
134 {
135 menu->addSeparator();
136 }
137 else
138 {
139 menu->addAction(new Action(ActionsManager::getActionIdentifier(entry.action), entry.parameters, entry.options, executor, menu));
140 }
141 }
142 else
143 {
144 Menu *subMenu(new Menu());
145 QAction *subMenuAction(new QAction(menu));
146 subMenuAction->setText(entry.options.value(QLatin1String("text"), tr("Menu")).toString());
147 subMenuAction->setMenu(subMenu);
148
149 menu->addAction(subMenuAction);
150
151 addMenu(subMenu, entry.entries);
152 }
153 }
154 }
155
setOptions(const QVariantMap & options)156 void ToolButtonWidget::setOptions(const QVariantMap &options)
157 {
158 m_options = options;
159 m_isCustomized = (options.contains(QLatin1String("icon")) || options.contains(QLatin1String("text")));
160
161 if (m_isCustomized)
162 {
163 if (options.contains(QLatin1String("text")))
164 {
165 setText(getText());
166 }
167
168 if (options.contains(QLatin1String("icon")))
169 {
170 setIcon(getIcon());
171 }
172 }
173
174 setButtonStyle(toolButtonStyle());
175 update();
176 }
177
setButtonStyle(Qt::ToolButtonStyle buttonStyle)178 void ToolButtonWidget::setButtonStyle(Qt::ToolButtonStyle buttonStyle)
179 {
180 if (m_options.contains(QLatin1String("buttonStyle")))
181 {
182 const QString buttonStyleString(m_options[QLatin1String("buttonStyle")].toString());
183
184 if (buttonStyleString == QLatin1String("auto"))
185 {
186 buttonStyle = Qt::ToolButtonFollowStyle;
187 }
188 else if (buttonStyleString == QLatin1String("textOnly"))
189 {
190 buttonStyle = Qt::ToolButtonTextOnly;
191 }
192 else if (buttonStyleString == QLatin1String("textBesideIcon"))
193 {
194 buttonStyle = Qt::ToolButtonTextBesideIcon;
195 }
196 else if (buttonStyleString == QLatin1String("textUnderIcon"))
197 {
198 buttonStyle = Qt::ToolButtonTextUnderIcon;
199 }
200 else
201 {
202 buttonStyle = Qt::ToolButtonIconOnly;
203 }
204 }
205
206 setToolButtonStyle(buttonStyle);
207 }
208
setIconSize(int size)209 void ToolButtonWidget::setIconSize(int size)
210 {
211 QToolButton::setIconSize(QSize(size, size));
212 }
213
setMaximumButtonSize(int size)214 void ToolButtonWidget::setMaximumButtonSize(int size)
215 {
216 if (size > 0)
217 {
218 setMaximumSize(size, size);
219 }
220 else
221 {
222 setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
223 }
224 }
225
getText() const226 QString ToolButtonWidget::getText() const
227 {
228 if (m_isCustomized && m_options.contains(QLatin1String("text")))
229 {
230 return m_options[QLatin1String("text")].toString();
231 }
232
233 if (defaultAction())
234 {
235 return defaultAction()->text();
236 }
237
238 return text();
239 }
240
getIcon() const241 QIcon ToolButtonWidget::getIcon() const
242 {
243 if (m_isCustomized && m_options.contains(QLatin1String("icon")))
244 {
245 const QVariant iconData(m_options[QLatin1String("icon")]);
246
247 if (iconData.type() == QVariant::Icon)
248 {
249 return iconData.value<QIcon>();
250 }
251
252 return ThemesManager::createIcon(iconData.toString());
253 }
254
255 return (defaultAction() ? defaultAction()->icon() : icon());
256 }
257
getOptions() const258 QVariantMap ToolButtonWidget::getOptions() const
259 {
260 return m_options;
261 }
262
getParameters() const263 QVariantMap ToolButtonWidget::getParameters() const
264 {
265 return m_parameters;
266 }
267
isCustomized() const268 bool ToolButtonWidget::isCustomized() const
269 {
270 return m_isCustomized;
271 }
272
event(QEvent * event)273 bool ToolButtonWidget::event(QEvent *event)
274 {
275 switch (event->type())
276 {
277 case QEvent::MouseButtonPress:
278 case QEvent::MouseButtonRelease:
279 if (!isEnabled())
280 {
281 return false;
282 }
283
284 break;
285 case QEvent::ContextMenu:
286 if (contextMenuPolicy() == Qt::NoContextMenu)
287 {
288 return false;
289 }
290
291 break;
292 default:
293 break;
294 }
295
296 return QToolButton::event(event);
297 }
298
299 }
300