From b23050fdfe1cd5be880c88b3c0934b959809b076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=89=E5=AE=87=E6=B8=85=E9=9F=B3?= <2422523675@qq.com> Date: Sat, 27 Jan 2024 09:47:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9C=80=E6=96=B0=E8=BF=9B=E5=B1=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- QtNovelDesc.pro.user | 2 +- libSplitView/dockpanel.cpp | 231 +++++++++++++++++++++++++---- libSplitView/dockpanel.h | 81 +++++++--- libSplitView/splitpanel.cpp | 29 +++- libSplitView/splitpanel.h | 45 ++++-- libSplitView/splitview_interface.h | 23 ++- 6 files changed, 352 insertions(+), 59 deletions(-) diff --git a/QtNovelDesc.pro.user b/QtNovelDesc.pro.user index 03b5228..641d6ed 100644 --- a/QtNovelDesc.pro.user +++ b/QtNovelDesc.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/libSplitView/dockpanel.cpp b/libSplitView/dockpanel.cpp index 2b79973..4871a23 100644 --- a/libSplitView/dockpanel.cpp +++ b/libSplitView/dockpanel.cpp @@ -10,31 +10,212 @@ using namespace base_view; -split_frame::ResManager *DockPanel::splitManager() const { - if(this->parent_res) - return this->parent_res->splitManager(); - return nullptr; -} - -split_frame::ViewRes *DockPanel::parentRes() const { return this->parent_res; } - -QWidget *DockPanel::widget() const { return const_cast(this); } - -bool DockPanel::canRetrieve() const { return m_retrieve; } - -bool DockPanel::canClose() const { return m_close; } - -bool DockPanel::canReplace() const { return m_replace; } - -QIcon DockPanel::icon() const { return QWidget::windowIcon(); } - -QString DockPanel::title() const { return QWidget::windowTitle(); } - -QSizeF DockPanel::viewSize() const { return this->size(); } - -void DockPanel::resizeView(const QSizeF &outline) { QWidget::resize(outline.toSize()); } - -DragHeader::DragHeader(const QString &title, DockPanel *bind_core) : QFrame(bind_core->widget()) { +DragHeader::DragHeader(const QString &title, DockableView *bind_core) + : QFrame(bind_core), + bind_core(bind_core), + title_holder(new QLabel(this)), + close_btn(new QPushButton("x",this)), + minimal_btn(new QPushButton("-",this)) { setWindowTitle(title); + auto layout = new QHBoxLayout(this); + layout->setSpacing(0); + layout->setContentsMargins(0, 0, 0, 0); + + title_holder->setText(title); + title_holder->setContentsMargins(2,0, 0, 0); + layout->addWidget(title_holder, 1, Qt::AlignLeft); + + minimal_btn->setMinimumSize(22,22); + minimal_btn->setMaximumSize(22,22); + layout->addWidget(minimal_btn, 0, Qt::AlignRight); + connect(minimal_btn, &QPushButton::clicked, this, &DragHeader::retrieveRequest); + + close_btn->setMinimumSize(22,22); + close_btn->setMaximumSize(22,22); + layout->addWidget(close_btn, 0, Qt::AlignRight); + connect(close_btn, &QPushButton::clicked, this, &DragHeader::closeRequest); +} + +DragHeader::DragHeader(const QString &title, const QIcon &icon, DockableView *bind_core) : DragHeader(title, bind_core) { + setWindowIcon(icon); + this->title_holder->setPixmap(icon.pixmap(22, 22)); +} + +void DragHeader::setTitle(const QString &title) +{ + this->title_holder->setText(title); + this->setWindowTitle(title); +} + +void DragHeader::setTitle(const QString &title, const QIcon &icon) +{ + this->setTitle(title); + this->title_holder->setPixmap(icon.pixmap(22, 22)); +} + +void DragHeader::mousePressEvent(QMouseEvent *event) +{ + QFrame::mousePressEvent(event); + this->press_flag = std::make_pair(true, this->mapToParent(event->pos())); +} + +void DragHeader::mouseReleaseEvent(QMouseEvent *event) +{ + QFrame::mouseReleaseEvent(event); + this->press_flag = std::make_pair(false, QPoint()); +} + +void DragHeader::mouseMoveEvent(QMouseEvent *event) +{ + QFrame::mouseMoveEvent(event); + if(std::get<0>(this->press_flag)){ + emit this->adjustRequest(event->pos()); + } +} + + + + + +// =============================================================================== + +DockableView::DockableView(split_frame::ResManager *mgr, QWidget *present, bool drag_header) + : title_header(new DragHeader("未命名", this)), + present_cube(present), + manager_inst(mgr) +{ + if(!drag_header){ + this->title_header->setVisible(false); + } + + auto layout = new QVBoxLayout(this); + layout->addWidget(title_header); + if(present_cube){\ + layout->addWidget(present); + } + else { + layout->addWidget(new QWidget(this)); + } + + layout->setSpacing(0); + layout->setContentsMargins(0, 2, 0, 0); + this->title_header->setMinimumHeight(26); + this->title_header->setMaximumHeight(26); + this->title_header->setFrameShape(QFrame::Shape::Panel); + this->title_header->setFrameShadow(QFrame::Shadow::Raised); + this->title_header->setLineWidth(3); + + this->manager_inst->appendPresentView(this); + connect(this, &QObject::destroyed, [this](){ + this->manager_inst->removePresentView(this); + }); +} + +void DockableView::viewConfig(bool replace, bool close, bool retrieve) +{ + this->m_replace = replace; + this->m_retrieve = retrieve; + this->m_close = close; +} + +void DockableView::setTitle(const QString &title) +{ + this->title_header->setTitle(title); +} + +void DockableView::setTitle(const QIcon &icon, const QString &title) +{ + this->title_header->setTitle(title, icon); + this->icon_store = icon; +} + +void DockableView::adjustAccept(const QPoint &pos) +{ + Q_UNUSED(pos); + + auto drag_trans = new QDrag(this); + auto mime_date = new QMimeData(); + mime_date->setText(QString("view-drags(view-id:%1)").arg(this->hashCode())); + drag_trans->setMimeData(mime_date); + drag_trans->setPixmap(this->grab(this->rect())); + drag_trans->setHotSpot(QPoint(5,5)); + drag_trans->exec(); +} + +void DockableView::closeAccept() +{ + this->manager_inst->doClose(this); +} + +void DockableView::retrieveAccept() +{ + this->manager_inst->doRetrieve(this); +} + +split_frame::ResManager *DockableView::splitManager() const +{ + return this->manager_inst; +} + +split_frame::SplitView *DockableView::parentRes() const +{ + return parent_res; +} + +void DockableView::setParentRes(split_frame::SplitView *inst) +{ + this->parent_res = inst; +} + +QWidget *DockableView::widget() const +{ + return const_cast(this); +} + +bool DockableView::canRetrieve() const +{ + return m_retrieve; +} + +bool DockableView::canClose() const +{ + return m_close; +} + +bool DockableView::canReplace() const +{ + return m_replace; +} + +qulonglong DockableView::hashCode() const +{ + return (qulonglong)this; +} + +QIcon DockableView::icon() const +{ + return icon_store; +} + +QString DockableView::title() const +{ + return title_header->windowTitle(); +} + +QSizeF DockableView::stiffSize() const +{ + auto sizex = present_cube->minimumSize(); + sizex.setHeight(sizex.height() + title_header->height()); + return sizex; +} + +QSizeF DockableView::viewSize() const +{ + return this->size(); +} + +void DockableView::resizeView(const QSizeF &outline) +{ + this->resize(outline.toSize()); } diff --git a/libSplitView/dockpanel.h b/libSplitView/dockpanel.h index 04b51c0..6e227a5 100644 --- a/libSplitView/dockpanel.h +++ b/libSplitView/dockpanel.h @@ -5,23 +5,45 @@ #include #include #include +#include #include namespace base_view { - class DockPanel; + class DockableView; /** * @brief 视图拖拽标题栏 */ class SPLITVIEW_EXPORT DragHeader : public QFrame { - public: - DragHeader(const QString &title, DockPanel *bind_core); - DragHeader(const QString &title, const QIcon &icon, DockPanel *bind_core); - + Q_OBJECT private: - DockPanel *bind_core; + DockableView *const bind_core; + QLabel *const title_holder; + QPushButton *const close_btn, *const minimal_btn; std::tuple press_flag = std::make_tuple(false, QPointF()); + signals: + /** + * @brief 关闭请求 + */ + void closeRequest(); + /** + * @brief 回收请求 + */ + void retrieveRequest(); + /** + * @brief 排版调整请求 + * @param pos 信号源上的位置 + */ + void adjustRequest(const QPoint &pos); + + public: + DragHeader(const QString &title, DockableView *bind_core); + DragHeader(const QString &title, const QIcon &icon, DockableView *bind_core); + + void setTitle(const QString &title); + void setTitle(const QString &title, const QIcon &icon); + // QWidget interface protected: virtual void mousePressEvent(QMouseEvent *event) override; @@ -32,38 +54,61 @@ namespace base_view { /** * @brief 基础内容视图组件 */ - class SPLITVIEW_EXPORT DockPanel : public QWidget, public split_frame::ViewBase { - signals: - void close_request(QWidget*); - void adjust_request(QWidget*); - void retrieve_request(QWidget*); - + class SPLITVIEW_EXPORT DockableView : public QWidget, public split_frame::ViewBase, public split_frame::ViewRes { public: - DockPanel(const QString &title, QWidget *present, bool custom_header = false); + /** + * @brief 构建新的呈现视图实例 + * @param present 内容视图实例 + * @param custom_header 是否添加标题栏 + */ + DockableView(split_frame::ResManager*mgr, QWidget *present, bool drag_header = false); + /** + * @brief 配置视图基本特性 + * @param replace 可以被隐藏和替换 + * @param close 可以被关闭 + * @param retrieve 可以被隐藏 + */ + void viewConfig(bool replace, bool close, bool retrieve); - void setModify(bool replace, bool close, bool retrieve); + /** + * @brief 设置标题栏内容 + * @param title + */ + void setTitle(const QString &title); + void setTitle(const QIcon &icon, const QString &title); + + public slots: + void adjustAccept(const QPoint &pos); + void closeAccept(); + void retrieveAccept(); private: - ViewRes *parent_res = nullptr; + DragHeader *const title_header; + QWidget *const present_cube; + split_frame::ResManager *const manager_inst; + QIcon icon_store; + split_frame::SplitView *parent_res = nullptr; bool m_replace = false, m_retrieve = false, m_close = false; // ViewRes interface public: virtual split_frame::ResManager *splitManager() const override; - virtual split_frame::ViewRes *parentRes() const override; - virtual void setParentRes(ViewRes *inst) override; + virtual split_frame::SplitView *parentRes() const override; + virtual void setParentRes(split_frame::SplitView *inst) override; virtual QWidget *widget() const override; virtual bool canRetrieve() const override; virtual bool canClose() const override; virtual bool canReplace() const override; + virtual qulonglong hashCode() const override; // ViewBase interface public: virtual QIcon icon() const override; virtual QString title() const override; + virtual QSizeF stiffSize() const override; virtual QSizeF viewSize() const override; virtual void resizeView(const QSizeF &outline) override; }; -} // namespace SplitFrame +} #endif // BASEVIEW_H diff --git a/libSplitView/splitpanel.cpp b/libSplitView/splitpanel.cpp index a256bc6..3d6e3f0 100644 --- a/libSplitView/splitpanel.cpp +++ b/libSplitView/splitpanel.cpp @@ -7,6 +7,28 @@ using namespace split_frame; using namespace split_panel; using namespace Config; +DragSplitter::DragSplitter(split_frame::SplitType split, split_frame::ViewRes *parent) + : QFrame(parent->widget()){ + this->setFrameShape(QFrame::Shape::WinPanel); + this->setFrameShadow(QFrame::Shadow::Raised); + + switch (split) { + case split_frame::SplitType::SPLIT_H: + this->setCursor(Qt::CursorShape::SplitHCursor); + break; + default: + this->setCursor(Qt::CursorShape::SizeVerCursor); + } +} + +void DragSplitter::mouseMoveEvent(QMouseEvent *event) +{ + QFrame::mouseMoveEvent(event); + emit this->adjustRequest(mapToParent(event->pos())); +} + + +//===================================================== SplitPanel::SplitPanel(ViewBase *first, ViewBase *next, ViewRes *parent) : QWidget(parent->widget()), parent_inst(parent) { @@ -21,7 +43,7 @@ SplitPanel::~SplitPanel() ResManager *SplitPanel::splitManager() const { return this->parent_inst->splitManager(); } -ViewRes *SplitPanel::parentRes() const +SplitView *SplitPanel::parentRes() const { return parent_inst; } @@ -41,6 +63,11 @@ bool SplitPanel::canReplace() const return true; } +qulonglong SplitPanel::hashCode() const +{ + return (qulonglong)this; +} + QIcon SplitPanel::icon() const { return QIcon(); diff --git a/libSplitView/splitpanel.h b/libSplitView/splitpanel.h index c8b4651..4adfbc8 100644 --- a/libSplitView/splitpanel.h +++ b/libSplitView/splitpanel.h @@ -3,32 +3,65 @@ #include "splitwindow.h" +#include + namespace split_panel { + class DragSplitter : public QFrame{ + Q_OBJECT + signals: + void adjustRequest(QPoint); + + public: + DragSplitter(split_frame::SplitType split, split_frame::ViewRes *parent); + + // QWidget interface + protected: + virtual void mouseMoveEvent(QMouseEvent *event) override; + }; + /** * @brief 分割视图 */ - class SPLITVIEW_EXPORT SplitPanel : public QWidget, public split_frame::SplitView { + class SPLITVIEW_EXPORT SplitPanel : + public QWidget, + public split_frame::SplitView, + public split_frame::ViewBase, + public split_frame::ViewRes + { typedef float split_pos; typedef float split_width; + private: + split_frame::ResManager *const manager_inst; + ViewRes *parent_inst; + std::tuple split_member; + // type, pos, width + std::tuple split_info_value; + + QList view_list() const; + public: - SplitPanel(split_frame::ViewBase *first, split_frame::ViewBase *next, ViewRes *parent); + SplitPanel(split_frame::ResManager *mgr, ViewBase *a, ViewBase *b, split_frame::SplitType split, ViewRes *parent); virtual ~SplitPanel(); + // ViewRes interface public: virtual split_frame::ResManager *splitManager() const override; - virtual ViewRes *parentRes() const override; + virtual split_frame::SplitView *parentRes() const override; + virtual void setParentRes(SplitView *inst) override; virtual bool canRetrieve() const override; virtual bool canClose() const override; virtual bool canReplace() const override; + virtual qulonglong hashCode() const override; // ViewBase interface public: virtual QIcon icon() const override; virtual QString title() const override; virtual QWidget* widget() const override; + virtual QSizeF stiffSize() const override; virtual QSizeF viewSize() const override; virtual void resizeView(const QSizeF &outline) override; @@ -40,13 +73,7 @@ namespace split_panel { virtual float splitterPos() const override; virtual void setSplitInfo(split_frame::SplitType type, float pos, float width) override; - private: - ViewRes *parent_inst; - std::tuple split_member; - // type, pos, width - std::tuple split_info_value; - QList view_list() const; }; } // namespace SplitFrame diff --git a/libSplitView/splitview_interface.h b/libSplitView/splitview_interface.h index b7101c8..b8d6fb3 100644 --- a/libSplitView/splitview_interface.h +++ b/libSplitView/splitview_interface.h @@ -40,8 +40,8 @@ namespace split_frame { * @brief 父资源实例 * @return */ - virtual ViewRes *parentRes() const = 0; - virtual void setParentRes(ViewRes *inst) = 0; + virtual SplitView *parentRes() const = 0; + virtual void setParentRes(SplitView *inst) = 0; /** * @brief 视图组件 @@ -64,12 +64,18 @@ namespace split_frame { * @return */ virtual bool canReplace() const = 0; + + /** + * @brief 资源唯一标号 + * @return + */ + virtual qulonglong hashCode() const = 0; }; /** * @brief 视图展示接口 */ - class ViewBase : public ViewRes { + class ViewBase { public: virtual ~ViewBase() = default; @@ -84,6 +90,12 @@ namespace split_frame { */ virtual QString title() const = 0; + /** + * @brief 不可压缩的最小尺寸 + * @return + */ + virtual QSizeF stiffSize() const = 0; + /** * @brief 获取外形尺寸 * @return @@ -99,7 +111,7 @@ namespace split_frame { /** * @brief 分裂视图规划和约束组件 */ - class SplitView : public ViewBase { + class SplitView { public: virtual ~SplitView() = default; @@ -135,6 +147,7 @@ namespace split_frame { virtual float splitterPos() const = 0; }; + /** * @brief 视图自由状态监听器 */ @@ -178,7 +191,7 @@ namespace split_frame { * @brief 回收视图显示,转换视图为自由(闲置)状态 * @param inst */ - virtual void doRetrieve(ViewRes *inst); + virtual void doRetrieve(ViewRes *inst) = 0; /** * @brief 回收视图,清除内存实例