FreeCAD

Форк
0
/
ToolBarManager.cpp 
576 строк · 18.9 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2005 Werner Mayer <wmayer[at]users.sourceforge.net>     *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
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 as published by the Free Software Foundation; either          *
9
 *   version 2 of the License, or (at your option) any later version.      *
10
 *                                                                         *
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.                  *
15
 *                                                                         *
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                                *
20
 *                                                                         *
21
 ***************************************************************************/
22

23
#include "PreCompiled.h"
24
#ifndef _PreComp_
25
# include <QAction>
26
# include <QApplication>
27
# include <QToolBar>
28
# include <QToolButton>
29
# include <QPointer>
30
#endif
31

32
#include "ToolBarManager.h"
33
#include "Application.h"
34
#include "Command.h"
35
#include "MainWindow.h"
36

37

38
using namespace Gui;
39

40
ToolBarItem::ToolBarItem() : visibilityPolicy(DefaultVisibility::Visible)
41
{
42
}
43

44
ToolBarItem::ToolBarItem(ToolBarItem* item, DefaultVisibility visibilityPolicy) : visibilityPolicy(visibilityPolicy)
45
{
46
    if (item) {
47
        item->appendItem(this);
48
    }
49
}
50

51
ToolBarItem::~ToolBarItem()
52
{
53
    clear();
54
}
55

56
void ToolBarItem::setCommand(const std::string& name)
57
{
58
    _name = name;
59
}
60

61
const std::string & ToolBarItem::command() const
62
{
63
    return _name;
64
}
65

66
bool ToolBarItem::hasItems() const
67
{
68
    return _items.count() > 0;
69
}
70

71
ToolBarItem* ToolBarItem::findItem(const std::string& name)
72
{
73
    if ( _name == name ) {
74
        return this;
75
    }
76

77
    for (auto it : qAsConst(_items)) {
78
        if (it->_name == name) {
79
            return it;
80
        }
81
    }
82

83
    return nullptr;
84
}
85

86
ToolBarItem* ToolBarItem::copy() const
87
{
88
    auto root = new ToolBarItem;
89
    root->setCommand( command() );
90

91
    QList<ToolBarItem*> items = getItems();
92
    for (auto it : items) {
93
        root->appendItem(it->copy());
94
    }
95

96
    return root;
97
}
98

99
uint ToolBarItem::count() const
100
{
101
    return _items.count();
102
}
103

104
void ToolBarItem::appendItem(ToolBarItem* item)
105
{
106
    _items.push_back( item );
107
}
108

109
bool ToolBarItem::insertItem( ToolBarItem* before, ToolBarItem* item)
110
{
111
    int pos = _items.indexOf(before);
112
    if (pos != -1) {
113
        _items.insert(pos, item);
114
        return true;
115
    }
116

117
    return false;
118
}
119

120
void ToolBarItem::removeItem(ToolBarItem* item)
121
{
122
    int pos = _items.indexOf(item);
123
    if (pos != -1) {
124
        _items.removeAt(pos);
125
    }
126
}
127

128
void ToolBarItem::clear()
129
{
130
    for (auto it : qAsConst(_items)) {
131
        delete it;
132
    }
133

134
    _items.clear();
135
}
136

137
ToolBarItem& ToolBarItem::operator << (ToolBarItem* item)
138
{
139
    appendItem(item);
140
    return *this;
141
}
142

143
ToolBarItem& ToolBarItem::operator << (const std::string& command)
144
{
145
    auto item = new ToolBarItem(this);
146
    item->setCommand(command);
147
    return *this;
148
}
149

150
QList<ToolBarItem*> ToolBarItem::getItems() const
151
{
152
    return _items;
153
}
154

155
// -----------------------------------------------------------
156

157
ToolBarManager* ToolBarManager::_instance=nullptr;
158

159
ToolBarManager* ToolBarManager::getInstance()
160
{
161
    if ( !_instance )
162
        _instance = new ToolBarManager;
163
    return _instance;
164
}
165

166
void ToolBarManager::destruct()
167
{
168
    delete _instance;
169
    _instance = nullptr;
170
}
171

172
ToolBarManager::ToolBarManager() = default;
173

174
ToolBarManager::~ToolBarManager() = default;
175

176
namespace {
177
QPointer<QWidget> createActionWidget()
178
{
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));
190
    }
191
    else {
192
        auto actions = _ActionWidget->actions();
193
        for (auto action : actions) {
194
            _ActionWidget->removeAction(action);
195
        }
196
    }
197

198
    return _ActionWidget;
199
}
200
}
201

202
void ToolBarManager::setup(ToolBarItem* toolBarItems)
203
{
204
    if (!toolBarItems)
205
        return; // empty menu bar
206

207
    QPointer<QWidget> _ActionWidget = createActionWidget();
208

209
    saveState();
210
    this->toolbarNames.clear();
211

212
    int max_width = getMainWindow()->width();
213
    int top_width = 0;
214

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;
228

229
        if (!toolbar) {
230
            toolbar = getMainWindow()->addToolBar(
231
                QApplication::translate("Workbench",
232
                                        toolbarName.c_str())); // i18n
233
            toolbar->setObjectName(name);
234
            if (nameAsToolTip){
235
                auto tooltip = QChar::fromLatin1('[')
236
                    + QApplication::translate("Workbench", toolbarName.c_str())
237
                    + QChar::fromLatin1(']');
238
                toolbar->setToolTip(tooltip);
239
            }
240
            toolbar_added = true;
241
        }
242
        else {
243
            int index = toolbars.indexOf(toolbar);
244
            toolbars.removeAt(index);
245
        }
246

247
        bool visible = false;
248

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.
251
        //
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;
255

256
            visible = hPref->GetBool(toolbarName.c_str(), defaultvisibility);
257

258
            // Enable automatic handling of visibility via, for example, (contextual) menu
259
            toolbar->toggleViewAction()->setVisible(true);
260
        }
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);
265
        }
266

267
        // Initialise toolbar item visibility
268
        toolbar->setVisible(visible);
269

270
        // Store item visibility policy within the action
271
        toolbar->toggleViewAction()->setProperty("DefaultVisibility", static_cast<int>((*it)->visibilityPolicy));
272

273
        // setup the toolbar
274
        setup(*it, toolbar);
275
        auto actions = toolbar->actions();
276
        for (auto action : actions) {
277
            _ActionWidget->addAction(action);
278
        }
279

280
        // try to add some breaks to avoid to have all toolbars in one line
281
        if (toolbar_added) {
282
            if (top_width > 0 && getMainWindow()->toolBarBreak(toolbar))
283
                top_width = 0;
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) {
289
                top_width = 0;
290
                getMainWindow()->insertToolBarBreak(toolbar);
291
            }
292
        }
293
    }
294

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()) {
301
            if (fw == *it) {
302
                getMainWindow()->setFocus();
303
                break;
304
            }
305
            fw = fw->parentWidget();
306
        }
307
        // ignore toolbars which do not belong to the previously active workbench
308
        //QByteArray toolbarName = (*it)->objectName().toUtf8();
309
        if (!(*it)->toggleViewAction()->isVisible())
310
            continue;
311
        //hPref->SetBool(toolbarName.constData(), (*it)->isVisible());
312
        (*it)->hide();
313
        (*it)->toggleViewAction()->setVisible(false);
314
    }
315

316
    hPref = App::GetApplication().GetUserParameter().GetGroup("BaseApp")
317
        ->GetGroup("Preferences")->GetGroup("General");
318
    bool lockToolBars = hPref->GetBool("LockToolBars", false);
319
    setMovable(!lockToolBars);
320
}
321

322
void ToolBarManager::setup(ToolBarItem* item, QToolBar* toolbar) const
323
{
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()));
330
        if (!action) {
331
            if ((*it)->command() == "Separator") {
332
                action = toolbar->addSeparator();
333
            }
334
            else {
335
                // Check if action was added successfully
336
                if (mgr.addTo((*it)->command().c_str(), toolbar))
337
                    action = toolbar->actions().constLast();
338
            }
339

340
            // set the tool button user data
341
            if (action) {
342
                action->setData(QString::fromLatin1((*it)->command().c_str()));
343
            }
344
        }
345
        else {
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);
351
        }
352
    }
353

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);
357
    }
358
}
359

360
void ToolBarManager::saveState() const
361
{
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()) {
366
            return true;
367
        }
368

369
        QVariant property = action->property("DefaultVisibility");
370
        if (property.isNull()) {
371
            return false;
372
        }
373

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;
378
    };
379

380
    ParameterGrp::handle hPref = App::GetApplication().GetUserParameter().GetGroup("BaseApp")
381
                               ->GetGroup("MainWindow")->GetGroup("Toolbars");
382

383
    QList<QToolBar*> toolbars = toolBars();
384
    for (QStringList::ConstIterator it = this->toolbarNames.begin(); it != this->toolbarNames.end(); ++it) {
385
        QToolBar* toolbar = findToolBar(toolbars, *it);
386
        if (toolbar) {
387
            if (ignoreSave(toolbar->toggleViewAction())) {
388
                continue;
389
            }
390

391
            QByteArray toolbarName = toolbar->objectName().toUtf8();
392
            hPref->SetBool(toolbarName.constData(), toolbar->isVisible());
393
        }
394
    }
395
}
396

397
void ToolBarManager::restoreState() const
398
{
399
    ParameterGrp::handle hPref = App::GetApplication().GetUserParameter().GetGroup("BaseApp")
400
                               ->GetGroup("MainWindow")->GetGroup("Toolbars");
401

402
    QList<QToolBar*> toolbars = toolBars();
403
    for (QStringList::ConstIterator it = this->toolbarNames.begin(); it != this->toolbarNames.end(); ++it) {
404
        QToolBar* toolbar = findToolBar(toolbars, *it);
405
        if (toolbar) {
406
            QByteArray toolbarName = toolbar->objectName().toUtf8();
407
            toolbar->setVisible(hPref->GetBool(toolbarName.constData(), toolbar->isVisible()));
408
        }
409
    }
410

411
    setMovable(!areToolBarsLocked());
412
}
413

414
void ToolBarManager::retranslate() const
415
{
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));
422
    }
423
}
424

425
bool Gui::ToolBarManager::areToolBarsLocked() const
426
{
427
    auto hPref = App::GetApplication()
428
                     .GetUserParameter()
429
                     .GetGroup("BaseApp")
430
                     ->GetGroup("Preferences")
431
                     ->GetGroup("General");
432

433
    return hPref->GetBool("LockToolBars", false);
434
}
435

436
void Gui::ToolBarManager::setToolBarsLocked(bool locked) const
437
{
438
    auto hPref = App::GetApplication()
439
                     .GetUserParameter()
440
                     .GetGroup("BaseApp")
441
                     ->GetGroup("Preferences")
442
                     ->GetGroup("General");
443

444
    hPref->SetBool("LockToolBars", locked);
445

446
    setMovable(!locked);
447
}
448

449
void Gui::ToolBarManager::setMovable(bool moveable) const
450
{
451
    for (auto& tb : toolBars()) {
452
        tb->setMovable(moveable);
453
    }
454
}
455

456
QToolBar* ToolBarManager::findToolBar(const QList<QToolBar*>& toolbars, const QString& item) const
457
{
458
    for (QList<QToolBar*>::ConstIterator it = toolbars.begin(); it != toolbars.end(); ++it) {
459
        if ((*it)->objectName() == item)
460
            return *it;
461
    }
462

463
    return nullptr; // no item with the user data found
464
}
465

466
QAction* ToolBarManager::findAction(const QList<QAction*>& acts, const QString& item) const
467
{
468
    for (QList<QAction*>::ConstIterator it = acts.begin(); it != acts.end(); ++it) {
469
        if ((*it)->data().toString() == item)
470
            return *it;
471
    }
472

473
    return nullptr; // no item with the user data found
474
}
475

476
QList<QToolBar*> ToolBarManager::toolBars() const
477
{
478
    QWidget* mw = getMainWindow();
479
    QList<QToolBar*> tb;
480
    QList<QToolBar*> bars = getMainWindow()->findChildren<QToolBar*>();
481
    for (QList<QToolBar*>::Iterator it = bars.begin(); it != bars.end(); ++it) {
482
        if ((*it)->parentWidget() == mw)
483
            tb.push_back(*it);
484
    }
485

486
    return tb;
487
}
488

489
ToolBarItem::DefaultVisibility ToolBarManager::getToolbarPolicy(const QToolBar* toolbar) const
490
{
491
    auto* action = toolbar->toggleViewAction();
492

493
    QVariant property = action->property("DefaultVisibility");
494
    if (property.isNull()) {
495
        return ToolBarItem::DefaultVisibility::Visible;
496
    }
497

498
    return static_cast<ToolBarItem::DefaultVisibility>(property.toInt());
499
}
500

501
void ToolBarManager::setState(const QList<QString>& names, State state)
502
{
503
    for (auto& name : names) {
504
        setState(name, state);
505
    }
506
}
507

508
void ToolBarManager::setState(const QString& name, State state)
509
{
510
    ParameterGrp::handle hPref = App::GetApplication().GetUserParameter().GetGroup("BaseApp")->GetGroup("MainWindow")->GetGroup("Toolbars");
511

512
    auto visibility = [hPref, name](bool defaultvalue) {
513
        return hPref->GetBool(name.toStdString().c_str(), defaultvalue);
514
    };
515

516
    auto saveVisibility = [hPref, name](bool value) {
517
        hPref->SetBool(name.toStdString().c_str(), value);
518
    };
519

520
    auto showhide = [visibility](QToolBar* toolbar, ToolBarItem::DefaultVisibility policy) {
521

522
        auto show = visibility( policy == ToolBarItem::DefaultVisibility::Visible );
523

524
        if(show) {
525
            toolbar->show();
526
        }
527
        else {
528
            toolbar->hide();
529
        }
530
    };
531

532
    QToolBar* tb = findToolBar(toolBars(), name);
533
    if (tb) {
534

535
        if (state == State::RestoreDefault) {
536

537
            auto policy = getToolbarPolicy(tb);
538

539
            if(policy == ToolBarItem::DefaultVisibility::Unavailable) {
540
                tb->hide();
541
                tb->toggleViewAction()->setVisible(false);
542
            }
543
            else  {
544
                tb->toggleViewAction()->setVisible(true);
545

546
                showhide(tb, policy);
547
            }
548
        }
549
        else if (state == State::ForceAvailable) {
550

551
            auto policy = getToolbarPolicy(tb);
552

553
            tb->toggleViewAction()->setVisible(true);
554

555
            // Unavailable policy defaults to a Visible toolbars when made available
556
            auto show = visibility( policy == ToolBarItem::DefaultVisibility::Visible ||
557
                                    policy == ToolBarItem::DefaultVisibility::Unavailable);
558

559
            if(show) {
560
                tb->show();
561
            }
562
            else {
563
                tb->hide();
564
            }
565
        }
566
        else if (state == State::ForceHidden) {
567
            tb->toggleViewAction()->setVisible(false); // not visible in context menus
568
            tb->hide(); // toolbar not visible
569

570
        }
571
        else if (state == State::SaveState) {
572
            auto show = tb->isVisible();
573
            saveVisibility(show);
574
        }
575
    }
576
}
577

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.