Disable app-based auto-update (application left running)
[feedingit] / src / 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 = "52"
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         button = hildon.CheckButton(gtk.HILDON_SIZE_FINGER_HEIGHT)
120         button.set_label("Widget Based Automatic Update\n"
121                          + "(See FeedingIt widget for options)")
122         #button.set_active(self.config["autoupdate"])
123         #button.connect("toggled", self.button_toggled, "autoupdate")
124         vbox.pack_start(button, expand=False)
125         button = hildon.CheckButton(gtk.HILDON_SIZE_FINGER_HEIGHT)
126         button.set_label("Woodchuck-Based Automatic Update")
127         button.set_active(self.config["woodchuck"])
128         button.connect("toggled", self.button_toggled, "woodchuck")
129         vbox.pack_start(button, expand=False)
130
131         try:
132             import woodchuck
133             woodchuck_installed = True
134         except ImportError:
135             woodchuck_installed = False
136
137         if not woodchuck_installed:
138             def install_woodchuck_clicked(button):
139                 from FeedingIt import open_in_browser
140                 open_in_browser("http://maemo.org/downloads/product/raw/Maemo5/murmeltier?get_installfile")
141
142             button = hildon.Button(gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
143             button.set_label("Install Woodchuck")
144             button.connect("clicked", install_woodchuck_clicked)
145             button.set_alignment(0,0,1,1)
146             vbox.pack_start(button, expand=False)
147         else:
148             add_setting('updateInterval')
149             add_setting('expiry')
150
151         heading('Network')
152         button = hildon.CheckButton(gtk.HILDON_SIZE_FINGER_HEIGHT)
153         button.set_label('Cache images')
154         button.set_active(self.config["imageCache"])
155         button.connect("toggled", self.button_toggled, "imageCache")
156         vbox.pack_start(button, expand=False)
157
158         button = hildon.CheckButton(gtk.HILDON_SIZE_FINGER_HEIGHT)
159         button.set_label("Use HTTP proxy")
160         button.set_active(self.config["proxy"])
161         button.connect("toggled", self.button_toggled, "proxy")
162         vbox.pack_start(button, expand=False)
163         
164         button = hildon.CheckButton(gtk.HILDON_SIZE_FINGER_HEIGHT)
165         button.set_label('Open links in external browser')
166         button.set_active(self.config["extBrowser"])
167         button.connect("toggled", self.button_toggled, "extBrowser")
168         vbox.pack_start(button, expand=False)
169         
170         panArea.add_with_viewport(vbox)
171         
172         self.window.vbox.add(panArea)
173         self.window.connect("destroy", self.onExit)
174         #self.window.add(self.vbox)
175         self.window.set_default_size(-1, 600)
176         self.window.show_all()
177         return self.window
178
179     def button_tips_clicked(self, *widget):
180         import dbus
181         bus = dbus.SessionBus()
182         proxy = bus.get_object("com.nokia.osso_browser", "/com/nokia/osso_browser/request")
183         iface = dbus.Interface(proxy, 'com.nokia.osso_browser')
184         iface.open_new_window("http://feedingit.marcoz.org/news/?page_id=%s" % VERSION)
185
186     def onExit(self, *widget):
187         # When the dialog is closed without hitting
188         # the "Save" button, restore the configuration
189         if self.do_restore_backup:
190             logger.debug('Restoring configuration')
191             self.config = self.config_backup
192
193         self.saveConfig()
194         self.window.destroy()
195
196     def button_toggled(self, widget, configName):
197         #print "widget", widget.get_active()
198         if (widget.get_active()):
199             self.config[configName] = True
200         else:
201             self.config[configName] = False
202         #print "autoup",  self.autoupdate
203
204         if configName == 'woodchuck':
205             try:
206                 from wc import wc_disable_set
207                 wc_disable_set(not self.config['woodchuck'])
208             except Exception:
209                 logger.exception("Disabling Woodchuck")
210
211         self.saveConfig()
212         
213     def selection_changed(self, selector, button, setting):
214         from gobject import idle_add
215         current_selection = selector.get_current_text()
216         if current_selection:
217             self.config[setting] = current_selection
218         idle_add(self.updateButton, setting)
219         self.saveConfig()
220         
221     def updateButton(self, setting):
222         self.buttons[setting].set_text(titles[setting], subtitles[setting] % self.config[setting])
223         
224     def loadConfig(self):
225         self.config = {}
226
227         configParser = RawConfigParser()
228         try:
229             configParser.read(self.configFilename)
230         except Exception:
231             logger.exception("Reading %s", self.configFilename)
232
233         # The function to use to fetch the parameter, the parameter's
234         # name and the default value.
235         values = ((configParser.getint, "fontSize", 17),
236                   (configParser.getint, "artFontSize", 14),
237                   (configParser.getint, "expiry", 24),
238                   (configParser.getboolean, "autoupdate", False),
239                   (configParser.getboolean, "woodchuck", True),
240                   (configParser.getboolean, "askedAboutWoodchuck", False),
241                   (configParser.getint, "updateInterval", 4),
242                   (configParser.get, "orientation", "Automatic"),
243                   (configParser.getboolean, "imageCache", False),
244                   (configParser.getboolean, "proxy", True),
245                   (configParser.getboolean, "hidereadfeeds", False),
246                   (configParser.getboolean, "hidereadarticles", False),
247                   (configParser.getboolean, "extBrowser", False),
248                   (configParser.get, "feedsort", "Manual"))
249
250         for fetcher, name, default in values:
251             try:
252                 v = fetcher(section, name)
253             except Exception:
254                 logger.exception("Reading config variable %s", name)
255                 v = default
256             self.config[name] = v
257
258     def saveConfig(self):
259         configParser = RawConfigParser()
260         configParser.add_section(section)
261         configParser.set(section, 'fontSize', str(self.config["fontSize"]))
262         configParser.set(section, 'artFontSize', str(self.config["artFontSize"]))
263         configParser.set(section, 'expiry', str(self.config["expiry"]))
264         configParser.set(section, 'autoupdate', str(self.config["autoupdate"]))
265         configParser.set(section, 'updateInterval', str(self.config["updateInterval"]))
266         configParser.set(section, 'woodchuck', str(self.config["woodchuck"]))
267         configParser.set(section, 'askedAboutWoodchuck', str(self.config["askedAboutWoodchuck"]))
268         configParser.set(section, 'orientation', str(self.config["orientation"]))
269         configParser.set(section, 'imageCache', str(self.config["imageCache"]))
270         configParser.set(section, 'proxy', str(self.config["proxy"]))
271         configParser.set(section, 'hidereadfeeds', str(self.config["hidereadfeeds"]))
272         configParser.set(section, 'hidereadarticles', str(self.config["hidereadarticles"]))
273         configParser.set(section, 'extBrowser', str(self.config["extBrowser"]))
274         configParser.set(section, 'feedsort', str(self.config["feedsort"]))
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 isAutoUpdateEnabled(self):
305         return self.config["autoupdate"]
306     def getWoodchuckEnabled(self):
307         return self.config["woodchuck"]
308     def getAskedAboutWoodchuck(self):
309         return self.config["askedAboutWoodchuck"]
310     def setAskedAboutWoodchuck(self, value):
311         self.config["askedAboutWoodchuck"] = value
312         self.saveConfig()
313     def getUpdateInterval(self):
314         return float(self.config["updateInterval"])
315     def getReadFont(self):
316         return "sans italic %s" % self.config["fontSize"]
317     def getUnreadFont(self):
318         return "sans %s" % self.config["fontSize"]
319     def getOrientation(self):
320         return ranges["orientation"].index(self.config["orientation"])
321     def getImageCache(self):
322         return self.config["imageCache"]
323     @mainthread
324     def getProxy(self):
325         if self.config["proxy"] == False:
326             return (False, None)
327         if client_get_default().get_bool('/system/http_proxy/use_http_proxy'):
328             port = client_get_default().get_int('/system/http_proxy/port')
329             http = client_get_default().get_string('/system/http_proxy/host')
330             proxy = ProxyHandler( {"http":"http://%s:%s/"% (http,port)} )
331             return (True, proxy)
332         return (False, None)
333     def getHideReadFeeds(self):
334         return self.config["hidereadfeeds"]
335     def getHideReadArticles(self):
336         return self.config["hidereadarticles"]
337     def getOpenInExternalBrowser(self):
338         return self.config["extBrowser"]
339     def getFeedSortOrder(self):
340         return self.config["feedsort"]