784 lines
24 KiB
C++
784 lines
24 KiB
C++
#include "splitview.h"
|
||
#include <QApplication>
|
||
#include <QDebug>
|
||
#include <QDrag>
|
||
#include <QHBoxLayout>
|
||
#include <QLineF>
|
||
#include <QMimeData>
|
||
#include <QPainter>
|
||
#include <QPushButton>
|
||
#include <QResizeEvent>
|
||
#include <QStyleOption>
|
||
#include <libConfig.h>
|
||
|
||
using namespace SplitFrame;
|
||
using namespace Config;
|
||
|
||
BaseView::BaseView(const QString &title, QWidget *view, bool empty, QWidget *parent) : QWidget(parent), title_header(nullptr), parent_store(nullptr) {
|
||
auto layout = new QVBoxLayout(this);
|
||
layout->setMargin(0);
|
||
layout->setSpacing(0);
|
||
|
||
registComp(this);
|
||
|
||
if (!empty) {
|
||
title_header = new DragHeader(this);
|
||
title_header->setText(title);
|
||
title_header->setMaximumHeight(22);
|
||
|
||
layout->addWidget(title_header, 0);
|
||
registComp(title_header);
|
||
}
|
||
|
||
registComp(view);
|
||
layout->addWidget(view, 1);
|
||
setMouseTracking(true);
|
||
}
|
||
|
||
void BaseView::setTitle(const QString &title) {
|
||
QWidget::setWindowTitle(title);
|
||
title_header->setText(title);
|
||
}
|
||
|
||
QString BaseView::title() const { return this->title_header->text(); }
|
||
|
||
void BaseView::setIcon(const QIcon &icon) { this->title_header->setIcon(icon); }
|
||
|
||
QIcon BaseView::viewIcon() const { return title_header->icon(); }
|
||
|
||
void BaseView::registComp(QWidget *child) {
|
||
if (this->comps_list.contains(child))
|
||
return;
|
||
comps_list << child;
|
||
}
|
||
|
||
ViewPresent *BaseView::viewPanel() const {
|
||
if (!parentRect())
|
||
return nullptr;
|
||
return parentRect()->viewPanel();
|
||
}
|
||
|
||
void BaseView::closeView() {}
|
||
|
||
bool BaseView::contains(QWidget *ptr) const { return comps_list.contains(ptr); }
|
||
|
||
QWidget *BaseView::bind() const { return const_cast<BaseView *>(this); }
|
||
|
||
SplitRect *BaseView::parentRect() const { return parent_store; }
|
||
|
||
void BaseView::setParentRect(SplitRect *pinst) {
|
||
if (pinst) {
|
||
auto conv = pinst->bind();
|
||
setParent(conv);
|
||
} else
|
||
setParent(nullptr);
|
||
|
||
this->parent_store = pinst;
|
||
}
|
||
|
||
std::pair<SplitRect *, SplitRect *> BaseView::child() const { return std::make_pair<SplitRect *, SplitRect *>(nullptr, nullptr); }
|
||
|
||
void BaseView::replace(SplitRect *view, SplitRect *old) { throw new SimpleException<QString>("异常调用", "不能对ViewBase调用replace函数"); }
|
||
|
||
float BaseView::splitterWidth() const { return 0; }
|
||
|
||
float BaseView::splitterPos() const { return 0; }
|
||
|
||
SplitType BaseView::splitType() const { return SplitType::SPLIT_H; }
|
||
|
||
void BaseView::setSplitInfo(SplitType type, float pos, float width, bool relayout) {
|
||
throw new SimpleException<QString>("异常调用", "不能对ViewBase调用setSplitInfo函数");
|
||
}
|
||
|
||
QRectF BaseView::outline() const { return this->rect(); }
|
||
|
||
void BaseView::relayout(const QRectF &outline) { this->setGeometry(outline.toRect()); }
|
||
|
||
void BaseView::installPerceptionHandle(ViewPresent *obj) {
|
||
for (auto &it : comps_list) {
|
||
it->setAcceptDrops(true);
|
||
it->removeEventFilter(obj);
|
||
it->installEventFilter(obj);
|
||
}
|
||
}
|
||
|
||
void BaseView::paintEvent(QPaintEvent *ev) { QWidget::paintEvent(ev); }
|
||
|
||
void BaseView::remove(SplitRect *child_inst) { throw new SimpleException<QString>("非法操作", "BaseView不支持retrieveComp操作"); }
|
||
|
||
AttachPanel::AttachPanel(ViewPresent *host) : QWidget(), size_host(host) {
|
||
setWindowOpacity(50);
|
||
setAcceptDrops(true);
|
||
}
|
||
|
||
void AttachPanel::bind(BaseView *widget) { this->current_target = widget; }
|
||
|
||
BaseView *AttachPanel::attachTarget() const { return this->current_target; }
|
||
|
||
void AttachPanel::paintEvent(QPaintEvent *event) {
|
||
QWidget::paintEvent(event);
|
||
|
||
QPainter p(this);
|
||
p.setBrush(Qt::lightGray);
|
||
p.fillRect(this->rect(), Qt::lightGray);
|
||
|
||
auto rect = this->rect();
|
||
p.setPen(QPen(Qt::black, 4));
|
||
switch (active_comp) {
|
||
case ActiveArea::LEFT:
|
||
p.fillRect(QRectF(rect.topLeft(), QSizeF(rect.width() / 2, rect.height())), Qt::gray);
|
||
break;
|
||
case ActiveArea::RIGHT:
|
||
p.fillRect(QRectF(rect.center() - QPointF(0, rect.height() / 2), QSizeF(rect.width() / 2, rect.height())), Qt::gray);
|
||
break;
|
||
case ActiveArea::TOP:
|
||
p.fillRect(QRectF(rect.topLeft(), QSizeF(rect.width(), rect.height() / 2)), Qt::gray);
|
||
break;
|
||
case ActiveArea::BOTTOM:
|
||
p.fillRect(QRectF(rect.center() - QPointF(rect.width() / 2, 0), QSizeF(rect.width(), rect.height() / 2)), Qt::gray);
|
||
break;
|
||
case ActiveArea::CENTER:
|
||
p.fillRect(rect, Qt::gray);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
p.setBrush(Qt::transparent);
|
||
|
||
auto lt0 = rect.center() - QPoint(50, 150);
|
||
p.drawRoundRect(QRectF(lt0, QSizeF(100, 300)));
|
||
|
||
auto lt1 = rect.center() - QPoint(150, 50);
|
||
p.drawRoundRect(QRectF(lt1, QSizeF(300, 100)));
|
||
}
|
||
|
||
void AttachPanel::mouseMoveEvent(QMouseEvent *event) { QWidget::mouseMoveEvent(event); }
|
||
|
||
void AttachPanel::dragMoveEvent(QDragMoveEvent *event) {
|
||
QWidget::dragMoveEvent(event);
|
||
|
||
auto tuple_list = view_rects();
|
||
if (std::get<0>(tuple_list).contains(event->pos())) {
|
||
this->active_comp = ActiveArea::LEFT;
|
||
} else if (std::get<1>(tuple_list).contains(event->pos())) {
|
||
this->active_comp = ActiveArea::RIGHT;
|
||
|
||
} else if (std::get<2>(tuple_list).contains(event->pos())) {
|
||
this->active_comp = ActiveArea::TOP;
|
||
|
||
} else if (std::get<3>(tuple_list).contains(event->pos())) {
|
||
this->active_comp = ActiveArea::BOTTOM;
|
||
|
||
} else if (std::get<4>(tuple_list).contains(event->pos())) {
|
||
this->active_comp = ActiveArea::CENTER;
|
||
} else {
|
||
this->active_comp = ActiveArea::NONE;
|
||
}
|
||
|
||
this->update();
|
||
}
|
||
|
||
void AttachPanel::dragEnterEvent(QDragEnterEvent *event) {
|
||
QWidget::dragEnterEvent(event);
|
||
|
||
if (size_host->adjustState())
|
||
event->acceptProposedAction();
|
||
}
|
||
|
||
void AttachPanel::dropEvent(QDropEvent *event) {
|
||
QWidget::dropEvent(event);
|
||
|
||
auto xsource = size_host->adjustView();
|
||
xsource->parentRect()->remove(xsource);
|
||
auto target = this->attachTarget();
|
||
auto ptarget = target->parentRect();
|
||
|
||
SplitRect *newsplit = nullptr;
|
||
switch (this->active_comp) {
|
||
case ActiveArea::LEFT: {
|
||
newsplit = new SplitView(xsource, target, size_host);
|
||
newsplit->setSplitInfo(SplitType::SPLIT_H, target->outline().width() / 2, size_host->splitterWidth());
|
||
} break;
|
||
case ActiveArea::RIGHT: {
|
||
newsplit = new SplitView(target, xsource, size_host);
|
||
newsplit->setSplitInfo(SplitType::SPLIT_H, target->outline().width() / 2, size_host->splitterWidth());
|
||
} break;
|
||
case ActiveArea::TOP: {
|
||
newsplit = new SplitView(xsource, target, size_host);
|
||
newsplit->setSplitInfo(SplitType::SPLIT_V, target->outline().height() / 2, size_host->splitterWidth());
|
||
} break;
|
||
case ActiveArea::BOTTOM: {
|
||
newsplit = new SplitView(target, xsource, size_host);
|
||
newsplit->setSplitInfo(SplitType::SPLIT_V, target->outline().height() / 2, size_host->splitterWidth());
|
||
} break;
|
||
case ActiveArea::CENTER: {
|
||
newsplit = xsource;
|
||
} break;
|
||
default:
|
||
return;
|
||
}
|
||
|
||
ptarget->replace(newsplit, target);
|
||
this->setVisible(false);
|
||
|
||
event->acceptProposedAction();
|
||
}
|
||
|
||
std::tuple<QRectF, QRectF, QRectF, QRectF, QRectF> AttachPanel::view_rects() const {
|
||
auto rect = this->rect();
|
||
auto lt0 = rect.center() - QPoint(50, 150);
|
||
auto lt1 = rect.center() - QPoint(150, 50);
|
||
|
||
return std::make_tuple(QRectF(lt1, QSizeF(100, 100)), QRectF(lt1 + QPoint(200, 0), QSizeF(100, 100)), QRectF(lt0, QSizeF(100, 100)),
|
||
QRectF(lt0 + QPointF(0, 200), QSizeF(100, 100)), QRectF(lt1 + QPointF(100, 0), QSizeF(100, 100)));
|
||
}
|
||
|
||
ViewPresent::ViewPresent(SplitRect *initial_view, QWidget *parent) : QWidget(parent), accept_panel(new AttachPanel(this)) {
|
||
accept_panel->hide();
|
||
|
||
this->split_info_store = std::make_tuple(SplitType::SPLIT_H, 100, 7, 1);
|
||
initial_view->setParentRect(this);
|
||
setMouseTracking(true);
|
||
view_anchors << initial_view;
|
||
}
|
||
|
||
ViewPresent::~ViewPresent() { accept_panel->deleteLater(); }
|
||
|
||
void ViewPresent::registViewComp(BaseView *it) {
|
||
if (this->all_sep_views.contains(it))
|
||
return;
|
||
|
||
it->installPerceptionHandle(this);
|
||
all_sep_views << it;
|
||
}
|
||
|
||
void ViewPresent::setViewAdjust(bool state, BaseView *one) {
|
||
this->adjust_state = state;
|
||
if (!state)
|
||
one = nullptr;
|
||
|
||
this->adjust_view_store = one;
|
||
}
|
||
|
||
bool ViewPresent::adjustState() const { return this->adjust_state; }
|
||
|
||
BaseView *ViewPresent::adjustView() const { return this->adjust_view_store; }
|
||
|
||
void ViewPresent::append(SplitRect *inst, uint index) {
|
||
auto pos = splitterPos();
|
||
auto width = splitterWidth();
|
||
auto idx = index ? 1 : 0;
|
||
auto type = splitType();
|
||
|
||
if (view_anchors.size() == 2) {
|
||
view_anchors[idx]->setParentRect(nullptr);
|
||
view_anchors[idx]->bind()->setVisible(false);
|
||
view_anchors[idx] = inst;
|
||
view_anchors[idx]->setParentRect(this);
|
||
view_anchors[idx]->bind()->setVisible(true);
|
||
} else if (view_anchors.size() == 1) {
|
||
view_anchors.insert(idx, inst);
|
||
view_anchors[idx] = inst;
|
||
view_anchors[idx]->setParentRect(this);
|
||
view_anchors[idx]->bind()->setVisible(true);
|
||
} else {
|
||
view_anchors << inst;
|
||
view_anchors.last()->setParentRect(this);
|
||
view_anchors.last()->bind()->setVisible(true);
|
||
}
|
||
|
||
this->split_info_store = std::make_tuple(type, pos, width, idx);
|
||
this->relayout();
|
||
}
|
||
|
||
bool ViewPresent::eventFilter(QObject *watched, QEvent *event) {
|
||
auto adjust_state = adjustState();
|
||
|
||
if (adjust_state && event->type() == QEvent::DragEnter) {
|
||
for (auto &v : all_sep_views) {
|
||
if (v->contains((QWidget *)watched)) {
|
||
auto outline = v->outline();
|
||
QPoint gpos(v->bind()->mapToGlobal(outline.topLeft().toPoint()));
|
||
|
||
accept_panel->setWindowFlag(Qt::FramelessWindowHint);
|
||
accept_panel->show();
|
||
accept_panel->setGeometry(QRect(gpos, outline.size().toSize()));
|
||
accept_panel->setVisible(true);
|
||
|
||
accept_panel->bind(v);
|
||
event->accept();
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
|
||
return QWidget::eventFilter(watched, event);
|
||
}
|
||
|
||
QWidget *ViewPresent::bind() const { return const_cast<ViewPresent *>(this); }
|
||
|
||
ViewPresent *ViewPresent::viewPanel() const { return const_cast<ViewPresent *>(this); }
|
||
|
||
SplitRect *ViewPresent::parentRect() const { return nullptr; }
|
||
|
||
void ViewPresent::setParentRect(SplitRect *pinst) { throw new SimpleException<QString>("非法操作", "不允许对ViewPresent调用setParentRect!"); }
|
||
|
||
std::pair<SplitRect *, SplitRect *> ViewPresent::child() const {
|
||
SplitRect *inst0 = nullptr, *inst1 = nullptr;
|
||
if (view_anchors.size() > 1)
|
||
inst1 = view_anchors[1];
|
||
if (view_anchors.size() > 0)
|
||
inst0 = view_anchors[0];
|
||
|
||
return std::make_pair(inst0, inst1);
|
||
}
|
||
|
||
void ViewPresent::replace(SplitRect *view, SplitRect *old) {
|
||
if (!view_anchors.contains(old))
|
||
throw new SimpleException<QString>("参数错误", "指定替换的界面不属于此界面");
|
||
|
||
if (view_anchors.contains(view))
|
||
return;
|
||
|
||
view_anchors.replace(view_anchors.indexOf(old), view);
|
||
|
||
relayout();
|
||
}
|
||
|
||
float ViewPresent::splitterWidth() const { return std::get<2>(split_info_store); }
|
||
|
||
float ViewPresent::splitterPos() const { return std::get<1>(split_info_store); }
|
||
|
||
SplitType ViewPresent::splitType() const { return std::get<0>(split_info_store); }
|
||
|
||
void ViewPresent::setSplitInfo(SplitType type, float pos, float width, bool relayout) {
|
||
this->split_info_store = std::make_tuple(type, pos, width, std::get<3>(split_info_store));
|
||
if (relayout)
|
||
this->relayout();
|
||
}
|
||
|
||
QRectF ViewPresent::outline() const { return this->rect(); }
|
||
|
||
void ViewPresent::relayout(const QRectF &outline) { setGeometry(outline.toRect()); }
|
||
|
||
void ViewPresent::paintEvent(QPaintEvent *ev) {
|
||
QWidget::paintEvent(ev);
|
||
|
||
if (view_anchors.size() == 2) {
|
||
QPainter p(this);
|
||
auto handle_rect = handleRect();
|
||
p.fillRect(handle_rect, QBrush(Qt::gray));
|
||
}
|
||
|
||
for (auto &it : view_anchors)
|
||
it->bind()->update();
|
||
}
|
||
|
||
void ViewPresent::remove(SplitRect *child_inst) {
|
||
if (!view_anchors.contains(child_inst))
|
||
throw new SimpleException<QString>("参数非法", "回收的指定视图不属于本ViewPresent");
|
||
|
||
if (child_inst)
|
||
child_inst->bind()->setVisible(false);
|
||
|
||
view_anchors.removeAll(child_inst);
|
||
relayout();
|
||
}
|
||
|
||
void ViewPresent::resizeEvent(QResizeEvent *ev) {
|
||
QWidget::resizeEvent(ev);
|
||
relayout();
|
||
}
|
||
|
||
void ViewPresent::mousePressEvent(QMouseEvent *event) {
|
||
QWidget::mousePressEvent(event);
|
||
|
||
if (event->button() == Qt::MouseButton::LeftButton) {
|
||
if (handleRect().contains(event->pos()))
|
||
this->press_flags = true;
|
||
}
|
||
}
|
||
|
||
void ViewPresent::mouseReleaseEvent(QMouseEvent *event) {
|
||
QWidget::mouseReleaseEvent(event);
|
||
|
||
if (event->button() == Qt::MouseButton::LeftButton) {
|
||
this->press_flags = false;
|
||
}
|
||
}
|
||
|
||
void ViewPresent::mouseMoveEvent(QMouseEvent *event) {
|
||
QWidget::mouseMoveEvent(event);
|
||
|
||
auto drag_rect = handleRect();
|
||
if (drag_rect.contains(event->pos())) {
|
||
if (splitType() == SplitType::SPLIT_H)
|
||
setCursor(QCursor(Qt::CursorShape::SplitHCursor));
|
||
else
|
||
setCursor(QCursor(Qt::CursorShape::SplitVCursor));
|
||
} else {
|
||
setCursor(QCursor(Qt::CursorShape::ArrowCursor));
|
||
}
|
||
|
||
if (this->press_flags) {
|
||
auto pos = this->mapFromGlobal(event->globalPos());
|
||
auto split_margin = splitterWidth();
|
||
if (std::get<0>(split_info_store) == SplitType::SPLIT_H) {
|
||
setSplitInfo(splitType(), pos.x() - split_margin / 2, split_margin, true);
|
||
} else {
|
||
setSplitInfo(splitType(), pos.y() - split_margin / 2, split_margin, true);
|
||
}
|
||
|
||
update();
|
||
}
|
||
}
|
||
|
||
void ViewPresent::relayout() {
|
||
auto rects = viewRects();
|
||
|
||
if (view_anchors.size() == 2) {
|
||
view_anchors[0]->setParentRect(this);
|
||
view_anchors[0]->relayout(rects.first.toRect());
|
||
view_anchors[0]->bind()->setVisible(true);
|
||
|
||
view_anchors[1]->setParentRect(this);
|
||
view_anchors[1]->relayout(rects.second.toRect());
|
||
view_anchors[1]->bind()->setVisible(true);
|
||
} else if (view_anchors.size() == 1) {
|
||
view_anchors[0]->setParentRect(this);
|
||
view_anchors[0]->relayout(this->rect());
|
||
view_anchors[0]->bind()->setVisible(true);
|
||
}
|
||
|
||
update();
|
||
}
|
||
|
||
std::pair<QRectF, QRectF> ViewPresent::viewRects() {
|
||
auto xrect = this->rect();
|
||
|
||
auto type = (int)splitType();
|
||
if (!type) {
|
||
auto width0 = splitterPos();
|
||
if (width0 + splitterWidth() > xrect.width())
|
||
width0 = xrect.width() - splitterWidth();
|
||
if (width0 < 0)
|
||
width0 = 0;
|
||
|
||
setSplitInfo(splitType(), width0, splitterWidth(), false);
|
||
|
||
auto rect0 = QRectF(xrect.topLeft(), QSizeF(width0, xrect.height()));
|
||
auto rect1 = QRectF(xrect.topLeft() + QPointF(rect0.width() + splitterWidth(), 0),
|
||
QSizeF(xrect.width() - rect0.width() - splitterWidth(), xrect.height()));
|
||
return std::make_pair(rect0, rect1);
|
||
} else {
|
||
auto height0 = splitterPos();
|
||
if (height0 + splitterWidth() > xrect.height())
|
||
height0 = xrect.height() - splitterWidth();
|
||
if (height0 < 0)
|
||
height0 = 0;
|
||
|
||
setSplitInfo(splitType(), height0, splitterWidth(), false);
|
||
|
||
auto rect0 = QRectF(xrect.topLeft(), QSizeF(xrect.width(), height0));
|
||
auto rect1 = QRectF(xrect.topLeft() + QPointF(0, rect0.height() + splitterWidth()),
|
||
QSizeF(xrect.width(), xrect.height() - splitterWidth() - rect0.height()));
|
||
return std::make_pair(rect0, rect1);
|
||
}
|
||
}
|
||
|
||
QRectF ViewPresent::handleRect() const {
|
||
QRectF rect;
|
||
|
||
auto width_middle = splitterWidth() - 2;
|
||
if (splitType() == SplitType::SPLIT_H) {
|
||
rect = QRectF(splitterPos() + 1, 0, width_middle, outline().height());
|
||
} else {
|
||
rect = QRectF(0, splitterPos() + 1, outline().width(), width_middle);
|
||
}
|
||
|
||
return rect;
|
||
}
|
||
|
||
SplitView::SplitView(SplitRect *first, SplitRect *next, QWidget *parent) : QWidget(parent) {
|
||
this->split_info_value = std::make_tuple(SplitType::SPLIT_H, 100, 7);
|
||
this->child_store << first;
|
||
this->child_store << next;
|
||
setMouseTracking(true);
|
||
|
||
first->setParentRect(this);
|
||
next->setParentRect(this);
|
||
}
|
||
|
||
QWidget *SplitView::bind() const { return const_cast<SplitView *>(this); }
|
||
|
||
ViewPresent *SplitView::viewPanel() const {
|
||
if (parentRect() == nullptr)
|
||
return nullptr;
|
||
return parentRect()->viewPanel();
|
||
}
|
||
|
||
SplitRect *SplitView::parentRect() const { return parent_inst; }
|
||
|
||
void SplitView::setParentRect(SplitRect *pinst) {
|
||
if (pinst) {
|
||
auto pwidget = pinst->bind();
|
||
this->setParent(pwidget);
|
||
} else
|
||
this->setParent(nullptr);
|
||
|
||
this->parent_inst = pinst;
|
||
}
|
||
|
||
std::pair<SplitRect *, SplitRect *> SplitView::child() const { return std::make_pair(child_store[0], child_store[1]); }
|
||
|
||
float SplitView::splitterWidth() const { return std::get<2>(split_info_value); }
|
||
|
||
float SplitView::splitterPos() const { return std::get<1>(split_info_value); }
|
||
|
||
SplitType SplitView::splitType() const { return std::get<0>(split_info_value); }
|
||
|
||
void SplitView::setSplitInfo(SplitType type, float pos, float width, bool relayout) {
|
||
this->split_info_value = std::make_tuple(type, pos, width);
|
||
if (relayout)
|
||
this->relayout();
|
||
}
|
||
|
||
void SplitView::replace(SplitRect *view, SplitRect *old) {
|
||
if (child_store.contains(old) && !child_store.contains(view)) {
|
||
auto index = child_store.indexOf(old);
|
||
child_store.replace(index, view);
|
||
}
|
||
|
||
relayout();
|
||
}
|
||
|
||
QRectF SplitView::outline() const { return this->rect(); }
|
||
|
||
void SplitView::relayout(const QRectF &outlinex) {
|
||
this->setGeometry(outlinex.toRect());
|
||
update();
|
||
}
|
||
|
||
void SplitView::remove(SplitRect *child_inst) {
|
||
auto pinst = parentRect();
|
||
|
||
auto sib = this->child().first;
|
||
if (child_inst == sib)
|
||
sib = this->child().second;
|
||
|
||
child_inst->bind()->setVisible(false);
|
||
pinst->replace(sib, this);
|
||
|
||
child_inst->setParentRect(nullptr);
|
||
delete this;
|
||
}
|
||
|
||
void SplitView::paintEvent(QPaintEvent *ev) {
|
||
QWidget::paintEvent(ev);
|
||
|
||
QPainter p(this);
|
||
QRectF rect = handleRect();
|
||
p.fillRect(rect, QBrush(Qt::gray, Qt::BrushStyle::SolidPattern));
|
||
|
||
for (auto &it : child_store)
|
||
it->bind()->update();
|
||
}
|
||
|
||
void SplitView::resizeEvent(QResizeEvent *ev) {
|
||
QWidget::resizeEvent(ev);
|
||
relayout();
|
||
}
|
||
|
||
void SplitView::mousePressEvent(QMouseEvent *event) {
|
||
QWidget::mousePressEvent(event);
|
||
|
||
if (event->button() == Qt::MouseButton::LeftButton) {
|
||
if (handleRect().contains(event->pos()))
|
||
this->press_flags = true;
|
||
}
|
||
}
|
||
|
||
void SplitView::mouseReleaseEvent(QMouseEvent *event) {
|
||
QWidget::mouseReleaseEvent(event);
|
||
|
||
if (event->button() == Qt::MouseButton::LeftButton) {
|
||
this->press_flags = false;
|
||
}
|
||
}
|
||
|
||
void SplitView::mouseMoveEvent(QMouseEvent *event) {
|
||
QWidget::mouseMoveEvent(event);
|
||
|
||
auto drag_rect = handleRect() + QMargins(2, 2, 2, 2);
|
||
if (drag_rect.contains(event->pos())) {
|
||
if (splitType() == SplitType::SPLIT_H)
|
||
setCursor(QCursor(Qt::CursorShape::SplitHCursor));
|
||
else
|
||
setCursor(QCursor(Qt::CursorShape::SplitVCursor));
|
||
|
||
drags_flag = true;
|
||
} else {
|
||
setCursor(QCursor(Qt::CursorShape::ArrowCursor));
|
||
}
|
||
|
||
if (this->press_flags) {
|
||
auto pos = this->mapFromGlobal(event->globalPos());
|
||
auto split_margin = splitterWidth();
|
||
if (std::get<0>(split_info_value) == SplitType::SPLIT_H) {
|
||
setSplitInfo(splitType(), pos.x() - split_margin / 2, split_margin, true);
|
||
} else {
|
||
setSplitInfo(splitType(), pos.y() - split_margin / 2, split_margin, true);
|
||
}
|
||
update();
|
||
}
|
||
}
|
||
|
||
bool SplitView::eventFilter(QObject *watched, QEvent *event) {
|
||
if (watched != this && this->drags_flag && event->type() == QEvent::MouseMove) {
|
||
auto x = static_cast<QMouseEvent *>(event);
|
||
auto pos = mapFromGlobal(x->globalPos());
|
||
if (!handleRect().contains(pos)) {
|
||
setCursor(QCursor(Qt::CursorShape::ArrowCursor));
|
||
this->drags_flag = false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
return QWidget::eventFilter(watched, event);
|
||
}
|
||
|
||
void SplitView::relayout() {
|
||
auto rects = viewRects();
|
||
auto pair = child();
|
||
|
||
pair.first->setParentRect(this);
|
||
pair.first->relayout(std::get<0>(rects));
|
||
pair.second->setParentRect(this);
|
||
pair.second->relayout(std::get<1>(rects));
|
||
|
||
auto awidget = dynamic_cast<QWidget *>(pair.first);
|
||
auto bwidget = dynamic_cast<QWidget *>(pair.second);
|
||
awidget->setVisible(true);
|
||
bwidget->setVisible(true);
|
||
|
||
update();
|
||
}
|
||
|
||
std::pair<QRectF, QRectF> SplitView::viewRects() {
|
||
auto xrect = this->rect();
|
||
|
||
auto type = (int)splitType();
|
||
if (!type) {
|
||
auto width0 = splitterPos();
|
||
if (width0 + splitterWidth() > xrect.width())
|
||
width0 = xrect.width() - splitterWidth();
|
||
if (width0 < 0)
|
||
width0 = 0;
|
||
|
||
setSplitInfo(splitType(), width0, splitterWidth(), false);
|
||
|
||
auto rect0 = QRectF(xrect.topLeft(), QSizeF(width0, xrect.height()));
|
||
auto rect1 = QRectF(xrect.topLeft() + QPointF(rect0.width() + splitterWidth(), 0),
|
||
QSizeF(xrect.width() - rect0.width() - splitterWidth(), xrect.height()));
|
||
return std::make_pair(rect0, rect1);
|
||
} else {
|
||
auto height0 = splitterPos();
|
||
if (height0 + splitterWidth() > xrect.height())
|
||
height0 = xrect.height() - splitterWidth();
|
||
if (height0 < 0)
|
||
height0 = 0;
|
||
|
||
setSplitInfo(splitType(), height0, splitterWidth(), false);
|
||
|
||
auto rect0 = QRectF(xrect.topLeft(), QSizeF(xrect.width(), height0));
|
||
auto rect1 = QRectF(xrect.topLeft() + QPointF(0, rect0.height() + splitterWidth()),
|
||
QSizeF(xrect.width(), xrect.height() - splitterWidth() - rect0.height()));
|
||
return std::make_pair(rect0, rect1);
|
||
}
|
||
}
|
||
|
||
QRectF SplitView::handleRect() const {
|
||
QRectF rect;
|
||
|
||
auto width_middle = splitterWidth() - 2;
|
||
if (splitType() == SplitType::SPLIT_H) {
|
||
rect = QRectF(splitterPos() + 1, 0, width_middle, outline().height());
|
||
} else {
|
||
rect = QRectF(0, splitterPos() + 1, outline().width(), width_middle);
|
||
}
|
||
|
||
return rect;
|
||
}
|
||
|
||
DragHeader::DragHeader(BaseView *bind) : QFrame(bind->bind()), icon_store(new QLabel(this)), title_store(new QLabel(this)), view_core(bind) {
|
||
setFrameShadow(QFrame::Shadow::Raised);
|
||
setFrameShape(QFrame::Shape::Box);
|
||
setStyleSheet("background-color: rgb(200, 200, 255);");
|
||
|
||
auto layout = new QHBoxLayout(this);
|
||
layout->setMargin(1);
|
||
layout->setSpacing(2);
|
||
layout->addWidget(icon_store, 0);
|
||
layout->addWidget(title_store, 1);
|
||
|
||
auto hide = new QPushButton("-", this);
|
||
layout->addWidget(hide, 0);
|
||
hide->setMaximumSize(20, 20);
|
||
auto close = new QPushButton("X", this);
|
||
layout->addWidget(close, 0);
|
||
close->setMaximumSize(20, 20);
|
||
|
||
connect(hide, &QPushButton::clicked, [=]() {
|
||
auto con = this->view_core->parentRect();
|
||
con->remove(view_core);
|
||
});
|
||
|
||
connect(close, &QPushButton::clicked, [=]() {
|
||
hide->click();
|
||
view_core->closeView();
|
||
});
|
||
}
|
||
|
||
void DragHeader::setIcon(const QIcon &icon) {
|
||
icon_inst = icon;
|
||
auto len = this->height() - 2;
|
||
this->icon_store->setPixmap(icon.pixmap(QSize(len, len)));
|
||
}
|
||
|
||
QIcon DragHeader::icon() const { return this->icon_inst; }
|
||
|
||
void DragHeader::setText(const QString &title) { this->title_store->setText(title); }
|
||
|
||
QString DragHeader::text() const { return title_store->text(); }
|
||
|
||
void DragHeader::mousePressEvent(QMouseEvent *event) {
|
||
if (event->button() == Qt::LeftButton && !std::get<0>(press_flag)) {
|
||
this->press_flag = std::make_tuple(true, event->pos());
|
||
}
|
||
}
|
||
|
||
void DragHeader::mouseReleaseEvent(QMouseEvent *event) {
|
||
if (event->button() == Qt::LeftButton) {
|
||
this->press_flag = std::make_tuple(false, QPointF());
|
||
}
|
||
}
|
||
|
||
void DragHeader::mouseMoveEvent(QMouseEvent *event) {
|
||
if (std::get<0>(press_flag) && QLineF(std::get<1>(press_flag), event->pos()).length() > QApplication::startDragDistance()) {
|
||
auto panel = view_core->viewPanel();
|
||
panel->setViewAdjust(true, view_core);
|
||
|
||
QDrag *drag = new QDrag(this);
|
||
auto pix = view_core->grab();
|
||
drag->setPixmap(pix);
|
||
drag->setHotSpot(QPoint(20, 20));
|
||
|
||
QMimeData *mimeData = new QMimeData;
|
||
mimeData->setText("移动视图:" + view_core->title());
|
||
drag->setMimeData(mimeData);
|
||
|
||
drag->exec();
|
||
}
|
||
}
|