QtNovelUI/libSplitView/splitwindow.cpp

191 lines
5.0 KiB
C++

#include "splitwindow.h"
#include "dockpanel.h"
#include "splitpanel.h"
#include <QApplication>
#include <QDebug>
#include <QDrag>
#include <QHBoxLayout>
#include <QLineF>
#include <QMimeData>
#include <QPainter>
#include <QPushButton>
#include <QResizeEvent>
#include <QStyleOption>
#include <QWindow>
#include <libConfig.h>
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<QDragMoveEvent *>(ev)->pos();
QPoint global_pos;
if (sender->isWindowType()) {
dynamic_cast<QWindow *>(sender)->requestActivate();
global_pos = dynamic_cast<QWindow *>(sender)->mapToGlobal(evn_pos);
} else if (sender->isWidgetType()) {
global_pos = dynamic_cast<QWidget *>(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;
}