Compare commits

...

25 Commits

Author SHA1 Message Date
33100cd204 Bump version to 2.91.6 2011-02-01 14:08:29 -05:00
39a8243f27 [l10n] Updated Estonian translation 2011-02-01 19:35:37 +02:00
5f50922d32 Build: Correct version numbers for eds-3.0/1.2
The respective version numbers got swapped in commit 703092f.
2011-02-01 16:37:17 +01:00
1137ca0fce main.js: fix variable naming style for css_stylesheet
Change css_stylesheet to cssStylesheet in various places.
2011-02-01 10:13:35 -05:00
36f3429ad2 Better API for extensions changing CSS
Rename the setter to reflect the fact that it's the stylesheet which is
changing

Add a getter to allow some useful checks
2011-02-01 10:13:35 -05:00
703092f2c9 build: Default to libedataserverui-3.0 instead of 1.2
The official GNOME moduleset builds evolution and e-d-s against
GTK+-3, so libedataserverui-1.2 is no longer part of the release.
As GNOME Shell can actually be build with either version, prefer
libedataserverui-3.0 if it is available and allow falling back
to 1.2. if it isn't.

https://bugzilla.gnome.org/show_bug.cgi?id=641085
2011-02-01 16:12:11 +01:00
fd75c7c7b4 Add an alternate bubble arrow drawing
When the bubble is near the screen border, draw a half arrow at the
corner of the bubble.

https://bugzilla.gnome.org/show_bug.cgi?id=639979
2011-02-01 10:07:05 -05:00
8abbd5dacb tray: Fix handling of SYSTEM_TRAY_CANCEL_MESSAGE
We were not looking at the right field for the message ID: the ID is in
the 4th field for BEGIN_MESSAGE, but 2nd field for CANCEL_MESSAGE.
2011-02-01 12:13:47 +01:00
ed0fa7e1b7 tray: Stop using gdk_display_add_client_message_filter()
It just got removed in GTK+ 3, and we actually don't need it since we
look for ClientMessage in na_tray_manager_window_filter() anyway.
2011-02-01 12:13:12 +01:00
15f1245927 Updating Galician translations 2011-02-01 02:45:13 +01:00
25434e42d0 calendar: Fix grid non-US week layouts
http://people.freedesktop.org/~david/calendar-grid-non-US-locale-collapse-bug.png

This was discovered when working on bug 641049:

 https://bugzilla.gnome.org/show_bug.cgi?id=641049

Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-01-31 15:53:56 -05:00
d6749589e8 calendar: Fix event list for week starts other than Sunday
In non-US locales, Monday is generally considered the first day
of the week. Take this into account when building the event
lists displayed under "This week"/"Next week".

https://bugzilla.gnome.org/show_bug.cgi?id=641049

Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-01-31 15:47:05 -05:00
8fea88879a calendar: Fix prev/next buttons to not skip months
When the current day does not exist in the next/prev month (like 31 Feb),
the next/prev buttons end up skipping the month.

Fix that by going to the last day of the month instead.

https://bugzilla.gnome.org/show_bug.cgi?id=641067
2011-01-31 21:31:17 +01:00
d9e778f501 Calendar: Fix UTC/local mixup
See https://bugzilla.gnome.org/show_bug.cgi?id=632109#c56

Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-01-31 11:52:27 -05:00
885b6ffaef Calendar: Implement new mockup
https://bugzilla.gnome.org/show_bug.cgi?id=632109

Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-01-31 11:52:27 -05:00
4c64920f45 build: Remove gtk-theme-engine-clearlooks
The default engine is now Adwaita in gnome-themes-standard, so
remove it from the moduleset. It has already been removed from the
gnome-suites-core-3.0 set.
2011-01-31 16:08:59 +01:00
7369ea6125 Make sure we only emit 'destroy' for a notification once
There are multiple code passes that can result in Notification::destroy()
being called, such as a notification being closed by the application
when it exits and the associated source being removed at the same time.
However, we should only emit 'destroy' for the notification and
do the associated work once.
2011-01-30 18:53:19 -05:00
20b7d34577 Avoid passing 'source' as an argument to Notification::destroy()
Notification::destroy() now takes 'reason' as an optional argument.
Calling Notification::destroy() directly when connecting to 'destroy'
on Source, as we did before, was inadvertently passing 'source' as an
argument to the function.

https://bugzilla.gnome.org/show_bug.cgi?id=640976
2011-01-30 18:53:07 -05:00
6cc4c33b13 Updated Hebrew translation. 2011-01-30 23:04:00 +02:00
5abf9a0425 Add an API to allow extension to set a theme
Add a setTheme function to Main that allows to set a CSS stylesheet
which overrides the GNOME Shell default one

https://bugzilla.gnome.org/show_bug.cgi?id=630428
2011-01-30 16:01:15 -05:00
17a0b27109 appSwitcher: Use shorter icon hover timeout
Using a timeout of 750ms seems to be too long,
a shorter one like 200ms still solves the original problem
without getting in the way of other uses.
2011-01-30 20:29:27 +01:00
2bcdae4d5d Include new GTK+ header for X11 extensions
Due to recent GTK+ changes X11 specific code was moved into different
headers. As Socket/Plug is X11 only this broke our calls to GtkSocket
in the tray code. Fix this by including the new gtkx.h header.
2011-01-30 13:53:03 -05:00
0244c6d5b8 Revert "KeyboardStatus: handle modifier key indicators"
The 'show-keyboard-leds-indicator' key has been removed from
the schema.

This reverts commit 20f49e8c89.
2011-01-29 19:34:12 +01:00
bc6be40fdd Updated Italian translation 2011-01-29 16:07:10 +01:00
8c22b58611 update Punjabi Translation by A S Alam 2011-01-29 07:42:22 +05:30
34 changed files with 5073 additions and 661 deletions

View File

@ -1,5 +1,5 @@
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])
@ -66,6 +66,11 @@ 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
@ -113,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`

View File

@ -25,6 +25,8 @@ 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 \

View 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

View 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

View File

@ -674,6 +674,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);
@ -686,37 +697,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 {
@ -895,10 +1024,6 @@ StTooltip StLabel {
padding-left: 4px;
}
.calendar-calendarweek {
color: #666666;
}
/* App Switcher */
#altTabPopup {
padding: 8px;

View File

@ -19,6 +19,7 @@ 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 \

View File

@ -15,7 +15,7 @@ const POPUP_APPICON_SIZE = 96;
const POPUP_SCROLL_TIME = 0.10; // seconds
const POPUP_FADE_TIME = 0.1; // seconds
const APP_ICON_HOVER_TIMEOUT = 750; // milliseconds
const APP_ICON_HOVER_TIMEOUT = 200; // milliseconds
const DISABLE_HOVER_TIMEOUT = 500; // milliseconds

View File

@ -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,59 @@ 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 = 10;
} else if (sourceCenterX > (primary.width - margin)) {
// Not enough space to the botom
this._arrowCorner = (this._arrowSide == St.Side.TOP) ? St.Corner.TOPRIGHT : St.Corner.BOTTOMRIGHT;
resX = primary.width - (10 + natWidth);
}
resX = Math.min(resX, primary.x + primary.width - natWidth - arrowRise - gap);
resX = Math.max(resX, primary.x);
resX = Math.max(resX, 10);
resX = Math.min(resX, primary.width - (10 + natWidth));
this.setArrowOrigin((sourceX - resX) + Math.floor(sourceWidth / 2));
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.height - margin)) {
// Not enough space to the right
this._arrowCorner = (this._arrowSide == St.Side.LEFT) ? St.Corner.BOTTOMLEFT : St.Corner.BOTTOMRIGHT;
resY = 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, 10);
resY = Math.min(resY, primary.height - (10 + natHeight));
this.setArrowOrigin((sourceY - resY) + Math.floor(sourceHeight / 2));
this.setArrowOrigin(sourceCenterY - resY);
break;
}

View File

@ -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] = ['&lt;', '&gt;'];
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);
}
}
};

212
js/ui/dateMenu.js Normal file
View 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');
},
};

View File

@ -67,6 +67,8 @@ let xdndHandler = null;
let statusIconDispatcher = null;
let _errorLogStack = [];
let _startDate;
let _defaultCssStylesheet = null;
let _cssStylesheet = null;
let background = null;
@ -111,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;
@ -204,15 +207,44 @@ function start() {
}
}
/**
* 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);
}
@ -265,10 +297,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,

View File

@ -254,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;
@ -274,7 +275,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 });
@ -767,6 +772,9 @@ Notification.prototype = {
},
destroy: function(reason) {
if (this._destroyed)
return;
this._destroyed = true;
if (!reason)
reason = NotificationDestroyedReason.DISMISSED;
this.emit('destroy', reason);

View File

@ -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;
@ -43,10 +44,6 @@ const STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION = {
if (Config.HAVE_BLUETOOTH)
STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION['bluetooth'] = imports.ui.status.bluetooth.Indicator;
const STANDARD_TRAY_INDICATOR_FACTORIES = [
imports.ui.status.keyboard.ModifierIndicatorFactory
];
// in org.gnome.desktop.interface
const CLOCK_FORMAT_KEY = 'clock-format';
@ -496,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();
}
@ -807,22 +689,19 @@ 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 */
// On-off indicators (for keyboard leds and accessx) are in indicatorBox
// System status applets live in statusBox, and legacy tray icons
// System status applets live in statusBox, while legacy tray icons
// live in trayBox
// The trayBox is hidden when there are no tray icons.
this._indicatorBox = new St.BoxLayout({ name: 'indicatorBox' });
this._trayBox = new St.BoxLayout({ name: 'legacyTray' });
this._statusBox = new St.BoxLayout({ name: 'statusTray' });
this._trayBox.hide();
this._rightBox.add(this._indicatorBox);
this._rightBox.add(this._trayBox);
this._rightBox.add(this._statusBox);
@ -874,13 +753,6 @@ Panel.prototype = {
},
startStatusArea: function() {
for (let i = 0; i < STANDARD_TRAY_INDICATOR_FACTORIES.length; i++) {
let factory = new STANDARD_TRAY_INDICATOR_FACTORIES[i];
let indicators = factory.getIndicators();
for (let j = 0; j < indicators.length; j++)
this._indicatorBox.add(indicators[j]);
}
for (let i = 0; i < STANDARD_TRAY_ICON_ORDER.length; i++) {
let role = STANDARD_TRAY_ICON_ORDER[i];
let constructor = STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION[role];
@ -898,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,

View File

@ -204,52 +204,3 @@ XKBIndicator.prototype = {
this._labelActors[i].allocate_align_fill(box, 0.5, 0, false, false, flags);
}
};
function ModifierIndicatorFactory() {
this._init.call(this);
}
ModifierIndicatorFactory.prototype = {
_init: function() {
this._settings = new Gio.Settings({ schema: INDICATOR_SCHEMA });
this._settings.connect('changed::show-keyboard-leds-indicator', Lang.bind(this, this._changed));
this._config = Gkbd.Configuration.get();
this._config.connect('indicators-changed', Lang.bind(this, this._changed));
this._scrollLock = new St.Icon({ icon_name: 'kbdled-scroll-lock', icon_type: St.IconType.SYMBOLIC, style_class: 'system-status-icon' });
this._numLock = new St.Icon({ icon_name: 'kbdled-num-lock', icon_type: St.IconType.SYMBOLIC, style_class: 'system-status-icon' });
this._capsLock = new St.Icon({ icon_name: 'kbdled-caps-lock', icon_type: St.IconType.SYMBOLIC, style_class: 'system-status-icon' });
this._changed();
},
getIndicators: function() {
return [this._scrollLock, this._numLock, this._capsLock];
},
_changed: function() {
let enable = this._settings.get_boolean('show-keyboard-leds-indicator');
if (enable) {
if (this._config.get_scroll_lock_state())
this._scrollLock.show();
else
this._scrollLock.hide();
if (this._config.get_num_lock_state())
this._numLock.show();
else
this._numLock.hide();
if (this._config.get_caps_lock_state())
this._capsLock.show();
else
this._capsLock.hide();
} else {
this._scrollLock.hide();
this._numLock.hide();
this._capsLock.hide();
}
}
};

View File

@ -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-21 18:46+0000\n"
"PO-Revision-Date: 2011-01-24 08:04+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"
@ -242,6 +242,9 @@ 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:"
@ -309,17 +312,17 @@ msgid "Logging out of the system."
msgstr "Süsteemist väljalogimine"
msgid "Shut Down"
msgstr "Seiska"
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 "Süsteem seisatakse automaatselt %d sekundi pärast."
msgstr "%d sekundi pärast lülitub süsteem automaatselt välja."
msgid "Shutting down the system."
msgstr "Süsteemi seiskamine."
msgstr "Süsteemi väljalülitamine."
msgid "Restart"
msgstr "Taaskäivita"

170
po/gl.po
View File

@ -10,8 +10,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-01-27 03:33+0100\n"
"PO-Revision-Date: 2011-01-26 21:02+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,8 +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
#, fuzzy
#: ../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,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."
@ -121,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 "
@ -131,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."
@ -139,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 "
@ -155,15 +159,15 @@ 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:22
#: ../data/org.gnome.shell.gschema.xml.in.h:23
msgid "disabled OpenSearch providers"
msgstr "fornecedores de OpenSearch desactivados"
@ -321,43 +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:108
#: ../js/misc/util.js:113
msgid "Could not parse command:"
msgstr "Non foi posíbel analizar a orde:"
#: ../js/misc/util.js:130
#: ../js/misc/util.js:135
msgid "No such application"
msgstr "Non existe o aplicativo"
#: ../js/misc/util.js:143 ../js/ui/runDialog.js:351
#: ../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"
@ -482,71 +490,31 @@ msgstr "Ver fonte"
msgid "Web Page"
msgstr "Páxina web"
#: ../js/ui/messageTray.js:1765
#: ../js/ui/messageTray.js:1786
msgid "System Information"
msgstr "Información do sistema"
#: ../js/ui/overview.js:75
#: ../js/ui/overview.js:88
msgid "Undo"
msgstr "Desfacer"
#: ../js/ui/overview.js:140
#: ../js/ui/overview.js:159
msgid "Windows"
msgstr "Xanelas"
#: ../js/ui/overview.js:143
#: ../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:479
#: ../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:564
msgid "%a %b %e, %R:%S"
msgstr "%a %e de %b, %R:%S"
#: ../js/ui/panel.js:565
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:569
msgid "%a %R:%S"
msgstr "%a %R:%S"
#: ../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:577
msgid "%a %b %e, %l:%M:%S %p"
msgstr "%a %e de %b, %H:%M:%S"
#: ../js/ui/panel.js:578
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:582
msgid "%a %l:%M:%S %p"
msgstr "%a %H:%M:%S"
#: ../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:728
#: ../js/ui/panel.js:614
msgid "Activities"
msgstr "Actividades"
@ -701,7 +669,7 @@ msgstr "Produciuse un erro ao explorar o dispositivo"
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:251 ../js/ui/status/keyboard.js:78
#: ../js/ui/status/bluetooth.js:251
msgid "Keyboard Settings"
msgstr "Configuracións do teclado"
@ -776,6 +744,10 @@ msgstr "Introduza o PIN mencionado no dispositivo."
msgid "OK"
msgstr "Aceptar"
#: ../js/ui/status/keyboard.js:78
msgid "Localization Settings"
msgstr "Configuracións do son"
#: ../js/ui/status/power.js:85
msgid "Power Settings"
msgstr "Configuracións de enerxía"
@ -910,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."
@ -943,32 +915,32 @@ msgstr[1] "%u entradas"
msgid "System Sounds"
msgstr "Sons do sistema"
#: ../src/shell-global.c:1366
#: ../src/shell-global.c:1365
msgid "Less than a minute ago"
msgstr "Hai menos dun minuto"
#: ../src/shell-global.c:1370
#: ../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:1375
#: ../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:1380
#: ../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:1385
#: ../src/shell-global.c:1384
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
@ -999,9 +971,29 @@ msgstr "Buscar"
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~| msgid "Sound Settings"
#~ msgid "Localization Settings"
#~ msgstr "Configuracións do son"
#~ 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"

View File

@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-01-23 02:42+0200\n"
"PO-Revision-Date: 2011-01-23 02:43+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"
@ -319,43 +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:108
#: ../js/misc/util.js:113
msgid "Could not parse command:"
msgstr "לא ניתן לפענח את הפקודה:"
#: ../js/misc/util.js:130
#: ../js/misc/util.js:135
msgid "No such application"
msgstr "אין כזה יישום"
#: ../js/misc/util.js:143 ../js/ui/runDialog.js:351
#: ../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 "הוספה למועדפים"
@ -476,71 +480,71 @@ msgstr "צפייה במקור"
msgid "Web Page"
msgstr "דף אינטרנט"
#: ../js/ui/messageTray.js:1765
#: ../js/ui/messageTray.js:1778
msgid "System Information"
msgstr "פרטי המערכת"
#: ../js/ui/overview.js:75
#: ../js/ui/overview.js:88
msgid "Undo"
msgstr "ביטול"
#: ../js/ui/overview.js:140
#: ../js/ui/overview.js:159
msgid "Windows"
msgstr "חלונות"
#: ../js/ui/overview.js:143
#: ../js/ui/overview.js:162
msgid "Applications"
msgstr "יישומים"
#. TODO - _quit() doesn't really work on apps in state STARTING yet
#: ../js/ui/panel.js:483
#: ../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:568
#: ../js/ui/panel.js:564
msgid "%a %b %e, %R:%S"
msgstr "%a %b %e, %R:%S"
#: ../js/ui/panel.js:569
#: ../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:573
#: ../js/ui/panel.js:569
msgid "%a %R:%S"
msgstr "%a %R:%S"
#: ../js/ui/panel.js:574
#: ../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:581
#: ../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:582
#: ../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:586
#: ../js/ui/panel.js:582
msgid "%a %l:%M:%S %p"
msgstr "%a %l:%M:%S %p"
#: ../js/ui/panel.js:587
#: ../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:732
#: ../js/ui/panel.js:728
msgid "Activities"
msgstr "פעילויות"
@ -912,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 "לא ניתן להסיר את מרחב העבודה הראשון."
@ -945,11 +949,11 @@ msgstr[2] "2 קלטים"
msgid "System Sounds"
msgstr "צלילי מערכת"
#: ../src/shell-global.c:1366
#: ../src/shell-global.c:1365
msgid "Less than a minute ago"
msgstr "לפני פחות מדקה"
#: ../src/shell-global.c:1370
#: ../src/shell-global.c:1369
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
@ -957,7 +961,7 @@ msgstr[0] "לפני דקה"
msgstr[1] "לפני %d דקות"
msgstr[2] "לפני 2 דקות"
#: ../src/shell-global.c:1375
#: ../src/shell-global.c:1374
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
@ -965,7 +969,7 @@ msgstr[0] "לפני שעה"
msgstr[1] "לפני %d שעות"
msgstr[2] "לפני שעתיים"
#: ../src/shell-global.c:1380
#: ../src/shell-global.c:1379
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
@ -973,7 +977,7 @@ msgstr[0] "לפני יום"
msgstr[1] "לפני %d ימים"
msgstr[2] "לפני יומיים"
#: ../src/shell-global.c:1385
#: ../src/shell-global.c:1384
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"

105
po/it.po
View File

@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-01-21 01:16+0100\n"
"PO-Revision-Date: 2011-01-15 01:19+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"
@ -76,7 +76,8 @@ msgstr "Se VERO, mostra il giorno della settimana ISO nel calendario."
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:11
#: ../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 "
@ -85,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 "
@ -97,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:12
#: ../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:13
#: ../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:14
#: ../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:15
#: ../data/org.gnome.shell.gschema.xml.in.h:16
msgid ""
"The applications corresponding to these identifiers will be displayed in the "
"favorites area."
@ -117,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: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 "
@ -127,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: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."
@ -135,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:18
#: ../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: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 "
@ -152,16 +155,16 @@ msgstr ""
"disabilitare questa funzionalità per motivi di privacy. I dati già salvati "
"non verranno comunque rimossi."
#: ../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 delle estensioni da disabilitare"
#: ../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 raccogliere statistiche riguardo l'utilizzo delle applicazioni"
#: ../data/org.gnome.shell.gschema.xml.in.h:22
#: ../data/org.gnome.shell.gschema.xml.in.h:23
msgid "disabled OpenSearch providers"
msgstr ""
@ -290,43 +293,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 ""
#. Replace "Error invoking GLib.shell_parse_argv: " with
#. something nicer
#: ../js/misc/util.js:108
#: ../js/misc/util.js:113
msgid "Could not parse command:"
msgstr "Impossibile analizzare il comando:"
#: ../js/misc/util.js:130
#: ../js/misc/util.js:135
msgid "No such application"
msgstr "Applicazione inesistente"
#: ../js/misc/util.js:143 ../js/ui/runDialog.js:351
#: ../js/misc/util.js:148
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Esecuzione di «%s» non riuscita:"
#. Translators: Filter to display all applications
#: ../js/ui/appDisplay.js:155
#: ../js/ui/appDisplay.js:164
msgid "All"
msgstr "Tutte"
#: ../js/ui/appDisplay.js:236
#: ../js/ui/appDisplay.js:245
msgid "APPLICATIONS"
msgstr "APPLICAZIONI"
#: ../js/ui/appDisplay.js:266
#: ../js/ui/appDisplay.js:275
msgid "PREFERENCES"
msgstr "PREFERENZE"
#: ../js/ui/appDisplay.js:563
#: ../js/ui/appDisplay.js:572
msgid "New Window"
msgstr "Nuova finestra"
#: ../js/ui/appDisplay.js:567
#: ../js/ui/appDisplay.js:576
msgid "Remove from Favorites"
msgstr "Rimuovi dai preferiti"
#: ../js/ui/appDisplay.js:568
#: ../js/ui/appDisplay.js:577
msgid "Add to Favorites"
msgstr "Aggiungi ai preferiti"
@ -459,72 +466,72 @@ msgstr "Visualizza sorgente"
msgid "Web Page"
msgstr "Pagina web"
#: ../js/ui/messageTray.js:1765
#: ../js/ui/messageTray.js:1778
msgid "System Information"
msgstr "Informazione di sistema"
#: ../js/ui/overview.js:75
#: ../js/ui/overview.js:88
msgid "Undo"
msgstr "Annulla"
#: ../js/ui/overview.js:140
#: ../js/ui/overview.js:159
msgid "Windows"
msgstr "Finestre"
#: ../js/ui/overview.js:143
#: ../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:479
#: ../js/ui/panel.js:483
#, c-format
msgid "Quit %s"
msgstr "Chiudi %s"
#. Translators: This is the time format with date used
#. in 24-hour mode.
#: ../js/ui/panel.js:564
#: ../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:565
#: ../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:569
#: ../js/ui/panel.js:573
msgid "%a %R:%S"
msgstr "%a %k.%M.%S"
#: ../js/ui/panel.js:570
#: ../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:577
#: ../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:578
#: ../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:582
#: ../js/ui/panel.js:586
msgid "%a %l:%M:%S %p"
msgstr "%a %l.%M.%S %P"
#: ../js/ui/panel.js:583
#: ../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:728
#: ../js/ui/panel.js:732
msgid "Activities"
msgstr "Attività"
@ -553,7 +560,7 @@ 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:209
msgid "Please enter a command:"
@ -683,7 +690,7 @@ msgstr "Errore nell'esplorare il dispositivo"
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:251 ../js/ui/status/keyboard.js:78
#: ../js/ui/status/bluetooth.js:251
msgid "Keyboard Settings"
msgstr "Impostazioni tastiera"
@ -758,6 +765,10 @@ msgstr "Inserire il PIN indicato sul dispositivo."
msgid "OK"
msgstr "OK"
#: ../js/ui/status/keyboard.js:78
msgid "Localization Settings"
msgstr "Impostazioni localizzazione"
#: ../js/ui/status/power.js:85
msgid "Power Settings"
msgstr "Impostazioni alimentazione"
@ -896,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."
@ -929,32 +940,32 @@ msgstr[1] "%u ingressi"
msgid "System Sounds"
msgstr "Audio di sistema"
#: ../src/shell-global.c:1366
#: ../src/shell-global.c:1365
msgid "Less than a minute ago"
msgstr "Meno di un minuto fa"
#: ../src/shell-global.c:1370
#: ../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:1375
#: ../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:1380
#: ../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:1385
#: ../src/shell-global.c:1384
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"

173
po/pa.po
View File

@ -7,8 +7,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-15 00:23+0000\n"
"PO-Revision-Date: 2011-01-16 11:07+0530\n"
"POT-Creation-Date: 2011-01-27 20:47+0000\n"
"PO-Revision-Date: 2011-01-29 07:39+0530\n"
"Last-Translator: A S Alam <aalam@users.sf.net>\n"
"Language-Team: Punjabi/Panjabi <punjabi-users@lists.sf.net>\n"
"MIME-Version: 1.0\n"
@ -74,7 +74,8 @@ msgstr "ਜੇ ਚੋਣ ਕੀਤੀ ਤਾਂ ਕੈਲੰਡਰ ਵਿੱਚ
msgid "List of desktop file IDs for favorite applications"
msgstr "ਪਸੰਦੀਦਾ ਐਪਲੀਕੇਸ਼ਨ ਲਈ ਡੈਸਕਟਾਪ ਫਾਇਲ ID ਦੀ ਲਿਸਟ ਹੈ"
#: ../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 "
@ -83,29 +84,31 @@ 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 "ਘੜੀ ਵਿੱਚ ਮਿਤੀ ਵੇਖੋ"
#: ../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 "ਕੈਲੰਡਰ ਵਿੱਚ ਹਫ਼ਤਾ ਮਿਤੀ ਵੇਖੋ"
#: ../data/org.gnome.shell.gschema.xml.in.h:14
#: ../data/org.gnome.shell.gschema.xml.in.h:15
msgid "Show time with seconds"
msgstr "ਸਮਾਂ ਵਿੱਚ ਸਕਿੰਟ ਵੇਖੋ"
#: ../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 "
@ -117,7 +120,7 @@ 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."
@ -126,11 +129,11 @@ 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 "
@ -145,14 +148,18 @@ 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 "ਇਕਟੈਨਸ਼ਨ ਦੀ Uuids ਬੰਦ ਹੈ"
#: ../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 "ਐਪਲੀਕੇਸ਼ਨ ਵਰਤੋਂ ਬਾਰੇ ਅੰਕੜੇ ਇੱਕਠੇ ਕਰਨੇ ਹਨ"
#: ../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 "ਸੈਂਟਰ ਉੱਤੇ ਕਰਾਂਸਹੇਅਰ ਕਲਿੱਪ ਕਰੋ"
@ -290,45 +297,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 "ਕਮਾਂਡ ਨਹੀਂ ਲੱਭੀ"
#. Replace "Error invoking GLib.shell_parse_argv: " with
#. something nicer
#: ../js/misc/util.js:108
#| msgid "Please enter a command:"
#: ../js/misc/util.js:113
msgid "Could not parse command:"
msgstr "ਕਮਾਂਡ ਪਾਰਸ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ:"
#: ../js/misc/util.js:130
#| msgid "Applications"
#: ../js/misc/util.js:135
msgid "No such application"
msgstr "ਇੰਞ ਦੀ ਕੋਈ ਐਪਲੀਕੇਸ਼ਨ ਨਹੀਂ ਹੈ"
#: ../js/misc/util.js:143 ../js/ui/runDialog.js:364
#: ../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 "ਪਸੰਦ 'ਚ ਸ਼ਾਮਲ ਕਰੋ"
@ -352,12 +361,10 @@ msgstr "ਤਾਜ਼ਾ ਆਈਟਮਾਂ"
#: ../js/ui/endSessionDialog.js:63
#, c-format
#| msgid "Log Out..."
msgid "Log Out %s"
msgstr "%s ਲਾਗਆਉਟ"
#: ../js/ui/endSessionDialog.js:64 ../js/ui/endSessionDialog.js:69
#| msgid "Log Out..."
msgid "Log Out"
msgstr "ਲਾਗਆਉਟ"
@ -381,7 +388,6 @@ msgid "Logging out of the system."
msgstr "ਸਿਸਟਮ ਲਾਗ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ।"
#: ../js/ui/endSessionDialog.js:74 ../js/ui/endSessionDialog.js:78
#| msgid "Shut Down..."
msgid "Shut Down"
msgstr "ਬੰਦ ਕਰੋ"
@ -399,7 +405,6 @@ msgid "Shutting down the system."
msgstr "ਸਿਸਟਮ ਬੰਦ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ।"
#: ../js/ui/endSessionDialog.js:84 ../js/ui/endSessionDialog.js:88
#| msgid "Restart..."
msgid "Restart"
msgstr "ਮੁੜ-ਚਾਲੂ ਕਰੋ"
@ -421,7 +426,7 @@ msgstr "ਸਿਸਟਮ ਮੁੜ-ਚਾਲੂ ਕੀਤਾ ਜਾ ਰਿਹਾ
msgid "Confirm"
msgstr "ਪੁਸ਼ਟੀ"
#: ../js/ui/endSessionDialog.js:400 ../js/ui/status/bluetooth.js:469
#: ../js/ui/endSessionDialog.js:400 ../js/ui/status/bluetooth.js:470
msgid "Cancel"
msgstr "ਰੱਦ ਕਰੋ"
@ -455,89 +460,88 @@ msgstr "ਸਰੋਤ ਵੇਖੋ"
msgid "Web Page"
msgstr "ਵੈੱਬ ਪੇਜ਼"
#: ../js/ui/messageTray.js:1748
#| msgid "Account Information..."
#: ../js/ui/messageTray.js:1765
msgid "System Information"
msgstr "ਸਿਸਟਮ ਜਾਣਕਾਰੀ"
#: ../js/ui/overview.js:75
#: ../js/ui/overview.js:88
msgid "Undo"
msgstr "ਵਾਪਸ"
#: ../js/ui/overview.js:140
#: ../js/ui/overview.js:159
msgid "Windows"
msgstr "ਵਿੰਡੋ"
#: ../js/ui/overview.js:143
#: ../js/ui/overview.js:162
msgid "Applications"
msgstr "ਐਪਲੀਕੇਸ਼ਨ"
#. TODO - _quit() doesn't really work on apps in state STARTING yet
#: ../js/ui/panel.js:479
#: ../js/ui/panel.js:483
#, c-format
msgid "Quit %s"
msgstr "%s ਬੰਦ ਕਰੋ"
#. Translators: This is the time format with date used
#. in 24-hour mode.
#: ../js/ui/panel.js:564
#: ../js/ui/panel.js:568
msgid "%a %b %e, %R:%S"
msgstr "%a, %e %b %R:%S"
#: ../js/ui/panel.js:565
#: ../js/ui/panel.js:569
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:569
#: ../js/ui/panel.js:573
msgid "%a %R:%S"
msgstr "%a %R:%S"
#: ../js/ui/panel.js:570
#: ../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:577
#: ../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:578
#: ../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:582
#: ../js/ui/panel.js:586
msgid "%a %l:%M:%S %p"
msgstr "%a %l:%M:%S %p"
#: ../js/ui/panel.js:583
#: ../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:728
#: ../js/ui/panel.js:732
msgid "Activities"
msgstr "ਸਰਗਰਮੀਆਂ"
#: ../js/ui/placeDisplay.js:112
#: ../js/ui/placeDisplay.js:106
#, c-format
msgid "Failed to unmount '%s'"
msgstr "'%s' ਅਣ-ਮਾਊਂਟ ਕਰਨ ਲਈ ਫੇਲ੍ਹ"
#: ../js/ui/placeDisplay.js:115
#: ../js/ui/placeDisplay.js:109
msgid "Retry"
msgstr "ਮੁੜ-ਕੋਸ਼ਿਸ਼"
#: ../js/ui/placeDisplay.js:160
#: ../js/ui/placeDisplay.js:150
msgid "Connect to..."
msgstr "...ਨਾਲ ਕੁਨੈਕਟ ਕਰੋ"
#: ../js/ui/placeDisplay.js:559
#: ../js/ui/placeDisplay.js:386
msgid "PLACES & DEVICES"
msgstr "ਥਾਵਾਂ ਤੇ ਜੰਤਰ"
@ -550,7 +554,7 @@ msgstr "ਥਾਵਾਂ ਤੇ ਜੰਤਰ"
msgid "toggle-switch-us"
msgstr "toggle-switch-us"
#: ../js/ui/runDialog.js:222
#: ../js/ui/runDialog.js:209
msgid "Please enter a command:"
msgstr "ਕਮਾਂਡ ਦਿਓ ਜੀ:"
@ -634,7 +638,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 "ਬਲਿਊਟੁੱਥ"
@ -650,106 +654,111 @@ msgstr "...ਜੰਤਰ ਨੂੰ ਫਾਇਲਾਂ ਭੇਜੋ"
msgid "Setup a New Device..."
msgstr "...ਨਵਾਂ ਜੰਤਰ ਸੈਟਅੱਪ"
#: ../js/ui/status/bluetooth.js:94
#: ../js/ui/status/bluetooth.js:95
msgid "Bluetooth Settings"
msgstr "ਬਲਿਊਟੁੱਥ ਸੈਟਿੰਗ"
#: ../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/keyboard.js:78
#: ../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:63
#: ../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 "ਬਲਿਊਟੁੱਥ ਏਜੰਟ"
#: ../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 "ਪੁਸ਼ਟੀ ਕਰੋ ਜੀ ਕਿ ਪਿੰਨ '%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 "ਜੰਤਰ ਉੱਤੇ ਦਿੱਤਾ ਗਿਆ ਪਿੰਨ ਦਿਉ ਜੀ।"
#: ../js/ui/status/bluetooth.js:468
#: ../js/ui/status/bluetooth.js:469
msgid "OK"
msgstr "ਠੀਕ ਹੈ"
#: ../js/ui/status/keyboard.js:78
#| msgid "Sound Settings"
msgid "Localization Settings"
msgstr "ਲੋਕਲਾਈਜ਼ੇਸ਼ਨ ਸੈਟਿੰਗ"
#: ../js/ui/status/power.js:85
msgid "Power Settings"
msgstr "ਪਾਵਰ ਸੈਟਿੰਗ"
@ -884,14 +893,14 @@ 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 "ਪਹਿਲਾਂ ਵਰਕਸਪੇਸ ਨਹੀਂ ਹਟਾਇਆ ਜਾ ਸਕਦਾ।"
@ -917,32 +926,32 @@ msgstr[1] "%u ਇੰਪੁੱਟ"
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"
msgstr[0] "%d ਮਿੰਟ ਪਹਿਲਾਂ"
msgstr[1] "%d ਮਿੰਟ ਪਹਿਲਾਂ"
#: ../src/shell-global.c:1242
#: ../src/shell-global.c:1374
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d ਘੰਟਾ ਪਹਿਲਾਂ"
msgstr[1] "%d ਘੰਟੇ ਪਹਿਲਾਂ"
#: ../src/shell-global.c:1247
#: ../src/shell-global.c:1379
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d ਦਿਨ ਪਹਿਲਾਂ"
msgstr[1] "%d ਦਿਨ ਪਹਿਲਾਂ"
#: ../src/shell-global.c:1252
#: ../src/shell-global.c:1384
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"

View 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

View File

@ -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) \
@ -89,6 +90,8 @@ libgnome_shell_la_SOURCES = \
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-global.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)

View File

@ -0,0 +1 @@
Please keep in sync with gnome-panel.

File diff suppressed because it is too large Load Diff

View 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__ */

View 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__ */

View 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;
}

View 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__ */

View 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;
}

View 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__ */

View File

@ -24,6 +24,7 @@
#define __NA_TRAY_CHILD_H__
#include <gtk/gtk.h>
#include <gtk/gtkx.h>
#include <gdk/gdkx.h>
G_BEGIN_DECLS

View File

@ -315,19 +315,13 @@ pending_message_free (PendingMessage *message)
g_free (message);
}
static GdkFilterReturn
na_tray_manager_handle_client_message_message_data (GdkXEvent *xev,
GdkEvent *event,
gpointer data)
static void
na_tray_manager_handle_message_data (NaTrayManager *manager,
XClientMessageEvent *xevent)
{
XClientMessageEvent *xevent;
NaTrayManager *manager;
GList *p;
int len;
GList *p;
int len;
xevent = (XClientMessageEvent *) xev;
manager = data;
/* Try to see if we can find the pending message in the list */
for (p = manager->messages; p; p = p->next)
{
@ -361,8 +355,6 @@ na_tray_manager_handle_client_message_message_data (GdkXEvent *xev,
break;
}
}
return GDK_FILTER_REMOVE;
}
static void
@ -382,13 +374,17 @@ na_tray_manager_handle_begin_message (NaTrayManager *manager,
if (!socket)
return;
timeout = xevent->data.l[2];
len = xevent->data.l[3];
id = xevent->data.l[4];
/* Check if the same message is already in the queue and remove it if so */
for (p = manager->messages; p; p = p->next)
{
PendingMessage *pmsg = p->data;
if (xevent->window == pmsg->window &&
xevent->data.l[4] == pmsg->id)
id == pmsg->id)
{
/* Hmm, we found it, now remove it */
pending_message_free (pmsg);
@ -398,10 +394,6 @@ na_tray_manager_handle_begin_message (NaTrayManager *manager,
}
}
timeout = xevent->data.l[2];
len = xevent->data.l[3];
id = xevent->data.l[4];
if (len == 0)
{
g_signal_emit (manager, manager_signals[MESSAGE_SENT], 0,
@ -428,6 +420,9 @@ na_tray_manager_handle_cancel_message (NaTrayManager *manager,
{
GList *p;
GtkSocket *socket;
long id;
id = xevent->data.l[2];
/* Check if the message is in the queue and remove it if so */
for (p = manager->messages; p; p = p->next)
@ -435,7 +430,7 @@ na_tray_manager_handle_cancel_message (NaTrayManager *manager,
PendingMessage *msg = p->data;
if (xevent->window == msg->window &&
xevent->data.l[4] == msg->id)
id == msg->id)
{
pending_message_free (msg);
manager->messages = g_list_remove_link (manager->messages, p);
@ -454,39 +449,6 @@ na_tray_manager_handle_cancel_message (NaTrayManager *manager,
}
}
static GdkFilterReturn
na_tray_manager_handle_client_message_opcode (GdkXEvent *xev,
GdkEvent *event,
gpointer data)
{
XClientMessageEvent *xevent;
NaTrayManager *manager;
xevent = (XClientMessageEvent *) xev;
manager = data;
switch (xevent->data.l[1])
{
case SYSTEM_TRAY_REQUEST_DOCK:
/* Ignore this one since we don't know on which window this was received
* and so we can't know for which screen this is. It will be handled
* in na_tray_manager_window_filter() since we also receive it there */
break;
case SYSTEM_TRAY_BEGIN_MESSAGE:
na_tray_manager_handle_begin_message (manager, xevent);
return GDK_FILTER_REMOVE;
case SYSTEM_TRAY_CANCEL_MESSAGE:
na_tray_manager_handle_cancel_message (manager, xevent);
return GDK_FILTER_REMOVE;
default:
break;
}
return GDK_FILTER_CONTINUE;
}
static GdkFilterReturn
na_tray_manager_window_filter (GdkXEvent *xev,
GdkEvent *event,
@ -497,8 +459,7 @@ na_tray_manager_window_filter (GdkXEvent *xev,
if (xevent->type == ClientMessage)
{
/* We handle this client message here. See comment in
* na_tray_manager_handle_client_message_opcode() for details */
/* _NET_SYSTEM_TRAY_OPCODE: SYSTEM_TRAY_REQUEST_DOCK */
if (xevent->xclient.message_type == manager->opcode_atom &&
xevent->xclient.data.l[1] == SYSTEM_TRAY_REQUEST_DOCK)
{
@ -506,6 +467,29 @@ na_tray_manager_window_filter (GdkXEvent *xev,
(XClientMessageEvent *) xevent);
return GDK_FILTER_REMOVE;
}
/* _NET_SYSTEM_TRAY_OPCODE: SYSTEM_TRAY_BEGIN_MESSAGE */
else if (xevent->xclient.message_type == manager->opcode_atom &&
xevent->xclient.data.l[1] == SYSTEM_TRAY_BEGIN_MESSAGE)
{
na_tray_manager_handle_begin_message (manager,
(XClientMessageEvent *) event);
return GDK_FILTER_REMOVE;
}
/* _NET_SYSTEM_TRAY_OPCODE: SYSTEM_TRAY_CANCEL_MESSAGE */
else if (xevent->xclient.message_type == manager->opcode_atom &&
xevent->xclient.data.l[1] == SYSTEM_TRAY_CANCEL_MESSAGE)
{
na_tray_manager_handle_cancel_message (manager,
(XClientMessageEvent *) event);
return GDK_FILTER_REMOVE;
}
/* _NET_SYSTEM_TRAY_MESSAGE_DATA */
else if (xevent->xclient.message_type == manager->message_data_atom)
{
na_tray_manager_handle_message_data (manager,
(XClientMessageEvent *) event);
return GDK_FILTER_REMOVE;
}
}
else if (xevent->type == SelectionClear)
{
@ -563,9 +547,6 @@ na_tray_manager_unmanage (NaTrayManager *manager)
TRUE);
}
//FIXME: we should also use gdk_remove_client_message_filter when it's
//available
// See bug #351254
gdk_window_remove_filter (window,
na_tray_manager_window_filter, manager);
@ -736,6 +717,8 @@ na_tray_manager_manage_screen_x11 (NaTrayManager *manager,
message_data_atom = gdk_atom_intern ("_NET_SYSTEM_TRAY_MESSAGE_DATA",
FALSE);
manager->message_data_atom = gdk_x11_atom_to_xatom_for_display (display,
message_data_atom);
/* Add a window filter */
#if 0
@ -744,17 +727,8 @@ na_tray_manager_manage_screen_x11 (NaTrayManager *manager,
G_CALLBACK (na_tray_manager_selection_clear_event),
manager);
#endif
/* This is for SYSTEM_TRAY_REQUEST_DOCK and SelectionClear */
gdk_window_add_filter (window,
na_tray_manager_window_filter, manager);
/* This is for SYSTEM_TRAY_BEGIN_MESSAGE and SYSTEM_TRAY_CANCEL_MESSAGE */
gdk_display_add_client_message_filter (display, opcode_atom,
na_tray_manager_handle_client_message_opcode,
manager);
/* This is for _NET_SYSTEM_TRAY_MESSAGE_DATA */
gdk_display_add_client_message_filter (display, message_data_atom,
na_tray_manager_handle_client_message_message_data,
manager);
return TRUE;
}
else

View File

@ -50,6 +50,7 @@ struct _NaTrayManager
#ifdef GDK_WINDOWING_X11
GdkAtom selection_atom;
Atom opcode_atom;
Atom message_data_atom;
#endif
GtkWidget *invisible;

View File

@ -62,7 +62,8 @@ fi
# libxklavier, libxml2, ORBit2, pam, python, readline,
# spidermonkey ({mozilla,firefox,xulrunner}-js), startup-notification,
# xdamage, icon-naming-utils, upower, libtool-ltdl, libvorbis,
# libgcrypt, libtasn1, libgnome-keyring, libgtop, cups
# libgcrypt, libtasn1, libgnome-keyring, libgtop, cups,
# evolution-data-server
#
# Non-devel packages needed by gnome-shell and its deps:
# glxinfo, gstreamer-plugins-base, gstreamer-plugins-good,
@ -83,7 +84,7 @@ if test "x$system" = xUbuntu -o "x$system" = xDebian -o "x$system" = xLinuxMint
xulrunner-dev xserver-xephyr gnome-terminal libcroco3-dev
libgstreamer0.10-dev gstreamer0.10-plugins-base gstreamer0.10-plugins-good
libltdl-dev libvorbis-dev libxklavier-dev libgnome-keyring-dev
libupower-glib-dev libcups2-dev
libupower-glib-dev libcups2-dev evolution-data-server-dev
"
if apt-cache show autopoint > /dev/null 2> /dev/null; then
@ -121,7 +122,7 @@ if test "x$system" = xFedora ; then
startup-notification-devel xorg-x11-server-Xephyr gnome-terminal zenity
icon-naming-utils upower-devel libtool-ltdl-devel libvorbis-devel
libxklavier-devel libgcrypt-devel libtasn1-devel libtasn1-tools
libgnome-keyring-devel libgtop2-devel cups-devel
libgnome-keyring-devel libgtop2-devel cups-devel evolution-data-server-devel
"
if expr $version \>= 14 > /dev/null ; then
@ -147,7 +148,7 @@ if test "x$system" = xSUSE -o "x$system" = "xSUSE LINUX" ; then
libgtop-devel libpulse-devel libtiff-devel cups-devel libffi-devel \
orbit2-devel libwnck-devel xorg-x11-proto-devel readline-devel \
mozilla-xulrunner191-devel libcroco-devel \
xorg-x11-devel xorg-x11 xorg-x11-server-extra \
xorg-x11-devel xorg-x11 xorg-x11-server-extra evolution-data-server-devel \
; do
if ! rpm -q $pkg > /dev/null 2>&1; then
reqd="$pkg $reqd"
@ -168,7 +169,7 @@ if test "x$system" = xMandrivaLinux ; then
intltool ffi5-devel libwnck-1-devel GL-devel ORBit2-devel \
readline-devel libxulrunner-devel \
libxdamage-devel mesa-demos x11-server-xephyr zenity \
libcroco0.6-devel \
libcroco0.6-devel libevolution-data-server3-devel \
; do
if ! rpm -q --whatprovides $pkg > /dev/null 2>&1; then
reqd="$pkg $reqd"

View File

@ -88,17 +88,10 @@
</dependencies>
</autotools>
<autotools id="gtk-theme-engine-clearlooks">
<branch repo="git.gnome.org" module="gtk-theme-engine-clearlooks"/>
<dependencies>
<dep package="gtk3"/>
</dependencies>
</autotools>
<autotools id="gnome-themes-standard">
<branch repo="git.gnome.org" module="gnome-themes-standard"/>
<dependencies>
<dep package="gtk-theme-engine-clearlooks"/>
<dep package="gtk3"/>
</dependencies>
</autotools>