on xenial help sign in
merge trunk
commitdd024c800ef840eb50706a172d40ef50dd5c1b23 authorMichael Zanetti <michael.zanetti@canonical.com> dateMon 8 Jul 2013, 15:46 (13 years ago) parent113a11d1e59aa1
39 files changed+808−480
Dash/Apps/RunningApplicationsGrid.qml+1 Dash/DashApps.qml+11−22 Dash/DashHome.qml+12−25 Dash/DashMusic.qml+3−10 Dash/DashVideos.qml+3−10 Dash/GenericScopeView.qml+2−2 Greeter/Infographics.qml+1−1 cmake/modules/Plugins.cmake+48 debian/changelog+19 plugins/HudClient/CMakeLists.txt+5−12 plugins/HudClient/qmldir+1 plugins/LightDM/CMakeLists.txt+5−12 plugins/LightDM/qmldir+1 plugins/ListViewWithPageHeader/CMakeLists.txt+5−12 plugins/ListViewWithPageHeader/qmldir+1 plugins/Ubuntu/Gestures/CMakeLists.txt+5−13 plugins/Ubuntu/Gestures/qmldir+1 plugins/Unity/CMakeLists.txt+6−17 plugins/Unity/categories.cpp+56−42 plugins/Unity/categories.h+13−16 plugins/Unity/categoryfilter.cpp−45 plugins/Unity/categoryfilter.h−48 plugins/Unity/categoryresults.cpp+96 plugins/Unity/categoryresults.h+67 plugins/Unity/plugin.cpp+2−2 plugins/Unity/qmldir+1 plugins/Unity/scope.cpp+19−57 plugins/Unity/scope.h+8−12 plugins/Utils/CMakeLists.txt+2−12 plugins/Utils/qmldir+1 po/sl.po+11−17 tests/mocks/Unity/CMakeLists.txt+2−3 tests/mocks/Unity/fake_categories.cpp+178 tests/mocks/Unity/fake_categories.h+69 tests/mocks/Unity/fake_scope.cpp+104−73 tests/mocks/Unity/fake_scope.h+43−11 tests/mocks/Unity/fake_unity_plugin.cpp+3−3 tests/plugins/Unity/CMakeLists.txt+1−1 tests/qmltests/Dash/qml/FakeScopeView.qml+2−2
Dash/Apps/RunningApplicationsGrid.qml+1
@@ -19,6 +19,7 @@ import "../../Components"
1919
2020ResponsiveFlowView {
2121 id: root
22+ clip: true
2223
2324 signal updateScreenshots
2425
Dash/DashApps.qml+11−22
@@ -56,10 +56,10 @@ ScopeView {
5656 ListModel {
5757 id: categoryListModel
5858 // specifies app categories, type of delegate and model used in each category
59− ListElement { category: "Running apps"; component: "RunningApplicationsGrid"; modelName: "RunningApplicationsModel" }
60− ListElement { category: "Frequently used"; component: "ApplicationsFilterGrid"; modelName: "FrequentlyUsedAppsModel" }
61− ListElement { category: "Installed"; component: "ApplicationsFilterGrid"; modelName: "InstalledApplicationsModel" }
62− ListElement { category: "Available for download"; component: "ApplicationsFilterGrid"; modelName: "AppsAvailableForDownloadModel" }
59+ ListElement { category: "Running apps"; component: "Apps/RunningApplicationsGrid.qml"; modelName: "RunningApplicationsModel" }
60+ ListElement { category: "Frequently used"; component: "Apps/ApplicationsFilterGrid.qml"; modelName: "FrequentlyUsedAppsModel" }
61+ ListElement { category: "Installed"; component: "Apps/ApplicationsFilterGrid.qml"; modelName: "InstalledApplicationsModel" }
62+ ListElement { category: "Available for download"; component: "Apps/ApplicationsFilterGrid.qml"; modelName: "AppsAvailableForDownloadModel" }
6363 function getCategory(category1) {
6464 if (category1 === "Running apps") {
6565 return i18n.tr("Running apps");
@@ -95,23 +95,6 @@ ScopeView {
9595 "AppsAvailableForDownloadModel": appsAvailableForDownloadModel,
9696 }
9797
98− /* Workaround for bug: https://bugreports.qt-project.org/browse/QTBUG-28403
99− When using Loader to load external QML file in the list deelgate, the ListView has
100− a bug where it can position the delegate content to overlap the section header
101− of the ListView - a workaround is to use sourceComponent of Loader instead */
102− Component { id: runningApplicationsGrid; RunningApplicationsGrid { clip: true } }
103− Component {
104− id: applicationsFilterGrid;
105− ApplicationsFilterGrid {
106− onClicked: shell.activateApplication(data)
107− }
108− }
109−
110− property var componentModels: {
111− "RunningApplicationsGrid": runningApplicationsGrid,
112− "ApplicationsFilterGrid": applicationsFilterGrid,
113− }
114−
11598 ScopeListView {
11699 id: categoryView
117100 anchors.fill: parent
@@ -139,7 +122,7 @@ ScopeView {
139122 left: parent.left
140123 right: parent.right
141124 }
142− sourceComponent: componentModels[component]
125+ source: component
143126 onLoaded: {
144127 if (modelName == "RunningApplicationsModel") {
145128 item.firstModel = mainStageApplicationsModel
@@ -147,7 +130,13 @@ ScopeView {
147130 item.canEnableTerminationMode =
148131 Qt.binding(function() { return isCurrent; })
149132 } else {
133+ function activateApplication(index, data) {
134+ shell.activateApplication(data);
135+ }
136+
150137 item.model = categoryModels[modelName]
138+ item.clicked.connect(activateApplication);
139+
151140 }
152141 }
153142 }
Dash/DashHome.qml+12−25
@@ -32,9 +32,9 @@ ScopeView {
3232 ListModel {
3333 id: categoryListModel
3434 // specifies page's content categories, type of delegate and model used in each category
35− ListElement { category: "Frequent Apps"; component: "AppsGrid"; modelName: "AppsModel" }
36− ListElement { category: "Recent Music"; component: "MusicGrid"; modelName: "MusicModel" }
37− ListElement { category: "Videos Popular Online"; component: "VideosGrid"; modelName: "VideosModel" }
35+ ListElement { category: "Frequent Apps"; component: "Apps/ApplicationsFilterGrid.qml"; modelName: "AppsModel" }
36+ ListElement { category: "Recent Music"; component: "Music/MusicFilterGrid.qml"; modelName: "MusicModel" }
37+ ListElement { category: "Videos Popular Online"; component: "Video/VideosFilterGrid.qml"; modelName: "VideosModel" }
3838 function getCategory(category1) {
3939 if (category1 === "Frequent Apps") {
4040 return i18n.tr("Frequent Apps");
@@ -110,26 +110,6 @@ ScopeView {
110110 "VideosModel": videosFilter,
111111 }
112112
113− /* Workaround for bug: https://bugreports.qt-project.org/browse/QTBUG-28403
114− When using Loader to load external QML file in the list deelgate, the ListView has
115− a bug where it can position the delegate content to overlap the section header
116− of the ListView - a workaround is to use sourceComponent of Loader instead */
117− Component {
118− id: applicationsFilterGrid
119− ApplicationsFilterGrid {
120− objectName: "dashHomeApplicationsGrid"
121− onClicked: shell.activateApplication(data);
122− }
123− }
124−
125− Component { id: musicGrid; MusicFilterGrid {} }
126− Component { id: videosGrid; VideosFilterGrid {} }
127− property var componentModels: {
128− "AppsGrid": applicationsFilterGrid,
129− "MusicGrid": musicGrid,
130− "VideosGrid": videosGrid,
131− }
132−
133113 ScopeListView {
134114 id: listView
135115 anchors.fill: parent
@@ -145,13 +125,13 @@ ScopeView {
145125
146126 Loader {
147127 anchors { top: parent.top; left: parent.left; right: parent.right }
148− sourceComponent: componentModels[component]
128+ source: component
149129 onLoaded: {
150130 item.model = categoryModels[modelName]
151131
152132 //FIXME: workaround for lack of previews for videos in Home scope.
153133 //Need to connect to the clicked() signal here and act upon it here instead.
154− if (component === "VideosGrid") {
134+ if (modelName === "VideosModel") {
155135 function playVideo(index, data) {
156136 if (data.fileUri) {
157137 shell.activateApplication('/usr/share/applications/mediaplayer-app.desktop', "/usr/share/demo-assets/videos/" + data.fileUri);
@@ -159,6 +139,13 @@ ScopeView {
159139 }
160140
161141 item.clicked.connect(playVideo);
142+ } else if (modelName === "AppsModel") {
143+ function activateApplication(index, data) {
144+ shell.activateApplication(data);
145+ }
146+
147+ item.objectName = "dashHomeApplicationsGrid";
148+ item.clicked.connect(activateApplication);
162149 }
163150 }
164151 }
Dash/DashMusic.qml+3−10
@@ -50,17 +50,10 @@ ScopeView {
5050 }
5151 }
5252
53− /* Workaround for bug: https://bugreports.qt-project.org/browse/QTBUG-28403
54− When using Loader to load external QML file in the list deelgate, the ListView has
55− a bug where it can position the delegate content to overlap the section header
56− of the ListView - a workaround is to use sourceComponent of Loader instead */
57− Component { id: musicCarousel; MusicCarousel {} }
58− Component { id: musicFilterGrid; MusicFilterGrid {} }
59−
6053 function getRenderer(categoryId) {
6154 switch (categoryId) {
62− case 1: return musicCarousel
63− default: return musicFilterGrid
55+ case 1: return "Music/MusicCarousel.qml"
56+ default: return "Music/MusicFilterGrid.qml"
6457 }
6558 }
6659
@@ -80,7 +73,7 @@ ScopeView {
8073
8174 Loader {
8275 anchors { top: parent.top; left: parent.left; right: parent.right }
83− sourceComponent: scopeView.getRenderer(base.categoryId)
76+ source: scopeView.getRenderer(base.categoryId)
8477 onLoaded: {
8578 item.model = results
8679 }
Dash/DashVideos.qml+3−10
@@ -51,17 +51,10 @@ ScopeView {
5151 }
5252 }
5353
54− /* Workaround for bug: https://bugreports.qt-project.org/browse/QTBUG-28403
55− When using Loader to load external QML file in the list deelgate, the ListView has
56− a bug where it can position the delegate content to overlap the section header
57− of the ListView - a workaround is to use sourceComponent of Loader instead */
58− Component { id: videosFilterGrid; VideosFilterGrid {} }
59− Component { id: videosCarousel; VideosCarousel {} }
60−
6154 function getRenderer(categoryId) {
6255 switch (categoryId) {
63− case 1: return videosCarousel
64− default: return videosFilterGrid
56+ case 1: return "Video/VideosCarousel.qml"
57+ default: return "Video/VideosFilterGrid.qml"
6558 }
6659 }
6760
@@ -115,7 +108,7 @@ ScopeView {
115108 Loader {
116109 id: loader
117110 anchors { top: parent.top; left: parent.left; right: parent.right }
118− sourceComponent: scopeView.getRenderer(base.categoryId)
111+ source: scopeView.getRenderer(base.categoryId)
119112 onLoaded: {
120113 item.model = results
121114 }
Dash/GenericScopeView.qml+2−2
@@ -72,10 +72,10 @@ ScopeView {
7272 delegate: Tile {
7373 width: filtergrid.cellWidth
7474 height: filtergrid.cellHeight
75− text: column_5 ? column_5 : "" // FIXME: this shouldn't be necessary
75+ text: title
7676 imageWidth: units.gu(11)
7777 imageHeight: units.gu(16)
78− source: column_1 ? IconUtil.from_gicon(column_1) : "" // FIXME: ditto
78+ source: IconUtil.from_gicon(icon)
7979 }
8080 }
8181 }
Greeter/Infographics.qml+1−1
@@ -81,7 +81,7 @@ Item {
8181 var nextCircle = presentCircles.itemAt(presentCircleCounter++)
8282 if (nextCircle !== null) nextCircle.presentCircleGrowAnim.start()
8383 }
84− if (presentCircleCounter > infographic.model.currentDay) {
84+ if (presentCircleCounter > infographic.model.currentDay && pastCircleCounter >= pastCircles.count) {
8585 stop()
8686 }
8787 }
cmake/modules/Plugins.cmakenew file+48
@@ -0,0 +1,48 @@
1+# Creates targets for copying and installing qmlfiles and generating the qmltypes file for a plugin
2+#
3+# export_qmlplugin(plugin version sub_path [TARGETS target1 [target2 ...]])
4+#
5+# TARGETS additional install targets (eg the plugin shared object)
6+#
7+# Two targets will be created:
8+# - plugin-qmlfiles - Copies the qml files (*.qml, *.js, qmldir) into the shadow build folder.
9+# - plugin-qmltypes - Generates the qmltypes file in the shadow build folder.
10+
11+
12+macro(export_qmlplugin PLUGIN VERSION PLUGIN_SUBPATH)
13+ set(multi_value_keywords TARGETS)
14+ cmake_parse_arguments(qmlplugin "" "" "${multi_value_keywords}" ${ARGN})
15+
16+ file(GLOB QMLFILES
17+ *.qml
18+ *.js
19+ qmldir
20+ )
21+
22+ # copy the qmldir file
23+ add_custom_target(${PLUGIN}-qmlfiles ALL
24+ COMMAND cp ${QMLFILES} ${CMAKE_BINARY_DIR}/plugins/${PLUGIN_SUBPATH}
25+ DEPENDS ${QMLFILES}
26+ )
27+
28+ # create the plugin.qmltypes file
29+ add_custom_target(${PLUGIN}-qmltypes ALL
30+ COMMAND qmlplugindump -notrelocatable ${PLUGIN} ${VERSION} ${CMAKE_BINARY_DIR}/plugins > ${CMAKE_BINARY_DIR}/plugins/${PLUGIN_SUBPATH}/plugin.qmltypes
31+ )
32+ add_dependencies(${PLUGIN}-qmltypes ${PLUGIN}-qmlfiles ${qmlplugin_TARGETS})
33+
34+ # install the qmldir file.
35+ install(FILES ${QMLFILES}
36+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/${PLUGIN_SUBPATH}
37+ )
38+
39+ # install the qmltypes file.
40+ install(FILES ${CMAKE_BINARY_DIR}/plugins/${PLUGIN_SUBPATH}/plugin.qmltypes
41+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/${PLUGIN_SUBPATH}
42+ )
43+
44+ # install the additional targets
45+ install(TARGETS ${qmlplugin_TARGETS}
46+ DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/${PLUGIN_SUBPATH}
47+ )
48+endmacro(export_qmlplugin)
debian/changelog+19
@@ -1,3 +1,22 @@
1+unity8 (7.81.3+13.10.20130708ubuntu.unity.next-0ubuntu1) saucy; urgency=low
2+
3+ [ Michael Terry ]
4+ * Ensure the past circle animations complete Currently, all the
5+ animations stop as soon as the present circles are all visible. This
6+ change ensures that the animations run to completion.
7+
8+ [ Michael Zanetti ]
9+ * improve launcher flicking bahavior - fix initial snapping - improve
10+ foldingAreas behavior - increase clickFlick speed to flick 4 items.
11+
12+ [ Albert Astals ]
13+ * Remove workarounds for Qt bug 28403 . (LP: #28403)
14+
15+ [ Ubuntu daily release ]
16+ * Automatic snapshot from revision 83 (ubuntu-unity/next)
17+
18+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Mon, 08 Jul 2013 02:34:23 +0000
19+
120unity8 (7.81.3+13.10.20130704ubuntu.unity.next-0ubuntu1) saucy; urgency=low
221
322 [ Didier Roche ]
plugins/HudClient/CMakeLists.txt+5−12
@@ -1,3 +1,6 @@
1+# export_qmlplugin macro
2+include(Plugins)
3+
14find_package(Qt5Core REQUIRED)
25find_package(Qt5Quick REQUIRED)
36pkg_search_module(DEE dee-1.0 REQUIRED)
@@ -35,15 +38,5 @@ target_link_libraries(HudClientQml
3538
3639qt5_use_modules(HudClientQml Qml)
3740
38−# copy qmldir file into build directory for shadow builds
39−file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
40− DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
41− )
42−
43−install(TARGETS HudClientQml
44− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/HudClient
45− )
46−
47−install(FILES qmldir
48− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/HudClient
49− )
41+# export the qmldir and qmltypes files
42+export_qmlplugin(HudClient 0.1 HudClient TARGETS HudClientQml)
plugins/HudClient/qmldir+1
@@ -1 +1,2 @@
11plugin HudClientQml
2+typeinfo plugin.qmltypes
plugins/LightDM/CMakeLists.txt+5−12
@@ -1,3 +1,6 @@
1+# export_qmlplugin macro
2+include(Plugins)
3+
14# Dependencies
25include(FindPkgConfig)
36pkg_check_modules(LIBUSERMETRICSOUTPUT REQUIRED libusermetricsoutput-1)
@@ -32,15 +35,5 @@ target_link_libraries(LightDM-qml
3235
3336qt5_use_modules(LightDM-qml Gui Qml)
3437
35−# copy qmldir file into build directory for shadow builds
36−file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
37− DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
38− )
39−
40−install(TARGETS LightDM-qml
41− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/LightDM
42− )
43−
44−install(FILES qmldir
45− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/LightDM
46− )
38+# export the qmldir and qmltypes files
39+export_qmlplugin(LightDM 0.1 LightDM TARGETS LightDM-qml)
plugins/LightDM/qmldir+1
@@ -1,2 +1,3 @@
11module LightDM
22plugin LightDM-qml
3+typeinfo plugin.qmltypes
plugins/ListViewWithPageHeader/CMakeLists.txt+5−12
@@ -1,3 +1,6 @@
1+# export_qmlplugin macro
2+include(Plugins)
3+
14# There's no cmake var for v8 include path :-/
25# so create one
36LIST(GET Qt5Core_INCLUDE_DIRS 0 QtCoreDir0)
@@ -30,15 +33,5 @@ target_link_libraries(ListViewWithPageHeader-qml
3033
3134qt5_use_modules(ListViewWithPageHeader-qml Qml Quick)
3235
33−# copy qmldir file into build directory for shadow builds
34−file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
35− DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
36− )
37−
38−install(TARGETS ListViewWithPageHeader-qml
39− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/ListViewWithPageHeader
40− )
41−
42−install(FILES qmldir
43− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/ListViewWithPageHeader
44− )
36+# export the qmldir and qmltypes files
37+export_qmlplugin(ListViewWithPageHeader 0.1 ListViewWithPageHeader TARGETS ListViewWithPageHeader-qml)
plugins/ListViewWithPageHeader/qmldir+1
@@ -1,2 +1,3 @@
11module ListViewWithPageHeader
22plugin ListViewWithPageHeader-qml
3+typeinfo plugin.qmltypes
plugins/Ubuntu/Gestures/CMakeLists.txt+5−13
@@ -1,3 +1,6 @@
1+# export_qmlplugin macro
2+include(Plugins)
3+
14set(CMAKE_AUTOMOC ON)
25
36include(FindPkgConfig)
@@ -20,16 +23,5 @@ qt5_use_modules(UbuntuGestureQml Core Quick)
2023# So that Foo.cpp can #include "Foo.moc"
2124include_directories(${CMAKE_CURRENT_BINARY_DIR})
2225
23−# copy files into build directory for shadow builds
24−add_custom_target(UbuntuGestureQmlDirFile ALL
25− COMMAND cp "${CMAKE_CURRENT_SOURCE_DIR}/qmldir" ${CMAKE_CURRENT_BINARY_DIR}
26− DEPENDS qmldir
27−)
28−
29−install(TARGETS UbuntuGestureQml
30− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Ubuntu/Gestures
31− )
32−
33−install(FILES qmldir
34− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Ubuntu/Gestures
35− )
26+# export the qmldir and qmltypes files
27+export_qmlplugin(Ubuntu.Gestures 0.1 Ubuntu/Gestures TARGETS UbuntuGestureQml)
plugins/Ubuntu/Gestures/qmldir+1
@@ -1,2 +1,3 @@
11module Ubuntu.Gestures
22plugin UbuntuGestureQml
3+typeinfo plugin.qmltypes
plugins/Unity/CMakeLists.txt+6−17
@@ -1,3 +1,6 @@
1+# export_qmlplugin macro
2+include(Plugins)
3+
14# Dependencies
25include(FindPkgConfig)
36pkg_check_modules(QTDEE REQUIRED libdee-qt5)
@@ -12,11 +15,10 @@ include_directories(
1215)
1316
1417set(QMLPLUGIN_SRC
15− ../Utils/qsortfilterproxymodelqml.cpp # FIXME evaluate a more generic approach for using other plugins
1618 scope.cpp
1719 scopes.cpp
1820 categories.cpp
19− categoryfilter.cpp
21+ categoryresults.cpp
2022 plugin.cpp
2123 bottombarvisibilitycommunicatorshell.cpp
2224 applicationpreview.cpp
@@ -42,18 +44,5 @@ target_link_libraries(Unity-qml
4244
4345qt5_use_modules(Unity-qml Qml)
4446
45−# copy qmldir file into build directory for shadow builds
46−file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
47− DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
48− )
49−
50−install(TARGETS Unity-qml
51− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Unity
52− )
53−
54−install(FILES qmldir
55− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Unity
56− )
57−
58−
59−add_subdirectory(Launcher)
47+# export the qmldir and qmltypes files
48+export_qmlplugin(Unity 0.1 Unity TARGETS Unity-qml)
plugins/Unity/categories.cpp+56−42
@@ -3,6 +3,7 @@
33 *
44 * Authors:
55 * Michał Sawicz <michal.sawicz@canonical.com>
6+ * Michal Hruby <michal.hruby@canonical.com>
67 *
78 * This program is free software; you can redistribute it and/or modify
89 * it under the terms of the GNU General Public License as published by
@@ -19,18 +20,25 @@
1920
2021// self
2122#include "categories.h"
22−#include "categoryfilter.h"
23+#include "categoryresults.h"
24+
25+// TODO: use something from libunity once it's public
26+enum CategoryColumn {
27+ ID,
28+ DISPLAY_NAME,
29+ ICON_HINT,
30+ RENDERER_NAME,
31+ HINTS
32+};
2333
2434Categories::Categories(QObject* parent)
2535 : DeeListModel(parent)
26− , m_resultModel(0)
2736{
28− // FIXME: need to clean up unused filters on countChanged
2937 m_roles[Categories::RoleId] = "id";
3038 m_roles[Categories::RoleName] = "name";
3139 m_roles[Categories::RoleIcon] = "icon";
3240 m_roles[Categories::RoleRenderer] = "renderer";
33− m_roles[Categories::RoleContentType] = "content_type";
41+ m_roles[Categories::RoleContentType] = "contentType";
3442 m_roles[Categories::RoleHints] = "hints";
3543 m_roles[Categories::RoleResults] = "results";
3644 m_roles[Categories::RoleCount] = "count";
@@ -40,49 +48,57 @@ Categories::Categories(QObject* parent)
4048 // change of the search term harder to reproduce
4149 m_timer.setSingleShot(true);
4250 m_timer.setInterval(50);
43− connect(&m_timer, SIGNAL(timeout()), this, SLOT(onEmitCountChanged()));
51+ connect(&m_timer, &QTimer::timeout, this, &Categories::onEmitCountChanged);
4452}
4553
46−Categories::~Categories()
54+DeeListModel*
55+Categories::getResults(int index) const
4756{
48− qDeleteAll(m_filters);
49−}
57+ if (!m_results.contains(index)) {
58+ CategoryResults* results = new CategoryResults(const_cast<Categories*>(this));
59+ results->setCategoryIndex(index);
60+ connect(results, &DeeListModel::countChanged, this, &Categories::onCountChanged);
5061
51−CategoryFilter*
52−Categories::getFilter(int index) const
53−{
54− if (!m_filters.contains(index)) {
55− CategoryFilter* filter = new CategoryFilter();
56− connect(filter, SIGNAL(countChanged()), this, SLOT(onCountChanged()));
57− filter->setModel(m_resultModel);
58− filter->setIndex(index);
62+ unsigned categoryIndex = static_cast<unsigned>(index);
63+ auto unity_results = m_unityScope->GetResultsForCategory(categoryIndex);
64+ results->setModel(unity_results->model());
5965
60− m_filters.insert(index, filter);
66+ m_results.insert(index, results);
6167 }
6268
63− return m_filters[index];
69+ return m_results[index];
70+}
71+
72+void Categories::onCategoriesModelChanged(unity::glib::Object<DeeModel> model)
73+{
74+ m_updatedCategories.clear();
75+ // FIXME: this might destroy the renderer view and re-create it, optimize?
76+ Q_FOREACH(DeeListModel* model, m_results) {
77+ delete model;
78+ }
79+ m_results.clear();
80+ setModel(model);
6481}
6582
6683void
67−Categories::setResultModel(DeeListModel* model)
84+Categories::setUnityScope(const unity::dash::Scope::Ptr& scope)
6885{
69− if (model != m_resultModel) {
70− m_resultModel = model;
86+ m_unityScope = scope;
7187
72− Q_FOREACH(CategoryFilter* filter, m_filters) {
73− filter->setModel(m_resultModel);
74− }
88+ // no need to call this, we'll get notified
89+ //setModel(m_unityScope->categories()->model());
7590
76− Q_EMIT resultModelChanged(m_resultModel);
77− }
91+ m_categoriesChangedConnection.disconnect();
92+ m_categoriesChangedConnection =
93+ m_unityScope->categories()->model.changed.connect(sigc::mem_fun(this, &Categories::onCategoriesModelChanged));
7894}
7995
8096void
8197Categories::onCountChanged()
8298{
83− CategoryFilter* filter = qobject_cast<CategoryFilter*>(sender());
84− if (filter) {
85− m_timerFilters << filter;
99+ CategoryResults* results = qobject_cast<CategoryResults*>(sender());
100+ if (results) {
101+ m_updatedCategories << results->categoryIndex();
86102 m_timer.start();
87103 }
88104}
@@ -92,11 +108,12 @@ Categories::onEmitCountChanged()
92108{
93109 QVector<int> roles;
94110 roles.append(Categories::RoleCount);
95− Q_FOREACH(CategoryFilter* filter, m_timerFilters) {
96− QModelIndex changedIndex = index(filter->index());
111+ Q_FOREACH(int categoryIndex, m_updatedCategories) {
112+ if (!m_results.contains(categoryIndex)) continue;
113+ QModelIndex changedIndex = index(categoryIndex);
97114 Q_EMIT dataChanged(changedIndex, changedIndex, roles);
98115 }
99− m_timerFilters.clear();
116+ m_updatedCategories.clear();
100117}
101118
102119QHash<int, QByteArray>
@@ -116,25 +133,22 @@ Categories::data(const QModelIndex& index, int role) const
116133 case RoleId:
117134 return QVariant::fromValue(index.row());
118135 case RoleName:
119− return QVariant::fromValue(DeeListModel::data(index, 1)); //DISPLAY_NAME
136+ return DeeListModel::data(index, CategoryColumn::DISPLAY_NAME);
120137 case RoleIcon:
121− return QVariant::fromValue(DeeListModel::data(index, 2)); //ICON_HINT
138+ return DeeListModel::data(index, CategoryColumn::ICON_HINT);
122139 case RoleRenderer:
123− return QVariant::fromValue(DeeListModel::data(index, 3)); //RENDERER_NAME
140+ return DeeListModel::data(index, CategoryColumn::RENDERER_NAME);
124141 case RoleContentType:
125142 {
126− auto hints = QVariant::fromValue(DeeListModel::data(index, 4)).toHash();
143+ auto hints = DeeListModel::data(index, CategoryColumn::HINTS).toHash();
127144 return hints.contains("content-type") ? hints["content-type"] : QVariant(QString("default"));
128145 }
129146 case RoleHints:
130− return QVariant::fromValue(DeeListModel::data(index, 4)); //HINTS
147+ return DeeListModel::data(index, CategoryColumn::HINTS);
131148 case RoleResults:
132− return QVariant::fromValue(getFilter(index.row()));
149+ return QVariant::fromValue(getResults(index.row()));
133150 case RoleCount:
134− {
135− CategoryFilter* filter = getFilter(index.row());
136− return QVariant::fromValue(filter->rowCount());
137− }
151+ return QVariant::fromValue(getResults(index.row())->rowCount());
138152 default:
139153 return QVariant();
140154 }
plugins/Unity/categories.h+13−16
@@ -3,6 +3,7 @@
33 *
44 * Authors:
55 * Michał Sawicz <michal.sawicz@canonical.com>
6+ * Michal Hruby <michal.hruby@canonical.com>
67 *
78 * This program is free software; you can redistribute it and/or modify
89 * it under the terms of the GNU General Public License as published by
@@ -21,25 +22,24 @@
2122#ifndef CATEGORIES_H
2223#define CATEGORIES_H
2324
25+// unity-core
26+#include <UnityCore/Scope.h>
27+
2428// dee-qt
2529#include "deelistmodel.h"
2630
31+#include <QPointer>
2732#include <QSet>
2833#include <QTimer>
2934
30−class CategoryFilter;
31−
3235class Categories : public DeeListModel
3336{
3437 Q_OBJECT
3538
3639 Q_ENUMS(Roles)
3740
38− Q_PROPERTY(DeeListModel* resultModel READ resultModel WRITE setResultModel NOTIFY resultModelChanged)
39−
4041public:
4142 explicit Categories(QObject* parent = 0);
42− ~Categories();
4343
4444 enum Roles {
4545 RoleId,
@@ -56,27 +56,24 @@ public:
5656
5757 QHash<int, QByteArray> roleNames() const;
5858
59− /* getters */
60− DeeListModel* resultModel() { return m_resultModel; }
61−
6259 /* setters */
63− void setResultModel(DeeListModel*);
64−
65−Q_SIGNALS:
66− void resultModelChanged(DeeListModel*);
60+ void setUnityScope(const unity::dash::Scope::Ptr& scope);
6761
6862private Q_SLOTS:
6963 void onCountChanged();
7064 void onEmitCountChanged();
7165
7266private:
73− CategoryFilter* getFilter(int index) const;
67+ void onCategoriesModelChanged(unity::glib::Object<DeeModel> model);
68+
69+ DeeListModel* getResults(int index) const;
7470
71+ unity::dash::Scope::Ptr m_unityScope;
7572 QTimer m_timer;
76− QSet<CategoryFilter*> m_timerFilters;
73+ QSet<int> m_updatedCategories;
7774 QHash<int, QByteArray> m_roles;
78− DeeListModel* m_resultModel;
79− mutable QMap<int, CategoryFilter*> m_filters;
75+ mutable QMap<int, DeeListModel*> m_results;
76+ sigc::connection m_categoriesChangedConnection;
8077};
8178
8279#endif // CATEGORIES_H
plugins/Unity/categoryfilter.cppdeleted−45
@@ -1,45 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Michał Sawicz <michal.sawicz@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#include "categoryfilter.h"
21−
22−int const CATEGORY_COLUMN = 2;
23−
24−CategoryFilter::CategoryFilter(QObject* parent)
25− : QSortFilterProxyModelQML(parent)
26− , m_index(-1)
27−{
28− setDynamicSortFilter(true);
29− setFilterRole(CATEGORY_COLUMN);
30− setFilterRegExp(QString("^%1$").arg(m_index));
31−}
32−
33−int CategoryFilter::index() const
34−{
35− return m_index;
36−}
37−
38−void CategoryFilter::setIndex(int index)
39−{
40− if (index != m_index) {
41− m_index = index;
42− setFilterRegExp(QString("^%1$").arg(m_index));
43− Q_EMIT indexChanged(m_index);
44− }
45−}
plugins/Unity/categoryfilter.hdeleted−48
@@ -1,48 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * Authors:
5− * Michał Sawicz <michal.sawicz@canonical.com>
6− *
7− * This program is free software; you can redistribute it and/or modify
8− * it under the terms of the GNU General Public License as published by
9− * the Free Software Foundation; version 3.
10− *
11− * This program is distributed in the hope that it will be useful,
12− * but WITHOUT ANY WARRANTY; without even the implied warranty of
13− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14− * GNU General Public License for more details.
15− *
16− * You should have received a copy of the GNU General Public License
17− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18− */
19−
20−#ifndef CATEGORY_FILTER_H
21−#define CATEGORY_FILTER_H
22−
23−// Utils
24−#include "plugins/Utils/qsortfilterproxymodelqml.h"
25−
26−class CategoryFilter : public QSortFilterProxyModelQML
27−{
28− Q_OBJECT
29−
30− Q_PROPERTY(int index READ index WRITE setIndex NOTIFY indexChanged)
31−
32−public:
33− explicit CategoryFilter(QObject* parent = 0);
34−
35− /* getters */
36− int index() const;
37−
38− /* setters */
39− void setIndex(int index);
40−
41−Q_SIGNALS:
42− void indexChanged(int index);
43−
44−private:
45− int m_index;
46−};
47−
48−#endif // CATEGORY_FILTER_H
plugins/Unity/categoryresults.cppnew file+96
@@ -0,0 +1,96 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Michal Hruby <michal.hruby@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+// self
21+#include "categoryresults.h"
22+
23+// TODO: use something from libunity once it's public
24+enum ResultsColumn {
25+ URI,
26+ ICON_HINT,
27+ CATEGORY,
28+ RESULT_TYPE,
29+ MIMETYPE,
30+ TITLE,
31+ COMMENT,
32+ DND_URI,
33+ METADATA
34+};
35+
36+CategoryResults::CategoryResults(QObject* parent)
37+ : DeeListModel(parent)
38+ , m_categoryIndex(-1)
39+{
40+ m_roles[CategoryResults::RoleUri] = "uri";
41+ m_roles[CategoryResults::RoleIconHint] = "icon";
42+ m_roles[CategoryResults::RoleCategory] = "category";
43+ m_roles[CategoryResults::RoleMimetype] = "mimetype";
44+ m_roles[CategoryResults::RoleTitle] = "title";
45+ m_roles[CategoryResults::RoleComment] = "comment";
46+ m_roles[CategoryResults::RoleDndUri] = "dndUri";
47+ m_roles[CategoryResults::RoleMetadata] = "metadata";
48+}
49+
50+int CategoryResults::categoryIndex() const
51+{
52+ return m_categoryIndex;
53+}
54+
55+void CategoryResults::setCategoryIndex(int index)
56+{
57+ if (m_categoryIndex != index) {
58+ m_categoryIndex = index;
59+ Q_EMIT categoryIndexChanged(m_categoryIndex);
60+ }
61+}
62+
63+QHash<int, QByteArray>
64+CategoryResults::roleNames() const
65+{
66+ return m_roles;
67+}
68+
69+QVariant
70+CategoryResults::data(const QModelIndex& index, int role) const
71+{
72+ if (!index.isValid()) {
73+ return QVariant();
74+ }
75+
76+ switch (role) {
77+ case RoleUri:
78+ return DeeListModel::data(index, ResultsColumn::URI);
79+ case RoleIconHint:
80+ return DeeListModel::data(index, ResultsColumn::ICON_HINT);
81+ case RoleCategory:
82+ return DeeListModel::data(index, ResultsColumn::CATEGORY);
83+ case RoleMimetype:
84+ return DeeListModel::data(index, ResultsColumn::MIMETYPE);
85+ case RoleTitle:
86+ return DeeListModel::data(index, ResultsColumn::TITLE);
87+ case RoleComment:
88+ return DeeListModel::data(index, ResultsColumn::COMMENT);
89+ case RoleDndUri:
90+ return DeeListModel::data(index, ResultsColumn::DND_URI);
91+ case RoleMetadata:
92+ return DeeListModel::data(index, ResultsColumn::METADATA);
93+ default:
94+ return QVariant();
95+ }
96+}
plugins/Unity/categoryresults.hnew file+67
@@ -0,0 +1,67 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Michal Hruby <michal.hruby@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+
21+#ifndef CATEGORY_RESULTS_H
22+#define CATEGORY_RESULTS_H
23+
24+// dee-qt
25+#include "deelistmodel.h"
26+
27+class CategoryResults : public DeeListModel
28+{
29+ Q_OBJECT
30+
31+ Q_ENUMS(Roles)
32+
33+ Q_PROPERTY(int categoryIndex READ categoryIndex WRITE setCategoryIndex NOTIFY categoryIndexChanged)
34+
35+public:
36+ explicit CategoryResults(QObject* parent = 0);
37+
38+ enum Roles {
39+ RoleUri,
40+ RoleIconHint,
41+ RoleCategory,
42+ RoleMimetype,
43+ RoleTitle,
44+ RoleComment,
45+ RoleDndUri,
46+ RoleMetadata
47+ };
48+
49+ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
50+
51+ QHash<int, QByteArray> roleNames() const;
52+
53+ /* getters */
54+ int categoryIndex() const;
55+
56+ /* setters */
57+ void setCategoryIndex(int index);
58+
59+Q_SIGNALS:
60+ void categoryIndexChanged(int index);
61+
62+private:
63+ QHash<int, QByteArray> m_roles;
64+ int m_categoryIndex;
65+};
66+
67+#endif // CATEGORY_RESULTS_H
plugins/Unity/plugin.cpp+2−2
@@ -30,7 +30,7 @@
3030#include "scope.h"
3131#include "scopes.h"
3232#include "categories.h"
33−#include "categoryfilter.h"
33+#include "categoryresults.h"
3434#include "bottombarvisibilitycommunicatorshell.h"
3535
3636// libqtdee
@@ -48,7 +48,7 @@ void UnityPlugin::registerTypes(const char *uri)
4848 qmlRegisterType<Scope>(uri, 0, 1, "Scope");
4949 qmlRegisterType<Scopes>(uri, 0, 1, "Scopes");
5050 qmlRegisterType<Categories>(uri, 0, 1, "Categories");
51− qmlRegisterType<CategoryFilter>(uri, 0, 1, "CategoryFilter");
51+ qmlRegisterUncreatableType<CategoryResults>(uri, 0, 1, "CategoryResults", "Can't create new Category Results in QML. Get them from Categories instance.");
5252 qmlRegisterType<DeeListModel>(uri, 0, 1, "DeeListModel");
5353 qmlRegisterUncreatableType<BottomBarVisibilityCommunicatorShell>(uri, 0, 1, "BottomBarVisibilityCommunicatorShell", "Can't create BottomBarVisibilityCommunicatorShell");
5454}
plugins/Unity/qmldir+1
@@ -1,2 +1,3 @@
11module Unity
22plugin Unity-qml
3+typeinfo plugin.qmltypes
plugins/Unity/scope.cpp+19−57
@@ -3,6 +3,7 @@
33 *
44 * Authors:
55 * Florian Boucault <florian.boucault@canonical.com>
6+ * Michal Hruby <michal.hruby@canonical.com>
67 *
78 * This program is free software; you can redistribute it and/or modify
89 * it under the terms of the GNU General Public License as published by
@@ -38,10 +39,7 @@
3839Scope::Scope(QObject *parent) :
3940 QObject(parent)
4041{
41− m_results = new DeeListModel(this);
42− m_categories = new Categories(this);
43−
44− m_categories->setResultModel(m_results);
42+ m_categories.reset(new Categories(this));
4543}
4644
4745QString Scope::id() const
@@ -84,14 +82,9 @@ bool Scope::connected() const
8482 return m_unityScope->connected();
8583}
8684
87−DeeListModel* Scope::results() const
88−{
89− return m_results;
90−}
91−
9285Categories* Scope::categories() const
9386{
94− return m_categories;
87+ return m_categories.get();
9588}
9689
9790QString Scope::searchQuery() const
@@ -104,6 +97,11 @@ QString Scope::noResultsHint() const
10497 return m_noResultsHint;
10598}
10699
100+QString Scope::formFactor() const
101+{
102+ return m_formFactor;
103+}
104+
107105void Scope::setSearchQuery(const QString& search_query)
108106{
109107 /* Checking for m_searchQuery.isNull() which returns true only when the string
@@ -125,6 +123,15 @@ void Scope::setNoResultsHint(const QString& hint) {
125123 }
126124}
127125
126+void Scope::setFormFactor(const QString& form_factor) {
127+ if (form_factor != m_formFactor) {
128+ m_formFactor = form_factor;
129+ if (m_unityScope) {
130+ m_unityScope->form_factor = m_formFactor.toStdString();
131+ }
132+ Q_EMIT formFactorChanged();
133+ }
134+}
128135
129136unity::dash::LocalResult Scope::createLocalResult(const QVariant &uri, const QVariant &icon_hint,
130137 const QVariant &category, const QVariant &result_type,
@@ -237,18 +244,9 @@ void Scope::setUnityScope(const unity::dash::Scope::Ptr& scope)
237244{
238245 m_unityScope = scope;
239246
240− if (QString::fromStdString(m_unityScope->results()->swarm_name) == QString(":local")) {
241− m_results->setModel(m_unityScope->results()->model());
242− } else {
243− m_results->setName(QString::fromStdString(m_unityScope->results()->swarm_name));
244− }
245−
246− if (QString::fromStdString(m_unityScope->categories()->swarm_name) == QString(":local")) {
247− m_categories->setModel(m_unityScope->categories()->model());
248− } else {
249− m_categories->setName(QString::fromStdString(m_unityScope->categories()->swarm_name));
250− }
247+ m_categories->setUnityScope(m_unityScope);
251248
249+ m_unityScope->form_factor = m_formFactor.toStdString();
252250 /* Property change signals */
253251 m_unityScope->id.changed.connect(sigc::mem_fun(this, &Scope::idChanged));
254252 m_unityScope->name.changed.connect(sigc::mem_fun(this, &Scope::nameChanged));
@@ -258,12 +256,6 @@ void Scope::setUnityScope(const unity::dash::Scope::Ptr& scope)
258256 m_unityScope->visible.changed.connect(sigc::mem_fun(this, &Scope::visibleChanged));
259257 m_unityScope->shortcut.changed.connect(sigc::mem_fun(this, &Scope::shortcutChanged));
260258 m_unityScope->connected.changed.connect(sigc::mem_fun(this, &Scope::connectedChanged));
261− m_unityScope->results.changed.connect(sigc::mem_fun(this, &Scope::onResultsChanged));
262− m_unityScope->results()->swarm_name.changed.connect(sigc::mem_fun(this, &Scope::onResultsSwarmNameChanged));
263− m_unityScope->results()->model.changed.connect(sigc::mem_fun(this, &Scope::onResultsModelChanged));
264− m_unityScope->categories()->model.changed.connect(sigc::mem_fun(this, &Scope::onCategoriesModelChanged));
265− m_unityScope->categories.changed.connect(sigc::mem_fun(this, &Scope::onCategoriesChanged));
266− m_unityScope->categories()->swarm_name.changed.connect(sigc::mem_fun(this, &Scope::onCategoriesSwarmNameChanged));
267259 /* Signals forwarding */
268260 connect(this, SIGNAL(searchFinished(const std::string &, unity::glib::HintsMap const &, unity::glib::Error const &)), SLOT(onSearchFinished(const std::string &, unity::glib::HintsMap const &)));
269261
@@ -294,36 +286,6 @@ void Scope::synchronizeStates()
294286 }
295287}
296288
297−void Scope::onResultsSwarmNameChanged(const std::string& /* swarm_name */)
298−{
299− m_results->setName(QString::fromStdString(m_unityScope->results()->swarm_name));
300−}
301−
302−void Scope::onResultsChanged(const unity::dash::Results::Ptr& /* results */)
303−{
304− m_results->setName(QString::fromStdString(m_unityScope->results()->swarm_name));
305−}
306−
307−void Scope::onResultsModelChanged(unity::glib::Object<DeeModel> /* model */)
308−{
309− m_results->setModel(m_unityScope->results()->model());
310−}
311−
312−void Scope::onCategoriesSwarmNameChanged(const std::string& /* swarm_name */)
313−{
314− m_categories->setName(QString::fromStdString(m_unityScope->categories()->swarm_name));
315−}
316−
317−void Scope::onCategoriesChanged(const unity::dash::Categories::Ptr& /* categories */)
318−{
319− m_categories->setName(QString::fromStdString(m_unityScope->categories()->swarm_name));
320−}
321−
322−void Scope::onCategoriesModelChanged(unity::glib::Object<DeeModel> model)
323−{
324− m_categories->setModel(model);
325−}
326−
327289void Scope::onSearchFinished(const std::string& /* query */, unity::glib::HintsMap const &hints)
328290{
329291 QString hint;
plugins/Unity/scope.h+8−12
@@ -32,7 +32,8 @@
3232// dee-qt
3333#include "deelistmodel.h"
3434
35−class Categories;
35+#include "categories.h"
36+
3637class Preview;
3738
3839class Scope : public QObject
@@ -47,11 +48,11 @@ class Scope : public QObject
4748 Q_PROPERTY(bool visible READ visible NOTIFY visibleChanged)
4849 Q_PROPERTY(QString shortcut READ shortcut NOTIFY shortcutChanged)
4950 Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged)
50− Q_PROPERTY(DeeListModel* results READ results NOTIFY resultsChanged)
5151 Q_PROPERTY(Categories* categories READ categories NOTIFY categoriesChanged)
5252
5353 Q_PROPERTY(QString searchQuery READ searchQuery WRITE setSearchQuery NOTIFY searchQueryChanged)
5454 Q_PROPERTY(QString noResultsHint READ noResultsHint WRITE setNoResultsHint NOTIFY noResultsHintChanged)
55+ Q_PROPERTY(QString formFactor READ formFactor WRITE setFormFactor NOTIFY formFactorChanged)
5556
5657public:
5758 explicit Scope(QObject *parent = 0);
@@ -65,14 +66,15 @@ public:
6566 bool visible() const;
6667 QString shortcut() const;
6768 bool connected() const;
68− DeeListModel* results() const;
6969 Categories* categories() const;
7070 QString searchQuery() const;
7171 QString noResultsHint() const;
72+ QString formFactor() const;
7273
7374 /* setters */
7475 void setSearchQuery(const QString& search_query);
7576 void setNoResultsHint(const QString& hint);
77+ void setFormFactor(const QString& form_factor);
7678
7779 Q_INVOKABLE void activate(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
7880 const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
@@ -94,11 +96,11 @@ Q_SIGNALS:
9496 void visibleChanged(bool);
9597 void shortcutChanged(const std::string&);
9698 void connectedChanged(bool);
97− void resultsChanged();
9899 void categoriesChanged();
99100 void searchFinished(const std::string&, unity::glib::HintsMap const&, unity::glib::Error const&);
100101 void searchQueryChanged();
101102 void noResultsHintChanged();
103+ void formFactorChanged();
102104
103105 // signals triggered by activate(..) or preview(..) requests.
104106 void previewReady(Preview *preview);
@@ -111,12 +113,6 @@ private Q_SLOTS:
111113 void onSearchFinished(const std::string &, unity::glib::HintsMap const &);
112114
113115private:
114− void onResultsSwarmNameChanged(const std::string&);
115− void onResultsChanged(const unity::dash::Results::Ptr&);
116− void onResultsModelChanged(unity::glib::Object<DeeModel>);
117− void onCategoriesSwarmNameChanged(const std::string&);
118− void onCategoriesModelChanged(unity::glib::Object<DeeModel>);
119− void onCategoriesChanged(const unity::dash::Categories::Ptr&);
120116 unity::dash::LocalResult createLocalResult(const QVariant &uri, const QVariant &icon_hint,
121117 const QVariant &category, const QVariant &result_type,
122118 const QVariant &mimetype, const QVariant &title,
@@ -127,10 +123,10 @@ private:
127123 void fallbackActivate(const QString& uri);
128124
129125 unity::dash::Scope::Ptr m_unityScope;
130− DeeListModel* m_results;
131− Categories* m_categories;
126+ std::unique_ptr<Categories> m_categories;
132127 QString m_searchQuery;
133128 QString m_noResultsHint;
129+ QString m_formFactor;
134130};
135131
136132Q_DECLARE_METATYPE(Scope*)
plugins/Utils/CMakeLists.txt+2−12
@@ -22,15 +22,5 @@ set_target_properties(Utils-qml PROPERTIES COMPILE_FLAGS -fvisibility=default)
2222
2323qt5_use_modules(Utils-qml Qml Quick)
2424
25−# copy qmldir file into build directory for shadow builds
26−file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
27− DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
28− )
29−
30−install(TARGETS Utils-qml
31− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Utils
32− )
33−
34−install(FILES qmldir
35− DESTINATION ${SHELL_PRIVATE_LIBDIR}/qml/Utils
36− )
25+# export the qmldir and qmltypes files
26+export_qmlplugin(Utils 0.1 Utils TARGETS Utils-qml)
plugins/Utils/qmldir+1
@@ -1,2 +1,3 @@
11module Utils
22plugin Utils-qml
3+typeinfo plugin.qmltypes
po/sl.po+11−17
@@ -8,14 +8,14 @@ msgstr ""
88"Project-Id-Version: unity\n"
99"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
1010"POT-Creation-Date: 2013-06-26 22:58+0200\n"
11−"PO-Revision-Date: 2013-06-29 10:26+0000\n"
11+"PO-Revision-Date: 2013-07-02 12:59+0000\n"
1212"Last-Translator: Damir Jerovšek <Unknown>\n"
1313"Language-Team: Slovenian <sl@li.org>\n"
1414"MIME-Version: 1.0\n"
1515"Content-Type: text/plain; charset=UTF-8\n"
1616"Content-Transfer-Encoding: 8bit\n"
17−"X-Launchpad-Export-Date: 2013-06-30 07:12+0000\n"
18−"X-Generator: Launchpad (build 16692)\n"
17+"X-Launchpad-Export-Date: 2013-07-06 08:44+0000\n"
18+"X-Generator: Launchpad (build 16696)\n"
1919
2020#: Applications/applications.js:23
2121msgid "Phone"
@@ -23,7 +23,7 @@ msgstr "Telefon"
2323
2424#: Applications/applications.js:29
2525msgid "Camera"
26−msgstr "Fotoaparat"
26+msgstr ""
2727
2828#: Applications/applications.js:35
2929msgid "Gallery"
@@ -111,7 +111,7 @@ msgstr "Programi"
111111
112112#: Dash/DashHome.qml:40
113113msgid "Frequent Apps"
114−msgstr ""
114+msgstr "Pogosto uporabljani programi"
115115
116116#: Dash/DashHome.qml:43
117117msgid "Recent Music"
@@ -127,7 +127,7 @@ msgstr "Domov"
127127
128128#: Dash/DashMusic.qml:27 Dash/DashVideos.qml:28
129129msgid "Featured"
130−msgstr ""
130+msgstr "Predstavljeno"
131131
132132#: Dash/DashMusic.qml:28 Dash/DashVideos.qml:29
133133msgid "Recent"
@@ -139,7 +139,7 @@ msgstr "Nove izdaje"
139139
140140#: Dash/DashMusic.qml:30
141141msgid "Top Charting"
142−msgstr ""
142+msgstr "Najvišje na lestvici"
143143
144144#: Dash/DashMusic.qml:99
145145msgid "Music"
@@ -147,7 +147,7 @@ msgstr "Glasba"
147147
148148#: Dash/DashVideos.qml:31
149149msgid "Popular Online"
150−msgstr ""
150+msgstr "Priljubljeno na spletu"
151151
152152#: Dash/DashVideos.qml:155
153153msgid "Videos"
@@ -163,7 +163,7 @@ msgstr ""
163163
164164#: Dash/Video/VideoPreview.qml:144
165165msgid "Author:"
166−msgstr "Avtor:"
166+msgstr ""
167167
168168#: Greeter/Lockscreen.qml:133
169169msgid "Emergency call"
@@ -176,7 +176,7 @@ msgstr "Pozdravljeni, %1"
176176
177177#: Greeter/PassphraseLockscreen.qml:59
178178msgid "Hello"
179−msgstr "Pozdravljeni"
179+msgstr ""
180180
181181#: Hud/HudParametrizedActionsPage.qml:132
182182msgid "Confirm"
@@ -217,10 +217,4 @@ msgstr "Nič se ne ujema z vašim iskalnim nizom."
217217#: Shell.qml:383
218218#, qt-format
219219msgid "Please enter %1"
220−msgstr "Vnesite %1"
221−
222−#~ msgid "People"
223−#~ msgstr "Ljudje"
224−
225−#~ msgid "Home screen"
226−#~ msgstr "Domači zaslon"
220+msgstr ""
tests/mocks/Unity/CMakeLists.txt+2−3
@@ -19,11 +19,10 @@ include_directories(
1919add_definitions(-DQT_NO_KEYWORDS)
2020
2121set(UnityQML_SOURCES
22− ${CMAKE_SOURCE_DIR}/plugins/Unity/categories.cpp
23− ${CMAKE_SOURCE_DIR}/plugins/Unity/categoryfilter.cpp
24− ${CMAKE_SOURCE_DIR}/plugins/Utils/qsortfilterproxymodelqml.cpp
22+ ${CMAKE_SOURCE_DIR}/plugins/Unity/categoryresults.cpp
2523 fake_scope.cpp
2624 fake_scopes.cpp
25+ fake_categories.cpp
2726 fake_unity_plugin.cpp
2827)
2928
tests/mocks/Unity/fake_categories.cppnew file+178
@@ -0,0 +1,178 @@
1+/*
2+ * Copyright (C) 2013 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+ * Author: Nick Dedekind <nick.dedekind@canonical.com>
17+ */
18+
19+// self
20+#include "fake_categories.h"
21+
22+// local
23+#include "categoryresults.h"
24+
25+#define CATEGORY_COLUMN 2
26+
27+Categories::Categories(QObject* parent)
28+ : DeeListModel(parent)
29+{
30+ // FIXME: need to clean up unused filters on countChanged
31+ m_roles[Categories::RoleId] = "id";
32+ m_roles[Categories::RoleName] = "name";
33+ m_roles[Categories::RoleIcon] = "icon";
34+ m_roles[Categories::RoleRenderer] = "renderer";
35+ m_roles[Categories::RoleContentType] = "content_type";
36+ m_roles[Categories::RoleHints] = "hints";
37+ m_roles[Categories::RoleResults] = "results";
38+ m_roles[Categories::RoleCount] = "count";
39+
40+ // TODO This should not be needed but accumulatting the count changes
41+ // makes the visualization more stable and also makes crashes on fast
42+ // change of the search term harder to reproduce
43+ m_timer.setSingleShot(true);
44+ m_timer.setInterval(50);
45+ connect(&m_timer, SIGNAL(timeout()), this, SLOT(onEmitCountChanged()));
46+}
47+
48+DeeListModel*
49+Categories::getFilter(int index) const
50+{
51+ if (!m_filters.contains(index)) {
52+ auto results = new CategoryResults ();
53+ results->setCategoryIndex(index);
54+ connect(results, SIGNAL(countChanged()), this, SLOT(onCountChanged()));
55+
56+ unsigned cat_index = static_cast<unsigned>(index);
57+ auto model = getResultsForCategory(cat_index);
58+ results->setModel(model);
59+
60+ m_filters.insert(index, results);
61+ }
62+
63+ return m_filters[index];
64+}
65+
66+void
67+Categories::onCountChanged()
68+{
69+ DeeListModel* filter = qobject_cast<DeeListModel*>(sender());
70+ if (filter) {
71+ m_timerFilters << filter;
72+ m_timer.start();
73+ }
74+}
75+
76+void
77+Categories::onEmitCountChanged()
78+{
79+ QVector<int> roles;
80+ roles.append(Categories::RoleCount);
81+ Q_FOREACH(DeeListModel* results, m_timerFilters) {
82+ auto cat_results = qobject_cast<CategoryResults*>(results);
83+ QModelIndex changedIndex = index(cat_results->categoryIndex());
84+ Q_EMIT dataChanged(changedIndex, changedIndex, roles);
85+ }
86+ m_timerFilters.clear();
87+}
88+
89+QHash<int, QByteArray>
90+Categories::roleNames() const
91+{
92+ return m_roles;
93+}
94+
95+void Categories::setResultModel(DeeModel* model)
96+{
97+ // FIXME: should ref it
98+ m_dee_results = model;
99+}
100+
101+
102+static void category_filter_map_func (DeeModel* orig_model,
103+ DeeFilterModel* filter_model,
104+ gpointer user_data)
105+{
106+ DeeModelIter* iter;
107+ DeeModelIter* end;
108+ unsigned index = GPOINTER_TO_UINT(user_data);
109+
110+ iter = dee_model_get_first_iter(orig_model);
111+ end = dee_model_get_last_iter(orig_model);
112+ while (iter != end) {
113+ unsigned category_index = dee_model_get_uint32(orig_model, iter, CATEGORY_COLUMN);
114+ if (index == category_index) {
115+ dee_filter_model_append_iter(filter_model, iter);
116+ }
117+ iter = dee_model_next(orig_model, iter);
118+ }
119+}
120+
121+static gboolean category_filter_notify_func (DeeModel* orig_model,
122+ DeeModelIter* orig_iter,
123+ DeeFilterModel* filter_model,
124+ gpointer user_data)
125+{
126+ unsigned index = GPOINTER_TO_UINT(user_data);
127+ unsigned category_index = dee_model_get_uint32(orig_model, orig_iter, CATEGORY_COLUMN);
128+
129+ if (index != category_index)
130+ return FALSE;
131+
132+ dee_filter_model_insert_iter_with_original_order(filter_model, orig_iter);
133+ return TRUE;
134+}
135+
136+DeeModel* Categories::getResultsForCategory(unsigned cat_index) const
137+{
138+ DeeFilter filter;
139+ filter.map_func = category_filter_map_func;
140+ filter.map_notify = category_filter_notify_func;
141+ filter.destroy = nullptr;
142+ filter.userdata = GUINT_TO_POINTER(cat_index);
143+
144+ DeeModel* filtered_model = dee_filter_model_new(m_dee_results, &filter);
145+ return filtered_model;
146+}
147+
148+QVariant
149+Categories::data(const QModelIndex& index, int role) const
150+{
151+ if (!index.isValid()) {
152+ return QVariant();
153+ }
154+
155+ switch (role) {
156+ case RoleId:
157+ return QVariant::fromValue(index.row());
158+ case RoleName:
159+ return DeeListModel::data(index, 1); //DISPLAY_NAME
160+ case RoleIcon:
161+ return DeeListModel::data(index, 2); //ICON_HINT
162+ case RoleRenderer:
163+ return DeeListModel::data(index, 3); //RENDERER_NAME
164+ case RoleContentType:
165+ {
166+ auto hints = DeeListModel::data(index, 4).toHash();
167+ return hints.contains("content-type") ? hints["content-type"] : QVariant(QString("default"));
168+ }
169+ case RoleHints:
170+ return DeeListModel::data(index, 4); //HINTS
171+ case RoleResults:
172+ return QVariant::fromValue(getFilter(index.row()));
173+ case RoleCount:
174+ return QVariant::fromValue(getFilter(index.row())->rowCount());
175+ default:
176+ return QVariant();
177+ }
178+}
tests/mocks/Unity/fake_categories.hnew file+69
@@ -0,0 +1,69 @@
1+/*
2+ * Copyright (C) 2013 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+#ifndef FAKE_CATEGORIES_H
18+#define FAKE_CATEGORIES_H
19+
20+// Qt
21+#include <QObject>
22+#include <QSet>
23+#include <QTimer>
24+
25+#include <dee.h>
26+#include <deelistmodel.h>
27+
28+class Categories : public DeeListModel
29+{
30+ Q_OBJECT
31+
32+ Q_ENUMS(Roles)
33+
34+public:
35+ Categories(QObject* parent = 0);
36+ enum Roles {
37+ RoleId,
38+ RoleName,
39+ RoleIcon,
40+ RoleRenderer,
41+ RoleContentType,
42+ RoleHints,
43+ RoleResults,
44+ RoleCount
45+ };
46+
47+ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
48+
49+ QHash<int, QByteArray> roleNames() const;
50+
51+ /* setters */
52+ void setResultModel(DeeModel* model);
53+
54+private Q_SLOTS:
55+ void onCountChanged();
56+ void onEmitCountChanged();
57+
58+private:
59+ DeeModel* getResultsForCategory(unsigned index) const;
60+ DeeListModel* getFilter(int index) const;
61+
62+ DeeModel* m_dee_results;
63+ QTimer m_timer;
64+ QSet<DeeListModel*> m_timerFilters;
65+ QHash<int, QByteArray> m_roles;
66+ mutable QMap<int, DeeListModel*> m_filters;
67+};
68+
69+#endif // FAKE_CATEGORIES_H
tests/mocks/Unity/fake_scope.cpp+104−73
@@ -26,32 +26,29 @@ static DeeModel* create_results_model(unsigned category_count, unsigned result_c
2626// TODO: Implement remaining pieces
2727
2828Scope::Scope(QObject* parent)
29−: QObject(parent),
30− m_visible(false),
31− m_categories(new Categories(this)),
32− m_results(new DeeListModel(this))
29+ : QObject(parent)
30+ , m_visible(false)
31+ , m_categories(new Categories(this))
32+ , m_results(new DeeListModel(this))
3333{
34+ DeeModel* results_model = create_results_model(4, 30);
35+ m_categories->setResultModel(results_model);
3436 m_categories->setModel(create_categories_model(4));
35− m_results->setModel(create_results_model(4, 30));
36−
37− m_categories->setResultModel(m_results);
37+ m_results->setModel(results_model);
3838}
3939
40−Scope::Scope(QString const& id,
41− QString const& name,
42− bool visible,
43− QObject* parent)
44−: QObject(parent),
45− m_id(id),
46− m_name(name),
47− m_visible(visible),
48− m_categories(new Categories(this)),
49− m_results(new DeeListModel(this))
40+Scope::Scope(QString const& id, QString const& name, bool visible, QObject* parent)
41+ : QObject(parent)
42+ , m_id(id)
43+ , m_name(name)
44+ , m_visible(visible)
45+ , m_categories(new Categories(this))
46+ , m_results(new DeeListModel(this))
5047{
48+ DeeModel* results_model = create_results_model(4, 30);
49+ m_categories->setResultModel(results_model);
5150 m_categories->setModel(create_categories_model(4));
52− m_results->setModel(create_results_model(4, 30));
53−
54− m_categories->setResultModel(m_results);
51+ m_results->setModel(results_model);
5552}
5653
5754QString Scope::id() const {
@@ -66,6 +63,42 @@ QString Scope::searchQuery() const {
6663 return m_searchQuery;
6764}
6865
66+QString Scope::iconHint() const {
67+ return m_iconHint;
68+}
69+
70+QString Scope::description() const {
71+ return m_description;
72+}
73+
74+QString Scope::searchHint() const {
75+ return QString("");
76+}
77+
78+QString Scope::shortcut() const {
79+ return QString("");
80+}
81+
82+bool Scope::connected() const {
83+ return true;
84+}
85+
86+Categories* Scope::categories() const {
87+ return m_categories;
88+}
89+
90+QString Scope::noResultsHint() const {
91+ return m_noResultsHint;
92+}
93+
94+QString Scope::formFactor() const {
95+ return m_formFactor;
96+}
97+
98+bool Scope::visible() const {
99+ return m_visible;
100+}
101+
69102void Scope::setName(const QString &str) {
70103 if (str != m_name) {
71104 m_name = str;
@@ -76,45 +109,47 @@ void Scope::setName(const QString &str) {
76109void Scope::setSearchQuery(const QString &str) {
77110 if (str != m_searchQuery) {
78111 m_searchQuery = str;
79− Q_EMIT searchQueryChanged(m_searchQuery);
112+ Q_EMIT searchQueryChanged();
80113 }
81114}
82115
83−bool Scope::visible() const {
84− return m_visible;
116+void Scope::setFormFactor(const QString &str) {
117+ if (str != m_formFactor) {
118+ m_formFactor = str;
119+ Q_EMIT formFactorChanged();
120+ }
85121}
86122
87−Categories* Scope::categories() const {
88− return m_categories;
123+void Scope::setNoResultsHint(const QString& str) {
124+ if (str != m_noResultsHint) {
125+ m_noResultsHint = str;
126+ Q_EMIT noResultsHintChanged();
127+ }
89128}
90129
91130static const gchar * categories_model_schema[] = {
92− "s", //ID
93− "s", // DISPLAY_NAME
94− "s", // ICON_HINT
95− "s", // RENDERER_NAME
96− "a{sv}" // HINTS
131+ "s", //ID
132+ "s", // DISPLAY_NAME
133+ "s", // ICON_HINT
134+ "s", // RENDERER_NAME
135+ "a{sv}" // HINTS
97136};
98137
99138
100139DeeModel* create_categories_model(unsigned category_count) {
101140 DeeModel* category_model = dee_sequence_model_new();
102141 dee_model_set_schema_full(category_model, categories_model_schema, G_N_ELEMENTS(categories_model_schema));
103−
104− GVariantBuilder b;
105− g_variant_builder_init(&b, G_VARIANT_TYPE("a{sv}"));
106− GVariant *hints = g_variant_builder_end(&b);
142+ GVariant* hints = g_variant_new_array(g_variant_type_element(G_VARIANT_TYPE_VARDICT), NULL, 0);
107143
108144 for(unsigned i = 0; i < category_count; ++i)
109145 {
110− dee_model_append(category_model,
111− std::to_string(i).c_str(),
112− ("Category "+std::to_string(i)).c_str(),
113− "gtk-apply",
114− "grid",
115− hints);
146+ dee_model_append(category_model,
147+ std::to_string(i).c_str(),
148+ ("Category "+std::to_string(i)).c_str(),
149+ "gtk-apply",
150+ "grid",
151+ hints);
116152 }
117− g_variant_unref(hints);
118153 return category_model;
119154}
120155
@@ -122,48 +157,44 @@ DeeModel* create_categories_model(unsigned category_count) {
122157/* Schema that is used in the DeeModel representing
123158 the results */
124159static const gchar * results_model_schema[] = {
125− "s", // URI
126− "s", // ICON_HINT
127− "u", // CATEGORY
128− "u", // RESULT_TYPE
129− "s", // MIMETYPE
130− "s", // TITLE
131− "s", // COMMENT
132− "s", // DND_URI
133− "a{sv}" // METADATA
160+ "s", // URI
161+ "s", // ICON_HINT
162+ "u", // CATEGORY
163+ "u", // RESULT_TYPE
164+ "s", // MIMETYPE
165+ "s", // TITLE
166+ "s", // COMMENT
167+ "s", // DND_URI
168+ "a{sv}" // METADATA
134169};
135170
136171static const gchar * icons[] = {
137− "Applications.png",
138− "Home.png",
139− "Music.png",
140− "People.png",
141− "Videos.png",
172+ "Applications.png",
173+ "Home.png",
174+ "Music.png",
175+ "People.png",
176+ "Videos.png",
142177};
143178
144179DeeModel* create_results_model(unsigned category_count, unsigned result_count) {
145180 DeeModel* results_model = dee_sequence_model_new();
146181 dee_model_set_schema_full(results_model, results_model_schema, G_N_ELEMENTS(results_model_schema));
147−
148− GVariantBuilder b;
149− g_variant_builder_init(&b, G_VARIANT_TYPE("a{sv}"));
150− GVariant *hints = g_variant_builder_end(&b);
182+ GVariant* hints = g_variant_new_array(g_variant_type_element(G_VARIANT_TYPE_VARDICT), NULL, 0);
151183
152184 for(unsigned i = 0; i < result_count; ++i)
153185 {
154− unsigned category = i % category_count;
155−
156− dee_model_append(results_model,
157− ("uri://result."+std::to_string(i)).c_str(),
158− (shellAppDirectory() + "Dash/graphics/scopeIcons/" + (icons[i%G_N_ELEMENTS(icons)])).toLatin1().data(),
159− category,
160− 0,
161− "application/x-desktop",
162− ("Title."+std::to_string(i)).c_str(),
163− ("Comment."+std::to_string(i)).c_str(),
164− ("uri://result."+std::to_string(i)).c_str(),
165− hints);
186+ unsigned category = i % category_count;
187+
188+ dee_model_append(results_model,
189+ ("uri://result."+std::to_string(i)).c_str(),
190+ (shellAppDirectory() + "Dash/graphics/scopeIcons/" + (icons[i%G_N_ELEMENTS(icons)])).toLatin1().data(),
191+ category,
192+ 0,
193+ "application/x-desktop",
194+ ("Title."+std::to_string(i)).c_str(),
195+ ("Comment."+std::to_string(i)).c_str(),
196+ ("uri://result."+std::to_string(i)).c_str(),
197+ hints);
166198 }
167− g_variant_unref(hints);
168199 return results_model;
169− }
200+}
tests/mocks/Unity/fake_scope.h+43−11
@@ -19,43 +19,75 @@
1919
2020// Qt
2121#include <QObject>
22−#include "categories.h"
22+#include "fake_categories.h"
2323
2424class Scope : public QObject
2525{
2626 Q_OBJECT
27+
2728 Q_PROPERTY(QString id READ id NOTIFY idChanged)
28− Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
29− Q_PROPERTY(QString searchQuery READ searchQuery WRITE setSearchQuery NOTIFY searchQueryChanged)
29+ Q_PROPERTY(QString name READ name NOTIFY nameChanged)
30+ Q_PROPERTY(QString iconHint READ iconHint NOTIFY iconHintChanged)
31+ Q_PROPERTY(QString description READ description NOTIFY descriptionChanged)
32+ Q_PROPERTY(QString searchHint READ searchHint NOTIFY searchHintChanged)
3033 Q_PROPERTY(bool visible READ visible NOTIFY visibleChanged)
34+ Q_PROPERTY(QString shortcut READ shortcut NOTIFY shortcutChanged)
35+ Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged)
3136 Q_PROPERTY(Categories* categories READ categories NOTIFY categoriesChanged)
3237
38+ Q_PROPERTY(QString searchQuery READ searchQuery WRITE setSearchQuery NOTIFY searchQueryChanged)
39+ Q_PROPERTY(QString noResultsHint READ noResultsHint WRITE setNoResultsHint NOTIFY noResultsHintChanged)
40+ Q_PROPERTY(QString formFactor READ formFactor WRITE setFormFactor NOTIFY formFactorChanged)
41+
3342public:
3443 Scope(QObject* parent = 0);
3544 Scope(QString const& id, QString const& name, bool visible, QObject* parent = 0);
3645
46+ /* getters */
3747 QString id() const;
3848 QString name() const;
39− QString searchQuery() const;
49+ QString iconHint() const;
50+ QString description() const;
51+ QString searchHint() const;
4052 bool visible() const;
41−
42− void setName(const QString &str);
43− void setSearchQuery(const QString &str);
44−
53+ QString shortcut() const;
54+ bool connected() const;
4555 Categories* categories() const;
56+ QString searchQuery() const;
57+ QString noResultsHint() const;
58+ QString formFactor() const;
59+
60+ /* setters */
61+ void setName(const QString& name);
62+ void setSearchQuery(const QString& search_query);
63+ void setNoResultsHint(const QString& hint);
64+ void setFormFactor(const QString& form_factor);
4665
4766Q_SIGNALS:
48− void idChanged(QString);
49− void nameChanged(QString);
50− void searchQueryChanged(QString);
67+ void idChanged(const QString&);
68+ void nameChanged(const QString&);
69+ void iconHintChanged(const QString&);
70+ void descriptionChanged(const QString&);
71+ void searchHintChanged(const QString&);
5172 void visibleChanged(bool);
73+ void shortcutChanged(const QString&);
74+ void connectedChanged(bool);
5275 void categoriesChanged();
76+ void searchFinished(const QString&);
77+ void searchQueryChanged();
78+ void noResultsHintChanged();
79+ void formFactorChanged();
5380
5481private:
5582 QString m_id;
83+ QString m_iconHint;
84+ QString m_description;
5685 QString m_name;
5786 QString m_searchQuery;
87+ QString m_noResultsHint;
88+ QString m_formFactor;
5889 bool m_visible;
90+
5991 Categories* m_categories;
6092 DeeListModel* m_results;
6193};
tests/mocks/Unity/fake_unity_plugin.cpp+3−3
@@ -21,8 +21,8 @@
2121
2222// local
2323#include "fake_scopes.h"
24−#include "categories.h"
25−#include "categoryfilter.h"
24+#include "fake_categories.h"
25+#include "categoryresults.h"
2626
2727// External
2828#include <glib-object.h>
@@ -39,5 +39,5 @@ void FakeUnityPlugin::registerTypes(const char *uri)
3939 qmlRegisterType<Scopes>(uri, 0, 1, "Scopes");
4040 qmlRegisterType<Scope>(uri, 0, 1, "Scope");
4141 qmlRegisterType<Categories>(uri, 0, 1, "Categories");
42− qmlRegisterType<CategoryFilter>(uri, 0, 1, "CategoryFilter");
42+ qmlRegisterUncreatableType<CategoryResults>(uri, 0, 1, "CategoryResults", "Can't create");
4343}
tests/plugins/Unity/CMakeLists.txt+1−1
@@ -21,7 +21,7 @@ macro(run_tests)
2121 add_executable(${_test}Exec ${_test}.cpp previewbindingstest.cpp)
2222 qt5_use_modules(${_test}Exec Test Core Qml)
2323 set_tests_properties(test${CLASSNAME}${_test}
24− PROPERTIES ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/plugins/Unity:${LIBUNITYPROTO_LIBRARY_DIRS})
24+ PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/plugins/Unity:${LIBUNITYPROTO_LIBRARY_DIRS}")
2525
2626 target_link_libraries(${_test}Exec
2727 Unity-qml
tests/qmltests/Dash/qml/FakeScopeView.qml+2−2
@@ -107,10 +107,10 @@ FocusScope {
107107 Image {
108108 width: units.gu(5)
109109 height: units.gu(5)
110− source: column_1
110+ source: icon
111111 anchors.horizontalCenter: parent.horizontalCenter
112112 }
113− Text { text: column_4; anchors.horizontalCenter: parent.horizontalCenter }
113+ Text { text: title; anchors.horizontalCenter: parent.horizontalCenter }
114114 }
115115 }
116116 }