Commit f921dc3f authored by Martin Straka's avatar Martin Straka

Added on-line Log bar into QML

parent ff080be3
......@@ -133,6 +133,7 @@ SOURCES += \
src/isds/isds_conversion.cpp \
src/isds/isds_type_conversion.cpp \
src/locker.cpp \
src/log.cpp \
src/main.cpp \
src/messages.cpp \
src/models/accountmodel.cpp \
......@@ -241,6 +242,7 @@ HEADERS += \
src/isds/isds_conversion.h \
src/isds/isds_type_conversion.h \
src/locker.h \
src/log.h \
src/messages.h \
src/models/accountmodel.h \
src/models/databoxmodel.h \
......
/*
* Copyright (C) 2014-2018 CZ.NIC
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations including
* the two.
*/
import QtQuick 2.7
import QtQuick.Controls 2.1
Rectangle {
id: root
visible: false
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.right: parent.right
height: parent.height * 0.3
color: datovkaPalette.text
Rectangle {
anchors.top: parent.top
anchors.right: parent.right
color: datovkaPalette.base
width: imgHeightHeader
height: imgHeightHeader
z: 1
AccessibleImageButton {
id: closeButton
anchors.centerIn: parent
sourceSize.height: imgHeightHeader
source: "qrc:/ui/remove.svg"
accessibleName: qsTr("Close log bar")
onClicked: {
root.visible = false
}
}
} // Rectangle
Flickable {
anchors.fill: parent
contentHeight: flickContent.implicitHeight
contentY: contentHeight-height
clip: true
Pane {
id: flickContent
anchors.fill: parent
background: parent
TextEdit {
id: logBarText
color: datovkaPalette.base
anchors.fill: parent
readOnly: true
wrapMode: Text.WordWrap
font.pointSize: textFontSizeSmall
text: log.loadLogContent("")
Connections {
target: log
onAppendNewLogMessage: {
logBarText.text += newLog
}
}
} // TextEdit
} // Pane
ScrollIndicator.vertical: ScrollIndicator {}
} // Flickable
}
......@@ -162,7 +162,10 @@ ApplicationWindow {
visible: true
StackView {
id: pageView
anchors.fill: parent
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: (logBar.visible) ? logBar.top : parent.bottom
visible: true
initialItem: PageAccountList {}
......@@ -170,6 +173,9 @@ ApplicationWindow {
nestedStack = pageView
}
}
LogBar {
id: logBar
}
}
ProgressBar {
id: statusBar
......
......@@ -8,7 +8,7 @@
*
* 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
* 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
......@@ -135,7 +135,8 @@ Component {
pageView.push(pageMenuDatovkaSettings, {
"pageView": pageView,
"statusBar": statusBar,
"accountModel": accountModel
"accountModel": accountModel,
"logBar": logBar
}, StackView.Immediate)
}
}
......
......@@ -42,10 +42,10 @@ Item {
}
Component.onCompleted: {
var logTxt = files.loadLogContent(logFilePath)
var logTxt = log.loadLogContent(logFilePath)
logContent.text = qsTr("Log from current run:") + "\n\n" + logTxt
actionButton.enabled = (logContent.text !== "")
logFileLocation = files.getLocFileLocation()
logFileLocation = log.getLocFileLocation()
}
/* File dialog for choose of files from the storage */
......@@ -56,7 +56,7 @@ Item {
if (pathListModel.count === 1) {
logContent.clear()
logFilePath = pathListModel.get(pathListModel.count-1).path
var logTxt = files.loadLogContent(logFilePath)
var logTxt = log.loadLogContent(logFilePath)
logContent.text = qsTr("Log file") + ": " + getFileNameFromPath(logFilePath) + "\n\n" + logTxt
actionButton.enabled = (logContent.text !== "")
}
......@@ -77,7 +77,7 @@ Item {
image.sourceSize.height: imgHeightHeader
image.source: "qrc:/ui/send-msg.svg"
accessibleName: qsTr("Send log to helpdesk")
onClicked: files.sendLogViaEmail(logContent.text)
onClicked: log.sendLogViaEmail(logContent.text)
}
}
Flickable {
......
......@@ -34,6 +34,7 @@ Component {
property var pageView
property var statusBar
property var accountModel: null
property var logBar
Component.onCompleted: {
var index
......@@ -137,6 +138,9 @@ Component {
"statusBar": statusBar
}, StackView.Immediate)
},
"showLogPanel": function callShowLogPanel() {
logBar.visible = true
},
"userGuide": function callUserGuide() {
Qt.openUrlExternally("https://secure.nic.cz/files/datove_schranky/redirect/mobile-manual.html")
pageView.pop(StackView.Immediate)
......@@ -215,6 +219,13 @@ Component {
name: qsTr("Log Viewer")
funcName: "logViewer"
}
ListElement {
image: "qrc:/ui/format-list-bulleted.svg"
showEntry: true
showNext: false
name: qsTr("Show log panel")
funcName: "showLogPanel"
}
ListElement {
image: "qrc:/ui/information.svg"
showEntry: true
......
......@@ -118,6 +118,7 @@
<file>../qml/components/DataboxList.qml</file>
<file>../qml/components/FilterBar.qml</file>
<file>../qml/components/InputLineMenu.qml</file>
<file>../qml/components/LogBar.qml</file>
<file>../qml/components/MessageList.qml</file>
<file>../qml/components/OverlaidImage.qml</file>
<file>../qml/components/PageHeader.qml</file>
......
/*
* Copyright (C) 2014-2017 CZ.NIC
* Copyright (C) 2014-2018 CZ.NIC
*
* 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
......@@ -8,7 +8,7 @@
*
* 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
* 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
......@@ -22,10 +22,14 @@
*/
#include <QDateTime>
#include <QDesktopServices>
#include <QMimeDatabase>
#include <QMimeType>
#include <QUrl>
#include "ios/src/url_opener.h"
#include "src/auxiliaries/email_helper.h"
#include "src/io/filesystem.h"
void addAttachmentToEmailMessage(QString &message, const QString &attachName,
const QByteArray &base64, const QString &boundary)
......@@ -109,3 +113,33 @@ QString generateEmailBodyText(qint64 dmId, const QString &from,
body += "\n";
return body;
}
void sendEmail(const QString &emailMessage, const QStringList &fileList,
const QString &to, const QString &subject, const QString &body,
const QString &msgId)
{
Q_UNUSED(to);
Q_UNUSED(subject);
Q_UNUSED(body);
Q_UNUSED(emailMessage);
Q_UNUSED(msgId);
Q_UNUSED(fileList);
#if defined Q_OS_IOS
UrlOpener urlOpener;
urlOpener.createEmail(body, to, subject, fileList);
#elif defined Q_OS_ANDROID
QDesktopServices::openUrl(QUrl("mailto:" + to + "?"
+ "subject=" + subject + "&body=" + body));
#else
QString tmpEmailFile = writeFile(appEmailDirPath(msgId),
msgId + "_mail.eml", emailMessage.toUtf8());
QDesktopServices::openUrl(QUrl::fromLocalFile(tmpEmailFile));
#endif
}
/*
* Copyright (C) 2014-2017 CZ.NIC
* Copyright (C) 2014-2018 CZ.NIC
*
* 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
......@@ -8,7 +8,7 @@
*
* 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
* 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
......@@ -21,10 +21,11 @@
* the two.
*/
#ifndef _EMAIL_HELPER_H_
#define _EMAIL_HELPER_H_
#pragma once
#include <QObject>
#include <QByteArray>
#include <QString>
#include <QStringList>
/*!
* @brief Add attachment into email.
......@@ -76,4 +77,16 @@ QString generateBoundaryString(void);
QString generateEmailBodyText(qint64 dmId, const QString &from,
const QString &to, const QString &delivered);
#endif /* _EMAIL_HELPER_H_ */
/*!
* @brief Send email.
*
* @param[in] emailMessage Eml email content.
* @param[in] fileList File list for email.
* @param[in] to Recipient mail addreess.
* @param[in] subject Email subject.
* @param[in] body Email body.
* @param[in] msgId Message ID.
*/
void sendEmail(const QString &emailMessage, const QStringList &fileList,
const QString &to, const QString &subject, const QString &body,
const QString &msgId);
......@@ -24,16 +24,12 @@
#include <QDesktopServices>
#include <QFileInfo>
#include <QQmlEngine>
#include <QSysInfo>
#include "ios/src/url_opener.h"
#include "src/auxiliaries/attachment_helper.h"
#include "src/auxiliaries/email_helper.h"
#include "src/common.h"
#include "src/crypto/crypto.h"
#include "src/datovka_shared/log/global.h"
#include "src/datovka_shared/log/log.h"
#include "src/datovka_shared/log/memory_log.h"
#include "src/dialogues/dialogues.h"
#include "src/files.h"
#include "src/global.h"
......@@ -154,42 +150,6 @@ QByteArray Files::getFileRawContentFromDb(const QString &userName, int fileId)
return fDb->getFileFromDb(fileId).binaryContent();
}
QString Files::getLocFileLocation(void)
{
return appLogDirPath();
}
QString Files::loadLogContent(const QString &filePath)
{
debugFuncCall();
QString log;
if (filePath.isEmpty()) {
MemoryLog *mLog = GlobInstcs::logPtr->memoryLog();
if (mLog == Q_NULLPTR) {
return QString();
}
const QList<quint64> keys(mLog->keys());
foreach (quint64 key, keys) {
log.append(mLog->message(key));
}
} else {
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
Q_ASSERT(0);
logErrorNL("Cannot open file '%s'.",
filePath.toUtf8().constData());
return QString();
}
log.append(file.readAll());
file.close();
}
return log;
}
void Files::openAttachmentFromDb(const QString &userName, int fileId)
{
debugFuncCall();
......@@ -283,41 +243,6 @@ void Files::openAttachmentFromPath(const QString &filePath)
#endif
}
void Files::sendLogViaEmail(const QString &logContent)
{
debugFuncCall();
int msgResponse = Dialogues::message(Dialogues::QUESTION,
tr("Send log via email"),
tr("Do you want to send the log information to developers?"),
QString(), Dialogues::NO | Dialogues::YES, Dialogues::NO);
if (msgResponse == Dialogues::NO) {
return;
}
QString to("datove-schranky@labs.nic.cz");
QString subject("Mobile Datovka: Log File");
QString body("Mobile Datovka");
body.append("\nVersion: " + QStringLiteral(VERSION));
body.append("\nOS: " + QSysInfo::productType() + " " + QSysInfo::productVersion());
body.append("\nArch: " + QSysInfo::currentCpuArchitecture());
removeDirFromDocLoc(DATOVKA_MAIL_DIR_NAME);
QString targetPath(appEmailDirPath("Log"));
QString filePath(writeFile(targetPath, "mobile-datovka.log",
base64ToRaw(logContent.toUtf8())));
QStringList attachmentList;
attachmentList.append(filePath);
const QString boundary = generateBoundaryString();
QString emailMessage = createEmailMessage(to, body, subject, boundary);
addAttachmentToEmailMessage(emailMessage, "mobile-datovka.log",
logContent.toUtf8().toBase64(), boundary);
finishEmailMessage(emailMessage, boundary);
sendEmail(emailMessage, attachmentList, to, subject, body, "Log");
}
void Files::sendMsgFilesWithEmail(const QString &userName, qint64 msgId,
MsgAttachFlags attachFlags)
{
......@@ -790,36 +715,6 @@ void Files::deleteTmpFileFromStorage(const QString &filePath)
#endif
}
void Files::sendEmail(const QString &emailMessage, const QStringList &fileList,
const QString &to, const QString &subject, const QString &body,
const QString &msgId)
{
Q_UNUSED(to);
Q_UNUSED(subject);
Q_UNUSED(body);
Q_UNUSED(emailMessage);
Q_UNUSED(msgId);
Q_UNUSED(fileList);
#if defined Q_OS_IOS
UrlOpener urlOpener;
urlOpener.createEmail(body, to, subject, fileList);
#elif defined Q_OS_ANDROID
QDesktopServices::openUrl(QUrl("mailto:" + to + "?"
+ "subject=" + subject + "&body=" + body));
#else
QString tmpEmailFile = writeFile(appEmailDirPath(msgId),
msgId + "_mail.eml", emailMessage.toUtf8());
QDesktopServices::openUrl(QUrl::fromLocalFile(tmpEmailFile));
#endif
}
bool Files::parseXmlData(enum MsgInfo::ZfoType *type, QString *idStr,
QString *annotation, QString *msgDescrHtml, FileListModel *attachModel,
QString *emailBody, QByteArray xmlData)
......
/*
* Copyright (C) 2014-2017 CZ.NIC
* Copyright (C) 2014-2018 CZ.NIC
*
* 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
......@@ -115,23 +115,6 @@ public:
Q_INVOKABLE static
QByteArray getFileRawContentFromDb(const QString &userName, int fileId);
/*!
* @brief Get log file location.
*
* @return Full path to log directory.
*/
Q_INVOKABLE static
QString getLocFileLocation(void);
/*!
* @brief Load log content from file or memory into QML.
*
* @param[in] filePath Log file path (empty = use memory log).
* @return Log content as html.
*/
Q_INVOKABLE static
QString loadLogContent(const QString &filePath);
/*!
* @brief Open attachment from database.
*
......@@ -159,14 +142,6 @@ public:
Q_INVOKABLE static
void openAttachmentFromPath(const QString &filePath);
/*!
* @brief Send log via email.
*
* @param[in] logContent Log content to be sent.
*/
Q_INVOKABLE static
void sendLogViaEmail(const QString &logContent);
/*!
* @brief Send message attachments or complete zfo message
* from database with email application.
......@@ -329,20 +304,6 @@ signals:
void statusBarTextChanged(QString txt, bool busy);
private:
/*!
* @brief Send email.
*
* @param[in] emailMessage Eml email content.
* @param[in] fileList File list for email.
* @param[in] to Recipient mail addreess.
* @param[in] subject Email subject.
* @param[in] body Email body.
* @param[in] msgId Message ID.
*/
static
void sendEmail(const QString &emailMessage, const QStringList &fileList,
const QString &to, const QString &subject, const QString &body,
const QString &msgId);
/*!
* @brief Parse xml data of zfo file.
......
/*
* Copyright (C) 2014-2018 CZ.NIC
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations including
* the two.
*/
#include <QByteArray>
#include <QFile>
#include <QList>
#include <QSysInfo>
#include "src/auxiliaries/email_helper.h"
#include "src/datovka_shared/log/global.h"
#include "src/datovka_shared/log/log.h"
#include "src/dialogues/dialogues.h"
#include "src/log.h"
#include "src/io/filesystem.h"
Log::Log(QObject *parent)
: QObject(parent)
{
m_memLog = GlobInstcs::logPtr->memoryLog();
if (m_memLog != Q_NULLPTR) {
connect(m_memLog, SIGNAL(logged(quint64)),
this, SLOT(appendNewLog(quint64)));
}
}
Log::~Log(void)
{
if (m_memLog != Q_NULLPTR) {
m_memLog->disconnect(SIGNAL(logged(quint64)),
this, SLOT(appendNewLog(quint64)));
}
}
QString Log::getLocFileLocation(void)
{
return appLogDirPath();
}
QString Log::loadLogContent(const QString &filePath)
{
debugFuncCall();
QString log;
if (filePath.isEmpty()) {
const QList<quint64> keys(m_memLog->keys());
foreach (quint64 key, keys) {
log.append(m_memLog->message(key));
}
} else {
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
Q_ASSERT(0);
logErrorNL("Cannot open file '%s'.",
filePath.toUtf8().constData());
return QString();
}
log.append(file.readAll());
file.close();
}
return log;
}
void Log::sendLogViaEmail(const QString &logContent)
{
debugFuncCall();
int msgResponse = Dialogues::message(Dialogues::QUESTION,
tr("Send log via email"),
tr("Do you want to send the log information to developers?"),
QString(), Dialogues::NO | Dialogues::YES, Dialogues::NO);
if (msgResponse == Dialogues::NO) {
return;
}
QString to("datove-schranky@labs.nic.cz");
QString subject("Mobile Datovka: Log File");
QString body("Mobile Datovka");
body.append("\nVersion: " + QStringLiteral(VERSION));
body.append("\nOS: " + QSysInfo::productType() + " "
+ QSysInfo::productVersion());
body.append("\nArch: " + QSysInfo::currentCpuArchitecture());
removeDirFromDocLoc(DATOVKA_MAIL_DIR_NAME);
QString targetPath(appEmailDirPath("Log"));
QString filePath(writeFile(targetPath, "mobile-datovka.log",
QByteArray::fromBase64(logContent.toUtf8())));
QStringList attachmentList;
attachmentList.append(filePath);
const QString boundary = generateBoundaryString();
QString emailMessage = createEmailMessage(to, body, subject, boundary);
addAttachmentToEmailMessage(emailMessage, "mobile-datovka.log",
logContent.toUtf8().toBase64(), boundary);
finishEmailMessage(emailMessage, boundary);
sendEmail(emailMessage, attachmentList, to, subject, body, "Log");
}
void Log::appendNewLog(quint64 key)
{
emit appendNewLogMessage(m_memLog->message(key));
}
/*
* Copyright (C) 2014-2018 CZ.NIC
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations including
* the two.
*/
#pragma once
#include <QObject>
#include <QString>
#include "src/datovka_shared/log/memory_log.h"
/*
* Class Log provides interface between QML and log device.
* Class is initialised in the main function (main.cpp)
*/
class Log : public QObject {
Q_OBJECT
public:
/*!
* @brief Constructor.
*
* @param[in] parent Parent object.
*/
explicit Log(QObject *parent = Q_NULLPTR);
/*!
* @brief Destructor.
*/
~Log(void);
/*!
* @brief Get log file location.
*
* @return Full path to log directory.
*/
Q_INVOKABLE static
QString getLocFileLocation(void);
/*!
* @brief Load log content from file or memory into QML.
*
* @param[in] filePath Log file path (empty = use memory log).
* @return Log content as text.
*/
Q_INVOKABLE
QString loadLogContent(const QString &filePath);
/*!
* @brief Send log via email.
*
* @param[in] logContent Log content to be sent.
*/
Q_INVOKABLE static
void sendLogViaEmail(const QString &logContent);
signals:
/*!
* @brief Append new log message to QML log bar.
*
* @param[in] newLog New log message.
*/
void appendNewLogMessage(QString newLog);
private slots:
/*!
* @brief Appends newly logged message to QML log bar.
*
* @param[in] key Log message key.
*/
void appendNewLog(quint64 key);
private:
MemoryLog *m_memLog; /*!< Pointer to memory log. */
};
......@@ -50,6 +50,7 @@
#include "src/global.h"
#include "src/io/filesystem.h"
#include "src/locker.h"
#include "src/log.h"
#include "src/net/isds_wrapper.h"
#include "src/models/accountmodel.h"
#include "src/models/databoxmodel.h"
......@@ -160,6 +161,7 @@ const struct QmlTypeEntry qmlComponents[] = {
{ "DataboxList", 1, 0 },
{ "FilterBar", 1, 0 },
{ "InputLineMenu", 1, 0 },
{ "LogBar", 1, 0 },
{ "MessageList", 1, 0 },