first reCommit

This commit is contained in:
2025-08-13 18:30:47 +02:00
commit a946c7dd58
73 changed files with 23368 additions and 0 deletions

15
items/xqgenericitem.cpp Normal file
View File

@@ -0,0 +1,15 @@
/***************************************************************************
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 <xqgenericitem.h>

33
items/xqgenericitem.h Normal file
View File

@@ -0,0 +1,33 @@
/***************************************************************************
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.
***************************************************************************/
#ifndef XQGENERICITEM_H
#define XQGENERICITEM_H
#include <xqitem.h>
//
// Was sollte das mal werden?
//
template<class T, class U>
class XQGenericItem : public XQItem, public T, public U
{
public:
XQGenericItem() = default;
};
#endif // XQGENERICITEM_H

608
items/xqitem.cpp Normal file
View File

@@ -0,0 +1,608 @@
/***************************************************************************
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];
}

298
items/xqitem.h Normal file
View File

@@ -0,0 +1,298 @@
/***************************************************************************
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.
***************************************************************************/
#ifndef XQITEM_H
#define XQITEM_H
#include <QVariant>
#include <QVector>
#include <QStandardItem>
#include <xqnode.h>
using XQItemList = QList<QStandardItem*>;
//class QStyleOptionViewItem;
class XQItemFactory;
class XQItemType;
/**
* @brief Extends QStandardItem to hold additional
* settings.
*/
class XQItem : public QStandardItem
{
public:
//friend class XQItemType;
//friend class XQItemFactory;
/// Die data(enum role) Infrastruktur wird sowohl für XQItem als auch
/// für den XQItemType verwendet, deshalb definieren wir hier _alle_
/// notwendigen Roles
enum ItemDataRole
{
NoRole = Qt::UserRole + 1,
// das ist ein pointer auf den original-string aus dem XML
ContentRole,
ItemTypeRole,
RenderStyleRole,
EditorTypeRole,
UnitTypeRole,
ContentFormatRole,
// @see qstandarditemmodel.cpp, stolen from there
FlagsRole = Qt::ItemDataRole(Qt::UserRole - 1),
IconRole = Qt::DecorationRole,
// re-start count
FixedChoicesRole = ContentFormatRole+1,
ContentNodeRole,
//?? werden beide gebraucht?
SheetNodeRole,
// das ist der Schlüssel um den content string aus dem contentNode zu holen
//ContentKeyRole,
// weitere, weniger gebräuchlichen Rollen für XQItemType::data()
TypeKeyRole,
//TypeNameRole, nicht so wichtig
/*
renderStyleToStringRole,
editorTypeToStringRole,
unitTypeToStringRole,
*/
RoleEnd
};
// wie wirds gemalt
enum RenderStyle
{
NoRenderStyle,
HiddenStyle,
HeaderStyle,
PlainStyle,
CheckBoxStyle,
ComboBoxStyle,
PickerStyle,
SpinBoxStyle,
ProgressBarStyle,
FormattedStyle,
TreeHeaderStyle,
CustomRenderStyle,
RenderStyleEnd //!< Not a special editor. Keep at end of this enumeration!
// ...
/*
PickerStyle
LineEditStyle ,
UserDefStyle ,
*/
};
// wie wirds editiert
enum EditorType
{
NoEditorType,
LineEditType,
ComboBoxType,
PickerType,
ProgressBarType,
SpinBoxType,
CustomEditorType,
EditorTypeEnd
};
// typische Einheiten
enum UnitType
{
NoUnitType,
Ampere,
Volt,
Ohm,
Watt,
WattPeak,
WattHour,
Farad,
Tesla,
Henry,
Hertz,
Coulomb,
Kelvin,
Percent,
Second,
Meter,
Kg,
ISODate,
UnitTypeEnd
};
//XQItem(int rows, int columns = 1);
XQItem();
XQItem( XQItemType* itemType );
XQItem( XQItemType* itemType, const QString* content );
XQItem( XQItemType* itemType, const QString* content, const XQNodePtr& contentNode );
/*
XQItem(const QString& text);
XQItem(const QIcon& icon, const QString& text);
XQItem(int rows, int columns);
*/
XQItem(const XQItem& other);
XQItem(const QStandardItem& other);
virtual ~XQItem();
//! creates not a clone but a new default item, \see QStandardItemModel::setItemPrototype()
//! -- not used at the moment --
XQItem* clone() const override;
bool isValid() const;
// shortcuts auf XQNodePtr
virtual XQNodePtr contentNode() const;
virtual void setContentNode(const XQNodePtr& contentNode );
virtual XQNodePtr sheetNode() const;
virtual void setSheetNode( const XQNodePtr& sheetNode );
bool hasAttribute( const QString& attribKey ) const;
const QString& attribute( const QString& attribKey, const QString& defaultValue="" ) const;
bool testAttribute( const QString& attribKey, const QString& attribValue ) const;
XQItemType& itemType() const;
void setItemType( XQItemType* itemTypePtr );
// shortcuts für die itemFlags
// __fix! das können die selber !?
void addFlag( Qt::ItemFlag newFlag );
void clearFlag( Qt::ItemFlag newFlag );
//das ist ein Sonderfall: Ein ist ein dereferenzierter Zeiger auf 'unser' Atrribut in
// XQNodePtr, also unserem contentNode(). Das wird hier direkt aufgelöst und nicht auf
// data() umgeleitet.
const QString& content() const;
const QString& contentKey() const;
void setContent( const QString* content );
//
// Convenience-Funktionen zum Memberzugriff, die Implementierung
// läuft über die data()-Methode wie in den QStandardItems. So
// ist sie für XQItem und auch für XQItemType als Deirvat von XQItem gültig.
//
RenderStyle renderStyle() const;
QString renderStyleToString() const;
void setRenderStyle(RenderStyle renderStyle );
EditorType editorType() const;
QString editorTypeToString() const;
void setEditorType(EditorType editorType);
UnitType unitType() const;
QString unitTypeToString() const;
void setUnitType(UnitType unitType);
QString contentFormat() const;
void setContentFormat(const QString& contentFormat);
QStandardItemModel* fixedChoices() const;
QString fixedChoicesToString() const;
void setfixedChoices( QStandardItemModel* newModel );
//
//shortCuts
//
bool isHeaderStyle();
// ...
QVariant data(int role = Qt::DisplayRole ) const override;
void setData(const QVariant &value, int role ) override;
// Das sind die die items im tree links: icon,text, node pointer
//XQItem( const QString& text, XQNodePtr contentNode );
//XQItem( const QString& text, XQItemType::RenderStyle renderStyle );
/*
template<class T>
void setToVariant(T entry, QtExtUserRoles::NTDataRoles role)
{
setData(QVariant::fromValue<T>(entry), role);
}
template<class T>
T getFromVariant(QtExtUserRoles::NTDataRoles role)
{
return data(role).value<T>();
}
*/
///
/// Static convenience methods
///
static const XQItem& xqConstItemFromIndex( const QModelIndex& index );
static XQItem& xqItemFromIndex( const QModelIndex& index );
static XQItem& fallBackDummyItem();
static int fetchItemDataRole( const QString& dataRoleKey );
static QString fetchItemDataRoleName( int dataRole );
static Qt::ItemFlag fetchItemFlag( const QString& flagKey );
static QString fetchItemFlagName( int flag );
static RenderStyle fetchRenderStyle( const QString& styleKey );
static QString fetchRenderStyleToString( RenderStyle renderStyle );
static EditorType fetchEditorType( const QString& editorTypeKey );
static QString fetchEditorTypeToString( EditorType editorType );
static UnitType fetchUnitType( const QString& typeKey );
static QString fetchUnitTypeToString( UnitType );
protected:
using XQItemFlagMap = QMap<QString,int>;
using XQItemDataRoleMap = QMap<QString,int>;
using XQRenderStyleMap = QMap<QString,RenderStyle>;
using XQEditorTypeMap = QMap<QString,EditorType>;
using XQUnitTypeMap = QMap<UnitType, QString>;
using XQPrefixExponentMap = QMap<QString, int>;
static XQItemFlagMap s_ItemFlagMap;
static XQItemDataRoleMap s_ItemDataRoleMap;
static XQRenderStyleMap s_RenderStyleMap;
static XQEditorTypeMap s_EditorTypeMap;
static XQUnitTypeMap s_UnitTypeMap;
static XQPrefixExponentMap s_PrefixExponentMap;
};
Q_DECLARE_METATYPE(XQItem::RenderStyle);
Q_DECLARE_METATYPE(XQItem::EditorType);
Q_DECLARE_METATYPE(XQItem::UnitType);
Q_DECLARE_METATYPE(const QString*);
#endif // XQITEM_H

291
items/xqitemdelegate.cpp Normal file
View File

@@ -0,0 +1,291 @@
/***************************************************************************
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 <QApplication>
#include <QItemEditorFactory>
#include <QLineEdit>
#include <QComboBox>
#include <QDoubleSpinBox>
#include <QProgressBar>
#include <QPainter>
#include <QHeaderView>
#include <QCommonStyle>
#include <xqitemdelegate.h>
#include <xqtreeview.h>
#include <xqitemtype.h>
#include <xqmodel.h>
class XQItemEditorFactory : public QItemEditorFactory
{
public:
XQItemEditorFactory()
{
registerEditor(XQItem::LineEditType, new QStandardItemEditorCreator<QLineEdit>());
registerEditor(XQItem::ComboBoxType, new QStandardItemEditorCreator<QLineEdit>());
registerEditor(XQItem::PickerType, new QStandardItemEditorCreator<QLineEdit>());
registerEditor(XQItem::ProgressBarType, new QStandardItemEditorCreator<QLineEdit>());
registerEditor(XQItem::SpinBoxType, new QStandardItemEditorCreator<QLineEdit>());
registerEditor(XQItem::CustomEditorType, new QStandardItemEditorCreator<QLineEdit>());
/*
registerEditor(XQItem::LineEditStyle, new QStandardItemEditorCreator<QLineEdit>());
registerEditor(XQItemType::ComboBoxStyle, new QStandardItemEditorCreator<QComboBox>());
//registerEditor(XQItemType::ProgressBarStyle, new QStandardItemEditorCreator<QProgressBar>());
registerEditor(XQItemType::SpinBoxStyle, new QStandardItemEditorCreator<QSpinBox>());
*/
/*
registerEditor(XQItem::etDoubleSpinType, new QStandardItemEditorCreator<QDoubleSpinBox>());
registerEditor(XQItemItemTypes::etDoubleSpinType, new QStandardItemEditorCreator<QDoubleSpinBox>());
registerEditor(XQItemItemTypes::etIPAddressType, new QStandardItemEditorCreator<NTIpAddressEdit>());
registerEditor(XQItemItemTypes::etLineEditBrowser, new QStandardItemEditorCreator<NTFileSelectLine>());
*/
}
};
XQItemDelegate::XQItemDelegate( XQModel& modelView)
: _modelView{modelView}
{
static XQItemEditorFactory s_EditorFactory;
setItemEditorFactory(&s_EditorFactory);
}
XQTreeView* XQItemDelegate::treeView() const
{
return _modelView.treeView();
}
XQItem& XQItemDelegate::xqItemFromIndex( const QModelIndex& index ) const
{
return _modelView.xqItemFromIndex( index );
}
QWidget* XQItemDelegate::prepareHeaderOption(const QStyleOptionViewItem& option, const QModelIndex& index, QStyleOptionHeader& headerOption) const
{
// use the header as "parent" for style init
QWidget* srcWidget = treeView()->header();
headerOption.initFrom(srcWidget);
headerOption.text = index.data(Qt::DisplayRole).toString();
headerOption.rect = option.rect;
headerOption.styleObject = option.styleObject;
// __ch: reduce inner offset when painting
headerOption.textAlignment |= Qt::AlignVCenter;
return srcWidget;
}
void XQItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
if( !index.isValid() )
qDebug() << " index DEAD!";
XQItem& item = xqItemFromIndex( index );
if( item.isValid() )
{
switch( item.renderStyle() )
{
case XQItem::HeaderStyle :
return drawHeaderStyle( painter, option, index );
case XQItem::ComboBoxStyle :
return drawComboBoxStyle( painter, option, index );
case XQItem::HiddenStyle :
return;
//case XQItem::ProgressBarStyle :
// return drawProgressBarStyle( painter, option, index );
default:
break;
} // switch
}
QStyledItemDelegate::paint(painter, option, index);
}
void XQItemDelegate::drawHeaderStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
QStyleOptionHeader headerOption;
QWidget* srcWidget = prepareHeaderOption(option, index, headerOption);
if (srcWidget != nullptr)
{
// save painter
painter->save();
//value = index.data(Qt::ForegroundRole);
//if (value.canConvert<QBrush>())
//headerOption.palette.setBrush(QPalette::Text, Qt::red );
//headerOption.palette.setBrush(QPalette::Window, Qt::red );
QCommonStyle itemStyle;
//headerOption.backgroundBrush()
//srcWidget->style()->drawControl(QStyle::CE_Header, &headerOption, painter, srcWidget);
itemStyle.drawControl(QStyle::CE_Header, &headerOption, painter, srcWidget);
// restore painter
painter->restore();
}
}
void XQItemDelegate::drawProgressBarStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
int progress = index.data(XQItem::ContentRole ).toInt();
QStyleOptionProgressBar progressBarOption;
progressBarOption.rect = option.rect;
progressBarOption.minimum = 0;
progressBarOption.maximum = 100;
progressBarOption.progress = progress;
progressBarOption.text = QString::number(progress) + "%";
progressBarOption.textAlignment = Qt::AlignCenter;
progressBarOption.textVisible = true;
QApplication::style()->drawControl(QStyle::CE_ProgressBar,&progressBarOption, painter);
}
void XQItemDelegate::drawComboBoxStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QWidget* srcWidget = qobject_cast<QWidget*>(option.styleObject);
QStyleOptionComboBox comboOption;
QStyle* comboStyle = srcWidget->style();
comboOption.initFrom(srcWidget);
// set options
comboOption.rect = option.rect;
comboOption.state = option.state | QStyle::State_Selected | QStyle::State_Enabled;
// not editable => only visual, but painter needs to know it
comboOption.editable = false;
comboOption.currentText = index.data(Qt::DisplayRole).toString();
// decoration (if any)
comboOption.currentIcon = qvariant_cast<QIcon>(index.data(Qt::DecorationRole));
comboOption.iconSize = comboOption.currentIcon.actualSize(QSize(option.rect.height() - 3, option.rect.height() - 3));
// save painter
painter->save();
// draw combo
comboStyle->drawComplexControl(QStyle::CC_ComboBox, &comboOption, painter, srcWidget);
// and combobox label
comboStyle->drawControl(QStyle::CE_ComboBoxLabel, &comboOption, painter, srcWidget);
// restore painter
painter->restore();
}
void XQItemDelegate::drawSpinBoxStyle(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
// xx_fix!
//int value = index.data(XQItem::ContentRole ).toInt();
QStyleOptionSpinBox spinBoxOption;
spinBoxOption.rect = option.rect;
/*
spinBoxOption.text = QString::number(value);
spinBoxOption.textAlignment = Qt::AlignCenter;
spinBoxOption.textVisible = true;
*/
QApplication::style()->drawComplexControl(QStyle::CC_SpinBox,&spinBoxOption, painter);
}
QSize XQItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return QStyledItemDelegate::sizeHint(option, index);
}
QWidget* XQItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
return QStyledItemDelegate::createEditor( parent, option, index );
int editorType = XQItem::xqItemFromIndex(index).editorType();
QWidget* editor = itemEditorFactory()->createEditor(editorType, parent);
if( editor )
{
return editor;
}
}
void XQItemDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
XQItem& item = xqItemFromIndex( index );
qDebug() << " --- ZZZ: setEditorData: " << item.text();
switch( item.editorType() )
{
case XQItemType::ComboBoxType :
{
QComboBox* comboBox = qobject_cast<QComboBox*>(editor);
comboBox->setModel( item.fixedChoices());
comboBox->setCurrentText( item.data().toString() );
comboBox->showPopup();
return;
}
default:
break;
}
QStyledItemDelegate::setEditorData(editor, index);
}
void XQItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
XQItem& item = xqItemFromIndex( index );
switch( item.editorType() )
{
case XQItem::ComboBoxType :
{
QComboBox* comboBox = qobject_cast<QComboBox*>(editor);
return;
}
default:
break;
}
QStyledItemDelegate::setModelData(editor, model, index);
}
void XQItemDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
//qDebug() << " --- update Editor Geometry";
QStyledItemDelegate::updateEditorGeometry(editor, option, index);
}

60
items/xqitemdelegate.h Normal file
View File

@@ -0,0 +1,60 @@
/***************************************************************************
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.
***************************************************************************/
#ifndef XQITEMDELEGATE_H
#define XQITEMDELEGATE_H
#include <QStyledItemDelegate>
#include <xqappdata.h>
class XQItem;
class XQTreeView;
class XQModel;
/**
* @brief A specialized QItemDelegate class to draw different XQItem styles.
*/
class XQItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit XQItemDelegate(XQModel& modelView);
XQTreeView* treeView() const;
XQItem& xqItemFromIndex( const QModelIndex& index ) const;
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
protected:
QWidget* prepareHeaderOption(const QStyleOptionViewItem& option, const QModelIndex& index, QStyleOptionHeader& headerOption) const;
void drawHeaderStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawProgressBarStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawComboBoxStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void drawSpinBoxStyle(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
XQModel& _modelView;
};
#endif // XQITEMDELEGATE_H

324
items/xqitemfactory.cpp Normal file
View File

@@ -0,0 +1,324 @@
/***************************************************************************
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 <xqitemfactory.h>
#include <xqexception.h>
#include <xqdocumentstore.h>
#include <xqmodel.h>
#include <xqitemtype.h>
#include <znode_factory.h>
void XQItemFactory::initItemFactory( const QString& modelSheetFileName )
{
auto configureItemType = [&, this](XQItemType* itemType, const XQNodePtr& sheetNode )
{
// über alle attribute
for( const auto& [key,value] : sheetNode->attributes() )
{
setItemDataFromString( *itemType, key, value );
}
};
// schritt #1: modelbeschreibung laden
XQNodeFactory treeLoader;
_modelSheet = treeLoader.load_tree( qPrintable(modelSheetFileName) );
// schritt #2: model root testen
if (!_modelSheet)
throw XQException("modelSheet load failed. ", modelSheetFileName);
// schritt #3: itemtype beschreibungen laden ...
_typesSheet = _modelSheet->find_child_by_tag_name( "ItemTypes" );
// ... und testen
if( !_typesSheet )
throw XQException( "initItemFactory typeSheetRoot is null" );
// alle itemtype vorlagen erzeugen
for( const XQNodePtr& typeSheetNode : _typesSheet->children())
{
XQItemType* itemType = new XQItemType;
//const QString& typeName = typeSheetNode->tag_name();
const QString& typeName = typeSheetNode->tag_name();
configureItemType(itemType, typeSheetNode);
itemType->setText( typeName);
s_ItemTypeCache[typeName] = itemType;
}
}
bool XQItemFactory::isValid()
{
return _modelSheet && _typesSheet;
}
XQItemType* XQItemFactory::findItemType(const QString& key ) const
{
if( !key.isEmpty() && s_ItemTypeCache.contains(key))
return s_ItemTypeCache[key];
throw XQException( "findItemType: not found:", key );
}
XQNodePtr XQItemFactory::findModelSheet( const QString& modelName ) const
{
XQNodePtr modelSheet = _modelSheet->find_child_by_tag_name( modelName );
if( !modelSheet )
throw XQException( "model sheet not found: ", modelName );
return modelSheet;
}
XQItem* XQItemFactory::makeItem( const XQNodePtr& contentNode, const XQNodePtr& sheetEntry ) const
{
// den itemtype des neuen items rausfinden
QString typeKey = sheetEntry->attribute("ItemType");
XQItemType* itemType = findItemType(typeKey); // throws
const QString* contentPtr = contentNode->attribute_ptr( sheetEntry->tag_name() );
XQItem* newItem = new XQItem( itemType, contentPtr );
return newItem;
}
XQItem* XQItemFactory::makeHeaderItem( const XQNodePtr& sheetEntry ) const
{
// header items are all non-data items:
// - section header row items
// - main tree header items
// - main tree child items
// - also: static items, hidden items
// den itemtype des neuen items rausfinden
QString typeKey = sheetEntry->attribute("HeaderItemType");
XQItemType* itemType = findItemType(typeKey); // throws
// das ist Unterschied zum normalen Item: Der Titel kommt aus der Modelbeschreibung
const QString* contentPtr = sheetEntry->attribute_ptr("HeaderCaption");
XQItem* newItem = new XQItem( itemType, contentPtr );
// brauchen wir den noch?
//newHeaderItem->setSheetNode( sheetNode );
return newItem;
}
void XQItemFactory::setItemDataFromString( XQItem& item, const QString& roleKey, const QString& source ) const
{
int dataRole = XQItem::fetchItemDataRole( roleKey );
if( dataRole != XQItem::NoRole)
{
QVariant variant = makeVariant( dataRole, source );
if( !variant.isNull() && variant.isValid() )
item.setData( variant, dataRole );
}
}
QVariant XQItemFactory::makeVariant( int dataRole, const QString& source ) const
{
QVariant value;
switch(dataRole)
{
// das ist ein pointer auf den original-string aus dem XML
case XQItem::ContentRole:
{
// content() -> QString*
value = QVariant::fromValue(&source);
break;
}
case XQItem::ItemTypeRole:
{
// itemType() -> XQItemType*
XQItemType* itemType = findItemType( source );
value = QVariant::fromValue(itemType);
break;
}
case XQItem::RenderStyleRole:
{
XQItem::RenderStyle renderStyle = XQItem::fetchRenderStyle( source );
value = QVariant::fromValue(renderStyle);
break;
}
case XQItem::EditorTypeRole:
{
XQItem::EditorType editorType = XQItem::fetchEditorType( source );
value = QVariant::fromValue(editorType);
break;
}
case XQItem::UnitTypeRole:
{
XQItem::UnitType unitType = XQItem::fetchUnitType( source );
value = QVariant::fromValue(unitType);
break;
}
case XQItem::ContentFormatRole:
{
// contentFormat() -> QString
value = QVariant::fromValue(source);
break;
}
case XQItem::FlagsRole:
{
QFlags itemFlags = Qt::NoItemFlags;
const QStringList flagKeys = source.split( '|' );
for( const QString& flagKey : flagKeys )
{
Qt::ItemFlag flag = XQItem::fetchItemFlag( flagKey );
itemFlags.setFlag( flag );
}
value = QVariant::fromValue(itemFlags);
break;
}
case XQItem::IconRole:
{
QIcon typeIcon;
if(XQAppData::hasTypeIcon(source))
typeIcon = XQAppData::typeIcon(source);
value = QVariant::fromValue(typeIcon);
break;
}
case XQItem::FixedChoicesRole:
{
const QStringList choices = source.split( '|' );
QStandardItemModel* fixedChoices = new QStandardItemModel();
for( const QString& entry : choices )
fixedChoices->appendRow( new QStandardItem( entry ) );
value = QVariant::fromValue(fixedChoices);
break;
}
/*
case XQItem::ContentNodeRole:
{
value = QVariant::fromValue(&source);
break;
}
case XQItem::XQItem::SheetNodeRole:
{
value = QVariant::fromValue(&source);
break;
}
*/
default:
case XQItem::XQItem::NoRole:
{
break;
}
};
//if( !value.toString().isEmpty())
// setData( value, dataRole);
return value;
}
///
/// ------------------------------------------------
///
// no clone here !
XQItemList XQItemFactory::createDataRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode )
{
XQItemList list;
// - Gehe über alle Einträge der Typbeschreibung:
//
// <Battery>
// <Voltage .../>
// -> <Capacity ../>
//
// - Nimm das dazugehörige Attribut aus dem contentNode
// value = contentNode->attributes["Capacity"];
//
for( const auto& sheetEntry : sheetNode->children() )
{
list.append( makeItem( contentNode, sheetEntry ) );
}
if( !list.empty() )
{
// wir merken uns den original content node auch, aber
// im ersten Item.
dynamic_cast<XQItem*>(list[0])->setContentNode(contentNode);
}
return list;
}
XQItemList XQItemFactory::createEmptyRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode )
{
Q_UNUSED(contentNode)
XQItemList list;
// create a data node for each sheet entry
size_t max = sheetNode->children().size();
for( size_t i=0; i<max; ++i )
{
// __fix
//list.append( new XQItem( "", XQItemType::EmptyStyle ) );
}
return list;
}
XQItemList XQItemFactory::createGenericRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode )
{
// we have a new empty contentNode, so we add attributes first.
for( const auto& sheetEntry : sheetNode->children() )
{
QString value = "[" + sheetEntry->tag_name() + "]";
if( sheetEntry->has_attribute("Unit") )
value = "0";
contentNode->set_attribute( sheetEntry->tag_name(), value );
}
if( sheetNode->has_attribute( c_FriendlyName ) )
contentNode->set_attribute( c_FriendlyName, sheetNode->friendly_name() );
// now, we can create a normal entry row
return createDataRow(contentNode, sheetNode );
}

66
items/xqitemfactory.h Normal file
View File

@@ -0,0 +1,66 @@
/* **************************************************************************
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.
***************************************************************************/
#ifndef XQITEMFACTORY_H
#define XQITEMFACTORY_H
#include <xqitem.h>
#include <xqitemtype.h>
#include <functional>
class XQModel;
// erzeugt items aus XQNodes
class XQItemFactory : public xsingleton<XQItemFactory>
{
public:
void initItemFactory(const QString& modelSheetFileName );
XQNodePtr findModelSheet( const QString& modelName ) const;
XQItem* makeItem( const XQNodePtr& contentNode, const XQNodePtr& sheetEntry ) const;
XQItem* makeHeaderItem(const XQNodePtr& typeSheetNode ) const;
virtual XQItemList createDataRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode );
virtual XQItemList createEmptyRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode );
virtual XQItemList createGenericRow( const XQNodePtr& contentNode, const XQNodePtr& sheetNode );
void setItemDataFromString( XQItem& item, const QString& roleKey, const QString& source ) const;
// __fix! unsinn!
XQItemType* findItemType(const QString& key ) const;
QVariant makeVariant(int dataRole, const QString &value ) const;
protected:
bool isValid();
// shortcuts
using ItemConfigFunc = std::function<void( XQItem* item, const QString& attrValue, XQNodePtr contentNode, XQNodePtr sheetNode )>;
using ItemConfigMap = QMap<QString,ItemConfigFunc>;
XQItemTypeMap s_ItemTypeCache;
// Beschreibung des XQModels
XQNodePtr _modelSheet{};
// Beschreibung der ItemTypes
XQNodePtr _typesSheet{};
};
#endif // XQITEMFACTORY_H

259
items/xqitemtype.cpp Normal file
View File

@@ -0,0 +1,259 @@
/***************************************************************************
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 )
{
}
XQItemType::~XQItemType()
{
}
QVariant XQItemType::data( int role ) const
{
return QStandardItem::data(role);
}
void XQItemType::setData(const QVariant &value, int role )
{
return QStandardItem::setData(value,role);
}
void XQItemType::replaceAttribute( XQItem* item, const QVariant& newValue, int role )
{
// hat sich überhaupt was geändert?
QVariant oldValue = data(role);
// ja, es hat
if( oldValue != newValue )
{
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 ) )
{
// nur abräumen, sonst nix
delete myClone;
}
else
{
// speichern
s_ItemTypeMap.insert( newKey, myClone );
// und ins item übernehmen
item->setItemType( myClone );
/// Obacht! Der alte, geänderte itemType bleibt erhaltent
/// und verrottet ggf. ohne Daseinszweck
}
}
}
QString XQItemType::formatToSI( const QString& valueTxt ) 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() );
*/
return "fitze!";
}
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;
*/
return "fitze!";
}
///
/// --- statics --------------------------------------------------------------------------
///
XQItemType* XQItemType::staticItemType()
{
static XQItemType s_DummyItemType;
return &s_DummyItemType;
}
//
// Das ist eigentlich Blödsinn, KISS baby KISS!
// Die ItemTypes sollten statisch bleiben, zusätzliche
// oder geänderte Attribute eines Items landen dann
// halt in G.N. in QStadardItem::data Vector!
//
/*
XQItemType* XQItemType::storeItemType(XQItemType* protoType)
{
// haben wir den prototype schon?
QString itemTypeKey = protoType->makeItemTypeKey();
if(s_ItemTypeMap.contains( itemTypeKey ) )
{
// dann weg damit ...
delete protoType;
// ... und die alte Version zurückgeben
return s_ItemTypeMap[itemTypeKey];
}
// sonst: wir speichern den prototype
s_ItemTypeMap.insert( itemTypeKey, protoType);
s_ItemTypeCount++;
qDebug() << " --- ItemTypes: " << s_ItemTypeCount;
return protoType;
}
*/
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( data(XQItem::FlagsRole).toString() );
key = key.arg( icon().name() );
key = key.arg( fixedChoicesToString() );
/*
static const QList<XQItem::ItemDataRole> roleList
{
XQItem::RenderStyleRole,
XQItem::EditorTypeRole,
XQItem::UnitTypeRole,
XQItem::ContentFormatRole,
XQItem::FlagsRole,
XQItem::IconRole,
XQItem::FixedChoicesRole
};
QString key;
for( const auto role : roleList )
{
qDebug() << " --- YYY trying: " << XQItem::fetchItemDataRoleName( role );
QVariant entry = data(role);
if( !entry.isNull() && entry.isValid())
{
// fckin' sonderlocke:
key += role == XQItem::IconRole ? entry.value<QIcon>().name() : entry.toString();
}
key += ":";
}
*/
//qDebug() << " --- YES: KEY: " << key;
return key;
}

86
items/xqitemtype.h Normal file
View File

@@ -0,0 +1,86 @@
/***************************************************************************
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.
***************************************************************************/
#ifndef XQITEMTYPE_H
#define XQITEMTYPE_H
#include <QDebug>
#include <QMap>
#include <xqitem.h>
///
/// Ist das Unsinn!? Einfach ein QStandardItem mit data() nehmen?
/// Ok, das erspart die die attribs, aber wo ist der fette gewinn?
/// statt _editorType = x hast Du dann halt setData( QVariant::fromValue<>(x) );
/// Aber: Du kannst T abbilden auf QString ... und dann
///
using XQItemTypeMap = QMap<QString, XQItemType*>;
//class XQItemType : public QObject
class XQItemType : public XQItem// public QObject
{
//
//Q_OBJECT
// wäre auch eine möglichkeit !?
//Q_PROPERTY(XQItem::RenderStyle renderStyle renderStyle getDate WRITE setrenderStyle )
public:
XQItemType();
XQItemType( const XQItemType& other);
virtual ~XQItemType();
QVariant data( int role ) const override;
void setData(const QVariant& value, int role ) override;
// FIX! Das gehört hier nicht her!
QString formatToSI(const QString& rawText ) const;
QString unFormatFromSI(const QString& valueText ) const;
void replaceAttribute( XQItem* item, const QVariant& newValue, int role );
QString makeItemTypeKey();
//static XQItemType* storeItemType( XQItemType* protoType );
static XQItemType* staticItemType();
protected:
static XQItemTypeMap s_ItemTypeMap;
static size_t s_ItemTypeCount;
/*
static void setItemType( XQItem* item, RenderStyle renderStyle, Qt::ItemFlags flags, UnitType unitType, const QString& format );
static void setStaticType( XQItem* item );
*/
// fix __ch
// static void setItemType( XQItem* item, const QString& renderStyle, const QString& unitType, const QString& itemTypeID );
//static XQItemType* addItemType( const QString& key, RenderStyle renderStyle, UnitType unitType);
//static XQItemType* makeItemType( RenderStyle renderStyle, UnitType unitType);
};
Q_DECLARE_METATYPE(XQItemType*);
#endif // XQITEMTYPE_H