install -d ${DESTDIR}/usr/bin
install src/FeedingIt ${DESTDIR}/usr/bin
install -d ${DESTDIR}/opt/FeedingIt
+ install -d ${DESTDIR}/opt/FeedingIt/qml/i18n
+ install -d ${DESTDIR}/opt/FeedingIt/qml/common
+ install -d ${DESTDIR}/opt/FeedingIt/qml/common/images
+ install -d ${DESTDIR}/opt/FeedingIt/qml
+ install src/qml/*.qml ${DESTDIR}/opt/FeedingIt/qml
+ install src/qml/i18n/*.qm ${DESTDIR}/opt/FeedingIt/qml/i18n
+ install src/qml/common/*.qml ${DESTDIR}/opt/FeedingIt/qml/common
+ install src/qml/common/images/*.{sci,png} ${DESTDIR}/opt/FeedingIt/qml/common/images
install src/FeedingIt.py ${DESTDIR}/opt/FeedingIt
install src/feedparser.py ${DESTDIR}/opt/FeedingIt
install src/portrait.py ${DESTDIR}/opt/FeedingIt
install src/rss.py ${DESTDIR}/opt/FeedingIt
install src/opml.py ${DESTDIR}/opt/FeedingIt
install src/config.py ${DESTDIR}/opt/FeedingIt
+ install src/FeedingIt-Web.py ${DESTDIR}/opt/FeedingIt
#install src/feedingit_status.desktop ${DESTDIR}/opt/FeedingIt
install src/update_feeds.py ${DESTDIR}/opt/FeedingIt
install src/updatedbus.py ${DESTDIR}/opt/FeedingIt
+feedingit (0.9.0-0) unstable; urgency=low
+
+ * Added QML interface
+ * Fixed the use of id as article identifier (#6473)
+ * Added categories
+
+ -- Yves <yves@marcoz.org> Sun, 31 Oct 2010 28:03:19 -0800
+
feedingit (0.8.0-9) unstable; urgency=low
- * Fixed date for articles without a date field
+ * Fixed date in feed shows as 1/1/1970 if no date field in rss feed is present (#6398)
-- Yves <yves@marcoz.org> Fri, 12 Sep 2010 10:54:19 -0800
#cp feedingit_status.desktop /usr/share/applications/hildon-status-menu/
nice python2.5 update_feeds.py
;;
+qml)
+ cd /opt/FeedingIt
+ python2.5 FeedingIt-Web.py 2>&1 >/dev/null &
+ pid=`pidof python2.5 FeedingIt-Web.py`
+ qmlviewer -fullscreen qml/FeedingIt.qml
+ kill $pid
+ ;;
*)
cd /opt/FeedingIt
python2.5 FeedingIt.py
--- /dev/null
+import BaseHTTPServer
+import sys
+from rss_sqlite import Listing
+from xml import sax
+from cgi import escape
+from re import sub
+from htmlentitydefs import name2codepoint
+
+CONFIGDIR = "/home/user/.feedingit/"
+
+def unescape(text):
+ def fixup(m):
+ text = m.group(0)
+ if text[:2] == "&#":
+ # character reference
+ try:
+ if text[:3] == "&#x":
+ return unichr(int(text[3:-1], 16))
+ else:
+ return unichr(int(text[2:-1]))
+ except ValueError:
+ pass
+ else:
+ # named entity
+ try:
+ text = unichr(name2codepoint[text[1:-1]])
+ except KeyError:
+ pass
+ return text # leave as is
+ return sub("&#?\w+;", fixup, text)
+
+class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
+
+ def openTaskSwitch(self):
+ import subprocess
+ subprocess.Popen("dbus-send /com/nokia/hildon_desktop com.nokia.hildon_desktop.exit_app_view", shell=True)
+
+ def getConfigXml(self):
+ xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><xml>"
+ xml += "<hideReadFeed>True</hideReadFeed>"
+ xml += "<hideReadArticles>True</hideReadArticles>"
+ xml += "</xml>"
+ return xml
+
+ def generateCategoryXml(self):
+ xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><xml>"
+ for cat in listing.getListOfCategories():
+ xml += "<category>"
+ xml += "<catname>%s</catname>" %listing.getCategoryTitle(cat)
+ xml += "<catid>%s</catid>" % cat
+ xml += "</category>"
+ xml += "</xml>"
+ return xml
+
+ def fix_title(self, title):
+ return escape(unescape(title).replace("<em>","").replace("</em>","").replace("<nobr>","").replace("</nobr>","").replace("<wbr>","").replace("—","-"))
+
+ def generateFeedsXml(self, catid):
+ xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><xml>"
+ for key in listing.getSortedListOfKeys("Manual", category=catid):
+ xml += "<feed>"
+ xml += "<feedname>%s</feedname>" %listing.getFeedTitle(key)
+ xml += "<feedid>%s</feedid>" %key
+ xml += "<unread>%s</unread>" %listing.getFeedNumberOfUnreadItems(key)
+ xml += "<updatedDate>%s</updatedDate>" %listing.getFeedUpdateTime(key)
+ xml += "<icon>%s</icon>" %listing.getFavicon(key)
+ xml += "</feed>"
+ xml += "</xml>"
+ return xml
+
+ def generateArticlesXml(self, key, onlyUnread, markAllAsRead):
+ feed = listing.getFeed(key)
+ if markAllAsRead=="True":
+ feed.markAllAsRead()
+ listing.updateUnread(key)
+ xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><xml>"
+ if onlyUnread == "False":
+ onlyUnread = False
+ for id in feed.getIds(onlyUnread):
+ xml += "<article>"
+ xml += "<title>%s</title>" %self.fix_title(feed.getTitle(id))
+ xml += "<articleid>%s</articleid>" %id
+ xml += "<unread>%s</unread>" %str(feed.isEntryRead(id))
+ xml += "<updatedDate>%s</updatedDate>" %feed.getDateStamp(id)
+ xml += "<path>%s</path>" %feed.getContentLink(id)
+ xml += "</article>"
+ xml += "</xml>"
+ return xml
+
+ def do_GET(self):
+ (req, sep, arg) = self.path.partition("?")
+ request = req.split("/")
+ arguments = {}
+ if arg != "":
+ args = arg.split("&")
+ print args
+ for arg in args:
+ ele = arg.split("=")
+ print ele
+ #try:
+ arguments[ele[0]] = ele[1]
+ #except:
+ # pass
+ if request[1] == "categories":
+ xml = self.generateCategoryXml()
+ elif request[1] == "feeds":
+ catid = request[2]
+ xml = self.generateFeedsXml(catid)
+ elif request[1] == "articles":
+ key = request[2]
+ onlyUnread = arguments.get("onlyUnread","False")
+ markAllAsRead = arguments.get("markAllAsRead", "False")
+ xml = self.generateArticlesXml(key, onlyUnread, markAllAsRead)
+ elif request[1] == "html":
+ key = request[2]
+ article = request[3]
+ feed = listing.getFeed(key)
+ file = open(feed.getContentLink(article))
+ feed.setEntryRead(article)
+ html = file.read().replace("body", "body bgcolor='#ffffff'", 1)
+ file.close()
+ self.send_response(200)
+ self.send_header("Content-type", "text/html")
+ self.end_headers()
+ self.wfile.write(html)
+ listing.updateUnread(key)
+ return
+ elif request[1] == "config":
+ xml = self.getConfigXml()
+ elif request[1] == "home":
+ file = open(self.path)
+ self.send_response(200)
+ self.send_header("Content-type", "text/html")
+ self.end_headers()
+ self.wfile.write(file.read())
+ file.close()
+ return
+ elif request[1] == "task":
+ self.openTaskSwitch()
+ xml = "<xml>OK</xml>"
+ else:
+ self.send_error(404, "File not found")
+ return
+ self.send_response(200)
+ self.send_header("Content-type", "text/xml")
+ self.end_headers()
+ self.wfile.write(xml.encode("utf-8"))
+
+PORT = 8000
+
+listing = Listing(CONFIGDIR)
+
+httpd = BaseHTTPServer.HTTPServer(("127.0.0.1", PORT), Handler)
+print "serving at port", PORT
+httpd.serve_forever()
wizard = AddWidgetWizard(self.window, self.listing, urlIn, self.listing.getListOfCategories())
ret = wizard.run()
if ret == 2:
- (title, url) = wizard.getData()
+ (title, url, category) = wizard.getData()
if (not title == '') and (not url == ''):
- self.listing.addFeed(title, url)
+ self.listing.addFeed(title, url, category=category)
wizard.destroy()
self.displayListing()
--- /dev/null
+import Qt 4.7
+import QtWebKit 1.0
+import "common" as Common
+
+Rectangle {
+ x: parent.width; /*height: parent.height;*/
+ width: parent.width;
+ height: parent.height
+ property alias zoomEnabled: slider.visible;
+ property alias value: slider.value;
+ //anchors.top: parent.top; anchors.bottom: parent.bottom;
+ color: "white";
+
+ Flickable {
+ id: flickable
+ //anchors.fill: screen;
+ height: parent.height;
+ width: parent.width;
+ contentWidth: webView.width*webView.scale; //Math.max(screen.width,webView.width*webView.scale)
+ contentHeight: Math.max(screen.height,webView.height*webView.scale)
+ //contentWidth: childrenRect.width; contentHeight: childrenRect.height
+
+ flickDeceleration: 1000;
+
+ WebView {
+ id: webView
+ url: articleDisplay.url;
+ preferredWidth: flickable.width
+ preferredHeight: flickable.height
+ //scale: 1.25;
+ transformOrigin: Item.TopLeft
+ scale: slider.value;
+ settings.defaultFontSize: 24
+ }
+ }
+
+ Common.Slider {
+ id: slider; visible: false
+ minimum: 0.2;
+ maximum: 2;
+ property real prevScale: 1
+ anchors {
+ bottom: parent.bottom; bottomMargin: 65
+ left: parent.left; leftMargin: 25
+ right: parent.right; rightMargin: 25
+ }
+ onValueChanged: {
+ if (webView.width * value > flickable.width) {
+ var xoff = (flickable.width/2 + flickable.contentX) * value / prevScale;
+ flickable.contentX = xoff - flickable.width/2;
+ }
+ if (webView.height * value > flickable.height) {
+ var yoff = (flickable.height/2 + flickable.contentY) * value / prevScale;
+ flickable.contentY = yoff - flickable.height/2;
+ }
+ prevScale = value;
+ }
+ Component.onCompleted: {value=0; value=1; }
+ }
+}
--- /dev/null
+import Qt 4.7
+
+Item {
+ //anchors.fill: parent;
+ width: parent.width;
+ property string feedid : ""
+ property alias count: articles.count
+ property alias url: articles.source
+ x: parent.width; height: parent.height;
+ anchors.top: parent.top; anchors.bottom: parent.bottom
+
+ function getArticleid(index) {
+ return articles.get(index).articleid
+ }
+
+ function reload() {
+ articles.reload()
+ }
+
+ ListView {
+ id: articleList; model: articles; delegate: articleDelegate; z: 6
+ width: parent.width; height: parent.height; /*x: 0;*/
+ cacheBuffer: 100;
+ flickDeceleration: 1500
+ }
+
+ XmlListModel {
+ id: articles
+
+ source: feedid == "" ? "" : "http://localhost:8000/articles/" + feedid + "?onlyUnread=" + hideReadArticles
+ query: "/xml/article"
+
+ XmlRole { name: "title"; query: "title/string()" }
+ XmlRole { name: "articleid"; query: "articleid/string()"; isKey: true }
+ XmlRole { name: "path"; query: "path/string()" }
+ XmlRole { name: "unread"; query: "unread/string()"; isKey: true}
+ }
+
+ Component {
+ id: articleDelegate
+
+ Item {
+ id: wrapper; width: wrapper.ListView.view.width; height: 86
+ Item {
+ id: moveMe
+ Rectangle { id: backRect; color: "black"; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: wrapper.width; y: 1 }
+ Text {
+ anchors.fill: backRect
+ anchors.margins: 5
+ verticalAlignment: Text.AlignVCenter; text: title; color: (unread=="True") ? "white" : "#7b97fd";
+ width: wrapper.width; wrapMode: Text.WordWrap; font.bold: false;
+ }
+// Rectangle {
+// x: 3; y: 4; width: 77; height: 77; color: "#ff0000"; smooth: true
+
+// }
+
+// Column {
+// x: 3;
+
+// width: wrapper.width - 3; y: 5; spacing: 2
+// height: parent.height;
+// Text { Rectangle {anchors.fill: parent; color: "white"; opacity: 0.5;}
+// verticalAlignment: Text.AlignVCenter; text: title; color: (unread=="True") ? "white" : "#7b97fd"; width: parent.width; wrapMode: Text.WordWrap; font.bold: false; /*elide: Text.ElideRight;*/ /*style: Text.Raised;*/ styleColor: "black"; }
+// //Text { text: feedname; width: parent.width; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
+// }
+ }
+ MouseArea { anchors.fill: wrapper; onClicked: { container.articleClicked(articleid, index) } }
+ }
+
+ }
+
+}
--- /dev/null
+import Qt 4.7
+
+Item {
+// anchors.fill: parent;
+ width: parent.width; height: parent.height;
+ //anchors.top: parent.top; anchors.bottom: parent.bottom
+
+ ListView {
+ id: categoryList; model: categories; delegate: categoryDelegate; z: 6;
+ cacheBuffer: 100; width: parent.width; height: parent.height;
+ }
+
+ XmlListModel {
+
+ id: categories
+
+ //source: "http://api.flickr.com/services/feeds/photos_public.gne?"+(tags ? "tags="+tags+"&" : "")+"format=rss2"
+ //source: "/home/ymarcoz/feedlist.xml"
+ source: "http://localhost:8000/categories"
+ query: "/xml/category"
+ //namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";"
+
+ XmlRole { name: "title"; query: "catname/string()" }
+ XmlRole { name: "catid"; query: "catid/string()"; isKey: true }
+
+ }
+
+ Component {
+ id: categoryDelegate
+
+ Item {
+
+ id: wrapper; width: wrapper.ListView.view.width; height: 86
+ Item {
+ id: moveMe
+ height: parent.height
+ Rectangle { color: "black"; 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: 92; width: wrapper.ListView.view.width - 95; y: 15; spacing: 2
+ Text { text: title; color: "white"; width: parent.width; font.bold: true; elide: Text.ElideRight; style: Text.Raised; styleColor: "black" }
+ //Text { text: feedname; width: parent.width; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
+ }
+ }
+ MouseArea { anchors.fill: wrapper; onClicked: { container.categoryClicked(catid); } }
+ }
+ }
+}
--- /dev/null
+import Qt 4.7
+import "common" as Common
+// Depends on qt4-declarative-qmlviewer
+
+Item {
+ width: 640
+ height: 480
+ id: screen
+
+ Rectangle {
+ id: container
+ anchors.fill: parent; color: "#343434";
+
+ function modulo(x,y) {
+ // Fixes modulo for negative numbers
+ return ((x%y)+y)%y;
+ }
+
+ function categoryClicked(catid) {
+ feedsItem.catid = catid;
+ categoriesItem.isShown = false;
+ feedsItem.visible = true;
+ }
+
+ function feedClicked(feedid) {
+ articlesItem.feedid = feedid;
+ articlesItem.visible = true;
+ }
+
+ function articleClicked(articleid, index) {
+ // Assign the articleId for the current, next and previous article to the associated variables
+ // Note the modulo, so it goes around
+ articleDisplay.articleindex = modulo(index,articlesItem.count)
+ articleDisplay.nextArticle = articlesItem.getArticleid(modulo(index+1,articlesItem.count))
+ articleDisplay.prevArticle = articlesItem.getArticleid(modulo(index-1,articlesItem.count))
+ articleDisplay.articleid = articleid
+ articleDisplay.visible = true;
+ }
+
+ function backClicked() {
+ if (articleDisplay.visible) {
+ // We're viewing an article, and going back to article listing
+ articleDisplay.visible = false;
+ articleDisplay.articleid = "";
+ articleDisplay.value = 1;
+ articlesItem.reload()
+ return;
+ }
+ if (articlesItem.visible) {
+ // Viewing articles, going back to feeds
+ //articlesItem.feedid = "";
+ feedsItem.reload();
+ articlesItem.visible = false;
+ //articlesItem.reload();
+ return;
+ }
+ if (feedsItem.visible) {
+ // Viewing feeds, going back to categories
+ //feedsItem.catid = "";
+ feedsItem.visible = false;
+ //feedsItem.reload();
+ categoriesItem.isShown = true;
+ return;
+ }
+ if (!feedsItem.visible) {
+ // Viewing categories, quitting
+ Qt.quit();
+ }
+ }
+
+ Common.Menu {
+ id: config
+ z: 5
+ property string hideReadFeeds : "False"
+ property string hideReadArticles : "False"
+
+ property bool isShown: false;
+
+ //width: parent.width; height: parent.height;
+
+ //height: 0
+ states: State {
+ name: "shown"; when: config.isShown == true
+ PropertyChanges { target: config; y: 66 }
+ }
+
+ transitions: Transition {
+ NumberAnimation { properties: "y"; duration: 300; easing.type: "InOutQuad" }
+ }
+
+ }
+
+ Common.ConfirmationMessage {
+ id: confirmationMessage;
+ visible: false
+ onOkClicked: { var doc = new XMLHttpRequest();
+ console.log(articlesItem.url+"&markAllAsRead=True")
+ var url = articlesItem.url+"&markAllAsRead=True"
+ console.log(url)
+ doc.open("GET", url);
+ doc.send();
+ var xmlDoc=doc.responseXML;
+ articlesItem.reload();
+ feedsItem.reload()
+ visible=false
+ }
+ onCancelClicked: visible=false
+ }
+
+ Common.ToolBar {
+ id: toolBar; z: 7
+ height: 66; anchors.top: parent.top; width: parent.width; opacity: 0.9
+ button1Label: qsTr("Config"); button2Label: qsTr("Back")
+ nextLabel: qsTr("Next"); prevLabel: qsTr("Previous")
+ markAllLabel: qsTr("Mark All As Read"); zoomLabel: qsTr("Zoom")
+ taskSwitcherLabel: qsTr("Task Switch")
+ onButton1Clicked: config.isShown = !config.isShown;
+ onButton2Clicked: container.backClicked()
+ onPrevClicked: container.articleClicked(articleDisplay.prevArticle, articleDisplay.articleindex-1)
+ onNextClicked: container.articleClicked(articleDisplay.nextArticle, articleDisplay.articleindex+1)
+ onMarkAllClicked: {
+ confirmationMessage.text = qsTr("Do you want to mark all items as read?");
+ confirmationMessage.visible = true;
+ }
+ onZoomClicked: { articleDisplay.zoomEnabled = !articleDisplay.zoomEnabled; }
+ onTaskSwitcherClicked: {
+ var doc = new XMLHttpRequest();
+ var url = "http://localhost:8000/task"
+ doc.open("GET", url);
+ doc.send();
+ //var xmlDoc=doc.responseXML;
+ }
+
+ states: [ State {
+ name: "navButtons"; when: articleDisplay.articleid != ""
+ PropertyChanges { target: toolBar; nextVisible: true; }
+ PropertyChanges { target: toolBar; prevVisible: true; }
+ PropertyChanges { target: toolBar; zoomVisible: true; }
+ },
+ State {
+ name: "feedButtons"; when: (articleDisplay.articleid == "")&&(articlesItem.feedid!="")
+ PropertyChanges { target: toolBar; markAllVisible: true; }
+ }
+ ]
+ }
+
+ Item {
+ id: views
+ //x: 2;
+ //y:66;
+ width: parent.width // - 4
+ anchors.top: toolBar.bottom; anchors.bottom: parent.bottom
+
+ Categories {
+ // Loads the categoryList view and delegate
+ id: categoriesItem
+ property bool isShown: true;
+
+ states: State {
+ name: "shown"; when: categoriesItem.isShown == false
+ PropertyChanges { target: categoriesItem; x: -screen.width }
+ }
+
+ transitions: Transition {
+ NumberAnimation { properties: "x"; duration: 300; easing.type: "InOutQuad" }
+ }
+
+ }
+
+ Feeds {
+
+ // Loads the feedList view and delegate
+ id: feedsItem;
+ property string hideReadFeeds: config.hideReadFeeds
+ visible: false;
+
+ states: [
+ State { name: "articlesShown"; when: articlesItem.visible; PropertyChanges { target: feedsItem; x: -parent.width } },
+ State { name: "shown"; when: feedsItem.visible; PropertyChanges { target: feedsItem; x: 0 } }
+ ]
+
+ transitions: Transition {
+ NumberAnimation { properties: "x"; duration: 300; easing.type: "InOutQuad" }
+ }
+
+ }
+
+ Articles {
+ // Loads the articleLost view and delegate
+ id: articlesItem;
+ property string hideReadArticles: config.hideReadArticles
+ visible: false;
+
+ states: [
+ State { name: "shown"; when: articleDisplay.visible; PropertyChanges { target: articlesItem; x: -parent.width }
+ },
+ State { name: "articleShown"; when: articlesItem.visible; PropertyChanges { target: articlesItem; x: 0 }
+ }
+ ]
+
+ transitions: Transition {
+ NumberAnimation { properties: "x"; duration: 300; easing.type: "InOutQuad" }
+ }
+ }
+
+ ArticleDisplay{
+ // Loads the WebView
+ id: articleDisplay;
+ //anchors.top: toolBar.bottom;
+ //anchors.bottom: screen.bottom;
+ height: parent.height;
+ visible: false;
+ property string feedid: articlesItem.feedid;
+ property string articleid: "";
+ property int articleindex: 0;
+ property string nextArticle: "";
+ property string prevArticle: "";
+ property string url: (articleid == "") ? "" : "http://localhost:8000/html/" + articleDisplay.feedid + "/" + articleDisplay.articleid;
+
+ gradient: Gradient {
+ GradientStop {
+ position: 0.00;
+ color: "#ffffff";
+ }
+ GradientStop {
+ position: 1.00;
+ color: "#ffffff";
+ }
+ }
+
+ states: State { name: "shown"; when: articleDisplay.visible; PropertyChanges { target: articleDisplay; x: 0 }
+ }
+
+ transitions: Transition {
+ NumberAnimation { properties: "x"; duration: 300; easing.type: "InOutQuad" }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/* File generated by QtCreator */
+
+import QmlProject 1.0
+
+Project {
+ /* Include .qml, .js, and image files from current directory and subdirectories */
+ QmlFiles {
+ directory: "."
+ }
+ JavaScriptFiles {
+ directory: "."
+ }
+ ImageFiles {
+ directory: "."
+ }
+ /* List of plugin directories passed to QML runtime */
+ // importPaths: [ "../exampleplugin" ]
+}
--- /dev/null
+<!DOCTYPE QtCreatorProject>
+<qtcreator>
+ <data>
+ <variable>ProjectExplorer.Project.ActiveTarget</variable>
+ <value type="int">0</value>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.EditorSettings</variable>
+ <valuemap type="QVariantMap">
+ <value key="EditorConfiguration.Codec" type="QByteArray">Default</value>
+ </valuemap>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.Target.0</variable>
+ <valuemap type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">QML Viewer</value>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">QML Viewer</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QmlProjectManager.QmlTarget</value>
+ <value key="ProjectExplorer.Target.ActiveBuildConfiguration" type="int">-1</value>
+ <value key="ProjectExplorer.Target.ActiveDeployConfiguration" type="int">-1</value>
+ <value key="ProjectExplorer.Target.ActiveRunConfiguration" type="int">0</value>
+ <value key="ProjectExplorer.Target.BuildConfigurationCount" type="int">0</value>
+ <value key="ProjectExplorer.Target.DeployConfigurationCount" type="int">0</value>
+ <valuemap key="ProjectExplorer.Target.RunConfiguration.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString"></value>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">QML Viewer</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QmlProjectManager.QmlRunConfiguration</value>
+ <value key="QmlProjectManager.QmlRunConfiguration.MainScript" type="QString">CurrentFile</value>
+ <value key="QmlProjectManager.QmlRunConfiguration.QDeclarativeViewerArguments" type="QString"></value>
+ <value key="QmlProjectManager.QmlRunConfiguration.QtVersion" type="int">4</value>
+ <value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value>
+ <value key="RunConfiguration.UseCppDebugger" type="bool">false</value>
+ <value key="RunConfiguration.UseQmlDebugger" type="bool">true</value>
+ </valuemap>
+ <value key="ProjectExplorer.Target.RunConfigurationCount" type="int">1</value>
+ </valuemap>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.TargetCount</variable>
+ <value type="int">1</value>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.Updater.EnvironmentId</variable>
+ <value type="QString">{6449687d-a4d3-4afc-95ac-89e1027ef47e}</value>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.Updater.FileVersion</variable>
+ <value type="int">8</value>
+ </data>
+</qtcreator>
--- /dev/null
+import Qt 4.7
+
+Item {
+ //anchors.fill: parent;
+ width: parent.width;
+ property string catid : ""
+ x: parent.width; height: parent.height;
+ anchors.top: parent.top; anchors.bottom: parent.bottom
+
+ function reload() {
+ feeds.reload()
+ }
+
+ //Component.onCompleted: { console.log(x + " /") }
+
+ ListView {
+ id: feedList; model: feeds; delegate: feedDelegate; z: 6
+ width: parent.width; height: parent.height; /*x: 0;*/
+ cacheBuffer: 100;
+ flickDeceleration: 1500
+ }
+
+ XmlListModel {
+
+ id: feeds
+
+ source: catid == "" ? "" : "http://localhost:8000/feeds/" + catid //+ "?onlyUnread=" + parent.hideReadArticles
+ query: "/xml/feed"
+
+ XmlRole { name: "title"; query: "feedname/string()" }
+ XmlRole { name: "feedid"; query: "feedid/string()"; isKey: true }
+ XmlRole { name: "unread"; query: "unread/string()"; isKey: true }
+ XmlRole { name: "updatedDate"; query: "updatedDate/string()" }
+ XmlRole { name: "icon"; query: "icon/string()" }
+ }
+
+ Component {
+ id: feedDelegate
+
+ Item {
+ id: wrapper; width: wrapper.ListView.view.width;
+ visible: (unread == "0" && feedsItem.hideReadFeeds=="True") ? false : true
+ height: (visible) ? 86 : 0
+
+ Item {
+ id: moveMe
+ Rectangle { color: "black"; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: wrapper.width; y: 1 }
+ 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: (icon == "False") ? "" : icon }
+ }
+
+ 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" }
+ 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" }
+ //Text { text: feedname; width: parent.width; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
+ }
+ }
+ MouseArea { anchors.fill: wrapper; onClicked: { container.feedClicked(feedid) } }
+ }
+
+ }
+
+}
--- /dev/null
+import Qt 4.7
+import QtWebKit 1.0
+import "common" as Common
+
+Rectangle {
+ width: 380
+ height: 480
+
+ //anchors.top: parent.top; anchors.bottom: parent.bottom;
+ color: "white";
+
+ property string url: "";
+ Flickable {
+ id: flickable
+ //anchors.fill: screen;
+ height: parent.height;
+ width: parent.width;
+ contentWidth: webView.width*scale; //Math.max(screen.width,webView.width*webView.scale)
+ contentHeight: Math.max(parent.height,webView.height*webView.scale)
+
+ WebView {
+ id: webView
+ url: "http://www.google.com";
+ //url: "/home/user/.feedingit/640fb167aca8bf5318ed721c5162f5eb.d/56a86b6b1675716ab54db83b1a78ab4c.html"
+ preferredWidth: flickable.width
+ preferredHeight: flickable.height
+ settings.defaultFontSize: 32
+ scale: slider.value;
+ //smooth: false
+ //width: 200
+ //width: parent.width; height: parent.height;
+// Rectangle {
+// color: "#10000000"
+// anchors.fill: parent
+// }
+ //onLoadFinished: {console.log("Hello"); url="javascript:void(document.body.style.background='red');" }
+ onLoadFinished: {console.log(url);/* url="javascript:(function() { " +
+ "document.getElementsByTagName('body')[0].style.background = 'red'; " +
+ "})()"; console.log(url);*/ /*heuristicZoom(0,0,100)*/ }
+ }
+ }
+ Common.Slider {
+ id: slider; visible: true
+ minimum: 0.2;
+ maximum: 2;
+ value: 1
+ property real prevScale: 1
+ anchors {
+ bottom: parent.bottom; bottomMargin: 65
+ left: parent.left; leftMargin: 25
+ right: parent.right; rightMargin: 25
+ }
+ onValueChanged: {
+ if (webView.width * value > flickable.width) {
+ var xoff = (flickable.width/2 + flickable.contentX) * value / prevScale;
+ flickable.contentX = xoff - flickable.width/2;
+ }
+ if (webView.height * value > flickable.height) {
+ var yoff = (flickable.height/2 + flickable.contentY) * value / prevScale;
+ flickable.contentY = yoff - flickable.height/2;
+ }
+ prevScale = value;
+ }
+ Component.onCompleted: { value=0; value=1; }
+ }
+}
--- /dev/null
+import Qt 4.7
+
+Item {
+ id: container
+
+ signal clicked
+
+ property string text
+
+ BorderImage {
+ id: buttonImage
+ source: "images/toolbutton.sci"
+ width: container.width; height: container.height
+ }
+ BorderImage {
+ id: pressed
+ opacity: 0
+ source: "images/toolbutton.sci"
+ width: container.width; height: container.height
+ }
+ MouseArea {
+ id: mouseRegion
+ anchors.fill: buttonImage
+ onClicked: { container.clicked(); }
+ }
+ Text {
+ color: "white"
+ anchors.centerIn: buttonImage; font.bold: true
+ text: container.text; style: Text.Raised; styleColor: "black"
+ }
+ states: [
+ State {
+ name: "Pressed"
+ when: mouseRegion.pressed == true
+ PropertyChanges { target: pressed; opacity: 1 }
+ }
+ ]
+}
--- /dev/null
+import Qt 4.7
+
+Rectangle {
+ width: 640
+ height: 480
+}
--- /dev/null
+import Qt 4.7
+
+Rectangle {
+ id: confirmationMessage
+ signal okClicked
+ signal cancelClicked
+
+ property alias text: question.text
+
+ border.color: "black";
+ border.width : 4;
+ radius: 10;
+ color: "white"
+ height: 160;
+ width: 160;
+ z: 10;
+ anchors.fill: parent
+
+ Text {
+ id: question
+ text: qsTr("Are you sure?")
+ width: parent.width; height: 80
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ anchors.top: parent.top
+ //anchors.bottom: parent.bottom
+ anchors.margins: 10;
+ //anchors.verticalCenter: parent.verticalCenter
+ }
+
+ Button {
+ id: ok
+ text: qsTr("OK")
+ anchors.left: parent.left; anchors.margins: 5; y: 3; width: 80; height: 60
+ anchors.top: question.bottom
+ //anchors.bottom: parent.bottom
+ onClicked: confirmationMessage.okClicked()
+ }
+
+ Button {
+ id: cancel
+ text: qsTr("Cancel")
+ anchors.right: parent.right; anchors.margins: 5; y: 3; width: 80; height: 60
+ anchors.top: question.bottom
+ //anchors.bottom: parent.bottom
+ anchors.left: ok.right
+ onClicked: confirmationMessage.cancelClicked()
+ }
+
+}
--- /dev/null
+import Qt 4.7
+
+Item {
+// anchors.fill: parent;
+ width: 300; //height: 0;
+ //anchors.top: parent.top; anchors.bottom: parent.bottom
+ y: -parent.height
+
+ function getConfig() {
+ //console.log("XX\n")
+ var doc = new XMLHttpRequest();
+ doc.onreadystatechange = function() {
+ if (doc.readyState == XMLHttpRequest.DONE) {
+ var a = doc.responseXML.documentElement;
+ //for (var ii = 0; ii < a.childNodes.length; ++ii) {
+ // console.log(ii+ " " + a.childNodes[ii].firstChild.nodeValue);
+ //}
+
+ //console.log("node: " + a.childNodes[0].nodeValue)
+ config.hideReadFeeds = a.childNodes[0].firstChild.nodeValue;
+ config.hideReadArticles = a.childNodes[1].firstChild.nodeValue;
+ //console.log("feed " + hideReadFeeds + "\n")
+ //console.log("Articles " + hideReadArticles + "\n")
+// showRequestInfo("Headers -->");
+// showRequestInfo(doc.getAllResponseHeaders ());
+// showRequestInfo("Last modified -->");
+// showRequestInfo(doc.getResponseHeader ("Last-Modified"));
+ }
+ }
+
+ doc.open("GET", "http://localhost:8000/config");
+ doc.send();
+
+ }
+
+ Switch {
+ id: hideReadFeedsSwitch;
+ text: "Hide Read Feeds";
+ value: config.hideReadFeeds
+ onClicked: config.hideReadFeeds = (config.hideReadFeeds == "False") ? "True" : "False"
+ }
+
+ Switch {
+ id: hideReadArticlesSwitch;
+ text: "Hide Read Articles";
+ value: config.hideReadArticles
+ onClicked: config.hideReadArticles = (config.hideReadArticles == "False") ? "True" : "False"
+ anchors.top: hideReadFeedsSwitch.bottom
+ }
+
+ Rectangle {
+ id: closeButton
+ height: 50;
+ gradient: Gradient {
+ GradientStop {
+ position: 0.00;
+ color: "#343434";
+ }
+ GradientStop {
+ position: 1.00;
+ color: "#ffffff";
+ }
+ }
+ radius: 10;
+ width: parent.width
+ anchors.top: hideReadArticlesSwitch.bottom
+
+ MouseArea {
+ id: mouseRegion
+ anchors.fill: closeButton
+ onClicked: { config.isShown = false }
+ }
+ }
+
+// ListView {
+// id: configList; model: configs; delegate: configDelegate; z: 6;
+// cacheBuffer: 100; width: parent.width; height: parent.height;
+// }
+
+// XmlListModel {
+
+// id: configs
+
+// //source: "http://api.flickr.com/services/feeds/photos_public.gne?"+(tags ? "tags="+tags+"&" : "")+"format=rss2"
+// //source: "/home/ymarcoz/feedlist.xml"
+// source: "http://localhost:8000/config"
+// query: "/xml/config"
+// //namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";"
+
+// XmlRole { name: "hideReadFeeds"; query: "hideReadFeeds/string()" }
+// XmlRole { name: "hideReadArticles"; query: "hideReadArticles/string()" }
+// //XmlRole { name: "catid"; query: "catid/string()"; isKey: true }
+
+// }
+
+// Component {
+// id: configDelegate
+
+// Item {
+
+// id: wrapper; width: wrapper.ListView.view.width; height: 86
+// Item {
+// id: moveMe
+// height: parent.height
+// Rectangle { color: "black"; 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: 92; width: wrapper.ListView.view.width - 95; y: 15; spacing: 2
+// Text { text: title; color: "white"; width: parent.width; font.bold: true; elide: Text.ElideRight; style: Text.Raised; styleColor: "black" }
+// //Text { text: feedname; width: parent.width; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
+// }
+// }
+// MouseArea { anchors.fill: wrapper; onClicked: { container.categoryClicked(catid); } }
+// }
+// }
+
+ Component.onCompleted: getConfig();
+}
--- /dev/null
+import Qt 4.7
+
+Item {
+ id: slider; width: 340; height: 48
+
+ // value is read/write.
+ property real value
+ onValueChanged: { handle.x = 2 + (value - minimum) * slider.xMax / (maximum - minimum); }
+ property real maximum: 1
+ property real minimum: 1
+ property int xMax: slider.width - handle.width - 4
+
+ Rectangle {
+ anchors.fill: parent
+ border.color: "white"; border.width: 0; radius: 8
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "#66343434" }
+ GradientStop { position: 1.0; color: "#66000000" }
+ }
+ }
+
+ Rectangle {
+ id: handle; smooth: true
+ x: slider.width / 2 - handle.width / 2; y: 2; width: 30; height: slider.height-4; radius: 6
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "lightgray" }
+ GradientStop { position: 1.0; color: "gray" }
+ }
+
+ MouseArea {
+ anchors.fill: parent; drag.target: parent
+ drag.axis: "XAxis"; drag.minimumX: 2; drag.maximumX: slider.xMax+2
+ onPositionChanged: { value = (maximum - minimum) * (handle.x-2) / slider.xMax + minimum; }
+ }
+ }
+}
--- /dev/null
+import Qt 4.7
+
+Item {
+ id: container
+
+ signal clicked
+
+ property string text
+ property string value
+
+ width: parent.width;
+ height: 86;
+ //anchors.fill: parent;
+
+// BorderImage {
+// id: buttonImage
+// source: "images/toolbutton.sci"
+// width: container.width; height: container.height
+// }
+// BorderImage {
+// id: pressed
+// opacity: 0
+// source: "images/toolbutton.sci"
+// width: container.width; height: container.height
+// }
+
+ Rectangle {
+ id: back
+ width: parent.width;
+ height: 82;
+ color: "#343434";
+ border.width : 4;
+ border.color: "black";
+ radius: 10;
+ }
+
+ Rectangle {
+ id: valueSwitch
+ color: (value=="False") ? "red" : "green";
+ border.width : 4;
+ border.color: "black";
+ radius: 10;
+ height: 40;
+ width: 40;
+ anchors.verticalCenter: back.verticalCenter
+ //anchors.verticalCenter: parent.verticalCenter
+ anchors.margins: 10;
+ anchors.right: back.right;
+ Text {
+ color: "white"
+ anchors.centerIn: valueSwitch; font.bold: true
+ text: (container.value == "False") ? "OFF" : "ON"; style: Text.Raised; styleColor: "black"
+ }
+ }
+
+ MouseArea {
+ id: mouseRegion
+ anchors.fill: back
+ onClicked: { container.clicked(); }
+ }
+ Text {
+ color: "white"
+ /*anchors.centerIn: back;*/ font.bold: true
+ anchors.left: parent.left;
+ anchors.margins: 10
+ anchors.verticalCenter: back.verticalCenter
+ text: container.text; style: Text.Raised; styleColor: "black"
+ }
+// states: [
+// State {
+// name: "Pressed"
+// when: mouseRegion.pressed == true
+// PropertyChanges { target: pressed; opacity: 1 }
+// }
+// ]
+}
--- /dev/null
+import Qt 4.7
+
+Item {
+ id: toolbar
+
+ property alias button1Label: button1.text
+ property alias button2Label: button2.text
+ property alias prevLabel: prevButton.text
+ property alias nextLabel: nextButton.text
+ property alias markAllLabel: markAllButton.text
+ property alias zoomLabel: zoomButton.text
+ property alias taskSwitcherLabel: taskSwitcherButton.text
+ property alias nextVisible: nextButton.visible
+ property alias prevVisible: prevButton.visible
+ property alias markAllVisible: markAllButton.visible
+ property alias zoomVisible: zoomButton.visible
+ signal button1Clicked
+ signal button2Clicked
+ signal prevClicked
+ signal nextClicked
+ signal markAllClicked
+ signal zoomClicked
+ signal taskSwitcherClicked
+
+ //BorderImage { source: "images/titlebar.sci"; width: parent.width; height: parent.height + 14; y: -7 }
+ Rectangle {
+ anchors.fill: parent; color: "#343434";
+ border.color: "black"
+ gradient: Gradient {
+ GradientStop {
+ position: 0.00;
+ color: "#343434";
+ }
+ GradientStop {
+ position: 1.00;
+ color: "#ffffff";
+ }
+ }
+
+ Button {
+ id: taskSwitcherButton
+ anchors.left: parent.left; anchors.leftMargin: 5; y: 3; width: 160; height: 60
+ onClicked: toolbar.taskSwitcherClicked()
+ }
+
+ Button {
+ id: button1
+ anchors.left: taskSwitcherButton.right; anchors.leftMargin: 5; y: 3; width: 160; height: 60
+ onClicked: toolbar.button1Clicked()
+ }
+
+ Button {
+ id: button2
+ anchors.right: parent.right; anchors.rightMargin: 5; y: 3; width: 160; height: 60
+ onClicked: toolbar.button2Clicked()
+ }
+
+ Button {
+ id: markAllButton
+ visible: false
+ anchors.left: button1.right; anchors.rightMargin: 5; y: 3; width: 240; height: 60
+ onClicked: toolbar.markAllClicked()
+ }
+
+ Button {
+ id: prevButton
+ visible: false
+ anchors.left: button1.right; anchors.rightMargin: 5; y: 3; width: 120; height: 60
+ onClicked: toolbar.prevClicked()
+ }
+
+ Button {
+ id: nextButton
+ visible: false
+ anchors.right: button2.left; anchors.rightMargin: 5; y: 3; width: 120; height: 60
+ onClicked: toolbar.nextClicked()
+ }
+
+ Button {
+ id: zoomButton
+ visible: false
+ anchors.right: nextButton.left; anchors.rightMargin: 5; y: 3; width: 80; height: 60
+ onClicked: toolbar.zoomClicked()
+ }
+ }
+}
--- /dev/null
+border.left: 15
+border.top: 4
+border.bottom: 4
+border.right: 15
+source: toolbutton.png
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="en_CA">
+<context>
+ <name>FeedingItUI2</name>
+ <message>
+ <location filename="../FeedingItUI2.qml" line="53"/>
+ <source>Back</source>
+ <translation type="unfinished">Back 2</translation>
+ </message>
+</context>
+</TS>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="en_CA">
+<context>
+ <name>FeedingItUI2</name>
+ <message>
+ <location filename="../FeedingItUI2.qml" line="75"/>
+ <source>Back</source>
+ <translation>Back 2</translation>
+ </message>
+ <message>
+ <location filename="../FeedingItUI2.qml" line="75"/>
+ <source>Config</source>
+ <translation>Config</translation>
+ </message>
+</context>
+<context>
+ <name>Feeds</name>
+ <message>
+ <source>unreadItems</source>
+ <translation type="obsolete"> %1 unread items</translation>
+ </message>
+ <message>
+ <location filename="../Feeds.qml" line="55"/>
+ <source>%1 unread items</source>
+ <translation>%1 unread items</translation>
+ </message>
+</context>
+</TS>
--- /dev/null
+import Qt 4.7
+
+Item {
+ id: screen; width: 800; height: 480;
+// property bool inListView : false;
+ Rectangle {
+ id: background
+ anchors.fill: parent; color: "#343434";
+
+ Text {
+ text: "Hello World"
+ anchors.centerIn: parent
+ MouseArea {
+ id: mouseRegion
+ anchors.fill: parent
+ onClicked: { screen.inListView = true; }
+ }
+ }
+ }
+// states: State {
+// name: "ListView"; when: screen.inListView == true
+// PropertyChanges { target: feedList; x: 0 }
+// //PropertyChanges { target: photoGridView; x: -(parent.width * 1.5) }
+// }
+
+ transitions: Transition {
+ NumberAnimation { properties: "x"; duration: 500; easing.type: "InOutQuad" }
+ }
+
+ ListView {
+ id: categoryList; model: categories; delegate: categoryDelegate; z: 6
+ property string shownCategory : ""
+ /*height: parent.height;*/ x: 0 /*-(parent.width * 1.5)*/; cacheBuffer: 100; width: parent.width;
+// states: State {
+// name: "showOneCategory"; when: categoryList.shownCategory != ""
+// PropertyChanges { target: categories; query: "/xml/category[catid=[\"" + categoryList.shownCategory + "\"]" }
+// }
+ }
+
+ ListView {
+ id: feedList; model: feeds; delegate: feedDelegate; z: 6
+ width: parent.width; height: parent.height; x: parent.width;
+ cacheBuffer: 100;
+// opacity: 0;
+ //anchors.top: categoryList.bottom
+ }
+
+ XmlListModel {
+
+ id: categories
+
+ //source: "http://api.flickr.com/services/feeds/photos_public.gne?"+(tags ? "tags="+tags+"&" : "")+"format=rss2"
+ source: "/home/ymarcoz/feedlist.xml"
+ query: "/xml/category"
+ //namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";"
+
+ XmlRole { name: "title"; query: "catname/string()" }
+ XmlRole { name: "catid"; query: "catid/string()"; isKey: true }
+
+ }
+
+ XmlListModel {
+ property string catid : ""
+ id: feeds
+
+ //source: "http://api.flickr.com/services/feeds/photos_public.gne?"+(tags ? "tags="+tags+"&" : "")+"format=rss2"
+ source: "/home/ymarcoz/feedlist.xml"
+ query: "/xml/category/feed"
+ //namespaceDeclarations: "declare namespace media=\"http://search.yahoo.com/mrss/\";"
+
+ XmlRole { name: "title"; query: "feedname/string()" }
+ XmlRole { name: "feedid"; query: "feedid/string()" }
+ }
+
+ Component {
+ id: categoryDelegate
+
+ Item {
+
+ function categoryClicked() {
+// if (categoryList.shownCategory == catid)
+// {
+ categoryList.shownCategory = ""
+// categories.query="/xml/category"
+// feedList.opacity = 0;
+// } else {
+// categoryList.shownCategory = catid;
+// categories.query="/xml/category[catid=\"" + catid + "\"]";
+ feeds.query = "/xml/category[catid=\"" + catid +"\"]/feed"
+ feedList.x = 0
+ //feeds.reload()
+// feedList.opacity = 100
+// }
+
+ //feedList.model = feeds;
+ }
+ id: wrapper; width: wrapper.ListView.view.width; height: 86
+ Item {
+ id: moveMe
+ height: parent.height
+ Rectangle { color: "black"; 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: 92; width: wrapper.ListView.view.width - 95; y: 15; spacing: 2
+ Text { text: title; color: "white"; width: parent.width; font.bold: true; elide: Text.ElideRight; style: Text.Raised; styleColor: "black" }
+ //Text { text: feedname; width: parent.width; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
+ }
+ }
+ MouseArea { anchors.fill: wrapper; onClicked: { categoryClicked() } }
+
+ // Animate adding and removing of items:
+
+// ListView.onAdd: SequentialAnimation {
+// PropertyAction { target: wrapper; property: "height"; value: 0 }
+// NumberAnimation { target: wrapper; property: "height"; to: 86; duration: 250; easing.type: Easing.InOutQuad }
+// }
+
+// ListView.onRemove: SequentialAnimation {
+// PropertyAction { target: wrapper; property: "ListView.delayRemove"; value: true }
+// NumberAnimation { target: wrapper; property: "height"; to: 0; duration: 250; easing.type: Easing.InOutQuad }
+
+// // Make sure delayRemove is set back to false so that the item can be destroyed
+// PropertyAction { target: wrapper; property: "ListView.delayRemove"; value: false }
+// }
+
+ }
+
+ }
+
+ Component {
+ id: feedDelegate
+
+ Item {
+
+ function feedClicked() {
+ //feeds.query = "/xml/category[catid=\"" + catid +"\"]/feed"
+ //feeds.reload()
+ //feedList.model = feeds;
+ }
+ id: wrapper; width: wrapper.ListView.view.width; height: 86
+ Item {
+ id: moveMe
+ Rectangle { color: "black"; opacity: index % 2 ? 0.2 : 0.4; height: 84; width: wrapper.width; y: 1 }
+ Rectangle {
+ x: 6; y: 4; width: 77; height: 77; color: "#ff0000"; smooth: true
+
+ }
+ Column {
+ x: 92; width: wrapper.ListView.view.width - 95; y: 15; spacing: 2
+ Text { text: title; color: "white"; width: parent.width; font.bold: true; elide: Text.ElideRight; style: Text.Raised; styleColor: "black" }
+ //Text { text: feedname; width: parent.width; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
+ }
+ }
+ MouseArea { anchors.fill: wrapper; onClicked: { feedClicked() } }
+ }
+
+ }
+
+}
entry["author"]
except:
entry["author"] = None
+ if(not(entry.has_key("id"))):
+ entry["id"] = None
tmpEntry = {"title":entry["title"], "content":self.extractContent(entry),
- "date":date, "link":entry["link"], "author":entry["author"]}
+ "date":date, "link":entry["link"], "author":entry["author"], "id":entry["id"]}
id = self.generateUniqueId(tmpEntry)
#articleTime = time.mktime(self.entries[id]["dateTuple"])
return self.db.execute("SELECT date FROM feed WHERE id=?;", (id,) ).fetchone()[0]
def generateUniqueId(self, entry):
- return getId(str(entry["date"]) + str(entry["title"]))
+ if(entry["id"] != None):
+ return getId(str(entry["id"]))
+ else:
+ return getId(str(entry["date"]) + str(entry["title"]))
def getIds(self, onlyUnread=False):
if onlyUnread:
text += "<html><head><title>" + title + "</title>"
text += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>\n'
#text += '<style> body {-webkit-user-select: none;} </style>'
- text += '</head><body><div><a href=\"' + link + '\">' + title + "</a>"
+ text += '</head><body background=\"white\"><div><a href=\"' + link + '\">' + title + "</a>"
if author != None:
text += "<BR /><small><i>Author: " + author + "</i></small>"
text += "<BR /><small><i>Date: " + date + "</i></small></div>"
return keys
def getCategoryTitle(self, id):
- print id
row = self.db.execute("SELECT title FROM categories WHERE id=?;", (id, )).fetchone()
return row[0]