From 3c818a3e14ef342b444d6efaf648f01e84c34491 Mon Sep 17 00:00:00 2001 From: duanshengchao <519970194@qq.com> Date: Tue, 5 Nov 2024 09:24:21 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=87=AA=E5=AE=9A=E4=B9=89ta?= =?UTF-8?q?bBar=E5=92=8Ctab=EF=BC=8C=E5=AE=9E=E7=8E=B0=E6=8B=96=E5=8A=A8?= =?UTF-8?q?=E5=92=8C=E6=A0=B7=E5=BC=8F=E5=AE=9A=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 12 +++ include/customMenu.h | 2 +- include/customTab.h | 47 +++++++++++ include/customTabBar.h | 43 ++++++++++ include/dashboard.h | 21 +++-- include/dvieMainWindow.h | 9 +- source/customTab.cpp | 169 +++++++++++++++++++++++++++++++++++++ source/customTabBar.cpp | 172 ++++++++++++++++++++++++++++++++++++++ source/dashboard.cpp | 111 +++++++++++------------- source/dvieMainWindow.cpp | 161 +++++++++++++++++++---------------- ui/dvieMainWindow.ui | 74 ++-------------- 11 files changed, 604 insertions(+), 217 deletions(-) create mode 100644 include/customTab.h create mode 100644 include/customTabBar.h create mode 100644 source/customTab.cpp create mode 100644 source/customTabBar.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c38d0a..2cfc331 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,8 @@ set(H_HEADER_FILES include/mainWindow.h include/customBorderContainer.h include/customMenu.h + include/customTab.h + include/customTabBar.h include/functionNavigationBar.h include/dvieMainWindow.h include/tccMainWindow.h @@ -45,6 +47,8 @@ set(CPP_SOURCE_FILES source/mainWindow.cpp source/customBorderContainer.cpp source/customMenu.cpp + source/customTab.cpp + source/customTabBar.cpp source/functionNavigationBar.cpp source/dvieMainWindow.cpp source/tccMainWindow.cpp @@ -76,6 +80,11 @@ set(UI_FILES ui/dateTimeSelectionPanel.ui ) +set(UTIL_FILES + util/TimeLine/timeLineWidget.h + util/TimeLine/timeLineWidget.cpp +) + # 包含源文件目录 INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}) @@ -85,6 +94,7 @@ if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) ${H_HEADER_FILES} ${CPP_SOURCE_FILES} ${UI_FILES} + ${UTIL_FILES} resource/PowerMaster.qrc ) # Define target properties for Android with Qt 6 as: @@ -97,6 +107,7 @@ else() ${H_HEADER_FILES} ${CPP_SOURCE_FILES} ${UI_FILES} + ${UTIL_FILES} resource/PowerMaster.qrc ) # Define properties for Android with Qt 5 after find_package() calls as: @@ -106,6 +117,7 @@ else() ${H_HEADER_FILES} ${CPP_SOURCE_FILES} ${UI_FILES} + ${UTIL_FILES} resource/PowerMaster.qrc ) endif() diff --git a/include/customMenu.h b/include/customMenu.h index 9c91d94..61a5bfd 100644 --- a/include/customMenu.h +++ b/include/customMenu.h @@ -9,7 +9,7 @@ class CustomMenu : public QMenu public: CustomMenu(QWidget *parent = nullptr); - ~CustomMenu(); + virtual ~CustomMenu(); bool mouseIsInside() {return m_bMouseInside;} diff --git a/include/customTab.h b/include/customTab.h new file mode 100644 index 0000000..34521fa --- /dev/null +++ b/include/customTab.h @@ -0,0 +1,47 @@ +#ifndef CUSTOMTAB_H +#define CUSTOMTAB_H + +#include + +class QLabel; +class QBoxLayout; +class CustomTab : public QFrame +{ + Q_OBJECT + +public: + CustomTab(QWidget *parent = nullptr); + virtual ~CustomTab(); + + void setActive(bool); + + void setText(const QString&); + QString text(); + + void setIcon(const QIcon&); + + void setTabBar(const QString); + QString tabBar(); + +signals: + void clicked(); + +protected: + void mousePressEvent(QMouseEvent*); + void mouseMoveEvent(QMouseEvent*); + void mouseReleaseEvent(QMouseEvent*); + +private: + QIcon m_Icon; + QSize m_IconSize; + QLabel* m_pIconLabel; + QLabel* m_pTitle; + QBoxLayout* m_pLayout; + QString m_strTabBar; //所在的tabBar + + QPoint m_pStartPos; + bool m_bLeftButtonPressed; + bool m_bDragging; +}; + +#endif diff --git a/include/customTabBar.h b/include/customTabBar.h new file mode 100644 index 0000000..8b50ff4 --- /dev/null +++ b/include/customTabBar.h @@ -0,0 +1,43 @@ +#ifndef CUSTOMTABBAR_H +#define CUSTOMTABBAR_H + +#include + +class QBoxLayout; +class CustomTab; +class CustomTabBar : public QScrollArea +{ + Q_OBJECT + +public: + CustomTabBar(QWidget *parent = nullptr); + virtual ~CustomTabBar(); + + //void insertTab(int, CustomTab*); + void addTab(CustomTab*); + void removeTab(CustomTab*); + CustomTab* tab(int); + +protected: + void dragEnterEvent(QDragEnterEvent* event) override; + void dragMoveEvent(QDragMoveEvent* event) override; + void dragLeaveEvent(QDragLeaveEvent* event) override; + void dropEvent(QDropEvent* event) override; + +private: + int count(); + +public slots: + void onTabClicked(); + +signals: + void tabMoved(int, int); + +private: + QWidget* m_pTabsContainerWidget; + QBoxLayout* m_pTabsLayout; + int m_nCurrentIndex; + QWidget* m_pPosMarking; +}; + +#endif diff --git a/include/dashboard.h b/include/dashboard.h index 3fc0a2f..983ddaa 100644 --- a/include/dashboard.h +++ b/include/dashboard.h @@ -1,13 +1,12 @@ #ifndef DASHBOARD_H #define DASHBOARD_H +#include "qboxlayout.h" #include -class QMdiArea; -class QPushButton; +class CustomTab; class QMenu; class DataPanel; - class Dashboard : public QObject { Q_OBJECT @@ -18,17 +17,16 @@ public: const QString& getName(); void setName(const QString&); - QPushButton* tabButton(); + void setDisplayAreaLayout(QHBoxLayout*); + CustomTab* tab(); QWidget* displayArea(); - void setSelected(bool); + void setActive(bool); void addPanel(const QString&); void removePanel(const QString&); - -private: - void updateTabButtonSize(); + void deleteSubWidgets(); public slots: - void contextMenu_tabButton(const QPoint&); + void contextMenu_tab(const QPoint&); void onAction_rename(); void onAction_remove(); @@ -40,9 +38,10 @@ signals: private: QString m_strName; - QPushButton* m_pTabButton; - QMenu* m_pTabBtnMenu; + CustomTab* m_pTab; + QMenu* m_pTabMenu; QWidget* m_pDisplayArea; + QHBoxLayout* m_pDisplayAreaLayout; QList m_dataPanels; int m_nPanenlNameNumber; }; diff --git a/include/dvieMainWindow.h b/include/dvieMainWindow.h index bde21fc..382fb3c 100644 --- a/include/dvieMainWindow.h +++ b/include/dvieMainWindow.h @@ -12,6 +12,7 @@ QT_END_NAMESPACE class TransparentMask; class MessageDialog; +class CustomTabBar; class Dashboard; class DashboardNamingDialog; class PanelSelectionDialog; @@ -29,7 +30,8 @@ private: void showTransparentMask(); void hideTransparentMask(); - void addADashboard(const QString&); + void addDashboard(const QString&); + void removeDashboard(const QString&, bool); void setCurrentDashboard(const QString&); protected: @@ -53,6 +55,7 @@ public slots: void onSignal_renameDashboard(); void onSignal_removeDashboard(); void onSignal_dashboardNaming(const QString&, const QString&); + void onSignal_dashboardTabMoved(int, int); //拖动tab引发了位置变化 void onSignal_panelSelectResult(const QString&); void onSignal_viewHistoricalData(QDateTime); @@ -61,8 +64,10 @@ private: Ui::dvieMainWindow* ui; TransparentMask* m_pTransparentMask; MessageDialog* m_pMessageDialog; + CustomTabBar* m_pDashboardTabBar; + QList m_listDashboard; - Dashboard* m_curSelectedDashboard; + Dashboard* m_curActiveDashboard; Dashboard* m_curOperationDashboard; DashboardNamingDialog* m_pDashboardNamingDialog; diff --git a/source/customTab.cpp b/source/customTab.cpp new file mode 100644 index 0000000..c700a3b --- /dev/null +++ b/source/customTab.cpp @@ -0,0 +1,169 @@ +#include "customTab.h" +#include +#include +#include +#include +#include +#include + +CustomTab::CustomTab(QWidget* parent) + :QFrame(parent) +{ + setContextMenuPolicy(Qt::CustomContextMenu); + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + setStyleSheet("QLabel{\n" + " color:rgb(250,250,250);\n" + " font:600 11pt \"微软雅黑\";\n" + " border:0px;\n" + " background-color:transparent;\n" + "}\n"); + + m_bLeftButtonPressed = false; + m_bDragging = false; + + m_pTitle = new QLabel(this); + m_pTitle->setAlignment(Qt::AlignCenter); + + m_IconSize = QSize(15,15); + m_pIconLabel = new QLabel(this); + m_pIconLabel->setMinimumSize(m_IconSize); + m_pIconLabel->setMaximumSize(m_IconSize); + QBoxLayout* iconLayout = new QBoxLayout(QBoxLayout::TopToBottom); + iconLayout->setContentsMargins(0, 1, 0, 0); + iconLayout->addWidget(m_pIconLabel); + QSpacerItem* spacer = new QSpacerItem(10, 40, QSizePolicy::Policy::Minimum, QSizePolicy::Policy::Expanding); + iconLayout->addSpacerItem(spacer); + + m_pLayout = new QBoxLayout(QBoxLayout::LeftToRight); + m_pLayout->setContentsMargins(15, 0, 0, 0); + m_pLayout->setSpacing(1); + m_pLayout->addWidget(m_pTitle); + m_pLayout->addLayout(iconLayout); + setLayout(m_pLayout); + + m_strTabBar = ""; +} + +CustomTab::~CustomTab() +{ +} + +void CustomTab::mousePressEvent(QMouseEvent* event) +{ + if(event->button() == Qt::LeftButton) + { + emit clicked(); + m_pStartPos = event->pos(); + m_bLeftButtonPressed = true; + } + + QFrame::mousePressEvent(event); +} +void CustomTab::mouseMoveEvent(QMouseEvent* event) +{ + if(m_bLeftButtonPressed && !m_bDragging) + { + //qDebug() << "dragging"; + int distance = (event->pos() - m_pStartPos).manhattanLength(); + if (distance >= QApplication::startDragDistance()) + { + QPoint hotSpot = event->pos(); + + QByteArray data; + QDataStream dataStream(&data, QIODevice::WriteOnly); + dataStream << text() << m_strTabBar; + + QMimeData *mimeData = new QMimeData; + mimeData->setData("customTabDrag", data); + + QDrag* drag = new QDrag(this); + drag->setMimeData(mimeData); + drag->setPixmap(grab()); //通过render绘制的pixmap会有噪点,直接通过grab获取效果更好 + drag->setHotSpot(hotSpot); + + m_bDragging = true; + Qt::DropAction dropAction = drag->exec(); + //exec之后的语句都会在drg操作完成之后(鼠标抬起)执行 + delete drag; + m_bLeftButtonPressed = false; + m_bDragging = false; + } + } + + QFrame::mouseMoveEvent(event); +} +void CustomTab::mouseReleaseEvent(QMouseEvent* event) +{ + //如果没有拖动事件发生,在这里处理相关逻辑 + m_bLeftButtonPressed = false; + QFrame::mouseReleaseEvent(event); +} + +void CustomTab::setActive(bool bActive) +{ + QString strStyleSheet = ""; + if(bActive) + strStyleSheet = "QFrame{\n" + " border-bottom:3px solid rgb(67,160,249);\n" + "}\n" + "QFrame:hover{\n" + " background-color:rgba(60, 60, 60, 150);\n" + "}\n" + "QLabel{\n" + " color:rgb(250,250,250);\n" + " font:600 11pt \"微软雅黑\";\n" + " border:0px;\n" + "}\n" + "QLabel:hover{\n" + " background-color:transparent;" + "}\n"; + else + strStyleSheet = "QFrame{\n" + " border-bottom:0px;\n" + "}\n" + "QFrame:hover{\n" + " background-color:rgba(60, 60, 60, 150);\n" + "}\n" + "QLabel{\n" + " color:rgb(250,250,250);\n" + " font:600 11pt \"微软雅黑\";\n" + " border:0px;\n" + "}\n" + "QLabel:hover{\n" + " background-color:transparent;\n" + "}\n"; + setStyleSheet(strStyleSheet); +} + +void CustomTab::setText(const QString& strTitle) +{ + m_pTitle->setText(strTitle); + + QFontMetrics metrics(m_pTitle->font()); + QRect rect = metrics.boundingRect(m_pTitle->text()); + m_pTitle->setMinimumSize(rect.width() + 10, 0); + m_pTitle->setMaximumSize(rect.width() + 10, 1660); + + setObjectName("dashboardTab_" + strTitle); +} +QString CustomTab::text() +{ + return m_pTitle->text(); +} + +void CustomTab::setIcon(const QIcon& icon) +{ + if(icon.isNull()) + m_pIconLabel->clear(); + else + m_pIconLabel->setPixmap(icon.pixmap(m_IconSize)); +} + +void CustomTab::setTabBar(const QString strBar) +{ + m_strTabBar = strBar; +} +QString CustomTab::tabBar() +{ + return m_strTabBar; +} diff --git a/source/customTabBar.cpp b/source/customTabBar.cpp new file mode 100644 index 0000000..ab6ffca --- /dev/null +++ b/source/customTabBar.cpp @@ -0,0 +1,172 @@ +#include "customTabBar.h" +#include "customTab.h" + +#include +#include +#include + +CustomTabBar::CustomTabBar(QWidget* parent) + :QScrollArea(parent) +{ + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + setFrameStyle(QFrame::NoFrame); + setWidgetResizable(true); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + + m_pPosMarking = new QWidget(this); + m_pPosMarking->setStyleSheet("QWidget{\n" + " border:0px;\n" + " background-color:rgb(200,200,200);\n" + "}\n"); + m_pPosMarking->setMaximumWidth(3); + m_pPosMarking->setMinimumWidth(3); + m_pPosMarking->hide(); + + m_nCurrentIndex = -1; + m_pTabsContainerWidget = new QWidget(this); + m_pTabsContainerWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + m_pTabsContainerWidget->setObjectName("tabsContainerWidget"); + m_pTabsLayout = new QBoxLayout(QBoxLayout::LeftToRight); + m_pTabsLayout->setContentsMargins(0, 0, 0, 0); + m_pTabsLayout->setSpacing(0); + m_pTabsLayout->addStretch(1); + m_pTabsContainerWidget->setLayout(m_pTabsLayout); + setWidget(m_pTabsContainerWidget); + + setFocusPolicy(Qt::NoFocus); + setAcceptDrops(true); +} + +CustomTabBar::~CustomTabBar() +{ +} + +void CustomTabBar::dragEnterEvent(QDragEnterEvent* event) +{ + const QMimeData* mimeData = event->mimeData(); + if( mimeData->hasFormat("customTabDrag") ) + { + event->acceptProposedAction(); + //qDebug() << "dragEnterEvent"; + } + else + event->ignore(); +} + +void CustomTabBar::dragMoveEvent(QDragMoveEvent* event) +{ + //qDebug() << "dragMoveEvent"; + event->acceptProposedAction(); + + int toIndex = -1; + int lastWidgetIndex = m_pTabsLayout->count() - 2; + QWidget* lastWidget = m_pTabsLayout->itemAt(lastWidgetIndex)->widget(); + if(lastWidget && event->position().x() > lastWidget->geometry().right()) //移到最后 + toIndex = lastWidgetIndex; + else + { + for (int i = 0; i < count(); ++i) + { + CustomTab* dropTab = tab(i); + if(!dropTab) + continue; + + QRect tabGeometry = dropTab->geometry(); + if( !tabGeometry.contains(event->position().toPoint()) ) + continue; + + toIndex = m_pTabsLayout->indexOf(dropTab); + if(toIndex > 0 && m_pPosMarking->isVisible()) + { + int nIndex = toIndex - 1; + if(m_pTabsLayout->indexOf(m_pPosMarking) == nIndex)//判断上一帧是否已经将posMarking放入到该tab之前 + toIndex = -1; + else if(m_pTabsLayout->indexOf(m_pPosMarking) < toIndex)//在dropTab之前插入了posMarking会让dropTab的索引放生变化(+1) + toIndex -= 1; + } + break; + } + } + + qDebug() << toIndex; + if(toIndex != -1) + { + m_pPosMarking->show(); + m_pTabsLayout->insertWidget(toIndex, m_pPosMarking); + } +} + +void CustomTabBar::dragLeaveEvent(QDragLeaveEvent* event) +{ + qDebug() << "dragLeaveEvent"; +} + +void CustomTabBar::dropEvent(QDropEvent* event) +{ + //qDebug() << "dropEvent"; + + int toIndex = m_pTabsLayout->indexOf(m_pPosMarking); + m_pPosMarking->hide(); + m_pTabsLayout->removeWidget(m_pPosMarking); + + CustomTab* sourceObj = qobject_cast(event->source()); + if(!sourceObj) + return; + int fromIndex = m_pTabsLayout->indexOf(sourceObj); + + if(toIndex > fromIndex)//因为被移动的tab要先remove出来再insert,如果是向后移动,remove会引起索引的变化,所以要-1 + toIndex -= 1; + + if(toIndex != fromIndex) //移动 + { + m_pTabsLayout->removeWidget(sourceObj); + m_pTabsLayout->insertWidget(toIndex, sourceObj); + emit tabMoved(fromIndex, toIndex); + } + + qDebug() << fromIndex << toIndex; +} + +int CustomTabBar::count() +{ + //含有一个stretch + return m_pTabsLayout->count() - 1; +} + +/*void CustomTabBar::insertTab(int index, CustomTab* tab) +{ + if(index < 0) + index = 0; + else if(index > count()) + index = count(); + + m_pTabsLayout->insertWidget(index, tab); + ensureWidgetVisible(tab); //定位到可以显示该tab + m_nCurrentIndex = index; +}*/ + +void CustomTabBar::addTab(CustomTab* tab) +{ + m_pTabsLayout->insertWidget(count(), tab); + ensureWidgetVisible(tab); //定位到可以显示该tab + tab->setTabBar(objectName()); +} +void CustomTabBar::removeTab(CustomTab* tab) +{ + m_pTabsLayout->removeWidget(tab); +} + +CustomTab* CustomTabBar::tab(int index) +{ + if (index >= count() || index < 0) + { + return nullptr; + } + return qobject_cast(m_pTabsLayout->itemAt(index)->widget()); +} + +void CustomTabBar::onTabClicked() +{ + +} diff --git a/source/dashboard.cpp b/source/dashboard.cpp index f83079e..2902042 100644 --- a/source/dashboard.cpp +++ b/source/dashboard.cpp @@ -1,5 +1,6 @@ #include "dashboard.h" #include "dataPanel.h" +#include "customTab.h" #include #include @@ -14,20 +15,15 @@ Dashboard::Dashboard(const QString& strName, QObject *parent) //displayArea m_pDisplayArea = new QWidget(); m_pDisplayArea->setObjectName("displayArea"); + m_pDisplayAreaLayout = nullptr; //m_pDisplayArea->setStyleSheet("QWidget #displayArea {background-color: rgb(18, 25, 30);}"); - //tabButton,自适应text内容 - m_pTabButton = new QPushButton(); - m_pTabButton->setContextMenuPolicy(Qt::CustomContextMenu); - m_pTabButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - m_pTabButton->setStyleSheet("QPushButton{\n" - " font:600 11pt \"微软雅黑\";\n" - " padding-left:5px;\n" - " padding-right:5px;\n" - "}\n"); - connect(m_pTabButton, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(contextMenu_tabButton(const QPoint&))); + //tab,自适应text内容 + m_pTab = new CustomTab(); + //m_pTabButton->setIcon(QIcon(":/images/btn_float_default.png")); + connect(m_pTab, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(contextMenu_tab(const QPoint&))); //右键菜单 - m_pTabBtnMenu = new QMenu(); - m_pTabBtnMenu->setStyleSheet("QMenu{\n" + m_pTabMenu = new QMenu(); + m_pTabMenu->setStyleSheet("QMenu{\n" " background-color:rgb(36,43,50);\n" " border:1px solid rgb(6, 6, 6);\n" "}\n" @@ -41,8 +37,8 @@ Dashboard::Dashboard(const QString& strName, QObject *parent) "QMenu:item:selected{\n" " background-color: rgba(67,160,249, 80);\n" "}\n"); - m_pTabBtnMenu->addAction(QString::fromWCharArray(L"删除"), this, SLOT(onAction_remove())); - m_pTabBtnMenu->addAction(QString::fromWCharArray(L"重命名"), this, SLOT(onAction_rename())); + m_pTabMenu->addAction(QString::fromWCharArray(L"删除"), this, SLOT(onAction_remove())); + m_pTabMenu->addAction(QString::fromWCharArray(L"重命名"), this, SLOT(onAction_rename())); m_nPanenlNameNumber = 0; @@ -51,34 +47,27 @@ Dashboard::Dashboard(const QString& strName, QObject *parent) Dashboard::~Dashboard() { - //m_pMdiArea和m_pTabButton不需要进行以下手动析构,因为QObject建立起的父子结构会自动析构,自动析构时不会将其置为nullptr,所以if判断无效,会引起'SIGSEGV'(存储器段错误)报错 - if(m_pTabBtnMenu) + //在这里m_pDisplayArea和m_pTabButton不需要进行手动析构,因为QObject建立起的父子结构会自动析构,自动析构时不会将其置为nullptr,所以if判断无效,会引起'SIGSEGV'(存储器段错误)报错 + if(m_pTabMenu) { - delete m_pTabBtnMenu; - m_pTabBtnMenu = nullptr; + delete m_pTabMenu; + m_pTabMenu = nullptr; } } -void Dashboard::updateTabButtonSize() +void Dashboard::deleteSubWidgets() { - QFontMetrics metrics(m_pTabButton->font()); - QRect rect = metrics.boundingRect(m_pTabButton->text()); - m_pTabButton->setMinimumSize(rect.width() + 30, tabButtonHeight); - m_pTabButton->setMaximumSize(rect.width() + 30, tabButtonHeight); - - /*int nWidth = 0; - for(int n=0; n= 0x4E00 && uni <= 0x9FA5) //为汉字 - nWidth += 12; - else - nWidth += 7; + delete m_pTab; + m_pTab = nullptr; + } + + if(m_pDisplayArea) + { + delete m_pDisplayArea; + m_pDisplayArea = nullptr; } - nWidth += 35; - m_pTabButton->setMinimumSize(nWidth, tabButtonHeight); - m_pTabButton->setMaximumSize(nWidth, tabButtonHeight);*/ } const QString& Dashboard::getName() @@ -88,13 +77,17 @@ const QString& Dashboard::getName() void Dashboard::setName(const QString& strName) { m_strName = strName; - m_pTabButton->setText(strName); - updateTabButtonSize(); + m_pTab->setText(strName); } -QPushButton* Dashboard::tabButton() +void Dashboard::setDisplayAreaLayout(QHBoxLayout* pLayout) { - return m_pTabButton; + m_pDisplayAreaLayout = pLayout; +} + +CustomTab* Dashboard::tab() +{ + return m_pTab; } QWidget* Dashboard::displayArea() @@ -102,30 +95,20 @@ QWidget* Dashboard::displayArea() return m_pDisplayArea; } -void Dashboard::setSelected(bool bSelected) +void Dashboard::setActive(bool bActive) { - QString strStyleSheet = ""; - if(bSelected) - strStyleSheet = "QPushButton{\n" - " color:rgb(250,250,250);\n" - " font:600 11pt \"微软雅黑\";\n" - " border-bottom:3px solid rgb(67,160,249);\n" - "}\n" - "QPushButton:hover{\n" - " background-color: rgba(60, 60, 60, 150);\n" - "}\n"; - else - strStyleSheet = "QPushButton{\n" - " color:rgb(220,220,220);\n" - " font:11pt \"微软雅黑\";\n" - " border-bottom:0px;\n" - "}\n" - "QPushButton:hover{\n" - " background-color: rgba(60, 60, 60, 150);\n" - "}\n"; + if(bActive && m_pDisplayAreaLayout) + { + m_pDisplayAreaLayout->addWidget(m_pDisplayArea); + m_pDisplayArea->show(); + } + else if(!bActive && m_pDisplayAreaLayout) + { + m_pDisplayAreaLayout->removeWidget(m_pDisplayArea); + m_pDisplayArea->hide(); + } - m_pTabButton->setStyleSheet(strStyleSheet); - updateTabButtonSize(); + m_pTab->setActive(bActive); } void Dashboard::addPanel(const QString& strType) @@ -164,10 +147,10 @@ void Dashboard::removePanel(const QString& strName) } } -void Dashboard::contextMenu_tabButton(const QPoint& pos) +void Dashboard::contextMenu_tab(const QPoint& pos) { - QPoint originPoint = m_pTabButton->mapToGlobal(QPoint(0, 0)); - m_pTabBtnMenu->popup(originPoint + pos); + QPoint originPoint = m_pTab->mapToGlobal(QPoint(0, 0)); + m_pTabMenu->popup(originPoint + pos); } void Dashboard::onAction_remove() diff --git a/source/dvieMainWindow.cpp b/source/dvieMainWindow.cpp index 03915b8..99507ba 100644 --- a/source/dvieMainWindow.cpp +++ b/source/dvieMainWindow.cpp @@ -2,7 +2,9 @@ #include "./ui_dvieMainWindow.h" #include "transparentMask.h" #include "messageDialog.h" +#include "customTabBar.h" #include "dashboard.h" +#include "customTab.h" #include "dashboardNamingDialog.h" #include "panelSelectionDialog.h" #include "dateTimeWidget.h" @@ -10,14 +12,17 @@ #include #include #include +#include +#include DvieMainWindow::DvieMainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::dvieMainWindow) , m_pTransparentMask(nullptr) , m_pMessageDialog(nullptr) + , m_pDashboardTabBar(nullptr) , m_pDashboardNamingDialog(nullptr) - , m_curSelectedDashboard(nullptr) + , m_curActiveDashboard(nullptr) , m_curOperationDashboard(nullptr) , m_pPanelSelectionDialog(nullptr) { @@ -29,6 +34,11 @@ DvieMainWindow::DvieMainWindow(QWidget *parent) connect(m_pDateTimeWidget, SIGNAL(hideMask()), this, SLOT(onSignal_hideMask())); connect(m_pDateTimeWidget, SIGNAL(viewHistoricalData(QDateTime)), this, SLOT(onSignal_viewHistoricalData(QDateTime))); + m_pDashboardTabBar = new CustomTabBar(this); + m_pDashboardTabBar->setObjectName("mainWindow_Bar"); + ui->hLayout_dashboardTabBar->addWidget(m_pDashboardTabBar); + connect(m_pDashboardTabBar, SIGNAL(tabMoved(int, int)), this, SLOT(onSignal_dashboardTabMoved(int, int))); + connect(ui->btnAddDashboard, SIGNAL(clicked()), this, SLOT(onBtnClicked_addDashboard())); connect(ui->btnAddPanel, SIGNAL(clicked()), this, SLOT(onBtnClicked_addDataPanel())); //connect(ui->btnDashboradList1, SIGNAL(clicked()), this, SLOT(onBtnClicked_dashboardList())); @@ -95,34 +105,70 @@ void DvieMainWindow::showMessageDialog(MessageDialogType type,const QString& str m_pMessageDialog->show(); } -void DvieMainWindow::addADashboard(const QString& strName) +void DvieMainWindow::addDashboard(const QString& strName) { Dashboard* dashboard = new Dashboard(strName, this); connect(dashboard, SIGNAL(sgl_rename()), this, SLOT(onSignal_renameDashboard())); connect(dashboard, SIGNAL(sgl_remove()), this, SLOT(onSignal_removeDashboard())); + dashboard->setDisplayAreaLayout(ui->hLayout_dashboardDisplayArea); - QPushButton* tabButton = dashboard->tabButton(); - QWidget* displayArea = dashboard->displayArea(); - //添加tabButton - int nCount = m_listDashboard.count(); - ui->hLayout_dashboardTab->insertWidget(nCount,tabButton); //已经内置好了一个水平spacer,所以要放置在其之前 - connect(tabButton, SIGNAL(clicked()), this, SLOT(onBtnClicked_dashboardTab())); - //添加mdiArea - QWidget* page = new QWidget(ui->dashboardStack); - QString objName = "page_dashboard_" + strName; - page->setObjectName(objName); - ui->dashboardStack->addWidget(page); - QHBoxLayout* pageLayout = new QHBoxLayout(page); - pageLayout->setContentsMargins(0, 0, 0, 0); - pageLayout->addWidget(displayArea); - displayArea->setParent(page); - ui->dashboardStack->setCurrentWidget(page); + //添加tab + CustomTab* tab = dashboard->tab(); + m_pDashboardTabBar->addTab(tab); + connect(tab, SIGNAL(clicked()), this, SLOT(onBtnClicked_dashboardTab())); m_listDashboard.push_back(dashboard); - dashboard->setSelected(true); - if(m_curSelectedDashboard) - m_curSelectedDashboard->setSelected(false); - m_curSelectedDashboard = dashboard; + if(m_curActiveDashboard) + m_curActiveDashboard->setActive(false); + dashboard->setActive(true); + m_curActiveDashboard = dashboard; +} + +void DvieMainWindow::removeDashboard(const QString& strName, bool bDelete) //右键删除和移动到别的frame下均会调用该函数,只有删除时才会delete +{ + int nIndex = 0; + Dashboard* dashboard = nullptr; + for(int n=0; ngetName() == strName) + { + nIndex = n; + dashboard = m_listDashboard.at(n); + break; + } + } + if( !dashboard ) + return; + + if(dashboard == m_curActiveDashboard) //删除的是当前所选 + { + dashboard->setActive(false); + if(m_listDashboard.count() == 1) //唯一一个 + m_curActiveDashboard = nullptr; + else + { + if(nIndex != 0) //不是第一个,将其前一个置为选中状态 + { + m_listDashboard.at(nIndex - 1)->setActive(true); + m_curActiveDashboard = m_listDashboard.at(nIndex - 1); + } + else //是第一个,将下一个置为选中状态 + { + m_listDashboard.at(nIndex + 1)->setActive(true); + m_curActiveDashboard = m_listDashboard.at(nIndex + 1); + } + } + } + + CustomTab* tab = dashboard->tab(); + if(tab) + m_pDashboardTabBar->removeTab(tab); + m_listDashboard.removeAt(nIndex); + if(bDelete) + { + dashboard->deleteSubWidgets(); + delete dashboard; + } } void DvieMainWindow::setCurrentDashboard(const QString& strName) @@ -131,13 +177,14 @@ void DvieMainWindow::setCurrentDashboard(const QString& strName) { if(m_listDashboard.at(n)->getName() == strName) { - if(m_listDashboard.at(n) == m_curSelectedDashboard) + if(m_listDashboard.at(n) == m_curActiveDashboard) return; - ui->dashboardStack->setCurrentIndex(n); - m_listDashboard.at(n)->setSelected(true); - m_curSelectedDashboard->setSelected(false); - m_curSelectedDashboard = m_listDashboard.at(n); + m_curActiveDashboard->setActive(false); + m_listDashboard.at(n)->setActive(true); + CustomTab* tab = m_listDashboard.at(n)->tab(); + m_pDashboardTabBar->ensureWidgetVisible(tab); + m_curActiveDashboard = m_listDashboard.at(n); } } } @@ -231,7 +278,7 @@ void DvieMainWindow::onBtnClicked_dashboardList() void DvieMainWindow::onBtnClicked_dashboardTab() { - QPushButton* pBtn = qobject_cast(sender()); + CustomTab* pBtn = qobject_cast(sender()); QString strName = pBtn->text(); setCurrentDashboard(strName); } @@ -261,65 +308,33 @@ void DvieMainWindow::onSignal_dashboardNaming(const QString& strName, const QStr } if(strUsedFor == "create") - addADashboard(strName); + addDashboard(strName); else if(strUsedFor == "rename" && m_curOperationDashboard) m_curOperationDashboard->setName(strName); m_pDashboardNamingDialog->hide(); hideTransparentMask(); } +void DvieMainWindow::onSignal_dashboardTabMoved(int nFromIndex, int nToIndex) +{ + //同步相应数据在其存储接结构中的位置 + Dashboard* movingDashboard = m_listDashboard.takeAt(nFromIndex); + m_listDashboard.insert(nToIndex, movingDashboard); +} + void DvieMainWindow::onSignal_removeDashboard() { - m_curOperationDashboard = qobject_cast(sender()); - if(m_curOperationDashboard) + Dashboard* dashboard = qobject_cast(sender()); + if(dashboard) { showTransparentMask(); - QString strName = m_curOperationDashboard->getName(); + QString strName = dashboard->getName(); QString strMsg = QString::fromStdWString(L"确认删除名为 \"") + strName + QString::fromStdWString(L"\" 的数据看板吗?"); showMessageDialog(type_question, QString::fromStdWString(L"删除看板"), strMsg); if(g_msgDlgBtn == btn_No) return; - - QPushButton* tabButton = m_curOperationDashboard->tabButton(); - QWidget* displayArea = m_curOperationDashboard->displayArea(); - if(tabButton) - { - ui->dashboardStack->removeWidget(tabButton); - delete tabButton; - } - if(displayArea) - { - QWidget* page = displayArea->parentWidget(); - if(page) - { - ui->dashboardStack->removeWidget(page); - delete page; - } - } - - int nIndex = 0; - for(int n=0; nsetSelected(true); - } - else - m_curSelectedDashboard = nullptr; - } - m_listDashboard.removeAt(nIndex); - delete m_curOperationDashboard; - m_curOperationDashboard = nullptr; + removeDashboard(strName, true); } } @@ -346,7 +361,7 @@ void DvieMainWindow::onSignal_panelSelectResult(const QString& strType) { //m_pPanelSelectionDialog->hide(); hideTransparentMask(); - m_curSelectedDashboard->addPanel(strType); + m_curActiveDashboard->addPanel(strType); } void DvieMainWindow::onSignal_viewHistoricalData(QDateTime dateTime) diff --git a/ui/dvieMainWindow.ui b/ui/dvieMainWindow.ui index 69ea274..e52e18a 100644 --- a/ui/dvieMainWindow.ui +++ b/ui/dvieMainWindow.ui @@ -179,7 +179,7 @@ font: 700 12pt "微软雅黑"; - Qt::Horizontal + Qt::Orientation::Horizontal @@ -263,7 +263,7 @@ font: 10pt "微软雅黑"; TakeCare1987 - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -334,7 +334,7 @@ QPushButton:pressed - background-color: rgba(39, 102, 59, 200); + background-color: rgba(0, 141, 212, 80); @@ -630,7 +630,7 @@ border-bottom:0px; 0 - + 0 @@ -725,63 +725,6 @@ QPushButton:pressed - - - - border:0px; -background-color:transparent; - - - Qt::ScrollBarAsNeeded - - - Qt::ScrollBarAsNeeded - - - true - - - - - 0 - 0 - 1188 - 50 - - - - - 0 - - - 0 - - - 6 - - - 0 - - - 0 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - @@ -870,7 +813,7 @@ QPushButton:pressed - + 0 @@ -886,9 +829,6 @@ QPushButton:pressed 0 - - - @@ -897,6 +837,8 @@ QPushButton:pressed - + + +