QtNovelUI/SplitView/splitview.cpp

784 lines
24 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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();
}
}