36 #include <QApplication>
38 #include <QGraphicsRectItem>
39 #include <QInputDialog>
41 #include <QMessageBox>
44 #include <QToolButton>
45 #include <QVBoxLayout>
46 #include <QVariantAnimation>
52 SettingsItemSpinbox* GraphWidget::sSettingAnimationDuration =
53 new SettingsItemSpinbox(
"Animation Duration [1/10s]",
54 "graph_view/animation_duration",
56 "Appearance:Graph View",
57 "Duration of 'fly to gate' animation when viewport is zooming in on new target. Unit is 1/10 second, thus 20=2sec, 10=1sec. Value of zero turns animation off.");
59 GraphWidget* GraphWidget::sInstance =
nullptr;
64 mSpinnerWidget(new
SpinnerWidget(this)), mCommentWidget(nullptr), mCurrentExpansion(0)
76 mSpinnerWidget->
hide();
113 mSpinnerWidget->
hide();
114 mOverlay->
setWidget(mNavigationWidgetV3);
118 else if (mStoreViewport.mValid)
124 void GraphWidget::hideOverlay()
130 mProgressBar =
nullptr;
136 mCommentWidget =
nullptr;
156 qApp->processEvents();
182 qApp->processEvents();
207 mStoreViewport.mValid =
false;
212 mStoreViewport.mValid =
true;
214 mStoreViewport.mGrid = mView->closestLayouterPos(mView->
mapToScene(
QPoint(viewportCenter)));
218 QRectF GraphWidget::restoreViewport(
bool reset)
220 if (!mStoreViewport.mValid)
223 mStoreViewport.mValid =
false;
226 QPointF topLeft = mStoreViewport.mRect.topLeft() - mStoreViewport.mGrid.second + centerPos;
227 return QRectF(topLeft, mStoreViewport.mRect.size());
238 switch (
event->key())
241 handleNavigationLeftRequest();
245 handleNavigationRightRequest();
249 handleNavigationUpRequest();
253 handleNavigationDownRequest();
271 void GraphWidget::substituteByVisibleModules(
const QSet<u32>& gates,
280 for (
auto& mid : modules)
287 target_modules.
insert(mid);
293 assert(common.
size() == 1);
294 target_modules += common;
298 for (
auto& gid : gates)
311 target_modules += common;
320 for (
auto& mid : mContext->
modules())
325 remove_modules.
insert(mid);
329 while (it != target_modules.
constEnd())
334 it = target_modules.
erase(it);
344 new_module_set = (mContext->
modules() - remove_modules) + target_modules;
345 for (
auto& gid : mContext->
gates())
354 while (it != target_gates.
constEnd())
359 it = target_gates.
erase(it);
375 void GraphWidget::handleNavigationJumpRequested(
const Node&
origin,
const u32 via_net,
const QSet<u32>& to_gates,
const QSet<u32>& to_modules)
384 if (!n || (to_gates.
empty() && to_modules.
empty()))
396 substituteByVisibleModules(to_gates, to_modules, final_gates, final_modules, remove_gates, remove_modules);
404 if (!nonvisible_gates.
empty() || !nonvisible_modules.
empty())
410 std::vector<Net*> in_nets;
411 if (to_gates.
empty())
419 bool netIsInput = std::find(in_nets.begin(), in_nets.end(), n) != in_nets.cend();
425 ActionRemoveItemsFromObject* act =
new ActionRemoveItemsFromObject(remove_modules, remove_gates);
431 ActionAddItemsToObject* act =
new ActionAddItemsToObject(nonvisible_modules, nonvisible_gates);
432 act->setPlacementHint(PlacementHint(placementMode,
origin));
460 if (final_gates.
size() == 1 && final_modules.
empty())
468 for (
const auto& pin : g->get_type()->get_input_pins())
470 if (g->get_fan_in_net(pin) == n)
481 for (
const auto& pin : g->get_type()->get_output_pins())
483 if (g->get_fan_out_net(pin) == n)
494 else if (final_modules.
size() == 1 && final_gates.
empty())
505 const GraphicsNode* gnode =
static_cast<const GraphicsNode*
>(nbox->item());
508 int inx = gnode->inputByNet(n->get_id());
511 inx = gnode->outputByNet(n->get_id());
537 ensureItemsVisible(final_gates, final_modules);
540 void GraphWidget::handleModuleDoubleClicked(
const u32 id)
544 handleEnterModuleRequested(
id);
548 void GraphWidget::handleNavigationLeftRequest()
552 mOverlay->
setWidget(mNavigationWidgetV3);
567 Net* n = g->get_fan_in_net(pin);
572 if (n->get_num_of_sources() == 0)
579 else if (n->get_num_of_sources() == 1)
581 handleNavigationJumpRequested(Node(g->get_id(),
Node::Gate), n->get_id(), {n->get_sources().at(0)->get_gate()->get_id()}, {});
585 mNavigationWidgetV3->
setup(navigateLeft);
590 else if (g->get_type()->get_input_pins().size())
605 if (n->get_num_of_sources() == 0)
608 if (n->get_num_of_sources() == 1)
610 handleNavigationJumpRequested(mContext->
getNetDestination(n), n->get_id(), {n->get_sources()[0]->get_gate()->get_id()}, {});
614 mNavigationWidgetV3->
setup(navigateLeft);
632 const GraphicsNode* gnode =
static_cast<const GraphicsNode*
>(nbox->item());
637 if (n->get_num_of_sources() == 0)
644 else if (n->get_num_of_sources() == 1)
646 handleNavigationJumpRequested(Node(m->get_id(),
Node::Module), n->get_id(), {n->get_sources()[0]->get_gate()->get_id()}, {});
650 mNavigationWidgetV3->
setup(navigateLeft);
655 else if (m->get_input_nets().size())
666 void GraphWidget::handleNavigationRightRequest()
670 mOverlay->
setWidget(mNavigationWidgetV3);
688 if (n->get_num_of_destinations() == 0)
695 else if (n->get_num_of_destinations() == 1)
697 handleNavigationJumpRequested(Node(g->get_id(),
Node::Gate), n->get_id(), {n->get_destinations()[0]->get_gate()->get_id()}, {});
701 mNavigationWidgetV3->
setup(navigateRight);
706 else if (g->get_type()->get_output_pins().size())
720 if (n->get_num_of_destinations() == 0)
723 if (n->get_num_of_destinations() == 1)
725 handleNavigationJumpRequested(mContext->
getNetSource(n), n->get_id(), {n->get_destinations()[0]->get_gate()->get_id()}, {});
729 mNavigationWidgetV3->
setup(navigateRight);
747 const GraphicsNode* gnode =
static_cast<const GraphicsNode*
>(nbox->item());
752 if (n->get_num_of_destinations() == 0)
759 else if (n->get_num_of_destinations() == 1)
761 handleNavigationJumpRequested(Node(m->get_id(),
Node::Module), n->get_id(), {n->get_destinations()[0]->get_gate()->get_id()}, {});
765 mNavigationWidgetV3->
setup(navigateRight);
770 else if (m->get_output_nets().size())
798 log_warning(
"gui",
"Cannot navigate from selected origin module ID={}, folded module not found on current view.",
id);
805 log_warning(
"gui",
"Cannot navigate from selected origin gate ID={}, gate not found on current view.",
id);
810 switch (navigateDirection) {
813 if (ep->get_gate())
return true;
817 if (ep->get_gate())
return true;
822 log_warning(
"gui",
"Cannot navigate from selected origin net ID={}, net not found on current view.",
id);
825 log_warning(
"gui",
"Cannot navigate, no origin selected");
831 void GraphWidget::handleNavigationUpRequest()
840 void GraphWidget::handleNavigationDownRequest()
849 void GraphWidget::handleEnterModuleRequested(
const u32 id)
852 if (m->get_gates().empty() && m->get_submodules().empty())
855 msg.
setText(
"This module does not contain any gates, it cannot be unfolded.");
866 ActionUnfoldModule* act =
new ActionUnfoldModule(
id);
867 act->setContextId(mContext->
id());
874 void GraphWidget::ensureItemsVisible(
const QSet<u32>& gates,
const QSet<u32>& modules)
884 for (
auto id : gates)
888 min_x = std::min(min_x,
static_cast<int>(
rect.left()));
889 max_x = std::max(max_x,
static_cast<int>(
rect.right()));
890 min_y = std::min(min_y,
static_cast<int>(
rect.top()));
891 max_y = std::max(max_y,
static_cast<int>(
rect.bottom()));
895 for (
auto id : modules)
899 min_x = std::min(min_x,
static_cast<int>(
rect.left()));
900 max_x = std::max(max_x,
static_cast<int>(
rect.right()));
901 min_y = std::min(min_y,
static_cast<int>(
rect.top()));
902 max_y = std::max(max_y,
static_cast<int>(
rect.bottom()));
907 focusRect(targetRect,
true);
930 min_x = std::min(min_x,
static_cast<int>(
rect.left()));
931 max_x = std::max(max_x,
static_cast<int>(
rect.right()));
932 min_y = std::min(min_y,
static_cast<int>(
rect.top()));
933 max_y = std::max(max_y,
static_cast<int>(
rect.bottom()));
942 min_x = std::min(min_x,
static_cast<int>(
rect.left()));
943 max_x = std::max(max_x,
static_cast<int>(
rect.right()));
944 min_y = std::min(min_y,
static_cast<int>(
rect.top()));
945 max_y = std::max(max_y,
static_cast<int>(
rect.bottom()));
954 min_x = std::min(min_x,
static_cast<int>(
rect.left()));
955 max_x = std::max(max_x,
static_cast<int>(
rect.right()));
956 min_y = std::min(min_y,
static_cast<int>(
rect.top()));
957 max_y = std::max(max_y,
static_cast<int>(
rect.bottom()));
960 if (min_x == INT_MAX ||
965 log_warning(
"gui",
"Attempt to zoom in on graphics item before layout was rendered.");
971 focusRect(targetRect,
true);
974 void GraphWidget::focusRect(
QRectF targetRect,
bool applyCenterFix)
977 if (mStoreViewport.mValid)
979 currentRect = restoreViewport();
993 int durationMsec = sSettingAnimationDuration->
value().
toInt() * 100;
998 if (!(targetRect == mLastTargetRect && currentRect == mRectAfterFocus))
1000 mLastTargetRect = targetRect;
1004 auto centerFix = targetRect.
center();
1013 anim->setDuration(durationMsec);
1014 anim->setStartValue(currentRect);
1015 anim->setEndValue(targetRect);
1037 focusRect(targetRect,
false);
1047 QRectF targetRect =
net->sceneBoundingRect().marginsAdded(
QMargins(50, 50, 50, 50));
1048 focusRect(targetRect,
false);
1059 focusRect(targetRect,
false);
1063 void GraphWidget::resetFocus()
1082 static std::atomic<u64> issuedTicket(0);
1083 static u64 appliedTicket = 0;
1085 const u64 ticket = ++issuedTicket;
1088 auto apply = [percent, qmsg, ticket]() {
1089 if (!sInstance)
return;
1090 if (ticket < appliedTicket)
1092 appliedTicket = ticket;
1096 sInstance->
showBusy(percent, qmsg);
1101 qApp->processEvents();
virtual void setValue(int percent)=0
virtual void setText(const QString &txt)=0
Abstract class for Widgets within HAL's ContentArea.
QVBoxLayout * mContentLayout
const std::vector< Net * > & get_fan_in_nets() const
GateType * get_type() const
Net * get_fan_out_net(const std::string &pin_name) const
std::vector< GatePin * > get_input_pins() const
Logical container for modules, gates, and nets.
Node getNetSource(const Net *n) const
Node getNetDestination(const Net *n) const
const QSet< u32 > & gates() const
const QSet< u32 > & modules() const
void setParentWidget(GraphWidget *gw)
GraphLayouter * getLayouter() const
const QSet< u32 > & nets() const
bool sceneUpdateInProgress() const
void openModuleInView(u32 moduleId, bool unfold)
A view to display the rendered graph (needs a GraphicsScene).
void moduleDoubleClicked(u32 id)
qreal gridXposition(int ix) const
qreal gridYposition(int iy) const
const NodeBoxes & boxes() const
Abstract base class for gates.
Abstract base class for modules.
The basic net class all other nets inherit from.
const GraphicsGate * getGateItem(const u32 id) const
const GraphicsModule * getModuleItem(const u32 id) const
const GraphicsNet * getNetItem(const u32 id) const
static QMap< QString, GuiExtensionInterface * > getGuiExtensions()
const std::unordered_set< Net * > & get_input_nets() const
std::vector< Endpoint * > get_destinations(const std::function< bool(Endpoint *ep)> &filter=nullptr) const
std::vector< Endpoint * > get_sources(const std::function< bool(Endpoint *ep)> &filter=nullptr) const
Gate * get_gate_by_id(const u32 gate_id) const
Module * get_module_by_id(u32 module_id) const
Net * get_net_by_id(u32 net_id) const
NodeBox * boxForNode(const Node &n) const
boxForNode find NodeBox by node
The Node class object represents a module or a gate.
PlacementModeType
The PlacementModeType enum either most compact arrangement (Standard) or to the left or right of give...
int numberSelectedGates() const
ItemType focusType() const
int numberSelectedItems() const
void setFocus(ItemType ftype, u32 fid, Subfocus sfoc=Subfocus::None, u32 sfinx=0)
const QSet< u32 > & selectedNets() const
void relaySelectionChanged(void *sender)
int numberSelectedNets() const
void relaySubfocusChanged(void *sender)
QList< u32 > selectedModulesList() const
const QSet< u32 > & selectedGates() const
void setFocusDirect(ItemType ftype, u32 fid, Subfocus sfoc=Subfocus::None, u32 sfinx=0)
QList< u32 > selectedNetsList() const
const QSet< u32 > & selectedModules() const
Subfocus subfocus() const
std::vector< u32 > selectedGatesVector() const
int numberSelectedModules() const
u32 subfocusIndex() const
std::vector< u32 > selectedNetsVector() const
QList< u32 > selectedGatesList() const
void setSelectedGates(const QSet< u32 > &ids)
std::vector< u32 > selectedModulesVector() const
void setSelectedModules(const QSet< u32 > &ids)
virtual QVariant value() const override
#define log_warning(channel,...)
const Module * module(const Gate *g, const NodeBoxes &boxes)
QSet< u32 > parentModules(Gate *g)
std::vector< T > to_vector(const Container< T, Args... > &container)
GraphContextManager * gGraphContextManager
SelectionRelay * gSelectionRelay
void setFrameStyle(int style)
QRectF sceneBoundingRect() const const
void centerOn(const QPointF &pos)
void setDragMode(QGraphicsView::DragMode mode)
void fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRatioMode)
QPointF mapToScene(const QPoint &point) const const
void setRenderHint(QPainter::RenderHint hint, bool enabled)
void setScene(QGraphicsScene *scene)
virtual int exec() override
void setWindowTitle(const QString &title)
void setText(const QString &text)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
QThread * thread() const const
QPoint bottomRight() const const
QPoint topLeft() const const
QPointF center() const const
qreal height() const const
QRectF marginsAdded(const QMarginsF &margins) const const
void moveCenter(const QPointF &position)
void setHeight(qreal height)
void setWidth(qreal width)
qreal width() const const
QSet::const_iterator constBegin() const const
QSet::const_iterator constEnd() const const
bool contains(const T &value) const const
QSet::iterator erase(QSet::iterator pos)
QSet::iterator insert(const T &value)
bool intersects(const QSet< T > &other) const const
bool isEmpty() const const
QString fromStdString(const std::string &str)
bool isEmpty() const const
QThread * currentThread()
int toInt(bool *ok) const const
QRectF toRectF() const const
void valueChanged(const QVariant &value)