Fix to support new NV API

This commit is contained in:
Muki 2016-12-23 20:02:29 +01:00
parent 848f4f0131
commit 79725af21a
33 changed files with 757 additions and 396 deletions

View file

@ -50,6 +50,15 @@ Page {
model: VisualItemModel {
SectionHeader {
text: qsTr("Version %1").arg("2.5.1")
}
LogItem {
title: 'Updated Netvibes API'
description: "Fixes for updated Netvibes API.";
}
SectionHeader {
text: qsTr("Version %1").arg("2.5.0")
}
@ -61,7 +70,7 @@ Page {
LogItem {
title: 'UI redesign'
description: "Some options were moved from pull down menu to bootom bar and bottom bar has a new dark look.";
description: "Some options were moved from pull down menu to the bottom bar and bottom bar has a new dark look.";
}
LogItem {
@ -71,7 +80,7 @@ Page {
LogItem {
title: 'Smoother offline mode'
description: "A few bugs were fixed and general offine mode experience has been improved.";
description: "A few bugs were fixed and general offline mode experience has been improved.";
}
LogItem {
@ -86,7 +95,7 @@ Page {
LogItem {
title: 'Night View'
description: "Night View reduces the brightness of websites by inverting colors (Heavily inspired and partially borrowed from harbour-webpirate project).";
description: "Night View reduces the brightness of websites by inverting colors (heavily inspired and code partially borrowed from harbour-webpirate project).";
}
SectionHeader {

View file

@ -127,7 +127,8 @@ Page {
function openEntryInBrowser() {
entryModel.setData(index, "read", 1, "");
notification.show(qsTr("Launching an external browser..."));
Qt.openUrlExternally(settings.offlineMode ? offlineUrl : onlineUrl);
//Qt.openUrlExternally(settings.offlineMode ? offlineUrl : onlineUrl);
Qt.openUrlExternally(onlineUrl)
}
function openUrlEntryInBrowser(url) {
@ -204,10 +205,12 @@ Page {
settings.zoom = ((zoom + delta) <= 0.5) || ((zoom + delta) >= 2.0) ? zoom : zoom + delta
var theme = { "zoom": settings.zoom }
postMessage("theme_set", { "theme": theme })
postMessage("theme_apply")
baner.show("" + Math.floor(settings.zoom * 100) + "%")
}
function messageReceivedHandler(message) {
if (message.type === "theme_init") {
if (message.type === "inited") {
if (root.themeApply) {
initTheme()
root.themeApply = false
@ -253,11 +256,13 @@ Page {
}*/
experimental.userScripts: [
Qt.resolvedUrl("js/ObjectOverrider.js"),
Qt.resolvedUrl("js/Kaktus.js"),
Qt.resolvedUrl("js/Console.js"),
Qt.resolvedUrl("js/MessageListener.js"),
Qt.resolvedUrl("js/Readability.js"),
Qt.resolvedUrl("js/Theme.js"),
Qt.resolvedUrl("js/ReaderModeHandler.js"),
Qt.resolvedUrl("js/MessageListener.js")]
Qt.resolvedUrl("js/ReaderMode.js"),
Qt.resolvedUrl("js/init.js")]
experimental.onMessageReceived: {
console.log("onMessageReceived data:", message.data)
@ -281,13 +286,20 @@ Page {
console.log(" navigation OtherNavigation:", request.navigationType === WebView.OtherNavigation)
console.log(" action:", request.action)*/
/*var url = "" + request.url
if (url.indexOf("about:") === 0) {
request.action = WebView.IgnoreRequest
return
}*/
if (request.url.toString() === root.onlineUrl ||
request.url.toString() === root.offlineUrl) {
if (_settings.webviewNavigation === 0) {
request.action = WebView.IgnoreRequest
return
}
if (_settings.webviewNavigation === 1 && !_settings.offlineMode) {
request.action = WebView.IgnoreRequest
root.openUrlEntryInBrowser(request.url)
return
}
if (request.url == root.onlineUrl || request.url == root.offlineUrl) {
root.openEntryInViewer()
request.action = WebView.IgnoreRequest
return
@ -318,14 +330,9 @@ Page {
}
if (_settings.webviewNavigation === 2) {
root.openUrlInViewer(request.url)
request.action = WebView.IgnoreRequest
return;
//request.action = WebView.AcceptRequest
//navigateBackPop = false
//return;
}
}
}
@ -339,6 +346,11 @@ Page {
flickable: view
}
TempBaner {
id: baner
anchors.centerIn: root
}
IconBar {
id: controlbar
flickable: view
@ -430,14 +442,6 @@ Page {
}
}
IconBarItem {
text: qsTr("Increase font")
icon: "image://icons/icon-m-fontup"
onClicked: {
root.updateZoom(0.1)
}
}
IconBarItem {
text: qsTr("Decrease font")
icon: "image://icons/icon-m-fontdown"
@ -445,5 +449,13 @@ Page {
root.updateZoom(-0.1)
}
}
IconBarItem {
text: qsTr("Increase font")
icon: "image://icons/icon-m-fontup"
onClicked: {
root.updateZoom(0.1)
}
}
}
}

View file

@ -61,6 +61,13 @@ Page {
onClicked: pageStack.push(Qt.resolvedUrl("AccountsDialog.qml"));
enabled: !settings.signedIn && !app.fetcherBusyStatus && !dm.busy && !dm.removerBusy
}
MenuItem {
text: enabled ? qsTr("Sync") : qsTr("Busy...")
visible: settings.signedIn && enabled
onClicked: fetcher.update()
enabled: !fetcher.busy && !dm.busy && !dm.removerBusy
}
}
ViewPlaceholder {

View file

@ -0,0 +1,67 @@
/*
Copyright (C) 2016 Michal Kosciesza <michal@mkiol.net>
This file is part of Kaktus.
Kaktus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Kaktus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Kaktus. If not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.0
import Sailfish.Silica 1.0
Item {
id: root
property alias leftIconSource: leftIcon.source
property alias rightIconSource: rightIcon.source
property alias minimumValue: slider.minimumValue
property alias maximumValue: slider.maximumValue
property alias value: slider.value
property alias label: slider.label
property alias valueText: slider.valueText
property alias stepSize: slider.stepSize
signal clicked
anchors { left: parent.left; right: parent.right}
height: Theme.itemSizeSmall + 3 * Theme.paddingLarge
Image {
id: leftIcon
width: Theme.itemSizeSmall
height: Theme.itemSizeSmall
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
}
Slider {
id: slider
width: parent.width - 2*Theme.itemSizeSmall
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
onClicked: root.clicked()
leftMargin: 0
rightMargin: 0
}
Image {
id: rightIcon
width: Theme.itemSizeSmall
height: Theme.itemSizeSmall
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
}
}

View file

@ -404,12 +404,13 @@ Page {
}
}
Slider {
width: root.width
IconSlider {
leftIconSource: "image://icons/icon-m-fontdown"
rightIconSource: "image://icons/icon-m-fontup"
label: qsTr("Viewer font size level")
minimumValue: 50
maximumValue: 200
value: Math.floor(settings.zoom * 100)
label: qsTr("Viewer font size level")
valueText: value + "%"
stepSize: 10
onValueChanged: settings.zoom = value/100
@ -432,33 +433,36 @@ Page {
return 0;
if (settings.locale === "cs")
return 1;
if (settings.locale === "en")
if (settings.locale === "de")
return 2;
if (settings.locale === "es")
if (settings.locale === "en")
return 3;
if (settings.locale === "it")
if (settings.locale === "es")
return 4;
if (settings.locale === "nl")
if (settings.locale === "it")
return 5;
if (settings.locale === "pl")
if (settings.locale === "nl")
return 6;
if (settings.locale === "ru")
if (settings.locale === "pl")
return 7;
if (settings.locale === "tr")
if (settings.locale === "ru")
return 8;
/*if (settings.locale === "tr")
return 9;*/
return 0;
}
menu: ContextMenu {
MenuItem { text: qsTr("Default"); onClicked: locale.showMessage() }
MenuItem { text: "Čeština"; onClicked: locale.showMessage() }
MenuItem { text: "Deutsch"; onClicked: locale.showMessage() }
MenuItem { text: "English"; onClicked: locale.showMessage() }
MenuItem { text: "Espanol"; onClicked: locale.showMessage() }
MenuItem { text: "Italiano"; onClicked: locale.showMessage() }
MenuItem { text: "Nederlands"; onClicked: locale.showMessage() }
MenuItem { text: "Polski"; onClicked: locale.showMessage() }
MenuItem { text: "Русский"; onClicked: locale.showMessage() }
MenuItem { text: "Türkçe"; onClicked: locale.showMessage() }
//MenuItem { text: "Türkçe"; onClicked: locale.showMessage() }
}
onCurrentIndexChanged: {
@ -470,26 +474,29 @@ Page {
settings.locale = "cs";
break;
case 2:
settings.locale = "en";
settings.locale = "de";
break;
case 3:
settings.locale = "es";
settings.locale = "en";
break;
case 4:
settings.locale = "it";
settings.locale = "es";
break;
case 5:
settings.locale = "nl";
settings.locale = "it";
break;
case 6:
settings.locale = "pl";
settings.locale = "nl";
break;
case 7:
settings.locale = "ru";
settings.locale = "pl";
break;
case 8:
settings.locale = "tr";
settings.locale = "ru";
break;
/*case 9:
settings.locale = "tr";
break;*/
}
}

View file

@ -1,5 +1,55 @@
/*
Copyright (C) 2014 Michal Kosciesza <michal@mkiol.net>
This file is part of Kaktus.
Kaktus is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Kaktus is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Kaktus. If not, see <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.0
import Sailfish.Silica 1.0
Item {
Rectangle {
id: root
property alias text: label.text
property alias interval: timer.interval
function show(text) {
root.text = text
timer.restart()
}
width: 2*Theme.iconSizeLarge
height: 2*Theme.iconSizeMedium
radius: 10
color: Theme.rgba("black", 0.7)
opacity: timer.running ? 1.0 : 0.0
visible: opacity > 0.0
Behavior on opacity { FadeAnimation {} }
Timer {
id: timer
interval: 1000
}
Label {
id: label
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignHCenter
anchors.left: parent.left; anchors.right: parent.right
font.pixelSize: Theme.fontSizeExtraLarge
}
}

View file

@ -72,12 +72,12 @@ Page {
var xhr = new XMLHttpRequest()
xhr.onreadystatechange = function () {
console.log("xhr.onreadystatechange")
/*console.log("xhr.onreadystatechange")
console.log(" xhr.readyState: " + xhr.readyState)
console.log(" xhr.status: " + xhr.status)
console.log(" xhr.responseType: " + xhr.responseType)
console.log(" xhr.responseURL : " + xhr.responseURL )
console.log(" xhr.statusText: " + xhr.statusText)
console.log(" xhr.statusText: " + xhr.statusText)*/
if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
view.loadHtml(xhr.responseText)
@ -93,10 +93,9 @@ Page {
function navigateBack() {
if (view.canGoBack) {
view.goBack()
root.readerModePossible = false
root.nightModePossible = false
//view.scrollToTop()
view.goBack()
} else {
pageStack.pop()
}
@ -118,6 +117,7 @@ Page {
"zoom": settings.zoom,
"theme": settings.readerTheme }
postMessage("theme_set", { "theme": theme })
postMessage("theme_update_scale")
}
function updateZoom(delta) {
@ -125,6 +125,8 @@ Page {
settings.zoom = ((zoom + delta) <= 0.5) || ((zoom + delta) >= 2.0) ? zoom : zoom + delta
var theme = { "zoom": settings.zoom }
postMessage("theme_set", { "theme": theme })
postMessage("theme_update_scale")
baner.show("" + Math.floor(settings.zoom * 100) + "%")
}
function switchReaderMode() {
@ -136,16 +138,16 @@ Page {
}
function messageReceivedHandler(message) {
if (message.type === "theme_init") {
initTheme()
if (message.type === "inited") {
// NightMode
root.nightModePossible = true
if ((settings.nightMode || root.nightMode) && !settings.offlineMode) {
postMessage("nightmode_enable")
} else {
postMessage("nightmode_disable")
}
// Theme
initTheme()
} else if (message.type === "readability_result") {
root.readerModePossible = message.data.possible
root.readerMode = message.data.enabled
@ -158,29 +160,18 @@ Page {
} else if (settings.offlineMode) {
postMessage("theme_apply")
}
} else if (message.type === "readability_status") {
console.log("readability_status: " + message.data.enabled)
} else if (message.type === "readability_enabled") {
root.readerMode = true
view.scrollToTop()
} else if (message.type === "readability_disabled") {
root.readerMode = false
view.scrollToTop()
} else if (message.type === "nightmode_enabled") {
root.nightMode = true
} else if (message.type === "nightmode_disabled") {
root.nightMode = false
}
}
@ -238,12 +229,14 @@ Page {
//experimental.transparentBackground: true
experimental.userScripts: [
Qt.resolvedUrl("js/ObjectOverrider.js"),
Qt.resolvedUrl("js/Kaktus.js"),
Qt.resolvedUrl("js/Console.js"),
Qt.resolvedUrl("js/MessageListener.js"),
Qt.resolvedUrl("js/NightMode.js"),
Qt.resolvedUrl("js/Readability.js"),
Qt.resolvedUrl("js/Theme.js"),
Qt.resolvedUrl("js/ReaderModeHandler.js"),
Qt.resolvedUrl("js/NightModeHandler.js"),
Qt.resolvedUrl("js/MessageListener.js")]
Qt.resolvedUrl("js/ReaderMode.js"),
Qt.resolvedUrl("js/init.js")]
experimental.onMessageReceived: {
console.log("onMessageReceived data:", message.data)
@ -324,7 +317,6 @@ Page {
if (_settings.webviewNavigation === 2) {
request.action = WebView.AcceptRequest
//root.readerMode = false
return;
}
}
@ -333,6 +325,11 @@ Page {
}
}
TempBaner {
id: baner
anchors.centerIn: root
}
IconBar {
id: controlbar
flickable: view
@ -399,7 +396,10 @@ Page {
icon: "image://icons/icon-m-browser"
onClicked: {
notification.show(qsTr("Launching an external browser..."));
Qt.openUrlExternally(onlineUrl);
var url = view.url.toString().lastIndexOf("about") === 0 ||
view.url.length === 0 ? root.onlineUrl : view.url
console.log("Opening: " + url)
Qt.openUrlExternally(url)
}
}
@ -436,14 +436,6 @@ Page {
}
}
IconBarItem {
text: qsTr("Increase font")
icon: "image://icons/icon-m-fontup"
onClicked: {
root.updateZoom(0.1)
}
}
IconBarItem {
text: qsTr("Decrease font")
icon: "image://icons/icon-m-fontdown"
@ -452,6 +444,14 @@ Page {
}
}
IconBarItem {
text: qsTr("Increase font")
icon: "image://icons/icon-m-fontup"
onClicked: {
root.updateZoom(0.1)
}
}
IconBarItem {
text: qsTr("Hide toolbar")
icon: "image://theme/icon-m-dismiss"

View file

@ -0,0 +1,9 @@
// Code borrowed from harbour-webpirate project (https://github.com/Dax89/harbour-webpirate)
console.log = function(msg) {
kaktusPostMessage("console_log", { log: ((typeof msg === "object") ? msg.toString() : msg) });
};
console.error = function(msg) {
kaktusPostMessage("console_error", { log: ((typeof msg === "object") ? msg.toString() : msg) });
};

View file

@ -0,0 +1,8 @@
function kaktusPostMessage(message, data) {
navigator.qt.postMessage(JSON.stringify({ "type": message, "data": data }));
}
/*window.XMLHttpRequest.prototype.open = function() {
console.log("BLOCKED: " + arguments[1]);
return null;
};*/

View file

@ -1,34 +1,41 @@
// Code heavily inspired and partially borrowed from
// harbour-webpirate project (https://github.com/Dax89/harbour-webpirate)
window.Kaktus_MessageListenerObject = function() {
window.KaktusMessageListenerObject = function() {
navigator.qt.onmessage = this.onMessage.bind(this);
};
window.Kaktus_MessageListenerObject.prototype.onMessage = function(message) {
var obj = JSON.parse(message.data);
var data = obj.data;
window.KaktusMessageListenerObject.prototype.onMessage = function(message) {
//console.log("onMessage: " + message);
try {
var obj = JSON.parse(message.data);
var data = obj.data;
if(obj.type === "readability_enable")
Kaktus_ReaderModeHandler.switchMode(true);
else if(obj.type === "readability_disable")
Kaktus_ReaderModeHandler.switchMode(false);
else if(obj.type === "readability_check")
Kaktus_ReaderModeHandler.check(data);
else if(obj.type === "readability_status")
Kaktus_ReaderModeHandler.status();
else if(obj.type === "readability_apply_fixups")
Kaktus_ReaderModeHandler.applyFixups(document);
else if(obj.type === "theme_set")
Kaktus_Theme.set(data.theme);
else if(obj.type === "theme_update_scale")
Kaktus_Theme.updateScale();
else if(obj.type === "theme_apply")
Kaktus_Theme.apply();
else if(obj.type === "nightmode_disable")
Kaktus_NightModeHandler.switchMode(false);
else if(obj.type === "nightmode_enable")
Kaktus_NightModeHandler.switchMode(true);
if(obj.type === "readability_enable")
KaktusReaderMode.switchMode(true);
else if(obj.type === "readability_disable")
KaktusReaderMode.switchMode(false);
else if(obj.type === "readability_check")
KaktusReaderMode.check(data);
else if(obj.type === "readability_status")
KaktusReaderMode.status();
else if(obj.type === "readability_apply_fixups")
KaktusReaderMode.applyFixups(document);
else if(obj.type === "theme_set")
KaktusTheme.set(data.theme);
else if(obj.type === "theme_update_scale")
KaktusTheme.updateScale();
else if(obj.type === "theme_apply")
KaktusTheme.apply();
else if(obj.type === "nightmode_disable")
KaktusNightMode.switchMode(false);
else if(obj.type === "nightmode_enable")
KaktusNightMode.switchMode(true);
} catch (err) {
console.error("Exception in KaktusMessageListener.onMessage: " + err);;
}
};
window.Kaktus_MessageListener = new window.Kaktus_MessageListenerObject();
window.KaktusMessageListener = new window.KaktusMessageListenerObject();

View file

@ -1,20 +1,20 @@
// Code heavily inspired and partially borrowed from
// harbour-webpirate project (https://github.com/Dax89/harbour-webpirate)
window.Kaktus_NightModeHandlerObject = function() {
window.KaktusNightModeObject = function() {
this.enabled = false;
this.style_id = "_kaktus_nightmode_style";
this.class_name = "_kaktus_nightmode_class";
}
kaktusPostMessage("nightmode_" + (this.enabled ? "enabled" : "disabled"));
};
window.Kaktus_NightModeHandlerObject.prototype.createStyle = function() {
window.KaktusNightModeObject.prototype.createStyle = function() {
var css = "html." + this.class_name + " { -webkit-filter: contrast(68%) brightness(108%) invert(); }\n" +
"html." + this.class_name + " iframe { -webkit-filter: invert(); }\n" + // Keep iframes normal
"html." + this.class_name + " object { -webkit-filter: invert(); }\n" + // Keep Flash items normal
"html." + this.class_name + " embed { -webkit-filter: invert(); }\n" + // Keep Flash items normal (HTML5)
"html." + this.class_name + " video { -webkit-filter: invert(); }\n" + // Keep HTML5 Videos normal
"html." + this.class_name + " img { -webkit-filter: invert(); }" ; // Keep images normal
var style_ele = document.getElementById(this.style_id);
if (style_ele) {
@ -24,11 +24,11 @@ window.Kaktus_NightModeHandlerObject.prototype.createStyle = function() {
style_ele.id = this.style_id;
style_ele.type = "text/css";
style_ele.appendChild(document.createTextNode(css));
document.head.appendChild(style_ele);
document.getElementsByTagName('head').item(0).appendChild(style_ele);
}
};
window.Kaktus_NightModeHandlerObject.prototype.switchMode = function(enabled) {
window.KaktusNightModeObject.prototype.switchMode = function(enabled) {
if (this.enabled === enabled)
return;
@ -42,9 +42,8 @@ window.Kaktus_NightModeHandlerObject.prototype.switchMode = function(enabled) {
this.createStyle();
html.className += " " + this.class_name;
}
kaktusPostMessage("nightmode_" + (this.enabled ? "enabled" : "disabled"));
};
var result = { type: "nightmode_" + (this.enabled ? "enabled" : "disabled") };
navigator.qt.postMessage(JSON.stringify(result));
}
window.Kaktus_NightModeHandler = new window.Kaktus_NightModeHandlerObject();
window.KaktusNightMode = new window.KaktusNightModeObject();

View file

@ -1,29 +0,0 @@
// Code borrowed from harbour-webpirate project (https://github.com/Dax89/harbour-webpirate)
console.log = function(msg) {
var data = { type: "console_log",
data: { log: ((typeof msg === "object") ? msg.toString() : msg) } };
navigator.qt.postMessage(JSON.stringify(data));
}
console.error = function(msg) {
var data = { type: "console_error",
data: { log: ((typeof msg === "object") ? msg.toString() : msg) } };
navigator.qt.postMessage(JSON.stringify(data));
}
window.open = function(url) { // Popup Blocker
var data = { type: "window_open",
data: { url: url } };
navigator.qt.postMessage(JSON.stringify(data));
}
window.onerror = function(errmsg, url, line) { // Print Javascript Errors
if((url !== undefined) && url.length)
console.log(url + "(" + line + "): " + errmsg);
return false; // Ignore other errors
}

View file

@ -112,7 +112,7 @@ Readability.prototype = {
// All of the regular expressions in use within readability.
// Defined up here so we don't instantiate them repeatedly in loops.
REGEXPS: {
unlikelyCandidates: /banner|combx|comment|community|disqus|extra|foot|header|menu|modal|related|remark|rss|share|shoutbox|sidebar|skyscraper|sponsor|ad-break|agegate|pagination|pager|popup/i,
unlikelyCandidates: /banner|combx|comment|community|disqus|extra|foot|header|legends|menu|modal|related|remark|rss|shoutbox|sidebar|skyscraper|sponsor|ad-break|agegate|pagination|pager|popup/i,
okMaybeItsACandidate: /and|article|body|column|main|shadow/i,
positive: /article|body|content|entry|hentry|h-entry|main|page|pagination|post|text|blog|story/i,
negative: /hidden|^hid$| hid$| hid |^hid |banner|combx|comment|com-|contact|foot|footer|footnote|masthead|media|meta|modal|outbrain|promo|related|scroll|share|shoutbox|sidebar|skyscraper|sponsor|shopping|tags|tool|widget/i,
@ -464,6 +464,12 @@ Readability.prototype = {
this._clean(articleContent, "h1");
this._clean(articleContent, "footer");
// Clean out elements have "share" in their id/class combinations from final top candidates,
// which means we don't remove the top candidates even they have "share".
this._forEachNode(articleContent.children, function(topCandidate) {
this._cleanMatchedNodes(topCandidate, /share/);
});
// If there is only one h2, they are probably using it as a header
// and not a subheader, so remove it since we already have a header.
if (articleContent.getElementsByTagName('h2').length === 1)
@ -655,9 +661,6 @@ Readability.prototype = {
var pageCacheHtml = page.innerHTML;
// Check if any "dir" is set on the toplevel document element
this._articleDir = doc.documentElement.getAttribute("dir");
while (true) {
var stripUnlikelyCandidates = this._flagIsActive(this.FLAG_STRIP_UNLIKELYS);
@ -805,6 +808,7 @@ Readability.prototype = {
var topCandidate = topCandidates[0] || null;
var neededToCreateTopCandidate = false;
var parentOfTopCandidate;
// If we still have no top candidate, just use the body as a last resort.
// We also have to copy the body node so it is something we can modify.
@ -831,7 +835,7 @@ Readability.prototype = {
// lurking in other places that we want to unify in. The sibling stuff
// below does some of that - but only if we've looked high enough up the DOM
// tree.
var parentOfTopCandidate = topCandidate.parentNode;
parentOfTopCandidate = topCandidate.parentNode;
var lastScore = topCandidate.readability.contentScore;
// The scores shouldn't get too low.
var scoreThreshold = lastScore / 3;
@ -857,7 +861,9 @@ Readability.prototype = {
articleContent.id = "readability-content";
var siblingScoreThreshold = Math.max(10, topCandidate.readability.contentScore * 0.2);
var siblings = topCandidate.parentNode.children;
// Keep potential top candidate's parent node to try to get text direction of it later.
parentOfTopCandidate = topCandidate.parentNode;
var siblings = parentOfTopCandidate.children;
for (var s = 0, sl = siblings.length; s < sl; s++) {
var sibling = siblings[s];
@ -961,6 +967,18 @@ Readability.prototype = {
return null;
}
} else {
// Find out text direction from ancestors of final top candidate.
var ancestors = [parentOfTopCandidate, topCandidate].concat(this._getNodeAncestors(parentOfTopCandidate));
this._someNode(ancestors, function(ancestor) {
if (!ancestor.tagName)
return false;
var articleDir = ancestor.getAttribute("dir");
if (articleDir) {
this._articleDir = articleDir;
return true;
}
return false;
});
return articleContent;
}
}
@ -1688,6 +1706,25 @@ Readability.prototype = {
});
},
/**
* Clean out elements whose id/class combinations match specific string.
*
* @param Element
* @param RegExp match id/class combination.
* @return void
**/
_cleanMatchedNodes: function(e, regex) {
var endOfSearchMarkerNode = this._getNextNode(e, true);
var next = this._getNextNode(e);
while (next && next != endOfSearchMarkerNode) {
if (regex.test(next.className + " " + next.id)) {
next = this._removeAndGetNext(next);
} else {
next = this._getNextNode(next);
}
}
},
/**
* Clean out spurious headers from an Element. Checks things like classnames and link density.
*

View file

@ -1,58 +1,62 @@
// Code heavily inspired and partially borrowed from
// harbour-webpirate project (https://github.com/Dax89/harbour-webpirate)
window.Kaktus_ReaderModeHandlerObject = function() {
window.KaktusReaderModeObject = function() {
this.enabled = false;
this.orginalDoc = null;
this.readabilityDoc = null;
this.readabilityPossible = false;
kaktusPostMessage("readability_" + (this.enabled ? "enabled" : "disabled"));
};
window.Kaktus_ReaderModeHandlerObject.prototype.applyFixups = function(doc) {
window.KaktusReaderModeObject.prototype.applyFixups = function(doc) {
var elements, i;
//doc = doc ? doc : document
// target attributes
// target attributess
elements = doc.querySelectorAll("[target]");
for (i = 0; i < elements.length; i++) {
elements[i].removeAttribute("target");
}
};
window.Kaktus_ReaderModeHandlerObject.prototype.applyFiltering = function(doc, insert) {
window.KaktusReaderModeObject.prototype.applyFiltering = function(doc, insert) {
var elements, i;
// kaktus img
var img = doc.getElementById("_kaktus_img");
// article element
elements = doc.getElementsByTagName("article");
if (elements.length > 0) {
var newBody = "" + insert + (img ? img.outerHTML : "");
for (i = 0; i < elements.length; i++) {
newBody += "<article>" + elements[i].innerHTML + "</article>";
}
doc.body.innerHTML = newBody;
try {
// kaktus img
var img = doc.getElementById("_kaktus_img");
// article element
elements = doc.getElementsByTagName("article");
if (elements.length > 0) {
var newBody = "" + insert + (img ? img.outerHTML : "");
for (i = 0; i < elements.length; i++) {
newBody += "<article>" + elements[i].innerHTML + "</article>";
}
doc.body.innerHTML = newBody;
}
// width, height, target, class attributes
elements = doc.querySelectorAll("[max-width],[min-width],[width],[height],[target],[class]");
for (i = 0; i < elements.length; i++) {
elements[i].removeAttribute("max-width");
elements[i].removeAttribute("min-width");
elements[i].removeAttribute("width");
elements[i].removeAttribute("height");
elements[i].removeAttribute("target");
elements[i].removeAttribute("class");
}
// img max-width
//elements = doc.getElementsByTagName("img");
//for (i = 0; i < elements.length; i++)
// elements[i].style.maxWidth = "100%";
} catch (err) {
console.error("Exception in KaktusReaderMode.applyFiltering: " + err);
}
// width, height, target, class attributes
elements = doc.querySelectorAll("[width],[height],[target],[class]");
for (i = 0; i < elements.length; i++) {
elements[i].removeAttribute("width");
elements[i].removeAttribute("height");
elements[i].removeAttribute("target");
elements[i].removeAttribute("class");
}
// img max-width
//elements = doc.getElementsByTagName("img");
//for (i = 0; i < elements.length; i++)
// elements[i].style.maxWidth = "100%";
};
window.Kaktus_ReaderModeHandlerObject.prototype.check = function(data) {
window.KaktusReaderModeObject.prototype.check = function(data) {
var loc = document.location;
var uri = { "spec": loc.href,
"host": loc.host,
@ -68,21 +72,21 @@ window.Kaktus_ReaderModeHandlerObject.prototype.check = function(data) {
var article = null;
try {
article = new window.Readability(uri, newDoc1).parse();
} catch (Exception) {}
} catch (err) {
console.error("Exception in KaktusReaderMode.check: " + err);
}
this.readabilityPossible = article && article.length > 0 ? true : false;
//console.log("Readability possible: " + this.readabilityPossible)
//console.log("Readability possible: " + this.readabilityPossible);
if (this.readabilityPossible) {
var title = article.title !== "" ? article.title : data.title;
var insert = title === "" ? "" : "<h1 id='_kaktus_title'>" + title + "</h1>";
var newDoc2 = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', null);
var newBody2 = document.createElementNS('http://www.w3.org/1999/xhtml', 'body');
newBody2.innerHTML = insert + article.content;
newDoc2.documentElement.appendChild(newBody2);
this.applyFiltering(newDoc2, insert);
this.readabilityDoc = newDoc2.documentElement.innerHTML;
this.orginalDoc = document.documentElement.innerHTML;
@ -90,34 +94,28 @@ window.Kaktus_ReaderModeHandlerObject.prototype.check = function(data) {
//console.log("Readability: " + this.readabilityDoc);
}
var result = { type: "readability_result", data: { possible: this.readabilityPossible, enabled: this.enabled } };
navigator.qt.postMessage(JSON.stringify(result));
kaktusPostMessage("readability_result", { possible: this.readabilityPossible, enabled: this.enabled });
};
window.Kaktus_ReaderModeHandlerObject.prototype.disable = function() {
window.KaktusReaderModeObject.prototype.disable = function() {
this.enabled = false;
document.documentElement.innerHTML = this.orginalDoc;
var result = { type: "readability_disabled" };
navigator.qt.postMessage(JSON.stringify(result));
window.Kaktus_Theme.updateScale();
kaktusPostMessage("readability_disabled");
window.KaktusTheme.updateScale();
};
window.Kaktus_ReaderModeHandlerObject.prototype.enable = function() {
window.KaktusReaderModeObject.prototype.enable = function() {
this.enabled = true;
document.documentElement.innerHTML = this.readabilityDoc;
window.Kaktus_Theme.apply();
var result = { type: "readability_enabled" };
navigator.qt.postMessage(JSON.stringify(result));
window.KaktusTheme.apply();
kaktusPostMessage("readability_enabled");
};
window.Kaktus_ReaderModeHandlerObject.prototype.status = function() {
var result = { type: "readability_status", data: { enabled: this.enabled } };
navigator.qt.postMessage(JSON.stringify(result));
window.KaktusReaderModeObject.prototype.status = function() {
kaktusPostMessage("readability_status", { enabled: this.enabled });
};
window.Kaktus_ReaderModeHandlerObject.prototype.switchMode = function(enabled) {
window.KaktusReaderModeObject.prototype.switchMode = function(enabled) {
if (this.enabled === enabled)
return;
@ -133,4 +131,4 @@ window.Kaktus_ReaderModeHandlerObject.prototype.switchMode = function(enabled) {
this.enable();
};
window.Kaktus_ReaderModeHandler = new window.Kaktus_ReaderModeHandlerObject();
window.KaktusReaderMode = new window.KaktusReaderModeObject();

View file

@ -1,19 +1,18 @@
// Code heavily inspired and partially borrowed from
// harbour-webpirate project (https://github.com/Dax89/harbour-webpirate)
window.Kaktus_ThemeObject = function() {
var result = { type: "theme_init" };
navigator.qt.postMessage(JSON.stringify(result));
};
window.Kaktus_ThemeObject.prototype.set = function(theme) {
for(var prop in theme)
this[prop] = theme[prop];
window.KaktusThemeObject = function() {
this.zoom = 1.0;
this.updateScale();
};
window.KaktusThemeObject.prototype.set = function(theme) {
for(var prop in theme)
this[prop] = theme[prop];
};
// Hack to fix wrong device Pixel Ratio reported by Webview (thanks to llelectronics)
window.Kaktus_ThemeObject.prototype.getPixelRatio = function() {
window.KaktusThemeObject.prototype.getPixelRatio = function() {
if(window.screen.width <= 540) // Jolla devicePixelRatio: 1.5
return 1.5
if(window.screen.width > 540 && screen.width <= 768) // Nexus 4 devicePixelRatio: 2.0
@ -22,13 +21,24 @@ window.Kaktus_ThemeObject.prototype.getPixelRatio = function() {
return 3.0
};
window.Kaktus_ThemeObject.prototype.updateScale = function() {
window.KaktusThemeObject.prototype.isBlacklisted = function() {
var host = document.location.hostname;
if (host === "www.reddit.com" || host === "reddit.com")
return true;
};
window.KaktusThemeObject.prototype.updateScale = function() {
var pr = this.getPixelRatio();
var _scale = this.zoom ? this.zoom * pr : pr;
var scale = Math.round((_scale <= 0.5 ? 0.5 : _scale ) * 10 ) / 10;
var viewport_ele = document.querySelector("meta[name='viewport']");
if (this.isBlacklisted())
scale = 1.0;
//var content = "initial-scale=" + scale;
var content = "width=device-width/" + scale + ", initial-scale=" + scale;
if (viewport_ele) {
viewport_ele.content = content;
} else {
@ -39,17 +49,16 @@ window.Kaktus_ThemeObject.prototype.updateScale = function() {
content_att.value = content;
meta_ele.setAttributeNode(name_att);
meta_ele.setAttributeNode(content_att);
document.head.appendChild(meta_ele);
document.getElementsByTagName('head').item(0).appendChild(meta_ele);
}
};
window.Kaktus_ThemeObject.prototype.apply = function() {
window.KaktusThemeObject.prototype.apply = function() {
var scale = this.getPixelRatio();
var pageMargin = Math.floor(this.pageMargin / (scale * this.zoom));
var pageMarginBottom = Math.floor(this.pageMarginBottom / (scale * this.zoom));
var fontSize = Math.floor(this.fontSize / scale);
var fontSizeTitle = Math.floor(this.fontSizeTitle / scale);
//var maxWidth = Math.floor(window.screen.width / (scale * this.zoom));
var css = "";
@ -72,15 +81,15 @@ window.Kaktus_ThemeObject.prototype.apply = function() {
"margin: 0; \n" +
"padding: " + pageMargin + "px " + pageMargin + "px " + pageMarginBottom + "px " + pageMargin + "px; \n" +
"font-size: " + fontSize + "px; }\n";
css += "img { max-width: 100% !important; max-height:device-height !important; }\n";
css += "buttom, input, form { max-width: 100% !important; max-height:device-height !important; }\n";
css += "img { max-width: 100% !important; max-height: device-height !important; }\n";
css += "buttom, input, form { max-width: 100% !important; max-height: device-height !important; }\n";
css += "a, h1, h2, h3, div, p, pre, code { word-wrap: break-word; }\n";
css += "h1, h1, h3 { font-family: \"" + this.fontFamilyHeading + "\"; }\n";
//css += "#_kaktus_img { margin-bottom: 10px; }\n";
css += "#_kaktus_img { margin-bottom: 10px; }\n";
css += "#_kaktus_title { font-size: " + fontSizeTitle + "px; font-weight: bold; }";
//css += "figure { margin: 0; padding: 0; }";
//console.log(css);
//console.log("apply: " + css);
var style_ele = document.getElementById("_kaktus_style");
if (style_ele) {
@ -90,10 +99,10 @@ window.Kaktus_ThemeObject.prototype.apply = function() {
style_ele.id = "_kaktus_style";
style_ele.type = "text/css";
style_ele.appendChild(document.createTextNode(css));
document.head.appendChild(style_ele);
document.getElementsByTagName('head').item(0).appendChild(style_ele);
}
this.updateScale();
}
};
window.Kaktus_Theme = new window.Kaktus_ThemeObject();
window.KaktusTheme = new window.KaktusThemeObject();

1
sailfish/qml/js/init.js Normal file
View file

@ -0,0 +1 @@
kaktusPostMessage("inited");

View file

@ -359,7 +359,7 @@ ApplicationWindow {
}
function fetcherBusyChanged() {
console.log("fetcherBusyChanged:", fetcher.busy, app.fetcherBusyStatus)
//console.log("fetcherBusyChanged:", fetcher.busy, app.fetcherBusyStatus)
if (app.fetcherBusyStatus != fetcher.busy)
app.fetcherBusyStatus = fetcher.busy;

View file

@ -8,6 +8,33 @@
# * date Author's Name <author's email> version-release
# - Summary of changes
* Thu Dec 22 2016 Michal Kosciesza 2.5.1-2
- DE & RU translations update
* Mon Dec 19 2016 Michal Kosciesza 2.5.1-1
- FIX: New netvibes API
* Sat Dec 03 2016 Michal Kosciesza 2.5.0-4
- Bug fixes
* Mon Nov 28 2016 Michal Kosciesza 2.5.0-3
- Translations update
* Sat Nov 19 2016 Michal Kosciesza 2.5.0-2
- Night View
- Translations update
* Sun Nov 13 2016 Michal Kosciesza 2.5.0-1
- List filtering
- Auto network mode
- Bug fixes
* Tue Nov 08 2016 Michal Kosciesza 2.5.0-0
- Reader View with Readablility.js
- Bottom bar improvements
- Smoother offline mode
- Unsynced data indicator
* Tue Jul 12 2016 Michal Kosciesza 2.4.0-0
- UI improvements for Jolla C

View file

@ -13,8 +13,8 @@ Name: harbour-kaktus
%{!?qtc_make:%define qtc_make make}
%{?qtc_builddir:%define _builddir %qtc_builddir}
Summary: Kaktus
Version: 2.4.0
Release: 0
Version: 2.5.1
Release: 2
Group: Qt/Qt
License: LICENSE
URL: https://github.com/mkiol/kaktus

View file

@ -1,7 +1,7 @@
Name: harbour-kaktus
Summary: Kaktus
Version: 2.4.0
Release: 0
Version: 2.5.1
Release: 2
# The contents of the Group field should be one of the groups listed here:
# http://gitorious.org/meego-developer-tools/spectacle/blobs/master/data/GROUPS
Group: Qt/Qt

View file

@ -335,6 +335,21 @@ bool CacheServer::readFile(const QString &filename, QByteArray &data)
return true;
}
bool CacheServer::readFile2(const QString &path, QByteArray &data)
{
QFile file(path);
if (!file.open(QIODevice::ReadOnly)) {
qWarning() << "Could not open" << path << "for reading: " << file.errorString();
file.close();
return false;
}
data.append(file.readAll());
file.close();
return true;
}
/*QByteArray CacheServer::getData(const QString &id)
{
qDebug() << "getData, id=" << id;
@ -388,18 +403,51 @@ QString CacheServer::getFileUrl(const QString &id)
void CacheServer::handle(QHttpRequest *req, QHttpResponse *resp)
{
//qDebug() << "handle, url=" << req->url().toString();
if (req->url().path() == "/test") {
resp->setHeader("Content-Type", "text/html");
resp->writeHead(200);
resp->end("<html><body><h1>It works!</h1></body></html>");
//qDebug() << "handle, url:" << req->url().toString();
QStringList parts = req->url().path().split('/');
//qDebug() << "handle, parts.length():" << parts.length();
if (parts.length() > 1) {
if (parts[1] == "test") {
resp->setHeader("Content-Type", "text/html");
resp->writeHead(200);
resp->end("<html><body><h1>It works!</h1></body></html>");
return;
}
/*if (parts[1] == "assets" && parts.length() > 2) {
//qDebug() << "handle, path=" << req->url().path();
QString path = "app/native" + req->url().path();
if (QFile::exists(path)) {
QByteArray content;
QStringList extParts = parts[parts.length()-1].split('.');
QString ext = extParts.length() > 0 ? extParts[extParts.length()-1] : "";
if (ext == "js") {
resp->setHeader("Content-Type", "application/javascript");
resp->setHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");
resp->setHeader("Pragma", "no-cache");
resp->writeHead(200);
CacheServer::readFile2(path, content);
resp->end(content);
return;
}
}
resp->writeHead(404);
resp->end("");
return;
}*/
FilteringWorker *worker = new FilteringWorker();
QObject::connect(this, SIGNAL(startWorker(QHttpRequest*,QHttpResponse*)), worker, SLOT(start(QHttpRequest*,QHttpResponse*)));
QObject::connect(worker, SIGNAL(finished()), this, SLOT(handleFinish()));
emit startWorker(req, resp);
} else {
resp->writeHead(404);
resp->end("");
return;
}
FilteringWorker *worker = new FilteringWorker();
QObject::connect(this, SIGNAL(startWorker(QHttpRequest*,QHttpResponse*)), worker, SLOT(start(QHttpRequest*,QHttpResponse*)));
QObject::connect(worker, SIGNAL(finished()), this, SLOT(handleFinish()));
emit startWorker(req, resp);
}
void CacheServer::handleFinish()

View file

@ -68,6 +68,7 @@ class CacheServer : public QObject
Q_OBJECT
public:
static bool readFile(const QString &filename, QByteArray &data);
static bool readFile2(const QString &path, QByteArray &data);
static QString getFileUrl(const QString &id);
static QByteArray getDataUrlByUrl(const QString &item);

View file

@ -232,7 +232,7 @@ bool DatabaseManager::checkParameters()
if (query.first()) {
int cur_db_ver = query.value(0).toString().toInt();
qDebug() << "DB version=" << cur_db_ver;
//qDebug() << "DB version =" << cur_db_ver;
if (cur_db_ver != DatabaseManager::version) {
qWarning() << "DB version mismatch!";
@ -880,31 +880,6 @@ void DatabaseManager::writeEntry(const Entry &item)
if (db.isOpen()) {
QSqlQuery query(db);
#ifdef BB10
bool ret = query.exec(QString("INSERT OR REPLACE INTO entries (id, stream_id, title, author, content, link, image, annotations, "
"fresh_or, read, saved, liked, broadcast, created_at, published_at, crawl_time, timestamp, last_update, fresh, cached) "
"VALUES ('%1','%2','%3','%4','%5','%6','%7','%8',%9,%10,%11,%12,%13,%14,%15,%16,%17,%18,%19, "
"coalesce((SELECT cached FROM entries WHERE id='%20'),0));")
.arg(item.id)
.arg(item.streamId)
.arg(QString(item.title.toUtf8().toBase64()))
.arg(QString(item.author.toUtf8().toBase64()))
.arg(QString(item.content.toUtf8().toBase64()))
.arg(QString(item.link.toUtf8().toBase64()))
.arg(QString(item.image.toUtf8().toBase64()))
.arg(QString(item.annotations.toUtf8().toBase64()))
.arg(item.freshOR)
.arg(item.read)
.arg(item.saved)
.arg(item.liked)
.arg(item.broadcast)
.arg(item.createdAt)
.arg(item.publishedAt)
.arg(item.crawlTime)
.arg(item.timestamp)
.arg(QDateTime::currentDateTimeUtc().toTime_t())
.arg(item.fresh).arg(item.id));
#else
query.prepare("INSERT OR REPLACE INTO entries (id, stream_id, title, author, content, link, image, annotations, "
"fresh_or, read, saved, liked, broadcast, created_at, published_at, crawl_time, timestamp, "
"last_update, fresh, cached) "
@ -932,7 +907,7 @@ void DatabaseManager::writeEntry(const Entry &item)
query.addBindValue(QDateTime::currentDateTimeUtc().toTime_t());
query.addBindValue(item.id);
query.addBindValue(item.id);
#endif
if (!query.exec()) {
qWarning() << "SQL Error!" << query.lastQuery();checkError(query.lastError());
}
@ -1402,12 +1377,6 @@ QList<DatabaseManager::StreamModuleTab> DatabaseManager::readStreamModuleTabList
"WHERE ms.module_id=m.id AND m.tab_id='%1';")
.arg(id));
/*bool ret = query.exec(QString("SELECT e.stream_id, m.id, m.tab_id, max(e.published_at) "
"FROM entries as e, module_stream as ms, modules as m "
"WHERE e.stream_id=ms.stream_id AND ms.module_id=m.id AND m.tab_id='%1' "
"GROUP BY e.stream_id;")
.arg(id));*/
if (!ret) {
qWarning() << "SQL Error!" << query.lastQuery();checkError(query.lastError());
}
@ -1440,12 +1409,6 @@ QList<DatabaseManager::StreamModuleTab> DatabaseManager::readStreamModuleTabList
"WHERE ms.module_id=m.id AND m.tab_id=t.id AND t.dashboard_id='%1';")
.arg(id));
/*bool ret = query.exec(QString("SELECT e.stream_id, m.id, m.tab_id, max(e.published_at) "
"FROM entries as e, module_stream as ms, modules as m, tabs as t "
"WHERE e.stream_id=ms.stream_id AND ms.module_id=m.id AND m.tab_id=t.id AND t.dashboard_id='%1' "
"GROUP BY e.stream_id;")
.arg(id));*/
if (!ret) {
qWarning() << "SQL Error!" << query.lastQuery();checkError(query.lastError());
}
@ -1480,14 +1443,6 @@ QList<DatabaseManager::StreamModuleTab> DatabaseManager::readSlowStreamModuleTab
"AND t.dashboard_id='%1' AND s.slow=1;")
.arg(id));
/*bool ret = query.exec(QString("SELECT e.stream_id, m.id, m.tab_id, max(e.published_at) "
"FROM entries as e, module_stream as ms, modules as m, tabs as t "
"WHERE e.stream_id=ms.stream_id AND ms.module_id=m.id AND m.tab_id=t.id "
"AND t.dashboard_id='%1' AND s.slow=1 "
"GROUP BY e.stream_id;")
.arg(id));*/
if (!ret) {
qWarning() << "SQL Error!" << query.lastQuery();checkError(query.lastError());
}

View file

@ -97,8 +97,10 @@ void EntryModel::initInThread()
void EntryModel::initFinished()
{
#ifndef BB10
this->beginResetModel();
this->endResetModel();
#endif
}
/*int EntryModel::fixIndex(const QString &id)
@ -222,6 +224,7 @@ int EntryModel::createItems(int offset, int limit)
//qDebug() << "limit:" << limit << "Row count:" << list.count() << "new offset:" << offset;
#ifndef ANDROID
// Remove dummy row
if (list.count()>0) {
int l = rowCount();
@ -232,6 +235,7 @@ int EntryModel::createItems(int offset, int limit)
removeRow(l-1);
}
}
#endif
QList<DatabaseManager::Entry>::iterator i = list.begin();
@ -340,9 +344,11 @@ int EntryModel::createItems(int offset, int limit)
++i;
}
#ifndef ANDROID
// Dummy row as workaround!
if (list.count()>0)
appendRow(new EntryItem("last","","","","","","","","","","","",false,false,false,0,0,0,0));
#endif
return list.count();
}

View file

@ -1,6 +1,8 @@
#ifdef SAILFISH
#include <sailfishapp.h>
#include <QPainter>
#include <mlite5/MGConfItem>
#endif
#include <QPainter>
#include <QDebug>
#include <QFile>
#include <QDir>
@ -9,6 +11,7 @@
IconProvider::IconProvider() : QQuickImageProvider(QQuickImageProvider::Pixmap)
{
#ifdef SAILFISH
// Getting pixel ratio
double ratio = MGConfItem("/desktop/sailfish/silica/theme_pixel_ratio").value().toDouble();
//qDebug() << "ratio:" << ratio;
@ -31,6 +34,11 @@ IconProvider::IconProvider() : QQuickImageProvider(QQuickImageProvider::Pixmap)
qWarning() << "Theme " + themeDir + " for ratio " + ratio + " doesn't exist!";
themeDir = SailfishApp::pathTo("images/z1.0").toString(QUrl::RemoveScheme);
}
#endif
#if ANDROID
//TODO
themeDir = "";
#endif
}
QPixmap IconProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
@ -42,7 +50,7 @@ QPixmap IconProvider::requestPixmap(const QString &id, QSize *size, const QSize
filepath = themeDir + "/icon-m-item.png";
}
QPixmap sourcePixmap(themeDir + "/" + parts.at(0) + ".png");
QPixmap sourcePixmap(filepath);
if (size)
*size = sourcePixmap.size();

View file

@ -18,13 +18,18 @@
*/
#include <QGuiApplication>
#include <QScopedPointer>
#include <QQmlEngine>
#include <QQmlContext>
#include <QQuickView>
#include <sailfishapp.h>
#include <QtDebug>
#include <QTranslator>
#include <QScopedPointer>
#ifdef SAILFISH
#include <sailfishapp.h>
#endif
#ifdef ANDROID
#include <QQmlApplicationEngine>
#endif
#include "iconprovider.h"
#include "nviconprovider.h"
@ -39,59 +44,78 @@ static const char *APP_NAME = "Kaktus";
static const char *AUTHOR = "Michal Kosciesza <michal@mkiol.net>";
static const char *PAGE = "https://github.com/mkiol/kaktus";
#ifdef KAKTUS_LIGHT
static const char *VERSION = "2.5.0 (light edition)";
static const char *VERSION = "2.5.1 (light edition)";
#else
static const char *VERSION = "2.5.0";
static const char *VERSION = "2.5.1";
#endif
int main(int argc, char *argv[])
{
#ifdef SAILFISH
QScopedPointer<QGuiApplication> app(SailfishApp::application(argc, argv));
QScopedPointer<QQuickView> view(SailfishApp::createView());
QScopedPointer<QQmlEngine> engine(view->engine());
QQmlContext *context = view->rootContext();
QString translationsDirPath = SailfishApp::pathTo("translations").toLocalFile();
#endif
#ifdef ANDROID
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QScopedPointer<QGuiApplication> app(new QGuiApplication(argc, argv));
QScopedPointer<QQmlApplicationEngine> engine(new QQmlApplicationEngine());
QQmlContext *context = engine->rootContext();
QString translationsDirPath = "";
//TODO
#endif
app->setApplicationName(APP_NAME);
app->setApplicationDisplayName(APP_NAME);
app->setApplicationVersion(VERSION);
view->rootContext()->setContextProperty("APP_NAME", APP_NAME);
view->rootContext()->setContextProperty("VERSION", VERSION);
view->rootContext()->setContextProperty("AUTHOR", AUTHOR);
view->rootContext()->setContextProperty("PAGE", PAGE);
context->setContextProperty("APP_NAME", APP_NAME);
context->setContextProperty("VERSION", VERSION);
context->setContextProperty("AUTHOR", AUTHOR);
context->setContextProperty("PAGE", PAGE);
view->engine()->addImageProvider(QLatin1String("icons"), new IconProvider);
view->engine()->addImageProvider(QLatin1String("nvicons"), new NvIconProvider);
engine->addImageProvider(QLatin1String("icons"), new IconProvider);
engine->addImageProvider(QLatin1String("nvicons"), new NvIconProvider);
qRegisterMetaType<DatabaseManager::CacheItem>("CacheItem");
//qmlRegisterMetaType<QQmlChangeSet>()
Settings* settings = Settings::instance();
Settings *settings = Settings::instance();
QTranslator translator;
QString locale = settings->getLocale() == "" ? QLocale::system().name() : settings->getLocale();
if(!translator.load(locale, "kaktus", "_", SailfishApp::pathTo("translations").toLocalFile(), ".qm")) {
qDebug() << "Couldn't load translation for locale " + locale + " from " + SailfishApp::pathTo("translations").toLocalFile();
if(!translator.load(locale, "kaktus", "_", translationsDirPath, ".qm")) {
qDebug() << "Couldn't load translation for locale " + locale + " from " + translationsDirPath;
}
app->installTranslator(&translator);
settings->view = view.data();
settings->context = context;
DatabaseManager db; settings->db = &db;
DownloadManager dm; settings->dm = &dm;
CacheServer cache(&db); settings->cache = &cache;
Utils utils;
QObject::connect(view->engine(), SIGNAL(quit()), QCoreApplication::instance(), SLOT(quit()));
QObject::connect(engine.data(), SIGNAL(quit()), QCoreApplication::instance(), SLOT(quit()));
NetworkAccessManagerFactory NAMfactory(settings->getDmUserAgent());
view->engine()->setNetworkAccessManagerFactory(&NAMfactory);
engine->setNetworkAccessManagerFactory(&NAMfactory);
view->rootContext()->setContextProperty("db", &db);
view->rootContext()->setContextProperty("utils", &utils);
view->rootContext()->setContextProperty("dm", &dm);
view->rootContext()->setContextProperty("cache", &cache);
view->rootContext()->setContextProperty("settings", settings);
context->setContextProperty("db", &db);
context->setContextProperty("utils", &utils);
context->setContextProperty("dm", &dm);
context->setContextProperty("cache", &cache);
context->setContextProperty("settings", settings);
#ifdef SAILFISH
view->setSource(SailfishApp::pathTo("qml/main.qml"));
view->show();
#endif
#ifdef ANDROID
engine->load(QUrl(QLatin1String("qrc:/qml/main.qml")));
#endif
return app->exec();
}

View file

@ -838,6 +838,13 @@ void NvFetcher::finishedDashboards2()
fetchTabs();
} else {
qWarning() << "No Dashboards found!";
// Restoring backup
Settings *s = Settings::instance();
if (!s->db->restoreBackup()) {
qWarning() << "Unable to restore DB backup!";
}
taskEnd();
}
}
@ -1183,7 +1190,7 @@ void NvFetcher::storeDashboardsByParsingHtml()
{
Settings *s = Settings::instance();
QRegExp rx1("<li id=\"page-([^\"]*)\" class=\"[^\"]*enabled[^\"]*\" title=\"([^\"]*)\">");
QRegExp rx1("<div id=\"page-([^\"]*)\" class=\"[^\"]*private-page[^\"]*\" title=\"([^\"]*)\">");
int pos = 0;
while ((pos = rx1.indexIn(this->data, pos)) != -1) {
//qDebug() << "enabled" << rx1.cap(1) << rx1.cap(2);
@ -1200,7 +1207,7 @@ void NvFetcher::storeDashboardsByParsingHtml()
// Active dashboard
QString defaultDashboardId = s->getDashboardInUse();
if (defaultDashboardId.isEmpty()) {
QRegExp rx2("<li id=\"page-([^\"]*)\" class=\"[^\"]*active[^\"]*\" title=\"([^\"]*)\">");
QRegExp rx2("<div id=\"page-([^\"]*)\" class=\"[^\"]*active[^\"]*\" title=\"([^\"]*)\">");
pos = 0;
while ((pos = rx2.indexIn(this->data, pos)) != -1) {
//qDebug() << "active:" << rx2.cap(1) << rx2.cap(2);
@ -1284,16 +1291,16 @@ void NvFetcher::storeTabs()
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
if (jsonObj["userData"].toObject()["tabs"].isArray()) {
QJsonArray::const_iterator i = jsonObj["userData"].toObject()["tabs"].toArray().constBegin();
QJsonArray::const_iterator end = jsonObj["userData"].toObject()["tabs"].toArray().constEnd();
QJsonArray arr = jsonObj["userData"].toObject()["tabs"].toArray();
int end = arr.count();
#else
if (jsonObj["userData"].toMap()["tabs"].type()==QVariant::List) {
QVariantList::const_iterator i = jsonObj["userData"].toMap()["tabs"].toList().constBegin();
QVariantList::const_iterator end = jsonObj["userData"].toMap()["tabs"].toList().constEnd();
#endif
while (i != end) {
for (int i = 0; i < end; ++i) {
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
QJsonObject obj = (*i).toObject();
QJsonObject obj = arr.at(i).toObject();
#else
QVariantMap obj = (*i).toMap();
#endif
@ -1334,8 +1341,6 @@ void NvFetcher::storeTabs()
emit addDownload(item);
//qDebug() << "icon:" << t.icon;
}
++i;
}
} else {
qWarning() << "No \"tabs\" element found!";
@ -1343,16 +1348,17 @@ void NvFetcher::storeTabs()
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
if (jsonObj["userData"].toObject()["modules"].isArray()) {
QJsonArray::const_iterator i = jsonObj["userData"].toObject()["modules"].toArray().constBegin();
QJsonArray::const_iterator end = jsonObj["userData"].toObject()["modules"].toArray().constEnd();
QJsonArray arr = jsonObj["userData"].toObject()["modules"].toArray();
int end = arr.count();
#else
if (jsonObj["userData"].toMap()["modules"].type()==QVariant::List) {
QVariantList::const_iterator i = jsonObj["userData"].toMap()["modules"].toList().constBegin();
QVariantList::const_iterator end = jsonObj["userData"].toMap()["modules"].toList().constEnd();
#endif
while (i != end) {
//while (i != end) {
for (int i = 0; i < end; ++i) {
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
QJsonObject obj = (*i).toObject();
QJsonObject obj = arr.at(i).toObject();
#else
QVariantMap obj = (*i).toMap();
#endif
@ -1372,10 +1378,10 @@ void NvFetcher::storeTabs()
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
if (obj["streams"].isArray()) {
QJsonArray::const_iterator mi = obj["streams"].toArray().constBegin();
QJsonArray::const_iterator mend = obj["streams"].toArray().constEnd();
while (mi != mend) {
QJsonObject mobj = (*mi).toObject();
QJsonArray marr = obj["streams"].toArray();
int mend = marr.count();
for (int mi = 0; mi < mend; ++mi) {
QJsonObject mobj = marr.at(mi).toObject();
#else
if (obj["streams"].type()==QVariant::List) {
QVariantList::const_iterator mi = obj["streams"].toList().constBegin();
@ -1390,17 +1396,13 @@ void NvFetcher::storeTabs()
streamList.append(smt);
m.streamList.append(smt.streamId);
//qDebug() << "Writing module: " << "tabid:" << smt.tabId << "moduleId:" << smt.moduleId << "streamId:" << smt.streamId << m.title;
++mi;
}
} else {
qWarning() << "Module"<<m.id<<"without streams!";
}
s->db->writeModule(m);
}
++i;
}
} else {
qWarning() << "No modules element found!";
@ -1418,28 +1420,28 @@ int NvFetcher::storeFeeds()
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
if (jsonObj["results"].isArray()) {
QJsonArray::const_iterator i = jsonObj["results"].toArray().constBegin();
QJsonArray::const_iterator end = jsonObj["results"].toArray().constEnd();
QJsonArray arr = jsonObj["results"].toArray();
int end = arr.count();
#else
if (jsonObj["results"].type()==QVariant::List) {
QVariantList::const_iterator i = jsonObj["results"].toList().constBegin();
QVariantList::const_iterator end = jsonObj["results"].toList().constEnd();
#endif
while (i != end) {
for (int i = 0; i < end; ++i) {
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
if ((*i).isObject()) {
if ((*i).toObject()["streams"].isArray()) {
QJsonArray::const_iterator ai = (*i).toObject()["streams"].toArray().constBegin();
QJsonArray::const_iterator aend = (*i).toObject()["streams"].toArray().constEnd();
if (arr.at(i).isObject()) {
if (arr.at(i).toObject()["streams"].isArray()) {
QJsonArray aarr = arr.at(i).toObject()["streams"].toArray();
int aend = arr.count();
#else
if ((*i).type()==QVariant::Map) {
if ((*i).toMap()["streams"].type()==QVariant::List) {
QVariantList::const_iterator ai = (*i).toMap()["streams"].toList().constBegin();
QVariantList::const_iterator aend = (*i).toMap()["streams"].toList().constEnd();
#endif
while (ai != aend) {
for (int ai = 0; ai < aend; ++ai) {
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
QJsonObject obj = (*ai).toObject();
QJsonObject obj = aarr.at(ai).toObject();
if (obj["error"].isObject()) {
int code = (int) obj["error"].toObject()["code"].toDouble();
if (code != 204) {
@ -1493,24 +1495,22 @@ int NvFetcher::storeFeeds()
//qDebug() << "Writing Stream: " << st.id << st.title;
s->db->writeStream(st);
++ai;
}
} else {
qWarning() << "No \"streams\" element found!";
}
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
if ((*i).toObject()["items"].isArray()) {
QJsonArray::const_iterator ai = (*i).toObject()["items"].toArray().constBegin();
QJsonArray::const_iterator aend = (*i).toObject()["items"].toArray().constEnd();
if (arr.at(i).toObject()["items"].isArray()) {
QJsonArray aarr = arr.at(i).toObject()["items"].toArray();
int aend = arr.count();
#else
if ((*i).toMap()["items"].type()==QVariant::List) {
QVariantList::const_iterator ai = (*i).toMap()["items"].toList().constBegin();
QVariantList::const_iterator aend = (*i).toMap()["items"].toList().constEnd();
#endif
while (ai != aend) {
for (int ai = 0; ai < aend; ++ai) {
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
QJsonObject obj = (*ai).toObject();
QJsonObject obj = aarr.at(ai).toObject();
#else
QVariantMap obj = (*ai).toMap();
#endif
@ -1634,15 +1634,11 @@ int NvFetcher::storeFeeds()
if (e.publishedAt>0)
publishedBeforeDate = e.publishedAt;
++ai;
}
} else {
qWarning() << "No \"items\" element found!";
}
}
++i;
}
} else {
qWarning() << "No \"relults\" element found!";

View file

@ -17,7 +17,9 @@
along with Kaktus. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef SAILFISH
#include <sailfishapp.h>
#endif
#include <QPainter>
#include <QRect>
#include <QColor>
@ -42,7 +44,14 @@ NvIconProvider::NvIconProvider() : QQuickImageProvider(QQuickImageProvider::Pixm
QPixmap NvIconProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
{
QStringList parts = id.split('?');
QPixmap iconsPixmap(SailfishApp::pathTo("qml/sprite-icons.png").toString(QUrl::RemoveScheme));
QString spriteImagePath = "";
#ifdef SAILFISH
spriteImagePath = SailfishApp::pathTo("qml/sprite-icons.png").toString(QUrl::RemoveScheme);
#endif
#ifdef ANDROID
spriteImagePath = ":/images/sprite-icons.png";
#endif
QPixmap iconsPixmap(spriteImagePath);
QPixmap iconPixmap = iconsPixmap.copy(getPosition(parts.at(0), parts.at(1)));
if (size)

View file

@ -1054,16 +1054,16 @@ void OldReaderFetcher::storeTabs()
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
if (jsonObj["tags"].isArray()) {
QJsonArray::const_iterator i = jsonObj["tags"].toArray().constBegin();
QJsonArray::const_iterator end = jsonObj["tags"].toArray().constEnd();
QJsonArray arr = jsonObj["tags"].toArray();
int end = arr.count();
#else
if (jsonObj["tags"].type()==QVariant::List) {
QVariantList::const_iterator i = jsonObj["tags"].toList().constBegin();
QVariantList::const_iterator end = jsonObj["tags"].toList().constEnd();
#endif
while (i != end) {
for (int i = 0; i < end; ++i) {
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
QJsonObject obj = (*i).toObject();
QJsonObject obj = arr.at(i).toObject();
#else
QVariantMap obj = (*i).toMap();
#endif
@ -1079,8 +1079,6 @@ void OldReaderFetcher::storeTabs()
s->db->writeTab(t);
tabList.append(t.id);
}
++i;
}
} else {
@ -1267,22 +1265,21 @@ void OldReaderFetcher::storeFeeds()
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
if (jsonObj["subscriptions"].isArray()) {
QJsonArray::const_iterator i = jsonObj["subscriptions"].toArray().constBegin();
QJsonArray::const_iterator end = jsonObj["subscriptions"].toArray().constEnd();
QJsonArray arr = jsonObj["subscriptions"].toArray();
int end = arr.count();
#else
if (jsonObj["subscriptions"].type()==QVariant::List) {
QVariantList::const_iterator i = jsonObj["subscriptions"].toList().constBegin();
QVariantList::const_iterator end = jsonObj["subscriptions"].toList().constEnd();
#endif
while (i != end) {
for (int i = 0; i < end; ++i) {
QString tabId, tabName;
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
// Checking tab (folder)
QJsonObject obj = (*i).toObject();
QJsonObject obj = arr.at(i).toObject();
if (obj["categories"].isArray()) {
getFolderFromCategories(obj["categories"].toArray(), tabId, tabName);
}
#else
QVariantMap obj = (*i).toMap();
@ -1341,8 +1338,6 @@ void OldReaderFetcher::storeFeeds()
smt.tabId = tabId;
feedList.append(smt);*/
}
++i;
}
} else {
@ -1373,8 +1368,8 @@ void OldReaderFetcher::storeStream()
qWarning() << "No updated param in stream!";
}
if (jsonObj["items"].isArray()) {
QJsonArray::const_iterator i = jsonObj["items"].toArray().constBegin();
QJsonArray::const_iterator end = jsonObj["items"].toArray().constEnd();
QJsonArray arr = jsonObj["items"].toArray();
int end = arr.count();
#else
//qDebug() << jsonObj["updated"].type();
if (jsonObj["updated"].type()==QVariant::ULongLong) {
@ -1387,10 +1382,10 @@ void OldReaderFetcher::storeStream()
QVariantList::const_iterator end = jsonObj["items"].toList().constEnd();
#endif
//qDebug() << "Updated:" << updated;
while (i != end) {
for (int i = 0; i < end; ++i) {
QString feedId;
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
QJsonObject obj = (*i).toObject();
QJsonObject obj = arr.at(i).toObject();
if (obj["origin"].isObject()) {
feedId = obj["origin"].toObject()["streamId"].toString();
}
@ -1492,8 +1487,6 @@ void OldReaderFetcher::storeStream()
lastDate = newLastDate;
}
}
++i;
}
}

View file

@ -241,8 +241,8 @@ void Settings::setWebviewNavigation(int value)
int Settings::getWebviewNavigation()
{
// Default is 0 - open in web view
return settings.value("webviewnavigation", 0).toInt();
// Default is 2 - open in web view
return settings.value("webviewnavigation", 2).toInt();
}
void Settings::setShowTabIcons(bool value)
@ -495,7 +495,11 @@ void Settings::setLocale(const QString &value)
QString Settings::getLocale()
{
return settings.value("locale", "").toString();
QString locale = settings.value("locale", "").toString();
if (locale == "" || locale == "cs" || locale == "de" || locale == "es" ||
locale == "en" || locale == "it" || locale == "nl" || locale == "pl" || locale == "ru")
return locale;
return "";
}
void Settings::setLastUpdateDate(int value)

View file

@ -30,7 +30,7 @@
#include <bb/cascades/QmlDocument>
#else
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QQuickView>
#include <QQmlContext>
#else
#include <QDeclarativeView>
#endif
@ -91,7 +91,7 @@ public:
bb::cascades::QmlDocument* qml;
#else
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
QQuickView* view;
QQmlContext* context;
#else
QDeclarativeView* view;
#endif

View file

@ -18,13 +18,16 @@
*/
#include <QtGui/QClipboard>
#include <QTextDocument>
#include <QDebug>
#include <QDateTime>
#include <QtCore/qmath.h>
#include <QCryptographicHash>
#include <QRegExp>
#ifdef ANDROID
#include <QtAndroidExtras/QAndroidJniObject>
#include <QtGui/QGuiApplication>
#endif
#ifdef BB10
#include <bps/navigator.h>
#include <QtGui/QApplication>
@ -34,12 +37,16 @@
#include <bb/cascades/Application>
#include <bb/cascades/ColorTheme>
#include <bb/cascades/VisualStyle>
#include <bb/cascades/SystemDefaults>
#include <bb/cascades/TextStyle>
#include <bb/cascades/FontSize>
#include <bb/platform/PlatformInfo>
#include <bb/device/DisplayTechnology>
#include <bb/platform/PlatformInfo>
#include <QtCore/QString>
#include <QtCore/QList>
#include <bb/system/Clipboard>
#include <QtGui/QTextDocument>
#else
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QGuiApplication>
@ -50,6 +57,7 @@
#include <QtGui/QApplication>
#include <QDeclarativeContext>
#endif
#include <QTextDocument>
#endif
#include "utils.h"
@ -65,6 +73,9 @@ Utils::Utils(QObject *parent) :
entryModel = NULL;
tabModel = NULL;
feedModel = NULL;
#ifdef ANDROID
screen = QGuiApplication::screens().at(0);
#endif
}
bool Utils::isLight()
@ -76,16 +87,45 @@ bool Utils::isLight()
#endif
}
/*bool Utils::isOnline()
#ifdef ANDROID
int Utils::dp(float value)
{
#ifdef ONLINE_CHECK
qDebug() << "ncm->isOnline()" << ncm->isOnline();
return ncm->isOnline();
//float dp = value * (screen->physicalDotsPerInch() / 160) + 0.5;
//dp = (10 * dp + 5) / 10;
//qDebug() << "value=" << value << "dp=" << value * (screen->physicalDotsPerInch() / 160) << "dpp=" << dp;
return value * (screen->physicalDotsPerInch() / 160) + 0.5;
}
int Utils::mm(float value)
{
return value * (screen->physicalDotsPerInch() / 25.4);
}
int Utils::in(float value)
{
return value * screen->physicalDotsPerInch();
}
int Utils::pt(float value)
{
return value * (screen->physicalDotsPerInch() / 72);
}
int Utils::sp(float value)
{
return dp(value);
}
void Utils::showNotification(const QString &title, const QString &text)
{
QAndroidJniObject jTitle = QAndroidJniObject::fromString(title);
QAndroidJniObject jText = QAndroidJniObject::fromString(text);
QAndroidJniObject::callStaticMethod<void>("net/mkiol/kaktus/KaktusActivity",
"notify",
"(Ljava/lang/String;Ljava/lang/String;)V",
jTitle.object<jstring>(), jText.object<jstring>());
}
#endif
#ifndef ONLINE_CHECK
return true;
#endif
}*/
#ifdef BB10
void Utils::launchBrowser(const QString &url)
@ -139,6 +179,7 @@ QString Utils::formatHtml(const QString & data, bool offline, const QString & st
{
QRegExp rxImg("<img[^>]*>", Qt::CaseInsensitive);
QRegExp rxWidth("\\s*width\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
QRegExp rxTarget("\\s*target\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
QRegExp rxHeight("\\s*height\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
QRegExp rxSizes("\\s*sizes\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
QRegExp rxA("<a[^>]*></a>", Qt::CaseInsensitive);
@ -149,6 +190,7 @@ QString Utils::formatHtml(const QString & data, bool offline, const QString & st
return "";
QString content = data;
content.remove(rxTarget);
if (offline) {
content.remove(rxImg); content.remove("</img>", Qt::CaseInsensitive);
content.remove(rxA);
@ -192,6 +234,21 @@ bool Utils::removeDir(const QString &dirName)
}
#ifdef BB10
QString Utils::readAsset(const QString &path)
{
QFile file("app/native/assets/" + path);
if (!file.open(QIODevice::ReadOnly)) {
qWarning() << "Could not open" << path << "for reading: " << file.errorString();
file.close();
return "";
}
QString data = QString(file.readAll());
file.close();
return data;
}
// Source: http://hecgeek.blogspot.com/2014/10/blackberry-10-multiple-os-versions-from.html
bool Utils::checkOSVersion(int major, int minor, int patch, int build)
{
@ -349,6 +406,28 @@ bb::cascades::Color Utils::textOnPlain()
{
return text();
}
/*float Utils::primaryTextFontSize()
{
bb::cascades::TextStyle style = bb::cascades::SystemDefaults::TextStyles::primaryText();
qDebug() << "primaryText:" << style.fontSize() << bb::cascades::FontSize::Medium;
return bb::cascades::SystemDefaults::TextStyles::primaryText().fontSizeValue();
}
QString Utils::primaryTextFontFamily()
{
return bb::cascades::SystemDefaults::TextStyles::primaryText().fontFamily();
}
float Utils::titleTextFontSize()
{
return bb::cascades::SystemDefaults::TextStyles::titleText().fontSizeValue();
}
QString Utils::titleTextFontFamily()
{
return bb::cascades::SystemDefaults::TextStyles::titleText().fontFamily();
}*/
#endif
void Utils::setRootModel()
@ -370,7 +449,7 @@ void Utils::setRootModel()
#ifdef BB10
s->qml->setContextProperty("tabModel", tabModel);
#else
s->view->rootContext()->setContextProperty("tabModel", tabModel);
s->context->setContextProperty("tabModel", tabModel);
#endif
if (oldTabModel != NULL) {
delete oldTabModel;
@ -389,7 +468,7 @@ void Utils::setRootModel()
#ifdef BB10
s->qml->setContextProperty("tabModel", tabModel);
#else
s->view->rootContext()->setContextProperty("tabModel", tabModel);
s->context->setContextProperty("tabModel", tabModel);
#endif
if (oldTabModel != NULL) {
delete oldTabModel;
@ -408,7 +487,7 @@ void Utils::setRootModel()
#ifdef BB10
s->qml->setContextProperty("feedModel", feedModel);
#else
s->view->rootContext()->setContextProperty("feedModel", feedModel);
s->context->setContextProperty("feedModel", feedModel);
#endif
if (tabModel != NULL)
delete tabModel; tabModel = NULL;
@ -434,7 +513,7 @@ void Utils::setRootModel()
#ifdef BB10
s->qml->setContextProperty("entryModel", entryModel);
#else
s->view->rootContext()->setContextProperty("entryModel", entryModel);
s->context->setContextProperty("entryModel", entryModel);
#endif
if (tabModel != NULL)
delete tabModel; tabModel = NULL;
@ -459,7 +538,7 @@ void Utils::setFeedModel(const QString &tabId)
#ifdef BB10
s->qml->setContextProperty("feedModel", feedModel);
#else
s->view->rootContext()->setContextProperty("feedModel", feedModel);
s->context->setContextProperty("feedModel", feedModel);
#endif
if (oldFeedModel != NULL) {
@ -478,7 +557,7 @@ void Utils::setEntryModel(const QString &feedId)
#ifdef BB10
s->qml->setContextProperty("entryModel", entryModel);
#else
s->view->rootContext()->setContextProperty("entryModel", entryModel);
s->context->setContextProperty("entryModel", entryModel);
#endif
if (oldEntryModel != NULL) {
@ -497,7 +576,7 @@ void Utils::setDashboardModel()
#ifdef BB10
s->qml->setContextProperty("dashboardModel", dashboardModel);
#else
s->view->rootContext()->setContextProperty("dashboardModel", dashboardModel);
s->context->setContextProperty("dashboardModel", dashboardModel);
#endif
if (oldDashboardModel != NULL)
@ -713,7 +792,7 @@ void Utils::resetFetcher(int type)
#ifdef BB10
s->qml->setContextProperty("fetcher", s->fetcher);
#else
s->view->rootContext()->setContextProperty("fetcher", s->fetcher);
s->context->setContextProperty("fetcher", s->fetcher);
#endif
}

View file

@ -28,7 +28,10 @@
#include <QFileInfo>
#include <QFileInfoList>
#include <QDate>
//#include <QNetworkConfigurationManager>
#ifdef ANDROID
#include <QScreen>
#endif
#ifdef BB10
#include <bb/device/DisplayInfo>
@ -74,9 +77,18 @@ public:
static bool isSameWeek(const QDate &date1, const QDate &date2);
Q_INVOKABLE static void log(const QString &data);
#ifdef ANDROID
Q_INVOKABLE int dp(float value);
Q_INVOKABLE int mm(float value);
Q_INVOKABLE int in(float value);
Q_INVOKABLE int pt(float value);
Q_INVOKABLE int sp(float value);
Q_INVOKABLE void showNotification(const QString &title, const QString &text);
#endif
#ifdef BB10
Q_INVOKABLE bool checkOSVersion(int major, int minor, int patch = 0, int build = 0);
Q_INVOKABLE int du(float value);
Q_INVOKABLE bool checkOSVersion(int major, int minor, int patch = 0, int build = 0);
Q_INVOKABLE bb::cascades::Color background();
Q_INVOKABLE bb::cascades::Color plain();
Q_INVOKABLE bb::cascades::Color plainBase();
@ -84,7 +96,12 @@ public:
Q_INVOKABLE bb::cascades::Color text();
Q_INVOKABLE bb::cascades::Color secondaryText();
Q_INVOKABLE bb::cascades::Color primary();
/*Q_INVOKABLE float primaryTextFontSize();
Q_INVOKABLE QString primaryTextFontFamily();
Q_INVOKABLE float titleTextFontSize();
Q_INVOKABLE QString titleTextFontFamily();*/
Q_INVOKABLE void launchBrowser(const QString &url);
Q_INVOKABLE QString readAsset(const QString &path);
#endif
public slots:
@ -96,6 +113,9 @@ private:
TabModel* tabModel;
DashboardModel* dashboardModel;
//QNetworkConfigurationManager* ncm;
#ifdef ANDROID
QScreen* screen;
#endif
#ifdef BB10
bb::device::DisplayInfo display;
#endif