24
#include "PreCompiled.h"
26
# include <QActionGroup>
27
# include <QApplication>
31
# include <QCloseEvent>
32
# include <QContextMenuEvent>
33
# include <QDesktopServices>
34
# include <QDockWidget>
35
# include <QFontMetrics>
36
# include <QKeySequence>
38
# include <QMdiSubWindow>
40
# include <QMessageBox>
43
# include <QRegularExpression>
44
# include <QRegularExpressionMatch>
47
# include <QSignalMapper>
54
# include <QPushButton>
57
#if defined(Q_OS_WIN) && QT_VERSION < QT_VERSION_CHECK(6,0,0)
58
# include <QtPlatformHeaders/QWindowsWindowFunctions>
61
#include <boost/algorithm/string/predicate.hpp>
63
#include <App/Application.h>
64
#include <App/Document.h>
65
#include <App/DocumentObject.h>
66
#include <App/DocumentObjectGroup.h>
67
#include <Base/ConsoleObserver.h>
68
#include <Base/Parameter.h>
69
#include <Base/Exception.h>
70
#include <Base/FileInfo.h>
71
#include <Base/Interpreter.h>
72
#include <Base/Stream.h>
73
#include <Base/Tools.h>
74
#include <Base/UnitsApi.h>
75
#include <DAGView/DAGView.h>
76
#include <TaskView/TaskView.h>
78
#include "MainWindow.h"
81
#include "BitmapFactory.h"
84
#include "DockWindowManager.h"
85
#include "DownloadManager.h"
86
#include "FileDialog.h"
87
#include "MenuManager.h"
88
#include "NotificationArea.h"
89
#include "OverlayManager.h"
90
#include "ProgressBar.h"
91
#include "PropertyView.h"
92
#include "PythonConsole.h"
93
#include "ReportView.h"
94
#include "SelectionView.h"
95
#include "Splashscreen.h"
96
#include "ToolBarManager.h"
97
#include "ToolBoxManager.h"
99
#include "WaitCursor.h"
100
#include "WorkbenchManager.h"
101
#include "Workbench.h"
103
#include "MergeDocuments.h"
104
#include "ViewProviderExtern.h"
106
#include "SpaceballEvent.h"
107
#include "View3DInventor.h"
108
#include "View3DInventorViewer.h"
109
#include "DlgObjectSelection.h"
111
#include <App/Color.h>
113
FC_LOG_LEVEL_INIT("MainWindow",false,true,true)
115
#if defined(Q_OS_WIN32)
120
using namespace Gui::DockWnd;
124
MainWindow* MainWindow::instance = nullptr;
136
class CustomMessageEvent : public QEvent
139
CustomMessageEvent(int t, const QString& s, int timeout=0)
140
: QEvent(QEvent::User), _type(t), msg(s), _timeout(timeout)
142
~CustomMessageEvent() override = default;
145
const QString& message() const
160
class DimensionWidget : public QPushButton, WindowParameter
165
explicit DimensionWidget(QWidget* parent): QPushButton(parent), WindowParameter("Units")
168
setText(qApp->translate("Gui::MainWindow", "Dimension"));
169
setMinimumWidth(120);
172
auto* menu = new QMenu(this);
173
auto* actionGrp = new QActionGroup(menu);
174
int num = static_cast<int>(Base::UnitSystem::NumUnitSystemTypes);
175
for (int i = 0; i < num; i++) {
176
QAction* action = menu->addAction(QStringLiteral("UnitSchema%1").arg(i));
177
actionGrp->addAction(action);
178
action->setCheckable(true);
181
QObject::connect(actionGrp, &QActionGroup::triggered, this, [this](QAction* action) {
182
int userSchema = action->data().toInt();
183
setUserSchema(userSchema);
185
const auto views = getMainWindow()->findChildren<PropertyView*>();
186
for(auto view : views) {
187
bool show = view->showAll();
188
view->setShowAll(!show);
189
view->setShowAll(show);
195
getWindowParameter()->Attach(this);
198
~DimensionWidget() override
200
getWindowParameter()->Detach(this);
203
void OnChange(Base::Subject<const char*> &rCaller, const char * sReason) override
206
if (strcmp(sReason, "UserSchema") == 0) {
211
void changeEvent(QEvent *event) override
213
if (event->type() == QEvent::LanguageChange) {
217
QPushButton::changeEvent(event);
221
void setUserSchema(int userSchema)
223
App::Document* doc = App::GetApplication().getActiveDocument();
224
if ( doc != nullptr ) {
225
if (doc->UnitSystem.getValue() != userSchema )
226
doc->UnitSystem.setValue(userSchema);
228
getWindowParameter()->SetInt("UserSchema", userSchema);
231
Base::UnitsApi::setSchema(static_cast<Base::UnitSystem>(userSchema));
233
Gui::Application::Instance->onUpdate();
239
ParameterGrp::handle hGrpu = App::GetApplication().GetParameterGroupByPath
240
("User parameter:BaseApp/Preferences/Units");
241
bool ignore = hGrpu->GetBool("IgnoreProjectSchema", false);
242
App::Document* doc = App::GetApplication().getActiveDocument();
243
int userSchema = getWindowParameter()->GetInt("UserSchema", 0);
244
if ( doc != nullptr && ! ignore) {
245
userSchema = doc->UnitSystem.getValue();
247
auto actions = menu()->actions();
248
if(Q_UNLIKELY(userSchema < 0 || userSchema >= actions.size())) {
251
actions[userSchema]->setChecked(true);
254
void retranslateUi() {
255
auto actions = menu()->actions();
256
int maxSchema = static_cast<int>(Base::UnitSystem::NumUnitSystemTypes);
257
assert(actions.size() <= maxSchema);
258
for(int i = 0; i < maxSchema ; i++)
260
actions[i]->setText(Base::UnitsApi::getDescription(static_cast<Base::UnitSystem>(i)));
269
DimensionWidget* sizeLabel;
273
QTimer* activityTimer;
274
QTimer saveStateTimer;
275
QTimer restoreStateTimer;
277
QPointer<MDIView> activeView;
278
QSignalMapper* windowMapper;
279
SplashScreen* splashscreen;
280
StatusBarObserver* status;
283
Assistant* assistant;
284
int currentStatusType = 100;
285
int actionUpdateDelay = 0;
286
QMap<QString, QPointer<UrlHandler> > urlHandler;
287
std::string hiddenDockWindows;
288
boost::signals2::scoped_connection connParam;
289
ParameterGrp::handle hGrp;
290
bool _restoring = false;
292
void restoreWindowState(const QByteArray &);
295
class MDITabbar : public QTabBar
298
explicit MDITabbar( QWidget * parent = nullptr ) : QTabBar(parent)
300
menu = new QMenu(this);
302
setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
305
~MDITabbar() override
311
void contextMenuEvent ( QContextMenuEvent * e ) override
314
CommandManager& cMgr = Application::Instance->commandManager();
315
if (tabRect(currentIndex()).contains(e->pos()))
316
cMgr.getCommandByName("Std_CloseActiveWindow")->addTo(menu);
317
cMgr.getCommandByName("Std_CloseAllWindows")->addTo(menu);
318
menu->addSeparator();
319
cMgr.getCommandByName("Std_CascadeWindows")->addTo(menu);
320
cMgr.getCommandByName("Std_TileWindows")->addTo(menu);
321
menu->addSeparator();
322
cMgr.getCommandByName("Std_Windows")->addTo(menu);
323
menu->popup(e->globalPos());
330
#if defined(Q_OS_WIN32)
331
class MainWindowTabBar : public QTabBar
334
MainWindowTabBar(QWidget *parent) : QTabBar(parent)
339
bool event(QEvent *e)
342
if (e->type() != QEvent::ToolTip)
343
return QTabBar::event(e);
344
QSize size = this->size();
345
QSize hint = sizeHint();
346
if (shape() == QTabBar::RoundedWest || shape() == QTabBar::RoundedEast) {
350
if (size.width() < hint.width())
351
return QTabBar::event(e);
355
void tabInserted (int index)
358
QList<QDockWidget*> dw = getMainWindow()->findChildren<QDockWidget*>();
359
for (QList<QDockWidget*>::iterator it = dw.begin(); it != dw.end(); ++it) {
361
if (this->tabText(index) == (*it)->windowTitle()) {
362
QWidget* dock = (*it)->widget();
364
QIcon icon = dock->windowIcon();
366
setTabIcon(index, icon);
379
MainWindow::MainWindow(QWidget * parent, Qt::WindowFlags f)
380
: QMainWindow( parent, f )
383
d->splashscreen = nullptr;
384
d->activeView = nullptr;
385
d->whatsthis = false;
386
d->assistant = new Assistant();
391
d->connParam = App::GetApplication().GetUserParameter().signalParamChanged.connect(
392
[this](ParameterGrp *Param, ParameterGrp::ParamType, const char *Name, const char *) {
393
if (Param != d->hGrp || !Name)
395
if (boost::equals(Name, "StatusBar")) {
396
if(auto sb = getMainWindow()->statusBar())
397
sb->setVisible(d->hGrp->GetBool("StatusBar", sb->isVisible()));
399
else if (boost::equals(Name, "MainWindowState")) {
400
OverlayManager::instance()->reload(OverlayManager::ReloadMode::ReloadPause);
401
d->restoreStateTimer.start(100);
405
d->hGrp = App::GetApplication().GetParameterGroupByPath(
406
"User parameter:BaseApp/Preferences/MainWindow");
407
d->saveStateTimer.setSingleShot(true);
408
connect(&d->saveStateTimer, &QTimer::timeout, [this](){this->saveWindowSettings();});
410
d->restoreStateTimer.setSingleShot(true);
411
connect(&d->restoreStateTimer, &QTimer::timeout, [this](){
412
d->restoreWindowState(QByteArray::fromBase64(d->hGrp->GetASCII("MainWindowState").c_str()));
413
ToolBarManager::getInstance()->restoreState();
414
OverlayManager::instance()->reload(OverlayManager::ReloadMode::ReloadResume);
419
setDockOptions(dockOptions() | QMainWindow::GroupedDragging);
422
d->mdiArea = new QMdiArea();
424
d->mdiArea->setTabsMovable(true);
425
d->mdiArea->setTabPosition(QTabWidget::South);
426
d->mdiArea->setViewMode(QMdiArea::TabbedView);
427
auto tab = d->mdiArea->findChild<QTabBar*>();
429
tab->setTabsClosable(true);
431
tab->setExpanding(false);
432
tab->setObjectName(QString::fromLatin1("mdiAreaTabBar"));
434
d->mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
435
d->mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
436
d->mdiArea->setOption(QMdiArea::DontMaximizeSubWindowOnActivation, false);
437
d->mdiArea->setActivationOrder(QMdiArea::ActivationHistoryOrder);
438
d->mdiArea->setBackground(QBrush(QColor(160,160,160)));
439
setCentralWidget(d->mdiArea);
441
statusBar()->setObjectName(QString::fromLatin1("statusBar"));
442
connect(statusBar(), &QStatusBar::messageChanged, this, &MainWindow::statusMessageChanged);
445
d->status = new StatusBarObserver();
446
d->actionLabel = new QLabel(statusBar());
449
d->sizeLabel = new DimensionWidget(statusBar());
451
statusBar()->addWidget(d->actionLabel, 1);
452
QProgressBar* progressBar = Gui::SequencerBar::instance()->getProgressBar(statusBar());
453
statusBar()->addPermanentWidget(progressBar, 0);
454
statusBar()->addPermanentWidget(d->sizeLabel, 0);
456
auto hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/NotificationArea");
458
auto notificationAreaEnabled = hGrp->GetBool("NotificationAreaEnabled", true);
460
if(notificationAreaEnabled) {
461
NotificationArea* notificationArea = new NotificationArea(statusBar());
462
notificationArea->setObjectName(QString::fromLatin1("notificationArea"));
463
notificationArea->setStyleSheet(QStringLiteral("text-align:left;"));
464
statusBar()->addPermanentWidget(notificationArea);
467
d->actionTimer = new QTimer( this );
468
d->actionTimer->setObjectName(QString::fromLatin1("actionTimer"));
469
connect(d->actionTimer, &QTimer::timeout, d->actionLabel, &QLabel::clear);
472
d->statusTimer = new QTimer( this );
473
d->statusTimer->setObjectName(QString::fromLatin1("statusTimer"));
474
connect(d->statusTimer, &QTimer::timeout, this, &MainWindow::clearStatus);
477
d->activityTimer = new QTimer(this);
478
d->activityTimer->setObjectName(QString::fromLatin1("activityTimer"));
479
connect(d->activityTimer, &QTimer::timeout, this, &MainWindow::_updateActions);
480
d->activityTimer->setSingleShot(false);
481
d->activityTimer->start(150);
484
QClipboard *clipbd = QApplication::clipboard();
485
connect(clipbd, &QClipboard::dataChanged, this, &MainWindow::updateEditorActions);
487
d->windowMapper = new QSignalMapper(this);
490
#if QT_VERSION < QT_VERSION_CHECK(5,15,0)
491
connect(d->windowMapper, qOverload<QWidget*>(&QSignalMapper::mapped),
492
this, &MainWindow::onSetActiveSubWindow);
493
#elif QT_VERSION < QT_VERSION_CHECK(6,0,0)
494
connect(d->windowMapper, &QSignalMapper::mappedWidget,
495
this, &MainWindow::onSetActiveSubWindow);
497
connect(d->windowMapper, &QSignalMapper::mappedObject,
498
this, [=](QObject* object) {
499
onSetActiveSubWindow(qobject_cast<QWidget*>(object));
502
connect(d->mdiArea, &QMdiArea::subWindowActivated,
503
this, &MainWindow::onWindowActivated);
508
setAcceptDrops(true);
510
statusBar()->showMessage(tr("Ready"), 2001);
513
MainWindow::~MainWindow()
520
MainWindow* MainWindow::getInstance()
529
static inline void _updateDockWidget(const char *name,
532
Qt::DockWidgetArea pos,
535
auto pDockMgr = DockWindowManager::instance();
536
auto widget = pDockMgr->findRegisteredDockWindow(name);
539
pDockMgr->removeDockWindow(widget);
540
pDockMgr->unregisterDockWindow(name);
541
widget->deleteLater();
546
widget = callback(widget);
549
DockWindowManager::instance()->registerDockWindow(name, widget);
551
auto dock = pDockMgr->addDockWindow(
552
widget->objectName().toUtf8().constData(), widget, pos);
554
if(!dock->toggleViewAction()->isChecked())
555
dock->toggleViewAction()->activate(QAction::Trigger);
556
OverlayManager::instance()->refresh(dock);
561
void MainWindow::initDockWindows(bool show)
563
updateTreeView(show);
564
updatePropertyView(show);
565
updateComboView(show);
566
updateTaskView(show);
570
void MainWindow::setupDockWindows()
574
setupPythonConsole();
575
setupSelectionView();
578
initDockWindows(false);
580
std::vector<QTabWidget::TabPosition> tabPos = {QTabWidget::North,
584
long value = d->hGrp->GetInt("LeftDockWidgetAreaTabPos", long(tabPos.front()));
585
if (value >= 0 && value < long(tabPos.size())) {
586
setTabPosition(Qt::LeftDockWidgetArea, tabPos[value]);
590
bool MainWindow::setupTaskView()
593
if (d->hiddenDockWindows.find("Std_TaskView") == std::string::npos) {
594
auto taskView = new Gui::TaskView::TaskView(this);
595
taskView->setObjectName
596
(QString::fromLatin1(QT_TRANSLATE_NOOP("QDockWidget","Tasks")));
597
taskView->setMinimumWidth(210);
599
DockWindowManager* pDockMgr = DockWindowManager::instance();
600
pDockMgr->registerDockWindow("Std_TaskView", taskView);
607
bool MainWindow::setupSelectionView()
610
if (d->hiddenDockWindows.find("Std_SelectionView") == std::string::npos) {
611
auto pcSelectionView = new SelectionView(nullptr, this);
612
pcSelectionView->setObjectName
613
(QString::fromLatin1(QT_TRANSLATE_NOOP("QDockWidget","Selection view")));
614
pcSelectionView->setMinimumWidth(210);
616
DockWindowManager* pDockMgr = DockWindowManager::instance();
617
pDockMgr->registerDockWindow("Std_SelectionView", pcSelectionView);
624
bool MainWindow::setupReportView()
627
if (d->hiddenDockWindows.find("Std_ReportView") == std::string::npos) {
628
auto pcReport = new ReportOutput(this);
629
pcReport->setWindowIcon(BitmapFactory().pixmap("MacroEditor"));
630
pcReport->setObjectName
631
(QString::fromLatin1(QT_TRANSLATE_NOOP("QDockWidget","Report view")));
633
DockWindowManager* pDockMgr = DockWindowManager::instance();
634
pDockMgr->registerDockWindow("Std_ReportView", pcReport);
636
auto rvObserver = new ReportOutputObserver(pcReport);
637
qApp->installEventFilter(rvObserver);
644
bool MainWindow::setupPythonConsole()
647
if (d->hiddenDockWindows.find("Std_PythonView") == std::string::npos) {
648
auto pcPython = new PythonConsole(this);
649
pcPython->setWindowIcon(Gui::BitmapFactory().iconFromTheme("applications-python"));
650
pcPython->setObjectName
651
(QString::fromLatin1(QT_TRANSLATE_NOOP("QDockWidget","Python console")));
653
DockWindowManager* pDockMgr = DockWindowManager::instance();
654
pDockMgr->registerDockWindow("Std_PythonView", pcPython);
661
bool MainWindow::updateTreeView(bool show)
663
if (d->hiddenDockWindows.find("Std_TreeView") == std::string::npos) {
664
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
665
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("DockWindows")->GetGroup("TreeView");
666
bool enabled = group->GetBool("Enabled", false);
667
_updateDockWidget("Std_TreeView", enabled, show, Qt::RightDockWidgetArea,
668
[](QWidget *widget) {
673
auto tree = new TreeDockWidget(0,getMainWindow());
674
tree->setObjectName(QStringLiteral(QT_TRANSLATE_NOOP("QDockWidget","Tree view")));
675
tree->setMinimumWidth(210);
686
bool MainWindow::updatePropertyView(bool show)
689
if (d->hiddenDockWindows.find("Std_PropertyView") == std::string::npos) {
690
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
691
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("DockWindows")->GetGroup("PropertyView");
692
bool enabled = group->GetBool("Enabled", false);
693
_updateDockWidget("Std_PropertyView", enabled, show, Qt::RightDockWidgetArea,
694
[](QWidget *widget) {
699
auto pcPropView = new PropertyDockView(0, getMainWindow());
700
pcPropView->setObjectName(QStringLiteral(QT_TRANSLATE_NOOP("QDockWidget","Property view")));
701
pcPropView->setMinimumWidth(210);
712
bool MainWindow::updateTaskView(bool show)
715
if (d->hiddenDockWindows.find("Std_TaskWatcher") == std::string::npos) {
717
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
718
GetGroup("BaseApp/Preferences/DockWindows/TaskWatcher");
719
bool enabled = group->GetBool("Enabled", false);
720
group->SetBool("Enabled", enabled);
721
_updateDockWidget("Std_TaskWatcher", enabled, show, Qt::RightDockWidgetArea,
722
[](QWidget *widget) {
727
widget = new TaskView::TaskView(getMainWindow());
728
widget->setObjectName(QStringLiteral(QT_TRANSLATE_NOOP("QDockWidget","Task List")));
738
bool MainWindow::updateComboView(bool show)
741
if (d->hiddenDockWindows.find("Std_ComboView") == std::string::npos) {
742
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
743
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("DockWindows")->GetGroup("ComboView");
744
bool enable = group->GetBool("Enabled", true);
745
_updateDockWidget("Std_ComboView", enable, show, Qt::LeftDockWidgetArea,
746
[](QWidget *widget) {
747
auto pcComboView = qobject_cast<ComboView*>(widget);
752
pcComboView = new ComboView(nullptr, getMainWindow());
753
pcComboView->setObjectName(QStringLiteral(QT_TRANSLATE_NOOP("QDockWidget", "Model")));
754
pcComboView->setMinimumWidth(150);
755
widget = pcComboView;
765
bool MainWindow::updateDAGView(bool show)
768
if (d->hiddenDockWindows.find("Std_DAGView") == std::string::npos) {
769
ParameterGrp::handle group = App::GetApplication().GetUserParameter().
770
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("DockWindows")->GetGroup("DAGView");
771
bool enabled = group->GetBool("Enabled", false);
772
_updateDockWidget("Std_DAGView", enabled, show, Qt::RightDockWidgetArea,
773
[](QWidget *widget) {
778
auto dagDockWindow = new DAG::DockWindow(nullptr, getMainWindow());
779
dagDockWindow->setObjectName(QStringLiteral(QT_TRANSLATE_NOOP("QDockWidget","DAG View")));
780
widget = dagDockWindow;
790
QMenu* MainWindow::createPopupMenu ()
792
QMenu* menu = QMainWindow::createPopupMenu();
793
Workbench* wb = WorkbenchManager::instance()->active();
796
wb->createMainWindowPopupMenu(&item);
797
if (item.hasItems()) {
798
menu->addSeparator();
799
QList<MenuItem*> items = item.getItems();
800
for (const auto & item : items) {
801
if (item->command() == "Separator") {
802
menu->addSeparator();
805
Command* cmd = Application::Instance->commandManager().getCommandByName(item->command().c_str());
806
if (cmd) cmd->addTo(menu);
815
void MainWindow::tile()
817
d->mdiArea->tileSubWindows();
820
void MainWindow::cascade()
822
d->mdiArea->cascadeSubWindows();
825
void MainWindow::closeActiveWindow ()
827
d->mdiArea->closeActiveSubWindow();
830
int MainWindow::confirmSave(const char *docName, QWidget *parent, bool addCheckbox) {
831
QMessageBox box(parent?parent:this);
832
box.setIcon(QMessageBox::Question);
833
box.setWindowTitle(QObject::tr("Unsaved document"));
835
box.setText(QObject::tr("Do you want to save your changes to document '%1' before closing?")
836
.arg(QString::fromUtf8(docName)));
838
box.setText(QObject::tr("Do you want to save your changes to document before closing?"));
840
box.setInformativeText(QObject::tr("If you don't save, your changes will be lost."));
841
box.setStandardButtons(QMessageBox::Discard | QMessageBox::Cancel | QMessageBox::Save);
842
box.setDefaultButton(QMessageBox::Save);
843
box.setEscapeButton(QMessageBox::Cancel);
845
QCheckBox checkBox(QObject::tr("Apply answer to all"));
846
ParameterGrp::handle hGrp;
848
hGrp = App::GetApplication().GetUserParameter().
849
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("General");
850
checkBox.setChecked(hGrp->GetBool("ConfirmAll",false));
851
checkBox.blockSignals(true);
852
box.addButton(&checkBox, QMessageBox::ResetRole);
856
QAbstractButton* saveBtn = box.button(QMessageBox::Save);
857
if (saveBtn->shortcut().isEmpty()) {
858
QString text = saveBtn->text();
859
text.prepend(QLatin1Char('&'));
860
saveBtn->setShortcut(QKeySequence::mnemonic(text));
863
QAbstractButton* discardBtn = box.button(QMessageBox::Discard);
864
if (discardBtn->shortcut().isEmpty()) {
865
QString text = discardBtn->text();
866
text.prepend(QLatin1Char('&'));
867
discardBtn->setShortcut(QKeySequence::mnemonic(text));
870
int res = ConfirmSaveResult::Cancel;
874
case QMessageBox::Save:
875
res = checkBox.isChecked()?ConfirmSaveResult::SaveAll:ConfirmSaveResult::Save;
877
case QMessageBox::Discard:
878
res = checkBox.isChecked()?ConfirmSaveResult::DiscardAll:ConfirmSaveResult::Discard;
881
if(addCheckbox && res)
882
hGrp->SetBool("ConfirmAll",checkBox.isChecked());
886
bool MainWindow::closeAllDocuments (bool close)
888
auto docs = App::GetApplication().getDocuments();
890
docs = App::Document::getDependentDocuments(docs, true);
892
catch(Base::Exception &e) {
896
bool checkModify = true;
897
bool saveAll = false;
900
for (auto doc : docs) {
901
auto gdoc = Application::Instance->getDocument(doc);
904
if (!gdoc->canClose(false))
906
if (!gdoc->isModified()
907
|| doc->testStatus(App::Document::PartialDoc)
908
|| doc->testStatus(App::Document::TempDoc))
911
if (!save && checkModify) {
912
int res = confirmSave(doc->Label.getStrValue().c_str(), this, docs.size()>1);
915
case ConfirmSaveResult::Cancel:
917
case ConfirmSaveResult::SaveAll:
920
case ConfirmSaveResult::Save:
923
case ConfirmSaveResult::DiscardAll:
928
if (save && !gdoc->save())
932
if (failedSaves > 0) {
933
int ret = QMessageBox::question(
935
QObject::tr("%1 Document(s) not saved").arg(QString::number(failedSaves)),
936
QObject::tr("Some documents could not be saved. Do you want to cancel closing?"),
937
QMessageBox::Discard | QMessageBox::Cancel,
938
QMessageBox::Discard);
939
if (ret == QMessageBox::Cancel)
944
App::GetApplication().closeAllDocuments();
949
void MainWindow::activateNextWindow ()
951
auto tab = d->mdiArea->findChild<QTabBar*>();
952
if (tab && tab->count() > 0) {
953
int index = (tab->currentIndex() + 1) % tab->count();
954
tab->setCurrentIndex(index);
958
void MainWindow::activatePreviousWindow ()
960
auto tab = d->mdiArea->findChild<QTabBar*>();
961
if (tab && tab->count() > 0) {
962
int index = (tab->currentIndex() + tab->count() - 1) % tab->count();
963
tab->setCurrentIndex(index);
967
void MainWindow::activateWorkbench(const QString& name)
969
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
970
bool saveWB = hGrp->GetBool("SaveWBbyTab", false);
971
QMdiSubWindow* subWin = d->mdiArea->activeSubWindow();
972
if (subWin && saveWB) {
973
QString currWb = subWin->property("ownWB").toString();
974
if (currWb.isEmpty() || currWb != name) {
975
subWin->setProperty("ownWB", name);
979
Q_EMIT workbenchActivated(name);
983
void MainWindow::whatsThis()
985
QWhatsThis::enterWhatsThisMode();
988
void MainWindow::showDocumentation(const QString& help)
990
Base::PyGILStateLocker lock;
991
PyObject* module = PyImport_ImportModule("Help");
994
Gui::Command::addModule(Gui::Command::Gui,"Help");
995
Gui::Command::doCommand(Gui::Command::Gui,"Help.show(\"%s\")", help.toStdString().c_str());
1000
if (url.scheme().isEmpty()) {
1001
QMessageBox msgBox(getMainWindow());
1002
msgBox.setWindowTitle(tr("Help addon needed!"));
1003
msgBox.setText(tr("The Help system of %1 is now handled by the \"Help\" addon. "
1004
"It can easily be installed via the Addons Manager").arg(QString(qApp->applicationName())));
1005
QAbstractButton* pButtonAddonMgr = msgBox.addButton(tr("Open Addon Manager"), QMessageBox::YesRole);
1006
msgBox.addButton(QMessageBox::Ok);
1008
if (msgBox.clickedButton() == pButtonAddonMgr) {
1009
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Addons");
1010
hGrp->SetASCII("SelectedAddon", "Help");
1011
Gui::Command::doCommand(Gui::Command::Gui,"Gui.runCommand('Std_AddonMgr',0)");
1015
QDesktopServices::openUrl(url);
1020
bool MainWindow::event(QEvent *e)
1022
if (e->type() == QEvent::EnterWhatsThisMode) {
1027
d->whatstext.clear();
1028
if (!d->whatsthis) {
1029
d-> whatsthis = true;
1030
qApp->installEventFilter(this);
1033
else if (e->type() == QEvent::LeaveWhatsThisMode) {
1038
else if (e->type() == QEvent::WhatsThisClicked) {
1039
auto wt = static_cast<QWhatsThisClickedEvent*>(e);
1040
showDocumentation(wt->href());
1042
else if (e->type() == QEvent::ApplicationWindowIconChange) {
1044
this->setWindowIcon(QApplication::windowIcon());
1045
Command* about = Application::Instance->commandManager().getCommandByName("Std_About");
1047
Action* action = about->getAction();
1048
if (action) action->setIcon(QApplication::windowIcon());
1051
else if (e->type() == Spaceball::ButtonEvent::ButtonEventType) {
1052
auto buttonEvent = dynamic_cast<Spaceball::ButtonEvent *>(e);
1055
buttonEvent->setHandled(true);
1057
if (buttonEvent->buttonStatus() != Spaceball::BUTTON_PRESSED)
1059
ParameterGrp::handle group = App::GetApplication().GetUserParameter().GetGroup("BaseApp")->
1060
GetGroup("Spaceball")->GetGroup("Buttons");
1061
QByteArray groupName(QVariant(buttonEvent->buttonNumber()).toByteArray());
1062
if (group->HasGroup(groupName.data())) {
1063
ParameterGrp::handle commandGroup = group->GetGroup(groupName.data());
1064
std::string commandName(commandGroup->GetASCII("Command"));
1065
if (commandName.empty())
1068
Application::Instance->commandManager().runCommandByName(commandName.c_str());
1073
else if (e->type() == Spaceball::MotionEvent::MotionEventType) {
1074
auto motionEvent = dynamic_cast<Spaceball::MotionEvent *>(e);
1077
motionEvent->setHandled(true);
1078
Gui::Document *doc = Application::Instance->activeDocument();
1081
auto temp = dynamic_cast<View3DInventor *>(doc->getActiveView());
1084
View3DInventorViewer *view = temp->getViewer();
1086
Spaceball::MotionEvent anotherEvent(*motionEvent);
1087
qApp->sendEvent(view, &anotherEvent);
1090
}else if(e->type() == QEvent::StatusTip) {
1092
if(std::abs(d->currentStatusType) <= MainWindow::Wrn)
1095
return QMainWindow::event(e);
1098
bool MainWindow::eventFilter(QObject* o, QEvent* e)
1101
if (e->type() == QEvent::WindowStateChange) {
1104
auto view = qobject_cast<MDIView*>(o);
1106
Qt::WindowStates oldstate = static_cast<QWindowStateChangeEvent*>(e)->oldState();
1107
Qt::WindowStates newstate = view->windowState();
1108
if (oldstate != newstate)
1109
Q_EMIT windowStateChanged(view);
1117
if (e->type() == QEvent::WhatsThis) {
1118
if (!o->isWidgetType())
1121
auto w = static_cast<QWidget *>(o);
1122
d->whatstext = w->whatsThis();
1124
if (e->type() == QEvent::WhatsThisClicked) {
1126
if (o->isWidgetType() && qobject_cast<QWidget*>(o)->isWindow()) {
1128
QApplication::sendEvent(this, e);
1133
if (o->inherits("QMenu") && QWhatsThis::inWhatsThisMode()) {
1134
bool whatthis = false;
1135
if (e->type() == QEvent::KeyPress) {
1136
auto ke = static_cast<QKeyEvent*>(e);
1137
if (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_F1)
1140
else if (e->type() == QEvent::MouseButtonRelease)
1142
else if (e->type() == QEvent::EnterWhatsThisMode)
1145
QAction* cur = static_cast<QMenu*>(o)->activeAction();
1148
QString s = cur->whatsThis();
1150
s = static_cast<QMenu*>(o)->whatsThis();
1155
if (o->inherits("QWhatsThat") && e->type() == QEvent::Show) {
1158
if (!d->whatstext.isEmpty()) {
1159
QWhatsThisClickedEvent e(d->whatstext);
1160
QApplication::sendEvent(this, &e);
1162
static_cast<QWidget *>(o)->setAttribute(Qt::WA_OutsideWSRange);
1166
if (o->inherits("QWhatsThat") && e->type() == QEvent::Hide) {
1169
d->whatsthis = false;
1170
d->whatstext.clear();
1171
qApp->removeEventFilter(this);
1176
return QMainWindow::eventFilter(o, e);
1179
void MainWindow::addWindow(MDIView* view)
1182
bool isempty = d->mdiArea->subWindowList().isEmpty();
1183
auto child = qobject_cast<QMdiSubWindow*>(view->parentWidget());
1185
child = new QMdiSubWindow(d->mdiArea->viewport());
1186
child->setAttribute(Qt::WA_DeleteOnClose);
1187
child->setWidget(view);
1188
child->setWindowIcon(view->windowIcon());
1189
QMenu* menu = child->systemMenu();
1192
QList<QAction*> acts = menu->actions();
1193
for (auto & act : acts) {
1194
if (act->shortcut() == QKeySequence(QKeySequence::Close)) {
1195
act->setShortcuts(QList<QKeySequence>());
1200
QAction* action = menu->addAction(tr("Close All"));
1201
connect(action, &QAction::triggered, d->mdiArea, &QMdiArea::closeAllSubWindows);
1202
d->mdiArea->addSubWindow(child);
1205
connect(view, &MDIView::message, this, &MainWindow::showMessage);
1206
connect(this, &MainWindow::windowStateChanged, view, &MDIView::windowStateChanged);
1209
view->installEventFilter(this);
1213
view->showMaximized();
1224
void MainWindow::removeWindow(Gui::MDIView* view, bool close)
1227
disconnect(view, &MDIView::message, this, &MainWindow::showMessage);
1228
disconnect(this, &MainWindow::windowStateChanged, view, &MDIView::windowStateChanged);
1230
view->removeEventFilter(this);
1233
QWidget* foc = this->focusWidget();
1235
QWidget* par = foc->parentWidget();
1241
par = par->parentWidget();
1245
QWidget* parent = view->parentWidget();
1256
auto subwindow = qobject_cast<QMdiSubWindow*>(parent);
1257
if(subwindow && d->mdiArea->subWindowList().contains(subwindow)) {
1258
subwindow->setParent(nullptr);
1260
assert(!d->mdiArea->subWindowList().contains(subwindow));
1265
parent->deleteLater();
1269
void MainWindow::tabChanged(MDIView* view)
1275
void MainWindow::tabCloseRequested(int index)
1277
auto tab = d->mdiArea->findChild<QTabBar*>();
1278
if (index < 0 || index >= tab->count())
1281
const QList<QMdiSubWindow *> subWindows = d->mdiArea->subWindowList();
1282
Q_ASSERT(index < subWindows.size());
1284
QMdiSubWindow *subWindow = d->mdiArea->subWindowList().at(index);
1285
Q_ASSERT(subWindow);
1290
void MainWindow::onSetActiveSubWindow(QWidget *window)
1294
d->mdiArea->setActiveSubWindow(qobject_cast<QMdiSubWindow *>(window));
1298
void MainWindow::setActiveWindow(MDIView* view)
1300
if (!view || d->activeView == view)
1302
onSetActiveSubWindow(view->parentWidget());
1303
d->activeView = view;
1304
Application::Instance->viewActivated(view);
1307
void MainWindow::onWindowActivated(QMdiSubWindow* mdi)
1310
setWindowTitle(QString());
1311
setWindowModified(false);
1315
auto view = dynamic_cast<MDIView*>(mdi->widget());
1320
d->activeView = view;
1321
Application::Instance->viewActivated(view);
1324
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
1325
bool saveWB = hGrp->GetBool("SaveWBbyTab", false);
1327
QString currWb = mdi->property("ownWB").toString();
1328
if (! currWb.isEmpty()) {
1329
this->activateWorkbench(currWb);
1332
mdi->setProperty("ownWB", QString::fromStdString(WorkbenchManager::instance()->active()->name()));
1349
updateActions(true);
1352
void MainWindow::onWindowsMenuAboutToShow()
1354
QList<QMdiSubWindow*> windows = d->mdiArea->subWindowList(QMdiArea::CreationOrder);
1355
QWidget* active = d->mdiArea->activeSubWindow();
1358
CommandManager& cMgr = Application::Instance->commandManager();
1359
Command* cmd = cMgr.getCommandByName("Std_WindowsMenu");
1360
QList<QAction*> actions = qobject_cast<ActionGroup*>(cmd->getAction())->actions();
1363
static bool firstShow = true;
1366
QAction* last = actions.isEmpty() ? 0 : actions.last();
1367
for (const auto & action : actions) {
1370
connect(action, &QAction::triggered, d->windowMapper, qOverload<>(&QSignalMapper::map));
1374
int numWindows = std::min<int>(actions.count()-1, windows.count());
1375
for (int index = 0; index < numWindows; index++) {
1376
QWidget* child = windows.at(index);
1377
QAction* action = actions.at(index);
1379
QString title = child->windowTitle();
1380
int lastIndex = title.lastIndexOf(QString::fromLatin1("[*]"));
1381
if (lastIndex > 0) {
1382
title = title.left(lastIndex);
1383
if (child->isWindowModified())
1384
title = QString::fromLatin1("%1*").arg(title);
1387
text = QString::fromLatin1("&%1 %2").arg(index+1).arg(title);
1389
text = QString::fromLatin1("%1 %2").arg(index+1).arg(title);
1390
action->setText(text);
1391
action->setVisible(true);
1392
action->setChecked(child == active);
1393
d->windowMapper->setMapping(action, child);
1397
for (int index = numWindows; index < actions.count(); index++)
1398
actions[index]->setVisible(false);
1401
actions.last()->setVisible(true);
1404
void MainWindow::onToolBarMenuAboutToShow()
1406
auto menu = static_cast<QMenu*>(sender());
1408
QList<QToolBar*> dock = this->findChildren<QToolBar*>();
1409
for (const auto & it : dock) {
1410
if (it->parentWidget() == this) {
1411
QAction* action = it->toggleViewAction();
1412
action->setToolTip(tr("Toggles this toolbar"));
1413
action->setStatusTip(tr("Toggles this toolbar"));
1414
action->setWhatsThis(tr("Toggles this toolbar"));
1415
menu->addAction(action);
1419
menu->addSeparator();
1421
Application::Instance->commandManager().getCommandByName("Std_ToggleToolBarLock")->addTo(menu);
1424
void MainWindow::onDockWindowMenuAboutToShow()
1426
auto menu = static_cast<QMenu*>(sender());
1428
QList<QDockWidget*> dock = this->findChildren<QDockWidget*>();
1429
for (auto & it : dock) {
1430
QAction* action = it->toggleViewAction();
1431
action->setToolTip(tr("Toggles this dockable window"));
1432
action->setStatusTip(tr("Toggles this dockable window"));
1433
action->setWhatsThis(tr("Toggles this dockable window"));
1434
menu->addAction(action);
1438
void MainWindow::setDockWindowMenu(QMenu* menu)
1440
connect(menu, &QMenu::aboutToShow, this, &MainWindow::onDockWindowMenuAboutToShow);
1443
void MainWindow::setToolBarMenu(QMenu* menu)
1445
connect(menu, &QMenu::aboutToShow, this, &MainWindow::onToolBarMenuAboutToShow);
1448
void MainWindow::setWindowsMenu(QMenu* menu)
1450
connect(menu, &QMenu::aboutToShow, this, &MainWindow::onWindowsMenuAboutToShow);
1453
QList<QWidget*> MainWindow::windows(QMdiArea::WindowOrder order) const
1455
QList<QWidget*> mdis;
1456
QList<QMdiSubWindow*> wnds = d->mdiArea->subWindowList(order);
1457
for (const auto & wnd : wnds) {
1458
mdis << wnd->widget();
1463
MDIView* MainWindow::activeWindow() const
1466
return d->activeView;
1469
void MainWindow::closeEvent (QCloseEvent * e)
1471
Application::Instance->tryClose(e);
1472
if (e->isAccepted()) {
1474
QList<QDialog*> dialogs = this->findChildren<QDialog*>();
1477
QVector< QPointer<QDialog> > dialogs_ptr;
1478
for (const auto & dialog : dialogs) {
1479
dialogs_ptr.append(dialog);
1481
for (auto & it : dialogs_ptr) {
1485
QList<MDIView*> mdis = this->findChildren<MDIView*>();
1487
for (auto & mdi : mdis) {
1492
if (Workbench* wb = WorkbenchManager::instance()->active())
1493
wb->removeTaskWatcher();
1495
Q_EMIT mainWindowClosed();
1496
d->activityTimer->stop();
1503
saveWindowSettings();
1505
delete d->assistant;
1506
d->assistant = nullptr;
1509
QVariant prop = this->property("x-documentobject-file");
1510
if (!prop.isNull()) {
1511
Base::FileInfo fi((const char*)prop.toByteArray());
1516
if (this->property("QuitOnClosed").isValid()) {
1517
QApplication::closeAllWindows();
1523
void MainWindow::showEvent(QShowEvent* e)
1525
std::clog << "Show main window" << std::endl;
1526
QMainWindow::showEvent(e);
1529
void MainWindow::hideEvent(QHideEvent* e)
1531
std::clog << "Hide main window" << std::endl;
1532
QMainWindow::hideEvent(e);
1535
void MainWindow::processMessages(const QList<QByteArray> & msg)
1540
std::list<std::string> files;
1541
QByteArray action("OpenFile:");
1542
for (const auto & it : msg) {
1543
if (it.startsWith(action))
1544
files.emplace_back(it.mid(action.size()).constData());
1546
files = App::Application::processFiles(files);
1547
for (const auto & file : files) {
1548
QString filename = QString::fromUtf8(file.c_str(), file.size());
1549
FileDialog::setWorkingDirectory(filename);
1552
catch (const Base::SystemExitException&) {
1556
void MainWindow::delayedStartup()
1559
if (App::Application::Config()["RunMode"] == "Internal") {
1560
QTimer::singleShot(1000, this, []{
1562
Base::Interpreter().runString(
1565
"import QtUnitGui\n\n"
1566
"testCase = FreeCAD.ConfigGet(\"TestCase\")\n"
1567
"QtUnitGui.addTest(testCase)\n"
1568
"QtUnitGui.setTest(testCase)\n"
1569
"result = QtUnitGui.runTest()\n"
1570
"sys.stdout.flush()\n"
1571
"sys.exit(0 if result else 1)");
1573
catch (const Base::SystemExitException&) {
1576
catch (const Base::Exception& e) {
1577
e.ReportException();
1585
std::list<std::string> files = App::Application::getCmdLineFiles();
1586
files = App::Application::processFiles(files);
1587
for (const auto & file : files) {
1588
QString filename = QString::fromUtf8(file.c_str(), file.size());
1589
FileDialog::setWorkingDirectory(filename);
1592
catch (const Base::SystemExitException&) {
1596
const std::map<std::string,std::string>& cfg = App::Application::Config();
1597
auto it = cfg.find("StartHidden");
1598
if (it != cfg.end()) {
1599
QApplication::quit();
1604
Application::Instance->checkForDeprecatedSettings();
1607
ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("Document");
1608
if (hGrp->GetBool("CreateNewDoc", false)) {
1609
if (App::GetApplication().getDocuments().empty()){
1610
Application::Instance->commandManager().runCommandByName("Std_New");
1614
if (hGrp->GetBool("RecoveryEnabled", true)) {
1615
Application::Instance->checkForPreviousCrashes();
1619
void MainWindow::appendRecentFile(const QString& filename)
1621
auto recent = this->findChild<RecentFilesAction *>
1622
(QString::fromLatin1("recentFiles"));
1624
recent->appendFile(filename);
1628
void MainWindow::appendRecentMacro(const QString& filename)
1630
auto recent = this->findChild<RecentMacrosAction *>
1631
(QString::fromLatin1("recentMacros"));
1633
recent->appendFile(filename);
1637
void MainWindow::updateActions(bool delay)
1643
if (!d->activityTimer->isActive()) {
1647
if (d->activityTimer->thread() != QThread::currentThread()) {
1648
QMetaObject::invokeMethod(d->activityTimer, "start", Qt::QueuedConnection,
1652
d->activityTimer->start(150);
1656
if (!d->actionUpdateDelay)
1657
d->actionUpdateDelay = 1;
1660
d->actionUpdateDelay = -1;
1664
void MainWindow::_updateActions()
1666
if (isVisible() && d->actionUpdateDelay <= 0) {
1667
FC_LOG("update actions");
1668
d->activityTimer->stop();
1669
Application::Instance->commandManager().testActive();
1672
d->actionUpdateDelay = 0;
1674
if (auto view = activeWindow()) {
1675
setWindowTitle(view->buildWindowTitle());
1676
if (auto document = view->getGuiDocument()) {
1677
setWindowModified(document->isModified());
1682
void MainWindow::updateEditorActions()
1684
Command* cmd = nullptr;
1685
CommandManager& mgr = Application::Instance->commandManager();
1687
cmd = mgr.getCommandByName("Std_Cut");
1688
if (cmd) cmd->testActive();
1690
cmd = mgr.getCommandByName("Std_Copy");
1691
if (cmd) cmd->testActive();
1693
cmd = mgr.getCommandByName("Std_Paste");
1694
if (cmd) cmd->testActive();
1696
cmd = mgr.getCommandByName("Std_Undo");
1697
if (cmd) cmd->testActive();
1699
cmd = mgr.getCommandByName("Std_Redo");
1700
if (cmd) cmd->testActive();
1703
void MainWindow::switchToTopLevelMode()
1705
QList<QDockWidget*> dw = this->findChildren<QDockWidget*>();
1706
for (auto & it : dw) {
1707
it->setParent(nullptr, Qt::Window);
1710
QList<QWidget*> mdi = getMainWindow()->windows();
1711
for (auto & it : mdi) {
1712
it->setParent(nullptr, Qt::Window);
1717
void MainWindow::switchToDockedMode()
1720
QWidgetList toplevel = QApplication::topLevelWidgets();
1721
for (const auto & it : toplevel) {
1722
auto view = qobject_cast<MDIView*>(it);
1724
view->setCurrentViewMode(MDIView::Child);
1728
void MainWindow::loadWindowSettings()
1730
QString vendor = QString::fromUtf8(App::Application::Config()["ExeVendor"].c_str());
1731
QString application = QString::fromUtf8(App::Application::Config()["ExeName"].c_str());
1732
int major = (QT_VERSION >> 0x10) & 0xff;
1733
int minor = (QT_VERSION >> 0x08) & 0xff;
1734
QString qtver = QStringLiteral("Qt%1.%2").arg(major).arg(minor);
1735
QSettings config(vendor, application);
1737
QRect rect = QApplication::primaryScreen()->availableGeometry();
1738
int maxHeight = rect.height();
1739
int maxWidth = rect.width();
1741
config.beginGroup(qtver);
1742
QPoint pos = config.value(QStringLiteral("Position"), this->pos()).toPoint();
1743
maxWidth -= pos.x();
1744
maxHeight -= pos.y();
1745
QSize size = config.value(QStringLiteral("Size"), QSize(maxWidth, maxHeight)).toSize();
1746
bool max = config.value(QStringLiteral("Maximized"), false).toBool();
1747
bool showStatusBar = config.value(QStringLiteral("StatusBar"), true).toBool();
1748
QByteArray windowState = config.value(QStringLiteral("MainWindowState")).toByteArray();
1752
std::string geometry = d->hGrp->GetASCII("Geometry");
1753
std::istringstream iss(geometry);
1755
if (iss >> x >> y >> w >> h) {
1760
max = d->hGrp->GetBool("Maximized", max);
1761
showStatusBar = d->hGrp->GetBool("StatusBar", showStatusBar);
1762
std::string wstate = d->hGrp->GetASCII("MainWindowState");
1763
if (!wstate.empty()) {
1764
windowState = QByteArray::fromBase64(wstate.c_str());
1768
int x1{},x2{},y1{},y2{};
1770
rect.getCoords(&x1, &y1, &x2, &y2);
1771
pos.setX(qMin(qMax(pos.x(),x1-this->width()+30),x2-30));
1772
pos.setY(qMin(qMax(pos.y(),y1-10),y2-10));
1775
Base::StateLocker guard(d->_restoring);
1777
d->restoreWindowState(windowState);
1778
std::clog << "Main window restored" << std::endl;
1780
max ? showMaximized() : show();
1783
#if defined(Q_OS_WIN) && QT_VERSION < QT_VERSION_CHECK(6,0,0)
1784
if (QWindow* win = this->windowHandle()) {
1785
QWindowsWindowFunctions::setHasBorderInFullScreen(win, true);
1789
statusBar()->setVisible(showStatusBar);
1791
ToolBarManager::getInstance()->restoreState();
1792
std::clog << "Toolbars restored" << std::endl;
1794
OverlayManager::instance()->restore();
1797
bool MainWindow::isRestoringWindowState() const
1799
return d->_restoring;
1802
void MainWindowP::restoreWindowState(const QByteArray &windowState)
1804
if (windowState.isEmpty())
1807
Base::StateLocker guard(_restoring);
1810
if (Base::Console().IsMsgTypeEnabled("ReportOutput", Base::ConsoleSingleton::MsgType_Wrn)) {
1811
Base::Console().SetEnabledMsgType("ReportOutput", Base::ConsoleSingleton::MsgType_Wrn, false);
1812
getMainWindow()->restoreState(windowState);
1813
Base::Console().SetEnabledMsgType("ReportOutput", Base::ConsoleSingleton::MsgType_Wrn, true);
1815
getMainWindow()->restoreState(windowState);
1817
Base::ConnectionBlocker block(connParam);
1819
hGrp->SetBool("WindowStateRestored", !hGrp->GetBool("WindowStateRestored", false));
1822
void MainWindow::saveWindowSettings(bool canDelay)
1824
if (isRestoringWindowState())
1828
d->saveStateTimer.start(100);
1832
QString vendor = QString::fromUtf8(App::Application::Config()["ExeVendor"].c_str());
1833
QString application = QString::fromUtf8(App::Application::Config()["ExeName"].c_str());
1834
int major = (QT_VERSION >> 0x10) & 0xff;
1835
int minor = (QT_VERSION >> 0x08) & 0xff;
1836
QString qtver = QStringLiteral("Qt%1.%2").arg(major).arg(minor);
1837
QSettings config(vendor, application);
1840
config.beginGroup(qtver);
1841
config.setValue(QStringLiteral("Size"), this->size());
1842
config.setValue(QStringLiteral("Position"), this->pos());
1843
config.setValue(QStringLiteral("Maximized"), this->isMaximized());
1844
config.setValue(QStringLiteral("MainWindowState"), this->saveState());
1845
config.setValue(QStringLiteral("StatusBar"), this->statusBar()->isVisible());
1852
Base::ConnectionBlocker block(d->connParam);
1853
d->hGrp->SetBool("Maximized", this->isMaximized());
1854
d->hGrp->SetBool("StatusBar", this->statusBar()->isVisible());
1855
d->hGrp->SetASCII("MainWindowState", this->saveState().toBase64().constData());
1857
std::ostringstream ss;
1858
QRect rect(this->pos(), this->size());
1859
ss << rect.left() << " " << rect.top() << " " << rect.width() << " " << rect.height();
1860
d->hGrp->SetASCII("Geometry", ss.str().c_str());
1862
DockWindowManager::instance()->saveState();
1863
OverlayManager::instance()->save();
1864
ToolBarManager::getInstance()->saveState();
1867
void MainWindow::startSplasher()
1871
if (!(App::Application::Config()["Verbose"] == "Strict") &&
1872
(App::Application::Config()["RunMode"] == "Gui")) {
1873
ParameterGrp::handle hGrp = App::GetApplication().GetUserParameter().
1874
GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("General");
1876
if (hGrp->GetBool("ShowSplasher", true)) {
1877
d->splashscreen = new SplashScreen(this->splashImage());
1879
if (!hGrp->GetBool("ShowSplasherMessages", true)) {
1880
d->splashscreen->setShowMessages(false);
1883
d->splashscreen->show();
1886
d->splashscreen = nullptr;
1891
void MainWindow::stopSplasher()
1893
if (d->splashscreen) {
1894
d->splashscreen->finish(this);
1895
delete d->splashscreen;
1896
d->splashscreen = nullptr;
1900
QPixmap MainWindow::aboutImage() const
1903
QPixmap about_image;
1904
QFileInfo fi(QString::fromLatin1("images:about_image.png"));
1905
if (fi.isFile() && fi.exists())
1906
about_image.load(fi.filePath(), "PNG");
1908
std::string about_path = App::Application::Config()["AboutImage"];
1909
if (!about_path.empty() && about_image.isNull()) {
1910
QString path = QString::fromUtf8(about_path.c_str());
1911
if (QDir(path).isRelative()) {
1912
QString home = QString::fromStdString(App::Application::getHomePath());
1913
path = QFileInfo(QDir(home), path).absoluteFilePath();
1915
about_image.load(path);
1918
if (about_image.isNull()) {
1919
about_image = Gui::BitmapFactory().pixmap(about_path.c_str());
1936
void MainWindow::renderDevBuildWarning(
1938
const QPoint startPosition,
1939
const QSize maxSize)
1942
QColor fader (Qt::black);
1943
constexpr float halfDensity (0.5);
1944
fader.setAlphaF(halfDensity);
1945
QBrush fillBrush(fader, Qt::BrushStyle::SolidPattern);
1946
painter.setBrush(fillBrush);
1949
const auto devWarningLine1 = tr("WARNING: This is a development version.");
1950
const auto devWarningLine2 = tr("Please do not use it in a production environment.");
1951
QFontMetrics fontMetrics(painter.font());
1952
int padding = QtTools::horizontalAdvance(fontMetrics, QLatin1String("M"));
1953
int line1Width = QtTools::horizontalAdvance(fontMetrics, devWarningLine1);
1954
int line2Width = QtTools::horizontalAdvance(fontMetrics, devWarningLine2);
1955
int boxWidth = std::max(line1Width,line2Width) + 2 * padding;
1956
int lineHeight = fontMetrics.lineSpacing();
1957
if (boxWidth > maxSize.width()) {
1961
float reductionFactor = static_cast<float>(maxSize.width()) / static_cast<float>(boxWidth);
1962
int newFontSize = static_cast<int>(painter.font().pointSize() * reductionFactor);
1963
padding *= reductionFactor;
1964
QFont newFont = painter.font();
1965
newFont.setPointSize(newFontSize);
1966
painter.setFont(newFont);
1967
lineHeight = painter.fontMetrics().lineSpacing();
1968
boxWidth = maxSize.width();
1970
constexpr float lineExpansionFactor(2.3F);
1971
int boxHeight = static_cast<int>(lineHeight*lineExpansionFactor);
1974
painter.drawRect(startPosition.x(), startPosition.y(), boxWidth, boxHeight);
1975
painter.drawText(startPosition.x()+padding, startPosition.y()+lineHeight, devWarningLine1);
1976
painter.drawText(startPosition.x()+padding, startPosition.y()+2*lineHeight, devWarningLine2);
1979
QPixmap MainWindow::splashImage() const
1982
QPixmap splash_image;
1983
QFileInfo fi(QString::fromLatin1("images:splash_image.png"));
1984
if (fi.isFile() && fi.exists())
1985
splash_image.load(fi.filePath(), "PNG");
1988
std::string splash_path = App::Application::Config()["SplashScreen"];
1989
if (splash_image.isNull()) {
1990
QString path = QString::fromUtf8(splash_path.c_str());
1991
if (QDir(path).isRelative()) {
1992
QString home = QString::fromStdString(App::Application::getHomePath());
1993
path = QFileInfo(QDir(home), path).absoluteFilePath();
1996
splash_image.load(path);
2000
float pixelRatio (1.0);
2001
if (splash_image.isNull()) {
2002
if (qApp->devicePixelRatio() > 1.0) {
2004
splash_path += "2x";
2005
splash_image = Gui::BitmapFactory().pixmap(splash_path.c_str());
2006
splash_image.setDevicePixelRatio(2.0);
2010
splash_image = Gui::BitmapFactory().pixmap(splash_path.c_str());
2015
std::map<std::string,std::string>::const_iterator tc = App::Application::Config().find("SplashInfoColor");
2016
if (tc != App::Application::Config().end()) {
2017
QString title = qApp->applicationName();
2018
QString major = QString::fromLatin1(App::Application::Config()["BuildVersionMajor"].c_str());
2019
QString minor = QString::fromLatin1(App::Application::Config()["BuildVersionMinor"].c_str());
2020
QString point = QString::fromLatin1(App::Application::Config()["BuildVersionPoint"].c_str());
2021
QString suffix = QString::fromLatin1(App::Application::Config()["BuildVersionSuffix"].c_str());
2022
QString version = QString::fromLatin1("%1.%2.%3%4").arg(major, minor, point, suffix);
2023
QString position, fontFamily;
2025
std::map<std::string,std::string>::const_iterator te = App::Application::Config().find("SplashInfoExeName");
2026
std::map<std::string,std::string>::const_iterator tv = App::Application::Config().find("SplashInfoVersion");
2027
std::map<std::string,std::string>::const_iterator tp = App::Application::Config().find("SplashInfoPosition");
2028
std::map<std::string,std::string>::const_iterator tf = App::Application::Config().find("SplashInfoFont");
2029
if (te != App::Application::Config().end())
2030
title = QString::fromUtf8(te->second.c_str());
2031
if (tv != App::Application::Config().end())
2032
version = QString::fromUtf8(tv->second.c_str());
2033
if (tp != App::Application::Config().end())
2034
position = QString::fromUtf8(tp->second.c_str());
2035
if (tf != App::Application::Config().end())
2036
fontFamily = QString::fromUtf8(tf->second.c_str());
2039
painter.begin(&splash_image);
2040
if (!fontFamily.isEmpty()) {
2041
QFont font = painter.font();
2042
if (font.fromString(fontFamily))
2043
painter.setFont(font);
2046
QFont fontExe = painter.font();
2047
fontExe.setPointSizeF(20.0);
2048
QFontMetrics metricExe(fontExe);
2049
int l = QtTools::horizontalAdvance(metricExe, title);
2050
if (title == QLatin1String("FreeCAD")) {
2053
int w = splash_image.width();
2054
int h = splash_image.height();
2056
QFont fontVer = painter.font();
2057
fontVer.setPointSizeF(14.0);
2058
QFontMetrics metricVer(fontVer);
2059
int v = QtTools::horizontalAdvance(metricVer, version);
2062
QRegularExpression rx(QLatin1String("(\\d+).(\\d+)"));
2063
auto match = rx.match(position);
2064
if (match.hasMatch()) {
2065
x = match.captured(1).toInt();
2066
y = match.captured(2).toInt();
2069
x = w - (l + v + 10);
2074
color.setNamedColor(QString::fromLatin1(tc->second.c_str()));
2075
if (color.isValid()) {
2076
painter.setPen(color);
2077
painter.setFont(fontExe);
2078
if (title != QLatin1String("FreeCAD")) {
2080
painter.drawText(x, y, title);
2082
painter.setFont(fontVer);
2083
painter.drawText(x + (l + 5), y, version);
2084
if (suffix == QLatin1String("dev")) {
2085
const int lineHeight = metricVer.lineSpacing();
2086
const int padding {10};
2087
QPoint startPosition(padding, y + lineHeight);
2088
QSize maxSize(w/pixelRatio - 2*padding, lineHeight * 3);
2089
MainWindow::renderDevBuildWarning(painter, startPosition, maxSize);
2095
return splash_image;
2101
void MainWindow::dropEvent (QDropEvent* e)
2103
const QMimeData* data = e->mimeData();
2104
if (data->hasUrls()) {
2106
loadUrls(App::GetApplication().getActiveDocument(), data->urls());
2109
QMainWindow::dropEvent(e);
2113
void MainWindow::dragEnterEvent (QDragEnterEvent * e)
2116
const QMimeData* data = e->mimeData();
2117
if (data->hasUrls()) {
2125
static QLatin1String _MimeDocObj("application/x-documentobject");
2126
static QLatin1String _MimeDocObjX("application/x-documentobject-x");
2127
static QLatin1String _MimeDocObjFile("application/x-documentobject-file");
2128
static QLatin1String _MimeDocObjXFile("application/x-documentobject-x-file");
2130
QMimeData * MainWindow::createMimeDataFromSelection () const
2132
std::vector<App::DocumentObject*> sel;
2133
std::set<App::DocumentObject*> objSet;
2134
for(auto &s : Selection().getCompleteSelection()) {
2135
if(s.pObject && s.pObject->isAttachedToDocument() && objSet.insert(s.pObject).second)
2136
sel.push_back(s.pObject);
2141
auto all = App::Document::getDependencyList(sel);
2142
if (all.size() > sel.size()) {
2143
DlgObjectSelection dlg(sel,getMainWindow());
2144
if(dlg.exec()!=QDialog::Accepted)
2146
sel = dlg.getSelections();
2151
std::vector<App::Document*> unsaved;
2152
bool hasXLink = App::PropertyXLink::hasXLink(sel,&unsaved);
2153
if(!unsaved.empty()) {
2154
QMessageBox::critical(getMainWindow(), tr("Unsaved document"),
2155
tr("The exported object contains external link. Please save the document"
2156
"at least once before exporting."));
2160
unsigned int memsize=1000;
2161
for (const auto & it : sel)
2162
memsize += it->getMemSize();
2165
bool use_buffer=(memsize < 0xA00000);
2169
res.reserve(memsize);
2171
catch (const std::bad_alloc &) {
2179
mime = hasXLink?_MimeDocObjX:_MimeDocObj;
2180
Base::ByteArrayOStreambuf buf(res);
2181
std::ostream str(&buf);
2183
App::Document* doc = sel.front()->getDocument();
2184
MergeDocuments mimeView(doc);
2185
doc->exportObjects(sel, str);
2188
mime = hasXLink?_MimeDocObjXFile:_MimeDocObjFile;
2189
static Base::FileInfo fi(App::Application::getTempFileName());
2190
Base::ofstream str(fi, std::ios::out | std::ios::binary);
2192
App::Document* doc = sel.front()->getDocument();
2193
MergeDocuments mimeView(doc);
2194
doc->exportObjects(sel, str);
2196
res = fi.filePath().c_str();
2200
const_cast<MainWindow*>(this)->setProperty("x-documentobject-file", res);
2203
auto mimeData = new QMimeData();
2204
mimeData->setData(mime,res);
2208
bool MainWindow::canInsertFromMimeData (const QMimeData * source) const
2212
return source->hasUrls() ||
2213
source->hasFormat(_MimeDocObj) || source->hasFormat(_MimeDocObjX) ||
2214
source->hasFormat(_MimeDocObjFile) || source->hasFormat(_MimeDocObjXFile);
2217
void MainWindow::insertFromMimeData (const QMimeData * mimeData)
2221
bool fromDoc = false;
2222
bool hasXLink = false;
2224
if(mimeData->hasFormat(_MimeDocObj))
2225
format = _MimeDocObj;
2226
else if(mimeData->hasFormat(_MimeDocObjX)) {
2227
format = _MimeDocObjX;
2229
}else if(mimeData->hasFormat(_MimeDocObjFile)) {
2230
format = _MimeDocObjFile;
2232
}else if(mimeData->hasFormat(_MimeDocObjXFile)) {
2233
format = _MimeDocObjXFile;
2237
if (mimeData->hasUrls())
2238
loadUrls(App::GetApplication().getActiveDocument(), mimeData->urls());
2242
App::Document* doc = App::GetApplication().getActiveDocument();
2243
if(!doc) doc = App::GetApplication().newDocument();
2245
if(hasXLink && !doc->isSaved()) {
2246
int ret = QMessageBox::question(getMainWindow(), tr("Unsaved document"),
2247
tr("To link to external objects, the document must be saved at least once.\n"
2248
"Do you want to save the document now?"),
2249
QMessageBox::Yes,QMessageBox::No);
2250
if(ret != QMessageBox::Yes || !Application::Instance->getDocument(doc)->saveAs())
2254
QByteArray res = mimeData->data(format);
2256
doc->openTransaction("Paste");
2257
Base::ByteArrayIStreambuf buf(res);
2258
std::istream in(nullptr);
2260
MergeDocuments mimeView(doc);
2261
std::vector<App::DocumentObject*> newObj = mimeView.importObjects(in);
2262
std::vector<App::DocumentObjectGroup*> grp = Gui::Selection().getObjectsOfType<App::DocumentObjectGroup>();
2263
if (grp.size() == 1) {
2264
Gui::Document* gui = Application::Instance->getDocument(doc);
2266
gui->addRootObjectsToGroup(newObj, grp.front());
2268
doc->commitTransaction();
2271
QByteArray res = mimeData->data(format);
2273
doc->openTransaction("Paste");
2274
Base::FileInfo fi((const char*)res);
2275
Base::ifstream str(fi, std::ios::in | std::ios::binary);
2276
MergeDocuments mimeView(doc);
2277
std::vector<App::DocumentObject*> newObj = mimeView.importObjects(str);
2279
std::vector<App::DocumentObjectGroup*> grp = Gui::Selection().getObjectsOfType<App::DocumentObjectGroup>();
2280
if (grp.size() == 1) {
2281
Gui::Document* gui = Application::Instance->getDocument(doc);
2283
gui->addRootObjectsToGroup(newObj, grp.front());
2285
doc->commitTransaction();
2289
void MainWindow::setUrlHandler(const QString &scheme, Gui::UrlHandler* handler)
2291
d->urlHandler[scheme] = handler;
2294
void MainWindow::unsetUrlHandler(const QString &scheme)
2296
d->urlHandler.remove(scheme);
2299
void MainWindow::loadUrls(App::Document* doc, const QList<QUrl>& urls)
2302
for (const auto & it : urls) {
2303
QMap<QString, QPointer<UrlHandler> >::iterator jt = d->urlHandler.find(it.scheme());
2304
if (jt != d->urlHandler.end() && !jt->isNull()) {
2306
(*jt)->openUrl(doc, it);
2310
QFileInfo info(it.toLocalFile());
2311
if (info.exists() && info.isFile()) {
2312
if (info.isSymLink())
2313
info.setFile(info.symLinkTarget());
2314
std::vector<std::string> module = App::GetApplication()
2315
.getImportModules(info.completeSuffix().toLatin1());
2316
if (module.empty()) {
2317
module = App::GetApplication()
2318
.getImportModules(info.suffix().toLatin1());
2320
if (!module.empty()) {
2322
files << info.absoluteFilePath();
2325
Base::Console().Message("No support to load file '%s'\n",
2326
(const char*)info.absoluteFilePath().toUtf8());
2329
else if (it.scheme().toLower() == QLatin1String("http")) {
2330
Gui::Dialog::DownloadManager* dm = Gui::Dialog::DownloadManager::getInstance();
2331
dm->download(dm->redirectUrl(it));
2334
else if (it.scheme().toLower() == QLatin1String("https")) {
2336
QUrlQuery urlq(url);
2337
if (urlq.hasQueryItem(QLatin1String("sid"))) {
2338
urlq.removeAllQueryItems(QLatin1String("sid"));
2340
url.setScheme(QLatin1String("http"));
2342
Gui::Dialog::DownloadManager* dm = Gui::Dialog::DownloadManager::getInstance();
2343
dm->download(dm->redirectUrl(url));
2346
else if (it.scheme().toLower() == QLatin1String("ftp")) {
2347
Gui::Dialog::DownloadManager::getInstance()->download(it);
2351
QByteArray docName = doc ? QByteArray(doc->getName()) : qApp->translate("StdCmdNew","Unnamed").toUtf8();
2352
SelectModule::Dict dict = SelectModule::importHandler(files);
2354
for (SelectModule::Dict::iterator it = dict.begin(); it != dict.end(); ++it) {
2356
Application::Instance->importFrom(it.key().toUtf8(), docName, it.value().toLatin1());
2360
void MainWindow::changeEvent(QEvent *e)
2362
if (e->type() == QEvent::LanguageChange) {
2363
d->sizeLabel->setText(tr("Dimension"));
2365
CommandManager& rclMan = Application::Instance->commandManager();
2366
std::vector<Command*> cmd = rclMan.getAllCommands();
2367
for (auto & it : cmd)
2368
it->languageChange();
2371
Workbench* wb = WorkbenchManager::instance()->active();
2372
if (wb) wb->retranslate();
2374
else if (e->type() == QEvent::ActivationChange) {
2375
if (isActiveWindow()) {
2376
QMdiSubWindow* mdi = d->mdiArea->currentSubWindow();
2378
auto view = dynamic_cast<MDIView*>(mdi->widget());
2379
if (view && getMainWindow()->activeWindow() != view) {
2380
d->activeView = view;
2381
Application::Instance->viewActivated(view);
2387
QMainWindow::changeEvent(e);
2391
void MainWindow::clearStatus() {
2392
d->currentStatusType = 100;
2393
statusBar()->setStyleSheet(QString::fromLatin1("#statusBar{}"));
2396
void MainWindow::statusMessageChanged() {
2397
if(d->currentStatusType<0)
2398
d->currentStatusType = -d->currentStatusType;
2403
d->statusTimer->stop();
2408
void MainWindow::showMessage(const QString& message, int timeout) {
2409
if(QApplication::instance()->thread() != QThread::currentThread()) {
2410
QApplication::postEvent(this, new CustomMessageEvent(MainWindow::Tmp,message,timeout));
2413
d->actionLabel->setText(message.simplified());
2415
d->actionTimer->setSingleShot(true);
2416
d->actionTimer->start(timeout);
2418
d->actionTimer->stop();
2421
void MainWindow::showStatus(int type, const QString& message)
2423
if(QApplication::instance()->thread() != QThread::currentThread()) {
2424
QApplication::postEvent(this,
2425
new CustomMessageEvent(type,message));
2429
if(d->currentStatusType < type)
2432
d->statusTimer->setSingleShot(true);
2435
d->statusTimer->start(timeout);
2437
QFontMetrics fm(statusBar()->font());
2438
QString msg = fm.elidedText(message, Qt::ElideMiddle, this->d->actionLabel->width());
2440
case MainWindow::Err:
2441
statusBar()->setStyleSheet(d->status->err);
2443
case MainWindow::Wrn:
2444
statusBar()->setStyleSheet(d->status->wrn);
2446
case MainWindow::Pane:
2447
statusBar()->setStyleSheet(QString::fromLatin1("#statusBar{}"));
2450
statusBar()->setStyleSheet(d->status->msg);
2453
d->currentStatusType = -type;
2454
statusBar()->showMessage(msg.simplified(), timeout);
2459
void MainWindow::setPaneText(int i, QString text)
2462
showStatus(MainWindow::Pane, text);
2465
d->sizeLabel->setText(text);
2470
void MainWindow::setUserSchema(int userSchema)
2472
d->sizeLabel->setUserSchema(userSchema);
2476
void MainWindow::customEvent(QEvent* e)
2478
if (e->type() == QEvent::User) {
2479
auto ce = static_cast<Gui::CustomMessageEvent*>(e);
2480
QString msg = ce->message();
2481
switch(ce->type()) {
2482
case MainWindow::Log: {
2483
if (msg.startsWith(QLatin1String("#Inventor V2.1 ascii "))) {
2484
Gui::Document *d = Application::Instance->activeDocument();
2486
auto view = new ViewProviderExtern();
2488
view->setModeByString("1",msg.toLatin1().constData());
2489
d->setAnnotationViewProvider("Vdbg",view);
2497
} case MainWindow::Tmp: {
2498
showMessage(msg, ce->timeout());
2501
showStatus(ce->type(),msg);
2504
else if (e->type() == ActionStyleEvent::EventType) {
2505
QList<TaskView::TaskView*> tasks = findChildren<TaskView::TaskView*>();
2506
if (static_cast<ActionStyleEvent*>(e)->getType() == ActionStyleEvent::Clear) {
2507
for (auto & task : tasks) {
2508
task->clearActionStyle();
2512
for (auto & task : tasks) {
2513
task->restoreActionStyle();
2519
QMdiArea *MainWindow::getMdiArea() const
2524
void MainWindow::setWindowTitle(const QString& string)
2527
QString appname = QCoreApplication::applicationName();
2528
if (appname.isEmpty()) {
2529
appname = QString::fromLatin1(App::Application::Config()["ExeName"].c_str());
2533
ParameterGrp::handle hGen = +App::GetApplication().GetParameterGroupByPath(
2534
"User parameter:BaseApp/Preferences/General");
2535
bool showVersion = hGen->GetBool("ShowVersionInTitle", true);
2539
auto config = App::Application::Config();
2540
QString major = QString::fromUtf8(config["BuildVersionMajor"].c_str());
2541
QString minor = QString::fromUtf8(config["BuildVersionMinor"].c_str());
2542
QString point = QString::fromUtf8(config["BuildVersionPoint"].c_str());
2543
QString suffix = QString::fromUtf8(config["BuildVersionSuffix"].c_str());
2544
title = QString::fromUtf8("%1 %2.%3.%4%5").arg(appname, major, minor, point, suffix);
2550
if (!string.isEmpty()) {
2551
title = QString::fromUtf8("[*] %1 - %2").arg(string, title);
2554
QMainWindow::setWindowTitle(title);
2559
StatusBarObserver::StatusBarObserver()
2560
: WindowParameter("OutputWindow")
2562
msg = QString::fromLatin1("#statusBar{color: #000000}");
2563
wrn = QString::fromLatin1("#statusBar{color: #ffaa00}");
2564
err = QString::fromLatin1("#statusBar{color: #ff0000}");
2565
Base::Console().AttachObserver(this);
2566
getWindowParameter()->Attach(this);
2567
getWindowParameter()->NotifyAll();
2570
StatusBarObserver::~StatusBarObserver()
2572
getWindowParameter()->Detach(this);
2573
Base::Console().DetachObserver(this);
2576
void StatusBarObserver::OnChange(Base::Subject<const char*> & rCaller, const char* sReason)
2578
ParameterGrp& rclGrp = ((ParameterGrp&)rCaller);
2579
auto format = QString::fromLatin1("#statusBar{color: %1}");
2580
if (strcmp(sReason, "colorText") == 0) {
2581
unsigned long col = rclGrp.GetUnsigned(sReason);
2582
this->msg = format.arg(App::Color::fromPackedRGB<QColor>(col).name());
2584
else if (strcmp(sReason, "colorWarning") == 0) {
2585
unsigned long col = rclGrp.GetUnsigned(sReason);
2586
this->wrn = format.arg(App::Color::fromPackedRGB<QColor>(col).name());
2588
else if (strcmp(sReason, "colorError") == 0) {
2589
unsigned long col = rclGrp.GetUnsigned(sReason);
2590
this->err = format.arg(App::Color::fromPackedRGB<QColor>(col).name());
2592
else if (strcmp(sReason, "colorCritical") == 0) {
2593
unsigned long col = rclGrp.GetUnsigned(sReason);
2594
this->critical = format.arg(
2595
QColor((col >> 24) & 0xff, (col >> 16) & 0xff, (col >> 8) & 0xff).name());
2599
void StatusBarObserver::SendLog(const std::string& notifiername,
2600
const std::string& msg,
2601
Base::LogStyle level,
2602
Base::IntendedRecipient recipient,
2603
Base::ContentType content)
2608
if (recipient == Base::IntendedRecipient::Developer
2609
|| content == Base::ContentType::Untranslated
2610
|| content == Base::ContentType::Untranslatable)
2613
int messageType = -1;
2615
case Base::LogStyle::Warning:
2616
messageType = MainWindow::Wrn;
2618
case Base::LogStyle::Message:
2619
messageType = MainWindow::Msg;
2621
case Base::LogStyle::Error:
2622
messageType = MainWindow::Err;
2624
case Base::LogStyle::Log:
2625
messageType = MainWindow::Log;
2627
case Base::LogStyle::Critical:
2628
messageType = MainWindow::Critical;
2635
auto ev = new CustomMessageEvent(messageType, QString::fromUtf8(msg.c_str()));
2636
QApplication::postEvent(getMainWindow(), ev);
2641
int ActionStyleEvent::EventType = -1;
2643
ActionStyleEvent::ActionStyleEvent(Style type)
2644
: QEvent(QEvent::Type(EventType))
2648
ActionStyleEvent::Style ActionStyleEvent::getType() const
2654
#include "moc_MainWindow.cpp"
2655
#include "MainWindow.moc"