5 from PySide import QtGui
6 from PySide import QtDeclarative
8 from os import mkdir, remove, stat, environ
9 from os.path import isfile, isdir, exists
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)
17 #from feedingitdbus import ServerObject
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
22 from rss_sqlite import Listing
23 CONFIGDIR = environ.get("HOME", "/home/user") + "/.feedingit/"
24 #CONFIGDIR = "/home/user/.feedingit"
27 logger = logging.getLogger(__name__)
30 debugging.init(dot_directory=".feedingit", program_name="feedingit-pyside")
32 from cgi import escape
35 class Controller(QtCore.QObject):
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)
45 def update_progress(self, percent_complete,
46 completed, in_progress, queued,
47 bytes_downloaded, bytes_updated, bytes_per_second,
49 total = completed + in_progress + queued
50 root.updateProgress(int(total), int(completed))
52 def articleCountUpdated(self):
53 #print "article updated"
56 def update_started(self):
59 def update_finished(self):
62 def openFeed(self, key):
63 # Called from dbus to open specific feed
66 @QtCore.Slot(str,str, result=str)
67 def getArticle(self, key, article):
68 feed = listing.getFeed(key)
70 file = codecs.open(feed.getContentLink(article), "r", "utf-8")
71 html = file.read().replace("body", "body bgcolor='#ffffff'", 1)
74 html = u"<html><body>Error retrieving article</body></html>"
77 @QtCore.Slot(str, result=str)
78 def getFeedsXml(self, catid):
79 return self._handler.generateFeedsXml(catid)
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())
88 @QtCore.Slot(str,str,bool,result=str)
89 def getNextId(self, key, articleid, onlyUnread):
91 #print self.cachedList, articleid
92 index = self.cachedList.index(articleid)
93 return self.cachedList[(index + 1) % len(self.cachedList)]
95 feed = listing.getFeed(key)
96 return feed.getNextId(articleid)
98 @QtCore.Slot(str,str,bool,result=str)
99 def getPreviousId(self, key, articleid, onlyUnread):
101 #print self.cachedList, articleid
102 index = self.cachedList.index(articleid)
103 return self.cachedList[(index - 1) % len(self.cachedList)]
105 feed = listing.getFeed(key)
106 return feed.getPreviousId(articleid)
108 @QtCore.Slot(result=str)
109 def getCategoryXml(self):
110 return self._handler.generateCategoryXml()
112 @QtCore.Slot(QtCore.QObject)
113 def feedClicked(self, wrapper):
114 #print 'User clicked on:', wrapper._key
115 #articlesModel.updateModel(wrapper._key)
119 def updateFeed(self, key):
120 listing.updateFeed(key)
124 for catid in listing.getListOfCategories():
125 for feed in listing.getSortedListOfKeys("Manual", category=catid):
126 listing.updateFeed(feed)
129 def updateCategory(self, catid):
130 for feed in listing.getSortedListOfKeys("Manual", category=catid):
131 listing.updateFeed(feed)
133 @QtCore.Slot(str,str,str)
134 def addFeed(self, title, url, catid):
135 listing.addFeed(title,url, category=catid)
138 def addCategory(self, name):
139 listing.addCategory(name)
142 def removeFeed(self, key):
143 listing.removeFeed(key)
146 def removeCategory(self, catid):
147 listing.removeCategory(catid)
150 def markAllAsRead(self, key):
151 feed = listing.getFeed(key)
153 listing.updateUnread(key)
155 @QtCore.Slot(str, str)
156 def setEntryRead(self, key, articleid):
157 feed = listing.getFeed(key)
158 feed.setEntryRead(articleid)
159 listing.updateUnread(key)
161 @QtCore.Slot(str, result=str)
162 def getConfig(self, item):
163 if (item == "hideReadFeed"):
165 if (item == "hideReadArticles"):
169 @QtCore.Slot(str, str)
170 def populateFileDialog(self, path, type):
173 for file in glob.glob(path+type):
175 root.addFileNotification(file, os.path.basename(file))
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())
183 for (title, url) in feeds:
184 listing.addFeed(title, url)
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
192 str = getOpmlText(listing)
193 file = open(filename, "w")
198 logger.debug("Error exporting: %s" % filename)
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()
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()
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)
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)
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"],)
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'
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)),] )
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)
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)
277 client_get_default().unset('/apps/ControlPanel/FeedingIt/EventFeed/Hide/'+key)
279 client_get_default().set_bool('/apps/ControlPanel/FeedingIt/EventFeed/Hide/'+key, True)
283 if not isdir(CONFIGDIR):
287 logger.error("Error: Can't create configuration directory")
291 from config import Config
293 config = Config(None,CONFIGDIR+"config.ini")
296 listing = Listing(config, CONFIGDIR)
301 from jobmanager import JobManager
304 app = QtGui.QApplication(sys.argv)
305 view = QtDeclarative.QDeclarativeView()
307 controller = Controller(listing)
309 # listen on dbus for download update progress
310 bus = dbus.SessionBus()
312 bus.add_signal_receiver(handler_function=controller.update_progress,
314 signal_name='UpdateProgress',
315 dbus_interface='org.marcoz.feedingit',
316 path='/org/marcoz/feedingit/update')
318 bus.add_signal_receiver(handler_function=controller.articleCountUpdated,
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,
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,
330 signal_name='UpdateFinished',
331 dbus_interface='org.marcoz.feedingit',
332 path='/org/marcoz/feedingit/update')
335 rc = view.rootContext()
337 rc.setContextProperty('controller', controller)
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)
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()
349 view.setSource(os.path.join('qml','main.qml'))
351 #view.setSource(os.path.join('qml','FeedingIt.qml'))
352 root = view.rootObject()
354 #view.showFullScreen()
356 sys.exit(app.exec_())
358 if __name__ == "__main__":