Compare commits
176 Commits
2.91.5
...
workspace-
Author | SHA1 | Date | |
---|---|---|---|
87ce301faa | |||
1ab526dc64 | |||
c11162f794 | |||
8e5d613bfa | |||
8786da0044 | |||
3d5cb0f30a | |||
fb28f77c85 | |||
58c8006f1f | |||
277cff3013 | |||
cde3ce2e27 | |||
57a4ad2d00 | |||
8bc0caa21b | |||
ae478c2344 | |||
0dfdc9371e | |||
ac92d0678b | |||
bd9e6a3bdf | |||
2ce93ce39e | |||
5b95ccae5f | |||
0310f07eab | |||
e3acaa05be | |||
91d8a32f25 | |||
457c7adf59 | |||
8ebdb7f493 | |||
6c55ca59b0 | |||
0e4a47c0aa | |||
33100cd204 | |||
39a8243f27 | |||
5f50922d32 | |||
1137ca0fce | |||
36f3429ad2 | |||
703092f2c9 | |||
fd75c7c7b4 | |||
8abbd5dacb | |||
ed0fa7e1b7 | |||
15f1245927 | |||
25434e42d0 | |||
d6749589e8 | |||
8fea88879a | |||
d9e778f501 | |||
885b6ffaef | |||
4c64920f45 | |||
7369ea6125 | |||
20b7d34577 | |||
6cc4c33b13 | |||
5abf9a0425 | |||
17a0b27109 | |||
2bcdae4d5d | |||
0244c6d5b8 | |||
bc6be40fdd | |||
8c22b58611 | |||
074fe3ea70 | |||
5666fdefce | |||
e9613b0340 | |||
8a030e8fc4 | |||
9c23bf02bd | |||
8468fe87eb | |||
9617e83d88 | |||
912a30c566 | |||
2cd84da835 | |||
64fad9a394 | |||
3b797b32bc | |||
f6ae48ec70 | |||
61869d7db1 | |||
e2e90a550e | |||
80ceead18d | |||
ed8884e192 | |||
3f6165799f | |||
d2a40d6885 | |||
eb8fc738af | |||
b9e1d917da | |||
f721e80685 | |||
361a115729 | |||
d107b84be4 | |||
4cb967f3ac | |||
6f070319a0 | |||
13edecde6c | |||
75d1230dd1 | |||
779d5462f2 | |||
03757c1fcb | |||
1faee65a68 | |||
f7ab90b93b | |||
a7fa7d748d | |||
2b6d4ff279 | |||
06cea89dae | |||
260ca64e94 | |||
6dc4adfc13 | |||
e727c184ef | |||
412c50b939 | |||
8dcd70edbe | |||
1b383c7285 | |||
e96a90b161 | |||
d64d491f63 | |||
a6da22fa70 | |||
56cf7a6628 | |||
5b71788a84 | |||
39f7aa8457 | |||
c6baee2622 | |||
20f49e8c89 | |||
d6a6e6220a | |||
3b333c37fd | |||
289d577bc1 | |||
00ba937171 | |||
df3560143d | |||
bdeb20f7c9 | |||
1dd35b7d08 | |||
450291b856 | |||
125adb4d32 | |||
13cc58937e | |||
ee6a852996 | |||
2cfe978e1f | |||
0625655456 | |||
39a1f5cfe0 | |||
961fdd861f | |||
28adc03cce | |||
68c482ec32 | |||
a739f89dd1 | |||
5c7042cff3 | |||
255d4634a9 | |||
cb4c2ab824 | |||
4c449124ee | |||
c74536c9b3 | |||
df10ef532f | |||
6e18d18a81 | |||
4bc078b5fd | |||
cf49882e96 | |||
b0c6cf3fc5 | |||
883f51be93 | |||
ad52d783bd | |||
05f9be046f | |||
26aaecc33d | |||
f91138d0a2 | |||
89d89ae1cf | |||
e67fbcdc79 | |||
f4572eedd0 | |||
988b515ad2 | |||
2205a395e7 | |||
108b582f0d | |||
6ebd808e8b | |||
343c1133f4 | |||
fea2044eb8 | |||
6b353ece82 | |||
5b3f40102f | |||
b2ab3de80e | |||
56f6c9c5f6 | |||
39b0c88c76 | |||
1fca8a8b95 | |||
d442494f3a | |||
1f1fe36b89 | |||
d21f04b8b4 | |||
e73e4375b8 | |||
2905b0318d | |||
ab1ecb5ba2 | |||
47b8d16067 | |||
dc020628b5 | |||
bed063eea1 | |||
ed76e52918 | |||
e0f58c615b | |||
a681a2ba02 | |||
856207c154 | |||
00d897f282 | |||
49a09657c5 | |||
38fb51a99e | |||
99a865fb0f | |||
b919dd7271 | |||
9ddf19a1a4 | |||
23353fb77a | |||
8bdfb8df68 | |||
a65a0f03d4 | |||
7322a4e4ef | |||
870be026d8 | |||
e4fc899aca | |||
5412ce276c | |||
6200daa5bb | |||
4207536377 | |||
90e042e30c | |||
4e45e28ea0 |
33
configure.ac
33
configure.ac
@ -1,11 +1,14 @@
|
||||
AC_PREREQ(2.63)
|
||||
AC_INIT([gnome-shell],[2.91.5],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
|
||||
AC_INIT([gnome-shell],[2.91.6],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_SRCDIR([src/shell-global.c])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_AUX_DIR([config])
|
||||
|
||||
AC_SUBST([PACKAGE_NAME], ["$PACKAGE_NAME"])
|
||||
AC_SUBST([PACKAGE_VERSION], ["$PACKAGE_VERSION"])
|
||||
|
||||
AM_INIT_AUTOMAKE([1.10 dist-bzip2 no-dist-gzip foreign])
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
@ -57,16 +60,21 @@ fi
|
||||
|
||||
AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
|
||||
|
||||
CLUTTER_MIN_VERSION=1.5.8
|
||||
GOBJECT_INTROSPECTION_MIN_VERSION=0.6.11
|
||||
GJS_MIN_VERSION=0.7
|
||||
CLUTTER_MIN_VERSION=1.5.15
|
||||
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
|
||||
GJS_MIN_VERSION=0.7.8
|
||||
MUTTER_MIN_VERSION=2.91.4
|
||||
GTK_MIN_VERSION=2.91.7
|
||||
GIO_MIN_VERSION=2.25.9
|
||||
LIBECAL_REQUIRED=1.6.0
|
||||
LIBEDATASERVER_REQUIRED=1.2.0
|
||||
LIBEDATASERVERUI2_REQUIRED=1.2.0
|
||||
LIBEDATASERVERUI3_REQUIRED=2.91.6
|
||||
|
||||
|
||||
# Collect more than 20 libraries for a prize!
|
||||
PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION
|
||||
gio-unix-2.0 dbus-glib-1
|
||||
gio-unix-2.0 dbus-glib-1 libxml-2.0
|
||||
gtk+-3.0 >= $GTK_MIN_VERSION
|
||||
mutter-plugins >= $MUTTER_MIN_VERSION
|
||||
gjs-internals-1.0 >= $GJS_MIN_VERSION
|
||||
@ -78,6 +86,10 @@ PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION
|
||||
gobject-introspection-1.0 >= $GOBJECT_INTROSPECTION_MIN_VERSION
|
||||
libcanberra)
|
||||
|
||||
GJS_VERSION=`$PKG_CONFIG --modversion gjs-internals-1.0`
|
||||
AC_DEFINE_UNQUOTED([GJS_VERSION], ["$GJS_VERSION"], [The version of GJS we're linking to])
|
||||
AC_SUBST([GJS_VERSION], ["$GJS_VERSION"])
|
||||
|
||||
saved_CFLAGS=$CFLAGS
|
||||
saved_LIBS=$LIBS
|
||||
CFLAGS=$MUTTER_PLUGIN_CFLAGS
|
||||
@ -87,7 +99,6 @@ AC_CHECK_FUNCS(JS_NewGlobalObject sn_startup_sequence_get_application_id)
|
||||
CFLAGS=$saved_CFLAGS
|
||||
LIBS=$saved_LIBS
|
||||
|
||||
PKG_CHECK_MODULES(TIDY, clutter-1.0)
|
||||
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 gnome-desktop-3.0 >= 2.90.0)
|
||||
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-3.0)
|
||||
PKG_CHECK_MODULES(TRAY, gtk+-3.0)
|
||||
@ -107,6 +118,16 @@ PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 2.90.0],
|
||||
AC_SUBST([HAVE_BLUETOOTH],[0])
|
||||
AC_MSG_RESULT([no])])
|
||||
|
||||
# Default to libedataserverui-3.0, but allow falling back to 1.2
|
||||
PKG_CHECK_EXISTS(libedataserverui-3.0,
|
||||
[EDS_API=3.0
|
||||
LIBEDATASERVERUI_REQUIRED=$LIBEDATASERVERUI3_REQUIRED],
|
||||
[EDS_API=1.2
|
||||
LIBEDATASERVERUI_REQUIRED=$LIBEDATASERVERUI2_REQUIRED])
|
||||
PKG_CHECK_MODULES(LIBECAL, libecal-1.2 >= $LIBECAL_REQUIRED libedataserver-1.2 >= $LIBEDATASERVER_REQUIRED libedataserverui-$EDS_API >= $LIBEDATASERVERUI_REQUIRED)
|
||||
AC_SUBST(LIBECAL_CFLAGS)
|
||||
AC_SUBST(LIBECAL_LIBS)
|
||||
|
||||
MUTTER_BIN_DIR=`$PKG_CONFIG --variable=exec_prefix mutter-plugins`/bin
|
||||
# FIXME: metacity-plugins.pc should point directly to its .gir file
|
||||
MUTTER_LIB_DIR=`$PKG_CONFIG --variable=libdir mutter-plugins`
|
||||
|
@ -12,6 +12,11 @@ desktop_DATA = gnome-shell.desktop
|
||||
%.desktop:%.desktop.in
|
||||
$(AM_V_GEN) sed s/^_// < $< > $@ || rm $@
|
||||
|
||||
searchprovidersdir = $(pkgdatadir)/search_providers
|
||||
dist_searchproviders_DATA = \
|
||||
search_providers/google.xml \
|
||||
search_providers/wikipedia.xml
|
||||
|
||||
imagesdir = $(pkgdatadir)/images
|
||||
dist_images_DATA = \
|
||||
close-black.svg \
|
||||
@ -19,19 +24,18 @@ dist_images_DATA = \
|
||||
|
||||
themedir = $(pkgdatadir)/theme
|
||||
dist_theme_DATA = \
|
||||
theme/add-workspace.svg \
|
||||
theme/calendar-arrow-left.svg \
|
||||
theme/calendar-arrow-right.svg \
|
||||
theme/close-window.svg \
|
||||
theme/close.svg \
|
||||
theme/corner-ripple.png \
|
||||
theme/dash-placeholder.svg \
|
||||
theme/dialog-error.svg \
|
||||
theme/filter-selected.svg \
|
||||
theme/gnome-shell.css \
|
||||
theme/mosaic-view-active.svg \
|
||||
theme/mosaic-view.svg \
|
||||
theme/move-window-on-new.svg \
|
||||
theme/process-working.png \
|
||||
theme/remove-workspace.svg \
|
||||
theme/running-indicator.svg \
|
||||
theme/scroll-button-down-hover.png \
|
||||
theme/scroll-button-down.png \
|
||||
|
@ -7,7 +7,7 @@ X-GNOME-Bugzilla-Bugzilla=GNOME
|
||||
X-GNOME-Bugzilla-Product=gnome-shell
|
||||
X-GNOME-Bugzilla-Component=general
|
||||
X-GNOME-Bugzilla-Version=@VERSION@
|
||||
Categories=GNOME;GTK;Utility;Core;
|
||||
Categories=GNOME;GTK;Core;
|
||||
OnlyShowIn=GNOME;
|
||||
NoDisplay=true
|
||||
X-GNOME-Autostart-Phase=WindowManager
|
||||
|
@ -77,10 +77,6 @@
|
||||
<OnlyUnallocated/>
|
||||
<Include>
|
||||
<And>
|
||||
<Or>
|
||||
<Category>Documentation</Category>
|
||||
<Not><Category>Core</Category></Not>
|
||||
</Or>
|
||||
<Not><Category>Settings</Category></Not>
|
||||
<Not><Category>Screensaver</Category></Not>
|
||||
</And>
|
||||
|
@ -37,6 +37,10 @@
|
||||
will be displayed in the favorites area.
|
||||
</_description>
|
||||
</key>
|
||||
<key name="disabled-open-search-providers" type="as">
|
||||
<default>[]</default>
|
||||
<_summary>disabled OpenSearch providers</_summary>
|
||||
</key>
|
||||
<key name="command-history" type="as">
|
||||
<default>[]</default>
|
||||
<_summary>History for command (Alt-F2) dialog</_summary>
|
||||
@ -97,11 +101,13 @@
|
||||
take care of its own output - this might be used to send the output
|
||||
to an icecast server via shout2send or similar. When unset or set
|
||||
to an empty value, the default pipeline will be used. This is currently
|
||||
'videorate ! theoraenc ! oggmux' and records to Ogg Theora.
|
||||
'videorate ! vp8enc quality=10 speed=2 threads=%T ! queue ! webmmux'
|
||||
and records to WEBM using the VP8 codec. %T is used as a placeholder
|
||||
for a guess at the optimal thread count on the system.
|
||||
</_description>
|
||||
</key>
|
||||
<key name="file-extension" type="s">
|
||||
<default>'ogv'</default>
|
||||
<default>'webm'</default>
|
||||
<_summary>File extension used for storing the screencast</_summary>
|
||||
<_description>
|
||||
The filename for recorded screencasts will be a unique filename
|
||||
|
7
data/search_providers/google.xml
Normal file
7
data/search_providers/google.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
|
||||
<ShortName>Google</ShortName>
|
||||
<Description>Google Search</Description>
|
||||
<InputEncoding>UTF-8</InputEncoding>
|
||||
<Image width="16" height="16">data:image/x-icon;base64,AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs9Pt8xetPtu9FsfFNtu%2BTzvb2%2B%2Fne4dFJeBw0egA%2FfAJAfAA8ewBBegAAAAD%2B%2FPtft98Mp%2BwWsfAVsvEbs%2FQeqvF8xO7%2F%2F%2F63yqkxdgM7gwE%2FggM%2BfQA%2BegBDeQDe7PIbotgQufcMufEPtfIPsvAbs%2FQvq%2Bfz%2Bf%2F%2B%2B%2FZKhR05hgBBhQI8hgBAgAI9ewD0%2B%2Fg3pswAtO8Cxf4Kw%2FsJvvYAqupKsNv%2B%2Fv7%2F%2FP5VkSU0iQA7jQA9hgBDgQU%2BfQH%2F%2Ff%2FQ6fM4sM4KsN8AteMCruIqqdbZ7PH8%2Fv%2Fg6Nc%2Fhg05kAA8jAM9iQI%2BhQA%2BgQDQu6b97uv%2F%2F%2F7V8Pqw3eiWz97q8%2Ff%2F%2F%2F%2F7%2FPptpkkqjQE4kwA7kAA5iwI8iAA8hQCOSSKdXjiyflbAkG7u2s%2F%2B%2F%2F39%2F%2F7r8utrqEYtjQE8lgA7kwA7kwA9jwA9igA9hACiWSekVRyeSgiYSBHx6N%2F%2B%2Fv7k7OFRmiYtlAA5lwI7lwI4lAA7kgI9jwE9iwI4iQCoVhWcTxCmb0K%2BooT8%2Fv%2F7%2F%2F%2FJ2r8fdwI1mwA3mQA3mgA8lAE8lAE4jwA9iwE%2BhwGfXifWvqz%2B%2Ff%2F58u%2Fev6Dt4tr%2B%2F%2F2ZuIUsggA7mgM6mAM3lgA5lgA6kQE%2FkwBChwHt4dv%2F%2F%2F728ei1bCi7VAC5XQ7kz7n%2F%2F%2F6bsZkgcB03lQA9lgM7kwA2iQktZToPK4r9%2F%2F%2F9%2F%2F%2FSqYK5UwDKZAS9WALIkFn%2B%2F%2F3%2F%2BP8oKccGGcIRJrERILYFEMwAAuEAAdX%2F%2Ff7%2F%2FP%2B%2BfDvGXQLIZgLEWgLOjlf7%2F%2F%2F%2F%2F%2F9QU90EAPQAAf8DAP0AAfMAAOUDAtr%2F%2F%2F%2F7%2B%2Fu2bCTIYwDPZgDBWQDSr4P%2F%2Fv%2F%2F%2FP5GRuABAPkAA%2FwBAfkDAPAAAesAAN%2F%2F%2B%2Fz%2F%2F%2F64g1C5VwDMYwK8Yg7y5tz8%2Fv%2FV1PYKDOcAAP0DAf4AAf0AAfYEAOwAAuAAAAD%2F%2FPvi28ymXyChTATRrIb8%2F%2F3v8fk6P8MAAdUCAvoAAP0CAP0AAfYAAO4AAACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAA</Image>
|
||||
<Url type="text/html" method="GET" template="http://www.google.com/search?q={searchTerms}"/>
|
||||
</OpenSearchDescription>
|
44
data/search_providers/wikipedia.xml
Normal file
44
data/search_providers/wikipedia.xml
Normal file
@ -0,0 +1,44 @@
|
||||
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
|
||||
<ShortName>Wikipedia</ShortName>
|
||||
<Description>Wikipedia, the free encyclopedia</Description>
|
||||
<InputEncoding>UTF-8</InputEncoding>
|
||||
<Image width="16" height="16">data:image/x-icon;base64,AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAEAgQAhIOEAMjHyABIR0gA6ejpAGlqaQCpqKkAKCgoAPz9%2FAAZGBkAmJiYANjZ2ABXWFcAent6ALm6uQA8OjwAiIiIiIiIiIiIiI4oiL6IiIiIgzuIV4iIiIhndo53KIiIiB%2FWvXoYiIiIfEZfWBSIiIEGi%2FfoqoiIgzuL84i9iIjpGIoMiEHoiMkos3FojmiLlUipYliEWIF%2BiDe0GoRa7D6GPbjcu1yIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA</Image>
|
||||
<Url type="text/html" method="GET" template="http://{language}.wikipedia.org/wiki/Special:Search?search={searchTerms}"/>
|
||||
<!-- The criterion for being below is being listed with more than 100,000
|
||||
articles on http://meta.wikimedia.org/wiki/List_of_Wikipedias -->
|
||||
<Language>ar</Language>
|
||||
<Language>bg</Language>
|
||||
<Language>ca</Language>
|
||||
<Language>cs</Language>
|
||||
<Language>da</Language>
|
||||
<Language>de</Language>
|
||||
<Language>en</Language>
|
||||
<Language>eo</Language>
|
||||
<Language>es</Language>
|
||||
<Language>fa</Language>
|
||||
<Language>fi</Language>
|
||||
<Language>fr</Language>
|
||||
<Language>he</Language>
|
||||
<Language>hu</Language>
|
||||
<Language>id</Language>
|
||||
<Language>it</Language>
|
||||
<Language>ja</Language>
|
||||
<Language>ko</Language>
|
||||
<Language>lt</Language>
|
||||
<Language>nl</Language>
|
||||
<Language>no</Language>
|
||||
<Language>pl</Language>
|
||||
<Language>pt</Language>
|
||||
<Language>ro</Language>
|
||||
<Language>ru</Language>
|
||||
<Language>sk</Language>
|
||||
<Language>sl</Language>
|
||||
<Language>sr</Language>
|
||||
<Language>sv</Language>
|
||||
<Language>tr</Language>
|
||||
<Language>uk</Language>
|
||||
<Language>vi</Language>
|
||||
<Language>vo</Language>
|
||||
<Language>war</Language>
|
||||
<Language>zh</Language>
|
||||
</OpenSearchDescription>
|
@ -1,98 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="23"
|
||||
height="15"
|
||||
id="svg6375"
|
||||
version="1.1"
|
||||
inkscape:version="0.47pre4 r22446"
|
||||
sodipodi:docname="New document 13">
|
||||
<defs
|
||||
id="defs6377">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 16 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="32 : 16 : 1"
|
||||
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
||||
id="perspective6383" />
|
||||
<inkscape:perspective
|
||||
id="perspective6366"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="11.197802"
|
||||
inkscape:cx="16"
|
||||
inkscape:cy="16"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1680"
|
||||
inkscape:window-height="997"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="26"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata6380">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
transform="translate(0,-17)">
|
||||
<g
|
||||
style="display:inline"
|
||||
id="g6243"
|
||||
transform="translate(-986.28859,-658.2796)">
|
||||
<rect
|
||||
style="fill:#000000;fill-opacity:0.98770495;stroke:#666666;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
|
||||
id="rect5318"
|
||||
width="22"
|
||||
height="14"
|
||||
x="986.89801"
|
||||
y="675.86743"
|
||||
rx="0.49999979"
|
||||
ry="0.5" />
|
||||
<g
|
||||
id="g5320"
|
||||
transform="translate(402.77304,-12.882544)">
|
||||
<path
|
||||
id="path5322"
|
||||
d="m 595.125,692.53048 0,6.43903"
|
||||
style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
<path
|
||||
id="path5324"
|
||||
d="m 598.34451,695.75 -6.43902,0"
|
||||
style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 3.2 KiB |
82
data/theme/calendar-arrow-left.svg
Normal file
82
data/theme/calendar-arrow-left.svg
Normal file
@ -0,0 +1,82 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16"
|
||||
height="16"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48+devel r9942 custom"
|
||||
sodipodi:docname="New document 4">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="8.984481"
|
||||
inkscape:cy="5.6224906"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
borderlayer="true"
|
||||
inkscape:showpageshadow="false"
|
||||
inkscape:window-width="930"
|
||||
inkscape:window-height="681"
|
||||
inkscape:window-x="1892"
|
||||
inkscape:window-y="272"
|
||||
inkscape:window-maximized="0">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid17403"
|
||||
empspacing="5"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1036.3622)">
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#5f5f5f;fill-opacity:1;stroke:#5f5f5f;stroke-width:0.43015847;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
|
||||
id="path18028"
|
||||
sodipodi:sides="3"
|
||||
sodipodi:cx="84.5"
|
||||
sodipodi:cy="337.5"
|
||||
sodipodi:r1="5"
|
||||
sodipodi:r2="2.5"
|
||||
sodipodi:arg1="0.52359878"
|
||||
sodipodi:arg2="1.5707963"
|
||||
inkscape:flatsided="true"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="M 88.830127,340 80.169873,340 84.5,332.5 z"
|
||||
transform="matrix(0,1.3621708,0.99186247,0,-325.48222,929.32667)" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
82
data/theme/calendar-arrow-right.svg
Normal file
82
data/theme/calendar-arrow-right.svg
Normal file
@ -0,0 +1,82 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16"
|
||||
height="16"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48+devel r9942 custom"
|
||||
sodipodi:docname="arrow-left.svg">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="7.7366092"
|
||||
inkscape:cy="6.4536271"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
borderlayer="true"
|
||||
inkscape:showpageshadow="false"
|
||||
inkscape:window-width="930"
|
||||
inkscape:window-height="681"
|
||||
inkscape:window-x="1892"
|
||||
inkscape:window-y="272"
|
||||
inkscape:window-maximized="0">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid17403"
|
||||
empspacing="5"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1036.3622)">
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#5f5f5f;fill-opacity:1;stroke:#5f5f5f;stroke-width:0.43015847;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
|
||||
id="path18028"
|
||||
sodipodi:sides="3"
|
||||
sodipodi:cx="84.5"
|
||||
sodipodi:cy="337.5"
|
||||
sodipodi:r1="5"
|
||||
sodipodi:r2="2.5"
|
||||
sodipodi:arg1="0.52359878"
|
||||
sodipodi:arg2="1.5707963"
|
||||
inkscape:flatsided="true"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="M 88.830127,340 80.169873,340 84.5,332.5 z"
|
||||
transform="matrix(0,1.3621708,-0.99186247,0,342.48324,929.32667)" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
@ -1,222 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="24"
|
||||
height="24"
|
||||
id="svg4908"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.47 r22583"
|
||||
sodipodi:docname="dialog-error.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
inkscape:export-filename="/home/andreas/project/gnome-icon-theme/scalable/actions/process-stop.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90"
|
||||
version="1.0">
|
||||
<defs
|
||||
id="defs4910">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 24 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="48 : 24 : 1"
|
||||
inkscape:persp3d-origin="24 : 16 : 1"
|
||||
id="perspective25" />
|
||||
<radialGradient
|
||||
gradientTransform="matrix(1.349881,0,0,1.349881,-3.498814,-1.810859)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
r="9.7183542"
|
||||
fy="4.9892726"
|
||||
fx="9.6893959"
|
||||
cy="4.9892726"
|
||||
cx="9.6893959"
|
||||
id="radialGradient5177"
|
||||
xlink:href="#linearGradient5171"
|
||||
inkscape:collect="always" />
|
||||
<radialGradient
|
||||
gradientTransform="matrix(2.417917,0,0,2.417917,-14.17917,-4.903184)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
r="9.7785711"
|
||||
fy="3.458019"
|
||||
fx="10"
|
||||
cy="3.458019"
|
||||
cx="10"
|
||||
id="radialGradient5157"
|
||||
xlink:href="#linearGradient5151"
|
||||
inkscape:collect="always" />
|
||||
<radialGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.928125,0,0,0.3143011,0.7718789,12.358015)"
|
||||
r="9.0598059"
|
||||
fy="18.022524"
|
||||
fx="10.739184"
|
||||
cy="18.022524"
|
||||
cx="10.739184"
|
||||
id="radialGradient5145"
|
||||
xlink:href="#linearGradient5139"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient5139"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop5141"
|
||||
offset="0"
|
||||
style="stop-color:black;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop5143"
|
||||
offset="1"
|
||||
style="stop-color:black;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5151"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop5153"
|
||||
offset="0"
|
||||
style="stop-color:white;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop5155"
|
||||
offset="1"
|
||||
style="stop-color:white;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5171">
|
||||
<stop
|
||||
id="stop5173"
|
||||
offset="0"
|
||||
style="stop-color:#fe3a00;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop5175"
|
||||
offset="1"
|
||||
style="stop-color:#c00;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="22.627417"
|
||||
inkscape:cx="24.442987"
|
||||
inkscape:cy="10.142308"
|
||||
inkscape:current-layer="g7001"
|
||||
showgrid="false"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:window-width="1674"
|
||||
inkscape:window-height="970"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="26"
|
||||
width="48px"
|
||||
height="48px"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata4913">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>Stop Process</dc:title>
|
||||
<dc:date>December 2006</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Jakub Steiner</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>Andreas Nilsson</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
|
||||
<dc:subject>
|
||||
<rdf:Bag>
|
||||
<rdf:li>stop</rdf:li>
|
||||
<rdf:li>halt</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/Notice" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/ShareAlike" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/SourceCode" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
transform="translate(0,-24)">
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
id="g7001"
|
||||
transform="matrix(1.4566048,0,0,1.4455352,0.4112881,1.2324709)">
|
||||
<path
|
||||
transform="matrix(0.91468137,0,0,0.70055266,-1.8812476,17.474032)"
|
||||
d="m 19.79899,18.022524 a 9.0598059,3.0935922 0 1 1 -18.1196115,0 9.0598059,3.0935922 0 1 1 18.1196115,0 z"
|
||||
sodipodi:ry="3.0935922"
|
||||
sodipodi:rx="9.0598059"
|
||||
sodipodi:cy="18.022524"
|
||||
sodipodi:cx="10.739184"
|
||||
id="path5137"
|
||||
style="color:#000000;fill:url(#radialGradient5145);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
transform="matrix(0.87347736,0,0,0.83068052,-0.79308842,15.602788)"
|
||||
d="m 19.25,9.625 a 9.25,9.25 0 1 1 -18.5,0 9.25,9.25 0 1 1 18.5,0 z"
|
||||
sodipodi:ry="9.25"
|
||||
sodipodi:rx="9.25"
|
||||
sodipodi:cy="9.625"
|
||||
sodipodi:cx="10"
|
||||
id="path4262"
|
||||
style="color:#000000;fill:url(#radialGradient5177);fill-opacity:1;fill-rule:nonzero;stroke:#a40000;stroke-width:0.47435912;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="opacity:0.35393258;color:#000000;fill:none;stroke:url(#radialGradient5157);stroke-width:0.49999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||
id="path5149"
|
||||
sodipodi:cx="10"
|
||||
sodipodi:cy="9.625"
|
||||
sodipodi:rx="9.25"
|
||||
sodipodi:ry="9.25"
|
||||
d="m 19.25,9.625 a 9.25,9.25 0 1 1 -18.5,0 9.25,9.25 0 1 1 18.5,0 z"
|
||||
transform="matrix(0.82868359,0,0,0.78808147,-0.34515141,16.012803)" />
|
||||
<path
|
||||
sodipodi:nodetypes="cc"
|
||||
id="path5159"
|
||||
d="m 4.834121,20.642783 6.215127,5.91061"
|
||||
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.21219134;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" />
|
||||
<path
|
||||
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.21219146;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
|
||||
d="M 11.04925,20.622826 4.8159529,26.553393"
|
||||
id="path5161"
|
||||
sodipodi:nodetypes="cc" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 8.0 KiB |
@ -17,6 +17,10 @@
|
||||
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
stage {
|
||||
font-family: cantarell, sans-serif;
|
||||
}
|
||||
|
||||
.shell-link {
|
||||
color: #0000ff;
|
||||
text-decoration: underline;
|
||||
@ -101,7 +105,7 @@ StTooltip StLabel {
|
||||
|
||||
.popup-menu {
|
||||
color: #ffffff;
|
||||
font-size: 16px;
|
||||
font-size: 14px;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
@ -151,7 +155,7 @@ StTooltip StLabel {
|
||||
}
|
||||
|
||||
.popup-menu-icon {
|
||||
icon-size: 1em;
|
||||
icon-size: 1.14em;
|
||||
}
|
||||
|
||||
/* Switches (to be used in menus) */
|
||||
@ -178,7 +182,6 @@ StTooltip StLabel {
|
||||
|
||||
#panel {
|
||||
color: #ffffff;
|
||||
font-size: 16px;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
@ -209,7 +212,7 @@ StTooltip StLabel {
|
||||
border-radius: 5px;
|
||||
border-radius-bottomleft: 0px;
|
||||
border-radius-bottomright: 0px;
|
||||
font: 16px sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
transition-duration: 100;
|
||||
}
|
||||
@ -242,7 +245,7 @@ StTooltip StLabel {
|
||||
}
|
||||
|
||||
.system-status-icon {
|
||||
icon-size: 1em;
|
||||
icon-size: 1.14em;
|
||||
}
|
||||
|
||||
/* Overview */
|
||||
@ -257,44 +260,23 @@ StTooltip StLabel {
|
||||
spacing: 25px;
|
||||
}
|
||||
|
||||
.workspace-indicator-panel {
|
||||
spacing: 8px;
|
||||
}
|
||||
|
||||
.workspace-indicator {
|
||||
width: 24px;
|
||||
height: 16px;
|
||||
background: rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
.workspace-indicator.active {
|
||||
background: rgba(255,255,255,0.8);
|
||||
}
|
||||
|
||||
.workspace-controls {
|
||||
width: 48px;
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
border: 2px solid rgba(128, 128, 128, 0.4);
|
||||
border: 1px solid #424242;
|
||||
border-right: 0px;
|
||||
border-radius: 9px 0px 0px 9px;
|
||||
background: #071524;
|
||||
}
|
||||
|
||||
.add-workspace {
|
||||
background-color: rgba(128, 128, 128, 0.4);
|
||||
.workspace-thumbnails {
|
||||
spacing: 7px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.add-workspace:hover {
|
||||
background-color: rgba(128, 128, 128, 0.6);
|
||||
}
|
||||
|
||||
.remove-workspace {
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.remove-workspace:hover {
|
||||
background-color: rgba(128, 128, 128, 0.2);
|
||||
.workspace-thumbnail-indicator {
|
||||
outline: 2px solid white;
|
||||
}
|
||||
|
||||
.window-caption {
|
||||
@ -310,7 +292,7 @@ StTooltip StLabel {
|
||||
background-image: url("close-window.svg");
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
-st-shadow: -2px 2px 6px rgba(0,0,0,0.5);
|
||||
-st-background-image-shadow: -2px 2px 6px rgba(0,0,0,0.5);
|
||||
-shell-close-overlap: 16px;
|
||||
}
|
||||
|
||||
@ -371,7 +353,7 @@ StTooltip StLabel {
|
||||
background-gradient-direction: vertical;
|
||||
color: rgb(64, 64, 64);
|
||||
font-weight: bold;
|
||||
-st-shadow: 0px 0px 6px 2px rgba(255,255,255,0.9);
|
||||
box-shadow: 0px 0px 6px 2px rgba(255,255,255,0.9);
|
||||
transition-duration: 0;
|
||||
}
|
||||
|
||||
@ -388,6 +370,10 @@ StTooltip StLabel {
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.view-tab-title:hover {
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.view-tab-title:selected {
|
||||
color: #000000;
|
||||
background-color: #c2c7cd;
|
||||
@ -441,40 +427,30 @@ StTooltip StLabel {
|
||||
spacing: 4px;
|
||||
}
|
||||
|
||||
/* GenericDisplay */
|
||||
|
||||
.generic-display-container {
|
||||
.search-providers-box {
|
||||
spacing: 4px;
|
||||
}
|
||||
|
||||
.generic-display-item {
|
||||
height: 50px;
|
||||
border-radius: 4px;
|
||||
color: #ffffff;
|
||||
font-size: 14px;
|
||||
spacing: 4px;
|
||||
.dash-search-button {
|
||||
background-gradient-direction: vertical;
|
||||
background-gradient-start: rgba(255, 255, 255, 0.2);
|
||||
background-gradient-end: rgba(255, 255, 255, 0);
|
||||
/* border: 1px solid #808080;*/
|
||||
border-radius: 10px;
|
||||
height: 32px;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.generic-display-item:selected {
|
||||
background-color: rgba(79,111,173,0.66);
|
||||
.dash-search-button:selected,
|
||||
.dash-search-button:hover {
|
||||
background-gradient-direction: vertical;
|
||||
background-gradient-start: rgba(255, 255, 255, 0.4);
|
||||
background-gradient-end: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.generic-display-item-text {
|
||||
spacing: 4px;
|
||||
}
|
||||
|
||||
.generic-display-item-description {
|
||||
font-size: 12px;
|
||||
color: #bababa;
|
||||
}
|
||||
|
||||
.generic-display-details {
|
||||
font-size: 14px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.generic-display-details-name {
|
||||
font-weight: bold;
|
||||
.dash-search-button-label {
|
||||
color: #cccccc;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* Apps */
|
||||
@ -513,7 +489,7 @@ StTooltip StLabel {
|
||||
|
||||
.remove-favorite-icon:hover {
|
||||
color: white;
|
||||
-st-shadow: black 0px 2px 2px;
|
||||
icon-shadow: black 0px 2px 2px;
|
||||
}
|
||||
|
||||
.app-well-app > .overview-icon,
|
||||
@ -554,57 +530,6 @@ StTooltip StLabel {
|
||||
font-size: 12px
|
||||
}
|
||||
|
||||
/* Places */
|
||||
|
||||
.places-section {
|
||||
spacing-columns: 4px;
|
||||
spacing-rows: 4px;
|
||||
}
|
||||
|
||||
.places-item-box {
|
||||
spacing: 2px;
|
||||
}
|
||||
|
||||
.places-item {
|
||||
border-radius: 4px;
|
||||
padding: 2px;
|
||||
border: 1px solid #181818;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
transition-duration: 100;
|
||||
}
|
||||
|
||||
.places-item:hover {
|
||||
border: 1px solid #666666;
|
||||
background-gradient-direction: vertical;
|
||||
background-gradient-start: rgba(61,61,61,0.8);
|
||||
background-gradient-end: rgba(24,24,24,0.2);
|
||||
transition-duration: 100;
|
||||
}
|
||||
|
||||
/* Recent items */
|
||||
|
||||
.recent-docs-item-box {
|
||||
spacing: 2px;
|
||||
}
|
||||
|
||||
.recent-docs-item {
|
||||
border-radius: 4px;
|
||||
padding: 2px;
|
||||
border: 1px solid #181818;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
transition-duration: 100;
|
||||
}
|
||||
|
||||
.recent-docs-item:hover {
|
||||
border: 1px solid #666666;
|
||||
background-gradient-direction: vertical;
|
||||
background-gradient-start: rgba(61,61,61,0.8);
|
||||
background-gradient-end: rgba(24,24,24,0.2);
|
||||
transition-duration: 100;
|
||||
}
|
||||
|
||||
/* LookingGlass */
|
||||
|
||||
#LookingGlassDialog
|
||||
@ -728,6 +653,17 @@ StTooltip StLabel {
|
||||
|
||||
/* Calendar popup */
|
||||
|
||||
#calendarArea {
|
||||
/* this is the width of the entire popup */
|
||||
width: 600px;
|
||||
}
|
||||
|
||||
.calendar-vertical-separator {
|
||||
-stipple-width: 1px;
|
||||
-stipple-color: #505050;
|
||||
width: 1.5em;
|
||||
}
|
||||
|
||||
#calendarPopup {
|
||||
border-radius: 5px;
|
||||
background: rgba(0,0,0,0.9);
|
||||
@ -740,37 +676,155 @@ StTooltip StLabel {
|
||||
}
|
||||
|
||||
.calendar {
|
||||
spacing-rows: 5px;
|
||||
spacing-columns: 3px;
|
||||
padding: .4em 1.75em;
|
||||
spacing-rows: 0px;
|
||||
spacing-columns: 0px;
|
||||
}
|
||||
|
||||
.calendar-change-month {
|
||||
.calendar-month-label {
|
||||
color: #666666;
|
||||
font-size: 10px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.calendar-change-month:hover {
|
||||
background: #314a6c;
|
||||
border-radius: 5px;
|
||||
.calendar-change-month-back {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-image: url("calendar-arrow-left.svg");
|
||||
border-radius: 4px;
|
||||
}
|
||||
.calendar-change-month-back:hover {
|
||||
background-color: #999999;
|
||||
}
|
||||
.calendar-change-month-back:active {
|
||||
background-color: #aaaaaa;
|
||||
}
|
||||
|
||||
.calendar-change-month:active {
|
||||
background: #213050;
|
||||
border-radius: 5px;
|
||||
.calendar-change-month-forward {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-image: url("calendar-arrow-right.svg");
|
||||
border-radius: 4px;
|
||||
}
|
||||
.calendar-change-month-forward:hover {
|
||||
background-color: #999999;
|
||||
}
|
||||
.calendar-change-month-forward:active {
|
||||
background-color: #aaaaaa;
|
||||
}
|
||||
|
||||
.datemenu-date-label {
|
||||
padding: .4em 1.75em;
|
||||
font-size: 16px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.calendar-day-base {
|
||||
font-size: 10px;
|
||||
text-align: center;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.calendar-day-base:hover {
|
||||
background: #777777;
|
||||
}
|
||||
|
||||
.calendar-day-base:active {
|
||||
background: #555555;
|
||||
}
|
||||
|
||||
.calendar-day-heading {
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.calendar-week-number {
|
||||
color: #666666;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Hack used in lieu of border-collapse - see calendar.js */
|
||||
.calendar-day {
|
||||
padding: 1px 2px;
|
||||
border: 1px solid #333333;
|
||||
color: #cccccc;
|
||||
border-top-width: 0;
|
||||
border-left-width: 0;
|
||||
}
|
||||
.calendar-day-top {
|
||||
border-top-width: 1px;
|
||||
}
|
||||
.calendar-day-left {
|
||||
border-left-width: 1px;
|
||||
}
|
||||
|
||||
.calendar-work-day {
|
||||
}
|
||||
|
||||
.calendar-nonwork-day {
|
||||
background-color: rgba(128, 128, 128, .1);
|
||||
}
|
||||
|
||||
.calendar-today {
|
||||
color: #ffffff;
|
||||
font-weight: bold;
|
||||
background: #ffffff;
|
||||
color: black;
|
||||
border-radius: 5px;
|
||||
background-gradient-direction: vertical;
|
||||
background-gradient-start: #3c3c3c;
|
||||
background-gradient-end: #131313;
|
||||
}
|
||||
|
||||
.calendar-other-month-day {
|
||||
color: #cccccc;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.calendar-day-with-events {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.events-header-vbox {
|
||||
spacing: 10px;
|
||||
}
|
||||
|
||||
.events-header {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.events-header-hbox {
|
||||
spacing: 8px;
|
||||
padding: 0.3em;
|
||||
}
|
||||
|
||||
.events-day-header {
|
||||
font-size: 14px;
|
||||
color: rgba(153, 153, 153, 1.0);
|
||||
}
|
||||
|
||||
.events-day-dayname {
|
||||
font-size: 12px;
|
||||
color: rgba(153, 153, 153, 1.0);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.events-day-time {
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.events-day-task {
|
||||
font-size: 12px;
|
||||
color: rgba(153, 153, 153, 1.0);
|
||||
}
|
||||
|
||||
.events-day-name-box {
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.events-time-box {
|
||||
width: 70px;
|
||||
}
|
||||
|
||||
.events-event-box {
|
||||
}
|
||||
|
||||
.url-highlighter {
|
||||
@ -846,6 +900,10 @@ StTooltip StLabel {
|
||||
border: 1px solid #a1a1a1;
|
||||
}
|
||||
|
||||
.notification-button:focus {
|
||||
background-color: #666666;
|
||||
}
|
||||
|
||||
.notification-button:active {
|
||||
border: 1px solid #a1a1a1;
|
||||
background-color: #2b2b2b;
|
||||
@ -858,6 +916,10 @@ StTooltip StLabel {
|
||||
}
|
||||
|
||||
.notification-icon-button:hover {
|
||||
border: 2px rgba(161,161,161,0.7);
|
||||
}
|
||||
|
||||
.notification-icon-button:focus {
|
||||
background: rgba(192,192,192,0.7);
|
||||
}
|
||||
|
||||
@ -909,7 +971,7 @@ StTooltip StLabel {
|
||||
color: #545454;
|
||||
background-color: #e8e8e8;
|
||||
caret-color: #545454;
|
||||
-st-shadow: 0px 0px 6px 2px rgba(255,255,255,0.9);
|
||||
box-shadow: 0px 0px 6px 2px rgba(255,255,255,0.9);
|
||||
}
|
||||
|
||||
/* The spacing and padding on the summary is tricky; we want to keep
|
||||
@ -944,15 +1006,11 @@ StTooltip StLabel {
|
||||
}
|
||||
|
||||
.source-title {
|
||||
font: 12px sans-serif;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.calendar-calendarweek {
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
/* App Switcher */
|
||||
#altTabPopup {
|
||||
padding: 8px;
|
||||
@ -965,7 +1023,7 @@ StTooltip StLabel {
|
||||
border-radius: 24px;
|
||||
padding: 20px;
|
||||
|
||||
font: 12px sans-serif;
|
||||
font-size: 12px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
@ -1080,41 +1138,146 @@ StTooltip StLabel {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* Run Dialog */
|
||||
.run-dialog-label {
|
||||
font: 12px sans-serif;
|
||||
color: white;
|
||||
/* Modal Dialogs */
|
||||
.modal-dialog {
|
||||
font-size: 12pt;
|
||||
border-radius: 24px;
|
||||
background-color: rgba(0.0, 0.0, 0.0, 0.9);
|
||||
border: 2px solid #868686;
|
||||
color: #ffffff;
|
||||
|
||||
padding-right: 42px;
|
||||
padding-left: 42px;
|
||||
padding-bottom: 30px;
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
.run-dialog-error-icon {
|
||||
background-image: url("dialog-error.svg");
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
.modal-dialog-button {
|
||||
border: 1px solid #8b8b8b;
|
||||
border-radius: 18px;
|
||||
font-size: 14px;
|
||||
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
|
||||
padding-left: 32px;
|
||||
padding-right: 32px;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
|
||||
background-gradient-direction: vertical;
|
||||
background-gradient-start: #29323b;
|
||||
background-gradient-end: #121a24;
|
||||
}
|
||||
|
||||
.modal-dialog-button:active,
|
||||
.modal-dialog-button:pressed {
|
||||
border-color: #a5a5a5;
|
||||
background-gradient-start: #121a24;
|
||||
background-gradient-end: #29323b;
|
||||
}
|
||||
|
||||
.modal-dialog-button:focus {
|
||||
border: 2px solid #a5a5a5;
|
||||
|
||||
padding-left: 31px;
|
||||
padding-right: 31px;
|
||||
padding-top: 7px;
|
||||
padding-bottom: 7px;
|
||||
}
|
||||
|
||||
/* Run Dialog */
|
||||
.run-dialog-label {
|
||||
font-size: 12px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.run-dialog-error-label {
|
||||
font: 16px sans-serif;
|
||||
font-size: 12px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.run-dialog-error-box {
|
||||
padding-top: 15px;
|
||||
spacing: 5px;
|
||||
}
|
||||
|
||||
.run-dialog-entry {
|
||||
font: 14px sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
width: 320px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.run-dialog {
|
||||
padding: 8px;
|
||||
border: 1px solid rgba(128,128,128,0.40);
|
||||
border-radius: 4px;
|
||||
background: rgba(0,0,0,0.8);
|
||||
border-radius: 16px;
|
||||
|
||||
padding-right: 21px;
|
||||
padding-left: 21px;
|
||||
padding-bottom: 15px;
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
.lightbox {
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
/* End Session Dialog */
|
||||
.end-session-dialog-subject {
|
||||
font-size: 12pt;
|
||||
font-weight: bold;
|
||||
color: #666666;
|
||||
padding-top: 10px;
|
||||
padding-left: 17px;
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
|
||||
.end-session-dialog-description {
|
||||
font-size: 10pt;
|
||||
color: white;
|
||||
padding-left: 17px;
|
||||
padding-right: 40px;
|
||||
width: 16em;
|
||||
}
|
||||
|
||||
.end-session-dialog-logout-icon {
|
||||
border: 2px solid #8b8b8b;
|
||||
border-radius: 5px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.end-session-dialog-shutdown-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.end-session-dialog-app-list {
|
||||
font-size: 10pt;
|
||||
max-height: 200px;
|
||||
padding-top: 42px;
|
||||
padding-bottom: 42px;
|
||||
padding-left: 17px;
|
||||
padding-right: 32px;
|
||||
}
|
||||
|
||||
.end-session-dialog-app-list-item {
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
.end-session-dialog-app-list-item-icon {
|
||||
padding-right: 17px;
|
||||
}
|
||||
|
||||
.end-session-dialog-app-list-item-name {
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
.end-session-dialog-app-list-item-description {
|
||||
font-size: 8pt;
|
||||
color: #444444;
|
||||
}
|
||||
|
||||
/* Magnifier */
|
||||
|
||||
.magnifier-zoom-region {
|
||||
|
@ -1,92 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="23"
|
||||
height="15"
|
||||
id="svg5501"
|
||||
version="1.1"
|
||||
inkscape:version="0.47pre4 r22446"
|
||||
sodipodi:docname="add-workspace.svg">
|
||||
<defs
|
||||
id="defs5503">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 16 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="32 : 16 : 1"
|
||||
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
||||
id="perspective5509" />
|
||||
<inkscape:perspective
|
||||
id="perspective5314"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="11.197802"
|
||||
inkscape:cx="-0.074583208"
|
||||
inkscape:cy="16"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1680"
|
||||
inkscape:window-height="997"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="26"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-grids="true"
|
||||
inkscape:snap-bbox="true" />
|
||||
<metadata
|
||||
id="metadata5506">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
transform="translate(0,-17)">
|
||||
<g
|
||||
style="display:inline"
|
||||
id="g6239"
|
||||
transform="translate(-953.97989,-657.32287)">
|
||||
<rect
|
||||
style="fill:#000000;fill-opacity:0.98770495;stroke:#666666;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
|
||||
id="rect5318-6"
|
||||
width="22"
|
||||
height="14"
|
||||
x="954.5"
|
||||
y="675"
|
||||
rx="0.49999979"
|
||||
ry="0.5" />
|
||||
<path
|
||||
style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
|
||||
d="m 968.71951,682 -6.43902,0"
|
||||
id="path5324-5" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.9 KiB |
@ -33,7 +33,7 @@
|
||||
<foaf:Person>
|
||||
<foaf:name>Colin Walters</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:walters@verbum.org" />
|
||||
<gnome:userid>cwalters</gnome:userid>
|
||||
<gnome:userid>walters</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
<maintainer>
|
||||
|
@ -9,7 +9,7 @@ nobase_dist_js_DATA = \
|
||||
misc/gnomeSession.js \
|
||||
misc/params.js \
|
||||
misc/telepathy.js \
|
||||
misc/utils.js \
|
||||
misc/util.js \
|
||||
perf/core.js \
|
||||
ui/altTab.js \
|
||||
ui/appDisplay.js \
|
||||
@ -19,11 +19,12 @@ nobase_dist_js_DATA = \
|
||||
ui/chrome.js \
|
||||
ui/ctrlAltTab.js \
|
||||
ui/dash.js \
|
||||
ui/dateMenu.js \
|
||||
ui/dnd.js \
|
||||
ui/docDisplay.js \
|
||||
ui/endSessionDialog.js \
|
||||
ui/environment.js \
|
||||
ui/extensionSystem.js \
|
||||
ui/genericDisplay.js \
|
||||
ui/iconGrid.js \
|
||||
ui/lightbox.js \
|
||||
ui/link.js \
|
||||
@ -32,6 +33,7 @@ nobase_dist_js_DATA = \
|
||||
ui/magnifierDBus.js \
|
||||
ui/main.js \
|
||||
ui/messageTray.js \
|
||||
ui/modalDialog.js \
|
||||
ui/notificationDaemon.js \
|
||||
ui/overview.js \
|
||||
ui/panel.js \
|
||||
@ -46,6 +48,7 @@ nobase_dist_js_DATA = \
|
||||
ui/statusIconDispatcher.js \
|
||||
ui/statusMenu.js \
|
||||
ui/status/accessibility.js \
|
||||
ui/status/keyboard.js \
|
||||
ui/status/power.js \
|
||||
ui/status/volume.js \
|
||||
ui/status/bluetooth.js \
|
||||
@ -55,6 +58,7 @@ nobase_dist_js_DATA = \
|
||||
ui/windowAttentionHandler.js \
|
||||
ui/windowManager.js \
|
||||
ui/workspace.js \
|
||||
ui/workspaceThumbnail.js \
|
||||
ui/workspacesView.js \
|
||||
ui/workspaceSwitcherPopup.js \
|
||||
ui/xdndHandler.js
|
||||
|
@ -1,3 +1,10 @@
|
||||
/* mode: js2; indent-tabs-mode: nil; tab-size: 4 */
|
||||
/* The name of this package (not localized) */
|
||||
const PACKAGE_NAME = '@PACKAGE_NAME@';
|
||||
/* The version of this package */
|
||||
const PACKAGE_VERSION = '@PACKAGE_VERSION@';
|
||||
/* The version of GJS we're linking to */
|
||||
const GJS_VERSION = '@GJS_VERSION@';
|
||||
/* 1 if gnome-bluetooth is available, 0 otherwise */
|
||||
const HAVE_BLUETOOTH = @HAVE_BLUETOOTH@;
|
||||
|
||||
|
@ -29,8 +29,8 @@ DocInfo.prototype = {
|
||||
return St.TextureCache.get_default().load_recent_thumbnail(size, this.recentInfo);
|
||||
},
|
||||
|
||||
launch : function() {
|
||||
Shell.DocSystem.get_default().open(this.recentInfo);
|
||||
launch : function(workspaceIndex) {
|
||||
Shell.DocSystem.get_default().open(this.recentInfo, workspaceIndex);
|
||||
},
|
||||
|
||||
matchTerms: function(terms) {
|
||||
@ -60,8 +60,7 @@ function getDocManager() {
|
||||
}
|
||||
|
||||
/**
|
||||
* DocManager wraps the DocSystem, primarily to expose DocInfo objects
|
||||
* which conform to the GenericDisplay item API.
|
||||
* DocManager wraps the DocSystem, primarily to expose DocInfo objects.
|
||||
*/
|
||||
function DocManager() {
|
||||
this._init();
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
const DBus = imports.dbus;
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const PresenceIface = {
|
||||
name: 'org.gnome.SessionManager.Presence',
|
||||
@ -43,3 +44,60 @@ Presence.prototype = {
|
||||
}
|
||||
};
|
||||
DBus.proxifyPrototype(Presence.prototype, PresenceIface);
|
||||
|
||||
// Note inhibitors are immutable objects, so they don't
|
||||
// change at runtime (changes always come in the form
|
||||
// of new inhibitors)
|
||||
const InhibitorIface = {
|
||||
name: 'org.gnome.SessionManager.Inhibitor',
|
||||
properties: [{ name: 'app_id',
|
||||
signature: 's',
|
||||
access: 'readonly' },
|
||||
{ name: 'client_id',
|
||||
signature: 's',
|
||||
access: 'readonly' },
|
||||
{ name: 'reason',
|
||||
signature: 's',
|
||||
access: 'readonly' },
|
||||
{ name: 'flags',
|
||||
signature: 'u',
|
||||
access: 'readonly' },
|
||||
{ name: 'toplevel_xid',
|
||||
signature: 'u',
|
||||
access: 'readonly' },
|
||||
{ name: 'cookie',
|
||||
signature: 'u',
|
||||
access: 'readonly' }],
|
||||
};
|
||||
|
||||
function Inhibitor(objectPath) {
|
||||
this._init(objectPath);
|
||||
}
|
||||
|
||||
Inhibitor.prototype = {
|
||||
_init: function(objectPath) {
|
||||
DBus.session.proxifyObject(this,
|
||||
"org.gnome.SessionManager",
|
||||
objectPath);
|
||||
this.isLoaded = false;
|
||||
this._loadingPropertiesCount = InhibitorIface.properties.length;
|
||||
for (let i = 0; i < InhibitorIface.properties.length; i++) {
|
||||
let propertyName = InhibitorIface.properties[i].name;
|
||||
this.GetRemote(propertyName, Lang.bind(this,
|
||||
function(value, exception) {
|
||||
if (exception)
|
||||
return;
|
||||
|
||||
this[propertyName] = value;
|
||||
this._loadingPropertiesCount--;
|
||||
|
||||
if (this._loadingPropertiesCount == 0) {
|
||||
this.isLoaded = true;
|
||||
this.emit("is-loaded");
|
||||
}
|
||||
}));
|
||||
}
|
||||
},
|
||||
};
|
||||
DBus.proxifyPrototype(Inhibitor.prototype, InhibitorIface);
|
||||
Signals.addSignalMethods(Inhibitor.prototype);
|
||||
|
180
js/misc/util.js
Normal file
180
js/misc/util.js
Normal file
@ -0,0 +1,180 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Gdk = imports.gi.Gdk;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Shell = imports.gi.Shell;
|
||||
|
||||
const Main = imports.ui.main;
|
||||
const MessageTray = imports.ui.messageTray;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
/* http://daringfireball.net/2010/07/improved_regex_for_matching_urls */
|
||||
const _urlRegexp = new RegExp('\\b(([a-z][\\w-]+:(/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}/)([^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:\'\\".,<>?«»“”‘’]))', 'gi');
|
||||
|
||||
// findUrls:
|
||||
// @str: string to find URLs in
|
||||
//
|
||||
// Searches @str for URLs and returns an array of objects with %url
|
||||
// properties showing the matched URL string, and %pos properties indicating
|
||||
// the position within @str where the URL was found.
|
||||
//
|
||||
// Return value: the list of match objects, as described above
|
||||
function findUrls(str) {
|
||||
let res = [], match;
|
||||
while ((match = _urlRegexp.exec(str)))
|
||||
res.push({ url: match[0], pos: match.index });
|
||||
return res;
|
||||
}
|
||||
|
||||
// spawn:
|
||||
// @argv: an argv array
|
||||
//
|
||||
// Runs @argv in the background, handling any errors that occur
|
||||
// when trying to start the program.
|
||||
function spawn(argv) {
|
||||
try {
|
||||
trySpawn(argv);
|
||||
} catch (err) {
|
||||
_handleSpawnError(argv[0], err);
|
||||
}
|
||||
}
|
||||
|
||||
// spawnCommandLine:
|
||||
// @command_line: a command line
|
||||
//
|
||||
// Runs @command_line in the background, handling any errors that
|
||||
// occur when trying to parse or start the program.
|
||||
function spawnCommandLine(command_line) {
|
||||
try {
|
||||
let [success, argc, argv] = GLib.shell_parse_argv(command_line);
|
||||
trySpawn(argv);
|
||||
} catch (err) {
|
||||
_handleSpawnError(command_line, err);
|
||||
}
|
||||
}
|
||||
|
||||
// spawnDesktop:
|
||||
// @id: a desktop file ID
|
||||
//
|
||||
// Spawns the desktop file identified by @id using startup notification,
|
||||
// etc, handling any errors that occur when trying to find or start
|
||||
// the program.
|
||||
function spawnDesktop(id) {
|
||||
try {
|
||||
trySpawnDesktop(id);
|
||||
} catch (err) {
|
||||
_handleSpawnError(id, err);
|
||||
}
|
||||
}
|
||||
|
||||
// trySpawn:
|
||||
// @argv: an argv array
|
||||
//
|
||||
// Runs @argv in the background. If launching @argv fails,
|
||||
// this will throw an error.
|
||||
function trySpawn(argv)
|
||||
{
|
||||
try {
|
||||
GLib.spawn_async(null, argv, null,
|
||||
GLib.SpawnFlags.SEARCH_PATH,
|
||||
null, null);
|
||||
} catch (err) {
|
||||
if (err.code == GLib.SpawnError.G_SPAWN_ERROR_NOENT) {
|
||||
err.message = _("Command not found");
|
||||
} else {
|
||||
// The exception from gjs contains an error string like:
|
||||
// Error invoking GLib.spawn_command_line_async: Failed to
|
||||
// execute child process "foo" (No such file or directory)
|
||||
// We are only interested in the part in the parentheses. (And
|
||||
// we can't pattern match the text, since it gets localized.)
|
||||
err.message = err.message.replace(/.*\((.+)\)/, '$1');
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// trySpawnCommandLine:
|
||||
// @command_line: a command line
|
||||
//
|
||||
// Runs @command_line in the background. If launching @command_line
|
||||
// fails, this will throw an error.
|
||||
function trySpawnCommandLine(command_line) {
|
||||
let success, argc, argv;
|
||||
|
||||
try {
|
||||
[success, argc, argv] = GLib.shell_parse_argv(command_line);
|
||||
} catch (err) {
|
||||
// Replace "Error invoking GLib.shell_parse_argv: " with
|
||||
// something nicer
|
||||
err.message = err.message.replace(/[^:]*: /, _("Could not parse command:") + "\n");
|
||||
throw err;
|
||||
}
|
||||
|
||||
trySpawn(argv);
|
||||
}
|
||||
|
||||
// trySpawnDesktop:
|
||||
// @id: a desktop file ID
|
||||
//
|
||||
// Spawns the desktop file identified by @id using startup notification.
|
||||
// On error, throws an exception.
|
||||
function trySpawnDesktop(id) {
|
||||
let app;
|
||||
|
||||
// shell_app_system_load_from_desktop_file() will end up returning
|
||||
// a stupid error message if the desktop file doesn't exist, but
|
||||
// that's the only case it returns an error for, so we just
|
||||
// substitute our own error in instead
|
||||
try {
|
||||
app = Shell.AppSystem.get_default().load_from_desktop_file(id + '.desktop');
|
||||
} catch (err) {
|
||||
throw new Error(_("No such application"));
|
||||
}
|
||||
|
||||
try {
|
||||
app.launch();
|
||||
} catch(err) {
|
||||
// see trySpawn
|
||||
err.message = err.message.replace(/.*\((.+)\)/, '$1');
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
function _handleSpawnError(command, err) {
|
||||
let title = _("Execution of '%s' failed:").format(command);
|
||||
|
||||
let source = new MessageTray.SystemNotificationSource();
|
||||
Main.messageTray.add(source);
|
||||
let notification = new MessageTray.Notification(source, title, err.message);
|
||||
notification.setTransient(true);
|
||||
source.notify(notification);
|
||||
}
|
||||
|
||||
// killall:
|
||||
// @processName: a process name
|
||||
//
|
||||
// Kills @processName. If no process with the given name is found,
|
||||
// this will fail silently.
|
||||
function killall(processName) {
|
||||
try {
|
||||
// pkill is more portable than killall, but on Linux at least
|
||||
// it won't match if you pass more than 15 characters of the
|
||||
// process name... However, if you use the '-f' flag to match
|
||||
// the entire command line, it will work, but we have to be
|
||||
// careful in that case that we can match
|
||||
// '/usr/bin/processName' but not 'gedit processName.c' or
|
||||
// whatever...
|
||||
|
||||
let argv = ['pkill', '-f', '^([^ ]*/)?' + processName + '($| )'];
|
||||
GLib.spawn_sync(null, argv, null, GLib.SpawnFlags.SEARCH_PATH, null, null);
|
||||
// It might be useful to return success/failure, but we'd need
|
||||
// a wrapper around WIFEXITED and WEXITSTATUS. Since none of
|
||||
// the current callers care, we don't bother.
|
||||
} catch (e) {
|
||||
logError(e, 'Failed to kill ' + processName);
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
/* http://daringfireball.net/2010/07/improved_regex_for_matching_urls */
|
||||
const _urlRegexp = /\b(([a-z][\w-]+:(\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)([^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'\".,<>?«»“”‘’]))/gi;
|
||||
|
||||
// findUrls:
|
||||
// @str: string to find URLs in
|
||||
//
|
||||
// Searches @str for URLs and returns an array of objects with %url
|
||||
// properties showing the matched URL string, and %pos properties indicating
|
||||
// the position within @str where the URL was found.
|
||||
//
|
||||
// Return value: the list of match objects, as described above
|
||||
function findUrls(str) {
|
||||
let res = [], match;
|
||||
while ((match = _urlRegexp.exec(str)))
|
||||
res.push({ url: match[0], pos: match.index });
|
||||
return res;
|
||||
}
|
@ -15,6 +15,8 @@ const POPUP_APPICON_SIZE = 96;
|
||||
const POPUP_SCROLL_TIME = 0.10; // seconds
|
||||
const POPUP_FADE_TIME = 0.1; // seconds
|
||||
|
||||
const APP_ICON_HOVER_TIMEOUT = 200; // milliseconds
|
||||
|
||||
const DISABLE_HOVER_TIMEOUT = 500; // milliseconds
|
||||
|
||||
const THUMBNAIL_DEFAULT_SIZE = 256;
|
||||
@ -50,6 +52,8 @@ AltTabPopup.prototype = {
|
||||
this._thumbnailTimeoutId = 0;
|
||||
this._motionTimeoutId = 0;
|
||||
|
||||
this.thumbnailsVisible = false;
|
||||
|
||||
// Initially disable hover so we ignore the enter-event if
|
||||
// the switcher appears underneath the current pointer location
|
||||
this._disableHover();
|
||||
@ -133,7 +137,7 @@ AltTabPopup.prototype = {
|
||||
this.actor.connect('button-press-event', Lang.bind(this, this._clickedOutside));
|
||||
this.actor.connect('scroll-event', Lang.bind(this, this._onScroll));
|
||||
|
||||
this._appSwitcher = new AppSwitcher(apps);
|
||||
this._appSwitcher = new AppSwitcher(apps, this);
|
||||
this.actor.add_actor(this._appSwitcher.actor);
|
||||
this._appSwitcher.connect('item-activated', Lang.bind(this, this._appActivated));
|
||||
this._appSwitcher.connect('item-entered', Lang.bind(this, this._appEntered));
|
||||
@ -457,11 +461,15 @@ AltTabPopup.prototype = {
|
||||
},
|
||||
|
||||
_destroyThumbnails : function() {
|
||||
Tweener.addTween(this._thumbnails.actor,
|
||||
let thumbnailsActor = this._thumbnails.actor;
|
||||
Tweener.addTween(thumbnailsActor,
|
||||
{ opacity: 0,
|
||||
time: THUMBNAIL_FADE_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: function() { this.destroy(); }
|
||||
onComplete: Lang.bind(this, function() {
|
||||
thumbnailsActor.destroy();
|
||||
this.thumbnailsVisible = false;
|
||||
})
|
||||
});
|
||||
this._thumbnails = null;
|
||||
},
|
||||
@ -477,7 +485,8 @@ AltTabPopup.prototype = {
|
||||
Tweener.addTween(this._thumbnails.actor,
|
||||
{ opacity: 255,
|
||||
time: THUMBNAIL_FADE_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this, function () { this.thumbnailsVisible = true; })
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -591,16 +600,20 @@ SwitcherList.prototype = {
|
||||
this._list.add_actor(bbox);
|
||||
|
||||
let n = this._items.length;
|
||||
bbox.connect('clicked', Lang.bind(this, function () {
|
||||
this._itemActivated(n);
|
||||
}));
|
||||
bbox.connect('enter-event', Lang.bind(this, function () {
|
||||
this._itemEntered(n);
|
||||
}));
|
||||
bbox.connect('clicked', Lang.bind(this, function() { this._onItemClicked(n); }));
|
||||
bbox.connect('enter-event', Lang.bind(this, function() { this._onItemEnter(n); }));
|
||||
|
||||
this._items.push(bbox);
|
||||
},
|
||||
|
||||
_onItemClicked: function (index) {
|
||||
this._itemActivated(index);
|
||||
},
|
||||
|
||||
_onItemEnter: function (index) {
|
||||
this._itemEntered(index);
|
||||
},
|
||||
|
||||
addSeparator: function () {
|
||||
let box = new St.Bin({ style_class: 'separator' });
|
||||
this._separator = box;
|
||||
@ -819,14 +832,14 @@ AppIcon.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
function AppSwitcher(apps) {
|
||||
this._init(apps);
|
||||
function AppSwitcher(apps, altTabPopup) {
|
||||
this._init(apps, altTabPopup);
|
||||
}
|
||||
|
||||
AppSwitcher.prototype = {
|
||||
__proto__ : SwitcherList.prototype,
|
||||
|
||||
_init : function(apps) {
|
||||
_init : function(apps, altTabPopup) {
|
||||
SwitcherList.prototype._init.call(this, true);
|
||||
|
||||
// Construct the AppIcons, sort by time, add to the popup
|
||||
@ -858,6 +871,8 @@ AppSwitcher.prototype = {
|
||||
|
||||
this._curApp = -1;
|
||||
this._iconSize = 0;
|
||||
this._altTabPopup = altTabPopup;
|
||||
this._mouseTimeOutId = 0;
|
||||
},
|
||||
|
||||
_getPreferredHeight: function (actor, forWidth, alloc) {
|
||||
@ -875,9 +890,9 @@ AppSwitcher.prototype = {
|
||||
totalSpacing += this._separator.width + this._list.spacing;
|
||||
|
||||
// We just assume the whole screen here due to weirdness happing with the passed width
|
||||
let focus = global.get_focus_monitor();
|
||||
let primary = global.get_primary_monitor();
|
||||
let parentPadding = this.actor.get_parent().get_theme_node().get_horizontal_padding();
|
||||
let availWidth = focus.width - parentPadding - this.actor.get_theme_node().get_horizontal_padding();
|
||||
let availWidth = primary.width - parentPadding - this.actor.get_theme_node().get_horizontal_padding();
|
||||
let height = 0;
|
||||
|
||||
for(let i = 0; i < iconSizes.length; i++) {
|
||||
@ -922,6 +937,29 @@ AppSwitcher.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
// We override SwitcherList's _onItemEnter method to delay
|
||||
// activation when the thumbnail list is open
|
||||
_onItemEnter: function (index) {
|
||||
if (this._mouseTimeOutId != 0)
|
||||
Mainloop.source_remove(this._mouseTimeOutId);
|
||||
if (this._altTabPopup.thumbnailsVisible) {
|
||||
this._mouseTimeOutId = Mainloop.timeout_add(APP_ICON_HOVER_TIMEOUT,
|
||||
Lang.bind(this, function () {
|
||||
this._enterItem(index);
|
||||
this._mouseTimeOutId = 0;
|
||||
return false;
|
||||
}));
|
||||
} else
|
||||
this._itemEntered(index);
|
||||
},
|
||||
|
||||
_enterItem: function(index) {
|
||||
let [x, y, mask] = global.get_pointer();
|
||||
let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y);
|
||||
if (this._items[index].contains(pickedActor))
|
||||
this._itemEntered(index);
|
||||
},
|
||||
|
||||
// We override SwitcherList's highlight() method to also deal with
|
||||
// the AppSwitcher->ThumbnailList arrows. Apps with only 1 window
|
||||
// will hide their arrows by default, but show them when their
|
||||
|
@ -40,9 +40,18 @@ AlphabeticalView.prototype = {
|
||||
this.actor = new St.ScrollView({ x_fill: true,
|
||||
y_fill: false,
|
||||
y_align: St.Align.START,
|
||||
vshadows: true });
|
||||
vfade: true });
|
||||
this.actor.add_actor(box);
|
||||
this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
||||
this.actor.connect('notify::mapped', Lang.bind(this,
|
||||
function() {
|
||||
if (!this.actor.mapped)
|
||||
return;
|
||||
|
||||
let adjustment = this.actor.vscroll.adjustment;
|
||||
let direction = Overview.SwipeScrollDirection.VERTICAL;
|
||||
Main.overview.setScrollAdjustment(adjustment, direction);
|
||||
}));
|
||||
},
|
||||
|
||||
_removeAll: function() {
|
||||
@ -214,14 +223,20 @@ BaseAppSearchProvider.prototype = {
|
||||
'icon': app.create_icon_texture(Search.RESULT_ICON_SIZE)};
|
||||
},
|
||||
|
||||
activateResult: function(id) {
|
||||
activateResult: function(id, params) {
|
||||
params = Params.parse(params, { workspace: null,
|
||||
timestamp: null });
|
||||
|
||||
let app = this._appSys.get_app(id);
|
||||
app.activate();
|
||||
app.activate(params.workspace ? params.workspace.index() : -1);
|
||||
},
|
||||
|
||||
dragActivateResult: function(id) {
|
||||
dragActivateResult: function(id, params) {
|
||||
params = Params.parse(params, { workspace: null,
|
||||
timestamp: null });
|
||||
|
||||
let app = this._appSys.get_app(id);
|
||||
app.open_new_window();
|
||||
app.open_new_window(params.workspace ? params.workspace.get_index() : -1);
|
||||
}
|
||||
};
|
||||
|
||||
@ -281,21 +296,21 @@ PrefsSearchProvider.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
function AppIcon(app) {
|
||||
this._init(app);
|
||||
function AppIcon(app, params) {
|
||||
this._init(app, params);
|
||||
}
|
||||
|
||||
AppIcon.prototype = {
|
||||
__proto__: IconGrid.BaseIcon.prototype,
|
||||
|
||||
_init : function(app) {
|
||||
_init : function(app, params) {
|
||||
this.app = app;
|
||||
|
||||
let label = this.app.get_name();
|
||||
|
||||
IconGrid.BaseIcon.prototype._init.call(this,
|
||||
label,
|
||||
{ setSizeManually: true });
|
||||
params);
|
||||
},
|
||||
|
||||
createIcon: function(iconSize) {
|
||||
@ -303,12 +318,12 @@ AppIcon.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
function AppWellIcon(app) {
|
||||
this._init(app);
|
||||
function AppWellIcon(app, iconParams) {
|
||||
this._init(app, iconParams);
|
||||
}
|
||||
|
||||
AppWellIcon.prototype = {
|
||||
_init : function(app) {
|
||||
_init : function(app, iconParams) {
|
||||
this.app = app;
|
||||
this.actor = new St.Clickable({ style_class: 'app-well-app',
|
||||
reactive: true,
|
||||
@ -316,7 +331,7 @@ AppWellIcon.prototype = {
|
||||
y_fill: true });
|
||||
this.actor._delegate = this;
|
||||
|
||||
this.icon = new AppIcon(app);
|
||||
this.icon = new AppIcon(app, iconParams);
|
||||
this.actor.set_child(this.icon.actor);
|
||||
|
||||
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
|
||||
@ -388,7 +403,7 @@ AppWellIcon.prototype = {
|
||||
if (newWorkspace != null) {
|
||||
newWorkspace.activate(global.get_current_time());
|
||||
this.emit('launching');
|
||||
this.app.open_new_window();
|
||||
this.app.open_new_window(-1);
|
||||
Main.overview.hide();
|
||||
}
|
||||
} else if (button == 3) {
|
||||
@ -476,9 +491,9 @@ AppWellIcon.prototype = {
|
||||
|
||||
if (modifiers & Clutter.ModifierType.CONTROL_MASK
|
||||
&& this.app.state == Shell.AppState.RUNNING) {
|
||||
this.app.open_new_window();
|
||||
this.app.open_new_window(-1);
|
||||
} else {
|
||||
this.app.activate();
|
||||
this.app.activate(-1);
|
||||
}
|
||||
Main.overview.hide();
|
||||
},
|
||||
@ -488,8 +503,11 @@ AppWellIcon.prototype = {
|
||||
return this._menu.menuEventFilter(event);
|
||||
},
|
||||
|
||||
shellWorkspaceLaunch : function() {
|
||||
this.app.open_new_window();
|
||||
shellWorkspaceLaunch : function(params) {
|
||||
params = Params.parse(params, { workspace: null,
|
||||
timestamp: null });
|
||||
|
||||
this.app.open_new_window(params.workspace ? params.workspace.index() : -1);
|
||||
},
|
||||
|
||||
getDragActor: function() {
|
||||
@ -621,7 +639,7 @@ AppIconMenu.prototype = {
|
||||
},
|
||||
|
||||
_findMetaWindowForActor: function (actor) {
|
||||
if (actor._delegate instanceof Workspace.WindowClone)
|
||||
if (actor._delegate.metaWindow)
|
||||
return actor._delegate.metaWindow;
|
||||
else if (actor.get_meta_window)
|
||||
return actor.get_meta_window();
|
||||
@ -658,7 +676,7 @@ AppIconMenu.prototype = {
|
||||
let metaWindow = child._window;
|
||||
this.emit('activate-window', metaWindow);
|
||||
} else if (child == this._newWindowMenuItem) {
|
||||
this._source.app.open_new_window();
|
||||
this._source.app.open_new_window(-1);
|
||||
this.emit('activate-window', null);
|
||||
} else if (child == this._toggleFavoriteMenuItem) {
|
||||
let favs = AppFavorites.getAppFavorites();
|
||||
|
@ -27,6 +27,7 @@ BoxPointer.prototype = {
|
||||
_init: function(arrowSide, binProperties) {
|
||||
this._arrowSide = arrowSide;
|
||||
this._arrowOrigin = 0;
|
||||
this._arrowCorner = null;
|
||||
this.actor = new St.Bin({ x_fill: true,
|
||||
y_fill: true });
|
||||
this._container = new Shell.GenericContainer();
|
||||
@ -212,47 +213,140 @@ BoxPointer.prototype = {
|
||||
cr.translate(rise, 0);
|
||||
}
|
||||
|
||||
cr.moveTo(borderRadius, halfBorder);
|
||||
let [x1, y1] = [halfBorder, halfBorder];
|
||||
let [x2, y2] = [boxWidth - halfBorder, boxHeight - halfBorder];
|
||||
|
||||
cr.moveTo(x1 + borderRadius, y1);
|
||||
if (this._arrowSide == St.Side.TOP) {
|
||||
cr.lineTo(this._arrowOrigin - halfBase, halfBorder);
|
||||
cr.lineTo(this._arrowOrigin, halfBorder - rise);
|
||||
cr.lineTo(this._arrowOrigin + halfBase, halfBorder);
|
||||
}
|
||||
cr.lineTo(boxWidth - borderRadius, halfBorder);
|
||||
if (this._arrowCorner == St.Corner.TOPLEFT) {
|
||||
cr.moveTo(x1, y1);
|
||||
cr.lineTo(x1, y1 - rise);
|
||||
cr.lineTo(x1 + halfBase, y1);
|
||||
cr.lineTo(x2 - borderRadius, y1);
|
||||
} else if (this._arrowCorner == St.Corner.TOPRIGHT) {
|
||||
cr.lineTo(x2 - halfBase, y1);
|
||||
cr.lineTo(x2, y1 - rise);
|
||||
} else if (this._arrowOrigin < (x1 + (borderRadius + halfBase))) {
|
||||
cr.lineTo(this._arrowOrigin, y1);
|
||||
cr.lineTo(this._arrowOrigin, y1 - rise);
|
||||
cr.lineTo(this._arrowOrigin + halfBase, y1);
|
||||
cr.lineTo(x2 - borderRadius, y1);
|
||||
} else if (this._arrowOrigin > (x2 - (borderRadius + halfBase))) {
|
||||
cr.lineTo(this._arrowOrigin - halfBase, y1);
|
||||
cr.lineTo(this._arrowOrigin, y1 - rise);
|
||||
cr.lineTo(this._arrowOrigin, y1);
|
||||
cr.lineTo(x2 - borderRadius, y1);
|
||||
} else {
|
||||
cr.lineTo(this._arrowOrigin - halfBase, y1);
|
||||
cr.lineTo(this._arrowOrigin, y1 - rise);
|
||||
cr.lineTo(this._arrowOrigin + halfBase, y1);
|
||||
cr.lineTo(x2 - borderRadius, y1);
|
||||
}
|
||||
} else
|
||||
cr.lineTo(x2 - borderRadius, y1);
|
||||
|
||||
cr.arc(boxWidth - borderRadius - halfBorder, borderRadius + halfBorder, borderRadius,
|
||||
3*Math.PI/2, Math.PI*2);
|
||||
// top-right corner
|
||||
if (this._arrowCorner != St.Corner.TOPRIGHT)
|
||||
cr.arc(x2 - borderRadius, y1 + borderRadius, borderRadius,
|
||||
3*Math.PI/2, Math.PI*2);
|
||||
|
||||
if (this._arrowSide == St.Side.RIGHT) {
|
||||
cr.lineTo(boxWidth - halfBorder, this._arrowOrigin - halfBase);
|
||||
cr.lineTo(boxWidth - halfBorder + rise, this._arrowOrigin);
|
||||
cr.lineTo(boxWidth - halfBorder, this._arrowOrigin + halfBase);
|
||||
}
|
||||
cr.lineTo(boxWidth - halfBorder, boxHeight - borderRadius);
|
||||
if (this._arrowCorner == St.Corner.TOPRIGHT) {
|
||||
cr.lineTo(x2, y1);
|
||||
cr.lineTo(x2 + rise, y1);
|
||||
cr.lineTo(x2, y1 + halfBase);
|
||||
cr.lineTo(x2, y2 - borderRadius);
|
||||
} else if (this._arrowCorner == St.Corner.BOTTOMRIGHT) {
|
||||
cr.moveTo(x2, y2 - halfBase);
|
||||
cr.lineTo(x2 + rise, y2);
|
||||
} else if (this._arrowOrigin < (y1 + (borderRadius + halfBase))) {
|
||||
cr.lineTo(x2, this._arrowOrigin);
|
||||
cr.lineTo(x2 + rise, this._arrowOrigin);
|
||||
cr.lineTo(x2, this._arrowOrigin + halfBase);
|
||||
cr.lineTo(x2, y2 - borderRadius);
|
||||
} else if (this._arrowOrigin > (y2 - (borderRadius + halfBase))) {
|
||||
cr.lineTo(x2, this._arrowOrigin - halfBase);
|
||||
cr.lineTo(x2 + rise, this._arrowOrigin);
|
||||
cr.lineTo(x2, this._arrowOrigin);
|
||||
cr.lineTo(x2, y2 - borderRadius);
|
||||
} else {
|
||||
cr.lineTo(x2, this._arrowOrigin - halfBase);
|
||||
cr.lineTo(x2 + rise, this._arrowOrigin);
|
||||
cr.lineTo(x2, this._arrowOrigin + halfBase);
|
||||
cr.lineTo(x2, y2 - borderRadius);
|
||||
}
|
||||
} else
|
||||
cr.lineTo(x2, y2 - borderRadius);
|
||||
|
||||
cr.arc(boxWidth - borderRadius - halfBorder, boxHeight - borderRadius - halfBorder, borderRadius,
|
||||
0, Math.PI/2);
|
||||
// bottom-right corner
|
||||
if (this._arrowCorner != St.Corner.BOTTOMRIGHT)
|
||||
cr.arc(x2 - borderRadius, y2 - borderRadius, borderRadius,
|
||||
0, Math.PI/2);
|
||||
|
||||
if (this._arrowSide == St.Side.BOTTOM) {
|
||||
cr.lineTo(this._arrowOrigin + halfBase, boxHeight - halfBorder);
|
||||
cr.lineTo(this._arrowOrigin, boxHeight - halfBorder + rise);
|
||||
cr.lineTo(this._arrowOrigin - halfBase, boxHeight - halfBorder);
|
||||
}
|
||||
cr.lineTo(borderRadius, boxHeight - halfBorder);
|
||||
if (this._arrowCorner == St.Corner.BOTTOMLEFT) {
|
||||
cr.lineTo(x1 + halfBase, y2);
|
||||
cr.lineTo(x1, y2 + rise);
|
||||
} else if (this._arrowCorner == St.Corner.BOTTOMRIGHT) {
|
||||
cr.lineTo(x2, y2 + rise);
|
||||
cr.lineTo(x2 - halfBase, y2);
|
||||
cr.lineTo(x1 + borderRadius, y2);
|
||||
} else if (this._arrowOrigin < (x1 + (borderRadius + halfBase))) {
|
||||
cr.lineTo(this._arrowOrigin + halfBase, y2);
|
||||
cr.lineTo(this._arrowOrigin, y2 + rise);
|
||||
cr.lineTo(this._arrowOrigin, y2);
|
||||
cr.lineTo(x1 + borderRadius, y2);
|
||||
} else if (this._arrowOrigin > (x2 - (borderRadius + halfBase))) {
|
||||
cr.lineTo(this._arrowOrigin, y2);
|
||||
cr.lineTo(this._arrowOrigin, y2 + rise);
|
||||
cr.lineTo(this._arrowOrigin - halfBase, y2);
|
||||
cr.lineTo(x1 + borderRadius, y2);
|
||||
} else {
|
||||
cr.lineTo(this._arrowOrigin + halfBase, y2);
|
||||
cr.lineTo(this._arrowOrigin, y2 + rise);
|
||||
cr.lineTo(this._arrowOrigin - halfBase, y2);
|
||||
cr.lineTo(x1 + borderRadius, y2);
|
||||
}
|
||||
} else
|
||||
cr.lineTo(x1 + borderRadius, y2);
|
||||
|
||||
cr.arc(borderRadius + halfBorder, boxHeight - borderRadius - halfBorder, borderRadius,
|
||||
Math.PI/2, Math.PI);
|
||||
// bottom-left corner
|
||||
if (this._arrowCorner != St.Corner.BOTTOMLEFT)
|
||||
cr.arc(x1 + borderRadius, y2 - borderRadius, borderRadius,
|
||||
Math.PI/2, Math.PI);
|
||||
|
||||
if (this._arrowSide == St.Side.LEFT) {
|
||||
cr.lineTo(halfBorder, this._arrowOrigin + halfBase);
|
||||
cr.lineTo(halfBorder - rise, this._arrowOrigin);
|
||||
cr.lineTo(halfBorder, this._arrowOrigin - halfBase);
|
||||
}
|
||||
cr.lineTo(halfBorder, borderRadius);
|
||||
if (this._arrowCorner == St.Corner.TOPLEFT) {
|
||||
cr.lineTo(x2, y1 + halfBase);
|
||||
cr.lineTo(x1 - rise, y1);
|
||||
} else if (this._arrowCorner == St.Corner.BOTTOMLEFT) {
|
||||
cr.lineTo(x1 + rise, y2);
|
||||
cr.moveTo(x1, y2 - halfBase);
|
||||
} else if (this._arrowOrigin < (y1 + (borderRadius + halfBase))) {
|
||||
cr.lineTo(x1, this._arrowOrigin + halfBase);
|
||||
cr.lineTo(x1 - rise, this._arrowOrigin);
|
||||
cr.lineTo(x1, this._arrowOrigin);
|
||||
cr.lineTo(x1, y1 + borderRadius);
|
||||
} else if (this._arrowOrigin > (y2 - (borderRadius + halfBase))) {
|
||||
cr.lineTo(x1, this._arrowOrigin);
|
||||
cr.lineTo(x1 - rise, this._arrowOrigin);
|
||||
cr.lineTo(x1, this._arrowOrigin - halfBase);
|
||||
cr.lineTo(x1, y1 + borderRadius);
|
||||
} else {
|
||||
cr.lineTo(x1, this._arrowOrigin + halfBase);
|
||||
cr.lineTo(x1 - rise, this._arrowOrigin);
|
||||
cr.lineTo(x1, this._arrowOrigin - halfBase);
|
||||
cr.lineTo(x1, y1 + borderRadius);
|
||||
}
|
||||
} else
|
||||
cr.lineTo(x1, y1 + borderRadius);
|
||||
|
||||
cr.arc(borderRadius + halfBorder, borderRadius + halfBorder, borderRadius,
|
||||
Math.PI, 3*Math.PI/2);
|
||||
// top-left corner
|
||||
if (this._arrowCorner != St.Corner.TOPLEFT)
|
||||
cr.arc(x1 + borderRadius, y1 + borderRadius, borderRadius,
|
||||
Math.PI, 3*Math.PI/2);
|
||||
else
|
||||
cr.lineTo(x1, y1);
|
||||
|
||||
Clutter.cairo_set_source_color(cr, backgroundColor);
|
||||
cr.fillPreserve();
|
||||
@ -269,7 +363,7 @@ BoxPointer.prototype = {
|
||||
// Position correctly relative to the sourceActor
|
||||
let [sourceX, sourceY] = sourceActor.get_transformed_position();
|
||||
let [sourceWidth, sourceHeight] = sourceActor.get_transformed_size();
|
||||
|
||||
let [sourceCenterX, sourceCenterY] = [sourceX + (sourceWidth / 2), sourceY + (sourceHeight / 2)];
|
||||
let [minWidth, minHeight, natWidth, natHeight] = this.actor.get_preferred_size();
|
||||
|
||||
// We also want to keep it onscreen, and separated from the
|
||||
@ -277,10 +371,14 @@ BoxPointer.prototype = {
|
||||
// separated from its sourceActor
|
||||
let primary = global.get_primary_monitor();
|
||||
let themeNode = this.actor.get_theme_node();
|
||||
let arrowRise = themeNode.get_length('-arrow-rise');
|
||||
let halfBorder = themeNode.get_length('-arrow-border-width') / 2;
|
||||
let halfBase = themeNode.get_length('-arrow-base') / 2;
|
||||
let borderRadius = themeNode.get_length('-arrow-border-radius');
|
||||
|
||||
let margin = 2 * borderRadius + halfBorder;
|
||||
|
||||
let resX, resY;
|
||||
this._arrowCorner = null;
|
||||
|
||||
switch (this._arrowSide) {
|
||||
case St.Side.TOP:
|
||||
@ -304,40 +402,58 @@ BoxPointer.prototype = {
|
||||
case St.Side.BOTTOM:
|
||||
switch (alignment) {
|
||||
case St.Align.START:
|
||||
resX = sourceX - 2 * borderRadius;
|
||||
resX = sourceCenterX - (halfBase + borderRadius + halfBorder);
|
||||
break;
|
||||
case St.Align.MIDDLE:
|
||||
resX = sourceX - Math.floor((natWidth - sourceWidth) / 2);
|
||||
resX = sourceCenterX - (natWidth / 2);
|
||||
break;
|
||||
case St.Align.END:
|
||||
resX = sourceX - (natWidth - sourceWidth) + 2 * borderRadius;
|
||||
resX = sourceCenterX - natWidth + (halfBase + borderRadius + halfBorder);
|
||||
break;
|
||||
}
|
||||
if (sourceCenterX < margin) {
|
||||
// Not enough space to the top
|
||||
this._arrowCorner = (this._arrowSide == St.Side.TOP) ? St.Corner.TOPLEFT : St.Corner.BOTTOMLEFT;
|
||||
resX = primary.x + 10;
|
||||
} else if (sourceCenterX > (primary.x + primary.width - margin)) {
|
||||
// Not enough space to the botom
|
||||
this._arrowCorner = (this._arrowSide == St.Side.TOP) ? St.Corner.TOPRIGHT : St.Corner.BOTTOMRIGHT;
|
||||
resX = primary.x + primary.width - (10 + natWidth);
|
||||
}
|
||||
|
||||
resX = Math.min(resX, primary.x + primary.width - natWidth - arrowRise - gap);
|
||||
resX = Math.max(resX, primary.x);
|
||||
|
||||
this.setArrowOrigin((sourceX - resX) + Math.floor(sourceWidth / 2));
|
||||
resX = Math.max(resX, primary.x + 10);
|
||||
resX = Math.min(resX, primary.x + primary.width - (10 + natWidth));
|
||||
this.setArrowOrigin(sourceCenterX - resX);
|
||||
break;
|
||||
|
||||
case St.Side.LEFT:
|
||||
case St.Side.RIGHT:
|
||||
switch (alignment) {
|
||||
case St.Align.START:
|
||||
resY = sourceY - 2 * borderRadius;
|
||||
resY = sourceCenterY - (halfBase + borderRadius + halfBorder);
|
||||
break;
|
||||
case St.Align.MIDDLE:
|
||||
resY = sourceY - Math.floor((natHeight - sourceHeight) / 2);
|
||||
resY = sourceCenterY - (natHeight / 2);
|
||||
break;
|
||||
case St.Align.END:
|
||||
resY = sourceY - (natHeight - sourceHeight) + 2 * borderRadius;
|
||||
resY = sourceCenterY - natHeight + (halfBase + borderRadius + halfBorder);
|
||||
break;
|
||||
}
|
||||
if (sourceCenterY < margin) {
|
||||
// Not enough space to the left
|
||||
this._arrowCorner = (this._arrowSide == St.Side.LEFT) ? St.Corner.TOPLEFT : St.Corner.TORIGHT;
|
||||
resY = 10;
|
||||
}
|
||||
else if (sourceCenterY > (primary.y + primary.height - margin)) {
|
||||
// Not enough space to the right
|
||||
this._arrowCorner = (this._arrowSide == St.Side.LEFT) ? St.Corner.BOTTOMLEFT : St.Corner.BOTTOMRIGHT;
|
||||
resY = primary.y + primary.height - (10 + natHeight);
|
||||
}
|
||||
|
||||
resY = Math.min(resY, primary.y + primary.height - natHeight - arrowRise - gap);
|
||||
resY = Math.max(resY, primary.y);
|
||||
resY = Math.max(resY, primary.y + 10);
|
||||
resY = Math.min(resY, primary.y + primary.height - (10 + natHeight));
|
||||
|
||||
this.setArrowOrigin((sourceY - resY) + Math.floor(sourceHeight / 2));
|
||||
this.setArrowOrigin(sourceCenterY - resY);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -4,19 +4,78 @@ const Clutter = imports.gi.Clutter;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const St = imports.gi.St;
|
||||
const Signals = imports.signals;
|
||||
const Pango = imports.gi.Pango;
|
||||
const Gettext_gtk30 = imports.gettext.domain('gtk30');
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Shell = imports.gi.Shell;
|
||||
|
||||
const MSECS_IN_DAY = 24 * 60 * 60 * 1000;
|
||||
const WEEKDATE_HEADER_WIDTH_DIGITS = 3;
|
||||
const SHOW_WEEKDATE_KEY = 'show-weekdate';
|
||||
|
||||
// in org.gnome.desktop.interface
|
||||
const CLOCK_FORMAT_KEY = 'clock-format';
|
||||
|
||||
function _sameDay(dateA, dateB) {
|
||||
return (dateA.getDate() == dateB.getDate() &&
|
||||
dateA.getMonth() == dateB.getMonth() &&
|
||||
dateA.getYear() == dateB.getYear());
|
||||
}
|
||||
|
||||
function _sameYear(dateA, dateB) {
|
||||
return (dateA.getYear() == dateB.getYear());
|
||||
}
|
||||
|
||||
/* TODO: maybe needs config - right now we assume that Saturday and
|
||||
* Sunday are non-work days (not true in e.g. Israel, it's Sunday and
|
||||
* Monday there)
|
||||
*/
|
||||
function _isWorkDay(date) {
|
||||
return date.getDay() != 0 && date.getDay() != 6;
|
||||
}
|
||||
|
||||
function _getBeginningOfDay(date) {
|
||||
let ret = new Date(date.getTime());
|
||||
ret.setHours(0);
|
||||
ret.setMinutes(0);
|
||||
ret.setSeconds(0);
|
||||
ret.setMilliseconds(0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
function _getEndOfDay(date) {
|
||||
let ret = new Date(date.getTime());
|
||||
ret.setHours(23);
|
||||
ret.setMinutes(59);
|
||||
ret.setSeconds(59);
|
||||
ret.setMilliseconds(999);
|
||||
return ret;
|
||||
}
|
||||
|
||||
function _formatEventTime(event, clockFormat) {
|
||||
let ret;
|
||||
if (event.allDay) {
|
||||
/* Translators: Shown in calendar event list for all day events */
|
||||
ret = _("All Day");
|
||||
} else {
|
||||
switch (clockFormat) {
|
||||
case '24h':
|
||||
ret = event.date.toLocaleFormat('%H:%M');
|
||||
break;
|
||||
|
||||
default:
|
||||
/* explicit fall-through */
|
||||
case '12h':
|
||||
ret = event.date.toLocaleFormat('%l:%M %p');
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function _getCalendarWeekForDate(date) {
|
||||
// Based on the algorithms found here:
|
||||
// http://en.wikipedia.org/wiki/Talk:ISO_week_date
|
||||
@ -43,12 +102,259 @@ function _getDigitWidth(actor){
|
||||
return width;
|
||||
}
|
||||
|
||||
function Calendar() {
|
||||
function _getCalendarDayAbbreviation(dayNumber) {
|
||||
let abbreviations = [
|
||||
/* Translators: Calendar grid abbreviation for Sunday.
|
||||
*
|
||||
* NOTE: These abbreviations are always shown together and in
|
||||
* order, e.g. "S M T W T F S".
|
||||
*/
|
||||
_("S"),
|
||||
/* Translators: Calendar grid abbreviation for Monday */
|
||||
_("M"),
|
||||
/* Translators: Calendar grid abbreviation for Tuesday */
|
||||
_("T"),
|
||||
/* Translators: Calendar grid abbreviation for Wednesday */
|
||||
_("W"),
|
||||
/* Translators: Calendar grid abbreviation for Thursday */
|
||||
_("T"),
|
||||
/* Translators: Calendar grid abbreviation for Friday */
|
||||
_("F"),
|
||||
/* Translators: Calendar grid abbreviation for Saturday */
|
||||
_("S")
|
||||
];
|
||||
return abbreviations[dayNumber];
|
||||
}
|
||||
|
||||
function _getEventDayAbbreviation(dayNumber) {
|
||||
let abbreviations = [
|
||||
/* Translators: Event list abbreviation for Sunday.
|
||||
*
|
||||
* NOTE: These abbreviations are normally not shown together
|
||||
* so they need to be unique (e.g. Tuesday and Thursday cannot
|
||||
* both be 'T').
|
||||
*/
|
||||
_("Su"),
|
||||
/* Translators: Event list abbreviation for Monday */
|
||||
_("M"),
|
||||
/* Translators: Event list abbreviation for Tuesday */
|
||||
_("T"),
|
||||
/* Translators: Event list abbreviation for Wednesday */
|
||||
_("W"),
|
||||
/* Translators: Event list abbreviation for Thursday */
|
||||
_("Th"),
|
||||
/* Translators: Event list abbreviation for Friday */
|
||||
_("F"),
|
||||
/* Translators: Event list abbreviation for Saturday */
|
||||
_("S")
|
||||
];
|
||||
return abbreviations[dayNumber];
|
||||
}
|
||||
|
||||
// Abstraction for an appointment/event in a calendar
|
||||
|
||||
function CalendarEvent(date, summary, allDay) {
|
||||
this._init(date, summary, allDay);
|
||||
}
|
||||
|
||||
CalendarEvent.prototype = {
|
||||
_init: function(date, summary, allDay) {
|
||||
this.date = date;
|
||||
this.summary = summary;
|
||||
this.allDay = allDay;
|
||||
}
|
||||
};
|
||||
|
||||
// Interface for appointments/events - e.g. the contents of a calendar
|
||||
//
|
||||
|
||||
// First, an implementation with no events
|
||||
function EmptyEventSource() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
Calendar.prototype = {
|
||||
EmptyEventSource.prototype = {
|
||||
_init: function() {
|
||||
},
|
||||
|
||||
requestRange: function(begin, end) {
|
||||
},
|
||||
|
||||
getEvents: function(begin, end) {
|
||||
let result = [];
|
||||
return result;
|
||||
},
|
||||
|
||||
hasEvents: function(day) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(EmptyEventSource.prototype);
|
||||
|
||||
// Second, wrap native Evolution event source
|
||||
function EvolutionEventSource() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
EvolutionEventSource.prototype = {
|
||||
_init: function() {
|
||||
this._native = new Shell.EvolutionEventSource();
|
||||
this._native.connect('changed', Lang.bind(this, function() {
|
||||
this.emit('changed');
|
||||
}));
|
||||
},
|
||||
|
||||
requestRange: function(begin, end) {
|
||||
this._native.request_range(begin.getTime(), end.getTime());
|
||||
},
|
||||
|
||||
getEvents: function(begin, end) {
|
||||
let result = [];
|
||||
let nativeEvents = this._native.get_events(begin.getTime(), end.getTime());
|
||||
for (let n = 0; n < nativeEvents.length; n++) {
|
||||
let nativeEvent = nativeEvents[n];
|
||||
result.push(new CalendarEvent(new Date(nativeEvent.msec_begin), nativeEvent.summary, nativeEvent.all_day));
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
hasEvents: function(day) {
|
||||
let dayBegin = _getBeginningOfDay(day);
|
||||
let dayEnd = _getEndOfDay(day);
|
||||
|
||||
let events = this.getEvents(dayBegin, dayEnd);
|
||||
|
||||
if (events.length == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(EvolutionEventSource.prototype);
|
||||
|
||||
// Finally, an implementation with fake events
|
||||
function FakeEventSource() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
FakeEventSource.prototype = {
|
||||
_init: function() {
|
||||
|
||||
this._fakeEvents = [];
|
||||
|
||||
// Generate fake events
|
||||
//
|
||||
let midnightToday = _getBeginningOfDay(new Date());
|
||||
let summary = '';
|
||||
|
||||
// '10-oclock pow-wow' is an event occuring IN THE PAST every four days at 10am
|
||||
for (let n = 0; n < 10; n++) {
|
||||
let t = new Date(midnightToday.getTime() - n * 4 * 86400 * 1000);
|
||||
t.setHours(10);
|
||||
summary = '10-oclock pow-wow (n=' + n + ')';
|
||||
this._fakeEvents.push(new CalendarEvent(t, summary, false));
|
||||
}
|
||||
|
||||
// '11-oclock thing' is an event occuring every three days at 11am
|
||||
for (let n = 0; n < 10; n++) {
|
||||
let t = new Date(midnightToday.getTime() + n * 3 * 86400 * 1000);
|
||||
t.setHours(11);
|
||||
summary = '11-oclock thing (n=' + n + ')';
|
||||
this._fakeEvents.push(new CalendarEvent(t, summary, false));
|
||||
}
|
||||
|
||||
// 'Weekly Meeting' is an event occuring every seven days at 1:45pm (two days displaced)
|
||||
for (let n = 0; n < 5; n++) {
|
||||
let t = new Date(midnightToday.getTime() + (n * 7 + 2) * 86400 * 1000);
|
||||
t.setHours(13);
|
||||
t.setMinutes(45);
|
||||
summary = 'Weekly Meeting (n=' + n + ')';
|
||||
this._fakeEvents.push(new CalendarEvent(t, summary, false));
|
||||
}
|
||||
|
||||
// 'Fun All Day' is an all-day event occuring every fortnight (three days displayed)
|
||||
for (let n = 0; n < 10; n++) {
|
||||
let t = new Date(midnightToday.getTime() + (n * 14 + 3) * 86400 * 1000);
|
||||
summary = 'Fun All Day (n=' + n + ')';
|
||||
this._fakeEvents.push(new CalendarEvent(t, summary, true));
|
||||
}
|
||||
|
||||
// 'Get Married' is an event that actually reflects reality (Dec 4, 2010) :-)
|
||||
this._fakeEvents.push(new CalendarEvent(new Date(2010, 11, 4, 16, 0), 'Get Married', false));
|
||||
|
||||
// ditto for 'NE Patriots vs NY Jets'
|
||||
this._fakeEvents.push(new CalendarEvent(new Date(2010, 11, 6, 20, 30), 'NE Patriots vs NY Jets', false));
|
||||
|
||||
// An event for tomorrow @6:30pm that is added/removed every five
|
||||
// seconds (to check that the ::changed signal works)
|
||||
let transientEventDate = new Date(midnightToday.getTime() + 86400 * 1000);
|
||||
transientEventDate.setHours(18);
|
||||
transientEventDate.setMinutes(30);
|
||||
transientEventDate.setSeconds(0);
|
||||
Mainloop.timeout_add(5000, Lang.bind(this, this._updateTransientEvent));
|
||||
this._includeTransientEvent = false;
|
||||
this._transientEvent = new CalendarEvent(transientEventDate, 'A Transient Event', false);
|
||||
this._transientEventCounter = 1;
|
||||
},
|
||||
|
||||
_updateTransientEvent: function() {
|
||||
this._includeTransientEvent = !this._includeTransientEvent;
|
||||
this._transientEventCounter = this._transientEventCounter + 1;
|
||||
this._transientEvent.summary = 'A Transient Event (' + this._transientEventCounter + ')';
|
||||
this.emit('changed');
|
||||
Mainloop.timeout_add(5000, Lang.bind(this, this._updateTransientEvent));
|
||||
},
|
||||
|
||||
requestRange: function(begin, end) {
|
||||
},
|
||||
|
||||
getEvents: function(begin, end) {
|
||||
let result = [];
|
||||
//log('begin:' + begin);
|
||||
//log('end: ' + end);
|
||||
for(let n = 0; n < this._fakeEvents.length; n++) {
|
||||
let event = this._fakeEvents[n];
|
||||
if (event.date >= begin && event.date <= end) {
|
||||
result.push(event);
|
||||
}
|
||||
//log('when:' + event.date + ' summary:' + event.summary);
|
||||
}
|
||||
if (this._includeTransientEvent && this._transientEvent.date >= begin && this._transientEvent.date <= end)
|
||||
result.push(this._transientEvent);
|
||||
result.sort(function(event1, event2) {
|
||||
return event1.date.getTime() - event2.date.getTime();
|
||||
});
|
||||
return result;
|
||||
},
|
||||
|
||||
hasEvents: function(day) {
|
||||
let dayBegin = _getBeginningOfDay(day);
|
||||
let dayEnd = _getEndOfDay(day);
|
||||
|
||||
let events = this.getEvents(dayBegin, dayEnd);
|
||||
|
||||
if (events.length == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
Signals.addSignalMethods(FakeEventSource.prototype);
|
||||
|
||||
// Calendar:
|
||||
// @eventSource: is an object implementing the EventSource API, e.g. the
|
||||
// requestRange(), getEvents(), hasEvents() methods and the ::changed signal.
|
||||
function Calendar(eventSource) {
|
||||
this._init(eventSource);
|
||||
}
|
||||
|
||||
Calendar.prototype = {
|
||||
_init: function(eventSource) {
|
||||
this._eventSource = eventSource;
|
||||
|
||||
this._eventSource.connect('changed', Lang.bind(this, this._update));
|
||||
|
||||
// FIXME: This is actually the fallback method for GTK+ for the week start;
|
||||
// GTK+ by preference uses nl_langinfo (NL_TIME_FIRST_WEEKDAY). We probably
|
||||
// should add a C function so we can do the full handling.
|
||||
@ -71,6 +377,7 @@ Calendar.prototype = {
|
||||
}
|
||||
|
||||
// Find the ordering for month/year in the calendar heading
|
||||
this._headerFormatWithoutYear = '%B';
|
||||
switch (Gettext_gtk30.gettext('calendar:MY')) {
|
||||
case 'calendar:MY':
|
||||
this._headerFormat = '%B %Y';
|
||||
@ -85,7 +392,7 @@ Calendar.prototype = {
|
||||
}
|
||||
|
||||
// Start off with the current date
|
||||
this.date = new Date();
|
||||
this._selectedDate = new Date();
|
||||
|
||||
this.actor = new St.Table({ homogeneous: false,
|
||||
style_class: 'calendar',
|
||||
@ -100,9 +407,10 @@ Calendar.prototype = {
|
||||
|
||||
// Sets the calendar to show a specific date
|
||||
setDate: function(date) {
|
||||
if (!_sameDay(date, this.date)) {
|
||||
this.date = date;
|
||||
if (!_sameDay(date, this._selectedDate)) {
|
||||
this._selectedDate = date;
|
||||
this._update();
|
||||
this.emit('selected-date-changed', new Date(this._selectedDate));
|
||||
}
|
||||
},
|
||||
|
||||
@ -116,45 +424,36 @@ Calendar.prototype = {
|
||||
{ row: 0, col: 0, col_span: offsetCols + 7 });
|
||||
|
||||
this.actor.connect('style-changed', Lang.bind(this, this._onStyleChange));
|
||||
let [backlabel, forwardlabel] = ['<', '>'];
|
||||
if (St.Widget.get_default_direction () == St.TextDirection.RTL) {
|
||||
[backlabel, forwardlabel] = [forwardlabel, backlabel];
|
||||
}
|
||||
|
||||
let back = new St.Button({ label: backlabel, style_class: 'calendar-change-month' });
|
||||
let back = new St.Button({ style_class: 'calendar-change-month-back' });
|
||||
this._topBox.add(back);
|
||||
back.connect('clicked', Lang.bind(this, this._prevMonth));
|
||||
back.connect('clicked', Lang.bind(this, this._onPrevMonthButtonClicked));
|
||||
|
||||
this._dateLabel = new St.Label();
|
||||
this._topBox.add(this._dateLabel, { expand: true, x_fill: false, x_align: St.Align.MIDDLE });
|
||||
this._monthLabel = new St.Label({style_class: 'calendar-month-label'});
|
||||
this._topBox.add(this._monthLabel, { expand: true, x_fill: false, x_align: St.Align.MIDDLE });
|
||||
|
||||
let forward = new St.Button({ label: forwardlabel, style_class: 'calendar-change-month' });
|
||||
let forward = new St.Button({ style_class: 'calendar-change-month-forward' });
|
||||
this._topBox.add(forward);
|
||||
forward.connect('clicked', Lang.bind(this, this._nextMonth));
|
||||
forward.connect('clicked', Lang.bind(this, this._onNextMonthButtonClicked));
|
||||
|
||||
// Add weekday labels...
|
||||
//
|
||||
// We need to figure out the abbreviated localized names for the days of the week;
|
||||
// we do this by just getting the next 7 days starting from right now and then putting
|
||||
// them in the right cell in the table. It doesn't matter if we add them in order
|
||||
let iter = new Date(this.date);
|
||||
let iter = new Date(this._selectedDate);
|
||||
iter.setSeconds(0); // Leap second protection. Hah!
|
||||
iter.setHours(12);
|
||||
|
||||
if (this._useWeekdate) {
|
||||
this._weekdateHeader = new St.Label();
|
||||
this.actor.add(this._weekdateHeader,
|
||||
{ row: 1,
|
||||
col: 0,
|
||||
x_fill: false, x_align: St.Align.MIDDLE });
|
||||
this._setWeekdateHeaderWidth();
|
||||
} else {
|
||||
this._weekdateHeader = null;
|
||||
}
|
||||
|
||||
for (let i = 0; i < 7; i++) {
|
||||
this.actor.add(new St.Label({ text: iter.toLocaleFormat('%a') }),
|
||||
// Could use iter.toLocaleFormat('%a') but that normally gives three characters
|
||||
// and we want, ideally, a single character for e.g. S M T W T F S
|
||||
let customDayAbbrev = _getCalendarDayAbbreviation(iter.getDay());
|
||||
let label = new St.Label({ style_class: 'calendar-day-base calendar-day-heading',
|
||||
text: customDayAbbrev });
|
||||
this.actor.add(label,
|
||||
{ row: 1,
|
||||
col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7,
|
||||
x_fill: false, x_align: St.Align.END });
|
||||
x_fill: false, x_align: St.Align.MIDDLE });
|
||||
iter.setTime(iter.getTime() + MSECS_IN_DAY);
|
||||
}
|
||||
|
||||
@ -178,33 +477,57 @@ Calendar.prototype = {
|
||||
switch (event.get_scroll_direction()) {
|
||||
case Clutter.ScrollDirection.UP:
|
||||
case Clutter.ScrollDirection.LEFT:
|
||||
this._prevMonth();
|
||||
this._onPrevMonthButtonClicked();
|
||||
break;
|
||||
case Clutter.ScrollDirection.DOWN:
|
||||
case Clutter.ScrollDirection.RIGHT:
|
||||
this._nextMonth();
|
||||
this._onNextMonthButtonClicked();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_prevMonth: function() {
|
||||
if (this.date.getMonth() == 0) {
|
||||
this.date.setMonth(11);
|
||||
this.date.setFullYear(this.date.getFullYear() - 1);
|
||||
} else {
|
||||
this.date.setMonth(this.date.getMonth() - 1);
|
||||
_onPrevMonthButtonClicked: function() {
|
||||
let newDate = new Date(this._selectedDate);
|
||||
let oldMonth = newDate.getMonth();
|
||||
if (oldMonth == 0) {
|
||||
newDate.setMonth(11);
|
||||
newDate.setFullYear(newDate.getFullYear() - 1);
|
||||
if (newDate.getMonth() != 11) {
|
||||
let day = 32 - new Date(newDate.getFullYear() - 1, 11, 32).getDate();
|
||||
newDate = new Date(newDate.getFullYear() - 1, 11, day);
|
||||
}
|
||||
}
|
||||
this._update();
|
||||
else {
|
||||
newDate.setMonth(oldMonth - 1);
|
||||
if (newDate.getMonth() != oldMonth - 1) {
|
||||
let day = 32 - new Date(newDate.getFullYear(), oldMonth - 1, 32).getDate();
|
||||
newDate = new Date(newDate.getFullYear(), oldMonth - 1, day);
|
||||
}
|
||||
}
|
||||
|
||||
this.setDate(newDate);
|
||||
},
|
||||
|
||||
_nextMonth: function() {
|
||||
if (this.date.getMonth() == 11) {
|
||||
this.date.setMonth(0);
|
||||
this.date.setFullYear(this.date.getFullYear() + 1);
|
||||
} else {
|
||||
this.date.setMonth(this.date.getMonth() + 1);
|
||||
_onNextMonthButtonClicked: function() {
|
||||
let newDate = new Date(this._selectedDate);
|
||||
let oldMonth = newDate.getMonth();
|
||||
if (oldMonth == 11) {
|
||||
newDate.setMonth(0);
|
||||
newDate.setFullYear(newDate.getFullYear() + 1);
|
||||
if (newDate.getMonth() != 0) {
|
||||
let day = 32 - new Date(newDate.getFullYear() + 1, 0, 32).getDate();
|
||||
newDate = new Date(newDate.getFullYear() + 1, 0, day);
|
||||
}
|
||||
}
|
||||
this._update();
|
||||
else {
|
||||
newDate.setMonth(oldMonth + 1);
|
||||
if (newDate.getMonth() != oldMonth + 1) {
|
||||
let day = 32 - new Date(newDate.getFullYear(), oldMonth + 1, 32).getDate();
|
||||
newDate = new Date(newDate.getFullYear(), oldMonth + 1, day);
|
||||
}
|
||||
}
|
||||
|
||||
this.setDate(newDate);
|
||||
},
|
||||
|
||||
_onSettingsChange: function() {
|
||||
@ -214,7 +537,12 @@ Calendar.prototype = {
|
||||
},
|
||||
|
||||
_update: function() {
|
||||
this._dateLabel.text = this.date.toLocaleFormat(this._headerFormat);
|
||||
let now = new Date();
|
||||
|
||||
if (_sameYear(this._selectedDate, now))
|
||||
this._monthLabel.text = this._selectedDate.toLocaleFormat(this._headerFormatWithoutYear);
|
||||
else
|
||||
this._monthLabel.text = this._selectedDate.toLocaleFormat(this._headerFormat);
|
||||
|
||||
// Remove everything but the topBox and the weekday labels
|
||||
let children = this.actor.get_children();
|
||||
@ -222,45 +550,215 @@ Calendar.prototype = {
|
||||
children[i].destroy();
|
||||
|
||||
// Start at the beginning of the week before the start of the month
|
||||
let iter = new Date(this.date);
|
||||
iter.setDate(1);
|
||||
iter.setSeconds(0);
|
||||
iter.setHours(12);
|
||||
let daysToWeekStart = (7 + iter.getDay() - this._weekStart) % 7;
|
||||
iter.setTime(iter.getTime() - daysToWeekStart * MSECS_IN_DAY);
|
||||
|
||||
let now = new Date();
|
||||
let beginDate = new Date(this._selectedDate);
|
||||
beginDate.setDate(1);
|
||||
beginDate.setSeconds(0);
|
||||
beginDate.setHours(12);
|
||||
let daysToWeekStart = (7 + beginDate.getDay() - this._weekStart) % 7;
|
||||
beginDate.setTime(beginDate.getTime() - daysToWeekStart * MSECS_IN_DAY);
|
||||
|
||||
let iter = new Date(beginDate);
|
||||
let row = 2;
|
||||
while (true) {
|
||||
let label = new St.Label({ text: iter.getDate().toString() });
|
||||
if (_sameDay(now, iter))
|
||||
label.style_class = 'calendar-day calendar-today';
|
||||
else if (iter.getMonth() != this.date.getMonth())
|
||||
label.style_class = 'calendar-day calendar-other-month-day';
|
||||
let button = new St.Button({ label: iter.getDate().toString() });
|
||||
|
||||
let iterStr = iter.toUTCString();
|
||||
button.connect('clicked', Lang.bind(this, function() {
|
||||
let newlySelectedDate = new Date(iterStr);
|
||||
this.setDate(newlySelectedDate);
|
||||
}));
|
||||
|
||||
let hasEvents = this._eventSource.hasEvents(iter);
|
||||
let styleClass = 'calendar-day-base calendar-day';
|
||||
if (_isWorkDay(iter))
|
||||
styleClass += ' calendar-work-day'
|
||||
else
|
||||
label.style_class = 'calendar-day';
|
||||
styleClass += ' calendar-nonwork-day'
|
||||
|
||||
// Hack used in lieu of border-collapse - see gnome-shell.css
|
||||
if (row == 2)
|
||||
styleClass = 'calendar-day-top ' + styleClass;
|
||||
if (iter.getDay() == this._weekStart)
|
||||
styleClass = 'calendar-day-left ' + styleClass;
|
||||
|
||||
if (_sameDay(now, iter))
|
||||
styleClass += ' calendar-today';
|
||||
else if (iter.getMonth() != this._selectedDate.getMonth())
|
||||
styleClass += ' calendar-other-month-day';
|
||||
|
||||
if (_sameDay(this._selectedDate, iter))
|
||||
button.add_style_pseudo_class('active');
|
||||
|
||||
if (hasEvents)
|
||||
styleClass += ' calendar-day-with-events'
|
||||
|
||||
button.style_class = styleClass;
|
||||
|
||||
let offsetCols = this._useWeekdate ? 1 : 0;
|
||||
this.actor.add(label,
|
||||
{ row: row, col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7,
|
||||
x_fill: false, x_align: St.Align.END });
|
||||
this.actor.add(button,
|
||||
{ row: row, col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7 });
|
||||
|
||||
if (this._useWeekdate && iter.getDay() == 4) {
|
||||
let label = new St.Label({ text: _getCalendarWeekForDate(iter).toString(),
|
||||
style_class: 'calendar-day calendar-calendarweek'});
|
||||
style_class: 'calendar-day-base calendar-week-number'});
|
||||
this.actor.add(label,
|
||||
{ row: row, col: 0,
|
||||
x_fill: false, x_align: St.Align.MIDDLE });
|
||||
{ row: row, col: 0, y_align: St.Align.MIDDLE });
|
||||
}
|
||||
|
||||
iter.setTime(iter.getTime() + MSECS_IN_DAY);
|
||||
if (iter.getDay() == this._weekStart) {
|
||||
// We stop on the first "first day of the week" after the month we are displaying
|
||||
if (iter.getMonth() > this.date.getMonth() || iter.getYear() > this.date.getYear())
|
||||
if (iter.getMonth() > this._selectedDate.getMonth() || iter.getYear() > this._selectedDate.getYear())
|
||||
break;
|
||||
row++;
|
||||
}
|
||||
}
|
||||
// Signal to the event source that we are interested in events
|
||||
// only from this date range
|
||||
this._eventSource.requestRange(beginDate, iter);
|
||||
}
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(Calendar.prototype);
|
||||
|
||||
function EventsList(eventSource) {
|
||||
this._init(eventSource);
|
||||
}
|
||||
|
||||
EventsList.prototype = {
|
||||
_init: function(eventSource) {
|
||||
this.actor = new St.BoxLayout({ vertical: true, style_class: 'events-header-vbox'});
|
||||
this._date = new Date();
|
||||
this._eventSource = eventSource;
|
||||
this._eventSource.connect('changed', Lang.bind(this, this._update));
|
||||
this._desktopSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
|
||||
this._desktopSettings.connect('changed', Lang.bind(this, this._update));
|
||||
let weekStartString = Gettext_gtk30.gettext('calendar:week_start:0');
|
||||
if (weekStartString.indexOf('calendar:week_start:') == 0) {
|
||||
this._weekStart = parseInt(weekStartString.substring(20));
|
||||
}
|
||||
|
||||
if (isNaN(this._weekStart) ||
|
||||
this._weekStart < 0 ||
|
||||
this._weekStart > 6) {
|
||||
log('Translation of "calendar:week_start:0" in GTK+ is not correct');
|
||||
this._weekStart = 0;
|
||||
}
|
||||
|
||||
this._update();
|
||||
},
|
||||
|
||||
_addEvent: function(dayNameBox, timeBox, eventTitleBox, includeDayName, day, time, desc) {
|
||||
if (includeDayName) {
|
||||
dayNameBox.add(new St.Label( { style_class: 'events-day-dayname',
|
||||
text: day } ),
|
||||
{ x_fill: true } );
|
||||
}
|
||||
timeBox.add(new St.Label( { style_class: 'events-day-time',
|
||||
text: time} ),
|
||||
{ x_fill: true } );
|
||||
eventTitleBox.add(new St.Label( { style_class: 'events-day-task',
|
||||
text: desc} ));
|
||||
},
|
||||
|
||||
_addPeriod: function(header, begin, end, includeDayName, showNothingScheduled) {
|
||||
let events = this._eventSource.getEvents(begin, end);
|
||||
|
||||
let clockFormat = this._desktopSettings.get_string(CLOCK_FORMAT_KEY);;
|
||||
|
||||
if (events.length == 0 && !showNothingScheduled)
|
||||
return;
|
||||
|
||||
let vbox = new St.BoxLayout( {vertical: true} );
|
||||
this.actor.add(vbox);
|
||||
|
||||
vbox.add(new St.Label({ style_class: 'events-day-header', text: header }));
|
||||
let box = new St.BoxLayout({style_class: 'events-header-hbox'});
|
||||
let dayNameBox = new St.BoxLayout({ vertical: true, style_class: 'events-day-name-box' });
|
||||
let timeBox = new St.BoxLayout({ vertical: true, style_class: 'events-time-box' });
|
||||
let eventTitleBox = new St.BoxLayout({ vertical: true, style_class: 'events-event-box' });
|
||||
box.add(dayNameBox, {x_fill: false});
|
||||
box.add(timeBox, {x_fill: false});
|
||||
box.add(eventTitleBox, {expand: true});
|
||||
vbox.add(box);
|
||||
|
||||
for (let n = 0; n < events.length; n++) {
|
||||
let event = events[n];
|
||||
let dayString = _getEventDayAbbreviation(event.date.getDay());
|
||||
let timeString = _formatEventTime(event, clockFormat);
|
||||
let summaryString = event.summary;
|
||||
this._addEvent(dayNameBox, timeBox, eventTitleBox, includeDayName, dayString, timeString, summaryString);
|
||||
}
|
||||
|
||||
if (events.length == 0 && showNothingScheduled) {
|
||||
let now = new Date();
|
||||
/* Translators: Text to show if there are no events */
|
||||
let nothingEvent = new CalendarEvent(now, _("Nothing Scheduled"), true);
|
||||
let timeString = _formatEventTime(nothingEvent, clockFormat);
|
||||
this._addEvent(dayNameBox, timeBox, eventTitleBox, false, "", timeString, nothingEvent.summary);
|
||||
}
|
||||
},
|
||||
|
||||
_showOtherDay: function(day) {
|
||||
this.actor.destroy_children();
|
||||
|
||||
let dayBegin = _getBeginningOfDay(day);
|
||||
let dayEnd = _getEndOfDay(day);
|
||||
|
||||
let dayString;
|
||||
let now = new Date();
|
||||
if (_sameYear(day, now))
|
||||
dayString = day.toLocaleFormat('%A, %B %d');
|
||||
else
|
||||
dayString = day.toLocaleFormat('%A, %B %d, %Y');
|
||||
this._addPeriod(dayString, dayBegin, dayEnd, false, true);
|
||||
},
|
||||
|
||||
_showToday: function() {
|
||||
this.actor.destroy_children();
|
||||
|
||||
let now = new Date();
|
||||
let dayBegin = _getBeginningOfDay(now);
|
||||
let dayEnd = _getEndOfDay(now);
|
||||
this._addPeriod(_("Today"), dayBegin, dayEnd, false, true);
|
||||
|
||||
let tomorrowBegin = new Date(dayBegin.getTime() + 86400 * 1000);
|
||||
let tomorrowEnd = new Date(dayEnd.getTime() + 86400 * 1000);
|
||||
this._addPeriod(_("Tomorrow"), tomorrowBegin, tomorrowEnd, false, true);
|
||||
|
||||
if (dayEnd.getDay() <= 4 + this._weekStart) {
|
||||
/* If now is within the first 5 days we show "This week" and
|
||||
* include events up until and including Saturday/Sunday
|
||||
* (depending on whether a week starts on Sunday/Monday).
|
||||
*/
|
||||
let thisWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000);
|
||||
let thisWeekEnd = new Date(dayEnd.getTime() + (6 + this._weekStart - dayEnd.getDay()) * 86400 * 1000);
|
||||
this._addPeriod(_("This week"), thisWeekBegin, thisWeekEnd, true, false);
|
||||
} else {
|
||||
/* otherwise it's one of the two last days of the week ... show
|
||||
* "Next week" and include events up until and including *next*
|
||||
* Saturday/Sunday
|
||||
*/
|
||||
let nextWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000);
|
||||
let nextWeekEnd = new Date(dayEnd.getTime() + (13 + this._weekStart - dayEnd.getDay()) * 86400 * 1000);
|
||||
this._addPeriod(_("Next week"), nextWeekBegin, nextWeekEnd, true, false);
|
||||
}
|
||||
},
|
||||
|
||||
// Sets the event list to show events from a specific date
|
||||
setDate: function(date) {
|
||||
if (!_sameDay(date, this._date)) {
|
||||
this._date = date;
|
||||
this._update();
|
||||
}
|
||||
},
|
||||
|
||||
_update: function() {
|
||||
let today = new Date();
|
||||
if (_sameDay (this._date, today)) {
|
||||
this._showToday();
|
||||
} else {
|
||||
this._showOtherDay(this._date);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -54,7 +54,7 @@ RemoveFavoriteIcon.prototype = {
|
||||
if (source instanceof AppDisplay.AppWellIcon) {
|
||||
let appSystem = Shell.AppSystem.get_default();
|
||||
app = appSystem.get_app(source.getId());
|
||||
} else if (source instanceof Workspace.WindowClone) {
|
||||
} else if (source.metaWindow) {
|
||||
let tracker = Shell.WindowTracker.get_default();
|
||||
app = tracker.get_window_app(source.metaWindow);
|
||||
}
|
||||
@ -78,8 +78,6 @@ function Dash() {
|
||||
|
||||
Dash.prototype = {
|
||||
_init : function() {
|
||||
this._menus = [];
|
||||
this._menuDisplays = [];
|
||||
this._maxHeight = -1;
|
||||
this._iconSize = 48;
|
||||
|
||||
@ -150,7 +148,7 @@ Dash.prototype = {
|
||||
let app = null;
|
||||
if (dragEvent.source instanceof AppDisplay.AppWellIcon)
|
||||
app = this._appSystem.get_app(dragEvent.source.getId());
|
||||
else if (dragEvent.source instanceof Workspace.WindowClone)
|
||||
else if (dragEvent.source.metaWindow)
|
||||
app = this._tracker.get_window_app(dragEvent.source.metaWindow);
|
||||
else
|
||||
return DND.DragMotionResult.CONTINUE;
|
||||
@ -193,7 +191,8 @@ Dash.prototype = {
|
||||
},
|
||||
|
||||
_addApp: function(app) {
|
||||
let display = new AppDisplay.AppWellIcon(app);
|
||||
let display = new AppDisplay.AppWellIcon(app,
|
||||
{ setSizeManually: true });
|
||||
display._draggable.connect('drag-begin',
|
||||
Lang.bind(this, function() {
|
||||
display.actor.opacity = 50;
|
||||
@ -207,7 +206,7 @@ Dash.prototype = {
|
||||
|
||||
_redisplay: function () {
|
||||
this._box.hide();
|
||||
this._box.remove_all();
|
||||
this._box.destroy_children();
|
||||
|
||||
let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
|
||||
|
||||
@ -266,7 +265,7 @@ Dash.prototype = {
|
||||
let app = null;
|
||||
if (source instanceof AppDisplay.AppWellIcon)
|
||||
app = this._appSystem.get_app(source.getId());
|
||||
else if (source instanceof Workspace.WindowClone)
|
||||
else if (source.metaWindow)
|
||||
app = this._tracker.get_window_app(source.metaWindow);
|
||||
|
||||
// Don't allow favoriting of transient apps
|
||||
@ -317,7 +316,7 @@ Dash.prototype = {
|
||||
let app = null;
|
||||
if (source instanceof AppDisplay.AppWellIcon) {
|
||||
app = this._appSystem.get_app(source.getId());
|
||||
} else if (source instanceof Workspace.WindowClone) {
|
||||
} else if (source.metaWindow) {
|
||||
app = this._tracker.get_window_app(source.metaWindow);
|
||||
}
|
||||
|
||||
|
212
js/ui/dateMenu.js
Normal file
212
js/ui/dateMenu.js
Normal file
@ -0,0 +1,212 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Cairo = imports.cairo;
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const Util = imports.misc.util;
|
||||
const Main = imports.ui.main;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const Calendar = imports.ui.calendar;
|
||||
|
||||
// in org.gnome.desktop.interface
|
||||
const CLOCK_FORMAT_KEY = 'clock-format';
|
||||
|
||||
// in org.gnome.shell.clock
|
||||
const CLOCK_SHOW_DATE_KEY = 'show-date';
|
||||
const CLOCK_SHOW_SECONDS_KEY = 'show-seconds';
|
||||
|
||||
function _onVertSepRepaint (area)
|
||||
{
|
||||
let cr = area.get_context();
|
||||
let themeNode = area.get_theme_node();
|
||||
let [width, height] = area.get_surface_size();
|
||||
let stippleColor = new Clutter.Color();
|
||||
let stippleWidth = themeNode.get_length('-stipple-width');
|
||||
let x = Math.floor(width/2) + 0.5;
|
||||
themeNode.lookup_color('-stipple-color', false, stippleColor);
|
||||
cr.moveTo(x, 0);
|
||||
cr.lineTo(x, height);
|
||||
Clutter.cairo_set_source_color(cr, stippleColor);
|
||||
cr.setDash([1, 3], 1); // Hard-code for now
|
||||
cr.setLineWidth(stippleWidth);
|
||||
cr.stroke();
|
||||
};
|
||||
|
||||
function DateMenuButton() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
DateMenuButton.prototype = {
|
||||
__proto__: PanelMenu.Button.prototype,
|
||||
|
||||
_init: function() {
|
||||
let item;
|
||||
let hbox;
|
||||
let vbox;
|
||||
|
||||
//this._eventSource = new Calendar.EmptyEventSource();
|
||||
//this._eventSource = new Calendar.FakeEventSource();
|
||||
this._eventSource = new Calendar.EvolutionEventSource();
|
||||
|
||||
PanelMenu.Button.prototype._init.call(this, St.Align.START);
|
||||
|
||||
this._clock = new St.Label();
|
||||
this.actor.set_child(this._clock);
|
||||
|
||||
hbox = new St.BoxLayout({name: 'calendarArea'});
|
||||
this.menu.addActor(hbox);
|
||||
|
||||
// Fill up the first column
|
||||
|
||||
vbox = new St.BoxLayout({vertical: true});
|
||||
hbox.add(vbox);
|
||||
|
||||
// Date
|
||||
this._date = new St.Label();
|
||||
this._date.style_class = 'datemenu-date-label';
|
||||
vbox.add(this._date);
|
||||
|
||||
this._eventList = new Calendar.EventsList(this._eventSource);
|
||||
|
||||
// Calendar
|
||||
this._calendar = new Calendar.Calendar(this._eventSource);
|
||||
this._calendar.connect('selected-date-changed',
|
||||
Lang.bind(this, function(calendar, date) {
|
||||
this._eventList.setDate(date);
|
||||
}));
|
||||
vbox.add(this._calendar.actor);
|
||||
|
||||
item = new PopupMenu.PopupSeparatorMenuItem();
|
||||
item.setColumnWidths(1);
|
||||
vbox.add(item.actor, {y_align: St.Align.END, expand: true, y_fill: false});
|
||||
item = new PopupMenu.PopupMenuItem(_("Date and Time Settings"));
|
||||
item.connect('activate', Lang.bind(this, this._onPreferencesActivate));
|
||||
vbox.add(item.actor);
|
||||
|
||||
// Add vertical separator
|
||||
|
||||
item = new St.DrawingArea({ style_class: 'calendar-vertical-separator',
|
||||
pseudo_class: 'highlighted' });
|
||||
item.connect('repaint', Lang.bind(this, _onVertSepRepaint));
|
||||
hbox.add(item);
|
||||
|
||||
// Fill up the second column
|
||||
|
||||
vbox = new St.BoxLayout({vertical: true});
|
||||
hbox.add(vbox);
|
||||
|
||||
// Event list
|
||||
vbox.add(this._eventList.actor);
|
||||
|
||||
item = new PopupMenu.PopupMenuItem(_("Open Calendar"));
|
||||
item.connect('activate', Lang.bind(this, this._onOpenCalendarActivate));
|
||||
vbox.add(item.actor, {y_align: St.Align.END, expand: true, y_fill: false});
|
||||
|
||||
// Whenever the menu is opened, select today
|
||||
this.menu.connect('open-state-changed', Lang.bind(this, function(menu, isOpen) {
|
||||
if (isOpen) {
|
||||
let now = new Date();
|
||||
this._calendar.setDate(now);
|
||||
// No need to update this._eventList as ::selected-date-changed
|
||||
// signal will fire
|
||||
}
|
||||
}));
|
||||
|
||||
// Done with hbox for calendar and event list
|
||||
|
||||
// Track changes to clock settings
|
||||
this._desktopSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
|
||||
this._clockSettings = new Gio.Settings({ schema: 'org.gnome.shell.clock' });
|
||||
this._desktopSettings.connect('changed', Lang.bind(this, this._updateClockAndDate));
|
||||
this._clockSettings.connect('changed', Lang.bind(this, this._updateClockAndDate));
|
||||
|
||||
// Start the clock
|
||||
this._updateClockAndDate();
|
||||
},
|
||||
|
||||
_updateClockAndDate: function() {
|
||||
let format = this._desktopSettings.get_string(CLOCK_FORMAT_KEY);
|
||||
let showDate = this._clockSettings.get_boolean(CLOCK_SHOW_DATE_KEY);
|
||||
let showSeconds = this._clockSettings.get_boolean(CLOCK_SHOW_SECONDS_KEY);
|
||||
|
||||
let clockFormat;
|
||||
let dateFormat;
|
||||
|
||||
switch (format) {
|
||||
case '24h':
|
||||
if (showDate)
|
||||
/* Translators: This is the time format with date used
|
||||
in 24-hour mode. */
|
||||
clockFormat = showSeconds ? _("%a %b %e, %R:%S")
|
||||
: _("%a %b %e, %R");
|
||||
else
|
||||
/* Translators: This is the time format without date used
|
||||
in 24-hour mode. */
|
||||
clockFormat = showSeconds ? _("%a %R:%S")
|
||||
: _("%a %R");
|
||||
break;
|
||||
case '12h':
|
||||
default:
|
||||
if (showDate)
|
||||
/* Translators: This is a time format with date used
|
||||
for AM/PM. */
|
||||
clockFormat = showSeconds ? _("%a %b %e, %l:%M:%S %p")
|
||||
: _("%a %b %e, %l:%M %p");
|
||||
else
|
||||
/* Translators: This is a time format without date used
|
||||
for AM/PM. */
|
||||
clockFormat = showSeconds ? _("%a %l:%M:%S %p")
|
||||
: _("%a %l:%M %p");
|
||||
break;
|
||||
}
|
||||
|
||||
let displayDate = new Date();
|
||||
let msecRemaining;
|
||||
if (showSeconds) {
|
||||
msecRemaining = 1000 - displayDate.getMilliseconds();
|
||||
if (msecRemaining < 50) {
|
||||
displayDate.setSeconds(displayDate.getSeconds() + 1);
|
||||
msecRemaining += 1000;
|
||||
}
|
||||
} else {
|
||||
msecRemaining = 60000 - (1000 * displayDate.getSeconds() +
|
||||
displayDate.getMilliseconds());
|
||||
if (msecRemaining < 500) {
|
||||
displayDate.setMinutes(displayDate.getMinutes() + 1);
|
||||
msecRemaining += 60000;
|
||||
}
|
||||
}
|
||||
|
||||
this._clock.set_text(displayDate.toLocaleFormat(clockFormat));
|
||||
|
||||
/* Translators: This is the date format to use when the calendar popup is
|
||||
* shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
|
||||
*/
|
||||
dateFormat = _("%A %B %e, %Y");
|
||||
this._date.set_text(displayDate.toLocaleFormat(dateFormat));
|
||||
|
||||
Mainloop.timeout_add(msecRemaining, Lang.bind(this, this._updateClockAndDate));
|
||||
return false;
|
||||
},
|
||||
|
||||
_onPreferencesActivate: function() {
|
||||
this.menu.close();
|
||||
Util.spawnDesktop('gnome-datetime-panel');
|
||||
},
|
||||
|
||||
_onOpenCalendarActivate: function() {
|
||||
this.menu.close();
|
||||
// TODO: pass '-c calendar' (to force the calendar at startup)
|
||||
// TODO: pass the selected day
|
||||
Util.spawnDesktop('evolution');
|
||||
},
|
||||
};
|
46
js/ui/dnd.js
46
js/ui/dnd.js
@ -101,6 +101,12 @@ _Draggable.prototype = {
|
||||
this._dragInProgress = false; // The drag has been started, and has not been dropped or cancelled yet.
|
||||
this._animationInProgress = false; // The drag is over and the item is in the process of animating to its original position (snapping back or reverting).
|
||||
|
||||
// During the drag, we eat enter/leave events so that actors don't prelight or show
|
||||
// tooltips. But we remember the relevant events (first leave, last enter) so we can
|
||||
// fix up the hover state after the drag ends.
|
||||
this._firstLeaveEvent = null;
|
||||
this._lastEnterEvent = null;
|
||||
|
||||
this._eventsGrabbed = false;
|
||||
},
|
||||
|
||||
@ -198,6 +204,11 @@ _Draggable.prototype = {
|
||||
this._cancelDrag(event.get_time());
|
||||
return true;
|
||||
}
|
||||
} else if (event.type() == Clutter.EventType.LEAVE) {
|
||||
if (this._firstLeaveEvent == null)
|
||||
this._firstLeaveEvent = event;
|
||||
} else if (event.type() == Clutter.EventType.ENTER) {
|
||||
this._lastEnterEvent = event;
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -485,7 +496,7 @@ _Draggable.prototype = {
|
||||
if (this._actorDestroyed) {
|
||||
global.unset_cursor();
|
||||
if (!this._buttonDown)
|
||||
this._ungrabEvents();
|
||||
this._dragComplete();
|
||||
this.emit('drag-end', eventTime, false);
|
||||
return;
|
||||
}
|
||||
@ -542,12 +553,41 @@ _Draggable.prototype = {
|
||||
this._dragComplete();
|
||||
},
|
||||
|
||||
// Actor is an actor we might have entered or left during the drag; call
|
||||
// st_widget_sync_hover on all StWidget ancestors
|
||||
_syncHover: function(actor) {
|
||||
// If the actor was reparented from its original location and
|
||||
// destroyed, then start syncing hover at the original parent
|
||||
if (actor == this._dragActor && this._actorDestroyed)
|
||||
actor = this._dragOrigParent;
|
||||
|
||||
while (actor) {
|
||||
let parent = actor.get_parent();
|
||||
if (actor instanceof St.Widget)
|
||||
actor.sync_hover();
|
||||
|
||||
actor = parent;
|
||||
}
|
||||
},
|
||||
|
||||
_dragComplete: function() {
|
||||
Shell.util_set_hidden_from_pick(this._dragActor, false);
|
||||
if (!this._actorDestroyed)
|
||||
Shell.util_set_hidden_from_pick(this._dragActor, false);
|
||||
|
||||
this._ungrabEvents();
|
||||
|
||||
if (this._firstLeaveEvent) {
|
||||
this._syncHover(this._firstLeaveEvent.get_source());
|
||||
this._firstLeaveEvent = null;
|
||||
}
|
||||
|
||||
if (this._lastEnterEvent) {
|
||||
this._syncHover(this._lastEnterEvent.get_source());
|
||||
this._lastEnterEvent = null;
|
||||
}
|
||||
|
||||
this._dragActor = undefined;
|
||||
currentDraggable = null;
|
||||
this._ungrabEvents();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,487 +1,12 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Lang = imports.lang;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const DocInfo = imports.misc.docInfo;
|
||||
const DND = imports.ui.dnd;
|
||||
const GenericDisplay = imports.ui.genericDisplay;
|
||||
const Main = imports.ui.main;
|
||||
const Params = imports.misc.params;
|
||||
const Search = imports.ui.search;
|
||||
|
||||
const MAX_DASH_DOCS = 50;
|
||||
const DASH_DOCS_ICON_SIZE = 16;
|
||||
|
||||
const DEFAULT_SPACING = 4;
|
||||
|
||||
/* This class represents a single display item containing information about a document.
|
||||
* We take the current number of seconds in the constructor to avoid looking up the current
|
||||
* time for every item when they are created in a batch.
|
||||
*
|
||||
* docInfo - DocInfo object containing information about the document
|
||||
* currentSeconds - current number of seconds since the epoch
|
||||
*/
|
||||
function DocDisplayItem(docInfo, currentSecs) {
|
||||
this._init(docInfo, currentSecs);
|
||||
}
|
||||
|
||||
DocDisplayItem.prototype = {
|
||||
__proto__: GenericDisplay.GenericDisplayItem.prototype,
|
||||
|
||||
_init : function(docInfo, currentSecs) {
|
||||
GenericDisplay.GenericDisplayItem.prototype._init.call(this);
|
||||
this._docInfo = docInfo;
|
||||
|
||||
this._setItemInfo(docInfo.name, '');
|
||||
|
||||
this._timeoutTime = -1;
|
||||
this._resetTimeDisplay(currentSecs);
|
||||
},
|
||||
|
||||
//// Public methods ////
|
||||
|
||||
getUpdateTimeoutTime: function() {
|
||||
return this._timeoutTime;
|
||||
},
|
||||
|
||||
// Update any relative-time based displays for this item.
|
||||
redisplay: function(currentSecs) {
|
||||
this._resetTimeDisplay(currentSecs);
|
||||
},
|
||||
|
||||
//// Public method overrides ////
|
||||
|
||||
// Opens a document represented by this display item.
|
||||
launch : function() {
|
||||
this._docInfo.launch();
|
||||
},
|
||||
|
||||
//// Protected method overrides ////
|
||||
|
||||
// Returns an icon for the item.
|
||||
_createIcon : function() {
|
||||
return this._docInfo.createIcon(GenericDisplay.ITEM_DISPLAY_ICON_SIZE);
|
||||
},
|
||||
|
||||
// Returns a preview icon for the item.
|
||||
_createPreviewIcon : function() {
|
||||
return this._docInfo.createIcon(GenericDisplay.PREVIEW_ICON_SIZE);
|
||||
},
|
||||
|
||||
// Creates and returns a large preview icon, but only if this._docInfo is an image file
|
||||
// and we were able to generate a pixbuf from it successfully.
|
||||
_createLargePreviewIcon : function() {
|
||||
if (this._docInfo.mimeType == null || this._docInfo.mimeType.indexOf('image/') != 0)
|
||||
return null;
|
||||
|
||||
try {
|
||||
return St.TextureCache.get_default().load_uri_sync(St.TextureCachePolicy.NONE,
|
||||
this._docInfo.uri, -1, -1);
|
||||
} catch (e) {
|
||||
// An exception will be raised when the image format isn't know
|
||||
/* FIXME: http://bugzilla.gnome.org/show_bug.cgi?id=591480: should
|
||||
* only ignore GDK_PIXBUF_ERROR_UNKNOWN_TYPE. */
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
//// Drag and Drop ////
|
||||
|
||||
shellWorkspaceLaunch: function() {
|
||||
this.launch();
|
||||
},
|
||||
|
||||
//// Private Methods ////
|
||||
|
||||
// Updates the last visited time displayed in the description text for the item.
|
||||
_resetTimeDisplay: function(currentSecs) {
|
||||
let lastSecs = this._docInfo.timestamp;
|
||||
let timeDelta = currentSecs - lastSecs;
|
||||
let [text, nextUpdate] = global.format_time_relative_pretty(timeDelta);
|
||||
this._timeoutTime = currentSecs + nextUpdate;
|
||||
this._setDescriptionText(text);
|
||||
}
|
||||
};
|
||||
|
||||
/* This class represents a display containing a collection of document items.
|
||||
* The documents are sorted by how recently they were last visited.
|
||||
*/
|
||||
function DocDisplay() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
DocDisplay.prototype = {
|
||||
__proto__: GenericDisplay.GenericDisplay.prototype,
|
||||
|
||||
_init : function() {
|
||||
GenericDisplay.GenericDisplay.prototype._init.call(this);
|
||||
// We keep a single timeout callback for updating last visited times
|
||||
// for all the items in the display. This avoids creating individual
|
||||
// callbacks for each item in the display. So proper time updates
|
||||
// for individual items and item details depend on the item being
|
||||
// associated with one of the displays.
|
||||
this._updateTimeoutTargetTime = -1;
|
||||
this._updateTimeoutId = 0;
|
||||
|
||||
this._docManager = DocInfo.getDocManager();
|
||||
this._docsStale = true;
|
||||
this._docManager.connect('changed', Lang.bind(this, function(mgr, userData) {
|
||||
this._docsStale = true;
|
||||
// Changes in local recent files should not happen when we are in the Overview mode,
|
||||
// but redisplaying right away is cool when we use Zephyr.
|
||||
// Also, we might be displaying remote documents, like Google Docs, in the future
|
||||
// which might be edited by someone else.
|
||||
this._redisplay(GenericDisplay.RedisplayFlags.NONE);
|
||||
}));
|
||||
|
||||
this.connect('destroy', Lang.bind(this, function (o) {
|
||||
if (this._updateTimeoutId > 0)
|
||||
Mainloop.source_remove(this._updateTimeoutId);
|
||||
}));
|
||||
},
|
||||
|
||||
//// Protected method overrides ////
|
||||
|
||||
// Gets the list of recent items from the recent items manager.
|
||||
_refreshCache : function() {
|
||||
if (!this._docsStale)
|
||||
return true;
|
||||
this._allItems = {};
|
||||
Lang.copyProperties(this._docManager.getInfosByUri(), this._allItems);
|
||||
this._docsStale = false;
|
||||
return false;
|
||||
},
|
||||
|
||||
// Sets the list of the displayed items based on how recently they were last visited.
|
||||
_setDefaultList : function() {
|
||||
// It seems to be an implementation detail of the Mozilla JavaScript that object
|
||||
// properties are returned during the iteration in the same order in which they were
|
||||
// defined, but it is not a guarantee according to this
|
||||
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/for...in
|
||||
// While this._allItems associative array seems to always be ordered by last added,
|
||||
// as the results of this._recentManager.get_items() based on which it is constructed are,
|
||||
// we should do the sorting manually because we want the order to be based on last visited.
|
||||
//
|
||||
// This function is called each time the search string is set back to '' or we display
|
||||
// the Overview, so we are doing the sorting over the same items multiple times if the list
|
||||
// of recent items didn't change. We could store an additional array of doc ids and sort
|
||||
// them once when they are returned by this._recentManager.get_items() to avoid having to do
|
||||
// this sorting each time, but the sorting seems to be very fast anyway, so there is no need
|
||||
// to introduce an additional class variable.
|
||||
this._matchedItems = {};
|
||||
this._matchedItemKeys = [];
|
||||
let docIdsToRemove = [];
|
||||
for (docId in this._allItems) {
|
||||
this._matchedItems[docId] = 1;
|
||||
this._matchedItemKeys.push(docId);
|
||||
}
|
||||
|
||||
for (docId in docIdsToRemove) {
|
||||
delete this._allItems[docId];
|
||||
}
|
||||
|
||||
this._matchedItemKeys.sort(Lang.bind(this, this._compareItems));
|
||||
},
|
||||
|
||||
// Compares items associated with the item ids based on how recently the items
|
||||
// were last visited.
|
||||
// Returns an integer value indicating the result of the comparison.
|
||||
_compareItems : function(itemIdA, itemIdB) {
|
||||
let docA = this._allItems[itemIdA];
|
||||
let docB = this._allItems[itemIdB];
|
||||
|
||||
return docB.timestamp - docA.timestamp;
|
||||
},
|
||||
|
||||
// Checks if the item info can be a match for the search string by checking
|
||||
// the name of the document. Item info is expected to be GtkRecentInfo.
|
||||
// Returns a boolean flag indicating if itemInfo is a match.
|
||||
_isInfoMatching : function(itemInfo, search) {
|
||||
if (!itemInfo.exists())
|
||||
return false;
|
||||
|
||||
if (search == null || search == '')
|
||||
return true;
|
||||
|
||||
let name = itemInfo.name.toLowerCase();
|
||||
if (name.indexOf(search) >= 0)
|
||||
return true;
|
||||
// TODO: we can also check doc URIs, so that
|
||||
// if you search for a directory name, we display recent files from it
|
||||
return false;
|
||||
},
|
||||
|
||||
// Creates a DocDisplayItem based on itemInfo, which is expected to be a DocInfo object.
|
||||
_createDisplayItem: function(itemInfo) {
|
||||
let currentSecs = new Date().getTime() / 1000;
|
||||
let docDisplayItem = new DocDisplayItem(itemInfo, currentSecs);
|
||||
this._updateTimeoutCallback(docDisplayItem, currentSecs);
|
||||
return docDisplayItem;
|
||||
},
|
||||
|
||||
//// Private Methods ////
|
||||
|
||||
// A callback function that redisplays the items, updating their descriptions,
|
||||
// and sets up a new timeout callback.
|
||||
_docTimeout: function () {
|
||||
let currentSecs = new Date().getTime() / 1000;
|
||||
this._updateTimeoutId = 0;
|
||||
this._updateTimeoutTargetTime = -1;
|
||||
for (let docId in this._displayedItems) {
|
||||
let docDisplayItem = this._displayedItems[docId];
|
||||
docDisplayItem.redisplay(currentSecs);
|
||||
this._updateTimeoutCallback(docDisplayItem, currentSecs);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// Updates the timeout callback if the timeout time for the docDisplayItem
|
||||
// is earlier than the target time for the current timeout callback.
|
||||
_updateTimeoutCallback: function (docDisplayItem, currentSecs) {
|
||||
let timeoutTime = docDisplayItem.getUpdateTimeoutTime();
|
||||
if (this._updateTimeoutTargetTime < 0 || timeoutTime < this._updateTimeoutTargetTime) {
|
||||
if (this._updateTimeoutId > 0)
|
||||
Mainloop.source_remove(this._updateTimeoutId);
|
||||
this._updateTimeoutId = Mainloop.timeout_add_seconds(timeoutTime - currentSecs, Lang.bind(this, this._docTimeout));
|
||||
this._updateTimeoutTargetTime = timeoutTime;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(DocDisplay.prototype);
|
||||
|
||||
function DashDocDisplayItem(docInfo) {
|
||||
this._init(docInfo);
|
||||
}
|
||||
|
||||
DashDocDisplayItem.prototype = {
|
||||
_init: function(docInfo) {
|
||||
this._info = docInfo;
|
||||
this._icon = docInfo.createIcon(DASH_DOCS_ICON_SIZE);
|
||||
|
||||
this.actor = new St.Clickable({ style_class: 'recent-docs-item',
|
||||
reactive: true,
|
||||
x_align: St.Align.START });
|
||||
|
||||
let box = new St.BoxLayout({ style_class: 'recent-docs-item-box' });
|
||||
this.actor.set_child(box);
|
||||
|
||||
box.add(this._icon);
|
||||
|
||||
let text = new St.Label({ text: docInfo.name });
|
||||
box.add(text);
|
||||
|
||||
this.actor.connect('clicked', Lang.bind(this, function () {
|
||||
docInfo.launch();
|
||||
Main.overview.hide();
|
||||
}));
|
||||
|
||||
this.actor._delegate = this;
|
||||
let draggable = DND.makeDraggable(this.actor);
|
||||
draggable.connect('drag-begin',
|
||||
Lang.bind(this, function() {
|
||||
Main.overview.beginItemDrag(this);
|
||||
}));
|
||||
draggable.connect('drag-end',
|
||||
Lang.bind(this, function() {
|
||||
Main.overview.endItemDrag(this);
|
||||
}));
|
||||
},
|
||||
|
||||
getUri: function() {
|
||||
return this._info.uri;
|
||||
},
|
||||
|
||||
getDragActorSource: function() {
|
||||
return this._icon;
|
||||
},
|
||||
|
||||
getDragActor: function(stageX, stageY) {
|
||||
this.dragActor = this._info.createIcon(DASH_DOCS_ICON_SIZE);
|
||||
return this.dragActor;
|
||||
},
|
||||
|
||||
//// Drag and drop functions ////
|
||||
|
||||
shellWorkspaceLaunch: function () {
|
||||
this._info.launch();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Class used to display two column recent documents in the dash
|
||||
*/
|
||||
function DashDocDisplay() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
DashDocDisplay.prototype = {
|
||||
_init: function() {
|
||||
this.actor = new Shell.GenericContainer();
|
||||
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
|
||||
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
|
||||
this.actor.connect('allocate', Lang.bind(this, this._allocate));
|
||||
this._workId = Main.initializeDeferredWork(this.actor, Lang.bind(this, this._redisplay));
|
||||
|
||||
this._actorsByUri = {};
|
||||
|
||||
this._docManager = DocInfo.getDocManager();
|
||||
this._docManager.connect('changed', Lang.bind(this, this._onDocsChanged));
|
||||
this._pendingDocsChange = true;
|
||||
this._checkDocExistence = false;
|
||||
},
|
||||
|
||||
_getPreferredWidth: function(actor, forHeight, alloc) {
|
||||
let children = actor.get_children();
|
||||
|
||||
// We use two columns maximum. Just take the min and natural size of the
|
||||
// first two items, even though strictly speaking it's not correct; we'd
|
||||
// need to calculate how many items we could fit for the height, then
|
||||
// take the biggest preferred width for each column.
|
||||
// In practice the dash gets a fixed width anyways.
|
||||
|
||||
// If we have one child, add its minimum and natural size
|
||||
if (children.length > 0) {
|
||||
let [minSize, naturalSize] = children[0].get_preferred_width(forHeight);
|
||||
alloc.min_size += minSize;
|
||||
alloc.natural_size += naturalSize;
|
||||
}
|
||||
// If we have two, add its size, plus DEFAULT_SPACING
|
||||
if (children.length > 1) {
|
||||
let [minSize, naturalSize] = children[1].get_preferred_width(forHeight);
|
||||
alloc.min_size += DEFAULT_SPACING + minSize;
|
||||
alloc.natural_size += DEFAULT_SPACING + naturalSize;
|
||||
}
|
||||
},
|
||||
|
||||
_getPreferredHeight: function(actor, forWidth, alloc) {
|
||||
let children = actor.get_children();
|
||||
|
||||
// The width of an item is our allocated width, minus spacing, divided in half.
|
||||
this._itemWidth = Math.floor((forWidth - DEFAULT_SPACING) / 2);
|
||||
|
||||
let maxNatural = 0;
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
let child = children[i];
|
||||
let [minSize, naturalSize] = child.get_preferred_height(this._itemWidth);
|
||||
maxNatural = Math.max(maxNatural, naturalSize);
|
||||
}
|
||||
|
||||
this._itemHeight = maxNatural;
|
||||
|
||||
let firstColumnChildren = Math.ceil(children.length / 2);
|
||||
alloc.natural_size = (firstColumnChildren * maxNatural +
|
||||
(firstColumnChildren - 1) * DEFAULT_SPACING);
|
||||
},
|
||||
|
||||
_allocate: function(actor, box, flags) {
|
||||
let width = box.x2 - box.x1;
|
||||
let height = box.y2 - box.y1;
|
||||
|
||||
// Make sure this._itemWidth/Height have been computed, even
|
||||
// if the parent actor didn't check our size before allocating.
|
||||
// (Not clear if that is required or not as a Clutter
|
||||
// invariant; this is safe and cheap because of caching.)
|
||||
actor.get_preferred_height(width);
|
||||
|
||||
let children = actor.get_children();
|
||||
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
let columnIndex = 0;
|
||||
let i = 0;
|
||||
// Loop over the children, going vertically down first. When we run
|
||||
// out of vertical space (our y variable is bigger than box.y2), switch
|
||||
// to the second column.
|
||||
while (i < children.length) {
|
||||
let child = children[i];
|
||||
|
||||
if (y + this._itemHeight > box.y2) {
|
||||
// Is this the second column, or we're in
|
||||
// the first column and can't even fit one
|
||||
// item? In that case, break.
|
||||
if (columnIndex == 1 || i == 0) {
|
||||
break;
|
||||
}
|
||||
// Set x to the halfway point.
|
||||
columnIndex += 1;
|
||||
x = x + this._itemWidth + DEFAULT_SPACING;
|
||||
// And y is back to the top.
|
||||
y = 0;
|
||||
// Retry this same item, now that we're in the second column.
|
||||
// By looping back to the top here, we re-test the size
|
||||
// again for the second column.
|
||||
continue;
|
||||
}
|
||||
|
||||
let childBox = new Clutter.ActorBox();
|
||||
childBox.x1 = x;
|
||||
childBox.y1 = y;
|
||||
childBox.x2 = childBox.x1 + this._itemWidth;
|
||||
childBox.y2 = y + this._itemHeight;
|
||||
|
||||
y = childBox.y2 + DEFAULT_SPACING;
|
||||
|
||||
child.allocate(childBox, flags);
|
||||
this.actor.set_skip_paint(child, false);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (this._checkDocExistence) {
|
||||
// Now we know how many docs we are displaying, queue a check to see if any of them
|
||||
// have been deleted. If they are deleted, then we'll get a 'changed' signal; since
|
||||
// we'll now be displaying items we weren't previously, we'll check again to see
|
||||
// if they were deleted, and so forth and so on.
|
||||
// TODO: We should change this to ask for as many as we can fit in the given space:
|
||||
// https://bugzilla.gnome.org/show_bug.cgi?id=603522#c23
|
||||
this._docManager.queueExistenceCheck(i);
|
||||
this._checkDocExistence = false;
|
||||
}
|
||||
|
||||
for (; i < children.length; i++)
|
||||
this.actor.set_skip_paint(children[i], true);
|
||||
},
|
||||
|
||||
_onDocsChanged: function() {
|
||||
this._checkDocExistence = true;
|
||||
Main.queueDeferredWork(this._workId);
|
||||
},
|
||||
|
||||
_redisplay: function() {
|
||||
// Should be kept alive by the _actorsByUri
|
||||
this.actor.remove_all();
|
||||
let docs = this._docManager.getTimestampOrderedInfos();
|
||||
for (let i = 0; i < docs.length && i < MAX_DASH_DOCS; i++) {
|
||||
let doc = docs[i];
|
||||
let display = this._actorsByUri[doc.uri];
|
||||
if (display) {
|
||||
this.actor.add_actor(display.actor);
|
||||
} else {
|
||||
let display = new DashDocDisplayItem(doc);
|
||||
this.actor.add_actor(display.actor);
|
||||
this._actorsByUri[doc.uri] = display;
|
||||
}
|
||||
}
|
||||
// Any unparented actors must have been deleted
|
||||
for (let uri in this._actorsByUri) {
|
||||
let display = this._actorsByUri[uri];
|
||||
if (display.actor.get_parent() == null) {
|
||||
display.actor.destroy();
|
||||
delete this._actorsByUri[uri];
|
||||
}
|
||||
}
|
||||
this.emit('changed');
|
||||
}
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(DashDocDisplay.prototype);
|
||||
|
||||
function DocSearchProvider() {
|
||||
this._init();
|
||||
@ -504,9 +29,12 @@ DocSearchProvider.prototype = {
|
||||
'icon': docInfo.createIcon(Search.RESULT_ICON_SIZE)};
|
||||
},
|
||||
|
||||
activateResult: function(id) {
|
||||
activateResult: function(id, params) {
|
||||
params = Params.parse(params, { workspace: null,
|
||||
timestamp: null });
|
||||
|
||||
let docInfo = this._docManager.lookupByUri(id);
|
||||
docInfo.launch();
|
||||
docInfo.launch(params.workspace ? params.workspace.index() : -1);
|
||||
},
|
||||
|
||||
getInitialResultSet: function(terms) {
|
||||
|
504
js/ui/endSessionDialog.js
Normal file
504
js/ui/endSessionDialog.js
Normal file
@ -0,0 +1,504 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||
*
|
||||
* Copyright 2010 Red Hat, Inc
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
const DBus = imports.dbus;
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gdm = imports.gi.Gdm;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Pango = imports.gi.Pango;
|
||||
const St = imports.gi.St;
|
||||
const Shell = imports.gi.Shell;
|
||||
|
||||
const GnomeSession = imports.misc.gnomeSession
|
||||
const Lightbox = imports.ui.lightbox;
|
||||
const Main = imports.ui.main;
|
||||
const ModalDialog = imports.ui.modalDialog;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
let _endSessionDialog = null;
|
||||
|
||||
const _ITEM_ICON_SIZE = 48;
|
||||
const _DIALOG_ICON_SIZE = 32;
|
||||
|
||||
const GSM_SESSION_MANAGER_LOGOUT_FORCE = 2;
|
||||
|
||||
const EndSessionDialogIface = {
|
||||
name: 'org.gnome.SessionManager.EndSessionDialog',
|
||||
methods: [{ name: 'Open',
|
||||
inSignature: 'uuuao',
|
||||
outSignature: ''
|
||||
}
|
||||
],
|
||||
signals: [{ name: 'Canceled',
|
||||
outSignature: '',
|
||||
}],
|
||||
properties: []
|
||||
};
|
||||
|
||||
const logoutDialogContent = {
|
||||
subjectWithUser: _("Log Out %s"),
|
||||
subject: _("Log Out"),
|
||||
inhibitedDescription: _("Click Log Out to quit these applications and log out of the system."),
|
||||
uninhibitedDescriptionWithUser: _("%s will be logged out automatically in %d seconds."),
|
||||
uninhibitedDescription: _("You will be logged out automatically in %d seconds."),
|
||||
endDescription: _("Logging out of the system."),
|
||||
confirmButtonText: _("Log Out"),
|
||||
iconStyleClass: 'end-session-dialog-logout-icon'
|
||||
};
|
||||
|
||||
const shutdownDialogContent = {
|
||||
subject: _("Shut Down"),
|
||||
inhibitedDescription: _("Click Shut Down to quit these applications and shut down the system."),
|
||||
uninhibitedDescription: _("The system will shut down automatically in %d seconds."),
|
||||
endDescription: _("Shutting down the system."),
|
||||
confirmButtonText: _("Shut Down"),
|
||||
iconName: 'system-shutdown',
|
||||
iconStyleClass: 'end-session-dialog-shutdown-icon'
|
||||
};
|
||||
|
||||
const restartDialogContent = {
|
||||
subject: _("Restart"),
|
||||
inhibitedDescription: _("Click Restart to quit these applications and restart the system."),
|
||||
uninhibitedDescription: _("The system will restart automatically in %d seconds."),
|
||||
endDescription: _("Restarting the system."),
|
||||
confirmButtonText: _("Restart"),
|
||||
iconName: 'system-shutdown',
|
||||
iconStyleClass: 'end-session-dialog-shutdown-icon'
|
||||
};
|
||||
|
||||
const DialogContent = {
|
||||
0 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_LOGOUT */: logoutDialogContent,
|
||||
1 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_SHUTDOWN */: shutdownDialogContent,
|
||||
2 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_RESTART */: restartDialogContent
|
||||
};
|
||||
|
||||
function findAppFromInhibitor(inhibitor) {
|
||||
let desktopFile = inhibitor.app_id;
|
||||
|
||||
if (!GLib.str_has_suffix(desktopFile, '.desktop'))
|
||||
desktopFile += '.desktop';
|
||||
|
||||
let candidateDesktopFiles = [];
|
||||
|
||||
candidateDesktopFiles.push(desktopFile);
|
||||
candidateDesktopFiles.push('gnome-' + desktopFile);
|
||||
|
||||
let appSystem = Shell.AppSystem.get_default();
|
||||
let app = null;
|
||||
for (let i = 0; i < candidateDesktopFiles.length; i++) {
|
||||
try {
|
||||
app = appSystem.get_app(candidateDesktopFiles[i]);
|
||||
|
||||
if (app)
|
||||
break;
|
||||
} catch(e) {
|
||||
// ignore errors
|
||||
}
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
function ListItem(app, reason) {
|
||||
this._init(app, reason);
|
||||
}
|
||||
|
||||
ListItem.prototype = {
|
||||
_init: function(app, reason) {
|
||||
this._app = app;
|
||||
this._reason = reason;
|
||||
|
||||
if (this._reason == null)
|
||||
this._reason = '';
|
||||
|
||||
let layout = new St.BoxLayout({ vertical: false});
|
||||
|
||||
this.actor = new St.Clickable({ style_class: 'end-session-dialog-app-list-item',
|
||||
can_focus: true,
|
||||
child: layout,
|
||||
reactive: true,
|
||||
x_align: St.Align.START,
|
||||
x_fill: true });
|
||||
|
||||
this._icon = this._app.create_icon_texture(_ITEM_ICON_SIZE);
|
||||
|
||||
let iconBin = new St.Bin({ style_class: 'end-session-dialog-app-list-item-icon',
|
||||
child: this._icon });
|
||||
layout.add(iconBin);
|
||||
|
||||
let textLayout = new St.BoxLayout({ style_class: 'end-session-dialog-app-list-item-text-box',
|
||||
vertical: true });
|
||||
layout.add(textLayout);
|
||||
|
||||
this._nameLabel = new St.Label({ text: this._app.get_name(),
|
||||
style_class: 'end-session-dialog-app-list-item-name' });
|
||||
textLayout.add(this._nameLabel,
|
||||
{ expand: false,
|
||||
x_fill: true });
|
||||
|
||||
this._descriptionLabel = new St.Label({ text: this._reason,
|
||||
style_class: 'end-session-dialog-app-list-item-description' });
|
||||
textLayout.add(this._descriptionLabel,
|
||||
{ expand: true,
|
||||
x_fill: true });
|
||||
|
||||
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
|
||||
},
|
||||
|
||||
_onClicked: function() {
|
||||
this.emit('activate');
|
||||
this._app.activate(-1);
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(ListItem.prototype);
|
||||
|
||||
// The logout timer only shows updates every 10 seconds
|
||||
// until the last 10 seconds, then it shows updates every
|
||||
// second. This function takes a given time and returns
|
||||
// what we should show to the user for that time.
|
||||
function _roundSecondsToInterval(totalSeconds, secondsLeft, interval) {
|
||||
let time;
|
||||
|
||||
time = Math.ceil(secondsLeft);
|
||||
|
||||
// Final count down is in decrements of 1
|
||||
if (time <= interval)
|
||||
return time;
|
||||
|
||||
// Round up higher than last displayable time interval
|
||||
time += interval - 1;
|
||||
|
||||
// Then round down to that time interval
|
||||
if (time > totalSeconds)
|
||||
time = Math.ceil(totalSeconds);
|
||||
else
|
||||
time -= time % interval;
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
function _setLabelText(label, text) {
|
||||
if (text) {
|
||||
label.set_text(text);
|
||||
label.show();
|
||||
} else {
|
||||
label.set_text('');
|
||||
label.hide();
|
||||
}
|
||||
}
|
||||
|
||||
function EndSessionDialog() {
|
||||
if (_endSessionDialog == null) {
|
||||
this._init();
|
||||
DBus.session.exportObject('/org/gnome/SessionManager/EndSessionDialog',
|
||||
this);
|
||||
_endSessionDialog = this;
|
||||
}
|
||||
|
||||
return _endSessionDialog;
|
||||
}
|
||||
|
||||
function init() {
|
||||
// This always returns the same singleton object
|
||||
// By instantiating it initially, we register the
|
||||
// bus object, etc.
|
||||
let dialog = new EndSessionDialog();
|
||||
}
|
||||
|
||||
EndSessionDialog.prototype = {
|
||||
__proto__: ModalDialog.ModalDialog.prototype,
|
||||
|
||||
_init: function() {
|
||||
ModalDialog.ModalDialog.prototype._init.call(this);
|
||||
|
||||
this._user = Gdm.UserManager.ref_default().get_user(GLib.get_user_name());
|
||||
|
||||
this._secondsLeft = 0;
|
||||
this._totalSecondsToStayOpen = 0;
|
||||
this._inhibitors = [];
|
||||
|
||||
this.connect('destroy',
|
||||
Lang.bind(this, this._onDestroy));
|
||||
this.connect('opened',
|
||||
Lang.bind(this, this._onOpened));
|
||||
|
||||
this._userLoadedId = this._user.connect('notify::is_loaded',
|
||||
Lang.bind(this, this._updateContent));
|
||||
|
||||
this._userChangedId = this._user.connect('changed',
|
||||
Lang.bind(this, this._updateContent));
|
||||
|
||||
let mainContentLayout = new St.BoxLayout({ vertical: false });
|
||||
this.contentLayout.add(mainContentLayout,
|
||||
{ x_fill: true,
|
||||
y_fill: false });
|
||||
|
||||
this._iconBin = new St.Bin();
|
||||
mainContentLayout.add(this._iconBin,
|
||||
{ x_fill: true,
|
||||
y_fill: false,
|
||||
x_align: St.Align.END,
|
||||
y_align: St.Align.START });
|
||||
|
||||
let messageLayout = new St.BoxLayout({ vertical: true });
|
||||
mainContentLayout.add(messageLayout,
|
||||
{ y_align: St.Align.START });
|
||||
|
||||
this._subjectLabel = new St.Label({ style_class: 'end-session-dialog-subject' });
|
||||
|
||||
messageLayout.add(this._subjectLabel,
|
||||
{ y_fill: false,
|
||||
y_align: St.Align.START });
|
||||
|
||||
this._descriptionLabel = new St.Label({ style_class: 'end-session-dialog-description' });
|
||||
this._descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
|
||||
this._descriptionLabel.clutter_text.line_wrap = true;
|
||||
|
||||
messageLayout.add(this._descriptionLabel,
|
||||
{ y_fill: true,
|
||||
y_align: St.Align.START });
|
||||
|
||||
let scrollView = new St.ScrollView({ style_class: 'end-session-dialog-app-list'});
|
||||
scrollView.set_policy(Gtk.PolicyType.NEVER,
|
||||
Gtk.PolicyType.AUTOMATIC);
|
||||
this.contentLayout.add(scrollView,
|
||||
{ x_fill: true,
|
||||
y_fill: true });
|
||||
this._applicationList = new St.BoxLayout({ vertical: true });
|
||||
scrollView.add_actor(this._applicationList,
|
||||
{ x_fill: true,
|
||||
y_fill: true,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.MIDDLE });
|
||||
},
|
||||
|
||||
_onDestroy: function() {
|
||||
this._user.disconnect(this._userLoadedId);
|
||||
this._user.disconnect(this._userChangedId);
|
||||
},
|
||||
|
||||
_setIconFromFile: function(iconFile, styleClass) {
|
||||
if (styleClass)
|
||||
this._iconBin.set_style_class_name(styleClass);
|
||||
this._iconBin.set_style(null);
|
||||
|
||||
this._iconBin.child = null;
|
||||
if (iconFile) {
|
||||
this._iconBin.show();
|
||||
this._iconBin.set_style('background-image: url("' + iconFile + '");');
|
||||
} else {
|
||||
this._iconBin.hide();
|
||||
}
|
||||
},
|
||||
|
||||
_setIconFromName: function(iconName, styleClass) {
|
||||
if (styleClass)
|
||||
this._iconBin.set_style_class_name(styleClass);
|
||||
this._iconBin.set_style(null);
|
||||
|
||||
if (iconName != null) {
|
||||
let textureCache = St.TextureCache.get_default();
|
||||
let icon = textureCache.load_icon_name(this._iconBin.get_theme_node(),
|
||||
iconName,
|
||||
St.IconType.SYMBOLIC,
|
||||
_DIALOG_ICON_SIZE);
|
||||
|
||||
this._iconBin.child = icon;
|
||||
this._iconBin.show();
|
||||
} else {
|
||||
this._iconBin.child = null;
|
||||
this._iconBin.hide();
|
||||
}
|
||||
},
|
||||
|
||||
_updateContent: function() {
|
||||
if (this.state != ModalDialog.State.OPENING &&
|
||||
this.state != ModalDialog.State.OPENED)
|
||||
return;
|
||||
|
||||
let dialogContent = DialogContent[this._type];
|
||||
|
||||
let subject = dialogContent.subject;
|
||||
let description;
|
||||
|
||||
if (this._user.is_loaded && !dialogContent.iconName) {
|
||||
let iconFile = this._user.get_icon_file();
|
||||
|
||||
this._setIconFromFile(iconFile, dialogContent.iconStyleClass);
|
||||
} else if (dialogContent.iconName) {
|
||||
this._setIconFromName(dialogContent.iconName,
|
||||
dialogContent.iconStyleClass);
|
||||
}
|
||||
|
||||
if (this._inhibitors.length > 0) {
|
||||
this._stopTimer();
|
||||
description = dialogContent.inhibitedDescription;
|
||||
} else if (this._secondsLeft > 0 && this._inhibitors.length == 0) {
|
||||
let displayTime = _roundSecondsToInterval(this._totalSecondsToStayOpen,
|
||||
this._secondsLeft,
|
||||
10);
|
||||
|
||||
if (this._user.is_loaded) {
|
||||
let realName = this._user.get_real_name();
|
||||
|
||||
if (realName != null) {
|
||||
if (dialogContent.subjectWithUser)
|
||||
subject = dialogContent.subjectWithUser.format(realName);
|
||||
|
||||
if (dialogContent.uninhibitedDescriptionWithUser)
|
||||
description = dialogContent.uninhibitedDescriptionWithUser.format(realName, displayTime);
|
||||
else
|
||||
description = dialogContent.uninhibitedDescription.format(displayTime);
|
||||
}
|
||||
}
|
||||
|
||||
if (!description)
|
||||
description = dialogContent.uninhibitedDescription.format(displayTime);
|
||||
} else {
|
||||
description = dialogContent.endDescription;
|
||||
}
|
||||
|
||||
_setLabelText(this._subjectLabel, subject);
|
||||
_setLabelText(this._descriptionLabel, description);
|
||||
},
|
||||
|
||||
_updateButtons: function() {
|
||||
if (this.state != ModalDialog.State.OPENING &&
|
||||
this.state != ModalDialog.State.OPENED)
|
||||
return;
|
||||
|
||||
let dialogContent = DialogContent[this._type];
|
||||
let confirmButtonText = _("Confirm");
|
||||
|
||||
if (dialogContent.confirmButtonText)
|
||||
confirmButtonText = dialogContent.confirmButtonText;
|
||||
|
||||
this.setButtons([{ label: _("Cancel"),
|
||||
action: Lang.bind(this, this.cancel),
|
||||
key: Clutter.Escape
|
||||
},
|
||||
{ label: confirmButtonText,
|
||||
action: Lang.bind(this, this._confirm)
|
||||
}]);
|
||||
},
|
||||
|
||||
cancel: function() {
|
||||
this._stopTimer();
|
||||
DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
|
||||
'org.gnome.SessionManager.EndSessionDialog',
|
||||
'Canceled', '', []);
|
||||
this.close(global.get_current_time());
|
||||
},
|
||||
|
||||
_confirm: function() {
|
||||
this._fadeOutDialog();
|
||||
this._stopTimer();
|
||||
DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
|
||||
'org.gnome.SessionManager.EndSessionDialog',
|
||||
'Confirmed', '', []);
|
||||
},
|
||||
|
||||
_onOpened: function() {
|
||||
if (this._inhibitors.length == 0)
|
||||
this._startTimer();
|
||||
},
|
||||
|
||||
_startTimer: function() {
|
||||
this._secondsLeft = this._totalSecondsToStayOpen;
|
||||
Tweener.addTween(this,
|
||||
{ _secondsLeft: 0,
|
||||
time: this._secondsLeft,
|
||||
transition: 'linear',
|
||||
onUpdate: Lang.bind(this, this._updateContent),
|
||||
onComplete: Lang.bind(this, this._confirm),
|
||||
});
|
||||
},
|
||||
|
||||
_stopTimer: function() {
|
||||
Tweener.removeTweens(this);
|
||||
this._secondsLeft = 0;
|
||||
},
|
||||
|
||||
_onInhibitorLoaded: function(inhibitor) {
|
||||
if (this._inhibitors.indexOf(inhibitor) < 0) {
|
||||
// Stale inhibitor
|
||||
return;
|
||||
}
|
||||
|
||||
let app = findAppFromInhibitor(inhibitor);
|
||||
|
||||
if (app) {
|
||||
let item = new ListItem(app, inhibitor.reason);
|
||||
item.connect('activate',
|
||||
Lang.bind(this, function() {
|
||||
this.close(global.get_current_time());
|
||||
}));
|
||||
this._applicationList.add(item.actor, { x_fill: true });
|
||||
this._stopTimer();
|
||||
} else {
|
||||
// inhibiting app is a service, not an application
|
||||
this._inhibitors.splice(this._inhibitors.indexOf(inhibitor), 1);
|
||||
}
|
||||
|
||||
this._updateContent();
|
||||
},
|
||||
|
||||
OpenAsync: function(type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths, callback) {
|
||||
this._totalSecondsToStayOpen = totalSecondsToStayOpen;
|
||||
this._inhibitors = [];
|
||||
this._applicationList.destroy_children();
|
||||
this._type = type;
|
||||
|
||||
if (!(this._type in DialogContent))
|
||||
throw new DBus.DBusError('org.gnome.Shell.ModalDialog.TypeError',
|
||||
"Unknown dialog type requested");
|
||||
|
||||
for (let i = 0; i < inhibitorObjectPaths.length; i++) {
|
||||
let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i]);
|
||||
|
||||
inhibitor.connect('is-loaded',
|
||||
Lang.bind(this, function() {
|
||||
this._onInhibitorLoaded(inhibitor);
|
||||
}));
|
||||
this._inhibitors.push(inhibitor);
|
||||
}
|
||||
|
||||
if (!this.open(timestamp))
|
||||
throw new DBus.DBusError('org.gnome.Shell.ModalDialog.GrabError',
|
||||
"Cannot grab pointer and keyboard");
|
||||
|
||||
this._updateButtons();
|
||||
this._updateContent();
|
||||
|
||||
let signalId = this.connect('opened',
|
||||
Lang.bind(this, function() {
|
||||
callback();
|
||||
this.disconnect(signalId);
|
||||
}));
|
||||
}
|
||||
};
|
||||
DBus.conformExport(EndSessionDialog.prototype, EndSessionDialogIface);
|
@ -88,8 +88,6 @@ function init() {
|
||||
|
||||
_blockMethod('Clutter.Event.get_state', 'Shell.get_event_state',
|
||||
'gjs\'s handling of Clutter.ModifierType is broken. See bug 597292.');
|
||||
_blockMethod('Gdk.Device.get_state', 'global.get_pointer',
|
||||
'gjs\'s handling of Gdk.ModifierType is broken. See bug 597292.');
|
||||
_blockMethod('Gdk.Window.get_device_position', 'global.get_pointer',
|
||||
'gjs\'s handling of Gdk.ModifierType is broken. See bug 597292.');
|
||||
|
||||
|
@ -4,6 +4,8 @@ const GLib = imports.gi.GLib;
|
||||
const Gio = imports.gi.Gio;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const Config = imports.misc.config;
|
||||
|
||||
const ExtensionState = {
|
||||
ENABLED: 1,
|
||||
DISABLED: 2,
|
||||
@ -25,6 +27,36 @@ var disabledExtensions;
|
||||
// GFile for user extensions
|
||||
var userExtensionsDir = null;
|
||||
|
||||
/**
|
||||
* versionCheck:
|
||||
* @required: an array of versions we're compatible with
|
||||
* @current: the version we have
|
||||
*
|
||||
* Check if a component is compatible for an extension.
|
||||
* @required is an array, and at least one version must match.
|
||||
* @current must be in the format <major>.<minor>.<point>.<micro>
|
||||
* <micro> is always ignored
|
||||
* <point> is ignored if <minor> is even (so you can target the
|
||||
* whole stable release)
|
||||
* <minor> and <major> must match
|
||||
* Each target version must be at least <major> and <minor>
|
||||
*/
|
||||
function versionCheck(required, current) {
|
||||
let currentArray = current.split('.');
|
||||
let major = currentArray[0];
|
||||
let minor = currentArray[1];
|
||||
let point = currentArray[2];
|
||||
for (let i = 0; i < required.length; i++) {
|
||||
let requiredArray = required[i].split('.');
|
||||
if (requiredArray[0] == major &&
|
||||
requiredArray[1] == minor &&
|
||||
(requiredArray[2] == point ||
|
||||
(requiredArray[2] == undefined && parseInt(minor) % 2 == 0)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function loadExtension(dir, enabled, type) {
|
||||
let info;
|
||||
let baseErrorString = 'While loading extension from "' + dir.get_parse_name() + '": ';
|
||||
@ -43,8 +75,8 @@ function loadExtension(dir, enabled, type) {
|
||||
global.logError(baseErrorString + 'Failed to parse metadata.json: ' + e);
|
||||
return;
|
||||
}
|
||||
let requiredProperties = ['uuid', 'name', 'description'];
|
||||
for (let i = 0; i < requiredProperties; i++) {
|
||||
let requiredProperties = ['uuid', 'name', 'description', 'shell-version'];
|
||||
for (let i = 0; i < requiredProperties.length; i++) {
|
||||
let prop = requiredProperties[i];
|
||||
if (!meta[prop]) {
|
||||
global.logError(baseErrorString + 'missing "' + prop + '" property in metadata.json');
|
||||
@ -68,6 +100,12 @@ function loadExtension(dir, enabled, type) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!versionCheck(meta['shell-version'], Config.PACKAGE_VERSION) ||
|
||||
(meta['js-version'] && !versionCheck(meta['js-version'], Config.GJS_VERSION))) {
|
||||
global.logError(baseErrorString + 'extension is not compatible with current GNOME Shell and/or GJS version');
|
||||
return;
|
||||
}
|
||||
|
||||
extensionMeta[meta.uuid] = meta;
|
||||
extensionMeta[meta.uuid].type = type;
|
||||
extensionMeta[meta.uuid].path = dir.get_path();
|
||||
|
@ -1,693 +0,0 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const DND = imports.ui.dnd;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
const RedisplayFlags = { NONE: 0,
|
||||
FULL: 1 << 1,
|
||||
SUBSEARCH: 1 << 2,
|
||||
IMMEDIATE: 1 << 3 };
|
||||
|
||||
// Used by subclasses
|
||||
const ITEM_DISPLAY_ICON_SIZE = 48;
|
||||
const PREVIEW_ICON_SIZE = 96;
|
||||
|
||||
/* This is a virtual class that represents a single display item containing
|
||||
* a name, a description, and an icon. It allows selecting an item and represents
|
||||
* it by highlighting it with a different background color than the default.
|
||||
*/
|
||||
function GenericDisplayItem() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
GenericDisplayItem.prototype = {
|
||||
_init: function() {
|
||||
this.actor = new St.BoxLayout({ style_class: 'generic-display-item',
|
||||
reactive: true });
|
||||
|
||||
this.actor._delegate = this;
|
||||
this.actor.connect('button-release-event',
|
||||
Lang.bind(this,
|
||||
function() {
|
||||
// Activates the item by launching it
|
||||
this.emit('activate');
|
||||
return true;
|
||||
}));
|
||||
|
||||
let draggable = DND.makeDraggable(this.actor);
|
||||
draggable.connect('drag-begin',
|
||||
Lang.bind(this, function() {
|
||||
Main.overview.beginItemDrag(this);
|
||||
}));
|
||||
draggable.connect('drag-end',
|
||||
Lang.bind(this, function() {
|
||||
Main.overview.endItemDrag(this);
|
||||
}));
|
||||
|
||||
this._iconBin = new St.Bin();
|
||||
this.actor.add(this._iconBin);
|
||||
|
||||
this._infoText = new St.BoxLayout({ style_class: 'generic-display-item-text',
|
||||
vertical: true });
|
||||
this.actor.add(this._infoText, { expand: true, y_fill: false });
|
||||
|
||||
this._name = null;
|
||||
this._description = null;
|
||||
this._icon = null;
|
||||
|
||||
this._initialLoadComplete = false;
|
||||
|
||||
// An array of details description actors that we create over time for the item.
|
||||
// It is used for updating the description text inside the details actor when
|
||||
// the description text for the item is updated.
|
||||
this._detailsDescriptions = [];
|
||||
},
|
||||
|
||||
//// Draggable object interface ////
|
||||
|
||||
// Returns a cloned texture of the item's icon to represent the item as it
|
||||
// is being dragged.
|
||||
getDragActor: function(stageX, stageY) {
|
||||
return this._createIcon();
|
||||
},
|
||||
|
||||
// Returns the item icon, a separate copy of which is used to
|
||||
// represent the item as it is being dragged. This is used to
|
||||
// determine a snap-back location for the drag icon if it does
|
||||
// not get accepted by any drop target.
|
||||
getDragActorSource: function() {
|
||||
return this._icon;
|
||||
},
|
||||
|
||||
//// Public methods ////
|
||||
|
||||
// Highlights the item by setting a different background color than the default
|
||||
// if isSelected is true, removes the highlighting otherwise.
|
||||
markSelected: function(isSelected) {
|
||||
if (isSelected)
|
||||
this.actor.add_style_pseudo_class('selected');
|
||||
else
|
||||
this.actor.remove_style_pseudo_class('selected');
|
||||
},
|
||||
|
||||
/*
|
||||
* Returns an actor containing item details. In the future details can have more information than what
|
||||
* the preview pop-up has and be item-type specific.
|
||||
*/
|
||||
createDetailsActor: function() {
|
||||
|
||||
let details = new St.BoxLayout({ style_class: 'generic-display-container',
|
||||
vertical: true });
|
||||
|
||||
let mainDetails = new St.BoxLayout({ style_class: 'generic-display-container' });
|
||||
|
||||
// Inner box with name and description
|
||||
let textDetails = new St.BoxLayout({ style_class: 'generic-display-details',
|
||||
vertical: true });
|
||||
let detailsName = new St.Label({ style_class: 'generic-display-details-name',
|
||||
text: this._name.text });
|
||||
textDetails.add(detailsName);
|
||||
|
||||
let detailsDescription = new St.Label({ text: this._description.text });
|
||||
textDetails.add(detailsDescription);
|
||||
|
||||
this._detailsDescriptions.push(detailsDescription);
|
||||
|
||||
mainDetails.add(textDetails, { expand: true });
|
||||
|
||||
let previewIcon = this._createPreviewIcon();
|
||||
let largePreviewIcon = this._createLargePreviewIcon();
|
||||
|
||||
if (previewIcon != null && largePreviewIcon == null) {
|
||||
mainDetails.insert_actor(previewIcon, 0);
|
||||
}
|
||||
|
||||
details.add(mainDetails);
|
||||
|
||||
if (largePreviewIcon != null) {
|
||||
details.add(largePreviewIcon);
|
||||
}
|
||||
|
||||
return details;
|
||||
},
|
||||
|
||||
// Destroys the item.
|
||||
destroy: function() {
|
||||
this.actor.destroy();
|
||||
},
|
||||
|
||||
//// Pure virtual public methods ////
|
||||
|
||||
// Performes an action associated with launching this item, such as opening a file or an application.
|
||||
launch: function() {
|
||||
throw new Error('Not implemented');
|
||||
},
|
||||
|
||||
//// Protected methods ////
|
||||
|
||||
/*
|
||||
* Creates the graphical elements for the item based on the item information.
|
||||
*
|
||||
* nameText - name of the item
|
||||
* descriptionText - short description of the item
|
||||
*/
|
||||
_setItemInfo: function(nameText, descriptionText) {
|
||||
if (this._name != null) {
|
||||
// this also removes this._name from the parent container,
|
||||
// so we don't need to call this.actor.remove_actor(this._name) directly
|
||||
this._name.destroy();
|
||||
this._name = null;
|
||||
}
|
||||
if (this._description != null) {
|
||||
this._description.destroy();
|
||||
this._description = null;
|
||||
}
|
||||
if (this._icon != null) {
|
||||
// though we get the icon from elsewhere, we assume its ownership here,
|
||||
// and therefore should be responsible for distroying it
|
||||
this._icon.destroy();
|
||||
this._icon = null;
|
||||
}
|
||||
|
||||
this._icon = this._createIcon();
|
||||
this._iconBin.set_child(this._icon);
|
||||
|
||||
this._name = new St.Label({ style_class: 'generic-display-item-name',
|
||||
text: nameText });
|
||||
this._infoText.add(this._name);
|
||||
|
||||
this._description = new St.Label({ style_class: 'generic-display-item-description',
|
||||
text: descriptionText ? descriptionText : '' });
|
||||
this._infoText.add(this._description);
|
||||
},
|
||||
|
||||
// Sets the description text for the item, including the description text
|
||||
// in the details actors that have been created for the item.
|
||||
_setDescriptionText: function(text) {
|
||||
this._description.text = text;
|
||||
for (let i = 0; i < this._detailsDescriptions.length; i++) {
|
||||
let detailsDescription = this._detailsDescriptions[i];
|
||||
if (detailsDescription != null) {
|
||||
detailsDescription.text = text;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//// Virtual protected methods ////
|
||||
|
||||
// Creates and returns a large preview icon, but only if we have a detailed image.
|
||||
_createLargePreviewIcon : function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
//// Pure virtual protected methods ////
|
||||
|
||||
// Returns an icon for the item.
|
||||
_createIcon: function() {
|
||||
throw new Error('Not implemented');
|
||||
},
|
||||
|
||||
// Returns a preview icon for the item.
|
||||
_createPreviewIcon: function() {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
//// Private methods ////
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(GenericDisplayItem.prototype);
|
||||
|
||||
/* This is a virtual class that represents a display containing a collection of items
|
||||
* that can be filtered with a search string.
|
||||
*/
|
||||
function GenericDisplay() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
GenericDisplay.prototype = {
|
||||
_init : function() {
|
||||
this._search = '';
|
||||
this._expanded = false;
|
||||
|
||||
this.actor = new St.ScrollView({ x_fill: true,
|
||||
y_fill: false,
|
||||
vshadows: true });
|
||||
this._list = new St.BoxLayout({ style_class: 'generic-display-container',
|
||||
vertical: true });
|
||||
this.actor.add_actor(this._list);
|
||||
this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
||||
|
||||
this._pendingRedisplay = RedisplayFlags.NONE;
|
||||
this.actor.connect('notify::mapped', Lang.bind(this, this._onMappedNotify));
|
||||
|
||||
// map<itemId, Object> where Object represents the item info
|
||||
this._allItems = {};
|
||||
// set<itemId>
|
||||
this._matchedItems = {};
|
||||
// sorted array of items matched by search
|
||||
this._matchedItemKeys = [];
|
||||
// map<itemId, GenericDisplayItem>
|
||||
this._displayedItems = {};
|
||||
this._openDetailIndex = -1;
|
||||
this._selectedIndex = -1;
|
||||
},
|
||||
|
||||
//// Public methods ////
|
||||
|
||||
// Sets the search string and displays the matching items.
|
||||
setSearch: function(text) {
|
||||
let lowertext = text.toLowerCase();
|
||||
if (lowertext == this._search) {
|
||||
return;
|
||||
}
|
||||
let flags = RedisplayFlags.IMMEDIATE;
|
||||
if (this._search != '') {
|
||||
// Because we combine search terms with OR, we have to be sure that no new term
|
||||
// was introduced before deciding that the new search results will be a subset of
|
||||
// the existing search results.
|
||||
if (lowertext.indexOf(this._search) == 0 &&
|
||||
lowertext.split(/\s+/).length == this._search.split(/\s+/).length) {
|
||||
flags |= RedisplayFlags.SUBSEARCH;
|
||||
}
|
||||
}
|
||||
this._search = lowertext;
|
||||
this._redisplay(flags);
|
||||
},
|
||||
|
||||
// Launches the item that is currently selected, closing the Overview
|
||||
activateSelected: function() {
|
||||
if (this._selectedIndex != -1) {
|
||||
let selected = this._findDisplayedByIndex(this._selectedIndex);
|
||||
selected.launch();
|
||||
this.unsetSelected();
|
||||
Main.overview.hide();
|
||||
}
|
||||
},
|
||||
|
||||
// Moves the selection one up. If the selection was already on the top item, it's moved
|
||||
// to the bottom one. Returns true if the selection actually moved up, false if it wrapped
|
||||
// around to the bottom.
|
||||
selectUp: function() {
|
||||
let count = this._getVisibleCount();
|
||||
let selectedUp = true;
|
||||
let prev = this._selectedIndex - 1;
|
||||
if (this._selectedIndex <= 0) {
|
||||
prev = count - 1;
|
||||
selectedUp = false;
|
||||
}
|
||||
this._selectIndex(prev);
|
||||
return selectedUp;
|
||||
},
|
||||
|
||||
// Moves the selection one down. If the selection was already on the bottom item, it's moved
|
||||
// to the top one. Returns true if the selection actually moved down, false if it wrapped
|
||||
// around to the top.
|
||||
selectDown: function() {
|
||||
let count = this._getVisibleCount();
|
||||
let selectedDown = true;
|
||||
let next = this._selectedIndex + 1;
|
||||
if (this._selectedIndex == count - 1) {
|
||||
next = 0;
|
||||
selectedDown = false;
|
||||
}
|
||||
this._selectIndex(next);
|
||||
return selectedDown;
|
||||
},
|
||||
|
||||
// Selects the first item among the displayed items.
|
||||
selectFirstItem: function() {
|
||||
if (this.hasItems())
|
||||
this._selectIndex(0);
|
||||
},
|
||||
|
||||
// Selects the last item among the displayed items.
|
||||
selectLastItem: function() {
|
||||
let count = this._getVisibleCount();
|
||||
if (this.hasItems())
|
||||
this._selectIndex(count - 1);
|
||||
},
|
||||
|
||||
// Returns true if the display has some item selected.
|
||||
hasSelected: function() {
|
||||
return this._selectedIndex != -1;
|
||||
},
|
||||
|
||||
// Removes selection if some display item is selected.
|
||||
unsetSelected: function() {
|
||||
this._selectIndex(-1);
|
||||
},
|
||||
|
||||
// Returns true if the display has any displayed items.
|
||||
hasItems: function() {
|
||||
// TODO: figure out why this._list.displayedCount is returning a
|
||||
// positive number when this._mathedItems.length is 0
|
||||
// This can be triggered if a search string is entered for which there are no matches.
|
||||
// log('this._mathedItems.length: ' + this._matchedItems.length + ' this._list.displayedCount ' + this._list.displayedCount);
|
||||
return this._matchedItemKeys.length > 0;
|
||||
},
|
||||
|
||||
getMatchedItemsCount: function() {
|
||||
return this._matchedItemKeys.length;
|
||||
},
|
||||
|
||||
// Load the initial state
|
||||
load: function() {
|
||||
this._redisplay(RedisplayFlags.FULL);
|
||||
},
|
||||
|
||||
// Should be called when the display is closed
|
||||
resetState: function() {
|
||||
this._filterReset();
|
||||
this._openDetailIndex = -1;
|
||||
this.actor.get_vscroll_bar().get_adjustment().value = 0;
|
||||
},
|
||||
|
||||
// Returns an actor which acts as a sidebar; this is used for
|
||||
// the applications category view
|
||||
getNavigationArea: function () {
|
||||
return null;
|
||||
},
|
||||
|
||||
createDetailsForIndex: function(index) {
|
||||
let item = this._findDisplayedByIndex(index);
|
||||
return item.createDetailsActor();
|
||||
},
|
||||
|
||||
//// Protected methods ////
|
||||
|
||||
_recreateDisplayItems: function() {
|
||||
this._removeAllDisplayItems();
|
||||
this._setDefaultList();
|
||||
for (let itemId in this._allItems) {
|
||||
this._addDisplayItem(itemId);
|
||||
}
|
||||
},
|
||||
|
||||
// Creates a display item based on the information associated with itemId
|
||||
// and adds it to the list of displayed items, but does not yet display it.
|
||||
_addDisplayItem : function(itemId) {
|
||||
if (this._displayedItems.hasOwnProperty(itemId)) {
|
||||
log('Tried adding a display item for ' + itemId + ', but an item with this item id is already among displayed items.');
|
||||
return;
|
||||
}
|
||||
|
||||
let itemInfo = this._allItems[itemId];
|
||||
let displayItem = this._createDisplayItem(itemInfo);
|
||||
|
||||
displayItem.connect('activate',
|
||||
Lang.bind(this,
|
||||
function() {
|
||||
// update the selection
|
||||
this._selectIndex(this._list.get_children().indexOf(displayItem.actor));
|
||||
this.activateSelected();
|
||||
}));
|
||||
|
||||
displayItem.connect('show-details',
|
||||
Lang.bind(this,
|
||||
function() {
|
||||
let index = this._list.get_children().indexOf(displayItem.actor);
|
||||
/* Close the details pane if already open */
|
||||
if (index == this._openDetailIndex) {
|
||||
this._openDetailIndex = -1;
|
||||
this.emit('show-details', -1);
|
||||
} else {
|
||||
this._openDetailIndex = index;
|
||||
this.emit('show-details', index);
|
||||
}
|
||||
}));
|
||||
this._displayedItems[itemId] = displayItem;
|
||||
},
|
||||
|
||||
// Removes an item identifed by the itemId from the displayed items.
|
||||
_removeDisplayItem: function(itemId) {
|
||||
let children = this._list.get_children();
|
||||
let count = children.length;
|
||||
let displayItem = this._displayedItems[itemId];
|
||||
let displayItemIndex = children.indexOf(displayItem.actor);
|
||||
|
||||
if (this.hasSelected() && count == 1) {
|
||||
this.unsetSelected();
|
||||
} else if (this.hasSelected() && displayItemIndex < this._selectedIndex) {
|
||||
this.selectUp();
|
||||
}
|
||||
|
||||
displayItem.destroy();
|
||||
|
||||
delete this._displayedItems[itemId];
|
||||
},
|
||||
|
||||
// Removes all displayed items.
|
||||
_removeAllDisplayItems: function() {
|
||||
this.unsetSelected();
|
||||
for (itemId in this._displayedItems)
|
||||
this._removeDisplayItem(itemId);
|
||||
},
|
||||
|
||||
// Return true if there's an active search or other constraint
|
||||
// on the list
|
||||
_filterActive: function() {
|
||||
return this._search != '';
|
||||
},
|
||||
|
||||
// Called when we are resetting state
|
||||
_filterReset: function() {
|
||||
this.unsetSelected();
|
||||
},
|
||||
|
||||
_compareSearchMatch: function(a, b) {
|
||||
let countA = this._matchedItems[a];
|
||||
let countB = this._matchedItems[b];
|
||||
if (countA > countB)
|
||||
return -1;
|
||||
else if (countA < countB)
|
||||
return 1;
|
||||
else
|
||||
return this._compareItems(a, b);
|
||||
},
|
||||
|
||||
_setMatches: function(matches) {
|
||||
this._matchedItems = matches;
|
||||
this._matchedItemKeys = [];
|
||||
for (let itemId in this._matchedItems) {
|
||||
this._matchedItemKeys.push(itemId);
|
||||
}
|
||||
this._matchedItemKeys.sort(Lang.bind(this, this._compareSearchMatch));
|
||||
},
|
||||
|
||||
/**
|
||||
* _redisplaySubSearch:
|
||||
* A somewhat more optimized function called when we know
|
||||
* that we're going to be displaying a subset of the items
|
||||
* we already had, in the same order. In that case, we can
|
||||
* just hide the actors that shouldn't be shown.
|
||||
*/
|
||||
_redisplaySubSearch: function() {
|
||||
let matches = this._getSearchMatchedItems(true);
|
||||
|
||||
// Just hide all from the old set,
|
||||
// we'll show the ones we want below
|
||||
for (let itemId in this._displayedItems) {
|
||||
let item = this._displayedItems[itemId];
|
||||
item.actor.hide();
|
||||
}
|
||||
|
||||
this._setMatches(matches);
|
||||
|
||||
for (let itemId in matches) {
|
||||
let item = this._displayedItems[itemId];
|
||||
item.actor.show();
|
||||
}
|
||||
this._list.queue_relayout();
|
||||
},
|
||||
|
||||
_redisplayReordering: function() {
|
||||
if (!this._filterActive()) {
|
||||
this._setDefaultList();
|
||||
} else {
|
||||
this._setMatches(this._getSearchMatchedItems(false));
|
||||
}
|
||||
this._list.remove_all();
|
||||
for (let i = 0; i < this._matchedItemKeys.length; i++) {
|
||||
let itemId = this._matchedItemKeys[i];
|
||||
let item = this._displayedItems[itemId];
|
||||
item.actor.show();
|
||||
this._list.add_actor(item.actor);
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Updates the displayed items, applying the search string if one exists.
|
||||
* @flags: Flags controlling redisplay behavior as follows:
|
||||
* SUBSEARCH - Indicates that the current _search is a superstring of the previous
|
||||
* one, which implies we only need to re-search through previous results.
|
||||
* FULL - Indicates that we need recreate all displayed items.
|
||||
* IMMEDIATE - Do the full redisplay even if we're not mapped. This is useful
|
||||
* if you want to get the number of matched items and show/hide a section based on
|
||||
* that number.
|
||||
*/
|
||||
_redisplay: function(flags) {
|
||||
let immediate = (flags & RedisplayFlags.IMMEDIATE) != 0;
|
||||
if (!immediate && !this.actor.mapped) {
|
||||
this._pendingRedisplay |= flags;
|
||||
return;
|
||||
}
|
||||
|
||||
let isSubSearch = (flags & RedisplayFlags.SUBSEARCH) != 0;
|
||||
let fullReload = (flags & RedisplayFlags.FULL) != 0;
|
||||
|
||||
let hadSelected = this.hasSelected();
|
||||
this.unsetSelected();
|
||||
|
||||
if (!this._initialLoadComplete)
|
||||
fullReload = true;
|
||||
|
||||
if (!this._refreshCache())
|
||||
fullReload = true;
|
||||
|
||||
if (fullReload) {
|
||||
this._recreateDisplayItems();
|
||||
this._initialLoadComplete = true;
|
||||
}
|
||||
|
||||
if (isSubSearch) {
|
||||
this._redisplaySubSearch();
|
||||
} else {
|
||||
this._redisplayReordering();
|
||||
}
|
||||
|
||||
if (hadSelected) {
|
||||
this._selectedIndex = -1;
|
||||
this.selectFirstItem();
|
||||
}
|
||||
|
||||
this.emit('redisplayed');
|
||||
},
|
||||
|
||||
//// Pure virtual protected methods ////
|
||||
|
||||
// Performs the steps needed to have the latest information about the items.
|
||||
// Implementation should return %true if we are up to date, and %false
|
||||
// if a full reload occurred.
|
||||
_refreshCache: function() {
|
||||
throw new Error('Not implemented');
|
||||
},
|
||||
|
||||
// Sets the list of the displayed items based on the default sorting order.
|
||||
// The default sorting order is specific to each implementing class.
|
||||
_setDefaultList: function() {
|
||||
throw new Error('Not implemented');
|
||||
},
|
||||
|
||||
// Compares items associated with the item ids based on the order in which the
|
||||
// items should be displayed.
|
||||
// Intended to be used as a compareFunction for array.sort().
|
||||
// Returns an integer value indicating the result of the comparison.
|
||||
_compareItems: function(itemIdA, itemIdB) {
|
||||
throw new Error('Not implemented');
|
||||
},
|
||||
|
||||
// Checks if the item info can be a match for the search string.
|
||||
// Returns a boolean flag indicating if that's the case.
|
||||
_isInfoMatching: function(itemInfo, search) {
|
||||
throw new Error('Not implemented');
|
||||
},
|
||||
|
||||
// Creates a display item based on itemInfo.
|
||||
_createDisplayItem: function(itemInfo) {
|
||||
throw new Error('Not implemented');
|
||||
},
|
||||
|
||||
//// Private methods ////
|
||||
|
||||
_getItemSearchScore: function(itemId, terms) {
|
||||
let item = this._allItems[itemId];
|
||||
let score = 0;
|
||||
for (let i = 0; i < terms.length; i++) {
|
||||
let term = terms[i];
|
||||
if (this._isInfoMatching(item, term)) {
|
||||
score++;
|
||||
}
|
||||
}
|
||||
return score;
|
||||
},
|
||||
|
||||
_getSearchMatchedItems: function(isSubSearch) {
|
||||
// Break the search up into terms, and search for each
|
||||
// individual term. Keep track of the number of terms
|
||||
// each item matched.
|
||||
let terms = this._search.split(/\s+/);
|
||||
let matchScores = {};
|
||||
|
||||
if (isSubSearch) {
|
||||
for (let i = 0; i < this._matchedItemKeys.length; i++) {
|
||||
let itemId = this._matchedItemKeys[i];
|
||||
let score = this._getItemSearchScore(itemId, terms);
|
||||
if (score > 0)
|
||||
matchScores[itemId] = score;
|
||||
}
|
||||
} else {
|
||||
for (let itemId in this._displayedItems) {
|
||||
let score = this._getItemSearchScore(itemId, terms);
|
||||
if (score > 0)
|
||||
matchScores[itemId] = score;
|
||||
}
|
||||
}
|
||||
return matchScores;
|
||||
},
|
||||
|
||||
// Returns a display item based on its index in the ordering of the
|
||||
// display children.
|
||||
_findDisplayedByIndex: function(index) {
|
||||
let actor = this._list.get_children()[index];
|
||||
return this._findDisplayedByActor(actor);
|
||||
},
|
||||
|
||||
// Returns a display item based on the actor that represents it in
|
||||
// the display.
|
||||
_findDisplayedByActor: function(actor) {
|
||||
for (itemId in this._displayedItems) {
|
||||
let item = this._displayedItems[itemId];
|
||||
if (item.actor == actor) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
// Selects (e.g. highlights) a display item at the provided index,
|
||||
// updates this.selectedItemDetails actor, and emits 'selected' signal.
|
||||
_selectIndex: function(index) {
|
||||
// Cleanup from the previous item
|
||||
if (this.hasSelected()) {
|
||||
this._findDisplayedByIndex(this._selectedIndex).markSelected(false);
|
||||
}
|
||||
|
||||
this._selectedIndex = index;
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
// Mark the new item as selected and create its details pane
|
||||
let item = this._findDisplayedByIndex(index);
|
||||
item.markSelected(true);
|
||||
this.emit('selected');
|
||||
},
|
||||
|
||||
_getVisibleCount: function() {
|
||||
return this._list.get_n_children();
|
||||
},
|
||||
|
||||
_onMappedNotify: function () {
|
||||
let mapped = this.actor.mapped;
|
||||
if (mapped && this._pendingRedisplay > RedisplayFlags.NONE)
|
||||
this._redisplay(this._pendingRedisplay);
|
||||
|
||||
this._pendingRedisplay = RedisplayFlags.NONE;
|
||||
}
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(GenericDisplay.prototype);
|
@ -398,6 +398,9 @@ Inspector.prototype = {
|
||||
},
|
||||
|
||||
_allocate: function(actor, box, flags) {
|
||||
if (!this._eventHandler)
|
||||
return;
|
||||
|
||||
let primary = global.get_primary_monitor();
|
||||
|
||||
let [minWidth, minHeight, natWidth, natHeight] =
|
||||
@ -415,6 +418,7 @@ Inspector.prototype = {
|
||||
Clutter.ungrab_pointer(this._eventHandler);
|
||||
Clutter.ungrab_keyboard(this._eventHandler);
|
||||
this._eventHandler.destroy();
|
||||
this._eventHandler = null;
|
||||
this.emit('closed');
|
||||
},
|
||||
|
||||
|
210
js/ui/main.js
210
js/ui/main.js
@ -22,6 +22,7 @@ const _ = Gettext.gettext;
|
||||
|
||||
const Chrome = imports.ui.chrome;
|
||||
const CtrlAltTab = imports.ui.ctrlAltTab;
|
||||
const EndSessionDialog = imports.ui.endSessionDialog;
|
||||
const Environment = imports.ui.environment;
|
||||
const ExtensionSystem = imports.ui.extensionSystem;
|
||||
const MessageTray = imports.ui.messageTray;
|
||||
@ -39,6 +40,7 @@ const WindowManager = imports.ui.windowManager;
|
||||
const Magnifier = imports.ui.magnifier;
|
||||
const XdndHandler = imports.ui.xdndHandler;
|
||||
const StatusIconDispatcher = imports.ui.statusIconDispatcher;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const DEFAULT_BACKGROUND_COLOR = new Clutter.Color();
|
||||
DEFAULT_BACKGROUND_COLOR.from_pixel(0x2266bbff);
|
||||
@ -65,6 +67,8 @@ let xdndHandler = null;
|
||||
let statusIconDispatcher = null;
|
||||
let _errorLogStack = [];
|
||||
let _startDate;
|
||||
let _defaultCssStylesheet = null;
|
||||
let _cssStylesheet = null;
|
||||
|
||||
let background = null;
|
||||
|
||||
@ -109,6 +113,7 @@ function start() {
|
||||
global.stage.color = DEFAULT_BACKGROUND_COLOR;
|
||||
global.stage.no_clear_hint = true;
|
||||
|
||||
_defaultCssStylesheet = global.datadir + '/theme/gnome-shell.css';
|
||||
loadTheme();
|
||||
|
||||
let shellwm = global.window_manager;
|
||||
@ -170,6 +175,12 @@ function start() {
|
||||
}
|
||||
});
|
||||
|
||||
global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT, false, -1, 1);
|
||||
|
||||
// Provide the bus object for gnome-session to
|
||||
// initiate logouts.
|
||||
EndSessionDialog.init();
|
||||
|
||||
global.gdk_screen.connect('monitors-changed', _relayout);
|
||||
|
||||
ExtensionSystem.init();
|
||||
@ -188,25 +199,143 @@ function start() {
|
||||
_log('info', 'loaded at ' + _startDate);
|
||||
log('GNOME Shell started at ' + _startDate);
|
||||
|
||||
Mainloop.idle_add(_removeUnusedWorkspaces);
|
||||
|
||||
let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
|
||||
if (perfModuleName) {
|
||||
let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT");
|
||||
let module = eval('imports.perf.' + perfModuleName + ';');
|
||||
Scripting.runPerfScript(module, perfOutput);
|
||||
}
|
||||
|
||||
global.screen.connect('notify::n-workspaces', _nWorkspacesChanged);
|
||||
Mainloop.idle_add(_nWorkspacesChanged);
|
||||
}
|
||||
|
||||
let _workspaces = [];
|
||||
let _checkWorkspacesId = 0;
|
||||
|
||||
function _checkWorkspaces() {
|
||||
let i;
|
||||
let emptyWorkspaces = [];
|
||||
|
||||
for (i = 0; i < _workspaces.length; i++)
|
||||
emptyWorkspaces[i] = true;
|
||||
|
||||
let windows = global.get_window_actors();
|
||||
for (i = 0; i < windows.length; i++) {
|
||||
let win = windows[i];
|
||||
|
||||
if (win.get_meta_window().is_on_all_workspaces())
|
||||
continue;
|
||||
|
||||
let workspaceIndex = win.get_workspace();
|
||||
emptyWorkspaces[workspaceIndex] = false;
|
||||
}
|
||||
|
||||
// If we don't have an empty workspace at the end, add one
|
||||
if (!emptyWorkspaces[emptyWorkspaces.length -1]) {
|
||||
global.screen.append_new_workspace(false, global.get_current_time());
|
||||
emptyWorkspaces.push(false);
|
||||
}
|
||||
|
||||
// Delete other empty workspaces; do it from the end to avoid index changes
|
||||
for (i = emptyWorkspaces.length - 2; i >= 0; i--) {
|
||||
if (emptyWorkspaces[i])
|
||||
global.screen.remove_workspace(_workspaces[i], global.get_current_time());
|
||||
}
|
||||
|
||||
_checkWorkspacesId = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
function _queueCheckWorkspaces() {
|
||||
if (_checkWorkspacesId == 0)
|
||||
_checkWorkspacesId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, _checkWorkspaces);
|
||||
}
|
||||
|
||||
function _nWorkspacesChanged() {
|
||||
let oldNumWorkspaces = _workspaces.length;
|
||||
let newNumWorkspaces = global.screen.n_workspaces;
|
||||
|
||||
if (oldNumWorkspaces == newNumWorkspaces)
|
||||
return false;
|
||||
|
||||
let lostWorkspaces = [];
|
||||
if (newNumWorkspaces > oldNumWorkspaces) {
|
||||
let w;
|
||||
|
||||
// Assume workspaces are only added at the end
|
||||
for (w = oldNumWorkspaces; w < newNumWorkspaces; w++)
|
||||
_workspaces[w] = global.screen.get_workspace_by_index(w);
|
||||
|
||||
for (w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
|
||||
let workspace = _workspaces[w];
|
||||
workspace._windowAddedId = workspace.connect('window-added', _queueCheckWorkspaces);
|
||||
workspace._windowRemovedId = workspace.connect('window-removed', _queueCheckWorkspaces);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Assume workspaces are only removed sequentially
|
||||
// (e.g. 2,3,4 - not 2,4,7)
|
||||
let removedIndex;
|
||||
let removedNum = oldNumWorkspaces - newNumWorkspaces;
|
||||
for (let w = 0; w < oldNumWorkspaces; w++) {
|
||||
let workspace = global.screen.get_workspace_by_index(w);
|
||||
if (_workspaces[w] != workspace) {
|
||||
removedIndex = w;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let lostWorkspaces = _workspaces.splice(removedIndex, removedNum);
|
||||
lostWorkspaces.forEach(function(workspace) {
|
||||
workspace.disconnect(workspace._windowAddedId);
|
||||
workspace.disconnect(workspace._windowRemovedId);
|
||||
});
|
||||
}
|
||||
|
||||
_queueCheckWorkspaces();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* getThemeStylesheet:
|
||||
*
|
||||
* Get the theme CSS file that the shell will load
|
||||
*
|
||||
* Returns: A file path that contains the theme CSS,
|
||||
* null if using the default
|
||||
*/
|
||||
function getThemeStylesheet()
|
||||
{
|
||||
return _cssStylesheet;
|
||||
}
|
||||
|
||||
/**
|
||||
* setThemeStylesheet:
|
||||
* @cssStylesheet: A file path that contains the theme CSS,
|
||||
* set it to null to use the default
|
||||
*
|
||||
* Set the theme CSS file that the shell will load
|
||||
*/
|
||||
function setThemeStylesheet(cssStylesheet)
|
||||
{
|
||||
_cssStylesheet = cssStylesheet;
|
||||
}
|
||||
|
||||
/**
|
||||
* loadTheme:
|
||||
*
|
||||
* Reloads the theme CSS file from the default theme.
|
||||
* Reloads the theme CSS file
|
||||
*/
|
||||
function loadTheme() {
|
||||
let themeContext = St.ThemeContext.get_for_stage (global.stage);
|
||||
let stylesheetPath = global.datadir + '/theme/gnome-shell.css';
|
||||
let theme = new St.Theme ({ application_stylesheet: stylesheetPath });
|
||||
|
||||
let cssStylesheet = _defaultCssStylesheet;
|
||||
if (_cssStylesheet != null)
|
||||
cssStylesheet = _cssStylesheet;
|
||||
|
||||
let theme = new St.Theme ({ application_stylesheet: cssStylesheet });
|
||||
themeContext.set_theme (theme);
|
||||
}
|
||||
|
||||
@ -259,38 +388,8 @@ function _relayout() {
|
||||
|
||||
// To avoid updating the position and size of the workspaces
|
||||
// in the overview, we just hide the overview. The positions
|
||||
// will be updated when it is next shown. We do the same for
|
||||
// the calendar popdown.
|
||||
// will be updated when it is next shown.
|
||||
overview.hide();
|
||||
panel.hideCalendar();
|
||||
}
|
||||
|
||||
// metacity-clutter currently uses the same prefs as plain metacity,
|
||||
// which probably means we'll be starting out with multiple workspaces;
|
||||
// remove any unused ones. (We do this from an idle handler, because
|
||||
// global.get_window_actors() still returns NULL at the point when start()
|
||||
// is called.)
|
||||
function _removeUnusedWorkspaces() {
|
||||
|
||||
let windows = global.get_window_actors();
|
||||
let maxWorkspace = 0;
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
let win = windows[i];
|
||||
|
||||
if (!win.get_meta_window().is_on_all_workspaces() &&
|
||||
win.get_workspace() > maxWorkspace) {
|
||||
maxWorkspace = win.get_workspace();
|
||||
}
|
||||
}
|
||||
let screen = global.screen;
|
||||
if (screen.n_workspaces > maxWorkspace) {
|
||||
for (let w = screen.n_workspaces - 1; w > maxWorkspace; w--) {
|
||||
let workspace = screen.get_workspace_by_index(w);
|
||||
screen.remove_workspace(workspace, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// This function encapsulates hacks to make certain global keybindings
|
||||
@ -317,11 +416,8 @@ function _globalKeyPressHandler(actor, event) {
|
||||
if (action == Meta.KeyBindingAction.COMMAND_SCREENSHOT) {
|
||||
let gconf = GConf.Client.get_default();
|
||||
let command = gconf.get_string('/apps/metacity/keybinding_commands/command_screenshot');
|
||||
if (command != null && command != '') {
|
||||
let [ok, len, args] = GLib.shell_parse_argv(command);
|
||||
let p = new Shell.Process({'args' : args});
|
||||
p.run();
|
||||
}
|
||||
if (command != null && command != '')
|
||||
Util.spawnCommandLine(command);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -343,6 +439,12 @@ function _globalKeyPressHandler(actor, event) {
|
||||
case Meta.KeyBindingAction.WORKSPACE_RIGHT:
|
||||
wm.actionMoveWorkspaceRight();
|
||||
return true;
|
||||
case Meta.KeyBindingAction.WORKSPACE_UP:
|
||||
wm.actionMoveWorkspaceUp();
|
||||
return true;
|
||||
case Meta.KeyBindingAction.WORKSPACE_DOWN:
|
||||
wm.actionMoveWorkspaceDown();
|
||||
return true;
|
||||
case Meta.KeyBindingAction.PANEL_RUN_DIALOG:
|
||||
case Meta.KeyBindingAction.COMMAND_2:
|
||||
getRunDialog().open();
|
||||
@ -371,6 +473,7 @@ function _findModal(actor) {
|
||||
/**
|
||||
* pushModal:
|
||||
* @actor: #ClutterActor which will be given keyboard focus
|
||||
* @timestamp: optional timestamp
|
||||
*
|
||||
* Ensure we are in a mode where all keyboard and mouse input goes to
|
||||
* the stage, and focus @actor. Multiple calls to this function act in
|
||||
@ -381,11 +484,19 @@ function _findModal(actor) {
|
||||
* modal stack returns to this actor, reset the focus to the actor
|
||||
* which was focused at the time pushModal() was invoked.
|
||||
*
|
||||
* @timestamp is optionally used to associate the call with a specific user
|
||||
* initiated event. If not provided then the value of
|
||||
* global.get_current_time() is assumed.
|
||||
*
|
||||
* Returns: true iff we successfully acquired a grab or already had one
|
||||
*/
|
||||
function pushModal(actor) {
|
||||
function pushModal(actor, timestamp) {
|
||||
|
||||
if (timestamp == undefined)
|
||||
timestamp = global.get_current_time();
|
||||
|
||||
if (modalCount == 0) {
|
||||
if (!global.begin_modal(global.get_current_time())) {
|
||||
if (!global.begin_modal(timestamp)) {
|
||||
log('pushModal: invocation of begin_modal failed');
|
||||
return false;
|
||||
}
|
||||
@ -416,12 +527,21 @@ function pushModal(actor) {
|
||||
/**
|
||||
* popModal:
|
||||
* @actor: #ClutterActor passed to original invocation of pushModal().
|
||||
* @timestamp: optional timestamp
|
||||
*
|
||||
* Reverse the effect of pushModal(). If this invocation is undoing
|
||||
* the topmost invocation, then the focus will be restored to the
|
||||
* previous focus at the time when pushModal() was invoked.
|
||||
*
|
||||
* @timestamp is optionally used to associate the call with a specific user
|
||||
* initiated event. If not provided then the value of
|
||||
* global.get_current_time() is assumed.
|
||||
*/
|
||||
function popModal(actor) {
|
||||
function popModal(actor, timestamp) {
|
||||
|
||||
if (timestamp == undefined)
|
||||
timestamp = global.get_current_time();
|
||||
|
||||
modalCount -= 1;
|
||||
let focusIndex = _findModal(actor);
|
||||
if (focusIndex >= 0) {
|
||||
@ -440,7 +560,7 @@ function popModal(actor) {
|
||||
return;
|
||||
|
||||
global.stage.set_key_focus(null);
|
||||
global.end_modal(global.get_current_time());
|
||||
global.end_modal(timestamp);
|
||||
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,10 @@ const Tweener = imports.ui.tweener;
|
||||
const Main = imports.ui.main;
|
||||
const BoxPointer = imports.ui.boxpointer;
|
||||
const Params = imports.misc.params;
|
||||
const Utils = imports.misc.utils;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const ANIMATION_TIME = 0.2;
|
||||
const NOTIFICATION_TIMEOUT = 4;
|
||||
@ -38,6 +41,17 @@ const State = {
|
||||
HIDING: 3
|
||||
};
|
||||
|
||||
// These reasons are useful when we destroy the notifications received through
|
||||
// the notification daemon. We use EXPIRED for transient notifications that the
|
||||
// user did not interact with, DISMISSED for all other notifications that were
|
||||
// destroyed as a result of a user action, and SOURCE_CLOSED for the notifications
|
||||
// that were requested to be destroyed by the associated source.
|
||||
const NotificationDestroyedReason = {
|
||||
EXPIRED: 1,
|
||||
DISMISSED: 2,
|
||||
SOURCE_CLOSED: 3
|
||||
};
|
||||
|
||||
// Message tray has its custom Urgency enumeration. LOW, NORMAL and CRITICAL
|
||||
// urgency values map to the corresponding values for the notifications received
|
||||
// through the notification daemon. HIGH urgency value is used for chats received
|
||||
@ -103,8 +117,7 @@ URLHighlighter.prototype = {
|
||||
return true;
|
||||
} catch (e) {
|
||||
// TODO: remove this after gnome 3 release
|
||||
let p = new Shell.Process({ 'args' : ['gvfs-open', url] });
|
||||
p.run();
|
||||
Util.spawn(['gvfs-open', url]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -135,13 +148,13 @@ URLHighlighter.prototype = {
|
||||
|
||||
this.actor.clutter_text.set_markup(text);
|
||||
/* clutter_text.text contain text without markup */
|
||||
this._urls = Utils.findUrls(this.actor.clutter_text.text);
|
||||
this._urls = Util.findUrls(this.actor.clutter_text.text);
|
||||
this._highlightUrls();
|
||||
},
|
||||
|
||||
_highlightUrls: function() {
|
||||
// text here contain markup
|
||||
let urls = Utils.findUrls(this._text);
|
||||
let urls = Util.findUrls(this._text);
|
||||
let markup = '';
|
||||
let pos = 0;
|
||||
for (let i = 0; i < urls.length; i++) {
|
||||
@ -241,6 +254,7 @@ Notification.prototype = {
|
||||
// 'transient' is a reserved keyword in JS, so we have to use an alternate variable name
|
||||
this.isTransient = false;
|
||||
this.expanded = false;
|
||||
this._destroyed = false;
|
||||
this._useActionIcons = false;
|
||||
this._customContent = false;
|
||||
this._bannerBodyText = null;
|
||||
@ -248,6 +262,7 @@ Notification.prototype = {
|
||||
this._titleFitsInBannerMode = true;
|
||||
this._spacing = 0;
|
||||
|
||||
this._buttonFocusManager = null;
|
||||
this._hasFocus = false;
|
||||
this._lockTrayOnFocusGrab = false;
|
||||
// We use this._prevFocusedWindow and this._prevKeyFocusActor to return the
|
||||
@ -261,7 +276,11 @@ Notification.prototype = {
|
||||
this._capturedEventId = 0;
|
||||
this._keyPressId = 0;
|
||||
|
||||
source.connect('destroy', Lang.bind(this, this.destroy));
|
||||
source.connect('destroy', Lang.bind(this,
|
||||
// Avoid passing 'source' as an argument to this.destroy()
|
||||
function () {
|
||||
this.destroy();
|
||||
}));
|
||||
|
||||
this.actor = new St.Table({ name: 'notification',
|
||||
reactive: true });
|
||||
@ -384,7 +403,7 @@ Notification.prototype = {
|
||||
this._scrollArea = new St.ScrollView({ name: 'notification-scrollview',
|
||||
vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
|
||||
hscrollbar_policy: Gtk.PolicyType.NEVER,
|
||||
vshadows: true });
|
||||
vfade: true });
|
||||
this.actor.add(this._scrollArea, { row: 1,
|
||||
col: 1 });
|
||||
this._contentArea = new St.BoxLayout({ name: 'notification-body',
|
||||
@ -486,7 +505,7 @@ Notification.prototype = {
|
||||
this._buttonBox = box;
|
||||
}
|
||||
|
||||
let button = new St.Button();
|
||||
let button = new St.Button({ can_focus: true });
|
||||
|
||||
if (this._useActionIcons && Gtk.IconTheme.get_default().has_icon(id)) {
|
||||
button.add_style_class_name('notification-icon-button');
|
||||
@ -496,8 +515,15 @@ Notification.prototype = {
|
||||
button.label = label;
|
||||
}
|
||||
|
||||
if (!this._buttonFocusManager)
|
||||
this._buttonFocusManager = St.FocusManager.get_for_stage(global.stage);
|
||||
if (this._buttonBox.get_children().length > 0)
|
||||
this._buttonFocusManager.remove_group(this._buttonBox);
|
||||
|
||||
this._buttonBox.add(button);
|
||||
this._buttonFocusManager.add_group(this._buttonBox);
|
||||
button.connect('clicked', Lang.bind(this, this._onActionInvoked, id));
|
||||
|
||||
this._updated();
|
||||
},
|
||||
|
||||
@ -647,6 +673,10 @@ Notification.prototype = {
|
||||
this._focusActorChangedId = global.stage.connect('notify::key-focus', Lang.bind(this, this._focusActorChanged));
|
||||
|
||||
this._hasFocus = true;
|
||||
|
||||
if (this._buttonFocusManager)
|
||||
this._buttonBox.get_children()[0].grab_key_focus();
|
||||
|
||||
if (lockTray)
|
||||
Main.messageTray.lock();
|
||||
},
|
||||
@ -704,15 +734,6 @@ Notification.prototype = {
|
||||
this.destroy();
|
||||
},
|
||||
|
||||
_onKeyPress: function(actor, event) {
|
||||
let symbol = event.get_key_symbol();
|
||||
if (symbol == Clutter.Escape) {
|
||||
Main.messageTray.escapeTray();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
ungrabFocus: function() {
|
||||
if (!this._hasFocus)
|
||||
return;
|
||||
@ -762,8 +783,13 @@ Notification.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.emit('destroy');
|
||||
destroy: function(reason) {
|
||||
if (this._destroyed)
|
||||
return;
|
||||
this._destroyed = true;
|
||||
if (!reason)
|
||||
reason = NotificationDestroyedReason.DISMISSED;
|
||||
this.emit('destroy', reason);
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(Notification.prototype);
|
||||
@ -780,6 +806,7 @@ Source.prototype = {
|
||||
this._iconBin = new St.Bin({ width: this.ICON_SIZE,
|
||||
height: this.ICON_SIZE });
|
||||
this.isTransient = false;
|
||||
this.isChat = false;
|
||||
},
|
||||
|
||||
setTransient: function(isTransient) {
|
||||
@ -999,6 +1026,7 @@ MessageTray.prototype = {
|
||||
// added to the summary without a notification being shown.
|
||||
this._newSummaryItems = [];
|
||||
this._longestSummaryItem = null;
|
||||
this._chatSummaryItemsCount = 0;
|
||||
},
|
||||
|
||||
_setSizePosition: function() {
|
||||
@ -1032,7 +1060,12 @@ MessageTray.prototype = {
|
||||
|
||||
let summaryItem = new SummaryItem(source);
|
||||
|
||||
this._summary.insert_actor(summaryItem.actor, 0);
|
||||
if (source.isChat) {
|
||||
this._summary.insert_actor(summaryItem.actor, 0);
|
||||
this._chatSummaryItemsCount++;
|
||||
} else {
|
||||
this._summary.insert_actor(summaryItem.actor, this._chatSummaryItemsCount);
|
||||
}
|
||||
|
||||
let titleWidth = summaryItem.getTitleNaturalWidth();
|
||||
if (titleWidth > this._summaryItemTitleWidth) {
|
||||
@ -1097,6 +1130,10 @@ MessageTray.prototype = {
|
||||
this._newSummaryItems.splice(newSummaryItemsIndex, 1);
|
||||
|
||||
this._summaryItems.splice(index, 1);
|
||||
|
||||
if (source.isChat)
|
||||
this._chatSummaryItemsCount--;
|
||||
|
||||
if (this._longestSummaryItem.source == source) {
|
||||
let newTitleWidth = 0;
|
||||
this._longestSummaryItem = null;
|
||||
@ -1507,23 +1544,40 @@ MessageTray.prototype = {
|
||||
|
||||
_updateShowingNotification: function() {
|
||||
Tweener.removeTweens(this._notificationBin);
|
||||
this._tween(this._notificationBin, '_notificationState', State.SHOWN,
|
||||
{ y: 0,
|
||||
opacity: 255,
|
||||
time: ANIMATION_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: this._showNotificationCompleted,
|
||||
onCompleteScope: this
|
||||
});
|
||||
|
||||
// We auto-expand notifications with CRITICAL urgency.
|
||||
// We call _expandNotification() again on the notifications that
|
||||
// are expanded in case they were in the process of hiding and need
|
||||
// to re-expand.
|
||||
// We use Tweener.removeTweens() to remove a tween that was hiding the notification we are
|
||||
// updating, in case that notification was in the process of being hidden. However,
|
||||
// Tweener.removeTweens() would also remove a tween that was updating the position of the
|
||||
// notification we are updating, in case that notification was already expanded and its height
|
||||
// changed. Therefore we need to call this._expandNotification() for expanded notifications
|
||||
// to make sure their position is updated.
|
||||
if (this._notification.urgency == Urgency.CRITICAL || this._notification.expanded)
|
||||
// This will overwrite the y tween, but leave the opacity
|
||||
// tween, and so the onComplete will remain as well.
|
||||
this._expandNotification(true);
|
||||
|
||||
// We tween all notifications to full opacity. This ensures that both new notifications and
|
||||
// notifications that might have been in the process of hiding get full opacity.
|
||||
//
|
||||
// We tween any notification showing in the banner mode to banner height (this._notificationBin.y = 0).
|
||||
// This ensures that both new notifications and notifications in the banner mode that might
|
||||
// have been in the process of hiding are shown with the banner height.
|
||||
//
|
||||
// We use this._showNotificationCompleted() onComplete callback to extend the time the updated
|
||||
// notification is being shown.
|
||||
//
|
||||
// We don't set the y parameter for the tween for expanded notifications because
|
||||
// this._expandNotification() will result in getting this._notificationBin.y set to the appropriate
|
||||
// fully expanded value.
|
||||
let tweenParams = { opacity: 255,
|
||||
time: ANIMATION_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: this._showNotificationCompleted,
|
||||
onCompleteScope: this
|
||||
};
|
||||
if (!this._notification.expanded)
|
||||
tweenParams.y = 0;
|
||||
|
||||
this._tween(this._notificationBin, '_notificationState', State.SHOWN, tweenParams);
|
||||
},
|
||||
|
||||
_showNotificationCompleted: function() {
|
||||
@ -1586,7 +1640,7 @@ MessageTray.prototype = {
|
||||
let notification = this._notification;
|
||||
this._notification = null;
|
||||
if (notification.isTransient)
|
||||
notification.destroy();
|
||||
notification.destroy(NotificationDestroyedReason.EXPIRED);
|
||||
},
|
||||
|
||||
_expandNotification: function(autoExpanding) {
|
||||
@ -1736,10 +1790,34 @@ MessageTray.prototype = {
|
||||
let summaryNotification = this._summaryNotification;
|
||||
this._summaryNotification = null;
|
||||
if (summaryNotification.isTransient && !this._reNotifyWithSummaryNotificationAfterHide)
|
||||
summaryNotification.destroy();
|
||||
summaryNotification.destroy(NotificationDestroyedReason.EXPIRED);
|
||||
if (this._reNotifyWithSummaryNotificationAfterHide) {
|
||||
this._onNotify(summaryNotification.source, summaryNotification);
|
||||
this._reNotifyWithSummaryNotificationAfterHide = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function SystemNotificationSource() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
SystemNotificationSource.prototype = {
|
||||
__proto__: Source.prototype,
|
||||
|
||||
_init: function() {
|
||||
Source.prototype._init.call(this, _("System Information"));
|
||||
|
||||
this._setSummaryIcon(this.createNotificationIcon());
|
||||
},
|
||||
|
||||
createNotificationIcon: function() {
|
||||
return new St.Icon({ icon_name: 'dialog-information',
|
||||
icon_type: St.IconType.SYMBOLIC,
|
||||
icon_size: this.ICON_SIZE });
|
||||
},
|
||||
|
||||
_notificationClicked: function() {
|
||||
this.destroy();
|
||||
}
|
||||
};
|
||||
|
235
js/ui/modalDialog.js
Normal file
235
js/ui/modalDialog.js
Normal file
@ -0,0 +1,235 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gdk = imports.gi.Gdk;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Pango = imports.gi.Pango;
|
||||
const St = imports.gi.St;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const Params = imports.misc.params;
|
||||
|
||||
const Lightbox = imports.ui.lightbox;
|
||||
const Main = imports.ui.main;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
const OPEN_AND_CLOSE_TIME = 0.1;
|
||||
const FADE_OUT_DIALOG_TIME = 1.0;
|
||||
|
||||
const State = {
|
||||
OPENED: 0,
|
||||
CLOSED: 1,
|
||||
OPENING: 2,
|
||||
CLOSING: 3,
|
||||
FADED_OUT: 4
|
||||
};
|
||||
|
||||
function ModalDialog() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
ModalDialog.prototype = {
|
||||
_init: function(params) {
|
||||
params = Params.parse(params, { styleClass: null });
|
||||
|
||||
this.state = State.CLOSED;
|
||||
|
||||
this._group = new St.Group({ visible: false,
|
||||
x: 0,
|
||||
y: 0 });
|
||||
Main.uiGroup.add_actor(this._group);
|
||||
global.focus_manager.add_group(this._group);
|
||||
this._initialKeyFocus = this._group;
|
||||
|
||||
this._group.connect('destroy', Lang.bind(this, this._onGroupDestroy));
|
||||
|
||||
this._actionKeys = {};
|
||||
this._group.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
|
||||
|
||||
this._lightbox = new Lightbox.Lightbox(this._group,
|
||||
{ inhibitEvents: true });
|
||||
|
||||
this._backgroundBin = new St.Bin();
|
||||
|
||||
this._group.add_actor(this._backgroundBin);
|
||||
this._lightbox.highlight(this._backgroundBin);
|
||||
|
||||
this._dialogLayout = new St.BoxLayout({ style_class: 'modal-dialog',
|
||||
vertical: true });
|
||||
if (params.styleClass != null) {
|
||||
this._dialogLayout.add_style_class_name(params.styleClass);
|
||||
}
|
||||
this._backgroundBin.child = this._dialogLayout;
|
||||
|
||||
this.contentLayout = new St.BoxLayout({ vertical: true });
|
||||
this._dialogLayout.add(this.contentLayout,
|
||||
{ x_fill: true,
|
||||
y_fill: true,
|
||||
x_align: St.Align.MIDDLE,
|
||||
y_align: St.Align.START });
|
||||
|
||||
this._buttonLayout = new St.BoxLayout({ opacity: 220,
|
||||
vertical: false });
|
||||
this._dialogLayout.add(this._buttonLayout,
|
||||
{ expand: true,
|
||||
x_align: St.Align.MIDDLE,
|
||||
y_align: St.Align.END });
|
||||
},
|
||||
|
||||
setButtons: function(buttons) {
|
||||
this._buttonLayout.destroy_children();
|
||||
this._actionKeys = {};
|
||||
|
||||
let i = 0;
|
||||
for (let index in buttons) {
|
||||
let buttonInfo = buttons[index];
|
||||
let label = buttonInfo['label'];
|
||||
let action = buttonInfo['action'];
|
||||
let key = buttonInfo['key'];
|
||||
|
||||
let button = new St.Button({ style_class: 'modal-dialog-button',
|
||||
reactive: true,
|
||||
can_focus: true,
|
||||
label: label });
|
||||
|
||||
let x_alignment;
|
||||
if (buttons.length == 1)
|
||||
x_alignment = St.Align.END;
|
||||
else if (i == 0)
|
||||
x_alignment = St.Align.START;
|
||||
else if (i == buttons.length - 1)
|
||||
x_alignment = St.Align.END;
|
||||
else
|
||||
x_alignment = St.Align.MIDDLE;
|
||||
|
||||
this._initialKeyFocus = button;
|
||||
this._buttonLayout.add(button,
|
||||
{ expand: true,
|
||||
x_fill: false,
|
||||
y_fill: false,
|
||||
x_align: x_alignment,
|
||||
y_align: St.Align.MIDDLE });
|
||||
|
||||
button.connect('clicked', action);
|
||||
|
||||
if (key)
|
||||
this._actionKeys[key] = action;
|
||||
i++;
|
||||
}
|
||||
},
|
||||
|
||||
_onKeyPressEvent: function(object, keyPressEvent) {
|
||||
let symbol = keyPressEvent.get_key_symbol();
|
||||
let action = this._actionKeys[symbol];
|
||||
|
||||
if (action)
|
||||
action();
|
||||
},
|
||||
|
||||
_onGroupDestroy: function() {
|
||||
this.emit('destroy');
|
||||
},
|
||||
|
||||
_fadeOpen: function() {
|
||||
let monitor = global.get_focus_monitor();
|
||||
|
||||
this._backgroundBin.set_position(monitor.x, monitor.y);
|
||||
this._backgroundBin.set_size(monitor.width, monitor.height);
|
||||
|
||||
this.state = State.OPENING;
|
||||
|
||||
this._dialogLayout.opacity = 255;
|
||||
this._lightbox.show();
|
||||
this._group.opacity = 0;
|
||||
this._group.show();
|
||||
Tweener.addTween(this._group,
|
||||
{ opacity: 255,
|
||||
time: OPEN_AND_CLOSE_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this,
|
||||
function() {
|
||||
this._initialKeyFocus.grab_key_focus();
|
||||
this.state = State.OPENED;
|
||||
this.emit('opened');
|
||||
}),
|
||||
});
|
||||
},
|
||||
|
||||
open: function(timestamp) {
|
||||
if (this.state == State.OPENED || this.state == State.OPENING)
|
||||
return true;
|
||||
|
||||
if (!Main.pushModal(this._group, timestamp))
|
||||
return false;
|
||||
|
||||
global.stage.set_key_focus(this._group);
|
||||
|
||||
this._fadeOpen();
|
||||
return true;
|
||||
},
|
||||
|
||||
close: function(timestamp) {
|
||||
if (this.state == State.CLOSED || this.state == State.CLOSING)
|
||||
return;
|
||||
|
||||
let needsPopModal;
|
||||
|
||||
if (this.state == State.OPENED || this.state == State.OPENING)
|
||||
needsPopModal = true;
|
||||
else
|
||||
needsPopModal = false;
|
||||
|
||||
this.state = State.CLOSING;
|
||||
|
||||
Tweener.addTween(this._group,
|
||||
{ opacity: 0,
|
||||
time: OPEN_AND_CLOSE_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this,
|
||||
function() {
|
||||
this.state = State.CLOSED;
|
||||
this._group.hide();
|
||||
|
||||
if (needsPopModal)
|
||||
Main.popModal(this._group, timestamp);
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
// This method is like close, but fades the dialog out much slower,
|
||||
// and leaves the lightbox in place. Once in the faded out state,
|
||||
// the dialog can be brought back by an open call, or the lightbox
|
||||
// can be dismissed by a close call.
|
||||
//
|
||||
// The main point of this method is to give some indication to the user
|
||||
// that the dialog reponse has been acknowledged but will take a few
|
||||
// moments before being processed.
|
||||
// e.g., if a user clicked "Log Out" then the dialog should go away
|
||||
// imediately, but the lightbox should remain until the logout is
|
||||
// complete.
|
||||
_fadeOutDialog: function(timestamp) {
|
||||
if (this.state == State.CLOSED || this.state == State.CLOSING)
|
||||
return;
|
||||
|
||||
if (this.state == State.FADED_OUT)
|
||||
return;
|
||||
|
||||
Tweener.addTween(this._dialogLayout,
|
||||
{ opacity: 0,
|
||||
time: FADE_OUT_DIALOG_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this,
|
||||
function() {
|
||||
this.state = State.FADED_OUT;
|
||||
Main.popModal(this._group, timestamp);
|
||||
})
|
||||
});
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(ModalDialog.prototype);
|
@ -9,9 +9,11 @@ const St = imports.gi.St;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const Config = imports.misc.config;
|
||||
const Main = imports.ui.main;
|
||||
const MessageTray = imports.ui.messageTray;
|
||||
const Params = imports.misc.params;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
let nextNotificationId = 1;
|
||||
|
||||
@ -126,17 +128,8 @@ NotificationDaemon.prototype = {
|
||||
log('Failed to acquire org.freedesktop.Notifications');
|
||||
else {
|
||||
log('Failed to acquire org.freedesktop.Notifications; trying again');
|
||||
|
||||
// kill the notification-daemon. pkill is more portable
|
||||
// than killall, but on Linux at least it won't match if
|
||||
// you pass more than 15 characters of the process name...
|
||||
// However, if you use the '-f' flag to match the entire
|
||||
// command line, it will work, but we have to be careful
|
||||
// in that case that we don't match 'gedit
|
||||
// notification-daemon.c' or whatever...
|
||||
let p = new Shell.Process({ args: ['pkill', '-f',
|
||||
'^([^ ]*/)?(notification-daemon|notify-osd)$']});
|
||||
p.run();
|
||||
Util.killall('notification-daemon');
|
||||
Util.killall('notify-osd');
|
||||
}
|
||||
},
|
||||
|
||||
@ -153,9 +146,9 @@ NotificationDaemon.prototype = {
|
||||
return new St.Icon({ icon_name: icon,
|
||||
icon_type: St.IconType.FULLCOLOR,
|
||||
icon_size: size });
|
||||
} else if (hints.icon_data) {
|
||||
} else if (hints['image-data']) {
|
||||
let [width, height, rowStride, hasAlpha,
|
||||
bitsPerSample, nChannels, data] = hints.icon_data;
|
||||
bitsPerSample, nChannels, data] = hints['image-data'];
|
||||
return textureCache.load_from_raw(data, data.length, hasAlpha,
|
||||
width, height, rowStride, size);
|
||||
} else {
|
||||
@ -245,6 +238,15 @@ NotificationDaemon.prototype = {
|
||||
|
||||
hints = Params.parse(hints, { urgency: Urgency.NORMAL }, true);
|
||||
|
||||
// Be compatible with the various hints for image data
|
||||
// 'image-data' is the latest name of this hint, introduced in 1.2
|
||||
if (!hints['image-data']) {
|
||||
if (hints['image_data'])
|
||||
hints['image-data'] = hints['image_data']; // version 1.1 of the spec
|
||||
else if (hints['icon_data'])
|
||||
hints['image-data'] = hints['icon_data']; // previous versions of the spec
|
||||
}
|
||||
|
||||
let ndata = { appName: appName,
|
||||
icon: icon,
|
||||
summary: summary,
|
||||
@ -320,13 +322,22 @@ NotificationDaemon.prototype = {
|
||||
{ icon: iconActor,
|
||||
bannerMarkup: true });
|
||||
ndata.notification = notification;
|
||||
notification.connect('clicked', Lang.bind(this,
|
||||
function(n) {
|
||||
this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
|
||||
}));
|
||||
notification.connect('destroy', Lang.bind(this,
|
||||
function(n) {
|
||||
function(n, reason) {
|
||||
delete this._notifications[id];
|
||||
let notificationClosedReason;
|
||||
switch (reason) {
|
||||
case MessageTray.NotificationDestroyedReason.EXPIRED:
|
||||
notificationClosedReason = NotificationClosedReason.EXPIRED;
|
||||
break;
|
||||
case MessageTray.NotificationDestroyedReason.DISMISSED:
|
||||
notificationClosedReason = NotificationClosedReason.DISMISSED;
|
||||
break;
|
||||
case MessageTray.NotificationDestroyedReason.SOURCE_CLOSED:
|
||||
notificationClosedReason = NotificationClosedReason.APP_CLOSED;
|
||||
break;
|
||||
}
|
||||
this._emitNotificationClosed(id, notificationClosedReason);
|
||||
}));
|
||||
notification.connect('action-invoked', Lang.bind(this,
|
||||
function(n, actionId) {
|
||||
@ -367,10 +378,9 @@ NotificationDaemon.prototype = {
|
||||
let ndata = this._notifications[id];
|
||||
if (ndata) {
|
||||
if (ndata.notification)
|
||||
ndata.notification.destroy();
|
||||
ndata.notification.destroy(MessageTray.NotificationDestroyedReason.SOURCE_CLOSED);
|
||||
delete this._notifications[id];
|
||||
}
|
||||
this._emitNotificationClosed(id, NotificationClosedReason.APP_CLOSED);
|
||||
},
|
||||
|
||||
GetCapabilities: function() {
|
||||
@ -390,10 +400,10 @@ NotificationDaemon.prototype = {
|
||||
|
||||
GetServerInformation: function() {
|
||||
return [
|
||||
'GNOME Shell',
|
||||
Config.PACKAGE_NAME,
|
||||
'GNOME',
|
||||
'0.1', // FIXME, get this from somewhere
|
||||
'1.0'
|
||||
Config.PACKAGE_VERSION,
|
||||
'1.2'
|
||||
];
|
||||
},
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
const Meta = imports.gi.Meta;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Signals = imports.signals;
|
||||
@ -15,7 +16,6 @@ const AppDisplay = imports.ui.appDisplay;
|
||||
const Dash = imports.ui.dash;
|
||||
const DND = imports.ui.dnd;
|
||||
const DocDisplay = imports.ui.docDisplay;
|
||||
const GenericDisplay = imports.ui.genericDisplay;
|
||||
const Lightbox = imports.ui.lightbox;
|
||||
const Main = imports.ui.main;
|
||||
const MessageTray = imports.ui.messageTray;
|
||||
@ -31,32 +31,19 @@ const ANIMATION_TIME = 0.25;
|
||||
// We split the screen vertically between the dash and the view selector.
|
||||
const DASH_SPLIT_FRACTION = 0.1;
|
||||
|
||||
|
||||
const DND_WINDOW_SWITCH_TIMEOUT = 1250;
|
||||
|
||||
function Source() {
|
||||
this._init();
|
||||
}
|
||||
const SwipeScrollDirection = {
|
||||
NONE: 0,
|
||||
HORIZONTAL: 1,
|
||||
VERTICAL: 2
|
||||
};
|
||||
|
||||
Source.prototype = {
|
||||
__proto__: MessageTray.Source.prototype,
|
||||
|
||||
_init: function() {
|
||||
MessageTray.Source.prototype._init.call(this,
|
||||
"System Information");
|
||||
this._setSummaryIcon(this.createNotificationIcon());
|
||||
},
|
||||
|
||||
createNotificationIcon: function() {
|
||||
return new St.Icon({ icon_name: 'dialog-information',
|
||||
icon_type: St.IconType.SYMBOLIC,
|
||||
icon_size: this.ICON_SIZE });
|
||||
},
|
||||
|
||||
_notificationClicked: function() {
|
||||
this.destroy();
|
||||
}
|
||||
}
|
||||
const SwipeScrollResult = {
|
||||
CANCEL: 0,
|
||||
SWIPE: 1,
|
||||
CLICK: 2
|
||||
};
|
||||
|
||||
function ShellInfo() {
|
||||
this._init();
|
||||
@ -79,7 +66,7 @@ ShellInfo.prototype = {
|
||||
|
||||
setMessage: function(text, undoCallback, undoLabel) {
|
||||
if (this._source == null) {
|
||||
this._source = new Source();
|
||||
this._source = new MessageTray.SystemNotificationSource();
|
||||
this._source.connect('destroy', Lang.bind(this,
|
||||
function() {
|
||||
this._source = null;
|
||||
@ -124,7 +111,8 @@ Overview.prototype = {
|
||||
|
||||
this._spacing = 0;
|
||||
|
||||
this._group = new St.Group({ name: 'overview' });
|
||||
this._group = new St.Group({ name: 'overview',
|
||||
reactive: true });
|
||||
this._group._delegate = this;
|
||||
this._group.connect('style-changed',
|
||||
Lang.bind(this, function() {
|
||||
@ -136,6 +124,11 @@ Overview.prototype = {
|
||||
}
|
||||
}));
|
||||
|
||||
this._scrollDirection = SwipeScrollDirection.NONE;
|
||||
this._scrollAdjustment = null;
|
||||
this._capturedEventId = 0;
|
||||
this._buttonPressId = 0;
|
||||
|
||||
this.shellInfo = new ShellInfo();
|
||||
|
||||
this._workspacesDisplay = null;
|
||||
@ -180,7 +173,7 @@ Overview.prototype = {
|
||||
this._dash.actor.add_constraint(this.viewSelector.constrainY);
|
||||
this._dash.actor.add_constraint(this.viewSelector.constrainHeight);
|
||||
|
||||
this._coverPane.lower_bottom();
|
||||
this._coverPane.hide();
|
||||
|
||||
// XDND
|
||||
this._dragMonitor = {
|
||||
@ -193,6 +186,7 @@ Overview.prototype = {
|
||||
this._windowSwitchTimeoutId = 0;
|
||||
this._windowSwitchTimestamp = 0;
|
||||
this._lastActiveWorkspaceIndex = -1;
|
||||
this._lastHoveredWindow = null;
|
||||
this._needsFakePointerEvent = false;
|
||||
|
||||
this.workspaces = null;
|
||||
@ -212,7 +206,7 @@ Overview.prototype = {
|
||||
global.screen.get_workspace_by_index(this._lastActiveWorkspaceIndex).activate(time);
|
||||
this.hideTemporarily();
|
||||
}
|
||||
|
||||
this._lastHoveredWindow = null;
|
||||
DND.removeMonitor(this._dragMonitor);
|
||||
},
|
||||
|
||||
@ -226,15 +220,24 @@ Overview.prototype = {
|
||||
},
|
||||
|
||||
_onDragMotion: function(dragEvent) {
|
||||
let targetIsWindow = dragEvent.targetActor &&
|
||||
dragEvent.targetActor._delegate &&
|
||||
dragEvent.targetActor._delegate.metaWindow;
|
||||
|
||||
if (targetIsWindow &&
|
||||
dragEvent.targetActor._delegate.metaWindow == this._lastHoveredWindow)
|
||||
return DND.DragMotionResult.CONTINUE;
|
||||
|
||||
this._lastHoveredWindow = null;
|
||||
|
||||
if (this._windowSwitchTimeoutId != 0) {
|
||||
Mainloop.source_remove(this._windowSwitchTimeoutId);
|
||||
this._windowSwitchTimeoutId = 0;
|
||||
this._needsFakePointerEvent = false;
|
||||
}
|
||||
|
||||
if (dragEvent.targetActor &&
|
||||
dragEvent.targetActor._delegate &&
|
||||
dragEvent.targetActor._delegate.metaWindow) {
|
||||
if (targetIsWindow) {
|
||||
this._lastHoveredWindow = dragEvent.targetActor._delegate.metaWindow;
|
||||
this._windowSwitchTimestamp = global.get_current_time();
|
||||
this._windowSwitchTimeoutId = Mainloop.timeout_add(DND_WINDOW_SWITCH_TIMEOUT,
|
||||
Lang.bind(this, function() {
|
||||
@ -242,12 +245,164 @@ Overview.prototype = {
|
||||
Main.activateWindow(dragEvent.targetActor._delegate.metaWindow,
|
||||
this._windowSwitchTimestamp);
|
||||
this.hideTemporarily();
|
||||
this._lastHoveredWindow = null;
|
||||
}));
|
||||
}
|
||||
|
||||
return DND.DragMotionResult.CONTINUE;
|
||||
},
|
||||
|
||||
setScrollAdjustment: function(adjustment, direction) {
|
||||
this._scrollAdjustment = adjustment;
|
||||
if (this._scrollAdjustment == null)
|
||||
this._scrollDirection = SwipeScrollDirection.NONE;
|
||||
else
|
||||
this._scrollDirection = direction;
|
||||
},
|
||||
|
||||
_onButtonPress: function(actor, event) {
|
||||
if (this._scrollDirection == SwipeScrollDirection.NONE)
|
||||
return;
|
||||
|
||||
let [stageX, stageY] = event.get_coords();
|
||||
this._dragStartX = this._dragX = stageX;
|
||||
this._dragStartY = this._dragY = stageY;
|
||||
this._dragStartValue = this._scrollAdjustment.value;
|
||||
this._lastMotionTime = -1; // used to track "stopping" while swipe-scrolling
|
||||
this._capturedEventId = global.stage.connect('captured-event',
|
||||
Lang.bind(this, this._onCapturedEvent));
|
||||
this.emit('swipe-scroll-begin');
|
||||
},
|
||||
|
||||
_onCapturedEvent: function(actor, event) {
|
||||
let stageX, stageY;
|
||||
let threshold = Gtk.Settings.get_default().gtk_dnd_drag_threshold;
|
||||
|
||||
switch(event.type()) {
|
||||
case Clutter.EventType.BUTTON_RELEASE:
|
||||
[stageX, stageY] = event.get_coords();
|
||||
|
||||
// default to snapping back to the original value
|
||||
let newValue = this._dragStartValue;
|
||||
|
||||
let minValue = this._scrollAdjustment.lower;
|
||||
let maxValue = this._scrollAdjustment.upper - this._scrollAdjustment.page_size;
|
||||
|
||||
let direction;
|
||||
if (this._scrollDirection == SwipeScrollDirection.HORIZONTAL) {
|
||||
direction = stageX > this._dragStartX ? -1 : 1;
|
||||
if (St.Widget.get_default_direction() == St.TextDirection.RTL)
|
||||
direction *= -1;
|
||||
} else {
|
||||
direction = stageY > this._dragStartY ? -1 : 1;
|
||||
}
|
||||
|
||||
// We default to scroll a full page size; both the first
|
||||
// and the last page may be smaller though, so we need to
|
||||
// adjust difference in those cases.
|
||||
let difference = direction * this._scrollAdjustment.page_size;
|
||||
if (this._dragStartValue + difference > maxValue)
|
||||
difference = maxValue - this._dragStartValue;
|
||||
else if (this._dragStartValue + difference < minValue)
|
||||
difference = minValue - this._dragStartValue;
|
||||
|
||||
// If the user has moved more than half the scroll
|
||||
// difference, we want to "settle" to the new value
|
||||
// even if the user stops dragging rather "throws" by
|
||||
// releasing during the drag.
|
||||
let distance = this._dragStartValue - this._scrollAdjustment.value;
|
||||
let noStop = Math.abs(distance / difference) > 0.5;
|
||||
|
||||
// We detect if the user is stopped by comparing the
|
||||
// timestamp of the button release with the timestamp of
|
||||
// the last motion. Experimentally, a difference of 0 or 1
|
||||
// millisecond indicates that the mouse is in motion, a
|
||||
// larger difference indicates that the mouse is stopped.
|
||||
if ((this._lastMotionTime > 0 &&
|
||||
this._lastMotionTime > event.get_time() - 2) ||
|
||||
noStop) {
|
||||
if (this._dragStartValue + difference >= minValue &&
|
||||
this._dragStartValue + difference <= maxValue)
|
||||
newValue += difference;
|
||||
}
|
||||
|
||||
let result;
|
||||
|
||||
// See if the user has moved the mouse enough to trigger
|
||||
// a drag
|
||||
if (Math.abs(stageX - this._dragStartX) < threshold &&
|
||||
Math.abs(stageY - this._dragStartY) < threshold) {
|
||||
// no motion? It's a click!
|
||||
result = SwipeScrollResult.CLICK;
|
||||
this.emit('swipe-scroll-end', result);
|
||||
} else {
|
||||
if (newValue == this._dragStartValue)
|
||||
result = SwipeScrollResult.CANCEL;
|
||||
else
|
||||
result = SwipeScrollResult.SWIPE;
|
||||
|
||||
// The event capture handler is disconnected
|
||||
// while scrolling to the final position, so
|
||||
// to avoid undesired prelights we raise
|
||||
// the cover pane.
|
||||
this._coverPane.raise_top();
|
||||
this._coverPane.show();
|
||||
|
||||
Tweener.addTween(this._scrollAdjustment,
|
||||
{ value: newValue,
|
||||
time: ANIMATION_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onCompleteScope: this,
|
||||
onComplete: function() {
|
||||
this._coverPane.hide();
|
||||
this.emit('swipe-scroll-end',
|
||||
result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
global.stage.disconnect(this._capturedEventId);
|
||||
this._capturedEventId = 0;
|
||||
|
||||
return result != SwipeScrollResult.CLICK;
|
||||
|
||||
case Clutter.EventType.MOTION:
|
||||
[stageX, stageY] = event.get_coords();
|
||||
let dx = this._dragX - stageX;
|
||||
let dy = this._dragY - stageY;
|
||||
let primary = global.get_primary_monitor();
|
||||
|
||||
this._dragX = stageX;
|
||||
this._dragY = stageY;
|
||||
this._lastMotionTime = event.get_time();
|
||||
|
||||
// See if the user has moved the mouse enough to trigger
|
||||
// a drag
|
||||
if (Math.abs(stageX - this._dragStartX) < threshold &&
|
||||
Math.abs(stageY - this._dragStartY) < threshold)
|
||||
return true;
|
||||
|
||||
if (this._scrollDirection == SwipeScrollDirection.HORIZONTAL) {
|
||||
if (St.Widget.get_default_direction() == St.TextDirection.RTL)
|
||||
this._scrollAdjustment.value -= (dx / primary.width) * this._scrollAdjustment.page_size;
|
||||
else
|
||||
this._scrollAdjustment.value += (dx / primary.width) * this._scrollAdjustment.page_size;
|
||||
} else {
|
||||
this._scrollAdjustment.value += (dy / primary.height) * this._scrollAdjustment.page_size;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
// Block enter/leave events to avoid prelights
|
||||
// during swipe-scroll
|
||||
case Clutter.EventType.ENTER:
|
||||
case Clutter.EventType.LEAVE:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
_getDesktopClone: function() {
|
||||
let windows = global.get_window_actors().filter(function(w) {
|
||||
return w.meta_window.get_window_type() == Meta.WindowType.DESKTOP;
|
||||
@ -350,6 +505,9 @@ Overview.prototype = {
|
||||
this._modal = true;
|
||||
this._animateVisible();
|
||||
this._shown = true;
|
||||
|
||||
this._buttonPressId = this._group.connect('button-press-event',
|
||||
Lang.bind(this, this._onButtonPress));
|
||||
},
|
||||
|
||||
_animateVisible: function() {
|
||||
@ -417,6 +575,7 @@ Overview.prototype = {
|
||||
});
|
||||
|
||||
this._coverPane.raise_top();
|
||||
this._coverPane.show();
|
||||
this.emit('showing');
|
||||
},
|
||||
|
||||
@ -447,6 +606,10 @@ Overview.prototype = {
|
||||
|
||||
this._shown = false;
|
||||
this._syncInputMode();
|
||||
|
||||
if (this._buttonPressId > 0)
|
||||
this._group.disconnect(this._buttonPressId);
|
||||
this._buttonPressId = 0;
|
||||
},
|
||||
|
||||
// hideTemporarily:
|
||||
@ -556,13 +719,14 @@ Overview.prototype = {
|
||||
});
|
||||
|
||||
this._coverPane.raise_top();
|
||||
this._coverPane.show();
|
||||
this.emit('hiding');
|
||||
},
|
||||
|
||||
_showDone: function() {
|
||||
this.animationInProgress = false;
|
||||
this._desktopFade.hide();
|
||||
this._coverPane.lower_bottom();
|
||||
this._coverPane.hide();
|
||||
|
||||
this.emit('shown');
|
||||
// Handle any calls to hide* while we were showing
|
||||
@ -590,7 +754,7 @@ Overview.prototype = {
|
||||
this.animationInProgress = false;
|
||||
this._hideInProgress = false;
|
||||
|
||||
this._coverPane.lower_bottom();
|
||||
this._coverPane.hide();
|
||||
|
||||
this.emit('hidden');
|
||||
// Handle any calls to show* while we were hiding
|
||||
|
141
js/ui/panel.js
141
js/ui/panel.js
@ -17,6 +17,7 @@ const Overview = imports.ui.overview;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const StatusMenu = imports.ui.statusMenu;
|
||||
const DateMenu = imports.ui.dateMenu;
|
||||
const Main = imports.ui.main;
|
||||
const Tweener = imports.ui.tweener;
|
||||
|
||||
@ -36,7 +37,8 @@ const STANDARD_TRAY_ICON_ORDER = ['a11y', 'display', 'keyboard', 'volume', 'blue
|
||||
const STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION = {
|
||||
'a11y': imports.ui.status.accessibility.ATIndicator,
|
||||
'volume': imports.ui.status.volume.Indicator,
|
||||
'battery': imports.ui.status.power.Indicator
|
||||
'battery': imports.ui.status.power.Indicator,
|
||||
'keyboard': imports.ui.status.keyboard.XKBIndicator
|
||||
};
|
||||
|
||||
if (Config.HAVE_BLUETOOTH)
|
||||
@ -491,121 +493,6 @@ AppMenuButton.prototype = {
|
||||
|
||||
Signals.addSignalMethods(AppMenuButton.prototype);
|
||||
|
||||
function ClockButton() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
ClockButton.prototype = {
|
||||
_init: function() {
|
||||
this.actor = new St.Bin({ style_class: 'panel-button',
|
||||
reactive: true,
|
||||
can_focus: true,
|
||||
x_fill: true,
|
||||
y_fill: false,
|
||||
track_hover: true });
|
||||
this.actor._delegate = this;
|
||||
this.actor.connect('button-press-event',
|
||||
Lang.bind(this, this._toggleCalendar));
|
||||
|
||||
this._clock = new St.Label();
|
||||
this.actor.set_child(this._clock);
|
||||
|
||||
this._calendarPopup = null;
|
||||
|
||||
this._desktopSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
|
||||
this._clockSettings = new Gio.Settings({ schema: 'org.gnome.shell.clock' });
|
||||
|
||||
this._desktopSettings.connect('changed', Lang.bind(this, this._updateClock));
|
||||
this._clockSettings.connect('changed', Lang.bind(this, this._updateClock));
|
||||
|
||||
// Start the clock
|
||||
this._updateClock();
|
||||
},
|
||||
|
||||
closeCalendar: function() {
|
||||
if (!this._calendarPopup || !this._calendarPopup.isOpen)
|
||||
return;
|
||||
|
||||
this._calendarPopup.hide();
|
||||
|
||||
this.actor.remove_style_pseudo_class('pressed');
|
||||
},
|
||||
|
||||
openCalendar: function() {
|
||||
this._calendarPopup.show();
|
||||
|
||||
this.actor.add_style_pseudo_class('pressed');
|
||||
},
|
||||
|
||||
_toggleCalendar: function() {
|
||||
if (this._calendarPopup == null) {
|
||||
this._calendarPopup = new CalendarPopup();
|
||||
this._calendarPopup.actor.hide();
|
||||
}
|
||||
|
||||
if (!this._calendarPopup.isOpen)
|
||||
this.openCalendar();
|
||||
else
|
||||
this.closeCalendar();
|
||||
},
|
||||
|
||||
_updateClock: function() {
|
||||
let format = this._desktopSettings.get_string(CLOCK_FORMAT_KEY);
|
||||
let showDate = this._clockSettings.get_boolean(CLOCK_SHOW_DATE_KEY);
|
||||
let showSeconds = this._clockSettings.get_boolean(CLOCK_SHOW_SECONDS_KEY);
|
||||
|
||||
let clockFormat;
|
||||
switch (format) {
|
||||
case '24h':
|
||||
if (showDate)
|
||||
/* Translators: This is the time format with date used
|
||||
in 24-hour mode. */
|
||||
clockFormat = showSeconds ? _("%a %b %e, %R:%S")
|
||||
: _("%a %b %e, %R");
|
||||
else
|
||||
/* Translators: This is the time format without date used
|
||||
in 24-hour mode. */
|
||||
clockFormat = showSeconds ? _("%a %R:%S")
|
||||
: _("%a %R");
|
||||
break;
|
||||
case '12h':
|
||||
default:
|
||||
if (showDate)
|
||||
/* Translators: This is a time format with date used
|
||||
for AM/PM. */
|
||||
clockFormat = showSeconds ? _("%a %b %e, %l:%M:%S %p")
|
||||
: _("%a %b %e, %l:%M %p");
|
||||
else
|
||||
/* Translators: This is a time format without date used
|
||||
for AM/PM. */
|
||||
clockFormat = showSeconds ? _("%a %l:%M:%S %p")
|
||||
: _("%a %l:%M %p");
|
||||
break;
|
||||
}
|
||||
|
||||
let displayDate = new Date();
|
||||
let msecRemaining;
|
||||
if (showSeconds) {
|
||||
msecRemaining = 1000 - displayDate.getMilliseconds();
|
||||
if (msecRemaining < 50) {
|
||||
displayDate.setSeconds(displayDate.getSeconds() + 1);
|
||||
msecRemaining += 1000;
|
||||
}
|
||||
} else {
|
||||
msecRemaining = 60000 - (1000 * displayDate.getSeconds() +
|
||||
displayDate.getMilliseconds());
|
||||
if (msecRemaining < 500) {
|
||||
displayDate.setMinutes(displayDate.getMinutes() + 1);
|
||||
msecRemaining += 60000;
|
||||
}
|
||||
}
|
||||
|
||||
this._clock.set_text(displayDate.toLocaleFormat(clockFormat));
|
||||
Mainloop.timeout_add(msecRemaining, Lang.bind(this, this._updateClock));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
function Panel() {
|
||||
this._init();
|
||||
}
|
||||
@ -802,23 +689,21 @@ Panel.prototype = {
|
||||
this._menus.addMenu(appMenuButton.menu);
|
||||
|
||||
/* center */
|
||||
|
||||
this._clockButton = new ClockButton();
|
||||
this._centerBox.add(this._clockButton.actor, { y_fill: true });
|
||||
this._dateMenu = new DateMenu.DateMenuButton();
|
||||
this._centerBox.add(this._dateMenu.actor, { y_fill: true });
|
||||
this._menus.addMenu(this._dateMenu.menu);
|
||||
|
||||
/* right */
|
||||
|
||||
// System status applets live in statusBox, while legacy tray icons
|
||||
// live in trayBox
|
||||
// The trayBox is hidden when there are no tray icons.
|
||||
let statusBox = new St.BoxLayout({ name: 'statusTray' });
|
||||
let trayBox = new St.BoxLayout({ name: 'legacyTray' });
|
||||
this._trayBox = trayBox;
|
||||
this._statusBox = statusBox;
|
||||
this._trayBox = new St.BoxLayout({ name: 'legacyTray' });
|
||||
this._statusBox = new St.BoxLayout({ name: 'statusTray' });
|
||||
|
||||
trayBox.hide();
|
||||
this._rightBox.add(trayBox);
|
||||
this._rightBox.add(statusBox);
|
||||
this._trayBox.hide();
|
||||
this._rightBox.add(this._trayBox);
|
||||
this._rightBox.add(this._statusBox);
|
||||
|
||||
Main.statusIconDispatcher.connect('status-icon-added', Lang.bind(this, this._onTrayIconAdded));
|
||||
Main.statusIconDispatcher.connect('status-icon-removed', Lang.bind(this, this._onTrayIconRemoved));
|
||||
@ -885,10 +770,6 @@ Panel.prototype = {
|
||||
this._rightBox.add(this._statusmenu.actor);
|
||||
},
|
||||
|
||||
hideCalendar: function() {
|
||||
this._clockButton.closeCalendar();
|
||||
},
|
||||
|
||||
startupAnimation: function() {
|
||||
this.actor.y = -this.actor.height;
|
||||
Tweener.addTween(this.actor,
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const GConf = imports.gi.GConf;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Shell = imports.gi.Shell;
|
||||
@ -13,12 +12,9 @@ const _ = Gettext.gettext;
|
||||
|
||||
const DND = imports.ui.dnd;
|
||||
const Main = imports.ui.main;
|
||||
const Params = imports.misc.params;
|
||||
const Search = imports.ui.search;
|
||||
|
||||
const NAUTILUS_PREFS_DIR = '/apps/nautilus/preferences';
|
||||
const DESKTOP_IS_HOME_KEY = NAUTILUS_PREFS_DIR + '/desktop_is_home_dir';
|
||||
|
||||
const PLACES_ICON_SIZE = 16;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
/**
|
||||
* Represents a place object, which is most normally a bookmark entry,
|
||||
@ -63,6 +59,21 @@ PlaceInfo.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
// Helper function to translate launch parameters into a GAppLaunchContext
|
||||
function _makeLaunchContext(params)
|
||||
{
|
||||
params = Params.parse(params, { workspace: null,
|
||||
timestamp: null });
|
||||
|
||||
let launchContext = global.create_app_launch_context();
|
||||
if (params.workspace != null)
|
||||
launchContext.set_desktop(params.workspace.index());
|
||||
if (params.timestamp != null)
|
||||
launchContext.set_timestamp(params.timestamp);
|
||||
|
||||
return launchContext;
|
||||
}
|
||||
|
||||
function PlaceDeviceInfo(mount) {
|
||||
this._init(mount);
|
||||
}
|
||||
@ -82,9 +93,9 @@ PlaceDeviceInfo.prototype = {
|
||||
return St.TextureCache.get_default().load_gicon(null, icon, size);
|
||||
},
|
||||
|
||||
launch: function() {
|
||||
launch: function(param) {
|
||||
Gio.app_info_launch_default_for_uri(this._mount.get_root().get_uri(),
|
||||
global.create_app_launch_context());
|
||||
_makeLaunchContex(params));
|
||||
},
|
||||
|
||||
isRemovable: function() {
|
||||
@ -116,20 +127,15 @@ PlaceDeviceInfo.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function PlacesManager() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
PlacesManager.prototype = {
|
||||
_init: function() {
|
||||
let gconf = GConf.Client.get_default();
|
||||
gconf.add_dir(NAUTILUS_PREFS_DIR, GConf.ClientPreloadType.PRELOAD_NONE);
|
||||
|
||||
this._defaultPlaces = [];
|
||||
this._mounts = [];
|
||||
this._bookmarks = [];
|
||||
this._isDesktopHome = gconf.get_bool(DESKTOP_IS_HOME_KEY);
|
||||
|
||||
let homeFile = Gio.file_new_for_path (GLib.get_home_dir());
|
||||
let homeUri = homeFile.get_uri();
|
||||
@ -139,8 +145,8 @@ PlacesManager.prototype = {
|
||||
function(size) {
|
||||
return St.TextureCache.get_default().load_gicon(null, homeIcon, size);
|
||||
},
|
||||
function() {
|
||||
Gio.app_info_launch_default_for_uri(homeUri, global.create_app_launch_context());
|
||||
function(params) {
|
||||
Gio.app_info_launch_default_for_uri(homeUri, _makeLaunchContext(params));
|
||||
});
|
||||
|
||||
let desktopPath = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP);
|
||||
@ -152,8 +158,8 @@ PlacesManager.prototype = {
|
||||
function(size) {
|
||||
return St.TextureCache.get_default().load_gicon(null, desktopIcon, size);
|
||||
},
|
||||
function() {
|
||||
Gio.app_info_launch_default_for_uri(desktopUri, global.create_app_launch_context());
|
||||
function(params) {
|
||||
Gio.app_info_launch_default_for_uri(desktopUri, _makeLaunchContext(params));
|
||||
});
|
||||
|
||||
this._connect = new PlaceInfo('special:connect', _("Connect to..."),
|
||||
@ -162,8 +168,12 @@ PlacesManager.prototype = {
|
||||
icon_type: St.IconType.FULLCOLOR,
|
||||
icon_size: size });
|
||||
},
|
||||
function () {
|
||||
new Shell.Process({ args: ['nautilus-connect-server'] }).run();
|
||||
function (params) {
|
||||
// BUG: nautilus-connect-server doesn't have a desktop file, so we can'
|
||||
// launch it with the workspace from params. It's probably pretty rare
|
||||
// and odd to drag this place onto a workspace in any case
|
||||
|
||||
Util.spawn(['nautilus-connect-server']);
|
||||
});
|
||||
|
||||
let networkApp = null;
|
||||
@ -182,16 +192,17 @@ PlacesManager.prototype = {
|
||||
function(size) {
|
||||
return networkApp.create_icon_texture(size);
|
||||
},
|
||||
function () {
|
||||
networkApp.launch();
|
||||
function (params) {
|
||||
params = Params.parse(params, { workspace: null,
|
||||
timestamp: 0 });
|
||||
|
||||
networkApp.launch_full(params.timestamp, [],
|
||||
params.workspace ? params.workspace.index() : -1);
|
||||
});
|
||||
}
|
||||
|
||||
this._defaultPlaces.push(this._home);
|
||||
|
||||
this._desktopMenuIndex = this._defaultPlaces.length;
|
||||
if (!this._isDesktopHome)
|
||||
this._defaultPlaces.push(this._desktopMenu);
|
||||
this._defaultPlaces.push(this._desktopMenu);
|
||||
|
||||
if (this._network)
|
||||
this._defaultPlaces.push(this._network);
|
||||
@ -229,9 +240,6 @@ PlacesManager.prototype = {
|
||||
}));
|
||||
|
||||
this._reloadBookmarks();
|
||||
|
||||
gconf.notify_add(DESKTOP_IS_HOME_KEY, Lang.bind(this, this._updateDesktopMenuVisibility));
|
||||
|
||||
},
|
||||
|
||||
_updateDevices: function() {
|
||||
@ -329,8 +337,8 @@ PlacesManager.prototype = {
|
||||
function(size) {
|
||||
return St.TextureCache.get_default().load_gicon(null, icon, size);
|
||||
},
|
||||
function() {
|
||||
Gio.app_info_launch_default_for_uri(bookmark, global.create_app_launch_context());
|
||||
function(params) {
|
||||
Gio.app_info_launch_default_for_uri(bookmark, _makeLaunchContext(params));
|
||||
});
|
||||
this._bookmarks.push(item);
|
||||
}
|
||||
@ -340,21 +348,6 @@ PlacesManager.prototype = {
|
||||
this.emit('places-updated');
|
||||
},
|
||||
|
||||
_updateDesktopMenuVisibility: function() {
|
||||
let gconf = GConf.Client.get_default();
|
||||
this._isDesktopHome = gconf.get_boolean(DESKTOP_IS_HOME_KEY);
|
||||
|
||||
if (this._isDesktopHome)
|
||||
this._removeById(this._defaultPlaces, 'special:desktop');
|
||||
else
|
||||
this._defaultPlaces.splice(this._desktopMenuIndex, 0,
|
||||
this._desktopMenu);
|
||||
|
||||
/* See comment in _updateDevices for explanation why there are two signals. */
|
||||
this.emit('defaults-updated');
|
||||
this.emit('places-updated');
|
||||
},
|
||||
|
||||
_addMount: function(mount) {
|
||||
let devItem = new PlaceDeviceInfo(mount);
|
||||
this._mounts.push(devItem);
|
||||
@ -402,150 +395,8 @@ PlacesManager.prototype = {
|
||||
sourceArray.splice(this._lookupIndexById(sourceArray, id), 1);
|
||||
}
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(PlacesManager.prototype);
|
||||
|
||||
/**
|
||||
* An entry in the places menu.
|
||||
* @info The corresponding PlaceInfo to populate this entry.
|
||||
*/
|
||||
function DashPlaceDisplayItem(info) {
|
||||
this._init(info);
|
||||
}
|
||||
|
||||
DashPlaceDisplayItem.prototype = {
|
||||
_init: function(info) {
|
||||
this.name = info.name;
|
||||
this._info = info;
|
||||
this._icon = info.iconFactory(PLACES_ICON_SIZE);
|
||||
|
||||
this.actor = new St.Clickable({ style_class: 'places-item',
|
||||
reactive: true,
|
||||
x_align: St.Align.START,
|
||||
x_fill: true });
|
||||
|
||||
let box = new St.BoxLayout({ style_class: 'places-item-box' });
|
||||
this.actor.set_child(box);
|
||||
|
||||
let bin = new St.Bin({ child: this._icon });
|
||||
box.add(bin);
|
||||
|
||||
let text = new St.Label({ text: info.name });
|
||||
box.add(text, { expand: true, x_fill: true });
|
||||
|
||||
if (info.isRemovable()) {
|
||||
let removeIcon = new St.Icon({ icon_name: 'media-eject',
|
||||
icon_type: St.IconType.FULLCOLOR,
|
||||
icon_size: PLACES_ICON_SIZE });
|
||||
let removeIconBox = new St.Clickable({ child: removeIcon,
|
||||
reactive: true });
|
||||
box.add(removeIconBox);
|
||||
removeIconBox.connect('clicked',
|
||||
Lang.bind(this, function() {
|
||||
this._info.remove();
|
||||
}));
|
||||
}
|
||||
|
||||
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
|
||||
|
||||
this.actor._delegate = this;
|
||||
this._draggable = DND.makeDraggable(this.actor);
|
||||
this._draggable.connect('drag-begin',
|
||||
Lang.bind(this, function() {
|
||||
Main.overview.beginItemDrag(this);
|
||||
}));
|
||||
this._draggable.connect('drag-end',
|
||||
Lang.bind(this, function() {
|
||||
Main.overview.endItemDrag(this);
|
||||
}));
|
||||
},
|
||||
|
||||
_onClicked: function(b) {
|
||||
this._info.launch();
|
||||
Main.overview.hide();
|
||||
},
|
||||
|
||||
getDragActorSource: function() {
|
||||
return this._icon;
|
||||
},
|
||||
|
||||
getDragActor: function(stageX, stageY) {
|
||||
return this._info.iconFactory(PLACES_ICON_SIZE);
|
||||
},
|
||||
|
||||
//// Drag and drop methods ////
|
||||
|
||||
shellWorkspaceLaunch: function() {
|
||||
this._info.launch();
|
||||
}
|
||||
};
|
||||
|
||||
function DashPlaceDisplay() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
DashPlaceDisplay.prototype = {
|
||||
_init: function() {
|
||||
|
||||
// Places is divided semi-arbitrarily into left and right; a grid would
|
||||
// look better in that there would be an even number of items left+right,
|
||||
// but it seems like we want some sort of differentiation between actions
|
||||
// like "Connect to server..." and regular folders
|
||||
this.actor = new St.Table({ style_class: 'places-section',
|
||||
homogeneous: true });
|
||||
|
||||
this._defaultsList = [];
|
||||
this._bookmarksList = [];
|
||||
this._mountsList = [];
|
||||
|
||||
Main.placesManager.connect('defaults-updated', Lang.bind(this, this._updateDefaults));
|
||||
Main.placesManager.connect('bookmarks-updated', Lang.bind(this, this._updateBookmarks));
|
||||
Main.placesManager.connect('mounts-updated', Lang.bind(this, this._updateMounts));
|
||||
|
||||
this._updateDefaults();
|
||||
this._updateMounts();
|
||||
this._updateBookmarks();
|
||||
},
|
||||
|
||||
_updateDefaults: function() {
|
||||
for (let i = 0; i < this._defaultsList.length; i++)
|
||||
this._defaultsList[i].destroy();
|
||||
|
||||
this._defaultsList = [];
|
||||
let places = Main.placesManager.getDefaultPlaces();
|
||||
for (let i = 0; i < places.length; i++) {
|
||||
this._defaultsList[i] = new DashPlaceDisplayItem(places[i]).actor;
|
||||
this.actor.add(this._defaultsList[i], {row: i, col: 0});
|
||||
}
|
||||
this._updateMounts();
|
||||
},
|
||||
|
||||
_updateMounts: function() {
|
||||
for (let i = 0; i < this._mountsList.length; i++)
|
||||
this._mountsList[i].destroy();
|
||||
|
||||
this._mountsList = [];
|
||||
let places = Main.placesManager.getMounts();
|
||||
for (let i = 0; i < places.length; i++) {
|
||||
this._mountsList[i] = new DashPlaceDisplayItem(places[i]).actor;
|
||||
this.actor.add(this._mountsList[i], {row: this._defaultsList.length + i, col: 0});
|
||||
}
|
||||
},
|
||||
|
||||
_updateBookmarks: function() {
|
||||
for (let i = 0; i < this._bookmarksList.length; i++)
|
||||
this._bookmarksList[i].destroy();
|
||||
|
||||
this._bookmarksList = [];
|
||||
let places = Main.placesManager.getBookmarks();
|
||||
for (let i = 0; i < places.length; i ++) {
|
||||
this._bookmarksList[i] = new DashPlaceDisplayItem(places[i]).actor;
|
||||
this.actor.add(this._bookmarksList[i], {row: i, col: 1});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(DashPlaceDisplay.prototype);
|
||||
|
||||
function PlaceSearchProvider() {
|
||||
this._init();
|
||||
@ -567,9 +418,9 @@ PlaceSearchProvider.prototype = {
|
||||
'icon': placeInfo.iconFactory(Search.RESULT_ICON_SIZE) };
|
||||
},
|
||||
|
||||
activateResult: function(id) {
|
||||
activateResult: function(id, params) {
|
||||
let placeInfo = Main.placesManager.lookupPlaceById(id);
|
||||
placeInfo.launch();
|
||||
placeInfo.launch(params);
|
||||
},
|
||||
|
||||
_compareResultMeta: function (idA, idB) {
|
||||
|
@ -11,16 +11,18 @@ const Signals = imports.signals;
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const Lightbox = imports.ui.lightbox;
|
||||
const FileUtils = imports.misc.fileUtils;
|
||||
const Main = imports.ui.main;
|
||||
const ModalDialog = imports.ui.modalDialog;
|
||||
const Tweener = imports.ui.tweener;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const MAX_FILE_DELETED_BEFORE_INVALID = 10;
|
||||
|
||||
const HISTORY_KEY = 'command-history';
|
||||
const HISTORY_LIMIT = 512;
|
||||
|
||||
const DIALOG_FADE_TIME = 0.1;
|
||||
const DIALOG_GROW_TIME = 0.1;
|
||||
|
||||
function CommandCompleter() {
|
||||
this._init();
|
||||
@ -62,25 +64,6 @@ CommandCompleter.prototype = {
|
||||
this._update(0);
|
||||
},
|
||||
|
||||
_onGetEnumerateComplete : function(obj, res) {
|
||||
this._enumerator = obj.enumerate_children_finish(res);
|
||||
this._enumerator.next_files_async(100, GLib.PRIORITY_LOW, null, Lang.bind(this, this._onNextFileComplete));
|
||||
},
|
||||
|
||||
_onNextFileComplete : function(obj, res) {
|
||||
let files = obj.next_files_finish(res);
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
this._childs[this._i].push(files[i].get_name());
|
||||
}
|
||||
if (files.length) {
|
||||
this._enumerator.next_files_async(100, GLib.PRIORITY_LOW, null, Lang.bind(this, this._onNextFileComplete));
|
||||
} else {
|
||||
this._enumerator.close(null);
|
||||
this._enumerator = null;
|
||||
this._update(this._i + 1);
|
||||
}
|
||||
},
|
||||
|
||||
update : function() {
|
||||
if (this._valid)
|
||||
return;
|
||||
@ -100,7 +83,12 @@ CommandCompleter.prototype = {
|
||||
}
|
||||
let file = Gio.file_new_for_path(this._paths[i]);
|
||||
this._childs[this._i] = [];
|
||||
file.enumerate_children_async(Gio.FILE_ATTRIBUTE_STANDARD_NAME, Gio.FileQueryInfoFlags.NONE, GLib.PRIORITY_LOW, null, Lang.bind(this, this._onGetEnumerateComplete));
|
||||
FileUtils.listDirAsync(file, Lang.bind(this, function (files) {
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
this._childs[this._i].push(files[i].get_name());
|
||||
}
|
||||
this._update(this._i + 1);
|
||||
}));
|
||||
},
|
||||
|
||||
_onChanged : function(m, f, of, type) {
|
||||
@ -175,8 +163,9 @@ function RunDialog() {
|
||||
}
|
||||
|
||||
RunDialog.prototype = {
|
||||
__proto__: ModalDialog.ModalDialog.prototype,
|
||||
_init : function() {
|
||||
this._isOpen = false;
|
||||
ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'run-dialog' });
|
||||
|
||||
global.settings.connect('changed::development-tools', Lang.bind(this, function () {
|
||||
this._enableInternalCommands = global.settings.get_boolean('development-tools');
|
||||
@ -215,49 +204,37 @@ RunDialog.prototype = {
|
||||
})
|
||||
};
|
||||
|
||||
// All actors are inside _group. We create it initially
|
||||
// hidden then show it in show()
|
||||
this._group = new Clutter.Group({ visible: false,
|
||||
x: 0, y: 0 });
|
||||
Main.uiGroup.add_actor(this._group);
|
||||
|
||||
this._lightbox = new Lightbox.Lightbox(this._group,
|
||||
{ inhibitEvents: true });
|
||||
|
||||
this._box = new St.Bin({ x_align: St.Align.MIDDLE,
|
||||
y_align: St.Align.MIDDLE });
|
||||
|
||||
this._group.add_actor(this._box);
|
||||
this._lightbox.highlight(this._box);
|
||||
|
||||
let dialogBox = new St.BoxLayout({ style_class: 'run-dialog', vertical: true });
|
||||
|
||||
this._box.set_child(dialogBox);
|
||||
|
||||
let label = new St.Label({ style_class: 'run-dialog-label',
|
||||
text: _("Please enter a command:") });
|
||||
|
||||
dialogBox.add(label, { expand: true, y_fill: false });
|
||||
this.contentLayout.add(label, { y_align: St.Align.START });
|
||||
|
||||
let entry = new St.Entry({ style_class: 'run-dialog-entry' });
|
||||
|
||||
this._entryText = entry.clutter_text;
|
||||
dialogBox.add(entry, { expand: true });
|
||||
this.contentLayout.add(entry, { y_align: St.Align.START });
|
||||
this.connect('opened',
|
||||
Lang.bind(this, function() {
|
||||
this._entryText.grab_key_focus();
|
||||
}));
|
||||
|
||||
this._errorBox = new St.BoxLayout();
|
||||
this._errorBox = new St.BoxLayout({ style_class: 'run-dialog-error-box' });
|
||||
|
||||
dialogBox.add(this._errorBox, { expand: true });
|
||||
this.contentLayout.add(this._errorBox, { expand: true });
|
||||
|
||||
let errorIcon = new St.Button({ style_class: 'run-dialog-error-icon' });
|
||||
let errorIcon = new St.Icon({ icon_name: 'dialog-error', icon_size: 24, style_class: 'run-dialog-error-icon' });
|
||||
|
||||
this._errorBox.add(errorIcon);
|
||||
this._errorBox.add(errorIcon, { y_align: St.Align.MIDDLE });
|
||||
|
||||
this._commandError = false;
|
||||
|
||||
this._errorMessage = new St.Label({ style_class: 'run-dialog-error-label' });
|
||||
this._errorMessage.clutter_text.line_wrap = true;
|
||||
|
||||
this._errorBox.add(this._errorMessage, { expand: true });
|
||||
this._errorBox.add(this._errorMessage, { expand: true,
|
||||
y_align: St.Align.MIDDLE,
|
||||
y_fill: false });
|
||||
|
||||
this._errorBox.hide();
|
||||
|
||||
@ -280,10 +257,10 @@ RunDialog.prototype = {
|
||||
else
|
||||
this._run(o.get_text(), false);
|
||||
if (!this._commandError)
|
||||
this.close();
|
||||
this.close(global.get_current_time());
|
||||
}
|
||||
if (symbol == Clutter.Escape) {
|
||||
this.close();
|
||||
this.close(global.get_current_time());
|
||||
return true;
|
||||
}
|
||||
if (symbol == Clutter.slash) {
|
||||
@ -354,9 +331,7 @@ RunDialog.prototype = {
|
||||
try {
|
||||
if (inTerminal)
|
||||
command = 'gnome-terminal -x ' + input;
|
||||
let [ok, len, args] = GLib.shell_parse_argv(command);
|
||||
let p = new Shell.Process({ 'args' : args });
|
||||
p.run();
|
||||
Util.trySpawnCommandLine(command);
|
||||
} catch (e) {
|
||||
// Mmmh, that failed - see if @input matches an existing file
|
||||
let path = null;
|
||||
@ -374,16 +349,24 @@ RunDialog.prototype = {
|
||||
global.create_app_launch_context());
|
||||
} else {
|
||||
this._commandError = true;
|
||||
// The exception contains an error string like:
|
||||
// Error invoking Shell.run: Failed to execute child
|
||||
// process "foo" (No such file or directory)
|
||||
// We are only interested in the actual error, so parse
|
||||
//that out.
|
||||
let m = /.+\((.+)\)/.exec(e);
|
||||
let errorStr = _("Execution of '%s' failed:").format(command) + '\n' + m[1];
|
||||
this._errorMessage.set_text(errorStr);
|
||||
|
||||
this._errorBox.show();
|
||||
this._errorMessage.set_text(e.message);
|
||||
|
||||
if (!this._errorBox.visible) {
|
||||
let [errorBoxMinHeight, errorBoxNaturalHeight] = this._errorBox.get_preferred_height(-1);
|
||||
|
||||
let parentActor = this._errorBox.get_parent();
|
||||
Tweener.addTween(parentActor,
|
||||
{ height: parentActor.height + errorBoxNaturalHeight,
|
||||
time: DIALOG_GROW_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this,
|
||||
function() {
|
||||
parentActor.set_height(-1);
|
||||
this._errorBox.show();
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -405,53 +388,14 @@ RunDialog.prototype = {
|
||||
this._entryText.set_text('');
|
||||
},
|
||||
|
||||
open : function() {
|
||||
if (this._isOpen) // Already shown
|
||||
return;
|
||||
|
||||
if (!Main.pushModal(this._group))
|
||||
return;
|
||||
|
||||
// Position the dialog on the current monitor
|
||||
let monitor = global.get_focus_monitor();
|
||||
|
||||
open: function() {
|
||||
this._historyIndex = this._history.length;
|
||||
|
||||
this._box.set_position(monitor.x, monitor.y);
|
||||
this._box.set_size(monitor.width, monitor.height);
|
||||
|
||||
this._isOpen = true;
|
||||
this._lightbox.show();
|
||||
this._group.opacity = 0;
|
||||
this._group.show();
|
||||
Tweener.addTween(this._group,
|
||||
{ opacity: 255,
|
||||
time: DIALOG_FADE_TIME,
|
||||
transition: 'easeOutQuad'
|
||||
});
|
||||
|
||||
global.stage.set_key_focus(this._entryText);
|
||||
},
|
||||
|
||||
close : function() {
|
||||
if (!this._isOpen)
|
||||
return;
|
||||
|
||||
this._isOpen = false;
|
||||
this._errorBox.hide();
|
||||
this._entryText.set_text('');
|
||||
this._commandError = false;
|
||||
|
||||
Main.popModal(this._group);
|
||||
ModalDialog.ModalDialog.prototype.open.call(this);
|
||||
},
|
||||
|
||||
Tweener.addTween(this._group,
|
||||
{ opacity: 0,
|
||||
time: DIALOG_FADE_TIME,
|
||||
transition: 'easeOutQuad',
|
||||
onComplete: Lang.bind(this, function() {
|
||||
this._errorBox.hide();
|
||||
this._group.hide();
|
||||
this._entryText.set_text('');
|
||||
})
|
||||
});
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(RunDialog.prototype);
|
||||
|
114
js/ui/search.js
114
js/ui/search.js
@ -1,6 +1,19 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Signals = imports.signals;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const FileUtils = imports.misc.fileUtils;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
const DISABLED_OPEN_SEARCH_PROVIDERS_KEY = 'disabled-open-search-providers';
|
||||
|
||||
const RESULT_ICON_SIZE = 48;
|
||||
|
||||
@ -211,6 +224,107 @@ SearchProvider.prototype = {
|
||||
};
|
||||
Signals.addSignalMethods(SearchProvider.prototype);
|
||||
|
||||
function OpenSearchSystem() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
OpenSearchSystem.prototype = {
|
||||
_init: function() {
|
||||
this._providers = [];
|
||||
global.settings.connect('changed::' + DISABLED_OPEN_SEARCH_PROVIDERS_KEY, Lang.bind(this, this._refresh));
|
||||
this._refresh();
|
||||
},
|
||||
|
||||
getProviders: function() {
|
||||
let res = [];
|
||||
for (let i = 0; i < this._providers.length; i++)
|
||||
res.push({ id: i, name: this._providers[i].name });
|
||||
|
||||
return res;
|
||||
},
|
||||
|
||||
setSearchTerms: function(terms) {
|
||||
this._terms = terms;
|
||||
},
|
||||
|
||||
_checkSupportedProviderLanguage: function(provider) {
|
||||
if (provider.url.search(/{language}/) == -1)
|
||||
return true;
|
||||
|
||||
let langs = GLib.get_language_names();
|
||||
|
||||
langs.push('en');
|
||||
let lang = null;
|
||||
for (let i = 0; i < langs.length; i++) {
|
||||
for (let k = 0; k < provider.langs.length; k++) {
|
||||
if (langs[i] == provider.langs[k])
|
||||
lang = langs[i];
|
||||
}
|
||||
if (lang)
|
||||
break;
|
||||
}
|
||||
provider.lang = lang;
|
||||
return lang != null;
|
||||
},
|
||||
|
||||
activateResult: function(id, params) {
|
||||
let searchTerms = this._terms.join(' ');
|
||||
|
||||
let url = this._providers[id].url.replace('{searchTerms}', encodeURIComponent(searchTerms));
|
||||
if (url.match('{language}'))
|
||||
url = url.replace('{language}', this._providers[id].lang);
|
||||
|
||||
try {
|
||||
Gio.app_info_launch_default_for_uri(url, global.create_app_launch_context());
|
||||
} catch (e) {
|
||||
// TODO: remove this after glib will be removed from moduleset
|
||||
// In the default jhbuild, gio is in our prefix but gvfs is not
|
||||
Util.spawn(['gvfs-open', url])
|
||||
}
|
||||
|
||||
Main.overview.hide();
|
||||
},
|
||||
|
||||
_addProvider: function(fileName) {
|
||||
let file = Gio.file_new_for_path(global.datadir + '/search_providers/' + fileName);
|
||||
let source = '';
|
||||
|
||||
file.load_contents_async(null, Lang.bind(this, function (obj, res) {
|
||||
let [success, source] = file.load_contents_finish(res);
|
||||
if (source) {
|
||||
let [success, name, url, langs, icon_uri] = global.parse_search_provider(source);
|
||||
let provider ={ name: name,
|
||||
url: url,
|
||||
id: this._providers.length,
|
||||
icon_uri: icon_uri,
|
||||
langs: langs };
|
||||
if (this._checkSupportedProviderLanguage(provider)) {
|
||||
this._providers.push(provider);
|
||||
this.emit('changed');
|
||||
}
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
_refresh: function() {
|
||||
this._providers = [];
|
||||
let names = global.settings.get_strv(DISABLED_OPEN_SEARCH_PROVIDERS_KEY);
|
||||
let file = Gio.file_new_for_path(global.datadir + '/search_providers');
|
||||
FileUtils.listDirAsync(file, Lang.bind(this, function(files) {
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
let enabled = true;
|
||||
let name = files[i].get_name();
|
||||
for (let k = 0; k < names.length; k++)
|
||||
if (names[k] == name)
|
||||
enabled = false;
|
||||
if (enabled)
|
||||
this._addProvider(name);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
Signals.addSignalMethods(OpenSearchSystem.prototype);
|
||||
|
||||
function SearchSystem() {
|
||||
this._init();
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ const St = imports.gi.St;
|
||||
const DND = imports.ui.dnd;
|
||||
const IconGrid = imports.ui.iconGrid;
|
||||
const Main = imports.ui.main;
|
||||
const Overview = imports.ui.overview;
|
||||
const Search = imports.ui.search;
|
||||
|
||||
const MAX_SEARCH_RESULTS_ROWS = 2;
|
||||
@ -80,11 +81,11 @@ SearchResult.prototype = {
|
||||
return new Clutter.Clone({ source: this.metaInfo['icon'] });
|
||||
},
|
||||
|
||||
shellWorkspaceLaunch: function() {
|
||||
shellWorkspaceLaunch: function(params) {
|
||||
if (this.provider.dragActivateResult)
|
||||
this.provider.dragActivateResult(this.metaInfo.id);
|
||||
this.provider.dragActivateResult(this.metaInfo.id, params);
|
||||
else
|
||||
this.provider.activateResult(this.metaInfo.id);
|
||||
this.provider.activateResult(this.metaInfo.id, params);
|
||||
}
|
||||
};
|
||||
|
||||
@ -149,28 +150,41 @@ GridSearchResults.prototype = {
|
||||
};
|
||||
|
||||
|
||||
function SearchResults(searchSystem) {
|
||||
this._init(searchSystem);
|
||||
function SearchResults(searchSystem, openSearchSystem) {
|
||||
this._init(searchSystem, openSearchSystem);
|
||||
}
|
||||
|
||||
SearchResults.prototype = {
|
||||
_init: function(searchSystem) {
|
||||
_init: function(searchSystem, openSearchSystem) {
|
||||
this._searchSystem = searchSystem;
|
||||
this._openSearchSystem = openSearchSystem;
|
||||
|
||||
this.actor = new St.BoxLayout({ name: 'searchResults',
|
||||
vertical: true });
|
||||
|
||||
this.actor = new St.Bin({ name: 'searchResults',
|
||||
y_align: St.Align.START,
|
||||
x_align: St.Align.START,
|
||||
x_fill: true });
|
||||
this._content = new St.BoxLayout({ name: 'searchResultsContent',
|
||||
vertical: true });
|
||||
|
||||
let scrollView = new St.ScrollView({ x_fill: true,
|
||||
y_fill: false,
|
||||
vshadows: true });
|
||||
vfade: true });
|
||||
scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
||||
scrollView.add_actor(this._content);
|
||||
|
||||
this.actor.set_child(scrollView);
|
||||
this.actor.add(scrollView, { x_fill: true,
|
||||
y_fill: false,
|
||||
expand: true,
|
||||
x_align: St.Align.START,
|
||||
y_align: St.Align.START });
|
||||
this.actor.connect('notify::mapped', Lang.bind(this,
|
||||
function() {
|
||||
if (!this.actor.mapped)
|
||||
return;
|
||||
|
||||
let adjustment = scrollView.vscroll.adjustment;
|
||||
let direction = Overview.SwipeScrollDirection.VERTICAL;
|
||||
Main.overview.setScrollAdjustment(adjustment, direction);
|
||||
}));
|
||||
|
||||
this._statusText = new St.Label({ style_class: 'search-statustext' });
|
||||
this._content.add(this._statusText);
|
||||
@ -179,6 +193,51 @@ SearchResults.prototype = {
|
||||
this._providerMeta = [];
|
||||
for (let i = 0; i < this._providers.length; i++)
|
||||
this.createProviderMeta(this._providers[i]);
|
||||
|
||||
this._searchProvidersBox = new St.BoxLayout({ style_class: 'search-providers-box' });
|
||||
this.actor.add(this._searchProvidersBox);
|
||||
|
||||
this._openSearchProviders = [];
|
||||
this._openSearchSystem.connect('changed', Lang.bind(this, this._updateOpenSearchProviderButtons));
|
||||
this._updateOpenSearchProviderButtons();
|
||||
},
|
||||
|
||||
_updateOpenSearchProviderButtons: function() {
|
||||
this._selectedOpenSearchButton = -1;
|
||||
for (let i = 0; i < this._openSearchProviders.length; i++)
|
||||
this._openSearchProviders[i].actor.destroy();
|
||||
this._openSearchProviders = this._openSearchSystem.getProviders();
|
||||
for (let i = 0; i < this._openSearchProviders.length; i++)
|
||||
this._createOpenSearchProviderButton(this._openSearchProviders[i]);
|
||||
},
|
||||
|
||||
_updateOpenSearchButtonState: function() {
|
||||
for (let i = 0; i < this._openSearchProviders.length; i++) {
|
||||
if (i == this._selectedOpenSearchButton)
|
||||
this._openSearchProviders[i].actor.add_style_pseudo_class('selected');
|
||||
else
|
||||
this._openSearchProviders[i].actor.remove_style_pseudo_class('selected');
|
||||
}
|
||||
},
|
||||
|
||||
_createOpenSearchProviderButton: function(provider) {
|
||||
let clickable = new St.Clickable({ style_class: 'dash-search-button',
|
||||
reactive: true,
|
||||
x_fill: true,
|
||||
y_align: St.Align.MIDDLE });
|
||||
let bin = new St.Bin({ x_fill: false,
|
||||
x_align:St.Align.MIDDLE });
|
||||
clickable.connect('clicked', Lang.bind(this, function() {
|
||||
this._openSearchSystem.activateResult(provider.id);
|
||||
}));
|
||||
let title = new St.Label({ text: provider.name,
|
||||
style_class: 'dash-search-button-label' });
|
||||
|
||||
bin.set_child(title);
|
||||
clickable.set_child(bin);
|
||||
provider.actor = clickable;
|
||||
|
||||
this._searchProvidersBox.add(clickable);
|
||||
},
|
||||
|
||||
createProviderMeta: function(provider) {
|
||||
@ -227,6 +286,8 @@ SearchResults.prototype = {
|
||||
this._searchSystem.reset();
|
||||
this._statusText.hide();
|
||||
this._clearDisplay();
|
||||
this._selectedOpenSearchButton = -1;
|
||||
this._updateOpenSearchButtonState();
|
||||
},
|
||||
|
||||
startingSearch: function() {
|
||||
@ -247,12 +308,14 @@ SearchResults.prototype = {
|
||||
if (results.length == 0) {
|
||||
this._statusText.set_text(_("No matching results."));
|
||||
this._statusText.show();
|
||||
return true;
|
||||
} else {
|
||||
this._selectedOpenSearchButton = -1;
|
||||
this._updateOpenSearchButtonState();
|
||||
this._statusText.hide();
|
||||
}
|
||||
|
||||
let terms = this._searchSystem.getTerms();
|
||||
this._openSearchSystem.setSearchTerms(terms);
|
||||
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
let [provider, providerResults] = results[i];
|
||||
@ -262,7 +325,8 @@ SearchResults.prototype = {
|
||||
meta.count.set_text('' + providerResults.length);
|
||||
}
|
||||
|
||||
this.selectDown(false);
|
||||
if (this._selectedOpenSearchButton == -1)
|
||||
this.selectDown(false);
|
||||
|
||||
return true;
|
||||
},
|
||||
@ -284,16 +348,26 @@ SearchResults.prototype = {
|
||||
},
|
||||
|
||||
selectUp: function(recursing) {
|
||||
for (let i = this._selectedProvider; i >= 0; i--) {
|
||||
let meta = this._providerMeta[i];
|
||||
if (!meta.actor.visible)
|
||||
continue;
|
||||
let success = this._modifyActorSelection(meta.resultDisplay, true);
|
||||
if (success) {
|
||||
this._selectedProvider = i;
|
||||
return;
|
||||
if (this._selectedOpenSearchButton == -1) {
|
||||
for (let i = this._selectedProvider; i >= 0; i--) {
|
||||
let meta = this._providerMeta[i];
|
||||
if (!meta.actor.visible)
|
||||
continue;
|
||||
let success = this._modifyActorSelection(meta.resultDisplay, true);
|
||||
if (success) {
|
||||
this._selectedProvider = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this._selectedOpenSearchButton == -1)
|
||||
this._selectedOpenSearchButton = this._openSearchProviders.length;
|
||||
this._selectedOpenSearchButton--;
|
||||
this._updateOpenSearchButtonState();
|
||||
if (this._selectedOpenSearchButton >= 0)
|
||||
return;
|
||||
|
||||
if (this._providerMeta.length > 0 && !recursing) {
|
||||
this._selectedProvider = this._providerMeta.length - 1;
|
||||
this.selectUp(true);
|
||||
@ -302,18 +376,30 @@ SearchResults.prototype = {
|
||||
|
||||
selectDown: function(recursing) {
|
||||
let current = this._selectedProvider;
|
||||
if (current == -1)
|
||||
current = 0;
|
||||
for (let i = current; i < this._providerMeta.length; i++) {
|
||||
let meta = this._providerMeta[i];
|
||||
if (!meta.actor.visible)
|
||||
continue;
|
||||
let success = this._modifyActorSelection(meta.resultDisplay, false);
|
||||
if (success) {
|
||||
this._selectedProvider = i;
|
||||
return;
|
||||
if (this._selectedOpenSearchButton == -1) {
|
||||
if (current == -1)
|
||||
current = 0;
|
||||
for (let i = current; i < this._providerMeta.length; i++) {
|
||||
let meta = this._providerMeta[i];
|
||||
if (!meta.actor.visible)
|
||||
continue;
|
||||
let success = this._modifyActorSelection(meta.resultDisplay, false);
|
||||
if (success) {
|
||||
this._selectedProvider = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
this._selectedOpenSearchButton++;
|
||||
|
||||
if (this._selectedOpenSearchButton < this._openSearchProviders.length) {
|
||||
this._updateOpenSearchButtonState();
|
||||
return;
|
||||
}
|
||||
|
||||
this._selectedOpenSearchButton = -1;
|
||||
this._updateOpenSearchButtonState();
|
||||
|
||||
if (this._providerMeta.length > 0 && !recursing) {
|
||||
this._selectedProvider = 0;
|
||||
this.selectDown(true);
|
||||
@ -321,6 +407,13 @@ SearchResults.prototype = {
|
||||
},
|
||||
|
||||
activateSelected: function() {
|
||||
if (this._selectedOpenSearchButton != -1) {
|
||||
let provider = this._openSearchProviders[this._selectedOpenSearchButton];
|
||||
this._openSearchSystem.activateResult(provider.id);
|
||||
Main.overview.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
let current = this._selectedProvider;
|
||||
if (current < 0)
|
||||
return;
|
||||
|
@ -12,6 +12,7 @@ const St = imports.gi.St;
|
||||
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
@ -108,8 +109,7 @@ ATIndicator.prototype = {
|
||||
|
||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
this.menu.addAction(_("Universal Access Settings"), function() {
|
||||
let p = new Shell.Process({ args: ['gnome-control-center','universal-access'] });
|
||||
p.run();
|
||||
Util.spawnDesktop('gnome-universal-access-panel');
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -67,7 +67,8 @@ Indicator.prototype = {
|
||||
|
||||
this._fullMenuItems = [new PopupMenu.PopupSeparatorMenuItem(),
|
||||
new PopupMenu.PopupMenuItem(_("Send Files to Device...")),
|
||||
new PopupMenu.PopupMenuItem(_("Setup a New Device..."))];
|
||||
new PopupMenu.PopupMenuItem(_("Setup a New Device...")),
|
||||
new PopupMenu.PopupSeparatorMenuItem()];
|
||||
this._hasDevices = false;
|
||||
this._deviceSep = this._fullMenuItems[0]; // hidden if no device exists
|
||||
|
||||
|
206
js/ui/status/keyboard.js
Normal file
206
js/ui/status/keyboard.js
Normal file
@ -0,0 +1,206 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const GdkPixbuf = imports.gi.GdkPixbuf;
|
||||
const Gkbd = imports.gi.Gkbd;
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Lang = imports.lang;
|
||||
const Shell = imports.gi.Shell;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
|
||||
const INDICATOR_SCHEMA = 'org.gnome.settings-daemon.plugins.keyboard';
|
||||
|
||||
function LayoutMenuItem() {
|
||||
this._init.apply(this, arguments);
|
||||
}
|
||||
|
||||
LayoutMenuItem.prototype = {
|
||||
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
|
||||
|
||||
_init: function(config, id, indicator, long_name) {
|
||||
PopupMenu.PopupBaseMenuItem.prototype._init.call(this);
|
||||
|
||||
this._config = config;
|
||||
this._id = id;
|
||||
this.label = new St.Label({ text: long_name });
|
||||
this.indicator = indicator;
|
||||
this.addActor(this.label);
|
||||
this.addActor(this.indicator);
|
||||
},
|
||||
|
||||
activate: function(event) {
|
||||
PopupMenu.PopupBaseMenuItem.prototype.activate.call(this);
|
||||
this._config.lock_group(this._id);
|
||||
}
|
||||
};
|
||||
|
||||
function XKBIndicator() {
|
||||
this._init.call(this);
|
||||
}
|
||||
|
||||
XKBIndicator.prototype = {
|
||||
__proto__: PanelMenu.Button.prototype,
|
||||
|
||||
_init: function() {
|
||||
PanelMenu.Button.prototype._init.call(this, St.Align.START);
|
||||
|
||||
this._container = new Shell.GenericContainer();
|
||||
this._container.connect('get-preferred-width', Lang.bind(this, this._get_preferred_width));
|
||||
this._container.connect('get-preferred-height', Lang.bind(this, this._get_preferred_height));
|
||||
this._container.connect('allocate', Lang.bind(this, this._allocate));
|
||||
this.actor.set_child(this._container);
|
||||
|
||||
this._iconActor = new St.Icon({ icon_name: 'keyboard', icon_type: St.IconType.SYMBOLIC, style_class: 'system-status-icon' });
|
||||
this._container.add_actor(this._iconActor);
|
||||
this._labelActors = [ ];
|
||||
this._layoutItems = [ ];
|
||||
|
||||
this._indicatorSettings = new Gio.Settings({ schema: INDICATOR_SCHEMA });
|
||||
this._indicatorSettings.connect('changed::disable-indicator', Lang.bind(this, this._sync_config));
|
||||
|
||||
this._disableIndicator = false;
|
||||
this._showFlags = false;
|
||||
this._config = Gkbd.Configuration.get();
|
||||
this._config.connect('changed', Lang.bind(this, this._sync_config));
|
||||
this._config.connect('group-changed', Lang.bind(this, this._sync_group));
|
||||
this._config.start_listen();
|
||||
|
||||
this._sync_config();
|
||||
|
||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
this.menu.addAction(_("Localization Settings"), function() {
|
||||
GLib.spawn_command_line_async('gnome-control-center region');
|
||||
});
|
||||
},
|
||||
|
||||
_sync_config: function() {
|
||||
this._disableIndicator = this._indicatorSettings.get_boolean('disable-indicator');
|
||||
|
||||
this._showFlags = this._config.if_flags_shown();
|
||||
if (this._showFlags) {
|
||||
this._container.set_skip_paint(this._iconActor, false);
|
||||
} else {
|
||||
this._container.set_skip_paint(this._iconActor, true);
|
||||
}
|
||||
|
||||
let groups = this._config.get_group_names();
|
||||
if (groups.length > 1 && !this._disableIndicator) {
|
||||
this.actor.show();
|
||||
} else {
|
||||
this.menu.close();
|
||||
this.actor.hide();
|
||||
}
|
||||
|
||||
for (let i = 0; i < this._layoutItems.length; i++)
|
||||
this._layoutItems[i].destroy();
|
||||
|
||||
for (let i = 0; i < this._labelActors.length; i++)
|
||||
this._labelActors[i].destroy();
|
||||
|
||||
let short_names = this._config.get_short_group_names();
|
||||
|
||||
this._selectedLayout = null;
|
||||
this._layoutItems = [ ];
|
||||
this._selectedLabel = null;
|
||||
this._labelActors = [ ];
|
||||
for (let i = 0; i < groups.length; i++) {
|
||||
let icon_name = this._config.get_group_name(i);
|
||||
let actor;
|
||||
if (this._showFlags)
|
||||
actor = new St.Icon({ icon_name: icon_name, icon_type: St.IconType.SYMBOLIC, style_class: 'popup-menu-icon' });
|
||||
else
|
||||
actor = new St.Label({ text: short_names[i] });
|
||||
let item = new LayoutMenuItem(this._config, i, actor, groups[i]);
|
||||
item._short_group_name = short_names[i];
|
||||
item._icon_name = icon_name;
|
||||
this._layoutItems.push(item);
|
||||
this.menu.addMenuItem(item, i);
|
||||
|
||||
let shortLabel = new St.Label({ text: short_names[i] });
|
||||
this._labelActors.push(shortLabel);
|
||||
this._container.add_actor(shortLabel);
|
||||
this._container.set_skip_paint(shortLabel, true);
|
||||
}
|
||||
|
||||
this._sync_group();
|
||||
},
|
||||
|
||||
_sync_group: function() {
|
||||
let selected = this._config.get_current_group();
|
||||
|
||||
if (this._selectedLayout) {
|
||||
this._selectedLayout.setShowDot(false);
|
||||
this._selectedLayout = null;
|
||||
}
|
||||
|
||||
if (this._selectedLabel) {
|
||||
this._container.set_skip_paint(this._selectedLabel, true);
|
||||
this._selectedLabel = null;
|
||||
}
|
||||
|
||||
let item = this._layoutItems[selected];
|
||||
item.setShowDot(true);
|
||||
|
||||
this._iconActor.icon_name = item._icon_name;
|
||||
this._selectedLabel = this._labelActors[selected];
|
||||
this._container.set_skip_paint(this._selectedLabel, this._showFlags);
|
||||
|
||||
this._selectedLayout = item;
|
||||
},
|
||||
|
||||
_get_preferred_width: function(container, for_height, alloc) {
|
||||
/* Here, and in _get_preferred_height, we need to query for the
|
||||
height of all children, but we ignore the results for those
|
||||
we don't actually display. */
|
||||
let max_min_width = 0, max_natural_width = 0;
|
||||
if (this._showFlags)
|
||||
[max_min_width, max_natural_width] = this._iconActor.get_preferred_width(for_height);
|
||||
|
||||
for (let i = 0; i < this._labelActors.length; i++) {
|
||||
let [min_width, natural_width] = this._labelActors[i].get_preferred_width(for_height);
|
||||
if (!this._showFlags) {
|
||||
max_min_width = Math.max(max_min_width, min_width);
|
||||
max_natural_width = Math.max(max_natural_width, natural_width);
|
||||
}
|
||||
}
|
||||
|
||||
alloc.min_size = max_min_width;
|
||||
alloc.natural_size = max_natural_width;
|
||||
},
|
||||
|
||||
_get_preferred_height: function(container, for_width, alloc) {
|
||||
let max_min_height = 0, max_natural_height = 0;
|
||||
if (this._showFlags)
|
||||
[max_min_height, max_natural_height] = this._iconActor.get_preferred_height(for_width);
|
||||
|
||||
for (let i = 0; i < this._labelActors.length; i++) {
|
||||
let [min_height, natural_height] = this._labelActors[i].get_preferred_height(for_width);
|
||||
if (!this._showFlags) {
|
||||
max_min_height = Math.max(max_min_height, min_height);
|
||||
max_natural_height = Math.max(max_natural_height, natural_height);
|
||||
}
|
||||
}
|
||||
|
||||
alloc.min_size = max_min_height;
|
||||
alloc.natural_size = max_natural_height;
|
||||
},
|
||||
|
||||
_allocate: function(container, box, flags) {
|
||||
// translate box to (0, 0)
|
||||
box.x2 -= box.x1;
|
||||
box.x1 = 0;
|
||||
box.y2 -= box.y1;
|
||||
box.y1 = 0;
|
||||
|
||||
this._iconActor.allocate_align_fill(box, 0.5, 0, false, false, flags);
|
||||
for (let i = 0; i < this._labelActors.length; i++)
|
||||
this._labelActors[i].allocate_align_fill(box, 0.5, 0, false, false, flags);
|
||||
}
|
||||
};
|
@ -1,7 +1,6 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Gio = imports.gi.Gio;
|
||||
const GLib = imports.gi.GLib;
|
||||
const DBus = imports.dbus;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
@ -10,6 +9,7 @@ const St = imports.gi.St;
|
||||
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
@ -83,7 +83,7 @@ Indicator.prototype = {
|
||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
|
||||
this.menu.addAction(_("Power Settings"),function() {
|
||||
GLib.spawn_command_line_async('gnome-control-center power');
|
||||
Util.spawnDesktop('gnome-power-panel');
|
||||
});
|
||||
|
||||
this._proxy.connect('Changed', Lang.bind(this, this._devicesChanged));
|
||||
@ -134,8 +134,7 @@ Indicator.prototype = {
|
||||
this._batteryItem.actor.reactive = true;
|
||||
this._batteryItem.actor.can_focus = true;
|
||||
this._batteryItem.connect('activate', function(item) {
|
||||
let p = new Shell.Process({ args: ['gnome-power-statistics', '--device', device_id] });
|
||||
p.run();
|
||||
Util.spawn(['gnome-power-statistics', '--device', device_id]);
|
||||
});
|
||||
} else {
|
||||
// virtual device
|
||||
@ -164,8 +163,7 @@ Indicator.prototype = {
|
||||
|
||||
let item = new DeviceItem (devices[i]);
|
||||
item.connect('activate', function() {
|
||||
let p = new Shell.Process({ args: ['gnome-power-statistics', '--device', device_id] });
|
||||
p.run();
|
||||
Util.spawn(['gnome-power-statistics', '--device', device_id]);
|
||||
});
|
||||
this._deviceItems.push(item);
|
||||
this.menu.addMenuItem(item, this._otherDevicePosition + position);
|
||||
@ -197,8 +195,8 @@ Indicator.prototype = {
|
||||
|
||||
_checkError: function(error) {
|
||||
if (!this._restarted && error && error.message.match(/org\.freedesktop\.DBus\.Error\.(UnknownMethod|InvalidArgs)/)) {
|
||||
GLib.spawn_command_line_sync('pkill -f "^gnome-power-manager$"');
|
||||
GLib.spawn_command_line_async('gnome-power-manager');
|
||||
Util.killall('gnome-power-manager');
|
||||
Util.spawn(['gnome-power-manager']);
|
||||
this._restarted = true;
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ const St = imports.gi.St;
|
||||
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const Gettext = imports.gettext.domain('gnome-shell');
|
||||
const _ = Gettext.gettext;
|
||||
@ -60,8 +61,7 @@ Indicator.prototype = {
|
||||
|
||||
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
|
||||
this.menu.addAction(_("Sound Settings"), function() {
|
||||
let p = new Shell.Process({ args: ['gnome-control-center', 'sound'] });
|
||||
p.run();
|
||||
Util.spawnDesktop('gnome-sound-panel');
|
||||
});
|
||||
|
||||
this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
|
||||
|
@ -6,6 +6,7 @@ const Signals = imports.signals;
|
||||
|
||||
const MessageTray = imports.ui.messageTray;
|
||||
const NotificationDaemon = imports.ui.notificationDaemon;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
|
||||
'bluetooth-applet': 'bluetooth',
|
||||
@ -15,7 +16,10 @@ const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
|
||||
'nm-applet': 'network',
|
||||
'gnome-power-manager': 'battery',
|
||||
'keyboard': 'keyboard',
|
||||
'gnome-settings-daemon': 'display'
|
||||
'a11y-keyboard': 'a11y',
|
||||
'kbd-scrolllock': 'keyboard',
|
||||
'kbd-numlock': 'keyboard',
|
||||
'kbd-capslock': 'keyboard'
|
||||
};
|
||||
|
||||
function StatusIconDispatcher() {
|
||||
@ -33,8 +37,7 @@ StatusIconDispatcher.prototype = {
|
||||
// app-indicators, so that applications fall back to normal
|
||||
// status icons
|
||||
// http://bugzilla.gnome.org/show_bug.cgi=id=621382
|
||||
let p = new Shell.Process({ args: ['pkill', '-f', '^([^ ]*/)?indicator-application-service$']});
|
||||
p.run();
|
||||
Util.killall('indicator-application-service');
|
||||
},
|
||||
|
||||
_onTrayIconAdded: function(o, icon) {
|
||||
|
@ -12,6 +12,7 @@ const GnomeSession = imports.misc.gnomeSession;
|
||||
const Main = imports.ui.main;
|
||||
const PanelMenu = imports.ui.panelMenu;
|
||||
const PopupMenu = imports.ui.popupMenu;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
// Adapted from gdm/gui/user-switch-applet/applet.c
|
||||
//
|
||||
@ -31,7 +32,7 @@ StatusMenuButton.prototype = {
|
||||
this.actor.set_child(box);
|
||||
|
||||
this._gdm = Gdm.UserManager.ref_default();
|
||||
this._gdm.queue_load()
|
||||
this._gdm.queue_load();
|
||||
|
||||
this._user = this._gdm.get_user(GLib.get_user_name());
|
||||
this._presence = new GnomeSession.Presence();
|
||||
@ -153,17 +154,17 @@ StatusMenuButton.prototype = {
|
||||
|
||||
_onMyAccountActivate: function() {
|
||||
Main.overview.hide();
|
||||
this._spawn(['gnome-control-center', 'user-accounts']);
|
||||
Util.spawnDesktop('gnome-user-accounts-panel');
|
||||
},
|
||||
|
||||
_onPreferencesActivate: function() {
|
||||
Main.overview.hide();
|
||||
this._spawn(['gnome-control-center', '-o']);
|
||||
Util.spawnDesktop('gnome-control-center');
|
||||
},
|
||||
|
||||
_onLockScreenActivate: function() {
|
||||
Main.overview.hide();
|
||||
this._spawn(['gnome-screensaver-command', '--lock']);
|
||||
Util.spawn(['gnome-screensaver-command', '--lock']);
|
||||
},
|
||||
|
||||
_onLoginScreenActivate: function() {
|
||||
@ -174,19 +175,11 @@ StatusMenuButton.prototype = {
|
||||
|
||||
_onQuitSessionActivate: function() {
|
||||
Main.overview.hide();
|
||||
this._spawn(['gnome-session-save', '--logout-dialog']);
|
||||
Util.spawn(['gnome-session-save', '--logout-dialog']);
|
||||
},
|
||||
|
||||
_onShutDownActivate: function() {
|
||||
Main.overview.hide();
|
||||
this._spawn(['gnome-session-save', '--shutdown-dialog']);
|
||||
},
|
||||
|
||||
_spawn: function(args) {
|
||||
// FIXME: once Shell.Process gets support for signalling
|
||||
// errors we should pop up an error dialog or something here
|
||||
// on failure
|
||||
let p = new Shell.Process({'args' : args});
|
||||
p.run();
|
||||
Util.spawn(['gnome-session-save', '--shutdown-dialog']);
|
||||
}
|
||||
};
|
||||
|
@ -455,6 +455,8 @@ Source.prototype = {
|
||||
_init: function(accountPath, connPath, channelPath, targetHandle, targetHandleType, targetId) {
|
||||
MessageTray.Source.prototype._init.call(this, targetId);
|
||||
|
||||
this.isChat = true;
|
||||
|
||||
this._accountPath = accountPath;
|
||||
|
||||
let connName = Telepathy.pathToName(connPath);
|
||||
|
@ -247,9 +247,10 @@ SearchTab.prototype = {
|
||||
this._focusBase = focusBase;
|
||||
|
||||
this._searchSystem = new Search.SearchSystem();
|
||||
this._openSearchSystem = new Search.OpenSearchSystem();
|
||||
|
||||
this._searchEntry = new SearchEntry(focusBase);
|
||||
this._searchResults = new SearchDisplay.SearchResults(this._searchSystem);
|
||||
this._searchResults = new SearchDisplay.SearchResults(this._searchSystem, this._openSearchSystem);
|
||||
BaseTab.prototype._init.call(this,
|
||||
this._searchEntry.actor,
|
||||
this._searchResults.actor);
|
||||
|
@ -497,6 +497,8 @@ WindowManager.prototype = {
|
||||
|
||||
for (let i = 0; i < switchData.windows.length; i++) {
|
||||
let w = switchData.windows[i];
|
||||
if (w.window.is_destroyed()) // Window gone
|
||||
continue;
|
||||
if (w.window.get_parent() == switchData.outGroup) {
|
||||
w.window.reparent(w.parent);
|
||||
w.window.hide();
|
||||
@ -523,23 +525,20 @@ WindowManager.prototype = {
|
||||
},
|
||||
|
||||
_showWorkspaceSwitcher : function(shellwm, binding, window, backwards) {
|
||||
/* We don't support this kind of layout */
|
||||
if (binding == 'switch_to_workspace_up' || binding == 'switch_to_workspace_down')
|
||||
return;
|
||||
|
||||
if (global.screen.n_workspaces == 1)
|
||||
return;
|
||||
|
||||
if (this._workspaceSwitcherPopup == null)
|
||||
this._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup();
|
||||
|
||||
if (binding == 'switch_to_workspace_left') {
|
||||
if (binding == 'switch_to_workspace_left')
|
||||
this.actionMoveWorkspaceLeft();
|
||||
}
|
||||
|
||||
if (binding == 'switch_to_workspace_right') {
|
||||
else if (binding == 'switch_to_workspace_right')
|
||||
this.actionMoveWorkspaceRight();
|
||||
}
|
||||
else if (binding == 'switch_to_workspace_up')
|
||||
this.actionMoveWorkspaceUp();
|
||||
else if (binding == 'switch_to_workspace_down')
|
||||
this.actionMoveWorkspaceDown();
|
||||
},
|
||||
|
||||
actionMoveWorkspaceLeft: function() {
|
||||
@ -570,6 +569,32 @@ WindowManager.prototype = {
|
||||
if (indexToActivate != activeWorkspaceIndex)
|
||||
global.screen.get_workspace_by_index(indexToActivate).activate(global.get_current_time());
|
||||
|
||||
if (!Main.overview.visible)
|
||||
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.RIGHT, indexToActivate);
|
||||
},
|
||||
|
||||
actionMoveWorkspaceUp: function() {
|
||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
||||
let indexToActivate = activeWorkspaceIndex;
|
||||
if (activeWorkspaceIndex > 0)
|
||||
indexToActivate--;
|
||||
|
||||
if (indexToActivate != activeWorkspaceIndex)
|
||||
global.screen.get_workspace_by_index(indexToActivate).activate(global.get_current_time());
|
||||
|
||||
if (!Main.overview.visible)
|
||||
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.LEFT, indexToActivate);
|
||||
},
|
||||
|
||||
actionMoveWorkspaceDown: function() {
|
||||
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
|
||||
let indexToActivate = activeWorkspaceIndex;
|
||||
if (activeWorkspaceIndex < global.screen.n_workspaces - 1)
|
||||
indexToActivate++;
|
||||
|
||||
if (indexToActivate != activeWorkspaceIndex)
|
||||
global.screen.get_workspace_by_index(indexToActivate).activate(global.get_current_time());
|
||||
|
||||
if (!Main.overview.visible)
|
||||
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.RIGHT, indexToActivate);
|
||||
}
|
||||
|
@ -104,6 +104,10 @@ WindowClone.prototype = {
|
||||
|
||||
this._stackAbove = null;
|
||||
|
||||
this._sizeChangedId = this.realWindow.connect('size-changed', Lang.bind(this, function() {
|
||||
this.emit('size-changed');
|
||||
}));
|
||||
|
||||
this.actor.connect('button-release-event',
|
||||
Lang.bind(this, this._onButtonRelease));
|
||||
|
||||
@ -157,6 +161,9 @@ WindowClone.prototype = {
|
||||
},
|
||||
|
||||
_onDestroy: function() {
|
||||
this.realWindow.disconnect(this._sizeChangedId);
|
||||
this._sizeChangedId = 0;
|
||||
|
||||
this.metaWindow._delegate = null;
|
||||
this.actor._delegate = null;
|
||||
if (this._zoomLightbox)
|
||||
@ -517,20 +524,10 @@ Workspace.prototype = {
|
||||
// Without this the drop area will be overlapped.
|
||||
this._windowOverlaysGroup.set_size(0, 0);
|
||||
|
||||
this.actor = new Clutter.Group({ reactive: true });
|
||||
this.actor = new Clutter.Group();
|
||||
this.actor._delegate = this;
|
||||
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
this.actor.connect('button-release-event', Lang.bind(this,
|
||||
function(actor, event) {
|
||||
// Only switch to the workspace when there's no application
|
||||
// windows open. The problem is that it's too easy to miss
|
||||
// an app window and get the wrong one focused.
|
||||
if (this._windows.length == 0) {
|
||||
this.metaWorkspace.activate(event.get_time());
|
||||
Main.overview.hide();
|
||||
}
|
||||
}));
|
||||
|
||||
// Items in _windowOverlaysGroup should not be scaled, so we don't
|
||||
// add them to this.actor, but to its parent whenever it changes
|
||||
@ -605,6 +602,10 @@ Workspace.prototype = {
|
||||
return this._lookupIndex(metaWindow) >= 0;
|
||||
},
|
||||
|
||||
isEmpty: function() {
|
||||
return this._windows.length == 0;
|
||||
},
|
||||
|
||||
setShowOnlyWindows: function(showOnlyWindows, reposition) {
|
||||
this._showOnlyWindows = showOnlyWindows;
|
||||
this._resetCloneVisibility();
|
||||
@ -1331,6 +1332,10 @@ Workspace.prototype = {
|
||||
Lang.bind(this, function() {
|
||||
this._windowIsZooming = false;
|
||||
}));
|
||||
clone.connect('size-changed',
|
||||
Lang.bind(this, function() {
|
||||
this.positionWindows(0);
|
||||
}));
|
||||
|
||||
this.actor.add_actor(clone.actor);
|
||||
|
||||
@ -1397,7 +1402,7 @@ Workspace.prototype = {
|
||||
},
|
||||
|
||||
acceptDrop : function(source, actor, x, y, time) {
|
||||
if (source instanceof WindowClone) {
|
||||
if (source.realWindow) {
|
||||
let win = source.realWindow;
|
||||
if (this._isMyWindow(win))
|
||||
return false;
|
||||
@ -1416,8 +1421,8 @@ Workspace.prototype = {
|
||||
time);
|
||||
return true;
|
||||
} else if (source.shellWorkspaceLaunch) {
|
||||
this.metaWorkspace.activate(time);
|
||||
source.shellWorkspaceLaunch();
|
||||
source.shellWorkspaceLaunch({ workspace: this.metaWorkspace,
|
||||
timestamp: time });
|
||||
return true;
|
||||
}
|
||||
|
||||
|
310
js/ui/workspaceThumbnail.js
Normal file
310
js/ui/workspaceThumbnail.js
Normal file
@ -0,0 +1,310 @@
|
||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||
|
||||
const Clutter = imports.gi.Clutter;
|
||||
const Lang = imports.lang;
|
||||
const Mainloop = imports.mainloop;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
const St = imports.gi.St;
|
||||
|
||||
const DND = imports.ui.dnd;
|
||||
const Main = imports.ui.main;
|
||||
const Workspace = imports.ui.workspace;
|
||||
|
||||
// Fraction of original screen size for thumbnails
|
||||
let THUMBNAIL_SCALE = 1/8.;
|
||||
|
||||
function WindowClone(realWindow) {
|
||||
this._init(realWindow);
|
||||
}
|
||||
|
||||
WindowClone.prototype = {
|
||||
_init : function(realWindow) {
|
||||
this.actor = new Clutter.Clone({ source: realWindow.get_texture(),
|
||||
clip_to_allocation: true,
|
||||
reactive: true });
|
||||
this.actor._delegate = this;
|
||||
this.realWindow = realWindow;
|
||||
this.metaWindow = realWindow.meta_window;
|
||||
this.metaWindow._delegate = this;
|
||||
|
||||
this._positionChangedId = this.realWindow.connect('position-changed',
|
||||
Lang.bind(this, this._onPositionChanged));
|
||||
this._onPositionChanged();
|
||||
|
||||
this.actor.connect('button-release-event',
|
||||
Lang.bind(this, this._onButtonRelease));
|
||||
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
|
||||
this._draggable = DND.makeDraggable(this.actor,
|
||||
{ restoreOnSuccess: true,
|
||||
dragActorMaxSize: Workspace.WINDOW_DND_SIZE,
|
||||
dragActorOpacity: Workspace.DRAGGING_WINDOW_OPACITY });
|
||||
this._draggable.connect('drag-begin', Lang.bind(this, this._onDragBegin));
|
||||
this._draggable.connect('drag-end', Lang.bind(this, this._onDragEnd));
|
||||
this.inDrag = false;
|
||||
|
||||
this._selected = false;
|
||||
},
|
||||
|
||||
setStackAbove: function (actor) {
|
||||
this._stackAbove = actor;
|
||||
if (this._stackAbove == null)
|
||||
this.actor.lower_bottom();
|
||||
else
|
||||
this.actor.raise(this._stackAbove);
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
this.actor.destroy();
|
||||
},
|
||||
|
||||
_onPositionChanged: function() {
|
||||
let rect = this.metaWindow.get_outer_rect();
|
||||
this.actor.set_position(this.realWindow.x, this.realWindow.y);
|
||||
},
|
||||
|
||||
_onDestroy: function() {
|
||||
this.metaWindow._delegate = null;
|
||||
this.actor._delegate = null;
|
||||
|
||||
if (this._positionChangedId != 0) {
|
||||
this.realWindow.disconnect(this._positionChangedId);
|
||||
this._positionChangedId = 0;
|
||||
}
|
||||
|
||||
if (this.inDrag) {
|
||||
this.emit('drag-end');
|
||||
this.inDrag = false;
|
||||
}
|
||||
|
||||
this.disconnectAll();
|
||||
},
|
||||
|
||||
_onButtonRelease : function (actor, event) {
|
||||
this._selected = true;
|
||||
this.emit('selected', event.get_time());
|
||||
},
|
||||
|
||||
_onDragBegin : function (draggable, time) {
|
||||
this.inDrag = true;
|
||||
this.emit('drag-begin');
|
||||
},
|
||||
|
||||
_onDragEnd : function (draggable, time, snapback) {
|
||||
this.inDrag = false;
|
||||
|
||||
// We may not have a parent if DnD completed successfully, in
|
||||
// which case our clone will shortly be destroyed and replaced
|
||||
// with a new one on the target workspace.
|
||||
if (this.actor.get_parent() != null) {
|
||||
if (this._stackAbove == null)
|
||||
this.actor.lower_bottom();
|
||||
else
|
||||
this.actor.raise(this._stackAbove);
|
||||
}
|
||||
|
||||
|
||||
this.emit('drag-end');
|
||||
}
|
||||
};
|
||||
Signals.addSignalMethods(WindowClone.prototype);
|
||||
|
||||
|
||||
/**
|
||||
* @metaWorkspace: a #Meta.Workspace
|
||||
*/
|
||||
function WorkspaceThumbnail(metaWorkspace) {
|
||||
this._init(metaWorkspace);
|
||||
}
|
||||
|
||||
WorkspaceThumbnail.prototype = {
|
||||
_init : function(metaWorkspace) {
|
||||
// When dragging a window, we use this slot for reserve space.
|
||||
this.metaWorkspace = metaWorkspace;
|
||||
|
||||
this.actor = new St.Bin({ reactive: true,
|
||||
style_class: 'workspace-thumbnail' });
|
||||
this.actor._delegate = this;
|
||||
|
||||
this._group = new Clutter.Group();
|
||||
this.actor.add_actor(this._group);
|
||||
|
||||
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
|
||||
this.actor.connect('button-press-event', Lang.bind(this,
|
||||
function(actor, event) {
|
||||
return true;
|
||||
}));
|
||||
this.actor.connect('button-release-event', Lang.bind(this,
|
||||
function(actor, event) {
|
||||
this.metaWorkspace.activate(event.get_time());
|
||||
return true;
|
||||
}));
|
||||
|
||||
this._background = new Clutter.Clone({ source: global.background_actor });
|
||||
this._group.add_actor(this._background);
|
||||
|
||||
this._group.set_size(THUMBNAIL_SCALE * global.screen_width, THUMBNAIL_SCALE * global.screen_height);
|
||||
this._group.set_scale(THUMBNAIL_SCALE, THUMBNAIL_SCALE);
|
||||
|
||||
let windows = global.get_window_actors().filter(this._isMyWindow, this);
|
||||
|
||||
// Create clones for windows that should be visible in the Overview
|
||||
this._windows = [];
|
||||
for (let i = 0; i < windows.length; i++) {
|
||||
if (this._isOverviewWindow(windows[i])) {
|
||||
this._addWindowClone(windows[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Track window changes
|
||||
this._windowAddedId = this.metaWorkspace.connect('window-added',
|
||||
Lang.bind(this, this._windowAdded));
|
||||
this._windowRemovedId = this.metaWorkspace.connect('window-removed',
|
||||
Lang.bind(this, this._windowRemoved));
|
||||
},
|
||||
|
||||
_lookupIndex: function (metaWindow) {
|
||||
for (let i = 0; i < this._windows.length; i++) {
|
||||
if (this._windows[i].metaWindow == metaWindow) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
|
||||
syncStacking: function(stackIndices) {
|
||||
this._windows.sort(function (a, b) { return stackIndices[a.metaWindow.get_stable_sequence()] - stackIndices[b.metaWindow.get_stable_sequence()]; });
|
||||
|
||||
for (let i = 0; i < this._windows.length; i++) {
|
||||
let clone = this._windows[i];
|
||||
let metaWindow = clone.metaWindow;
|
||||
if (i == 0) {
|
||||
clone.setStackAbove(this._background);
|
||||
} else {
|
||||
let previousClone = this._windows[i - 1];
|
||||
clone.setStackAbove(previousClone.actor);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_windowRemoved : function(metaWorkspace, metaWin) {
|
||||
let win = metaWin.get_compositor_private();
|
||||
|
||||
// find the position of the window in our list
|
||||
let index = this._lookupIndex (metaWin);
|
||||
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
let clone = this._windows[index];
|
||||
this._windows.splice(index, 1);
|
||||
clone.destroy();
|
||||
},
|
||||
|
||||
_windowAdded : function(metaWorkspace, metaWin) {
|
||||
if (this.leavingOverview)
|
||||
return;
|
||||
|
||||
let win = metaWin.get_compositor_private();
|
||||
|
||||
if (!win) {
|
||||
// Newly-created windows are added to a workspace before
|
||||
// the compositor finds out about them...
|
||||
Mainloop.idle_add(Lang.bind(this,
|
||||
function () {
|
||||
if (this.actor && metaWin.get_compositor_private())
|
||||
this._windowAdded(metaWorkspace, metaWin);
|
||||
return false;
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._isOverviewWindow(win))
|
||||
return;
|
||||
|
||||
let clone = this._addWindowClone(win);
|
||||
},
|
||||
|
||||
destroy : function() {
|
||||
this.actor.destroy();
|
||||
},
|
||||
|
||||
_onDestroy: function(actor) {
|
||||
this.metaWorkspace.disconnect(this._windowAddedId);
|
||||
this.metaWorkspace.disconnect(this._windowRemovedId);
|
||||
|
||||
this._windows = [];
|
||||
this.actor = null;
|
||||
},
|
||||
|
||||
// Tests if @win belongs to this workspaces
|
||||
_isMyWindow : function (win) {
|
||||
return win.get_workspace() == this.metaWorkspace.index() ||
|
||||
(win.get_meta_window() && win.get_meta_window().is_on_all_workspaces());
|
||||
},
|
||||
|
||||
// Tests if @win should be shown in the Overview
|
||||
_isOverviewWindow : function (win) {
|
||||
let tracker = Shell.WindowTracker.get_default();
|
||||
return tracker.is_window_interesting(win.get_meta_window());
|
||||
},
|
||||
|
||||
// Create a clone of a (non-desktop) window and add it to the window list
|
||||
_addWindowClone : function(win) {
|
||||
let clone = new WindowClone(win);
|
||||
|
||||
clone.connect('selected',
|
||||
Lang.bind(this, this._onCloneSelected));
|
||||
clone.connect('drag-begin',
|
||||
Lang.bind(this, function(clone) {
|
||||
Main.overview.beginWindowDrag();
|
||||
}));
|
||||
clone.connect('drag-end',
|
||||
Lang.bind(this, function(clone) {
|
||||
Main.overview.endWindowDrag();
|
||||
}));
|
||||
this._group.add_actor(clone.actor);
|
||||
|
||||
this._windows.push(clone);
|
||||
|
||||
return clone;
|
||||
},
|
||||
|
||||
_onCloneSelected : function (clone, time) {
|
||||
this.metaWorkspace.activate(time);
|
||||
},
|
||||
|
||||
// Draggable target interface
|
||||
handleDragOver : function(source, actor, x, y, time) {
|
||||
if (source.realWindow)
|
||||
return DND.DragMotionResult.MOVE_DROP;
|
||||
if (source.shellWorkspaceLaunch)
|
||||
return DND.DragMotionResult.COPY_DROP;
|
||||
|
||||
return DND.DragMotionResult.CONTINUE;
|
||||
},
|
||||
|
||||
acceptDrop : function(source, actor, x, y, time) {
|
||||
if (source.realWindow) {
|
||||
let win = source.realWindow;
|
||||
if (this._isMyWindow(win))
|
||||
return false;
|
||||
|
||||
let metaWindow = win.get_meta_window();
|
||||
metaWindow.change_workspace_by_index(this.metaWorkspace.index(),
|
||||
false, // don't create workspace
|
||||
time);
|
||||
return true;
|
||||
} else if (source.shellWorkspaceLaunch) {
|
||||
source.shellWorkspaceLaunch({ workspace: this.metaWorkspace,
|
||||
timestamp: time });
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(WorkspaceThumbnail.prototype);
|
File diff suppressed because it is too large
Load Diff
@ -67,18 +67,15 @@ XdndHandler.prototype = {
|
||||
if (!cursorWindow.is_override_redirect())
|
||||
return;
|
||||
|
||||
let constraint_x = new Clutter.BindConstraint({ coordinate : Clutter.BindCoordinate.X,
|
||||
source: cursorWindow});
|
||||
let constraint_y = new Clutter.BindConstraint({ coordinate : Clutter.BindCoordinate.Y,
|
||||
source: cursorWindow});
|
||||
let constraint_position = new Clutter.BindConstraint({ coordinate : Clutter.BindCoordinate.POSITION,
|
||||
source: cursorWindow});
|
||||
|
||||
this._cursorWindowClone = new Clutter.Clone({ source: cursorWindow });
|
||||
global.overlay_group.add_actor(this._cursorWindowClone);
|
||||
Shell.util_set_hidden_from_pick(this._cursorWindowClone, true);
|
||||
|
||||
// Make sure that the clone has the same position as the source
|
||||
this._cursorWindowClone.add_constraint(constraint_x);
|
||||
this._cursorWindowClone.add_constraint(constraint_y);
|
||||
this._cursorWindowClone.add_constraint(constraint_position);
|
||||
} else {
|
||||
if (this._cursorWindowClone)
|
||||
{
|
||||
|
@ -1,11 +1,16 @@
|
||||
data/gnome-shell.desktop.in.in
|
||||
data/org.gnome.shell.gschema.xml.in
|
||||
data/org.gnome.accessibility.magnifier.gschema.xml.in
|
||||
js/misc/util.js
|
||||
js/ui/appDisplay.js
|
||||
js/ui/appFavorites.js
|
||||
js/ui/calendar.js
|
||||
js/ui/dash.js
|
||||
js/ui/dateMenu.js
|
||||
js/ui/docDisplay.js
|
||||
js/ui/endSessionDialog.js
|
||||
js/ui/lookingGlass.js
|
||||
js/ui/messageTray.js
|
||||
js/ui/overview.js
|
||||
js/ui/panel.js
|
||||
js/ui/placeDisplay.js
|
||||
@ -14,6 +19,7 @@ js/ui/runDialog.js
|
||||
js/ui/statusMenu.js
|
||||
js/ui/status/accessibility.js
|
||||
js/ui/status/bluetooth.js
|
||||
js/ui/status/keyboard.js
|
||||
js/ui/status/power.js
|
||||
js/ui/status/volume.js
|
||||
js/ui/telepathyClient.js
|
||||
|
362
po/es.po
362
po/es.po
@ -1,7 +1,7 @@
|
||||
# Spanish translation of gnome-shell.
|
||||
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
# Jorge González <jorgegonz@svn.gnome.org>, 2009, 2010.
|
||||
# Jorge González <jorgegonz@svn.gnome.org>, 2009, 2010, 2011.
|
||||
# Daniel Mustieles <daniel.mustieles@gmail.com>, 2010, 2011.
|
||||
#
|
||||
msgid ""
|
||||
@ -9,8 +9,8 @@ msgstr ""
|
||||
"Project-Id-Version: gnome-shell.master\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&component=general\n"
|
||||
"POT-Creation-Date: 2011-01-04 16:17+0000\n"
|
||||
"PO-Revision-Date: 2011-01-05 12:38+0100\n"
|
||||
"POT-Creation-Date: 2011-01-27 20:47+0000\n"
|
||||
"PO-Revision-Date: 2011-01-28 10:43+0100\n"
|
||||
"Last-Translator: Daniel Mustieles <daniel.mustieles@gmail.com>\n"
|
||||
"Language-Team: Español <gnome-es-list@gnome.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -61,14 +61,10 @@ msgid "History for command (Alt-F2) dialog"
|
||||
msgstr "Histórico del diálogo de comandos (Alt+F2)"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:7
|
||||
#| msgid ""
|
||||
#| "If true and format is either \"12-hour\" or \"24-hour\", display date in "
|
||||
#| "the clock, in addition to time."
|
||||
msgid "If true, display date in the clock, in addition to time."
|
||||
msgstr "Si es cierta, muestra la fecha en el reloj, además de la hora."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:8
|
||||
#| msgid "If true, display the ISO week date in the calendar."
|
||||
msgid "If true, display seconds in time."
|
||||
msgstr "Si es cierta, muestra los segundos en la hora."
|
||||
|
||||
@ -80,7 +76,8 @@ msgstr "Si es cierta muestra la fecha de semana ISO en el calendario."
|
||||
msgid "List of desktop file IDs for favorite applications"
|
||||
msgstr "Lista de ID de archivos de escritorio para las aplicaciones favoritas"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:11
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:12
|
||||
#, no-c-format
|
||||
msgid ""
|
||||
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
|
||||
"used for gst-launch. The pipeline should have an unconnected sink pad where "
|
||||
@ -89,7 +86,9 @@ msgid ""
|
||||
"pipeline can also take care of its own output - this might be used to send "
|
||||
"the output to an icecast server via shout2send or similar. When unset or set "
|
||||
"to an empty value, the default pipeline will be used. This is currently "
|
||||
"'videorate ! theoraenc ! oggmux' and records to Ogg Theora."
|
||||
"'videorate ! vp8enc quality=10 speed=2 threads=%T ! queue ! webmmux' and "
|
||||
"records to WEBM using the VP8 codec. %T is used as a placeholder for a guess "
|
||||
"at the optimal thread count on the system."
|
||||
msgstr ""
|
||||
"Establece la tubería GStreamer usada para codificar grabaciones. Sigue la "
|
||||
"sintaxis usada para gst-launch. La tubería debería tener un sumidero («sink») "
|
||||
@ -99,22 +98,23 @@ msgstr ""
|
||||
"puede tomar parte en su propia salida; esto se puede usar para enviar la "
|
||||
"salida a un servidor «icecast» a través de shout2send o similar. Cuando no "
|
||||
"está establecido o lo está a un valor vacío, se usará la tubería "
|
||||
"predeterminada. Actualmente es «videorate ! theoraenc ! oggmux» y greba en "
|
||||
"Ogg Theora."
|
||||
"predeterminada. Actualmente es «videorate ! vp8enc quality=10 speed=2 threads="
|
||||
"%T ! queue ! webmmux» y greba en WEBM usando el códec VP8. Se usa %T como "
|
||||
"suposición para el número de hilos óptimos en el sistema."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:12
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:13
|
||||
msgid "Show date in clock"
|
||||
msgstr "Mostrar la fecha en el reloj"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:13
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:14
|
||||
msgid "Show the week date in the calendar"
|
||||
msgstr "Mostrar la fecha de la semana en el calendario"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:14
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:15
|
||||
msgid "Show time with seconds"
|
||||
msgstr "Mostrar la hora con segundos"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:15
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:16
|
||||
msgid ""
|
||||
"The applications corresponding to these identifiers will be displayed in the "
|
||||
"favorites area."
|
||||
@ -122,7 +122,7 @@ msgstr ""
|
||||
"Las aplicaciones correspondientes con esos identificadores se mostrarán en "
|
||||
"el área de favoritos."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:16
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:17
|
||||
msgid ""
|
||||
"The filename for recorded screencasts will be a unique filename based on the "
|
||||
"current date, and use this extension. It should be changed when recording to "
|
||||
@ -132,7 +132,7 @@ msgstr ""
|
||||
"basado en la fecha actual y usará esta extensión. Se debería cambiar al "
|
||||
"grabar en otro formato contenedor diferente."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:17
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:18
|
||||
msgid ""
|
||||
"The framerate of the resulting screencast recordered by GNOME Shell's "
|
||||
"screencast recorder in frames-per-second."
|
||||
@ -140,11 +140,11 @@ msgstr ""
|
||||
"La tasa de fotogramas de la grabación resultante grabada por el grabador de "
|
||||
"«screencast» de GNOME Shell, en fotogramas por segundo."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:18
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:19
|
||||
msgid "The gstreamer pipeline used to encode the screencast"
|
||||
msgstr "La tubería de gstreamer usada para codificar el «screencast»"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:19
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:20
|
||||
msgid ""
|
||||
"The shell normally monitors active applications in order to present the most "
|
||||
"used ones (e.g. in launchers). While this data will be kept private, you may "
|
||||
@ -156,15 +156,19 @@ msgstr ""
|
||||
"mantienen de forma privada, puede querer desactivarlo por razones de "
|
||||
"privacidad. Note que haciéndolo no eliminará los datos ya guardados."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:20
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:21
|
||||
msgid "Uuids of extensions to disable"
|
||||
msgstr "Uuid de las extensiones que desactivar"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:21
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:22
|
||||
msgid "Whether to collect stats about applications usage"
|
||||
msgstr ""
|
||||
"Indica si se deben recolectar estadísticas acerca del uso de las aplicaciones"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:23
|
||||
msgid "disabled OpenSearch providers"
|
||||
msgstr "proveedores OpenSearch desactivados"
|
||||
|
||||
#: ../data/org.gnome.accessibility.magnifier.gschema.xml.in.h:1
|
||||
msgid "Clip the crosshairs at the center"
|
||||
msgstr "Fijar los cursores en el centro"
|
||||
@ -322,28 +326,47 @@ msgid "Width of the vertical and horizontal lines that make up the crosshairs."
|
||||
msgstr ""
|
||||
"Anchura de las líneas verticales y horizontales que conforman las cruces."
|
||||
|
||||
#: ../js/misc/util.js:86
|
||||
msgid "Command not found"
|
||||
msgstr "Comando no encontrado"
|
||||
|
||||
#. Replace "Error invoking GLib.shell_parse_argv: " with
|
||||
#. something nicer
|
||||
#: ../js/misc/util.js:113
|
||||
msgid "Could not parse command:"
|
||||
msgstr "No se pudo analizar el comando:"
|
||||
|
||||
#: ../js/misc/util.js:135
|
||||
msgid "No such application"
|
||||
msgstr "No existe la aplicación"
|
||||
|
||||
#: ../js/misc/util.js:148
|
||||
#, c-format
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "Falló la ejecución de «%s»:"
|
||||
|
||||
#. Translators: Filter to display all applications
|
||||
#: ../js/ui/appDisplay.js:155
|
||||
#: ../js/ui/appDisplay.js:164
|
||||
msgid "All"
|
||||
msgstr "Todas"
|
||||
|
||||
#: ../js/ui/appDisplay.js:236
|
||||
#: ../js/ui/appDisplay.js:245
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "APLICACIONES"
|
||||
|
||||
#: ../js/ui/appDisplay.js:266
|
||||
#: ../js/ui/appDisplay.js:275
|
||||
msgid "PREFERENCES"
|
||||
msgstr "PREFERENCIAS"
|
||||
|
||||
#: ../js/ui/appDisplay.js:563
|
||||
#: ../js/ui/appDisplay.js:572
|
||||
msgid "New Window"
|
||||
msgstr "Ventana nueva"
|
||||
|
||||
#: ../js/ui/appDisplay.js:567
|
||||
#: ../js/ui/appDisplay.js:576
|
||||
msgid "Remove from Favorites"
|
||||
msgstr "Quitar de los favoritos"
|
||||
|
||||
#: ../js/ui/appDisplay.js:568
|
||||
#: ../js/ui/appDisplay.js:577
|
||||
msgid "Add to Favorites"
|
||||
msgstr "Añadir a los favoritos"
|
||||
|
||||
@ -361,118 +384,194 @@ msgstr "Se ha quitado %s de sus favoritos."
|
||||
msgid "Remove"
|
||||
msgstr "Quitar"
|
||||
|
||||
#: ../js/ui/docDisplay.js:494
|
||||
#: ../js/ui/docDisplay.js:18
|
||||
msgid "RECENT ITEMS"
|
||||
msgstr "ELEMENTOS RECIENTES"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:552
|
||||
#: ../js/ui/endSessionDialog.js:63
|
||||
#, c-format
|
||||
msgid "Log Out %s"
|
||||
msgstr "Cerrar la sesión %s"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:64 ../js/ui/endSessionDialog.js:69
|
||||
msgid "Log Out"
|
||||
msgstr "Cerrar la sesión"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:65
|
||||
msgid "Click Log Out to quit these applications and log out of the system."
|
||||
msgstr ""
|
||||
"Pulse «Cerrar la sesión» para salir de esas aplicaciones y cerrar la sesión "
|
||||
"del sistema."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:66
|
||||
#, c-format
|
||||
msgid "%s will be logged out automatically in %d seconds."
|
||||
msgstr "La sesión de %s se cerrará automáticamente en %d segundos."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:67
|
||||
#, c-format
|
||||
msgid "You will be logged out automatically in %d seconds."
|
||||
msgstr "Su sesión se cerrará automáticamente en %d segundos."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:68
|
||||
msgid "Logging out of the system."
|
||||
msgstr "Cerrando la sesión."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:74 ../js/ui/endSessionDialog.js:78
|
||||
msgid "Shut Down"
|
||||
msgstr "Apagar"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:75
|
||||
msgid "Click Shut Down to quit these applications and shut down the system."
|
||||
msgstr "Pulse «Apagar» para salir de esas aplicaciones y apagar el sistema."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:76
|
||||
#, c-format
|
||||
msgid "The system will shut down automatically in %d seconds."
|
||||
msgstr "El sistema se apagará automáticamente en %d segundo."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:77
|
||||
msgid "Shutting down the system."
|
||||
msgstr "Apagando el sistema."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:84 ../js/ui/endSessionDialog.js:88
|
||||
msgid "Restart"
|
||||
msgstr "Reiniciar"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:85
|
||||
msgid "Click Restart to quit these applications and restart the system."
|
||||
msgstr ""
|
||||
"Pulse «Reiniciar» para salir de esas aplicaciones y reiniciar el sistema."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:86
|
||||
#, c-format
|
||||
msgid "The system will restart automatically in %d seconds."
|
||||
msgstr "El sistema se reiniciará automáticamente en %d segundos."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:87
|
||||
msgid "Restarting the system."
|
||||
msgstr "Reiniciando el sistema."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:395
|
||||
msgid "Confirm"
|
||||
msgstr "Confirmar"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:400 ../js/ui/status/bluetooth.js:470
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:556
|
||||
msgid "No extensions installed"
|
||||
msgstr "No hay extensiones instaladas"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:589
|
||||
#: ../js/ui/lookingGlass.js:593
|
||||
msgid "Enabled"
|
||||
msgstr "Activado"
|
||||
|
||||
#. translators:
|
||||
#. * The device has been disabled
|
||||
#: ../js/ui/lookingGlass.js:591 ../src/gvc/gvc-mixer-control.c:1087
|
||||
#: ../js/ui/lookingGlass.js:595 ../src/gvc/gvc-mixer-control.c:1087
|
||||
msgid "Disabled"
|
||||
msgstr "Desactivado"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:593
|
||||
#: ../js/ui/lookingGlass.js:597
|
||||
msgid "Error"
|
||||
msgstr "Error"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:595
|
||||
#: ../js/ui/lookingGlass.js:599
|
||||
msgid "Out of date"
|
||||
msgstr "Caducado"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:620
|
||||
#: ../js/ui/lookingGlass.js:624
|
||||
msgid "View Source"
|
||||
msgstr "Ver fuente"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:626
|
||||
#: ../js/ui/lookingGlass.js:630
|
||||
msgid "Web Page"
|
||||
msgstr "Página web"
|
||||
|
||||
#: ../js/ui/overview.js:96
|
||||
#: ../js/ui/messageTray.js:1765
|
||||
msgid "System Information"
|
||||
msgstr "Información del sistema"
|
||||
|
||||
#: ../js/ui/overview.js:88
|
||||
msgid "Undo"
|
||||
msgstr "Deshacer"
|
||||
|
||||
#: ../js/ui/overview.js:158
|
||||
#: ../js/ui/overview.js:159
|
||||
msgid "Windows"
|
||||
msgstr "Ventanas"
|
||||
|
||||
#: ../js/ui/overview.js:161
|
||||
#: ../js/ui/overview.js:162
|
||||
msgid "Applications"
|
||||
msgstr "Aplicaciones"
|
||||
|
||||
#. TODO - _quit() doesn't really work on apps in state STARTING yet
|
||||
#: ../js/ui/panel.js:476
|
||||
#: ../js/ui/panel.js:483
|
||||
#, c-format
|
||||
msgid "Quit %s"
|
||||
msgstr "Salir de %s"
|
||||
|
||||
#. Translators: This is the time format with date used
|
||||
#. in 24-hour mode.
|
||||
#: ../js/ui/panel.js:561
|
||||
#: ../js/ui/panel.js:568
|
||||
msgid "%a %b %e, %R:%S"
|
||||
msgstr "%a %e de %b, %R:%S"
|
||||
|
||||
#: ../js/ui/panel.js:562
|
||||
#: ../js/ui/panel.js:569
|
||||
msgid "%a %b %e, %R"
|
||||
msgstr "%a %e de %b, %R"
|
||||
|
||||
#. Translators: This is the time format without date used
|
||||
#. in 24-hour mode.
|
||||
#: ../js/ui/panel.js:566
|
||||
#: ../js/ui/panel.js:573
|
||||
msgid "%a %R:%S"
|
||||
msgstr "%a %R:%S"
|
||||
|
||||
#: ../js/ui/panel.js:567
|
||||
#: ../js/ui/panel.js:574
|
||||
msgid "%a %R"
|
||||
msgstr "%a %R"
|
||||
|
||||
#. Translators: This is a time format with date used
|
||||
#. for AM/PM.
|
||||
#: ../js/ui/panel.js:574
|
||||
#: ../js/ui/panel.js:581
|
||||
msgid "%a %b %e, %l:%M:%S %p"
|
||||
msgstr "%a %e de %b, %H:%M:%S"
|
||||
|
||||
#: ../js/ui/panel.js:575
|
||||
#: ../js/ui/panel.js:582
|
||||
msgid "%a %b %e, %l:%M %p"
|
||||
msgstr "%a %e de %b, %H:%M"
|
||||
|
||||
#. Translators: This is a time format without date used
|
||||
#. for AM/PM.
|
||||
#: ../js/ui/panel.js:579
|
||||
#: ../js/ui/panel.js:586
|
||||
msgid "%a %l:%M:%S %p"
|
||||
msgstr "%a %H:%M:%S"
|
||||
|
||||
#: ../js/ui/panel.js:580
|
||||
#: ../js/ui/panel.js:587
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %H:%M"
|
||||
|
||||
#. Button on the left side of the panel.
|
||||
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
|
||||
#: ../js/ui/panel.js:725
|
||||
#: ../js/ui/panel.js:732
|
||||
msgid "Activities"
|
||||
msgstr "Actividades"
|
||||
|
||||
#: ../js/ui/placeDisplay.js:111
|
||||
#: ../js/ui/placeDisplay.js:106
|
||||
#, c-format
|
||||
msgid "Failed to unmount '%s'"
|
||||
msgstr "Falló al desmontar «%s»"
|
||||
|
||||
#: ../js/ui/placeDisplay.js:114
|
||||
#: ../js/ui/placeDisplay.js:109
|
||||
msgid "Retry"
|
||||
msgstr "Reintentar"
|
||||
|
||||
#: ../js/ui/placeDisplay.js:159
|
||||
#: ../js/ui/placeDisplay.js:150
|
||||
msgid "Connect to..."
|
||||
msgstr "Conectar a…"
|
||||
|
||||
#: ../js/ui/placeDisplay.js:558
|
||||
#: ../js/ui/placeDisplay.js:386
|
||||
msgid "PLACES & DEVICES"
|
||||
msgstr "LUGARES Y DISPOSITIVOS"
|
||||
|
||||
@ -485,84 +584,79 @@ msgstr "LUGARES Y DISPOSITIVOS"
|
||||
msgid "toggle-switch-us"
|
||||
msgstr "toggle-switch-intl"
|
||||
|
||||
#: ../js/ui/runDialog.js:233
|
||||
#: ../js/ui/runDialog.js:209
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Introduzca un comando:"
|
||||
|
||||
#: ../js/ui/runDialog.js:378
|
||||
#, c-format
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "Falló la ejecución de «%s»:"
|
||||
|
||||
#: ../js/ui/statusMenu.js:101
|
||||
#: ../js/ui/statusMenu.js:102
|
||||
msgid "Available"
|
||||
msgstr "Disponible"
|
||||
|
||||
#: ../js/ui/statusMenu.js:106
|
||||
#: ../js/ui/statusMenu.js:107
|
||||
msgid "Busy"
|
||||
msgstr "Ocupado"
|
||||
|
||||
#: ../js/ui/statusMenu.js:114
|
||||
#: ../js/ui/statusMenu.js:115
|
||||
msgid "My Account"
|
||||
msgstr "Mi cuenta"
|
||||
|
||||
#: ../js/ui/statusMenu.js:118
|
||||
#: ../js/ui/statusMenu.js:119
|
||||
msgid "System Settings"
|
||||
msgstr "Configuración del sistema"
|
||||
|
||||
#: ../js/ui/statusMenu.js:125
|
||||
#: ../js/ui/statusMenu.js:126
|
||||
msgid "Lock Screen"
|
||||
msgstr "Bloquear la pantalla"
|
||||
|
||||
#: ../js/ui/statusMenu.js:129
|
||||
#: ../js/ui/statusMenu.js:130
|
||||
msgid "Switch User"
|
||||
msgstr "Cambiar de usuario"
|
||||
|
||||
#: ../js/ui/statusMenu.js:134
|
||||
#: ../js/ui/statusMenu.js:135
|
||||
msgid "Log Out..."
|
||||
msgstr "Salir…"
|
||||
msgstr "Cerrar la sesión…"
|
||||
|
||||
#: ../js/ui/statusMenu.js:141
|
||||
#: ../js/ui/statusMenu.js:142
|
||||
msgid "Suspend..."
|
||||
msgstr "Suspender…"
|
||||
|
||||
#: ../js/ui/statusMenu.js:145
|
||||
#: ../js/ui/statusMenu.js:146
|
||||
msgid "Shut Down..."
|
||||
msgstr "Apagar…"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:82
|
||||
#: ../js/ui/status/accessibility.js:83
|
||||
msgid "Zoom"
|
||||
msgstr "Ampliación"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:88
|
||||
#: ../js/ui/status/accessibility.js:89
|
||||
msgid "Screen Reader"
|
||||
msgstr "Lector de pantalla"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:91
|
||||
#: ../js/ui/status/accessibility.js:92
|
||||
msgid "Screen Keyboard"
|
||||
msgstr "Teclado en pantalla"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:94
|
||||
#: ../js/ui/status/accessibility.js:95
|
||||
msgid "Visual Alerts"
|
||||
msgstr "Alertas visuales"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:97
|
||||
#: ../js/ui/status/accessibility.js:98
|
||||
msgid "Sticky Keys"
|
||||
msgstr "Teclas persistentes"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:100
|
||||
#: ../js/ui/status/accessibility.js:101
|
||||
msgid "Slow Keys"
|
||||
msgstr "Teclas lentas"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:103
|
||||
#: ../js/ui/status/accessibility.js:104
|
||||
msgid "Bounce Keys"
|
||||
msgstr "Rechazo de teclas"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:106
|
||||
#: ../js/ui/status/accessibility.js:107
|
||||
msgid "Mouse Keys"
|
||||
msgstr "Teclas del ratón"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:110
|
||||
#: ../js/ui/status/accessibility.js:111
|
||||
msgid "Universal Access Settings"
|
||||
msgstr "Preferencias del acceso universal"
|
||||
|
||||
@ -574,7 +668,7 @@ msgstr "Contraste alto"
|
||||
msgid "Large Text"
|
||||
msgstr "<b>Texto:</b>"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:42 ../js/ui/status/bluetooth.js:234
|
||||
#: ../js/ui/status/bluetooth.js:42 ../js/ui/status/bluetooth.js:241
|
||||
msgid "Bluetooth"
|
||||
msgstr "Bluetooth"
|
||||
|
||||
@ -590,109 +684,109 @@ msgstr "Enviar archivos al dispositivo…"
|
||||
msgid "Setup a New Device..."
|
||||
msgstr "Configurar un dispositivo nuevo…"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:94
|
||||
#: ../js/ui/status/bluetooth.js:95
|
||||
msgid "Bluetooth Settings"
|
||||
msgstr "Configuración de Bluetooth"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:185
|
||||
#: ../js/ui/status/bluetooth.js:192
|
||||
msgid "Connection"
|
||||
msgstr "Conexión"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:221
|
||||
#: ../js/ui/status/bluetooth.js:228
|
||||
msgid "Send Files..."
|
||||
msgstr "Enviar archivos…"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:226
|
||||
#: ../js/ui/status/bluetooth.js:233
|
||||
msgid "Browse Files..."
|
||||
msgstr "Examinar archivos…"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:235
|
||||
#: ../js/ui/status/bluetooth.js:242
|
||||
msgid "Error browsing device"
|
||||
msgstr "Error al examinar el dispositivo"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:236
|
||||
#: ../js/ui/status/bluetooth.js:243
|
||||
#, c-format
|
||||
msgid "The requested device cannot be browsed, error is '%s'"
|
||||
msgstr "No se puede examinar el dispositivo solicitado, el error es «%s»"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:244
|
||||
#: ../js/ui/status/bluetooth.js:251
|
||||
msgid "Keyboard Settings"
|
||||
msgstr "Configuración del teclado"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:249
|
||||
#: ../js/ui/status/bluetooth.js:256
|
||||
msgid "Mouse Settings"
|
||||
msgstr "Ajustes del ratón…"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:256 ../js/ui/status/volume.js:62
|
||||
#: ../js/ui/status/bluetooth.js:263 ../js/ui/status/volume.js:63
|
||||
msgid "Sound Settings"
|
||||
msgstr "Configuración del sonido"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:327 ../js/ui/status/bluetooth.js:361
|
||||
#: ../js/ui/status/bluetooth.js:401 ../js/ui/status/bluetooth.js:434
|
||||
#: ../js/ui/status/bluetooth.js:337 ../js/ui/status/bluetooth.js:371
|
||||
#: ../js/ui/status/bluetooth.js:411 ../js/ui/status/bluetooth.js:444
|
||||
msgid "Bluetooth Agent"
|
||||
msgstr "Agente Bluetooth"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:362
|
||||
#: ../js/ui/status/bluetooth.js:372
|
||||
#, c-format
|
||||
msgid "Authorization request from %s"
|
||||
msgstr "Solicitud de autorización de %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:368
|
||||
#: ../js/ui/status/bluetooth.js:378
|
||||
#, c-format
|
||||
msgid "Device %s wants access to the service '%s'"
|
||||
msgstr "El dispositivo %s quiere acceder al servicio «%s»"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:370
|
||||
#: ../js/ui/status/bluetooth.js:380
|
||||
msgid "Always grant access"
|
||||
msgstr "Conceder acceso siempre"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:371
|
||||
#: ../js/ui/status/bluetooth.js:381
|
||||
msgid "Grant this time only"
|
||||
msgstr "Conceder sólo esta vez"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:372
|
||||
#: ../js/ui/status/bluetooth.js:382
|
||||
msgid "Reject"
|
||||
msgstr "Rechazar"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:402
|
||||
#: ../js/ui/status/bluetooth.js:412
|
||||
#, c-format
|
||||
msgid "Pairing confirmation for %s"
|
||||
msgstr "Confirmación de emparejamiento para «%s»"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:408 ../js/ui/status/bluetooth.js:442
|
||||
#: ../js/ui/status/bluetooth.js:418 ../js/ui/status/bluetooth.js:452
|
||||
#, c-format
|
||||
msgid "Device %s wants to pair with this computer"
|
||||
msgstr "El dispositivo «%s» quiere emparejarse con este equipo"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:409
|
||||
#: ../js/ui/status/bluetooth.js:419
|
||||
#, c-format
|
||||
msgid "Please confirm whether the PIN '%s' matches the one on the device."
|
||||
msgstr "Confirme que el PIN mostrado en «%s» coincide con el del dispositivo."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:411
|
||||
#: ../js/ui/status/bluetooth.js:421
|
||||
msgid "Matches"
|
||||
msgstr "Coincide"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:412
|
||||
#: ../js/ui/status/bluetooth.js:422
|
||||
msgid "Does not match"
|
||||
msgstr "No coincide"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:435
|
||||
#: ../js/ui/status/bluetooth.js:445
|
||||
#, c-format
|
||||
msgid "Pairing request for %s"
|
||||
msgstr "Solicitud de emparejamiento para «%s»"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:443
|
||||
#: ../js/ui/status/bluetooth.js:453
|
||||
msgid "Please enter the PIN mentioned on the device."
|
||||
msgstr "Introduzca el PIN mencionado en el dispositivo."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:459
|
||||
#: ../js/ui/status/bluetooth.js:469
|
||||
msgid "OK"
|
||||
msgstr "Aceptar"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:460
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
#: ../js/ui/status/keyboard.js:78
|
||||
msgid "Localization Settings"
|
||||
msgstr "Configuración regional"
|
||||
|
||||
#: ../js/ui/status/power.js:85
|
||||
msgid "Power Settings"
|
||||
@ -730,78 +824,78 @@ msgid_plural "%d minutes remaining"
|
||||
msgstr[0] "Queda %d minuto"
|
||||
msgstr[1] "Queda %d minutos"
|
||||
|
||||
#: ../js/ui/status/power.js:237
|
||||
#: ../js/ui/status/power.js:235
|
||||
msgid "AC adapter"
|
||||
msgstr "Adaptador de corriente"
|
||||
|
||||
#: ../js/ui/status/power.js:239
|
||||
#: ../js/ui/status/power.js:237
|
||||
msgid "Laptop battery"
|
||||
msgstr "Batería del portátil"
|
||||
|
||||
#: ../js/ui/status/power.js:241
|
||||
#: ../js/ui/status/power.js:239
|
||||
msgid "UPS"
|
||||
msgstr "SAI"
|
||||
|
||||
#: ../js/ui/status/power.js:243
|
||||
#: ../js/ui/status/power.js:241
|
||||
msgid "Monitor"
|
||||
msgstr "Monitor"
|
||||
|
||||
#: ../js/ui/status/power.js:245
|
||||
#: ../js/ui/status/power.js:243
|
||||
msgid "Mouse"
|
||||
msgstr "Ratón"
|
||||
|
||||
#: ../js/ui/status/power.js:247
|
||||
#: ../js/ui/status/power.js:245
|
||||
msgid "Keyboard"
|
||||
msgstr "Teclado"
|
||||
|
||||
#: ../js/ui/status/power.js:249
|
||||
#: ../js/ui/status/power.js:247
|
||||
msgid "PDA"
|
||||
msgstr "PDA"
|
||||
|
||||
#: ../js/ui/status/power.js:251
|
||||
#: ../js/ui/status/power.js:249
|
||||
msgid "Cell phone"
|
||||
msgstr "Teléfono móvil"
|
||||
|
||||
#: ../js/ui/status/power.js:253
|
||||
#: ../js/ui/status/power.js:251
|
||||
msgid "Media player"
|
||||
msgstr "Reproductor multimedia"
|
||||
|
||||
#: ../js/ui/status/power.js:255
|
||||
#: ../js/ui/status/power.js:253
|
||||
msgid "Tablet"
|
||||
msgstr "Tableta"
|
||||
|
||||
#: ../js/ui/status/power.js:257
|
||||
#: ../js/ui/status/power.js:255
|
||||
msgid "Computer"
|
||||
msgstr "Equipo"
|
||||
|
||||
#: ../js/ui/status/power.js:259 ../src/shell-app-system.c:1012
|
||||
#: ../js/ui/status/power.js:257 ../src/shell-app-system.c:1012
|
||||
msgid "Unknown"
|
||||
msgstr "Desconocido"
|
||||
|
||||
#: ../js/ui/status/volume.js:41
|
||||
#: ../js/ui/status/volume.js:42
|
||||
msgid "Volume"
|
||||
msgstr "Volumen"
|
||||
|
||||
#: ../js/ui/status/volume.js:54
|
||||
#: ../js/ui/status/volume.js:55
|
||||
msgid "Microphone"
|
||||
msgstr "Micrófono"
|
||||
|
||||
#: ../js/ui/telepathyClient.js:560
|
||||
#: ../js/ui/telepathyClient.js:561
|
||||
#, c-format
|
||||
msgid "%s is online."
|
||||
msgstr "%s está conectado/a."
|
||||
|
||||
#: ../js/ui/telepathyClient.js:565
|
||||
#: ../js/ui/telepathyClient.js:566
|
||||
#, c-format
|
||||
msgid "%s is offline."
|
||||
msgstr "%s está desconectado/a."
|
||||
|
||||
#: ../js/ui/telepathyClient.js:568
|
||||
#: ../js/ui/telepathyClient.js:569
|
||||
#, c-format
|
||||
msgid "%s is away."
|
||||
msgstr "%s está ausente."
|
||||
|
||||
#: ../js/ui/telepathyClient.js:571
|
||||
#: ../js/ui/telepathyClient.js:572
|
||||
#, c-format
|
||||
msgid "%s is busy."
|
||||
msgstr "%s está ocupado/a."
|
||||
@ -809,7 +903,7 @@ msgstr "%s está ocupado/a."
|
||||
#. Translators: this is a time format string followed by a date.
|
||||
#. If applicable, replace %X with a strftime format valid for your
|
||||
#. locale, without seconds.
|
||||
#: ../js/ui/telepathyClient.js:665
|
||||
#: ../js/ui/telepathyClient.js:666
|
||||
#, no-c-format
|
||||
msgid "Sent at %X on %A"
|
||||
msgstr "Enviado a las %X el %A"
|
||||
@ -828,14 +922,14 @@ msgstr "%s finalizó su lanzamiento"
|
||||
msgid "'%s' is ready"
|
||||
msgstr "«%s» está preparado"
|
||||
|
||||
#: ../js/ui/workspacesView.js:244
|
||||
#: ../js/ui/workspacesView.js:243
|
||||
msgid ""
|
||||
"Can't add a new workspace because maximum workspaces limit has been reached."
|
||||
msgstr ""
|
||||
"No se puede añadir un área de trabajo nueva porque se ha llegado al límite "
|
||||
"de áreas de trabajo."
|
||||
|
||||
#: ../js/ui/workspacesView.js:260
|
||||
#: ../js/ui/workspacesView.js:259
|
||||
msgid "Can't remove the first workspace."
|
||||
msgstr "No se puede quitar el primer área de trabajo."
|
||||
|
||||
@ -861,32 +955,32 @@ msgstr[1] "%u entradas"
|
||||
msgid "System Sounds"
|
||||
msgstr "Sonidos del sistema"
|
||||
|
||||
#: ../src/shell-global.c:1156
|
||||
#: ../src/shell-global.c:1365
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Hace menos de un minuto"
|
||||
|
||||
#: ../src/shell-global.c:1160
|
||||
#: ../src/shell-global.c:1369
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "Hace %d minuto"
|
||||
msgstr[1] "Hace %d minutos"
|
||||
|
||||
#: ../src/shell-global.c:1165
|
||||
#: ../src/shell-global.c:1374
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "Hace %d hora"
|
||||
msgstr[1] "Hace %d horas"
|
||||
|
||||
#: ../src/shell-global.c:1170
|
||||
#: ../src/shell-global.c:1379
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "Hace %d día"
|
||||
msgstr[1] "Hace %d días"
|
||||
|
||||
#: ../src/shell-global.c:1175
|
||||
#: ../src/shell-global.c:1384
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
@ -1016,12 +1110,6 @@ msgstr "%1$s: %2$s"
|
||||
#~ msgid "Invisible"
|
||||
#~ msgstr "Invisible"
|
||||
|
||||
#~ msgid "Restart..."
|
||||
#~ msgstr "Reiniciar…"
|
||||
|
||||
#~ msgid "Account Information..."
|
||||
#~ msgstr "Información de la cuenta…"
|
||||
|
||||
#~ msgid "ON"
|
||||
#~ msgstr "ENCENDIDO"
|
||||
|
||||
|
102
po/et.po
102
po/et.po
@ -13,14 +13,14 @@ msgstr ""
|
||||
"Project-Id-Version: gnome-shell MASTER\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
|
||||
"shell&component=general\n"
|
||||
"POT-Creation-Date: 2011-01-04 16:17+0000\n"
|
||||
"PO-Revision-Date: 2011-01-09 11:20+0200\n"
|
||||
"Last-Translator: Ivar Smolin <okul@linux.ee>\n"
|
||||
"POT-Creation-Date: 2011-01-29 18:34+0000\n"
|
||||
"PO-Revision-Date: 2011-02-01 13:51+0300\n"
|
||||
"Last-Translator: Mattias Põldaru <mahfiaz gmail com>\n"
|
||||
"Language-Team: Estonian <gnome-et@linux.ee>\n"
|
||||
"Language: et\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: et\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Poedit-Language: Estonian\n"
|
||||
"X-Poedit-Country: Estonia\n"
|
||||
@ -70,6 +70,7 @@ msgstr "Kui määratud, kuvatakse kalendris kuupäeva ISO nädalavormingus."
|
||||
msgid "List of desktop file IDs for favorite applications"
|
||||
msgstr "Lemmikrakenduste töölauafailide ID-de loend"
|
||||
|
||||
#, no-c-format
|
||||
msgid ""
|
||||
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
|
||||
"used for gst-launch. The pipeline should have an unconnected sink pad where "
|
||||
@ -78,7 +79,9 @@ msgid ""
|
||||
"pipeline can also take care of its own output - this might be used to send "
|
||||
"the output to an icecast server via shout2send or similar. When unset or set "
|
||||
"to an empty value, the default pipeline will be used. This is currently "
|
||||
"'videorate ! theoraenc ! oggmux' and records to Ogg Theora."
|
||||
"'videorate ! vp8enc quality=10 speed=2 threads=%T ! queue ! webmmux' and "
|
||||
"records to WEBM using the VP8 codec. %T is used as a placeholder for a guess "
|
||||
"at the optimal thread count on the system."
|
||||
msgstr ""
|
||||
|
||||
msgid "Show date in clock"
|
||||
@ -126,6 +129,9 @@ msgstr "Keelatavate laienduste UUID-d"
|
||||
msgid "Whether to collect stats about applications usage"
|
||||
msgstr ""
|
||||
|
||||
msgid "disabled OpenSearch providers"
|
||||
msgstr ""
|
||||
|
||||
msgid "Clip the crosshairs at the center"
|
||||
msgstr "Niitristi keskel on auk"
|
||||
|
||||
@ -236,6 +242,21 @@ msgstr ""
|
||||
msgid "Width of the vertical and horizontal lines that make up the crosshairs."
|
||||
msgstr "Niitristi moodustavate püst- ja rõhtjoone laius"
|
||||
|
||||
msgid "Command not found"
|
||||
msgstr ""
|
||||
|
||||
#. Replace "Error invoking GLib.shell_parse_argv: " with
|
||||
#. something nicer
|
||||
msgid "Could not parse command:"
|
||||
msgstr "Käsku pole võimalik analüüsida:"
|
||||
|
||||
msgid "No such application"
|
||||
msgstr "Sellist rakendust ei ole"
|
||||
|
||||
#, c-format
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "'%s' käivitamine nurjus:"
|
||||
|
||||
#. Translators: Filter to display all applications
|
||||
msgid "All"
|
||||
msgstr "Kõik"
|
||||
@ -269,6 +290,61 @@ msgstr "Eemalda"
|
||||
msgid "RECENT ITEMS"
|
||||
msgstr "Hiljutised dokumendid"
|
||||
|
||||
#, c-format
|
||||
msgid "Log Out %s"
|
||||
msgstr "Logi %s välja"
|
||||
|
||||
msgid "Log Out"
|
||||
msgstr "Logi välja"
|
||||
|
||||
msgid "Click Log Out to quit these applications and log out of the system."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "%s will be logged out automatically in %d seconds."
|
||||
msgstr "%s logitakse %d sekundi pärast automaatselt välja."
|
||||
|
||||
#, c-format
|
||||
msgid "You will be logged out automatically in %d seconds."
|
||||
msgstr "Sind logitakse %d sekundi pärast automaatselt välja."
|
||||
|
||||
msgid "Logging out of the system."
|
||||
msgstr "Süsteemist väljalogimine"
|
||||
|
||||
msgid "Shut Down"
|
||||
msgstr "Lülita välja"
|
||||
|
||||
msgid "Click Shut Down to quit these applications and shut down the system."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "The system will shut down automatically in %d seconds."
|
||||
msgstr "%d sekundi pärast lülitub süsteem automaatselt välja."
|
||||
|
||||
msgid "Shutting down the system."
|
||||
msgstr "Süsteemi väljalülitamine."
|
||||
|
||||
msgid "Restart"
|
||||
msgstr "Taaskäivita"
|
||||
|
||||
msgid "Click Restart to quit these applications and restart the system."
|
||||
msgstr ""
|
||||
"Nende rakenduste sulgemiseks ja süsteemi taaskäivitamiseks klõpsa "
|
||||
"\"Taaskäivita\"."
|
||||
|
||||
#, c-format
|
||||
msgid "The system will restart automatically in %d seconds."
|
||||
msgstr "Süsteem taaskäivitatakse automaatselt %d sekundi pärast."
|
||||
|
||||
msgid "Restarting the system."
|
||||
msgstr "Süsteemi taaskäivitamine."
|
||||
|
||||
msgid "Confirm"
|
||||
msgstr "Kinnita"
|
||||
|
||||
msgid "Cancel"
|
||||
msgstr "Katkesta"
|
||||
|
||||
msgid "No extensions installed"
|
||||
msgstr "Ühtegi laiendust pole paigaldatud"
|
||||
|
||||
@ -292,6 +368,9 @@ msgstr "Kuva lähtekoodi"
|
||||
msgid "Web Page"
|
||||
msgstr "Veebileht"
|
||||
|
||||
msgid "System Information"
|
||||
msgstr "Süsteemi andmed"
|
||||
|
||||
msgid "Undo"
|
||||
msgstr "Võta tagasi"
|
||||
|
||||
@ -367,10 +446,6 @@ msgstr "toggle-switch-intl"
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Palun sisesta käsk:"
|
||||
|
||||
#, c-format
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "'%s' käivitamine nurjus:"
|
||||
|
||||
msgid "Available"
|
||||
msgstr "Saadaval"
|
||||
|
||||
@ -393,7 +468,7 @@ msgid "Log Out..."
|
||||
msgstr "Logi välja..."
|
||||
|
||||
msgid "Suspend..."
|
||||
msgstr ""
|
||||
msgstr "Peata..."
|
||||
|
||||
msgid "Shut Down..."
|
||||
msgstr "Lülita välja..."
|
||||
@ -519,8 +594,8 @@ msgstr "Palun sisesta seadme poolt öeldav PIN-kood."
|
||||
msgid "OK"
|
||||
msgstr "Olgu"
|
||||
|
||||
msgid "Cancel"
|
||||
msgstr "Katkesta"
|
||||
msgid "Localization Settings"
|
||||
msgstr "Lokaliseerimissätted"
|
||||
|
||||
msgid "Power Settings"
|
||||
msgstr "Toitesätted..."
|
||||
@ -751,6 +826,3 @@ msgstr "%1$s: %2$s"
|
||||
|
||||
#~ msgid "Invisible"
|
||||
#~ msgstr "Nähtamatu"
|
||||
|
||||
#~ msgid "Account Information..."
|
||||
#~ msgstr "Konto andmed..."
|
||||
|
426
po/gl.po
426
po/gl.po
@ -10,8 +10,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-01-06 23:28+0100\n"
|
||||
"PO-Revision-Date: 2011-01-06 23:33+0100\n"
|
||||
"POT-Creation-Date: 2011-02-01 02:40+0100\n"
|
||||
"PO-Revision-Date: 2011-02-01 02:44+0100\n"
|
||||
"Last-Translator: Fran Diéguez <frandieguez@ubuntu.com>\n"
|
||||
"Language-Team: Galician <gnome-gl-list@gnome.org>\n"
|
||||
"Language: gl\n"
|
||||
@ -79,7 +79,8 @@ msgstr "Se é verdadeiro, móstrase a data da semana ISO no calendario."
|
||||
msgid "List of desktop file IDs for favorite applications"
|
||||
msgstr "Mostra os ID de ficheiros desktop para os aplicativos preferidos"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:11
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:12
|
||||
#, no-c-format
|
||||
msgid ""
|
||||
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
|
||||
"used for gst-launch. The pipeline should have an unconnected sink pad where "
|
||||
@ -88,31 +89,35 @@ msgid ""
|
||||
"pipeline can also take care of its own output - this might be used to send "
|
||||
"the output to an icecast server via shout2send or similar. When unset or set "
|
||||
"to an empty value, the default pipeline will be used. This is currently "
|
||||
"'videorate ! theoraenc ! oggmux' and records to Ogg Theora."
|
||||
"'videorate ! vp8enc quality=10 speed=2 threads=%T ! queue ! webmmux' and "
|
||||
"records to WEBM using the VP8 codec. %T is used as a placeholder for a guess "
|
||||
"at the optimal thread count on the system."
|
||||
msgstr ""
|
||||
"Estabelece a tubería GStreamer usada para codificar gravacións. Segue a "
|
||||
"sintaxe usada para gst-launch. A tubería debería ter un sumideiro («sink») "
|
||||
"de ensamblaxe/desensamblaxe onde o vídeo que se está gravando grávase. "
|
||||
"Xeralmente terá unha orixe de ensamblado/desensamblado; a saída dese punto "
|
||||
"escribirase no ficheiro de saída. Porén, a tubería tamén pode tomar parte na "
|
||||
"súa propia saída; isto pódese usar para enviar a saída a un servidor "
|
||||
"«icecast» a través de shout2send ou similar. Cando non está estabelecido ou "
|
||||
"está a un valor baleiro, usarase a tubería predeterminada. Actualmente é "
|
||||
"«videorate ! theoraenc ! oggmux» e grava en Ogg Theora."
|
||||
"de ensamblaxe/desensamblaxe onde o vídeo gravado se grava. Xeralmente terá "
|
||||
"unha orixe de ensamblado/desensamblado; a saída dese punto escribirase no "
|
||||
"ficheiro de saída. Porén, a tubería tamén pode tomar parte na súa propia "
|
||||
"saída; isto pódese usar para enviar a saída a un servidor «icecast» a través "
|
||||
"de shout2send ou similar. Cando non está estabelecido ou está a un valor "
|
||||
"baleiro, usarase a tubería predeterminada. Actualmente é «! vp8enc "
|
||||
"quality=10 speed=2 threads=%T ! queue ! webmmux'» e grava en WEBM usando o "
|
||||
"códec VP8. Úsase %T como suposición para o número de fillos óptimos no "
|
||||
"sistema."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:12
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:13
|
||||
msgid "Show date in clock"
|
||||
msgstr "Mostrar a data no reloxo"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:13
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:14
|
||||
msgid "Show the week date in the calendar"
|
||||
msgstr "Mostrar a data da semana no calendario"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:14
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:15
|
||||
msgid "Show time with seconds"
|
||||
msgstr "Mostrar a hora con segundos"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:15
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:16
|
||||
msgid ""
|
||||
"The applications corresponding to these identifiers will be displayed in the "
|
||||
"favorites area."
|
||||
@ -120,7 +125,7 @@ msgstr ""
|
||||
"Os aplicativos que corresponden a estes identificadores mostraranse na área "
|
||||
"de preferidos."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:16
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:17
|
||||
msgid ""
|
||||
"The filename for recorded screencasts will be a unique filename based on the "
|
||||
"current date, and use this extension. It should be changed when recording to "
|
||||
@ -130,7 +135,7 @@ msgstr ""
|
||||
"baseado na data actual e usa esta extensión. Debería cambiar ao grabar nun "
|
||||
"formato de contedor diferente."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:17
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:18
|
||||
msgid ""
|
||||
"The framerate of the resulting screencast recordered by GNOME Shell's "
|
||||
"screencast recorder in frames-per-second."
|
||||
@ -138,11 +143,11 @@ msgstr ""
|
||||
"A taxa de marcos do screencast resultante grabado polo grabador de "
|
||||
"screencasts de GNOME Shell en marcos-por-segundo."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:18
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:19
|
||||
msgid "The gstreamer pipeline used to encode the screencast"
|
||||
msgstr "A tubería de gstreamer usada para codificar o screencast"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:19
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:20
|
||||
msgid ""
|
||||
"The shell normally monitors active applications in order to present the most "
|
||||
"used ones (e.g. in launchers). While this data will be kept private, you may "
|
||||
@ -154,14 +159,18 @@ msgstr ""
|
||||
"privados, vostede pode desactivar isto por motivos de privacidade. Teña en "
|
||||
"conta que facendo isto non eliminará os datos gardados."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:20
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:21
|
||||
msgid "Uuids of extensions to disable"
|
||||
msgstr "Os Uuid das extensións a desactivar"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:21
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:22
|
||||
msgid "Whether to collect stats about applications usage"
|
||||
msgstr "Indica se recoller estatísticas sobre o uso dos aplicativos"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:23
|
||||
msgid "disabled OpenSearch providers"
|
||||
msgstr "fornecedores de OpenSearch desactivados"
|
||||
|
||||
#: ../data/org.gnome.accessibility.magnifier.gschema.xml.in.h:1
|
||||
msgid "Clip the crosshairs at the center"
|
||||
msgstr "Poñer o punto de mira no centro"
|
||||
@ -266,16 +275,16 @@ msgstr "Mostrar os contidos magnificados máis aló dos bordos do escritorio"
|
||||
|
||||
#: ../data/org.gnome.accessibility.magnifier.gschema.xml.in.h:16
|
||||
msgid "Show or hide crosshairs"
|
||||
msgstr "Mostrar ou agochar o punto de mira"
|
||||
msgstr "Mostrar ou ocultar o punto de mira"
|
||||
|
||||
#: ../data/org.gnome.accessibility.magnifier.gschema.xml.in.h:17
|
||||
msgid "Show or hide the magnifier"
|
||||
msgstr "Mostrar ou agochar o magnificador"
|
||||
msgstr "Mostrar ou ocultar o magnificador"
|
||||
|
||||
#: ../data/org.gnome.accessibility.magnifier.gschema.xml.in.h:18
|
||||
msgid "Show or hide the magnifier and all of its zoom regions."
|
||||
msgstr ""
|
||||
"Mostrar ou agochar o magnificador e todas as súas rexións de magnificación."
|
||||
"Mostrar ou ocultar o magnificador e todas as súas rexións de magnificación."
|
||||
|
||||
#: ../data/org.gnome.accessibility.magnifier.gschema.xml.in.h:19
|
||||
msgid ""
|
||||
@ -316,28 +325,47 @@ msgstr ""
|
||||
msgid "Width of the vertical and horizontal lines that make up the crosshairs."
|
||||
msgstr "Anchura das liñas verticais e horizontais que contén o punto de mira."
|
||||
|
||||
#: ../js/misc/util.js:86
|
||||
msgid "Command not found"
|
||||
msgstr "Orde non atopada"
|
||||
|
||||
#. Replace "Error invoking GLib.shell_parse_argv: " with
|
||||
#. something nicer
|
||||
#: ../js/misc/util.js:113
|
||||
msgid "Could not parse command:"
|
||||
msgstr "Non foi posíbel analizar a orde:"
|
||||
|
||||
#: ../js/misc/util.js:135
|
||||
msgid "No such application"
|
||||
msgstr "Non existe o aplicativo"
|
||||
|
||||
#: ../js/misc/util.js:148
|
||||
#, c-format
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "Produciuse un fallo na execución de «%s»:"
|
||||
|
||||
#. Translators: Filter to display all applications
|
||||
#: ../js/ui/appDisplay.js:155
|
||||
#: ../js/ui/appDisplay.js:164
|
||||
msgid "All"
|
||||
msgstr "Todos"
|
||||
|
||||
#: ../js/ui/appDisplay.js:236
|
||||
#: ../js/ui/appDisplay.js:245
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "APLICATIVOS"
|
||||
|
||||
#: ../js/ui/appDisplay.js:266
|
||||
#: ../js/ui/appDisplay.js:275
|
||||
msgid "PREFERENCES"
|
||||
msgstr "PREFERENCIAS"
|
||||
|
||||
#: ../js/ui/appDisplay.js:563
|
||||
#: ../js/ui/appDisplay.js:572
|
||||
msgid "New Window"
|
||||
msgstr "Xanela nova"
|
||||
|
||||
#: ../js/ui/appDisplay.js:567
|
||||
#: ../js/ui/appDisplay.js:576
|
||||
msgid "Remove from Favorites"
|
||||
msgstr "Eliminar dos favoritos"
|
||||
|
||||
#: ../js/ui/appDisplay.js:568
|
||||
#: ../js/ui/appDisplay.js:577
|
||||
msgid "Add to Favorites"
|
||||
msgstr "Engadir aos favoritos"
|
||||
|
||||
@ -355,118 +383,155 @@ msgstr "%s foi eliminado dos seus favoritos."
|
||||
msgid "Remove"
|
||||
msgstr "Eliminar"
|
||||
|
||||
#: ../js/ui/docDisplay.js:494
|
||||
#: ../js/ui/docDisplay.js:18
|
||||
msgid "RECENT ITEMS"
|
||||
msgstr "ELEMENTOS RECENTES"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:552
|
||||
#: ../js/ui/endSessionDialog.js:63
|
||||
#, c-format
|
||||
msgid "Log Out %s"
|
||||
msgstr "Saír da sesión de %s"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:64 ../js/ui/endSessionDialog.js:69
|
||||
msgid "Log Out"
|
||||
msgstr "Saír da sesión"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:65
|
||||
msgid "Click Log Out to quit these applications and log out of the system."
|
||||
msgstr ""
|
||||
"Prema sobre Saír da sesión para saír de estes aplicativos e pechar a sesión."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:66
|
||||
#, c-format
|
||||
msgid "%s will be logged out automatically in %d seconds."
|
||||
msgstr "Vaise pechar a sesión de %s de forma automática en %d segundos."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:67
|
||||
#, c-format
|
||||
msgid "You will be logged out automatically in %d seconds."
|
||||
msgstr "A súa sesión pecharase automaticamente en %d segundos."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:68
|
||||
msgid "Logging out of the system."
|
||||
msgstr "Saíndo da sesión."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:74 ../js/ui/endSessionDialog.js:78
|
||||
msgid "Shut Down"
|
||||
msgstr "Apagar"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:75
|
||||
msgid "Click Shut Down to quit these applications and shut down the system."
|
||||
msgstr ""
|
||||
"Prema sobre Apagar para saír de estes aplicativos e apagar o computador."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:76
|
||||
#, c-format
|
||||
msgid "The system will shut down automatically in %d seconds."
|
||||
msgstr "O computador apagarase automaticamente en %d segundos."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:77
|
||||
msgid "Shutting down the system."
|
||||
msgstr "Apagando o computador."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:84 ../js/ui/endSessionDialog.js:88
|
||||
msgid "Restart"
|
||||
msgstr "Reiniciar"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:85
|
||||
msgid "Click Restart to quit these applications and restart the system."
|
||||
msgstr ""
|
||||
"Prema sobre Reiniciar para saír de estes aplicativos e reiniciar o seu "
|
||||
"computador."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:86
|
||||
#, c-format
|
||||
msgid "The system will restart automatically in %d seconds."
|
||||
msgstr "O seu computador reiniciarase automaticamente en %d segundos."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:87
|
||||
msgid "Restarting the system."
|
||||
msgstr "Reiniciando o computador."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:395
|
||||
msgid "Confirm"
|
||||
msgstr "Confirmar"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:400 ../js/ui/status/bluetooth.js:470
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:556
|
||||
msgid "No extensions installed"
|
||||
msgstr "Non hai ningunha extensión instalada"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:589
|
||||
#: ../js/ui/lookingGlass.js:593
|
||||
msgid "Enabled"
|
||||
msgstr "Activado"
|
||||
|
||||
#. translators:
|
||||
#. * The device has been disabled
|
||||
#: ../js/ui/lookingGlass.js:591 ../src/gvc/gvc-mixer-control.c:1087
|
||||
#: ../js/ui/lookingGlass.js:595 ../src/gvc/gvc-mixer-control.c:1087
|
||||
msgid "Disabled"
|
||||
msgstr "Desactivado"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:593
|
||||
#: ../js/ui/lookingGlass.js:597
|
||||
msgid "Error"
|
||||
msgstr "Erro"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:595
|
||||
#: ../js/ui/lookingGlass.js:599
|
||||
msgid "Out of date"
|
||||
msgstr "Desactualizado"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:620
|
||||
#: ../js/ui/lookingGlass.js:624
|
||||
msgid "View Source"
|
||||
msgstr "Ver fonte"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:626
|
||||
#: ../js/ui/lookingGlass.js:630
|
||||
msgid "Web Page"
|
||||
msgstr "Páxina web"
|
||||
|
||||
#: ../js/ui/overview.js:101
|
||||
#: ../js/ui/messageTray.js:1786
|
||||
msgid "System Information"
|
||||
msgstr "Información do sistema"
|
||||
|
||||
#: ../js/ui/overview.js:88
|
||||
msgid "Undo"
|
||||
msgstr "Desfacer"
|
||||
|
||||
#: ../js/ui/overview.js:166
|
||||
#: ../js/ui/overview.js:159
|
||||
msgid "Windows"
|
||||
msgstr "Xanelas"
|
||||
|
||||
#: ../js/ui/overview.js:169
|
||||
#: ../js/ui/overview.js:162
|
||||
msgid "Applications"
|
||||
msgstr "Aplicativos"
|
||||
|
||||
#. TODO - _quit() doesn't really work on apps in state STARTING yet
|
||||
#: ../js/ui/panel.js:478
|
||||
#: ../js/ui/panel.js:480
|
||||
#, c-format
|
||||
msgid "Quit %s"
|
||||
msgstr "Saír de %s"
|
||||
|
||||
#. Translators: This is the time format with date used
|
||||
#. in 24-hour mode.
|
||||
#: ../js/ui/panel.js:563
|
||||
msgid "%a %b %e, %R:%S"
|
||||
msgstr "%a %e de %b, %R:%S"
|
||||
|
||||
#: ../js/ui/panel.js:564
|
||||
msgid "%a %b %e, %R"
|
||||
msgstr "%a %e de %b, %R"
|
||||
|
||||
#. Translators: This is the time format without date used
|
||||
#. in 24-hour mode.
|
||||
#: ../js/ui/panel.js:568
|
||||
msgid "%a %R:%S"
|
||||
msgstr "%a %R:%S"
|
||||
|
||||
#: ../js/ui/panel.js:569
|
||||
msgid "%a %R"
|
||||
msgstr "%a %R"
|
||||
|
||||
#. Translators: This is a time format with date used
|
||||
#. for AM/PM.
|
||||
#: ../js/ui/panel.js:576
|
||||
msgid "%a %b %e, %l:%M:%S %p"
|
||||
msgstr "%a %e de %b, %H:%M:%S"
|
||||
|
||||
#: ../js/ui/panel.js:577
|
||||
msgid "%a %b %e, %l:%M %p"
|
||||
msgstr "%a %e de %b, %H:%M"
|
||||
|
||||
#. Translators: This is a time format without date used
|
||||
#. for AM/PM.
|
||||
#: ../js/ui/panel.js:581
|
||||
msgid "%a %l:%M:%S %p"
|
||||
msgstr "%a %H:%M:%S"
|
||||
|
||||
#: ../js/ui/panel.js:582
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %l:%M %p"
|
||||
|
||||
#. Button on the left side of the panel.
|
||||
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
|
||||
#: ../js/ui/panel.js:727
|
||||
#: ../js/ui/panel.js:614
|
||||
msgid "Activities"
|
||||
msgstr "Actividades"
|
||||
|
||||
#: ../js/ui/placeDisplay.js:111
|
||||
#: ../js/ui/placeDisplay.js:106
|
||||
#, c-format
|
||||
msgid "Failed to unmount '%s'"
|
||||
msgstr "Produciuse un fallo ao desmontar «%s»"
|
||||
|
||||
#: ../js/ui/placeDisplay.js:114
|
||||
#: ../js/ui/placeDisplay.js:109
|
||||
msgid "Retry"
|
||||
msgstr "Reintentar"
|
||||
|
||||
#: ../js/ui/placeDisplay.js:159
|
||||
#: ../js/ui/placeDisplay.js:150
|
||||
msgid "Connect to..."
|
||||
msgstr "Conectar con..."
|
||||
msgstr "Conectar con…"
|
||||
|
||||
#: ../js/ui/placeDisplay.js:558
|
||||
#: ../js/ui/placeDisplay.js:386
|
||||
msgid "PLACES & DEVICES"
|
||||
msgstr "LUGARES E DISPOSITIVOS"
|
||||
|
||||
@ -479,84 +544,79 @@ msgstr "LUGARES E DISPOSITIVOS"
|
||||
msgid "toggle-switch-us"
|
||||
msgstr "toggle-switch-intl"
|
||||
|
||||
#: ../js/ui/runDialog.js:233
|
||||
#: ../js/ui/runDialog.js:209
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Insira unha orde:"
|
||||
|
||||
#: ../js/ui/runDialog.js:378
|
||||
#, c-format
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "Produciuse un fallo na execución de «%s»:"
|
||||
|
||||
#: ../js/ui/statusMenu.js:101
|
||||
#: ../js/ui/statusMenu.js:102
|
||||
msgid "Available"
|
||||
msgstr "Dispoñíbel"
|
||||
|
||||
#: ../js/ui/statusMenu.js:106
|
||||
#: ../js/ui/statusMenu.js:107
|
||||
msgid "Busy"
|
||||
msgstr "Ocupado"
|
||||
|
||||
#: ../js/ui/statusMenu.js:114
|
||||
#: ../js/ui/statusMenu.js:115
|
||||
msgid "My Account"
|
||||
msgstr "A miña conta"
|
||||
|
||||
#: ../js/ui/statusMenu.js:118
|
||||
#: ../js/ui/statusMenu.js:119
|
||||
msgid "System Settings"
|
||||
msgstr "Configuracións do sistema"
|
||||
|
||||
#: ../js/ui/statusMenu.js:125
|
||||
#: ../js/ui/statusMenu.js:126
|
||||
msgid "Lock Screen"
|
||||
msgstr "Bloquear pantalla"
|
||||
|
||||
#: ../js/ui/statusMenu.js:129
|
||||
#: ../js/ui/statusMenu.js:130
|
||||
msgid "Switch User"
|
||||
msgstr "Cambiar de usuario"
|
||||
|
||||
#: ../js/ui/statusMenu.js:134
|
||||
#: ../js/ui/statusMenu.js:135
|
||||
msgid "Log Out..."
|
||||
msgstr "Saír da sesión..."
|
||||
msgstr "Saír da sesión…"
|
||||
|
||||
#: ../js/ui/statusMenu.js:141
|
||||
#: ../js/ui/statusMenu.js:142
|
||||
msgid "Suspend..."
|
||||
msgstr "Suspender..."
|
||||
msgstr "Suspender…"
|
||||
|
||||
#: ../js/ui/statusMenu.js:145
|
||||
#: ../js/ui/statusMenu.js:146
|
||||
msgid "Shut Down..."
|
||||
msgstr "Apagar..."
|
||||
msgstr "Apagar…"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:82
|
||||
#: ../js/ui/status/accessibility.js:83
|
||||
msgid "Zoom"
|
||||
msgstr "Ampliación"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:88
|
||||
#: ../js/ui/status/accessibility.js:89
|
||||
msgid "Screen Reader"
|
||||
msgstr "Lector de pantalla"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:91
|
||||
#: ../js/ui/status/accessibility.js:92
|
||||
msgid "Screen Keyboard"
|
||||
msgstr "Teclado en pantalla"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:94
|
||||
#: ../js/ui/status/accessibility.js:95
|
||||
msgid "Visual Alerts"
|
||||
msgstr "Alertas visuais"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:97
|
||||
#: ../js/ui/status/accessibility.js:98
|
||||
msgid "Sticky Keys"
|
||||
msgstr "Teclas persistentes"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:100
|
||||
#: ../js/ui/status/accessibility.js:101
|
||||
msgid "Slow Keys"
|
||||
msgstr "Teclas lentas"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:103
|
||||
#: ../js/ui/status/accessibility.js:104
|
||||
msgid "Bounce Keys"
|
||||
msgstr "Rebote das teclas"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:106
|
||||
#: ../js/ui/status/accessibility.js:107
|
||||
msgid "Mouse Keys"
|
||||
msgstr "Teclas do Rato"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:110
|
||||
#: ../js/ui/status/accessibility.js:111
|
||||
msgid "Universal Access Settings"
|
||||
msgstr "Configuracións de acceso universal"
|
||||
|
||||
@ -568,7 +628,7 @@ msgstr "Alto contraste"
|
||||
msgid "Large Text"
|
||||
msgstr "Texto máis grande"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:42 ../js/ui/status/bluetooth.js:240
|
||||
#: ../js/ui/status/bluetooth.js:42 ../js/ui/status/bluetooth.js:241
|
||||
msgid "Bluetooth"
|
||||
msgstr "Bluetooth"
|
||||
|
||||
@ -578,115 +638,115 @@ msgstr "Visibilidade"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:69
|
||||
msgid "Send Files to Device..."
|
||||
msgstr "Enviar ficheiros ao dispositivo..."
|
||||
msgstr "Enviar ficheiros ao dispositivo…"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:70
|
||||
msgid "Setup a New Device..."
|
||||
msgstr "Configurar un novo dispositivo..."
|
||||
msgstr "Configurar un novo dispositivo…"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:94
|
||||
#: ../js/ui/status/bluetooth.js:95
|
||||
msgid "Bluetooth Settings"
|
||||
msgstr "Configuracións de Bluetooth"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:191
|
||||
#: ../js/ui/status/bluetooth.js:192
|
||||
msgid "Connection"
|
||||
msgstr "Conexión"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:227
|
||||
#: ../js/ui/status/bluetooth.js:228
|
||||
msgid "Send Files..."
|
||||
msgstr "Enviar ficheiros..."
|
||||
msgstr "Enviar ficheiros…"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:232
|
||||
#: ../js/ui/status/bluetooth.js:233
|
||||
msgid "Browse Files..."
|
||||
msgstr "Explorar ficheiros..."
|
||||
msgstr "Explorar ficheiros…"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:241
|
||||
#: ../js/ui/status/bluetooth.js:242
|
||||
msgid "Error browsing device"
|
||||
msgstr "Produciuse un erro ao explorar o dispositivo"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:242
|
||||
#: ../js/ui/status/bluetooth.js:243
|
||||
#, c-format
|
||||
msgid "The requested device cannot be browsed, error is '%s'"
|
||||
msgstr "O dispositivo solicitado non pode explorarse, o erro foi «%s»"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:250
|
||||
#: ../js/ui/status/bluetooth.js:251
|
||||
msgid "Keyboard Settings"
|
||||
msgstr "Configuracións do teclado"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:255
|
||||
#: ../js/ui/status/bluetooth.js:256
|
||||
msgid "Mouse Settings"
|
||||
msgstr "Configuracións do rato"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:262 ../js/ui/status/volume.js:62
|
||||
#: ../js/ui/status/bluetooth.js:263 ../js/ui/status/volume.js:63
|
||||
msgid "Sound Settings"
|
||||
msgstr "Configuracións do son"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:336 ../js/ui/status/bluetooth.js:370
|
||||
#: ../js/ui/status/bluetooth.js:410 ../js/ui/status/bluetooth.js:443
|
||||
#: ../js/ui/status/bluetooth.js:337 ../js/ui/status/bluetooth.js:371
|
||||
#: ../js/ui/status/bluetooth.js:411 ../js/ui/status/bluetooth.js:444
|
||||
msgid "Bluetooth Agent"
|
||||
msgstr "Axente Bluetooth"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:371
|
||||
#: ../js/ui/status/bluetooth.js:372
|
||||
#, c-format
|
||||
msgid "Authorization request from %s"
|
||||
msgstr "Solicitude de autorización de %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:377
|
||||
#: ../js/ui/status/bluetooth.js:378
|
||||
#, c-format
|
||||
msgid "Device %s wants access to the service '%s'"
|
||||
msgstr "O dispositivo %s quere acceder ao servizo «%s»"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:379
|
||||
#: ../js/ui/status/bluetooth.js:380
|
||||
msgid "Always grant access"
|
||||
msgstr "Conceder acceso sempre"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:380
|
||||
#: ../js/ui/status/bluetooth.js:381
|
||||
msgid "Grant this time only"
|
||||
msgstr "Conceder só esta vez"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:381
|
||||
#: ../js/ui/status/bluetooth.js:382
|
||||
msgid "Reject"
|
||||
msgstr "Rexeitar"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:411
|
||||
#: ../js/ui/status/bluetooth.js:412
|
||||
#, c-format
|
||||
msgid "Pairing confirmation for %s"
|
||||
msgstr "Confirmación de emparellado para «%s»"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:417 ../js/ui/status/bluetooth.js:451
|
||||
#: ../js/ui/status/bluetooth.js:418 ../js/ui/status/bluetooth.js:452
|
||||
#, c-format
|
||||
msgid "Device %s wants to pair with this computer"
|
||||
msgstr "O dispositivo «%s» quere emparellarse con este equipo"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:418
|
||||
#: ../js/ui/status/bluetooth.js:419
|
||||
#, c-format
|
||||
msgid "Please confirm whether the PIN '%s' matches the one on the device."
|
||||
msgstr "Confirme que o PIN mostrado en «%s» coincide co do dispositivo."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:420
|
||||
#: ../js/ui/status/bluetooth.js:421
|
||||
msgid "Matches"
|
||||
msgstr "Coincide"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:421
|
||||
#: ../js/ui/status/bluetooth.js:422
|
||||
msgid "Does not match"
|
||||
msgstr "Non coincide"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:444
|
||||
#: ../js/ui/status/bluetooth.js:445
|
||||
#, c-format
|
||||
msgid "Pairing request for %s"
|
||||
msgstr "Solicitude de emparellamento para «%s»"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:452
|
||||
#: ../js/ui/status/bluetooth.js:453
|
||||
msgid "Please enter the PIN mentioned on the device."
|
||||
msgstr "Introduza o PIN mencionado no dispositivo."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:468
|
||||
#: ../js/ui/status/bluetooth.js:469
|
||||
msgid "OK"
|
||||
msgstr "Aceptar"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:469
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
#: ../js/ui/status/keyboard.js:78
|
||||
msgid "Localization Settings"
|
||||
msgstr "Configuracións do son"
|
||||
|
||||
#: ../js/ui/status/power.js:85
|
||||
msgid "Power Settings"
|
||||
@ -724,59 +784,59 @@ msgid_plural "%d minutes remaining"
|
||||
msgstr[0] "%d minuto restante"
|
||||
msgstr[1] "%d minutos restantes"
|
||||
|
||||
#: ../js/ui/status/power.js:237
|
||||
#: ../js/ui/status/power.js:235
|
||||
msgid "AC adapter"
|
||||
msgstr "Adaptador de corrente"
|
||||
|
||||
#: ../js/ui/status/power.js:239
|
||||
#: ../js/ui/status/power.js:237
|
||||
msgid "Laptop battery"
|
||||
msgstr "Batería do portátil"
|
||||
|
||||
#: ../js/ui/status/power.js:241
|
||||
#: ../js/ui/status/power.js:239
|
||||
msgid "UPS"
|
||||
msgstr "UPS"
|
||||
|
||||
#: ../js/ui/status/power.js:243
|
||||
#: ../js/ui/status/power.js:241
|
||||
msgid "Monitor"
|
||||
msgstr "Monitor"
|
||||
|
||||
#: ../js/ui/status/power.js:245
|
||||
#: ../js/ui/status/power.js:243
|
||||
msgid "Mouse"
|
||||
msgstr "Rato"
|
||||
|
||||
#: ../js/ui/status/power.js:247
|
||||
#: ../js/ui/status/power.js:245
|
||||
msgid "Keyboard"
|
||||
msgstr "Teclado"
|
||||
|
||||
#: ../js/ui/status/power.js:249
|
||||
#: ../js/ui/status/power.js:247
|
||||
msgid "PDA"
|
||||
msgstr "PDA"
|
||||
|
||||
#: ../js/ui/status/power.js:251
|
||||
#: ../js/ui/status/power.js:249
|
||||
msgid "Cell phone"
|
||||
msgstr "Teléfono móbil"
|
||||
|
||||
#: ../js/ui/status/power.js:253
|
||||
#: ../js/ui/status/power.js:251
|
||||
msgid "Media player"
|
||||
msgstr "Reprodutor multimedia"
|
||||
|
||||
#: ../js/ui/status/power.js:255
|
||||
#: ../js/ui/status/power.js:253
|
||||
msgid "Tablet"
|
||||
msgstr "Tablet"
|
||||
|
||||
#: ../js/ui/status/power.js:257
|
||||
#: ../js/ui/status/power.js:255
|
||||
msgid "Computer"
|
||||
msgstr "Computador"
|
||||
|
||||
#: ../js/ui/status/power.js:259 ../src/shell-app-system.c:1012
|
||||
#: ../js/ui/status/power.js:257 ../src/shell-app-system.c:1012
|
||||
msgid "Unknown"
|
||||
msgstr "Descoñecido"
|
||||
|
||||
#: ../js/ui/status/volume.js:41
|
||||
#: ../js/ui/status/volume.js:42
|
||||
msgid "Volume"
|
||||
msgstr "Volume"
|
||||
|
||||
#: ../js/ui/status/volume.js:54
|
||||
#: ../js/ui/status/volume.js:55
|
||||
msgid "Microphone"
|
||||
msgstr "Micrófono"
|
||||
|
||||
@ -822,14 +882,14 @@ msgstr "%s rematou de iniarse"
|
||||
msgid "'%s' is ready"
|
||||
msgstr "«%s» está preparado"
|
||||
|
||||
#: ../js/ui/workspacesView.js:244
|
||||
#: ../js/ui/workspacesView.js:243
|
||||
msgid ""
|
||||
"Can't add a new workspace because maximum workspaces limit has been reached."
|
||||
msgstr ""
|
||||
"Non é posíbel engadir unha área de traballo nova porque chegouse ao límite "
|
||||
"de áreas de traballo."
|
||||
|
||||
#: ../js/ui/workspacesView.js:260
|
||||
#: ../js/ui/workspacesView.js:259
|
||||
msgid "Can't remove the first workspace."
|
||||
msgstr "Non é posíbel quitar a primeira área de traballo."
|
||||
|
||||
@ -855,32 +915,32 @@ msgstr[1] "%u entradas"
|
||||
msgid "System Sounds"
|
||||
msgstr "Sons do sistema"
|
||||
|
||||
#: ../src/shell-global.c:1233
|
||||
#: ../src/shell-global.c:1365
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Hai menos dun minuto"
|
||||
|
||||
#: ../src/shell-global.c:1237
|
||||
#: ../src/shell-global.c:1369
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "hai %d minuto"
|
||||
msgstr[1] "hai %d minutos"
|
||||
|
||||
#: ../src/shell-global.c:1242
|
||||
#: ../src/shell-global.c:1374
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "hai %d hora"
|
||||
msgstr[1] "hai %d horas"
|
||||
|
||||
#: ../src/shell-global.c:1247
|
||||
#: ../src/shell-global.c:1379
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "hai %d día"
|
||||
msgstr[1] "hai %d días"
|
||||
|
||||
#: ../src/shell-global.c:1252
|
||||
#: ../src/shell-global.c:1384
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
@ -911,6 +971,30 @@ msgstr "Buscar"
|
||||
msgid "%1$s: %2$s"
|
||||
msgstr "%1$s: %2$s"
|
||||
|
||||
#~ msgid "%a %b %e, %R:%S"
|
||||
#~ msgstr "%a %e de %b, %R:%S"
|
||||
|
||||
#~ msgid "%a %b %e, %R"
|
||||
#~ msgstr "%a %e de %b, %R"
|
||||
|
||||
#~ msgid "%a %R:%S"
|
||||
#~ msgstr "%a %R:%S"
|
||||
|
||||
#~ msgid "%a %R"
|
||||
#~ msgstr "%a %R"
|
||||
|
||||
#~ msgid "%a %b %e, %l:%M:%S %p"
|
||||
#~ msgstr "%a %e de %b, %H:%M:%S"
|
||||
|
||||
#~ msgid "%a %b %e, %l:%M %p"
|
||||
#~ msgstr "%a %e de %b, %H:%M"
|
||||
|
||||
#~ msgid "%a %l:%M:%S %p"
|
||||
#~ msgstr "%a %H:%M:%S"
|
||||
|
||||
#~ msgid "%a %l:%M %p"
|
||||
#~ msgstr "%a %l:%M %p"
|
||||
|
||||
#~ msgid "Clock"
|
||||
#~ msgstr "Reloxo"
|
||||
|
||||
@ -1011,15 +1095,9 @@ msgstr "%1$s: %2$s"
|
||||
#~ msgid "Invisible"
|
||||
#~ msgstr "Invisíbel"
|
||||
|
||||
#~ msgid "Restart..."
|
||||
#~ msgstr "Reiniciar..."
|
||||
|
||||
#~ msgid "System Preferences..."
|
||||
#~ msgstr "Preferencias do sistema..."
|
||||
|
||||
#~ msgid "Account Information..."
|
||||
#~ msgstr "Información da conta..."
|
||||
|
||||
#~ msgid "ON"
|
||||
#~ msgstr "⚫"
|
||||
|
||||
|
362
po/he.po
362
po/he.po
@ -8,8 +8,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell master\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-01-09 18:50+0200\n"
|
||||
"PO-Revision-Date: 2011-01-09 18:51+0200\n"
|
||||
"POT-Creation-Date: 2011-01-30 23:03+0200\n"
|
||||
"PO-Revision-Date: 2011-01-30 23:03+0200\n"
|
||||
"Last-Translator: Yaron Shahrabani <sh.yaron@gmail.com>\n"
|
||||
"Language-Team: Hebrew <he@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -73,7 +73,8 @@ msgstr "If true, display the ISO week date in the calendar."
|
||||
msgid "List of desktop file IDs for favorite applications"
|
||||
msgstr "List of desktop file IDs for favorite applications"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:11
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:12
|
||||
#, no-c-format
|
||||
msgid ""
|
||||
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
|
||||
"used for gst-launch. The pipeline should have an unconnected sink pad where "
|
||||
@ -82,7 +83,9 @@ msgid ""
|
||||
"pipeline can also take care of its own output - this might be used to send "
|
||||
"the output to an icecast server via shout2send or similar. When unset or set "
|
||||
"to an empty value, the default pipeline will be used. This is currently "
|
||||
"'videorate ! theoraenc ! oggmux' and records to Ogg Theora."
|
||||
"'videorate ! vp8enc quality=10 speed=2 threads=%T ! queue ! webmmux' and "
|
||||
"records to WEBM using the VP8 codec. %T is used as a placeholder for a guess "
|
||||
"at the optimal thread count on the system."
|
||||
msgstr ""
|
||||
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
|
||||
"used for gst-launch. The pipeline should have an unconnected sink pad where "
|
||||
@ -91,51 +94,53 @@ msgstr ""
|
||||
"pipeline can also take care of its own output - this might be used to send "
|
||||
"the output to an icecast server via shout2send or similar. When unset or set "
|
||||
"to an empty value, the default pipeline will be used. This is currently "
|
||||
"'videorate ! theoraenc ! oggmux' and records to Ogg Theora."
|
||||
"'videorate ! vp8enc quality=10 speed=2 threads=%T ! queue ! webmmux' and "
|
||||
"records to WEBM using the VP8 codec. %T is used as a placeholder for a guess "
|
||||
"at the optimal thread count on the system."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:12
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:13
|
||||
msgid "Show date in clock"
|
||||
msgstr "Show date in clock"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:13
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:14
|
||||
msgid "Show the week date in the calendar"
|
||||
msgstr "Show the week date in the calendar"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:14
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:15
|
||||
msgid "Show time with seconds"
|
||||
msgstr "Show time with seconds"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:15
|
||||
msgid ""
|
||||
"The applications corresponding to these identifiers will be displayed in the "
|
||||
"favorites area."
|
||||
msgstr ""
|
||||
"The applications corresponding to these identifiers will be displayed in the "
|
||||
"favorites area."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:16
|
||||
msgid ""
|
||||
"The filename for recorded screencasts will be a unique filename based on the "
|
||||
"current date, and use this extension. It should be changed when recording to "
|
||||
"a different container format."
|
||||
"The applications corresponding to these identifiers will be displayed in the "
|
||||
"favorites area."
|
||||
msgstr ""
|
||||
"The filename for recorded screencasts will be a unique filename based on the "
|
||||
"current date, and use this extension. It should be changed when recording to "
|
||||
"a different container format."
|
||||
"The applications corresponding to these identifiers will be displayed in the "
|
||||
"favorites area."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:17
|
||||
msgid ""
|
||||
"The filename for recorded screencasts will be a unique filename based on the "
|
||||
"current date, and use this extension. It should be changed when recording to "
|
||||
"a different container format."
|
||||
msgstr ""
|
||||
"The filename for recorded screencasts will be a unique filename based on the "
|
||||
"current date, and use this extension. It should be changed when recording to "
|
||||
"a different container format."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:18
|
||||
msgid ""
|
||||
"The framerate of the resulting screencast recordered by GNOME Shell's "
|
||||
"screencast recorder in frames-per-second."
|
||||
msgstr ""
|
||||
"The framerate of the resulting screencast recordered by GNOME Shell's "
|
||||
"screencast recorder in frames-per-second."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:18
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:19
|
||||
msgid "The gstreamer pipeline used to encode the screencast"
|
||||
msgstr "The gstreamer pipeline used to encode the screencast"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:19
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:20
|
||||
msgid ""
|
||||
"The shell normally monitors active applications in order to present the most "
|
||||
"used ones (e.g. in launchers). While this data will be kept private, you may "
|
||||
@ -147,14 +152,18 @@ msgstr ""
|
||||
"want to disable this for privacy reasons. Please note that doing so won't "
|
||||
"remove already saved data."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:20
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:21
|
||||
msgid "Uuids of extensions to disable"
|
||||
msgstr "Uuids of extensions to disable"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:21
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:22
|
||||
msgid "Whether to collect stats about applications usage"
|
||||
msgstr "Whether to collect stats about applications usage"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:23
|
||||
msgid "disabled OpenSearch providers"
|
||||
msgstr "disabled OpenSearch providers"
|
||||
|
||||
#: ../data/org.gnome.accessibility.magnifier.gschema.xml.in.h:1
|
||||
msgid "Clip the crosshairs at the center"
|
||||
msgstr "Clip the crosshairs at the center"
|
||||
@ -310,28 +319,47 @@ msgid "Width of the vertical and horizontal lines that make up the crosshairs."
|
||||
msgstr ""
|
||||
"Width of the vertical and horizontal lines that make up the crosshairs."
|
||||
|
||||
#: ../js/misc/util.js:86
|
||||
msgid "Command not found"
|
||||
msgstr "הפקודה לא נמצאה"
|
||||
|
||||
#. Replace "Error invoking GLib.shell_parse_argv: " with
|
||||
#. something nicer
|
||||
#: ../js/misc/util.js:113
|
||||
msgid "Could not parse command:"
|
||||
msgstr "לא ניתן לפענח את הפקודה:"
|
||||
|
||||
#: ../js/misc/util.js:135
|
||||
msgid "No such application"
|
||||
msgstr "אין כזה יישום"
|
||||
|
||||
#: ../js/misc/util.js:148
|
||||
#, c-format
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "ההרצה של '%s' נכשלה:"
|
||||
|
||||
#. Translators: Filter to display all applications
|
||||
#: ../js/ui/appDisplay.js:155
|
||||
#: ../js/ui/appDisplay.js:164
|
||||
msgid "All"
|
||||
msgstr "הכול"
|
||||
|
||||
#: ../js/ui/appDisplay.js:236
|
||||
#: ../js/ui/appDisplay.js:245
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "יישומים"
|
||||
|
||||
#: ../js/ui/appDisplay.js:266
|
||||
#: ../js/ui/appDisplay.js:275
|
||||
msgid "PREFERENCES"
|
||||
msgstr "העדפות"
|
||||
|
||||
#: ../js/ui/appDisplay.js:563
|
||||
#: ../js/ui/appDisplay.js:572
|
||||
msgid "New Window"
|
||||
msgstr "חלון חדש"
|
||||
|
||||
#: ../js/ui/appDisplay.js:567
|
||||
#: ../js/ui/appDisplay.js:576
|
||||
msgid "Remove from Favorites"
|
||||
msgstr "הסרה מהמועדפים"
|
||||
|
||||
#: ../js/ui/appDisplay.js:568
|
||||
#: ../js/ui/appDisplay.js:577
|
||||
msgid "Add to Favorites"
|
||||
msgstr "הוספה למועדפים"
|
||||
|
||||
@ -349,118 +377,191 @@ msgstr "%s הוסר מהמועדפים שלך."
|
||||
msgid "Remove"
|
||||
msgstr "הסרה"
|
||||
|
||||
#: ../js/ui/docDisplay.js:494
|
||||
#: ../js/ui/docDisplay.js:18
|
||||
msgid "RECENT ITEMS"
|
||||
msgstr "פריטים אחרונים"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:552
|
||||
#: ../js/ui/endSessionDialog.js:63
|
||||
#, c-format
|
||||
msgid "Log Out %s"
|
||||
msgstr "הוצאת %s"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:64 ../js/ui/endSessionDialog.js:69
|
||||
msgid "Log Out"
|
||||
msgstr "יציאה"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:65
|
||||
msgid "Click Log Out to quit these applications and log out of the system."
|
||||
msgstr "יש ללחוץ על יציאה כדי לסגור יישומים אלה ולצאת מהמערכת."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:66
|
||||
#, c-format
|
||||
msgid "%s will be logged out automatically in %d seconds."
|
||||
msgstr "המשתמש %s ייצא אוטומטית בעוד %d שניות."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:67
|
||||
#, c-format
|
||||
msgid "You will be logged out automatically in %d seconds."
|
||||
msgstr "המערכת תוציא אותך אוטומטית בעוד %d שניות."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:68
|
||||
msgid "Logging out of the system."
|
||||
msgstr "מתבצעת יציאה מהמערכת."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:74 ../js/ui/endSessionDialog.js:78
|
||||
msgid "Shut Down"
|
||||
msgstr "כיבוי"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:75
|
||||
msgid "Click Shut Down to quit these applications and shut down the system."
|
||||
msgstr "יש ללחוץ על יציאה כדי לסגור יישומים אלה ולכבות את המערכת."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:76
|
||||
#, c-format
|
||||
msgid "The system will shut down automatically in %d seconds."
|
||||
msgstr "המערכת תכבה אוטומטית בעוד %d שניות."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:77
|
||||
msgid "Shutting down the system."
|
||||
msgstr "המערכת נכבית."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:84 ../js/ui/endSessionDialog.js:88
|
||||
msgid "Restart"
|
||||
msgstr "הפעלה מחדש"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:85
|
||||
msgid "Click Restart to quit these applications and restart the system."
|
||||
msgstr "יש ללחוץ על יציאה כדי לסגור יישומים אלה ולהפעיל את המערכת מחדש."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:86
|
||||
#, c-format
|
||||
msgid "The system will restart automatically in %d seconds."
|
||||
msgstr "המערכת תופעל מחדש בעוד %d שניות."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:87
|
||||
msgid "Restarting the system."
|
||||
msgstr "המערכת מופעלת מחדש"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:395
|
||||
msgid "Confirm"
|
||||
msgstr "אישור"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:400 ../js/ui/status/bluetooth.js:470
|
||||
msgid "Cancel"
|
||||
msgstr "ביטול"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:556
|
||||
msgid "No extensions installed"
|
||||
msgstr "לא מותקנות הרחבות"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:589
|
||||
#: ../js/ui/lookingGlass.js:593
|
||||
msgid "Enabled"
|
||||
msgstr "פעיל"
|
||||
|
||||
#. translators:
|
||||
#. * The device has been disabled
|
||||
#: ../js/ui/lookingGlass.js:591 ../src/gvc/gvc-mixer-control.c:1087
|
||||
#: ../js/ui/lookingGlass.js:595 ../src/gvc/gvc-mixer-control.c:1087
|
||||
msgid "Disabled"
|
||||
msgstr "מנוטרל"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:593
|
||||
#: ../js/ui/lookingGlass.js:597
|
||||
msgid "Error"
|
||||
msgstr "שגיאה"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:595
|
||||
#: ../js/ui/lookingGlass.js:599
|
||||
msgid "Out of date"
|
||||
msgstr "לא בתוקף"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:620
|
||||
#: ../js/ui/lookingGlass.js:624
|
||||
msgid "View Source"
|
||||
msgstr "צפייה במקור"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:626
|
||||
#: ../js/ui/lookingGlass.js:630
|
||||
msgid "Web Page"
|
||||
msgstr "דף אינטרנט"
|
||||
|
||||
#: ../js/ui/overview.js:101
|
||||
#: ../js/ui/messageTray.js:1778
|
||||
msgid "System Information"
|
||||
msgstr "פרטי המערכת"
|
||||
|
||||
#: ../js/ui/overview.js:88
|
||||
msgid "Undo"
|
||||
msgstr "ביטול"
|
||||
|
||||
#: ../js/ui/overview.js:166
|
||||
#: ../js/ui/overview.js:159
|
||||
msgid "Windows"
|
||||
msgstr "חלונות"
|
||||
|
||||
#: ../js/ui/overview.js:169
|
||||
#: ../js/ui/overview.js:162
|
||||
msgid "Applications"
|
||||
msgstr "יישומים"
|
||||
|
||||
#. TODO - _quit() doesn't really work on apps in state STARTING yet
|
||||
#: ../js/ui/panel.js:478
|
||||
#: ../js/ui/panel.js:479
|
||||
#, c-format
|
||||
msgid "Quit %s"
|
||||
msgstr "יציאה מ־%s"
|
||||
|
||||
#. Translators: This is the time format with date used
|
||||
#. in 24-hour mode.
|
||||
#: ../js/ui/panel.js:563
|
||||
#: ../js/ui/panel.js:564
|
||||
msgid "%a %b %e, %R:%S"
|
||||
msgstr "%a %b %e, %R:%S"
|
||||
|
||||
#: ../js/ui/panel.js:564
|
||||
#: ../js/ui/panel.js:565
|
||||
msgid "%a %b %e, %R"
|
||||
msgstr "%a %b %e, %R"
|
||||
|
||||
#. Translators: This is the time format without date used
|
||||
#. in 24-hour mode.
|
||||
#: ../js/ui/panel.js:568
|
||||
#: ../js/ui/panel.js:569
|
||||
msgid "%a %R:%S"
|
||||
msgstr "%a %R:%S"
|
||||
|
||||
#: ../js/ui/panel.js:569
|
||||
#: ../js/ui/panel.js:570
|
||||
msgid "%a %R"
|
||||
msgstr "%a %R"
|
||||
|
||||
#. Translators: This is a time format with date used
|
||||
#. for AM/PM.
|
||||
#: ../js/ui/panel.js:576
|
||||
#: ../js/ui/panel.js:577
|
||||
msgid "%a %b %e, %l:%M:%S %p"
|
||||
msgstr "%a %b %e, %l:%M:%S %p"
|
||||
|
||||
#: ../js/ui/panel.js:577
|
||||
#: ../js/ui/panel.js:578
|
||||
msgid "%a %b %e, %l:%M %p"
|
||||
msgstr "%a %b %e, %l:%M %p"
|
||||
|
||||
#. Translators: This is a time format without date used
|
||||
#. for AM/PM.
|
||||
#: ../js/ui/panel.js:581
|
||||
#: ../js/ui/panel.js:582
|
||||
msgid "%a %l:%M:%S %p"
|
||||
msgstr "%a %l:%M:%S %p"
|
||||
|
||||
#: ../js/ui/panel.js:582
|
||||
#: ../js/ui/panel.js:583
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %l:%M %p"
|
||||
|
||||
#. Button on the left side of the panel.
|
||||
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
|
||||
#: ../js/ui/panel.js:727
|
||||
#: ../js/ui/panel.js:728
|
||||
msgid "Activities"
|
||||
msgstr "פעילויות"
|
||||
|
||||
#: ../js/ui/placeDisplay.js:111
|
||||
#: ../js/ui/placeDisplay.js:106
|
||||
#, c-format
|
||||
msgid "Failed to unmount '%s'"
|
||||
msgstr "אירע כשל בניתוק '%s'"
|
||||
|
||||
#: ../js/ui/placeDisplay.js:114
|
||||
#: ../js/ui/placeDisplay.js:109
|
||||
msgid "Retry"
|
||||
msgstr "ניסיון חוזר"
|
||||
|
||||
#: ../js/ui/placeDisplay.js:159
|
||||
#: ../js/ui/placeDisplay.js:150
|
||||
msgid "Connect to..."
|
||||
msgstr "התחברות אל..."
|
||||
|
||||
#: ../js/ui/placeDisplay.js:558
|
||||
#: ../js/ui/placeDisplay.js:386
|
||||
msgid "PLACES & DEVICES"
|
||||
msgstr "מקומות והתקנים"
|
||||
|
||||
@ -473,84 +574,79 @@ msgstr "מקומות והתקנים"
|
||||
msgid "toggle-switch-us"
|
||||
msgstr "toggle-switch-intl"
|
||||
|
||||
#: ../js/ui/runDialog.js:238
|
||||
#: ../js/ui/runDialog.js:209
|
||||
msgid "Please enter a command:"
|
||||
msgstr "נא להזין פקודה:"
|
||||
|
||||
#: ../js/ui/runDialog.js:383
|
||||
#, c-format
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "ההרצה של '%s' נכשלה:"
|
||||
|
||||
#: ../js/ui/statusMenu.js:101
|
||||
#: ../js/ui/statusMenu.js:102
|
||||
msgid "Available"
|
||||
msgstr "זמין"
|
||||
|
||||
#: ../js/ui/statusMenu.js:106
|
||||
#: ../js/ui/statusMenu.js:107
|
||||
msgid "Busy"
|
||||
msgstr "עסוק"
|
||||
|
||||
#: ../js/ui/statusMenu.js:114
|
||||
#: ../js/ui/statusMenu.js:115
|
||||
msgid "My Account"
|
||||
msgstr "החשבון שלי"
|
||||
|
||||
#: ../js/ui/statusMenu.js:118
|
||||
#: ../js/ui/statusMenu.js:119
|
||||
msgid "System Settings"
|
||||
msgstr "הגדרות המערכת"
|
||||
|
||||
#: ../js/ui/statusMenu.js:125
|
||||
#: ../js/ui/statusMenu.js:126
|
||||
msgid "Lock Screen"
|
||||
msgstr "נעילת המסך"
|
||||
|
||||
#: ../js/ui/statusMenu.js:129
|
||||
#: ../js/ui/statusMenu.js:130
|
||||
msgid "Switch User"
|
||||
msgstr "החלפת משתמש"
|
||||
|
||||
#: ../js/ui/statusMenu.js:134
|
||||
#: ../js/ui/statusMenu.js:135
|
||||
msgid "Log Out..."
|
||||
msgstr "ניתוק..."
|
||||
|
||||
#: ../js/ui/statusMenu.js:141
|
||||
#: ../js/ui/statusMenu.js:142
|
||||
msgid "Suspend..."
|
||||
msgstr "השהיה..."
|
||||
|
||||
#: ../js/ui/statusMenu.js:145
|
||||
#: ../js/ui/statusMenu.js:146
|
||||
msgid "Shut Down..."
|
||||
msgstr "כיבוי..."
|
||||
|
||||
#: ../js/ui/status/accessibility.js:82
|
||||
#: ../js/ui/status/accessibility.js:83
|
||||
msgid "Zoom"
|
||||
msgstr "תקריב"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:88
|
||||
#: ../js/ui/status/accessibility.js:89
|
||||
msgid "Screen Reader"
|
||||
msgstr "מקריא מסך"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:91
|
||||
#: ../js/ui/status/accessibility.js:92
|
||||
msgid "Screen Keyboard"
|
||||
msgstr "מקלדת מסך"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:94
|
||||
#: ../js/ui/status/accessibility.js:95
|
||||
msgid "Visual Alerts"
|
||||
msgstr "התראות חזותיות"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:97
|
||||
#: ../js/ui/status/accessibility.js:98
|
||||
msgid "Sticky Keys"
|
||||
msgstr "מקשים דביקים"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:100
|
||||
#: ../js/ui/status/accessibility.js:101
|
||||
msgid "Slow Keys"
|
||||
msgstr "מקשים אטיים"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:103
|
||||
#: ../js/ui/status/accessibility.js:104
|
||||
msgid "Bounce Keys"
|
||||
msgstr "מקשים קופצים"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:106
|
||||
#: ../js/ui/status/accessibility.js:107
|
||||
msgid "Mouse Keys"
|
||||
msgstr "מקשי עכבר"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:110
|
||||
#: ../js/ui/status/accessibility.js:111
|
||||
msgid "Universal Access Settings"
|
||||
msgstr "הגדרות גישה אוניברסלית"
|
||||
|
||||
@ -562,7 +658,7 @@ msgstr "ניגודיות גבוהה"
|
||||
msgid "Large Text"
|
||||
msgstr "טקסט גדול"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:42 ../js/ui/status/bluetooth.js:240
|
||||
#: ../js/ui/status/bluetooth.js:42 ../js/ui/status/bluetooth.js:241
|
||||
msgid "Bluetooth"
|
||||
msgstr "Bluetooth"
|
||||
|
||||
@ -578,109 +674,109 @@ msgstr "שליחת קובץ להתקן..."
|
||||
msgid "Setup a New Device..."
|
||||
msgstr "הגדרת התקן חדש..."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:94
|
||||
#: ../js/ui/status/bluetooth.js:95
|
||||
msgid "Bluetooth Settings"
|
||||
msgstr "הגדרות Bluetooth"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:191
|
||||
#: ../js/ui/status/bluetooth.js:192
|
||||
msgid "Connection"
|
||||
msgstr "חיבור"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:227
|
||||
#: ../js/ui/status/bluetooth.js:228
|
||||
msgid "Send Files..."
|
||||
msgstr "שליחת קבצים..."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:232
|
||||
#: ../js/ui/status/bluetooth.js:233
|
||||
msgid "Browse Files..."
|
||||
msgstr "עיון בקבצים..."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:241
|
||||
#: ../js/ui/status/bluetooth.js:242
|
||||
msgid "Error browsing device"
|
||||
msgstr "שגיאה בעיון בהתקן"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:242
|
||||
#: ../js/ui/status/bluetooth.js:243
|
||||
#, c-format
|
||||
msgid "The requested device cannot be browsed, error is '%s'"
|
||||
msgstr "לא ניתן לעיין בהתקן הנבחר, השגיאה היא '%s'"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:250
|
||||
#: ../js/ui/status/bluetooth.js:251
|
||||
msgid "Keyboard Settings"
|
||||
msgstr "הגדרות מקלדת"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:255
|
||||
#: ../js/ui/status/bluetooth.js:256
|
||||
msgid "Mouse Settings"
|
||||
msgstr "הגדרות עכבר"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:262 ../js/ui/status/volume.js:62
|
||||
#: ../js/ui/status/bluetooth.js:263 ../js/ui/status/volume.js:63
|
||||
msgid "Sound Settings"
|
||||
msgstr "הגדרות שמע"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:336 ../js/ui/status/bluetooth.js:370
|
||||
#: ../js/ui/status/bluetooth.js:410 ../js/ui/status/bluetooth.js:443
|
||||
#: ../js/ui/status/bluetooth.js:337 ../js/ui/status/bluetooth.js:371
|
||||
#: ../js/ui/status/bluetooth.js:411 ../js/ui/status/bluetooth.js:444
|
||||
msgid "Bluetooth Agent"
|
||||
msgstr "סוכן Bluetooth"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:371
|
||||
#: ../js/ui/status/bluetooth.js:372
|
||||
#, c-format
|
||||
msgid "Authorization request from %s"
|
||||
msgstr "בקשת אישור מאת %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:377
|
||||
#: ../js/ui/status/bluetooth.js:378
|
||||
#, c-format
|
||||
msgid "Device %s wants access to the service '%s'"
|
||||
msgstr "ההתקן %s מעוניין לגשת אל השירות '%s'"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:379
|
||||
#: ../js/ui/status/bluetooth.js:380
|
||||
msgid "Always grant access"
|
||||
msgstr "תמיד להעניק גישה"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:380
|
||||
#: ../js/ui/status/bluetooth.js:381
|
||||
msgid "Grant this time only"
|
||||
msgstr "הענקת גישה הפעם בלבד"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:381
|
||||
#: ../js/ui/status/bluetooth.js:382
|
||||
msgid "Reject"
|
||||
msgstr "סירוב"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:411
|
||||
#: ../js/ui/status/bluetooth.js:412
|
||||
#, c-format
|
||||
msgid "Pairing confirmation for %s"
|
||||
msgstr "אישור צימוד עבור %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:417 ../js/ui/status/bluetooth.js:451
|
||||
#: ../js/ui/status/bluetooth.js:418 ../js/ui/status/bluetooth.js:452
|
||||
#, c-format
|
||||
msgid "Device %s wants to pair with this computer"
|
||||
msgstr "ההתקן %s מעוניין בצימוד עם מחשב זה"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:418
|
||||
#: ../js/ui/status/bluetooth.js:419
|
||||
#, c-format
|
||||
msgid "Please confirm whether the PIN '%s' matches the one on the device."
|
||||
msgstr "נא לאשר האם קוד ה־PIN '%s' תואם את זה שמופיע בהתקן."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:420
|
||||
#: ../js/ui/status/bluetooth.js:421
|
||||
msgid "Matches"
|
||||
msgstr "התאמות"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:421
|
||||
#: ../js/ui/status/bluetooth.js:422
|
||||
msgid "Does not match"
|
||||
msgstr "אינו תואם"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:444
|
||||
#: ../js/ui/status/bluetooth.js:445
|
||||
#, c-format
|
||||
msgid "Pairing request for %s"
|
||||
msgstr "בקשת צימוד עבור %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:452
|
||||
#: ../js/ui/status/bluetooth.js:453
|
||||
msgid "Please enter the PIN mentioned on the device."
|
||||
msgstr "נא להזין את קוד ה־PIN המוזכר בהתקן."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:468
|
||||
#: ../js/ui/status/bluetooth.js:469
|
||||
msgid "OK"
|
||||
msgstr "אישור"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:469
|
||||
msgid "Cancel"
|
||||
msgstr "ביטול"
|
||||
#: ../js/ui/status/keyboard.js:78
|
||||
msgid "Localization Settings"
|
||||
msgstr "הגדרות אוזריות"
|
||||
|
||||
#: ../js/ui/status/power.js:85
|
||||
msgid "Power Settings"
|
||||
@ -722,59 +818,59 @@ msgstr[0] "דקה אחת נותרה"
|
||||
msgstr[1] "%d דקות נותרו"
|
||||
msgstr[2] "שתי דקות נותרו"
|
||||
|
||||
#: ../js/ui/status/power.js:237
|
||||
#: ../js/ui/status/power.js:235
|
||||
msgid "AC adapter"
|
||||
msgstr "מתאם חשמל"
|
||||
|
||||
#: ../js/ui/status/power.js:239
|
||||
#: ../js/ui/status/power.js:237
|
||||
msgid "Laptop battery"
|
||||
msgstr "סוללת נייד"
|
||||
|
||||
#: ../js/ui/status/power.js:241
|
||||
#: ../js/ui/status/power.js:239
|
||||
msgid "UPS"
|
||||
msgstr "אל־פסק"
|
||||
|
||||
#: ../js/ui/status/power.js:243
|
||||
#: ../js/ui/status/power.js:241
|
||||
msgid "Monitor"
|
||||
msgstr "צג"
|
||||
|
||||
#: ../js/ui/status/power.js:245
|
||||
#: ../js/ui/status/power.js:243
|
||||
msgid "Mouse"
|
||||
msgstr "עכבר"
|
||||
|
||||
#: ../js/ui/status/power.js:247
|
||||
#: ../js/ui/status/power.js:245
|
||||
msgid "Keyboard"
|
||||
msgstr "מקלדת"
|
||||
|
||||
#: ../js/ui/status/power.js:249
|
||||
#: ../js/ui/status/power.js:247
|
||||
msgid "PDA"
|
||||
msgstr "מחשב כף יד"
|
||||
|
||||
#: ../js/ui/status/power.js:251
|
||||
#: ../js/ui/status/power.js:249
|
||||
msgid "Cell phone"
|
||||
msgstr "טלפון סלולרי"
|
||||
|
||||
#: ../js/ui/status/power.js:253
|
||||
#: ../js/ui/status/power.js:251
|
||||
msgid "Media player"
|
||||
msgstr "נגן מדיה"
|
||||
|
||||
#: ../js/ui/status/power.js:255
|
||||
#: ../js/ui/status/power.js:253
|
||||
msgid "Tablet"
|
||||
msgstr "טבלת שליטה"
|
||||
|
||||
#: ../js/ui/status/power.js:257
|
||||
#: ../js/ui/status/power.js:255
|
||||
msgid "Computer"
|
||||
msgstr "מחשב"
|
||||
|
||||
#: ../js/ui/status/power.js:259 ../src/shell-app-system.c:1012
|
||||
#: ../js/ui/status/power.js:257 ../src/shell-app-system.c:1012
|
||||
msgid "Unknown"
|
||||
msgstr "לא ידוע"
|
||||
|
||||
#: ../js/ui/status/volume.js:41
|
||||
#: ../js/ui/status/volume.js:42
|
||||
msgid "Volume"
|
||||
msgstr "עצמה"
|
||||
|
||||
#: ../js/ui/status/volume.js:54
|
||||
#: ../js/ui/status/volume.js:55
|
||||
msgid "Microphone"
|
||||
msgstr "מיקרופון"
|
||||
|
||||
@ -820,12 +916,12 @@ msgstr "%s סיים את תהליך ההתחלה"
|
||||
msgid "'%s' is ready"
|
||||
msgstr "'%s' מוכן"
|
||||
|
||||
#: ../js/ui/workspacesView.js:244
|
||||
#: ../js/ui/workspacesView.js:243
|
||||
msgid ""
|
||||
"Can't add a new workspace because maximum workspaces limit has been reached."
|
||||
msgstr "לא ניתן להוסיף מרחבי עבודה כיוון שהם ממלאים את המכסה המרבית."
|
||||
|
||||
#: ../js/ui/workspacesView.js:260
|
||||
#: ../js/ui/workspacesView.js:259
|
||||
msgid "Can't remove the first workspace."
|
||||
msgstr "לא ניתן להסיר את מרחב העבודה הראשון."
|
||||
|
||||
@ -853,11 +949,11 @@ msgstr[2] "2 קלטים"
|
||||
msgid "System Sounds"
|
||||
msgstr "צלילי מערכת"
|
||||
|
||||
#: ../src/shell-global.c:1233
|
||||
#: ../src/shell-global.c:1365
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "לפני פחות מדקה"
|
||||
|
||||
#: ../src/shell-global.c:1237
|
||||
#: ../src/shell-global.c:1369
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
@ -865,7 +961,7 @@ msgstr[0] "לפני דקה"
|
||||
msgstr[1] "לפני %d דקות"
|
||||
msgstr[2] "לפני 2 דקות"
|
||||
|
||||
#: ../src/shell-global.c:1242
|
||||
#: ../src/shell-global.c:1374
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
@ -873,7 +969,7 @@ msgstr[0] "לפני שעה"
|
||||
msgstr[1] "לפני %d שעות"
|
||||
msgstr[2] "לפני שעתיים"
|
||||
|
||||
#: ../src/shell-global.c:1247
|
||||
#: ../src/shell-global.c:1379
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
@ -881,7 +977,7 @@ msgstr[0] "לפני יום"
|
||||
msgstr[1] "לפני %d ימים"
|
||||
msgstr[2] "לפני יומיים"
|
||||
|
||||
#: ../src/shell-global.c:1252
|
||||
#: ../src/shell-global.c:1384
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
@ -1010,12 +1106,6 @@ msgstr "%1$s: %2$s"
|
||||
#~ msgid "Invisible"
|
||||
#~ msgstr "בלתי נראה"
|
||||
|
||||
#~ msgid "Restart..."
|
||||
#~ msgstr "הפעלה מחדש..."
|
||||
|
||||
#~ msgid "Account Information..."
|
||||
#~ msgstr "פרטי המשתמש..."
|
||||
|
||||
#~ msgid "ON"
|
||||
#~ msgstr "1"
|
||||
|
||||
|
466
po/it.po
466
po/it.po
@ -3,13 +3,13 @@
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
#
|
||||
# Milo Casagrande <milo@ubuntu.com>, 2009, 2010.
|
||||
# Luca Ferretti <lferrett@gnome.org>, 2010.
|
||||
# Luca Ferretti <lferrett@gnome.org>, 2010, 2011.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2010-12-20 22:54+0100\n"
|
||||
"PO-Revision-Date: 2010-12-20 22:55+0100\n"
|
||||
"POT-Creation-Date: 2011-01-29 16:06+0100\n"
|
||||
"PO-Revision-Date: 2011-01-29 16:06+0100\n"
|
||||
"Last-Translator: Luca Ferretti <lferrett@gnome.org>\n"
|
||||
"Language-Team: Italian <tp@lists.linux.it>\n"
|
||||
"Language: it\n"
|
||||
@ -26,14 +26,6 @@ msgstr "GNOME Shell"
|
||||
msgid "Window management and application launching"
|
||||
msgstr "Gestisce finestre e avvia applicazioni"
|
||||
|
||||
#: ../data/gnome-shell-clock-preferences.desktop.in.in.h:1
|
||||
msgid "Clock"
|
||||
msgstr "Orologio"
|
||||
|
||||
#: ../data/gnome-shell-clock-preferences.desktop.in.in.h:2
|
||||
msgid "Customize the panel clock"
|
||||
msgstr "Personalizza l'orologio sul pannello"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:1
|
||||
msgid ""
|
||||
"Allows access to internal debugging and monitoring tools using the Alt-F2 "
|
||||
@ -43,24 +35,20 @@ msgstr ""
|
||||
"utilizzando il dialogo Alt-F2."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:2
|
||||
msgid "Custom format of the clock"
|
||||
msgstr "Formato personalizzato dell'orologio"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:3
|
||||
msgid "Enable internal tools useful for developers and testers from Alt-F2"
|
||||
msgstr ""
|
||||
"Abilita gli strumenti interni utili a sviluppatori e beta-tester attraverso "
|
||||
"Alt-F2"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:4
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:3
|
||||
msgid "File extension used for storing the screencast"
|
||||
msgstr "Estensione del file utilizzato per salvare lo screencast"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:5
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:4
|
||||
msgid "Framerate used for recording screencasts."
|
||||
msgstr "Framerate per la registrazione di screencast."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:6
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:5
|
||||
msgid ""
|
||||
"GNOME Shell extensions have a uuid property; this key lists extensions which "
|
||||
"should not be loaded."
|
||||
@ -68,39 +56,28 @@ msgstr ""
|
||||
"Le estensioni per la GNOME Shell dispongono di una proprietà UUID: questa "
|
||||
"chiave elenca le estensioni che non dovrebbero essere caricate."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:7
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:6
|
||||
msgid "History for command (Alt-F2) dialog"
|
||||
msgstr "Cronologia per il dialogo dei comandi (Alt-F2)"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:7
|
||||
msgid "If true, display date in the clock, in addition to time."
|
||||
msgstr "Se VERO, mostra nell'orologio la data, oltre all'orario."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:8
|
||||
msgid "Hour format"
|
||||
msgstr "Formato orario"
|
||||
msgid "If true, display seconds in time."
|
||||
msgstr "Se VERO, mostra i secondi nell'orario."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:9
|
||||
msgid ""
|
||||
"If true and format is either \"12-hour\" or \"24-hour\", display date in the "
|
||||
"clock, in addition to time."
|
||||
msgstr ""
|
||||
"Se VERO e il formato è \"12-hour\" oppure \"24-hour\", visualizza anche la "
|
||||
"data nell'orologio oltre all'orario."
|
||||
msgid "If true, display the ISO week date in the calendar."
|
||||
msgstr "Se VERO, mostra il giorno della settimana ISO nel calendario."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:10
|
||||
msgid ""
|
||||
"If true and format is either \"12-hour\" or \"24-hour\", display seconds in "
|
||||
"time."
|
||||
msgstr ""
|
||||
"Se VERO e il formato è \"12-hour\" oppure \"24-hour\", visualizza i secondi "
|
||||
"nell'ora."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:11
|
||||
msgid "If true, display the ISO week date in the calendar."
|
||||
msgstr "Se VERO, visualizza il giorno della settimana ISO nel calendario."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:12
|
||||
msgid "List of desktop file IDs for favorite applications"
|
||||
msgstr "Elenco di ID di file desktop per le applicazioni preferite"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:13
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:12
|
||||
#, fuzzy, no-c-format
|
||||
msgid ""
|
||||
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
|
||||
"used for gst-launch. The pipeline should have an unconnected sink pad where "
|
||||
@ -109,7 +86,9 @@ msgid ""
|
||||
"pipeline can also take care of its own output - this might be used to send "
|
||||
"the output to an icecast server via shout2send or similar. When unset or set "
|
||||
"to an empty value, the default pipeline will be used. This is currently "
|
||||
"'videorate ! theoraenc ! oggmux' and records to Ogg Theora."
|
||||
"'videorate ! vp8enc quality=10 speed=2 threads=%T ! queue ! webmmux' and "
|
||||
"records to WEBM using the VP8 codec. %T is used as a placeholder for a guess "
|
||||
"at the optimal thread count on the system."
|
||||
msgstr ""
|
||||
"Imposta la pipeline di GStreamer utilizzata per codificare le registrazioni, "
|
||||
"seguendo la sintassi di gst-launch. La pipeline dovrebbe disporre di un sink "
|
||||
@ -121,19 +100,19 @@ msgstr ""
|
||||
"alcun valore, viene usata la pipeline predefinita il cui valore è "
|
||||
"\"videorate ! theoraenc ! oggmux\" e che registra nel formato Ogg Theora."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:14
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:13
|
||||
msgid "Show date in clock"
|
||||
msgstr "Mostra la data nell'orologio"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:15
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:14
|
||||
msgid "Show the week date in the calendar"
|
||||
msgstr "Mostra il giorno della settimana nel calendario"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:16
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:15
|
||||
msgid "Show time with seconds"
|
||||
msgstr "Mostra l'ora con i secondi"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:17
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:16
|
||||
msgid ""
|
||||
"The applications corresponding to these identifiers will be displayed in the "
|
||||
"favorites area."
|
||||
@ -141,7 +120,7 @@ msgstr ""
|
||||
"Le applicazioni che corrispondono a questi identificatori vengono "
|
||||
"visualizzate nell'area dei preferiti."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:18
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:17
|
||||
msgid ""
|
||||
"The filename for recorded screencasts will be a unique filename based on the "
|
||||
"current date, and use this extension. It should be changed when recording to "
|
||||
@ -151,7 +130,7 @@ msgstr ""
|
||||
"data corrente e utilizza questa estensione. Dovrebbe essere modificato "
|
||||
"quando si registra utilizzando un diverso formato contenitore."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:19
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:18
|
||||
msgid ""
|
||||
"The framerate of the resulting screencast recordered by GNOME Shell's "
|
||||
"screencast recorder in frames-per-second."
|
||||
@ -159,12 +138,12 @@ msgstr ""
|
||||
"Il framerate in fotogrammi al secondo dello screencast registrato attraverso "
|
||||
"il registratore della GNOME Shell."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:20
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:19
|
||||
msgid "The gstreamer pipeline used to encode the screencast"
|
||||
msgstr "La pipeline di gstreamer utilizzata per codificare lo screencast"
|
||||
|
||||
# (ndt) quel "in launchers" non mi convince...
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:21
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:20
|
||||
msgid ""
|
||||
"The shell normally monitors active applications in order to present the most "
|
||||
"used ones (e.g. in launchers). While this data will be kept private, you may "
|
||||
@ -176,44 +155,19 @@ msgstr ""
|
||||
"disabilitare questa funzionalità per motivi di privacy. I dati già salvati "
|
||||
"non verranno comunque rimossi."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:22
|
||||
msgid ""
|
||||
"This key specifies the format used by the panel clock when the format key is "
|
||||
"set to \"custom\". You can use conversion specifiers understood by strftime"
|
||||
"() to obtain a specific format. See the strftime() manual for more "
|
||||
"information."
|
||||
msgstr ""
|
||||
"Questa chiave indica il formato usato dall'orologio nel pannello quando la "
|
||||
"chiave specifica è impostata a \"custom\". È possibile utilizzare gli "
|
||||
"specificatori di formato compatibili con strftime(). Per maggiori "
|
||||
"informazioni, consultare il manuale di strftime()."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:23
|
||||
msgid ""
|
||||
"This key specifies the hour format used by the panel clock. Possible values "
|
||||
"are \"12-hour\", \"24-hour\", \"unix\" and \"custom\". If set to \"unix\", "
|
||||
"the clock will display time in seconds since Epoch, i.e. 1970-01-01. If set "
|
||||
"to \"custom\", the clock will display time according to the format specified "
|
||||
"in the custom_format key. Note that if set to either \"unix\" or \"custom\", "
|
||||
"the show_date and show_seconds keys are ignored."
|
||||
msgstr ""
|
||||
"Questa chiave indica il formato orario usato dall'orologio. I possibili "
|
||||
"valori sono \"12-hour\", \"24-hour\", \"unix\" e \"custom\". Se impostata a "
|
||||
"\"unix\", l'orologio visualizza l'ora in secondi a partire dall'era Epoch, "
|
||||
"cioè dal 1970-01-01. Se impostata a \"custom\", l'orologio visualizza l'ora "
|
||||
"in base al formato specificato nella chiave custom_format. Notare che se "
|
||||
"impostata a \"unix\" o \"custom\", le chiavi show_date e show_seconds non "
|
||||
"vengono considerate."
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:24
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:21
|
||||
msgid "Uuids of extensions to disable"
|
||||
msgstr "UUID delle estensioni da disabilitare"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:25
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:22
|
||||
msgid "Whether to collect stats about applications usage"
|
||||
msgstr ""
|
||||
"Indica se raccogliere statistiche riguardo l'utilizzo delle applicazioni"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:23
|
||||
msgid "disabled OpenSearch providers"
|
||||
msgstr ""
|
||||
|
||||
#: ../data/org.gnome.accessibility.magnifier.gschema.xml.in.h:1
|
||||
msgid "Clip the crosshairs at the center"
|
||||
msgstr ""
|
||||
@ -339,55 +293,47 @@ msgstr ""
|
||||
msgid "Width of the vertical and horizontal lines that make up the crosshairs."
|
||||
msgstr ""
|
||||
|
||||
#: ../data/clock-preferences.ui.h:1
|
||||
msgid "Clock Format"
|
||||
msgstr "Formato ora"
|
||||
#: ../js/misc/util.js:86
|
||||
msgid "Command not found"
|
||||
msgstr ""
|
||||
|
||||
#: ../data/clock-preferences.ui.h:2
|
||||
msgid "Clock Preferences"
|
||||
msgstr "Preferenze di Orologio"
|
||||
#. Replace "Error invoking GLib.shell_parse_argv: " with
|
||||
#. something nicer
|
||||
#: ../js/misc/util.js:113
|
||||
msgid "Could not parse command:"
|
||||
msgstr "Impossibile analizzare il comando:"
|
||||
|
||||
#: ../data/clock-preferences.ui.h:3
|
||||
msgid "Panel Display"
|
||||
msgstr "Visualizzazione sul pannello"
|
||||
#: ../js/misc/util.js:135
|
||||
msgid "No such application"
|
||||
msgstr "Applicazione inesistente"
|
||||
|
||||
#: ../data/clock-preferences.ui.h:4
|
||||
msgid "Show seco_nds"
|
||||
msgstr "Mostrare i _secondi"
|
||||
#: ../js/misc/util.js:148
|
||||
#, c-format
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "Esecuzione di «%s» non riuscita:"
|
||||
|
||||
#: ../data/clock-preferences.ui.h:5
|
||||
msgid "Show the _date"
|
||||
msgstr "Mostrare la _data"
|
||||
|
||||
#: ../data/clock-preferences.ui.h:6
|
||||
msgid "_12 hour format"
|
||||
msgstr "Formato _12 ore"
|
||||
|
||||
#: ../data/clock-preferences.ui.h:7
|
||||
msgid "_24 hour format"
|
||||
msgstr "Formato _24 ore"
|
||||
|
||||
#: ../js/ui/appDisplay.js:154
|
||||
#. Translators: Filter to display all applications
|
||||
#: ../js/ui/appDisplay.js:164
|
||||
msgid "All"
|
||||
msgstr "Tutte"
|
||||
|
||||
#: ../js/ui/appDisplay.js:235
|
||||
#: ../js/ui/appDisplay.js:245
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "APPLICAZIONI"
|
||||
|
||||
#: ../js/ui/appDisplay.js:265
|
||||
#: ../js/ui/appDisplay.js:275
|
||||
msgid "PREFERENCES"
|
||||
msgstr "PREFERENZE"
|
||||
|
||||
#: ../js/ui/appDisplay.js:562
|
||||
#: ../js/ui/appDisplay.js:572
|
||||
msgid "New Window"
|
||||
msgstr "Nuova finestra"
|
||||
|
||||
#: ../js/ui/appDisplay.js:566
|
||||
#: ../js/ui/appDisplay.js:576
|
||||
msgid "Remove from Favorites"
|
||||
msgstr "Rimuovi dai preferiti"
|
||||
|
||||
#: ../js/ui/appDisplay.js:567
|
||||
#: ../js/ui/appDisplay.js:577
|
||||
msgid "Add to Favorites"
|
||||
msgstr "Aggiungi ai preferiti"
|
||||
|
||||
@ -407,128 +353,205 @@ msgstr "%s è stato rimosso dai preferiti."
|
||||
msgid "Remove"
|
||||
msgstr "Rimuovi"
|
||||
|
||||
#: ../js/ui/docDisplay.js:494
|
||||
#: ../js/ui/docDisplay.js:18
|
||||
msgid "RECENT ITEMS"
|
||||
msgstr "Elementi recenti"
|
||||
msgstr "ELEMENTI RECENTI"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:552
|
||||
#: ../js/ui/endSessionDialog.js:63
|
||||
#, c-format
|
||||
msgid "Log Out %s"
|
||||
msgstr "Termina sessione di %s"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:64 ../js/ui/endSessionDialog.js:69
|
||||
msgid "Log Out"
|
||||
msgstr "Termina sessione"
|
||||
|
||||
# oddio... abbandonare il sistema sembra la nave che affonda... (LF)
|
||||
#: ../js/ui/endSessionDialog.js:65
|
||||
msgid "Click Log Out to quit these applications and log out of the system."
|
||||
msgstr ""
|
||||
"Fare clic su «Termina sessione» per chiudere queste applicazioni e "
|
||||
"abbandonare il sistema."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:66
|
||||
#, c-format
|
||||
msgid "%s will be logged out automatically in %d seconds."
|
||||
msgstr "La sessione di %s verrà terminata automaticamente tra %d secondi."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:67
|
||||
#, c-format
|
||||
msgid "You will be logged out automatically in %d seconds."
|
||||
msgstr "La sessione verrà terminata automaticamente tra %d secondi."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:68
|
||||
msgid "Logging out of the system."
|
||||
msgstr "Chiusura della sessione."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:74 ../js/ui/endSessionDialog.js:78
|
||||
msgid "Shut Down"
|
||||
msgstr "Arresta"
|
||||
|
||||
# usato un termine diverso, magari si capisce meglio (LF)
|
||||
#: ../js/ui/endSessionDialog.js:75
|
||||
msgid "Click Shut Down to quit these applications and shut down the system."
|
||||
msgstr ""
|
||||
"Fare clic su «Arresta» per chiudere queste applicazioni e spegnere il "
|
||||
"sistema."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:76
|
||||
#, c-format
|
||||
msgid "The system will shut down automatically in %d seconds."
|
||||
msgstr "Il sistema verrà arrestato automaticamente tra %d secondi."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:77
|
||||
msgid "Shutting down the system."
|
||||
msgstr "Arresto del sistema."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:84 ../js/ui/endSessionDialog.js:88
|
||||
msgid "Restart"
|
||||
msgstr "Riavvia"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:85
|
||||
msgid "Click Restart to quit these applications and restart the system."
|
||||
msgstr ""
|
||||
"Fare clic su «Riavvia» per chiudere queste applicazioni e riavviare il "
|
||||
"sistema."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:86
|
||||
#, c-format
|
||||
msgid "The system will restart automatically in %d seconds."
|
||||
msgstr "Il sistema verrà riavviato automaticamente tra %d secondi."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:87
|
||||
msgid "Restarting the system."
|
||||
msgstr "Riavvio del sistema."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:395
|
||||
msgid "Confirm"
|
||||
msgstr "Conferma"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:400 ../js/ui/status/bluetooth.js:470
|
||||
msgid "Cancel"
|
||||
msgstr "Annulla"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:556
|
||||
msgid "No extensions installed"
|
||||
msgstr "Nessuna estensione installata"
|
||||
|
||||
# (ndt) o abilitata?
|
||||
#: ../js/ui/lookingGlass.js:589
|
||||
#: ../js/ui/lookingGlass.js:593
|
||||
msgid "Enabled"
|
||||
msgstr "Abilitato"
|
||||
|
||||
# (ndt) o disabilitata?
|
||||
#. translators:
|
||||
#. * The device has been disabled
|
||||
#: ../js/ui/lookingGlass.js:591 ../src/gvc/gvc-mixer-control.c:1087
|
||||
#: ../js/ui/lookingGlass.js:595 ../src/gvc/gvc-mixer-control.c:1087
|
||||
msgid "Disabled"
|
||||
msgstr "Disabilitato"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:593
|
||||
#: ../js/ui/lookingGlass.js:597
|
||||
msgid "Error"
|
||||
msgstr "Errore"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:595
|
||||
#: ../js/ui/lookingGlass.js:599
|
||||
msgid "Out of date"
|
||||
msgstr "Non aggiornato"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:620
|
||||
#: ../js/ui/lookingGlass.js:624
|
||||
msgid "View Source"
|
||||
msgstr "Visualizza sorgente"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:626
|
||||
#: ../js/ui/lookingGlass.js:630
|
||||
msgid "Web Page"
|
||||
msgstr "Pagina web"
|
||||
|
||||
#: ../js/ui/overview.js:96
|
||||
#: ../js/ui/messageTray.js:1778
|
||||
msgid "System Information"
|
||||
msgstr "Informazione di sistema"
|
||||
|
||||
#: ../js/ui/overview.js:88
|
||||
msgid "Undo"
|
||||
msgstr "Annulla"
|
||||
|
||||
#: ../js/ui/overview.js:158
|
||||
#: ../js/ui/overview.js:159
|
||||
msgid "Windows"
|
||||
msgstr "Finestra"
|
||||
msgstr "Finestre"
|
||||
|
||||
#: ../js/ui/overview.js:161
|
||||
#: ../js/ui/overview.js:162
|
||||
msgid "Applications"
|
||||
msgstr "Applicazioni"
|
||||
|
||||
#. TODO - _quit() doesn't really work on apps in state STARTING yet
|
||||
#: ../js/ui/panel.js:474
|
||||
#: ../js/ui/panel.js:483
|
||||
#, c-format
|
||||
msgid "Quit %s"
|
||||
msgstr "Chiudi %s"
|
||||
|
||||
#: ../js/ui/panel.js:499
|
||||
msgid "Preferences"
|
||||
msgstr "Preferenze"
|
||||
|
||||
#. Translators: This is the time format with date used
|
||||
#. in 24-hour mode.
|
||||
#: ../js/ui/panel.js:585
|
||||
#: ../js/ui/panel.js:568
|
||||
msgid "%a %b %e, %R:%S"
|
||||
msgstr "%a %e %b, %k.%M.%S"
|
||||
|
||||
# (ndt) proviamo col k, se non funge, sappiamo il perché...
|
||||
#: ../js/ui/panel.js:586
|
||||
#: ../js/ui/panel.js:569
|
||||
msgid "%a %b %e, %R"
|
||||
msgstr "%a %e %b, %k.%M"
|
||||
|
||||
#. Translators: This is the time format without date used
|
||||
#. in 24-hour mode.
|
||||
#: ../js/ui/panel.js:590
|
||||
#: ../js/ui/panel.js:573
|
||||
msgid "%a %R:%S"
|
||||
msgstr "%a %k.%M.%S"
|
||||
|
||||
#: ../js/ui/panel.js:591
|
||||
#: ../js/ui/panel.js:574
|
||||
msgid "%a %R"
|
||||
msgstr "%a %k.%M"
|
||||
|
||||
#. Translators: This is a time format with date used
|
||||
#. for AM/PM.
|
||||
#: ../js/ui/panel.js:598
|
||||
#: ../js/ui/panel.js:581
|
||||
msgid "%a %b %e, %l:%M:%S %p"
|
||||
msgstr "%a %e %b, %l.%M.%S %P"
|
||||
|
||||
#: ../js/ui/panel.js:599
|
||||
#: ../js/ui/panel.js:582
|
||||
msgid "%a %b %e, %l:%M %p"
|
||||
msgstr "%a %e %b, %l.%M %P"
|
||||
|
||||
#. Translators: This is a time format without date used
|
||||
#. for AM/PM.
|
||||
#: ../js/ui/panel.js:603
|
||||
#: ../js/ui/panel.js:586
|
||||
msgid "%a %l:%M:%S %p"
|
||||
msgstr "%a %l.%M.%S %P"
|
||||
|
||||
#: ../js/ui/panel.js:604
|
||||
#: ../js/ui/panel.js:587
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %l.%M %P"
|
||||
|
||||
#. Button on the left side of the panel.
|
||||
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
|
||||
#: ../js/ui/panel.js:749
|
||||
#: ../js/ui/panel.js:732
|
||||
msgid "Activities"
|
||||
msgstr "Attività"
|
||||
|
||||
# (ndt) libera, ma unmount non si può proprio vedere...
|
||||
#: ../js/ui/placeDisplay.js:111
|
||||
#: ../js/ui/placeDisplay.js:106
|
||||
#, c-format
|
||||
msgid "Failed to unmount '%s'"
|
||||
msgstr "Impossibile scollegare «%s»"
|
||||
|
||||
#: ../js/ui/placeDisplay.js:114
|
||||
#: ../js/ui/placeDisplay.js:109
|
||||
msgid "Retry"
|
||||
msgstr "Riprova"
|
||||
|
||||
#: ../js/ui/placeDisplay.js:159
|
||||
#: ../js/ui/placeDisplay.js:150
|
||||
msgid "Connect to..."
|
||||
msgstr "Connetti a..."
|
||||
|
||||
#: ../js/ui/placeDisplay.js:558
|
||||
#: ../js/ui/placeDisplay.js:386
|
||||
msgid "PLACES & DEVICES"
|
||||
msgstr "Risorse e dispositivi"
|
||||
msgstr "RISORSE E DISPOSITIVI"
|
||||
|
||||
#. Translators: this MUST be either "toggle-switch-us"
|
||||
#. (for toggle switches containing the English words
|
||||
@ -537,86 +560,81 @@ msgstr "Risorse e dispositivi"
|
||||
#. simply result in invisible toggle switches.
|
||||
#: ../js/ui/popupMenu.js:33
|
||||
msgid "toggle-switch-us"
|
||||
msgstr "toggle-switch-intl"
|
||||
msgstr "toggle-switch-us"
|
||||
|
||||
#: ../js/ui/runDialog.js:233
|
||||
#: ../js/ui/runDialog.js:209
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Inserire un comando:"
|
||||
|
||||
#: ../js/ui/runDialog.js:378
|
||||
#, c-format
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "Esecuzione di «%s» non riuscita:"
|
||||
|
||||
#: ../js/ui/statusMenu.js:101
|
||||
#: ../js/ui/statusMenu.js:102
|
||||
msgid "Available"
|
||||
msgstr "Disponibile"
|
||||
|
||||
#: ../js/ui/statusMenu.js:106
|
||||
#: ../js/ui/statusMenu.js:107
|
||||
msgid "Busy"
|
||||
msgstr "Non disponibile"
|
||||
|
||||
#: ../js/ui/statusMenu.js:114
|
||||
#: ../js/ui/statusMenu.js:115
|
||||
msgid "My Account"
|
||||
msgstr "Account personale"
|
||||
|
||||
#: ../js/ui/statusMenu.js:118
|
||||
#: ../js/ui/statusMenu.js:119
|
||||
msgid "System Settings"
|
||||
msgstr "Impostazioni di sistema"
|
||||
|
||||
#: ../js/ui/statusMenu.js:125
|
||||
#: ../js/ui/statusMenu.js:126
|
||||
msgid "Lock Screen"
|
||||
msgstr "Blocca schermo"
|
||||
|
||||
#: ../js/ui/statusMenu.js:129
|
||||
#: ../js/ui/statusMenu.js:130
|
||||
msgid "Switch User"
|
||||
msgstr "Cambia utente"
|
||||
|
||||
#: ../js/ui/statusMenu.js:134
|
||||
#: ../js/ui/statusMenu.js:135
|
||||
msgid "Log Out..."
|
||||
msgstr "Termina sessione..."
|
||||
|
||||
#: ../js/ui/statusMenu.js:141
|
||||
#: ../js/ui/statusMenu.js:142
|
||||
msgid "Suspend..."
|
||||
msgstr "Sospendi..."
|
||||
|
||||
#: ../js/ui/statusMenu.js:145
|
||||
#: ../js/ui/statusMenu.js:146
|
||||
msgid "Shut Down..."
|
||||
msgstr "Arresta..."
|
||||
|
||||
#: ../js/ui/status/accessibility.js:82
|
||||
#: ../js/ui/status/accessibility.js:83
|
||||
msgid "Zoom"
|
||||
msgstr "Ingrandimento"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:88
|
||||
#: ../js/ui/status/accessibility.js:89
|
||||
msgid "Screen Reader"
|
||||
msgstr "Lettore schermo"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:91
|
||||
#: ../js/ui/status/accessibility.js:92
|
||||
msgid "Screen Keyboard"
|
||||
msgstr "Tastiera a schermo"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:94
|
||||
#: ../js/ui/status/accessibility.js:95
|
||||
msgid "Visual Alerts"
|
||||
msgstr "Allerte visive"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:97
|
||||
#: ../js/ui/status/accessibility.js:98
|
||||
msgid "Sticky Keys"
|
||||
msgstr "Permanenza tasti"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:100
|
||||
#: ../js/ui/status/accessibility.js:101
|
||||
msgid "Slow Keys"
|
||||
msgstr "Rallentamento tasti"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:103
|
||||
#: ../js/ui/status/accessibility.js:104
|
||||
msgid "Bounce Keys"
|
||||
msgstr "Pressione ravvicinata tasti"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:106
|
||||
#: ../js/ui/status/accessibility.js:107
|
||||
msgid "Mouse Keys"
|
||||
msgstr "Mouse da tastiera"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:110
|
||||
#: ../js/ui/status/accessibility.js:111
|
||||
msgid "Universal Access Settings"
|
||||
msgstr "Impostazioni accesso universale"
|
||||
|
||||
@ -628,7 +646,7 @@ msgstr "Contrasto elevato"
|
||||
msgid "Large Text"
|
||||
msgstr "Caratteri grandi"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:42 ../js/ui/status/bluetooth.js:200
|
||||
#: ../js/ui/status/bluetooth.js:42 ../js/ui/status/bluetooth.js:241
|
||||
msgid "Bluetooth"
|
||||
msgstr "Bluetooth"
|
||||
|
||||
@ -637,119 +655,119 @@ msgstr "Bluetooth"
|
||||
msgid "Visibility"
|
||||
msgstr "Rilevabile"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:68
|
||||
#: ../js/ui/status/bluetooth.js:69
|
||||
msgid "Send Files to Device..."
|
||||
msgstr "Invia file al dispositivo..."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:71
|
||||
#: ../js/ui/status/bluetooth.js:70
|
||||
msgid "Setup a New Device..."
|
||||
msgstr "Imposta un nuovo dispositivo..."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:94
|
||||
#: ../js/ui/status/bluetooth.js:95
|
||||
msgid "Bluetooth Settings"
|
||||
msgstr "Impostazioni Bluetooth"
|
||||
|
||||
# indica lo stato del device BT, per esempio gli auricolari
|
||||
# credo sia meglio l'aggettivo che il sostantivo
|
||||
#: ../js/ui/status/bluetooth.js:151
|
||||
#: ../js/ui/status/bluetooth.js:192
|
||||
msgid "Connection"
|
||||
msgstr "Collegato"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:187
|
||||
#: ../js/ui/status/bluetooth.js:228
|
||||
msgid "Send Files..."
|
||||
msgstr "Invia file..."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:192
|
||||
#: ../js/ui/status/bluetooth.js:233
|
||||
msgid "Browse Files..."
|
||||
msgstr "Esplora file..."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:201
|
||||
#: ../js/ui/status/bluetooth.js:242
|
||||
msgid "Error browsing device"
|
||||
msgstr "Errore nell'esplorare il dispositivo"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:202
|
||||
#: ../js/ui/status/bluetooth.js:243
|
||||
#, c-format
|
||||
msgid "The requested device cannot be browsed, error is '%s'"
|
||||
msgstr "Non è possibile esplorare il dispositivo richiesto, l'errore è «%s»"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:210
|
||||
#: ../js/ui/status/bluetooth.js:251
|
||||
msgid "Keyboard Settings"
|
||||
msgstr "Impostazioni tastiera"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:215
|
||||
#: ../js/ui/status/bluetooth.js:256
|
||||
msgid "Mouse Settings"
|
||||
msgstr "Impostazioni mouse"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:222 ../js/ui/status/volume.js:62
|
||||
#: ../js/ui/status/bluetooth.js:263 ../js/ui/status/volume.js:63
|
||||
msgid "Sound Settings"
|
||||
msgstr "Impostazioni audio"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:293 ../js/ui/status/bluetooth.js:327
|
||||
#: ../js/ui/status/bluetooth.js:367 ../js/ui/status/bluetooth.js:400
|
||||
#: ../js/ui/status/bluetooth.js:337 ../js/ui/status/bluetooth.js:371
|
||||
#: ../js/ui/status/bluetooth.js:411 ../js/ui/status/bluetooth.js:444
|
||||
msgid "Bluetooth Agent"
|
||||
msgstr ""
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:328
|
||||
#: ../js/ui/status/bluetooth.js:372
|
||||
#, c-format
|
||||
msgid "Authorization request from %s"
|
||||
msgstr "Richesta autorizzazione da %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:334
|
||||
#: ../js/ui/status/bluetooth.js:378
|
||||
#, c-format
|
||||
msgid "Device %s wants access to the service '%s'"
|
||||
msgstr "Il dispositivo %s vuole accedere al servizio «%s»"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:336
|
||||
#: ../js/ui/status/bluetooth.js:380
|
||||
msgid "Always grant access"
|
||||
msgstr "Consenti sempre accesso"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:337
|
||||
#: ../js/ui/status/bluetooth.js:381
|
||||
msgid "Grant this time only"
|
||||
msgstr "Consenti solo stavolta"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:338
|
||||
#: ../js/ui/status/bluetooth.js:382
|
||||
msgid "Reject"
|
||||
msgstr "Rifiuta"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:368
|
||||
#: ../js/ui/status/bluetooth.js:412
|
||||
#, c-format
|
||||
msgid "Pairing confirmation for %s"
|
||||
msgstr "Conferma associazione per %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:374 ../js/ui/status/bluetooth.js:408
|
||||
#: ../js/ui/status/bluetooth.js:418 ../js/ui/status/bluetooth.js:452
|
||||
#, c-format
|
||||
msgid "Device %s wants to pair with this computer"
|
||||
msgstr "Il dispositivo %s vuole associarsi con questo computer"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:375
|
||||
#: ../js/ui/status/bluetooth.js:419
|
||||
#, c-format
|
||||
msgid "Please confirm whether the PIN '%s' matches the one on the device."
|
||||
msgstr "Confermare la corrispondenza del PIN «%s» con quello sul dispositivo."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:377
|
||||
#: ../js/ui/status/bluetooth.js:421
|
||||
msgid "Matches"
|
||||
msgstr "Corrisponde"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:378
|
||||
#: ../js/ui/status/bluetooth.js:422
|
||||
msgid "Does not match"
|
||||
msgstr "Non corrisponde"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:401
|
||||
#: ../js/ui/status/bluetooth.js:445
|
||||
#, c-format
|
||||
msgid "Pairing request for %s"
|
||||
msgstr "Richiesta associazione per %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:409
|
||||
#: ../js/ui/status/bluetooth.js:453
|
||||
msgid "Please enter the PIN mentioned on the device."
|
||||
msgstr "Inserire il PIN indicato sul dispositivo."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:425
|
||||
#: ../js/ui/status/bluetooth.js:469
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:426
|
||||
msgid "Cancel"
|
||||
msgstr "Annulla"
|
||||
#: ../js/ui/status/keyboard.js:78
|
||||
msgid "Localization Settings"
|
||||
msgstr "Impostazioni localizzazione"
|
||||
|
||||
#: ../js/ui/status/power.js:85
|
||||
msgid "Power Settings"
|
||||
@ -787,79 +805,79 @@ msgid_plural "%d minutes remaining"
|
||||
msgstr[0] "%d minuto rimanente"
|
||||
msgstr[1] "%d minuti rimanenti"
|
||||
|
||||
#: ../js/ui/status/power.js:237
|
||||
#: ../js/ui/status/power.js:235
|
||||
msgid "AC adapter"
|
||||
msgstr "Alimentatore di corrente"
|
||||
|
||||
#: ../js/ui/status/power.js:239
|
||||
#: ../js/ui/status/power.js:237
|
||||
msgid "Laptop battery"
|
||||
msgstr "Batteria del portatile"
|
||||
|
||||
#: ../js/ui/status/power.js:241
|
||||
#: ../js/ui/status/power.js:239
|
||||
msgid "UPS"
|
||||
msgstr "UPS"
|
||||
|
||||
#: ../js/ui/status/power.js:243
|
||||
#: ../js/ui/status/power.js:241
|
||||
msgid "Monitor"
|
||||
msgstr "Monitor"
|
||||
|
||||
#: ../js/ui/status/power.js:245
|
||||
#: ../js/ui/status/power.js:243
|
||||
msgid "Mouse"
|
||||
msgstr "Mouse"
|
||||
|
||||
#: ../js/ui/status/power.js:247
|
||||
#: ../js/ui/status/power.js:245
|
||||
msgid "Keyboard"
|
||||
msgstr "Tastiera"
|
||||
|
||||
#: ../js/ui/status/power.js:249
|
||||
#: ../js/ui/status/power.js:247
|
||||
msgid "PDA"
|
||||
msgstr "PDS"
|
||||
|
||||
# c'era una discussione su tp...
|
||||
#: ../js/ui/status/power.js:251
|
||||
#: ../js/ui/status/power.js:249
|
||||
msgid "Cell phone"
|
||||
msgstr "Cellulare"
|
||||
|
||||
#: ../js/ui/status/power.js:253
|
||||
#: ../js/ui/status/power.js:251
|
||||
msgid "Media player"
|
||||
msgstr "Lettore multimediale"
|
||||
|
||||
#: ../js/ui/status/power.js:255
|
||||
#: ../js/ui/status/power.js:253
|
||||
msgid "Tablet"
|
||||
msgstr "Tablet"
|
||||
|
||||
#: ../js/ui/status/power.js:257
|
||||
#: ../js/ui/status/power.js:255
|
||||
msgid "Computer"
|
||||
msgstr "Computer"
|
||||
|
||||
#: ../js/ui/status/power.js:259 ../src/shell-app-system.c:1012
|
||||
#: ../js/ui/status/power.js:257 ../src/shell-app-system.c:1012
|
||||
msgid "Unknown"
|
||||
msgstr "Sconosciuto"
|
||||
|
||||
#: ../js/ui/status/volume.js:41
|
||||
#: ../js/ui/status/volume.js:42
|
||||
msgid "Volume"
|
||||
msgstr "Volume"
|
||||
|
||||
#: ../js/ui/status/volume.js:54
|
||||
#: ../js/ui/status/volume.js:55
|
||||
msgid "Microphone"
|
||||
msgstr "Microfono"
|
||||
|
||||
#: ../js/ui/telepathyClient.js:560
|
||||
#: ../js/ui/telepathyClient.js:561
|
||||
#, c-format
|
||||
msgid "%s is online."
|
||||
msgstr "%s è disponibile."
|
||||
|
||||
#: ../js/ui/telepathyClient.js:565
|
||||
#: ../js/ui/telepathyClient.js:566
|
||||
#, c-format
|
||||
msgid "%s is offline."
|
||||
msgstr "%s è fuori rete."
|
||||
|
||||
#: ../js/ui/telepathyClient.js:568
|
||||
#: ../js/ui/telepathyClient.js:569
|
||||
#, c-format
|
||||
msgid "%s is away."
|
||||
msgstr "%s è assente."
|
||||
|
||||
#: ../js/ui/telepathyClient.js:571
|
||||
#: ../js/ui/telepathyClient.js:572
|
||||
#, c-format
|
||||
msgid "%s is busy."
|
||||
msgstr "%s non è disponibile."
|
||||
@ -867,10 +885,10 @@ msgstr "%s non è disponibile."
|
||||
#. Translators: this is a time format string followed by a date.
|
||||
#. If applicable, replace %X with a strftime format valid for your
|
||||
#. locale, without seconds.
|
||||
#: ../js/ui/telepathyClient.js:664
|
||||
#: ../js/ui/telepathyClient.js:666
|
||||
#, no-c-format
|
||||
msgid "Sent at %X on %A"
|
||||
msgstr "Inviato alle %-H.%M.%S di %A"
|
||||
msgstr "Inviato alle %-H.%M di %A"
|
||||
|
||||
# FIXME ma ha senso in inglese???
|
||||
#: ../js/ui/viewSelector.js:26
|
||||
@ -889,14 +907,14 @@ msgid "'%s' is ready"
|
||||
msgstr "«%s» è pronto"
|
||||
|
||||
# (ndt) un po' liberetta...
|
||||
#: ../js/ui/workspacesView.js:244
|
||||
#: ../js/ui/workspacesView.js:243
|
||||
msgid ""
|
||||
"Can't add a new workspace because maximum workspaces limit has been reached."
|
||||
msgstr ""
|
||||
"Impossibile aggiungere un nuovo spazio di lavoro: raggiunto il limite "
|
||||
"massimo consentito."
|
||||
|
||||
#: ../js/ui/workspacesView.js:260
|
||||
#: ../js/ui/workspacesView.js:259
|
||||
msgid "Can't remove the first workspace."
|
||||
msgstr "Impossibile rimuovere il primo spazio di lavoro."
|
||||
|
||||
@ -922,32 +940,32 @@ msgstr[1] "%u ingressi"
|
||||
msgid "System Sounds"
|
||||
msgstr "Audio di sistema"
|
||||
|
||||
#: ../src/shell-global.c:1155
|
||||
#: ../src/shell-global.c:1365
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Meno di un minuto fa"
|
||||
|
||||
#: ../src/shell-global.c:1159
|
||||
#: ../src/shell-global.c:1369
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d minuto fa"
|
||||
msgstr[1] "%d minuti fa"
|
||||
|
||||
#: ../src/shell-global.c:1164
|
||||
#: ../src/shell-global.c:1374
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d ora fa"
|
||||
msgstr[1] "%d ore fa"
|
||||
|
||||
#: ../src/shell-global.c:1169
|
||||
#: ../src/shell-global.c:1379
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d giorno fa"
|
||||
msgstr[1] "%d giorni fa"
|
||||
|
||||
#: ../src/shell-global.c:1174
|
||||
#: ../src/shell-global.c:1384
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
|
513
po/nb.po
513
po/nb.po
@ -2,14 +2,14 @@
|
||||
# Copyright (C) 2009 THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the gnome-shell package.
|
||||
#
|
||||
# Kjartan Maraas <kmaraas@gnome.org>, 2009-2010.
|
||||
# Kjartan Maraas <kmaraas@gnome.org>, 2009-2011.
|
||||
# Torstein Adolf Winterseth <kvikende@fsfe.org>, 2010.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: gnome-shell 2.91.x\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-01-04 19:39+0100\n"
|
||||
"PO-Revision-Date: 2011-01-04 19:43+0100\n"
|
||||
"POT-Creation-Date: 2011-02-02 20:31+0100\n"
|
||||
"PO-Revision-Date: 2011-02-02 20:34+0100\n"
|
||||
"Last-Translator: Torstein Adolf Winterseth <kvikende@fsfe.org>\n"
|
||||
"Language-Team: Norwegian Bokmål <i18n-nb@lister.ping.uio.no>\n"
|
||||
"Language: \n"
|
||||
@ -73,7 +73,8 @@ msgstr ""
|
||||
msgid "List of desktop file IDs for favorite applications"
|
||||
msgstr ""
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:11
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:12
|
||||
#, no-c-format
|
||||
msgid ""
|
||||
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
|
||||
"used for gst-launch. The pipeline should have an unconnected sink pad where "
|
||||
@ -82,45 +83,47 @@ msgid ""
|
||||
"pipeline can also take care of its own output - this might be used to send "
|
||||
"the output to an icecast server via shout2send or similar. When unset or set "
|
||||
"to an empty value, the default pipeline will be used. This is currently "
|
||||
"'videorate ! theoraenc ! oggmux' and records to Ogg Theora."
|
||||
"'videorate ! vp8enc quality=10 speed=2 threads=%T ! queue ! webmmux' and "
|
||||
"records to WEBM using the VP8 codec. %T is used as a placeholder for a guess "
|
||||
"at the optimal thread count on the system."
|
||||
msgstr ""
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:12
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:13
|
||||
msgid "Show date in clock"
|
||||
msgstr "Vis dato i klokken"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:13
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:14
|
||||
msgid "Show the week date in the calendar"
|
||||
msgstr "Vis dato for uken i kalender"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:14
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:15
|
||||
msgid "Show time with seconds"
|
||||
msgstr "Vis tid med sekunder"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:15
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:16
|
||||
msgid ""
|
||||
"The applications corresponding to these identifiers will be displayed in the "
|
||||
"favorites area."
|
||||
msgstr ""
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:16
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:17
|
||||
msgid ""
|
||||
"The filename for recorded screencasts will be a unique filename based on the "
|
||||
"current date, and use this extension. It should be changed when recording to "
|
||||
"a different container format."
|
||||
msgstr ""
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:17
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:18
|
||||
msgid ""
|
||||
"The framerate of the resulting screencast recordered by GNOME Shell's "
|
||||
"screencast recorder in frames-per-second."
|
||||
msgstr ""
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:18
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:19
|
||||
msgid "The gstreamer pipeline used to encode the screencast"
|
||||
msgstr ""
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:19
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:20
|
||||
msgid ""
|
||||
"The shell normally monitors active applications in order to present the most "
|
||||
"used ones (e.g. in launchers). While this data will be kept private, you may "
|
||||
@ -128,14 +131,18 @@ msgid ""
|
||||
"remove already saved data."
|
||||
msgstr ""
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:20
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:21
|
||||
msgid "Uuids of extensions to disable"
|
||||
msgstr "Uuider på utvidelser som skal slås av"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:21
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:22
|
||||
msgid "Whether to collect stats about applications usage"
|
||||
msgstr "Om det skal samles statistikk om bruk av programmer"
|
||||
|
||||
#: ../data/org.gnome.shell.gschema.xml.in.h:23
|
||||
msgid "disabled OpenSearch providers"
|
||||
msgstr ""
|
||||
|
||||
#: ../data/org.gnome.accessibility.magnifier.gschema.xml.in.h:1
|
||||
msgid "Clip the crosshairs at the center"
|
||||
msgstr ""
|
||||
@ -261,28 +268,47 @@ msgstr ""
|
||||
msgid "Width of the vertical and horizontal lines that make up the crosshairs."
|
||||
msgstr ""
|
||||
|
||||
#: ../js/misc/util.js:86
|
||||
msgid "Command not found"
|
||||
msgstr "Kommando ikke funnet"
|
||||
|
||||
#. Replace "Error invoking GLib.shell_parse_argv: " with
|
||||
#. something nicer
|
||||
#: ../js/misc/util.js:113
|
||||
msgid "Could not parse command:"
|
||||
msgstr "Klarte ikke å lese kommando:"
|
||||
|
||||
#: ../js/misc/util.js:135
|
||||
msgid "No such application"
|
||||
msgstr "Programmet finnes ikke"
|
||||
|
||||
#: ../js/misc/util.js:148
|
||||
#, c-format
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "Kjøring av «%s» feilet:"
|
||||
|
||||
#. Translators: Filter to display all applications
|
||||
#: ../js/ui/appDisplay.js:155
|
||||
#: ../js/ui/appDisplay.js:164
|
||||
msgid "All"
|
||||
msgstr "Alle"
|
||||
|
||||
#: ../js/ui/appDisplay.js:236
|
||||
#: ../js/ui/appDisplay.js:245
|
||||
msgid "APPLICATIONS"
|
||||
msgstr "PROGRAMMER"
|
||||
|
||||
#: ../js/ui/appDisplay.js:266
|
||||
#: ../js/ui/appDisplay.js:275
|
||||
msgid "PREFERENCES"
|
||||
msgstr "BRUKERVALG"
|
||||
|
||||
#: ../js/ui/appDisplay.js:563
|
||||
#: ../js/ui/appDisplay.js:572
|
||||
msgid "New Window"
|
||||
msgstr "Nytt vindu"
|
||||
|
||||
#: ../js/ui/appDisplay.js:567
|
||||
#: ../js/ui/appDisplay.js:576
|
||||
msgid "Remove from Favorites"
|
||||
msgstr "Fjern fra favoritter"
|
||||
|
||||
#: ../js/ui/appDisplay.js:568
|
||||
#: ../js/ui/appDisplay.js:577
|
||||
msgid "Add to Favorites"
|
||||
msgstr "Legg til i favoritter"
|
||||
|
||||
@ -296,122 +322,290 @@ msgstr "%s ble lagt til i dine favoritter."
|
||||
msgid "%s has been removed from your favorites."
|
||||
msgstr "%s ble fjernet fra dine favoritter."
|
||||
|
||||
#. Translators: Shown in calendar event list for all day events
|
||||
#: ../js/ui/calendar.js:62
|
||||
msgid "All Day"
|
||||
msgstr "Hele dagen"
|
||||
|
||||
#. Translators: Calendar grid abbreviation for Sunday.
|
||||
#. *
|
||||
#. * NOTE: These abbreviations are always shown together and in
|
||||
#. * order, e.g. "S M T W T F S".
|
||||
#.
|
||||
#. Translators: Calendar grid abbreviation for Saturday
|
||||
#. Translators: Event list abbreviation for Saturday
|
||||
#: ../js/ui/calendar.js:112 ../js/ui/calendar.js:124 ../js/ui/calendar.js:149
|
||||
msgid "S"
|
||||
msgstr "S"
|
||||
|
||||
#. Translators: Calendar grid abbreviation for Monday
|
||||
#. Translators: Event list abbreviation for Monday
|
||||
#: ../js/ui/calendar.js:114 ../js/ui/calendar.js:139
|
||||
msgid "M"
|
||||
msgstr "M"
|
||||
|
||||
#. Translators: Calendar grid abbreviation for Tuesday
|
||||
#. Translators: Calendar grid abbreviation for Thursday
|
||||
#. Translators: Event list abbreviation for Tuesday
|
||||
#: ../js/ui/calendar.js:116 ../js/ui/calendar.js:120 ../js/ui/calendar.js:141
|
||||
msgid "T"
|
||||
msgstr "T"
|
||||
|
||||
#. Translators: Calendar grid abbreviation for Wednesday
|
||||
#. Translators: Event list abbreviation for Wednesday
|
||||
#: ../js/ui/calendar.js:118 ../js/ui/calendar.js:143
|
||||
msgid "W"
|
||||
msgstr "O"
|
||||
|
||||
#. Translators: Calendar grid abbreviation for Friday
|
||||
#. Translators: Event list abbreviation for Friday
|
||||
#: ../js/ui/calendar.js:122 ../js/ui/calendar.js:147
|
||||
msgid "F"
|
||||
msgstr "F"
|
||||
|
||||
#. Translators: Event list abbreviation for Sunday.
|
||||
#. *
|
||||
#. * NOTE: These abbreviations are normally not shown together
|
||||
#. * so they need to be unique (e.g. Tuesday and Thursday cannot
|
||||
#. * both be 'T').
|
||||
#.
|
||||
#: ../js/ui/calendar.js:137
|
||||
msgid "Su"
|
||||
msgstr "Sø"
|
||||
|
||||
#. Translators: Event list abbreviation for Thursday
|
||||
#: ../js/ui/calendar.js:145
|
||||
msgid "Th"
|
||||
msgstr "To"
|
||||
|
||||
#. Translators: Text to show if there are no events
|
||||
#: ../js/ui/calendar.js:696
|
||||
msgid "Nothing Scheduled"
|
||||
msgstr "Ingenting planlagt"
|
||||
|
||||
#: ../js/ui/calendar.js:723
|
||||
msgid "Today"
|
||||
msgstr "I dag"
|
||||
|
||||
#: ../js/ui/calendar.js:727
|
||||
msgid "Tomorrow"
|
||||
msgstr "I morgen"
|
||||
|
||||
#: ../js/ui/calendar.js:736
|
||||
msgid "This week"
|
||||
msgstr "Denne uken"
|
||||
|
||||
#: ../js/ui/calendar.js:744
|
||||
msgid "Next week"
|
||||
msgstr "Neste uke"
|
||||
|
||||
#: ../js/ui/dash.js:27
|
||||
msgid "Remove"
|
||||
msgstr "Fjern"
|
||||
|
||||
#: ../js/ui/docDisplay.js:494
|
||||
msgid "RECENT ITEMS"
|
||||
msgstr "SISTE OPPFØRINGER"
|
||||
#: ../js/ui/dateMenu.js:91
|
||||
msgid "Date and Time Settings"
|
||||
msgstr "Innstillinger for dato og klokkeslett"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:552
|
||||
msgid "No extensions installed"
|
||||
msgstr "Ingen utvidelser installert"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:589
|
||||
msgid "Enabled"
|
||||
msgstr "Aktivert"
|
||||
|
||||
#. translators:
|
||||
#. * The device has been disabled
|
||||
#: ../js/ui/lookingGlass.js:591 ../src/gvc/gvc-mixer-control.c:1087
|
||||
msgid "Disabled"
|
||||
msgstr "Deaktivert"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:593
|
||||
msgid "Error"
|
||||
msgstr "Feil"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:595
|
||||
msgid "Out of date"
|
||||
msgstr "Utdatert"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:620
|
||||
msgid "View Source"
|
||||
msgstr "Vis kildekode"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:626
|
||||
msgid "Web Page"
|
||||
msgstr "Nettside"
|
||||
|
||||
#: ../js/ui/overview.js:96
|
||||
msgid "Undo"
|
||||
msgstr "Angre"
|
||||
|
||||
#: ../js/ui/overview.js:158
|
||||
msgid "Windows"
|
||||
msgstr "Vinduer"
|
||||
|
||||
#: ../js/ui/overview.js:161
|
||||
msgid "Applications"
|
||||
msgstr "Programmer"
|
||||
|
||||
#. TODO - _quit() doesn't really work on apps in state STARTING yet
|
||||
#: ../js/ui/panel.js:476
|
||||
#, c-format
|
||||
msgid "Quit %s"
|
||||
msgstr "Avslutt %s"
|
||||
#: ../js/ui/dateMenu.js:110
|
||||
msgid "Open Calendar"
|
||||
msgstr "Åpne kalender"
|
||||
|
||||
#. Translators: This is the time format with date used
|
||||
#. in 24-hour mode.
|
||||
#: ../js/ui/panel.js:561
|
||||
#: ../js/ui/dateMenu.js:149
|
||||
msgid "%a %b %e, %R:%S"
|
||||
msgstr "%a %e %b, %R.%S"
|
||||
|
||||
#: ../js/ui/panel.js:562
|
||||
#: ../js/ui/dateMenu.js:150
|
||||
msgid "%a %b %e, %R"
|
||||
msgstr "%a %e %b, %R"
|
||||
|
||||
#. Translators: This is the time format without date used
|
||||
#. in 24-hour mode.
|
||||
#: ../js/ui/panel.js:566
|
||||
#: ../js/ui/dateMenu.js:154
|
||||
msgid "%a %R:%S"
|
||||
msgstr "%a %R.%S"
|
||||
|
||||
#: ../js/ui/panel.js:567
|
||||
#: ../js/ui/dateMenu.js:155
|
||||
msgid "%a %R"
|
||||
msgstr "%a %R"
|
||||
|
||||
#. Translators: This is a time format with date used
|
||||
#. for AM/PM.
|
||||
#: ../js/ui/panel.js:574
|
||||
#: ../js/ui/dateMenu.js:162
|
||||
msgid "%a %b %e, %l:%M:%S %p"
|
||||
msgstr "%a %e %b, %l.%M.%S %p"
|
||||
|
||||
#: ../js/ui/panel.js:575
|
||||
#: ../js/ui/dateMenu.js:163
|
||||
msgid "%a %b %e, %l:%M %p"
|
||||
msgstr "%a %e %b, %l.%M %p"
|
||||
|
||||
#. Translators: This is a time format without date used
|
||||
#. for AM/PM.
|
||||
#: ../js/ui/panel.js:579
|
||||
#: ../js/ui/dateMenu.js:167
|
||||
msgid "%a %l:%M:%S %p"
|
||||
msgstr "%a %l.%M.%S %p"
|
||||
|
||||
#: ../js/ui/panel.js:580
|
||||
#: ../js/ui/dateMenu.js:168
|
||||
msgid "%a %l:%M %p"
|
||||
msgstr "%a %l.%M %p"
|
||||
|
||||
#. Translators: This is the date format to use when the calendar popup is
|
||||
#. * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
|
||||
#.
|
||||
#: ../js/ui/dateMenu.js:194
|
||||
msgid "%A %B %e, %Y"
|
||||
msgstr "%a %e %B, %Y"
|
||||
|
||||
#: ../js/ui/docDisplay.js:18
|
||||
msgid "RECENT ITEMS"
|
||||
msgstr "SISTE OPPFØRINGER"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:63
|
||||
#, c-format
|
||||
msgid "Log Out %s"
|
||||
msgstr "Logg ut %s"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:64 ../js/ui/endSessionDialog.js:69
|
||||
msgid "Log Out"
|
||||
msgstr "Logg ut …"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:65
|
||||
msgid "Click Log Out to quit these applications and log out of the system."
|
||||
msgstr ""
|
||||
"Klikk Logg ut for å avslutte disse programmene og logge ut av systemet."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:66
|
||||
#, c-format
|
||||
msgid "%s will be logged out automatically in %d seconds."
|
||||
msgstr "%s vil bli logget ut automatisk om %d sekunder."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:67
|
||||
#, c-format
|
||||
msgid "You will be logged out automatically in %d seconds."
|
||||
msgstr "Du vil bli logget ut automatisk om %d sekunder."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:68
|
||||
msgid "Logging out of the system."
|
||||
msgstr "Logger ut av systemet"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:74 ../js/ui/endSessionDialog.js:78
|
||||
msgid "Shut Down"
|
||||
msgstr "Avslutt"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:75
|
||||
msgid "Click Shut Down to quit these applications and shut down the system."
|
||||
msgstr "Klikk Avslutt for å avslutte disse programmene og stenge ned systemet."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:76
|
||||
#, c-format
|
||||
msgid "The system will shut down automatically in %d seconds."
|
||||
msgstr "Systemet vil slås av automatisk om %d sekunder."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:77
|
||||
msgid "Shutting down the system."
|
||||
msgstr "Slår av systemet."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:84 ../js/ui/endSessionDialog.js:88
|
||||
msgid "Restart"
|
||||
msgstr "Start på nytt"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:85
|
||||
msgid "Click Restart to quit these applications and restart the system."
|
||||
msgstr ""
|
||||
"Klikk Start på nytt for å avslutte disse programmene og starte systemet på "
|
||||
"nytt."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:86
|
||||
#, c-format
|
||||
msgid "The system will restart automatically in %d seconds."
|
||||
msgstr "Systemet vil starte på nytt automatisk om %d sekunder."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:87
|
||||
msgid "Restarting the system."
|
||||
msgstr "Starter systemet på nytt."
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:395
|
||||
msgid "Confirm"
|
||||
msgstr "Bekreft"
|
||||
|
||||
#: ../js/ui/endSessionDialog.js:400 ../js/ui/status/bluetooth.js:470
|
||||
msgid "Cancel"
|
||||
msgstr "Avbryt"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:556
|
||||
msgid "No extensions installed"
|
||||
msgstr "Ingen utvidelser installert"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:593
|
||||
msgid "Enabled"
|
||||
msgstr "Aktivert"
|
||||
|
||||
#. translators:
|
||||
#. * The device has been disabled
|
||||
#: ../js/ui/lookingGlass.js:595 ../src/gvc/gvc-mixer-control.c:1087
|
||||
msgid "Disabled"
|
||||
msgstr "Deaktivert"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:597
|
||||
msgid "Error"
|
||||
msgstr "Feil"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:599
|
||||
msgid "Out of date"
|
||||
msgstr "Utdatert"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:624
|
||||
msgid "View Source"
|
||||
msgstr "Vis kildekode"
|
||||
|
||||
#: ../js/ui/lookingGlass.js:630
|
||||
msgid "Web Page"
|
||||
msgstr "Nettside"
|
||||
|
||||
#: ../js/ui/messageTray.js:1809
|
||||
msgid "System Information"
|
||||
msgstr "Systeminformasjon"
|
||||
|
||||
#: ../js/ui/overview.js:88
|
||||
msgid "Undo"
|
||||
msgstr "Angre"
|
||||
|
||||
#: ../js/ui/overview.js:159
|
||||
msgid "Windows"
|
||||
msgstr "Vinduer"
|
||||
|
||||
#: ../js/ui/overview.js:162
|
||||
msgid "Applications"
|
||||
msgstr "Programmer"
|
||||
|
||||
#. TODO - _quit() doesn't really work on apps in state STARTING yet
|
||||
#: ../js/ui/panel.js:480
|
||||
#, c-format
|
||||
msgid "Quit %s"
|
||||
msgstr "Avslutt %s"
|
||||
|
||||
#. Button on the left side of the panel.
|
||||
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
|
||||
#: ../js/ui/panel.js:725
|
||||
#: ../js/ui/panel.js:614
|
||||
msgid "Activities"
|
||||
msgstr "Aktiviteter"
|
||||
|
||||
#: ../js/ui/placeDisplay.js:111
|
||||
#: ../js/ui/placeDisplay.js:106
|
||||
#, c-format
|
||||
msgid "Failed to unmount '%s'"
|
||||
msgstr "Klarte ikke å avmontere «%s»"
|
||||
|
||||
#: ../js/ui/placeDisplay.js:114
|
||||
#: ../js/ui/placeDisplay.js:109
|
||||
msgid "Retry"
|
||||
msgstr "Prøv igjen"
|
||||
|
||||
#: ../js/ui/placeDisplay.js:159
|
||||
#: ../js/ui/placeDisplay.js:150
|
||||
msgid "Connect to..."
|
||||
msgstr "Koble til …"
|
||||
|
||||
#: ../js/ui/placeDisplay.js:558
|
||||
#: ../js/ui/placeDisplay.js:386
|
||||
msgid "PLACES & DEVICES"
|
||||
msgstr "STEDER & ENHETER"
|
||||
|
||||
@ -424,84 +618,79 @@ msgstr "STEDER & ENHETER"
|
||||
msgid "toggle-switch-us"
|
||||
msgstr "toggle-switch-intl"
|
||||
|
||||
#: ../js/ui/runDialog.js:233
|
||||
#: ../js/ui/runDialog.js:209
|
||||
msgid "Please enter a command:"
|
||||
msgstr "Oppgi en kommando:"
|
||||
|
||||
#: ../js/ui/runDialog.js:378
|
||||
#, c-format
|
||||
msgid "Execution of '%s' failed:"
|
||||
msgstr "Kjøring av «%s» feilet:"
|
||||
|
||||
#: ../js/ui/statusMenu.js:101
|
||||
#: ../js/ui/statusMenu.js:102
|
||||
msgid "Available"
|
||||
msgstr "Tilgjengelig"
|
||||
|
||||
#: ../js/ui/statusMenu.js:106
|
||||
#: ../js/ui/statusMenu.js:107
|
||||
msgid "Busy"
|
||||
msgstr "Opptatt"
|
||||
|
||||
#: ../js/ui/statusMenu.js:114
|
||||
#: ../js/ui/statusMenu.js:115
|
||||
msgid "My Account"
|
||||
msgstr "Min konto"
|
||||
|
||||
#: ../js/ui/statusMenu.js:118
|
||||
#: ../js/ui/statusMenu.js:119
|
||||
msgid "System Settings"
|
||||
msgstr "Systeminnstillinger"
|
||||
|
||||
#: ../js/ui/statusMenu.js:125
|
||||
#: ../js/ui/statusMenu.js:126
|
||||
msgid "Lock Screen"
|
||||
msgstr "Lås skjerm"
|
||||
|
||||
#: ../js/ui/statusMenu.js:129
|
||||
#: ../js/ui/statusMenu.js:130
|
||||
msgid "Switch User"
|
||||
msgstr "Bytt bruker"
|
||||
|
||||
#: ../js/ui/statusMenu.js:134
|
||||
#: ../js/ui/statusMenu.js:135
|
||||
msgid "Log Out..."
|
||||
msgstr "Logg ut …"
|
||||
|
||||
#: ../js/ui/statusMenu.js:141
|
||||
#: ../js/ui/statusMenu.js:142
|
||||
msgid "Suspend..."
|
||||
msgstr "Hvilemodus …"
|
||||
|
||||
#: ../js/ui/statusMenu.js:145
|
||||
#: ../js/ui/statusMenu.js:146
|
||||
msgid "Shut Down..."
|
||||
msgstr "Avslutt …"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:82
|
||||
#: ../js/ui/status/accessibility.js:83
|
||||
msgid "Zoom"
|
||||
msgstr "Zoom"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:88
|
||||
#: ../js/ui/status/accessibility.js:89
|
||||
msgid "Screen Reader"
|
||||
msgstr "Skjermleser"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:91
|
||||
#: ../js/ui/status/accessibility.js:92
|
||||
msgid "Screen Keyboard"
|
||||
msgstr "Tastatur på skjermen"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:94
|
||||
#: ../js/ui/status/accessibility.js:95
|
||||
msgid "Visual Alerts"
|
||||
msgstr "Synlig varsling"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:97
|
||||
#: ../js/ui/status/accessibility.js:98
|
||||
msgid "Sticky Keys"
|
||||
msgstr "Klebrige taster"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:100
|
||||
#: ../js/ui/status/accessibility.js:101
|
||||
msgid "Slow Keys"
|
||||
msgstr "Trege taster"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:103
|
||||
#: ../js/ui/status/accessibility.js:104
|
||||
msgid "Bounce Keys"
|
||||
msgstr "Spretne taster"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:106
|
||||
#: ../js/ui/status/accessibility.js:107
|
||||
msgid "Mouse Keys"
|
||||
msgstr "Mustaster"
|
||||
|
||||
#: ../js/ui/status/accessibility.js:110
|
||||
#: ../js/ui/status/accessibility.js:111
|
||||
msgid "Universal Access Settings"
|
||||
msgstr "Innstillinger for tilgjengelighet"
|
||||
|
||||
@ -513,7 +702,7 @@ msgstr "Høy kontrast"
|
||||
msgid "Large Text"
|
||||
msgstr "Stor tekst"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:42 ../js/ui/status/bluetooth.js:234
|
||||
#: ../js/ui/status/bluetooth.js:42 ../js/ui/status/bluetooth.js:241
|
||||
msgid "Bluetooth"
|
||||
msgstr "Bluetooth"
|
||||
|
||||
@ -529,109 +718,109 @@ msgstr "Send filer til enhet..."
|
||||
msgid "Setup a New Device..."
|
||||
msgstr "Sett opp en ny enhet..."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:94
|
||||
#: ../js/ui/status/bluetooth.js:95
|
||||
msgid "Bluetooth Settings"
|
||||
msgstr "Innstillinger for Bluetooth"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:185
|
||||
#: ../js/ui/status/bluetooth.js:192
|
||||
msgid "Connection"
|
||||
msgstr "Tilkobling"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:221
|
||||
#: ../js/ui/status/bluetooth.js:228
|
||||
msgid "Send Files..."
|
||||
msgstr "Send filer..."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:226
|
||||
#: ../js/ui/status/bluetooth.js:233
|
||||
msgid "Browse Files..."
|
||||
msgstr "Bla gjennom filer..."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:235
|
||||
#: ../js/ui/status/bluetooth.js:242
|
||||
msgid "Error browsing device"
|
||||
msgstr "Feil under lesing av enhet"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:236
|
||||
#: ../js/ui/status/bluetooth.js:243
|
||||
#, c-format
|
||||
msgid "The requested device cannot be browsed, error is '%s'"
|
||||
msgstr "Kan ikke bla gjennom forespurt enhet. Feilen er «%s»"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:244
|
||||
#: ../js/ui/status/bluetooth.js:251
|
||||
msgid "Keyboard Settings"
|
||||
msgstr "Innstillinger for tastatur"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:249
|
||||
#: ../js/ui/status/bluetooth.js:256
|
||||
msgid "Mouse Settings"
|
||||
msgstr "Innstillinger for mus"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:256 ../js/ui/status/volume.js:62
|
||||
#: ../js/ui/status/bluetooth.js:263 ../js/ui/status/volume.js:63
|
||||
msgid "Sound Settings"
|
||||
msgstr "Innstillinger for lyd"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:327 ../js/ui/status/bluetooth.js:361
|
||||
#: ../js/ui/status/bluetooth.js:401 ../js/ui/status/bluetooth.js:434
|
||||
#: ../js/ui/status/bluetooth.js:337 ../js/ui/status/bluetooth.js:371
|
||||
#: ../js/ui/status/bluetooth.js:411 ../js/ui/status/bluetooth.js:444
|
||||
msgid "Bluetooth Agent"
|
||||
msgstr "Bluetooth-agent"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:362
|
||||
#: ../js/ui/status/bluetooth.js:372
|
||||
#, c-format
|
||||
msgid "Authorization request from %s"
|
||||
msgstr "Forespørsel om autorisering fra %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:368
|
||||
#: ../js/ui/status/bluetooth.js:378
|
||||
#, c-format
|
||||
msgid "Device %s wants access to the service '%s'"
|
||||
msgstr "Enhet %s vil ha tilgang til tjenesten «%s»"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:370
|
||||
#: ../js/ui/status/bluetooth.js:380
|
||||
msgid "Always grant access"
|
||||
msgstr "Alltid gi tilgang"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:371
|
||||
#: ../js/ui/status/bluetooth.js:381
|
||||
msgid "Grant this time only"
|
||||
msgstr "Gi tilgang kun denne ene gangen"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:372
|
||||
#: ../js/ui/status/bluetooth.js:382
|
||||
msgid "Reject"
|
||||
msgstr "Avvis"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:402
|
||||
#: ../js/ui/status/bluetooth.js:412
|
||||
#, c-format
|
||||
msgid "Pairing confirmation for %s"
|
||||
msgstr "Bekreftelse for tilkobling for %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:408 ../js/ui/status/bluetooth.js:442
|
||||
#: ../js/ui/status/bluetooth.js:418 ../js/ui/status/bluetooth.js:452
|
||||
#, c-format
|
||||
msgid "Device %s wants to pair with this computer"
|
||||
msgstr "Enhet %s vil koble seg sammen med denne datamaskinen"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:409
|
||||
#: ../js/ui/status/bluetooth.js:419
|
||||
#, c-format
|
||||
msgid "Please confirm whether the PIN '%s' matches the one on the device."
|
||||
msgstr "Vennligst bekreft om PIN «%s» er lik den som brukes på enheten."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:411
|
||||
#: ../js/ui/status/bluetooth.js:421
|
||||
msgid "Matches"
|
||||
msgstr "Stemmer overens"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:412
|
||||
#: ../js/ui/status/bluetooth.js:422
|
||||
msgid "Does not match"
|
||||
msgstr "Stemmer ikke overens"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:435
|
||||
#: ../js/ui/status/bluetooth.js:445
|
||||
#, c-format
|
||||
msgid "Pairing request for %s"
|
||||
msgstr "Forespørsel om tilkobling for %s"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:443
|
||||
#: ../js/ui/status/bluetooth.js:453
|
||||
msgid "Please enter the PIN mentioned on the device."
|
||||
msgstr "Vennligst oppgi PIN som oppgitt på enheten."
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:459
|
||||
#: ../js/ui/status/bluetooth.js:469
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: ../js/ui/status/bluetooth.js:460
|
||||
msgid "Cancel"
|
||||
msgstr "Avbryt"
|
||||
#: ../js/ui/status/keyboard.js:78
|
||||
msgid "Localization Settings"
|
||||
msgstr "Innstillinger for lokalisering"
|
||||
|
||||
#: ../js/ui/status/power.js:85
|
||||
msgid "Power Settings"
|
||||
@ -669,78 +858,78 @@ msgid_plural "%d minutes remaining"
|
||||
msgstr[0] "%d minutt gjenstår"
|
||||
msgstr[1] "%d minutter gjenstår"
|
||||
|
||||
#: ../js/ui/status/power.js:237
|
||||
#: ../js/ui/status/power.js:235
|
||||
msgid "AC adapter"
|
||||
msgstr "Strømadapter"
|
||||
|
||||
#: ../js/ui/status/power.js:239
|
||||
#: ../js/ui/status/power.js:237
|
||||
msgid "Laptop battery"
|
||||
msgstr "Batteri på bærbar"
|
||||
|
||||
#: ../js/ui/status/power.js:241
|
||||
#: ../js/ui/status/power.js:239
|
||||
msgid "UPS"
|
||||
msgstr "UPS"
|
||||
|
||||
#: ../js/ui/status/power.js:243
|
||||
#: ../js/ui/status/power.js:241
|
||||
msgid "Monitor"
|
||||
msgstr "Skjerm"
|
||||
|
||||
#: ../js/ui/status/power.js:245
|
||||
#: ../js/ui/status/power.js:243
|
||||
msgid "Mouse"
|
||||
msgstr "Mus"
|
||||
|
||||
#: ../js/ui/status/power.js:247
|
||||
#: ../js/ui/status/power.js:245
|
||||
msgid "Keyboard"
|
||||
msgstr "Tastatur"
|
||||
|
||||
#: ../js/ui/status/power.js:249
|
||||
#: ../js/ui/status/power.js:247
|
||||
msgid "PDA"
|
||||
msgstr "PDA"
|
||||
|
||||
#: ../js/ui/status/power.js:251
|
||||
#: ../js/ui/status/power.js:249
|
||||
msgid "Cell phone"
|
||||
msgstr "Mobiltelefon"
|
||||
|
||||
#: ../js/ui/status/power.js:253
|
||||
#: ../js/ui/status/power.js:251
|
||||
msgid "Media player"
|
||||
msgstr "Medieavspiller"
|
||||
|
||||
#: ../js/ui/status/power.js:255
|
||||
#: ../js/ui/status/power.js:253
|
||||
msgid "Tablet"
|
||||
msgstr "Nettbrett"
|
||||
|
||||
#: ../js/ui/status/power.js:257
|
||||
#: ../js/ui/status/power.js:255
|
||||
msgid "Computer"
|
||||
msgstr "Datamaskin"
|
||||
|
||||
#: ../js/ui/status/power.js:259 ../src/shell-app-system.c:1012
|
||||
#: ../js/ui/status/power.js:257 ../src/shell-app-system.c:1012
|
||||
msgid "Unknown"
|
||||
msgstr "Ukjent"
|
||||
|
||||
#: ../js/ui/status/volume.js:41
|
||||
#: ../js/ui/status/volume.js:42
|
||||
msgid "Volume"
|
||||
msgstr "Volum"
|
||||
|
||||
#: ../js/ui/status/volume.js:54
|
||||
#: ../js/ui/status/volume.js:55
|
||||
msgid "Microphone"
|
||||
msgstr "Mikrofon"
|
||||
|
||||
#: ../js/ui/telepathyClient.js:560
|
||||
#: ../js/ui/telepathyClient.js:563
|
||||
#, c-format
|
||||
msgid "%s is online."
|
||||
msgstr "%s er tilkoblet."
|
||||
|
||||
#: ../js/ui/telepathyClient.js:565
|
||||
#: ../js/ui/telepathyClient.js:568
|
||||
#, c-format
|
||||
msgid "%s is offline."
|
||||
msgstr "%s er frakoblet."
|
||||
|
||||
#: ../js/ui/telepathyClient.js:568
|
||||
#: ../js/ui/telepathyClient.js:571
|
||||
#, c-format
|
||||
msgid "%s is away."
|
||||
msgstr "«%s» er borte."
|
||||
|
||||
#: ../js/ui/telepathyClient.js:571
|
||||
#: ../js/ui/telepathyClient.js:574
|
||||
#, c-format
|
||||
msgid "%s is busy."
|
||||
msgstr "%s er opptatt."
|
||||
@ -748,7 +937,7 @@ msgstr "%s er opptatt."
|
||||
#. Translators: this is a time format string followed by a date.
|
||||
#. If applicable, replace %X with a strftime format valid for your
|
||||
#. locale, without seconds.
|
||||
#: ../js/ui/telepathyClient.js:665
|
||||
#: ../js/ui/telepathyClient.js:668
|
||||
#, no-c-format
|
||||
msgid "Sent at %X on %A"
|
||||
msgstr "Sendt %X på %A"
|
||||
@ -767,14 +956,14 @@ msgstr "%s er ferdig startet"
|
||||
msgid "'%s' is ready"
|
||||
msgstr "«%s» er klar"
|
||||
|
||||
#: ../js/ui/workspacesView.js:244
|
||||
#: ../js/ui/workspacesView.js:243
|
||||
msgid ""
|
||||
"Can't add a new workspace because maximum workspaces limit has been reached."
|
||||
msgstr ""
|
||||
"Kan ikke legge til nytt arbeidsområde fordi grensen for maksimalt antall "
|
||||
"arbeidsområder er nådd."
|
||||
|
||||
#: ../js/ui/workspacesView.js:260
|
||||
#: ../js/ui/workspacesView.js:259
|
||||
msgid "Can't remove the first workspace."
|
||||
msgstr "Kan ikke fjerne første arbeidsområde"
|
||||
|
||||
@ -800,32 +989,32 @@ msgstr[1] "%u innganger"
|
||||
msgid "System Sounds"
|
||||
msgstr "Systemlyder"
|
||||
|
||||
#: ../src/shell-global.c:1156
|
||||
#: ../src/shell-global.c:1365
|
||||
msgid "Less than a minute ago"
|
||||
msgstr "Mindre enn ett minutt siden"
|
||||
|
||||
#: ../src/shell-global.c:1160
|
||||
#: ../src/shell-global.c:1369
|
||||
#, c-format
|
||||
msgid "%d minute ago"
|
||||
msgid_plural "%d minutes ago"
|
||||
msgstr[0] "%d minutt siden"
|
||||
msgstr[1] "%d minutter siden"
|
||||
|
||||
#: ../src/shell-global.c:1165
|
||||
#: ../src/shell-global.c:1374
|
||||
#, c-format
|
||||
msgid "%d hour ago"
|
||||
msgid_plural "%d hours ago"
|
||||
msgstr[0] "%d time siden"
|
||||
msgstr[1] "%d timer siden"
|
||||
|
||||
#: ../src/shell-global.c:1170
|
||||
#: ../src/shell-global.c:1379
|
||||
#, c-format
|
||||
msgid "%d day ago"
|
||||
msgid_plural "%d days ago"
|
||||
msgstr[0] "%d dag siden"
|
||||
msgstr[1] "%d dager siden"
|
||||
|
||||
#: ../src/shell-global.c:1175
|
||||
#: ../src/shell-global.c:1384
|
||||
#, c-format
|
||||
msgid "%d week ago"
|
||||
msgid_plural "%d weeks ago"
|
||||
|
22
src/Makefile-calendar-client.am
Normal file
22
src/Makefile-calendar-client.am
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
noinst_LTLIBRARIES += libcalendar-client.la
|
||||
|
||||
libcalendar_client_la_SOURCES = \
|
||||
calendar-client/calendar-client.h calendar-client/calendar-client.c \
|
||||
calendar-client/calendar-debug.h \
|
||||
calendar-client/calendar-sources.c calendar-client/calendar-sources.h \
|
||||
$(NULL)
|
||||
|
||||
libcalendar_client_la_CFLAGS = \
|
||||
-I$(top_srcdir)/src \
|
||||
-DPREFIX=\""$(prefix)"\" \
|
||||
-DLIBDIR=\""$(libdir)"\" \
|
||||
-DDATADIR=\""$(datadir)"\" \
|
||||
-DG_DISABLE_DEPRECATED \
|
||||
-DG_LOG_DOMAIN=\"CalendarClient\" \
|
||||
$(LIBECAL_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
libcalendar_client_la_LIBADD = $(LIBECAL_LIBS)
|
||||
|
||||
EXTRA_DIST += calendar-client/README
|
@ -98,6 +98,7 @@ st_source_h = \
|
||||
st/st-tooltip.h \
|
||||
st/st-types.h \
|
||||
st/st-widget.h \
|
||||
st/st-widget-accessible.h \
|
||||
$(NULL)
|
||||
|
||||
st.h: stamp-st.h
|
||||
@ -158,11 +159,17 @@ st_source_c = \
|
||||
st/st-widget.c \
|
||||
$(NULL)
|
||||
|
||||
st_non_gir_sources = \
|
||||
st/st-scroll-view-fade.c \
|
||||
st/st-scroll-view-fade.h \
|
||||
$(NULL)
|
||||
|
||||
noinst_LTLIBRARIES += libst-1.0.la
|
||||
|
||||
libst_1_0_la_LIBADD = -lm $(ST_LIBS)
|
||||
libst_1_0_la_SOURCES = \
|
||||
$(st_source_c) \
|
||||
$(st_source_c) \
|
||||
$(st_non_gir_sources) \
|
||||
$(st_source_private_h) \
|
||||
$(st_source_private_c) \
|
||||
$(st_source_h) \
|
||||
|
@ -27,6 +27,7 @@ include Makefile-gdmuser.am
|
||||
include Makefile-st.am
|
||||
include Makefile-tray.am
|
||||
include Makefile-gvc.am
|
||||
include Makefile-calendar-client.am
|
||||
|
||||
gnome_shell_cflags = \
|
||||
$(MUTTER_PLUGIN_CFLAGS) \
|
||||
@ -59,7 +60,6 @@ shell_public_headers_h = \
|
||||
shell-embedded-window.h \
|
||||
shell-generic-container.h \
|
||||
shell-gtk-embed.h \
|
||||
shell-process.h \
|
||||
shell-global.h \
|
||||
shell-perf-log.h \
|
||||
shell-slicer.h \
|
||||
@ -82,15 +82,18 @@ libgnome_shell_la_SOURCES = \
|
||||
shell-wm-private.h \
|
||||
gnome-shell-plugin.c \
|
||||
shell-app.c \
|
||||
shell-a11y.h \
|
||||
shell-a11y.c \
|
||||
shell-app-system.c \
|
||||
shell-app-usage.c \
|
||||
shell-arrow.c \
|
||||
shell-doc-system.c \
|
||||
shell-drawing.c \
|
||||
shell-embedded-window.c \
|
||||
shell-evolution-event-source.h \
|
||||
shell-evolution-event-source.c \
|
||||
shell-generic-container.c \
|
||||
shell-gtk-embed.c \
|
||||
shell-process.c \
|
||||
shell-global.c \
|
||||
shell-perf-log.c \
|
||||
shell-slicer.c \
|
||||
@ -212,7 +215,9 @@ libgnome_shell_la_LIBADD = \
|
||||
libst-1.0.la \
|
||||
libgdmuser-1.0.la \
|
||||
libtray.la \
|
||||
libgvc.la
|
||||
libgvc.la \
|
||||
libcalendar-client.la \
|
||||
$(NULL)
|
||||
|
||||
libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags)
|
||||
|
||||
@ -262,7 +267,7 @@ St-1.0.gir: $(mutter) $(G_IR_SCANNER) libst-1.0.la Makefile
|
||||
--libtool="$(LIBTOOL)" \
|
||||
--library=libst-1.0.la \
|
||||
-DST_COMPILATION \
|
||||
$(filter-out %-private.h, $(addprefix $(srcdir)/,$(st_source_h))) \
|
||||
$(filter-out %-private.h $(st_non_gir_sources), $(addprefix $(srcdir)/,$(st_source_h))) \
|
||||
$(addprefix $(srcdir)/,$(st_source_c)) \
|
||||
$(srcdir)/st-enum-types.h \
|
||||
$(st_cflags) \
|
||||
|
1
src/calendar-client/README
Normal file
1
src/calendar-client/README
Normal file
@ -0,0 +1 @@
|
||||
Please keep in sync with gnome-panel.
|
2169
src/calendar-client/calendar-client.c
Normal file
2169
src/calendar-client/calendar-client.c
Normal file
File diff suppressed because it is too large
Load Diff
149
src/calendar-client/calendar-client.h
Normal file
149
src/calendar-client/calendar-client.h
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Authors:
|
||||
* Mark McLoughlin <mark@skynet.ie>
|
||||
* William Jon McCann <mccann@jhu.edu>
|
||||
* Martin Grimme <martin@pycage.de>
|
||||
* Christian Kellner <gicmo@xatom.net>
|
||||
*/
|
||||
|
||||
#ifndef __CALENDAR_CLIENT_H__
|
||||
#define __CALENDAR_CLIENT_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CALENDAR_EVENT_APPOINTMENT = 1 << 0,
|
||||
CALENDAR_EVENT_TASK = 1 << 1,
|
||||
CALENDAR_EVENT_ALL = (1 << 2) - 1
|
||||
} CalendarEventType;
|
||||
|
||||
#define CALENDAR_TYPE_CLIENT (calendar_client_get_type ())
|
||||
#define CALENDAR_CLIENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CALENDAR_TYPE_CLIENT, CalendarClient))
|
||||
#define CALENDAR_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), CALENDAR_TYPE_CLIENT, CalendarClientClass))
|
||||
#define CALENDAR_IS_CLIENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CALENDAR_TYPE_CLIENT))
|
||||
#define CALENDAR_IS_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CALENDAR_TYPE_CLIENT))
|
||||
#define CALENDAR_CLIENT_GET_CLASS(o)(G_TYPE_INSTANCE_GET_CLASS ((o), CALENDAR_TYPE_CLIENT, CalendarClientClass))
|
||||
|
||||
typedef struct _CalendarClient CalendarClient;
|
||||
typedef struct _CalendarClientClass CalendarClientClass;
|
||||
typedef struct _CalendarClientPrivate CalendarClientPrivate;
|
||||
|
||||
struct _CalendarClient
|
||||
{
|
||||
GObject parent;
|
||||
CalendarClientPrivate *priv;
|
||||
};
|
||||
|
||||
struct _CalendarClientClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* appointments_changed) (CalendarClient *client);
|
||||
void (* tasks_changed) (CalendarClient *client);
|
||||
};
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
time_t start_time;
|
||||
time_t end_time;
|
||||
} CalendarOccurrence;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *uid;
|
||||
char *rid;
|
||||
char *uri;
|
||||
char *summary;
|
||||
char *description;
|
||||
char *color_string;
|
||||
time_t start_time;
|
||||
time_t end_time;
|
||||
guint is_all_day : 1;
|
||||
|
||||
/* Only used internally */
|
||||
GSList *occurrences;
|
||||
} CalendarAppointment;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *uid;
|
||||
char *summary;
|
||||
char *description;
|
||||
char *color_string;
|
||||
char *url;
|
||||
time_t start_time;
|
||||
time_t due_time;
|
||||
guint percent_complete;
|
||||
time_t completed_time;
|
||||
int priority;
|
||||
} CalendarTask;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
CalendarAppointment appointment;
|
||||
CalendarTask task;
|
||||
} event;
|
||||
CalendarEventType type;
|
||||
} CalendarEvent;
|
||||
|
||||
#define CALENDAR_EVENT(e) ((CalendarEvent *)(e))
|
||||
#define CALENDAR_APPOINTMENT(e) ((CalendarAppointment *)(e))
|
||||
#define CALENDAR_TASK(e) ((CalendarTask *)(e))
|
||||
|
||||
typedef void (* CalendarDayIter) (CalendarClient *client,
|
||||
guint day,
|
||||
gpointer user_data);
|
||||
|
||||
|
||||
GType calendar_client_get_type (void) G_GNUC_CONST;
|
||||
CalendarClient *calendar_client_new (void);
|
||||
|
||||
void calendar_client_get_date (CalendarClient *client,
|
||||
guint *year,
|
||||
guint *month,
|
||||
guint *day);
|
||||
void calendar_client_select_month (CalendarClient *client,
|
||||
guint month,
|
||||
guint year);
|
||||
void calendar_client_select_day (CalendarClient *client,
|
||||
guint day);
|
||||
|
||||
GSList *calendar_client_get_events (CalendarClient *client,
|
||||
CalendarEventType event_mask);
|
||||
void calendar_client_foreach_appointment_day (CalendarClient *client,
|
||||
CalendarDayIter iter_func,
|
||||
gpointer user_data);
|
||||
|
||||
void calendar_client_set_task_completed (CalendarClient *client,
|
||||
char *task_uid,
|
||||
gboolean task_completed,
|
||||
guint percent_complete);
|
||||
|
||||
void calendar_event_free (CalendarEvent *event);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CALENDAR_CLIENT_H__ */
|
52
src/calendar-client/calendar-debug.h
Normal file
52
src/calendar-client/calendar-debug.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Authors:
|
||||
* Mark McLoughlin <mark@skynet.ie>
|
||||
*/
|
||||
|
||||
#ifndef __CALENDAR_DEBUG_H__
|
||||
#define __CALENDAR_DEBUG_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#ifdef CALENDAR_ENABLE_DEBUG
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef G_HAVE_ISO_VARARGS
|
||||
# define dprintf(...) fprintf (stderr, __VA_ARGS__);
|
||||
#elif defined(G_HAVE_GNUC_VARARGS)
|
||||
# define dprintf(args...) fprintf (stderr, args);
|
||||
#endif
|
||||
|
||||
#else /* if !defined (CALENDAR_DEBUG) */
|
||||
|
||||
#ifdef G_HAVE_ISO_VARARGS
|
||||
# define dprintf(...)
|
||||
#elif defined(G_HAVE_GNUC_VARARGS)
|
||||
# define dprintf(args...)
|
||||
#endif
|
||||
|
||||
#endif /* CALENDAR_ENABLE_DEBUG */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CALENDAR_DEBUG_H__ */
|
658
src/calendar-client/calendar-sources.c
Normal file
658
src/calendar-client/calendar-sources.c
Normal file
@ -0,0 +1,658 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Authors:
|
||||
* Mark McLoughlin <mark@skynet.ie>
|
||||
* William Jon McCann <mccann@jhu.edu>
|
||||
* Martin Grimme <martin@pycage.de>
|
||||
* Christian Kellner <gicmo@xatom.net>
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "calendar-sources.h"
|
||||
|
||||
#include <libintl.h>
|
||||
#include <string.h>
|
||||
#include <gconf/gconf-client.h>
|
||||
#define HANDLE_LIBICAL_MEMORY
|
||||
#include <libecal/e-cal.h>
|
||||
#include <libedataserver/e-source-list.h>
|
||||
#include <libedataserverui/e-passwords.h>
|
||||
|
||||
#undef CALENDAR_ENABLE_DEBUG
|
||||
#include "calendar-debug.h"
|
||||
|
||||
#ifndef _
|
||||
#define _(x) gettext(x)
|
||||
#endif
|
||||
|
||||
#ifndef N_
|
||||
#define N_(x) x
|
||||
#endif
|
||||
|
||||
#define CALENDAR_SOURCES_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CALENDAR_TYPE_SOURCES, CalendarSourcesPrivate))
|
||||
|
||||
#define CALENDAR_SOURCES_EVO_DIR "/apps/evolution"
|
||||
#define CALENDAR_SOURCES_APPOINTMENT_SOURCES_KEY CALENDAR_SOURCES_EVO_DIR "/calendar/sources"
|
||||
#define CALENDAR_SOURCES_SELECTED_APPOINTMENT_SOURCES_DIR CALENDAR_SOURCES_EVO_DIR "/calendar/display"
|
||||
#define CALENDAR_SOURCES_SELECTED_APPOINTMENT_SOURCES_KEY CALENDAR_SOURCES_SELECTED_APPOINTMENT_SOURCES_DIR "/selected_calendars"
|
||||
#define CALENDAR_SOURCES_TASK_SOURCES_KEY CALENDAR_SOURCES_EVO_DIR "/tasks/sources"
|
||||
#define CALENDAR_SOURCES_SELECTED_TASK_SOURCES_DIR CALENDAR_SOURCES_EVO_DIR "/calendar/tasks"
|
||||
#define CALENDAR_SOURCES_SELECTED_TASK_SOURCES_KEY CALENDAR_SOURCES_SELECTED_TASK_SOURCES_DIR "/selected_tasks"
|
||||
|
||||
typedef struct _CalendarSourceData CalendarSourceData;
|
||||
|
||||
struct _CalendarSourceData
|
||||
{
|
||||
ECalSourceType source_type;
|
||||
CalendarSources *sources;
|
||||
guint changed_signal;
|
||||
|
||||
GSList *clients;
|
||||
GSList *selected_sources;
|
||||
ESourceList *esource_list;
|
||||
|
||||
guint selected_sources_listener;
|
||||
char *selected_sources_dir;
|
||||
|
||||
guint timeout_id;
|
||||
|
||||
guint loaded : 1;
|
||||
};
|
||||
|
||||
struct _CalendarSourcesPrivate
|
||||
{
|
||||
CalendarSourceData appointment_sources;
|
||||
CalendarSourceData task_sources;
|
||||
|
||||
GConfClient *gconf_client;
|
||||
};
|
||||
|
||||
static void calendar_sources_class_init (CalendarSourcesClass *klass);
|
||||
static void calendar_sources_init (CalendarSources *sources);
|
||||
static void calendar_sources_finalize (GObject *object);
|
||||
|
||||
static void backend_died_cb (ECal *client, CalendarSourceData *source_data);
|
||||
static void calendar_sources_esource_list_changed (ESourceList *source_list,
|
||||
CalendarSourceData *source_data);
|
||||
|
||||
enum
|
||||
{
|
||||
APPOINTMENT_SOURCES_CHANGED,
|
||||
TASK_SOURCES_CHANGED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
static guint signals [LAST_SIGNAL] = { 0, };
|
||||
|
||||
static GObjectClass *parent_class = NULL;
|
||||
static CalendarSources *calendar_sources_singleton = NULL;
|
||||
|
||||
GType
|
||||
calendar_sources_get_type (void)
|
||||
{
|
||||
static GType sources_type = 0;
|
||||
|
||||
if (!sources_type)
|
||||
{
|
||||
static const GTypeInfo sources_info =
|
||||
{
|
||||
sizeof (CalendarSourcesClass),
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
(GClassInitFunc) calendar_sources_class_init,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
sizeof (CalendarSources),
|
||||
0, /* n_preallocs */
|
||||
(GInstanceInitFunc) calendar_sources_init,
|
||||
};
|
||||
|
||||
sources_type = g_type_register_static (G_TYPE_OBJECT,
|
||||
"CalendarSources",
|
||||
&sources_info, 0);
|
||||
}
|
||||
|
||||
return sources_type;
|
||||
}
|
||||
|
||||
static void
|
||||
calendar_sources_class_init (CalendarSourcesClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
|
||||
parent_class = g_type_class_peek_parent (klass);
|
||||
|
||||
gobject_class->finalize = calendar_sources_finalize;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (CalendarSourcesPrivate));
|
||||
|
||||
signals [APPOINTMENT_SOURCES_CHANGED] =
|
||||
g_signal_new ("appointment-sources-changed",
|
||||
G_TYPE_FROM_CLASS (gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (CalendarSourcesClass,
|
||||
appointment_sources_changed),
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
|
||||
signals [TASK_SOURCES_CHANGED] =
|
||||
g_signal_new ("task-sources-changed",
|
||||
G_TYPE_FROM_CLASS (gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (CalendarSourcesClass,
|
||||
task_sources_changed),
|
||||
NULL,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
}
|
||||
|
||||
static void
|
||||
calendar_sources_init (CalendarSources *sources)
|
||||
{
|
||||
sources->priv = CALENDAR_SOURCES_GET_PRIVATE (sources);
|
||||
|
||||
sources->priv->appointment_sources.source_type = E_CAL_SOURCE_TYPE_EVENT;
|
||||
sources->priv->appointment_sources.sources = sources;
|
||||
sources->priv->appointment_sources.changed_signal = signals [APPOINTMENT_SOURCES_CHANGED];
|
||||
sources->priv->appointment_sources.timeout_id = 0;
|
||||
|
||||
sources->priv->task_sources.source_type = E_CAL_SOURCE_TYPE_TODO;
|
||||
sources->priv->task_sources.sources = sources;
|
||||
sources->priv->task_sources.changed_signal = signals [TASK_SOURCES_CHANGED];
|
||||
sources->priv->task_sources.timeout_id = 0;
|
||||
|
||||
sources->priv->gconf_client = gconf_client_get_default ();
|
||||
}
|
||||
|
||||
static void
|
||||
calendar_sources_finalize_source_data (CalendarSources *sources,
|
||||
CalendarSourceData *source_data)
|
||||
{
|
||||
if (source_data->loaded)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
if (source_data->selected_sources_dir)
|
||||
{
|
||||
gconf_client_remove_dir (sources->priv->gconf_client,
|
||||
source_data->selected_sources_dir,
|
||||
NULL);
|
||||
|
||||
g_free (source_data->selected_sources_dir);
|
||||
source_data->selected_sources_dir = NULL;
|
||||
}
|
||||
|
||||
if (source_data->selected_sources_listener)
|
||||
{
|
||||
gconf_client_notify_remove (sources->priv->gconf_client,
|
||||
source_data->selected_sources_listener);
|
||||
source_data->selected_sources_listener = 0;
|
||||
}
|
||||
|
||||
for (l = source_data->clients; l; l = l->next)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (G_OBJECT (l->data),
|
||||
G_CALLBACK (backend_died_cb),
|
||||
source_data);
|
||||
g_object_unref (l->data);
|
||||
}
|
||||
g_slist_free (source_data->clients);
|
||||
source_data->clients = NULL;
|
||||
|
||||
if (source_data->esource_list)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (source_data->esource_list,
|
||||
G_CALLBACK (calendar_sources_esource_list_changed),
|
||||
source_data);
|
||||
g_object_unref (source_data->esource_list);
|
||||
}
|
||||
source_data->esource_list = NULL;
|
||||
|
||||
for (l = source_data->selected_sources; l; l = l->next)
|
||||
g_free (l->data);
|
||||
g_slist_free (source_data->selected_sources);
|
||||
source_data->selected_sources = NULL;
|
||||
|
||||
if (source_data->timeout_id != 0)
|
||||
{
|
||||
g_source_remove (source_data->timeout_id);
|
||||
source_data->timeout_id = 0;
|
||||
}
|
||||
|
||||
source_data->loaded = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
calendar_sources_finalize (GObject *object)
|
||||
{
|
||||
CalendarSources *sources = CALENDAR_SOURCES (object);
|
||||
|
||||
calendar_sources_finalize_source_data (sources, &sources->priv->appointment_sources);
|
||||
calendar_sources_finalize_source_data (sources, &sources->priv->task_sources);
|
||||
|
||||
if (sources->priv->gconf_client)
|
||||
g_object_unref (sources->priv->gconf_client);
|
||||
sources->priv->gconf_client = NULL;
|
||||
|
||||
if (G_OBJECT_CLASS (parent_class)->finalize)
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
CalendarSources *
|
||||
calendar_sources_get (void)
|
||||
{
|
||||
gpointer singleton_location = &calendar_sources_singleton;
|
||||
|
||||
if (calendar_sources_singleton)
|
||||
return g_object_ref (calendar_sources_singleton);
|
||||
|
||||
calendar_sources_singleton = g_object_new (CALENDAR_TYPE_SOURCES, NULL);
|
||||
g_object_add_weak_pointer (G_OBJECT (calendar_sources_singleton),
|
||||
singleton_location);
|
||||
|
||||
return calendar_sources_singleton;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_source_selected (ESource *esource,
|
||||
GSList *selected_sources)
|
||||
{
|
||||
const char *uid;
|
||||
GSList *l;
|
||||
|
||||
uid = e_source_peek_uid (esource);
|
||||
|
||||
for (l = selected_sources; l; l = l->next)
|
||||
{
|
||||
const char *source = l->data;
|
||||
|
||||
if (!strcmp (source, uid))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static char *
|
||||
auth_func_cb (ECal *ecal,
|
||||
const char *prompt,
|
||||
const char *key,
|
||||
gpointer user_data)
|
||||
{
|
||||
ESource *source;
|
||||
const gchar *auth_domain;
|
||||
const gchar *component_name;
|
||||
|
||||
source = e_cal_get_source (ecal);
|
||||
auth_domain = e_source_get_property (source, "auth-domain");
|
||||
component_name = auth_domain ? auth_domain : "Calendar";
|
||||
|
||||
return e_passwords_get_password (component_name, key);
|
||||
}
|
||||
|
||||
/* The clients are just created here but not loaded */
|
||||
static ECal *
|
||||
get_ecal_from_source (ESource *esource,
|
||||
ECalSourceType source_type,
|
||||
GSList *existing_clients)
|
||||
{
|
||||
ECal *retval;
|
||||
|
||||
if (existing_clients)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
for (l = existing_clients; l; l = l->next)
|
||||
{
|
||||
ECal *client = E_CAL (l->data);
|
||||
|
||||
if (e_source_equal (esource, e_cal_get_source (client)))
|
||||
{
|
||||
dprintf (" load_esource: found existing source ... returning that\n");
|
||||
|
||||
return g_object_ref (client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
retval = e_cal_new (esource, source_type);
|
||||
if (!retval)
|
||||
{
|
||||
g_warning ("Could not load source '%s' from '%s'\n",
|
||||
e_source_peek_name (esource),
|
||||
e_source_peek_relative_uri (esource));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
e_cal_set_auth_func (retval, auth_func_cb, NULL);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* - Order doesn't matter
|
||||
* - Can just compare object pointers since we
|
||||
* re-use client connections
|
||||
*/
|
||||
static gboolean
|
||||
compare_ecal_lists (GSList *a,
|
||||
GSList *b)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
if (g_slist_length (a) != g_slist_length (b))
|
||||
return FALSE;
|
||||
|
||||
for (l = a; l; l = l->next)
|
||||
{
|
||||
if (!g_slist_find (b, l->data))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
debug_dump_selected_sources (GSList *selected_sources)
|
||||
{
|
||||
#ifdef CALENDAR_ENABLE_DEBUG
|
||||
GSList *l;
|
||||
|
||||
dprintf ("Selected sources:\n");
|
||||
for (l = selected_sources; l; l = l->next)
|
||||
{
|
||||
char *source = l->data;
|
||||
|
||||
dprintf (" %s\n", source);
|
||||
}
|
||||
dprintf ("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
debug_dump_ecal_list (GSList *ecal_list)
|
||||
{
|
||||
#ifdef CALENDAR_ENABLE_DEBUG
|
||||
GSList *l;
|
||||
|
||||
dprintf ("Loaded clients:\n");
|
||||
for (l = ecal_list; l; l = l->next)
|
||||
{
|
||||
ECal *client = l->data;
|
||||
ESource *source = e_cal_get_source (client);
|
||||
|
||||
dprintf (" %s %s %s\n",
|
||||
e_source_peek_uid (source),
|
||||
e_source_peek_name (source),
|
||||
e_cal_get_uri (client));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
calendar_sources_load_esource_list (CalendarSourceData *source_data);
|
||||
|
||||
static gboolean
|
||||
backend_restart (gpointer data)
|
||||
{
|
||||
CalendarSourceData *source_data = data;
|
||||
|
||||
calendar_sources_load_esource_list (source_data);
|
||||
|
||||
source_data->timeout_id = 0;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
backend_died_cb (ECal *client, CalendarSourceData *source_data)
|
||||
{
|
||||
const char *uristr;
|
||||
|
||||
source_data->clients = g_slist_remove (source_data->clients, client);
|
||||
if (g_slist_length (source_data->clients) < 1)
|
||||
{
|
||||
g_slist_free (source_data->clients);
|
||||
source_data->clients = NULL;
|
||||
}
|
||||
uristr = e_cal_get_uri (client);
|
||||
g_warning ("The calendar backend for %s has crashed.", uristr);
|
||||
|
||||
if (source_data->timeout_id != 0)
|
||||
{
|
||||
g_source_remove (source_data->timeout_id);
|
||||
source_data->timeout_id = 0;
|
||||
}
|
||||
|
||||
source_data->timeout_id = g_timeout_add_seconds (2, backend_restart,
|
||||
source_data);
|
||||
}
|
||||
|
||||
static void
|
||||
calendar_sources_load_esource_list (CalendarSourceData *source_data)
|
||||
{
|
||||
GSList *clients = NULL;
|
||||
GSList *groups, *l;
|
||||
gboolean emit_signal = FALSE;
|
||||
|
||||
g_return_if_fail (source_data->esource_list != NULL);
|
||||
|
||||
debug_dump_selected_sources (source_data->selected_sources);
|
||||
|
||||
dprintf ("Source groups:\n");
|
||||
groups = e_source_list_peek_groups (source_data->esource_list);
|
||||
for (l = groups; l; l = l->next)
|
||||
{
|
||||
GSList *esources, *s;
|
||||
|
||||
dprintf (" %s\n", e_source_group_peek_uid (l->data));
|
||||
dprintf (" sources:\n");
|
||||
|
||||
esources = e_source_group_peek_sources (l->data);
|
||||
for (s = esources; s; s = s->next)
|
||||
{
|
||||
ESource *esource = E_SOURCE (s->data);
|
||||
ECal *client;
|
||||
|
||||
dprintf (" type = '%s' uid = '%s', name = '%s', relative uri = '%s': \n",
|
||||
source_data->source_type == E_CAL_SOURCE_TYPE_EVENT ? "appointment" : "task",
|
||||
e_source_peek_uid (esource),
|
||||
e_source_peek_name (esource),
|
||||
e_source_peek_relative_uri (esource));
|
||||
|
||||
if (is_source_selected (esource, source_data->selected_sources) &&
|
||||
(client = get_ecal_from_source (esource, source_data->source_type, source_data->clients)))
|
||||
{
|
||||
clients = g_slist_prepend (clients, client);
|
||||
}
|
||||
}
|
||||
}
|
||||
dprintf ("\n");
|
||||
|
||||
if (source_data->loaded &&
|
||||
!compare_ecal_lists (source_data->clients, clients))
|
||||
emit_signal = TRUE;
|
||||
|
||||
for (l = source_data->clients; l; l = l->next)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (G_OBJECT (l->data),
|
||||
G_CALLBACK (backend_died_cb),
|
||||
source_data);
|
||||
|
||||
g_object_unref (l->data);
|
||||
}
|
||||
g_slist_free (source_data->clients);
|
||||
source_data->clients = g_slist_reverse (clients);
|
||||
|
||||
/* connect to backend_died after we disconnected the previous signal
|
||||
* handlers. If we do it before, we'll lose some handlers (for clients that
|
||||
* were already there before) */
|
||||
for (l = source_data->clients; l; l = l->next)
|
||||
{
|
||||
g_signal_connect (G_OBJECT (l->data), "backend_died",
|
||||
G_CALLBACK (backend_died_cb), source_data);
|
||||
}
|
||||
|
||||
if (emit_signal)
|
||||
{
|
||||
dprintf ("Emitting %s-sources-changed signal\n",
|
||||
source_data->source_type == E_CAL_SOURCE_TYPE_EVENT ? "appointment" : "task");
|
||||
g_signal_emit (source_data->sources, source_data->changed_signal, 0);
|
||||
}
|
||||
|
||||
debug_dump_ecal_list (source_data->clients);
|
||||
}
|
||||
|
||||
static void
|
||||
calendar_sources_esource_list_changed (ESourceList *source_list,
|
||||
CalendarSourceData *source_data)
|
||||
|
||||
{
|
||||
dprintf ("ESourceList changed, reloading\n");
|
||||
|
||||
calendar_sources_load_esource_list (source_data);
|
||||
}
|
||||
|
||||
static void
|
||||
calendar_sources_selected_sources_notify (GConfClient *client,
|
||||
guint cnx_id,
|
||||
GConfEntry *entry,
|
||||
CalendarSourceData *source_data)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
if (!entry->value ||
|
||||
entry->value->type != GCONF_VALUE_LIST ||
|
||||
gconf_value_get_list_type (entry->value) != GCONF_VALUE_STRING)
|
||||
return;
|
||||
|
||||
dprintf ("Selected sources key (%s) changed, reloading\n", entry->key);
|
||||
|
||||
for (l = source_data->selected_sources; l; l = l->next)
|
||||
g_free (l->data);
|
||||
source_data->selected_sources = NULL;
|
||||
|
||||
for (l = gconf_value_get_list (entry->value); l; l = l->next)
|
||||
{
|
||||
const char *source = gconf_value_get_string (l->data);
|
||||
|
||||
source_data->selected_sources =
|
||||
g_slist_prepend (source_data->selected_sources,
|
||||
g_strdup (source));
|
||||
}
|
||||
source_data->selected_sources =
|
||||
g_slist_reverse (source_data->selected_sources);
|
||||
|
||||
calendar_sources_load_esource_list (source_data);
|
||||
}
|
||||
|
||||
static void
|
||||
calendar_sources_load_sources (CalendarSources *sources,
|
||||
CalendarSourceData *source_data,
|
||||
const char *sources_key,
|
||||
const char *selected_sources_key,
|
||||
const char *selected_sources_dir)
|
||||
{
|
||||
GConfClient *gconf_client;
|
||||
GError *error;
|
||||
|
||||
dprintf ("---------------------------\n");
|
||||
dprintf ("Loading sources:\n");
|
||||
dprintf (" sources_key: %s\n", sources_key);
|
||||
dprintf (" selected_sources_key: %s\n", selected_sources_key);
|
||||
dprintf (" selected_sources_dir: %s\n", selected_sources_dir);
|
||||
|
||||
gconf_client = sources->priv->gconf_client;
|
||||
|
||||
error = NULL;
|
||||
source_data->selected_sources = gconf_client_get_list (gconf_client,
|
||||
selected_sources_key,
|
||||
GCONF_VALUE_STRING,
|
||||
&error);
|
||||
if (error)
|
||||
{
|
||||
g_warning ("Failed to get selected sources from '%s': %s\n",
|
||||
selected_sources_key,
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
gconf_client_add_dir (gconf_client,
|
||||
selected_sources_dir,
|
||||
GCONF_CLIENT_PRELOAD_NONE,
|
||||
NULL);
|
||||
source_data->selected_sources_dir = g_strdup (selected_sources_dir);
|
||||
|
||||
source_data->selected_sources_listener =
|
||||
gconf_client_notify_add (gconf_client,
|
||||
selected_sources_dir,
|
||||
(GConfClientNotifyFunc) calendar_sources_selected_sources_notify,
|
||||
source_data, NULL, NULL);
|
||||
|
||||
source_data->esource_list = e_source_list_new_for_gconf (gconf_client, sources_key);
|
||||
g_signal_connect (source_data->esource_list, "changed",
|
||||
G_CALLBACK (calendar_sources_esource_list_changed),
|
||||
source_data);
|
||||
|
||||
calendar_sources_load_esource_list (source_data);
|
||||
|
||||
source_data->loaded = TRUE;
|
||||
|
||||
dprintf ("---------------------------\n");
|
||||
}
|
||||
|
||||
GSList *
|
||||
calendar_sources_get_appointment_sources (CalendarSources *sources)
|
||||
{
|
||||
g_return_val_if_fail (CALENDAR_IS_SOURCES (sources), NULL);
|
||||
|
||||
if (!sources->priv->appointment_sources.loaded)
|
||||
{
|
||||
calendar_sources_load_sources (sources,
|
||||
&sources->priv->appointment_sources,
|
||||
CALENDAR_SOURCES_APPOINTMENT_SOURCES_KEY,
|
||||
CALENDAR_SOURCES_SELECTED_APPOINTMENT_SOURCES_KEY,
|
||||
CALENDAR_SOURCES_SELECTED_APPOINTMENT_SOURCES_DIR);
|
||||
}
|
||||
|
||||
return sources->priv->appointment_sources.clients;
|
||||
}
|
||||
|
||||
GSList *
|
||||
calendar_sources_get_task_sources (CalendarSources *sources)
|
||||
{
|
||||
g_return_val_if_fail (CALENDAR_IS_SOURCES (sources), NULL);
|
||||
|
||||
if (!sources->priv->task_sources.loaded)
|
||||
{
|
||||
calendar_sources_load_sources (sources,
|
||||
&sources->priv->task_sources,
|
||||
CALENDAR_SOURCES_TASK_SOURCES_KEY,
|
||||
CALENDAR_SOURCES_SELECTED_TASK_SOURCES_KEY,
|
||||
CALENDAR_SOURCES_SELECTED_TASK_SOURCES_DIR);
|
||||
}
|
||||
|
||||
return sources->priv->task_sources.clients;
|
||||
}
|
66
src/calendar-client/calendar-sources.h
Normal file
66
src/calendar-client/calendar-sources.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Authors:
|
||||
* Mark McLoughlin <mark@skynet.ie>
|
||||
* William Jon McCann <mccann@jhu.edu>
|
||||
* Martin Grimme <martin@pycage.de>
|
||||
* Christian Kellner <gicmo@xatom.net>
|
||||
*/
|
||||
|
||||
#ifndef __CALENDAR_SOURCES_H__
|
||||
#define __CALENDAR_SOURCES_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CALENDAR_TYPE_SOURCES (calendar_sources_get_type ())
|
||||
#define CALENDAR_SOURCES(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CALENDAR_TYPE_SOURCES, CalendarSources))
|
||||
#define CALENDAR_SOURCES_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), CALENDAR_TYPE_SOURCES, CalendarSourcesClass))
|
||||
#define CALENDAR_IS_SOURCES(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CALENDAR_TYPE_SOURCES))
|
||||
#define CALENDAR_IS_SOURCES_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CALENDAR_TYPE_SOURCES))
|
||||
#define CALENDAR_SOURCES_GET_CLASS(o)(G_TYPE_INSTANCE_GET_CLASS ((o), CALENDAR_TYPE_SOURCES, CalendarSourcesClass))
|
||||
|
||||
typedef struct _CalendarSources CalendarSources;
|
||||
typedef struct _CalendarSourcesClass CalendarSourcesClass;
|
||||
typedef struct _CalendarSourcesPrivate CalendarSourcesPrivate;
|
||||
|
||||
struct _CalendarSources
|
||||
{
|
||||
GObject parent;
|
||||
CalendarSourcesPrivate *priv;
|
||||
};
|
||||
|
||||
struct _CalendarSourcesClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* appointment_sources_changed) (CalendarSources *sources);
|
||||
void (* task_sources_changed) (CalendarSources *sources);
|
||||
};
|
||||
|
||||
|
||||
GType calendar_sources_get_type (void) G_GNUC_CONST;
|
||||
CalendarSources *calendar_sources_get (void);
|
||||
GSList *calendar_sources_get_appointment_sources (CalendarSources *sources);
|
||||
GSList *calendar_sources_get_task_sources (CalendarSources *sources);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CALENDAR_SOURCES_H__ */
|
@ -1020,13 +1020,10 @@ on_get_unix_user_finished (DBusGProxy *proxy,
|
||||
DBusGProxyCall *call,
|
||||
GdmUserManagerNewSession *new_session)
|
||||
{
|
||||
GdmUserManager *manager;
|
||||
GError *error;
|
||||
guint uid;
|
||||
gboolean res;
|
||||
|
||||
manager = new_session->manager;
|
||||
|
||||
g_assert (new_session->get_unix_user_call == call);
|
||||
|
||||
error = NULL;
|
||||
@ -1550,11 +1547,9 @@ static void
|
||||
get_accounts_proxy (GdmUserManager *manager)
|
||||
{
|
||||
DBusGProxy *proxy;
|
||||
GError *error;
|
||||
|
||||
g_assert (manager->priv->accounts_proxy == NULL);
|
||||
|
||||
error = NULL;
|
||||
proxy = dbus_g_proxy_new_for_name (manager->priv->connection,
|
||||
ACCOUNTS_NAME,
|
||||
ACCOUNTS_PATH,
|
||||
@ -2554,8 +2549,6 @@ reload_shells (GdmUserManager *manager)
|
||||
static void
|
||||
load_users_manually (GdmUserManager *manager)
|
||||
{
|
||||
gboolean res;
|
||||
|
||||
manager->priv->shells = g_hash_table_new_full (g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
@ -2564,7 +2557,7 @@ load_users_manually (GdmUserManager *manager)
|
||||
|
||||
load_sessions (manager);
|
||||
|
||||
res = load_ck_history (manager);
|
||||
load_ck_history (manager);
|
||||
schedule_reload_passwd (manager);
|
||||
}
|
||||
|
||||
@ -2605,10 +2598,8 @@ load_seat_incrementally (GdmUserManager *manager)
|
||||
}
|
||||
|
||||
if (manager->priv->seat.state == GDM_USER_MANAGER_SEAT_STATE_LOADED) {
|
||||
gboolean res;
|
||||
|
||||
load_sessions (manager);
|
||||
res = load_ck_history (manager);
|
||||
load_ck_history (manager);
|
||||
}
|
||||
|
||||
maybe_set_is_loaded (manager);
|
||||
@ -3059,15 +3050,6 @@ gdm_user_manager_finalize (GObject *object)
|
||||
G_OBJECT_CLASS (gdm_user_manager_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_user_muted_debug_log_handler (const char *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
const char *message,
|
||||
gpointer data)
|
||||
{
|
||||
/* Intentionally empty to discard message */
|
||||
}
|
||||
|
||||
/**
|
||||
* gdm_user_manager_ref_default:
|
||||
*
|
||||
@ -3086,11 +3068,6 @@ gdm_user_manager_ref_default (void)
|
||||
user_manager_object = g_object_new (GDM_TYPE_USER_MANAGER, NULL);
|
||||
g_object_add_weak_pointer (user_manager_object,
|
||||
(gpointer *) &user_manager_object);
|
||||
|
||||
/* We don't normally care about user manager messages in the shell,
|
||||
* so mute them */
|
||||
g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
|
||||
gdm_user_muted_debug_log_handler, NULL);
|
||||
}
|
||||
|
||||
return GDM_USER_MANAGER (user_manager_object);
|
||||
|
@ -151,10 +151,6 @@ gdm_user_set_property (GObject *object,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdmUser *user;
|
||||
|
||||
user = GDM_USER (object);
|
||||
|
||||
switch (prop_id) {
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include "shell-perf-log.h"
|
||||
#include "shell-wm-private.h"
|
||||
#include "st.h"
|
||||
#include "shell-a11y.h"
|
||||
|
||||
static void gnome_shell_plugin_dispose (GObject *object);
|
||||
static void gnome_shell_plugin_finalize (GObject *object);
|
||||
@ -301,11 +302,104 @@ add_statistics (GnomeShellPlugin *shell_plugin)
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
/* This is an IBus workaround. The flow of events with IBus is that every time
|
||||
* it gets gets a key event, it:
|
||||
*
|
||||
* Sends it to the daemon via D-Bus asynchronously
|
||||
* When it gets an reply, synthesizes a new GdkEvent and puts it into the
|
||||
* GDK event queue with gdk_event_put(), including
|
||||
* IBUS_FORWARD_MASK = 1 << 25 in the state to prevent a loop.
|
||||
*
|
||||
* (Normally, IBus uses the GTK+ key snooper mechanism to get the key
|
||||
* events early, but since our key events aren't visible to GTK+ key snoopers,
|
||||
* IBus will instead get the events via the standard
|
||||
* GtkIMContext.filter_keypress() mechanism.)
|
||||
*
|
||||
* There are a number of potential problems here; probably the worst
|
||||
* problem is that IBus doesn't forward the timestamp with the event
|
||||
* so that every key event that gets delivered ends up with
|
||||
* GDK_CURRENT_TIME. This creates some very subtle bugs; for example
|
||||
* if you have IBus running and a keystroke is used to trigger
|
||||
* launching an application, focus stealing prevention won't work
|
||||
* right. http://code.google.com/p/ibus/issues/detail?id=1184
|
||||
*
|
||||
* In any case, our normal flow of key events is:
|
||||
*
|
||||
* GDK filter function => clutter_x11_handle_event => clutter actor
|
||||
*
|
||||
* So, if we see a key event that gets delivered via the GDK event handler
|
||||
* function - then we know it must be one of these synthesized events, and
|
||||
* we should push it back to clutter.
|
||||
*
|
||||
* To summarize, the full key event flow with IBus is:
|
||||
*
|
||||
* GDK filter function
|
||||
* => Mutter
|
||||
* => gnome_shell_plugin_xevent_filter()
|
||||
* => clutter_x11_handle_event()
|
||||
* => clutter event delivery to actor
|
||||
* => gtk_im_context_filter_event()
|
||||
* => sent to IBus daemon
|
||||
* => response received from IBus daemon
|
||||
* => gdk_event_put()
|
||||
* => GDK event handler
|
||||
* => <this function>
|
||||
* => clutter_event_put()
|
||||
* => clutter event delivery to actor
|
||||
*
|
||||
* Anything else we see here we just pass on to the normal GDK event handler
|
||||
* gtk_main_do_event().
|
||||
*/
|
||||
static void
|
||||
gvc_muted_debug_log_handler (const char *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
const char *message,
|
||||
gpointer data)
|
||||
gnome_shell_gdk_event_handler (GdkEvent *event_gdk,
|
||||
gpointer data)
|
||||
{
|
||||
if (event_gdk->type == GDK_KEY_PRESS || event_gdk->type == GDK_KEY_RELEASE)
|
||||
{
|
||||
ClutterActor *stage;
|
||||
Window stage_xwindow;
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
stage_xwindow = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
|
||||
|
||||
if (GDK_WINDOW_XID (event_gdk->key.window) == stage_xwindow)
|
||||
{
|
||||
ClutterDeviceManager *device_manager = clutter_device_manager_get_default ();
|
||||
ClutterInputDevice *keyboard = clutter_device_manager_get_core_device (device_manager,
|
||||
CLUTTER_KEYBOARD_DEVICE);
|
||||
|
||||
ClutterEvent *event_clutter = clutter_event_new ((event_gdk->type == GDK_KEY_RELEASE) ?
|
||||
CLUTTER_KEY_PRESS : CLUTTER_KEY_RELEASE);
|
||||
event_clutter->key.time = event_gdk->key.time;
|
||||
event_clutter->key.flags = CLUTTER_EVENT_NONE;
|
||||
event_clutter->key.stage = CLUTTER_STAGE (stage);
|
||||
event_clutter->key.source = NULL;
|
||||
|
||||
/* This depends on ClutterModifierType and GdkModifierType being
|
||||
* identical, which they are currently. (They both match the X
|
||||
* modifier state in the low 16-bits and have the same extensions.) */
|
||||
event_clutter->key.modifier_state = event_gdk->key.state;
|
||||
|
||||
event_clutter->key.keyval = event_gdk->key.keyval;
|
||||
event_clutter->key.hardware_keycode = event_gdk->key.hardware_keycode;
|
||||
event_clutter->key.unicode_value = gdk_keyval_to_unicode (event_clutter->key.keyval);
|
||||
event_clutter->key.device = keyboard;
|
||||
|
||||
clutter_event_put (event_clutter);
|
||||
clutter_event_free (event_clutter);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_main_do_event (event_gdk);
|
||||
}
|
||||
|
||||
static void
|
||||
muted_log_handler (const char *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
const char *message,
|
||||
gpointer data)
|
||||
{
|
||||
/* Intentionally empty to discard message */
|
||||
}
|
||||
@ -327,6 +421,8 @@ gnome_shell_plugin_start (MetaPlugin *plugin)
|
||||
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
|
||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||
|
||||
shell_a11y_init ();
|
||||
|
||||
settings = gtk_settings_get_default ();
|
||||
g_object_connect (settings,
|
||||
"signal::notify::gtk-xft-dpi",
|
||||
@ -340,6 +436,8 @@ gnome_shell_plugin_start (MetaPlugin *plugin)
|
||||
NULL);
|
||||
update_font_options (settings);
|
||||
|
||||
gdk_event_handler_set (gnome_shell_gdk_event_handler, plugin, NULL);
|
||||
|
||||
screen = meta_plugin_get_screen (plugin);
|
||||
display = meta_screen_get_display (screen);
|
||||
|
||||
@ -375,9 +473,13 @@ gnome_shell_plugin_start (MetaPlugin *plugin)
|
||||
NULL);
|
||||
g_strfreev(search_path);
|
||||
|
||||
/* Disable the gnome-volume-control debug */
|
||||
/* Disable debug spew from various libraries */
|
||||
g_log_set_handler ("Gvc", G_LOG_LEVEL_DEBUG,
|
||||
gvc_muted_debug_log_handler, NULL);
|
||||
muted_log_handler, NULL);
|
||||
g_log_set_handler ("GdmUser", G_LOG_LEVEL_DEBUG,
|
||||
muted_log_handler, NULL);
|
||||
g_log_set_handler ("libgnome-bluetooth", G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_MESSAGE,
|
||||
muted_log_handler, NULL);
|
||||
|
||||
/* Initialize the global object here. */
|
||||
shell_plugin->global = shell_global_get ();
|
||||
|
@ -219,12 +219,23 @@ def start_shell(perf_output=None):
|
||||
js_dir = os.path.join('@pkgdatadir@', 'js')
|
||||
|
||||
# Set up environment
|
||||
|
||||
# About the value of NO_GAIL and NO_AT_BRIDGE: If a11y is enabled,
|
||||
# gtk_init() will normally load gail and at-bridge. But we don't
|
||||
# want at-bridge to be loaded until after clutter is initialized
|
||||
# (which mutter does after initializing gtk) and we don't want
|
||||
# gail to be loaded at all. So set these flags. shell_a11y_init()
|
||||
# will clear them so they don't get passed to gnome-shell's
|
||||
# children.
|
||||
|
||||
env = dict(os.environ)
|
||||
env.update({'GNOME_SHELL_JS' : js_dir,
|
||||
'PATH' : '@MUTTER_BIN_DIR@:' + os.environ.get('PATH', ''),
|
||||
'XDG_CONFIG_DIRS' : '@sysconfdir@/xdg:' + (os.environ.get('XDG_CONFIG_DIRS') or '/etc/xdg'),
|
||||
'XDG_DATA_DIRS' : '@datadir@:' + (os.environ.get('XDG_DATA_DIRS') or '/usr/local/share:/usr/share'),
|
||||
'GNOME_DISABLE_CRASH_DIALOG' : '1'})
|
||||
'GNOME_DISABLE_CRASH_DIALOG' : '1',
|
||||
'NO_GAIL' : '1',
|
||||
'NO_AT_BRIDGE' : '1'})
|
||||
|
||||
if running_from_source_tree:
|
||||
env.update({'GNOME_SHELL_DATADIR' : data_dir,
|
||||
@ -672,7 +683,8 @@ use an extension title clicktofocus@janedoe.example.com.'''
|
||||
os.makedirs(extension_path)
|
||||
meta = { 'name': name,
|
||||
'description': description,
|
||||
'uuid': uuid }
|
||||
'uuid': uuid,
|
||||
'shell-version': ['@VERSION@'] }
|
||||
f = open(os.path.join(extension_path, 'metadata.json'), 'w')
|
||||
try:
|
||||
json.dump(meta, f)
|
||||
|
@ -59,13 +59,10 @@ update_settings (GvcMixerEventRole *role,
|
||||
gpointer *op)
|
||||
{
|
||||
pa_operation *o;
|
||||
guint index;
|
||||
const GvcChannelMap *map;
|
||||
pa_context *context;
|
||||
pa_ext_stream_restore_info info;
|
||||
|
||||
index = gvc_mixer_stream_get_index (GVC_MIXER_STREAM (role));
|
||||
|
||||
map = gvc_mixer_stream_get_channel_map (GVC_MIXER_STREAM(role));
|
||||
|
||||
info.volume = *gvc_channel_map_get_cvolume(map);
|
||||
@ -165,12 +162,9 @@ gvc_mixer_event_role_constructor (GType type,
|
||||
GObjectConstructParam *construct_params)
|
||||
{
|
||||
GObject *object;
|
||||
GvcMixerEventRole *self;
|
||||
|
||||
object = G_OBJECT_CLASS (gvc_mixer_event_role_parent_class)->constructor (type, n_construct_properties, construct_params);
|
||||
|
||||
self = GVC_MIXER_EVENT_ROLE (object);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
|
@ -55,12 +55,10 @@ gvc_mixer_sink_input_push_volume (GvcMixerStream *stream, gpointer *op)
|
||||
const GvcChannelMap *map;
|
||||
pa_context *context;
|
||||
const pa_cvolume *cv;
|
||||
guint num_channels;
|
||||
|
||||
index = gvc_mixer_stream_get_index (stream);
|
||||
|
||||
map = gvc_mixer_stream_get_channel_map (stream);
|
||||
num_channels = gvc_channel_map_get_num_channels (map);
|
||||
|
||||
cv = gvc_channel_map_get_cvolume(map);
|
||||
|
||||
@ -115,12 +113,9 @@ gvc_mixer_sink_input_constructor (GType type,
|
||||
GObjectConstructParam *construct_params)
|
||||
{
|
||||
GObject *object;
|
||||
GvcMixerSinkInput *self;
|
||||
|
||||
object = G_OBJECT_CLASS (gvc_mixer_sink_input_parent_class)->constructor (type, n_construct_properties, construct_params);
|
||||
|
||||
self = GVC_MIXER_SINK_INPUT (object);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
@ -149,13 +144,9 @@ gvc_mixer_sink_input_init (GvcMixerSinkInput *sink_input)
|
||||
static void
|
||||
gvc_mixer_sink_input_dispose (GObject *object)
|
||||
{
|
||||
GvcMixerSinkInput *mixer_sink_input;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (GVC_IS_MIXER_SINK_INPUT (object));
|
||||
|
||||
mixer_sink_input = GVC_MIXER_SINK_INPUT (object);
|
||||
|
||||
G_OBJECT_CLASS (gvc_mixer_sink_input_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
@ -145,12 +145,9 @@ gvc_mixer_sink_constructor (GType type,
|
||||
GObjectConstructParam *construct_params)
|
||||
{
|
||||
GObject *object;
|
||||
GvcMixerSink *self;
|
||||
|
||||
object = G_OBJECT_CLASS (gvc_mixer_sink_parent_class)->constructor (type, n_construct_properties, construct_params);
|
||||
|
||||
self = GVC_MIXER_SINK (object);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
@ -180,13 +177,9 @@ gvc_mixer_sink_init (GvcMixerSink *sink)
|
||||
static void
|
||||
gvc_mixer_sink_dispose (GObject *object)
|
||||
{
|
||||
GvcMixerSink *mixer_sink;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (GVC_IS_MIXER_SINK (object));
|
||||
|
||||
mixer_sink = GVC_MIXER_SINK (object);
|
||||
|
||||
G_OBJECT_CLASS (gvc_mixer_sink_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
@ -66,12 +66,9 @@ gvc_mixer_source_output_constructor (GType type,
|
||||
GObjectConstructParam *construct_params)
|
||||
{
|
||||
GObject *object;
|
||||
GvcMixerSourceOutput *self;
|
||||
|
||||
object = G_OBJECT_CLASS (gvc_mixer_source_output_parent_class)->constructor (type, n_construct_properties, construct_params);
|
||||
|
||||
self = GVC_MIXER_SOURCE_OUTPUT (object);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
|
@ -145,12 +145,9 @@ gvc_mixer_source_constructor (GType type,
|
||||
GObjectConstructParam *construct_params)
|
||||
{
|
||||
GObject *object;
|
||||
GvcMixerSource *self;
|
||||
|
||||
object = G_OBJECT_CLASS (gvc_mixer_source_parent_class)->constructor (type, n_construct_properties, construct_params);
|
||||
|
||||
self = GVC_MIXER_SOURCE (object);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
@ -180,13 +177,9 @@ gvc_mixer_source_init (GvcMixerSource *source)
|
||||
static void
|
||||
gvc_mixer_source_dispose (GObject *object)
|
||||
{
|
||||
GvcMixerSource *mixer_source;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (GVC_IS_MIXER_SOURCE (object));
|
||||
|
||||
mixer_source = GVC_MIXER_SOURCE (object);
|
||||
|
||||
G_OBJECT_CLASS (gvc_mixer_source_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
165
src/shell-a11y.c
Normal file
165
src/shell-a11y.c
Normal file
@ -0,0 +1,165 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2010 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <gmodule.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "shell-a11y.h"
|
||||
|
||||
#define INIT_METHOD "gnome_accessibility_module_init"
|
||||
#define DESKTOP_SCHEMA "org.gnome.desktop.interface"
|
||||
#define ACCESSIBILITY_ENABLED_KEY "accessibility"
|
||||
#define AT_SPI_SCHEMA "org.a11y.atspi"
|
||||
#define ATK_BRIDGE_LOCATION_KEY "atk-bridge-location"
|
||||
|
||||
static gboolean
|
||||
should_enable_a11y (void)
|
||||
{
|
||||
GSettings *desktop_settings = NULL;
|
||||
gboolean value = FALSE;
|
||||
|
||||
desktop_settings = g_settings_new (DESKTOP_SCHEMA);
|
||||
value = g_settings_get_boolean (desktop_settings, ACCESSIBILITY_ENABLED_KEY);
|
||||
|
||||
g_object_unref (desktop_settings);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static char*
|
||||
get_atk_bridge_path (void)
|
||||
{
|
||||
GSettings *atspi_settings = NULL;
|
||||
char *value = NULL;
|
||||
const char * const *schemas = NULL;
|
||||
gboolean found = FALSE;
|
||||
int i = 0;
|
||||
|
||||
schemas = g_settings_list_schemas ();
|
||||
|
||||
for (i = 0; schemas [i]; i++)
|
||||
{
|
||||
if (!strcmp (schemas[i], AT_SPI_SCHEMA))
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
g_warning ("Accessibility: %s schema not found. Are you sure that at-spi or"
|
||||
" at-spi2 is installed on your system?", AT_SPI_SCHEMA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
atspi_settings = g_settings_new (AT_SPI_SCHEMA);
|
||||
value = g_settings_get_string (atspi_settings, ATK_BRIDGE_LOCATION_KEY);
|
||||
|
||||
g_object_unref (atspi_settings);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
a11y_invoke_module (const char *module_path)
|
||||
{
|
||||
GModule *handle;
|
||||
void (*invoke_fn) (void);
|
||||
|
||||
if (!module_path)
|
||||
{
|
||||
g_warning ("Accessibility: invalid module path (NULL)");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!(handle = g_module_open (module_path, 0)))
|
||||
{
|
||||
g_warning ("Accessibility: failed to load module '%s': '%s'",
|
||||
module_path, g_module_error ());
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!g_module_symbol (handle, INIT_METHOD, (gpointer *)&invoke_fn))
|
||||
{
|
||||
g_warning ("Accessibility: error library '%s' does not include "
|
||||
"method '%s' required for accessibility support",
|
||||
module_path, INIT_METHOD);
|
||||
g_module_close (handle);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
invoke_fn ();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* It loads the atk-bridge if required. It checks:
|
||||
* * If the proper gsetting key is set
|
||||
* * If clutter has already enabled the accessibility
|
||||
*
|
||||
* You need to ensure that the atk-bridge was not loaded before this
|
||||
* call, because in that case the application would be already
|
||||
* registered on at-spi using the AtkUtil implementation on that
|
||||
* moment (if any, although without anyone the application would
|
||||
* crash). Anyway this is the reason of NO_AT_BRIDGE.
|
||||
*
|
||||
*/
|
||||
void
|
||||
shell_a11y_init (void)
|
||||
{
|
||||
char *bridge_path = NULL;
|
||||
|
||||
g_unsetenv ("NO_AT_BRIDGE");
|
||||
g_unsetenv ("NO_GAIL");
|
||||
|
||||
if (!should_enable_a11y ())
|
||||
return;
|
||||
|
||||
if (clutter_get_accessibility_enabled () == FALSE)
|
||||
{
|
||||
g_warning ("Accessibility: clutter has no accessibility enabled"
|
||||
" skipping the atk-bridge load");
|
||||
return;
|
||||
}
|
||||
|
||||
bridge_path = get_atk_bridge_path ();
|
||||
|
||||
if (a11y_invoke_module (bridge_path) == FALSE)
|
||||
{
|
||||
g_warning ("Accessibility: error loading the atk-bridge. Although the"
|
||||
" accessibility on the system is enabled and clutter"
|
||||
" accessibility is also enabled, accessibility support on"
|
||||
" GNOME Shell will not work");
|
||||
}
|
||||
|
||||
/* NOTE: We avoid to load gail module, as gail-cally interaction is
|
||||
* not fully supported right now.
|
||||
*/
|
||||
|
||||
g_free (bridge_path);
|
||||
}
|
32
src/shell-a11y.h
Normal file
32
src/shell-a11y.h
Normal file
@ -0,0 +1,32 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||
*
|
||||
* Copyright (C) 2010 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SHELL_A11Y_H_
|
||||
#define __SHELL_A11Y_H_
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void shell_a11y_init (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __SHELL_A11Y_H_ */
|
@ -1317,7 +1317,6 @@ shell_app_info_launch_full (ShellAppInfo *info,
|
||||
gboolean ret;
|
||||
ShellGlobal *global;
|
||||
MetaScreen *screen;
|
||||
MetaDisplay *display;
|
||||
|
||||
if (startup_id)
|
||||
*startup_id = NULL;
|
||||
@ -1353,7 +1352,6 @@ shell_app_info_launch_full (ShellAppInfo *info,
|
||||
|
||||
global = shell_global_get ();
|
||||
screen = shell_global_get_screen (global);
|
||||
display = meta_screen_get_display (screen);
|
||||
|
||||
if (timestamp == 0)
|
||||
timestamp = clutter_get_current_event_time ();
|
||||
|
@ -34,63 +34,69 @@ struct _ShellAppSystemClass
|
||||
void (*favorites_changed)(ShellAppSystem *appsys, gpointer user_data);
|
||||
};
|
||||
|
||||
GType shell_app_system_get_type (void) G_GNUC_CONST;
|
||||
ShellAppSystem* shell_app_system_get_default(void);
|
||||
GType shell_app_system_get_type (void) G_GNUC_CONST;
|
||||
ShellAppSystem *shell_app_system_get_default (void);
|
||||
|
||||
typedef struct _ShellAppInfo ShellAppInfo;
|
||||
|
||||
#define SHELL_TYPE_APP_INFO (shell_app_info_get_type ())
|
||||
GType shell_app_info_get_type (void);
|
||||
GType shell_app_info_get_type (void);
|
||||
|
||||
ShellAppInfo* shell_app_info_ref (ShellAppInfo *info);
|
||||
void shell_app_info_unref (ShellAppInfo *info);
|
||||
ShellAppInfo *shell_app_info_ref (ShellAppInfo *info);
|
||||
void shell_app_info_unref (ShellAppInfo *info);
|
||||
|
||||
const char *shell_app_info_get_id (ShellAppInfo *info);
|
||||
char *shell_app_info_get_name (ShellAppInfo *info);
|
||||
char *shell_app_info_get_description (ShellAppInfo *info);
|
||||
char *shell_app_info_get_executable (ShellAppInfo *info);
|
||||
char *shell_app_info_get_desktop_file_path (ShellAppInfo *info);
|
||||
GIcon *shell_app_info_get_icon (ShellAppInfo *info);
|
||||
ClutterActor *shell_app_info_create_icon_texture (ShellAppInfo *info, float size);
|
||||
char *shell_app_info_get_section (ShellAppInfo *info);
|
||||
gboolean shell_app_info_get_is_nodisplay (ShellAppInfo *info);
|
||||
gboolean shell_app_info_is_transient (ShellAppInfo *info);
|
||||
const char *shell_app_info_get_id (ShellAppInfo *info);
|
||||
char *shell_app_info_get_name (ShellAppInfo *info);
|
||||
char *shell_app_info_get_description (ShellAppInfo *info);
|
||||
char *shell_app_info_get_executable (ShellAppInfo *info);
|
||||
char *shell_app_info_get_desktop_file_path (ShellAppInfo *info);
|
||||
GIcon *shell_app_info_get_icon (ShellAppInfo *info);
|
||||
ClutterActor *shell_app_info_create_icon_texture (ShellAppInfo *info,
|
||||
float size);
|
||||
char *shell_app_info_get_section (ShellAppInfo *info);
|
||||
gboolean shell_app_info_get_is_nodisplay (ShellAppInfo *info);
|
||||
gboolean shell_app_info_is_transient (ShellAppInfo *info);
|
||||
MetaWindow *shell_app_info_get_source_window (ShellAppInfo *info);
|
||||
|
||||
MetaWindow *shell_app_info_get_source_window (ShellAppInfo *info);
|
||||
gboolean shell_app_info_launch (ShellAppInfo *info,
|
||||
GError **error);
|
||||
gboolean shell_app_info_launch_full (ShellAppInfo *info,
|
||||
guint timestamp,
|
||||
GList *uris,
|
||||
int workspace,
|
||||
char **startup_id,
|
||||
GError **error);
|
||||
|
||||
gboolean shell_app_info_launch_full (ShellAppInfo *info,
|
||||
guint timestamp,
|
||||
GList *uris,
|
||||
int workspace,
|
||||
char **startup_id,
|
||||
GError **error);
|
||||
gboolean shell_app_info_launch (ShellAppInfo *info,
|
||||
GError **error);
|
||||
|
||||
ShellAppInfo *shell_app_system_load_from_desktop_file (ShellAppSystem *system, const char *filename, GError **error);
|
||||
GList *shell_app_system_get_sections (ShellAppSystem *system);
|
||||
GSList *shell_app_system_get_flattened_apps (ShellAppSystem *system);
|
||||
GSList *shell_app_system_get_all_settings (ShellAppSystem *system);
|
||||
|
||||
GList *shell_app_system_get_sections (ShellAppSystem *system);
|
||||
ShellApp *shell_app_system_get_app (ShellAppSystem *system, const char *id);
|
||||
ShellApp *shell_app_system_get_app_for_path (ShellAppSystem *system, const char *desktop_path);
|
||||
ShellApp *shell_app_system_get_app_for_window (ShellAppSystem *self, MetaWindow *window);
|
||||
ShellApp *shell_app_system_get_app (ShellAppSystem *system,
|
||||
const char *id);
|
||||
ShellApp *shell_app_system_get_app_for_path (ShellAppSystem *system,
|
||||
const char *desktop_path);
|
||||
ShellApp *shell_app_system_get_app_for_window (ShellAppSystem *self,
|
||||
MetaWindow *window);
|
||||
ShellApp *shell_app_system_lookup_heuristic_basename (ShellAppSystem *system,
|
||||
const char *id);
|
||||
|
||||
void _shell_app_system_register_app (ShellAppSystem *self, ShellApp *app);
|
||||
ShellAppInfo *shell_app_system_load_from_desktop_file (ShellAppSystem *system,
|
||||
const char *filename,
|
||||
GError **error);
|
||||
ShellAppInfo *shell_app_system_create_from_window (ShellAppSystem *system,
|
||||
MetaWindow *window);
|
||||
|
||||
ShellApp *shell_app_system_lookup_heuristic_basename (ShellAppSystem *system, const char *id);
|
||||
GSList *shell_app_system_initial_search (ShellAppSystem *system,
|
||||
gboolean prefs,
|
||||
GSList *terms);
|
||||
GSList *shell_app_system_subsearch (ShellAppSystem *system,
|
||||
gboolean prefs,
|
||||
GSList *previous_results,
|
||||
GSList *terms);
|
||||
|
||||
ShellAppInfo *shell_app_system_create_from_window (ShellAppSystem *system, MetaWindow *window);
|
||||
|
||||
GSList *shell_app_system_get_flattened_apps (ShellAppSystem *system);
|
||||
|
||||
GSList *shell_app_system_get_all_settings (ShellAppSystem *system);
|
||||
|
||||
GSList *shell_app_system_initial_search (ShellAppSystem *system,
|
||||
gboolean prefs,
|
||||
GSList *terms);
|
||||
|
||||
GSList *shell_app_system_subsearch (ShellAppSystem *system,
|
||||
gboolean prefs,
|
||||
GSList *previous_results,
|
||||
GSList *terms);
|
||||
/* internal API */
|
||||
void _shell_app_system_register_app (ShellAppSystem *self,
|
||||
ShellApp *app);
|
||||
|
||||
#endif /* __SHELL_APP_SYSTEM_H__ */
|
||||
|
@ -324,7 +324,8 @@ on_app_state_changed (ShellWindowTracker *tracker,
|
||||
|
||||
running = shell_app_get_state (app) == SHELL_APP_STATE_RUNNING;
|
||||
|
||||
usage->last_seen = get_time ();
|
||||
if (running)
|
||||
usage->last_seen = get_time ();
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -411,6 +411,8 @@ shell_app_activate_window (ShellApp *app,
|
||||
/**
|
||||
* shell_app_activate:
|
||||
* @app: a #ShellApp
|
||||
* @workspace: launch on this workspace, or -1 for default. Ignored if
|
||||
* activating an existing window
|
||||
*
|
||||
* Perform an appropriate default action for operating on this application,
|
||||
* dependent on its current state. For example, if the application is not
|
||||
@ -419,13 +421,19 @@ shell_app_activate_window (ShellApp *app,
|
||||
* recently used transient for that window).
|
||||
*/
|
||||
void
|
||||
shell_app_activate (ShellApp *app)
|
||||
shell_app_activate (ShellApp *app,
|
||||
int workspace)
|
||||
{
|
||||
switch (app->state)
|
||||
{
|
||||
case SHELL_APP_STATE_STOPPED:
|
||||
/* TODO sensibly handle this error */
|
||||
shell_app_info_launch (app->info, NULL);
|
||||
shell_app_info_launch_full (app->info,
|
||||
0,
|
||||
NULL,
|
||||
workspace,
|
||||
NULL,
|
||||
NULL);
|
||||
break;
|
||||
case SHELL_APP_STATE_STARTING:
|
||||
break;
|
||||
@ -438,11 +446,13 @@ shell_app_activate (ShellApp *app)
|
||||
/**
|
||||
* shell_app_open_new_window:
|
||||
* @app: a #ShellApp
|
||||
* @workspace: open on this workspace, or -1 for default
|
||||
*
|
||||
* Request that the application create a new window.
|
||||
*/
|
||||
void
|
||||
shell_app_open_new_window (ShellApp *app)
|
||||
shell_app_open_new_window (ShellApp *app,
|
||||
int workspace)
|
||||
{
|
||||
/* Here we just always launch the application again, even if we know
|
||||
* it was already running. For most applications this
|
||||
@ -452,7 +462,12 @@ shell_app_open_new_window (ShellApp *app)
|
||||
* as say Pidgin. Ideally, we have the application express to us
|
||||
* that it supports an explicit new-window action.
|
||||
*/
|
||||
shell_app_info_launch (app->info, NULL);
|
||||
shell_app_info_launch_full (app->info,
|
||||
0,
|
||||
NULL,
|
||||
workspace,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -577,7 +592,8 @@ shell_app_is_on_workspace (ShellApp *app,
|
||||
|
||||
if (shell_app_get_state (app) == SHELL_APP_STATE_STARTING)
|
||||
{
|
||||
if (meta_workspace_index (workspace) == app->started_on_workspace)
|
||||
if (app->started_on_workspace == -1 ||
|
||||
meta_workspace_index (workspace) == app->started_on_workspace)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
|
@ -44,9 +44,11 @@ gboolean shell_app_is_transient (ShellApp *app);
|
||||
|
||||
void shell_app_activate_window (ShellApp *app, MetaWindow *window, guint32 timestamp);
|
||||
|
||||
void shell_app_activate (ShellApp *app);
|
||||
void shell_app_activate (ShellApp *app,
|
||||
int workspace);
|
||||
|
||||
void shell_app_open_new_window (ShellApp *app);
|
||||
void shell_app_open_new_window (ShellApp *app,
|
||||
int workspace);
|
||||
|
||||
ShellAppState shell_app_get_state (ShellApp *app);
|
||||
|
||||
|
@ -227,17 +227,24 @@ shell_doc_system_on_recent_changed (GtkRecentManager *manager,
|
||||
* shell_doc_system_open:
|
||||
* @system: A #ShellDocSystem
|
||||
* @info: A #GtkRecentInfo
|
||||
* @workspace: Open on this workspace, or -1 for default
|
||||
*
|
||||
* Launch the default application associated with the mime type of
|
||||
* @info, using its uri.
|
||||
*/
|
||||
void
|
||||
shell_doc_system_open (ShellDocSystem *system,
|
||||
GtkRecentInfo *info)
|
||||
GtkRecentInfo *info,
|
||||
int workspace)
|
||||
{
|
||||
GFile *file;
|
||||
GAppInfo *app_info;
|
||||
gboolean needs_uri;
|
||||
GAppLaunchContext *context;
|
||||
|
||||
context = shell_global_create_app_launch_context (shell_global_get ());
|
||||
if (workspace != -1)
|
||||
gdk_app_launch_context_set_desktop ((GdkAppLaunchContext *)context, workspace);
|
||||
|
||||
file = g_file_new_for_uri (gtk_recent_info_get_uri (info));
|
||||
needs_uri = g_file_get_path (file) == NULL;
|
||||
@ -248,7 +255,7 @@ shell_doc_system_open (ShellDocSystem *system,
|
||||
{
|
||||
GList *uris;
|
||||
uris = g_list_prepend (NULL, (gpointer)gtk_recent_info_get_uri (info));
|
||||
g_app_info_launch_uris (app_info, uris, shell_global_create_app_launch_context (shell_global_get ()), NULL);
|
||||
g_app_info_launch_uris (app_info, uris, context, NULL);
|
||||
g_list_free (uris);
|
||||
}
|
||||
else
|
||||
@ -267,7 +274,6 @@ shell_doc_system_open (ShellDocSystem *system,
|
||||
if (gtk_recent_info_get_application_info (info, app_name, &app_exec, &count, &time))
|
||||
{
|
||||
GRegex *regex;
|
||||
GAppLaunchContext *context;
|
||||
|
||||
/* TODO: Change this once better support for creating
|
||||
GAppInfo is added to GtkRecentInfo, as right now
|
||||
@ -285,7 +291,8 @@ shell_doc_system_open (ShellDocSystem *system,
|
||||
app_exec_quoted = g_regex_replace (regex, app_exec, -1, 0, "%%", 0, NULL);
|
||||
g_regex_unref (regex);
|
||||
|
||||
app_info = g_app_info_create_from_commandline (app_exec, NULL, 0, NULL);
|
||||
app_info = g_app_info_create_from_commandline (app_exec_quoted, NULL, 0, NULL);
|
||||
g_free (app_exec_quoted);
|
||||
|
||||
/* The point of passing an app launch context to
|
||||
launch() is mostly to get startup notification and
|
||||
@ -297,13 +304,13 @@ shell_doc_system_open (ShellDocSystem *system,
|
||||
despite passing the app launch context, no startup
|
||||
notification occurs.
|
||||
*/
|
||||
context = shell_global_create_app_launch_context (shell_global_get ());
|
||||
g_app_info_launch (app_info, NULL, context, NULL);
|
||||
g_object_unref (context);
|
||||
}
|
||||
|
||||
g_free (app_name);
|
||||
}
|
||||
|
||||
g_object_unref (context);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -41,6 +41,7 @@ void shell_doc_system_queue_existence_check (ShellDocSystem *system,
|
||||
guint n_items);
|
||||
|
||||
void shell_doc_system_open (ShellDocSystem *system,
|
||||
GtkRecentInfo *info);
|
||||
GtkRecentInfo *info,
|
||||
int workspace);
|
||||
|
||||
#endif /* __SHELL_DOC_SYSTEM_H__ */
|
||||
|
265
src/shell-evolution-event-source.c
Normal file
265
src/shell-evolution-event-source.c
Normal file
@ -0,0 +1,265 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "calendar-client/calendar-client.h"
|
||||
#include "shell-evolution-event-source.h"
|
||||
|
||||
|
||||
struct _ShellEvolutionEventSourceClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
struct _ShellEvolutionEventSource {
|
||||
GObject parent;
|
||||
CalendarClient *client;
|
||||
/* The month that we are currently requesting events from */
|
||||
gint req_year;
|
||||
gint req_mon; /* starts at 1, not zero */
|
||||
};
|
||||
|
||||
/* Signals */
|
||||
enum
|
||||
{
|
||||
CHANGED_SIGNAL,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
G_DEFINE_TYPE (ShellEvolutionEventSource, shell_evolution_event_source, G_TYPE_OBJECT);
|
||||
|
||||
static void
|
||||
on_tasks_changed (CalendarClient *client,
|
||||
gpointer user_data)
|
||||
{
|
||||
ShellEvolutionEventSource *source = SHELL_EVOLUTION_EVENT_SOURCE (user_data);
|
||||
/* g_print ("on tasks changed\n"); */
|
||||
g_signal_emit (source, signals[CHANGED_SIGNAL], 0);
|
||||
}
|
||||
|
||||
static void
|
||||
on_appointments_changed (CalendarClient *client,
|
||||
gpointer user_data)
|
||||
{
|
||||
ShellEvolutionEventSource *source = SHELL_EVOLUTION_EVENT_SOURCE (user_data);
|
||||
/* g_print ("on appointments changed\n"); */
|
||||
g_signal_emit (source, signals[CHANGED_SIGNAL], 0);
|
||||
}
|
||||
|
||||
static void
|
||||
shell_evolution_event_source_init (ShellEvolutionEventSource *source)
|
||||
{
|
||||
source->client = calendar_client_new ();
|
||||
g_signal_connect (source->client,
|
||||
"tasks-changed",
|
||||
G_CALLBACK (on_tasks_changed),
|
||||
source);
|
||||
g_signal_connect (source->client,
|
||||
"appointments-changed",
|
||||
G_CALLBACK (on_appointments_changed),
|
||||
source);
|
||||
}
|
||||
|
||||
static void
|
||||
shell_evolution_event_source_finalize (GObject *object)
|
||||
{
|
||||
ShellEvolutionEventSource *source = SHELL_EVOLUTION_EVENT_SOURCE (object);
|
||||
g_object_unref (source->client);
|
||||
G_OBJECT_CLASS (shell_evolution_event_source_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
shell_evolution_event_source_class_init (ShellEvolutionEventSourceClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = shell_evolution_event_source_finalize;
|
||||
|
||||
signals[CHANGED_SIGNAL] =
|
||||
g_signal_new ("changed",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
}
|
||||
|
||||
ShellEvolutionEventSource *
|
||||
shell_evolution_event_source_new (void)
|
||||
{
|
||||
return SHELL_EVOLUTION_EVENT_SOURCE (g_object_new (SHELL_TYPE_EVOLUTION_EVENT_SOURCE, NULL));
|
||||
}
|
||||
|
||||
void
|
||||
shell_evolution_event_source_request_range (ShellEvolutionEventSource *source,
|
||||
gint64 msec_begin,
|
||||
gint64 msec_end)
|
||||
{
|
||||
GDateTime *middle_utc, *middle;
|
||||
|
||||
/* The CalendarClient type is a convenience wrapper on top of
|
||||
* Evolution Data Server. It is based on the assumption that only
|
||||
* a single month is shown at a time.
|
||||
*
|
||||
* To avoid reimplemting all the work already done in CalendarClient
|
||||
* we make the same assumption. This means that we only show events
|
||||
* in the month that is in the middle of @msec_begin and
|
||||
* @msec_end. Since the Shell displays a month at a time (plus the
|
||||
* days before and after) it works out just fine.
|
||||
*/
|
||||
|
||||
middle_utc = g_date_time_new_from_unix_utc ((msec_begin + msec_end) / 2 / 1000);
|
||||
/* CalendarClient uses localtime rather than UTC */
|
||||
middle = g_date_time_to_local (middle_utc);
|
||||
g_date_time_unref (middle_utc);
|
||||
g_date_time_get_ymd (middle, &source->req_year, &source->req_mon, NULL);
|
||||
g_date_time_unref (middle);
|
||||
calendar_client_select_month (source->client, source->req_mon - 1, source->req_year);
|
||||
}
|
||||
|
||||
static gint
|
||||
event_cmp (gconstpointer a,
|
||||
gconstpointer b)
|
||||
{
|
||||
const ShellEvolutionEvent *ea;
|
||||
const ShellEvolutionEvent *eb;
|
||||
|
||||
ea = a;
|
||||
eb = b;
|
||||
if (ea->msec_begin < eb->msec_begin)
|
||||
return -1;
|
||||
else if (ea->msec_begin > eb->msec_begin)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_evolution_event_source_get_events:
|
||||
* @source: A #ShellEvolutionEventSource.
|
||||
* @msec_begin: Start date (milli-seconds since Epoch).
|
||||
* @msec_end: End date (milli-seconds since Epoch).
|
||||
*
|
||||
* Gets all events that occur between @msec_begin and @msec_end.
|
||||
*
|
||||
* Returns: (element-type ShellEvolutionEvent) (transfer full): List of events.
|
||||
*/
|
||||
GList *
|
||||
shell_evolution_event_source_get_events (ShellEvolutionEventSource *source,
|
||||
gint64 msec_begin,
|
||||
gint64 msec_end)
|
||||
{
|
||||
GList *result;
|
||||
GDateTime *cur_date;
|
||||
GDateTime *begin_date_utc, *begin_date;
|
||||
GDateTime *end_date_utc, *end_date;
|
||||
|
||||
g_return_val_if_fail (msec_begin <= msec_end, NULL);
|
||||
|
||||
result = NULL;
|
||||
|
||||
begin_date_utc = g_date_time_new_from_unix_utc (msec_begin / 1000);
|
||||
end_date_utc = g_date_time_new_from_unix_utc (msec_end / 1000);
|
||||
|
||||
/* CalendarClient uses localtime rather than UTC */
|
||||
begin_date = g_date_time_to_local (begin_date_utc);
|
||||
end_date = g_date_time_to_local (end_date_utc);
|
||||
g_date_time_unref (begin_date_utc);
|
||||
g_date_time_unref (end_date_utc);
|
||||
|
||||
cur_date = g_date_time_ref (begin_date);
|
||||
do
|
||||
{
|
||||
gint year, mon, day;
|
||||
GDateTime *next_date;
|
||||
|
||||
g_date_time_get_ymd (cur_date, &year, &mon, &day);
|
||||
/* g_print ("y=%04d m=%02d d=%02d\n", year, mon, day); */
|
||||
|
||||
/* Silently drop events not in range (see comment in
|
||||
* shell_evolution_event_source_request_range() above)
|
||||
*/
|
||||
if (!(year == source->req_year && mon == source->req_mon))
|
||||
{
|
||||
/* g_print ("skipping day\n"); */
|
||||
}
|
||||
else
|
||||
{
|
||||
GSList *events;
|
||||
GSList *l;
|
||||
calendar_client_select_day (source->client, day);
|
||||
events = calendar_client_get_events (source->client, CALENDAR_EVENT_APPOINTMENT);
|
||||
/* g_print ("num_events: %d\n", g_slist_length (events)); */
|
||||
for (l = events; l; l = l->next)
|
||||
{
|
||||
CalendarAppointment *appointment = l->data;
|
||||
ShellEvolutionEvent *event;
|
||||
gint64 start_time;
|
||||
|
||||
if (appointment->is_all_day)
|
||||
{
|
||||
start_time = g_date_time_to_unix (cur_date) * G_GINT64_CONSTANT (1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
start_time = appointment->start_time * G_GINT64_CONSTANT (1000);
|
||||
}
|
||||
event = shell_evolution_event_new (appointment->summary,
|
||||
appointment->is_all_day,
|
||||
start_time);
|
||||
result = g_list_prepend (result, event);
|
||||
}
|
||||
g_slist_foreach (events, (GFunc) calendar_event_free, NULL);
|
||||
g_slist_free (events);
|
||||
}
|
||||
|
||||
next_date = g_date_time_add_days (cur_date, 1);
|
||||
g_date_time_unref (cur_date);
|
||||
cur_date = next_date;
|
||||
}
|
||||
while (g_date_time_difference (end_date, cur_date) > 0);
|
||||
g_date_time_unref (begin_date);
|
||||
g_date_time_unref (end_date);
|
||||
|
||||
result = g_list_sort (result, event_cmp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
G_DEFINE_BOXED_TYPE (ShellEvolutionEvent,
|
||||
shell_evolution_event,
|
||||
shell_evolution_event_copy,
|
||||
shell_evolution_event_free);
|
||||
|
||||
void
|
||||
shell_evolution_event_free (ShellEvolutionEvent *event)
|
||||
{
|
||||
g_free (event->summary);
|
||||
g_free (event);
|
||||
}
|
||||
|
||||
ShellEvolutionEvent *
|
||||
shell_evolution_event_copy (ShellEvolutionEvent *event)
|
||||
{
|
||||
ShellEvolutionEvent *copy;
|
||||
copy = g_memdup (event, sizeof (ShellEvolutionEvent));
|
||||
copy->summary = g_strdup (event->summary);
|
||||
return copy;
|
||||
}
|
||||
|
||||
ShellEvolutionEvent *
|
||||
shell_evolution_event_new (const gchar *summary,
|
||||
gboolean all_day,
|
||||
gint64 msec_begin)
|
||||
{
|
||||
ShellEvolutionEvent *event;
|
||||
event = g_new0 (ShellEvolutionEvent, 1);
|
||||
event->summary = g_strdup (summary);
|
||||
event->all_day = all_day;
|
||||
event->msec_begin = msec_begin;
|
||||
return event;
|
||||
}
|
45
src/shell-evolution-event-source.h
Normal file
45
src/shell-evolution-event-source.h
Normal file
@ -0,0 +1,45 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
#ifndef __SHELL_EVOLUTION_EVENT_SOURCE_H__
|
||||
#define __SHELL_EVOLUTION_EVENT_SOURCE_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _ShellEvolutionEvent ShellEvolutionEvent;
|
||||
|
||||
struct _ShellEvolutionEvent
|
||||
{
|
||||
gchar *summary;
|
||||
gboolean all_day;
|
||||
gint64 msec_begin;
|
||||
};
|
||||
|
||||
GType shell_evolution_event_get_type (void) G_GNUC_CONST;
|
||||
ShellEvolutionEvent *shell_evolution_event_new (const gchar *summary,
|
||||
gboolean all_day,
|
||||
gint64 msec_begin);
|
||||
ShellEvolutionEvent *shell_evolution_event_copy (ShellEvolutionEvent *event);
|
||||
void shell_evolution_event_free (ShellEvolutionEvent *event);
|
||||
|
||||
typedef struct _ShellEvolutionEventSource ShellEvolutionEventSource;
|
||||
typedef struct _ShellEvolutionEventSourceClass ShellEvolutionEventSourceClass;
|
||||
|
||||
#define SHELL_TYPE_EVOLUTION_EVENT_SOURCE (shell_evolution_event_source_get_type ())
|
||||
#define SHELL_EVOLUTION_EVENT_SOURCE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), SHELL_TYPE_EVOLUTION_EVENT_SOURCE, ShellEvolutionEventSource))
|
||||
#define SHELL_EVOLUTION_EVENT_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_EVOLUTION_EVENT_SOURCE, ShellEvolutionEventSourceClass))
|
||||
#define SHELL_IS_EVOLUTION_EVENT_SOURCE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), SHELL_TYPE_EVOLUTION_EVENT_SOURCE))
|
||||
#define SHELL_IS_EVOLUTION_EVENT_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_EVOLUTION_EVENT_SOURCE))
|
||||
#define SHELL_EVOLUTION_EVENT_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_EVOLUTION_EVENT_SOURCE, ShellEvolutionEventSourceClass))
|
||||
|
||||
GType shell_evolution_event_source_get_type (void) G_GNUC_CONST;
|
||||
ShellEvolutionEventSource *shell_evolution_event_source_new (void);
|
||||
void shell_evolution_event_source_request_range (ShellEvolutionEventSource *source,
|
||||
gint64 msec_begin,
|
||||
gint64 msec_end);
|
||||
GList *shell_evolution_event_source_get_events (ShellEvolutionEventSource *source,
|
||||
gint64 msec_begin,
|
||||
gint64 msec_end);
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __SHELL_EVOLUTION_EVENT_SOURCE_H__ */
|
@ -233,6 +233,8 @@ shell_generic_container_set_skip_paint (ShellGenericContainer *self,
|
||||
g_hash_table_remove (self->priv->skip_paint, child);
|
||||
else
|
||||
g_hash_table_insert (self->priv->skip_paint, child, child);
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -27,6 +27,9 @@
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#include <gjs/gjs-module.h>
|
||||
#include <canberra.h>
|
||||
#include <libxml/xmlmemory.h>
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/tree.h>
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
@ -882,7 +885,6 @@ shell_global_add_extension_importer (ShellGlobal *global,
|
||||
GError **error)
|
||||
{
|
||||
jsval target_object;
|
||||
JSObject *importer;
|
||||
JSContext *context = gjs_context_get_native_context (global->js_context);
|
||||
char *search_path[2] = { 0, 0 };
|
||||
|
||||
@ -917,7 +919,7 @@ shell_global_add_extension_importer (ShellGlobal *global,
|
||||
}
|
||||
|
||||
search_path[0] = (char*)directory;
|
||||
importer = gjs_define_importer (context, JSVAL_TO_OBJECT (target_object), target_property, (const char **)search_path, FALSE);
|
||||
gjs_define_importer (context, JSVAL_TO_OBJECT (target_object), target_property, (const char **)search_path, FALSE);
|
||||
JS_EndRequest (context);
|
||||
return TRUE;
|
||||
out_error:
|
||||
@ -1070,6 +1072,136 @@ shell_global_breakpoint (ShellGlobal *global)
|
||||
G_BREAKPOINT ();
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_global_parse_search_provider:
|
||||
* @global: A #ShellGlobal
|
||||
* @data: description of provider
|
||||
* @name: (out): location to store a display name
|
||||
* @url: (out): location to store template of url
|
||||
* @langs: (out) (transfer full) (element-type utf8): list of supported languages
|
||||
* @icon_data_uri: (out): location to store uri
|
||||
* @error: location to store GError
|
||||
*
|
||||
* Returns: %TRUE on success
|
||||
*/
|
||||
gboolean
|
||||
shell_global_parse_search_provider (ShellGlobal *global,
|
||||
const char *data,
|
||||
char **name,
|
||||
char **url,
|
||||
GList **langs,
|
||||
char **icon_data_uri,
|
||||
GError **error)
|
||||
{
|
||||
xmlDocPtr doc = xmlParseMemory (data, strlen(data));
|
||||
xmlNode *root;
|
||||
|
||||
*name = NULL;
|
||||
*url = NULL;
|
||||
*icon_data_uri = NULL;
|
||||
*langs = NULL;
|
||||
|
||||
if (!doc)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Malformed xml");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
root = xmlDocGetRootElement (doc);
|
||||
if (root && root->name && xmlStrcmp (root->name, (const xmlChar *)"OpenSearchDescription") == 0)
|
||||
{
|
||||
xmlNode *child;
|
||||
for (child = root->children; child; child = child->next)
|
||||
{
|
||||
if (!child->name)
|
||||
continue;
|
||||
if (xmlStrcmp (child->name, (const xmlChar *)"Language") == 0)
|
||||
{
|
||||
xmlChar *val = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
|
||||
if (!val)
|
||||
continue;
|
||||
*langs = g_list_append (*langs, g_strdup ((char *)val));
|
||||
xmlFree (val);
|
||||
}
|
||||
if (!*name && xmlStrcmp (child->name, (const xmlChar *)"ShortName") == 0)
|
||||
{
|
||||
xmlChar *val = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
|
||||
*name = g_strdup ((char *)val);
|
||||
xmlFree (val);
|
||||
}
|
||||
if (!*icon_data_uri && xmlStrcmp (child->name, (const xmlChar *)"Image") == 0)
|
||||
{
|
||||
xmlChar *val = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
|
||||
if (val)
|
||||
*icon_data_uri = g_strdup ((char *)val);
|
||||
xmlFree (val);
|
||||
}
|
||||
if (!*url && xmlStrcmp (child->name, (const xmlChar *)"Url") == 0)
|
||||
{
|
||||
xmlChar *template;
|
||||
xmlChar *type;
|
||||
|
||||
type = xmlGetProp(child, (const xmlChar *)"type");
|
||||
if (!type)
|
||||
continue;
|
||||
|
||||
if (xmlStrcmp (type, (const xmlChar *)"text/html") != 0)
|
||||
{
|
||||
xmlFree (type);
|
||||
continue;
|
||||
}
|
||||
xmlFree (type);
|
||||
|
||||
template = xmlGetProp(child, (const xmlChar *)"template");
|
||||
if (!template)
|
||||
continue;
|
||||
*url = g_strdup ((char *)template);
|
||||
xmlFree (template);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid OpenSearch document");
|
||||
xmlFreeDoc (doc);
|
||||
return FALSE;
|
||||
}
|
||||
xmlFreeDoc (doc);
|
||||
if (*icon_data_uri && *name && *url)
|
||||
return TRUE;
|
||||
|
||||
if (*icon_data_uri)
|
||||
g_free (*icon_data_uri);
|
||||
else
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"search provider doesn't have icon");
|
||||
|
||||
if (*name)
|
||||
g_free (*name);
|
||||
else if (error && !*error)
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"search provider doesn't have ShortName");
|
||||
|
||||
if (*url)
|
||||
g_free (*url);
|
||||
else if (error && !*error)
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"search provider doesn't have template for url");
|
||||
|
||||
if (*langs)
|
||||
{
|
||||
g_list_foreach (*langs, (GFunc)g_free, NULL);
|
||||
g_list_free (*langs);
|
||||
}
|
||||
|
||||
*url = NULL;
|
||||
*name = NULL;
|
||||
*icon_data_uri = NULL;
|
||||
*langs = NULL;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_global_gc:
|
||||
* @global: A #ShellGlobal
|
||||
|
@ -84,6 +84,14 @@ void shell_global_reexec_self (ShellGlobal *global);
|
||||
|
||||
void shell_global_breakpoint (ShellGlobal *global);
|
||||
|
||||
gboolean shell_global_parse_search_provider (ShellGlobal *global,
|
||||
const char *data,
|
||||
char **name,
|
||||
char **url,
|
||||
GList **langs,
|
||||
char **icon_data_uri,
|
||||
GError **error);
|
||||
|
||||
void shell_global_gc (ShellGlobal *global);
|
||||
|
||||
void shell_global_maybe_gc (ShellGlobal *global);
|
||||
|
@ -1,129 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "shell-process.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
struct _ShellProcessPrivate {
|
||||
char **args;
|
||||
GPid pid;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_ARGS,
|
||||
};
|
||||
|
||||
static void shell_process_dispose (GObject *object);
|
||||
static void shell_process_finalize (GObject *object);
|
||||
static void shell_process_set_property ( GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec );
|
||||
static void shell_process_get_property( GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec );
|
||||
|
||||
G_DEFINE_TYPE( ShellProcess, shell_process, G_TYPE_OBJECT);
|
||||
|
||||
static void shell_process_class_init( ShellProcessClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *)klass;
|
||||
|
||||
gobject_class->dispose = shell_process_dispose;
|
||||
gobject_class->finalize = shell_process_finalize;
|
||||
gobject_class->set_property = shell_process_set_property;
|
||||
gobject_class->get_property = shell_process_get_property;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_ARGS,
|
||||
g_param_spec_boxed ("args",
|
||||
"Arguments",
|
||||
"",
|
||||
G_TYPE_STRV,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
}
|
||||
|
||||
static void shell_process_init (ShellProcess *self)
|
||||
{
|
||||
self->priv = g_new0 (ShellProcessPrivate, 1);
|
||||
}
|
||||
|
||||
static void shell_process_dispose (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (shell_process_parent_class)->dispose(object);
|
||||
}
|
||||
|
||||
static void shell_process_finalize (GObject *object)
|
||||
{
|
||||
ShellProcess *self = (ShellProcess*)object;
|
||||
|
||||
g_free (self->priv);
|
||||
g_signal_handlers_destroy(object);
|
||||
G_OBJECT_CLASS (shell_process_parent_class)->finalize(object);
|
||||
}
|
||||
static void shell_process_set_property ( GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec )
|
||||
{
|
||||
ShellProcess* self = SHELL_PROCESS(object);
|
||||
switch (property_id) {
|
||||
case PROP_ARGS:
|
||||
self->priv->args = (char**) g_value_dup_boxed (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void shell_process_get_property ( GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec )
|
||||
{
|
||||
ShellProcess* self = SHELL_PROCESS(object);
|
||||
switch (property_id) {
|
||||
case PROP_ARGS:
|
||||
g_value_set_boxed (value, self->priv->args);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ShellProcess* shell_process_new(char **args)
|
||||
{
|
||||
return (ShellProcess*) g_object_new(SHELL_TYPE_PROCESS,
|
||||
"args", args,
|
||||
NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
shell_process_run (ShellProcess *self,
|
||||
GError **error)
|
||||
{
|
||||
return g_spawn_async (NULL, self->priv->args, NULL,
|
||||
G_SPAWN_SEARCH_PATH, NULL, NULL,
|
||||
&self->priv->pid,
|
||||
error);
|
||||
}
|
||||
/*
|
||||
int
|
||||
shell_process_wait (ShellProcess *self)
|
||||
{
|
||||
int status;
|
||||
|
||||
waitpid ((pid_t) self->priv->pid, &status, 0);
|
||||
|
||||
return status;
|
||||
}
|
||||
*/
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user