Files
cbh/ElaWidgetTools/ElaWindow.cpp
2025-09-19 22:40:52 +08:00

530 lines
16 KiB
C++

#include "ElaWindow.h"
#include "ElaApplication.h"
#include "ElaCentralStackedWidget.h"
#include "ElaEventBus.h"
#include "ElaMenu.h"
#include "ElaNavigationBar.h"
#include "ElaNavigationRouter.h"
#include "ElaTheme.h"
#include "ElaWindowStyle.h"
#include "private/ElaAppBarPrivate.h"
#include "private/ElaNavigationBarPrivate.h"
#include "private/ElaWindowPrivate.h"
#include <QApplication>
#include <QDockWidget>
#include <QHBoxLayout>
#include <QPropertyAnimation>
#include <QResizeEvent>
#include <QScreen>
#include <QStackedWidget>
#include <QStyleOption>
#include <QTimer>
#include <QToolBar>
#include <QVBoxLayout>
Q_PROPERTY_CREATE_Q_CPP(ElaWindow, int, ThemeChangeTime)
Q_PROPERTY_CREATE_Q_CPP(ElaWindow, ElaNavigationType::NavigationDisplayMode, NavigationBarDisplayMode)
Q_PROPERTY_CREATE_Q_CPP(ElaWindow, ElaWindowType::StackSwitchMode, StackSwitchMode)
Q_TAKEOVER_NATIVEEVENT_CPP(ElaWindow, d_func()->_appBar);
ElaWindow::ElaWindow(QWidget* parent)
: QMainWindow{parent}, d_ptr(new ElaWindowPrivate())
{
Q_D(ElaWindow);
d->q_ptr = this;
d->_pStackSwitchMode = ElaWindowType::StackSwitchMode::Popup;
setProperty("ElaBaseClassName", "ElaWindow");
resize(1020, 680); // 默认宽高
d->_pThemeChangeTime = 700;
d->_pNavigationBarDisplayMode = ElaNavigationType::NavigationDisplayMode::Auto;
connect(this, &ElaWindow::pNavigationBarDisplayModeChanged, d, &ElaWindowPrivate::onDisplayModeChanged);
// 自定义AppBar
d->_appBar = new ElaAppBar(this);
connect(d->_appBar, &ElaAppBar::routeBackButtonClicked, this, []() {
ElaNavigationRouter::getInstance()->navigationRouteBack();
});
connect(d->_appBar, &ElaAppBar::closeButtonClicked, this, &ElaWindow::closeButtonClicked);
// 导航栏
d->_navigationBar = new ElaNavigationBar(this);
// 返回按钮状态变更
connect(ElaNavigationRouter::getInstance(), &ElaNavigationRouter::navigationRouterStateChanged, this, [d](bool isEnable) {
d->_appBar->setRouteBackButtonEnable(isEnable);
});
// 转发用户卡片点击信号
connect(d->_navigationBar, &ElaNavigationBar::userInfoCardClicked, this, &ElaWindow::userInfoCardClicked);
// 转发点击信号
connect(d->_navigationBar, &ElaNavigationBar::navigationNodeClicked, this, &ElaWindow::navigationNodeClicked);
// 跳转处理
connect(d->_navigationBar, &ElaNavigationBar::navigationNodeClicked, d, &ElaWindowPrivate::onNavigationNodeClicked);
// 新增窗口
connect(d->_navigationBar, &ElaNavigationBar::navigationNodeAdded, d, &ElaWindowPrivate::onNavigationNodeAdded);
// 移除窗口
connect(d->_navigationBar, &ElaNavigationBar::navigationNodeRemoved, d, &ElaWindowPrivate::onNavigationNodeRemoved);
// 在新窗口打开
connect(d->_navigationBar, &ElaNavigationBar::pageOpenInNewWindow, this, &ElaWindow::pageOpenInNewWindow);
// 导航中心堆栈窗口
d->_navigationCenterStackedWidget = new ElaCentralStackedWidget(this);
d->_navigationCenterStackedWidget->setContentsMargins(0, 0, 0, 0);
QWidget* navigationCentralWidget = new QWidget(this);
navigationCentralWidget->setObjectName("ElaWindowNavigationCentralWidget");
navigationCentralWidget->setStyleSheet("#ElaWindowNavigationCentralWidget{background-color:transparent;}");
navigationCentralWidget->installEventFilter(this);
d->_centerLayout = new QHBoxLayout(navigationCentralWidget);
d->_centerLayout->setSpacing(0);
d->_centerLayout->addWidget(d->_navigationBar);
d->_centerLayout->addWidget(d->_navigationCenterStackedWidget);
d->_centerLayout->setContentsMargins(d->_contentsMargins, 0, 0, 0);
// 事件总线
d->_focusEvent = new ElaEvent("WMWindowClicked", "onWMWindowClickedEvent", d);
d->_focusEvent->registerAndInit();
// 展开导航栏
connect(d->_appBar, &ElaAppBar::navigationButtonClicked, d, &ElaWindowPrivate::onNavigationButtonClicked);
// 主题变更动画
d->_themeMode = eTheme->getThemeMode();
connect(eTheme, &ElaTheme::themeModeChanged, d, &ElaWindowPrivate::onThemeModeChanged);
connect(d->_appBar, &ElaAppBar::themeChangeButtonClicked, d, &ElaWindowPrivate::onThemeReadyChange);
d->_isInitFinished = true;
// 中心堆栈窗口
d->_centerStackedWidget = new ElaCentralStackedWidget(this);
d->_centerStackedWidget->setIsTransparent(true);
d->_centerStackedWidget->addWidget(navigationCentralWidget);
setCentralWidget(d->_centerStackedWidget);
setObjectName("ElaWindow");
setStyleSheet("#ElaWindow{background-color:transparent;}");
setStyle(new ElaWindowStyle(style()));
//延时渲染
QTimer::singleShot(1, this, [=] {
QPalette palette = this->palette();
palette.setBrush(QPalette::Window, ElaThemeColor(d->_themeMode, WindowBase));
this->setPalette(palette);
});
eApp->syncWindowDisplayMode(this);
connect(eApp, &ElaApplication::pWindowDisplayModeChanged, this, [=]() {
d->onThemeModeChanged(d->_themeMode);
});
}
ElaWindow::~ElaWindow()
{
eApp->syncWindowDisplayMode(this, false);
delete this->style();
}
void ElaWindow::setIsStayTop(bool isStayTop)
{
Q_D(ElaWindow);
d->_appBar->setIsStayTop(isStayTop);
Q_EMIT pIsStayTopChanged();
}
bool ElaWindow::getIsStayTop() const
{
return d_ptr->_appBar->getIsStayTop();
}
void ElaWindow::setIsFixedSize(bool isFixedSize)
{
Q_D(ElaWindow);
d->_appBar->setIsFixedSize(isFixedSize);
Q_EMIT pIsFixedSizeChanged();
}
bool ElaWindow::getIsFixedSize() const
{
return d_ptr->_appBar->getIsFixedSize();
}
void ElaWindow::setIsDefaultClosed(bool isDefaultClosed)
{
Q_D(ElaWindow);
d->_appBar->setIsDefaultClosed(isDefaultClosed);
Q_EMIT pIsDefaultClosedChanged();
}
bool ElaWindow::getIsDefaultClosed() const
{
return d_ptr->_appBar->getIsDefaultClosed();
}
void ElaWindow::setAppBarHeight(int appBarHeight)
{
Q_D(ElaWindow);
d->_appBar->setAppBarHeight(appBarHeight);
Q_EMIT pAppBarHeightChanged();
}
int ElaWindow::getAppBarHeight() const
{
Q_D(const ElaWindow);
return d->_appBar->getAppBarHeight();
}
void ElaWindow::setCustomWidget(ElaAppBarType::CustomArea customArea, QWidget* widget)
{
Q_D(ElaWindow);
d->_appBar->setCustomWidget(customArea, widget);
Q_EMIT customWidgetChanged();
}
QWidget* ElaWindow::getCustomWidget() const
{
Q_D(const ElaWindow);
return d->_appBar->getCustomWidget();
}
void ElaWindow::setCustomMenu(QMenu* customMenu)
{
Q_D(ElaWindow);
d->_appBar->setCustomMenu(customMenu);
Q_EMIT customMenuChanged();
}
QMenu* ElaWindow::getCustomMenu() const
{
Q_D(const ElaWindow);
return d->_appBar->getCustomMenu();
}
void ElaWindow::setCustomWidgetMaximumWidth(int width)
{
Q_D(ElaWindow);
d->_appBar->setCustomWidgetMaximumWidth(width);
Q_EMIT pCustomWidgetMaximumWidthChanged();
}
int ElaWindow::getCustomWidgetMaximumWidth() const
{
Q_D(const ElaWindow);
return d->_appBar->getCustomWidgetMaximumWidth();
}
void ElaWindow::setIsCentralStackedWidgetTransparent(bool isTransparent)
{
Q_D(ElaWindow);
d->_navigationCenterStackedWidget->setIsTransparent(isTransparent);
}
bool ElaWindow::getIsCentralStackedWidgetTransparent() const
{
Q_D(const ElaWindow);
return d->_navigationCenterStackedWidget->getIsTransparent();
}
void ElaWindow::setIsAllowPageOpenInNewWindow(bool isAllowPageOpenInNewWindow)
{
Q_D(ElaWindow);
d->_navigationBar->setIsAllowPageOpenInNewWindow(isAllowPageOpenInNewWindow);
Q_EMIT pIsAllowPageOpenInNewWindowChanged();
}
bool ElaWindow::getIsAllowPageOpenInNewWindow() const
{
Q_D(const ElaWindow);
return d->_navigationBar->getIsAllowPageOpenInNewWindow();
}
void ElaWindow::setNavigationBarWidth(int navigationBarWidth)
{
Q_D(ElaWindow);
d->_navigationBar->setNavigationBarWidth(navigationBarWidth);
Q_EMIT pNavigationBarWidthChanged();
}
int ElaWindow::getNavigationBarWidth() const
{
Q_D(const ElaWindow);
return d->_navigationBar->getNavigationBarWidth();
}
void ElaWindow::setCurrentStackIndex(int currentStackIndex)
{
Q_D(ElaWindow);
if (currentStackIndex >= d->_centerStackedWidget->count() || currentStackIndex < 0 || currentStackIndex == d->_centralStackTargetIndex)
{
return;
}
d->_centralStackTargetIndex = currentStackIndex;
QVariantMap routeData;
routeData.insert("ElaCentralStackIndex", d->_centerStackedWidget->currentIndex());
ElaNavigationRouter::getInstance()->navigationRoute(d, "onNavigationRouteBack", routeData);
d->_centerStackedWidget->doWindowStackSwitch(d->_pStackSwitchMode, currentStackIndex, false);
Q_EMIT pCurrentStackIndexChanged();
}
int ElaWindow::getCurrentStackIndex() const
{
Q_D(const ElaWindow);
return d->_centerStackedWidget->currentIndex();
}
void ElaWindow::moveToCenter()
{
if (isMaximized() || isFullScreen())
{
return;
}
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
auto geometry = screen()->availableGeometry();
#else
auto geometry = qApp->screenAt(this->geometry().center())->geometry();
#endif
setGeometry((geometry.left() + geometry.right() - width()) / 2, (geometry.top() + geometry.bottom() - height()) / 2, width(), height());
}
void ElaWindow::setIsNavigationBarEnable(bool isVisible)
{
Q_D(ElaWindow);
d->_isNavigationEnable = isVisible;
d->_navigationBar->setVisible(isVisible);
d->_centerLayout->setContentsMargins(isVisible ? d->_contentsMargins : 0, 0, 0, 0);
d->_navigationCenterStackedWidget->setIsHasRadius(isVisible);
}
bool ElaWindow::getIsNavigationBarEnable() const
{
return d_ptr->_isNavigationEnable;
}
void ElaWindow::setUserInfoCardVisible(bool isVisible)
{
Q_D(ElaWindow);
d->_navigationBar->setUserInfoCardVisible(isVisible);
}
void ElaWindow::setUserInfoCardPixmap(QPixmap pix)
{
Q_D(ElaWindow);
d->_navigationBar->setUserInfoCardPixmap(pix);
}
void ElaWindow::setUserInfoCardTitle(QString title)
{
Q_D(ElaWindow);
d->_navigationBar->setUserInfoCardTitle(title);
}
void ElaWindow::setUserInfoCardSubTitle(QString subTitle)
{
Q_D(ElaWindow);
d->_navigationBar->setUserInfoCardSubTitle(subTitle);
}
ElaNavigationType::NodeOperateReturnType ElaWindow::addExpanderNode(QString expanderTitle, QString& expanderKey, ElaIconType::IconName awesome) const
{
Q_D(const ElaWindow);
return d->_navigationBar->addExpanderNode(expanderTitle, expanderKey, awesome);
}
ElaNavigationType::NodeOperateReturnType ElaWindow::addExpanderNode(QString expanderTitle, QString& expanderKey, QString targetExpanderKey, ElaIconType::IconName awesome) const
{
Q_D(const ElaWindow);
return d->_navigationBar->addExpanderNode(expanderTitle, expanderKey, targetExpanderKey, awesome);
}
ElaNavigationType::NodeOperateReturnType ElaWindow::addPageNode(QString pageTitle, QWidget* page, ElaIconType::IconName awesome) const
{
Q_D(const ElaWindow);
return d->_navigationBar->addPageNode(pageTitle, page, awesome);
}
ElaNavigationType::NodeOperateReturnType ElaWindow::addPageNode(QString pageTitle, QWidget* page, QString targetExpanderKey, ElaIconType::IconName awesome) const
{
Q_D(const ElaWindow);
return d->_navigationBar->addPageNode(pageTitle, page, targetExpanderKey, awesome);
}
ElaNavigationType::NodeOperateReturnType ElaWindow::addPageNode(QString pageTitle, QWidget* page, int keyPoints, ElaIconType::IconName awesome) const
{
Q_D(const ElaWindow);
return d->_navigationBar->addPageNode(pageTitle, page, keyPoints, awesome);
}
ElaNavigationType::NodeOperateReturnType ElaWindow::addPageNode(QString pageTitle, QWidget* page, QString targetExpanderKey, int keyPoints, ElaIconType::IconName awesome) const
{
Q_D(const ElaWindow);
return d->_navigationBar->addPageNode(pageTitle, page, targetExpanderKey, keyPoints, awesome);
}
ElaNavigationType::NodeOperateReturnType ElaWindow::addFooterNode(QString footerTitle, QString& footerKey, int keyPoints, ElaIconType::IconName awesome) const
{
Q_D(const ElaWindow);
return d->_navigationBar->addFooterNode(footerTitle, nullptr, footerKey, keyPoints, awesome);
}
ElaNavigationType::NodeOperateReturnType ElaWindow::addFooterNode(QString footerTitle, QWidget* page, QString& footerKey, int keyPoints, ElaIconType::IconName awesome) const
{
Q_D(const ElaWindow);
return d->_navigationBar->addFooterNode(footerTitle, page, footerKey, keyPoints, awesome);
}
void ElaWindow::addCentralWidget(QWidget* centralWidget)
{
Q_D(ElaWindow);
if (!centralWidget)
{
return;
}
d->_centerStackedWidget->addWidget(centralWidget);
}
QWidget* ElaWindow::getCentralWidget(int index) const
{
Q_D(const ElaWindow);
if (index >= d->_centerStackedWidget->count() || index < 1)
{
return nullptr;
}
return d->_centerStackedWidget->widget(index);
}
bool ElaWindow::getNavigationNodeIsExpanded(QString expanderKey) const
{
Q_D(const ElaWindow);
return d->_navigationBar->getNavigationNodeIsExpanded(expanderKey);
}
void ElaWindow::expandNavigationNode(QString expanderKey)
{
Q_D(ElaWindow);
d->_navigationBar->expandNavigationNode(expanderKey);
}
void ElaWindow::collpaseNavigationNode(QString expanderKey)
{
Q_D(ElaWindow);
d->_navigationBar->collpaseNavigationNode(expanderKey);
}
void ElaWindow::removeNavigationNode(QString nodeKey) const
{
Q_D(const ElaWindow);
d->_navigationBar->removeNavigationNode(nodeKey);
}
int ElaWindow::getPageOpenInNewWindowCount(QString nodeKey) const
{
Q_D(const ElaWindow);
return d->_navigationBar->getPageOpenInNewWindowCount(nodeKey);
}
void ElaWindow::setNodeKeyPoints(QString nodeKey, int keyPoints)
{
Q_D(ElaWindow);
d->_navigationBar->setNodeKeyPoints(nodeKey, keyPoints);
}
int ElaWindow::getNodeKeyPoints(QString nodeKey) const
{
Q_D(const ElaWindow);
return d->_navigationBar->getNodeKeyPoints(nodeKey);
}
void ElaWindow::navigation(QString pageKey)
{
Q_D(ElaWindow);
d->_navigationBar->navigation(pageKey);
}
int ElaWindow::getCurrentNavigationIndex() const
{
Q_D(const ElaWindow);
return d->_navigationCenterStackedWidget->currentIndex();
}
QString ElaWindow::getCurrentNavigationPageKey() const
{
Q_D(const ElaWindow);
return d->_navigationCenterStackedWidget->currentWidget()->property("ElaPageKey").toString();
}
void ElaWindow::setWindowButtonFlag(ElaAppBarType::ButtonType buttonFlag, bool isEnable)
{
Q_D(ElaWindow);
d->_appBar->setWindowButtonFlag(buttonFlag, isEnable);
}
void ElaWindow::setWindowButtonFlags(ElaAppBarType::ButtonFlags buttonFlags)
{
Q_D(ElaWindow);
d->_appBar->setWindowButtonFlags(buttonFlags);
}
ElaAppBarType::ButtonFlags ElaWindow::getWindowButtonFlags() const
{
return d_ptr->_appBar->getWindowButtonFlags();
}
void ElaWindow::closeWindow()
{
Q_D(ElaWindow);
d->_isWindowClosing = true;
d->_appBar->closeWindow();
}
bool ElaWindow::eventFilter(QObject* watched, QEvent* event)
{
Q_D(ElaWindow);
switch (event->type())
{
case QEvent::Resize:
{
d->_doNavigationDisplayModeChange();
break;
}
default:
{
break;
}
}
return QMainWindow::eventFilter(watched, event);
}
QMenu* ElaWindow::createPopupMenu()
{
ElaMenu* menu = nullptr;
QList<QDockWidget*> dockwidgets = findChildren<QDockWidget*>();
if (dockwidgets.size())
{
menu = new ElaMenu(this);
for (int i = 0; i < dockwidgets.size(); ++i)
{
QDockWidget* dockWidget = dockwidgets.at(i);
if (dockWidget->parentWidget() == this)
{
menu->addAction(dockwidgets.at(i)->toggleViewAction());
}
}
menu->addSeparator();
}
QList<QToolBar*> toolbars = findChildren<QToolBar*>();
if (toolbars.size())
{
if (!menu)
{
menu = new ElaMenu(this);
}
for (int i = 0; i < toolbars.size(); ++i)
{
QToolBar* toolBar = toolbars.at(i);
if (toolBar->parentWidget() == this)
{
menu->addAction(toolbars.at(i)->toggleViewAction());
}
}
}
if (menu)
{
menu->setMenuItemHeight(28);
}
return menu;
}