QStandardItem setData does not work
-
I need to associate one of 2 some custom data structs with each QStandardItem in a tree. Each item represents a leaf in QTreeView's QStandardItemModel, and I do not want to subclass the QStandardItem to add this extra data as I should be able so save it in item directly with:
void setData(const QVariant &value, int role = Qt::UserRole + 1)Normally I would use a simple QVariant to store something like a simple string or something else in the QStandardItem, however this time since I need to associate one of the 2 structs below as alternative types (and neither of these 2 structs has a default constructor as required by a QVariant), I needed to use introduce a std::variant with a default std::monotype as the default variant type as a QVariant wrapper. QVariant has a converter from this std::variant QVariant fromStdVariant(const std::variant<Types...> &value) to a QVariant. Unfortunately after retrieving the value later by calling item->data().value<PortVariant>(); always results in a std::monotype value from the variant.
const auto& portVariant = item->data().value<PortVariant>();
I set the data this way
// searchable portID name - used for coloring PortVariant portVariant = port; portItem->setData(QVariant::fromStdVariant(portVariant));and I retrieve it later this way, however it always contains the default std::monotype
const auto& portVariant = item->data().value<PortVariant>();using PortVariant = std::variant<std::monostate, RxMessagePort, TxMessagePort>;The RxMessagePort and TxMesssgePort are similar structs with explicit constructors
using RxMessagePort = struct RxMessagePort { /** * Explicit constructor. * * @param name [in] RxMessagePort name. * @param portId [in] RxMessagePort identifier. * @param network [in] A, B or Both network identifier. * @param rxSapUdpPort [in] receive SapUdpPort. */ constexpr explicit RxMessagePort( std::string name, const unsigned portId, const A664Network network, RxSapUdpPort rxSapUdpPort) : mName{ std::move(name) } , mPortId{ portId } , mNetwork{ network } , mRxSapUdpPort{ std::move(rxSapUdpPort) } {} std::string mName; unsigned mPortId; A664Network mNetwork; RxSapUdpPort mRxSapUdpPort; };and
using TxMessagePort = struct TxMessagePort { /** * SapUdp TxMessagePort. * * @param name [in] Port name. * @param portId [in] Port ID. * @param txSapUdpPort [in] txSapUdpPort. */ constexpr explicit TxMessagePort( std::string name, const unsigned portId, TxSapUdpPort txSapUdpPort) : mName{ std::move(name) } , mPortId{ portId } , mTxSapUdpPort{ std::move(txSapUdpPort) } {} std::string mName; unsigned mPortId; TxSapUdpPort mTxSapUdpPort; }; -
I need to associate one of 2 some custom data structs with each QStandardItem in a tree. Each item represents a leaf in QTreeView's QStandardItemModel, and I do not want to subclass the QStandardItem to add this extra data as I should be able so save it in item directly with:
void setData(const QVariant &value, int role = Qt::UserRole + 1)Normally I would use a simple QVariant to store something like a simple string or something else in the QStandardItem, however this time since I need to associate one of the 2 structs below as alternative types (and neither of these 2 structs has a default constructor as required by a QVariant), I needed to use introduce a std::variant with a default std::monotype as the default variant type as a QVariant wrapper. QVariant has a converter from this std::variant QVariant fromStdVariant(const std::variant<Types...> &value) to a QVariant. Unfortunately after retrieving the value later by calling item->data().value<PortVariant>(); always results in a std::monotype value from the variant.
const auto& portVariant = item->data().value<PortVariant>();
I set the data this way
// searchable portID name - used for coloring PortVariant portVariant = port; portItem->setData(QVariant::fromStdVariant(portVariant));and I retrieve it later this way, however it always contains the default std::monotype
const auto& portVariant = item->data().value<PortVariant>();using PortVariant = std::variant<std::monostate, RxMessagePort, TxMessagePort>;The RxMessagePort and TxMesssgePort are similar structs with explicit constructors
using RxMessagePort = struct RxMessagePort { /** * Explicit constructor. * * @param name [in] RxMessagePort name. * @param portId [in] RxMessagePort identifier. * @param network [in] A, B or Both network identifier. * @param rxSapUdpPort [in] receive SapUdpPort. */ constexpr explicit RxMessagePort( std::string name, const unsigned portId, const A664Network network, RxSapUdpPort rxSapUdpPort) : mName{ std::move(name) } , mPortId{ portId } , mNetwork{ network } , mRxSapUdpPort{ std::move(rxSapUdpPort) } {} std::string mName; unsigned mPortId; A664Network mNetwork; RxSapUdpPort mRxSapUdpPort; };and
using TxMessagePort = struct TxMessagePort { /** * SapUdp TxMessagePort. * * @param name [in] Port name. * @param portId [in] Port ID. * @param txSapUdpPort [in] txSapUdpPort. */ constexpr explicit TxMessagePort( std::string name, const unsigned portId, TxSapUdpPort txSapUdpPort) : mName{ std::move(name) } , mPortId{ portId } , mTxSapUdpPort{ std::move(txSapUdpPort) } {} std::string mName; unsigned mPortId; TxSapUdpPort mTxSapUdpPort; };@johnco3
I'm afraid I know nothing aboutstd::variant, but a couple of observations.Your
setData()isvoid.QStandardItemModel's isbool. Have you checked the return result when you call that, you never know if it might be barfing?Your
setData()defaults toQt::UserRole + 1. How does youritem->data().value<PortVariant>()pass that role to fetch?setData()copies its argument. I assume the equivalent code to test would be something like:PortVariant portVariant = port; QVariant v = QVariant::fromStdVariant(portVariant); QVariant v2 = v1; const auto& portVariant = v2.value<PortVariant>();How does that come out? You might also call
QVariant::canConvert<>()to check, including on youritem->data().I assume all the various component types in your
structs are serializable toQVariantwithout further registration.