/*************************************************************************** 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 { {"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()} { } 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); } /* XQItem::XQItem(const XQItem& other) : QStandardItem( other ) { // QStandardItem( other ) koopiert bereits // die data() struktur } XQItem& XQItem::operator=(const XQItem& other) { if( this != &other) { // kopiert data() this->QStandardItem::operator=( other ); } return *this; } */ //! firz XQItem::~XQItem() { } //! firz XQItem* XQItem::clone() const { //return new XQItem( *this ); // this is used as invisible filling material //return new XQItem( "", XQItemType::StaticStyle ); // __fix! return new XQItem(); } //! false für ein ungültiges item. 'ungültig' heisst hier, dass nur ein //! mockup-itemtype gesetzt ist. bool XQItem::isValid() const { XQItemType* dummyType = XQItemType::staticItemType(); return QStandardItem::data( XQItem::ItemTypeRole ).value() != dummyType; } //! firz XQNodePtr XQItem::contentNode() const { return data( ContentNodeRole ).value(); } //! firz void XQItem::setContentNode( const XQNodePtr& contentNode ) { QStandardItem::setData( QVariant::fromValue(contentNode), ContentNodeRole); } //! firz XQNodePtr XQItem::sheetNode() const { // return data( SheetNodeRole ).value(); } //! firz void XQItem::setSheetNode(const XQNodePtr& sheetNode ) { QStandardItem::setData( QVariant::fromValue(sheetNode), SheetNodeRole); } //! firz bool XQItem::hasAttribute( const QString& attribKey ) const { return contentNode()->has_attribute( attribKey ); } //! firz const QString& XQItem::attribute( const QString& attribKey, const QString& defaultValue ) const { if( !hasAttribute(attribKey ) ) return defaultValue; return contentNode()->attribute( attribKey ); } //! firz bool XQItem::testAttribute( const QString& attribKey, const QString& attribValue ) const { return contentNode()->test_attribute( attribKey, attribValue ); } //! firz XQItemType& XQItem::itemType() const { XQItemType* itemTypePtr = QStandardItem::data( XQItem::ItemTypeRole ).value(); return *itemTypePtr; } //! firz void XQItem::setItemType( XQItemType* itemTypePtr ) { // der ItemType wird direkt hier gespeichert QStandardItem::setData( QVariant::fromValue(itemTypePtr), XQItem::ItemTypeRole ); } //! firz void XQItem::addFlag( Qt::ItemFlag newFlag ) { setFlags( flags() | newFlag ); } //! firz void XQItem::clearFlag( Qt::ItemFlag newFlag ) { setFlags( flags() & ~newFlag); } /// /// data() access shortcuts /// //! firz XQItem::RenderStyle XQItem::renderStyle() const { return data( RenderStyleRole ).value(); } //! firz QString XQItem::renderStyleToString() const { return XQItem::fetchRenderStyleToString( renderStyle() ); } //! firz 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(); } //! firz QString XQItem::editorTypeToString() const { return XQItem::fetchEditorTypeToString( editorType() ); } //! firz void XQItem::setEditorType(EditorType editorType) { setData( QVariant::fromValue(editorType), XQItem::EditorTypeRole); // Der EditorType wohnt im ItemType //itemType().replaceAttribute( this, EditorTypeRole, editorType ); } //! firz XQItem::UnitType XQItem::unitType() const { return data( XQItem::UnitTypeRole ).value(); } //! firz QString XQItem::unitTypeToString() const { return XQItem::fetchUnitTypeToString( unitType() ); } //! firz void XQItem::setUnitType(UnitType unitType) { setData( QVariant::fromValue(unitType), XQItem::UnitTypeRole); } //! firz 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; } //! firz void XQItem::setContent( const QString* content ) { setData( QVariant::fromValue(content), XQItem::ContentRole ); } //! firz const QString& XQItem::contentKey() const { return contentNode()->attributes().key_of( content() ); } //! gibt den content-format string zurück QString XQItem::contentFormat() const { return data( XQItem::ContentFormatRole ).toString(); } void XQItem::setContentFormat(const QString& contentFormat) { setData( QVariant::fromValue(contentFormat), XQItem::ContentFormatRole); } //! gibt das read-only auswahl-model zurück (wenn dieses item als //! combobox gerendert wird) QStandardItemModel* XQItem::fixedChoices() const { return data( XQItem::FixedChoicesRole ).value(); } //! erzeugt einen string aus den werten des read-only auswahl-models 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; } //! setzt das auswahl-model für read-only comboboxes void XQItem::setfixedChoices( QStandardItemModel* newModel ) { setData( QVariant::fromValue(newModel), XQItem::FixedChoicesRole); } //! true, wenn 'ich' ein header item bin bool XQItem::isHeaderStyle() { return renderStyle() == XQItem::HeaderStyle; } //! gibt den namen der datarole zurück QString XQItem::dataRoleName(int role) { if( role < XQItem::NoRole && model() ) return model()->roleNames()[role]; return XQItem::fetchItemDataRoleName(role); } //! angespasste variante von qstandarditem::setData. geteilte attribute //! werden vom xqitemtype geholt 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; } XQItem& XQItem::xqItemFromIndex(const QModelIndex& index) { if (index.isValid()) { const XQViewModel* 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 ) { 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]; }