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 # Comment the line below if you don't want to use OpenGL for QML rendering or if it is not supported
18 from PySide import QtOpenGL, QtCore
20 from rss_sqlite import Listing
21 CONFIGDIR = environ.get("HOME", "/home/user") + "/.feedingit/"
22 #CONFIGDIR = "/home/user/.feedingit"
25 logger = logging.getLogger(__name__)
28 debugging.init(dot_directory=".feedingit", program_name="feedingit-pyside")
30 from cgi import escape
33 class Controller(QtCore.QObject):
36 def __init__(self, listing):
37 QtCore.QObject.__init__(self)
38 from XmlHandler import XmlHandler
39 self._handler = XmlHandler(listing)
41 def update_progress(self, percent_complete,
42 completed, in_progress, queued,
43 bytes_downloaded, bytes_updated, bytes_per_second,
45 total = completed + in_progress + queued
46 root.updateProgress(int(total), int(completed))
48 def articleCountUpdated(self):
49 #print "article updated"
52 def update_started(self):
55 def update_finished(self):
58 @QtCore.Slot(str,str, result=str)
59 def getArticle(self, key, article):
60 feed = listing.getFeed(key)
62 file = codecs.open(feed.getContentLink(article), "r", "utf-8")
63 html = file.read().replace("body", "body bgcolor='#ffffff'", 1)
66 html = u"<html><body>Error retrieving article</body></html>"
69 @QtCore.Slot(str, result=str)
70 def getFeedsXml(self, catid):
71 return self._handler.generateFeedsXml(catid)
73 @QtCore.Slot(str,result=str)
74 def getArticlesXml(self, key):
75 feed = listing.getFeed(key)
76 self.cachedList = feed.getIds(onlyUnread=True)
77 #onlyUnread = arguments.get("onlyUnread","False")
78 return self._handler.generateArticlesXml(key, config.getHideReadArticles())
80 @QtCore.Slot(str,str,bool,result=str)
81 def getNextId(self, key, articleid, onlyUnread):
83 #print self.cachedList, articleid
84 index = self.cachedList.index(articleid)
85 return self.cachedList[(index + 1) % len(self.cachedList)]
87 feed = listing.getFeed(key)
88 return feed.getNextId(articleid)
90 @QtCore.Slot(str,str,bool,result=str)
91 def getPreviousId(self, key, articleid, onlyUnread):
93 #print self.cachedList, articleid
94 index = self.cachedList.index(articleid)
95 return self.cachedList[(index - 1) % len(self.cachedList)]
97 feed = listing.getFeed(key)
98 return feed.getPreviousId(articleid)
100 @QtCore.Slot(result=str)
101 def getCategoryXml(self):
102 return self._handler.generateCategoryXml()
104 @QtCore.Slot(QtCore.QObject)
105 def feedClicked(self, wrapper):
106 #print 'User clicked on:', wrapper._key
107 #articlesModel.updateModel(wrapper._key)
111 def updateFeed(self, key):
112 listing.updateFeed(key)
116 for catid in listing.getListOfCategories():
117 for feed in listing.getSortedListOfKeys("Manual", category=catid):
118 listing.updateFeed(feed)
121 def updateCategory(self, catid):
122 for feed in listing.getSortedListOfKeys("Manual", category=catid):
123 listing.updateFeed(feed)
125 @QtCore.Slot(str,str,str)
126 def addFeed(self, title, url, catid):
127 listing.addFeed(title,url, category=catid)
130 def addCategory(self, name):
131 listing.addCategory(name)
134 def removeFeed(self, key):
135 listing.removeFeed(key)
138 def removeCategory(self, catid):
139 listing.removeCategory(catid)
142 def markAllAsRead(self, key):
143 feed = listing.getFeed(key)
145 listing.updateUnread(key)
147 @QtCore.Slot(str, str)
148 def setEntryRead(self, key, articleid):
149 feed = listing.getFeed(key)
150 feed.setEntryRead(articleid)
151 listing.updateUnread(key)
153 @QtCore.Slot(str, result=str)
154 def getConfig(self, item):
155 if (item == "hideReadFeed"):
157 if (item == "hideReadArticles"):
161 @QtCore.Slot(str, str)
162 def populateFileDialog(self, path, type):
165 for file in glob.glob(path+type):
167 root.addFileNotification(file, os.path.basename(file))
169 @QtCore.Slot(str, result=int)
170 def importOpml(self, filename):
171 from opml_lib import parseOpml
172 file = open(filename, "r")
173 feeds = parseOpml(file.read())
175 for (title, url) in feeds:
176 listing.addFeed(title, url)
179 @QtCore.Slot(str, result=str)
180 def exportOpml(self, filename="/home/user/MyDocs/feedingit-export.opml"):
181 logger.debug("ExportOpmlData: %s" % filename)
182 from opml_lib import getOpmlText
184 str = getOpmlText(listing)
185 file = open(filename, "w")
190 logger.debug("Error exporting: %s" % filename)
193 @QtCore.Slot(str, result=bool)
194 def getBooleanSetting(self, setting):
195 if (setting == "theme"):
196 return config.getTheme()
197 elif (setting == "imageCache" ):
198 return config.getImageCache()
199 elif (setting == "hideReadFeeds"):
200 return config.getHideReadFeeds()
201 elif (setting == "hideReadArticles"):
202 return config.getHideReadArticles()
203 elif (setting == "autoupdate"):
204 return config.isAutoUpdateEnabled()
208 @QtCore.Slot(str, result=int)
209 def getIntSetting(self, setting):
210 if (setting == "artFontSize"):
211 return config.getArtFontSize()
212 elif (setting == "fontSize" ):
213 return config.getFontSize()
217 @QtCore.Slot(str, bool)
218 def setBooleanSetting(self, setting, value):
219 if (setting == "theme"):
220 config.setTheme(value)
221 elif (setting == "imageCache" ):
222 config.setImageCache(value)
223 elif (setting == "hideReadFeeds"):
224 config.setHideReadFeeds(value)
225 elif (setting == "hideReadArticles"):
226 config.setHideReadArticles(value)
227 elif (setting == "autoupdate"):
228 config.setAutoUpdateEnabled(value)
231 @QtCore.Slot(str, int)
232 def setIntSetting(self, setting, value):
233 if (setting == "artFontSize"):
234 config.setArtFontSize(value)
235 elif (setting == "fontSize" ):
236 config.setFontSize(value)
239 @QtCore.Slot(str, str)
240 def openSettings(self):
241 bus = dbus.SessionBus()
242 settingService = bus.get_object('com.nokia.DuiControlPanel', '/')
243 setting = shareService.get_dbus_method('appletPage', 'com.nokia.DuiControlPanelIf')
246 @QtCore.Slot(str, str)
247 def share(self, key, articleid):
248 feed = listing.getFeed(key)
249 title = feed.getTitle(articleid)
250 link = feed.getExternalLink(articleid)
251 description = 'Shared%20via%20FeedingIt%20on%20Meego'
253 bus = dbus.SessionBus()
254 shareService = bus.get_object('com.nokia.ShareUi', '/')
255 share = shareService.get_dbus_method('share', 'com.nokia.maemo.meegotouch.ShareUiInterface')
256 #share([u'data:text/x-url;description=Support%20for%20Nokia%20Developers;title=Forum%20Nokia,http%3A%2F%2Fforum.nokia.com',])
257 share( ['data:text/x-url;title=%s;description=%s,%s' %(urllib.quote(title), description, urllib.quote(link)),] )
259 @QtCore.Slot(str, result=bool)
260 def getFeedEventStatus(self, key):
261 from gconf import client_get_default
262 return client_get_default().get_bool('/apps/ControlPanel/FeedingIt/EventFeed/Hide/'+key)
265 def switchEventFeedStatus(self, key):
266 from gconf import client_get_default
267 value = client_get_default().get_bool('/apps/ControlPanel/FeedingIt/EventFeed/Hide/'+key)
269 client_get_default().unset('/apps/ControlPanel/FeedingIt/EventFeed/Hide/'+key)
271 client_get_default().set_bool('/apps/ControlPanel/FeedingIt/EventFeed/Hide/'+key, True)
275 if not isdir(CONFIGDIR):
279 logger.error("Error: Can't create configuration directory")
283 from config import Config
285 config = Config(None,CONFIGDIR+"config.ini")
288 listing = Listing(config, CONFIGDIR)
293 from jobmanager import JobManager
296 app = QtGui.QApplication(sys.argv)
297 view = QtDeclarative.QDeclarativeView()
299 controller = Controller(listing)
301 # listen on dbus for download update progress
302 bus = dbus.SessionBus()
304 bus.add_signal_receiver(handler_function=controller.update_progress,
306 signal_name='UpdateProgress',
307 dbus_interface='org.marcoz.feedingit',
308 path='/org/marcoz/feedingit/update')
310 bus.add_signal_receiver(handler_function=controller.articleCountUpdated,
312 signal_name='ArticleCountUpdated',
313 dbus_interface='org.marcoz.feedingit',
314 path='/org/marcoz/feedingit/update')
315 bus.add_signal_receiver(handler_function=controller.update_started,
317 signal_name='UpdateStarted',
318 dbus_interface='org.marcoz.feedingit',
319 path='/org/marcoz/feedingit/update')
320 bus.add_signal_receiver(handler_function=controller.update_finished,
322 signal_name='UpdateFinished',
323 dbus_interface='org.marcoz.feedingit',
324 path='/org/marcoz/feedingit/update')
327 rc = view.rootContext()
329 rc.setContextProperty('controller', controller)
331 # Comment the two lines below if you don't want to use OpenGL for QML rendering or if it is not supported
332 #glw = QtOpenGL.QGLWidget()
333 #view.setViewport(glw)
335 if os.path.exists('/usr/share/feedingit/qml'):
336 glw = QtOpenGL.QGLWidget()
337 view.setViewport(glw)
338 view.setSource('/usr/share/feedingit/qml/main.qml')
339 view.showFullScreen()
341 view.setSource(os.path.join('qml','main.qml'))
343 #view.setSource(os.path.join('qml','FeedingIt.qml'))
344 root = view.rootObject()
346 #view.showFullScreen()
348 sys.exit(app.exec_())
350 if __name__ == "__main__":