added pages for sftp and tor website settings

This commit is contained in:
vladimir.kuznetsov 2023-07-18 11:15:04 +09:00
parent 75489c00c2
commit 5d677a9115
22 changed files with 713 additions and 6 deletions

View file

@ -129,8 +129,16 @@ file(GLOB_RECURSE PAGE_LOGIC_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/
file(GLOB CONFIGURATORS_H CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/configurators/*.h)
file(GLOB CONFIGURATORS_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/configurators/*.cpp)
file(GLOB UI_MODELS_H CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/models/*.h ${CMAKE_CURRENT_LIST_DIR}/ui/models/protocols/*.h)
file(GLOB UI_MODELS_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/models/*.cpp ${CMAKE_CURRENT_LIST_DIR}/ui/models/protocols/*.cpp)
file(GLOB UI_MODELS_H CONFIGURE_DEPENDS
${CMAKE_CURRENT_LIST_DIR}/ui/models/*.h
${CMAKE_CURRENT_LIST_DIR}/ui/models/protocols/*.h
${CMAKE_CURRENT_LIST_DIR}/ui/models/services/*.h
)
file(GLOB UI_MODELS_CPP CONFIGURE_DEPENDS
${CMAKE_CURRENT_LIST_DIR}/ui/models/*.cpp
${CMAKE_CURRENT_LIST_DIR}/ui/models/protocols/*.cpp
${CMAKE_CURRENT_LIST_DIR}/ui/models/services/*.cpp
)
file(GLOB UI_CONTROLLERS_H CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/controllers/*.h)
file(GLOB UI_CONTROLLERS_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/controllers/*.cpp)

View file

@ -267,6 +267,9 @@ void AmneziaApplication::initModels()
m_ikev2ConfigModel.reset(new Ikev2ConfigModel(this));
m_engine->rootContext()->setContextProperty("Ikev2ConfigModel", m_ikev2ConfigModel.get());
#endif
m_sftpConfigModel.reset(new SftpConfigModel(this));
m_engine->rootContext()->setContextProperty("SftpConfigModel", m_sftpConfigModel.get());
}
void AmneziaApplication::initControllers()

View file

@ -31,6 +31,7 @@
#include "ui/models/protocols/wireguardConfigModel.h"
#include "ui/models/protocols_model.h"
#include "ui/models/servers_model.h"
#include "ui/models/services/sftpConfigModel.h"
#define amnApp (static_cast<AmneziaApplication *>(QCoreApplication::instance()))
@ -91,6 +92,8 @@ private:
QScopedPointer<Ikev2ConfigModel> m_ikev2ConfigModel;
#endif
QScopedPointer<SftpConfigModel> m_sftpConfigModel;
QSharedPointer<VpnConnection> m_vpnConnection;
QScopedPointer<NotificationHandler> m_notificationHandler;

View file

@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20 9H11C9.89543 9 9 9.89543 9 11V20C9 21.1046 9.89543 22 11 22H20C21.1046 22 22 21.1046 22 20V11C22 9.89543 21.1046 9 20 9Z" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5 15H4C3.46957 15 2.96086 14.7893 2.58579 14.4142C2.21071 14.0391 2 13.5304 2 13V4C2 3.46957 2.21071 2.96086 2.58579 2.58579C2.96086 2.21071 3.46957 2 4 2H13C13.5304 2 14.0391 2.21071 14.4142 2.58579C14.7893 2.96086 15 3.46957 15 4V5" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 649 B

View file

@ -65,6 +65,7 @@ namespace amnezia
constexpr char wireguard[] = "wireguard";
constexpr char shadowsocks[] = "shadowsocks";
constexpr char cloak[] = "cloak";
constexpr char sftp[] = "sftp";
}

View file

@ -275,5 +275,8 @@
<file>ui/qml/Pages2/PageProtocolCloakSettings.qml</file>
<file>ui/qml/Pages2/PageProtocolRaw.qml</file>
<file>ui/qml/Pages2/PageSettingsLogging.qml</file>
<file>ui/qml/Pages2/PageServiceSftpSettings.qml</file>
<file>images/controls/copy.svg</file>
<file>ui/qml/Pages2/PageServiceTorWebsiteSettings.qml</file>
</qresource>
</RCC>

View file

@ -1,6 +1,8 @@
#include "installController.h"
#include <QDesktopServices>
#include <QJsonObject>
#include <QStandardPaths>
#include "core/errorstrings.h"
#include "core/servercontroller.h"
@ -214,3 +216,80 @@ void InstallController::setShouldCreateServer(bool shouldCreateServer)
{
m_shouldCreateServer = shouldCreateServer;
}
void InstallController::mountSftpDrive(const QString &port, const QString &password, const QString &username)
{
QString mountPath;
QString cmd;
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
ServerCredentials serverCredentials =
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
QString hostname = serverCredentials.hostName;
#ifdef Q_OS_WINDOWS
mountPath = getNextDriverLetter() + ":";
// QString cmd = QString("net use \\\\sshfs\\%1@x.x.x.x!%2 /USER:%1 %3")
// .arg(labelTftpUserNameText())
// .arg(labelTftpPortText())
// .arg(labelTftpPasswordText());
cmd = "C:\\Program Files\\SSHFS-Win\\bin\\sshfs.exe";
#elif defined AMNEZIA_DESKTOP
mountPath =
QString("%1/sftp:%2:%3").arg(QStandardPaths::writableLocation(QStandardPaths::HomeLocation), hostname, port);
QDir dir(mountPath);
if (!dir.exists()) {
dir.mkpath(mountPath);
}
cmd = "/usr/local/bin/sshfs";
#endif
#ifdef AMNEZIA_DESKTOP
QSharedPointer<QProcess> process;
process.reset(new QProcess());
m_sftpMountProcesses.append(process);
process->setProcessChannelMode(QProcess::MergedChannels);
connect(process.get(), &QProcess::readyRead, this, [this, process, mountPath]() {
QString s = process->readAll();
if (s.contains("The service sshfs has been started")) {
QDesktopServices::openUrl(QUrl("file:///" + mountPath));
}
qDebug() << s;
});
process->setProgram(cmd);
QString args = QString("%1@%2:/ %3 "
"-o port=%4 "
"-f "
"-o reconnect "
"-o rellinks "
"-o fstypename=SSHFS "
"-o ssh_command=/usr/bin/ssh.exe "
"-o UserKnownHostsFile=/dev/null "
"-o StrictHostKeyChecking=no "
"-o password_stdin")
.arg(username, hostname, mountPath, port);
// args.replace("\n", " ");
// args.replace("\r", " ");
// #ifndef Q_OS_WIN
// args.replace("reconnect-orellinks", "");
// #endif
process->setArguments(args.split(" ", Qt::SkipEmptyParts));
process->start();
process->waitForStarted(50);
if (process->state() != QProcess::Running) {
qDebug() << "onPushButtonSftpMountDriveClicked process not started";
qDebug() << args;
} else {
process->write((password + "\n").toUtf8());
}
// qDebug().noquote() << "onPushButtonSftpMountDriveClicked" << args;
#endif
}

View file

@ -2,6 +2,7 @@
#define INSTALLCONTROLLER_H
#include <QObject>
#include <QProcess>
#include "containers/containers_defs.h"
#include "core/defs.h"
@ -28,6 +29,8 @@ public slots:
QRegularExpression ipAddressPortRegExp();
void mountSftpDrive(const QString &port, const QString &password, const QString &username);
signals:
void installContainerFinished(bool isInstalledContainerFound);
void installServerFinished(bool isInstalledContainerFound);
@ -52,6 +55,8 @@ private:
ServerCredentials m_currentlyInstalledServerCredentials;
bool m_shouldCreateServer;
QList<QSharedPointer<QProcess>> m_sftpMountProcesses;
};
#endif // INSTALLCONTROLLER_H

View file

@ -29,6 +29,9 @@ namespace PageLoader
PageSettingsAbout,
PageSettingsLogging,
PageServiceSftpSettings,
PageServiceTorWebsiteSettings,
PageSetupWizardStart,
PageSetupWizardCredentials,
PageSetupWizardProtocols,

View file

@ -118,6 +118,11 @@ QString ContainersModel::getCurrentlyProcessedContainerName()
return ContainerProps::containerHumanNames().value(static_cast<DockerContainer>(m_currentlyProcessedContainerIndex));
}
QJsonObject ContainersModel::getCurrentlyProcessedContainerConfig()
{
return qvariant_cast<QJsonObject>(data(index(m_currentlyProcessedContainerIndex), ConfigRole));
}
void ContainersModel::removeAllContainers()
{

View file

@ -50,6 +50,7 @@ public slots:
int getCurrentlyProcessedContainerIndex();
QString getCurrentlyProcessedContainerName();
QJsonObject getCurrentlyProcessedContainerConfig();
void removeAllContainers();
void removeCurrentlyProcessedContainer();

View file

@ -106,6 +106,11 @@ int ServersModel::getCurrentlyProcessedServerIndex()
return m_currentlyProcessedServerIndex;
}
QString ServersModel::getCurrentlyProcessedServerHostName()
{
return qvariant_cast<QString>(data(m_currentlyProcessedServerIndex, HostNameRole));
}
bool ServersModel::isDefaultServerCurrentlyProcessed()
{
return m_defaultServerIndex == m_currentlyProcessedServerIndex;

View file

@ -45,6 +45,8 @@ public slots:
void setCurrentlyProcessedServerIndex(const int index);
int getCurrentlyProcessedServerIndex();
QString getCurrentlyProcessedServerHostName();
void addServer(const QJsonObject &server);
void removeServer();

View file

@ -0,0 +1,64 @@
#include "sftpConfigModel.h"
#include "protocols/protocols_defs.h"
SftpConfigModel::SftpConfigModel(QObject *parent) : QAbstractListModel(parent)
{
}
int SftpConfigModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return 1;
}
QVariant SftpConfigModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() < 0 || index.row() >= rowCount()) {
return false;
}
switch (role) {
case Roles::PortRole: return m_protocolConfig.value(config_key::port).toString();
case Roles::UserNameRole:
return m_protocolConfig.value(config_key::userName).toString(protocols::sftp::defaultUserName);
case Roles::PasswordRole: return m_protocolConfig.value(config_key::password).toString();
}
return QVariant();
}
void SftpConfigModel::updateModel(const QJsonObject &config)
{
beginResetModel();
m_container = ContainerProps::containerFromString(config.value(config_key::container).toString());
m_fullConfig = config;
QJsonObject protocolConfig = config.value(config_key::sftp).toObject();
m_protocolConfig.insert(config_key::userName,
protocolConfig.value(config_key::userName).toString(protocols::sftp::defaultUserName));
m_protocolConfig.insert(config_key::password, protocolConfig.value(config_key::password).toString());
m_protocolConfig.insert(config_key::port, protocolConfig.value(config_key::port).toString());
endResetModel();
}
QJsonObject SftpConfigModel::getConfig()
{
m_fullConfig.insert(config_key::sftp, m_protocolConfig);
return m_fullConfig;
}
QHash<int, QByteArray> SftpConfigModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[PortRole] = "port";
roles[UserNameRole] = "username";
roles[PasswordRole] = "password";
return roles;
}

View file

@ -0,0 +1,39 @@
#ifndef SFTPCONFIGMODEL_H
#define SFTPCONFIGMODEL_H
#include <QAbstractListModel>
#include <QJsonObject>
#include "containers/containers_defs.h"
class SftpConfigModel : public QAbstractListModel
{
Q_OBJECT
public:
enum Roles {
PortRole = Qt::UserRole + 1,
UserNameRole,
PasswordRole
};
explicit SftpConfigModel(QObject *parent = nullptr);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
public slots:
void updateModel(const QJsonObject &config);
QJsonObject getConfig();
protected:
QHash<int, QByteArray> roleNames() const override;
private:
DockerContainer m_container;
QJsonObject m_protocolConfig;
QJsonObject m_fullConfig;
};
#endif // SFTPCONFIGMODEL_H

View file

@ -92,6 +92,7 @@ ListView {
if (isInstalled) {
var containerIndex = root.model.mapToSource(index)
ContainersModel.setCurrentlyProcessedContainerIndex(containerIndex)
if (config[ContainerProps.containerTypeToString(containerIndex)]["isThirdPartyConfig"]) {
ProtocolsModel.updateModel(config)
goToPage(PageEnum.PageProtocolRaw)
@ -114,6 +115,16 @@ ListView {
goToPage(PageEnum.PageProtocolIKev2Settings)
break
}
case ContainerEnum.Sftp: {
SftpConfigModel.updateModel(config)
goToPage(PageEnum.PageServiceSftpSettings)
break
}
case ContainerEnum.TorWebSite: {
goToPage(PageEnum.PageServiceTorWebsiteSettings)
break
}
default: {
if (serviceType !== ProtocolEnum.Other) { //todo disable settings for dns container
ProtocolsModel.updateModel(config)

View file

@ -16,6 +16,10 @@ Item {
property string leftImageSource
property string textColor: "#d7d8db"
property string descriptionColor: "#878B91"
property string rightImageColor: "#878B91"
property bool descriptionOnTop: false
implicitWidth: content.implicitWidth + content.anchors.topMargin + content.anchors.bottomMargin
implicitHeight: content.implicitHeight + content.anchors.leftMargin + content.anchors.rightMargin
@ -53,26 +57,41 @@ Item {
}
ColumnLayout {
property real textLineHeight: 21.6
property real descriptionTextLineHeight: 16
property int textPixelSize: 18
property int descriptionTextSize: 13
ListItemTitleType {
text: root.text
color: root.textColor
color: root.descriptionOnTop ? root.descriptionColor : root.textColor
Layout.fillWidth: true
lineHeight: root.descriptionOnTop ? parent.descriptionTextLineHeight : parent.textLineHeight
font.pixelSize: root.descriptionOnTop ? parent.descriptionTextSize : parent.textPixelSize
font.letterSpacing: root.descriptionOnTop ? 0.02 : 0
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
}
CaptionTextType {
id: description
color: "#878B91"
color: root.descriptionOnTop ? root.textColor : root.descriptionColor
text: root.descriptionText
visible: root.descriptionText !== ""
Layout.fillWidth: true
lineHeight: root.descriptionOnTop ? parent.textLineHeight : parent.descriptionTextLineHeight
font.pixelSize: root.descriptionOnTop ? parent.textPixelSize : parent.descriptionTextSize
font.letterSpacing: root.descriptionOnTop ? 0 : 0.02
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
}
@ -83,6 +102,7 @@ Item {
hoverEnabled: false
image: rightImageSource
imageColor: rightImageColor
visible: rightImageSource ? true : false
Layout.alignment: Qt.AlignRight

View file

@ -10,5 +10,5 @@ Text {
font.family: "PT Root UI VF"
font.letterSpacing: 0.02
wrapMode: Text.WordWrap
wrapMode: Text.Wrap
}

View file

@ -9,5 +9,5 @@ Text {
font.weight: 400
font.family: "PT Root UI VF"
wrapMode: Text.WordWrap
wrapMode: Text.Wrap
}

View file

@ -413,6 +413,8 @@ PageType {
BasicButtonType {
Layout.topMargin: 24
Layout.leftMargin: -8
implicitHeight: 32
defaultColor: "transparent"
hoveredColor: Qt.rgba(1, 1, 1, 0.08)

View file

@ -0,0 +1,280 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import SortFilterProxyModel 0.2
import PageEnum 1.0
import "./"
import "../Controls2"
import "../Controls2/TextTypes"
import "../Config"
import "../Components"
PageType {
id: root
//todo move to main?
Connections {
target: InstallController
function onInstallationErrorOccurred(errorMessage) {
PageController.showErrorMessage(errorMessage)
}
function onUpdateContainerFinished() {
//todo change to notification
PageController.showErrorMessage(qsTr("Settings updated successfully"))
}
}
ColumnLayout {
id: backButton
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 20
BackButtonType {
}
}
FlickableType {
id: fl
anchors.top: backButton.bottom
anchors.bottom: parent.bottom
contentHeight: content.implicitHeight
Column {
id: content
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
enabled: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
ListView {
id: listview
width: parent.width
height: listview.contentItem.height
clip: true
interactive: false
model: SftpConfigModel
delegate: Item {
implicitWidth: listview.width
implicitHeight: col.implicitHeight
ColumnLayout {
id: col
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
spacing: 0
HeaderType {
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
headerText: qsTr("SFTP settings")
}
LabelWithButtonType {
Layout.fillWidth: true
Layout.topMargin: 32
text: qsTr("Host")
descriptionText: ServersModel.getCurrentlyProcessedServerHostName()
descriptionOnTop: true
rightImageSource: "qrc:/images/controls/copy.svg"
rightImageColor: "#D7D8DB"
clickedFunction: function() {
col.copyToClipBoard(descriptionText)
}
}
LabelWithButtonType {
Layout.fillWidth: true
text: qsTr("Port")
descriptionText: port
descriptionOnTop: true
rightImageSource: "qrc:/images/controls/copy.svg"
rightImageColor: "#D7D8DB"
clickedFunction: function() {
col.copyToClipBoard(descriptionText)
}
}
LabelWithButtonType {
Layout.fillWidth: true
text: qsTr("Login")
descriptionText: username
descriptionOnTop: true
rightImageSource: "qrc:/images/controls/copy.svg"
rightImageColor: "#D7D8DB"
clickedFunction: function() {
col.copyToClipBoard(descriptionText)
}
}
LabelWithButtonType {
Layout.fillWidth: true
text: qsTr("Password")
descriptionText: password
descriptionOnTop: true
rightImageSource: "qrc:/images/controls/copy.svg"
rightImageColor: "#D7D8DB"
clickedFunction: function() {
col.copyToClipBoard(descriptionText)
}
}
TextEdit{
id: clipboard
visible: false
}
function copyToClipBoard(text) {
clipboard.text = text
clipboard.selectAll()
clipboard.copy()
clipboard.select(0, 0)
}
BasicButtonType {
Layout.fillWidth: true
Layout.topMargin: 24
Layout.bottomMargin: 24
Layout.leftMargin: 16
Layout.rightMargin: 16
defaultColor: "transparent"
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
pressedColor: Qt.rgba(1, 1, 1, 0.12)
disabledColor: "#878B91"
textColor: "#D7D8DB"
borderWidth: 1
text: qsTr("Mount folder on device")
onClicked: {
PageController.showBusyIndicator(true)
InstallController.mountSftpDrive(port, password, username)
PageController.showBusyIndicator(false)
}
}
ParagraphTextType {
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
readonly property string windowsFirstLink: "<a href=\"https://github.com/billziss-gh/winfsp/releases/latest\" style=\"color: #FBB26A;\">WinFsp</a>"
readonly property string windowsSecondLink: "<a href=\"https://github.com/billziss-gh/sshfs-win/releases\" style=\"color: #FBB26A;\">SSHFS-Win</a>"
readonly property string macosFirstLink: "<a href=\"https://osxfuse.github.io/\" style=\"color: #FBB26A;\">macFUSE</a>"
readonly property string macosSecondLink: "<a href=\"https://osxfuse.github.io/\" style=\"color: #FBB26A;\">SSHFS</a>"
onLinkActivated: Qt.openUrlExternally(link)
textFormat: Text.RichText
text: {
var str = qsTr("In order to mount remote SFTP folder as local drive, perform following steps: <br>")
if (Qt.platform.os === "windows") {
str += qsTr("<br>1. Install the latest version of ") + windowsFirstLink + "\n"
str += qsTr("<br>2. Install the latest version of ") + windowsSecondLink + "\n"
} else if (Qt.platform.os === "osx") {
str += qsTr("<br>1. Install the latest version of ") + macosFirstLink + "\n"
str += qsTr("<br>2. Install the latest version of ") + macosSecondLink + "\n"
} else if (Qt.platform.os === "linux") {
return ""
} else return ""
return str
}
}
BasicButtonType {
Layout.topMargin: 16
Layout.bottomMargin: 16
Layout.leftMargin: 8
implicitHeight: 32
defaultColor: "transparent"
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
pressedColor: Qt.rgba(1, 1, 1, 0.12)
disabledColor: "#878B91"
textColor: "#FBB26A"
text: qsTr("Detailed instructions")
onClicked: {
// Qt.openUrlExternally("https://github.com/amnezia-vpn/desktop-client/releases/latest")
}
}
BasicButtonType {
Layout.topMargin: 24
Layout.bottomMargin: 16
Layout.leftMargin: 8
implicitHeight: 32
defaultColor: "transparent"
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
pressedColor: Qt.rgba(1, 1, 1, 0.12)
textColor: "#EB5757"
text: qsTr("Remove SFTP and all data stored there")
onClicked: {
questionDrawer.headerText = qsTr("Some description")
questionDrawer.yesButtonText = qsTr("Continue")
questionDrawer.noButtonText = qsTr("Cancel")
questionDrawer.yesButtonFunction = function() {
questionDrawer.visible = false
goToPage(PageEnum.PageDeinstalling)
ContainersModel.removeCurrentlyProcessedContainer()
closePage()
closePage() //todo auto close to deinstall page?
}
questionDrawer.noButtonFunction = function() {
questionDrawer.visible = false
}
questionDrawer.visible = true
}
}
}
}
}
}
QuestionDrawer {
id: questionDrawer
}
}
}

View file

@ -0,0 +1,169 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import SortFilterProxyModel 0.2
import PageEnum 1.0
import ContainerProps 1.0
import "./"
import "../Controls2"
import "../Controls2/TextTypes"
import "../Config"
import "../Components"
PageType {
id: root
//todo move to main?
Connections {
target: InstallController
function onInstallationErrorOccurred(errorMessage) {
PageController.showErrorMessage(errorMessage)
}
function onUpdateContainerFinished() {
//todo change to notification
PageController.showErrorMessage(qsTr("Settings updated successfully"))
}
}
ColumnLayout {
id: backButton
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 20
BackButtonType {
}
}
FlickableType {
id: fl
anchors.top: backButton.bottom
anchors.bottom: parent.bottom
contentHeight: content.implicitHeight
ColumnLayout {
id: content
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
spacing: 0
HeaderType {
Layout.fillWidth: true
Layout.leftMargin: 16
Layout.rightMargin: 16
headerText: qsTr("Tor website settings")
}
LabelWithButtonType {
Layout.fillWidth: true
Layout.topMargin: 32
text: qsTr("Website address")
descriptionText: {
var config = ContainersModel.getCurrentlyProcessedContainerConfig()
var containerIndex = ContainersModel.getCurrentlyProcessedContainerIndex()
return config[ContainerProps.containerTypeToString(containerIndex)]["site"]
}
descriptionOnTop: true
textColor: "#FBB26A"
rightImageSource: "qrc:/images/controls/copy.svg"
rightImageColor: "#D7D8DB"
clickedFunction: function() {
content.copyToClipBoard(descriptionText)
}
}
TextEdit{
id: clipboard
visible: false
}
function copyToClipBoard(text) {
clipboard.text = text
clipboard.selectAll()
clipboard.copy()
clipboard.select(0, 0)
}
ParagraphTextType {
Layout.fillWidth: true
Layout.topMargin: 40
Layout.leftMargin: 16
Layout.rightMargin: 16
onLinkActivated: Qt.openUrlExternally(link)
textFormat: Text.RichText
text: qsTr("Use <a href=\"https://www.torproject.org/download/\" style=\"color: #FBB26A;\">Tor Browser</a> to open this url.")
}
ParagraphTextType {
Layout.fillWidth: true
Layout.topMargin: 16
Layout.leftMargin: 16
Layout.rightMargin: 16
text: qsTr("After installation it takes several minutes while your onion site will become available in the Tor Network.")
}
ParagraphTextType {
Layout.fillWidth: true
Layout.topMargin: 16
Layout.leftMargin: 16
Layout.rightMargin: 16
text: qsTr("When configuring WordPress set the domain as this onion address.")
}
BasicButtonType {
Layout.topMargin: 24
Layout.bottomMargin: 16
Layout.leftMargin: 8
implicitHeight: 32
defaultColor: "transparent"
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
pressedColor: Qt.rgba(1, 1, 1, 0.12)
textColor: "#EB5757"
text: qsTr("Remove website")
onClicked: {
questionDrawer.headerText = qsTr("Some description")
questionDrawer.yesButtonText = qsTr("Continue")
questionDrawer.noButtonText = qsTr("Cancel")
questionDrawer.yesButtonFunction = function() {
questionDrawer.visible = false
goToPage(PageEnum.PageDeinstalling)
ContainersModel.removeCurrentlyProcessedContainer()
closePage()
closePage() //todo auto close to deinstall page?
}
questionDrawer.noButtonFunction = function() {
questionDrawer.visible = false
}
questionDrawer.visible = true
}
}
}
QuestionDrawer {
id: questionDrawer
}
}
}