harmonized maemo/harmattan src files
[feedingit] / psa_harmattan / feedingit / pysrc / config.py
1 #!/usr/bin/env python2.5
2
3
4 # Copyright (c) 2007-2008 INdT.
5 # Copyright (c) 2011 Neal H. Walfield.
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU Lesser General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 #  This program is distributed in the hope that it will be useful,
12 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 #  GNU Lesser General Public License for more details.
15 #
16 #  You should have received a copy of the GNU Lesser General Public License
17 #  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 #
19
20 # ============================================================================
21 # Name        : FeedingIt.py
22 # Author      : Yves Marcoz
23 # Version     : 0.6.1
24 # Description : Simple RSS Reader
25 # ============================================================================
26 #try:
27 #    import gtk
28 #    import hildon
29 #    from gobject import idle_add
30 #except:
31 #    pass
32
33 from ConfigParser import RawConfigParser
34 from gconf import client_get_default
35 from urllib2 import ProxyHandler
36 from mainthread import mainthread
37 import logging
38 logger = logging.getLogger(__name__)
39
40 VERSION = "120"
41
42 section = "FeedingIt"
43 ranges = { "updateInterval":[0.5, 1, 2, 4, 8, 12, 24], "expiry":[24, 48, 72, 144, 288], "fontSize":range(12,24), "orientation":["Automatic", "Landscape", "Portrait"], "artFontSize":[10, 12, 14, 16, 18, 20], "feedsort":["Manual", "Most unread", "Least unread", "Most recent", "Least recent"] }
44 titles = {"updateInterval":"Auto-update interval", "expiry":"Delete articles", "fontSize":"List font size", "orientation":"Display orientation", "artFontSize":"Article font size","feedsort":"Feed sort order"}
45 subtitles = {"updateInterval":"Every %s hours", "expiry":"After %s hours", "fontSize":"%s pixels", "orientation":"%s", "artFontSize":"%s pixels", "feedsort":"%s"}
46
47 class Config():
48     def __init__(self, parent, configFilename):
49         self.configFilename = configFilename
50         self.parent = parent
51         # Load config
52         self.loadConfig()
53
54         # Backup current settings for later restore
55         self.config_backup = dict(self.config)
56         self.do_restore_backup = True
57
58     def on_save_button_clicked(self, button):
59         self.do_restore_backup = False
60         self.window.destroy()
61
62     def createDialog(self):
63         import gtk
64         import hildon
65         from gobject import idle_add
66         self.window = gtk.Dialog("Settings", self.parent)
67         self.window.set_geometry_hints(min_height=600)
68
69         save_button = self.window.add_button(gtk.STOCK_SAVE, gtk.RESPONSE_OK)
70         save_button.connect('clicked', self.on_save_button_clicked)
71         #self.window.set_default_size(-1, 600)
72         panArea = hildon.PannableArea()
73         
74         vbox = gtk.VBox(False, 2)
75         self.buttons = {}
76
77         def heading(text):
78             l = gtk.Label()
79             l.set_size_request(-1, 6)
80             vbox.pack_start(l, expand=False)
81             vbox.pack_start(gtk.Frame(text), expand=False)
82
83         def add_setting(setting):
84             picker = hildon.PickerButton(gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
85             selector = self.create_selector(ranges[setting], setting)
86             picker.set_selector(selector)
87             picker.set_title(titles[setting])
88             picker.set_text(titles[setting], subtitles[setting] % self.config[setting])
89             picker.set_name('HildonButton-finger')
90             picker.set_alignment(0,0,1,1)
91             self.buttons[setting] = picker
92             vbox.pack_start(picker, expand=False)
93
94         button = hildon.Button(gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
95         button.set_label("View Known Issues and Tips")
96         button.connect("clicked", self.button_tips_clicked)
97         button.set_alignment(0,0,1,1)
98         vbox.pack_start(button, expand=False)  
99
100         heading('Display')
101         add_setting('fontSize')
102         add_setting('artFontSize')
103         add_setting('orientation')
104         add_setting('feedsort')
105         button = hildon.CheckButton(gtk.HILDON_SIZE_FINGER_HEIGHT)
106         button.set_label("Hide read feeds")
107         button.set_active(self.config["hidereadfeeds"])
108         button.connect("toggled", self.button_toggled, "hidereadfeeds")
109         vbox.pack_start(button, expand=False)
110
111         button = hildon.CheckButton(gtk.HILDON_SIZE_FINGER_HEIGHT)
112         button.set_label("Hide read articles")
113         button.set_active(self.config["hidereadarticles"])
114         button.connect("toggled", self.button_toggled, "hidereadarticles")
115         vbox.pack_start(button, expand=False)
116
117
118         heading('Updating')
119         label = gtk.Label(gtk.HILDON_SIZE_FINGER_HEIGHT)
120         label.set_label("Use Woodchuck network daemon, or the home-screen widget for automatic updates.")
121         label.set_line_wrap(True)
122         vbox.pack_start(label, expand=False)
123
124         try:
125             import woodchuck
126             woodchuck_installed = True
127         except ImportError:
128             woodchuck_installed = False
129
130         if not woodchuck_installed:
131             def install_woodchuck_clicked(button):
132                 from FeedingIt import open_in_browser
133                 open_in_browser("http://maemo.org/downloads/product/raw/Maemo5/murmeltier?get_installfile")
134
135             button = hildon.Button(gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
136             button.set_label("Install Woodchuck")
137             button.connect("clicked", install_woodchuck_clicked)
138             button.set_alignment(0,0,1,1)
139             vbox.pack_start(button, expand=False)
140         else:
141             button = hildon.CheckButton(gtk.HILDON_SIZE_FINGER_HEIGHT)
142             button.set_label("Woodchuck-Based Automatic Update")
143             button.set_active(self.config["woodchuck"])
144             button.connect("toggled", self.button_toggled, "woodchuck")
145             vbox.pack_start(button, expand=False)
146             add_setting('updateInterval')
147             add_setting('expiry')
148
149         heading('Network')
150         button = hildon.CheckButton(gtk.HILDON_SIZE_FINGER_HEIGHT)
151         button.set_label('Cache images')
152         button.set_active(self.config["imageCache"])
153         button.connect("toggled", self.button_toggled, "imageCache")
154         vbox.pack_start(button, expand=False)
155
156         button = hildon.CheckButton(gtk.HILDON_SIZE_FINGER_HEIGHT)
157         button.set_label("Use HTTP proxy")
158         button.set_active(self.config["proxy"])
159         button.connect("toggled", self.button_toggled, "proxy")
160         vbox.pack_start(button, expand=False)
161         
162         button = hildon.CheckButton(gtk.HILDON_SIZE_FINGER_HEIGHT)
163         button.set_label('Open links in external browser')
164         button.set_active(self.config["extBrowser"])
165         button.connect("toggled", self.button_toggled, "extBrowser")
166         vbox.pack_start(button, expand=False)
167         
168         panArea.add_with_viewport(vbox)
169         
170         self.window.vbox.add(panArea)
171         self.window.connect("destroy", self.onExit)
172         #self.window.add(self.vbox)
173         self.window.set_default_size(-1, 600)
174         self.window.show_all()
175         return self.window
176
177     def button_tips_clicked(self, *widget):
178         import dbus
179         bus = dbus.SessionBus()
180         proxy = bus.get_object("com.nokia.osso_browser", "/com/nokia/osso_browser/request")
181         iface = dbus.Interface(proxy, 'com.nokia.osso_browser')
182         iface.open_new_window("http://feedingit.marcoz.org/news/?page_id=%s" % VERSION)
183
184     def onExit(self, *widget):
185         # When the dialog is closed without hitting
186         # the "Save" button, restore the configuration
187         if self.do_restore_backup:
188             logger.debug('Restoring configuration')
189             self.config = self.config_backup
190
191         self.saveConfig()
192         self.window.destroy()
193
194     def button_toggled(self, widget, configName):
195         #print "widget", widget.get_active()
196         if (widget.get_active()):
197             self.config[configName] = True
198         else:
199             self.config[configName] = False
200         #print "autoup",  self.autoupdate
201
202         if configName == 'woodchuck':
203             try:
204                 from wc import wc_disable_set
205                 wc_disable_set(not self.config['woodchuck'])
206             except Exception:
207                 logger.exception("Disabling Woodchuck")
208
209         self.saveConfig()
210         
211     def selection_changed(self, selector, button, setting):
212         from gobject import idle_add
213         current_selection = selector.get_current_text()
214         if current_selection:
215             self.config[setting] = current_selection
216         idle_add(self.updateButton, setting)
217         self.saveConfig()
218         
219     def updateButton(self, setting):
220         self.buttons[setting].set_text(titles[setting], subtitles[setting] % self.config[setting])
221         
222     def loadConfig(self):
223         self.config = {}
224
225         configParser = RawConfigParser()
226         try:
227             configParser.read(self.configFilename)
228         except Exception:
229             logger.exception("Reading %s", self.configFilename)
230
231         # The function to use to fetch the parameter, the parameter's
232         # name and the default value.
233         values = ((configParser.getint, "fontSize", 17),
234                   (configParser.getint, "artFontSize", 14),
235                   (configParser.getint, "expiry", 24),
236                   (configParser.getboolean, "autoupdate", False),
237                   (configParser.getboolean, "woodchuck", True),
238                   (configParser.getboolean, "askedAboutWoodchuck", False),
239                   (configParser.getint, "updateInterval", 4),
240                   (configParser.get, "orientation", "Automatic"),
241                   (configParser.getboolean, "imageCache", False),
242                   (configParser.getboolean, "proxy", True),
243                   (configParser.getboolean, "hidereadfeeds", False),
244                   (configParser.getboolean, "hidereadarticles", False),
245                   (configParser.getboolean, "extBrowser", False),
246                   (configParser.getboolean, "theme", True),
247                   (configParser.get, "feedsort", "Manual"))
248
249         for fetcher, name, default in values:
250             try:
251                 v = fetcher(section, name)
252             except Exception:
253                 logger.exception("Reading config variable %s", name)
254                 v = default
255             self.config[name] = v
256
257     def saveConfig(self):
258         configParser = RawConfigParser()
259         configParser.add_section(section)
260         configParser.set(section, 'fontSize', str(self.config["fontSize"]))
261         configParser.set(section, 'artFontSize', str(self.config["artFontSize"]))
262         configParser.set(section, 'expiry', str(self.config["expiry"]))
263         configParser.set(section, 'autoupdate', str(self.config["autoupdate"]))
264         configParser.set(section, 'updateInterval', str(self.config["updateInterval"]))
265         configParser.set(section, 'woodchuck', str(self.config["woodchuck"]))
266         configParser.set(section, 'askedAboutWoodchuck', str(self.config["askedAboutWoodchuck"]))
267         configParser.set(section, 'orientation', str(self.config["orientation"]))
268         configParser.set(section, 'imageCache', str(self.config["imageCache"]))
269         configParser.set(section, 'proxy', str(self.config["proxy"]))
270         configParser.set(section, 'hidereadfeeds', str(self.config["hidereadfeeds"]))
271         configParser.set(section, 'hidereadarticles', str(self.config["hidereadarticles"]))
272         configParser.set(section, 'extBrowser', str(self.config["extBrowser"]))
273         configParser.set(section, 'feedsort', str(self.config["feedsort"]))
274         configParser.set(section, 'theme', str(self.config["theme"]))
275
276         # Writing our configuration file
277         file = open(self.configFilename, 'wb')
278         configParser.write(file)
279         file.close()
280
281     def create_selector(self, choices, setting):
282         import gtk
283         import hildon
284         from gobject import idle_add
285         #self.pickerDialog = hildon.PickerDialog(self.parent)
286         selector = hildon.TouchSelector(text=True)
287         index = 0
288         for item in choices:
289             iter = selector.append_text(str(item))
290             if str(self.config[setting]) == str(item): 
291                 selector.set_active(0, index)
292             index += 1
293         selector.connect("changed", self.selection_changed, setting)
294         #self.pickerDialog.set_selector(selector)
295         return selector
296         #self.pickerDialog.show_all()
297
298     def getFontSize(self):
299         return self.config["fontSize"]
300     def getArtFontSize(self):
301         return self.config["artFontSize"]
302     def getExpiry(self):
303         return self.config["expiry"]
304     def setExpiry(self, expiry):
305         self.config["expiry"] = expiry
306     def isAutoUpdateEnabled(self):
307         return self.config["autoupdate"]
308     def setAutoUpdateEnabled(self, value):
309         self.config["autoupdate"] = value
310     def getWoodchuckEnabled(self):
311         return self.config["woodchuck"]
312     def getAskedAboutWoodchuck(self):
313         return self.config["askedAboutWoodchuck"]
314     def setAskedAboutWoodchuck(self, value):
315         self.config["askedAboutWoodchuck"] = value
316         self.saveConfig()
317     def getUpdateInterval(self):
318         return float(self.config["updateInterval"])
319     def getReadFont(self):
320         return "sans italic %s" % self.config["fontSize"]
321     def getUnreadFont(self):
322         return "sans %s" % self.config["fontSize"]
323     def getOrientation(self):
324         return ranges["orientation"].index(self.config["orientation"])
325     def getOrientationChoices(self):
326         return ranges["orientation"]
327     def setOrientation(self, choice):
328         self.config["orientation"] = index 
329     def getImageCache(self):
330         return self.config["imageCache"]
331     def setImageCache(self, cache):
332         self.config["imageCache"] = bool(cache) 
333     @mainthread
334     def getProxy(self):
335         if self.config["proxy"] == False:
336             return (False, None)
337         if client_get_default().get_bool('/system/http_proxy/use_http_proxy'):
338             port = client_get_default().get_int('/system/http_proxy/port')
339             http = client_get_default().get_string('/system/http_proxy/host')
340             proxy = ProxyHandler( {"http":"http://%s:%s/"% (http,port)} )
341             return (True, proxy)
342         return (False, None)
343     def getHideReadFeeds(self):
344         return self.config["hidereadfeeds"]
345     def setHideReadFeeds(self, setting):
346         self.config["hidereadfeeds"] = bool(setting)
347     def getHideReadArticles(self):
348         return self.config["hidereadarticles"]
349     def setHideReadArticles(self, setting):
350         self.config["hidereadarticles"] = bool(setting)
351     def getOpenInExternalBrowser(self):
352         return self.config["extBrowser"]
353     def getFeedSortOrder(self):
354         return self.config["feedsort"]
355     def getFeedSortOrderChoices(self):
356         return ranges["feedsort"]
357     def setFeedSortOrder(self, setting):
358         self.config["feedsort"] = setting
359     def getTheme(self):
360         return self.config["theme"]
361     def setTheme(self, theme):
362         self.config["theme"] = bool(theme)