Merge lp:~nik90/podbird/8.6-aboutpage into lp:podbird
- 8.6-aboutpage
- Merge into trunk
Proposed by
Nekhelesh Ramananthan
Status: | Superseded |
---|---|
Proposed branch: | lp:~nik90/podbird/8.6-aboutpage |
Merge into: | lp:podbird |
Diff against target: |
4725 lines (+3268/-686) 38 files modified
CMakeLists.txt (+2/-2) Podbird.apparmor (+4/-2) app/CMakeLists.txt (+3/-1) app/graphics/CMakeLists.txt (+7/-0) app/graphics/notFound.svg (+131/-0) app/graphics/owlSearch.svg (+140/-0) app/podbird.qml (+102/-8) app/podcasts.js (+16/-3) app/settings/About.qml (+151/-0) app/settings/CMakeLists.txt (+7/-0) app/settings/CleanSetting.qml (+65/-0) app/settings/DownloadSetting.qml (+64/-0) app/settings/ThemeSetting.qml (+63/-0) app/themes/Dark.qml (+4/-4) app/themes/Light.qml (+4/-4) app/ui/ActionButton.qml (+2/-2) app/ui/BlurredBackground.qml (+4/-21) app/ui/Card.qml (+139/-0) app/ui/CardView.qml (+55/-0) app/ui/ColumnFlow.qml (+494/-0) app/ui/EmptyState.qml (+6/-2) app/ui/EpisodesPage.qml (+393/-232) app/ui/ExpandableListItem.qml (+1/-0) app/ui/NowPlayingPage.qml (+5/-0) app/ui/PlayerControls.qml (+2/-2) app/ui/PodcastsTab.qml (+168/-120) app/ui/SearchPage.qml (+160/-101) app/ui/SettingsPage.qml (+119/-86) app/ui/Walkthrough.qml (+169/-0) app/welcomewizard/CMakeLists.txt (+8/-0) app/welcomewizard/Slide1.qml (+76/-0) app/welcomewizard/Slide2.qml (+66/-0) app/welcomewizard/Slide3.qml (+67/-0) app/welcomewizard/Slide4.qml (+70/-0) app/welcomewizard/Slide5.qml (+66/-0) app/welcomewizard/Slide6.qml (+80/-0) app/welcomewizard/WelcomeWizard.qml (+41/-0) po/com.mikeasoft.podbird.pot (+314/-96) |
To merge this branch: | bzr merge lp:~nik90/podbird/8.6-aboutpage |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michael Sheldon | Pending | ||
Review via email: mp+255909@code.launchpad.net |
Commit message
Added about page to provide information about the licensing, version and also the contributors of Podbird.
Description of the change
Added about page to provide information about the licensing, version and also the contributors of Podbird.
To post a comment you must log in.
lp:~nik90/podbird/8.6-aboutpage
updated
- 79. By Nekhelesh Ramananthan
-
merged prerequisite
- 80. By Nekhelesh Ramananthan
-
Split the credits and about page as otherwise it exposes a SDK bug
- 81. By Nekhelesh Ramananthan
-
Merged prerequisite
- 82. By Nekhelesh Ramananthan
-
merged prerequisite fix
- 83. By Nekhelesh Ramananthan
-
merged prerequisite
- 84. By Nekhelesh Ramananthan
-
Fixed version
- 85. By Nekhelesh Ramananthan
-
changed version to beta1
- 86. By Nekhelesh Ramananthan
-
merged prerequsiite
- 87. By Nekhelesh Ramananthan
-
merged prerequisite
- 88. By Nekhelesh Ramananthan
-
updated to v0.6.b2
- 89. By Nekhelesh Ramananthan
-
merged prerequisite lp:~nik90/podbird/8.5-usermetrics
- 90. By Nekhelesh Ramananthan
-
Adjusted link color to be more visible in the dark theme throughout the app
Unmerged revisions
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2015-01-04 10:20:41 +0000 |
3 | +++ CMakeLists.txt 2015-04-11 21:39:04 +0000 |
4 | @@ -28,7 +28,7 @@ |
5 | set(APP_ID "com.mikeasoft.podbird") |
6 | set(PODBIRD_DIR "share/qml/podbird") |
7 | set(MAIN_QML "podbird.qml") |
8 | -set(ICON "graphics/podbird.png") |
9 | +set(ICON "podbird.png") |
10 | |
11 | # Set install paths |
12 | set(CMAKE_INSTALL_PREFIX /) |
13 | @@ -49,7 +49,7 @@ |
14 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/manifest.json |
15 | DESTINATION ${CMAKE_INSTALL_PREFIX}) |
16 | |
17 | -install(DIRECTORY "app/graphics" DESTINATION ${DATA_DIR}) |
18 | +install(FILES "podbird.png" DESTINATION ${DATA_DIR}) |
19 | install(FILES "Podbird.apparmor" DESTINATION ${DATA_DIR}) |
20 | |
21 | add_subdirectory(app) |
22 | |
23 | === modified file 'Podbird.apparmor' |
24 | --- Podbird.apparmor 2015-01-30 00:16:10 +0000 |
25 | +++ Podbird.apparmor 2015-04-11 21:39:04 +0000 |
26 | @@ -1,7 +1,9 @@ |
27 | { |
28 | "policy_groups": [ |
29 | "networking", |
30 | - "audio" |
31 | + "audio", |
32 | + "connectivity", |
33 | + "usermetrics" |
34 | ], |
35 | "policy_version": 1.2 |
36 | -} |
37 | \ No newline at end of file |
38 | +} |
39 | |
40 | === modified file 'app/CMakeLists.txt' |
41 | --- app/CMakeLists.txt 2015-03-03 22:44:29 +0000 |
42 | +++ app/CMakeLists.txt 2015-04-11 21:39:04 +0000 |
43 | @@ -11,4 +11,6 @@ |
44 | |
45 | add_subdirectory(ui) |
46 | add_subdirectory(themes) |
47 | - |
48 | +add_subdirectory(welcomewizard) |
49 | +add_subdirectory(graphics) |
50 | +add_subdirectory(settings) |
51 | |
52 | === added file 'app/graphics/CMakeLists.txt' |
53 | --- app/graphics/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
54 | +++ app/graphics/CMakeLists.txt 2015-04-11 21:39:04 +0000 |
55 | @@ -0,0 +1,7 @@ |
56 | +file(GLOB GRAPHIC_FILES *.png *.jpg *.svg) |
57 | + |
58 | +# Make the files visible in the qtcreator tree |
59 | +add_custom_target(podbird_GRAPHICFiles ALL SOURCES ${GRAPHIC_FILES}) |
60 | + |
61 | +install(FILES ${GRAPHIC_FILES} DESTINATION ${PODBIRD_DIR}/graphics) |
62 | + |
63 | |
64 | === added file 'app/graphics/discover.png' |
65 | Binary files app/graphics/discover.png 1970-01-01 00:00:00 +0000 and app/graphics/discover.png 2015-04-11 21:39:04 +0000 differ |
66 | === added file 'app/graphics/gift.png' |
67 | Binary files app/graphics/gift.png 1970-01-01 00:00:00 +0000 and app/graphics/gift.png 2015-04-11 21:39:04 +0000 differ |
68 | === added file 'app/graphics/language.png' |
69 | Binary files app/graphics/language.png 1970-01-01 00:00:00 +0000 and app/graphics/language.png 2015-04-11 21:39:04 +0000 differ |
70 | === added file 'app/graphics/notFound.svg' |
71 | --- app/graphics/notFound.svg 1970-01-01 00:00:00 +0000 |
72 | +++ app/graphics/notFound.svg 2015-04-11 21:39:04 +0000 |
73 | @@ -0,0 +1,131 @@ |
74 | +<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
75 | +<!-- Created with Inkscape (http://www.inkscape.org/) --> |
76 | + |
77 | +<svg |
78 | + xmlns:dc="http://purl.org/dc/elements/1.1/" |
79 | + xmlns:cc="http://creativecommons.org/ns#" |
80 | + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
81 | + xmlns:svg="http://www.w3.org/2000/svg" |
82 | + xmlns="http://www.w3.org/2000/svg" |
83 | + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
84 | + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
85 | + width="383.80545" |
86 | + height="214.75534" |
87 | + id="svg12819" |
88 | + version="1.1" |
89 | + inkscape:version="0.48.4 r9939" |
90 | + sodipodi:docname="notFound.svg" |
91 | + inkscape:export-filename="/home/kevin/Documents/Development/app screenshots/owlSearch.png" |
92 | + inkscape:export-xdpi="90" |
93 | + inkscape:export-ydpi="90"> |
94 | + <defs |
95 | + id="defs12821" /> |
96 | + <sodipodi:namedview |
97 | + id="base" |
98 | + pagecolor="#ffffff" |
99 | + bordercolor="#666666" |
100 | + borderopacity="1.0" |
101 | + inkscape:pageopacity="0.0" |
102 | + inkscape:pageshadow="2" |
103 | + inkscape:zoom="1.41521" |
104 | + inkscape:cx="388.73869" |
105 | + inkscape:cy="44.241833" |
106 | + inkscape:document-units="px" |
107 | + inkscape:current-layer="g15020" |
108 | + showgrid="false" |
109 | + fit-margin-top="10" |
110 | + fit-margin-left="0" |
111 | + fit-margin-right="0" |
112 | + fit-margin-bottom="10" |
113 | + inkscape:window-width="1920" |
114 | + inkscape:window-height="1056" |
115 | + inkscape:window-x="0" |
116 | + inkscape:window-y="24" |
117 | + inkscape:window-maximized="1" /> |
118 | + <metadata |
119 | + id="metadata12824"> |
120 | + <rdf:RDF> |
121 | + <cc:Work |
122 | + rdf:about=""> |
123 | + <dc:format>image/svg+xml</dc:format> |
124 | + <dc:type |
125 | + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
126 | + <dc:title /> |
127 | + </cc:Work> |
128 | + </rdf:RDF> |
129 | + </metadata> |
130 | + <g |
131 | + inkscape:label="Layer 1" |
132 | + inkscape:groupmode="layer" |
133 | + id="layer1" |
134 | + transform="translate(-174.89943,-164.11232)"> |
135 | + <g |
136 | + style="display:inline" |
137 | + id="g14777" |
138 | + transform="matrix(0.69639553,0,0,0.69639553,-479.44734,119.33528)"> |
139 | + <g |
140 | + id="g15020" |
141 | + transform="matrix(0.63322219,0,0,0.63322219,-295.2311,987.63072)"> |
142 | + <g |
143 | + id="g15082" |
144 | + transform="translate(0,82.828838)"> |
145 | + <path |
146 | + sodipodi:type="arc" |
147 | + style="fill:none;stroke:#808080;stroke-width:46.75191879;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" |
148 | + id="path14966-8" |
149 | + sodipodi:cx="1962.8733" |
150 | + sodipodi:cy="-378.12149" |
151 | + sodipodi:rx="136.36804" |
152 | + sodipodi:ry="136.36804" |
153 | + d="m 2099.2413,-378.12149 c 0,75.31399 -61.054,136.36804 -136.368,136.36804 -75.314,0 -136.3681,-61.05405 -136.3681,-136.36804 0,-75.31399 61.0541,-136.36804 136.3681,-136.36804 75.314,0 136.368,61.05405 136.368,136.36804 z" |
154 | + transform="matrix(1.2126303,0,0,1.2126303,246.51638,-866.06892)" /> |
155 | + <path |
156 | + sodipodi:type="arc" |
157 | + style="fill:#808080;fill-opacity:1;fill-rule:evenodd;stroke:none" |
158 | + id="path14988" |
159 | + sodipodi:cx="2108.5391" |
160 | + sodipodi:cy="-525.33698" |
161 | + sodipodi:rx="41.840195" |
162 | + sodipodi:ry="41.840195" |
163 | + d="m 2150.3793,-525.33698 c 0,23.10771 -18.7325,41.8402 -41.8402,41.8402 -23.1077,0 -41.8402,-18.73249 -41.8402,-41.8402 0,-23.1077 18.7325,-41.84019 41.8402,-41.84019 23.1077,0 41.8402,18.73249 41.8402,41.84019 z" |
164 | + transform="matrix(1.4359656,0,0,1.4359656,-645.94974,-626.80514)" /> |
165 | + <path |
166 | + inkscape:connector-curvature="0" |
167 | + style="fill:#808080;fill-opacity:1;stroke:none" |
168 | + d="m 2089.4375,-438.03125 0,103.3125 17.9063,0 c 7.3889,-17.02228 24.323,-28.9375 44.0624,-28.9375 19.7395,0 36.7049,11.91522 44.0938,28.9375 l 17.9062,0 0,-103.3125 -123.9687,0 z" |
169 | + transform="matrix(1.4359656,0,0,1.4359656,-707.51452,-787.38294)" |
170 | + id="rect14986" /> |
171 | + <path |
172 | + sodipodi:type="arc" |
173 | + style="fill:none;stroke:#808080;stroke-width:46.75191879;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" |
174 | + id="path14966-8-2" |
175 | + sodipodi:cx="1962.8733" |
176 | + sodipodi:cy="-378.12149" |
177 | + sodipodi:rx="136.36804" |
178 | + sodipodi:ry="136.36804" |
179 | + d="m 2099.2413,-378.12149 c 0,75.31399 -61.054,136.36804 -136.368,136.36804 -75.314,0 -136.3681,-61.05405 -136.3681,-136.36804 0,-75.31399 61.0541,-136.36804 136.3681,-136.36804 75.314,0 136.368,61.05405 136.368,136.36804 z" |
180 | + transform="matrix(1.2126303,0,0,1.2126303,-236.42299,-866.06892)" /> |
181 | + </g> |
182 | + <rect |
183 | + style="fill:#808080;fill-opacity:1;stroke:none" |
184 | + id="rect15091" |
185 | + width="129.21298" |
186 | + height="129.21298" |
187 | + x="856.36871" |
188 | + y="-2520.2727" |
189 | + transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)" /> |
190 | + <path |
191 | + style="fill:#808080;fill-opacity:1;fill-rule:evenodd;stroke:none" |
192 | + d="m 103.71875,171.6875 -33.5625,16.21875 c 2.149792,8.13106 9.568126,14.125 18.375,14.125 10.489627,0 18.96875,-8.51037 18.96875,-19 0,-4.26924 -1.40349,-8.17188 -3.78125,-11.34375 z" |
193 | + transform="matrix(2.267712,0,0,2.267712,1943.0825,-1656.8514)" |
194 | + id="path15093" |
195 | + inkscape:connector-curvature="0" /> |
196 | + <path |
197 | + inkscape:connector-curvature="0" |
198 | + style="fill:#808080;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" |
199 | + d="m 2592.9883,-1268.3362 76.1101,36.7795 c -4.8751,18.4389 -21.6977,32.0314 -41.6692,32.0314 -23.7874,0 -43.0156,-19.2991 -43.0156,-43.0865 0,-9.6814 3.1827,-18.5315 8.5747,-25.7244 z" |
200 | + id="path15093-2" /> |
201 | + </g> |
202 | + </g> |
203 | + </g> |
204 | +</svg> |
205 | |
206 | === added file 'app/graphics/owlSearch.svg' |
207 | --- app/graphics/owlSearch.svg 1970-01-01 00:00:00 +0000 |
208 | +++ app/graphics/owlSearch.svg 2015-04-11 21:39:04 +0000 |
209 | @@ -0,0 +1,140 @@ |
210 | +<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
211 | +<!-- Created with Inkscape (http://www.inkscape.org/) --> |
212 | + |
213 | +<svg |
214 | + xmlns:dc="http://purl.org/dc/elements/1.1/" |
215 | + xmlns:cc="http://creativecommons.org/ns#" |
216 | + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
217 | + xmlns:svg="http://www.w3.org/2000/svg" |
218 | + xmlns="http://www.w3.org/2000/svg" |
219 | + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
220 | + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
221 | + width="383.80545" |
222 | + height="214.75534" |
223 | + id="svg12819" |
224 | + version="1.1" |
225 | + inkscape:version="0.48.4 r9939" |
226 | + sodipodi:docname="owlSearch.svg" |
227 | + inkscape:export-filename="/home/kevin/Documents/Development/app screenshots/owlSearch.png" |
228 | + inkscape:export-xdpi="90" |
229 | + inkscape:export-ydpi="90"> |
230 | + <defs |
231 | + id="defs12821" /> |
232 | + <sodipodi:namedview |
233 | + id="base" |
234 | + pagecolor="#ffffff" |
235 | + bordercolor="#666666" |
236 | + borderopacity="1.0" |
237 | + inkscape:pageopacity="0.0" |
238 | + inkscape:pageshadow="2" |
239 | + inkscape:zoom="1.990625" |
240 | + inkscape:cx="153.4653" |
241 | + inkscape:cy="131.99307" |
242 | + inkscape:document-units="px" |
243 | + inkscape:current-layer="layer1" |
244 | + showgrid="false" |
245 | + fit-margin-top="10" |
246 | + fit-margin-left="0" |
247 | + fit-margin-right="0" |
248 | + fit-margin-bottom="10" |
249 | + inkscape:window-width="1920" |
250 | + inkscape:window-height="1056" |
251 | + inkscape:window-x="0" |
252 | + inkscape:window-y="24" |
253 | + inkscape:window-maximized="1" /> |
254 | + <metadata |
255 | + id="metadata12824"> |
256 | + <rdf:RDF> |
257 | + <cc:Work |
258 | + rdf:about=""> |
259 | + <dc:format>image/svg+xml</dc:format> |
260 | + <dc:type |
261 | + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
262 | + <dc:title /> |
263 | + </cc:Work> |
264 | + </rdf:RDF> |
265 | + </metadata> |
266 | + <g |
267 | + inkscape:label="Layer 1" |
268 | + inkscape:groupmode="layer" |
269 | + id="layer1" |
270 | + transform="translate(-174.89943,-164.11232)"> |
271 | + <g |
272 | + style="display:inline" |
273 | + id="g14777" |
274 | + transform="matrix(0.69639553,0,0,0.69639553,-479.44734,119.33528)"> |
275 | + <g |
276 | + id="g15020" |
277 | + transform="matrix(0.63322219,0,0,0.63322219,-295.2311,987.63072)"> |
278 | + <g |
279 | + id="g15082" |
280 | + transform="translate(0,82.828838)"> |
281 | + <path |
282 | + sodipodi:type="arc" |
283 | + style="fill:none;stroke:#808080;stroke-width:46.75191879;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" |
284 | + id="path14966-8" |
285 | + sodipodi:cx="1962.8733" |
286 | + sodipodi:cy="-378.12149" |
287 | + sodipodi:rx="136.36804" |
288 | + sodipodi:ry="136.36804" |
289 | + d="m 2099.2413,-378.12149 c 0,75.31399 -61.054,136.36804 -136.368,136.36804 -75.314,0 -136.3681,-61.05405 -136.3681,-136.36804 0,-75.31399 61.0541,-136.36804 136.3681,-136.36804 75.314,0 136.368,61.05405 136.368,136.36804 z" |
290 | + transform="matrix(1.2126303,0,0,1.2126303,246.51638,-866.06892)" /> |
291 | + <path |
292 | + sodipodi:type="arc" |
293 | + style="fill:#808080;fill-opacity:1;fill-rule:evenodd;stroke:none" |
294 | + id="path14988" |
295 | + sodipodi:cx="2108.5391" |
296 | + sodipodi:cy="-525.33698" |
297 | + sodipodi:rx="41.840195" |
298 | + sodipodi:ry="41.840195" |
299 | + d="m 2150.3793,-525.33698 c 0,23.10771 -18.7325,41.8402 -41.8402,41.8402 -23.1077,0 -41.8402,-18.73249 -41.8402,-41.8402 0,-23.1077 18.7325,-41.84019 41.8402,-41.84019 23.1077,0 41.8402,18.73249 41.8402,41.84019 z" |
300 | + transform="matrix(1.4359656,0,0,1.4359656,-645.94974,-626.80514)" /> |
301 | + <path |
302 | + inkscape:connector-curvature="0" |
303 | + style="fill:#808080;fill-opacity:1;stroke:none" |
304 | + d="m 2089.4375,-438.03125 0,103.3125 17.9063,0 c 7.3889,-17.02228 24.323,-28.9375 44.0624,-28.9375 19.7395,0 36.7049,11.91522 44.0938,28.9375 l 17.9062,0 0,-103.3125 -123.9687,0 z" |
305 | + transform="matrix(1.4359656,0,0,1.4359656,-707.51452,-787.38294)" |
306 | + id="rect14986" /> |
307 | + <path |
308 | + sodipodi:type="arc" |
309 | + style="fill:none;stroke:#808080;stroke-width:46.75191879;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" |
310 | + id="path14966-8-2" |
311 | + sodipodi:cx="1962.8733" |
312 | + sodipodi:cy="-378.12149" |
313 | + sodipodi:rx="136.36804" |
314 | + sodipodi:ry="136.36804" |
315 | + d="m 2099.2413,-378.12149 c 0,75.31399 -61.054,136.36804 -136.368,136.36804 -75.314,0 -136.3681,-61.05405 -136.3681,-136.36804 0,-75.31399 61.0541,-136.36804 136.3681,-136.36804 75.314,0 136.368,61.05405 136.368,136.36804 z" |
316 | + transform="matrix(1.2126303,0,0,1.2126303,-236.42299,-866.06892)" /> |
317 | + </g> |
318 | + <rect |
319 | + style="fill:#808080;fill-opacity:1;stroke:none" |
320 | + id="rect15091" |
321 | + width="129.21298" |
322 | + height="129.21298" |
323 | + x="856.36871" |
324 | + y="-2520.2727" |
325 | + transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)" /> |
326 | + <path |
327 | + sodipodi:type="arc" |
328 | + style="fill:#808080;fill-opacity:1;fill-rule:evenodd;stroke:none" |
329 | + id="path15093" |
330 | + sodipodi:cx="1206.7955" |
331 | + sodipodi:cy="673.53888" |
332 | + sodipodi:rx="18.993151" |
333 | + sodipodi:ry="18.993151" |
334 | + d="m 1225.7887,673.53888 c 0,10.48963 -8.5035,18.99315 -18.9932,18.99315 -10.4896,0 -18.9931,-8.50352 -18.9931,-18.99315 0,-10.48963 8.5035,-18.99315 18.9931,-18.99315 10.4897,0 18.9932,8.50352 18.9932,18.99315 z" |
335 | + transform="matrix(2.267712,0,0,2.267712,-592.84807,-2769.1539)" /> |
336 | + <path |
337 | + sodipodi:type="arc" |
338 | + style="fill:#808080;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" |
339 | + id="path15093-0" |
340 | + sodipodi:cx="1206.7955" |
341 | + sodipodi:cy="673.53888" |
342 | + sodipodi:rx="18.993151" |
343 | + sodipodi:ry="18.993151" |
344 | + d="m 1225.7887,673.53888 c 0,10.48963 -8.5035,18.99315 -18.9932,18.99315 -10.4896,0 -18.9931,-8.50352 -18.9931,-18.99315 0,-10.48963 8.5035,-18.99315 18.9931,-18.99315 10.4897,0 18.9932,8.50352 18.9932,18.99315 z" |
345 | + transform="matrix(2.267712,0,0,2.267712,-109.9087,-2769.1539)" /> |
346 | + </g> |
347 | + </g> |
348 | + </g> |
349 | +</svg> |
350 | |
351 | === modified file 'app/graphics/podbird.png' |
352 | Binary files app/graphics/podbird.png 2015-01-04 10:20:41 +0000 and app/graphics/podbird.png 2015-04-11 21:39:04 +0000 differ |
353 | === added file 'app/graphics/smart.png' |
354 | Binary files app/graphics/smart.png 1970-01-01 00:00:00 +0000 and app/graphics/smart.png 2015-04-11 21:39:04 +0000 differ |
355 | === added file 'app/graphics/support.png' |
356 | Binary files app/graphics/support.png 1970-01-01 00:00:00 +0000 and app/graphics/support.png 2015-04-11 21:39:04 +0000 differ |
357 | === modified file 'app/podbird.qml' |
358 | --- app/podbird.qml 2015-03-27 15:38:43 +0000 |
359 | +++ app/podbird.qml 2015-04-11 21:39:04 +0000 |
360 | @@ -18,7 +18,9 @@ |
361 | |
362 | import QtQuick 2.3 |
363 | import Podbird 1.0 |
364 | +import UserMetrics 0.1 |
365 | import QtMultimedia 5.0 |
366 | +import Ubuntu.Connectivity 1.0 |
367 | import Qt.labs.settings 1.0 |
368 | import Ubuntu.Components 1.1 |
369 | import QtQuick.LocalStorage 2.0 |
370 | @@ -41,18 +43,35 @@ |
371 | backgroundColor: theme.background |
372 | |
373 | Component.onDestruction: { |
374 | - console.log("Download cancelled"); |
375 | + console.log("[LOG]: Download cancelled"); |
376 | downloader.cancel(); |
377 | + var db = Podcasts.init() |
378 | + db.transaction(function (tx) { |
379 | + tx.executeSql('UPDATE Episode SET queued=0 WHERE queued=1'); |
380 | + }) |
381 | } |
382 | |
383 | Component.onCompleted: { |
384 | + var db = Podcasts.init() |
385 | + db.transaction(function (tx) { |
386 | + tx.executeSql('UPDATE Episode SET queued=0 WHERE queued=1'); |
387 | + }) |
388 | + |
389 | var today = new Date() |
390 | // Only perform cleanup of old episodes once a day |
391 | if (Math.floor((today - settings.lastCheck)/86400000) >= 1 && settings.retentionDays !== -1) { |
392 | - console.log("[LOG]: Starting cleanup of old episodes..") |
393 | cleanUp(today, settings.retentionDays) |
394 | settings.lastCheck = today |
395 | } |
396 | + |
397 | + if (NetworkingStatus.limitedBandwith && settings.onlyWifiDownload || !NetworkingStatus.online || settings.maxEpisodeDownload === -1) { |
398 | + console.log("[LOG]: Skipped autodownloading due to missing wifi connectivity and only download on wifi preference.") |
399 | + console.log("[LOG]: Detecting limited bandwidth: " + NetworkingStatus.limitedBandwith) |
400 | + console.log("[LOG]: Detecting online connectivity: " + NetworkingStatus.online) |
401 | + console.log("[LOG]: User settings (onlywifidownload & maxEpisodeDownload): " + settings.onlyWifiDownload + ", " + settings.maxEpisodeDownload) |
402 | + } else { |
403 | + autoDownloadEpisodes(settings.maxEpisodeDownload) |
404 | + } |
405 | } |
406 | |
407 | property string currentName |
408 | @@ -73,6 +92,11 @@ |
409 | property string themeName: "Light.qml" |
410 | property int retentionDays: -1 |
411 | property var lastCheck: new Date() |
412 | + property bool firstRun: true |
413 | + property bool onlyWifiDownload: true |
414 | + property int maxEpisodeDownload: -1 |
415 | + property bool hideListened: false |
416 | + property bool showListView: true |
417 | } |
418 | |
419 | FileManager { |
420 | @@ -100,7 +124,7 @@ |
421 | var db = Podcasts.init(); |
422 | var finalLocation = fileManager.saveDownload(path); |
423 | db.transaction(function (tx) { |
424 | - tx.executeSql("UPDATE Episode SET downloadedfile=? WHERE guid=?", [finalLocation, downloadingGuid]); |
425 | + tx.executeSql("UPDATE Episode SET downloadedfile=?, queued=0 WHERE guid=?", [finalLocation, downloadingGuid]); |
426 | queue.shift(); |
427 | if (queue.length > 0) { |
428 | downloadingGuid = queue[0][0]; |
429 | @@ -120,13 +144,36 @@ |
430 | } |
431 | } |
432 | |
433 | + // UserMetrics to show Podbird stats on welcome screen |
434 | + Metric { |
435 | + id: podcastsMetric |
436 | + name: "podcast-metrics" |
437 | + // TRANSLATORS: this refers to a number of songs greater than one. The actual number will be prepended to the string automatically (plural forms are not yet fully supported in usermetrics, the library that displays that string) |
438 | + format: "<b>%1</b> " + i18n.tr("podcasts listened today") |
439 | + emptyFormat: i18n.tr("No podcasts listened today") |
440 | + domain: "com.mikeasoft.podbird" |
441 | + } |
442 | + |
443 | MediaPlayer { |
444 | id: player |
445 | + |
446 | + property bool podcastCounted: false |
447 | + |
448 | + onSourceChanged: { |
449 | + podcastCounted = false |
450 | + } |
451 | + |
452 | onPositionChanged: { |
453 | if (currentGuid == "" || duration <= 0) { |
454 | return; |
455 | } |
456 | |
457 | + if (position > 10000 && !podcastCounted) { |
458 | + podcastCounted = true |
459 | + podcastsMetric.increment() |
460 | + console.log("[LOG]: Podcast User metric incremented") |
461 | + } |
462 | + |
463 | var db = Podcasts.init(); |
464 | db.transaction(function (tx) { |
465 | tx.executeSql("UPDATE Episode SET position=? WHERE guid=?", [position >= duration ? 120 : position, currentGuid]); |
466 | @@ -139,7 +186,16 @@ |
467 | |
468 | PageStack { |
469 | id: mainStack |
470 | - Component.onCompleted: push(tabs) |
471 | + Component.onCompleted: { |
472 | + // Show the welcome wizard only when running the app for the first time |
473 | + if (settings.firstRun) { |
474 | + console.log("[LOG]: Detecting first time run by user. Starting welcome wizard.") |
475 | + push(Qt.resolvedUrl("welcomewizard/WelcomeWizard.qml")) |
476 | + } else { |
477 | + push(tabs) |
478 | + } |
479 | + } |
480 | + |
481 | Tabs { |
482 | id: tabs |
483 | |
484 | @@ -148,14 +204,32 @@ |
485 | objectName: "podcastsTab" |
486 | } |
487 | |
488 | - SearchTab { |
489 | + Tab { |
490 | id: searchTab |
491 | - objectName: "searchTab" |
492 | + |
493 | + title: i18n.tr("Find New Podcasts") |
494 | + |
495 | + page: Loader { |
496 | + parent: searchTab |
497 | + anchors.left: parent.left |
498 | + anchors.right: parent.right |
499 | + anchors.bottom: parent.bottom |
500 | + source: (tabs.selectedTab === searchTab) ? Qt.resolvedUrl("ui/SearchPage.qml") : "" |
501 | + } |
502 | } |
503 | |
504 | - SettingsTab { |
505 | + Tab { |
506 | id: settingsTab |
507 | - objectName: "settingsTab" |
508 | + |
509 | + title: i18n.tr("Settings") |
510 | + |
511 | + page: Loader { |
512 | + parent: settingsTab |
513 | + anchors.left: parent.left |
514 | + anchors.right: parent.right |
515 | + anchors.bottom: parent.bottom |
516 | + source: (tabs.selectedTab === settingsTab) ? Qt.resolvedUrl("ui/SettingsPage.qml") : "" |
517 | + } |
518 | } |
519 | } |
520 | } |
521 | @@ -189,6 +263,7 @@ |
522 | } |
523 | |
524 | function cleanUp(today, retentionDays) { |
525 | + console.log("[LOG]: Cleaning up old episodes") |
526 | var dayToMs = 86400000; //1 * 24 * 60 * 60 * 1000 |
527 | var db = Podcasts.init() |
528 | db.transaction(function (tx) { |
529 | @@ -206,4 +281,23 @@ |
530 | } |
531 | }); |
532 | } |
533 | + |
534 | + function autoDownloadEpisodes(maxEpisodeDownload) { |
535 | + console.log("[LOG]: Auto-downloading new episodes") |
536 | + var db = Podcasts.init() |
537 | + db.transaction(function (tx) { |
538 | + var rs = tx.executeSql("SELECT rowid, * FROM Podcast ORDER BY name ASC"); |
539 | + for (var i=0; i < rs.rows.length; i++) { |
540 | + var podcast = rs.rows.item(i); |
541 | + var rs2 = tx.executeSql("SELECT rowid, * FROM Episode WHERE podcast=? ORDER BY published DESC", [rs.rows.item(i).rowid]); |
542 | + var loopCount = maxEpisodeDownload > rs2.rows.length ? rs2.rows.length : maxEpisodeDownload |
543 | + for (var j=0; j < loopCount; j++) { |
544 | + if (!rs2.rows.item(j).downloadedfile && !rs2.rows.item(j).listened) { |
545 | + downloader.addDownload(rs2.rows.item(j).guid, rs2.rows.item(j).audiourl) |
546 | + tx.executeSql("UPDATE Episode SET queued=1 WHERE guid = ?", [rs2.rows.item(j).guid]); |
547 | + } |
548 | + } |
549 | + } |
550 | + }); |
551 | + } |
552 | } |
553 | |
554 | === modified file 'app/podcasts.js' |
555 | --- app/podcasts.js 2015-02-28 09:46:48 +0000 |
556 | +++ app/podcasts.js 2015-04-11 21:39:04 +0000 |
557 | @@ -1,5 +1,5 @@ |
558 | /* |
559 | - * Copyright 2015 Michael Sheldon <mike@mikeasoft.com> |
560 | + * Copyright 2015 Podbird Team |
561 | * |
562 | * This file is part of Podbird. |
563 | * |
564 | @@ -17,11 +17,24 @@ |
565 | */ |
566 | |
567 | function init() { |
568 | - var db = LocalStorage.openDatabaseSync("Podbird", "1.0", "Database of subscribed podcasts and their episodes", 1000000); |
569 | + var db = LocalStorage.openDatabaseSync("Podbird", "", "Database of subscribed podcasts and their episodes", 1000000); |
570 | + |
571 | db.transaction(function(tx) { |
572 | tx.executeSql('CREATE TABLE IF NOT EXISTS Podcast(artist TEXT, name TEXT, description TEXT, feed TEXT, image TEXT, lastupdate TIMESTAMP)'); |
573 | - tx.executeSql('CREATE TABLE IF NOT EXISTS Episode(guid TEXT, podcast INTEGER, name TEXT, subtitle TEXT, description TEXT, duration INTEGER, audiourl TEXT, downloadedfile TEXT, published TIMESTAMP, listened BOOLEAN, position INTEGER, FOREIGN KEY(podcast) REFERENCES Podcast(rowid))'); |
574 | + tx.executeSql('CREATE TABLE IF NOT EXISTS Episode(guid TEXT, podcast INTEGER, name TEXT, subtitle TEXT, description TEXT, duration INTEGER, audiourl TEXT, downloadedfile TEXT, published TIMESTAMP, queued BOOLEAN, listened BOOLEAN, position INTEGER, FOREIGN KEY(podcast) REFERENCES Podcast(rowid))'); |
575 | }); |
576 | + |
577 | + /* |
578 | + Schema Upgrade to v1.1 which adds a new queued boolean variable which is needed to track the queued status |
579 | + of a episode properly. |
580 | + */ |
581 | + if (db.version == "1.0") { |
582 | + db.changeVersion("1.0", "1.1", function(tx) { |
583 | + tx.executeSql('ALTER TABLE Episode ADD queued BOOLEAN'); |
584 | + tx.executeSql('UPDATE Episode SET queued=0'); |
585 | + }); |
586 | + } |
587 | + |
588 | return db; |
589 | } |
590 | |
591 | |
592 | === added directory 'app/settings' |
593 | === added file 'app/settings/About.qml' |
594 | --- app/settings/About.qml 1970-01-01 00:00:00 +0000 |
595 | +++ app/settings/About.qml 2015-04-11 21:39:04 +0000 |
596 | @@ -0,0 +1,151 @@ |
597 | +/* |
598 | + * Copyright 2015 Podbird Team |
599 | + * |
600 | + * This file is part of Podbird. |
601 | + * |
602 | + * Podbird is free software; you can redistribute it and/or modify |
603 | + * it under the terms of the GNU General Public License as published by |
604 | + * the Free Software Foundation; version 3. |
605 | + * |
606 | + * Podbird is distributed in the hope that it will be useful, |
607 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
608 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
609 | + * GNU General Public License for more details. |
610 | + * |
611 | + * You should have received a copy of the GNU General Public License |
612 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
613 | + */ |
614 | + |
615 | +import QtQuick 2.3 |
616 | +import Ubuntu.Components 1.1 |
617 | +import Ubuntu.Components.ListItems 1.0 as ListItem |
618 | + |
619 | +Page { |
620 | + id: aboutPage |
621 | + |
622 | + title: i18n.tr("About") |
623 | + visible: false |
624 | + |
625 | + head.sections.model: [i18n.tr("About"), i18n.tr("Credits")] |
626 | + |
627 | + VisualItemModel { |
628 | + id: tabs |
629 | + |
630 | + Item { |
631 | + width: tabView.width |
632 | + height: tabView.height |
633 | + |
634 | + Column { |
635 | + spacing: units.gu(4) |
636 | + anchors.centerIn: parent |
637 | + width: parent.width > units.gu(50) ? units.gu(50) : parent.width |
638 | + |
639 | + Image { |
640 | + height: width |
641 | + width: parent.width/2 |
642 | + source: "../graphics/podbird.png" |
643 | + anchors.horizontalCenter: parent.horizontalCenter |
644 | + } |
645 | + |
646 | + Column { |
647 | + width: parent.width |
648 | + Label { |
649 | + width: parent.width |
650 | + fontSize: "x-large" |
651 | + font.weight: Font.DemiBold |
652 | + horizontalAlignment: Text.AlignHCenter |
653 | + text: "Podbird" |
654 | + } |
655 | + Label { |
656 | + width: parent.width |
657 | + horizontalAlignment: Text.AlignHCenter |
658 | + text: qsTr("Version %1").arg(0.6) |
659 | + } |
660 | + } |
661 | + |
662 | + Column { |
663 | + anchors { |
664 | + left: parent.left |
665 | + right: parent.right |
666 | + margins: units.gu(2) |
667 | + } |
668 | + Label { |
669 | + width: parent.width |
670 | + wrapMode: Text.WordWrap |
671 | + horizontalAlignment: Text.AlignHCenter |
672 | + text: "(C) 2015 Podbird Team" |
673 | + } |
674 | + Label { |
675 | + fontSize: "small" |
676 | + width: parent.width |
677 | + wrapMode: Text.WordWrap |
678 | + horizontalAlignment: Text.AlignHCenter |
679 | + text: i18n.tr("Released under the terms of the GNU GPL v3") |
680 | + } |
681 | + } |
682 | + |
683 | + Label { |
684 | + width: parent.width |
685 | + wrapMode: Text.WordWrap |
686 | + fontSize: "small" |
687 | + horizontalAlignment: Text.AlignHCenter |
688 | + text: i18n.tr("Source code available on %1").arg("<a href=\"https://launchpad.net/podbird\">launchpad.net</a>") |
689 | + onLinkActivated: Qt.openUrlExternally(link) |
690 | + } |
691 | + } |
692 | + } |
693 | + |
694 | + Item { |
695 | + width: tabView.width |
696 | + height: tabView.height |
697 | + |
698 | + Column { |
699 | + anchors.topMargin: units.gu(1) |
700 | + anchors.fill: parent |
701 | + |
702 | + ListItem.Header { |
703 | + text: i18n.tr("Developers") |
704 | + } |
705 | + |
706 | + ListItem.Standard { |
707 | + showDivider: false |
708 | + text: "Michael Sheldon (Creator)" |
709 | + } |
710 | + |
711 | + ListItem.Standard { |
712 | + showDivider: false |
713 | + text: "Nekhelesh Ramananthan" |
714 | + } |
715 | + |
716 | + ListItem.Header { |
717 | + text: i18n.tr("Designer") |
718 | + } |
719 | + |
720 | + ListItem.Standard { |
721 | + showDivider: false |
722 | + text: "Kevin Feyder" |
723 | + } |
724 | + |
725 | + ListItem.Header { |
726 | + text: i18n.tr("Translators") |
727 | + } |
728 | + |
729 | + ListItem.Standard { |
730 | + showDivider: false |
731 | + text: "Ubuntu Translators Team" |
732 | + } |
733 | + } |
734 | + } |
735 | + } |
736 | + |
737 | + ListView { |
738 | + id: tabView |
739 | + model: tabs |
740 | + interactive: false |
741 | + anchors.fill: parent |
742 | + orientation: Qt.Horizontal |
743 | + snapMode: ListView.SnapOneItem |
744 | + currentIndex: aboutPage.head.sections.selectedIndex |
745 | + highlightMoveDuration: UbuntuAnimation.SlowDuration |
746 | + } |
747 | +} |
748 | |
749 | === added file 'app/settings/CMakeLists.txt' |
750 | --- app/settings/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
751 | +++ app/settings/CMakeLists.txt 2015-04-11 21:39:04 +0000 |
752 | @@ -0,0 +1,7 @@ |
753 | +file(GLOB SETTING_FILES *.qml) |
754 | + |
755 | +# Make the files visible in the qtcreator tree |
756 | +add_custom_target(podbird_SETTINGFiles ALL SOURCES ${SETTING_FILES}) |
757 | + |
758 | +install(FILES ${SETTING_FILES} DESTINATION ${PODBIRD_DIR}/settings) |
759 | + |
760 | |
761 | === added file 'app/settings/CleanSetting.qml' |
762 | --- app/settings/CleanSetting.qml 1970-01-01 00:00:00 +0000 |
763 | +++ app/settings/CleanSetting.qml 2015-04-11 21:39:04 +0000 |
764 | @@ -0,0 +1,65 @@ |
765 | +/* |
766 | + * Copyright 2015 Podbird Team |
767 | + * |
768 | + * This file is part of Podbird. |
769 | + * |
770 | + * Podbird is free software; you can redistribute it and/or modify |
771 | + * it under the terms of the GNU General Public License as published by |
772 | + * the Free Software Foundation; version 3. |
773 | + * |
774 | + * Podbird is distributed in the hope that it will be useful, |
775 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
776 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
777 | + * GNU General Public License for more details. |
778 | + * |
779 | + * You should have received a copy of the GNU General Public License |
780 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
781 | + */ |
782 | + |
783 | +import QtQuick 2.3 |
784 | +import Ubuntu.Components 1.1 |
785 | +import Ubuntu.Components.ListItems 1.0 as ListItem |
786 | + |
787 | +Page { |
788 | + id: cleanSettingPage |
789 | + |
790 | + visible: false |
791 | + title: i18n.tr("Delete older than") |
792 | + |
793 | + ListModel { |
794 | + id: cleanupModel |
795 | + Component.onCompleted: initialize() |
796 | + function initialize() { |
797 | + cleanupModel.append({ name: i18n.tr("Never"), value: -1 }) |
798 | + cleanupModel.append({ name: i18n.tr("%1 day", "%1 days", 7).arg(7), value: 7 }) |
799 | + cleanupModel.append({ name: i18n.tr("%1 month", "%1 months", 1).arg(1), value: 31 }) |
800 | + cleanupModel.append({ name: i18n.tr("%1 month", "%1 months", 3).arg(3), value: 90 }) |
801 | + cleanupModel.append({ name: i18n.tr("%1 month", "%1 months", 6).arg(6), value: 180 }) |
802 | + cleanupModel.append({ name: i18n.tr("%1 year", "%1 years", 1).arg(1), value: 360 }) |
803 | + } |
804 | + } |
805 | + |
806 | + UbuntuListView { |
807 | + id: cleanup |
808 | + |
809 | + model: cleanupModel |
810 | + anchors.fill: parent |
811 | + |
812 | + delegate: ListItem.Standard { |
813 | + text: model.name |
814 | + onClicked: { |
815 | + podbird.settings.retentionDays = model.value |
816 | + } |
817 | + |
818 | + Icon { |
819 | + width: units.gu(2) |
820 | + height: width |
821 | + name: "ok" |
822 | + visible: podbird.settings.retentionDays === model.value |
823 | + anchors.right: parent.right |
824 | + anchors.rightMargin: units.gu(3) |
825 | + anchors.verticalCenter: parent.verticalCenter |
826 | + } |
827 | + } |
828 | + } |
829 | +} |
830 | |
831 | === added file 'app/settings/DownloadSetting.qml' |
832 | --- app/settings/DownloadSetting.qml 1970-01-01 00:00:00 +0000 |
833 | +++ app/settings/DownloadSetting.qml 2015-04-11 21:39:04 +0000 |
834 | @@ -0,0 +1,64 @@ |
835 | +/* |
836 | + * Copyright 2015 Podbird Team |
837 | + * |
838 | + * This file is part of Podbird. |
839 | + * |
840 | + * Podbird is free software; you can redistribute it and/or modify |
841 | + * it under the terms of the GNU General Public License as published by |
842 | + * the Free Software Foundation; version 3. |
843 | + * |
844 | + * Podbird is distributed in the hope that it will be useful, |
845 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
846 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
847 | + * GNU General Public License for more details. |
848 | + * |
849 | + * You should have received a copy of the GNU General Public License |
850 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
851 | + */ |
852 | + |
853 | +import QtQuick 2.3 |
854 | +import Ubuntu.Components 1.1 |
855 | +import Ubuntu.Components.ListItems 1.0 as ListItem |
856 | + |
857 | +Page { |
858 | + id: downloadSetting |
859 | + |
860 | + visible: false |
861 | + title: i18n.tr("Download at most") |
862 | + |
863 | + ListModel { |
864 | + id: episodeDownloadNumber |
865 | + Component.onCompleted: initialize() |
866 | + function initialize() { |
867 | + episodeDownloadNumber.append({ name: i18n.tr("Never"), value: -1 }) |
868 | + episodeDownloadNumber.append({ name: i18n.tr("%1 episode", "%1 episodes", 1).arg(1), value: 1 }) |
869 | + episodeDownloadNumber.append({ name: i18n.tr("%1 episode", "%1 episodes", 3).arg(3), value: 3 }) |
870 | + episodeDownloadNumber.append({ name: i18n.tr("%1 episode", "%1 episodes", 5).arg(5), value: 5 }) |
871 | + episodeDownloadNumber.append({ name: i18n.tr("%1 episode", "%1 episodes", 10).arg(10), value: 10 }) |
872 | + } |
873 | + } |
874 | + |
875 | + UbuntuListView { |
876 | + id: download |
877 | + |
878 | + model: episodeDownloadNumber |
879 | + anchors.fill: parent |
880 | + |
881 | + delegate: ListItem.Standard { |
882 | + text: model.name |
883 | + onClicked: { |
884 | + podbird.settings.maxEpisodeDownload = model.value |
885 | + } |
886 | + |
887 | + Icon { |
888 | + width: units.gu(2) |
889 | + height: width |
890 | + name: "ok" |
891 | + visible: podbird.settings.maxEpisodeDownload === model.value |
892 | + anchors.right: parent.right |
893 | + anchors.rightMargin: units.gu(3) |
894 | + anchors.verticalCenter: parent.verticalCenter |
895 | + } |
896 | + } |
897 | + } |
898 | +} |
899 | |
900 | === added file 'app/settings/ThemeSetting.qml' |
901 | --- app/settings/ThemeSetting.qml 1970-01-01 00:00:00 +0000 |
902 | +++ app/settings/ThemeSetting.qml 2015-04-11 21:39:04 +0000 |
903 | @@ -0,0 +1,63 @@ |
904 | +/* |
905 | + * Copyright 2015 Podbird Team |
906 | + * |
907 | + * This file is part of Podbird. |
908 | + * |
909 | + * Podbird is free software; you can redistribute it and/or modify |
910 | + * it under the terms of the GNU General Public License as published by |
911 | + * the Free Software Foundation; version 3. |
912 | + * |
913 | + * Podbird is distributed in the hope that it will be useful, |
914 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
915 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
916 | + * GNU General Public License for more details. |
917 | + * |
918 | + * You should have received a copy of the GNU General Public License |
919 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
920 | + */ |
921 | + |
922 | +import QtQuick 2.3 |
923 | +import Ubuntu.Components 1.1 |
924 | +import Ubuntu.Components.ListItems 1.0 as ListItem |
925 | + |
926 | +Page { |
927 | + id: themeSettingPage |
928 | + |
929 | + visible: false |
930 | + title: i18n.tr("Theme") |
931 | + |
932 | + ListModel { |
933 | + id: themeModel |
934 | + Component.onCompleted: initialize() |
935 | + function initialize() { |
936 | + themeModel.append({ name: i18n.tr("Light"), file: "Light.qml" }) |
937 | + themeModel.append({ name: i18n.tr("Dark"), file: "Dark.qml" }) |
938 | + } |
939 | + } |
940 | + |
941 | + UbuntuListView { |
942 | + id: themes |
943 | + |
944 | + model: themeModel |
945 | + anchors.fill: parent |
946 | + |
947 | + delegate: ListItem.Standard { |
948 | + text: model.name |
949 | + onClicked: { |
950 | + var themeElement = model.file |
951 | + podbird.settings.themeName = themeElement |
952 | + podbird.themeManager.source = themeElement |
953 | + } |
954 | + |
955 | + Icon { |
956 | + width: units.gu(2) |
957 | + height: width |
958 | + name: "ok" |
959 | + visible: podbird.settings.themeName === model.file |
960 | + anchors.right: parent.right |
961 | + anchors.rightMargin: units.gu(3) |
962 | + anchors.verticalCenter: parent.verticalCenter |
963 | + } |
964 | + } |
965 | + } |
966 | +} |
967 | |
968 | === modified file 'app/themes/Dark.qml' |
969 | --- app/themes/Dark.qml 2015-03-04 02:58:36 +0000 |
970 | +++ app/themes/Dark.qml 2015-04-11 21:39:04 +0000 |
971 | @@ -21,12 +21,12 @@ |
972 | |
973 | QtObject { |
974 | // MainView |
975 | - property color background: "#1E1E23" |
976 | + property color background: "#242423" |
977 | |
978 | // Main Text Colors |
979 | property color baseText: "White" |
980 | property color baseSubText: "#999999" |
981 | - property color focusText: "#FF9900" |
982 | + property color focusText: "#35AF44" |
983 | |
984 | // Icon Colors |
985 | property color baseIcon: "White" |
986 | @@ -37,8 +37,8 @@ |
987 | property color neutralActionButton: UbuntuColors.coolGrey |
988 | |
989 | // Bottom Player Bar Colors |
990 | - property color bottomBarBackground: "#0F0F0F" |
991 | + property color bottomBarBackground: "#15141A" |
992 | |
993 | // Highlight Color |
994 | - property color hightlightListView: "#2C2C34" |
995 | + property color hightlightListView: "#333533" |
996 | } |
997 | |
998 | === modified file 'app/themes/Light.qml' |
999 | --- app/themes/Light.qml 2015-03-04 02:58:36 +0000 |
1000 | +++ app/themes/Light.qml 2015-04-11 21:39:04 +0000 |
1001 | @@ -21,12 +21,12 @@ |
1002 | |
1003 | QtObject { |
1004 | // MainView |
1005 | - property color background: "#EEEEEE" |
1006 | + property color background: "#ECECEC" |
1007 | |
1008 | // Main Text Colors |
1009 | property color baseText: UbuntuColors.darkGrey |
1010 | property color baseSubText: "#999999" |
1011 | - property color focusText: UbuntuColors.orange |
1012 | + property color focusText: "#35AF44" |
1013 | |
1014 | // Icon Colors |
1015 | property color baseIcon: UbuntuColors.darkGrey |
1016 | @@ -37,8 +37,8 @@ |
1017 | property color neutralActionButton: UbuntuColors.coolGrey |
1018 | |
1019 | // Bottom Player Bar Colors |
1020 | - property color bottomBarBackground: "#0F0F0F" |
1021 | + property color bottomBarBackground: "#323435" |
1022 | |
1023 | // Highlight Color |
1024 | - property color hightlightListView: "#D8D8D8" |
1025 | + property color hightlightListView: "#F5F5F5" |
1026 | } |
1027 | |
1028 | === modified file 'app/ui/ActionButton.qml' |
1029 | --- app/ui/ActionButton.qml 2015-03-08 11:10:07 +0000 |
1030 | +++ app/ui/ActionButton.qml 2015-04-11 21:39:04 +0000 |
1031 | @@ -22,7 +22,8 @@ |
1032 | AbstractButton { |
1033 | id: abstractButton |
1034 | |
1035 | - property string iconName |
1036 | + property alias iconName: _icon.name |
1037 | + property alias color: _icon.color |
1038 | |
1039 | Rectangle { |
1040 | visible: abstractButton.pressed |
1041 | @@ -35,7 +36,6 @@ |
1042 | width: units.gu(2.5) |
1043 | height: width |
1044 | anchors.centerIn: parent |
1045 | - name: abstractButton.iconName |
1046 | color: podbird.theme.baseIcon |
1047 | } |
1048 | } |
1049 | |
1050 | === modified file 'app/ui/BlurredBackground.qml' |
1051 | --- app/ui/BlurredBackground.qml 2015-02-10 06:57:54 +0000 |
1052 | +++ app/ui/BlurredBackground.qml 2015-04-11 21:39:04 +0000 |
1053 | @@ -25,15 +25,8 @@ |
1054 | Item { |
1055 | width: parent.width |
1056 | |
1057 | - property string art // : player.currentMetaFile === "" ? Qt.resolvedUrl("../images/music-app-cover@30.png") : player.currentMetaArt |
1058 | - |
1059 | - // dark layer |
1060 | - Rectangle { |
1061 | - anchors { |
1062 | - fill: parent |
1063 | - } |
1064 | - color: "black" |
1065 | - } |
1066 | + property string art |
1067 | + property real backgroundStrength: 0.4 |
1068 | |
1069 | // the album art |
1070 | Image { |
1071 | @@ -44,16 +37,6 @@ |
1072 | fillMode: Image.PreserveAspectCrop |
1073 | height: parent.height |
1074 | source: art // this has to be fixed for the default cover art to work - cant find in this dir |
1075 | - |
1076 | - // TODO: This should be investigated once http://pad.lv/1391368 |
1077 | - // is resolved. Once it is, these can either be set to |
1078 | - // "height" and "width" or a property exposed via the |
1079 | - // SDK or Thumbnailer to avoid a regression caused by |
1080 | - // these hardcoded values changing in the Thumbnailer. |
1081 | - // 512 is size of the "xlarge" thumbnails in pixels. |
1082 | - sourceSize.height: 512 |
1083 | - sourceSize.width: 512 |
1084 | - |
1085 | visible: false |
1086 | width: Math.max(parent.height, parent.width) |
1087 | } |
1088 | @@ -63,8 +46,8 @@ |
1089 | id: backgroundBlur |
1090 | anchors.fill: backgroundImage |
1091 | source: backgroundImage |
1092 | - radius: units.dp(42) |
1093 | - opacity: 0.2 |
1094 | + radius: units.dp(30) |
1095 | + opacity: backgroundStrength |
1096 | } |
1097 | onArtChanged: { |
1098 | // TODO: This is a work around for LP:1261078 and LP:1306845. Ideally, |
1099 | |
1100 | === added file 'app/ui/Card.qml' |
1101 | --- app/ui/Card.qml 1970-01-01 00:00:00 +0000 |
1102 | +++ app/ui/Card.qml 2015-04-11 21:39:04 +0000 |
1103 | @@ -0,0 +1,139 @@ |
1104 | +/* |
1105 | + * Copyright (C) 2014 |
1106 | + * Andrew Hayzen <ahayzen@gmail.com> |
1107 | + * |
1108 | + * This program is free software; you can redistribute it and/or modify |
1109 | + * it under the terms of the GNU General Public License as published by |
1110 | + * the Free Software Foundation; version 3. |
1111 | + * |
1112 | + * This program is distributed in the hope that it will be useful, |
1113 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1114 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1115 | + * GNU General Public License for more details. |
1116 | + * |
1117 | + * You should have received a copy of the GNU General Public License |
1118 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1119 | + */ |
1120 | + |
1121 | +import QtQuick 2.3 |
1122 | +import Ubuntu.Components 1.1 |
1123 | + |
1124 | +Item { |
1125 | + id: card |
1126 | + |
1127 | + /* Required by ColumnFlow */ |
1128 | + property int index |
1129 | + property var model |
1130 | + |
1131 | + property alias coverArt: imgFrame.source |
1132 | + property alias primaryText: primaryLabel.text |
1133 | + property alias secondaryText: secondaryLabel.text |
1134 | + property alias secondaryTextVisible: secondaryLabel.visible |
1135 | + |
1136 | + signal clicked(var mouse) |
1137 | + signal pressAndHold(var mouse) |
1138 | + |
1139 | + height: cardColumn.childrenRect.height + 2 * bg.anchors.margins |
1140 | + |
1141 | + /* Background for card */ |
1142 | + Rectangle { |
1143 | + id: bg |
1144 | + anchors.fill: parent |
1145 | + anchors.margins: units.gu(1) |
1146 | + color: podbird.theme.hightlightListView |
1147 | + } |
1148 | + |
1149 | + /* Column containing image and labels */ |
1150 | + Column { |
1151 | + id: cardColumn |
1152 | + |
1153 | + anchors.fill: bg |
1154 | + spacing: units.gu(0.5) |
1155 | + |
1156 | + Image { |
1157 | + id: imgFrame |
1158 | + width: parent.width |
1159 | + height: width |
1160 | + sourceSize.height: width |
1161 | + sourceSize.width: width |
1162 | + } |
1163 | + |
1164 | + Item { |
1165 | + height: units.gu(1) |
1166 | + width: units.gu(1) |
1167 | + } |
1168 | + |
1169 | + Label { |
1170 | + id: primaryLabel |
1171 | + anchors { |
1172 | + left: parent.left |
1173 | + right: parent.right |
1174 | + margins: units.gu(1) |
1175 | + } |
1176 | + color: podbird.theme.baseText |
1177 | + elide: Text.ElideRight |
1178 | + fontSize: "small" |
1179 | + opacity: 1.0 |
1180 | + wrapMode: Text.WordWrap |
1181 | + horizontalAlignment: Text.AlignHCenter |
1182 | + } |
1183 | + |
1184 | + Label { |
1185 | + id: secondaryLabel |
1186 | + anchors { |
1187 | + left: parent.left |
1188 | + leftMargin: units.gu(1) |
1189 | + right: parent.right |
1190 | + rightMargin: units.gu(1) |
1191 | + } |
1192 | + color: podbird.theme.baseSubText |
1193 | + elide: Text.ElideRight |
1194 | + fontSize: "small" |
1195 | + opacity: 1.0 |
1196 | + wrapMode: Text.WordWrap |
1197 | + horizontalAlignment: Text.AlignHCenter |
1198 | + } |
1199 | + |
1200 | + Item { |
1201 | + height: units.gu(1.5) |
1202 | + width: units.gu(1) |
1203 | + } |
1204 | + } |
1205 | + |
1206 | + /* Overlay for when card is pressed */ |
1207 | + Rectangle { |
1208 | + id: overlay |
1209 | + anchors.fill: bg |
1210 | + color: "#000" |
1211 | + opacity: 0 |
1212 | + |
1213 | + Behavior on opacity { |
1214 | + UbuntuNumberAnimation {} |
1215 | + } |
1216 | + } |
1217 | + |
1218 | + /* Capture mouse events */ |
1219 | + MouseArea { |
1220 | + anchors.fill: parent |
1221 | + onClicked: card.clicked(mouse) |
1222 | + onPressAndHold: card.pressAndHold(mouse) |
1223 | + onPressedChanged: overlay.opacity = pressed ? 0.3 : 0 |
1224 | + } |
1225 | + |
1226 | + /* Animations */ |
1227 | + Behavior on height { |
1228 | + UbuntuNumberAnimation {} |
1229 | + } |
1230 | + |
1231 | + Behavior on width { |
1232 | + UbuntuNumberAnimation {} |
1233 | + } |
1234 | + |
1235 | + Behavior on x { |
1236 | + UbuntuNumberAnimation {} |
1237 | + } |
1238 | + |
1239 | + Behavior on y { |
1240 | + UbuntuNumberAnimation {} |
1241 | + } |
1242 | +} |
1243 | |
1244 | === added file 'app/ui/CardView.qml' |
1245 | --- app/ui/CardView.qml 1970-01-01 00:00:00 +0000 |
1246 | +++ app/ui/CardView.qml 2015-04-11 21:39:04 +0000 |
1247 | @@ -0,0 +1,55 @@ |
1248 | +/* |
1249 | + * Copyright (C) 2014 |
1250 | + * Andrew Hayzen <ahayzen@gmail.com> |
1251 | + * |
1252 | + * This program is free software; you can redistribute it and/or modify |
1253 | + * it under the terms of the GNU General Public License as published by |
1254 | + * the Free Software Foundation; version 3. |
1255 | + * |
1256 | + * This program is distributed in the hope that it will be useful, |
1257 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1258 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1259 | + * GNU General Public License for more details. |
1260 | + * |
1261 | + * You should have received a copy of the GNU General Public License |
1262 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1263 | + */ |
1264 | + |
1265 | +import QtQuick 2.3 |
1266 | +import Ubuntu.Components 1.1 |
1267 | + |
1268 | +Flickable { |
1269 | + id: cardViewFlickable |
1270 | + anchors { |
1271 | + fill: parent |
1272 | + margins: units.gu(1) |
1273 | + } |
1274 | + |
1275 | + // dont use flow.contentHeight as it is inaccurate due to height of labels |
1276 | + // changing as they load |
1277 | + contentHeight: flow.contentHeight + flow.anchors.margins * 2 + units.gu(8) |
1278 | + contentWidth: width |
1279 | + |
1280 | + property alias count: flow.count |
1281 | + property alias delegate: flow.delegate |
1282 | + property var getter |
1283 | + property alias model: flow.model |
1284 | + property real itemWidth: units.gu(15) |
1285 | + |
1286 | + onGetterChanged: flow.getter = getter // cannot use alias to set a function (must be var) |
1287 | + |
1288 | + ColumnFlow { |
1289 | + id: flow |
1290 | + anchors.fill: parent |
1291 | + columns: parseInt(cardViewFlickable.width / itemWidth) || 1 // never drop to 0 |
1292 | + flickable: cardViewFlickable |
1293 | + } |
1294 | + |
1295 | + Component.onCompleted: { |
1296 | + // FIXME: workaround for qtubuntu not returning values depending on the grid unit definition |
1297 | + // for Flickable.maximumFlickVelocity and Flickable.flickDeceleration |
1298 | + var scaleFactor = units.gridUnit / 8; |
1299 | + maximumFlickVelocity = maximumFlickVelocity * scaleFactor; |
1300 | + flickDeceleration = flickDeceleration * scaleFactor; |
1301 | + } |
1302 | +} |
1303 | |
1304 | === added file 'app/ui/ColumnFlow.qml' |
1305 | --- app/ui/ColumnFlow.qml 1970-01-01 00:00:00 +0000 |
1306 | +++ app/ui/ColumnFlow.qml 2015-04-11 21:39:04 +0000 |
1307 | @@ -0,0 +1,494 @@ |
1308 | +/* |
1309 | + * Copyright (C) 2014, 2015 |
1310 | + * Andrew Hayzen <ahayzen@gmail.com> |
1311 | + * |
1312 | + * This program is free software; you can redistribute it and/or modify |
1313 | + * it under the terms of the GNU General Public License as published by |
1314 | + * the Free Software Foundation; version 3. |
1315 | + * |
1316 | + * This program is distributed in the hope that it will be useful, |
1317 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1318 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1319 | + * GNU General Public License for more details. |
1320 | + * |
1321 | + * You should have received a copy of the GNU General Public License |
1322 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1323 | + */ |
1324 | + |
1325 | +import QtQuick 2.3 |
1326 | + |
1327 | +Item { |
1328 | + id: columnFlow |
1329 | + property int columns: 1 |
1330 | + property Flickable flickable |
1331 | + property var model |
1332 | + property Component delegate |
1333 | + |
1334 | + property var getter: function (i) { return model.get(i); } // optional getter override (useful for music-app ms2 models) |
1335 | + |
1336 | + property int buffer: units.gu(20) |
1337 | + property var columnHeights: [] |
1338 | + property var columnHeightsMax: [] |
1339 | + property int columnWidth: parent.width / columns |
1340 | + property int contentHeight: 0 |
1341 | + property int count: model === undefined ? 0 : model.count |
1342 | + property int delayRebuildIndex: -1 |
1343 | + property var incubating: ({}) // incubating objects |
1344 | + property var items: ({}) |
1345 | + property var itemToColumn: ({}) // cache of the columns of indexes |
1346 | + property int lastIndex: 0 // the furtherest index loaded |
1347 | + property bool removing: false |
1348 | + property bool restoring: false // is the view restoring? |
1349 | + property var restoreItems: ({}) // when rebuilding items are stored here temporarily |
1350 | + |
1351 | + onColumnWidthChanged: { |
1352 | + if (restoring) { |
1353 | + return; |
1354 | + } else if (columns != columnHeights.length && visible) { |
1355 | + // number of columns has changed so rebuild the columns |
1356 | + rebuildColumns() |
1357 | + } else { // column width has changed update visible items properties linked to columnWidth |
1358 | + for (var column=0; column < columnHeights.length; column++) { |
1359 | + for (var i in columnHeights[column]) { |
1360 | + if (columnHeights[column].hasOwnProperty(i) && items.hasOwnProperty(i)) { |
1361 | + items[i].width = columnWidth; |
1362 | + items[i].x = column * columnWidth; |
1363 | + } |
1364 | + } |
1365 | + } |
1366 | + |
1367 | + ensureItemsVisible() |
1368 | + } |
1369 | + } |
1370 | + |
1371 | + onVisibleChanged: { |
1372 | + if (visible && delayRebuildIndex !== -1) { // restore from count change |
1373 | + if (delayRebuildIndex === 0) { |
1374 | + reset() |
1375 | + } else { |
1376 | + removeIndex(delayRebuildIndex) |
1377 | + } |
1378 | + |
1379 | + delayRebuildIndex = -1 |
1380 | + append(true) |
1381 | + } |
1382 | + |
1383 | + // number of columns has changed while invisible so reset if not already restoring |
1384 | + if (visible && !restoring && columns != columnHeights.length) { |
1385 | + rebuildColumns() |
1386 | + } |
1387 | + } |
1388 | + |
1389 | + ListModel { // fakemodel for connections to link to when there is no model |
1390 | + id: fakeModel |
1391 | + } |
1392 | + |
1393 | + Connections { |
1394 | + target: model === undefined ? fakeModel : model |
1395 | + onModelReset: { |
1396 | + if (!visible && lastIndex > 0) { |
1397 | + delayRebuildIndex = 0 |
1398 | + } else { |
1399 | + reset() |
1400 | + append() |
1401 | + } |
1402 | + } |
1403 | + onRowsInserted: { |
1404 | + if (!visible && lastIndex > 0) { |
1405 | + setDelayRebuildIndex(first) |
1406 | + } else { |
1407 | + if (first <= lastIndex) { |
1408 | + if (first === 0) { |
1409 | + reset() |
1410 | + } else { |
1411 | + removeIndex(first) // remove earliest index and all items after |
1412 | + } |
1413 | + } |
1414 | + |
1415 | + // Supply last index if larger as count is not updated until after insertion |
1416 | + append(true, last > count ? last : count) |
1417 | + } |
1418 | + } |
1419 | + onRowsRemoved: { |
1420 | + if (!visible) { |
1421 | + setDelayRebuildIndex(first) |
1422 | + } else { |
1423 | + if (first <= lastIndex) { |
1424 | + if (first === 0) { |
1425 | + reset() |
1426 | + } else { |
1427 | + removeIndex(first) // remove earliest index and all items after |
1428 | + } |
1429 | + |
1430 | + // count is not updated until after removal, so send insertMax |
1431 | + // insertMax is count - removal region inclusive - 1 (lastIndex is 1 infront) |
1432 | + |
1433 | + append(true, count - (1 + last - first) - 1) // rebuild any items on screen or before |
1434 | + } |
1435 | + } |
1436 | + } |
1437 | + } |
1438 | + |
1439 | + |
1440 | + Connections { |
1441 | + target: flickable |
1442 | + onContentYChanged: { |
1443 | + append() // Append any new items (scrolling down) |
1444 | + |
1445 | + ensureItemsVisible() |
1446 | + } |
1447 | + } |
1448 | + |
1449 | + // Append a new row of items if possible |
1450 | + function append(loadBefore, insertMax) |
1451 | + { |
1452 | + // Do not allow append to run if incubating |
1453 | + if (isIncubating() || restoring || removing) { |
1454 | + return; |
1455 | + } |
1456 | + |
1457 | + // get the columns in order |
1458 | + var columnsByHeight = getColumnsByHeight(); |
1459 | + var workDone = false; |
1460 | + |
1461 | + // check if a new item in each column is possible |
1462 | + for (var i=0; i < columnsByHeight.length; i++) { |
1463 | + var y = columnHeightsMax[columnsByHeight[i]]; |
1464 | + |
1465 | + // build new object in column if possible |
1466 | + // if insertMax is undefined then allow if there is work todo (from the count in the model) |
1467 | + // otherwise use the insertMax as the count to compare with the lastIndex added to the columnFlow |
1468 | + // and |
1469 | + // allow if the y position is within the viewport |
1470 | + // or if loadBefore is true then allow if the y position is before the viewport |
1471 | + if (((count > 0 && lastIndex < count && insertMax === undefined) || (insertMax !== undefined && lastIndex <= insertMax)) && (inViewport(y, 0) || (loadBefore === true && beforeViewport(y)))) { |
1472 | + incubateObject(lastIndex++, columnsByHeight[i], getMaxInColumn(columnsByHeight[i]), append); |
1473 | + workDone = true |
1474 | + } else { |
1475 | + break; |
1476 | + } |
1477 | + } |
1478 | + |
1479 | + if (!workDone) { // last iteration over append so visible ensure items are correct |
1480 | + ensureItemsVisible(); |
1481 | + } |
1482 | + } |
1483 | + |
1484 | + // Detect if a loaded object is before the viewport with a buffer |
1485 | + function beforeViewport(y) |
1486 | + { |
1487 | + return y <= flickable.contentY - buffer; |
1488 | + } |
1489 | + |
1490 | + // Cache the size of the columns for use later |
1491 | + function cacheColumnHeights() |
1492 | + { |
1493 | + columnHeightsMax = []; |
1494 | + |
1495 | + for (var i=0; i < columnHeights.length; i++) { |
1496 | + var sum = 0; |
1497 | + |
1498 | + for (var j in columnHeights[i]) { |
1499 | + sum += columnHeights[i][j]; |
1500 | + } |
1501 | + |
1502 | + columnHeightsMax.push(sum); |
1503 | + } |
1504 | + |
1505 | + if (!restoring) { // when not restoring otherwise user will be pushed to the top of the view |
1506 | + // set the height of columnFlow to max column (for flickable contentHeight) |
1507 | + contentHeight = Math.max.apply(null, columnHeightsMax); |
1508 | + } |
1509 | + } |
1510 | + |
1511 | + // Recache the visible items heights (due to a change in their height) |
1512 | + function cacheVisibleItemsHeights() |
1513 | + { |
1514 | + for (var i in items) { |
1515 | + if (items.hasOwnProperty(i)) { |
1516 | + columnHeights[itemToColumn[i]][i] = items[i].height; |
1517 | + } |
1518 | + } |
1519 | + |
1520 | + cacheColumnHeights(); |
1521 | + } |
1522 | + |
1523 | + // Ensures that the correct items are visible |
1524 | + function ensureItemsVisible() |
1525 | + { |
1526 | + for (var i in items) { |
1527 | + if (items.hasOwnProperty(i)) { |
1528 | + items[i].visible = inViewport(items[i].y, items[i].height) |
1529 | + } |
1530 | + } |
1531 | + } |
1532 | + |
1533 | + // Return if there are incubating objects |
1534 | + function isIncubating() |
1535 | + { |
1536 | + for (var i in incubating) { |
1537 | + if (incubating.hasOwnProperty(i)) { |
1538 | + return true; |
1539 | + } |
1540 | + } |
1541 | + |
1542 | + return false; |
1543 | + } |
1544 | + |
1545 | + // Run after incubation to store new column height and call any further append/restores |
1546 | + function finishIncubation(index, callback) |
1547 | + { |
1548 | + var obj = incubating[index].object; |
1549 | + delete incubating[index]; |
1550 | + |
1551 | + obj.heightChanged.connect(cacheVisibleItemsHeights) // if the height changes recache |
1552 | + |
1553 | + // Ensure properties linked to columnWidth are correct (as width may still be changing) |
1554 | + obj.x = itemToColumn[index] * columnWidth; |
1555 | + obj.width = columnWidth; |
1556 | + |
1557 | + items[index] = obj; |
1558 | + |
1559 | + columnHeights[itemToColumn[index]][index] = obj.height; // ensure height is the latest |
1560 | + |
1561 | + if (!isIncubating()) { |
1562 | + cacheColumnHeights(); |
1563 | + |
1564 | + // Check if there is any more work to be done (append or restore) |
1565 | + callback(); |
1566 | + } |
1567 | + } |
1568 | + |
1569 | + // Force any incubation to finish |
1570 | + function forceIncubationCompletion() |
1571 | + { |
1572 | + for (var i in incubating) { |
1573 | + if (incubating.hasOwnProperty(i)) { |
1574 | + incubating[i].forceCompletion() |
1575 | + } |
1576 | + } |
1577 | + } |
1578 | + |
1579 | + // Get the column index in order of height |
1580 | + function getColumnsByHeight() |
1581 | + { |
1582 | + var columnsByHeight = []; |
1583 | + |
1584 | + for (var i=0; i < columnHeightsMax.length; i++) { |
1585 | + var min = undefined; |
1586 | + var index = -1; |
1587 | + |
1588 | + // Find the smallest column that has not been found yet |
1589 | + for (var j=0; j < columnHeightsMax.length; j++) { |
1590 | + if (columnsByHeight.indexOf(j) === -1 && (min === undefined || columnHeightsMax[j] < min)) { |
1591 | + min = columnHeightsMax[j]; |
1592 | + index = j; |
1593 | + } |
1594 | + } |
1595 | + |
1596 | + columnsByHeight.push(index); |
1597 | + } |
1598 | + |
1599 | + return columnsByHeight; |
1600 | + } |
1601 | + |
1602 | + // Get the highest index for a column |
1603 | + function getMaxInColumn(column) |
1604 | + { |
1605 | + var max; |
1606 | + |
1607 | + for (var i in columnHeights[column]) { |
1608 | + if (columnHeights[column].hasOwnProperty(i)) { |
1609 | + i = parseInt(i); |
1610 | + |
1611 | + if (items.hasOwnProperty(i)) { |
1612 | + if (i > max || max === undefined) { |
1613 | + max = i; |
1614 | + } |
1615 | + } |
1616 | + } |
1617 | + } |
1618 | + |
1619 | + return max; |
1620 | + } |
1621 | + |
1622 | + // Incubate an object for creation |
1623 | + function incubateObject(index, column, anchorIndex, callback) |
1624 | + { |
1625 | + // Load parameters to send to the object on creation |
1626 | + var params = { |
1627 | + "anchors.top": anchorIndex === undefined ? parent.top : items[anchorIndex].bottom, |
1628 | + index: index, |
1629 | + model: getter(index), |
1630 | + width: columnWidth, |
1631 | + x: column * columnWidth |
1632 | + }; |
1633 | + |
1634 | + // Start incubating and cache the column |
1635 | + incubating[index] = delegate.incubateObject(parent, params); |
1636 | + itemToColumn[index] = column; |
1637 | + |
1638 | + if (incubating[index].status != Component.Ready) { |
1639 | + incubating[index].onStatusChanged = function(status) { |
1640 | + if (status == Component.Ready) { |
1641 | + finishIncubation(index, callback) |
1642 | + } |
1643 | + } |
1644 | + } else { |
1645 | + finishIncubation(index, callback) |
1646 | + } |
1647 | + } |
1648 | + |
1649 | + // Detect if a loaded object is in the viewport with a buffer |
1650 | + function inViewport(y, height) |
1651 | + { |
1652 | + return flickable.contentY - buffer < y + height && y < flickable.contentY + flickable.height + buffer; |
1653 | + } |
1654 | + |
1655 | + // Number of columns has changed rebuild with live items |
1656 | + function rebuildColumns() |
1657 | + { |
1658 | + restoring = true; |
1659 | + var i; |
1660 | + |
1661 | + forceIncubationCompletion() |
1662 | + |
1663 | + columnHeights = [] |
1664 | + columnHeightsMax = [] |
1665 | + |
1666 | + for (i=0; i < columns; i++) { |
1667 | + columnHeights.push({}); |
1668 | + columnHeightsMax.push(0); |
1669 | + } |
1670 | + |
1671 | + lastIndex = 0; |
1672 | + |
1673 | + restoreItems = items; |
1674 | + items = {}; |
1675 | + |
1676 | + restoreExisting() |
1677 | + |
1678 | + restoring = false; |
1679 | + |
1680 | + cacheColumnHeights(); // rebuilds contentHeight |
1681 | + |
1682 | + // If the columns have changed while the view was locked rerun |
1683 | + if (columns != columnHeights.length && visible) { |
1684 | + rebuildColumns() |
1685 | + } else { |
1686 | + append() // check if any new items can be added |
1687 | + } |
1688 | + } |
1689 | + |
1690 | + // Remove an index from the model (invalidating anything after) |
1691 | + function removeIndex(index) |
1692 | + { |
1693 | + removing = true |
1694 | + |
1695 | + forceIncubationCompletion() |
1696 | + |
1697 | + for (var i in items) { |
1698 | + if (i >= index && items.hasOwnProperty(i)) { |
1699 | + delete columnHeights[itemToColumn[i]][i] |
1700 | + delete itemToColumn[i] |
1701 | + |
1702 | + items[i].destroy() |
1703 | + delete items[i] |
1704 | + } |
1705 | + } |
1706 | + |
1707 | + lastIndex = index |
1708 | + removing = false |
1709 | + |
1710 | + cacheColumnHeights() |
1711 | + } |
1712 | + |
1713 | + // Restores existing items into potentially new positions |
1714 | + function restoreExisting() |
1715 | + { |
1716 | + var i; |
1717 | + |
1718 | + // get the columns in order |
1719 | + var columnsByHeight = getColumnsByHeight(); |
1720 | + var workDone = false; |
1721 | + |
1722 | + // check if a new item in each column is possible |
1723 | + for (i=0; i < columnsByHeight.length; i++) { |
1724 | + var column = columnsByHeight[i]; |
1725 | + |
1726 | + // build new object in column if possible |
1727 | + if (count > 0 && lastIndex < count) { |
1728 | + if (restoreItems.hasOwnProperty(lastIndex)) { |
1729 | + var item = restoreItems[lastIndex]; |
1730 | + var maxInColumn = getMaxInColumn(column); // get lowest item in column |
1731 | + |
1732 | + itemToColumn[lastIndex] = column; |
1733 | + columnHeights[column][lastIndex] = item.height; // ensure height is the latest |
1734 | + |
1735 | + // Rebuild item properties |
1736 | + item.anchors.bottom = undefined |
1737 | + item.anchors.top = maxInColumn === undefined ? parent.top : items[maxInColumn].bottom; |
1738 | + item.x = column * columnWidth; |
1739 | + item.visible = inViewport(item.y, item.height); |
1740 | + |
1741 | + // Migrate item from restoreItems to items |
1742 | + items[lastIndex] = item; |
1743 | + delete restoreItems[lastIndex]; |
1744 | + |
1745 | + // set after restore as height will likely change causing cacheVisibleItemsHeights to be run |
1746 | + item.width = columnWidth; |
1747 | + |
1748 | + cacheColumnHeights(); // ensure column heights are up to date |
1749 | + |
1750 | + lastIndex++; |
1751 | + workDone = true; |
1752 | + } |
1753 | + } else { |
1754 | + break; |
1755 | + } |
1756 | + } |
1757 | + |
1758 | + if (workDone) { |
1759 | + restoreExisting() // if work done then check if any more is needed |
1760 | + } else { |
1761 | + restoreItems = {}; // ensure restoreItems is empty |
1762 | + } |
1763 | + } |
1764 | + |
1765 | + // Reset the column flow |
1766 | + function reset() |
1767 | + { |
1768 | + forceIncubationCompletion() |
1769 | + |
1770 | + // Destroy any old items |
1771 | + for (var j in items) { |
1772 | + if (items.hasOwnProperty(j)) { |
1773 | + items[j].destroy() |
1774 | + } |
1775 | + } |
1776 | + |
1777 | + // Reset and rebuild the variables |
1778 | + items = ({}) |
1779 | + itemToColumn = ({}) |
1780 | + lastIndex = 0 |
1781 | + |
1782 | + columnHeights = [] |
1783 | + |
1784 | + for (var k=0; k < columns; k++) { |
1785 | + columnHeights.push({}) |
1786 | + } |
1787 | + |
1788 | + cacheColumnHeights() |
1789 | + |
1790 | + contentHeight = 0 |
1791 | + } |
1792 | + |
1793 | + function setDelayRebuildIndex(index) |
1794 | + { |
1795 | + if (delayRebuildIndex === -1 || index < lastIndex) { |
1796 | + delayRebuildIndex = index |
1797 | + } |
1798 | + } |
1799 | + |
1800 | + Component.onCompleted: append(true) |
1801 | +} |
1802 | |
1803 | === modified file 'app/ui/EmptyState.qml' |
1804 | --- app/ui/EmptyState.qml 2015-03-04 03:27:26 +0000 |
1805 | +++ app/ui/EmptyState.qml 2015-04-11 21:39:04 +0000 |
1806 | @@ -31,14 +31,18 @@ |
1807 | property alias iconName: emptyIcon.name |
1808 | property alias title: emptyLabel.text |
1809 | property alias subTitle: emptySublabel.text |
1810 | + property alias iconSource: emptyIcon.source |
1811 | + |
1812 | + property real iconHeight: units.gu(10) |
1813 | + property real iconWidth: units.gu(10) |
1814 | |
1815 | height: childrenRect.height |
1816 | width: parent.width |
1817 | |
1818 | Icon { |
1819 | id: emptyIcon |
1820 | - width: height |
1821 | - height: units.gu(10) |
1822 | + width: parent.iconWidth |
1823 | + height: parent.iconHeight |
1824 | color: podbird.theme.baseIcon |
1825 | anchors.horizontalCenter: parent.horizontalCenter |
1826 | } |
1827 | |
1828 | === modified file 'app/ui/EpisodesPage.qml' |
1829 | --- app/ui/EpisodesPage.qml 2015-03-29 15:33:26 +0000 |
1830 | +++ app/ui/EpisodesPage.qml 2015-04-11 21:39:04 +0000 |
1831 | @@ -30,17 +30,21 @@ |
1832 | id: episodesPage |
1833 | |
1834 | visible: false |
1835 | - title: episodeName |
1836 | + title: i18n.tr("Podcast") |
1837 | + flickable: null |
1838 | |
1839 | property string episodeName |
1840 | property string episodeId |
1841 | property string episodeArtist |
1842 | property string episodeImage |
1843 | + property string tempGuid: "NULL" |
1844 | |
1845 | property bool episodesUpdating: false; |
1846 | |
1847 | Component.onCompleted: { |
1848 | loadEpisodes(episodeId, episodeArtist, episodeImage) |
1849 | + if (downloader.downloadingGuid != "") |
1850 | + tempGuid = downloader.downloadingGuid |
1851 | } |
1852 | |
1853 | /* |
1854 | @@ -95,7 +99,7 @@ |
1855 | onTriggered: { |
1856 | var db = Podcasts.init(); |
1857 | db.transaction(function (tx) { |
1858 | - tx.executeSql("UPDATE Episode SET listened=1 WHERE podcast=?", [episodeModel.pid]); |
1859 | + tx.executeSql("UPDATE Episode SET listened=1 WHERE podcast=?", [episodeId]); |
1860 | refreshModel(); |
1861 | }); |
1862 | } |
1863 | @@ -122,6 +126,7 @@ |
1864 | episodeList.forceActiveFocus() |
1865 | searchField.text = "" |
1866 | episodesPage.state = "default" |
1867 | + episodeList.positionViewAtBeginning() |
1868 | } |
1869 | } |
1870 | |
1871 | @@ -139,7 +144,36 @@ |
1872 | Connections { |
1873 | target: downloader |
1874 | onDownloadingGuidChanged: { |
1875 | - loadEpisodes(episodeId, episodeArtist, episodeImage); |
1876 | + var db = Podcasts.init(); |
1877 | + db.transaction(function (tx) { |
1878 | + /* |
1879 | + If tempGuid is NULL, then the episode currently being downloaded is not found within |
1880 | + this podcast. On the other hand, if it is within this podcast, then update the episodeModel |
1881 | + with the downloadedfile location we just received from the downloader. |
1882 | + */ |
1883 | + if (tempGuid != "NULL") { |
1884 | + var rs2 = tx.executeSql("SELECT downloadedfile, podcast FROM Episode WHERE guid=?", [tempGuid]); |
1885 | + for (var i=0; i<episodeModel.count; i++) { |
1886 | + if (episodeModel.get(i).guid == tempGuid) { |
1887 | + console.log("[LOG]: Setting episode download URL to " + rs2.rows.item(0).downloadedfile) |
1888 | + episodeModel.setProperty(i, "downloadedfile", rs2.rows.item(0).downloadedfile) |
1889 | + break |
1890 | + } |
1891 | + } |
1892 | + tempGuid = "NULL" |
1893 | + } |
1894 | + |
1895 | + /* |
1896 | + Here it is checked if the currently downloaded episode belongs to the podcast |
1897 | + page being currently displayed. If it is, then the downloaded episode guid is |
1898 | + stored in the tempGuid variable to track it. |
1899 | + */ |
1900 | + var rs = tx.executeSql("SELECT podcast FROM Episode WHERE guid=?", [downloader.downloadingGuid]); |
1901 | + |
1902 | + if (downloader.downloadingGuid != "" && rs.rows.item(0).podcast == episodeId && tempGuid == "NULL") { |
1903 | + tempGuid = downloader.downloadingGuid |
1904 | + } |
1905 | + }); |
1906 | } |
1907 | } |
1908 | |
1909 | @@ -155,12 +189,12 @@ |
1910 | onClicked: { |
1911 | var db = Podcasts.init(); |
1912 | db.transaction(function (tx) { |
1913 | - var rs = tx.executeSql("SELECT downloadedfile FROM Episode WHERE downloadedfile NOT NULL AND podcast=?", [episodeModel.pid]); |
1914 | + var rs = tx.executeSql("SELECT downloadedfile FROM Episode WHERE downloadedfile NOT NULL AND podcast=?", [episodeId]); |
1915 | for(var i = 0; i < rs.rows.length; i++) { |
1916 | fileManager.deleteFile(rs.rows.item(i).downloadedfile); |
1917 | } |
1918 | - tx.executeSql("DELETE FROM Episode WHERE podcast=?", [episodeModel.pid]); |
1919 | - tx.executeSql("DELETE FROM Podcast WHERE rowid=?", [episodeModel.pid]); |
1920 | + tx.executeSql("DELETE FROM Episode WHERE podcast=?", [episodeId]); |
1921 | + tx.executeSql("DELETE FROM Podcast WHERE rowid=?", [episodeId]); |
1922 | mainStack.pop() |
1923 | PopupUtils.close(dialogInternal) |
1924 | }); |
1925 | @@ -176,20 +210,135 @@ |
1926 | } |
1927 | } |
1928 | |
1929 | + Component { |
1930 | + id: popoverComponent |
1931 | + |
1932 | + Popover { |
1933 | + id: popover |
1934 | + |
1935 | + property bool queued: false |
1936 | + property bool listened: false |
1937 | + property string downloadedfile: "" |
1938 | + property string guid: "" |
1939 | + property string audiourl: "" |
1940 | + property int index: -1 |
1941 | + |
1942 | + contentWidth: mainColumn.width |
1943 | + |
1944 | + Column { |
1945 | + id: mainColumn |
1946 | + |
1947 | + width: Math.max(download.width, listen.width) |
1948 | + anchors.top: parent.top |
1949 | + |
1950 | + ListItem.Empty { |
1951 | + id: download |
1952 | + |
1953 | + width: Math.max(row.width, row2.width) |
1954 | + |
1955 | + Row { |
1956 | + id: row |
1957 | + |
1958 | + spacing: units.gu(3) |
1959 | + anchors.left: parent.left |
1960 | + anchors.leftMargin: units.gu(2) |
1961 | + anchors.verticalCenter: parent.verticalCenter |
1962 | + width: downloadIcon.width + downloadText.implicitWidth + row.spacing + units.gu(4) |
1963 | + |
1964 | + Icon { |
1965 | + id: downloadIcon |
1966 | + width: height |
1967 | + height: downloadText.height |
1968 | + name: popover.downloadedfile ? "delete" : (popover.queued && downloader.downloadingGuid !== popover.guid ? "history" : "save") |
1969 | + } |
1970 | + |
1971 | + Label { |
1972 | + id: downloadText |
1973 | + color: UbuntuColors.darkGrey |
1974 | + text: popover.downloadedfile ? i18n.tr("Delete local file") |
1975 | + : (popover.queued && downloader.downloadingGuid !== popover.guid ? i18n.tr("Episode queued for download") |
1976 | + : i18n.tr("Download episode")) |
1977 | + } |
1978 | + } |
1979 | + |
1980 | + enabled: downloader.downloadingGuid !== popover.guid |
1981 | + onClicked: { |
1982 | + var db = Podcasts.init(); |
1983 | + if (popover.downloadedfile) { |
1984 | + fileManager.deleteFile(popover.downloadedfile); |
1985 | + db.transaction(function (tx) { |
1986 | + tx.executeSql("UPDATE Episode SET downloadedfile = NULL WHERE guid = ?", [popover.guid]); |
1987 | + }); |
1988 | + episodeModel.setProperty(popover.index, "downloadedfile", "") |
1989 | + } else { |
1990 | + db.transaction(function (tx) { |
1991 | + tx.executeSql("UPDATE Episode SET queued=1 WHERE guid = ?", [popover.guid]); |
1992 | + }); |
1993 | + episodeModel.setProperty(popover.index, "queued", 1) |
1994 | + downloader.addDownload(popover.guid, popover.audiourl); |
1995 | + } |
1996 | + PopupUtils.close(popover) |
1997 | + } |
1998 | + } |
1999 | + |
2000 | + ListItem.Empty { |
2001 | + id: listen |
2002 | + |
2003 | + showDivider: false |
2004 | + width: Math.max(row.width, row2.width) |
2005 | + |
2006 | + Row { |
2007 | + id: row2 |
2008 | + |
2009 | + spacing: units.gu(3) |
2010 | + anchors.left: parent.left |
2011 | + anchors.leftMargin: units.gu(2) |
2012 | + anchors.verticalCenter: parent.verticalCenter |
2013 | + width: listenIcon.width + listenText.implicitWidth + row2.spacing + units.gu(4) |
2014 | + |
2015 | + Icon { |
2016 | + id: listenIcon |
2017 | + width: height |
2018 | + height: listenText.height |
2019 | + name: popover.listened ? "view-collapse" : "select" |
2020 | + } |
2021 | + |
2022 | + Label { |
2023 | + id: listenText |
2024 | + color: UbuntuColors.darkGrey |
2025 | + text: popover.listened ? "Mark episode unlistened" : "Mark episode listened" |
2026 | + } |
2027 | + } |
2028 | + |
2029 | + onClicked: { |
2030 | + var db = Podcasts.init(); |
2031 | + db.transaction(function (tx) { |
2032 | + if (popover.listened) |
2033 | + tx.executeSql("UPDATE Episode SET listened=0 WHERE guid=?", [popover.guid]) |
2034 | + else |
2035 | + tx.executeSql("UPDATE Episode SET listened=1 WHERE guid=?", [popover.guid]) |
2036 | + refreshModel(); |
2037 | + }); |
2038 | + PopupUtils.close(popover) |
2039 | + } |
2040 | + } |
2041 | + } |
2042 | + } |
2043 | + } |
2044 | + |
2045 | EmptyState { |
2046 | anchors.centerIn: parent |
2047 | anchors.verticalCenterOffset: Qt.inputMethod.visible ? units.gu(4) : 0 |
2048 | - visible: episodesPage.state === "search" && sortedEpisodeModel.count === 0 |
2049 | - iconName: "music-app-symbolic" |
2050 | - title: i18n.tr("No Episodes found") |
2051 | - subTitle: i18n.tr("No episodes found matching the search term.") |
2052 | + visible: (episodesPage.state === "search" && sortedEpisodeModel.count === 0) || (episodeModel.count === 0 && podbird.settings.hideListened) |
2053 | + iconHeight: units.gu(12) |
2054 | + iconWidth: iconHeight + units.gu(10) |
2055 | + iconSource: Qt.resolvedUrl("../graphics/notFound.svg") |
2056 | + title: podbird.settings.hideListened ? i18n.tr("No more episodes") : i18n.tr("No Episodes found") |
2057 | + subTitle: podbird.settings.hideListened ? i18n.tr("All episodes have been listened to.") : i18n.tr("No episodes found matching the search term.") |
2058 | } |
2059 | |
2060 | ListModel { |
2061 | id: episodeModel |
2062 | - property string pid; |
2063 | - property string artist; |
2064 | - property string image; |
2065 | } |
2066 | |
2067 | SortFilterModel { |
2068 | @@ -199,12 +348,126 @@ |
2069 | filter.pattern: RegExp(searchField.text, "gi") |
2070 | } |
2071 | |
2072 | - ListView { |
2073 | + function formatTime(seconds) { |
2074 | + var time = Podcasts.getTimeDiff(seconds) |
2075 | + var hour = time[0] |
2076 | + var minute = time[1] |
2077 | + // TRANSLATORS: the first argument is the number of hours, |
2078 | + // followed by minute (eg. 20h 3m) |
2079 | + if(hour > 0 && minute > 0) { |
2080 | + // xgettext: no-c-format |
2081 | + return (i18n.tr("%1 hr %2 min")) |
2082 | + .arg(hour) |
2083 | + .arg(minute) |
2084 | + } |
2085 | + |
2086 | + // TRANSLATORS: this string indicates the number of hours |
2087 | + // eg. 20h (no plural state required) |
2088 | + else if(hour > 0 && minute === 0) { |
2089 | + // xgettext: no-c-format |
2090 | + return (i18n.tr("%1 hr")) |
2091 | + .arg(hour) |
2092 | + } |
2093 | + |
2094 | + // TRANSLATORS: this string indicates the number of minutes |
2095 | + // eg. 15m (no plural state required) |
2096 | + else if(hour === 0 && minute > 0) { |
2097 | + // xgettext: no-c-format |
2098 | + return (i18n.tr("%1 min")) |
2099 | + .arg(minute) |
2100 | + } |
2101 | + |
2102 | + else { |
2103 | + return Podcasts.formatTime(seconds) |
2104 | + } |
2105 | + } |
2106 | + |
2107 | + UbuntuListView { |
2108 | id: episodeList |
2109 | |
2110 | + Component.onCompleted: { |
2111 | + // FIXME: workaround for qtubuntu not returning values depending on the grid unit definition |
2112 | + // for Flickable.maximumFlickVelocity and Flickable.flickDeceleration |
2113 | + var scaleFactor = units.gridUnit / 8; |
2114 | + maximumFlickVelocity = maximumFlickVelocity * scaleFactor; |
2115 | + flickDeceleration = flickDeceleration * scaleFactor; |
2116 | + } |
2117 | + |
2118 | + anchors.fill: parent |
2119 | + model: sortedEpisodeModel |
2120 | + |
2121 | clip: true |
2122 | - anchors.fill: parent |
2123 | - model: sortedEpisodeModel |
2124 | + section.property: "listened" |
2125 | + section.labelPositioning: ViewSection.InlineLabels |
2126 | + |
2127 | + section.delegate: Rectangle { |
2128 | + width: parent.width |
2129 | + color: section === "0" ? podbird.theme.hightlightListView : "Transparent" |
2130 | + height: header.implicitHeight + units.gu(2) |
2131 | + Label { |
2132 | + id: header |
2133 | + anchors { |
2134 | + left: parent.left |
2135 | + right: parent.right |
2136 | + margins: units.gu(2) |
2137 | + verticalCenter: parent.verticalCenter |
2138 | + } |
2139 | + fontSize: "x-large" |
2140 | + text: section === "0" ? i18n.tr("Unheard") : i18n.tr("Listened") |
2141 | + } |
2142 | + } |
2143 | + |
2144 | + header: BlurredBackground { |
2145 | + id: blurredBackground |
2146 | + |
2147 | + art: episodeImage |
2148 | + width: parent.width |
2149 | + visible: episodesPage.state !== "search" && sortedEpisodeModel.count !== 0 |
2150 | + height: episodesPage.state !== "search" && sortedEpisodeModel.count !== 0 ? cover.height + units.gu(4) : 0 |
2151 | + backgroundStrength: podbird.settings.themeName === "Light.qml" ? 0.3 : 0.6 |
2152 | + |
2153 | + Image { |
2154 | + id:cover |
2155 | + width: units.gu(12) |
2156 | + height: width |
2157 | + sourceSize.height: width |
2158 | + sourceSize.width: width |
2159 | + source: episodeImage |
2160 | + anchors { |
2161 | + left: parent.left |
2162 | + top: parent.top |
2163 | + margins: units.gu(2) |
2164 | + } |
2165 | + } |
2166 | + |
2167 | + Column { |
2168 | + id: podcastTitle |
2169 | + |
2170 | + anchors { |
2171 | + left: cover.right |
2172 | + right: parent.right |
2173 | + bottom: parent.bottom |
2174 | + margins: units.gu(2) |
2175 | + } |
2176 | + |
2177 | + Label { |
2178 | + text: episodeName |
2179 | + width: parent.width |
2180 | + wrapMode: Text.WordWrap |
2181 | + maximumLineCount: 2 |
2182 | + elide: Text.ElideRight |
2183 | + color: podbird.theme.baseText |
2184 | + } |
2185 | + |
2186 | + Label { |
2187 | + text: i18n.tr("%1 episode", "%1 episodes", episodeList.count).arg(episodeList.count) |
2188 | + width: parent.width |
2189 | + elide: Text.ElideRight |
2190 | + fontSize: "x-small" |
2191 | + color: podbird.theme.baseText |
2192 | + } |
2193 | + } |
2194 | + } |
2195 | |
2196 | footer: Item { |
2197 | width: parent.width |
2198 | @@ -214,51 +477,41 @@ |
2199 | delegate: ListItem.Empty { |
2200 | id: listItem |
2201 | |
2202 | - property bool expanded: false |
2203 | + property bool expanded |
2204 | |
2205 | - width: parent.width |
2206 | - height: mainColumn.height |
2207 | + height: dataColumn.height + units.gu(2) |
2208 | highlightWhenPressed: false |
2209 | + showDivider: false |
2210 | |
2211 | - onClicked: listItem.expanded = !listItem.expanded |
2212 | + onClicked: { |
2213 | + expanded = !expanded; |
2214 | + } |
2215 | |
2216 | Rectangle { |
2217 | - anchors.fill: parent |
2218 | - color: listItem.pressed ? podbird.theme.hightlightListView : "transparent" |
2219 | + visible: !model.listened |
2220 | + width: parent.width |
2221 | + height: dataColumn.height + units.gu(2) |
2222 | + color: podbird.theme.hightlightListView |
2223 | } |
2224 | |
2225 | Column { |
2226 | - id: mainColumn |
2227 | - |
2228 | - anchors { |
2229 | - top: parent.top |
2230 | - left: parent.left |
2231 | - right: parent.right |
2232 | - margins: units.gu(2) |
2233 | - topMargin: units.gu(1) |
2234 | - } |
2235 | + id: dataColumn |
2236 | |
2237 | spacing: units.gu(1) |
2238 | + anchors.left: parent.left |
2239 | + anchors.right: parent.right |
2240 | + anchors.margins: units.gu(2) |
2241 | + anchors.top: parent.top |
2242 | + anchors.topMargin: units.gu(0.5) |
2243 | |
2244 | RowLayout { |
2245 | - id: titleRow |
2246 | + id: rowlayout |
2247 | |
2248 | width: parent.width |
2249 | - spacing: units.gu(2) |
2250 | - |
2251 | - Image { |
2252 | - id: imgFrame |
2253 | - width: units.gu(6) |
2254 | - height: width |
2255 | - sourceSize.height: width |
2256 | - sourceSize.width: width |
2257 | - source: model.image |
2258 | - } |
2259 | + height: titleColumn.height |
2260 | |
2261 | Column { |
2262 | - id: detailColumn |
2263 | - |
2264 | - anchors.verticalCenter: imgFrame.verticalCenter |
2265 | + id: titleColumn |
2266 | Layout.fillWidth: true |
2267 | |
2268 | Label { |
2269 | @@ -267,19 +520,88 @@ |
2270 | maximumLineCount: 2 |
2271 | wrapMode: Text.WordWrap |
2272 | elide: Text.ElideRight |
2273 | - color: currentGuid === model.guid ? podbird.theme.focusText |
2274 | - : podbird.theme.baseText |
2275 | + color: listItem.expanded || currentGuid === model.guid || downloader.downloadingGuid === model.guid ? podbird.theme.focusText |
2276 | + : podbird.theme.baseText |
2277 | } |
2278 | |
2279 | Label { |
2280 | id: episodePublishDate |
2281 | width: parent.width |
2282 | - text: Qt.formatDate(new Date(model.published), "MMM d, yyyy") |
2283 | + text: formatTime(model.duration) + " | " + Qt.formatDate(new Date(model.published), "MMM d, yyyy") |
2284 | fontSize: "x-small" |
2285 | - color: currentGuid === model.guid ? podbird.theme.focusText |
2286 | - : podbird.theme.baseText |
2287 | elide: Text.ElideRight |
2288 | - } |
2289 | + color: podbird.theme.baseSubText |
2290 | + } |
2291 | + } |
2292 | + |
2293 | + ActionButton { |
2294 | + id: contextualMenu |
2295 | + |
2296 | + width: units.gu(5) |
2297 | + height: units.gu(4) |
2298 | + |
2299 | + iconName: "contextual-menu" |
2300 | + color: progressBar.visible || listItem.expanded ? podbird.theme.focusText |
2301 | + : podbird.theme.baseIcon |
2302 | + onClicked: { |
2303 | + var popover = PopupUtils.open(popoverComponent, contextualMenu) |
2304 | + popover.queued = Qt.binding(function() { return model.queued }) |
2305 | + popover.listened = Qt.binding(function() { return model.listened }) |
2306 | + popover.guid = Qt.binding(function() { return model.guid }) |
2307 | + popover.audiourl = Qt.binding(function() { return model.audiourl }) |
2308 | + popover.downloadedfile = Qt.binding(function() { return episodeModel.get(index).downloadedfile }) |
2309 | + popover.index = Qt.binding(function() { return index }) |
2310 | + } |
2311 | + } |
2312 | + |
2313 | + ActionButton { |
2314 | + width: units.gu(4) |
2315 | + height: units.gu(4) |
2316 | + |
2317 | + iconName: player.playbackState === MediaPlayer.PlayingState && currentGuid === model.guid ? "media-playback-pause" |
2318 | + : "media-playback-start" |
2319 | + color: player.playbackState === MediaPlayer.PlayingState && currentGuid === model.guid ? podbird.theme.focusText |
2320 | + : podbird.theme.baseIcon |
2321 | + |
2322 | + onClicked: { |
2323 | + var db = Podcasts.init(); |
2324 | + db.transaction(function (tx) { |
2325 | + if (currentGuid === model.guid) { |
2326 | + if (player.playbackState === MediaPlayer.PlayingState) { |
2327 | + player.pause() |
2328 | + } else { |
2329 | + player.play() |
2330 | + } |
2331 | + } else { |
2332 | + currentGuid = ""; |
2333 | + player.source = model.downloadedfile ? model.downloadedfile : model.audiourl; |
2334 | + var rs = tx.executeSql("SELECT position FROM Episode WHERE guid=?", [model.guid]); |
2335 | + player.play(); |
2336 | + player.seek(rs.rows.item(0).position); |
2337 | + currentName = model.name; |
2338 | + currentArtist = model.artist; |
2339 | + currentImage = model.image; |
2340 | + currentGuid = model.guid; |
2341 | + } |
2342 | + }); |
2343 | + } |
2344 | + } |
2345 | + } |
2346 | + |
2347 | + Rectangle { |
2348 | + id: progressBar |
2349 | + radius: width/3 |
2350 | + width: parent.width |
2351 | + height: units.dp(5) |
2352 | + color: Theme.palette.normal.base |
2353 | + visible: downloader.downloadingGuid === model.guid |
2354 | + Rectangle { |
2355 | + height: parent.height |
2356 | + radius: parent.radius |
2357 | + anchors.left: parent.left |
2358 | + anchors.top: parent.top |
2359 | + color: podbird.theme.focusText |
2360 | + width: downloader.progress > 0 ? Math.min((downloader.progress / 100) * parent.width, parent.width) : 0 |
2361 | } |
2362 | } |
2363 | |
2364 | @@ -288,184 +610,15 @@ |
2365 | text: model.description |
2366 | textFormat: Text.RichText |
2367 | clip: true |
2368 | - height: listItem.expanded ? contentHeight : units.gu(4) |
2369 | + height: listItem.expanded ? contentHeight : 0 |
2370 | wrapMode: Text.WordWrap |
2371 | width: parent.width |
2372 | - elide: Text.ElideRight |
2373 | fontSize: "small" |
2374 | color: podbird.theme.baseSubText |
2375 | Behavior on height { |
2376 | UbuntuNumberAnimation { |
2377 | - duration: UbuntuAnimation.SlowDuration |
2378 | - } |
2379 | - } |
2380 | - |
2381 | - } |
2382 | - |
2383 | - Item { |
2384 | - id: statusBox |
2385 | - |
2386 | - width: parent.width |
2387 | - height: units.gu(6) |
2388 | - |
2389 | - function formatTime(seconds) { |
2390 | - var time = Podcasts.getTimeDiff(seconds) |
2391 | - var hour = time[0] |
2392 | - var minute = time[1] |
2393 | - // TRANSLATORS: the first argument is the number of hours, |
2394 | - // followed by minute (eg. 20h 3m) |
2395 | - if(hour > 0 && minute > 0) { |
2396 | - // xgettext: no-c-format |
2397 | - return (i18n.tr("%1h %2m")) |
2398 | - .arg(hour) |
2399 | - .arg(minute) |
2400 | - } |
2401 | - |
2402 | - // TRANSLATORS: this string indicates the number of hours |
2403 | - // eg. 20h (no plural state required) |
2404 | - else if(hour > 0 && minute === 0) { |
2405 | - // xgettext: no-c-format |
2406 | - return (i18n.tr("%1h")) |
2407 | - .arg(hour) |
2408 | - } |
2409 | - |
2410 | - // TRANSLATORS: this string indicates the number of minutes |
2411 | - // eg. 15m (no plural state required) |
2412 | - else if(hour === 0 && minute > 0) { |
2413 | - // xgettext: no-c-format |
2414 | - return (i18n.tr("%1m")) |
2415 | - .arg(minute) |
2416 | - } |
2417 | - |
2418 | - else { |
2419 | - return Podcasts.formatTime(model.duration) |
2420 | - } |
2421 | - } |
2422 | - |
2423 | - Rectangle { |
2424 | - id: listened |
2425 | - border.color: UbuntuColors.lightGrey |
2426 | - height: units.gu(2.5) |
2427 | - width: height |
2428 | - radius: width / 2 |
2429 | - anchors.right: durationIcon.left |
2430 | - anchors.rightMargin: units.gu(2) |
2431 | - anchors.verticalCenter: actionRow.verticalCenter |
2432 | - visible: model.listened |
2433 | - Icon { |
2434 | - id: tick |
2435 | - name: "tick" |
2436 | - anchors.centerIn: parent |
2437 | - anchors.verticalCenterOffset: units.gu(0.1) |
2438 | - height: units.gu(1.4) |
2439 | - width: height |
2440 | - } |
2441 | - } |
2442 | - |
2443 | - Icon { |
2444 | - id: durationIcon |
2445 | - width: units.gu(2.5) |
2446 | - height: width |
2447 | - name: "alarm-clock" |
2448 | - visible: duration.text !== "" |
2449 | - anchors.right: duration.left |
2450 | - anchors.rightMargin: units.gu(0.5) |
2451 | - anchors.verticalCenter: actionRow.verticalCenter |
2452 | - color: podbird.theme.baseIcon |
2453 | - } |
2454 | - |
2455 | - Label { |
2456 | - id: duration |
2457 | - color: podbird.theme.baseText |
2458 | - anchors.right: parent.right |
2459 | - anchors.verticalCenter: durationIcon.verticalCenter |
2460 | - fontSize: "small" |
2461 | - text: !isNaN(model.duration) && model.duration !== 0 ? statusBox.formatTime(model.duration) : "" |
2462 | - } |
2463 | - |
2464 | - Row { |
2465 | - id: actionRow |
2466 | - |
2467 | - anchors.left: parent.left |
2468 | - anchors.leftMargin: units.gu(-1.5) |
2469 | - |
2470 | - ActionButton { |
2471 | - width: units.gu(5) |
2472 | - height: units.gu(4) |
2473 | - |
2474 | - iconName: player.playbackState === MediaPlayer.PlayingState && currentGuid === model.guid ? "media-playback-pause" |
2475 | - : "media-playback-start" |
2476 | - |
2477 | - onClicked: { |
2478 | - var db = Podcasts.init(); |
2479 | - db.transaction(function (tx) { |
2480 | - if (currentGuid === model.guid) { |
2481 | - if (player.playbackState === MediaPlayer.PlayingState) { |
2482 | - player.pause() |
2483 | - } else { |
2484 | - player.play() |
2485 | - } |
2486 | - } else { |
2487 | - currentGuid = ""; |
2488 | - player.source = model.downloadedfile ? model.downloadedfile : model.audiourl; |
2489 | - var rs = tx.executeSql("SELECT position FROM Episode WHERE guid=?", [model.guid]); |
2490 | - player.play(); |
2491 | - player.seek(rs.rows.item(0).position); |
2492 | - currentName = model.name; |
2493 | - currentArtist = model.artist; |
2494 | - currentImage = model.image; |
2495 | - currentGuid = model.guid; |
2496 | - } |
2497 | - }); |
2498 | - } |
2499 | - } |
2500 | - |
2501 | - ActionButton { |
2502 | - id: downloadButton |
2503 | - |
2504 | - width: units.gu(5) |
2505 | - height: units.gu(4) |
2506 | - |
2507 | - property bool queued: false |
2508 | - |
2509 | - iconName: model.downloadedfile ? "delete" : (queued && downloader.downloadingGuid !== model.guid ? "history" : "save") |
2510 | - opacity: downloader.downloadingGuid === model.guid ? 0.4 : 1.0 |
2511 | - enabled: downloader.downloadingGuid !== model.guid |
2512 | - |
2513 | - ActivityIndicator { |
2514 | - anchors.centerIn: parent |
2515 | - visible: downloader.downloadingGuid === model.guid |
2516 | - running: visible |
2517 | - } |
2518 | - |
2519 | - onClicked: { |
2520 | - if (model.downloadedfile) { |
2521 | - fileManager.deleteFile(model.downloadedfile); |
2522 | - var db = Podcasts.init(); |
2523 | - db.transaction(function (tx) { |
2524 | - tx.executeSql("UPDATE Episode SET downloadedfile = NULL WHERE guid = ?", [model.guid]); |
2525 | - }); |
2526 | - loadEpisodes(episodeModel.pid, episodeModel.artist, episodeModel.image); |
2527 | - } else { |
2528 | - downloadButton.queued = true; |
2529 | - downloader.addDownload(model.guid, model.audiourl); |
2530 | - } |
2531 | - } |
2532 | - } |
2533 | - } |
2534 | - |
2535 | - |
2536 | - ProgressBar { |
2537 | - visible: downloader.downloadingGuid === model.guid |
2538 | - minimumValue: 0 |
2539 | - maximumValue: 100 |
2540 | - anchors.left: actionRow.right |
2541 | - anchors.right: model.listened ? listened.left : durationIcon.left |
2542 | - anchors.leftMargin: units.gu(2) |
2543 | - anchors.rightMargin: units.gu(2) |
2544 | - anchors.verticalCenter: actionRow.verticalCenter |
2545 | - height: units.gu(2.6) |
2546 | - value: downloader.progress |
2547 | + duration: UbuntuAnimation.BriskDuration |
2548 | + } |
2549 | } |
2550 | } |
2551 | } |
2552 | @@ -483,21 +636,28 @@ |
2553 | |
2554 | function refreshModel() { |
2555 | var db = Podcasts.init(); |
2556 | - loadEpisodes(episodeModel.pid, episodeModel.artist, episodeModel.image); |
2557 | + loadEpisodes(episodeId, episodeArtist, episodeImage); |
2558 | episodesUpdating = false; |
2559 | } |
2560 | |
2561 | function loadEpisodes(pid, artist, img) { |
2562 | + var i, episode; |
2563 | + var newCount = 0; |
2564 | + |
2565 | + episodeModel.clear(); |
2566 | + |
2567 | var db = Podcasts.init(); |
2568 | db.transaction(function (tx) { |
2569 | - episodeModel.clear(); |
2570 | var rs = tx.executeSql("SELECT rowid, * FROM Episode WHERE podcast=? ORDER BY published DESC", [pid]); |
2571 | - for(var i = 0; i < rs.rows.length; i++) { |
2572 | - var episode = rs.rows.item(i); |
2573 | - episodeModel.pid = pid; |
2574 | - episodeModel.artist = artist; |
2575 | - episodeModel.image = img; |
2576 | - episodeModel.append({"guid" : episode.guid, "listened" : episode.listened, "published": episode.published, "name" : episode.name, "description" : episode.description, "duration" : episode.duration, "position" : episode.position, "downloadedfile" : episode.downloadedfile, "image" : img, "artist" : artist, "audiourl" : episode.audiourl}); |
2577 | + for(i = 0; i < rs.rows.length; i++) { |
2578 | + episode = rs.rows.item(i); |
2579 | + //console.log(episode.queued) |
2580 | + if (!episode.listened) { |
2581 | + episodeModel.insert(newCount, {"guid" : episode.guid, "listened" : episode.listened, "published": episode.published, "name" : episode.name, "description" : episode.description, "duration" : episode.duration, "position" : episode.position, "downloadedfile" : episode.downloadedfile, "image" : img, "artist" : artist, "audiourl" : episode.audiourl, "queued": episode.queued}); |
2582 | + newCount++; |
2583 | + } else if (!podbird.settings.hideListened) { |
2584 | + episodeModel.insert(i,{"guid" : episode.guid, "listened" : episode.listened, "published": episode.published, "name" : episode.name, "description" : episode.description, "duration" : episode.duration, "position" : episode.position, "downloadedfile" : episode.downloadedfile, "image" : img, "artist" : artist, "audiourl" : episode.audiourl, "queued": episode.queued}); |
2585 | + } |
2586 | } |
2587 | }); |
2588 | } |
2589 | @@ -558,12 +718,13 @@ |
2590 | db.transaction(function(tx2) { |
2591 | var ers = tx2.executeSql("SELECT rowid FROM Episode WHERE guid=?", [track.guid]); |
2592 | if (ers.rows.length === 0) { |
2593 | - tx2.executeSql("INSERT INTO Episode(podcast, name, description, audiourl, guid, listened, duration, published) VALUES(?, ?, ? , ?, ?, ?, ?, ?)", [pid, |
2594 | + tx2.executeSql("INSERT INTO Episode(podcast, name, description, audiourl, guid, listened, queued, duration, published) VALUES(?, ?, ? , ?, ?, ?, ?, ?)", [pid, |
2595 | track.name, |
2596 | track.description, |
2597 | track.audiourl, |
2598 | track.guid, |
2599 | false, |
2600 | + false, |
2601 | track.duration, |
2602 | track.published]); |
2603 | } |
2604 | |
2605 | === modified file 'app/ui/ExpandableListItem.qml' |
2606 | --- app/ui/ExpandableListItem.qml 2015-03-27 15:04:39 +0000 |
2607 | +++ app/ui/ExpandableListItem.qml 2015-04-11 21:39:04 +0000 |
2608 | @@ -61,6 +61,7 @@ |
2609 | width: units.gu(2) |
2610 | height: width |
2611 | anchors.right: parent.right |
2612 | + anchors.rightMargin: units.gu(1) |
2613 | anchors.verticalCenter: parent.verticalCenter |
2614 | |
2615 | name: "go-down" |
2616 | |
2617 | === modified file 'app/ui/NowPlayingPage.qml' |
2618 | --- app/ui/NowPlayingPage.qml 2015-03-08 11:10:07 +0000 |
2619 | +++ app/ui/NowPlayingPage.qml 2015-04-11 21:39:04 +0000 |
2620 | @@ -101,6 +101,11 @@ |
2621 | function formatValue(v) { return Podcasts.formatTime(v/1000); } |
2622 | } |
2623 | |
2624 | + Connections { |
2625 | + target: player |
2626 | + onPositionChanged: scrubber.value = player.position |
2627 | + } |
2628 | + |
2629 | Label { |
2630 | id: startTime |
2631 | fontSize: "small" |
2632 | |
2633 | === modified file 'app/ui/PlayerControls.qml' |
2634 | --- app/ui/PlayerControls.qml 2015-03-08 11:10:07 +0000 |
2635 | +++ app/ui/PlayerControls.qml 2015-04-11 21:39:04 +0000 |
2636 | @@ -53,7 +53,7 @@ |
2637 | id: progressBarHint |
2638 | anchors.left: parent.left |
2639 | anchors.top: cover.bottom |
2640 | - color: UbuntuColors.orange |
2641 | + color: podbird.theme.focusText |
2642 | height: units.gu(0.25) |
2643 | width: player.duration > 0 ? (player.position / player.duration) * parent.width : 0 |
2644 | } |
2645 | @@ -72,7 +72,7 @@ |
2646 | color: "white" |
2647 | elide: Text.ElideRight |
2648 | maximumLineCount: 2 |
2649 | - wrapMode: Text.WrapAnywhere |
2650 | + wrapMode: Text.WordWrap |
2651 | text: currentName |
2652 | } |
2653 | |
2654 | |
2655 | === modified file 'app/ui/PodcastsTab.qml' |
2656 | --- app/ui/PodcastsTab.qml 2015-03-29 15:33:26 +0000 |
2657 | +++ app/ui/PodcastsTab.qml 2015-04-11 21:39:04 +0000 |
2658 | @@ -36,6 +36,8 @@ |
2659 | page: Page { |
2660 | id: podcastPage |
2661 | |
2662 | + flickable: viewLoader.item |
2663 | + |
2664 | /* |
2665 | #FIXME: The following lines of code is necessary due to a upstream bug |
2666 | in the SDK http://pad.lv/1400297. This bug is still present in the rtm. |
2667 | @@ -74,6 +76,14 @@ |
2668 | podcastPage.state = "search" |
2669 | searchField.forceActiveFocus() |
2670 | } |
2671 | + }, |
2672 | + |
2673 | + Action { |
2674 | + iconName: podbird.settings.showListView ? "view-grid-symbolic" : "view-list-symbolic" |
2675 | + text: podbird.settings.showListView ? i18n.tr("Grid View") : i18n.tr("List View") |
2676 | + onTriggered: { |
2677 | + podbird.settings.showListView = !podbird.settings.showListView |
2678 | + } |
2679 | } |
2680 | ] |
2681 | }, |
2682 | @@ -85,7 +95,7 @@ |
2683 | iconName: "back" |
2684 | text: i18n.tr("Back") |
2685 | onTriggered: { |
2686 | - view.forceActiveFocus() |
2687 | + viewLoader.item.forceActiveFocus() |
2688 | searchField.text = "" |
2689 | podcastPage.state = "default" |
2690 | } |
2691 | @@ -108,7 +118,7 @@ |
2692 | iconName: "back" |
2693 | text: i18n.tr("Back") |
2694 | onTriggered: { |
2695 | - view.forceActiveFocus() |
2696 | + viewLoader.item.forceActiveFocus() |
2697 | feedUrlField.text = "" |
2698 | podcastPage.state = "default" |
2699 | } |
2700 | @@ -119,7 +129,7 @@ |
2701 | iconName: "ok" |
2702 | text: i18n.tr("Save Podcast") |
2703 | onTriggered: { |
2704 | - view.forceActiveFocus() |
2705 | + viewLoader.item.forceActiveFocus() |
2706 | subscribeFromFeed(feedUrlField.text); |
2707 | feedUrlField.text = "" |
2708 | podcastPage.state = "default" |
2709 | @@ -134,7 +144,7 @@ |
2710 | anchors.left: parent ? parent.left : undefined |
2711 | anchors.right: parent ? parent.right : undefined |
2712 | onAccepted: { |
2713 | - view.forceActiveFocus() |
2714 | + viewLoader.item.forceActiveFocus() |
2715 | subscribeFromFeed(feedUrlField.text); |
2716 | feedUrlField.text = "" |
2717 | podcastPage.state = "default" |
2718 | @@ -167,8 +177,10 @@ |
2719 | EmptyState { |
2720 | anchors.centerIn: parent |
2721 | anchors.verticalCenterOffset: Qt.inputMethod.visible ? units.gu(4) : 0 |
2722 | + iconHeight: units.gu(12) |
2723 | + iconWidth: iconHeight + units.gu(10) |
2724 | + iconSource: Qt.resolvedUrl("../graphics/notFound.svg") |
2725 | visible: podcastModel.count === 0 || sortedPodcastModel.count === 0 |
2726 | - iconName: "music-app-symbolic" |
2727 | title: podcastModel.count === 0 ? i18n.tr("No Podcast Subscriptions") |
2728 | : i18n.tr("No Podcasts Found") |
2729 | subTitle: podcastModel.count === 0 ? i18n.tr("You haven't subscribed to any podcasts yet, visit the 'Find New Podcasts' page to add some.") |
2730 | @@ -186,122 +198,158 @@ |
2731 | filter.pattern: RegExp(searchField.text, "gi") |
2732 | } |
2733 | |
2734 | - ListModel { |
2735 | - id: episodeModel |
2736 | - property string pid; |
2737 | - property string artist; |
2738 | - property string image; |
2739 | - } |
2740 | - |
2741 | - ListView { |
2742 | - id: view |
2743 | - |
2744 | - clip: true |
2745 | - model: sortedPodcastModel |
2746 | + Loader { |
2747 | + id: viewLoader |
2748 | anchors.fill: parent |
2749 | - |
2750 | - footer: Item { |
2751 | - width: parent.width |
2752 | - height: units.gu(8) |
2753 | - } |
2754 | - |
2755 | - delegate: ListItem.Empty { |
2756 | - id: listItem |
2757 | - |
2758 | - property bool expanded: false |
2759 | - |
2760 | - height: units.gu(8) |
2761 | - removable: true |
2762 | - confirmRemoval: true |
2763 | - highlightWhenPressed: false |
2764 | - |
2765 | - onItemRemoved: { |
2766 | - var db = Podcasts.init(); |
2767 | - db.transaction(function (tx) { |
2768 | - var rs = tx.executeSql("SELECT downloadedfile FROM Episode WHERE downloadedfile NOT NULL AND podcast=?", [model.id]); |
2769 | - for(var i = 0; i < rs.rows.length; i++) { |
2770 | - fileManager.deleteFile(rs.rows.item(i).downloadedfile); |
2771 | - } |
2772 | - tx.executeSql("DELETE FROM Episode WHERE podcast=?", [model.id]); |
2773 | - tx.executeSql("DELETE FROM Podcast WHERE rowid=?", [model.id]); |
2774 | - refreshModel() |
2775 | - }); |
2776 | - } |
2777 | - |
2778 | - Rectangle { |
2779 | - anchors.fill: parent |
2780 | - color: listItem.pressed ? podbird.theme.hightlightListView : "transparent" |
2781 | - } |
2782 | - |
2783 | - onClicked: { |
2784 | - if(podcastPage.state === "search") { |
2785 | - view.forceActiveFocus() |
2786 | - searchField.text = "" |
2787 | - podcastPage.state = "default" |
2788 | - } |
2789 | - mainStack.push(Qt.resolvedUrl("EpisodesPage.qml"), {"episodeName": model.name, "episodeId": model.id, "episodeArtist": model.artist, "episodeImage": model.image}) |
2790 | - } |
2791 | - |
2792 | - Column { |
2793 | - id: mainColumn |
2794 | - |
2795 | - anchors.left: parent.left |
2796 | - anchors.right: parent.right |
2797 | - anchors.margins: units.gu(2) |
2798 | - anchors.verticalCenter: parent.verticalCenter |
2799 | - spacing: units.gu(1) |
2800 | - |
2801 | - RowLayout { |
2802 | - id: titleRow |
2803 | - |
2804 | - width: parent.width |
2805 | - spacing: units.gu(2) |
2806 | - |
2807 | - Image { |
2808 | - id: imgFrame |
2809 | - width: units.gu(6) |
2810 | - height: width |
2811 | - sourceSize.height: width |
2812 | - sourceSize.width: width |
2813 | - source: model.image |
2814 | - } |
2815 | - |
2816 | - Column { |
2817 | - id: detailColumn |
2818 | - |
2819 | - anchors.verticalCenter: imgFrame.verticalCenter |
2820 | - Layout.fillWidth: true |
2821 | - |
2822 | - Label { |
2823 | - id: podcastTitle |
2824 | - textFormat: Text.PlainText |
2825 | - text: model.name.trim() |
2826 | - width: parent.width |
2827 | - fontSize: "small" |
2828 | - elide: Text.ElideRight |
2829 | - color: podbird.theme.baseText |
2830 | - } |
2831 | - |
2832 | - Label { |
2833 | - id: episodeCount |
2834 | - width: parent.width |
2835 | - fontSize: "x-small" |
2836 | - color: podbird.theme.baseSubText |
2837 | - visible: model.episodeCount > 0 |
2838 | - text: i18n.tr("%1 unheard episode", "%1 unheard episodes", model.episodeCount).arg(model.episodeCount) |
2839 | - } |
2840 | - } |
2841 | - } |
2842 | - } |
2843 | - } |
2844 | - |
2845 | - PullToRefresh { |
2846 | - refreshing: episodesUpdating |
2847 | - onRefresh: updateEpisodes(); |
2848 | - } |
2849 | - } |
2850 | - Scrollbar { |
2851 | - flickableItem: view |
2852 | + sourceComponent: podbird.settings.showListView ? listviewComponent : cardviewComponent |
2853 | + } |
2854 | + |
2855 | + Component { |
2856 | + id: cardviewComponent |
2857 | + |
2858 | + CardView { |
2859 | + id: cardView |
2860 | + model: sortedPodcastModel |
2861 | + delegate: Card { |
2862 | + id: albumCard |
2863 | + coverArt: model.image |
2864 | + primaryText: model.name.trim() |
2865 | + secondaryText: i18n.tr("%1 unheard episode", "%1 unheard episodes", model.episodeCount).arg(model.episodeCount) |
2866 | + onClicked: { |
2867 | + if(podcastPage.state === "search") { |
2868 | + cardView.forceActiveFocus() |
2869 | + searchField.text = "" |
2870 | + podcastPage.state = "default" |
2871 | + } |
2872 | + mainStack.push(Qt.resolvedUrl("EpisodesPage.qml"), {"episodeName": model.name, "episodeId": model.id, "episodeArtist": model.artist, "episodeImage": model.image}) |
2873 | + } |
2874 | + } |
2875 | + } |
2876 | + } |
2877 | + |
2878 | + Component { |
2879 | + id: listviewComponent |
2880 | + |
2881 | + ListView { |
2882 | + id: listView |
2883 | + |
2884 | + Component.onCompleted: { |
2885 | + // FIXME: workaround for qtubuntu not returning values depending on the grid unit definition |
2886 | + // for Flickable.maximumFlickVelocity and Flickable.flickDeceleration |
2887 | + var scaleFactor = units.gridUnit / 8; |
2888 | + maximumFlickVelocity = maximumFlickVelocity * scaleFactor; |
2889 | + flickDeceleration = flickDeceleration * scaleFactor; |
2890 | + } |
2891 | + |
2892 | + model: sortedPodcastModel |
2893 | + anchors.fill: parent |
2894 | + |
2895 | + footer: Item { |
2896 | + width: parent.width |
2897 | + height: units.gu(8) |
2898 | + } |
2899 | + |
2900 | + delegate: ListItem.Empty { |
2901 | + id: listItem |
2902 | + |
2903 | + property bool expanded: false |
2904 | + |
2905 | + height: units.gu(8) |
2906 | + removable: true |
2907 | + confirmRemoval: true |
2908 | + showDivider: false |
2909 | + highlightWhenPressed: false |
2910 | + |
2911 | + onItemRemoved: { |
2912 | + var db = Podcasts.init(); |
2913 | + db.transaction(function (tx) { |
2914 | + var rs = tx.executeSql("SELECT downloadedfile FROM Episode WHERE downloadedfile NOT NULL AND podcast=?", [model.id]); |
2915 | + for(var i = 0; i < rs.rows.length; i++) { |
2916 | + fileManager.deleteFile(rs.rows.item(i).downloadedfile); |
2917 | + } |
2918 | + tx.executeSql("DELETE FROM Episode WHERE podcast=?", [model.id]); |
2919 | + tx.executeSql("DELETE FROM Podcast WHERE rowid=?", [model.id]); |
2920 | + podcastModel.remove(index, 1) |
2921 | + }); |
2922 | + } |
2923 | + |
2924 | + Rectangle { |
2925 | + anchors.fill: parent |
2926 | + opacity: 0.3 |
2927 | + color: index % 2 === 0 ? podbird.theme.hightlightListView : "Transparent" |
2928 | + } |
2929 | + |
2930 | + onClicked: { |
2931 | + if(podcastPage.state === "search") { |
2932 | + listView.forceActiveFocus() |
2933 | + searchField.text = "" |
2934 | + podcastPage.state = "default" |
2935 | + } |
2936 | + mainStack.push(Qt.resolvedUrl("EpisodesPage.qml"), {"episodeName": model.name, "episodeId": model.id, "episodeArtist": model.artist, "episodeImage": model.image}) |
2937 | + } |
2938 | + |
2939 | + Column { |
2940 | + id: mainColumn |
2941 | + |
2942 | + anchors.left: parent.left |
2943 | + anchors.right: parent.right |
2944 | + anchors.margins: units.gu(2) |
2945 | + anchors.verticalCenter: parent.verticalCenter |
2946 | + spacing: units.gu(1) |
2947 | + |
2948 | + RowLayout { |
2949 | + id: titleRow |
2950 | + |
2951 | + width: parent.width |
2952 | + spacing: units.gu(2) |
2953 | + |
2954 | + Image { |
2955 | + id: imgFrame |
2956 | + width: units.gu(6) |
2957 | + height: width |
2958 | + sourceSize.height: width |
2959 | + sourceSize.width: width |
2960 | + source: model.image |
2961 | + } |
2962 | + |
2963 | + Column { |
2964 | + id: detailColumn |
2965 | + |
2966 | + anchors.verticalCenter: imgFrame.verticalCenter |
2967 | + Layout.fillWidth: true |
2968 | + |
2969 | + Label { |
2970 | + id: podcastTitle |
2971 | + textFormat: Text.PlainText |
2972 | + text: model.name.trim() |
2973 | + width: parent.width |
2974 | + fontSize: "small" |
2975 | + elide: Text.ElideRight |
2976 | + color: podbird.theme.baseText |
2977 | + } |
2978 | + |
2979 | + Label { |
2980 | + id: episodeCount |
2981 | + width: parent.width |
2982 | + fontSize: "x-small" |
2983 | + color: podbird.theme.baseSubText |
2984 | + visible: model.episodeCount > 0 |
2985 | + text: i18n.tr("%1 unheard episode", "%1 unheard episodes", model.episodeCount).arg(model.episodeCount) |
2986 | + } |
2987 | + } |
2988 | + } |
2989 | + } |
2990 | + } |
2991 | + |
2992 | + Scrollbar { |
2993 | + flickableItem: listView |
2994 | + } |
2995 | + |
2996 | + PullToRefresh { |
2997 | + refreshing: episodesUpdating |
2998 | + onRefresh: updateEpisodes(); |
2999 | + } |
3000 | + } |
3001 | } |
3002 | } |
3003 | |
3004 | |
3005 | === renamed file 'app/ui/SearchTab.qml' => 'app/ui/SearchPage.qml' |
3006 | --- app/ui/SearchTab.qml 2015-03-29 15:33:26 +0000 |
3007 | +++ app/ui/SearchPage.qml 2015-04-11 21:39:04 +0000 |
3008 | @@ -23,24 +23,64 @@ |
3009 | import Ubuntu.Components.ListItems 1.0 as ListItem |
3010 | import "../podcasts.js" as Podcasts |
3011 | |
3012 | -Tab { |
3013 | - title: i18n.tr("Find New Podcasts") |
3014 | +Page { |
3015 | + id: searchPage |
3016 | |
3017 | property var xhr: new XMLHttpRequest; |
3018 | |
3019 | - page: Page { |
3020 | - Column { |
3021 | - spacing: units.gu(2) |
3022 | - anchors.fill: parent |
3023 | - anchors.topMargin: units.gu(2) |
3024 | - |
3025 | - TextField { |
3026 | + /* |
3027 | + #FIXME: The following lines of code is necessary due to a upstream bug |
3028 | + in the SDK http://pad.lv/1400297. This bug is still present in the rtm. |
3029 | + Once it is fixed, this following property and connection can be remvoed. |
3030 | + */ |
3031 | + property Item __oldContents: null |
3032 | + Connections { |
3033 | + target: searchPage.head |
3034 | + onContentsChanged: { |
3035 | + if (searchPage.__oldContents) { |
3036 | + searchPage.__oldContents.parent = null; |
3037 | + } |
3038 | + searchPage.__oldContents = searchPage.head.contents; |
3039 | + } |
3040 | + } |
3041 | + |
3042 | + state: "default" |
3043 | + states: [ |
3044 | + PageHeadState { |
3045 | + name: "default" |
3046 | + head: searchPage.head |
3047 | + actions: [ |
3048 | + Action { |
3049 | + iconName: "search" |
3050 | + text: i18n.tr("Search Episode") |
3051 | + onTriggered: { |
3052 | + searchPage.state = "search" |
3053 | + searchField.forceActiveFocus() |
3054 | + } |
3055 | + } |
3056 | + ] |
3057 | + }, |
3058 | + |
3059 | + PageHeadState { |
3060 | + name: "search" |
3061 | + head: searchPage.head |
3062 | + backAction: Action { |
3063 | + iconName: "back" |
3064 | + text: i18n.tr("Back") |
3065 | + onTriggered: { |
3066 | + resultsView.forceActiveFocus() |
3067 | + searchField.text = "" |
3068 | + searchPage.state = "default" |
3069 | + } |
3070 | + } |
3071 | + |
3072 | + contents: TextField { |
3073 | id: searchField |
3074 | - anchors.left: parent.left |
3075 | - anchors.right: parent.right |
3076 | - anchors.margins: units.gu(2) |
3077 | + inputMethodHints: Qt.ImhNoPredictiveText |
3078 | placeholderText: i18n.tr("Search...") |
3079 | - inputMethodHints: Qt.ImhNoPredictiveText; |
3080 | + anchors.left: parent ? parent.left : undefined |
3081 | + anchors.right: parent ? parent.right : undefined |
3082 | + anchors.rightMargin: units.gu(2) |
3083 | onTextChanged: { |
3084 | if (text.length > 2) { |
3085 | search(text) |
3086 | @@ -49,94 +89,113 @@ |
3087 | } |
3088 | } |
3089 | } |
3090 | - |
3091 | - ListView { |
3092 | - id: resultsView |
3093 | - clip: true |
3094 | - width: parent.width |
3095 | - model: searchResults |
3096 | - height: parent.height - searchField.height - units.gu(2) |
3097 | - |
3098 | - footer: Item { |
3099 | - width: parent.width |
3100 | - height: units.gu(7) |
3101 | - } |
3102 | - |
3103 | - delegate: ListItem.Empty { |
3104 | - id: listItem |
3105 | - |
3106 | - height: units.gu(8) |
3107 | - highlightWhenPressed: false |
3108 | - |
3109 | - Rectangle { |
3110 | - anchors.fill: parent |
3111 | - color: listItem.pressed ? podbird.theme.hightlightListView : "transparent" |
3112 | - } |
3113 | - |
3114 | - RowLayout { |
3115 | - id: titleRow |
3116 | - |
3117 | - anchors.left: parent.left |
3118 | - anchors.right: parent.right |
3119 | - anchors.margins: units.gu(2) |
3120 | - anchors.verticalCenter: parent.verticalCenter |
3121 | - |
3122 | - spacing: units.gu(2) |
3123 | - |
3124 | - Image { |
3125 | - id: imgFrame |
3126 | - width: units.gu(6) |
3127 | - height: width |
3128 | - sourceSize.height: width |
3129 | - sourceSize.width: width |
3130 | - source: model.image |
3131 | - } |
3132 | - |
3133 | - Column { |
3134 | - id: detailColumn |
3135 | - |
3136 | - anchors.verticalCenter: imgFrame.verticalCenter |
3137 | - Layout.fillWidth: true |
3138 | - |
3139 | - Label { |
3140 | - id: podcastTitle |
3141 | - textFormat: Text.PlainText |
3142 | - text: model.name |
3143 | - width: parent.width |
3144 | - fontSize: "small" |
3145 | - elide: Text.ElideRight |
3146 | - } |
3147 | - |
3148 | - Label { |
3149 | - id: episodeCount |
3150 | - width: parent.width |
3151 | - color: "#999999" |
3152 | - text: model.artist |
3153 | - fontSize: "x-small" |
3154 | - elide: Text.ElideRight |
3155 | - } |
3156 | - } |
3157 | - |
3158 | - Button { |
3159 | - anchors.right: parent.right |
3160 | - text: i18n.tr("Subscribe") |
3161 | - color: UbuntuColors.green |
3162 | - onClicked: { |
3163 | - Podcasts.subscribe(model.artist, model.name, model.feed, model.image); |
3164 | - imageDownloader.feed = model.feed; |
3165 | - imageDownloader.download(model.image); |
3166 | - tabs.selectedTabIndex = 0; |
3167 | - searchField.text = "" |
3168 | - } |
3169 | - } |
3170 | - } |
3171 | - } |
3172 | - |
3173 | - Scrollbar { |
3174 | - flickableItem: resultsView |
3175 | - } |
3176 | - |
3177 | - } |
3178 | + } |
3179 | + ] |
3180 | + |
3181 | + EmptyState { |
3182 | + anchors.centerIn: parent |
3183 | + anchors.verticalCenterOffset: Qt.inputMethod.visible ? units.gu(4) : 0 |
3184 | + iconHeight: units.gu(12) |
3185 | + iconWidth: iconHeight + units.gu(10) |
3186 | + visible: searchPage.state !== "search" ? true : searchResults.count === 0 && searchField.text.length > 2 |
3187 | + iconSource: searchPage.state !== "search" ? Qt.resolvedUrl("../graphics/owlSearch.svg") : Qt.resolvedUrl("../graphics/notFound.svg") |
3188 | + title: searchPage.state !== "search" ? i18n.tr("Looking for a new Podcast?") : i18n.tr("No Podcasts found") |
3189 | + subTitle: searchPage.state !== "search" ? i18n.tr("Click the 'magnifier' at the top to search.") : i18n.tr("No podcasts found matching the search term.") |
3190 | + } |
3191 | + |
3192 | + ListView { |
3193 | + id: resultsView |
3194 | + |
3195 | + Component.onCompleted: { |
3196 | + // FIXME: workaround for qtubuntu not returning values depending on the grid unit definition |
3197 | + // for Flickable.maximumFlickVelocity and Flickable.flickDeceleration |
3198 | + var scaleFactor = units.gridUnit / 8; |
3199 | + maximumFlickVelocity = maximumFlickVelocity * scaleFactor; |
3200 | + flickDeceleration = flickDeceleration * scaleFactor; |
3201 | + } |
3202 | + |
3203 | + model: searchResults |
3204 | + anchors.fill: parent |
3205 | + |
3206 | + footer: Item { |
3207 | + width: parent.width |
3208 | + height: units.gu(7) |
3209 | + } |
3210 | + |
3211 | + delegate: ListItem.Empty { |
3212 | + id: listItem |
3213 | + |
3214 | + height: units.gu(8) |
3215 | + showDivider: false |
3216 | + highlightWhenPressed: false |
3217 | + |
3218 | + Rectangle { |
3219 | + anchors.fill: parent |
3220 | + opacity: 0.3 |
3221 | + color: index % 2 === 0 ? podbird.theme.hightlightListView : "Transparent" |
3222 | + } |
3223 | + |
3224 | + RowLayout { |
3225 | + id: titleRow |
3226 | + |
3227 | + anchors.left: parent.left |
3228 | + anchors.right: parent.right |
3229 | + anchors.margins: units.gu(2) |
3230 | + anchors.verticalCenter: parent.verticalCenter |
3231 | + |
3232 | + spacing: units.gu(2) |
3233 | + |
3234 | + Image { |
3235 | + id: imgFrame |
3236 | + width: units.gu(6) |
3237 | + height: width |
3238 | + sourceSize.height: width |
3239 | + sourceSize.width: width |
3240 | + source: model.image |
3241 | + } |
3242 | + |
3243 | + Column { |
3244 | + id: detailColumn |
3245 | + |
3246 | + anchors.verticalCenter: imgFrame.verticalCenter |
3247 | + Layout.fillWidth: true |
3248 | + |
3249 | + Label { |
3250 | + id: podcastTitle |
3251 | + textFormat: Text.PlainText |
3252 | + text: model.name |
3253 | + width: parent.width |
3254 | + fontSize: "medium" |
3255 | + elide: Text.ElideRight |
3256 | + } |
3257 | + |
3258 | + Label { |
3259 | + id: episodeCount |
3260 | + width: parent.width |
3261 | + color: "#999999" |
3262 | + text: model.artist |
3263 | + fontSize: "x-small" |
3264 | + elide: Text.ElideRight |
3265 | + } |
3266 | + } |
3267 | + |
3268 | + Button { |
3269 | + anchors.right: parent.right |
3270 | + text: i18n.tr("Subscribe") |
3271 | + color: UbuntuColors.green |
3272 | + onClicked: { |
3273 | + Podcasts.subscribe(model.artist, model.name, model.feed, model.image); |
3274 | + imageDownloader.feed = model.feed; |
3275 | + imageDownloader.download(model.image); |
3276 | + tabs.selectedTabIndex = 0; |
3277 | + searchField.text = "" |
3278 | + } |
3279 | + } |
3280 | + } |
3281 | + } |
3282 | + |
3283 | + Scrollbar { |
3284 | + flickableItem: resultsView |
3285 | } |
3286 | } |
3287 | |
3288 | |
3289 | === renamed file 'app/ui/SettingsTab.qml' => 'app/ui/SettingsPage.qml' |
3290 | --- app/ui/SettingsTab.qml 2015-03-27 15:38:43 +0000 |
3291 | +++ app/ui/SettingsPage.qml 2015-04-11 21:39:04 +0000 |
3292 | @@ -20,98 +20,131 @@ |
3293 | import Ubuntu.Components 1.1 |
3294 | import Ubuntu.Components.ListItems 1.0 as ListItem |
3295 | |
3296 | -Tab { |
3297 | - id: tab |
3298 | - |
3299 | - title: i18n.tr("Settings") |
3300 | - |
3301 | - page: Page { |
3302 | - id: settingsPage |
3303 | - |
3304 | - ListModel { |
3305 | - id: themeModel |
3306 | - Component.onCompleted: initialize() |
3307 | - function initialize() { |
3308 | - themeModel.append({ name: i18n.tr("Light"), file: "Light.qml" }) |
3309 | - themeModel.append({ name: i18n.tr("Dark"), file: "Dark.qml" }) |
3310 | - } |
3311 | - } |
3312 | - |
3313 | - ListModel { |
3314 | - id: cleanupModel |
3315 | - Component.onCompleted: initialize() |
3316 | - function initialize() { |
3317 | - cleanupModel.append({ name: i18n.tr("Never"), value: -1 }) |
3318 | - cleanupModel.append({ name: i18n.tr("7 days"), value: 7 }) |
3319 | - cleanupModel.append({ name: i18n.tr("31 days"), value: 31 }) |
3320 | - cleanupModel.append({ name: i18n.tr("90 days"), value: 90 }) |
3321 | - cleanupModel.append({ name: i18n.tr("180 days"), value: 180 }) |
3322 | - cleanupModel.append({ name: i18n.tr("360 days"), value: 360 }) |
3323 | - } |
3324 | - } |
3325 | +Page { |
3326 | + id: settingsPage |
3327 | + |
3328 | + Flickable { |
3329 | + id: flickable |
3330 | + |
3331 | + anchors.fill: parent |
3332 | + contentHeight: settingsColumn.height + units.gu(8) |
3333 | + contentWidth: parent.width |
3334 | |
3335 | Column { |
3336 | id: settingsColumn |
3337 | |
3338 | - anchors.fill: parent |
3339 | - |
3340 | - ExpandableListItem { |
3341 | - id: themeSetting |
3342 | - |
3343 | - model: themeModel |
3344 | + anchors { |
3345 | + top: parent.top |
3346 | + left: parent.left |
3347 | + right: parent.right |
3348 | + } |
3349 | + |
3350 | + ListItem.Header { |
3351 | + text: i18n.tr("General Settings") |
3352 | + } |
3353 | + |
3354 | + ListItem.SingleValue { |
3355 | + progression: true |
3356 | + showDivider: false |
3357 | text: i18n.tr("Theme") |
3358 | - subText: podbird.settings.themeName.split(".qml")[0] |
3359 | - |
3360 | - delegate: ListItem.Standard { |
3361 | - text: model.name |
3362 | - |
3363 | - onClicked: { |
3364 | - var themeElement = model.file |
3365 | - podbird.settings.themeName = themeElement |
3366 | - podbird.themeManager.source = themeElement |
3367 | - themeSetting.expanded = false |
3368 | - } |
3369 | - |
3370 | - Icon { |
3371 | - width: units.gu(2) |
3372 | - height: width |
3373 | - name: "ok" |
3374 | - visible: podbird.settings.themeName === model.file |
3375 | - anchors.right: parent.right |
3376 | - anchors.rightMargin: units.gu(2) |
3377 | - anchors.verticalCenter: parent.verticalCenter |
3378 | - } |
3379 | - } |
3380 | - } |
3381 | - |
3382 | - ExpandableListItem { |
3383 | - id: cleanupSetting |
3384 | - |
3385 | - listViewHeight: units.gu(36) |
3386 | - model: cleanupModel |
3387 | - text: i18n.tr("Remove episodes older than") |
3388 | - subText: podbird.settings.retentionDays === -1 ? i18n.tr("Never") |
3389 | - : i18n.tr("%1 days").arg(podbird.settings.retentionDays) |
3390 | - |
3391 | - delegate: ListItem.Standard { |
3392 | - text: model.name |
3393 | - |
3394 | - onClicked: { |
3395 | - podbird.settings.retentionDays = model.value |
3396 | - cleanupSetting.expanded = false |
3397 | - } |
3398 | - |
3399 | - Icon { |
3400 | - width: units.gu(2) |
3401 | - height: width |
3402 | - name: "ok" |
3403 | - visible: podbird.settings.retentionDays === model.value |
3404 | - anchors.right: parent.right |
3405 | - anchors.rightMargin: units.gu(2) |
3406 | - anchors.verticalCenter: parent.verticalCenter |
3407 | - } |
3408 | - } |
3409 | + value: podbird.settings.themeName.split(".qml")[0] |
3410 | + onClicked: mainStack.push(Qt.resolvedUrl("../settings/ThemeSetting.qml")) |
3411 | + } |
3412 | + |
3413 | + ListItem.Header { |
3414 | + text: i18n.tr("Podcast Episode Settings") |
3415 | + } |
3416 | + |
3417 | + ListItem.Standard { |
3418 | + showDivider: false |
3419 | + text: i18n.tr("Hide listened episodes") |
3420 | + control: Switch { |
3421 | + checked: podbird.settings.hideListened |
3422 | + onClicked: podbird.settings.hideListened = checked |
3423 | + } |
3424 | + } |
3425 | + |
3426 | + ListItem.Base { |
3427 | + height: units.gu(10) |
3428 | + progression: true |
3429 | + showDivider: false |
3430 | + onClicked: mainStack.push(Qt.resolvedUrl("../settings/CleanSetting.qml")) |
3431 | + Column { |
3432 | + anchors.verticalCenter: parent.verticalCenter |
3433 | + anchors.right: parent.right |
3434 | + anchors.left: parent.left |
3435 | + Label { |
3436 | + width: parent.width |
3437 | + wrapMode: Text.WordWrap |
3438 | + text: i18n.tr("Automatically delete old episodes") |
3439 | + } |
3440 | + |
3441 | + Label { |
3442 | + fontSize: "small" |
3443 | + color: podbird.theme.baseSubText |
3444 | + width: parent.width |
3445 | + wrapMode: Text.WordWrap |
3446 | + text: i18n.tr("Delete episodes that are older than a given number of days for each podcast") |
3447 | + } |
3448 | + } |
3449 | + } |
3450 | + |
3451 | + ListItem.Base { |
3452 | + height: units.gu(10) |
3453 | + progression: true |
3454 | + showDivider: false |
3455 | + onClicked: mainStack.push(Qt.resolvedUrl("../settings/DownloadSetting.qml")) |
3456 | + Column { |
3457 | + anchors.verticalCenter: parent.verticalCenter |
3458 | + anchors.right: parent.right |
3459 | + anchors.left: parent.left |
3460 | + Label { |
3461 | + width: parent.width |
3462 | + wrapMode: Text.WordWrap |
3463 | + text: i18n.tr("Automatically download new episodes") |
3464 | + } |
3465 | + |
3466 | + Label { |
3467 | + fontSize: "small" |
3468 | + color: podbird.theme.baseSubText |
3469 | + width: parent.width |
3470 | + wrapMode: Text.WordWrap |
3471 | + text: i18n.tr("Default number of new episodes to download for each podcast") |
3472 | + } |
3473 | + } |
3474 | + } |
3475 | + |
3476 | + ListItem.Standard { |
3477 | + showDivider: false |
3478 | + text: i18n.tr("Auto download on WiFi only") |
3479 | + enabled: podbird.settings.maxEpisodeDownload !== -1 |
3480 | + control: Switch { |
3481 | + checked: podbird.settings.onlyWifiDownload |
3482 | + onClicked: { |
3483 | + podbird.settings.onlyWifiDownload = checked |
3484 | + } |
3485 | + } |
3486 | + } |
3487 | + |
3488 | + ListItem.Header { |
3489 | + text: i18n.tr("Misc.") |
3490 | + } |
3491 | + |
3492 | + ListItem.Standard { |
3493 | + progression: true |
3494 | + showDivider: false |
3495 | + text: i18n.tr("About") |
3496 | + onClicked: mainStack.push(Qt.resolvedUrl("../settings/About.qml")) |
3497 | + } |
3498 | + |
3499 | + ListItem.Standard { |
3500 | + progression: true |
3501 | + showDivider: false |
3502 | + text: i18n.tr("Report Bug") |
3503 | + onClicked: Qt.openUrlExternally("https://bugs.launchpad.net/podbird/+filebug") |
3504 | } |
3505 | } |
3506 | } |
3507 | } |
3508 | + |
3509 | + |
3510 | |
3511 | === added file 'app/ui/Walkthrough.qml' |
3512 | --- app/ui/Walkthrough.qml 1970-01-01 00:00:00 +0000 |
3513 | +++ app/ui/Walkthrough.qml 2015-04-11 21:39:04 +0000 |
3514 | @@ -0,0 +1,169 @@ |
3515 | +/* |
3516 | + * Copyright 2015 Nekhelesh Ramananthan (UCS) |
3517 | + * |
3518 | + * This file is part of Podbird. |
3519 | + * |
3520 | + * Podbird is free software; you can redistribute it and/or modify |
3521 | + * it under the terms of the GNU General Public License as published by |
3522 | + * the Free Software Foundation; version 3. |
3523 | + * |
3524 | + * Podbird is distributed in the hope that it will be useful, |
3525 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3526 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3527 | + * GNU General Public License for more details. |
3528 | + * |
3529 | + * You should have received a copy of the GNU General Public License |
3530 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3531 | + */ |
3532 | + |
3533 | +import QtQuick 2.3 |
3534 | +import Ubuntu.Components 1.1 |
3535 | +import Ubuntu.Components.ListItems 1.0 as ListItem |
3536 | + |
3537 | +Page { |
3538 | + id: walkthrough |
3539 | + |
3540 | + // Property to set the app name used in the walkthrough |
3541 | + property string appName |
3542 | + |
3543 | + // Property to check if this is the first run or not |
3544 | + property bool isFirstRun: true |
3545 | + |
3546 | + // Property to store the slides shown in the walkthrough (Each slide is a component defined in a separate file for simplicity) |
3547 | + property list<Component> model |
3548 | + |
3549 | + // Property to set the color of bottom cirle to indicate the user's progress |
3550 | + property color completeColor: "green" |
3551 | + |
3552 | + // Property to set the color of the bottom circle to indicate the slide still left to cover |
3553 | + property color inCompleteColor: "lightgrey" |
3554 | + |
3555 | + // Property to set the color of the skip welcome wizard text |
3556 | + property color skipTextColor: "grey" |
3557 | + |
3558 | + // Property to signal walkthrough completion |
3559 | + signal finished |
3560 | + |
3561 | + // ListView to show the slides |
3562 | + ListView { |
3563 | + id: listView |
3564 | + anchors { |
3565 | + left: parent.left |
3566 | + right: parent.right |
3567 | + top: skipLabel.bottom |
3568 | + bottom: slideIndicator.top |
3569 | + } |
3570 | + |
3571 | + model: walkthrough.model |
3572 | + snapMode: ListView.SnapOneItem |
3573 | + orientation: Qt.Horizontal |
3574 | + highlightMoveDuration: UbuntuAnimation.FastDuration |
3575 | + highlightRangeMode: ListView.StrictlyEnforceRange |
3576 | + highlightFollowsCurrentItem: true |
3577 | + |
3578 | + delegate: Item { |
3579 | + width: listView.width |
3580 | + height: listView.height |
3581 | + clip: true |
3582 | + |
3583 | + Loader { |
3584 | + anchors { |
3585 | + fill: parent |
3586 | + margins: units.gu(2) |
3587 | + } |
3588 | + |
3589 | + sourceComponent: modelData |
3590 | + } |
3591 | + } |
3592 | + } |
3593 | + |
3594 | + // Label to skip the walkthrough. Only visible on the first slide |
3595 | + Label { |
3596 | + id: skipLabel |
3597 | + |
3598 | + color: skipTextColor |
3599 | + fontSize: "small" |
3600 | + wrapMode: Text.WordWrap |
3601 | + text: i18n.tr("Skip") |
3602 | + horizontalAlignment: Text.AlignRight |
3603 | + |
3604 | + anchors { |
3605 | + top: parent.top |
3606 | + left: parent.left |
3607 | + right: parent.right |
3608 | + margins: units.gu(2) |
3609 | + } |
3610 | + |
3611 | + MouseArea { |
3612 | + anchors.fill: parent |
3613 | + onClicked: walkthrough.finished() |
3614 | + } |
3615 | + } |
3616 | + |
3617 | + // Indicator element to represent the current slide of the walkthrough |
3618 | + Row { |
3619 | + id: slideIndicator |
3620 | + height: units.gu(6) |
3621 | + spacing: units.gu(2) |
3622 | + anchors { |
3623 | + bottom: parent.bottom |
3624 | + horizontalCenter: parent.horizontalCenter |
3625 | + } |
3626 | + |
3627 | + Repeater { |
3628 | + model: walkthrough.model.length |
3629 | + delegate: Rectangle { |
3630 | + height: width |
3631 | + radius: width/2 |
3632 | + width: units.gu(2) |
3633 | + antialiasing: true |
3634 | + border.width: listView.currentIndex == index ? units.gu(0.2) : units.gu(0) |
3635 | + border.color: completeColor |
3636 | + anchors.verticalCenter: parent.verticalCenter |
3637 | + color: listView.currentIndex == index ? "White" |
3638 | + : listView.currentIndex >= index ? completeColor |
3639 | + : inCompleteColor |
3640 | + Behavior on color { |
3641 | + ColorAnimation { |
3642 | + duration: UbuntuAnimation.FastDuration |
3643 | + } |
3644 | + } |
3645 | + } |
3646 | + } |
3647 | + } |
3648 | + |
3649 | + ActionButton { |
3650 | + id: rightchevron |
3651 | + |
3652 | + width: units.gu(6) |
3653 | + height: units.gu(6) |
3654 | + |
3655 | + anchors { |
3656 | + bottom: parent.bottom |
3657 | + right: parent.right |
3658 | + } |
3659 | + |
3660 | + iconName: "chevron" |
3661 | + visible: enabled |
3662 | + enabled: listView.currentIndex !== listView.count-1 |
3663 | + onClicked: listView.currentIndex++ |
3664 | + } |
3665 | + |
3666 | + ActionButton { |
3667 | + id: leftchevron |
3668 | + |
3669 | + width: units.gu(6) |
3670 | + height: units.gu(6) |
3671 | + |
3672 | + anchors { |
3673 | + bottom: parent.bottom |
3674 | + left: parent.left |
3675 | + } |
3676 | + |
3677 | + iconName: "chevron" |
3678 | + rotation: 180 |
3679 | + visible: enabled |
3680 | + enabled: listView.currentIndex !== 0 |
3681 | + onClicked: listView.currentIndex-- |
3682 | + } |
3683 | +} |
3684 | |
3685 | === added directory 'app/welcomewizard' |
3686 | === added file 'app/welcomewizard/CMakeLists.txt' |
3687 | --- app/welcomewizard/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
3688 | +++ app/welcomewizard/CMakeLists.txt 2015-04-11 21:39:04 +0000 |
3689 | @@ -0,0 +1,8 @@ |
3690 | +file(GLOB WELCOMEWIZARD_QML_JS_FILES *.qml *.js) |
3691 | + |
3692 | +# Make the files visible in the qtcreator tree |
3693 | +add_custom_target(podbird_welcomewizard_QMlFiles ALL SOURCES ${WELCOMEWIZARD_QML_JS_FILES}) |
3694 | + |
3695 | +install(FILES ${WELCOMEWIZARD_QML_JS_FILES} DESTINATION ${PODBIRD_DIR}/welcomewizard) |
3696 | + |
3697 | + |
3698 | |
3699 | === added file 'app/welcomewizard/Slide1.qml' |
3700 | --- app/welcomewizard/Slide1.qml 1970-01-01 00:00:00 +0000 |
3701 | +++ app/welcomewizard/Slide1.qml 2015-04-11 21:39:04 +0000 |
3702 | @@ -0,0 +1,76 @@ |
3703 | +/* |
3704 | + * Copyright 2015 Podbird Team |
3705 | + * |
3706 | + * This file is part of Podbird. |
3707 | + * |
3708 | + * Podbird is free software; you can redistribute it and/or modify |
3709 | + * it under the terms of the GNU General Public License as published by |
3710 | + * the Free Software Foundation; version 3. |
3711 | + * |
3712 | + * Podbird is distributed in the hope that it will be useful, |
3713 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3714 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3715 | + * GNU General Public License for more details. |
3716 | + * |
3717 | + * You should have received a copy of the GNU General Public License |
3718 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3719 | + */ |
3720 | + |
3721 | +import QtQuick 2.3 |
3722 | +import Ubuntu.Components 1.1 |
3723 | + |
3724 | +// Slide 1 |
3725 | +Component { |
3726 | + id: slide1 |
3727 | + Item { |
3728 | + id: slide1Container |
3729 | + |
3730 | + Image { |
3731 | + anchors { |
3732 | + top: parent.top |
3733 | + bottom: introductionText.top |
3734 | + bottomMargin: units.gu(6) |
3735 | + horizontalCenter: parent.horizontalCenter |
3736 | + } |
3737 | + source: Qt.resolvedUrl("../graphics/podbird.png") |
3738 | + fillMode: Image.PreserveAspectFit |
3739 | + antialiasing: true |
3740 | + } |
3741 | + |
3742 | + Label { |
3743 | + id: introductionText |
3744 | + text: i18n.tr("Welcome to Podbird") |
3745 | + fontSize: "x-large" |
3746 | + height: contentHeight |
3747 | + anchors.centerIn: parent |
3748 | + } |
3749 | + |
3750 | + Label { |
3751 | + id: bodyText |
3752 | + text: i18n.tr("Enjoy your favourite podcasts with Podbird, the one and only podcast \ |
3753 | +manager for Ubuntu Touch.\n\nChirp Chirp..") |
3754 | + anchors.left: parent.left |
3755 | + anchors.right: parent.right |
3756 | + anchors.margins: units.gu(1) |
3757 | + anchors.top: introductionText.bottom |
3758 | + anchors.topMargin: units.gu(4) |
3759 | + anchors.bottom: swipeText.top |
3760 | + wrapMode: Text.WordWrap |
3761 | + horizontalAlignment: Text.AlignHCenter |
3762 | + } |
3763 | + |
3764 | + Label { |
3765 | + id: swipeText |
3766 | + anchors.left: parent.left |
3767 | + anchors.right: parent.right |
3768 | + anchors.margins: units.gu(1) |
3769 | + anchors.bottom: parent.bottom |
3770 | + color: "grey" |
3771 | + fontSize: "small" |
3772 | + wrapMode: Text.WordWrap |
3773 | + horizontalAlignment: Text.AlignHCenter |
3774 | + text: i18n.tr("Swipe to move between Pages") |
3775 | + |
3776 | + } |
3777 | + } |
3778 | +} |
3779 | |
3780 | === added file 'app/welcomewizard/Slide2.qml' |
3781 | --- app/welcomewizard/Slide2.qml 1970-01-01 00:00:00 +0000 |
3782 | +++ app/welcomewizard/Slide2.qml 2015-04-11 21:39:04 +0000 |
3783 | @@ -0,0 +1,66 @@ |
3784 | +/* |
3785 | + * Copyright 2015 Podbird Team |
3786 | + * |
3787 | + * This file is part of Podbird. |
3788 | + * |
3789 | + * Podbird is free software; you can redistribute it and/or modify |
3790 | + * it under the terms of the GNU General Public License as published by |
3791 | + * the Free Software Foundation; version 3. |
3792 | + * |
3793 | + * Podbird is distributed in the hope that it will be useful, |
3794 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3795 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3796 | + * GNU General Public License for more details. |
3797 | + * |
3798 | + * You should have received a copy of the GNU General Public License |
3799 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3800 | + */ |
3801 | + |
3802 | +import QtQuick 2.3 |
3803 | +import Ubuntu.Components 1.1 |
3804 | + |
3805 | +// Slide 2 |
3806 | +Component { |
3807 | + id: slide2 |
3808 | + Item { |
3809 | + id: slide1Container |
3810 | + |
3811 | + Image { |
3812 | + anchors { |
3813 | + top: parent.top |
3814 | + bottom: introductionText.top |
3815 | + bottomMargin: units.gu(6) |
3816 | + horizontalCenter: parent.horizontalCenter |
3817 | + } |
3818 | + fillMode: Image.PreserveAspectFit |
3819 | + source: Qt.resolvedUrl("../graphics/discover.png") |
3820 | + } |
3821 | + |
3822 | + Label { |
3823 | + id: introductionText |
3824 | + anchors.centerIn: parent |
3825 | + elide: Text.ElideRight |
3826 | + fontSize: "x-large" |
3827 | + maximumLineCount: 2 |
3828 | + text: i18n.tr("Discover New Podcasts") |
3829 | + horizontalAlignment: Text.AlignHCenter |
3830 | + width: parent.width |
3831 | + wrapMode: Text.WordWrap |
3832 | + } |
3833 | + |
3834 | + Label { |
3835 | + id: finalMessage |
3836 | + anchors { |
3837 | + top: introductionText.bottom |
3838 | + bottom: parent.bottom |
3839 | + left: parent.left |
3840 | + right: parent.right |
3841 | + margins: units.gu(1) |
3842 | + topMargin: units.gu(4) |
3843 | + } |
3844 | + horizontalAlignment: Text.AlignHCenter |
3845 | + text: i18n.tr("Podbird uses the Itunes database to provide access to a huge collections of podcasts. You can also add podcasts by URL.") |
3846 | + wrapMode: Text.WordWrap |
3847 | + } |
3848 | + } |
3849 | +} |
3850 | |
3851 | === added file 'app/welcomewizard/Slide3.qml' |
3852 | --- app/welcomewizard/Slide3.qml 1970-01-01 00:00:00 +0000 |
3853 | +++ app/welcomewizard/Slide3.qml 2015-04-11 21:39:04 +0000 |
3854 | @@ -0,0 +1,67 @@ |
3855 | +/* |
3856 | + * Copyright 2015 Podbird Team |
3857 | + * |
3858 | + * This file is part of Podbird. |
3859 | + * |
3860 | + * Podbird is free software; you can redistribute it and/or modify |
3861 | + * it under the terms of the GNU General Public License as published by |
3862 | + * the Free Software Foundation; version 3. |
3863 | + * |
3864 | + * Podbird is distributed in the hope that it will be useful, |
3865 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3866 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3867 | + * GNU General Public License for more details. |
3868 | + * |
3869 | + * You should have received a copy of the GNU General Public License |
3870 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3871 | + */ |
3872 | + |
3873 | +import QtQuick 2.3 |
3874 | +import Ubuntu.Components 1.1 |
3875 | + |
3876 | +// Slide 3 |
3877 | +Component { |
3878 | + id: slide3 |
3879 | + Item { |
3880 | + id: slide1Container |
3881 | + |
3882 | + Image { |
3883 | + anchors { |
3884 | + top: parent.top |
3885 | + bottom: introductionText.top |
3886 | + bottomMargin: units.gu(6) |
3887 | + horizontalCenter: parent.horizontalCenter |
3888 | + } |
3889 | + fillMode: Image.PreserveAspectFit |
3890 | + source: Qt.resolvedUrl("../graphics/smart.png") |
3891 | + } |
3892 | + |
3893 | + Label { |
3894 | + id: introductionText |
3895 | + anchors.centerIn: parent |
3896 | + elide: Text.ElideRight |
3897 | + fontSize: "x-large" |
3898 | + maximumLineCount: 2 |
3899 | + text: i18n.tr("Smart Settings") |
3900 | + horizontalAlignment: Text.AlignHCenter |
3901 | + width: parent.width |
3902 | + wrapMode: Text.WordWrap |
3903 | + } |
3904 | + |
3905 | + Label { |
3906 | + id: finalMessage |
3907 | + anchors { |
3908 | + top: introductionText.bottom |
3909 | + bottom: parent.bottom |
3910 | + left: parent.left |
3911 | + right: parent.right |
3912 | + margins: units.gu(1) |
3913 | + topMargin: units.gu(4) |
3914 | + } |
3915 | + horizontalAlignment: Text.AlignHCenter |
3916 | + text: i18n.tr("Podbird automatically downloads new episodes and cleans up old episodes. \ |
3917 | +As a power user you can also tweak these settings to suit your needs.") |
3918 | + wrapMode: Text.WordWrap |
3919 | + } |
3920 | + } |
3921 | +} |
3922 | |
3923 | === added file 'app/welcomewizard/Slide4.qml' |
3924 | --- app/welcomewizard/Slide4.qml 1970-01-01 00:00:00 +0000 |
3925 | +++ app/welcomewizard/Slide4.qml 2015-04-11 21:39:04 +0000 |
3926 | @@ -0,0 +1,70 @@ |
3927 | +/* |
3928 | + * Copyright 2015 Podbird Team |
3929 | + * |
3930 | + * This file is part of Podbird. |
3931 | + * |
3932 | + * Podbird is free software; you can redistribute it and/or modify |
3933 | + * it under the terms of the GNU General Public License as published by |
3934 | + * the Free Software Foundation; version 3. |
3935 | + * |
3936 | + * Podbird is distributed in the hope that it will be useful, |
3937 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3938 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3939 | + * GNU General Public License for more details. |
3940 | + * |
3941 | + * You should have received a copy of the GNU General Public License |
3942 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3943 | + */ |
3944 | + |
3945 | +import QtQuick 2.3 |
3946 | +import Ubuntu.Components 1.1 |
3947 | + |
3948 | +// Slide 4 |
3949 | +Component { |
3950 | + id: slide4 |
3951 | + Item { |
3952 | + id: slide1Container |
3953 | + |
3954 | + Image { |
3955 | + anchors { |
3956 | + top: parent.top |
3957 | + bottom: introductionText.top |
3958 | + bottomMargin: units.gu(6) |
3959 | + horizontalCenter: parent.horizontalCenter |
3960 | + } |
3961 | + fillMode: Image.PreserveAspectFit |
3962 | + source: Qt.resolvedUrl("../graphics/language.png") |
3963 | + } |
3964 | + |
3965 | + Label { |
3966 | + id: introductionText |
3967 | + anchors.centerIn: parent |
3968 | + elide: Text.ElideRight |
3969 | + fontSize: "x-large" |
3970 | + maximumLineCount: 2 |
3971 | + // TRANSLATORS: This text should be in a language different from the language set by the user. |
3972 | + // For instance, if the app was in english, then it is appropriate to set this string as |
3973 | + // Hallo or Bonjour etc to symbolize the internationalization feature in podbird. |
3974 | + text: i18n.tr("Hallo! Bonjour!") |
3975 | + horizontalAlignment: Text.AlignHCenter |
3976 | + width: parent.width |
3977 | + wrapMode: Text.WordWrap |
3978 | + } |
3979 | + |
3980 | + Label { |
3981 | + id: finalMessage |
3982 | + anchors { |
3983 | + top: introductionText.bottom |
3984 | + bottom: parent.bottom |
3985 | + left: parent.left |
3986 | + right: parent.right |
3987 | + margins: units.gu(1) |
3988 | + topMargin: units.gu(4) |
3989 | + } |
3990 | + horizontalAlignment: Text.AlignHCenter |
3991 | + text: i18n.tr("Podbird is available in over 15 languages and is translated by the \ |
3992 | +Ubuntu Translators community.") |
3993 | + wrapMode: Text.WordWrap |
3994 | + } |
3995 | + } |
3996 | +} |
3997 | |
3998 | === added file 'app/welcomewizard/Slide5.qml' |
3999 | --- app/welcomewizard/Slide5.qml 1970-01-01 00:00:00 +0000 |
4000 | +++ app/welcomewizard/Slide5.qml 2015-04-11 21:39:04 +0000 |
4001 | @@ -0,0 +1,66 @@ |
4002 | +/* |
4003 | + * Copyright 2015 Podbird Team |
4004 | + * |
4005 | + * This file is part of Podbird. |
4006 | + * |
4007 | + * Podbird is free software; you can redistribute it and/or modify |
4008 | + * it under the terms of the GNU General Public License as published by |
4009 | + * the Free Software Foundation; version 3. |
4010 | + * |
4011 | + * Podbird is distributed in the hope that it will be useful, |
4012 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4013 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4014 | + * GNU General Public License for more details. |
4015 | + * |
4016 | + * You should have received a copy of the GNU General Public License |
4017 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4018 | + */ |
4019 | + |
4020 | +import QtQuick 2.3 |
4021 | +import Ubuntu.Components 1.1 |
4022 | + |
4023 | +// Slide 5 |
4024 | +Component { |
4025 | + id: slide5 |
4026 | + Item { |
4027 | + id: slide1Container |
4028 | + |
4029 | + Image { |
4030 | + anchors { |
4031 | + top: parent.top |
4032 | + bottom: introductionText.top |
4033 | + bottomMargin: units.gu(6) |
4034 | + horizontalCenter: parent.horizontalCenter |
4035 | + } |
4036 | + fillMode: Image.PreserveAspectFit |
4037 | + source: Qt.resolvedUrl("../graphics/support.png") |
4038 | + } |
4039 | + |
4040 | + Label { |
4041 | + id: introductionText |
4042 | + anchors.centerIn: parent |
4043 | + elide: Text.ElideRight |
4044 | + fontSize: "x-large" |
4045 | + maximumLineCount: 2 |
4046 | + text: i18n.tr("Support") |
4047 | + horizontalAlignment: Text.AlignHCenter |
4048 | + width: parent.width |
4049 | + wrapMode: Text.WordWrap |
4050 | + } |
4051 | + |
4052 | + Label { |
4053 | + id: finalMessage |
4054 | + anchors { |
4055 | + top: introductionText.bottom |
4056 | + bottom: parent.bottom |
4057 | + left: parent.left |
4058 | + right: parent.right |
4059 | + margins: units.gu(1) |
4060 | + topMargin: units.gu(4) |
4061 | + } |
4062 | + horizontalAlignment: Text.AlignHCenter |
4063 | + text: i18n.tr("If you find any bugs or have any feature requests, let us know at our project page https://launchpad.net/podbird.") |
4064 | + wrapMode: Text.WordWrap |
4065 | + } |
4066 | + } |
4067 | +} |
4068 | |
4069 | === added file 'app/welcomewizard/Slide6.qml' |
4070 | --- app/welcomewizard/Slide6.qml 1970-01-01 00:00:00 +0000 |
4071 | +++ app/welcomewizard/Slide6.qml 2015-04-11 21:39:04 +0000 |
4072 | @@ -0,0 +1,80 @@ |
4073 | +/* |
4074 | + * Copyright 2015 Podbird Team |
4075 | + * |
4076 | + * This file is part of Podbird. |
4077 | + * |
4078 | + * Podbird is free software; you can redistribute it and/or modify |
4079 | + * it under the terms of the GNU General Public License as published by |
4080 | + * the Free Software Foundation; version 3. |
4081 | + * |
4082 | + * Podbird is distributed in the hope that it will be useful, |
4083 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4084 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4085 | + * GNU General Public License for more details. |
4086 | + * |
4087 | + * You should have received a copy of the GNU General Public License |
4088 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4089 | + */ |
4090 | + |
4091 | +import QtQuick 2.3 |
4092 | +import Ubuntu.Components 1.1 |
4093 | + |
4094 | +// Slide 6 |
4095 | +Component { |
4096 | + id: slide6 |
4097 | + Item { |
4098 | + id: slide1Container |
4099 | + |
4100 | + Image { |
4101 | + anchors { |
4102 | + top: parent.top |
4103 | + bottom: introductionText.top |
4104 | + bottomMargin: units.gu(6) |
4105 | + horizontalCenter: parent.horizontalCenter |
4106 | + } |
4107 | + fillMode: Image.PreserveAspectFit |
4108 | + source: Qt.resolvedUrl("../graphics/gift.png") |
4109 | + } |
4110 | + |
4111 | + Label { |
4112 | + id: introductionText |
4113 | + anchors.centerIn: parent |
4114 | + elide: Text.ElideRight |
4115 | + fontSize: "x-large" |
4116 | + maximumLineCount: 2 |
4117 | + text: i18n.tr("Enjoy") |
4118 | + horizontalAlignment: Text.AlignHCenter |
4119 | + width: parent.width |
4120 | + wrapMode: Text.WordWrap |
4121 | + } |
4122 | + |
4123 | + Label { |
4124 | + id: finalMessage |
4125 | + anchors { |
4126 | + top: introductionText.bottom |
4127 | + bottom: continueButton.top |
4128 | + left: parent.left |
4129 | + right: parent.right |
4130 | + margins: units.gu(1) |
4131 | + topMargin: units.gu(4) |
4132 | + } |
4133 | + horizontalAlignment: Text.AlignHCenter |
4134 | + text: i18n.tr("We hope you will enjoy using Podbird!") |
4135 | + wrapMode: Text.WordWrap |
4136 | + } |
4137 | + |
4138 | + Button { |
4139 | + id: continueButton |
4140 | + anchors { |
4141 | + bottom: parent.bottom |
4142 | + bottomMargin: units.gu(3) |
4143 | + horizontalCenter: parent.horizontalCenter |
4144 | + } |
4145 | + height: units.gu(6) |
4146 | + width: parent.width/1.3 |
4147 | + color: UbuntuColors.green |
4148 | + text: i18n.tr("Finish") |
4149 | + onClicked: finished() |
4150 | + } |
4151 | + } |
4152 | +} |
4153 | |
4154 | === added file 'app/welcomewizard/WelcomeWizard.qml' |
4155 | --- app/welcomewizard/WelcomeWizard.qml 1970-01-01 00:00:00 +0000 |
4156 | +++ app/welcomewizard/WelcomeWizard.qml 2015-04-11 21:39:04 +0000 |
4157 | @@ -0,0 +1,41 @@ |
4158 | +/* |
4159 | + * Copyright 2015 Podbird Team |
4160 | + * |
4161 | + * This file is part of Podbird. |
4162 | + * |
4163 | + * Podbird is free software; you can redistribute it and/or modify |
4164 | + * it under the terms of the GNU General Public License as published by |
4165 | + * the Free Software Foundation; version 3. |
4166 | + * |
4167 | + * Podbird is distributed in the hope that it will be useful, |
4168 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4169 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4170 | + * GNU General Public License for more details. |
4171 | + * |
4172 | + * You should have received a copy of the GNU General Public License |
4173 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4174 | + */ |
4175 | + |
4176 | +import QtQuick 2.3 |
4177 | +import Ubuntu.Components 1.1 |
4178 | +import "../ui" |
4179 | + |
4180 | +// Initial Walkthrough tutorial |
4181 | +Walkthrough { |
4182 | + id: walkthrough |
4183 | + appName: "Podbird" |
4184 | + onFinished: { |
4185 | + console.log("[LOG]: Welcome tour complete") |
4186 | + settings.firstRun = false |
4187 | + mainStack.pop() |
4188 | + mainStack.push(tabs) |
4189 | + } |
4190 | + model: [ |
4191 | + Slide1{}, |
4192 | + Slide2{}, |
4193 | + Slide3{}, |
4194 | + Slide4{}, |
4195 | + Slide5{}, |
4196 | + Slide6{} |
4197 | + ] |
4198 | +} |
4199 | |
4200 | === modified file 'po/com.mikeasoft.podbird.pot' |
4201 | --- po/com.mikeasoft.podbird.pot 2015-03-29 16:40:52 +0000 |
4202 | +++ po/com.mikeasoft.podbird.pot 2015-04-11 21:39:04 +0000 |
4203 | @@ -8,7 +8,7 @@ |
4204 | msgstr "" |
4205 | "Project-Id-Version: \n" |
4206 | "Report-Msgid-Bugs-To: \n" |
4207 | -"POT-Creation-Date: 2015-03-29 16:48+0100\n" |
4208 | +"POT-Creation-Date: 2015-04-11 23:32+0200\n" |
4209 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
4210 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
4211 | "Language-Team: LANGUAGE <LL@li.org>\n" |
4212 | @@ -18,72 +18,207 @@ |
4213 | "Content-Transfer-Encoding: 8bit\n" |
4214 | "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" |
4215 | |
4216 | -#: ../app/ui/EpisodesPage.qml:85 |
4217 | +#. TRANSLATORS: this refers to a number of songs greater than one. The actual number will be prepended to the string automatically (plural forms are not yet fully supported in usermetrics, the library that displays that string) |
4218 | +#: ../app/podbird.qml:152 |
4219 | +msgid "podcasts listened today" |
4220 | +msgstr "" |
4221 | + |
4222 | +#: ../app/podbird.qml:153 |
4223 | +msgid "No podcasts listened today" |
4224 | +msgstr "" |
4225 | + |
4226 | +#: ../app/podbird.qml:210 |
4227 | +msgid "Find New Podcasts" |
4228 | +msgstr "" |
4229 | + |
4230 | +#: ../app/podbird.qml:224 |
4231 | +msgid "Settings" |
4232 | +msgstr "" |
4233 | + |
4234 | +#: ../app/settings/About.qml:8 ../app/settings/About.qml:11 |
4235 | +#: ../app/ui/SettingsPage.qml:136 |
4236 | +msgid "About" |
4237 | +msgstr "" |
4238 | + |
4239 | +#: ../app/settings/About.qml:11 |
4240 | +msgid "Credits" |
4241 | +msgstr "" |
4242 | + |
4243 | +#: ../app/settings/About.qml:65 |
4244 | +msgid "Released under the terms of the GNU GPL v3" |
4245 | +msgstr "" |
4246 | + |
4247 | +#: ../app/settings/About.qml:74 |
4248 | +#, qt-format |
4249 | +msgid "Source code available on %1" |
4250 | +msgstr "" |
4251 | + |
4252 | +#: ../app/settings/About.qml:89 |
4253 | +msgid "Developers" |
4254 | +msgstr "" |
4255 | + |
4256 | +#: ../app/settings/About.qml:103 |
4257 | +msgid "Designer" |
4258 | +msgstr "" |
4259 | + |
4260 | +#: ../app/settings/About.qml:112 |
4261 | +msgid "Translators" |
4262 | +msgstr "" |
4263 | + |
4264 | +#: ../app/settings/CleanSetting.qml:27 |
4265 | +msgid "Delete older than" |
4266 | +msgstr "" |
4267 | + |
4268 | +#: ../app/settings/CleanSetting.qml:33 ../app/settings/DownloadSetting.qml:33 |
4269 | +msgid "Never" |
4270 | +msgstr "" |
4271 | + |
4272 | +#: ../app/settings/CleanSetting.qml:34 |
4273 | +#, qt-format |
4274 | +msgid "%1 day" |
4275 | +msgid_plural "%1 days" |
4276 | +msgstr[0] "" |
4277 | +msgstr[1] "" |
4278 | + |
4279 | +#: ../app/settings/CleanSetting.qml:35 ../app/settings/CleanSetting.qml:36 |
4280 | +#: ../app/settings/CleanSetting.qml:37 |
4281 | +#, qt-format |
4282 | +msgid "%1 month" |
4283 | +msgid_plural "%1 months" |
4284 | +msgstr[0] "" |
4285 | +msgstr[1] "" |
4286 | + |
4287 | +#: ../app/settings/CleanSetting.qml:38 |
4288 | +#, qt-format |
4289 | +msgid "%1 year" |
4290 | +msgid_plural "%1 years" |
4291 | +msgstr[0] "" |
4292 | +msgstr[1] "" |
4293 | + |
4294 | +#: ../app/settings/DownloadSetting.qml:27 |
4295 | +msgid "Download at most" |
4296 | +msgstr "" |
4297 | + |
4298 | +#: ../app/settings/DownloadSetting.qml:34 |
4299 | +#: ../app/settings/DownloadSetting.qml:35 |
4300 | +#: ../app/settings/DownloadSetting.qml:36 |
4301 | +#: ../app/settings/DownloadSetting.qml:37 ../app/ui/EpisodesPage.qml:463 |
4302 | +#, qt-format |
4303 | +msgid "%1 episode" |
4304 | +msgid_plural "%1 episodes" |
4305 | +msgstr[0] "" |
4306 | +msgstr[1] "" |
4307 | + |
4308 | +#: ../app/settings/ThemeSetting.qml:27 ../app/ui/SettingsPage.qml:49 |
4309 | +msgid "Theme" |
4310 | +msgstr "" |
4311 | + |
4312 | +#: ../app/settings/ThemeSetting.qml:33 |
4313 | +msgid "Light" |
4314 | +msgstr "" |
4315 | + |
4316 | +#: ../app/settings/ThemeSetting.qml:34 |
4317 | +msgid "Dark" |
4318 | +msgstr "" |
4319 | + |
4320 | +#: ../app/ui/EpisodesPage.qml:33 |
4321 | +msgid "Podcast" |
4322 | +msgstr "" |
4323 | + |
4324 | +#: ../app/ui/EpisodesPage.qml:89 ../app/ui/SearchPage.qml:55 |
4325 | msgid "Search Episode" |
4326 | msgstr "" |
4327 | |
4328 | -#: ../app/ui/EpisodesPage.qml:94 |
4329 | +#: ../app/ui/EpisodesPage.qml:98 |
4330 | msgid "Mark all listened" |
4331 | msgstr "" |
4332 | |
4333 | -#: ../app/ui/EpisodesPage.qml:105 ../app/ui/EpisodesPage.qml:153 |
4334 | +#: ../app/ui/EpisodesPage.qml:109 ../app/ui/EpisodesPage.qml:187 |
4335 | msgid "Unsubscribe" |
4336 | msgstr "" |
4337 | |
4338 | -#: ../app/ui/EpisodesPage.qml:120 ../app/ui/PodcastsTab.qml:86 |
4339 | -#: ../app/ui/PodcastsTab.qml:109 |
4340 | +#: ../app/ui/EpisodesPage.qml:124 ../app/ui/PodcastsTab.qml:96 |
4341 | +#: ../app/ui/PodcastsTab.qml:119 ../app/ui/SearchPage.qml:69 |
4342 | msgid "Back" |
4343 | msgstr "" |
4344 | |
4345 | -#: ../app/ui/EpisodesPage.qml:131 |
4346 | +#: ../app/ui/EpisodesPage.qml:136 |
4347 | msgid "Search episode" |
4348 | msgstr "" |
4349 | |
4350 | -#: ../app/ui/EpisodesPage.qml:150 |
4351 | +#: ../app/ui/EpisodesPage.qml:184 |
4352 | msgid "Unsubscribe Confirmation" |
4353 | msgstr "" |
4354 | |
4355 | -#: ../app/ui/EpisodesPage.qml:151 |
4356 | +#: ../app/ui/EpisodesPage.qml:185 |
4357 | #, qt-format |
4358 | msgid "Are you sure you want to unsubscribe from <b>%1</b>?" |
4359 | msgstr "" |
4360 | |
4361 | -#: ../app/ui/EpisodesPage.qml:170 |
4362 | +#: ../app/ui/EpisodesPage.qml:204 |
4363 | msgid "Cancel" |
4364 | msgstr "" |
4365 | |
4366 | -#: ../app/ui/EpisodesPage.qml:184 |
4367 | +#: ../app/ui/EpisodesPage.qml:258 |
4368 | +msgid "Delete local file" |
4369 | +msgstr "" |
4370 | + |
4371 | +#: ../app/ui/EpisodesPage.qml:259 |
4372 | +msgid "Episode queued for download" |
4373 | +msgstr "" |
4374 | + |
4375 | +#: ../app/ui/EpisodesPage.qml:260 |
4376 | +msgid "Download episode" |
4377 | +msgstr "" |
4378 | + |
4379 | +#: ../app/ui/EpisodesPage.qml:336 |
4380 | +msgid "No more episodes" |
4381 | +msgstr "" |
4382 | + |
4383 | +#: ../app/ui/EpisodesPage.qml:336 |
4384 | msgid "No Episodes found" |
4385 | msgstr "" |
4386 | |
4387 | -#: ../app/ui/EpisodesPage.qml:185 |
4388 | +#: ../app/ui/EpisodesPage.qml:337 |
4389 | +msgid "All episodes have been listened to." |
4390 | +msgstr "" |
4391 | + |
4392 | +#: ../app/ui/EpisodesPage.qml:337 |
4393 | msgid "No episodes found matching the search term." |
4394 | msgstr "" |
4395 | |
4396 | -#: ../app/ui/EpisodesPage.qml:319 |
4397 | -#, no-c-format, qt-format |
4398 | -msgid "%1h %2m" |
4399 | -msgstr "" |
4400 | - |
4401 | -#: ../app/ui/EpisodesPage.qml:328 |
4402 | -#, no-c-format, qt-format |
4403 | -msgid "%1h" |
4404 | -msgstr "" |
4405 | - |
4406 | -#: ../app/ui/EpisodesPage.qml:336 |
4407 | -#, no-c-format, qt-format |
4408 | -msgid "%1m" |
4409 | +#: ../app/ui/EpisodesPage.qml:359 |
4410 | +#, no-c-format, qt-format |
4411 | +msgid "%1 hr %2 min" |
4412 | +msgstr "" |
4413 | + |
4414 | +#: ../app/ui/EpisodesPage.qml:368 |
4415 | +#, no-c-format, qt-format |
4416 | +msgid "%1 hr" |
4417 | +msgstr "" |
4418 | + |
4419 | +#: ../app/ui/EpisodesPage.qml:376 |
4420 | +#, no-c-format, qt-format |
4421 | +msgid "%1 min" |
4422 | +msgstr "" |
4423 | + |
4424 | +#: ../app/ui/EpisodesPage.qml:416 |
4425 | +msgid "Unheard" |
4426 | +msgstr "" |
4427 | + |
4428 | +#: ../app/ui/EpisodesPage.qml:416 |
4429 | +msgid "Listened" |
4430 | msgstr "" |
4431 | |
4432 | #: ../app/ui/NowPlayingPage.qml:28 |
4433 | msgid "Now Playing" |
4434 | msgstr "" |
4435 | |
4436 | -#: ../app/ui/NowPlayingPage.qml:145 |
4437 | +#: ../app/ui/NowPlayingPage.qml:150 |
4438 | msgid "-15s" |
4439 | msgstr "" |
4440 | |
4441 | -#: ../app/ui/NowPlayingPage.qml:204 |
4442 | +#: ../app/ui/NowPlayingPage.qml:209 |
4443 | msgid "+15s" |
4444 | msgstr "" |
4445 | |
4446 | @@ -91,124 +226,207 @@ |
4447 | msgid "Podcasts" |
4448 | msgstr "" |
4449 | |
4450 | -#: ../app/ui/PodcastsTab.qml:62 |
4451 | +#: ../app/ui/PodcastsTab.qml:64 |
4452 | msgid "Add Podcast" |
4453 | msgstr "" |
4454 | |
4455 | -#: ../app/ui/PodcastsTab.qml:72 |
4456 | +#: ../app/ui/PodcastsTab.qml:74 |
4457 | msgid "Search Podcast" |
4458 | msgstr "" |
4459 | |
4460 | -#: ../app/ui/PodcastsTab.qml:97 |
4461 | +#: ../app/ui/PodcastsTab.qml:83 |
4462 | +msgid "Grid View" |
4463 | +msgstr "" |
4464 | + |
4465 | +#: ../app/ui/PodcastsTab.qml:83 |
4466 | +msgid "List View" |
4467 | +msgstr "" |
4468 | + |
4469 | +#: ../app/ui/PodcastsTab.qml:107 |
4470 | msgid "Search podcast" |
4471 | msgstr "" |
4472 | |
4473 | -#: ../app/ui/PodcastsTab.qml:120 |
4474 | +#: ../app/ui/PodcastsTab.qml:130 |
4475 | msgid "Save Podcast" |
4476 | msgstr "" |
4477 | |
4478 | -#: ../app/ui/PodcastsTab.qml:133 |
4479 | +#: ../app/ui/PodcastsTab.qml:143 |
4480 | msgid "Feed URL" |
4481 | msgstr "" |
4482 | |
4483 | -#: ../app/ui/PodcastsTab.qml:157 |
4484 | +#: ../app/ui/PodcastsTab.qml:167 |
4485 | msgid "Unable to subscribe" |
4486 | msgstr "" |
4487 | |
4488 | -#: ../app/ui/PodcastsTab.qml:158 |
4489 | +#: ../app/ui/PodcastsTab.qml:168 |
4490 | msgid "Please check the URL and try again" |
4491 | msgstr "" |
4492 | |
4493 | -#: ../app/ui/PodcastsTab.qml:160 |
4494 | +#: ../app/ui/PodcastsTab.qml:170 |
4495 | msgid "Close" |
4496 | msgstr "" |
4497 | |
4498 | -#: ../app/ui/PodcastsTab.qml:172 |
4499 | +#: ../app/ui/PodcastsTab.qml:184 |
4500 | msgid "No Podcast Subscriptions" |
4501 | msgstr "" |
4502 | |
4503 | -#: ../app/ui/PodcastsTab.qml:173 |
4504 | +#: ../app/ui/PodcastsTab.qml:185 |
4505 | msgid "No Podcasts Found" |
4506 | msgstr "" |
4507 | |
4508 | -#: ../app/ui/PodcastsTab.qml:174 |
4509 | +#: ../app/ui/PodcastsTab.qml:186 |
4510 | msgid "" |
4511 | "You haven't subscribed to any podcasts yet, visit the 'Find New Podcasts' " |
4512 | "page to add some." |
4513 | msgstr "" |
4514 | |
4515 | -#: ../app/ui/PodcastsTab.qml:175 |
4516 | +#: ../app/ui/PodcastsTab.qml:187 ../app/ui/SearchPage.qml:103 |
4517 | msgid "No podcasts found matching the search term." |
4518 | msgstr "" |
4519 | |
4520 | -#: ../app/ui/PodcastsTab.qml:291 |
4521 | +#: ../app/ui/PodcastsTab.qml:217 ../app/ui/PodcastsTab.qml:337 |
4522 | #, qt-format |
4523 | msgid "%1 unheard episode" |
4524 | msgid_plural "%1 unheard episodes" |
4525 | msgstr[0] "" |
4526 | msgstr[1] "" |
4527 | |
4528 | -#: ../app/ui/SearchTab.qml:27 |
4529 | -msgid "Find New Podcasts" |
4530 | -msgstr "" |
4531 | - |
4532 | -#: ../app/ui/SearchTab.qml:42 |
4533 | +#: ../app/ui/SearchPage.qml:80 |
4534 | msgid "Search..." |
4535 | msgstr "" |
4536 | |
4537 | -#: ../app/ui/SearchTab.qml:122 |
4538 | +#: ../app/ui/SearchPage.qml:102 |
4539 | +msgid "Looking for a new Podcast?" |
4540 | +msgstr "" |
4541 | + |
4542 | +#: ../app/ui/SearchPage.qml:102 |
4543 | +msgid "No Podcasts found" |
4544 | +msgstr "" |
4545 | + |
4546 | +#: ../app/ui/SearchPage.qml:103 |
4547 | +msgid "Click the 'magnifier' at the top to search." |
4548 | +msgstr "" |
4549 | + |
4550 | +#: ../app/ui/SearchPage.qml:184 |
4551 | msgid "Subscribe" |
4552 | msgstr "" |
4553 | |
4554 | -#: ../app/ui/SettingsTab.qml:26 |
4555 | -msgid "Settings" |
4556 | -msgstr "" |
4557 | - |
4558 | -#: ../app/ui/SettingsTab.qml:35 |
4559 | -msgid "Light" |
4560 | -msgstr "" |
4561 | - |
4562 | -#: ../app/ui/SettingsTab.qml:36 |
4563 | -msgid "Dark" |
4564 | -msgstr "" |
4565 | - |
4566 | -#: ../app/ui/SettingsTab.qml:44 ../app/ui/SettingsTab.qml:93 |
4567 | -msgid "Never" |
4568 | -msgstr "" |
4569 | - |
4570 | -#: ../app/ui/SettingsTab.qml:45 |
4571 | -msgid "7 days" |
4572 | -msgstr "" |
4573 | - |
4574 | -#: ../app/ui/SettingsTab.qml:46 |
4575 | -msgid "31 days" |
4576 | -msgstr "" |
4577 | - |
4578 | -#: ../app/ui/SettingsTab.qml:47 |
4579 | -msgid "90 days" |
4580 | -msgstr "" |
4581 | - |
4582 | -#: ../app/ui/SettingsTab.qml:48 |
4583 | -msgid "180 days" |
4584 | -msgstr "" |
4585 | - |
4586 | -#: ../app/ui/SettingsTab.qml:49 |
4587 | -msgid "360 days" |
4588 | -msgstr "" |
4589 | - |
4590 | -#: ../app/ui/SettingsTab.qml:62 |
4591 | -msgid "Theme" |
4592 | -msgstr "" |
4593 | - |
4594 | -#: ../app/ui/SettingsTab.qml:92 |
4595 | -msgid "Remove episodes older than" |
4596 | -msgstr "" |
4597 | - |
4598 | -#: ../app/ui/SettingsTab.qml:94 |
4599 | -#, qt-format |
4600 | -msgid "%1 days" |
4601 | -msgstr "" |
4602 | - |
4603 | -#: /home/mike/src/build-podbird-Ubuntu_Device_GCC_armhf_ubuntu_sdk_14_10_utopic-Default/po/Podbird.desktop.in.h:1 |
4604 | +#: ../app/ui/SettingsPage.qml:43 |
4605 | +msgid "General Settings" |
4606 | +msgstr "" |
4607 | + |
4608 | +#: ../app/ui/SettingsPage.qml:55 |
4609 | +msgid "Podcast Episode Settings" |
4610 | +msgstr "" |
4611 | + |
4612 | +#: ../app/ui/SettingsPage.qml:60 |
4613 | +msgid "Hide listened episodes" |
4614 | +msgstr "" |
4615 | + |
4616 | +#: ../app/ui/SettingsPage.qml:79 |
4617 | +msgid "Automatically delete old episodes" |
4618 | +msgstr "" |
4619 | + |
4620 | +#: ../app/ui/SettingsPage.qml:87 |
4621 | +msgid "" |
4622 | +"Delete episodes that are older than a given number of days for each podcast" |
4623 | +msgstr "" |
4624 | + |
4625 | +#: ../app/ui/SettingsPage.qml:104 |
4626 | +msgid "Automatically download new episodes" |
4627 | +msgstr "" |
4628 | + |
4629 | +#: ../app/ui/SettingsPage.qml:112 |
4630 | +msgid "Default number of new episodes to download for each podcast" |
4631 | +msgstr "" |
4632 | + |
4633 | +#: ../app/ui/SettingsPage.qml:119 |
4634 | +msgid "Auto download on WiFi only" |
4635 | +msgstr "" |
4636 | + |
4637 | +#: ../app/ui/SettingsPage.qml:130 |
4638 | +msgid "Misc." |
4639 | +msgstr "" |
4640 | + |
4641 | +#: ../app/ui/SettingsPage.qml:143 |
4642 | +msgid "Report Bug" |
4643 | +msgstr "" |
4644 | + |
4645 | +#: ../app/ui/Walkthrough.qml:87 |
4646 | +msgid "Skip" |
4647 | +msgstr "" |
4648 | + |
4649 | +#: ../app/welcomewizard/Slide1.qml:42 |
4650 | +msgid "Welcome to Podbird" |
4651 | +msgstr "" |
4652 | + |
4653 | +#: ../app/welcomewizard/Slide1.qml:50 |
4654 | +msgid "" |
4655 | +"Enjoy your favourite podcasts with Podbird, the one and only podcast manager " |
4656 | +"for Ubuntu Touch.\n" |
4657 | +"\n" |
4658 | +"Chirp Chirp.." |
4659 | +msgstr "" |
4660 | + |
4661 | +#: ../app/welcomewizard/Slide1.qml:72 |
4662 | +msgid "Swipe to move between Pages" |
4663 | +msgstr "" |
4664 | + |
4665 | +#: ../app/welcomewizard/Slide2.qml:45 |
4666 | +msgid "Discover New Podcasts" |
4667 | +msgstr "" |
4668 | + |
4669 | +#: ../app/welcomewizard/Slide2.qml:62 |
4670 | +msgid "" |
4671 | +"Podbird uses the Itunes database to provide access to a huge collections of " |
4672 | +"podcasts. You can also add podcasts by URL." |
4673 | +msgstr "" |
4674 | + |
4675 | +#: ../app/welcomewizard/Slide3.qml:45 |
4676 | +msgid "Smart Settings" |
4677 | +msgstr "" |
4678 | + |
4679 | +#: ../app/welcomewizard/Slide3.qml:62 |
4680 | +msgid "" |
4681 | +"Podbird automatically downloads new episodes and cleans up old episodes. As " |
4682 | +"a power user you can also tweak these settings to suit your needs." |
4683 | +msgstr "" |
4684 | + |
4685 | +#. TRANSLATORS: This text should be in a language different from the language set by the user. |
4686 | +#. For instance, if the app was in english, then it is appropriate to set this string as |
4687 | +#. Hallo or Bonjour etc to symbolize the internationalization feature in podbird. |
4688 | +#: ../app/welcomewizard/Slide4.qml:48 |
4689 | +msgid "Hallo! Bonjour!" |
4690 | +msgstr "" |
4691 | + |
4692 | +#: ../app/welcomewizard/Slide4.qml:65 |
4693 | +msgid "" |
4694 | +"Podbird is available in over 15 languages and is translated by the Ubuntu " |
4695 | +"Translators community." |
4696 | +msgstr "" |
4697 | + |
4698 | +#: ../app/welcomewizard/Slide5.qml:45 |
4699 | +msgid "Support" |
4700 | +msgstr "" |
4701 | + |
4702 | +#: ../app/welcomewizard/Slide5.qml:62 |
4703 | +msgid "" |
4704 | +"If you find any bugs or have any feature requests, let us know at our " |
4705 | +"project page https://launchpad.net/podbird." |
4706 | +msgstr "" |
4707 | + |
4708 | +#: ../app/welcomewizard/Slide6.qml:45 |
4709 | +msgid "Enjoy" |
4710 | +msgstr "" |
4711 | + |
4712 | +#: ../app/welcomewizard/Slide6.qml:62 |
4713 | +msgid "We hope you will enjoy using Podbird!" |
4714 | +msgstr "" |
4715 | + |
4716 | +#: ../app/welcomewizard/Slide6.qml:76 |
4717 | +msgid "Finish" |
4718 | +msgstr "" |
4719 | + |
4720 | +#: /home/krnekhelesh/Documents/Ubuntu-Projects/MP-Reviews/builddir/build-8.6-aboutpage-UbuntuSDK_for_armhf_GCC_ubuntu_sdk_14_10_utopic-Default/po/Podbird.desktop.in.h:1 |
4721 | msgid "Podbird" |
4722 | msgstr "" |
4723 | |
4724 | === added file 'podbird.png' |
4725 | Binary files podbird.png 1970-01-01 00:00:00 +0000 and podbird.png 2015-04-11 21:39:04 +0000 differ |