diff --git a/include/hal_core/netlist/netlist.h b/include/hal_core/netlist/netlist.h index 48f550918cf..415db8badbf 100644 --- a/include/hal_core/netlist/netlist.h +++ b/include/hal_core/netlist/netlist.h @@ -476,6 +476,7 @@ namespace hal /** * Remove a module from the netlist. + * Submodules, gates and nets under this module will be moved to the parent of this module. * * @param[in] module - The module. * @returns True on success, false otherwise. diff --git a/plugins/gui/include/gui/basic_tree_model/tree_item.h b/plugins/gui/include/gui/basic_tree_model/base_tree_item.h similarity index 68% rename from plugins/gui/include/gui/basic_tree_model/tree_item.h rename to plugins/gui/include/gui/basic_tree_model/base_tree_item.h index 1fff2d116d9..ae9a9efe332 100644 --- a/plugins/gui/include/gui/basic_tree_model/tree_item.h +++ b/plugins/gui/include/gui/basic_tree_model/base_tree_item.h @@ -39,7 +39,7 @@ namespace hal * purpose, it uses QVariants as its main type of storage for its columns. (Note: Perhaps add * additional data in form of a list or map (split it from "normal" displayed column data) */ - class TreeItem + class BaseTreeItem { // maybe add enum type for all possible scenarios? or use additional data with key to access type // and handle type handling in model...e.g.: item->getAddData("type")(structure, more generalization,...) @@ -50,25 +50,25 @@ namespace hal * * @param item - The item to copy. */ - TreeItem(const TreeItem &item); + BaseTreeItem(const BaseTreeItem &item); public: /** * The constructor. */ - TreeItem(); + BaseTreeItem(); /** * Second constructor to immediately assign column data. * * @param columnData - The item's data. */ - TreeItem(QList columnData); + BaseTreeItem(QList columnData); /** * The destructor. */ - ~TreeItem(); + virtual ~BaseTreeItem(); /** * Get the data of a specific column (most in the form of a string). @@ -76,14 +76,14 @@ namespace hal * @param column - The requested column. * @return The data if within the column count. Empty QVariant otherwise. */ - QVariant getData(int column); + virtual QVariant getData(int column) const = 0; /** * Sets the data for all columns. * * @param data - Each entry in the list represents one column. */ - void setData(QList data); + virtual void setData(QList data) = 0; /** * Sets the data for a specified column. The index must be within @@ -92,28 +92,28 @@ namespace hal * @param index - The column to set the new data. * @param data - The new column data. */ - void setDataAtIndex(int index, QVariant data); + virtual void setDataAtIndex(int index, QVariant& data) = 0; /** * Appends a new column to the item. * * @param data - The data of the new column. */ - void appendData(QVariant data); + virtual void appendData(QVariant data) = 0; /** * Get the item's parent. * * @return The parent. */ - TreeItem* getParent(); + virtual BaseTreeItem* getParent() const; /** * Sets the item's parent. * * @param parent - The parent. */ - void setParent(TreeItem* parent); + virtual void setParent(BaseTreeItem* parent); /** * Get the child of a specific row. @@ -121,21 +121,21 @@ namespace hal * @param row - The requested row. * @return The child if within bounds. Nullptr otherwise. */ - TreeItem* getChild(int row); + virtual BaseTreeItem* getChild(int row) const; /** * Get the list of all children. * * @return The list of children. */ - QList getChildren(); + virtual QList getChildren() const; /** * Appends a child. * * @param child - The child to append. */ - void appendChild(TreeItem* child); + virtual void appendChild(BaseTreeItem* child); /** * Inserts a child at the given index. If the index exceeds the amount @@ -144,7 +144,7 @@ namespace hal * @param index - The position at which to insert. * @param child - The child to insert. */ - void insertChild(int index, TreeItem* child); + virtual void insertChild(int index, BaseTreeItem* child); /** * Removes the child at the given row and returns it. @@ -152,7 +152,7 @@ namespace hal * @param row - The row from which to remove the child. * @return The removed child. Nullptr if row was out of bounds. */ - TreeItem* removeChildAtPos(int row); + virtual BaseTreeItem* removeChildAtPos(int row); /** * Removes the given item and returns True if removing was successful @@ -161,21 +161,21 @@ namespace hal * @param child - The child to remove. * @return True on success, False otherwise. */ - bool removeChild(TreeItem* child); + virtual bool removeChild(BaseTreeItem* child); /** * Get the number of children. * * @return The number of children. */ - int getChildCount(); + virtual int getChildCount() const; /** * Get the number of currently stored column data. * * @return The column count. */ - int getColumnCount(); + virtual int getColumnCount() const = 0; /** * Convenience method to get the row for a given item. @@ -184,7 +184,7 @@ namespace hal * @param child - The child for which the row is requested. * @return The row if the item is a child, -1 otherwise. */ - int getRowForChild(TreeItem* child); + virtual int getRowForChild(const BaseTreeItem* child) const; /** * Convenience method to get the row of this item within @@ -192,7 +192,7 @@ namespace hal * * @return The row of this item if it has a parent, -1 otherwise. */ - int getOwnRow(); + virtual int getOwnRow(); /** * Stores additional data. Can be accessed by getAdditionalData. @@ -201,7 +201,7 @@ namespace hal * @param key - The key to store the data under. * @param data - The actual data to store. */ - void setAdditionalData(QString key, QVariant data); + virtual void setAdditionalData(QString key, QVariant data); /** * Retrieve the data stored under the given key. @@ -209,16 +209,64 @@ namespace hal * @param key - The key for the requested data. * @return The data if something was stored under the key, empty QVariant otherwise. */ - QVariant getAdditionalData(QString key); + virtual QVariant getAdditionalData(QString key) const; private: - TreeItem* mParent; - QList mChildren; - QList mData; + BaseTreeItem* mParent; + QList mChildren; // experimental, additional data (for anything) QMap mAdditionalData; //QList mAdditionalData; }; + + /** + * Since the BaseTreeItem class is pure virtual it cannot be instanciated for + * root tree item. + * + * RootTreeItem class also provides the header labels. + */ + class RootTreeItem : public BaseTreeItem + { + QStringList mHeaderLabels; + public: + RootTreeItem(const QStringList& labels) : mHeaderLabels(labels) {;} + + /** + * Get header label for section. + * @param column The section of the header. + * @return The label for the header. + */ + QVariant getData(int column) const override; + + /** + * Set header label to new value. If element in list does not exist it gets created. + * @param column The section of the header. + * @param data The string value. + */ + void setData(QList data) override; + + /** + * Sets the data for a specified column. The index must be within + * already existing boundaries (for example, add dummy data beforehand). + * + * @param index - The column to set the new data. + * @param data - The new column data. + */ + void setDataAtIndex(int index, QVariant& data) override; + + /** + * Appends a new column to the item. + * + * @param data - The data of the new column. + */ + void appendData(QVariant data) override; + + /** + * Get number of sections for which header label exist. + * @return The number of sections. + */ + int getColumnCount() const override { return mHeaderLabels.size(); } + }; } diff --git a/plugins/gui/include/gui/basic_tree_model/base_tree_model.h b/plugins/gui/include/gui/basic_tree_model/base_tree_model.h index c836f1cc2dc..a654035c4e9 100644 --- a/plugins/gui/include/gui/basic_tree_model/base_tree_model.h +++ b/plugins/gui/include/gui/basic_tree_model/base_tree_model.h @@ -26,7 +26,7 @@ #pragma once #include -#include "tree_item.h" +#include "base_tree_item.h" namespace hal { @@ -101,7 +101,7 @@ namespace hal * * @param firstLevelItems - All items that will be appended to this model's root item. */ - void setContent(QList firstLevelItems); + void setContent(QList firstLevelItems); /** * Resets the model (deletes the tree). @@ -113,7 +113,7 @@ namespace hal * classed to initialize * @param labels */ - void setHeaderLabels(QList labels); + void setHeaderLabels(const QStringList& label); // important converter methods /** @@ -122,7 +122,7 @@ namespace hal * @param item - The item from which to get the index. * @return The index. */ - QModelIndex getIndexFromItem(TreeItem* item) const; + QModelIndex getIndexFromItem(BaseTreeItem* item) const; /** * Helper method to convert between the index and its item. @@ -130,7 +130,7 @@ namespace hal * @param index - The index to convert. * @return The internal item. */ - TreeItem* getItemFromIndex(QModelIndex index) const; + BaseTreeItem* getItemFromIndex(QModelIndex index) const; /** * Convenient function to get the root item to which the tree is appended @@ -138,10 +138,10 @@ namespace hal * * @return The root item. */ - TreeItem* getRootItem() const; + BaseTreeItem* getRootItem() const; protected: - TreeItem* mRootItem; + RootTreeItem* mRootItem; }; } diff --git a/plugins/gui/include/gui/grouping/grouping_color_serializer.h b/plugins/gui/include/gui/grouping/grouping_color_serializer.h index fd292865fab..ab5f7937c08 100644 --- a/plugins/gui/include/gui/grouping/grouping_color_serializer.h +++ b/plugins/gui/include/gui/grouping/grouping_color_serializer.h @@ -30,7 +30,6 @@ namespace hal { class GroupingTableModel; - class ModuleModel; class GroupingColorSerializer : public ProjectSerializer { @@ -44,18 +43,4 @@ namespace hal { void restore(GroupingTableModel *gtm); }; - - class ModuleColorSerializer : public ProjectSerializer - { - void restoreModuleColor(const std::filesystem::path& loaddir, const std::string& jsonfile, ModuleModel *mm = nullptr); - void serializeColorRecursion(QJsonArray& mcArr, const ModuleModel* mm, QModelIndex parent=QModelIndex()); - public: - ModuleColorSerializer(); - - std::string serialize(Netlist* netlist, const std::filesystem::path& savedir, bool isAutosave) override; - - void deserialize(Netlist* netlist, const std::filesystem::path& loaddir) override; - - void restore(ModuleModel *mm); - }; } diff --git a/plugins/gui/include/gui/gui_utils/graphics.h b/plugins/gui/include/gui/gui_utils/graphics.h index 329cd68037b..c04cc0a4acf 100644 --- a/plugins/gui/include/gui/gui_utils/graphics.h +++ b/plugins/gui/include/gui/gui_utils/graphics.h @@ -80,14 +80,5 @@ namespace hal * @return The (perhabs styled) icon. */ extern QIcon getStyledSvgIcon(const QString& from_to_colors, const QString& svg_path); - - /** - * Returns a somewhat random color through a funny method (should be the same order - * of colors each time the program starts). This brilliant piece of code MUST NEVER - * BE REMOVED, PURE COMEDY! - * - * @return The "random" color. - */ - extern QColor getRandomColor(); } } diff --git a/plugins/gui/include/gui/module_model/module_color_manager.h b/plugins/gui/include/gui/module_model/module_color_manager.h new file mode 100644 index 00000000000..692a4db18d5 --- /dev/null +++ b/plugins/gui/include/gui/module_model/module_color_manager.h @@ -0,0 +1,125 @@ +// MIT License +// +// Copyright (c) 2019 Ruhr University Bochum, Chair for Embedded Security. All Rights reserved. +// Copyright (c) 2019 Marc Fyrbiak, Sebastian Wallat, Max Hoffmann ("ORIGINAL AUTHORS"). All rights reserved. +// Copyright (c) 2021 Max Planck Institute for Security and Privacy. All Rights reserved. +// Copyright (c) 2021 Jörn Langheinrich, Julian Speith, Nils Albartus, René Walendy, Simon Klix ("ORIGINAL AUTHORS"). All Rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include "hal_core/defines.h" +#include "hal_core/netlist/project_serializer.h" +#include +#include +#include + +namespace hal +{ + /** + * Manages the module colors which will be assigned either by an "random" algorithm or manually by user. + * Quotes around "random" indicate it is not random at all, it is some homemade spinning around in HSV color circle. + */ + class ModuleColorManager : public QObject + { + Q_OBJECT + + Q_SIGNALS: + /** + * Q_SIGNAL to notify that the color of a module has been changed. + * + * @param id - Id of the module with the changed color + */ + void moduleColorChanged(u32 id) const; + + public: + ModuleColorManager(QObject* parent = nullptr); + + /** + * Gets the module color of a module of a specific id. + * + * @param id - The module id of the module to get the color for + * @returns the color of the module + */ + QColor moduleColor(u32 id) const; + + /** + * Changes the color of a module. + * + * @param id - The id of the module + * @param col - The new color + * @returns the old color of the module (used to create an undo action easier) + */ + QColor setModuleColor(u32 id, const QColor& col); + + /** + * Changes the color of a module to a random color. + * + * @param id - The id of the module + * @returns the old color of the module (used to create an undo action easier) + */ + QColor setRandomColor(u32 id); + + /** + * Removes the color that belongs to the given id. + * + * @param id - The module id for which to remove the color. + */ + void removeColor(u32 id); + + /** + * Getter for map of all module colores + * + * @returns The map of all module colores + */ + QMap getColorMap() const; + + void clear(); + private: + + + /** + * Returns a somewhat random color through a funny method (should be the same order + * of colors each time the program starts). + * + * @return The "random" color. + */ + QColor getRandomColor(); + + QMap mModuleColors; + }; + + /** + * Persist module color settings to file and restore module color assignment from previous session + */ + class ModuleColorSerializer : public ProjectSerializer + { + void restoreModuleColor(const std::filesystem::path& loaddir, const std::string& jsonfile, ModuleColorManager *mcm = nullptr); + void serializeColorMap(QJsonArray& mcArr, const ModuleColorManager* mcm); + public: + ModuleColorSerializer(); + + std::string serialize(Netlist* netlist, const std::filesystem::path& savedir, bool isAutosave) override; + + void deserialize(Netlist* netlist, const std::filesystem::path& loaddir) override; + + void restore(ModuleColorManager *mcm); + }; +} diff --git a/plugins/gui/include/gui/module_model/module_item.h b/plugins/gui/include/gui/module_model/module_item.h index 2a692fea251..49bbdc9288b 100644 --- a/plugins/gui/include/gui/module_model/module_item.h +++ b/plugins/gui/include/gui/module_model/module_item.h @@ -26,6 +26,8 @@ #pragma once #include "hal_core/defines.h" +#include "gui/basic_tree_model/base_tree_model.h" + #include #include @@ -38,39 +40,28 @@ namespace hal * @ingroup gui * @brief An item in the ModuleModel. * - * The ModuleItem is one item in the ModuleModel item model. It represents one module of the netlist. + * The ModuleItem is one item in the ModuleModel item model. It represents either a module, a gate or a net of the netlist. */ - class ModuleItem + class ModuleItem : public BaseTreeItem { public: /** - * Constructor. - * - * @param id - The id of the module this item represents + * The possible types that a ModuleItem in the ModuleModel can have. */ - ModuleItem(const u32 id); + enum class TreeItemType {Module, Gate, Net}; - /** - * Appends a child ModuleItem to this ModuleItem. - * - * @param row - The index of the childs of this ModuleItem the new child should be moved to - * @param child - The new child to be inserted - */ - void insertChild(int row, ModuleItem* child); + void setData(QList data) override; + void setDataAtIndex(int index, QVariant& data) override; + void appendData(QVariant data) override; + int getColumnCount() const override; /** - * Removes a child ModuleItem from this ModuleItem. - * - * @param child - The child to remove - */ - void removeChild(ModuleItem* child); - - /** - * Inserts a child ModuleItem at the end of the children list of this ModuleItem. + * Constructor. * - * @param child - The child to be appended + * @param id - The id of the netlist item this ModuleItem represents + * @param type - The type of the netlist item */ - void appendChild(ModuleItem* child); + ModuleItem(const u32 id, const TreeItemType type = TreeItemType::Module); /** * Given a set of ModuleItems (in a map [id]->[ModuleItem]) this function adds each ModuleItem of this set as @@ -80,58 +71,13 @@ namespace hal */ void appendExistingChildIfAny(const QMap& moduleMap); - /** - * Inserts a child ModuleItem at the beginning of the children list of this ModuleItem. - * - * @param child - The child to be prepended - */ - void prependChild(ModuleItem* child); - - /** - * Gets the parent ModuleItem of this ModuleItem. - * - * @returns the parent ModuleItem - */ - ModuleItem* parent(); - - /** - * Get the child ModuleItem at a certain position in the children list of this ModuleItem. - * - * @param row - The position in the children list of this ModuleItem - * @returns then children ModuleItem at the specified position in the children list - */ - ModuleItem* child(int row); - - /** - * Gets the parent ModuleItem of this ModuleItem. - * - * @returns the parent ModuleItem. Returns a constant ModuleItem pointer - */ - const ModuleItem* constParent() const; - - /** - * Get the child ModuleItem at a certain position in the children list of this ModuleItem. - * - * @param row - The position in the children list of this ModuleItem - * @returns then children ModuleItem at the specified position in the children list. - * Returns a constant ModuleItem pointer - */ - const ModuleItem* constChild(int row) const; - - /** - * Gets the current amount of children of this ModuleItem - * - * @returns the amount of children - */ - int childCount() const; - /** * Gets the data of this item model item i.e. the name of this ModuleItem if column=1. * * @param column - The column to get the data for * @returns the data in the specified column of this ModuleItem */ - QVariant data(int column) const; + QVariant getData(int column) const override; /** * Gets the index of this ModuleItem in the list of children ModuleItems of its parent. @@ -141,53 +87,39 @@ namespace hal int row() const; /** - * Gets the name of the module this ModuleItem represents. + * Gets the name of the netlist item this ModuleItem represents. * - * @returns the modules name + * @returns the netlist items name */ QString name() const; /** - * Gets the id of the module this ModuleItem represents. + * Gets the id of the netlist item this ModuleItem represents. * * @returns the module id */ u32 id() const; - /** - * Gets the color of the module this ModuleItem represents. - * - * @returns the module color - */ - QColor color() const; - /** * Checks if this ModuleItem is currently highlighted. * - * @returns true iff this ModuleItem is currently highlighted. + * @returns true if this ModuleItem is currently highlighted. */ bool highlighted() const; /** - * Sets the parent ModuleItem of this ModuleItem. + * Gets the type of the netlist item this ModuleItem represents. * - * @param parent - The new parent + * @returns the ModuleItem type */ - void setParent(ModuleItem* parent); + TreeItemType getType() const; /** * Sets the name of this ModuleItem (not the underlying module). * * @param name - The new name */ - void set_name(const QString& name); - - /** - * Sets the color of the module this ModuleItem represents. - * - * @param color - The new color - */ - void setColor(const QColor& color); + void setName(const QString& name); /** * Marks/Unmarks this ModuleItem as highlighted. @@ -198,13 +130,10 @@ namespace hal void setHighlighted(const bool highlighted); private: - ModuleItem* mParent; - QList mChildItems; - u32 mId; + TreeItemType mType; QString mName; - QColor mColor; bool mHighlighted; }; } diff --git a/plugins/gui/include/gui/module_model/module_model.h b/plugins/gui/include/gui/module_model/module_model.h index c7e972552f6..7baaf7bb281 100644 --- a/plugins/gui/include/gui/module_model/module_model.h +++ b/plugins/gui/include/gui/module_model/module_model.h @@ -1,20 +1,20 @@ // MIT License -// +// // Copyright (c) 2019 Ruhr University Bochum, Chair for Embedded Security. All Rights reserved. // Copyright (c) 2019 Marc Fyrbiak, Sebastian Wallat, Max Hoffmann ("ORIGINAL AUTHORS"). All rights reserved. // Copyright (c) 2021 Max Planck Institute for Security and Privacy. All Rights reserved. // Copyright (c) 2021 Jörn Langheinrich, Julian Speith, Nils Albartus, René Walendy, Simon Klix ("ORIGINAL AUTHORS"). All Rights reserved. -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -28,16 +28,17 @@ #include "hal_core/defines.h" #include "gui/gui_utils/sort.h" #include "hal_core/netlist/module.h" +#include "gui/module_model/module_item.h" + #include #include #include -#include #include +#include namespace hal { - class ModuleItem; /** * @ingroup gui @@ -45,7 +46,7 @@ namespace hal * * The ModuleModel is the item model that represents the modules and their hierarchy in the netlist. */ - class ModuleModel : public QAbstractItemModel + class ModuleModel : public BaseTreeModel { Q_OBJECT @@ -60,41 +61,6 @@ namespace hal explicit ModuleModel(QObject* parent = nullptr); // === Pure Virtual === - /** - * Returns the index of the item in the model specified by the given row, column and parent index. - * - * @param row - The row of the item - * @param column - The column of the item - * @param parent - the index of the parent of the item - * @returns the index at the specified position - */ - QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; - - /** - * Returns the parent of the model item with the given index. If the item has no parent (i.e. index is - * invalid or module is the top module), and invalid QModelIndex is returned. - * - * @param index - The index to find the parent for - * @returns the model index of the parent - */ - QModelIndex parent(const QModelIndex& index) const override; - - /** - * Returns the number of rows under the given parent (i.e. the number of children of the parent). - * - * @param parent - The model index of the parent - * @returns the number of rows under the given parent - */ - int rowCount(const QModelIndex& parent = QModelIndex()) const override; - - /** - * Returns the number of columns for the children of the given parent. Since the module model only contains - * one column this function returns always 1. - * - * @param parent - The model index of the parent - * @returns the number of columns for the children of the given parent. Always 1. - */ - int columnCount(const QModelIndex& parent = QModelIndex()) const override; /** * Returns the data stored under the given role for the item referred to by the index. @@ -114,42 +80,32 @@ namespace hal */ Qt::ItemFlags flags(const QModelIndex& index) const override; - /** - * Returns the data for the given role and section in the header with the specified orientation. - * Since the model has not headers, an empty QVariant is always returned. - * - * @param section - The section - * @param orientation - The orientation - * @param role - The role - * @returns the header data. Always empty. - */ - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - // === Others === /** * Returns the ModuleItem stored under the specified model index. * - * @param index - The model index to get the module item from + * @param index - The model index to get the ModuleItem from * @returns the module item at the specified index */ ModuleItem* getItem(const QModelIndex& index) const; /** - * Returns the module index where the specified ModuleItem can be found. + * Returns the index where the specified ModuleItem can be found. * - * @param item - The module item to search for in the item model + * @param item - The ModuleItem to search for in the item model * @returns the model index of the specified ModuleItem */ QModelIndex getIndex(const ModuleItem* const item) const; /** - * Returns the ModuleItem for a specified module id. + * Returns the ModuleItem for a specified id and type. * - * @param module_id - The id of the module to get the ModuleItem for - * @returns the ModuleItem with the id module_id + * @param module_id - The id of the ModuleItem + * @param type - The type of the ModuleItem + * @returns the ModuleItem with the specified id and type. */ - ModuleItem* getItem(const u32 module_id) const; + ModuleItem* getItem(const u32 id, ModuleItem::TreeItemType type = ModuleItem::TreeItemType::Module) const; /** * Initializes the item model using the global netlist object gNetlist. @@ -157,7 +113,7 @@ namespace hal void init(); /** - * Clears the item model. + * Clears the item model and deletes all ModuleItems. */ void clear(); @@ -170,80 +126,131 @@ namespace hal void addModule(const u32 id, const u32 parent_module); /** - * Recursively adds all given modules with all their sub modules (and their submodules and so on...) to - * the item model. + * Add a gate to the item model. For the specified gate a new ModuleItem is created and stored. * - * @param modules - The list of modules which should be added to the item model together - * with all their submodules. + * @param id - The id of the gate to add. + * @param parent_module - The id of the parent module of the gate to add. */ - void addRecursively(const std::vector& modules); + void addGate(const u32 id, const u32 parent_module); /** - * Removes a module from the item model. The specified module MUST be contained in the item model. + * Add a net to the item model. For the specified net a new ModuleItem is created and stored. * - * @param id - The id of the model to remove + * @param id - The id of the net to add. + * @param parent_module - The id of the parent module of the net to add. */ - void remove_module(const u32 id); + void addNet(const u32 id, const u32 parent_module); /** - * Updates the ModuleItem for the specified module. The specified module MUST be contained in the item model. + * Recursively adds the given module with all of its submodules (and their submodules and so on...) + * and the gates those modules to the item model. * - * @param id - The id of the module to update + * @param module - The module which should be added to the item model together with all its + * submodules, gates and nets. */ - void updateModule(const u32 id); + void addRecursively(const Module* module); -// void addModule(u32 id, u32 parent_module); -// void addRecursively(const std::vector& modules); -// void remove_module(u32 id); -// void updateModule(u32 id); + /** + * Removes a module from the item model. The specified module MUST be contained in the item model. + * + * @param id - The id of the module to remove + */ + void removeModule(const u32 id); + /** + * Removes a gate from the item model. The specified gate MUST be contained in the item model. + * + * @param id - The id of the gate to remove + */ + void removeGate(const u32 id); /** - * Returns true if the item model is currently changed/updated. This is the case while adding and - * removing modules to/from the item model. It can be used to ignore certain signals sent by the item model - * while the model is modified. + * Removes a net from the item model. * - * @returns true while the item model is modified. Returns false otherwise. + * @param id - The id of the net to remove */ - bool isModifying(); + void removeNet(const u32 id); + + /** + * Moves the ModuleItem corresponding to the module under it's new parent ModuleItem. + * The items for all nets, that have at least one source or one destination within the module, + * will be updated afterwards. + * + * @param module The module whose parent has changed. + */ + void handleModuleParentChanged(const Module* module); + + /** + * Handles the assigment of gates to modules. + * If the gate does not yet exist in the item model, a new one is created. + * All nets, that are connected to the gate, will be updated. + */ + void handleModuleGateAssinged(const u32 id, const u32 parent_module); + + /** + * Updates the position of a net in the ModuleTree. + * The net will be placed under the deepest module, that contains all sources and destinations of the net. + * If no suitable parent could be found, then the net will instead be placed under the top module. + * If the net does not exist in the item model (e.g. it's a global net), then nothing is updated. + * + * @param net The net whose source or destination might have changed. + */ + void updateNet(const Net* net); /** - * Gets the module color of a module of a specific id. + * Reattaches the ModuleItem corresponding to the specified module to a new parent item. + * The new parent must already be set in the Module object. * - * @param id - The module id of the module to get the color for - * @returns the color of the module + * @param module - The module whose ModuleItem will be reattached to a new parent in the item model. + */ + void updateModuleParent(const Module* module); + + /** + * Updates the ModuleItem for the specified module. The specified module MUST be contained in the item model. + * + * @param id - The id of the module to update */ - QColor moduleColor(u32 id) const; + void updateModuleName(const u32 id); /** - * Changes the color of a module. + * Updates the ModuleItem for the specified gate. The specified gate MUST be contained in the item model. * - * @param id - The id of the module - * @param col - The new color - * @returns the old color of the module (used to create an undo action easier) + * @param id - The id of the gate to update */ - QColor setModuleColor(u32 id, const QColor& col); + void updateGateName(const u32 id); /** - * Changes the color of a module to a random color. + * Updates the ModuleItem for the specified net. The specified gate MUST be contained in the item model. * - * @param id - The id of the module - * @returns the old color of the module (used to create an undo action easier) + * @param id - The id of the net to update */ - QColor setRandomColor(u32 id); + void updateNetName(const u32 id); /** - * Removes the color that belongs to the given id. + * Returns true if the item model is currently changed/updated. This is the case while adding and + * removing modules to/from the item model. It can be used to ignore certain signals sent by the item model + * while the model is modified. * - * @param id - The module id for which to remove the color. + * @returns true while the item model is modified. Returns false otherwise. */ - void removeColor(u32 id); + bool isModifying(); private: - ModuleItem* mTopModuleItem; - - QMap mModuleItems; - QMap mModuleColors; + /** + * Searches for a new parent module, such that it is the deepest module in the hierarchy, that contains all + * sources and destinations of the net. + * + * @param net The net for which a new parent should be searched. + * + * @return The new parent module, that contains all sources and destinations of net. If no such parent could be found + * (e.g. net has no sources or destinations), nullptr is returned instead. + */ + Module* findNetParent(const Net* net); + + QMap mModuleMap; + QMap mGateMap; + QMap mNetMap; + std::array*, 3> mModuleItemMaps = {&mModuleMap, &mGateMap, &mNetMap};; bool mIsModifying; }; diff --git a/plugins/gui/include/gui/module_model/module_proxy_model.h b/plugins/gui/include/gui/module_model/module_proxy_model.h index d142763de15..7954fe021a1 100644 --- a/plugins/gui/include/gui/module_model/module_proxy_model.h +++ b/plugins/gui/include/gui/module_model/module_proxy_model.h @@ -64,10 +64,23 @@ namespace hal */ void setSortMechanism(gui_utility::mSortMechanism sortMechanism); + /** + * Toggles whether or not nets are accepted by the filter. + * @returns true if nets are filtered out now. false if not. + */ + bool toggleFilterNets(); + + /** + * Toggles whether or not gates are accepted by the filter. + * @returns true if gates are filtered out now. false if not. + */ + bool toggleFilterGates(); + protected: /** * Overrides QSortFilterProxyModel::filterAcceptsRow to implement the filter logic based on the regular - * expression stored by setFilterRegularExpression.
+ * expression stored by setFilterRegularExpression. Also filters nets or gates, depending on the state + * of the toggle buttons.
* Returns true if the item in the row indicated by sourceRow and sourceParent should be included * in the model. * TODO: Filtering seems to be broken. Can't search for submodules. Works only for the topmodule. @@ -79,7 +92,8 @@ namespace hal bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override; /** - * Implements a comparison operator used for sorting. In this case it is based on the module names. + * Implements a comparison operator used for sorting. + * In this case it is based on the ModuleItem names and types. * * @param source_left - The model index of the left element * @param source_right - The model index of the right element @@ -89,5 +103,8 @@ namespace hal private: gui_utility::mSortMechanism mSortMechanism; + + bool mFilterNets; + bool mFilterGates; }; } diff --git a/plugins/gui/include/gui/module_widget/module_tree_view.h b/plugins/gui/include/gui/module_widget/module_tree_view.h index e143a09b7cb..5710163fce7 100644 --- a/plugins/gui/include/gui/module_widget/module_tree_view.h +++ b/plugins/gui/include/gui/module_widget/module_tree_view.h @@ -56,5 +56,10 @@ namespace hal * @param event */ void mousePressEvent(QMouseEvent* event); + + /** + * Sets the default width of each column. MUST be called after setting the model. + */ + void setDefaultColumnWidth(); }; } // namespace hal diff --git a/plugins/gui/include/gui/module_widget/module_widget.h b/plugins/gui/include/gui/module_widget/module_widget.h index 0eb15955d34..01b91bd8620 100644 --- a/plugins/gui/include/gui/module_widget/module_widget.h +++ b/plugins/gui/include/gui/module_widget/module_widget.h @@ -57,6 +57,14 @@ namespace hal class ModuleWidget : public ContentWidget { Q_OBJECT + Q_PROPERTY(QString showNetsIconPath READ showNetsIconPath WRITE setShowNetsIconPath) + Q_PROPERTY(QString showNetsIconStyle READ showNetsIconStyle WRITE setShowNetsIconStyle) + Q_PROPERTY(QString hideNetsIconPath READ hideNetsIconPath WRITE setHideNetsIconPath) + Q_PROPERTY(QString hideNetsIconStyle READ hideNetsIconStyle WRITE setHideNetsIconStyle) + Q_PROPERTY(QString showGatesIconPath READ showGatesIconPath WRITE setShowGatesIconPath) + Q_PROPERTY(QString showGatesIconStyle READ showGatesIconStyle WRITE setShowGatesIconStyle) + Q_PROPERTY(QString hideGatesIconPath READ hideGatesIconPath WRITE setHideGatesIconPath) + Q_PROPERTY(QString hideGatesIconStyle READ hideGatesIconStyle WRITE setHideGatesIconStyle) Q_PROPERTY(QString searchIconPath READ searchIconPath WRITE setSearchIconPath) Q_PROPERTY(QString searchIconStyle READ searchIconStyle WRITE setSearchIconStyle) Q_PROPERTY(QString searchActiveIconStyle READ searchActiveIconStyle WRITE setSearchActiveIconStyle) @@ -102,6 +110,14 @@ namespace hal /** @name Q_PROPERTY READ Functions */ ///@{ + QString showNetsIconPath() const; + QString showNetsIconStyle() const; + QString hideNetsIconPath() const; + QString hideNetsIconStyle() const; + QString showGatesIconPath() const; + QString showGatesIconStyle() const; + QString hideGatesIconPath() const; + QString hideGatesIconStyle() const; QString searchIconPath() const; QString searchIconStyle() const; QString searchActiveIconStyle() const; @@ -110,6 +126,14 @@ namespace hal /** @name Q_PROPERTY WRITE Functions */ ///@{ + void setShowNetsIconPath(const QString &path); + void setShowNetsIconStyle(const QString &path); + void setHideNetsIconPath(const QString &path); + void setHideNetsIconStyle(const QString &path); + void setShowGatesIconPath(const QString &path); + void setShowGatesIconStyle(const QString &path); + void setHideGatesIconPath(const QString &path); + void setHideGatesIconStyle(const QString &path); void setSearchIconPath(const QString &path); void setSearchIconStyle(const QString &style); void setSearchActiveIconStyle(const QString &style); @@ -171,6 +195,17 @@ namespace hal */ void handleModuleRemoved(Module* module, u32 module_id); + private Q_SLOTS: + /** + * Q_SLOT to toggle the visibility of nets in the module widget. Called when the 'Toggle Net Visibility'-buttons was clicked. + */ + void handleToggleNetsClicked(); + + /** + * Q_SLOT to toggle the visibility of gates in the module widget. Called when the 'Toggle Gate Visibility'-buttons was clicked. + */ + void handleToggleGatesClicked(); + private Q_SLOTS: void handleDeleteShortcutOnFocusChanged(QWidget *oldWidget, QWidget *newWidget); @@ -181,14 +216,24 @@ namespace hal ModuleTreeView* mTreeView; Searchbar* mSearchbar; + QAction* mToggleNetsAction; + QString mShowNetsIconPath; + QString mShowNetsIconStyle; + QString mHideNetsIconPath; + QString mHideNetsIconStyle; + + QAction* mToggleGatesAction; + QString mShowGatesIconPath; + QString mShowGatesIconStyle; + QString mHideGatesIconPath; + QString mHideGatesIconStyle; + QString mSearchIconPath; QString mSearchIconStyle; QString mSearchActiveIconStyle; QAction* mFilterAction; - QSortFilterProxyModel* mCurrentModel; - QList mRegexps; bool mIgnoreSelectionChange; @@ -199,6 +244,12 @@ namespace hal void openModuleInView(const QModelIndex& index); + void openGateInView(const QModelIndex& index); + + void changeGateName(const QModelIndex& index); + + void changeNetName(const QModelIndex& index); + ModuleItem* getModuleItemFromIndex(const QModelIndex& index); }; diff --git a/plugins/gui/include/gui/netlist_relay/netlist_relay.h b/plugins/gui/include/gui/netlist_relay/netlist_relay.h index 03a8bd3fb1b..83085c6b8ae 100644 --- a/plugins/gui/include/gui/netlist_relay/netlist_relay.h +++ b/plugins/gui/include/gui/netlist_relay/netlist_relay.h @@ -27,6 +27,7 @@ #include "hal_core/netlist/event_system/event_handler.h" #include "gui/grouping/grouping_color_serializer.h" +#include "gui/module_model/module_color_manager.h" #include #include @@ -34,6 +35,8 @@ namespace hal { class ModuleItem; class ModuleModel; + class ModuleColorManager; + class ModuleColorSerializer; class Module; /** @@ -88,7 +91,14 @@ namespace hal * * @returns the module model */ - ModuleModel* getModuleModel(); + ModuleModel* getModuleModel() const; + + /** + * Accesses the module color manager + * + * @returns the module color manager + */ + ModuleColorManager* getModuleColorManager() const; /** * Changes the name of a specific module by asking the user for a new name in a 'Rename'-dialogue. @@ -584,17 +594,6 @@ namespace hal */ void groupingModuleRemoved(Grouping* grp, u32 id) const; - /*======================================= - Other Signals - ========================================*/ - - /** - * Q_SIGNAL to notify that the color of a module has been changed. - * - * @param m - The module with the changed color - */ - void moduleColorChanged(Module* m) const; - public Q_SLOTS: /** * Q_SLOT to handle that a netlist has been opened. @@ -621,6 +620,7 @@ namespace hal QMap mModuleColors; ModuleModel* mModuleModel; + ModuleColorManager* mModuleColorManager; ModuleColorSerializer mColorSerializer; enum ThreadEventType { TetNetlist, TetModule, TetGate, TetNet, TetGrouping }; }; diff --git a/plugins/gui/include/gui/selection_details_widget/gate_details_widget/gate_pin_tree.h b/plugins/gui/include/gui/selection_details_widget/gate_details_widget/gate_pin_tree.h index 2d22705060f..1d23ff76df1 100644 --- a/plugins/gui/include/gui/selection_details_widget/gate_details_widget/gate_pin_tree.h +++ b/plugins/gui/include/gui/selection_details_widget/gate_details_widget/gate_pin_tree.h @@ -33,7 +33,7 @@ namespace hal { class GatePinsTreeModel; class Gate; - class TreeItem; + class BaseTreeItem; class GraphNavigationWidget; /** @@ -98,8 +98,8 @@ namespace hal bool mClearSelection; //helper functions - void buildPythonMenuForPin(QMenu &menu, TreeItem* clickedPinItem); - void buildPythonMenuForPinGroup(QMenu &menu, TreeItem* clickedPinIGrouptem); + void buildPythonMenuForPin(QMenu &menu, BaseTreeItem* clickedPinItem); + void buildPythonMenuForPinGroup(QMenu &menu, BaseTreeItem* clickedPinIGrouptem); void addSourceOurDestinationToSelection(int netId, bool isInputPin); void handleNavigationCloseRequested(); void handleNavigationJumpRequested(const Node& origin, const u32 via_net, const QSet& to_gates, const QSet& to_modules); diff --git a/plugins/gui/include/gui/selection_details_widget/gate_details_widget/pin_tree_model.h b/plugins/gui/include/gui/selection_details_widget/gate_details_widget/pin_tree_model.h index 3002aed1b3f..142601fa32a 100644 --- a/plugins/gui/include/gui/selection_details_widget/gate_details_widget/pin_tree_model.h +++ b/plugins/gui/include/gui/selection_details_widget/gate_details_widget/pin_tree_model.h @@ -34,6 +34,25 @@ namespace hal class Gate; + class PinTreeItem : public BaseTreeItem + { + + private: + std::string mPinName; + QString mPinDirection; + QString mPinType; + QString mNetName; + public: + + PinTreeItem(const std::string& pinName, QString pinDirection, QString pinTypee, QString netName); + PinTreeItem(); + QVariant getData(int column) const override; + void setData(QList data) override; + void setDataAtIndex(int index, QVariant& data) override; + void appendData(QVariant data) override; + int getColumnCount() const override; + }; + /** * @ingroup gui * @brief A model to display the pins of a gate. @@ -87,7 +106,7 @@ class GatePinsTreeModel : public BaseTreeModel * @param item - The treeitem from which to get the connected nets. * @return A list of net ids. */ - QList getNetIDsOfTreeItem(TreeItem* item); + QList getNetIDsOfTreeItem(BaseTreeItem* item); /** * Get the type (enum) of a given item. @@ -95,7 +114,7 @@ class GatePinsTreeModel : public BaseTreeModel * @param item - The item for which the type is requested. * @return The item's type. */ - itemType getTypeOfItem(TreeItem* item); + itemType getTypeOfItem(BaseTreeItem* item); /** * Get the number of displayed pins (the number of pins of all types). @@ -117,7 +136,7 @@ class GatePinsTreeModel : public BaseTreeModel private: int mGateId; - QMap mPinGroupingToTreeItem; + QMap mPinGroupingToTreeItem; }; diff --git a/plugins/gui/include/gui/selection_details_widget/module_details_tab_widget.h b/plugins/gui/include/gui/selection_details_widget/module_details_tab_widget.h index 108276203fa..e1d86d99dd8 100644 --- a/plugins/gui/include/gui/selection_details_widget/module_details_tab_widget.h +++ b/plugins/gui/include/gui/selection_details_widget/module_details_tab_widget.h @@ -71,6 +71,9 @@ namespace hal */ void clear(); + private Q_SLOTS: + void handleModuleColorChanged(u32 id); + private: //general tab @@ -96,5 +99,7 @@ namespace hal //comment tab CommentWidget* mCommentWidget; + //store module id + u32 mModuleId; }; } diff --git a/plugins/gui/include/gui/selection_details_widget/module_details_widget/module_ports_tree.h b/plugins/gui/include/gui/selection_details_widget/module_details_widget/module_ports_tree.h index bf70d682e4c..75918f63aeb 100644 --- a/plugins/gui/include/gui/selection_details_widget/module_details_widget/module_ports_tree.h +++ b/plugins/gui/include/gui/selection_details_widget/module_details_widget/module_ports_tree.h @@ -33,7 +33,7 @@ namespace hal { class Module; class ModulePinsTreeModel; - class TreeItem; + class BaseTreeItem; /** * @brief A widget to display the ports of a given module. @@ -104,7 +104,7 @@ namespace hal * (and if yes it returns the group id, otherwise -1), * second boolean = true if only pins (and no groups) were selected. */ - std::tuple, std::pair, bool> getSelectedPins(); + std::tuple, std::pair, bool> getSelectedPins(); }; } diff --git a/plugins/gui/include/gui/selection_details_widget/module_details_widget/module_tree_model.h b/plugins/gui/include/gui/selection_details_widget/module_details_widget/module_tree_model.h index 9dd4d29f54f..0608a6bd89f 100644 --- a/plugins/gui/include/gui/selection_details_widget/module_details_widget/module_tree_model.h +++ b/plugins/gui/include/gui/selection_details_widget/module_details_widget/module_tree_model.h @@ -23,17 +23,38 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +#pragma once + #include "gui/basic_tree_model/base_tree_model.h" #include "hal_core/defines.h" #include #include +#include + namespace hal { class Module; class Gate; class Net; - class TreeItem; + class BaseTreeItem; + + class ModuleTreeitem : public BaseTreeItem + { + + private: + std::string mType; + int mId; + std::string mName; + public: + + ModuleTreeitem(const std::string& name, int id, std::string tp); + QVariant getData(int column) const override; + void setData(QList data) override; + void setDataAtIndex(int index, QVariant& data) override; + void appendData(QVariant data) override; + int getColumnCount() const override; + }; class ModuleTreeModel : public BaseTreeModel { @@ -68,7 +89,7 @@ namespace hal * @param item - The item for which the type is requested. * @return The item's type. */ - itemType getTypeOfItem(TreeItem* item) const; + itemType getTypeOfItem(BaseTreeItem* item) const; /** * Disconnects all events from the model. Can be called to increase performance when @@ -108,11 +129,11 @@ namespace hal bool mEventsConnected = false; int mModId; - QMap mModuleToTreeitems; - QMap mGateToTreeitems; + QMap mModuleToTreeitems; + QMap mGateToTreeitems; //necessary because setModule uses beginResetModel (should not be called by each recursive iteration) - void moduleRecursive(Module* mod, TreeItem* modItem); + void moduleRecursive(Module* mod, BaseTreeItem* modItem); //perhaps more performance instead of setting the whole displayed module anew void updateGatesOfModule(Module* mod); @@ -123,7 +144,7 @@ namespace hal * @param item - The requested item. * @return A module, net, or gate icon depending on the item's type. */ - QIcon getIconFromItem(TreeItem* item) const; + QIcon getIconFromItem(BaseTreeItem* item) const; void clearOwnStructures(); diff --git a/plugins/gui/include/gui/selection_details_widget/module_details_widget/netlist_elements_tree_model.h b/plugins/gui/include/gui/selection_details_widget/module_details_widget/netlist_elements_tree_model.h index 086d9185199..5bb90aa7240 100644 --- a/plugins/gui/include/gui/selection_details_widget/module_details_widget/netlist_elements_tree_model.h +++ b/plugins/gui/include/gui/selection_details_widget/module_details_widget/netlist_elements_tree_model.h @@ -27,7 +27,7 @@ #include #include -//#include "gui/new_selection_details_widget/models/tree_item.h" +//#include "gui/new_selection_details_widget/models/base_tree_item.h" #include "gui/basic_tree_model/base_tree_model.h" namespace hal @@ -35,7 +35,24 @@ namespace hal class Module; class Gate; class Net; - class TreeItem; + class BaseTreeItem; + + class NetlistElementsTreeitem : public BaseTreeItem + { + + private: + QString mType; + int mId; + QString mName; + public: + + NetlistElementsTreeitem(const QString& name, int id, QString tp); + QVariant getData(int column) const override; + void setData(QList data) override; + void setDataAtIndex(int index, QVariant& data) override; + void appendData(QVariant data) override; + int getColumnCount() const override; + }; /** * @ingroup utility_widgets-selection_details @@ -110,7 +127,7 @@ namespace hal * @param item - The item for which the type is requested. * @return The item's type. */ - itemType getTypeOfItem(TreeItem* item) const; + itemType getTypeOfItem(NetlistElementsTreeitem* item) const; /** * Get the module/gate/net id that the given item represents. @@ -119,7 +136,7 @@ namespace hal * @param item - The item from which to extract the id. * @return The corresponding module, gate, or net id. */ - int getRepresentedIdOfItem(TreeItem* item) const; + int getRepresentedIdOfItem(NetlistElementsTreeitem* item) const; /** @name Event Handler Functions */ @@ -173,12 +190,12 @@ namespace hal //1) 1 map that maps "raw element pointer (gate,net,module)" to a list of treeitems //2) 3 maps with either id->treeitems or pointer->treeitems //QMultiMap mElementToTreeitem; - QMultiMap mModuleToTreeitems; - QMultiMap mGateToTreeitems; - QMultiMap mNetToTreeitems; + QMultiMap mModuleToTreeitems; + QMultiMap mGateToTreeitems; + QMultiMap mNetToTreeitems; //necessary because setModule uses beginResetModel (should not be called by each recursive iteration) - void moduleRecursive(Module* mod, TreeItem* modItem, bool showGates = true, bool showNets = true); + void moduleRecursive(Module* mod, NetlistElementsTreeitem* modItem, bool showGates = true, bool showNets = true); /** * Utility function to determine the displayed icon for a given item @@ -186,7 +203,7 @@ namespace hal * @param item - The requested item. * @return A module, net, or gate icon depending on the item's type. */ - QIcon getIconFromItem(TreeItem* item) const; + QIcon getIconFromItem(NetlistElementsTreeitem* item) const; /** * Utility function to remove all net items of the given module item and @@ -195,7 +212,7 @@ namespace hal * * @param moduleItem - The module item to modify. */ - void updateInternalNetsOfModule(TreeItem* moduleItem); + void updateInternalNetsOfModule(NetlistElementsTreeitem* moduleItem); }; diff --git a/plugins/gui/include/gui/selection_details_widget/module_details_widget/port_tree_model.h b/plugins/gui/include/gui/selection_details_widget/module_details_widget/port_tree_model.h index 349bc1e0422..5167f9bfc48 100644 --- a/plugins/gui/include/gui/selection_details_widget/module_details_widget/port_tree_model.h +++ b/plugins/gui/include/gui/selection_details_widget/module_details_widget/port_tree_model.h @@ -35,6 +35,25 @@ namespace hal class Net; + class PortTreeItem : public BaseTreeItem + { + + private: + QString mPinName; + QString mPinDirection; + QString mPinType; + QString mNetName; + public: + + PortTreeItem(QString pinName, QString pinDirection, QString pinType, QString netName); + PortTreeItem(); + QVariant getData(int column) const override; + void setData(QList data) override; + void setDataAtIndex(int index, QVariant& data) override; + void appendData(QVariant data) override; + int getColumnCount() const override; + }; + /** * @brief A model to represent the ports of a module. */ @@ -87,7 +106,7 @@ namespace hal * @param item - The (port) item. * @return The net or nullptr. */ - Net* getNetFromItem(TreeItem* item); + Net* getNetFromItem(PortTreeItem* item); /** * Get the id of the module that is currently represented. @@ -103,7 +122,7 @@ namespace hal * @param item - The item for which the type is requested. * @return The item's type. */ - itemType getTypeOfItem(TreeItem* item) const; + itemType getTypeOfItem(PortTreeItem* item) const; /** * Returns the pin-id if the item represents a pin or the pingroup-id @@ -112,7 +131,7 @@ namespace hal * @param item - The item. * @return The pin- or pingroup-id. */ - int getIdOfItem(TreeItem* item) const; + int getIdOfItem(BaseTreeItem* item) const; /** @name Event Handler Functions */ @@ -143,20 +162,20 @@ namespace hal int mModuleId; // perhaps remove? Module* mModule; //name is (hopefully) enough to identify - QMap mNameToTreeItem; - QMap mIdToPinItem; - QMap mIdToGroupItem; + QMap mNameToTreeItem; + QMap mIdToPinItem; + QMap mIdToGroupItem; bool mIgnoreEventsFlag; - void insertItem(TreeItem* item, TreeItem* parent, int index); - void removeItem(TreeItem* item); + void insertItem(PortTreeItem* item, BaseTreeItem* parent, int index); + void removeItem(PortTreeItem* item); // helper functions for dnd for more clarity - void dndGroupOnGroup(TreeItem* droppedGroup, TreeItem* onDroppedGroup); - void dndGroupBetweenGroup(TreeItem* droppedGroup, int row); - void dndPinOnGroup(TreeItem* droppedPin, TreeItem* onDroppedGroup); - void dndPinBetweenPin(TreeItem* droppedPin, TreeItem* onDroppedParent, int row); - void dndPinBetweenGroup(TreeItem* droppedPin, int row); + void dndGroupOnGroup(BaseTreeItem* droppedGroup, BaseTreeItem* onDroppedGroup); + void dndGroupBetweenGroup(PortTreeItem* droppedGroup, int row); + void dndPinOnGroup(PortTreeItem* droppedPin, BaseTreeItem* onDroppedGroup); + void dndPinBetweenPin(PortTreeItem* droppedPin, BaseTreeItem* onDroppedParent, int row); + void dndPinBetweenGroup(PortTreeItem* droppedPin, int row); }; } diff --git a/plugins/gui/include/gui/selection_details_widget/net_details_widget/net_endpoint_table.h b/plugins/gui/include/gui/selection_details_widget/net_details_widget/net_endpoint_table.h index 85c3a9b3b12..8b980ab0adf 100644 --- a/plugins/gui/include/gui/selection_details_widget/net_details_widget/net_endpoint_table.h +++ b/plugins/gui/include/gui/selection_details_widget/net_details_widget/net_endpoint_table.h @@ -32,7 +32,7 @@ namespace hal { class EndpointTableModel; class Net; - class TreeItem; + class BaseTreeItem; class NetEndpointTable : public QTableView { diff --git a/plugins/gui/include/gui/selection_details_widget/net_details_widget/net_module_table.h b/plugins/gui/include/gui/selection_details_widget/net_details_widget/net_module_table.h index 5781289741f..408e0bf6319 100644 --- a/plugins/gui/include/gui/selection_details_widget/net_details_widget/net_module_table.h +++ b/plugins/gui/include/gui/selection_details_widget/net_details_widget/net_module_table.h @@ -33,7 +33,7 @@ namespace hal { class ModuleTableModel; class Net; - class TreeItem; + class BaseTreeItem; class NetModuleTable : public QTableView { diff --git a/plugins/gui/include/gui/selection_details_widget/selection_details_icon_provider.h b/plugins/gui/include/gui/selection_details_widget/selection_details_icon_provider.h index 2075ddb180a..a9d9cdf8cba 100644 --- a/plugins/gui/include/gui/selection_details_widget/selection_details_icon_provider.h +++ b/plugins/gui/include/gui/selection_details_widget/selection_details_icon_provider.h @@ -31,6 +31,7 @@ #include #include #include +#include namespace hal { @@ -47,10 +48,11 @@ namespace hal private Q_SLOTS: void loadIcons(int istyle); + void handleModuleColorChanged(u32 id); private: QHash mDefaultIcons; QHash mGateIcons; - QHash mModuleIcons; + QHash mModuleIcons; static bool sSettingsInitialized; static bool initSettings(); public: @@ -58,5 +60,4 @@ namespace hal static SelectionDetailsIconProvider* instance(); static SettingsItemDropdown* sIconSizeSetting; }; -} - +} \ No newline at end of file diff --git a/plugins/gui/include/gui/selection_details_widget/tree_navigation/selection_tree_view.h b/plugins/gui/include/gui/selection_details_widget/tree_navigation/selection_tree_view.h index c677f114f54..8dd7c85eae8 100644 --- a/plugins/gui/include/gui/selection_details_widget/tree_navigation/selection_tree_view.h +++ b/plugins/gui/include/gui/selection_details_widget/tree_navigation/selection_tree_view.h @@ -79,6 +79,12 @@ namespace hal * @param filter_text -The text to filter the model. */ void handleFilterTextChanged(const QString& filter_text); + + /** + * Might have to change icon color if module selected, thus updating view upon this event + * @param id - unused + */ + void handleModuleColorChanged(u32 id); protected: /** diff --git a/plugins/gui/resources/stylesheet/dark.qss b/plugins/gui/resources/stylesheet/dark.qss index 4cbe8ff2d47..da81e020db2 100755 --- a/plugins/gui/resources/stylesheet/dark.qss +++ b/plugins/gui/resources/stylesheet/dark.qss @@ -1195,6 +1195,18 @@ hal--Toolbar QPushButton:checked:hover { } hal--ModuleWidget { + qproperty-showNetsIconStyle: "all->#e8e8e8"; + qproperty-showNetsIconPath: ":/icons/ne_net"; + + qproperty-hideNetsIconStyle: "all->#e8e8e8"; + qproperty-hideNetsIconPath: ":/icons/ne_no_net"; + + qproperty-showGatesIconStyle: "all->#e8e8e8"; + qproperty-showGatesIconPath: ":/icons/ne_gate"; + + qproperty-hideGatesIconStyle: "all->#e8e8e8"; + qproperty-hideGatesIconPath: ":/icons/ne_no_gate"; + qproperty-searchActiveIconStyle: "all->#30ac4f"; qproperty-searchIconStyle: "all->#e8e8e8"; qproperty-searchIconPath: ":/icons/search"; diff --git a/plugins/gui/resources/stylesheet/light.qss b/plugins/gui/resources/stylesheet/light.qss index ce3511af89b..cf7dec2b945 100755 --- a/plugins/gui/resources/stylesheet/light.qss +++ b/plugins/gui/resources/stylesheet/light.qss @@ -1219,6 +1219,18 @@ hal--Toolbar QPushButton:checked:hover { } hal--ModuleWidget { + qproperty-showNetsIconStyle: "all->#FFFFFF"; + qproperty-showNetsIconPath: ":/icons/ne_net"; + + qproperty-hideNetsIconStyle: "all->#FFFFFF"; + qproperty-hideNetsIconPath: ":/icons/ne_no_net"; + + qproperty-showGatesIconStyle: "all->#FFFFFF"; + qproperty-showGatesIconPath: ":/icons/ne_gate"; + + qproperty-hideGatesIconStyle: "all->#FFFFFF"; + qproperty-hideGatesIconPath: ":/icons/ne_no_gate"; + qproperty-searchActiveIconStyle: "all->#30ac4f"; qproperty-searchIconStyle: "all->#FFFFFF"; qproperty-searchIconPath: ":/icons/search"; diff --git a/plugins/gui/src/basic_tree_model/base_tree_item.cpp b/plugins/gui/src/basic_tree_model/base_tree_item.cpp new file mode 100644 index 00000000000..d0209984816 --- /dev/null +++ b/plugins/gui/src/basic_tree_model/base_tree_item.cpp @@ -0,0 +1,139 @@ +#include "gui/basic_tree_model/base_tree_item.h" + + +namespace hal +{ + BaseTreeItem::BaseTreeItem() : mParent(nullptr) + { + + } + + + BaseTreeItem::~BaseTreeItem() + { + for(BaseTreeItem* item : mChildren) + delete item; + } + + + BaseTreeItem *BaseTreeItem::getParent() const + { + return mParent; + } + + void BaseTreeItem::setParent(BaseTreeItem *parent) + { + mParent = parent; + } + + BaseTreeItem *BaseTreeItem::getChild(int row) const + { + return (row < 0 || row >= mChildren.size()) ? nullptr : mChildren.at(row); + } + + QList BaseTreeItem::getChildren() const + { + return mChildren; + } + + void BaseTreeItem::appendChild(BaseTreeItem *child) + { + child->setParent(this); + mChildren.append(child); + } + + void BaseTreeItem::insertChild(int index, BaseTreeItem *child) + { + child->setParent(this); + mChildren.insert(index, child); + } + + BaseTreeItem* BaseTreeItem::removeChildAtPos(int row) + { + if(row < 0 || row >= mChildren.size()) + return nullptr; + else + { + BaseTreeItem* itemToRemove = mChildren.at(row); + mChildren.removeAt(row); + return itemToRemove; + } + } + + bool BaseTreeItem::removeChild(BaseTreeItem *child) + { + int index = mChildren.indexOf(child); + if(index == -1) + return false; + else + { + mChildren.removeAt(index); + return true; + } + } + + int BaseTreeItem::getChildCount() const + { + return mChildren.size(); + } + + int BaseTreeItem::getRowForChild(const BaseTreeItem *child) const + { + int index = -1; + for(int i = 0; i < mChildren.size(); i++) + { + if(mChildren.at(i) == child) + { + index = i; + break; + } + } + return index; + } + + int BaseTreeItem::getOwnRow() + { + if(!mParent) + return -1; + + return mParent->getRowForChild(this); + } + + void BaseTreeItem::setAdditionalData(QString key, QVariant data) + { + mAdditionalData.insert(key, data); + } + + QVariant BaseTreeItem::getAdditionalData(QString key) const + { + return mAdditionalData.value(key, QVariant()); + } + + QVariant RootTreeItem::getData(int column) const + { + if (column <= mHeaderLabels.size()) + return mHeaderLabels.at(column); + return QVariant(); + } + + void RootTreeItem::setData(QList data) + { + mHeaderLabels.clear(); + for (int i = 0; i < data.length(); i++) { + mHeaderLabels[i] = data[i].toString(); + } + } + + void RootTreeItem::setDataAtIndex(int index, QVariant &data) + { + while (index >= mHeaderLabels.size()) + mHeaderLabels << QString(); + mHeaderLabels[index] = data.toString(); + } + + void RootTreeItem::appendData(QVariant data) + { + + } + +} diff --git a/plugins/gui/src/basic_tree_model/base_tree_model.cpp b/plugins/gui/src/basic_tree_model/base_tree_model.cpp index a7610902892..764a46ace37 100644 --- a/plugins/gui/src/basic_tree_model/base_tree_model.cpp +++ b/plugins/gui/src/basic_tree_model/base_tree_model.cpp @@ -1,12 +1,12 @@ #include "gui/basic_tree_model/base_tree_model.h" -#include "gui/basic_tree_model/tree_item.h" +#include "gui/basic_tree_model/base_tree_item.h" namespace hal { BaseTreeModel::BaseTreeModel(QObject *parent) : QAbstractItemModel(parent) { - mRootItem = new TreeItem(); + mRootItem = new RootTreeItem(QStringList()); } QVariant BaseTreeModel::data(const QModelIndex &index, int role) const @@ -14,7 +14,7 @@ namespace hal if(!index.isValid()) return QVariant(); - TreeItem* item = getItemFromIndex(index); + BaseTreeItem* item = getItemFromIndex(index); if(!item) return QVariant(); @@ -27,7 +27,7 @@ namespace hal QVariant BaseTreeModel::headerData(int section, Qt::Orientation orientation, int role) const { - if(role == Qt::DisplayRole && orientation == Qt::Horizontal && section < mRootItem->getColumnCount()) + if(role == Qt::DisplayRole && orientation == Qt::Horizontal && section < mRootItem->getColumnCount() && section >= 0) return mRootItem->getData(section); else return QVariant(); @@ -38,8 +38,8 @@ namespace hal if(!hasIndex(row, column, parent)) return QModelIndex(); - TreeItem* parentItem = parent.isValid() ? getItemFromIndex(parent) : mRootItem; - TreeItem* childItem = parentItem->getChild(row); + BaseTreeItem* parentItem = parent.isValid() ? getItemFromIndex(parent) : mRootItem; + BaseTreeItem* childItem = parentItem->getChild(row); return (childItem) ? createIndex(row, column, childItem) : QModelIndex(); } @@ -48,11 +48,11 @@ namespace hal if(!index.isValid()) return QModelIndex(); - TreeItem* currentItem = getItemFromIndex(index); + BaseTreeItem* currentItem = getItemFromIndex(index); if(!currentItem) return QModelIndex(); - TreeItem* parentItem = currentItem->getParent(); + BaseTreeItem* parentItem = currentItem->getParent(); if(parentItem == mRootItem) return QModelIndex(); @@ -80,7 +80,7 @@ namespace hal return mRootItem->getColumnCount(); } - void BaseTreeModel::setContent(QList firstLevelItems) + void BaseTreeModel::setContent(QList firstLevelItems) { for(auto item : firstLevelItems) mRootItem->appendChild(item); @@ -92,25 +92,30 @@ namespace hal //delete all children, not the root item while(mRootItem->getChildCount() > 0) { - TreeItem* tmp = mRootItem->removeChildAtPos(0); + BaseTreeItem* tmp = mRootItem->removeChildAtPos(0); delete tmp; } endResetModel(); } - void BaseTreeModel::setHeaderLabels(QList labels) + void BaseTreeModel::setHeaderLabels(const QStringList& labels) { if(!mRootItem) - mRootItem = new TreeItem(); + mRootItem = new RootTreeItem(labels); + else + for (int i=0; isetDataAtIndex(i, qv); + } + - mRootItem->setData(labels); } - QModelIndex BaseTreeModel::getIndexFromItem(TreeItem *item) const + QModelIndex BaseTreeModel::getIndexFromItem(BaseTreeItem *item) const { assert(item); - TreeItem* parentItem = item->getParent(); + BaseTreeItem* parentItem = item->getParent(); // if the given item has no parent, it is the root item if(!parentItem) @@ -124,12 +129,12 @@ namespace hal return QModelIndex(); } - TreeItem *BaseTreeModel::getItemFromIndex(QModelIndex index) const + BaseTreeItem *BaseTreeModel::getItemFromIndex(QModelIndex index) const { - return (index.isValid()) ? static_cast(index.internalPointer()) : nullptr; + return (index.isValid()) ? static_cast(index.internalPointer()) : nullptr; } - TreeItem *BaseTreeModel::getRootItem() const + BaseTreeItem *BaseTreeModel::getRootItem() const { return mRootItem; } diff --git a/plugins/gui/src/basic_tree_model/tree_item.cpp b/plugins/gui/src/basic_tree_model/tree_item.cpp deleted file mode 100644 index e875a3a64b2..00000000000 --- a/plugins/gui/src/basic_tree_model/tree_item.cpp +++ /dev/null @@ -1,147 +0,0 @@ -#include "gui/basic_tree_model/tree_item.h" - - -namespace hal -{ - TreeItem::TreeItem() : mParent(nullptr) - { - - } - - TreeItem::TreeItem(QList columnData) : mParent(nullptr), mData(columnData) - { - - } - - TreeItem::TreeItem(const TreeItem &item) - { - mData = item.mData; - mAdditionalData = item.mAdditionalData; - } - - TreeItem::~TreeItem() - { - for(TreeItem* item : mChildren) - delete item; - } - - QVariant TreeItem::getData(int column) - { - return (column < 0 || column >= mData.size()) ? QVariant() : mData.at(column); - } - - void TreeItem::setData(QList data) - { - mData = data; - } - - void TreeItem::setDataAtIndex(int index, QVariant data) - { - if(!(index < 0 || index >= mData.size()) && !mData.empty()) - mData.replace(index, data); - } - - void TreeItem::appendData(QVariant data) - { - mData.append(data); - } - - TreeItem *TreeItem::getParent() - { - return mParent; - } - - void TreeItem::setParent(TreeItem *parent) - { - mParent = parent; - } - - TreeItem *TreeItem::getChild(int row) - { - return (row < 0 || row >= mChildren.size()) ? nullptr : mChildren.at(row); - } - - QList TreeItem::getChildren() - { - return mChildren; - } - - void TreeItem::appendChild(TreeItem *child) - { - child->setParent(this); - mChildren.append(child); - } - - void TreeItem::insertChild(int index, TreeItem *child) - { - child->setParent(this); - mChildren.insert(index, child); - } - - TreeItem* TreeItem::removeChildAtPos(int row) - { - if(row < 0 || row >= mChildren.size()) - return nullptr; - else - { - TreeItem* itemToRemove = mChildren.at(row); - mChildren.removeAt(row); - return itemToRemove; - } - } - - bool TreeItem::removeChild(TreeItem *child) - { - int index = mChildren.indexOf(child); - if(index == -1) - return false; - else - { - mChildren.removeAt(index); - return true; - } - } - - int TreeItem::getChildCount() - { - return mChildren.size(); - } - - int TreeItem::getColumnCount() - { - return mData.size(); - } - - int TreeItem::getRowForChild(TreeItem *child) - { - int index = -1; - for(int i = 0; i < mChildren.size(); i++) - { - if(mChildren.at(i) == child) - { - index = i; - break; - } - } - return index; - } - - int TreeItem::getOwnRow() - { - if(!mParent) - return -1; - - return mParent->getRowForChild(this); - } - - void TreeItem::setAdditionalData(QString key, QVariant data) - { - mAdditionalData.insert(key, data); - } - - QVariant TreeItem::getAdditionalData(QString key) - { - return mAdditionalData.value(key, QVariant()); - } - -} diff --git a/plugins/gui/src/graph_widget/layouters/graph_layouter.cpp b/plugins/gui/src/graph_widget/layouters/graph_layouter.cpp index e1918230993..dae127f6260 100644 --- a/plugins/gui/src/graph_widget/layouters/graph_layouter.cpp +++ b/plugins/gui/src/graph_widget/layouters/graph_layouter.cpp @@ -945,8 +945,10 @@ namespace hal graphicsNet = san; int yGridPos = mGlobalInputHash.value(dnt->id(), -1); Q_ASSERT(yGridPos >= 0); - const EndpointCoordinate& epc = mEndpointHash.value(QPoint(mNodeBoundingBox.left(), yGridPos * 2)); - san->setInputPosition(QPointF(mCoordArrayX->lanePosition(mNodeBoundingBox.left(),0), epc.lanePosition(0, true))); + QPoint pnt(mNodeBoundingBox.left(), yGridPos * 2); + const EndpointCoordinate& epc = mEndpointHash.value(pnt); + const NetLayoutJunction* nlj = mJunctionHash.value(pnt); + san->setInputPosition(QPointF(mCoordArrayX->lanePosition(mNodeBoundingBox.left(),nlj?nlj->rect().left():0), epc.lanePosition(0, true))); } if (epl.hasOutputArrow()) { diff --git a/plugins/gui/src/grouping/grouping_color_serializer.cpp b/plugins/gui/src/grouping/grouping_color_serializer.cpp index 1832465b641..cc54efd319f 100644 --- a/plugins/gui/src/grouping/grouping_color_serializer.cpp +++ b/plugins/gui/src/grouping/grouping_color_serializer.cpp @@ -6,6 +6,7 @@ #include "gui/grouping/grouping_table_model.h" #include "gui/module_model/module_model.h" #include "gui/module_model/module_item.h" +#include "gui/module_model/module_color_manager.h" #include #include @@ -104,92 +105,4 @@ namespace hal { gtm->setData(gtm->index(irow,2), color, Qt::EditRole); } } - - //--------------------------------------- - ModuleColorSerializer::ModuleColorSerializer() - : ProjectSerializer("modulecolor") - {;} - - void ModuleColorSerializer::restore(ModuleModel* mm) - { - ProjectManager* pm = ProjectManager::instance(); - std::string relname = pm->get_filename(m_name); - if (!relname.empty()) - restoreModuleColor(pm->get_project_directory(), relname, mm); - } - - void ModuleColorSerializer::serializeColorRecursion(QJsonArray& mcArr, const ModuleModel* mm, QModelIndex parent) - { - int nrows = mm->rowCount(parent); - for (int irow=0; irowindex(irow,0,parent); - const ModuleItem* mItem = mm->getItem(inx); - if (!mItem) continue; - QJsonObject mcEntry; - mcEntry["id"] = (int) mItem->id(); - mcEntry["color"] = mItem->color().name(QColor::HexArgb); - mcArr.append(mcEntry); - serializeColorRecursion(mcArr,mm,inx); - } - } - - std::string ModuleColorSerializer::serialize(Netlist* netlist, const std::filesystem::path& savedir, bool isAutosave) - { - Q_UNUSED(netlist); - Q_UNUSED(isAutosave); - QString mcFilename("modulecolor.json"); - QFile mcFile(QDir(QString::fromStdString(savedir.string())).absoluteFilePath(mcFilename)); - if (!mcFile.open(QIODevice::WriteOnly)) return std::string(); - - QJsonObject mcObj; - QJsonArray mcArr; - - const ModuleModel* mm = gNetlistRelay->getModuleModel(); - if (!mm) return std::string(); - - serializeColorRecursion(mcArr,mm); - - mcObj["modcolors"] = mcArr; - - mcFile.write(QJsonDocument(mcObj).toJson(QJsonDocument::Compact)); - - return mcFilename.toStdString(); - } - - - void ModuleColorSerializer::deserialize(Netlist* netlist, const std::filesystem::path& loaddir) - { - Q_UNUSED(netlist); - std::string relname = ProjectManager::instance()->get_filename(m_name); - if (!relname.empty()) - restoreModuleColor(loaddir, relname); - } - - void ModuleColorSerializer::restoreModuleColor(const std::filesystem::path& loaddir, const std::string& jsonfile, ModuleModel* mm) - { - if (!mm) - { - mm = gNetlistRelay->getModuleModel(); - if (!mm) return; - } - - QFile mcFile(QDir(QString::fromStdString(loaddir.string())).absoluteFilePath(QString::fromStdString(jsonfile))); - if (!mcFile.open(QIODevice::ReadOnly)) - return; - QJsonDocument jsonDoc = QJsonDocument::fromJson(mcFile.readAll()); - const QJsonObject& json = jsonDoc.object(); - - if (json.contains("modcolors") && json["modcolors"].isArray()) - { - QJsonArray mcArr = json["modcolors"].toArray(); - int nmc = mcArr.size(); - for (int imc = 0; imc < nmc; imc++) - { - QJsonObject mcEntry = mcArr.at(imc).toObject(); - u32 moduleId = mcEntry["id"].toInt(); - mm->setModuleColor(moduleId,QColor(mcEntry["color"].toString())); - } - } - } } diff --git a/plugins/gui/src/gui_utils/graphics.cpp b/plugins/gui/src/gui_utils/graphics.cpp index 8ae8e9bf831..0e3ed8bac04 100644 --- a/plugins/gui/src/gui_utils/graphics.cpp +++ b/plugins/gui/src/gui_utils/graphics.cpp @@ -80,19 +80,5 @@ namespace hal return getIconFromSvgData(svg_data); } - - QColor getRandomColor() - { - static qreal h = 0.5; - - h += 0.6180339887498948; - - if (h > 1) - --h; - - QColor c; - c.setHsvF(h, 0.8, 0.95); // (MAYBE) GET S AND V FROM STYLESHEET OR CYCLE 3 DIMENSIONAL - return c; - } } // namespace gui_utility } diff --git a/plugins/gui/src/module_model/module_color_manager.cpp b/plugins/gui/src/module_model/module_color_manager.cpp new file mode 100644 index 00000000000..12a84020847 --- /dev/null +++ b/plugins/gui/src/module_model/module_color_manager.cpp @@ -0,0 +1,155 @@ +#include "gui/module_model/module_color_manager.h" + +#include "hal_core/netlist/project_manager.h" +#include "gui/gui_globals.h" +#include "gui/gui_utils/graphics.h" + +#include +#include +#include +#include +#include + +namespace hal +{ + + ModuleColorManager::ModuleColorManager(QObject *parent) + : QObject(parent) + { + setModuleColor(1, QColor(96, 110, 112)); + } + + void ModuleColorManager::clear() + { + mModuleColors.clear(); + } + + QColor ModuleColorManager::moduleColor(u32 id) const + { + return mModuleColors.value(id); + } + + QColor ModuleColorManager::setModuleColor(u32 id, const QColor& col) + { + QColor retval = mModuleColors.value(id); + mModuleColors[id] = col; + Q_EMIT moduleColorChanged(id); + return retval; + } + + QColor ModuleColorManager::getRandomColor() + { + static qreal h = 0.5; + + h += 0.6180339887498948; + + if (h > 1) + --h; + + QColor c; + c.setHsvF(h, 0.8, 0.95); // (MAYBE) GET S AND V FROM STYLESHEET OR CYCLE 3 DIMENSIONAL + return c; + } + + QColor ModuleColorManager::setRandomColor(u32 id) + { + QColor retval = mModuleColors.value(id); + mModuleColors.insert(id,getRandomColor()); + return retval; + } + + QMap ModuleColorManager::getColorMap() const + { + return mModuleColors; + } + + void ModuleColorManager::removeColor(u32 id) + { + mModuleColors.remove(id); + } + + //--------------------------------------- + ModuleColorSerializer::ModuleColorSerializer() + : ProjectSerializer("modulecolor") + {;} + + void ModuleColorSerializer::restore(ModuleColorManager *mcm) + { + ProjectManager* pm = ProjectManager::instance(); + std::string relname = pm->get_filename(m_name); + if (!relname.empty()) + restoreModuleColor(pm->get_project_directory(), relname, mcm); + } + + void ModuleColorSerializer::serializeColorMap(QJsonArray& mcArr, const ModuleColorManager *mcm) + { + QMap cmap = mcm->getColorMap(); + + for (auto it = cmap.constBegin(); it != cmap.constEnd(); ++it) + { + QJsonObject mcEntry; + mcEntry["id"] = (int) it.key(); + mcEntry["color"] = it.value().name(QColor::HexArgb); + mcArr.append(mcEntry); + } + } + + std::string ModuleColorSerializer::serialize(Netlist* netlist, const std::filesystem::path& savedir, bool isAutosave) + { + Q_UNUSED(netlist); + Q_UNUSED(isAutosave); + QString mcFilename("modulecolor.json"); + QFile mcFile(QDir(QString::fromStdString(savedir.string())).absoluteFilePath(mcFilename)); + if (!mcFile.open(QIODevice::WriteOnly)) return std::string(); + + QJsonObject mcObj; + QJsonArray mcArr; + + const ModuleColorManager* mcm = gNetlistRelay->getModuleColorManager(); + if (!mcm) return std::string(); + + serializeColorMap(mcArr,mcm); + + mcObj["modcolors"] = mcArr; + + mcFile.write(QJsonDocument(mcObj).toJson(QJsonDocument::Compact)); + + return mcFilename.toStdString(); + } + + + void ModuleColorSerializer::deserialize(Netlist* netlist, const std::filesystem::path& loaddir) + { + Q_UNUSED(netlist); + std::string relname = ProjectManager::instance()->get_filename(m_name); + if (!relname.empty()) + restoreModuleColor(loaddir, relname); + } + + void ModuleColorSerializer::restoreModuleColor(const std::filesystem::path& loaddir, const std::string& jsonfile, ModuleColorManager *mcm) + { + if (!mcm) + { + mcm = gNetlistRelay->getModuleColorManager(); + if (!mcm) return; + } + + QFile mcFile(QDir(QString::fromStdString(loaddir.string())).absoluteFilePath(QString::fromStdString(jsonfile))); + if (!mcFile.open(QIODevice::ReadOnly)) + return; + QJsonDocument jsonDoc = QJsonDocument::fromJson(mcFile.readAll()); + const QJsonObject& json = jsonDoc.object(); + + if (json.contains("modcolors") && json["modcolors"].isArray()) + { + QJsonArray mcArr = json["modcolors"].toArray(); + int nmc = mcArr.size(); + for (int imc = 0; imc < nmc; imc++) + { + QJsonObject mcEntry = mcArr.at(imc).toObject(); + u32 moduleId = mcEntry["id"].toInt(); + gNetlistRelay->getModuleColorManager()->setModuleColor(moduleId,QColor(mcEntry["color"].toString())); + } + } + } +} diff --git a/plugins/gui/src/module_model/module_item.cpp b/plugins/gui/src/module_model/module_item.cpp index 3293d0ae39a..cf5a79bcc56 100644 --- a/plugins/gui/src/module_model/module_item.cpp +++ b/plugins/gui/src/module_model/module_item.cpp @@ -7,31 +7,40 @@ namespace hal { - ModuleItem::ModuleItem(const u32 id) : - mParent(nullptr), + +ModuleItem::ModuleItem(const u32 id, const TreeItemType type) : + BaseTreeItem(), mId(id), - mName(QString::fromStdString(gNetlist->get_module_by_id(id)->get_name())), - mColor(gNetlistRelay->getModuleColor(id)), + mType(type), mHighlighted(false) - {;} - - void ModuleItem::insertChild(int row, ModuleItem* child) { - mChildItems.insert(row, child); + switch(type) + { + case TreeItemType::Module: + mName = QString::fromStdString(gNetlist->get_module_by_id(id)->get_name()); + break; + case TreeItemType::Gate: + mName = QString::fromStdString(gNetlist->get_gate_by_id(id)->get_name()); + break; + case TreeItemType::Net: + mName = QString::fromStdString(gNetlist->get_net_by_id(id)->get_name()); + break; + } } - void ModuleItem::removeChild(ModuleItem* child) + int ModuleItem::row() const { - mChildItems.removeOne(child); + BaseTreeItem* parent = getParent(); + if (!parent) return 0; + return parent->getRowForChild(this); } - void ModuleItem::appendChild(ModuleItem* child) - { - mChildItems.append(child); - } void ModuleItem::appendExistingChildIfAny(const QMap& moduleMap) { + if(mType != TreeItemType::Module) // only module can have children + return; + Module* m = gNetlist->get_module_by_id(mId); Q_ASSERT(m); for (Module* subm : m->get_submodules()) @@ -46,51 +55,74 @@ namespace hal } } - void ModuleItem::prependChild(ModuleItem* child) - { - // PROBABLY OBSOLETE - mChildItems.prepend(child); - } - - ModuleItem* ModuleItem::parent() + QVariant ModuleItem::getData(int column) const { - return mParent; - } - - ModuleItem* ModuleItem::child(int row) - { - return mChildItems.value(row); - } - - const ModuleItem* ModuleItem::constParent() const - { - return mParent; - } - - const ModuleItem* ModuleItem::constChild(int row) const - { - return mChildItems.value(row); - } - - int ModuleItem::childCount() const - { - return mChildItems.count(); + // DEBUG CODE, USE STYLED DELEGATES OR SOMETHING + if(column == 0) + return mName; + else if (column == 1) + return mId; + else if(column == 2) + { + switch(mType) + { + case TreeItemType::Module: + { + Module* module = gNetlist->get_module_by_id(mId); + if(!module) + return QVariant(); + return QString::fromStdString(module->get_type()); + } + case TreeItemType::Gate: + Gate* gate = gNetlist->get_gate_by_id(mId); + if(!gate) + return QVariant(); + return QString::fromStdString(gate->get_type()->get_name()); + } + } + return QVariant(); } - int ModuleItem::row() const + void ModuleItem::setData(QList data) { - if (mParent) - return mParent->mChildItems.indexOf(const_cast(this)); - else - return 0; + setName(data[0].toString()); + switch(mType) + { + case TreeItemType::Module: + { + Module* module = gNetlist->get_module_by_id(mId); + if(!module) + return; + module->set_type(data[3].toString().toStdString()); + } + case TreeItemType::Gate: + return; + } } - QVariant ModuleItem::data(int column) const + void ModuleItem::setDataAtIndex(int index, QVariant &data) { - // DEBUG CODE, USE STYLED DELEGATES OR SOMETHING - if (column != 0) - return QVariant(); - return mName; + if(index == 0) { + setName(data.toString()); + return; + } + else if (index == 1) + return; + else if(index == 2) + { + switch(mType) + { + case TreeItemType::Module: + { + Module* module = gNetlist->get_module_by_id(mId); + if(!module) + return; + module->set_type(data.toString().toStdString()); + } + case TreeItemType::Gate: + return; + } + } } QString ModuleItem::name() const @@ -103,33 +135,29 @@ namespace hal return mId; } - QColor ModuleItem::color() const - { - return mColor; - } - bool ModuleItem::highlighted() const { return mHighlighted; } - void ModuleItem::setParent(ModuleItem* parent) - { - mParent = parent; + ModuleItem::TreeItemType ModuleItem::getType() const{ + return mType; } - void ModuleItem::set_name(const QString& name) + void ModuleItem::setName(const QString& name) { mName = name; } - void ModuleItem::setColor(const QColor& color) + void ModuleItem::setHighlighted(const bool highlighted) { - mColor = color; + mHighlighted = highlighted; } - void ModuleItem::setHighlighted(const bool highlighted) + int ModuleItem::getColumnCount() const { - mHighlighted = highlighted; + return 3; } + + void ModuleItem::appendData(QVariant data) {} } diff --git a/plugins/gui/src/module_model/module_model.cpp b/plugins/gui/src/module_model/module_model.cpp index d1e02d99baf..7c645b97364 100644 --- a/plugins/gui/src/module_model/module_model.cpp +++ b/plugins/gui/src/module_model/module_model.cpp @@ -1,104 +1,18 @@ #include "gui/module_model/module_model.h" -#include "gui/module_model/module_item.h" - #include "gui/gui_globals.h" -#include "gui/gui_utils/graphics.h" -//#include "gui/ModuleModel/ModuleItem.h" + +#include "gui/selection_details_widget/selection_details_icon_provider.h" #include "hal_core/netlist/gate.h" #include "hal_core/netlist/net.h" - namespace hal { - ModuleModel::ModuleModel(QObject* parent) : QAbstractItemModel(parent), mTopModuleItem(nullptr) - { - } - - QModelIndex ModuleModel::index(int row, int column, const QModelIndex& parent) const + ModuleModel::ModuleModel(QObject* parent) : BaseTreeModel(parent) { - // BEHAVIOR FOR ILLEGAL INDICES IS UNDEFINED - // SEE QT DOCUMENTATION - - if (!parent.isValid()) - { - if (row == 0 && column == 0 && mTopModuleItem) - return createIndex(0, 0, mTopModuleItem); - else - return QModelIndex(); - } - - if (column != 0 || parent.column() != 0) - return QModelIndex(); - - ModuleItem* parent_item = getItem(parent); - - ModuleItem* child_item = static_cast(parent_item)->child(row); - assert(child_item); - - return createIndex(row, column, child_item); - - // NECESSARY ??? - // if (column != 0) - // return QModelIndex(); - - // // PROBABLY REDUNDANT - // if (parent.isValid() && parent.column() != 0) - // return QModelIndex(); - - // ModuleItem* parent_item = getItem(parent); - // ModuleItem* child_item = parent_item->child(row); - - // if (child_item) - // return createIndex(row, column, child_item); - // else - // return QModelIndex(); - } - - QModelIndex ModuleModel::parent(const QModelIndex& index) const - { - if (!index.isValid()) - return QModelIndex(); - - ModuleItem* item = getItem(index); - - if (item == mTopModuleItem) - return QModelIndex(); - - ModuleItem* parent_item = item->parent(); - return createIndex(parent_item->row(), 0, parent_item); - - // if (!index.isValid()) - // return QModelIndex(); - - // ModuleItem* child_item = getItem(index); - // ModuleItem* parent_item = child_item->parent(); - - // if (parent_item == m_root_item) - // return QModelIndex(); - - // return createIndex(parent_item->row(), 0, parent_item); - } - - int ModuleModel::rowCount(const QModelIndex& parent) const - { - if (!parent.isValid()) // ?? - return 1; - - if (parent.column() != 0) - return 0; - - ModuleItem* parent_item = getItem(parent); - - return parent_item->childCount(); - } - - int ModuleModel::columnCount(const QModelIndex& parent) const - { - Q_UNUSED(parent) - - return 1; + // use root item to store header information + setHeaderLabels(QStringList() << "Name" << "ID" << "Type"); } QVariant ModuleModel::data(const QModelIndex& index, int role) const @@ -117,16 +31,20 @@ namespace hal { if (index.column() == 0) { - QString runIconStyle = "all->" + item->color().name(); - QString runIconPath = ":/icons/filled-circle"; - - return gui_utility::getStyledSvgIcon(runIconStyle, runIconPath); + switch(item->getType()){ + case ModuleItem::TreeItemType::Module: + return QIcon(*SelectionDetailsIconProvider::instance()->getIcon(SelectionDetailsIconProvider::ModuleIcon, item->id())); + case ModuleItem::TreeItemType::Gate: + return QIcon(*SelectionDetailsIconProvider::instance()->getIcon(SelectionDetailsIconProvider::GateIcon, item->id())); + case ModuleItem::TreeItemType::Net: + return QIcon(*SelectionDetailsIconProvider::instance()->getIcon(SelectionDetailsIconProvider::NetIcon, item->id())); + } } break; } case Qt::DisplayRole: { - return item->data(index.column()); + return item->getData(index.column()); } case Qt::ForegroundRole: { @@ -149,15 +67,6 @@ namespace hal return QAbstractItemModel::flags(index); } - QVariant ModuleModel::headerData(int section, Qt::Orientation orientation, int role) const - { - Q_UNUSED(section) - Q_UNUSED(orientation) - Q_UNUSED(role) - - return QVariant(); - } - ModuleItem* ModuleModel::getItem(const QModelIndex& index) const { if (index.isValid()) @@ -173,10 +82,10 @@ namespace hal QVector row_numbers; const ModuleItem* current_item = item; - while (current_item != mTopModuleItem) + while (current_item != mRootItem->getChild(0)) { row_numbers.append(current_item->row()); - current_item = current_item->constParent(); + current_item = static_cast(current_item->getParent()); } QModelIndex model_index = index(0, 0, QModelIndex()); @@ -189,42 +98,31 @@ namespace hal void ModuleModel::init() { - setModuleColor(1, QColor(96, 110, 112)); ModuleItem* item = new ModuleItem(1); - - mModuleItems.insert(1, item); + mModuleMap.insert(1, item); beginInsertRows(index(0, 0, QModelIndex()), 0, 0); - mTopModuleItem = item; + mRootItem->appendChild(item); endInsertRows(); - // This is broken because it can attempt to insert a child before its parent - // which will cause an assertion failure and then crash - - // std::set s = gNetlist->get_modules(); - // s.erase(gNetlist->get_top_module()); - // for (Module* m : s) - // addModule(m->get_id(), m->get_parent_module()->get_id()); - - // This works - - // recursively insert modules Module* m = gNetlist->get_top_module(); - addRecursively(m->get_submodules()); + addRecursively(m); + for(auto net : gNetlist->get_top_module()->get_internal_nets()) + { + addNet(net->get_id(), m->get_id()); + updateNet(net); + } } void ModuleModel::clear() { beginResetModel(); - mTopModuleItem = nullptr; - - for (ModuleItem* m : mModuleItems) - delete m; - - mModuleItems.clear(); - mModuleColors.clear(); - + BaseTreeModel::clear(); + mModuleMap.clear(); + mGateMap.clear(); + mNetMap.clear(); + //TODO : clear colors endResetModel(); } @@ -232,43 +130,90 @@ namespace hal { assert(gNetlist->get_module_by_id(id)); assert(gNetlist->get_module_by_id(parent_module)); - assert(!mModuleItems.contains(id)); - assert(mModuleItems.contains(parent_module)); + assert(!mModuleMap.contains(id)); + assert(mModuleMap.contains(parent_module)); ModuleItem* item = new ModuleItem(id); - item->appendExistingChildIfAny(mModuleItems); - ModuleItem* parent = mModuleItems.value(parent_module); + ModuleItem* parent = mModuleMap.value(parent_module); item->setParent(parent); - mModuleItems.insert(id, item); + mModuleMap.insert(id, item); QModelIndex index = getIndex(parent); - int row = parent->childCount(); + int row = parent->getChildCount(); mIsModifying = true; beginInsertRows(index, row, row); - parent->insertChild(row, item); + parent->appendChild(item); mIsModifying = false; endInsertRows(); } - void ModuleModel::addRecursively(const std::vector& modules) + void ModuleModel::addGate(u32 id, u32 parent_module) { - for (auto &m : modules) - { - addModule(m->get_id(), m->get_parent_module()->get_id()); - addRecursively(m->get_submodules()); - } + assert(gNetlist->get_gate_by_id(id)); + assert(gNetlist->get_module_by_id(parent_module)); + assert(!mGateMap.contains(id)); + assert(mModuleMap.contains(parent_module)); + + ModuleItem* item = new ModuleItem(id, ModuleItem::TreeItemType::Gate); + ModuleItem* parent = mModuleMap.value(parent_module); + + item->setParent(parent); + mGateMap.insert(id, item); + + QModelIndex index = getIndex(parent); + + int row = parent->getChildCount(); + mIsModifying = true; + beginInsertRows(index, row, row); + parent->appendChild(item); + mIsModifying = false; + endInsertRows(); } - void ModuleModel::remove_module(const u32 id) + void ModuleModel::addNet(u32 id, u32 parent_module) + { + assert(gNetlist->get_net_by_id(id)); + assert(gNetlist->get_module_by_id(parent_module)); + assert(!mNetMap.contains(id)); + assert(mModuleMap.contains(parent_module)); + + ModuleItem* item = new ModuleItem(id, ModuleItem::TreeItemType::Net); + ModuleItem* parent = mModuleMap.value(parent_module); + + item->setParent(parent); + mNetMap.insert(id, item); + + QModelIndex index = getIndex(parent); + + int row = parent->getChildCount(); + mIsModifying = true; + beginInsertRows(index, row, row); + parent->appendChild(item); + mIsModifying = false; + endInsertRows(); + } + + void ModuleModel::addRecursively(const Module* module) + { + if(!module->is_top_module()) + addModule(module->get_id(), module->get_parent_module()->get_id()); + for(auto &m : module->get_submodules()) + addRecursively(m); + + for(auto &g : module->get_gates()) + addGate(g->get_id(), module->get_id()); + } + + void ModuleModel::removeModule(const u32 id) { assert(id != 1); -// module was most likely already purged from netlist - assert(mModuleItems.contains(id)); + // module was most likely already purged from netlist + assert(mModuleMap.contains(id)); - ModuleItem* item = mModuleItems.value(id); - ModuleItem* parent = item->parent(); + ModuleItem* item = mModuleMap.value(id); + ModuleItem* parent = static_cast(item->getParent()); assert(item); assert(parent); @@ -282,56 +227,229 @@ namespace hal mIsModifying = false; endRemoveRows(); - mModuleItems.remove(id); + mModuleMap.remove(id); delete item; } - void ModuleModel::updateModule(u32 id) // SPLIT ??? + void ModuleModel::removeGate(const u32 id) { - assert(gNetlist->get_module_by_id(id)); - assert(mModuleItems.contains(id)); + //assert(gNetlist->get_gate_by_id(id)); + assert(mGateMap.contains(id)); - ModuleItem* item = mModuleItems.value(id); + ModuleItem* item = mGateMap.value(id); + ModuleItem* parent = static_cast(item->getParent()); assert(item); + assert(parent); - item->set_name(QString::fromStdString(gNetlist->get_module_by_id(id)->get_name())); // REMOVE & ADD AGAIN - item->setColor(gNetlistRelay->getModuleColor(id)); + QModelIndex index = getIndex(parent); - QModelIndex index = getIndex(item); - Q_EMIT dataChanged(index, index); + int row = item->row(); + + mIsModifying = true; + beginRemoveRows(index, row, row); + parent->removeChild(item); + mIsModifying = false; + endRemoveRows(); + + mGateMap.remove(id); + delete item; } - ModuleItem* ModuleModel::getItem(u32 module_id) const + void ModuleModel::removeNet(const u32 id) { - return mModuleItems.value(module_id); + //assert(gNetlist->get_net_by_id(id)); + if(!mNetMap.contains(id)) // global nets are not contained in the item model + return; + + ModuleItem* item = mNetMap.value(id); + ModuleItem* parent = static_cast(item->getParent()); + assert(item); + assert(parent); + + QModelIndex index = getIndex(parent); + + int row = item->row(); + + mIsModifying = true; + beginRemoveRows(index, row, row); + parent->removeChild(item); + mIsModifying = false; + endRemoveRows(); + + mNetMap.remove(id); + delete item; } - QColor ModuleModel::moduleColor(u32 id) const + void ModuleModel::handleModuleParentChanged(const Module* module) { - return mModuleColors.value(id); + assert(module); + updateModuleParent(module); + + for(Net* net : module->get_nets()) + updateNet(net); } - QColor ModuleModel::setModuleColor(u32 id, const QColor& col) + void ModuleModel::handleModuleGateAssinged(const u32 id, const u32 parent_module) { - QColor retval = mModuleColors.value(id); - mModuleColors[id] = col; - return retval; + // Don't need new function handleModuleGateRemoved(), because the GateAssinged event always follows GateRemoved + // or NetlistInternalManager updates Net connections when a gate is deleted. + + if(!mGateMap.contains(id)) + addGate(id, parent_module); + + Gate* gate = gNetlist->get_gate_by_id(id); + for(Net* in_net : gate->get_fan_in_nets()) + updateNet(in_net); + for(Net* in_net : gate->get_fan_out_nets()) + updateNet(in_net); } - QColor ModuleModel::setRandomColor(u32 id) + void ModuleModel::updateNet(const Net* net) { - QColor retval = mModuleColors.value(id); - mModuleColors.insert(id,gui_utility::getRandomColor()); - return retval; + assert(net); + u32 id = net->get_id(); + + if(!mNetMap.contains(id)) + return; + + ModuleItem* item = mNetMap.value(id); + ModuleItem* oldParentItem = static_cast(item->getParent()); + assert(oldParentItem); + + Module* newParentModule = findNetParent(net); + if(newParentModule == nullptr) + newParentModule = gNetlist->get_top_module(); + if(newParentModule->get_id() == oldParentItem->id()) + return; + + assert(mModuleMap.contains(newParentModule->get_id())); + ModuleItem* newParentItem = mModuleMap[newParentModule->get_id()]; + QModelIndex newIndex = getIndex(newParentItem); + QModelIndex oldIndex = getIndex(oldParentItem); + int row = item->row(); + + mIsModifying = true; + beginMoveRows(oldIndex, row, row, newIndex, newParentItem->getChildCount()); + oldParentItem->removeChild(item); + newParentItem->appendChild(item); + mIsModifying = false; + endMoveRows(); + } + + void ModuleModel::updateModuleParent(const Module* module){ + assert(module); + u32 id = module->get_id(); + assert(id != 1); + assert(mModuleMap.contains(id)); + ModuleItem* item = mModuleMap.value(id); + ModuleItem* oldParent = static_cast(item->getParent()); + assert(oldParent); + + assert(module->get_parent_module()); + if(oldParent->id() == module->get_parent_module()->get_id()) + return; + + assert(mModuleMap.contains(module->get_parent_module()->get_id())); + ModuleItem* newParent = mModuleMap.value(module->get_parent_module()->get_id()); + + QModelIndex oldIndex = getIndex(oldParent); + QModelIndex newIndex = getIndex(newParent); + int row = item->row(); + + mIsModifying = true; + beginMoveRows(oldIndex, row, row, newIndex, newParent->getChildCount()); + oldParent->removeChild(item); + newParent->appendChild(item); + mIsModifying = false; + endMoveRows(); } - void ModuleModel::removeColor(u32 id) + void ModuleModel::updateModuleName(u32 id) { - mModuleColors.remove(id); + assert(gNetlist->get_module_by_id(id)); + assert(mModuleMap.contains(id)); + + ModuleItem* item = mModuleMap.value(id); + assert(item); + + item->setName(QString::fromStdString(gNetlist->get_module_by_id(id)->get_name())); // REMOVE & ADD AGAIN + + QModelIndex index = getIndex(item); + Q_EMIT dataChanged(index, index); + } + + void ModuleModel::updateGateName(u32 id) + { + assert(gNetlist->get_gate_by_id(id)); + assert(mGateMap.contains(id)); + + ModuleItem* item = mGateMap.value(id); + assert(item); + + item->setName(QString::fromStdString(gNetlist->get_gate_by_id(id)->get_name())); // REMOVE & ADD AGAIN + + QModelIndex index = getIndex(item); + Q_EMIT dataChanged(index, index); + } + + void ModuleModel::updateNetName(u32 id) + { + assert(gNetlist->get_net_by_id(id)); + assert(mNetMap.contains(id)); + + ModuleItem* item = mNetMap.value(id); + assert(item); + + item->setName(QString::fromStdString(gNetlist->get_net_by_id(id)->get_name())); // REMOVE & ADD AGAIN + + QModelIndex index = getIndex(item); + Q_EMIT dataChanged(index, index); + } + + ModuleItem* ModuleModel::getItem(u32 id, ModuleItem::TreeItemType type) const + { + return mModuleItemMaps[(int)type]->value(id); } bool ModuleModel::isModifying() { return mIsModifying; } + + Module* ModuleModel::findNetParent(const Net* net){ + // cannot use Module::get_internal_nets(), because currently that function is implemented so, + // that a net can be "internal" to multiple modules at the same depth. + // => instead manually search for deepest module, that contains all sources and destinations of net. + assert(net); + if(net->get_num_of_sources() == 0 && net->get_num_of_destinations() == 0) + return nullptr; + + std::vector endpoints = net->get_sources(); + + { + std::vector destinations = net->get_destinations(); + endpoints.insert(endpoints.end(), destinations.begin(), destinations.end()); + } + + Module* parent = endpoints[0]->get_gate()->get_module(); + endpoints.erase(endpoints.begin()); + + // might want to split up endpoints, if sources and destinations should be handled differently + while(endpoints.size() > 0) + { + std::vector::iterator it = endpoints.begin(); + while(it != endpoints.end()) + { + if(parent->contains_gate((*it)->get_gate(), true)) + it = endpoints.erase(it); + else + ++it; + } + + if(endpoints.size() > 0) + parent = parent->get_parent_module(); + } + + return parent; + } } diff --git a/plugins/gui/src/module_model/module_proxy_model.cpp b/plugins/gui/src/module_model/module_proxy_model.cpp index 482fbc96ac2..ec5ca9e7123 100644 --- a/plugins/gui/src/module_model/module_proxy_model.cpp +++ b/plugins/gui/src/module_model/module_proxy_model.cpp @@ -5,7 +5,7 @@ namespace hal { - ModuleProxyModel::ModuleProxyModel(QObject* parent) : QSortFilterProxyModel(parent), mSortMechanism(gui_utility::mSortMechanism::lexical) + ModuleProxyModel::ModuleProxyModel(QObject* parent) : QSortFilterProxyModel(parent), mSortMechanism(gui_utility::mSortMechanism::lexical), mFilterNets(true), mFilterGates(true) { // QTS PROXY MODELS ARE DUMB, IMPLEMENT CUSTOM SOLUTION OR SWITCH TO A DIFFERENT FILTER METHOD @@ -14,32 +14,55 @@ namespace hal // STYLED DELEGATES USE THAT DATA STRUCTURE TO DRAW THEMSELVES } + bool ModuleProxyModel::toggleFilterNets() + { + mFilterNets = !mFilterNets; + invalidateFilter(); + return mFilterNets; + } + + bool ModuleProxyModel::toggleFilterGates() + { + mFilterGates = !mFilterGates; + invalidateFilter(); + return mFilterGates; + } + bool ModuleProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const { + QModelIndex sourceIndex = sourceModel()->index(sourceRow, 0, sourceParent); + if(!sourceIndex.isValid()) + return true; + auto item = static_cast(sourceIndex.internalPointer()); + + if(mFilterGates && item->getType() == ModuleItem::TreeItemType::Gate) + return false; + if(mFilterNets && item->getType() == ModuleItem::TreeItemType::Net) + return false; + if(filterRegularExpression().pattern().isEmpty()) return true; - QModelIndex sourceIndex = sourceModel()->index(sourceRow, 0, sourceParent); - if(sourceIndex.isValid()) + if(item->getChildCount() == 0) + return sourceModel()->data(sourceIndex, filterRole()).toString().contains(filterRegularExpression()); + + bool shouldBeDisplayed = sourceModel()->data(sourceIndex, filterRole()).toString().contains(filterRegularExpression());; + //go through all children and return the check of itself and the check of the children + for(int i = 0; i < item->getChildCount(); i++) { - auto item = static_cast(sourceIndex.internalPointer()); - if(item->childCount() == 0) - return sourceModel()->data(sourceIndex, filterRole()).toString().contains(filterRegularExpression()); - - bool shouldBeDisplayed = sourceModel()->data(sourceIndex, filterRole()).toString().contains(filterRegularExpression());; - //go through all children and return the check of itself and the check of the children - for(int i = 0; i < item->childCount(); i++) - { - shouldBeDisplayed = shouldBeDisplayed || filterAcceptsRow(i, sourceIndex); - } - - return shouldBeDisplayed; + shouldBeDisplayed = shouldBeDisplayed || filterAcceptsRow(i, sourceIndex); } - return true; + + return shouldBeDisplayed; } bool ModuleProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const { + ModuleItem* item_left = static_cast(source_left.internalPointer()); + ModuleItem* item_right = static_cast(source_right.internalPointer()); + if(item_left->getType() != item_right->getType()) + return item_left->getType() < item_right->getType(); + QString name_left = source_left.data().toString(); QString name_right = source_right.data().toString(); if (sortCaseSensitivity() == Qt::CaseInsensitive) diff --git a/plugins/gui/src/module_widget/module_tree_view.cpp b/plugins/gui/src/module_widget/module_tree_view.cpp index 65643141fec..cd0a168dcbe 100644 --- a/plugins/gui/src/module_widget/module_tree_view.cpp +++ b/plugins/gui/src/module_widget/module_tree_view.cpp @@ -1,5 +1,6 @@ #include "gui/module_widget/module_tree_view.h" #include +#include namespace hal { @@ -7,6 +8,14 @@ namespace hal { } + void ModuleTreeView::setDefaultColumnWidth() + { + setColumnWidth(0, 240); + setColumnWidth(1, 40); + setColumnWidth(2, 80); + header()->setStretchLastSection(true); + } + void ModuleTreeView::mousePressEvent(QMouseEvent *event) { if(event->button() != Qt::RightButton) diff --git a/plugins/gui/src/module_widget/module_widget.cpp b/plugins/gui/src/module_widget/module_widget.cpp index 223ad8f7ed4..063c36cf559 100644 --- a/plugins/gui/src/module_widget/module_widget.cpp +++ b/plugins/gui/src/module_widget/module_widget.cpp @@ -10,10 +10,13 @@ #include "gui/user_action/action_create_object.h" #include "gui/user_action/action_unfold_module.h" #include "gui/user_action/user_action_compound.h" +#include "gui/user_action/action_rename_object.h" #include "hal_core/netlist/gate.h" #include "hal_core/netlist/module.h" #include "hal_core/netlist/net.h" #include "gui/module_model/module_model.h" +#include "gui/graph_tab_widget/graph_tab_widget.h" + #include #include #include @@ -25,6 +28,8 @@ #include #include #include +#include +#include namespace hal { @@ -32,6 +37,8 @@ namespace hal : ContentWidget("Modules", parent), mTreeView(new ModuleTreeView(this)), mSearchbar(new Searchbar(this)), + mToggleNetsAction(new QAction(this)), + mToggleGatesAction(new QAction(this)), mModuleProxyModel(new ModuleProxyModel(this)) { @@ -39,7 +46,12 @@ namespace hal connect(mTreeView, &QTreeView::customContextMenuRequested, this, &ModuleWidget::handleTreeViewContextMenuRequested); + mToggleNetsAction->setIcon(gui_utility::getStyledSvgIcon(mHideNetsIconStyle, mHideNetsIconPath)); + mToggleGatesAction->setIcon(gui_utility::getStyledSvgIcon(mHideGatesIconStyle, mHideGatesIconPath)); mSearchAction->setIcon(gui_utility::getStyledSvgIcon(mSearchIconStyle, mSearchIconPath)); + + mToggleNetsAction->setToolTip("Toggle Net Visibility"); + mToggleGatesAction->setToolTip("Toggle Gate Visibility"); mSearchAction->setToolTip("Search"); mModuleProxyModel->setFilterKeyColumn(-1); @@ -48,12 +60,13 @@ namespace hal //mModuleProxyModel->setRecursiveFilteringEnabled(true); mModuleProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); mTreeView->setModel(mModuleProxyModel); + mTreeView->setDefaultColumnWidth(); mTreeView->setSortingEnabled(true); mTreeView->sortByColumn(0, Qt::AscendingOrder); mTreeView->setContextMenuPolicy(Qt::CustomContextMenu); mTreeView->setEditTriggers(QAbstractItemView::NoEditTriggers); mTreeView->setFrameStyle(QFrame::NoFrame); - mTreeView->header()->close(); + //mTreeView->header()->close(); mTreeView->setExpandsOnDoubleClick(false); mTreeView->setSelectionMode(QAbstractItemView::ExtendedSelection); mTreeView->expandAll(); @@ -82,10 +95,39 @@ namespace hal connect(qApp, &QApplication::focusChanged, this, &ModuleWidget::handleDeleteShortcutOnFocusChanged); + + connect(mToggleNetsAction, &QAction::triggered, this, &ModuleWidget::handleToggleNetsClicked); + connect(mToggleGatesAction, &QAction::triggered, this, &ModuleWidget::handleToggleGatesClicked); + } + + void ModuleWidget::handleToggleNetsClicked() + { + if(mModuleProxyModel->toggleFilterNets()) + { + mToggleNetsAction->setIcon(gui_utility::getStyledSvgIcon(mHideNetsIconStyle, mHideNetsIconPath)); + } + else + { + mToggleNetsAction->setIcon(gui_utility::getStyledSvgIcon(mShowNetsIconStyle, mShowNetsIconPath)); + } + } + + void ModuleWidget::handleToggleGatesClicked() + { + if(mModuleProxyModel->toggleFilterGates()) + { + mToggleGatesAction->setIcon(gui_utility::getStyledSvgIcon(mHideGatesIconStyle, mHideGatesIconPath)); + } + else + { + mToggleGatesAction->setIcon(gui_utility::getStyledSvgIcon(mShowGatesIconStyle, mShowGatesIconPath)); + } } void ModuleWidget::setupToolbar(Toolbar* toolbar) { + toolbar->addAction(mToggleNetsAction); + toolbar->addAction(mToggleGatesAction); toolbar->addAction(mSearchAction); } @@ -136,27 +178,110 @@ namespace hal if (!index.isValid()) return; + ModuleItem::TreeItemType type = getModuleItemFromIndex(index)->getType(); + QMenu context_menu; - QAction isolate_action("Isolate in new view", &context_menu); - QAction add_selection_action("Add selected gates to module", &context_menu); - QAction add_child_action("Add child module", &context_menu); - QAction change_name_action("Change module name", &context_menu); - QAction change_type_action("Change module type", &context_menu); - QAction change_color_action("Change module color", &context_menu); - QAction delete_action("Delete module", &context_menu); - - context_menu.addAction(&isolate_action); - context_menu.addAction(&add_selection_action); - context_menu.addAction(&add_child_action); - context_menu.addAction(&change_name_action); - context_menu.addAction(&change_type_action); - context_menu.addAction(&change_color_action); + QAction isolate_action; + QAction add_selection_action; + QAction add_child_action; + QAction change_name_action; + QAction change_type_action; + QAction change_color_action; + QAction delete_action; + QAction extractPythonAction; + QAction focus_in_view; + + switch(type) { + + case ModuleItem::TreeItemType::Module:{ + extractPythonAction.setIcon(QIcon(":/icons/python")); + extractPythonAction.setText("Extract Module as python code (copy to clipboard)"); + extractPythonAction.setParent(&context_menu); + + isolate_action.setText("Isolate in new view"); + isolate_action.setParent(&context_menu); + + add_selection_action.setText("Add selected gates to module"); + add_selection_action.setParent(&context_menu); + + add_child_action.setText("Add child module"); + add_child_action.setParent(&context_menu); + + change_name_action.setText("Change module name"); + change_name_action.setParent(&context_menu); + + change_type_action.setText("Change module type"); + change_type_action.setParent(&context_menu); + + change_color_action.setText("Change module color"); + change_color_action.setParent(&context_menu); + + delete_action.setText("Delete module"); + delete_action.setParent(&context_menu); + + focus_in_view.setText("Focus item in Graph View"); + focus_in_view.setParent(&context_menu); + break; + } + case ModuleItem::TreeItemType::Gate: { + extractPythonAction.setIcon(QIcon(":/icons/python")); + extractPythonAction.setText("Extract Gate as python code (copy to clipboard)"); + extractPythonAction.setParent(&context_menu); + + isolate_action.setText("Isolate in new view"); + isolate_action.setParent(&context_menu); + + change_name_action.setText("Change Gate name"); + change_name_action.setParent(&context_menu); + + focus_in_view.setText("Focus item in Graph View"); + focus_in_view.setParent(&context_menu); + break; + } + case ModuleItem::TreeItemType::Net: { + extractPythonAction.setIcon(QIcon(":/icons/python")); + extractPythonAction.setText("Extract Net as python code (copy to clipboard)"); + extractPythonAction.setParent(&context_menu); + + change_name_action.setText("Change Net name"); + change_name_action.setParent(&context_menu); + + focus_in_view.setText("Focus item in Graph View"); + focus_in_view.setParent(&context_menu); + break; + } + } + + if (type == ModuleItem::TreeItemType::Gate){ + context_menu.addAction(&extractPythonAction); + context_menu.addAction(&isolate_action); + context_menu.addAction(&change_name_action); + context_menu.addAction(&focus_in_view); + + } + + if (type == ModuleItem::TreeItemType::Module){ + context_menu.addAction(&extractPythonAction); + context_menu.addAction(&isolate_action); + context_menu.addAction(&change_name_action); + context_menu.addAction(&add_selection_action); + context_menu.addAction(&add_child_action); + context_menu.addAction(&change_type_action); + context_menu.addAction(&change_color_action); + context_menu.addAction(&focus_in_view); + } + + if (type == ModuleItem::TreeItemType::Net){ + context_menu.addAction(&extractPythonAction); + context_menu.addAction(&change_name_action); + context_menu.addAction(&focus_in_view); + } u32 module_id = getModuleItemFromIndex(index)->id(); auto module = gNetlist->get_module_by_id(module_id); - if(!(module == gNetlist->get_top_module())) + if(!(module == gNetlist->get_top_module()) && type == ModuleItem::TreeItemType::Module) context_menu.addAction(&delete_action); QAction* clicked = context_menu.exec(mTreeView->viewport()->mapToGlobal(point)); @@ -164,8 +289,23 @@ namespace hal if (!clicked) return; + if (clicked == &extractPythonAction){ + switch(type) + { + case ModuleItem::TreeItemType::Module: QApplication::clipboard()->setText("netlist.get_Module_by_id(" + QString::number(getModuleItemFromIndex(index)->id()) + ")"); break; + case ModuleItem::TreeItemType::Gate: QApplication::clipboard()->setText("netlist.get_gate_by_id(" + QString::number(getModuleItemFromIndex(index)->id()) + ")"); break; + case ModuleItem::TreeItemType::Net: QApplication::clipboard()->setText("netlist.get_net_by_id(" + QString::number(getModuleItemFromIndex(index)->id()) + ")"); break; + } + } + if (clicked == &isolate_action) - openModuleInView(index); + { + switch(type) + { + case ModuleItem::TreeItemType::Module: openModuleInView(index); break; + case ModuleItem::TreeItemType::Gate: openGateInView(index); break; + } + } if (clicked == &add_selection_action) gNetlistRelay->addSelectionToModule(getModuleItemFromIndex(index)->id()); @@ -177,7 +317,14 @@ namespace hal } if (clicked == &change_name_action) - gNetlistRelay->changeModuleName(getModuleItemFromIndex(index)->id()); + { + switch(type) + { + case ModuleItem::TreeItemType::Module: gNetlistRelay->changeModuleName(getModuleItemFromIndex(index)->id()); break; + case ModuleItem::TreeItemType::Gate: changeGateName(index); break; + case ModuleItem::TreeItemType::Net: changeNetName(index); break; + } + } if (clicked == &change_type_action) gNetlistRelay->changeModuleType(getModuleItemFromIndex(index)->id()); @@ -185,8 +332,20 @@ namespace hal if (clicked == &change_color_action) gNetlistRelay->changeModuleColor(getModuleItemFromIndex(index)->id()); - if (clicked == &delete_action) + if (clicked == &delete_action){ gNetlistRelay->deleteModule(getModuleItemFromIndex(index)->id()); + } + + if (clicked == &focus_in_view){ + switch(type) + { + case ModuleItem::TreeItemType::Module: gContentManager->getGraphTabWidget()->handleModuleFocus(getModuleItemFromIndex(index)->id()); break; + case ModuleItem::TreeItemType::Gate: gContentManager->getGraphTabWidget()->handleGateFocus(getModuleItemFromIndex(index)->id()); break; + case ModuleItem::TreeItemType::Net: gContentManager->getGraphTabWidget()->handleNetFocus(getModuleItemFromIndex(index)->id()); break; + } + + } + } void ModuleWidget::handleModuleRemoved(Module* module, u32 module_id) @@ -214,8 +373,13 @@ namespace hal for (const auto& index : current_selection) { - u32 module_id = getModuleItemFromIndex(index)->id(); - gSelectionRelay->addModule(module_id); + ModuleItem* mi = getModuleItemFromIndex(index); + if(mi->getType() == ModuleItem::TreeItemType::Module) + gSelectionRelay->addModule(mi->id()); + else if(mi->getType() == ModuleItem::TreeItemType::Gate) + gSelectionRelay->addGate(mi->id()); + else if(mi->getType() == ModuleItem::TreeItemType::Net) + gSelectionRelay->addNet(mi->id()); } if (current_selection.size() == 1) @@ -237,6 +401,52 @@ namespace hal openModuleInView(getModuleItemFromIndex(index)->id(), false); } + void ModuleWidget::openGateInView(const QModelIndex &index) + { + QSet gateId; + QSet moduleId; + QString name; + + name = gGraphContextManager->nextViewName("Isolated View"); + gateId.insert(getModuleItemFromIndex(index)->id()); + + UserActionCompound* act = new UserActionCompound; + act->setUseCreatedObject(); + act->addAction(new ActionCreateObject(UserActionObjectType::Context, name)); + act->addAction(new ActionAddItemsToObject(moduleId, gateId)); + act->exec(); + } + + void ModuleWidget::changeGateName(const QModelIndex &index) + { + QString oldName = getModuleItemFromIndex(index)->name(); + + bool confirm; + QString newName = QInputDialog::getText(this, "Rename Gate", "New name:", QLineEdit::Normal, oldName, &confirm); + + if (confirm && !newName.isEmpty()) + { + ActionRenameObject* act = new ActionRenameObject(newName); + act->setObject(UserActionObject(getModuleItemFromIndex(index)->id(), UserActionObjectType::ObjectType::Gate)); + act->exec(); + } + } + + void ModuleWidget::changeNetName(const QModelIndex &index) + { + QString oldName = getModuleItemFromIndex(index)->name(); + + bool confirm; + QString newName = QInputDialog::getText(this, "Rename Net", "New name:", QLineEdit::Normal, oldName, &confirm); + + if (confirm && !newName.isEmpty()) + { + ActionRenameObject* act = new ActionRenameObject(newName); + act->setObject(UserActionObject(getModuleItemFromIndex(index)->id(), UserActionObjectType::ObjectType::Net)); + act->exec(); + } + } + void ModuleWidget::openModuleInView(u32 moduleId, bool unfold) { const Module* module = gNetlist->get_module_by_id(moduleId); @@ -304,6 +514,46 @@ namespace hal return mModuleProxyModel; } + QString ModuleWidget::showNetsIconPath() const + { + return mShowNetsIconPath; + } + + QString ModuleWidget::showNetsIconStyle() const + { + return mShowNetsIconStyle; + } + + QString ModuleWidget::hideNetsIconPath() const + { + return mHideNetsIconPath; + } + + QString ModuleWidget::hideNetsIconStyle() const + { + return mHideNetsIconStyle; + } + + QString ModuleWidget::showGatesIconPath() const + { + return mShowGatesIconPath; + } + + QString ModuleWidget::showGatesIconStyle() const + { + return mShowGatesIconStyle; + } + + QString ModuleWidget::hideGatesIconPath() const + { + return mHideGatesIconPath; + } + + QString ModuleWidget::hideGatesIconStyle() const + { + return mHideGatesIconStyle; + } + QString ModuleWidget::searchIconPath() const { return mSearchIconPath; @@ -319,6 +569,46 @@ namespace hal return mSearchActiveIconStyle; } + void ModuleWidget::setShowNetsIconPath(const QString& path) + { + mShowNetsIconPath = path; + } + + void ModuleWidget::setShowNetsIconStyle(const QString& path) + { + mShowNetsIconStyle = path; + } + + void ModuleWidget::setHideNetsIconPath(const QString& path) + { + mHideNetsIconPath = path; + } + + void ModuleWidget::setHideNetsIconStyle(const QString& path) + { + mHideNetsIconStyle = path; + } + + void ModuleWidget::setShowGatesIconPath(const QString& path) + { + mShowGatesIconPath = path; + } + + void ModuleWidget::setShowGatesIconStyle(const QString& path) + { + mShowGatesIconStyle = path; + } + + void ModuleWidget::setHideGatesIconPath(const QString& path) + { + mHideGatesIconPath = path; + } + + void ModuleWidget::setHideGatesIconStyle(const QString& path) + { + mHideGatesIconStyle = path; + } + void ModuleWidget::setSearchIconPath(const QString& path) { mSearchIconPath = path; @@ -342,9 +632,21 @@ namespace hal } ModuleItem* selectedItem = getModuleItemFromIndex(mTreeView->currentIndex()); - if(selectedItem->parent() != nullptr) + if(selectedItem->getParent() != nullptr) { - gNetlistRelay->deleteModule(getModuleItemFromIndex(mTreeView->currentIndex())->id()); + switch(getModuleItemFromIndex(mTreeView->currentIndex())->getType()) + { + case ModuleItem::TreeItemType::Module: { + auto module = gNetlist->get_module_by_id(selectedItem->id()); + if((module == gNetlist->get_top_module())) + break; + gNetlistRelay->deleteModule(getModuleItemFromIndex(mTreeView->currentIndex())->id()); + break; + } + case ModuleItem::TreeItemType::Gate: break; + case ModuleItem::TreeItemType::Net: break; + + } } } diff --git a/plugins/gui/src/netlist_relay/netlist_relay.cpp b/plugins/gui/src/netlist_relay/netlist_relay.cpp index 92655c372ae..1132ffc8db2 100644 --- a/plugins/gui/src/netlist_relay/netlist_relay.cpp +++ b/plugins/gui/src/netlist_relay/netlist_relay.cpp @@ -27,7 +27,8 @@ namespace hal { - NetlistRelay::NetlistRelay(QObject* parent) : QObject(parent), mModuleModel(new ModuleModel(this)) + NetlistRelay::NetlistRelay(QObject* parent) + : QObject(parent), mModuleModel(new ModuleModel(this)), mModuleColorManager(new ModuleColorManager(this)) { connect(FileManager::get_instance(), &FileManager::fileOpened, this, &NetlistRelay::debugHandleFileOpened); // DEBUG LINE connect(this, &NetlistRelay::signalThreadEvent, this, &NetlistRelay::handleThreadEvent, Qt::BlockingQueuedConnection); @@ -81,14 +82,19 @@ namespace hal QColor NetlistRelay::getModuleColor(const u32 id) { - return mModuleModel->moduleColor(id); + return mModuleColorManager->moduleColor(id); } - ModuleModel* NetlistRelay::getModuleModel() + ModuleModel* NetlistRelay::getModuleModel() const { return mModuleModel; } + ModuleColorManager* NetlistRelay::getModuleColorManager() const + { + return mModuleColorManager; + } + void NetlistRelay::changeModuleName(const u32 id) { // NOT THREADSAFE @@ -140,8 +146,6 @@ namespace hal ActionSetObjectColor* act = new ActionSetObjectColor(color); act->setObject(UserActionObject(id, UserActionObjectType::Module)); act->exec(); - - Q_EMIT moduleColorChanged(m); } void NetlistRelay::addSelectionToModule(const u32 id) @@ -376,7 +380,8 @@ namespace hal // suppress actions if we receive this for the top module if (mod->get_parent_module() != nullptr) { - mModuleModel->setRandomColor(mod->get_id()); + mModuleModel->addModule(mod->get_id(), mod->get_parent_module()->get_id()); + mModuleColorManager->setRandomColor(mod->get_id()); } gGraphContextManager->handleModuleCreated(mod); @@ -387,7 +392,8 @@ namespace hal case ModuleEvent::event::removed: { //< no associated_data - mModuleModel->removeColor(mod->get_id()); + mModuleColorManager->removeColor(mod->get_id()); + mModuleModel->removeModule(mod->get_id()); gGraphContextManager->handleModuleRemoved(mod); gSelectionRelay->handleModuleRemoved(mod->get_id()); @@ -398,7 +404,7 @@ namespace hal case ModuleEvent::event::name_changed: { //< no associated_data - mModuleModel->updateModule(mod->get_id()); + mModuleModel->updateModuleName(mod->get_id()); gGraphContextManager->handleModuleNameChanged(mod); @@ -408,14 +414,14 @@ namespace hal case ModuleEvent::event::parent_changed: { //< no associated_data + mModuleModel->handleModuleParentChanged(mod); + Q_EMIT moduleParentChanged(mod); break; } case ModuleEvent::event::submodule_added: { //< associated_data = id of added module - mModuleModel->addModule(associated_data, mod->get_id()); - gGraphContextManager->handleModuleSubmoduleAdded(mod, associated_data); Q_EMIT moduleSubmoduleAdded(mod, associated_data); @@ -424,8 +430,6 @@ namespace hal case ModuleEvent::event::submodule_removed: { //< associated_data = id of removed module - mModuleModel->remove_module(associated_data); - gGraphContextManager->handleModuleSubmoduleRemoved(mod, associated_data); Q_EMIT moduleSubmoduleRemoved(mod, associated_data); @@ -434,6 +438,7 @@ namespace hal case ModuleEvent::event::gate_assigned: { //< associated_data = id of inserted gate + mModuleModel->handleModuleGateAssinged(associated_data, mod->get_id()); gGraphContextManager->handleModuleGateAssigned(mod, associated_data); Q_EMIT moduleGateAssigned(mod, associated_data); @@ -442,6 +447,7 @@ namespace hal case ModuleEvent::event::gate_removed: { //< associated_data = id of removed gate + mModuleModel->removeGate(associated_data); gGraphContextManager->handleModuleGateRemoved(mod, associated_data); Q_EMIT moduleGateRemoved(mod, associated_data); @@ -529,6 +535,7 @@ namespace hal case GateEvent::event::name_changed: { //< no associated_data + mModuleModel->updateGateName(gat->get_id()); gGraphContextManager->handleGateNameChanged(gat); Q_EMIT gateNameChanged(gat); @@ -573,6 +580,7 @@ namespace hal case NetEvent::event::created: { //< no associated_data + mModuleModel->addNet(net->get_id(), gNetlist->get_top_module()->get_id()); gGraphContextManager->handleNetCreated(net); Q_EMIT netCreated(net); @@ -581,6 +589,7 @@ namespace hal case NetEvent::event::removed: { //< no associated_data + mModuleModel->removeNet(net->get_id()); gGraphContextManager->handleNetRemoved(net); gSelectionRelay->handleNetRemoved(net->get_id()); @@ -590,6 +599,7 @@ namespace hal case NetEvent::event::name_changed: { //< no associated_data + mModuleModel->updateNetName(net->get_id()); gGraphContextManager->handleNetNameChanged(net); Q_EMIT netNameChanged(net); @@ -608,6 +618,7 @@ namespace hal case NetEvent::event::src_added: { //< associated_data = id of src gate + mModuleModel->updateNet(net); gGraphContextManager->handleNetSourceAdded(net, associated_data); Q_EMIT netSourceAdded(net, associated_data); @@ -616,6 +627,7 @@ namespace hal case NetEvent::event::src_removed: { //< associated_data = id of src gate + mModuleModel->updateNet(net); gGraphContextManager->handleNetSourceRemoved(net, associated_data); Q_EMIT netSourceRemoved(net, associated_data); @@ -624,6 +636,7 @@ namespace hal case NetEvent::event::dst_added: { //< associated_data = id of dst gate + mModuleModel->updateNet(net); gGraphContextManager->handleNetDestinationAdded(net, associated_data); Q_EMIT netDestinationAdded(net, associated_data); @@ -632,6 +645,7 @@ namespace hal case NetEvent::event::dst_removed: { //< associated_data = id of dst gate + mModuleModel->updateNet(net); gGraphContextManager->handleNetDestinationRemoved(net, associated_data); Q_EMIT netDestinationRemoved(net, associated_data); @@ -670,9 +684,9 @@ namespace hal void NetlistRelay::debugHandleFileOpened() { for (Module* m : gNetlist->get_modules()) - mModuleModel->setRandomColor(m->get_id()); + mModuleColorManager->setRandomColor(m->get_id()); mModuleModel->init(); - mColorSerializer.restore(mModuleModel); + mColorSerializer.restore(mModuleColorManager); } void NetlistRelay::debugHandleFileClosed() diff --git a/plugins/gui/src/selection_details_widget/gate_details_widget/gate_pin_tree.cpp b/plugins/gui/src/selection_details_widget/gate_details_widget/gate_pin_tree.cpp index ffce52f1003..f1ed3a05928 100644 --- a/plugins/gui/src/selection_details_widget/gate_details_widget/gate_pin_tree.cpp +++ b/plugins/gui/src/selection_details_widget/gate_details_widget/gate_pin_tree.cpp @@ -96,7 +96,7 @@ namespace hal if(!idx.isValid()) return; - TreeItem* clickedItem = mPinModel->getItemFromIndex(idx); + BaseTreeItem* clickedItem = mPinModel->getItemFromIndex(idx); QMenu menu; GatePinsTreeModel::itemType type = mPinModel->getTypeOfItem(clickedItem); bool isMiscSectionSet = false;//so that the misc-section is not set multiple times @@ -201,7 +201,7 @@ namespace hal } - void GatePinTree::buildPythonMenuForPin(QMenu &menu, TreeItem *clickedPinItem) + void GatePinTree::buildPythonMenuForPin(QMenu &menu, BaseTreeItem *clickedPinItem) { // 1.) NET-OBJECT QList netIdsOfItem = mPinModel->getNetIDsOfTreeItem(clickedPinItem); @@ -243,7 +243,7 @@ namespace hal } - void GatePinTree::buildPythonMenuForPinGroup(QMenu &menu, TreeItem *clickedPinIGrouptem) + void GatePinTree::buildPythonMenuForPinGroup(QMenu &menu, BaseTreeItem *clickedPinIGrouptem) { // 1. PYTHON LIST OF PIN GROUPS QString pythonList = "["; @@ -259,7 +259,7 @@ namespace hal }); //2. DIRECTION and TYPE(determined by the pin(s) within the group) - TreeItem* firstPinItemOfGroup = clickedPinIGrouptem->getChild(0); + BaseTreeItem* firstPinItemOfGroup = clickedPinIGrouptem->getChild(0); if(firstPinItemOfGroup) { QString pythonCommandGroupDirection = PyCodeProvider::pyCodeGateTypePinDirection(mPinModel->getCurrentGateID(), diff --git a/plugins/gui/src/selection_details_widget/gate_details_widget/pin_tree_model.cpp b/plugins/gui/src/selection_details_widget/gate_details_widget/pin_tree_model.cpp index 25ae97821af..3b2a9e9138b 100644 --- a/plugins/gui/src/selection_details_widget/gate_details_widget/pin_tree_model.cpp +++ b/plugins/gui/src/selection_details_widget/gate_details_widget/pin_tree_model.cpp @@ -12,12 +12,78 @@ namespace hal { + PinTreeItem::PinTreeItem(const std::string &pinName, QString pinDirection, QString pinType, QString netName) + :mPinName(pinName), mPinDirection(pinDirection), mPinType(pinType), mNetName(netName) + {;} + + PinTreeItem::PinTreeItem() + {;} + + QVariant PinTreeItem::getData(int index) const + { + switch (index) + { + case 0: { + QVariant qvPinName = QVariant(QString::fromStdString(mPinName)); + return qvPinName; + break;} + case 1: { + QVariant qvPinDirection = QVariant(mPinDirection); + return qvPinDirection; + break;} + case 2: { + QVariant qvPinType = QVariant(mPinType); + return qvPinType; + break;} + case 3: { + QVariant qvNetName = QVariant(mNetName); + return qvNetName; + break;} + } + } + + void PinTreeItem::setData(QList data) + { + mPinName = data[0].toString().toStdString(); + mPinDirection = data[1].toString(); + mPinType = data[2].toString(); + mNetName = data[3].toString(); + } + + void PinTreeItem::setDataAtIndex(int index, QVariant &data) + { + switch (index) + { + case 0: { + mPinName = data.toString().toStdString(); + break;} + case 1: { + mPinDirection = data.toString(); + break;} + case 2: { + mPinType = data.toString(); + break;} + case 3: { + mNetName = data.toString(); + break;} + } + + + } + + void PinTreeItem::appendData(QVariant data) {} + + int PinTreeItem::getColumnCount() const + { + return 4; + } + GatePinsTreeModel::GatePinsTreeModel(QObject* parent) : BaseTreeModel(parent) { - setHeaderLabels(QList() << "Name" - << "Direction" - << "Type" - << "Connected Net"); + setHeaderLabels(QStringList() << "Name" + << "Direction" + << "Type" + << "Connected Net"); //added to store a list of (multiple) net ids in a given treeitem (perhaps dont do this //at all, handle it in the view? (since the gate-id and pin name is accessable, the nets can be evaluated there @@ -45,7 +111,7 @@ namespace hal GateType* gateType = g->get_type(); for (auto pin : gateType->get_pins()) { - TreeItem* pinItem = new TreeItem(); + PinTreeItem* pinItem = new PinTreeItem(); //get all infos for that pin const std::string& grouping = pin->get_group().first->get_name(); PinDirection direction = pin->get_direction(); @@ -96,11 +162,11 @@ namespace hal pinItem->setAdditionalData(keyRepresentedNetsID, QVariant::fromValue(netIDs)); if (!grouping.empty()) { - TreeItem* groupingsItem = mPinGroupingToTreeItem.value(grouping, nullptr); //since its a map, its okay + BaseTreeItem* groupingsItem = mPinGroupingToTreeItem.value(grouping, nullptr); //since its a map, its okay if (!groupingsItem) { //assume all items in the same grouping habe the same direction and type, so the grouping-item has also these types - groupingsItem = new TreeItem(QList() << QString::fromStdString(grouping) << pinDirection << pinType << ""); + groupingsItem = new PinTreeItem(grouping, pinDirection, pinType, ""); groupingsItem->setAdditionalData(keyType, QVariant::fromValue(itemType::grouping)); mRootItem->appendChild(groupingsItem); mPinGroupingToTreeItem.insert(grouping, groupingsItem); @@ -118,12 +184,12 @@ namespace hal return mGateId; } - QList GatePinsTreeModel::getNetIDsOfTreeItem(TreeItem* item) + QList GatePinsTreeModel::getNetIDsOfTreeItem(BaseTreeItem* item) { return item->getAdditionalData(keyRepresentedNetsID).value>(); } - GatePinsTreeModel::itemType GatePinsTreeModel::getTypeOfItem(TreeItem* item) + GatePinsTreeModel::itemType GatePinsTreeModel::getTypeOfItem(BaseTreeItem* item) { return item->getAdditionalData(keyType).value(); } @@ -136,4 +202,7 @@ namespace hal return g->get_type()->get_pins().size(); } + + + } // namespace hal diff --git a/plugins/gui/src/selection_details_widget/module_details_tab_widget.cpp b/plugins/gui/src/selection_details_widget/module_details_tab_widget.cpp index 37fbd29284d..d97e986f8aa 100644 --- a/plugins/gui/src/selection_details_widget/module_details_tab_widget.cpp +++ b/plugins/gui/src/selection_details_widget/module_details_tab_widget.cpp @@ -7,10 +7,14 @@ #include "gui/comment_system/widgets/comment_widget.h" #include "hal_core/netlist/module.h" +#include "gui/gui_globals.h" +#include "gui/module_model/module_model.h" +#include "gui/module_model/module_color_manager.h" namespace hal { - ModuleDetailsTabWidget::ModuleDetailsTabWidget(QWidget* parent) : DetailsTabWidget(parent) + ModuleDetailsTabWidget::ModuleDetailsTabWidget(QWidget* parent) + : DetailsTabWidget(parent), mModuleId(0) { setIcon(SelectionDetailsIconProvider::ModuleIcon); @@ -48,11 +52,24 @@ namespace hal mCommentWidget = new CommentWidget(this); QTabWidget::addTab(mCommentWidget, "Comments"); + connect(gNetlistRelay->getModuleColorManager(),&ModuleColorManager::moduleColorChanged,this,&ModuleDetailsTabWidget::handleModuleColorChanged); } + void ModuleDetailsTabWidget::handleModuleColorChanged(u32 id) + { + if (!mModuleId || mModuleId != id) return; + setIcon(SelectionDetailsIconProvider::ModuleIcon,mModuleId); + } + void ModuleDetailsTabWidget::setModule(Module* module) { - if (module) setIcon(SelectionDetailsIconProvider::ModuleIcon, module->get_id()); + if (module) + { + setIcon(SelectionDetailsIconProvider::ModuleIcon, module->get_id()); + mModuleId = module->get_id(); + } + else + mModuleId = 0; //pass module or other stuff to widgets mModuleInfoTable->setModule(module); mPinsTree->setModule(module); diff --git a/plugins/gui/src/selection_details_widget/module_details_widget/module_elements_tree.cpp b/plugins/gui/src/selection_details_widget/module_details_widget/module_elements_tree.cpp index dc38c9eb7d2..208a6c1d362 100644 --- a/plugins/gui/src/selection_details_widget/module_details_widget/module_elements_tree.cpp +++ b/plugins/gui/src/selection_details_widget/module_details_widget/module_elements_tree.cpp @@ -61,7 +61,7 @@ namespace hal if(!clickedIndex.isValid()) return; - TreeItem* clickedItem = mModel->getItemFromIndex(clickedIndex); + BaseTreeItem* clickedItem = mModel->getItemFromIndex(clickedIndex); int id = clickedItem->getData(ModuleTreeModel::sIdColumn).toInt(); ModuleTreeModel::itemType type = mModel->getTypeOfItem(clickedItem); QMenu menu; diff --git a/plugins/gui/src/selection_details_widget/module_details_widget/module_ports_tree.cpp b/plugins/gui/src/selection_details_widget/module_details_widget/module_ports_tree.cpp index 9d1b73c0400..c4c34d3d2a2 100644 --- a/plugins/gui/src/selection_details_widget/module_details_widget/module_ports_tree.cpp +++ b/plugins/gui/src/selection_details_widget/module_details_widget/module_ports_tree.cpp @@ -87,13 +87,13 @@ namespace hal return; //all relevant information - TreeItem* clickedItem = mPortModel->getItemFromIndex(clickedIndex); + PortTreeItem* clickedItem = static_cast(mPortModel->getItemFromIndex(clickedIndex)); ModulePinsTreeModel::itemType type = mPortModel->getTypeOfItem(clickedItem); Net* n = mPortModel->getNetFromItem(clickedItem); QString name = clickedItem->getData(ModulePinsTreeModel::sNameColumn).toString(); u32 modId = mPortModel->getRepresentedModuleId(); auto mod = gNetlist->get_module_by_id(modId); - QList selectedPins; + QList selectedPins; std::pair sameGroup; bool onlyPins; std::tie(selectedPins, sameGroup, onlyPins) = getSelectedPins(); @@ -266,7 +266,7 @@ namespace hal void ModulePinsTree::appendMultiSelectionEntries(QMenu& menu, int modId) { - QList selectedPins; + QList selectedPins; std::pair sameGroup; bool onlyPins; std::tie(selectedPins, sameGroup, onlyPins) = getSelectedPins(); @@ -299,16 +299,16 @@ namespace hal } } - std::tuple, std::pair, bool> ModulePinsTree::getSelectedPins() + std::tuple, std::pair, bool> ModulePinsTree::getSelectedPins() { - QList selectedPins; //ordered - QSet alreadyProcessedPins; //only for performance purposes + QList selectedPins; //ordered + QSet alreadyProcessedPins; //only for performance purposes bool sameGroup = true; bool onlyPins = true; int groupId = -1; for (auto index : selectionModel()->selectedRows()) { - TreeItem* item = mPortModel->getItemFromIndex(index); + PortTreeItem* item = static_cast(mPortModel->getItemFromIndex(index)); auto itemType = mPortModel->getTypeOfItem(item); if (itemType == ModulePinsTreeModel::itemType::pin) { diff --git a/plugins/gui/src/selection_details_widget/module_details_widget/module_tree_model.cpp b/plugins/gui/src/selection_details_widget/module_details_widget/module_tree_model.cpp index 90b38a79a58..c6b16cdd36f 100644 --- a/plugins/gui/src/selection_details_widget/module_details_widget/module_tree_model.cpp +++ b/plugins/gui/src/selection_details_widget/module_details_widget/module_tree_model.cpp @@ -1,6 +1,5 @@ #include "gui/selection_details_widget/module_details_widget/module_tree_model.h" #include "gui/selection_details_widget/selection_details_icon_provider.h" -#include "gui/basic_tree_model/tree_item.h" #include "hal_core/netlist/module.h" #include "hal_core/netlist/gate.h" #include "gui/gui_globals.h" @@ -9,9 +8,69 @@ namespace hal { + + ModuleTreeitem::ModuleTreeitem(const std::string &name, int id, std::string tp) + : mType(tp), mId(id), mName(name) + {;} + + QVariant ModuleTreeitem::getData(int index) const + { + switch (index) + { + case 0: { + QVariant qvName = QVariant(QString::fromStdString(mName)); + return qvName; + break;} + case 1: { + QVariant qvId = QVariant(mId); + return qvId; + break;} + case 2: { + QVariant qvType = QVariant(QString::fromStdString(mType)); + return qvType; + break;} + } + } + + void ModuleTreeitem::setData(QList data) + { + mName = data[0].toString().toStdString(); + mId = data[1].toInt(); + mType = data[2].toString().toStdString(); + } + + void ModuleTreeitem::setDataAtIndex(int index, QVariant &data) + { + const char* ctyp[] = { "module", "gate"}; + + switch (index) + { + case 0: mName = data.toString().toStdString(); break; + case 1: mId = data.toInt(); break; + case 2: + for (int j=0; j<3; j++) + if (data.toString() == ctyp[j]) + { + mType = data.toString().toStdString(); + break; + } + } + } + + void ModuleTreeitem::appendData(QVariant data) + { + + } + + int ModuleTreeitem::getColumnCount() const + { + return 3; + } + + ModuleTreeModel::ModuleTreeModel(QObject* parent) : BaseTreeModel(parent), mModId(-1) { - setHeaderLabels(QList() << "Name" << "ID" << "Type"); + setHeaderLabels(QStringList() << "Name" << "ID" << "Type"); } ModuleTreeModel::~ModuleTreeModel() @@ -33,7 +92,7 @@ namespace hal //delete all children, not the root item (manually for performance reasons) while(mRootItem->getChildCount() > 0) { - TreeItem* tmp = mRootItem->removeChildAtPos(0); + BaseTreeItem* tmp = mRootItem->removeChildAtPos(0); delete tmp; } @@ -41,8 +100,8 @@ namespace hal //add modules for(auto mod : m->get_submodules()) { - TreeItem* modItem = new TreeItem(QList() << QString::fromStdString(mod->get_name()) - << mod->get_id() << QString::fromStdString(mod->get_type())); + ModuleTreeitem* modItem = new ModuleTreeitem(mod->get_name(), + mod->get_id(), mod->get_type()); moduleRecursive(mod, modItem); modItem->setAdditionalData(mKeyItemType, QVariant::fromValue(itemType::module)); modItem->setAdditionalData(mKeyRepId, mod->get_id()); @@ -52,8 +111,8 @@ namespace hal //add gates for(auto gate : m->get_gates()) { - TreeItem* gateItem = new TreeItem(QList() << QString::fromStdString(gate->get_name()) - << gate->get_id() << QString::fromStdString(gate->get_type()->get_name())); + ModuleTreeitem* gateItem = new ModuleTreeitem(gate->get_name(), + gate->get_id(), gate->get_type()->get_name()); gateItem->setAdditionalData(mKeyItemType, QVariant::fromValue(itemType::gate)); gateItem->setAdditionalData(mKeyRepId, gate->get_id()); mRootItem->appendChild(gateItem); @@ -78,7 +137,7 @@ namespace hal if(!index.isValid()) return QVariant(); - TreeItem* item = getItemFromIndex(index); + BaseTreeItem* item = getItemFromIndex(index); if(!item) return QVariant(); @@ -90,18 +149,18 @@ namespace hal } - ModuleTreeModel::itemType ModuleTreeModel::getTypeOfItem(TreeItem *item) const + ModuleTreeModel::itemType ModuleTreeModel::getTypeOfItem(BaseTreeItem *item) const { return item->getAdditionalData(mKeyItemType).value(); } - void ModuleTreeModel::moduleRecursive(Module *mod, TreeItem *modItem) + void ModuleTreeModel::moduleRecursive(Module *mod, BaseTreeItem *modItem) { - TreeItem* subModItem = nullptr; + ModuleTreeitem* subModItem = nullptr; for(Module* subMod : mod->get_submodules()) { - subModItem = new TreeItem(QList() << QString::fromStdString(subMod->get_name()) - << subMod->get_id() << QString::fromStdString(subMod->get_type())); + subModItem = new ModuleTreeitem(subMod->get_name(), + subMod->get_id(), subMod->get_type()); moduleRecursive(subMod, subModItem); subModItem->setAdditionalData(mKeyItemType, QVariant::fromValue(itemType::module)); subModItem->setAdditionalData(mKeyRepId, subMod->get_id()); @@ -110,8 +169,8 @@ namespace hal } for(auto gate : mod->get_gates()) { - TreeItem* gateItem = new TreeItem(QList() << QString::fromStdString(gate->get_name()) - << gate->get_id() << QString::fromStdString(gate->get_type()->get_name())); + ModuleTreeitem* gateItem = new ModuleTreeitem(gate->get_name(), + gate->get_id(), gate->get_type()->get_name()); gateItem->setAdditionalData(mKeyItemType, QVariant::fromValue(itemType::gate)); gateItem->setAdditionalData(mKeyRepId, gate->get_id()); modItem->appendChild(gateItem); @@ -153,8 +212,8 @@ namespace hal beginResetModel(); for(auto gate : mod->get_gates()) { - TreeItem* gateItem = new TreeItem(QList() << QString::fromStdString(gate->get_name()) - << gate->get_id() << QString::fromStdString(gate->get_type()->get_name())); + ModuleTreeitem* gateItem = new ModuleTreeitem(gate->get_name(), + gate->get_id(), gate->get_type()->get_name()); gateItem->setAdditionalData(mKeyItemType, QVariant::fromValue(itemType::gate)); gateItem->setAdditionalData(mKeyRepId, gate->get_id()); modItem->appendChild(gateItem); @@ -164,7 +223,7 @@ namespace hal endResetModel(); } - QIcon ModuleTreeModel::getIconFromItem(TreeItem *item) const + QIcon ModuleTreeModel::getIconFromItem(BaseTreeItem *item) const { if(!item) return QIcon(); @@ -238,8 +297,8 @@ namespace hal { beginResetModel(); auto addedMod = gNetlist->get_module_by_id(added_module); - TreeItem* addedSubmodItem = new TreeItem(QList() << QString::fromStdString(addedMod->get_name()) << addedMod->get_id() - << QString::fromStdString(addedMod->get_type())); + ModuleTreeitem* addedSubmodItem = new ModuleTreeitem(addedMod->get_name(), addedMod->get_id(), + addedMod->get_type()); moduleRecursive(addedMod, addedSubmodItem); addedSubmodItem->setAdditionalData(mKeyItemType, QVariant::fromValue(itemType::module)); addedSubmodItem->setAdditionalData(mKeyRepId, addedMod->get_id()); @@ -258,11 +317,11 @@ namespace hal return; //1. Remove all items from maps through BFS (maybe own function?) - QQueue treeItemsQueue; + QQueue treeItemsQueue; treeItemsQueue.enqueue(removedModItem); while(!treeItemsQueue.isEmpty()) { - TreeItem* current = treeItemsQueue.dequeue(); + BaseTreeItem* current = treeItemsQueue.dequeue(); switch (getTypeOfItem(current)) { case itemType::module: mModuleToTreeitems.remove(gNetlist->get_module_by_id(current->getData(ModuleTreeModel::sIdColumn).toInt())); break; @@ -283,7 +342,7 @@ namespace hal void ModuleTreeModel::handleModuleGateAssigned(Module *m, u32 assigned_gate) { - TreeItem* modItem = mModuleToTreeitems.value(m, nullptr); + BaseTreeItem* modItem = mModuleToTreeitems.value(m, nullptr); if((int)m->get_id() == mModId) modItem = mRootItem; @@ -296,8 +355,8 @@ namespace hal if(getTypeOfItem(modItem->getChild(indexToInsert)) != itemType::module) break; - TreeItem* gateItem = new TreeItem(QList() << QString::fromStdString(assignedGate->get_name()) - << assignedGate->get_id() << QString::fromStdString(assignedGate->get_type()->get_name())); + ModuleTreeitem* gateItem = new ModuleTreeitem(assignedGate->get_name(), + assignedGate->get_id(), assignedGate->get_type()->get_name()); gateItem->setAdditionalData(mKeyItemType, QVariant::fromValue(itemType::gate)); mGateToTreeitems.insert(assignedGate, gateItem); //beginInsertRows(getIndexFromItem(modItem), indexToInsert, indexToInsert); @@ -336,7 +395,8 @@ namespace hal auto gateItem = mGateToTreeitems.value(g, nullptr); if(gateItem) { - gateItem->setDataAtIndex(sNameColumn, QString::fromStdString(g->get_name())); + QVariant qv = QVariant(QString::fromStdString(g->get_name())); + gateItem->setDataAtIndex(sNameColumn, qv); QModelIndex inx0 = getIndexFromItem(gateItem); QModelIndex inx1 = createIndex(inx0.row(), sNameColumn, inx0.internalPointer()); Q_EMIT dataChanged(inx0, inx1); @@ -348,7 +408,8 @@ namespace hal auto moduleItem = mModuleToTreeitems.value(m, nullptr); if(moduleItem) { - moduleItem->setDataAtIndex(sNameColumn, QString::fromStdString(m->get_name())); + QVariant qv = QVariant(QString::fromStdString(m->get_name())); + moduleItem->setDataAtIndex(sNameColumn, qv); QModelIndex inx0 = getIndexFromItem(moduleItem); QModelIndex inx1 = createIndex(inx0.row(), sNameColumn, inx0.internalPointer()); Q_EMIT dataChanged(inx0, inx1); @@ -360,7 +421,8 @@ namespace hal auto moduleItem = mModuleToTreeitems.value(m, nullptr); if(moduleItem) { - moduleItem->setDataAtIndex(sTypeColumn, QString::fromStdString(m->get_type())); + QVariant qv = QVariant(QString::fromStdString(m->get_type())); + moduleItem->setDataAtIndex(sTypeColumn, qv); QModelIndex inx0 = getIndexFromItem(moduleItem); QModelIndex inx1 = createIndex(inx0.row(), sTypeColumn, inx0.internalPointer()); Q_EMIT dataChanged(inx0, inx1); @@ -416,4 +478,7 @@ namespace hal mEventsConnected = true; } + + + } diff --git a/plugins/gui/src/selection_details_widget/module_details_widget/netlist_elements_tree_model.cpp b/plugins/gui/src/selection_details_widget/module_details_widget/netlist_elements_tree_model.cpp index b66f040dd03..0073b6e8a0c 100644 --- a/plugins/gui/src/selection_details_widget/module_details_widget/netlist_elements_tree_model.cpp +++ b/plugins/gui/src/selection_details_widget/module_details_widget/netlist_elements_tree_model.cpp @@ -1,6 +1,6 @@ #include "gui/selection_details_widget/module_details_widget/netlist_elements_tree_model.h" #include "gui/selection_details_widget/selection_details_icon_provider.h" -#include "gui/basic_tree_model/tree_item.h" +#include "gui/basic_tree_model/base_tree_item.h" #include "hal_core/netlist/module.h" #include "hal_core/netlist/gate.h" #include "gui/gui_globals.h" @@ -9,12 +9,69 @@ namespace hal { + + NetlistElementsTreeitem::NetlistElementsTreeitem(const QString &name, int id, QString tp) + : mType(tp), mId(id), mName(name) + {;} + + QVariant NetlistElementsTreeitem::getData(int index) const + { + switch (index) + { + case 0: { + QVariant qvName = QVariant(mName); + return qvName; + break;} + case 1: { + QVariant qvId = QVariant(mId); + return qvId; + break;} + case 2: { + QVariant qvType = QVariant(mType); + return qvType; + break;} + } + } + + void NetlistElementsTreeitem::setData(QList data) + { + mName = data[0].toString(); + mId = data[1].toInt(); + mType = data[2].toString(); + + } + + void NetlistElementsTreeitem::setDataAtIndex(int index, QVariant &data) + { + const char* ctyp[] = { "module", "gate", "net"}; + + switch (index) + { + case 0: mName = data.toString(); break; + case 1: mId = data.toInt(); break; + case 2: + for (int j=0; j<3; j++) + if (data.toString() == ctyp[j]) + { + mType = data.toString(); + break; + } + } + } + + void NetlistElementsTreeitem::appendData(QVariant data) {} + + int NetlistElementsTreeitem::getColumnCount() const + { + return 3; + } + NetlistElementsTreeModel::NetlistElementsTreeModel(QObject *parent) : BaseTreeModel(parent), mGatesDisplayed(true), mNetsDisplayed(true), mDisplaySubmodRecursive(true), mCurrentlyDisplayingModule(false), mModId(-1) { // use root item to store header information - setHeaderLabels(QList() << "Name" << "ID" << "Type"); + setHeaderLabels(QStringList() << "Name" << "ID" << "Type"); // CONNECTIONS connect(gNetlistRelay, &NetlistRelay::gateNameChanged, this, &NetlistElementsTreeModel::gateNameChanged); @@ -38,12 +95,14 @@ namespace hal if(!index.isValid()) return QVariant(); - TreeItem* item = getItemFromIndex(index); + BaseTreeItem* item = getItemFromIndex(index); if(!item) return QVariant(); - if(role == Qt::DecorationRole && index.column() == 0) - return getIconFromItem(getItemFromIndex(index)); + if(role == Qt::DecorationRole && index.column() == 0) { + NetlistElementsTreeitem* neti = static_cast(getItemFromIndex(index)); + return getIconFromItem(neti); + } //yes, it performs the same two checks again, should be okay though (in terms of performance) return BaseTreeModel::data(index, role); @@ -83,8 +142,8 @@ namespace hal Module* mod = gNetlist->get_module_by_id(id); if(!mod) continue; - TreeItem* modItem = new TreeItem(QList() << QString::fromStdString(mod->get_name()) - << mod->get_id() << QString::fromStdString(mod->get_type())); + NetlistElementsTreeitem* modItem = new NetlistElementsTreeitem(QString::fromStdString(mod->get_name()), + mod->get_id(), QString::fromStdString(mod->get_type())); if(displayModulesRecursive) moduleRecursive(mod, modItem, showGatesInSubmods, showNetsInSubmods); modItem->setAdditionalData(keyItemType, QVariant::fromValue(itemType::module)); @@ -96,8 +155,8 @@ namespace hal for(int id : gateIds) { Gate* gate = gNetlist->get_gate_by_id(id); - TreeItem* gateItem = new TreeItem(QList() << QString::fromStdString(gate->get_name()) - << gate->get_id() << QString::fromStdString(gate->get_type()->get_name())); + NetlistElementsTreeitem* gateItem = new NetlistElementsTreeitem(QString::fromStdString(gate->get_name()), + gate->get_id(), QString::fromStdString(gate->get_type()->get_name())); gateItem->setAdditionalData(keyItemType, QVariant::fromValue(itemType::gate)); gateItem->setAdditionalData(keyRepresentedID, gate->get_id()); mRootItem->appendChild(gateItem); @@ -106,8 +165,8 @@ namespace hal for(int id : netIds) { Net* net = gNetlist->get_net_by_id(id); - TreeItem* netItem = new TreeItem(QList() << QString::fromStdString(net->get_name()) - << net->get_id() << ""); + NetlistElementsTreeitem* netItem = new NetlistElementsTreeitem(QString::fromStdString(net->get_name()), + net->get_id(), ""); netItem->setAdditionalData(keyItemType, QVariant::fromValue(itemType::net)); netItem->setAdditionalData(keyRepresentedID, net->get_id()); mRootItem->appendChild(netItem); @@ -137,21 +196,22 @@ namespace hal Q_EMIT numberOfSubmodulesChanged(mod->get_submodules().size()); } - NetlistElementsTreeModel::itemType NetlistElementsTreeModel::getTypeOfItem(TreeItem *item) const + NetlistElementsTreeModel::itemType NetlistElementsTreeModel::getTypeOfItem(NetlistElementsTreeitem *item) const { return item->getAdditionalData(keyItemType).value(); } - int NetlistElementsTreeModel::getRepresentedIdOfItem(TreeItem *item) const + int NetlistElementsTreeModel::getRepresentedIdOfItem(NetlistElementsTreeitem *item) const { return item->getAdditionalData(keyRepresentedID).toInt(); } void NetlistElementsTreeModel::gateNameChanged(Gate *g) { - for(TreeItem* gateItem : mGateToTreeitems.values(g)) + for(BaseTreeItem* gateItem : mGateToTreeitems.values(g)) { - gateItem->setDataAtIndex(sNameColumn, QString::fromStdString(g->get_name())); + QVariant data = QVariant(QString::fromStdString(g->get_name())); + gateItem->setDataAtIndex(sNameColumn, data); QModelIndex inx0 = getIndexFromItem(gateItem); QModelIndex inx1 = createIndex(inx0.row(), sNameColumn, inx0.internalPointer()); Q_EMIT dataChanged(inx0, inx1); @@ -160,8 +220,8 @@ namespace hal void NetlistElementsTreeModel::gateRemoved(Gate *g) { - QList items = mGateToTreeitems.values(g); - for(TreeItem* gateItem : items) + QList items = mGateToTreeitems.values(g); + for(NetlistElementsTreeitem* gateItem : items) { beginRemoveRows(parent(getIndexFromItem(gateItem)), gateItem->getOwnRow(), gateItem->getOwnRow()); gateItem->getParent()->removeChild(gateItem); @@ -170,7 +230,8 @@ namespace hal if(mNetsDisplayed && ( (gateItem->getParent() == mRootItem && mCurrentlyDisplayingModule) || gateItem->getParent() != mRootItem)) { beginResetModel(); - updateInternalNetsOfModule(gateItem->getParent());//perhaps for all parents? go until the mRootItem node? + NetlistElementsTreeitem* neti = static_cast(gateItem->getParent()); + updateInternalNetsOfModule(neti);//perhaps for all parents? go until the mRootItem node? endResetModel(); } delete gateItem; @@ -179,9 +240,10 @@ namespace hal void NetlistElementsTreeModel::netNameChanged(Net *n) { - for(TreeItem* netItem : mNetToTreeitems.values(n)) + for(NetlistElementsTreeitem* netItem : mNetToTreeitems.values(n)) { - netItem->setDataAtIndex(sNameColumn, QString::fromStdString(n->get_name())); + QVariant data = QVariant(QString::fromStdString(n->get_name())); + netItem->setDataAtIndex(sNameColumn, data); QModelIndex inx0 = getIndexFromItem(netItem); QModelIndex inx1 = createIndex(inx0.row(), sNameColumn, inx0.internalPointer()); Q_EMIT dataChanged(inx0, inx1); @@ -190,8 +252,8 @@ namespace hal void NetlistElementsTreeModel::netRemoved(Net *n) { - QList items = mNetToTreeitems.values(n); - for(TreeItem* netItem : items) + QList items = mNetToTreeitems.values(n); + for(NetlistElementsTreeitem* netItem : items) { beginRemoveRows(parent(getIndexFromItem(netItem)), netItem->getOwnRow(), netItem->getOwnRow()); netItem->getParent()->removeChild(netItem); @@ -203,9 +265,10 @@ namespace hal void NetlistElementsTreeModel::moduleNameChanged(Module *m) { - for(TreeItem* modItem : mModuleToTreeitems.values(m)) + for(NetlistElementsTreeitem* modItem : mModuleToTreeitems.values(m)) { - modItem->setDataAtIndex(sNameColumn, QString::fromStdString(m->get_name())); + QVariant data = QVariant(QString::fromStdString(m->get_name())); + modItem->setDataAtIndex(sNameColumn, data); QModelIndex inx0 = getIndexFromItem(modItem); Q_EMIT dataChanged(inx0, createIndex(inx0.row(), sNameColumn, inx0.internalPointer())); } @@ -213,9 +276,10 @@ namespace hal void NetlistElementsTreeModel::moduleTypeChanged(Module *m) { - for(TreeItem* modItem : mModuleToTreeitems.values(m)) + for(NetlistElementsTreeitem* modItem : mModuleToTreeitems.values(m)) { - modItem->setDataAtIndex(sTypeColumn, QString::fromStdString(m->get_type())); + QVariant data = QVariant(QString::fromStdString(m->get_type())); + modItem->setDataAtIndex(sTypeColumn, data); QModelIndex inx0 = getIndexFromItem(modItem); Q_EMIT dataChanged(inx0, createIndex(inx0.row(), sTypeColumn, inx0.internalPointer())); } @@ -226,15 +290,15 @@ namespace hal //1. go through the actual TreeItems through a BFS and remove them from the maps //2. delete the associated module tree items (beginResetModel) Module* removedMod = gNetlist->get_module_by_id(removed_module); - QList tmpSubmodItems; // they already get removed in the BFS - for(TreeItem* removedSubmodItem : mModuleToTreeitems.values(removedMod)) + QList tmpSubmodItems; // they already get removed in the BFS + for(NetlistElementsTreeitem* removedSubmodItem : mModuleToTreeitems.values(removedMod)) { tmpSubmodItems.append(removedSubmodItem); - QQueue treeItemsQueue; + QQueue treeItemsQueue; treeItemsQueue.enqueue(removedSubmodItem); while(!treeItemsQueue.isEmpty()) { - TreeItem* currentItem = treeItemsQueue.dequeue(); + NetlistElementsTreeitem* currentItem = treeItemsQueue.dequeue(); int id = currentItem->getAdditionalData(keyRepresentedID).toUInt(); switch (getTypeOfItem(currentItem)) @@ -244,17 +308,21 @@ namespace hal case itemType::net: mNetToTreeitems.remove(gNetlist->get_net_by_id(id), currentItem); break; } - for(TreeItem* child : currentItem->getChildren()) - treeItemsQueue.enqueue(child); + for(BaseTreeItem* child : currentItem->getChildren()){ + NetlistElementsTreeitem* neti = static_cast(child); + treeItemsQueue.enqueue(neti); + } } } //after clearing the maps, delete the corresponding module items (propagates through all children) beginResetModel(); - for(TreeItem* removedSubItem : tmpSubmodItems) + for(NetlistElementsTreeitem* removedSubItem : tmpSubmodItems) { removedSubItem->getParent()->removeChild(removedSubItem); - if(mNetsDisplayed) - updateInternalNetsOfModule(removedSubItem->getParent()); + if(mNetsDisplayed) { + NetlistElementsTreeitem* neti = static_cast(removedSubItem->getParent()); + updateInternalNetsOfModule(neti); + } delete removedSubItem; } endResetModel(); @@ -274,14 +342,16 @@ namespace hal Gate* assignedGate = gNetlist->get_gate_by_id(assigned_gate); //helper lambda function to parametrize the moduleItem parent (not worth own named class function) - auto appendNewGateToModule = [this, assignedGate](TreeItem* modItem){ + auto appendNewGateToModule = [this, assignedGate](BaseTreeItem* modItem){ int indexToInsert = 0; - for(; indexToInsert < modItem->getChildCount(); indexToInsert++) - if(getTypeOfItem(modItem->getChild(indexToInsert)) != itemType::module) + for(; indexToInsert < modItem->getChildCount(); indexToInsert++) { + NetlistElementsTreeitem* neti = static_cast(modItem->getChild(indexToInsert)); + if(getTypeOfItem(neti) != itemType::module) break; + } - TreeItem* gateItem = new TreeItem(QList() << QString::fromStdString(assignedGate->get_name()) - << assignedGate->get_id() << QString::fromStdString(assignedGate->get_type()->get_name())); + NetlistElementsTreeitem* gateItem = new NetlistElementsTreeitem(QString::fromStdString(assignedGate->get_name()), + assignedGate->get_id(), QString::fromStdString(assignedGate->get_type()->get_name())); gateItem->setAdditionalData(keyItemType, QVariant::fromValue(itemType::gate)); gateItem->setAdditionalData(keyRepresentedID, assignedGate->get_id()); //beginInsertRows(getIndexFromItem(modItem), indexToInsert, indexToInsert); @@ -289,8 +359,10 @@ namespace hal modItem->insertChild(indexToInsert, gateItem); //endInsertRows(); mGateToTreeitems.insert(assignedGate, gateItem); - if(mNetsDisplayed) - updateInternalNetsOfModule(modItem); + if(mNetsDisplayed) { + NetlistElementsTreeitem* neti = static_cast(modItem); + updateInternalNetsOfModule(neti); + } endResetModel(); }; @@ -299,7 +371,7 @@ namespace hal appendNewGateToModule(mRootItem); //standard case in which you do the same as obove, but just go through each module item - for(TreeItem* modItem : mModuleToTreeitems.values(m)) + for(BaseTreeItem* modItem : mModuleToTreeitems.values(m)) appendNewGateToModule(modItem); } @@ -317,16 +389,18 @@ namespace hal beginResetModel(); Module* addedModule = gNetlist->get_module_by_id(added_module); - auto appendNewSubmodItem = [this, addedModule](TreeItem* parentModItem){ - TreeItem* addedSubmodItem = new TreeItem(QList() << QString::fromStdString(addedModule->get_name()) << addedModule->get_id() - << QString::fromStdString(addedModule->get_type())); + auto appendNewSubmodItem = [this, addedModule](BaseTreeItem* parentModItem){ + NetlistElementsTreeitem* addedSubmodItem = new NetlistElementsTreeitem(QString::fromStdString(addedModule->get_name()), + addedModule->get_id(), QString::fromStdString(addedModule->get_type())); moduleRecursive(addedModule, addedSubmodItem, mGatesDisplayed, mNetsDisplayed); addedSubmodItem->setAdditionalData(keyItemType, QVariant::fromValue(itemType::module)); addedSubmodItem->setAdditionalData(keyRepresentedID, addedModule->get_id()); parentModItem->insertChild(0, addedSubmodItem); mModuleToTreeitems.insert(addedModule, addedSubmodItem); - if(mNetsDisplayed) - updateInternalNetsOfModule(parentModItem); + if(mNetsDisplayed) { + NetlistElementsTreeitem* neti = static_cast(parentModItem); + updateInternalNetsOfModule(neti); + } }; //special case when a module is represented with setModule @@ -337,19 +411,19 @@ namespace hal } //standard case for all displayed things - for(TreeItem* parentModItem : mModuleToTreeitems.values(m)) + for(NetlistElementsTreeitem* parentModItem : mModuleToTreeitems.values(m)) appendNewSubmodItem(parentModItem); endResetModel(); } - void NetlistElementsTreeModel::moduleRecursive(Module* mod, TreeItem* modItem, bool showGates, bool showNets) + void NetlistElementsTreeModel::moduleRecursive(Module* mod, NetlistElementsTreeitem* modItem, bool showGates, bool showNets) { - TreeItem* subModItem = nullptr; + NetlistElementsTreeitem* subModItem = nullptr; for(Module* subMod : mod->get_submodules()) { - subModItem = new TreeItem(QList() << QString::fromStdString(subMod->get_name()) - << subMod->get_id() << QString::fromStdString(subMod->get_type())); + subModItem = new NetlistElementsTreeitem(QString::fromStdString(subMod->get_name()), + subMod->get_id(), QString::fromStdString(subMod->get_type())); moduleRecursive(subMod, subModItem, showGates); subModItem->setAdditionalData(keyItemType, QVariant::fromValue(itemType::module)); subModItem->setAdditionalData(keyRepresentedID, subMod->get_id()); @@ -360,8 +434,8 @@ namespace hal { for(auto gate : mod->get_gates()) { - TreeItem* gateItem = new TreeItem(QList() << QString::fromStdString(gate->get_name()) - << gate->get_id() << QString::fromStdString(gate->get_type()->get_name())); + NetlistElementsTreeitem* gateItem = new NetlistElementsTreeitem(QString::fromStdString(gate->get_name()), + gate->get_id(), QString::fromStdString(gate->get_type()->get_name())); gateItem->setAdditionalData(keyItemType, QVariant::fromValue(itemType::gate)); gateItem->setAdditionalData(keyRepresentedID, gate->get_id()); modItem->appendChild(gateItem); @@ -372,8 +446,8 @@ namespace hal { for(auto net : mod->get_internal_nets()) { - TreeItem* netItem = new TreeItem(QList() << QString::fromStdString(net->get_name()) - << net->get_id() << ""); + NetlistElementsTreeitem* netItem = new NetlistElementsTreeitem(QString::fromStdString(net->get_name()), + net->get_id(), ""); netItem->setAdditionalData(keyItemType, QVariant::fromValue(itemType::net)); netItem->setAdditionalData(keyRepresentedID, net->get_id()); modItem->appendChild(netItem); @@ -382,7 +456,7 @@ namespace hal } } - QIcon NetlistElementsTreeModel::getIconFromItem(TreeItem *item) const + QIcon NetlistElementsTreeModel::getIconFromItem(NetlistElementsTreeitem *item) const { if(!item) return QIcon(); @@ -399,21 +473,23 @@ namespace hal } } - void NetlistElementsTreeModel::updateInternalNetsOfModule(TreeItem *moduleItem) + void NetlistElementsTreeModel::updateInternalNetsOfModule(NetlistElementsTreeitem *moduleItem) { - int moduleId = (moduleItem == mRootItem) ? mModId : moduleItem->getAdditionalData(keyRepresentedID).toInt(); + BaseTreeItem* moduleItemBase = static_cast(moduleItem); + BaseTreeItem* mRootBase = static_cast(mRootItem); + int moduleId = (moduleItemBase == mRootBase) ? mModId : moduleItem->getAdditionalData(keyRepresentedID).toInt(); Module* mod = gNetlist->get_module_by_id(moduleId); //remove and delte the last child of the module-item until no net items are left - while(moduleItem->getChildCount() > 0 && getTypeOfItem(moduleItem->getChild(moduleItem->getChildCount()-1)) == itemType::net) + while(moduleItem->getChildCount() > 0 && getTypeOfItem(static_cast(moduleItem->getChild(moduleItem->getChildCount()-1))) == itemType::net) { - TreeItem* lastNetItem = moduleItem->removeChildAtPos(moduleItem->getChildCount()-1); + NetlistElementsTreeitem* lastNetItem = static_cast(moduleItem->removeChildAtPos(moduleItem->getChildCount()-1)); mNetToTreeitems.remove(gNetlist->get_net_by_id(lastNetItem->getAdditionalData(keyRepresentedID).toUInt()), lastNetItem); delete lastNetItem; } //append (potentionally) new internal nets for(Net* n : mod->get_internal_nets()) { - TreeItem* netItem = new TreeItem(QList() << QString::fromStdString(n->get_name()) << n->get_id() << ""); + NetlistElementsTreeitem* netItem = new NetlistElementsTreeitem(QString::fromStdString(n->get_name()),n->get_id(), ""); //netItem->setAdditionalData(keyItemType, itemType::net); netItem->setAdditionalData(keyItemType, QVariant::fromValue(itemType::net)); netItem->setAdditionalData(keyRepresentedID, n->get_id()); @@ -422,4 +498,5 @@ namespace hal } } + } diff --git a/plugins/gui/src/selection_details_widget/module_details_widget/port_tree_model.cpp b/plugins/gui/src/selection_details_widget/module_details_widget/port_tree_model.cpp index 73f65c1bd8f..ea11e74c5a5 100644 --- a/plugins/gui/src/selection_details_widget/module_details_widget/port_tree_model.cpp +++ b/plugins/gui/src/selection_details_widget/module_details_widget/port_tree_model.cpp @@ -1,6 +1,6 @@ #include "gui/selection_details_widget/module_details_widget/port_tree_model.h" -#include "gui/basic_tree_model/tree_item.h" +#include "gui/basic_tree_model/base_tree_item.h" #include "gui/gui_globals.h" #include "gui/input_dialog/input_dialog.h" #include "gui/user_action/action_add_items_to_object.h" @@ -19,12 +19,76 @@ namespace hal { + PortTreeItem::PortTreeItem(QString pinName, QString pinDirection, QString pinTypee, QString netName) + : mPinName(pinName), mPinDirection(pinDirection), mPinType(pinTypee), mNetName(netName) + {;} + + QVariant PortTreeItem::getData(int index) const + { + switch (index) + { + case 0: { + QVariant qvPinName = QVariant(mPinName); + return qvPinName; + break;} + case 1: { + QVariant qvPinDirection = QVariant(mPinDirection); + return qvPinDirection; + break;} + case 2: { + QVariant qvPinType = QVariant(mPinType); + return qvPinType; + break;} + case 3: { + QVariant qvNetName = QVariant(mNetName); + return qvNetName; + break;} + } + } + + void PortTreeItem::setData(QList data) + { + mPinName = data[0].toString(); + mPinDirection = data[1].toString(); + mPinType = data[2].toString(); + mNetName = data[3].toString(); + } + + void PortTreeItem::setDataAtIndex(int index, QVariant &data) + { + switch (index) + { + case 0: { + mPinName = data.toString(); + break;} + case 1: { + mPinDirection = data.toString(); + break;} + case 2: { + mPinType = data.toString(); + break;} + case 3: { + mNetName = data.toString(); + break;} + } + } + + void PortTreeItem::appendData(QVariant data) + { + + } + + int PortTreeItem::getColumnCount() const + { + return 4; + } + ModulePinsTreeModel::ModulePinsTreeModel(QObject* parent) : BaseTreeModel(parent), mIgnoreEventsFlag(false) { - setHeaderLabels(QList() << "Name" - << "Direction" - << "Type" - << "Connected Net"); + setHeaderLabels(QStringList() << "Name" + << "Direction" + << "Type" + << "Connected Net"); setModule(gNetlist->get_module_by_id(1)); //connections @@ -79,7 +143,7 @@ namespace hal return new QMimeData(); QMimeData* data = new QMimeData(); - auto item = getItemFromIndex(indexes.at(0)); + auto item = static_cast(getItemFromIndex(indexes.at(0))); QByteArray encodedData; QDataStream stream(&encodedData, QIODevice::WriteOnly); QString type = getTypeOfItem(item) == itemType::pin ? "pin" : "group"; @@ -99,7 +163,7 @@ namespace hal QDataStream dataStream(&encItem, QIODevice::ReadOnly); dataStream >> type >> id; - auto droppedItem = (type == "group") ? mIdToGroupItem.value(id) : mIdToPinItem.value(id); + auto droppedItem = (type == "group") ? static_cast(mIdToGroupItem.value(id)) : static_cast(mIdToPinItem.value(id)); //auto droppedParentItem = droppedItem->getParent(); auto parentItem = getItemFromIndex(parent); @@ -280,7 +344,7 @@ namespace hal auto encItem = data->data("pintreemodel/item"); QDataStream dataStream(&encItem, QIODevice::ReadOnly); dataStream >> type >> id; - auto parentItem = getItemFromIndex(parent); + auto parentItem = static_cast(getItemFromIndex(parent)); qDebug() << "type: " << type << ", id" << id << ", row: " << row; // construct a "drop-matrix" here, but only 4(5) things are NOT allowed (so check for these): @@ -349,16 +413,16 @@ namespace hal auto pinGroupDirection = QString::fromStdString(enum_to_string((pinGroup->get_direction()))); auto pinGroupType = QString::fromStdString(enum_to_string(pinGroup->get_type())); - TreeItem* pinGroupItem = new TreeItem(QList() << pinGroupName << pinGroupDirection << pinGroupType << ""); + PortTreeItem* pinGroupItem = new PortTreeItem(pinGroupName, pinGroupDirection, pinGroupType, ""); pinGroupItem->setAdditionalData(keyType, QVariant::fromValue(itemType::group)); // port multi bit pinGroupItem->setAdditionalData(keyId, pinGroup->get_id()); mIdToGroupItem.insert(pinGroup->get_id(), pinGroupItem); for(ModulePin* pin : pinGroup->get_pins()) { - TreeItem* pinItem = new TreeItem(QList() << QString::fromStdString(pin->get_name()) - << QString::fromStdString(enum_to_string(pin->get_direction())) - << QString::fromStdString(enum_to_string(pin->get_type())) - << QString::fromStdString(pin->get_net()->get_name())); + PortTreeItem* pinItem = new PortTreeItem(QString::fromStdString(pin->get_name()), + QString::fromStdString(enum_to_string(pin->get_direction())), + QString::fromStdString(enum_to_string(pin->get_type())), + QString::fromStdString(pin->get_net()->get_name())); pinItem->setAdditionalData(keyType, QVariant::fromValue(itemType::pin)); pinItem->setAdditionalData(keyId, pin->get_id()); pinGroupItem->appendChild(pinItem); @@ -423,7 +487,7 @@ namespace hal Q_EMIT numberOfPortsChanged(m->get_pins().size()); } - Net* ModulePinsTreeModel::getNetFromItem(TreeItem* item) + Net* ModulePinsTreeModel::getNetFromItem(PortTreeItem* item) { if (mModuleId == -1) //no current module = no represented net return nullptr; @@ -450,12 +514,12 @@ namespace hal return mModuleId; } - ModulePinsTreeModel::itemType ModulePinsTreeModel::getTypeOfItem(TreeItem* item) const + ModulePinsTreeModel::itemType ModulePinsTreeModel::getTypeOfItem(PortTreeItem* item) const { return item->getAdditionalData(keyType).value(); } - int ModulePinsTreeModel::getIdOfItem(TreeItem* item) const + int ModulePinsTreeModel::getIdOfItem(BaseTreeItem* item) const { return item->getAdditionalData(keyId).toInt(); } @@ -469,7 +533,7 @@ namespace hal } } - void ModulePinsTreeModel::dndGroupOnGroup(TreeItem *droppedGroup, TreeItem *onDroppedGroup) + void ModulePinsTreeModel::dndGroupOnGroup(BaseTreeItem *droppedGroup, BaseTreeItem *onDroppedGroup) { // SPECIFY: 1) create completely new group, all pins in that, delete old 2 groups // 2) just add all pins from dropped group to "ondroppedgroup", then rename? @@ -498,7 +562,7 @@ namespace hal } - void ModulePinsTreeModel::dndGroupBetweenGroup(TreeItem *droppedGroup, int row) + void ModulePinsTreeModel::dndGroupBetweenGroup(PortTreeItem *droppedGroup, int row) { mIgnoreEventsFlag = true; int ownRow = droppedGroup->getOwnRow(); @@ -517,7 +581,7 @@ namespace hal mIgnoreEventsFlag = false; } - void ModulePinsTreeModel::dndPinOnGroup(TreeItem *droppedPin, TreeItem *onDroppedGroup) + void ModulePinsTreeModel::dndPinOnGroup(PortTreeItem *droppedPin, BaseTreeItem *onDroppedGroup) { mIgnoreEventsFlag = true; QSet e; @@ -529,14 +593,14 @@ namespace hal removeItem(droppedPin); insertItem(droppedPin, onDroppedGroup, onDroppedGroup->getChildCount()); if(!(oldParent->getChildCount())){ - removeItem(oldParent); + removeItem(static_cast(oldParent)); delete oldParent; } //setModule(mModule); mIgnoreEventsFlag = false; } - void ModulePinsTreeModel::dndPinBetweenPin(TreeItem *droppedPin, TreeItem *onDroppedParent, int row) + void ModulePinsTreeModel::dndPinBetweenPin(PortTreeItem *droppedPin, BaseTreeItem *onDroppedParent, int row) { mIgnoreEventsFlag = true; int desiredIdx = row; @@ -573,14 +637,14 @@ namespace hal removeItem(droppedPin); insertItem(droppedPin, onDroppedParent, desiredIdx); if(!(oldParent->getChildCount())){ - removeItem(oldParent); + removeItem(static_cast(oldParent)); delete oldParent; } //setModule(mModule); mIgnoreEventsFlag = false; } - void ModulePinsTreeModel::dndPinBetweenGroup(TreeItem *droppedPin, int row) + void ModulePinsTreeModel::dndPinBetweenGroup(PortTreeItem *droppedPin, int row) { // row is needed for when groups can change its order within the module Q_UNUSED(row) @@ -600,7 +664,7 @@ namespace hal auto pinGroupDirection = QString::fromStdString(enum_to_string((newGroup->get_direction()))); auto pinGroupType = QString::fromStdString(enum_to_string(newGroup->get_type())); - TreeItem* pinGroupItem = new TreeItem(QList() << pinGroupName << pinGroupDirection << pinGroupType << ""); + PortTreeItem* pinGroupItem = new PortTreeItem(pinGroupName, pinGroupDirection, pinGroupType, ""); pinGroupItem->setAdditionalData(keyType, QVariant::fromValue(itemType::group)); pinGroupItem->setAdditionalData(keyId, newGroup->get_id()); @@ -618,7 +682,7 @@ namespace hal mIgnoreEventsFlag = false; } - void ModulePinsTreeModel::insertItem(TreeItem* item, TreeItem* parent, int index) + void ModulePinsTreeModel::insertItem(PortTreeItem* item, BaseTreeItem* parent, int index) { // fun fact: if an item is inserted above an item that is expanded, the tree collapses all indeces beginInsertRows(getIndexFromItem(parent), index, index); @@ -628,7 +692,7 @@ namespace hal getTypeOfItem(item) == itemType::pin ? mIdToPinItem.insert(getIdOfItem(item), item) : mIdToGroupItem.insert(getIdOfItem(item), item); //mIdToPinItem.insert(getIdOfItem(item), item); } - void ModulePinsTreeModel::removeItem(TreeItem* item) + void ModulePinsTreeModel::removeItem(PortTreeItem* item) { beginRemoveRows(parent(getIndexFromItem(item)), item->getOwnRow(), item->getOwnRow()); item->getParent()->removeChild(item); @@ -639,4 +703,7 @@ namespace hal //mIdToPinItem.remove(getIdOfItem(item)); //delete item; } + + + } // namespace hal diff --git a/plugins/gui/src/selection_details_widget/selection_details_icon_provider.cpp b/plugins/gui/src/selection_details_widget/selection_details_icon_provider.cpp index a3bd1fddd1b..f6748dd9c44 100644 --- a/plugins/gui/src/selection_details_widget/selection_details_icon_provider.cpp +++ b/plugins/gui/src/selection_details_widget/selection_details_icon_provider.cpp @@ -3,6 +3,8 @@ #include "gui/gui_globals.h" #include "gui/main_window/main_window.h" #include "gui/settings/settings_items/settings_item_dropdown.h" +#include "gui/module_model/module_model.h" +#include "gui/module_model/module_color_manager.h" #include #include @@ -30,6 +32,7 @@ namespace hal SelectionDetailsIconProvider* SelectionDetailsIconProvider::instance() { + Q_ASSERT(gNetlistRelay); // make sure it does not get called before event relay is installed if (!inst) inst = new SelectionDetailsIconProvider(); return inst; } @@ -38,9 +41,19 @@ namespace hal : QObject(parent) { connect(MainWindow::sSettingStyle, &SettingsItemDropdown::intChanged,this,&SelectionDetailsIconProvider::loadIcons); + connect(gNetlistRelay->getModuleColorManager(),&ModuleColorManager::moduleColorChanged,this,&SelectionDetailsIconProvider::handleModuleColorChanged); loadIcons(MainWindow::sSettingStyle->value().toInt()); } + void SelectionDetailsIconProvider::handleModuleColorChanged(u32 id) + { + auto it = mModuleIcons.find(id); + if (it == mModuleIcons.end()) return; + delete it.value(); + QColor col = gNetlistRelay->getModuleColor(id); + mModuleIcons[id] = new QIcon(gui_utility::getStyledSvgIcon("all->" + col.name(QColor::HexRgb), ":/icons/ne_module")); + } + void SelectionDetailsIconProvider::loadIcons(int istyle) { MainWindow::StyleSheetOption theme = static_cast(istyle); @@ -75,7 +88,7 @@ namespace hal const QIcon* SelectionDetailsIconProvider::getIcon(IconCategory catg, u32 itemId) { Gate* g = nullptr; - Module* m = nullptr; + QColor col; switch (catg) { @@ -92,18 +105,15 @@ namespace hal } break; case ModuleIcon: - m = gNetlist->get_module_by_id(itemId); - if (m) + col = gNetlistRelay->getModuleColor(itemId); + if (col.isValid()) { - QColor col = gNetlistRelay->getModuleColor(itemId); - if (col.isValid()) - { - const QIcon* moduleColorIcon = mModuleIcons.value(m,nullptr); - if (moduleColorIcon) return moduleColorIcon; - moduleColorIcon = new QIcon(gui_utility::getStyledSvgIcon("all->" + col.name(QColor::HexRgb), ":/icons/ne_module")); - mModuleIcons.insert(m, moduleColorIcon); - return moduleColorIcon; - } + auto it = mModuleIcons.find(itemId); + if (it != mModuleIcons.end()) + return it.value(); + QIcon* newIcon = new QIcon(gui_utility::getStyledSvgIcon("all->" + col.name(QColor::HexRgb), ":/icons/ne_module")); + mModuleIcons[itemId] = newIcon; + return newIcon; } break; default: diff --git a/plugins/gui/src/selection_details_widget/tree_navigation/selection_tree_view.cpp b/plugins/gui/src/selection_details_widget/tree_navigation/selection_tree_view.cpp index cfc1959ca84..4eeeaec0afe 100644 --- a/plugins/gui/src/selection_details_widget/tree_navigation/selection_tree_view.cpp +++ b/plugins/gui/src/selection_details_widget/tree_navigation/selection_tree_view.cpp @@ -33,6 +33,7 @@ namespace hal connect(this, &SelectionTreeView::itemDoubleClicked, this, &SelectionTreeView::handleTreeViewItemFocusClicked); connect(this, &SelectionTreeView::focusItemClicked, this, &SelectionTreeView::handleTreeViewItemFocusClicked); + connect(gNetlistRelay->getModuleColorManager(),&ModuleColorManager::moduleColorChanged,this,&SelectionTreeView::handleModuleColorChanged); } void SelectionTreeView::setDefaultColumnWidth() @@ -78,6 +79,12 @@ namespace hal return static_cast(modelIndex.internalPointer()); } + void SelectionTreeView::handleModuleColorChanged(u32 id) + { + Q_UNUSED(id); + update(); + } + void SelectionTreeView::handleCustomContextMenuRequested(const QPoint& point) { QModelIndex index = indexAt(point); diff --git a/plugins/gui/src/user_action/action_delete_object.cpp b/plugins/gui/src/user_action/action_delete_object.cpp index b26e214e8d5..c1ddee64cb1 100644 --- a/plugins/gui/src/user_action/action_delete_object.cpp +++ b/plugins/gui/src/user_action/action_delete_object.cpp @@ -5,6 +5,7 @@ #include "gui/grouping/grouping_table_model.h" #include "gui/gui_globals.h" #include "gui/module_model/module_model.h" +#include "gui/module_model/module_color_manager.h" #include "gui/user_action/action_add_items_to_object.h" #include "gui/user_action/action_create_object.h" #include "gui/user_action/action_set_object_color.h" @@ -74,7 +75,7 @@ namespace hal actCreate->setParentId(mod->get_parent_module()->get_id()); act->addAction(actCreate); act->addAction(new ActionSetObjectType(QString::fromStdString(mod->get_type()))); - act->addAction(new ActionSetObjectColor(gNetlistRelay->getModuleModel()->moduleColor(mod->get_id()))); + act->addAction(new ActionSetObjectColor(gNetlistRelay->getModuleColorManager()->moduleColor(mod->get_id()))); QSet mods, gats; for (Gate* g : mod->get_gates()) gats.insert(g->get_id()); diff --git a/plugins/gui/src/user_action/action_set_object_color.cpp b/plugins/gui/src/user_action/action_set_object_color.cpp index f6818a66a6b..20b173a4ba3 100644 --- a/plugins/gui/src/user_action/action_set_object_color.cpp +++ b/plugins/gui/src/user_action/action_set_object_color.cpp @@ -1,7 +1,7 @@ #include "gui/user_action/action_set_object_color.h" #include "gui/grouping/grouping_manager_widget.h" #include "gui/grouping/grouping_table_model.h" -#include "gui/module_model/module_model.h" +#include "gui/module_model/module_color_manager.h" #include "gui/gui_globals.h" namespace hal @@ -47,11 +47,10 @@ namespace hal switch (mObject.type()) { case UserActionObjectType::Module: - oldColor = gNetlistRelay->getModuleModel()->setModuleColor(mObject.id(),mColor); - gNetlistRelay->getModuleModel()->updateModule(mObject.id()); + oldColor = gNetlistRelay->getModuleColorManager()->setModuleColor(mObject.id(),mColor); - // Since color is our Overlay over the netlist data, no event is - // automatically fired. We need to take care of that ourselves here. + // Set module color will fire moduleColorChanged event. + // However, gGraphContextManager is not in the receiver list and has to be updated manually gGraphContextManager->handleModuleColorChanged(gNetlist->get_module_by_id(mObject.id())); break; case UserActionObjectType::Grouping: diff --git a/src/python_bindings/bindings/netlist.cpp b/src/python_bindings/bindings/netlist.cpp index 012f6de1255..3b30eb2b882 100644 --- a/src/python_bindings/bindings/netlist.cpp +++ b/src/python_bindings/bindings/netlist.cpp @@ -517,6 +517,7 @@ namespace hal py_netlist.def("delete_module", &Netlist::delete_module, py::arg("module"), R"( Remove a module from the netlist. + Submodules, gates and nets under this module will be moved to the parent of this module. :param module: The module. :type module: hal_py.Module