完成拖动,但是未完成释放
This commit is contained in:
parent
d2ac84894d
commit
b6bae9980b
|
|
@ -2,6 +2,7 @@ TEMPLATE = subdirs
|
|||
|
||||
SUBDIRS += \
|
||||
GenericConsole \
|
||||
SplitView \
|
||||
WordsIDE \
|
||||
libConfig \
|
||||
libProjectManager \
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 4.15.0, 2023-08-13T11:50:05. -->
|
||||
<!-- Written by QtCreator 4.15.0, 2023-08-20T21:48:18. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
|
|
@ -346,7 +346,80 @@
|
|||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">D:/Projects/Cpp/build-QtNovelDesc-Desktop_Qt_5_12_11_MSVC2017_64bit-Debug/u_test</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.1">
|
||||
<value type="QString" key="Analyzer.Perf.CallgraphMode">dwarf</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Perf.Events">
|
||||
<value type="QString">cpu-cycles</value>
|
||||
</valuelist>
|
||||
<valuelist type="QVariantList" key="Analyzer.Perf.ExtraArguments"/>
|
||||
<value type="int" key="Analyzer.Perf.Frequency">250</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Perf.RecordArguments">
|
||||
<value type="QString">-e</value>
|
||||
<value type="QString">cpu-cycles</value>
|
||||
<value type="QString">--call-graph</value>
|
||||
<value type="QString">dwarf,4096</value>
|
||||
<value type="QString">-F</value>
|
||||
<value type="QString">250</value>
|
||||
</valuelist>
|
||||
<value type="QString" key="Analyzer.Perf.SampleMode">-F</value>
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Perf.StackSize">4096</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
|
||||
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
|
||||
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
|
||||
<value type="QString" key="Analyzer.Valgrind.Callgrind.Arguments"></value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.KCachegrindExecutable">kcachegrind</value>
|
||||
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.Memcheck.Arguments"></value>
|
||||
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
|
||||
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.ValgrindArguments"></value>
|
||||
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
|
||||
<value type="int">0</value>
|
||||
<value type="int">1</value>
|
||||
<value type="int">2</value>
|
||||
<value type="int">3</value>
|
||||
<value type="int">4</value>
|
||||
<value type="int">5</value>
|
||||
<value type="int">6</value>
|
||||
<value type="int">7</value>
|
||||
<value type="int">8</value>
|
||||
<value type="int">9</value>
|
||||
<value type="int">10</value>
|
||||
<value type="int">11</value>
|
||||
<value type="int">12</value>
|
||||
<value type="int">13</value>
|
||||
<value type="int">14</value>
|
||||
</valuelist>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:D:/Projects/Cpp/QtNovelDesc/WordsIDE/WordsIDE.pro</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">D:/Projects/Cpp/QtNovelDesc/WordsIDE/WordsIDE.pro</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">D:/Projects/Cpp/build-QtNovelDesc-Desktop_Qt_5_12_11_MSVC2017_64bit-Debug/WordsIDE</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">2</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
QT += gui widgets
|
||||
|
||||
TEMPLATE = lib
|
||||
DEFINES += SPLITVIEW_LIBRARY
|
||||
|
||||
CONFIG += c++11
|
||||
|
||||
# You can make your code fail to compile if it uses deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
msvc{
|
||||
QMAKE_CFLAGS += /utf-8
|
||||
QMAKE_CXXFLAGS += /utf-8
|
||||
}
|
||||
|
||||
SOURCES += \
|
||||
splitview.cpp
|
||||
|
||||
HEADERS += \
|
||||
SplitView_global.h \
|
||||
splitview.h
|
||||
|
||||
# Default rules for deployment.
|
||||
unix {
|
||||
target.path = /usr/lib
|
||||
}
|
||||
!isEmpty(target.path): INSTALLS += target
|
||||
|
||||
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../libConfig/release/ -llibConfig
|
||||
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../libConfig/debug/ -llibConfig
|
||||
else:unix: LIBS += -L$$OUT_PWD/../libConfig/ -llibConfig
|
||||
|
||||
INCLUDEPATH += $$PWD/../libConfig
|
||||
DEPENDPATH += $$PWD/../libConfig
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef SPLITVIEW_GLOBAL_H
|
||||
#define SPLITVIEW_GLOBAL_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#if defined(SPLITVIEW_LIBRARY)
|
||||
# define SPLITVIEW_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
# define SPLITVIEW_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
#endif // SPLITVIEW_GLOBAL_H
|
||||
|
|
@ -0,0 +1,719 @@
|
|||
#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;
|
||||
|
||||
class ViewDragDrapCommon {
|
||||
public:
|
||||
BaseView *target;
|
||||
static QString type_sign;
|
||||
|
||||
ViewDragDrapCommon(BaseView *inst) : target(inst) {}
|
||||
ViewDragDrapCommon() : target(nullptr) {}
|
||||
};
|
||||
QString ViewDragDrapCommon::type_sign = "custom/drag-drop-view";
|
||||
|
||||
Q_DECLARE_METATYPE(ViewDragDrapCommon)
|
||||
QDataStream &operator<<(QDataStream &out, const ViewDragDrapCommon &myObj) {
|
||||
out << myObj.target;
|
||||
return out;
|
||||
}
|
||||
QDataStream &operator>>(QDataStream &in, ViewDragDrapCommon &myObj) {
|
||||
qint64 handle;
|
||||
in >> handle;
|
||||
myObj.target = (BaseView *)handle;
|
||||
return in;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (!empty) {
|
||||
title_header = new DragHeader(this);
|
||||
title_header->setText(title);
|
||||
title_header->setMaximumHeight(22);
|
||||
|
||||
layout->addWidget(title_header, 0);
|
||||
}
|
||||
|
||||
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 {
|
||||
const SplitRect *tnode = this;
|
||||
while (!tnode->parentRect()) {
|
||||
tnode = tnode->parentRect();
|
||||
}
|
||||
|
||||
return static_cast<ViewPresent *>(const_cast<SplitRect *>(tnode));
|
||||
}
|
||||
|
||||
void BaseView::closeView() {}
|
||||
|
||||
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::insertPerceptionHandle(ViewPresent *obj) {
|
||||
for (auto &it : comps_list) {
|
||||
it->removeEventFilter(obj);
|
||||
it->installEventFilter(obj);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseView::paintEvent(QPaintEvent *ev) { QWidget::paintEvent(ev); }
|
||||
|
||||
void BaseView::retrieveComp(SplitRect *child_inst) { throw new SimpleException<QString>("非法操作", "BaseView不支持retrieveComp操作"); }
|
||||
|
||||
DockPanel::DockPanel(ViewPresent *host) : QWidget(host->bind()), size_host(host) { setWindowOpacity(50); }
|
||||
|
||||
void DockPanel::bind(BaseView *widget) { this->current_target = widget; }
|
||||
|
||||
BaseView *DockPanel::target() const { return this->current_target; }
|
||||
|
||||
void DockPanel::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 DockPanel::mouseMoveEvent(QMouseEvent *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();
|
||||
}
|
||||
|
||||
std::tuple<QRectF, QRectF, QRectF, QRectF, QRectF> DockPanel::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 DockPanel(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;
|
||||
|
||||
qRegisterMetaTypeStreamOperators<ViewDragDrapCommon>("ViewDragDrapCommon");
|
||||
}
|
||||
|
||||
void ViewPresent::setViewAdjust(bool state) { this->dragdrop_state = state; }
|
||||
|
||||
bool ViewPresent::adjustState() const { return this->dragdrop_state; }
|
||||
|
||||
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) {
|
||||
if (adjustState()) {
|
||||
qDebug() << "adjust-move";
|
||||
return true;
|
||||
}
|
||||
|
||||
return QWidget::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
QWidget *ViewPresent::bind() 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;
|
||||
|
||||
if (old) {
|
||||
old->bind()->setVisible(false);
|
||||
old->setParentRect(nullptr);
|
||||
}
|
||||
|
||||
view_anchors.replace(view_anchors.indexOf(old), view);
|
||||
if (view) {
|
||||
view->setParentRect(this);
|
||||
view->bind()->setVisible(true);
|
||||
}
|
||||
|
||||
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::retrieveComp(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]->relayout(rects.first.toRect());
|
||||
view_anchors[1]->relayout(rects.second.toRect());
|
||||
} else if (view_anchors.size() == 1) {
|
||||
view_anchors[0]->relayout(this->rect());
|
||||
}
|
||||
|
||||
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); }
|
||||
|
||||
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);
|
||||
|
||||
old->setParentRect(nullptr);
|
||||
view->setParentRect(this);
|
||||
}
|
||||
|
||||
relayout();
|
||||
}
|
||||
|
||||
QRectF SplitView::outline() const { return this->rect(); }
|
||||
|
||||
void SplitView::relayout(const QRectF &outlinex) {
|
||||
this->setGeometry(outlinex.toRect());
|
||||
update();
|
||||
}
|
||||
|
||||
void SplitView::retrieveComp(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();
|
||||
|
||||
auto awidget = dynamic_cast<QWidget *>(pair.first);
|
||||
auto bwidget = dynamic_cast<QWidget *>(pair.second);
|
||||
if (!awidget->isVisible())
|
||||
awidget->setVisible(true);
|
||||
if (!bwidget->isVisible())
|
||||
bwidget->setVisible(true);
|
||||
|
||||
pair.first->relayout(std::get<0>(rects));
|
||||
pair.second->relayout(std::get<1>(rects));
|
||||
|
||||
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->retrieveComp(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()) {
|
||||
view_core->viewPanel()->setViewAdjust(true);
|
||||
|
||||
QDrag *drag = new QDrag(this);
|
||||
auto pix = view_core->grab();
|
||||
drag->setPixmap(pix);
|
||||
drag->setHotSpot(QPoint(20, 20));
|
||||
|
||||
QMimeData *mimeData = new QMimeData;
|
||||
|
||||
ViewDragDrapCommon wrap(view_core);
|
||||
QByteArray buff;
|
||||
QDataStream out(&buff, QIODevice::WriteOnly);
|
||||
out << wrap;
|
||||
|
||||
mimeData->setData(ViewDragDrapCommon::type_sign, buff);
|
||||
drag->setMimeData(mimeData);
|
||||
|
||||
drag->exec();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,236 @@
|
|||
#ifndef SPLITVIEW_H
|
||||
#define SPLITVIEW_H
|
||||
|
||||
#include "SplitView_global.h"
|
||||
#include <QHash>
|
||||
#include <QIcon>
|
||||
#include <QLabel>
|
||||
#include <QWidget>
|
||||
|
||||
namespace SplitFrame {
|
||||
class SplitRect;
|
||||
class ViewPresent;
|
||||
class BaseView;
|
||||
|
||||
/**
|
||||
* @brief 承接堆放操作及设定摆放位置
|
||||
*/
|
||||
class SPLITVIEW_EXPORT DockPanel : public QWidget {
|
||||
enum class ActiveArea { LEFT, RIGHT, TOP, BOTTOM, CENTER, NONE };
|
||||
|
||||
public:
|
||||
DockPanel(ViewPresent *host);
|
||||
|
||||
void bind(BaseView *widget);
|
||||
BaseView *target() const;
|
||||
|
||||
virtual void paintEvent(QPaintEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
ViewPresent *const size_host;
|
||||
BaseView *current_target;
|
||||
ActiveArea active_comp;
|
||||
|
||||
std::tuple<QRectF, QRectF, QRectF, QRectF, QRectF> view_rects() const;
|
||||
};
|
||||
|
||||
enum class SplitType { SPLIT_H = 0, SPLIT_V = 1 };
|
||||
|
||||
/**
|
||||
* @brief 分裂视图规划和约束组件
|
||||
*/
|
||||
class SplitRect {
|
||||
public:
|
||||
virtual ~SplitRect() = default;
|
||||
|
||||
virtual QWidget *bind() const = 0;
|
||||
|
||||
virtual SplitRect *parentRect() const = 0;
|
||||
virtual void setParentRect(SplitRect *pinst) = 0;
|
||||
|
||||
virtual std::pair<SplitRect *, SplitRect *> child() const = 0;
|
||||
virtual void replace(SplitRect *view, SplitRect *old) = 0;
|
||||
virtual float splitterWidth() const = 0;
|
||||
virtual float splitterPos() const = 0;
|
||||
virtual SplitType splitType() const = 0;
|
||||
virtual void setSplitInfo(SplitType type, float pos, float width, bool relayout = true) = 0;
|
||||
|
||||
virtual QRectF outline() const = 0;
|
||||
virtual void relayout(const QRectF &outline) = 0;
|
||||
virtual void retrieveComp(SplitRect *child) = 0;
|
||||
|
||||
virtual void paintEvent(QPaintEvent *ev) = 0;
|
||||
};
|
||||
|
||||
class SPLITVIEW_EXPORT SplitView : public QWidget, public SplitRect {
|
||||
|
||||
public:
|
||||
SplitView(SplitRect *first, SplitRect *next, QWidget *parent = nullptr);
|
||||
|
||||
// SplitRect interface
|
||||
public:
|
||||
virtual QWidget *bind() const override;
|
||||
virtual SplitRect *parentRect() const override;
|
||||
virtual void setParentRect(SplitRect *pinst) override;
|
||||
|
||||
virtual std::pair<SplitRect *, SplitRect *> child() const override;
|
||||
virtual float splitterWidth() const override;
|
||||
virtual float splitterPos() const override;
|
||||
virtual SplitType splitType() const override;
|
||||
virtual void setSplitInfo(SplitType type, float pos, float width, bool relayout) override;
|
||||
virtual void replace(SplitRect *view, SplitRect *old) override;
|
||||
|
||||
virtual QRectF outline() const override;
|
||||
virtual void relayout(const QRectF &outline) override;
|
||||
virtual void retrieveComp(SplitRect *child_inst) override;
|
||||
|
||||
// QWidget interface
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent *ev) override;
|
||||
virtual void resizeEvent(QResizeEvent *ev) override;
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
|
||||
// QObject interface
|
||||
public:
|
||||
virtual bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
|
||||
private:
|
||||
SplitRect *parent_inst;
|
||||
QList<SplitRect *> child_store;
|
||||
// type, pos, width
|
||||
std::tuple<SplitType, float, float> split_info_value;
|
||||
bool press_flags = false, drags_flag = false;
|
||||
|
||||
virtual void relayout();
|
||||
std::pair<QRectF, QRectF> viewRects();
|
||||
QRectF handleRect() const;
|
||||
};
|
||||
|
||||
class DragHeader : public QFrame {
|
||||
public:
|
||||
DragHeader(BaseView *bind);
|
||||
|
||||
void setIcon(const QIcon &icon);
|
||||
QIcon icon() const;
|
||||
void setText(const QString &title);
|
||||
QString text() const;
|
||||
|
||||
private:
|
||||
QIcon icon_inst;
|
||||
QLabel *const icon_store, *const title_store;
|
||||
BaseView *const view_core;
|
||||
std::tuple<bool, QPointF> press_flag = std::make_tuple(false, QPointF());
|
||||
|
||||
// QWidget interface
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 基础内容视图组件
|
||||
*/
|
||||
class SPLITVIEW_EXPORT BaseView : public QWidget, public SplitRect {
|
||||
public:
|
||||
BaseView(const QString &title, QWidget *view, bool empty = false, QWidget *parent = nullptr);
|
||||
|
||||
virtual void setTitle(const QString &title);
|
||||
virtual QString title() const;
|
||||
|
||||
virtual void setIcon(const QIcon &icon);
|
||||
virtual QIcon viewIcon() const;
|
||||
|
||||
ViewPresent *viewPanel() const;
|
||||
virtual void closeView();
|
||||
|
||||
// SplitRect interface
|
||||
public:
|
||||
virtual QWidget *bind() const override;
|
||||
virtual SplitRect *parentRect() const override;
|
||||
virtual void setParentRect(SplitRect *pinst) override;
|
||||
virtual std::pair<SplitRect *, SplitRect *> child() const override;
|
||||
virtual void replace(SplitRect *view, SplitRect *old) override;
|
||||
virtual float splitterWidth() const override;
|
||||
virtual float splitterPos() const override;
|
||||
virtual SplitType splitType() const override;
|
||||
virtual void setSplitInfo(SplitType type, float pos, float width, bool relayout) override;
|
||||
virtual QRectF outline() const override;
|
||||
virtual void relayout(const QRectF &outline) override;
|
||||
|
||||
virtual void insertPerceptionHandle(ViewPresent *obj);
|
||||
virtual void paintEvent(QPaintEvent *ev) override;
|
||||
virtual void retrieveComp(SplitRect *child_inst) override;
|
||||
|
||||
private:
|
||||
DragHeader *title_header;
|
||||
SplitRect *parent_store;
|
||||
QList<QWidget *> comps_list;
|
||||
|
||||
protected:
|
||||
virtual void registComp(QWidget *child);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 分裂视图呈现组件
|
||||
*/
|
||||
class SPLITVIEW_EXPORT ViewPresent : public QWidget, public SplitRect {
|
||||
public:
|
||||
ViewPresent(SplitRect *initial_view, QWidget *parent = nullptr);
|
||||
|
||||
/**
|
||||
* @brief 切换视图调整状态
|
||||
* @param state 状态开关
|
||||
*/
|
||||
void setViewAdjust(bool state);
|
||||
bool adjustState() const;
|
||||
|
||||
void append(SplitRect *inst, uint index);
|
||||
|
||||
// QObject interface
|
||||
public:
|
||||
virtual bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
|
||||
// SplitRect interface
|
||||
public:
|
||||
virtual QWidget *bind() const override;
|
||||
virtual SplitRect *parentRect() const override;
|
||||
virtual void setParentRect(SplitRect *pinst) override;
|
||||
|
||||
virtual std::pair<SplitRect *, SplitRect *> child() const override;
|
||||
virtual void replace(SplitRect *view, SplitRect *old) override;
|
||||
virtual float splitterWidth() const override;
|
||||
virtual float splitterPos() const override;
|
||||
virtual SplitType splitType() const override;
|
||||
virtual void setSplitInfo(SplitType type, float pos, float width, bool relayout) override;
|
||||
virtual QRectF outline() const override;
|
||||
virtual void relayout(const QRectF &outline) override;
|
||||
virtual void retrieveComp(SplitRect *child_inst) override;
|
||||
|
||||
// QWidget interface
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent *ev) override;
|
||||
virtual void resizeEvent(QResizeEvent *ev) override;
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
DockPanel *const accept_panel;
|
||||
bool press_flags = false;
|
||||
bool dragdrop_state = false;
|
||||
QList<SplitRect *> view_anchors;
|
||||
// 方向,splitter位置,splitter宽度,extend索引
|
||||
std::tuple<SplitType, float, float, uint> split_info_store;
|
||||
|
||||
virtual void relayout();
|
||||
std::pair<QRectF, QRectF> viewRects();
|
||||
QRectF handleRect() const;
|
||||
};
|
||||
|
||||
} // namespace SplitFrame
|
||||
|
||||
#endif // SPLITVIEW_H
|
||||
|
|
@ -12,11 +12,3 @@
|
|||
using namespace Core;
|
||||
using namespace Components;
|
||||
using namespace MakeTools;
|
||||
|
||||
|
||||
SimpleException::SimpleException(const QString &msg)
|
||||
: msg_store(msg) {}
|
||||
|
||||
const char *SimpleException::what() const{
|
||||
return msg_store.toLocal8Bit();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,19 +7,6 @@
|
|||
#include <libConfig.h>
|
||||
#include <libProjectManager.h>
|
||||
|
||||
class SimpleException : public std::exception
|
||||
{
|
||||
public:
|
||||
explicit SimpleException(const QString &msg);
|
||||
|
||||
private:
|
||||
QString msg_store;
|
||||
|
||||
// exception interface
|
||||
public:
|
||||
virtual const char *what() const override;
|
||||
};
|
||||
|
||||
namespace Core {
|
||||
|
||||
enum class Scale
|
||||
|
|
|
|||
|
|
@ -53,24 +53,22 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
setMinimumSize(1000, 600);
|
||||
setWindowTitle("提线木偶");
|
||||
|
||||
project_present->widget()->setVisible(false);
|
||||
errors_present->setVisible(false);
|
||||
|
||||
auto mbar = menuBar();
|
||||
initial_menubar(mbar);
|
||||
|
||||
setCentralWidget(this->split_first);
|
||||
this->split_first->addWidget(project_present);
|
||||
this->split_first->addWidget(this->split_second);
|
||||
this->split_third->addWidget(this->center_frame->hostWidget());
|
||||
this->split_third->addWidget(this->messages_frame);
|
||||
|
||||
this->split_second->addWidget(this->split_third);
|
||||
this->split_second->addWidget(this->errors_present);
|
||||
|
||||
this->split_third->addWidget(this->center_frame->hostWidget());
|
||||
this->split_third->addWidget(this->messages_frame);
|
||||
this->messages_frame->setTabPosition(QTabWidget::TabPosition::South);
|
||||
this->split_first->addWidget(project_present);
|
||||
this->split_first->addWidget(this->split_second);
|
||||
|
||||
project_present->setVisible(true);
|
||||
this->active_docscollect->setPresent(this);
|
||||
setCentralWidget(this->split_first);
|
||||
this->messages_frame->setTabPosition(QTabWidget::TabPosition::South);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() {}
|
||||
|
|
@ -177,12 +175,6 @@ void MainWindow::initial_menubar(QMenuBar *mbar) {
|
|||
auto func = view->addMenu("功能视图");
|
||||
sync_kernel->widgetEnableSync(func, [this]() { return this->project_manager->isOpenning(); });
|
||||
// 项目管理
|
||||
{
|
||||
auto project_v = func->addAction("项目管理", [this](bool v) { XApp::disp_core->postCommand(CompVisible(this, project_present, v)); });
|
||||
sync_kernel->actionCheckSync(project_v, [this]() -> bool { return this->project_present->isVisible(); });
|
||||
}
|
||||
func->addAction("引用统计");
|
||||
func->addAction("脉络分蘖");
|
||||
|
||||
// 工具菜单
|
||||
auto tool = mbar->addMenu("工具");
|
||||
|
|
@ -222,10 +214,8 @@ void MainWindow::initial_commandlist(Schedule::CommandsDispatcher *host) {
|
|||
host->registerCommand(new CloseProject());
|
||||
|
||||
host->registerCommand(new CompVisible(this, welcome_list, true));
|
||||
host->registerCommand(new CompVisible(this, errors_present, true));
|
||||
host->registerCommand(new CompVisible(this, project_present, true));
|
||||
|
||||
host->registerCommand(new NewFile(Route(), "", ""));
|
||||
host->registerCommand(new NewFile(Route(), "", "txt"));
|
||||
host->registerCommand(new NewPackage(""));
|
||||
host->registerCommand(new NewProject(QDir(), ""));
|
||||
host->registerCommand(new OpenFile(Route()));
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
using namespace Components;
|
||||
using namespace Core;
|
||||
using namespace DataModel;
|
||||
using namespace Config;
|
||||
|
||||
DocumentsManager::DocumentsManager(Project::ProjectManager *project) : pjtins(project), present_ui(nullptr) { registViewPlugins(); }
|
||||
|
||||
|
|
@ -31,7 +32,7 @@ void DocumentsManager::createPackage(const Core::Route &link) { pjtins->operateA
|
|||
void DocumentsManager::createFile(const Core::Route &group_path, const QString &name, const QString &suffix) {
|
||||
auto all_types = fileTypes();
|
||||
if (!all_types.contains(suffix))
|
||||
throw new SimpleException("指定文件类型无法打开:" + suffix);
|
||||
throw new SimpleException<QString>("创建文件错误", "指定文件类型无法打开:" + suffix);
|
||||
|
||||
auto midx = convertPath(group_path);
|
||||
auto fidx = projectManager()->operateAccess()->newFile(midx, name, suffix);
|
||||
|
|
@ -83,7 +84,7 @@ void DocumentsManager::openFile(const QList<Route> &doc_paths) {
|
|||
|
||||
auto info = pjtins->queryAccess()->queryInfo(convertPath(it));
|
||||
if (!info.isFile())
|
||||
throw new SimpleException("指向的节点不是文件节点");
|
||||
throw new SimpleException<QString>("打开文件错误", "指向的节点不是文件节点");
|
||||
|
||||
auto view = factory_map[info.suffix()]->newInst(present_ui->hostWidget());
|
||||
doc_openning[it] = view;
|
||||
|
|
@ -120,7 +121,7 @@ QModelIndex DocumentsManager::convertPath(const Core::Route &path) {
|
|||
}
|
||||
|
||||
if (idx == itor_node->parent()->rowCount())
|
||||
throw new SimpleException("指定的path非法:/" + path.links().join("/"));
|
||||
throw new SimpleException<QString>("路径转换错误", "指定的path非法:/" + path.links().join("/"));
|
||||
}
|
||||
return itor_node->index();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,3 @@
|
|||
using namespace Components;
|
||||
|
||||
MessagesPresent::MessagesPresent(QStandardItemModel *base, QWidget *parent) : QTableView(parent), items_present(base) { setModel(items_present); }
|
||||
|
||||
QWidget *MessagesPresent::widget() const { return (QWidget *)this; }
|
||||
|
||||
QString MessagesPresent::name() const { return NAME(MessagesPresent); }
|
||||
|
|
|
|||
|
|
@ -10,18 +10,13 @@ namespace Components {
|
|||
/**
|
||||
* @brief 显示各种提示信息
|
||||
*/
|
||||
class MessagesPresent : public QTableView, public MakeTools::PresentBase {
|
||||
class MessagesPresent : public QTableView {
|
||||
public:
|
||||
MessagesPresent(QStandardItemModel *base, QWidget *parent = nullptr);
|
||||
virtual ~MessagesPresent() = default;
|
||||
|
||||
private:
|
||||
QStandardItemModel *const items_present;
|
||||
|
||||
// PresentBase interface
|
||||
public:
|
||||
virtual QWidget *widget() const override;
|
||||
virtual QString name() const override;
|
||||
};
|
||||
} // namespace Components
|
||||
|
||||
|
|
|
|||
|
|
@ -13,8 +13,9 @@ using namespace DataModel;
|
|||
ProjectPresent::ProjectPresent(CommandsDispatcher *core, DocumentsManager *mgr, QWidget *parent)
|
||||
: QWidget(parent), source(core), view_present(new QTreeView(this)) {
|
||||
auto layout = new QVBoxLayout(this);
|
||||
|
||||
layout->addWidget(view_present);
|
||||
layout->setMargin(1);
|
||||
|
||||
view_present->setModel(mgr->projectManager()->model());
|
||||
view_present->setHeaderHidden(true);
|
||||
|
||||
|
|
@ -27,13 +28,6 @@ ProjectPresent::ProjectPresent(CommandsDispatcher *core, DocumentsManager *mgr,
|
|||
|
||||
QModelIndex ProjectPresent::currentIndex() const { return view_present->currentIndex(); }
|
||||
|
||||
QString ProjectPresent::name() const
|
||||
{
|
||||
return NAME(ProjectPresent);
|
||||
}
|
||||
|
||||
QWidget *ProjectPresent::widget() const { return (QWidget *)this; }
|
||||
|
||||
void ProjectPresent::menu_popup(const QPoint &p)
|
||||
{
|
||||
QMenu m;
|
||||
|
|
@ -51,7 +45,7 @@ void ProjectPresent::menu_popup(const QPoint &p)
|
|||
auto menu = m.addMenu("新建文件");
|
||||
auto views = mgr->fileTypes();
|
||||
for (auto &it : views) {
|
||||
menu->addAction(it, [this, &it, &index, mgr]() {
|
||||
menu->addAction(it, [this, it, &index, mgr]() {
|
||||
auto name = QInputDialog::getText(this, "输入文件名称", "文件名称");
|
||||
auto path = mgr->convertPath(index);
|
||||
source->postCommand(NewFile(path, name, it));
|
||||
|
|
|
|||
|
|
@ -13,18 +13,13 @@ namespace Components {
|
|||
/**
|
||||
* @brief 项目视图
|
||||
*/
|
||||
class ProjectPresent : public QWidget, public MakeTools::PresentBase {
|
||||
class ProjectPresent : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ProjectPresent(Schedule::CommandsDispatcher *core, DataModel::DocumentsManager *mgr, QWidget *parent = nullptr);
|
||||
|
||||
QModelIndex currentIndex() const;
|
||||
|
||||
// PresentBase interface
|
||||
public:
|
||||
virtual QWidget *widget() const override;
|
||||
virtual QString name() const override;
|
||||
|
||||
private:
|
||||
Schedule::CommandsDispatcher *const source;
|
||||
QTreeView *const view_present;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
using namespace Components;
|
||||
using namespace Enhancement;
|
||||
using namespace Core;
|
||||
using namespace Config;
|
||||
|
||||
class Impl_EditError2 : public MakeTools::EditException {
|
||||
public:
|
||||
|
|
@ -63,14 +64,14 @@ QString StorySourceEdit::name() const
|
|||
void StorySourceEdit::load(const QFileInfo &target_file)
|
||||
{
|
||||
if(!target_file.exists())
|
||||
throw new SimpleException("参数错误:传入的文件不存在");
|
||||
throw new SimpleException<QString>("参数错误", "传入的文件不存在:" + target_file.absoluteFilePath());
|
||||
if(!target_file.isFile())
|
||||
throw new SimpleException("参数错误:传入参数非文件类型");
|
||||
throw new SimpleException<QString>("参数错误", "传入参数非文件类型:" + target_file.absoluteFilePath());
|
||||
|
||||
filepath_store = target_file.absoluteFilePath();
|
||||
filepath_store = target_file.canonicalFilePath();
|
||||
QFile bin(filepath_store);
|
||||
if(!bin.open(QIODevice::ReadOnly|QIODevice::Text))
|
||||
throw new SimpleException("参数错误:指定的文件无法打开");
|
||||
throw new SimpleException<QString>("参数错误", "指定的文件无法打开:" + target_file.absoluteFilePath());
|
||||
|
||||
QTextStream tin(&bin);
|
||||
tin.setCodec("UTF-8");
|
||||
|
|
@ -84,7 +85,7 @@ void StorySourceEdit::saveAs(const QString &path)
|
|||
|
||||
QFile bout(filepath_store);
|
||||
if(!bout.open(QIODevice::WriteOnly|QIODevice::Text))
|
||||
throw new SimpleException("参数错误:指定的文件无法打开");
|
||||
throw new SimpleException<QString>("保存文件参数错误", "指定的文件无法打开:" + path);
|
||||
|
||||
QTextStream tout(&bout);
|
||||
tout.setCodec("UTF-8");
|
||||
|
|
|
|||
|
|
@ -17,6 +17,30 @@ namespace Config {
|
|||
virtual QString title() const = 0;
|
||||
};
|
||||
|
||||
template <class T> class SimpleException : public ParseException {
|
||||
public:
|
||||
SimpleException(const QString &title, const QString &reason) : ts(title), rs(reason) {
|
||||
this->buffer = QString("%1:%2").arg(title, reason).toLocal8Bit();
|
||||
}
|
||||
|
||||
T datas() const { return datas_store; }
|
||||
void setDatas(T val) { this->datas_store = val; }
|
||||
|
||||
// exception interface
|
||||
public:
|
||||
virtual const char *what() const override { return this->buffer; }
|
||||
|
||||
// ParseException interface
|
||||
public:
|
||||
virtual QString reason() const override { return rs; }
|
||||
virtual QString title() const override { return ts; }
|
||||
|
||||
private:
|
||||
T datas_store;
|
||||
QString ts, rs;
|
||||
QByteArray buffer;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 配置读写交互端口
|
||||
*/
|
||||
|
|
@ -27,7 +51,7 @@ namespace Config {
|
|||
virtual ~Configration() = default;
|
||||
|
||||
/**
|
||||
* @brief 载入配置文件
|
||||
* @brief 载入配置文件,如果文件不存在,则生成新文件
|
||||
* @param path 指定配置文件路径
|
||||
* @throw ParseException* 配置文件解析异常
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,18 +1,62 @@
|
|||
#include <QCoreApplication>
|
||||
#include "unnnn.h"
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QDomDocument>
|
||||
#include <QHBoxLayout>
|
||||
#include <QMainWindow>
|
||||
#include <QMenuBar>
|
||||
#include <QPushButton>
|
||||
#include <QStyle>
|
||||
#include <QToolBar>
|
||||
#include <splitview.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication a(argc, argv);
|
||||
using namespace SplitFrame;
|
||||
|
||||
QString value = "row:23212,col:5234";
|
||||
QRegExp exp("(\\d+)");
|
||||
auto offset = exp.indexIn(value);
|
||||
qDebug() << exp.cap(1);
|
||||
int main(int argc, char *argv[]) {
|
||||
QApplication a(argc, argv);
|
||||
|
||||
exp.indexIn(value, offset + exp.cap(1).length());
|
||||
qDebug() << exp.cap(1);
|
||||
// auto z = new QWidget();
|
||||
|
||||
// auto v = new XWidget();
|
||||
// v->setParent(z);
|
||||
// v->setGeometry(0, 50, 200, 100);
|
||||
|
||||
// z->show();
|
||||
|
||||
auto win = new QMainWindow();
|
||||
win->setMinimumSize(800, 600);
|
||||
win->menuBar()->addMenu("文件");
|
||||
auto tbar = new QToolBar();
|
||||
win->addToolBar(Qt::ToolBarArea::LeftToolBarArea, tbar);
|
||||
tbar->addAction("添加");
|
||||
|
||||
auto aview = new BaseView("hello", new QWidget);
|
||||
auto bview = new BaseView("world", new QWidget);
|
||||
auto cview = new BaseView("everyone", new QWidget);
|
||||
|
||||
auto conv0 = new SplitView(aview, bview);
|
||||
conv0->setSplitInfo(SplitType::SPLIT_V, 100, 8, true);
|
||||
auto conv = new ViewPresent(conv0);
|
||||
win->setCentralWidget(conv);
|
||||
conv->append(cview, 0);
|
||||
|
||||
aview->installEventFilter(conv);
|
||||
bview->installEventFilter(conv);
|
||||
cview->installEventFilter(conv);
|
||||
|
||||
win->show();
|
||||
|
||||
// auto w = new QWidget();
|
||||
// QLabel w0, w1;
|
||||
// w0.setPixmap(a.style()->standardIcon(QStyle::StandardPixmap::SP_ArrowUp).pixmap(QSize(20, 20)));
|
||||
// w1.setText("hello");
|
||||
// auto v = new QHBoxLayout(w);
|
||||
// v->setMargin(0);
|
||||
// v->setSpacing(1);
|
||||
// v->addWidget(&w0, 0);
|
||||
// v->addWidget(&w1, 1);
|
||||
// w->show();
|
||||
|
||||
return a.exec();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
QT -= gui
|
||||
QT += gui
|
||||
|
||||
QT += xml
|
||||
QT += xml widgets
|
||||
|
||||
CONFIG += c++11 console
|
||||
CONFIG -= app_bundle
|
||||
|
|
@ -10,9 +10,27 @@ CONFIG -= app_bundle
|
|||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
SOURCES += \
|
||||
main.cpp
|
||||
main.cpp \
|
||||
unnnn.cpp
|
||||
|
||||
# Default rules for deployment.
|
||||
qnx: target.path = /tmp/$${TARGET}/bin
|
||||
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||
!isEmpty(target.path): INSTALLS += target
|
||||
|
||||
HEADERS += \
|
||||
unnnn.h
|
||||
|
||||
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../SplitView/release/ -lSplitView
|
||||
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../SplitView/debug/ -lSplitView
|
||||
else:unix: LIBS += -L$$OUT_PWD/../SplitView/ -lSplitView
|
||||
|
||||
INCLUDEPATH += $$PWD/../SplitView
|
||||
DEPENDPATH += $$PWD/../SplitView
|
||||
|
||||
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../GenericConsole/release/ -lGenericConsole
|
||||
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../GenericConsole/debug/ -lGenericConsole
|
||||
else:unix: LIBS += -L$$OUT_PWD/../GenericConsole/ -lGenericConsole
|
||||
|
||||
INCLUDEPATH += $$PWD/../GenericConsole
|
||||
DEPENDPATH += $$PWD/../GenericConsole
|
||||
|
|
|
|||
|
|
@ -1,3 +1,10 @@
|
|||
#include "unnnn.h"
|
||||
|
||||
QString EditView::t = "txt";
|
||||
#include <QPainter>
|
||||
|
||||
XWidget::XWidget(QWidget *parent) : QWidget(parent) {}
|
||||
|
||||
void XWidget::paintEvent(QPaintEvent *ev) {
|
||||
QPainter p(this);
|
||||
p.fillRect(this->rect(), Qt::red);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,15 +2,12 @@
|
|||
#define UNNNN_H
|
||||
|
||||
#include <QString>
|
||||
#include <QWidget>
|
||||
|
||||
template <class TargetType> class TypeDefine {
|
||||
class XWidget : public QWidget {
|
||||
public:
|
||||
static QString suffix() { return TargetType::t; }
|
||||
};
|
||||
|
||||
class EditView : public TypeDefine<EditView> {
|
||||
public:
|
||||
static QString t;
|
||||
XWidget(QWidget *parent = nullptr);
|
||||
virtual void paintEvent(QPaintEvent *ev);
|
||||
};
|
||||
|
||||
#endif // UNNNN_H
|
||||
|
|
|
|||
Loading…
Reference in New Issue