Turn pages with volume keys

And allow to configure volume key actions.
This commit is contained in:
Slava Monich 2017-08-08 16:09:01 +03:00
parent 5fd1827e57
commit 0e8d758879
20 changed files with 1107 additions and 105 deletions

View file

@ -109,10 +109,13 @@ SOURCES += \
src/BooksImportModel.cpp \
src/BooksListWatcher.cpp \
src/BooksLoadingProperty.cpp \
src/BooksMediaPlugin.cpp \
src/BooksPageStack.cpp \
src/BooksPageWidget.cpp \
src/BooksPaintContext.cpp \
src/BooksPathModel.cpp \
src/BooksPluginLoader.cpp \
src/BooksPolicyPlugin.cpp \
src/BooksSaveTimer.cpp \
src/BooksSettings.cpp \
src/BooksShelf.cpp \
@ -151,10 +154,13 @@ HEADERS += \
src/BooksItem.h \
src/BooksListWatcher.h \
src/BooksLoadingProperty.h \
src/BooksMediaPlugin.h \
src/BooksPageStack.h \
src/BooksPageWidget.h \
src/BooksPaintContext.h \
src/BooksPathModel.h \
src/BooksPluginLoader.h \
src/BooksPolicyPlugin.h \
src/BooksPos.h \
src/BooksSaveTimer.h \
src/BooksSettings.h \

View file

@ -34,6 +34,9 @@ import QtQuick 2.0
import Sailfish.Silica 1.0
import harbour.books 1.0
//import Sailfish.Media 1.0 // Not allowed
//import org.nemomobile.policy 1.0 // Not allowed
SilicaFlickable {
id: root
@ -57,10 +60,21 @@ SilicaFlickable {
(!imageView || !imageView.visible) &&
(!footnoteView || !footnoteView.visible)
readonly property bool viewActive: Qt.application.active && book
readonly property bool haveVolumeUpAction: Settings.volumeUpAction !== BooksSettings.ActionNone
readonly property bool haveVolumeDownAction: Settings.volumeDownAction !== BooksSettings.ActionNone
readonly property bool haveKeyAction: haveVolumeUpAction || haveVolumeDownAction
property var linkMenu
property var imageView
property var footnoteView
function hideViews() {
if (linkMenu) linkMenu.hide()
if (imageView) imageView.hide()
if (footnoteView) footnoteView.hide()
}
onOrientationChanged: {
if (footnoteView) {
footnoteView.cancel()
@ -111,6 +125,7 @@ SilicaFlickable {
opacity: loading ? 0 : 1
visible: opacity > 0
interactive: root.interactive
readonly property real maxContentX: Math.max(0, contentWidth - width)
readonly property int currentPage: stackModel.currentPage
property bool completed
@ -143,7 +158,7 @@ SilicaFlickable {
}
}
function updateModel() {
if (linkMenu) linkMenu.hide()
hideViews()
//console.trace()
stackModel.currentPage = currentIndex
if (!pager.pressed) {
@ -212,6 +227,32 @@ SilicaFlickable {
}
}
function prevPage() {
if (!scrollAnimation.running && contentX > 0) {
hideViews();
scrollAnimation.from = contentX
scrollAnimation.to = Math.max(0, contentX - width - spacing)
scrollAnimation.start()
}
}
function nextPage() {
if (!scrollAnimation.running && contentX < maxContentX) {
hideViews();
scrollAnimation.from = contentX
scrollAnimation.to = Math.min(maxContentX, contentX + width + spacing)
scrollAnimation.start()
}
}
NumberAnimation {
id: scrollAnimation
target: bookView
property: "contentX"
duration: 500
easing.type: Easing.InOutQuad
}
Behavior on opacity { FadeAnimation {} }
Timer {
@ -326,4 +367,48 @@ SilicaFlickable {
//% "Formatting..."
qsTrId("harbour-books-book-view-formatting")) : ""
}
function performAction(action)
{
switch (action) {
case BooksSettings.ActionPreviousPage:
bookView.prevPage()
return
case BooksSettings.ActionNextPage:
bookView.nextPage()
return
}
}
MediaKey {
enabled: viewActive && haveVolumeUpAction
key: Qt.Key_VolumeUp
onPressed: volumeUpAction()
onRepeat: volumeUpAction()
function volumeUpAction() {
performAction(Settings.volumeUpAction)
}
}
MediaKey {
enabled: viewActive && haveVolumeDownAction
key: Qt.Key_VolumeDown
onPressed: volumeDownAction()
onRepeat: volumeDownAction()
function volumeDownAction() {
performAction(Settings.volumeDownAction)
}
}
Permissions {
enabled: viewActive && haveKeyAction
autoRelease: true
applicationClass: "camera"
Resource {
id: volumeKeysResource
type: Resource.ScaleButton
optional: true
}
}
}

View file

@ -1,5 +1,5 @@
/*
Copyright (C) 2015-2016 Jolla Ltd.
Copyright (C) 2015-2017 Jolla Ltd.
Contact: Slava Monich <slava.monich@jolla.com>
You may use this file under the terms of BSD license as follows:
@ -39,9 +39,9 @@ ApplicationWindow {
allowedOrientations: {
switch (Settings.orientation) {
default:
case Settings.OrientationAny: return Orientation.All
case Settings.OrientationPortrait: return Orientation.Portrait
case Settings.OrientationLandscape: return Orientation.Landscape
case BooksSettings.OrientationAny: return Orientation.All
case BooksSettings.OrientationPortrait: return Orientation.Portrait
case BooksSettings.OrientationLandscape: return Orientation.Landscape
}
}

View file

@ -0,0 +1,92 @@
/*
Copyright (C) 2017 Jolla Ltd.
Contact: Slava Monich <slava.monich@jolla.com>
You may use this file under the terms of BSD license as follows:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Jolla Ltd nor the names of its contributors may
be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.
*/
import QtQuick 2.0
import Sailfish.Silica 1.0
import org.nemomobile.configuration 1.0
ComboBox {
id: actionComboBox
property alias key: configuration.key
property alias defaultValue: configuration.defaultValue
property bool ready
value: currentItem ? currentItem.text : ""
menu: ContextMenu {
id: actionMenu
readonly property int defaultIndex: 0
MenuItem {
//: Combo box value for no action
//% "No action"
text: qsTrId("harbour-books-settings-page-action-none")
readonly property int value: 0
}
MenuItem {
//: Combo box value for previous page action
//% "Previous page"
text: qsTrId("harbour-books-settings-page-action-previous_page")
readonly property int value: 1
}
MenuItem {
//: Combo box value for next page action
//% "Next page"
text: qsTrId("harbour-books-settings-page-action-next_page")
readonly property int value: 2
}
}
onCurrentItemChanged: {
if (ready && currentItem) {
configuration.value = currentItem.value
}
}
Component.onCompleted: {
configuration.updateControls()
ready = true
}
ConfigurationValue {
id: configuration
defaultValue: 0
onValueChanged: updateControls()
function updateControls() {
var n = actionMenu.children.length
var index = actionMenu.defaultIndex
for (var i=0; i<n; i++) {
if (actionMenu.children[i].value === value) {
index = i
break
}
}
actionComboBox.currentIndex = index
}
}
}

View file

@ -1,5 +1,5 @@
/*
Copyright (C) 2016 Jolla Ltd.
Copyright (C) 2016-2017 Jolla Ltd.
Contact: Slava Monich <slava.monich@jolla.com>
You may use this file under the terms of BSD license as follows:
@ -78,6 +78,12 @@ Page {
title: qsTrId("harbour-books-settings-page-header")
}
SectionHeader {
//: Section header for display settings
//% "Display"
text: qsTrId("harbour-books-settings-page-display-section_header")
}
Slider {
id: fontSizeSlider
minimumValue: -5
@ -161,6 +167,28 @@ Page {
}
}
SectionHeader {
//: Section header for media keys
//% "Media keys"
text: qsTrId("harbour-books-settings-page-media-keys-section_header")
}
BooksActionSelector {
//: Combo box label
//% "Volume up"
label: qsTrId("harbour-books-settings-page-volume_up-label")
key: rootPath + "volumeUpAction"
defaultValue: 2 // BooksSettings.ActionNextPage
}
BooksActionSelector {
//: Combo box label
//% "Volume down"
label: qsTrId("harbour-books-settings-page-volume_down-label")
key: rootPath + "volumeDownAction"
defaultValue: 1 // BooksSettings.ActionPreviousPage
}
SectionHeader {
//: Section header for memory card settings
//% "Memory card"

View file

@ -0,0 +1,69 @@
/*
* Copyright (C) 2017 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Jolla Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "BooksMediaPlugin.h"
// Workaround for org.nemomobile.policy (or Sailfish.Media) not being
// allowed in harbour apps
BooksMediaPlugin* BooksMediaPlugin::gInstance = Q_NULLPTR;
const char BooksMediaPlugin::MEDIAKEY_QML_TYPE[] = "MediaKey";
BooksMediaPlugin::BooksMediaPlugin(
QQmlEngine* aEngine) :
BooksPluginLoader(aEngine, "Sailfish.Media", 1, 0)
{
}
void
BooksMediaPlugin::registerTypes(
const char* aModule,
int aMajor,
int aMinor)
{
reRegisterType(MEDIAKEY_QML_TYPE, aModule, aMajor, aMinor);
}
void
BooksMediaPlugin::registerTypes(
QQmlEngine* aEngine,
const char* aModule,
int aMajor,
int aMinor)
{
if (!gInstance) {
gInstance = new BooksMediaPlugin(aEngine);
}
gInstance->registerTypes(aModule, aMajor, aMinor);
}

View file

@ -0,0 +1,53 @@
/*
* Copyright (C) 2017 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Jolla Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BOOKS_MEDIA_PLUGIN_H
#define BOOKS_MEDIA_PLUGIN_H
#include "BooksPluginLoader.h"
class BooksMediaPlugin : public BooksPluginLoader
{
static BooksMediaPlugin* gInstance;
static const char MEDIAKEY_QML_TYPE[];
public:
static void registerTypes(QQmlEngine* aEngine, const char* aModule,
int aMajor, int aMinor);
private:
BooksMediaPlugin(QQmlEngine* aEngine);
void registerTypes(const char* aModule, int aMajor, int aMinor);
};
#endif // BOOKS_MEDIA_KEY_H

View file

@ -0,0 +1,218 @@
/*
* Copyright (C) 2017 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Jolla Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "BooksPluginLoader.h"
#include "HarbourDebug.h"
#include <qqml.h>
#include <QQmlEngine>
#include <QQmlTypesExtensionInterface>
#include <QStringList>
#include <QPluginLoader>
#include <QTextStream>
#include <QFile>
// This hack allows to use prohibited QML imports by re-registering
// then under harbour.books
// PRIVATE QT API!
class Q_QML_EXPORT QQmlType
{
public:
int typeId() const;
int qListTypeId() const;
typedef void (*CreateFunc)(void *);
CreateFunc createFunction() const;
int createSize() const;
const QMetaObject *metaObject() const;
int parserStatusCast() const;
int propertyValueSourceCast() const;
int propertyValueInterceptorCast() const;
};
// PRIVATE QT API!
class Q_QML_EXPORT QQmlMetaType
{
public:
static QQmlType* qmlType(const QString &qualifiedName, int, int);
};
BooksPluginLoader::BooksPluginLoader(
QQmlEngine* aEngine,
QString aModule,
int aMajor,
int aMinor) :
iTypesRegistered(false),
iPlugin(pluginLoader(aEngine, aModule)),
iModule(aModule),
iMajor(aMajor),
iMinor(aMinor)
{}
BooksPluginLoader::~BooksPluginLoader()
{
delete iPlugin;
}
QPluginLoader*
BooksPluginLoader::pluginLoader(
QQmlEngine* aEngine,
QString aModule)
{
QStringList pathList = aEngine->importPathList();
aModule.replace('.', '/');
const int n = pathList.count();
for (int i=0; i<n; i++) {
QString dir(pathList.at(i));
QPluginLoader* loader = pluginLoader(dir.append('/').append(aModule));
if (loader) {
if (loader->load()) {
HDEBUG("loaded" << qPrintable(loader->fileName()));
return loader;
} else {
HWARN("Failed to load" << qPrintable(loader->fileName()));
delete loader;
}
}
}
return NULL;
}
QPluginLoader*
BooksPluginLoader::pluginLoader(
QString aPluginDir)
{
QString qmldir(QString(aPluginDir).append('/').append("qmldir"));
QFile f(qmldir);
if (f.open(QIODevice::ReadOnly)) {
QTextStream in(&f);
while (!in.atEnd()) {
static const QString plugin("plugin");
QString line = in.readLine();
if (line.indexOf(plugin) >= 0) {
QStringList parts = line.split(' ', QString::SkipEmptyParts);
if (parts.count() == 2 && parts.at(0) == plugin) {
QString path(QString(aPluginDir).append("/lib").
append(parts.at(1)).append(".so"));
if (QFile::exists(path)) {
return new QPluginLoader(path);
}
}
}
}
}
return NULL;
}
QQmlType*
BooksPluginLoader::qmlType(
QString aName)
{
if (iPlugin) {
if (!iTypesRegistered) {
iTypesRegistered = true;
QObject* root = iPlugin->instance();
if (root) {
QQmlTypesExtensionInterface* ext =
qobject_cast<QQmlTypesExtensionInterface*>(root);
if (ext) {
QByteArray str = iModule.toLocal8Bit();
ext->registerTypes(str.constData());
}
} else {
HWARN("Could not load" << qPrintable(iPlugin->fileName()));
}
}
QString fullName(iModule + '/' + aName);
QQmlType* type = QQmlMetaType::qmlType(fullName, iMajor, iMinor);
if (!type) {
HWARN("Failed to load" << fullName);
}
return type;
}
return NULL;
}
void
BooksPluginLoader::reRegisterType(
const char* aQmlName,
const char* aModule,
int aMajor,
int aMinor)
{
// Re-register with the same type name (in different module)
reRegisterType(qmlType(aQmlName), aQmlName, aModule, aMajor, aMinor);
}
// Re-registers the existing QML type under a different name/module
void
BooksPluginLoader::reRegisterType(
QQmlType* aType,
const char* aQmlName,
const char* aModule,
int aMajor,
int aMinor)
{
if (aType) {
QQmlPrivate::RegisterType type = {
0, // int version;
aType->typeId(), // int typeId;
aType->qListTypeId(), // int listId;
aType->createSize(), // int objectSize;
aType->createFunction(), // void (*create)(void *);
QString(), // QString noCreationReason;
aModule, // const char *uri;
aMajor, // int versionMajor;
aMinor, // int versionMinor;
aQmlName, // const char *elementName;
aType->metaObject(), // const QMetaObject *metaObject;
#if 0 // We don't need those, it seems
aType->attachedPropertiesFunction(),
aType->attachedPropertiesType(),
#else
Q_NULLPTR, // QQmlAttachedPropertiesFunc attachedPropertiesFunction;
Q_NULLPTR, // const QMetaObject *attachedPropertiesMetaObject;
#endif
aType->parserStatusCast(), // int parserStatusCast;
aType->propertyValueSourceCast(), // int valueSourceCast;
aType->propertyValueInterceptorCast(), // int valueInterceptorCast;
Q_NULLPTR, // QObject *(*extensionObjectCreate)(QObject *);
Q_NULLPTR, // const QMetaObject *extensionMetaObject;
Q_NULLPTR, // QQmlCustomParser *customParser;
0 // int revision;
};
QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
}
}

View file

@ -0,0 +1,67 @@
/*
* Copyright (C) 2017 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Jolla Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BOOKS_PLUGIN_LOADER_H
#define BOOKS_PLUGIN_LOADER_H
#include <QString>
class QQmlType;
class QQmlEngine;
class QPluginLoader;
class BooksPluginLoader
{
protected:
BooksPluginLoader(QQmlEngine* aEngine, QString aModule, int aMajor, int aMinor);
~BooksPluginLoader();
QQmlType* qmlType(QString aName);
void reRegisterType(QQmlType* aType, const char* aQmlName,
const char* aModule, int aMajor, int aMinor);
void reRegisterType(const char* aQmlName,
const char* aModule, int aMajor, int aMinor);
static QPluginLoader* pluginLoader(QQmlEngine* aEngine, QString aModule);
static QPluginLoader* pluginLoader(QString aPluginDir);
private:
bool iTypesRegistered;
QPluginLoader* iPlugin;
QString iModule;
int iMajor;
int iMinor;
};
#endif // BOOKS_PLUGIN_LOADER_H

View file

@ -0,0 +1,71 @@
/*
* Copyright (C) 2017 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Jolla Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "BooksPolicyPlugin.h"
// Workaround for org.nemomobile.policy (or Nemo.Policy) not being
// allowed in harbour apps
BooksPolicyPlugin* BooksPolicyPlugin::gInstance = Q_NULLPTR;
const char BooksPolicyPlugin::RESOURCE_QML_TYPE[] = "Resource";
const char BooksPolicyPlugin::PERMISSIONS_QML_TYPE[] = "Permissions";
BooksPolicyPlugin::BooksPolicyPlugin(
QQmlEngine* aEngine) :
BooksPluginLoader(aEngine, "org.nemomobile.policy", 1, 0)
{
}
void
BooksPolicyPlugin::registerTypes(
const char* aModule,
int aMajor,
int aMinor)
{
reRegisterType(RESOURCE_QML_TYPE, aModule, aMajor, aMinor);
reRegisterType(PERMISSIONS_QML_TYPE, aModule, aMajor, aMinor);
}
void
BooksPolicyPlugin::registerTypes(
QQmlEngine* aEngine,
const char* aModule,
int aMajor,
int aMinor)
{
if (!gInstance) {
gInstance = new BooksPolicyPlugin(aEngine);
}
gInstance->registerTypes(aModule, aMajor, aMinor);
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (C) 2017 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Jolla Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BOOKS_POLICY_PLUGIN_H
#define BOOKS_POLICY_PLUGIN_H
#include "BooksPluginLoader.h"
class QQmlEngine;
class BooksPolicyPlugin : public BooksPluginLoader
{
static BooksPolicyPlugin* gInstance;
static const char RESOURCE_QML_TYPE[];
static const char PERMISSIONS_QML_TYPE[];
public:
static void registerTypes(QQmlEngine* aEngine, const char* aModule,
int aMajor, int aMinor);
private:
BooksPolicyPlugin(QQmlEngine* aEngine);
void registerTypes(const char* aModule, int aMajor, int aMinor);
};
#endif // BOOKS_POLICY_PLUGIN_H

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
@ -42,21 +42,26 @@
#include <MGConfItem>
#define DCONF_PATH BOOKS_DCONF_ROOT
#define KEY_FONT_SIZE "fontSize"
#define KEY_PAGE_DETAILS "pageDetails"
#define KEY_CURRENT_BOOK "currentBook"
#define KEY_CURRENT_FOLDER "currentFolder"
#define KEY_REMOVABLE_ROOT "removableRoot"
#define KEY_INVERT_COLORS "invertColors"
#define KEY_ORIENTATION "orientation"
#define DEFAULT_FONT_SIZE 0
#define DEFAULT_PAGE_DETAILS 0
#define DEFAULT_CURRENT_BOOK QString()
#define DEFAULT_CURRENT_FOLDER QString()
#define DEFAULT_REMOVABLE_ROOT "Books"
#define DEFAULT_INVERT_COLORS false
#define DEFAULT_ORIENTATION (BooksSettings::OrientationAny)
#define DCONF_PATH BOOKS_DCONF_ROOT
#define KEY_FONT_SIZE "fontSize"
#define KEY_PAGE_DETAILS "pageDetails"
#define KEY_CURRENT_BOOK "currentBook"
#define KEY_CURRENT_FOLDER "currentFolder"
#define KEY_REMOVABLE_ROOT "removableRoot"
#define KEY_INVERT_COLORS "invertColors"
#define KEY_VOLUME_UP_ACTION "volumeUpAction"
#define KEY_VOLUME_DOWN_ACTION "volumeDownAction"
#define KEY_ORIENTATION "orientation"
#define DEFAULT_FONT_SIZE 0
#define DEFAULT_PAGE_DETAILS 0
#define DEFAULT_CURRENT_BOOK QString()
#define DEFAULT_CURRENT_FOLDER QString()
#define DEFAULT_REMOVABLE_ROOT "Books"
#define DEFAULT_INVERT_COLORS false
#define DEFAULT_VOLUME_UP_ACTION (BooksSettings::ActionNextPage)
#define DEFAULT_VOLUME_DOWN_ACTION (BooksSettings::ActionPreviousPage)
#define DEFAULT_ORIENTATION (BooksSettings::OrientationAny)
#define PAGETOOL_COLOR QColor(128,128,128) // any bg
#define NORMAL_PAGETOOL_HIGHLIGHT_COLOR QColor(64,64,64) // on white
@ -214,6 +219,7 @@ public:
QString currentFolder() const;
shared_ptr<ZLTextStyle> textStyle(int aFontSizeAdjust) const;
void setCurrentBook(QObject* aBook);
static Action getAction(MGConfItem* aItem, Action aDefault);
private Q_SLOTS:
void onFontSizeValueChanged();
@ -226,6 +232,8 @@ public:
MGConfItem* iFontSizeConf;
MGConfItem* iPageDetailsConf;
MGConfItem* iInvertColorsConf;
MGConfItem* iVolumeUpActionConf;
MGConfItem* iVolumeDownActionConf;
MGConfItem* iCurrentFolderConf;
MGConfItem* iCurrentBookPathConf;
MGConfItem* iOrientationConf;
@ -244,6 +252,8 @@ BooksSettings::Private::Private(BooksSettings* aParent) :
iFontSizeConf(new MGConfItem(DCONF_PATH KEY_FONT_SIZE, this)),
iPageDetailsConf(new MGConfItem(DCONF_PATH KEY_PAGE_DETAILS, this)),
iInvertColorsConf(new MGConfItem(DCONF_PATH KEY_INVERT_COLORS, this)),
iVolumeUpActionConf(new MGConfItem(DCONF_PATH KEY_VOLUME_UP_ACTION, this)),
iVolumeDownActionConf(new MGConfItem(DCONF_PATH KEY_VOLUME_DOWN_ACTION, this)),
iCurrentFolderConf(new MGConfItem(DCONF_PATH KEY_CURRENT_FOLDER, this)),
iCurrentBookPathConf(new MGConfItem(DCONF_PATH KEY_CURRENT_BOOK, this)),
iOrientationConf(new MGConfItem(DCONF_PATH KEY_ORIENTATION, this)),
@ -257,6 +267,8 @@ BooksSettings::Private::Private(BooksSettings* aParent) :
connect(iPageDetailsConf, SIGNAL(valueChanged()), iParent, SIGNAL(pageDetailsChanged()));
connect(iInvertColorsConf, SIGNAL(valueChanged()), iParent, SIGNAL(invertColorsChanged()));
connect(iInvertColorsConf, SIGNAL(valueChanged()), iParent, SIGNAL(pageBackgroundColorChanged()));
connect(iVolumeUpActionConf, SIGNAL(valueChanged()), iParent, SIGNAL(volumeUpActionChanged()));
connect(iVolumeDownActionConf, SIGNAL(valueChanged()), iParent, SIGNAL(volumeDownActionChanged()));
connect(iOrientationConf, SIGNAL(valueChanged()), iParent, SIGNAL(orientationChanged()));
connect(iRemovableRootConf, SIGNAL(valueChanged()), iParent, SIGNAL(removableRootChanged()));
}
@ -405,11 +417,29 @@ BooksSettings::Private::onCurrentBookPathChanged()
}
}
BooksSettings::Action
BooksSettings::Private::getAction(
MGConfItem* aItem,
Action aDefault)
{
// Need to cast int to enum right away to force "enumeration value not
// handled in switch" warning if we miss one of the actions:
Action value = (Action)aItem->value(aDefault).toInt();
switch (value) {
case ActionNone:
case ActionPreviousPage:
case ActionNextPage:
return value;
}
return aDefault;
}
// ==========================================================================
// BooksSettings
// ==========================================================================
BooksSettings::BooksSettings() :
BooksSettings::BooksSettings(QObject* aParent) :
QObject(aParent),
iPrivate(new Private(this))
{
}
@ -513,6 +543,36 @@ BooksSettings::setInvertColors(
iPrivate->iInvertColorsConf->set(aValue);
}
BooksSettings::Action
BooksSettings::volumeUpAction() const
{
return Private::getAction(iPrivate->iVolumeUpActionConf,
DEFAULT_VOLUME_UP_ACTION);
}
void
BooksSettings::setVolumeUpAction(
int aValue)
{
HDEBUG(aValue);
iPrivate->iVolumeUpActionConf->set(aValue);
}
BooksSettings::Action
BooksSettings::volumeDownAction() const
{
return Private::getAction(iPrivate->iVolumeDownActionConf,
DEFAULT_VOLUME_DOWN_ACTION);
}
void
BooksSettings::setVolumeDownAction(
int aValue)
{
HDEBUG(aValue);
iPrivate->iVolumeDownActionConf->set(aValue);
}
QString
BooksSettings::removableRoot() const
{

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
@ -45,9 +45,12 @@ class BooksSettings : public QObject
Q_OBJECT
Q_ENUMS(FontSize)
Q_ENUMS(Orientation)
Q_ENUMS(Action)
Q_PROPERTY(int fontSize READ fontSize WRITE setFontSize NOTIFY fontSizeChanged)
Q_PROPERTY(int pageDetails READ pageDetails WRITE setPageDetails NOTIFY pageDetailsChanged)
Q_PROPERTY(bool invertColors READ invertColors WRITE setInvertColors NOTIFY invertColorsChanged)
Q_PROPERTY(int volumeUpAction READ volumeUpAction WRITE setVolumeUpAction NOTIFY volumeUpActionChanged)
Q_PROPERTY(int volumeDownAction READ volumeDownAction WRITE setVolumeDownAction NOTIFY volumeDownActionChanged)
Q_PROPERTY(QObject* currentBook READ currentBook WRITE setCurrentBook NOTIFY currentBookChanged)
Q_PROPERTY(QString currentFolder READ currentFolder WRITE setCurrentFolder NOTIFY currentFolderChanged)
Q_PROPERTY(QString currentStorage READ currentStorage NOTIFY currentStorageChanged)
@ -60,9 +63,6 @@ class BooksSettings : public QObject
Q_PROPERTY(int orientation READ orientation NOTIFY orientationChanged)
class TextStyle;
// Use sharedInstance() to instantiate this class
BooksSettings();
public:
enum FontSize {
MinFontSize = -5,
@ -77,6 +77,14 @@ public:
OrientationLandscape
};
enum Action {
ActionNone,
ActionPreviousPage,
ActionNextPage
};
// Use sharedInstance() to instantiate this class
explicit BooksSettings(QObject* aParent = Q_NULLPTR);
static QSharedPointer<BooksSettings> sharedInstance();
Q_INVOKABLE bool increaseFontSize();
@ -93,6 +101,12 @@ public:
bool invertColors() const;
void setInvertColors(bool aValue);
Action volumeUpAction() const;
void setVolumeUpAction(int aValue);
Action volumeDownAction() const;
void setVolumeDownAction(int aValue);
QObject* currentBook() const;
void setCurrentBook(QObject* aBook);
@ -113,6 +127,8 @@ Q_SIGNALS:
void textStyleChanged();
void pageDetailsChanged();
void invertColorsChanged();
void volumeUpActionChanged();
void volumeDownActionChanged();
void currentBookChanged();
void currentFolderChanged();
void currentStorageChanged();

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
@ -36,6 +36,8 @@
#include "BooksPaintContext.h"
#include "BooksDialogManager.h"
#include "BooksImageProvider.h"
#include "BooksMediaPlugin.h"
#include "BooksPolicyPlugin.h"
#include "BooksSettings.h"
#include "HarbourDebug.h"
@ -199,9 +201,15 @@ void ZLibrary::run(ZLApplication* aApp)
QQuickView* view = SailfishApp::createView();
QQmlContext* root = view->rootContext();
QQmlEngine* engine = root->engine();
QSharedPointer<BooksSettings> settings = BooksSettings::sharedInstance();
root->engine()->addImageProvider(BooksImageProvider::PROVIDER_ID,
BooksPolicyPlugin::registerTypes(engine, BOOKS_QML_PLUGIN,
BOOKS_QML_PLUGIN_V1, BOOKS_QML_PLUGIN_V2);
BooksMediaPlugin::registerTypes(engine, BOOKS_QML_PLUGIN,
BOOKS_QML_PLUGIN_V1, BOOKS_QML_PLUGIN_V2);
engine->addImageProvider(BooksImageProvider::PROVIDER_ID,
new BooksImageProvider(root));
root->setContextProperty("PointsPerInch", booksPPI);
root->setContextProperty("MaximumHintCount", 1);
root->setContextProperty("BooksSettingsMenu",

View file

@ -83,6 +83,7 @@ Q_DECL_EXPORT int main(int argc, char **argv)
BOOKS_QML_REGISTER(BooksListWatcher, "ListWatcher");
BOOKS_QML_REGISTER(BooksCoverWidget, "BookCover");
BOOKS_QML_REGISTER(BooksHints, "BooksHints");
BOOKS_QML_REGISTER(BooksSettings, "BooksSettings");
HarbourLib::registerTypes(BOOKS_QML_PLUGIN,
BOOKS_QML_PLUGIN_V1, BOOKS_QML_PLUGIN_V2);

View file

@ -99,11 +99,31 @@
<extracomment>Import page placeholder</extracomment>
<translation>Keine neuen Bücher gefunden</translation>
</message>
<message id="harbour-books-book-browser_link-title">
<source>Link</source>
<extracomment>External link menu title</extracomment>
<translation type="unfinished">Link</translation>
</message>
<message id="harbour-books-book-browser_link-open_in_browser">
<source>Open in browser</source>
<extracomment>Open link in browser</extracomment>
<translation type="unfinished">Im Browser öffnen</translation>
</message>
<message id="harbour-books-book-browser_link-copy_to_clipboard">
<source>Copy to clipboard</source>
<extracomment>Copy link to clipboard</extracomment>
<translation>In Zwischenablage kopieren</translation>
</message>
<message id="harbour-books-settings-page-header">
<source>Books</source>
<extracomment>Settings page header</extracomment>
<translation>Bücher</translation>
</message>
<message id="harbour-books-settings-page-display-section_header">
<source>Display</source>
<extracomment>Section header for display settings</extracomment>
<translation type="unfinished">Display</translation>
</message>
<message id="harbour-books-settings-page-font_size_label">
<source>Font size</source>
<extracomment>Slider label</extracomment>
@ -134,6 +154,36 @@
<extracomment>Combo box value for landscape orientation</extracomment>
<translation>Querformat</translation>
</message>
<message id="harbour-books-settings-page-action-none">
<source>No action</source>
<extracomment>Combo box value for no action</extracomment>
<translation type="unfinished">Keine Aktion</translation>
</message>
<message id="harbour-books-settings-page-action-previous_page">
<source>Previous page</source>
<extracomment>Combo box value for previous page action</extracomment>
<translation type="unfinished">Vorherige Seite</translation>
</message>
<message id="harbour-books-settings-page-action-next_page">
<source>Next page</source>
<extracomment>Combo box value for next page action</extracomment>
<translation type="unfinished">Folge Seite</translation>
</message>
<message id="harbour-books-settings-page-media-keys-section_header">
<source>Media keys</source>
<extracomment>Section header for media keys</extracomment>
<translation type="unfinished">Medienschlüssel</translation>
</message>
<message id="harbour-books-settings-page-volume_up-label">
<source>Volume up</source>
<extracomment>Combo box label</extracomment>
<translation type="unfinished">Lautstärke erhöhen</translation>
</message>
<message id="harbour-books-settings-page-volume_down-label">
<source>Volume down</source>
<extracomment>Combo box label</extracomment>
<translation type="unfinished">Lautstärke runter</translation>
</message>
<message id="harbour-books-settings-page-removable-section_header">
<source>Memory card</source>
<extracomment>Section header for memory card settings</extracomment>
@ -149,21 +199,5 @@
<extracomment>Settings field description</extracomment>
<translation type="unfinished">Lassen Sie den Verzeichnisnamen leer, um die gesamte Speicherkarte für Bücher zu scannen.</translation>
</message>
<message id="harbour-books-book-browser_link-title">
<source>Link</source>
<oldsource>External link</oldsource>
<extracomment>External link menu title</extracomment>
<translation type="unfinished">Link</translation>
</message>
<message id="harbour-books-book-browser_link-open_in_browser">
<source>Open in browser</source>
<extracomment>Open link in browser</extracomment>
<translation type="unfinished">Im Browser öffnen</translation>
</message>
<message id="harbour-books-book-browser_link-copy_to_clipboard">
<source>Copy to clipboard</source>
<extracomment>Copy link to clipboard</extracomment>
<translation>In Zwischenablage kopieren</translation>
</message>
</context>
</TS>

View file

@ -99,11 +99,31 @@
<extracomment>Import page placeholder</extracomment>
<translation>Uusia kirjoja ei löytynyt</translation>
</message>
<message id="harbour-books-book-browser_link-title">
<source>Link</source>
<extracomment>External link menu title</extracomment>
<translation type="unfinished">Linkki</translation>
</message>
<message id="harbour-books-book-browser_link-open_in_browser">
<source>Open in browser</source>
<extracomment>Open link in browser</extracomment>
<translation type="unfinished">Avaa selaimessa</translation>
</message>
<message id="harbour-books-book-browser_link-copy_to_clipboard">
<source>Copy to clipboard</source>
<extracomment>Copy link to clipboard</extracomment>
<translation>Kopioi leikepöydälle</translation>
</message>
<message id="harbour-books-settings-page-header">
<source>Books</source>
<extracomment>Settings page header</extracomment>
<translation>Kirjat</translation>
</message>
<message id="harbour-books-settings-page-display-section_header">
<source>Display</source>
<extracomment>Section header for display settings</extracomment>
<translation type="unfinished">Näyttö</translation>
</message>
<message id="harbour-books-settings-page-font_size_label">
<source>Font size</source>
<extracomment>Slider label</extracomment>
@ -134,6 +154,36 @@
<extracomment>Combo box value for landscape orientation</extracomment>
<translation>Vaaka</translation>
</message>
<message id="harbour-books-settings-page-action-none">
<source>No action</source>
<extracomment>Combo box value for no action</extracomment>
<translation type="unfinished">Ei käytössä</translation>
</message>
<message id="harbour-books-settings-page-action-previous_page">
<source>Previous page</source>
<extracomment>Combo box value for previous page action</extracomment>
<translation type="unfinished">Edelliselle sivulle</translation>
</message>
<message id="harbour-books-settings-page-action-next_page">
<source>Next page</source>
<extracomment>Combo box value for next page action</extracomment>
<translation type="unfinished">Seuraavalle sivulle</translation>
</message>
<message id="harbour-books-settings-page-media-keys-section_header">
<source>Media keys</source>
<extracomment>Section header for media keys</extracomment>
<translation type="unfinished">Media näppäimet</translation>
</message>
<message id="harbour-books-settings-page-volume_up-label">
<source>Volume up</source>
<extracomment>Combo box label</extracomment>
<translation type="unfinished">Äänenvoimakkuus ylös</translation>
</message>
<message id="harbour-books-settings-page-volume_down-label">
<source>Volume down</source>
<extracomment>Combo box label</extracomment>
<translation type="unfinished">Äänenvoimakkuus alas</translation>
</message>
<message id="harbour-books-settings-page-removable-section_header">
<source>Memory card</source>
<extracomment>Section header for memory card settings</extracomment>
@ -149,21 +199,5 @@
<extracomment>Settings field description</extracomment>
<translation type="unfinished">Jätä kenttä tyhjäksi käyttää kokonaista muistikorttia.</translation>
</message>
<message id="harbour-books-book-browser_link-title">
<source>Link</source>
<oldsource>External link</oldsource>
<extracomment>External link menu title</extracomment>
<translation type="unfinished">Linkki</translation>
</message>
<message id="harbour-books-book-browser_link-open_in_browser">
<source>Open in browser</source>
<extracomment>Open link in browser</extracomment>
<translation type="unfinished">Avaa selaimessa</translation>
</message>
<message id="harbour-books-book-browser_link-copy_to_clipboard">
<source>Copy to clipboard</source>
<extracomment>Copy link to clipboard</extracomment>
<translation>Kopioi leikepöydälle</translation>
</message>
</context>
</TS>

View file

@ -101,11 +101,31 @@
<extracomment>Import page placeholder</extracomment>
<translation>Новых книг не найдено, вообще ни одной</translation>
</message>
<message id="harbour-books-book-browser_link-title">
<source>Link</source>
<extracomment>External link menu title</extracomment>
<translation>Ссылка</translation>
</message>
<message id="harbour-books-book-browser_link-open_in_browser">
<source>Open in browser</source>
<extracomment>Open link in browser</extracomment>
<translation>Открыть в браузере</translation>
</message>
<message id="harbour-books-book-browser_link-copy_to_clipboard">
<source>Copy to clipboard</source>
<extracomment>Copy link to clipboard</extracomment>
<translation>Скопировать</translation>
</message>
<message id="harbour-books-settings-page-header">
<source>Books</source>
<extracomment>Settings page header</extracomment>
<translation>Книги</translation>
</message>
<message id="harbour-books-settings-page-display-section_header">
<source>Display</source>
<extracomment>Section header for display settings</extracomment>
<translation>Экран</translation>
</message>
<message id="harbour-books-settings-page-font_size_label">
<source>Font size</source>
<extracomment>Slider label</extracomment>
@ -151,20 +171,35 @@
<extracomment>Settings field description</extracomment>
<translation>Если оставить имя папки пустым, то можно будет найти книгу в любой папке на карте памяти. Особого смысла в этой настройке нет, просто так исторически сложилось, что по умолчанию книги искались только в папке Books, а теперь можно вообще где угодно.</translation>
</message>
<message id="harbour-books-book-browser_link-title">
<source>Link</source>
<extracomment>External link menu title</extracomment>
<translation>Ссылка</translation>
<message id="harbour-books-settings-page-media-keys-section_header">
<source>Media keys</source>
<extracomment>Section header for media keys</extracomment>
<translation>Кнопки</translation>
</message>
<message id="harbour-books-book-browser_link-open_in_browser">
<source>Open in browser</source>
<extracomment>Open link in browser</extracomment>
<translation>Открыть в браузере</translation>
<message id="harbour-books-settings-page-action-none">
<source>No action</source>
<extracomment>Combo box value for no action</extracomment>
<translation>Ничего не делать</translation>
</message>
<message id="harbour-books-book-browser_link-copy_to_clipboard">
<source>Copy to clipboard</source>
<extracomment>Copy link to clipboard</extracomment>
<translation>Скопировать</translation>
<message id="harbour-books-settings-page-action-previous_page">
<source>Previous page</source>
<extracomment>Combo box value for previous page action</extracomment>
<translation>Предыдущая страница</translation>
</message>
<message id="harbour-books-settings-page-action-next_page">
<source>Next page</source>
<extracomment>Combo box value for next page action</extracomment>
<translation>Следующая страница</translation>
</message>
<message id="harbour-books-settings-page-volume_up-label">
<source>Volume up</source>
<extracomment>Combo box label</extracomment>
<translation>Громкость вверх</translation>
</message>
<message id="harbour-books-settings-page-volume_down-label">
<source>Volume down</source>
<extracomment>Combo box label</extracomment>
<translation>Громкость вниз</translation>
</message>
</context>
</TS>

View file

@ -99,11 +99,31 @@
<extracomment>Import page placeholder</extracomment>
<translation>Inga nya böcker hittades</translation>
</message>
<message id="harbour-books-book-browser_link-title">
<source>Link</source>
<extracomment>External link menu title</extracomment>
<translation>Extern länk</translation>
</message>
<message id="harbour-books-book-browser_link-open_in_browser">
<source>Open in browser</source>
<extracomment>Open link in browser</extracomment>
<translation>Öppna i webbläsaren</translation>
</message>
<message id="harbour-books-book-browser_link-copy_to_clipboard">
<source>Copy to clipboard</source>
<extracomment>Copy link to clipboard</extracomment>
<translation>Kopiera till urklipp</translation>
</message>
<message id="harbour-books-settings-page-header">
<source>Books</source>
<extracomment>Settings page header</extracomment>
<translation>Böcker</translation>
</message>
<message id="harbour-books-settings-page-display-section_header">
<source>Display</source>
<extracomment>Section header for display settings</extracomment>
<translation type="unfinished">Skärm</translation>
</message>
<message id="harbour-books-settings-page-font_size_label">
<source>Font size</source>
<extracomment>Slider label</extracomment>
@ -134,6 +154,36 @@
<extracomment>Combo box value for landscape orientation</extracomment>
<translation>Liggande</translation>
</message>
<message id="harbour-books-settings-page-action-none">
<source>No action</source>
<extracomment>Combo box value for no action</extracomment>
<translation type="unfinished">Ingen action</translation>
</message>
<message id="harbour-books-settings-page-action-previous_page">
<source>Previous page</source>
<extracomment>Combo box value for previous page action</extracomment>
<translation type="unfinished">Föregående sida</translation>
</message>
<message id="harbour-books-settings-page-action-next_page">
<source>Next page</source>
<extracomment>Combo box value for next page action</extracomment>
<translation type="unfinished">Nästa sida</translation>
</message>
<message id="harbour-books-settings-page-media-keys-section_header">
<source>Media keys</source>
<extracomment>Section header for media keys</extracomment>
<translation type="unfinished">Mediaknappar</translation>
</message>
<message id="harbour-books-settings-page-volume_up-label">
<source>Volume up</source>
<extracomment>Combo box label</extracomment>
<translation type="unfinished">Höj volymen</translation>
</message>
<message id="harbour-books-settings-page-volume_down-label">
<source>Volume down</source>
<extracomment>Combo box label</extracomment>
<translation type="unfinished">Sänk volymen</translation>
</message>
<message id="harbour-books-settings-page-removable-section_header">
<source>Memory card</source>
<extracomment>Section header for memory card settings</extracomment>
@ -149,21 +199,5 @@
<extracomment>Settings field description</extracomment>
<translation>Lämna mappnamnet tomt för att söka igenom hela minneskortet efter böcker.</translation>
</message>
<message id="harbour-books-book-browser_link-title">
<source>Link</source>
<oldsource>External link</oldsource>
<extracomment>External link menu title</extracomment>
<translation>Extern länk</translation>
</message>
<message id="harbour-books-book-browser_link-open_in_browser">
<source>Open in browser</source>
<extracomment>Open link in browser</extracomment>
<translation>Öppna i webbläsaren</translation>
</message>
<message id="harbour-books-book-browser_link-copy_to_clipboard">
<source>Copy to clipboard</source>
<extracomment>Copy link to clipboard</extracomment>
<translation>Kopiera till urklipp</translation>
</message>
</context>
</TS>

View file

@ -65,7 +65,7 @@
<message id="harbour-books-storage-menu-settings">
<source>Settings</source>
<extracomment>Pulley menu item</extracomment>
<translation type="unfinished"></translation>
<translation>Settings</translation>
</message>
<message id="harbour-books-storage-menu-scan_downloads">
<source>Scan downloads</source>
@ -99,11 +99,31 @@
<extracomment>Import page placeholder</extracomment>
<translation>No new books found</translation>
</message>
<message id="harbour-books-book-browser_link-title">
<source>Link</source>
<extracomment>External link menu title</extracomment>
<translation>Link</translation>
</message>
<message id="harbour-books-book-browser_link-open_in_browser">
<source>Open in browser</source>
<extracomment>Open link in browser</extracomment>
<translation>Open in browser</translation>
</message>
<message id="harbour-books-book-browser_link-copy_to_clipboard">
<source>Copy to clipboard</source>
<extracomment>Copy link to clipboard</extracomment>
<translation>Copy to clipboard</translation>
</message>
<message id="harbour-books-settings-page-header">
<source>Books</source>
<extracomment>Settings page header</extracomment>
<translation>Books</translation>
</message>
<message id="harbour-books-settings-page-display-section_header">
<source>Display</source>
<extracomment>Section header for display settings</extracomment>
<translation>Display</translation>
</message>
<message id="harbour-books-settings-page-font_size_label">
<source>Font size</source>
<extracomment>Slider label</extracomment>
@ -134,6 +154,36 @@
<extracomment>Combo box value for landscape orientation</extracomment>
<translation>Landscape</translation>
</message>
<message id="harbour-books-settings-page-media-keys-section_header">
<source>Media keys</source>
<extracomment>Section header for media keys</extracomment>
<translation>Media keys</translation>
</message>
<message id="harbour-books-settings-page-volume_up-label">
<source>Volume up</source>
<extracomment>Combo box label</extracomment>
<translation>Volume up</translation>
</message>
<message id="harbour-books-settings-page-volume_down-label">
<source>Volume down</source>
<extracomment>Combo box label</extracomment>
<translation>Volume down</translation>
</message>
<message id="harbour-books-settings-page-action-none">
<source>No action</source>
<extracomment>Combo box value for no action</extracomment>
<translation>No action</translation>
</message>
<message id="harbour-books-settings-page-action-previous_page">
<source>Previous page</source>
<extracomment>Combo box value for previous page action</extracomment>
<translation>Previous page</translation>
</message>
<message id="harbour-books-settings-page-action-next_page">
<source>Next page</source>
<extracomment>Combo box value for next page action</extracomment>
<translation>Next page</translation>
</message>
<message id="harbour-books-settings-page-removable-section_header">
<source>Memory card</source>
<extracomment>Section header for memory card settings</extracomment>
@ -149,20 +199,5 @@
<extracomment>Settings field description</extracomment>
<translation>Leave the folder name empty to scan the entire memory card for books.</translation>
</message>
<message id="harbour-books-book-browser_link-title">
<source>Link</source>
<extracomment>External link menu title</extracomment>
<translation>Link</translation>
</message>
<message id="harbour-books-book-browser_link-open_in_browser">
<source>Open in browser</source>
<extracomment>Open link in browser</extracomment>
<translation>Open in browser</translation>
</message>
<message id="harbour-books-book-browser_link-copy_to_clipboard">
<source>Copy to clipboard</source>
<extracomment>Copy link to clipboard</extracomment>
<translation>Copy to clipboard</translation>
</message>
</context>
</TS>