#include "SplitWindow.h" #include "DockPanel.h" #include "SplitPanel.h" #include #include #include #include #include #include #include #include #include #include #include #include using namespace split_window; using namespace split_frame; SplitWindow::SplitWindow(QWidget *parent) : QMainWindow(parent), active(true), unused_stack(new QToolBar(this)), accept_port(new accept_panel::AcceptPanel(this, this)), view_root(nullptr) { accept_port->setVisible(false); this->addToolBar(Qt::ToolBarArea::LeftToolBarArea, unused_stack); } SplitWindow::~SplitWindow() {this->active = false;} 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){ this->takeCentralWidget(); this->view_root = nullptr; inst->setParentRes(nullptr); inst->widget()->setParent(this); this->setCentralWidget(inst->widget()); } else if (!inst) { this->takeCentralWidget(); } this->view_root = inst; this->update(); } bool SplitWindow::eventFilter(QObject *sender, QEvent *ev) { switch (ev->type()) { case QEvent::Type::DragMove: { if (sender->isWidgetType() || sender->isWindowType()) { auto evn_pos = static_cast(ev)->pos(); QPoint global_pos; if (sender->isWindowType()) { dynamic_cast(sender)->requestActivate(); global_pos = dynamic_cast(sender)->mapToGlobal(evn_pos); } else if (sender->isWidgetType()) { global_pos = dynamic_cast(sender)->mapToGlobal(evn_pos); } for (auto &cmp : this->presents_store) { auto local_pos = cmp->widget()->mapFromGlobal(global_pos); auto rect_shape = cmp->outlineRect(); rect_shape.moveTopLeft(QPointF()); if (rect_shape.contains(local_pos) && cmp->widget()->isActiveWindow()) { accept_port->bindWith(cmp); accept_port->raise(); accept_port->setVisible(true); break; } } } } break; case QEvent::Type::MouseButtonRelease: accept_port->setVisible(false); break; default: break; } return QMainWindow::eventFilter(sender, ev); } void SplitWindow::addListener(split_frame::FreedomViewsListener *lsn) { if(listener_list.contains(lsn)) return; listener_list << lsn; } void SplitWindow::removeListener(split_frame::FreedomViewsListener *lsn) { this->listener_list.removeAll(lsn); } void SplitWindow::appendPresentView(split_frame::ViewBase *inst) { if(this->active && inst) this->presents_store[inst->hashCode()] = inst; } void SplitWindow::removePresentView(split_frame::ViewBase *inst) { if(this->active && inst) this->presents_store.remove(inst->hashCode()); } bool SplitWindow::isPresented(split_frame::ViewBase *inst) const { return inst && presents_store.contains(inst->hashCode()); } #include void SplitWindow::doRetrieve(split_frame::ViewBase *inst) { if(!isPresented(inst)){ throw new Config::SimpleException("参数错误", "无法回收空闲视图!"); } // 呈现视图结构调整 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 = inst->parentRes(); auto remains = pinst->except(inst); inst->setParentRes(nullptr); remains.first->setParentRes(nullptr); setPresentTarget(remains.first); delete pinst; } else if(inst->parentRes()){ auto pinst = inst->parentRes(); auto remains = pinst->except(inst); remains.first->setParentRes(nullptr); inst->setParentRes(nullptr); auto ppinst = pinst->parentRes(); ppinst->replaceView(remains.first, pinst); delete pinst; } inst->setParentRes(nullptr); inst->setVisible(false); removePresentView(inst); // 当前视图已被回收 for(auto &lsn : listener_list) lsn->freedomAppend(inst); } void SplitWindow::doClose(split_frame::ViewBase *inst) { if(isPresented(inst)) throw new Config::SimpleException("编码异常", "不能关闭非空闲视图!"); // 回收当前视图 for(auto &lsn : listener_list) lsn->aboutToBeDelete(inst); delete inst; } void SplitWindow::siblingAttach(ViewBase *view, ViewBase *pos, SplitType ori) { if(isPresented(view) && view != temp_show){ throw new Config::SimpleException("参数错误", "只能使用空闲视图吸附重组!"); } if(!isPresented(pos)){ throw new Config::SimpleException("参数错误", "不能依据空闲视图吸附重组!"); } auto remains_frm = pos->parentRes(); auto split_slot = new split_panel::SplitPanel(this, ori); if(pos == view_root){ setPresentTarget(split_slot); } else{ if(!remains_frm) throw new Config::SimpleException("参数错误", "指定吸附视图父引用为空"); remains_frm->replaceView(split_slot, pos); } switch (ori) { case SplitType::SPLIT_H_LFIRST: split_slot->initViews(view, pos); split_slot->setSplitInfo(0.333, 8); break; case SplitType::SPLIT_H_RFIRST: split_slot->initViews(pos, view); split_slot->setSplitInfo(0.666, 8); break; case SplitType::SPLIT_V_TFIRST: split_slot->initViews(view, pos); split_slot->setSplitInfo(0.333, 8); break; case SplitType::SPLIT_V_BFIRST: split_slot->initViews(pos, view); split_slot->setSplitInfo(0.666, 8); break; } for(auto &lsn : listener_list) lsn->freedomRemove(view); } ViewBase *SplitWindow::adjustView() const { return adjust_target; } void SplitWindow::setAdjustView(split_frame::ViewBase *target) { this->adjust_target = target; }