f6dc2de269407e163d6a349f48fb3cd8f4ffe25d
[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 = "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.get, "feedsort", "Manual"))
247
248         for fetcher, name, default in values:
249             try:
250                 v = fetcher(section, name)
251             except Exception:
252                 logger.exception("Reading config variable %s", name)
253                 v = default
254             self.config[name] = v
255
256     def saveConfig(self):
257         configParser = RawConfigParser()
258         configParser.add_section(section)
259         configParser.set(section, 'fontSize', str(self.config["fontSize"]))
260         configParser.set(section, 'artFontSize', str(self.config["artFontSize"]))
261         configParser.set(section, 'expiry', str(self.config["expiry"]))
262         configParser.set(section, 'autoupdate', str(self.config["autoupdate"]))
263         configParser.set(section, 'updateInterval', str(self.config["updateInterval"]))
264         configParser.set(section, 'woodchuck', str(self.config["woodchuck"]))
265         configParser.set(section, 'askedAboutWoodchuck', str(self.config["askedAboutWoodchuck"]))
266         configParser.set(section, 'orientation', str(self.config["orientation"]))
267         configParser.set(section, 'imageCache', str(self.config["imageCache"]))
268         configParser.set(section, 'proxy', str(self.config["proxy"]))
269         configParser.set(section, 'hidereadfeeds', str(self.config["hidereadfeeds"]))
270         configParser.set(section, 'hidereadarticles', str(self.config["hidereadarticles"]))
271         configParser.set(section, 'extBrowser', str(self.config["extBrowser"]))
272         configParser.set(section, 'feedsort', str(self.config["feedsort"]))
273
274         # Writing our configuration file
275         file = open(self.configFilename, 'wb')
276         configParser.write(file)
277         file.close()
278
279     def create_selector(self, choices, setting):
280         import gtk
281         import hildon
282         from gobject import idle_add
283         #self.pickerDialog = hildon.PickerDialog(self.parent)
284         selector = hildon.TouchSelector(text=True)
285         index = 0
286         for item in choices:
287             iter = selector.append_text(str(item))
288             if str(self.config[setting]) == str(item): 
289                 selector.set_active(0, index)
290             index += 1
291         selector.connect("changed", self.selection_changed, setting)
292         #self.pickerDialog.set_selector(selector)
293         return selector
294         #self.pickerDialog.show_all()
295
296     def getFontSize(self):
297         return self.config["fontSize"]
298     def getArtFontSize(self):
299         return self.config["artFontSize"]
300     def getExpiry(self):
301         return self.config["expiry"]
302     def isAutoUpdateEnabled(self):
303         return self.config["autoupdate"]
304     def getWoodchuckEnabled(self):
305         return self.config["woodchuck"]
306     def getAskedAboutWoodchuck(self):
307         return self.config["askedAboutWoodchuck"]
308     def setAskedAboutWoodchuck(self, value):
309         self.config["askedAboutWoodchuck"] = value
310         self.saveConfig()
311     def getUpdateInterval(self):
312         return float(self.config["updateInterval"])
313     def getReadFont(self):
314         return "sans italic %s" % self.config["fontSize"]
315     def getUnreadFont(self):
316         return "sans %s" % self.config["fontSize"]
317     def getOrientation(self):
318         return ranges["orientation"].index(self.config["orientation"])
319     def getImageCache(self):
320         return self.config["imageCache"]
321     @mainthread
322     def getProxy(self):
323         if self.config["proxy"] == False:
324             return (False, None)
325         if client_get_default().get_bool('/system/http_proxy/use_http_proxy'):
326             port = client_get_default().get_int('/system/http_proxy/port')
327             http = client_get_default().get_string('/system/http_proxy/host')
328             proxy = ProxyHandler( {"http":"http://%s:%s/"% (http,port)} )
329             return (True, proxy)
330         return (False, None)
331     def getHideReadFeeds(self):
332         return self.config["hidereadfeeds"]
333     def getHideReadArticles(self):
334         return self.config["hidereadarticles"]
335     def getOpenInExternalBrowser(self):
336         return self.config["extBrowser"]
337     def getFeedSortOrder(self):
338         return self.config["feedsort"]