From bd9a4c156e00f4c6caa4acbd0b263f5944ff3bd2 Mon Sep 17 00:00:00 2001 From: codeboss <2422523675@qq.com> Date: Sun, 11 Feb 2024 21:24:02 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9F=BA=E7=A1=80=E7=89=88=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- libSplitView/AcceptPanel.cpp | 1 + libSplitView/DockPanel.cpp | 2 + libSplitView/DockPanel.h | 13 ++---- libSplitView/SplitPanel.cpp | 4 +- libSplitView/SplitWindow.cpp | 78 ++++++++++++++++++++++++------------ libSplitView/SplitWindow.h | 11 +++-- libSplitView/libSplitView.h | 11 ++++- 7 files changed, 77 insertions(+), 43 deletions(-) diff --git a/libSplitView/AcceptPanel.cpp b/libSplitView/AcceptPanel.cpp index 7490726..8a2e7c3 100644 --- a/libSplitView/AcceptPanel.cpp +++ b/libSplitView/AcceptPanel.cpp @@ -136,6 +136,7 @@ void accept_panel::AcceptPanel::dropEvent(QDropEvent *ev) if(pinst){ pinst->replaceView(view, anchor_view); view_manager->doRetrieve(anchor_view); + dynamic_cast(view_manager)->freedomHasBeenRemoved(view); }else{ view_manager->doRetrieve(anchor_view); dynamic_cast(view_manager)->setPresentTarget(view); diff --git a/libSplitView/DockPanel.cpp b/libSplitView/DockPanel.cpp index 5b1776d..4f9c26a 100644 --- a/libSplitView/DockPanel.cpp +++ b/libSplitView/DockPanel.cpp @@ -124,6 +124,8 @@ DockableView::DockableView(split_frame::ResManager *mgr, QWidget *present) connect(this->title_header, &DragHeader::retrieveRequest, this, &DockableView::retrieveAccept); connect(this->title_header, &DragHeader::closeRequest, this, &DockableView::closeAccept); connect(this->title_header, &DragHeader::adjustRequest, this, &DockableView::adjustAccept); + + viewConfig(m_replace, m_close, m_retrieve); } DockableView::~DockableView() { diff --git a/libSplitView/DockPanel.h b/libSplitView/DockPanel.h index 7901b68..2feaf15 100644 --- a/libSplitView/DockPanel.h +++ b/libSplitView/DockPanel.h @@ -57,7 +57,7 @@ namespace dock_panel { /** * @brief 基础内容视图组件 */ - class SPLITVIEW_EXPORT DockableView : public QWidget, public split_frame::ViewBase { + class SPLITVIEW_EXPORT DockableView : public QFrame, public split_frame::ViewBase { public: /** * @brief 构建新的呈现视图实例 @@ -66,13 +66,7 @@ namespace dock_panel { */ DockableView(split_frame::ResManager*mgr, QWidget *present); virtual ~DockableView(); - /** - * @brief 配置视图基本特性 - * @param replace 可以被隐藏和替换 - * @param close 可以被关闭 - * @param retrieve 可以被隐藏 - */ - void viewConfig(bool replace, bool close, bool retrieve); + /** * @brief 设置标题栏内容 @@ -92,7 +86,7 @@ namespace dock_panel { 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; + bool m_replace = true, m_retrieve = true, m_close = true; // ViewRes interface public: @@ -109,6 +103,7 @@ namespace dock_panel { // ViewBase interface public: + virtual void viewConfig(bool replace, bool close, bool retrieve) override; virtual QIcon icon() const override; virtual QString title() const override; virtual bool canRetrieve() const override; diff --git a/libSplitView/SplitPanel.cpp b/libSplitView/SplitPanel.cpp index a23d7db..91857f9 100644 --- a/libSplitView/SplitPanel.cpp +++ b/libSplitView/SplitPanel.cpp @@ -9,7 +9,7 @@ using namespace Config; DragSplitter::DragSplitter(split_frame::SplitType split, split_frame::ViewRes *parent) : QFrame(parent->widget()){ - this->setFrameShape(QFrame::Shape::WinPanel); + this->setFrameShape(QFrame::Shape::StyledPanel); this->setFrameShadow(QFrame::Shadow::Raised); switch (split) { @@ -185,7 +185,7 @@ void SplitPanel::sync_status() auto second = this->split_member.second; first->setOutline(QRectF(0, 0, width_a, total_h)); - second->setOutline(QRectF(width_a + std::get<2>(split_info), 0, width_b, total_h)); + second->setOutline(QRectF(width_a + std::get<2>(split_info) - 1, 0, width_b + 1, total_h)); this->splitter_inst->setGeometry(QRect(width_a, 0, std::get<2>(split_info), total_h)); } break; case SplitType::SPLIT_V_BFIRST: diff --git a/libSplitView/SplitWindow.cpp b/libSplitView/SplitWindow.cpp index aa18cdc..816169d 100644 --- a/libSplitView/SplitWindow.cpp +++ b/libSplitView/SplitWindow.cpp @@ -25,21 +25,30 @@ SplitWindow::SplitWindow(QWidget *parent) view_root(nullptr) { accept_port->setVisible(false); this->addToolBar(Qt::ToolBarArea::LeftToolBarArea, unused_stack); + unused_stack->setMovable(false); this->addListener(this); } SplitWindow::~SplitWindow() {this->active = false;} -void SplitWindow::tempShow(split_frame::DockType t, split_frame::ViewBase *target) +void SplitWindow::tempShow(split_frame::ViewBase *target) { if(target){ this->temp_show = target; + auto current_center = centralWidget(); + if(!current_center){ + this->setCentralWidget(temp_show->widget()); + freedomHasBeenRemoved(target); + appendPresentView(target); + view_root = target; + } + else{ + auto twidget = this->centralWidget(); - auto center_w = centralWidget(); - auto size = center_w->size(); - this->temp_show->widget()->setParent(center_w); - this->temp_show->widget()->setGeometry(0, 0, size.width()/3, size.height()); + this->temp_show->widget()->setParent(twidget); + this->temp_show->widget()->setGeometry(0, 0, twidget->width()/3, twidget->height()); + } target->setVisible(true); } else if(temp_show){ @@ -49,6 +58,18 @@ void SplitWindow::tempShow(split_frame::DockType t, split_frame::ViewBase *targe } } +void SplitWindow::freedomHasBeenRemoved(split_frame::ViewBase *inst) +{ + for(auto &it : listener_list) + it->freedomRemove(inst); +} + +void SplitWindow::freedomHasBeenAppended(split_frame::ViewBase *inst) +{ + for(auto &it : listener_list) + it->freedomAppend(inst); +} + void SplitWindow::setPresentTarget(split_frame::ViewRes *inst) { if(inst && this->view_root != inst){ @@ -58,6 +79,8 @@ void SplitWindow::setPresentTarget(split_frame::ViewRes *inst) inst->setParentRes(nullptr); inst->widget()->setParent(this); this->setCentralWidget(inst->widget()); + appendPresentView(dynamic_cast(inst)); + freedomHasBeenRemoved(dynamic_cast(inst)); } else if (!inst) { this->takeCentralWidget(); } @@ -117,8 +140,13 @@ void SplitWindow::removeListener(split_frame::FreedomViewsListener *lsn) void SplitWindow::appendPresentView(split_frame::ViewBase *inst) { - if(this->active && inst) + if(this->active && inst){ + if(!isPresented(inst)){ + freedomHasBeenRemoved(inst); + } + this->presents_store[inst->hashCode()] = inst; + } } void SplitWindow::removePresentView(split_frame::ViewBase *inst) @@ -137,15 +165,14 @@ bool SplitWindow::isPresented(split_frame::ViewBase *inst) const void SplitWindow::doRetrieve(split_frame::ViewBase *inst) { if(!isPresented(inst)){ - throw new Config::SimpleException("参数错误", "无法回收空闲视图!"); + if(inst == temp_show){ + temp_show->setVisible(false); + } + return; } // 呈现视图结构调整 - if(inst == temp_show){ - temp_show->setVisible(false); - return; - } - else if (inst == view_root) { + if (inst == view_root) { setPresentTarget(); inst->setParentRes(nullptr); } @@ -176,8 +203,7 @@ void SplitWindow::doRetrieve(split_frame::ViewBase *inst) removePresentView(inst); // 当前视图已被回收 - for(auto &lsn : listener_list) - lsn->freedomAppend(inst); + freedomHasBeenAppended(inst); } void SplitWindow::doClose(split_frame::ViewBase *inst) @@ -232,8 +258,7 @@ void SplitWindow::siblingAttach(ViewBase *view, ViewBase *pos, SplitType ori) break; } - for(auto &lsn : listener_list) - lsn->freedomRemove(view); + freedomHasBeenRemoved(view); } ViewBase *SplitWindow::adjustView() const @@ -248,34 +273,37 @@ void SplitWindow::setAdjustView(split_frame::ViewBase *target) void SplitWindow::freedomAppend(split_frame::ViewBase *ins) { - if(!freedom_list.contains(ins->hashCode())){ - freedom_list[ins->hashCode()]=ins; + if(ins && !freedom_records.contains(ins->hashCode())){ + freedom_records[ins->hashCode()]=std::make_tuple(ins, ins->canReplace(), ins->canClose(), ins->canRetrieve()); + ins->viewConfig(false, false, false); auto act = this->unused_stack->addAction(ins->title(), [this, ins](bool state) { if (state) { - this->tempShow(split_frame::DockType::LEFT, ins); + this->tempShow(ins); } else { - this->tempShow(split_frame::DockType::LEFT, nullptr); + this->tempShow(nullptr); } }); act->setData(ins->hashCode()); act->setIcon(ins->icon()); - act->setCheckable(true); + act->setCheckable(true); } } void SplitWindow::freedomRemove(split_frame::ViewBase *ins) { - if(freedom_list.contains(ins->hashCode())){ + if (ins && freedom_records.contains(ins->hashCode())) { auto allacts = unused_stack->actions(); - for(auto &act : allacts){ - if(act->data().toULongLong() == ins->hashCode()){ + for (auto &act : allacts) { + if (act->data().toULongLong() == ins->hashCode()) { unused_stack->removeAction(act); break; } } - freedom_list.remove(ins->hashCode()); + auto record = freedom_records[ins->hashCode()]; + ins->viewConfig(std::get<1>(record), std::get<2>(record), std::get<3>(record)); + freedom_records.remove(ins->hashCode()); } } diff --git a/libSplitView/SplitWindow.h b/libSplitView/SplitWindow.h index b11b5c8..8a89fca 100644 --- a/libSplitView/SplitWindow.h +++ b/libSplitView/SplitWindow.h @@ -15,9 +15,6 @@ namespace split_window { * @brief 窗口即视图资源管理器 */ class SPLITVIEW_EXPORT SplitWindow : public QMainWindow, public split_frame::ResManager, public split_frame::FreedomViewsListener { - typedef float pos; - typedef float width; - private: bool active = false; QToolBar *const unused_stack; @@ -28,8 +25,8 @@ namespace split_window { split_frame::ViewRes *view_root = nullptr, *temp_show = nullptr; split_frame::ViewBase *adjust_target = nullptr; - // freedom-list - QHash freedom_list; + // freedom-records:tuple> + QHash> freedom_records; public: @@ -42,8 +39,10 @@ namespace split_window { * @param t * @param target */ - void tempShow(split_frame::DockType t, split_frame::ViewBase *target); + void tempShow(split_frame::ViewBase *target); + void freedomHasBeenRemoved(split_frame::ViewBase *inst); + void freedomHasBeenAppended(split_frame::ViewBase *inst); /** * @brief 璁剧疆鎸囧畾瑙嗗浘涓烘牴瑙嗗浘鎴栬€呭彇娑 * @param inst diff --git a/libSplitView/libSplitView.h b/libSplitView/libSplitView.h index 8c157fe..77f0bb0 100644 --- a/libSplitView/libSplitView.h +++ b/libSplitView/libSplitView.h @@ -86,6 +86,13 @@ namespace split_frame { public: virtual ~ViewBase() = default; + /** + * @brief 配置视图基本特性 + * @param replace 可以被隐藏和替换 + * @param close 可以被关闭 + * @param retrieve 可以被隐藏 + */ + virtual void viewConfig(bool replace, bool close, bool retrieve) = 0; /** * @brief 视图图标 * @return @@ -129,7 +136,9 @@ namespace split_frame { virtual void initViews(ViewRes *a, ViewRes *b) = 0; /** - * @brief 浣跨敤鏂拌鍥炬浛鎹㈡寚瀹氳鍥撅紝閲嶆瀯鍛堢幇鏍 * @param view 瀹炰緥闇€瑕佸睘浜庨棽缃鍥撅紝璋冪敤瀹屾垚琚噸寤虹埗瀛愬紩鐢 * @param pos 瀹炰緥灞炰簬鍛堢幇鏍戯紝璋冪敤瀹屾垚灏嗚瑙i櫎鐖跺瓙寮曠敤 + * @brief 替换视图,旧视图被剔除呈现树 + * @param view 新视图,必须闲置视图 + * @param pos 目标视图 */ virtual void replaceView(ViewRes *_new, ViewRes *_old) = 0;