Commit 34dba744 authored by Sebastian Kügler's avatar Sebastian Kügler

Add 'applications/webbrowser/' from commit 'eaf2a1632c8a68604c1fa0c4d78e3038e87f36cb'

git-subtree-dir: applications/webbrowser
git-subtree-mainline: 64cc339ae0dffae22de8bc292dd21adb34bf4b5b
git-subtree-split: eaf2a1632c8a68604c1fa0c4d78e3038e87f36cb
parent 867328cd
project(plasma-mobile-browser)
cmake_minimum_required(VERSION 2.8.10.1)
################# Disallow in-source build #################
if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
message(FATAL_ERROR "plasma-mobile-browser requires an out of source build. Please create a separate build directory and run 'cmake path_to_plasma-mobile-browser [options]' there.")
endif()
# Make CPack available to easy generate binary packages
include(CPack)
include(FeatureSummary)
################# set KDE specific information #################
find_package(ECM 0.0.8 REQUIRED NO_MODULE)
find_package(PkgConfig)
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})
include(KDEInstallDirs)
include(KDECMakeSettings)
include(KDECompilerSettings)
find_package(Qt5 REQUIRED NO_MODULE COMPONENTS Core Quick Test Gui WebEngine)
#add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0)
if(KDE_PLATFORM_FEATURE_DISABLE_DEPRECATED)
set(KDE_NO_DEPRECATED TRUE)
set(CMAKE_AUTOMOC_MOC_OPTIONS "-DKDE_NO_DEPRECATED")
endif()
################# Enable C++11 features for clang and gcc #################
if(UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++0x")
endif()
################# now find all used packages #################
set (QT_MIN_VERSION "5.4.0")
find_package(KF5Plasma REQUIRED NO_MODULE)
find_package(KF5PlasmaQuick REQUIRED NO_MODULE)
find_package(KF5Declarative REQUIRED NO_MODULE)
find_package(KF5KIO REQUIRED NO_MODULE)
#find_package(KF5Activities REQUIRED NO_MODULE)
find_package(KF5Declarative REQUIRED NO_MODULE)
find_package(PkgConfig)
#########################################################################
add_subdirectory(src)
add_subdirectory(autotests)
install( PROGRAMS angelfish.desktop DESTINATION ${XDG_APPS_INSTALL_DIR} )
plasma_install_package(package org.kde.plasma.satellite.angelfish packages package)
# install(FILES plasma-mobile-browser.desktop DESTINATION ${XDG_APPS_INSTALL_DIR})
# Plasma Mobile Browser
This is an experimental webbrowser designed to
- be used on small mobile devices,
- integrate well in Plasma workspaces
It is built on top of QtWebEngine, and thus requires Qt 5.4.
Preliminary TODO:
- browser navigation: back + forward + reload (done)
- browser status (done)
- Implement URL bar (done)
- Error handler in UI (done)
- in-window navigation: tabs vs. top bar
- SSL error handler
- Touch actions (pinch?)
- user-agent to request mobile site
- adblock
- kwallet integration
In progress:
- bookmarks store (done)
- bookmarks model (done)
- bookmarks UI
- show bookmarks (done)
- add / remove
[Desktop Entry]
Name=Angelfish Web Browser
Comment=Mobile web browser
GenericName=Web Browser
Encoding=UTF-8
Icon=internet-web-browser
Exec=angelfish
Type=Application
X-DocPath=angelfish/index.html
Categories=Qt;KDE;Network;WebBrowser;
Terminal=false
MimeType=text/html;
InitialPreference=10
include(ECMAddTests)
find_package(Qt5 ${REQUIRED_QT_VERSION} CONFIG REQUIRED Test)
include_directories(../src)
ecm_add_test(urlmodeltest.cpp ../src/urlmodel.cpp
TEST_NAME urlmodeltest
LINK_LIBRARIES Qt5::Test )
[
{
"bookmarked": true,
"icon": "text-html",
"lastVisited": "Sat Dec 13 02:29:58 2014",
"title": "Nieuws",
"url": "http://m.nos.nl"
},
{
"bookmarked": true,
"icon": "/home/sebas/Pictures/avatar-small.jpg",
"lastVisited": "Sat Dec 13 02:29:58 2014",
"preview": "/home/sebas/Pictures/avatar-small.jpg",
"title": "sebas' blog",
"url": "http://vizZzion.org"
},
{
"bookmarked": true,
"icon": "text-html",
"lastVisited": "Sat Dec 13 02:29:58 2014",
"title": "Linux Weekly News",
"url": "http://lwn.net"
},
{
"bookmarked": true,
"icon": "text-html",
"lastVisited": "Sat Dec 13 02:29:58 2014",
"title": "Tweakers.net",
"url": "http://tweakers.net"
},
{
"bookmarked": false,
"icon": "text-html",
"lastVisited": "Sat Dec 13 02:29:58 2014",
"title": "Wikipedia",
"url": "http://en.wikipedia.org"
},
{
"bookmarked": true,
"icon": "plasma",
"lastVisited": "Sat Dec 13 02:29:58 2014",
"title": "Plasma Mobile",
"url": "http://plasma-mobile.org"
}
]
/*
* Copyright 2014 Alex Richardson <arichardson.kde@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License version 2 as published by the Free Software Foundation;
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <QtTest/QTest>
#include <QDebug>
#include <QJsonDocument>
#include <QFileInfo>
#include <QJsonArray>
#include <QJsonObject>
#include <QSignalSpy>
#include "urlmodel.h"
using namespace AngelFish;
class UrlModelTest : public QObject
{
Q_OBJECT
static void compare(const QJsonArray &data, QAbstractListModel *model)
{
QCOMPARE(data.count(), model->rowCount(QModelIndex()));
QStringList roleNames;
foreach (auto rn, model->roleNames()) {
roleNames << rn;
}
for (int i = 0; i < data.count(); i++) {
auto index = model->index(i);
QVariantMap vm = data.at(i).toObject().toVariantMap();
foreach (auto k, vm.keys()) {
QVERIFY2(roleNames.contains(k), QString("Key \"" + k + "\" not found roleNames").toLocal8Bit());
}
foreach (int k, model->roleNames().keys()) {
UrlModel *urlmodel = static_cast<UrlModel*>(model);
const QString ks = urlmodel->key(k);
QVariant ori = vm[ks];
QVariant val = model->data(index, k);
// qDebug() << "Comparing " << ks << k;
// qDebug() << " " << (ori == val) << ori << " == " << val;
if (!vm.keys().contains(ks)) {
//QVERIFY(val == QVariant());
continue;
}
if (ks == "lastVisited") {
auto dt = QDateTime::fromString(model->data(index, k).toString(), Qt::ISODate);
QCOMPARE(vm[ks].toDateTime(), dt);
} else {
QCOMPARE(vm[ks], model->data(index, k));
}
}
QString u = model->data(index, UrlModel::url).toString();
//QVERIFY(!u.isEmpty());
// qDebug() << i << "URL: " << u;
}
};
static QJsonArray readFile(const QString &fileName)
{
QFile jsonFile(fileName);
jsonFile.open(QIODevice::ReadOnly);
//QJsonDocument jdoc = QJsonDocument::fromBinaryData(jsonFile.readAll());
QJsonDocument jdoc = QJsonDocument::fromJson(jsonFile.readAll());
jsonFile.close();
return jdoc.array();
}
private Q_SLOTS:
void init()
{
m_bookmarksModel = new UrlModel(QStringLiteral("urlmodeltest.json"), this);
}
void cleanup()
{
delete m_bookmarksModel;
}
void initTestCase()
{
init();
{
QJsonObject u;
u.insert(m_bookmarksModel->key(UrlModel::url), QStringLiteral("http://m.nos.nl"));
u.insert(m_bookmarksModel->key(UrlModel::title), QStringLiteral("Nieuws"));
u.insert(m_bookmarksModel->key(UrlModel::icon), QStringLiteral("text-html"));
u.insert(m_bookmarksModel->key(UrlModel::bookmarked), true);
u.insert(m_bookmarksModel->key(UrlModel::lastVisited), QDateTime::currentDateTime().toString(Qt::ISODate));
m_data << u;
}
{
QJsonObject u;
u.insert(m_bookmarksModel->key(UrlModel::url), QStringLiteral("http://vizZzion.org"));
u.insert(m_bookmarksModel->key(UrlModel::title), QStringLiteral("sebas' blog"));
u.insert(m_bookmarksModel->key(UrlModel::icon), QStringLiteral("/home/sebas/Pictures/avatar-small.jpg"));
u.insert(m_bookmarksModel->key(UrlModel::preview), QStringLiteral("/home/sebas/Pictures/avatar-small.jpg"));
u.insert(m_bookmarksModel->key(UrlModel::bookmarked), true);
u.insert(m_bookmarksModel->key(UrlModel::lastVisited), QDateTime::currentDateTime().toString(Qt::ISODate));
m_data << u;
}
{
QJsonObject u;
u.insert(m_bookmarksModel->key(UrlModel::url), QStringLiteral("http://lwn.net"));
u.insert(m_bookmarksModel->key(UrlModel::title), QStringLiteral("Linux Weekly News"));
u.insert(m_bookmarksModel->key(UrlModel::icon), QStringLiteral("text-html"));
u.insert(m_bookmarksModel->key(UrlModel::bookmarked), true);
u.insert(m_bookmarksModel->key(UrlModel::lastVisited), QDateTime::currentDateTime().toString(Qt::ISODate));
m_data << u;
}
{
QJsonObject u;
u.insert(m_bookmarksModel->key(UrlModel::url), QStringLiteral("http://tweakers.net"));
u.insert(m_bookmarksModel->key(UrlModel::title), QStringLiteral("Tweakers.net"));
u.insert(m_bookmarksModel->key(UrlModel::icon), QStringLiteral("text-html"));
u.insert(m_bookmarksModel->key(UrlModel::bookmarked), true);
u.insert(m_bookmarksModel->key(UrlModel::lastVisited), QDateTime::currentDateTime().toString(Qt::ISODate));
m_data << u;
}
{
QJsonObject u;
u.insert(m_bookmarksModel->key(UrlModel::url), QStringLiteral("http://en.wikipedia.org"));
u.insert(m_bookmarksModel->key(UrlModel::title), QStringLiteral("Wikipedia"));
u.insert(m_bookmarksModel->key(UrlModel::icon), QStringLiteral("text-html"));
//u.insert(m_bookmarksModel->key(UrlModel::preview), QStringLiteral("/home/sebas/Pictures/avatar-small.jpg"));
u.insert(m_bookmarksModel->key(UrlModel::bookmarked), false);
u.insert(m_bookmarksModel->key(UrlModel::lastVisited), QDateTime::currentDateTime().toString(Qt::ISODate));
m_data << u;
}
{
QJsonObject u;
u.insert(m_bookmarksModel->key(UrlModel::url), QStringLiteral("http://plasma-mobile.org"));
u.insert(m_bookmarksModel->key(UrlModel::title), QStringLiteral("Plasma Mobile"));
u.insert(m_bookmarksModel->key(UrlModel::icon), QStringLiteral("plasma"));
u.insert(m_bookmarksModel->key(UrlModel::bookmarked), true);
u.insert(m_bookmarksModel->key(UrlModel::lastVisited), QDateTime::currentDateTime().toString(Qt::ISODate));
m_data << u;
}
cleanup();
};
void testEmpty()
{
QVERIFY(m_data.count() > 0);
QVERIFY(m_bookmarksModel->rowCount(QModelIndex()) == 0);
};
void testSetSourceData() {
m_bookmarksModel->setSourceData(m_data);
// TODO wait for update!
// ...
QVERIFY(m_bookmarksModel->rowCount(QModelIndex()) > 0);
QCOMPARE(m_bookmarksModel->rowCount(QModelIndex()), m_data.count());
QCOMPARE(m_data, m_bookmarksModel->sourceData());
}
void testSave()
{
const QString fileName("savetest.json");
// save, reset, load...
auto saveModel = new UrlModel(fileName);
saveModel->setSourceData(m_data);
QVERIFY(saveModel->save());
const QString fpath = saveModel->filePath();
delete saveModel;
auto loadModel = new UrlModel(fileName);
QVERIFY(loadModel->load());
QJsonArray written = readFile(fpath);
// return;
compare(written, loadModel);
delete loadModel;
};
void compareData()
{
m_bookmarksModel->setSourceData(m_data);
compare(m_data, m_bookmarksModel);
}
void testLoad()
{
const QString file1 = QFINDTESTDATA("data/simplebookmarks.json");
auto model = new UrlModel(file1, this);
QVERIFY(model->load());
QVERIFY(model->rowCount(QModelIndex()));
compare(readFile(file1), model);
};
void testAdd() {
m_bookmarksModel->setSourceData(m_data);
// Adding bookmarks
compare(m_data, m_bookmarksModel);
{
int i0 = m_bookmarksModel->rowCount(QModelIndex());
QJsonObject u;
u.insert(m_bookmarksModel->key(UrlModel::url), QStringLiteral("http://kde.org"));
u.insert(m_bookmarksModel->key(UrlModel::title), QStringLiteral("KDE"));
u.insert(m_bookmarksModel->key(UrlModel::icon), QStringLiteral("kde-start-here"));
u.insert(m_bookmarksModel->key(UrlModel::bookmarked), true);
u.insert(m_bookmarksModel->key(UrlModel::lastVisited), QDateTime::currentDateTime().toString(Qt::ISODate));
//m_data << u;
m_bookmarksModel->add(u);
int i1 = m_bookmarksModel->rowCount(QModelIndex());
QCOMPARE(i0 + 1, i1);
QJsonArray copy = m_data;
copy << u;
compare(copy, m_bookmarksModel);
}
{ // dupe, should not insert
// reset
m_bookmarksModel->setSourceData(m_data);
int i0 = m_bookmarksModel->rowCount(QModelIndex());
QJsonObject u;
u.insert(m_bookmarksModel->key(UrlModel::url), QStringLiteral("http://plasma-mobile.org"));
u.insert(m_bookmarksModel->key(UrlModel::title), QStringLiteral("Plasma Mobile"));
u.insert(m_bookmarksModel->key(UrlModel::icon), QStringLiteral("plasma"));
u.insert(m_bookmarksModel->key(UrlModel::bookmarked), true);
u.insert(m_bookmarksModel->key(UrlModel::lastVisited), QDateTime::currentDateTime().toString(Qt::ISODate));
m_bookmarksModel->add(u);
int i2 = m_bookmarksModel->rowCount(QModelIndex());
QCOMPARE(i0, i2);
QJsonArray copy = m_data;
copy << u;
QCOMPARE(copy.count() - 1, m_bookmarksModel->rowCount(QModelIndex()));
//QVERIFY(!compare(copy, m_bookmarksModel));
}
};
void testDataChanged()
{
//QSignalSpy spy(m_bookmarksModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &, const QVector<int> &)));
QSignalSpy spy(m_bookmarksModel, SIGNAL(modelReset()));
{
QJsonObject u;
u.insert(m_bookmarksModel->key(UrlModel::url), QStringLiteral("http://kde.org"));
u.insert(m_bookmarksModel->key(UrlModel::title), QStringLiteral("KDE"));
u.insert(m_bookmarksModel->key(UrlModel::icon), QStringLiteral("kde-start-here"));
u.insert(m_bookmarksModel->key(UrlModel::bookmarked), true);
u.insert(m_bookmarksModel->key(UrlModel::lastVisited), QDateTime::currentDateTime().toString(Qt::ISODate));
//m_data << u;
m_bookmarksModel->add(u);
m_bookmarksModel->add(u);
}
QCOMPARE(spy.count(), 1);
QSignalSpy spy2(m_bookmarksModel, SIGNAL(modelReset()));
m_bookmarksModel->remove("http://kde.org");
QCOMPARE(spy2.count(), 1);
}
void testRemove() {
m_bookmarksModel->setSourceData(m_data);
// Remove a bookmark
int c1 = m_bookmarksModel->rowCount(QModelIndex());
const QString r = "http://lwn.net";
m_bookmarksModel->remove(r);
int c2 = m_bookmarksModel->rowCount(QModelIndex());
QCOMPARE(c1, c2 + 1);
QStringList urls;
for (int i = 0; i < c2; i++) {
auto index = m_bookmarksModel->index(i);
const QString r = m_bookmarksModel->data(index, UrlModel::url).toString();
urls << r;
}
int c3 = m_bookmarksModel->rowCount(QModelIndex());
foreach (auto r, urls) {
c3--;
m_bookmarksModel->remove(r);
QCOMPARE(m_bookmarksModel->rowCount(QModelIndex()), c3);
}
QCOMPARE(m_bookmarksModel->rowCount(QModelIndex()), 0);
};
void testNotify() {
m_bookmarksModel->setSourceData(m_data);
// save to file while waiting for model update...
};
private: // disable from here for testing just the above
private:
QJsonArray m_data;
QJsonArray m_empty;
UrlModel* m_bookmarksModel;
};
QTEST_MAIN(UrlModelTest)
#include "urlmodeltest.moc"
/***************************************************************************
* *
* Copyright 2014-2015 Sebastian Kügler <sebas@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
* *
***************************************************************************/
import QtQuick 2.3
//import QtQuick.Controls 1.0
//import QtWebEngine 1.0
import QtQuick.Layouts 1.0
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
Item {
// id: options
//Rectangle { anchors.fill: parent; color: "orange"; opacity: 0.5; }
anchors.fill: parent
ListView {
anchors.fill: parent
spacing: units.smallSpacing
interactive: height < contentHeight
model: browserManager.bookmarks
delegate: UrlDelegate {
onRemoved: browserManager.removeBookmark(url);
}
}
Component.onCompleted: print("Bookmarks.qml complete.");
}
/***************************************************************************
* *
* Copyright 2014-2015 Sebastian Kügler <sebas@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
* *
***************************************************************************/
import QtQuick 2.3
//import QtWebEngine 1.0
//import QtQuick.Controls 1.0
//import QtQuick.Controls.Styles 1.0
import QtQuick.Layouts 1.0
//import QtQuick.Window 2.1
//import QtQuick.Controls.Private 1.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
Rectangle {
id: contentView
//state: "hidden"
state: "hidden"
property string title: ""
color: theme.backgroundColor
Rectangle {
color: "white"
opacity: 0.6
anchors.fill: parent
}
opacity: state == "hidden" ? 0.0 : 1.0
Behavior on opacity {
NumberAnimation {
duration: units.longDuration/2;
easing.type: Easing.InOutQuad
}
}
MouseArea {
// block intput from arriving in the webview
anchors.fill: parent
visible: contentView.state != "hidden"
onPressed: {
mouse.accepted = true;
print("Blocked Mouse.");
}