1
/***************************************************************************
2
* Copyright (c) 2005 Werner Mayer <wmayer[at]users.sourceforge.net> *
4
* This file is part of the FreeCAD CAx development system. *
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 as published by the Free Software Foundation; either *
9
* version 2 of the License, or (at your option) any later version. *
11
* This library is distributed in the hope that it will be useful, *
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
* GNU Library General Public License for more details. *
16
* You should have received a copy of the GNU Library General Public *
17
* License along with this library; see the file COPYING.LIB. If not, *
18
* write to the Free Software Foundation, Inc., 59 Temple Place, *
19
* Suite 330, Boston, MA 02111-1307, USA *
21
***************************************************************************/
23
#include "PreCompiled.h"
26
# include <QApplication>
28
# include <QToolButton>
32
#include "ToolBarManager.h"
33
#include "Application.h"
35
#include "MainWindow.h"
40
ToolBarItem::ToolBarItem() : visibilityPolicy(DefaultVisibility::Visible)
44
ToolBarItem::ToolBarItem(ToolBarItem* item, DefaultVisibility visibilityPolicy) : visibilityPolicy(visibilityPolicy)
47
item->appendItem(this);
51
ToolBarItem::~ToolBarItem()
56
void ToolBarItem::setCommand(const std::string& name)
61
const std::string & ToolBarItem::command() const
66
bool ToolBarItem::hasItems() const
68
return _items.count() > 0;
71
ToolBarItem* ToolBarItem::findItem(const std::string& name)
73
if ( _name == name ) {
77
for (auto it : qAsConst(_items)) {
78
if (it->_name == name) {
86
ToolBarItem* ToolBarItem::copy() const
88
auto root = new ToolBarItem;
89
root->setCommand( command() );
91
QList<ToolBarItem*> items = getItems();
92
for (auto it : items) {
93
root->appendItem(it->copy());
99
uint ToolBarItem::count() const
101
return _items.count();
104
void ToolBarItem::appendItem(ToolBarItem* item)
106
_items.push_back( item );
109
bool ToolBarItem::insertItem( ToolBarItem* before, ToolBarItem* item)
111
int pos = _items.indexOf(before);
113
_items.insert(pos, item);
120
void ToolBarItem::removeItem(ToolBarItem* item)
122
int pos = _items.indexOf(item);
124
_items.removeAt(pos);
128
void ToolBarItem::clear()
130
for (auto it : qAsConst(_items)) {
137
ToolBarItem& ToolBarItem::operator << (ToolBarItem* item)
143
ToolBarItem& ToolBarItem::operator << (const std::string& command)
145
auto item = new ToolBarItem(this);
146
item->setCommand(command);
150
QList<ToolBarItem*> ToolBarItem::getItems() const
155
// -----------------------------------------------------------
157
ToolBarManager* ToolBarManager::_instance=nullptr;
159
ToolBarManager* ToolBarManager::getInstance()
162
_instance = new ToolBarManager;
166
void ToolBarManager::destruct()
172
ToolBarManager::ToolBarManager() = default;
174
ToolBarManager::~ToolBarManager() = default;
177
QPointer<QWidget> createActionWidget()
179
static QPointer<QWidget> _ActionWidget;
180
if (!_ActionWidget) {
181
_ActionWidget = new QWidget(getMainWindow());
182
_ActionWidget->setObjectName(QStringLiteral("_fc_action_widget_"));
183
/* TODO This is a temporary hack until a longterm solution
184
is found, thanks to @realthunder for this pointer.
185
Although _ActionWidget has zero size, it somehow has a
186
'phantom' size without any visible content and will block the top
187
left tool buttons and menus of the application main window.
188
Therefore it is moved out of the way. */
189
_ActionWidget->move(QPoint(-100,-100));
192
auto actions = _ActionWidget->actions();
193
for (auto action : actions) {
194
_ActionWidget->removeAction(action);
198
return _ActionWidget;
202
void ToolBarManager::setup(ToolBarItem* toolBarItems)
205
return; // empty menu bar
207
QPointer<QWidget> _ActionWidget = createActionWidget();
210
this->toolbarNames.clear();
212
int max_width = getMainWindow()->width();
215
ParameterGrp::handle hPref = App::GetApplication().GetUserParameter().GetGroup("BaseApp")
216
->GetGroup("MainWindow")->GetGroup("Toolbars");
217
bool nameAsToolTip = App::GetApplication().GetUserParameter().GetGroup("BaseApp")
218
->GetGroup("Preferences")->GetGroup("MainWindow")->GetBool("ToolBarNameAsToolTip",true);
219
QList<ToolBarItem*> items = toolBarItems->getItems();
220
QList<QToolBar*> toolbars = toolBars();
221
for (QList<ToolBarItem*>::Iterator it = items.begin(); it != items.end(); ++it) {
222
// search for the toolbar
223
QString name = QString::fromUtf8((*it)->command().c_str());
224
this->toolbarNames << name;
225
QToolBar* toolbar = findToolBar(toolbars, name);
226
std::string toolbarName = (*it)->command();
227
bool toolbar_added = false;
230
toolbar = getMainWindow()->addToolBar(
231
QApplication::translate("Workbench",
232
toolbarName.c_str())); // i18n
233
toolbar->setObjectName(name);
235
auto tooltip = QChar::fromLatin1('[')
236
+ QApplication::translate("Workbench", toolbarName.c_str())
237
+ QChar::fromLatin1(']');
238
toolbar->setToolTip(tooltip);
240
toolbar_added = true;
243
int index = toolbars.indexOf(toolbar);
244
toolbars.removeAt(index);
247
bool visible = false;
249
// If visibility policy is custom, the toolbar is initialised as not visible, and the
250
// toggleViewAction to control its visibility is not visible either.
252
// Both are managed under the responsibility of the client code
253
if((*it)->visibilityPolicy != ToolBarItem::DefaultVisibility::Unavailable) {
254
bool defaultvisibility = (*it)->visibilityPolicy == ToolBarItem::DefaultVisibility::Visible;
256
visible = hPref->GetBool(toolbarName.c_str(), defaultvisibility);
258
// Enable automatic handling of visibility via, for example, (contextual) menu
259
toolbar->toggleViewAction()->setVisible(true);
261
else { // ToolBarItem::DefaultVisibility::Unavailable
262
// Prevent that the action to show/hide a toolbar appears on the (contextual) menus.
263
// This is also managed by the client code for a toolbar with custom policy
264
toolbar->toggleViewAction()->setVisible(false);
267
// Initialise toolbar item visibility
268
toolbar->setVisible(visible);
270
// Store item visibility policy within the action
271
toolbar->toggleViewAction()->setProperty("DefaultVisibility", static_cast<int>((*it)->visibilityPolicy));
275
auto actions = toolbar->actions();
276
for (auto action : actions) {
277
_ActionWidget->addAction(action);
280
// try to add some breaks to avoid to have all toolbars in one line
282
if (top_width > 0 && getMainWindow()->toolBarBreak(toolbar))
284
// the width() of a toolbar doesn't return useful results so we estimate
285
// its size by the number of buttons and the icon size
286
QList<QToolButton*> btns = toolbar->findChildren<QToolButton*>();
287
top_width += (btns.size() * toolbar->iconSize().width());
288
if (top_width > max_width) {
290
getMainWindow()->insertToolBarBreak(toolbar);
295
// hide all unneeded toolbars
296
for (QList<QToolBar*>::Iterator it = toolbars.begin(); it != toolbars.end(); ++it) {
297
// make sure that the main window has the focus when hiding the toolbar with
298
// the combo box inside
299
QWidget *fw = QApplication::focusWidget();
300
while (fw && !fw->isWindow()) {
302
getMainWindow()->setFocus();
305
fw = fw->parentWidget();
307
// ignore toolbars which do not belong to the previously active workbench
308
//QByteArray toolbarName = (*it)->objectName().toUtf8();
309
if (!(*it)->toggleViewAction()->isVisible())
311
//hPref->SetBool(toolbarName.constData(), (*it)->isVisible());
313
(*it)->toggleViewAction()->setVisible(false);
316
hPref = App::GetApplication().GetUserParameter().GetGroup("BaseApp")
317
->GetGroup("Preferences")->GetGroup("General");
318
bool lockToolBars = hPref->GetBool("LockToolBars", false);
319
setMovable(!lockToolBars);
322
void ToolBarManager::setup(ToolBarItem* item, QToolBar* toolbar) const
324
CommandManager& mgr = Application::Instance->commandManager();
325
QList<ToolBarItem*> items = item->getItems();
326
QList<QAction*> actions = toolbar->actions();
327
for (QList<ToolBarItem*>::Iterator it = items.begin(); it != items.end(); ++it) {
328
// search for the action item
329
QAction* action = findAction(actions, QString::fromLatin1((*it)->command().c_str()));
331
if ((*it)->command() == "Separator") {
332
action = toolbar->addSeparator();
335
// Check if action was added successfully
336
if (mgr.addTo((*it)->command().c_str(), toolbar))
337
action = toolbar->actions().constLast();
340
// set the tool button user data
342
action->setData(QString::fromLatin1((*it)->command().c_str()));
346
// Note: For toolbars we do not remove and re-add the actions
347
// because this causes flicker effects. So, it could happen that the order of
348
// buttons doesn't match with the order of commands in the workbench.
349
int index = actions.indexOf(action);
350
actions.removeAt(index);
354
// remove all tool buttons which we don't need for the moment
355
for (QList<QAction*>::Iterator it = actions.begin(); it != actions.end(); ++it) {
356
toolbar->removeAction(*it);
360
void ToolBarManager::saveState() const
362
auto ignoreSave = [](QAction* action) {
363
// If the toggle action is invisible then it's controlled by the application.
364
// In this case the current state is not saved.
365
if (!action->isVisible()) {
369
QVariant property = action->property("DefaultVisibility");
370
if (property.isNull()) {
374
// If DefaultVisibility is Unavailable then never save the state because it's
375
// always controlled by the client code.
376
auto value = static_cast<ToolBarItem::DefaultVisibility>(property.toInt());
377
return value == ToolBarItem::DefaultVisibility::Unavailable;
380
ParameterGrp::handle hPref = App::GetApplication().GetUserParameter().GetGroup("BaseApp")
381
->GetGroup("MainWindow")->GetGroup("Toolbars");
383
QList<QToolBar*> toolbars = toolBars();
384
for (QStringList::ConstIterator it = this->toolbarNames.begin(); it != this->toolbarNames.end(); ++it) {
385
QToolBar* toolbar = findToolBar(toolbars, *it);
387
if (ignoreSave(toolbar->toggleViewAction())) {
391
QByteArray toolbarName = toolbar->objectName().toUtf8();
392
hPref->SetBool(toolbarName.constData(), toolbar->isVisible());
397
void ToolBarManager::restoreState() const
399
ParameterGrp::handle hPref = App::GetApplication().GetUserParameter().GetGroup("BaseApp")
400
->GetGroup("MainWindow")->GetGroup("Toolbars");
402
QList<QToolBar*> toolbars = toolBars();
403
for (QStringList::ConstIterator it = this->toolbarNames.begin(); it != this->toolbarNames.end(); ++it) {
404
QToolBar* toolbar = findToolBar(toolbars, *it);
406
QByteArray toolbarName = toolbar->objectName().toUtf8();
407
toolbar->setVisible(hPref->GetBool(toolbarName.constData(), toolbar->isVisible()));
411
setMovable(!areToolBarsLocked());
414
void ToolBarManager::retranslate() const
416
QList<QToolBar*> toolbars = toolBars();
417
for (QList<QToolBar*>::Iterator it = toolbars.begin(); it != toolbars.end(); ++it) {
418
QByteArray toolbarName = (*it)->objectName().toUtf8();
419
(*it)->setWindowTitle(
420
QApplication::translate("Workbench",
421
(const char*)toolbarName));
425
bool Gui::ToolBarManager::areToolBarsLocked() const
427
auto hPref = App::GetApplication()
430
->GetGroup("Preferences")
431
->GetGroup("General");
433
return hPref->GetBool("LockToolBars", false);
436
void Gui::ToolBarManager::setToolBarsLocked(bool locked) const
438
auto hPref = App::GetApplication()
441
->GetGroup("Preferences")
442
->GetGroup("General");
444
hPref->SetBool("LockToolBars", locked);
449
void Gui::ToolBarManager::setMovable(bool moveable) const
451
for (auto& tb : toolBars()) {
452
tb->setMovable(moveable);
456
QToolBar* ToolBarManager::findToolBar(const QList<QToolBar*>& toolbars, const QString& item) const
458
for (QList<QToolBar*>::ConstIterator it = toolbars.begin(); it != toolbars.end(); ++it) {
459
if ((*it)->objectName() == item)
463
return nullptr; // no item with the user data found
466
QAction* ToolBarManager::findAction(const QList<QAction*>& acts, const QString& item) const
468
for (QList<QAction*>::ConstIterator it = acts.begin(); it != acts.end(); ++it) {
469
if ((*it)->data().toString() == item)
473
return nullptr; // no item with the user data found
476
QList<QToolBar*> ToolBarManager::toolBars() const
478
QWidget* mw = getMainWindow();
480
QList<QToolBar*> bars = getMainWindow()->findChildren<QToolBar*>();
481
for (QList<QToolBar*>::Iterator it = bars.begin(); it != bars.end(); ++it) {
482
if ((*it)->parentWidget() == mw)
489
ToolBarItem::DefaultVisibility ToolBarManager::getToolbarPolicy(const QToolBar* toolbar) const
491
auto* action = toolbar->toggleViewAction();
493
QVariant property = action->property("DefaultVisibility");
494
if (property.isNull()) {
495
return ToolBarItem::DefaultVisibility::Visible;
498
return static_cast<ToolBarItem::DefaultVisibility>(property.toInt());
501
void ToolBarManager::setState(const QList<QString>& names, State state)
503
for (auto& name : names) {
504
setState(name, state);
508
void ToolBarManager::setState(const QString& name, State state)
510
ParameterGrp::handle hPref = App::GetApplication().GetUserParameter().GetGroup("BaseApp")->GetGroup("MainWindow")->GetGroup("Toolbars");
512
auto visibility = [hPref, name](bool defaultvalue) {
513
return hPref->GetBool(name.toStdString().c_str(), defaultvalue);
516
auto saveVisibility = [hPref, name](bool value) {
517
hPref->SetBool(name.toStdString().c_str(), value);
520
auto showhide = [visibility](QToolBar* toolbar, ToolBarItem::DefaultVisibility policy) {
522
auto show = visibility( policy == ToolBarItem::DefaultVisibility::Visible );
532
QToolBar* tb = findToolBar(toolBars(), name);
535
if (state == State::RestoreDefault) {
537
auto policy = getToolbarPolicy(tb);
539
if(policy == ToolBarItem::DefaultVisibility::Unavailable) {
541
tb->toggleViewAction()->setVisible(false);
544
tb->toggleViewAction()->setVisible(true);
546
showhide(tb, policy);
549
else if (state == State::ForceAvailable) {
551
auto policy = getToolbarPolicy(tb);
553
tb->toggleViewAction()->setVisible(true);
555
// Unavailable policy defaults to a Visible toolbars when made available
556
auto show = visibility( policy == ToolBarItem::DefaultVisibility::Visible ||
557
policy == ToolBarItem::DefaultVisibility::Unavailable);
566
else if (state == State::ForceHidden) {
567
tb->toggleViewAction()->setVisible(false); // not visible in context menus
568
tb->hide(); // toolbar not visible
571
else if (state == State::SaveState) {
572
auto show = tb->isVisible();
573
saveVisibility(show);