191 lines
5.0 KiB
C++
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;
|
|
}
|