psa: improved add feed/categories dialog
authorYves Marcoz <yves@marcoz.org>
Tue, 8 Nov 2011 05:34:24 +0000 (21:34 -0800)
committerYves Marcoz <yves@marcoz.org>
Tue, 8 Nov 2011 05:34:24 +0000 (21:34 -0800)
black/white theme support
delete categories/feeds support

43 files changed:
psa_harmattan/feedingit/build-deb.log
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/changelog
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/control
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/DEBIAN/control
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/DEBIAN/md5sums
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/doc/feedingit/changelog.Debian.gz
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/XmlHandler.py
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/debugging.py
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/feedingit.py
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/qml/ArticleViewer.qml
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/qml/Categories.qml
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/qml/Feeds.qml
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/qml/TestWebview.qml
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/qml/main.qml
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/rss_sqlite.py
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/pyshared/feedingit-0.1.0.egg-info
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/rules
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/feedingit.longdesc
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/pysrc/XmlHandler.py
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/pysrc/debugging.py
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/pysrc/feedingit.py
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/pysrc/rss_sqlite.py
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/qml/ArticleViewer.qml
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/qml/Categories.qml
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/qml/Feeds.qml
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/qml/TestWebview.qml
psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/qml/main.qml
psa_harmattan/feedingit/deb_dist/feedingit_0.1.0-1.debian.tar.gz
psa_harmattan/feedingit/deb_dist/feedingit_0.1.0-1.dsc
psa_harmattan/feedingit/deb_dist/feedingit_0.1.0-1_all.deb
psa_harmattan/feedingit/deb_dist/feedingit_0.1.0-1_i386.changes
psa_harmattan/feedingit/deb_dist/feedingit_0.1.0.orig.tar.gz
psa_harmattan/feedingit/feedingit.longdesc
psa_harmattan/feedingit/pysrc/XmlHandler.py
psa_harmattan/feedingit/pysrc/feedingit.py
psa_harmattan/feedingit/pysrc/rss_sqlite.py
psa_harmattan/feedingit/qml/AddFeed.qml
psa_harmattan/feedingit/qml/ArticleViewer.qml
psa_harmattan/feedingit/qml/Categories.qml
psa_harmattan/feedingit/qml/Feeds.qml
psa_harmattan/feedingit/qml/Settings.qml [new file with mode: 0644]
psa_harmattan/feedingit/qml/main.qml
src/rss_sqlite.py

index 71a7529..ffed24a 100644 (file)
@@ -74,6 +74,7 @@ copying qml/TextInputClear.qml -> /scratchbox/users/ymarcoz/home/ymarcoz/workspa
 copying qml/ArticleViewer.qml -> /scratchbox/users/ymarcoz/home/ymarcoz/workspace/feedingit/psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/qml
 copying qml/MainPage.qml -> /scratchbox/users/ymarcoz/home/ymarcoz/workspace/feedingit/psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/qml
 copying qml/main.qml -> /scratchbox/users/ymarcoz/home/ymarcoz/workspace/feedingit/psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/qml
 copying qml/ArticleViewer.qml -> /scratchbox/users/ymarcoz/home/ymarcoz/workspace/feedingit/psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/qml
 copying qml/MainPage.qml -> /scratchbox/users/ymarcoz/home/ymarcoz/workspace/feedingit/psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/qml
 copying qml/main.qml -> /scratchbox/users/ymarcoz/home/ymarcoz/workspace/feedingit/psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/qml
+copying qml/Settings.qml -> /scratchbox/users/ymarcoz/home/ymarcoz/workspace/feedingit/psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/qml
 copying qml/ArticleDisplay.qml -> /scratchbox/users/ymarcoz/home/ymarcoz/workspace/feedingit/psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/qml
 copying qml/AddFeed.qml -> /scratchbox/users/ymarcoz/home/ymarcoz/workspace/feedingit/psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/qml
 copying qml/feedSearch.js -> /scratchbox/users/ymarcoz/home/ymarcoz/workspace/feedingit/psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/qml
 copying qml/ArticleDisplay.qml -> /scratchbox/users/ymarcoz/home/ymarcoz/workspace/feedingit/psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/qml
 copying qml/AddFeed.qml -> /scratchbox/users/ymarcoz/home/ymarcoz/workspace/feedingit/psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/qml
 copying qml/feedSearch.js -> /scratchbox/users/ymarcoz/home/ymarcoz/workspace/feedingit/psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/feedingit/qml
index 1603ef9..88ed358 100644 (file)
@@ -2,4 +2,4 @@ feedingit (0.1.0-1) unstable; urgency=low
 
   * source package automatically created by stdeb 0.6.0+git
 
 
   * source package automatically created by stdeb 0.6.0+git
 
- -- Yves <yves@marcoz.org>  Sun, 06 Nov 2011 21:13:19 -0800
+ -- Yves <yves@marcoz.org>  Mon, 07 Nov 2011 21:25:40 -0800
index 7fc9752..4414804 100644 (file)
@@ -11,8 +11,9 @@ Architecture: all
 Depends: ${misc:Depends}, python-pyside.qtgui, python-pyside.qtopengl, python-pyside.qtdeclarative, python-dbus, python-gconf
 Breaks: ${python:Breaks}
 Description: FeedingIt - RSS Reader
 Depends: ${misc:Depends}, python-pyside.qtgui, python-pyside.qtopengl, python-pyside.qtdeclarative, python-dbus, python-gconf
 Breaks: ${python:Breaks}
 Description: FeedingIt - RSS Reader
- This file should contain a writeup describing what your application does,
- and how to use it. The content of this file goes into the long_description
- field of setup.py, which in turn becomes the long version of the Description
- field in the debian/control file of the project.
+ FeedingIt is an easy to use RSS feed reader with portrait mode support and 
+ automatic feed updates. You can swipe left and right to move between articles.
+ Import and export of subscription lists is supported for OPML files.
+ Images can be cached during the feed update, so you can view images in the
+ downloaded articles while offline.
  .
  .
index 037b0fa..4ad45af 100644 (file)
@@ -2,13 +2,14 @@ Package: feedingit
 Version: 0.1.0-1
 Architecture: all
 Maintainer: Yves <yves@marcoz.org>
 Version: 0.1.0-1
 Architecture: all
 Maintainer: Yves <yves@marcoz.org>
-Installed-Size: 756
+Installed-Size: 764
 Depends: python-pyside.qtgui, python-pyside.qtopengl, python-pyside.qtdeclarative, python-dbus, python-gconf
 Breaks: python (<< 2.6)
 Section: user/development
 Priority: optional
 Description: FeedingIt - RSS Reader
 Depends: python-pyside.qtgui, python-pyside.qtopengl, python-pyside.qtdeclarative, python-dbus, python-gconf
 Breaks: python (<< 2.6)
 Section: user/development
 Priority: optional
 Description: FeedingIt - RSS Reader
- This file should contain a writeup describing what your application does,
- and how to use it. The content of this file goes into the long_description
- field of setup.py, which in turn becomes the long version of the Description
- field in the debian/control file of the project.
+ FeedingIt is an easy to use RSS feed reader with portrait mode support and
+ automatic feed updates. You can swipe left and right to move between articles.
+ Import and export of subscription lists is supported for OPML files.
+ Images can be cached during the feed update, so you can view images in the
+ downloaded articles while offline.
index 6649503..a74cf8d 100644 (file)
@@ -1,28 +1,29 @@
 4420c31f88de68fe6e1b7637abb06196  usr/bin/feedingit
 6a42e9aebedfd157062bd5a9616dc935  usr/share/applications/feedingit.desktop
 eda8cc6ffe8d842d6dfe0244b01b3042  usr/share/dbus-1/services/feedingit_status.service
 4420c31f88de68fe6e1b7637abb06196  usr/bin/feedingit
 6a42e9aebedfd157062bd5a9616dc935  usr/share/applications/feedingit.desktop
 eda8cc6ffe8d842d6dfe0244b01b3042  usr/share/dbus-1/services/feedingit_status.service
-8a3883bbf4914140ca72678bfdac9230  usr/share/doc/feedingit/changelog.Debian.gz
+f0e50a0975405a76169cc01da42cdcff  usr/share/doc/feedingit/changelog.Debian.gz
 bac2be6ae9673ee5096e20e8b714c9cd  usr/share/feedingit/BeautifulSoup.py
 bac2be6ae9673ee5096e20e8b714c9cd  usr/share/feedingit/BeautifulSoup.py
-fa5490f2022424a091b36e75f21e6596  usr/share/feedingit/XmlHandler.py
+8f6e980f2e1154103a90763be6c00dc4  usr/share/feedingit/XmlHandler.py
 d41d8cd98f00b204e9800998ecf8427e  usr/share/feedingit/__init__.py
 6b5296119ef6bc859c3e3a8706fa7f0d  usr/share/feedingit/config.py
 d41d8cd98f00b204e9800998ecf8427e  usr/share/feedingit/__init__.py
 6b5296119ef6bc859c3e3a8706fa7f0d  usr/share/feedingit/config.py
-4724920e64b0f5d2828c1c245502a115  usr/share/feedingit/debugging.py
+9cf859c8297e4b0e8466cb5861eb75e7  usr/share/feedingit/debugging.py
 fae02e730b76761d43a626fe19828d5e  usr/share/feedingit/download.py
 fae02e730b76761d43a626fe19828d5e  usr/share/feedingit/download.py
-b9b632032e30e584115aecab8c809f88  usr/share/feedingit/feedingit.py
+42786634079070f54f06838e922a1307  usr/share/feedingit/feedingit.py
 afa4f462892136f59beaf96b6bf1cf96  usr/share/feedingit/feedparser.py
 c1a0c0a9ccefd64d1e27bddb817c72a3  usr/share/feedingit/httpprogresshandler.py
 f1e9ba0f44786f513659a7fa3111fc8a  usr/share/feedingit/jobmanager.py
 0201faa30d34c58d71f36ab42a7a8233  usr/share/feedingit/mainthread.py
 d9c0665dfdd5cf19f1529ce88af95134  usr/share/feedingit/opml.py
 afa4f462892136f59beaf96b6bf1cf96  usr/share/feedingit/feedparser.py
 c1a0c0a9ccefd64d1e27bddb817c72a3  usr/share/feedingit/httpprogresshandler.py
 f1e9ba0f44786f513659a7fa3111fc8a  usr/share/feedingit/jobmanager.py
 0201faa30d34c58d71f36ab42a7a8233  usr/share/feedingit/mainthread.py
 d9c0665dfdd5cf19f1529ce88af95134  usr/share/feedingit/opml.py
-37230c16aad0865afbec03d8105dd491  usr/share/feedingit/qml/AddFeed.qml
+31d26f7ae14940f99ec8d47c7035fd04  usr/share/feedingit/qml/AddFeed.qml
 af27062fdba0bc7a3df92116e8340d19  usr/share/feedingit/qml/ArticleDisplay.qml
 af27062fdba0bc7a3df92116e8340d19  usr/share/feedingit/qml/ArticleDisplay.qml
-594c82729b9e53bd9ca143006e088893  usr/share/feedingit/qml/ArticleViewer.qml
+80858d581189fcf00ab1c6192be87e27  usr/share/feedingit/qml/ArticleViewer.qml
 15083e9a1fac05c8efaaa085dfabcbcb  usr/share/feedingit/qml/Articles.qml
 15083e9a1fac05c8efaaa085dfabcbcb  usr/share/feedingit/qml/Articles.qml
-555d070ba1db23b7b553628c9ae4ce72  usr/share/feedingit/qml/Categories.qml
+8f480702a2107a8017fdd94226b9b7d4  usr/share/feedingit/qml/Categories.qml
 cd30f5eaec0885358261d7a96bfaf8cd  usr/share/feedingit/qml/FeedingIt.qml
 cd30f5eaec0885358261d7a96bfaf8cd  usr/share/feedingit/qml/FeedingIt.qml
-29e9f5811d5e5bb9b4078fb2fb8d5b17  usr/share/feedingit/qml/Feeds.qml
+02784496485eb5547a1ad48c043bb2a9  usr/share/feedingit/qml/Feeds.qml
 bec5fe4599a3ad5799ed96d7ed81fb5f  usr/share/feedingit/qml/MainPage.qml
 bec5fe4599a3ad5799ed96d7ed81fb5f  usr/share/feedingit/qml/MainPage.qml
-aa3fc0a4edbd17d93a9dc5c39c433c3d  usr/share/feedingit/qml/TestWebview.qml
+1c500d41d190f8f8c6d478fda117bb28  usr/share/feedingit/qml/Settings.qml
+53595350196421039e3adefac380d21f  usr/share/feedingit/qml/TestWebview.qml
 508fde19c7bb7bc4892bd6642fbcb7d3  usr/share/feedingit/qml/TextInputClear.qml
 cef5ae4af926a759f4a233336c00f017  usr/share/feedingit/qml/common/AddCat.qml
 c39cde168ef8d608670c81be7c808701  usr/share/feedingit/qml/common/AddFeed.qml
 508fde19c7bb7bc4892bd6642fbcb7d3  usr/share/feedingit/qml/TextInputClear.qml
 cef5ae4af926a759f4a233336c00f017  usr/share/feedingit/qml/common/AddCat.qml
 c39cde168ef8d608670c81be7c808701  usr/share/feedingit/qml/common/AddFeed.qml
@@ -56,11 +57,11 @@ af11b73b195513d08c17723b41db0b04  usr/share/feedingit/qml/common/images/wmBackIc
 1c7751b124aa1bdf4b89ec76cdf815a2  usr/share/feedingit/qml/i18n/FeedingIt.ts
 7790a99425dd7c1046e6ae3b1ee72a03  usr/share/feedingit/qml/i18n/qml_en.qm
 1674fcce45bcf3319e61d19a9adf4fdd  usr/share/feedingit/qml/i18n/qml_en.ts
 1c7751b124aa1bdf4b89ec76cdf815a2  usr/share/feedingit/qml/i18n/FeedingIt.ts
 7790a99425dd7c1046e6ae3b1ee72a03  usr/share/feedingit/qml/i18n/qml_en.qm
 1674fcce45bcf3319e61d19a9adf4fdd  usr/share/feedingit/qml/i18n/qml_en.ts
-c94a3937f0104446e0ceed1eb4aacf78  usr/share/feedingit/qml/main.qml
-7def699001828ea16976de3d5835dd3c  usr/share/feedingit/rss_sqlite.py
+0ede84085fc61707b6ee27f72ef2808c  usr/share/feedingit/qml/main.qml
+da4cc789664ec1980300d1df080c6d90  usr/share/feedingit/rss_sqlite.py
 721777a26cd2a5b8466ce2aa2b99fad7  usr/share/feedingit/update_feeds.py
 6ccf12dc4379e91800ae8505b2e86082  usr/share/feedingit/updatedbus.py
 833ff79caab7c1fa89d6ff4a2f3bb3fd  usr/share/feedingit/wc.py
 8d49c002ad8bb98837e2a642eec86fc5  usr/share/icons/hicolor/64x64/apps/feedingit.png
 721777a26cd2a5b8466ce2aa2b99fad7  usr/share/feedingit/update_feeds.py
 6ccf12dc4379e91800ae8505b2e86082  usr/share/feedingit/updatedbus.py
 833ff79caab7c1fa89d6ff4a2f3bb3fd  usr/share/feedingit/wc.py
 8d49c002ad8bb98837e2a642eec86fc5  usr/share/icons/hicolor/64x64/apps/feedingit.png
-035a8a90300ae10602a25bd24a8121c7  usr/share/pyshared/feedingit-0.1.0.egg-info
+7f4a829935d2f4cfede75830a4dd61c7  usr/share/pyshared/feedingit-0.1.0.egg-info
 1ce7b7194658769bb4173134a725d1ce  usr/share/python/runtime.d/feedingit.rtupdate
 1ce7b7194658769bb4173134a725d1ce  usr/share/python/runtime.d/feedingit.rtupdate
index 2b6e9a9..79c27ea 100644 (file)
Binary files a/psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/doc/feedingit/changelog.Debian.gz and b/psa_harmattan/feedingit/deb_dist/feedingit-0.1.0/debian/feedingit/usr/share/doc/feedingit/changelog.Debian.gz differ
index 8acdb75..41167cb 100644 (file)
@@ -49,9 +49,11 @@ class XmlHandler():
     def generateCategoryXml(self):
         xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><xml>"
         for cat in self.listing.getListOfCategories():
     def generateCategoryXml(self):
         xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><xml>"
         for cat in self.listing.getListOfCategories():
+            print cat
             xml += "<category>"
             xml += "<catname>%s</catname>" %sanitize(self.listing.getCategoryTitle(cat))
             xml += "<catid>%s</catid>" % cat
             xml += "<category>"
             xml += "<catname>%s</catname>" %sanitize(self.listing.getCategoryTitle(cat))
             xml += "<catid>%s</catid>" % cat
+            xml += "<unread>%s</unread>" % self.listing.getCategoryUnread(cat)
             xml += "</category>"
         xml += "</xml>"
         return xml
             xml += "</category>"
         xml += "</xml>"
         return xml
index 91be2b4..7330871 100644 (file)
@@ -35,7 +35,6 @@ def my_excepthook(exctype, value, tb):
     original_excepthook(exctype, value, tb)
 
 def init(dot_directory, debug=False, max_logfiles=1, program_name=None):
     original_excepthook(exctype, value, tb)
 
 def init(dot_directory, debug=False, max_logfiles=1, program_name=None):
-    debug = True
     if not os.path.isabs(dot_directory):
         dot_directory = os.path.join(os.path.expanduser("~"), dot_directory)
 
     if not os.path.isabs(dot_directory):
         dot_directory = os.path.join(os.path.expanduser("~"), dot_directory)
 
index 209c021..10d08b9 100644 (file)
@@ -7,6 +7,7 @@ from PySide import QtDeclarative
 import os
 from os import mkdir, remove, stat, environ
 from os.path import isfile, isdir, exists
 import os
 from os import mkdir, remove, stat, environ
 from os.path import isfile, isdir, exists
+import codecs
 
 # Comment the line below if you don't want to use OpenGL for QML rendering or if it is not supported
 from PySide import QtOpenGL,  QtCore
 
 # Comment the line below if you don't want to use OpenGL for QML rendering or if it is not supported
 from PySide import QtOpenGL,  QtCore
@@ -35,11 +36,11 @@ class Controller(QtCore.QObject):
     def getArticle(self, key, article):
        feed = listing.getFeed(key)
        try:
     def getArticle(self, key, article):
        feed = listing.getFeed(key)
        try:
-          file = open(feed.getContentLink(article))
+          file = codecs.open(feed.getContentLink(article), "r", "utf-8")
           html = file.read().replace("body", "body bgcolor='#ffffff'", 1)
           file.close()
        except:
           html = file.read().replace("body", "body bgcolor='#ffffff'", 1)
           file.close()
        except:
-          html = "<html><body>Error retrieving article</body></html>"
+          html = u"<html><body>Error retrieving article</body></html>"
        return html
     
     @QtCore.Slot(str, result=str)
        return html
     
     @QtCore.Slot(str, result=str)
@@ -67,9 +68,15 @@ class Controller(QtCore.QObject):
         
     @QtCore.Slot()
     def updateAll(self):
         
     @QtCore.Slot()
     def updateAll(self):
-        for feed in listing.getSortedListOfKeys("Manual"):
-            listing.updateFeed(feed)
-            
+        for catid in listing.getListOfCategories():
+            for feed in listing.getSortedListOfKeys("Manual", category=catid):
+                listing.updateFeed(feed)
+
+    @QtCore.Slot(str)
+    def updateCategory(self, catid):
+        for feed in listing.getSortedListOfKeys("Manual", category=catid):
+            listing.updateFeed(feed)           
+
     @QtCore.Slot(str,str,str)
     def addFeed(self, title, url, catid):
         listing.addFeed(title,url, category=catid)
     @QtCore.Slot(str,str,str)
     def addFeed(self, title, url, catid):
         listing.addFeed(title,url, category=catid)
@@ -79,6 +86,14 @@ class Controller(QtCore.QObject):
         listing.addCategory(name)
 
     @QtCore.Slot(str)
         listing.addCategory(name)
 
     @QtCore.Slot(str)
+    def removeFeed(self, key):
+        listing.removeFeed(key)
+
+    @QtCore.Slot(str)
+    def removeCategory(self, catid):
+        listing.removeCategory(catid)
+
+    @QtCore.Slot(str)
     def markAllAsRead(self, key):
         feed = listing.getFeed(key)
         feed.markAllAsRead()
     def markAllAsRead(self, key):
         feed = listing.getFeed(key)
         feed.markAllAsRead()
index 83898b4..ac31e0b 100644 (file)
@@ -108,16 +108,24 @@ Item {
             id: listing;
 
             Item {
             id: listing;
 
             Item {
-                width: articleViewer.width; height: 86
+                width: articleViewer.width; height: backRect.height + 3
                 id: listItem
                 id: listItem
-                Rectangle { id: backRect; color: "#dddddd"; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: listItem.width; y: 1 }
+                Rectangle {
+                    id: backRect; color: settings.backColour; opacity: index % 2 ? 0.2 : 0.4;
+                    height: articleText.height + 22; width: listItem.width;
+                    y: 1
+                }
                 Text {
                 Text {
-                    anchors.fill: backRect
+                    id: articleText
+                    anchors.verticalCenter: backRect.verticalCenter
+                    x: 3
+                    width: listItem.width - 6;
+
                     anchors.margins: 5
                     verticalAlignment: Text.AlignVCenter; text: title;
                     anchors.margins: 5
                     verticalAlignment: Text.AlignVCenter; text: title;
-                    color: (unread=="True") ? "white" : "#7b97fd";
+                    color: (unread=="True") ? settings.mainTextColour : settings.secondaryTextColour;
 
 
-                    width: listItem.width; wrapMode: Text.WordWrap; font.bold: false;
+                     wrapMode: Text.WordWrap; font.bold: false;
                     font.pointSize: 18
                 }
                 MouseArea { anchors.fill: listItem;
                     font.pointSize: 18
                 }
                 MouseArea { anchors.fill: listItem;
index 5a97370..4469ba1 100644 (file)
@@ -8,7 +8,9 @@ Item {
     signal categoryClicked(string cat)
 
     function reload() {
     signal categoryClicked(string cat)
 
     function reload() {
-        categories.reload();
+        //categories.reload();
+        categories.xml = controller.getCategoryXml()
+        //console.log(controller.getCategoryXml())
     }
 
     ListView {
     }
 
     ListView {
@@ -25,6 +27,7 @@ Item {
 
         XmlRole { name: "title"; query: "catname/string()" }
         XmlRole { name: "catid"; query: "catid/string()"; isKey: true }
 
         XmlRole { name: "title"; query: "catname/string()" }
         XmlRole { name: "catid"; query: "catid/string()"; isKey: true }
+        XmlRole { name: "unread"; query: "unread/string()" }
     }
 
     Component {
     }
 
     Component {
@@ -36,46 +39,68 @@ Item {
             Item {
                 id: moveMe
                 height: parent.height
             Item {
                 id: moveMe
                 height: parent.height
-                Rectangle { color: "#eeeeee"; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: wrapper.width; y: 1 }
+                Rectangle { color: settings.backColour; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: wrapper.width; y: 1 }
 //                Rectangle {
 //                    x: 6; y: 4; width: 77; height: parent.height - 9; color: "white"; smooth: true
 
 //                }
                 Column {
                     x: 15;
 //                Rectangle {
 //                    x: 6; y: 4; width: 77; height: parent.height - 9; color: "white"; smooth: true
 
 //                }
                 Column {
                     x: 15;
-                    width: wrapper.ListView.view.width /*- 95; y: 15*/; spacing: 2
+                    width: wrapper.ListView.view.width /*- 95;*/
+                    y: 15; spacing: 2
                     anchors.margins: 5
                     height: parent.height
 
                     anchors.margins: 5
                     height: parent.height
 
-                    Text { text: title; color: "white"; width: parent.width; font.bold: true;
-                        height: parent.height
-                        elide: Text.ElideRight; style: Text.Raised; styleColor: "black"; font.pointSize: 20
+                    Text { text: title; color: settings.mainTextColour; width: parent.width; font.bold: true;
+                        //height: parent.height
+                        elide: Text.ElideRight; style: Text.Raised;
+                        styleColor: settings.mainShadowColour;
+                        font.pointSize: settings.mainTextSize
                         verticalAlignment: Text.AlignVCenter;
                     }
                         verticalAlignment: Text.AlignVCenter;
                     }
+                    Text {
+                        text: qsTr("%1 unread items").arg(unread);
+                        color: (unread=="0") ? settings.mainTextColour : settings.secondaryTextColour;
+                        width: parent.width; font.bold: false;
+                        elide: Text.ElideRight;
+                        //style: Text.Raised; styleColor: settings.mainShadowColour;
+                        font.pointSize: settings.secondaryTextSize
+                    }
                     //Text { text: feedname; width: parent.width; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
                 }
                     //Text { text: feedname; width: parent.width; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
                 }
-                Item {
-                    x: wrapper.ListView.view.width - 128; y: 12
-                    height: 58; width: 58;
-                    //anchors.horizontalCenter: parent.horizontalCenter;
-                    Image { source: "common/images/wmEditIcon.png" }
-                    MouseArea {
-                        anchors.fill: parent; onClicked: { container.categoryEdit(catname, catid); }
-                    }
-                    visible: inEditMode
+//                Item {
+//                    x: wrapper.ListView.view.width - 128; y: 12
+//                    height: 58; width: 58;
+//                    //anchors.horizontalCenter: parent.horizontalCenter;
+//                    Image { source: "common/images/wmEditIcon.png" }
+//                    MouseArea {
+//                        anchors.fill: parent; onClicked: { container.categoryEdit(catname, catid); }
+//                    }
+//                    visible: inEditMode
+//                }
+//                Item {
+//                    x: wrapper.ListView.view.width - 64; y: 12
+//                    height: 58; width: 58;
+//                    //anchors.horizontalCenter: parent.horizontalCenter;
+//                    Image { source: "common/images/delete.png" }
+//                    MouseArea {
+//                        anchors.fill: parent; onClicked: { container.categoryDeleted(catid); }
+//                    }
+//                    visible: inEditMode
+//                }
+            }
+            MouseArea {
+                enabled: !inEditMode; anchors.fill: wrapper;
+                onClicked: { categoryClicked(catid); }
+                onPressAndHold: {
+                    window.longPressCategory(catid)
                 }
                 }
-                Item {
-                    x: wrapper.ListView.view.width - 64; y: 12
-                    height: 58; width: 58;
-                    //anchors.horizontalCenter: parent.horizontalCenter;
-                    Image { source: "common/images/delete.png" }
-                    MouseArea {
-                        anchors.fill: parent; onClicked: { container.categoryDeleted(catid); }
-                    }
-                    visible: inEditMode
+            }
+            Component.onCompleted: {
+                if (categories.count == 1) {
+                    categoryClicked(catid)
                 }
             }
                 }
             }
-            MouseArea { enabled: !inEditMode; anchors.fill: wrapper; onClicked: { categoryClicked(catid); } }
         }
     }
 }
         }
     }
 }
index 32b5919..5131cbc 100644 (file)
@@ -56,21 +56,34 @@ Item {
 
             Item {
                 id: moveMe
 
             Item {
                 id: moveMe
-                Rectangle { color: "#dddddd"; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: wrapper.width; y: 1 }
+                Rectangle { color: settings.backColour; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: wrapper.width; y: 1 }
                 Rectangle {
                 Rectangle {
-                    x: 3; y: 4; width: 77; height: 77; color: "#000000"; smooth: true
-                    Image { width:32; height: 32; anchors.verticalCenter: parent.verticalCenter; anchors.horizontalCenter: parent.horizontalCenter;
-                        source: (updating=="True")? "common/images/loading.png" : (icon == "False") ? "common/images/feedingit.png" : icon;
-                        NumberAnimation on rotation {
-                            from: 0; to: 360; running: (updating=="True"); loops: Animation.Infinite; duration: 900
-                        }
+                    x: 3; y: 4; width: 77; height: 77;
+                    color: "#000000"; smooth: true
+                    Image { width:32; height: 32; anchors.verticalCenter: parent.verticalCenter;
+                        anchors.horizontalCenter: parent.horizontalCenter;
+                        source: (icon == "False") ? "common/images/feedingit.png" : icon
+                            // (updating=="True")? "common/images/loading.png" : (icon == "False") ? "common/images/feedingit.png" : icon;
+//                        NumberAnimation on rotation {
+//                            from: 0; to: 360; running: (updating=="True"); loops: Animation.Infinite; duration: 900
+//                        }
                     }
                 }
 
                 Column {
                     x: 92; width: wrapper.ListView.view.width - 95; y: 5; spacing: 2
                     }
                 }
 
                 Column {
                     x: 92; width: wrapper.ListView.view.width - 95; y: 5; spacing: 2
-                    Text { text: title; color: "white"; width: parent.width; font.bold: true; elide: Text.ElideRight; style: Text.Raised; styleColor: "black"; font.pointSize: 18 }
-                    Text { text: updatedDate + " / " + qsTr("%1 unread items").arg(unread); color: (unread=="0") ? "white" : "#7b97fd"; width: parent.width; font.bold: false; elide: Text.ElideRight; style: Text.Raised; styleColor: "black"; font.pointSize: 12 }
+                    Text { text: title; color: settings.mainTextColour;
+                        width: parent.width;
+                        font.bold: true; elide: Text.ElideRight; style: Text.Raised; styleColor: settings.mainShadowColour;
+                        font.pointSize: settings.mainTextSize
+                    }
+                    Text {
+                        text: updatedDate + " / " + qsTr("%1 unread items").arg(unread);
+                        color: (unread=="0") ? settings.mainTextColour : settings.secondaryTextColour;
+                        width: parent.width; font.bold: false; elide: Text.ElideRight;
+                        //style: Text.Raised; styleColor: settings.mainShadowColour;
+                        font.pointSize: settings.secondaryTextSize
+                    }
                     //Text { text: feedname; width: parent.width; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
                 }
 ////                Item {
                     //Text { text: feedname; width: parent.width; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
                 }
 ////                Item {
@@ -101,6 +114,9 @@ Item {
                     feedClicked(feedid)
                     
                 }
                     feedClicked(feedid)
                     
                 }
+                onPressAndHold: {
+                    window.longPressFeed(feedid)
+                }
             }
 
         }
             }
 
         }
index 79e05fc..e992e1e 100644 (file)
@@ -20,8 +20,9 @@ Rectangle {
 
         WebView {
             id: webView
 
         WebView {
             id: webView
-            url: "http://www.google.com";
-            //url: "/home/user/.feedingit/640fb167aca8bf5318ed721c5162f5eb.d/56a86b6b1675716ab54db83b1a78ab4c.html"
+            //url: "http://www.google.com";
+            //url: "http://www.viedemerde.fr/inclassable/5873986?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+viedemerde+%28Vie+de+merde%29"
+            url: "/home/ymarcoz/.feedingit/361f6abe590be9c681b5489e5d48331c.d/1b1033c75378fb19a8a70151d764cd33.html"
             preferredWidth: flickable.width
             preferredHeight: flickable.height
             settings.defaultFontSize: 32
             preferredWidth: flickable.width
             preferredHeight: flickable.height
             settings.defaultFontSize: 32
index e38c12a..2fda083 100644 (file)
@@ -6,12 +6,25 @@ PageStackWindow {
     id: window
     initialPage: categoryPage
 
     id: window
     initialPage: categoryPage
 
-    signal articleClosed()
+    signal longPressCategory(string catid)
+    signal longPressFeed(string key)
+    signal categoryReloadRequest()
+    signal feedReloadRequest()
     property string feedid
     property string catid
 
     Component.onCompleted: theme.inverted= true
 
     property string feedid
     property string catid
 
     Component.onCompleted: theme.inverted= true
 
+    onLongPressFeed: {
+        unsubscribeFeedMenu.key = key
+        unsubscribeFeedMenu.open()
+    }
+
+    onLongPressCategory: {
+        unsubscribeCategoryMenu.catid = catid
+        unsubscribeCategoryMenu.open()
+    }
+
     ToolBarLayout {
         id: commonTools
         visible: false
     ToolBarLayout {
         id: commonTools
         visible: false
@@ -29,6 +42,7 @@ PageStackWindow {
         visualParent: pageStack
         MenuLayout {
             MenuItem { text: qsTr("Settings"); onClicked: {}  }
         visualParent: pageStack
         MenuLayout {
             MenuItem { text: qsTr("Settings"); onClicked: {}  }
+            MenuItem { text: qsTr("Invert Theme"); onClicked: { theme.inverted = !theme.inverted }  }
             MenuItem { text: qsTr("Add Feeds"); onClicked: { pageStack.push(addFeedPage)  } }
             MenuItem { text: qsTr("Update All Categories"); onClicked: controller.updateAll(); }
             MenuItem { text: qsTr("About FeedingIt"); onClicked: query.open(); }
             MenuItem { text: qsTr("Add Feeds"); onClicked: { pageStack.push(addFeedPage)  } }
             MenuItem { text: qsTr("Update All Categories"); onClicked: controller.updateAll(); }
             MenuItem { text: qsTr("About FeedingIt"); onClicked: query.open(); }
@@ -39,8 +53,8 @@ PageStackWindow {
         id: myFeedsMenu
         visualParent: pageStack
         MenuLayout {
         id: myFeedsMenu
         visualParent: pageStack
         MenuLayout {
-            MenuItem { text: qsTr("Update All Feeds"); onClicked: controller.updateAll(); }
-            MenuItem { text: qsTr("About FeedingIt"); onClicked: query.open(); }
+            MenuItem { text: qsTr("Update All Feeds"); onClicked: controller.updateCategory(catid); }
+            //MenuItem { text: qsTr("About FeedingIt"); onClicked: query.open(); }
         }
     }
 
         }
     }
 
@@ -50,7 +64,61 @@ PageStackWindow {
         MenuLayout {
             MenuItem { text: qsTr("Mark All As Read"); onClicked: controller.markAllAsRead(feedid); }
             MenuItem { text: qsTr("Update Feed"); onClicked: controller.updateFeed(feedid); }
         MenuLayout {
             MenuItem { text: qsTr("Mark All As Read"); onClicked: controller.markAllAsRead(feedid); }
             MenuItem { text: qsTr("Update Feed"); onClicked: controller.updateFeed(feedid); }
-            MenuItem { text: qsTr("About FeedingIt"); onClicked: query.open(); }
+            //MenuItem { text: qsTr("About FeedingIt"); onClicked: query.open(); }
+        }
+    }
+
+    Menu {
+        id: unsubscribeFeedMenu
+        visualParent: pageStack
+        property string key
+        MenuLayout {
+            //MenuItem { text: qsTr("Update"); onClicked: controller.updateFeed(parent.feedid); }
+            MenuItem { text: qsTr("Delete");
+                onClicked: {
+                    feedConfirm.open()
+                    unsubscribeFeedMenu.close()
+                }
+            }
+        }
+        QueryDialog {
+            id: feedConfirm
+            //icon: "common/images/feedingit.png"
+            //titleText: "Delete Feed?"
+            message: "Delete this feed?"
+            acceptButtonText: "OK"
+            rejectButtonText: "Cancel"
+            onAccepted: {
+                controller.removeFeed(unsubscribeFeedMenu.key);
+                window.feedReloadRequest()
+            }
+        }
+    }
+
+    Menu {
+        id: unsubscribeCategoryMenu
+        visualParent: pageStack
+        property string catid
+        MenuLayout {
+            //MenuItem { text: qsTr("Update"); onClicked: controller.updateFeed(parent.feedid); }
+            MenuItem { text: qsTr("Delete");
+                onClicked: {
+                    categoryConfirm.open()
+                    unsubscribeFeedMenu.close()
+                }
+            }
+        }
+        QueryDialog {
+            id: categoryConfirm
+            //icon: "common/images/feedingit.png"
+            //titleText: "Delete Feed?"
+            message: "Delete this category?"
+            acceptButtonText: "OK"
+            rejectButtonText: "Cancel"
+            onAccepted: {
+                controller.removeCategory(unsubscribeCategoryMenu.catid);
+                window.categoryReloadRequest()
+            }
         }
     }
 
         }
     }
 
@@ -65,23 +133,24 @@ PageStackWindow {
         acceptButtonText: "OK"
     }
 
         acceptButtonText: "OK"
     }
 
-//    Page{
-//        id: mainPage
-//        Component.onCompleted: {
-//            var main = Qt.createComponent("FeedingIt.qml");
-//            main.createObject(mainPage);
-//        }
-//    }
-
     Component {
         id: categoryPage
         Page {
             tools: commonTools
             Categories {
     Component {
         id: categoryPage
         Page {
             tools: commonTools
             Categories {
+                id: categoriesItem
                 onCategoryClicked: {
                     window.catid = cat
                     pageStack.push(feedsPage)
                 }
                 onCategoryClicked: {
                     window.catid = cat
                     pageStack.push(feedsPage)
                 }
+
+            }
+            Connections {
+                target: window
+                onCategoryReloadRequest: {
+                    console.log("category reloaded")
+                    categoriesItem.reload()
+                }
             }
         }
     }
             }
         }
     }
@@ -99,6 +168,7 @@ PageStackWindow {
                     window.feedid = feedid
                     pageStack.push(articlesPage)
                 }
                     window.feedid = feedid
                     pageStack.push(articlesPage)
                 }
+
             }
             ToolBarLayout {
                 id: feedsTools
             }
             ToolBarLayout {
                 id: feedsTools
@@ -117,7 +187,7 @@ PageStackWindow {
             }
             Connections {
                  target: window
             }
             Connections {
                  target: window
-                 onArticleClosed: feedsItem.reload()
+                 onFeedReloadRequest: feedsItem.reload()
              }
         }
     }
              }
         }
     }
@@ -141,7 +211,7 @@ PageStackWindow {
                             flipper.articleShown = false;
                             flipper.reload()
                         } else {
                             flipper.articleShown = false;
                             flipper.reload()
                         } else {
-                            window.articleClosed();
+                            window.feedReloadRequest();
                             pageStack.pop();
                         }
                     }
                             pageStack.pop();
                         }
                     }
@@ -174,4 +244,8 @@ PageStackWindow {
         id: addFeedPage
         AddFeed {}
     }
         id: addFeedPage
         AddFeed {}
     }
+
+    Settings {
+        id: settings
+    }
 }
 }
index 4b4d276..68797cd 100644 (file)
@@ -1211,6 +1211,15 @@ class Listing(BaseObject):
     
     def getCategoryTitle(self, id):
         return self.lookup('categories', 'title', id)
     
     def getCategoryTitle(self, id):
         return self.lookup('categories', 'title', id)
+
+    def getCategoryUnread(self, id):
+        count = 0
+        for key in self.getListOfFeeds(category=id):
+            try: 
+                count = count + self.getFeedNumberOfUnreadItems(key)
+            except:
+                pass
+        return count
     
     def getSortedListOfKeys(self, order, onlyUnread=False, category=1):
         if   order == "Most unread":
     
     def getSortedListOfKeys(self, order, onlyUnread=False, category=1):
         if   order == "Most unread":
@@ -1286,6 +1295,7 @@ class Listing(BaseObject):
             id=1
         self.db.execute("INSERT INTO categories (id, title, unread, rank) VALUES (?, ?, 0, ?)", (id, title, rank))
         self.db.commit()
             id=1
         self.db.execute("INSERT INTO categories (id, title, unread, rank) VALUES (?, ?, 0, ?)", (id, title, rank))
         self.db.commit()
+        self.cache_invalidate('categories')
     
     def removeFeed(self, key):
         if wc().available ():
     
     def removeFeed(self, key):
         if wc().available ():
@@ -1301,6 +1311,7 @@ class Listing(BaseObject):
 
         if isdir(self.configdir+key+".d/"):
            rmtree(self.configdir+key+".d/")
 
         if isdir(self.configdir+key+".d/"):
            rmtree(self.configdir+key+".d/")
+        self.cache_invalidate('feeds')
            
     def removeCategory(self, key):
         if self.db.execute("SELECT count(*) FROM categories;").fetchone()[0] > 1:
            
     def removeCategory(self, key):
         if self.db.execute("SELECT count(*) FROM categories;").fetchone()[0] > 1:
@@ -1309,6 +1320,7 @@ class Listing(BaseObject):
             self.db.execute("UPDATE categories SET rank=rank-1 WHERE rank>?;", (rank,) )
             self.db.execute("UPDATE feeds SET category=1 WHERE category=?;", (key,) )
             self.db.commit()
             self.db.execute("UPDATE categories SET rank=rank-1 WHERE rank>?;", (rank,) )
             self.db.execute("UPDATE feeds SET category=1 WHERE category=?;", (key,) )
             self.db.commit()
+            self.cache_invalidate('categories')
         
     #def saveConfig(self):
     #    self.listOfFeeds["feedingit-order"] = self.sortedKeys
         
     #def saveConfig(self):
     #    self.listOfFeeds["feedingit-order"] = self.sortedKeys
index 9b6014d..5d71c02 100644 (file)
@@ -6,9 +6,10 @@ Home-page: UNKNOWN
 Author: Yves
 Author-email: yves@marcoz.org
 License: UNKNOWN
 Author: Yves
 Author-email: yves@marcoz.org
 License: UNKNOWN
-Description: This file should contain a writeup describing what your application does,
-        and how to use it. The content of this file goes into the long_description
-        field of setup.py, which in turn becomes the long version of the Description
-        field in the debian/control file of the project.
+Description: FeedingIt is an easy to use RSS feed reader with portrait mode support and 
+        automatic feed updates. You can swipe left and right to move between articles.
+        Import and export of subscription lists is supported for OPML files.
+        Images can be cached during the feed update, so you can view images in the
+        downloaded articles while offline.
         
 Platform: UNKNOWN
         
 Platform: UNKNOWN
index 2b2c6df..5d5a425 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/make -f
 
 # This file was automatically generated by stdeb 0.6.0+git at
 #!/usr/bin/make -f
 
 # This file was automatically generated by stdeb 0.6.0+git at
-# Sun, 06 Nov 2011 21:13:19 -0800
+# Mon, 07 Nov 2011 21:25:40 -0800
 
 %:
        dh $@ --with python2 --buildsystem=python_distutils
 
 %:
        dh $@ --with python2 --buildsystem=python_distutils
index 47e9f38..a606943 100644 (file)
@@ -1,4 +1,5 @@
-This file should contain a writeup describing what your application does,
-and how to use it. The content of this file goes into the long_description
-field of setup.py, which in turn becomes the long version of the Description
-field in the debian/control file of the project.
+FeedingIt is an easy to use RSS feed reader with portrait mode support and 
+automatic feed updates. You can swipe left and right to move between articles.
+Import and export of subscription lists is supported for OPML files.
+Images can be cached during the feed update, so you can view images in the
+downloaded articles while offline.
index 8acdb75..41167cb 100644 (file)
@@ -49,9 +49,11 @@ class XmlHandler():
     def generateCategoryXml(self):
         xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><xml>"
         for cat in self.listing.getListOfCategories():
     def generateCategoryXml(self):
         xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><xml>"
         for cat in self.listing.getListOfCategories():
+            print cat
             xml += "<category>"
             xml += "<catname>%s</catname>" %sanitize(self.listing.getCategoryTitle(cat))
             xml += "<catid>%s</catid>" % cat
             xml += "<category>"
             xml += "<catname>%s</catname>" %sanitize(self.listing.getCategoryTitle(cat))
             xml += "<catid>%s</catid>" % cat
+            xml += "<unread>%s</unread>" % self.listing.getCategoryUnread(cat)
             xml += "</category>"
         xml += "</xml>"
         return xml
             xml += "</category>"
         xml += "</xml>"
         return xml
index 91be2b4..7330871 100644 (file)
@@ -35,7 +35,6 @@ def my_excepthook(exctype, value, tb):
     original_excepthook(exctype, value, tb)
 
 def init(dot_directory, debug=False, max_logfiles=1, program_name=None):
     original_excepthook(exctype, value, tb)
 
 def init(dot_directory, debug=False, max_logfiles=1, program_name=None):
-    debug = True
     if not os.path.isabs(dot_directory):
         dot_directory = os.path.join(os.path.expanduser("~"), dot_directory)
 
     if not os.path.isabs(dot_directory):
         dot_directory = os.path.join(os.path.expanduser("~"), dot_directory)
 
index 209c021..10d08b9 100644 (file)
@@ -7,6 +7,7 @@ from PySide import QtDeclarative
 import os
 from os import mkdir, remove, stat, environ
 from os.path import isfile, isdir, exists
 import os
 from os import mkdir, remove, stat, environ
 from os.path import isfile, isdir, exists
+import codecs
 
 # Comment the line below if you don't want to use OpenGL for QML rendering or if it is not supported
 from PySide import QtOpenGL,  QtCore
 
 # Comment the line below if you don't want to use OpenGL for QML rendering or if it is not supported
 from PySide import QtOpenGL,  QtCore
@@ -35,11 +36,11 @@ class Controller(QtCore.QObject):
     def getArticle(self, key, article):
        feed = listing.getFeed(key)
        try:
     def getArticle(self, key, article):
        feed = listing.getFeed(key)
        try:
-          file = open(feed.getContentLink(article))
+          file = codecs.open(feed.getContentLink(article), "r", "utf-8")
           html = file.read().replace("body", "body bgcolor='#ffffff'", 1)
           file.close()
        except:
           html = file.read().replace("body", "body bgcolor='#ffffff'", 1)
           file.close()
        except:
-          html = "<html><body>Error retrieving article</body></html>"
+          html = u"<html><body>Error retrieving article</body></html>"
        return html
     
     @QtCore.Slot(str, result=str)
        return html
     
     @QtCore.Slot(str, result=str)
@@ -67,9 +68,15 @@ class Controller(QtCore.QObject):
         
     @QtCore.Slot()
     def updateAll(self):
         
     @QtCore.Slot()
     def updateAll(self):
-        for feed in listing.getSortedListOfKeys("Manual"):
-            listing.updateFeed(feed)
-            
+        for catid in listing.getListOfCategories():
+            for feed in listing.getSortedListOfKeys("Manual", category=catid):
+                listing.updateFeed(feed)
+
+    @QtCore.Slot(str)
+    def updateCategory(self, catid):
+        for feed in listing.getSortedListOfKeys("Manual", category=catid):
+            listing.updateFeed(feed)           
+
     @QtCore.Slot(str,str,str)
     def addFeed(self, title, url, catid):
         listing.addFeed(title,url, category=catid)
     @QtCore.Slot(str,str,str)
     def addFeed(self, title, url, catid):
         listing.addFeed(title,url, category=catid)
@@ -79,6 +86,14 @@ class Controller(QtCore.QObject):
         listing.addCategory(name)
 
     @QtCore.Slot(str)
         listing.addCategory(name)
 
     @QtCore.Slot(str)
+    def removeFeed(self, key):
+        listing.removeFeed(key)
+
+    @QtCore.Slot(str)
+    def removeCategory(self, catid):
+        listing.removeCategory(catid)
+
+    @QtCore.Slot(str)
     def markAllAsRead(self, key):
         feed = listing.getFeed(key)
         feed.markAllAsRead()
     def markAllAsRead(self, key):
         feed = listing.getFeed(key)
         feed.markAllAsRead()
index 4b4d276..68797cd 100644 (file)
@@ -1211,6 +1211,15 @@ class Listing(BaseObject):
     
     def getCategoryTitle(self, id):
         return self.lookup('categories', 'title', id)
     
     def getCategoryTitle(self, id):
         return self.lookup('categories', 'title', id)
+
+    def getCategoryUnread(self, id):
+        count = 0
+        for key in self.getListOfFeeds(category=id):
+            try: 
+                count = count + self.getFeedNumberOfUnreadItems(key)
+            except:
+                pass
+        return count
     
     def getSortedListOfKeys(self, order, onlyUnread=False, category=1):
         if   order == "Most unread":
     
     def getSortedListOfKeys(self, order, onlyUnread=False, category=1):
         if   order == "Most unread":
@@ -1286,6 +1295,7 @@ class Listing(BaseObject):
             id=1
         self.db.execute("INSERT INTO categories (id, title, unread, rank) VALUES (?, ?, 0, ?)", (id, title, rank))
         self.db.commit()
             id=1
         self.db.execute("INSERT INTO categories (id, title, unread, rank) VALUES (?, ?, 0, ?)", (id, title, rank))
         self.db.commit()
+        self.cache_invalidate('categories')
     
     def removeFeed(self, key):
         if wc().available ():
     
     def removeFeed(self, key):
         if wc().available ():
@@ -1301,6 +1311,7 @@ class Listing(BaseObject):
 
         if isdir(self.configdir+key+".d/"):
            rmtree(self.configdir+key+".d/")
 
         if isdir(self.configdir+key+".d/"):
            rmtree(self.configdir+key+".d/")
+        self.cache_invalidate('feeds')
            
     def removeCategory(self, key):
         if self.db.execute("SELECT count(*) FROM categories;").fetchone()[0] > 1:
            
     def removeCategory(self, key):
         if self.db.execute("SELECT count(*) FROM categories;").fetchone()[0] > 1:
@@ -1309,6 +1320,7 @@ class Listing(BaseObject):
             self.db.execute("UPDATE categories SET rank=rank-1 WHERE rank>?;", (rank,) )
             self.db.execute("UPDATE feeds SET category=1 WHERE category=?;", (key,) )
             self.db.commit()
             self.db.execute("UPDATE categories SET rank=rank-1 WHERE rank>?;", (rank,) )
             self.db.execute("UPDATE feeds SET category=1 WHERE category=?;", (key,) )
             self.db.commit()
+            self.cache_invalidate('categories')
         
     #def saveConfig(self):
     #    self.listOfFeeds["feedingit-order"] = self.sortedKeys
         
     #def saveConfig(self):
     #    self.listOfFeeds["feedingit-order"] = self.sortedKeys
index 83898b4..ac31e0b 100644 (file)
@@ -108,16 +108,24 @@ Item {
             id: listing;
 
             Item {
             id: listing;
 
             Item {
-                width: articleViewer.width; height: 86
+                width: articleViewer.width; height: backRect.height + 3
                 id: listItem
                 id: listItem
-                Rectangle { id: backRect; color: "#dddddd"; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: listItem.width; y: 1 }
+                Rectangle {
+                    id: backRect; color: settings.backColour; opacity: index % 2 ? 0.2 : 0.4;
+                    height: articleText.height + 22; width: listItem.width;
+                    y: 1
+                }
                 Text {
                 Text {
-                    anchors.fill: backRect
+                    id: articleText
+                    anchors.verticalCenter: backRect.verticalCenter
+                    x: 3
+                    width: listItem.width - 6;
+
                     anchors.margins: 5
                     verticalAlignment: Text.AlignVCenter; text: title;
                     anchors.margins: 5
                     verticalAlignment: Text.AlignVCenter; text: title;
-                    color: (unread=="True") ? "white" : "#7b97fd";
+                    color: (unread=="True") ? settings.mainTextColour : settings.secondaryTextColour;
 
 
-                    width: listItem.width; wrapMode: Text.WordWrap; font.bold: false;
+                     wrapMode: Text.WordWrap; font.bold: false;
                     font.pointSize: 18
                 }
                 MouseArea { anchors.fill: listItem;
                     font.pointSize: 18
                 }
                 MouseArea { anchors.fill: listItem;
index 5a97370..4469ba1 100644 (file)
@@ -8,7 +8,9 @@ Item {
     signal categoryClicked(string cat)
 
     function reload() {
     signal categoryClicked(string cat)
 
     function reload() {
-        categories.reload();
+        //categories.reload();
+        categories.xml = controller.getCategoryXml()
+        //console.log(controller.getCategoryXml())
     }
 
     ListView {
     }
 
     ListView {
@@ -25,6 +27,7 @@ Item {
 
         XmlRole { name: "title"; query: "catname/string()" }
         XmlRole { name: "catid"; query: "catid/string()"; isKey: true }
 
         XmlRole { name: "title"; query: "catname/string()" }
         XmlRole { name: "catid"; query: "catid/string()"; isKey: true }
+        XmlRole { name: "unread"; query: "unread/string()" }
     }
 
     Component {
     }
 
     Component {
@@ -36,46 +39,68 @@ Item {
             Item {
                 id: moveMe
                 height: parent.height
             Item {
                 id: moveMe
                 height: parent.height
-                Rectangle { color: "#eeeeee"; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: wrapper.width; y: 1 }
+                Rectangle { color: settings.backColour; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: wrapper.width; y: 1 }
 //                Rectangle {
 //                    x: 6; y: 4; width: 77; height: parent.height - 9; color: "white"; smooth: true
 
 //                }
                 Column {
                     x: 15;
 //                Rectangle {
 //                    x: 6; y: 4; width: 77; height: parent.height - 9; color: "white"; smooth: true
 
 //                }
                 Column {
                     x: 15;
-                    width: wrapper.ListView.view.width /*- 95; y: 15*/; spacing: 2
+                    width: wrapper.ListView.view.width /*- 95;*/
+                    y: 15; spacing: 2
                     anchors.margins: 5
                     height: parent.height
 
                     anchors.margins: 5
                     height: parent.height
 
-                    Text { text: title; color: "white"; width: parent.width; font.bold: true;
-                        height: parent.height
-                        elide: Text.ElideRight; style: Text.Raised; styleColor: "black"; font.pointSize: 20
+                    Text { text: title; color: settings.mainTextColour; width: parent.width; font.bold: true;
+                        //height: parent.height
+                        elide: Text.ElideRight; style: Text.Raised;
+                        styleColor: settings.mainShadowColour;
+                        font.pointSize: settings.mainTextSize
                         verticalAlignment: Text.AlignVCenter;
                     }
                         verticalAlignment: Text.AlignVCenter;
                     }
+                    Text {
+                        text: qsTr("%1 unread items").arg(unread);
+                        color: (unread=="0") ? settings.mainTextColour : settings.secondaryTextColour;
+                        width: parent.width; font.bold: false;
+                        elide: Text.ElideRight;
+                        //style: Text.Raised; styleColor: settings.mainShadowColour;
+                        font.pointSize: settings.secondaryTextSize
+                    }
                     //Text { text: feedname; width: parent.width; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
                 }
                     //Text { text: feedname; width: parent.width; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
                 }
-                Item {
-                    x: wrapper.ListView.view.width - 128; y: 12
-                    height: 58; width: 58;
-                    //anchors.horizontalCenter: parent.horizontalCenter;
-                    Image { source: "common/images/wmEditIcon.png" }
-                    MouseArea {
-                        anchors.fill: parent; onClicked: { container.categoryEdit(catname, catid); }
-                    }
-                    visible: inEditMode
+//                Item {
+//                    x: wrapper.ListView.view.width - 128; y: 12
+//                    height: 58; width: 58;
+//                    //anchors.horizontalCenter: parent.horizontalCenter;
+//                    Image { source: "common/images/wmEditIcon.png" }
+//                    MouseArea {
+//                        anchors.fill: parent; onClicked: { container.categoryEdit(catname, catid); }
+//                    }
+//                    visible: inEditMode
+//                }
+//                Item {
+//                    x: wrapper.ListView.view.width - 64; y: 12
+//                    height: 58; width: 58;
+//                    //anchors.horizontalCenter: parent.horizontalCenter;
+//                    Image { source: "common/images/delete.png" }
+//                    MouseArea {
+//                        anchors.fill: parent; onClicked: { container.categoryDeleted(catid); }
+//                    }
+//                    visible: inEditMode
+//                }
+            }
+            MouseArea {
+                enabled: !inEditMode; anchors.fill: wrapper;
+                onClicked: { categoryClicked(catid); }
+                onPressAndHold: {
+                    window.longPressCategory(catid)
                 }
                 }
-                Item {
-                    x: wrapper.ListView.view.width - 64; y: 12
-                    height: 58; width: 58;
-                    //anchors.horizontalCenter: parent.horizontalCenter;
-                    Image { source: "common/images/delete.png" }
-                    MouseArea {
-                        anchors.fill: parent; onClicked: { container.categoryDeleted(catid); }
-                    }
-                    visible: inEditMode
+            }
+            Component.onCompleted: {
+                if (categories.count == 1) {
+                    categoryClicked(catid)
                 }
             }
                 }
             }
-            MouseArea { enabled: !inEditMode; anchors.fill: wrapper; onClicked: { categoryClicked(catid); } }
         }
     }
 }
         }
     }
 }
index 32b5919..5131cbc 100644 (file)
@@ -56,21 +56,34 @@ Item {
 
             Item {
                 id: moveMe
 
             Item {
                 id: moveMe
-                Rectangle { color: "#dddddd"; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: wrapper.width; y: 1 }
+                Rectangle { color: settings.backColour; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: wrapper.width; y: 1 }
                 Rectangle {
                 Rectangle {
-                    x: 3; y: 4; width: 77; height: 77; color: "#000000"; smooth: true
-                    Image { width:32; height: 32; anchors.verticalCenter: parent.verticalCenter; anchors.horizontalCenter: parent.horizontalCenter;
-                        source: (updating=="True")? "common/images/loading.png" : (icon == "False") ? "common/images/feedingit.png" : icon;
-                        NumberAnimation on rotation {
-                            from: 0; to: 360; running: (updating=="True"); loops: Animation.Infinite; duration: 900
-                        }
+                    x: 3; y: 4; width: 77; height: 77;
+                    color: "#000000"; smooth: true
+                    Image { width:32; height: 32; anchors.verticalCenter: parent.verticalCenter;
+                        anchors.horizontalCenter: parent.horizontalCenter;
+                        source: (icon == "False") ? "common/images/feedingit.png" : icon
+                            // (updating=="True")? "common/images/loading.png" : (icon == "False") ? "common/images/feedingit.png" : icon;
+//                        NumberAnimation on rotation {
+//                            from: 0; to: 360; running: (updating=="True"); loops: Animation.Infinite; duration: 900
+//                        }
                     }
                 }
 
                 Column {
                     x: 92; width: wrapper.ListView.view.width - 95; y: 5; spacing: 2
                     }
                 }
 
                 Column {
                     x: 92; width: wrapper.ListView.view.width - 95; y: 5; spacing: 2
-                    Text { text: title; color: "white"; width: parent.width; font.bold: true; elide: Text.ElideRight; style: Text.Raised; styleColor: "black"; font.pointSize: 18 }
-                    Text { text: updatedDate + " / " + qsTr("%1 unread items").arg(unread); color: (unread=="0") ? "white" : "#7b97fd"; width: parent.width; font.bold: false; elide: Text.ElideRight; style: Text.Raised; styleColor: "black"; font.pointSize: 12 }
+                    Text { text: title; color: settings.mainTextColour;
+                        width: parent.width;
+                        font.bold: true; elide: Text.ElideRight; style: Text.Raised; styleColor: settings.mainShadowColour;
+                        font.pointSize: settings.mainTextSize
+                    }
+                    Text {
+                        text: updatedDate + " / " + qsTr("%1 unread items").arg(unread);
+                        color: (unread=="0") ? settings.mainTextColour : settings.secondaryTextColour;
+                        width: parent.width; font.bold: false; elide: Text.ElideRight;
+                        //style: Text.Raised; styleColor: settings.mainShadowColour;
+                        font.pointSize: settings.secondaryTextSize
+                    }
                     //Text { text: feedname; width: parent.width; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
                 }
 ////                Item {
                     //Text { text: feedname; width: parent.width; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
                 }
 ////                Item {
@@ -101,6 +114,9 @@ Item {
                     feedClicked(feedid)
                     
                 }
                     feedClicked(feedid)
                     
                 }
+                onPressAndHold: {
+                    window.longPressFeed(feedid)
+                }
             }
 
         }
             }
 
         }
index 79e05fc..e992e1e 100644 (file)
@@ -20,8 +20,9 @@ Rectangle {
 
         WebView {
             id: webView
 
         WebView {
             id: webView
-            url: "http://www.google.com";
-            //url: "/home/user/.feedingit/640fb167aca8bf5318ed721c5162f5eb.d/56a86b6b1675716ab54db83b1a78ab4c.html"
+            //url: "http://www.google.com";
+            //url: "http://www.viedemerde.fr/inclassable/5873986?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+viedemerde+%28Vie+de+merde%29"
+            url: "/home/ymarcoz/.feedingit/361f6abe590be9c681b5489e5d48331c.d/1b1033c75378fb19a8a70151d764cd33.html"
             preferredWidth: flickable.width
             preferredHeight: flickable.height
             settings.defaultFontSize: 32
             preferredWidth: flickable.width
             preferredHeight: flickable.height
             settings.defaultFontSize: 32
index e38c12a..2fda083 100644 (file)
@@ -6,12 +6,25 @@ PageStackWindow {
     id: window
     initialPage: categoryPage
 
     id: window
     initialPage: categoryPage
 
-    signal articleClosed()
+    signal longPressCategory(string catid)
+    signal longPressFeed(string key)
+    signal categoryReloadRequest()
+    signal feedReloadRequest()
     property string feedid
     property string catid
 
     Component.onCompleted: theme.inverted= true
 
     property string feedid
     property string catid
 
     Component.onCompleted: theme.inverted= true
 
+    onLongPressFeed: {
+        unsubscribeFeedMenu.key = key
+        unsubscribeFeedMenu.open()
+    }
+
+    onLongPressCategory: {
+        unsubscribeCategoryMenu.catid = catid
+        unsubscribeCategoryMenu.open()
+    }
+
     ToolBarLayout {
         id: commonTools
         visible: false
     ToolBarLayout {
         id: commonTools
         visible: false
@@ -29,6 +42,7 @@ PageStackWindow {
         visualParent: pageStack
         MenuLayout {
             MenuItem { text: qsTr("Settings"); onClicked: {}  }
         visualParent: pageStack
         MenuLayout {
             MenuItem { text: qsTr("Settings"); onClicked: {}  }
+            MenuItem { text: qsTr("Invert Theme"); onClicked: { theme.inverted = !theme.inverted }  }
             MenuItem { text: qsTr("Add Feeds"); onClicked: { pageStack.push(addFeedPage)  } }
             MenuItem { text: qsTr("Update All Categories"); onClicked: controller.updateAll(); }
             MenuItem { text: qsTr("About FeedingIt"); onClicked: query.open(); }
             MenuItem { text: qsTr("Add Feeds"); onClicked: { pageStack.push(addFeedPage)  } }
             MenuItem { text: qsTr("Update All Categories"); onClicked: controller.updateAll(); }
             MenuItem { text: qsTr("About FeedingIt"); onClicked: query.open(); }
@@ -39,8 +53,8 @@ PageStackWindow {
         id: myFeedsMenu
         visualParent: pageStack
         MenuLayout {
         id: myFeedsMenu
         visualParent: pageStack
         MenuLayout {
-            MenuItem { text: qsTr("Update All Feeds"); onClicked: controller.updateAll(); }
-            MenuItem { text: qsTr("About FeedingIt"); onClicked: query.open(); }
+            MenuItem { text: qsTr("Update All Feeds"); onClicked: controller.updateCategory(catid); }
+            //MenuItem { text: qsTr("About FeedingIt"); onClicked: query.open(); }
         }
     }
 
         }
     }
 
@@ -50,7 +64,61 @@ PageStackWindow {
         MenuLayout {
             MenuItem { text: qsTr("Mark All As Read"); onClicked: controller.markAllAsRead(feedid); }
             MenuItem { text: qsTr("Update Feed"); onClicked: controller.updateFeed(feedid); }
         MenuLayout {
             MenuItem { text: qsTr("Mark All As Read"); onClicked: controller.markAllAsRead(feedid); }
             MenuItem { text: qsTr("Update Feed"); onClicked: controller.updateFeed(feedid); }
-            MenuItem { text: qsTr("About FeedingIt"); onClicked: query.open(); }
+            //MenuItem { text: qsTr("About FeedingIt"); onClicked: query.open(); }
+        }
+    }
+
+    Menu {
+        id: unsubscribeFeedMenu
+        visualParent: pageStack
+        property string key
+        MenuLayout {
+            //MenuItem { text: qsTr("Update"); onClicked: controller.updateFeed(parent.feedid); }
+            MenuItem { text: qsTr("Delete");
+                onClicked: {
+                    feedConfirm.open()
+                    unsubscribeFeedMenu.close()
+                }
+            }
+        }
+        QueryDialog {
+            id: feedConfirm
+            //icon: "common/images/feedingit.png"
+            //titleText: "Delete Feed?"
+            message: "Delete this feed?"
+            acceptButtonText: "OK"
+            rejectButtonText: "Cancel"
+            onAccepted: {
+                controller.removeFeed(unsubscribeFeedMenu.key);
+                window.feedReloadRequest()
+            }
+        }
+    }
+
+    Menu {
+        id: unsubscribeCategoryMenu
+        visualParent: pageStack
+        property string catid
+        MenuLayout {
+            //MenuItem { text: qsTr("Update"); onClicked: controller.updateFeed(parent.feedid); }
+            MenuItem { text: qsTr("Delete");
+                onClicked: {
+                    categoryConfirm.open()
+                    unsubscribeFeedMenu.close()
+                }
+            }
+        }
+        QueryDialog {
+            id: categoryConfirm
+            //icon: "common/images/feedingit.png"
+            //titleText: "Delete Feed?"
+            message: "Delete this category?"
+            acceptButtonText: "OK"
+            rejectButtonText: "Cancel"
+            onAccepted: {
+                controller.removeCategory(unsubscribeCategoryMenu.catid);
+                window.categoryReloadRequest()
+            }
         }
     }
 
         }
     }
 
@@ -65,23 +133,24 @@ PageStackWindow {
         acceptButtonText: "OK"
     }
 
         acceptButtonText: "OK"
     }
 
-//    Page{
-//        id: mainPage
-//        Component.onCompleted: {
-//            var main = Qt.createComponent("FeedingIt.qml");
-//            main.createObject(mainPage);
-//        }
-//    }
-
     Component {
         id: categoryPage
         Page {
             tools: commonTools
             Categories {
     Component {
         id: categoryPage
         Page {
             tools: commonTools
             Categories {
+                id: categoriesItem
                 onCategoryClicked: {
                     window.catid = cat
                     pageStack.push(feedsPage)
                 }
                 onCategoryClicked: {
                     window.catid = cat
                     pageStack.push(feedsPage)
                 }
+
+            }
+            Connections {
+                target: window
+                onCategoryReloadRequest: {
+                    console.log("category reloaded")
+                    categoriesItem.reload()
+                }
             }
         }
     }
             }
         }
     }
@@ -99,6 +168,7 @@ PageStackWindow {
                     window.feedid = feedid
                     pageStack.push(articlesPage)
                 }
                     window.feedid = feedid
                     pageStack.push(articlesPage)
                 }
+
             }
             ToolBarLayout {
                 id: feedsTools
             }
             ToolBarLayout {
                 id: feedsTools
@@ -117,7 +187,7 @@ PageStackWindow {
             }
             Connections {
                  target: window
             }
             Connections {
                  target: window
-                 onArticleClosed: feedsItem.reload()
+                 onFeedReloadRequest: feedsItem.reload()
              }
         }
     }
              }
         }
     }
@@ -141,7 +211,7 @@ PageStackWindow {
                             flipper.articleShown = false;
                             flipper.reload()
                         } else {
                             flipper.articleShown = false;
                             flipper.reload()
                         } else {
-                            window.articleClosed();
+                            window.feedReloadRequest();
                             pageStack.pop();
                         }
                     }
                             pageStack.pop();
                         }
                     }
@@ -174,4 +244,8 @@ PageStackWindow {
         id: addFeedPage
         AddFeed {}
     }
         id: addFeedPage
         AddFeed {}
     }
+
+    Settings {
+        id: settings
+    }
 }
 }
index 9b03374..39df53e 100644 (file)
Binary files a/psa_harmattan/feedingit/deb_dist/feedingit_0.1.0-1.debian.tar.gz and b/psa_harmattan/feedingit/deb_dist/feedingit_0.1.0-1.debian.tar.gz differ
index 91c1808..ca9964d 100644 (file)
@@ -7,11 +7,11 @@ Maintainer: Yves <yves@marcoz.org>
 Standards-Version: 3.9.1
 Build-Depends: python-all (>= 2.6.6-3), debhelper (>= 7.4.3)
 Checksums-Sha1: 
 Standards-Version: 3.9.1
 Build-Depends: python-all (>= 2.6.6-3), debhelper (>= 7.4.3)
 Checksums-Sha1: 
- 12a7cdb7b5cdb98d79bda6e6a4dc2562685423c3 176240 feedingit_0.1.0.orig.tar.gz
- 954096a5d2fa51bb359517d7578c684e4625f237 859 feedingit_0.1.0-1.debian.tar.gz
+ 0f46819e2084145776f49c7f7f2ee922a980687c 177736 feedingit_0.1.0.orig.tar.gz
+ bc99501e4cf014353f2f9d8807498a9d311337c7 931 feedingit_0.1.0-1.debian.tar.gz
 Checksums-Sha256: 
 Checksums-Sha256: 
- 8421abef41b572247ce1292445c075eec032136b121e9d3bc550897881ea975a 176240 feedingit_0.1.0.orig.tar.gz
- 229779d81f6541d46086a972ee2d93db66abd4a7adc8be746f5c97d585aa4044 859 feedingit_0.1.0-1.debian.tar.gz
+ 223c41eba6bad5241f54e54e776a6e3bb272d07d91b1fa380848b7d8ce0128f4 177736 feedingit_0.1.0.orig.tar.gz
+ 58f20d85f1cae2b33fb346fc6bee304cd304b6674026540aee31b73748d49a7c 931 feedingit_0.1.0-1.debian.tar.gz
 Files: 
 Files: 
- c58fcc9048d74f69926cb53696c75c5e 176240 feedingit_0.1.0.orig.tar.gz
- e143c5daf921dac855fb227f77646a0e 859 feedingit_0.1.0-1.debian.tar.gz
+ 1b7ddb59ac327613cb42c0bbd7ffa06b 177736 feedingit_0.1.0.orig.tar.gz
+ 9c4aba31f4ca66c7cb5fe5dbcd83d100 931 feedingit_0.1.0-1.debian.tar.gz
index e0cb412..70ebaee 100644 (file)
Binary files a/psa_harmattan/feedingit/deb_dist/feedingit_0.1.0-1_all.deb and b/psa_harmattan/feedingit/deb_dist/feedingit_0.1.0-1_all.deb differ
index bfead88..edd979d 100644 (file)
@@ -1,5 +1,5 @@
 Format: 1.8
 Format: 1.8
-Date: Sun, 06 Nov 2011 21:13:19 -0800
+Date: Mon, 07 Nov 2011 21:25:40 -0800
 Source: feedingit
 Binary: feedingit
 Architecture: source all
 Source: feedingit
 Binary: feedingit
 Architecture: source all
@@ -15,17 +15,17 @@ Changes:
  .
    * source package automatically created by stdeb 0.6.0+git
 Checksums-Sha1: 
  .
    * source package automatically created by stdeb 0.6.0+git
 Checksums-Sha1: 
- ec3bc8cdf6562addb5a09da997d8ebdcd8f94b51 753 feedingit_0.1.0-1.dsc
- 12a7cdb7b5cdb98d79bda6e6a4dc2562685423c3 176240 feedingit_0.1.0.orig.tar.gz
- 954096a5d2fa51bb359517d7578c684e4625f237 859 feedingit_0.1.0-1.debian.tar.gz
- 6edf2daadc2cc46ce0a0733ac666207db8ca12b7 165780 feedingit_0.1.0-1_all.deb
+ 4872f7d851392a4c31cf7c4e6fba426ef7bfecf9 753 feedingit_0.1.0-1.dsc
+ 0f46819e2084145776f49c7f7f2ee922a980687c 177736 feedingit_0.1.0.orig.tar.gz
+ bc99501e4cf014353f2f9d8807498a9d311337c7 931 feedingit_0.1.0-1.debian.tar.gz
+ d5f6a17d75b19f6ae48a94c3fc685eb55d2cedab 167012 feedingit_0.1.0-1_all.deb
 Checksums-Sha256: 
 Checksums-Sha256: 
- 5b4b10db2bd978e8b26dbda2533912d30a484ce10427ead1667517896f0f4c6c 753 feedingit_0.1.0-1.dsc
- 8421abef41b572247ce1292445c075eec032136b121e9d3bc550897881ea975a 176240 feedingit_0.1.0.orig.tar.gz
- 229779d81f6541d46086a972ee2d93db66abd4a7adc8be746f5c97d585aa4044 859 feedingit_0.1.0-1.debian.tar.gz
- 9e5238dfd7dded6daa107482e4a205442c57042a39e273c740ae8328e65a08b7 165780 feedingit_0.1.0-1_all.deb
+ a39151af4220e3ee0b11e210f1d41b78968f4dfc874b949dd914688e99e97d7f 753 feedingit_0.1.0-1.dsc
+ 223c41eba6bad5241f54e54e776a6e3bb272d07d91b1fa380848b7d8ce0128f4 177736 feedingit_0.1.0.orig.tar.gz
+ 58f20d85f1cae2b33fb346fc6bee304cd304b6674026540aee31b73748d49a7c 931 feedingit_0.1.0-1.debian.tar.gz
+ ef85ba37ee11a4bcdae73fc629c3a0acfa2e023cc0502409f0c37b9045a10eb8 167012 feedingit_0.1.0-1_all.deb
 Files: 
 Files: 
- 87eb4279d8f3744a01cf5de3ee7f87fe 753 user/development optional feedingit_0.1.0-1.dsc
- c58fcc9048d74f69926cb53696c75c5e 176240 user/development optional feedingit_0.1.0.orig.tar.gz
- e143c5daf921dac855fb227f77646a0e 859 user/development optional feedingit_0.1.0-1.debian.tar.gz
- 308928231246478c11cd5078aba9b193 165780 user/development optional feedingit_0.1.0-1_all.deb
+ b885f4386ce99ea355ff17988744f887 753 user/development optional feedingit_0.1.0-1.dsc
+ 1b7ddb59ac327613cb42c0bbd7ffa06b 177736 user/development optional feedingit_0.1.0.orig.tar.gz
+ 9c4aba31f4ca66c7cb5fe5dbcd83d100 931 user/development optional feedingit_0.1.0-1.debian.tar.gz
+ 762bca546128e97766835cf81a2d7a5b 167012 user/development optional feedingit_0.1.0-1_all.deb
index a9857d9..6a367c0 100644 (file)
Binary files a/psa_harmattan/feedingit/deb_dist/feedingit_0.1.0.orig.tar.gz and b/psa_harmattan/feedingit/deb_dist/feedingit_0.1.0.orig.tar.gz differ
index 47e9f38..a606943 100644 (file)
@@ -1,4 +1,5 @@
-This file should contain a writeup describing what your application does,
-and how to use it. The content of this file goes into the long_description
-field of setup.py, which in turn becomes the long version of the Description
-field in the debian/control file of the project.
+FeedingIt is an easy to use RSS feed reader with portrait mode support and 
+automatic feed updates. You can swipe left and right to move between articles.
+Import and export of subscription lists is supported for OPML files.
+Images can be cached during the feed update, so you can view images in the
+downloaded articles while offline.
index 8acdb75..41167cb 100644 (file)
@@ -49,9 +49,11 @@ class XmlHandler():
     def generateCategoryXml(self):
         xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><xml>"
         for cat in self.listing.getListOfCategories():
     def generateCategoryXml(self):
         xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><xml>"
         for cat in self.listing.getListOfCategories():
+            print cat
             xml += "<category>"
             xml += "<catname>%s</catname>" %sanitize(self.listing.getCategoryTitle(cat))
             xml += "<catid>%s</catid>" % cat
             xml += "<category>"
             xml += "<catname>%s</catname>" %sanitize(self.listing.getCategoryTitle(cat))
             xml += "<catid>%s</catid>" % cat
+            xml += "<unread>%s</unread>" % self.listing.getCategoryUnread(cat)
             xml += "</category>"
         xml += "</xml>"
         return xml
             xml += "</category>"
         xml += "</xml>"
         return xml
index 209c021..10d08b9 100644 (file)
@@ -7,6 +7,7 @@ from PySide import QtDeclarative
 import os
 from os import mkdir, remove, stat, environ
 from os.path import isfile, isdir, exists
 import os
 from os import mkdir, remove, stat, environ
 from os.path import isfile, isdir, exists
+import codecs
 
 # Comment the line below if you don't want to use OpenGL for QML rendering or if it is not supported
 from PySide import QtOpenGL,  QtCore
 
 # Comment the line below if you don't want to use OpenGL for QML rendering or if it is not supported
 from PySide import QtOpenGL,  QtCore
@@ -35,11 +36,11 @@ class Controller(QtCore.QObject):
     def getArticle(self, key, article):
        feed = listing.getFeed(key)
        try:
     def getArticle(self, key, article):
        feed = listing.getFeed(key)
        try:
-          file = open(feed.getContentLink(article))
+          file = codecs.open(feed.getContentLink(article), "r", "utf-8")
           html = file.read().replace("body", "body bgcolor='#ffffff'", 1)
           file.close()
        except:
           html = file.read().replace("body", "body bgcolor='#ffffff'", 1)
           file.close()
        except:
-          html = "<html><body>Error retrieving article</body></html>"
+          html = u"<html><body>Error retrieving article</body></html>"
        return html
     
     @QtCore.Slot(str, result=str)
        return html
     
     @QtCore.Slot(str, result=str)
@@ -67,9 +68,15 @@ class Controller(QtCore.QObject):
         
     @QtCore.Slot()
     def updateAll(self):
         
     @QtCore.Slot()
     def updateAll(self):
-        for feed in listing.getSortedListOfKeys("Manual"):
-            listing.updateFeed(feed)
-            
+        for catid in listing.getListOfCategories():
+            for feed in listing.getSortedListOfKeys("Manual", category=catid):
+                listing.updateFeed(feed)
+
+    @QtCore.Slot(str)
+    def updateCategory(self, catid):
+        for feed in listing.getSortedListOfKeys("Manual", category=catid):
+            listing.updateFeed(feed)           
+
     @QtCore.Slot(str,str,str)
     def addFeed(self, title, url, catid):
         listing.addFeed(title,url, category=catid)
     @QtCore.Slot(str,str,str)
     def addFeed(self, title, url, catid):
         listing.addFeed(title,url, category=catid)
@@ -79,6 +86,14 @@ class Controller(QtCore.QObject):
         listing.addCategory(name)
 
     @QtCore.Slot(str)
         listing.addCategory(name)
 
     @QtCore.Slot(str)
+    def removeFeed(self, key):
+        listing.removeFeed(key)
+
+    @QtCore.Slot(str)
+    def removeCategory(self, catid):
+        listing.removeCategory(catid)
+
+    @QtCore.Slot(str)
     def markAllAsRead(self, key):
         feed = listing.getFeed(key)
         feed.markAllAsRead()
     def markAllAsRead(self, key):
         feed = listing.getFeed(key)
         feed.markAllAsRead()
index f90ffc3..68797cd 100644 (file)
@@ -809,7 +809,7 @@ class Feed(BaseObject):
         #text = '''<div style="color: black; background-color: white;">'''
         text = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
         text += "<html><head><title>" + title + "</title>"
         #text = '''<div style="color: black; background-color: white;">'''
         text = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
         text += "<html><head><title>" + title + "</title>"
-        text += '<meta http-equiv="Content-Type" content="text/html; charset="UTF-8"/>\n'
+        text += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>\n'
         #text += '<style> body {-webkit-user-select: none;} </style>'
         text += '</head><body bgcolor=\"#ffffff\"><div><a href=\"' + link + '\">' + title + "</a>"
         if author != None:
         #text += '<style> body {-webkit-user-select: none;} </style>'
         text += '</head><body bgcolor=\"#ffffff\"><div><a href=\"' + link + '\">' + title + "</a>"
         if author != None:
@@ -1211,6 +1211,15 @@ class Listing(BaseObject):
     
     def getCategoryTitle(self, id):
         return self.lookup('categories', 'title', id)
     
     def getCategoryTitle(self, id):
         return self.lookup('categories', 'title', id)
+
+    def getCategoryUnread(self, id):
+        count = 0
+        for key in self.getListOfFeeds(category=id):
+            try: 
+                count = count + self.getFeedNumberOfUnreadItems(key)
+            except:
+                pass
+        return count
     
     def getSortedListOfKeys(self, order, onlyUnread=False, category=1):
         if   order == "Most unread":
     
     def getSortedListOfKeys(self, order, onlyUnread=False, category=1):
         if   order == "Most unread":
@@ -1286,6 +1295,7 @@ class Listing(BaseObject):
             id=1
         self.db.execute("INSERT INTO categories (id, title, unread, rank) VALUES (?, ?, 0, ?)", (id, title, rank))
         self.db.commit()
             id=1
         self.db.execute("INSERT INTO categories (id, title, unread, rank) VALUES (?, ?, 0, ?)", (id, title, rank))
         self.db.commit()
+        self.cache_invalidate('categories')
     
     def removeFeed(self, key):
         if wc().available ():
     
     def removeFeed(self, key):
         if wc().available ():
@@ -1301,6 +1311,7 @@ class Listing(BaseObject):
 
         if isdir(self.configdir+key+".d/"):
            rmtree(self.configdir+key+".d/")
 
         if isdir(self.configdir+key+".d/"):
            rmtree(self.configdir+key+".d/")
+        self.cache_invalidate('feeds')
            
     def removeCategory(self, key):
         if self.db.execute("SELECT count(*) FROM categories;").fetchone()[0] > 1:
            
     def removeCategory(self, key):
         if self.db.execute("SELECT count(*) FROM categories;").fetchone()[0] > 1:
@@ -1309,6 +1320,7 @@ class Listing(BaseObject):
             self.db.execute("UPDATE categories SET rank=rank-1 WHERE rank>?;", (rank,) )
             self.db.execute("UPDATE feeds SET category=1 WHERE category=?;", (key,) )
             self.db.commit()
             self.db.execute("UPDATE categories SET rank=rank-1 WHERE rank>?;", (rank,) )
             self.db.execute("UPDATE feeds SET category=1 WHERE category=?;", (key,) )
             self.db.commit()
+            self.cache_invalidate('categories')
         
     #def saveConfig(self):
     #    self.listOfFeeds["feedingit-order"] = self.sortedKeys
         
     #def saveConfig(self):
     #    self.listOfFeeds["feedingit-order"] = self.sortedKeys
index 6b25fd9..e089dac 100644 (file)
@@ -70,7 +70,7 @@ Page {
                 TextInputClear {
                     id: urlInput
                     placeHolder: "Feed URL"
                 TextInputClear {
                     id: urlInput
                     placeHolder: "Feed URL"
-
+                    width: parent.width
                 }
 
                 Button {
                 }
 
                 Button {
@@ -81,16 +81,58 @@ Page {
                         //controller.addFeed("",urlInput.text,1);
                         categoryDialog.confirmCategory("", urlInput.text);
                     }
                         //controller.addFeed("",urlInput.text,1);
                         categoryDialog.confirmCategory("", urlInput.text);
                     }
+                    width: 150
                 }
             }
 
                 }
             }
 
-        } //searchTab
+        } //urlTab
+
+        Item {
+            id: categoryTab
+
+            Column {
+                Text {
+                    id: categoryText
+                    font.pixelSize: 22
+                    color: "white"
+                    text: "Enter the category name"
+                }
+
+                TextInputClear {
+                    id: categoryInput
+                    placeHolder: "name"
+                    width: parent.width
+                }
+
+                Button {
+                    id: categoryButton
+                    text: "Add"
+                    onClicked: {
+                        if (categoryInput.text != "") {
+                            controller.addCategory(categoryInput.text)
+                            categoryDialog.reload()
+                            window.categoryReloadRequest()
+                        }
+                    }
+                    width: 150
+                }
+            }
+
+        } //categoryTab
 
         ToolBarLayout {
             id: tabTools
             ToolIcon {
                 iconId: "toolbar-back"
 
         ToolBarLayout {
             id: tabTools
             ToolIcon {
                 iconId: "toolbar-back"
-                onClicked: tabGroup.currentTab.depth > 1 ? tabGroup.currentTab.pop() : pageStack.pop()
+                onClicked: {
+                    if (tabGroup.currentTab.depth > 1) {
+                        tabGroup.currentTab.pop()
+                    } else {
+                        pageStack.pop()
+                    }
+                    window.feedReloadRequest()
+                    window.categoryReloadRequest()
+                }
             }
             ButtonRow {
                 TabButton {
             }
             ButtonRow {
                 TabButton {
@@ -101,7 +143,12 @@ Page {
                     text: "URL"
                     tab: urlTab
                 }
                     text: "URL"
                     tab: urlTab
                 }
+                TabButton {
+                    text: "Categories"
+                    tab: categoryTab
+                }
             }
             }
+
         }
     }
 
         }
     }
 
@@ -130,6 +177,11 @@ Page {
                  open();
              }
 
                  open();
              }
 
+             function reload() {
+                 //categories.reload()
+                 categories.xml = controller.getCategoryXml()
+             }
+
              //model: []
              //model: categories
 
              //model: []
              //model: categories
 
index 83898b4..ac31e0b 100644 (file)
@@ -108,16 +108,24 @@ Item {
             id: listing;
 
             Item {
             id: listing;
 
             Item {
-                width: articleViewer.width; height: 86
+                width: articleViewer.width; height: backRect.height + 3
                 id: listItem
                 id: listItem
-                Rectangle { id: backRect; color: "#dddddd"; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: listItem.width; y: 1 }
+                Rectangle {
+                    id: backRect; color: settings.backColour; opacity: index % 2 ? 0.2 : 0.4;
+                    height: articleText.height + 22; width: listItem.width;
+                    y: 1
+                }
                 Text {
                 Text {
-                    anchors.fill: backRect
+                    id: articleText
+                    anchors.verticalCenter: backRect.verticalCenter
+                    x: 3
+                    width: listItem.width - 6;
+
                     anchors.margins: 5
                     verticalAlignment: Text.AlignVCenter; text: title;
                     anchors.margins: 5
                     verticalAlignment: Text.AlignVCenter; text: title;
-                    color: (unread=="True") ? "white" : "#7b97fd";
+                    color: (unread=="True") ? settings.mainTextColour : settings.secondaryTextColour;
 
 
-                    width: listItem.width; wrapMode: Text.WordWrap; font.bold: false;
+                     wrapMode: Text.WordWrap; font.bold: false;
                     font.pointSize: 18
                 }
                 MouseArea { anchors.fill: listItem;
                     font.pointSize: 18
                 }
                 MouseArea { anchors.fill: listItem;
index 5a97370..4469ba1 100644 (file)
@@ -8,7 +8,9 @@ Item {
     signal categoryClicked(string cat)
 
     function reload() {
     signal categoryClicked(string cat)
 
     function reload() {
-        categories.reload();
+        //categories.reload();
+        categories.xml = controller.getCategoryXml()
+        //console.log(controller.getCategoryXml())
     }
 
     ListView {
     }
 
     ListView {
@@ -25,6 +27,7 @@ Item {
 
         XmlRole { name: "title"; query: "catname/string()" }
         XmlRole { name: "catid"; query: "catid/string()"; isKey: true }
 
         XmlRole { name: "title"; query: "catname/string()" }
         XmlRole { name: "catid"; query: "catid/string()"; isKey: true }
+        XmlRole { name: "unread"; query: "unread/string()" }
     }
 
     Component {
     }
 
     Component {
@@ -36,46 +39,68 @@ Item {
             Item {
                 id: moveMe
                 height: parent.height
             Item {
                 id: moveMe
                 height: parent.height
-                Rectangle { color: "#eeeeee"; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: wrapper.width; y: 1 }
+                Rectangle { color: settings.backColour; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: wrapper.width; y: 1 }
 //                Rectangle {
 //                    x: 6; y: 4; width: 77; height: parent.height - 9; color: "white"; smooth: true
 
 //                }
                 Column {
                     x: 15;
 //                Rectangle {
 //                    x: 6; y: 4; width: 77; height: parent.height - 9; color: "white"; smooth: true
 
 //                }
                 Column {
                     x: 15;
-                    width: wrapper.ListView.view.width /*- 95; y: 15*/; spacing: 2
+                    width: wrapper.ListView.view.width /*- 95;*/
+                    y: 15; spacing: 2
                     anchors.margins: 5
                     height: parent.height
 
                     anchors.margins: 5
                     height: parent.height
 
-                    Text { text: title; color: "white"; width: parent.width; font.bold: true;
-                        height: parent.height
-                        elide: Text.ElideRight; style: Text.Raised; styleColor: "black"; font.pointSize: 20
+                    Text { text: title; color: settings.mainTextColour; width: parent.width; font.bold: true;
+                        //height: parent.height
+                        elide: Text.ElideRight; style: Text.Raised;
+                        styleColor: settings.mainShadowColour;
+                        font.pointSize: settings.mainTextSize
                         verticalAlignment: Text.AlignVCenter;
                     }
                         verticalAlignment: Text.AlignVCenter;
                     }
+                    Text {
+                        text: qsTr("%1 unread items").arg(unread);
+                        color: (unread=="0") ? settings.mainTextColour : settings.secondaryTextColour;
+                        width: parent.width; font.bold: false;
+                        elide: Text.ElideRight;
+                        //style: Text.Raised; styleColor: settings.mainShadowColour;
+                        font.pointSize: settings.secondaryTextSize
+                    }
                     //Text { text: feedname; width: parent.width; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
                 }
                     //Text { text: feedname; width: parent.width; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
                 }
-                Item {
-                    x: wrapper.ListView.view.width - 128; y: 12
-                    height: 58; width: 58;
-                    //anchors.horizontalCenter: parent.horizontalCenter;
-                    Image { source: "common/images/wmEditIcon.png" }
-                    MouseArea {
-                        anchors.fill: parent; onClicked: { container.categoryEdit(catname, catid); }
-                    }
-                    visible: inEditMode
+//                Item {
+//                    x: wrapper.ListView.view.width - 128; y: 12
+//                    height: 58; width: 58;
+//                    //anchors.horizontalCenter: parent.horizontalCenter;
+//                    Image { source: "common/images/wmEditIcon.png" }
+//                    MouseArea {
+//                        anchors.fill: parent; onClicked: { container.categoryEdit(catname, catid); }
+//                    }
+//                    visible: inEditMode
+//                }
+//                Item {
+//                    x: wrapper.ListView.view.width - 64; y: 12
+//                    height: 58; width: 58;
+//                    //anchors.horizontalCenter: parent.horizontalCenter;
+//                    Image { source: "common/images/delete.png" }
+//                    MouseArea {
+//                        anchors.fill: parent; onClicked: { container.categoryDeleted(catid); }
+//                    }
+//                    visible: inEditMode
+//                }
+            }
+            MouseArea {
+                enabled: !inEditMode; anchors.fill: wrapper;
+                onClicked: { categoryClicked(catid); }
+                onPressAndHold: {
+                    window.longPressCategory(catid)
                 }
                 }
-                Item {
-                    x: wrapper.ListView.view.width - 64; y: 12
-                    height: 58; width: 58;
-                    //anchors.horizontalCenter: parent.horizontalCenter;
-                    Image { source: "common/images/delete.png" }
-                    MouseArea {
-                        anchors.fill: parent; onClicked: { container.categoryDeleted(catid); }
-                    }
-                    visible: inEditMode
+            }
+            Component.onCompleted: {
+                if (categories.count == 1) {
+                    categoryClicked(catid)
                 }
             }
                 }
             }
-            MouseArea { enabled: !inEditMode; anchors.fill: wrapper; onClicked: { categoryClicked(catid); } }
         }
     }
 }
         }
     }
 }
index 32b5919..5131cbc 100644 (file)
@@ -56,21 +56,34 @@ Item {
 
             Item {
                 id: moveMe
 
             Item {
                 id: moveMe
-                Rectangle { color: "#dddddd"; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: wrapper.width; y: 1 }
+                Rectangle { color: settings.backColour; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: wrapper.width; y: 1 }
                 Rectangle {
                 Rectangle {
-                    x: 3; y: 4; width: 77; height: 77; color: "#000000"; smooth: true
-                    Image { width:32; height: 32; anchors.verticalCenter: parent.verticalCenter; anchors.horizontalCenter: parent.horizontalCenter;
-                        source: (updating=="True")? "common/images/loading.png" : (icon == "False") ? "common/images/feedingit.png" : icon;
-                        NumberAnimation on rotation {
-                            from: 0; to: 360; running: (updating=="True"); loops: Animation.Infinite; duration: 900
-                        }
+                    x: 3; y: 4; width: 77; height: 77;
+                    color: "#000000"; smooth: true
+                    Image { width:32; height: 32; anchors.verticalCenter: parent.verticalCenter;
+                        anchors.horizontalCenter: parent.horizontalCenter;
+                        source: (icon == "False") ? "common/images/feedingit.png" : icon
+                            // (updating=="True")? "common/images/loading.png" : (icon == "False") ? "common/images/feedingit.png" : icon;
+//                        NumberAnimation on rotation {
+//                            from: 0; to: 360; running: (updating=="True"); loops: Animation.Infinite; duration: 900
+//                        }
                     }
                 }
 
                 Column {
                     x: 92; width: wrapper.ListView.view.width - 95; y: 5; spacing: 2
                     }
                 }
 
                 Column {
                     x: 92; width: wrapper.ListView.view.width - 95; y: 5; spacing: 2
-                    Text { text: title; color: "white"; width: parent.width; font.bold: true; elide: Text.ElideRight; style: Text.Raised; styleColor: "black"; font.pointSize: 18 }
-                    Text { text: updatedDate + " / " + qsTr("%1 unread items").arg(unread); color: (unread=="0") ? "white" : "#7b97fd"; width: parent.width; font.bold: false; elide: Text.ElideRight; style: Text.Raised; styleColor: "black"; font.pointSize: 12 }
+                    Text { text: title; color: settings.mainTextColour;
+                        width: parent.width;
+                        font.bold: true; elide: Text.ElideRight; style: Text.Raised; styleColor: settings.mainShadowColour;
+                        font.pointSize: settings.mainTextSize
+                    }
+                    Text {
+                        text: updatedDate + " / " + qsTr("%1 unread items").arg(unread);
+                        color: (unread=="0") ? settings.mainTextColour : settings.secondaryTextColour;
+                        width: parent.width; font.bold: false; elide: Text.ElideRight;
+                        //style: Text.Raised; styleColor: settings.mainShadowColour;
+                        font.pointSize: settings.secondaryTextSize
+                    }
                     //Text { text: feedname; width: parent.width; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
                 }
 ////                Item {
                     //Text { text: feedname; width: parent.width; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
                 }
 ////                Item {
@@ -101,6 +114,9 @@ Item {
                     feedClicked(feedid)
                     
                 }
                     feedClicked(feedid)
                     
                 }
+                onPressAndHold: {
+                    window.longPressFeed(feedid)
+                }
             }
 
         }
             }
 
         }
diff --git a/psa_harmattan/feedingit/qml/Settings.qml b/psa_harmattan/feedingit/qml/Settings.qml
new file mode 100644 (file)
index 0000000..e6d7362
--- /dev/null
@@ -0,0 +1,10 @@
+import Qt 4.7
+Item {
+    property string mainTextColour: theme.inverted ? "white" : "black"
+    property string mainShadowColour: theme.inverted ? "black" : "white"
+    property int mainTextSize: 18
+    property string secondaryTextColour: theme.inverted?  "#7b97fd" : "#5c71bd"
+    property int secondaryTextSize: 14
+
+    property string backColour: theme.inverted? "#dddddd" : "#222222"
+}
index e38c12a..577bb7b 100644 (file)
@@ -6,12 +6,25 @@ PageStackWindow {
     id: window
     initialPage: categoryPage
 
     id: window
     initialPage: categoryPage
 
-    signal articleClosed()
+    signal longPressCategory(string catid)
+    signal longPressFeed(string key)
+    signal categoryReloadRequest()
+    signal feedReloadRequest()
     property string feedid
     property string catid
 
     Component.onCompleted: theme.inverted= true
 
     property string feedid
     property string catid
 
     Component.onCompleted: theme.inverted= true
 
+    onLongPressFeed: {
+        unsubscribeFeedMenu.key = key
+        unsubscribeFeedMenu.open()
+    }
+
+    onLongPressCategory: {
+        unsubscribeCategoryMenu.catid = catid
+        unsubscribeCategoryMenu.open()
+    }
+
     ToolBarLayout {
         id: commonTools
         visible: false
     ToolBarLayout {
         id: commonTools
         visible: false
@@ -29,6 +42,7 @@ PageStackWindow {
         visualParent: pageStack
         MenuLayout {
             MenuItem { text: qsTr("Settings"); onClicked: {}  }
         visualParent: pageStack
         MenuLayout {
             MenuItem { text: qsTr("Settings"); onClicked: {}  }
+            MenuItem { text: qsTr("Invert Theme"); onClicked: { theme.inverted = !theme.inverted }  }
             MenuItem { text: qsTr("Add Feeds"); onClicked: { pageStack.push(addFeedPage)  } }
             MenuItem { text: qsTr("Update All Categories"); onClicked: controller.updateAll(); }
             MenuItem { text: qsTr("About FeedingIt"); onClicked: query.open(); }
             MenuItem { text: qsTr("Add Feeds"); onClicked: { pageStack.push(addFeedPage)  } }
             MenuItem { text: qsTr("Update All Categories"); onClicked: controller.updateAll(); }
             MenuItem { text: qsTr("About FeedingIt"); onClicked: query.open(); }
@@ -39,8 +53,8 @@ PageStackWindow {
         id: myFeedsMenu
         visualParent: pageStack
         MenuLayout {
         id: myFeedsMenu
         visualParent: pageStack
         MenuLayout {
-            MenuItem { text: qsTr("Update All Feeds"); onClicked: controller.updateAll(); }
-            MenuItem { text: qsTr("About FeedingIt"); onClicked: query.open(); }
+            MenuItem { text: qsTr("Update All Feeds"); onClicked: controller.updateCategory(catid); }
+            //MenuItem { text: qsTr("About FeedingIt"); onClicked: query.open(); }
         }
     }
 
         }
     }
 
@@ -50,7 +64,61 @@ PageStackWindow {
         MenuLayout {
             MenuItem { text: qsTr("Mark All As Read"); onClicked: controller.markAllAsRead(feedid); }
             MenuItem { text: qsTr("Update Feed"); onClicked: controller.updateFeed(feedid); }
         MenuLayout {
             MenuItem { text: qsTr("Mark All As Read"); onClicked: controller.markAllAsRead(feedid); }
             MenuItem { text: qsTr("Update Feed"); onClicked: controller.updateFeed(feedid); }
-            MenuItem { text: qsTr("About FeedingIt"); onClicked: query.open(); }
+            //MenuItem { text: qsTr("About FeedingIt"); onClicked: query.open(); }
+        }
+    }
+
+    Menu {
+        id: unsubscribeFeedMenu
+        visualParent: pageStack
+        property string key
+        MenuLayout {
+            //MenuItem { text: qsTr("Update"); onClicked: controller.updateFeed(parent.feedid); }
+            MenuItem { text: qsTr("Delete");
+                onClicked: {
+                    feedConfirm.open()
+                    unsubscribeFeedMenu.close()
+                }
+            }
+        }
+        QueryDialog {
+            id: feedConfirm
+            //icon: "common/images/feedingit.png"
+            //titleText: "Delete Feed?"
+            message: "Delete this feed?"
+            acceptButtonText: "OK"
+            rejectButtonText: "Cancel"
+            onAccepted: {
+                controller.removeFeed(unsubscribeFeedMenu.key);
+                window.feedReloadRequest()
+            }
+        }
+    }
+
+    Menu {
+        id: unsubscribeCategoryMenu
+        visualParent: pageStack
+        property string catid
+        MenuLayout {
+            //MenuItem { text: qsTr("Update"); onClicked: controller.updateFeed(parent.feedid); }
+            MenuItem { text: qsTr("Delete");
+                onClicked: {
+                    categoryConfirm.open()
+                    unsubscribeFeedMenu.close()
+                }
+            }
+        }
+        QueryDialog {
+            id: categoryConfirm
+            //icon: "common/images/feedingit.png"
+            //titleText: "Delete Feed?"
+            message: "Delete this category?"
+            acceptButtonText: "OK"
+            rejectButtonText: "Cancel"
+            onAccepted: {
+                controller.removeCategory(unsubscribeCategoryMenu.catid);
+                window.categoryReloadRequest()
+            }
         }
     }
 
         }
     }
 
@@ -65,23 +133,24 @@ PageStackWindow {
         acceptButtonText: "OK"
     }
 
         acceptButtonText: "OK"
     }
 
-//    Page{
-//        id: mainPage
-//        Component.onCompleted: {
-//            var main = Qt.createComponent("FeedingIt.qml");
-//            main.createObject(mainPage);
-//        }
-//    }
-
     Component {
         id: categoryPage
         Page {
             tools: commonTools
             Categories {
     Component {
         id: categoryPage
         Page {
             tools: commonTools
             Categories {
+                id: categoriesItem
                 onCategoryClicked: {
                     window.catid = cat
                     pageStack.push(feedsPage)
                 }
                 onCategoryClicked: {
                     window.catid = cat
                     pageStack.push(feedsPage)
                 }
+
+            }
+            Connections {
+                target: window
+                onCategoryReloadRequest: {
+                    console.log("category reloaded")
+                    categoriesItem.reload()
+                }
             }
         }
     }
             }
         }
     }
@@ -99,6 +168,7 @@ PageStackWindow {
                     window.feedid = feedid
                     pageStack.push(articlesPage)
                 }
                     window.feedid = feedid
                     pageStack.push(articlesPage)
                 }
+
             }
             ToolBarLayout {
                 id: feedsTools
             }
             ToolBarLayout {
                 id: feedsTools
@@ -106,6 +176,7 @@ PageStackWindow {
                 ToolIcon { iconId: "toolbar-back";
                     onClicked: {
                         myArticlesMenu.close();
                 ToolIcon { iconId: "toolbar-back";
                     onClicked: {
                         myArticlesMenu.close();
+                        window.categoryReloadRequest()
                         pageStack.pop();
                     }
                 }
                         pageStack.pop();
                     }
                 }
@@ -117,7 +188,7 @@ PageStackWindow {
             }
             Connections {
                  target: window
             }
             Connections {
                  target: window
-                 onArticleClosed: feedsItem.reload()
+                 onFeedReloadRequest: feedsItem.reload()
              }
         }
     }
              }
         }
     }
@@ -141,7 +212,7 @@ PageStackWindow {
                             flipper.articleShown = false;
                             flipper.reload()
                         } else {
                             flipper.articleShown = false;
                             flipper.reload()
                         } else {
-                            window.articleClosed();
+                            window.feedReloadRequest();
                             pageStack.pop();
                         }
                     }
                             pageStack.pop();
                         }
                     }
@@ -174,4 +245,8 @@ PageStackWindow {
         id: addFeedPage
         AddFeed {}
     }
         id: addFeedPage
         AddFeed {}
     }
+
+    Settings {
+        id: settings
+    }
 }
 }
index d243933..129f500 100644 (file)
@@ -803,7 +803,7 @@ class Feed(BaseObject):
         #text = '''<div style="color: black; background-color: white;">'''
         text = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
         text += "<html><head><title>" + title + "</title>"
         #text = '''<div style="color: black; background-color: white;">'''
         text = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
         text += "<html><head><title>" + title + "</title>"
-        text += '<meta http-equiv="Content-Type" content="text/html; charset="UTF-8"/>\n'
+        text += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>\n'
         #text += '<style> body {-webkit-user-select: none;} </style>'
         text += '</head><body bgcolor=\"#ffffff\"><div><a href=\"' + link + '\">' + title + "</a>"
         if author != None:
         #text += '<style> body {-webkit-user-select: none;} </style>'
         text += '</head><body bgcolor=\"#ffffff\"><div><a href=\"' + link + '\">' + title + "</a>"
         if author != None: