/*************************************************************************** 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 #include #include #include #include #include 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 { {"ItemTypeRole", ItemTypeRole}, {"ContentRole", ContentRole}, {"RenderStyleRole", RenderStyleRole}, {"EditorTypeRole", EditorTypeRole}, {"ItemFlagsRole", FlagsRole}, {"UnitTypeRole", UnitTypeRole}, {"ContentFormatRole", ContentFormatRole}, {"FlagsRoleRole", FlagsRole}, {"IconRole", IconRole}, {"FixedChoicesRole", FixedChoicesRole}, {"DataNodeRole", ContentNodeRole}, {"SheetNodeRole", 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 { // fragwürdig return QStandardItem::data( XQItem::ItemTypeRole ).value() != nullptr; } XQNodePtr XQItem::contentNode() const { return data( ContentNodeRole ).value(); } void XQItem::setContentNode( const XQNodePtr& contentNode ) { QStandardItem::setData( QVariant::fromValue(contentNode), ContentNodeRole); } XQNodePtr XQItem::sheetNode() const { // return data( SheetNodeRole ).value(); } 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(); 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(); } 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(); } 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(); } 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(); if(contentPtr) return *contentPtr; static const QString s_dummyContent("-"); return s_dummyContent; } void XQItem::setContent( const QString* content ) { setData( QVariant::fromValue(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(); } 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; } QString XQItem::dataRoleName(int role) { if( role < XQItem::NoRole && model() ) return model()->roleNames()[role]; return XQItem::fetchItemDataRoleName(role); } 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 ) { //qDebug() << " -- item set data: " << value.toString() << " for: " << role << ": " << dataRoleName(role); //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 Qt::DisplayRole : case Qt::EditRole : // return the raw, unformatted data case ContentRole: { //qDebug() << " -- item set data xxx: " << value.toString() << " for: " << role; break; QString* contentPtr = QStandardItem::data( XQItem::ContentRole ).value(); if(contentPtr) { contentPtr->operator=( value.toString() ); } return; } // what to do here? case ContentNodeRole: case SheetNodeRole: case TypeKeyRole: default: break; } QStandardItem::setData( value,role); } XQItem& XQItem::fallBackDummyItem() { static XQItem s_fallBackDummyItem; return s_fallBackDummyItem; } XQItem& XQItem::xqItemFromIndex(const QModelIndex& index) { if (index.isValid()) { const XQModel* mdl = dynamic_cast(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 ) { //if( dataRole < XQItem::NoRole) // return this->model()-> 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]; }