Package list xapp / upstream/2.0.0
New upstream version 2.0.0 Norbert Preining 10 months ago
41 changed file(s) with 5533 addition(s) and 409 deletion(s). Raw diff Collapse all Expand all
00 # Specify filepatterns you want git to ignore.
11
2 debian/build/
2 obj-x86_64-linux-gnu
33 debian/tmp/
44 debian/*.debhelper
55 debian/gir1.2-xapp-1.0/
55
66 # API Reference
77
8 https://projects.linuxmint.com/xapps/reference/index.html
8 https://projects.linuxmint.com/xapp/reference/index.html
99
1010 # xapp-common
1111
0 # This file is sourced by Xsession(5), not executed.
1
2 if [ -z "$GTK_MODULES" ] ; then
3 GTK_MODULES="xapp-gtk3-module"
4 else
5 GTK_MODULES="$GTK_MODULES:xapp-gtk3-module"
6 fi
7
8 export GTK_MODULES
0 install_data(['80xapp-gtk3-module'],
1 install_dir: join_paths(get_option('sysconfdir'), 'X11', 'Xsession.d')
2 )
0 xapp (2.0.0) ulyssa; urgency=medium
1
2 [ Michael Webster ]
3 * Bump for favorites support
4 * .gitignore: Ignore the new debian build folder.
5 * favorites: expose xapp_favorites_rename (), it was mistakenly made private during some cleanup.
6 * xapp-gtk3-module.c: Don't initialize favorites until they're needed.
7 * xapp-gtk3-module.c: Register the favorites uri scheme immediately, rather than when XAppFavorites is instantiated.
8 * xapp-favorites: Add missing pointer to the DestroyData.
9
10 [ Clement Lefebvre ]
11 * l10n: Update POT
12
13 -- Clement Lefebvre <root@linuxmint.com> Wed, 25 Nov 2020 11:27:06 +0000
14
015 xapp (1.8.9) ulyana; urgency=medium
116
217 [ Michael Webster ]
+0
-1
debian/clean less more
0 debian/build/
+0
-1
debian/compat less more
0 10
22 Priority: optional
33 Maintainer: Clement Lefebvre <root@linuxmint.com>
44 Build-Depends:
5 debhelper (>= 10),
5 debhelper-compat (= 12),
66 dh-python,
77 dpkg-dev (>= 1.15.1),
88 gobject-introspection (>= 0.10.2-1~),
0 usr/lib/*/libxapp.so.1*
0 usr/lib/*/libxapp.so.*
11 usr/libexec/xapps/sn-watcher/*
2 usr/lib/*/gtk-3.0/modules
3 /etc/X11
00 #!/usr/bin/make -f
11
2 # FIXME: much of this can be removed once we move off of xenial/mint 18 base support
3 # meson support is baked in
2 export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed -Wl,-z,now
43
54 %:
65 dh $@ --with=gir,python3
76
87 override_dh_auto_configure:
9 mkdir -p debian/build
10 meson debian/build \
11 --prefix=/usr \
12 --buildtype=plain \
8 dh_auto_configure -- \
9 --libexecdir=/usr/libexec \
1310 -D docs=true \
1411 -D deprecated_warnings=false
1512
1613 override_dh_strip:
1714 dh_strip --dbg-package=libxapp-dbg
18
19 override_dh_auto_build:
20 ninja -C debian/build
21
22 override_dh_auto_test:
23 ninja -C debian/build test
24
25 override_dh_auto_install:
26 DESTDIR=${CURDIR}/debian/tmp \
27 ninja -C debian/build install
1010 main_xml: 'xapp-docs.xml',
1111 scan_args: ['--rebuild-types'],
1212 mkdb_args: ['--xml-mode', '--output-format=xml'],
13 )
13 ignore_headers: ['favorite-vfs-file.h', 'favorite-vfs-file-enumerator.h', 'favorite-vfs-file-monitor.h']
14 )
1515
1616 <chapter>
1717 <title>API reference</title>
18 <xi:include href="xml/xapp-favorites.xml"/>
1819 <xi:include href="xml/xapp-gtk-window.xml"/>
1920 <xi:include href="xml/xapp-icon-chooser-button.xml"/>
2021 <xi:include href="xml/xapp-icon-chooser-dialog.xml"/>
0 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
1 <svg
2 xmlns:dc="http://purl.org/dc/elements/1.1/"
3 xmlns:cc="http://creativecommons.org/ns#"
4 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
5 xmlns:svg="http://www.w3.org/2000/svg"
6 xmlns="http://www.w3.org/2000/svg"
7 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
8 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
9 id="svg4060"
10 height="16"
11 width="16"
12 version="1.1"
13 sodipodi:docname="xapp-favorite-symbolic.svg"
14 inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
15 <sodipodi:namedview
16 pagecolor="#ffffff"
17 bordercolor="#666666"
18 borderopacity="1"
19 objecttolerance="10"
20 gridtolerance="10"
21 guidetolerance="10"
22 inkscape:pageopacity="0"
23 inkscape:pageshadow="2"
24 inkscape:window-width="1920"
25 inkscape:window-height="989"
26 id="namedview6"
27 showgrid="true"
28 inkscape:zoom="41.7193"
29 inkscape:cx="0.93745069"
30 inkscape:cy="8.3555532"
31 inkscape:window-x="0"
32 inkscape:window-y="27"
33 inkscape:window-maximized="1"
34 inkscape:current-layer="svg4060">
35 <inkscape:grid
36 type="xygrid"
37 id="grid816" />
38 </sodipodi:namedview>
39 <defs
40 id="defs4062" />
41 <metadata
42 id="metadata4065">
43 <rdf:RDF>
44 <cc:Work
45 rdf:about="">
46 <dc:format>image/svg+xml</dc:format>
47 <dc:type
48 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
49 <dc:title />
50 </cc:Work>
51 </rdf:RDF>
52 </metadata>
53 <path
54 id="path3649"
55 style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.92937016;marker:none;enable-background:accumulate"
56 d="M 9.087891,10.5 5.9983503,8.874203 2.9075508,10.497604 3.4990553,7.0568778 1,4.6190107 4.4551098,4.1183218 6.0014083,0.98823644 7.5452799,4.1195202 11,4.6228883 8.4990549,7.0588163 Z M 11,9.0000004 V 11 H 9.0000002 v 2 H 11 v 2 h 2 v -2 h 2 V 11 H 13 V 9.0000004 Z" />
57 </svg>
0 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
1 <svg
2 xmlns:dc="http://purl.org/dc/elements/1.1/"
3 xmlns:cc="http://creativecommons.org/ns#"
4 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
5 xmlns:svg="http://www.w3.org/2000/svg"
6 xmlns="http://www.w3.org/2000/svg"
7 xmlns:xlink="http://www.w3.org/1999/xlink"
8 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
9 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
10 id="svg4060"
11 height="16"
12 width="16"
13 version="1.1"
14 sodipodi:docname="xapp-unfavorite-symbolic.svg"
15 inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
16 <sodipodi:namedview
17 pagecolor="#ffffff"
18 bordercolor="#666666"
19 borderopacity="1"
20 objecttolerance="10"
21 gridtolerance="10"
22 guidetolerance="10"
23 inkscape:pageopacity="0"
24 inkscape:pageshadow="2"
25 inkscape:window-width="1920"
26 inkscape:window-height="989"
27 id="namedview6"
28 showgrid="true"
29 inkscape:zoom="41.7193"
30 inkscape:cx="1.4574888"
31 inkscape:cy="7.7311177"
32 inkscape:window-x="0"
33 inkscape:window-y="27"
34 inkscape:window-maximized="1"
35 inkscape:current-layer="svg4060">
36 <inkscape:grid
37 type="xygrid"
38 id="grid816" />
39 </sodipodi:namedview>
40 <defs
41 id="defs4062">
42 <linearGradient
43 inkscape:collect="always"
44 xlink:href="#linearGradient5261"
45 id="linearGradient5263"
46 x1="1.013729"
47 y1="8"
48 x2="15"
49 y2="8"
50 gradientUnits="userSpaceOnUse"
51 gradientTransform="matrix(1.1111111,0,0,1.1111111,-0.11111111,-0.0555556)" />
52 <linearGradient
53 inkscape:collect="always"
54 id="linearGradient5261">
55 <stop
56 style="stop-color:#bebebe;stop-opacity:1;"
57 offset="0"
58 id="stop5257" />
59 <stop
60 style="stop-color:#bebebe;stop-opacity:0;"
61 offset="1"
62 id="stop5259" />
63 </linearGradient>
64 </defs>
65 <metadata
66 id="metadata4065">
67 <rdf:RDF>
68 <cc:Work
69 rdf:about="">
70 <dc:format>image/svg+xml</dc:format>
71 <dc:type
72 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
73 <dc:title />
74 </cc:Work>
75 </rdf:RDF>
76 </metadata>
77 <path
78 id="path836"
79 style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:url(#linearGradient5263);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.20698357;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
80 d="M 6.00217,0.98828111 4.4548611,4.1176211 1,4.6189233 3.5,7.0559889 2.9075522,10.49783 5.99783,8.8745656 9.0881078,10.5 8.5,7.05816 11,4.6232633 7.5451389,4.1197911 Z M 11,11 v 0 H 9.0000002 v 2 H 11 v 0 h 2 v 0 h 2 v -2 h -2 v 0 z" />
81 </svg>
0 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
1 <svg
2 xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
3 xmlns:dc="http://purl.org/dc/elements/1.1/"
4 xmlns:cc="http://creativecommons.org/ns#"
5 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
6 xmlns:svg="http://www.w3.org/2000/svg"
7 xmlns="http://www.w3.org/2000/svg"
8 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
9 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
10 inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
11 sodipodi:docname="xapp-favorites-symbolic.svg"
12 id="svg4"
13 version="1.1"
14 width="48"
15 height="48">
16 <metadata
17 id="metadata10">
18 <rdf:RDF>
19 <cc:Work
20 rdf:about="">
21 <dc:format>image/svg+xml</dc:format>
22 <dc:type
23 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
24 <dc:title></dc:title>
25 </cc:Work>
26 </rdf:RDF>
27 </metadata>
28 <defs
29 id="defs8">
30 <linearGradient
31 id="linearGradient7722"
32 osb:paint="gradient">
33 <stop
34 style="stop-color:#000000;stop-opacity:1;"
35 offset="0"
36 id="stop7718" />
37 <stop
38 style="stop-color:#000000;stop-opacity:0;"
39 offset="1"
40 id="stop7720" />
41 </linearGradient>
42 <filter
43 style="color-interpolation-filters:sRGB;"
44 inkscape:label="Feather"
45 id="filter1726">
46 <feGaussianBlur
47 stdDeviation="5"
48 result="blur"
49 id="feGaussianBlur1718" />
50 <feComposite
51 in="SourceGraphic"
52 in2="blur"
53 operator="atop"
54 result="composite1"
55 id="feComposite1720" />
56 <feComposite
57 in2="composite1"
58 operator="in"
59 result="composite2"
60 id="feComposite1722" />
61 <feComposite
62 in2="composite2"
63 operator="in"
64 result="composite3"
65 id="feComposite1724" />
66 </filter>
67 </defs>
68 <sodipodi:namedview
69 pagecolor="#ffffff"
70 bordercolor="#666666"
71 borderopacity="1"
72 objecttolerance="10"
73 gridtolerance="10"
74 guidetolerance="10"
75 inkscape:pageopacity="0"
76 inkscape:pageshadow="2"
77 inkscape:window-width="1920"
78 inkscape:window-height="989"
79 id="namedview6"
80 showgrid="false"
81 inkscape:zoom="12.525139"
82 inkscape:cx="27.539377"
83 inkscape:cy="20.700947"
84 inkscape:window-x="0"
85 inkscape:window-y="27"
86 inkscape:window-maximized="1"
87 inkscape:current-layer="svg4" />
88 <path
89 d="M 23.953096,2.4741988 17.470049,15.628515 3,17.78943 13.429644,28.03116 10.9867,42.5 23.953096,35.641717 36.91799,42.5 34.476548,28.03116 45,17.78943 30.435543,15.628515 Z"
90 id="path2"
91 style="fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:1.12517142;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0;paint-order:normal"
92 inkscape:connector-curvature="0"
93 sodipodi:nodetypes="ccccccccccc" />
94 </svg>
0 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
1 <svg
2 xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
3 xmlns:dc="http://purl.org/dc/elements/1.1/"
4 xmlns:cc="http://creativecommons.org/ns#"
5 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
6 xmlns:svg="http://www.w3.org/2000/svg"
7 xmlns="http://www.w3.org/2000/svg"
8 xmlns:xlink="http://www.w3.org/1999/xlink"
9 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
10 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
11 inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
12 sodipodi:docname="xapp-favorites.svg"
13 id="svg4"
14 version="1.1"
15 width="96"
16 height="96"
17 style="enable-background:new">
18 <metadata
19 id="metadata10">
20 <rdf:RDF>
21 <cc:Work
22 rdf:about="">
23 <dc:format>image/svg+xml</dc:format>
24 <dc:type
25 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
26 <dc:title></dc:title>
27 </cc:Work>
28 </rdf:RDF>
29 </metadata>
30 <defs
31 id="defs8">
32 <linearGradient
33 x1="48"
34 y1="90"
35 x2="48"
36 gradientUnits="userSpaceOnUse"
37 y2="5.9877"
38 id="linearGradient6452">
39 <stop
40 id="stop6448"
41 offset="0"
42 stop-color="#b4b4b4" />
43 <stop
44 id="stop6450"
45 offset="1"
46 stop-color="#e6e6e6" />
47 </linearGradient>
48 <linearGradient
49 id="linearGradient4984"
50 osb:paint="solid">
51 <stop
52 style="stop-color:#ffffff;stop-opacity:1;"
53 offset="0"
54 id="stop4982" />
55 </linearGradient>
56 <linearGradient
57 id="linearGradient7722"
58 osb:paint="gradient">
59 <stop
60 style="stop-color:#000000;stop-opacity:1;"
61 offset="0"
62 id="stop7718" />
63 <stop
64 style="stop-color:#000000;stop-opacity:0;"
65 offset="1"
66 id="stop7720" />
67 </linearGradient>
68 <filter
69 style="color-interpolation-filters:sRGB"
70 inkscape:label="Feather"
71 id="filter1726">
72 <feGaussianBlur
73 stdDeviation="5"
74 result="blur"
75 id="feGaussianBlur1718" />
76 <feComposite
77 in="SourceGraphic"
78 in2="blur"
79 operator="atop"
80 result="composite1"
81 id="feComposite1720" />
82 <feComposite
83 in2="composite1"
84 operator="in"
85 result="composite2"
86 id="feComposite1722" />
87 <feComposite
88 in2="composite2"
89 operator="in"
90 result="composite3"
91 id="feComposite1724" />
92 </filter>
93 <filter
94 style="color-interpolation-filters:sRGB"
95 inkscape:label="Drop Shadow"
96 id="filter1795">
97 <feFlood
98 flood-opacity="0.498039"
99 flood-color="rgb(0,0,0)"
100 result="flood"
101 id="feFlood1785" />
102 <feComposite
103 in="flood"
104 in2="SourceGraphic"
105 operator="in"
106 result="composite1"
107 id="feComposite1787" />
108 <feGaussianBlur
109 in="composite1"
110 stdDeviation="1"
111 result="blur"
112 id="feGaussianBlur1789" />
113 <feOffset
114 dx="1"
115 dy="1"
116 result="offset"
117 id="feOffset1791" />
118 <feComposite
119 in="SourceGraphic"
120 in2="offset"
121 operator="over"
122 result="composite2"
123 id="feComposite1793" />
124 </filter>
125 <filter
126 style="color-interpolation-filters:sRGB"
127 inkscape:label="Drop Shadow"
128 id="filter1819">
129 <feFlood
130 flood-opacity="0.498039"
131 flood-color="rgb(0,0,0)"
132 result="flood"
133 id="feFlood1809" />
134 <feComposite
135 in="flood"
136 in2="SourceGraphic"
137 operator="in"
138 result="composite1"
139 id="feComposite1811" />
140 <feGaussianBlur
141 in="composite1"
142 stdDeviation="1"
143 result="blur"
144 id="feGaussianBlur1813" />
145 <feOffset
146 dx="1"
147 dy="1"
148 result="offset"
149 id="feOffset1815" />
150 <feComposite
151 in="SourceGraphic"
152 in2="offset"
153 operator="over"
154 result="composite2"
155 id="feComposite1817" />
156 </filter>
157 <filter
158 style="color-interpolation-filters:sRGB"
159 inkscape:label="Drop Shadow"
160 id="filter1720">
161 <feFlood
162 flood-opacity="0.498039"
163 flood-color="rgb(0,0,0)"
164 result="flood"
165 id="feFlood1710" />
166 <feComposite
167 in="flood"
168 in2="SourceGraphic"
169 operator="in"
170 result="composite1"
171 id="feComposite1712" />
172 <feGaussianBlur
173 in="composite1"
174 stdDeviation="1"
175 result="blur"
176 id="feGaussianBlur1714" />
177 <feOffset
178 dx="1"
179 dy="1"
180 result="offset"
181 id="feOffset1716" />
182 <feComposite
183 in="SourceGraphic"
184 in2="offset"
185 operator="over"
186 result="composite2"
187 id="feComposite1718" />
188 </filter>
189 <filter
190 style="color-interpolation-filters:sRGB"
191 inkscape:label="Drop Shadow"
192 id="filter1740">
193 <feFlood
194 flood-opacity="0.498039"
195 flood-color="rgb(0,0,0)"
196 result="flood"
197 id="feFlood1730" />
198 <feComposite
199 in="flood"
200 in2="SourceGraphic"
201 operator="in"
202 result="composite1"
203 id="feComposite1732" />
204 <feGaussianBlur
205 in="composite1"
206 stdDeviation="1"
207 result="blur"
208 id="feGaussianBlur1734" />
209 <feOffset
210 dx="1"
211 dy="1"
212 result="offset"
213 id="feOffset1736" />
214 <feComposite
215 in="SourceGraphic"
216 in2="offset"
217 operator="over"
218 result="composite2"
219 id="feComposite1738" />
220 </filter>
221 <linearGradient
222 id="g"
223 y2="90.238998"
224 xlink:href="#a"
225 gradientUnits="userSpaceOnUse"
226 x2="32.250999"
227 gradientTransform="matrix(1.0238,0,0,-1.0119,-1.1429,98.071)"
228 y1="6.1317"
229 x1="32.250999" />
230 <linearGradient
231 id="a"
232 y2="7.0165"
233 gradientUnits="userSpaceOnUse"
234 x2="45.448002"
235 gradientTransform="matrix(1.0059,0,0,0.99417,100,0)"
236 y1="92.540001"
237 x1="45.448002">
238 <stop
239 offset="0"
240 id="stop3979" />
241 <stop
242 stop-opacity=".58824"
243 offset="1"
244 id="stop3981" />
245 </linearGradient>
246 <linearGradient
247 id="h"
248 y2="5.9995999"
249 xlink:href="#a"
250 gradientUnits="userSpaceOnUse"
251 x2="32.250999"
252 gradientTransform="matrix(1.0238,0,0,1.0119,-1.1429,0.929)"
253 y1="90"
254 x1="32.250999" />
255 <linearGradient
256 id="i"
257 y2="6"
258 xlink:href="#a"
259 gradientUnits="userSpaceOnUse"
260 x2="32.250999"
261 gradientTransform="translate(0,1)"
262 y1="90"
263 x1="32.250999" />
264 <radialGradient
265 id="e"
266 gradientUnits="userSpaceOnUse"
267 cy="78.287003"
268 cx="47.098"
269 gradientTransform="matrix(1.383,-1.035e-8,0,1.3124,-18.038997,-24.219)"
270 r="38.957001">
271 <stop
272 stop-color="#42394b"
273 offset="0"
274 id="stop4006" />
275 <stop
276 offset="1"
277 id="stop4008" />
278 </radialGradient>
279 <filter
280 style="color-interpolation-filters:sRGB"
281 id="o"
282 height="1.0908"
283 width="1.3035001"
284 y="-0.045378"
285 x="-0.15174">
286 <feGaussianBlur
287 stdDeviation="1.1526305"
288 id="feGaussianBlur3973" />
289 </filter>
290 <linearGradient
291 id="b"
292 y2="52.101002"
293 xlink:href="#d"
294 gradientUnits="userSpaceOnUse"
295 x2="19.941999"
296 gradientTransform="matrix(0,-0.65823,0.65616,0,-10.186,94.127)"
297 y1="52.101002"
298 x1="80.710999" />
299 <linearGradient
300 id="d"
301 stop-color="#fff">
302 <stop
303 offset="0"
304 id="stop3968" />
305 <stop
306 stop-opacity="0"
307 offset="1"
308 id="stop3970" />
309 </linearGradient>
310 <filter
311 style="color-interpolation-filters:sRGB"
312 id="p"
313 height="1.3025"
314 width="1.0888"
315 y="-0.15126"
316 x="-0.044411998">
317 <feGaussianBlur
318 stdDeviation="1.1526305"
319 id="feGaussianBlur3976" />
320 </filter>
321 <linearGradient
322 id="c"
323 y2="52.101002"
324 xlink:href="#d"
325 gradientUnits="userSpaceOnUse"
326 x2="19.941999"
327 gradientTransform="matrix(0.65823,0,0,0.65616,2.8732,25.814)"
328 y1="52.101002"
329 x1="80.710999" />
330 <linearGradient
331 id="j"
332 y2="5.9877"
333 gradientUnits="userSpaceOnUse"
334 x2="48"
335 y1="90"
336 x1="48">
337 <stop
338 stop-color="#b4b4b4"
339 offset="0"
340 id="stop3999" />
341 <stop
342 stop-color="#e6e6e6"
343 offset="1"
344 id="stop4001" />
345 </linearGradient>
346 <linearGradient
347 id="m"
348 stop-color="#fff"
349 y2="63.893002"
350 gradientUnits="userSpaceOnUse"
351 x2="36.356998"
352 y1="6"
353 x1="36.356998">
354 <stop
355 offset="0"
356 id="stop3994" />
357 <stop
358 stop-opacity="0"
359 offset="1"
360 id="stop3996" />
361 </linearGradient>
362 <linearGradient
363 id="n"
364 y2="83.294998"
365 gradientUnits="userSpaceOnUse"
366 x2="43.179001"
367 gradientTransform="matrix(1.0294,0,0,1.0294,-1.4118,-1.4118)"
368 y1="13"
369 x1="43.179001">
370 <stop
371 stop-color="#919191"
372 offset="0"
373 id="stop3989" />
374 <stop
375 stop-color="#fdfdfd"
376 offset="1"
377 id="stop3991" />
378 </linearGradient>
379 <radialGradient
380 id="f"
381 stop-color="#fff"
382 gradientUnits="userSpaceOnUse"
383 cy="90.171997"
384 cx="48"
385 gradientTransform="matrix(1.1573,0,0,0.99591,-7.551,0.19713)"
386 r="42">
387 <stop
388 offset="0"
389 id="stop3984" />
390 <stop
391 stop-opacity="0"
392 offset="1"
393 id="stop3986" />
394 </radialGradient>
395 <linearGradient
396 inkscape:collect="always"
397 xlink:href="#a"
398 id="linearGradient4912"
399 gradientUnits="userSpaceOnUse"
400 gradientTransform="matrix(1.0238,0,0,-1.0119,-1.1429,98.071)"
401 x1="32.250999"
402 y1="6.1317"
403 x2="32.250999"
404 y2="90.238998" />
405 <linearGradient
406 inkscape:collect="always"
407 xlink:href="#a"
408 id="linearGradient4914"
409 gradientUnits="userSpaceOnUse"
410 gradientTransform="matrix(1.0238,0,0,-1.0119,-1.1429,98.071)"
411 x1="32.250999"
412 y1="6.1317"
413 x2="32.250999"
414 y2="90.238998" />
415 <linearGradient
416 inkscape:collect="always"
417 xlink:href="#a"
418 id="linearGradient4916"
419 gradientUnits="userSpaceOnUse"
420 gradientTransform="matrix(1.0238,0,0,-1.0119,-1.1429,98.071)"
421 x1="32.250999"
422 y1="6.1317"
423 x2="32.250999"
424 y2="90.238998" />
425 <radialGradient
426 inkscape:collect="always"
427 xlink:href="#linearGradient6452"
428 id="radialGradient6446"
429 cx="24.000002"
430 cy="23.915552"
431 fx="24.000002"
432 fy="23.915552"
433 r="23.37389"
434 gradientTransform="matrix(0.50559953,-0.01484073,0.01430171,0.48723605,11.523578,12.619211)"
435 gradientUnits="userSpaceOnUse" />
436 </defs>
437 <sodipodi:namedview
438 pagecolor="#ffffff"
439 bordercolor="#666666"
440 borderopacity="1"
441 objecttolerance="10"
442 gridtolerance="10"
443 guidetolerance="10"
444 inkscape:pageopacity="0"
445 inkscape:pageshadow="2"
446 inkscape:window-width="1920"
447 inkscape:window-height="989"
448 id="namedview6"
449 showgrid="false"
450 inkscape:zoom="4.4283054"
451 inkscape:cx="46.062124"
452 inkscape:cy="35.733194"
453 inkscape:window-x="0"
454 inkscape:window-y="27"
455 inkscape:window-maximized="1"
456 inkscape:current-layer="svg4" />
457 <ellipse
458 style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.95995587;stroke-opacity:1;filter:url(#filter1819)"
459 id="path1698"
460 cx="-62.545948"
461 cy="154.09407"
462 rx="21"
463 ry="20.501823" />
464 <rect
465 style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-opacity:1;filter:url(#filter1740)"
466 id="rect1728"
467 width="40"
468 height="40"
469 x="-129.49153"
470 y="121.61999"
471 rx="6"
472 ry="6" />
473 <path
474 d="M 93.79561,48.452021 87.457596,61.312062 73.31126,63.424634 83.50758,73.437241 81.119287,87.5824 93.79561,80.877544 106.47046,87.5824 104.08364,73.437241 114.37167,63.424634 100.13303,61.312062 Z"
475 id="path2-3"
476 style="fill:none;fill-opacity:0.94117647;stroke:#000000;stroke-width:2.93992543;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0"
477 inkscape:connector-curvature="0"
478 sodipodi:nodetypes="ccccccccccc" />
479 <g
480 style="fill:url(#g)"
481 id="g4022">
482 <path
483 style="opacity:0.07999998;fill:url(#linearGradient4912)"
484 inkscape:connector-curvature="0"
485 d="M 12,95.031 C 6.4889,95.031 1.969,90.511 1.969,85 V 14 C 1.969,8.4889 6.4892,3.969 12,3.969 h 72 c 5.5111,0 10.031,4.5202 10.031,10.031 v 71 c 0,5.5111 -4.5202,10.031 -10.031,10.031 z"
486 id="path4016" />
487 <path
488 style="opacity:0.1;fill:url(#linearGradient4914)"
489 inkscape:connector-curvature="0"
490 d="m 12,94.031 c -4.9716,0 -9.0312,-4.0596 -9.0312,-9.0312 v -71 C 2.9688,9.028 7.0284,4.9684 12,4.9684 h 72 c 4.9716,0 9.0312,4.0596 9.0312,9.0312 v 71 c 0,4.9716 -4.0596,9.0312 -9.0312,9.0312 H 12 Z"
491 id="path4018" />
492 <path
493 style="opacity:0.2;fill:url(#linearGradient4916)"
494 inkscape:connector-curvature="0"
495 d="M 12,93 C 7.5909,93 4,89.409 4,85 V 14 C 4,9.5909 7.5909,6 12,6 h 72 c 4.4091,0 8,3.5909 8,8 v 71 c 0,4.4091 -3.5909,8 -8,8 z"
496 id="path4020" />
497 </g>
498 <rect
499 style="opacity:0.3;fill:url(#h)"
500 rx="7"
501 ry="7"
502 height="85"
503 width="86"
504 y="6.9999986"
505 x="4.9999986"
506 id="rect4024" />
507 <rect
508 style="opacity:0.45;fill:url(#i)"
509 rx="6"
510 ry="6"
511 height="84"
512 width="84"
513 y="6.9999986"
514 x="5.9999986"
515 id="rect4026" />
516 <path
517 inkscape:connector-curvature="0"
518 style="opacity:0.15"
519 d="m 19,13 c -3.2894,0 -6,2.7106 -6,6 v 58 c 0,3.2894 2.7106,6 6,6 h 58 c 3.2894,0 6,-2.7106 6,-6 V 19 c 0,-3.2894 -2.7106,-6 -6,-6 z m 0,4 h 58 c 1.1426,0 2,0.85741 2,2 v 58 c 0,1.1426 -0.85741,2 -2,2 H 19 c -1.1426,0 -2,-0.85741 -2,-2 V 19 c 0,-1.1426 0.85741,-2 2,-2 z"
520 id="path4058" />
521 <path
522 inkscape:connector-curvature="0"
523 style="opacity:0.3"
524 d="m 17,14 c -1.662,0 -3,1.338 -3,3 v 62 c 0,1.662 1.338,3 3,3 h 62 c 1.662,0 3,-1.338 3,-3 V 17 c 0,-1.662 -1.338,-3 -3,-3 z m 0,1.9375 h 62 c 0.61816,0 1.0625,0.44434 1.0625,1.0625 v 62 c 0,0.61816 -0.44434,1.0625 -1.0625,1.0625 H 17 c -0.61816,0 -1.0625,-0.44434 -1.0625,-1.0625 V 17 c 0,-0.61816 0.44434,-1.0625 1.0625,-1.0625 z"
525 id="path4060" />
526 <path
527 inkscape:connector-curvature="0"
528 style="opacity:0.6"
529 d="m 17,14 c -1.662,0 -3,1.338 -3,3 v 62 c 0,1.662 1.338,3 3,3 h 62 c 1.662,0 3,-1.338 3,-3 V 17 c 0,-1.662 -1.338,-3 -3,-3 z m 0,0.96875 h 62 c 1.1401,0 2.0312,0.89117 2.0312,2.0312 v 62 c 0,1.1401 -0.89117,2.0312 -2.0312,2.0312 H 17 c -1.1401,0 -2.0312,-0.89117 -2.0312,-2.0312 v -62 c 0,-1.1401 0.89117,-2.0312 2.0312,-2.0312 z"
530 id="path4062" />
531 <path
532 inkscape:connector-curvature="0"
533 style="fill:url(#j)"
534 d="M 12,6 C 8.676,6 6,8.676 6,12 v 72 c 0,3.324 2.676,6 6,6 h 72 c 3.324,0 6,-2.676 6,-6 V 12 C 90,8.676 87.324,6 84,6 Z m 5,7 h 62 c 2.216,0 4,1.784 4,4 v 62 c 10e-7,2.216 -1.784,4 -4,4 H 17 c -2.216,10e-7 -4,-1.784 -4,-4 V 17 c 0,-2.216 1.784,-4 4,-4 z"
535 id="path4064" />
536 <path
537 inkscape:connector-curvature="0"
538 style="opacity:0.5;fill:url(#m)"
539 d="M 12,6 C 8.676,6 6,8.676 6,12 v 72 c 0,0.33472 0.04135,0.6507 0.09375,0.96875 0.0487,0.2956 0.09704,0.59692 0.1875,0.875 0.0099,0.03038 0.02089,0.0636 0.03125,0.09375 0.09887,0.28777 0.23488,0.54745 0.375,0.8125 0.14459,0.27351 0.31562,0.53562 0.5,0.78125 0.18438,0.24564 0.37378,0.47347 0.59375,0.6875 0.43995,0.42806 0.94291,0.81453 1.5,1.0938 0.27854,0.13961 0.5734698,0.24695 0.875,0.34375 -0.2562002,-0.10022 -0.48671,-0.23627 -0.71875,-0.375 -0.0074,-0.0044 -0.02387,0.0045 -0.03125,0 -0.0319,-0.019 -0.0622,-0.042 -0.0937,-0.062 -0.1204,-0.077 -0.231,-0.164 -0.3437,-0.25 -0.1062,-0.081 -0.2133,-0.161 -0.3126,-0.25 -0.1778,-0.162 -0.3473,-0.346 -0.4999,-0.531 -0.1075,-0.131 -0.2183,-0.266 -0.3124,-0.407 -0.0251,-0.038 -0.0385,-0.086 -0.0626,-0.125 -0.0647,-0.103 -0.1302,-0.204 -0.1874,-0.312 -0.1011,-0.195 -0.2057,-0.416 -0.2813,-0.625 -0.008,-0.022 -0.0236,-0.041 -0.0313,-0.063 -0.0318,-0.092 -0.0358,-0.187 -0.0624,-0.281 -0.0304,-0.107 -0.0704,-0.203 -0.0938,-0.313 -0.0729,-0.341 -0.125,-0.698 -0.125,-1.062 v -72 c 0,-2.782 2.2182,-5 5,-5 h 72 c 2.7818,0 5,2.2182 5,5 v 72 c 0,0.3643 -0.05212,0.72099 -0.125,1.0625 -0.04415,0.20689 -0.08838,0.39766 -0.15625,0.59375 -0.0077,0.02195 -0.0233,0.04069 -0.03125,0.0625 -0.06274,0.17374 -0.13838,0.36745 -0.21875,0.53125 -0.04158,0.0828 -0.07904,0.16995 -0.125,0.25 -0.0546,0.09721 -0.12677,0.18835 -0.1875,0.28125 -0.09411,0.14096 -0.20492,0.276 -0.3125,0.40625 -0.14317,0.17445 -0.30314,0.347 -0.46875,0.5 -0.01117,0.0102 -0.01998,0.02115 -0.03125,0.03125 -0.13839,0.12556 -0.28509,0.23444 -0.4375,0.34375 -0.10257,0.07315 -0.20432,0.15336 -0.3125,0.21875 -0.0074,0.0045 -0.02384,-0.0044 -0.03125,0 -0.23204,0.13873 -0.46255,0.27478 -0.71875,0.375 0.30153,-0.0968 0.59646,-0.20414 0.875,-0.34375 0.55709,-0.27922 1.0601,-0.66569 1.5,-1.0938 0.21997,-0.21403 0.40937,-0.44186 0.59375,-0.6875 0.18438,-0.24564 0.35541,-0.50774 0.5,-0.78125 0.14012,-0.26505 0.27614,-0.52473 0.375,-0.8125 0.01041,-0.03078 0.02133,-0.06274 0.03125,-0.09375 0.09046,-0.27808 0.1388,-0.5794 0.1875,-0.875 0.053,-0.318 0.094,-0.634 0.094,-0.969 V 12 c 0,-3.324 -2.676,-6 -6,-6 h -72 z"
540 id="path4066" />
541 <path
542 inkscape:connector-curvature="0"
543 style="fill:url(#n)"
544 d="m 17,12 c -2.7527,0 -5,2.2473 -5,5 v 62 c 0,2.7527 2.2473,5 5,5 h 62 c 2.7527,0 5,-2.2473 5,-5 V 17 c 0,-2.7527 -2.2473,-5 -5,-5 z m 0,2 h 62 c 1.6793,0 3,1.3207 3,3 v 62 c 10e-7,1.6793 -1.3207,3 -3,3 H 17 c -1.6793,0 -3,-1.3207 -3,-3 V 17 c 0,-1.6793 1.3207,-3 3,-3 z"
545 id="path4068" />
546 <path
547 inkscape:connector-curvature="0"
548 style="opacity:0.4;fill:url(#f)"
549 d="M 12,90 C 8.676,90 6,87.324 6,84 V 12 c 0,-0.33472 0.04135,-0.6507 0.09375,-0.96875 0.0487,-0.2956 0.09704,-0.59692 0.1875,-0.875 0.0099,-0.03 0.0209,-0.063 0.0313,-0.094 0.0989,-0.2873 0.2349,-0.547 0.375,-0.812 0.1446,-0.2735 0.3156,-0.5356 0.5,-0.7812 0.1844,-0.2457 0.3738,-0.4735 0.5937,-0.6876 0.44,-0.428 0.943,-0.8145 1.5,-1.0937 0.2786,-0.1396 0.5734998,-0.2469 0.8748,-0.3437 -0.2560002,0.1002 -0.4865,0.2362 -0.7185,0.375 -0.0074,0.0044 -0.02387,-0.0045 -0.03125,0 -0.03193,0.0193 -0.06229,0.04251 -0.09375,0.0625 -0.1204,0.0767 -0.23102,0.16351 -0.34375,0.25 -0.10617,0.0808 -0.21328,0.16111 -0.3125,0.25 -0.1779,0.1614 -0.3474,0.3453 -0.5,0.5312 -0.1075,0.1303 -0.2183,0.2653 -0.3124,0.4063 -0.0251,0.0383 -0.0385,0.0858 -0.0626,0.125 -0.0647,0.103 -0.1302,0.2045 -0.1874,0.3124 -0.1011,0.1948 -0.2057,0.4158 -0.2813,0.625 -0.008,0.0219 -0.0236,0.0406 -0.0313,0.0626 -0.0318,0.0919 -0.0358,0.1868 -0.0624,0.2812 -0.0304,0.1066 -0.0704,0.203 -0.0938,0.3125 -0.0729,0.3415 -0.125,0.6985 -0.125,1.0625 v 72 c 0,2.7818 2.2182,5 5,5 h 72 c 2.7818,0 5,-2.2182 5,-5 v -72 c 0,-0.364 -0.052,-0.721 -0.125,-1.0625 -0.044,-0.2069 -0.088,-0.3977 -0.156,-0.5937 -0.008,-0.022 -0.024,-0.0407 -0.031,-0.0626 -0.063,-0.1737 -0.139,-0.3674 -0.219,-0.5312 -0.042,-0.0828 -0.079,-0.17 -0.125,-0.25 -0.055,-0.0972 -0.127,-0.1884 -0.188,-0.2812 -0.094,-0.141 -0.205,-0.276 -0.312,-0.4063 -0.143,-0.1745 -0.303,-0.347 -0.469,-0.5 -0.011,-0.0102 -0.02,-0.0211 -0.031,-0.0313 -0.139,-0.1255 -0.285,-0.2344 -0.438,-0.3437 -0.102,-0.0731 -0.204,-0.1534 -0.312,-0.2187 -0.0074,-0.0045 -0.02384,0.0044 -0.03125,0 -0.23204,-0.13873 -0.46255,-0.27478 -0.71875,-0.375 0.30153,0.0968 0.59646,0.20414 0.875,0.34375 0.55709,0.27922 1.0601,0.66569 1.5,1.0938 0.21997,0.21403 0.40937,0.44186 0.59375,0.6875 0.18438,0.24564 0.35541,0.50774 0.5,0.78125 0.14012,0.26505 0.27614,0.52473 0.375,0.8125 0.01041,0.03078 0.02133,0.06274 0.03125,0.09375 0.09046,0.27808 0.1388,0.5794 0.1875,0.875 0.053,0.318 0.094,0.634 0.094,0.969 v 72 c 0,3.324 -2.676,6 -6,6 h -72 z"
550 id="path4070" />
551 <path
552 d="M 23.956495,5.3528801 17.94324,17.553973 4.521759,19.558298 l 9.673863,9.499563 -2.265917,13.420364 12.02679,-6.3613 12.025397,6.3613 -2.264523,-13.420364 9.760873,-9.499563 -13.509048,-2.004325 z"
553 id="path2"
554 style="fill:url(#radialGradient6446);fill-opacity:1;stroke:#000000;stroke-width:1.0436362;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0;paint-order:normal;filter:url(#filter1795)"
555 inkscape:connector-curvature="0"
556 sodipodi:nodetypes="ccccccccccc"
557 transform="matrix(1.4973973,0,0,1.4973973,12.062463,10.33408)" />
558 </svg>
0 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
1 <svg
2 xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
3 xmlns:dc="http://purl.org/dc/elements/1.1/"
4 xmlns:cc="http://creativecommons.org/ns#"
5 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
6 xmlns:svg="http://www.w3.org/2000/svg"
7 xmlns="http://www.w3.org/2000/svg"
8 xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
9 xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
10 inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
11 sodipodi:docname="emblem-xapp-favorite.svg"
12 id="svg4"
13 version="1.1"
14 width="48"
15 height="48"
16 enable-background="new">
17 <metadata
18 id="metadata10">
19 <rdf:RDF>
20 <cc:Work
21 rdf:about="">
22 <dc:format>image/svg+xml</dc:format>
23 <dc:type
24 rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
25 <dc:title />
26 </cc:Work>
27 </rdf:RDF>
28 </metadata>
29 <defs
30 id="defs8">
31 <linearGradient
32 id="linearGradient7722"
33 osb:paint="gradient">
34 <stop
35 style="stop-color:#000000;stop-opacity:1;"
36 offset="0"
37 id="stop7718" />
38 <stop
39 style="stop-color:#000000;stop-opacity:0;"
40 offset="1"
41 id="stop7720" />
42 </linearGradient>
43 <filter
44 style="color-interpolation-filters:sRGB;"
45 inkscape:label="Feather"
46 id="filter1726">
47 <feGaussianBlur
48 stdDeviation="5"
49 result="blur"
50 id="feGaussianBlur1718" />
51 <feComposite
52 in="SourceGraphic"
53 in2="blur"
54 operator="atop"
55 result="composite1"
56 id="feComposite1720" />
57 <feComposite
58 in2="composite1"
59 operator="in"
60 result="composite2"
61 id="feComposite1722" />
62 <feComposite
63 in2="composite2"
64 operator="in"
65 result="composite3"
66 id="feComposite1724" />
67 </filter>
68 <filter
69 inkscape:collect="always"
70 style="color-interpolation-filters:sRGB"
71 id="filter1694"
72 x="-0.02929493"
73 width="1.0585899"
74 y="-0.030739846"
75 height="1.0614797">
76 <feGaussianBlur
77 inkscape:collect="always"
78 stdDeviation="0.54683814"
79 id="feGaussianBlur1696" />
80 </filter>
81 <filter
82 style="color-interpolation-filters:sRGB;"
83 inkscape:label="Drop Shadow"
84 id="filter1795">
85 <feFlood
86 flood-opacity="0.498039"
87 flood-color="rgb(0,0,0)"
88 result="flood"
89 id="feFlood1785" />
90 <feComposite
91 in="flood"
92 in2="SourceGraphic"
93 operator="in"
94 result="composite1"
95 id="feComposite1787" />
96 <feGaussianBlur
97 in="composite1"
98 stdDeviation="1"
99 result="blur"
100 id="feGaussianBlur1789" />
101 <feOffset
102 dx="1"
103 dy="1"
104 result="offset"
105 id="feOffset1791" />
106 <feComposite
107 in="SourceGraphic"
108 in2="offset"
109 operator="over"
110 result="composite2"
111 id="feComposite1793" />
112 </filter>
113 <filter
114 style="color-interpolation-filters:sRGB;"
115 inkscape:label="Drop Shadow"
116 id="filter1819">
117 <feFlood
118 flood-opacity="0.498039"
119 flood-color="rgb(0,0,0)"
120 result="flood"
121 id="feFlood1809" />
122 <feComposite
123 in="flood"
124 in2="SourceGraphic"
125 operator="in"
126 result="composite1"
127 id="feComposite1811" />
128 <feGaussianBlur
129 in="composite1"
130 stdDeviation="1"
131 result="blur"
132 id="feGaussianBlur1813" />
133 <feOffset
134 dx="1"
135 dy="1"
136 result="offset"
137 id="feOffset1815" />
138 <feComposite
139 in="SourceGraphic"
140 in2="offset"
141 operator="over"
142 result="composite2"
143 id="feComposite1817" />
144 </filter>
145 </defs>
146 <sodipodi:namedview
147 pagecolor="#ffffff"
148 bordercolor="#666666"
149 borderopacity="1"
150 objecttolerance="10"
151 gridtolerance="10"
152 guidetolerance="10"
153 inkscape:pageopacity="0"
154 inkscape:pageshadow="2"
155 inkscape:window-width="1920"
156 inkscape:window-height="989"
157 id="namedview6"
158 showgrid="false"
159 inkscape:zoom="12.525139"
160 inkscape:cx="10.514129"
161 inkscape:cy="19.752735"
162 inkscape:window-x="0"
163 inkscape:window-y="27"
164 inkscape:window-maximized="1"
165 inkscape:current-layer="svg4" />
166 <ellipse
167 style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.95995587;stroke-opacity:1;filter:url(#filter1819)"
168 id="path1698"
169 cx="24"
170 cy="24.498177"
171 rx="21"
172 ry="20.501823" />
173 <path
174 d="m -38.085272,-1.7272848 -6.915242,14.0312568 -15.434703,2.304974 11.124942,10.924498 -2.605805,15.433419 13.830808,-7.315495 13.829207,7.315495 -2.604201,-15.433419 11.225004,-10.924498 -15.535406,-2.304974 z"
175 id="path2-2"
176 style="fill:#cccccc;fill-opacity:1;stroke:#000000;stroke-width:1.20018172;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0;paint-order:normal;filter:url(#filter1694)"
177 inkscape:connector-curvature="0"
178 sodipodi:nodetypes="ccccccccccc" />
179 <path
180 d="M 23.956495,5.3528801 17.94324,17.553973 4.521759,19.558298 l 9.673863,9.499563 -2.265917,13.420364 12.02679,-6.3613 12.025397,6.3613 -2.264523,-13.420364 9.760873,-9.499563 -13.509048,-2.004325 z"
181 id="path2"
182 style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.0436362;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0;paint-order:normal;filter:url(#filter1795)"
183 inkscape:connector-curvature="0"
184 sodipodi:nodetypes="ccccccccccc"
185 transform="matrix(0.90919255,0,0,0.90919255,2.1793771,1.0885881)" />
186 <path
187 d="M 8.0836672,-3.5187526 1.7456531,9.3412879 -12.400683,11.45386 -2.2043633,21.466467 -4.5926558,35.611626 8.0836672,28.90677 20.758521,35.611626 18.371698,21.466467 28.659726,11.45386 14.421094,9.3412879 Z"
188 id="path2-3"
189 style="fill:none;fill-opacity:0.94117647;stroke:#000000;stroke-width:2.93992543;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0"
190 inkscape:connector-curvature="0"
191 sodipodi:nodetypes="ccccccccccc" />
192 </svg>
0 #include "xapp-favorites.h"
1 #include "favorite-vfs-file-enumerator.h"
2 #include "favorite-vfs-file.h"
3
4 typedef struct
5 {
6 GFile *file;
7
8 GList *uris;
9 gchar *attributes;
10 GFileQueryInfoFlags flags;
11
12 GList *current_pos;
13 } FavoriteVfsFileEnumeratorPrivate;
14
15 struct _FavoriteVfsFileEnumerator
16 {
17 GObject parent_instance;
18 FavoriteVfsFileEnumeratorPrivate *priv;
19 };
20
21 G_DEFINE_TYPE_WITH_PRIVATE(FavoriteVfsFileEnumerator,
22 favorite_vfs_file_enumerator,
23 G_TYPE_FILE_ENUMERATOR)
24
25 static GFileInfo *
26 next_file (GFileEnumerator *enumerator,
27 GCancellable *cancellable,
28 GError **error)
29 {
30 FavoriteVfsFileEnumerator *self = FAVORITE_VFS_FILE_ENUMERATOR (enumerator);
31 FavoriteVfsFileEnumeratorPrivate *priv = favorite_vfs_file_enumerator_get_instance_private (self);
32 GFileInfo *info;
33
34 if (cancellable)
35 {
36 if (g_cancellable_is_cancelled (cancellable))
37 {
38 *error = g_error_new (G_IO_ERROR, G_IO_ERROR_CANCELLED, "Enumerate canceled");
39 return NULL;
40 }
41 }
42
43 info = NULL;
44
45 while (priv->current_pos != NULL && info == NULL)
46 {
47 GFile *file;
48 gchar *uri;
49
50 uri = path_to_fav_uri ((const gchar *) priv->current_pos->data);
51 if (!xapp_favorites_find_by_display_name (xapp_favorites_get_default (), (gchar *) priv->current_pos->data))
52 {
53 *error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "File not found");
54
55 g_warn_if_reached ();
56 }
57 else
58 {
59 file = g_file_new_for_uri (uri);
60
61 info = g_file_query_info (file,
62 priv->attributes,
63 priv->flags,
64 cancellable,
65 error);
66 }
67
68 g_free (uri);
69 g_object_unref (file);
70 }
71
72 if (priv->current_pos)
73 {
74 priv->current_pos = priv->current_pos->next;
75 }
76
77 return info;
78 }
79
80 static void
81 next_async_op_free (GList *files)
82 {
83 g_list_free_full (files, g_object_unref);
84 }
85
86 static void
87 next_files_async_thread (GTask *task,
88 gpointer source_object,
89 gpointer task_data,
90 GCancellable *cancellable)
91 {
92 FavoriteVfsFileEnumerator *self = FAVORITE_VFS_FILE_ENUMERATOR (source_object);
93 GList *ret;
94 GError *error = NULL;
95 gint i, n_requested;
96
97 n_requested = GPOINTER_TO_INT (g_task_get_task_data (task));
98
99 ret = NULL;
100
101 for (i = 0; i < n_requested; i++)
102 {
103 GFileInfo *info = NULL;
104 // g_clear_error (&error);
105
106 if (g_cancellable_set_error_if_cancelled (cancellable, &error))
107 {
108 g_task_return_error (task, error);
109 return;
110 }
111 else
112 {
113 info = next_file (G_FILE_ENUMERATOR (self), cancellable, &error);
114 }
115
116 if (info != NULL)
117 {
118 ret = g_list_prepend (ret, info);
119 }
120 else
121 {
122 if (error)
123 {
124 g_critical ("ERROR: %s\n", error->message);
125 }
126 break;
127 }
128 }
129
130 if (error)
131 {
132 g_task_return_error (task, error);
133 }
134 else
135 {
136 ret = g_list_reverse (ret);
137 g_task_return_pointer (task, ret, (GDestroyNotify) next_async_op_free);
138 }
139 }
140
141 static void
142 next_files_async (GFileEnumerator *enumerator,
143 gint num_files,
144 gint io_priority,
145 GCancellable *cancellable,
146 GAsyncReadyCallback callback,
147 gpointer user_data)
148 {
149 // FavoriteVfsFileEnumerator *self = FAVORITE_VFS_FILE_ENUMERATOR (enumerator);
150
151 GTask *task;
152 task = g_task_new (enumerator, cancellable, callback, user_data);
153 g_task_set_priority (task, io_priority);
154 g_task_set_task_data (task, GINT_TO_POINTER (num_files), NULL);
155
156 g_task_run_in_thread (task, next_files_async_thread);
157 g_object_unref (task);
158 }
159
160 static GList *
161 next_files_finished (GFileEnumerator *enumerator,
162 GAsyncResult *result,
163 GError **error)
164 {
165 g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
166 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
167
168 return (GList *) g_task_propagate_pointer (G_TASK (result), error);
169 }
170
171 static gboolean
172 close_fn (GFileEnumerator *enumerator,
173 GCancellable *cancellable,
174 GError **error)
175 {
176 // FavoriteVfsFileEnumerator *self = FAVORITE_VFS_FILE_ENUMERATOR (enumerator);
177
178 return TRUE;
179 }
180
181 static void
182 favorite_vfs_file_enumerator_init (FavoriteVfsFileEnumerator *self)
183 {
184 }
185
186 static void
187 favorite_vfs_file_enumerator_dispose (GObject *object)
188 {
189 G_OBJECT_CLASS (favorite_vfs_file_enumerator_parent_class)->dispose (object);
190 }
191
192 static void
193 favorite_vfs_file_enumerator_finalize (GObject *object)
194 {
195 FavoriteVfsFileEnumerator *self = FAVORITE_VFS_FILE_ENUMERATOR(object);
196 FavoriteVfsFileEnumeratorPrivate *priv = favorite_vfs_file_enumerator_get_instance_private(self);
197
198 g_list_free_full (priv->uris, (GDestroyNotify) g_free);
199 g_free (priv->attributes);
200 g_object_unref (priv->file);
201
202 G_OBJECT_CLASS (favorite_vfs_file_enumerator_parent_class)->finalize (object);
203 }
204
205 static void
206 favorite_vfs_file_enumerator_class_init (FavoriteVfsFileEnumeratorClass *klass)
207 {
208 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
209 GFileEnumeratorClass *enumerator_class = G_FILE_ENUMERATOR_CLASS (klass);
210
211 gobject_class->dispose = favorite_vfs_file_enumerator_dispose;
212 gobject_class->finalize = favorite_vfs_file_enumerator_finalize;
213
214 enumerator_class->next_file = next_file;
215 enumerator_class->next_files_async = next_files_async;
216 enumerator_class->next_files_finish = next_files_finished;
217 enumerator_class->close_fn = close_fn;
218 }
219
220 GFileEnumerator *
221 favorite_vfs_file_enumerator_new (GFile *file,
222 const gchar *attributes,
223 GFileQueryInfoFlags flags,
224 GList *uris)
225 {
226 FavoriteVfsFileEnumerator *enumerator = g_object_new (FAVORITE_TYPE_VFS_FILE_ENUMERATOR, NULL);
227 FavoriteVfsFileEnumeratorPrivate *priv = favorite_vfs_file_enumerator_get_instance_private(enumerator);
228
229 priv->uris = g_list_copy_deep (uris, (GCopyFunc) g_strdup, NULL);
230 priv->current_pos = priv->uris;
231
232 priv->file = g_object_ref (file);
233 priv->attributes = g_strdup (attributes);
234 priv->flags = flags;
235
236 return G_FILE_ENUMERATOR (enumerator);
237 }
238
0 #ifndef FAVORITE_VFS_FILE_ENUMERATOR_H
1 #define FAVORITE_VFS_FILE_ENUMERATOR_H
2
3 #include <glib-object.h>
4 #include <gio/gio.h>
5
6 G_BEGIN_DECLS
7
8 #define FAVORITE_TYPE_VFS_FILE_ENUMERATOR favorite_vfs_file_enumerator_get_type()
9
10 G_DECLARE_FINAL_TYPE (FavoriteVfsFileEnumerator, favorite_vfs_file_enumerator, \
11 FAVORITE, VFS_FILE_ENUMERATOR, \
12 GFileEnumerator)
13
14 GFileEnumerator *
15 favorite_vfs_file_enumerator_new (GFile *file,
16 const gchar *attributes,
17 GFileQueryInfoFlags flags,
18 GList *favorites);
19
20 G_END_DECLS
21
22 #endif // FAVORITE_VFS_FILE_ENUMERATOR_H
0 #include "xapp-favorites.h"
1 #include "favorite-vfs-file.h"
2 #include "favorite-vfs-file-monitor.h"
3
4 typedef struct
5 {
6 gulong changed_handler_id;
7 GHashTable *file_monitors;
8 GList *infos;
9
10 GVolumeMonitor *mount_mon;
11 } FavoriteVfsFileMonitorPrivate;
12
13 struct _FavoriteVfsFileMonitor
14 {
15 GObject parent_instance;
16 FavoriteVfsFileMonitorPrivate *priv;
17 };
18
19 G_DEFINE_TYPE_WITH_PRIVATE(FavoriteVfsFileMonitor, \
20 favorite_vfs_file_monitor, \
21 G_TYPE_FILE_MONITOR)
22
23 GFile *_favorite_vfs_file_new_for_info (XAppFavoriteInfo *info);
24
25 // static void
26 // rename_favorite (GFile *old_file,
27 // GFile *new_file)
28 // {
29 // gchar *old_file_uri, *new_file_uri;
30
31 // old_file_uri = g_file_get_uri (old_file);
32 // new_file_uri = g_file_get_uri (new_file);
33
34 // _xapp_favorites_rename (xapp_favorites_get_default (),
35 // old_file_uri,
36 // new_file_uri);
37
38 // g_free (old_file_uri);
39 // g_free (new_file_uri);
40 // }
41
42 static void
43 favorite_real_file_changed (GFileMonitor *rfmonitor,
44 GFile *file,
45 GFile *other_file,
46 GFileMonitorEvent event_type,
47 gpointer user_data)
48 {
49 // Disabled
50 return;
51
52 // g_return_if_fail (FAVORITE_IS_VFS_FILE_MONITOR (user_data));
53 // FavoriteVfsFileMonitor *monitor = FAVORITE_VFS_FILE_MONITOR (user_data);
54 // FavoriteVfsFileMonitorPrivate *priv = favorite_vfs_file_monitor_get_instance_private (monitor);
55
56 // g_debug ("real file changed: %s: %d", g_file_get_uri (file), event_type);
57
58 // switch (event_type)
59 // {
60 // case G_FILE_MONITOR_EVENT_MOVED_OUT:
61 // break;
62 // {
63 // gchar *uri = g_file_get_uri (file);
64
65 // g_debug ("Deleted: %s\n", uri);
66
67 // xapp_favorites_remove (xapp_favorites_get_default (), uri);
68 // g_free (uri);
69 // }
70
71 // break;
72 // case G_FILE_MONITOR_EVENT_RENAMED:
73 // break;
74 // {
75 // gchar *uri = g_file_get_uri (file);
76
77 // g_debug ("Renamed: %s\n", uri);
78
79 // rename_favorite (file, other_file);
80 // }
81 // break;
82 // case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
83 // case G_FILE_MONITOR_EVENT_CHANGED:
84 // {
85 // gchar *uri = g_file_get_uri (file);
86
87 // GList *iter;
88
89 // for (iter = priv->infos; iter != NULL; iter = iter->next)
90 // {
91 // XAppFavoriteInfo *info = (XAppFavoriteInfo *) iter->data;
92
93 // if (g_strcmp0 (uri, info->uri) == 0)
94 // {
95 // GFile *fav_file;
96 // gchar *uri;
97
98 // uri = path_to_fav_uri (info->display_name);
99 // fav_file = g_file_new_for_uri (uri);
100
101 // g_debug ("Changed: %s", uri);
102 // g_free (uri);
103
104 // g_file_monitor_emit_event (G_FILE_MONITOR (monitor),
105 // fav_file,
106 // NULL,
107 // G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED);
108 // g_file_monitor_emit_event (G_FILE_MONITOR (monitor),
109 // fav_file,
110 // NULL,
111 // G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT);
112 // g_object_unref (fav_file);
113
114 // break;
115 // }
116 // }
117 // }
118 // break;
119 // case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
120 // case G_FILE_MONITOR_EVENT_CREATED:
121 // // case G_FILE_MONITOR_EVENT_CHANGED:
122 // case G_FILE_MONITOR_EVENT_PRE_UNMOUNT:
123 // case G_FILE_MONITOR_EVENT_UNMOUNTED:
124 // case G_FILE_MONITOR_EVENT_MOVED:
125 // case G_FILE_MONITOR_EVENT_MOVED_IN:
126 // case G_FILE_MONITOR_EVENT_DELETED:
127 // break;
128 // default:
129 // g_warn_if_reached ();
130 // }
131 }
132
133 static void
134 unmonitor_files (FavoriteVfsFileMonitor *monitor)
135 {
136 /* Disabled. See below */
137 return;
138
139 FavoriteVfsFileMonitorPrivate *priv = favorite_vfs_file_monitor_get_instance_private (monitor);
140
141 if (priv->file_monitors != NULL)
142 {
143 g_hash_table_destroy (priv->file_monitors);
144 priv->file_monitors = NULL;
145 }
146 }
147
148 static void
149 monitor_files (FavoriteVfsFileMonitor *monitor)
150 {
151
152 /* Disabled - this isn't necessary right now but could be expanded to help
153 * support less integrated apps. */
154 return;
155
156 FavoriteVfsFileMonitorPrivate *priv = favorite_vfs_file_monitor_get_instance_private (monitor);
157 GList *iter;
158
159 priv->file_monitors = g_hash_table_new_full (g_str_hash, g_str_equal,
160 g_free, (GDestroyNotify) g_object_unref);
161
162 for (iter = priv->infos; iter != NULL; iter = iter->next)
163 {
164 XAppFavoriteInfo *info = (XAppFavoriteInfo *) iter->data;
165 GFileMonitor *real_monitor;
166 GFile *real_file;
167 GError *error;
168
169 g_debug ("Monitoring real file: %s\n", info->uri);
170
171 error = NULL;
172 real_file = g_file_new_for_uri (info->uri);
173 real_monitor = g_file_monitor (real_file,
174 G_FILE_MONITOR_WATCH_MOVES,
175 NULL,
176 &error);
177 g_object_unref (real_file);
178
179 if (real_monitor == NULL)
180 {
181 if (error != NULL)
182 {
183 g_warning ("Unable to add file monitor for '%s': %s", info->uri, error->message);
184 g_error_free (error);
185 }
186
187 continue;
188 }
189
190 g_hash_table_insert (priv->file_monitors,
191 (gpointer) g_strdup (info->uri),
192 (gpointer) real_monitor);
193
194 g_signal_connect (real_monitor,
195 "changed",
196 G_CALLBACK (favorite_real_file_changed),
197 monitor);
198 }
199 }
200
201 static gint
202 find_info_by_uri (gconstpointer ptr_a,
203 gconstpointer ptr_b)
204 {
205 XAppFavoriteInfo *info = (XAppFavoriteInfo *) ptr_a;
206 const gchar *uri = (gchar *) ptr_b;
207
208 return g_strcmp0 (info->uri, uri);
209 }
210
211 static void
212 favorites_changed (XAppFavorites *favorites,
213 gpointer user_data)
214 {
215 g_return_if_fail (XAPP_IS_FAVORITES (favorites));
216 g_return_if_fail (FAVORITE_IS_VFS_FILE_MONITOR (user_data));
217
218 FavoriteVfsFileMonitor *monitor = FAVORITE_VFS_FILE_MONITOR (user_data);
219 FavoriteVfsFileMonitorPrivate *priv = favorite_vfs_file_monitor_get_instance_private (monitor);
220 GList *added, *removed;
221 GList *iter, *new_infos;
222
223 if (g_file_monitor_is_cancelled (G_FILE_MONITOR (monitor)))
224 {
225 return;
226 }
227
228 added = removed = NULL;
229
230 new_infos = xapp_favorites_get_favorites (favorites, NULL);
231
232 for (iter = priv->infos; iter != NULL; iter = iter->next)
233 {
234 XAppFavoriteInfo *old_info = (XAppFavoriteInfo *) iter->data;
235 GList *res = g_list_find_custom (new_infos,
236 (gpointer) old_info->uri,
237 (GCompareFunc) find_info_by_uri);
238 if (res == NULL)
239 {
240 removed = g_list_prepend (removed, old_info);
241 }
242 }
243
244 for (iter = new_infos; iter != NULL; iter = iter->next)
245 {
246 XAppFavoriteInfo *new_info = (XAppFavoriteInfo *) iter->data;
247 GList *res = g_list_find_custom (priv->infos,
248 (gpointer) new_info->uri,
249 (GCompareFunc) find_info_by_uri);
250 if (res == NULL)
251 {
252 added = g_list_prepend (added, new_info);
253 }
254 }
255
256 for (iter = added; iter != NULL; iter = iter->next)
257 {
258 XAppFavoriteInfo *added_info = (XAppFavoriteInfo *) iter->data;
259
260 GFile *file = _favorite_vfs_file_new_for_info (added_info);
261
262 g_file_monitor_emit_event (G_FILE_MONITOR (monitor),
263 file,
264 NULL,
265 G_FILE_MONITOR_EVENT_CREATED);
266 g_file_monitor_emit_event (G_FILE_MONITOR (monitor),
267 file,
268 NULL,
269 G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT);
270 g_object_unref (file);
271 }
272
273 for (iter = removed; iter != NULL; iter = iter->next)
274 {
275 XAppFavoriteInfo *removed_info = (XAppFavoriteInfo *) iter->data;
276
277 GFile *file = _favorite_vfs_file_new_for_info (removed_info);
278
279 g_file_monitor_emit_event (G_FILE_MONITOR (monitor),
280 file,
281 NULL,
282 G_FILE_MONITOR_EVENT_DELETED);
283 g_file_monitor_emit_event (G_FILE_MONITOR (monitor),
284 file,
285 NULL,
286 G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT);
287 g_object_unref (file);
288 }
289
290 GList *tmp = priv->infos;
291 priv->infos = new_infos;
292
293 g_list_free_full (tmp, (GDestroyNotify) xapp_favorite_info_free);
294
295 //FIXME: add/remove individually
296 unmonitor_files (monitor);
297 monitor_files (monitor);
298 }
299
300 static void
301 mounts_changed (GVolumeMonitor *mount_mon,
302 GMount *mount,
303 gpointer user_data)
304 {
305 g_return_if_fail (FAVORITE_IS_VFS_FILE_MONITOR (user_data));
306
307 FavoriteVfsFileMonitor *monitor = FAVORITE_VFS_FILE_MONITOR (user_data);
308 FavoriteVfsFileMonitorPrivate *priv = favorite_vfs_file_monitor_get_instance_private (monitor);
309
310 GFile *root;
311 GList *iter, *mount_favorites;
312
313 root = g_mount_get_root (mount);
314 mount_favorites = NULL;
315
316 // Find any favorites that are descendent from root.
317
318 for (iter = priv->infos; iter != NULL; iter = iter->next)
319 {
320 XAppFavoriteInfo *info = (XAppFavoriteInfo *) iter->data;
321 GFile *fav_file = g_file_new_for_uri (info->uri);
322 gchar *relpath;
323
324 relpath = g_file_get_relative_path (root, fav_file);
325
326 if (relpath != NULL)
327 {
328 mount_favorites = g_list_prepend (mount_favorites, info);
329 }
330
331 g_free (relpath);
332 g_object_unref (fav_file);
333 }
334
335 if (mount_favorites != NULL)
336 {
337 for (iter = mount_favorites; iter != NULL; iter = iter->next) {
338 XAppFavoriteInfo *info = (XAppFavoriteInfo *) iter->data;
339 GFile *fav_file;
340 gchar *uri;
341
342 uri = path_to_fav_uri (info->display_name);
343 fav_file = g_file_new_for_uri (uri);
344
345 g_file_monitor_emit_event (G_FILE_MONITOR (monitor),
346 fav_file,
347 NULL,
348 G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED);
349 g_file_monitor_emit_event (G_FILE_MONITOR (monitor),
350 fav_file,
351 NULL,
352 G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT);
353
354 g_free (uri);
355 g_object_unref (fav_file);
356 }
357
358 g_list_free (mount_favorites);
359 }
360
361 g_object_unref (root);
362
363 unmonitor_files (monitor);
364 monitor_files (monitor);
365 }
366
367 static gboolean
368 favorite_vfs_file_monitor_cancel (GFileMonitor* gfilemon)
369 {
370 FavoriteVfsFileMonitor *monitor = FAVORITE_VFS_FILE_MONITOR (gfilemon);
371 FavoriteVfsFileMonitorPrivate *priv = favorite_vfs_file_monitor_get_instance_private (monitor);
372
373 if (priv->changed_handler_id > 0)
374 {
375 g_signal_handler_disconnect (xapp_favorites_get_default (), priv->changed_handler_id);
376 }
377
378 return TRUE;
379 }
380
381 static void
382 favorite_vfs_file_monitor_init (FavoriteVfsFileMonitor *monitor)
383 {
384 FavoriteVfsFileMonitorPrivate *priv = favorite_vfs_file_monitor_get_instance_private (monitor);
385
386 priv->mount_mon = g_volume_monitor_get ();
387 g_signal_connect (priv->mount_mon,
388 "mount-added",
389 G_CALLBACK (mounts_changed),
390 monitor);
391 g_signal_connect (priv->mount_mon,
392 "mount-removed",
393 G_CALLBACK (mounts_changed),
394 monitor);
395
396 priv->infos = xapp_favorites_get_favorites (xapp_favorites_get_default (), NULL);
397 priv->changed_handler_id = g_signal_connect (xapp_favorites_get_default (),
398 "changed",
399 G_CALLBACK (favorites_changed),
400 monitor);
401
402 monitor_files (monitor);
403 }
404
405 static void
406 favorite_vfs_file_monitor_dispose (GObject *object)
407 {
408 FavoriteVfsFileMonitor *monitor = FAVORITE_VFS_FILE_MONITOR(object);
409 FavoriteVfsFileMonitorPrivate *priv = favorite_vfs_file_monitor_get_instance_private(monitor);
410
411 unmonitor_files (monitor);
412
413 g_signal_handlers_disconnect_by_func (priv->mount_mon, mounts_changed, monitor);
414 g_clear_object (&priv->mount_mon);
415
416 if (priv->infos != NULL)
417 {
418 g_list_free_full (priv->infos, (GDestroyNotify) xapp_favorite_info_free);
419 priv->infos = NULL;
420 }
421
422 G_OBJECT_CLASS (favorite_vfs_file_monitor_parent_class)->dispose (object);
423 }
424
425 static void
426 favorite_vfs_file_monitor_finalize (GObject *object)
427 {
428 // FavoriteVfsFileMonitor *self = FAVORITE_VFS_FILE_MONITOR(object);
429 // FavoriteVfsFileMonitorPrivate *priv = favorite_vfs_file_monitor_get_instance_private(self);
430
431 G_OBJECT_CLASS (favorite_vfs_file_monitor_parent_class)->finalize (object);
432 }
433
434 static void
435 favorite_vfs_file_monitor_class_init (FavoriteVfsFileMonitorClass *klass)
436 {
437 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
438 GFileMonitorClass *monitor_class = G_FILE_MONITOR_CLASS (klass);
439
440 gobject_class->dispose = favorite_vfs_file_monitor_dispose;
441 gobject_class->finalize = favorite_vfs_file_monitor_finalize;
442
443 monitor_class->cancel = favorite_vfs_file_monitor_cancel;
444 }
445
446 GFileMonitor *
447 favorite_vfs_file_monitor_new (void)
448 {
449 return G_FILE_MONITOR (g_object_new (FAVORITE_TYPE_VFS_FILE_MONITOR, NULL));
450 }
451
0 #ifndef __FAVORITE_VFS_FILE_MONITOR_H__
1 #define __FAVORITE_VFS_FILE_MONITOR_H__
2
3 #include <gio/gio.h>
4 #include <glib-object.h>
5
6 G_BEGIN_DECLS
7
8 #define FAVORITE_TYPE_VFS_FILE_MONITOR (favorite_vfs_file_monitor_get_type ())
9
10 G_DECLARE_FINAL_TYPE (FavoriteVfsFileMonitor, favorite_vfs_file_monitor,
11 FAVORITE, VFS_FILE_MONITOR, GFileMonitor)
12
13 GFileMonitor *favorite_vfs_file_monitor_new (void);
14
15 G_END_DECLS
16
17 #endif /* __FAVORITE_VFS_FILE_MONITOR_H__ */
0 #include <config.h>
1 #include <glib/gi18n-lib.h>
2
3 #include "favorite-vfs-file.h"
4 #include "favorite-vfs-file-enumerator.h"
5 #include "favorite-vfs-file-monitor.h"
6
7 #define FAVORITES_SCHEMA "org.x.apps.favorites"
8 #define FAVORITE_DCONF_METADATA_KEY "root-metadata"
9
10 static GSettings *settings = NULL;
11
12 typedef struct
13 {
14 gchar *uri; // favorites://foo
15
16 XAppFavoriteInfo *info;
17 } FavoriteVfsFilePrivate;
18
19 struct _FavoriteVfsFile
20 {
21 GObject parent_instance;
22 FavoriteVfsFilePrivate *priv;
23 };
24
25 GList *_xapp_favorites_get_display_names (XAppFavorites *favorites);
26 static void favorite_vfs_file_gfile_iface_init (GFileIface *iface);
27
28 gchar *
29 path_to_fav_uri (const gchar *path)
30 {
31 g_return_val_if_fail (path != NULL, NULL);
32
33 return g_strconcat (ROOT_URI, path, NULL);
34 }
35
36 gchar *
37 fav_uri_to_display_name (const gchar *uri)
38 {
39 g_return_val_if_fail (uri != NULL, NULL);
40 g_return_val_if_fail (g_str_has_prefix (uri, ROOT_URI), NULL);
41
42 const gchar *ptr;
43
44 ptr = uri + strlen (ROOT_URI);
45
46 if (ptr[0] == '/')
47 {
48 ptr++;
49 }
50
51 return g_strdup (ptr);
52 }
53
54 G_DEFINE_TYPE_EXTENDED (FavoriteVfsFile,
55 favorite_vfs_file,
56 G_TYPE_OBJECT,
57 0,
58 G_ADD_PRIVATE (FavoriteVfsFile)
59 G_IMPLEMENT_INTERFACE (G_TYPE_FILE, favorite_vfs_file_gfile_iface_init))
60
61 static gboolean
62 is_root_file (FavoriteVfsFile *file)
63 {
64 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (file);
65
66 return g_strcmp0 (priv->uri, ROOT_URI) == 0;
67 }
68
69 static GFile *
70 file_dup (GFile *file)
71 {
72 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
73
74 return favorite_vfs_file_new_for_uri (priv->uri);
75 }
76
77 static guint
78 file_hash (GFile *file)
79 {
80 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
81
82 return g_str_hash (priv->uri);
83 }
84
85 static gboolean
86 file_equal (GFile *file1,
87 GFile *file2)
88 {
89 FavoriteVfsFilePrivate *priv1 = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file1));
90 FavoriteVfsFilePrivate *priv2 = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file2));
91
92 return g_strcmp0 (priv1->uri, priv2->uri) == 0;
93 }
94
95 static gboolean
96 file_is_native (GFile *file)
97 {
98 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
99
100 if (priv->info != NULL && priv->info->uri != NULL)
101 {
102 GFile *real_file;
103 gboolean is_really_native;
104
105 real_file = g_file_new_for_uri (priv->info->uri);
106 is_really_native = g_file_is_native (real_file);
107
108 g_object_unref (real_file);
109 return is_really_native;
110 }
111
112 return FALSE;
113 }
114
115 static gboolean
116 file_has_uri_scheme (GFile *file,
117 const gchar *uri_scheme)
118 {
119 return g_strcmp0 (uri_scheme, URI_SCHEME) == 0;
120 }
121
122 static gchar *
123 file_get_uri_scheme (GFile *file)
124 {
125 return g_strdup (URI_SCHEME);
126 }
127
128 static gchar *
129 file_get_basename (GFile *file)
130 {
131 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
132
133 if (priv->info == NULL)
134 {
135 return g_strdup ("/");
136 }
137
138 return g_strdup (priv->info->display_name);
139 }
140
141 static gchar *
142 file_get_path (GFile *file)
143 {
144 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
145
146 if (file_is_native (file))
147 {
148 GFile *real_file;
149 gchar *ret;
150
151 real_file = g_file_new_for_uri (priv->info->uri);
152
153 // file can't be native without an info, so we don't need to check for null here
154 ret = g_file_get_path (real_file);
155 g_object_unref (real_file);
156
157 return ret;
158 }
159
160 // GtkFileChooser checks for a path (and not null) before allowing a shortcut to
161 // be added using gtk_file_chooser_add_shortcut_folder_uri(). Even though this / doesn't
162 // make much sense for favorites:/// it allows it to be added to the file chooser without
163 // being forced to override its 'local-only' property.
164 if (is_root_file (FAVORITE_VFS_FILE (file)))
165 {
166 return g_strdup ("/");
167 }
168
169 return NULL;
170 }
171
172 static gchar *
173 file_get_uri (GFile *file)
174 {
175 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
176
177 return g_strdup (priv->uri);
178 }
179
180 static gchar *
181 file_get_parse_name (GFile *file)
182 {
183 return file_get_uri (file);
184 }
185
186 static GFile *
187 file_get_parent (GFile *file)
188 {
189 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
190
191 // We're only ever one level deep.
192 if (priv->info != NULL)
193 {
194 return g_file_new_for_uri (ROOT_URI);
195 }
196
197 return NULL;
198 }
199
200 static gboolean
201 file_prefix_matches (GFile *parent,
202 GFile *descendant)
203 {
204 g_autofree gchar *puri = NULL;
205 g_autofree gchar *duri = NULL;
206 gchar *ptr = NULL;
207
208 puri = g_file_get_uri (parent);
209 duri = g_file_get_uri (descendant);
210
211 ptr = g_strstr_len (puri, -1, duri);
212
213 if ((ptr == puri) && ptr[strlen (duri) + 1] == '/')
214 {
215 return TRUE;
216 }
217
218 return FALSE;
219 }
220
221 static gchar *
222 file_get_relative_path (GFile *parent,
223 GFile *descendant)
224 {
225 g_autofree gchar *puri = NULL;
226 g_autofree gchar *duri = NULL;
227 g_autofree gchar *rpath = NULL;
228 gchar *ptr = NULL;
229
230 puri = g_file_get_uri (parent);
231 duri = g_file_get_uri (descendant);
232
233 ptr = g_strstr_len (puri, -1, duri);
234
235 if ((ptr == puri) && ptr[strlen (duri) + 1] == '/')
236 {
237 rpath = g_strdup (puri + strlen (duri) + 1);
238
239 return rpath;
240 }
241
242 return NULL;
243 }
244
245 static GFile *
246 file_resolve_relative_path (GFile *file,
247 const gchar *relative_path)
248 {
249 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
250 GFile *relative_file;
251 gchar *uri;
252
253 if (g_path_is_absolute (relative_path))
254 {
255 return g_file_new_for_path (relative_path);
256 }
257
258 if (priv->info != NULL && priv->info->uri != NULL)
259 {
260 GFile *real_file;
261 real_file = g_file_new_for_uri (priv->info->uri);
262
263 relative_file = g_file_resolve_relative_path (real_file,
264 relative_path);
265
266 g_object_unref (real_file);
267 return relative_file;
268 }
269
270 if (g_strcmp0 (relative_path, ".") == 0)
271 {
272 relative_file = file_dup (file);
273
274 return relative_file;
275 }
276
277 uri = path_to_fav_uri (relative_path);
278
279 relative_file = g_file_new_for_uri (uri);
280 g_free (uri);
281
282 return relative_file;
283 }
284
285 static GFile *
286 file_get_child_for_display_name (GFile *file,
287 const char *display_name,
288 GError **error)
289 {
290 return g_file_get_child (file, display_name);
291 }
292
293 static GFile *
294 file_set_display_name (GFile *file,
295 const gchar *display_name,
296 GCancellable *cancellable,
297 GError **error)
298 {
299 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
300
301 if (priv->info != NULL && priv->info->uri != NULL)
302 {
303 GFile *real_file;
304 GFile *ret;
305
306 real_file = g_file_new_for_uri (priv->info->uri);
307 ret = g_file_set_display_name (real_file,
308 display_name,
309 cancellable,
310 error);
311 g_object_unref (real_file);
312
313 return ret;
314 }
315
316 g_set_error_literal (error, G_IO_ERROR,
317 G_IO_ERROR_NOT_SUPPORTED,
318 "Can't rename file");
319
320 return NULL;
321 }
322
323 static GFileEnumerator *
324 file_enumerate_children(GFile *file,
325 const char *attributes,
326 GFileQueryInfoFlags flags,
327 GCancellable *cancellable,
328 GError **error)
329 {
330 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
331 GFileEnumerator *enumerator;
332
333 if (priv->info != NULL && priv->info->uri != NULL)
334 {
335 GFile *real_file;
336 real_file = g_file_new_for_uri (priv->info->uri);
337
338 enumerator = g_file_enumerate_children (real_file,
339 attributes,
340 flags,
341 cancellable,
342 error);
343
344 g_object_unref (real_file);
345 return enumerator;
346 }
347
348 GList *uris;
349
350 uris = _xapp_favorites_get_display_names (xapp_favorites_get_default ());
351 enumerator = favorite_vfs_file_enumerator_new (file,
352 attributes,
353 flags,
354 uris);
355
356 g_list_free (uris);
357
358 return enumerator;
359 }
360
361 static GFileInfo *
362 file_query_info (GFile *file,
363 const char *attributes,
364 GFileQueryInfoFlags flags,
365 GCancellable *cancellable,
366 GError **error)
367 {
368 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
369 GFileInfo *info;
370 GIcon *icon;
371
372 if (priv->info != NULL)
373 {
374 if (!priv->info->uri)
375 {
376 if (error != NULL)
377 {
378 *error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "File not found");
379 }
380 return NULL;
381 }
382
383 GFile *real_file = g_file_new_for_uri (priv->info->uri);
384
385 info = g_file_query_info (real_file, attributes, flags, cancellable, error);
386
387 if (info != NULL)
388 {
389 gchar *local_path;
390
391 g_file_info_set_display_name (info, priv->info->display_name);
392 g_file_info_set_name (info, priv->info->display_name);
393 g_file_info_set_is_symlink (info, TRUE);
394
395 local_path = g_file_get_path (real_file);
396
397 if (local_path != NULL)
398 {
399 g_file_info_set_symlink_target (info, local_path);
400 g_free (local_path);
401 }
402 else
403 {
404 g_file_info_set_symlink_target (info, priv->info->uri);
405 }
406
407 // Recent sets this also. If it's set, this uri is used to display the "location"
408 // for the file (the directory in which real file resides).
409 g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI, priv->info->uri);
410
411 g_file_info_set_attribute_string (info, FAVORITE_AVAILABLE_METADATA_KEY, META_TRUE);
412 }
413 else
414 {
415 g_clear_error (error);
416 gchar *content_type;
417
418 info = g_file_info_new ();
419
420 g_file_info_set_display_name (info, priv->info->display_name);
421 g_file_info_set_name (info, priv->info->display_name);
422 g_file_info_set_is_symlink (info, TRUE);
423
424 g_file_info_set_symlink_target (info, priv->info->uri);
425
426 /* Prevent showing a 'thumbnailing' icon */
427 g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED, TRUE);
428
429 /* This will keep the sort position the same for missing or unmounted files */
430 g_file_info_set_attribute_string (info, FAVORITE_METADATA_KEY, META_TRUE);
431 g_file_info_set_attribute_string (info, FAVORITE_AVAILABLE_METADATA_KEY, META_FALSE);
432 g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI, priv->info->uri);
433
434 content_type = g_content_type_from_mime_type (priv->info->cached_mimetype);
435
436 icon = g_content_type_get_icon (content_type);
437 g_file_info_set_icon (info, icon);
438 g_object_unref (icon);
439
440 icon = g_content_type_get_symbolic_icon (content_type);
441 g_file_info_set_symbolic_icon (info, icon);
442 g_object_unref (icon);
443
444 g_free (content_type);
445 }
446
447 g_object_unref (real_file);
448
449 return info;
450 }
451
452 if (is_root_file (FAVORITE_VFS_FILE (file)))
453 {
454 GFileAttributeMatcher *matcher = g_file_attribute_matcher_new (attributes);
455
456 info = g_file_info_new ();
457
458 if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_STANDARD_NAME))
459 g_file_info_set_name (info, "/");
460
461 if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME))
462 g_file_info_set_display_name (info, _("Favorites"));
463
464 if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_STANDARD_TYPE))
465 g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY);
466
467 if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_STANDARD_ICON))
468 {
469 icon = g_themed_icon_new ("xapp-favorites");
470 g_file_info_set_icon (info, icon);
471
472 g_object_unref (icon);
473 }
474
475 if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON))
476 {
477 icon = g_themed_icon_new ("xapp-favorites-symbolic");
478 g_file_info_set_symbolic_icon (info, icon);
479 g_object_unref (icon);
480 }
481
482 if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_GVFS_BACKEND))
483 g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_GVFS_BACKEND, "favorites");
484
485 if (g_file_attribute_matcher_matches (matcher, FAVORITE_AVAILABLE_METADATA_KEY))
486 g_file_info_set_attribute_string (info, FAVORITE_AVAILABLE_METADATA_KEY, META_TRUE);
487
488 if (g_file_attribute_matcher_enumerate_namespace (matcher, "metadata"))
489 {
490 gchar **entries = g_settings_get_strv (settings, FAVORITE_DCONF_METADATA_KEY);
491
492 if (entries != NULL)
493 {
494 gint i;
495
496 for (i = 0; entries[i] != NULL; i++)
497 {
498 gchar **t_n_v;
499
500 t_n_v = g_strsplit (entries[i], "==", 3);
501
502 if (g_strv_length (t_n_v) == 3)
503 {
504 if (g_strcmp0 (t_n_v[0], "string") == 0)
505 {
506 g_file_info_set_attribute_string (info, t_n_v[1], t_n_v[2]);
507 }
508 else
509 if (g_strcmp0 (t_n_v[0], "strv") == 0)
510 {
511 gchar **members = g_strsplit (t_n_v[2], "|", -1);
512
513 g_file_info_set_attribute_stringv (info, t_n_v[1], members);
514
515 g_strfreev (members);
516 }
517 }
518
519 g_strfreev (t_n_v);
520 }
521 }
522
523 g_strfreev (entries);
524 }
525
526 g_file_attribute_matcher_unref (matcher);
527 }
528
529 return info;
530 }
531
532 GFileInfo *
533 file_query_filesystem_info (GFile *file,
534 const char *attributes,
535 GCancellable *cancellable,
536 GError **error)
537 {
538 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
539
540 if (priv->info != NULL && priv->info->uri != NULL)
541 {
542 GFileInfo *info;
543 GFile *real_file;
544 real_file = g_file_new_for_uri (priv->info->uri);
545
546 info = g_file_query_filesystem_info (real_file,
547 attributes,
548 cancellable,
549 error);
550
551 g_object_unref (real_file);
552 return info;
553 }
554
555 GFileInfo *info;
556 GFileAttributeMatcher *matcher;
557
558 info = g_file_info_new ();
559
560 matcher = g_file_attribute_matcher_new (attributes);
561
562 if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE))
563 {
564 g_file_info_set_attribute_string (info,
565 G_FILE_ATTRIBUTE_FILESYSTEM_TYPE, "favorites");
566 }
567
568 if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY))
569 {
570 g_file_info_set_attribute_boolean (info,
571 G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, TRUE);
572 }
573
574 g_file_attribute_matcher_unref (matcher);
575
576 return info;
577 }
578
579 GMount *
580 file_find_enclosing_mount (GFile *file,
581 GCancellable *cancellable,
582 GError **error)
583 {
584 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
585
586 if (priv->info != NULL && priv->info->uri != NULL)
587 {
588 GMount *mount;
589 GFile *real_file;
590 real_file = g_file_new_for_uri (priv->info->uri);
591
592 mount = g_file_find_enclosing_mount (real_file,
593 cancellable,
594 error);
595
596 g_object_unref (real_file);
597 return mount;
598 }
599
600 g_set_error_literal (error, G_IO_ERROR,
601 G_IO_ERROR_NOT_SUPPORTED,
602 "Can't find favorite file enclosing mount");
603
604 return NULL;
605 }
606
607 GFileAttributeInfoList *
608 file_query_settable_attributes (GFile *file,
609 GCancellable *cancellable,
610 GError **error)
611 {
612 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
613
614 if (priv->info != NULL && priv->info->uri != NULL)
615 {
616 GFileAttributeInfoList *list;
617 GFile *real_file;
618 real_file = g_file_new_for_uri (priv->info->uri);
619
620 list = g_file_query_settable_attributes (real_file,
621 cancellable,
622 error);
623
624 g_object_unref (real_file);
625 return list;
626 }
627
628 return g_file_attribute_info_list_new ();
629 }
630
631 GFileAttributeInfoList *
632 file_query_writable_namespaces (GFile *file,
633 GCancellable *cancellable,
634 GError **error)
635 {
636 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
637 GFileAttributeInfoList *list;
638
639 if (priv->info != NULL && priv->info->uri != NULL)
640 {
641 GFile *real_file;
642 real_file = g_file_new_for_uri (priv->info->uri);
643
644 list = g_file_query_writable_namespaces (real_file,
645 cancellable,
646 error);
647
648 g_object_unref (real_file);
649 return list;
650 }
651
652 list = g_file_attribute_info_list_new ();
653
654 g_file_attribute_info_list_add (list,
655 "metadata",
656 G_FILE_ATTRIBUTE_TYPE_STRING,
657 G_FILE_ATTRIBUTE_INFO_NONE);
658
659 return list;
660 }
661
662 static void
663 remove_root_metadata (const gchar *attr_name)
664 {
665 GPtrArray *new_array;
666 gchar **old_metadata, **new_metadata;
667 gint i;
668
669 old_metadata = g_settings_get_strv (settings, FAVORITE_DCONF_METADATA_KEY);
670
671 if (old_metadata == NULL)
672 {
673 return;
674 }
675
676 new_array = g_ptr_array_new ();
677
678 for (i = 0; old_metadata[i] != NULL; i++)
679 {
680 gchar **t_n_v;
681
682 t_n_v = g_strsplit (old_metadata[i], "==", 3);
683
684 if (g_strcmp0 (t_n_v[1], attr_name) != 0)
685 {
686 g_ptr_array_add (new_array, g_strdup (old_metadata[i]));
687 }
688
689 g_strfreev (t_n_v);
690 }
691
692 g_ptr_array_add (new_array, NULL);
693 g_strfreev (old_metadata);
694
695 new_metadata = (gchar **) g_ptr_array_free (new_array, FALSE);
696
697 g_settings_set_strv (settings, FAVORITE_DCONF_METADATA_KEY, (const gchar * const *) new_metadata);
698 g_strfreev (new_metadata);
699 }
700
701 static void
702 set_or_update_root_metadata (const gchar *attr_name,
703 const gpointer value,
704 GFileAttributeType type)
705 {
706 GPtrArray *new_array;
707 gchar **old_metadata, **new_metadata;
708 gint i;
709 gchar *entry;
710 gboolean exists;
711
712 old_metadata = g_settings_get_strv (settings, FAVORITE_DCONF_METADATA_KEY);
713
714 if (old_metadata == NULL)
715 {
716 return;
717 }
718
719 switch (type)
720 {
721 case G_FILE_ATTRIBUTE_TYPE_STRING:
722 {
723 entry = g_strdup_printf ("string==%s==%s", attr_name, (gchar *) value);
724 break;
725 }
726 case G_FILE_ATTRIBUTE_TYPE_STRINGV:
727 {
728 gchar *val_strv = g_strjoinv ("|", (gchar **) value);
729 entry = g_strdup_printf ("strv==%s==%s", attr_name, val_strv);
730 g_free (val_strv);
731 break;
732 }
733 default:
734 break;
735 }
736
737 exists = FALSE;
738 new_array = g_ptr_array_new ();
739
740 for (i = 0; old_metadata[i] != NULL; i++)
741 {
742 gchar **t_n_v;
743
744 t_n_v = g_strsplit (old_metadata[i], "==", 3);
745
746 if (g_strcmp0 (t_n_v[1], attr_name) == 0)
747 {
748 g_ptr_array_add (new_array, entry);
749 exists = TRUE;
750 }
751 else
752 {
753 g_ptr_array_add (new_array, g_strdup (old_metadata[i]));
754 }
755
756 g_strfreev (t_n_v);
757 }
758
759 if (!exists)
760 {
761 g_ptr_array_add (new_array, entry);
762 }
763
764 g_ptr_array_add (new_array, NULL);
765 g_strfreev (old_metadata);
766
767 new_metadata = (gchar **) g_ptr_array_free (new_array, FALSE);
768
769 g_settings_set_strv (settings, FAVORITE_DCONF_METADATA_KEY, (const gchar * const *) new_metadata);
770 g_strfreev (new_metadata);
771 }
772
773 gboolean
774 file_set_attribute (GFile *file,
775 const gchar *attribute,
776 GFileAttributeType type,
777 gpointer value_p,
778 GFileQueryInfoFlags flags,
779 GCancellable *cancellable,
780 GError **error)
781 {
782 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
783 gboolean ret;
784
785 if (priv->info != NULL && priv->info->uri != NULL)
786 {
787 GFile *real_file;
788 gboolean ret;
789 real_file = g_file_new_for_uri (priv->info->uri);
790
791 ret = g_file_set_attribute (real_file,
792 attribute,
793 type,
794 value_p,
795 flags,
796 cancellable,
797 error);
798
799 g_object_unref (real_file);
800 return ret;
801 }
802
803 ret = FALSE;
804
805 if (!is_root_file (FAVORITE_VFS_FILE (file)))
806 {
807 g_set_error (error, G_IO_ERROR,
808 G_IO_ERROR_NOT_SUPPORTED,
809 "Can't set attributes for %s - only the root (favorites:///) is supported.", priv->uri);
810 }
811 else
812 {
813 if (g_str_has_prefix (attribute, "metadata"))
814 {
815 if (type == G_FILE_ATTRIBUTE_TYPE_INVALID || value_p == NULL || ((char *) value_p)[0] == '\0')
816 {
817 // unset metadata
818 remove_root_metadata (attribute);
819 ret = TRUE;
820 }
821 else
822 {
823 if (type == G_FILE_ATTRIBUTE_TYPE_STRING || type == G_FILE_ATTRIBUTE_TYPE_STRINGV)
824 {
825 set_or_update_root_metadata (attribute, (gchar *) value_p, type);
826 ret = TRUE;
827 }
828 else
829 {
830 g_set_error (error, G_IO_ERROR,
831 G_IO_ERROR_NOT_SUPPORTED,
832 "Can't set attribute '%s' for favorites:/// file "
833 "(only string-type metadata are allowed).", attribute);
834 }
835 }
836 }
837 else
838 {
839 g_set_error (error, G_IO_ERROR,
840 G_IO_ERROR_NOT_SUPPORTED,
841 "Can't set attribute '%s' for favorites:/// file "
842 "(only 'metadata' namespace is allowed).", attribute);
843 }
844 }
845
846 return ret;
847 }
848
849 static gboolean
850 file_set_attributes_from_info (GFile *file,
851 GFileInfo *info,
852 GFileQueryInfoFlags flags,
853 GCancellable *cancellable,
854 GError **error)
855 {
856 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
857 gboolean res;
858
859 if (priv->info != NULL && priv->info->uri != NULL)
860 {
861 GFile *real_file;
862 gboolean ret = FALSE;
863 real_file = g_file_new_for_uri (priv->info->uri);
864
865 ret = g_file_set_attributes_from_info (real_file, info, flags, cancellable, error);
866
867 g_object_unref (real_file);
868 return ret;
869 }
870
871 res = TRUE;
872
873 if (g_file_info_has_namespace (info, "metadata"))
874 {
875 GFileAttributeType type;
876 gchar **attributes;
877 gpointer value_p;
878 gint i;
879
880 attributes = g_file_info_list_attributes (info, "metadata");
881
882 for (i = 0; attributes[i] != NULL; i++)
883 {
884 if (g_file_info_get_attribute_data (info, attributes[i], &type, &value_p, NULL))
885 {
886 if (!file_set_attribute (file,
887 attributes[i],
888 type,
889 value_p,
890 flags,
891 cancellable,
892 error))
893 {
894 g_file_info_set_attribute_status (info, attributes[i], G_FILE_ATTRIBUTE_STATUS_ERROR_SETTING);
895 error = NULL; // from gvfs gdaemonvfs.c - ignore subsequent errors iterating thru attribute list.
896 res = FALSE;
897 }
898 else
899 {
900 g_file_info_set_attribute_status (info, attributes[i], G_FILE_ATTRIBUTE_STATUS_SET);
901 }
902 }
903 }
904
905 g_strfreev (attributes);
906 }
907
908 return res;
909 }
910
911 static GFileInputStream *
912 file_read_fn (GFile *file,
913 GCancellable *cancellable,
914 GError **error)
915 {
916 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
917
918 if (priv->info != NULL && priv->info->uri != NULL)
919 {
920 GFile *real_file = g_file_new_for_uri (priv->info->uri);
921
922 GFileInputStream *stream;
923
924 stream = g_file_read (real_file, cancellable, error);
925
926 g_object_unref (real_file);
927 return stream;
928 }
929
930 g_set_error_literal (error, G_IO_ERROR,
931 G_IO_ERROR_NOT_SUPPORTED,
932 _("Operation not supported"));
933
934 return NULL;
935 }
936
937 GFileOutputStream *
938 file_append_to (GFile *file,
939 GFileCreateFlags flags,
940 GCancellable *cancellable,
941 GError **error)
942 {
943 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
944
945 if (priv->info != NULL && priv->info->uri != NULL)
946 {
947 GFile *real_file = g_file_new_for_uri (priv->info->uri);
948
949 GFileOutputStream *stream;
950
951 stream = g_file_append_to (real_file,
952 flags,
953 cancellable,
954 error);
955
956 g_object_unref (real_file);
957 return stream;
958 }
959
960 g_set_error_literal (error, G_IO_ERROR,
961 G_IO_ERROR_NOT_SUPPORTED,
962 _("Operation not supported"));
963 return NULL;
964 }
965
966 GFileOutputStream *
967 file_create (GFile *file,
968 GFileCreateFlags flags,
969 GCancellable *cancellable,
970 GError **error)
971 {
972 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
973
974 if (priv->info != NULL && priv->info->uri != NULL)
975 {
976 GFile *real_file = g_file_new_for_uri (priv->info->uri);
977
978 GFileOutputStream *stream;
979
980 stream = g_file_create (real_file,
981 flags,
982 cancellable,
983 error);
984
985 g_object_unref (real_file);
986 return stream;
987 }
988
989 g_set_error_literal (error, G_IO_ERROR,
990 G_IO_ERROR_NOT_SUPPORTED,
991 _("Operation not supported"));
992
993 return NULL;
994 }
995
996 static GFileOutputStream *
997 file_replace (GFile *file,
998 const char *etag,
999 gboolean make_backup,
1000 GFileCreateFlags flags,
1001 GCancellable *cancellable,
1002 GError **error)
1003 {
1004 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
1005
1006 if (priv->info != NULL && priv->info->uri != NULL)
1007 {
1008 GFile *real_file = g_file_new_for_uri (priv->info->uri);
1009
1010 GFileOutputStream *stream;
1011
1012 stream = g_file_replace (real_file,
1013 etag,
1014 make_backup,
1015 flags,
1016 cancellable,
1017 error);
1018
1019 g_object_unref (real_file);
1020 return stream;
1021 }
1022
1023 g_set_error_literal (error, G_IO_ERROR,
1024 G_IO_ERROR_NOT_SUPPORTED,
1025 _("Operation not supported"));
1026
1027 return NULL;
1028 }
1029
1030 static GFileIOStream *
1031 file_open_readwrite (GFile *file,
1032 GCancellable *cancellable,
1033 GError **error)
1034 {
1035 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
1036
1037 if (priv->info != NULL && priv->info->uri != NULL)
1038 {
1039 GFileIOStream *res;
1040 GFile *real_file = g_file_new_for_uri (priv->info->uri);
1041
1042 res = g_file_open_readwrite (real_file,
1043 cancellable,
1044 error);
1045
1046 g_object_unref (real_file);
1047 return res;
1048 }
1049
1050 g_set_error_literal (error, G_IO_ERROR,
1051 G_IO_ERROR_NOT_SUPPORTED,
1052 _("Operation not supported"));
1053
1054 return NULL;
1055 }
1056
1057 static GFileIOStream *
1058 file_create_readwrite (GFile *file,
1059 GFileCreateFlags flags,
1060 GCancellable *cancellable,
1061 GError **error)
1062 {
1063 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
1064
1065 if (priv->info != NULL && priv->info->uri != NULL)
1066 {
1067 GFileIOStream *res;
1068 GFile *real_file = g_file_new_for_uri (priv->info->uri);
1069
1070 res = g_file_create_readwrite (real_file,
1071 flags,
1072 cancellable,
1073 error);
1074
1075 g_object_unref (real_file);
1076 return res;
1077 }
1078
1079 g_set_error_literal (error, G_IO_ERROR,
1080 G_IO_ERROR_NOT_SUPPORTED,
1081 _("Operation not supported"));
1082
1083 return NULL;
1084 }
1085
1086 static GFileIOStream *
1087 file_replace_readwrite (GFile *file,
1088 const char *etag,
1089 gboolean make_backup,
1090 GFileCreateFlags flags,
1091 GCancellable *cancellable,
1092 GError **error)
1093 {
1094 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
1095
1096 if (priv->info != NULL && priv->info->uri != NULL)
1097 {
1098 GFileIOStream *res;
1099 GFile *real_file = g_file_new_for_uri (priv->info->uri);
1100
1101 res = g_file_replace_readwrite (real_file,
1102 etag,
1103 make_backup,
1104 flags,
1105 cancellable,
1106 error);
1107
1108 g_object_unref (real_file);
1109 return res;
1110 }
1111
1112 g_set_error_literal (error, G_IO_ERROR,
1113 G_IO_ERROR_NOT_SUPPORTED,
1114 _("Operation not supported"));
1115
1116 return NULL;
1117 }
1118
1119 static gboolean
1120 file_delete (GFile *file,
1121 GCancellable *cancellable,
1122 GError **error)
1123 {
1124 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
1125
1126 if (priv->info != NULL && priv->info->uri != NULL)
1127 {
1128 gboolean res;
1129 GFile *real_file = g_file_new_for_uri (priv->info->uri);
1130
1131 res = g_file_delete (real_file,
1132 cancellable,
1133 error);
1134
1135 g_object_unref (real_file);
1136 return res;
1137 }
1138
1139 g_set_error_literal (error, G_IO_ERROR,
1140 G_IO_ERROR_NOT_SUPPORTED,
1141 _("Operation not supported"));
1142
1143 return FALSE;
1144 }
1145
1146 static gboolean
1147 file_trash (GFile *file,
1148 GCancellable *cancellable,
1149 GError **error)
1150 {
1151 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
1152
1153 if (priv->info != NULL && priv->info->uri != NULL)
1154 {
1155 gboolean res;
1156 GFile *real_file = g_file_new_for_uri (priv->info->uri);
1157
1158 res = g_file_trash (real_file,
1159 cancellable,
1160 error);
1161 g_object_unref (real_file);
1162
1163 return res;
1164 }
1165
1166 g_set_error_literal (error, G_IO_ERROR,
1167 G_IO_ERROR_NOT_SUPPORTED,
1168 "Not supported");
1169
1170 return FALSE;
1171 }
1172
1173 gboolean
1174 file_move (GFile *source,
1175 GFile *destination,
1176 GFileCopyFlags flags,
1177 GCancellable *cancellable,
1178 GFileProgressCallback progress_callback,
1179 gpointer progress_callback_data,
1180 GError **error)
1181 {
1182 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (source));
1183
1184 if (priv->info != NULL && priv->info->uri != NULL)
1185 {
1186 gboolean res;
1187 GFile *real_file = g_file_new_for_uri (priv->info->uri);
1188
1189 res = g_file_move (real_file,
1190 destination,
1191 flags,
1192 cancellable,
1193 progress_callback,
1194 progress_callback_data,
1195 error);
1196
1197 g_object_unref (real_file);
1198 return res;
1199 }
1200
1201 g_set_error_literal (error, G_IO_ERROR,
1202 G_IO_ERROR_NOT_SUPPORTED,
1203 _("Operation not supported"));
1204
1205 return FALSE;
1206 }
1207
1208 static GFileMonitor *
1209 file_monitor_dir (GFile *file,
1210 GFileMonitorFlags flags,
1211 GCancellable *cancellable,
1212 GError **error)
1213 {
1214 FavoriteVfsFilePrivate *priv = favorite_vfs_file_get_instance_private (FAVORITE_VFS_FILE (file));
1215
1216 if (priv->info != NULL && priv->info->uri != NULL)
1217 {
1218 GFile *real_file;
1219 GFileMonitor *monitor;
1220
1221 real_file = g_file_new_for_uri (priv->info->uri);
1222 monitor = g_file_monitor_directory (real_file,
1223 flags,
1224 cancellable,
1225 error);
1226 g_object_unref (real_file);
1227
1228 return monitor;
1229 }