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"?>
<!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>
<data>
<variable>EnvironmentId</variable>

View File

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

View File

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

View File

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

View File

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

View File

@ -17,26 +17,34 @@
using namespace split_window;
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){
this->view_root = inst;
inst->setParentRes(nullptr);
this->setCentralWidget(inst->widget());
}
else{
this->takeCentralWidget();
this->view_root = nullptr;
}
}
SplitWindow::SplitWindow(QWidget *parent) : QMainWindow(parent), view_root(nullptr), accept_port(new accept_panel::AcceptPanel(this, this)) {
this->setRoot(nullptr);
accept_port->setVisible(false);
this->view_root = inst;
this->update();
}
SplitWindow::~SplitWindow() {}
bool SplitWindow::eventFilter(QObject *sender, QEvent *ev)
{
switch (ev->type()) {
@ -51,7 +59,7 @@ bool SplitWindow::eventFilter(QObject *sender, QEvent *ev)
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 rect_shape = cmp->outlineRect();
rect_shape.moveTopLeft(QPointF());
@ -89,57 +97,70 @@ void SplitWindow::removeListener(split_frame::FreedomViewsListener *lsn)
void SplitWindow::appendPresentView(split_frame::ViewBase *inst)
{
if(inst)
this->views_store[inst->hashCode()] = inst;
this->presents_store[inst->hashCode()] = inst;
}
void SplitWindow::removePresentView(split_frame::ViewBase *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
{
// 面板树中间节点
if(inst != view_root && inst->parentRes()){
return inst && presents_store.contains(inst->hashCode());
}
#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 remains = pinst->except(inst);
remains.first->setParentRes(nullptr);
inst->setParentRes(nullptr);
// 父节点不是根节点
auto ppinst = pinst->parentRes();
if (ppinst) {
ppinst->replaceView(remains.first, pinst);
} else {
this->setRoot(remains.first);
}
ppinst->replaceView(remains.first, 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->setVisible(false);
removePresentView(inst);
// 当前视图已被回收
for(auto &lsn : listener_list)
lsn->freedomAppend(inst);
}
void SplitWindow::doClose(split_frame::ViewBase *inst)
{
// 呈现视图结构调整
present_remove(inst);
if(isPresented(inst))
throw new Config::SimpleException<QString>("编码异常", "不能关闭非空闲视图!");
// 回收当前视图
for(auto &lsn : listener_list)
@ -149,11 +170,16 @@ void SplitWindow::doClose(split_frame::ViewBase *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();
doRetrieve(view);
if(isPresented(view) && view != temp_show){
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);
remains_frm->replaceView(split_slot, pos);

View File

@ -19,12 +19,12 @@ namespace split_window {
private:
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;
split_frame::ViewRes *view_root = nullptr, *temp_show = nullptr;
split_frame::ViewBase *adjust_target = nullptr;
void present_remove(split_frame::ViewRes *inst);
public:
SplitWindow(QWidget *parent = nullptr);
@ -39,8 +39,11 @@ namespace split_window {
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;
@ -50,9 +53,10 @@ namespace split_window {
virtual void removeListener(split_frame::FreedomViewsListener *lsn) override;
virtual void appendPresentView(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 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 void setAdjustView(split_frame::ViewBase *target) override;
};

View File

@ -20,12 +20,11 @@ int main(int argc, char *argv[]) {
split_window::SplitWindow w;
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 dview = new dock_panel::DockableView(&w, new QWidget, true);
spb->initViews(bview, dview);
w.setPresentTarget(spb);
a.installEventFilter(&w);
w.show();