File indexing completed on 2024-05-12 03:47:46

0001 /*
0002     File                 : macros.h
0003     Project              : LabPlot
0004     Description          : Various preprocessor macros
0005     --------------------------------------------------------------------
0006     SPDX-FileCopyrightText: 2008 Tilman Benkert <thzs@gmx.net>
0007     SPDX-FileCopyrightText: 2013-2015 Alexander Semke <alexander.semke@web.de>
0008     SPDX-FileCopyrightText: 2016-2021 Stefan Gerlach <stefan.gerlach@uni.kn>
0009     SPDX-License-Identifier: GPL-2.0-or-later
0010 */
0011 
0012 #ifndef MACROS_H
0013 #define MACROS_H
0014 
0015 #include <QApplication>
0016 #include <QMetaEnum>
0017 
0018 #include "macrosWarningStyle.h"
0019 
0020 // C++ style warning (works on Windows)
0021 #include <iomanip>
0022 #include <iostream>
0023 #define WARN(x)                                                                                                                                                \
0024     std::cout << std::dec << std::setprecision(std::numeric_limits<double>::digits10 + 1) << std::boolalpha << x                                               \
0025               << std::resetiosflags(std::ios_base::boolalpha) << std::setprecision(-1) << std::endl;
0026 
0027 #ifndef NDEBUG
0028 #include <QDebug>
0029 #define QDEBUG(x) qDebug() << x;
0030 #define DEBUG(x) WARN(x)
0031 #else
0032 #define QDEBUG(x)                                                                                                                                              \
0033     { }
0034 #define DEBUG(x)                                                                                                                                               \
0035     { }
0036 #endif
0037 
0038 #define DEBUG_TEXTLABEL_BOUNDING_RECT 0
0039 #define DEBUG_TEXTLABEL_GLUEPOINTS 0
0040 #define DEBUG_AXIS_BOUNDING_RECT 0
0041 
0042 struct Lock {
0043     inline explicit Lock(bool& variable)
0044         : variable(variable) {
0045         // Make sure it is not already locked
0046         // somewhere else
0047         assert(!variable);
0048         this->variable = true;
0049     }
0050 
0051     inline ~Lock() {
0052         variable = false;
0053     }
0054 
0055 private:
0056     bool& variable;
0057 };
0058 
0059 /*!
0060  * Used for example for connections with NumberSpinbox because those are using
0061  * a feedback and so breaking the connection dock -> element -> dock is not desired
0062  */
0063 #define CONDITIONAL_RETURN_NO_LOCK                                                                                                                             \
0064     if (m_initializing)                                                                                                                                        \
0065         return;
0066 
0067 /*!
0068  * Lock mechanism used in docks to prevent loops (dock -> element -> dock)
0069  * dock (locking) -> element: No feedback to the dock
0070  */
0071 #define CONDITIONAL_LOCK_RETURN                                                                                                                                \
0072     CONDITIONAL_RETURN_NO_LOCK                                                                                                                                 \
0073     const Lock lock(m_initializing);
0074 
0075 #define WAIT_CURSOR QApplication::setOverrideCursor(QCursor(Qt::WaitCursor))
0076 #define RESET_CURSOR QApplication::restoreOverrideCursor()
0077 
0078 #ifdef HAVE_WINDOWS
0079 #define STDSTRING(qstr) qstr.toUtf8().constData()
0080 #else
0081 #define STDSTRING(qstr) qstr.toStdString()
0082 #endif
0083 #define UTF8_QSTRING(str) QString::fromUtf8(str)
0084 
0085 #define CHECK(expr)                                                                                                                                            \
0086     if (!(expr)) {                                                                                                                                             \
0087         DEBUG(Q_FUNC_INFO << ", FAILING " #expr);                                                                                                              \
0088         return false;                                                                                                                                          \
0089     }
0090 // check if var is in [min, max)
0091 #define INRANGE(var, min, max) (var >= min && var < max)
0092 
0093 // access enums in Q_OBJECT/Q_GADGET classes
0094 #define ENUM_TO_STRING(class, enum, index)                                                                                                                     \
0095     (class ::staticMetaObject.enumerator(class ::staticMetaObject.indexOfEnumerator(#enum)).valueToKey(static_cast<int>(index)))
0096 #define ENUM_COUNT(class, enum) (class ::staticMetaObject.enumerator(class ::staticMetaObject.indexOfEnumerator(#enum)).keyCount())
0097 
0098 //////////////////////// LineEdit Access ///////////////////////////////
0099 #define SET_INT_FROM_LE(var, le)                                                                                                                               \
0100     {                                                                                                                                                          \
0101         bool ok;                                                                                                                                               \
0102         const int tmp = QLocale().toInt((le)->text(), &ok);                                                                                                    \
0103         if (ok)                                                                                                                                                \
0104             var = tmp;                                                                                                                                         \
0105     }
0106 
0107 #define SET_DOUBLE_FROM_LE(var, le)                                                                                                                            \
0108     {                                                                                                                                                          \
0109         bool ok;                                                                                                                                               \
0110         const double tmp = QLocale().toDouble((le)->text(), &ok);                                                                                              \
0111         if (ok)                                                                                                                                                \
0112             var = tmp;                                                                                                                                         \
0113     }
0114 
0115 // including enable recalculate
0116 #define SET_DOUBLE_FROM_LE_REC(var, le)                                                                                                                        \
0117     {                                                                                                                                                          \
0118         QString str = (le)->text().trimmed();                                                                                                                  \
0119         if (!str.isEmpty()) {                                                                                                                                  \
0120             bool ok;                                                                                                                                           \
0121             const double tmp = QLocale().toDouble(str, &ok);                                                                                                   \
0122             if (ok) {                                                                                                                                          \
0123                 var = tmp;                                                                                                                                     \
0124                 enableRecalculate();                                                                                                                           \
0125             }                                                                                                                                                  \
0126         }                                                                                                                                                      \
0127     }
0128 
0129 //////////////////////// Accessor ///////////////////////////////
0130 
0131 // type: BASIC (by value), CLASS (by reference)
0132 // D: private var, SHARED: Q_D
0133 // DECL and IMPL
0134 #define BASIC_ACCESSOR(type, var, method, Method)                                                                                                              \
0135     type method() const {                                                                                                                                      \
0136         return var;                                                                                                                                            \
0137     };                                                                                                                                                         \
0138     void set##Method(const type value) {                                                                                                                       \
0139         var = value;                                                                                                                                           \
0140     }
0141 #define CLASS_ACCESSOR(type, var, method, Method)                                                                                                              \
0142     type method() const {                                                                                                                                      \
0143         return var;                                                                                                                                            \
0144     };                                                                                                                                                         \
0145     void set##Method(const type& value) {                                                                                                                      \
0146         var = value;                                                                                                                                           \
0147     }
0148 
0149 #define BASIC_D_ACCESSOR_DECL(type, method, Method)                                                                                                            \
0150     type method() const;                                                                                                                                       \
0151     void set##Method(const type value);
0152 #define CLASS_D_ACCESSOR_DECL(type, method, Method)                                                                                                            \
0153     type method() const;                                                                                                                                       \
0154     void set##Method(const type& value);
0155 
0156 #define BASIC_D_INDEX_ACCESSOR_DECL(type, method, Method)                                                                                                      \
0157     type method(int index) const;                                                                                                                              \
0158     void set##Method(int index, type value);
0159 
0160 // replaces CLASS_D_READER_IMPL
0161 #define BASIC_D_READER_IMPL(classname, type, method, var)                                                                                                      \
0162     type classname::method() const {                                                                                                                           \
0163         Q_D(const classname);                                                                                                                                  \
0164         return d->var;                                                                                                                                         \
0165     }
0166 // replaces CLASS_SHARED_D_READER_IMPL
0167 #define BASIC_SHARED_D_READER_IMPL(classname, type, method, var)                                                                                               \
0168     type classname::method() const {                                                                                                                           \
0169         Q_D(const classname);                                                                                                                                  \
0170         return d->var;                                                                                                                                         \
0171     }
0172 
0173 #define BASIC_D_ACCESSOR_IMPL(classname, type, method, Method, var)                                                                                            \
0174     void classname::set##Method(const type value) {                                                                                                            \
0175         Q_D(classname);                                                                                                                                        \
0176         d->var = value;                                                                                                                                        \
0177     }                                                                                                                                                          \
0178     BASIC_D_READER_IMPL(classname, type, method, var)
0179 
0180 #define CLASS_D_ACCESSOR_IMPL(classname, type, method, Method, var)                                                                                            \
0181     void classname::set##Method(const type& value) {                                                                                                           \
0182         Q_D(classname);                                                                                                                                        \
0183         d->var = value;                                                                                                                                        \
0184     }                                                                                                                                                          \
0185     BASIC_D_READER_IMPL(classname, type, method, var)
0186 
0187 #define BASIC_SHARED_D_ACCESSOR_IMPL(classname, type, method, Method, var)                                                                                     \
0188     void classname::set##Method(const type value) {                                                                                                            \
0189         Q_D(classname);                                                                                                                                        \
0190         d->var = value;                                                                                                                                        \
0191     }                                                                                                                                                          \
0192     BASIC_SHARED_D_READER_IMPL(classname, type, method, var)
0193 
0194 #define CLASS_SHARED_D_ACCESSOR_IMPL(classname, type, method, Method, var)                                                                                     \
0195     void classname::set##Method(const type& value) {                                                                                                           \
0196         Q_D(classname);                                                                                                                                        \
0197         d->var = value;                                                                                                                                        \
0198     }                                                                                                                                                          \
0199     BASIC_SHARED_D_READER_IMPL(classname, type, method, var)
0200 
0201 #define POINTER_D_ACCESSOR_DECL(type, method, Method)                                                                                                          \
0202     type* method() const;                                                                                                                                      \
0203     void set##Method(type* ptr);
0204 
0205 #define FLAG_D_ACCESSOR_DECL(Method)                                                                                                                           \
0206     bool is##Method() const;                                                                                                                                   \
0207     bool has##Method() const;                                                                                                                                  \
0208     void set##Method(const bool value = true);                                                                                                                 \
0209     void enable##Method(const bool value = true);
0210 
0211 #define FLAG_D_ACCESSOR_IMPL(classname, Method, var)                                                                                                           \
0212     void classname::set##Method(const bool value) {                                                                                                            \
0213         d->var = value;                                                                                                                                        \
0214     }                                                                                                                                                          \
0215     void classname::enable##Method(const bool value) {                                                                                                         \
0216         d->var = value;                                                                                                                                        \
0217     }                                                                                                                                                          \
0218     bool classname::is##Method() const {                                                                                                                       \
0219         return d->var;                                                                                                                                         \
0220     }                                                                                                                                                          \
0221     bool classname::has##Method() const {                                                                                                                      \
0222         return d->var;                                                                                                                                         \
0223     }
0224 
0225 //////////////////////// Standard Setter /////////////////////
0226 
0227 #define STD_SETTER_CMD_IMPL(class_name, cmd_name, value_type, field_name)                                                                                      \
0228     class class_name##cmd_name##Cmd : public StandardSetterCmd<class_name::Private, value_type> {                                                              \
0229     public:                                                                                                                                                    \
0230         class_name##cmd_name##Cmd(class_name::Private* target, value_type newValue, const KLocalizedString& description)                                       \
0231             : StandardSetterCmd<class_name::Private, value_type>(target, &class_name::Private::field_name, newValue, description) {                            \
0232         }                                                                                                                                                      \
0233     };
0234 
0235 // setter class with finalize()
0236 #define STD_SETTER_CMD_IMPL_F(class_name, cmd_name, value_type, field_name, finalize_method)                                                                   \
0237     class class_name##cmd_name##Cmd : public StandardSetterCmd<class_name::Private, value_type> {                                                              \
0238     public:                                                                                                                                                    \
0239         class_name##cmd_name##Cmd(class_name::Private* target, value_type newValue, const KLocalizedString& description)                                       \
0240             : StandardSetterCmd<class_name::Private, value_type>(target, &class_name::Private::field_name, newValue, description) {                            \
0241         }                                                                                                                                                      \
0242         virtual void finalize() override {                                                                                                                     \
0243             m_target->finalize_method();                                                                                                                       \
0244         }                                                                                                                                                      \
0245     };
0246 
0247 // setter class with signal emitting.
0248 #define STD_SETTER_CMD_IMPL_S(class_name, cmd_name, value_type, field_name)                                                                                    \
0249     class class_name##cmd_name##Cmd : public StandardSetterCmd<class_name::Private, value_type> {                                                              \
0250     public:                                                                                                                                                    \
0251         class_name##cmd_name##Cmd(class_name::Private* target, value_type newValue, const KLocalizedString& description, QUndoCommand* parent = nullptr)       \
0252             : StandardSetterCmd<class_name::Private, value_type>(target, &class_name::Private::field_name, newValue, description, parent) {                    \
0253         }                                                                                                                                                      \
0254         virtual void finalize() override {                                                                                                                     \
0255             Q_EMIT m_target->q->field_name##Changed(m_target->*m_field);                                                                                       \
0256         }                                                                                                                                                      \
0257     };
0258 
0259 // setter class with finalize() and signal emitting.
0260 #define STD_SETTER_CMD_IMPL_F_S(class_name, cmd_name, value_type, field_name, finalize_method)                                                                 \
0261     class class_name##cmd_name##Cmd : public StandardSetterCmd<class_name::Private, value_type> {                                                              \
0262     public:                                                                                                                                                    \
0263         class_name##cmd_name##Cmd(class_name::Private* target, value_type newValue, const KLocalizedString& description, QUndoCommand* parent = nullptr)       \
0264             : StandardSetterCmd<class_name::Private, value_type>(target, &class_name::Private::field_name, newValue, description, parent) {                    \
0265         }                                                                                                                                                      \
0266         virtual void finalize() override {                                                                                                                     \
0267             m_target->finalize_method();                                                                                                                       \
0268             Q_EMIT m_target->q->field_name##Changed(m_target->*m_field);                                                                                       \
0269         }                                                                                                                                                      \
0270     };
0271 
0272 // setter class with finalize() and signal emitting, one field_name signal and one custom signal.
0273 #define STD_SETTER_CMD_IMPL_F_S_SC(class_name, cmd_name, value_type, field_name, finalize_method, custom_signal)                                               \
0274     class class_name##cmd_name##Cmd : public StandardSetterCmd<class_name::Private, value_type> {                                                              \
0275     public:                                                                                                                                                    \
0276         class_name##cmd_name##Cmd(class_name::Private* target, value_type newValue, const KLocalizedString& description, QUndoCommand* parent = nullptr)       \
0277             : StandardSetterCmd<class_name::Private, value_type>(target, &class_name::Private::field_name, newValue, description, parent) {                    \
0278         }                                                                                                                                                      \
0279         virtual void finalize() override {                                                                                                                     \
0280             m_target->finalize_method();                                                                                                                       \
0281             Q_EMIT m_target->q->field_name##Changed(m_target->*m_field);                                                                                       \
0282             Q_EMIT m_target->q->custom_signal();                                                                                                               \
0283         }                                                                                                                                                      \
0284     };
0285 
0286 // setter class with finalize() and signal emitting for changing several properties in one single step (embedded in beginMacro/endMacro)
0287 #define STD_SETTER_CMD_IMPL_M_F_S(class_name, cmd_name, value_type, field_name, finalize_method)                                                               \
0288     class class_name##cmd_name##Cmd : public StandardMacroSetterCmd<class_name::Private, value_type> {                                                         \
0289     public:                                                                                                                                                    \
0290         class_name##cmd_name##Cmd(class_name::Private* target, value_type newValue, const KLocalizedString& description)                                       \
0291             : StandardMacroSetterCmd<class_name::Private, value_type>(target, &class_name::Private::field_name, newValue, description) {                       \
0292         }                                                                                                                                                      \
0293         virtual void finalize() override {                                                                                                                     \
0294             m_target->finalize_method();                                                                                                                       \
0295             Q_EMIT m_target->q->field_name##Changed(m_target->*m_field);                                                                                       \
0296         }                                                                                                                                                      \
0297         virtual void finalizeUndo() override {                                                                                                                 \
0298             Q_EMIT m_target->q->field_name##Changed(m_target->*m_field);                                                                                       \
0299         }                                                                                                                                                      \
0300     };
0301 
0302 #define STD_SETTER_CMD_IMPL_I(class_name, cmd_name, value_type, field_name, init_method)                                                                       \
0303     class class_name##cmd_name##Cmd : public StandardSetterCmd<class_name::Private, value_type> {                                                              \
0304     public:                                                                                                                                                    \
0305         class_name##cmd_name##Cmd(class_name::Private* target, value_type newValue, const KLocalizedString& description)                                       \
0306             : StandardSetterCmd<class_name::Private, value_type>(target, &class_name::Private::field_name, newValue, description) {                            \
0307         }                                                                                                                                                      \
0308         virtual void initialize() {                                                                                                                            \
0309             m_target->init_method();                                                                                                                           \
0310         }                                                                                                                                                      \
0311     };
0312 
0313 #define STD_SETTER_CMD_IMPL_IF(class_name, cmd_name, value_type, field_name, init_method, finalize_method)                                                     \
0314     class class_name##cmd_name##Cmd : public StandardSetterCmd<class_name::Private, value_type> {                                                              \
0315     public:                                                                                                                                                    \
0316         class_name##cmd_name##Cmd(class_name::Private* target, value_type newValue, const KLocalizedString& description)                                       \
0317             : StandardSetterCmd<class_name::Private, value_type>(target, &class_name::Private::field_name, newValue, description) {                            \
0318         }                                                                                                                                                      \
0319         virtual void initialize() {                                                                                                                            \
0320             m_target->init_method();                                                                                                                           \
0321         }                                                                                                                                                      \
0322         virtual void finalize() {                                                                                                                              \
0323             m_target->finalize_method();                                                                                                                       \
0324         }                                                                                                                                                      \
0325     };
0326 
0327 #define STD_SWAP_METHOD_SETTER_CMD_IMPL(class_name, cmd_name, value_type, method_name)                                                                         \
0328     class class_name##cmd_name##Cmd : public StandardSwapMethodSetterCmd<class_name::Private, value_type> {                                                    \
0329     public:                                                                                                                                                    \
0330         class_name##cmd_name##Cmd(class_name::Private* target, value_type newValue, const KLocalizedString& description)                                       \
0331             : StandardSwapMethodSetterCmd<class_name::Private, value_type>(target, &class_name::Private::method_name, newValue, description) {                 \
0332         }                                                                                                                                                      \
0333     };
0334 
0335 #define STD_SWAP_METHOD_SETTER_CMD_IMPL_F(class_name, cmd_name, value_type, method_name, finalize_method)                                                      \
0336     class class_name##cmd_name##Cmd : public StandardSwapMethodSetterCmd<class_name::Private, value_type> {                                                    \
0337     public:                                                                                                                                                    \
0338         class_name##cmd_name##Cmd(class_name::Private* target, value_type newValue, const KLocalizedString& description)                                       \
0339             : StandardSwapMethodSetterCmd<class_name::Private, value_type>(target, &class_name::Private::method_name, newValue, description) {                 \
0340         }                                                                                                                                                      \
0341         virtual void finalize() override {                                                                                                                     \
0342             m_target->finalize_method();                                                                                                                       \
0343         }                                                                                                                                                      \
0344     };
0345 
0346 #define STD_SWAP_METHOD_SETTER_CMD_IMPL_I(class_name, cmd_name, value_type, method_name, init_method)                                                          \
0347     class class_name##cmd_name##Cmd : public StandardSwapMethodSetterCmd<class_name::Private, value_type> {                                                    \
0348     public:                                                                                                                                                    \
0349         class_name##cmd_name##Cmd(class_name::Private* target, value_type newValue, const KLocalizedString& description)                                       \
0350             : StandardSwapMethodSetterCmd<class_name::Private, value_type>(target, &class_name::Private::method_name, newValue, description) {                 \
0351         }                                                                                                                                                      \
0352         virtual void initialize() {                                                                                                                            \
0353             m_target->init_method();                                                                                                                           \
0354         }                                                                                                                                                      \
0355     };
0356 
0357 #define STD_SWAP_METHOD_SETTER_CMD_IMPL_IF(class_name, cmd_name, value_type, method_name, init_method, finalize_method)                                        \
0358     class class_name##cmd_name##Cmd : public StandardSwapMethodSetterCmd<class_name::Private, value_type> {                                                    \
0359     public:                                                                                                                                                    \
0360         class_name##cmd_name##Cmd(class_name::Private* target, value_type newValue, const KLocalizedString& description)                                       \
0361             : StandardSwapMethodSetterCmd<class_name::Private, value_type>(target, &class_name::Private::method_name, newValue, description) {                 \
0362         }                                                                                                                                                      \
0363         virtual void initialize() {                                                                                                                            \
0364             m_target->init_method();                                                                                                                           \
0365         }                                                                                                                                                      \
0366         virtual void finalize() {                                                                                                                              \
0367             m_target->finalize_method();                                                                                                                       \
0368         }                                                                                                                                                      \
0369     };
0370 
0371 // setter class for QGraphicsitem settings because
0372 // there field_name() and setter_method() is used to get and set values
0373 // with finalize() function and signal emitting.
0374 #define GRAPHICSITEM_SETTER_CMD_IMPL_F_S(class_name, cmd_name, value_type, field_name, setter_method, finalize_method)                                         \
0375     class class_name##cmd_name##Cmd : public QUndoCommand {                                                                                                    \
0376     public:                                                                                                                                                    \
0377         class_name##cmd_name##Cmd(class_name::Private* target, value_type newValue, const KLocalizedString& description, QUndoCommand* parent = nullptr)       \
0378             : QUndoCommand(parent)                                                                                                                             \
0379             , m_target(target)                                                                                                                                 \
0380             , m_otherValue(newValue) {                                                                                                                         \
0381             setText(description.subs(m_target->name()).toString());                                                                                            \
0382         }                                                                                                                                                      \
0383         void redo() override {                                                                                                                                 \
0384             value_type tmp = m_target->field_name();                                                                                                           \
0385             m_target->setter_method(m_otherValue);                                                                                                             \
0386             m_otherValue = tmp;                                                                                                                                \
0387             QUndoCommand::redo(); /* redo all childs */                                                                                                        \
0388             finalize();                                                                                                                                        \
0389         }                                                                                                                                                      \
0390                                                                                                                                                                \
0391         void undo() override {                                                                                                                                 \
0392             redo();                                                                                                                                            \
0393         }                                                                                                                                                      \
0394         void finalize() {                                                                                                                                      \
0395             m_target->finalize_method();                                                                                                                       \
0396             Q_EMIT m_target->q->field_name##Changed(m_target->field_name());                                                                                   \
0397         }                                                                                                                                                      \
0398                                                                                                                                                                \
0399     private:                                                                                                                                                   \
0400         class_name::Private* m_target;                                                                                                                         \
0401         value_type m_otherValue;                                                                                                                               \
0402     };
0403 
0404 //////////////////////// XML - serialization/deserialization /////
0405 // TODO: do we really need all these tabs?
0406 // TODO: why "do {...} while(0)"?
0407 
0408 // QColor
0409 #define WRITE_QCOLOR(color)                                                                                                                                    \
0410     {                                                                                                                                                          \
0411         writer->writeAttribute(QStringLiteral("color_r"), QString::number(color.red()));                                                                       \
0412         writer->writeAttribute(QStringLiteral("color_g"), QString::number(color.green()));                                                                     \
0413         writer->writeAttribute(QStringLiteral("color_b"), QString::number(color.blue()));                                                                      \
0414     }
0415 
0416 #define WRITE_QCOLOR2(color, label)                                                                                                                            \
0417     {                                                                                                                                                          \
0418         writer->writeAttribute(QStringLiteral(label "_r"), QString::number(color.red()));                                                                      \
0419         writer->writeAttribute(QStringLiteral(label "_g"), QString::number(color.green()));                                                                    \
0420         writer->writeAttribute(QStringLiteral(label "_b"), QString::number(color.blue()));                                                                     \
0421     }
0422 
0423 #define READ_QCOLOR(color)                                                                                                                                     \
0424     {                                                                                                                                                          \
0425         str = attribs.value(QStringLiteral("color_r")).toString();                                                                                             \
0426         if (str.isEmpty())                                                                                                                                     \
0427             reader->raiseMissingAttributeWarning(QStringLiteral("color_r"));                                                                                   \
0428         else                                                                                                                                                   \
0429             color.setRed(str.toInt());                                                                                                                         \
0430                                                                                                                                                                \
0431         str = attribs.value(QStringLiteral("color_g")).toString();                                                                                             \
0432         if (str.isEmpty())                                                                                                                                     \
0433             reader->raiseMissingAttributeWarning(QStringLiteral("color_g"));                                                                                   \
0434         else                                                                                                                                                   \
0435             color.setGreen(str.toInt());                                                                                                                       \
0436                                                                                                                                                                \
0437         str = attribs.value(QStringLiteral("color_b")).toString();                                                                                             \
0438         if (str.isEmpty())                                                                                                                                     \
0439             reader->raiseMissingAttributeWarning(QStringLiteral("color_b"));                                                                                   \
0440         else                                                                                                                                                   \
0441             color.setBlue(str.toInt());                                                                                                                        \
0442     }
0443 
0444 #define READ_QCOLOR2(color, label)                                                                                                                             \
0445     {                                                                                                                                                          \
0446         str = attribs.value(QStringLiteral(label "_r")).toString();                                                                                            \
0447         if (str.isEmpty())                                                                                                                                     \
0448             reader->raiseMissingAttributeWarning(QStringLiteral(label "_r"));                                                                                  \
0449         else                                                                                                                                                   \
0450             color.setRed(str.toInt());                                                                                                                         \
0451                                                                                                                                                                \
0452         str = attribs.value(QStringLiteral(label "_g")).toString();                                                                                            \
0453         if (str.isEmpty())                                                                                                                                     \
0454             reader->raiseMissingAttributeWarning(QStringLiteral(label "_g"));                                                                                  \
0455         else                                                                                                                                                   \
0456             color.setGreen(str.toInt());                                                                                                                       \
0457                                                                                                                                                                \
0458         str = attribs.value(QStringLiteral(label "_b")).toString();                                                                                            \
0459         if (str.isEmpty())                                                                                                                                     \
0460             reader->raiseMissingAttributeWarning(QStringLiteral(label "_b"));                                                                                  \
0461         else                                                                                                                                                   \
0462             color.setBlue(str.toInt());                                                                                                                        \
0463     }
0464 // QPen
0465 #define WRITE_QPEN(pen)                                                                                                                                        \
0466     {                                                                                                                                                          \
0467         writer->writeAttribute(QStringLiteral("style"), QString::number(pen.style()));                                                                         \
0468         writer->writeAttribute(QStringLiteral("color_r"), QString::number(pen.color().red()));                                                                 \
0469         writer->writeAttribute(QStringLiteral("color_g"), QString::number(pen.color().green()));                                                               \
0470         writer->writeAttribute(QStringLiteral("color_b"), QString::number(pen.color().blue()));                                                                \
0471         writer->writeAttribute(QStringLiteral("width"), QString::number(pen.widthF()));                                                                        \
0472     }
0473 
0474 #define READ_QPEN(pen)                                                                                                                                         \
0475     {                                                                                                                                                          \
0476         str = attribs.value(QStringLiteral("style")).toString();                                                                                               \
0477         if (str.isEmpty())                                                                                                                                     \
0478             reader->raiseMissingAttributeWarning(QStringLiteral("style"));                                                                                     \
0479         else                                                                                                                                                   \
0480             pen.setStyle(static_cast<Qt::PenStyle>(str.toInt()));                                                                                              \
0481                                                                                                                                                                \
0482         QColor color;                                                                                                                                          \
0483         str = attribs.value(QStringLiteral("color_r")).toString();                                                                                             \
0484         if (str.isEmpty())                                                                                                                                     \
0485             reader->raiseMissingAttributeWarning(QStringLiteral("color_r"));                                                                                   \
0486         else                                                                                                                                                   \
0487             color.setRed(str.toInt());                                                                                                                         \
0488                                                                                                                                                                \
0489         str = attribs.value(QStringLiteral("color_g")).toString();                                                                                             \
0490         if (str.isEmpty())                                                                                                                                     \
0491             reader->raiseMissingAttributeWarning(QStringLiteral("color_g"));                                                                                   \
0492         else                                                                                                                                                   \
0493             color.setGreen(str.toInt());                                                                                                                       \
0494                                                                                                                                                                \
0495         str = attribs.value(QStringLiteral("color_b")).toString();                                                                                             \
0496         if (str.isEmpty())                                                                                                                                     \
0497             reader->raiseMissingAttributeWarning(QStringLiteral("color_b"));                                                                                   \
0498         else                                                                                                                                                   \
0499             color.setBlue(str.toInt());                                                                                                                        \
0500                                                                                                                                                                \
0501         pen.setColor(color);                                                                                                                                   \
0502                                                                                                                                                                \
0503         str = attribs.value(QStringLiteral("width")).toString();                                                                                               \
0504         if (str.isEmpty())                                                                                                                                     \
0505             reader->raiseMissingAttributeWarning(QStringLiteral("width"));                                                                                     \
0506         else                                                                                                                                                   \
0507             pen.setWidthF(str.toDouble());                                                                                                                     \
0508     }
0509 
0510 // QFont
0511 #define WRITE_QFONT(font)                                                                                                                                      \
0512     {                                                                                                                                                          \
0513         writer->writeAttribute(QStringLiteral("fontFamily"), font.family());                                                                                   \
0514         writer->writeAttribute(QStringLiteral("fontSize"), QString::number(font.pixelSize()));                                                                 \
0515         writer->writeAttribute(QStringLiteral("fontPointSize"), QString::number(font.pointSize()));                                                            \
0516         writer->writeAttribute(QStringLiteral("fontWeight"), QString::number(font.weight()));                                                                  \
0517         writer->writeAttribute(QStringLiteral("fontItalic"), QString::number(font.italic()));                                                                  \
0518     }
0519 
0520 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) // uses font.setLegacyWeight(int)
0521 #define READ_QFONT(font)                                                                                                                                       \
0522     {                                                                                                                                                          \
0523         str = attribs.value(QStringLiteral("fontFamily")).toString();                                                                                          \
0524         if (str.isEmpty())                                                                                                                                     \
0525             reader->raiseMissingAttributeWarning(QStringLiteral("fontFamily"));                                                                                \
0526         else                                                                                                                                                   \
0527             font.setFamily(str);                                                                                                                               \
0528                                                                                                                                                                \
0529         str = attribs.value(QStringLiteral("fontSize")).toString();                                                                                            \
0530         if (str.isEmpty())                                                                                                                                     \
0531             reader->raiseMissingAttributeWarning(QStringLiteral("fontSize"));                                                                                  \
0532         else {                                                                                                                                                 \
0533             int size = str.toInt();                                                                                                                            \
0534             if (size != -1)                                                                                                                                    \
0535                 font.setPixelSize(size);                                                                                                                       \
0536         }                                                                                                                                                      \
0537                                                                                                                                                                \
0538         str = attribs.value(QStringLiteral("fontPointSize")).toString();                                                                                       \
0539         if (str.isEmpty())                                                                                                                                     \
0540             reader->raiseMissingAttributeWarning(QStringLiteral("fontPointSize"));                                                                             \
0541         else {                                                                                                                                                 \
0542             int size = str.toInt();                                                                                                                            \
0543             if (size != -1)                                                                                                                                    \
0544                 font.setPointSize(size);                                                                                                                       \
0545         }                                                                                                                                                      \
0546                                                                                                                                                                \
0547         str = attribs.value(QStringLiteral("fontWeight")).toString();                                                                                          \
0548         if (str.isEmpty())                                                                                                                                     \
0549             reader->raiseMissingAttributeWarning(QStringLiteral("fontWeight"));                                                                                \
0550         else                                                                                                                                                   \
0551             font.setLegacyWeight(str.toInt());                                                                                                                 \
0552                                                                                                                                                                \
0553         str = attribs.value(QStringLiteral("fontItalic")).toString();                                                                                          \
0554         if (str.isEmpty())                                                                                                                                     \
0555             reader->raiseMissingAttributeWarning(QStringLiteral("fontItalic"));                                                                                \
0556         else                                                                                                                                                   \
0557             font.setItalic(str.toInt());                                                                                                                       \
0558     }
0559 #else
0560 #define READ_QFONT(font)                                                                                                                                       \
0561     {                                                                                                                                                          \
0562         str = attribs.value(QStringLiteral("fontFamily")).toString();                                                                                          \
0563         if (str.isEmpty())                                                                                                                                     \
0564             reader->raiseMissingAttributeWarning(QStringLiteral("fontFamily"));                                                                                \
0565         else                                                                                                                                                   \
0566             font.setFamily(str);                                                                                                                               \
0567                                                                                                                                                                \
0568         str = attribs.value(QStringLiteral("fontSize")).toString();                                                                                            \
0569         if (str.isEmpty())                                                                                                                                     \
0570             reader->raiseMissingAttributeWarning(QStringLiteral("fontSize"));                                                                                  \
0571         else {                                                                                                                                                 \
0572             int size = str.toInt();                                                                                                                            \
0573             if (size != -1)                                                                                                                                    \
0574                 font.setPixelSize(size);                                                                                                                       \
0575         }                                                                                                                                                      \
0576                                                                                                                                                                \
0577         str = attribs.value(QStringLiteral("fontPointSize")).toString();                                                                                       \
0578         if (str.isEmpty())                                                                                                                                     \
0579             reader->raiseMissingAttributeWarning(QStringLiteral("fontPointSize"));                                                                             \
0580         else {                                                                                                                                                 \
0581             int size = str.toInt();                                                                                                                            \
0582             if (size != -1)                                                                                                                                    \
0583                 font.setPointSize(size);                                                                                                                       \
0584         }                                                                                                                                                      \
0585                                                                                                                                                                \
0586         str = attribs.value(QStringLiteral("fontWeight")).toString();                                                                                          \
0587         if (str.isEmpty())                                                                                                                                     \
0588             reader->raiseMissingAttributeWarning(QStringLiteral("fontWeight"));                                                                                \
0589         else                                                                                                                                                   \
0590             font.setWeight(str.toInt());                                                                                                                       \
0591                                                                                                                                                                \
0592         str = attribs.value(QStringLiteral("fontItalic")).toString();                                                                                          \
0593         if (str.isEmpty())                                                                                                                                     \
0594             reader->raiseMissingAttributeWarning(QStringLiteral("fontItalic"));                                                                                \
0595         else                                                                                                                                                   \
0596             font.setItalic(str.toInt());                                                                                                                       \
0597     }
0598 #endif
0599 
0600 // QBrush
0601 #define WRITE_QBRUSH(brush)                                                                                                                                    \
0602     {                                                                                                                                                          \
0603         writer->writeAttribute(QStringLiteral("brush_style"), QString::number(brush.style()));                                                                 \
0604         writer->writeAttribute(QStringLiteral("brush_color_r"), QString::number(brush.color().red()));                                                         \
0605         writer->writeAttribute(QStringLiteral("brush_color_g"), QString::number(brush.color().green()));                                                       \
0606         writer->writeAttribute(QStringLiteral("brush_color_b"), QString::number(brush.color().blue()));                                                        \
0607     }
0608 
0609 #define READ_QBRUSH(brush)                                                                                                                                     \
0610     {                                                                                                                                                          \
0611         str = attribs.value(QStringLiteral("brush_style")).toString();                                                                                         \
0612         if (str.isEmpty())                                                                                                                                     \
0613             reader->raiseMissingAttributeWarning(QStringLiteral("brush_style"));                                                                               \
0614         else                                                                                                                                                   \
0615             brush.setStyle(static_cast<Qt::BrushStyle>(str.toInt()));                                                                                          \
0616                                                                                                                                                                \
0617         QColor color;                                                                                                                                          \
0618         str = attribs.value(QStringLiteral("brush_color_r")).toString();                                                                                       \
0619         if (str.isEmpty())                                                                                                                                     \
0620             reader->raiseMissingAttributeWarning(QStringLiteral("brush_color_r"));                                                                             \
0621         else                                                                                                                                                   \
0622             color.setRed(str.toInt());                                                                                                                         \
0623                                                                                                                                                                \
0624         str = attribs.value(QStringLiteral("brush_color_g")).toString();                                                                                       \
0625         if (str.isEmpty())                                                                                                                                     \
0626             reader->raiseMissingAttributeWarning(QStringLiteral("brush_color_g"));                                                                             \
0627         else                                                                                                                                                   \
0628             color.setGreen(str.toInt());                                                                                                                       \
0629                                                                                                                                                                \
0630         str = attribs.value(QStringLiteral("brush_color_b")).toString();                                                                                       \
0631         if (str.isEmpty())                                                                                                                                     \
0632             reader->raiseMissingAttributeWarning(QStringLiteral("brush_color_b"));                                                                             \
0633         else                                                                                                                                                   \
0634             color.setBlue(str.toInt());                                                                                                                        \
0635                                                                                                                                                                \
0636         brush.setColor(color);                                                                                                                                 \
0637     }
0638 
0639 // Column
0640 #define WRITE_COLUMN(column, columnName)                                                                                                                       \
0641     if (column) {                                                                                                                                              \
0642         writer->writeAttribute(QStringLiteral(#columnName), column->path());                                                                                   \
0643     } else {                                                                                                                                                   \
0644         writer->writeAttribute(QStringLiteral(#columnName), QString());                                                                                        \
0645     }
0646 
0647 // column names can be empty in case no columns were used before save
0648 // the actual pointers to the x- and y-columns are restored in Project::load()
0649 #define READ_COLUMN(columnName)                                                                                                                                \
0650     {                                                                                                                                                          \
0651         str = attribs.value(QStringLiteral(#columnName)).toString();                                                                                           \
0652         d->columnName##Path = str;                                                                                                                             \
0653     }
0654 
0655 #define READ_INT_VALUE_DIRECT(name, var, type)                                                                                                                 \
0656     {                                                                                                                                                          \
0657         str = attribs.value(QStringLiteral(name)).toString();                                                                                                  \
0658         if (str.isEmpty())                                                                                                                                     \
0659             reader->raiseMissingAttributeWarning(QStringLiteral(name));                                                                                        \
0660         else                                                                                                                                                   \
0661             var = static_cast<type>(str.toInt());                                                                                                              \
0662     }
0663 
0664 #define READ_INT_VALUE(name, var, type) READ_INT_VALUE_DIRECT(name, d->var, type)
0665 
0666 #define READ_DOUBLE_VALUE(name, var)                                                                                                                           \
0667     {                                                                                                                                                          \
0668         str = attribs.value(QStringLiteral(name)).toString();                                                                                                  \
0669         if (str.isEmpty())                                                                                                                                     \
0670             reader->raiseMissingAttributeWarning(QStringLiteral(name));                                                                                        \
0671         else                                                                                                                                                   \
0672             d->var = str.toDouble();                                                                                                                           \
0673     }
0674 
0675 #define QGRAPHICSITEM_READ_DOUBLE_VALUE(name, Var)                                                                                                             \
0676     {                                                                                                                                                          \
0677         str = attribs.value(QStringLiteral(name)).toString();                                                                                                  \
0678         if (str.isEmpty())                                                                                                                                     \
0679             reader->raiseMissingAttributeWarning(QStringLiteral(name));                                                                                        \
0680         else                                                                                                                                                   \
0681             d->set##Var(str.toDouble());                                                                                                                       \
0682     }
0683 
0684 #define READ_STRING_VALUE(name, var)                                                                                                                           \
0685     { d->var = attribs.value(QLatin1String(name)).toString(); }
0686 
0687 // used in Project::load()
0688 #define RESTORE_COLUMN_POINTER(obj, col, Col)                                                                                                                  \
0689     if (!obj->col##Path().isEmpty()) {                                                                                                                         \
0690         for (Column * column : columns) {                                                                                                                      \
0691             if (!column)                                                                                                                                       \
0692                 continue;                                                                                                                                      \
0693             if (column->path() == obj->col##Path()) {                                                                                                          \
0694                 obj->set##Col(column);                                                                                                                         \
0695                 break;                                                                                                                                         \
0696             }                                                                                                                                                  \
0697         }                                                                                                                                                      \
0698     }
0699 
0700 #define WRITE_PATH(obj, name)                                                                                                                                  \
0701     if (obj) {                                                                                                                                                 \
0702         writer->writeAttribute(QLatin1String(#name), obj->path());                                                                                             \
0703     } else {                                                                                                                                                   \
0704         writer->writeAttribute(QLatin1String(#name), QString());                                                                                               \
0705     }
0706 
0707 #define READ_PATH(name)                                                                                                                                        \
0708     {                                                                                                                                                          \
0709         str = attribs.value(QLatin1String(#name)).toString();                                                                                                  \
0710         d->name##Path = str;                                                                                                                                   \
0711     }
0712 
0713 #define RESTORE_POINTER(obj, name, Name, Type, list)                                                                                                           \
0714     if (!obj->name##Path().isEmpty()) {                                                                                                                        \
0715         for (AbstractAspect * aspect : list) {                                                                                                                 \
0716             if (aspect->path() == obj->name##Path()) {                                                                                                         \
0717                 auto a = dynamic_cast<Type*>(aspect);                                                                                                          \
0718                 if (!a)                                                                                                                                        \
0719                     continue;                                                                                                                                  \
0720                 obj->set##Name(a);                                                                                                                             \
0721                 break;                                                                                                                                         \
0722             }                                                                                                                                                  \
0723         }                                                                                                                                                      \
0724     }
0725 
0726 #endif // MACROS_H