Merge lp:~unity-2d-team/unity-2d/launcher-layout into lp:unity-2d/3.0
- launcher-layout
- Merge into natty
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Approved by: | Florian Boucault | ||||||||
Approved revision: | 395 | ||||||||
Merged at revision: | 388 | ||||||||
Proposed branch: | lp:~unity-2d-team/unity-2d/launcher-layout | ||||||||
Merge into: | lp:unity-2d/3.0 | ||||||||
Diff against target: |
1074 lines (+394/-278) 19 files modified
launcher/Launcher.qml (+31/-22) launcher/LauncherItem.qml (+180/-167) launcher/UnityApplications/iconimageprovider.cpp (+29/-19) launcher/UnityApplications/launcherapplication.cpp (+19/-0) launcher/UnityApplications/launcherapplication.h (+2/-0) launcher/UnityApplications/launcherdevice.cpp (+6/-0) launcher/UnityApplications/launcherdevice.h (+1/-0) launcher/UnityApplications/launcheritem.h (+3/-0) launcher/UnityApplications/placeentry.cpp (+6/-0) launcher/UnityApplications/placeentry.h (+1/-0) launcher/UnityApplications/trash.cpp (+7/-1) launcher/UnityApplications/trash.h (+1/-0) launcher/UnityApplications/workspaces.cpp (+6/-0) launcher/UnityApplications/workspaces.h (+1/-0) launcher/app/launcher.cpp (+8/-1) launcher/app/launcherview.cpp (+39/-51) launcher/app/launcherview.h (+2/-1) libunity-2d-private/Unity2d/blendedimageprovider.cpp (+51/-15) panel/applets/homebutton/homebuttonapplet.cpp (+1/-1) |
||||||||
To merge this branch: | bzr merge lp:~unity-2d-team/unity-2d/launcher-layout | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Florian Boucault (community) | Approve | ||
Review via email: mp+49368@code.launchpad.net |
Commit message
Description of the change
[launcher] Implement various look and feel changes in the launcher to match the launcher design on Natty.
The only functional change is the "pips" on the right side of the window to indicate the number of open windows.
There are also changes to the icon and blended image providers, to correctly handle scaling if requested in the former and to use the right compositing mode for the latter. Both also have more warnings and safer code.
Everything else is visual changes and code cleaning.
Florian Boucault (fboucault) wrote : | # |
launcher/
QDebug include is in the middle of the file.
Ugo Riboni (uriboni) wrote : | # |
Fixed the QDebug. Regarding the 66 vs. 65 pixels: it's 66 in the current natty implementation, 65 in the mockup. I didn't fix it for now, and you will figure it out with Otto later as agreed.
- 387. By Ugo Riboni
-
Move QDebug include to the top of the file
Florian Boucault (fboucault) wrote : | # |
=== modified file 'launcher/
@@ -44,11 +53,7 @@
}
-
- /* The menu needs to never overlap with the MouseArea of
- item otherwise flickering happens when the mouse is on
- an overlapping pixel (hence the -4). */
- item.menu.
+ item.menu.
The contextual menu's vertical position is slightly off, it should be around 3 pixels below. The point of the arrow of the contextual menu should be at the same height as the point of the arrow showing that the application is focused.
Florian Boucault (fboucault) wrote : | # |
Can you add an unexpected change to that merge request? The width of the ubuntu circle of friends button in the panel has to coincide with the width of the launcher so that the line of the button and the border line of the launcher match perfectly and form only one continuous vertical line.
Thanks.
Florian Boucault (fboucault) wrote : | # |
=== modified file 'launcher/
+ It is tile composed by a colored background layer, an icon (with 'icon' as source),
+ and a shine layer on top.
does not make sense.
Florian Boucault (fboucault) wrote : | # |
=== modified file 'launcher/
@@ -394,6 +404,8 @@
}
if (m_has_
emit hasVisibleWindo
+
+ Q_EMIT windowCountChan
}
This is a hack taking advantage of the fact that LauncherApplica
Instead you need to define a slot that will do Q_EMIT windowCountChan
Florian Boucault (fboucault) wrote : | # |
> === modified file 'launcher/
>
> @@ -394,6 +404,8 @@
> }
> if (m_has_
> emit hasVisibleWindo
> +
> + Q_EMIT windowCountChan
> }
>
>
> This is a hack taking advantage of the fact that
> LauncherApplica
>
> Instead you need to define a slot that will do Q_EMIT
> windowCountChan
> BamfApplication
I suggest calling the slot 'updateWindowCo
Florian Boucault (fboucault) wrote : | # |
=== modified file 'launcher/
@@ -32,6 +32,9 @@
#include <X11/Xlib.h>
#include <X11/Xatom.h>
+#define MAX(a,b) ((a >= b) ? a : b)
+#define MIN(a,b) ((a <= b) ? a : b)
+
Remove and replace with Qt's qMax and qMin.
Florian Boucault (fboucault) wrote : | # |
=== modified file 'launcher/
--- launcher/
+++ launcher/
@@ -76,12 +76,15 @@
launcherVi
launcherVi
+ launcherView-
This should _only_ be done when running un-installed. Please take example from places/
if (!isRunningInst
[...]
/* Place.qml imports Unity2d */
}
Florian Boucault (fboucault) wrote : | # |
=== modified file 'launcher/
launcherVi
launcherVi
+ launcherView-
+ launcherView-
This looks like a workaround for the lack of support of images in path relative to the launcher binary in BlendedImagePro
Florian Boucault (fboucault) wrote : | # |
=== added file 'launcher/
=== added file 'launcher/
=== added file 'launcher/
No abbreviations. Replace 'ltr' with 'left' and 'rtl' with 'right'.
Florian Boucault (fboucault) wrote : | # |
I sometimes get a WARNING (hopefully not important):
LauncherItem.qml:89 Unable to assign undefined value
Florian Boucault (fboucault) wrote : | # |
=== modified file 'libunity-
qWarning() << "BlendedImagePr
should read
qWarning() << "BlendedImagePr
"[...] when a sting isn't an SVG color name"
should read
"[...] when a string is not a SVG color name (eg. "red", "yellow", etc.)
Florian Boucault (fboucault) wrote : | # |
Only 'launcher/
- 388. By Ugo Riboni
-
Make sure the panel home button is aligned with the new launcher size
- 389. By Ugo Riboni
-
Make sure the menu is aligned with the center of tha active app arrow
- 390. By Ugo Riboni
-
Fix typos in comment
- 391. By Ugo Riboni
-
Fix to prevent some harmless warnings
- 392. By Ugo Riboni
-
Separate the code path for updating windowCount from that of hasVisibleWindow
- 393. By Ugo Riboni
-
Use qMin and qMax instead of local defines
- 394. By Ugo Riboni
-
Make sure to correctly add import paths based on installed/
uninstalled status. Document a workaround. - 395. By Ugo Riboni
-
Fix typos and docs
Ugo Riboni (uriboni) wrote : | # |
Fixed pretty much everything, except the renaming of the icons which stay as they are since they were copied from Unity.
Also please check my fix in commit 391 for the following warning:
"LauncherItem.
and let me know if you have a better workaround.
Florian Boucault (fboucault) wrote : | # |
Sounds good to me, ship that good job!
Preview Diff
1 | === modified file 'launcher/Launcher.qml' |
2 | --- launcher/Launcher.qml 2011-02-10 08:24:27 +0000 |
3 | +++ launcher/Launcher.qml 2011-02-15 13:21:38 +0000 |
4 | @@ -2,39 +2,48 @@ |
5 | import UnityApplications 1.0 |
6 | |
7 | Item { |
8 | - width: 58 |
9 | - height: 1024 |
10 | + id: launcher |
11 | |
12 | Image { |
13 | id: background |
14 | |
15 | anchors.fill: parent |
16 | fillMode: Image.TileVertically |
17 | - source: "/usr/share/unity/themes/launcher_background_middle.png" |
18 | + source: "artwork/background.png" |
19 | } |
20 | |
21 | ListView { |
22 | id: list |
23 | + spacing: 5 |
24 | + anchors.topMargin: 5 |
25 | + anchors.fill: parent |
26 | + focus: true |
27 | |
28 | /* Keep a reference to the currently visible contextual menu */ |
29 | property variant visibleMenu |
30 | |
31 | - anchors.fill: parent |
32 | - focus: true |
33 | - |
34 | model: ListAggregatorModel { |
35 | id: items |
36 | } |
37 | |
38 | delegate: LauncherItem { |
39 | - id: wrapper |
40 | - |
41 | - width: 58; height: 54 |
42 | - icon: "image://icons/"+item.icon |
43 | + id: launcherItem |
44 | + |
45 | + width: launcher.width |
46 | + height: tileSize |
47 | + |
48 | + icon: "image://icons/" + item.icon |
49 | running: item.running |
50 | active: item.active |
51 | urgent: item.urgent |
52 | launching: item.launching |
53 | + pips: Math.min(item.windowCount, 3) |
54 | + tileSize: 54 |
55 | + |
56 | + /* Best way I could find to check if the item is an application or the |
57 | + workspaces switcher. There may be something cleaner and better. */ |
58 | + backgroundFromIcon: item.toString().indexOf("LauncherApplication") == 0 || |
59 | + item.toString().indexOf("Workspaces") == 0 |
60 | |
61 | Binding { target: item.menu; property: "title"; value: item.name } |
62 | |
63 | @@ -44,11 +53,9 @@ |
64 | list.visibleMenu.hide() |
65 | } |
66 | list.visibleMenu = item.menu |
67 | - |
68 | - /* The menu needs to never overlap with the MouseArea of |
69 | - item otherwise flickering happens when the mouse is on |
70 | - an overlapping pixel (hence the -4). */ |
71 | - item.menu.show(width-4, y+height/2-list.contentY+panel.y) |
72 | + // The extra 4 pixels are needed to center exactly with the arrow |
73 | + // that indicated the active tile. |
74 | + item.menu.show(width, y + height / 2 - list.contentY + panel.y + 4) |
75 | } |
76 | |
77 | onClicked: { |
78 | @@ -75,6 +82,7 @@ |
79 | else |
80 | item.menu.hide() |
81 | } |
82 | + |
83 | Connections { |
84 | target: list |
85 | onMovementStarted: item.menu.hide() |
86 | @@ -87,16 +95,17 @@ |
87 | } |
88 | |
89 | ListView.onAdd: SequentialAnimation { |
90 | - PropertyAction { target: wrapper; property: "scale"; value: 0 } |
91 | - NumberAnimation { target: wrapper; property: "height"; from: 0; to: 54; duration: 250; easing.type: Easing.InOutQuad } |
92 | - NumberAnimation { target: wrapper; property: "scale"; to: 1; duration: 250; easing.type: Easing.InOutQuad } |
93 | + PropertyAction { target: launcherItem; property: "scale"; value: 0 } |
94 | + NumberAnimation { target: launcherItem; property: "height"; |
95 | + from: 0; to: launcherItem.tileSize; duration: 250; easing.type: Easing.InOutQuad } |
96 | + NumberAnimation { target: launcherItem; property: "scale"; to: 1; duration: 250; easing.type: Easing.InOutQuad } |
97 | } |
98 | |
99 | ListView.onRemove: SequentialAnimation { |
100 | - PropertyAction { target: wrapper; property: "ListView.delayRemove"; value: true } |
101 | - NumberAnimation { target: wrapper; property: "scale"; to: 0; duration: 250; easing.type: Easing.InOutQuad } |
102 | - NumberAnimation { target: wrapper; property: "height"; to: 0; duration: 250; easing.type: Easing.InOutQuad } |
103 | - PropertyAction { target: wrapper; property: "ListView.delayRemove"; value: false } |
104 | + PropertyAction { target: launcherItem; property: "ListView.delayRemove"; value: true } |
105 | + NumberAnimation { target: launcherItem; property: "scale"; to: 0; duration: 250; easing.type: Easing.InOutQuad } |
106 | + NumberAnimation { target: launcherItem; property: "height"; to: 0; duration: 250; easing.type: Easing.InOutQuad } |
107 | + PropertyAction { target: launcherItem; property: "ListView.delayRemove"; value: false } |
108 | } |
109 | |
110 | onRunningChanged: setIconGeometry() |
111 | |
112 | === modified file 'launcher/LauncherItem.qml' |
113 | --- launcher/LauncherItem.qml 2011-01-17 19:17:00 +0000 |
114 | +++ launcher/LauncherItem.qml 2011-02-15 13:21:38 +0000 |
115 | @@ -1,201 +1,214 @@ |
116 | import Qt 4.7 |
117 | - |
118 | -/* Item displaying a launcher item. |
119 | - |
120 | - It contains: |
121 | - - a generic bordered background image |
122 | - - an icon representing the item |
123 | - - a text describing the item |
124 | - |
125 | - When an application is launched, the border changes appearance. |
126 | - It supports mouse hover by changing the appearance of the background image. |
127 | - |
128 | - The 'icon' property holds the source of the image to load as an icon. |
129 | - The 'label' property holds the text to display. |
130 | - The 'running' property is a boolean indicating whether or not the |
131 | - application is launched. |
132 | - |
133 | - The 'clicked' signal is emitted upon clicking on the item. |
134 | +import Unity2d 1.0 |
135 | + |
136 | +/* This component represents a single "tile" in the launcher and the surrounding |
137 | + indicator icons. |
138 | + |
139 | + The tile is square in size, with a side determined by the 'tileSize' property, |
140 | + and rounded borders. |
141 | + It is composed by a colored background layer, an icon (with 'icon' as source), |
142 | + and a layer on top that provides a "shine" effect. |
143 | + The main color of the background layer may be calculated based on the icon color |
144 | + or may be fixed (depending on the 'backgroundFromIcon' property). |
145 | + |
146 | + There's also an additional layer which contains only the outline of the tile |
147 | + that is only appearing during the launching animation (when the 'launching' property is |
148 | + true). During this animation the background fades out and the outline fades in, |
149 | + giving a "pulsing" appearance to the tile. |
150 | + |
151 | + Around the tile we may have on the left a number of "pips" between zero and three. |
152 | + Pips are small icons used to indicate how many windows we have open for the current tile |
153 | + (based on the 'windowCount' property). |
154 | + The rule is: if there's only one window, we just display an arrow. If there are |
155 | + two we display 2 pips, if there are 3 or more display 3 pips. |
156 | + |
157 | + On the right of the tile there's an arrow that appears if the tile is currently 'active'. |
158 | + |
159 | + Additionally, when the tile is marked as 'urgent' it will start an animation where the |
160 | + rotation is changed so that it appears to be "shaking". |
161 | */ |
162 | Item { |
163 | - id: launcherItem |
164 | + id: item |
165 | + anchors.horizontalCenter: parent.horizontalCenter |
166 | |
167 | + property int tileSize |
168 | property alias icon: icon.source |
169 | - property alias label: label.text |
170 | property bool running: false |
171 | property bool active: false |
172 | property bool urgent: false |
173 | property bool launching: false |
174 | + property bool backgroundFromIcon |
175 | + property color defaultBackgroundColor: "#333333" |
176 | + |
177 | + property int pips: 0 |
178 | + property string pipSource: engineBaseUrl + "artwork/launcher_" + |
179 | + ((pips <= 1) ? "arrow" : "pip") + "_ltr.png" |
180 | + function getPipOffset(index) { |
181 | + /* Pips need to always be centered, regardless if they are an even or odd |
182 | + number. The following simple conditional code works and is less |
183 | + convoluted than a generic formula. It's ok since we always work with at |
184 | + most three pips anyway. */ |
185 | + if (pips == 1) return 0; |
186 | + if (pips == 2) return (index == 0) ? -2 : +2 |
187 | + else return (index == 0) ? 0 : (index == 1) ? -4 : +4 |
188 | + } |
189 | |
190 | signal clicked(variant mouse) |
191 | signal entered |
192 | signal exited |
193 | |
194 | - Keys.onPressed: { |
195 | - if (event.key == Qt.Key_Return) { |
196 | - clicked() |
197 | - event.accepted = true; |
198 | - } |
199 | - } |
200 | - |
201 | - Image { |
202 | - id: shadow |
203 | - |
204 | - source: "artwork/shadow.png" |
205 | - asynchronous: true |
206 | - } |
207 | - |
208 | - Image { |
209 | - id: glow |
210 | - |
211 | - anchors.horizontalCenter: parent.horizontalCenter |
212 | + /* This is the arrow shown at the right of the tile when the application is |
213 | + the active one */ |
214 | + Image { |
215 | + anchors.right: parent.right |
216 | anchors.verticalCenter: parent.verticalCenter |
217 | - |
218 | - source: "artwork/glow.png" |
219 | - asynchronous: true |
220 | - opacity: 0.0 |
221 | - |
222 | - SequentialAnimation on opacity { |
223 | - loops: Animation.Infinite |
224 | - alwaysRunToEnd: true |
225 | - running: launching |
226 | - NumberAnimation { to: 1.0; duration: 1000; easing.type: Easing.InOutQuad } |
227 | - NumberAnimation { to: 0.0; duration: 1000; easing.type: Easing.InOutQuad } |
228 | + source: "image://blended/%1color=%2alpha=%3" |
229 | + .arg(engineBaseUrl + "artwork/launcher_arrow_rtl.png") |
230 | + .arg("lightgrey") |
231 | + .arg(1.0) |
232 | + |
233 | + /* This extra shift is necessary (as is for the pips below) |
234 | + since we are vertically centering in a parent with even height, so |
235 | + there's one pixel offset that need to be assigned arbitrarily. |
236 | + Unity chose to add it, QML to subtract it. So we adjust for that. */ |
237 | + transform: Translate { y: 1 } |
238 | + |
239 | + visible: active |
240 | + } |
241 | + |
242 | + /* This is the area on the left of the tile where the pips/arrow end up. |
243 | + |
244 | + I'd rather use a Column here, but the pip images have an halo |
245 | + around them, so they are pretty tall and would mess up the column. |
246 | + As a workaround I center all of them, then shift up or down |
247 | + depending on the index. */ |
248 | + Repeater { |
249 | + model: item.pips |
250 | + delegate: Image { |
251 | + /* FIXME: It seems that when the image is created (or re-used) by the Repeater |
252 | + for a moment it doesn't have any parent, and therefore warnings are |
253 | + printed for the following two anchor assignements. This fixes the |
254 | + problem, but I'm not sure if it should happen in the first place. */ |
255 | + anchors.left: (parent) ? parent.left : undefined |
256 | + anchors.verticalCenter: (parent) ? parent.verticalCenter : undefined |
257 | + |
258 | + source: "image://blended/%1color=%2alpha=%3" |
259 | + .arg(pipSource).arg("lightgrey").arg(1.0) |
260 | + |
261 | + transform: Translate { y: getPipOffset(index) + 1 } |
262 | } |
263 | } |
264 | |
265 | + /* This is the for centering the actual tile in the launcher */ |
266 | Item { |
267 | - id: container |
268 | - |
269 | - width: 50 |
270 | - height: 50 |
271 | - anchors.horizontalCenter: parent.horizontalCenter |
272 | - anchors.verticalCenter: parent.verticalCenter |
273 | - |
274 | - MouseArea { |
275 | - id: mouse |
276 | - |
277 | - acceptedButtons: Qt.LeftButton | Qt.RightButton |
278 | - hoverEnabled: true |
279 | - anchors.fill: parent |
280 | - onClicked: launcherItem.clicked(mouse) |
281 | - onEntered: launcherItem.entered() |
282 | - onExited: launcherItem.exited() |
283 | - } |
284 | - |
285 | - Rectangle { |
286 | - id: background |
287 | - |
288 | - opacity: mouse.containsMouse ? 1.0 : 0.9 |
289 | - anchors.fill: parent |
290 | - anchors.margins: 1 |
291 | - anchors.horizontalCenter: parent.horizontalCenter |
292 | - anchors.verticalCenter: parent.verticalCenter |
293 | - smooth: true |
294 | - color: if(icon.source != "") |
295 | - return launcherView.iconAverageColor(icon.source, |
296 | - Qt.size(icon.width, icon.height)) |
297 | - radius: 5 |
298 | - } |
299 | - |
300 | + id: tile |
301 | + anchors.centerIn: parent |
302 | + width: item.tileSize |
303 | + height: parent.height |
304 | + |
305 | + /* This is the image providing the background image. The |
306 | + color blended with this image is obtained from the color of the icon when it's |
307 | + loaded. |
308 | + While the application is launching, this will fade out and in. */ |
309 | + Image { |
310 | + id: tileBackground |
311 | + property color color: defaultBackgroundColor |
312 | + anchors.fill: parent |
313 | + |
314 | + SequentialAnimation on opacity { |
315 | + NumberAnimation { to: 0.0; duration: 1000; easing.type: Easing.InOutQuad } |
316 | + NumberAnimation { to: 1.0; duration: 1000; easing.type: Easing.InOutQuad } |
317 | + |
318 | + loops: Animation.Infinite |
319 | + alwaysRunToEnd: true |
320 | + running: launching |
321 | + } |
322 | + |
323 | + sourceSize.width: item.tileSize |
324 | + sourceSize.height: item.tileSize |
325 | + source: "image://blended/%1color=%2alpha=%3" |
326 | + .arg(engineBaseUrl + "artwork/round_corner_54x54.png") |
327 | + .arg(color.toString().replace("#", "")) |
328 | + .arg(1.0) |
329 | + } |
330 | + |
331 | + /* This image appears only while launching, and pulses in and out in counterpoint |
332 | + to the background, so that the outline of the tile is always visible. */ |
333 | + Image { |
334 | + id: tileOutline |
335 | + anchors.fill: parent |
336 | + |
337 | + sourceSize.width: item.tileSize |
338 | + sourceSize.height: item.tileSize |
339 | + source: "artwork/round_outline_54x54.png" |
340 | + |
341 | + opacity: 0 |
342 | + |
343 | + SequentialAnimation on opacity { |
344 | + NumberAnimation { to: 1.0; duration: 1000; easing.type: Easing.InOutQuad } |
345 | + NumberAnimation { to: 0.0; duration: 1000; easing.type: Easing.InOutQuad } |
346 | + |
347 | + loops: Animation.Infinite |
348 | + alwaysRunToEnd: true |
349 | + running: launching |
350 | + } |
351 | + } |
352 | + |
353 | + /* This is just the main icon of the tile */ |
354 | Image { |
355 | id: icon |
356 | - |
357 | - width: 32 |
358 | - height: 32 |
359 | - anchors.horizontalCenter: parent.horizontalCenter |
360 | - anchors.verticalCenter: parent.verticalCenter |
361 | - fillMode: Image.PreserveAspectFit |
362 | - sourceSize.width: width |
363 | - sourceSize.height: height |
364 | - smooth: true |
365 | - |
366 | - asynchronous: true |
367 | - opacity: status == Image.Ready ? 1 : 0 |
368 | - Behavior on opacity {NumberAnimation {duration: 200; easing.type: Easing.InOutQuad}} |
369 | + anchors.centerIn: parent |
370 | + |
371 | + sourceSize.width: 48 |
372 | + sourceSize.height: 48 |
373 | + |
374 | + /* Whenever one of the parameters used in calculating the background color of |
375 | + the icon changes, recalculate its value */ |
376 | + onWidthChanged: updateColors() |
377 | + onHeightChanged: updateColors() |
378 | + onSourceChanged: updateColors() |
379 | + |
380 | + function updateColors() { |
381 | + if (!item.backgroundFromIcon) return; |
382 | + |
383 | + var colors = launcherView.getColorsFromIcon(icon.source, icon.sourceSize) |
384 | + if (colors && colors.length > 0) tileBackground.color = colors[0] |
385 | + } |
386 | } |
387 | |
388 | + /* This just adds some shiny effect to the tile */ |
389 | Image { |
390 | - id: foreground |
391 | - |
392 | + id: tileShine |
393 | anchors.fill: parent |
394 | - anchors.horizontalCenter: parent.horizontalCenter |
395 | - anchors.verticalCenter: parent.verticalCenter |
396 | - fillMode: Image.PreserveAspectFit |
397 | - sourceSize.width: width |
398 | - sourceSize.height: height |
399 | - smooth: true |
400 | - |
401 | - source: "/usr/share/unity/themes/prism_icon_foreground.png" |
402 | - |
403 | - asynchronous: true |
404 | - opacity: status == Image.Ready ? 1 : 0 |
405 | - Behavior on opacity {NumberAnimation {duration: 200; easing.type: Easing.InOutQuad}} |
406 | + |
407 | + source: "artwork/round_shine_54x54.png" |
408 | + sourceSize.width: item.tileSize |
409 | + sourceSize.height: item.tileSize |
410 | } |
411 | |
412 | + /* The entire tile will "shake" when the window is marked as "urgent", to attract |
413 | + the user's attention */ |
414 | SequentialAnimation { |
415 | - id: nudging |
416 | running: urgent |
417 | + alwaysRunToEnd: true |
418 | + |
419 | SequentialAnimation { |
420 | loops: 30 |
421 | - NumberAnimation { target: container; property: "rotation"; to: 15; duration: 150 } |
422 | - NumberAnimation { target: container; property: "rotation"; to: -15; duration: 150 } |
423 | + NumberAnimation { target: tile; property: "rotation"; to: 15; duration: 150 } |
424 | + NumberAnimation { target: tile; property: "rotation"; to: -15; duration: 150 } |
425 | } |
426 | - NumberAnimation { target: container; property: "rotation"; to: 0; duration: 75 } |
427 | - } |
428 | - |
429 | - NumberAnimation { |
430 | - id: end_nudging |
431 | - running: !urgent |
432 | - target: container |
433 | - property: "rotation" |
434 | - to: 0 |
435 | - duration: 75 |
436 | - } |
437 | - |
438 | - } |
439 | - |
440 | - Image { |
441 | - id: running_arrow |
442 | - |
443 | - z: -1 |
444 | - width: sourceSize.width |
445 | - height: sourceSize.height |
446 | - anchors.rightMargin: -2 |
447 | - anchors.right: container.left |
448 | - anchors.verticalCenter: container.verticalCenter |
449 | - opacity: running ? 1.0 : 0.0 |
450 | - source: urgent ? "/usr/share/unity/themes/application-running-notify.png" : "/usr/share/unity/themes/application-running.png" |
451 | - |
452 | - Behavior on opacity {NumberAnimation {duration: 200; easing.type: Easing.InOutQuad}} |
453 | - } |
454 | - |
455 | - Image { |
456 | - id: active_arrow |
457 | - |
458 | - z: -1 |
459 | - width: sourceSize.width |
460 | - height: sourceSize.height |
461 | - anchors.leftMargin: -2 |
462 | - anchors.left: container.right |
463 | - anchors.verticalCenter: container.verticalCenter |
464 | - opacity: active ? 1.0 : 0.0 |
465 | - source: "/usr/share/unity/themes/application-selected.png" |
466 | - |
467 | - Behavior on opacity {NumberAnimation {duration: 200; easing.type: Easing.InOutQuad}} |
468 | - } |
469 | - |
470 | - Text { |
471 | - id: label |
472 | - |
473 | - font.pointSize: 10 |
474 | - wrapMode: Text.WordWrap |
475 | - horizontalAlignment: Text.AlignHCenter |
476 | - anchors.top: parent.bottom |
477 | - anchors.topMargin: 7 |
478 | - anchors.right: parent.right |
479 | - anchors.bottom: parent.bottom |
480 | - anchors.left: parent.left |
481 | - font.underline: parent.focus |
482 | + NumberAnimation { target: tile; property: "rotation"; to: 0; duration: 75 } |
483 | + } |
484 | + } |
485 | + |
486 | + MouseArea { |
487 | + id: mouse |
488 | + anchors.fill: parent |
489 | + |
490 | + hoverEnabled: true |
491 | + acceptedButtons: Qt.LeftButton | Qt.RightButton |
492 | + onClicked: item.clicked(mouse) |
493 | + onEntered: item.entered() |
494 | + onExited: item.exited() |
495 | } |
496 | } |
497 | |
498 | === modified file 'launcher/UnityApplications/iconimageprovider.cpp' |
499 | --- launcher/UnityApplications/iconimageprovider.cpp 2011-01-15 01:41:03 +0000 |
500 | +++ launcher/UnityApplications/iconimageprovider.cpp 2011-02-15 13:21:38 +0000 |
501 | @@ -21,6 +21,7 @@ |
502 | #include "config.h" |
503 | |
504 | #include <QFile> |
505 | +#include <QDebug> |
506 | |
507 | |
508 | static const char* UNITY_RES_PATH = "/usr/share/unity/"; |
509 | @@ -46,25 +47,34 @@ |
510 | to do so was a failure due to the fragility of the code path. For example |
511 | it is very easy to break the entire mechanism by adding or forgetting a |
512 | slash in any of the paths. */ |
513 | - if (id.startsWith(UNITY_RES_PATH)) |
514 | - { |
515 | - if (QFile::exists(id)) |
516 | - { |
517 | - return QImage(id); |
518 | - } |
519 | - else |
520 | - { |
521 | - QString rid(id); |
522 | - rid.replace(UNITY_RES_PATH, INSTALL_PREFIX "/share/unity-2d/"); |
523 | - /* No need to check whether the file exists, we don’t have a |
524 | - fallback anyway. */ |
525 | - return QImage(rid); |
526 | - } |
527 | - } |
528 | - |
529 | - /* Dealing with case where id is an absolute path to the icon file */ |
530 | - if(id.startsWith("/")) |
531 | - return QImage(id); |
532 | + QString iconFilePath; |
533 | + if (id.startsWith(UNITY_RES_PATH)) { |
534 | + iconFilePath = id; |
535 | + if (!QFile::exists(iconFilePath)) { |
536 | + iconFilePath.replace(UNITY_RES_PATH, INSTALL_PREFIX "/share/unity-2d/"); |
537 | + } |
538 | + } else if (id.startsWith("/")) { |
539 | + iconFilePath = id; |
540 | + } |
541 | + |
542 | + /* We have a direct path to the icon file. Let's load it, scale it if required and |
543 | + we are done */ |
544 | + if (!iconFilePath.isEmpty()) { |
545 | + QImage icon(iconFilePath); |
546 | + if (icon.isNull()) { |
547 | + qWarning() << "Failed to directly load icon at path:" << iconFilePath; |
548 | + return QImage(); |
549 | + } |
550 | + |
551 | + if (requestedSize.isValid()) { |
552 | + icon = icon.scaled(requestedSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); |
553 | + } |
554 | + |
555 | + if (size) { |
556 | + *size = icon.size(); |
557 | + } |
558 | + return icon; |
559 | + } |
560 | |
561 | /* if id is of the form theme_name/icon_name then lookup the icon in the |
562 | specified theme otherwise in the default theme */ |
563 | |
564 | === modified file 'launcher/UnityApplications/launcherapplication.cpp' |
565 | --- launcher/UnityApplications/launcherapplication.cpp 2011-02-10 08:24:27 +0000 |
566 | +++ launcher/UnityApplications/launcherapplication.cpp 2011-02-15 13:21:38 +0000 |
567 | @@ -109,6 +109,16 @@ |
568 | return false; |
569 | } |
570 | |
571 | +int |
572 | +LauncherApplication::windowCount() const |
573 | +{ |
574 | + if (m_application == NULL) { |
575 | + return 0; |
576 | + } |
577 | + |
578 | + return m_application->windows()->size(); |
579 | +} |
580 | + |
581 | bool |
582 | LauncherApplication::urgent() const |
583 | { |
584 | @@ -297,6 +307,8 @@ |
585 | QObject::connect(application, SIGNAL(UrgentChanged(bool)), this, SIGNAL(urgentChanged(bool))); |
586 | QObject::connect(application, SIGNAL(WindowAdded(BamfWindow*)), this, SLOT(updateHasVisibleWindow())); |
587 | QObject::connect(application, SIGNAL(WindowRemoved(BamfWindow*)), this, SLOT(updateHasVisibleWindow())); |
588 | + QObject::connect(application, SIGNAL(WindowAdded(BamfWindow*)), this, SLOT(updateWindowCount())); |
589 | + QObject::connect(application, SIGNAL(WindowRemoved(BamfWindow*)), this, SLOT(updateWindowCount())); |
590 | connect(application, SIGNAL(ChildAdded(BamfView*)), SLOT(slotChildAdded(BamfView*))); |
591 | connect(application, SIGNAL(ChildRemoved(BamfView*)), SLOT(slotChildRemoved(BamfView*))); |
592 | |
593 | @@ -318,6 +330,7 @@ |
594 | m_launching_timer.stop(); |
595 | emit launchingChanged(launching()); |
596 | updateHasVisibleWindow(); |
597 | + updateWindowCount(); |
598 | fetchIndicatorMenus(); |
599 | } |
600 | |
601 | @@ -396,6 +409,12 @@ |
602 | emit hasVisibleWindowChanged(m_has_visible_window); |
603 | } |
604 | |
605 | +void |
606 | +LauncherApplication::updateWindowCount() |
607 | +{ |
608 | + Q_EMIT windowCountChanged(windowCount()); |
609 | +} |
610 | + |
611 | bool |
612 | LauncherApplication::has_visible_window() const |
613 | { |
614 | |
615 | === modified file 'launcher/UnityApplications/launcherapplication.h' |
616 | --- launcher/UnityApplications/launcherapplication.h 2011-02-10 08:24:27 +0000 |
617 | +++ launcher/UnityApplications/launcherapplication.h 2011-02-15 13:21:38 +0000 |
618 | @@ -52,6 +52,7 @@ |
619 | /* getters */ |
620 | virtual bool active() const; |
621 | virtual bool running() const; |
622 | + virtual int windowCount() const; |
623 | virtual bool urgent() const; |
624 | bool sticky() const; |
625 | virtual QString name() const; |
626 | @@ -93,6 +94,7 @@ |
627 | void onBamfApplicationClosed(bool running); |
628 | void onLaunchingTimeouted(); |
629 | void updateHasVisibleWindow(); |
630 | + void updateWindowCount(); |
631 | |
632 | bool launch(); |
633 | void show(); |
634 | |
635 | === modified file 'launcher/UnityApplications/launcherdevice.cpp' |
636 | --- launcher/UnityApplications/launcherdevice.cpp 2011-01-14 20:41:34 +0000 |
637 | +++ launcher/UnityApplications/launcherdevice.cpp 2011-02-15 13:21:38 +0000 |
638 | @@ -54,6 +54,12 @@ |
639 | return false; |
640 | } |
641 | |
642 | +int |
643 | +LauncherDevice::windowCount() const |
644 | +{ |
645 | + return 0; |
646 | +} |
647 | + |
648 | bool |
649 | LauncherDevice::urgent() const |
650 | { |
651 | |
652 | === modified file 'launcher/UnityApplications/launcherdevice.h' |
653 | --- launcher/UnityApplications/launcherdevice.h 2010-11-04 19:50:22 +0000 |
654 | +++ launcher/UnityApplications/launcherdevice.h 2011-02-15 13:21:38 +0000 |
655 | @@ -40,6 +40,7 @@ |
656 | /* getters */ |
657 | virtual bool active() const; |
658 | virtual bool running() const; |
659 | + virtual int windowCount() const; |
660 | virtual bool urgent() const; |
661 | virtual QString name() const; |
662 | virtual QString icon() const; |
663 | |
664 | === modified file 'launcher/UnityApplications/launcheritem.h' |
665 | --- launcher/UnityApplications/launcheritem.h 2010-12-16 11:07:52 +0000 |
666 | +++ launcher/UnityApplications/launcheritem.h 2011-02-15 13:21:38 +0000 |
667 | @@ -31,6 +31,7 @@ |
668 | |
669 | Q_PROPERTY(bool active READ active NOTIFY activeChanged) |
670 | Q_PROPERTY(bool running READ running NOTIFY runningChanged) |
671 | + Q_PROPERTY(int windowCount READ windowCount NOTIFY windowCountChanged) |
672 | Q_PROPERTY(bool urgent READ urgent NOTIFY urgentChanged) |
673 | Q_PROPERTY(QString name READ name NOTIFY nameChanged) |
674 | Q_PROPERTY(QString icon READ icon NOTIFY iconChanged) |
675 | @@ -45,6 +46,7 @@ |
676 | /* getters */ |
677 | virtual bool active() const = 0; |
678 | virtual bool running() const = 0; |
679 | + virtual int windowCount() const = 0; |
680 | virtual bool urgent() const = 0; |
681 | virtual QString name() const = 0; |
682 | virtual QString icon() const = 0; |
683 | @@ -61,6 +63,7 @@ |
684 | signals: |
685 | void activeChanged(bool); |
686 | void runningChanged(bool); |
687 | + void windowCountChanged(int); |
688 | void urgentChanged(bool); |
689 | void nameChanged(QString); |
690 | void iconChanged(QString); |
691 | |
692 | === modified file 'launcher/UnityApplications/placeentry.cpp' |
693 | --- launcher/UnityApplications/placeentry.cpp 2011-02-07 15:41:35 +0000 |
694 | +++ launcher/UnityApplications/placeentry.cpp 2011-02-15 13:21:38 +0000 |
695 | @@ -234,6 +234,12 @@ |
696 | return false; |
697 | } |
698 | |
699 | +int |
700 | +PlaceEntry::windowCount() const |
701 | +{ |
702 | + return 0; |
703 | +} |
704 | + |
705 | bool |
706 | PlaceEntry::urgent() const |
707 | { |
708 | |
709 | === modified file 'launcher/UnityApplications/placeentry.h' |
710 | --- launcher/UnityApplications/placeentry.h 2011-02-01 18:03:11 +0000 |
711 | +++ launcher/UnityApplications/placeentry.h 2011-02-15 13:21:38 +0000 |
712 | @@ -109,6 +109,7 @@ |
713 | /* getters */ |
714 | virtual bool active() const; |
715 | virtual bool running() const; |
716 | + virtual int windowCount() const; |
717 | virtual bool urgent() const; |
718 | virtual QString name() const; |
719 | virtual QString icon() const; |
720 | |
721 | === modified file 'launcher/UnityApplications/trash.cpp' |
722 | --- launcher/UnityApplications/trash.cpp 2011-01-14 20:41:34 +0000 |
723 | +++ launcher/UnityApplications/trash.cpp 2011-02-15 13:21:38 +0000 |
724 | @@ -53,6 +53,12 @@ |
725 | return false; |
726 | } |
727 | |
728 | +int |
729 | +Trash::windowCount() const |
730 | +{ |
731 | + return 0; |
732 | +} |
733 | + |
734 | bool |
735 | Trash::urgent() const |
736 | { |
737 | @@ -68,7 +74,7 @@ |
738 | QString |
739 | Trash::icon() const |
740 | { |
741 | - return QString(unity2dDirectory() + "/launcher/artwork/trash.png"); |
742 | + return "user-trash"; |
743 | } |
744 | |
745 | bool |
746 | |
747 | === modified file 'launcher/UnityApplications/trash.h' |
748 | --- launcher/UnityApplications/trash.h 2010-11-09 10:52:04 +0000 |
749 | +++ launcher/UnityApplications/trash.h 2011-02-15 13:21:38 +0000 |
750 | @@ -39,6 +39,7 @@ |
751 | /* getters */ |
752 | virtual bool active() const; |
753 | virtual bool running() const; |
754 | + virtual int windowCount() const; |
755 | virtual bool urgent() const; |
756 | virtual QString name() const; |
757 | virtual QString icon() const; |
758 | |
759 | === modified file 'launcher/UnityApplications/workspaces.cpp' |
760 | --- launcher/UnityApplications/workspaces.cpp 2011-02-03 20:31:40 +0000 |
761 | +++ launcher/UnityApplications/workspaces.cpp 2011-02-15 13:21:38 +0000 |
762 | @@ -48,6 +48,12 @@ |
763 | return false; |
764 | } |
765 | |
766 | +int |
767 | +Workspaces::windowCount() const |
768 | +{ |
769 | + return 0; |
770 | +} |
771 | + |
772 | bool |
773 | Workspaces::urgent() const |
774 | { |
775 | |
776 | === modified file 'launcher/UnityApplications/workspaces.h' |
777 | --- launcher/UnityApplications/workspaces.h 2011-02-02 22:45:59 +0000 |
778 | +++ launcher/UnityApplications/workspaces.h 2011-02-15 13:21:38 +0000 |
779 | @@ -39,6 +39,7 @@ |
780 | /* getters */ |
781 | virtual bool active() const; |
782 | virtual bool running() const; |
783 | + virtual int windowCount() const; |
784 | virtual bool urgent() const; |
785 | virtual QString name() const; |
786 | virtual QString icon() const; |
787 | |
788 | === modified file 'launcher/app/launcher.cpp' |
789 | --- launcher/app/launcher.cpp 2011-02-08 10:41:55 +0000 |
790 | +++ launcher/app/launcher.cpp 2011-02-15 13:21:38 +0000 |
791 | @@ -64,7 +64,7 @@ |
792 | /* Panel containing the QML declarative view */ |
793 | Unity2dPanel panel; |
794 | panel.setEdge(Unity2dPanel::LeftEdge); |
795 | - panel.setFixedWidth(58); |
796 | + panel.setFixedWidth(66); |
797 | |
798 | /* QML declarative view */ |
799 | LauncherView *launcherView = new LauncherView; |
800 | @@ -79,10 +79,17 @@ |
801 | /* Note: baseUrl seems to be picky: if it does not end with a slash, |
802 | setSource() will fail */ |
803 | launcherView->engine()->setBaseUrl(QUrl::fromLocalFile(unity2dDirectory() + "/launcher/")); |
804 | + if (!isRunningInstalled()) { |
805 | + launcherView->engine()->addImportPath(unity2dDirectory() + "/libunity-2d-private/"); |
806 | + } |
807 | |
808 | launcherView->rootContext()->setContextProperty("launcherView", launcherView); |
809 | launcherView->rootContext()->setContextProperty("panel", &panel); |
810 | |
811 | + /* FIXME: this is needed since the blended image provider doesn't support relative paths yet */ |
812 | + launcherView->rootContext()->setContextProperty("engineBaseUrl", |
813 | + launcherView->engine()->baseUrl().toLocalFile()); |
814 | + |
815 | LauncherControl control; |
816 | launcherView->rootContext()->setContextProperty("launcherControl", &control); |
817 | control.connectToBus(); |
818 | |
819 | === modified file 'launcher/app/launcherview.cpp' |
820 | --- launcher/app/launcherview.cpp 2011-02-07 17:21:35 +0000 |
821 | +++ launcher/app/launcherview.cpp 2011-02-15 13:21:38 +0000 |
822 | @@ -110,65 +110,53 @@ |
823 | if (accepted) event->accept(); |
824 | } |
825 | |
826 | -QColor |
827 | -LauncherView::iconAverageColor(QUrl source, QSize size) |
828 | +/* Calculates both the background color and the glow color of a launcher tile |
829 | + based on the colors in the specified icon (using the same algorithm as Unity). |
830 | + The values are returned as list where the first item is the background color |
831 | + and the second one is the glow color. |
832 | +*/ |
833 | +QList<QVariant> |
834 | +LauncherView::getColorsFromIcon(QUrl source, QSize size) const |
835 | { |
836 | - /* FIXME: we are loading again an icon that was already loaded */ |
837 | + QList<QVariant> colors; |
838 | + |
839 | + // FIXME: we should find a way to avoid reloading the icon |
840 | QImage icon = engine()->imageProvider("icons")->requestImage(source.path().mid(1), &size, size); |
841 | - |
842 | - if (icon.width() == 0 || icon.height() == 0) |
843 | - { |
844 | - qWarning() << "Unable to load icon at" << source; |
845 | - return QColor(); |
846 | + if (icon.width() == 0 || icon.height() == 0) { |
847 | + qWarning() << "Unable to load icon in getColorsFromIcon from" << source; |
848 | + return colors; |
849 | } |
850 | |
851 | - int total_r = 0, total_g = 0, total_b = 0; |
852 | - int select_r = 0, select_g = 0, select_b = 0; |
853 | - int selected_pixels = 0; |
854 | + long int rtotal = 0, gtotal = 0, btotal = 0; |
855 | + float total = 0.0f; |
856 | |
857 | - for (int y=0; y<icon.height(); ++y) |
858 | - { |
859 | - for (int x=0; x<icon.width(); ++x) |
860 | - { |
861 | + for (int y = 0; y < icon.height(); ++y) { |
862 | + for (int x = 0; x < icon.width(); ++x) { |
863 | QColor color = QColor::fromRgba(icon.pixel(x, y)); |
864 | |
865 | - if (color.alphaF() < 0.5) |
866 | - continue; |
867 | - |
868 | - total_r += color.red(); |
869 | - total_g += color.green(); |
870 | - total_b += color.blue(); |
871 | - |
872 | - if (color.saturationF() <= 0.33) |
873 | - continue; |
874 | - |
875 | - select_r += color.red(); |
876 | - select_g += color.green(); |
877 | - select_b += color.blue(); |
878 | - |
879 | - selected_pixels++; |
880 | + float saturation = (qMax (color.red(), qMax (color.green(), color.blue())) - |
881 | + qMin (color.red(), qMin (color.green(), color.blue()))) / 255.0f; |
882 | + float relevance = .1 + .9 * (color.alpha() / 255.0f) * saturation; |
883 | + |
884 | + rtotal += (unsigned char) (color.red() * relevance); |
885 | + gtotal += (unsigned char) (color.green() * relevance); |
886 | + btotal += (unsigned char) (color.blue() * relevance); |
887 | + |
888 | + total += relevance * 255; |
889 | } |
890 | } |
891 | |
892 | - QColor color; |
893 | - |
894 | - if (selected_pixels <= 20) |
895 | - { |
896 | - int total_pixels = icon.width()*icon.height(); |
897 | - color = QColor::fromRgb(total_r/total_pixels, |
898 | - total_g/total_pixels, |
899 | - total_b/total_pixels); |
900 | - color.setHsv(color.hue(), 0, color.value()); |
901 | - } |
902 | - else |
903 | - { |
904 | - color = QColor::fromRgb(select_r/selected_pixels, |
905 | - select_g/selected_pixels, |
906 | - select_b/selected_pixels); |
907 | - float saturation = qMin(color.saturationF()*0.7, 1.0); |
908 | - float value = qMin(color.valueF()*1.4, 1.0); |
909 | - color.setHsvF(color.hueF(), saturation, value); |
910 | - } |
911 | - |
912 | - return color; |
913 | + QColor hsv = QColor::fromRgbF(rtotal / total, gtotal / total, btotal / total).toHsv(); |
914 | + |
915 | + /* Background color is the base color with 0.90f HSV value */ |
916 | + hsv.setHsvF(hsv.hueF(), |
917 | + (hsv.saturationF() > .15f) ? 0.65f : hsv.saturationF(), |
918 | + 0.90f); |
919 | + colors.append(QVariant::fromValue(hsv.toRgb())); |
920 | + |
921 | + /* Glow color is the base color with 1.0f HSV value */ |
922 | + hsv.setHsvF(hsv.hueF(), hsv.saturationF(), 1.0f); |
923 | + colors.append(QVariant::fromValue(hsv.toRgb())); |
924 | + |
925 | + return colors; |
926 | } |
927 | |
928 | === modified file 'launcher/app/launcherview.h' |
929 | --- launcher/app/launcherview.h 2011-02-07 17:21:35 +0000 |
930 | +++ launcher/app/launcherview.h 2011-02-15 13:21:38 +0000 |
931 | @@ -23,6 +23,7 @@ |
932 | #include <QDeclarativeView> |
933 | #include <QUrl> |
934 | #include <QDragEnterEvent> |
935 | +#include <QList> |
936 | |
937 | class LauncherView : public QDeclarativeView |
938 | { |
939 | @@ -30,7 +31,7 @@ |
940 | |
941 | public: |
942 | explicit LauncherView(); |
943 | - Q_INVOKABLE QColor iconAverageColor(QUrl source, QSize size); |
944 | + Q_INVOKABLE QList<QVariant> getColorsFromIcon(QUrl source, QSize size) const; |
945 | |
946 | signals: |
947 | void desktopFileDropped(QString path); |
948 | |
949 | === added file 'launcher/artwork/background.png' |
950 | Binary files launcher/artwork/background.png 1970-01-01 00:00:00 +0000 and launcher/artwork/background.png 2011-02-15 13:21:38 +0000 differ |
951 | === removed file 'launcher/artwork/glow.png' |
952 | Binary files launcher/artwork/glow.png 2011-01-28 14:43:29 +0000 and launcher/artwork/glow.png 1970-01-01 00:00:00 +0000 differ |
953 | === added file 'launcher/artwork/launcher_arrow_ltr.png' |
954 | Binary files launcher/artwork/launcher_arrow_ltr.png 1970-01-01 00:00:00 +0000 and launcher/artwork/launcher_arrow_ltr.png 2011-02-15 13:21:38 +0000 differ |
955 | === added file 'launcher/artwork/launcher_arrow_rtl.png' |
956 | Binary files launcher/artwork/launcher_arrow_rtl.png 1970-01-01 00:00:00 +0000 and launcher/artwork/launcher_arrow_rtl.png 2011-02-15 13:21:38 +0000 differ |
957 | === added file 'launcher/artwork/launcher_pip_ltr.png' |
958 | Binary files launcher/artwork/launcher_pip_ltr.png 1970-01-01 00:00:00 +0000 and launcher/artwork/launcher_pip_ltr.png 2011-02-15 13:21:38 +0000 differ |
959 | === added file 'launcher/artwork/round_corner_54x54.png' |
960 | Binary files launcher/artwork/round_corner_54x54.png 1970-01-01 00:00:00 +0000 and launcher/artwork/round_corner_54x54.png 2011-02-15 13:21:38 +0000 differ |
961 | === added file 'launcher/artwork/round_outline_54x54.png' |
962 | Binary files launcher/artwork/round_outline_54x54.png 1970-01-01 00:00:00 +0000 and launcher/artwork/round_outline_54x54.png 2011-02-15 13:21:38 +0000 differ |
963 | === added file 'launcher/artwork/round_shine_54x54.png' |
964 | Binary files launcher/artwork/round_shine_54x54.png 1970-01-01 00:00:00 +0000 and launcher/artwork/round_shine_54x54.png 2011-02-15 13:21:38 +0000 differ |
965 | === removed file 'launcher/artwork/shadow.png' |
966 | Binary files launcher/artwork/shadow.png 2010-09-13 15:52:34 +0000 and launcher/artwork/shadow.png 1970-01-01 00:00:00 +0000 differ |
967 | === removed file 'launcher/artwork/trash.png' |
968 | Binary files launcher/artwork/trash.png 2010-11-09 10:52:04 +0000 and launcher/artwork/trash.png 1970-01-01 00:00:00 +0000 differ |
969 | === modified file 'libunity-2d-private/Unity2d/blendedimageprovider.cpp' |
970 | --- libunity-2d-private/Unity2d/blendedimageprovider.cpp 2011-02-07 15:32:51 +0000 |
971 | +++ libunity-2d-private/Unity2d/blendedimageprovider.cpp 2011-02-15 13:21:38 +0000 |
972 | @@ -16,6 +16,7 @@ |
973 | |
974 | #include "blendedimageprovider.h" |
975 | #include <QPainter> |
976 | +#include <QDebug> |
977 | |
978 | BlendedImageProvider::BlendedImageProvider() : QDeclarativeImageProvider(QDeclarativeImageProvider::Image) |
979 | { |
980 | @@ -28,31 +29,66 @@ |
981 | QImage BlendedImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize) |
982 | { |
983 | /* id is of the form [FILENAME]color=[COLORNAME]alpha=[FLOAT] */ |
984 | - QRegExp rx("(.+)color=(.+)alpha=(\\d+(?:\.\\d+)?)"); |
985 | - rx.indexIn(id); |
986 | + QRegExp rx("^(.+)color=(.+)alpha=(\\d+(?:\\.\\d+)?)$"); |
987 | + if (rx.indexIn(id)) { |
988 | + qWarning() << "BlendedImageProvider: failed to match id:" << id; |
989 | + return QImage(); |
990 | + } |
991 | QStringList list = rx.capturedTexts(); |
992 | - if(list.size() != 4) |
993 | - return QImage(); |
994 | - |
995 | - QString filename = list[1]; |
996 | - QColor color; |
997 | - color.setNamedColor(list[2]); |
998 | - float alpha = list[3].toFloat(); |
999 | + |
1000 | + QString fileName = list[1]; |
1001 | + if (fileName.isEmpty()) { |
1002 | + qWarning() << "BlendedImageProvider: filename can't be empty."; |
1003 | + return QImage(); |
1004 | + } |
1005 | + |
1006 | + QString colorName = list[2]; |
1007 | + if (!QColor::isValidColor(colorName)) { |
1008 | + /* Passing a named color of the form #RRGGBB is impossible |
1009 | + due to the fact that QML Image considers the source an URL and strips any anchor |
1010 | + from the string it passes to this method (i.e. everything after the #). |
1011 | + As a workaround we allow passing the color as RRGGBB and when a sting is not an |
1012 | + SVG color name (e.g. "blue", "yellow" etc.) we try interpreting it as an RRGGBB |
1013 | + color by adding back the #. |
1014 | + */ |
1015 | + colorName.prepend("#"); |
1016 | + if (!QColor::isValidColor(colorName)) { |
1017 | + qWarning() << "BlendedImageProvider: invalid color name:" << list[2]; |
1018 | + return QImage(); |
1019 | + } |
1020 | + } |
1021 | + QColor color(colorName); |
1022 | + |
1023 | + bool valid = false; |
1024 | + float alpha = list[3].toFloat(&valid); |
1025 | + if (!valid) { |
1026 | + qWarning() << "BlendedImageProvider: can't convert alpha to floating point:" << list[3]; |
1027 | + return QImage(); |
1028 | + } |
1029 | color.setAlphaF(alpha); |
1030 | |
1031 | - QImage image(filename); |
1032 | - if(requestedSize.width() == 0 && requestedSize.height() != 0) |
1033 | + QImage image(fileName); |
1034 | + if (image.isNull()) { |
1035 | + qWarning() << "BlendedImageProvider: failed to load image from file:" << fileName; |
1036 | + return QImage(); |
1037 | + } |
1038 | + |
1039 | + if (requestedSize.width() == 0 && requestedSize.height() != 0) { |
1040 | image = image.scaledToHeight(requestedSize.height(), Qt::SmoothTransformation); |
1041 | - else if(requestedSize.width() != 0 && requestedSize.height() == 0) |
1042 | + } else if (requestedSize.width() != 0 && requestedSize.height() == 0) { |
1043 | image = image.scaledToWidth(requestedSize.width(), Qt::SmoothTransformation); |
1044 | - else if(requestedSize.isValid()) |
1045 | + } else if (requestedSize.isValid()) { |
1046 | image = image.scaled(requestedSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); |
1047 | + } |
1048 | |
1049 | - if(size) |
1050 | + if (size) { |
1051 | *size = image.size(); |
1052 | + } |
1053 | |
1054 | + /* We use SourceAtop as the composition mode since we want any area that is fully transparent |
1055 | + in the source image to be fully transparent also in the result. */ |
1056 | QPainter painter(&image); |
1057 | - painter.setCompositionMode(QPainter::CompositionMode_SourceOver); |
1058 | + painter.setCompositionMode(QPainter::CompositionMode_SourceAtop); |
1059 | painter.fillRect(image.rect(), color); |
1060 | painter.end(); |
1061 | |
1062 | |
1063 | === modified file 'panel/applets/homebutton/homebuttonapplet.cpp' |
1064 | --- panel/applets/homebutton/homebuttonapplet.cpp 2011-01-22 03:52:17 +0000 |
1065 | +++ panel/applets/homebutton/homebuttonapplet.cpp 2011-02-15 13:21:38 +0000 |
1066 | @@ -49,7 +49,7 @@ |
1067 | connect(m_button, SIGNAL(clicked()), SLOT(toggleDash())); |
1068 | |
1069 | m_button->setStyleSheet( |
1070 | - "QToolButton { border: none; margin: 0; padding: 0; width: 54 }" |
1071 | + "QToolButton { border: none; margin: 0; padding: 0; width: 61 }" |
1072 | "QToolButton:checked, QToolButton:pressed {" |
1073 | // Use border-image here, not background-image, because bfb_bg_active.png is 56px wide |
1074 | " border-image: url(theme:/bfb_bg_active.png);" |
The launcher width is only 65 pixels in the mockups, not 66.