Skip to content

Commit

Permalink
App: replace QByteArray with std::vector<uint8_t> in AppUiState class
Browse files Browse the repository at this point in the history
  • Loading branch information
HuguesDelorme committed Dec 11, 2024
1 parent 1a357be commit b48dee6
Show file tree
Hide file tree
Showing 13 changed files with 157 additions and 80 deletions.
14 changes: 4 additions & 10 deletions src/app/app_module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,15 +166,10 @@ Settings::Variant AppModule::toVariant(const Property& prop) const
QByteArray blob;
QDataStream stream(&blob, QIODevice::WriteOnly);
AppModule::writeRecentFiles(stream, filesProp.value());
Variant varBlob(blob.toStdString());
varBlob.setByteArray(true);
return varBlob;
return Variant(QtCoreUtils::toStdByteArray(blob));
}
else if (isType<PropertyAppUiState>(prop)) {
const QByteArray blob = AppUiState::toBlob(constRef<PropertyAppUiState>(prop));
Variant varBlob(blob.toStdString());
varBlob.setByteArray(true);
return varBlob;
return Variant(AppUiState::toBlob(constRef<PropertyAppUiState>(prop)));
}
else {
return PropertyValueConversion::toVariant(prop);
Expand All @@ -184,7 +179,7 @@ Settings::Variant AppModule::toVariant(const Property& prop) const
bool AppModule::fromVariant(Property* prop, const Settings::Variant& variant) const
{
if (isType<PropertyRecentFiles>(prop)) {
const QByteArray blob = QtCoreUtils::QByteArray_frowRawData(variant.toConstRefString());
const QByteArray blob = QtCoreUtils::QByteArray_fromRawData(variant.toConstRefByteArray());
QDataStream stream(blob);
RecentFiles recentFiles;
AppModule::readRecentFiles(stream, &recentFiles);
Expand All @@ -193,8 +188,7 @@ bool AppModule::fromVariant(Property* prop, const Settings::Variant& variant) co
}
else if (isType<PropertyAppUiState>(prop)) {
bool ok = false;
auto blob = QtCoreUtils::QByteArray_frowRawData(variant.toConstRefString());
auto uiState = AppUiState::fromBlob(blob, &ok);
auto uiState = AppUiState::fromBlob(variant.toConstRefByteArray(), &ok);
ptr<PropertyAppUiState>(prop)->setValue(uiState);
return ok;
}
Expand Down
18 changes: 10 additions & 8 deletions src/app/app_ui_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,20 @@ namespace Mayo {

template<> const char PropertyAppUiState::TypeName[] = "Mayo::PropertyAppUiState";

QByteArray AppUiState::toBlob(const AppUiState& state)
std::vector<uint8_t> AppUiState::toBlob(const AppUiState& state)
{
QByteArray blob;
QDataStream stream(&blob, QIODevice::WriteOnly);
stream << QtCoreUtils::QByteArray_frowRawData(std::string_view{PropertyAppUiState::TypeName});
stream << QtCoreUtils::QByteArray_fromRawData(std::string_view{PropertyAppUiState::TypeName});
constexpr uint32_t version = 2;
stream << version;
stream << state.mainWindowGeometry;
stream << QtCoreUtils::QByteArray_fromRawData<uint8_t>(state.mainWindowGeometry);
stream << state.pageDocuments_isLeftSideBarVisible;
stream << state.pageDocuments_widgetLeftSideBarWidthFactor;
return blob;

return QtCoreUtils::toStdByteArray(blob);
}

AppUiState AppUiState::fromBlob(const QByteArray& blob, bool* ok)
AppUiState AppUiState::fromBlob(Span<const uint8_t> blob, bool* ok)
{
auto fnSetOk = [=](bool v) {
if (ok)
Expand All @@ -31,14 +30,17 @@ AppUiState AppUiState::fromBlob(const QByteArray& blob, bool* ok)

fnSetOk(false);
AppUiState state;
QDataStream stream(blob);

QDataStream stream(QtCoreUtils::QByteArray_fromRawData(blob));
QByteArray identifier;
stream >> identifier;
if (identifier == PropertyAppUiState::TypeName) {
uint32_t version = 0;
stream >> version;
if (version >= 1) {
stream >> state.mainWindowGeometry;
QByteArray blobMainWindowGeom;
stream >> blobMainWindowGeom;
state.mainWindowGeometry = QtCoreUtils::toStdByteArray(blobMainWindowGeom);
stream >> state.pageDocuments_isLeftSideBarVisible;
fnSetOk(true);
}
Expand Down
10 changes: 6 additions & 4 deletions src/app/app_ui_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,21 @@
#pragma once

#include "../base/property_builtins.h"
#include <QtCore/QByteArray>
#include "../base/span.h"

#include <vector>

namespace Mayo {

// Stores the UI state of the main application widgets
struct AppUiState {
QByteArray mainWindowGeometry; // Provided by QWidget::saveGeometry()
std::vector<uint8_t> mainWindowGeometry; // Provided by QWidget::saveGeometry()
bool pageDocuments_isLeftSideBarVisible = true;
double pageDocuments_widgetLeftSideBarWidthFactor = 0.25;

// Serialization functions
static QByteArray toBlob(const AppUiState& state);
static AppUiState fromBlob(const QByteArray& blob, bool* ok = nullptr);
static std::vector<uint8_t> toBlob(const AppUiState& state);
static AppUiState fromBlob(Span<const uint8_t> blob, bool* ok = nullptr);
};
using PropertyAppUiState = GenericProperty<AppUiState>;

Expand Down
7 changes: 4 additions & 3 deletions src/app/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "../base/global.h"
#include "../gui/gui_application.h"
#include "../gui/gui_document.h"
#include "../qtcommon/qtcore_utils.h"
#include "app_context.h"
#include "app_module.h"
#include "commands_file.h"
Expand Down Expand Up @@ -74,8 +75,8 @@ MainWindow::~MainWindow()
void MainWindow::showEvent(QShowEvent* event)
{
const auto& uiState = AppModule::get()->properties()->appUiState.value();
if (!uiState.mainWindowGeometry.isEmpty())
this->restoreGeometry(uiState.mainWindowGeometry);
if (!uiState.mainWindowGeometry.empty())
this->restoreGeometry(QtCoreUtils::QByteArray_fromRawData<uint8_t>(uiState.mainWindowGeometry));

WidgetMainControl* pageDocs = this->widgetPageDocuments();
if (pageDocs) {
Expand All @@ -97,7 +98,7 @@ void MainWindow::showEvent(QShowEvent* event)
void MainWindow::closeEvent(QCloseEvent* event)
{
AppUiState uiState = AppModule::get()->properties()->appUiState;
uiState.mainWindowGeometry = this->saveGeometry();
uiState.mainWindowGeometry = QtCoreUtils::toStdByteArray(this->saveGeometry());
WidgetMainControl* pageDocs = this->widgetPageDocuments();
if (pageDocs) {
uiState.pageDocuments_isLeftSideBarVisible = pageDocs->widgetLeftSideBar()->isVisible();
Expand Down
8 changes: 4 additions & 4 deletions src/app/widget_model_tree_builder_xde.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ class WidgetModelTreeBuilder_Xde::Module : public PropertyGroup {
// UTF8 rightwards arrow : \xe2\x86\x92
static const char templateBoth[] = "%instance \xe2\x86\x92 %product";
switch (format) {
case NameFormat::Instance: return QtCoreUtils::QByteArray_frowRawData(templateInstance);
case NameFormat::Product: return QtCoreUtils::QByteArray_frowRawData(templateProduct);
case NameFormat::Both: return QtCoreUtils::QByteArray_frowRawData(templateBoth);
case NameFormat::Instance: return QtCoreUtils::QByteArray_fromRawData(templateInstance);
case NameFormat::Product: return QtCoreUtils::QByteArray_fromRawData(templateProduct);
case NameFormat::Both: return QtCoreUtils::QByteArray_fromRawData(templateBoth);
}
return QByteArray();
}
Expand Down Expand Up @@ -214,7 +214,7 @@ QTreeWidgetItem* WidgetModelTreeBuilder_Xde::buildXdeTree(

QByteArray WidgetModelTreeBuilder_Xde::instanceNameFormat() const
{
return QtCoreUtils::QByteArray_frowRawData(Module::get()->instanceNameFormat.valueName());
return QtCoreUtils::QByteArray_fromRawData(Module::get()->instanceNameFormat.valueName());
}

void WidgetModelTreeBuilder_Xde::setInstanceNameFormat(const QByteArray& format)
Expand Down
38 changes: 32 additions & 6 deletions src/base/property_value_conversion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "unit_system.h"

#include <fmt/format.h>
#include <algorithm>
#if __cpp_lib_to_chars
# include <charconv>
#endif
Expand Down Expand Up @@ -346,6 +347,8 @@ std::string PropertyValueConversion::Variant::toString(bool* ok) const
return std::to_string(std::get<int>(*this));
else if (std::holds_alternative<double>(*this))
return std::to_string(std::get<double>(*this));
else if (std::holds_alternative<std::vector<uint8_t>>(*this))
return std::to_string(std::get<double>(*this));
else
return this->toConstRefString();
}
Expand All @@ -366,19 +369,42 @@ const std::string& PropertyValueConversion::Variant::toConstRefString(bool* ok)
return CppUtils::nullString();
}

bool PropertyValueConversion::Variant::isConvertibleToConstRefString() const
std::vector<uint8_t> PropertyValueConversion::Variant::toByteArray(bool* ok) const
{
return std::holds_alternative<bool>(*this) || std::holds_alternative<std::string>(*this);
assignBoolPtr(ok, true);
if (std::holds_alternative<std::string>(*this)) {
const std::string& str = std::get<std::string>(*this);
std::vector<uint8_t> bytes;
bytes.resize(str.size());
std::copy(str.cbegin(), str.cend(), bytes.begin());
return bytes;
}
else if (std::holds_alternative<std::vector<uint8_t>>(*this)) {
return std::get<std::vector<uint8_t>>(*this);
}

assignBoolPtr(ok, false);
return {};
}

bool PropertyValueConversion::Variant::isByteArray() const
Span<const uint8_t> PropertyValueConversion::Variant::toConstRefByteArray(bool* ok) const
{
return m_isByteArray && std::holds_alternative<std::string>(*this);
assignBoolPtr(ok, true);
if (std::holds_alternative<std::vector<uint8_t>>(*this))
return std::get<std::vector<uint8_t>>(*this);

assignBoolPtr(ok, false);
return {};
}

bool PropertyValueConversion::Variant::isConvertibleToConstRefString() const
{
return std::holds_alternative<bool>(*this) || std::holds_alternative<std::string>(*this);
}

void PropertyValueConversion::Variant::setByteArray(bool on)
bool PropertyValueConversion::Variant::isByteArray() const
{
m_isByteArray = on;
return std::holds_alternative<std::vector<uint8_t>>(*this);
}

} // namespace Mayo
19 changes: 12 additions & 7 deletions src/base/property_value_conversion.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#pragma once

#include "property.h"
#include "span.h"

#include <string>
#include <variant>
#include <vector>
Expand All @@ -16,32 +18,35 @@ namespace Mayo {
// Mechanism to convert value of a Property object to/from a basic variant type
class PropertyValueConversion {
public:
using BaseVariantType = std::variant<
std::monostate, bool, int, double, std::string, std::vector<uint8_t>
>;
// Variant type to be used when (de)serializing values
class Variant : public std::variant<std::monostate, bool, int, double, std::string> {
class Variant : public BaseVariantType {
public:
using BaseType = std::variant<std::monostate, bool, int, double, std::string>;
using BaseType = BaseVariantType;
Variant() = default;
Variant(bool v) : BaseType(v) {}
Variant(int v) : BaseType(v) {}
Variant(float v) : Variant(static_cast<double>(v)) {}
Variant(double v) : BaseType(v) {}
Variant(const char* str) : BaseType(std::string(str)) {}
Variant(const std::string& str) : BaseType(str) {}
Variant(Span<const uint8_t> bytes) : BaseType(std::vector<uint8_t>(bytes.begin(), bytes.end())) {}

bool isValid() const;
bool toBool(bool* ok = nullptr) const;
int toInt(bool* ok = nullptr) const;
double toDouble(bool* ok = nullptr) const;

std::string toString(bool* ok = nullptr) const;
const std::string& toConstRefString(bool* ok = nullptr) const;

bool isConvertibleToConstRefString() const;
std::vector<uint8_t> toByteArray(bool* ok = nullptr) const;
Span<const uint8_t> toConstRefByteArray(bool* ok = nullptr) const;

bool isConvertibleToConstRefString() const;
bool isByteArray() const;
void setByteArray(bool on);

private:
bool m_isByteArray = false;
};

int doubleToStringPrecision() const { return m_doubleToStringPrecision; }
Expand Down
11 changes: 5 additions & 6 deletions src/qtbackend/qsettings_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Settings::Variant QSettingsStorage::value(std::string_view key) const
const QVariant value = m_storage.value(to_QString(key));
switch (value.type()) {
case QVariant::ByteArray:
return value.toByteArray().toStdString();
return QtCoreUtils::toStdByteArray(value.toByteArray());
case QVariant::String: {
const QString strval = value.toString();
if (strval == "true")
Expand Down Expand Up @@ -80,11 +80,10 @@ void QSettingsStorage::setValue(std::string_view key, const Settings::Variant& v
qvalue = std::get<double>(value);
}
else if (std::holds_alternative<std::string>(value)) {
const std::string& str = value.toConstRefString();
if (value.isByteArray())
qvalue = QByteArray::fromStdString(str); // Don't use QtCoreUtils::QByteArray_frowRawData(str)
else
qvalue = to_QString(str);
qvalue = to_QString(value.toConstRefString());
}
else if (std::holds_alternative<std::vector<uint8_t>>(value)) {
qvalue = QtCoreUtils::toQByteArray(value.toConstRefByteArray());
}

if (!qvalue.isNull())
Expand Down
43 changes: 43 additions & 0 deletions src/qtcommon/qtcore_utils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/****************************************************************************
** Copyright (c) 2024, Fougue Ltd. <https://www.fougue.pro>
** All rights reserved.
** See license at https://github.com/fougue/mayo/blob/master/LICENSE.txt
****************************************************************************/

#include "qtcore_utils.h"

#include <algorithm>

namespace Mayo::QtCoreUtils {

std::vector<uint8_t> toStdByteArray(const QByteArray& bytes)
{
std::vector<uint8_t> stdBytes;
stdBytes.resize(bytes.size());
std::copy(bytes.cbegin(), bytes.cend(), stdBytes.begin());
return stdBytes;
}

Qt::CheckState toQtCheckState(Mayo::CheckState state)
{
switch (state) {
case CheckState::Off: return Qt::Unchecked;
case CheckState::Partially: return Qt::PartiallyChecked;
case CheckState::On: return Qt::Checked;
}

return Qt::Unchecked;
}

Mayo::CheckState toCheckState(Qt::CheckState state)
{
switch (state) {
case Qt::Unchecked: return CheckState::Off;
case Qt::PartiallyChecked: return CheckState::Partially;
case Qt::Checked: return CheckState::On;
}

return CheckState::Off;
}

} // namespace Mayo::QtCoreUtils
Loading

0 comments on commit b48dee6

Please sign in to comment.