Margini alto/basso (Settings.readerMarginV) + applicazione a caldo senza reload: i margini si sovrascrivono via runJavaScript (setProperty !important) sul documento aperto, anteprima live nel dialogo e al ritorno dalle impostazioni
This commit is contained in:
+40
-10
@@ -1,13 +1,22 @@
|
|||||||
import QtQuick 2.0
|
import QtQuick 2.0
|
||||||
import Sailfish.Silica 1.0
|
import Sailfish.Silica 1.0
|
||||||
|
|
||||||
// Regola i margini laterali del testo nel lettore senza uscire dal libro.
|
// Regola i margini del testo nel lettore senza uscire dal libro.
|
||||||
// Il valore viene applicato all'accettazione; il capitolo aperto si ricarica
|
// Anteprima LIVE: ogni variazione degli slider viene inoltrata al lettore via
|
||||||
// con il nuovo margine (il chiamante si occupa del reload).
|
// previewHandler (runJavaScript sul documento aperto), quindi il testo si
|
||||||
|
// adatta subito. I valori vengono persistiti solo all'accettazione.
|
||||||
Dialog {
|
Dialog {
|
||||||
id: dialog
|
id: dialog
|
||||||
|
|
||||||
property int marginValue: 24
|
property int marginLr: 24
|
||||||
|
property int marginTb: 0
|
||||||
|
// funzione chiamata a ogni variazione: previewHandler(marginLr, marginTb)
|
||||||
|
property var previewHandler: null
|
||||||
|
|
||||||
|
function preview() {
|
||||||
|
if (dialog.previewHandler)
|
||||||
|
dialog.previewHandler(dialog.marginLr, dialog.marginTb)
|
||||||
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@@ -18,26 +27,47 @@ Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Slider {
|
Slider {
|
||||||
id: marginSlider
|
id: lrSlider
|
||||||
width: parent.width
|
width: parent.width
|
||||||
label: "Margine laterale"
|
label: "Margini laterali"
|
||||||
minimumValue: 0
|
minimumValue: 0
|
||||||
maximumValue: 80
|
maximumValue: 80
|
||||||
stepSize: 4
|
stepSize: 4
|
||||||
value: dialog.marginValue
|
value: dialog.marginLr
|
||||||
valueText: value + " px"
|
valueText: value + " px"
|
||||||
onValueChanged: dialog.marginValue = value
|
onValueChanged: {
|
||||||
|
dialog.marginLr = value
|
||||||
|
dialog.preview()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Slider {
|
||||||
|
id: tbSlider
|
||||||
|
width: parent.width
|
||||||
|
label: "Alto e basso"
|
||||||
|
minimumValue: 0
|
||||||
|
maximumValue: 80
|
||||||
|
stepSize: 4
|
||||||
|
value: dialog.marginTb
|
||||||
|
valueText: value + " px"
|
||||||
|
onValueChanged: {
|
||||||
|
dialog.marginTb = value
|
||||||
|
dialog.preview()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
x: Theme.horizontalPageMargin
|
x: Theme.horizontalPageMargin
|
||||||
width: parent.width - 2 * Theme.horizontalPageMargin
|
width: parent.width - 2 * Theme.horizontalPageMargin
|
||||||
text: "Il margine viene applicato al capitolo corrente e salvato per tutti i libri."
|
text: "Le modifiche si applicano subito al testo. Conferma per salvarle per tutti i libri."
|
||||||
color: Theme.secondaryColor
|
color: Theme.secondaryColor
|
||||||
wrapMode: Text.Wrap
|
wrapMode: Text.Wrap
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onAccepted: appSettings.readerMargin = dialog.marginValue
|
onAccepted: {
|
||||||
|
appSettings.readerMargin = dialog.marginLr
|
||||||
|
appSettings.readerMarginV = dialog.marginTb
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,11 +43,14 @@ Page {
|
|||||||
MenuItem {
|
MenuItem {
|
||||||
text: "Margini del testo"
|
text: "Margini del testo"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var dlg = pageStack.push(Qt.resolvedUrl("MarginDialog.qml"),
|
var dlg = pageStack.push(Qt.resolvedUrl("MarginDialog.qml"), {
|
||||||
{ marginValue: appSettings.readerMargin })
|
marginLr: appSettings.readerMargin,
|
||||||
|
marginTb: appSettings.readerMarginV,
|
||||||
|
previewHandler: page.previewMargins
|
||||||
|
})
|
||||||
dlg.accepted.connect(function() {
|
dlg.accepted.connect(function() {
|
||||||
if (page.ready && book.chapterCount() > 0)
|
// i valori sono già persistiti da onAccepted; rinfresca subito
|
||||||
loadChapter()
|
applyMarginsJS()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -239,7 +242,7 @@ Page {
|
|||||||
// e margini) è iniettato nell'HTML dal parser, quindi niente JS post-load
|
// e margini) è iniettato nell'HTML dal parser, quindi niente JS post-load
|
||||||
function loadChapter() {
|
function loadChapter() {
|
||||||
var html = book.chapterHtml(page.currentChapter, page.fontPx(),
|
var html = book.chapterHtml(page.currentChapter, page.fontPx(),
|
||||||
appSettings.readerMargin)
|
appSettings.readerMargin, appSettings.readerMarginV)
|
||||||
if (html.length === 0) {
|
if (html.length === 0) {
|
||||||
page.errorMessage = "Capitolo non leggibile"
|
page.errorMessage = "Capitolo non leggibile"
|
||||||
page.ready = true
|
page.ready = true
|
||||||
@@ -259,6 +262,34 @@ Page {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JS che sovrascrive i margini sul documento aperto: stile inline con
|
||||||
|
// 'important' batte lo stylesheet iniettato. Effetto immediato, niente reload.
|
||||||
|
function marginJs(lr, tb) {
|
||||||
|
return "var h=document.documentElement,b=document.body;"
|
||||||
|
+ "h.style.setProperty('margin-left','" + lr + "px','important');"
|
||||||
|
+ "h.style.setProperty('margin-right','" + lr + "px','important');"
|
||||||
|
+ "b.style.setProperty('margin-left','" + lr + "px','important');"
|
||||||
|
+ "b.style.setProperty('margin-right','" + lr + "px','important');"
|
||||||
|
+ "b.style.setProperty('margin-top','" + tb + "px','important');"
|
||||||
|
+ "b.style.setProperty('margin-bottom','" + tb + "px','important');"
|
||||||
|
+ "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
// riapplica i margini salvati nelle impostazioni (senza ricaricare il libro)
|
||||||
|
function applyMarginsJS() {
|
||||||
|
if (!web.loaded || !page.ready)
|
||||||
|
return
|
||||||
|
web.runJavaScript(marginJs(appSettings.readerMargin, appSettings.readerMarginV),
|
||||||
|
function() { })
|
||||||
|
}
|
||||||
|
|
||||||
|
// anteprima live dal dialogo margini: valori non ancora persistiti
|
||||||
|
function previewMargins(lr, tb) {
|
||||||
|
if (!web.loaded || !page.ready)
|
||||||
|
return
|
||||||
|
web.runJavaScript(marginJs(lr, tb), function() { })
|
||||||
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
page.ready = false
|
page.ready = false
|
||||||
if (!book.open(page.epubPath)) {
|
if (!book.open(page.epubPath)) {
|
||||||
@@ -290,10 +321,10 @@ Page {
|
|||||||
if (status === PageStatus.Inactive) {
|
if (status === PageStatus.Inactive) {
|
||||||
maybeSave(true)
|
maybeSave(true)
|
||||||
} else if (status === PageStatus.Active) {
|
} else if (status === PageStatus.Active) {
|
||||||
// riapplica font/margini se cambiati nelle impostazioni:
|
// riapplica i margini se cambiati nelle impostazioni:
|
||||||
// ricarica il capitolo e ripristina la posizione
|
// via JS sul documento aperto, senza ricaricare il capitolo
|
||||||
if (page.ready && book.chapterCount() > 0)
|
if (page.ready && book.chapterCount() > 0)
|
||||||
loadChapter()
|
applyMarginsJS()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ Page {
|
|||||||
Slider {
|
Slider {
|
||||||
id: marginSlider
|
id: marginSlider
|
||||||
width: parent.width
|
width: parent.width
|
||||||
label: "Margini del testo"
|
label: "Margini laterali"
|
||||||
minimumValue: 0
|
minimumValue: 0
|
||||||
maximumValue: 80
|
maximumValue: 80
|
||||||
stepSize: 4
|
stepSize: 4
|
||||||
@@ -71,6 +71,18 @@ Page {
|
|||||||
onValueChanged: appSettings.readerMargin = value
|
onValueChanged: appSettings.readerMargin = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Slider {
|
||||||
|
id: marginVSlider
|
||||||
|
width: parent.width
|
||||||
|
label: "Margine alto e basso"
|
||||||
|
minimumValue: 0
|
||||||
|
maximumValue: 80
|
||||||
|
stepSize: 4
|
||||||
|
value: appSettings.readerMarginV
|
||||||
|
valueText: value + " px"
|
||||||
|
onValueChanged: appSettings.readerMarginV = value
|
||||||
|
}
|
||||||
|
|
||||||
SectionHeader { text: "Connessione" }
|
SectionHeader { text: "Connessione" }
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
|
|||||||
+7
-4
@@ -406,7 +406,7 @@ QVariantList EpubBook::chapterList() const
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString EpubBook::chapterHtml(int index, int fontSizePx, int marginPx) const
|
QString EpubBook::chapterHtml(int index, int fontSizePx, int marginPx, int marginVerticalPx) const
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= m_chapters.size())
|
if (index < 0 || index >= m_chapters.size())
|
||||||
return QString();
|
return QString();
|
||||||
@@ -415,12 +415,15 @@ QString EpubBook::chapterHtml(int index, int fontSizePx, int marginPx) const
|
|||||||
return QString();
|
return QString();
|
||||||
QString html = QString::fromUtf8(f.readAll());
|
QString html = QString::fromUtf8(f.readAll());
|
||||||
|
|
||||||
// stile di reflow iniettato nel documento: !important vince sui CSS del libro
|
// stile di reflow iniettato nel documento: !important vince sui CSS del libro.
|
||||||
|
// I margini si possono aggiornare a caldo via runJavaScript (setProperty con
|
||||||
|
// 'important' inline), senza ricaricare il capitolo.
|
||||||
const QString style = QStringLiteral(
|
const QString style = QStringLiteral(
|
||||||
"<style id=\"cw-font\">html,body{font-size:%1px!important;"
|
"<style id=\"cw-font\">html,body{font-size:%1px!important;"
|
||||||
"margin-left:%2px!important;margin-right:%2px!important}"
|
"margin-left:%2px!important;margin-right:%2px!important;"
|
||||||
|
"margin-top:%3px!important;margin-bottom:%3px!important}"
|
||||||
"p,div,li,td,blockquote,section{font-size:1em!important}</style>")
|
"p,div,li,td,blockquote,section{font-size:1em!important}</style>")
|
||||||
.arg(fontSizePx).arg(marginPx);
|
.arg(fontSizePx).arg(marginPx).arg(marginVerticalPx);
|
||||||
const int headEnd = html.indexOf(QStringLiteral("</head>"), 0, Qt::CaseInsensitive);
|
const int headEnd = html.indexOf(QStringLiteral("</head>"), 0, Qt::CaseInsensitive);
|
||||||
if (headEnd >= 0)
|
if (headEnd >= 0)
|
||||||
html.insert(headEnd, style);
|
html.insert(headEnd, style);
|
||||||
|
|||||||
+1
-1
@@ -37,7 +37,7 @@ public:
|
|||||||
// elenco [{index, title}] per la lista capitoli
|
// elenco [{index, title}] per la lista capitoli
|
||||||
Q_INVOKABLE QVariantList chapterList() const;
|
Q_INVOKABLE QVariantList chapterList() const;
|
||||||
// HTML del capitolo con lo stile di reflow iniettato (font-size e margini in px)
|
// HTML del capitolo con lo stile di reflow iniettato (font-size e margini in px)
|
||||||
Q_INVOKABLE QString chapterHtml(int index, int fontSizePx, int marginPx) const;
|
Q_INVOKABLE QString chapterHtml(int index, int fontSizePx, int marginPx, int marginVerticalPx) const;
|
||||||
// base URL (file://) per risolvere immagini/CSS relativi del capitolo
|
// base URL (file://) per risolvere immagini/CSS relativi del capitolo
|
||||||
Q_INVOKABLE QString chapterBaseUrl(int index) const;
|
Q_INVOKABLE QString chapterBaseUrl(int index) const;
|
||||||
|
|
||||||
|
|||||||
+16
-1
@@ -11,7 +11,8 @@ Settings::Settings(QObject *parent)
|
|||||||
// diagnostica: path reale del file di configurazione e valori letti all'avvio
|
// diagnostica: path reale del file di configurazione e valori letti all'avvio
|
||||||
qDebug() << "Settings file:" << m_settings.fileName();
|
qDebug() << "Settings file:" << m_settings.fileName();
|
||||||
qDebug() << "Settings read: serverUrl=[" << serverUrl() << "] user=[" << username()
|
qDebug() << "Settings read: serverUrl=[" << serverUrl() << "] user=[" << username()
|
||||||
<< "] ssl=" << ignoreSslErrors() << "margin=" << readerMargin();
|
<< "] ssl=" << ignoreSslErrors() << "margin=" << readerMargin()
|
||||||
|
<< "marginV=" << readerMarginV();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Settings::serverUrl() const
|
QString Settings::serverUrl() const
|
||||||
@@ -85,6 +86,20 @@ void Settings::setReaderMargin(int value)
|
|||||||
emit readerMarginChanged();
|
emit readerMarginChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Settings::readerMarginV() const
|
||||||
|
{
|
||||||
|
return m_settings.value(QStringLiteral("readerMarginV"), 0).toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::setReaderMarginV(int value)
|
||||||
|
{
|
||||||
|
if (value == readerMarginV())
|
||||||
|
return;
|
||||||
|
m_settings.setValue(QStringLiteral("readerMarginV"), value);
|
||||||
|
m_settings.sync();
|
||||||
|
emit readerMarginVChanged();
|
||||||
|
}
|
||||||
|
|
||||||
QString Settings::downloadDir() const
|
QString Settings::downloadDir() const
|
||||||
{
|
{
|
||||||
QString dir = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
|
QString dir = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ class Settings : public QObject
|
|||||||
Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged)
|
Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged)
|
||||||
Q_PROPERTY(bool ignoreSslErrors READ ignoreSslErrors WRITE setIgnoreSslErrors NOTIFY ignoreSslErrorsChanged)
|
Q_PROPERTY(bool ignoreSslErrors READ ignoreSslErrors WRITE setIgnoreSslErrors NOTIFY ignoreSslErrorsChanged)
|
||||||
Q_PROPERTY(int readerMargin READ readerMargin WRITE setReaderMargin NOTIFY readerMarginChanged)
|
Q_PROPERTY(int readerMargin READ readerMargin WRITE setReaderMargin NOTIFY readerMarginChanged)
|
||||||
|
Q_PROPERTY(int readerMarginV READ readerMarginV WRITE setReaderMarginV NOTIFY readerMarginVChanged)
|
||||||
Q_PROPERTY(QString downloadDir READ downloadDir CONSTANT)
|
Q_PROPERTY(QString downloadDir READ downloadDir CONSTANT)
|
||||||
// derivata da serverUrl (senza slash finale): accesso QML come appSettings.baseUrl
|
// derivata da serverUrl (senza slash finale): accesso QML come appSettings.baseUrl
|
||||||
Q_PROPERTY(QString baseUrl READ baseUrl NOTIFY baseUrlChanged)
|
Q_PROPERTY(QString baseUrl READ baseUrl NOTIFY baseUrlChanged)
|
||||||
@@ -36,6 +37,10 @@ public:
|
|||||||
int readerMargin() const;
|
int readerMargin() const;
|
||||||
void setReaderMargin(int value);
|
void setReaderMargin(int value);
|
||||||
|
|
||||||
|
// margine verticale (alto e basso, simmetrico) del testo nel lettore, in px
|
||||||
|
int readerMarginV() const;
|
||||||
|
void setReaderMarginV(int value);
|
||||||
|
|
||||||
QString downloadDir() const;
|
QString downloadDir() const;
|
||||||
|
|
||||||
// Header "Authorization: Basic ..." pronto da usare, vuoto se utente non impostato
|
// Header "Authorization: Basic ..." pronto da usare, vuoto se utente non impostato
|
||||||
@@ -57,6 +62,7 @@ signals:
|
|||||||
void passwordChanged();
|
void passwordChanged();
|
||||||
void ignoreSslErrorsChanged();
|
void ignoreSslErrorsChanged();
|
||||||
void readerMarginChanged();
|
void readerMarginChanged();
|
||||||
|
void readerMarginVChanged();
|
||||||
void baseUrlChanged();
|
void baseUrlChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
Reference in New Issue
Block a user