234 lines
6.4 KiB
C++
234 lines
6.4 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;
|
|
|
|
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<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->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 <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){
|
|
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<QString>("编码异常", "不能关闭非空闲视图!");
|
|
|
|
// 回收当前视图
|
|
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<QString>("参数错误", "只能使用空闲视图吸附重组!");
|
|
}
|
|
if(!isPresented(pos)){
|
|
throw new Config::SimpleException<QString>("参数错误", "不能依据空闲视图吸附重组!");
|
|
}
|
|
|
|
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<QString>("参数错误", "指定吸附视图父引用为空");
|
|
|
|
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;
|
|
}
|