added open service logs to logs page (#951)
* added open service logs to logs page * redesign of log saving buttons * hide service logs buttons for mobile platforms * refactoring: moved logger to common folder * feature: added the ability to enable logs to the start screen
This commit is contained in:
parent
918be16372
commit
9cab51fb00
22 changed files with 519 additions and 691 deletions
|
|
@ -113,6 +113,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/cmake/3rdparty.cmake)
|
|||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_LIST_DIR}/../ipc
|
||||
${CMAKE_CURRENT_LIST_DIR}/../common/logger
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
|
@ -134,7 +135,6 @@ set(HEADERS ${HEADERS}
|
|||
${CMAKE_CURRENT_LIST_DIR}/protocols/protocols_defs.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocols/qml_register_protocols.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/ui/pages.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/ui/property_helper.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/ui/qautostart.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/protocols/vpnprotocol.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.h
|
||||
|
|
@ -143,6 +143,7 @@ set(HEADERS ${HEADERS}
|
|||
${CMAKE_CURRENT_LIST_DIR}/core/serialization/serialization.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/core/serialization/transfer.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/core/enums/apiEnums.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/../common/logger/logger.h
|
||||
)
|
||||
|
||||
# Mozilla headres
|
||||
|
|
@ -193,6 +194,7 @@ set(SOURCES ${SOURCES}
|
|||
${CMAKE_CURRENT_LIST_DIR}/core/serialization/trojan.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/core/serialization/vmess.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/core/serialization/vmess_new.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/../common/logger/logger.cpp
|
||||
)
|
||||
|
||||
# Mozilla sources
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ void AmneziaApplication::init()
|
|||
bool enabled = m_settings->isSaveLogs();
|
||||
#ifndef Q_OS_ANDROID
|
||||
if (enabled) {
|
||||
if (!Logger::init()) {
|
||||
if (!Logger::init(false)) {
|
||||
qWarning() << "Initialization of debug subsystem failed";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,7 +83,6 @@ ErrorCode ServerController::runScript(const ServerCredentials &credentials, QStr
|
|||
}
|
||||
|
||||
qDebug().noquote() << lineToExec;
|
||||
Logger::appendSshLog("Run command:" + lineToExec);
|
||||
|
||||
error = m_sshClient.executeCommand(lineToExec, cbReadStdOut, cbReadStdErr);
|
||||
if (error != ErrorCode::NoError) {
|
||||
|
|
@ -100,7 +99,6 @@ ErrorCode ServerController::runContainerScript(const ServerCredentials &credenti
|
|||
const std::function<ErrorCode(const QString &, libssh::Client &)> &cbReadStdErr)
|
||||
{
|
||||
QString fileName = "/opt/amnezia/" + Utils::getRandomString(16) + ".sh";
|
||||
Logger::appendSshLog("Run container script for " + ContainerProps::containerToString(container) + ":\n" + script);
|
||||
|
||||
ErrorCode e = uploadTextFileToContainer(container, credentials, script, fileName);
|
||||
if (e)
|
||||
|
|
|
|||
|
|
@ -1,304 +0,0 @@
|
|||
#include "logger.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QDesktopServices>
|
||||
#include <QDir>
|
||||
#include <QMetaEnum>
|
||||
#include <QJsonDocument>
|
||||
#include <QStandardPaths>
|
||||
#include <QUrl>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "version.h"
|
||||
#include "utilities.h"
|
||||
|
||||
#ifdef AMNEZIA_DESKTOP
|
||||
#include <core/ipcclient.h>
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_IOS
|
||||
#include <AmneziaVPN-Swift.h>
|
||||
#endif
|
||||
|
||||
QFile Logger::m_file;
|
||||
QTextStream Logger::m_textStream;
|
||||
QString Logger::m_logFileName = QString("%1.log").arg(APPLICATION_NAME);
|
||||
|
||||
void debugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg)
|
||||
{
|
||||
if (msg.simplified().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip annoying messages from Qt
|
||||
if (msg.contains("OpenType support missing for")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.startsWith("Unknown property") || msg.startsWith("Could not create pixmap") || msg.startsWith("Populating font") || msg.startsWith("stale focus object")) {
|
||||
return;
|
||||
}
|
||||
|
||||
Logger::m_textStream << qFormatLogMessage(type, context, msg) << Qt::endl << Qt::flush;
|
||||
Logger::appendAllLog(qFormatLogMessage(type, context, msg));
|
||||
|
||||
std::cout << qFormatLogMessage(type, context, msg).toStdString() << std::endl << std::flush;
|
||||
}
|
||||
|
||||
Logger &Logger::Instance()
|
||||
{
|
||||
static Logger s;
|
||||
return s;
|
||||
}
|
||||
|
||||
void Logger::appendSshLog(const QString &log)
|
||||
{
|
||||
QString dt = QDateTime::currentDateTime().toString();
|
||||
Instance().m_sshLog.append(dt + ": " + log + "\n");
|
||||
emit Instance().sshLogChanged(Instance().sshLog());
|
||||
}
|
||||
|
||||
void Logger::appendAllLog(const QString &log)
|
||||
{
|
||||
Instance().m_allLog.append(log + "\n");
|
||||
emit Instance().allLogChanged(Instance().allLog());
|
||||
}
|
||||
|
||||
bool Logger::init()
|
||||
{
|
||||
qSetMessagePattern("%{time yyyy-MM-dd hh:mm:ss} %{type} %{message}");
|
||||
|
||||
QString path = userLogsDir();
|
||||
QDir appDir(path);
|
||||
if (!appDir.mkpath(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_file.setFileName(appDir.filePath(m_logFileName));
|
||||
if (!m_file.open(QIODevice::Append)) {
|
||||
qWarning() << "Cannot open log file:" << m_logFileName;
|
||||
return false;
|
||||
}
|
||||
m_file.setTextModeEnabled(true);
|
||||
m_textStream.setDevice(&m_file);
|
||||
|
||||
#if !defined(QT_DEBUG) || defined(Q_OS_IOS)
|
||||
qInstallMessageHandler(debugMessageHandler);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Logger::deInit()
|
||||
{
|
||||
qInstallMessageHandler(nullptr);
|
||||
qSetMessagePattern("%{message}");
|
||||
m_textStream.setDevice(nullptr);
|
||||
m_file.close();
|
||||
}
|
||||
|
||||
bool Logger::setServiceLogsEnabled(bool enabled) {
|
||||
#ifdef AMNEZIA_DESKTOP
|
||||
IpcClient *m_IpcClient = new IpcClient;
|
||||
|
||||
if (!m_IpcClient->isSocketConnected()) {
|
||||
if (!IpcClient::init(m_IpcClient)) {
|
||||
qWarning() << "Error occurred when init IPC client";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_IpcClient->Interface()) {
|
||||
m_IpcClient->Interface()->setLogsEnabled(enabled);
|
||||
}
|
||||
else {
|
||||
qWarning() << "Error occurred setting up service logs";
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QString Logger::userLogsDir()
|
||||
{
|
||||
return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/log";
|
||||
}
|
||||
|
||||
QString Logger::userLogsFilePath()
|
||||
{
|
||||
return userLogsDir() + QDir::separator() + m_logFileName;
|
||||
}
|
||||
|
||||
QString Logger::getLogFile()
|
||||
{
|
||||
m_file.flush();
|
||||
QFile file(userLogsFilePath());
|
||||
|
||||
file.open(QIODevice::ReadOnly);
|
||||
QString qtLog = file.readAll();
|
||||
|
||||
#ifdef Q_OS_IOS
|
||||
return QString().fromStdString(AmneziaVPN::swiftUpdateLogData(qtLog.toStdString()));
|
||||
#else
|
||||
return qtLog;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
bool Logger::openLogsFolder()
|
||||
{
|
||||
QString path = userLogsDir();
|
||||
#ifdef Q_OS_WIN
|
||||
path = "file:///" + path;
|
||||
#endif
|
||||
if (!QDesktopServices::openUrl(QUrl::fromLocalFile(path))) {
|
||||
qWarning() << "Can't open url:" << path;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Logger::openServiceLogsFolder()
|
||||
{
|
||||
QString path = Utils::systemLogPath();
|
||||
#ifdef Q_OS_WIN
|
||||
path = "file:///" + path;
|
||||
#endif
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
|
||||
return true;
|
||||
}
|
||||
|
||||
QString Logger::appLogFileNamePath()
|
||||
{
|
||||
return m_file.fileName();
|
||||
}
|
||||
|
||||
void Logger::clearLogs()
|
||||
{
|
||||
bool isLogActive = m_file.isOpen();
|
||||
m_file.close();
|
||||
|
||||
QFile file(userLogsFilePath());
|
||||
|
||||
file.open(QIODevice::WriteOnly | QIODevice::Truncate);
|
||||
file.resize(0);
|
||||
file.close();
|
||||
|
||||
#ifdef Q_OS_IOS
|
||||
AmneziaVPN::swiftDeleteLog();
|
||||
#endif
|
||||
|
||||
if (isLogActive) {
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::clearServiceLogs()
|
||||
{
|
||||
#ifdef AMNEZIA_DESKTOP
|
||||
IpcClient *m_IpcClient = new IpcClient;
|
||||
|
||||
if (!m_IpcClient->isSocketConnected()) {
|
||||
if (!IpcClient::init(m_IpcClient)) {
|
||||
qWarning() << "Error occurred when init IPC client";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_IpcClient->Interface()) {
|
||||
m_IpcClient->Interface()->clearLogs();
|
||||
}
|
||||
else {
|
||||
qWarning() << "Error occurred cleaning up service logs";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Logger::cleanUp()
|
||||
{
|
||||
clearLogs();
|
||||
QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
|
||||
dir.removeRecursively();
|
||||
|
||||
clearServiceLogs();
|
||||
}
|
||||
|
||||
Logger::Log::Log(Logger* logger, LogLevel logLevel)
|
||||
: m_logger(logger), m_logLevel(logLevel), m_data(new Data()) {}
|
||||
|
||||
Logger::Log::~Log() {
|
||||
qDebug() << "Amnezia" << m_logger->className() << m_data->m_buffer.trimmed();
|
||||
delete m_data;
|
||||
}
|
||||
|
||||
Logger::Log Logger::error() { return Log(this, LogLevel::Error); }
|
||||
Logger::Log Logger::warning() { return Log(this, LogLevel::Warning); }
|
||||
Logger::Log Logger::info() { return Log(this, LogLevel::Info); }
|
||||
Logger::Log Logger::debug() { return Log(this, LogLevel::Debug); }
|
||||
QString Logger::sensitive(const QString& input) {
|
||||
#ifdef Q_DEBUG
|
||||
return input;
|
||||
#else
|
||||
Q_UNUSED(input);
|
||||
return QString(8, 'X');
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#define CREATE_LOG_OP_REF(x) \
|
||||
Logger::Log& Logger::Log::operator<<(x t) { \
|
||||
m_data->m_ts << t << ' '; \
|
||||
return *this; \
|
||||
}
|
||||
|
||||
CREATE_LOG_OP_REF(uint64_t);
|
||||
CREATE_LOG_OP_REF(const char*);
|
||||
CREATE_LOG_OP_REF(const QString&);
|
||||
CREATE_LOG_OP_REF(const QByteArray&);
|
||||
CREATE_LOG_OP_REF(const void*);
|
||||
|
||||
#undef CREATE_LOG_OP_REF
|
||||
|
||||
Logger::Log& Logger::Log::operator<<(const QStringList& t) {
|
||||
m_data->m_ts << '[' << t.join(",") << ']' << ' ';
|
||||
return *this;
|
||||
}
|
||||
|
||||
Logger::Log& Logger::Log::operator<<(const QJsonObject& t) {
|
||||
m_data->m_ts << QJsonDocument(t).toJson(QJsonDocument::Indented) << ' ';
|
||||
return *this;
|
||||
}
|
||||
|
||||
Logger::Log& Logger::Log::operator<<(QTextStreamFunction t) {
|
||||
m_data->m_ts << t;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Logger::Log::addMetaEnum(quint64 value, const QMetaObject* meta,
|
||||
const char* name) {
|
||||
QMetaEnum me = meta->enumerator(meta->indexOfEnumerator(name));
|
||||
|
||||
QString out;
|
||||
QTextStream ts(&out);
|
||||
|
||||
if (const char* scope = me.scope()) {
|
||||
ts << scope << "::";
|
||||
}
|
||||
|
||||
const char* key = me.valueToKey(static_cast<int>(value));
|
||||
const bool scoped = me.isScoped();
|
||||
if (scoped || !key) {
|
||||
ts << me.enumName() << (!key ? "(" : "::");
|
||||
}
|
||||
|
||||
if (key) {
|
||||
ts << key;
|
||||
} else {
|
||||
ts << value << ")";
|
||||
}
|
||||
|
||||
m_data->m_ts << out;
|
||||
}
|
||||
107
client/logger.h
107
client/logger.h
|
|
@ -1,107 +0,0 @@
|
|||
#ifndef LOGGER_H
|
||||
#define LOGGER_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QString>
|
||||
#include <QTextStream>
|
||||
|
||||
#include "ui/property_helper.h"
|
||||
|
||||
#include "mozilla/shared/loglevel.h"
|
||||
|
||||
class Logger : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
AUTO_PROPERTY(QString, sshLog)
|
||||
AUTO_PROPERTY(QString, allLog)
|
||||
|
||||
public:
|
||||
static Logger& Instance();
|
||||
|
||||
static void appendSshLog(const QString &log);
|
||||
static void appendAllLog(const QString &log);
|
||||
|
||||
|
||||
static bool init();
|
||||
static void deInit();
|
||||
static bool setServiceLogsEnabled(bool enabled);
|
||||
static bool openLogsFolder();
|
||||
static bool openServiceLogsFolder();
|
||||
static QString appLogFileNamePath();
|
||||
static void clearLogs();
|
||||
static void clearServiceLogs();
|
||||
static void cleanUp();
|
||||
|
||||
static QString userLogsFilePath();
|
||||
static QString getLogFile();
|
||||
|
||||
// compat with Mozilla logger
|
||||
Logger(const QString &className) { m_className = className; }
|
||||
const QString& className() const { return m_className; }
|
||||
|
||||
class Log {
|
||||
public:
|
||||
Log(Logger* logger, LogLevel level);
|
||||
~Log();
|
||||
|
||||
Log& operator<<(uint64_t t);
|
||||
Log& operator<<(const char* t);
|
||||
Log& operator<<(const QString& t);
|
||||
Log& operator<<(const QStringList& t);
|
||||
Log& operator<<(const QByteArray& t);
|
||||
Log& operator<<(const QJsonObject& t);
|
||||
Log& operator<<(QTextStreamFunction t);
|
||||
Log& operator<<(const void* t);
|
||||
|
||||
// Q_ENUM
|
||||
template <typename T>
|
||||
typename std::enable_if<QtPrivate::IsQEnumHelper<T>::Value, Log&>::type
|
||||
operator<<(T t) {
|
||||
const QMetaObject* meta = qt_getEnumMetaObject(t);
|
||||
const char* name = qt_getEnumName(t);
|
||||
addMetaEnum(typename QFlags<T>::Int(t), meta, name);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
void addMetaEnum(quint64 value, const QMetaObject* meta, const char* name);
|
||||
|
||||
Logger* m_logger;
|
||||
LogLevel m_logLevel;
|
||||
|
||||
struct Data {
|
||||
Data() : m_ts(&m_buffer, QIODevice::WriteOnly) {}
|
||||
|
||||
QString m_buffer;
|
||||
QTextStream m_ts;
|
||||
};
|
||||
|
||||
Data* m_data;
|
||||
};
|
||||
|
||||
Log error();
|
||||
Log warning();
|
||||
Log info();
|
||||
Log debug();
|
||||
QString sensitive(const QString& input);
|
||||
|
||||
private:
|
||||
Logger() {}
|
||||
Logger(Logger const &) = delete;
|
||||
Logger& operator= (Logger const&) = delete;
|
||||
|
||||
static QString userLogsDir();
|
||||
|
||||
static QFile m_file;
|
||||
static QTextStream m_textStream;
|
||||
static QString m_logFileName;
|
||||
|
||||
friend void debugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg);
|
||||
|
||||
// compat with Mozilla logger
|
||||
QString m_className;
|
||||
};
|
||||
|
||||
#endif // LOGGER_H
|
||||
|
|
@ -227,7 +227,7 @@ void Settings::setSaveLogs(bool enabled)
|
|||
if (!isSaveLogs()) {
|
||||
Logger::deInit();
|
||||
} else {
|
||||
if (!Logger::init()) {
|
||||
if (!Logger::init(false)) {
|
||||
qWarning() << "Initialization of debug subsystem failed";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,12 @@ void SettingsController::toggleLogging(bool enable)
|
|||
|
||||
void SettingsController::openLogsFolder()
|
||||
{
|
||||
Logger::openLogsFolder();
|
||||
Logger::openLogsFolder(false);
|
||||
}
|
||||
|
||||
void SettingsController::openServiceLogsFolder()
|
||||
{
|
||||
Logger::openLogsFolder(true);
|
||||
}
|
||||
|
||||
void SettingsController::exportLogsFile(const QString &fileName)
|
||||
|
|
@ -100,12 +105,21 @@ void SettingsController::exportLogsFile(const QString &fileName)
|
|||
#endif
|
||||
}
|
||||
|
||||
void SettingsController::exportServiceLogsFile(const QString &fileName)
|
||||
{
|
||||
#ifdef Q_OS_ANDROID
|
||||
AndroidController::instance()->exportLogsFile(fileName);
|
||||
#else
|
||||
SystemController::saveFile(fileName, Logger::getServiceLogFile());
|
||||
#endif
|
||||
}
|
||||
|
||||
void SettingsController::clearLogs()
|
||||
{
|
||||
#ifdef Q_OS_ANDROID
|
||||
AndroidController::instance()->clearLogs();
|
||||
#else
|
||||
Logger::clearLogs();
|
||||
Logger::clearLogs(false);
|
||||
Logger::clearServiceLogs();
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,9 @@ public slots:
|
|||
void toggleLogging(bool enable);
|
||||
|
||||
void openLogsFolder();
|
||||
void openServiceLogsFolder();
|
||||
void exportLogsFile(const QString &fileName);
|
||||
void exportServiceLogsFile(const QString &fileName);
|
||||
void clearLogs();
|
||||
|
||||
void backupAppConfig(const QString &fileName);
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
#ifndef PROPERTY_HELPER_H
|
||||
#define PROPERTY_HELPER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#define AUTO_PROPERTY(TYPE, NAME) \
|
||||
Q_PROPERTY(TYPE NAME READ NAME WRITE set_ ## NAME NOTIFY NAME ## Changed ) \
|
||||
public: \
|
||||
TYPE NAME() const { return m_ ## NAME ; } \
|
||||
void set_ ## NAME(TYPE value) { \
|
||||
if (m_ ## NAME == value) return; \
|
||||
m_ ## NAME = value; \
|
||||
emit NAME ## Changed(value); \
|
||||
} \
|
||||
Q_SIGNAL void NAME ## Changed(TYPE value);\
|
||||
private: \
|
||||
TYPE m_ ## NAME{};
|
||||
|
||||
#define READONLY_PROPERTY(TYPE, NAME) \
|
||||
Q_PROPERTY(TYPE NAME READ NAME CONSTANT ) \
|
||||
public: \
|
||||
TYPE NAME() const { return m_ ## NAME ; } \
|
||||
private: \
|
||||
void NAME(TYPE value) {m_ ## NAME = value; } \
|
||||
TYPE m_ ## NAME{};
|
||||
|
||||
#endif // PROPERTY_HELPER_H
|
||||
|
|
@ -20,7 +20,8 @@ Item {
|
|||
property string buttonImageSource
|
||||
property string rightImageSource
|
||||
property string leftImageSource
|
||||
property bool isLeftImageHoverEnabled: true //todo separete this qml file to 3
|
||||
property bool isLeftImageHoverEnabled: true
|
||||
property bool isSmallLeftImage: false
|
||||
|
||||
property alias rightButton: rightImage
|
||||
property alias eyeButton: eyeImage
|
||||
|
|
@ -114,9 +115,9 @@ Item {
|
|||
|
||||
visible: leftImageSource ? true : false
|
||||
|
||||
Layout.preferredHeight: rightImageSource || !isLeftImageHoverEnabled ? leftImage.implicitHeight : 56
|
||||
Layout.preferredWidth: rightImageSource || !isLeftImageHoverEnabled ? leftImage.implicitWidth : 56
|
||||
Layout.rightMargin: rightImageSource || !isLeftImageHoverEnabled ? 16 : 0
|
||||
Layout.preferredHeight: (rightImageSource || !isLeftImageHoverEnabled || isSmallLeftImage) ? 40 : 56
|
||||
Layout.preferredWidth: (rightImageSource || !isLeftImageHoverEnabled || isSmallLeftImage)? 40 : 56
|
||||
Layout.rightMargin: isSmallLeftImage ? 8 : (rightImageSource || !isLeftImageHoverEnabled) ? 16 : 0
|
||||
|
||||
radius: 12
|
||||
color: AmneziaStyle.color.transparent
|
||||
|
|
|
|||
|
|
@ -102,8 +102,7 @@ Switch {
|
|||
contentItem: ColumnLayout {
|
||||
id: content
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
|
||||
ListItemTitleType {
|
||||
|
|
|
|||
|
|
@ -16,18 +16,6 @@ import "../Controls2/TextTypes"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
Connections {
|
||||
target: SettingsController
|
||||
|
||||
function onLoggingStateChanged() {
|
||||
if (SettingsController.isLoggingEnabled) {
|
||||
var message = qsTr("Logging is enabled. Note that logs will be automatically \
|
||||
disabled after 14 days, and all log files will be deleted.")
|
||||
PageController.showNotificationMessage(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultActiveFocusItem: focusItem
|
||||
|
||||
Item {
|
||||
|
|
@ -58,13 +46,12 @@ disabled after 14 days, and all log files will be deleted.")
|
|||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 16
|
||||
anchors.rightMargin: 16
|
||||
|
||||
spacing: 16
|
||||
spacing: 0
|
||||
|
||||
HeaderType {
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
||||
headerText: qsTr("Logging")
|
||||
descriptionText: qsTr("Enabling this function will save application's logs automatically. " +
|
||||
|
|
@ -75,11 +62,13 @@ disabled after 14 days, and all log files will be deleted.")
|
|||
id: switcher
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
||||
text: qsTr("Save logs")
|
||||
text: qsTr("Enable logs")
|
||||
|
||||
checked: SettingsController.isLoggingEnabled
|
||||
KeyNavigation.tab: openFolderButton
|
||||
//KeyNavigation.tab: openFolderButton
|
||||
onCheckedChanged: {
|
||||
if (checked !== SettingsController.isLoggingEnabled) {
|
||||
SettingsController.isLoggingEnabled = checked
|
||||
|
|
@ -87,132 +76,200 @@ disabled after 14 days, and all log files will be deleted.")
|
|||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
// id: labelWithButton2
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: -8
|
||||
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignBaseline
|
||||
Layout.preferredWidth: GC.isMobile() ? 0 : root.width / 3
|
||||
visible: !GC.isMobile()
|
||||
text: qsTr("Clear logs")
|
||||
leftImageSource: "qrc:/images/controls/trash.svg"
|
||||
isSmallLeftImage: true
|
||||
|
||||
ImageButtonType {
|
||||
id: openFolderButton
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
// KeyNavigation.tab: labelWithButton3
|
||||
|
||||
implicitWidth: 56
|
||||
implicitHeight: 56
|
||||
clickedFunction: function() {
|
||||
var headerText = qsTr("Clear logs?")
|
||||
var yesButtonText = qsTr("Continue")
|
||||
var noButtonText = qsTr("Cancel")
|
||||
|
||||
image: "qrc:/images/controls/folder-open.svg"
|
||||
KeyNavigation.tab: saveButton
|
||||
|
||||
onClicked: SettingsController.openLogsFolder()
|
||||
Keys.onReturnPressed: openFolderButton.clicked()
|
||||
Keys.onEnterPressed: openFolderButton.clicked()
|
||||
var yesButtonFunction = function() {
|
||||
PageController.showBusyIndicator(true)
|
||||
SettingsController.clearLogs()
|
||||
PageController.showBusyIndicator(false)
|
||||
PageController.showNotificationMessage(qsTr("Logs have been cleaned up"))
|
||||
if (!GC.isMobile()) {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
CaptionTextType {
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Open folder with logs")
|
||||
color: AmneziaStyle.color.paleGray
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignBaseline
|
||||
Layout.preferredWidth: root.width / ( GC.isMobile() ? 2 : 3 )
|
||||
|
||||
ImageButtonType {
|
||||
id: saveButton
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
implicitWidth: 56
|
||||
implicitHeight: 56
|
||||
|
||||
image: "qrc:/images/controls/save.svg"
|
||||
KeyNavigation.tab: clearButton
|
||||
|
||||
Keys.onReturnPressed: saveButton.clicked()
|
||||
Keys.onEnterPressed: saveButton.clicked()
|
||||
onClicked: {
|
||||
var fileName = ""
|
||||
if (GC.isMobile()) {
|
||||
fileName = "AmneziaVPN.log"
|
||||
} else {
|
||||
fileName = SystemController.getFileName(qsTr("Save"),
|
||||
qsTr("Logs files (*.log)"),
|
||||
StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/AmneziaVPN",
|
||||
true,
|
||||
".log")
|
||||
}
|
||||
if (fileName !== "") {
|
||||
PageController.showBusyIndicator(true)
|
||||
SettingsController.exportLogsFile(fileName)
|
||||
PageController.showBusyIndicator(false)
|
||||
PageController.showNotificationMessage(qsTr("Logs file saved"))
|
||||
}
|
||||
var noButtonFunction = function() {
|
||||
if (!GC.isMobile()) {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
CaptionTextType {
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||
}
|
||||
}
|
||||
|
||||
text: qsTr("Save logs to file")
|
||||
color: AmneziaStyle.color.paleGray
|
||||
ListItemTitleType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 8
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
||||
text: qsTr("Client logs")
|
||||
}
|
||||
|
||||
ParagraphTextType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 8
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
||||
color: AmneziaStyle.color.mutedGray
|
||||
text: qsTr("AmneziaVPN logs")
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
// id: labelWithButton2
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: -8
|
||||
Layout.bottomMargin: -8
|
||||
|
||||
text: qsTr("Open logs folder")
|
||||
leftImageSource: "qrc:/images/controls/folder-open.svg"
|
||||
isSmallLeftImage: true
|
||||
|
||||
// KeyNavigation.tab: labelWithButton3
|
||||
|
||||
clickedFunction: function() {
|
||||
SettingsController.openLogsFolder()
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
||||
LabelWithButtonType {
|
||||
// id: labelWithButton2
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: -8
|
||||
Layout.bottomMargin: -8
|
||||
|
||||
text: qsTr("Export logs")
|
||||
leftImageSource: "qrc:/images/controls/save.svg"
|
||||
isSmallLeftImage: true
|
||||
|
||||
// KeyNavigation.tab: labelWithButton3
|
||||
|
||||
clickedFunction: function() {
|
||||
var fileName = ""
|
||||
if (GC.isMobile()) {
|
||||
fileName = "AmneziaVPN.log"
|
||||
} else {
|
||||
fileName = SystemController.getFileName(qsTr("Save"),
|
||||
qsTr("Logs files (*.log)"),
|
||||
StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/AmneziaVPN",
|
||||
true,
|
||||
".log")
|
||||
}
|
||||
if (fileName !== "") {
|
||||
PageController.showBusyIndicator(true)
|
||||
SettingsController.exportLogsFile(fileName)
|
||||
PageController.showBusyIndicator(false)
|
||||
PageController.showNotificationMessage(qsTr("Logs file saved"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignBaseline
|
||||
Layout.preferredWidth: root.width / ( GC.isMobile() ? 2 : 3 )
|
||||
DividerType {}
|
||||
|
||||
ImageButtonType {
|
||||
id: clearButton
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
ListItemTitleType {
|
||||
visible: !GC.isMobile()
|
||||
|
||||
implicitWidth: 56
|
||||
implicitHeight: 56
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 32
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
||||
image: "qrc:/images/controls/delete.svg"
|
||||
Keys.onTabPressed: lastItemTabClicked(focusItem)
|
||||
text: qsTr("Service logs")
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: clearButton.clicked()
|
||||
Keys.onEnterPressed: clearButton.clicked()
|
||||
onClicked: function() {
|
||||
var headerText = qsTr("Clear logs?")
|
||||
var yesButtonText = qsTr("Continue")
|
||||
var noButtonText = qsTr("Cancel")
|
||||
ParagraphTextType {
|
||||
visible: !GC.isMobile()
|
||||
|
||||
var yesButtonFunction = function() {
|
||||
PageController.showBusyIndicator(true)
|
||||
SettingsController.clearLogs()
|
||||
PageController.showBusyIndicator(false)
|
||||
PageController.showNotificationMessage(qsTr("Logs have been cleaned up"))
|
||||
if (!GC.isMobile()) {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
var noButtonFunction = function() {
|
||||
if (!GC.isMobile()) {
|
||||
focusItem.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 8
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
||||
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||
}
|
||||
color: AmneziaStyle.color.mutedGray
|
||||
text: qsTr("AmneziaVPN-service logs")
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
// id: labelWithButton2
|
||||
|
||||
visible: !GC.isMobile()
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: -8
|
||||
Layout.bottomMargin: -8
|
||||
|
||||
text: qsTr("Open logs folder")
|
||||
leftImageSource: "qrc:/images/controls/folder-open.svg"
|
||||
isSmallLeftImage: true
|
||||
|
||||
// KeyNavigation.tab: labelWithButton3
|
||||
|
||||
clickedFunction: function() {
|
||||
SettingsController.openServiceLogsFolder()
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {
|
||||
visible: !GC.isMobile()
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
// id: labelWithButton2
|
||||
|
||||
visible: !GC.isMobile()
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: -8
|
||||
Layout.bottomMargin: -8
|
||||
|
||||
text: qsTr("Export logs")
|
||||
leftImageSource: "qrc:/images/controls/save.svg"
|
||||
isSmallLeftImage: true
|
||||
|
||||
// KeyNavigation.tab: labelWithButton3
|
||||
|
||||
clickedFunction: function() {
|
||||
var fileName = ""
|
||||
if (GC.isMobile()) {
|
||||
fileName = "AmneziaVPN-service.log"
|
||||
} else {
|
||||
fileName = SystemController.getFileName(qsTr("Save"),
|
||||
qsTr("Logs files (*.log)"),
|
||||
StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/AmneziaVPN-service",
|
||||
true,
|
||||
".log")
|
||||
}
|
||||
|
||||
CaptionTextType {
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: qsTr("Clear logs")
|
||||
color: AmneziaStyle.color.paleGray
|
||||
if (fileName !== "") {
|
||||
PageController.showBusyIndicator(true)
|
||||
SettingsController.exportServiceLogsFile(fileName)
|
||||
PageController.showBusyIndicator(false)
|
||||
PageController.showNotificationMessage(qsTr("Logs file saved"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {
|
||||
visible: !GC.isMobile()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,51 @@ PageType {
|
|||
Layout.leftMargin: 16
|
||||
|
||||
headerText: qsTr("Connection")
|
||||
|
||||
actionButtonImage: PageController.isStartPageVisible() ? "qrc:/images/controls/more-vertical.svg" : ""
|
||||
actionButtonFunction: function() {
|
||||
moreActionsDrawer.open()
|
||||
}
|
||||
|
||||
DrawerType2 {
|
||||
id: moreActionsDrawer
|
||||
|
||||
parent: root
|
||||
|
||||
anchors.fill: parent
|
||||
expandedHeight: root.height * 0.35
|
||||
|
||||
expandedContent: ColumnLayout {
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 16
|
||||
anchors.rightMargin: 16
|
||||
|
||||
HeaderType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 32
|
||||
|
||||
headerText: qsTr("Settings")
|
||||
}
|
||||
|
||||
SwitcherType {
|
||||
id: switcher
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
text: qsTr("Enable logs")
|
||||
|
||||
checked: SettingsController.isLoggingEnabled
|
||||
onCheckedChanged: {
|
||||
if (checked !== SettingsController.isLoggingEnabled) {
|
||||
SettingsController.isLoggingEnabled = checked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ParagraphTextType {
|
||||
|
|
|
|||
|
|
@ -202,6 +202,14 @@ PageType {
|
|||
PageController.showNotificationMessage(qsTr("Settings restored from backup file"))
|
||||
PageController.goToPageHome()
|
||||
}
|
||||
|
||||
function onLoggingStateChanged() {
|
||||
if (SettingsController.isLoggingEnabled) {
|
||||
var message = qsTr("Logging is enabled. Note that logs will be automatically" +
|
||||
"disabled after 14 days, and all log files will be deleted.")
|
||||
PageController.showNotificationMessage(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StackViewType {
|
||||
|
|
|
|||
|
|
@ -69,22 +69,6 @@ QString Utils::JsonToString(const QJsonArray &array, QJsonDocument::JsonFormat f
|
|||
return doc.toJson(format);
|
||||
}
|
||||
|
||||
QString Utils::systemLogPath()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
QStringList locationList = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
|
||||
QString primaryLocation = "ProgramData";
|
||||
foreach (const QString &location, locationList) {
|
||||
if (location.contains(primaryLocation)) {
|
||||
return QString("%1/%2/log").arg(location).arg(APPLICATION_NAME);
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
#else
|
||||
return QString("/var/log/%1").arg(APPLICATION_NAME);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Utils::initializePath(const QString &path)
|
||||
{
|
||||
QDir dir;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ public:
|
|||
static QJsonObject JsonFromString(const QString &string);
|
||||
static QString executable(const QString &baseName, bool absPath);
|
||||
static QString usrExecutable(const QString &baseName);
|
||||
static QString systemLogPath();
|
||||
static bool createEmptyFile(const QString &path);
|
||||
static bool initializePath(const QString &path);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue