diff --git a/QtNovelDesc.pro b/QtNovelDesc.pro index ecb9006..40a1feb 100644 --- a/QtNovelDesc.pro +++ b/QtNovelDesc.pro @@ -3,7 +3,7 @@ TEMPLATE = subdirs SUBDIRS += \ libGenericConsole \ libSplitView \ - WordsIDE \ + # WordsIDE \ libConfig \ libProjectManager \ # libTextEdit \ diff --git a/QtNovelDesc.pro.user b/QtNovelDesc.pro.user index b77e475..672200a 100644 --- a/QtNovelDesc.pro.user +++ b/QtNovelDesc.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -94,16 +94,16 @@ ProjectExplorer.Project.Target.0 Desktop - Desktop Qt 5.12.11 MinGW 64-bit - Desktop Qt 5.12.11 MinGW 64-bit - qt.qt5.51211.win64_mingw73_kit + Desktop Qt 5.12.11 MSVC2017 64bit + Desktop Qt 5.12.11 MSVC2017 64bit + qt.qt5.51211.win64_msvc2017_64_kit 0 0 - 1 + 0 0 - D:\Projects\Cpp\build-QtNovelDesc-Desktop_Qt_5_12_11_MinGW_64_bit-Debug - D:/Projects/Cpp/build-QtNovelDesc-Desktop_Qt_5_12_11_MinGW_64_bit-Debug + D:\Projects\Cpp\build-QtNovelDesc-Desktop_Qt_5_12_11_MSVC2017_64bit-Debug + D:/Projects/Cpp/build-QtNovelDesc-Desktop_Qt_5_12_11_MSVC2017_64bit-Debug true @@ -140,8 +140,8 @@ 2 - D:\Projects\Cpp\build-QtNovelDesc-Desktop_Qt_5_12_11_MinGW_64_bit-Release - D:/Projects/Cpp/build-QtNovelDesc-Desktop_Qt_5_12_11_MinGW_64_bit-Release + D:\Projects\Cpp\build-QtNovelDesc-Desktop_Qt_5_12_11_MSVC2017_64bit-Release + D:/Projects/Cpp/build-QtNovelDesc-Desktop_Qt_5_12_11_MSVC2017_64bit-Release true @@ -180,8 +180,8 @@ 0 - D:\Projects\Cpp\build-QtNovelDesc-Desktop_Qt_5_12_11_MinGW_64_bit-Profile - D:/Projects/Cpp/build-QtNovelDesc-Desktop_Qt_5_12_11_MinGW_64_bit-Profile + D:\Projects\Cpp\build-QtNovelDesc-Desktop_Qt_5_12_11_MSVC2017_64bit-Profile + D:/Projects/Cpp/build-QtNovelDesc-Desktop_Qt_5_12_11_MSVC2017_64bit-Profile true @@ -304,82 +304,9 @@ true false true - D:/Projects/Cpp/build-QtNovelDesc-Desktop_Qt_5_12_11_MinGW_64_bit-Debug/u_test + D:/Projects/Cpp/build-QtNovelDesc-Desktop_Qt_5_12_11_MSVC2017_64bit-Debug/u_test - - dwarf - - cpu-cycles - - - 250 - - -e - cpu-cycles - --call-graph - dwarf,4096 - -F - 250 - - -F - true - 4096 - false - false - 1000 - - true - - - false - false - false - false - true - 0.01 - 10 - true - kcachegrind - 1 - - 25 - - 1 - true - false - true - - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - - - 2 - - Qt4ProjectManager.Qt4RunConfiguration:D:/Projects/Cpp/QtNovelDesc/WordsIDE/WordsIDE.pro - D:/Projects/Cpp/QtNovelDesc/WordsIDE/WordsIDE.pro - false - true - true - false - true - D:/Projects/Cpp/build-QtNovelDesc-Desktop_Qt_5_12_11_MinGW_64_bit-Debug/WordsIDE - - 2 + 1 diff --git a/libSplitView/acceptpanel.cpp b/libSplitView/acceptpanel.cpp new file mode 100644 index 0000000..dd53e71 --- /dev/null +++ b/libSplitView/acceptpanel.cpp @@ -0,0 +1,153 @@ +#include "acceptpanel.h" + +#include +#include + + +using namespace split_frame; + +accept_panel::AcceptPanel::AcceptPanel(QMainWindow *win, split_frame::ResManager *mgr) + : QWidget(nullptr), bind_win(win), view_manager(mgr) { + this->setMouseTracking(true); + this->setAcceptDrops(true); +} + +void accept_panel::AcceptPanel::bindWith(split_frame::ViewBase *target) +{ + this->setParent(target->widget()); + this->anchor_view = target; + this->paint_panel = this->anchor_view->widget()->grab(); + this->setGeometry(QRect(QPoint(), target->widget()->size())); +} + +void accept_panel::AcceptPanel::resizeEvent(QResizeEvent *ev) +{ + QWidget::resizeEvent(ev); + + auto render_width = this->width() / 3; + auto render_height = this->height() / 3; + this->cube_center = QRectF(render_width, render_height, render_width, render_height) - QMargins(15, 15, 15, 15); + this->cube_left = QRectF(0, render_height, render_width, render_height) - QMargins(15, 15, 15, 15); + this->cube_right = QRectF(this->width() - render_width, render_height, render_width, render_height) - QMargins(15, 15, 15, 15); + this->cube_top = QRectF(render_width, 0, render_width, render_height) - QMargins(15, 15, 15, 15); + this->cube_bottom = QRectF(render_width, this->height() - render_height, render_width, render_height) - QMargins(15, 15, 15, 15); + + this->target_type = HoverType::CUBE_UNDEFINED; +} + +void accept_panel::AcceptPanel::paintEvent(QPaintEvent *ev) +{ + QWidget::paintEvent(ev); + + QPainter t(this); + t.fillRect(this->rect(), this->paint_panel); + + + switch(this->target_type){ + case HoverType::CUBE_LEFT: + t.fillRect(this->cube_left + QMargins(15, 15, 15, 15), Qt::gray); + break; + case HoverType::CUBE_RIGHT: + t.fillRect(this->cube_right + QMargins(15, 15, 15, 15), Qt::gray); + break; + case HoverType::CUBE_TOP: + t.fillRect(this->cube_top+ QMargins(15, 15, 15, 15), Qt::gray); + break; + case HoverType::CUBE_BOTTOM: + t.fillRect(this->cube_bottom + QMargins(15, 15, 15, 15), Qt::gray); + break; + case HoverType::CUBE_CENTER: + t.fillRect(this->cube_center + QMargins(15, 15, 15, 15), Qt::gray); + break; + default: + break; + } + + t.fillRect(this->cube_left, Qt::green); + t.fillRect(this->cube_right, Qt::green); + t.fillRect(this->cube_top, Qt::green); + t.fillRect(this->cube_bottom, Qt::green); + t.fillRect(this->cube_center, Qt::green); +} + +void accept_panel::AcceptPanel::dragMoveEvent(QDragMoveEvent *ev) +{ + QWidget::dragMoveEvent(ev); + + if(this->cube_left.contains(ev->pos())) + this->target_type = HoverType::CUBE_LEFT; + else if(this->cube_right.contains(ev->pos())) + this->target_type = HoverType::CUBE_RIGHT; + else if(this->cube_top.contains(ev->pos())) + this->target_type = HoverType::CUBE_TOP; + else if(this->cube_bottom.contains(ev->pos())) + this->target_type = HoverType::CUBE_BOTTOM; + else if(this->cube_center.contains(ev->pos())) + this->target_type = HoverType::CUBE_CENTER; + else + this->target_type = HoverType::CUBE_UNDEFINED; + + this->update(); +} + +void accept_panel::AcceptPanel::dragEnterEvent(QDragEnterEvent *ev) +{ + QWidget::dragEnterEvent(ev); + + if(view_manager->adjustView()) + ev->acceptProposedAction(); +} + +#include "splitpanel.h" +#include +void accept_panel::AcceptPanel::dropEvent(QDropEvent *ev) +{ + auto view = view_manager->adjustView(); + if(view){ + switch (target_type) { + case HoverType::CUBE_LEFT: + view_manager->doRetrieve(view); + view_manager->siblingAttach(view, anchor_view, SplitType::SPLIT_H_LFIRST); + break; + case HoverType::CUBE_RIGHT: + view_manager->doRetrieve(view); + view_manager->siblingAttach(view, anchor_view, SplitType::SPLIT_H_RFIRST); + break; + case HoverType::CUBE_TOP: + view_manager->doRetrieve(view); + view_manager->siblingAttach(view, anchor_view, SplitType::SPLIT_V_TFIRST); + break; + case HoverType::CUBE_BOTTOM: + view_manager->doRetrieve(view); + view_manager->siblingAttach(view, anchor_view, SplitType::SPLIT_V_BFIRST); + break; + case HoverType::CUBE_CENTER: + view_manager->doRetrieve(view); + anchor_view->parentRes()->replaceView(view, anchor_view); + view_manager->doRetrieve(anchor_view); + break; + default: + break; + } + view_manager->setAdjustView(); + target_type = HoverType::CUBE_UNDEFINED; + } + + this->setParent(bind_win); +} + + + + + + + + + + + + + + + + diff --git a/libSplitView/acceptpanel.h b/libSplitView/acceptpanel.h new file mode 100644 index 0000000..f4bdb12 --- /dev/null +++ b/libSplitView/acceptpanel.h @@ -0,0 +1,40 @@ +#ifndef ACCEPTPANEL_H +#define ACCEPTPANEL_H + +#include +#include +#include "splitview_interface.h" + +namespace accept_panel { + enum class HoverType{ + CUBE_LEFT, CUBE_RIGHT, CUBE_TOP, CUBE_BOTTOM, CUBE_CENTER, CUBE_UNDEFINED, + }; + + class AcceptPanel : public QWidget + { + Q_OBJECT + public: + AcceptPanel(QMainWindow* win, split_frame::ResManager *mgr); + + void bindWith(split_frame::ViewBase *target); + + protected: + void resizeEvent(QResizeEvent *ev) override; + void paintEvent(QPaintEvent *ev) override; + void dragMoveEvent(QDragMoveEvent *ev) override; + void dragEnterEvent(QDragEnterEvent *ev) override; + void dropEvent(QDropEvent *ev) override; + + private: + QWidget *const bind_win; + QRectF cube_left, cube_right, cube_top, cube_bottom, cube_center; + split_frame::ResManager *const view_manager; + split_frame::ViewBase *anchor_view = nullptr; + HoverType target_type = HoverType::CUBE_UNDEFINED; + QPixmap paint_panel; + + }; +} + + +#endif // ACCEPTPANEL_H diff --git a/libSplitView/dockpanel.cpp b/libSplitView/dockpanel.cpp index 4871a23..7856014 100644 --- a/libSplitView/dockpanel.cpp +++ b/libSplitView/dockpanel.cpp @@ -8,7 +8,7 @@ #include #include -using namespace base_view; +using namespace dock_panel; DragHeader::DragHeader(const QString &title, DockableView *bind_core) : QFrame(bind_core), @@ -91,7 +91,7 @@ DockableView::DockableView(split_frame::ResManager *mgr, QWidget *present, bool auto layout = new QVBoxLayout(this); layout->addWidget(title_header); - if(present_cube){\ + if(present_cube){ layout->addWidget(present); } else { @@ -106,10 +106,9 @@ DockableView::DockableView(split_frame::ResManager *mgr, QWidget *present, bool this->title_header->setFrameShadow(QFrame::Shadow::Raised); this->title_header->setLineWidth(3); - this->manager_inst->appendPresentView(this); - connect(this, &QObject::destroyed, [this](){ - this->manager_inst->removePresentView(this); - }); + connect(this->title_header, &DragHeader::retrieveRequest, this, &DockableView::retrieveAccept); + connect(this->title_header, &DragHeader::closeRequest, this, &DockableView::closeAccept); + connect(this->title_header, &DragHeader::adjustRequest, this, &DockableView::adjustAccept); } void DockableView::viewConfig(bool replace, bool close, bool retrieve) @@ -134,10 +133,10 @@ void DockableView::adjustAccept(const QPoint &pos) { Q_UNUSED(pos); + manager_inst->setAdjustView(this); + auto drag_trans = new QDrag(this); - auto mime_date = new QMimeData(); - mime_date->setText(QString("view-drags(view-id:%1)").arg(this->hashCode())); - drag_trans->setMimeData(mime_date); + drag_trans->setMimeData(new QMimeData); drag_trans->setPixmap(this->grab(this->rect())); drag_trans->setHotSpot(QPoint(5,5)); drag_trans->exec(); @@ -153,6 +152,18 @@ void DockableView::retrieveAccept() this->manager_inst->doRetrieve(this); } +void DockableView::showEvent(QShowEvent *ev) +{ + QWidget::showEvent(ev); + manager_inst->appendPresentView(this); +} + +void DockableView::hideEvent(QHideEvent *ev) +{ + QWidget::hideEvent(ev); + manager_inst->removePresentView(this); +} + split_frame::ResManager *DockableView::splitManager() const { return this->manager_inst; @@ -166,6 +177,12 @@ split_frame::SplitView *DockableView::parentRes() const void DockableView::setParentRes(split_frame::SplitView *inst) { this->parent_res = inst; + if(inst){ + this->setParent(inst->widget()); + } + else{ + this->setParent(nullptr); + } } QWidget *DockableView::widget() const @@ -193,6 +210,16 @@ qulonglong DockableView::hashCode() const return (qulonglong)this; } +void DockableView::setVisible(bool state) +{ + QWidget::setVisible(state); +} + +bool DockableView::isVisible() const +{ + return QWidget::isVisible(); +} + QIcon DockableView::icon() const { return icon_store; @@ -210,12 +237,12 @@ QSizeF DockableView::stiffSize() const return sizex; } -QSizeF DockableView::viewSize() const +QRectF DockableView::outlineRect() const { - return this->size(); + return this->rect(); } -void DockableView::resizeView(const QSizeF &outline) +void DockableView::setOutline(const QRectF &rect) { - this->resize(outline.toSize()); + this->setGeometry(rect.toRect()); } diff --git a/libSplitView/dockpanel.h b/libSplitView/dockpanel.h index 6e227a5..37f14ef 100644 --- a/libSplitView/dockpanel.h +++ b/libSplitView/dockpanel.h @@ -8,7 +8,7 @@ #include #include -namespace base_view { +namespace dock_panel { class DockableView; /** @@ -54,7 +54,7 @@ namespace base_view { /** * @brief 基础内容视图组件 */ - class SPLITVIEW_EXPORT DockableView : public QWidget, public split_frame::ViewBase, public split_frame::ViewRes { + class SPLITVIEW_EXPORT DockableView : public QWidget, public split_frame::ViewBase { public: /** * @brief 构建新的呈现视图实例 @@ -77,11 +77,15 @@ namespace base_view { void setTitle(const QString &title); void setTitle(const QIcon &icon, const QString &title); - public slots: + void adjustAccept(const QPoint &pos); void closeAccept(); void retrieveAccept(); + protected: + void showEvent(QShowEvent *ev) override; + void hideEvent(QHideEvent *ev) override; + private: DragHeader *const title_header; QWidget *const present_cube; @@ -96,18 +100,21 @@ namespace base_view { virtual split_frame::SplitView *parentRes() const override; virtual void setParentRes(split_frame::SplitView *inst) override; virtual QWidget *widget() const override; - virtual bool canRetrieve() const override; - virtual bool canClose() const override; - virtual bool canReplace() const override; + virtual QSizeF stiffSize() const override; + virtual QRectF outlineRect() const override; + virtual void setOutline(const QRectF &rect) override; virtual qulonglong hashCode() const override; + virtual void setVisible(bool state) override; + virtual bool isVisible() const override; // ViewBase interface public: virtual QIcon icon() const override; virtual QString title() const override; - virtual QSizeF stiffSize() const override; - virtual QSizeF viewSize() const override; - virtual void resizeView(const QSizeF &outline) override; + virtual bool canRetrieve() const override; + virtual bool canClose() const override; + virtual bool canReplace() const override; + }; } diff --git a/libSplitView/libSplitView.pro b/libSplitView/libSplitView.pro index 5c9975c..bafa2c5 100644 --- a/libSplitView/libSplitView.pro +++ b/libSplitView/libSplitView.pro @@ -15,11 +15,13 @@ msvc{ } SOURCES += \ + acceptpanel.cpp \ dockpanel.cpp \ splitpanel.cpp \ splitwindow.cpp HEADERS += \ + acceptpanel.h \ dockpanel.h \ splitpanel.h \ splitview_interface.h \ diff --git a/libSplitView/splitpanel.cpp b/libSplitView/splitpanel.cpp index a0546d8..579a631 100644 --- a/libSplitView/splitpanel.cpp +++ b/libSplitView/splitpanel.cpp @@ -13,7 +13,8 @@ DragSplitter::DragSplitter(split_frame::SplitType split, split_frame::ViewRes *p this->setFrameShadow(QFrame::Shadow::Raised); switch (split) { - case split_frame::SplitType::SPLIT_H: + case split_frame::SplitType::SPLIT_H_LFIRST: + case split_frame::SplitType::SPLIT_H_RFIRST: this->setCursor(Qt::CursorShape::SplitHCursor); break; default: @@ -29,147 +30,192 @@ void DragSplitter::mouseMoveEvent(QMouseEvent *event) //===================================================== -SplitPanel::SplitPanel(ResManager *mgr, ViewBase *a, ViewBase *b, SplitType split, ViewRes *parent) - : QWidget(parent->widget()), parent_inst(parent) +SplitPanel::SplitPanel(ResManager *mgr, SplitType split) + : QWidget(nullptr), + manager_inst(mgr), + parent_inst(nullptr), + splitter_inst(new DragSplitter(split, this)) { - this->split_member = std::make_tuple(a, b); - this->split_info_value = std::make_tuple(SplitType::SPLIT_H, 0.5, 8); + connect(this->splitter_inst, &DragSplitter::adjustRequest, this, &SplitPanel::splitter_adjust); + this->split_info = std::make_tuple(split, 0.5, 8); } -SplitPanel::~SplitPanel() -{ +#include +SplitPanel::~SplitPanel() { } -ResManager *SplitPanel::splitManager() const { return this->parent_inst->splitManager(); } - -SplitView *SplitPanel::parentRes() const +void SplitPanel::resizeEvent(QResizeEvent *e) { - return parent_inst; + QWidget::resizeEvent(e); + this->sync_status(); } -bool SplitPanel::canRetrieve() const -{ - return true; -} +ResManager *SplitPanel::splitManager() const { return this->manager_inst; } -bool SplitPanel::canClose() const -{ - return true; -} +SplitView *SplitPanel::parentRes() const { return parent_inst; } -bool SplitPanel::canReplace() const -{ - return true; -} - -qulonglong SplitPanel::hashCode() const -{ - return (qulonglong)this; -} - -QIcon SplitPanel::icon() const -{ - return QIcon(); -} - -QString SplitPanel::title() const -{ - return QString("split-view:%1").arg((int64_t)this); -} - -QWidget *SplitPanel::widget() const -{ - return const_cast(this); -} - -QSizeF SplitPanel::viewSize() const -{ - return this->size(); -} - -void SplitPanel::resizeView(const QSizeF &outline) -{ - if(outline != this->size()){ - this->resize(outline.toSize()); - } - - - auto tuple_values = this->child(); - - if(view_list().size() == 1){ - view_list().first()->resizeView(this->viewSize()); +void SplitPanel::setParentRes(SplitView *inst) { + this->parent_inst = inst; + if(inst){ + this->setParent(inst->widget()); } else{ - switch (std::get<2>(tuple_values)) { - case SplitType::SPLIT_H: { - auto width_value = QWidget::width() * this->splitterPos(); - std::get<0>(tuple_values)->widget()->setGeometry(0, 0, width_value, QWidget::height()); - - auto second_pos = width_value + splitterWidth(); - auto second_width = QWidget::width() - second_pos; - std::get<1>(tuple_values)->widget()->setGeometry(second_pos, 0, second_width, QWidget::height()); - } break; - case SplitType::SPLIT_V: { - auto height_value = QWidget::height() * this->splitterPos(); - std::get<0>(tuple_values)->widget()->setGeometry(0, 0, QWidget::width(), height_value); - - auto second_pos = height_value + splitterWidth(); - auto second_height = QWidget::height() - second_pos; - std::get<1>(tuple_values)->widget()->setGeometry(0, second_pos, QWidget::width(), second_height); - } break; - } + this->setParent(nullptr); } } -std::tuple SplitPanel::child() const +qulonglong SplitPanel::hashCode() const { return (qulonglong)this; } + +void SplitPanel::setVisible(bool state) { - return std::make_tuple(std::get<0>(split_member), std::get<1>(split_member), std::get<0>(split_info_value)); + QWidget::setVisible(state); } -void SplitPanel::replaceComp(ViewBase *view, ViewBase *old) +bool SplitPanel::isVisible() const { - QList mbrs = view_list(); + return QWidget::isVisible(); +} - if(!mbrs.contains(view) && mbrs.contains(old)){ - if(std::get<1>(split_member) == old){ - this->split_member = std::make_tuple(std::get<0>(split_member), view); - } - else if(std::get<0>(split_member) == old){ - this->split_member = std::make_tuple(view, std::get<1>(split_member)); - } +void SplitPanel::initViews(ViewRes *a, ViewRes *b) +{ + this->split_member = std::make_pair(a, b); - view->setParentRes(this); - view->widget()->setParent(this); - old->widget()->setParent(nullptr); - this->resizeView(this->viewSize()); + a->setParentRes(this); + b->setParentRes(this); +} + +QWidget *SplitPanel::widget() const { return const_cast(this); } + +QSizeF SplitPanel::stiffSize() const +{ + auto size_a = split_member.first->stiffSize(); + auto size_b = split_member.second->stiffSize(); + + switch (this->splitType()) { + case SplitType::SPLIT_H_LFIRST: + case SplitType::SPLIT_H_RFIRST: + return QSizeF(size_a.width() + size_b.width() + std::get<2>(split_info), std::max(size_a.height(), size_b.height())); + default: + return QSizeF(std::max(size_a.width(), size_b.width()), size_a.height() + size_b.height() + std::get<2>(split_info)); } } +QRectF SplitPanel::outlineRect() const { return this->rect(); } + +void SplitPanel::setOutline(const QRectF &outline) +{ + if(outline != this->outlineRect()){ + this->setGeometry(outline.toRect()); + this->sync_status(); + } +} + +std::pair SplitPanel::except(ViewRes *inst) const +{ + if(!contains(inst)) + throw new SimpleException("运行异常", "传入的视图实例不属于本组件"); + + if(split_member.first == inst) + return std::make_pair(split_member.second, 1); + return std::make_pair(split_member.first, 0); +} + +bool SplitPanel::contains(ViewRes *inst) const +{ + return split_member.first == inst || split_member.second == inst; +} + +void SplitPanel::replaceView(ViewRes *_new, ViewRes *_old) +{ + if(!contains(_old)){ + throw new SimpleException("运行异常", "指定替换的视图不属于本组件"); + } + + _new->setParentRes(this); + auto elsev = except(_old); + switch (std::get<1>(elsev)) { + case 0: + this->split_member = std::make_pair(elsev.first, _new); + break; + default: + this->split_member = std::make_pair(_new, elsev.first); + } + + sync_status(); + this->update(); +} + float SplitPanel::splitterWidth() const { - return std::get<1>(split_info_value); + return std::get<2>(split_info); } float SplitPanel::splitterPos() const { - return std::get<1>(split_info_value); + return std::get<1>(split_info); } -void SplitPanel::setSplitInfo(split_frame::SplitType type, float pos, float width) +SplitType SplitPanel::splitType() const { - this->split_info_value = std::make_tuple(type, pos, width); + return std::get<0>(split_info); } - -QList SplitPanel::view_list() const +void SplitPanel::setSplitInfo(float pos, float width) { - QList items; - - if(std::get<0>(split_member)) - items << std::get<0>(split_member); - if(std::get<1>(split_member)) - items << std::get<1>(split_member); - - return items; + this->split_info = std::make_tuple(std::get<0>(split_info), pos, width); + this->sync_status(); + this->update(); +} + + +void SplitPanel::sync_status() +{ + auto total_w = this->width(); + auto total_h = this->height(); + switch (std::get<0>(split_info)) { + case SplitType::SPLIT_H_LFIRST: + case SplitType::SPLIT_H_RFIRST: { + auto width_a = total_w * std::get<1>(split_info); + auto width_b = total_w - width_a - std::get<2>(split_info); + + this->split_member.first->setOutline(QRectF(0, 0, width_a, total_h)); + this->split_member.second->setOutline(QRectF(width_a + std::get<2>(split_info), 0, width_b, total_h)); + this->splitter_inst->setGeometry(QRect(width_a, 0, std::get<2>(split_info), total_h)); + } break; + case SplitType::SPLIT_V_BFIRST: + case SplitType::SPLIT_V_TFIRST: { + auto height_a = total_h * std::get<1>(split_info); + auto height_b = total_h - height_a - std::get<2>(split_info); + + split_member.first->setOutline(QRectF(0, 0, total_w, height_a)); + split_member.second->setOutline(QRectF(0, height_a + std::get<2>(split_info) - 1, total_w, height_b + 1)); + splitter_inst->setGeometry(QRect(0, height_a, total_w, std::get<2>(split_info))); + } break; + } + + split_member.first->setVisible(true); + split_member.second->setVisible(true); +} + +void SplitPanel::splitter_adjust(const QPoint &pos) +{ + switch (std::get<0>(split_info)) { + case SplitType::SPLIT_H_LFIRST: + case SplitType::SPLIT_H_RFIRST:{ + auto lwidth = split_member.first->stiffSize().width(); + auto rwidth = split_member.second->stiffSize().width(); + if(pos.x() >= lwidth && pos.x() <= this->width() - rwidth - std::get<2>(split_info)) + this->split_info = std::make_tuple(std::get<0>(split_info), pos.x()/(float)this->width(), std::get<2>(split_info)); + }break; + case SplitType::SPLIT_V_BFIRST: + case SplitType::SPLIT_V_TFIRST:{ + auto theight = split_member.first->stiffSize().height(); + auto bheight = split_member.second->stiffSize().height(); + if(pos.y() >= theight && pos.y() <= this->height() - bheight - std::get<2>(split_info)) + this->split_info = std::make_tuple(std::get<0>(split_info), pos.y()/this->height(), std::get<2>(split_info)); + }break; + } + + this->sync_status(); } diff --git a/libSplitView/splitpanel.h b/libSplitView/splitpanel.h index 4adfbc8..000c4fe 100644 --- a/libSplitView/splitpanel.h +++ b/libSplitView/splitpanel.h @@ -6,11 +6,13 @@ #include namespace split_panel { - - class DragSplitter : public QFrame{ + /** + * @brief 分割边栏 + */ + class SPLITVIEW_EXPORT DragSplitter : public QFrame{ Q_OBJECT signals: - void adjustRequest(QPoint); + void adjustRequest(const QPoint&); public: DragSplitter(split_frame::SplitType split, split_frame::ViewRes *parent); @@ -23,56 +25,54 @@ namespace split_panel { /** * @brief 分割视图 */ - class SPLITVIEW_EXPORT SplitPanel : - public QWidget, - public split_frame::SplitView, - public split_frame::ViewBase, - public split_frame::ViewRes + class SPLITVIEW_EXPORT SplitPanel : public QWidget, public split_frame::SplitView { typedef float split_pos; typedef float split_width; private: split_frame::ResManager *const manager_inst; - ViewRes *parent_inst; - std::tuple split_member; + SplitView *parent_inst; + DragSplitter *const splitter_inst; + std::pair split_member; // type, pos, width - std::tuple split_info_value; + std::tuple split_info; + + void sync_status(); + void splitter_adjust(const QPoint &pos); - QList view_list() const; public: - SplitPanel(split_frame::ResManager *mgr, ViewBase *a, ViewBase *b, split_frame::SplitType split, ViewRes *parent); + SplitPanel(split_frame::ResManager *mgr,split_frame::SplitType split); virtual ~SplitPanel(); + protected: + void resizeEvent(QResizeEvent *e) override; + // ViewRes interface public: virtual split_frame::ResManager *splitManager() const override; virtual split_frame::SplitView *parentRes() const override; virtual void setParentRes(SplitView *inst) override; - virtual bool canRetrieve() const override; - virtual bool canClose() const override; - virtual bool canReplace() const override; - virtual qulonglong hashCode() const override; - - // ViewBase interface - public: - virtual QIcon icon() const override; - virtual QString title() const override; virtual QWidget* widget() const override; virtual QSizeF stiffSize() const override; - virtual QSizeF viewSize() const override; - virtual void resizeView(const QSizeF &outline) override; + virtual QRectF outlineRect() const override; + virtual void setOutline(const QRectF &outline) override; + virtual qulonglong hashCode() const override; + virtual void setVisible(bool state) override; + virtual bool isVisible() const override; // SplitView interface public: - virtual std::tuple child() const override; - virtual void replaceComp(ViewBase *view, ViewBase *old) override; + virtual void initViews(ViewRes *a, ViewRes *b) override; + virtual std::pair except(split_frame::ViewRes *inst) const override; + virtual bool contains(split_frame::ViewRes *inst) const override; + virtual void replaceView(split_frame::ViewRes *_new, split_frame::ViewRes *_old) override; + virtual void setSplitInfo(float pos, float width) override; virtual float splitterWidth() const override; virtual float splitterPos() const override; - virtual void setSplitInfo(split_frame::SplitType type, float pos, float width) override; - + virtual split_frame::SplitType splitType() const override; }; diff --git a/libSplitView/splitview_interface.h b/libSplitView/splitview_interface.h index b8d6fb3..ce77739 100644 --- a/libSplitView/splitview_interface.h +++ b/libSplitView/splitview_interface.h @@ -18,7 +18,7 @@ namespace split_frame { /** * @brief 面板分割方向 */ - enum class SplitType { SPLIT_H = 0, SPLIT_V = 1 }; + enum class SplitType { SPLIT_H_LFIRST = 0, SPLIT_H_RFIRST = 1, SPLIT_V_TFIRST = 2, SPLIT_V_BFIRST = 3 }; /** * @brief 临时视图贴附方位 */ @@ -36,19 +36,73 @@ namespace split_frame { */ virtual ResManager *splitManager() const = 0; + /** * @brief 父资源实例 * @return */ virtual SplitView *parentRes() const = 0; + /** + * @brief 设置父资源实例 + * @param inst + */ virtual void setParentRes(SplitView *inst) = 0; + /** * @brief 视图组件 * @return */ virtual QWidget *widget() const = 0; + /** + * @brief 不可压缩的最小尺寸 + * @return + */ + virtual QSizeF stiffSize() const = 0; + + /** + * @brief 获取外形尺寸 + * @return + */ + virtual QRectF outlineRect() const = 0; + /** + * @brief 重新设置外形尺寸 + * @param outline + */ + virtual void setOutline(const QRectF &rect) = 0; + /** + * @brief 设置可见性 + * @param state + */ + virtual void setVisible(bool state) = 0; + virtual bool isVisible() const = 0; + + /** + * @brief 资源唯一标号 + * @return + */ + virtual qulonglong hashCode() const = 0; + }; + + /** + * @brief 视图展示接口 + */ + class ViewBase : public ViewRes { + public: + virtual ~ViewBase() = default; + + /** + * @brief 视图图标 + * @return + */ + virtual QIcon icon() const = 0; + /** + * @brief 视图标题 + * @return + */ + virtual QString title() const = 0; + /** * @brief 可以被回收 */ @@ -64,63 +118,28 @@ namespace split_frame { * @return */ virtual bool canReplace() const = 0; - - /** - * @brief 资源唯一标号 - * @return - */ - virtual qulonglong hashCode() const = 0; - }; - - /** - * @brief 视图展示接口 - */ - class ViewBase { - public: - virtual ~ViewBase() = default; - - /** - * @brief 视图图标 - * @return - */ - virtual QIcon icon() const = 0; - /** - * @brief 视图标题 - * @return - */ - virtual QString title() const = 0; - - /** - * @brief 不可压缩的最小尺寸 - * @return - */ - virtual QSizeF stiffSize() const = 0; - - /** - * @brief 获取外形尺寸 - * @return - */ - virtual QSizeF viewSize() const = 0; - /** - * @brief 重新设置外形尺寸 - * @param outline - */ - virtual void resizeView(const QSizeF &outline) = 0; }; /** * @brief 分裂视图规划和约束组件 */ - class SplitView { + class SplitView : public ViewRes { public: virtual ~SplitView() = default; /** - * @brief 替换子视图 - * @param view - * @param old + * @brief 载入视图成员 + * @param a 成员视图a + * @param b 成员视图b */ - virtual void replaceComp(ViewBase *view, ViewBase *old) = 0; + virtual void initViews(ViewRes *a, ViewRes *b) = 0; + + /** + * @brief 构建子视图 + * @param old 不为nullptr + * @param view 不为nullptr + */ + virtual void replaceView(ViewRes *_new, ViewRes *_old) = 0; /** * @brief 设置分割信息 @@ -128,13 +147,19 @@ namespace split_frame { * @param pos * @param width */ - virtual void setSplitInfo(SplitType type, float pos, float width) = 0; + virtual void setSplitInfo(float pos, float width) = 0; /** - * @brief 获取子视图列表和分割方式 + * @brief 获取本视图中的其他视图 + * @return std::pair + */ + virtual std::pair except(ViewRes *inst) const = 0; + /** + * @brief 测试是否包含指定视图 + * @param inst * @return */ - virtual std::tuple child() const = 0; + virtual bool contains(ViewRes *inst) const = 0; /** * @brief 分隔符的宽度 * @return @@ -145,6 +170,11 @@ namespace split_frame { * @return */ virtual float splitterPos() const = 0; + /** + * @brief 分割方向 + * @return 分割类型 + */ + virtual SplitType splitType() const = 0; }; @@ -158,12 +188,23 @@ namespace split_frame { * @brief 闲置视图增加 * @param ins */ - virtual void freedomAppended(ViewBase *ins) = 0; + virtual void freedomAppend(ViewBase *ins) = 0; /** * @brief 闲置视图减少 * @param ins */ - virtual void freedomRemoved(ViewBase *ins) = 0; + virtual void freedomRemove(ViewBase *ins) = 0; + + /** + * @brief 视图关闭 + * @param inst + */ + virtual void aboutToBeDelete(ViewBase *inst) = 0; + /** + * @brief 视图增加 + * @param inst + */ + virtual void hasBeenAppend(ViewBase *inst) = 0; }; /** @@ -176,6 +217,9 @@ namespace split_frame { virtual void addListener(FreedomViewsListener *lsn) = 0; virtual void removeListener(FreedomViewsListener *lsn) = 0; + virtual ViewBase* adjustView() const = 0; + virtual void setAdjustView(ViewBase *target = nullptr) = 0; + /** * @brief 在系统中移除指定视图 * @param inst @@ -191,19 +235,19 @@ namespace split_frame { * @brief 回收视图显示,转换视图为自由(闲置)状态 * @param inst */ - virtual void doRetrieve(ViewRes *inst) = 0; + virtual void doRetrieve(ViewBase *inst) = 0; /** * @brief 回收视图,清除内存实例 */ - virtual void doClose(ViewRes *inst) = 0; + virtual void doClose(ViewBase *inst) = 0; /** * @brief 替换指定视图 * @param view * @param old */ - virtual void doReplace(ViewRes *view, ViewRes *old) = 0; + virtual void siblingAttach(ViewBase *view, ViewRes *pos, SplitType ori) = 0; }; } // namespace SplitFrame diff --git a/libSplitView/splitwindow.cpp b/libSplitView/splitwindow.cpp index 1fc25d9..b984301 100644 --- a/libSplitView/splitwindow.cpp +++ b/libSplitView/splitwindow.cpp @@ -11,11 +11,180 @@ #include #include #include +#include #include -using namespace split_panel; +using namespace split_window; using namespace split_frame; -SplitWindow::SplitWindow(QWidget *parent) : QMainWindow(parent) {} +void SplitWindow::setRoot(split_frame::ViewRes *inst) +{ + if(inst){ + this->view_root = inst; + inst->setParentRes(nullptr); + this->setCentralWidget(inst->widget()); + } + else{ + this->takeCentralWidget(); + this->view_root = nullptr; + } +} + +SplitWindow::SplitWindow(QWidget *parent) : QMainWindow(parent), view_root(nullptr), accept_port(new accept_panel::AcceptPanel(this, this)) { + this->setRoot(nullptr); + accept_port->setVisible(false); +} SplitWindow::~SplitWindow() {} + +bool SplitWindow::eventFilter(QObject *sender, QEvent *ev) +{ + switch (ev->type()) { + case QEvent::Type::DragMove: { + if (sender->isWidgetType() || sender->isWindowType()) { + auto evn_pos = static_cast(ev)->pos(); + QPoint global_pos; + if (sender->isWindowType()) { + dynamic_cast(sender)->requestActivate(); + global_pos = dynamic_cast(sender)->mapToGlobal(evn_pos); + } else if (sender->isWidgetType()) { + global_pos = dynamic_cast(sender)->mapToGlobal(evn_pos); + } + + for (auto &cmp : this->views_store) { + auto local_pos = cmp->widget()->mapFromGlobal(global_pos); + auto rect_shape = cmp->outlineRect(); + rect_shape.moveTopLeft(QPointF()); + + if (rect_shape.contains(local_pos) && cmp->widget()->isActiveWindow()) { + accept_port->bindWith(cmp); + accept_port->raise(); + accept_port->setVisible(true); + break; + } + } + } + } break; + case QEvent::Type::MouseButtonRelease: + accept_port->setVisible(false); + break; + default: + break; + } + return QMainWindow::eventFilter(sender, ev); +} + +void SplitWindow::addListener(split_frame::FreedomViewsListener *lsn) +{ + if(listener_list.contains(lsn)) + return; + listener_list << lsn; +} + +void SplitWindow::removeListener(split_frame::FreedomViewsListener *lsn) +{ + this->listener_list.removeAll(lsn); +} + +void SplitWindow::appendPresentView(split_frame::ViewBase *inst) +{ + if(inst) + this->views_store[inst->hashCode()] = inst; +} + +void SplitWindow::removePresentView(split_frame::ViewBase *inst) +{ + if(inst) + this->views_store.remove(inst->hashCode()); +} + +void SplitWindow::present_remove(split_frame::ViewRes *inst) +{ + // 面板树中间节点 + if(inst != view_root && inst->parentRes()){ + auto pinst = inst->parentRes(); + + auto remains = pinst->except(inst); + remains.first->setParentRes(nullptr); + inst->setParentRes(nullptr); + + // 父节点不是根节点 + auto ppinst = pinst->parentRes(); + if (ppinst) { + ppinst->replaceView(remains.first, pinst); + } else { + this->setRoot(remains.first); + } + delete pinst; + } + else if(inst == view_root){ + setRoot(nullptr); + } +} +void SplitWindow::doRetrieve(split_frame::ViewBase *inst) +{ + // 呈现视图结构调整 + present_remove(inst); + + // 回收当前视图 + for(auto &lsn : listener_list) + lsn->freedomAppend(inst); + + inst->setParentRes(nullptr); + inst->setVisible(false); + removePresentView(inst); +} + +void SplitWindow::doClose(split_frame::ViewBase *inst) +{ + // 呈现视图结构调整 + present_remove(inst); + + // 回收当前视图 + for(auto &lsn : listener_list) + lsn->aboutToBeDelete(inst); + + removePresentView(inst); + delete inst; +} + +void SplitWindow::siblingAttach(ViewBase *view, ViewRes *pos, SplitType ori) +{ + doRetrieve(view); + + auto split_slot = new split_panel::SplitPanel(this, ori); + auto remains_frm = pos->parentRes(); + remains_frm->replaceView(split_slot, pos); + + switch (ori) { + case SplitType::SPLIT_H_LFIRST: + split_slot->initViews(view, pos); + split_slot->setSplitInfo(0.333, 8); + break; + case SplitType::SPLIT_H_RFIRST: + split_slot->initViews(pos, view); + split_slot->setSplitInfo(0.666, 8); + break; + case SplitType::SPLIT_V_TFIRST: + split_slot->initViews(view, pos); + split_slot->setSplitInfo(0.333, 8); + break; + case SplitType::SPLIT_V_BFIRST: + split_slot->initViews(pos, view); + split_slot->setSplitInfo(0.666, 8); + break; + } + + for(auto &lsn : listener_list) + lsn->freedomRemove(view); +} + +ViewBase *SplitWindow::adjustView() const +{ + return adjust_target; +} + +void SplitWindow::setAdjustView(split_frame::ViewBase *target) +{ + this->adjust_target = target; +} diff --git a/libSplitView/splitwindow.h b/libSplitView/splitwindow.h index 0240de4..e50a52d 100644 --- a/libSplitView/splitwindow.h +++ b/libSplitView/splitwindow.h @@ -2,34 +2,59 @@ #define SPLITWINDOW_H #include "splitview_interface.h" +#include "acceptpanel.h" #include #include #include -namespace split_panel { - +namespace split_window { /** - * @brief 鍒嗚瑙嗗浘鍛堢幇缁勪欢 + * @brief 窗口即视图资源管理器 */ - class SPLITVIEW_EXPORT SplitWindow : public QMainWindow, public split_frame::SplitView { + class SPLITVIEW_EXPORT SplitWindow : public QMainWindow, public split_frame::ResManager { typedef float pos; typedef float width; + private: + QList listener_list; + QHash views_store; + split_frame::ViewRes *view_root; + accept_panel::AcceptPanel *const accept_port; + split_frame::ViewBase *adjust_target = nullptr; + + void present_remove(split_frame::ViewRes *inst); + public: SplitWindow(QWidget *parent = nullptr); virtual ~SplitWindow(); //====================================================== /** - * @brief 涓存椂鏄剧ず鎸囧畾瑙嗗浘 + * @brief 临时展示 * @param t * @param target */ void tempShow(split_frame::DockType t, split_frame::ViewBase *target); + void setRoot(split_frame::ViewRes *inst); + + + bool eventFilter(QObject *sender, QEvent *ev) override; + + // ResManager interface + public: + virtual void addListener(split_frame::FreedomViewsListener *lsn) override; + virtual void removeListener(split_frame::FreedomViewsListener *lsn) override; + virtual void appendPresentView(split_frame::ViewBase *inst) override; + virtual void removePresentView(split_frame::ViewBase *inst) override; + virtual void doRetrieve(split_frame::ViewBase *inst) override; + virtual void doClose(split_frame::ViewBase *inst) override; + virtual void siblingAttach(split_frame::ViewBase *view, split_frame::ViewRes *pos, split_frame::SplitType ori) override; + virtual split_frame::ViewBase *adjustView() const override; + virtual void setAdjustView(split_frame::ViewBase *target) override; }; } // namespace split_panel diff --git a/u_test/main.cpp b/u_test/main.cpp index 5a0fafe..556b32e 100644 --- a/u_test/main.cpp +++ b/u_test/main.cpp @@ -13,25 +13,21 @@ #include #include #include - -using namespace SplitFrame; +#include int main(int argc, char *argv[]) { QApplication a(argc, argv); - auto win = new QMainWindow(); - win->show(); + split_window::SplitWindow w; + auto spb = new split_panel::SplitPanel(&w, split_frame::SplitType::SPLIT_H_LFIRST); + w.setRoot(spb); - QWidget *firstPageWidget = new XWidget(nullptr, Qt::GlobalColor::green); - QWidget *secondPageWidget = new XWidget(nullptr, Qt::black); - QWidget *thirdPageWidget = new XWidget(nullptr, Qt::black); + auto bview = new dock_panel::DockableView(&w, new QWidget, true); + auto dview = new dock_panel::DockableView(&w, new QWidget, true); + spb->initViews(bview, dview); - QStackedWidget *stackedWidget = new QStackedWidget; - stackedWidget->addWidget(firstPageWidget); - stackedWidget->addWidget(secondPageWidget); - stackedWidget->addWidget(thirdPageWidget); - - win->setCentralWidget(stackedWidget); + a.installEventFilter(&w); + w.show(); return a.exec(); } diff --git a/u_test/unnnn.cpp b/u_test/unnnn.cpp index 2eba210..35eacff 100644 --- a/u_test/unnnn.cpp +++ b/u_test/unnnn.cpp @@ -1,22 +1,3 @@ #include "unnnn.h" #include -using namespace SplitFrame; - -XWidget::XWidget(SplitPanel *host, Qt::GlobalColor c, QWidget *parent) : FnWrap(host), c_store(c) {} - -void XWidget::paintEvent(QPaintEvent *ev) { - QPainter p(this); - p.fillRect(this->rect(), c_store); -} - -void XWidget::closeProcess() {} - -YWidget::YWidget(SplitPanel *host, QWidget *parent) : FnWrap(host) {} - -void YWidget::paintEvent(QPaintEvent *ev) { - QPainter p(this); - p.fillRect(this->rect(), Qt::blue); -} - -void YWidget::closeProcess() {} diff --git a/u_test/unnnn.h b/u_test/unnnn.h index ef907a3..50e3e15 100644 --- a/u_test/unnnn.h +++ b/u_test/unnnn.h @@ -5,26 +5,5 @@ #include #include -class XWidget : public SplitFrame::FnWrap { -public: - XWidget(SplitFrame::SplitPanel *host, Qt::GlobalColor c, QWidget *parent = nullptr); - virtual void paintEvent(QPaintEvent *ev) override; - - // FnWrap interface -public: - virtual void closeProcess() override; - -private: - Qt::GlobalColor c_store; -}; - -class YWidget : public SplitFrame::FnWrap { -public: - YWidget(SplitFrame::SplitPanel *host, QWidget *parent = nullptr); - virtual void paintEvent(QPaintEvent *ev) override; - // FnWrap interface -public: - virtual void closeProcess() override; -}; #endif // UNNNN_H