QtNovelUI/libSplitView/splitview.cpp

231 lines
7.1 KiB
C++

#include "splitview.h"
#include "baseview.h"
#include <QPainter>
#include <libConfig.h>
using namespace SplitFrame;
using namespace Config;
SplitView::SplitView(RectCom *first, RectCom *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);
}
SplitFrame::SplitView::~SplitView() {
for (auto &it : children()) {
auto widget = qobject_cast<QWidget *>(it);
if (widget) {
widget->setParent(nullptr);
}
}
}
QWidget *SplitView::bind() const { return const_cast<SplitView *>(this); }
ViewPresent *SplitView::viewPanel() const { return parentRes()->viewPanel(); }
ViewRes *SplitView::parentRes() const { return parent_inst; }
void SplitView::setParentRes(ViewRes *pinst) {
this->parent_inst = pinst;
QWidget::setParent(pinst != nullptr ? pinst->bind() : nullptr);
for (auto &c : child_store)
c->setParentRes(this);
}
void SplitView::registElement(QWidget *) { throw new SimpleException<bool>("非法操作", "SplitView当前不支持registElement操作"); }
void SplitView::pRelease() { throw new SimpleException<bool>("非法操作", "SplitView当前不支持pRelease操作"); }
void SplitView::pClose() { throw new SimpleException<bool>("非法操作", "SplitView当前不支持pClose操作"); }
std::pair<RectCom *, RectCom *> 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::replaceComp(RectCom *view, RectCom *old) {
if (!child_store.contains(old) || child_store.contains(view)) {
throw new SimpleException<QString>("参数非法", "要替换的视图不属于本构件,或者新视图本就属于本构件");
}
auto index = child_store.indexOf(old);
child_store.replace(index, view);
view->setParentRes(this);
viewPanel()->objsRelateRebuild();
}
QRectF SplitView::outline() const { return this->rect(); }
void SplitView::relayout(const QRectF &outlinex) {
this->setGeometry(outlinex.toRect());
this->relayout();
}
void SplitView::removeComp(RectCom *child_inst) {
auto pinst = parentRes();
auto prev_childs = child();
prev_childs.first->setParentRes(nullptr);
prev_childs.second->setParentRes(nullptr);
this->child_store.clear();
this->setParentRes(nullptr);
auto sib = prev_childs.first;
if (child_inst == sib)
sib = prev_childs.second;
static_cast<SplitRect *>(pinst)->replaceComp(sib, this);
delete this;
}
void SplitView::paintEvent(QPaintEvent *ev) {
QWidget::paintEvent(ev);
QPainter p(this);
QRectF rect = handle_rect();
p.fillRect(rect, QBrush(Qt::gray, Qt::BrushStyle::SolidPattern));
for (auto &it : child_store) {
it->bind()->setVisible(true);
it->bind()->update();
}
}
bool SplitView::contains(QWidget *) const { return false; }
QString SplitView::title() const { return ""; }
void SplitView::resizeEvent(QResizeEvent *ev) {
QWidget::resizeEvent(ev);
relayout();
}
void SplitView::mousePressEvent(QMouseEvent *event) {
QWidget::mousePressEvent(event);
if (event->button() == Qt::MouseButton::LeftButton) {
if (handle_rect().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 = handle_rect() + 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 (!handle_rect().contains(pos)) {
setCursor(QCursor(Qt::CursorShape::ArrowCursor));
this->drags_flag = false;
}
return true;
}
return QWidget::eventFilter(watched, event);
}
void SplitView::relayout() {
auto rects = view_rects();
auto pair = child();
pair.first->relayout(std::get<0>(rects));
pair.second->relayout(std::get<1>(rects));
update();
}
std::pair<QRectF, QRectF> SplitView::view_rects() {
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::handle_rect() 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;
}