Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ RUN apt-get update && \
libglib2.0-0 \
libxkbcommon-dev \
ninja-build \
pkg-config \
python3 \
python3-pip \
unzip \
Expand All @@ -42,7 +43,7 @@ RUN ./emsdk activate 4.0.7 && \
qt-cmake -S /app -B /build \
-DQT_HOST_PATH=$QTSDK_DIR/6.10.3/gcc_64 \
-DCMAKE_BUILD_TYPE=Release \
-DWITH_OPENSSL=OFF -DWITH_TESTS=OFF -DWITH_WEBSOCKET=ON -DWITH_UPDATER=OFF -DPACKAGE_TYPE=Wasm && \
-DWITH_OPENSSL=OFF -DWITH_TESTS=OFF -DWITH_WEBSOCKET=ON -DWITH_UPDATER=OFF -DWITH_QTKEYCHAIN=ON -DPACKAGE_TYPE=Wasm && \
ACTUAL_JOBS=${JOBS:-$(nproc)} && \
cmake --build /build --parallel ${ACTUAL_JOBS} && \
cmake --install /build --prefix /dist && \
Expand Down
28 changes: 21 additions & 7 deletions external/qtkeychain/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
if(QTKEYCHAIN_FOUND)
message(STATUS "QtKeychain found: ${QTKEYCHAIN_LIBRARIES} ${QTKEYCHAIN_INCLUDE_DIRS}")
else()
if(WIN32 OR APPLE)
if(WIN32 OR APPLE OR EMSCRIPTEN)
message(STATUS "Could not find system QtKeychain; building from local source tree")
else()
message(FATAL_ERROR "QtKeychain NOT found: use `-DWITH_QTKEYCHAIN=OFF` to build without account autologin")
endif()

set(QTKEYCHAIN_LIBRARY_NAME qt6keychain)
if(WIN32 AND CMAKE_BUILD_TYPE STREQUAL "Debug")
set(QTKEYCHAIN_LIBRARY_NAME "${QTKEYCHAIN_LIBRARY_NAME}d")
endif()

set(QTKEYCHAIN_SHARED_LIBRARY
"${CMAKE_CURRENT_BINARY_DIR}/qtkeychain-build/bin/${CMAKE_SHARED_LIBRARY_PREFIX}${QTKEYCHAIN_LIBRARY_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}")
if (MSVC)

if (MSVC OR EMSCRIPTEN)
set(QTKEYCHAIN_LIBRARY
"${CMAKE_CURRENT_BINARY_DIR}/qtkeychain-build/lib/${QTKEYCHAIN_LIBRARY_NAME}.lib")
"${CMAKE_CURRENT_BINARY_DIR}/qtkeychain-build/lib/${CMAKE_STATIC_LIBRARY_PREFIX}${QTKEYCHAIN_LIBRARY_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}")
else()
set(QTKEYCHAIN_LIBRARY "${QTKEYCHAIN_SHARED_LIBRARY}")
endif()

set(QTKEYCHAIN_LIBRARIES ${QTKEYCHAIN_LIBRARY})
set(QTKEYCHAIN_INCLUDE_DIR
"${CMAKE_CURRENT_BINARY_DIR}/qtkeychain-build/qtkeychain/" PARENT_SCOPE)
Expand All @@ -32,9 +35,19 @@ else()
add_dependencies(qtkeychain qtkeychain_repo)
else()
include(ExternalProject)

set(QTKEYCHAIN_EXTRA_ARGS -DBUILD_SHARED_LIBS:BOOL=ON)
if(EMSCRIPTEN)
set(QTKEYCHAIN_EXTRA_ARGS
-DBUILD_SHARED_LIBS:BOOL=OFF
-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
-DQT_HOST_PATH=${QT_HOST_PATH}
)
endif()

ExternalProject_Add(qtkeychain_repo
GIT_REPOSITORY "https://github.com/frankosterfeld/qtkeychain.git"
GIT_TAG "7668a63a3669400223c5a563928ae042f499dbf4"
GIT_REPOSITORY "https://github.com/nschimme/qtkeychain.git"
GIT_TAG "wasm"

SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/qtkeychain-src"
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/qtkeychain-build"
Expand All @@ -43,17 +56,18 @@ else()
CMAKE_ARGS -DBUILD_WITH_QT6:BOOL=ON
-DBUILD_TRANSLATIONS:BOOL=OFF
-DBUILD_TEST_APPLICATION:BOOL=OFF
-DBUILD_SHARED_LIBS:BOOL=ON
-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
-DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${CMAKE_OSX_DEPLOYMENT_TARGET}
${QTKEYCHAIN_EXTRA_ARGS}
CMAKE_CACHE_ARGS -DCMAKE_PREFIX_PATH:PATH=${Qt6_DIR}

UPDATE_COMMAND ""
BUILD_ALWAYS 0

BUILD_BYPRODUCTS "${QTKEYCHAIN_SHARED_LIBRARY}"
"${CMAKE_CURRENT_BINARY_DIR}/qtkeychain-build/lib/${QTKEYCHAIN_LIBRARY_NAME}.lib"
"${CMAKE_CURRENT_BINARY_DIR}/qtkeychain-build/lib/${CMAKE_STATIC_LIBRARY_PREFIX}${QTKEYCHAIN_LIBRARY_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}"
)

add_custom_target(qtkeychain)
if(WIN32)
if(MSVC)
Expand Down
3 changes: 3 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,8 @@ set(mmapper_SRCS
preferences/grouppage.h
preferences/mumeprotocolpage.cpp
preferences/mumeprotocolpage.h
preferences/ManagePasswordDialog.cpp
preferences/ManagePasswordDialog.h
preferences/parserpage.cpp
preferences/parserpage.h
preferences/pathmachinepage.cpp
Expand Down Expand Up @@ -665,6 +667,7 @@ set(mmapper_UIS
preferences/graphicspage.ui
preferences/grouppage.ui
preferences/mumeprotocolpage.ui
preferences/ManagePasswordDialog.ui
preferences/parserpage.ui
preferences/pathmachinepage.ui
)
Expand Down
60 changes: 53 additions & 7 deletions src/configuration/PasswordConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@

#include "PasswordConfig.h"

#include "../global/macros.h"
#include "../global/ConfigConsts-Computed.h"
#include "../global/ConfigEnums.h"
#include "configuration.h"

#ifndef MMAPPER_NO_QTKEYCHAIN
static const QLatin1String PASSWORD_KEY("password");
Expand All @@ -15,21 +17,43 @@ PasswordConfig::PasswordConfig(QObject *const parent)
#ifndef MMAPPER_NO_QTKEYCHAIN
, m_readJob(APP_NAME)
, m_writeJob(APP_NAME)
, m_deleteJob(APP_NAME)
{
m_readJob.setAutoDelete(false);
m_writeJob.setAutoDelete(false);
m_deleteJob.setAutoDelete(false);

connect(&m_readJob, &QKeychain::ReadPasswordJob::finished, [this]() {
auto handleError = [this](const QKeychain::Job &job) {
if constexpr (CURRENT_PLATFORM == PlatformEnum::Wasm) {
if (job.error() == QKeychain::AccessDeniedByUser) {
return true;
}
}
emit sig_error(job.errorString());
return false;
};

connect(&m_readJob, &QKeychain::ReadPasswordJob::finished, [this, handleError]() {
if (m_readJob.error()) {
emit sig_error(m_readJob.errorString());
handleError(m_readJob);
} else {
emit sig_incomingPassword(m_readJob.textData());
}
});

connect(&m_writeJob, &QKeychain::WritePasswordJob::finished, [this]() {
connect(&m_writeJob, &QKeychain::WritePasswordJob::finished, [this, handleError]() {
if (m_writeJob.error()) {
emit sig_error(m_writeJob.errorString());
handleError(m_writeJob);
} else {
emit sig_passwordSaved();
}
});

connect(&m_deleteJob, &QKeychain::DeletePasswordJob::finished, [this, handleError]() {
if (m_deleteJob.error()) {
handleError(m_deleteJob);
} else {
emit sig_passwordDeleted();
}
});
}
Expand All @@ -41,7 +65,11 @@ PasswordConfig::PasswordConfig(QObject *const parent)
void PasswordConfig::setPassword(const QString &password)
{
#ifndef MMAPPER_NO_QTKEYCHAIN
m_writeJob.setKey(PASSWORD_KEY);
if constexpr (CURRENT_PLATFORM == PlatformEnum::Wasm) {
m_writeJob.setKey(getConfig().account.accountName);
} else {
m_writeJob.setKey(PASSWORD_KEY);
}
m_writeJob.setTextData(password);
m_writeJob.start();
#else
Expand All @@ -53,9 +81,27 @@ void PasswordConfig::setPassword(const QString &password)
void PasswordConfig::getPassword()
{
#ifndef MMAPPER_NO_QTKEYCHAIN
m_readJob.setKey(PASSWORD_KEY);
if constexpr (CURRENT_PLATFORM == PlatformEnum::Wasm) {
m_readJob.setKey(getConfig().account.accountName);
} else {
m_readJob.setKey(PASSWORD_KEY);
}
m_readJob.start();
#else
emit sig_error("Password retrieval is not available.");
#endif
}

void PasswordConfig::deletePassword()
{
#ifndef MMAPPER_NO_QTKEYCHAIN
if constexpr (CURRENT_PLATFORM == PlatformEnum::Wasm) {
m_deleteJob.setKey(getConfig().account.accountName);
} else {
m_deleteJob.setKey(PASSWORD_KEY);
}
m_deleteJob.start();
#else
emit sig_error("Password deletion is not available.");
#endif
}
7 changes: 6 additions & 1 deletion src/configuration/PasswordConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// Copyright (C) 2019 The MMapper Authors

#include "../global/RuleOf5.h"
#include "../global/macros.h"

#include <QObject>
#include <QString>
Expand All @@ -11,14 +12,15 @@
#include <keychain.h>
#endif

class PasswordConfig final : public QObject
class NODISCARD_QOBJECT PasswordConfig final : public QObject
{
Q_OBJECT

private:
#ifndef MMAPPER_NO_QTKEYCHAIN
QKeychain::ReadPasswordJob m_readJob;
QKeychain::WritePasswordJob m_writeJob;
QKeychain::DeletePasswordJob m_deleteJob;
#endif

public:
Expand All @@ -28,8 +30,11 @@ class PasswordConfig final : public QObject

void setPassword(const QString &password);
void getPassword();
void deletePassword();

signals:
void sig_error(const QString &msg);
void sig_incomingPassword(const QString &password);
void sig_passwordSaved();
void sig_passwordDeleted();
};
64 changes: 64 additions & 0 deletions src/preferences/ManagePasswordDialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (C) 2026 The MMapper Authors

#include "ManagePasswordDialog.h"

#include "../global/ConfigConsts-Computed.h"
#include "../global/ConfigEnums.h"
#include "ui_ManagePasswordDialog.h"

#include <QLineEdit>
#include <QPushButton>

ManagePasswordDialog::ManagePasswordDialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::ManagePasswordDialog)
{
ui->setupUi(this);

if constexpr (CURRENT_PLATFORM == PlatformEnum::Wasm) {
setWindowTitle("Manage Account");
ui->label_2->hide();
ui->accountPassword->hide();
ui->showPassword->hide();
ui->deleteButton->hide();
} else {
connect(ui->showPassword, &QToolButton::toggled, this, [this](bool checked) {
ui->accountPassword->setEchoMode(checked ? QLineEdit::Normal : QLineEdit::Password);
});

connect(ui->deleteButton, &QPushButton::clicked, this, [this]() {
emit sig_deleteRequested();
ui->accountPassword->clear();
ui->deleteButton->setEnabled(false);
});
}
}

ManagePasswordDialog::~ManagePasswordDialog()
{
delete ui;
}

void ManagePasswordDialog::setAccountName(const QString &name)
{
ui->accountName->setText(name);
}

QString ManagePasswordDialog::accountName() const
{
return ui->accountName->text();
}

void ManagePasswordDialog::setPassword(const QString &password)
{
ui->accountPassword->setText(password);
if constexpr (CURRENT_PLATFORM != PlatformEnum::Wasm) {
ui->deleteButton->setEnabled(!password.isEmpty());
}
}

QString ManagePasswordDialog::password() const
{
return ui->accountPassword->text();
}
32 changes: 32 additions & 0 deletions src/preferences/ManagePasswordDialog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#pragma once
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (C) 2026 The MMapper Authors

#include "../global/macros.h"

#include <QDialog>

namespace Ui {
class ManagePasswordDialog;
}

class NODISCARD_QOBJECT ManagePasswordDialog final : public QDialog
{
Q_OBJECT

private:
Ui::ManagePasswordDialog *const ui;

public:
explicit ManagePasswordDialog(QWidget *parent = nullptr);
~ManagePasswordDialog() final;

void setAccountName(const QString &name);
NODISCARD QString accountName() const;

void setPassword(const QString &password);
NODISCARD QString password() const;

signals:
void sig_deleteRequested();
};
Loading
Loading