-
Notifications
You must be signed in to change notification settings - Fork 0
/
graphicsview.h
175 lines (148 loc) · 6.48 KB
/
graphicsview.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/********************************************************************************
* Author : Damir Bakiev *
* Version : na *
* Date : March 25, 2023 *
* Website : na *
* Copyright : Damir Bakiev 2016-2023 *
* License : *
* Use, modification & distribution is subject to Boost Software License Ver 1. *
* http://www.boost.org/LICENSE_1_0.txt *
********************************************************************************/
#pragma once
#include <QGraphicsItem>
#include <QGraphicsView>
#include <QScreen>
#include <QSettings>
#include <ranges>
namespace ranges = std::ranges;
namespace rviews = std::ranges::views;
class Ruler;
class QGridLayout;
// class Scene;
class GraphicsView : public QGraphicsView {
Q_OBJECT
Q_PROPERTY(double scale READ getScale WRITE setScale)
Q_PROPERTY(QRectF viewRect READ getViewRect WRITE setViewRect)
template <size_t N>
struct EnumHelper : std::integral_constant<bool, N != 0> {
template <typename... Es>
requires(std::is_enum_v<Es> && ...) || (sizeof...(Es) == 0)
constexpr EnumHelper(Es... es)
: array{es...} { }
int array[N];
template <size_t... Is>
constexpr bool impl(auto* item, std::index_sequence<Is...>) const {
return ((item->type() == array[Is]) || ...);
}
constexpr bool operator()(auto* item) const {
return impl(item, std::make_index_sequence<N>{});
}
};
template <typename... Es>
EnumHelper(Es...) -> EnumHelper<sizeof...(Es)>;
public:
explicit GraphicsView(QWidget* parent = nullptr);
~GraphicsView() override;
// void setScene(QGraphicsScene* Scene);
void zoom100();
void zoomFit();
void zoomToSelected();
void zoomIn();
void zoomOut();
void fitInView(QRectF destRect, bool withBorders = true);
void setRuler(bool ruller);
double scaleFactor() const noexcept { return 1.0 / getScale(); }
QPointF mappedPos(QMouseEvent* event) const;
void setScale(double s) noexcept;
double getScale() const noexcept { return transform().m11(); }
void setOpenGL(bool useOpenGL);
void setViewRect(const QRectF& r);
QRectF getViewRect();
QRectF getSelectedBoundingRect();
bool boundingRectFl() const { return boundingRect_; }
void startUpdateTimer(int timeMs) {
if(timerId)
killTimer(timerId);
timerId = startTimer(timeMs);
}
void stopUpdateTimer() {
if(timerId)
killTimer(timerId);
timerId = 0;
}
/////////////////////////////////
template <typename T = QGraphicsItem, typename... Ts>
auto items(Ts... ts) const {
return getItemImpl<qOverload<Qt::SortOrder>(&QGraphicsScene::items), T>(EnumHelper{ts...}, Qt::DescendingOrder);
}
template <typename T = QGraphicsItem, typename... Ts>
auto selectedItems(Ts... ts) const {
return getItemImpl<&QGraphicsScene::selectedItems, T>(EnumHelper{ts...});
}
template <typename T>
auto addItem(T* item) const { return scene()->addItem(item), item; }
template <typename T, typename... Args>
auto addItem(Args... args) const {
auto item = new T{std::forward<Args>(args)...};
return addItem(item);
}
signals:
void fileDroped(const QString&);
void mouseClickL(const QPointF&);
void mouseClickR(const QPointF&);
void mouseMove(const QPointF&);
private:
template <auto Ptr, typename T, typename FilterInt, typename... Args>
std::vector<T*> getItemImpl(FilterInt&& et, Args&&... args) const {
const auto items = (scene()->*Ptr)(std::forward<Args>(args)...); // get all items
constexpr bool isQGraphicsItem = std::is_same_v<T, QGraphicsItem>;
if constexpr(isQGraphicsItem && !FilterInt::value) { // вернуть все QGraphicsItem*
return {items.begin(), items.end()};
} else {
// WARNING FilterInt faster than dynamic_cast
// to improve speed dont use FilterDyn
using FilterDyn = decltype([](auto* item) { return bool(dynamic_cast<T*>(item)); });
using Transform = decltype([](auto* item) { return static_cast<T*>(item); });
if constexpr(!isQGraphicsItem && !FilterInt::value) { // вернуть все T*
auto rview = items | rviews::filter(FilterDyn{}) | rviews::transform(Transform{});
return {rview.begin(), rview.end()};
} else if constexpr(!isQGraphicsItem && FilterInt::value) { // вернуть все T* отсортированные по type()
auto rview = items | rviews::filter(et) | rviews::filter(FilterDyn{}) | rviews::transform(Transform{});
return {rview.begin(), rview.end()};
} else if constexpr(isQGraphicsItem && FilterInt::value) { // вернуть все QGraphicsItem* отсортированные по type()
auto rview = items | rviews::filter(et);
return {rview.begin(), rview.end()};
}
}
}
// Ruler* const hRuler;
// Ruler* const vRuler;
// QGridLayout* const gridLayout;
// Scene* scene_;
bool ruler_{};
int rulerCtr{};
bool boundingRect_{};
void updateRuler();
template <class T>
void animate(QObject* target, const QByteArray& propertyName, T begin, T end);
QPoint latPos;
QPointF point, rulPt1, rulPt2;
void drawRuller(QPainter* painter, const QRectF& rect) const;
int timerId{};
// QWidget interface
protected:
void dragEnterEvent(QDragEnterEvent* event) override;
void dragMoveEvent(QDragMoveEvent* event) override;
void dropEvent(QDropEvent* event) override;
void resizeEvent(QResizeEvent* event) override;
void wheelEvent(QWheelEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void drawForeground(QPainter* painter, const QRectF& rect) override;
void drawBackground(QPainter* painter, const QRectF& rect) override;
// QObject interface
protected:
void timerEvent(QTimerEvent* event) override;
};
// #include "app.h"