bug,设置父引用为null的时候引发visible过程,导致其他视图被归类到空闲视图类别错误
This commit is contained in:
parent
e2bafb16fb
commit
75982278b4
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue