#include "emainwindow.h" #include #include #include #include EMainWindow::EMainWindow(QWidget * parent): QMainWindow(parent), action_show_all_tools(this), action_hide_all_tools(this), action_show_all_docks(this), action_hide_all_docks(this), first_show(true) { menu_recent = 0; action_clear_recent = new QAction(QIcon(":/icons/edit-clear.png"), tr("Clear recent list"), this); connect(action_clear_recent, SIGNAL(triggered()), this, SLOT(clearRecent())); connect(this, &QMainWindow::tabifiedDockWidgetActivated, this, [](QDockWidget*w){qDebug() << "tabifiedDockWidgetActivated" << w;}); qRegisterMetaType("Qt::DockWidgetArea"); action_show_all_tools.setText(tr("Show all")); action_show_all_docks.setText(tr("Show all")); action_hide_all_tools.setText(tr("Hide all")); action_hide_all_docks.setText(tr("Hide all")); action_show_all_tools.setIcon(QIcon(":/icons/layer-visible-on.png")); action_show_all_docks.setIcon(QIcon(":/icons/layer-visible-on.png")); action_hide_all_tools.setIcon(QIcon(":/icons/layer-visible-off.png")); action_hide_all_docks.setIcon(QIcon(":/icons/layer-visible-off.png")); max_recent = 8; setChanged(false); initMenus(); initSession(); } EMainWindow::~EMainWindow() { } void EMainWindow::setRecentFiles(const QStringList & rl) { clearRecent(); for (int i = rl.size() - 1; i >= 0; --i) addToRecent(rl[i]); } QStringList EMainWindow::recentFiles() const { QStringList ret; foreach (QAction * a, actions_recent) ret << a->data().toString(); return ret; } void EMainWindow::setRecentMenu(QMenu * m) { menu_recent = m; prepareRecent(); } void EMainWindow::showEvent(QShowEvent * e) { QWidget::showEvent(e); initMenus(); if (!first_show) return; first_show = false; QList docks(findChildren()); for (QDockWidget * d: docks) { connect(d, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(changedDock())); connect(d, SIGNAL(topLevelChanged(bool)), this, SLOT(changedDock())); connect(d, SIGNAL(visibilityChanged(bool)), this, SLOT(changedDock())); } changedDock(); } void EMainWindow::closeEvent(QCloseEvent * e) { if (!checkSave()) e->ignore(); else saveSession(); } bool EMainWindow::eventFilter(QObject * o, QEvent * e) { if (tbars.contains((QTabBar*)o) && e->type() == QEvent::MouseButtonDblClick) { int tab = ((QTabBar*)o)->tabAt(((QMouseEvent * )e)->pos()); if (tab >= 0) { QDockWidget * dock = (QDockWidget * )(((QTabBar*)o)->tabData(tab).toULongLong()); if (dock) { dock->setFloating(true); return true; } } } /*if (e->type() == QEvent::Show || e->type() == QEvent::Hide) { if (tdocks.contains((QDockWidget*)o)) { changedDock(); } }*/ if (e->type() == QEvent::MouseButtonPress) { if (tbars.contains((QTabBar*)o) || tdocks.contains((QDockWidget*)o)) { if (e->type() == QEvent::MouseButtonPress) { if (((QMouseEvent*)e)->button() == Qt::RightButton) { bool popup = tbars.contains((QTabBar*)o); if (tdocks.contains((QDockWidget*)o)) popup = popup || ((QDockWidget*)o)->titleBarWidget()->geometry().contains(((QMouseEvent*)e)->pos()); if (popup) { createPopupMenu()->popup( #if QT_VERSION_MAJOR <= 5 ((QMouseEvent*)e)->globalPos() #else ((QMouseEvent*)e)->globalPosition().toPoint() #endif ); return true; } } } } } return QMainWindow::eventFilter(o, e); } void EMainWindow::changeEvent(QEvent * e) { QMainWindow::changeEvent(e); switch (e->type()) { case QEvent::LanguageChange: action_show_all_tools.setText(tr("Show all")); action_show_all_docks.setText(tr("Show all")); action_hide_all_tools.setText(tr("Hide all")); action_hide_all_docks.setText(tr("Hide all")); action_clear_recent->setText(tr("Clear recent list")); break; default: break; } } QMenu * EMainWindow::createPopupMenu() { QMenu * menuPopup = new QMenu; QWidgetAction * wa; QLabel * lbl; QAction * a; QFont f; f.setBold(true); // Toolbars QList tools = findChildren(); if (!tools.isEmpty()) { wa = new QWidgetAction(menuPopup); lbl = new QLabel(); lbl->setFrameShape(QFrame::StyledPanel); lbl->setFrameShadow(QFrame::Sunken); lbl->setText(tr("Toolbars")); lbl->setFont(f); lbl->setAlignment(Qt::AlignCenter); wa->setDefaultWidget(lbl); menuPopup->addAction(wa); for (QToolBar * i: tools) { if (i->property("ribbon").toBool()) continue; a = new QAction(i->windowTitle(), menuPopup); a->setCheckable(true); a->setChecked(!i->isHidden()); a->setIcon(i->windowIcon()); connect(a, SIGNAL(toggled(bool)), i, SLOT(setVisible(bool))); menuPopup->addAction(a); } menuPopup->addSeparator(); menuPopup->addAction(&action_show_all_tools); menuPopup->addAction(&action_hide_all_tools); } // Docks QList docks = findChildren(); if (!docks.isEmpty()) { wa = new QWidgetAction(menuPopup); lbl = new QLabel(); lbl->setFrameShape(QFrame::StyledPanel); lbl->setFrameShadow(QFrame::Sunken); lbl->setText(tr("Docks")); lbl->setFont(f); lbl->setAlignment(Qt::AlignCenter); wa->setDefaultWidget(lbl); menuPopup->addAction(wa); for (QDockWidget * i: docks) { if (i->property("ribbon").toBool()) continue; a = new QAction(i->windowTitle(), menuPopup); a->setCheckable(true); a->setChecked(!i->isHidden()); a->setIcon(i->windowIcon()); connect(a, SIGNAL(toggled(bool)), i, SLOT(setVisible(bool))); menuPopup->addAction(a); } menuPopup->addSeparator(); menuPopup->addAction(&action_show_all_docks); menuPopup->addAction(&action_hide_all_docks); } return menuPopup; } void EMainWindow::addToRecent(const QString & path) { if (path.isEmpty()) return; QFileInfo fi(path); QString fp = fi.absoluteFilePath(); bool insert = true; for (int i = 0; i < actions_recent.size(); ++i) if (actions_recent[i]->data().toString() == fp) { actions_recent.push_front(actions_recent.takeAt(i)); insert = false; prepareRecent(); break; } if (!insert) return; QAction * a = new QAction(this); a->setData(fp); connect(a, SIGNAL(triggered()), this, SLOT(recentTriggered())); actions_recent.push_front(a); while (actions_recent.size() > max_recent) delete actions_recent.takeLast(); prepareRecent(); } void EMainWindow::prepareRecent() { for (int i = 0; i < actions_recent.size(); ++i) { QAction * a = actions_recent[i]; a->setText(QString("&%1 - %2").arg(i + 1).arg(a->data().toString())); } if (!menu_recent) return; menu_recent->clear(); menu_recent->addActions(actions_recent); menu_recent->addSeparator(); menu_recent->addAction(action_clear_recent); } void EMainWindow::initMenus() { action_show_all_tools.disconnect(); action_hide_all_tools.disconnect(); action_show_all_docks.disconnect(); action_hide_all_docks.disconnect(); QList tools = findChildren(); for (QToolBar * i: tools) { if (i->property("ribbon").toBool()) continue; i->toggleViewAction()->setIcon(i->windowIcon()); connect(&action_show_all_tools, SIGNAL(triggered(bool)), i, SLOT(show())); connect(&action_hide_all_tools, SIGNAL(triggered(bool)), i, SLOT(hide())); } QList docks = findChildren(); for (QDockWidget * i: docks) { if (i->property("ribbon").toBool()) continue; i->toggleViewAction()->setIcon(i->windowIcon()); connect(&action_show_all_docks, SIGNAL(triggered(bool)), i, SLOT(show())); connect(&action_hide_all_docks, SIGNAL(triggered(bool)), i, SLOT(hide())); } QList actions = findChildren(); for (QAction * i: actions) i->setIconVisibleInMenu(true); addActions(actions); } void EMainWindow::initSession() { connect(&session, SIGNAL(loading(QPIConfig & )), this, SLOT(sessionLoading(QPIConfig & ))); connect(&session, SIGNAL(saving(QPIConfig & )), this, SLOT(sessionSaving(QPIConfig & ))); } void EMainWindow::saveSession() { session.save(); } void EMainWindow::loadSession() { session.load(); } bool EMainWindow::checkSave() { if (!isWindowModified()) return true; return saveFile(true); } void EMainWindow::changedDock() { if (isHidden()) return; QSet invalid_tab_docks; QList tabs(findChildren()); QList docks = findChildren(); QRect geom = geometry(); //qDebug() << "### change" << docks.size() << tabs.size(); for (QTabBar * t: tabs) { if (!t->objectName().isEmpty() || t->isHidden()) continue; if (!tbars.contains(t)) { //qDebug() << "add tab" << t; tbars << t; connect(t, SIGNAL(tabCloseRequested(int)), this, SLOT(closeDock(int))); connect(t, &QObject::destroyed, this, [this,t](){tbars.removeOne(t);}); t->installEventFilter(this); #ifndef Q_OS_MACOS t->setIconSize(dockTabsIconSize()); #endif t->setTabsClosable(true); } for (int i = 0; i < t->count(); ++i) { QDockWidget * dock = (QDockWidget * )t->tabData(i).toULongLong(); //qDebug() << i << t->tabText(i) << t->isTabVisible(i) << dock; if (!dock) continue; if (!docks.contains(dock)) continue; if (!geom.intersects(t->geometry())) invalid_tab_docks << dock; #ifndef Q_OS_MACOS QSize is = dockTabsIconSize(); if (t->iconSize() != is) t->setIconSize(is); #endif t->setTabIcon(i, dock->windowIcon()); } } for (QDockWidget * d: docks) { if (!d->titleBarWidget()) continue; QWidget * ctb = d->titleBarWidget(); if (!d->property("__titleWidget").isValid()) { d->setProperty("__titleWidget", qulonglong(ctb)); QWidget * ntb = new QWidget(); int m = style()->pixelMetric(QStyle::PM_DockWidgetTitleMargin); ntb->setLayout(new QBoxLayout(QBoxLayout::BottomToTop)); ntb->layout()->setContentsMargins(m, m, 0, 0); d->setProperty("__titleEmptyWidget", qulonglong(ntb)); } if (!tdocks.contains(d)) { //qDebug() << "add dock" << d; tdocks << d; connect(d, &QObject::destroyed, this, [this,d](){tdocks.removeOne(d);}); d->installEventFilter(this); } //qDebug() << d->windowTitle() << tabifiedDockWidgets(d); if (tabifiedDockWidgets(d).isEmpty() || invalid_tab_docks.contains(d)) { if (d->titleBarWidget() != (QWidget * )(d->property("__titleWidget").toULongLong())) d->setTitleBarWidget((QWidget * )(d->property("__titleWidget").toULongLong())); } else { if (d->titleBarWidget() != (QWidget * )(d->property("__titleEmptyWidget").toULongLong())) { d->setTitleBarWidget((QWidget * )(d->property("__titleEmptyWidget").toULongLong())); d->layout()->setContentsMargins(0, 20, 0, 0); } } } } void EMainWindow::closeDock(int index) { QDockWidget * dock = (QDockWidget * )((QTabBar*)sender())->tabData(index).toULongLong(); if (dock == 0) return; dock->close(); } void EMainWindow::recentTriggered() { QAction * a = qobject_cast(sender()); if (!a) return; QString path = a->data().toString(); if (path.isEmpty()) return; if (!checkSave()) return; if (load(path)) addToRecent(path); } void EMainWindow::setMaxRecentItems(int mr) { max_recent = qMax(0, mr); for (int i = actions_recent.size() - 1; i >= mr; --i) delete actions_recent.takeLast(); } void EMainWindow::newFile() { if (!checkSave()) return; reset(true); setWindowModified(false); } void EMainWindow::openFile() { if (!checkSave()) return; QString ret = QFileDialog::getOpenFileName(this, tr("Select file to open"), file_name, loadFilter()); if (ret.isEmpty()) return; if (load(ret)) addToRecent(ret); } void EMainWindow::openFiles() { if (!checkSave()) return; QStringList ret = QFileDialog::getOpenFileNames(this, tr("Select files to open"), file_name, loadFilter()); foreach (QString s, ret) { if (load(s)) addToRecent(s); } } bool EMainWindow::saveFile(bool ask) { if (ask) { int ret = QMessageBox::question(this, windowTitle(), tr("Save changes%1?").arg(!file_name.isEmpty() ? (tr(" in") + " \"" + file_name + "\"") : ""), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Save); if (ret == QMessageBox::Cancel) return false; if (ret == QMessageBox::Save) return saveFile(); return true; } if (file_name.isEmpty()) return saveAsFile(); if (save(file_name)) addToRecent(file_name); return true; } bool EMainWindow::saveAsFile() { QString ret = QFileDialog::getSaveFileName(this, tr("Select file to save"), file_name, saveFilter()); if (ret.isEmpty()) return false; if (save(ret)) addToRecent(ret); return true; } void EMainWindow::clearRecent() { qDeleteAll(actions_recent); actions_recent.clear(); prepareRecent(); }