##// END OF EJS Templates
New style on mac to keep the scrollbars visible
Thibaud Rabillard -
r929:5ec3f5d1277b
parent child
Show More
@@ -0,0 +1,18
1 #ifndef SCIQLOP_MACSCROLLBARSTYLE_H
2 #define SCIQLOP_MACSCROLLBARSTYLE_H
3
4 #include <QProxyStyle>
5
6 /**
7 * @brief Special style to always display the scrollbars on MAC.
8 */
9 class MacScrollBarStyle : public QProxyStyle {
10
11 public:
12 int styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget,
13 QStyleHintReturn *returnData) const;
14
15 void selfInstallOn(QWidget *widget, bool installOnSubWidgets);
16 };
17
18 #endif // SCIQLOP_MACSCROLLBARSTYLE_H
@@ -0,0 +1,40
1 #include "Visualization/MacScrollBarStyle.h"
2
3 #include <QWidget>
4
5 int MacScrollBarStyle::styleHint(QStyle::StyleHint hint, const QStyleOption *option,
6 const QWidget *widget, QStyleHintReturn *returnData) const
7 {
8 switch (hint) {
9 case SH_ScrollBar_Transient:
10 return false; // Makes the scrollbar always visible
11 case SH_ScrollView_FrameOnlyAroundContents:
12 return true; // Avoid that the scrollbar is drawn on top of the widget
13 default:
14 break;
15 }
16
17 return QProxyStyle::styleHint(hint, option, widget, returnData);
18 }
19
20 void MacScrollBarStyle::selfInstallOn(QWidget *widget, bool installOnSubWidgets)
21 {
22 // Note: a style can be installed on a particular widget but it is not automatically applied its
23 // children widgets.
24
25 QList<QWidget *> widgetsToStyle{widget};
26 while (!widgetsToStyle.isEmpty()) {
27
28 auto widget = widgetsToStyle.takeFirst();
29 widget->setStyle(this);
30
31 if (installOnSubWidgets) {
32 for (auto child : widget->children()) {
33 auto childWidget = qobject_cast<QWidget *>(child);
34 if (childWidget) {
35 widgetsToStyle << childWidget;
36 }
37 }
38 }
39 }
40 }
@@ -1,97 +1,98
1 1
2 2 gui_moc_headers = [
3 3 'include/DataSource/DataSourceWidget.h',
4 4 'include/DataSource/DataSourceTreeWidget.h',
5 5 'include/Settings/SqpSettingsDialog.h',
6 6 'include/Settings/SqpSettingsGeneralWidget.h',
7 7 'include/SidePane/SqpSidePane.h',
8 8 'include/SqpApplication.h',
9 9 'include/DragAndDrop/DragDropHelper.h',
10 10 'include/DragAndDrop/DragDropScroller.h',
11 11 'include/DragAndDrop/DragDropTabSwitcher.h',
12 12 'include/TimeWidget/TimeWidget.h',
13 13 'include/Variable/VariableInspectorWidget.h',
14 14 'include/Variable/VariableInspectorTableView.h',
15 15 'include/Variable/RenameVariableDialog.h',
16 16 'include/Visualization/qcustomplot.h',
17 17 'include/Visualization/VisualizationGraphWidget.h',
18 18 'include/Visualization/VisualizationTabWidget.h',
19 19 'include/Visualization/VisualizationWidget.h',
20 20 'include/Visualization/VisualizationZoneWidget.h',
21 21 'include/Visualization/VisualizationDragDropContainer.h',
22 22 'include/Visualization/VisualizationDragWidget.h'
23 23 ]
24 24
25 25 gui_ui_files = [
26 26 'ui/DataSource/DataSourceWidget.ui',
27 27 'ui/Settings/SqpSettingsDialog.ui',
28 28 'ui/Settings/SqpSettingsGeneralWidget.ui',
29 29 'ui/SidePane/SqpSidePane.ui',
30 30 'ui/TimeWidget/TimeWidget.ui',
31 31 'ui/Variable/VariableInspectorWidget.ui',
32 32 'ui/Variable/RenameVariableDialog.ui',
33 33 'ui/Variable/VariableMenuHeaderWidget.ui',
34 34 'ui/Visualization/VisualizationGraphWidget.ui',
35 35 'ui/Visualization/VisualizationTabWidget.ui',
36 36 'ui/Visualization/VisualizationWidget.ui',
37 37 'ui/Visualization/VisualizationZoneWidget.ui'
38 38 ]
39 39
40 40 gui_qresources = ['resources/sqpguiresources.qrc']
41 41
42 42 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
43 43 ui_files : gui_ui_files,
44 44 qresources : gui_qresources)
45 45
46 46 gui_sources = [
47 47 'src/SqpApplication.cpp',
48 48 'src/DragAndDrop/DragDropHelper.cpp',
49 49 'src/DragAndDrop/DragDropScroller.cpp',
50 50 'src/DragAndDrop/DragDropTabSwitcher.cpp',
51 51 'src/Common/ColorUtils.cpp',
52 52 'src/Common/VisualizationDef.cpp',
53 53 'src/DataSource/DataSourceTreeWidgetItem.cpp',
54 54 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
55 55 'src/DataSource/DataSourceWidget.cpp',
56 56 'src/DataSource/DataSourceTreeWidget.cpp',
57 57 'src/Settings/SqpSettingsDialog.cpp',
58 58 'src/Settings/SqpSettingsGeneralWidget.cpp',
59 59 'src/SidePane/SqpSidePane.cpp',
60 60 'src/TimeWidget/TimeWidget.cpp',
61 61 'src/Variable/VariableInspectorWidget.cpp',
62 62 'src/Variable/VariableInspectorTableView.cpp',
63 63 'src/Variable/VariableMenuHeaderWidget.cpp',
64 64 'src/Variable/RenameVariableDialog.cpp',
65 65 'src/Visualization/VisualizationGraphHelper.cpp',
66 66 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
67 67 'src/Visualization/VisualizationGraphWidget.cpp',
68 68 'src/Visualization/VisualizationTabWidget.cpp',
69 69 'src/Visualization/VisualizationWidget.cpp',
70 70 'src/Visualization/VisualizationZoneWidget.cpp',
71 71 'src/Visualization/qcustomplot.cpp',
72 72 'src/Visualization/QCustomPlotSynchronizer.cpp',
73 73 'src/Visualization/operations/FindVariableOperation.cpp',
74 74 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
75 75 'src/Visualization/operations/MenuBuilder.cpp',
76 76 'src/Visualization/operations/RemoveVariableOperation.cpp',
77 77 'src/Visualization/operations/RescaleAxeOperation.cpp',
78 78 'src/Visualization/VisualizationDragDropContainer.cpp',
79 79 'src/Visualization/VisualizationDragWidget.cpp',
80 80 'src/Visualization/AxisRenderingUtils.cpp',
81 'src/Visualization/PlottablesRenderingUtils.cpp'
81 'src/Visualization/PlottablesRenderingUtils.cpp',
82 'src/Visualization/MacScrollBarStyle.cpp'
82 83 ]
83 84
84 85 gui_inc = include_directories(['include'])
85 86
86 87 sciqlop_gui_lib = library('sciqlopgui',
87 88 gui_sources,
88 89 gui_moc_files,
89 90 include_directories : [gui_inc],
90 91 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core],
91 92 install : true
92 93 )
93 94
94 95 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
95 96 include_directories : gui_inc,
96 97 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core])
97 98
@@ -1,309 +1,319
1 1 #include "Visualization/VisualizationTabWidget.h"
2 2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 3 #include "ui_VisualizationTabWidget.h"
4 4
5 5 #include "Visualization/VisualizationGraphWidget.h"
6 6 #include "Visualization/VisualizationZoneWidget.h"
7 7
8 #include "Visualization/MacScrollBarStyle.h"
9
8 10 #include "Variable/VariableController.h"
9 11
10 12 #include "Common/MimeTypesDef.h"
11 13
12 14 #include "DragAndDrop/DragDropHelper.h"
13 15 #include "SqpApplication.h"
14 16
15 17 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
16 18
17 19 namespace {
18 20
19 21 /// Generates a default name for a new zone, according to the number of zones already displayed in
20 22 /// the tab
21 23 QString defaultZoneName(const QLayout &layout)
22 24 {
23 25 auto count = 0;
24 26 for (auto i = 0; i < layout.count(); ++i) {
25 27 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
26 28 count++;
27 29 }
28 30 }
29 31
30 32 return QObject::tr("Zone %1").arg(count + 1);
31 33 }
32 34
33 35 /**
34 36 * Applies a function to all zones of the tab represented by its layout
35 37 * @param layout the layout that contains zones
36 38 * @param fun the function to apply to each zone
37 39 */
38 40 template <typename Fun>
39 41 void processZones(QLayout &layout, Fun fun)
40 42 {
41 43 for (auto i = 0; i < layout.count(); ++i) {
42 44 if (auto item = layout.itemAt(i)) {
43 45 if (auto visualizationZoneWidget
44 46 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
45 47 fun(*visualizationZoneWidget);
46 48 }
47 49 }
48 50 }
49 51 }
50 52
51 53 } // namespace
52 54
53 55 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
54 56 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
55 57
56 58 QString m_Name;
57 59
60 #ifdef Q_OS_MAC
61 std::unique_ptr<MacScrollBarStyle> m_MacScrollBarStyle = std::make_unique<MacScrollBarStyle>();
62 #endif
63
58 64 void dropGraph(int index, VisualizationTabWidget *tabWidget);
59 65 void dropZone(int index, VisualizationTabWidget *tabWidget);
60 66 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
61 67 VisualizationTabWidget *tabWidget);
62 68 };
63 69
64 70 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
65 71 : QWidget{parent},
66 72 ui{new Ui::VisualizationTabWidget},
67 73 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
68 74 {
69 75 ui->setupUi(this);
70 76
77 #ifdef Q_OS_MAC
78 impl->m_MacScrollBarStyle->selfInstallOn(ui->scrollArea, true);
79 #endif
80
71 81 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Zone, "Zone");
72 82 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 5);
73 83 ui->dragDropContainer->addAcceptedMimeType(
74 84 MIME_TYPE_GRAPH, VisualizationDragDropContainer::DropBehavior::Inserted);
75 85 ui->dragDropContainer->addAcceptedMimeType(
76 86 MIME_TYPE_ZONE, VisualizationDragDropContainer::DropBehavior::Inserted);
77 87 ui->dragDropContainer->addAcceptedMimeType(
78 88 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::Inserted);
79 89
80 90 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
81 91 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
82 92 ui->dragDropContainer);
83 93 });
84 94
85 95 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
86 96 &VisualizationTabWidget::dropMimeData);
87 97
88 98 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
89 99
90 100 // Widget is deleted when closed
91 101 setAttribute(Qt::WA_DeleteOnClose);
92 102 }
93 103
94 104 VisualizationTabWidget::~VisualizationTabWidget()
95 105 {
96 106 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
97 107 delete ui;
98 108 }
99 109
100 110 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
101 111 {
102 112 ui->dragDropContainer->addDragWidget(zoneWidget);
103 113 }
104 114
105 115 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
106 116 {
107 117 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
108 118 }
109 119
110 120 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
111 121 {
112 122 return createZone({variable}, -1);
113 123 }
114 124
115 125 VisualizationZoneWidget *
116 126 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
117 127 {
118 128 auto zoneWidget = createEmptyZone(index);
119 129
120 130 // Creates a new graph into the zone
121 131 zoneWidget->createGraph(variables, index);
122 132
123 133 return zoneWidget;
124 134 }
125 135
126 136 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
127 137 {
128 138 auto zoneWidget
129 139 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
130 140 this->insertZone(index, zoneWidget);
131 141
132 142 return zoneWidget;
133 143 }
134 144
135 145 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
136 146 {
137 147 if (visitor) {
138 148 visitor->visitEnter(this);
139 149
140 150 // Apply visitor to zone children: widgets different from zones are not visited (no action)
141 151 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
142 152 zoneWidget.accept(visitor);
143 153 });
144 154
145 155 visitor->visitLeave(this);
146 156 }
147 157 else {
148 158 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
149 159 }
150 160 }
151 161
152 162 bool VisualizationTabWidget::canDrop(const Variable &variable) const
153 163 {
154 164 // A tab can always accomodate a variable
155 165 Q_UNUSED(variable);
156 166 return true;
157 167 }
158 168
159 169 bool VisualizationTabWidget::contains(const Variable &variable) const
160 170 {
161 171 Q_UNUSED(variable);
162 172 return false;
163 173 }
164 174
165 175 QString VisualizationTabWidget::name() const
166 176 {
167 177 return impl->m_Name;
168 178 }
169 179
170 180 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
171 181 {
172 182 // Closes zones in the tab
173 183 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
174 184
175 185 QWidget::closeEvent(event);
176 186 }
177 187
178 188 QLayout &VisualizationTabWidget::tabLayout() const noexcept
179 189 {
180 190 return *ui->dragDropContainer->layout();
181 191 }
182 192
183 193 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
184 194 {
185 195 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
186 196 impl->dropGraph(index, this);
187 197 }
188 198 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
189 199 impl->dropZone(index, this);
190 200 }
191 201 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
192 202 auto variables = sqpApp->variableController().variablesForMimeData(
193 203 mimeData->data(MIME_TYPE_VARIABLE_LIST));
194 204 impl->dropVariables(variables, index, this);
195 205 }
196 206 else {
197 207 qCWarning(LOG_VisualizationZoneWidget())
198 208 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
199 209 }
200 210 }
201 211
202 212 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
203 213 int index, VisualizationTabWidget *tabWidget)
204 214 {
205 215 auto &helper = sqpApp->dragDropHelper();
206 216
207 217 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
208 218 if (!graphWidget) {
209 219 qCWarning(LOG_VisualizationZoneWidget())
210 220 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
211 221 "found or invalid.");
212 222 Q_ASSERT(false);
213 223 return;
214 224 }
215 225
216 226 auto parentDragDropContainer
217 227 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
218 228 if (!parentDragDropContainer) {
219 229 qCWarning(LOG_VisualizationZoneWidget())
220 230 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
221 231 "the dropped graph is not found.");
222 232 Q_ASSERT(false);
223 233 return;
224 234 }
225 235
226 236 auto nbGraph = parentDragDropContainer->countDragWidget();
227 237
228 238 const auto &variables = graphWidget->variables();
229 239
230 240 if (!variables.isEmpty()) {
231 241 // Abort the requests for the variables (if any)
232 242 // Commented, because it's not sure if it's needed or not
233 243 // for (const auto& var : variables)
234 244 //{
235 245 // sqpApp->variableController().onAbortProgressRequested(var);
236 246 //}
237 247
238 248 if (nbGraph == 1) {
239 249 // This is the only graph in the previous zone, close the zone
240 250 helper.delayedCloseWidget(graphWidget->parentZoneWidget());
241 251 }
242 252 else {
243 253 // Close the graph
244 254 helper.delayedCloseWidget(graphWidget);
245 255 }
246 256
247 257 tabWidget->createZone(variables, index);
248 258 }
249 259 else {
250 260 // The graph is empty, create an empty zone and move the graph inside
251 261
252 262 auto parentZoneWidget = graphWidget->parentZoneWidget();
253 263
254 264 parentDragDropContainer->layout()->removeWidget(graphWidget);
255 265
256 266 auto zoneWidget = tabWidget->createEmptyZone(index);
257 267 zoneWidget->addGraph(graphWidget);
258 268
259 269 // Close the old zone if it was the only graph inside
260 270 if (nbGraph == 1) {
261 271 helper.delayedCloseWidget(parentZoneWidget);
262 272 }
263 273 }
264 274 }
265 275
266 276 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
267 277 int index, VisualizationTabWidget *tabWidget)
268 278 {
269 279 auto &helper = sqpApp->dragDropHelper();
270 280
271 281 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
272 282 if (!zoneWidget) {
273 283 qCWarning(LOG_VisualizationZoneWidget())
274 284 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
275 285 "found or invalid.");
276 286 Q_ASSERT(false);
277 287 return;
278 288 }
279 289
280 290 auto parentDragDropContainer
281 291 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
282 292 if (!parentDragDropContainer) {
283 293 qCWarning(LOG_VisualizationZoneWidget())
284 294 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
285 295 "the dropped zone is not found.");
286 296 Q_ASSERT(false);
287 297 return;
288 298 }
289 299
290 300 // Simple move of the zone, no variable operation associated
291 301 parentDragDropContainer->layout()->removeWidget(zoneWidget);
292 302 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
293 303 }
294 304
295 305 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
296 306 const QList<std::shared_ptr<Variable> > &variables, int index,
297 307 VisualizationTabWidget *tabWidget)
298 308 {
299 309 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
300 310 // compatible variable here
301 311 if (variables.count() > 1) {
302 312 qCWarning(LOG_VisualizationZoneWidget())
303 313 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
304 314 "aborted.");
305 315 return;
306 316 }
307 317
308 318 tabWidget->createZone(variables, index);
309 319 }
General Comments 1
Under Review
author

Auto status change to "Under Review"

You need to be logged in to leave comments. Login now