bug,设置父引用为null的时候引发visible过程,导致其他视图被归类到空闲视图类别错误

This commit is contained in:
codeboss 2024-02-09 16:45:40 +08:00
parent e2bafb16fb
commit 75982278b4
8 changed files with 102 additions and 63 deletions

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject> <!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.15.0, 2024-02-07T16:25:47. --> <!-- Written by QtCreator 4.15.0, 2024-02-09T16:03:39. -->
<qtcreator> <qtcreator>
<data> <data>
<variable>EnvironmentId</variable> <variable>EnvironmentId</variable>

View File

@ -112,7 +112,7 @@ void accept_panel::AcceptPanel::dragEnterEvent(QDragEnterEvent *ev)
void accept_panel::AcceptPanel::dropEvent(QDropEvent *ev) void accept_panel::AcceptPanel::dropEvent(QDropEvent *ev)
{ {
auto view = view_manager->adjustView(); auto view = view_manager->adjustView();
if(view){ if(view && anchor_view != view){
switch (target_type) { switch (target_type) {
case HoverType::CUBE_LEFT: case HoverType::CUBE_LEFT:
view_manager->doRetrieve(view); view_manager->doRetrieve(view);

View File

@ -146,6 +146,7 @@ void DockableView::adjustAccept(const QPoint &pos)
void DockableView::closeAccept() void DockableView::closeAccept()
{ {
this->manager_inst->doRetrieve(this);
this->manager_inst->doClose(this); this->manager_inst->doClose(this);
} }

View File

@ -79,10 +79,11 @@ bool SplitPanel::isVisible() const
void SplitPanel::initViews(ViewRes *a, ViewRes *b) void SplitPanel::initViews(ViewRes *a, ViewRes *b)
{ {
this->split_member = std::make_pair(a, b);
a->setParentRes(this); a->setParentRes(this);
b->setParentRes(this); b->setParentRes(this);
this->split_member = std::make_pair(a, b);
this->sync_status();
} }
QWidget *SplitPanel::widget() const { return const_cast<SplitPanel *>(this); } QWidget *SplitPanel::widget() const { return const_cast<SplitPanel *>(this); }
@ -132,9 +133,9 @@ void SplitPanel::replaceView(ViewRes *_new, ViewRes *_old)
throw new SimpleException<QString>("运行异常", "指定替换的视图不属于本组件"); throw new SimpleException<QString>("运行异常", "指定替换的视图不属于本组件");
} }
_new->setParentRes(this);
auto elsev = except(_old); auto elsev = except(_old);
switch (std::get<1>(elsev)) { _new->setParentRes(this);
switch (elsev.second) {
case 0: case 0:
this->split_member = std::make_pair(elsev.first, _new); this->split_member = std::make_pair(elsev.first, _new);
break; break;
@ -142,6 +143,7 @@ void SplitPanel::replaceView(ViewRes *_new, ViewRes *_old)
this->split_member = std::make_pair(_new, elsev.first); this->split_member = std::make_pair(_new, elsev.first);
} }
_old->setParentRes(nullptr);
sync_status(); sync_status();
this->update(); this->update();
} }

View File

@ -128,16 +128,16 @@ namespace split_frame {
virtual ~SplitView() = default; virtual ~SplitView() = default;
/** /**
* @brief * @brief
* @param a a * @param a a
* @param b b * @param b b
*/ */
virtual void initViews(ViewRes *a, ViewRes *b) = 0; virtual void initViews(ViewRes *a, ViewRes *b) = 0;
/** /**
* @brief * @brief 使
* @param old nullptr * @param view
* @param view nullptr * @param pos
*/ */
virtual void replaceView(ViewRes *_new, ViewRes *_old) = 0; virtual void replaceView(ViewRes *_new, ViewRes *_old) = 0;
@ -231,23 +231,30 @@ namespace split_frame {
*/ */
virtual void appendPresentView(ViewBase *inst) = 0; virtual void appendPresentView(ViewBase *inst) = 0;
/**
* @brief
* @param inst
*/
virtual bool isPresented(ViewBase *inst) const = 0;
/** /**
* @brief * @brief
* @param inst * @param inst
*/ */
virtual void doRetrieve(ViewBase *inst) = 0; virtual void doRetrieve(ViewBase *inst) = 0;
/** /**
* @brief * @brief
* @param inst
*/ */
virtual void doClose(ViewBase *inst) = 0; virtual void doClose(ViewBase *inst) = 0;
/** /**
* @brief * @brief 使
* @param view * @param view
* @param old * @param pos
*/ */
virtual void siblingAttach(ViewBase *view, ViewRes *pos, SplitType ori) = 0; virtual void siblingAttach(ViewBase *view, ViewBase *pos, SplitType ori) = 0;
}; };
} // namespace SplitFrame } // namespace SplitFrame

View File

@ -17,26 +17,34 @@
using namespace split_window; using namespace split_window;
using namespace split_frame; using namespace split_frame;
void SplitWindow::setRoot(split_frame::ViewRes *inst)
SplitWindow::SplitWindow(QWidget *parent) : QMainWindow(parent), view_root(nullptr), accept_port(new accept_panel::AcceptPanel(this, this)) {
this->view_root = nullptr;
accept_port->setVisible(false);
}
SplitWindow::~SplitWindow() {}
void SplitWindow::tempShow(split_frame::DockType t, split_frame::ViewBase *target)
{
this->temp_show = target;
target->setVisible(true);
}
void SplitWindow::setPresentTarget(split_frame::ViewRes *inst)
{ {
if(inst){ if(inst){
this->view_root = inst;
inst->setParentRes(nullptr); inst->setParentRes(nullptr);
this->setCentralWidget(inst->widget()); this->setCentralWidget(inst->widget());
} }
else{ else{
this->takeCentralWidget(); this->takeCentralWidget();
this->view_root = nullptr;
}
} }
SplitWindow::SplitWindow(QWidget *parent) : QMainWindow(parent), view_root(nullptr), accept_port(new accept_panel::AcceptPanel(this, this)) { this->view_root = inst;
this->setRoot(nullptr); this->update();
accept_port->setVisible(false);
} }
SplitWindow::~SplitWindow() {}
bool SplitWindow::eventFilter(QObject *sender, QEvent *ev) bool SplitWindow::eventFilter(QObject *sender, QEvent *ev)
{ {
switch (ev->type()) { switch (ev->type()) {
@ -51,7 +59,7 @@ bool SplitWindow::eventFilter(QObject *sender, QEvent *ev)
global_pos = dynamic_cast<QWidget *>(sender)->mapToGlobal(evn_pos); global_pos = dynamic_cast<QWidget *>(sender)->mapToGlobal(evn_pos);
} }
for (auto &cmp : this->views_store) { for (auto &cmp : this->presents_store) {
auto local_pos = cmp->widget()->mapFromGlobal(global_pos); auto local_pos = cmp->widget()->mapFromGlobal(global_pos);
auto rect_shape = cmp->outlineRect(); auto rect_shape = cmp->outlineRect();
rect_shape.moveTopLeft(QPointF()); rect_shape.moveTopLeft(QPointF());
@ -89,57 +97,70 @@ void SplitWindow::removeListener(split_frame::FreedomViewsListener *lsn)
void SplitWindow::appendPresentView(split_frame::ViewBase *inst) void SplitWindow::appendPresentView(split_frame::ViewBase *inst)
{ {
if(inst) if(inst)
this->views_store[inst->hashCode()] = inst; this->presents_store[inst->hashCode()] = inst;
} }
void SplitWindow::removePresentView(split_frame::ViewBase *inst) void SplitWindow::removePresentView(split_frame::ViewBase *inst)
{ {
if(inst) if(inst)
this->views_store.remove(inst->hashCode()); this->presents_store.remove(inst->hashCode());
} }
void SplitWindow::present_remove(split_frame::ViewRes *inst) bool SplitWindow::isPresented(split_frame::ViewBase *inst) const
{ {
// 面板树中间节点 return inst && presents_store.contains(inst->hashCode());
if(inst != view_root && inst->parentRes()){ }
#include <libConfig.h>
void SplitWindow::doRetrieve(split_frame::ViewBase *inst)
{
if(!isPresented(inst)){
throw new Config::SimpleException<QString>("参数错误", "无法回收空闲视图!");
}
// 呈现视图结构调整
if(inst == temp_show){
temp_show->setVisible(false);
return;
}
else if (inst == view_root) {
setPresentTarget();
inst->setParentRes(nullptr);
}
else if(inst->parentRes() == view_root){
auto pinst_root = inst->parentRes();
auto remains = pinst_root->except(inst);
inst->setParentRes(nullptr);
setPresentTarget(remains.first);
delete pinst_root;
}
else if(inst->parentRes()){
auto pinst = inst->parentRes(); auto pinst = inst->parentRes();
auto remains = pinst->except(inst); auto remains = pinst->except(inst);
remains.first->setParentRes(nullptr);
inst->setParentRes(nullptr); inst->setParentRes(nullptr);
// 父节点不是根节点
auto ppinst = pinst->parentRes(); auto ppinst = pinst->parentRes();
if (ppinst) {
ppinst->replaceView(remains.first, pinst); ppinst->replaceView(remains.first, pinst);
} else {
this->setRoot(remains.first);
}
delete pinst; delete pinst;
} }
else if(inst == view_root){
setRoot(nullptr);
inst->setParentRes(nullptr);
}
}
void SplitWindow::doRetrieve(split_frame::ViewBase *inst)
{
// 呈现视图结构调整
present_remove(inst);
// 回收当前视图
for(auto &lsn : listener_list)
lsn->freedomAppend(inst);
inst->setParentRes(nullptr); inst->setParentRes(nullptr);
inst->setVisible(false); inst->setVisible(false);
removePresentView(inst); removePresentView(inst);
// 当前视图已被回收
for(auto &lsn : listener_list)
lsn->freedomAppend(inst);
} }
void SplitWindow::doClose(split_frame::ViewBase *inst) void SplitWindow::doClose(split_frame::ViewBase *inst)
{ {
// 呈现视图结构调整 if(isPresented(inst))
present_remove(inst); throw new Config::SimpleException<QString>("编码异常", "不能关闭非空闲视图!");
// 回收当前视图 // 回收当前视图
for(auto &lsn : listener_list) for(auto &lsn : listener_list)
@ -149,11 +170,16 @@ void SplitWindow::doClose(split_frame::ViewBase *inst)
delete inst; delete inst;
} }
void SplitWindow::siblingAttach(ViewBase *view, ViewRes *pos, SplitType ori) void SplitWindow::siblingAttach(ViewBase *view, ViewBase *pos, SplitType ori)
{ {
auto remains_frm = pos->parentRes(); if(isPresented(view) && view != temp_show){
doRetrieve(view); throw new Config::SimpleException<QString>("参数错误", "只能使用空闲视图吸附重组!");
}
if(!isPresented(pos)){
throw new Config::SimpleException<QString>("参数错误", "不能依据空闲视图吸附重组!");
}
auto remains_frm = pos->parentRes();
auto split_slot = new split_panel::SplitPanel(this, ori); auto split_slot = new split_panel::SplitPanel(this, ori);
remains_frm->replaceView(split_slot, pos); remains_frm->replaceView(split_slot, pos);

View File

@ -19,12 +19,12 @@ namespace split_window {
private: private:
QList<split_frame::FreedomViewsListener*> listener_list; QList<split_frame::FreedomViewsListener*> listener_list;
QHash<qulonglong, split_frame::ViewBase*> views_store;
split_frame::ViewRes *view_root; QHash<qulonglong, split_frame::ViewBase*> presents_store;
accept_panel::AcceptPanel *const accept_port; accept_panel::AcceptPanel *const accept_port;
split_frame::ViewRes *view_root = nullptr, *temp_show = nullptr;
split_frame::ViewBase *adjust_target = nullptr; split_frame::ViewBase *adjust_target = nullptr;
void present_remove(split_frame::ViewRes *inst);
public: public:
SplitWindow(QWidget *parent = nullptr); SplitWindow(QWidget *parent = nullptr);
@ -39,8 +39,11 @@ namespace split_window {
void tempShow(split_frame::DockType t, split_frame::ViewBase *target); void tempShow(split_frame::DockType t, split_frame::ViewBase *target);
void setRoot(split_frame::ViewRes *inst); /**
* @brief
* @param inst
*/
void setPresentTarget(split_frame::ViewRes *inst = nullptr);
bool eventFilter(QObject *sender, QEvent *ev) override; bool eventFilter(QObject *sender, QEvent *ev) override;
@ -50,9 +53,10 @@ namespace split_window {
virtual void removeListener(split_frame::FreedomViewsListener *lsn) override; virtual void removeListener(split_frame::FreedomViewsListener *lsn) override;
virtual void appendPresentView(split_frame::ViewBase *inst) override; virtual void appendPresentView(split_frame::ViewBase *inst) override;
virtual void removePresentView(split_frame::ViewBase *inst) override; virtual void removePresentView(split_frame::ViewBase *inst) override;
virtual bool isPresented(split_frame::ViewBase *inst) const override;
virtual void doRetrieve(split_frame::ViewBase *inst) override; virtual void doRetrieve(split_frame::ViewBase *inst) override;
virtual void doClose(split_frame::ViewBase *inst) override; virtual void doClose(split_frame::ViewBase *inst) override;
virtual void siblingAttach(split_frame::ViewBase *view, split_frame::ViewRes *pos, split_frame::SplitType ori) override; virtual void siblingAttach(split_frame::ViewBase *view, split_frame::ViewBase *pos, split_frame::SplitType ori) override;
virtual split_frame::ViewBase *adjustView() const override; virtual split_frame::ViewBase *adjustView() const override;
virtual void setAdjustView(split_frame::ViewBase *target) override; virtual void setAdjustView(split_frame::ViewBase *target) override;
}; };

View File

@ -20,12 +20,11 @@ int main(int argc, char *argv[]) {
split_window::SplitWindow w; split_window::SplitWindow w;
auto spb = new split_panel::SplitPanel(&w, split_frame::SplitType::SPLIT_H_LFIRST); auto spb = new split_panel::SplitPanel(&w, split_frame::SplitType::SPLIT_H_LFIRST);
w.setRoot(spb);
auto bview = new dock_panel::DockableView(&w, new QWidget, true); auto bview = new dock_panel::DockableView(&w, new QWidget, true);
auto dview = new dock_panel::DockableView(&w, new QWidget, true); auto dview = new dock_panel::DockableView(&w, new QWidget, true);
spb->initViews(bview, dview); spb->initViews(bview, dview);
w.setPresentTarget(spb);
a.installEventFilter(&w); a.installEventFilter(&w);
w.show(); w.show();