From b325b5f2e1fa047a0eebab5e2d53d98654bb7a10 Mon Sep 17 00:00:00 2001 From: duanshengchao <519970194@qq.com> Date: Tue, 15 Apr 2025 16:39:36 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0customBorderContainer?= =?UTF-8?q?=E5=92=8CmaskManager=E5=85=AC=E5=85=B1=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 2 + include/attributeTableModel.h | 13 ++ include/connectionDialog.h | 3 + include/customBorderContainer.h | 96 +++++++++++++++ include/global.h | 12 -- include/maskManager.h | 2 +- source/connectionDialog.cpp | 4 + source/customBorderContainer.cpp | 202 +++++++++++++++++++++++++++++++ source/maskManager.cpp | 10 +- 9 files changed, 326 insertions(+), 18 deletions(-) create mode 100644 include/customBorderContainer.h create mode 100644 source/customBorderContainer.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e3ebd0e..9d3245e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,7 @@ set(H_HEADER_FILES include/attributeView.h include/attributeSelector.h include/maskManager.h + include/customBorderContainer.h ) set(CPP_SOURCE_FILES @@ -66,6 +67,7 @@ set(CPP_SOURCE_FILES source/attributeView.cpp source/attributeSelector.cpp source/maskManager.cpp + source/customBorderContainer.cpp ) set(UI_FILES diff --git a/include/attributeTableModel.h b/include/attributeTableModel.h index 74be095..89b6cd2 100644 --- a/include/attributeTableModel.h +++ b/include/attributeTableModel.h @@ -24,6 +24,16 @@ class AttributeTableModel : public QAbstractTableModel Q_OBJECT public: + enum EditStateFlag + { + Clean = 0, // 二进制: 0b0000 + Modified = 1 << 0, // 二进制: 0b0001 + New = 1 << 1, // 二进制: 0b0010 + Deleted = 1 << 2 // 二进制: 0b0100 + }; + //创建 QFlags 包装类型 + Q_DECLARE_FLAGS(EditState, EditStateFlag) + struct DataType //数据类型 { int id; @@ -114,4 +124,7 @@ private: QHash m_reversalDataTypes; //dataType的反转,用来通过名称快速查找对应id }; +//生成运算符重载 +Q_DECLARE_OPERATORS_FOR_FLAGS(AttributeTableModel::EditState) + #endif //ATTRIBUTETABLEMODEL_H diff --git a/include/connectionDialog.h b/include/connectionDialog.h index 692b778..1b4eadf 100644 --- a/include/connectionDialog.h +++ b/include/connectionDialog.h @@ -12,6 +12,7 @@ class ConnectionDialog; } QT_END_NAMESPACE +class CustomBorderContainer; class ConnectionDialog : public QDialog { Q_OBJECT @@ -40,6 +41,8 @@ private: bool m_isNewStatus;//是否是新建链接编辑状态 int m_curConnListRow; + CustomBorderContainer* m_customBorderContainer; + signals: void addConnection(DatabaseConfig&); diff --git a/include/customBorderContainer.h b/include/customBorderContainer.h new file mode 100644 index 0000000..d9efbc4 --- /dev/null +++ b/include/customBorderContainer.h @@ -0,0 +1,96 @@ +/** + *\brief 自定义边框容器类,可以挂载给任意采用无系统边框的widget上,进而实现widget的缩放、移动等功能 + * + *\author dsc + */ +#ifndef CUSTOMBORDERCONTAINER_H +#define CUSTOMBORDERCONTAINER_H + +#include +#include +#include +#include +#include + +class CustomBorderContainer : public QObject +{ + Q_OBJECT + +public: + enum borderType + { + border_left = 0, + border_right, + border_top, + border_bottom, + border_leftTop, + border_leftBottom, + border_rightTop, + border_rightBottom, + border_move + }; + + enum OperationOption + { + NoOperation = 0, // 二进制: 0b0000 + Movable = 1 << 0, // 二进制: 0b0001 + Resizable = 1 << 1, // 二进制: 0b0010 + DefaultOperation = Movable | Resizable + }; + //创建 QFlags 包装类型 + Q_DECLARE_FLAGS(OperationOptions, OperationOption) + + explicit CustomBorderContainer(QWidget* parent, QSize minimumSize = QSize(50, 50), int borderSize = 3); + ~CustomBorderContainer(); + + void setMinimumWindowSize(QSize); + void setBorderSize(int); + void setOperationOptions(OperationOptions); + void updateBorder(); + void updateContentWidget(); + +private: + //内部类 + class Border : public QLabel + { + public: + explicit Border(QWidget* parent, borderType type, CustomBorderContainer* container); + + protected: + void mousePressEvent(QMouseEvent*); + void mouseMoveEvent(QMouseEvent*); + void mouseReleaseEvent(QMouseEvent*); + void timerEvent(QTimerEvent*); + + private: + borderType m_type; + QPoint m_mouseLastPoint; + QPoint m_mouseMoveLength; + bool m_mouseIsPressed; + CustomBorderContainer* m_contaniner; + QBasicTimer m_repaintTimer; + }; + + void initializeBorder(); + void scaleByCustomBorder(borderType, const QPoint&); + + QWidget* m_contentWidget; + QSize m_minimumSize; + int m_borderSize; + //borders + Border* m_borderLeft; + Border* m_borderRight; + Border* m_borderTop; + Border* m_borderBottom; + Border* m_borderLeftTop; + Border* m_borderLeftBottom; + Border* m_borderRightTop; + Border* m_borderRightBottom; + Border* m_borderMove; //用于移动的border + OperationOptions m_operationOptions; +}; + +//生成运算符重载(不能放在类的内部) +Q_DECLARE_OPERATORS_FOR_FLAGS(CustomBorderContainer::OperationOptions) + +#endif //CUSTOMBORDERCONTAINER_H diff --git a/include/global.h b/include/global.h index 7483278..3303e14 100644 --- a/include/global.h +++ b/include/global.h @@ -11,18 +11,6 @@ enum DialogState DS_Edit }; -enum EditStateFlag -{ - Clean = 0, // 二进制: 0b0000 - Modified = 1 << 0, // 二进制: 0b0001 - New = 1 << 1, // 二进制: 0b0010 - Deleted = 1 << 2 // 二进制: 0b0100 -}; -//创建 QFlags 包装类型 -Q_DECLARE_FLAGS(EditState, EditStateFlag) -//生成运算符重载 -Q_DECLARE_OPERATORS_FOR_FLAGS(EditState) - struct DatabaseConfig { QString strID; //存储在配置文件时用作唯一标识 diff --git a/include/maskManager.h b/include/maskManager.h index 4f93a5d..194ba0d 100644 --- a/include/maskManager.h +++ b/include/maskManager.h @@ -24,7 +24,7 @@ private: static MaskManager* m_instance; QWidget* m_mainWindow; QWidget* m_maskLayer; - QSet m_activeRequsets; + QSet m_activeRequests; }; #endif //MASKMANAGER_H diff --git a/source/connectionDialog.cpp b/source/connectionDialog.cpp index ec3743a..c9a1fd7 100644 --- a/source/connectionDialog.cpp +++ b/source/connectionDialog.cpp @@ -3,6 +3,7 @@ #include "mainwindow.h" #include "settings.h" #include "tableWidgetHoverDelegate.h" +#include "customBorderContainer.h" #include #define itemID 1 @@ -18,6 +19,9 @@ ConnectionDialog::ConnectionDialog(QWidget *parent) //Linux下默认的Qt::Dialog即使有父窗口也无法按照子窗口的行为进行展示,并且最大、最小按钮不好关闭,因此需要去掉Dialog属性,随之而来的问题是,模态无法起作用 setWindowFlags(windowFlags() & ~Qt::Dialog); setStyleSheet("QDialog{border: 1px solid rgb(205,205,205);border-radius:5px;background-color:rgb(245,245,245);}"); + + m_customBorderContainer = new CustomBorderContainer(this); + m_customBorderContainer->setOperationOptions(CustomBorderContainer::Movable | CustomBorderContainer::Resizable); } else { diff --git a/source/customBorderContainer.cpp b/source/customBorderContainer.cpp new file mode 100644 index 0000000..51c55df --- /dev/null +++ b/source/customBorderContainer.cpp @@ -0,0 +1,202 @@ +#include "customBorderContainer.h" +#include + +//Class Border +CustomBorderContainer::Border::Border(QWidget* parent, borderType type, CustomBorderContainer* container) + : QLabel(parent) + , m_type(type) + , m_contaniner(container) +{ + switch(m_type) + { + case border_left: + case border_right: + setCursor(Qt::SizeHorCursor); + break; + case border_top: + case border_bottom: + setCursor(Qt::SizeVerCursor); + break; + case border_leftTop: + case border_rightBottom: + setCursor(Qt::SizeFDiagCursor); + break; + case border_rightTop: + case border_leftBottom: + setCursor(Qt::SizeBDiagCursor); + break; + default: + setCursor(Qt::ArrowCursor); + break; + } +} + +void CustomBorderContainer::Border::mousePressEvent(QMouseEvent* event) +{ + if(m_contaniner->m_operationOptions == NoOperation) + return; + + if(event->button() != Qt::LeftButton) + return; + + m_mouseIsPressed = true; + m_mouseLastPoint = event->globalPosition().toPoint(); + + QLabel::mousePressEvent(event); +} + +void CustomBorderContainer::Border::mouseMoveEvent(QMouseEvent* event) +{ + if(m_mouseIsPressed) + { + m_mouseMoveLength = event->globalPosition().toPoint() - m_mouseLastPoint; + m_contaniner->scaleByCustomBorder(m_type, m_mouseMoveLength); + m_mouseLastPoint = event->globalPosition().toPoint(); + } + + QLabel::mouseMoveEvent(event); +} + +void CustomBorderContainer::Border::mouseReleaseEvent(QMouseEvent* event) +{ + Q_UNUSED(event) + m_mouseIsPressed = false; + m_contaniner->updateBorder(); + + QLabel::mouseReleaseEvent(event); +} + +void CustomBorderContainer::Border::timerEvent(QTimerEvent* event) +{ + if(event->timerId() == m_repaintTimer.timerId()) + { + m_repaintTimer.stop(); + m_contaniner->updateContentWidget(); + } +} + +//Class CustomBorderContainer +CustomBorderContainer::CustomBorderContainer(QWidget *parent, QSize minimumSize, int borderSize) + : QObject(parent) + , m_contentWidget(parent) + , m_minimumSize(minimumSize) + , m_borderSize(borderSize) +{ + m_operationOptions = NoOperation; + initializeBorder(); +} + +CustomBorderContainer::~CustomBorderContainer() +{} + +void CustomBorderContainer::initializeBorder() +{ + m_borderLeft = new Border(m_contentWidget, border_left, this); + m_borderLeft->setStyleSheet("background-color:transparent"); + m_borderLeft->raise(); + + m_borderRight = new Border(m_contentWidget, border_right, this); + m_borderRight->setStyleSheet("background-color:transparent"); + m_borderRight->raise(); + + m_borderTop = new Border(m_contentWidget, border_top, this); + m_borderTop->setStyleSheet("background-color:transparent"); + m_borderTop->raise(); + + m_borderBottom = new Border(m_contentWidget, border_bottom, this); + m_borderBottom->setStyleSheet("background-color:transparent"); + m_borderBottom->raise(); + + m_borderLeftTop = new Border(m_contentWidget, border_leftTop, this); + m_borderLeftTop->setStyleSheet("background-color:transparent"); + m_borderLeftTop->raise(); + + m_borderLeftBottom = new Border(m_contentWidget, border_leftBottom, this); + m_borderLeftBottom->setStyleSheet("background-color:transparent"); + m_borderLeftBottom->raise(); + + m_borderRightTop = new Border(m_contentWidget, border_rightTop, this); + m_borderRightTop->setStyleSheet("background-color:transparent"); + m_borderRightTop->raise(); + + m_borderRightBottom = new Border(m_contentWidget, border_rightBottom, this); + m_borderRightBottom->setStyleSheet("background-color:transparent"); + m_borderRightBottom->raise(); + + m_borderMove = new Border(m_contentWidget, border_move, this); + m_borderMove->setStyleSheet("background-color:transparent"); + m_borderMove->raise(); + + updateBorder(); +} + +void CustomBorderContainer::scaleByCustomBorder(borderType type, const QPoint& moveLength) +{ + switch (type) + { + case border_left: + m_contentWidget->setGeometry(m_contentWidget->pos().x() + moveLength.x(), m_contentWidget->pos().y(), m_contentWidget->width() - moveLength.x(), m_contentWidget->height()); + break; + case border_right: + m_contentWidget->setGeometry(m_contentWidget->pos().x(), m_contentWidget->pos().y(), m_contentWidget->width() + moveLength.x(), m_contentWidget->height()); + break; + case border_top: + m_contentWidget->setGeometry(m_contentWidget->pos().x(), m_contentWidget->pos().y() + moveLength.y(), m_contentWidget->width(), m_contentWidget->height() - moveLength.y()); + break; + case border_bottom: + m_contentWidget->setGeometry(m_contentWidget->pos().x(), m_contentWidget->pos().y(), m_contentWidget->width(), m_contentWidget->height() + moveLength.y()); + break; + case border_leftTop: + m_contentWidget->setGeometry(m_contentWidget->pos().x() + moveLength.x(), m_contentWidget->pos().y() + moveLength.y(), m_contentWidget->width() - moveLength.x(), m_contentWidget->height() - moveLength.y()); + break; + case border_leftBottom: + m_contentWidget->setGeometry(m_contentWidget->pos().x() + moveLength.x(), m_contentWidget->pos().y(), m_contentWidget->width() - moveLength.x(), m_contentWidget->height() + moveLength.y()); + break; + case border_rightTop: + m_contentWidget->setGeometry(m_contentWidget->pos().x(), m_contentWidget->pos().y() + moveLength.y(), m_contentWidget->width() + moveLength.x(), m_contentWidget->height() - moveLength.y()); + break; + case border_rightBottom: + m_contentWidget->setGeometry(m_contentWidget->pos().x(), m_contentWidget->pos().y(), m_contentWidget->width() + moveLength.x(), m_contentWidget->height() + moveLength.y()); + break; + case border_move: + m_contentWidget->move(moveLength + m_contentWidget->pos()); + break; + default: + break; + } + + //m_borderMove->setGeometry(m_borderSize, m_borderSize, m_contentWidget->width() - m_borderSize * 2, m_borderSize * 10); +} + +void CustomBorderContainer::setMinimumWindowSize(QSize size) +{ + m_minimumSize = size; +} + +void CustomBorderContainer::setBorderSize(int size) +{ + m_borderSize = size; +} + +void CustomBorderContainer::setOperationOptions(OperationOptions options) +{ + m_operationOptions = options; +} + +void CustomBorderContainer::updateBorder() +{ + m_borderLeft->setGeometry(0, m_borderSize, m_borderSize, m_contentWidget->height() - m_borderSize * 2); + m_borderTop->setGeometry(m_borderSize, 0, m_contentWidget->width() - m_borderSize * 2, m_borderSize); + m_borderRight->setGeometry(m_contentWidget->width() - m_borderSize, m_borderSize, m_borderSize, m_contentWidget->height() - m_borderSize * 2); + m_borderBottom->setGeometry(m_borderSize, m_contentWidget->height() - m_borderSize, m_contentWidget->width() - m_borderSize * 2, m_borderSize); + m_borderLeftTop->setGeometry(0, 0, m_borderSize, m_borderSize); + m_borderLeftBottom->setGeometry(0, m_contentWidget->height() - m_borderSize, m_borderSize, m_borderSize); + m_borderRightTop->setGeometry(m_contentWidget->width() - m_borderSize, 0, m_borderSize, m_borderSize); + m_borderRightBottom->setGeometry(m_contentWidget->width() - m_borderSize, m_contentWidget->height() - m_borderSize, m_borderSize, m_borderSize); + m_borderMove->setGeometry(m_borderSize, m_borderSize, m_contentWidget->width() - m_borderSize * 2, m_borderSize * 10); +} + +void CustomBorderContainer::updateContentWidget() +{ + m_contentWidget->update(); +} diff --git a/source/maskManager.cpp b/source/maskManager.cpp index e503b62..ae68a22 100644 --- a/source/maskManager.cpp +++ b/source/maskManager.cpp @@ -37,20 +37,20 @@ bool MaskManager::eventFilter(QObject* obj, QEvent* event) return QObject::eventFilter(obj, event); } -void MaskManager::showMask(QWidget* requseter) +void MaskManager::showMask(QWidget* requester) { - if(m_activeRequsets.isEmpty()) + if(m_activeRequests.isEmpty()) { m_maskLayer->setGeometry(m_mainWindow->rect()); //m_maskLayer->raise(); //显示在最上层,后续打开的同级子窗口依然在其之上 m_maskLayer->show(); } - m_activeRequsets.insert(requseter); + m_activeRequests.insert(requester); } void MaskManager::hideMask(QWidget* requester) { - m_activeRequsets.remove(requester); - if(m_activeRequsets.isEmpty()) + m_activeRequests.remove(requester); + if(m_activeRequests.isEmpty()) m_maskLayer->hide(); }