2024-02-10 07:09:02 +00:00
|
|
|
#include "SplitWindow.h"
|
|
|
|
#include "DockPanel.h"
|
|
|
|
#include "SplitPanel.h"
|
2023-12-30 05:04:51 +00:00
|
|
|
#include <QApplication>
|
|
|
|
#include <QDebug>
|
|
|
|
#include <QDrag>
|
|
|
|
#include <QHBoxLayout>
|
|
|
|
#include <QLineF>
|
|
|
|
#include <QMimeData>
|
|
|
|
#include <QPainter>
|
|
|
|
#include <QPushButton>
|
|
|
|
#include <QResizeEvent>
|
|
|
|
#include <QStyleOption>
|
2024-02-08 13:12:45 +00:00
|
|
|
#include <QWindow>
|
2023-12-30 05:04:51 +00:00
|
|
|
#include <libConfig.h>
|
|
|
|
|
2024-02-08 13:12:45 +00:00
|
|
|
using namespace split_window;
|
2023-12-30 05:04:51 +00:00
|
|
|
using namespace split_frame;
|
|
|
|
|
2024-02-10 07:09:02 +00:00
|
|
|
SplitWindow::SplitWindow(QWidget *parent) : QMainWindow(parent), accept_port(new accept_panel::AcceptPanel(this, this)), view_root(nullptr) {
|
2024-02-09 08:45:40 +00:00
|
|
|
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)
|
2024-02-08 13:12:45 +00:00
|
|
|
{
|
2024-02-10 07:09:02 +00:00
|
|
|
if(inst && this->view_root != inst){
|
|
|
|
this->takeCentralWidget();
|
|
|
|
this->view_root = nullptr;
|
|
|
|
|
2024-02-08 13:12:45 +00:00
|
|
|
inst->setParentRes(nullptr);
|
2024-02-10 07:09:02 +00:00
|
|
|
inst->widget()->setParent(this);
|
2024-02-08 13:12:45 +00:00
|
|
|
this->setCentralWidget(inst->widget());
|
2024-02-10 07:09:02 +00:00
|
|
|
} else if (!inst) {
|
2024-02-08 13:12:45 +00:00
|
|
|
this->takeCentralWidget();
|
|
|
|
}
|
|
|
|
|
2024-02-09 08:45:40 +00:00
|
|
|
this->view_root = inst;
|
|
|
|
this->update();
|
2024-02-08 13:12:45 +00:00
|
|
|
}
|
2023-12-30 05:04:51 +00:00
|
|
|
|
2024-02-08 13:12:45 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2024-02-09 08:45:40 +00:00
|
|
|
for (auto &cmp : this->presents_store) {
|
2024-02-08 13:12:45 +00:00
|
|
|
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)
|
2024-02-09 08:45:40 +00:00
|
|
|
this->presents_store[inst->hashCode()] = inst;
|
2024-02-08 13:12:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SplitWindow::removePresentView(split_frame::ViewBase *inst)
|
|
|
|
{
|
|
|
|
if(inst)
|
2024-02-09 08:45:40 +00:00
|
|
|
this->presents_store.remove(inst->hashCode());
|
2024-02-08 13:12:45 +00:00
|
|
|
}
|
|
|
|
|
2024-02-09 08:45:40 +00:00
|
|
|
bool SplitWindow::isPresented(split_frame::ViewBase *inst) const
|
2024-02-08 13:12:45 +00:00
|
|
|
{
|
2024-02-09 08:45:40 +00:00
|
|
|
return inst && presents_store.contains(inst->hashCode());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#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){
|
2024-02-10 07:09:02 +00:00
|
|
|
auto pinst = inst->parentRes();
|
2024-02-09 08:45:40 +00:00
|
|
|
|
2024-02-10 07:09:02 +00:00
|
|
|
auto remains = pinst->except(inst);
|
2024-02-09 08:45:40 +00:00
|
|
|
inst->setParentRes(nullptr);
|
2024-02-10 07:09:02 +00:00
|
|
|
remains.first->setParentRes(nullptr);
|
|
|
|
|
|
|
|
auto awidget = inst->widget()->parent();
|
|
|
|
auto cwidget = inst->widget()->parentWidget();
|
|
|
|
auto bwidget = inst->widget()->parent();
|
2024-02-09 08:45:40 +00:00
|
|
|
|
|
|
|
setPresentTarget(remains.first);
|
2024-02-10 07:09:02 +00:00
|
|
|
delete pinst;
|
2024-02-09 08:45:40 +00:00
|
|
|
}
|
|
|
|
else if(inst->parentRes()){
|
2024-02-08 13:12:45 +00:00
|
|
|
auto pinst = inst->parentRes();
|
|
|
|
|
|
|
|
auto remains = pinst->except(inst);
|
2024-02-10 07:09:02 +00:00
|
|
|
remains.first->setParentRes(nullptr);
|
2024-02-08 13:12:45 +00:00
|
|
|
inst->setParentRes(nullptr);
|
|
|
|
|
|
|
|
auto ppinst = pinst->parentRes();
|
2024-02-09 08:45:40 +00:00
|
|
|
ppinst->replaceView(remains.first, pinst);
|
2024-02-08 13:12:45 +00:00
|
|
|
delete pinst;
|
|
|
|
}
|
|
|
|
|
|
|
|
inst->setParentRes(nullptr);
|
|
|
|
inst->setVisible(false);
|
|
|
|
removePresentView(inst);
|
2024-02-09 08:45:40 +00:00
|
|
|
|
|
|
|
// 当前视图已被回收
|
|
|
|
for(auto &lsn : listener_list)
|
|
|
|
lsn->freedomAppend(inst);
|
2024-02-08 13:12:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SplitWindow::doClose(split_frame::ViewBase *inst)
|
|
|
|
{
|
2024-02-09 08:45:40 +00:00
|
|
|
if(isPresented(inst))
|
|
|
|
throw new Config::SimpleException<QString>("编码异常", "不能关闭非空闲视图!");
|
2024-02-08 13:12:45 +00:00
|
|
|
|
|
|
|
// 回收当前视图
|
|
|
|
for(auto &lsn : listener_list)
|
|
|
|
lsn->aboutToBeDelete(inst);
|
|
|
|
|
|
|
|
delete inst;
|
|
|
|
}
|
|
|
|
|
2024-02-09 08:45:40 +00:00
|
|
|
void SplitWindow::siblingAttach(ViewBase *view, ViewBase *pos, SplitType ori)
|
2024-02-08 13:12:45 +00:00
|
|
|
{
|
2024-02-09 08:45:40 +00:00
|
|
|
if(isPresented(view) && view != temp_show){
|
|
|
|
throw new Config::SimpleException<QString>("参数错误", "只能使用空闲视图吸附重组!");
|
|
|
|
}
|
|
|
|
if(!isPresented(pos)){
|
|
|
|
throw new Config::SimpleException<QString>("参数错误", "不能依据空闲视图吸附重组!");
|
|
|
|
}
|
2024-02-08 13:12:45 +00:00
|
|
|
|
2024-02-09 08:45:40 +00:00
|
|
|
auto remains_frm = pos->parentRes();
|
2024-02-08 13:12:45 +00:00
|
|
|
auto split_slot = new split_panel::SplitPanel(this, ori);
|
2024-02-10 07:09:02 +00:00
|
|
|
if(pos == view_root){
|
|
|
|
setPresentTarget(split_slot);
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
if(!remains_frm)
|
|
|
|
throw new Config::SimpleException<QString>("参数错误", "指定吸附视图父引用为空");
|
|
|
|
|
|
|
|
remains_frm->replaceView(split_slot, pos);
|
|
|
|
}
|
2024-02-08 13:12:45 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|