Skip to content

Commit

Permalink
Resolve "Separate UI and non-UI code in ComponentModel"
Browse files Browse the repository at this point in the history
  • Loading branch information
Hugo Jiménez Hernández committed Dec 2, 2024
1 parent 072c538 commit c4c8cfa
Show file tree
Hide file tree
Showing 24 changed files with 515 additions and 434 deletions.
210 changes: 194 additions & 16 deletions src/libs/ivcore/ivcomponentlibrary.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "ivcomponentlibrary.h"

#include "ivxmlreader.h"

#include <QDir>
#include <QFileSystemWatcher>
#include <archetypes/archetypemodel.h>
Expand Down Expand Up @@ -29,6 +31,20 @@ IVComponentLibrary::IVComponentLibrary(const QString &path, const QString &model
{
d->libraryPath = path;
d->modelName = modelName;

connect(&d->watcher, &QFileSystemWatcher::directoryChanged, this, [this](const QString &path) {
/// Removed components which FS folder has been removed
processComponentsDeletedinFS(path);
});

connect(&d->watcher, &QFileSystemWatcher::fileChanged, this, [this](const QString &path) {
for (auto it = d->components.cbegin(); it != d->components.cend(); ++it) {
if ((*it)->componentPath == path) {
Q_EMIT componentUpdated(it.key());
break;
}
}
});
}

QString IVComponentLibrary::libraryPath() const
Expand Down Expand Up @@ -61,6 +77,7 @@ bool IVComponentLibrary::exportComponent(const QString &targetPath, const QList<

QDir targetDir(targetPath);
IVXMLWriter exporter;
connect(&exporter, &IVXMLWriter::exported, this, &IVComponentLibrary::componentExported);
if (!exporter.exportObjectsSilently(objects, targetDir.filePath(shared::kDefaultInterfaceViewFileName),
archetypesModel, exporter.templatePath(QLatin1String("interfaceview.ui")))) {
return false;
Expand All @@ -80,16 +97,6 @@ bool IVComponentLibrary::exportComponent(const QString &targetPath, const QList<
shared::ErrorItem::Error, tr("Error during ASN.1 file copying: %1").arg(asnFile));
}
}
QSharedPointer<IVComponentLibrary::Component> component =
QSharedPointer<IVComponentLibrary::Component>(new Component);
component->componentPath = targetPath;
component->asn1Files = asn1FilesPaths;
for (const auto obj : objects) {
component->rootIds.append(obj->id());
d->components.insert(obj->id(), component);
}
d->watcher.addPath(component->componentPath);

copyImplementation(ivDir, targetDir, objects);
shared::QMakeFile::createProFileForDirectory(targetPath, asn1FilesPathsExternal);

Expand All @@ -98,14 +105,185 @@ bool IVComponentLibrary::exportComponent(const QString &targetPath, const QList<

void IVComponentLibrary::removeComponent(const shared::Id &id)
{
auto component = d->components.value(id);
for (auto id : component->rootIds) {
d->components.remove(id);
auto component = d->components.take(id);
if (!component.isNull()) {
auto idsToRemove = component->rootIds;
d->components.removeIf(
[&idsToRemove](QHash<shared::Id, QSharedPointer<IVComponentLibrary::Component>>::Iterator it) {
return idsToRemove.contains(it.key());
});
d->watcher.removePath(component->componentPath);

QDir dir(QFileInfo(component->componentPath).absolutePath());
if (dir.exists()) {
dir.removeRecursively();
}
}
}

QSharedPointer<ivm::IVComponentLibrary::Component> IVComponentLibrary::loadComponent(const QString &path)
{
if (path.isEmpty() || !QFileInfo::exists(path)) {
qDebug() << path << "doesn't exist";
return nullptr;
}

shared::ErrorHub::setCurrentFile(path);
ivm::IVXMLReader parser;
if (!parser.readFile(path)) {
shared::ErrorHub::addError(shared::ErrorItem::Error, parser.errorString(), path);
shared::ErrorHub::clearCurrentFile();
return nullptr;
}

QSharedPointer<ivm::IVModel> model { new ivm::IVModel(ivm::IVPropertyTemplateConfig::instance()) };
model->initFromObjects(parser.parsedObjects(), parser.externalAttributes());

shared::ErrorHub::clearCurrentFile();
if (!anyLoadableIVObjects(model->ivobjects().values())) {
return nullptr;
}

static const QStringList asn1extensions { QLatin1String("asn1"), QLatin1String("asn"), QLatin1String("acn") };
const QFileInfo fi(path);
const QDir dir = fi.absoluteDir();
auto asn1Files = shared::QMakeFile::readFilesList(
dir.absoluteFilePath(dir.dirName() + QLatin1String(".pro")), asn1extensions);

auto component = createComponent(path, asn1Files, rootIds(model->ivobjects().values()), model);
addComponent(component);
return component;
}

QList<shared::Id> IVComponentLibrary::rootIds(QVector<IVObject *> objects)
{
QList<shared::Id> ids;
std::for_each(objects.constBegin(), objects.constEnd(), [&objects, &ids](IVObject *obj) {
if (!obj->parentObject()) {
ids.append(obj->id());
}
});
return ids;
}

QSharedPointer<IVComponentLibrary::Component> IVComponentLibrary::createComponent(const QString &componentPath,
const QStringList &asn1Files, const QList<shared::Id> &rootIds, QSharedPointer<IVModel> model)
{
QSharedPointer<ivm::IVComponentLibrary::Component> component { new ivm::IVComponentLibrary::Component };
component->componentPath = componentPath;
component->asn1Files = asn1Files;
component->rootIds = rootIds;
component->model.swap(model);
return component;
}

void IVComponentLibrary::processComponentsDeletedinFS(const QString &path)
{
if (path != d->libraryPath)
return;

/// Get all interfaceview paths from fs
const QDir libDir(d->libraryPath);
const QStringList entries = libDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
QSet<QString> componentsPaths;
for (const QString &name : std::as_const(entries)) {
const QString relInterfaceviewPath = name + QDir::separator() + shared::kDefaultInterfaceViewFileName;
if (libDir.exists(relInterfaceviewPath)) {
componentsPaths.insert(libDir.absoluteFilePath(relInterfaceviewPath));
}
}

/// Get all loaded components with removing them in previously loaded paths
QSet<QString> existingComponents;
for (auto it = d->components.cbegin(); it != d->components.cend(); ++it) {
if (!componentsPaths.remove(it.value()->componentPath)) {
existingComponents.insert(it.value()->componentPath);
}
}
d->watcher.removePath(component->componentPath);

QDir dir(component->componentPath);
dir.removeRecursively();
/// Remove from the model non-existing in fs component
QList<shared::Id> idsToRemove;
for (const QString &path : std::as_const(existingComponents)) {
for (auto it = d->components.cbegin(); it != d->components.cend(); ++it) {
if (it.value()->componentPath == path) {
idsToRemove << it.key();
removeComponent(it.key());
break;
}
}
}
Q_EMIT componentsToBeRemovedFromModel(idsToRemove);
/// Add to the model new components
Q_EMIT componentsToBeLoaded(componentsPaths);
}

QVector<IVObject *> IVComponentLibrary::rootObjects(QVector<IVObject *> objects)
{
QVector<IVObject *> rootObjs;
std::for_each(objects.constBegin(), objects.constEnd(), [&objects, &rootObjs](IVObject *obj) {
if (!obj->parentObject()) {
rootObjs.append(obj);
}
});
return rootObjs;
}

QSharedPointer<IVComponentLibrary::Component> IVComponentLibrary::component(const shared::Id &id) const
{
auto it = d->components.constFind(id);
if (it != d->components.constEnd()) {
return (*it);
}
return nullptr;
}

QStringList IVComponentLibrary::asn1Files(const shared::Id &id) const
{
auto comp = component(id);
if (!comp.isNull()) {
return comp->asn1Files;
}
return QStringList();
}

QString IVComponentLibrary::componentPath(const shared::Id &id) const
{
auto comp = component(id);
if (!comp.isNull()) {
return comp->componentPath;
}
return QString();
}

QString IVComponentLibrary::modelName() const
{
return d->modelName;
}

QList<shared::Id> IVComponentLibrary::componentsIds()
{
return d->components.keys();
}

void IVComponentLibrary::unWatchComponent(const QString &componentPath)
{
d->watcher.removePath(componentPath);
}

void IVComponentLibrary::addComponent(const QSharedPointer<Component> &component)
{
for (auto id : std::as_const(component->rootIds)) {
d->components.insert(id, component);
}
d->watcher.addPath(component->componentPath);
}

bool IVComponentLibrary::anyLoadableIVObjects(QVector<IVObject *> objects)
{
return std::any_of(objects.begin(), objects.end(), [](IVObject *obj) {
auto type = obj->type();
return (type != ivm::IVObject::Type::InterfaceGroup);
});
}

bool IVComponentLibrary::resetTasteENV(const QString &path)
Expand Down
53 changes: 51 additions & 2 deletions src/libs/ivcore/ivcomponentlibrary.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/lgpl-2.1.html

#include <QObject>
#include <common.h>
#include <vemodel.h>
#include <ivmodel.h>

namespace ivm {

Expand All @@ -37,7 +37,7 @@ class IVComponentLibrary : public QObject
QStringList asn1Files;
QList<shared::Id> rootIds;
QString componentPath;
std::unique_ptr<shared::VEModel> model;
QSharedPointer<IVModel> model;
};

IVComponentLibrary(const QString &path, const QString &modelName);
Expand All @@ -60,9 +60,58 @@ class IVComponentLibrary : public QObject
* \param id
*/
void removeComponent(const shared::Id &id);
/*!
* \brief loadComponent tries to load the component taking into account that at least one of the objects in the
* model is not of type ivm::IVObject::Type::InterfaceGroup
* \param path to the interfaceview.xml file in the
* components library
* \return return a QSharePointer to a component
*/
QSharedPointer<ivm::IVComponentLibrary::Component> loadComponent(const QString &path);
/*!
* \brief rootObjects: objects that doesn't have a parentObject
* \param objects: list of IVObjects to be filtered
* \return
*/
QVector<IVObject *> rootObjects(QVector<IVObject *> objects);
/*!
* \brief component: get a component given an ID
* \param id
* \return QSharedPointer<ivm::IVComponentLibrary::Component>
*/
QSharedPointer<ivm::IVComponentLibrary::Component> component(const shared::Id &id) const;
/*!
* \brief asn1Files: returns asn1Files associated with that component
* \param id
* \return
*/
QStringList asn1Files(const shared::Id &id) const;
/*!
* \brief componentPath: returns the component's path given his Id
* \param id
* \return
*/
QString componentPath(const shared::Id &id) const;

QString modelName() const;
QList<shared::Id> componentsIds();
void unWatchComponent(const QString &componentPath);
Q_SIGNALS:
void componentUpdated(const shared::Id &id);
void componentsToBeLoaded(QSet<QString> componentsPaths);
void componentExported(const QString &filePath, bool ok);
void componentsToBeRemovedFromModel(QList<shared::Id> idsToRemove);

private:
bool anyLoadableIVObjects(QVector<ivm::IVObject *> objects);
QList<shared::Id> rootIds(QVector<ivm::IVObject *> objects);
QSharedPointer<Component> createComponent(const QString &componentPath, const QStringList &asn1Files,
const QList<shared::Id> &rootIds, QSharedPointer<IVModel> model);
void processComponentsDeletedinFS(const QString &path);

private:
struct IVComponentLibraryPrivate;
IVComponentLibraryPrivate *d;
void addComponent(const QSharedPointer<Component> &component);
};
} // ivm
6 changes: 5 additions & 1 deletion src/libs/ivcore/ivobject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ IVObject::IVObject(const IVObject::Type t, QObject *parent, const shared::Id &id
setModel(parentObject->model());
else if (IVModel *model = qobject_cast<IVModel *>(parent))
setModel(model);
else {
qDebug() << " model not established";
}
}

IVObject::~IVObject() { }
Expand Down Expand Up @@ -409,7 +412,8 @@ QList<EntityAttribute> IVObject::sortedAttributesValues(const EntityAttributes &

IVModel *IVObject::model() const
{
return qobject_cast<IVModel *>(shared::VEObject::model());
auto vemodel = shared::VEObject::model();
return qobject_cast<IVModel *>(vemodel);
}

bool IVObject::isRootObject() const
Expand Down
2 changes: 1 addition & 1 deletion src/libs/libiveditor/commands/cmdentitiesimport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ QSet<QString> fnTypeNames(const QVector<ivm::IVObject *> &objects)
}

CmdEntitiesImport::CmdEntitiesImport(const QList<ivm::IVObject *> &objects, ivm::IVFunctionType *parent,
ivm::IVModel *model, shared::ComponentModel *componentModel, Asn1Acn::Asn1SystemChecks *asn1Checks,
ivm::IVModel *model, IVComponentModel *componentModel, Asn1Acn::Asn1SystemChecks *asn1Checks,
const QPointF &pos)
: ComponentImportHelper(componentModel, asn1Checks)
, QUndoCommand()
Expand Down
3 changes: 2 additions & 1 deletion src/libs/libiveditor/commands/cmdentitiesimport.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,15 @@ class IVFunctionType;
}

namespace ive {
class IVComponentModel;
namespace cmd {

class CmdEntitiesImport : public ComponentImportHelper, public QUndoCommand
{
Q_OBJECT
public:
explicit CmdEntitiesImport(const QList<ivm::IVObject *> &entities, ivm::IVFunctionType *parent, ivm::IVModel *model,
shared::ComponentModel *componentModel, Asn1Acn::Asn1SystemChecks *asn1Checks, const QPointF &pos);
IVComponentModel *componentModel, Asn1Acn::Asn1SystemChecks *asn1Checks, const QPointF &pos);
~CmdEntitiesImport() override;

void redo() override;
Expand Down
2 changes: 1 addition & 1 deletion src/libs/libiveditor/commands/cmdentitiesinstantiate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ namespace ive {
namespace cmd {

CmdEntitiesInstantiate::CmdEntitiesInstantiate(ivm::IVFunctionType *entity, ivm::IVFunctionType *parent,
ivm::IVModel *model, shared::ComponentModel *componentModel, Asn1Acn::Asn1SystemChecks *asn1Checks,
ivm::IVModel *model, IVComponentModel *componentModel, Asn1Acn::Asn1SystemChecks *asn1Checks,
const QPointF &pos)
: ComponentImportHelper(componentModel, asn1Checks)
, QUndoCommand()
Expand Down
3 changes: 2 additions & 1 deletion src/libs/libiveditor/commands/cmdentitiesinstantiate.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class IVModel;
}

namespace ive {
class IVComponentModel;
namespace cmd {
class CmdEntityAttributeChange;

Expand All @@ -37,7 +38,7 @@ class CmdEntitiesInstantiate : public ComponentImportHelper, public QUndoCommand
Q_OBJECT
public:
explicit CmdEntitiesInstantiate(ivm::IVFunctionType *entity, ivm::IVFunctionType *parent, ivm::IVModel *model,
shared::ComponentModel *componentModel, Asn1Acn::Asn1SystemChecks *asn1Checks, const QPointF &pos);
IVComponentModel *componentModel, Asn1Acn::Asn1SystemChecks *asn1Checks, const QPointF &pos);
~CmdEntitiesInstantiate() override;

void redo() override;
Expand Down
Loading

0 comments on commit c4c8cfa

Please sign in to comment.