Merge lp:~kvalo/indicator-network/settings-merge into lp:~indicator-applet-developers/indicator-network/indicator-network

Proposed by Kalle Valo
Status: Merged
Merged at revision: 121
Proposed branch: lp:~kvalo/indicator-network/settings-merge
Merge into: lp:~indicator-applet-developers/indicator-network/indicator-network
Diff against target: 2659 lines (+2425/-2)
39 files modified
.bzrignore (+1/-0)
AUTHORS (+1/-0)
configure.ac (+12/-1)
po/POTFILES.in (+6/-0)
src/Makefile.am (+2/-1)
src/settings/Makefile.am (+16/-0)
src/settings/indicator-network-settings (+61/-0)
src/settings/indicatorNetworkSettings/Makefile.am (+13/-0)
src/settings/indicatorNetworkSettings/SimpleGtkbuilderApp.py (+58/-0)
src/settings/indicatorNetworkSettings/__init__.py (+1/-0)
src/settings/indicatorNetworkSettings/app.py (+74/-0)
src/settings/indicatorNetworkSettings/backend/Makefile.am (+6/-0)
src/settings/indicatorNetworkSettings/backend/__init__.py (+1/-0)
src/settings/indicatorNetworkSettings/backend/connection.py (+49/-0)
src/settings/indicatorNetworkSettings/backend/device.py (+86/-0)
src/settings/indicatorNetworkSettings/enums.py (+43/-0)
src/settings/indicatorNetworkSettings/frontend/Makefile.am (+9/-0)
src/settings/indicatorNetworkSettings/frontend/__init__.py (+1/-0)
src/settings/indicatorNetworkSettings/frontend/pages/Makefile.am (+5/-0)
src/settings/indicatorNetworkSettings/frontend/pages/connections.py (+111/-0)
src/settings/indicatorNetworkSettings/frontend/utils.py (+34/-0)
src/settings/indicatorNetworkSettings/frontend/widgets/Makefile.am (+6/-0)
src/settings/indicatorNetworkSettings/frontend/widgets/__init__.py (+1/-0)
src/settings/indicatorNetworkSettings/frontend/widgets/cellrenderers.py (+210/-0)
src/settings/indicatorNetworkSettings/frontend/widgets/connectionview.py (+78/-0)
src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/Makefile.am (+3/-0)
src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/__init__.py (+30/-0)
src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/bluetooth.py (+35/-0)
src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/mobile.py (+121/-0)
src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/wired.py (+35/-0)
src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/wireless.py (+134/-0)
src/settings/indicatorNetworkSettings/frontend/widgets/deviceview.py (+157/-0)
src/settings/indicatorNetworkSettings/frontend/widgets/toggleswitch.py (+529/-0)
src/settings/indicatorNetworkSettings/utils.py (+18/-0)
src/settings/indicatorNetworkSettings/version.py (+5/-0)
src/settings/ui/Makefile.am (+5/-0)
src/settings/ui/indicator-network-settings.ui (+163/-0)
src/settings/ui/mobile_box.ui (+212/-0)
src/settings/ui/wireless_box.ui (+93/-0)
To merge this branch: bzr merge lp:~kvalo/indicator-network/settings-merge
Reviewer Review Type Date Requested Status
Mikkel Kamstrup Erlandsen (community) Approve
Andrew Pending
Review via email: mp+43183@code.launchpad.net
To post a comment you must log in.
120. By Kalle Valo

Add Andrew to the authors file.

121. By Kalle Valo

Change copyright of SimpleGtkbuilderApp.py with approval from Michael
Vogt.

122. By Kalle Valo

settings: unify copyrights with approval from Andrew.

Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) wrote :

in src/settings/indicator-network-settings:
 * There are two checks on os.path.exists("ui/indicator-network-settings.ui") can they be merged into one in order to simplify the code a bit?

 * Uses hardcoded /usr/share/indicator-network. It should use $pkgdatadir from autoconf

in src/settings/indicatorNetworkSettings/SimpleGtkbuilderApp.py:
 * The header says SimpleGladeApp, it should be SimpleGtkbuilderApp i guess

in src/settings/indicatorNetworkSettings/app.py:
 * There is a hardcoded /usr/share/locale in the _setup_translations(). I think this oughta use the datadir from autoconf.

in */Makefile.am:
 * Please put each python module on its own line that is autofoo standard

class ToggleSwitch: I don't know whether gtk.Switch will be backported to gtk2.0 (or if this UI will switch to gtk3). If it is than it's probably the widget to use here: http://library.gnome.org/devel/gtk/unstable/GtkSwitch.html. Otherwise the custom widget needs to stay of course.

class InfoBox: Why is gtk.InfoBar not good enough?

review: Needs Information
Revision history for this message
Kalle Valo (kvalo) wrote :

Mikkel Kamstrup Erlandsen <email address hidden> writes:

> in src/settings/indicator-network-settings:
>
> * There are two checks on
> os.path.exists("ui/indicator-network-settings.ui") can they be merged
> into one in order to simplify the code a bit?

Actually I don't know why we need to set the path anyway. Maybe Andrew
can comment on that?

But for now I just removed this code:

-if os.path.exists("ui/indicator-network-settings.ui"):
- sys.path.insert(0, os.path.abspath(os.getcwd()))

> * Uses hardcoded /usr/share/indicator-network. It should use
> $pkgdatadir from autoconf

That's a bit harder to implement. I believe the convention is from
software-center which also hardcodes the path in
/usr/share/software-center/software-center script.

> in src/settings/indicatorNetworkSettings/SimpleGtkbuilderApp.py:
> * The header says SimpleGladeApp, it should be SimpleGtkbuilderApp i guess

Fixed.

> in src/settings/indicatorNetworkSettings/app.py:
>
> * There is a hardcoded /usr/share/locale in the
> _setup_translations(). I think this oughta use the datadir from
> autoconf.

Same comment as above. Any tips how to do this properly is appreciated.

> in */Makefile.am:
> * Please put each python module on its own line that is autofoo standard

Fixed.

> class ToggleSwitch: I don't know whether gtk.Switch will be backported
> to gtk2.0 (or if this UI will switch to gtk3). If it is than it's
> probably the widget to use here:
> http://library.gnome.org/devel/gtk/unstable/GtkSwitch.html. Otherwise
> the custom widget needs to stay of course.

I think we have to switch to gtk3 quite soon, especially due to the new
control center, but not quite yet.

> class InfoBox: Why is gtk.InfoBar not good enough?

Andrew, can you answer this one?

Thank you for the review. I have now pushed the fixes. I also noticed
some other issues with distcheck and fixed them at the same time.

--
Kalle Valo

123. By Kalle Valo

settings: don't set path if running locally

124. By Kalle Valo

settings: fix name of a script in comments

125. By Kalle Valo

settings: each autofoo item in it's own line

126. By Kalle Valo

settings: include ui files to the dist

127. By Kalle Valo

potfiles: add files from settings

Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) wrote :

 review approve

On 13 December 2010 15:13, Kalle Valo <email address hidden> wrote:
> Mikkel Kamstrup Erlandsen <email address hidden> writes:
>
>> in src/settings/indicator-network-settings:
>>
>>  * There are two checks on
>>  os.path.exists("ui/indicator-network-settings.ui") can they be merged
>>  into one in order to simplify the code a bit?
>
> Actually I don't know why we need to set the path anyway. Maybe Andrew
> can comment on that?
>
> But for now I just removed this code:
>
> -if os.path.exists("ui/indicator-network-settings.ui"):
> -    sys.path.insert(0, os.path.abspath(os.getcwd()))

This section is there to be able to run the app directly from the
source tree, soo you might wanna re-add it for convenience. My point
was merely to move together with the other check for the same file.

>>  * Uses hardcoded /usr/share/indicator-network. It should use
>>  $pkgdatadir from autoconf
>
> That's a bit harder to implement. I believe the convention is from
> software-center which also hardcodes the path in
> /usr/share/software-center/software-center script.

Passing the monkey on eh? I think I need to talk to Michael about
these "conventions" ;-)

The normal way to do this is to have a config.py.in file and add
config.py to your AC_OUTPUT in configure.ac

review: Approve
Revision history for this message
Kalle Valo (kvalo) wrote :

Mikkel Kamstrup Erlandsen <email address hidden> writes:

> Review: Approve

Thanks!

> On 13 December 2010 15:13, Kalle Valo <email address hidden> wrote:
>> Mikkel Kamstrup Erlandsen <email address hidden> writes:
>>
>>> in src/settings/indicator-network-settings:
>>>
>>>  * There are two checks on
>>>  os.path.exists("ui/indicator-network-settings.ui") can they be merged
>>>  into one in order to simplify the code a bit?
>>
>> Actually I don't know why we need to set the path anyway. Maybe Andrew
>> can comment on that?
>>
>> But for now I just removed this code:
>>
>> -if os.path.exists("ui/indicator-network-settings.ui"):
>> -    sys.path.insert(0, os.path.abspath(os.getcwd()))
>
> This section is there to be able to run the app directly from the
> source tree, soo you might wanna re-add it for convenience.

Don't worry, I tested that before removing the code. I didn't find any
why we need to set the path, so it should be safe to remove. If somebody
comes up with a reason, please let me know :)

> My point was merely to move together with the other check for the same
> file.

Yeah, I got your point. I just want to remove stale code as I find them.

>>>  * Uses hardcoded /usr/share/indicator-network. It should use
>>>  $pkgdatadir from autoconf
>>
>> That's a bit harder to implement. I believe the convention is from
>> software-center which also hardcodes the path in
>> /usr/share/software-center/software-center script.
>
> Passing the monkey on eh?

Whatever it takes to get the code merged in ;)

More seriously, I noticed this problem already earlier but I didn't
think that this is serious enough to prevent merging the code to trunk.
I now filed bug #689708 to handle this so that it won't be forgotten.

> The normal way to do this is to have a config.py.in file and add
> config.py to your AC_OUTPUT in configure.ac

But how can a script from /usr/bin find this config.py? Or should I
create indicator-network-settings.in and create the script dynamically
with the correct path?

Thank you for the good comments.

--
Kalle Valo

Revision history for this message
Andrew (and471) wrote :

Ok so...

>in src/settings/indicator-network-settings:
> * There are two checks on os.path.exists("ui/indicator-network-settings.ui") can they be merged into one in order >to simplify the code a bit?
>* Uses hardcoded /usr/share/indicator-network. It should use $pkgdatadir from autoconf
>in src/settings/indicatorNetworkSettings/SimpleGtkbuilderApp.py:
> * The header says SimpleGladeApp, it should be SimpleGtkbuilderApp i guess
>in src/settings/indicatorNetworkSettings/app.py:
> * There is a hardcoded /usr/share/locale in the _setup_translations(). I think this oughta use the datadir from >autoconf.
>in */Makefile.am:
> * Please put each python module on its own line that is autofoo standard

I assume the above have been taken care of by Kalle.

>class ToggleSwitch: I don't know whether gtk.Switch will be backported to gtk2.0 (or if this UI will switch to >gtk3). If it is than it's probably the widget to use here: http://library.gnome.org/devel/gtk/unstable/GtkSwitch.html. Otherwise the custom widget needs to stay of course.

I am also not sure of this. What actually happened is I created the toggleswitch and then a week later say it had been created in GTK :/ However it is as you say, it it isn't back-ported we will keep it, otherwise it should be simple to port it to gtk.Switch

>class InfoBox: Why is gtk.InfoBar not good enough?

Because they are different colours and InfoBar should contain an icon and text, whereas we are packing it with other things :)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2010-12-01 07:47:53 +0000
3+++ .bzrignore 2010-12-13 14:13:17 +0000
4@@ -88,3 +88,4 @@
5 src/libconnman/libconnman_la-connman-manager.lo
6 tests/libconnman-tool
7 src/libconnman/libconnman_la-connman-service.lo
8+py-compile
9
10=== modified file 'AUTHORS'
11--- AUTHORS 2010-05-19 07:49:00 +0000
12+++ AUTHORS 2010-12-13 14:13:17 +0000
13@@ -1,1 +1,2 @@
14 Kalle Valo <kalle.valo@canonical.com>
15+Andrew Higginson
16
17=== modified file 'configure.ac'
18--- configure.ac 2010-12-09 22:05:35 +0000
19+++ configure.ac 2010-12-13 14:13:17 +0000
20@@ -1,6 +1,6 @@
21 AC_INIT([indicator-network], [0.3.1])
22 AC_CONFIG_SRCDIR(src/indicator/indicator.c)
23-AM_INIT_AUTOMAKE
24+AM_INIT_AUTOMAKE([tar-ustar])
25
26 AC_PREREQ(2.53)
27
28@@ -17,6 +17,9 @@
29 AM_PROG_CC_C_O
30 AC_STDC_HEADERS
31 AC_PROG_LIBTOOL
32+AM_PATH_PYTHON
33+AC_PROG_LN_S
34+AC_PROG_MKDIR_P
35
36 AC_SUBST(VERSION)
37 AC_CONFIG_MACRO_DIR([m4])
38@@ -149,6 +152,14 @@
39 src/libconnman/Makefile
40 src/backend/Makefile
41 src/agent/Makefile
42+src/settings/Makefile
43+src/settings/ui/Makefile
44+src/settings/indicatorNetworkSettings/Makefile
45+src/settings/indicatorNetworkSettings/backend/Makefile
46+src/settings/indicatorNetworkSettings/frontend/Makefile
47+src/settings/indicatorNetworkSettings/frontend/pages/Makefile
48+src/settings/indicatorNetworkSettings/frontend/widgets/Makefile
49+src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/Makefile
50 data/Makefile
51 po/Makefile.in
52 scripts/Makefile
53
54=== modified file 'po/POTFILES.in'
55--- po/POTFILES.in 2010-09-23 07:24:58 +0000
56+++ po/POTFILES.in 2010-12-13 14:13:17 +0000
57@@ -8,3 +8,9 @@
58 src/agent/pin-dialog.c
59 scripts/indicator-network-settings
60 scripts/indicator-network-mobile-wizard
61+src/settings/indicatorNetworkSettings/enums.py
62+src/settings/indicatorNetworkSettings/frontend/widgets/connectionview.py
63+src/settings/indicatorNetworkSettings/frontend/widgets/deviceview.py
64+src/settings/ui/indicator-network-settings.ui
65+src/settings/ui/mobile_box.ui
66+src/settings/ui/wireless_box.ui
67
68=== modified file 'src/Makefile.am'
69--- src/Makefile.am 2010-12-01 07:47:53 +0000
70+++ src/Makefile.am 2010-12-13 14:13:17 +0000
71@@ -3,4 +3,5 @@
72 libconnman \
73 indicator \
74 backend \
75- agent
76+ agent \
77+ settings
78
79=== added directory 'src/settings'
80=== added file 'src/settings/Makefile.am'
81--- src/settings/Makefile.am 1970-01-01 00:00:00 +0000
82+++ src/settings/Makefile.am 2010-12-13 14:13:17 +0000
83@@ -0,0 +1,16 @@
84+SUBDIRS = \
85+ indicatorNetworkSettings \
86+ ui
87+
88+dist_pkgdata_SCRIPTS = \
89+ indicator-network-settings
90+
91+# create a symbolic link to bindir
92+# FIXME: it will have suffix -2 until new settings window is usable
93+#
94+# Note: ln -f is not portable
95+install-exec-hook:
96+ $(MKDIR_P) $(DESTDIR)$(bindir) && \
97+ cd $(DESTDIR)$(bindir) && \
98+ $(LN_S) -f $(pkgdatadir)/indicator-network-settings \
99+ indicator-network-settings-2
100
101=== added file 'src/settings/indicator-network-settings'
102--- src/settings/indicator-network-settings 1970-01-01 00:00:00 +0000
103+++ src/settings/indicator-network-settings 2010-12-13 14:13:17 +0000
104@@ -0,0 +1,61 @@
105+#!/usr/bin/python
106+# Copyright (C) 2010 Canonical
107+#
108+# Authors:
109+# Andrew Higginson
110+#
111+# This program is free software; you can redistribute it and/or modify it under
112+# the terms of the GNU General Public License as published by the Free Software
113+# Foundation; version 3.
114+#
115+# This program is distributed in the hope that it will be useful, but WITHOUT
116+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
117+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
118+# details.
119+#
120+# You should have received a copy of the GNU General Public License along with
121+# this program; if not, write to the Free Software Foundation, Inc.,
122+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
123+
124+import pygtk
125+pygtk.require ("2.0")
126+import gtk
127+
128+import gettext
129+import logging
130+import os
131+import sys
132+
133+from optparse import OptionParser
134+from indicatorNetworkSettings.enums import *
135+from indicatorNetworkSettings.version import *
136+
137+if __name__ == "__main__":
138+ parser = OptionParser("usage: %prog [options]", version="%prog "+VERSION)
139+ parser.add_option("--debug", action="store_true",
140+ help="enable debug mode", default=False)
141+ parser.add_option("--force-rtl", action="store_true",
142+ help="force rtl mode (useful for debugging)",
143+ default=False)
144+ (options, args) = parser.parse_args()
145+
146+ if options.debug:
147+ logging.basicConfig(level=logging.DEBUG)
148+ else:
149+ logging.basicConfig(level=logging.INFO)
150+
151+ # Override text direction for testing purposes
152+ if options.force_rtl:
153+ gtk.widget_set_default_direction(gtk.TEXT_DIR_RTL)
154+
155+ if os.path.exists("./ui/indicator-network-settings.ui"):
156+ logging.info("Running locally")
157+ datadir = "./"
158+ else:
159+ datadir = "/usr/share/indicator-network/"
160+
161+ from indicatorNetworkSettings.app import NetworkSettingsApp
162+
163+ app = NetworkSettingsApp(datadir)
164+ app.run()
165+
166
167=== added directory 'src/settings/indicatorNetworkSettings'
168=== added file 'src/settings/indicatorNetworkSettings/Makefile.am'
169--- src/settings/indicatorNetworkSettings/Makefile.am 1970-01-01 00:00:00 +0000
170+++ src/settings/indicatorNetworkSettings/Makefile.am 2010-12-13 14:13:17 +0000
171@@ -0,0 +1,13 @@
172+SUBDIRS = \
173+ backend \
174+ frontend
175+
176+# indicator-network-settings
177+insdir = $(pkgdatadir)/indicatorNetworkSettings
178+ins_PYTHON = \
179+ app.py \
180+ enums.py \
181+ __init__.py \
182+ SimpleGtkbuilderApp.py \
183+ utils.py \
184+ version.py
185
186=== added file 'src/settings/indicatorNetworkSettings/SimpleGtkbuilderApp.py'
187--- src/settings/indicatorNetworkSettings/SimpleGtkbuilderApp.py 1970-01-01 00:00:00 +0000
188+++ src/settings/indicatorNetworkSettings/SimpleGtkbuilderApp.py 2010-12-13 14:13:17 +0000
189@@ -0,0 +1,58 @@
190+"""
191+ SimpleGtkbuilderApp.py
192+ Module that provides an object oriented abstraction to pygtk and gtkbuilder
193+ Copyright (C) 2009 Canonical
194+ Author Michael Vogt
195+ based on ideas from SimpleGladeBuilder by Sandino Flores Moreno
196+"""
197+
198+# This library is free software; you can redistribute it and/or
199+# modify it under the terms of the GNU Lesser General Public
200+# License as published by the Free Software Foundation; version 3.
201+#
202+# This library is distributed in the hope that it will be useful,
203+# but WITHOUT ANY WARRANTY; without even the implied warranty of
204+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
205+# Lesser General Public License for more details.
206+#
207+# You should have received a copy of the GNU Lesser General Public
208+# License along with this library; if not, write to the Free Software
209+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
210+# USA
211+
212+import sys
213+import gtk
214+
215+class SimpleGtkbuilderApp(object):
216+ def __init__(self, path, domain):
217+ self.builder = gtk.Builder()
218+ self.builder.set_translation_domain(domain)
219+ self.builder.add_from_file(path)
220+ self.builder.connect_signals(self)
221+ for o in self.builder.get_objects():
222+ if issubclass(type(o), gtk.Buildable):
223+ name = gtk.Buildable.get_name(o)
224+ setattr(self, name, o)
225+ else:
226+ print >> sys.stderr, "WARNING: can not get name for '%s'" % o
227+
228+ def run(self):
229+ """
230+ Starts the main loop of processing events checking for Control-C.
231+
232+ The default implementation checks wheter a Control-C is pressed,
233+ then calls on_keyboard_interrupt().
234+
235+ Use this method for starting programs.
236+ """
237+ try:
238+ gtk.main()
239+ except KeyboardInterrupt:
240+ self.on_keyboard_interrupt()
241+
242+ def on_keyboard_interrupt(self):
243+ """
244+ This method is called by the default implementation of run()
245+ after a program is finished by pressing Control-C.
246+ """
247+ pass
248
249=== added file 'src/settings/indicatorNetworkSettings/__init__.py'
250--- src/settings/indicatorNetworkSettings/__init__.py 1970-01-01 00:00:00 +0000
251+++ src/settings/indicatorNetworkSettings/__init__.py 2010-12-13 14:13:17 +0000
252@@ -0,0 +1,1 @@
253+
254
255=== added file 'src/settings/indicatorNetworkSettings/app.py'
256--- src/settings/indicatorNetworkSettings/app.py 1970-01-01 00:00:00 +0000
257+++ src/settings/indicatorNetworkSettings/app.py 2010-12-13 14:13:17 +0000
258@@ -0,0 +1,74 @@
259+# Copyright (C) 2010 Canonical
260+#
261+# Authors:
262+# Andrew Higginson
263+#
264+# This program is free software; you can redistribute it and/or modify it under
265+# the terms of the GNU General Public License as published by the Free Software
266+# Foundation; version 3.
267+#
268+# This program is distributed in the hope that it will be useful, but WITHOUT
269+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
270+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
271+# details.
272+#
273+# You should have received a copy of the GNU General Public License along with
274+# this program; if not, write to the Free Software Foundation, Inc.,
275+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
276+
277+import locale
278+import gtk
279+import os
280+import gettext
281+
282+from indicatorNetworkSettings.enums import *
283+from indicatorNetworkSettings.version import *
284+from indicatorNetworkSettings.frontend.pages.connections import \
285+ ConnectionsPage
286+from indicatorNetworkSettings.SimpleGtkbuilderApp import \
287+ SimpleGtkbuilderApp
288+
289+class NetworkSettingsApp(SimpleGtkbuilderApp):
290+ def __init__(self, datadir):
291+ SimpleGtkbuilderApp.__init__(self,
292+ os.path.join(datadir, "ui", "indicator-network-settings.ui"),
293+ "indicator-network-settings")
294+
295+ # Useful variables
296+ self.datadir = datadir
297+ self.icons = gtk.icon_theme_get_default()
298+
299+ # Setup Translations
300+ self._setup_translations()
301+
302+ # Setup Pages
303+ self.page_connections = ConnectionsPage(self, datadir)
304+ self.pages = [self.page_connections]
305+
306+ self.on_notebook_main_page_switched(None, None, 0)
307+
308+ # Callbacks
309+ def on_window_main_delete_event(self, widget, event):
310+ gtk.main_quit()
311+
312+ def on_notebook_main_page_switched(self, widget, move_focus, page_num):
313+ page_alignment = self.notebook_main.get_nth_page(page_num)
314+
315+ for page in self.pages:
316+ if page.alignment == page_alignment:
317+ page.on_first_expose()
318+
319+ # Private Functions
320+ def _setup_translations(self):
321+ gettext.bindtextdomain("indicator-network-settings",
322+ "/usr/share/locale")
323+ gettext.textdomain("indicator-network-settings")
324+ try:
325+ locale.setlocale(locale.LC_ALL, "")
326+ except Exception:
327+ print "setlocale failed"
328+
329+ # Public Functions
330+ def run(self):
331+ self.window_main.show_all()
332+ super(NetworkSettingsApp, self).run()
333
334=== added directory 'src/settings/indicatorNetworkSettings/backend'
335=== added file 'src/settings/indicatorNetworkSettings/backend/Makefile.am'
336--- src/settings/indicatorNetworkSettings/backend/Makefile.am 1970-01-01 00:00:00 +0000
337+++ src/settings/indicatorNetworkSettings/backend/Makefile.am 2010-12-13 14:13:17 +0000
338@@ -0,0 +1,6 @@
339+# indicator-network-settings
340+insdir = $(pkgdatadir)/indicatorNetworkSettings/backend
341+ins_PYTHON = \
342+ connection.py \
343+ device.py \
344+ __init__.py
345
346=== added file 'src/settings/indicatorNetworkSettings/backend/__init__.py'
347--- src/settings/indicatorNetworkSettings/backend/__init__.py 1970-01-01 00:00:00 +0000
348+++ src/settings/indicatorNetworkSettings/backend/__init__.py 2010-12-13 14:13:17 +0000
349@@ -0,0 +1,1 @@
350+
351
352=== added file 'src/settings/indicatorNetworkSettings/backend/connection.py'
353--- src/settings/indicatorNetworkSettings/backend/connection.py 1970-01-01 00:00:00 +0000
354+++ src/settings/indicatorNetworkSettings/backend/connection.py 2010-12-13 14:13:17 +0000
355@@ -0,0 +1,49 @@
356+#!/usr/bin/env python
357+# -*- coding: utf-8 -*-
358+#
359+# Copyright (C) 2010 Canonical
360+#
361+# Authors:
362+# Andrew Higginson
363+#
364+# This program is free software; you can redistribute it and/or modify it under
365+# the terms of the GNU General Public License as published by the Free Software
366+# Foundation; version 3.
367+#
368+# This program is distributed in the hope that it will be useful, but WITHOUT
369+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
370+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
371+# details.
372+#
373+# You should have received a copy of the GNU General Public License along with
374+# this program; if not, write to the Free Software Foundation, Inc.,
375+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
376+
377+import datetime
378+
379+class WifiConnection(object):
380+ def __init__(self):
381+ self.network = None
382+ self.signal = None
383+ self.last_used = None
384+
385+ def connect_(self, key):
386+ print "Connecting to %s" % self.network
387+
388+def get_remembered_wireless_connections(device):
389+ ### Dummy Connections (temporary)
390+ connection1 = WifiConnection()
391+ connection1.network = "BTHomeHub-193209"
392+ connection1.signal = "0.75"
393+ connection1.last_used = datetime.date(2010, 11, 3)
394+ connection2 = WifiConnection()
395+ connection2.network = "SKY-001"
396+ connection2.signal = "0.55"
397+ connection2.last_used = datetime.date(2010, 5, 22)
398+ connection3 = WifiConnection()
399+ connection3.network = "Starbucks OpenAccess"
400+ connection3.signal = "0.2"
401+ connection3.last_used = None
402+ ###
403+ connections = (connection1, connection2, connection3)
404+ return connections
405
406=== added file 'src/settings/indicatorNetworkSettings/backend/device.py'
407--- src/settings/indicatorNetworkSettings/backend/device.py 1970-01-01 00:00:00 +0000
408+++ src/settings/indicatorNetworkSettings/backend/device.py 2010-12-13 14:13:17 +0000
409@@ -0,0 +1,86 @@
410+#!/usr/bin/env python
411+# -*- coding: utf-8 -*-
412+#
413+# Copyright (C) 2010 Canonical
414+#
415+# Authors:
416+# Andrew Higginson
417+#
418+# This program is free software; you can redistribute it and/or modify it under
419+# the terms of the GNU General Public License as published by the Free Software
420+# Foundation; version 3.
421+#
422+# This program is distributed in the hope that it will be useful, but WITHOUT
423+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
424+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
425+# details.
426+#
427+# You should have received a copy of the GNU General Public License along with
428+# this program; if not, write to the Free Software Foundation, Inc.,
429+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
430+
431+import gobject
432+
433+from indicatorNetworkSettings.enums import *
434+
435+class Device(gobject.GObject):
436+
437+ __gsignals__ = {
438+ "state-changed" : (gobject.SIGNAL_RUN_LAST,
439+ gobject.TYPE_NONE,
440+ ([gobject.TYPE_PYOBJECT]),
441+ ),
442+ }
443+
444+
445+ def __init__(self):
446+ super(Device, self).__init__()
447+ self.type = None
448+ self.state = None
449+
450+ def set_state(self, state):
451+ self.state = state
452+ self.emit("state-changed", self.state)
453+
454+ def get_state(self):
455+ return self.state
456+
457+def get_wired_devices():
458+ ### Populate Device View (temporary)
459+ device1 = Device()
460+ device1.type = DEVICE_TYPE_WIRED
461+ device1.state = DEVICE_STATE_OFFLINE
462+ ###
463+ devices = (device1,)
464+ return devices
465+
466+def get_wireless_devices():
467+ ### Populate Device View (temporary)
468+ device1 = Device()
469+ device1.type = DEVICE_TYPE_WIRELESS
470+ device1.state = DEVICE_STATE_ONLINE
471+ device2 = Device()
472+ device2.type = DEVICE_TYPE_WIRELESS
473+ device2.state = DEVICE_STATE_OFF
474+ ###
475+ devices = (device1, device2)
476+ return devices
477+
478+def get_mobile_devices():
479+ ### Populate Device View (temporary)
480+ device3 = Device()
481+ device3.type = DEVICE_TYPE_MOBILE
482+ device3.state = DEVICE_STATE_CONNECTED
483+ ###
484+ devices = (device3,)
485+ return devices
486+
487+def get_bluetooth_devices():
488+ ### Populate Device View (temporary)
489+ device4 = Device()
490+ device4.type = DEVICE_TYPE_BLUETOOTH
491+ device4.state = DEVICE_STATE_OFF
492+ ###
493+ devices = (device4,)
494+ return devices
495+
496
497=== added file 'src/settings/indicatorNetworkSettings/enums.py'
498--- src/settings/indicatorNetworkSettings/enums.py 1970-01-01 00:00:00 +0000
499+++ src/settings/indicatorNetworkSettings/enums.py 2010-12-13 14:13:17 +0000
500@@ -0,0 +1,43 @@
501+# Copyright (C) 2010 Canonical
502+#
503+# Authors:
504+# Andrew Higginson
505+#
506+# This program is free software; you can redistribute it and/or modify it under
507+# the terms of the GNU General Public License as published by the Free Software
508+# Foundation; version 3.
509+#
510+# This program is distributed in the hope that it will be useful, but WITHOUT
511+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
512+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
513+# details.
514+#
515+# You should have received a copy of the GNU General Public License along with
516+# this program; if not, write to the Free Software Foundation, Inc.,
517+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
518+
519+from gettext import gettext as _
520+
521+DEVICE_TYPES = (DEVICE_TYPE_WIRED, DEVICE_TYPE_WIRELESS, \
522+ DEVICE_TYPE_BLUETOOTH, DEVICE_TYPE_MOBILE) = range(4)
523+
524+DEVICE_TYPE_NAMES = {DEVICE_TYPE_WIRED:_("Wired"),
525+ DEVICE_TYPE_WIRELESS:_("Wireless"),
526+ DEVICE_TYPE_BLUETOOTH:_("Bluetooth"),
527+ DEVICE_TYPE_MOBILE:_("Mobile Broadband")}
528+
529+DEVICE_TYPE_LNAMES = {DEVICE_TYPE_WIRED:"wired",
530+ DEVICE_TYPE_WIRELESS:"wireless",
531+ DEVICE_TYPE_BLUETOOTH:"bluetooth",
532+ DEVICE_TYPE_MOBILE:"mobile"}
533+
534+DEVICE_TYPE_ICONS = {DEVICE_TYPE_WIRED:"network-wired",
535+ DEVICE_TYPE_WIRELESS:"network-wireless",
536+ DEVICE_TYPE_BLUETOOTH:"bluetooth-active",
537+ DEVICE_TYPE_MOBILE:"gsm-3g-high"}
538+
539+DEVICE_STATE_OFF, DEVICE_STATE_OFFLINE, DEVICE_STATE_CONNECTED, \
540+ DEVICE_STATE_ONLINE = range(4)
541+
542+
543+GENERIC_DEVICE_ICON = DEVICE_TYPE_ICONS[DEVICE_TYPE_WIRED]
544
545=== added directory 'src/settings/indicatorNetworkSettings/frontend'
546=== added file 'src/settings/indicatorNetworkSettings/frontend/Makefile.am'
547--- src/settings/indicatorNetworkSettings/frontend/Makefile.am 1970-01-01 00:00:00 +0000
548+++ src/settings/indicatorNetworkSettings/frontend/Makefile.am 2010-12-13 14:13:17 +0000
549@@ -0,0 +1,9 @@
550+SUBDIRS = \
551+ pages \
552+ widgets
553+
554+# indicator-network-settings
555+insdir = $(pkgdatadir)/indicatorNetworkSettings/frontend
556+ins_PYTHON = \
557+ __init__.py \
558+ utils.py
559
560=== added file 'src/settings/indicatorNetworkSettings/frontend/__init__.py'
561--- src/settings/indicatorNetworkSettings/frontend/__init__.py 1970-01-01 00:00:00 +0000
562+++ src/settings/indicatorNetworkSettings/frontend/__init__.py 2010-12-13 14:13:17 +0000
563@@ -0,0 +1,1 @@
564+
565
566=== added directory 'src/settings/indicatorNetworkSettings/frontend/pages'
567=== added file 'src/settings/indicatorNetworkSettings/frontend/pages/Makefile.am'
568--- src/settings/indicatorNetworkSettings/frontend/pages/Makefile.am 1970-01-01 00:00:00 +0000
569+++ src/settings/indicatorNetworkSettings/frontend/pages/Makefile.am 2010-12-13 14:13:17 +0000
570@@ -0,0 +1,5 @@
571+# indicator-network-settings
572+insdir = $(pkgdatadir)/indicatorNetworkSettings/frontend/pages
573+ins_PYTHON = \
574+ connections.py \
575+ __init__.py
576
577=== added file 'src/settings/indicatorNetworkSettings/frontend/pages/__init__.py'
578=== added file 'src/settings/indicatorNetworkSettings/frontend/pages/connections.py'
579--- src/settings/indicatorNetworkSettings/frontend/pages/connections.py 1970-01-01 00:00:00 +0000
580+++ src/settings/indicatorNetworkSettings/frontend/pages/connections.py 2010-12-13 14:13:17 +0000
581@@ -0,0 +1,111 @@
582+# Copyright (C) 2010 Canonical
583+#
584+# Authors:
585+# Andrew Higginson
586+#
587+# This program is free software; you can redistribute it and/or modify it under
588+# the terms of the GNU General Public License as published by the Free Software
589+# Foundation; version 3.
590+#
591+# This program is distributed in the hope that it will be useful, but WITHOUT
592+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
593+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
594+# details.
595+#
596+# You should have received a copy of the GNU General Public License along with
597+# this program; if not, write to the Free Software Foundation, Inc.,
598+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
599+
600+import gobject
601+
602+from indicatorNetworkSettings.frontend.widgets.device_boxes.wired \
603+ import WiredBox
604+from indicatorNetworkSettings.frontend.widgets.device_boxes.wireless \
605+ import WirelessBox
606+from indicatorNetworkSettings.frontend.widgets.device_boxes.bluetooth \
607+ import BluetoothBox
608+from indicatorNetworkSettings.frontend.widgets.device_boxes.mobile \
609+ import MobileBox
610+from indicatorNetworkSettings.frontend.widgets.deviceview \
611+ import DeviceView, DeviceStore
612+
613+from indicatorNetworkSettings.backend.device import *
614+from indicatorNetworkSettings.enums import *
615+
616+class ConnectionsPage(gobject.GObject):
617+ def __init__(self, app, datadir):
618+ super(ConnectionsPage, self).__init__()
619+
620+ self.app = app
621+ self.alignment = app.alignment_connections
622+ self.viewed = False
623+
624+ # Create LHS
625+ ## Create device view
626+ device_store = DeviceStore(app.icons)
627+ self.treeview_devices = DeviceView(device_store)
628+ ## Pack it
629+ app.scrolledwindow_c_devices.add(self.treeview_devices)
630+ ## Connect signals to callbacks
631+ self.treeview_devices.connect("selection-changed",
632+ self._on_treeview_devices_selection_changed)
633+ self.treeview_devices.connect("reordered",
634+ self._on_treeview_devices_reordered)
635+
636+ wired_devices = get_wired_devices()
637+ wireless_devices = get_wireless_devices()
638+ mobile_devices = get_mobile_devices()
639+ bluetooth_devices = get_bluetooth_devices()
640+
641+ for device in wired_devices:
642+ box = WiredBox(device, datadir)
643+ self.app.notebook_c_right.append_page(box)
644+ self.add_device(device, box)
645+
646+ for device in wireless_devices:
647+ box = WirelessBox(device, datadir)
648+ self.app.notebook_c_right.append_page(box)
649+ self.add_device(device, box)
650+
651+ for device in mobile_devices:
652+ box = MobileBox(device, datadir)
653+ self.app.notebook_c_right.append_page(box)
654+ self.add_device(device, box)
655+
656+ for device in bluetooth_devices:
657+ box = BluetoothBox(device, datadir)
658+ self.app.notebook_c_right.append_page(box)
659+ self.add_device(device, box)
660+
661+ # Order the RHS notebook pages inaccordance with the deviceview
662+ self._on_treeview_devices_reordered(self.treeview_devices)
663+
664+ # Private Functions
665+
666+ # Public Functions
667+
668+ def add_device(self, device, box):
669+ liststore = self.treeview_devices.get_model()
670+ liststore.append(device, box)
671+
672+ # Callbacks
673+
674+ def on_first_expose(self):
675+ if not self.viewed:
676+ self.treeview_devices.get_selection().select_path((0,))
677+ self.viewed = True
678+
679+ def _on_treeview_devices_selection_changed(self, widget, selection):
680+ (model, iter_) = selection.get_selected()
681+
682+ if iter_:
683+ i = model.get_path(iter_)[0]
684+ self.app.notebook_c_right.set_current_page(i)
685+
686+ def _on_treeview_devices_reordered(self, widget):
687+ i = 0
688+ model = widget.get_model()
689+ for device in model:
690+ page = device[DeviceStore.COL_SETTINGS_BOX]
691+ self.app.notebook_c_right.reorder_child(page, i)
692+ i += 1
693
694=== added file 'src/settings/indicatorNetworkSettings/frontend/utils.py'
695--- src/settings/indicatorNetworkSettings/frontend/utils.py 1970-01-01 00:00:00 +0000
696+++ src/settings/indicatorNetworkSettings/frontend/utils.py 2010-12-13 14:13:17 +0000
697@@ -0,0 +1,34 @@
698+# Copyright (C) 2010 Canonical
699+#
700+# Authors:
701+# Andrew Higginson
702+#
703+# This program is free software; you can redistribute it and/or modify it under
704+# the terms of the GNU General Public License as published by the Free Software
705+# Foundation; version 3.
706+#
707+# This program is distributed in the hope that it will be useful, but WITHOUT
708+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
709+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
710+# details.
711+#
712+# You should have received a copy of the GNU General Public License along with
713+# this program; if not, write to the Free Software Foundation, Inc.,
714+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
715+
716+import os
717+import sys
718+import gtk
719+
720+def setup_ui(self, datadir, name):
721+ builder = gtk.Builder()
722+ builder.set_translation_domain("indicator-network-settings")
723+ path = os.path.join(datadir, "ui", "%s.ui" % name)
724+ builder.add_from_file(path)
725+ builder.connect_signals(self)
726+ for object_ in builder.get_objects():
727+ if issubclass(type(object_), gtk.Buildable):
728+ name = gtk.Buildable.get_name(object_)
729+ setattr(self, name, object_)
730+ else:
731+ print >> sys.stderr, "WARNING: can not get name for '%s'" % object_
732
733=== added directory 'src/settings/indicatorNetworkSettings/frontend/widgets'
734=== added file 'src/settings/indicatorNetworkSettings/frontend/widgets/Makefile.am'
735--- src/settings/indicatorNetworkSettings/frontend/widgets/Makefile.am 1970-01-01 00:00:00 +0000
736+++ src/settings/indicatorNetworkSettings/frontend/widgets/Makefile.am 2010-12-13 14:13:17 +0000
737@@ -0,0 +1,6 @@
738+SUBDIRS = device_boxes
739+
740+# indicator-network-settings
741+insdir = $(pkgdatadir)/indicatorNetworkSettings/frontend/widgets
742+ins_PYTHON = cellrenderers.py deviceview.py toggleswitch.py connectionview.py __init__.py
743+
744
745=== added file 'src/settings/indicatorNetworkSettings/frontend/widgets/__init__.py'
746--- src/settings/indicatorNetworkSettings/frontend/widgets/__init__.py 1970-01-01 00:00:00 +0000
747+++ src/settings/indicatorNetworkSettings/frontend/widgets/__init__.py 2010-12-13 14:13:17 +0000
748@@ -0,0 +1,1 @@
749+
750
751=== added file 'src/settings/indicatorNetworkSettings/frontend/widgets/cellrenderers.py'
752--- src/settings/indicatorNetworkSettings/frontend/widgets/cellrenderers.py 1970-01-01 00:00:00 +0000
753+++ src/settings/indicatorNetworkSettings/frontend/widgets/cellrenderers.py 2010-12-13 14:13:17 +0000
754@@ -0,0 +1,210 @@
755+#!/usr/bin/env python
756+# -*- coding: utf-8 -*-
757+#
758+# Copyright (C) 2010 Canonical
759+#
760+# Authors:
761+# Andrew Higginson
762+#
763+# This program is free software; you can redistribute it and/or modify it under
764+# the terms of the GNU General Public License as published by the Free Software
765+# Foundation; version 3.
766+#
767+# This program is distributed in the hope that it will be useful, but WITHOUT
768+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
769+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
770+# details.
771+#
772+# You should have received a copy of the GNU General Public License along with
773+# this program; if not, write to the Free Software Foundation, Inc.,
774+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
775+
776+import gtk
777+import gobject
778+
779+from math import pi
780+
781+PI = 3.1415926535897931
782+PI_OVER_180 = 0.017453292519943295
783+
784+class PinCellRenderer(gtk.GenericCellRenderer):
785+ __gproperties__ = {
786+ 'color': (gobject.TYPE_STRING,
787+ 'The color of the pin.',
788+ 'The color of the pin.',
789+ '#FFFFFF',
790+ gobject.PARAM_READWRITE
791+ ),
792+ }
793+
794+ RED_FILL = "#ef2929"
795+ RED_STROKE = "#a40000"
796+ GREEN_FILL = "#8ae234"
797+ GREEN_STROKE = "#4e9a06"
798+ YELLOW_FILL = "#fce94f"
799+ YELLOW_STROKE = "#c4a000"
800+ GREY_FILL = "#d3d7cf"
801+ GREY_STROKE = "#555753"
802+
803+ PIN_WIDTH = 8
804+ PIN_HEIGHT = 8
805+
806+ PIN_XPAD = 8
807+ PIN_YPAD = 8
808+
809+ CELL_WIDTH = PIN_WIDTH + PIN_XPAD
810+ CELL_HEIGHT = PIN_HEIGHT + PIN_YPAD
811+
812+ def __init__(self):
813+ super(PinCellRenderer, self).__init__()
814+
815+ def on_get_size(self, widget, cell_area):
816+ return 0, 0, self.CELL_WIDTH, self.CELL_HEIGHT
817+
818+ def do_set_property(self, pspec, value):
819+ setattr(self, pspec.name, value)
820+
821+ def do_get_property(self, pspec):
822+ return getattr(self, pspec.name)
823+
824+ def on_render(self, window, widget, background_area, cell_area,
825+ expose_area, flags):
826+ cr = window.cairo_create()
827+
828+ x = cell_area.x
829+ y = cell_area.y
830+
831+ y_offset = (cell_area.height - self.CELL_HEIGHT) / 2
832+
833+ cr.arc(self.CELL_WIDTH/2+x, self.CELL_HEIGHT/2+y+y_offset,
834+ self.PIN_WIDTH/2, 0, 2 * pi)
835+
836+ stroke_string = getattr(self, "%s_STROKE" % self.color.upper())
837+ stroke = gtk.gdk.Color(stroke_string)
838+ fill_string = getattr(self, "%s_FILL" % self.color.upper())
839+ fill = gtk.gdk.Color(fill_string)
840+
841+ cr.set_source_rgb(stroke.red / 65535.,
842+ stroke.green / 65535.,
843+ stroke.blue / 65535.)
844+ cr.stroke_preserve()
845+ cr.set_source_rgb(fill.red / 65535.,
846+ fill.green / 65535.,
847+ fill.blue / 65535.)
848+ cr.fill()
849+
850+class SignalStrengthCellRenderer(gtk.GenericCellRenderer):
851+ __gproperties__ = {
852+ 'signal': (gobject.TYPE_STRING,
853+ 'The color of the pin.',
854+ 'The color of the pin.',
855+ '#FFFFFF',
856+ gobject.PARAM_READWRITE
857+ ),
858+ }
859+
860+ BG_FILL = "#f2f1f0"
861+ BG_STROKE = "#ada9a4"
862+ FG_FILL = "#d6d4d2"
863+ FG_STROKE = "#ada9a4"
864+
865+ BAR_WIDTH = 50
866+ BAR_HEIGHT = 12
867+
868+ BAR_XPAD = 4
869+ BAR_YPAD = 5
870+
871+ CELL_WIDTH = BAR_WIDTH + BAR_XPAD * 2
872+ CELL_HEIGHT = BAR_HEIGHT + BAR_YPAD * 2
873+
874+ CORNER_RADIUS = 3
875+
876+ def __init__(self):
877+ super(SignalStrengthCellRenderer, self).__init__()
878+
879+ def on_get_size(self, widget, cell_area):
880+ return (0, 0, self.CELL_WIDTH, self.CELL_HEIGHT)
881+
882+ def do_set_property(self, pspec, value):
883+ setattr(self, pspec.name, value)
884+
885+ def do_get_property(self, pspec):
886+ return getattr(self, pspec.name)
887+
888+ def on_render(self, window, widget, background_area, cell_area,
889+ expose_area, flags):
890+ cr = window.cairo_create()
891+
892+ x = cell_area.x
893+ y = cell_area.y
894+
895+ x_offset = self.BAR_XPAD
896+ y_offset = self.BAR_YPAD
897+
898+ self._draw_rounded_rectangle(cr, x+x_offset, y+y_offset,
899+ x+x_offset+self.BAR_WIDTH, y+y_offset+self.BAR_HEIGHT,
900+ self.BG_FILL, self.BG_STROKE)
901+
902+ self._draw_rounded_rectangle(cr, x+x_offset, y+y_offset,
903+ x+x_offset+(int(self.BAR_WIDTH*float(self.signal))), y+y_offset+self.BAR_HEIGHT,
904+ self.FG_FILL, self.FG_STROKE)
905+
906+ def _draw_rounded_rectangle(self, cr, x, y, w, h, fill, stroke):
907+ self._layout_rounded_rectangle(cr, x, y, w, h)
908+
909+ stroke = gtk.gdk.Color(stroke)
910+ fill = gtk.gdk.Color(fill)
911+
912+ cr.set_source_rgb(stroke.red / 65535.,
913+ stroke.green / 65535.,
914+ stroke.blue / 65535.)
915+ cr.stroke_preserve()
916+
917+ cr.set_source_rgb(fill.red / 65535.,
918+ fill.green / 65535.,
919+ fill.blue / 65535.)
920+ cr.fill()
921+
922+ def _layout_rounded_rectangle(self, cr, x, y, w, h):
923+ r = self.CORNER_RADIUS
924+ cr.new_sub_path()
925+ cr.arc(r+x, r+y, r, PI, 270*PI_OVER_180)
926+ cr.arc(w-r, r+y, r, 270*PI_OVER_180, 0)
927+ cr.arc(w-r, h-r, r, 0, 90*PI_OVER_180)
928+ cr.arc(r+x, h-r, r, 90*PI_OVER_180, PI)
929+ cr.close_path()
930+
931+
932+
933+gobject.type_register(PinCellRenderer)
934+gobject.type_register(SignalStrengthCellRenderer)
935+
936+if __name__ == "__main__":
937+ window = gtk.Window()
938+
939+ treeview = gtk.TreeView()
940+
941+ # Main Column
942+ column = gtk.TreeViewColumn("Main")
943+ cr = PinCellRenderer()
944+ crs = SignalStrengthCellRenderer()
945+ crt = gtk.CellRendererText()
946+ column.pack_start(cr)
947+ column.pack_start(crs)
948+ column.pack_start(crt)
949+ column.set_attributes(cr, color=0)
950+ column.set_attributes(crs, signal=1)
951+ column.set_attributes(crt, text=2)
952+ treeview.append_column(column)
953+
954+ store = gtk.ListStore(str, float, str)
955+ store.append(["green", 0.25, "Hey"])
956+ store.append(["red", 0.5, "hi"])
957+ store.append(["yellow", 0.75, "ho"])
958+ store.append(["grey", 1.0, "ha"])
959+ treeview.set_model(store)
960+
961+ window.add(treeview)
962+ window.show_all()
963+ gtk.main()
964+
965
966=== added file 'src/settings/indicatorNetworkSettings/frontend/widgets/connectionview.py'
967--- src/settings/indicatorNetworkSettings/frontend/widgets/connectionview.py 1970-01-01 00:00:00 +0000
968+++ src/settings/indicatorNetworkSettings/frontend/widgets/connectionview.py 2010-12-13 14:13:17 +0000
969@@ -0,0 +1,78 @@
970+# Copyright (C) 2010 Canonical
971+#
972+# Authors:
973+# Andrew Higginson
974+#
975+# This program is free software; you can redistribute it and/or modify it under
976+# the terms of the GNU General Public License as published by the Free Software
977+# Foundation; version 3.
978+#
979+# This program is distributed in the hope that it will be useful, but WITHOUT
980+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
981+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
982+# details.
983+#
984+# You should have received a copy of the GNU General Public License along with
985+# this program; if not, write to the Free Software Foundation, Inc.,
986+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
987+
988+import gtk
989+import gobject
990+
991+from indicatorNetworkSettings.enums import *
992+from indicatorNetworkSettings.frontend.widgets.cellrenderers \
993+ import SignalStrengthCellRenderer
994+
995+from gettext import gettext as _
996+
997+class WirelessConnectionView(gtk.TreeView):
998+ def __init__(self, store):
999+ super(WirelessConnectionView, self).__init__()
1000+ self.set_model(store)
1001+
1002+ # Network Column (contains label)
1003+ column = gtk.TreeViewColumn(_("Network"))
1004+ cr_label = gtk.CellRendererText()
1005+ column.pack_start(cr_label, True)
1006+ column.set_attributes(cr_label,
1007+ markup=WirelessConnectionStore.COL_NETWORK)
1008+ column.set_expand(True)
1009+ self.append_column(column)
1010+
1011+ # Signal Column (contains signal indicator)
1012+ column = gtk.TreeViewColumn(_("Signal"))
1013+ cr_signal = SignalStrengthCellRenderer()
1014+ column.pack_start(cr_signal, True)
1015+ column.set_attributes(cr_signal,
1016+ signal=WirelessConnectionStore.COL_SIGNAL)
1017+ column.set_clickable(True)
1018+ column.set_sort_column_id(WirelessConnectionStore.COL_SIGNAL)
1019+ self.append_column(column)
1020+
1021+ # Last Used Column (contains label)
1022+ column = gtk.TreeViewColumn(_("Last Used"))
1023+ cr_label = gtk.CellRendererText()
1024+ column.pack_start(cr_label, True)
1025+ column.set_attributes(cr_label,
1026+ markup=WirelessConnectionStore.COL_LAST_USED)
1027+ self.append_column(column)
1028+
1029+ def get_selected_connection(self):
1030+ (model, iter_) = self.get_selection().get_selected()
1031+ if iter_:
1032+ return model.get_value(iter_, 0)
1033+ return None
1034+
1035+
1036+class WirelessConnectionStore(gtk.ListStore):
1037+
1038+ (COL_OBJ, COL_NETWORK, COL_SIGNAL, COL_LAST_USED) = range(4)
1039+
1040+ def __init__(self):
1041+ super(WirelessConnectionStore, self).__init__(
1042+ gobject.TYPE_PYOBJECT, str, str, str)
1043+
1044+ def append(self, obj, network, signal, last_used):
1045+ row_data = [obj, network, signal, last_used]
1046+ return super(WirelessConnectionStore, self).append(row_data)
1047+
1048
1049=== added directory 'src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes'
1050=== added file 'src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/Makefile.am'
1051--- src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/Makefile.am 1970-01-01 00:00:00 +0000
1052+++ src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/Makefile.am 2010-12-13 14:13:17 +0000
1053@@ -0,0 +1,3 @@
1054+# indicator-network-settings
1055+insdir = $(pkgdatadir)/indicatorNetworkSettings/frontend/widgets/device_boxes
1056+ins_PYTHON = bluetooth.py __init__.py mobile.py wired.py wireless.py
1057
1058=== added file 'src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/__init__.py'
1059--- src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/__init__.py 1970-01-01 00:00:00 +0000
1060+++ src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/__init__.py 2010-12-13 14:13:17 +0000
1061@@ -0,0 +1,30 @@
1062+# Copyright (C) 2010 Canonical
1063+#
1064+# Authors:
1065+# Andrew Higginson
1066+#
1067+# This program is free software; you can redistribute it and/or modify it under
1068+# the terms of the GNU General Public License as published by the Free Software
1069+# Foundation; version 3.
1070+#
1071+# This program is distributed in the hope that it will be useful, but WITHOUT
1072+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1073+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1074+# details.
1075+#
1076+# You should have received a copy of the GNU General Public License along with
1077+# this program; if not, write to the Free Software Foundation, Inc.,
1078+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1079+
1080+import gtk
1081+
1082+class DeviceBox(gtk.VBox):
1083+ """A gtk.VBox which holds all of the widgets to control a device."""
1084+
1085+ def __init__(self, device, datadir):
1086+ super(DeviceBox, self).__init__(spacing=12)
1087+ self.device = device
1088+ self.device.connect("state-changed", self._on_device_state_changed)
1089+
1090+ def _on_device_state_changed(self, device, state):
1091+ pass
1092
1093=== added file 'src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/bluetooth.py'
1094--- src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/bluetooth.py 1970-01-01 00:00:00 +0000
1095+++ src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/bluetooth.py 2010-12-13 14:13:17 +0000
1096@@ -0,0 +1,35 @@
1097+# Copyright (C) 2010 Canonical
1098+#
1099+# Authors:
1100+# Andrew Higginson
1101+#
1102+# This program is free software; you can redistribute it and/or modify it under
1103+# the terms of the GNU General Public License as published by the Free Software
1104+# Foundation; version 3.
1105+#
1106+# This program is distributed in the hope that it will be useful, but WITHOUT
1107+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1108+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1109+# details.
1110+#
1111+# You should have received a copy of the GNU General Public License along with
1112+# this program; if not, write to the Free Software Foundation, Inc.,
1113+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1114+
1115+import gtk
1116+import locale
1117+
1118+from indicatorNetworkSettings.enums import *
1119+
1120+from gettext import gettext as _
1121+
1122+class BluetoothBox(gtk.VBox):
1123+
1124+ """A gtk.VBox which holds all of thw widgets to control a bluetooth
1125+ device."""
1126+
1127+ def __init__(self, device, datadir):
1128+ super(BluetoothBox, self).__init__(spacing=12)
1129+ self.device = device
1130+
1131+ # Callbacks
1132
1133=== added file 'src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/mobile.py'
1134--- src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/mobile.py 1970-01-01 00:00:00 +0000
1135+++ src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/mobile.py 2010-12-13 14:13:17 +0000
1136@@ -0,0 +1,121 @@
1137+# -*- coding: utf-8 -*-
1138+# Copyright (C) 2010 Canonical
1139+#
1140+# Authors:
1141+# Andrew Higginson
1142+#
1143+# This program is free software; you can redistribute it and/or modify it under
1144+# the terms of the GNU General Public License as published by the Free Software
1145+# Foundation; version 3.
1146+#
1147+# This program is distributed in the hope that it will be useful, but WITHOUT
1148+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1149+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1150+# details.
1151+#
1152+# You should have received a copy of the GNU General Public License along with
1153+# this program; if not, write to the Free Software Foundation, Inc.,
1154+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1155+
1156+import gtk
1157+
1158+from indicatorNetworkSettings.frontend.widgets.device_boxes \
1159+ import DeviceBox
1160+from indicatorNetworkSettings.frontend.widgets.toggleswitch \
1161+ import InfoBox, ToggleSwitch
1162+
1163+from indicatorNetworkSettings.enums import *
1164+import indicatorNetworkSettings.frontend.utils as utils
1165+
1166+from gettext import gettext as _
1167+
1168+class MobileBox(DeviceBox):
1169+
1170+ """A gtk.VBox which holds all of the widgets to control a mobile
1171+ device. It contains an InfoBox and ToggleSwitch to control and
1172+ monitor the state of the mobile device, and a set of widgets
1173+ to enter details about the mobile network to connect to."""
1174+
1175+ SENSITIVE_WIDGETS = ["label_apn_place", "label_apn",
1176+ "label_pin_auth", "checkbutton_show_pin"]
1177+
1178+ def __init__(self, device, datadir):
1179+ super(MobileBox, self).__init__(device, datadir)
1180+
1181+ # Infobox and Togglswitch
1182+ ## Creation
1183+ self.infobox = InfoBox(spacing=12)
1184+ self.toggleswitch = ToggleSwitch((_("ON"), _("OFF")))
1185+ self.label_status = gtk.Label()
1186+ ## Padding and alignment
1187+ self.label_status.set_alignment(0, 0.5)
1188+ self.infobox.set_border_width(10)
1189+ ## Packing
1190+ self.infobox.pack_start(self.label_status, True, True)
1191+ self.infobox.pack_start(self.toggleswitch, False, True)
1192+ self.pack_start(self.infobox, False, False)
1193+ ## Connect signals
1194+ self.toggleswitch.connect("toggled", self._on_toggleswitch_toggled)
1195+
1196+ # Network Settings
1197+ ## Creation
1198+ utils.setup_ui(self, datadir, "mobile_box")
1199+ ## Packing
1200+ self.pack_start(self.table_settings, True, True)
1201+
1202+ self._update_widget_states(self.device.get_state())
1203+ self._on_checkbutton_show_pin_toggled(self.checkbutton_show_pin)
1204+
1205+ # Private Functions
1206+ def _update_widget_states(self, state):
1207+ if state == DEVICE_STATE_CONNECTED:
1208+ device_editable = True
1209+ settings_editable = False
1210+ toggleswitch_state = True
1211+ status_text = _("Connected to “Vodafone UK”.")
1212+ elif state == DEVICE_STATE_ONLINE:
1213+ device_editable = True
1214+ settings_editable = False
1215+ toggleswitch_state = True
1216+ status_text = _("Connected to the Internet on “Vodafone UK”.")
1217+ elif state == DEVICE_STATE_OFF:
1218+ device_editable = False
1219+ settings_editable = True
1220+ toggleswitch_state = False
1221+ status_text = _("The Mobile Broadband device is powered off.")
1222+ elif state == DEVICE_STATE_OFFLINE:
1223+ device_editable = True
1224+ settings_editable = True
1225+ toggleswitch_state = False
1226+ status_text = _("Mobile Broadband is offline.")
1227+
1228+ self.toggleswitch.set_sensitive(device_editable)
1229+ self.toggleswitch.set_active(toggleswitch_state)
1230+ self.label_status.set_text(status_text)
1231+
1232+ self.table_settings.foreach(self._sensitise_widgets,
1233+ (device_editable, settings_editable))
1234+
1235+ def _sensitise_widgets(self, widget, data):
1236+ (device_editable, settings_editable) = data
1237+ name = gtk.Buildable.get_name(widget)
1238+ if name in self.SENSITIVE_WIDGETS:
1239+ widget.set_sensitive(device_editable)
1240+ elif not isinstance(widget, gtk.Box):
1241+ widget.set_sensitive(settings_editable)
1242+ else:
1243+ widget.foreach(self._sensitise_widgets,
1244+ (device_editable, settings_editable))
1245+
1246+ # Callbacks
1247+ def _on_device_state_changed(self, device, state):
1248+ self._update_widget_states(state)
1249+
1250+ def _on_toggleswitch_toggled(self, widget):
1251+ if widget.get_active():
1252+ self.device.set_state(DEVICE_STATE_CONNECTED)
1253+ else:
1254+ self.device.set_state(DEVICE_STATE_OFFLINE)
1255+
1256+ def _on_checkbutton_show_pin_toggled(self, widget):
1257+ self.entry_pin.set_visibility(widget.get_active())
1258
1259=== added file 'src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/wired.py'
1260--- src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/wired.py 1970-01-01 00:00:00 +0000
1261+++ src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/wired.py 2010-12-13 14:13:17 +0000
1262@@ -0,0 +1,35 @@
1263+# Copyright (C) 2010 Canonical
1264+#
1265+# Authors:
1266+# Andrew Higginson
1267+#
1268+# This program is free software; you can redistribute it and/or modify it under
1269+# the terms of the GNU General Public License as published by the Free Software
1270+# Foundation; version 3.
1271+#
1272+# This program is distributed in the hope that it will be useful, but WITHOUT
1273+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1274+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1275+# details.
1276+#
1277+# You should have received a copy of the GNU General Public License along with
1278+# this program; if not, write to the Free Software Foundation, Inc.,
1279+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1280+
1281+import gtk
1282+import locale
1283+
1284+from indicatorNetworkSettings.enums import *
1285+
1286+from gettext import gettext as _
1287+
1288+class WiredBox(gtk.VBox):
1289+
1290+ """A gtk.VBox which holds all of the widgets to control a wired
1291+ device."""
1292+
1293+ def __init__(self, device, datadir):
1294+ super(WiredBox, self).__init__(spacing=12)
1295+ self.device = device
1296+
1297+ # Callbacks
1298
1299=== added file 'src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/wireless.py'
1300--- src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/wireless.py 1970-01-01 00:00:00 +0000
1301+++ src/settings/indicatorNetworkSettings/frontend/widgets/device_boxes/wireless.py 2010-12-13 14:13:17 +0000
1302@@ -0,0 +1,134 @@
1303+# Copyright (C) 2010 Canonical
1304+#
1305+# Authors:
1306+# Andrew Higginson
1307+#
1308+# This program is free software; you can redistribute it and/or modify it under
1309+# the terms of the GNU General Public License as published by the Free Software
1310+# Foundation; version 3.
1311+#
1312+# This program is distributed in the hope that it will be useful, but WITHOUT
1313+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1314+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1315+# details.
1316+#
1317+# You should have received a copy of the GNU General Public License along with
1318+# this program; if not, write to the Free Software Foundation, Inc.,
1319+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1320+
1321+import gtk
1322+import locale
1323+
1324+from indicatorNetworkSettings.frontend.widgets.device_boxes \
1325+ import DeviceBox
1326+from indicatorNetworkSettings.frontend.widgets.connectionview \
1327+ import WirelessConnectionView, WirelessConnectionStore
1328+from indicatorNetworkSettings.frontend.widgets.toggleswitch \
1329+ import InfoBox, ToggleSwitch
1330+
1331+from indicatorNetworkSettings.backend.connection \
1332+ import get_remembered_wireless_connections
1333+
1334+from indicatorNetworkSettings.enums import *
1335+import indicatorNetworkSettings.frontend.utils as utils
1336+
1337+from gettext import gettext as _
1338+
1339+class WirelessBox(DeviceBox):
1340+
1341+ """A gtk.VBox which holds all of the widgets to control a wireless
1342+ device. It contains an InfoBox and ToggleSwitch to control and
1343+ monitor the state of the wireless device, and a
1344+ WirelessConnectionView to connect to and remember details for
1345+ wireless networks."""
1346+
1347+ def __init__(self, device, datadir):
1348+ super(WirelessBox, self).__init__(device, datadir)
1349+
1350+ # Infobox and Togglswitch
1351+ ## Creation
1352+ self.infobox = InfoBox(spacing=12)
1353+ self.toggleswitch = ToggleSwitch((_("ON"), _("OFF")))
1354+ self.label_status = gtk.Label()
1355+ ## Padding and alignment
1356+ self.label_status.set_alignment(0, 0.5)
1357+ self.infobox.set_border_width(10)
1358+ ## Packing
1359+ self.infobox.pack_start(self.label_status, True, True)
1360+ self.infobox.pack_start(self.toggleswitch, False, True)
1361+ self.pack_start(self.infobox, False, False)
1362+ ## Connect signals
1363+ self.toggleswitch.connect("toggled", self._on_toggleswitch_toggled)
1364+
1365+ # Network Settings
1366+ ## Creation
1367+ utils.setup_ui(self, datadir, "wireless_box")
1368+ ## Packing
1369+ self.pack_start(self.vbox_connections, True, True)
1370+
1371+ # Connection View
1372+ ## Creation
1373+ connection_store = WirelessConnectionStore()
1374+ self.treeview_connections = WirelessConnectionView(connection_store)
1375+ ## Packing
1376+ self.scrolledwindow_connections.add(self.treeview_connections)
1377+ ## Population
1378+ connections = get_remembered_wireless_connections(device)
1379+ for connection in connections:
1380+ self._add_connection(connection)
1381+
1382+ self._update_widget_states(self.device.get_state())
1383+
1384+ # Private Functions
1385+ def _update_widget_states(self, state):
1386+ if state == DEVICE_STATE_CONNECTED:
1387+ device_editable = True
1388+ settings_editable = True
1389+ toggleswitch_state = True
1390+ status_text = _("Wi-fi is on but not connected to the Internet.")
1391+ elif state == DEVICE_STATE_ONLINE:
1392+ device_editable = True
1393+ settings_editable = True
1394+ toggleswitch_state = True
1395+ status_text = _("Wi-fi is on and connected to the Internet.")
1396+ elif state == DEVICE_STATE_OFF:
1397+ device_editable = False
1398+ settings_editable = False
1399+ toggleswitch_state = False
1400+ status_text = _("The Wi-fi device is powered off.")
1401+ elif state == DEVICE_STATE_OFFLINE:
1402+ device_editable = True
1403+ settings_editable = False
1404+ toggleswitch_state = False
1405+ status_text = _("Wi-fi is offline.")
1406+
1407+ self.vbox_connections.set_sensitive(settings_editable)
1408+ self.toggleswitch.set_sensitive(device_editable)
1409+ self.toggleswitch.set_active(toggleswitch_state)
1410+ self.label_status.set_text(status_text)
1411+
1412+ def _add_connection(self, connection):
1413+ network = connection.network
1414+ signal = connection.signal
1415+ if connection.last_used:
1416+ date_format = locale.nl_langinfo(locale.D_FMT)
1417+ last_used = connection.last_used.strftime(date_format)
1418+ else:
1419+ last_used = _("Never")
1420+
1421+ liststore = self.treeview_connections.get_model()
1422+ liststore.append(connection, network, signal, last_used)
1423+
1424+ # Callbacks
1425+ def _on_device_state_changed(self, device, state):
1426+ self._update_widget_states(state)
1427+
1428+ def _on_toggleswitch_toggled(self, widget):
1429+ if widget.get_active():
1430+ self.device.set_state(DEVICE_STATE_CONNECTED)
1431+ else:
1432+ self.device.set_state(DEVICE_STATE_OFFLINE)
1433+
1434+ def _on_button_connect_clicked(self, widget):
1435+ connection = self.treeview_connections.get_selected_connection()
1436+ connection.connect_("password")
1437
1438=== added file 'src/settings/indicatorNetworkSettings/frontend/widgets/deviceview.py'
1439--- src/settings/indicatorNetworkSettings/frontend/widgets/deviceview.py 1970-01-01 00:00:00 +0000
1440+++ src/settings/indicatorNetworkSettings/frontend/widgets/deviceview.py 2010-12-13 14:13:17 +0000
1441@@ -0,0 +1,157 @@
1442+# Copyright (C) 2010 Canonical
1443+#
1444+# Authors:
1445+# Andrew Higginson
1446+#
1447+# This program is free software; you can redistribute it and/or modify it under
1448+# the terms of the GNU General Public License as published by the Free Software
1449+# Foundation; version 3.
1450+#
1451+# This program is distributed in the hope that it will be useful, but WITHOUT
1452+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1453+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1454+# details.
1455+#
1456+# You should have received a copy of the GNU General Public License along with
1457+# this program; if not, write to the Free Software Foundation, Inc.,
1458+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1459+
1460+import gtk
1461+import glib
1462+import gobject
1463+import pango
1464+
1465+from indicatorNetworkSettings.enums import *
1466+from indicatorNetworkSettings.frontend.widgets.cellrenderers \
1467+ import PinCellRenderer
1468+
1469+from gettext import gettext as _
1470+
1471+class DeviceView(gtk.TreeView):
1472+
1473+ __gsignals__ = {
1474+ "selection-changed" : (gobject.SIGNAL_RUN_LAST,
1475+ gobject.TYPE_NONE,
1476+ ([gobject.TYPE_PYOBJECT]),
1477+ ),
1478+ "reordered" : (gobject.SIGNAL_RUN_LAST,
1479+ gobject.TYPE_NONE,
1480+ (),
1481+ ),
1482+ }
1483+
1484+ def __init__(self, store):
1485+ super(DeviceView, self).__init__()
1486+ self.set_model(store)
1487+
1488+ # Device (main) Column (contains pin icon, type icon and label)
1489+ column = gtk.TreeViewColumn("Device")
1490+ cr_pin = PinCellRenderer()
1491+ cr_icon = gtk.CellRendererPixbuf()
1492+ cr_label = gtk.CellRendererText()
1493+ column.pack_start(cr_pin, False)
1494+ column.set_attributes(cr_pin, color=DeviceStore.COL_PIN)
1495+ column.pack_start(cr_icon, False)
1496+ column.set_attributes(cr_icon, pixbuf=DeviceStore.COL_ICON)
1497+ column.pack_start(cr_label, True)
1498+ column.set_attributes(cr_label, markup=DeviceStore.COL_LABEL)
1499+ cr_label.set_property("ellipsize", pango.ELLIPSIZE_END)
1500+ self.append_column(column)
1501+
1502+ self.set_headers_visible(False)
1503+ self.set_reorderable(True)
1504+
1505+ self._dragging = False
1506+
1507+ self.get_selection().connect("changed", self._on_selection_changed)
1508+ self.connect("drag-begin", self._on_drag_begin)
1509+ self.connect("drag-end", self._on_drag_end)
1510+ self.connect("drag-failed", self._on_drag_failed)
1511+
1512+ def _on_selection_changed(self, selection):
1513+ self.emit("selection-changed", selection)
1514+
1515+ def _on_drag_begin(self, drag_context, *data):
1516+ self._dragging = True
1517+
1518+ def _on_drag_failed(self, drag_context, *data):
1519+ self._dragging = False
1520+
1521+ def _on_drag_end(self, drag_context, *data):
1522+ if self._dragging:
1523+ self.emit("reordered")
1524+
1525+ def get_selected_device(self):
1526+ (model, iter_) = self.get_selection().get_selected()
1527+ if iter_:
1528+ return model.get_value(iter_, 0)
1529+ return None
1530+
1531+class DeviceStore(gtk.ListStore):
1532+
1533+ (COL_DEVICE_OBJ, COL_SETTINGS_BOX, COL_PIN, COL_ICON, COL_LABEL) = range(5)
1534+
1535+ def __init__(self, icons):
1536+ super(DeviceStore, self).__init__(gobject.TYPE_PYOBJECT,
1537+ gobject.TYPE_PYOBJECT, str,
1538+ gtk.gdk.Pixbuf, str)
1539+ self.icons = icons
1540+
1541+ def append(self, device, settings_box):
1542+ device.connect("state-changed", self._on_device_state_changed)
1543+
1544+ pin_color = self._get_pin_color(device.state)
1545+ caption = self._get_device_caption(device.state)
1546+ label = DEVICE_TYPE_NAMES[device.type]
1547+ icon = DEVICE_TYPE_ICONS[device.type]
1548+
1549+ markup = self._get_markup(label, caption)
1550+ try:
1551+ icon_pixbuf = self.icons.load_icon(icon, 16, 16)
1552+ except glib.GError:
1553+ icon_pixbuf = self.icons.load_icon(GENERIC_DEVICE_ICON, 16, 16)
1554+
1555+ row_data = [device, settings_box, pin_color, icon_pixbuf, markup]
1556+
1557+ return super(DeviceStore, self).append(row_data)
1558+
1559+ def _on_device_state_changed(self, device, state):
1560+ iter_ = self._get_iter_for_device(device)
1561+ pin_color = self._get_pin_color(state)
1562+ caption = self._get_device_caption(state)
1563+ label = DEVICE_TYPE_NAMES[device.type]
1564+
1565+ markup = self._get_markup(label, caption)
1566+
1567+ self.set_value(iter_, self.COL_PIN, pin_color)
1568+ self.set_value(iter_, self.COL_LABEL, markup)
1569+
1570+ def _get_iter_for_device(self, device):
1571+ for row in self:
1572+ if row[0] == device:
1573+ return row.iter
1574+
1575+ def _get_pin_color(self, state):
1576+ if state == DEVICE_STATE_OFF:
1577+ return "grey"
1578+ elif state == DEVICE_STATE_OFFLINE:
1579+ return "red"
1580+ elif state == DEVICE_STATE_CONNECTED:
1581+ return "yellow"
1582+ elif state == DEVICE_STATE_ONLINE:
1583+ return "green"
1584+
1585+ def _get_device_caption(self, state):
1586+ if state == DEVICE_STATE_OFF:
1587+ return _("Off")
1588+ elif state == DEVICE_STATE_OFFLINE:
1589+ return _("Offline")
1590+ elif state == DEVICE_STATE_CONNECTED:
1591+ return _("Connected")
1592+ elif state == DEVICE_STATE_ONLINE:
1593+ return _("Online")
1594+
1595+ def _get_markup(self, label, caption):
1596+ return "%s\n<span font_size=\"small\">%s</span>" % (label, caption)
1597+
1598+
1599
1600=== added file 'src/settings/indicatorNetworkSettings/frontend/widgets/toggleswitch.py'
1601--- src/settings/indicatorNetworkSettings/frontend/widgets/toggleswitch.py 1970-01-01 00:00:00 +0000
1602+++ src/settings/indicatorNetworkSettings/frontend/widgets/toggleswitch.py 2010-12-13 14:13:17 +0000
1603@@ -0,0 +1,529 @@
1604+#!/usr/bin/env python
1605+# -*- coding: utf-8 -*-
1606+#
1607+# Copyright (C) 2010 Canonical
1608+#
1609+# Authors:
1610+# Andrew Higginson
1611+#
1612+# This program is free software; you can redistribute it and/or modify it under
1613+# the terms of the GNU General Public License as published by the Free Software
1614+# Foundation; version 3.
1615+#
1616+# This program is distributed in the hope that it will be useful, but WITHOUT
1617+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1618+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1619+# details.
1620+#
1621+# You should have received a copy of the GNU General Public License along with
1622+# this program; if not, write to the Free Software Foundation, Inc.,
1623+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1624+
1625+import atk
1626+import gtk
1627+import gobject
1628+import cairo
1629+
1630+from gettext import gettext as _
1631+
1632+PI = 3.1415926535897931
1633+PI_OVER_180 = 0.017453292519943295
1634+
1635+class ToggleSwitch(gtk.EventBox):
1636+
1637+ """A switch containing the values ON and OFF (or user-inputed) that
1638+ hides the inactive value. It can be clicked or dragged to change
1639+ state, or through an enter/return keypress."""
1640+
1641+ __gsignals__ = {
1642+ "clicked" : (gobject.SIGNAL_RUN_LAST,
1643+ gobject.TYPE_NONE,
1644+ (),
1645+ ),
1646+ "toggled" : (gobject.SIGNAL_RUN_LAST,
1647+ gobject.TYPE_NONE,
1648+ (),
1649+ ),
1650+ }
1651+
1652+ # (In relation to the height of the covering rectangle)
1653+ LINE_HEIGHT_RATIO = 9/25.0
1654+ LINE_SPACING_RATIO = 5/38.0
1655+ CORNER_RADIUS = 3
1656+
1657+ ANIMATION_DURATION = 800
1658+
1659+ STATE_ACTIVE, STATE_INACTIVE = (True, False)
1660+
1661+ # (In relation to the width/height of the text)
1662+ TEXT_XPAD = 0.5
1663+ TEXT_YPAD = 0.55
1664+
1665+ # Used for storing Geometry of Widget
1666+ GEO = {}
1667+
1668+ def __init__(self, values=(_("ON"), _("OFF")), active=False):
1669+ super(ToggleSwitch, self).__init__()
1670+
1671+ self.set_visible_window(False)
1672+
1673+ # Accessibility info
1674+ self.atk = self.get_accessible()
1675+ self.atk.set_role(atk.ROLE_CHECK_BOX)
1676+
1677+ # Set events for the widget to receive
1678+ self.set_flags(gtk.CAN_FOCUS)
1679+ self.set_events(gtk.gdk.KEY_PRESS_MASK|
1680+ gtk.gdk.ENTER_NOTIFY_MASK|
1681+ gtk.gdk.LEAVE_NOTIFY_MASK|
1682+ gtk.gdk.BUTTON_PRESS_MASK|
1683+ gtk.gdk.BUTTON_RELEASE_MASK)
1684+
1685+ # Connect signls and callbacks
1686+ self.connect('style-set', self._on_style_set)
1687+ self.connect('expose-event', self._on_expose_event)
1688+ self.connect('button-press-event', self._on_press)
1689+ self.connect('button-release-event', self._on_release)
1690+ self.connect('key-release-event', self._on_key_release)
1691+ self.connect('enter-notify-event', self._on_enter)
1692+ self.connect('leave-notify-event', self._on_leave)
1693+ self.connect('motion-notify-event', self._on_motion_notify_event)
1694+
1695+ # Set values of the widget
1696+ self.set_values(values)
1697+ # Set default state of widget
1698+ self.state_ = active
1699+ # Allocate variables that will be used later
1700+ self._layout = None
1701+ self._animating = False
1702+ self._pressed = False
1703+
1704+ # If the covering rectangle needs to start on the right
1705+ # set the offset to -1
1706+ if self.state_ == self.STATE_ACTIVE:
1707+ self.x_movement_offset = -1
1708+ else:
1709+ self.x_movement_offset = 0
1710+
1711+ # Calculate the best size
1712+ calc_width, calc_height = self._calculate_size()
1713+ self.set_size_request(calc_width, calc_height)
1714+
1715+ # Private functions
1716+
1717+ def _calculate_size(self):
1718+ """Calculate the best size for the toggleswitch based on the
1719+ dimensions of the user's default font."""
1720+ self._layout = self.create_pango_layout('')
1721+
1722+ self._layout.set_text("ON")
1723+ text_width, text_height = self._layout.get_pixel_extents()[1][2:]
1724+
1725+ width = (text_width+(text_width*self.TEXT_XPAD*2))*2
1726+ height = text_height+(text_height*self.TEXT_YPAD*2)
1727+
1728+ return (int(width), int(height))
1729+
1730+
1731+ def _draw_widget(self, widget):
1732+ """Do the drawing of the actual widget."""
1733+ cr = widget.window.cairo_create()
1734+
1735+ # Store the dimensions of the widget for access throughout
1736+ self.GEO["x"] = widget.allocation.x
1737+ self.GEO["y"] = widget.allocation.y
1738+ self.GEO["x1"] = widget.allocation.x + 1
1739+ self.GEO["y1"] = widget.allocation.y + 1
1740+ self.GEO["width"] = widget.allocation.width - 3
1741+ self.GEO["height"] = widget.allocation.height - 3
1742+ self.GEO["x2"] = widget.allocation.x + 1 + widget.allocation.width - 5
1743+ self.GEO["y2"] = widget.allocation.y + 1 + widget.allocation.height - 5
1744+
1745+ # Draw clipping rectangle
1746+ self._layout_rounded_rectangle(cr, self.GEO["x"],
1747+ self.GEO["y"],
1748+ self.GEO["x"] + widget.allocation.width,
1749+ self.GEO["y"] + widget.allocation.height)
1750+ cr.clip()
1751+
1752+ # Draw the main background
1753+ self._draw_main_background(cr)
1754+
1755+ # Draw the text
1756+ self._draw_on_text()
1757+ self._draw_off_text()
1758+
1759+ # Draw the covering rectangle
1760+ self._draw_covering_rectangle(cr)
1761+
1762+ # Update ATK description, based on state
1763+ if self.state_ == self.STATE_ACTIVE:
1764+ self.atk.set_name(self.values[0])
1765+ else:
1766+ self.atk.set_name(self.values[1])
1767+
1768+ def _draw_main_background(self, cr):
1769+ x1 = self.GEO["x1"]
1770+ y1 = self.GEO["y1"]
1771+ x2 = self.GEO["x2"]
1772+ y2 = self.GEO["y2"]
1773+
1774+ # Don't change colour of background on hover or press
1775+ if self.state == gtk.STATE_PRELIGHT or self.state == gtk.STATE_ACTIVE:
1776+ state = gtk.STATE_NORMAL
1777+ else:
1778+ state = self.state
1779+
1780+ # Layout the outline of the whole widget
1781+ self._layout_rounded_rectangle(cr, x1, y1, x2, y2)
1782+ ## Select colours
1783+ fill = self.style.base[state]
1784+ stroke = self.style.dark[state]
1785+ ## Stroke and then fill it in
1786+ self._stroke_rounded_rectangle(cr, stroke)
1787+ self._fill_rounded_rectangle(cr, fill)
1788+
1789+ # Layout the left (highlighted) part
1790+ x1 = self.GEO["x1"]
1791+ x2 = self.GEO["x1"] + (self.GEO["width"]/2)
1792+ self._layout_rounded_rectangle(cr, x1, y1, x2, y2)
1793+ ## Select colours
1794+ fill = self.style.light[gtk.STATE_SELECTED]
1795+ stroke = self.style.mid[gtk.STATE_SELECTED]
1796+ ## Stroke and then fill it in
1797+ self._stroke_rounded_rectangle(cr, stroke)
1798+ self._fill_rounded_rectangle(cr, fill)
1799+
1800+ # Layout the right (normal) part
1801+ x1 = self.GEO["x2"] - (self.GEO["width"]/2)
1802+ x2 = self.GEO["x2"]
1803+ self._layout_rounded_rectangle(cr, x1, y1, x2, y2)
1804+ ## Select colours
1805+ fill = self.style.base[state]
1806+ stroke = self.style.dark[state]
1807+ ## Stroke and then fill it in
1808+ self._stroke_rounded_rectangle(cr, stroke)
1809+ self._fill_rounded_rectangle(cr, fill)
1810+
1811+
1812+ def _draw_covering_rectangle(self, cr, x_offset=0):
1813+ if self.x_movement_offset == -1:
1814+ self.x_movement_offset = self.GEO["width"] / 2 - 1
1815+ x1 = self.GEO["x1"] + self.x_movement_offset
1816+ x2 = (self.GEO["width"] / 2) + self.GEO["x1"] + self.x_movement_offset
1817+
1818+ y1 = self.GEO["y1"]
1819+ y2 = self.GEO["y2"]
1820+
1821+ stroke = self.style.dark[self.state]
1822+ self._layout_rounded_rectangle(cr, x1, y1, x2, y2)
1823+ self._stroke_rounded_rectangle(cr, stroke)
1824+
1825+ if self.state == gtk.STATE_INSENSITIVE:
1826+ fill = self.style.bg[self.state]
1827+ self._fill_rounded_rectangle(cr, fill)
1828+ else:
1829+ fill1 = self.style.light[self.state]
1830+ fill2 = self.style.mid[self.state]
1831+ linear = self._create_vertical_gradient(fill1, fill2, x1, x2, y1, y2)
1832+ self._fill_gradient_rounded_rectangle(cr, linear)
1833+
1834+ # Draw the vertical lines
1835+ fill_dark = self.style.dark[self.state]
1836+ fill_light = self.style.light[self.state]
1837+ height = round(self.GEO["height"]*self.LINE_HEIGHT_RATIO)
1838+ width = 1
1839+
1840+ spacing = int(self.LINE_SPACING_RATIO * (self.GEO["width"] / 2))
1841+ c_spacing = 0
1842+
1843+ x_offset = ((self.GEO["width"] / 2) - (6+(spacing*2)))/2 + 2
1844+ y_offset = (self.GEO["height"] - height)/2
1845+
1846+ for i in range(3):
1847+ self._draw_vertical_line(cr, x1+x_offset+c_spacing,
1848+ y1+y_offset, width, height, fill_dark)
1849+ self._draw_vertical_line(cr, x1+x_offset+c_spacing+1,
1850+ y1+y_offset, width, height, fill_light)
1851+ c_spacing += spacing
1852+
1853+
1854+ def _draw_vertical_line(self, cr, x1, y1, width, height, fill):
1855+ """Draw a vertical line on the covering rectangle"""
1856+ cr.rectangle(x1, y1, width, height)
1857+ cr.set_source_rgb(fill.red_float, fill.green_float, fill.blue_float)
1858+ cr.fill()
1859+
1860+ def _draw_on_text(self):
1861+ """Draw the ON (or otherwise) text"""
1862+ text = self.values[0]
1863+ gravity = "left"
1864+ self._draw_text_centered_text(text, gravity)
1865+
1866+ def _draw_off_text(self):
1867+ """Draw the OFF (or otherwise) text"""
1868+ text = self.values[1]
1869+ gravity = "right"
1870+ self._draw_text_centered_text(text, gravity)
1871+
1872+ def _draw_text_centered_text(self, text, gravity):
1873+ if not self._layout:
1874+ self._layout = self.create_pango_layout('')
1875+
1876+ self._layout.set_text(text)
1877+ text_width, text_height = self._layout.get_pixel_extents()[1][2:]
1878+
1879+ if self.x_movement_offset == -1:
1880+ if gravity == "right":
1881+ text_x_offset = (((self.GEO["width"]/2) - text_width) / 2) + (self.GEO["width"]/2)
1882+ elif gravity == "left":
1883+ text_x_offset = (((self.GEO["width"]/2) - text_width) / 2) + self.x_movement_offset
1884+ else:
1885+ if gravity == "right":
1886+ text_x_offset = (((self.GEO["width"]/2) - text_width) / 2) + (self.GEO["width"]/2) + self.x_movement_offset
1887+ elif gravity == "left":
1888+ text_x_offset = (((self.GEO["width"]/2) - text_width) / 2) + (self.x_movement_offset-(self.GEO["width"]/2))
1889+
1890+ text_y_offset = ((self.GEO["height"] - text_height) / 2)
1891+
1892+ self.style.paint_layout(self.window, self.state, True,
1893+ (self.GEO["x"], self.GEO["y"],
1894+ self.GEO["width"], self.GEO["height"]),
1895+ self, '',
1896+ int(self.GEO["x1"]+text_x_offset),
1897+ int(self.GEO["y1"]+text_y_offset),
1898+ self._layout)
1899+
1900+
1901+ def _layout_rounded_rectangle(self, cr, x, y, w, h):
1902+ r = self.CORNER_RADIUS
1903+ cr.new_sub_path()
1904+ cr.arc(r+x, r+y, r, PI, 270*PI_OVER_180)
1905+ cr.arc(w-r, r+y, r, 270*PI_OVER_180, 0)
1906+ cr.arc(w-r, h-r, r, 0, 90*PI_OVER_180)
1907+ cr.arc(r+x, h-r, r, 90*PI_OVER_180, PI)
1908+ cr.close_path()
1909+
1910+ def _fill_rounded_rectangle(self, cr, fill):
1911+ cr.set_source_rgb(fill.red_float,
1912+ fill.green_float,
1913+ fill.blue_float)
1914+ cr.fill()
1915+
1916+ def _fill_gradient_rounded_rectangle(self, cr, fill):
1917+ cr.set_source(fill)
1918+ cr.fill()
1919+
1920+ def _stroke_rounded_rectangle(self, cr, stroke):
1921+ cr.set_source_rgb(stroke.red_float,
1922+ stroke.green_float,
1923+ stroke.blue_float)
1924+ cr.stroke_preserve()
1925+
1926+ def _create_vertical_gradient(self, color1, color2, x1, x2, y1, y2):
1927+ linear = cairo.LinearGradient(x1, y1, x1, y2)
1928+ linear.add_color_stop_rgba(0.00, color1.red_float,
1929+ color1.green_float,
1930+ color1.blue_float, 1)
1931+ linear.add_color_stop_rgba(0.8, color2.red_float,
1932+ color2.green_float,
1933+ color2.blue_float, 1)
1934+ return linear
1935+
1936+ def _increment_movement(self, state):
1937+ if state == self.STATE_ACTIVE:
1938+ increment = 1
1939+ criterion = self.x_movement_offset == (self.GEO["x2"] - (self.GEO["width"]/2) - self.GEO["x1"])
1940+ else:
1941+ increment = -1
1942+ criterion = self.x_movement_offset == 0
1943+
1944+ if criterion:
1945+ self._animating = False
1946+ self.queue_draw()
1947+ return False
1948+ else:
1949+ self.x_movement_offset += increment
1950+ self.queue_draw()
1951+ return True
1952+
1953+ # Callbacks
1954+ def _on_style_set(self, widget, event):
1955+ # Re-calculate the best size
1956+ calc_width, calc_height = self._calculate_size()
1957+ self.set_size_request(calc_width, calc_height)
1958+
1959+ def _on_expose_event(self, widget, event):
1960+ self._draw_widget(widget)
1961+
1962+ def _on_press(self, widget, event):
1963+ self.set_state(gtk.STATE_ACTIVE)
1964+ if event.x < self.GEO["width"]/2:
1965+ self.offset = event.x
1966+ elif event.x > self.GEO["width"]/2:
1967+ self.offset = event.x - self.GEO["width"]/2
1968+
1969+ def _on_release(self, widget, event):
1970+ if not self._animating:
1971+ if self._pressed:
1972+ if self.x_movement_offset <= self.GEO["width"] / 4:
1973+ gobject.timeout_add(5, self._increment_movement,
1974+ self.STATE_INACTIVE)
1975+ self.state_ = self.STATE_INACTIVE
1976+ self.emit('toggled')
1977+ elif self.x_movement_offset >= self.GEO["width"] / 4:
1978+ gobject.timeout_add(5, self._increment_movement,
1979+ self.STATE_ACTIVE)
1980+ self.state_ = self.STATE_ACTIVE
1981+ self.emit('toggled')
1982+ self._pressed = False
1983+ self.offset = 0
1984+ else:
1985+ self.set_state(gtk.STATE_PRELIGHT)
1986+ self.state_ = not self.state_
1987+ self.emit('clicked')
1988+ self.emit('toggled')
1989+ gobject.timeout_add(5, self._increment_movement,
1990+ self.state_)
1991+ self._pressed = False
1992+ self._animating = True
1993+
1994+ def _on_motion_notify_event(self, widget, event):
1995+ self._pressed = True
1996+ if event.x - self.offset < 0:
1997+ self.x_movement_offset = 0
1998+ elif event.x - self.offset >= (self.GEO["width"]/2 - 1):
1999+ self.x_movement_offset = self.GEO["width"]/2 -1
2000+ else:
2001+ self.x_movement_offset = event.x - self.offset
2002+ self.queue_draw()
2003+
2004+ def _on_key_release(self, widget, event):
2005+ if widget.has_focus():
2006+ if event.keyval == gtk.keysyms.Return or \
2007+ event.keyval == gtk.keysyms.KP_Enter:
2008+ self.toggled()
2009+
2010+ def _on_enter(self, widget, event):
2011+ self.set_state(gtk.STATE_PRELIGHT)
2012+
2013+ def _on_leave(self, widget, event):
2014+ self.set_state(gtk.STATE_NORMAL)
2015+
2016+ # Public functions
2017+
2018+ def get_active(self):
2019+ return self.state_
2020+
2021+ def set_active(self, state):
2022+ # If the widget is not yet realized, don't bother animating
2023+ if self.get_window() == None:
2024+ if state:
2025+ self.x_movement_offset = -1
2026+ else:
2027+ self.x_movement_offset = 0
2028+ self.queue_draw()
2029+ self.state_ = state
2030+ # Otherwise if we are not already animating, change the state
2031+ elif not self._animating:
2032+ self._animating = True
2033+ self._on_release(self, None)
2034+
2035+ def set_values(self, values):
2036+ # If the variable values is a tuple of length 2, and type string
2037+ # set the widget's values property to it.
2038+ if (len(values) == 2) and (type(values) == tuple):
2039+ if (type(values[0]) == str) and (type(values[1]) == str):
2040+ self.values = values
2041+ return
2042+ # Otherwise raise a Type error
2043+ raise TypeError("ToggleSwitch.set_values() argument 1 must be " + \
2044+ "String Tuple of length 2, not %s." % type(values))
2045+
2046+ def toggled(self):
2047+ self._on_release(self, None)
2048+
2049+ def pressed(self):
2050+ self._on_press(self, None)
2051+
2052+ def clicked(self):
2053+ self._on_release(self, None)
2054+
2055+ def enter(self):
2056+ self._on_enter(self, None)
2057+
2058+ def leave(self):
2059+ self._on_leave(self, None)
2060+
2061+class InfoBox(gtk.HBox):
2062+ """A gtk.HBox that is filled with the mid-colour and stroked with
2063+ the dark colour from a user's gtk theme so that it stands out."""
2064+
2065+ YPAD = 1
2066+ XPAD = 1
2067+
2068+ def __init__(self, homogeneous=False, spacing=0):
2069+ super(InfoBox, self).__init__(homogeneous, spacing)
2070+ self.connect('expose-event', self._on_expose_event)
2071+
2072+ def _on_expose_event(self, widget, event):
2073+ cr = widget.window.cairo_create()
2074+
2075+ # Get geometry
2076+ x = widget.allocation.x + self.XPAD
2077+ y = widget.allocation.y + self.YPAD
2078+ width = widget.allocation.width - (self.XPAD * 2)
2079+ height = widget.allocation.height - (self.YPAD * 2)
2080+
2081+ # Fill with the mid color from the current gtk theme
2082+ fill = self.style.mid[self.state]
2083+ # Fill with the dark color from the current gtk theme
2084+ stroke = self.style.dark[self.state]
2085+
2086+ # Layout the rectangle
2087+ cr.rectangle(x, y, width, height)
2088+ # Stroke the outline
2089+ cr.set_source_rgb(stroke.red_float, stroke.green_float,
2090+ stroke.blue_float)
2091+ cr.stroke_preserve()
2092+ # Fill it in
2093+ cr.set_source_rgb(fill.red_float, fill.green_float,
2094+ fill.blue_float)
2095+ cr.fill()
2096+
2097+if __name__ == "__main__":
2098+ def on_toggle_switch_clicked(widget):
2099+ print widget.get_active()
2100+
2101+ def do():
2102+ s.toggled()
2103+ return True
2104+
2105+ w = gtk.Window()
2106+ v = gtk.VBox()
2107+ h = gtk.HBox()
2108+ i = InfoBox(spacing=12)
2109+ s = ToggleSwitch()
2110+ si = ToggleSwitch()
2111+ si.set_sensitive(False)
2112+ l = gtk.Label("Wi-fi is on and connected to the Internet.")
2113+
2114+ gobject.timeout_add(3000, do)
2115+
2116+ w.connect("delete-event", gtk.main_quit)
2117+ s.connect("clicked", on_toggle_switch_clicked)
2118+
2119+ v.set_border_width(10)
2120+ w.set_default_size(200, 200)
2121+
2122+ i.pack_start(l, False)
2123+ i.pack_start(s, False, False)
2124+ i.pack_start(si, False, False)
2125+ i.set_border_width(12)
2126+ h.pack_start(i)
2127+ v.pack_start(h, False, False)
2128+ w.add(v)
2129+
2130+ w.show_all()
2131+ gtk.main()
2132+
2133
2134=== added file 'src/settings/indicatorNetworkSettings/utils.py'
2135--- src/settings/indicatorNetworkSettings/utils.py 1970-01-01 00:00:00 +0000
2136+++ src/settings/indicatorNetworkSettings/utils.py 2010-12-13 14:13:17 +0000
2137@@ -0,0 +1,18 @@
2138+# Copyright (C) 2010 Canonical
2139+#
2140+# Authors:
2141+# Andrew Higginson
2142+#
2143+# This program is free software; you can redistribute it and/or modify it under
2144+# the terms of the GNU General Public License as published by the Free Software
2145+# Foundation; version 3.
2146+#
2147+# This program is distributed in the hope that it will be useful, but WITHOUT
2148+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
2149+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
2150+# details.
2151+#
2152+# You should have received a copy of the GNU General Public License along with
2153+# this program; if not, write to the Free Software Foundation, Inc.,
2154+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2155+
2156
2157=== added file 'src/settings/indicatorNetworkSettings/version.py'
2158--- src/settings/indicatorNetworkSettings/version.py 1970-01-01 00:00:00 +0000
2159+++ src/settings/indicatorNetworkSettings/version.py 2010-12-13 14:13:17 +0000
2160@@ -0,0 +1,5 @@
2161+
2162+VERSION = '0.01'
2163+CODENAME = 'UNRELEASED'
2164+DISTRO = 'Ubuntu'
2165+RELEASE = '11.04'
2166
2167=== added directory 'src/settings/ui'
2168=== added file 'src/settings/ui/Makefile.am'
2169--- src/settings/ui/Makefile.am 1970-01-01 00:00:00 +0000
2170+++ src/settings/ui/Makefile.am 2010-12-13 14:13:17 +0000
2171@@ -0,0 +1,5 @@
2172+uidir = $(pkgdatadir)/ui
2173+dist_ui_DATA = \
2174+ indicator-network-settings.ui \
2175+ mobile_box.ui \
2176+ wireless_box.ui
2177
2178=== added file 'src/settings/ui/indicator-network-settings.ui'
2179--- src/settings/ui/indicator-network-settings.ui 1970-01-01 00:00:00 +0000
2180+++ src/settings/ui/indicator-network-settings.ui 2010-12-13 14:13:17 +0000
2181@@ -0,0 +1,163 @@
2182+<?xml version="1.0" encoding="UTF-8"?>
2183+<interface>
2184+ <requires lib="gtk+" version="2.16"/>
2185+ <!-- interface-naming-policy project-wide -->
2186+ <object class="GtkWindow" id="window_main">
2187+ <property name="title" translatable="yes">Network Settings</property>
2188+ <property name="default_width">600</property>
2189+ <property name="default_height">300</property>
2190+ <signal name="delete_event" handler="on_window_main_delete_event"/>
2191+ <child>
2192+ <object class="GtkNotebook" id="notebook_main">
2193+ <property name="visible">True</property>
2194+ <property name="can_focus">True</property>
2195+ <property name="border_width">12</property>
2196+ <signal name="switch_page" handler="on_notebook_main_page_switched"/>
2197+ <child>
2198+ <object class="GtkAlignment" id="alignment_connections">
2199+ <property name="visible">True</property>
2200+ <child>
2201+ <object class="GtkHBox" id="hbox_c">
2202+ <property name="visible">True</property>
2203+ <property name="border_width">12</property>
2204+ <property name="spacing">12</property>
2205+ <child>
2206+ <object class="GtkViewport" id="viewport_c_devices">
2207+ <property name="width_request">170</property>
2208+ <property name="visible">True</property>
2209+ <property name="resize_mode">queue</property>
2210+ <child>
2211+ <object class="GtkScrolledWindow" id="scrolledwindow_c_devices">
2212+ <property name="visible">True</property>
2213+ <property name="can_focus">True</property>
2214+ <property name="hscrollbar_policy">automatic</property>
2215+ <property name="vscrollbar_policy">automatic</property>
2216+ <child>
2217+ <placeholder/>
2218+ </child>
2219+ </object>
2220+ </child>
2221+ </object>
2222+ <packing>
2223+ <property name="expand">False</property>
2224+ <property name="position">0</property>
2225+ </packing>
2226+ </child>
2227+ <child>
2228+ <object class="GtkNotebook" id="notebook_c_right">
2229+ <property name="visible">True</property>
2230+ <property name="can_focus">True</property>
2231+ <property name="show_tabs">False</property>
2232+ <property name="show_border">False</property>
2233+ <property name="tab_hborder">3</property>
2234+ <child>
2235+ <placeholder/>
2236+ </child>
2237+ <child type="tab">
2238+ <placeholder/>
2239+ </child>
2240+ <child>
2241+ <placeholder/>
2242+ </child>
2243+ <child type="tab">
2244+ <placeholder/>
2245+ </child>
2246+ <child>
2247+ <placeholder/>
2248+ </child>
2249+ <child type="tab">
2250+ <placeholder/>
2251+ </child>
2252+ <child>
2253+ <placeholder/>
2254+ </child>
2255+ <child type="tab">
2256+ <placeholder/>
2257+ </child>
2258+ </object>
2259+ <packing>
2260+ <property name="position">1</property>
2261+ </packing>
2262+ </child>
2263+ </object>
2264+ </child>
2265+ </object>
2266+ </child>
2267+ <child type="tab">
2268+ <object class="GtkLabel" id="label1">
2269+ <property name="visible">True</property>
2270+ <property name="label" translatable="yes">Connections</property>
2271+ </object>
2272+ <packing>
2273+ <property name="tab_fill">False</property>
2274+ </packing>
2275+ </child>
2276+ <!--
2277+ <child>
2278+ <object class="GtkAlignment" id="alignment_vpns">
2279+ <property name="visible">True</property>
2280+ <child>
2281+ <placeholder/>
2282+ </child>
2283+ </object>
2284+ <packing>
2285+ <property name="position">1</property>
2286+ </packing>
2287+ </child>
2288+ <child type="tab">
2289+ <object class="GtkLabel" id="label2">
2290+ <property name="visible">True</property>
2291+ <property name="label" translatable="yes">VPNs</property>
2292+ </object>
2293+ <packing>
2294+ <property name="position">1</property>
2295+ <property name="tab_fill">False</property>
2296+ </packing>
2297+ </child>
2298+ <child>
2299+ <object class="GtkAlignment" id="alignment_sharing">
2300+ <property name="visible">True</property>
2301+ <child>
2302+ <placeholder/>
2303+ </child>
2304+ </object>
2305+ <packing>
2306+ <property name="position">2</property>
2307+ </packing>
2308+ </child>
2309+ <child type="tab">
2310+ <object class="GtkLabel" id="label4">
2311+ <property name="visible">True</property>
2312+ <property name="label" translatable="yes">Sharing</property>
2313+ </object>
2314+ <packing>
2315+ <property name="position">2</property>
2316+ <property name="tab_fill">False</property>
2317+ </packing>
2318+ </child>
2319+ <child>
2320+ <object class="GtkAlignment" id="alignment_firewall">
2321+ <property name="visible">True</property>
2322+ <child>
2323+ <placeholder/>
2324+ </child>
2325+ </object>
2326+ <packing>
2327+ <property name="position">3</property>
2328+ </packing>
2329+ </child>
2330+ <child type="tab">
2331+ <object class="GtkLabel" id="label3">
2332+ <property name="visible">True</property>
2333+ <property name="label" translatable="yes">Firewall</property>
2334+ </object>
2335+ <packing>
2336+ <property name="position">3</property>
2337+ <property name="tab_fill">False</property>
2338+ </packing>
2339+ </child>
2340+ -->
2341+ </object>
2342+ </child>
2343+ </object>
2344+</interface>
2345
2346=== added file 'src/settings/ui/mobile_box.ui'
2347--- src/settings/ui/mobile_box.ui 1970-01-01 00:00:00 +0000
2348+++ src/settings/ui/mobile_box.ui 2010-12-13 14:13:17 +0000
2349@@ -0,0 +1,212 @@
2350+<?xml version="1.0" encoding="UTF-8"?>
2351+<interface>
2352+ <requires lib="gtk+" version="2.16"/>
2353+ <!-- interface-naming-policy project-wide -->
2354+ <object class="GtkTable" id="table_settings">
2355+ <property name="visible">True</property>
2356+ <property name="n_rows">6</property>
2357+ <property name="n_columns">2</property>
2358+ <property name="column_spacing">6</property>
2359+ <property name="row_spacing">6</property>
2360+ <child>
2361+ <object class="GtkLabel" id="label_pin">
2362+ <property name="visible">True</property>
2363+ <property name="sensitive">False</property>
2364+ <property name="xalign">1</property>
2365+ <property name="label" translatable="yes">Device PIN:</property>
2366+ </object>
2367+ <packing>
2368+ <property name="x_options">GTK_FILL</property>
2369+ <property name="y_options">GTK_FILL</property>
2370+ </packing>
2371+ </child>
2372+ <child>
2373+ <object class="GtkLabel" id="label_access_point">
2374+ <property name="visible">True</property>
2375+ <property name="sensitive">False</property>
2376+ <property name="xalign">1</property>
2377+ <property name="label" translatable="yes">Access point:</property>
2378+ </object>
2379+ <packing>
2380+ <property name="top_attach">2</property>
2381+ <property name="bottom_attach">3</property>
2382+ <property name="x_options">GTK_FILL</property>
2383+ <property name="y_options">GTK_FILL</property>
2384+ </packing>
2385+ </child>
2386+ <child>
2387+ <object class="GtkLabel" id="label_region">
2388+ <property name="visible">True</property>
2389+ <property name="sensitive">False</property>
2390+ <property name="xalign">1</property>
2391+ <property name="label" translatable="yes">Region:</property>
2392+ </object>
2393+ <packing>
2394+ <property name="top_attach">3</property>
2395+ <property name="bottom_attach">4</property>
2396+ <property name="x_options">GTK_FILL</property>
2397+ <property name="y_options">GTK_FILL</property>
2398+ </packing>
2399+ </child>
2400+ <child>
2401+ <object class="GtkLabel" id="label_provider">
2402+ <property name="visible">True</property>
2403+ <property name="sensitive">False</property>
2404+ <property name="xalign">1</property>
2405+ <property name="label" translatable="yes">Provider:</property>
2406+ </object>
2407+ <packing>
2408+ <property name="top_attach">4</property>
2409+ <property name="bottom_attach">5</property>
2410+ <property name="x_options">GTK_FILL</property>
2411+ <property name="y_options">GTK_FILL</property>
2412+ </packing>
2413+ </child>
2414+ <child>
2415+ <object class="GtkLabel" id="label_apn">
2416+ <property name="visible">True</property>
2417+ <property name="xalign">1</property>
2418+ <property name="label" translatable="yes">APN:</property>
2419+ </object>
2420+ <packing>
2421+ <property name="top_attach">5</property>
2422+ <property name="bottom_attach">6</property>
2423+ <property name="x_options">GTK_FILL</property>
2424+ <property name="y_options">GTK_FILL</property>
2425+ </packing>
2426+ </child>
2427+ <child>
2428+ <object class="GtkHBox" id="hbox_entry_pin">
2429+ <property name="visible">True</property>
2430+ <property name="spacing">6</property>
2431+ <child>
2432+ <object class="GtkEntry" id="entry_pin">
2433+ <property name="visible">True</property>
2434+ <property name="can_focus">True</property>
2435+ <property name="invisible_char">•</property>
2436+ <property name="text" translatable="yes">0123456</property>
2437+ </object>
2438+ <packing>
2439+ <property name="position">0</property>
2440+ </packing>
2441+ </child>
2442+ <child>
2443+ <object class="GtkLabel" id="label_pin_auth">
2444+ <property name="visible">True</property>
2445+ <property name="label" translatable="yes">Authorized</property>
2446+ </object>
2447+ <packing>
2448+ <property name="expand">False</property>
2449+ <property name="position">1</property>
2450+ </packing>
2451+ </child>
2452+ </object>
2453+ <packing>
2454+ <property name="left_attach">1</property>
2455+ <property name="right_attach">2</property>
2456+ <property name="y_options">GTK_FILL</property>
2457+ </packing>
2458+ </child>
2459+ <child>
2460+ <object class="GtkCheckButton" id="checkbutton_show_pin">
2461+ <property name="label" translatable="yes">Show PIN</property>
2462+ <property name="visible">True</property>
2463+ <property name="can_focus">True</property>
2464+ <property name="receives_default">False</property>
2465+ <property name="draw_indicator">True</property>
2466+ <signal name="toggled" handler="_on_checkbutton_show_pin_toggled"/>
2467+ </object>
2468+ <packing>
2469+ <property name="left_attach">1</property>
2470+ <property name="right_attach">2</property>
2471+ <property name="top_attach">1</property>
2472+ <property name="bottom_attach">2</property>
2473+ <property name="y_options">GTK_FILL</property>
2474+ </packing>
2475+ </child>
2476+ <child>
2477+ <object class="GtkHBox" id="hbox_radiobuttons">
2478+ <property name="visible">True</property>
2479+ <property name="spacing">6</property>
2480+ <child>
2481+ <object class="GtkRadioButton" id="radiobutton_automatic">
2482+ <property name="label" translatable="yes">Automatic</property>
2483+ <property name="visible">True</property>
2484+ <property name="can_focus">True</property>
2485+ <property name="receives_default">False</property>
2486+ <property name="active">True</property>
2487+ <property name="draw_indicator">True</property>
2488+ </object>
2489+ <packing>
2490+ <property name="expand">False</property>
2491+ <property name="position">0</property>
2492+ </packing>
2493+ </child>
2494+ <child>
2495+ <object class="GtkRadioButton" id="radiobutton_manual">
2496+ <property name="label" translatable="yes">Manual</property>
2497+ <property name="visible">True</property>
2498+ <property name="can_focus">True</property>
2499+ <property name="receives_default">False</property>
2500+ <property name="active">True</property>
2501+ <property name="draw_indicator">True</property>
2502+ <property name="group">radiobutton_automatic</property>
2503+ </object>
2504+ <packing>
2505+ <property name="expand">False</property>
2506+ <property name="position">1</property>
2507+ </packing>
2508+ </child>
2509+ </object>
2510+ <packing>
2511+ <property name="left_attach">1</property>
2512+ <property name="right_attach">2</property>
2513+ <property name="top_attach">2</property>
2514+ <property name="bottom_attach">3</property>
2515+ <property name="y_options">GTK_FILL</property>
2516+ </packing>
2517+ </child>
2518+ <child>
2519+ <object class="GtkLabel" id="label_apn_place">
2520+ <property name="visible">True</property>
2521+ <property name="xalign">0</property>
2522+ <property name="label" translatable="yes">INTERNET</property>
2523+ </object>
2524+ <packing>
2525+ <property name="left_attach">1</property>
2526+ <property name="right_attach">2</property>
2527+ <property name="top_attach">5</property>
2528+ <property name="bottom_attach">6</property>
2529+ <property name="x_options">GTK_FILL</property>
2530+ <property name="y_options">GTK_FILL</property>
2531+ </packing>
2532+ </child>
2533+ <child>
2534+ <object class="GtkComboBox" id="combobox1">
2535+ <property name="visible">True</property>
2536+ </object>
2537+ <packing>
2538+ <property name="left_attach">1</property>
2539+ <property name="right_attach">2</property>
2540+ <property name="top_attach">3</property>
2541+ <property name="bottom_attach">4</property>
2542+ <property name="y_options">GTK_FILL</property>
2543+ </packing>
2544+ </child>
2545+ <child>
2546+ <object class="GtkComboBox" id="combobox2">
2547+ <property name="visible">True</property>
2548+ </object>
2549+ <packing>
2550+ <property name="left_attach">1</property>
2551+ <property name="right_attach">2</property>
2552+ <property name="top_attach">4</property>
2553+ <property name="bottom_attach">5</property>
2554+ <property name="y_options">GTK_FILL</property>
2555+ </packing>
2556+ </child>
2557+ <child>
2558+ <placeholder/>
2559+ </child>
2560+ </object>
2561+</interface>
2562
2563=== added file 'src/settings/ui/wireless_box.ui'
2564--- src/settings/ui/wireless_box.ui 1970-01-01 00:00:00 +0000
2565+++ src/settings/ui/wireless_box.ui 2010-12-13 14:13:17 +0000
2566@@ -0,0 +1,93 @@
2567+<?xml version="1.0" encoding="UTF-8"?>
2568+<interface>
2569+ <requires lib="gtk+" version="2.16"/>
2570+ <!-- interface-naming-policy project-wide -->
2571+ <object class="GtkVBox" id="vbox_connections">
2572+ <property name="visible">True</property>
2573+ <property name="spacing">6</property>
2574+ <child>
2575+ <object class="GtkScrolledWindow" id="scrolledwindow_connections">
2576+ <property name="visible">True</property>
2577+ <property name="can_focus">True</property>
2578+ <property name="hscrollbar_policy">automatic</property>
2579+ <property name="vscrollbar_policy">automatic</property>
2580+ <property name="shadow_type">in</property>
2581+ <child>
2582+ <placeholder/>
2583+ </child>
2584+ </object>
2585+ <packing>
2586+ <property name="position">0</property>
2587+ </packing>
2588+ </child>
2589+ <child>
2590+ <object class="GtkHBox" id="hbox1">
2591+ <property name="visible">True</property>
2592+ <child>
2593+ <object class="GtkHButtonBox" id="hbuttonbox_left">
2594+ <property name="visible">True</property>
2595+ <property name="spacing">6</property>
2596+ <property name="layout_style">start</property>
2597+ <child>
2598+ <object class="GtkButton" id="button_connect">
2599+ <property name="label" translatable="yes">Connect</property>
2600+ <property name="visible">True</property>
2601+ <property name="can_focus">True</property>
2602+ <property name="receives_default">True</property>
2603+ <signal name="clicked" handler="_on_button_connect_clicked"/>
2604+ </object>
2605+ <packing>
2606+ <property name="position">0</property>
2607+ </packing>
2608+ </child>
2609+ <child>
2610+ <object class="GtkButton" id="button_other">
2611+ <property name="label" translatable="yes">Other...</property>
2612+ <property name="visible">True</property>
2613+ <property name="can_focus">True</property>
2614+ <property name="receives_default">True</property>
2615+ </object>
2616+ <packing>
2617+ <property name="expand">False</property>
2618+ <property name="fill">False</property>
2619+ <property name="position">1</property>
2620+ </packing>
2621+ </child>
2622+ </object>
2623+ <packing>
2624+ <property name="expand">False</property>
2625+ <property name="fill">False</property>
2626+ <property name="position">0</property>
2627+ </packing>
2628+ </child>
2629+ <child>
2630+ <object class="GtkHButtonBox" id="hbuttonbox_right">
2631+ <property name="visible">True</property>
2632+ <property name="spacing">6</property>
2633+ <property name="layout_style">end</property>
2634+ <child>
2635+ <object class="GtkButton" id="button_forget">
2636+ <property name="label" translatable="yes">Forget Details</property>
2637+ <property name="visible">True</property>
2638+ <property name="can_focus">True</property>
2639+ <property name="receives_default">True</property>
2640+ </object>
2641+ <packing>
2642+ <property name="expand">False</property>
2643+ <property name="fill">False</property>
2644+ <property name="position">0</property>
2645+ </packing>
2646+ </child>
2647+ </object>
2648+ <packing>
2649+ <property name="position">1</property>
2650+ </packing>
2651+ </child>
2652+ </object>
2653+ <packing>
2654+ <property name="expand">False</property>
2655+ <property name="position">1</property>
2656+ </packing>
2657+ </child>
2658+ </object>
2659+</interface>

Subscribers

People subscribed via source and target branches