diff options
Diffstat (limited to 'compat')
-rw-r--r-- | compat/options.cpp | 269 | ||||
-rw-r--r-- | compat/options.hpp | 491 | ||||
-rw-r--r-- | compat/singleton.cpp | 0 | ||||
-rw-r--r-- | compat/singleton.hpp | 0 | ||||
-rw-r--r-- | compat/slider.cpp | 73 | ||||
-rw-r--r-- | compat/slider.hpp | 62 |
6 files changed, 0 insertions, 895 deletions
diff --git a/compat/options.cpp b/compat/options.cpp deleted file mode 100644 index 33c1cf0d..00000000 --- a/compat/options.cpp +++ /dev/null @@ -1,269 +0,0 @@ -#include "options.hpp" - -namespace options -{ - -group::group(const QString& name) : name(name) -{ - auto conf = ini_file(); - conf->beginGroup(name); - for (auto& k_ : conf->childKeys()) - { - auto tmp = k_.toUtf8(); - QString k(tmp); - kvs[k] = conf->value(k_); - } - conf->endGroup(); -} - -void group::save() const -{ - auto s = ini_file(); - s->beginGroup(name); - for (auto& i : kvs) - s->setValue(i.first, i.second); - s->endGroup(); -} - -void group::put(const QString &s, const QVariant &d) -{ - kvs[s] = d; -} - -bool group::contains(const QString &s) const -{ - return kvs.count(s) != 0; -} - -QString group::ini_directory() -{ - const auto dirs = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); - if (dirs.size() == 0) - return ""; - if (QDir(dirs[0]).mkpath(OPENTRACK_ORG)) - return dirs[0] + "/" OPENTRACK_ORG; - return ""; -} - -QString group::ini_filename() -{ - QSettings settings(OPENTRACK_ORG); - return settings.value(OPENTRACK_CONFIG_FILENAME_KEY, OPENTRACK_DEFAULT_CONFIG).toString(); -} - -QString group::ini_pathname() -{ - const auto dir = ini_directory(); - if (dir == "") - return ""; - return dir + "/" + ini_filename(); -} - -const QStringList group::ini_list() -{ - const auto dirname = ini_directory(); - if (dirname == "") - return QStringList(); - QDir settings_dir(dirname); - QStringList list = settings_dir.entryList( QStringList { "*.ini" } , QDir::Files, QDir::Name ); - std::sort(list.begin(), list.end()); - return list; -} - -const mem<QSettings> group::ini_file() -{ - const auto pathname = ini_pathname(); - if (pathname != "") - return std::make_shared<QSettings>(ini_pathname(), QSettings::IniFormat); - return std::make_shared<QSettings>(); -} - -bool group::operator==(const group& other) const -{ - for (const auto& kv : kvs) - { - const QVariant val = other.get<QVariant>(kv.first); - if (!other.contains(kv.first) || kv.second != val) - { - qDebug() << "bundle" << name << "modified" << "key" << kv.first << "-" << val << "<>" << kv.second; - return false; - } - } - - for (const auto& kv : other.kvs) - { - const QVariant val = get<QVariant>(kv.first); - if (!contains(kv.first) || kv.second != val) - { - qDebug() << "bundle" << name << "modified" << "key" << kv.first << "-" << kv.second << "<>" << val; - return false; - } - } - return true; -} - -impl_bundle::impl_bundle(const QString& group_name) - : - mtx(QMutex::Recursive), - group_name(group_name), - saved(group_name), - transient(saved) -{ -} - -void impl_bundle::reload() -{ - { - QMutexLocker l(&mtx); - saved = group(group_name); - transient = saved; - } - emit reloading(); -} - -void impl_bundle::store_kv(const QString& name, const QVariant& datum) -{ - QMutexLocker l(&mtx); - - transient.put(name, datum); -} - -bool impl_bundle::contains(const QString &name) const -{ - QMutexLocker l(const_cast<QMutex*>(&mtx)); - return transient.contains(name); -} - -void impl_bundle::save() -{ - bool modified_ = false; - - { - QMutexLocker l(&mtx); - if (saved != transient) - { - qDebug() << "bundle" << group_name << "changed, saving"; - modified_ = true; - saved = transient; - saved.save(); - } - } - - if (modified_) - emit saving(); -} - -bool impl_bundle::modifiedp() const // XXX unused -{ - QMutexLocker l(const_cast<QMutex*>(&mtx)); - return transient != saved; -} - -base_value::base_value(pbundle b, const QString &name) : - b(b), - self_name(name) -{ -} - -opts::~opts() -{ - b->reload(); -} - -opts::opts(const QString &name) : b(bundle(name)) -{ -} - -detail::custom_type_initializer::custom_type_initializer() -{ - qRegisterMetaTypeStreamOperators<slider_value>("slider_value"); - QMetaType::registerDebugStreamOperator<slider_value>(); -} - -detail::custom_type_initializer detail::custom_type_initializer::singleton; - -namespace detail { - -opt_bundle::opt_bundle(const QString& group_name) - : impl_bundle(group_name) -{ -} - -opt_bundle::~opt_bundle() -{ - detail::singleton().bundle_decf(group_name); -} - -void opt_singleton::bundle_decf(const opt_singleton::k& key) -{ - QMutexLocker l(&implsgl_mtx); - - if (--std::get<0>(implsgl_data[key]) == 0) - { - qDebug() << "bundle -" << key; - - implsgl_data.erase(key); - } -} - -void opt_singleton::after_profile_changed_() -{ - QMutexLocker l(&implsgl_mtx); - - for (auto& kv : implsgl_data) - { - tt& tuple = kv.second; - std::weak_ptr<v>& bundle = std::get<1>(tuple); - - mem<v> bundle_ = bundle.lock(); - if (bundle_) - { - qDebug() << "bundle: reverting" << kv.first << "due to profile change"; - bundle_->reload(); - } - } -} - -void opt_singleton::refresh_all_bundles() -{ - singleton().after_profile_changed_(); -} - -opt_singleton::opt_singleton() : implsgl_mtx(QMutex::Recursive) -{ -} - -opt_singleton::~opt_singleton() -{ - qDebug() << "exit: bundle singleton"; -} - -pbundle opt_singleton::bundle(const opt_singleton::k &key) -{ - QMutexLocker l(&implsgl_mtx); - - if (implsgl_data.count(key) != 0) - { - auto shared = std::get<1>(implsgl_data[key]).lock(); - if (shared != nullptr) - return shared; - } - - qDebug() << "bundle +" << key; - - auto shr = std::make_shared<v>(key); - implsgl_data[key] = tt(1, shr); - return shr; -} - -OPENTRACK_COMPAT_EXPORT opt_singleton& singleton() -{ - static opt_singleton ret; - return ret; -} - - -} // end options::detail - -} // end options - diff --git a/compat/options.hpp b/compat/options.hpp deleted file mode 100644 index 7b004ba6..00000000 --- a/compat/options.hpp +++ /dev/null @@ -1,491 +0,0 @@ -/* Copyright (c) 2013-2016 Stanislaw Halik - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - */ - -#pragma once - -#include <memory> -#include <tuple> -#include <map> -#include <cinttypes> -#include <vector> -#include <memory> - -#include <QObject> -#include <QSettings> -#include <QString> -#include <QVariant> -#include <QMutex> -#include <QMutexLocker> -#include <QWidget> -#include <QComboBox> -#include <QCheckBox> -#include <QDoubleSpinBox> -#include <QSpinBox> -#include <QSlider> -#include <QLineEdit> -#include <QLabel> -#include <QTabWidget> -#include <QCoreApplication> -#include <QFileInfo> -#include <QDir> -#include <QStandardPaths> -#include <QApplication> - -#include <QMetaType> -#include <QDataStream> - -#include <QDebug> - -#include "export.hpp" -#include "slider.hpp" - -#include "util.hpp" - -#define OPENTRACK_CONFIG_FILENAME_KEY "settings-filename" -#define OPENTRACK_DEFAULT_CONFIG "default.ini" -#define OPENTRACK_ORG "opentrack-2.3" - -namespace options { -namespace detail { -class custom_type_initializer -{ - custom_type_initializer(); - static custom_type_initializer singleton; -}; -} - -template<typename k, typename v> using map = std::map<k, v>; - -// snapshot of qsettings group at given time -class OPENTRACK_COMPAT_EXPORT group -{ -private: - map<QString, QVariant> kvs; - QString name; -public: - group(const QString& name); - void save() const; - void put(const QString& s, const QVariant& d); - bool contains(const QString& s) const; - static QString ini_directory(); - static QString ini_filename(); - static QString ini_pathname(); - static const QStringList ini_list(); - static const mem<QSettings> ini_file(); - bool operator==(const group& other) const; - bool operator!=(const group& other) const { return !(*this == other); } - - template<typename t> - t get(const QString& k) const - { - auto value = kvs.find(k); - if (value != kvs.cend()) - return value->second.value<t>(); - return t(); - } -}; - -class OPENTRACK_COMPAT_EXPORT impl_bundle : public QObject -{ - Q_OBJECT -protected: - QMutex mtx; - const QString group_name; - group saved; - group transient; - impl_bundle(const impl_bundle&) = delete; - impl_bundle& operator=(const impl_bundle&) = delete; -signals: - void reloading(); - void saving() const; -public: - impl_bundle(const QString& group_name); - QString name() { return group_name; } - void reload(); - void store_kv(const QString& name, const QVariant& datum); - bool contains(const QString& name) const; - void save(); - bool modifiedp() const; - - template<typename t> - t get(const QString& name) const - { - QMutexLocker l(const_cast<QMutex*>(&mtx)); - return transient.get<t>(name); - } -}; - -namespace detail -{ -class OPENTRACK_COMPAT_EXPORT opt_bundle final : public impl_bundle -{ -public: - opt_bundle(const QString& group_name); - ~opt_bundle(); -}; - -struct OPENTRACK_COMPAT_EXPORT opt_singleton -{ -public: - using k = QString; - using v = opt_bundle; - using cnt = int; - using pbundle = std::shared_ptr<v>; - using tt = std::tuple<cnt, std::weak_ptr<v>>; -private: - QMutex implsgl_mtx; - map<k, tt> implsgl_data; - void after_profile_changed_(); -public: - opt_singleton(); - ~opt_singleton(); - pbundle bundle(const k& key); - void bundle_decf(const k& key); - static void refresh_all_bundles(); -}; - -OPENTRACK_COMPAT_EXPORT opt_singleton& singleton(); -} - -using pbundle = std::shared_ptr<detail::opt_bundle>; - -inline pbundle bundle(const QString& name) -{ - return detail::singleton().bundle(name); -} - -#define OPENTRACK_DEFINE_SLOT(t) void setValue(t datum) { store(datum); } -#define OPENTRACK_DEFINE_SIGNAL(t) void valueChanged(t) - -namespace detail { -template<typename t> struct value_type_traits { using type = t;}; -template<> struct value_type_traits<QString> { using type = const QString&; }; -template<> struct value_type_traits<slider_value> { using type = const slider_value&; }; -template<typename t> using value_type_t = typename value_type_traits<t>::type; -} - -class OPENTRACK_COMPAT_EXPORT base_value : public QObject -{ - Q_OBJECT -public: - QString name() const { return self_name; } - base_value(pbundle b, const QString& name); -signals: - OPENTRACK_DEFINE_SIGNAL(double); - OPENTRACK_DEFINE_SIGNAL(float); - OPENTRACK_DEFINE_SIGNAL(int); - OPENTRACK_DEFINE_SIGNAL(bool); - OPENTRACK_DEFINE_SIGNAL(const QString&); - OPENTRACK_DEFINE_SIGNAL(const slider_value&); -protected: - pbundle b; - QString self_name; - - template<typename t> - void store(const t& datum) - { - b->store_kv(self_name, QVariant::fromValue(datum)); - emit valueChanged(static_cast<detail::value_type_t<t>>(datum)); - } - void store(float datum) - { - store(double(datum)); - } - -public slots: - OPENTRACK_DEFINE_SLOT(double) - OPENTRACK_DEFINE_SLOT(int) - OPENTRACK_DEFINE_SLOT(bool) - OPENTRACK_DEFINE_SLOT(const QString&) - OPENTRACK_DEFINE_SLOT(const slider_value&) - public slots: - virtual void reload() = 0; -}; - -namespace detail { -template<typename t> -struct value_get_traits -{ - static inline t get(const t& val, const t&) - { - return val; - } -}; - -template<> -struct value_get_traits<slider_value> -{ - using t = slider_value; - static inline t get(const t& val, const t& def) - { - return t(val.cur(), def.min(), def.max()); - } -}; -} - -template<typename t_> -class value : public base_value -{ - template<typename t__, typename Enable = void> - struct get_t - { using t = t__; }; - - // Qt uses int a lot in slots so use it for all enums - template<typename t__> - struct get_t<t__, typename std::enable_if<std::is_enum<t__>::value>::type> - //{ using t = typename std::underlying_type<t__>::type; }; - { using t = int; }; - - using t = t_; -public: - using underlying_t = typename get_t<t_>::t; - - t operator=(const t& datum) - { - store(static_cast<underlying_t>(datum)); - return datum; - } - - static constexpr const Qt::ConnectionType DIRECT_CONNTYPE = Qt::AutoConnection; - static constexpr const Qt::ConnectionType SAFE_CONNTYPE = Qt::QueuedConnection; - - value(pbundle b, const QString& name, t def) : base_value(b, name), def(def) - { - QObject::connect(b.get(), SIGNAL(reloading()), - this, SLOT(reload()), - DIRECT_CONNTYPE); - if (!b->contains(name) || b->get<QVariant>(name).type() == QVariant::Invalid) - *this = def; - } - - value(pbundle b, const char* name, t def) : value(b, QString(name), def) - { - } - - t get() const - { - t val = b->contains(self_name) - ? static_cast<t>(b->get<underlying_t>(self_name)) - : def; - return detail::value_get_traits<t>::get(val, def); - } - - operator t() const { return get(); } - - void reload() override - { - *this = static_cast<t>(*this); - } - -private: - t def; -}; - -struct OPENTRACK_COMPAT_EXPORT opts -{ - pbundle b; - opts(const QString& name); - opts& operator=(const opts&) = delete; - opts(const opts&) = delete; - ~opts(); -}; - -template<typename t, typename q> -inline void tie_setting(value<t>&, q*); - -template<typename t> -inline -typename std::enable_if<std::is_enum<t>::value>::type -tie_setting(value<t>& v, QComboBox* cb) -{ - cb->setCurrentIndex(cb->findData((unsigned)static_cast<t>(v))); - v = static_cast<t>(cb->currentData().toInt()); - - // QObject::connect plays badly with std::bind of std::shared_ptr. Data seems to get freed. - // Direct accesses of cb->currentData within arbitrary thread context cause crashes as well. - // Hence we go for a verbose implementation. - - std::vector<int> enum_cases; - enum_cases.reserve(unsigned(cb->count())); - - for (int i = 0; i < cb->count(); i++) - enum_cases.push_back(cb->itemData(i).toInt()); - - struct fn1 - { - value<t>& v; - QComboBox* cb; - std::vector<int> enum_cases; - - fn1(value<t>& v, QComboBox* cb, const std::vector<int>& enum_cases) : - v(v), - cb(cb), - enum_cases(enum_cases) - { - } - - void operator()(int idx) - { - if (idx < 0 || idx >= (int)enum_cases.size()) - v = static_cast<t>(-1); - else - v = static_cast<t>(t(std::intptr_t(enum_cases[idx]))); - } - }; - - struct fn2 - { - value<t>& v; - QComboBox* cb; - std::vector<int> enum_cases; - - fn2(value<t>& v, QComboBox* cb, const std::vector<int>& enum_cases) : - v(v), - cb(cb), - enum_cases(enum_cases) - { - } - - void operator()(int val) - { - for (unsigned i = 0; i < enum_cases.size(); i++) - { - if (val == enum_cases[i]) - { - cb->setCurrentIndex(i); - return; - } - } - cb->setCurrentIndex(-1); - } - }; - - base_value::connect(cb, - static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), - &v, - fn1(v, cb, enum_cases), - v.DIRECT_CONNTYPE); - base_value::connect(&v, - static_cast<void (base_value::*)(int)>(&base_value::valueChanged), - cb, - fn2(v, cb, enum_cases), - v.DIRECT_CONNTYPE); -} - -template<> -inline void tie_setting(value<int>& v, QComboBox* cb) -{ - cb->setCurrentIndex(v); - v = cb->currentIndex(); - base_value::connect(cb, SIGNAL(currentIndexChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE); - base_value::connect(&v, SIGNAL(valueChanged(int)), cb, SLOT(setCurrentIndex(int)), v.SAFE_CONNTYPE); -} - -template<> -inline void tie_setting(value<QString>& v, QComboBox* cb) -{ - cb->setCurrentText(v); - v = cb->currentText(); - base_value::connect(cb, SIGNAL(currentTextChanged(QString)), &v, SLOT(setValue(QString)), v.DIRECT_CONNTYPE); - base_value::connect(&v, SIGNAL(valueChanged(QString)), cb, SLOT(setCurrentText(QString)), v.SAFE_CONNTYPE); -} - -template<> -inline void tie_setting(value<bool>& v, QCheckBox* cb) -{ - cb->setChecked(v); - base_value::connect(cb, SIGNAL(toggled(bool)), &v, SLOT(setValue(bool)), v.DIRECT_CONNTYPE); - base_value::connect(&v, SIGNAL(valueChanged(bool)), cb, SLOT(setChecked(bool)), v.SAFE_CONNTYPE); -} - -template<> -inline void tie_setting(value<double>& v, QDoubleSpinBox* dsb) -{ - dsb->setValue(v); - base_value::connect(dsb, SIGNAL(valueChanged(double)), &v, SLOT(setValue(double)), v.DIRECT_CONNTYPE); - base_value::connect(&v, SIGNAL(valueChanged(double)), dsb, SLOT(setValue(double)), v.SAFE_CONNTYPE); -} - -template<> -inline void tie_setting(value<int>& v, QSpinBox* sb) -{ - sb->setValue(v); - base_value::connect(sb, SIGNAL(valueChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE); - base_value::connect(&v, SIGNAL(valueChanged(int)), sb, SLOT(setValue(int)), v.SAFE_CONNTYPE); -} - -template<> -inline void tie_setting(value<int>& v, QSlider* sl) -{ - sl->setValue(v); - v = sl->value(); - base_value::connect(sl, SIGNAL(valueChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE); - base_value::connect(&v, SIGNAL(valueChanged(int)), sl, SLOT(setValue(int)), v.SAFE_CONNTYPE); -} - -template<> -inline void tie_setting(value<QString>& v, QLineEdit* le) -{ - le->setText(v); - base_value::connect(le, SIGNAL(textChanged(QString)), &v, SLOT(setValue(QString)), v.DIRECT_CONNTYPE); - base_value::connect(&v, SIGNAL(valueChanged(QString)),le, SLOT(setText(QString)), v.SAFE_CONNTYPE); -} - -template<> -inline void tie_setting(value<QString>& v, QLabel* lb) -{ - lb->setText(v); - base_value::connect(&v, SIGNAL(valueChanged(QString)), lb, SLOT(setText(QString)), v.DIRECT_CONNTYPE); -} - -template<> -inline void tie_setting(value<int>& v, QTabWidget* t) -{ - t->setCurrentIndex(v); - base_value::connect(t, SIGNAL(currentChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE); - base_value::connect(&v, SIGNAL(valueChanged(int)), t, SLOT(setCurrentIndex(int)), v.SAFE_CONNTYPE); -} - -template<> -inline void tie_setting(value<slider_value>& v, QSlider* w) -{ - // we can't get these at runtime since signals cross threads - const int q_min = w->minimum(); - const int q_max = w->maximum(); - const int q_diff = q_max - q_min; - - slider_value sv(v); - - const double sv_max = sv.max(); - const double sv_min = sv.min(); - const double sv_c = sv_max - sv_min; - - w->setValue(int((sv.cur() - sv_min) / sv_c * q_diff + q_min)); - v = slider_value(q_diff <= 0 ? 0 : (w->value() - q_min) * sv_c / (double)q_diff + sv_min, sv_min, sv_max); - - base_value::connect(w, - &QSlider::valueChanged, - &v, - [=, &v](int pos) -> void - { - if (q_diff <= 0 || pos <= 0) - v = slider_value(sv_min, sv_min, sv_max); - else - v = slider_value((pos - q_min) * sv_c / (double)q_diff + sv_min, sv_min, sv_max); - }, - v.DIRECT_CONNTYPE); - base_value::connect(&v, - static_cast<void(base_value::*)(double)>(&base_value::valueChanged), - w, - [=](double value) -> void - { - w->setValue(int(value * q_diff) + q_min); - }, - v.SAFE_CONNTYPE); -} -} - diff --git a/compat/singleton.cpp b/compat/singleton.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/compat/singleton.cpp diff --git a/compat/singleton.hpp b/compat/singleton.hpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/compat/singleton.hpp diff --git a/compat/slider.cpp b/compat/slider.cpp deleted file mode 100644 index be1aaeb8..00000000 --- a/compat/slider.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "slider.hpp" -#include <cmath> - -namespace options { - -slider_value::slider_value(double cur, double min, double max) : - cur_(cur), - min_(min), - max_(max) -{ - if (min_ > max_) - min_ = max_; - if (cur_ > max_) - cur_ = max; - if (cur_ < min_) - cur_ = min_; -} - -slider_value::slider_value(const slider_value& v) : slider_value(v.cur(), v.min(), v.max()) -{ -} - -slider_value::slider_value() : slider_value(0, 0, 0) -{ -} - -slider_value& slider_value::operator=(const slider_value& v) -{ - cur_ = v.cur_; - - min_ = v.min_; - max_ = v.max_; - - return *this; -} - -bool slider_value::operator==(const slider_value& v) const -{ - using std::fabs; - - static constexpr double eps = 1e-3; - - return (fabs(v.cur_ - cur_) < eps && - fabs(v.min_ - min_) < eps && - fabs(v.max_ - max_) < eps); -} - -slider_value slider_value::update_from_slider(int pos, int q_min, int q_max) const -{ - slider_value v(*this); - - const int q_diff = q_max - q_min; - const double sv_pos = q_diff == 0 - ? -1e6 - : (((pos - q_min) * (v.max() - v.min())) / q_diff + v.min()); - - if (sv_pos < v.min()) - v = slider_value(v.min(), v.min(), v.max()); - else if (sv_pos > v.max()) - v = slider_value(v.max(), v.min(), v.max()); - else - v = slider_value(sv_pos, v.min(), v.max()); - return v; -} - -int slider_value::to_slider_pos(int q_min, int q_max) const -{ - const int q_diff = q_max - q_min; - - return int(std::round(((cur() - min() * q_diff) / (max() - min())) + q_min)); -} - -} // end ns options diff --git a/compat/slider.hpp b/compat/slider.hpp deleted file mode 100644 index 7d54c650..00000000 --- a/compat/slider.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright (c) 2016 Stanislaw Halik - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - */ - -#pragma once - -#include "export.hpp" -#include <QMetaType> -#include <QDataStream> -#include <QDebug> - -namespace options -{ - class OPENTRACK_COMPAT_EXPORT slider_value final - { - double cur_, min_, max_; - public: - slider_value(double cur, double min, double max); - slider_value(const slider_value& v); - slider_value(); - slider_value& operator=(const slider_value& v); - bool operator==(const slider_value& v) const; - operator double() const { return cur_; } - double cur() const { return cur_; } - double min() const { return min_; } - double max() const { return max_; } - slider_value update_from_slider(int pos, int q_min, int q_max) const; - int to_slider_pos(int q_min, int q_max) const; - }; -} - -QT_BEGIN_NAMESPACE - -inline QDebug operator << (QDebug dbg, const options::slider_value& val) -{ - return dbg << val.cur(); -} - -inline QDataStream& operator << (QDataStream& out, const options::slider_value& v) -{ - out << v.cur() - << v.min() - << v.max(); - return out; -} - -inline QDataStream& operator >> (QDataStream& in, options::slider_value& v) -{ - double cur, min, max; - in >> cur; - in >> min; - in >> max; - v = options::slider_value(cur, min, max); - return in; -} - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(options::slider_value) |