psa: fix dbus call to open automatic update settings
[feedingit] / FeedingIt-Sync / pysrc / feedingit.py
1 #!/usr/bin/python
2
3 import sys
4
5 from PySide import QtGui
6 from PySide import QtDeclarative
7 import os
8 from os import mkdir, remove, stat, environ
9 from os.path import isfile, isdir, exists
10 import codecs
11 import dbus
12 # import python dbus GLib mainloop support
13 import dbus.mainloop.glib
14 # Enable glib main loop support
15 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
16
17 #from feedingitdbus import ServerObject
18
19 # Comment the line below if you don't want to use OpenGL for QML rendering or if it is not supported
20 from PySide import QtOpenGL,  QtCore
21
22 from rss_sqlite import Listing
23 CONFIGDIR = environ.get("HOME", "/home/user") + "/.feedingit/"
24 #CONFIGDIR = "/home/user/.feedingit"
25
26 import logging
27 logger = logging.getLogger(__name__)
28
29 import debugging
30 debugging.init(dot_directory=".feedingit", program_name="feedingit-pyside")
31
32 from cgi import escape
33 from re import sub
34
35 class Controller(QtCore.QObject):
36     cachedList = None
37     
38     def __init__(self, listing):
39         QtCore.QObject.__init__(self)
40         from XmlHandler import XmlHandler
41         self._handler = XmlHandler(listing)
42         # Initialize the DBus interface.
43         #self.dbusHandler = ServerObject(self)
44         
45     def update_progress(self, percent_complete,
46                         completed, in_progress, queued,
47                         bytes_downloaded, bytes_updated, bytes_per_second,
48                         feed_updated):
49         total = completed + in_progress + queued
50         root.updateProgress(int(total), int(completed))
51         
52     def articleCountUpdated(self):
53         #print "article updated"
54         pass
55     
56     def update_started(self):
57         root.updateStarted()
58     
59     def update_finished(self):
60         root.updateFinished()
61         
62     def openFeed(self, key):
63         # Called from dbus to open specific feed
64         root.openFeed(key)
65
66     @QtCore.Slot(str,str, result=str)
67     def getArticle(self, key, article):
68        feed = listing.getFeed(key)
69        try:
70           file = codecs.open(feed.getContentLink(article), "r", "utf-8")
71           html = file.read().replace("body", "body bgcolor='#ffffff'", 1)
72           file.close()
73        except:
74           html = u"<html><body>Error retrieving article</body></html>"
75        return html
76     
77     @QtCore.Slot(str, result=str)
78     def getFeedsXml(self, catid):
79         return self._handler.generateFeedsXml(catid)
80     
81     @QtCore.Slot(str,result=str)
82     def getArticlesXml(self, key):
83         feed = listing.getFeed(key)
84         self.cachedList = feed.getIds(onlyUnread=True)
85         #onlyUnread = arguments.get("onlyUnread","False")
86         return self._handler.generateArticlesXml(key, config.getHideReadArticles())
87     
88     @QtCore.Slot(str,str,bool,result=str)
89     def getNextId(self, key, articleid, onlyUnread):
90         if (onlyUnread):
91             #print self.cachedList, articleid
92             index = self.cachedList.index(articleid)
93             return self.cachedList[(index + 1) % len(self.cachedList)]
94         else:
95             feed = listing.getFeed(key)
96             return feed.getNextId(articleid)
97         
98     @QtCore.Slot(str,str,bool,result=str)
99     def getPreviousId(self, key, articleid, onlyUnread):
100         if (onlyUnread):
101             #print self.cachedList, articleid
102             index = self.cachedList.index(articleid)
103             return self.cachedList[(index - 1) % len(self.cachedList)]
104         else:
105             feed = listing.getFeed(key)
106             return feed.getPreviousId(articleid)
107     
108     @QtCore.Slot(result=str)
109     def getCategoryXml(self):
110         return self._handler.generateCategoryXml()
111     
112     @QtCore.Slot(QtCore.QObject)
113     def feedClicked(self, wrapper):
114         #print 'User clicked on:', wrapper._key
115         #articlesModel.updateModel(wrapper._key)
116         pass
117         
118     @QtCore.Slot(str)
119     def updateFeed(self, key):
120         listing.updateFeed(key)
121         
122     @QtCore.Slot()
123     def updateAll(self):
124         for catid in listing.getListOfCategories():
125             for feed in listing.getSortedListOfKeys("Manual", category=catid):
126                 listing.updateFeed(feed)
127
128     @QtCore.Slot(str)
129     def updateCategory(self, catid):
130         for feed in listing.getSortedListOfKeys("Manual", category=catid):
131             listing.updateFeed(feed)           
132
133     @QtCore.Slot(str,str,str)
134     def addFeed(self, title, url, catid):
135         listing.addFeed(title,url, category=catid)
136         
137     @QtCore.Slot(str)
138     def addCategory(self, name):
139         listing.addCategory(name)
140
141     @QtCore.Slot(str)
142     def removeFeed(self, key):
143         listing.removeFeed(key)
144
145     @QtCore.Slot(str)
146     def removeCategory(self, catid):
147         listing.removeCategory(catid)
148
149     @QtCore.Slot(str)
150     def markAllAsRead(self, key):
151         feed = listing.getFeed(key)
152         feed.markAllAsRead()
153         listing.updateUnread(key)
154
155     @QtCore.Slot(str, str)
156     def setEntryRead(self, key, articleid):
157         feed = listing.getFeed(key)
158         feed.setEntryRead(articleid)
159         listing.updateUnread(key)
160
161     @QtCore.Slot(str, result=str)
162     def getConfig(self, item):
163         if (item == "hideReadFeed"):
164             return "True"
165         if (item == "hideReadArticles"):
166             return "False"
167         return ""
168     
169     @QtCore.Slot(str, str)
170     def populateFileDialog(self, path, type):
171         import glob
172         import os.path
173         for file in glob.glob(path+type):
174             logger.debug(file)
175             root.addFileNotification(file, os.path.basename(file))
176     
177     @QtCore.Slot(str, result=int)
178     def importOpml(self, filename):
179         from opml_lib import parseOpml
180         file = open(filename, "r")
181         feeds = parseOpml(file.read())
182         file.close()
183         for (title, url) in feeds:
184             listing.addFeed(title, url)
185         return len(feeds)
186     
187     @QtCore.Slot(str, result=str)
188     def exportOpml(self, filename="/home/user/MyDocs/feedingit-export.opml"):
189         logger.debug("ExportOpmlData: %s" % filename)
190         from opml_lib import getOpmlText
191         try:
192             str = getOpmlText(listing)
193             file = open(filename, "w")
194             file.write(str)
195             file.close()
196             return filename
197         except:
198             logger.debug("Error exporting: %s" % filename)
199             return "error"
200         
201     @QtCore.Slot(str, result=bool)
202     def getBooleanSetting(self, setting):
203         if (setting == "theme"):
204             return config.getTheme()
205         elif (setting == "imageCache" ):
206             return config.getImageCache()
207         elif (setting == "hideReadFeeds"):
208             return config.getHideReadFeeds()
209         elif (setting == "hideReadArticles"):
210             return config.getHideReadArticles()
211         elif (setting == "autoupdate"):
212             return config.isAutoUpdateEnabled()
213         else:
214             return 'True'
215         
216     @QtCore.Slot(str, result=int)
217     def getIntSetting(self, setting):
218         if (setting == "artFontSize"):
219             return config.getArtFontSize()
220         elif (setting == "fontSize" ):
221             return config.getFontSize()
222         else:
223             return -1
224         
225     @QtCore.Slot(str, bool)
226     def setBooleanSetting(self, setting, value):
227         if (setting == "theme"):
228             config.setTheme(value)
229         elif (setting == "imageCache" ):
230             config.setImageCache(value)
231         elif (setting == "hideReadFeeds"):
232             config.setHideReadFeeds(value)
233         elif (setting == "hideReadArticles"):
234             config.setHideReadArticles(value)
235         elif (setting == "autoupdate"):
236             config.setAutoUpdateEnabled(value)
237         config.saveConfig()
238         
239     @QtCore.Slot(str, int)
240     def setIntSetting(self, setting, value):
241         if (setting == "artFontSize"):
242             config.setArtFontSize(value)
243         elif (setting == "fontSize" ):
244             config.setFontSize(value)
245         config.saveConfig()
246     
247     @QtCore.Slot()
248     def openSettings(self):
249         bus = dbus.SessionBus()
250         settingService = bus.get_object('com.nokia.DuiControlPanel', '/')
251         setting = settingService.get_dbus_method('appletPage', 'com.nokia.DuiControlPanelIf')
252         setting(["FeedingIt"],)
253
254     @QtCore.Slot(str, str)
255     def share(self, key, articleid):
256         feed = listing.getFeed(key)
257         title = feed.getTitle(articleid)
258         link = feed.getExternalLink(articleid)
259         description = 'Shared%20via%20FeedingIt%20on%20Meego'
260         import urllib
261         bus = dbus.SessionBus()
262         shareService = bus.get_object('com.nokia.ShareUi', '/')
263         share = shareService.get_dbus_method('share', 'com.nokia.maemo.meegotouch.ShareUiInterface')
264         #share([u'data:text/x-url;description=Support%20for%20Nokia%20Developers;title=Forum%20Nokia,http%3A%2F%2Fforum.nokia.com',])
265         share( ['data:text/x-url;title=%s;description=%s,%s' %(urllib.quote(title), description, urllib.quote(link)),] )
266         
267     @QtCore.Slot(str, result=bool)
268     def getFeedEventStatus(self, key):
269         from gconf import client_get_default
270         return client_get_default().get_bool('/apps/ControlPanel/FeedingIt/EventFeed/Hide/'+key)
271     
272     @QtCore.Slot(str)
273     def switchEventFeedStatus(self, key):
274         from gconf import client_get_default
275         value = client_get_default().get_bool('/apps/ControlPanel/FeedingIt/EventFeed/Hide/'+key)
276         if value:
277             client_get_default().unset('/apps/ControlPanel/FeedingIt/EventFeed/Hide/'+key)
278         else:
279             client_get_default().set_bool('/apps/ControlPanel/FeedingIt/EventFeed/Hide/'+key, True)
280     
281
282 def main():
283     if not isdir(CONFIGDIR):
284         try:
285             mkdir(CONFIGDIR)
286         except:
287             logger.error("Error: Can't create configuration directory")
288             from sys import exit
289             exit(1)
290             
291     from config import Config
292     global config
293     config = Config(None,CONFIGDIR+"config.ini")
294
295     global listing
296     listing = Listing(config, CONFIGDIR)
297     
298     import mainthread
299     mainthread.init()
300
301     from jobmanager import JobManager
302     JobManager(True)
303
304     app = QtGui.QApplication(sys.argv)
305     view = QtDeclarative.QDeclarativeView()
306
307     controller = Controller(listing)
308  
309     # listen on dbus for download update progress
310     bus = dbus.SessionBus()
311     
312     bus.add_signal_receiver(handler_function=controller.update_progress,
313                             bus_name=None,
314                             signal_name='UpdateProgress',
315                             dbus_interface='org.marcoz.feedingit',
316                             path='/org/marcoz/feedingit/update')
317     
318     bus.add_signal_receiver(handler_function=controller.articleCountUpdated,
319                             bus_name=None,
320                             signal_name='ArticleCountUpdated',
321                             dbus_interface='org.marcoz.feedingit',
322                             path='/org/marcoz/feedingit/update')
323     bus.add_signal_receiver(handler_function=controller.update_started,
324                             bus_name=None,
325                             signal_name='UpdateStarted',
326                             dbus_interface='org.marcoz.feedingit',
327                             path='/org/marcoz/feedingit/update')
328     bus.add_signal_receiver(handler_function=controller.update_finished,
329                             bus_name=None,
330                             signal_name='UpdateFinished',
331                             dbus_interface='org.marcoz.feedingit',
332                             path='/org/marcoz/feedingit/update')
333  
334     global root
335     rc = view.rootContext()
336  
337     rc.setContextProperty('controller', controller)
338
339     # Comment the two lines below if you don't want to use OpenGL for QML rendering or if it is not supported
340     #glw = QtOpenGL.QGLWidget()
341     #view.setViewport(glw)
342
343     if os.path.exists('/usr/share/feedingit/qml'):
344         glw = QtOpenGL.QGLWidget()
345         view.setViewport(glw)
346         view.setSource('/usr/share/feedingit/qml/main.qml')
347         view.showFullScreen()
348     else:
349         view.setSource(os.path.join('qml','main.qml'))
350         view.show()
351         #view.setSource(os.path.join('qml','FeedingIt.qml'))
352     root = view.rootObject()
353
354     #view.showFullScreen()
355     #view.show()
356     sys.exit(app.exec_())
357
358 if __name__ == "__main__": 
359     main()