@@ -1,567 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import Dash 0.1
19−import Ubuntu.Components 0.1
20−import "../Components"
21−
22−Item {
23− id: root
24−
25− // Properties set by parent
26− property real progress: 0
27− property var scope: null
28− property int currentIndex: 0
29− property real scopeScale: 1
30−
31− // Properties set and used by parent
32− property alias currentTab: tabBar.currentTab
33−
34− // Properties used by parent
35− readonly property bool processing: searchResultsViewer.processing || tempScopeItem.processing || previewListView.processing
36− property bool growingDashFromPos: false
37− readonly property bool searching: scope && scope.searchQuery == ""
38− readonly property bool showingNonFavoriteScope: tempScopeItem.scope != null
39− readonly property var dashItemEater: {
40− if (!forceXYScalerEater && tabBar.currentTab == 0 && middleItems.count > 0) {
41− var loaderItem = middleItems.itemAt(0).item;
42− return loaderItem && loaderItem.currentItem ? loaderItem.currentItem : null;
43− }
44− return scopesOverviewXYScaler;
45− }
46− readonly property size allCardSize: {
47− if (middleItems.count > 1) {
48− var loaderItem = middleItems.itemAt(1).item;
49− if (loaderItem) {
50− var cardTool = loaderItem.cardTool;
51− return Qt.size(cardTool.cardWidth, cardTool.cardHeight);
52− }
53− }
54− return Qt.size(0, 0);
55− }
56−
57− // Internal properties
58− property bool forceXYScalerEater: false
59−
60− signal done()
61− signal favoriteSelected(var scopeId)
62− signal allFavoriteSelected(var scopeId)
63− signal searchSelected(var scopeId, var result, var pos, var size)
64−
65− Connections {
66− target: scope
67− onOpenScope: {
68− var itemPos = scopesOverviewXYScaler.restorePosition;
69− var itemSize = scopesOverviewXYScaler.restoreSize;
70− scopesOverviewXYScaler.scale = itemSize.width / scopesOverviewXYScaler.width;
71− if (itemPos) {
72− scopesOverviewXYScaler.x = itemPos.x -(scopesOverviewXYScaler.width - scopesOverviewXYScaler.width * scopesOverviewXYScaler.scale) / 2;
73− scopesOverviewXYScaler.y = itemPos.y -(scopesOverviewXYScaler.height - scopesOverviewXYScaler.height * scopesOverviewXYScaler.scale) / 2;
74− } else {
75− scopesOverviewXYScaler.x = 0;
76− scopesOverviewXYScaler.y = 0;
77− }
78− scopesOverviewXYScaler.opacity = 0;
79− tempScopeItem.scope = scope;
80− middleItems.overrideOpacity = 0;
81− scopesOverviewXYScaler.scale = 1;
82− scopesOverviewXYScaler.x = 0;
83− scopesOverviewXYScaler.y = 0;
84− scopesOverviewXYScaler.opacity = 1;
85− }
86− onGotoScope: {
87− if (tabBar.currentTab == 0) {
88− root.favoriteSelected(scopeId);
89− } else {
90− root.allFavoriteSelected(scopeId);
91− }
92− }
93− }
94−
95− Binding {
96− target: scope
97− property: "isActive"
98− value: progress === 1
99− }
100−
101− function animateDashFromAll(scopeId) {
102− var currentScopePos = allScopeCardPosition(scopeId);
103− if (currentScopePos) {
104− showDashFromPos(currentScopePos, allCardSize);
105− } else {
106− console.log("Warning: Could not find Dash OverView All card position for scope", dashContent.currentScopeId);
107− }
108− }
109−
110− function showDashFromPos(itemPos, itemSize) {
111− scopesOverviewXYScaler.scale = itemSize.width / scopesOverviewXYScaler.width;
112− scopesOverviewXYScaler.x = itemPos.x -(scopesOverviewXYScaler.width - scopesOverviewXYScaler.width * scopesOverviewXYScaler.scale) / 2;
113− scopesOverviewXYScaler.y = itemPos.y -(scopesOverviewXYScaler.height - scopesOverviewXYScaler.height * scopesOverviewXYScaler.scale) / 2;
114− scopesOverviewXYScaler.opacity = 0;
115− root.growingDashFromPos = true;
116− scopesOverviewXYScaler.scale = 1;
117− scopesOverviewXYScaler.x = 0;
118− scopesOverviewXYScaler.y = 0;
119− scopesOverviewXYScaler.opacity = 1;
120− }
121−
122− function allScopeCardPosition(scopeId) {
123− if (middleItems.count > 1) {
124− var loaderItem = middleItems.itemAt(1).item;
125− if (loaderItem) {
126− var pos = loaderItem.scopeCardPosition(scopeId);
127− return loaderItem.mapToItem(null, pos.x, pos.y);
128− }
129− }
130− }
131−
132− function ensureAllScopeVisible(scopeId) {
133− if (middleItems.count > 1) {
134− var loaderItem = middleItems.itemAt(1).item;
135− if (loaderItem) {
136− var pos = loaderItem.scopeCardPosition(scopeId);
137− loaderItem.contentY = Math.min(pos.y, loaderItem.contentHeight - loaderItem.height);
138− }
139− }
140− }
141−
142− onProgressChanged: {
143− if (progress == 0) {
144− pageHeader.resetSearch();
145− pageHeader.unfocus(); // Shouldn't the previous call do this too?
146− }
147− }
148−
149− ScopeStyle {
150− id: overviewScopeStyle
151− style: { "foreground-color" : "white",
152− "background-color" : "transparent",
153− "page-header": {
154− "background": "color:///transparent"
155− }
156− }
157− }
158−
159− DashBackground {
160− anchors.fill: parent
161− source: "graphics/dark_background.jpg"
162− }
163−
164− Connections {
165− target: pageHeader
166− onSearchQueryChanged: {
167− // Need this in order, otherwise something gets unhappy in rendering
168− // of the overlay in carousels because the parent of the dash dies for
169− // a moment, this way we make sure it's reparented first
170− // by forceXYScalerEater making dashItemEater return scopesOverviewXYScaler
171− // before we kill the previous parent by scope.searchQuery
172− root.forceXYScalerEater = true;
173− root.scope.searchQuery = pageHeader.searchQuery;
174− root.forceXYScalerEater = false;
175− }
176− }
177−
178− Binding {
179− target: pageHeader
180− property: "searchQuery"
181− value: scope ? scope.searchQuery : ""
182− }
183−
184− Item {
185− id: scopesOverviewContent
186− x: previewListView.open ? -width : 0
187− Behavior on x { UbuntuNumberAnimation { } }
188− width: parent.width
189− height: parent.height
190−
191− PageHeader {
192− id: pageHeader
193− objectName: "scopesOverviewPageHeader"
194−
195− readonly property real yDisplacement: pageHeader.height + tabBar.height + tabBar.anchors.margins
196−
197− y: {
198− if (root.progress < 0.5) {
199− return -yDisplacement;
200− } else {
201− return -yDisplacement + (root.progress - 0.5) * yDisplacement * 2;
202− }
203− }
204− width: parent.width
205− clip: true
206− title: i18n.tr("Manage Dash")
207− scopeStyle: overviewScopeStyle
208− showSignatureLine: false
209− searchEntryEnabled: true
210− }
211−
212− ScopesOverviewTab {
213− id: tabBar
214− anchors {
215− left: parent.left
216− right: parent.right
217− top: pageHeader.bottom
218− margins: units.gu(2)
219− }
220− height: units.gu(4)
221−
222− enabled: opacity == 1
223− opacity: !scope || scope.searchQuery == "" ? 1 : 0
224− Behavior on opacity { UbuntuNumberAnimation { } }
225− }
226−
227− Repeater {
228− id: middleItems
229− objectName: "scopesOverviewRepeater"
230− property real overrideOpacity: -1
231− model: scope && scope.searchQuery == "" ? scope.categories : null
232− delegate: Loader {
233− id: loader
234− objectName: "scopesOverviewRepeaterChild" + index
235−
236− height: {
237− if (index == 0) {
238− return root.height;
239− } else {
240− return root.height - pageHeader.height - tabBar.height - tabBar.anchors.margins - units.gu(2);
241− }
242− }
243− width: {
244− if (index == 0) {
245− return root.width / scopeScale;
246− } else {
247− return root.width;
248− }
249− }
250− x: {
251− if (index == 0) {
252− return (root.width - width) / 2;
253− } else {
254− return 0;
255− }
256− }
257− anchors {
258− bottom: scopesOverviewContent.bottom
259− }
260−
261− scale: index == 0 ? scopeScale : 1
262−
263− opacity: {
264− if (middleItems.overrideOpacity >= 0)
265− return middleItems.overrideOpacity;
266−
267− if (tabBar.currentTab != index)
268− return 0;
269−
270− return index == 0 ? 1 : root.progress;
271− }
272− Behavior on opacity {
273− enabled: root.progress == 1
274− UbuntuNumberAnimation { }
275− }
276− enabled: opacity == 1
277−
278− clip: index == 1
279−
280− CardTool {
281− id: cardTool
282− objectName: "cardTool"
283− count: results.count
284− template: model.renderer
285− components: model.components
286− viewWidth: parent.width
287− }
288−
289− source: {
290− if (index == 0 && categoryId == "favorites") return "ScopesOverviewFavorites.qml";
291− else if (index == 1 && categoryId == "all") return "ScopesOverviewAll.qml";
292− else return "";
293− }
294−
295− onLoaded: {
296− item.model = Qt.binding(function() { return results; });
297− item.cardTool = cardTool;
298− if (index == 0) {
299− item.scopeWidth = Qt.binding(function() { return root.width; });
300− item.scopeHeight = Qt.binding(function() { return root.height; });
301− item.appliedScale = Qt.binding(function() { return loader.scale });
302− item.currentIndex = Qt.binding(function() { return root.currentIndex });
303− } else if (index == 1) {
304− item.extraHeight = bottomBar.height;
305− }
306− }
307−
308− Connections {
309− target: loader.item
310− onClicked: {
311− pageHeader.unfocus();
312− if (tabBar.currentTab == 0) {
313− root.favoriteSelected(itemModel.scopeId);
314− } else {
315− var favoriteScopesItem = middleItems.itemAt(0).item;
316− var scopeIndex = favoriteScopesItem.model.scopeIndex(itemModel.scopeId);
317− if (scopeIndex >= 0) {
318− root.allFavoriteSelected(itemModel.scopeId);
319− } else {
320− // Will result in an openScope from root.scope
321− scopesOverviewXYScaler.restorePosition = item.mapToItem(null, 0, 0);
322− scopesOverviewXYScaler.restoreSize = allCardSize;
323− root.scope.activate(result);
324− }
325− }
326− }
327− onPressAndHold: {
328− // Preview can call openScope so make sure restorePosition and restoreSize are set
329− scopesOverviewXYScaler.restorePosition = undefined;
330− scopesOverviewXYScaler.restoreSize = allCardSize;
331−
332− previewListView.model = target.model;
333− previewListView.currentIndex = -1;
334− previewListView.currentIndex = index;
335− previewListView.open = true;
336− }
337− }
338− }
339− }
340−
341− GenericScopeView {
342− id: searchResultsViewer
343− objectName: "searchResultsViewer"
344− anchors {
345− top: pageHeader.bottom
346− right: parent.right
347− left: parent.left
348− bottom: parent.bottom
349− }
350− scope: root.scope && root.scope.searchQuery != "" ? root.scope : null
351− scopeStyle: overviewScopeStyle
352− enabled: opacity == 1
353− showPageHeader: false
354− clip: true
355− opacity: searchResultsViewer.scope ? 1 : 0
356− isCurrent: true
357− Behavior on opacity { UbuntuNumberAnimation { } }
358−
359− function itemClicked(index, result, item, itemModel, resultsModel, limitedCategoryItemCount) {
360− pageHeader.unfocus();
361− pageHeader.closePopup();
362− if (itemModel.scopeId) {
363− // This can end up in openScope so save restorePosition and restoreSize
364− scopesOverviewXYScaler.restorePosition = item.mapToItem(null, 0, 0);
365− scopesOverviewXYScaler.restoreSize = Qt.size(item.width, item.height);
366− root.searchSelected(itemModel.scopeId, result, item.mapToItem(null, 0, 0), Qt.size(item.width, item.height));
367− } else {
368− // Not a scope, just activate it
369− searchResultsViewer.scope.activate(result);
370− }
371− }
372−
373− function itemPressedAndHeld(index, itemModel, resultsModel, limitedCategoryItemCount) {
374− if (itemModel.uri.indexOf("scope://") === 0) {
375− // Preview can call openScope so make sure restorePosition and restoreSize are set
376− scopesOverviewXYScaler.restorePosition = undefined;
377− scopesOverviewXYScaler.restoreSize = allCardSize;
378−
379− previewListView.model = resultsModel;
380− previewListView.currentIndex = -1;
381− previewListView.currentIndex = index;
382− previewListView.open = true;
383− }
384− }
385− }
386−
387− Rectangle {
388− id: bottomBar
389− objectName: "bottomBar"
390− color: "black"
391− height: units.gu(8)
392− width: parent.width
393− enabled: opacity == 1
394− opacity: scope && scope.searchQuery == "" ? 1 : 0
395− Behavior on opacity { UbuntuNumberAnimation { } }
396− y: {
397− if (root.progress < 0.5) {
398− return parent.height;
399− } else {
400− return parent.height - (root.progress - 0.5) * height * 2;
401− }
402− }
403−
404− MouseArea {
405− // Just eat any other press since this parent is black opaque
406− anchors.fill: parent
407− }
408−
409− AbstractButton {
410− objectName: "scopesOverviewDoneButton"
411− width: Math.max(label.width + units.gu(2), units.gu(10))
412− height: units.gu(4)
413− anchors {
414− left: parent.left
415− leftMargin: units.gu(2)
416− verticalCenter: parent.verticalCenter
417− }
418− Rectangle {
419− anchors.fill: parent
420− border.color: "white"
421− border.width: units.dp(1)
422− radius: units.dp(10)
423− color: parent.pressed ? Theme.palette.normal.baseText : "transparent"
424− }
425− Label {
426− id: label
427− anchors.centerIn: parent
428− text: i18n.tr("Done")
429− color: parent.pressed ? "black" : "white"
430− }
431− onClicked: root.done();
432− }
433−
434− AbstractButton {
435− objectName: "scopesOverviewStoreButton"
436− width: Math.max(storeLabel.width, units.gu(10))
437− height: units.gu(4)
438− anchors {
439− right: parent.right
440− verticalCenter: parent.verticalCenter
441− }
442− Icon {
443− id: storeImage
444− name: "ubuntu-store-symbolic"
445− color: "white"
446− anchors.horizontalCenter: parent.horizontalCenter
447− width: units.gu(2)
448− height: units.gu(2)
449− }
450− Label {
451− id: storeLabel
452− anchors.horizontalCenter: parent.horizontalCenter
453− anchors.top: storeImage.bottom
454− text: i18n.tr("Store")
455− color: "white"
456− }
457− onClicked: {
458− // Just zoom from the middle
459− scopesOverviewXYScaler.restorePosition = undefined;
460− scopesOverviewXYScaler.restoreSize = allCardSize;
461− scope.performQuery("scope://com.canonical.scopes.clickstore");
462− }
463− }
464− }
465− }
466−
467− PreviewListView {
468− id: previewListView
469− objectName: "scopesOverviewPreviewListView"
470− scope: root.scope
471− scopeStyle: overviewScopeStyle
472− showSignatureLine: false
473− visible: x != width
474− width: parent.width
475− height: parent.height
476− anchors.left: scopesOverviewContent.right
477−
478− onBackClicked: open = false
479− }
480−
481− Item {
482− id: scopesOverviewXYScaler
483− width: parent.width
484− height: parent.height
485−
486− clip: scale != 1.0
487− enabled: scale == 1
488−
489− property bool animationsEnabled: root.showingNonFavoriteScope || root.growingDashFromPos
490−
491− property var restorePosition
492− property var restoreSize
493−
494− Behavior on x {
495− enabled: scopesOverviewXYScaler.animationsEnabled
496− UbuntuNumberAnimation { }
497− }
498− Behavior on y {
499− enabled: scopesOverviewXYScaler.animationsEnabled
500− UbuntuNumberAnimation { }
501− }
502− Behavior on opacity {
503− enabled: scopesOverviewXYScaler.animationsEnabled
504− UbuntuNumberAnimation { }
505− }
506− Behavior on scale {
507− enabled: scopesOverviewXYScaler.animationsEnabled
508− UbuntuNumberAnimation {
509− onRunningChanged: {
510− if (!running) {
511− if (root.showingNonFavoriteScope && scopesOverviewXYScaler.scale != 1) {
512− root.scope.closeScope(tempScopeItem.scope);
513− tempScopeItem.scope = null;
514− } else if (root.growingDashFromPos) {
515− root.growingDashFromPos = false;
516− }
517− }
518− }
519− }
520− }
521−
522− DashBackground {
523− anchors.fill: tempScopeItem
524− visible: tempScopeItem.visible
525− parent: tempScopeItem.parent
526− }
527−
528− GenericScopeView {
529− id: tempScopeItem
530− objectName: "scopesOverviewTempScopeItem"
531−
532− width: parent.width
533− height: parent.height
534− scale: dash.contentScale
535− clip: scale != 1.0
536− visible: scope != null
537− hasBackAction: true
538− isCurrent: visible
539− onBackClicked: {
540− var v = scopesOverviewXYScaler.restoreSize.width / tempScopeItem.width;
541− scopesOverviewXYScaler.scale = v;
542− if (scopesOverviewXYScaler.restorePosition) {
543− scopesOverviewXYScaler.x = scopesOverviewXYScaler.restorePosition.x -(tempScopeItem.width - tempScopeItem.width * v) / 2;
544− scopesOverviewXYScaler.y = scopesOverviewXYScaler.restorePosition.y -(tempScopeItem.height - tempScopeItem.height * v) / 2;
545− } else {
546− scopesOverviewXYScaler.x = 0;
547− scopesOverviewXYScaler.y = 0;
548− }
549− scopesOverviewXYScaler.opacity = 0;
550− middleItems.overrideOpacity = -1;
551− }
552− // TODO Add tests for these connections
553− Connections {
554− target: tempScopeItem.scope
555− onOpenScope: {
556− // TODO Animate the newly opened scope into the foreground (stacked on top of the current scope)
557− tempScopeItem.scope = scope;
558− }
559− onGotoScope: {
560− tempScopeItem.backClicked();
561− root.currentTab = 0;
562− root.scope.gotoScope(scopeId);
563− }
564− }
565− }
566− }
567−}