Merge lp:~ahayzen/ubuntu-ui-extras/tabs-add-dnd into lp:~phablet-team/ubuntu-ui-extras/tabs
- tabs-add-dnd
- Merge into tabs
Proposed by
Andrew Hayzen
Status: | Merged |
---|---|
Merged at revision: | 122 |
Proposed branch: | lp:~ahayzen/ubuntu-ui-extras/tabs-add-dnd |
Merge into: | lp:~phablet-team/ubuntu-ui-extras/tabs |
Diff against target: |
672 lines (+490/-7) 8 files modified
modules/Ubuntu/Components/Extras/TabsBar.qml (+147/-4) modules/Ubuntu/Components/Extras/TabsBar/DragAndDropSettings.qml (+32/-0) modules/Ubuntu/Components/Extras/TabsBar/Tab.qml (+1/-0) modules/Ubuntu/Components/Extras/plugin/CMakeLists.txt (+5/-1) modules/Ubuntu/Components/Extras/plugin/components.cpp (+6/-1) modules/Ubuntu/Components/Extras/plugin/components.h (+1/-1) modules/Ubuntu/Components/Extras/plugin/tabsbar/drag-helper.cpp (+205/-0) modules/Ubuntu/Components/Extras/plugin/tabsbar/drag-helper.h (+93/-0) |
To merge this branch: | bzr merge lp:~ahayzen/ubuntu-ui-extras/tabs-add-dnd |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Florian Boucault | Pending | ||
Review via email: mp+314003@code.launchpad.net |
Commit message
* Add drag and drop support to tabs component
Description of the change
* Add drag and drop support to tabs component
To post a comment you must log in.
Revision history for this message
Andrew Hayzen (ahayzen) wrote : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'modules/Ubuntu/Components/Extras/TabsBar.qml' |
2 | --- modules/Ubuntu/Components/Extras/TabsBar.qml 2016-12-08 14:26:41 +0000 |
3 | +++ modules/Ubuntu/Components/Extras/TabsBar.qml 2017-01-06 16:37:25 +0000 |
4 | @@ -1,5 +1,5 @@ |
5 | /* |
6 | - * Copyright (C) 2016 Canonical Ltd |
7 | + * Copyright (C) 2016, 2017 Canonical Ltd |
8 | * |
9 | * This program is free software: you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License version 3 as |
11 | @@ -22,6 +22,8 @@ |
12 | import Ubuntu.Components 1.3 |
13 | import "TabsBar" as LocalTabs |
14 | |
15 | +import Ubuntu.Components.Extras 0.3 |
16 | + |
17 | Rectangle { |
18 | id: tabsBar |
19 | |
20 | @@ -35,15 +37,40 @@ |
21 | property color highlightColor: Qt.rgba(actionColor.r, actionColor.g, actionColor.b, 0.1) |
22 | /* 'model' needs to have the following members: |
23 | property int selectedIndex |
24 | + function addExistingTab(var tab) |
25 | function selectTab(int index) |
26 | function removeTab(int index) |
27 | + function removeTabWithoutDestroying(int index) |
28 | function moveTab(int from, int to) |
29 | + |
30 | + removeTabWithoutDestroying is useful when a tab is being removed due |
31 | + to moving, so you don't want the content to be destroyed |
32 | */ |
33 | property var model |
34 | property list<Action> actions |
35 | + property bool dimmed: false |
36 | + |
37 | + /* To enable drag and drop set to enabled |
38 | + * |
39 | + * Use expose to set any information you need the DropArea to access |
40 | + * Then use drag.source.expose.myproperty |
41 | + * |
42 | + * Set mimeType to one of the keys in the DropArea's you want to accept |
43 | + * |
44 | + * Set a function for previewUrlFromIndex which is given the index |
45 | + * and returns a url to an image, which will be shown in the handle |
46 | + */ |
47 | + readonly property alias dragAndDrop: dragAndDropImpl |
48 | + |
49 | + LocalTabs.DragAndDropSettings { |
50 | + id: dragAndDropImpl |
51 | + } |
52 | |
53 | property string fallbackIcon: "" |
54 | |
55 | + property Component windowFactory: null |
56 | + property var windowFactoryProperties: ({}) // any addition properties such as height, width |
57 | + |
58 | signal contextMenu(var tabDelegate, int index) |
59 | |
60 | function iconNameFromModelItem(modelItem, index) { |
61 | @@ -106,6 +133,7 @@ |
62 | right: tabs.overflow ? rightStepper.left : actions.left |
63 | } |
64 | interactive: false |
65 | + objectName: "tabListView" |
66 | orientation: ListView.Horizontal |
67 | clip: true |
68 | highlightMoveDuration: UbuntuAnimation.FastDuration |
69 | @@ -139,16 +167,21 @@ |
70 | model: tabsBar.model |
71 | delegate: MouseArea { |
72 | id: tabMouseArea |
73 | + objectName: "tabDelegate" |
74 | |
75 | + acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton |
76 | width: tab.width |
77 | height: tab.height |
78 | drag { |
79 | - target: tabs.count > 1 && tab.isFocused ? tab : null |
80 | - axis: Drag.XAxis |
81 | + target: (tabs.count > 1 || dragAndDrop.enabled) && tab.isFocused ? tab : null |
82 | + axis: dragAndDrop.enabled ? Drag.XAndYAxis : Drag.XAxis |
83 | minimumX: tab.isDragged ? -tab.width/2 : -Infinity |
84 | maximumX: tab.isDragged ? tabs.width - tab.width/2 : Infinity |
85 | } |
86 | z: tab.isFocused ? 1 : 0 |
87 | + |
88 | + readonly property int tabIndex: index // for autopilot |
89 | + |
90 | Binding { |
91 | target: tabsBar |
92 | property: "selectedTabX" |
93 | @@ -161,6 +194,13 @@ |
94 | value: tab.width |
95 | when: tab.isFocused |
96 | } |
97 | + NumberAnimation { |
98 | + id: resetVerticalAnimation |
99 | + target: tab |
100 | + duration: 250 |
101 | + property: "y" |
102 | + to: 0 |
103 | + } |
104 | |
105 | onPressed: { |
106 | if (mouse.button === Qt.LeftButton) { |
107 | @@ -171,6 +211,7 @@ |
108 | tabsBar.model.removeTab(index) |
109 | } |
110 | } |
111 | + onReleased: resetVerticalAnimation.start() |
112 | onWheel: { |
113 | if (wheel.angleDelta.y >= 0) { |
114 | tabsBar.model.selectTab(tabsBar.model.selectedIndex - 1); |
115 | @@ -183,12 +224,17 @@ |
116 | |
117 | LocalTabs.Tab { |
118 | id: tab |
119 | + objectName: "tabItem" |
120 | |
121 | anchors.left: tabMouseArea.left |
122 | implicitWidth: tabs.availableWidth / 2 |
123 | width: tabs.overflow ? tabs.availableWidth / tabs.maximumTabsCount : Math.min(tabs.maximumTabWidth, implicitWidth) |
124 | height: tabs.height |
125 | |
126 | + // Reference the tab and window so that the dropArea can determine what to do |
127 | + readonly property var thisTab: tabsBar.model.get(index) |
128 | + readonly property var thisWindow: dragAndDrop.thisWindow |
129 | + |
130 | property bool isDragged: tabMouseArea.drag.active |
131 | Drag.active: tab.isDragged |
132 | Drag.source: tabMouseArea |
133 | @@ -243,6 +289,67 @@ |
134 | } |
135 | } |
136 | } |
137 | + |
138 | + DragHelper { |
139 | + id: dragHelper |
140 | + expectedAction: dragAndDrop.expectedAction |
141 | + mimeType: dragAndDrop.mimeType |
142 | + previewBorderWidth: dragAndDrop.previewBorderWidth |
143 | + previewSize: dragAndDrop.previewSize |
144 | + previewTopCrop: dragAndDrop.previewTopCrop |
145 | + previewUrl: dragAndDrop.previewUrlFromIndex(index) |
146 | + source: tab |
147 | + } |
148 | + |
149 | + onPositionChanged: { |
150 | + if (!dragAndDrop.enabled || !tabMouseArea.drag.active) { |
151 | + return; |
152 | + } |
153 | + |
154 | + // Keep the visual tab within maxYDiff of starting point when |
155 | + // dragging vertically so that it doesn't cover other elements |
156 | + // or appear to be detached |
157 | + tab.y = Math.abs(tab.y) > dragAndDrop.maxYDiff ? (tab.y > 0 ? 1 : -1) * dragAndDrop.maxYDiff : tab.y |
158 | + |
159 | + // Initiate drag and drop if mouse y has gone further than the height from the object |
160 | + if (mouse.y > height * 2 || mouse.y < -height) { |
161 | + // Reset visual position of tab delegate |
162 | + resetVerticalAnimation.start(); |
163 | + |
164 | + var dropAction = dragHelper.execDrag(index); |
165 | + |
166 | + // IgnoreAction - no DropArea accepted so New Window |
167 | + // MoveAction - DropArea accept but different window |
168 | + // CopyAction - DropArea accept but same window |
169 | + |
170 | + if (dropAction === Qt.MoveAction) { |
171 | + // Moved into another window |
172 | + |
173 | + // Just remove from model and do not destroy |
174 | + // as webview is used in other window |
175 | + tabsBar.model.removeTabWithoutDestroying(index); |
176 | + } else if (dropAction === Qt.CopyAction) { |
177 | + // Moved into the same window |
178 | + |
179 | + // So no action |
180 | + } else if (dropAction === Qt.IgnoreAction) { |
181 | + // Moved outside of any window |
182 | + |
183 | + // Create new window and add existing tab |
184 | + var window = windowFactory.createObject(null, windowFactoryProperties); |
185 | + window.model.addExistingTab(tab.thisTab); |
186 | + window.model.selectTab(window.model.count - 1); |
187 | + window.show(); |
188 | + |
189 | + // Just remove from model and do not destroy |
190 | + // as webview is used in other window |
191 | + tabsBar.model.removeTabWithoutDestroying(index); |
192 | + } else { |
193 | + // Unknown state |
194 | + console.debug("Unknown drop action:", dropAction); |
195 | + } |
196 | + } |
197 | + } |
198 | } |
199 | } |
200 | |
201 | @@ -290,6 +397,7 @@ |
202 | model: tabsBar.actions |
203 | |
204 | LocalTabs.TabButton { |
205 | + objectName: modelData.objectName |
206 | iconColor: tabsBar.actionColor |
207 | iconSource: modelData.iconSource |
208 | onClicked: modelData.trigger() |
209 | @@ -303,6 +411,41 @@ |
210 | anchors.fill: parent |
211 | color: backgroundColor |
212 | opacity: 0.4 |
213 | - visible: !Window.active |
214 | + visible: !Window.active || (dimmed && !dropArea.containsDrag) |
215 | + } |
216 | + |
217 | + DropArea { |
218 | + id: dropArea |
219 | + anchors { |
220 | + fill: parent |
221 | + } |
222 | + keys: [dragAndDrop.mimeType] |
223 | + |
224 | + onDropped: { |
225 | + // IgnoreAction - no DropArea accepted so New Window |
226 | + // MoveAction - DropArea accept but different window |
227 | + // CopyAction - DropArea accept but same window |
228 | + if (drag.source.thisWindow === dragAndDrop.thisWindow) { |
229 | + // Dropped in same window |
230 | + drop.accept(Qt.CopyAction); |
231 | + } else { |
232 | + // Dropped in new window, moving tab |
233 | + tabsBar.model.addExistingTab(drag.source.thisTab); |
234 | + tabsBar.model.selectTab(tabsBar.model.count - 1); |
235 | + |
236 | + drop.accept(Qt.MoveAction); |
237 | + } |
238 | + } |
239 | + onEntered: { |
240 | + thisWindow.raise() |
241 | + thisWindow.requestActivate(); |
242 | + } |
243 | + onPositionChanged: { |
244 | + if (drag.source.thisWindow === dragAndDrop.thisWindow) { |
245 | + // tab drag is within same window and in chrome |
246 | + // so reorder tabs by setting tab x position |
247 | + drag.source.x = drag.x - (drag.source.width / 2); |
248 | + } |
249 | + } |
250 | } |
251 | } |
252 | |
253 | === added file 'modules/Ubuntu/Components/Extras/TabsBar/DragAndDropSettings.qml' |
254 | --- modules/Ubuntu/Components/Extras/TabsBar/DragAndDropSettings.qml 1970-01-01 00:00:00 +0000 |
255 | +++ modules/Ubuntu/Components/Extras/TabsBar/DragAndDropSettings.qml 2017-01-06 16:37:25 +0000 |
256 | @@ -0,0 +1,32 @@ |
257 | +/* |
258 | + * Copyright (C) 2016 Canonical Ltd |
259 | + * |
260 | + * This program is free software: you can redistribute it and/or modify |
261 | + * it under the terms of the GNU General Public License version 3 as |
262 | + * published by the Free Software Foundation. |
263 | + * |
264 | + * This program is distributed in the hope that it will be useful, |
265 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
266 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
267 | + * GNU General Public License for more details. |
268 | + * |
269 | + * You should have received a copy of the GNU General Public License |
270 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
271 | + * |
272 | + * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com> |
273 | + */ |
274 | +import QtQuick 2.4 |
275 | + |
276 | +QtObject { |
277 | + property bool enabled: false |
278 | + property var expectedAction: Qt.IgnoreAction | Qt.CopyAction | Qt.MoveAction |
279 | + property int maxYDiff: parent.height / 16 |
280 | + property string mimeType: "x-tabsbar/tab" |
281 | + property real previewBorderWidth: units.gu(1) |
282 | + property var previewSize: Qt.size(units.gu(35), units.gu(22.5)) |
283 | + property real previewTopCrop: 0 |
284 | + property var previewUrlFromIndex: function(index) { |
285 | + return ""; |
286 | + } |
287 | + property var thisWindow: null // Qt 5.7 retrieve from attached property |
288 | +} |
289 | |
290 | === modified file 'modules/Ubuntu/Components/Extras/TabsBar/Tab.qml' |
291 | --- modules/Ubuntu/Components/Extras/TabsBar/Tab.qml 2016-12-08 14:26:41 +0000 |
292 | +++ modules/Ubuntu/Components/Extras/TabsBar/Tab.qml 2017-01-06 16:37:25 +0000 |
293 | @@ -78,6 +78,7 @@ |
294 | |
295 | MouseArea { |
296 | id: tabCloseButton |
297 | + objectName: "tabCloseButton" |
298 | |
299 | anchors { |
300 | top: parent.top |
301 | |
302 | === modified file 'modules/Ubuntu/Components/Extras/plugin/CMakeLists.txt' |
303 | --- modules/Ubuntu/Components/Extras/plugin/CMakeLists.txt 2016-07-06 08:26:51 +0000 |
304 | +++ modules/Ubuntu/Components/Extras/plugin/CMakeLists.txt 2017-01-06 16:37:25 +0000 |
305 | @@ -19,12 +19,16 @@ |
306 | photoeditor/photo-edit-thread.cpp |
307 | ) |
308 | |
309 | +set(TABS_BAR_PLUGIN_SRC |
310 | + tabsbar/drag-helper.cpp |
311 | +) |
312 | + |
313 | include_directories( |
314 | ${CMAKE_BINARY_DIR} |
315 | ) |
316 | |
317 | add_library(ubuntu-ui-extras-plugin SHARED ${PLUGIN_SRC} ${PLUGIN_HDRS} |
318 | - ${EXAMPLE_PLUGIN_SRC} ${PHOTO_EDITOR_PLUGIN_SRC}) |
319 | + ${EXAMPLE_PLUGIN_SRC} ${PHOTO_EDITOR_PLUGIN_SRC} ${TABS_BAR_PLUGIN_SRC}) |
320 | qt5_use_modules(ubuntu-ui-extras-plugin Core Qml Quick Xml Widgets) |
321 | target_link_libraries(ubuntu-ui-extras-plugin |
322 | ${EXIV2_LIBRARIES} |
323 | |
324 | === modified file 'modules/Ubuntu/Components/Extras/plugin/components.cpp' |
325 | --- modules/Ubuntu/Components/Extras/plugin/components.cpp 2015-04-29 15:48:07 +0000 |
326 | +++ modules/Ubuntu/Components/Extras/plugin/components.cpp 2017-01-06 16:37:25 +0000 |
327 | @@ -1,5 +1,5 @@ |
328 | /* |
329 | - * Copyright (C) 2012-2013 Canonical, Ltd. |
330 | + * Copyright (C) 2012-2013, 2016 Canonical, Ltd. |
331 | * |
332 | * This program is free software; you can redistribute it and/or modify |
333 | * it under the terms of the GNU General Public License as published by |
334 | @@ -23,6 +23,8 @@ |
335 | #include "photoeditor/photo-image-provider.h" |
336 | #include "photoeditor/file-utils.h" |
337 | |
338 | +#include "tabsbar/drag-helper.h" |
339 | + |
340 | void Components::registerTypes(const char *uri) |
341 | { |
342 | // Example component |
343 | @@ -32,6 +34,9 @@ |
344 | qmlRegisterType<PhotoData>(uri, 0, 2, "PhotoData"); |
345 | qmlRegisterSingletonType<FileUtils>(uri, 0, 2, "FileUtils", |
346 | exportFileUtilsSingleton); |
347 | + |
348 | + // TabsBar component |
349 | + qmlRegisterType<DragHelper>(uri, 0, 3, "DragHelper"); |
350 | } |
351 | |
352 | void Components::initializeEngine(QQmlEngine *engine, const char *uri) |
353 | |
354 | === modified file 'modules/Ubuntu/Components/Extras/plugin/components.h' |
355 | --- modules/Ubuntu/Components/Extras/plugin/components.h 2014-11-19 10:14:20 +0000 |
356 | +++ modules/Ubuntu/Components/Extras/plugin/components.h 2017-01-06 16:37:25 +0000 |
357 | @@ -1,5 +1,5 @@ |
358 | /* |
359 | - * Copyright (C) 2012-2013 Canonical, Ltd. |
360 | + * Copyright (C) 2012-2013, 2016 Canonical, Ltd. |
361 | * |
362 | * This program is free software; you can redistribute it and/or modify |
363 | * it under the terms of the GNU General Public License as published by |
364 | |
365 | === added directory 'modules/Ubuntu/Components/Extras/plugin/tabsbar' |
366 | === added file 'modules/Ubuntu/Components/Extras/plugin/tabsbar/drag-helper.cpp' |
367 | --- modules/Ubuntu/Components/Extras/plugin/tabsbar/drag-helper.cpp 1970-01-01 00:00:00 +0000 |
368 | +++ modules/Ubuntu/Components/Extras/plugin/tabsbar/drag-helper.cpp 2017-01-06 16:37:25 +0000 |
369 | @@ -0,0 +1,205 @@ |
370 | +/* |
371 | + * Copyright 2016 Canonical Ltd. |
372 | + * |
373 | + * This file is part of webbrowser-app. |
374 | + * |
375 | + * webbrowser-app is free software; you can redistribute it and/or modify |
376 | + * it under the terms of the GNU General Public License as published by |
377 | + * the Free Software Foundation; version 3. |
378 | + * |
379 | + * webbrowser-app is distributed in the hope that it will be useful, |
380 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
381 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
382 | + * GNU General Public License for more details. |
383 | + * |
384 | + * You should have received a copy of the GNU General Public License |
385 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
386 | + * |
387 | + * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com> |
388 | + */ |
389 | + |
390 | +#include "drag-helper.h" |
391 | + |
392 | +#include <QtCore/QMimeData> |
393 | +#include <QtCore/QPoint> |
394 | +#include <QtCore/QSize> |
395 | +#include <QtCore/QString> |
396 | +#include <QtGui/QDrag> |
397 | +#include <QtGui/QDropEvent> |
398 | +#include <QtGui/QPainter> |
399 | +#include <QtGui/QPen> |
400 | +#include <QtGui/QPixmap> |
401 | +#include <QtQuick/QQuickItem> |
402 | + |
403 | +DragHelper::DragHelper() |
404 | + : QObject(), |
405 | + m_active(false), |
406 | + m_dragging(false), |
407 | + m_expected_action(Qt::IgnoreAction), |
408 | + m_mime_type(QStringLiteral("x-tabsbar/tab")), |
409 | + m_preview_border_width(8), |
410 | + m_preview_size(QSizeF(200, 150)), |
411 | + m_preview_top_crop(0), |
412 | + m_preview_url(""), |
413 | + m_source(Q_NULLPTR) |
414 | +{ |
415 | + |
416 | +} |
417 | + |
418 | +QPixmap DragHelper::drawPixmapWithBorder(QPixmap pixmap, int borderWidth, QColor color) |
419 | +{ |
420 | + // Create a transparent pixmap to draw to |
421 | + QPixmap output(pixmap.width() + borderWidth * 2, pixmap.height() + borderWidth * 2); |
422 | + output.fill(QColor(0, 0, 0, 0)); |
423 | + |
424 | + // Draw the pixmap with space around the edge for a border |
425 | + QPainter borderPainter(&output); |
426 | + borderPainter.setRenderHint(QPainter::Antialiasing); |
427 | + borderPainter.drawPixmap(borderWidth, borderWidth, pixmap); |
428 | + |
429 | + // Define a pen to use for the border |
430 | + QPen borderPen; |
431 | + borderPen.setColor(color); |
432 | + borderPen.setJoinStyle(Qt::MiterJoin); |
433 | + borderPen.setStyle(Qt::SolidLine); |
434 | + borderPen.setWidth(borderWidth); |
435 | + |
436 | + // Set the pen and draw the border |
437 | + borderPainter.setPen(borderPen); |
438 | + borderPainter.drawRect(borderWidth / 2, borderWidth / 2, |
439 | + output.width() - borderWidth, output.height() - borderWidth); |
440 | + |
441 | + return output; |
442 | +} |
443 | + |
444 | +Qt::DropAction DragHelper::execDrag(QString tabId) |
445 | +{ |
446 | + QDrag *drag = new QDrag(m_source); |
447 | + |
448 | + // Create a mimedata object to use for the drag |
449 | + QMimeData *mimeData = new QMimeData; |
450 | + mimeData->setData(mimeType(), tabId.toLatin1()); |
451 | + |
452 | + // Get a bordered pixmap of the previewUrl |
453 | + QSize size = previewSize().toSize(); |
454 | + |
455 | + QPixmap pixmap = drawPixmapWithBorder(getPreviewUrlAsPixmap(size.width(), size.height()), |
456 | + previewBorderWidth(), QColor(205, 205, 205, 255 * 0.6)); // #cdcdcd |
457 | + |
458 | + // Setup the drag and then execute it |
459 | + drag->setHotSpot(QPoint(size.width() * 0.1, size.height() * 0.1)); |
460 | + drag->setMimeData(mimeData); |
461 | + drag->setPixmap(pixmap); |
462 | + |
463 | + setDragging(true); |
464 | + |
465 | + Qt::DropAction action = drag->exec(expectedAction()); |
466 | + |
467 | + setDragging(false); |
468 | + |
469 | + return action; |
470 | +} |
471 | + |
472 | +QPixmap DragHelper::getPreviewUrlAsPixmap(int width, int height) |
473 | +{ |
474 | + QSize pixmapSize(width, height); |
475 | + QPixmap pixmap(previewUrl()); |
476 | + |
477 | + if (pixmap.isNull()) { |
478 | + // If loading pixmap failed, draw a white rectangle |
479 | + pixmap = QPixmap(pixmapSize); |
480 | + QPainter painter(&pixmap); |
481 | + painter.eraseRect(0, 0, pixmapSize.width(), pixmapSize.height()); |
482 | + painter.fillRect(0, 0, pixmapSize.width(), pixmapSize.height(), QColor(255, 255, 255, 255)); |
483 | + } else { |
484 | + // Crop transparent part off the top of the image |
485 | + pixmap = pixmap.copy(0, previewTopCrop(), pixmap.width(), pixmap.height() - previewTopCrop()); |
486 | + |
487 | + // Scale image to fit the expected size |
488 | + pixmap = pixmap.scaled(pixmapSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); |
489 | + } |
490 | + |
491 | + return pixmap; |
492 | +} |
493 | + |
494 | +void DragHelper::setActive(bool active) |
495 | +{ |
496 | + if (m_active != active) { |
497 | + m_active = active; |
498 | + |
499 | + Q_EMIT activeChanged(); |
500 | + } |
501 | +} |
502 | + |
503 | +void DragHelper::setDragging(bool dragging) |
504 | +{ |
505 | + if (m_dragging != dragging) { |
506 | + m_dragging = dragging; |
507 | + |
508 | + Q_EMIT draggingChanged(); |
509 | + } |
510 | +} |
511 | + |
512 | +void DragHelper::setExpectedAction(Qt::DropAction expectedAction) |
513 | +{ |
514 | + if (m_expected_action != expectedAction) { |
515 | + m_expected_action = expectedAction; |
516 | + |
517 | + Q_EMIT expectedActionChanged(); |
518 | + } |
519 | +} |
520 | + |
521 | +void DragHelper::setMimeType(QString mimeType) |
522 | +{ |
523 | + if (m_mime_type != mimeType) { |
524 | + m_mime_type = mimeType; |
525 | + |
526 | + Q_EMIT mimeTypeChanged(); |
527 | + } |
528 | +} |
529 | + |
530 | +void DragHelper::setPreviewBorderWidth(int previewBorderWidth) |
531 | +{ |
532 | + if (m_preview_border_width != previewBorderWidth) { |
533 | + m_preview_border_width = previewBorderWidth; |
534 | + |
535 | + Q_EMIT previewBorderWidthChanged(); |
536 | + } |
537 | +} |
538 | + |
539 | +void DragHelper::setPreviewSize(QSizeF previewSize) |
540 | +{ |
541 | + if (m_preview_size != previewSize) { |
542 | + m_preview_size = previewSize; |
543 | + |
544 | + Q_EMIT previewSizeChanged(); |
545 | + } |
546 | +} |
547 | + |
548 | +void DragHelper::setPreviewTopCrop(int previewTopCrop) |
549 | +{ |
550 | + if (m_preview_top_crop != previewTopCrop) { |
551 | + m_preview_top_crop = previewTopCrop; |
552 | + |
553 | + Q_EMIT previewTopCropChanged(); |
554 | + } |
555 | +} |
556 | + |
557 | +void DragHelper::setPreviewUrl(QString previewUrl) |
558 | +{ |
559 | + if (m_preview_url != previewUrl) { |
560 | + m_preview_url = previewUrl; |
561 | + |
562 | + Q_EMIT previewUrlChanged(); |
563 | + } |
564 | +} |
565 | + |
566 | +void DragHelper::setSource(QQuickItem *source) |
567 | +{ |
568 | + if (m_source != source) { |
569 | + m_source = source; |
570 | + |
571 | + Q_EMIT sourceChanged(); |
572 | + } |
573 | +} |
574 | + |
575 | |
576 | === added file 'modules/Ubuntu/Components/Extras/plugin/tabsbar/drag-helper.h' |
577 | --- modules/Ubuntu/Components/Extras/plugin/tabsbar/drag-helper.h 1970-01-01 00:00:00 +0000 |
578 | +++ modules/Ubuntu/Components/Extras/plugin/tabsbar/drag-helper.h 2017-01-06 16:37:25 +0000 |
579 | @@ -0,0 +1,93 @@ |
580 | +/* |
581 | + * Copyright 2016 Canonical Ltd. |
582 | + * |
583 | + * This file is part of webbrowser-app. |
584 | + * |
585 | + * webbrowser-app is free software; you can redistribute it and/or modify |
586 | + * it under the terms of the GNU General Public License as published by |
587 | + * the Free Software Foundation; version 3. |
588 | + * |
589 | + * webbrowser-app is distributed in the hope that it will be useful, |
590 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
591 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
592 | + * GNU General Public License for more details. |
593 | + * |
594 | + * You should have received a copy of the GNU General Public License |
595 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
596 | + * |
597 | + * Authored-by: Andrew Hayzen <andrew.hayzen@canonical.com> |
598 | + */ |
599 | + |
600 | +#ifndef __DRAGHELPER_H__ |
601 | +#define __DRAGHELPER_H__ |
602 | + |
603 | +#include <QtCore/QSizeF> |
604 | +#include <QtCore/QObject> |
605 | +#include <QtCore/QString> |
606 | +#include <QtGui/QColor> |
607 | +#include <QtGui/QMouseEvent> |
608 | + |
609 | +class QQuickItem; |
610 | + |
611 | +class DragHelper : public QObject |
612 | +{ |
613 | + Q_OBJECT |
614 | + |
615 | + Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged) |
616 | + Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged) |
617 | + Q_PROPERTY(Qt::DropAction expectedAction READ expectedAction WRITE setExpectedAction NOTIFY expectedActionChanged) |
618 | + Q_PROPERTY(QString mimeType READ mimeType WRITE setMimeType NOTIFY mimeTypeChanged) |
619 | + Q_PROPERTY(int previewBorderWidth READ previewBorderWidth WRITE setPreviewBorderWidth NOTIFY previewBorderWidthChanged) |
620 | + Q_PROPERTY(QSizeF previewSize READ previewSize WRITE setPreviewSize NOTIFY previewSizeChanged) |
621 | + Q_PROPERTY(int previewTopCrop READ previewTopCrop WRITE setPreviewTopCrop NOTIFY previewTopCropChanged) |
622 | + Q_PROPERTY(QString previewUrl READ previewUrl WRITE setPreviewUrl NOTIFY previewUrlChanged) |
623 | + Q_PROPERTY(QQuickItem* source READ source WRITE setSource NOTIFY sourceChanged) |
624 | +public: |
625 | + DragHelper(); |
626 | + bool active() { return m_active; } |
627 | + bool dragging() { return m_dragging; } |
628 | + Qt::DropAction expectedAction() { return m_expected_action; } |
629 | + QString mimeType() { return m_mime_type; } |
630 | + int previewBorderWidth() { return m_preview_border_width; } |
631 | + QSizeF previewSize() { return m_preview_size; } |
632 | + int previewTopCrop() { return m_preview_top_crop; } |
633 | + QString previewUrl() { return m_preview_url; } |
634 | + QQuickItem *source() { return m_source; } |
635 | +Q_SIGNALS: |
636 | + void activeChanged(); |
637 | + void draggingChanged(); |
638 | + void expectedActionChanged(); |
639 | + void mimeTypeChanged(); |
640 | + void previewBorderWidthChanged(); |
641 | + void previewSizeChanged(); |
642 | + void previewTopCropChanged(); |
643 | + void previewUrlChanged(); |
644 | + void sourceChanged(); |
645 | +public Q_SLOTS: |
646 | + Q_INVOKABLE Qt::DropAction execDrag(QString tabId); |
647 | + void setActive(bool active); |
648 | + void setExpectedAction(Qt::DropAction expectedAction); |
649 | + void setMimeType(QString mimeType); |
650 | + void setPreviewBorderWidth(int previewBorderWidth); |
651 | + void setPreviewSize(QSizeF previewSize); |
652 | + void setPreviewTopCrop(int previewTopCrop); |
653 | + void setPreviewUrl(QString previewUrl); |
654 | + void setSource(QQuickItem *source); |
655 | +private: |
656 | + QPixmap drawPixmapWithBorder(QPixmap pixmap, int borderWidth, QColor color); |
657 | + QPixmap getPreviewUrlAsPixmap(int width, int height); |
658 | + void setDragging(bool dragging); |
659 | + |
660 | + bool m_active; |
661 | + bool m_dragging; |
662 | + Qt::DropAction m_expected_action; |
663 | + QString m_mime_type; |
664 | + int m_preview_border_width; |
665 | + QSizeF m_preview_size; |
666 | + int m_preview_top_crop; |
667 | + QString m_preview_url; |
668 | + QQuickItem *m_source; |
669 | +}; |
670 | + |
671 | +#endif // __DRAGHELPER_H__ |
672 | + |
I wonder if it should be containsDrag)
visible: !Window.active || dimmed
or
visible: !Window.active || (dimmed && !dropArea.
For the Rectangle dimming the TabBar