on xenial help sign in
Derive apps scope from GenericScopeView
373a2c2Michal Hruby
Dash/DashApps.qml+35−125
@@ -19,155 +19,65 @@ import Ubuntu.Components 0.1
19import Utils 0.1
19import Utils 0.1
20import "../Components"
20import "../Components"
21import "../Components/ListItems"
21import "../Components/ListItems"
22+import "../Applications"
22import "Apps"
23import "Apps"
23
24
24−ScopeView {
25+GenericScopeView {
25 id: scopeView
26 id: scopeView
26
27
27 // FIXME: a way to aggregate these models would be ideal
28 // FIXME: a way to aggregate these models would be ideal
28 property var mainStageApplicationsModel: shell.applicationManager.mainStageApplications
29 property var mainStageApplicationsModel: shell.applicationManager.mainStageApplications
29 property var sideStageApplicationModel: shell.applicationManager.sideStageApplications
30 property var sideStageApplicationModel: shell.applicationManager.sideStageApplications
30
31
31− onMovementStarted: categoryView.showHeader()
32+ ListModel {
32− onPositionedAtBeginning: {
33+ id: frequentlyUsedAppsModel
33− if (isCurrent) {
34− categoryView.positionAtBeginning()
35− }
36− }
37−
38− onIsCurrentChanged: {
39− pageHeader.resetSearch();
40− }
41−
42− Binding {
43− target: scopeView.scope
44− property: "searchQuery"
45− value: pageHeader.searchQuery
46 }
34 }
47
35
48− Connections {
36+ FrequentlyUsedAppsModel { id: frequentlyUsedAppsBaseModel }
49− target: panel
50− onSearchClicked: if (isCurrent) {
51− pageHeader.triggerSearch()
52− categoryView.showHeader()
53− }
54− }
55
37
56− ListModel {
38+ Repeater {
57− id: categoryListModel
39+ model: frequentlyUsedAppsBaseModel
58− // specifies app categories, type of delegate and model used in each category
40+ delegate: Item {
59− ListElement { category: "Running apps"; component: "Apps/RunningApplicationsGrid.qml"; modelName: "RunningApplicationsModel" }
41+ Application {
60− ListElement { category: "Frequently used"; component: "Apps/ApplicationsFilterGrid.qml"; modelName: "FrequentlyUsedAppsModel" }
42+ id: application
61− ListElement { category: "Installed"; component: "Apps/ApplicationsFilterGrid.qml"; modelName: "InstalledApplicationsModel" }
43+ desktopFile: model.desktopFile
62− ListElement { category: "Available for download"; component: "Apps/ApplicationsFilterGrid.qml"; modelName: "AppsAvailableForDownloadModel" }
63− function getCategory(category1) {
64− if (category1 === "Running apps") {
65− return i18n.tr("Running apps");
66− }
67− if (category1 === "Frequently used") {
68− return i18n.tr("Frequently used");
69− }
70− if (category1 === "Installed") {
71− return i18n.tr("Installed");
72 }
44 }
73− if (category1 === "Available for download") {
45+ Component.onCompleted: {
74− return i18n.tr("Available for download");
46+ frequentlyUsedAppsModel.append({"uri": model.desktopFile, "icon": "../../graphics/applicationIcons/" + application.icon + ".png", "title": application.name, "dndUri": model.desktopFile});
75 }
47 }
76− return ""
77 }
48 }
78 }
49 }
79
50
80− FrequentlyUsedAppsModel { id: frequentlyUsedAppsModel }
51+ ListModel {
81− AppsAvailableForDownloadModel { id: appsAvailableForDownloadModel }
52+ id: appsAvailableForDownloadModel
53+ }
82
54
83− // FIXME this should not be needed, the backend should handle all that itself
55+ AppsAvailableForDownloadModel { id: appsAvailableForDownloadBaseModel }
84− property var installedModel: null
85
56
86 Repeater {
57 Repeater {
87− model: scopeView.scope.categories
58+ model: appsAvailableForDownloadBaseModel
88−
89 delegate: Item {
59 delegate: Item {
90− Component.onCompleted: if (categoryId == "installed") scopeView.installedModel = Qt.binding(function() { return model.results; });
60+ Application {
61+ id: application
62+ desktopFile: model.desktopFile
63+ }
64+ Component.onCompleted: {
65+ appsAvailableForDownloadModel.append({"uri": model.desktopFile, "icon": "../../graphics/applicationIcons/" + application.icon + ".png", "title": application.name, "dndUri": model.desktopFile});
66+ }
91 }
67 }
92 }
68 }
93
69
94− property var categoryModels: {
70+ ListModel {
95− "FrequentlyUsedAppsModel": frequentlyUsedAppsModel,
71+ id: runningApplicationsModel
96− "InstalledApplicationsModel": installedModel,
97− "AppsAvailableForDownloadModel": appsAvailableForDownloadModel,
98− }
99−
100− ScopeListView {
101− id: categoryView
102− anchors.fill: parent
103− model: SortFilterProxyModel {
104− model: categoryListModel
105− filterRole: 0 // 0 == modelName
106− // FIXME: need to use invertMatch here, otherwise the filter won't update correctly
107− // if filterRegExp is set before invertMatch. Bug in SortFilterProxyModel?
108− filterRegExp: invertMatch ? ((mainStageApplicationsModel.count === 0
109− && sideStageApplicationModel.count === 0) ? RegExp("RunningApplicationsModel") : RegExp("")) :
110− RegExp("InstalledApplicationsModel")
111− invertMatch: pageHeader.searchQuery.length == 0
112− }
113−
114− onAtYEndChanged: if (atYEnd) endReached()
115− onMovingChanged: if (moving && atYEnd) endReached()
116−
117− delegate: Base {
118− id: container
119− highlightWhenPressed: false
120−
121− Loader {
122− anchors {
123− top: parent.top
124− left: parent.left
125− right: parent.right
126− }
127− source: component
128− onLoaded: {
129− if (modelName == "RunningApplicationsModel") {
130− item.firstModel = mainStageApplicationsModel
131− item.secondModel = sideStageApplicationModel
132− item.canEnableTerminationMode =
133− Qt.binding(function() { return isCurrent; })
134− } else {
135− function activateApplication(index, data) {
136− shell.activateApplication(data);
137− }
138−
139− item.model = Qt.binding(function() { return categoryModels[modelName]; });
140− item.clicked.connect(activateApplication);
141−
142− }
143− }
144− }
145
72
146− ListView.onRemove: SequentialAnimation {
73+ property var firstModel: mainStageApplicationsModel
147− PropertyAction {
74+ property var secondModel: sideStageApplicationModel
148− target: container; property: "ListView.delayRemove"; value: true
75+ property bool canEnableTerminationMode: Qt.binding(function() { return isCurrent; })
149− }
150− NumberAnimation {
151− target: container; property: "height"; to: 0;
152− duration: 250; easing.type: Easing.InOutQuad
153− }
154− PropertyAction {
155− target: container; property: "ListView.delayRemove"; value: false
156− }
157− }
158− }
76+ }
159
77
160− sectionProperty: "category"
78+ onScopeChanged: {
161− sectionDelegate: Header {
79+ scopeView.scope.categories.overrideCategory("recently-used", frequentlyUsedAppsModel);
162− width: categoryView.width
80+ scopeView.scope.categories.overrideCategory("recent", runningApplicationsModel);
163− text: categoryListModel.getCategory(section)
81+ scopeView.scope.categories.overrideCategory("more", appsAvailableForDownloadModel);
164− }
165− pageHeader: PageHeader {
166− id: pageHeader
167− width: categoryView.width
168− text: i18n.tr("Apps")
169− searchEntryEnabled: true
170− searchHistory: scopeView.searchHistory
171− }
172 }
82 }
173}
83}
Dash/GenericScopeView.qml+5
@@ -132,6 +132,11 @@ ScopeView {
132 }
132 }
133 }
133 }
134 case "carousel": return "Generic/GenericCarousel.qml";
134 case "carousel": return "Generic/GenericCarousel.qml";
135+ case "special": {
136+ switch (contentType) {
137+ case "apps": return "Apps/RunningApplicationsGrid.qml";
138+ }
139+ }
135 default: return "Generic/GenericFilterGrid.qml";
140 default: return "Generic/GenericFilterGrid.qml";
136 }
141 }
137 }
142 }