/*************************************************************************** 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 XQItemTypeMap XQItemType::s_ItemTypeMap; size_t XQItemType::s_ItemTypeCount = 0; /// /// XQItemType /// XQItemType::XQItemType() : XQItem(nullptr) // vermeide rekursion { } XQItemType::XQItemType( const XQItemType& other) : XQItem( other ) { } //! destruktor, räumt das fixedChoices auf, so vorhanden. XQItemType::~XQItemType() { // das einzige property, was auch auf dem heap liegt. QStandardItemModel* choices = fixedChoices(); if( choices ) { setfixedChoices( nullptr ); delete choices; } } //! ruft QStandardItem::data auf QVariant XQItemType::data( int role ) const { return QStandardItem::data(role); } //! ruft QStandardItem::setData auf void XQItemType::setData(const QVariant& value, int role ) { //qDebug() << " --- itemType set Data:" << role << " : " << value.toString(); return QStandardItem::setData(value,role); } //! tested, ob ein attribute (z.B. unitType) hier vorhanden ist int XQItemType::roleForAttributeKey( const QString& attrKey ) { int role = XQItem::fetchItemDataRole(attrKey); // gibbed überhaupt eine rolle für unser attribut? if( role != XQItem::NoRole) { // wenn ja, ist die role hier besetzt? QVariant value = data(role); if( !value.isValid() || value.isNull() ) return XQItem::NoRole; } return role; } //! setzt einen attributwert neu. Ggf. wird ein neuer ItemType erzeugt. XQItemType* XQItemType::replaceAttribute( const QVariant& newValue, int role ) { QString msg = newValue.toString(); if( role == XQItem::IconRole ) { QIcon icn = newValue.value(); msg = XQAppData::iconName( icn ); } qDebug() << " --- Before: " << makeItemTypeKey() << " role:" << XQItem::fetchItemDataRoleName(role) << " value:" << msg; // hat sich überhaupt was geändert? QVariant oldValue = data(role); // nein, es hat nicht if( oldValue == newValue ) return this; // kopie von mir XQItemType* myClone = new XQItemType(*this); // Änderungen übernehmen myClone->setData( newValue, role ); // Gibt es den geänderten ItemType schon? QString newKey = myClone->makeItemTypeKey(); // jawoll if( s_ItemTypeMap.contains( newKey ) ) { // abräumen ... delete myClone; // und die alte version zurückgegen return s_ItemTypeMap[newKey]; } // speichern s_ItemTypeMap.insert( newKey, myClone ); qDebug() << " --- After: " << myClone->makeItemTypeKey(); /// Obacht! Der alte, geänderte itemType bleibt erhalten /// und verrottet ggf. ohne Daseinszweck return myClone; } //! formatiert den content() string eines items. QVariant XQItemType::formatText( const XQItem& item ) const { XQItem::UnitType uType = unitType(); //qDebug() << " --- formatText: " << XQItem::fetchUnitTypeToString( uType); const QString& cont = item.content(); if( uType != XQItem::NoUnitType ) return formatToSI( cont, uType ); return cont; } //! formatiert einen zahlenwert als string mit einheit. QString XQItemType::formatToSI( const QString& valueTxt, XQItem::UnitType unitType ) const { if( valueTxt.isEmpty() ) return valueTxt; if( XQItem::ISODate == unitType ) { // format iso date QDateTime dateTime = QDateTime::fromString(valueTxt, Qt::ISODate); // fixme! make this configurable! QString format = "dd.MM.yyyy HH:mm:ss"; // You can customize this format // Format the QDateTime object into a human-readable string return dateTime.toString(format); } QLocale sysLocale = QLocale::system(); sysLocale.setNumberOptions(sysLocale.numberOptions() | QLocale::OmitGroupSeparator); double dVal = sysLocale.toDouble(valueTxt); QString strVal, strPrefix; int exp = (int)::log10f(dVal); exp = (exp/3)*3; double nVal = dVal; if( !s_PrefixExponentMap.key(exp).isEmpty() ) nVal /= ::pow( 10,exp); strVal = sysLocale.toString(nVal, 'f', 2); strPrefix = s_PrefixExponentMap.key(exp); //qDebug() << " convert: " << dVal << " : " << valueTxt << ": " << strVal << ":" << exp << " : " << strPrefix << ": " << nVal; return QString("%1 %2%3").arg( strVal, strPrefix, unitTypeToString() ); } //! entfernt die einheit aus einem formatierten string QString XQItemType::unFormatFromSI(const QString& formText ) const { QString input = formText.simplified(); // #1: strip numeric part if( input.isEmpty() ) return input; int idx = 0; for( auto c : input ) { if( c.isNumber() || c.toLower() == 'e' || c == '.' || c == ',' ||c == '-' || c == '+' ) idx++; else break; } if(!idx) return QString("0"); QString numPart = formText.left(idx); QString unitPart; //if(idx + 1 < formText.size() ) unitPart = formText.right(idx - 1).simplified(); QLocale sysLocale = QLocale::system(); double dVal = sysLocale.toDouble(numPart); if( unitPart.size() > 0 ) { QString prefix = QString(unitPart[0]); if( s_PrefixExponentMap.contains(prefix) ) dVal *= std::pow( 10.0, s_PrefixExponentMap[prefix] ); } sysLocale.setNumberOptions(sysLocale.numberOptions() | QLocale::OmitGroupSeparator); QString result = sysLocale.toString(dVal, 'f', 2); //qDebug() << " convert: " << numPart << " : " << unitPart << " : " << dVal << " : " << result; return result; } /// /// --- statics -------------------------------------------------------------------------- /// //! gibt den dummy item type zurück (benutzt für null-items). XQItemType* XQItemType::staticItemType() { static XQItemType s_DummyItemType; return &s_DummyItemType; } //! erzeugt aus den eingenschaften des itemTypes einen eindeutigen schlüssel. QString XQItemType::makeItemTypeKey() { QString key("%1:%2:%3:%4:%5:%6:%7"); key = key.arg( renderStyleToString() ); key = key.arg( editorTypeToString() ); key = key.arg( unitTypeToString() ); key = key.arg( contentFormat() ); key = key.arg( itemFlagsToString() ); // icons haben leider keine namen, es sei denn, sie kommen aus einen theme //key = key.arg( icon().name() ); //key = key.arg( icon().cacheKey() ); key = key.arg( XQAppData::iconName( icon() ) ); key = key.arg( fixedChoicesToString() ); return key; }