[Sailfish] Literals update and fixes

This commit is contained in:
Muki 2016-11-19 14:04:10 +01:00
parent 7f99968e7d
commit 4ab1d65775
73 changed files with 1495 additions and 1262 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 868 B

After

Width:  |  Height:  |  Size: 830 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 986 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 924 B

After

Width:  |  Height:  |  Size: 913 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -98,7 +98,7 @@ Page {
MouseArea {
anchors.fill: parent
onClicked: {
notification.show(qsTr("Launching an external browser..."));
notification.show(qsTr("Launching an external browser."));
Qt.openUrlExternally(PAGE);
}
}
@ -129,7 +129,7 @@ Page {
MouseArea {
anchors.fill: parent
onClicked: {
notification.show(qsTr("Launching an external browser..."));
notification.show(qsTr("Launching an external browser."));
Qt.openUrlExternally("https://www.gnu.org/licenses/gpl-3.0.txt");
}
}

View file

@ -48,7 +48,7 @@ Page {
model: ListModel {
ListElement { name: "Netvibes"; iconSource: "nv.png"; type: 1}
ListElement { name: "Old Reader"; iconSource: "oldreader.png"; type: 2}
ListElement { name: "Feedly (comming soon)"; iconSource: "feedly.png"; type: 3}
/*ListElement { name: "Feedly (comming soon)"; iconSource: "feedly.png"; type: 3}*/
}
header: PageHeader {

View file

@ -90,7 +90,7 @@ Page {
onLoadingChanged: {
switch (loadRequest.status) {
case WebView.LoadStartedStatus:
proggressPanel.text = qsTr("Loading page content...");
proggressPanel.text = qsTr("Loading page content");
proggressPanel.open = true;
break;
case WebView.LoadSucceededStatus:
@ -98,7 +98,6 @@ Page {
break;
case WebView.LoadFailedStatus:
proggressPanel.open = false;
//notification.show(qsTr("Failed to load page content :-("));
break;
default:
proggressPanel.open = false;

View file

@ -1,5 +1,5 @@
/*
Copyright (C) 2014 Michal Kosciesza <michal@mkiol.net>
Copyright (C) 2016 Michal Kosciesza <michal@mkiol.net>
This file is part of Kaktus.
@ -50,6 +50,45 @@ Page {
model: VisualItemModel {
SectionHeader {
text: qsTr("Version %1").arg("2.5.0")
}
LogItem {
title: 'Reader View'
description: "Reader View is a feature that strips away clutter like buttons, ads and background images, and changes the page's layout for better readability. Reader View implementation in Kaktus is based on Readability.js library, the same that is used in Firefox browser.";
}
LogItem {
title: 'UI redesign'
description: "Some options were moved from pull down menu to bootom bar and bottom bar has a new dark look.";
}
LogItem {
title: 'Unsynced data indicator'
description: "When Kaktus has any unsynchronized data, indicator (red dot) is shown on the bottom bar.";
}
LogItem {
title: 'Smoother offline mode'
description: "A few bugs were fixed and general offine mode experience has been improved.";
}
LogItem {
title: 'List filtering'
description: "List of articles can be filtered to display all articles, unread and saved or only unread.";
}
LogItem {
title: 'Auto network mode'
description: "Option to automatically enabling offline mode on network connection lost.";
}
LogItem {
title: 'Night View'
description: "Night View reduces the brightness of websites by inverting colors (Heavily inspired and partially borrowed from harbour-webpirate project).";
}
SectionHeader {
text: qsTr("Version %1").arg("2.4.0")
}
@ -169,7 +208,7 @@ Page {
description: 'Many improvements, like performance optimization and UI polishing were made.'
}
SectionHeader {
/*SectionHeader {
text: qsTr("Version %1").arg("1.4")
}
@ -213,7 +252,7 @@ Page {
title: 'Caching only on WiFi'
description: 'Until now you could only enable or disable caching feature. '+
'Now, you can also set caching to start only when phone is connected with WiFi.'
}
}*/
Item {

View file

@ -1,5 +1,5 @@
/*
Copyright (C) 2014 Michal Kosciesza <michal@mkiol.net>
Copyright (C) 2016 Michal Kosciesza <michal@mkiol.net>
This file is part of Kaktus.
@ -25,190 +25,280 @@ Item {
property bool open: false
property bool openable: true
property int showTime: 7000
property int showTime: 5000
// view modes
property bool vmOpen: false
// progress
property bool busy: false
property alias progressText: progressLabel.text
property bool cancelable: true
property real progress: 0.0
signal cancelClicked
// flick show/hide
property real barShowMoveWidth: 20
property real barShowMoveWidthBack: height
property Flickable flick: null
property bool isPortrait: app.orientation==Orientation.Portrait
// other
readonly property bool isPortrait: app.orientation === Orientation.Portrait
readonly property color iconColor: Theme.secondaryColor
readonly property int stdHeight: isPortrait ? Theme.itemSizeMedium : 0.8 * Theme.itemSizeMedium
height: Theme.itemSizeMedium
height: root.stdHeight
width: parent.width
clip: true
onOpenChanged: {
if (!open)
progress = 0.0
}
onBusyChanged: {
//console.log("onBusyChanged:", busy)
open = busy
}
function show() {
if (openable && pageStack.currentPage.showBar) {
if (!open)
root.open = true;
timer.restart();
if (!open) {
root.open = true
root.vmOpen = false
}
timer.restart()
}
}
function showAndEnable() {
openable = true
show();
show()
}
function hide() {
if (open) {
root.open = false;
timer.stop();
if (open && !busy) {
root.open = false
root.vmOpen = false
timer.stop()
}
}
function hideAndDisable() {
hide();
openable = false;
hide()
openable = false
}
Item {
Rectangle {
id: bar
anchors.fill: parent
opacity: root.open ? 1.0 : 0.0
visible: opacity > 0.0
Behavior on opacity { FadeAnimation {duration: 300} }
width: parent.width
height: parent.height
color: "black"
property int off: 5
property int size: vm0b.width + Theme.paddingMedium
clip: true
Rectangle {
id: leftRect
anchors.left: parent.left
anchors.top: parent.top; anchors.bottom: parent.bottom
color: Theme.highlightBackgroundColor
width: settings.viewMode==0 ? 0 :
settings.viewMode==1 ? 1 * bar.size - bar.off :
settings.viewMode==3 ? 2 * bar.size - bar.off :
settings.viewMode==4 ? 3 * bar.size - bar.off :
settings.viewMode==5 ? 4 * bar.size - bar.off :
settings.viewMode==6 ? 4 * bar.size - bar.off :
5 * bar.size
Behavior on width { NumberAnimation { duration: 200;easing.type: Easing.OutQuad } }
}
Rectangle {
id: rightRect
anchors.right: parent.right
anchors.top: parent.top; anchors.bottom: parent.bottom
color: Theme.highlightBackgroundColor
width: settings.viewMode==0 ? root.width - bar.size + bar.off :
settings.viewMode==1 ? root.width - 2 * bar.size + bar.off :
settings.viewMode==3 ? root.width - 3 * bar.size + bar.off :
settings.viewMode==4 ? root.width - 4 * bar.size + bar.off :
settings.viewMode==5 ? root.width - 5 * bar.size + bar.off :
settings.viewMode==6 ? root.width - 5 * bar.size + bar.off :
0
Behavior on width { NumberAnimation { duration: 200;easing.type: Easing.OutQuad } }
}
Rectangle {
anchors.right: rightRect.left; anchors.left: leftRect.right
anchors.bottom: parent.bottom;
height: root.height/10
color: Theme.highlightColor
}
Behavior on y {NumberAnimation { duration: 200; easing.type: Easing.OutQuad }}
y: open ? 0 : height
MouseArea {
enabled: bar.visible
enabled: root.open
anchors.fill: parent
onClicked: root.hide()
}
Item {
property int off: -root.height/10
anchors.left: parent.left; anchors.right: parent.right
anchors.bottom: parent.bottom; height: parent.height
anchors.fill: parent
opacity: root.vmOpen && !root.busy ? 1.0 : 0.0
visible: opacity > 0.0
Behavior on opacity { FadeAnimation {} }
IconButton {
id: vm0b
x: 0*(width+Theme.paddingMedium)
y: ((parent.height-height)/2) + (highlighted ? parent.off : 0)
icon.source: "image://icons/icon-m-vm0?"+Theme.highlightDimmerColor
highlighted: settings.viewMode==0
onClicked: {
show();
if (!app.progress && settings.viewMode!=0) {
app.progress = true;
settings.viewMode = 0;
}
}
}
IconButton {
id: vm1b
x: 1*(width+Theme.paddingMedium)
y: ((parent.height-height)/2) + (highlighted ? parent.off : 0)
icon.source: "image://icons/icon-m-vm1?"+Theme.highlightDimmerColor
highlighted: settings.viewMode==1
onClicked: {
show();
if (!app.progress && settings.viewMode!=1) {
app.progress = true;
settings.viewMode = 1;
}
}
}
IconButton {
id: vm3b
x: 2*(width+Theme.paddingMedium)
y: ((parent.height-height)/2) + (highlighted ? parent.off : 0)
icon.source: "image://icons/icon-m-vm3?"+Theme.highlightDimmerColor
highlighted: settings.viewMode==3
onClicked: {
show();
if (!app.progress && settings.viewMode!=3) {
app.progress = true;
settings.viewMode = 3;
}
}
}
IconButton {
id: vm4b
x: 3*(width+Theme.paddingMedium)
y: ((parent.height-height)/2) + (highlighted ? parent.off : 0)
icon.source: "image://icons/icon-m-vm4?"+Theme.highlightDimmerColor
highlighted: settings.viewMode==4
onClicked: {
show();
if (!app.progress && settings.viewMode!=4) {
app.progress = true;
settings.viewMode = 4;
}
}
}
IconButton {
id: vm5b
x: 4*(width+Theme.paddingMedium)
visible: app.isNetvibes || (app.isOldReader && settings.showBroadcast) // Disabled for Feedly
y: ((parent.height-height)/2) + (highlighted ? parent.off : 0)
icon.source: app.isOldReader ? "image://icons/icon-m-vm6?"+(root.transparent ? Theme.primaryColor : Theme.highlightDimmerColor) :
"image://icons/icon-m-vm5?"+(root.transparent ? Theme.primaryColor : Theme.highlightDimmerColor)
highlighted: settings.viewMode==5 || settings.viewMode==6
onClicked: {
show();
if (!app.progress && (settings.viewMode!=5 || settings.viewMode!=6)) {
app.progress = true;
if (settings.signinType >= 10)
settings.viewMode = 6;
else
settings.viewMode = 5;
}
}
}
IconButton {
visible: pageStack.currentPage.objectName != ""
anchors.right: parent.right; anchors.rightMargin: Theme.paddingSmall
anchors.right: parent.right; anchors.rightMargin: Theme.paddingMedium
anchors.verticalCenter: parent.verticalCenter
icon.source: "image://icons/icon-m-read?"+(root.transparent ? Theme.primaryColor : Theme.highlightDimmerColor)
icon.source: "image://theme/icon-m-dismiss?"+root.iconColor
onClicked: {
show();
show()
root.vmOpen = !root.vmOpen
}
}
Row {
anchors.leftMargin: Theme.paddingMedium
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
spacing: Theme.paddingMedium * 0.8
IconButton {
id: vm0b
anchors.verticalCenter: parent.verticalCenter
icon.source: "image://icons/icon-m-vm0?"+root.iconColor
highlighted: settings.viewMode==0
onClicked: {
show()
root.vmOpen = false
if (!app.progress && settings.viewMode!=0) {
app.progress = true
settings.viewMode = 0
}
}
}
IconButton {
id: vm1b
anchors.verticalCenter: parent.verticalCenter
icon.source: "image://icons/icon-m-vm1?"+root.iconColor
highlighted: settings.viewMode==1
onClicked: {
show()
root.vmOpen = false
if (!app.progress && settings.viewMode!=1) {
app.progress = true
settings.viewMode = 1
}
}
}
IconButton {
id: vm3b
anchors.verticalCenter: parent.verticalCenter
icon.source: "image://icons/icon-m-vm3?"+root.iconColor
highlighted: settings.viewMode==3
onClicked: {
show()
root.vmOpen = false
if (!app.progress && settings.viewMode!=3) {
app.progress = true
settings.viewMode = 3
}
}
}
IconButton {
id: vm4b
anchors.verticalCenter: parent.verticalCenter
icon.source: "image://icons/icon-m-vm4?"+root.iconColor
highlighted: settings.viewMode==4
onClicked: {
show()
root.vmOpen = false
if (!app.progress && settings.viewMode!=4) {
app.progress = true
settings.viewMode = 4
}
}
}
IconButton {
id: vm5b
visible: app.isNetvibes || (app.isOldReader && settings.showBroadcast) // Disabled for Feedly
anchors.verticalCenter: parent.verticalCenter
icon.source: app.isOldReader ? "image://icons/icon-m-vm6?"+root.iconColor :
"image://icons/icon-m-vm5?"+root.iconColor
highlighted: settings.viewMode==5 || settings.viewMode==6
onClicked: {
show()
root.vmOpen = false
if (!app.progress && (settings.viewMode!=5 || settings.viewMode!=6)) {
app.progress = true
if (settings.signinType >= 10)
settings.viewMode = 6
else
settings.viewMode = 5
}
}
}
}
}
Item {
id: menu
anchors.fill: parent
opacity: !root.busy && !root.vmOpen && root.open ? 1.0 : 0.0
visible: opacity > 0.0
Behavior on opacity { FadeAnimation {} }
IconButton {
id: vmIcon
anchors.right: parent.right; anchors.rightMargin: Theme.paddingMedium
anchors.verticalCenter: parent.verticalCenter
//icon.source: "image://theme/icon-m-menu?"+root.iconColor
icon.source: "image://icons/icon-m-vm" + settings.viewMode + "?" + root.iconColor
highlighted: root.vmOpen
onClicked: {
show()
root.vmOpen = !root.vmOpen
}
}
IconButton {
id: refreshIcon
anchors.right: vmIcon.left; anchors.rightMargin: Theme.paddingMedium
anchors.verticalCenter: parent.verticalCenter
icon.source: "image://theme/icon-m-refresh?"+root.iconColor
enabled: !fetcher.busy && !dm.busy && !dm.removerBusy && dm.online
onClicked: {
show()
fetcher.update()
}
Rectangle {
x: parent.height/8
y: parent.width/8
visible: !db.synced
width: Theme.paddingMedium
height: Theme.paddingMedium
radius: Theme.paddingMedium/2
color: "red"
}
}
IconButton {
anchors.right: refreshIcon.left; anchors.rightMargin: Theme.paddingMedium
anchors.verticalCenter: parent.verticalCenter
visible: opacity > 0.0
Behavior on opacity { FadeAnimation {} }
opacity: pageStack.currentPage.objectName === "entries" ? 1.0 : 0.0
icon.source: "image://icons/icon-m-filter-" + settings.filter + "?" + root.iconColor
onClicked: {
show()
settings.filter = settings.filter === 2 ? 0 : settings.filter + 1
}
}
/*IconButton {
id: networkIcon
anchors.left: markallIcon.right; anchors.leftMargin: Theme.paddingMedium
//anchors.left: parent.left; anchors.leftMargin: Theme.paddingMedium
anchors.verticalCenter: parent.verticalCenter
enabled: !settings.offlineMode || (settings.offlineMode && dm.online)
icon.source: "image://theme/icon-m-wlan" + (settings.offlineMode ? "-no-signal" : "") + "?" + root.iconColor
onClicked: {
show()
if (settings.offlineMode) {
if (dm.online)
settings.offlineMode = false;
else
notification.show(qsTr("Can't switch to online mode because network is disconnected."));
} else {
settings.offlineMode = true;
}
}
}*/
IconButton {
id: markallIcon
visible: pageStack.currentPage.objectName != ""
anchors.left: parent.left; anchors.leftMargin: Theme.paddingMedium
//anchors.left: networkIcon.right; anchors.leftMargin: Theme.paddingMedium
anchors.verticalCenter: parent.verticalCenter
icon.source: "image://icons/icon-m-read?"+root.iconColor
onClicked: {
show()
var remorse = pageStack.currentPage.remorse;
var name = pageStack.currentPage.objectName;
if (name == "tabs") {
@ -246,13 +336,79 @@ Item {
}
}
}
Item {
id: progressPanel
anchors.fill: parent
opacity: root.busy && root.open ? 1.0 : 0.0
visible: opacity > 0.0
Behavior on opacity { FadeAnimation {} }
Rectangle {
anchors.bottom: parent.bottom; anchors.top: parent.top
anchors.left: parent.left
width: root.progress * parent.width
/*gradient: Gradient {
GradientStop { position: 0.0; color: Theme.rgba(Theme.highlightColor, 0.4) }
GradientStop { position: 1.0; color: Theme.rgba(Theme.highlightColor, 0.0) }
}*/
color: Theme.highlightDimmerColor
Behavior on width {
SmoothedAnimation {
velocity: 480; duration: 200
}
}
}
Image {
id: progressIcon
height: 0.6*root.stdHeight; width: height
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: Theme.paddingMedium
source: "image://theme/graphic-busyindicator-medium?"+root.iconColor
RotationAnimation on rotation {
loops: Animation.Infinite
from: 0
to: 360
duration: 1200
running: root.busy && Qt.application.active
}
}
Label {
id: progressLabel
height: bar.height
anchors.verticalCenter: parent.verticalCenter
anchors.left: progressIcon.right; anchors.right: root.cancelable ? closeButton.left : parent.right
anchors.leftMargin: Theme.paddingMedium; anchors.rightMargin: Theme.paddingMedium
font.pixelSize: Theme.fontSizeSmall
font.family: Theme.fontFamily
color: root.iconColor
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
}
IconButton {
id: closeButton
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right; anchors.rightMargin: Theme.paddingMedium
icon.source: "image://theme/icon-m-dismiss?"+root.iconColor
onClicked: root.cancelClicked()
visible: root.cancelable
}
}
}
MouseArea {
enabled: !bar.visible && pageStack.currentPage.showBar
enabled: !root.open && pageStack.currentPage.showBar
anchors.bottom: parent.bottom; anchors.left: parent.left; anchors.right: parent.right
height: root.height/2
onClicked: root.show();
height: root.height/3
onClicked: root.show()
}
Timer {

View file

@ -56,7 +56,6 @@ ListItem {
property bool defaultIcon: feedIcon === "http://s.theoldreader.com/icons/user_icon.png"
property color highlightedColor: Theme.rgba(Theme.highlightBackgroundColor, Theme.highlightBackgroundOpacity)
readonly property alias expandable: box.expandable
property bool expandedMode: settings.expandedMode
signal markedAsRead
@ -74,6 +73,11 @@ ListItem {
enabled: !last && !daterow
contentHeight: last ?
app.orientation === Orientation.Portrait ? app.panelHeightPortrait : app.panelHeightLandscape :
daterow ? dateRowbox.height :
box.height + expander.height
onMenuOpenChanged: { if(menuOpen) app.hideBar() }
Component.onCompleted: {
@ -96,11 +100,6 @@ ListItem {
menu: last ? null : settings.iconContextMenu ? iconContextMenu : contextMenu
contentHeight: last ?
app.orientation==Orientation.Portrait ? app.panelHeightPortrait : app.panelHeightLandscape :
daterow ? dateRowbox.height :
box.height + expander.height
onHiddenChanged: {
if (hidden && expanded) {
expanded = false;
@ -309,14 +308,13 @@ ListItem {
fillMode: Image.PreserveAspectFit
width: root.landscapeMode ? 0 : sourceSize.width>=root.width ? root.width : sourceSize.width
enabled: root.landscapeMode ? false : source!="" && status==Image.Ready &&
settings.showTabIcons &&
sourceSize.width > Theme.iconSizeMedium &&
sourceSize.height > Theme.iconSizeMedium
visible: opacity>0
opacity: enabled ? 1.0 : 0.0
Behavior on opacity { FadeAnimation {} }
source: {
if (settings.showTabIcons && root.image!="") {
if (root.image!="") {
return settings.offlineMode ? getUrlbyUrl(root.image) : dm.online ? root.image : getUrlbyUrl(root.image);
} else {
return "";

View file

@ -43,17 +43,10 @@ Page {
property string expandedUid: ""
property int expandedIndex: 0
function navigate(url) {
var hcolor = Theme.highlightColor.toString().substr(1, 6);
var shcolor = Theme.secondaryHighlightColor.toString().substr(1, 6);
var imgWidth = settings.fontSize == 1 ? root.width/(1.5) : settings.fontSize == 2 ? root.width/(2.0) : root.width;
return url+"?fontsize=18px&width="+imgWidth+"&highlightColor="+hcolor+"&secondaryHighlightColor="+shcolor+"&margin="+Theme.paddingMedium;
}
function openInExaternalBrowser(index, link, uid) {
entryModel.setData(index, "read", 1, "");
notification.show(qsTr("Launching an external browser..."));
Qt.openUrlExternally(settings.offlineMode ? navigate(cache.getUrlbyId(uid)) : link);
notification.show(qsTr("Launching an external browser."));
Qt.openUrlExternally(link);
}
function setContentPane(delegate) {
@ -203,8 +196,9 @@ Page {
PageMenu {
id: menu
showAbout: settings.viewMode>2 ? true : false
showShowOnlyUnread: settings.viewMode!=4 && settings.viewMode!=6 && settings.viewMode!=7
//showAbout: settings.viewMode>2 ? true : false
showAbout: true
//showShowOnlyUnread: settings.viewMode!=4 && settings.viewMode!=6 && settings.viewMode!=7
}
header: PageHeader {
@ -261,25 +255,25 @@ Page {
function check() {
// Not allowed while Syncing
if (dm.busy || fetcher.busy || dm.removerBusy) {
notification.show(qsTr("Please wait until current task is complete."));
notification.show(qsTr("Wait until current task is complete."));
return false;
}
// Entry not cached and offline mode enabled
if (settings.offlineMode && !model.cached) {
notification.show(qsTr("Offline version not available."));
notification.show(qsTr("Offline version is not available."));
return false;
}
// Switch to Offline mode if no network
// Switch to offline mode if no network
if (!settings.offlineMode && !dm.online) {
if (model.cached) {
// Entry cached
notification.show(qsTr("Network connection is unavailable.\nSwitching to Offline mode."));
notification.show(qsTr("Enabling offline mode because network is disconnected."));
settings.offlineMode = true;
} else {
// Entry not cached
notification.show(qsTr("Network connection is unavailable."));
notification.show(qsTr("Network is disconnected."));
return false;
}
}
@ -288,24 +282,17 @@ Page {
}
function openEntryInViewer() {
// (!dm.online && settings.offlineMode) -> WORKAROUND for https://github.com/mkiol/kaktus/issues/14
if (!dm.online && settings.offlineMode) {
openInExaternalBrowser(model.index, model.link, model.uid);
return;
}
pageStack.push(Qt.resolvedUrl("WebPreviewPage.qml"),
{"entryId": model.uid,
"onlineUrl": delegate.onlineurl,
"offlineUrl": delegate.offlineurl,
"title": model.title,
"stared": model.readlater==1,
"stared": model.readlater===1,
"liked": model.liked,
"broadcast": model.broadcast,
"index": model.index,
"feedindex": root.index,
"read" : model.read==1,
"read" : model.read===1,
"cached" : model.cached
});
}
@ -313,7 +300,7 @@ Page {
function showEntryFeedContent() {
// Not allowed while Syncing
if (dm.busy || fetcher.busy || dm.removerBusy) {
notification.show(qsTr("Please wait until current task is complete."));
notification.show(qsTr("Wait until current task is complete."));
return false;
}
@ -323,12 +310,12 @@ Page {
"onlineUrl": delegate.onlineurl,
"offlineUrl": delegate.offlineurl,
"title": model.title,
"stared": model.readlater==1,
"stared": model.readlater===1,
"liked": model.liked,
"broadcast": model.broadcast,
"index": model.index,
"feedindex": root.index,
"read" : model.read==1,
"read" : model.read===1,
"cached" : model.cached
});
}
@ -495,7 +482,7 @@ Page {
ViewPlaceholder {
id: placeholder
enabled: listView.count == 0
text: fetcher.busy ? qsTr("Wait until Sync finish.") :
text: fetcher.busy ? qsTr("Wait until sync finish") :
settings.viewMode==4 ? app.isNetvibes || app.isFeedly ? qsTr("No saved items") : qsTr("No starred items") :
settings.viewMode==6 ? qsTr("No liked items") : settings.showOnlyUnread ? qsTr("No unread items") : qsTr("No items")
}

View file

@ -69,14 +69,13 @@ SilicaFlickable {
fillMode: Image.PreserveAspectFit
width: sourceSize.width>=root.width ? root.width : sourceSize.width
enabled: source!="" && status==Image.Ready &&
settings.showTabIcons &&
sourceSize.width > Theme.iconSizeMedium &&
sourceSize.height > Theme.iconSizeMedium
visible: opacity>0
opacity: enabled ? 1.0 : 0.0
Behavior on opacity { FadeAnimation {} }
source: {
if (settings.showTabIcons && root.image!="") {
if (root.image!="") {
return settings.offlineMode ? getUrlbyUrl(root.image) : dm.online ? root.image : getUrlbyUrl(root.image);
} else {
return "";

View file

@ -54,7 +54,7 @@ Page {
function check() {
// Not allowed while Syncing
if (dm.busy || fetcher.busy || dm.removerBusy) {
notification.show(qsTr("Please wait until current task is complete."));
notification.show(qsTr("Wait until current task is complete."));
return false;
}
@ -68,11 +68,11 @@ Page {
if (!settings.offlineMode && !dm.online) {
if (cached) {
// Entry cached
notification.show(qsTr("Network connection is unavailable.\nSwitching to Offline mode."));
notification.show(qsTr("Enabling offline mode because network is disconnected."));
settings.offlineMode = true;
} else {
// Entry not cached
notification.show(qsTr("Network connection is unavailable."));
notification.show(qsTr("Network is disconnected."));
return false;
}
}
@ -82,7 +82,7 @@ Page {
function openEntryInBrowser() {
entryModel.setData(index, "read", 1, "");
notification.show(qsTr("Launching an external browser..."));
notification.show(qsTr("Launching an external browser."));
Qt.openUrlExternally(settings.offlineMode ? offlineUrl : onlineUrl);
}
@ -228,7 +228,7 @@ Page {
}
onClipboardClicked: {
notification.show(qsTr("URL copied to clipboard"));
notification.show(qsTr("URL was copied to the clipboard."));
Clipboard.text = root.onlineUrl;
}
}

View file

@ -43,8 +43,8 @@ Page {
property int index
ActiveDetector {
onActivated: { feedModel.updateFlags();}
onInit: { bar.flick = listView; }
onActivated: { feedModel.updateFlags() }
onInit: { bar.flick = listView }
}
RemorsePopup {
@ -62,7 +62,8 @@ Page {
PageMenu {
id: menu
showAbout: settings.viewMode==2 ? true : false
//showAbout: settings.viewMode==2 ? true : false
showAbout: true
}
header: PageHeader {
@ -194,7 +195,7 @@ Page {
MenuItem {
id: readItem
text: qsTr("Mark all as read")
enabled: model.unread!=0
enabled: model.unread!==0
visible: enabled
onClicked: {
feedModel.markAsRead(model.index);
@ -203,7 +204,7 @@ Page {
MenuItem {
id: unreadItem
text: qsTr("Mark all as unread")
enabled: model.read!=0 && settings.signinType<10
enabled: model.read!==0 && settings.signinType<10
visible: enabled
onClicked: {
feedModel.markAsUnread(model.index);
@ -215,7 +216,7 @@ Page {
ViewPlaceholder {
id: placeholder
enabled: listView.count == 0
text: fetcher.busy ? qsTr("Wait until Sync finish.") : qsTr("No feeds")
text: fetcher.busy ? qsTr("Wait until sync finish") : qsTr("No feeds")
}
VerticalScrollDecorator {

View file

@ -98,7 +98,7 @@ Page {
function check() {
// Not allowed while Syncing
if (dm.busy || fetcher.busy || dm.removerBusy) {
notification.show(qsTr("Please wait until current task is complete."));
notification.show(qsTr("Wait until current task is complete."));
return false;
}
@ -112,11 +112,11 @@ Page {
if (!settings.offlineMode && !dm.online) {
if (cached) {
// Entry cached
notification.show(qsTr("Network connection is unavailable.\nSwitching to offline mode."));
notification.show(qsTr("Enabling offline mode because network is disconnected."));
settings.offlineMode = true;
} else {
// Entry not cached
notification.show(qsTr("Network connection is unavailable."));
notification.show(qsTr("Network is disconnected."));
return false;
}
}
@ -126,12 +126,12 @@ Page {
function openEntryInBrowser() {
entryModel.setData(index, "read", 1, "");
notification.show(qsTr("Launching an external browser..."));
notification.show(qsTr("Launching an external browser."));
Qt.openUrlExternally(settings.offlineMode ? offlineUrl : onlineUrl);
}
function openUrlEntryInBrowser(url) {
notification.show(qsTr("Launching an external browser..."));
notification.show(qsTr("Launching an external browser."));
Qt.openUrlExternally(url);
}
@ -212,6 +212,7 @@ Page {
initTheme()
root.themeApply = false
}
postMessage("readability_apply_fixups")
}
}
@ -239,8 +240,8 @@ Page {
experimental.preferences.javascriptEnabled: true
experimental.preferences.navigatorQtObjectEnabled: true
onLoadingChanged: {
/*console.log("onLoadingChanged:")
/*onLoadingChanged: {
console.log("onLoadingChanged:")
console.log(" url: ", loadRequest.url)
console.log(" status: ", loadRequest.status)
console.log(" error string: ", loadRequest.errorString)
@ -248,8 +249,8 @@ Page {
if (loadRequest.status === WebView.LoadSucceededStatus) {
console.log(" LoadSucceededStatus")
}*/
}
}
}*/
experimental.userScripts: [
Qt.resolvedUrl("js/ObjectOverrider.js"),
@ -269,14 +270,23 @@ Page {
return
}
/*console.log("onNavigationRequested: ")
console.log(" url:",request.url)
console.log(" navigation type:", request.navigationType)
console.log(" navigation LinkClickedNavigation:", request.navigationType === WebView.LinkClickedNavigation)
console.log(" navigation FormSubmittedNavigation:", request.navigationType === WebView.FormSubmittedNavigation)
console.log(" navigation BackForwardNavigation:", request.navigationType === WebView.BackForwardNavigation)
console.log(" navigation ReloadNavigation:", request.navigationType === WebView.ReloadNavigation)
console.log(" navigation FormResubmittedNavigation:", request.navigationType === WebView.FormResubmittedNavigation)
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
}*/
//console.log("request.url: " + request.url)
//console.log("onlineUrl: " + root.onlineUrl)
if (request.url == root.onlineUrl || request.url == root.offlineUrl) {
root.openEntryInViewer()
request.action = WebView.IgnoreRequest
@ -411,6 +421,15 @@ Page {
}
}
IconBarItem {
text: qsTr("Copy URL")
icon: "image://theme/icon-m-clipboard"
onClicked: {
notification.show(qsTr("URL was copied to the clipboard."));
Clipboard.text = root.onlineUrl;
}
}
IconBarItem {
text: qsTr("Increase font")
icon: "image://icons/icon-m-fontup"
@ -426,14 +445,5 @@ Page {
root.updateZoom(-0.1)
}
}
IconBarItem {
text: qsTr("Copy URL")
icon: "image://theme/icon-m-clipboard"
onClicked: {
notification.show(qsTr("URL copied to clipboard"));
Clipboard.text = root.onlineUrl;
}
}
}
}

View file

@ -67,8 +67,8 @@ Page {
id: placeholder
enabled: true
text: settings.signedIn ?
app.fetcherBusyStatus || dm.busy ? qsTr("Wait until Sync finish.") :
qsTr("To do feeds synchronisation, pull down and select Sync.") :
app.fetcherBusyStatus || dm.busy ? qsTr("Wait until sync finish") :
qsTr("To do feeds synchronization, pull down and select sync.") :
qsTr("You are not signed in to any account. Pull down to add one.")
}

View file

@ -28,23 +28,29 @@ Item {
property bool open: false
property bool openable: true
property bool showable: true
property int showTime: 7000
property real barShowMoveWidth: 20
property Flickable flickable: null
property bool shown: opacity == 1.0
width: parent.width
//height: isPortrait ? app.panelHeightPortrait : app.panelHeightLandscape
height: Theme.itemSizeMedium
anchors.bottom: parent.bottom
anchors.left: parent.left
enabled: showable
visible: showable
clip: true
opacity: root.open ? 1.0 : 0.0
Behavior on opacity { FadeAnimation {duration: 300} }
function show() {
if (!showable)
return
if (!open) {
root.open = true;
flick.contentX = 0;
@ -75,6 +81,7 @@ Item {
}
MouseArea {
enabled: root.showable
anchors { left: parent.left; right: parent.right; bottom: parent.bottom }
height: root.open ? parent.height : parent.height / 3
onClicked: root.show();

View file

@ -26,8 +26,11 @@ Item {
property string icon: "image://icons/item"
property alias enabled: iconButton.enabled
property alias text: lbl.text
property string theme: "invert"
//property bool barOpen: parent.open
property string iconColor: theme === "black" ? Theme.primaryColor :
theme === "invert" ? Theme.highlightDimmerColor :
Theme.primaryColor
width: iconButton.width
height: iconButton.height
@ -52,7 +55,7 @@ Item {
horizontalCenter: parent.horizontalCenter
}
color: bar.transparent ? Theme.highlightColor : Theme.highlightDimmerColor
color: iconColor
font.pixelSize: Theme.fontSizeTiny
wrapMode: Text.Wrap
horizontalAlignment: Text.AlignHCenter
@ -60,10 +63,9 @@ Item {
IconButton {
id: iconButton
icon.source: root.icon + "?"+(root.transparent ? Theme.highlightColor : Theme.highlightDimmerColor)
//onClicked: { if (root.barOpen){ root.clicked() } }
//onDownChanged: { if (down && root.barOpen){ root.downed() } }
icon.source: root.icon + "?" + iconColor
onClicked: root.clicked()
onDownChanged: { if (down){ root.downed() } }
enabled: root.enabled
}
}

View file

@ -41,6 +41,7 @@ Item {
property bool highlighted
property alias text: label.text
property alias icon: icon
property string iconSource: "image://icons/icon-m-item"
signal clicked
@ -72,7 +73,7 @@ Item {
Image {
id: icon
source: "image://icons/icon-m-item"
source: parent.iconSource + "?" + (parent.highlighted ? Theme.highlightColor : parent.enabled ? Theme.primaryColor : Theme.secondaryColor)
height: Theme.iconSizeMedium
width: Theme.iconSizeMedium
anchors.right: parent.right

View file

@ -44,15 +44,7 @@ Dialog {
SilicaFlickable {
anchors {left: parent.left; right: parent.right }
anchors {top: parent.top; bottom: parent.bottom }
anchors.bottomMargin: {
var size = 0;
var d = app.orientation===Orientation.Portrait ? app.panelHeightPortrait : app.panelHeightLandscape;
if (bar.open)
size += d;
if (progressPanel.open||progressPanelRemover.open||progressPanelDm.open)
size += d;
return size;
}
anchors.bottomMargin: app.barHeight
clip: true
contentHeight: content.height

View file

@ -43,15 +43,7 @@ Dialog {
SilicaFlickable {
anchors {left: parent.left; right: parent.right }
anchors {top: parent.top; bottom: parent.bottom }
anchors.bottomMargin: {
var size = 0;
var d = app.orientation===Orientation.Portrait ? app.panelHeightPortrait : app.panelHeightLandscape;
if (bar.open)
size += d;
if (progressPanel.open||progressPanelRemover.open||progressPanelDm.open)
size += d;
return size;
}
anchors.bottomMargin: app.barHeight
clip: true
contentHeight: content.height

View file

@ -26,8 +26,8 @@ PullDownMenu {
property bool showAbout: true
property bool showSettings: true
property bool showSync: true
property bool showShowOnlyUnread: false
//property bool showSync: true
//property bool showShowOnlyUnread: false
property bool showNetwork: true
MenuItem {
@ -51,35 +51,36 @@ PullDownMenu {
MenuItem {
text: settings.offlineMode ? qsTr("Network mode: offline") : qsTr("Network mode: online")
visible: root.showNetwork
enabled: !settings.offlineMode || (settings.offlineMode && dm.online)
onClicked: {
if (settings.offlineMode) {
if (dm.online)
settings.offlineMode = false;
else
notification.show(qsTr("Can't switch to Online mode.\nNetwork connection is unavailable."));
notification.show(qsTr("Can't switch to online mode because network is disconnected."));
} else {
settings.offlineMode = true;
}
}
}
MenuItem {
/*MenuItem {
text: settings.showOnlyUnread ? qsTr("Showing: only unread") : qsTr("Showing: all articles")
enabled: root.showShowOnlyUnread
visible: enabled
onClicked: {
settings.showOnlyUnread = !settings.showOnlyUnread;
}
}
}*/
MenuItem {
/*MenuItem {
text: enabled ? qsTr("Sync") : qsTr("Busy...")
visible: root.showSync
onClicked: fetcher.update()
enabled: !fetcher.busy && !dm.busy && !dm.removerBusy
}
}*/
onActiveChanged: {
if (active) {

View file

@ -64,14 +64,6 @@ Item {
color: Theme.highlightBackgroundColor
}
/*Rectangle {
height: 7
anchors.left: parent.left; anchors.top: parent.top
width: parent.width
//color: Theme.rgba(Theme.highlightBackgroundColor, 0.5)
color: Theme.rgba(Theme.highlightDimmerColor, 0.2)
}*/
Image {
anchors.left: parent.left; anchors.right: parent.right
source: "image://theme/graphic-gradient-edge?"+Theme.highlightBackgroundColor
@ -130,7 +122,7 @@ Item {
id: closeButton
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
icon.source: "image://theme/icon-m-close?"+(root.transparent ? Theme.highlightColor : Theme.highlightDimmerColor)
icon.source: "image://theme/icon-m-dismiss?"+(root.transparent ? Theme.highlightColor : Theme.highlightDimmerColor)
onClicked: root.closeClicked()
visible: root.cancelable
}

View file

@ -285,8 +285,8 @@ Page {
currentIndex: settings.offlineMode ? 1 : 0
menu: ContextMenu {
MenuItem { id: onlineMode; text: qsTr("Online") }
MenuItem { id: offlineMode; text: qsTr("Offline") }
MenuIconItem { text: qsTr("Online"); iconSource: "image://theme/icon-m-wlan" }
MenuIconItem { text: qsTr("Offline"); iconSource: "image://theme/icon-m-wlan-no-signal" }
}
onCurrentIndexChanged: {
@ -296,10 +296,21 @@ Page {
settings.offlineMode = true;
}
description: qsTr("In the offline mode, Kaktus will only use local cache to get web pages and images, so "+
description: qsTr("In offline mode, Kaktus will only use local cache to get web pages and images, so "+
"network connection won't be needed.")
}
TextSwitch {
text: qsTr("Auto network mode")
description: qsTr("Network mode will be switched automatically on network connection lost or restore.")
onCheckedChanged: {
settings.autoOffline = checked;
}
Component.onCompleted: {
checked = settings.autoOffline;
}
}
ComboBox {
width: root.width
label: qsTr("Cache articles")
@ -319,6 +330,95 @@ Page {
"and cached for access in the offline mode.")
}
SectionHeader {
text: qsTr("Web viewer")
}
ComboBox {
width: root.width
label: qsTr("Open link behaviour")
currentIndex: settings.webviewNavigation
menu: ContextMenu {
MenuItem { text: qsTr("Disabled") }
MenuIconItem { text: qsTr("External browser"); iconSource: "image://icons/icon-m-browser" }
MenuIconItem { text: qsTr("Web viewer"); iconSource: "image://icons/icon-m-webview" }
}
onCurrentIndexChanged: {
settings.webviewNavigation = currentIndex;
}
description: qsTr("Defines how navigation is handled inside built-in web viewer. Hyperlinks could be disabled, opened in an external browser or opened inside web viewer.")
}
TextSwitchWithIcon {
text: qsTr("Auto switch to Reader View")
description: qsTr("Reader View is a feature that strips away clutter like buttons, ads and background images, and changes the page's layout for better readability. By enabling this option, Reader View will be automatically switch on when page is loaded in the web viewer.")
iconSource: settings.readerMode ? "image://icons/icon-m-reader-selected" : "image://icons/icon-m-reader"
onCheckedChanged: {
settings.readerMode = checked;
}
Component.onCompleted: {
checked = settings.readerMode;
}
}
ComboBox {
width: root.width
label: qsTr("Reader View theme")
description: qsTr("Style of theme which will be used to display articles in Reader View.")
currentIndex: {
if (settings.readerTheme === "dark")
return 0;
if (settings.readerTheme === "light")
return 1;
}
menu: ContextMenu {
MenuItem { text: qsTr("Dark") }
MenuItem { text: qsTr("Light") }
}
onCurrentIndexChanged: {
switch (currentIndex) {
case 0:
settings.readerTheme = "dark";
break;
case 1:
settings.readerTheme = "light";
break;
}
}
}
TextSwitchWithIcon {
text: qsTr("Auto switch to Night View")
description: qsTr("Night View reduces the brightness of websites. By enabling this option, Night View will be automatically switch on when page is loaded in the web viewer.")
iconSource: settings.nightMode ? "image://icons/icon-m-night-selected" : "image://icons/icon-m-night"
onCheckedChanged: {
settings.nightMode = checked;
}
Component.onCompleted: {
checked = settings.nightMode;
}
}
Slider {
width: root.width
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
onClicked: {
// Default value
value = 100;
}
}
SectionHeader {
text: qsTr("UI")
}
@ -504,7 +604,7 @@ Page {
}
}*/
/*ComboBox {
ComboBox {
width: root.width
label: qsTr("View mode")
currentIndex: {
@ -518,16 +618,33 @@ Page {
case 4:
return 3;
case 5:
case 6:
return 4;
}
}
menu: ContextMenu {
MenuItem { text: settings.getSigninType()<10 ? qsTr("Tabs & Feeds") : qsTr("Folders & Feeds") }
MenuItem { text: settings.getSigninType()<10 ? qsTr("Only Folders") : qsTr("Only Folders") }
MenuItem { text: qsTr("All feeds") }
MenuItem { text: settings.getSigninType()<10 ? qsTr("Saved") : qsTr("Starred") }
MenuItem { text: qsTr("Slow") }
MenuIconItem {
text: app.isNetvibes ? qsTr("Tabs, feeds & articles") : qsTr("Folders, feeds & articles")
iconSource: "image://icons/icon-m-vm0"
}
MenuIconItem {
text: app.isNetvibes ? qsTr("Tabs & articles") : qsTr("Folders & articles")
iconSource: "image://icons/icon-m-vm1"
}
MenuIconItem {
text: qsTr("All articles")
iconSource: "image://icons/icon-m-vm3"
}
MenuIconItem {
text: app.isNetvibes || app.isFeedly ? qsTr("Saved") : qsTr("Starred")
iconSource: "image://icons/icon-m-vm4"
}
MenuIconItem {
enabled: app.isNetvibes || (app.isOldReader && settings.showBroadcast)
text: app.isNetvibes ? qsTr("Slow") : qsTr("Liked")
iconSource: app.isNetvibes ? "image://icons/icon-m-vm5" : "image://icons/icon-m-vm6"
}
}
onCurrentIndexChanged: {
@ -541,10 +658,14 @@ Page {
case 3:
settings.viewMode = 4; break;
case 4:
settings.viewMode = 5; break;
if (app.isNetvibes)
settings.viewMode = 5;
else
settings.viewMode = 6;
break;
}
}
}*/
}
ComboBox {
width: root.width
@ -588,37 +709,21 @@ Page {
currentIndex: settings.clickBehavior
menu: ContextMenu {
MenuIconItem { text: qsTr("Built-in viewer"); icon.source: "image://icons/icon-m-webview" }
MenuIconItem { text: qsTr("External browser"); icon.source: "image://icons/icon-m-browser" }
MenuIconItem { text: qsTr("Feed content"); icon.source: "image://icons/icon-m-rss" }
MenuIconItem { text: qsTr("Web viewer"); iconSource: "image://icons/icon-m-webview" }
MenuIconItem { text: qsTr("External browser"); iconSource: "image://icons/icon-m-browser" }
MenuIconItem { text: qsTr("Feed content"); iconSource: "image://icons/icon-m-rss" }
}
onCurrentIndexChanged: {
settings.clickBehavior = currentIndex;
}
description: qsTr("Defines the behavior for clicking on an article item. Article can be opened in the built-in viewer, opened in an external browser or full RSS feed content can be shown.")
description: qsTr("Defines the behavior for clicking on an article item. Article can be opened in the built-in web viewer, opened in an external browser or full RSS feed content can be shown.")
}
ComboBox {
width: root.width
label: qsTr("Open link behaviour")
currentIndex: settings.webviewNavigation
menu: ContextMenu {
MenuItem { text: qsTr("Disabled") }
MenuIconItem { text: qsTr("External browser"); icon.source: "image://icons/icon-m-browser" }
MenuIconItem { text: qsTr("Built-in viewer"); icon.source: "image://icons/icon-m-webview" }
}
onCurrentIndexChanged: {
settings.webviewNavigation = currentIndex;
}
description: qsTr("Defines how navigation is handled inside built-in viewer. Hyperlinks could be disabled, opened in an external browser or opened inside viewer.")
}
TextSwitch {
/*TextSwitch {
text: qsTr("Show only unread articles")
onCheckedChanged: {
settings.showOnlyUnread = checked;
@ -626,62 +731,29 @@ Page {
Component.onCompleted: {
checked = settings.showOnlyUnread;
}
}
TextSwitchWithIcon {
text: qsTr("Auto switch to Reader View")
description: qsTr("Reader View is a feature that strips away clutter like buttons, ads and background images, and changes the page's layout for better readability.")
iconSource: "image://icons/icon-m-reader"
onCheckedChanged: {
settings.readerMode = checked;
}
Component.onCompleted: {
checked = settings.readerMode;
}
}
}*/
ComboBox {
width: root.width
label: qsTr("Reader View theme")
description: qsTr("Style theme which will be used to display articles in Reader View.")
currentIndex: {
if (settings.readerTheme === "dark")
return 0;
if (settings.readerTheme === "light")
return 1;
}
label: qsTr("List filtering")
currentIndex: settings.filter
menu: ContextMenu {
MenuItem { text: qsTr("Dark") }
MenuItem { text: qsTr("Light") }
MenuIconItem { text: qsTr("All articles"); iconSource: "image://icons/icon-m-filter-0" }
MenuIconItem { text: app.isNetvibes || app.isFeedly ? qsTr("Unread or saved") : qsTr("Unread & starred"); iconSource: "image://icons/icon-m-filter-1" }
MenuIconItem { text: qsTr("Only unread"); iconSource: "image://icons/icon-m-filter-2" }
}
onCurrentIndexChanged: {
switch (currentIndex) {
case 0:
settings.readerTheme = "dark";
break;
case 1:
settings.readerTheme = "light";
break;
}
settings.filter = currentIndex;
}
description: app.isNetvibes || app.isFeedly ?
qsTr("List of articles can be filtered to display all articles, unread and saved or only unread.") :
qsTr("List of articles can be filtered to display all articles, unread and starred or only unread.")
}
Slider {
width: root.width
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
onClicked: {
// Default value
value = 100;
}
}
TextSwitch {
text: qsTr("Expanded items")

View file

@ -192,7 +192,7 @@ Page {
MenuItem {
id: readItem
text: qsTr("Mark all as read")
enabled: model.unread!=0
enabled: model.unread!==0
visible: enabled
onClicked: {
tabModel.markAsRead(model.index);
@ -201,7 +201,7 @@ Page {
MenuItem {
id: unreadItem
text: qsTr("Mark all as unread")
enabled: model.read!=0 && settings.signinType<10
enabled: model.read!==0 && settings.signinType<10
visible: enabled
onClicked: {
tabModel.markAsUnread(model.index);
@ -214,7 +214,7 @@ Page {
ViewPlaceholder {
id: placeholder
enabled: listView.count < 1
text: fetcher.busy ? qsTr("Wait until Sync finish.") :
text: fetcher.busy ? qsTr("Wait until sync finish") :
settings.signinType<10 ? qsTr("No tabs") : qsTr("No folders")
}

View file

@ -28,7 +28,6 @@ ApplicationWindow {
property int oldViewMode
property bool isTablet: Screen.sizeCategory === Screen.Large || Screen.sizeCategory === Screen.ExtraLarge
//property bool isTablet: Screen.width > 540
property bool isNetvibes: settings.signinType >= 0 && settings.signinType < 10
property bool isOldReader: settings.signinType >= 10 && settings.signinType < 20
@ -38,6 +37,18 @@ ApplicationWindow {
Component.onCompleted: {
db.init();
if (settings.autoOffline) {
if (dm.online) {
if (settings.offlineMode) {
settings.offlineMode = false
}
} else {
if (!settings.offlineMode) {
settings.offlineMode = true
}
}
}
}
function hideBar() {
@ -57,7 +68,6 @@ ApplicationWindow {
// Reconnect fetcher
if (typeof fetcher === 'undefined') {
var type = settings.signinType;
//console.log("settings.signinType:",type);
if (type < 10)
reconnectFetcher(1);
@ -129,8 +139,8 @@ ApplicationWindow {
fetcher.cancel(); dm.cancel();
db.init();
} else {
if(!settings.helpDone)
guide.showDelayed();
/*if(!settings.helpDone)
guide.showDelayed();*/
}
}
@ -149,7 +159,7 @@ ApplicationWindow {
console.log("DB error! code="+code);
if (code==511) {
notification.show(qsTr("Something went wrong :-(\nRestart the app to rebuild cache data."));
notification.show(qsTr("Restart the app to rebuild cache data."), qsTr("Something went wrong :-("));
return;
}
@ -173,28 +183,40 @@ ApplicationWindow {
target: dm
onProgress: {
if (current > 0 && total != 0) {
progressPanelDm.text = qsTr("Caching... %1 of %2").arg(current).arg(total);
progressPanelDm.progress = current / total;
/*if (current == total) {
progressPanelDm.text = qsTr("All done!");
}*/
} else {
progressPanelDm.text = qsTr("Caching...");
if (!app.fetcherBusyStatus) {
if (current > 0 && total != 0) {
bar.progressText= qsTr("Caching... %1 of %2").arg(current).arg(total);
bar.progress = current / total;
} else {
bar.progressText = qsTr("Caching...");
}
}
}
onOnlineChanged: {
if (settings.autoOffline) {
if (dm.online) {
if (settings.offlineMode) {
//notification.show(qsTr("Enabling online mode because network is connected."));
settings.offlineMode = false
}
} else {
if (!settings.offlineMode) {
//notification.show(qsTr("Enabling offline mode because network is disconnected."));
settings.offlineMode = true
}
}
}
}
onNetworkNotAccessible: {
notification.show(qsTr("Download failed!\nNetwork connection is unavailable."));
notification.show(qsTr("Download has failed because network is disconnected."));
}
onRemoverProgressChanged: {
progressPanelRemover.progress = current / total;
bar.progress = current / total;
bar.progressText = qsTr("Removing cache data... %1 of %2").arg(current).arg(total);
}
/*onError: {
console.log("DM error code:", code);
}*/
}
function reconnectFetcher(type) {
@ -306,75 +328,74 @@ ApplicationWindow {
} else {
// Unknown error
notification.show(qsTr("Something went wrong :-(\nAn unknown error occurred."));
notification.show(qsTr("An unknown error occurred."), qsTr("Something went wrong :-("));
resetView();
}
}
function fetcherErrorCheckingCredentials() {
notification.show(qsTr("The user name or password is incorrect!"));
notification.show(qsTr("The user name or password is incorrect."));
}
function fetcherCredentialsValid() {
notification.show(qsTr("You are signed in!"));
notification.show(qsTr("You are signed in."));
}
function fetcherProgress(current, total) {
//console.log("fetcherProgress", current, total);
progressPanel.text = qsTr("Receiving data... ");
progressPanel.progress = current / total;
bar.progressText = qsTr("Receiving data... ");
bar.progress = current / total;
}
function fetcherUploadProgress(current, total) {
//console.log("fetcherUploadProgress", current, total);
progressPanel.text = qsTr("Sending data...");
progressPanel.progress = current / total;
bar.progressText = qsTr("Sending data...");
bar.progress = current / total;
}
function fetcherUploading() {
//console.log("fetcherUploading");
progressPanel.text = qsTr("Sending data...");
bar.progressText = qsTr("Sending data...");
}
function fetcherBusyChanged() {
console.log("fetcherBusyChanged:", fetcher.busy, app.fetcherBusyStatus)
if (app.fetcherBusyStatus != fetcher.busy)
app.fetcherBusyStatus = fetcher.busy;
switch(fetcher.busyType) {
case 1:
progressPanel.text = qsTr("Initiating...");
progressPanel.progress = 0;
bar.progressText = qsTr("Initiating...");
bar.progress = 0;
break;
case 2:
progressPanel.text = qsTr("Updating...");
progressPanel.progress = 0;
bar.progressText = qsTr("Updating...");
bar.progress = 0;
break;
case 3:
progressPanel.text = qsTr("Signing in...");
progressPanel.progress = 0;
bar.progressText = qsTr("Signing in...");
bar.progress = 0;
break;
case 4:
progressPanel.text = qsTr("Signing in...");
progressPanel.progress = 0;
bar.progressText = qsTr("Signing in...");
bar.progress = 0;
break;
case 11:
progressPanel.text = qsTr("Waiting for network...");
progressPanel.progress = 0;
bar.progressText = qsTr("Waiting for network...");
bar.progress = 0;
break;
case 21:
progressPanel.text = qsTr("Waiting for network...");
progressPanel.progress = 0;
bar.progressText = qsTr("Waiting for network...");
bar.progress = 0;
break;
case 31:
progressPanel.text = qsTr("Waiting for network...");
progressPanel.progress = 0;
bar.progressText = qsTr("Waiting for network...");
bar.progress = 0;
break;
}
}
function fetcherCanceled() {
//notification.show(qsTr("Syncing canceled!"));
resetView();
}
@ -382,103 +403,42 @@ ApplicationWindow {
id: notification
}
property int panelHeightPortrait: Theme.itemSizeMedium
property int panelHeightLandscape: Theme.itemSizeMedium
property int barHeightPortrait: Theme.itemSizeMedium
property int barHeightLandscape: Theme.itemSizeMedium
property int panelHeight: app.orientation==Orientation.Portrait ? app.panelHeightPortrait : app.panelHeightLandscape
property int panelWidth: app.orientation==Orientation.Portrait ? Screen.width : Screen.height
property int barHeight: app.orientation==Orientation.Portrait ? app.barHeightPortrait : app.barHeightLandscape
property int barWidth: app.orientation==Orientation.Portrait ? Screen.width : Screen.height
property int landscapeContentPanelWidth: isTablet ?
app.orientation==Orientation.Portrait ? Screen.width-700 : Screen.height-700 :
app.orientation==Orientation.Portrait ? Screen.width/2 : Screen.height/2
app.orientation==Orientation.Portrait ? Screen.width-700 : Screen.height-700 :
app.orientation==Orientation.Portrait ? Screen.width/2 : Screen.height/2
property int flickHeight: {
var size = 0;
var size = 0
if (bar.open)
size += barHeight;
if (progressPanel.open||progressPanelRemover.open||progressPanelDm.open)
size += panelHeight;
size += bar.stdHeight
return app.orientation==Orientation.Portrait ? Screen.height-size : Screen.width-size;
}
property int barX: {
if (app.orientation==Orientation.Portrait)
return 0;
if (bar.open && (progressPanel.open||progressPanelRemover.open||progressPanelDm.open))
return app.barHeightLandscape + app.panelHeightLandscape;
return app.barHeightLandscape;
}
property int barY: {
if (app.orientation==Orientation.Portrait) {
if (bar.open && (progressPanel.open||progressPanelRemover.open||progressPanelDm.open))
return Screen.height - (app.barHeightPortrait + app.panelHeightPortrait);
return Screen.height - app.barHeightPortrait;
}
return 0;
}
property int panelX: app.orientation==Orientation.Portrait ? 0 : app.panelHeight
property int panelY: app.orientation==Orientation.Portrait ? Screen.height-app.panelHeight : 0
property int barX: app.orientation==Orientation.Portrait ? 0 : bar.height
property int barY: app.orientation==Orientation.Portrait ? Screen.height - bar.height : 0
readonly property alias barHeight: bar.height
ControlBar {
id: bar
busy: app.fetcherBusyStatus || dm.removerBusy || dm.busy
rotation: app.orientation==Orientation.Portrait ? 0 : 90
transformOrigin: Item.TopLeft
height: app.barHeight
width: app.barWidth
width: app.panelWidth
onCancelClicked: {
dm.cancel()
fetcher.cancel()
dm.removerCancel()
}
onBusyChanged: {
if (!busy)
hide()
}
y: app.barY
x: app.barX
}
ProgressPanel {
id: progressPanelRemover
open: dm.removerBusy
onCloseClicked: dm.removerCancel();
transparent: false
rotation: app.orientation==Orientation.Portrait ? 0 : 90
transformOrigin: Item.TopLeft
height: app.panelHeight
width: app.panelWidth
y: app.panelY
x: app.panelX
text: qsTr("Removing cache data...");
Behavior on y { NumberAnimation { duration: 200;easing.type: Easing.OutQuad } }
Behavior on x { NumberAnimation { duration: 200;easing.type: Easing.OutQuad } }
}
ProgressPanel {
id: progressPanelDm
open: dm.busy && !app.fetcherBusyStatus
onCloseClicked: dm.cancel();
transparent: false
rotation: app.orientation==Orientation.Portrait ? 0 : 90
transformOrigin: Item.TopLeft
height: app.panelHeight
width: app.panelWidth
y: app.panelY
x: app.panelX
Behavior on y { NumberAnimation { duration: 200;easing.type: Easing.OutQuad } }
Behavior on x { NumberAnimation { duration: 200;easing.type: Easing.OutQuad } }
}
ProgressPanel {
id: progressPanel
open: app.fetcherBusyStatus
onCloseClicked: fetcher.cancel();
transparent: false
rotation: app.orientation==Orientation.Portrait ? 0 : 90
transformOrigin: Item.TopLeft
height: app.panelHeight
width: app.panelWidth
y: app.panelY
x: app.panelX
Behavior on y { NumberAnimation { duration: 200;easing.type: Easing.OutQuad } }
Behavior on x { NumberAnimation { duration: 200;easing.type: Easing.OutQuad } }
}
Guide {
id: guide

View file

@ -23,10 +23,6 @@
#include <QFile>
#include <QDebug>
//#include <QWebPage>
//#include <QWebFrame>
//#include <QWebElement>
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QUrlQuery>
#endif
@ -196,70 +192,16 @@ bool FilteringWorker::filterArticle()
return true;
}
/*void FilteringWorker::advancedFilter()
{
QUrl url(item.baseUrl);
if (url.host().contains("reddit.com")) {
QWebPage page;
QWebFrame *frame = page.mainFrame();
frame->setHtml(content);
QWebElement el1 = frame->findFirstElement("div[role='banner']");
if (!el1.isNull())
el1.removeFromDocument();
content = frame->toHtml();
return;
}
qDebug() << "-2";
if (url.host().contains("lightreading.com")) {
QWebPage page;
qDebug() << "-1";
QWebFrame *frame = page.mainFrame();
frame->setHtml(content);
qDebug() << "0";
QWebElement el1 = frame->findFirstElement("article");
if (!el1.isNull()) {
qDebug() << "1";
QWebElement el2 = frame->findFirstElement("div[name='msgqueue']");
QWebElement body = frame->findFirstElement("body");
if (!body.isNull()) {
qDebug() << "2";
body.removeFromDocument();
QWebElement head = frame->findFirstElement("head");
head.appendOutside(el2);
head.appendOutside(el1);
content = frame->toHtml();
}
}
return;
}
}*/
void FilteringWorker::filter()
{
QUrl url(item.baseUrl);
bool dofilterArticle = true;
if (url.host().contains("engadget.com")) {
dofilterArticle = false;
}
if (dofilterArticle)
filterArticle();
QRegExp rxLinkAll("<link[^>]*>", Qt::CaseInsensitive);
QRegExp rxScriptAll("<script[^>]*>((?!<\\/script>).)*<\\/script>", Qt::CaseInsensitive);
QRegExp rxStyleAll("<style[^>]*>((?!<\\/style>).)*<\\/style>", Qt::CaseInsensitive);
QRegExp rxStyle("\\s*style\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
QRegExp rxClass("\\s*class\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
//QRegExp rxId("\\s*id\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
QRegExp rxWidth("\\s*width\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
QRegExp rxHeight("\\s*height\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
QRegExp rxMetaViewport("<meta\\s[^>]*name\\s*=(\"viewport\"|'viewport')[^>]*>", Qt::CaseInsensitive);
//QRegExp rxMetaAll("<meta[^>]*>", Qt::CaseInsensitive);
//QRegExp rxFormAll("<form[^>]*>((?!<\\/form>).)*<\\/form>", Qt::CaseInsensitive);
QRegExp rxInputAll("<input[^>]*>", Qt::CaseInsensitive);
QRegExp rxTextareaAll("<textarea[^>]*>((?!<\\/textarea>).)*<\\/textarea>", Qt::CaseInsensitive);
QRegExp rxObjectAll("<object[^>]*>((?!<\\/object>).)*<\\/object>", Qt::CaseInsensitive);
@ -283,79 +225,30 @@ void FilteringWorker::filter()
content.remove(rxNoscriptAll);
content.remove(rxSelectAll);
content.remove(rxNavAll);
// Applying Theme's style
QUrl query = req->url();
Settings *s = Settings::instance();
QString style, fontsize, highlightColor, secondaryHighlightColor;
int margin = 0;
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
QUrlQuery urlQuery(query);
if (urlQuery.hasQueryItem("fontsize"))
fontsize = urlQuery.queryItemValue("fontsize");
if (urlQuery.hasQueryItem("highlightColor"))
highlightColor = urlQuery.queryItemValue("highlightColor");
if (urlQuery.hasQueryItem("secondaryHighlightColor"))
secondaryHighlightColor = urlQuery.queryItemValue("secondaryHighlightColor");
if (urlQuery.hasQueryItem("margin"))
margin = urlQuery.queryItemValue("margin").toInt();
#else
if (query.hasQueryItem("fontsize"))
fontsize= query.queryItemValue("fontsize");
if (query.hasQueryItem("highlightColor"))
highlightColor = query.queryItemValue("highlightColor");
if (query.hasQueryItem("secondaryHighlightColor"))
secondaryHighlightColor = query.queryItemValue("secondaryHighlightColor");
if (query.hasQueryItem("margin"))
margin = query.queryItemValue("margin").toInt();
#endif
QString initialScale = "1.0";
if (s->getOfflineTheme() == "white") {
style = QString("<meta name='viewport' content='initial-scale=%6'>"
"<style>a,h1,h2,h3,div,p,pre,code{word-wrap:break-word}body{margin:%5px;background:#FFF;font-family:sans-serif;font-size:%1;color:#323232;}figure{margin:0;padding:0;}a:link{color:#%2;}a:visited{color:#%4;}a:active{color:#%3;}img{max-width:100%;max-height:device-height;}</style></head>")
.arg(fontsize).arg(highlightColor).arg(highlightColor).arg(secondaryHighlightColor).arg(margin).arg(initialScale);
}
if (s->getOfflineTheme() == "black") {
style = QString("<meta name='viewport' content='initial-scale=%6'>"
"<style>a,h1,h2,h3,div,p,pre,code{word-wrap:break-word}body{margin:%5px;background:#141414;font-family:sans-serif;font-size:%1;color:#FFF;}figure{margin:0;padding:0;}a:link{color:#%2;}a:visited{color:#%4;}a:active{color:#%3;}img{max-width:100%;max-height:device-height;}</style></head>")
.arg(fontsize).arg(highlightColor).arg(highlightColor).arg(secondaryHighlightColor).arg(margin).arg(initialScale);
//qDebug() << style;
}
QRegExp rxHeadEnd("</head>", Qt::CaseInsensitive);
content.replace(rxHeadEnd,style);
}
void FilteringWorker::filterOnline()
{
filter();
//advancedFilter();
//QRegExp rxCss("<link\\s[^>]*rel\\s*=(\"stylesheet\"|'stylesheet')[^>]*href\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
QRegExp rxImg("(<img\\s[^>]*)src\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
resolveRelativeUrls(rxImg);
QRegExp rxA("(<a\\s[^>]*)href\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
resolveRelativeUrls(rxA);
//QRegExp rxImg("(<img\\s[^>]*)src\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
//resolveRelativeUrls(rxImg);
//QRegExp rxA("(<a\\s[^>]*)href\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
//resolveRelativeUrls(rxA);
}
void FilteringWorker::filterOffline()
{
filter();
//QRegExp rxMetaAll("<meta[^>]*>", Qt::CaseInsensitive);
//QRegExp rxA("(<a\\s[^>]*)href\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
QRegExp rxUrl("url[\\s]*\\([^\\)]*\\)", Qt::CaseInsensitive);
QRegExp rxImgAll("<img[^>]*>", Qt::CaseInsensitive);
QRegExp rxFrame("(<iframe\\s[^>]*)src\\s*=\\s*(\"[^\"]*\"|'[^']*')", Qt::CaseInsensitive);
QRegExp rxBody("(<body[^>]*>)", Qt::CaseInsensitive);
//content.replace(rxA,"\\1href='#'");
//removeUrls(content, rxA);
content.replace(rxUrl,"http://0.0.0.0");
content.replace(rxImgAll,"");
content.replace(rxImgAll,""); content.remove("</img>", Qt::CaseInsensitive);
content.replace(rxFrame,"\\1");
// Inserting image after <body> tag
@ -363,8 +256,12 @@ void FilteringWorker::filterOffline()
QString image = "";
if(item.entryId!="")
image = s->db->readEntryImageById(item.entryId);
if (image!="") {
content.replace(rxBody,QString("\\1<img src=\"%1\"/>").arg(s->cache->getUrlbyUrl(image)));
if (!image.isEmpty()) {
image = QString(CacheServer::getDataUrlByUrl(image));
if (!image.isEmpty()) {
content.replace(rxBody,QString("\\1<img id='_kaktus_img' src='%1'/>")
.arg(image));
}
}
}
@ -524,65 +421,8 @@ void CacheServer::handleFinish()
delete(worker);
}
/*#define HOST_FILTER 0x01 // => 0001
#define REMOVE_FILTER 0x02 // => 0010
void CacheServer::resolveRelativeUrls(QString &content, const QRegExp &rx, const QUrl &baseUrl, int filter)
{
QStringList list = baseUrl.host().split(".");
QString baseHost = list.at(list.length()-2);
int i = 1, pos = 0;
QStringList caps;
while ((pos = rx.indexIn(content, pos)) != -1) {
QString cap = rx.cap(2); cap = cap.mid(1,cap.length()-2);
caps.append(cap);
pos += rx.matchedLength();
++i;
}
//qDebug() << filter << (filter & REMOVE_FILTER) ;
QStringList::iterator it = caps.begin();
while (it != caps.end()) {
QString cap = *it;
QUrl capUrl(cap);
if ((filter & REMOVE_FILTER) != 0) {
content.replace(cap, "");
qDebug() << "removed cap=" << cap;
} else if (capUrl.isRelative()) {
content.replace(cap, baseUrl.resolved(capUrl).toString());
} else {
qDebug() << "filter, host=" << capUrl.host() << "base host=" << baseUrl.host();
if ((filter & HOST_FILTER) != 0) {
// Host filter => Removing URL if host not match base URL's host
list = capUrl.host().split(".");
if (list.length()>1) {
QString capHost = list.at(list.length()-2);
qDebug() << "filter, capHost=" << capHost << "baseHost=" << baseHost;
if (capHost!=baseHost) {
qDebug() << "replace";
content.replace(cap, "");
}
}
}
}
++it;
}
}*/
/*QString CacheServer::hash(const QString &url)
{
QByteArray data; data.append(url);
return QString(QCryptographicHash::hash(data, QCryptographicHash::Md5).toHex());
}*/
QString CacheServer::getUrlbyId(const QString &item)
{
//return "http://127.0.0.1:" + QString::number(port) + "/" + item;
return "http://localhost:" + QString::number(port) + "/" + item;
}
@ -595,10 +435,33 @@ QString CacheServer::getUrlbyUrl(const QString &url)
return url;
}
//return "http://127.0.0.1:" + QString::number(port) + "/" + Utils::hash(url);
return "http://localhost:" + QString::number(port) + "/" + Utils::hash(url);
}
QByteArray CacheServer::getDataUrlByUrl(const QString &url)
{
Settings *s = Settings::instance();
QString entryId = Utils::hash(url);
DatabaseManager::CacheItem item = s->db->readCacheByEntry(entryId);
QString filename;
if (item.id == "") {
item = s->db->readCacheByFinalUrl(entryId);
filename = entryId;
} else {
filename = item.finalUrl;
}
QByteArray data;
if (!CacheServer::readFile(filename, data)) {
return QByteArray();
}
QStringList ct = item.contentType.split(';');
return QString("data:"+ct[0]+";base64,").toUtf8() + data.toBase64();
}
QString CacheServer::getCacheUrlbyUrl(const QString &url)
{
// If url is "image://" will not be hashed

View file

@ -69,13 +69,13 @@ class CacheServer : public QObject
public:
static bool readFile(const QString &filename, QByteArray &data);
static QString getFileUrl(const QString &id);
static QByteArray getDataUrlByUrl(const QString &item);
explicit CacheServer(QObject *parent = 0);
~CacheServer();
Q_INVOKABLE QString getUrlbyId(const QString &item);
Q_INVOKABLE QString getUrlbyUrl(const QString &item);
Q_INVOKABLE QString getCacheUrlbyUrl(const QString &item);
//Q_INVOKABLE QByteArray getData(const QString &id);
public slots:
void handle(QHttpRequest *req, QHttpResponse *resp);

File diff suppressed because it is too large Load diff

View file

@ -34,11 +34,16 @@
#include "settings.h"
class DatabaseManager : public QObject
{
Q_OBJECT
Q_PROPERTY (bool synced READ isSynced NOTIFY syncedChanged)
public:
static const int version = 23;
static const int dashboardsLimit = 100;
static const int tabsLimit = 100;
static const int streamLimit = 100;
@ -172,6 +177,8 @@ public:
Q_INVOKABLE void init();
Q_INVOKABLE void newInit();
bool isSynced();
void cleanDashboards();
void cleanTabs();
void cleanModules();
@ -235,7 +242,9 @@ public:
QList<Entry> readEntriesByDashboard(const QString &id, int offset, int limit, bool ascOrder = false);
QList<Entry> readEntriesUnreadByDashboard(const QString &id, int offset, int limit, bool ascOrder = false);
QList<Entry> readEntriesUnreadAndSavedByDashboard(const QString &id, int offset, int limit, bool ascOrder = false);
QList<Entry> readEntriesSlowUnreadByDashboard(const QString &id, int offset, int limit, bool ascOrder = false);
QList<Entry> readEntriesSlowUnreadAndSavedByDashboard(const QString &id, int offset, int limit, bool ascOrder = false);
QList<Entry> readEntriesSavedByDashboard(const QString &id, int offset, int limit, bool ascOrder = false);
//QList<Entry> readEntriesSaved(int offset, int limit, bool ascOrder = false);
QList<Entry> readEntriesSlowByDashboard(const QString &id, int offset, int limit, bool ascOrder = false);
@ -243,8 +252,10 @@ public:
QList<Entry> readEntriesBroadcastByDashboard(const QString &id, int offset, int limit, bool ascOrder = false);
QList<Entry> readEntriesByStream(const QString &id, int offset, int limit, bool ascOrder = false);
QList<Entry> readEntriesUnreadByStream(const QString &id, int offset, int limit, bool ascOrder = false);
QList<Entry> readEntriesUnreadAndSavedByStream(const QString &id, int offset, int limit, bool ascOrder = false);
QList<Entry> readEntriesByTab(const QString &id, int offset, int limit, bool ascOrder = false);
QList<Entry> readEntriesUnreadByTab(const QString &id, int offset, int limit, bool ascOrder = false);
QList<Entry> readEntriesUnreadAndSavedByTab(const QString &id, int offset, int limit, bool ascOrder = false);
QList<Entry> readEntriesCachedOlderThan(int cacheDate, int limit);
QList<QString> readCacheFinalUrlOlderThan(int cacheDate, int limit);
QList<QString> readCacheIdsOlderThan(int cacheDate, int limit);
@ -320,8 +331,9 @@ signals:
void empty();
void notEmpty();
void syncedChanged();
private:
static const QString version;
QSqlDatabase db;
QString dbFilePath;
@ -329,9 +341,9 @@ private:
bool openDB();
bool createDB();
bool alterDB_19to22();
bool alterDB_20to22();
bool alterDB_21to22();
//bool alterDB_19to22();
//bool alterDB_20to22();
//bool alterDB_21to22();
bool deleteDB();
bool createStructure();

View file

@ -29,14 +29,42 @@
#include "entrymodel.h"
#include "utils.h"
EntryModelIniter::EntryModelIniter(QObject *parent) :
QThread(parent), feedId()
{}
void EntryModelIniter::init(EntryModel *model)
{
this->model = model;
this->feedId.clear();
this->start(QThread::LowestPriority);
}
void EntryModelIniter::init(EntryModel *model, const QString &feedId)
{
this->model = model;
this->feedId = feedId;
this->start(QThread::LowestPriority);
}
void EntryModelIniter::run()
{
if (feedId.isEmpty())
this->model->init();
else
this->model->init(feedId);
}
EntryModel::EntryModel(DatabaseManager *db, QObject *parent) :
ListModel(new EntryItem, parent)
ListModel(new EntryItem, parent), initer(parent)
{
_db = db;
reInit = false;
Settings *s = Settings::instance();
connect(s,SIGNAL(showOnlyUnreadChanged()),this,SLOT(init()));
connect(s,SIGNAL(filterChanged()),this,SLOT(initInThread()));
connect(&initer,SIGNAL(finished()),this,SLOT(initFinished()));
connect(s,SIGNAL(showOldestFirstChanged()),this,SLOT(init()));
}
@ -57,6 +85,22 @@ void EntryModel::init()
emit ready();
}
void EntryModel::initInThread(const QString &feedId)
{
this->initer.init(this, feedId);
}
void EntryModel::initInThread()
{
this->initer.init(this);
}
void EntryModel::initFinished()
{
this->beginResetModel();
this->endResetModel();
}
/*int EntryModel::fixIndex(const QString &id)
{
int l = this->rowCount();
@ -119,29 +163,37 @@ int EntryModel::createItems(int offset, int limit)
switch (mode) {
case 0:
// View mode: Tabs->Feeds->Entries
if (s->getShowOnlyUnread())
if (s->getFilter() == 2)
list = _db->readEntriesUnreadByStream(_feedId,offset,limit,ascOrder);
else if (s->getFilter() == 1)
list = _db->readEntriesUnreadAndSavedByStream(_feedId,offset,limit,ascOrder);
else
list = _db->readEntriesByStream(_feedId,offset,limit,ascOrder);
break;
case 1:
// View mode: Tabs->Entries
if (s->getShowOnlyUnread())
if (s->getFilter() == 2)
list = _db->readEntriesUnreadByTab(_feedId,offset,limit,ascOrder);
else if (s->getFilter() == 1)
list = _db->readEntriesUnreadAndSavedByTab(_feedId,offset,limit,ascOrder);
else
list = _db->readEntriesByTab(_feedId,offset,limit,ascOrder);
break;
case 2:
// View mode: Feeds->Entries
if (s->getShowOnlyUnread())
if (s->getFilter() == 2)
list = _db->readEntriesUnreadByStream(_feedId,offset,limit,ascOrder);
else if (s->getFilter() == 1)
list = _db->readEntriesUnreadAndSavedByStream(_feedId,offset,limit,ascOrder);
else
list = _db->readEntriesByStream(_feedId,offset,limit,ascOrder);
break;
case 3:
// View mode: Entries
if (s->getShowOnlyUnread())
if (s->getFilter() == 2)
list = _db->readEntriesUnreadByDashboard(s->getDashboardInUse(),offset,limit,ascOrder);
else if (s->getFilter() == 1)
list = _db->readEntriesUnreadAndSavedByDashboard(s->getDashboardInUse(),offset,limit,ascOrder);
else
list = _db->readEntriesByDashboard(s->getDashboardInUse(),offset,limit,ascOrder);
break;
@ -151,8 +203,10 @@ int EntryModel::createItems(int offset, int limit)
break;
case 5:
// View mode: Slow
if (s->getShowOnlyUnread())
if (s->getFilter() == 2)
list = _db->readEntriesSlowUnreadByDashboard(s->getDashboardInUse(),offset,limit,ascOrder);
else if (s->getFilter() == 1)
list = _db->readEntriesSlowUnreadAndSavedByDashboard(s->getDashboardInUse(),offset,limit,ascOrder);
else
list = _db->readEntriesSlowByDashboard(s->getDashboardInUse(),offset,limit,ascOrder);
break;

View file

@ -25,11 +25,29 @@
#include <QByteArray>
#include <QVariant>
#include <QHash>
#include <QThread>
#include "listmodel.h"
#include "feedmodel.h"
#include "databasemanager.h"
class EntryModel;
class EntryModelIniter : public QThread
{
Q_OBJECT
public:
EntryModelIniter(QObject *parent = 0);
void init(EntryModel *model);
void init(EntryModel *model, const QString &feedId);
private:
QString feedId;
EntryModel *model;
void run();
};
class EntryItem : public ListItem
{
Q_OBJECT
@ -139,6 +157,7 @@ public:
explicit EntryModel(DatabaseManager* db, QObject *parent = 0);
void init(const QString &feedId);
void initInThread(const QString &feedId);
Q_INVOKABLE void setData(int row, const QString &fieldName, QVariant newValue, QVariant newValue2);
@ -156,6 +175,8 @@ public:
public slots:
void init();
void initInThread();
void initFinished();
signals:
void ready();
@ -164,6 +185,7 @@ private:
static const int idsOnActionLimit = 100;
DatabaseManager* _db;
QString _feedId;
EntryModelIniter initer;
int getDateRowId(int date);
};

View file

@ -14,7 +14,7 @@ IconProvider::IconProvider() : QQuickImageProvider(QQuickImageProvider::Pixmap)
//qDebug() << "ratio:" << ratio;
if (ratio == 0) {
qWarning() << "Pixel ratio is 0, defaulting to 1.0.";
themeDir = SailfishApp::pathTo("images/z1.5").toString(QUrl::RemoveScheme);
themeDir = SailfishApp::pathTo("images/z1.0").toString(QUrl::RemoveScheme);
} else if (ratio == 1.0) {
themeDir = SailfishApp::pathTo("images/z1.0").toString(QUrl::RemoveScheme);
} else if (ratio == 1.25) {

View file

@ -39,9 +39,9 @@ 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.4.0 (light edition)";
static const char *VERSION = "2.5.0 (light edition)";
#else
static const char *VERSION = "2.4.0";
static const char *VERSION = "2.5.0";
#endif
int main(int argc, char *argv[])
@ -61,6 +61,7 @@ int main(int argc, char *argv[])
view->engine()->addImageProvider(QLatin1String("nvicons"), new NvIconProvider);
qRegisterMetaType<DatabaseManager::CacheItem>("CacheItem");
//qmlRegisterMetaType<QQmlChangeSet>()
Settings* settings = Settings::instance();

View file

@ -473,7 +473,7 @@ void Utils::setEntryModel(const QString &feedId)
Settings *s = Settings::instance();
entryModel = new EntryModel(s->db);
entryModel->init(feedId);
entryModel->initInThread(feedId);
#ifdef BB10
s->qml->setContextProperty("entryModel", entryModel);