#cp feedingit_status.desktop /usr/share/applications/hildon-status-menu/
nice python2.5 update_feeds.py
;;
-qml)
+noqml)
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
+ python2.5 FeedingIt.py
;;
*)
cd /opt/FeedingIt
- python2.5 FeedingIt.py
+ python2.5 FeedingIt-Web.py 2>&1 >/dev/null &
+ pid=`pidof python2.5 FeedingIt-Web.py`
+ sleep 1
+ qmlviewer -opengl -fullscreen qml/FeedingIt.qml
+ kill $pid
;;
+
esac
\ No newline at end of file
from cgi import escape
from re import sub
from htmlentitydefs import name2codepoint
+from gconf import client_get_default
+from urllib2 import ProxyHandler
+from threading import Thread
+from os.path import isfile, isdir, exists
+from os import mkdir, remove, stat
CONFIGDIR = "/home/user/.feedingit/"
+updatingFeeds = []
+#commands = [("addFeed","httpwww"), ("openFeed", "xxxx"), ("openArticle", ("feedid","artid"))]
+commands = [("openFeed", "1,", "61ac1458d761423344998dc76770e36e")]
+
def unescape(text):
def fixup(m):
text = m.group(0)
return text # leave as is
return sub("&#?\w+;", fixup, text)
-class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
+def sanitize(text):
+ from cgi import escape
+ return escape(text).encode('ascii', 'xmlcharrefreplace')
+
+def start_server():
+ global listing
+ listing = Listing(CONFIGDIR)
+ httpd = BaseHTTPServer.HTTPServer(("127.0.0.1", PORT), Handler)
+ httpd.serve_forever()
+
+class App():
+ def addFeed(self, url):
+ commands.append(("addFeed",url))
+
+ def getStatus(self):
+ pass
+
+ def openFeed(self, key):
+ cat = listing.getFeedCategory(key)
+ commands.append( ("openFeed", cat, key) )
+
+ def OpenArticle(self, key, id):
+ cat = listing.getFeedCategory(key)
+ commands.append( ("openArticle", (cat, key, id)) )
+class Download(Thread):
+ def __init__(self, listing, keys):
+ Thread.__init__(self)
+ self.listing = listing
+ self.keys = keys
+
+ def run (self):
+ for key in self.keys:
+ print "Start update: %s" % key
+ updatingFeeds.append(key)
+ (use_proxy, proxy) = config.getProxy()
+ try:
+ if use_proxy:
+ self.listing.updateFeed(key, proxy=proxy, imageCache=config.getImageCache() )
+ else:
+ self.listing.updateFeed(key, imageCache=config.getImageCache() )
+ except:
+ print "Error updating feed: %s" %key
+ updatingFeeds.remove(key)
+ print "End update: %s" % key
+
+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 updateAll(self):
+ import subprocess
+ subprocess.Popen("FeedingIt update", shell=True)
+
+ def getCommands(self):
+
+ commandXml = "<commands>"
+ for item in commands:
+ if item[0]=="addFeed":
+ commandXml += "<command c='addFeed'>%s</command>" %(sanitize(item[1]))
+ if item[0]=="openFeed":
+ commandXml += "<command c='openFeed' cat='%s'>%s</command>" % (sanitize(item[1]), sanitize(item[2]) )
+ if item[0]=="openArticle":
+ commandXml += "<command c='openArticle' cat='%s' key='%s'>%s</command>" %(sanitize(item[1], sanitize(item[2][0]), sanitize(item[2][1])) )
+ commands.remove(item)
+ commandXml += "</commands>"
+ return commandXml
def getConfigXml(self):
xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><xml>"
xml += "<unread>%s</unread>" %listing.getFeedNumberOfUnreadItems(key)
xml += "<updatedDate>%s</updatedDate>" %listing.getFeedUpdateTime(key)
xml += "<icon>%s</icon>" %listing.getFavicon(key)
+ if key in updatingFeeds:
+ xml += "<updating>True</updating>"
+ else:
+ xml += "<updating>False</updating>"
xml += "</feed>"
xml += "</xml>"
return xml
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":
feed = listing.getFeed(key)
try:
file = open(feed.getContentLink(article))
- #feed.setEntryRead(article)
html = file.read().replace("body", "body bgcolor='#ffffff'", 1)
file.close()
except:
self.wfile.write(html)
#listing.updateUnread(key)
return
+ elif request[1] == "isUpdating":
+ xml = "<xml>"
+ key = request[2]
+ if (key in updatingFeeds) or ((key=="") and (len(updatingFeeds)>0)):
+ xml += "<updating>True</updating>"
+ else:
+ xml += "<updating>False</updating>"
+ xml += self.getCommands()
+ xml += "</xml>"
elif request[1] == "read":
key = request[2]
article = request[3]
elif request[1] == "task":
self.openTaskSwitch()
xml = "<xml>OK</xml>"
+ elif request[1] == "deleteCat":
+ key = request[2]
+ listing.removeCategory(key)
+ xml = "<xml>OK</xml>"
+ elif request[1] == "deleteFeed":
+ key = request[3]
+ listing.removeFeed(key)
+ xml = "<xml>OK</xml>"
+ elif request[1] == "addFeed":
+ cat = request[2]
+ name = request[3]
+ url = arguments.get("url","")
+ listing.addFeed(name, url, category=cat)
+ xml = "<xml>OK</xml>"
+ elif request[1] == "updateFeed":
+ key = request[2]
+ download = Download(listing, [key,])
+ download.start()
+ xml = "<xml>OK</xml>"
+ elif request[1]=="updateAll":
+ feeds = []
+ for cat in listing.getListOfCategories():
+ for feed in listing.getSortedListOfKeys("Manual", category=cat):
+ feeds.append(feed)
+ print feeds
+ download = Download(listing, feeds)
+ download.start()
+ xml = "<xml>OK</xml>"
+ elif request[1] == "addCat":
+ catName = request[2]
+ listing.addCategory(catName)
+ xml = "<xml>OK</xml>"
else:
self.send_error(404, "File not found")
return
PORT = 8000
-listing = Listing(CONFIGDIR)
+if not isdir(CONFIGDIR):
+ try:
+ mkdir(CONFIGDIR)
+ except:
+ print "Error: Can't create configuration directory"
+ from sys import exit
+ exit(1)
+
+from config import Config
+config = Config(None,CONFIGDIR+"config.ini")
+
+import thread
+
+#print "serving at port", PORT
+thread.start_new_thread(start_server, ())
+
+from feedingitdbus import ServerObject
+#from updatedbus import UpdateServerObject, get_lock
+import gobject
+gobject.threads_init()
+import dbus.mainloop.glib
+dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
-httpd = BaseHTTPServer.HTTPServer(("127.0.0.1", PORT), Handler)
-print "serving at port", PORT
-httpd.serve_forever()
+mainloop = gobject.MainLoop()
+mainloop.run()
# Version : 0.6.1
# Description : Simple RSS Reader
# ============================================================================
+try:
+ import gtk
+ import hildon
+ from gobject import idle_add
+except:
+ pass
-import gtk
-import hildon
from ConfigParser import RawConfigParser
-from gobject import idle_add
from gconf import client_get_default
from urllib2 import ProxyHandler
}
}
+ function markAllAsRead() {
+ if (feedid!="") {
+ var doc = new XMLHttpRequest();
+ //console.log(articlesItem.url+"&markAllAsRead=True")
+ var url = "http://localhost:8000/articles/" + feedid + "?markAllAsRead=True"
+ console.log(url)
+ doc.open("GET", url);
+ doc.send();
+ articles.reload();
+ }
+ }
+
+ function viewArticle(articleid) {
+ var index = 0;
+ for (var i=0; i<articleList.count; ++i) {
+ if (articles.get(0).articleid==articleid) {
+ index = i;
+ }
+ }
+ articleView.positionViewAtIndex(index, ListView.Contain); articleView.visible = true;
+ }
+
ListView {
id: articleList; model: visualModel.parts.list; z: 6
width: parent.width; height: parent.height; /*x: 0;*/
highlightMoveDuration: 300;
}
+ Rectangle {
+ id: noArticle
+ width: parent.width; height: parent.height;
+ visible: false;
+ z:8;
+ Text { text: qsTr("No articles available"); }
+ states: State {
+ name: "noArticle"; when: articles.count==0
+ PropertyChanges { target: noArticle; visible: true; }
+ }
+ }
+
VisualDataModel {
id: visualModel;
delegate: Package {
// anchors.fill: parent;
width: parent.width; height: parent.height;
//anchors.top: parent.top; anchors.bottom: parent.bottom
+ property bool inEditMode: true
+
+ function reload() {
+ categories.reload();
+ }
ListView {
id: categoryList; model: categories; delegate: categoryDelegate; z: 6;
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 {
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" }
}
+ 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 { anchors.fill: wrapper; onClicked: { container.categoryClicked(catid); } }
+ MouseArea { enabled: !inEditMode; anchors.fill: wrapper; onClicked: { container.categoryClicked(catid); } }
}
}
}
/*anchors.fill: parent;*/ color: "#343434";
anchors.centerIn: parent
transformOrigin: Item.Center
+ property bool editMode: false
function categoryClicked(catid) {
feedsItem.catid = catid;
feedsItem.visible = true;
}
- function feedClicked(feedid) {
+ function feedClicked(feedid, updating) {
flipper.feedid = feedid;
+ toolBar.feedUpdating = updating;
flipper.visible = true;
}
}
if (flipper.visible) {
feedsItem.reload();
+ toolBar.feedUpdating = false;
flipper.visible = false;
flipper.feedid = "";
return;
}
}
+ function categoryDeleted(catid) {
+ confirmationMessage.catid=catid;
+ confirmationMessage.state="deleteCat";
+ }
+
+ function feedDeleted(catid, feedid) {
+ confirmationMessage.catid=catid;
+ confirmationMessage.feedid=feedid;
+ confirmationMessage.state="deleteFeed";
+ }
+
+ function addCategory(categoryName) {
+ var doc = new XMLHttpRequest();
+ var url = "http://localhost:8000/addCat/"+categoryName
+ doc.open("GET", url);
+ doc.send();
+ categoriesItem.reload();
+ addCat.visible=false;
+ }
+
+ function addFeed(catid, feedName, feedURL) {
+ var doc = new XMLHttpRequest();
+ var url = "http://localhost:8000/addFeed/"+catid + "/" + feedName + "?url=" + feedURL
+ doc.open("GET", url);
+ doc.send();
+ feedsItem.reload();
+ console.log(addFeedDialog.visible)
+ addFeedDialog.visible=false;
+ console.log(addFeedDialog.visible)
+ }
+
+ function updateClicked(feedid) {
+ var doc = new XMLHttpRequest();
+ var url = "http://localhost:8000/updateFeed/" + feedid
+ doc.open("GET", url);
+ doc.send();
+ }
+
+ function updateAllClicked() {
+ var doc = new XMLHttpRequest();
+ var url = "http://localhost:8000/updateAll"
+ doc.open("GET", url);
+ doc.send();
+ }
+
Common.Menu {
id: config
z: 5
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
+ property string catid: "";
+ property string feedid: "";
+
+ function action() {
+ if (state=="markAll") {
+ flipper.markAllAsRead();
+ state="hidden"
+ feedsItem.reload()
+ return;
+ }
+ if (state=="deleteCat") {
+ var doc = new XMLHttpRequest();
+ var url = "http://localhost:8000/deleteCat/"+catid
+ doc.open("GET", url);
+ doc.send();
+ categoriesItem.reload();
+ state="hidden";
+ return;
+ }
+ if (state=="deleteFeed") {
+ var doc = new XMLHttpRequest();
+ var url = "http://localhost:8000/deleteFeed/"+catid+"/"+feedid
+ doc.open("GET", url);
+ doc.send();
+ feedsItem.reload();
+ state="hidden";
+ return;
+ }
}
+ visible: false
+ onOkClicked: action()
onCancelClicked: visible=false
+ state: "hidden"
+ states: [ State {name: "markAll";
+ PropertyChanges { target: confirmationMessage; text: qsTr("Do you want to mark all items as read?") }
+ PropertyChanges { target: confirmationMessage; visible: true; }
+
+ }, State {name: "deleteCat";
+ PropertyChanges { target: confirmationMessage; text: qsTr("Do you want to delete this category?") }
+ PropertyChanges { target: confirmationMessage; visible: true; }
+ }, State {name: "deleteFeed";
+ PropertyChanges { target: confirmationMessage; text: qsTr("Do you want to delete this feed and all its articles?") }
+ PropertyChanges { target: confirmationMessage; visible: true; }
+ }, State {name: "hidden";
+ PropertyChanges { target: confirmationMessage; visible: false; }
+ }
+ ]
+
}
Common.ToolBar {
onPrevClicked: flipper.prev();
onNextClicked: flipper.next();
onMarkAllClicked: {
- confirmationMessage.text = qsTr("Do you want to mark all items as read?");
- confirmationMessage.visible = true;
+ confirmationMessage.state = "markAll";
}
onZoomClicked: { flipper.zoomEnabled = !flipper.zoomEnabled; }
onTaskSwitcherClicked: {
var url = "http://localhost:8000/task"
doc.open("GET", url);
doc.send();
- //var xmlDoc=doc.responseXML;
}
- //onRotateClicked: { container.rotation=-90; container.width=screen.height; container.height=screen.width; }
+ onAddClicked: {
+ if (feedsItem.visible) {
+ addFeedDialog.feedName="";
+ addFeedDialog.catid = feedsItem.catid;
+ addFeedDialog.visible = true;
+ return;
+ }
+ if (categoriesItem.visible) {
+ addCat.catName="";
+ addCat.visible=true;
+ return;
+ }
+ }
+ onUpdateClicked: {
+ if (flipper.visible) {
+ toolBar.feedUpdating = true
+ container.updateClicked(flipper.feedid);
+ } else {
+ container.updateAllClicked();
+ }
+ }
states: [ State {
name: "navButtons"; when: flipper.articleShown
PropertyChanges { target: toolBar; nextVisible: !container.inPortrait; }
PropertyChanges { target: toolBar; prevVisible: !container.inPortrait; }
PropertyChanges { target: toolBar; zoomVisible: true; }
+ PropertyChanges { target: toolBar; addVisible: false; }
},
State {
name: "feedButtons"; when: (flipper.visible)&&(!flipper.articleShown)
PropertyChanges { target: toolBar; markAllVisible: true; }
+ PropertyChanges { target: toolBar; addVisible: false; }
+ PropertyChanges { target: toolBar; updateVisible: true; }
},
State {
name: "quitButton"; when: (!feedsItem.visible)
PropertyChanges { target: toolBar; quitVisible: true;}
PropertyChanges { target: toolBar; backVisible: false; }
+ PropertyChanges { target: toolBar; updateVisible: true; }
+ //PropertyChanges { target: toolBar; addVisible: true; }
}
]
}
anchors.top: toolBar.bottom; anchors.bottom: parent.bottom
y: toolBar.height;
+ Common.AddCat {
+ visible: false;
+ id: addCat
+ width: parent.width;
+ height: parent.height;
+ z: 10;
+ }
+
+ Common.AddFeed {
+ visible: false;
+ id: addFeedDialog
+ width: parent.width;
+ height: parent.height;
+ z: 10;
+ }
+
+ Timer {
+ function checkUpdates() {
+ if (categoriesItem.visible && !feedsItem.visible) {
+ var doc = new XMLHttpRequest();
+ var url = "http://localhost:8000/isUpdating/"
+ doc.onreadystatechange = function() {
+ if (doc.readyState == XMLHttpRequest.DONE) {
+ var xmlDoc = doc.responseXML.documentElement;
+ //var els = xmlDoc.getElementsByTagName("updating");
+ var isUpdating = xmlDoc.firstChild.firstChild.nodeValue;
+
+ console.log(isUpdating);
+ if (isUpdating=="True") {
+ toolBar.feedUpdating = true;
+ } else {
+ if (toolBar.feedUpdating) {
+ // We changed from updating to not updating, so we reload the listing
+ toolBar.feedUpdating = false;
+ categoriesItem.reload();
+ }
+ }
+ var commands = xmlDoc.lastChild.childNodes;
+ for (var ii = 0; ii < commands.length; ++ii) {
+ // process the commands
+ var command = commands[ii].attributes[0].value; //("c")
+ console.log(command)
+ if (command=="openFeed") {
+ // Open feed feed
+ var catid = commands[ii].attributes[1].value;
+ var feedid = commands[ii].firstChild.nodeValue;
+ if (!flipper.visible) {
+ container.categoryClicked(catid);
+ container.feedClicked(feedid,false);
+ console.log("feedid: " + feedid);
+ }
+ }
+ if (command=="openArticle") {
+ // Open feed and article
+ var feedid = commands[ii].attributes[2].value; //("key");
+ var articleid = commands[ii].firstChild.nodeValue;
+ if (!flipper.visible) {
+ container.categoryClicked(catid);
+ container.feedClicked(feedid,false);
+ container.articleClicked(articleid, index)
+ console.log("art: "+feedid+"/"+articleid);
+ }
+ }
+ if (command=="addFeed") {
+ // Open the addFeed dialog
+ var url = commands[ii].firstChild.nodeValue;
+ console.log("add: "+url)
+ }
+ }
+
+ }
+ }
+ doc.open("GET", url);
+ doc.send();
+ //categoriesItem.reload()
+ }
+ if (feedsItem.visible && !flipper.visible) {
+ //feedsItem.reload()
+ }
+ if (flipper.visible) {
+ var doc = new XMLHttpRequest();
+ var url = "http://localhost:8000/isUpdating/" + flipper.feedid
+ doc.onreadystatechange = function() {
+ if (doc.readyState == XMLHttpRequest.DONE) {
+ var a = doc.responseXML.documentElement;
+ console.log(a.firstChild.nodeValue);
+ if (a.firstChild.nodeValue=="True") {
+ toolBar.feedUpdating = true;
+ } else {
+ if (toolBar.feedUpdating) {
+ // We changed from updating to not updating, so we reload the listing
+ toolBar.feedUpdating = false;
+ flipper.reload();
+ }
+ }
+ }
+ }
+ doc.open("GET", url);
+ doc.send();
+
+ //flipper.reload()
+ }
+ }
+ interval: 2000; running: true; repeat: true
+ onTriggered: checkUpdates();
+ }
+
Categories {
// Loads the categoryList view and delegate
id: categoriesItem
property bool isShown: true;
+ inEditMode: container.editMode;
states: State {
name: "shown"; when: categoriesItem.isShown == false
id: feedsItem;
property string hideReadFeeds: config.hideReadFeeds
visible: false;
+ inEditMode: container.editMode;
states: [
State { name: "articlesShown"; when: flipper.visible; PropertyChanges { target: feedsItem; x: -parent.width } },
//anchors.fill: parent;
width: parent.width;
property string catid : ""
+ property bool inEditMode: true
x: parent.width; height: parent.height;
anchors.top: parent.top; anchors.bottom: parent.bottom
XmlRole { name: "unread"; query: "unread/string()"; isKey: true }
XmlRole { name: "updatedDate"; query: "updatedDate/string()" }
XmlRole { name: "icon"; query: "icon/string()" }
+ XmlRole { name: "updating"; query: "updating/string()"; isKey: true }
}
Component {
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 }
+ 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
+ }
+ }
}
Column {
//Text { text: feedname; width: parent.width; elide: Text.ElideLeft; color: "#cccccc"; style: Text.Raised; styleColor: "black" }
}
}
- MouseArea { anchors.fill: wrapper; onClicked: { container.feedClicked(feedid) } }
+ MouseArea { anchors.fill: wrapper; onClicked: { container.feedClicked(feedid, updating=="True") } }
}
}
--- /dev/null
+import Qt 4.7
+
+Rectangle {
+ id: addCat;
+ width: 200 //parent.width
+ height: 172
+ color: "white"
+ property alias catName: categoryName.text
+ MouseArea { anchors.fill: parent; onClicked: {} }
+ Column {
+ Row {
+ width: addCat.width
+ height: 86;
+ Text { anchors.verticalCenter: parent.verticalCenter; text: qsTr("Category name:") }
+ LineInput{
+ id: categoryName
+ anchors.centerIn: parent
+ width: 140
+ focus: true
+ }
+ }
+ Row {
+ width: addCat.width
+ Button {
+ id: ok
+ text: qsTr("OK")
+ anchors.margins: 5; y: 3; width: 80; height: 60
+ onClicked: container.addCategory(categoryName.text)
+ }
+
+ Button {
+ id: cancel
+ text: qsTr("Cancel")
+ anchors.margins: 5; y: 3; width: 80; height: 60
+ onClicked: addCat.visible=false;
+ }
+ }
+ }
+
+}
--- /dev/null
+import Qt 4.7
+
+Rectangle {
+ id: addFeed;
+ width: 500 //parent.width
+ height: 172
+ color: "white"
+ property alias feedName: feedName.text
+ property string catid
+ MouseArea { anchors.fill: parent; onClicked: {} }
+ Column {
+ Row {
+ width: addFeed.width
+ height: 86;
+ Text { anchors.verticalCenter: parent.verticalCenter; text: qsTr("Feed name:") }
+ LineInput{
+ id: feedName
+ anchors.centerIn: parent
+ width: 140
+ focus: true
+ }
+ }
+ Row {
+ width: addFeed.width
+ height: 86;
+ Text { anchors.verticalCenter: parent.verticalCenter; text: qsTr("Feed URL:") }
+ LineInput{
+ id: feedURL
+ anchors.centerIn: parent
+ width: 140
+ focus: true
+ text: "http://"
+ }
+ }
+ Row {
+ width: addFeed.width
+ Button {
+ id: ok
+ text: qsTr("OK")
+ anchors.margins: 5; y: 3; width: 80; height: 60
+ onClicked: container.addFeed(catid, feedName.text, feedURL.text)
+ }
+ Button {
+ id: cancel
+ text: qsTr("Cancel")
+ anchors.margins: 5; y: 3; width: 80; height: 60
+ onClicked: addFeed.visible=false;
+ }
+ }
+ }
+}
property string imageSource: ""
property int imageRotation: 0
+ property alias iconRotation: icon.rotation
+
BorderImage {
id: buttonImage
source: "images/toolbutton.sci"
//visible: (container.imageSource=="")
}
Image {
+ id: icon
source: container.imageSource
rotation: container.imageRotation
//fillMode: Image.PreserveAspectFit
+++ /dev/null
-import Qt 4.7
-
-Rectangle {
- width: 640
- height: 480
-}
--- /dev/null
+import Qt 4.7
+
+FocusScope {
+ property alias text: input.text
+ property alias maximumLength: input.maximumLength
+ //anchors.centerIn: parent
+ width: 180; height: 28
+ BorderImage {
+ source: "images/lineedit.sci"
+ anchors.fill: parent
+ }
+ TextInput {
+ id: input
+ color: "#151515"; selectionColor: "green"
+ font.pixelSize: 16; font.bold: true
+ width: parent.width-16
+ anchors.centerIn: parent
+ focus: true
+ }
+}
--- /dev/null
+import Qt 4.7
+
+Rectangle {
+ width: 640
+ height: 480
+
+ ListView {
+ id: categoryList; model: categories; delegate: categoryDelegate; z: 6;
+ cacheBuffer: 100; width: parent.width; height: parent.height;
+ }
+
+
+
+}
anchors.top: hideReadArticlesSwitch.bottom
}
+ Switch {
+ id: editMode;
+ text: qsTr("Enter Edit Mode");
+ value: container.editMode ? "True" : "False"
+ onClicked: { container.editMode=!container.editMode; }
+ anchors.top: lockRotation.bottom
+ }
+
Rectangle {
id: closeButton
height: 50;
}
radius: 10;
width: parent.width
- anchors.top: lockRotation.bottom
+ anchors.top: editMode.bottom
MouseArea {
id: mouseRegion
property alias markAllVisible: markAllButton.visible
property alias zoomVisible: zoomButton.visible
property alias quitVisible: quitButton.visible
+ property alias addVisible: addButton.visible
+ property alias updateVisible: updateFeedButton.visible
+
+ property bool feedUpdating: false
signal menuClicked
signal backClicked
signal markAllClicked
signal zoomClicked
signal taskSwitcherClicked
+ signal addClicked
+ signal updateClicked
//signal rotateClicked
//BorderImage { source: "images/titlebar.sci"; width: parent.width; height: parent.height + 14; y: -7 }
}
}
- Button {
- id: taskSwitcherButton
- anchors.left: parent.left; anchors.leftMargin: 5; y: 3; width: 116; height: 60
- onClicked: toolbar.taskSwitcherClicked()
- imageSource: "images/wmTaskLauncherIcon.png"
- }
+ Row {
+ anchors.fill: parent
+ Button {
+ id: taskSwitcherButton
+ /*anchors.left: parent.left;*/ anchors.leftMargin: 5; y: 3; width: 116; height: 60
+ onClicked: toolbar.taskSwitcherClicked()
+ imageSource: "images/wmTaskLauncherIcon.png"
+ }
- Button {
- id: menuButton
- anchors.left: taskSwitcherButton.right; anchors.leftMargin: 5; y: 3; width: 60; height: 60
- onClicked: toolbar.menuClicked()
- imageSource: "images/wmEditIcon.png"
- }
+ Button {
+ id: menuButton
+ /*anchors.left: taskSwitcherButton.right;*/ anchors.leftMargin: 5; y: 3; width: 60; height: 60
+ onClicked: toolbar.menuClicked()
+ imageSource: "images/wmEditIcon.png"
+ }
- Button {
- id: backButton
- anchors.right: parent.right; anchors.rightMargin: 5; y: 3; width: 116; height: 60
- onClicked: toolbar.backClicked()
- imageSource: "images/wmBackIcon.png"
- }
+ Button {
+ id: addButton
+ visible: true; /*anchors.left: menuButton.right;*/
+ anchors.rightMargin: 5; y: 3; width: 60; height: 60
+ onClicked: toolbar.addClicked()
+ imageSource: "images/plus.png"
- Button {
- id: markAllButton
- visible: false
- anchors.left: menuButton.right; anchors.rightMargin: 5; y: 3; width: 60; height: 60
- onClicked: toolbar.markAllClicked()
- imageSource: "images/checkmark.png"
- }
+ }
- Button {
- id: prevButton
- visible: false
- anchors.left: menuButton.right; anchors.rightMargin: 5; y: 3; width: 120; height: 60
- onClicked: toolbar.prevClicked()
- imageSource: "images/InputMethodShiftButtonNormal.png"
- imageRotation: -90;
- }
+ Button {
+ id: updateFeedButton
+ visible: false; /*anchors.left: menuButton.right;*/
+ anchors.rightMargin: 5; y: 3; width: 60; height: 60
+ onClicked: toolbar.updateClicked()
+ //imageSource: (!feedUpdating) ? "images/rotate.png" : "images/loading.png"
+ NumberAnimation on iconRotation {
+ from: 0; to: 360; running: (visible == true) && (feedUpdating); loops: Animation.Infinite; duration: 900
+ }
+ state: "update"
+ states : [State {name: "loading"; when: (feedUpdating);
+ PropertyChanges {target: updateFeedButton; imageSource: "images/loading.png" }
+ }, State { name: "update"; when: (!feedUpdating);
+ PropertyChanges {target: updateFeedButton; iconRotation: 0}
+ PropertyChanges {target: updateFeedButton; imageSource: "images/rotate.png"}
+ }
+ ]
+ }
- Button {
- id: nextButton
- visible: false
- anchors.right: zoomButton.left; anchors.rightMargin: 5; y: 3; width: 120; height: 60
- onClicked: toolbar.nextClicked()
- imageSource: "images/InputMethodShiftButtonNormal.png"
- imageRotation: 90
- }
+ Button {
+ id: markAllButton
+ visible: false
+ /*anchors.left: updateFeedButton.right;*/ anchors.rightMargin: 5; y: 3; width: 60; height: 60
+ onClicked: toolbar.markAllClicked()
+ imageSource: "images/checkmark.png"
+ }
- Button {
- id: zoomButton
- visible: false
- anchors.right: backButton.left; anchors.rightMargin: 5; y: 3; width: 80; height: 60
- onClicked: toolbar.zoomClicked()
- imageSource: "images/Zoom-In-icon.png"
- }
+ Button {
+ id: prevButton
+ visible: false
+ /*anchors.left: menuButton.right;*/ anchors.rightMargin: 5; y: 3; width: 120; height: 60
+ onClicked: toolbar.prevClicked()
+ imageSource: "images/InputMethodShiftButtonNormal.png"
+ imageRotation: -90;
+ }
- Button {
- id: quitButton
- visible: false
- anchors.right: parent.right; anchors.rightMargin: 5; y: 3; width: 116; height: 60
- onClicked: toolbar.backClicked()
- imageSource: "images/wmCloseIcon.png"
- }
+ Button {
+ id: zoomButton
+ visible: false
+ /*anchors.right: backButton.left; */anchors.rightMargin: 5; y: 3; width: 80; height: 60
+ onClicked: toolbar.zoomClicked()
+ imageSource: "images/Zoom-In-icon.png"
+ }
-// Button {
-// id: rotateButton
-// visible: true; anchors.left: taskSwitcherButton.right;
-// anchors.rightMargin: 5; y: 3; width: 60; height: 60
-// onClicked: toolbar.rotateClicked()
-// imageSource: "images/rotate.png"
-// }
+ Button {
+ id: nextButton
+ visible: false
+ /*anchors.right: zoomButton.left;*/ anchors.rightMargin: 5; y: 3; width: 120; height: 60
+ onClicked: toolbar.nextClicked()
+ imageSource: "images/InputMethodShiftButtonNormal.png"
+ imageRotation: 90
+ }
+
+ Button {
+ id: backButton
+ anchors.right: parent.right; anchors.rightMargin: 5; y: 3; width: 116; height: 60
+ onClicked: toolbar.backClicked()
+ imageSource: "images/wmBackIcon.png"
+ }
+
+ Button {
+ id: quitButton
+ visible: false
+ anchors.right: parent.right; anchors.rightMargin: 5; y: 3; width: 116; height: 60
+ onClicked: toolbar.backClicked()
+ imageSource: "images/wmCloseIcon.png"
+ }
+ }
}
}
--- /dev/null
+border.left: 10
+border.top: 10
+border.bottom: 10
+border.right: 10
+source: lineedit.png
def getFeedUrl(self, key):
return self.db.execute("SELECT url FROM feeds WHERE id=?;", (key,)).fetchone()[0]
+
+ def getFeedCategory(self, key):
+ return self.db.execute("SELECT category FROM feeds WHERE id=?;", (key,)).fetchone()[0]
def getListOfFeeds(self, category=None):
if category: