1 /**************************************************************************
2 * Otter Browser: Web browser controlled by the user, not vice-versa.
3 * Copyright (C) 2015 - 2019 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 "MenuBarWidget.h"
21 #include "MainWindow.h"
22 #include "Menu.h"
23 #include "ToolBarWidget.h"
24 #include "../core/SessionsManager.h"
25
26 #include <QtCore/QFile>
27 #include <QtCore/QJsonArray>
28 #include <QtCore/QJsonDocument>
29 #include <QtCore/QJsonObject>
30 #include <QtCore/QTimer>
31 #include <QtGui/QContextMenuEvent>
32 #include <QtWidgets/QStyle>
33 #include <QtWidgets/QStyleOptionMenuItem>
34
35 namespace Otter
36 {
37
MenuBarWidget(MainWindow * parent)38 MenuBarWidget::MenuBarWidget(MainWindow *parent) : QMenuBar(parent),
39 m_mainWindow(parent),
40 m_leftToolBar(nullptr),
41 m_rightToolBar(nullptr)
42 {
43 QFile file(SessionsManager::getReadableDataPath(QLatin1String("menu/menuBar.json")));
44 file.open(QIODevice::ReadOnly);
45
46 const QJsonArray definition(QJsonDocument::fromJson(file.readAll()).array());
47
48 file.close();
49
50 for (int i = 0; i < definition.count(); ++i)
51 {
52 const QJsonObject object(definition.at(i).toObject());
53 Menu *menu(new Menu(Menu::getMenuRoleIdentifier(object.value(QLatin1String("identifier")).toString()), this));
54 menu->load(object);
55
56 addMenu(menu);
57 }
58
59 if (!isNativeMenuBar())
60 {
61 reload();
62
63 connect(ToolBarsManager::getInstance(), &ToolBarsManager::toolBarModified, this, [&](int identifier)
64 {
65 if (identifier == ToolBarsManager::MenuBar)
66 {
67 reload();
68 }
69 });
70 }
71 }
72
changeEvent(QEvent * event)73 void MenuBarWidget::changeEvent(QEvent *event)
74 {
75 QMenuBar::changeEvent(event);
76
77 if (event->type() == QEvent::LanguageChange)
78 {
79 QTimer::singleShot(100, this, &MenuBarWidget::updateGeometries);
80 }
81 }
82
resizeEvent(QResizeEvent * event)83 void MenuBarWidget::resizeEvent(QResizeEvent *event)
84 {
85 QMenuBar::resizeEvent(event);
86
87 updateGeometries();
88 }
89
contextMenuEvent(QContextMenuEvent * event)90 void MenuBarWidget::contextMenuEvent(QContextMenuEvent *event)
91 {
92 QMenu *menu(ToolBarWidget::createCustomizationMenu(ToolBarsManager::MenuBar));
93 menu->exec(event->globalPos());
94 menu->deleteLater();
95 }
96
reload()97 void MenuBarWidget::reload()
98 {
99 const ToolBarsManager::ToolBarDefinition definition(ToolBarsManager::getToolBarDefinition(ToolBarsManager::MenuBar));
100 QStringList actions;
101 actions.reserve(definition.entries.count());
102
103 for (int i = 0; i < definition.entries.count(); ++i)
104 {
105 actions.append(definition.entries.at(i).action);
106 }
107
108 if (actions.count() == 1 && actions.at(0) == QLatin1String("MenuBarWidget"))
109 {
110 if (m_leftToolBar)
111 {
112 m_leftToolBar->deleteLater();
113 m_leftToolBar = nullptr;
114
115 setCornerWidget(nullptr, Qt::TopLeftCorner);
116 }
117
118 if (m_rightToolBar)
119 {
120 m_rightToolBar->deleteLater();
121 m_rightToolBar = nullptr;
122
123 setCornerWidget(nullptr, Qt::TopRightCorner);
124 }
125
126 return;
127 }
128
129 const int position(actions.indexOf(QLatin1String("MenuBarWidget")));
130 const bool needsLeftToolbar(position != 0);
131 const bool needsRightToolbar(position != (definition.entries.count() - 1));
132
133 if (needsLeftToolbar && !m_leftToolBar)
134 {
135 m_leftToolBar = new ToolBarWidget(ToolBarsManager::MenuBar, m_mainWindow->getActiveWindow(), this);
136
137 setCornerWidget(m_leftToolBar, Qt::TopLeftCorner);
138 }
139 else if (!needsLeftToolbar && m_leftToolBar)
140 {
141 m_leftToolBar->deleteLater();
142 m_leftToolBar = nullptr;
143
144 setCornerWidget(nullptr, Qt::TopLeftCorner);
145 }
146
147 if (needsRightToolbar && !m_rightToolBar)
148 {
149 m_rightToolBar = new ToolBarWidget(ToolBarsManager::MenuBar, m_mainWindow->getActiveWindow(), this);
150
151 setCornerWidget(m_rightToolBar, Qt::TopRightCorner);
152 }
153 else if (!needsRightToolbar && m_rightToolBar)
154 {
155 m_rightToolBar->deleteLater();
156 m_rightToolBar = nullptr;
157
158 setCornerWidget(nullptr, Qt::TopRightCorner);
159 }
160
161 ToolBarsManager::ToolBarDefinition leftDefinition(definition);
162 leftDefinition.entries.clear();
163
164 ToolBarsManager::ToolBarDefinition rightDefinition(definition);
165 rightDefinition.entries.clear();
166
167 for (int i = 0; i < definition.entries.count(); ++i)
168 {
169 if (i != position)
170 {
171 if (i < position)
172 {
173 leftDefinition.entries.append(definition.entries.at(i));
174 }
175 else
176 {
177 rightDefinition.entries.append(definition.entries.at(i));
178 }
179 }
180 }
181
182 const int menuBarHeight(actionGeometry(this->actions().at(0)).height());
183
184 if (m_leftToolBar || m_rightToolBar)
185 {
186 const int toolBarHeight((m_leftToolBar ? m_leftToolBar->getIconSize() : m_rightToolBar->getIconSize()) + 12);
187
188 if (m_leftToolBar)
189 {
190 m_leftToolBar->setDefinition(leftDefinition);
191 }
192
193 if (m_rightToolBar)
194 {
195 m_rightToolBar->setDefinition(rightDefinition);
196 }
197
198 setFixedHeight((toolBarHeight > menuBarHeight) ? toolBarHeight : menuBarHeight);
199 }
200 else
201 {
202 setFixedHeight(menuBarHeight);
203 }
204
205 QTimer::singleShot(100, this, &MenuBarWidget::updateGeometries);
206 }
207
updateGeometries()208 void MenuBarWidget::updateGeometries()
209 {
210 if (!m_leftToolBar && !m_rightToolBar)
211 {
212 return;
213 }
214
215 int size(0);
216
217 if (actions().count() > 0)
218 {
219 size = ((style()->pixelMetric(QStyle::PM_MenuBarHMargin, nullptr, this) * 2) + (style()->pixelMetric(QStyle::PM_MenuBarItemSpacing, nullptr, this) * actions().count()));
220
221 for (int i = 0; i < actions().count(); ++i)
222 {
223 QStyleOptionMenuItem option;
224
225 initStyleOption(&option, actions().at(i));
226
227 size += style()->sizeFromContents(QStyle::CT_MenuBarItem, &option, fontMetrics().size(Qt::TextShowMnemonic, option.text), this).width();
228 }
229 }
230
231 if (m_rightToolBar && width() > (size + (m_leftToolBar ? m_leftToolBar->sizeHint().width() : 0) + (m_rightToolBar ? m_rightToolBar->sizeHint().width() : 0)))
232 {
233 const int offset(size - (m_leftToolBar ? m_leftToolBar->sizeHint().width() : 0));
234 ToolBarWidget *toolBar(qobject_cast<ToolBarWidget*>(m_rightToolBar));
235 toolBar->move(QPoint(offset, 0));
236 toolBar->resize((width() - offset), toolBar->height());
237 }
238 }
239
240 }
241