diff --git a/CHANGELOG.md b/CHANGELOG.md
index 459c0cf9721..384569c1762 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file.
* refactored module widget
* added option to show gate content for each module
* added option to show interior nets for each module
+ * added `Isolate in new view` feature for nets
* added button to expand or collapse all tree items
* added delete module action and shortcut
* added entries for context menu
@@ -18,7 +19,14 @@ All notable changes to this project will be documented in this file.
* boosted performance by using classes with faster memory access
* removed layouter code used prior to version 3.1.0 - thus removing the setting option to use that code
* added setting option to dump junction layout input data for experts to debug in case of layout errors
+* module pins
+ * added qualifier for `pin_changed` core events telling receiver details about the recent modification
+ * added event scope and stacking classes so that `pin_changed` events can be collected and prioritized
+ * added specific GUI handler for every `pin_changed` event thus replacing the reload-entire-pingroup-tree policy
+ * added class `ActionPingroup` so that UNDO function works for all pin / pin group actions issued from GUI
* miscellaneous
+ * added INIT field declaration to FF-gate-types in example library
+ * added drag'n drop feature allowing to move several nodes in graph view at same time
* added functions to Python GUI API to create, modifiy and delete views
* added GUI PluginParameter type `ComboBox` for parameters that can be requested from plugin
* added GUI PluginParameter types `Module` and `Gated` for parameters that can be requested from plugin
diff --git a/README.md b/README.md
index 428f156f796..536a7b20a78 100644
--- a/README.md
+++ b/README.md
@@ -55,7 +55,7 @@ This repository contains a selection of curated plugins:
A comprehensive documentation of HAL's features from a user perspective is available in our [Wiki](https://github.com/emsec/hal/wiki). In addition, we provide a full [C++ API](https://emsec.github.io/hal/doc/) and [Python API](https://emsec.github.io/hal/pydoc/) documentation.
## Slack, Contact and Support
-For all kinds of inquiries, please contact us using our dedicated e-mail address: [hal@csp.mpg.de](mailto:hal@csp.mpg.de). To receive an invite to our dedicated hal-support Slack workspace, please write us an e-mail as well.
+For all kinds of inquiries, please contact us using our dedicated e-mail address: [hal@mpi-sp.org](mailto:hal@mpi-sp.org).
# Build Instructions
diff --git a/cmake/detect_dependencies.cmake b/cmake/detect_dependencies.cmake
index 6ee82c749e4..1c1c612f188 100644
--- a/cmake/detect_dependencies.cmake
+++ b/cmake/detect_dependencies.cmake
@@ -27,11 +27,19 @@ find_package(Sanitizers REQUIRED)
# ###############################
# #### Bitwuzla
# ###############################
-find_package(Bitwuzla)
+pkg_check_modules(BITWUZLA bitwuzla)
+
+if(BITWUZLA_FOUND)
+ message(STATUS "Found BITWUZLA")
+ message(STATUS " BITWUZLA_LIBRARIES: ${BITWUZLA_LIBRARIES}")
+ message(STATUS " BITWUZLA_LINK_LIBRARIES: ${BITWUZLA_LINK_LIBRARIES}")
+ message(STATUS " BITWUZLA_INCLUDE_DIRS: ${BITWUZLA_INCLUDE_DIRS}")
+else()
+ set(BITWUZLA_LIBRARY "")
+ set(BITWUZLA_INCLUDE_DIRS "")
+ message(STATUS "Bitwuzla not found, but this is optional...")
+endif(BITWUZLA_FOUND)
-if(Bitwuzla_FOUND)
- set(BITWUZLA_LIBRARY Bitwuzla::bitwuzla)
-endif()
# ###############################
# #### OpenMP
@@ -109,24 +117,32 @@ endif()
# ###############################
find_package(Filesystem REQUIRED Final Experimental)
+
# ###############################
# #### RapidJSON
# ###############################
find_package(RapidJSON REQUIRED)
-message(STATUS "Found rapidjson ${RAPIDJSON_INCLUDEDIR}")
-
if(RapidJSON_FOUND AND NOT TARGET RapidJSON::RapidJSON)
if(NOT RAPIDJSON_INCLUDEDIR)
set(RAPIDJSON_INCLUDEDIR ${RAPIDJSON_INCLUDE_DIRS})
endif()
+ # fix for macOS if most recent version
+ if(NOT RAPIDJSON_INCLUDEDIR)
+ set(RAPIDJSON_INCLUDEDIR ${RapidJSON_INCLUDE_DIRS})
+ endif()
+
+
add_library(RapidJSON::RapidJSON INTERFACE IMPORTED)
set_target_properties(RapidJSON::RapidJSON PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${RAPIDJSON_INCLUDEDIR}"
)
- message(STATUS "Set rapidjson successully: ${RAPIDJSON_INCLUDEDIR}")
+ message(STATUS "Found rapidjson ${RAPIDJSON_INCLUDEDIR}")
+ message(STATUS "Set rapidjson path successully: ${RAPIDJSON_INCLUDEDIR}")
endif()
+
+
# ###############################
# #### pybind11
# ###############################
@@ -243,7 +259,7 @@ endif(Z3_FOUND)
# ###############################
# #### igraph
# ###############################
-set (IGRAPH_SUBDIR "${CMAKE_SOURCE_DIR}/deps/igraph-0.9.10")
+set(IGRAPH_SUBDIR "${CMAKE_SOURCE_DIR}/deps/igraph-0.9.10")
add_subdirectory(${IGRAPH_SUBDIR})
get_directory_property(IGRAPH_INCLUDES DIRECTORY ${IGRAPH_SUBDIR} DEFINITION IGRAPH_INCLUDES)
-get_directory_property(IGRAPH_LIB DIRECTORY ${IGRAPH_SUBDIR} DEFINITION IGRAPH_LIB)
+get_directory_property(IGRAPH_LIB DIRECTORY ${IGRAPH_SUBDIR} DEFINITION IGRAPH_LIB)
diff --git a/include/hal_core/netlist/event_system/event_handler.h b/include/hal_core/netlist/event_system/event_handler.h
index 06c6b13372c..58570fdd81d 100644
--- a/include/hal_core/netlist/event_system/event_handler.h
+++ b/include/hal_core/netlist/event_system/event_handler.h
@@ -114,7 +114,7 @@ namespace hal
gates_remove_begin, ///< associated_data = number of gates to remove
gates_remove_end, ///< associated_data = number of removed gates
gate_removed, ///< associated_data = id of removed gate
- pin_changed, ///< no associated_data
+ pin_changed, ///< associated_data = [4LSB: type of action] [28HSB: id of pin group or pin]
};
};
diff --git a/include/hal_core/netlist/gate_library/enums/pin_event.h b/include/hal_core/netlist/gate_library/enums/pin_event.h
new file mode 100644
index 00000000000..7f4b6daf3c8
--- /dev/null
+++ b/include/hal_core/netlist/gate_library/enums/pin_event.h
@@ -0,0 +1,166 @@
+// 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/utilities/enums.h"
+#include "hal_core/defines.h"
+#include
+#include
+
+namespace hal
+{
+ /**
+ * Spezifies the pin_changed event type
+ *
+ * The order of events in enum class defines the order in which events are handled.
+ *
+ */
+ enum class PinEvent
+ {
+ unknown,
+ GroupCreate, /// new pin group created
+ GroupRename, /// pin group renamed
+ GroupTypeChange, /// changed PinType attribute of group (like data)
+ GroupDirChange, /// changed PinDirection attribute of group (like input)
+ GroupReorder, /// moved group to a new position within containing module
+ PinCreate, /// new pin created
+ PinAssignToGroup, /// pin assigned to new group
+ PinRename, /// pin renamed
+ PinTypeChange, /// changed PinType attribute of pin (like data)
+ PinDirChange, /// changed PinDirection attribute of pin (like input)
+ PinReorder, /// moved pin to a new position within containing group
+ PinDelete, /// pin deleted
+ GroupDelete /// group deleted
+ };
+
+ template<>
+ std::map EnumStrings::data;
+
+ class Module;
+
+ /**
+ * Wrapper class for core pin_changed events.
+ *
+ * Events can be send immediately or stacked and send at according to their priority.
+ */
+ class PinChangedEvent
+ {
+ friend bool pin_event_order(const PinChangedEvent& a, const PinChangedEvent& b);
+ friend class PinChangedEventScope;
+
+ /**
+ * Subclass for event stack.
+ */
+ class EventStack : public std::vector
+ {
+ public:
+ /**
+ * Scope count indicates the nesting depth of event-throwing subroutines.
+ * Only the top level (m_count=0) is allowed to send the events from stack.
+ */
+ int m_count;
+
+ /**
+ * Construct empty stack
+ */
+ EventStack() : m_count(0) {;}
+
+ /**
+ * Attempts to send events, typically at the end of a pin-changing subroutine.
+ * Events will only be send if m_count is zero.
+ */
+ void send_events(Module* m);
+ };
+
+ static std::unordered_map s_event_stack;
+
+ Module* m_module;
+ PinEvent m_event;
+ u32 m_id;
+
+ public:
+ /**
+ * PinChangedEvent class for single event
+ * @param m - The module comprising pins and pin groups
+ * @param pev - The pin event enum
+ * @param id - pin or pin group ID
+ */
+ PinChangedEvent(Module* m, PinEvent pev, u32 id);
+
+ /**
+ * Returns the module for which pins or pin groups have been changed
+ * @return The module comprising pins and pin groups
+ */
+ Module* get_module() const;
+
+ /**
+ * Return bitwise binary encoded PinEvent and ID
+ * 4LSB = The pin event enum as 4 bit int
+ * 28HSB = The ID as 28 bit int
+ * @return The bitcode according to scheme above
+ */
+ u32 associated_data();
+
+ /**
+ * Attempts to send event.
+ * If this routine or any calling routine wants to collect events the event gets written on stack instead.
+ */
+ void send();
+ };
+
+ /**
+ * By creating an instance of this class a new scope gets created thus collecting events.
+ */
+ class PinChangedEventScope
+ {
+ Module* m_module;
+ public:
+
+ /**
+ * Constructor for scope instance incrementing scope count
+ * @param m The module comprising pins and pin groups
+ */
+ PinChangedEventScope(Module* m);
+
+ /**
+ * Destructor for scope instance decrementing scope count
+ */
+ ~PinChangedEventScope();
+
+ /**
+ * Attempts to send all stacked events. Will do nothing if not issued from top-level scope.
+ */
+ void send_events();
+ };
+
+ /**
+ * Function used by sort algorithm to organize events according to their priority.
+ * @param a - Pin changed event A
+ * @param b - Pin changed event B
+ * @return true if A should be handled before B, false otherwise.
+ */
+ bool pin_event_order(const PinChangedEvent& a, const PinChangedEvent& b);
+}
diff --git a/include/hal_core/netlist/gate_library/enums/pin_type.h b/include/hal_core/netlist/gate_library/enums/pin_type.h
index 295e7d0acbc..b8a35ef1a03 100644
--- a/include/hal_core/netlist/gate_library/enums/pin_type.h
+++ b/include/hal_core/netlist/gate_library/enums/pin_type.h
@@ -54,4 +54,5 @@ namespace hal
template<>
std::map EnumStrings::data;
-} // namespace hal
\ No newline at end of file
+
+} // namespace hal
diff --git a/include/hal_core/netlist/gate_library/gate_type.h b/include/hal_core/netlist/gate_library/gate_type.h
index 34399a46661..17fcdf81893 100644
--- a/include/hal_core/netlist/gate_library/gate_type.h
+++ b/include/hal_core/netlist/gate_library/gate_type.h
@@ -354,9 +354,9 @@ namespace hal
* Delete the given pin group.
*
* @param[in] pin_group - The pin group to be deleted.
- * @returns Ok on success, an error message otherwise.
+ * @returns true on success, false otherwise.
*/
- Result delete_pin_group(PinGroup* pin_group);
+ bool delete_pin_group(PinGroup* pin_group);
/**
* Assign a pin to a pin group.
@@ -469,6 +469,6 @@ namespace hal
GateType& operator=(const GateType&) = delete;
Result*> create_pin_group_internal(const u32 id, const std::string& name, PinDirection direction, PinType type, bool ascending, u32 start_index);
- Result delete_pin_group_internal(PinGroup* pin_group);
+ bool delete_pin_group_internal(PinGroup* pin_group);
};
} // namespace hal
diff --git a/include/hal_core/netlist/module.h b/include/hal_core/netlist/module.h
index a785ef1eacf..0cccca0441e 100644
--- a/include/hal_core/netlist/module.h
+++ b/include/hal_core/netlist/module.h
@@ -30,6 +30,7 @@
#include "hal_core/netlist/event_system/event_handler.h"
#include "hal_core/netlist/gate_library/enums/pin_direction.h"
#include "hal_core/netlist/gate_library/enums/pin_type.h"
+#include "hal_core/netlist/gate_library/enums/pin_event.h"
#include "hal_core/netlist/gate_library/gate_library.h"
#include "hal_core/netlist/pins/module_pin.h"
#include "hal_core/netlist/pins/pin_group.h"
@@ -526,9 +527,9 @@ namespace hal
* Delete the given pin group.
*
* @param[in] pin_group - The pin group to be deleted.
- * @returns Ok on success, an error message otherwise.
+ * @returns true on success, false otherwise.
*/
- Result delete_pin_group(PinGroup* pin_group);
+ bool delete_pin_group(PinGroup* pin_group);
/**
* Move a pin group to another index within the module.
@@ -536,9 +537,9 @@ namespace hal
*
* @param[in] pin_group - The pin group to be moved.
* @param[in] new_index - The index to which the pin group is moved.
- * @returns Ok on success, an error message otherwise.
+ * @returns true on success, false message otherwise.
*/
- Result move_pin_group(PinGroup* pin_group, u32 new_index);
+ bool move_pin_group(PinGroup* pin_group, u32 new_index);
/**
* Set the name of the given pin group.
@@ -574,9 +575,9 @@ namespace hal
* @param[in] pin_group - The new pin group.
* @param[in] pin - The pin to be added.
* @param[in] delete_empty_groups - Set `true` to delete groups that are empty after the pin has been assigned to the new group, `false` to keep empty groups. Defaults to `true`.
- * @returns Ok on success, an error message otherwise.
+ * @returns `true` on success, `false` otherwise.
*/
- Result assign_pin_to_group(PinGroup* pin_group, ModulePin* pin, bool delete_empty_groups = true);
+ bool assign_pin_to_group(PinGroup* pin_group, ModulePin* pin, bool delete_empty_groups = true);
/**
* Move a pin to another index within the given pin group.
@@ -585,9 +586,9 @@ namespace hal
* @param[in] pin_group - The pin group.
* @param[in] pin - The pin to be moved.
* @param[in] new_index - The index to which the pin is moved.
- * @returns Ok on success, an error message otherwise.
+ * @returns `true` on success, `false` otherwise.
*/
- Result move_pin_within_group(PinGroup* pin_group, ModulePin* pin, u32 new_index);
+ bool move_pin_within_group(PinGroup* pin_group, ModulePin* pin, u32 new_index);
/**
* Remove a pin from a pin group.
@@ -596,9 +597,9 @@ namespace hal
* @param[in] pin_group - The old pin group.
* @param[in] pin - The pin to be removed.
* @param[in] delete_empty_groups - Set `true` to delete the group of it is empty after the pin has been removed, `false` to keep the empty group. Defaults to `true`.
- * @returns Ok on success, an error message otherwise.
+ * @returns `true` on success, `false` otherwise.
*/
- Result remove_pin_from_group(PinGroup* pin_group, ModulePin* pin, bool delete_empty_groups = true);
+ bool remove_pin_from_group(PinGroup* pin_group, ModulePin* pin, bool delete_empty_groups = true);
/*
* ################################################################
@@ -680,6 +681,12 @@ namespace hal
*/
std::vector get_gates(const std::function& filter, bool recursive = false) const;
+ /**
+ * Get the event handler connected to module
+ * @return The event handler;
+ */
+ EventHandler* get_event_handler() const;
+
private:
friend class NetlistInternalManager;
Module(NetlistInternalManager* internal_manager, EventHandler* event_handler, u32 id, Module* parent, const std::string& name);
@@ -741,11 +748,11 @@ namespace hal
NetConnectivity check_net_endpoints(const Net* net) const;
Result check_net(Net* net, bool recursive = false);
- Result assign_pin_net(const u32 pin_id, Net* net, PinDirection direction, const std::string& name = "", PinType type = PinType::none);
- Result remove_pin_net(Net* net);
+ bool assign_pin_net(const u32 pin_id, Net* net, PinDirection direction);
+ bool remove_pin_net(Net* net);
Result create_pin_internal(const u32 id, const std::string& name, Net* net, PinDirection direction, PinType type, bool force_name);
- Result delete_pin_internal(ModulePin* pin);
+ bool delete_pin_internal(ModulePin* pin);
Result*> create_pin_group_internal(const u32 id, const std::string& name, PinDirection direction, PinType type, bool ascending, u32 start_index, bool force_name);
- Result delete_pin_group_internal(PinGroup* pin_group);
+ bool delete_pin_group_internal(PinGroup* pin_group);
};
} // namespace hal
diff --git a/include/hal_core/netlist/pins/base_pin.h b/include/hal_core/netlist/pins/base_pin.h
index 79629f2c34c..855db0470bd 100644
--- a/include/hal_core/netlist/pins/base_pin.h
+++ b/include/hal_core/netlist/pins/base_pin.h
@@ -187,4 +187,4 @@ namespace hal
{
}
};
-} // namespace hal
\ No newline at end of file
+} // namespace hal
diff --git a/include/hal_core/netlist/pins/pin_group.h b/include/hal_core/netlist/pins/pin_group.h
index b036ab682d1..31f0f526cab 100644
--- a/include/hal_core/netlist/pins/pin_group.h
+++ b/include/hal_core/netlist/pins/pin_group.h
@@ -27,6 +27,7 @@
#include "hal_core/defines.h"
#include "hal_core/utilities/result.h"
+#include "hal_core/utilities/log.h"
#include
#include
@@ -312,19 +313,39 @@ namespace hal
* Assign a pin to the pin group.
*
* @param[in] pin - The pin to assign.
- * @returns Ok on success, an error message otherwise.
+ * @returns true on success, false otherwise.
*/
- Result assign_pin(T* pin)
+ bool assign_pin(T* pin)
{
if (pin == nullptr)
{
- return ERR("'nullptr' given instead of a pin when trying to assign a pin to pin group '" + m_name + "' with ID " + std::to_string(m_id));
+ log_warning("pin_group", "'nullptr' given instead of a pin when trying to assign a pin to pin group '{}' with ID {}",
+ m_name, m_id);
+ return false;
}
- i32 index = m_ascending ? m_next_index++ : m_next_index--;
- m_pins.push_back(pin);
+ i32 index = 0;
+ if (m_ascending)
+ {
+ index = m_next_index++;
+ m_pins.push_back(pin);
+ }
+ else
+ {
+ if (m_start_index == m_next_index)
+ {
+ // special case empty pin group
+ index = m_start_index;
+ -- m_next_index;
+ }
+ else
+ {
+ index = ++m_start_index;
+ }
+ m_pins.push_front(pin);
+ }
pin->m_group = std::make_pair(this, index);
- return OK({});
+ return true;
}
/**
@@ -405,18 +426,20 @@ namespace hal
* Remove a pin from the pin group.
*
* @param[in] pin - The pin to remove.
- * @returns Ok on success, an error message otherwise.
+ * @returns true on success, false otherwise.
*/
- Result remove_pin(T* pin)
+ bool remove_pin(T* pin)
{
if (pin == nullptr)
{
- return ERR("'nullptr' given instead of a pin when trying to remove pin from pin group '" + m_name + "' with ID " + std::to_string(m_id));
+ log_warning("pin_group", "'nullptr' given instead of a pin when trying to remove pin from pin group '{}' with ID {}.", m_name, m_id);
+ return false;
}
if (pin->m_group.first != this)
{
- return ERR("pin '" + pin->get_name() + "' with ID " + std::to_string(pin->get_id()) + " does not belong to pin group '" + m_name + "' with ID " + std::to_string(m_id));
+ log_warning("pin_group", "pin '{}' with ID {} does not belong to pin group '{}' with ID {}.", pin->get_name(), pin->get_id(), m_name, m_id);
+ return false;
}
i32 index = pin->m_group.second;
@@ -433,16 +456,24 @@ namespace hal
}
else
{
- auto it = std::next(m_pins.begin(), m_start_index - index);
- it = m_pins.erase(it);
- for (; it != m_pins.end(); it++)
+ if (m_pins.size()==1)
{
- std::get<1>((*it)->m_group)++;
+ m_pins.clear();
+ m_next_index++;
}
- m_next_index++;
- }
+ else
+ {
+ auto it = m_pins.begin();
+ for (int i=m_start_index; i>index;i--)
+ {
+ std::get<1>((*(it++))->m_group)--;
+ }
+ m_pins.erase(it);
+ --m_start_index;
+ }
+ }
- return OK({});
+ return true;
}
/**
@@ -481,4 +512,4 @@ namespace hal
PinGroup& operator=(const PinGroup&) = delete;
PinGroup& operator=(PinGroup&&) = delete;
};
-} // namespace hal
\ No newline at end of file
+} // namespace hal
diff --git a/plugins/bitorder_propagation/src/plugin_bitorder_propagation.cpp b/plugins/bitorder_propagation/src/plugin_bitorder_propagation.cpp
index 32df78b9850..7e839e0d7ac 100644
--- a/plugins/bitorder_propagation/src/plugin_bitorder_propagation.cpp
+++ b/plugins/bitorder_propagation/src/plugin_bitorder_propagation.cpp
@@ -928,10 +928,9 @@ namespace hal
for (const auto& [index, pin] : index_to_pin)
{
- auto move_res = m->move_pin_within_group(pg, pin, index);
- if (move_res.is_error())
+ if (!m->move_pin_within_group(pg, pin, index))
{
- return ERR_APPEND(move_res.get_error(),
+ return ERR(
"cannot reorder module pin groups: failed to move pin " + pin->get_name() + " in pin group " + pg->get_name() + " of module with ID "
+ std::to_string(m->get_id()) + " to new index " + std::to_string(index));
}
diff --git a/plugins/dataflow_analysis/src/api/result.cpp b/plugins/dataflow_analysis/src/api/result.cpp
index 1aecd57dcaf..d8441ec5c2c 100644
--- a/plugins/dataflow_analysis/src/api/result.cpp
+++ b/plugins/dataflow_analysis/src/api/result.cpp
@@ -519,9 +519,9 @@ namespace hal
}
else
{
- if (const auto res = new_mod->assign_pin_to_group(data_in_group, pin); res.is_error())
+ if (!new_mod->assign_pin_to_group(data_in_group, pin))
{
- log_warning("dataflow", "{}", res.get_error().get());
+ log_warning("dataflow", "Assign pin to group failed.");
}
}
@@ -542,9 +542,9 @@ namespace hal
}
else
{
- if (const auto res = new_mod->assign_pin_to_group(data_out_group, pin); res.is_error())
+ if (!new_mod->assign_pin_to_group(data_out_group, pin))
{
- log_warning("dataflow", "{}", res.get_error().get());
+ log_warning("dataflow", "Assign pin to group failed.");
}
}
@@ -588,9 +588,9 @@ namespace hal
}
else
{
- if (const auto res = new_mod->assign_pin_to_group(pin_group, pin); res.is_error())
+ if (!new_mod->assign_pin_to_group(pin_group, pin))
{
- log_warning("dataflow", "{}", res.get_error().get());
+ log_warning("dataflow", "Assign pin to group failed.");
}
}
@@ -814,4 +814,4 @@ namespace hal
return OK(new_group_ids);
}
} // namespace dataflow
-} // namespace hal
\ No newline at end of file
+} // namespace hal
diff --git a/plugins/gate_libraries/definitions/example_library.hgl b/plugins/gate_libraries/definitions/example_library.hgl
index b42016e1c2c..ed1af26c8af 100644
--- a/plugins/gate_libraries/definitions/example_library.hgl
+++ b/plugins/gate_libraries/definitions/example_library.hgl
@@ -2055,7 +2055,9 @@
"state": "IQ",
"neg_state": "IQN",
"next_state": "(D & CE)",
- "clocked_on": "C"
+ "clocked_on": "C",
+ "data_category": "generic",
+ "data_identifier": "INIT"
},
"pin_groups": [
{
@@ -2128,7 +2130,9 @@
"neg_state": "IQN",
"next_state": "(D & CE)",
"clocked_on": "C",
- "preset_on": "S"
+ "preset_on": "S",
+ "data_category": "generic",
+ "data_identifier": "INIT"
},
"pin_groups": [
{
@@ -2215,7 +2219,9 @@
"neg_state": "IQN",
"next_state": "(D & CE)",
"clocked_on": "C",
- "clear_on": "R"
+ "clear_on": "R",
+ "data_category": "generic",
+ "data_identifier": "INIT"
},
"pin_groups": [
{
@@ -2305,7 +2311,9 @@
"clear_on": "R",
"preset_on": "S",
"state_clear_preset": "L",
- "neg_state_clear_preset": "H"
+ "neg_state_clear_preset": "H",
+ "data_category": "generic",
+ "data_identifier": "INIT"
},
"pin_groups": [
{
@@ -2444,4 +2452,4 @@
]
}
]
-}
\ No newline at end of file
+}
diff --git a/plugins/gui/include/gui/basic_tree_model/base_tree_item.h b/plugins/gui/include/gui/basic_tree_model/base_tree_item.h
index ae9a9efe332..04df7bf683e 100644
--- a/plugins/gui/include/gui/basic_tree_model/base_tree_item.h
+++ b/plugins/gui/include/gui/basic_tree_model/base_tree_item.h
@@ -35,15 +35,10 @@ namespace hal
/**
* @brief (Future) Base class for all tree models related to the details widget.
*
- * This class functions as a generic data container for all tree models. For this
- * 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)
+ * This class functions as a generic data container for all tree models.
*/
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,...)
-
private:
/**
* Copy constructor. Copies the item's data, not the parent/children.
@@ -194,31 +189,9 @@ namespace hal
*/
virtual int getOwnRow();
- /**
- * Stores additional data. Can be accessed by getAdditionalData.
- * (For example, a menu or color)
- *
- * @param key - The key to store the data under.
- * @param data - The actual data to store.
- */
- virtual void setAdditionalData(QString key, QVariant data);
-
- /**
- * Retrieve the data stored under the given key.
- *
- * @param key - The key for the requested data.
- * @return The data if something was stored under the key, empty QVariant otherwise.
- */
- virtual QVariant getAdditionalData(QString key) const;
-
- private:
+ protected:
BaseTreeItem* mParent;
QList mChildren;
-
- // experimental, additional data (for anything)
- QMap mAdditionalData;
- //QList mAdditionalData;
-
};
/**
diff --git a/plugins/gui/include/gui/content_anchor/content_anchor.h b/plugins/gui/include/gui/content_anchor/content_anchor.h
index eefe744c322..8fb03c1c8dd 100644
--- a/plugins/gui/include/gui/content_anchor/content_anchor.h
+++ b/plugins/gui/include/gui/content_anchor/content_anchor.h
@@ -84,6 +84,11 @@ namespace hal
* Destructor that has to be overriden.
*/
virtual inline ~ContentAnchor() = 0;
+
+ /**
+ * Returns the number of widgets / buttons as of mDockBar->count()
+ */
+ virtual int count() const = 0;
};
ContentAnchor::~ContentAnchor()
diff --git a/plugins/gui/include/gui/docking_system/splitter_anchor.h b/plugins/gui/include/gui/docking_system/splitter_anchor.h
index 7678f0c01f6..d7bd083c071 100644
--- a/plugins/gui/include/gui/docking_system/splitter_anchor.h
+++ b/plugins/gui/include/gui/docking_system/splitter_anchor.h
@@ -113,7 +113,7 @@ namespace hal
*
* @return The number of widgets.
*/
- int count();
+ int count() const override;
/**
* Removes all buttons from the dockbar and therefore the widgets from the area. The corresponding
diff --git a/plugins/gui/include/gui/docking_system/tab_widget.h b/plugins/gui/include/gui/docking_system/tab_widget.h
index d5d56f5ea50..9692b36c411 100644
--- a/plugins/gui/include/gui/docking_system/tab_widget.h
+++ b/plugins/gui/include/gui/docking_system/tab_widget.h
@@ -116,6 +116,12 @@ namespace hal
*/
void handleNoCurrentWidget(int index);
+ /**
+ * Returns the number of widgets / buttons as of mDockBar->count()
+ * @return - The number of widgets / buttons
+ */
+ int count() const override;
+
/**
* Removes all buttons from the dockbar and therefore the widgets from the area. The corresponding
* widgets are not destroyed but hidden.
diff --git a/plugins/gui/include/gui/graph_widget/contexts/graph_context.h b/plugins/gui/include/gui/graph_widget/contexts/graph_context.h
index ddb2d70c423..5af6e8fb1cd 100644
--- a/plugins/gui/include/gui/graph_widget/contexts/graph_context.h
+++ b/plugins/gui/include/gui/graph_widget/contexts/graph_context.h
@@ -224,6 +224,13 @@ namespace hal
*/
bool isShowingNetDestination(const u32 mNetId) const;
+ /**
+ * Checks whether there is only the folded top_module in the context
+ * which makes other time consumptive tests unnecessary
+ * @return true If here is only the folded top_module in the context
+ */
+ bool isShowingFoldedTopModule() const;
+
/**
* Given a net, this function returns the first visible source node.
*
diff --git a/plugins/gui/include/gui/graph_widget/drag_controller.h b/plugins/gui/include/gui/graph_widget/drag_controller.h
new file mode 100644
index 00000000000..8914ed99746
--- /dev/null
+++ b/plugins/gui/include/gui/graph_widget/drag_controller.h
@@ -0,0 +1,90 @@
+// 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
+#include
+#include
+#include
+#include "gui/gui_def.h"
+#include "gui/graph_widget/items/utility_items/node_drag_shadow.h"
+
+namespace hal {
+
+ class GraphWidget;
+ class GraphicsNode;
+ class NodeBox;
+ class NodeDragShadow;
+ class GraphicsScene;
+
+ class DragController : public QObject
+ {
+ Q_OBJECT
+ GraphWidget* mGraphWidget;
+ bool mDropAllowed;
+ bool mWantSwap;
+ QPoint mMousedownPosition;
+ NodeBox* mDragNodeBox;
+ QPoint mCurrentGridpos;
+ QSet mAdditionalBoxes;
+ QHash mShadows;
+ GraphicsScene* mShadowScene;
+
+ void setSwapIntent(bool wantSwap);
+ void addShadow(const NodeBox* nb);
+ public:
+ DragController(GraphWidget* gw, QObject* parent = nullptr);
+
+ void clear();
+
+ void set(GraphicsNode* drgItem, const QPoint& eventPos);
+
+ /**
+ * Starts the dragging of a gate or module to show its shadow meanwhile.
+ *
+ * @param wantSwap - True if keyboard swap modifier has been pressed, false otherwise
+ */
+ void enterDrag(bool wantSwap);
+
+ /**
+ * Moves the shadow that appears while dragging a gate or module.
+ *
+ * @param eventPos - The mouse position in scene coordinates while dragging
+ * @param wantSwap - True if keyboard swap modifier has been pressed, false otherwise
+ * @param gridPos - The new grid position of the primary node
+ */
+ void move(const QPoint& eventPos, bool wantSwap, const QPoint& gridPos);
+
+ /**
+ * Remove all painted shadows from graphics scene
+ */
+ void clearShadows(GraphicsScene* sc);
+
+ bool hasDragged(const QPoint& eventPos);
+ bool isDropAllowed() const;
+ GridPlacement* finalGridPlacement() const;
+ NodeDragShadow::DragCue dragCue() const;
+ };
+}
diff --git a/plugins/gui/include/gui/graph_widget/graph_context_manager.h b/plugins/gui/include/gui/graph_widget/graph_context_manager.h
index 36582f917d0..d1ad735176d 100644
--- a/plugins/gui/include/gui/graph_widget/graph_context_manager.h
+++ b/plugins/gui/include/gui/graph_widget/graph_context_manager.h
@@ -26,6 +26,7 @@
#pragma once
#include "hal_core/defines.h"
+#include "hal_core/netlist/gate_library/enums/pin_event.h"
#include
#include
@@ -142,7 +143,7 @@ namespace hal
bool contextWithNameExists(const QString& name) const;
/**
- * Generate next view with given prefix
+ * Generate next view name with given prefix
* @param prefix
* @return the view name which does not exist so far
*/
@@ -226,7 +227,7 @@ namespace hal
*
* @param m - The module with the changed port
*/
- void handleModulePortsChanged(Module* m);
+ void handleModulePortsChanged(Module* m, PinEvent pev, u32 pgid);
/**
* Handler to be called after a gate has been removed.
@@ -390,6 +391,8 @@ namespace hal
}
static SettingsItemCheckbox* sSettingNetGroupingToPins;
+
+ static SettingsItemCheckbox* sSettingPanOnMiddleButton;
Q_SIGNALS:
/**
* Q_SIGNAL that notifies about the creation of a new context by the context manager.
diff --git a/plugins/gui/include/gui/graph_widget/graph_graphics_view.h b/plugins/gui/include/gui/graph_widget/graph_graphics_view.h
index 88519baf70f..424384b7c01 100644
--- a/plugins/gui/include/gui/graph_widget/graph_graphics_view.h
+++ b/plugins/gui/include/gui/graph_widget/graph_graphics_view.h
@@ -40,6 +40,7 @@ namespace hal
{
class GraphicsItem;
class GraphWidget;
+ class DragController;
namespace graph_widget_constants
{
@@ -202,6 +203,8 @@ namespace hal
void addSuccessorToView(int maxLevel, bool succ);
void addCommonSuccessorToView(int maxLevel, bool succ);
+ void dragPan(float dpx, float dpy);
+
GraphWidget* mGraphWidget;
QSet getSelectableGates();
@@ -233,13 +236,7 @@ namespace hal
bool mGridClustersEnabled;
GraphicsScene::GridType mGridType;
- QPoint mDragMousedownPosition;
- QPoint mDragStartGridpos;
- GraphicsGate* mDragItem;
- QPoint mDragCurrentGridpos;
- bool mDragCurrentModifier;
- bool mDropAllowed;
-
+ DragController* mDragController;
Qt::KeyboardModifier mDragModifier;
QPoint mMovePosition;
diff --git a/plugins/gui/include/gui/graph_widget/graphics_scene.h b/plugins/gui/include/gui/graph_widget/graphics_scene.h
index 08182287355..a9965e749e8 100644
--- a/plugins/gui/include/gui/graph_widget/graphics_scene.h
+++ b/plugins/gui/include/gui/graph_widget/graphics_scene.h
@@ -44,6 +44,7 @@ namespace hal
class GraphicsItem;
class GraphicsModule;
class GraphicsNet;
+ class DragController;
/**
* @ingroup graph
@@ -119,28 +120,6 @@ namespace hal
*/
~GraphicsScene();
- /**
- * Starts the dragging of a gate or module to show its shadow meanwhile.
- *
- * @param posF - The position of the shadow
- * @param sizeF - The size of the shadow (i.e. the size of the dragged gate)
- * @param cue - The cue of the current position
- */
- void startDragShadow(const QPointF& posF, const QSizeF& sizeF, const NodeDragShadow::DragCue cue);
-
- /**
- * Moves the shadow that appears while dragging a gate or module.
- *
- * @param posF - The new position of the shadow
- * @param cue - The cue of the current position
- */
- void moveDragShadow(const QPointF& posF, const NodeDragShadow::DragCue cue);
-
- /**
- * Removes the shadow that appears while dragging a gate or module (at the end of the drag action).
- */
- void stopDragShadow();
-
/**
* Gets the position of the drag shadow.
*
@@ -297,6 +276,12 @@ namespace hal
*/
void updateAllItems();
+ /**
+ * Set reference pointer to drag controller on start drag, nullptr when drag ended
+ * @param dc - Reference to drag controller
+ */
+ void setDragController(DragController* dc);
+
protected:
/**
* Handles the mouse event. Used to intercept and ignore right-clicks.
@@ -321,8 +306,6 @@ namespace hal
void drawBackground(QPainter* painter, const QRectF& rect) override;
- NodeDragShadow* mDragShadowGate;
-
QVector mModuleItems;
QVector mGateItems;
QVector mNetItems;
@@ -334,6 +317,7 @@ namespace hal
qreal mDebugDefaultWidth;
qreal mDebugDefaultHeight;
bool mDebugGridEnable;
+ DragController* mDragController;
enum RubberBandSelectionStatus
{
NotPressed,
diff --git a/plugins/gui/include/gui/graph_widget/items/utility_items/node_drag_shadow.h b/plugins/gui/include/gui/graph_widget/items/utility_items/node_drag_shadow.h
index 5b773285853..8031ce7bd77 100644
--- a/plugins/gui/include/gui/graph_widget/items/utility_items/node_drag_shadow.h
+++ b/plugins/gui/include/gui/graph_widget/items/utility_items/node_drag_shadow.h
@@ -25,7 +25,9 @@
#pragma once
-#include
+#include
+#include
+#include
namespace hal
{
@@ -33,9 +35,8 @@ namespace hal
* @ingroup graph-visuals
* @brief An item that is drawn when a node is dragged through the scene.
*/
- class NodeDragShadow : public QGraphicsObject
+ class NodeDragShadow : public QGraphicsItem
{
- Q_OBJECT
public:
enum class DragCue
@@ -50,14 +51,17 @@ namespace hal
void start(const QPointF& posF, const QSizeF& sizeF);
void stop();
+ /*
qreal width() const;
qreal height() const;
QSizeF size() const;
void setWidth(const qreal width);
void setHeight(const qreal height);
+*/
void setVisualCue(const DragCue cue);
+ QList multiMoveGridPositions() const;
static void setLod(const qreal lod);
static void loadSettings();
@@ -75,8 +79,6 @@ namespace hal
static QColor sColorTranslucent[];
DragCue mCue;
-
- qreal mWidth;
- qreal mHeight;
+ QRectF mRect;
};
} // namespace hal
diff --git a/plugins/gui/include/gui/graph_widget/layout_locker.h b/plugins/gui/include/gui/graph_widget/layout_locker.h
index ebc6472a05c..34af29617d5 100644
--- a/plugins/gui/include/gui/graph_widget/layout_locker.h
+++ b/plugins/gui/include/gui/graph_widget/layout_locker.h
@@ -26,6 +26,7 @@
#pragma once
#include
+#include "hal_core/defines.h"
namespace hal
{
@@ -37,7 +38,7 @@ namespace hal
LayoutLockerManager();
int mLockCount;
- QSet mWaitingRoom;
+ QSet mWaitingRoom;
public:
static LayoutLockerManager* instance();
diff --git a/plugins/gui/include/gui/graph_widget/layouters/graph_layouter.h b/plugins/gui/include/gui/graph_widget/layouters/graph_layouter.h
index 9324227d717..6fd0498649b 100644
--- a/plugins/gui/include/gui/graph_widget/layouters/graph_layouter.h
+++ b/plugins/gui/include/gui/graph_widget/layouters/graph_layouter.h
@@ -271,7 +271,15 @@ namespace hal
const QMap nodeToPositionMap() const;
const QMap positionToNodeMap() const;
+
+ /**
+ * Creates a new GridPlacement instance (node to position hash) and returns the pointer
+ * The caller has the ownership and responsibility to delete that instance
+ */
+ GridPlacement* gridPlacementFactory() const;
+
NetLayoutPoint positonForNode(const Node& nd) const;
+ Node nodeAtPosition(const QPoint& p) const;
QPoint gridPointByItem(GraphicsNode* item) const;
diff --git a/plugins/gui/include/gui/module_model/module_item.h b/plugins/gui/include/gui/module_model/module_item.h
index 49bbdc9288b..f34143e088c 100644
--- a/plugins/gui/include/gui/module_model/module_item.h
+++ b/plugins/gui/include/gui/module_model/module_item.h
@@ -107,6 +107,13 @@ namespace hal
*/
bool highlighted() const;
+ /**
+ * Checks if this ModuleItem is direct child to mRootItem
+ *
+ * @return
+ */
+ bool isToplevelItem() const;
+
/**
* Gets the type of the netlist item this ModuleItem represents.
*
@@ -121,6 +128,12 @@ namespace hal
*/
void setName(const QString& name);
+ /**
+ * Set the module type name (gate types are immutable)
+ * @param moduleType
+ */
+ void setModuleType(const QString& moduleType);
+
/**
* Marks/Unmarks this ModuleItem as highlighted.
*
@@ -131,8 +144,9 @@ namespace hal
private:
u32 mId;
- TreeItemType mType;
+ TreeItemType mItemType;
QString mName;
+ QString mModuleType;
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 11086efdb05..fd0e5c01755 100644
--- a/plugins/gui/include/gui/module_model/module_model.h
+++ b/plugins/gui/include/gui/module_model/module_model.h
@@ -36,6 +36,7 @@
#include
#include
#include
+#include
namespace hal
{
@@ -50,6 +51,28 @@ namespace hal
{
Q_OBJECT
+ class TempGateAssignment
+ {
+ int mAccumulate;
+ public:
+ QHash mGateRemove;
+ QHash mGateAssign;
+
+ TempGateAssignment() : mAccumulate(0) {;}
+ void removeGateFromModule(u32 gateId, Module* m)
+ {
+ if (!mGateRemove.contains(gateId))
+ mGateRemove[gateId] = m;
+ }
+ void assignGateToModule(u32 gateId, Module* m)
+ {
+ mGateAssign[gateId] = m;
+ }
+ bool isAccumulate() const { return mAccumulate > 0; }
+ void beginAccumulate() { mAccumulate++; }
+ void endAccumulate() { mAccumulate--; }
+ };
+
public:
/**
* Constructor.
@@ -90,14 +113,6 @@ namespace hal
*/
ModuleItem* getItem(const QModelIndex& index) const;
- /**
- * Returns the index where the specified ModuleItem can be found.
- *
- * @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 id and type.
*
@@ -123,7 +138,7 @@ namespace hal
* @param id - The id of the module to add.
* @param parent_module - The id of the parent module of the module to add.
*/
- void addModule(const u32 id, const u32 parent_module);
+ void addModule(const u32 id, const u32 parentId);
/**
* Add a gate to the item model. For the specified gate a new ModuleItem is created and stored.
@@ -131,7 +146,7 @@ namespace hal
* @param id - The id of the gate to add.
* @param parent_module - The id of the parent module of the gate to add.
*/
- void addGate(const u32 id, const u32 parent_module);
+ void addGate(const u32 id, const u32 parentId);
/**
* Add a net to the item model. For the specified net a new ModuleItem is created and stored.
@@ -139,7 +154,7 @@ namespace hal
* @param id - The id of the net to add.
* @param parent_module - The id of the parent module of the net to add.
*/
- void addNet(const u32 id, const u32 parent_module);
+ void addNet(const u32 id, const u32 parentId);
/**
* Recursively adds the given module with all of its submodules (and their submodules and so on...)
@@ -148,7 +163,7 @@ namespace hal
* @param module - The module which should be added to the item model together with all its
* submodules, gates and nets.
*/
- void addRecursively(const Module* module);
+ void addRecursively(const Module* module, BaseTreeItem* parentItem = nullptr);
/**
* Removes a module from the item model. The specified module MUST be contained in the item model.
@@ -172,20 +187,16 @@ namespace hal
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.
+ * Handles the assigment of gates to modules.
+ * If the gate does not yet exist in the item model, a new one is created.
*/
- void handleModuleParentChanged(const Module* module);
+ void moduleAssignGate(const u32 moduleId, const u32 gateId);
/**
- * 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.
+ * Handles the assigment of nets to modules for nets connected to gates of list.
+ * If the gate list is empty all nets connected to modules in tree are considered.
*/
- void handleModuleGateAssinged(const u32 id, const u32 parent_module);
+ void moduleAssignNets(const QList& gateIds = QList());
/**
* Updates the position of a net in the ModuleTree.
@@ -195,7 +206,7 @@ namespace hal
*
* @param net The net whose source or destination might have changed.
*/
- void updateNet(const Net* net);
+ void updateNetParent(const Net* net, const QHash* parentAssignment = nullptr);
/**
* Reattaches the ModuleItem corresponding to the specified module to a new parent item.
@@ -235,6 +246,47 @@ namespace hal
*/
bool isModifying();
+ private Q_SLOTS:
+ void handleModuleNameChanged(Module* mod);
+
+ void handleModuleRemoved(Module* mod);
+
+ void handleModuleCreated(Module* mod);
+
+ /**
+ * 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* mod);
+
+ void handleModuleSubmoduleAdded(Module* mod, u32 submodId);
+
+ void handleModuleSubmoduleRemoved(Module* mod, u32 submodId);
+
+ void handleModuleGateAssigned(Module* mod, u32 gateId);
+
+ void handleModuleGateRemoved(Module* mod, u32 gateId);
+
+ void handleModuleGatesAssignBegin(Module* mod, u32 numberGates);
+
+ void handleModuleGatesAssignEnd(Module* mod, u32 numberGates);
+
+ void handleGateCreated(Gate* gat);
+
+ void handleGateNameChanged(Gate* gat);
+
+ void handleGateRemoved(Gate* gat);
+
+ void handleNetCreated(Net* net);
+
+ void handleNetNameChanged(Net* net);
+
+ void handleNetRemoved(Net* net);
+
+ void handleNetUpdated(Net* net, u32 data);
private:
/**
* Searches for a new parent module, such that it is the deepest module in the hierarchy, that contains all
@@ -243,15 +295,41 @@ namespace hal
* @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.
+ * (e.g. global input/output, net has no sources or destinations), nullptr is returned instead.
*/
- Module* findNetParent(const Net* net);
+ Module* findNetParent(const Net* net) const;
+
+ /**
+ * Recursion to loop over all modules from (sub-)tree and create a hash assign how internal nets are assigned to module
+ * @param parent - top tree element
+ * @param parentAssignment - the resulting net module assignment
+ * @param assignedNets - nets already assigned (no assignment to module higher up in hierarchy)
+ */
+ void findNetParentRecursion(BaseTreeItem* parent, QHash& parentAssignment, std::unordered_set& assignedNets) const;
+
+ /**
+ * Factory method to append new tree items. Insert signals are sent to view. New items are put into hash table.
+ * @param id - ID of new tree item
+ * @param itemType - Whether new tree item is module, gate, or net
+ * @param parentItem - Parent to new tree item. Will create top-level item if parent is nullptr
+ * @return Point to new tree item
+ */
+ ModuleItem* createChildItem(u32 id, ModuleItem::TreeItemType itemType, BaseTreeItem* parentItem = nullptr);
+
+ /**
+ * Method to remove and delete tree items. Remove signals are sent to view.
+ * Hash table will _NOT_ be updated since caller can do it more efficiently.
+ * @param itemToRemove - Item to be removed from tree
+ * @param parentItem - Parent item. Must be present.
+ */
+ void removeChildItem(ModuleItem* itemToRemove, BaseTreeItem* parentItem);
- QMap mModuleMap;
- QMap mGateMap;
- QMap mNetMap;
- std::array*, 3> mModuleItemMaps = {&mModuleMap, &mGateMap, &mNetMap};;
+ QMultiMap mModuleMap;
+ QMultiMap mGateMap;
+ QMultiMap mNetMap;
+ QMultiMap* mModuleItemMaps[3] = {&mModuleMap, &mGateMap, &mNetMap};;
bool mIsModifying;
+ TempGateAssignment mTempGateAssignment;
};
} // 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 d3df33a65b2..115a6e7199c 100644
--- a/plugins/gui/include/gui/module_widget/module_widget.h
+++ b/plugins/gui/include/gui/module_widget/module_widget.h
@@ -45,6 +45,7 @@ class QTreeView;
namespace hal
{
+ class ModuleModel;
class ModuleProxyModel;
/**
@@ -93,6 +94,13 @@ namespace hal
*/
virtual QList createShortcuts() override;
+ /**
+ * Accesses the module model.
+ *
+ * @returns the module model
+ */
+ ModuleModel* getModuleModel() const;
+
/**
* Opens a existing view that contains the given module, otherwise creates a new context
* and opens it.
@@ -268,6 +276,7 @@ namespace hal
bool mIgnoreSelectionChange;
+ ModuleModel* mModuleModel;
ModuleProxyModel* mModuleProxyModel;
QShortcut* mShortCutDeleteItem;
@@ -276,6 +285,8 @@ namespace hal
void openGateInView(const QModelIndex& index);
+ void openNetEndpointsInView(const QModelIndex &index);
+
void changeGateName(const QModelIndex& index);
void changeNetName(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 83085c6b8ae..7e0630d1243 100644
--- a/plugins/gui/include/gui/netlist_relay/netlist_relay.h
+++ b/plugins/gui/include/gui/netlist_relay/netlist_relay.h
@@ -26,6 +26,7 @@
#pragma once
#include "hal_core/netlist/event_system/event_handler.h"
+#include "hal_core/netlist/gate_library/enums/pin_event.h"
#include "gui/grouping/grouping_color_serializer.h"
#include "gui/module_model/module_color_manager.h"
#include
@@ -34,7 +35,6 @@
namespace hal
{
class ModuleItem;
- class ModuleModel;
class ModuleColorManager;
class ModuleColorSerializer;
class Module;
@@ -86,13 +86,6 @@ namespace hal
*/
QColor getModuleColor(const u32 id);
- /**
- * Accesses the module model.
- *
- * @returns the module model
- */
- ModuleModel* getModuleModel() const;
-
/**
* Accesses the module color manager
*
@@ -342,7 +335,7 @@ namespace hal
* @param m - The module with the changed port
* @param respective_net - The id of the net of the renamed input port
*/
- void modulePortsChanged(Module* m) const;
+ void modulePortsChanged(Module* m, PinEvent pev, u32 pgid) const;
/**
* Q_SIGNAL to notify that the type of a module has been changed.
@@ -614,12 +607,12 @@ namespace hal
void relayGateEvent(GateEvent::event ev, Gate* gat, u32 associated_data);
void relayNetEvent(NetEvent::event ev, Net* net, u32 associated_data);
void relayGroupingEvent(GroupingEvent::event ev, Grouping* grp, u32 associated_data);
+ static void dumpModuleRecursion(Module* m);
void handleNetlistModified();
bool mNotified;
QMap mModuleColors;
- ModuleModel* mModuleModel;
ModuleColorManager* mModuleColorManager;
ModuleColorSerializer mColorSerializer;
enum ThreadEventType { TetNetlist, TetModule, TetGate, TetNet, TetGrouping };
diff --git a/plugins/gui/include/gui/python/python_editor.h b/plugins/gui/include/gui/python/python_editor.h
index 4e07f167a12..5a8e2fba537 100644
--- a/plugins/gui/include/gui/python/python_editor.h
+++ b/plugins/gui/include/gui/python/python_editor.h
@@ -848,5 +848,7 @@ namespace hal
SettingsItemKeybind* mSettingSaveFileAs;
SettingsItemKeybind* mSettingRunFile;
SettingsItemKeybind* mSettingCreateFile;
+
+ QList mBlockedContextIds;
};
} // namespace hal
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 1d23ff76df1..746eb58931e 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 BaseTreeItem;
+ class PinTreeItem;
class GraphNavigationWidget;
/**
@@ -98,8 +98,8 @@ namespace hal
bool mClearSelection;
//helper functions
- void buildPythonMenuForPin(QMenu &menu, BaseTreeItem* clickedPinItem);
- void buildPythonMenuForPinGroup(QMenu &menu, BaseTreeItem* clickedPinIGrouptem);
+ void buildPythonMenuForPin(QMenu &menu, PinTreeItem* clickedPinItem);
+ void buildPythonMenuForPinGroup(QMenu &menu, PinTreeItem* 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 142601fa32a..81c06e3f4b2 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
@@ -26,8 +26,10 @@
#pragma once
//#include "gui/new_selection_details_widget/models/base_tree_model.h"
+#include "hal_core/defines.h"
#include "gui/basic_tree_model/base_tree_model.h"
#include
+#include
namespace hal
{
@@ -36,8 +38,12 @@ namespace hal
class PinTreeItem : public BaseTreeItem
{
+ public:
+ enum Type {None, Pin, Group};
private:
+ Type mType;
+ QList mNetIds;
std::string mPinName;
QString mPinDirection;
QString mPinType;
@@ -51,6 +57,24 @@ namespace hal
void setDataAtIndex(int index, QVariant& data) override;
void appendData(QVariant data) override;
int getColumnCount() const override;
+ void setType(Type tp) { mType = tp; }
+
+ /**
+ * Get the type (enum) of a given item.
+ *
+ * @return The item's type.
+ */
+ Type type() const { return mType; }
+ void setNetIds(const QList& nids) { mNetIds = nids; }
+
+ /**
+ * Get the connected nets for a given treeitem (represents a pin). If the
+ * item is grouping type or the pin has no connected net, an empty list
+ * is returned. In case of an inout pin, even multiple connected nets are possible.
+ *
+ * @return A list of net ids.
+ */
+ QList netIds() const { return mNetIds; }
};
/**
@@ -63,9 +87,6 @@ class GatePinsTreeModel : public BaseTreeModel
public:
- //metatype declaration at the end of file
- enum class itemType {grouping = 0, pin = 1};
-
/**
* The constructor.
*
@@ -98,24 +119,6 @@ class GatePinsTreeModel : public BaseTreeModel
*/
int getCurrentGateID();
- /**
- * Get the connected nets for a given treeitem (represents a pin). If the
- * item is grouping type or the pin has no connected net, an empty list
- * is returned. In case of an inout pin, even multiple connected nets are possible.
- *
- * @param item - The treeitem from which to get the connected nets.
- * @return A list of net ids.
- */
- QList getNetIDsOfTreeItem(BaseTreeItem* item);
-
- /**
- * Get the type (enum) of a given item.
- *
- * @param item - The item for which the type is requested.
- * @return The item's type.
- */
- itemType getTypeOfItem(BaseTreeItem* item);
-
/**
* Get the number of displayed pins (the number of pins of all types).
*
@@ -130,16 +133,10 @@ class GatePinsTreeModel : public BaseTreeModel
static const int sTypeColumn = 2;
static const int sConnectedNetColumn = 3;
- //additional data keys
- const QString keyType = "type";
- const QString keyRepresentedNetsID = "netID"; //might not be needed
-
private:
int mGateId;
- QMap mPinGroupingToTreeItem;
+ QMap mPinGroupToTreeItem;
};
}
-
-Q_DECLARE_METATYPE(hal::GatePinsTreeModel::itemType)
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 0608a6bd89f..81dceaf580a 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
@@ -41,19 +41,30 @@ namespace hal
class ModuleTreeitem : public BaseTreeItem
{
+ public:
+ enum ItemType { None, Module, Gate};
private:
- std::string mType;
+ ItemType mItemType;
int mId;
- std::string mName;
+ QString mName;
+ QString mNodeType;
public:
- ModuleTreeitem(const std::string& name, int id, std::string tp);
+ ModuleTreeitem(ItemType itp, int id, const QString& name, const QString& ntp);
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;
+
+ /**
+ * Get the type (enum) of a given item.
+ *
+ * @param item - The item for which the type is requested.
+ * @return The item's type.
+ */
+ ItemType itemType() const { return mItemType; }
};
class ModuleTreeModel : public BaseTreeModel
@@ -61,9 +72,6 @@ namespace hal
Q_OBJECT
public:
- //metatype declaration at the end of file
- enum class itemType {module = 0, gate = 1};
-
ModuleTreeModel(QObject* parent = nullptr);
~ModuleTreeModel();
@@ -83,14 +91,6 @@ namespace hal
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
///@}
- /**
- * Get the type (enum) of a given item.
- *
- * @param item - The item for which the type is requested.
- * @return The item's type.
- */
- itemType getTypeOfItem(BaseTreeItem* item) const;
-
/**
* Disconnects all events from the model. Can be called to increase performance when
* no module is displayed.
@@ -144,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(BaseTreeItem* item) const;
+ QIcon getIconFromItem(ModuleTreeitem* item) const;
void clearOwnStructures();
@@ -167,5 +167,3 @@ namespace hal
};
}
-
-Q_DECLARE_METATYPE(hal::ModuleTreeModel::itemType)
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 5bb90aa7240..b6540d1855e 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
@@ -29,6 +29,7 @@
#include
//#include "gui/new_selection_details_widget/models/base_tree_item.h"
#include "gui/basic_tree_model/base_tree_model.h"
+#include "hal_core/defines.h"
namespace hal
{
@@ -39,19 +40,30 @@ namespace hal
class NetlistElementsTreeitem : public BaseTreeItem
{
+ public:
+ enum ItemType { None, Module, Gate, Net};
private:
- QString mType;
- int mId;
+ ItemType mItemType;
+ u32 mId;
QString mName;
+ QString mNodeType;
public:
- NetlistElementsTreeitem(const QString& name, int id, QString tp);
+ NetlistElementsTreeitem(ItemType itp, u32 id_, const QString& name, const QString& ntp = QString());
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;
+
+ u32 id() const { return mId; }
+ /**
+ * Get the type (enum) of a given item.
+ *
+ * @return The item's type.
+ */
+ ItemType itemType() const { return mItemType; }
};
/**
@@ -63,8 +75,6 @@ namespace hal
Q_OBJECT
public:
- //metatype declaration at the end of file
- enum class itemType {module = 0, gate = 1, net = 2};
/**
* The constructor.
@@ -121,14 +131,6 @@ namespace hal
*/
void setModule(Module* mod, bool showGates = true, bool showNets = true, bool displayModulesRecursive = true);
- /**
- * Get the type (enum) of a given item.
- *
- * @param item - The item for which the type is requested.
- * @return The item's type.
- */
- itemType getTypeOfItem(NetlistElementsTreeitem* item) const;
-
/**
* Get the module/gate/net id that the given item represents.
* To know the type of the item, call getTypeOfItem().
@@ -217,5 +219,3 @@ namespace hal
};
}
-
-Q_DECLARE_METATYPE(hal::NetlistElementsTreeModel::itemType)
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 5167f9bfc48..d14937a00d7 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
@@ -27,6 +27,9 @@
//#include "gui/new_selection_details_widget/models/base_tree_model.h"
#include "gui/basic_tree_model/base_tree_model.h"
+#include "hal_core/netlist/gate_library/enums/pin_direction.h"
+#include "hal_core/netlist/gate_library/enums/pin_event.h"
+#include "hal_core/netlist/gate_library/enums/pin_type.h"
#include
namespace hal
@@ -37,21 +40,41 @@ namespace hal
class PortTreeItem : public BaseTreeItem
{
+ public:
+ enum Type {None, Pin, Group};
private:
+ Type mItemType;
+ u32 mId;
QString mPinName;
- QString mPinDirection;
- QString mPinType;
+ PinDirection mPinDirection;
+ PinType mPinType;
QString mNetName;
+
public:
- PortTreeItem(QString pinName, QString pinDirection, QString pinType, QString netName);
- PortTreeItem();
+ PortTreeItem(Type itype, u32 id_, QString pinName, PinDirection dir, PinType ptype, QString netName = QString());
+ PortTreeItem() : mItemType(None), mId(0) {;}
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;
+ void setItemType(Type tp) { mItemType = tp; }
+ Type itemType() const { return mItemType; }
+ QString name() const { return mPinName; }
+ void setName(const QString& nam) { mPinName = nam; }
+ void setPinType(PinType ptype) { mPinType = ptype; }
+ void setPinDirection(PinDirection dir) { mPinDirection = dir; }
+
+ /**
+ * Returns the pin-id if the item represents a pin or the pingroup-id
+ * if the item represents a pingroup.
+ *
+ * @param item - The item.
+ * @return The pin- or pingroup-id.
+ */
+ u32 id() const { return mId; }
};
/**
@@ -62,10 +85,6 @@ namespace hal
Q_OBJECT
public:
- //metatype declaration at the end of file (portSingleBit and portMultiBit are deprecated)
- //important now are pins and groups
- enum class itemType{portSingleBit = 0, portMultiBit = 1, pin = 2, group = 3};
-
/**
* The constructor.
*
@@ -116,27 +135,10 @@ namespace hal
*/
int getRepresentedModuleId();
- /**
- * Get the type (enum) of a given item.
- *
- * @param item - The item for which the type is requested.
- * @return The item's type.
- */
- itemType getTypeOfItem(PortTreeItem* item) const;
-
- /**
- * Returns the pin-id if the item represents a pin or the pingroup-id
- * if the item represents a pingroup.
- *
- * @param item - The item.
- * @return The pin- or pingroup-id.
- */
- int getIdOfItem(BaseTreeItem* item) const;
-
/** @name Event Handler Functions
*/
///@{
- void handleModulePortsChanged(Module* m);
+ void handleModulePortsChanged(Module* m, PinEvent pev, u32 pgid);
///@}
//column identifier
@@ -145,10 +147,6 @@ namespace hal
static const int sTypeColumn = 2;
static const int sNetColumn = 3;
- //additional data keys
- const QString keyType = "type";
- const QString keyId = "id";
-
Q_SIGNALS:
/**
* Q_SIGNAL that is emitted when the number of the model's port changed.
@@ -163,9 +161,8 @@ namespace hal
Module* mModule;
//name is (hopefully) enough to identify
QMap mNameToTreeItem;
- QMap mIdToPinItem;
- QMap mIdToGroupItem;
- bool mIgnoreEventsFlag;
+ QMap mIdToPinItem;
+ QMap mIdToGroupItem;
void insertItem(PortTreeItem* item, BaseTreeItem* parent, int index);
void removeItem(PortTreeItem* item);
@@ -178,5 +175,3 @@ namespace hal
void dndPinBetweenGroup(PortTreeItem* droppedPin, int row);
};
}
-
-Q_DECLARE_METATYPE(hal::ModulePinsTreeModel::itemType)
diff --git a/plugins/gui/include/gui/selection_details_widget/net_details_widget/module_table_model.h b/plugins/gui/include/gui/selection_details_widget/net_details_widget/module_table_model.h
index a1b6a8cdf31..cfe0a053e7d 100644
--- a/plugins/gui/include/gui/selection_details_widget/net_details_widget/module_table_model.h
+++ b/plugins/gui/include/gui/selection_details_widget/net_details_widget/module_table_model.h
@@ -26,6 +26,7 @@
#pragma once
#include "hal_core/defines.h"
+#include "hal_core/netlist/gate_library/enums/pin_event.h"
#include
#include
@@ -154,7 +155,7 @@ class ModuleTableModel : public QAbstractTableModel
/** @name Event Handler Functions
*/
///@{
- void handleModulePortsChanged(Module* m);
+ void handleModulePortsChanged(Module* m, PinEvent pev, u32 pgid);
void handleModuleRemoved(Module* m);
///@}
diff --git a/plugins/gui/include/gui/selection_details_widget/selection_details_widget.h b/plugins/gui/include/gui/selection_details_widget/selection_details_widget.h
index 43f90b100b2..42010ac0807 100644
--- a/plugins/gui/include/gui/selection_details_widget/selection_details_widget.h
+++ b/plugins/gui/include/gui/selection_details_widget/selection_details_widget.h
@@ -338,6 +338,8 @@ namespace hal
*/
void selectionToModuleAction(int actionCode);
+ void showNoSelection();
+
QSplitter* mSplitter;
SelectionTreeView* mSelectionTreeView;
unsigned int mNumberSelectedItems;
diff --git a/plugins/gui/include/gui/user_action/action_create_object.h b/plugins/gui/include/gui/user_action/action_create_object.h
index 14407020ca4..65954b44c1a 100644
--- a/plugins/gui/include/gui/user_action/action_create_object.h
+++ b/plugins/gui/include/gui/user_action/action_create_object.h
@@ -40,6 +40,8 @@ namespace hal
{
QString mObjectName;
u32 mParentId;
+ u32 mLinkedObjectId;
+
public:
/**
* Action Constructor.
@@ -54,7 +56,8 @@ namespace hal
void writeToXml(QXmlStreamWriter& xmlOut) const override;
void readFromXml(QXmlStreamReader& xmlIn) override;
void addToHash(QCryptographicHash& cryptoHash) const override;
- void setParentId(u32 pid) {mParentId = pid;}//todo: remove this, use setParentObject instead
+ void setParentId(u32 pid) {mParentId = pid;}
+ void setLinkedObjectId(u32 lid) {mLinkedObjectId = lid;}
};
/**
diff --git a/plugins/gui/include/gui/user_action/action_move_node.h b/plugins/gui/include/gui/user_action/action_move_node.h
index 47d7a7d2d6e..d2279d4e0ff 100644
--- a/plugins/gui/include/gui/user_action/action_move_node.h
+++ b/plugins/gui/include/gui/user_action/action_move_node.h
@@ -66,7 +66,7 @@ namespace hal
* @param from - The initial position of the node to move
* @param to - The destination of the node
*/
- ActionMoveNode(u32 ctxID, const QPoint& from, const QPoint& to, bool swap = false);
+ // ActionMoveNode(u32 ctxID, const QPoint& from, const QPoint& to, bool swap = false);
/**
* Action constructor.
diff --git a/plugins/gui/include/gui/user_action/action_pingroup.h b/plugins/gui/include/gui/user_action/action_pingroup.h
new file mode 100644
index 00000000000..4ab871068f7
--- /dev/null
+++ b/plugins/gui/include/gui/user_action/action_pingroup.h
@@ -0,0 +1,179 @@
+// 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 "user_action.h"
+#include "hal_core/netlist/module.h"
+#include
+#include
+
+namespace hal
+{
+ class PinActionType : public QObject
+ {
+ Q_OBJECT
+ public:
+ enum Type { None, GroupCreate, GroupDelete, GroupMoveToRow, GroupRename, GroupTypeChange, GroupDirChange,
+ PinAsignToGroup, PinRename, PinTypeChange, PinDirChange, PinMoveToRow, MaxAction };
+ Q_ENUM(Type);
+
+ public:
+ static QString toString(Type tp);
+ static Type fromString(const QString& s);
+ static bool useExistingGroup(Type tp);
+ static bool useExistingPin(Type tp);
+ };
+
+ int pinGroupIndex(const Module* mod, const PinGroup* pgrp);
+
+ int pinIndex2Row(const ModulePin* pin, int index);
+
+ int pinRow2Index(const ModulePin* pin, int row);
+
+ QString generateGroupName(const Module* mod, const ModulePin* pin);
+
+ void dumpPingroups(Module* m = nullptr);
+ /**
+ * @ingroup user_action
+ * @brief Pingroup user actions
+ *
+ * Arguments depends on PinActionType::Type:
+ *
+ * GroupCreate:
+ * ID : ID of group to create
+ * negative ID: call constructor without ID, however,
+ * ID will be used internally for subsequent commands related to crated group
+ * name : name of group
+ * value : start index, assume ascending
+ * negative value: descending order starting with (-value-1)
+ *
+ * GroupDelete
+ * ID : ID of group to delete
+ *
+ * GroupMoveToRow
+ * ID : ID of group to move
+ * value : row to which group get moved within vector of pin groups
+ *
+ * GroupRename
+ * ID : ID of group to rename
+ * name : new name
+ *
+ * GroupTypeChange
+ * ID : ID of group to modifiy
+ * value : (int) PinType as of hal_core/netlist/gate_library/enums/pin_type.h
+ *
+ * GroupDirChange
+ * ID : ID of group to modifiy
+ * value : (int) PinDirection as of hal_core/netlist/gate_library/enums/pin_direction.h
+ *
+ * PinAsignToGroup
+ * ID : ID of pin
+ * value : ID of group, might be negative if group recently created
+ *
+ * PinRename
+ * ID : ID of pin to rename
+ * name : new name
+ *
+ * PinTypeChange
+ * ID : ID of pin to modify
+ * value : (int) PinType
+ *
+ * PinDirChange
+ * ID : ID of pin to modify
+ * value : (int) PinDirection
+ *
+ * PinMoveToRow
+ * ID : ID of pin
+ * value : row to which pin gets moved in pingroup
+ */
+ class ActionPingroup : public UserAction
+ {
+ private:
+ class AtomicAction
+ {
+ public:
+ PinActionType::Type mType;
+ int mId;
+ QString mName;
+ int mValue;
+ AtomicAction(PinActionType::Type tp, int id, const QString& name = QString(), int v=0) : mType(tp), mId(id), mName(name), mValue(v) {;}
+ };
+
+ class GroupRestore
+ {
+ public:
+ int mId;
+ QString mName;
+ int mRow;
+ int mStartIndex;
+ PinDirection mDirection;
+ PinType mType;
+ GroupRestore(Module* m, PinGroup* pgroup);
+ };
+
+ QHash*> mPinGroups;
+ QList mPinActions;
+ Module* mParentModule;
+ QMap mGroupRestore;
+ QSet mPinsMoved;
+ QSet mGroupToRemove;
+
+ PinGroup* getGroup(ModulePin* pin) const;
+ PinGroup* getGroup(int grpId) const;
+ void prepareUndoAction();
+ void finalizeUndoAction();
+ void addUndoAction(PinActionType::Type tp, int id = 0, const QString& name=QString(), int value=0);
+ static int pinGroupRow(Module* m, PinGroup* pgroup);
+ public:
+ ActionPingroup(PinActionType::Type tp = PinActionType::None, int id = 0, const QString& name=QString(), int value=0);
+ ActionPingroup(const QList& aaList);
+ bool exec() override;
+ QString tagname() const override;
+ void writeToXml(QXmlStreamWriter& xmlOut) const override;
+ void readFromXml(QXmlStreamReader& xmlIn) override;
+ void addToHash(QCryptographicHash& cryptoHash) const override;
+
+ static ActionPingroup* addPinsToExistingGroup(const Module* m, u32 grpId, QList pinIds, int pinRow = -1);
+ static ActionPingroup* addPinToExistingGroup(const Module* m, u32 grpId, u32 pinId, int pinRow = -1);
+ static ActionPingroup* addPinsToNewGroup(const Module* m, const QString& name, QList pinIds, int grpRow = -1);
+ static ActionPingroup* addPinToNewGroup(const Module* m, const QString& name, u32 pinId, int grpRow = -1);
+ static ActionPingroup* removePinsFromGroup(const Module* m, QList pinIds);
+ static ActionPingroup* deletePinGroup(const Module* m, u32 grpId);
+ };
+
+ /**
+ * @ingroup user_action
+ * @brief UserActionFactory for ActionPingroup
+ */
+ class ActionPingroupFactory : public UserActionFactory
+ {
+ public:
+ ActionPingroupFactory();
+ UserAction* newAction() const;
+ static ActionPingroupFactory* sFactory;
+ };
+
+ uint qHash(PinEvent pev);
+}
diff --git a/plugins/gui/include/gui/user_action/action_reorder_object.h b/plugins/gui/include/gui/user_action/action_reorder_object.h
deleted file mode 100644
index befac339d3e..00000000000
--- a/plugins/gui/include/gui/user_action/action_reorder_object.h
+++ /dev/null
@@ -1,101 +0,0 @@
-// 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 "user_action.h"
-
-namespace hal
-{
-
- /**
- * @ingroup user_action
- * @brief Reorders an item within a container.
- *
- * Reorders an item (only pins are currently supported, pingroups are planned) to a new position.
- * If the object's type is a pin or pingroup, the name is used to identify the object (configured
- * by setPinOrPingroupIdentifier or correct Constructor). In this case, object's id is used
- * to identify the corresponding module.
- */
- class ActionReorderObject : public UserAction
- {
- public:
- /**
- * Normal constructor (all purpose).
- *
- * @param newIndex - The new index.
- */
- ActionReorderObject(const int newIndex = -1);
-
- /**
- * Overwritten user_action function.
- *
- * @return True on success, False otherwise.
- */
- bool exec() override;
-
- /**
- * Overwritten user_action function.
- * @return The tag.
- */
- QString tagname() const override;
-
- /**
- * Overwritten user_action function.
- *
- * @param xmlOut - The writer.
- */
- void writeToXml(QXmlStreamWriter &xmlOut) const override;
-
- /**
- * Overwritten user_action function.
- *
- * @param xmlIn - The reader.
- */
- void readFromXml(QXmlStreamReader &xmlIn) override;
-
- /**
- * Overwritten user_action function.
- *
- * @param cryptoHash - The hash to add to.
- */
- void addToHash(QCryptographicHash &cryptoHash) const override;
-
- private:
- int mNewIndex;
- };
-
- /**
- * @ingroup user_action
- * @brief UserActionFactory for ActionReorderObject
- */
- class ActionReorderObjectFactory : public UserActionFactory
- {
- public:
- ActionReorderObjectFactory();
- UserAction * newAction() const override;
- static ActionReorderObjectFactory* sFactory;
- };
-
-}
diff --git a/plugins/gui/include/gui/user_action/user_action.h b/plugins/gui/include/gui/user_action/user_action.h
index f04f1809ed4..610e073454b 100644
--- a/plugins/gui/include/gui/user_action/user_action.h
+++ b/plugins/gui/include/gui/user_action/user_action.h
@@ -108,22 +108,6 @@ namespace hal
*/
virtual void setObject(const UserActionObject& obj);
- /**
- * Setter for parent object argument. Used to identify pins and
- * pingroups in which case the parent obj must be the corresponding
- * module.
- *
- * @param obj - The parent object.
- */
- virtual void setParentObject(const UserActionObject& obj);
-
- /**
- * Getter for parent object argument.
- *
- * @return The parent object argument.
- */
- virtual UserActionObject parentObject() const {return mParentObject;}
-
/**
* Get the order number in action compound, -1 if not in compound.
*
@@ -181,13 +165,6 @@ namespace hal
*/
void setObjectLock(bool lock) { mObjectLock = lock; }
- /**
- * Refuse set parent object requests (in case if needed)
- *
- * @param lock - Param to set parent lock.
- */
- void setParentObjectLock(bool lock) {mParentObjectLock = lock;}
-
/**
* Executing this action will modify the project thus a warning pops up when leaving hal without saving.
* @return True if executing the action will modify the project, false otherwise.
@@ -197,12 +174,10 @@ namespace hal
protected:
UserAction();
UserActionObject mObject;
- UserActionObject mParentObject;
int mCompoundOrder;
UserAction *mUndoAction;
qint64 mTimeStamp;
bool mObjectLock;
- bool mParentObjectLock;
bool mProjectModified;
static QString setToText(const QSet& set);
diff --git a/plugins/gui/include/gui/user_action/user_action_object.h b/plugins/gui/include/gui/user_action/user_action_object.h
index a3de7b57012..c6553091e1c 100644
--- a/plugins/gui/include/gui/user_action/user_action_object.h
+++ b/plugins/gui/include/gui/user_action/user_action_object.h
@@ -55,8 +55,6 @@ namespace hal
Netlist,
ContextView,
ContextDir,
- Pin,
- PinGroup,
MaxObjectType
};
Q_ENUM(ObjectType)
diff --git a/plugins/gui/src/basic_tree_model/base_tree_item.cpp b/plugins/gui/src/basic_tree_model/base_tree_item.cpp
index d0209984816..493a803e68a 100644
--- a/plugins/gui/src/basic_tree_model/base_tree_item.cpp
+++ b/plugins/gui/src/basic_tree_model/base_tree_item.cpp
@@ -99,16 +99,6 @@ namespace hal
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())
diff --git a/plugins/gui/src/content_layout_area/content_layout_area.cpp b/plugins/gui/src/content_layout_area/content_layout_area.cpp
index 8a3ac9b66f2..8dc4d88d102 100644
--- a/plugins/gui/src/content_layout_area/content_layout_area.cpp
+++ b/plugins/gui/src/content_layout_area/content_layout_area.cpp
@@ -1,5 +1,6 @@
#include "gui/content_layout_area/content_layout_area.h"
+#include "hal_core/utilities/log.h"
#include "gui/docking_system/dock_bar.h"
#include "gui/docking_system/splitter_anchor.h"
#include "gui/docking_system/tab_widget.h"
@@ -109,6 +110,30 @@ namespace hal
void ContentLayoutArea::addContent(ContentWidget* widget, int index, content_anchor anchor)
{
+ int maxIndex = 0;
+ switch (anchor)
+ {
+ case content_anchor::center:
+ maxIndex = mTabWidget->count();
+ break;
+ case content_anchor::left:
+ maxIndex = mLeftAnchor->count();
+ break;
+ case content_anchor::right:
+ maxIndex = mRightAnchor->count();
+ break;
+ case content_anchor::bottom:
+ maxIndex = mBottomAnchor->count();
+ break;
+ }
+
+ if (index > maxIndex)
+ {
+ log_warning("gui", "Cannot insert widget '{}' at index {}, moved to index {}", widget->name().toStdString(), index, maxIndex);
+ index = maxIndex;
+ }
+
+
switch (anchor)
{
case content_anchor::center:
diff --git a/plugins/gui/src/content_manager/content_manager.cpp b/plugins/gui/src/content_manager/content_manager.cpp
index 8b2d13a7a0a..09fd59069b2 100644
--- a/plugins/gui/src/content_manager/content_manager.cpp
+++ b/plugins/gui/src/content_manager/content_manager.cpp
@@ -150,10 +150,10 @@ namespace hal
void ContentManager::handleOpenDocument(const QString& fileName)
{
- mExternalIndex = 6;
+ mExternalIndex = 1;
mGraphTabWidget = new GraphTabWidget();
- mMainWindow->addContent(mGraphTabWidget, 2, content_anchor::center);
+ mMainWindow->addContent(mGraphTabWidget, 0, content_anchor::center);
mModuleWidget = new ModuleWidget();
mMainWindow->addContent(mModuleWidget, 0, content_anchor::left);
@@ -200,7 +200,7 @@ namespace hal
mPythonWidget->open();
mPythonConsoleWidget = new PythonConsoleWidget();
- mMainWindow->addContent(mPythonConsoleWidget, 5, content_anchor::bottom);
+ mMainWindow->addContent(mPythonConsoleWidget, 2, content_anchor::bottom);
mPythonConsoleWidget->open();
mContent.append(mGraphTabWidget);
diff --git a/plugins/gui/src/context_manager_widget/context_manager_widget.cpp b/plugins/gui/src/context_manager_widget/context_manager_widget.cpp
index 9668324bc72..7fa52f8764e 100644
--- a/plugins/gui/src/context_manager_widget/context_manager_widget.cpp
+++ b/plugins/gui/src/context_manager_widget/context_manager_widget.cpp
@@ -249,8 +249,8 @@ namespace hal
void ContextManagerWidget::handleDeleteClicked()
{
- QModelIndex current = mContextTreeView->currentIndex();
- if (!current.isValid()) return;
+ QModelIndex currentIndex = mContextTreeView->currentIndex();
+ if (!currentIndex.isValid()) return;
ContextTreeItem* currentItem = getCurrentItem();
@@ -264,6 +264,13 @@ namespace hal
act->exec();
}
else if (currentItem->isDirectory()) {
+ if (currentItem->getChildCount())
+ {
+ if (QMessageBox::Ok !=
+ QMessageBox::information(this, "Directory not empty", "You are about to delete a directory which is not empty.\nThis action cannot be undone",
+ QMessageBox::Ok|QMessageBox::Cancel))
+ return;
+ }
ContextDirectory* clicked_directory = currentItem->directory();
@@ -291,9 +298,10 @@ namespace hal
{
const QModelIndex clicked_index = mContextTreeView->indexAt(point);
- // TODO change current directory :
- // if clicked index is view : parent dir of view
- // if clicked index is dir : this dir
+ QModelIndex sourceIndex = mContextTreeProxyModel->mapToSource(clicked_index);
+ ContextTreeItem* item = static_cast(mContextTreeModel->getItemFromIndex(sourceIndex));
+ if (item)
+ mContextTreeModel->setCurrentDirectory(item);
QMenu context_menu;
diff --git a/plugins/gui/src/context_manager_widget/models/context_proxy_model.cpp b/plugins/gui/src/context_manager_widget/models/context_proxy_model.cpp
index 846b59b9488..4004a4bef64 100644
--- a/plugins/gui/src/context_manager_widget/models/context_proxy_model.cpp
+++ b/plugins/gui/src/context_manager_widget/models/context_proxy_model.cpp
@@ -13,7 +13,7 @@ namespace hal
bool ContextProxyModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
{
- return checkRow(source_row, source_parent, 0, 1);
+ return checkRowRecursion(source_row, source_parent, 0, 1);
}
bool ContextProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
diff --git a/plugins/gui/src/context_manager_widget/models/context_tree_model.cpp b/plugins/gui/src/context_manager_widget/models/context_tree_model.cpp
index b1d1ba1ed2c..38490034369 100644
--- a/plugins/gui/src/context_manager_widget/models/context_tree_model.cpp
+++ b/plugins/gui/src/context_manager_widget/models/context_tree_model.cpp
@@ -288,6 +288,7 @@ namespace hal
}
QList childCopy = item->getChildren();
+
for (int i = 0; i < childCopy.length(); i++) {
ContextTreeItem* child = static_cast(childCopy[i]);
@@ -304,7 +305,7 @@ namespace hal
}
- ContextTreeItem* parent = static_cast(item->getParent());
+ BaseTreeItem* parent = item->getParent();
assert(item);
assert(parent);
diff --git a/plugins/gui/src/docking_system/splitter_anchor.cpp b/plugins/gui/src/docking_system/splitter_anchor.cpp
index 996ef138e21..5500e80a87f 100644
--- a/plugins/gui/src/docking_system/splitter_anchor.cpp
+++ b/plugins/gui/src/docking_system/splitter_anchor.cpp
@@ -95,7 +95,7 @@ namespace hal
mDockBar->uncheckButton(widget);
}
- int SplitterAnchor::count()
+ int SplitterAnchor::count() const
{
return mDockBar->count();
}
diff --git a/plugins/gui/src/docking_system/tab_widget.cpp b/plugins/gui/src/docking_system/tab_widget.cpp
index 15602f4f18f..1934b53b9ef 100644
--- a/plugins/gui/src/docking_system/tab_widget.cpp
+++ b/plugins/gui/src/docking_system/tab_widget.cpp
@@ -201,4 +201,9 @@ namespace hal
if (mDockBar->unused())
hide();
}
+
+ int TabWidget::count() const
+ {
+ return mDockBar->count();
+ }
}
diff --git a/plugins/gui/src/graph_widget/contexts/graph_context.cpp b/plugins/gui/src/graph_widget/contexts/graph_context.cpp
index 75bf0042e8b..4b9a7866b8c 100644
--- a/plugins/gui/src/graph_widget/contexts/graph_context.cpp
+++ b/plugins/gui/src/graph_widget/contexts/graph_context.cpp
@@ -321,6 +321,16 @@ namespace hal
return contextGates == moduleGates && contextModules == moduleModules;
}
+
+ bool GraphContext::isShowingFoldedTopModule() const
+ {
+ auto contextGates = (mGates - mRemovedGates) + mAddedGates;
+ if (!contextGates.isEmpty()) return false;
+ auto contextModules = (mModules - mRemovedModules) + mAddedModules;
+ if (contextModules.size() != 1) return false;
+ return (*mModules.constBegin() == 1); // top_module has ID=1
+ }
+
void GraphContext::getModuleChildrenRecursively(const u32 id, QSet* gates, QSet* modules) const
{
diff --git a/plugins/gui/src/graph_widget/drag_controller.cpp b/plugins/gui/src/graph_widget/drag_controller.cpp
new file mode 100644
index 00000000000..d84e1a493f2
--- /dev/null
+++ b/plugins/gui/src/graph_widget/drag_controller.cpp
@@ -0,0 +1,234 @@
+#include "gui/graph_widget/drag_controller.h"
+#include "gui/graph_widget/graph_widget.h"
+#include "gui/graph_widget/contexts/graph_context.h"
+#include "gui/graph_widget/graphics_scene.h"
+#include
+#include
+
+namespace hal {
+ DragController::DragController(GraphWidget* gw, QObject *parent)
+ : QObject(parent), mGraphWidget(gw), mDragNodeBox(nullptr), mShadowScene(nullptr)
+ {;}
+
+ void DragController::clear()
+ {
+ mDragNodeBox = nullptr;
+ mAdditionalBoxes.clear();
+ mDropAllowed = false;
+ mWantSwap = false;
+ GraphicsScene* sc = mGraphWidget->getContext()->getLayouter()->scene();
+ clearShadows(sc);
+ }
+
+ void DragController::clearShadows(GraphicsScene *sc)
+ {
+ if (sc && sc == mShadowScene)
+ {
+ // otherwise (if old scene deleted) items owned by scene already removed
+ for (NodeDragShadow* nds : mShadows.values())
+ {
+ sc->removeItem(nds);
+ delete nds;
+ }
+ mShadowScene->setDragController(nullptr);
+ }
+ mShadows.clear();
+ mShadowScene = nullptr;
+ }
+
+ NodeDragShadow::DragCue DragController::dragCue() const
+ {
+ if (!mDropAllowed)
+ return NodeDragShadow::DragCue::Rejected;
+ if (mWantSwap)
+ return NodeDragShadow::DragCue::Swappable;
+ return NodeDragShadow::DragCue::Movable;
+ }
+
+ void DragController::set(GraphicsNode *drgItem, const QPoint &eventPos)
+ {
+ clear();
+ if (!drgItem) return;
+ // TODO: swap modifier -> deselect all but current
+
+ QSet nodesToMove;
+ QSet selGats = gSelectionRelay->selectedGates();
+ QSet selMods = gSelectionRelay->selectedModules();
+ bool isAlreadySelected = false;
+
+ switch (drgItem->itemType())
+ {
+ case ItemType::Module:
+ nodesToMove.insert(Node(drgItem->id(),Node::Module));
+ if (selMods.contains(drgItem->id())) isAlreadySelected = true;
+ break;
+ case ItemType::Gate:
+ nodesToMove.insert(Node(drgItem->id(),Node::Gate));
+ if (selGats.contains(drgItem->id())) isAlreadySelected = true;
+ break;
+ default:
+ break;
+ }
+
+ if (isAlreadySelected)
+ {
+ // multi-select requires that drag node was already selected before
+ for (u32 mid : selMods)
+ {
+ nodesToMove.insert(Node(mid,Node::Module));
+ }
+ for (u32 gid : selGats)
+ {
+ nodesToMove.insert(Node(gid,Node::Gate));
+ }
+ }
+
+ auto context = mGraphWidget->getContext();
+ const GraphLayouter* layouter = context->getLayouter();
+ if (!layouter->done()) return;
+
+ mMousedownPosition = eventPos;
+
+ for (const Node& nd : nodesToMove)
+ {
+ NodeBox* nb = layouter->boxes().boxForNode(nd);
+ if (!nb) continue;
+ if (nb->item() == drgItem)
+ mDragNodeBox = nb;
+ else
+ mAdditionalBoxes.insert(nb);
+ }
+
+ if (!mAdditionalBoxes.isEmpty()) mWantSwap = false;
+ }
+
+ void DragController::setSwapIntent(bool wantSwap)
+ {
+ if (wantSwap == mWantSwap) return;
+ if (wantSwap)
+ {
+ GraphicsScene* sc = mGraphWidget->getContext()->getLayouter()->scene();
+ if (sc && sc == mShadowScene)
+ {
+ for (NodeBox* nb : mAdditionalBoxes)
+ {
+ NodeDragShadow* nds = mShadows.value(nb);
+ if (nds)
+ {
+ sc->removeItem(nds);
+ mShadows.remove(nb);
+ delete nds;
+ }
+ }
+ }
+ mAdditionalBoxes.clear();
+ }
+ mWantSwap = wantSwap;
+ }
+
+ void DragController::addShadow(const NodeBox* nb)
+ {
+ NodeDragShadow* nds = new NodeDragShadow;
+ nds->setVisualCue(dragCue());
+ nds->start(nb->item()->pos(), nb->item()->boundingRect().size());
+ mShadowScene = mGraphWidget->getContext()->getLayouter()->scene();
+ if (mShadowScene)
+ {
+ mShadowScene->setDragController(this);
+ mShadowScene->addItem(nds);
+ mShadows.insert(nb,nds);
+ }
+ else
+ delete nds;
+ }
+
+ void DragController::enterDrag(bool wantSwap)
+ {
+ if (!mDragNodeBox) return;
+ setSwapIntent(wantSwap);
+ mCurrentGridpos = mDragNodeBox->gridPosition();
+ mDropAllowed = false;
+ addShadow(mDragNodeBox);
+ for (NodeBox* nb : mAdditionalBoxes)
+ addShadow(nb);
+ }
+
+ void DragController::move(const QPoint& eventPos, bool wantSwap, const QPoint& gridPos)
+ {
+ Q_UNUSED(eventPos);
+ if (!mDragNodeBox || (wantSwap == mWantSwap && gridPos == mCurrentGridpos)) return;
+
+ setSwapIntent(wantSwap);
+ mCurrentGridpos = gridPos;
+ mDropAllowed = isDropAllowed();
+
+ QPoint delta = mCurrentGridpos - mDragNodeBox->gridPosition();
+ for (auto it = mShadows.constBegin(); it != mShadows.constEnd(); ++it)
+ {
+ it.value()->setVisualCue(dragCue());
+ QPoint p = it.key()->gridPosition() + delta;
+ float x = mGraphWidget->getContext()->getLayouter()->gridXposition(p.x());
+ float y = mGraphWidget->getContext()->getLayouter()->gridYposition(p.y());
+ it.value()->setPos(QPointF(x,y));
+ }
+ }
+
+ bool DragController::hasDragged(const QPoint &eventPos)
+ {
+ if (!mDragNodeBox) return false;
+ return (eventPos - mMousedownPosition).manhattanLength() >= QApplication::startDragDistance();
+ }
+
+ bool DragController::isDropAllowed() const
+ {
+ if (!mDragNodeBox) return false;
+ if (mDragNodeBox->gridPosition() == mCurrentGridpos) return false;
+ const NodeBoxes& boxes = mGraphWidget->getContext()->getLayouter()->boxes();
+
+ if (mWantSwap)
+ {
+ return (boxes.boxForPoint(mCurrentGridpos) != nullptr);
+ }
+
+ QList pointsToCheck;
+ QSet freedPositions;
+ pointsToCheck.append(mCurrentGridpos);
+ freedPositions.insert(mDragNodeBox->gridPosition());
+
+ QPoint delta = mCurrentGridpos - mDragNodeBox->gridPosition();
+ for (const NodeBox* nb : mAdditionalBoxes)
+ {
+ pointsToCheck.append(nb->gridPosition() + delta);
+ freedPositions.insert(nb->gridPosition());
+ }
+
+ for (const QPoint& p : pointsToCheck)
+ {
+ if (freedPositions.contains(p)) continue;
+ if (boxes.boxForPoint(p) != nullptr) return false;
+ }
+ return true;
+ }
+
+ GridPlacement *DragController::finalGridPlacement() const
+ {
+ GridPlacement* retval = mGraphWidget->getContext()->getLayouter()->gridPlacementFactory();
+ retval->operator[](mDragNodeBox->getNode()) = mCurrentGridpos;
+ if (mWantSwap)
+ {
+ Node targetNode = mGraphWidget->getContext()->getLayouter()->nodeAtPosition(mCurrentGridpos);
+ if (!targetNode.isNull())
+ retval->operator[](targetNode) = mDragNodeBox->gridPosition();
+ return retval;
+ }
+ if (!mAdditionalBoxes.isEmpty())
+ {
+ QPoint delta = mCurrentGridpos - mDragNodeBox->gridPosition();
+ for (const NodeBox* nb : mAdditionalBoxes)
+ {
+ retval->operator[](nb->getNode()) = nb->gridPosition() + delta;
+ }
+ }
+ return retval;
+ }
+}
diff --git a/plugins/gui/src/graph_widget/graph_context_manager.cpp b/plugins/gui/src/graph_widget/graph_context_manager.cpp
index faa1ccbc928..1198551ad57 100644
--- a/plugins/gui/src/graph_widget/graph_context_manager.cpp
+++ b/plugins/gui/src/graph_widget/graph_context_manager.cpp
@@ -30,8 +30,17 @@ namespace hal
"Appearance:Graph View",
"If set net grouping colors are also applied to input and output pins of gates");
- GraphContextManager::GraphContextManager() : mContextTreeModel(new ContextTreeModel()), mMaxContextId(0)
+ SettingsItemCheckbox* GraphContextManager::sSettingPanOnMiddleButton = new SettingsItemCheckbox("Pan with Middle Mouse Button",
+ "graph_view/pan_middle_button",
+ false,
+ "Graph View",
+ "If enabled middle mouse button will pan the graphics.\n"
+ "If disabled middle mouse button can be used for rubber band selection.");
+
+ GraphContextManager::GraphContextManager()
+ : mMaxContextId(0)
{
+ mContextTreeModel = new ContextTreeModel(this);
mSettingDebugGrid = new SettingsItemCheckbox("GUI Debug Grid",
"debug/grid",
false,
@@ -276,6 +285,7 @@ namespace hal
for (GraphContext* context : mContextTreeModel->list())
{
+ if (context->isShowingFoldedTopModule()) continue;
if (context->isShowingModule(m->get_id(), {added_module}, {}, {}, {}) && !context->isShowingModule(added_module, {}, {}, {}, {}))
context->add({added_module}, {});
else
@@ -310,6 +320,7 @@ namespace hal
for (GraphContext* context : mContextTreeModel->list())
{
+ if (context->isShowingFoldedTopModule()) continue;
if (context->isScheduledRemove(Node(removed_module,Node::Module)) ||
context->isShowingModule(m->get_id(), {}, {}, {removed_module}, {}))
context->remove({removed_module}, {});
@@ -336,6 +347,7 @@ namespace hal
for (GraphContext* context : mContextTreeModel->list())
{
+ if (context->isShowingFoldedTopModule()) continue;
if (context->isShowingModule(m->get_id(), {}, {inserted_gate}, {}, {}))
context->add({}, {inserted_gate});
else
@@ -360,6 +372,7 @@ namespace hal
// dump("ModuleGateRemoved", m->get_id(), removed_gate);
for (GraphContext* context : mContextTreeModel->list())
{
+ if (context->isShowingFoldedTopModule()) continue;
if (context->isScheduledRemove(Node(removed_gate,Node::Gate)) ||
context->isShowingModule(m->get_id(), {}, {}, {}, {removed_gate}))
{
@@ -417,8 +430,10 @@ namespace hal
xout << "-------\n";
}
- void GraphContextManager::handleModulePortsChanged(Module* m)
+ void GraphContextManager::handleModulePortsChanged(Module* m, PinEvent pev, u32 pgid)
{
+ Q_UNUSED(pev);
+ Q_UNUSED(pgid);
for (GraphContext* context : mContextTreeModel->list())
if (context->modules().contains(m->get_id()))
{
diff --git a/plugins/gui/src/graph_widget/graph_graphics_view.cpp b/plugins/gui/src/graph_widget/graph_graphics_view.cpp
index 069fe6bbed7..038b6a6d606 100644
--- a/plugins/gui/src/graph_widget/graph_graphics_view.cpp
+++ b/plugins/gui/src/graph_widget/graph_graphics_view.cpp
@@ -2,6 +2,7 @@
#include "gui/comment_system/comment_speech_bubble.h"
#include "gui/graph_widget/contexts/graph_context.h"
+#include "gui/graph_widget/drag_controller.h"
#include "gui/graph_widget/graph_widget.h"
#include "gui/graph_widget/graph_widget_constants.h"
#include "gui/graph_widget/graphics_scene.h"
@@ -15,6 +16,7 @@
#include "gui/content_manager/content_manager.h"
#include "gui/context_manager_widget/context_manager_widget.h"
#include "gui/graph_tab_widget/graph_tab_widget.h"
+#include "gui/graph_widget/graph_context_manager.h"
#include "gui/grouping/grouping_manager_widget.h"
#include "gui/grouping/grouping_table_model.h"
#include "gui/grouping_dialog/grouping_dialog.h"
@@ -38,6 +40,7 @@
#include "gui/module_dialog/module_dialog.h"
#include "gui/module_dialog/gate_dialog.h"
#include "gui/comment_system/widgets/comment_dialog.h"
+#include "gui/settings/settings_items/settings_item_checkbox.h"
#include "hal_core/netlist/gate.h"
#include "hal_core/netlist/grouping.h"
#include "hal_core/netlist/module.h"
@@ -75,6 +78,7 @@ namespace hal
: QGraphicsView(parent), mGraphWidget(parent),
mMinimapEnabled(false), mGridEnabled(true), mGridClustersEnabled(true),
mGridType(GraphicsScene::GridType::Dots),
+ mDragController(new DragController(mGraphWidget,this)),
mDragModifier(Qt::KeyboardModifier::AltModifier),
mPanModifier(Qt::KeyboardModifier::ShiftModifier),
mZoomModifier(Qt::NoModifier),
@@ -381,23 +385,21 @@ namespace hal
if(dynamic_cast(itemAt(event->pos())))
return;
- if (event->modifiers() == mPanModifier)
+ if ((event->modifiers() == mPanModifier && event->button() == Qt::LeftButton) ||
+ (event->button() == Qt::MidButton && gGraphContextManager->sSettingPanOnMiddleButton->value().toBool()))
{
- if (event->button() == Qt::LeftButton)
- mMovePosition = event->pos();
+ mMovePosition = event->pos();
}
else if (event->button() == Qt::LeftButton)
{
- GraphicsItem* item = static_cast(itemAt(event->pos()));
+ GraphicsNode* item = dynamic_cast(itemAt(event->pos()));
if (item && itemDraggable(item))
{
- mDragItem = static_cast(item);
- mDragMousedownPosition = event->pos();
- mDragStartGridpos = closestLayouterPos(mapToScene(mDragMousedownPosition)).first;
+ mDragController->set(item, event->pos());
}
else
{
- mDragItem = nullptr;
+ mDragController->clear();
}
// we still need the normal mouse logic for single clicks
@@ -435,32 +437,30 @@ namespace hal
mTargetScenePos = mapToScene(event->pos());
}
- if (event->buttons().testFlag(Qt::LeftButton))
+ if ((event->buttons().testFlag(Qt::LeftButton) && event->modifiers() == mPanModifier) ||
+ (event->buttons().testFlag(Qt::MidButton) && gGraphContextManager->sSettingPanOnMiddleButton->value().toBool()))
{
- if (event->modifiers() == mPanModifier)
- {
- QScrollBar* hBar = horizontalScrollBar();
- QScrollBar* vBar = verticalScrollBar();
- QPoint delta_move = event->pos() - mMovePosition;
- mMovePosition = event->pos();
- hBar->setValue(hBar->value() + (isRightToLeft() ? delta_move.x() : -delta_move.x()));
- vBar->setValue(vBar->value() - delta_move.y());
- }
- else
+ QScrollBar* hBar = horizontalScrollBar();
+ QScrollBar* vBar = verticalScrollBar();
+ QPoint delta_move = event->pos() - mMovePosition;
+ mMovePosition = event->pos();
+ hBar->setValue(hBar->value() + (isRightToLeft() ? delta_move.x() : -delta_move.x()));
+ vBar->setValue(vBar->value() - delta_move.y());
+ }
+ else if (event->buttons().testFlag(Qt::LeftButton))
+ {
+ if (mDragController->hasDragged(event->pos()))
{
- if (mDragItem && (event->pos() - mDragMousedownPosition).manhattanLength() >= QApplication::startDragDistance())
- {
- QDrag* drag = new QDrag(this);
- QMimeData* mimeData = new QMimeData;
+ QDrag* drag = new QDrag(this);
+ QMimeData* mimeData = new QMimeData;
- // TODO set MIME type and icon
- mimeData->setText("dragTest");
- drag->setMimeData(mimeData);
- // drag->setPixmap(iconPixmap);
+ // TODO set MIME type and icon
+ mimeData->setText("dragTest");
+ drag->setMimeData(mimeData);
+ // drag->setPixmap(iconPixmap);
- // enable DragMoveEvents until mouse released
- drag->exec(Qt::MoveAction);
- }
+ // enable DragMoveEvents until mouse released
+ drag->exec(Qt::MoveAction);
}
}
#ifdef GUI_DEBUG_GRID
@@ -474,21 +474,8 @@ namespace hal
{
if (event->source() == this && event->proposedAction() == Qt::MoveAction)
{
+ mDragController->enterDrag(event->keyboardModifiers() == mDragModifier);
event->acceptProposedAction();
- QSizeF size(mDragItem->width(), mDragItem->height());
- QPointF mouse = event->posF();
- QPointF snap = closestLayouterPos(mapToScene(mouse.x(), mouse.y())).second;
- if (gSelectionRelay->numberSelectedGates() > 1)
- {
- // if we are in multi-select mode, reduce the selection to the
- // item we are dragging
- gSelectionRelay->clear();
- gSelectionRelay->addGate(mDragItem->id());
- gSelectionRelay->setFocus(SelectionRelay::ItemType::Gate,mDragItem->id());
- gSelectionRelay->relaySelectionChanged(nullptr);
- }
- mDropAllowed = false;
- static_cast(scene())->startDragShadow(snap, size, NodeDragShadow::DragCue::Rejected);
}
else
{
@@ -500,53 +487,49 @@ namespace hal
void GraphGraphicsView::dragLeaveEvent(QDragLeaveEvent* event)
{
Q_UNUSED(event)
- if (scene()) static_cast(scene())->stopDragShadow();
+ mDragController->clear();
+ }
+
+ void GraphGraphicsView::dragPan(float dpx, float dpy)
+ {
+ if (dpx != 0)
+ {
+ QScrollBar* hBar = horizontalScrollBar();
+ int hValue = hBar->value() + 10*dpx;
+ if (hValue < hBar->minimum()) hBar->setMinimum(hValue);
+ if (hValue > hBar->maximum()) hBar->setMaximum(hValue);
+ hBar->setValue(hValue);
+ }
+ if (dpy != 0)
+ {
+ QScrollBar* vBar = verticalScrollBar();
+ int vValue = vBar->value() + 10*dpy;
+ if (vValue < vBar->minimum()) vBar->setMinimum(vValue);
+ if (vValue > vBar->maximum()) vBar->setMaximum(vValue);
+ vBar->setValue(vValue);
+ }
}
void GraphGraphicsView::dragMoveEvent(QDragMoveEvent* event)
{
if (event->source() == this && event->proposedAction() == Qt::MoveAction)
{
- bool swapModifier = event->keyboardModifiers() == mDragModifier;
QPair snap = closestLayouterPos(mapToScene(event->pos()));
- if (snap.first == mDragCurrentGridpos && swapModifier == mDragCurrentModifier)
- {
- return;
- }
- mDragCurrentGridpos = snap.first;
- mDragCurrentModifier = swapModifier;
-
- auto context = mGraphWidget->getContext();
- const GraphLayouter* layouter = context->getLayouter();
- assert(layouter->done()); // ensure grid stable
-
- QMap::const_iterator node_iter = layouter->positionToNodeMap().find(snap.first);
-
- NodeDragShadow::DragCue cue = NodeDragShadow::DragCue::Rejected;
- // disallow dropping an item on itself
- if (snap.first != mDragStartGridpos)
- {
- if (swapModifier)
- {
- if (node_iter != layouter->positionToNodeMap().end())
- {
- // allow move only on empty cells
- cue = NodeDragShadow::DragCue::Swappable;
- }
- }
- else
- {
- if (node_iter == layouter->positionToNodeMap().end())
- {
- // allow move only on empty cells
- cue = NodeDragShadow::DragCue::Movable;
- }
- }
- }
- mDropAllowed = (cue != NodeDragShadow::DragCue::Rejected);
-
- static_cast(scene())->moveDragShadow(snap.second, cue);
+ mDragController->move(event->pos(),event->keyboardModifiers() == mDragModifier,snap.first);
+
+ QPoint p = event->pos() - viewport()->geometry().topLeft();
+ float rx = 100. * p.x() / viewport()->geometry().width();
+ float ry = 100. * p.y() / viewport()->geometry().height();
+// qDebug() << "move it" << event->pos() << viewport()->geometry() << rx << ry;
+ float dpx = 0;
+ float dpy = 0;
+ if (rx < 10) dpx = -10+rx;
+ if (rx > 90) dpx = rx-90;
+ if (ry < 10) dpy = -10+ry;
+ if (ry > 90) dpy = ry-90;
+ if (dpx !=0 || dpy != 0)
+ dragPan(dpx, dpy);
}
}
@@ -555,36 +538,23 @@ namespace hal
if (event->source() == this && event->proposedAction() == Qt::MoveAction)
{
event->acceptProposedAction();
- GraphicsScene* s = static_cast(scene());
- if (s) s->stopDragShadow();
- if (mDropAllowed)
+ if (mDragController->isDropAllowed())
{
- auto context = mGraphWidget->getContext();
+ GridPlacement* plc = mDragController->finalGridPlacement();
+ GraphContext* context = mGraphWidget->getContext();
GraphLayouter* layouter = context->getLayouter();
assert(layouter->done()); // ensure grid stable
-
- // convert scene coordinates into layouter grid coordinates
- QPointF targetPos = s->dropTarget();
- QPoint targetLayouterPos = closestLayouterPos(targetPos).first;
- QPoint sourceLayouterPos = layouter->gridPointByItem(mDragItem);
-
- if (targetLayouterPos == sourceLayouterPos)
- {
- qDebug() << "Attempted to drop gate onto itself, this should never happen!";
- return;
- }
- // assert(targetLayouterPos != sourceLayouterPos);
-
- bool modifierPressed = event->keyboardModifiers() == mDragModifier;
- ActionMoveNode* act = new ActionMoveNode(context->id(), sourceLayouterPos, targetLayouterPos, modifierPressed);
+ ActionMoveNode* act = new ActionMoveNode(context->id(),plc);
if (act->exec())
context->setDirty(true);
+ delete plc;
}
}
else
{
QGraphicsView::dropEvent(event);
}
+ mDragController->clear();
}
void GraphGraphicsView::wheelEvent(QWheelEvent* event)
diff --git a/plugins/gui/src/graph_widget/graphics_scene.cpp b/plugins/gui/src/graph_widget/graphics_scene.cpp
index 78d40b965d3..1525a2a7fa1 100644
--- a/plugins/gui/src/graph_widget/graphics_scene.cpp
+++ b/plugins/gui/src/graph_widget/graphics_scene.cpp
@@ -7,6 +7,7 @@
#include "gui/graph_widget/graph_widget_constants.h"
#include "gui/graph_widget/graphics_factory.h"
+#include "gui/graph_widget/drag_controller.h"
#include "gui/graph_widget/items/nodes/gates/graphics_gate.h"
#include "gui/graph_widget/items/graphics_item.h"
#include "gui/graph_widget/items/nodes/modules/graphics_module.h"
@@ -74,23 +75,24 @@ namespace hal
}
GraphicsScene::GraphicsScene(QObject* parent) : QGraphicsScene(parent),
- mDragShadowGate(new NodeDragShadow()), mDebugGridEnable(false),
+ mDebugGridEnable(false),
+ mDragController(nullptr),
mSelectionStatus(NotPressed)
{
// FIND OUT IF MANUAL CHANGE TO DEPTH IS NECESSARY / INCREASES PERFORMANCE
//mScene.setBspTreeDepth(10);
-
gSelectionRelay->registerSender(this, "GraphView");
connectAll();
- QGraphicsScene::addItem(mDragShadowGate);
connect(gGraphContextManager->sSettingNetGroupingToPins,&SettingsItem::valueChanged,this,&GraphicsScene::updateAllItems);
}
GraphicsScene::~GraphicsScene()
{
disconnect(this, &QGraphicsScene::selectionChanged, this, &GraphicsScene::handleInternSelectionChanged);
+ if (mDragController) mDragController->clearShadows(this);
+
for (QGraphicsItem* gi : items())
{
removeItem(gi);
@@ -98,26 +100,9 @@ namespace hal
}
}
- void GraphicsScene::startDragShadow(const QPointF& posF, const QSizeF& sizeF, const NodeDragShadow::DragCue cue)
- {
- mDragShadowGate->setVisualCue(cue);
- mDragShadowGate->start(posF, sizeF);
- }
-
- void GraphicsScene::moveDragShadow(const QPointF& posF, const NodeDragShadow::DragCue cue)
+ void GraphicsScene::setDragController(DragController* dc)
{
- mDragShadowGate->setPos(posF);
- mDragShadowGate->setVisualCue(cue);
- }
-
- void GraphicsScene::stopDragShadow()
- {
- mDragShadowGate->stop();
- }
-
- QPointF GraphicsScene::dropTarget()
- {
- return mDragShadowGate->pos();
+ mDragController = dc;
}
void GraphicsScene::addGraphItem(GraphicsItem* item)
@@ -330,16 +315,11 @@ namespace hal
void GraphicsScene::deleteAllItems()
{
- // this breaks the mDragShadowGate
- // clear();
- // so we do this instead
- // TODO check performance hit
+ if (mDragController) mDragController->clearShadows(this);
+
for (auto item : items())
{
- if (item != mDragShadowGate)
- {
- removeItem(item);
- }
+ removeItem(item);
}
mModuleItems.clear();
@@ -375,10 +355,14 @@ namespace hal
void GraphicsScene::setMousePressed(bool isPressed)
{
if (isPressed)
- mSelectionStatus = BeginPressed;
+ {
+ // internal selection changed event might fire before mouse pressed event
+ if (mSelectionStatus != SelectionChanged)
+ mSelectionStatus = BeginPressed;
+ }
else
{
- // not pressed ...
+ // released ...
if (mSelectionStatus == SelectionChanged)
{
mSelectionStatus = EndPressed;
@@ -388,6 +372,7 @@ namespace hal
}
}
+
void GraphicsScene::handleInternSelectionChanged()
{
switch (mSelectionStatus)
diff --git a/plugins/gui/src/graph_widget/items/nets/labeled_separated_net.cpp b/plugins/gui/src/graph_widget/items/nets/labeled_separated_net.cpp
index f21fd6c73be..b1edadd74f0 100644
--- a/plugins/gui/src/graph_widget/items/nets/labeled_separated_net.cpp
+++ b/plugins/gui/src/graph_widget/items/nets/labeled_separated_net.cpp
@@ -32,6 +32,9 @@ namespace hal
LabeledSeparatedNet::LabeledSeparatedNet(Net* n, const QString& text) : SeparatedGraphicsNet(n),
mText(text)
{
+ int ipos = mText.lastIndexOf('/');
+ if (ipos >= 0)
+ mText = mText.mid(ipos+1);
QFontMetricsF fm(sFont);
mTextWidth = fm.width(mText);
}
diff --git a/plugins/gui/src/graph_widget/items/utility_items/node_drag_shadow.cpp b/plugins/gui/src/graph_widget/items/utility_items/node_drag_shadow.cpp
index 60f746f9d47..63ec05fa826 100644
--- a/plugins/gui/src/graph_widget/items/utility_items/node_drag_shadow.cpp
+++ b/plugins/gui/src/graph_widget/items/utility_items/node_drag_shadow.cpp
@@ -8,6 +8,7 @@
#include
#include
#include
+#include
namespace hal
{
@@ -36,29 +37,21 @@ namespace hal
sPen.setJoinStyle(Qt::MiterJoin);
}
- NodeDragShadow::NodeDragShadow() : QGraphicsObject()
+ NodeDragShadow::NodeDragShadow()
+ : QGraphicsItem(), mRect(0,0,100,100)
{
- hide();
-
setAcceptedMouseButtons(0);
- mWidth = 100;
- mHeight = 100;
}
void NodeDragShadow::start(const QPointF& posF, const QSizeF& sizeF)
{
+ mRect = QRectF(QPointF(0,0),sizeF);
setPos(posF);
- setWidth(sizeF.width());
- setHeight(sizeF.height());
setZValue(1);
show();
}
- void NodeDragShadow::stop()
- {
- hide();
- }
-
+ /*
qreal NodeDragShadow::width() const
{
return mWidth;
@@ -83,6 +76,7 @@ namespace hal
{
mHeight = height;
}
+*/
void NodeDragShadow::setLod(const qreal lod)
{
@@ -108,25 +102,25 @@ namespace hal
if (sLod < 0.5)
{
- painter->fillRect(QRectF(0, 0, mWidth, mHeight), sColorSolid[color_index]);
+
+ painter->fillRect(mRect, sColorSolid[color_index]);
}
else
{
- QRectF rect = QRectF(0, 0, mWidth, mHeight);
- painter->drawRect(rect);
- painter->fillRect(rect, sColorTranslucent[color_index]);
+ painter->drawRect(mRect);
+ painter->fillRect(mRect, sColorTranslucent[color_index]);
}
}
QRectF NodeDragShadow::boundingRect() const
{
- return QRectF(0, 0, mWidth, mHeight);
+ return mRect;
}
QPainterPath NodeDragShadow::shape() const
{
QPainterPath path;
- path.addRect(QRectF(0, 0, mWidth, mHeight));
+ path.addRect(mRect);
return path;
}
}
diff --git a/plugins/gui/src/graph_widget/layout_locker.cpp b/plugins/gui/src/graph_widget/layout_locker.cpp
index 70082902bdb..e2bf1f46bb2 100644
--- a/plugins/gui/src/graph_widget/layout_locker.cpp
+++ b/plugins/gui/src/graph_widget/layout_locker.cpp
@@ -1,4 +1,5 @@
#include "gui/graph_widget/layout_locker.h"
+#include "gui/gui_globals.h"
#include "gui/graph_widget/contexts/graph_context.h"
namespace hal {
@@ -22,24 +23,29 @@ namespace hal {
void LayoutLockerManager::removeLock()
{
--mLockCount;
+
if (mLockCount <= 0 && !mWaitingRoom.isEmpty())
{
- for (GraphContext* ctx : mWaitingRoom)
- ctx->startSceneUpdate();
+ for (u32 ctxId : mWaitingRoom)
+ {
+ GraphContext* ctx = gGraphContextManager->getContextById(ctxId);
+ if (ctx) ctx->startSceneUpdate();
+ }
mWaitingRoom.clear();
}
}
bool LayoutLockerManager::canUpdate(GraphContext* ctx)
{
+ if (!ctx) return false;
if (mLockCount <= 0) return true;
- mWaitingRoom.insert(ctx);
+ mWaitingRoom.insert(ctx->id());
return false;
}
void LayoutLockerManager::removeWaitingContext(GraphContext* ctx)
{
- auto it = mWaitingRoom.find(ctx);
+ auto it = mWaitingRoom.find(ctx->id());
if (it != mWaitingRoom.end())
mWaitingRoom.erase(it);
}
diff --git a/plugins/gui/src/graph_widget/layouters/graph_layouter.cpp b/plugins/gui/src/graph_widget/layouters/graph_layouter.cpp
index dae127f6260..ae6eee941ee 100644
--- a/plugins/gui/src/graph_widget/layouters/graph_layouter.cpp
+++ b/plugins/gui/src/graph_widget/layouters/graph_layouter.cpp
@@ -68,6 +68,19 @@ namespace hal
return mNodeToPositionMap;
}
+ GridPlacement *GraphLayouter::gridPlacementFactory() const
+ {
+ GridPlacement* retval = new GridPlacement();
+ for (auto it=mNodeToPositionMap.constBegin(); it!=mNodeToPositionMap.constEnd(); ++it)
+ retval->insert(it.key(),it.value());
+ return retval;
+ }
+
+ Node GraphLayouter::nodeAtPosition(const QPoint& p) const
+ {
+ return mPositionToNodeMap.value(p);
+ }
+
NetLayoutPoint GraphLayouter::positonForNode(const Node& nd) const
{
if (nd.isNull()) return NetLayoutPoint();
@@ -194,10 +207,10 @@ namespace hal
Q_ASSERT(!mXValues.isEmpty());
int inx = ix - mMinXIndex;
if (inx < 0)
- return mXValues[0] - inx * defaultGridWidth();
+ return mXValues[0] + inx * defaultGridWidth();
if (inx < mXValues.size())
return mXValues[inx];
- return mXValues.last() + (inx - mXValues.size() - 1) * defaultGridWidth();
+ return mXValues.last() + (inx - mXValues.size() + 1) * defaultGridWidth();
}
qreal GraphLayouter::gridYposition(int iy) const
@@ -205,10 +218,10 @@ namespace hal
Q_ASSERT(!mYValues.isEmpty());
int inx = iy - mMinYIndex;
if (inx < 0)
- return mYValues[0] - inx * defaultGridHeight();
+ return mYValues[0] + inx * defaultGridHeight();
if (inx < mYValues.size())
return mYValues[inx];
- return mYValues.last() + (inx - mYValues.size() - 1) * defaultGridHeight();
+ return mYValues.last() + (inx - mYValues.size() + 1) * defaultGridHeight();
}
void GraphLayouter::layout()
@@ -1362,14 +1375,14 @@ namespace hal
// netjunction -> endpoint
auto itEpc = mLayouter->mEndpointHash.find(wToPoint);
y0 = mLayouter->mCoordArrayY->lanePosition(iy0, j0? j0->rect().bottom() : 0);
- y1 = itEpc != mLayouter->mEndpointHash.constEnd() ? itEpc.value().lanePosition(j1->rect().top(), true)
+ y1 = itEpc != mLayouter->mEndpointHash.constEnd() ? itEpc.value().lanePosition(j1 ? j1->rect().top() : 0, true)
: mLayouter->mCoordArrayY->lanePosition(iy1,0);
}
else
{
// endpoint -> netjunction
auto itEpc = mLayouter->mEndpointHash.find(wFromPoint);
- y0 = itEpc != mLayouter->mEndpointHash.constEnd() ? itEpc.value().lanePosition(j0->rect().bottom(), true)
+ y0 = itEpc != mLayouter->mEndpointHash.constEnd() ? itEpc.value().lanePosition(j0 ? j0->rect().bottom() : 0, true)
: mLayouter->mCoordArrayY->lanePosition(iy0,0);
y1 = mLayouter->mCoordArrayY->lanePosition(iy1, j1? j1->rect().top() : 0);
}
diff --git a/plugins/gui/src/grouping/grouping_manager_widget.cpp b/plugins/gui/src/grouping/grouping_manager_widget.cpp
index 7c1354457b1..ecd13b1b3ae 100644
--- a/plugins/gui/src/grouping/grouping_manager_widget.cpp
+++ b/plugins/gui/src/grouping/grouping_manager_widget.cpp
@@ -503,6 +503,11 @@ namespace hal
// Replace InputDialog with SelectionTreeView
SelectionTreeView* selectionTreeView = new SelectionTreeView(&dialog, true);
+ SelectionTreeModel* selectionTreeModel = new SelectionTreeModel(this); // Need to fully initialise SelectionTreeView with a model
+ SelectionTreeProxyModel* selectionTreeProxyModel = new SelectionTreeProxyModel(this);
+ selectionTreeProxyModel->setSourceModel(selectionTreeModel);
+ selectionTreeView->setModel(selectionTreeProxyModel);
+
selectionTreeView->populate(true, grpId);
QPushButton* closeButton = new QPushButton("Close", &dialog);
diff --git a/plugins/gui/src/gui_api/gui_api.cpp b/plugins/gui/src/gui_api/gui_api.cpp
index c7d8016387d..b29d5103e38 100644
--- a/plugins/gui/src/gui_api/gui_api.cpp
+++ b/plugins/gui/src/gui_api/gui_api.cpp
@@ -87,7 +87,7 @@ namespace hal
gSelectionRelay->addGate(gate->get_id());
gSelectionRelay->setFocus(SelectionRelay::ItemType::Gate,gate->get_id());
- gSelectionRelay->selectionChanged(this);
+ gSelectionRelay->relaySelectionChanged(this);
if(navigate_to_selection)
Q_EMIT navigationRequested();
@@ -115,7 +115,7 @@ namespace hal
gate_ids.unite(gSelectionRelay->selectedGates());
gSelectionRelay->setSelectedGates(gate_ids);
- gSelectionRelay->selectionChanged(this);
+ gSelectionRelay->relaySelectionChanged(this);
if(navigate_to_selection)
Q_EMIT navigationRequested();
@@ -138,7 +138,7 @@ namespace hal
gSelectionRelay->addNet(net->get_id());
gSelectionRelay->setFocus(SelectionRelay::ItemType::Net,net->get_id());
- gSelectionRelay->selectionChanged(this);
+ gSelectionRelay->relaySelectionChanged(this);
if(navigate_to_selection)
Q_EMIT navigationRequested();
@@ -166,7 +166,7 @@ namespace hal
net_ids.unite(gSelectionRelay->selectedNets());
gSelectionRelay->setSelectedNets(net_ids);
- gSelectionRelay->selectionChanged(this);
+ gSelectionRelay->relaySelectionChanged(this);
if(navigate_to_selection)
Q_EMIT navigationRequested();
@@ -189,7 +189,7 @@ namespace hal
gSelectionRelay->addModule(module->get_id());
gSelectionRelay->setFocus(SelectionRelay::ItemType::Module,module->get_id());
- gSelectionRelay->selectionChanged(this);
+ gSelectionRelay->relaySelectionChanged(this);
if(navigate_to_selection)
Q_EMIT navigationRequested();
@@ -217,7 +217,7 @@ namespace hal
module_ids.unite(gSelectionRelay->selectedModules());
gSelectionRelay->setSelectedModules(module_ids);
- gSelectionRelay->selectionChanged(this);
+ gSelectionRelay->relaySelectionChanged(this);
if(navigate_to_selection)
Q_EMIT navigationRequested();
@@ -290,7 +290,7 @@ namespace hal
return;
gSelectionRelay->removeGate(gate->get_id());
- gSelectionRelay->selectionChanged(this);
+ gSelectionRelay->relaySelectionChanged(this);
}
void GuiApi::deselectGate(u32 gate_id)
@@ -312,7 +312,7 @@ namespace hal
}
gSelectionRelay->setSelectedGates(gate_ids);
- gSelectionRelay->selectionChanged(this);
+ gSelectionRelay->relaySelectionChanged(this);
}
void GuiApi::deselectGate(const std::vector& gate_ids)
@@ -328,7 +328,7 @@ namespace hal
return;
gSelectionRelay->removeNet(net->get_id());
- gSelectionRelay->selectionChanged(this);
+ gSelectionRelay->relaySelectionChanged(this);
}
void GuiApi::deselectNet(u32 netId)
@@ -350,7 +350,7 @@ namespace hal
}
gSelectionRelay->setSelectedNets(net_ids);
- gSelectionRelay->selectionChanged(this);
+ gSelectionRelay->relaySelectionChanged(this);
}
void GuiApi::deselectNet(const std::vector& net_ids)
@@ -366,7 +366,7 @@ namespace hal
return;
gSelectionRelay->removeModule(module->get_id());
- gSelectionRelay->selectionChanged(this);
+ gSelectionRelay->relaySelectionChanged(this);
}
void GuiApi::deselectModule(u32 module_id)
@@ -387,7 +387,7 @@ namespace hal
}
gSelectionRelay->setSelectedModules(module_ids);
- gSelectionRelay->selectionChanged(this);
+ gSelectionRelay->relaySelectionChanged(this);
}
void GuiApi::deselectModule(const std::vector& module_ids)
diff --git a/plugins/gui/src/module_dialog/module_dialog.cpp b/plugins/gui/src/module_dialog/module_dialog.cpp
index c2b58d9c436..f3502409b54 100644
--- a/plugins/gui/src/module_dialog/module_dialog.cpp
+++ b/plugins/gui/src/module_dialog/module_dialog.cpp
@@ -4,6 +4,7 @@
#include "gui/module_model/module_model.h"
#include "gui/module_model/module_proxy_model.h"
#include "gui/module_model/module_item.h"
+#include "gui/module_widget/module_widget.h"
#include "gui/graph_tab_widget/graph_tab_widget.h"
#include "gui/searchbar/searchbar.h"
#include "gui/content_manager/content_manager.h"
@@ -81,7 +82,7 @@ namespace hal {
mModuleTreeProxyModel = new ModuleProxyModel(this);
mModuleTreeProxyModel->setFilterKeyColumn(-1);
mModuleTreeProxyModel->setDynamicSortFilter(true);
- mModuleTreeProxyModel->setSourceModel(gNetlistRelay->getModuleModel());
+ mModuleTreeProxyModel->setSourceModel(gContentManager->getModuleWidget()->getModuleModel());
mTreeView->setModel(mModuleTreeProxyModel);
mTreeView->expandAll();
diff --git a/plugins/gui/src/module_model/module_item.cpp b/plugins/gui/src/module_model/module_item.cpp
index cf5a79bcc56..8291ac52b80 100644
--- a/plugins/gui/src/module_model/module_item.cpp
+++ b/plugins/gui/src/module_model/module_item.cpp
@@ -11,21 +11,35 @@ namespace hal
ModuleItem::ModuleItem(const u32 id, const TreeItemType type) :
BaseTreeItem(),
mId(id),
- mType(type),
+ mItemType(type),
mHighlighted(false)
{
switch(type)
{
case TreeItemType::Module:
- mName = QString::fromStdString(gNetlist->get_module_by_id(id)->get_name());
+ {
+ const Module* m = gNetlist->get_module_by_id(id);
+ Q_ASSERT(m);
+ mName = QString::fromStdString(m->get_name());
+ mModuleType = QString::fromStdString(m->get_type());
break;
+ }
case TreeItemType::Gate:
- mName = QString::fromStdString(gNetlist->get_gate_by_id(id)->get_name());
+ {
+ const Gate* g = gNetlist->get_gate_by_id(id);
+ Q_ASSERT(g);
+ mName = QString::fromStdString(g->get_name());
+ mModuleType = QString::fromStdString(g->get_type()->get_name());
break;
+ }
case TreeItemType::Net:
- mName = QString::fromStdString(gNetlist->get_net_by_id(id)->get_name());
+ {
+ const Net* n = gNetlist->get_net_by_id(id);
+ Q_ASSERT(n);
+ mName = QString::fromStdString(n->get_name());
break;
}
+ }
}
int ModuleItem::row() const
@@ -38,7 +52,7 @@ ModuleItem::ModuleItem(const u32 id, const TreeItemType type) :
void ModuleItem::appendExistingChildIfAny(const QMap& moduleMap)
{
- if(mType != TreeItemType::Module) // only module can have children
+ if(mItemType != TreeItemType::Module) // only module can have children
return;
Module* m = gNetlist->get_module_by_id(mId);
@@ -55,30 +69,25 @@ ModuleItem::ModuleItem(const u32 id, const TreeItemType type) :
}
}
+ void ModuleItem::setModuleType(const QString &moduleType)
+ {
+ if (mItemType != TreeItemType::Module) return;
+ Module* module = gNetlist->get_module_by_id(mId);
+ if (!module) return;
+ module->set_type(moduleType.toStdString());
+ mModuleType = moduleType;
+ }
+
QVariant ModuleItem::getData(int column) const
{
// DEBUG CODE, USE STYLED DELEGATES OR SOMETHING
- if(column == 0)
+ switch (column) {
+ case 0:
return mName;
- else if (column == 1)
+ case 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());
- }
+ case 2:
+ return mModuleType;
}
return QVariant();
}
@@ -86,42 +95,21 @@ ModuleItem::ModuleItem(const u32 id, const TreeItemType type) :
void ModuleItem::setData(QList data)
{
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;
- }
+ if (mItemType == TreeItemType::Module)
+ setModuleType(data.at(2).toString());
}
void ModuleItem::setDataAtIndex(int index, QVariant &data)
{
- if(index == 0) {
+ switch (index) {
+ case 0:
setName(data.toString());
return;
- }
- else if (index == 1)
+ case 1:
+ return;
+ case 2:
+ setModuleType(data.toString());
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;
- }
}
}
@@ -140,8 +128,14 @@ ModuleItem::ModuleItem(const u32 id, const TreeItemType type) :
return mHighlighted;
}
+ bool ModuleItem::isToplevelItem() const
+ {
+ if (dynamic_cast(mParent)) return true;
+ return false;
+ }
+
ModuleItem::TreeItemType ModuleItem::getType() const{
- return mType;
+ return mItemType;
}
void ModuleItem::setName(const QString& name)
@@ -159,5 +153,8 @@ ModuleItem::ModuleItem(const u32 id, const TreeItemType type) :
return 3;
}
- void ModuleItem::appendData(QVariant data) {}
+ void ModuleItem::appendData(QVariant data)
+ {
+ Q_UNUSED(data);
+ }
}
diff --git a/plugins/gui/src/module_model/module_model.cpp b/plugins/gui/src/module_model/module_model.cpp
index 7c645b97364..28e9de94035 100644
--- a/plugins/gui/src/module_model/module_model.cpp
+++ b/plugins/gui/src/module_model/module_model.cpp
@@ -13,6 +13,24 @@ namespace hal
{
// use root item to store header information
setHeaderLabels(QStringList() << "Name" << "ID" << "Type");
+ connect(gNetlistRelay, &NetlistRelay::moduleCreated, this, &ModuleModel::handleModuleCreated);
+ connect(gNetlistRelay, &NetlistRelay::moduleNameChanged, this, &ModuleModel::handleModuleNameChanged);
+ connect(gNetlistRelay, &NetlistRelay::moduleParentChanged, this, &ModuleModel::handleModuleParentChanged);
+ connect(gNetlistRelay, &NetlistRelay::moduleSubmoduleAdded, this, &ModuleModel::handleModuleSubmoduleAdded);
+ connect(gNetlistRelay, &NetlistRelay::moduleSubmoduleRemoved, this, &ModuleModel::handleModuleSubmoduleRemoved);
+ connect(gNetlistRelay, &NetlistRelay::moduleGateAssigned, this, &ModuleModel::handleModuleGateAssigned);
+ connect(gNetlistRelay, &NetlistRelay::moduleGatesAssignBegin, this, &ModuleModel::handleModuleGatesAssignBegin);
+ connect(gNetlistRelay, &NetlistRelay::moduleGatesAssignEnd, this, &ModuleModel::handleModuleGatesAssignEnd);
+ connect(gNetlistRelay, &NetlistRelay::moduleGateRemoved, this, &ModuleModel::handleModuleGateRemoved);
+ connect(gNetlistRelay, &NetlistRelay::moduleRemoved, this, &ModuleModel::handleModuleRemoved);
+ connect(gNetlistRelay, &NetlistRelay::gateNameChanged, this, &ModuleModel::handleGateNameChanged);
+ connect(gNetlistRelay, &NetlistRelay::netCreated, this, &ModuleModel::handleNetCreated);
+ connect(gNetlistRelay, &NetlistRelay::netRemoved, this, &ModuleModel::handleNetRemoved);
+ connect(gNetlistRelay, &NetlistRelay::netNameChanged, this, &ModuleModel::handleNetNameChanged);
+ connect(gNetlistRelay, &NetlistRelay::netSourceAdded, this, &ModuleModel::handleNetUpdated);
+ connect(gNetlistRelay, &NetlistRelay::netSourceRemoved, this, &ModuleModel::handleNetUpdated);
+ connect(gNetlistRelay, &NetlistRelay::netDestinationAdded, this, &ModuleModel::handleNetUpdated);
+ connect(gNetlistRelay, &NetlistRelay::netDestinationRemoved, this, &ModuleModel::handleNetUpdated);
}
QVariant ModuleModel::data(const QModelIndex& index, int role) const
@@ -75,335 +93,614 @@ namespace hal
return nullptr;
}
- QModelIndex ModuleModel::getIndex(const ModuleItem* const item) const
+ void ModuleModel::init()
{
- assert(item);
-
- QVector row_numbers;
- const ModuleItem* current_item = item;
+ addRecursively(gNetlist->get_top_module());
+ moduleAssignNets();
+ }
- while (current_item != mRootItem->getChild(0))
- {
- row_numbers.append(current_item->row());
- current_item = static_cast(current_item->getParent());
- }
+ void ModuleModel::clear()
+ {
+ beginResetModel();
- QModelIndex model_index = index(0, 0, QModelIndex());
+ BaseTreeModel::clear();
+ mModuleMap.clear();
+ mGateMap.clear();
+ mNetMap.clear();
+ endResetModel();
+ }
- for (QVector::const_reverse_iterator i = row_numbers.crbegin(); i != row_numbers.crend(); ++i)
- model_index = index(*i, 0, model_index);
+ void ModuleModel::addModule(u32 id, u32 parentId)
+ {
+ Q_ASSERT(gNetlist->get_module_by_id(id));
+ Q_ASSERT(gNetlist->get_module_by_id(parentId));
- return model_index;
+ for (auto it = mModuleMap.lowerBound(parentId); it != mModuleMap.upperBound(parentId); ++it)
+ {
+ ModuleItem* parentItem = it.value();
+ createChildItem(id, ModuleItem::TreeItemType::Module, parentItem);
+ }
}
- void ModuleModel::init()
+ void ModuleModel::addGate(u32 id, u32 parentId)
{
- ModuleItem* item = new ModuleItem(1);
- mModuleMap.insert(1, item);
+ Q_ASSERT(gNetlist->get_gate_by_id(id));
+ Q_ASSERT(gNetlist->get_module_by_id(parentId));
- beginInsertRows(index(0, 0, QModelIndex()), 0, 0);
- mRootItem->appendChild(item);
- endInsertRows();
- Module* m = gNetlist->get_top_module();
- addRecursively(m);
- for(auto net : gNetlist->get_top_module()->get_internal_nets())
+ for (auto it = mModuleMap.lowerBound(parentId); it != mModuleMap.upperBound(parentId); ++it)
{
- addNet(net->get_id(), m->get_id());
- updateNet(net);
+ createChildItem(id, ModuleItem::TreeItemType::Gate, it.value());
}
}
- void ModuleModel::clear()
+ void ModuleModel::addNet(u32 id, u32 parentId)
{
- beginResetModel();
+ Q_ASSERT(gNetlist->get_net_by_id(id));
+ Q_ASSERT(gNetlist->get_module_by_id(parentId));
- BaseTreeModel::clear();
- mModuleMap.clear();
- mGateMap.clear();
- mNetMap.clear();
- //TODO : clear colors
- endResetModel();
+ for (auto it = mModuleMap.lowerBound(parentId); it != mModuleMap.upperBound(parentId); ++it)
+ {
+ createChildItem(id, ModuleItem::TreeItemType::Net, it.value());
+ }
}
- void ModuleModel::addModule(u32 id, u32 parent_module)
+ void ModuleModel::addRecursively(const Module* module, BaseTreeItem *parentItem)
{
- assert(gNetlist->get_module_by_id(id));
- assert(gNetlist->get_module_by_id(parent_module));
- assert(!mModuleMap.contains(id));
- assert(mModuleMap.contains(parent_module));
-
- ModuleItem* item = new ModuleItem(id);
- ModuleItem* parent = mModuleMap.value(parent_module);
+ Q_ASSERT(module);
+ ModuleItem* moduleItem = createChildItem(module->get_id(), ModuleItem::TreeItemType::Module, parentItem ? parentItem : mRootItem);
+ Q_ASSERT(moduleItem);
+ for(const Module* subModule : module->get_submodules())
+ addRecursively(subModule, moduleItem);
+
+ for(const Gate* g : module->get_gates())
+ createChildItem(g->get_id(), ModuleItem::TreeItemType::Gate, moduleItem);
+ }
- item->setParent(parent);
- mModuleMap.insert(id, item);
+ void ModuleModel::removeModule(const u32 id)
+ {
+ auto it = mModuleMap.lowerBound(id);
+ while (it != mModuleMap.upperBound(id))
+ {
+ ModuleItem* item = it.value();
+ BaseTreeItem* parentItem = item->getParent();
- QModelIndex index = getIndex(parent);
+ removeChildItem(item,parentItem);
- int row = parent->getChildCount();
- mIsModifying = true;
- beginInsertRows(index, row, row);
- parent->appendChild(item);
- mIsModifying = false;
- endInsertRows();
+ it = mModuleMap.erase(it);
+ }
}
- void ModuleModel::addGate(u32 id, u32 parent_module)
+ void ModuleModel::removeGate(const u32 id)
{
- assert(gNetlist->get_gate_by_id(id));
- assert(gNetlist->get_module_by_id(parent_module));
- assert(!mGateMap.contains(id));
- assert(mModuleMap.contains(parent_module));
+ auto it = mGateMap.lowerBound(id);
+ while (it != mGateMap.upperBound(id))
+ {
+ ModuleItem* item = it.value();
+ BaseTreeItem* parentItem = item->getParent();
- ModuleItem* item = new ModuleItem(id, ModuleItem::TreeItemType::Gate);
- ModuleItem* parent = mModuleMap.value(parent_module);
+ removeChildItem(item, parentItem);
- item->setParent(parent);
- mGateMap.insert(id, item);
+ it = mGateMap.erase(it);
+ }
+ }
- QModelIndex index = getIndex(parent);
+ void ModuleModel::removeNet(const u32 id)
+ {
+ auto it = mNetMap.lowerBound(id);
+ while (it != mNetMap.upperBound(id))
+ {
+ ModuleItem* item = it.value();
+ BaseTreeItem* parentItem = item->getParent();
- int row = parent->getChildCount();
- mIsModifying = true;
- beginInsertRows(index, row, row);
- parent->appendChild(item);
- mIsModifying = false;
- endInsertRows();
+ removeChildItem(item, parentItem);
+
+ it = mNetMap.erase(it);
+ }
}
- void ModuleModel::addNet(u32 id, u32 parent_module)
+ void ModuleModel::removeChildItem(ModuleItem *itemToRemove, BaseTreeItem *parentItem)
{
- assert(gNetlist->get_net_by_id(id));
- assert(gNetlist->get_module_by_id(parent_module));
- assert(!mNetMap.contains(id));
- assert(mModuleMap.contains(parent_module));
+ Q_ASSERT(itemToRemove);
+ Q_ASSERT(parentItem);
- ModuleItem* item = new ModuleItem(id, ModuleItem::TreeItemType::Net);
- ModuleItem* parent = mModuleMap.value(parent_module);
+ while (itemToRemove->getChildCount())
+ {
+ ModuleItem* childItem = static_cast(itemToRemove->getChildren().at(0));
+ int ityp = static_cast(childItem->getType());
+ auto it = mModuleItemMaps[ityp]->lowerBound(childItem->id());
+ while (it != mModuleItemMaps[ityp]->upperBound(childItem->id()))
+ {
+ if (it.value() == childItem)
+ it = mModuleItemMaps[ityp]->erase(it);
+ else
+ ++it;
+ }
+ removeChildItem(childItem,itemToRemove);
+ }
- item->setParent(parent);
- mNetMap.insert(id, item);
+ QModelIndex index = getIndexFromItem(parentItem);
- QModelIndex index = getIndex(parent);
+ int row = itemToRemove->row();
- int row = parent->getChildCount();
mIsModifying = true;
- beginInsertRows(index, row, row);
- parent->appendChild(item);
+ beginRemoveRows(index, row, row);
+ parentItem->removeChild(itemToRemove);
+ endRemoveRows();
mIsModifying = false;
- endInsertRows();
+
+ delete itemToRemove;
}
- void ModuleModel::addRecursively(const Module* module)
+ void ModuleModel::handleModuleNameChanged(Module* mod)
{
- if(!module->is_top_module())
- addModule(module->get_id(), module->get_parent_module()->get_id());
- for(auto &m : module->get_submodules())
- addRecursively(m);
+ updateModuleName(mod->get_id());
+ }
- for(auto &g : module->get_gates())
- addGate(g->get_id(), module->get_id());
+ void ModuleModel::handleModuleRemoved(Module* mod)
+ {
+ removeModule(mod->get_id());
}
- void ModuleModel::removeModule(const u32 id)
+ void ModuleModel::handleModuleCreated(Module* mod)
{
- assert(id != 1);
- // module was most likely already purged from netlist
- assert(mModuleMap.contains(id));
+ if (mod->get_parent_module() == nullptr) return;
+ addModule(mod->get_id(), mod->get_parent_module()->get_id());
+ }
- ModuleItem* item = mModuleMap.value(id);
- ModuleItem* parent = static_cast(item->getParent());
- assert(item);
- assert(parent);
+ void ModuleModel::handleModuleGateAssigned(Module* mod, u32 gateId)
+ {
+ if (mTempGateAssignment.isAccumulate())
+ mTempGateAssignment.assignGateToModule(gateId,mod);
+ else
+ {
+ moduleAssignGate(mod->get_id(), gateId);
+ moduleAssignNets({gateId});
+ }
+ }
- QModelIndex index = getIndex(parent);
+ void ModuleModel::handleModuleGateRemoved(Module* mod, u32 gateId)
+ {
+ if (mTempGateAssignment.isAccumulate())
+ mTempGateAssignment.removeGateFromModule(gateId,mod);
+ else
+ {
+ auto it = mGateMap.lowerBound(gateId);
+ while (it != mGateMap.upperBound(gateId))
+ {
+ ModuleItem* item = it.value();
+ if (!item->isToplevelItem())
+ {
+ ModuleItem* parentItem = static_cast(item->getParent());
+ if (parentItem->id() == mod->get_id())
+ {
+ removeChildItem(item, parentItem);
+ it = mGateMap.erase(it);
+ continue;
+ }
+ }
+ ++it;
+ }
+ }
+ }
- int row = item->row();
+ void ModuleModel::handleModuleGatesAssignBegin(Module* mod, u32 numberGates)
+ {
+ Q_UNUSED(mod);
+ Q_UNUSED(numberGates);
+ mTempGateAssignment.beginAccumulate();
+ }
- mIsModifying = true;
- beginRemoveRows(index, row, row);
- parent->removeChild(item);
- mIsModifying = false;
- endRemoveRows();
+ void ModuleModel::handleModuleGatesAssignEnd(Module* mod, u32 numberGates)
+ {
+ Q_UNUSED(mod);
+ Q_UNUSED(numberGates);
+ mTempGateAssignment.endAccumulate();
+ if (!mTempGateAssignment.isAccumulate())
+ {
+ for (auto it = mTempGateAssignment.mGateAssign.begin(); it != mTempGateAssignment.mGateAssign.end(); ++it)
+ {
+ moduleAssignGate(it.value()->get_id(), it.key()); // moduleId, gateId
+ }
+ moduleAssignNets(mTempGateAssignment.mGateAssign.keys());
+ mTempGateAssignment.mGateAssign.clear();
+ mTempGateAssignment.mGateRemove.clear();
+ }
+ }
- mModuleMap.remove(id);
- delete item;
+ void ModuleModel::handleGateRemoved(Gate* gat)
+ {
+ removeGate(gat->get_id());
}
- void ModuleModel::removeGate(const u32 id)
+ void ModuleModel::handleGateCreated(Gate* gat)
{
- //assert(gNetlist->get_gate_by_id(id));
- assert(mGateMap.contains(id));
+ Module* mod = gat->get_module();
+ if (mod) moduleAssignGate(mod->get_id(), gat->get_id());
+ }
- ModuleItem* item = mGateMap.value(id);
- ModuleItem* parent = static_cast(item->getParent());
- assert(item);
- assert(parent);
+ void ModuleModel::handleGateNameChanged(Gate* gat)
+ {
+ updateGateName(gat->get_id());
+ }
- QModelIndex index = getIndex(parent);
+ void ModuleModel::handleNetCreated(Net* net)
+ {
+ addNet(net->get_id(), gNetlist->get_top_module()->get_id());
+ }
- int row = item->row();
+ void ModuleModel::handleNetRemoved(Net* net)
+ {
+ removeNet(net->get_id());
+ }
- mIsModifying = true;
- beginRemoveRows(index, row, row);
- parent->removeChild(item);
- mIsModifying = false;
- endRemoveRows();
+ void ModuleModel::handleNetNameChanged(Net* net)
+ {
+ updateNetName(net->get_id());
+ }
- mGateMap.remove(id);
- delete item;
+ void ModuleModel::handleNetUpdated(Net* net, u32 data)
+ {
+ Q_UNUSED(data);
+ updateNetParent(net);
}
- void ModuleModel::removeNet(const u32 id)
+ void ModuleModel::handleModuleParentChanged(const Module* mod)
{
- //assert(gNetlist->get_net_by_id(id));
- if(!mNetMap.contains(id)) // global nets are not contained in the item model
- return;
+ Q_ASSERT(mod);
+ updateModuleParent(mod);
- ModuleItem* item = mNetMap.value(id);
- ModuleItem* parent = static_cast(item->getParent());
- assert(item);
- assert(parent);
+ QHash parentAssignment;
+ std::unordered_set assignedNets;
+ findNetParentRecursion(mRootItem, parentAssignment, assignedNets);
- QModelIndex index = getIndex(parent);
+ for(Net* net : mod->get_nets())
+ updateNetParent(net, &parentAssignment);
+ }
- int row = item->row();
+ void ModuleModel::handleModuleSubmoduleAdded(Module* mod, u32 submodId)
+ {
+ Q_UNUSED(mod);
+ Q_UNUSED(submodId);
+ }
- mIsModifying = true;
- beginRemoveRows(index, row, row);
- parent->removeChild(item);
- mIsModifying = false;
- endRemoveRows();
+ void ModuleModel::handleModuleSubmoduleRemoved(Module* mod, u32 submodId)
+ {
+ Q_UNUSED(mod);
+ Q_UNUSED(submodId);
+ }
- mNetMap.remove(id);
- delete item;
+ void ModuleModel::findNetParentRecursion(BaseTreeItem* parent, QHash &parentAssignment, std::unordered_set& assignedNets) const
+ {
+ for (BaseTreeItem* bti : parent->getChildren())
+ {
+ ModuleItem* item = dynamic_cast(bti);
+ if (!item || item->getType() != ModuleItem::TreeItemType::Module) continue;
+ findNetParentRecursion(item, parentAssignment, assignedNets);
+ Module* m = gNetlist->get_module_by_id(item->id());
+ Q_ASSERT(m);
+ std::unordered_set internalNets = m->get_nets();
+ if (!internalNets.empty())
+ {
+ for (Net* n : assignedNets)
+ internalNets.erase(n);
+ for (Net* n : m->get_input_nets())
+ internalNets.erase(n);
+ for (Net* n : m->get_output_nets())
+ internalNets.erase(n);
+ }
+ for (Net* n : internalNets)
+ {
+ parentAssignment[n] = item;
+ assignedNets.insert(n);
+ }
+ }
}
- void ModuleModel::handleModuleParentChanged(const Module* module)
+ Module* ModuleModel::findNetParent(const Net *net) const
{
- assert(module);
- updateModuleParent(module);
+ QHash modHash;
+ if (net->is_global_input_net() || net->is_global_output_net()) return nullptr;
+ int maxDepth = 0;
+
+ for (const Endpoint* ep : net->get_sources())
+ {
+ Module* m = ep->get_gate()->get_module();
+ Q_ASSERT(m);
+ int depth = m->get_submodule_depth();
+ if (depth > maxDepth) maxDepth = depth;
+ modHash.insert(m,depth);
+ }
- for(Net* net : module->get_nets())
- updateNet(net);
+ for (const Endpoint* ep : net->get_destinations())
+ {
+ Module* m = ep->get_gate()->get_module();
+ Q_ASSERT(m);
+ int depth = m->get_submodule_depth();
+ if (depth > maxDepth) maxDepth = depth;
+ modHash.insert(m,depth);
+ }
+
+ while (modHash.size() > 1 && maxDepth > 0)
+ {
+ auto it = modHash.begin();
+ while (it != modHash.end())
+ {
+ if (it.value() == maxDepth)
+ {
+ Module* parentMod = it.key()->get_parent_module();
+ modHash.erase(it);
+ if (parentMod) modHash.insert(parentMod,maxDepth-1);
+ break;
+ }
+ ++it;
+ }
+ if (it == modHash.end())
+ --maxDepth;
+ }
+ if (modHash.empty()) return nullptr;
+ return modHash.begin().key();
}
- void ModuleModel::handleModuleGateAssinged(const u32 id, const u32 parent_module)
+ void ModuleModel::moduleAssignGate(const u32 moduleId, const u32 gateId)
{
// 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);
+ QSet parentsHandled;
+ Q_ASSERT(gNetlist->get_gate_by_id(gateId));
+
+ auto itGat = mGateMap.lowerBound(gateId);
+ while (itGat != mGateMap.upperBound(gateId))
+ {
+ ModuleItem* gatItem = itGat.value();
+ if (gatItem->isToplevelItem()) continue;
+ ModuleItem* oldParentItem = static_cast(gatItem->getParent());
+ Q_ASSERT(oldParentItem);
+
+ if (oldParentItem->id() != moduleId)
+ {
+ removeChildItem(gatItem,oldParentItem);
+ itGat = mGateMap.erase(itGat);
+ }
+ else
+ {
+ parentsHandled.insert(oldParentItem);
+ ++itGat;
+ }
+
+ }
+
+ if (!moduleId) return;
+ for (auto itMod = mModuleMap.lowerBound(moduleId); itMod != mModuleMap.upperBound(moduleId); ++itMod)
+ {
+ ModuleItem* parentItem = itMod.value();
+ if (parentsHandled.contains(parentItem)) continue;
+ createChildItem(gateId, ModuleItem::TreeItemType::Gate, parentItem);
+ }
+
}
- void ModuleModel::updateNet(const Net* net)
+ void ModuleModel::moduleAssignNets(const QList& gateIds)
{
- assert(net);
- u32 id = net->get_id();
+ QHash parentAssignment;
+ std::unordered_set assignedNets;
+ findNetParentRecursion(mRootItem, parentAssignment, assignedNets);
+
+ QSet netsToAssign;
+ if (gateIds.isEmpty())
+ {
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
+ QList tempKeys = parentAssignment.keys();
+ netsToAssign = QSet(tempKeys.begin(),tempKeys.end());
+#else
+ netsToAssign = parentAssignment.keys().toSet();
+#endif
+ }
+ else
+ {
+ for (u32 id : gateIds)
+ {
+ Gate* gate = gNetlist->get_gate_by_id(id);
+ for(Net* in_net : gate->get_fan_in_nets())
+ netsToAssign.insert(in_net);
+ for(Net* out_net : gate->get_fan_out_nets())
+ netsToAssign.insert(out_net);
+ }
+ }
+
+ for (const Net* n: netsToAssign)
+ updateNetParent(n, &parentAssignment);
+ }
+
+ void ModuleModel::updateNetParent(const Net* net, const QHash *parentAssignment)
+ {
+ Q_ASSERT(net);
+ u32 netId = net->get_id();
+
+ QSet parentsHandled;
+ u32 newParentId = 0;
+ if (parentAssignment)
+ {
+ ModuleItem* modItem = parentAssignment->value(net);
+ if (modItem)
+ newParentId = modItem->id();
+ }
+ else
+ {
+ Module* newParentModule = findNetParent(net);
+ if (newParentModule)
+ newParentId = newParentModule->get_id();
+ }
- if(!mNetMap.contains(id))
- return;
+ auto itNet = mNetMap.lowerBound(netId);
+ while (itNet != mNetMap.upperBound(netId))
+ {
+ if (itNet.value()->isToplevelItem()) continue;
- 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();
+ ModuleItem* netItem = itNet.value();
+ ModuleItem* oldParentItem = static_cast(netItem->getParent());
+ Q_ASSERT(oldParentItem);
- mIsModifying = true;
- beginMoveRows(oldIndex, row, row, newIndex, newParentItem->getChildCount());
- oldParentItem->removeChild(item);
- newParentItem->appendChild(item);
- mIsModifying = false;
- endMoveRows();
+
+ if (newParentId == 0 || newParentId != oldParentItem->id())
+ {
+ removeChildItem(netItem,oldParentItem);
+ itNet = mNetMap.erase(itNet);
+ }
+ else
+ {
+ parentsHandled.insert(oldParentItem);
+ ++itNet;
+ }
+ }
+
+ if (!newParentId) return;
+ for (auto itMod = mModuleMap.lowerBound(newParentId); itMod != mModuleMap.upperBound(newParentId); ++itMod)
+ {
+ ModuleItem* parentItem = itMod.value();
+ if (parentsHandled.contains(parentItem)) continue;
+ createChildItem(net->get_id(), ModuleItem::TreeItemType::Net, parentItem);
+ }
}
- void ModuleModel::updateModuleParent(const Module* module){
- assert(module);
+ void ModuleModel::updateModuleParent(const Module* module)
+ {
+ ModuleItem* moduleItemToBeMoved = nullptr;
+ bool moduleItemReassigned = false;
+
+ Q_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);
+ Q_ASSERT(id != 1);
- assert(module->get_parent_module());
- if(oldParent->id() == module->get_parent_module()->get_id())
- return;
+ QSet parentsHandled;
+ u32 parentId = module->get_parent_module()->get_id();
+ Q_ASSERT(parentId > 0);
- assert(mModuleMap.contains(module->get_parent_module()->get_id()));
- ModuleItem* newParent = mModuleMap.value(module->get_parent_module()->get_id());
+ auto itSubm = mModuleMap.lowerBound(id);
+ while (itSubm != mModuleMap.upperBound(id))
+ {
+ ModuleItem* submItem = itSubm.value();
+ if (submItem->isToplevelItem()) continue;
+ ModuleItem* oldParentItem = static_cast(submItem->getParent());
+ Q_ASSERT(oldParentItem);
- QModelIndex oldIndex = getIndex(oldParent);
- QModelIndex newIndex = getIndex(newParent);
- int row = item->row();
+ if (oldParentItem->id() != parentId)
+ {
+ if (moduleItemToBeMoved)
+ {
+ // remove tree item recursively
+ removeChildItem(submItem,oldParentItem);
+ itSubm = mModuleMap.erase(itSubm);
+ }
+ else
+ {
+ // save tree item for reassignment
+ moduleItemToBeMoved = submItem;
+ QModelIndex index = getIndexFromItem(oldParentItem);
+
+ int row = submItem->row();
+
+ mIsModifying = true;
+ beginRemoveRows(index, row, row);
+ oldParentItem->removeChild(submItem);
+ endRemoveRows();
+ mIsModifying = false;
+ ++itSubm;
+ }
+ }
+ else
+ {
+ parentsHandled.insert(oldParentItem);
+ ++itSubm;
+ }
+ }
+
+ if (!parentId) return;
+ for (auto itMod = mModuleMap.lowerBound(parentId); itMod != mModuleMap.upperBound(parentId); ++itMod)
+ {
+ ModuleItem* parentItem = itMod.value();
+ if (parentsHandled.contains(parentItem)) continue;
+ if (moduleItemToBeMoved && !moduleItemReassigned)
+ {
+ QModelIndex index = getIndexFromItem(parentItem);
+ int row = parentItem->getChildCount();
+ mIsModifying = true;
+ beginInsertRows(index, row, row);
+ parentItem->appendChild(moduleItemToBeMoved);
+ endInsertRows();
+ mIsModifying = false;
+ moduleItemReassigned = true;
+ }
+ else
+ {
+ addRecursively(module, parentItem);
+ }
+ }
+
+ if (moduleItemToBeMoved && !moduleItemReassigned)
+ {
+ // stored item could not be reassigned, delete it
+ auto it = mModuleMap.lowerBound(id);
+ while (it != mModuleMap.upperBound(id))
+ {
+ if (it.value() == moduleItemToBeMoved)
+ it = mModuleMap.erase(it);
+ else
+ ++it;
+ }
+ delete moduleItemToBeMoved;
+ }
- mIsModifying = true;
- beginMoveRows(oldIndex, row, row, newIndex, newParent->getChildCount());
- oldParent->removeChild(item);
- newParent->appendChild(item);
- mIsModifying = false;
- endMoveRows();
}
void ModuleModel::updateModuleName(u32 id)
{
- assert(gNetlist->get_module_by_id(id));
- assert(mModuleMap.contains(id));
+ Q_ASSERT(gNetlist->get_module_by_id(id));
- ModuleItem* item = mModuleMap.value(id);
- assert(item);
+ for (auto it = mModuleMap.lowerBound(id); it != mModuleMap.upperBound(id); ++it)
+ {
+ ModuleItem* item = it.value();
+ Q_ASSERT(item);
- item->setName(QString::fromStdString(gNetlist->get_module_by_id(id)->get_name())); // REMOVE & ADD AGAIN
+ item->setName(QString::fromStdString(gNetlist->get_module_by_id(id)->get_name())); // REMOVE & ADD AGAIN
- QModelIndex index = getIndex(item);
- Q_EMIT dataChanged(index, index);
+ QModelIndex index = getIndexFromItem(item);
+ Q_EMIT dataChanged(index, index);
+ }
}
void ModuleModel::updateGateName(u32 id)
{
- assert(gNetlist->get_gate_by_id(id));
- assert(mGateMap.contains(id));
+ Q_ASSERT(gNetlist->get_gate_by_id(id));
- ModuleItem* item = mGateMap.value(id);
- assert(item);
+ for (auto it = mGateMap.lowerBound(id); it != mGateMap.upperBound(id); ++it)
+ {
+ ModuleItem* item = it.value();
+ Q_ASSERT(item);
- item->setName(QString::fromStdString(gNetlist->get_gate_by_id(id)->get_name())); // REMOVE & ADD AGAIN
+ item->setName(QString::fromStdString(gNetlist->get_gate_by_id(id)->get_name())); // REMOVE & ADD AGAIN
- QModelIndex index = getIndex(item);
- Q_EMIT dataChanged(index, index);
+ QModelIndex index = getIndexFromItem(item);
+ Q_EMIT dataChanged(index, index);
+ }
}
void ModuleModel::updateNetName(u32 id)
{
- assert(gNetlist->get_net_by_id(id));
- assert(mNetMap.contains(id));
+ Q_ASSERT(gNetlist->get_net_by_id(id));
+ Q_ASSERT(mNetMap.contains(id));
- ModuleItem* item = mNetMap.value(id);
- assert(item);
+ for (auto it = mNetMap.lowerBound(id); it != mNetMap.upperBound(id); ++it)
+ {
+ ModuleItem* item = it.value();
+ Q_ASSERT(item);
- item->setName(QString::fromStdString(gNetlist->get_net_by_id(id)->get_name())); // REMOVE & ADD AGAIN
+ item->setName(QString::fromStdString(gNetlist->get_net_by_id(id)->get_name())); // REMOVE & ADD AGAIN
- QModelIndex index = getIndex(item);
- Q_EMIT dataChanged(index, index);
+ QModelIndex index = getIndexFromItem(item);
+ Q_EMIT dataChanged(index, index);
+ }
}
ModuleItem* ModuleModel::getItem(u32 id, ModuleItem::TreeItemType type) const
@@ -411,45 +708,27 @@ namespace hal
return mModuleItemMaps[(int)type]->value(id);
}
- bool ModuleModel::isModifying()
+ ModuleItem* ModuleModel::createChildItem(u32 id, ModuleItem::TreeItemType itemType, BaseTreeItem *parentItem)
{
- 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());
- }
+ ModuleItem* retval = new ModuleItem(id, itemType);
+ mModuleItemMaps[(int)itemType]->insertMulti(id,retval);
- Module* parent = endpoints[0]->get_gate()->get_module();
- endpoints.erase(endpoints.begin());
+ if (!parentItem) parentItem = mRootItem;
+ QModelIndex index = getIndexFromItem(parentItem);
+ int row = parentItem->getChildCount();
+ mIsModifying = true;
+ beginInsertRows(index, row, row);
+ parentItem->appendChild(retval);
+ endInsertRows();
+ mIsModifying = false;
- // 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;
- }
+ return retval;
+ }
- if(endpoints.size() > 0)
- parent = parent->get_parent_module();
- }
- return parent;
+ bool ModuleModel::isModifying()
+ {
+ return mIsModifying;
}
+
}
diff --git a/plugins/gui/src/module_widget/module_widget.cpp b/plugins/gui/src/module_widget/module_widget.cpp
index 21443463e2e..2d5050aba8f 100644
--- a/plugins/gui/src/module_widget/module_widget.cpp
+++ b/plugins/gui/src/module_widget/module_widget.cpp
@@ -62,7 +62,8 @@ namespace hal
mRenameAction->setToolTip("Rename");
mToggleExpandTreeAction->setToolTip("Toggle expand all / collapse all");
- mModuleProxyModel->setSourceModel(gNetlistRelay->getModuleModel());
+ mModuleModel = new ModuleModel(this);
+ mModuleProxyModel->setSourceModel(mModuleModel);
mTreeView->setModel(mModuleProxyModel);
mTreeView->setDefaultColumnWidth();
@@ -75,10 +76,9 @@ namespace hal
mTreeView->setExpandsOnDoubleClick(false);
mTreeView->setSelectionBehavior(QAbstractItemView::SelectRows);
mTreeView->setSelectionMode(QAbstractItemView::SingleSelection);
- mTreeView->expandAllModules();
mContentLayout->addWidget(mTreeView);
- mSearchbar->setColumnNames(gNetlistRelay->getModuleModel()->headerLabels());
+ mSearchbar->setColumnNames(mModuleModel->headerLabels());
mContentLayout->addWidget(mSearchbar);
mSearchbar->hide();
@@ -91,7 +91,7 @@ namespace hal
connect(mTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ModuleWidget::handleTreeSelectionChanged);
connect(mTreeView->selectionModel(), &QItemSelectionModel::currentChanged, this, &ModuleWidget::handleCurrentChanged);
connect(mTreeView, &ModuleTreeView::doubleClicked, this, &ModuleWidget::handleItemDoubleClicked);
- connect(gSelectionRelay, &SelectionRelay::selectionChanged, this, &ModuleWidget::handleSelectionChanged);
+ connect(gSelectionRelay, &SelectionRelay::selectionChanged, this, &ModuleWidget::handleSelectionChanged, Qt::QueuedConnection);
connect(gNetlistRelay, &NetlistRelay::moduleSubmoduleRemoved, this, &ModuleWidget::handleModuleRemoved);
connect(mSearchAction, &QAction::triggered, this, &ModuleWidget::toggleSearchbar);
@@ -113,6 +113,9 @@ namespace hal
connect(mToggleGatesAction, &QAction::triggered, this, &ModuleWidget::handleToggleGatesClicked);
connect(mToggleExpandTreeAction, &QAction::triggered, this, &ModuleWidget::handleToggleExpandTreeClicked);
connect(mRenameAction, &QAction::triggered, this, &ModuleWidget::handleRenameClicked);
+
+ mModuleModel->init();
+ mTreeView->expandAllModules();
}
void ModuleWidget::enableDeleteAction(bool enable)
@@ -295,6 +298,9 @@ namespace hal
extractPythonAction.setText("Extract Net 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 Net name");
change_name_action.setParent(&context_menu);
@@ -325,6 +331,7 @@ namespace hal
if (type == ModuleItem::TreeItemType::Net){
context_menu.addAction(&extractPythonAction);
+ context_menu.addAction(&isolate_action);
context_menu.addAction(&change_name_action);
context_menu.addAction(&focus_in_view);
}
@@ -355,6 +362,7 @@ namespace hal
{
case ModuleItem::TreeItemType::Module: openModuleInView(index); break;
case ModuleItem::TreeItemType::Gate: openGateInView(index); break;
+ case ModuleItem::TreeItemType::Net: openNetEndpointsInView(index); break;
default:
break;
}
@@ -427,7 +435,7 @@ namespace hal
Q_UNUSED(selected)
Q_UNUSED(deselected)
- if (mIgnoreSelectionChange || gNetlistRelay->getModuleModel()->isModifying())
+ if (mIgnoreSelectionChange || mModuleModel->isModifying())
return;
gSelectionRelay->clear();
@@ -474,7 +482,12 @@ namespace hal
void ModuleWidget::handleItemDoubleClicked(const QModelIndex& index)
{
- openModuleInView(index);
+ ModuleItem* mi = getModuleItemFromIndex(index);
+ switch(mi->getType()){
+ case ModuleItem::TreeItemType::Module: openModuleInView(index); break;
+ case ModuleItem::TreeItemType::Gate: openGateInView(index); break;
+ case ModuleItem::TreeItemType::Net: openNetEndpointsInView(index); break;
+ }
}
void ModuleWidget::openModuleInView(const QModelIndex& index)
@@ -498,6 +511,36 @@ namespace hal
act->exec();
}
+ void ModuleWidget::openNetEndpointsInView(const QModelIndex &index){
+ QSet allGates;
+
+ Net* net = gNetlist->get_net_by_id(getModuleItemFromIndex(index)->id());
+
+ PlacementHint plc(PlacementHint::PlacementModeType::GridPosition);
+ int currentY = -(int)(net->get_num_of_sources()/2);
+ for(auto endpoint : net->get_sources()) {
+ u32 id = endpoint->get_gate()->get_id();
+ allGates.insert(id);
+ plc.addGridPosition(Node(id, Node::NodeType::Gate), {0, currentY++});
+ }
+ currentY = -(int)(net->get_num_of_destinations()/2);
+ for(auto endpoint : net->get_destinations()) {
+ u32 id = endpoint->get_gate()->get_id();
+ allGates.insert(id);
+ plc.addGridPosition(Node(id, Node::NodeType::Gate), {1, currentY++});
+ }
+
+ QString name = gGraphContextManager->nextViewName("Isolated View");
+
+ UserActionCompound* act = new UserActionCompound;
+ act->setUseCreatedObject();
+ act->addAction(new ActionCreateObject(UserActionObjectType::ContextView, name));
+ auto actionAITO = new ActionAddItemsToObject({}, allGates);
+ actionAITO->setPlacementHint(plc);
+ act->addAction(actionAITO);
+ act->exec();
+ }
+
void ModuleWidget::changeGateName(const QModelIndex &index)
{
QString oldName = getModuleItemFromIndex(index)->name();
@@ -568,8 +611,12 @@ namespace hal
for (auto module_id : gSelectionRelay->selectedModulesList())
{
- QModelIndex index = mModuleProxyModel->mapFromSource(gNetlistRelay->getModuleModel()->getIndex(gNetlistRelay->getModuleModel()->getItem(module_id)));
- module_selection.select(index, index);
+ ModuleItem* item = mModuleModel->getItem(module_id);
+ if(item)
+ {
+ QModelIndex index = mModuleProxyModel->mapFromSource(mModuleModel->getIndexFromItem(item));
+ module_selection.select(index, index);
+ }
}
mTreeView->selectionModel()->select(module_selection, QItemSelectionModel::SelectionFlag::ClearAndSelect);
@@ -579,7 +626,7 @@ namespace hal
ModuleItem* ModuleWidget::getModuleItemFromIndex(const QModelIndex& index)
{
- return gNetlistRelay->getModuleModel()->getItem(mModuleProxyModel->mapToSource(index));
+ return mModuleModel->getItem(mModuleProxyModel->mapToSource(index));
}
void ModuleWidget::updateSearchIcon()
@@ -590,6 +637,11 @@ namespace hal
mSearchAction->setIcon(gui_utility::getStyledSvgIcon(mSearchIconStyle, mSearchIconPath));
}
+ ModuleModel* ModuleWidget::getModuleModel() const
+ {
+ return mModuleModel;
+ }
+
QString ModuleWidget::disabledIconStyle() const
{
return mDisabledIconStyle;
diff --git a/plugins/gui/src/netlist_relay/netlist_relay.cpp b/plugins/gui/src/netlist_relay/netlist_relay.cpp
index 7eb4eac4309..416bb3e80a1 100644
--- a/plugins/gui/src/netlist_relay/netlist_relay.cpp
+++ b/plugins/gui/src/netlist_relay/netlist_relay.cpp
@@ -28,7 +28,7 @@
namespace hal
{
NetlistRelay::NetlistRelay(QObject* parent)
- : QObject(parent), mModuleModel(new ModuleModel(this)), mModuleColorManager(new ModuleColorManager(this))
+ : QObject(parent), mModuleColorManager(new ModuleColorManager(this))
{
connect(FileManager::get_instance(), &FileManager::fileOpened, this, &NetlistRelay::debugHandleFileOpened); // DEBUG LINE
connect(this, &NetlistRelay::signalThreadEvent, this, &NetlistRelay::handleThreadEvent, Qt::BlockingQueuedConnection);
@@ -85,11 +85,6 @@ namespace hal
return mModuleColorManager->moduleColor(id);
}
- ModuleModel* NetlistRelay::getModuleModel() const
- {
- return mModuleModel;
- }
-
ModuleColorManager* NetlistRelay::getModuleColorManager() const
{
return mModuleColorManager;
@@ -380,7 +375,6 @@ namespace hal
// suppress actions if we receive this for the top module
if (mod->get_parent_module() != nullptr)
{
- mModuleModel->addModule(mod->get_id(), mod->get_parent_module()->get_id());
mModuleColorManager->setRandomColor(mod->get_id());
}
@@ -393,7 +387,6 @@ namespace hal
//< no associated_data
mModuleColorManager->removeColor(mod->get_id());
- mModuleModel->removeModule(mod->get_id());
gGraphContextManager->handleModuleRemoved(mod);
gSelectionRelay->handleModuleRemoved(mod->get_id());
@@ -404,8 +397,6 @@ namespace hal
case ModuleEvent::event::name_changed: {
//< no associated_data
- mModuleModel->updateModuleName(mod->get_id());
-
gGraphContextManager->handleModuleNameChanged(mod);
Q_EMIT moduleNameChanged(mod);
@@ -414,8 +405,6 @@ namespace hal
case ModuleEvent::event::parent_changed: {
//< no associated_data
- mModuleModel->handleModuleParentChanged(mod);
-
Q_EMIT moduleParentChanged(mod);
break;
}
@@ -438,7 +427,6 @@ 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);
@@ -447,18 +435,18 @@ 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);
break;
}
case ModuleEvent::event::pin_changed: {
- //< no associated_data
-
- gGraphContextManager->handleModulePortsChanged(mod);
+ //< associated_data = [4LSB: type of action] [28HSB: id of pin group or pin]
+ PinEvent pev = (PinEvent) (associated_data&0xF);
+ u32 id = (associated_data >> 4);
+ gGraphContextManager->handleModulePortsChanged(mod,pev,id);
- Q_EMIT modulePortsChanged(mod);
+ Q_EMIT modulePortsChanged(mod,pev,id);
break;
}
case ModuleEvent::event::type_changed: {
@@ -535,7 +523,6 @@ namespace hal
case GateEvent::event::name_changed: {
//< no associated_data
- mModuleModel->updateGateName(gat->get_id());
gGraphContextManager->handleGateNameChanged(gat);
Q_EMIT gateNameChanged(gat);
@@ -580,7 +567,6 @@ 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);
@@ -589,7 +575,6 @@ namespace hal
case NetEvent::event::removed: {
//< no associated_data
- mModuleModel->removeNet(net->get_id());
gGraphContextManager->handleNetRemoved(net);
gSelectionRelay->handleNetRemoved(net->get_id());
@@ -599,7 +584,6 @@ namespace hal
case NetEvent::event::name_changed: {
//< no associated_data
- mModuleModel->updateNetName(net->get_id());
gGraphContextManager->handleNetNameChanged(net);
Q_EMIT netNameChanged(net);
@@ -618,7 +602,6 @@ 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);
@@ -627,7 +610,6 @@ 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);
@@ -636,7 +618,6 @@ 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);
@@ -645,7 +626,6 @@ 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);
@@ -681,16 +661,23 @@ namespace hal
}
}
+ void NetlistRelay::dumpModuleRecursion(Module *m)
+ {
+ for (int i=0; iget_submodule_depth(); i++)
+ std::cerr << " ";
+ std::cerr << "Mod " << m->get_id() << " <" << m->get_name() << ">\n";
+ for (Module* sm : m->get_submodules())
+ dumpModuleRecursion(sm);
+ }
+
void NetlistRelay::debugHandleFileOpened()
{
for (Module* m : gNetlist->get_modules())
mModuleColorManager->setRandomColor(m->get_id());
- mModuleModel->init();
mColorSerializer.restore(mModuleColorManager);
}
void NetlistRelay::debugHandleFileClosed()
{
- mModuleModel->clear();
}
} // namespace hal
diff --git a/plugins/gui/src/python/python_editor.cpp b/plugins/gui/src/python/python_editor.cpp
index 54e11dcfba5..b986c7c716f 100644
--- a/plugins/gui/src/python/python_editor.cpp
+++ b/plugins/gui/src/python/python_editor.cpp
@@ -852,8 +852,9 @@ namespace hal
// Update snapshots when clicking on run
this->updateSnapshots();
- for (const auto& ctx : gGraphContextManager->getContexts())
+ for (GraphContext* ctx : gGraphContextManager->getContexts())
{
+ mBlockedContextIds.append(ctx->id());
ctx->beginChange();
}
@@ -862,9 +863,10 @@ namespace hal
void PythonEditor::handleThreadFinished()
{
- for (const auto& ctx : gGraphContextManager->getContexts())
+ for (u32 ctxId : mBlockedContextIds)
{
- ctx->endChange();
+ GraphContext* ctx = gGraphContextManager->getContextById(ctxId);
+ if (ctx) ctx->endChange();
}
mFileModifiedBar->setHidden(true);
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 f1ed3a05928..754770955ef 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
@@ -69,11 +69,11 @@ namespace hal
if(!idx.isValid())
return;
- auto clickedItem = mPinModel->getItemFromIndex(idx);
- if(mPinModel->getTypeOfItem(clickedItem) != GatePinsTreeModel::itemType::pin)
+ PinTreeItem* clickedItem = dynamic_cast(mPinModel->getItemFromIndex(idx));
+ if(!clickedItem || clickedItem->type() != PinTreeItem::Pin)
return;
- auto netId = mPinModel->getNetIDsOfTreeItem(clickedItem).front();
+ auto netId = clickedItem->netIds().front();
auto clickedNet = gNetlist->get_net_by_id(netId);
if(clickedNet)
{
@@ -96,9 +96,8 @@ namespace hal
if(!idx.isValid())
return;
- BaseTreeItem* clickedItem = mPinModel->getItemFromIndex(idx);
+ PinTreeItem* clickedItem = dynamic_cast(mPinModel->getItemFromIndex(idx));
QMenu menu;
- GatePinsTreeModel::itemType type = mPinModel->getTypeOfItem(clickedItem);
bool isMiscSectionSet = false;//so that the misc-section is not set multiple times
//PLAINTEXT: NAME, DIRECTION, TYPE
@@ -118,9 +117,9 @@ namespace hal
});
//Check if jump to source or destination is possible
- if(type == GatePinsTreeModel::itemType::pin && mPinModel->getNetIDsOfTreeItem(clickedItem).size()==1)
+ if(clickedItem->type() == PinTreeItem::Pin && clickedItem->netIds().size()==1)
{
- auto netId = mPinModel->getNetIDsOfTreeItem(clickedItem).front();
+ auto netId = clickedItem->netIds().front();
auto clickedNet = gNetlist->get_net_by_id(netId);
if(clickedNet)
{
@@ -156,15 +155,19 @@ namespace hal
}
//Add nets to selection if possible
- QList netIds;
- if(type == GatePinsTreeModel::itemType::pin)
+ QList netIds;
+ if(clickedItem->type() == PinTreeItem::Pin)
{
- netIds = mPinModel->getNetIDsOfTreeItem(clickedItem);
+ netIds = clickedItem->netIds();
}
else
{
for(auto childItem : clickedItem->getChildren())
- netIds.append(mPinModel->getNetIDsOfTreeItem(childItem));
+ {
+ PinTreeItem* pti = dynamic_cast(childItem);
+ if (pti)
+ netIds.append(pti->netIds());
+ }
}
if(netIds.size() != 0)
{
@@ -191,7 +194,7 @@ namespace hal
menu.addSection("Python");
- if(type == GatePinsTreeModel::itemType::pin)
+ if(clickedItem->type() == PinTreeItem::Pin)
buildPythonMenuForPin(menu, clickedItem);
else
buildPythonMenuForPinGroup(menu, clickedItem);
@@ -201,10 +204,10 @@ namespace hal
}
- void GatePinTree::buildPythonMenuForPin(QMenu &menu, BaseTreeItem *clickedPinItem)
+ void GatePinTree::buildPythonMenuForPin(QMenu &menu, PinTreeItem *clickedPinItem)
{
// 1.) NET-OBJECT
- QList netIdsOfItem = mPinModel->getNetIDsOfTreeItem(clickedPinItem);
+ QList netIdsOfItem = clickedPinItem->netIds();
QString pythonCommandNetIds, pythonCommandName;
if(netIdsOfItem.size() == 1)
@@ -243,7 +246,7 @@ namespace hal
}
- void GatePinTree::buildPythonMenuForPinGroup(QMenu &menu, BaseTreeItem *clickedPinIGrouptem)
+ void GatePinTree::buildPythonMenuForPinGroup(QMenu &menu, PinTreeItem *clickedPinIGrouptem)
{
// 1. PYTHON LIST OF PIN GROUPS
QString pythonList = "[";
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 3b2a9e9138b..34e85964008 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
@@ -40,6 +40,7 @@ namespace hal
return qvNetName;
break;}
}
+ return QVariant();
}
void PinTreeItem::setData(QList data)
@@ -98,7 +99,7 @@ namespace hal
void GatePinsTreeModel::clear()
{
BaseTreeModel::clear();
- mPinGroupingToTreeItem.clear();
+ mPinGroupToTreeItem.clear();
mGateId = -1;
}
@@ -120,7 +121,7 @@ namespace hal
//evaluate netname (in case of inout multiple possible nets), method depends on pindirection (kind of ugly switch)
QString netName = "";
- QList netIDs;
+ QList netIDs;
switch (direction)
{
case PinDirection::input:
@@ -158,20 +159,20 @@ namespace hal
}
pinItem->setData(QList() << QString::fromStdString(pin->get_name()) << pinDirection << pinType << netName);
- pinItem->setAdditionalData(keyType, QVariant::fromValue(itemType::pin));
- pinItem->setAdditionalData(keyRepresentedNetsID, QVariant::fromValue(netIDs));
+ pinItem->setType(PinTreeItem::Pin);
+ pinItem->setNetIds(netIDs);
if (!grouping.empty())
{
- BaseTreeItem* groupingsItem = mPinGroupingToTreeItem.value(grouping, nullptr); //since its a map, its okay
- if (!groupingsItem)
+ PinTreeItem* pingroupItem = dynamic_cast(mPinGroupToTreeItem.value(grouping, nullptr)); //since its a map, its okay
+ if (!pingroupItem)
{
//assume all items in the same grouping habe the same direction and type, so the grouping-item has also these types
- groupingsItem = new PinTreeItem(grouping, pinDirection, pinType, "");
- groupingsItem->setAdditionalData(keyType, QVariant::fromValue(itemType::grouping));
- mRootItem->appendChild(groupingsItem);
- mPinGroupingToTreeItem.insert(grouping, groupingsItem);
+ pingroupItem = new PinTreeItem(grouping, pinDirection, pinType, "");
+ pingroupItem->setType(PinTreeItem::Group);
+ mRootItem->appendChild(pingroupItem);
+ mPinGroupToTreeItem.insert(grouping, pingroupItem);
}
- groupingsItem->appendChild(pinItem);
+ pingroupItem->appendChild(pinItem);
}
else
mRootItem->appendChild(pinItem);
@@ -184,16 +185,6 @@ namespace hal
return mGateId;
}
- QList GatePinsTreeModel::getNetIDsOfTreeItem(BaseTreeItem* item)
- {
- return item->getAdditionalData(keyRepresentedNetsID).value>();
- }
-
- GatePinsTreeModel::itemType GatePinsTreeModel::getTypeOfItem(BaseTreeItem* item)
- {
- return item->getAdditionalData(keyType).value();
- }
-
int GatePinsTreeModel::getNumberOfDisplayedPins()
{
Gate* g = gNetlist->get_gate_by_id(mGateId);
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 d97e986f8aa..bf04ac12806 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
@@ -67,16 +67,20 @@ namespace hal
{
setIcon(SelectionDetailsIconProvider::ModuleIcon, module->get_id());
mModuleId = module->get_id();
+ //pass module or other stuff to widgets
+ mModuleInfoTable->setModule(module);
+ mPinsTree->setModule(module);
+ mElementsTree->setModule(module);
+ mGroupingsOfItemTable->setModule(module);
+ mDataTable->setModule(module);
+ mCommentWidget->nodeChanged(Node(module->get_id(), Node::NodeType::Module));
}
else
+ {
mModuleId = 0;
- //pass module or other stuff to widgets
- mModuleInfoTable->setModule(module);
- mPinsTree->setModule(module);
- mElementsTree->setModule(module);
- mGroupingsOfItemTable->setModule(module);
- mDataTable->setModule(module);
- mCommentWidget->nodeChanged(Node(module->get_id(), Node::NodeType::Module));
+ mElementsTree->removeContent();
+ mCommentWidget->nodeChanged(Node());
+ }
}
void ModuleDetailsTabWidget::clear()
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 208a6c1d362..30e3cf47006 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,9 +61,9 @@ namespace hal
if(!clickedIndex.isValid())
return;
- BaseTreeItem* clickedItem = mModel->getItemFromIndex(clickedIndex);
+ ModuleTreeitem* clickedItem = dynamic_cast(mModel->getItemFromIndex(clickedIndex));
int id = clickedItem->getData(ModuleTreeModel::sIdColumn).toInt();
- ModuleTreeModel::itemType type = mModel->getTypeOfItem(clickedItem);
+ ModuleTreeitem::ItemType type = clickedItem->itemType();
QMenu menu;
//menu.addSection("here comes the plaintext");
@@ -97,8 +97,8 @@ namespace hal
gSelectionRelay->clear();
switch(type)
{
- case ModuleTreeModel::itemType::module: gSelectionRelay->addModule(id); break;
- case ModuleTreeModel::itemType::gate: gSelectionRelay->addGate(id); break;
+ case ModuleTreeitem::Module: gSelectionRelay->addModule(id); break;
+ case ModuleTreeitem::Gate: gSelectionRelay->addGate(id); break;
}
gSelectionRelay->relaySelectionChanged(this);
}
@@ -109,8 +109,8 @@ namespace hal
{
switch(type)
{
- case ModuleTreeModel::itemType::module: gSelectionRelay->addModule(id); break;
- case ModuleTreeModel::itemType::gate: gSelectionRelay->addGate(id); break;
+ case ModuleTreeitem::Module: gSelectionRelay->addModule(id); break;
+ case ModuleTreeitem::Gate: gSelectionRelay->addGate(id); break;
}
gSelectionRelay->relaySelectionChanged(this);
}
@@ -122,8 +122,8 @@ namespace hal
Node nd;
switch(type)
{
- case ModuleTreeModel::itemType::module: nd = Node(id, Node::Module); break;
- case ModuleTreeModel::itemType::gate: nd = Node(id, Node::Gate); break;
+ case ModuleTreeitem::Module: nd = Node(id, Node::Module); break;
+ case ModuleTreeitem::Gate: nd = Node(id, Node::Gate); break;
}
SelectionTreeView::isolateInNewViewAction(nd);
}
@@ -134,16 +134,16 @@ namespace hal
{
switch(type)
{
- case ModuleTreeModel::itemType::module: gContentManager->getGraphTabWidget()->handleModuleFocus(id); break;
- case ModuleTreeModel::itemType::gate: gContentManager->getGraphTabWidget()->handleGateFocus(id); break;
+ case ModuleTreeitem::Module: gContentManager->getGraphTabWidget()->handleModuleFocus(id); break;
+ case ModuleTreeitem::Gate: gContentManager->getGraphTabWidget()->handleGateFocus(id); break;
}
}
);
menu.addSection("Python Code");
- QString pythonGetObject = (type == ModuleTreeModel::itemType::module) ? PyCodeProvider::pyCodeModule(id) : PyCodeProvider::pyCodeGate(id);
- QString pythonDescription = (type == ModuleTreeModel::itemType::module) ? "Get module" : "Get gate";
+ QString pythonGetObject = (type == ModuleTreeitem::Module) ? PyCodeProvider::pyCodeModule(id) : PyCodeProvider::pyCodeGate(id);
+ QString pythonDescription = (type == ModuleTreeitem::Module) ? "Get module" : "Get gate";
menu.addAction(QIcon(":/icons/python"), pythonDescription,
[pythonGetObject]()
{
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 c4c34d3d2a2..b38eea359f7 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
@@ -12,6 +12,7 @@
#include "gui/user_action/action_remove_items_from_object.h"
#include "gui/user_action/action_rename_object.h"
#include "gui/user_action/action_set_object_type.h"
+#include "gui/user_action/action_pingroup.h"
#include "gui/user_action/user_action_compound.h"
#include "hal_core/netlist/gate_library/enums/pin_direction.h"
#include "hal_core/netlist/gate_library/enums/pin_type.h"
@@ -87,8 +88,7 @@ namespace hal
return;
//all relevant information
- PortTreeItem* clickedItem = static_cast(mPortModel->getItemFromIndex(clickedIndex));
- ModulePinsTreeModel::itemType type = mPortModel->getTypeOfItem(clickedItem);
+ PortTreeItem* clickedItem = static_cast(mPortModel->getItemFromIndex(clickedIndex));
Net* n = mPortModel->getNetFromItem(clickedItem);
QString name = clickedItem->getData(ModulePinsTreeModel::sNameColumn).toString();
u32 modId = mPortModel->getRepresentedModuleId();
@@ -97,7 +97,7 @@ namespace hal
std::pair sameGroup;
bool onlyPins;
std::tie(selectedPins, sameGroup, onlyPins) = getSelectedPins();
- int itemId = mPortModel->getIdOfItem(clickedItem);
+ int itemId = clickedItem->id();
QMenu menu;
//shared plaintext entries: NAME, DIRECTION, TYPE (shared with pins and groups)
@@ -119,30 +119,28 @@ namespace hal
// }
if (addToExistingActionPossible)
{
- menu.addAction("Add selection to existing pin group", [this, selectedPins, mod]() {
+ menu.addAction("Add selection to existing pin group", [selectedPins, mod]() {
PingroupSelectorDialog psd("Pingroup selector", "Select pingroup", mod, false);
if (psd.exec() == QDialog::Accepted)
{
- QSet pinSet;
+ QList pins;
auto* pinGroup = mod->get_pin_group_by_id(psd.getSelectedGroupId());
if (pinGroup == nullptr)
return;
for (auto item : selectedPins)
{
- auto* pin = mod->get_pin_by_id(mPortModel->getIdOfItem(item));
+ auto* pin = mod->get_pin_by_id(static_cast(item)->id());
if (pin == nullptr)
return;
- pinSet.insert(pin->get_id());
+ pins.append(pin->get_id());
}
- ActionAddItemsToObject* act = new ActionAddItemsToObject(QSet(), QSet(), QSet(), pinSet);
- act->setObject(UserActionObject(pinGroup->get_id(), UserActionObjectType::PinGroup));
- act->setParentObject(UserActionObject(mod->get_id(), UserActionObjectType::Module));
- act->exec();
+ ActionPingroup* act = ActionPingroup::addPinsToExistingGroup(mod,pinGroup->get_id(),pins);
+ if (act) act->exec();
}
});
}
- if (type == ModulePinsTreeModel::itemType::group) //group specific context, own helper function? (returns at the end)
+ if (clickedItem->itemType() == PortTreeItem::Group) //group specific context, own helper function? (returns at the end)
{
menu.addAction("Change name", [name, modId, itemId]() {
InputDialog ipd("Change pin group name", "New group name", name);
@@ -153,10 +151,9 @@ namespace hal
auto* group = gNetlist->get_module_by_id(modId)->get_pin_group_by_id(itemId);
if (group != nullptr)
{
- ActionRenameObject* renameObj = new ActionRenameObject(ipd.textValue());
- renameObj->setObject(UserActionObject(group->get_id(), UserActionObjectType::PinGroup));
- renameObj->setParentObject(UserActionObject(modId, UserActionObjectType::Module));
- renameObj->exec();
+ ActionPingroup* act = new ActionPingroup(PinActionType::GroupRename,itemId,ipd.textValue());
+ act->setObject(UserActionObject(modId, UserActionObjectType::Module));
+ act->exec();
}
}
});
@@ -164,10 +161,8 @@ namespace hal
auto* pinGroup = mod->get_pin_group_by_id(itemId);
if (pinGroup != nullptr)
{
- ActionDeleteObject* delObj = new ActionDeleteObject;
- delObj->setObject(UserActionObject(pinGroup->get_id(), UserActionObjectType::PinGroup));
- delObj->setParentObject(UserActionObject(mod->get_id(), UserActionObjectType::Module));
- delObj->exec();
+ ActionPingroup* act = ActionPingroup::deletePinGroup(mod,itemId);
+ if (act) act->exec();
}
});
@@ -193,10 +188,9 @@ namespace hal
auto* pin = mod->get_pin_by_id(itemId);
if (pin != nullptr)
{
- ActionRenameObject* renameObj = new ActionRenameObject(ipd.textValue());
- renameObj->setObject(UserActionObject(pin->get_id(), UserActionObjectType::Pin));
- renameObj->setParentObject(UserActionObject(mod->get_id(), UserActionObjectType::Module));
- renameObj->exec();
+ ActionPingroup* act = new ActionPingroup(PinActionType::PinRename,pin->get_id(),ipd.textValue());
+ act->setObject(UserActionObject(mod->get_id(), UserActionObjectType::Module));
+ act->exec();
}
}
});
@@ -214,9 +208,10 @@ namespace hal
if (cbd.exec() == QDialog::Accepted)
{
- ActionSetObjectType* act = new ActionSetObjectType(cbd.textValue());
- act->setObject(UserActionObject(pin->get_id(), UserActionObjectType::Pin));
- act->setParentObject(UserActionObject(mod->get_id(), UserActionObjectType::Module));
+ PinType ptype = enum_from_string(cbd.textValue().toStdString(),PinType::none);
+
+ ActionPingroup* act = new ActionPingroup(PinActionType::PinTypeChange,pin->get_id(),"",(int)ptype);
+ act->setObject(UserActionObject(mod->get_id(), UserActionObjectType::Module));
act->exec();
}
});
@@ -233,15 +228,13 @@ namespace hal
//can be both single(simple right-click, no real selection) and multi-selection
if (sameGroup.first && mod->get_pin_group_by_id(sameGroup.second)->size() > 1)
{
- menu.addAction("Remove selection from group", [this, selectedPins, mod, sameGroup]() {
- QSet pins;
+ menu.addAction("Remove selection from group", [selectedPins, mod /*, sameGroup*/]() {
+ QList pins;
for (auto item : selectedPins)
- pins.insert(mPortModel->getIdOfItem(item));
+ pins.append(static_cast(item)->id());
- ActionRemoveItemsFromObject* act = new ActionRemoveItemsFromObject(QSet(), QSet(), QSet(), pins);
- act->setObject(UserActionObject(mod->get_pin_group_by_id(sameGroup.second)->get_id(), UserActionObjectType::PinGroup));
- act->setParentObject(UserActionObject(mod->get_id(), UserActionObjectType::Module));
- act->exec();
+ ActionPingroup* act = ActionPingroup::removePinsFromGroup(mod, pins);
+ if (act) act->exec();
});
}
@@ -250,7 +243,7 @@ namespace hal
appendMultiSelectionEntries(menu, modId);
menu.addSection("Python");
- if(type == ModulePinsTreeModel::itemType::pin)
+ if(clickedItem->itemType()==PortTreeItem::Pin)
menu.addAction(QIcon(":/icons/python"), "Get pin", [modId, itemId]() { QApplication::clipboard()->setText(PyCodeProvider::pyCodeModulePinById(modId, itemId)); });
else
menu.addAction(QIcon(":/icons/python"), "Get group", [modId, itemId]() { QApplication::clipboard()->setText(PyCodeProvider::pyCodeModulePinGroup(modId, itemId)); });
@@ -272,28 +265,22 @@ namespace hal
std::tie(selectedPins, sameGroup, onlyPins) = getSelectedPins();
if (selectedPins.size() > 1)
{
- menu.addAction("Add objects to new pin group", [this, selectedPins, modId]() {
+ menu.addAction("Add objects to new pin group", [selectedPins, modId]() {
InputDialog ipd("Pingroup name", "New pingroup name", "ExampleName");
if (ipd.exec() == QDialog::Accepted && !ipd.textValue().isEmpty())
{
- QSet pins;
- auto mod = gNetlist->get_module_by_id(modId);
+ QList pins;
+ Module* mod = gNetlist->get_module_by_id(modId);
for (auto item : selectedPins)
{
- auto* pin = mod->get_pin_by_id(mPortModel->getIdOfItem(item));
+ auto* pin = mod->get_pin_by_id(static_cast(item)->id());
if (pin == nullptr)
return;
- pins.insert(pin->get_id());
+ pins.append(pin->get_id());
}
- UserActionCompound* act = new UserActionCompound;
- act->setUseCreatedObject();
- ActionCreateObject* actCreate = new ActionCreateObject(UserActionObjectType::PinGroup, ipd.textValue());
- actCreate->setParentObject(UserActionObject(modId, UserActionObjectType::Module));
- ActionAddItemsToObject* actAdd = new ActionAddItemsToObject(QSet(), QSet(), QSet(), pins);
- actAdd->setUsedInCreateContext();
- act->addAction(actCreate);
- act->addAction(actAdd);
- act->exec();
+
+ ActionPingroup* act = ActionPingroup::addPinsToNewGroup(mod,ipd.textValue(),pins);
+ if (act) act->exec();
}
});
}
@@ -309,8 +296,7 @@ namespace hal
for (auto index : selectionModel()->selectedRows())
{
PortTreeItem* item = static_cast(mPortModel->getItemFromIndex(index));
- auto itemType = mPortModel->getTypeOfItem(item);
- if (itemType == ModulePinsTreeModel::itemType::pin)
+ if (item->itemType() == PortTreeItem::Pin)
{
if (!alreadyProcessedPins.contains(item))
{
@@ -318,7 +304,7 @@ namespace hal
alreadyProcessedPins.insert(item);
}
}
- else if (itemType == ModulePinsTreeModel::itemType::group)
+ else if (item->itemType() == PortTreeItem::Group)
{
onlyPins = false;
for (auto pinItem : item->getChildren())
@@ -335,11 +321,11 @@ namespace hal
if (!selectedPins.isEmpty())
{
auto mod = gNetlist->get_module_by_id(mModuleID);
- auto* firstPin = mod->get_pin_by_id(mPortModel->getIdOfItem(selectedPins.front()));
+ auto* firstPin = mod->get_pin_by_id(static_cast(selectedPins.front())->id());
groupId = firstPin->get_group().first->get_id();
for (auto pinTreeItem : selectedPins)
{
- auto pin = mod->get_pin_by_id(mPortModel->getIdOfItem(pinTreeItem));
+ auto pin = mod->get_pin_by_id(static_cast(pinTreeItem)->id());
if (groupId != (int)pin->get_group().first->get_id())
{
sameGroup = false;
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 c6b16cdd36f..630bed28d37 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
@@ -9,34 +9,29 @@ namespace hal
{
- ModuleTreeitem::ModuleTreeitem(const std::string &name, int id, std::string tp)
- : mType(tp), mId(id), mName(name)
+ ModuleTreeitem::ModuleTreeitem(ItemType itp, int id, const QString &name, const QString &ntp)
+ : mItemType(itp), mId(id), mName(name), mNodeType(ntp)
{;}
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;}
+ case 0:
+ return mName;
+ case 1:
+ return mId;
+ case 2:
+ return mNodeType;
}
+ return QVariant();
}
void ModuleTreeitem::setData(QList data)
{
- mName = data[0].toString().toStdString();
+ mName = data[0].toString();
mId = data[1].toInt();
- mType = data[2].toString().toStdString();
+ mNodeType = data[2].toString();
}
void ModuleTreeitem::setDataAtIndex(int index, QVariant &data)
@@ -45,13 +40,13 @@ namespace hal
switch (index)
{
- case 0: mName = data.toString().toStdString(); break;
+ 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().toStdString();
+ mNodeType = data.toString();
break;
}
}
@@ -100,21 +95,21 @@ namespace hal
//add modules
for(auto mod : m->get_submodules())
{
- ModuleTreeitem* modItem = new ModuleTreeitem(mod->get_name(),
- mod->get_id(), mod->get_type());
+ ModuleTreeitem* modItem = new ModuleTreeitem(ModuleTreeitem::Module,
+ mod->get_id(),
+ QString::fromStdString(mod->get_name()),
+ QString::fromStdString(mod->get_type()));
moduleRecursive(mod, modItem);
- modItem->setAdditionalData(mKeyItemType, QVariant::fromValue(itemType::module));
- modItem->setAdditionalData(mKeyRepId, mod->get_id());
mRootItem->appendChild(modItem);
mModuleToTreeitems.insert(mod, modItem);
}
//add gates
for(auto gate : m->get_gates())
{
- 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());
+ ModuleTreeitem* gateItem = new ModuleTreeitem(ModuleTreeitem::Gate,
+ gate->get_id(),
+ QString::fromStdString(gate->get_name()),
+ QString::fromStdString(gate->get_type()->get_name()));
mRootItem->appendChild(gateItem);
mGateToTreeitems.insert(gate, gateItem);
}
@@ -137,42 +132,37 @@ namespace hal
if(!index.isValid())
return QVariant();
- BaseTreeItem* item = getItemFromIndex(index);
+ ModuleTreeitem* item = dynamic_cast(getItemFromIndex(index));
if(!item)
return QVariant();
if(role == Qt::DecorationRole && index.column() == 0)
- return getIconFromItem(getItemFromIndex(index));
+ return getIconFromItem(item);
//yes, it performs the same two checks again, should be okay though (in terms of performance)
return BaseTreeModel::data(index, role);
}
- ModuleTreeModel::itemType ModuleTreeModel::getTypeOfItem(BaseTreeItem *item) const
- {
- return item->getAdditionalData(mKeyItemType).value();
- }
-
void ModuleTreeModel::moduleRecursive(Module *mod, BaseTreeItem *modItem)
{
ModuleTreeitem* subModItem = nullptr;
for(Module* subMod : mod->get_submodules())
{
- subModItem = new ModuleTreeitem(subMod->get_name(),
- subMod->get_id(), subMod->get_type());
+ subModItem = new ModuleTreeitem(ModuleTreeitem::Module,
+ subMod->get_id(),
+ QString::fromStdString(subMod->get_name()),
+ QString::fromStdString(subMod->get_type()));
moduleRecursive(subMod, subModItem);
- subModItem->setAdditionalData(mKeyItemType, QVariant::fromValue(itemType::module));
- subModItem->setAdditionalData(mKeyRepId, subMod->get_id());
modItem->appendChild(subModItem);
mModuleToTreeitems.insert(subMod, subModItem);
}
for(auto gate : mod->get_gates())
{
- 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());
+ ModuleTreeitem* gateItem = new ModuleTreeitem(ModuleTreeitem::Gate,
+ gate->get_id(),
+ QString::fromStdString(gate->get_name()),
+ QString::fromStdString(gate->get_type()->get_name()));
modItem->appendChild(gateItem);
mGateToTreeitems.insert(gate, gateItem);
}
@@ -189,8 +179,10 @@ namespace hal
//1. Find index of first gate-type item
int startIndex = 0;
for(; startIndex < modItem->getChildCount(); startIndex++)
- if(getTypeOfItem(modItem->getChild(startIndex)) != itemType::module)
+ {
+ if(static_cast(modItem->getChild(startIndex))->itemType() != ModuleTreeitem::Module)
break;
+ }
beginResetModel();
@@ -212,10 +204,10 @@ namespace hal
beginResetModel();
for(auto gate : mod->get_gates())
{
- 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());
+ ModuleTreeitem* gateItem = new ModuleTreeitem(ModuleTreeitem::Gate,
+ gate->get_id(),
+ QString::fromStdString(gate->get_name()),
+ QString::fromStdString(gate->get_type()->get_name()));
modItem->appendChild(gateItem);
mGateToTreeitems.insert(gate, gateItem);
}
@@ -223,17 +215,17 @@ namespace hal
endResetModel();
}
- QIcon ModuleTreeModel::getIconFromItem(BaseTreeItem *item) const
+ QIcon ModuleTreeModel::getIconFromItem(ModuleTreeitem *item) const
{
if(!item)
return QIcon();
u32 id = item->getData(1).toInt();
- switch (getTypeOfItem(item))
+ switch (item->itemType())
{
- case itemType::module:
+ case ModuleTreeitem::Module:
return QIcon(*SelectionDetailsIconProvider::instance()->getIcon(SelectionDetailsIconProvider::ModuleIcon,id));
- case itemType::gate:
+ case ModuleTreeitem::Gate:
return QIcon(*SelectionDetailsIconProvider::instance()->getIcon(SelectionDetailsIconProvider::GateIcon,id));
default:
return QIcon();
@@ -297,11 +289,11 @@ namespace hal
{
beginResetModel();
auto addedMod = gNetlist->get_module_by_id(added_module);
- ModuleTreeitem* addedSubmodItem = new ModuleTreeitem(addedMod->get_name(), addedMod->get_id(),
- addedMod->get_type());
+ ModuleTreeitem* addedSubmodItem = new ModuleTreeitem(ModuleTreeitem::Module,
+ addedMod->get_id(),
+ QString::fromStdString(addedMod->get_name()),
+ QString::fromStdString(addedMod->get_type()));
moduleRecursive(addedMod, addedSubmodItem);
- addedSubmodItem->setAdditionalData(mKeyItemType, QVariant::fromValue(itemType::module));
- addedSubmodItem->setAdditionalData(mKeyRepId, addedMod->get_id());
parentModItem ? parentModItem->insertChild(0, addedSubmodItem) : mRootItem->insertChild(0, addedSubmodItem);
mModuleToTreeitems.insert(addedMod, addedSubmodItem);
endResetModel();
@@ -321,11 +313,11 @@ namespace hal
treeItemsQueue.enqueue(removedModItem);
while(!treeItemsQueue.isEmpty())
{
- BaseTreeItem* current = treeItemsQueue.dequeue();
- switch (getTypeOfItem(current))
+ ModuleTreeitem* current = static_cast(treeItemsQueue.dequeue());
+ switch (current->itemType())
{
- case itemType::module: mModuleToTreeitems.remove(gNetlist->get_module_by_id(current->getData(ModuleTreeModel::sIdColumn).toInt())); break;
- case itemType::gate: mGateToTreeitems.remove(gNetlist->get_gate_by_id(current->getData(ModuleTreeModel::sIdColumn).toInt()));break;
+ case ModuleTreeitem::Module: mModuleToTreeitems.remove(gNetlist->get_module_by_id(current->getData(ModuleTreeModel::sIdColumn).toInt())); break;
+ case ModuleTreeitem::Gate: mGateToTreeitems.remove(gNetlist->get_gate_by_id(current->getData(ModuleTreeModel::sIdColumn).toInt()));break;
}
for(auto child : current->getChildren())
treeItemsQueue.enqueue(child);
@@ -352,12 +344,13 @@ namespace hal
auto assignedGate = gNetlist->get_gate_by_id(assigned_gate);
int indexToInsert = 0; //first item after the modules
for(; indexToInsert < modItem->getChildCount(); indexToInsert++)
- if(getTypeOfItem(modItem->getChild(indexToInsert)) != itemType::module)
+ if(static_cast(modItem->getChild(indexToInsert))->itemType() != ModuleTreeitem::Module)
break;
- ModuleTreeitem* gateItem = new ModuleTreeitem(assignedGate->get_name(),
- assignedGate->get_id(), assignedGate->get_type()->get_name());
- gateItem->setAdditionalData(mKeyItemType, QVariant::fromValue(itemType::gate));
+ ModuleTreeitem* gateItem = new ModuleTreeitem(ModuleTreeitem::Gate,
+ assignedGate->get_id(),
+ QString::fromStdString(assignedGate->get_name()),
+ QString::fromStdString(assignedGate->get_type()->get_name()));
mGateToTreeitems.insert(assignedGate, gateItem);
//beginInsertRows(getIndexFromItem(modItem), indexToInsert, indexToInsert);
beginResetModel();
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 0073b6e8a0c..bf68a43ff41 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
@@ -10,34 +10,29 @@
namespace hal
{
- NetlistElementsTreeitem::NetlistElementsTreeitem(const QString &name, int id, QString tp)
- : mType(tp), mId(id), mName(name)
+ NetlistElementsTreeitem::NetlistElementsTreeitem(ItemType itp, u32 id_, const QString &name, const QString &ntp)
+ : mItemType(itp), mId(id_), mName(name), mNodeType(ntp)
{;}
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;}
+ case 0:
+ return mName;
+ case 1:
+ return mId;
+ case 2:
+ return mNodeType;
}
+ return QVariant();
}
void NetlistElementsTreeitem::setData(QList data)
{
mName = data[0].toString();
mId = data[1].toInt();
- mType = data[2].toString();
+ mNodeType = data[2].toString();
}
@@ -53,7 +48,7 @@ namespace hal
for (int j=0; j<3; j++)
if (data.toString() == ctyp[j])
{
- mType = data.toString();
+ mNodeType = data.toString();
break;
}
}
@@ -142,12 +137,12 @@ namespace hal
Module* mod = gNetlist->get_module_by_id(id);
if(!mod)
continue;
- NetlistElementsTreeitem* modItem = new NetlistElementsTreeitem(QString::fromStdString(mod->get_name()),
- mod->get_id(), QString::fromStdString(mod->get_type()));
+ NetlistElementsTreeitem* modItem = new NetlistElementsTreeitem(NetlistElementsTreeitem::Module,
+ mod->get_id(),
+ QString::fromStdString(mod->get_name()),
+ QString::fromStdString(mod->get_type()));
if(displayModulesRecursive)
moduleRecursive(mod, modItem, showGatesInSubmods, showNetsInSubmods);
- modItem->setAdditionalData(keyItemType, QVariant::fromValue(itemType::module));
- modItem->setAdditionalData(keyRepresentedID, mod->get_id());
mRootItem->appendChild(modItem);
mModuleToTreeitems.insert(mod, modItem);
}
@@ -155,20 +150,19 @@ namespace hal
for(int id : gateIds)
{
Gate* gate = gNetlist->get_gate_by_id(id);
- 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());
+ NetlistElementsTreeitem* gateItem = new NetlistElementsTreeitem(NetlistElementsTreeitem::Gate,
+ gate->get_id(),
+ QString::fromStdString(gate->get_name()),
+ QString::fromStdString(gate->get_type()->get_name()));
mRootItem->appendChild(gateItem);
mGateToTreeitems.insert(gate, gateItem);
}
for(int id : netIds)
{
Net* net = gNetlist->get_net_by_id(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());
+ NetlistElementsTreeitem* netItem = new NetlistElementsTreeitem(NetlistElementsTreeitem::Net,
+ net->get_id(),
+ QString::fromStdString(net->get_name()));
mRootItem->appendChild(netItem);
mNetToTreeitems.insert(net, netItem);
}
@@ -196,16 +190,6 @@ namespace hal
Q_EMIT numberOfSubmodulesChanged(mod->get_submodules().size());
}
- NetlistElementsTreeModel::itemType NetlistElementsTreeModel::getTypeOfItem(NetlistElementsTreeitem *item) const
- {
- return item->getAdditionalData(keyItemType).value();
- }
-
- int NetlistElementsTreeModel::getRepresentedIdOfItem(NetlistElementsTreeitem *item) const
- {
- return item->getAdditionalData(keyRepresentedID).toInt();
- }
-
void NetlistElementsTreeModel::gateNameChanged(Gate *g)
{
for(BaseTreeItem* gateItem : mGateToTreeitems.values(g))
@@ -299,13 +283,13 @@ namespace hal
while(!treeItemsQueue.isEmpty())
{
NetlistElementsTreeitem* currentItem = treeItemsQueue.dequeue();
- int id = currentItem->getAdditionalData(keyRepresentedID).toUInt();
+ int id = currentItem->id();
- switch (getTypeOfItem(currentItem))
+ switch (currentItem->itemType())
{
- case itemType::module: mModuleToTreeitems.remove(gNetlist->get_module_by_id(id),currentItem); break;
- case itemType::gate: mGateToTreeitems.remove(gNetlist->get_gate_by_id(id), currentItem); break;
- case itemType::net: mNetToTreeitems.remove(gNetlist->get_net_by_id(id), currentItem); break;
+ case NetlistElementsTreeitem::Module : mModuleToTreeitems.remove(gNetlist->get_module_by_id(id),currentItem); break;
+ case NetlistElementsTreeitem::Gate : mGateToTreeitems.remove(gNetlist->get_gate_by_id(id), currentItem); break;
+ case NetlistElementsTreeitem::Net : mNetToTreeitems.remove(gNetlist->get_net_by_id(id), currentItem); break;
}
for(BaseTreeItem* child : currentItem->getChildren()){
@@ -346,14 +330,14 @@ namespace hal
int indexToInsert = 0;
for(; indexToInsert < modItem->getChildCount(); indexToInsert++) {
NetlistElementsTreeitem* neti = static_cast(modItem->getChild(indexToInsert));
- if(getTypeOfItem(neti) != itemType::module)
+ if(neti->itemType() != NetlistElementsTreeitem::Module)
break;
}
- 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());
+ NetlistElementsTreeitem* gateItem = new NetlistElementsTreeitem(NetlistElementsTreeitem::Gate,
+ assignedGate->get_id(),
+ QString::fromStdString(assignedGate->get_name()),
+ QString::fromStdString(assignedGate->get_type()->get_name()));
//beginInsertRows(getIndexFromItem(modItem), indexToInsert, indexToInsert);
beginResetModel();
modItem->insertChild(indexToInsert, gateItem);
@@ -390,11 +374,11 @@ namespace hal
Module* addedModule = gNetlist->get_module_by_id(added_module);
auto appendNewSubmodItem = [this, addedModule](BaseTreeItem* parentModItem){
- NetlistElementsTreeitem* addedSubmodItem = new NetlistElementsTreeitem(QString::fromStdString(addedModule->get_name()),
- addedModule->get_id(), QString::fromStdString(addedModule->get_type()));
+ NetlistElementsTreeitem* addedSubmodItem = new NetlistElementsTreeitem(NetlistElementsTreeitem::Module,
+ addedModule->get_id(),
+ QString::fromStdString(addedModule->get_name()),
+ 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) {
@@ -422,11 +406,11 @@ namespace hal
NetlistElementsTreeitem* subModItem = nullptr;
for(Module* subMod : mod->get_submodules())
{
- subModItem = new NetlistElementsTreeitem(QString::fromStdString(subMod->get_name()),
- subMod->get_id(), QString::fromStdString(subMod->get_type()));
+ subModItem = new NetlistElementsTreeitem(NetlistElementsTreeitem::Module,
+ subMod->get_id(),
+ QString::fromStdString(subMod->get_name()),
+ QString::fromStdString(subMod->get_type()));
moduleRecursive(subMod, subModItem, showGates);
- subModItem->setAdditionalData(keyItemType, QVariant::fromValue(itemType::module));
- subModItem->setAdditionalData(keyRepresentedID, subMod->get_id());
modItem->appendChild(subModItem);
mModuleToTreeitems.insert(subMod, subModItem);
}
@@ -434,10 +418,10 @@ namespace hal
{
for(auto gate : mod->get_gates())
{
- 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());
+ NetlistElementsTreeitem* gateItem = new NetlistElementsTreeitem(NetlistElementsTreeitem::Gate,
+ gate->get_id(),
+ QString::fromStdString(gate->get_name()),
+ QString::fromStdString(gate->get_type()->get_name()));
modItem->appendChild(gateItem);
mGateToTreeitems.insert(gate, gateItem);
}
@@ -446,10 +430,10 @@ namespace hal
{
for(auto net : mod->get_internal_nets())
{
- 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());
+ NetlistElementsTreeitem* netItem = new NetlistElementsTreeitem(NetlistElementsTreeitem::Net,
+ net->get_id(),
+ QString::fromStdString(net->get_name()),
+ "");
modItem->appendChild(netItem);
mNetToTreeitems.insert(net, netItem);
}
@@ -462,11 +446,11 @@ namespace hal
return QIcon();
u32 id = item->getData(1).toInt();
- switch (getTypeOfItem(item))
+ switch (item->itemType())
{
- case itemType::module:
+ case NetlistElementsTreeitem::Module:
return QIcon(*SelectionDetailsIconProvider::instance()->getIcon(SelectionDetailsIconProvider::ModuleIcon,id));
- case itemType::gate:
+ case NetlistElementsTreeitem::Gate:
return QIcon(*SelectionDetailsIconProvider::instance()->getIcon(SelectionDetailsIconProvider::GateIcon,id));
default:
return QIcon();
@@ -476,27 +460,26 @@ namespace hal
void NetlistElementsTreeModel::updateInternalNetsOfModule(NetlistElementsTreeitem *moduleItem)
{
BaseTreeItem* moduleItemBase = static_cast(moduleItem);
- BaseTreeItem* mRootBase = static_cast(mRootItem);
- int moduleId = (moduleItemBase == mRootBase) ? mModId : moduleItem->getAdditionalData(keyRepresentedID).toInt();
+ BaseTreeItem* mRootBase = static_cast(mRootItem);
+ int moduleId = (moduleItemBase == mRootBase) ? mModId : moduleItem->id();
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(static_cast(moduleItem->getChild(moduleItem->getChildCount()-1))) == itemType::net)
+ while(moduleItem->getChildCount() > 0 && static_cast