36 #include <QApplication>
38 #include <QGraphicsRectItem>
39 #include <QInputDialog>
41 #include <QMessageBox>
44 #include <QToolButton>
45 #include <QVBoxLayout>
46 #include <QVariantAnimation>
50 SettingsItemSpinbox* GraphWidget::sSettingAnimationDuration =
51 new SettingsItemSpinbox(
"Animation Duration [1/10s]",
52 "graph_view/animation_duration",
54 "Appearance:Graph View",
55 "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.");
57 GraphWidget* GraphWidget::sInstance =
nullptr;
62 mSpinnerWidget(new
SpinnerWidget(this)), mCommentWidget(nullptr), mCurrentExpansion(0)
74 mSpinnerWidget->
hide();
111 mSpinnerWidget->
hide();
112 mOverlay->
setWidget(mNavigationWidgetV3);
116 else if (mStoreViewport.mValid)
122 void GraphWidget::hideOverlay()
128 mProgressBar =
nullptr;
134 mCommentWidget =
nullptr;
154 qApp->processEvents();
180 qApp->processEvents();
205 mStoreViewport.mValid =
false;
210 mStoreViewport.mValid =
true;
212 mStoreViewport.mGrid = mView->closestLayouterPos(mView->
mapToScene(
QPoint(viewportCenter)));
216 QRectF GraphWidget::restoreViewport(
bool reset)
218 if (!mStoreViewport.mValid)
221 mStoreViewport.mValid =
false;
224 QPointF topLeft = mStoreViewport.mRect.topLeft() - mStoreViewport.mGrid.second + centerPos;
225 return QRectF(topLeft, mStoreViewport.mRect.size());
236 switch (
event->key())
239 handleNavigationLeftRequest();
243 handleNavigationRightRequest();
247 handleNavigationUpRequest();
251 handleNavigationDownRequest();
269 void GraphWidget::substituteByVisibleModules(
const QSet<u32>& gates,
278 for (
auto& mid : modules)
285 target_modules.
insert(mid);
291 assert(common.
size() == 1);
292 target_modules += common;
296 for (
auto& gid : gates)
309 target_modules += common;
318 for (
auto& mid : mContext->
modules())
323 remove_modules.
insert(mid);
327 while (it != target_modules.
constEnd())
332 it = target_modules.
erase(it);
342 new_module_set = (mContext->
modules() - remove_modules) + target_modules;
343 for (
auto& gid : mContext->
gates())
352 while (it != target_gates.
constEnd())
357 it = target_gates.
erase(it);
373 void GraphWidget::handleNavigationJumpRequested(
const Node& origin,
const u32 via_net,
const QSet<u32>& to_gates,
const QSet<u32>& to_modules)
382 if (!
n || (to_gates.
empty() && to_modules.
empty()))
394 substituteByVisibleModules(to_gates, to_modules, final_gates, final_modules, remove_gates, remove_modules);
402 if (!nonvisible_gates.
empty() || !nonvisible_modules.
empty())
408 std::vector<Net*> in_nets;
409 if (to_gates.
empty())
417 bool netIsInput = std::find(in_nets.begin(), in_nets.end(),
n) != in_nets.cend();
423 ActionRemoveItemsFromObject* act =
new ActionRemoveItemsFromObject(remove_modules, remove_gates);
429 ActionAddItemsToObject* act =
new ActionAddItemsToObject(nonvisible_modules, nonvisible_gates);
430 act->setPlacementHint(PlacementHint(placementMode, origin));
458 if (final_gates.
size() == 1 && final_modules.
empty())
466 for (
const auto& pin :
g->get_type()->get_input_pins())
468 if (
g->get_fan_in_net(pin) ==
n)
479 for (
const auto& pin :
g->get_type()->get_output_pins())
481 if (
g->get_fan_out_net(pin) ==
n)
492 else if (final_modules.
size() == 1 && final_gates.
empty())
503 const GraphicsNode* gnode =
static_cast<const GraphicsNode*
>(nbox->item());
506 int inx = gnode->inputByNet(
n->get_id());
509 inx = gnode->outputByNet(
n->get_id());
535 ensureItemsVisible(final_gates, final_modules);
538 void GraphWidget::handleModuleDoubleClicked(
const u32 id)
542 handleEnterModuleRequested(
id);
546 void GraphWidget::handleNavigationLeftRequest()
550 mOverlay->
setWidget(mNavigationWidgetV3);
565 Net*
n =
g->get_fan_in_net(pin);
570 if (
n->get_num_of_sources() == 0)
577 else if (
n->get_num_of_sources() == 1)
579 handleNavigationJumpRequested(Node(
g->get_id(),
Node::Gate),
n->get_id(), {n->get_sources().at(0)->get_gate()->get_id()}, {});
583 mNavigationWidgetV3->
setup(navigateLeft);
588 else if (
g->get_type()->get_input_pins().size())
603 if (
n->get_num_of_sources() == 0)
606 if (
n->get_num_of_sources() == 1)
608 handleNavigationJumpRequested(mContext->
getNetDestination(
n),
n->get_id(), {n->get_sources()[0]->get_gate()->get_id()}, {});
612 mNavigationWidgetV3->
setup(navigateLeft);
630 const GraphicsNode* gnode =
static_cast<const GraphicsNode*
>(nbox->item());
635 if (
n->get_num_of_sources() == 0)
642 else if (
n->get_num_of_sources() == 1)
644 handleNavigationJumpRequested(Node(m->get_id(),
Node::Module),
n->get_id(), {n->get_sources()[0]->get_gate()->get_id()}, {});
648 mNavigationWidgetV3->
setup(navigateLeft);
653 else if (m->get_input_nets().size())
664 void GraphWidget::handleNavigationRightRequest()
668 mOverlay->
setWidget(mNavigationWidgetV3);
686 if (
n->get_num_of_destinations() == 0)
693 else if (
n->get_num_of_destinations() == 1)
695 handleNavigationJumpRequested(Node(
g->get_id(),
Node::Gate),
n->get_id(), {n->get_destinations()[0]->get_gate()->get_id()}, {});
699 mNavigationWidgetV3->
setup(navigateRight);
704 else if (
g->get_type()->get_output_pins().size())
718 if (
n->get_num_of_destinations() == 0)
721 if (
n->get_num_of_destinations() == 1)
723 handleNavigationJumpRequested(mContext->
getNetSource(
n),
n->get_id(), {n->get_destinations()[0]->get_gate()->get_id()}, {});
727 mNavigationWidgetV3->
setup(navigateRight);
745 const GraphicsNode* gnode =
static_cast<const GraphicsNode*
>(nbox->item());
750 if (
n->get_num_of_destinations() == 0)
757 else if (
n->get_num_of_destinations() == 1)
759 handleNavigationJumpRequested(Node(m->get_id(),
Node::Module),
n->get_id(), {n->get_destinations()[0]->get_gate()->get_id()}, {});
763 mNavigationWidgetV3->
setup(navigateRight);
768 else if (m->get_output_nets().size())
796 log_warning(
"gui",
"Cannot navigate from selected origin module ID={}, folded module not found on current view.",
id);
803 log_warning(
"gui",
"Cannot navigate from selected origin gate ID={}, gate not found on current view.",
id);
808 switch (navigateDirection) {
811 if (ep->get_gate())
return true;
815 if (ep->get_gate())
return true;
820 log_warning(
"gui",
"Cannot navigate from selected origin net ID={}, net not found on current view.",
id);
823 log_warning(
"gui",
"Cannot navigate, no origin selected");
829 void GraphWidget::handleNavigationUpRequest()
838 void GraphWidget::handleNavigationDownRequest()
847 void GraphWidget::handleEnterModuleRequested(
const u32 id)
850 if (m->get_gates().empty() && m->get_submodules().empty())
853 msg.
setText(
"This module does not contain any gates, it cannot be unfolded.");
864 ActionUnfoldModule* act =
new ActionUnfoldModule(
id);
865 act->setContextId(mContext->
id());
872 void GraphWidget::ensureItemsVisible(
const QSet<u32>& gates,
const QSet<u32>& modules)
882 for (
auto id : gates)
886 min_x = std::min(min_x,
static_cast<int>(
rect.left()));
887 max_x = std::max(max_x,
static_cast<int>(
rect.right()));
888 min_y = std::min(min_y,
static_cast<int>(
rect.top()));
889 max_y = std::max(max_y,
static_cast<int>(
rect.bottom()));
893 for (
auto id : modules)
897 min_x = std::min(min_x,
static_cast<int>(
rect.left()));
898 max_x = std::max(max_x,
static_cast<int>(
rect.right()));
899 min_y = std::min(min_y,
static_cast<int>(
rect.top()));
900 max_y = std::max(max_y,
static_cast<int>(
rect.bottom()));
905 focusRect(targetRect,
true);
928 min_x = std::min(min_x,
static_cast<int>(
rect.left()));
929 max_x = std::max(max_x,
static_cast<int>(
rect.right()));
930 min_y = std::min(min_y,
static_cast<int>(
rect.top()));
931 max_y = std::max(max_y,
static_cast<int>(
rect.bottom()));
940 min_x = std::min(min_x,
static_cast<int>(
rect.left()));
941 max_x = std::max(max_x,
static_cast<int>(
rect.right()));
942 min_y = std::min(min_y,
static_cast<int>(
rect.top()));
943 max_y = std::max(max_y,
static_cast<int>(
rect.bottom()));
952 min_x = std::min(min_x,
static_cast<int>(
rect.left()));
953 max_x = std::max(max_x,
static_cast<int>(
rect.right()));
954 min_y = std::min(min_y,
static_cast<int>(
rect.top()));
955 max_y = std::max(max_y,
static_cast<int>(
rect.bottom()));
958 if (min_x == INT_MAX ||
963 log_warning(
"gui",
"Attempt to zoom in on graphics item before layout was rendered.");
969 focusRect(targetRect,
true);
972 void GraphWidget::focusRect(
QRectF targetRect,
bool applyCenterFix)
975 if (mStoreViewport.mValid)
977 currentRect = restoreViewport();
991 int durationMsec = sSettingAnimationDuration->
value().
toInt() * 100;
996 if (!(targetRect == mLastTargetRect && currentRect == mRectAfterFocus))
998 mLastTargetRect = targetRect;
1002 auto centerFix = targetRect.
center();
1011 anim->setDuration(durationMsec);
1012 anim->setStartValue(currentRect);
1013 anim->setEndValue(targetRect);
1035 focusRect(targetRect,
false);
1045 QRectF targetRect =
net->sceneBoundingRect().marginsAdded(
QMargins(50, 50, 50, 50));
1046 focusRect(targetRect,
false);
1057 focusRect(targetRect,
false);
1061 void GraphWidget::resetFocus()
1077 auto apply = [percent, qmsg]() {
1078 if (!sInstance)
return;
1082 sInstance->
showBusy(percent, qmsg);
1087 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
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)
CORE_API 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)