Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
Plasma Mobile
Angelfish
Commits
de240d92
Commit
de240d92
authored
Mar 26, 2020
by
Marco Martin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
base on desktop file for app name/icon
open external links in external browser
parent
6092d883
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
317 additions
and
10 deletions
+317
-10
CMakeLists.txt
CMakeLists.txt
+1
-1
src/CMakeLists.txt
src/CMakeLists.txt
+11
-1
src/contents/webapp-ui/WebAppView.qml
src/contents/webapp-ui/WebAppView.qml
+270
-0
src/contents/webapp-ui/webapp.qml
src/contents/webapp-ui/webapp.qml
+2
-1
src/urlutils.cpp
src/urlutils.cpp
+5
-0
src/urlutils.h
src/urlutils.h
+1
-0
src/webapp-resources.qrc
src/webapp-resources.qrc
+1
-0
src/webappmain.cpp
src/webappmain.cpp
+26
-7
No files found.
CMakeLists.txt
View file @
de240d92
...
...
@@ -30,7 +30,7 @@ include(KDECompilerSettings NO_POLICY_SCOPE)
################# Find dependencies #################
find_package
(
Qt5
${
QT_MIN_VERSION
}
REQUIRED NO_MODULE COMPONENTS Core Quick Test Gui Svg QuickControls2 Sql
)
find_package
(
KF5
${
KF5_MIN_VERSION
}
REQUIRED COMPONENTS Kirigami2 Purpose I18n
)
find_package
(
KF5
${
KF5_MIN_VERSION
}
REQUIRED COMPONENTS Kirigami2 Purpose I18n
Config CoreAddons
)
# Necessary to support QtWebEngine installed in a different prefix than the rest of Qt (e.g flatpak)
find_package
(
Qt5WebEngine REQUIRED
)
...
...
src/CMakeLists.txt
View file @
de240d92
...
...
@@ -32,6 +32,16 @@ set(angelfish_webapp_SRCS
qt5_add_resources
(
WEBAPP_RESOURCES webapp-resources.qrc
)
add_executable
(
angelfish-webapp
${
angelfish_webapp_SRCS
}
${
RESOURCES
}
${
WEBAPP_RESOURCES
}
)
target_link_libraries
(
angelfish-webapp Qt5::Core Qt5::Qml Qt5::Quick Qt5::Sql Qt5::Svg Qt5::WebEngine KF5::I18n
)
target_link_libraries
(
angelfish-webapp
Qt5::Core
Qt5::Qml
Qt5::Quick
Qt5::Sql
Qt5::Svg
Qt5::WebEngine
KF5::I18n
KF5::CoreAddons
KF5::ConfigCore
KF5::ConfigGui
)
install
(
TARGETS angelfish-webapp
${
KF5_INSTALL_TARGETS_DEFAULT_ARGS
}
)
src/contents/webapp-ui/WebAppView.qml
0 → 100644
View file @
de240d92
/***************************************************************************
* *
* 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
2.4
as
Controls
import
QtQuick
.
Window
2.1
import
QtQuick
.
Layouts
1.3
import
QtWebEngine
1.7
import
org
.
kde
.
kirigami
2.4
as
Kirigami
import
org
.
kde
.
mobile
.
angelfish
1.0
WebEngineView
{
id
:
webEngineView
property
string
errorCode
:
""
property
string
errorString
:
""
property
bool
privateMode
:
false
property
alias
userAgent
:
userAgent
// loadingActive property is set to true when loading is started
// and turned to false only after succesful or failed loading. It
// is possible to set it to false by calling stopLoading method.
//
// The property was introduced as it triggers visibility of the webEngineView
// in the other parts of the code. When using loading that is linked
// to visibility, stop/start loading was observed in some conditions. It looked as if
// there is an internal optimization of webengine in the case of parallel
// loading of several pages that could use visibility as one of the decision
// making parameters.
property
bool
loadingActive
:
false
property
bool
reloadOnVisible
:
true
// URL that was requested and should be used
// as a base for user interaction. It reflects
// last request (successful or failed)
property
url
requestedUrl
:
url
UserAgentGenerator
{
id
:
userAgent
onUserAgentChanged
:
webEngineView
.
reload
()
}
profile
{
offTheRecord
:
privateMode
httpUserAgent
:
userAgent
.
userAgent
onDownloadRequested
:
{
// if we don't accept the request right away, it will be deleted
download
.
accept
()
// therefore just stop the download again as quickly as possible,
// and ask the user for confirmation
download
.
pause
()
questionLoader
.
setSource
(
"
DownloadQuestion.qml
"
)
questionLoader
.
item
.
download
=
download
questionLoader
.
item
.
visible
=
true
}
onDownloadFinished
:
{
if
(
download
.
state
===
WebEngineDownloadItem
.
DownloadCompleted
)
{
showPassiveNotification
(
i18n
(
"
Download finished
"
))
}
else
if
(
download
.
state
===
WebEngineDownloadItem
.
DownloadInterrupted
)
{
showPassiveNotification
(
i18n
(
"
Download failed
"
))
console
.
log
(
"
Download interrupt reason:
"
+
download
.
interruptReason
)
}
else
if
(
download
.
state
===
WebEngineDownloadItem
.
DownloadCancelled
)
{
console
.
log
(
"
Download cancelled by the user
"
)
}
}
}
settings
{
autoLoadImages
:
webBrowser
.
settings
.
webAutoLoadImages
javascriptEnabled
:
webBrowser
.
settings
.
webJavascriptEnabled
// Disable builtin error pages in favor of our own
errorPageEnabled
:
false
// Load larger touch icons
touchIconsEnabled
:
true
// Disable scrollbars on mobile
showScrollBars
:
!
Kirigami
.
Settings
.
isMobile
}
// Custom context menu
Controls.Menu
{
property
ContextMenuRequest
request
id
:
contextMenu
Controls.MenuItem
{
enabled
:
contextMenu
.
request
!=
null
&&
(
contextMenu
.
request
.
editFlags
&
ContextMenuRequest
.
CanCopy
)
!=
0
text
:
i18n
(
"
Copy
"
)
onTriggered
:
webEngineView
.
triggerWebAction
(
WebEngineView
.
Copy
)
}
Controls.MenuItem
{
enabled
:
contextMenu
.
request
!=
null
&&
(
contextMenu
.
request
.
editFlags
&
ContextMenuRequest
.
CanCut
)
!=
0
text
:
i18n
(
"
Cut
"
)
onTriggered
:
webEngineView
.
triggerWebAction
(
WebEngineView
.
Cut
)
}
Controls.MenuItem
{
enabled
:
contextMenu
.
request
!=
null
&&
(
contextMenu
.
request
.
editFlags
&
ContextMenuRequest
.
CanPaste
)
!=
0
text
:
i18n
(
"
Paste
"
)
onTriggered
:
webEngineView
.
triggerWebAction
(
WebEngineView
.
Paste
)
}
Controls.MenuItem
{
enabled
:
contextMenu
.
request
!=
null
&&
contextMenu
.
request
.
selectedText
text
:
contextMenu
.
request
&&
contextMenu
.
request
.
selectedText
?
i18n
(
"
Search online for '%1'
"
,
contextMenu
.
request
.
selectedText
)
:
i18n
(
"
Search online
"
)
onTriggered
:
Qt
.
openUrlExternally
(
UrlUtils
.
urlFromUserInput
(
BrowserManager
.
searchBaseUrl
+
contextMenu
.
request
.
selectedText
));
}
Controls.MenuItem
{
enabled
:
contextMenu
.
request
!==
null
&&
contextMenu
.
request
.
linkUrl
!==
""
text
:
i18n
(
"
Copy Url
"
)
onTriggered
:
webEngineView
.
triggerWebAction
(
WebEngineView
.
CopyLinkToClipboard
)
}
Controls.MenuItem
{
text
:
i18n
(
"
Download
"
)
onTriggered
:
webEngineView
.
triggerWebAction
(
WebEngineView
.
DownloadLinkToDisk
)
}
}
focus
:
true
onLoadingChanged
:
{
//print("Loading: " + loading);
print
(
"
url:
"
+
loadRequest
.
url
)
//print(" icon: " + webEngineView.icon)
//print(" title: " + webEngineView.title)
/* Handle
* - WebEngineView::LoadStartedStatus,
* - WebEngineView::LoadStoppedStatus,
* - WebEngineView::LoadSucceededStatus and
* - WebEngineView::LoadFailedStatus
*/
var
ec
=
""
;
var
es
=
""
;
if
(
loadRequest
.
status
===
WebEngineView
.
LoadStartedStatus
)
{
loadingActive
=
true
;
}
if
(
loadRequest
.
status
===
WebEngineView
.
LoadSucceededStatus
)
{
if
(
!
privateMode
)
{
var
request
=
new
Object
;
// FIXME
request
.
url
=
currentWebView
.
url
;
request
.
title
=
currentWebView
.
title
;
request
.
icon
=
currentWebView
.
icon
;
BrowserManager
.
addToHistory
(
request
);
BrowserManager
.
updateLastVisited
(
currentWebView
.
url
);
}
loadingActive
=
false
;
}
if
(
loadRequest
.
status
===
WebEngineView
.
LoadFailedStatus
)
{
print
(
"
Load failed:
"
+
loadRequest
.
errorCode
+
"
"
+
loadRequest
.
errorString
);
print
(
"
Load failed url:
"
+
loadRequest
.
url
+
"
"
+
url
);
ec
=
loadRequest
.
errorCode
;
es
=
loadRequest
.
errorString
;
loadingActive
=
false
;
// update requested URL only after its clear that it fails.
// Otherwise, its updated as a part of url property update.
if
(
requestedUrl
!==
loadRequest
.
url
)
requestedUrl
=
loadRequest
.
url
;
}
errorCode
=
ec
;
errorString
=
es
;
}
Component.onCompleted
:
{
print
(
"
WebView completed.
"
);
var
settings
=
webEngineView
.
settings
;
print
(
"
Settings:
"
+
settings
);
}
onIconChanged
:
{
if
(
icon
&&
!
privateMode
)
BrowserManager
.
updateIcon
(
url
,
icon
)
}
onNewViewRequested
:
{
if
(
UrlUtils
.
urlHost
(
request
.
requestedUrl
)
===
UrlUtils
.
urlHost
(
BrowserManager
.
initialUrl
))
{
url
=
request
.
requestedUrl
;
}
else
{
Qt
.
openUrlExternally
(
request
.
requestedUrl
);
}
}
onUrlChanged
:
{
if
(
requestedUrl
!==
url
)
{
requestedUrl
=
url
;
}
}
onFullScreenRequested
:
{
request
.
accept
()
if
(
webBrowser
.
visibility
!==
Window
.
FullScreen
)
webBrowser
.
showFullScreen
()
else
webBrowser
.
showNormal
()
}
onContextMenuRequested
:
{
request
.
accepted
=
true
// Make sure QtWebEngine doesn't show its own context menu.
contextMenu
.
request
=
request
contextMenu
.
x
=
request
.
x
contextMenu
.
y
=
request
.
y
contextMenu
.
open
()
}
onAuthenticationDialogRequested
:
{
request
.
accepted
=
true
sheetLoader
.
setSource
(
"
AuthSheet.qml
"
)
sheetLoader
.
item
.
request
=
request
sheetLoader
.
item
.
open
()
}
onFeaturePermissionRequested
:
{
questionLoader
.
setSource
(
"
PermissionQuestion.qml
"
)
questionLoader
.
item
.
permission
=
feature
questionLoader
.
item
.
origin
=
securityOrigin
questionLoader
.
item
.
visible
=
true
}
onJavaScriptDialogRequested
:
{
request
.
accepted
=
true
sheetLoader
.
setSource
(
"
JavaScriptDialogSheet.qml
"
)
sheetLoader
.
item
.
request
=
request
sheetLoader
.
item
.
open
()
}
onVisibleChanged
:
{
// set user agent to the current displayed tab
// this ensures that we follow mobile preference
// of the current webview. also update the current
// snapshot image with short delay to be sure that
// all kirigami pages have moved into place
if
(
visible
)
{
profile
.
httpUserAgent
=
Qt
.
binding
(
function
()
{
return
userAgent
.
userAgent
;
});
if
(
reloadOnVisible
)
{
reloadOnVisible
=
false
;
reload
();
}
}
}
function
stopLoading
()
{
loadingActive
=
false
;
stop
();
}
}
src/contents/webapp-ui/webapp.qml
View file @
de240d92
...
...
@@ -73,7 +73,8 @@ Kirigami.ApplicationWindow {
// tabs will work correctly
property
bool
initialized
:
false
WebView
{
//FIXME: WebView assumes a multi tab ui, will probably need own implementation
WebAppView
{
id
:
webView
anchors.fill
:
parent
url
:
BrowserManager
.
initialUrl
...
...
src/urlutils.cpp
View file @
de240d92
...
...
@@ -72,3 +72,8 @@ QString UrlUtils::urlPath(const QString &url)
{
return
QUrl
::
fromUserInput
(
url
).
path
();
}
QString
UrlUtils
::
urlHost
(
const
QString
&
url
)
{
return
QUrl
::
fromUserInput
(
url
).
host
();
}
src/urlutils.h
View file @
de240d92
...
...
@@ -41,6 +41,7 @@ public:
Q_INVOKABLE
static
QString
urlScheme
(
const
QString
&
url
);
Q_INVOKABLE
static
QString
urlHostPort
(
const
QString
&
url
);
Q_INVOKABLE
static
QString
urlPath
(
const
QString
&
url
);
Q_INVOKABLE
static
QString
urlHost
(
const
QString
&
url
);
};
#endif // URLUTILS_H
src/webapp-resources.qrc
View file @
de240d92
<RCC>
<qresource prefix="/">
<file alias="webapp.qml">contents/webapp-ui/webapp.qml</file>
<file alias="WebAppView.qml">contents/webapp-ui/WebAppView.qml</file>
</qresource>
</RCC>
src/webappmain.cpp
View file @
de240d92
...
...
@@ -25,6 +25,8 @@
#include <KLocalizedContext>
#include <KLocalizedString>
#include <KDesktopFile>
#include <KAboutData>
#include "bookmarkshistorymodel.h"
#include "browsermanager.h"
...
...
@@ -45,9 +47,9 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
#endif
QApplication
app
(
argc
,
argv
);
QCoreApplication
::
setOrganizationName
(
"KDE"
);
QCoreApplication
::
setOrganizationDomain
(
"mobile.kde.org"
);
QCoreApplication
::
setApplicationName
(
"angelfish"
);
//
QCoreApplication::setOrganizationName("KDE");
//
QCoreApplication::setOrganizationDomain("mobile.kde.org");
//
QCoreApplication::setApplicationName("angelfish");
#if QT_VERSION <= QT_VERSION_CHECK(5, 14, 0)
QtWebEngine
::
initialize
();
...
...
@@ -65,10 +67,27 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
engine
.
addImageProvider
(
IconImageProvider
::
providerId
(),
new
IconImageProvider
(
&
engine
));
// initial url command line parameter
QString
initialUrl
;
if
(
!
parser
.
positionalArguments
().
isEmpty
())
initialUrl
=
QUrl
::
fromUserInput
(
parser
.
positionalArguments
().
first
()).
toString
();
if
(
parser
.
positionalArguments
().
isEmpty
())
{
return
0
;
}
const
QString
fileName
=
parser
.
positionalArguments
().
first
();
KDesktopFile
desktopFile
(
fileName
);
if
(
desktopFile
.
readUrl
().
isEmpty
())
{
return
0
;
}
const
QString
initialUrl
=
QUrl
::
fromUserInput
(
desktopFile
.
readUrl
()).
toString
();
const
QString
appName
=
desktopFile
.
readName
().
toLower
().
replace
(
QLatin1Char
(
' '
),
QLatin1Char
(
'-'
))
+
QLatin1String
(
"-angelfish-webapp"
);
KAboutData
aboutData
(
appName
.
toLower
(),
desktopFile
.
readName
(),
QStringLiteral
(
"0.1"
),
i18n
(
"Angelfish Web App runtime"
),
KAboutLicense
::
GPL
,
i18n
(
"Copyright 2020 Angelfish developers"
));
QApplication
::
setWindowIcon
(
QIcon
::
fromTheme
(
desktopFile
.
readIcon
()));
aboutData
.
addAuthor
(
i18n
(
"Marco Martin"
),
QString
(),
"mart@kde.org"
);
KAboutData
::
setApplicationData
(
aboutData
);
// Exported types
qmlRegisterType
<
BookmarksHistoryModel
>
(
"org.kde.mobile.angelfish"
,
1
,
0
,
"BookmarksHistoryModel"
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment