Merge pull request #533 from geri1701/no-kf5-qt-only

Fix Qt-only build when BUILD_WITH_KF5=OFF
This commit is contained in:
Laurent Trinques
2026-07-05 18:00:35 +02:00
committed by GitHub
16 changed files with 714 additions and 33 deletions
+8
View File
@@ -148,6 +148,14 @@ target_include_directories(
${QET_DIR}/sources/svg ${QET_DIR}/sources/svg
) )
if(NOT BUILD_WITH_KF5)
target_include_directories(
${PROJECT_NAME}
PRIVATE
${QET_DIR}/sources/ui/nokde
)
endif()
install(TARGETS ${PROJECT_NAME}) install(TARGETS ${PROJECT_NAME})
if (NOT MINGW) if (NOT MINGW)
+1 -1
View File
@@ -16,7 +16,7 @@
message(" - fetch_kdeaddons") message(" - fetch_kdeaddons")
if(DEFINED BUILD_WITH_KF5) if(BUILD_WITH_KF5)
Include(FetchContent) Include(FetchContent)
option(BUILD_KF5 "Build KF5 libraries, use system ones otherwise" YES) option(BUILD_KF5 "Build KF5 libraries, use system ones otherwise" YES)
+11
View File
@@ -724,6 +724,17 @@ set(QET_SRC_FILES
${QET_DIR}/sources/xml/terminalstriplayoutpatternxml.h ${QET_DIR}/sources/xml/terminalstriplayoutpatternxml.h
) )
if(NOT BUILD_WITH_KF5)
list(APPEND QET_SRC_FILES
${QET_DIR}/sources/ui/nokde/kautosavefile.cpp
${QET_DIR}/sources/ui/nokde/kautosavefile.h
${QET_DIR}/sources/ui/nokde/kcolorbutton.cpp
${QET_DIR}/sources/ui/nokde/kcolorbutton.h
${QET_DIR}/sources/ui/nokde/kcolorcombo.cpp
${QET_DIR}/sources/ui/nokde/kcolorcombo.h
)
endif()
set(TS_FILES set(TS_FILES
${QET_DIR}/lang/qet_ar.ts ${QET_DIR}/lang/qet_ar.ts
${QET_DIR}/lang/qet_ca.ts ${QET_DIR}/lang/qet_ca.ts
+1 -4
View File
@@ -47,6 +47,7 @@
#include <QProcessEnvironment> #include <QProcessEnvironment>
#include <QRegularExpression> #include <QRegularExpression>
#ifdef BUILD_WITHOUT_KF5 #ifdef BUILD_WITHOUT_KF5
# include "ui/nokde/kautosavefile.h"
#else #else
# include <KAutoSaveFile> # include <KAutoSaveFile>
#endif #endif
@@ -2500,9 +2501,6 @@ void QETApp::buildSystemTrayMenu()
*/ */
void QETApp::checkBackupFiles() void QETApp::checkBackupFiles()
{ {
#ifdef BUILD_WITHOUT_KF5
return;
#else
QList<KAutoSaveFile *> stale_files = KAutoSaveFile::allStaleFiles(); QList<KAutoSaveFile *> stale_files = KAutoSaveFile::allStaleFiles();
//Remove from the list @stale_files, the stales file of opened project //Remove from the list @stale_files, the stales file of opened project
@@ -2577,7 +2575,6 @@ void QETApp::checkBackupFiles()
delete stale; delete stale;
} }
} }
#endif
} }
/** /**
+1 -3
View File
@@ -49,6 +49,7 @@
#include "ui/terminalnumberingdialog.h" #include "ui/terminalnumberingdialog.h"
#include <QDebug> #include <QDebug>
#ifdef BUILD_WITHOUT_KF5 #ifdef BUILD_WITHOUT_KF5
# include "ui/nokde/kautosavefile.h"
#else #else
# include <KAutoSaveFile> # include <KAutoSaveFile>
#endif #endif
@@ -1948,8 +1949,6 @@ bool QETDiagramEditor::drawGrid() const
return m_draw_grid->isChecked(); return m_draw_grid->isChecked();
} }
#ifdef BUILD_WITHOUT_KF5
#else
/** /**
@brief QETDiagramEditor::openBackupFiles @brief QETDiagramEditor::openBackupFiles
@param backup_files @param backup_files
@@ -1980,7 +1979,6 @@ void QETDiagramEditor::openBackupFiles(QList<KAutoSaveFile *> backup_files)
DialogWaiting::dropInstance(); DialogWaiting::dropInstance();
} }
} }
#endif
/** /**
met a jour le menu "Fenetres" met a jour le menu "Fenetres"
*/ */
-6
View File
@@ -44,10 +44,7 @@ class ElementsCollectionWidget;
class AutoNumberingDockWidget; class AutoNumberingDockWidget;
class TerminalNumberingDialog; class TerminalNumberingDialog;
#ifdef BUILD_WITHOUT_KF5
#else
class KAutoSaveFile; class KAutoSaveFile;
#endif
/** /**
This class represents the main window of the QElectroTech diagram editor and, This class represents the main window of the QElectroTech diagram editor and,
ipso facto, the most important part of the QElectroTech user interface. ipso facto, the most important part of the QElectroTech user interface.
@@ -72,10 +69,7 @@ class QETDiagramEditor : public QETMainWindow
ProjectView *currentProjectView() const; ProjectView *currentProjectView() const;
QETProject *currentProject() const; QETProject *currentProject() const;
bool drawGrid() const; bool drawGrid() const;
#ifdef BUILD_WITHOUT_KF5
#else
void openBackupFiles (QList<KAutoSaveFile *> backup_files); void openBackupFiles (QList<KAutoSaveFile *> backup_files);
#endif
protected: protected:
bool event(QEvent *) override; bool event(QEvent *) override;
-9
View File
@@ -93,8 +93,6 @@ QETProject::QETProject(const QString &path, QObject *parent) :
init(); init();
} }
#ifdef BUILD_WITHOUT_KF5
#else
/** /**
@brief QETProject::QETProject @brief QETProject::QETProject
@param backup : backup file to open, QETProject take ownership of backup. @param backup : backup file to open, QETProject take ownership of backup.
@@ -129,7 +127,6 @@ QETProject::QETProject(KAutoSaveFile *backup, QObject *parent) :
init(); init();
} }
#endif
/** /**
@brief QETProject::~QETProject @brief QETProject::~QETProject
@@ -342,15 +339,12 @@ void QETProject::setFilePath(const QString &filepath)
if (filepath == m_file_path) { if (filepath == m_file_path) {
return; return;
} }
#ifdef BUILD_WITHOUT_KF5
#else
//Don't close/re-point the backup file while a backup is still writing it. //Don't close/re-point the backup file while a backup is still writing it.
m_backup_future.waitForFinished(); m_backup_future.waitForFinished();
if (m_backup_file.isOpen()) { if (m_backup_file.isOpen()) {
m_backup_file.close(); m_backup_file.close();
} }
m_backup_file.setManagedFile(QUrl::fromLocalFile(filepath)); m_backup_file.setManagedFile(QUrl::fromLocalFile(filepath));
#endif
m_file_path = filepath; m_file_path = filepath;
QFileInfo fi(m_file_path); QFileInfo fi(m_file_path);
@@ -1813,8 +1807,6 @@ void QETProject::writeBackup()
{ {
if (!m_backup_enabled) if (!m_backup_enabled)
return; return;
#ifdef BUILD_WITHOUT_KF5
#else
# if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt 6: remove # if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt 6: remove
//Don't launch a new backup while the previous one is still writing: //Don't launch a new backup while the previous one is still writing:
//both would write through &m_backup_file on different threads. //both would write through &m_backup_file on different threads.
@@ -1830,7 +1822,6 @@ void QETProject::writeBackup()
qDebug() << "Help code for QT 6 or later" qDebug() << "Help code for QT 6 or later"
<< "QtConcurrent::run its backwards now...function, object, args"; << "QtConcurrent::run its backwards now...function, object, args";
# endif # endif
#endif
} }
/** /**
+1 -10
View File
@@ -30,6 +30,7 @@
#include "titleblockproperties.h" #include "titleblockproperties.h"
#ifdef BUILD_WITHOUT_KF5 #ifdef BUILD_WITHOUT_KF5
# include "ui/nokde/kautosavefile.h"
#else #else
# include <KAutoSaveFile> # include <KAutoSaveFile>
#endif #endif
@@ -48,10 +49,6 @@ class XmlElementCollection;
class QTimer; class QTimer;
class TerminalStrip; class TerminalStrip;
#ifdef BUILD_WITHOUT_KF5
#else
class KAutoSaveFile;
#endif
/** /**
This class represents a QET project. Typically saved as a .qet file, it This class represents a QET project. Typically saved as a .qet file, it
@@ -79,10 +76,7 @@ class QETProject : public QObject
public: public:
QETProject (QObject *parent = nullptr); QETProject (QObject *parent = nullptr);
QETProject (const QString &path, QObject * = nullptr); QETProject (const QString &path, QObject * = nullptr);
#ifdef BUILD_WITHOUT_KF5
#else
QETProject (KAutoSaveFile *backup, QObject *parent=nullptr); QETProject (KAutoSaveFile *backup, QObject *parent=nullptr);
#endif
~QETProject() override; ~QETProject() override;
private: private:
@@ -297,10 +291,7 @@ class QETProject : public QObject
QTimer m_save_backup_timer, QTimer m_save_backup_timer,
m_autosave_timer; m_autosave_timer;
QFuture<bool> m_backup_future; QFuture<bool> m_backup_future;
#ifdef BUILD_WITHOUT_KF5
#else
KAutoSaveFile m_backup_file; KAutoSaveFile m_backup_file;
#endif
QUuid m_uuid = QUuid::createUuid(); QUuid m_uuid = QUuid::createUuid();
projectDataBase m_data_base; projectDataBase m_data_base;
QVector<TerminalStrip *> m_terminal_strip_vector; QVector<TerminalStrip *> m_terminal_strip_vector;
+303
View File
@@ -0,0 +1,303 @@
/*
Copyright 2006-2026 The QElectroTech Team
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "kautosavefile.h"
#include <QCryptographicHash>
#include <QDir>
#include <QFileInfo>
#include <QLockFile>
#include <QRandomGenerator>
#include <QStandardPaths>
#include <QTextStream>
namespace {
const auto autosaveSuffix = QStringLiteral(".qetautosave");
QString staleFilesDir()
{
auto data_dir = QStandardPaths::writableLocation(
QStandardPaths::AppDataLocation);
while (data_dir.endsWith(QLatin1Char('/'))) {
data_dir.chop(1);
}
if (data_dir.isEmpty()) {
return {};
}
return data_dir + QDir::separator() + QStringLiteral("autosave");
}
QString metadataFileName(const QString &autosave_file_name)
{
return autosave_file_name + QStringLiteral(".path");
}
QString lockFileName(const QString &autosave_file_name)
{
return autosave_file_name + QStringLiteral(".lock");
}
QUrl normalizeManagedFile(const QUrl &url)
{
if (url.isEmpty()) {
return {};
}
if (url.isLocalFile() || url.scheme().isEmpty()) {
const auto path = url.isLocalFile() ? url.toLocalFile() : url.path();
QUrl normalized;
normalized.setPath(QDir::cleanPath(QFileInfo(path).absoluteFilePath()));
return normalized;
}
return url;
}
QString storedManagedFile(const QUrl &url)
{
if (url.isLocalFile() || url.scheme().isEmpty()) {
return url.path();
}
return url.toString(QUrl::FullyEncoded);
}
QUrl managedFileFromStorage(const QString &stored_path)
{
if (!stored_path.startsWith(QLatin1Char('/'))) {
return QUrl(stored_path);
}
QUrl url;
url.setPath(QDir::cleanPath(stored_path));
return url;
}
bool writeManagedFileMetadata(const QString &autosave_file_name, const QUrl &managed_file)
{
QFile metadata_file(metadataFileName(autosave_file_name));
if (!metadata_file.open(QIODevice::WriteOnly
| QIODevice::Truncate
| QIODevice::Text)) {
return false;
}
QTextStream stream(&metadata_file);
stream << storedManagedFile(managed_file) << '\n';
stream.flush();
return metadata_file.error() == QFile::NoError;
}
QUrl readManagedFileMetadata(const QString &autosave_file_name)
{
QFile metadata_file(metadataFileName(autosave_file_name));
if (!metadata_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
return {};
}
QTextStream stream(&metadata_file);
const auto stored_path = stream.readLine().trimmed();
if (stored_path.isEmpty()) {
return {};
}
return normalizeManagedFile(managedFileFromStorage(stored_path));
}
QString autosaveFileName(const QUrl &managed_file)
{
const auto stored_path = storedManagedFile(managed_file);
const auto digest = QCryptographicHash::hash(
stored_path.toUtf8(),
QCryptographicHash::Sha256).toHex().left(16);
auto basename = QFileInfo(managed_file.path()).fileName();
if (basename.isEmpty()) {
basename = QStringLiteral("autosave");
}
auto encoded_basename = QString::fromLatin1(
QUrl::toPercentEncoding(basename));
if (encoded_basename.size() > 80) {
encoded_basename.truncate(80);
}
const auto random = QString::number(
QRandomGenerator::global()->generate64(), 16);
return QStringLiteral("%1_%2_%3%4").arg(
encoded_basename,
QString::fromLatin1(digest),
random,
autosaveSuffix);
}
QStringList findAllStaleFiles(const QString &application_name)
{
Q_UNUSED(application_name)
const auto dir_path = staleFilesDir();
if (dir_path.isEmpty()) {
return {};
}
QDir dir(dir_path);
const auto entries = dir.entryList(
{QStringLiteral("*") + autosaveSuffix},
QDir::Files);
QStringList files;
for (const auto &entry : entries) {
files << dir.absoluteFilePath(entry);
}
return files;
}
bool autosaveFileIsRecoverable(const QString &autosave_file_name)
{
QLockFile lock(lockFileName(autosave_file_name));
lock.setStaleLockTime(60 * 1000);
if (!lock.tryLock()) {
return false;
}
lock.unlock();
return true;
}
} // namespace
KAutoSaveFile::KAutoSaveFile(const QUrl &filename, QObject *parent) :
QFile{parent}
{
setManagedFile(filename);
}
KAutoSaveFile::KAutoSaveFile(QObject *parent) :
QFile{parent}
{
}
KAutoSaveFile::~KAutoSaveFile()
{
releaseLock();
}
QUrl KAutoSaveFile::managedFile() const
{
return m_managed_file;
}
void KAutoSaveFile::setManagedFile(const QUrl &filename)
{
releaseLock();
m_managed_file = normalizeManagedFile(filename);
m_managed_file_name_changed = true;
setFileName({});
}
void KAutoSaveFile::releaseLock()
{
if (m_lock && m_lock->isLocked()) {
const auto autosave_file_name = fileName();
m_lock.reset();
if (!autosave_file_name.isEmpty()) {
QFile::remove(metadataFileName(autosave_file_name));
remove();
}
} else {
m_lock.reset();
}
}
bool KAutoSaveFile::open(OpenMode openmode)
{
if (m_managed_file.isEmpty()) {
return false;
}
if (m_managed_file_name_changed) {
const auto stale_dir = staleFilesDir();
if (stale_dir.isEmpty() || !QDir().mkpath(stale_dir)) {
return false;
}
setFileName(QDir(stale_dir).absoluteFilePath(
autosaveFileName(m_managed_file)));
if (!writeManagedFileMetadata(fileName(), m_managed_file)) {
setFileName({});
return false;
}
m_managed_file_name_changed = false;
}
if (!QFile::open(openmode)) {
return false;
}
if (!m_lock) {
m_lock = std::make_unique<QLockFile>(lockFileName(fileName()));
m_lock->setStaleLockTime(60 * 1000);
}
if (m_lock->isLocked() || m_lock->tryLock()) {
return true;
}
close();
return false;
}
QList<KAutoSaveFile *> KAutoSaveFile::staleFiles(
const QUrl &url,
const QString &applicationName)
{
const auto managed_file_filter = normalizeManagedFile(url);
QList<KAutoSaveFile *> stale_files;
for (const auto &file : findAllStaleFiles(applicationName)) {
const auto managed_file = readManagedFileMetadata(file);
if (managed_file.isEmpty()) {
continue;
}
if (!managed_file_filter.isEmpty()
&& managed_file != managed_file_filter) {
continue;
}
if (!autosaveFileIsRecoverable(file)) {
continue;
}
auto *stale_file = new KAutoSaveFile(managed_file);
stale_file->setFileName(file);
stale_file->m_managed_file_name_changed = false;
stale_files << stale_file;
}
return stale_files;
}
QList<KAutoSaveFile *> KAutoSaveFile::allStaleFiles(const QString &applicationName)
{
return staleFiles({}, applicationName);
}
+61
View File
@@ -0,0 +1,61 @@
/*
Copyright 2006-2026 The QElectroTech Team
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef QET_KAUTOSAVEFILE_H
#define QET_KAUTOSAVEFILE_H
#include <QFile>
#include <QList>
#include <QUrl>
#include <memory>
class QLockFile;
/**
Small Qt-only replacement for the KAutoSaveFile API used by QET.
It stores crash-recovery files below the application data autosave folder
and protects each recovery file with QLockFile. The original managed file
path is kept in a sidecar file so allStaleFiles() can present recoverable
projects on the next startup.
*/
class KAutoSaveFile : public QFile
{
public:
explicit KAutoSaveFile(const QUrl &filename, QObject *parent = nullptr);
explicit KAutoSaveFile(QObject *parent = nullptr);
~KAutoSaveFile() override;
QUrl managedFile() const;
void setManagedFile(const QUrl &filename);
virtual void releaseLock();
bool open(OpenMode openmode) override;
static QList<KAutoSaveFile *> staleFiles(
const QUrl &url,
const QString &applicationName = QString());
static QList<KAutoSaveFile *> allStaleFiles(
const QString &applicationName = QString());
private:
QUrl m_managed_file;
std::unique_ptr<QLockFile> m_lock;
bool m_managed_file_name_changed = false;
};
#endif // QET_KAUTOSAVEFILE_H
+70
View File
@@ -0,0 +1,70 @@
/*
Copyright 2006-2026 The QElectroTech Team
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "kcolorbutton.h"
#include <QColorDialog>
#include <QPalette>
namespace {
QColor fallbackColor()
{
return QPalette{}.color(QPalette::Button);
}
}
KColorButton::KColorButton(QWidget *parent) :
QPushButton{parent},
m_color{fallbackColor()}
{
connect(this, &QPushButton::clicked, this, &KColorButton::chooseColor);
updateButton();
}
QColor KColorButton::color() const
{
return m_color;
}
void KColorButton::setColor(const QColor &color)
{
m_color = color.isValid() ? color : fallbackColor();
updateButton();
}
void KColorButton::chooseColor()
{
const auto selected = QColorDialog::getColor(m_color, this);
if (!selected.isValid() || selected == m_color) {
return;
}
m_color = selected;
updateButton();
emit changed(m_color);
}
void KColorButton::updateButton()
{
setText(m_color.name());
auto pal = palette();
pal.setColor(QPalette::Button, m_color);
setAutoFillBackground(true);
setPalette(pal);
update();
}
+48
View File
@@ -0,0 +1,48 @@
/*
Copyright 2006-2026 The QElectroTech Team
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef QET_KCOLORBUTTON_H
#define QET_KCOLORBUTTON_H
#include <QColor>
#include <QPushButton>
class KColorButton : public QPushButton
{
Q_OBJECT
public:
explicit KColorButton(QWidget *parent = nullptr);
QColor color() const;
public slots:
void setColor(const QColor &color);
signals:
void changed(const QColor &color);
private slots:
void chooseColor();
private:
void updateButton();
QColor m_color;
};
#endif // QET_KCOLORBUTTON_H
+49
View File
@@ -0,0 +1,49 @@
/*
Copyright 2006-2026 The QElectroTech Team
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "kcolorcombo.h"
#include <QVariant>
KColorCombo::KColorCombo(QWidget *parent) :
QComboBox{parent}
{
connect(
this,
QOverload<int>::of(&QComboBox::activated),
this,
[this](int index) {
emit activated(itemData(index).value<QColor>());
});
}
void KColorCombo::setColors(const QList<QColor> &colors)
{
clear();
for (const auto &color : colors) {
addItem(color.name(), color);
}
}
QColor KColorCombo::color(int index) const
{
if (index < 0 || index >= count()) {
return {};
}
return itemData(index).value<QColor>();
}
+38
View File
@@ -0,0 +1,38 @@
/*
Copyright 2006-2026 The QElectroTech Team
This file is part of QElectroTech.
QElectroTech 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.
QElectroTech 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 QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef QET_KCOLORCOMBO_H
#define QET_KCOLORCOMBO_H
#include <QColor>
#include <QComboBox>
class KColorCombo : public QComboBox
{
Q_OBJECT
public:
explicit KColorCombo(QWidget *parent = nullptr);
void setColors(const QList<QColor> &colors);
QColor color(int index) const;
signals:
void activated(const QColor &color);
};
#endif // QET_KCOLORCOMBO_H
+14
View File
@@ -83,6 +83,20 @@ add_executable(
${QET_DIR}/sources/borderproperties.h ${QET_DIR}/sources/borderproperties.h
) )
if(NOT BUILD_WITH_KF5)
target_sources(
${PROJECT_NAME}
PRIVATE
src/kautosavefile_test.cpp
${QET_DIR}/sources/ui/nokde/kautosavefile.cpp
)
target_include_directories(
${PROJECT_NAME}
PRIVATE
${QET_DIR}/sources/ui/nokde
)
endif()
target_link_libraries( target_link_libraries(
${PROJECT_NAME} ${PROJECT_NAME}
PUBLIC PUBLIC
+108
View File
@@ -0,0 +1,108 @@
#include "../../../sources/ui/nokde/kautosavefile.h"
#include <catch2/catch.hpp>
#include <QCoreApplication>
#include <QFile>
#include <QFileInfo>
#include <QTemporaryDir>
#include <QUrl>
#include <memory>
#ifdef Q_OS_UNIX
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#endif
TEST_CASE("Qt-only KAutoSaveFile recovers stale files", "[nokde][autosave]")
{
#ifndef Q_OS_UNIX
SUCCEED("crash-style stale lock test is Unix-only");
#else
QTemporaryDir data_home;
REQUIRE(data_home.isValid());
qputenv("XDG_DATA_HOME", QFile::encodeName(data_home.path()));
QCoreApplication::setOrganizationName(QStringLiteral("QElectroTech"));
QCoreApplication::setApplicationName(QStringLiteral("KAutoSaveFileTest"));
const auto managed_path = data_home.filePath(QStringLiteral("project.qet"));
QFile managed_file(managed_path);
REQUIRE(managed_file.open(QIODevice::WriteOnly | QIODevice::Text));
REQUIRE(managed_file.write("<project/>\n") > 0);
managed_file.close();
int ready_pipe[2] = {-1, -1};
REQUIRE(pipe(ready_pipe) == 0);
const QByteArray payload("<project><diagram /></project>\n");
const auto child_pid = fork();
REQUIRE(child_pid >= 0);
if (child_pid == 0) {
close(ready_pipe[0]);
KAutoSaveFile backup(QUrl::fromLocalFile(managed_path));
if (!backup.open(QIODevice::WriteOnly
| QIODevice::Truncate
| QIODevice::Text)) {
_exit(2);
}
if (backup.write(payload) != payload.size()) {
_exit(3);
}
if (!backup.flush()) {
_exit(4);
}
const char ready = '1';
if (write(ready_pipe[1], &ready, 1) != 1) {
_exit(5);
}
close(ready_pipe[1]);
for (;;) {
pause();
}
}
close(ready_pipe[1]);
char ready = 0;
REQUIRE(read(ready_pipe[0], &ready, 1) == 1);
close(ready_pipe[0]);
REQUIRE(ready == '1');
auto active_files = KAutoSaveFile::allStaleFiles();
CHECK(active_files.isEmpty());
for (auto *file : active_files) {
delete file;
}
REQUIRE(kill(child_pid, SIGKILL) == 0);
int status = 0;
REQUIRE(waitpid(child_pid, &status, 0) == child_pid);
REQUIRE(WIFSIGNALED(status));
REQUIRE(WTERMSIG(status) == SIGKILL);
auto stale_files = KAutoSaveFile::allStaleFiles();
REQUIRE(stale_files.size() == 1);
std::unique_ptr<KAutoSaveFile> stale_file(stale_files.takeFirst());
CHECK(stale_file->managedFile().path()
== QFileInfo(managed_path).absoluteFilePath());
REQUIRE(stale_file->open(QIODevice::ReadOnly | QIODevice::Text));
CHECK(stale_file->readAll() == payload);
const auto autosave_file_name = stale_file->fileName();
const auto metadata_file_name = autosave_file_name + QStringLiteral(".path");
const auto lock_file_name = autosave_file_name + QStringLiteral(".lock");
stale_file.reset();
CHECK_FALSE(QFile::exists(autosave_file_name));
CHECK_FALSE(QFile::exists(metadata_file_name));
CHECK_FALSE(QFile::exists(lock_file_name));
#endif
}