#include "ElaNavigationBarPrivate.h" #include "ElaApplication.h" #include "ElaBaseListView.h" #include "ElaCustomTabWidget.h" #include "ElaCustomWidget.h" #include "ElaFooterDelegate.h" #include "ElaFooterModel.h" #include "ElaIconButton.h" #include "ElaInteractiveCard.h" #include "ElaMenu.h" #include "ElaNavigationBar.h" #include "ElaNavigationModel.h" #include "ElaNavigationNode.h" #include "ElaNavigationRouter.h" #include "ElaNavigationView.h" #include "ElaSuggestBox.h" #include "ElaSuggestBoxPrivate.h" #include "ElaToolButton.h" #include #include #include #include ElaNavigationBarPrivate::ElaNavigationBarPrivate(QObject *parent) : QObject{parent} {} ElaNavigationBarPrivate::~ElaNavigationBarPrivate() {} // ADDZY: 导航栏内部展开收缩按钮被点击 void ElaNavigationBarPrivate::onNavigationButtonClicked() { Q_Q(ElaNavigationBar); if (_currentDisplayMode == ElaNavigationType::Compact) { q->setDisplayMode(ElaNavigationType::Maximal); } else { q->setDisplayMode(ElaNavigationType::Compact); } } void ElaNavigationBarPrivate::onNavigationOpenNewWindow(QString nodeKey) { Q_Q(ElaNavigationBar); const QMetaObject *meta = _pageMetaMap.value(nodeKey); if (!meta) { return; } QWidget *widget = static_cast(meta->newInstance()); if (widget) { widget->setProperty("ElaPageKey", nodeKey); widget->setProperty("ElaFloatParentWidget", QVariant::fromValue(q)); widget->installEventFilter(this); ElaCustomTabWidget *floatWidget = new ElaCustomTabWidget(q); floatWidget->addTab(widget, widget->windowIcon(), widget->windowTitle()); floatWidget->show(); Q_EMIT q->pageOpenInNewWindow(nodeKey); } } void ElaNavigationBarPrivate::onNavigationRouteBack(QVariantMap routeData) { Q_Q(ElaNavigationBar); QString pageKey = routeData.value("ElaPageKey").toString(); q->navigation(pageKey, false, true); } void ElaNavigationBarPrivate::onTreeViewClicked(const QModelIndex &index, bool isLogRoute, bool isRouteBack) { Q_Q(ElaNavigationBar); if (index.isValid()) { ElaNavigationNode *node = static_cast(index.internalPointer()); if (!node) { return; } if (node->getIsExpanderNode()) { _expandOrCollpaseExpanderNode(node, !_navigationView->isExpanded(index)); } else { if (node->getKeyPoints()) { node->setKeyPoints(0); _navigationView->update(); } ElaNavigationNode *selectedNode = _navigationModel->getSelectedNode(); if (selectedNode != node) { // 记录跳转 if (isLogRoute) { QVariantMap routeData = QVariantMap(); QString pageKey; if (selectedNode) { pageKey.append(selectedNode->getNodeKey()); } else { if (_footerModel->getSelectedNode()) { pageKey.append(_footerModel->getSelectedNode()->getNodeKey()); } } routeData.insert("ElaPageKey", pageKey); ElaNavigationRouter::getInstance()->navigationRoute(this, "onNavigationRouteBack", routeData); } Q_EMIT q->navigationNodeClicked(ElaNavigationType::PageNode, node->getNodeKey(), isRouteBack); if (_footerModel->getSelectedNode()) { _footerView->clearSelection(); QVariantMap footerPostData = QVariantMap(); footerPostData.insert("SelectMarkChanged", true); footerPostData.insert("LastSelectedNode", QVariant::fromValue(_footerModel->getSelectedNode())); footerPostData.insert("SelectedNode", QVariant::fromValue(nullptr)); _footerModel->setSelectedNode(nullptr); _footerDelegate->navigationNodeStateChange(footerPostData); } QVariantMap postData = QVariantMap(); postData.insert("SelectMarkChanged", true); if (_navigationModel->getSelectedExpandedNode()) { postData.insert("LastSelectedNode", QVariant::fromValue(_navigationModel->getSelectedExpandedNode())); } else { postData.insert("LastSelectedNode", QVariant::fromValue(_navigationModel->getSelectedNode())); } if (_currentDisplayMode == ElaNavigationType::Compact) { ElaNavigationNode *originNode = node->getOriginalNode(); if (originNode == node) { postData.insert("SelectedNode", QVariant::fromValue(node)); } else { if (originNode == _navigationModel->getSelectedExpandedNode()) { _navigationModel->setSelectedNode(node); _resetNodeSelected(); return; } _navigationModel->setSelectedExpandedNode(originNode); postData.insert("SelectedNode", QVariant::fromValue(originNode)); } } else { postData.insert("SelectedNode", QVariant::fromValue(node)); } _navigationModel->setSelectedNode(node); _navigationView->navigationNodeStateChange(postData); if (!node->getIsVisible() && _currentDisplayMode != ElaNavigationType::Compact) { _expandSelectedNodeParent(); } } } _resetNodeSelected(); } } void ElaNavigationBarPrivate::onFooterViewClicked(const QModelIndex &index, bool isLogRoute, bool isRouteBack) { Q_Q(ElaNavigationBar); ElaNavigationNode *node = index.data(Qt::UserRole).value(); if (node->getKeyPoints()) { node->setKeyPoints(0); _navigationView->update(); } ElaNavigationNode *selectedNode = _footerModel->getSelectedNode(); if (selectedNode != node) { // 记录跳转 if (isLogRoute && node->getIsHasFooterPage()) { QVariantMap routeData = QVariantMap(); QString pageKey; if (selectedNode) { pageKey.append(selectedNode->getNodeKey()); } else { if (_navigationModel->getSelectedNode()) { pageKey.append(_navigationModel->getSelectedNode()->getNodeKey()); } } routeData.insert("ElaPageKey", pageKey); ElaNavigationRouter::getInstance()->navigationRoute(this, "onNavigationRouteBack", routeData); } Q_EMIT q->navigationNodeClicked(ElaNavigationType::FooterNode, node->getNodeKey(), isRouteBack); if (node->getIsHasFooterPage()) { if (_navigationModel->getSelectedNode() || _navigationModel->getSelectedExpandedNode()) { QVariantMap mainPostData = QVariantMap(); mainPostData.insert("SelectMarkChanged", true); mainPostData.insert("LastSelectedNode", QVariant::fromValue(_navigationModel->getSelectedExpandedNode() ? _navigationModel->getSelectedExpandedNode() : _navigationModel->getSelectedNode())); mainPostData.insert("SelectedNode", QVariant::fromValue(nullptr)); _navigationView->clearSelection(); _navigationView->navigationNodeStateChange(mainPostData); _navigationModel->setSelectedExpandedNode(nullptr); _navigationModel->setSelectedNode(nullptr); } _footerView->clearSelection(); _footerView->selectionModel()->select(index, QItemSelectionModel::Select); QVariantMap postData = QVariantMap(); postData.insert("SelectMarkChanged", true); postData.insert("LastSelectedNode", QVariant::fromValue(_footerModel->getSelectedNode())); postData.insert("SelectedNode", QVariant::fromValue(node)); _footerDelegate->navigationNodeStateChange(postData); _footerModel->setSelectedNode(node); } } } bool ElaNavigationBarPrivate::eventFilter(QObject *watched, QEvent *event) { switch (event->type()) { case QEvent::Show: { QString nodeKey = watched->property("ElaPageKey").toString(); if (!nodeKey.isNull()) { _pageNewWindowCountMap[nodeKey] += 1; } break; } case QEvent::HideToParent: { QString nodeKey = watched->property("ElaPageKey").toString(); if (!nodeKey.isNull()) { _pageNewWindowCountMap[nodeKey] -= 1; } break; } default: { break; } } return QObject::eventFilter(watched, event); } void ElaNavigationBarPrivate::_initNodeModelIndex(const QModelIndex &parentIndex) { int rowCount = _navigationModel->rowCount(parentIndex); for (int row = 0; row < rowCount; ++row) { QModelIndex index = _navigationModel->index(row, 0, parentIndex); ElaNavigationNode *childNode = static_cast(index.internalPointer()); childNode->setModelIndex(index); if (_navigationModel->hasChildren(index)) { _initNodeModelIndex(index); } } } void ElaNavigationBarPrivate::_resetNodeSelected() { _navigationView->clearSelection(); ElaNavigationNode *selectedNode = _navigationModel->getSelectedNode(); if (!selectedNode || !selectedNode->getModelIndex().isValid()) { return; } if (selectedNode->getParentNode()->getIsRootNode() || selectedNode->getIsVisible()) { _navigationView->selectionModel()->select(selectedNode->getModelIndex(), QItemSelectionModel::Select); if (_navigationModel->getSelectedExpandedNode()) { QVariantMap postData = QVariantMap(); postData.insert("SelectMarkChanged", true); postData.insert("LastSelectedNode", QVariant::fromValue(_navigationModel->getSelectedExpandedNode())); postData.insert("SelectedNode", QVariant::fromValue(selectedNode)); _navigationView->navigationNodeStateChange(postData); } _navigationModel->setSelectedExpandedNode(nullptr); } else { ElaNavigationNode *parentNode = selectedNode->getParentNode(); while (parentNode && !parentNode->getParentNode()->getIsRootNode() && !parentNode->getIsVisible()) { parentNode = parentNode->getParentNode(); } if (!parentNode) { return; } // 单级节点展开/收起时Mark变化 if (!_navigationModel->getSelectedExpandedNode()) { QVariantMap postData = QVariantMap(); postData.insert("SelectMarkChanged", true); postData.insert("LastSelectedNode", QVariant::fromValue(_navigationModel->getSelectedNode())); postData.insert("SelectedNode", QVariant::fromValue(parentNode)); _navigationView->navigationNodeStateChange(postData); } else { // 多级节点 if (_navigationModel->getSelectedExpandedNode() != parentNode) { // 同一起源节点展开/收起时的Mark变化 if (_navigationModel->getSelectedExpandedNode()->getOriginalNode() == parentNode->getOriginalNode()) { QVariantMap postData = QVariantMap(); postData.insert("SelectMarkChanged", true); postData.insert("LastSelectedNode", QVariant::fromValue(_navigationModel->getSelectedExpandedNode())); postData.insert("SelectedNode", QVariant::fromValue(parentNode)); _navigationView->navigationNodeStateChange(postData); } } } _navigationModel->setSelectedExpandedNode(parentNode); _navigationView->selectionModel()->select(parentNode->getModelIndex(), QItemSelectionModel::Select); } } void ElaNavigationBarPrivate::_expandSelectedNodeParent() { ElaNavigationNode *parentNode = _navigationModel->getSelectedNode()->getParentNode(); while (parentNode && !parentNode->getIsRootNode()) { QVariantMap data; data.insert("Expand", QVariant::fromValue(parentNode)); _navigationView->navigationNodeStateChange(data); parentNode->setIsExpanded(true); _navigationView->expand(parentNode->getModelIndex()); parentNode = parentNode->getParentNode(); } } void ElaNavigationBarPrivate::_expandOrCollpaseExpanderNode(ElaNavigationNode *node, bool isExpand) { if (_currentDisplayMode == ElaNavigationType::Compact) { if (node->getIsHasPageChild()) { // 展开菜单 ElaMenu *menu = _compactMenuMap.value(node); if (menu) { QPoint nodeTopRight = _navigationView->mapToGlobal(_navigationView->visualRect(node->getModelIndex()).topRight()); menu->popup(QPoint(nodeTopRight.x() + 10, nodeTopRight.y())); } } } else { QModelIndex index = node->getModelIndex(); bool isExpanded = _navigationView->isExpanded(index); if (node->getIsHasChild() && isExpand != isExpanded) { QVariantMap data; if (isExpanded) { // 收起 data.insert("Collapse", QVariant::fromValue(node)); node->setIsExpanded(isExpand); _navigationView->navigationNodeStateChange(data); _navigationView->collapse(index); } else { // 展开 data.insert("Expand", QVariant::fromValue(node)); node->setIsExpanded(true); _navigationView->navigationNodeStateChange(data); _navigationView->expand(index); } } } } void ElaNavigationBarPrivate::_addStackedPage(QWidget *page, QString pageKey) { Q_Q(ElaNavigationBar); page->setProperty("ElaPageKey", pageKey); Q_EMIT q->navigationNodeAdded(ElaNavigationType::PageNode, pageKey, page); ElaNavigationNode *node = _navigationModel->getNavigationNode(pageKey); QVariantMap suggestData; suggestData.insert("ElaNodeType", "Stacked"); suggestData.insert("ElaPageKey", pageKey); QString suggestKey = _navigationSuggestBox->addSuggestion(node->getAwesome(), node->getNodeTitle(), suggestData); _suggestKeyMap.insert(pageKey, suggestKey); } void ElaNavigationBarPrivate::_addFooterPage(QWidget *page, QString footKey) { Q_Q(ElaNavigationBar); Q_EMIT q->navigationNodeAdded(ElaNavigationType::FooterNode, footKey, page); if (page) { page->setProperty("ElaPageKey", footKey); } _footerView->setFixedHeight(40 * _footerModel->getFooterNodeCount()); ElaNavigationNode *node = _footerModel->getNavigationNode(footKey); QVariantMap suggestData; suggestData.insert("ElaNodeType", "Footer"); suggestData.insert("ElaPageKey", footKey); QString suggestKey = _navigationSuggestBox->addSuggestion(node->getAwesome(), node->getNodeTitle(), suggestData); _suggestKeyMap.insert(footKey, suggestKey); } void ElaNavigationBarPrivate::_raiseNavigationBar() { Q_Q(ElaNavigationBar); q->raise(); } void ElaNavigationBarPrivate::_doComponentAnimation(ElaNavigationType::NavigationDisplayMode displayMode, bool isAnimation) { switch (displayMode) { case ElaNavigationType::Minimal: { _doNavigationBarWidthAnimation(displayMode, isAnimation); if (_currentDisplayMode == ElaNavigationType::Maximal) { _searchButton->setVisible(true); _userCard->setVisible(false); _navigationSuggestBox->setVisible(false); if (_isShowUserCard) { _userButton->setVisible(true); } _handleNavigationExpandState(true); } _currentDisplayMode = displayMode; break; } case ElaNavigationType::Compact: { _doNavigationBarWidthAnimation(displayMode, isAnimation); _doNavigationViewWidthAnimation(isAnimation); if (_currentDisplayMode != ElaNavigationType::Minimal) { _handleMaximalToCompactLayout(); _doNavigationButtonAnimation(true, isAnimation); _doSearchButtonAnimation(true, isAnimation); _doUserButtonAnimation(true, isAnimation); _navigationSuggestBox->setVisible(false); _handleNavigationExpandState(true); } _currentDisplayMode = displayMode; break; } case ElaNavigationType::Maximal: { _resetLayout(); _handleCompactToMaximalLayout(); _doNavigationBarWidthAnimation(displayMode, isAnimation); _doUserButtonAnimation(false, isAnimation); _doNavigationButtonAnimation(false, isAnimation); _doSearchButtonAnimation(false, isAnimation); _navigationSuggestBox->setVisible(true); _currentDisplayMode = displayMode; _handleNavigationExpandState(false); break; } default: { break; } } } void ElaNavigationBarPrivate::_handleNavigationExpandState(bool isSave) { if (isSave) { // 保存展开状态 收起根节点所有子树 _lastExpandedNodesList = _navigationModel->getRootExpandedNodes(); for (auto node : _lastExpandedNodesList) { onTreeViewClicked(node->getModelIndex(), false); } } else { // 修正动画覆盖 _navigationView->resize(_pNavigationBarWidth - 5, _navigationView->height()); for (auto node : _lastExpandedNodesList) { onTreeViewClicked(node->getModelIndex(), false); } } } void ElaNavigationBarPrivate::_handleMaximalToCompactLayout() { // 动画过程布局 while (_navigationButtonLayout->count()) { _navigationButtonLayout->takeAt(0); } if (_isShowUserCard) { _navigationButtonLayout->addSpacing(76); } else { _navigationButtonLayout->addSpacing(40); } _navigationSuggestLayout->addStretch(); while (_userButtonLayout->count()) { _userButtonLayout->takeAt(0); } _userButtonLayout->addSpacing(36); } void ElaNavigationBarPrivate::_handleCompactToMaximalLayout() { // 动画过程布局 while (_navigationButtonLayout->count()) { _navigationButtonLayout->takeAt(0); } _navigationButtonLayout->addSpacing(38); _navigationSuggestLayout->insertSpacing(0, 46); while (_userButtonLayout->count()) { _userButtonLayout->takeAt(0); } if (_isShowUserCard) { _userButtonLayout->addSpacing(74); } } void ElaNavigationBarPrivate::_resetLayout() { // 恢复初始布局 while (_navigationButtonLayout->count()) { _navigationButtonLayout->takeAt(0); } _navigationButtonLayout->addWidget(_navigationButton); _navigationButtonLayout->addWidget(_searchButton); while (_navigationSuggestLayout->count()) { _navigationSuggestLayout->takeAt(0); } _navigationSuggestLayout->addLayout(_navigationButtonLayout); _navigationSuggestLayout->addWidget(_navigationSuggestBox); while (_userButtonLayout->count()) { _userButtonLayout->takeAt(0); } _userButtonLayout->addWidget(_userButton); } void ElaNavigationBarPrivate::_doNavigationBarWidthAnimation(ElaNavigationType::NavigationDisplayMode displayMode, bool isAnimation) { Q_Q(ElaNavigationBar); QPropertyAnimation *navigationBarWidthAnimation = new QPropertyAnimation(q, "maximumWidth"); navigationBarWidthAnimation->setEasingCurve(QEasingCurve::OutCubic); navigationBarWidthAnimation->setStartValue(q->width()); navigationBarWidthAnimation->setDuration(isAnimation ? 285 : 0); switch (displayMode) { case ElaNavigationType::Minimal: { connect(navigationBarWidthAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant &value) { q->setFixedWidth(value.toUInt()); }); navigationBarWidthAnimation->setEndValue(0); break; } case ElaNavigationType::Compact: { connect(navigationBarWidthAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant &value) { q->setFixedWidth(value.toUInt()); }); navigationBarWidthAnimation->setEndValue(47); break; } case ElaNavigationType::Maximal: { connect(navigationBarWidthAnimation, &QPropertyAnimation::finished, this, [=]() { _resetLayout(); }); connect(navigationBarWidthAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant &value) { q->setFixedWidth(value.toUInt()); }); navigationBarWidthAnimation->setEndValue(_pNavigationBarWidth); break; } default: { break; } } navigationBarWidthAnimation->start(QAbstractAnimation::DeleteWhenStopped); } void ElaNavigationBarPrivate::_doNavigationViewWidthAnimation(bool isAnimation) { QPropertyAnimation *navigationViewWidthAnimation = new QPropertyAnimation(this, "pNavigationViewWidth"); connect(navigationViewWidthAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant &value) { _navigationView->setColumnWidth(0, value.toUInt()); }); navigationViewWidthAnimation->setEasingCurve(QEasingCurve::OutCubic); navigationViewWidthAnimation->setStartValue(_navigationView->columnWidth(0)); navigationViewWidthAnimation->setEndValue(40); navigationViewWidthAnimation->setDuration(isAnimation ? 285 : 0); navigationViewWidthAnimation->start(QAbstractAnimation::DeleteWhenStopped); } void ElaNavigationBarPrivate::_doNavigationButtonAnimation(bool isCompact, bool isAnimation) { if (isCompact) { // 导航按钮 QPropertyAnimation *navigationButtonAnimation = new QPropertyAnimation(_navigationButton, "pos"); connect(navigationButtonAnimation, &QPropertyAnimation::finished, this, [=]() { _resetLayout(); }); QPoint navigationButtonPos = _navigationButton->pos(); navigationButtonAnimation->setStartValue(navigationButtonPos); if (_isShowUserCard) { navigationButtonAnimation->setEndValue(QPoint(0, 56)); } else { navigationButtonAnimation->setEndValue(navigationButtonPos); } navigationButtonAnimation->setEasingCurve(QEasingCurve::OutCubic); navigationButtonAnimation->setDuration(isAnimation ? 285 : 0); navigationButtonAnimation->start(QAbstractAnimation::DeleteWhenStopped); } else { QPropertyAnimation *navigationButtonAnimation = new QPropertyAnimation(_navigationButton, "pos"); QPoint navigationButtonPos = _navigationButton->pos(); navigationButtonAnimation->setStartValue(navigationButtonPos); if (_isShowUserCard) { navigationButtonAnimation->setEndValue(QPoint(0, 94)); } else { navigationButtonAnimation->setEndValue(navigationButtonPos); } navigationButtonAnimation->setEasingCurve(QEasingCurve::InOutSine); navigationButtonAnimation->setDuration(isAnimation ? 130 : 0); navigationButtonAnimation->start(QAbstractAnimation::DeleteWhenStopped); } } void ElaNavigationBarPrivate::_doSearchButtonAnimation(bool isCompact, bool isAnimation) { if (isCompact) { QPoint navigationButtonPos = _navigationButton->pos(); // 搜索按钮 QPropertyAnimation *searchButtonAnimation = new QPropertyAnimation(_searchButton, "pos"); if (_isShowUserCard) { searchButtonAnimation->setStartValue(QPoint(200, navigationButtonPos.y())); searchButtonAnimation->setEndValue(QPoint(0, navigationButtonPos.y())); } else { searchButtonAnimation->setStartValue(QPoint(200, navigationButtonPos.y() + 38)); searchButtonAnimation->setEndValue(QPoint(0, navigationButtonPos.y() + 38)); } searchButtonAnimation->setEasingCurve(QEasingCurve::OutCubic); searchButtonAnimation->setDuration(isAnimation ? 285 : 0); searchButtonAnimation->start(QAbstractAnimation::DeleteWhenStopped); _searchButton->setVisible(true); } else { _searchButton->setVisible(false); } } void ElaNavigationBarPrivate::_doUserButtonAnimation(bool isCompact, bool isAnimation) { if (isCompact) { _userCard->setVisible(false); if (_isShowUserCard) { _userButton->setVisible(true); } QPropertyAnimation *userButtonAnimation = new QPropertyAnimation(_userButton, "geometry"); connect(userButtonAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant &value) { _userButton->setFixedSize(value.toRect().size()); }); userButtonAnimation->setEasingCurve(QEasingCurve::OutCubic); userButtonAnimation->setStartValue(QRect(13, 18, 64, 64)); userButtonAnimation->setEndValue(QRect(3, 10, 36, 36)); userButtonAnimation->setDuration(isAnimation ? 285 : 0); userButtonAnimation->start(QAbstractAnimation::DeleteWhenStopped); } else { QPropertyAnimation *userButtonAnimation = new QPropertyAnimation(_userButton, "geometry"); connect(userButtonAnimation, &QPropertyAnimation::finished, this, [=]() { if (_isShowUserCard) { _userCard->setVisible(true); } _userButton->setFixedSize(36, 36); _userButton->setGeometry(QRect(3, 10, 36, 36)); _userButton->setVisible(false); }); connect(userButtonAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant &value) { _userButton->setFixedSize(value.toRect().size()); }); userButtonAnimation->setEasingCurve(QEasingCurve::InOutSine); userButtonAnimation->setStartValue(QRect(3, 10, 36, 36)); userButtonAnimation->setEndValue(QRect(13, 18, 64, 64)); userButtonAnimation->setDuration(isAnimation ? 130 : 0); userButtonAnimation->start(QAbstractAnimation::DeleteWhenStopped); } }