refs #304, refs #307, refs #173 as preparation for GUI, name / variant pair

* for a generic table and tree view
* generic name pair models and view
* Hash for variant
This commit is contained in:
Klaus Basan
2014-07-27 03:00:13 +02:00
parent 8c94f9b479
commit 8a5a268a77
11 changed files with 710 additions and 6 deletions

View File

@@ -0,0 +1,36 @@
/* Copyright (C) 2013
* swift Project Community / Contributors
*
* This file is part of swift Project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of Swift Project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "namevariantpairlistmodel.h"
#include "blackmisc/blackmiscfreefunctions.h"
using namespace BlackMisc;
namespace BlackGui
{
namespace Models
{
/*
* Constructor
*/
CNameVariantPairModel::CNameVariantPairModel(QObject *parent) : CListModelBase("ViewNameVariantPairList", parent)
{
this->m_columns.addColumn(CColumn("name", CNameVariantPair::IndexName));
this->m_columns.addColumn(CColumn("value", CNameVariantPair::IndexVariant));
// default sort order
this->setSortColumnByPropertyIndex(CNameVariantPair::IndexName);
this->m_sortOrder = Qt::AscendingOrder;
// force strings for translation in resource files
(void)QT_TRANSLATE_NOOP("ViewNameVariantPairList", "name");
(void)QT_TRANSLATE_NOOP("ViewNameVariantPairList", "value");
}
}
}

View File

@@ -0,0 +1,45 @@
/* Copyright (C) 2013
* Swift Project Community / Contributors
*
* This file is part of swift Project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of Swift Project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
//! \file
#ifndef BLACKGUI_NAMEVARIANTLISTMODEL_H
#define BLACKGUI_NAMEVARIANTLISTMODEL_H
#include "blackmisc/namevariantpairlist.h"
#include "blackgui/models/listmodelbase.h"
#include <QAbstractItemModel>
#include <QMap>
namespace BlackGui
{
namespace Models
{
/*!
* Simple model displaying name / variant values
*/
class CNameVariantPairModel : public CListModelBase<BlackMisc::CNameVariantPair, BlackMisc::CNameVariantPairList>
{
public:
//! Constructor
explicit CNameVariantPairModel(QObject *parent = nullptr);
//! Constructor
explicit CNameVariantPairModel(const BlackMisc::CNameVariantPairList &nameValues, QObject *parent = nullptr);
//! Destructor
virtual ~CNameVariantPairModel() {}
};
}
}
#endif // guard

View File

@@ -0,0 +1,32 @@
/* Copyright (C) 2013
* swift Project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of Swift Project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "namevariantpairview.h"
#include <QHeaderView>
using namespace BlackMisc;
using namespace BlackGui::Models;
namespace BlackGui
{
namespace Views
{
CNameVariantPairView::CNameVariantPairView(QWidget *parent) : CViewBase(parent)
{
this->m_model = new CNameVariantPairModel(this);
this->setModel(this->m_model); // via QTableView
this->m_model->setSortColumnByPropertyIndex(BlackMisc::CNameVariantPair::IndexName);
if (this->m_model->hasValidSortColumn())
this->horizontalHeader()->setSortIndicator(
this->m_model->getSortColumn(),
this->m_model->getSortOrder());
this->horizontalHeader()->setStretchLastSection(true);
}
}
}

View File

@@ -0,0 +1,32 @@
/* Copyright (C) 2013
* swift Project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of Swift Project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#ifndef BLACKGUI_NAMEVARIANTPAIRVIEW_H
#define BLACKGUI_NAMEVARIANTPAIRVIEW_H
//! \file
#include "viewbase.h"
#include "../models/namevariantpairlistmodel.h"
namespace BlackGui
{
namespace Views
{
//! User view
class CNameVariantPairView : public CViewBase<Models::CNameVariantPairModel>
{
public:
//! Constructor
explicit CNameVariantPairView(QWidget *parent = nullptr);
};
}
}
#endif // guard

View File

@@ -12,6 +12,7 @@
#include "settingsblackmiscclasses.h"
#include "hwallclasses.h"
#include "indexvariantmap.h"
#include "namevariantpairlist.h"
#include "variant.h"
#include "statusmessagelist.h"
#include "audioallclasses.h"
@@ -144,6 +145,8 @@ void BlackMisc::registerMetadata()
{
CVariant::registerMetadata();
CIndexVariantMap::registerMetadata();
CNameVariantPair::registerMetadata();
CNameVariantPairList::registerMetadata();
CStatusMessage::registerMetadata();
CStatusMessageList::registerMetadata();
@@ -387,7 +390,6 @@ QVariant BlackMisc::complexQtTypeFromDbusArgument(const QDBusArgument &argument,
*/
size_t BlackMisc::heapSizeOf(const QMetaType &metaType)
{
metaType.destroy(metaType.create()); // ignore one-off allocations of a class being instantiated for the first time
_CrtMemState oldState, newState, diff;
oldState.lTotalCount = newState.lTotalCount = diff.lTotalCount = 0; // avoid compiler warning

View File

@@ -0,0 +1,172 @@
/* Copyright (C) 2013
* swift Project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of Swift Project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "namevariantpair.h"
#include "blackmisc/blackmiscfreefunctions.h"
namespace BlackMisc
{
/*
* Constructor
*/
CNameVariantPair::CNameVariantPair(const QString &name, const CVariant &variant)
: m_name(name), m_variant(variant)
{ }
/*
* Convert to string
*/
QString CNameVariantPair::convertToQString(bool i18n) const
{
QString s(this->m_name);
s.append(" ").append(this->m_variant.toString(i18n));
return s;
}
/*
* Marshall to DBus
*/
void CNameVariantPair::marshallToDbus(QDBusArgument &argument) const
{
argument << TupleConverter<CNameVariantPair>::toTuple(*this);
}
/*
* Unmarshall from DBus
*/
void CNameVariantPair::unmarshallFromDbus(const QDBusArgument &argument)
{
argument >> TupleConverter<CNameVariantPair>::toTuple(*this);
}
/*
* Equal?
*/
bool CNameVariantPair::operator ==(const CNameVariantPair &other) const
{
if (this == &other) return true;
return TupleConverter<CNameVariantPair>::toTuple(*this) == TupleConverter<CNameVariantPair>::toTuple(other);
}
/*
* Unequal?
*/
bool CNameVariantPair::operator !=(const CNameVariantPair &other) const
{
return !((*this) == other);
}
/*
* Hash
*/
uint CNameVariantPair::getValueHash() const
{
return qHash(TupleConverter<CNameVariantPair>::toTuple(*this));
}
/*
* metaTypeId
*/
int CNameVariantPair::getMetaTypeId() const
{
return qMetaTypeId<CNameVariantPair>();
}
/*
* is a
*/
bool CNameVariantPair::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<CNameVariantPair>()) { return true; }
return this->CValueObject::isA(metaTypeId);
}
/*
* Compare
*/
int CNameVariantPair::compareImpl(const CValueObject &otherBase) const
{
const auto &other = static_cast<const CNameVariantPair &>(otherBase);
return compare(TupleConverter<CNameVariantPair>::toTuple(*this), TupleConverter<CNameVariantPair>::toTuple(other));
}
/*
* Property by index
*/
QVariant CNameVariantPair::propertyByIndex(int index) const
{
switch (index)
{
case IndexName:
return QVariant(this->m_name);
case IndexVariant:
return this->m_variant.toQVariant();
default:
break;
}
Q_ASSERT_X(false, "CNameVariantPair", "index unknown");
QString m = QString("no property, index ").append(QString::number(index));
return QVariant::fromValue(m);
}
/*
* Property by index (setter)
*/
void CNameVariantPair::setPropertyByIndex(const QVariant &variant, int index)
{
switch (index)
{
case IndexName:
this->setName(variant.value<QString>());
break;
case IndexVariant:
this->m_variant = variant;
break;
default:
Q_ASSERT_X(false, "CNameVariantPair", "index unknown");
break;
}
}
/*
* Register metadata
*/
void CNameVariantPair::registerMetadata()
{
qRegisterMetaType<CNameVariantPair>();
qDBusRegisterMetaType<CNameVariantPair>();
}
/*
* To JSON
*/
QJsonObject CNameVariantPair::toJson() const
{
return BlackMisc::serializeJson(TupleConverter<CNameVariantPair>::toMetaTuple(*this));
}
/*
* From JSON
*/
void CNameVariantPair::fromJson(const QJsonObject &json)
{
BlackMisc::deserializeJson(json, TupleConverter<CNameVariantPair>::toMetaTuple(*this));
}
/*
* Members
*/
const QStringList &CNameVariantPair::jsonMembers()
{
return TupleConverter<CNameVariantPair>::jsonMembers();
}
} // namespace

View File

@@ -0,0 +1,113 @@
/* Copyright (C) 2013
* swift Project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of Swift Project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
//! \file
#ifndef BLACKMISC_NAMEVARIANTPAIR_H
#define BLACKMISC_NAMEVARIANTPAIR_H
#include "variant.h"
#include "valueobject.h"
namespace BlackMisc
{
/*!
* Value / variant pair
*/
class CNameVariantPair : public BlackMisc::CValueObject
{
public:
//! Default constructor.
CNameVariantPair() {}
//! Constructor.
CNameVariantPair(const QString &name, const CVariant &variant);
//! \copydoc CValueObject::toQVariant
virtual QVariant toQVariant() const override
{
return QVariant::fromValue(*this);
}
//! Get name.
const QString &getName() const { return m_name; }
//! Get variant.
CVariant getVariant() const { return m_variant; }
//! Set name.
void setName(const QString &name) { this->m_name = name; }
//! Set variant.
void setVariant(const CVariant &variant) { m_variant = variant; }
//! Equal operator ==
bool operator ==(const CNameVariantPair &other) const;
//! Unequal operator !=
bool operator !=(const CNameVariantPair &other) const;
//! \copydoc CValueObject::getValueHash
virtual uint getValueHash() const override;
//! \copydoc CValueObject::toJson
virtual QJsonObject toJson() const override;
//! \copydoc CValueObject::fromJson
virtual void fromJson(const QJsonObject &json) override;
//! Register metadata
static void registerMetadata();
//! Members
static const QStringList &jsonMembers();
//! Properties by index
enum ColumnIndex
{
IndexName = 0,
IndexVariant,
};
//! \copydoc CValueObject::propertyByIndex()
virtual QVariant propertyByIndex(int index) const override;
//! \copydoc CValueObject::setPropertyByIndex(variant, index)
virtual void setPropertyByIndex(const QVariant &variant, int index) override;
protected:
//! \copydoc CValueObject::convertToQString()
virtual QString convertToQString(bool i18n = false) const override;
//! \copydoc CValueObject::getMetaTypeId
virtual int getMetaTypeId() const override;
//! \copydoc CValueObject::isA
virtual bool isA(int metaTypeId) const override;
//! \copydoc CValueObject::compareImpl
virtual int compareImpl(const CValueObject &other) const override;
//! \copydoc CValueObject::marshallToDbus()
virtual void marshallToDbus(QDBusArgument &argument) const override;
//! \copydoc CValueObject::marshallFromDbus()
virtual void unmarshallFromDbus(const QDBusArgument &argument) override;
private:
BLACK_ENABLE_TUPLE_CONVERSION(CNameVariantPair)
QString m_name;
CVariant m_variant;
};
} // namespace
BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::CNameVariantPair, (o.m_name, o.m_variant))
Q_DECLARE_METATYPE(BlackMisc::CNameVariantPair)
#endif // guard

View File

@@ -0,0 +1,39 @@
/* Copyright (C) 2013
* swift Project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of Swift Project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "namevariantpairlist.h"
#include "predicates.h"
namespace BlackMisc
{
/*
* Empty constructor
*/
CNameVariantPairList::CNameVariantPairList() { }
/*
* Construct from base class object
*/
CNameVariantPairList::CNameVariantPairList(const CSequence<CNameVariantPair> &other) :
CSequence<CNameVariantPair>(other)
{ }
/*
* Register metadata
*/
void CNameVariantPairList::registerMetadata()
{
qRegisterMetaType<BlackMisc::CSequence<CNameVariantPair>>();
qDBusRegisterMetaType<BlackMisc::CSequence<CNameVariantPair>>();
qRegisterMetaType<BlackMisc::CCollection<CNameVariantPair>>();
qDBusRegisterMetaType<BlackMisc::CCollection<CNameVariantPair>>();
qRegisterMetaType<CNameVariantPairList>();
qDBusRegisterMetaType<CNameVariantPairList>();
}
} // namespace

View File

@@ -0,0 +1,46 @@
/* Copyright (C) 2013
* swift Project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of Swift Project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
//! \file
#ifndef BLACKMISC_NAMEVARIANPAIRTLIST_H
#define BLACKMISC_NAMEVARIANPAIRTLIST_H
#include "namevariantpair.h"
#include "collection.h"
#include "sequence.h"
namespace BlackMisc
{
/*!
* Value object encapsulating a list of name/variant pairs.
*/
class CNameVariantPairList : public CSequence<CNameVariantPair>
{
public:
//! Default constructor.
CNameVariantPairList();
//! Construct from a base class object.
CNameVariantPairList(const CSequence<CNameVariantPair> &other);
//! CValueObject::toQVariant()
virtual QVariant toQVariant() const override { return QVariant::fromValue(*this); }
//! Register metadata
static void registerMetadata();
};
} //namespace
Q_DECLARE_METATYPE(BlackMisc::CNameVariantPairList)
Q_DECLARE_METATYPE(BlackMisc::CCollection<BlackMisc::CNameVariantPair>)
Q_DECLARE_METATYPE(BlackMisc::CSequence<BlackMisc::CNameVariantPair>)
#endif //guard

View File

@@ -1,7 +1,11 @@
/* Copyright (C) 2014 VATSIM Community / authors
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* Copyright (C) 2013
* swift Project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of Swift Project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "variant.h"
#include "blackmiscfreefunctions.h"
@@ -23,14 +27,131 @@ namespace BlackMisc
if (type() == QVariant::UserType)
{
const CValueObject *s = CValueObject::fromQVariant(m_v); // FIXME this will return garbage if value is not a CValueObject
Q_ASSERT(s);
if (s)
{
return s->toQString(i18n);
}
else
{
return "No CValueObject, no string conversion";
}
}
return m_v.toString();
}
QJsonObject CVariant::toJson() const
{
QJsonObject json;
json.insert("type", static_cast<int>(this->type())); // type
json.insert("usertype", this->userType()); // user type
json.insert("typename", this->typeName()); // as tring, mainly for debugging, readablity
json.insert("value", this->toString(false));
return json;
}
void CVariant::fromJson(const QJsonObject &json)
{
int type = json.value("type").toInt(-1);
int userType = json.value("usertype").toInt(-1);
QString typeName = json.value("typename").toString();
QString value = json.value("value").toString();
// KB: Not yet implemented, but would be possible IMHO
Q_ASSERT(false);
qDebug() << type << userType << typeName << value;
}
uint CVariant::getValueHash() const
{
uint h = 0;
if (!this->isValid() || this->isNull())
{
QString hs;
hs.sprintf("%p", this);
h = ::qHash(hs);
}
else
{
QVariant qv = this->toQVariant();
switch (qv.type())
{
case QVariant::Int:
h = ::qHash(qv.toInt());
break;
case QVariant::UInt:
h = ::qHash(qv.toUInt());
break;
case QVariant::Bool:
h = ::qHash(qv.toUInt());
break;
case QVariant::Double:
h = ::qHash(qv.toUInt());
break;
case QVariant::LongLong:
h = ::qHash(qv.toLongLong());
break;
case QVariant::ULongLong:
h = ::qHash(qv.toULongLong());
break;
case QVariant::String:
h = ::qHash(qv.toString());
break;
case QVariant::Char:
h = ::qHash(qv.toChar());
break;
case QVariant::StringList:
h = ::qHash(qv.toString());
break;
case QVariant::ByteArray:
h = ::qHash(qv.toByteArray());
break;
case QVariant::Date:
case QVariant::Time:
case QVariant::DateTime:
case QVariant::Url:
case QVariant::Locale:
case QVariant::RegExp:
h = ::qHash(qv.toString());
break;
case QVariant::Map:
case QVariant::List:
case QVariant::BitArray:
case QVariant::Size:
case QVariant::SizeF:
case QVariant::Rect:
case QVariant::LineF:
case QVariant::Line:
case QVariant::RectF:
case QVariant::Point:
case QVariant::PointF:
case QVariant::UserType:
case QVariant::Invalid:
h = 2; // known, but not supported
break;
default:
{
// value object?
const QVariant qv = this->toQVariant();
const CValueObject *cv = CValueObject::fromQVariant(qv);
if (cv)
{
h = cv->getValueHash();
}
else
{
// no value object
QString hs;
hs.sprintf("%p", this);
h = ::qHash(hs);
}
}
break;
}
}
return h;
}
QDBusArgument &operator <<(QDBusArgument &arg, const CVariant &var)
{
arg.beginStructure();
@@ -51,4 +172,5 @@ namespace BlackMisc
return arg;
}
} // namespace
} // namespace

View File

@@ -14,11 +14,16 @@
#include <QVariant>
#include <QDateTime>
#include <QJsonValueRef>
#include <QJsonValue>
#include <QJsonObject>
#include <QJsonArray>
class QDBusArgument;
namespace BlackMisc
{
// KB: Would it make sense to turn CVariant into an CValueObject? #307
/*!
* Wrapper class for QVariant, for more natural and transparent DBus integration.
@@ -47,6 +52,9 @@ namespace BlackMisc
//! Construct a variant from the given type and opaque pointer.
CVariant(int typeId, const void *copy) : m_v(typeId, copy) {}
//! Value hash
uint getValueHash() const;
//! Change the internal QVariant.
void reset(const QVariant &var) { m_v = var; }
@@ -134,6 +142,12 @@ namespace BlackMisc
//! Return the metatype ID of the value in this variant.
int userType() const { return m_v.userType(); }
//! To JSON
QJsonObject toJson() const;
//! From JSON
void fromJson(const QJsonObject &json);
//! Equal operator.
bool operator ==(const CVariant &other) const { return m_v == other.m_v; }
@@ -165,6 +179,57 @@ namespace BlackMisc
//! Unmarshall a variant from DBus.
const QDBusArgument &operator >>(const QDBusArgument &arg, CVariant &var);
//! Non member, non friend operator >> for JSON
inline QJsonArray &operator<<(QJsonArray &json, const BlackMisc::CVariant &variant)
{
json.append(variant.toJson());
return json;
}
/*!
* \brief Non member, non friend operator << for JSON
* \param json
* \param value as pair name/value
* \return
*/
inline QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, BlackMisc::CVariant> &value)
{
json.insert(value.first, QJsonValue(value.second.toJson()));
return json;
}
//! Non member, non friend operator >> for JSON
inline const QJsonObject &operator>>(const QJsonObject &json, BlackMisc::CVariant &variant)
{
variant.fromJson(json);
return json;
}
//! Non member, non friend operator >> for JSON
inline const QJsonValue &operator>>(const QJsonValue &json, BlackMisc::CVariant &variant)
{
variant.fromJson(json.toObject());
return json;
}
//! Non member, non friend operator >> for JSON
inline const QJsonValueRef &operator>>(const QJsonValueRef &json, BlackMisc::CVariant &variant)
{
variant.fromJson(json.toObject());
return json;
}
//! qHash overload, needed for storing CVariant with tupel system
inline uint qHash(const BlackMisc::CVariant &value, uint seed = 0)
{
return ::qHash(value.getValueHash(), seed);
}
// Needed so that our qHash overload doesn't hide the qHash overloads in the global namespace.
// This will be safe as long as no global qHash has the same signature as ours.
// Alternative would be to qualify all our invokations of the global qHash as ::qHash.
using ::qHash;
} // namespace
Q_DECLARE_METATYPE(BlackMisc::CVariant)