#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; void SplitWindow::setRoot(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); } SplitWindow::~SplitWindow() {} 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->views_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(inst) this->views_store[inst->hashCode()] = inst; } void SplitWindow::removePresentView(split_frame::ViewBase *inst) { if(inst) this->views_store.remove(inst->hashCode()); } void SplitWindow::present_remove(split_frame::ViewRes *inst) { // 面板树中间节点 if(inst != view_root && 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); } delete pinst; } else if(inst == view_root){ setRoot(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); } void SplitWindow::doClose(split_frame::ViewBase *inst) { // 呈现视图结构调整 present_remove(inst); // 回收当前视图 for(auto &lsn : listener_list) lsn->aboutToBeDelete(inst); removePresentView(inst); delete inst; } void SplitWindow::siblingAttach(ViewBase *view, ViewRes *pos, SplitType ori) { doRetrieve(view); auto split_slot = new split_panel::SplitPanel(this, ori); auto remains_frm = pos->parentRes(); 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; }