#ifndef SPLITPANEL_H #define SPLITPANEL_H #include "splitpanel_global.h" #include #include namespace SplitFrame { class ViewPresent; class AttachPanel; /** * @brief 面板分割方向 */ enum class SplitType { SPLIT_H = 0, SPLIT_V = 1 }; /** * @brief 临时视图贴附方位 */ enum class DockType { LEFT = 0, RIGHT, TOP, BOTTOM }; /** * @brief 视图资源基类 */ class ViewRes { public: virtual ~ViewRes() = default; virtual void registElement(QWidget *child) = 0; virtual QWidget *bind() const = 0; virtual QString title() const = 0; virtual ViewPresent *viewPanel() const = 0; /** * @brief 关闭视图显示,转换视图为自由(闲置)状态 */ virtual void pRelease() = 0; /** * @brief 回收视图,清除内存实例 */ virtual void pClose() = 0; virtual void setParentRes(ViewRes *inst) = 0; virtual ViewRes *parentRes() const = 0; }; /** * @brief 资源管理接口 */ class ResManager { public: virtual ~ResManager() = default; virtual ViewPresent *viewPanel() const = 0; virtual void objsRelateRebuild() = 0; virtual void markFreedom(ViewRes *view) = 0; virtual void purge(ViewRes *target) = 0; }; /** * @brief 视图展示接口 */ class RectCom : public ViewRes { public: virtual ~RectCom() = default; virtual bool contains(QWidget *ptr) const = 0; virtual QRectF outline() const = 0; virtual void relayout(const QRectF &outline) = 0; virtual void paintEvent(QPaintEvent *ev) = 0; }; /** * @brief 功能视图基板 */ template class FnWrap : public QWidget { private: static bool type_blank_blank; ViewPresent *const host_store; public: explicit FnWrap(ViewPresent *bind, QWidget *parent = nullptr) : QWidget(parent), host_store(bind) {} virtual ~FnWrap() { this->closeProcess(); } ViewPresent *bindHost() const { return host_store; } virtual void closeProcess(){}; }; /** * @brief 分裂视图规划和约束组件 */ class SplitRect : public RectCom { public: virtual ~SplitRect() = default; virtual std::pair child() const = 0; virtual void removeComp(RectCom *child) = 0; virtual void replaceComp(RectCom *view, RectCom *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; }; class FreedomViewsListener { public: virtual ~FreedomViewsListener() = default; /** * @brief 闲置视图增加 * @param ins */ virtual void freedomAppended(RectCom *ins, const QIcon &icon, const QString &title) = 0; /** * @brief 闲置视图减少 * @param ins */ virtual void freedomRemoved(RectCom *ins) = 0; }; /** * @brief 分裂视图呈现组件 */ class SPLITVIEW_EXPORT ViewPresent : private QWidget, public SplitRect, public ResManager { public: ViewPresent(QWidget *parent = nullptr); virtual ~ViewPresent(); void addListener(FreedomViewsListener *lsn); void removeListener(FreedomViewsListener *lsn); //====================================================== const QList freedomViews() const; void resetEngross(RectCom *view = nullptr); void temporaryVisible(DockType t, RectCom *target = nullptr); bool isTemporaryView(RectCom *view); QObject *globalEventFilter() const; /** * @brief 切换视图调整状态 * @param state 状态开关 */ void setAdjustView(RectCom *one = nullptr); bool adjustState() const; RectCom *adjustView() const; SplitRect *createSplit(RectCom *first, RectCom *next, SplitType sp, float pos = 20, float split_width = 8); template RectCom *appendView(FnWrap *view_inst, const QIcon &icon, const QString &title) { if (view_inst->bindHost() != this) throw new Config::SimpleException("非法操作", "不允许混用不同ViewPresent的成员"); auto panel = create_base_panel(view_inst, icon, title, _blank); regist_basepanel(panel); return panel; } // RectCom interface public: virtual QWidget *bind() const override; virtual bool contains(QWidget *) const override; virtual QRectF outline() const override; virtual void relayout(const QRectF &outline) override; virtual QString title() const override; // ViewRes interface public: virtual ViewPresent *viewPanel() const override; virtual void setParentRes(ViewRes *p = nullptr) override; virtual ViewRes *parentRes() const override; virtual void pRelease() override; virtual void pClose() override; virtual void registElement(QWidget *) override; // ResManager interface public: virtual void objsRelateRebuild() override; virtual void markFreedom(ViewRes *view) override; virtual void purge(ViewRes *target) override; // SplitRect interface public: virtual std::pair child() const override; virtual void removeComp(RectCom *child) override; virtual void replaceComp(RectCom *view, RectCom *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; // QObject interface public: virtual bool eventFilter(QObject *watched, QEvent *event) 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: QList lsn_list; AttachPanel *const accept_panel; // 拖拽属性=================================== RectCom *adjust_view_temp; // 拖拽中转 bool press_flags = false; // 空间调整标志 // 方向,splitter位置,splitter宽度 std::tuple split_info_store = std::make_tuple(SplitType::SPLIT_H, 200, 8); // 视图展现堆栈=============================== QList all_func_views; QList freedom_views; RectCom *display_members = nullptr; std::pair temp_visible_view = std::make_pair(DockType::LEFT, nullptr); std::pair view_rects(); QRectF handle_rect() const; virtual void relayout(); RectCom *create_base_panel(QWidget *bview, const QIcon &icon, const QString &title, bool empty_flag = false); void regist_basepanel(RectCom *it); }; } // namespace SplitFrame #endif // SPLITPANEL_H