Files
xtree.ng.zwo/items/xqitem.cpp
2025-08-13 18:30:47 +02:00

609 lines
14 KiB
C++

/***************************************************************************
source::worx xtree
Copyright © 2024-2025 c.holzheuer
christoph.holzheuer@gmail.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
***************************************************************************/
#include <xqitem.h>
#include <xqmodel.h>
#include <xqmaptor.h>
#include <QDateTime>
#include <xqitemtype.h>
#include <QDebug>
XQItem::XQItemFlagMap XQItem::s_ItemFlagMap
{
{ "NoItemFlags", Qt::NoItemFlags },
{ "IsSelectable", Qt::ItemIsSelectable },
{ "IsEditable", Qt::ItemIsEditable },
{ "IsDragEnabled", Qt::ItemIsDragEnabled },
{ "IsDropEnabled", Qt::ItemIsDropEnabled },
{ "IsUserCheckable", Qt::ItemIsUserCheckable },
{ "IsEnabled", Qt::ItemIsEnabled },
{ "IsAutoTristate", Qt::ItemIsAutoTristate },
{ "ItemNeverHasChildren", Qt::ItemNeverHasChildren },
{ "IsUserTristate", Qt::ItemIsUserTristate }
};
XQItem::XQItemDataRoleMap XQItem::s_ItemDataRoleMap
{
{"ItemType", ItemTypeRole},
{"Content", ContentRole},
{"RenderStyle", RenderStyleRole},
{"EditorType", EditorTypeRole},
{"ItemFlags", FlagsRole},
{"UnitType", UnitTypeRole},
{"ContentFormat", ContentFormatRole},
{"FlagsRole", FlagsRole},
{"Icon", IconRole},
{"FixedChoices", FixedChoicesRole},
{"DataNode", ContentNodeRole},
{"SheetNode", SheetNodeRole}
};
// No bi-map needed here, qmap.key() is sufficient for the job
XQItem::XQRenderStyleMap XQItem::s_RenderStyleMap
{
{ "NoRenderStyle", NoRenderStyle },
{ "HiddenStyle", HiddenStyle },
{ "HeaderStyle", HeaderStyle },
{ "PlainStyle", PlainStyle },
{ "CheckBoxStyle", CheckBoxStyle },
{ "ComboBoxStyle", ComboBoxStyle },
{ "TreeHeaderStyle", TreeHeaderStyle },
{ "CustomRenderStyle", CustomRenderStyle },
{ "PickerStyle", PickerStyle },
{ "SpinBoxStyle", SpinBoxStyle },
{ "ProgressBarStyle", ProgressBarStyle},
{ "FormattedStyle", FormattedStyle},
};
XQItem::XQEditorTypeMap XQItem::s_EditorTypeMap
{
{ "NoEditorType", NoEditorType },
{ "LineEditType", LineEditType },
{ "ComboBoxType", ComboBoxType },
{ "PickerType", PickerType },
{ "ProgressBarType", ProgressBarType },
{ "SpinBoxType", SpinBoxType},
{ "CustomEditorType", CustomEditorType}
};
XQItem::XQUnitTypeMap XQItem::s_UnitTypeMap
{
{ NoUnitType, "NoUnitType" },
{ Ampere, "A" },
{ Volt, "V" },
{ Ohm, "Ohm" },
{ Farad, "C" },
{ Watt, "W" },
{ WattPeak, "Wp" },
{ WattHour, "Wh" },
{ Second, "s" },
{ Percent, "%" },
{ Hertz, "Hz" },
{ Meter, "m" },
{ Kg, "kg" },
{ ISODate, "ISODate" }, // fixme: ISO-Date is present, but has no Unit ?!?
};
XQItem::XQPrefixExponentMap XQItem::s_PrefixExponentMap
{
{ "p", -12 }, // pico
{ "n", -9 }, // nano
{ "µ", -6 }, // micro
{ "m", -3 }, // Milli
{ "" , 0 }, // No prefix means multiplier of 1
//{ " ", 0 }, // No prefix means multiplier of 1
{ "k", 3 }, // Kilo
{ "M", 6 }, // Mega
{ "G", 9 }, // Giga
{ "T", 12 }, // Tera
{ "P", 15 }, // Peta
{ "E", 18 }, // Exa
{ "Z", 21 }, // Zetta
{ "Y", 24}, // Yotta
};
XQItem::XQItem()
: XQItem{XQItemType::staticItemType()}
{
setFlags(Qt::NoItemFlags);
//setText("[dummy]");
//XQItemType::setStaticType( this );
//setItemType(NTItemType::defaultItemType());
}
XQItem::XQItem( XQItemType* itemType )
: QStandardItem{}
{
setItemType( itemType );
}
XQItem::XQItem(XQItemType* itemType, const QString *content )
: XQItem{ itemType }
{
setContent(content);
}
// Warum beides?
XQItem::XQItem(XQItemType* itemType, const QString *content, const XQNodePtr& contentNode )
: XQItem{ itemType, content }
{
setContentNode(contentNode);
}
/// ------------------ forbidden fruits ------------------
XQItem::XQItem(const XQItem& other)
: QStandardItem( other )
{
// QStandardItem( other ) koopiert bereits
// die data() struktur
}
XQItem::~XQItem()
{
// fixed choices lebt im item type, also
// im parent
//QAbstractItemModel* model = fixedChoices();
//if( model )
// delete model;
}
XQItem* XQItem::clone() const
{
//return new XQItem( *this );
// this is used as invisible filling material
//return new XQItem( "", XQItemType::StaticStyle );
// __fix!
return new XQItem();
}
bool XQItem::isValid() const
{
return QStandardItem::data( XQItem::ItemTypeRole ).value<XQItemType*>() != nullptr;
}
XQNodePtr XQItem::contentNode() const
{
return data( ContentNodeRole ).value<XQNodePtr>();
}
void XQItem::setContentNode( const XQNodePtr& contentNode )
{
QStandardItem::setData( QVariant::fromValue(contentNode), ContentNodeRole);
}
XQNodePtr XQItem::sheetNode() const
{
//
return data( SheetNodeRole ).value<XQNodePtr>();
}
void XQItem::setSheetNode(const XQNodePtr& sheetNode )
{
QStandardItem::setData( QVariant::fromValue(sheetNode), SheetNodeRole);
}
bool XQItem::hasAttribute( const QString& attribKey ) const
{
return contentNode()->has_attribute( attribKey );
}
const QString& XQItem::attribute( const QString& attribKey, const QString& defaultValue ) const
{
if( !hasAttribute(attribKey ) )
return defaultValue;
return contentNode()->attribute( attribKey );
}
bool XQItem::testAttribute( const QString& attribKey, const QString& attribValue ) const
{
return contentNode()->test_attribute( attribKey, attribValue );
}
XQItemType& XQItem::itemType() const
{
XQItemType* itemTypePtr = QStandardItem::data( XQItem::ItemTypeRole ).value<XQItemType*>();
return *itemTypePtr;
}
void XQItem::setItemType( XQItemType* itemTypePtr )
{
// der ItemType wird direkt hier gespeichert
QStandardItem::setData( QVariant::fromValue(itemTypePtr), XQItem::ItemTypeRole );
}
void XQItem::addFlag( Qt::ItemFlag newFlag )
{
setFlags( flags() | newFlag );
}
void XQItem::clearFlag( Qt::ItemFlag newFlag )
{
setFlags( flags() & ~newFlag);
}
///
/// data() access shortcuts
///
XQItem::RenderStyle XQItem::renderStyle() const
{
return data( RenderStyleRole ).value<RenderStyle>();
}
QString XQItem::renderStyleToString() const
{
return XQItem::fetchRenderStyleToString( renderStyle() );
}
void XQItem::setRenderStyle(RenderStyle renderStyle )
{
setData( QVariant::fromValue(renderStyle), XQItem::RenderStyleRole );
// Der RenderStyle wohnt im ItemType
//itemType().replaceAttribute( this, RenderStyleRole, renderStyle );
}
XQItem::EditorType XQItem::editorType() const
{
return data( EditorTypeRole ).value<EditorType>();
}
QString XQItem::editorTypeToString() const
{
return XQItem::fetchEditorTypeToString( editorType() );
}
void XQItem::setEditorType(EditorType editorType)
{
setData( QVariant::fromValue(editorType), XQItem::EditorTypeRole);
// Der EditorType wohnt im ItemType
//itemType().replaceAttribute( this, EditorTypeRole, editorType );
}
XQItem::UnitType XQItem::unitType() const
{
return data( XQItem::UnitTypeRole ).value<UnitType>();
}
QString XQItem::unitTypeToString() const
{
return XQItem::fetchUnitTypeToString( unitType() );
}
void XQItem::setUnitType(UnitType unitType)
{
setData( QVariant::fromValue(unitType), XQItem::UnitTypeRole);
}
const QString& XQItem::content() const
{
const QString* contentPtr = QStandardItem::data( XQItem::ContentRole ).value<const QString*>();
if(contentPtr)
return *contentPtr;
static const QString s_dummyContent("-");
return s_dummyContent;
}
void XQItem::setContent( const QString* content )
{
setData( QVariant::fromValue<const QString*>(content), XQItem::ContentRole );
}
const QString& XQItem::contentKey() const
{
return contentNode()->attributes().key_of( content() );
}
QString XQItem::contentFormat() const
{
return data( XQItem::ContentFormatRole ).toString();
}
void XQItem::setContentFormat(const QString& contentFormat)
{
setData( QVariant::fromValue(contentFormat), XQItem::ContentFormatRole);
}
QStandardItemModel* XQItem::fixedChoices() const
{
return data( XQItem::FixedChoicesRole ).value<QStandardItemModel*>();
}
QString XQItem::fixedChoicesToString() const
{
QStandardItemModel* model = fixedChoices();
if( !model || model->rowCount() == 0)
return QString("()");
QString result = "(";
int rc = model->rowCount();
for (int row = 0; row < rc; ++row)
{
const QString text = model->item(row)->text();
result += text;
if(row < rc-1)
result += "|";
}
result += ")";
return result;
}
void XQItem::setfixedChoices( QStandardItemModel* newModel )
{
// Der RenderStyle wohnt im ItemType
setData( QVariant::fromValue(newModel), XQItem::FixedChoicesRole);
}
bool XQItem::isHeaderStyle()
{
return renderStyle() == XQItem::HeaderStyle;
}
QVariant XQItem::data(int role ) const
{
//emitDataChanged()
switch(role)
{
//
// Die im ItemType ausgelagerten Daten werden
// von da geholt.
//
case FlagsRole: // aka Qt::ItemDataRole(Qt::UserRole - 1),
case IconRole: // aka Qt::DecorationRole,
case RenderStyleRole:
case EditorTypeRole:
case UnitTypeRole:
case ContentFormatRole:
case FixedChoicesRole:
{
return itemType().data(role);
}
// Das ist der Sonderfall, hier dereferenzieren wir den
// Zeiger auf den QString* aus unserem XQNodePtr
case Qt::DisplayRole :
case Qt::EditRole :
case XQItem::ContentRole:
{
return content();
}
case Qt::ToolTipRole:
{
return content() + ":" + itemType().text() + ":" + renderStyleToString();
}
//
// Die lokal verwalteten Resourcen werden über QStandardItem::data(role)
// abgewickelt.
//
case ContentNodeRole:
{
// Das Node-Besitzer-Item wohnt in der ersten Spalte,
// wenn wir also der Node-Besitzer item sind ...
if( column() == 0)
return QStandardItem::data( XQItem::ContentNodeRole );
// sonst: delegieren an den node-Besitzer
QModelIndex pIndex = model()->index( row(), 0 );
XQItem& firstItem = xqItemFromIndex( pIndex );
return firstItem.data( XQItem::ContentNodeRole );
}
case Qt::StatusTipRole:
case Qt::WhatsThisRole:
case Qt::SizeHintRole:
case Qt::FontRole:
case Qt::TextAlignmentRole:
case Qt::BackgroundRole:
case Qt::ForegroundRole:
case Qt::CheckStateRole:
case Qt::InitialSortOrderRole:
default:
break;
}
return QStandardItem::data(role);
}
void XQItem::setData(const QVariant& value, int role )
{
//replaceAttribute( XQItem* item, XQItem::ItemDataRole role, const QVariant& newValue)
//emitDataChanged()
switch(role)
{
// das ist ein pointer auf den original-string aus dem XML
// ContentRole :
// ItemTypeRole :
case RenderStyleRole :
case EditorTypeRole :
case UnitTypeRole:
case ContentFormatRole:
case FlagsRole:
case IconRole:
case FixedChoicesRole:
//qDebug() << " ---call type set Data: " << role << ": " << XQItem::fetchItemDataRoleName(role) << ":" << value.toString();
itemType().replaceAttribute( this, value, role );
break;
case ContentNodeRole:
case SheetNodeRole:
case TypeKeyRole:
case Qt::DisplayRole :
case Qt::EditRole :
// return the raw, unformatted data
case ContentRole:
default:
QStandardItem::setData( value,role);
}
}
XQItem& XQItem::fallBackDummyItem()
{
static XQItem s_fallBackDummyItem;
return s_fallBackDummyItem;
}
const XQItem& XQItem::xqConstItemFromIndex(const QModelIndex& index)
{
if (index.isValid())
{
const XQModel* mdl = dynamic_cast<const XQModel*>(index.model());
if (mdl)
return mdl->xqConstItemFromIndex(index);
}
return fallBackDummyItem();
}
XQItem& XQItem::xqItemFromIndex(const QModelIndex& index)
{
if (index.isValid())
{
const XQModel* mdl = dynamic_cast<const XQModel*>(index.model());
if (mdl)
return mdl->xqItemFromIndex(index);
}
return fallBackDummyItem();
}
int XQItem::fetchItemDataRole( const QString& dataRoleKey )
{
if(!dataRoleKey.isEmpty() && s_ItemDataRoleMap.contains(dataRoleKey) )
return s_ItemDataRoleMap[ dataRoleKey ];
return NoRole;
}
QString XQItem::fetchItemDataRoleName( int dataRole )
{
return s_ItemDataRoleMap.key(dataRole);
}
Qt::ItemFlag XQItem::fetchItemFlag( const QString& flagKey )
{
if(!flagKey.isEmpty() && s_ItemFlagMap.contains(flagKey) )
return Qt::ItemFlag( s_ItemFlagMap[ flagKey ] );
return Qt::NoItemFlags;
}
QString XQItem::fetchItemFlagName( int flag )
{
return s_ItemFlagMap.key(flag);
}
XQItem::RenderStyle XQItem::fetchRenderStyle(const QString& styleKey )
{
if(!styleKey.isEmpty() && s_RenderStyleMap.contains(styleKey) )
return s_RenderStyleMap[styleKey];
return NoRenderStyle;
}
QString XQItem::fetchRenderStyleToString(XQItem::RenderStyle renderStyle )
{
return s_RenderStyleMap.key(renderStyle);
}
XQItem::EditorType XQItem::fetchEditorType( const QString& editorTypeKey )
{
if(!editorTypeKey.isEmpty() && s_EditorTypeMap.contains(editorTypeKey) )
return s_EditorTypeMap[editorTypeKey];
return NoEditorType;
}
QString XQItem::fetchEditorTypeToString( EditorType editorType )
{
return s_EditorTypeMap.key(editorType);
}
XQItem::UnitType XQItem::fetchUnitType(const QString& unitTypeKey)
{
return s_UnitTypeMap.key(unitTypeKey);
}
QString XQItem::fetchUnitTypeToString( UnitType unitType)
{
return s_UnitTypeMap[unitType];
}