Support item tabs based on item group string

This commit is contained in:
Carl Philipp Klemm 2026-04-01 19:40:47 +02:00
parent 0e09b6f46c
commit a17cd23a4e
29 changed files with 527 additions and 181 deletions

View file

@ -10,5 +10,19 @@ FixedItemSource::FixedItemSource(Microcontroller* micro, QObject *parent):
void FixedItemSource::refresh()
{
gotItems({powerItem, rgbItem, auxItem}, ITEM_UPDATE_BACKEND);
std::vector<ItemAddRequest> requests;
ItemAddRequest request;
request.type = ITEM_UPDATE_BACKEND;
request.payload = powerItem;
requests.push_back(request);
request.payload = rgbItem;
requests.push_back(request);
request.payload = auxItem;
requests.push_back(request);
gotItems(requests);
}

View file

@ -46,21 +46,49 @@ uint32_t ItemData::id() const
void ItemData::store(QJsonObject &json)
{
json["Name"] = name_;
storeWithChanges(json, ItemFieldChanges(true));
}
void ItemData::storeWithChanges(QJsonObject& json, const ItemFieldChanges& changes)
{
json["ItemId"] = static_cast<double>(itemId_);
json["Value"] = static_cast<double>(value_);
json["GroupName"] = groupName_;
json["ValueType"] = type_;
if(changes.name)
json["Name"] = name_;
if(changes.value)
json["Value"] = static_cast<double>(value_);
if(changes.groupName)
json["GroupName"] = groupName_;
}
void ItemData::load(const QJsonObject &json, const bool preserve)
{
loadWithChanges(json, preserve);
}
ItemFieldChanges ItemData::loadWithChanges(const QJsonObject& json, const bool preserve)
{
ItemFieldChanges changes;
if(!preserve)
{
name_ = json["Name"].toString(name_);
if(json.contains("Name"))
{
name_ = json["Name"].toString();
changes.name = true;
}
if(json.contains("Value"))
{
value_ = json["Value"].toInt();
changes.value = true;
}
if(json.contains("GroupName"))
{
groupName_ = json["GroupName"].toString();
changes.groupName = true;
}
itemId_ = static_cast<uint32_t>(json["ItemId"].toDouble(0));
value_ = json["Value"].toInt();
groupName_ = json["GroupName"].toString("All");
}
return changes;
}
bool ItemData::getLoaded() const
@ -73,15 +101,23 @@ void ItemData::setLoaded(bool loaded)
loaded_ = loaded;
}
bool ItemData::hasChanged(const ItemData& other)
bool ItemData::hasChanged(const ItemData& other) const
{
if(other != *this)
return false;
if(other.getName() != getName())
ItemFieldChanges changes(true);
return hasChanged(other, changes);
}
bool ItemData::hasChanged(const ItemData& other, const ItemFieldChanges& changes) const
{
if(changes.name && other.getName() != getName())
return true;
if(other.getValue() != getValue())
if(changes.value && other.getValue() != getValue())
return true;
if(other.getLoaded() != getLoaded())
if(changes.hidden && other.isHidden() != isHidden())
return true;
if(changes.groupName && other.getGroupName() != getGroupName())
return true;
if(changes.actors)
return true;
return false;
}
@ -143,7 +179,6 @@ void Item::store(QJsonObject &json)
}
}
json["Actors"] = actorsArray;
json["ValueType"] = type_;
}
void Item::load(const QJsonObject &json, const bool preserve)
@ -175,7 +210,14 @@ Item& Item::operator=(const ItemData& other)
void Item::requestUpdate(ItemUpdateRequest update)
{
assert(update.type != ITEM_UPDATE_INVALID);
if(update.type != ITEM_UPDATE_LOADED && value_ == update.payload.getValue())
assert(!update.changes.isNone());
if(update.type == ITEM_UPDATE_LOADED)
{
qDebug()<<__func__<<update.changes.actors<<update.newActors.size();
}
if(!hasChanged(update.payload, update.changes))
return;
if(update.type == ITEM_UPDATE_ACTOR && override_)
@ -183,20 +225,24 @@ void Item::requestUpdate(ItemUpdateRequest update)
qDebug()<<"Item Update Request for"<<getName()<<" type "<<update.type<<" value "<<update.payload.getValue();
if(update.type != ITEM_UPDATE_LOADED &&
update.type != ITEM_UPDATE_BACKEND &&
(programMode == PROGRAM_MODE_PRIMARY || programMode == PROGRAM_MODE_HEADLESS_PRIMARY))
if(update.type != ITEM_UPDATE_LOADED && update.type != ITEM_UPDATE_BACKEND &&
(programMode == PROGRAM_MODE_PRIMARY || programMode == PROGRAM_MODE_HEADLESS_PRIMARY) &&
update.changes.value)
enactValue(update.payload.getValue());
if(update.type != ITEM_UPDATE_LOADED)
{
if(update.changes.value)
value_ = update.payload.getValue();
}
else
{
if(update.changes.name)
name_ = update.payload.getName();
//itemId_ = update.payload.id();
if(update.changes.hidden)
hidden_ = update.payload.isHidden();
if(update.changes.groupName)
groupName_ = update.payload.getGroupName();
if(update.changes.type)
type_ = update.payload.getValueType();
if(update.changes.actors)
{
actors_.clear();
for(std::shared_ptr<Actor>& actor : update.newActors)
addActor(actor);
@ -302,14 +348,12 @@ std::shared_ptr<Item> Item::loadItem(const QJsonObject& json)
return newItem;
}
ItemUpdateRequest Item::createValueUpdateRequest(uint8_t value,
item_update_type_t type,
ItemUpdateRequest Item::createValueUpdateRequest(item_update_type_t type,
bool withActors)
{
ItemUpdateRequest update;
update.type = type;
update.payload = *this;
update.payload.setValueData(value);
if(withActors)
update.newActors = actors_;
return update;

View file

@ -23,6 +23,9 @@ typedef enum {
ITEM_UPDATE_INVALID
} item_update_type_t;
struct ItemFieldChanges;
struct ItemUpdateRequest;
class ItemData
{
protected:
@ -41,7 +44,7 @@ public:
bool loaded = false,
bool hidden = false,
item_value_type_t type = ITEM_VALUE_BOOL,
QString groupName = "All");
QString groupName = "");
inline bool operator==(const ItemData& in) const
{
@ -54,7 +57,8 @@ public:
uint32_t id() const;
bool hasChanged(const ItemData& other);
bool hasChanged(const ItemData& other) const;
bool hasChanged(const ItemData& other, const ItemFieldChanges& changes) const;
void setName(QString name);
uint8_t getValue() const;
void setValueData(uint8_t value);
@ -65,19 +69,13 @@ public:
item_value_type_t getValueType();
QString getGroupName() const;
void setGroupName(QString groupName);
void storeWithChanges(QJsonObject& json, const ItemFieldChanges& changes);
ItemFieldChanges loadWithChanges(const QJsonObject& json, const bool preserve = false);
virtual QString getName() const;
virtual void store(QJsonObject& json);
virtual void load(const QJsonObject& json, const bool preserve = false);
};
struct ItemUpdateRequest
{
item_update_type_t type = ITEM_UPDATE_INVALID;
ItemData payload;
std::vector<std::shared_ptr<Actor> > newActors;
};
class Item: public QObject, public ItemData
{
Q_OBJECT
@ -108,8 +106,7 @@ public:
void setActorsActive(bool in);
void setOverride(const bool in);
bool getOverride();
ItemUpdateRequest createValueUpdateRequest(uint8_t value,
item_update_type_t type,
ItemUpdateRequest createValueUpdateRequest(item_update_type_t type,
bool withActors = false);
virtual void store(QJsonObject& json);
@ -122,3 +119,52 @@ protected:
};
struct ItemFieldChanges
{
bool name :1;
bool value :1;
bool hidden :1;
bool type :1;
bool groupName :1;
bool actors :1;
ItemFieldChanges(bool defaultVal = false)
{
name = defaultVal;
value = defaultVal;
hidden = defaultVal;
type = defaultVal;
groupName = defaultVal;
actors = false;
}
inline bool isNone() const
{
return !name && !value && !hidden && !type && !groupName && !actors;
}
};
struct ItemUpdateRequest
{
item_update_type_t type = ITEM_UPDATE_INVALID;
ItemData payload;
ItemFieldChanges changes;
std::vector<std::shared_ptr<Actor> > newActors;
};
struct ItemAddRequest
{
item_update_type_t type = ITEM_UPDATE_INVALID;
std::shared_ptr<Item> payload;
ItemFieldChanges changes;
inline ItemUpdateRequest updateRequest() const
{
ItemUpdateRequest update;
update.payload = *payload;
update.type = type;
update.changes = changes;
if(changes.actors)
update.newActors = payload->getActors();
return update;
}
};

View file

@ -10,7 +10,7 @@ ItemLoaderSource::ItemLoaderSource(const QJsonObject& json, QObject *parent):
void ItemLoaderSource::refresh()
{
std::vector<std::shared_ptr<Item>> items;
std::vector<ItemAddRequest> itemAddRequests;
const QJsonArray itemsArray(json["Items"].toArray());
for(int i = 0; i < itemsArray.size(); ++i)
{
@ -21,11 +21,15 @@ void ItemLoaderSource::refresh()
std::shared_ptr<Item> newItem = Item::loadItem(itemObject);
if(newItem)
{
items.push_back(newItem);
qDebug()<<"Loaded item"<<newItem->getName();
ItemAddRequest request;
request.type = ITEM_UPDATE_LOADED;
request.payload = newItem;
request.changes = ItemFieldChanges(true);
itemAddRequests.push_back(request);
}
}
gotItems(items, ITEM_UPDATE_LOADED);
gotItems(itemAddRequests);
}
void ItemLoaderSource::updateJson(const QJsonObject& json)

View file

@ -17,7 +17,7 @@ public slots:
virtual void refresh() = 0;
signals:
void gotItems(std::vector<std::shared_ptr<Item>> items, item_update_type_t updateType);
void gotItems(std::vector<ItemAddRequest> items);
void requestReplaceItems(std::vector<std::shared_ptr<Item>> items);
void updateItems(std::vector<ItemUpdateRequest> updates);
};

View file

@ -6,39 +6,38 @@ ItemStore::ItemStore(QObject *parent): QObject(parent)
{
}
void ItemStore::addItem(const std::shared_ptr<Item>& item, item_update_type_t updateType)
void ItemStore::addItem(const ItemAddRequest& item)
{
qDebug()<<"Item add request for"<<item.payload->getName()<<item.payload->id();
std::shared_ptr<Item> matched = nullptr;
for(unsigned i = 0; i < items_.size(); i++ )
{
if(*items_[i] == *item)
if(*items_[i] == *item.payload)
{
matched = items_[i];
assert(matched->id() == items_[i]->id());
break;
}
}
if(!matched)
{
items_.push_back(std::shared_ptr<Item>(item));
connect(item.get(), &Item::updated, this, &ItemStore::itemUpdateSlot);
qDebug()<<"Item"<<item->getName()<<"added"<<(item->getLoaded() ? "from loaded" : "");
items_.push_back(item.payload);
connect(item.payload.get(), &Item::updated, this, &ItemStore::itemUpdateSlot);
qDebug()<<"Item"<<item.payload->getName()<<"added"<<(item.payload->getLoaded() ? "from loaded" : "");
itemAdded(std::weak_ptr<Item>(items_.back()));
}
else
else if(!item.changes.isNone())
{
ItemUpdateRequest request = item->createValueUpdateRequest(item->getValue(),
updateType,
updateType == ITEM_UPDATE_LOADED);
request.newActors = item->getActors();
qDebug()<<"Item"<<item.payload->getName()<<"was matched with"<<matched->getName()<<"and has changes";
ItemUpdateRequest request = item.updateRequest();
updateItem(request);
}
}
void ItemStore::addItems(const std::vector<std::shared_ptr<Item>>& itemIn,
item_update_type_t updateType)
void ItemStore::addItems(const std::vector<ItemAddRequest>& itemIn)
{
for(unsigned j = 0; j < itemIn.size(); j++)
addItem(itemIn[j], updateType);
addItem(itemIn[j]);
}
void ItemStore::removeItem(const ItemData& item)
@ -57,8 +56,15 @@ void ItemStore::removeItem(const ItemData& item)
void ItemStore::replaceItems(const std::vector<std::shared_ptr<Item>>& items)
{
qDebug()<<__func__;
addItems(items, ITEM_UPDATE_LOADED);
for(const std::shared_ptr<Item>& item : items)
{
ItemAddRequest request;
request.changes = ItemFieldChanges(true);
request.changes.actors = true;
request.type = ITEM_UPDATE_LOADED;
request.payload = item;
addItem(request);
}
std::vector<ItemData> deletedItems;
for(std::shared_ptr<Item> item : items_)
{

View file

@ -39,8 +39,8 @@ signals:
public slots:
void removeItem(const ItemData& item);
void addItem(const std::shared_ptr<Item>& item, item_update_type_t updateType);
void addItems(const std::vector<std::shared_ptr<Item>>& itemsIn, item_update_type_t updateType);
void addItem(const ItemAddRequest& item);
void addItems(const std::vector<ItemAddRequest>& itemsIn);
void replaceItems(const std::vector<std::shared_ptr<Item>>& items);
void updateItems(const std::vector<ItemUpdateRequest>& updates);
void updateItem(const ItemUpdateRequest& update);