2025-08-05 22:39:41 +02:00
|
|
|
/***************************************************************************
|
|
|
|
|
|
|
|
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 <cmath>
|
|
|
|
#include <xqitemtype.h>
|
|
|
|
|
|
|
|
#include <QDateTime>
|
|
|
|
#include <QDebug>
|
|
|
|
|
|
|
|
XQItemTypeMap XQItemType::s_ItemTypeMap;
|
|
|
|
size_t XQItemType::s_ItemTypeCount = 0;
|
|
|
|
|
|
|
|
///
|
|
|
|
/// XQItemType
|
|
|
|
///
|
|
|
|
|
|
|
|
|
|
|
|
XQItemType::XQItemType()
|
|
|
|
: XQItem(nullptr) // vermeide rekursion
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
XQItemType::XQItemType( const XQItemType& other)
|
|
|
|
: XQItem( other )
|
|
|
|
{
|
2025-08-08 21:39:33 +02:00
|
|
|
}
|
2025-08-05 22:39:41 +02:00
|
|
|
|
|
|
|
|
2025-08-08 21:39:33 +02:00
|
|
|
//! destruktor, räumt das fixedChoices auf, so vorhanden.
|
2025-08-05 22:39:41 +02:00
|
|
|
|
|
|
|
XQItemType::~XQItemType()
|
|
|
|
{
|
2025-08-08 21:39:33 +02:00
|
|
|
// das einzige property, was auch auf dem heap liegt.
|
|
|
|
QStandardItemModel* choices = fixedChoices();
|
|
|
|
if( choices )
|
|
|
|
{
|
|
|
|
setfixedChoices( nullptr );
|
|
|
|
delete choices;
|
|
|
|
}
|
2025-08-05 22:39:41 +02:00
|
|
|
}
|
|
|
|
|
2025-08-08 21:39:33 +02:00
|
|
|
|
|
|
|
//! ruft QStandardItem::data auf
|
|
|
|
|
2025-08-05 22:39:41 +02:00
|
|
|
QVariant XQItemType::data( int role ) const
|
|
|
|
{
|
|
|
|
return QStandardItem::data(role);
|
|
|
|
}
|
|
|
|
|
2025-08-08 21:39:33 +02:00
|
|
|
|
|
|
|
//! ruft QStandardItem::setData auf
|
|
|
|
|
2025-08-09 07:45:32 +02:00
|
|
|
void XQItemType::setData(const QVariant& value, int role )
|
2025-08-05 22:39:41 +02:00
|
|
|
{
|
2025-08-14 19:13:53 +02:00
|
|
|
//qDebug() << " --- itemType set Data:" << role << " : " << value.toString();
|
2025-08-05 22:39:41 +02:00
|
|
|
return QStandardItem::setData(value,role);
|
|
|
|
}
|
|
|
|
|
2025-08-09 11:56:11 +02:00
|
|
|
//! tested, ob ein attribute (z.B. unitType) hier vorhanden ist
|
2025-08-15 20:31:40 +02:00
|
|
|
int XQItemType::roleForAttributeKey( const QString& attrKey )
|
2025-08-09 11:56:11 +02:00
|
|
|
{
|
|
|
|
int role = XQItem::fetchItemDataRole(attrKey);
|
|
|
|
// gibbed überhaupt eine rolle für unser attribut?
|
2025-08-15 20:31:40 +02:00
|
|
|
if( role != XQItem::NoRole)
|
|
|
|
{
|
|
|
|
// wenn ja, ist die role hier besetzt?
|
|
|
|
QVariant value = data(role);
|
|
|
|
if( !value.isValid() || value.isNull() )
|
|
|
|
return XQItem::NoRole;
|
|
|
|
}
|
2025-08-09 11:56:11 +02:00
|
|
|
return role;
|
|
|
|
}
|
|
|
|
|
2025-08-08 21:39:33 +02:00
|
|
|
|
|
|
|
//! setzt einen attributwert neu. Ggf. wird ein neuer ItemType erzeugt.
|
|
|
|
|
2025-08-09 11:56:11 +02:00
|
|
|
XQItemType* XQItemType::replaceAttribute( const QVariant& newValue, int role )
|
2025-08-05 22:39:41 +02:00
|
|
|
{
|
2025-08-09 11:56:11 +02:00
|
|
|
|
2025-08-15 20:55:53 +02:00
|
|
|
QString msg = newValue.toString();
|
|
|
|
if( role == XQItem::IconRole )
|
|
|
|
{
|
|
|
|
QIcon icn = newValue.value<QIcon>();
|
|
|
|
msg = XQAppData::iconName( icn );
|
|
|
|
}
|
|
|
|
|
2025-08-16 16:39:23 +02:00
|
|
|
//qDebug() << " --- Before: " << makeItemTypeKey() << " role:" << XQItem::fetchItemDataRoleName(role) << " value:" << msg;
|
2025-08-15 20:55:53 +02:00
|
|
|
|
2025-08-05 22:39:41 +02:00
|
|
|
// hat sich überhaupt was geändert?
|
|
|
|
QVariant oldValue = data(role);
|
2025-08-09 11:56:11 +02:00
|
|
|
|
|
|
|
// 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 ) )
|
2025-08-05 22:39:41 +02:00
|
|
|
{
|
2025-08-09 11:56:11 +02:00
|
|
|
// abräumen ...
|
|
|
|
delete myClone;
|
|
|
|
// und die alte version zurückgegen
|
|
|
|
return s_ItemTypeMap[newKey];
|
2025-08-05 22:39:41 +02:00
|
|
|
}
|
2025-08-09 11:56:11 +02:00
|
|
|
|
|
|
|
// speichern
|
|
|
|
s_ItemTypeMap.insert( newKey, myClone );
|
2025-08-15 20:31:40 +02:00
|
|
|
|
2025-08-16 16:39:23 +02:00
|
|
|
//qDebug() << " --- After: " << myClone->makeItemTypeKey();
|
2025-08-09 11:56:11 +02:00
|
|
|
|
|
|
|
/// Obacht! Der alte, geänderte itemType bleibt erhalten
|
|
|
|
/// und verrottet ggf. ohne Daseinszweck
|
|
|
|
|
|
|
|
return myClone;
|
|
|
|
|
2025-08-05 22:39:41 +02:00
|
|
|
}
|
|
|
|
|
2025-08-11 22:27:55 +02:00
|
|
|
|
|
|
|
//! formatiert den content() string eines items.
|
|
|
|
|
2025-08-08 21:39:33 +02:00
|
|
|
QVariant XQItemType::formatText( const XQItem& item ) const
|
|
|
|
{
|
2025-08-09 07:45:32 +02:00
|
|
|
XQItem::UnitType uType = unitType();
|
2025-08-15 20:31:40 +02:00
|
|
|
//qDebug() << " --- formatText: " << XQItem::fetchUnitTypeToString( uType);
|
2025-08-20 17:37:14 +02:00
|
|
|
const QString& cont = item.rawText();
|
2025-08-09 07:45:32 +02:00
|
|
|
if( uType != XQItem::NoUnitType )
|
|
|
|
return formatToSI( cont, uType );
|
|
|
|
return cont;
|
2025-08-08 21:39:33 +02:00
|
|
|
}
|
|
|
|
|
2025-08-11 22:27:55 +02:00
|
|
|
|
|
|
|
//! formatiert einen zahlenwert als string mit einheit.
|
2025-08-05 22:39:41 +02:00
|
|
|
|
2025-08-08 21:39:33 +02:00
|
|
|
QString XQItemType::formatToSI( const QString& valueTxt, XQItem::UnitType unitType ) const
|
2025-08-05 22:39:41 +02:00
|
|
|
{
|
2025-08-08 21:39:33 +02:00
|
|
|
|
2025-08-05 22:39:41 +02:00
|
|
|
if( valueTxt.isEmpty() )
|
|
|
|
return valueTxt;
|
|
|
|
|
2025-08-08 21:39:33 +02:00
|
|
|
if( XQItem::ISODate == unitType )
|
2025-08-05 22:39:41 +02:00
|
|
|
{
|
|
|
|
// 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() );
|
2025-08-08 21:39:33 +02:00
|
|
|
|
2025-08-05 22:39:41 +02:00
|
|
|
}
|
|
|
|
|
2025-08-11 22:27:55 +02:00
|
|
|
|
|
|
|
//! entfernt die einheit aus einem formatierten string
|
2025-08-05 22:39:41 +02:00
|
|
|
|
|
|
|
QString XQItemType::unFormatFromSI(const QString& formText ) const
|
|
|
|
{
|
2025-08-08 21:39:33 +02:00
|
|
|
|
2025-08-05 22:39:41 +02:00
|
|
|
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;
|
2025-08-08 21:39:33 +02:00
|
|
|
|
2025-08-05 22:39:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
///
|
|
|
|
/// --- statics --------------------------------------------------------------------------
|
|
|
|
///
|
|
|
|
|
2025-08-08 21:39:33 +02:00
|
|
|
//! gibt den dummy item type zurück (benutzt für null-items).
|
|
|
|
|
2025-08-05 22:39:41 +02:00
|
|
|
XQItemType* XQItemType::staticItemType()
|
|
|
|
{
|
|
|
|
static XQItemType s_DummyItemType;
|
|
|
|
return &s_DummyItemType;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2025-08-08 21:39:33 +02:00
|
|
|
//! erzeugt aus den eingenschaften des itemTypes einen eindeutigen schlüssel.
|
|
|
|
|
2025-08-05 22:39:41 +02:00
|
|
|
QString XQItemType::makeItemTypeKey()
|
|
|
|
{
|
|
|
|
QString key("%1:%2:%3:%4:%5:%6:%7");
|
|
|
|
|
|
|
|
key = key.arg( renderStyleToString() );
|
|
|
|
key = key.arg( editorTypeToString() );
|
|
|
|
key = key.arg( unitTypeToString() );
|
2025-08-16 15:28:18 +02:00
|
|
|
key = key.arg( contentFormat() );
|
|
|
|
key = key.arg( itemFlagsToString() );
|
2025-08-15 20:31:40 +02:00
|
|
|
// icons haben leider keine namen, es sei denn, sie kommen aus einen theme
|
|
|
|
//key = key.arg( icon().name() );
|
2025-08-15 20:55:53 +02:00
|
|
|
//key = key.arg( icon().cacheKey() );
|
|
|
|
key = key.arg( XQAppData::iconName( icon() ) );
|
2025-08-05 22:39:41 +02:00
|
|
|
key = key.arg( fixedChoicesToString() );
|
|
|
|
|
|
|
|
return key;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|