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

Proposed by Kalle Valo on 2010-12-09
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) 2010-12-09 Approve on 2010-12-13
Andrew 2010-12-09 Pending
Review via email: mp+43183@code.launchpad.net
To post a comment you must log in.
120. By Kalle Valo on 2010-12-09

Add Andrew to the authors file.

121. By Kalle Valo on 2010-12-09

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

122. By Kalle Valo on 2010-12-09

settings: unify copyrights with approval from Andrew.

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
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 on 2010-12-13

settings: don't set path if running locally

124. By Kalle Valo on 2010-12-13

settings: fix name of a script in comments

125. By Kalle Valo on 2010-12-13

settings: each autofoo item in it's own line

126. By Kalle Valo on 2010-12-13

settings: include ui files to the dist

127. By Kalle Valo on 2010-12-13

potfiles: add files from settings

 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
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

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