609 lines
14 KiB
C++
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];
|
|
}
|
|
|
|
|
|
|