#include "emainwindow.h" #include #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) { 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())); 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(); initDocks(); } 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::initDocks() { QList docks(findChildren()); for (QDockWidget * d: docks) { static const char * pname = "__edock_inited__"; if (d->property(pname).toBool()) continue; d->setProperty(pname, true); 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::initSession() { connect(&session, &SessionManager::loading, this, [this](QPIConfig & conf) { loadingSession(conf); }); connect(&session, &SessionManager::saving, this, [this](QPIConfig & conf) { savingSession(conf); }); } void EMainWindow::saveSession() { session.save(); } void EMainWindow::loadSession() { session.load(); } bool EMainWindow::checkSave() { if (!isWindowModified()) return true; return saveFile(true); } void EMainWindow::setChanged(bool yes) { is_changed = yes; setWindowModified(yes); } void EMainWindow::changedDock() { if (isHidden()) return; QSet invalid_tab_docks; QList tabs(findChildren()); QList docks = findChildren(); QRect geom = rect(); // 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; if (!tdocks.contains(d)) { // qDebug() << "add dock" << d; tdocks << d; connect(d, &QObject::destroyed, this, [this, d]() { tdocks.removeOne(d); }); d->installEventFilter(this); } auto * ed = qobject_cast(d); if (ed) { // qDebug() << d->windowTitle() << tabifiedDockWidgets(d); if (tabifiedDockWidgets(d).isEmpty() || invalid_tab_docks.contains(d)) ed->setStandardHeader(); else ed->setEmptyHeader(); } } } 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(file_name); return true; } void EMainWindow::clearRecent() { qDeleteAll(actions_recent); actions_recent.clear(); prepareRecent(); }