diff --git a/include/hal_core/plugin_system/plugin_manager.h b/include/hal_core/plugin_system/plugin_manager.h index 6bb49f4adb3..a745a548330 100644 --- a/include/hal_core/plugin_system/plugin_manager.h +++ b/include/hal_core/plugin_system/plugin_manager.h @@ -62,6 +62,13 @@ namespace hal */ std::set get_plugin_names(); + /** + * Get the full path for plugin. Will probe several possible extension on MAC + * + * @returns The full path to plugin in HAL build directory. + */ + std::filesystem::path get_plugin_path(std::string plugin_name); + /** * TODO Python binding. * 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 20443a3ba1c..88519baf70f 100644 --- a/plugins/gui/include/gui/graph_widget/graph_graphics_view.h +++ b/plugins/gui/include/gui/graph_widget/graph_graphics_view.h @@ -212,7 +212,7 @@ namespace hal int mIndex; qreal mPos; }; - QVector closestLayouterPos(const QPointF& scene_pos) const; + QPair closestLayouterPos(const QPointF& scene_pos) const; LayouterPoint closestLayouterPoint(qreal scene_pos, int default_spacing, int min_index, QVector sections) const; #ifdef GUI_DEBUG_GRID diff --git a/plugins/gui/include/gui/graph_widget/graph_widget.h b/plugins/gui/include/gui/graph_widget/graph_widget.h index 15144c70028..6e60b925248 100644 --- a/plugins/gui/include/gui/graph_widget/graph_widget.h +++ b/plugins/gui/include/gui/graph_widget/graph_widget.h @@ -178,7 +178,7 @@ namespace hal public: bool mValid; QRectF mRect; - QVector mGrid; + QPair mGrid; StoreViewport() : mValid(false) {;} }; 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 a7b8c291259..47d7a7d2d6e 100644 --- a/plugins/gui/include/gui/user_action/action_move_node.h +++ b/plugins/gui/include/gui/user_action/action_move_node.h @@ -44,7 +44,7 @@ namespace hal u32 mContextId; QPoint mTo; bool mSwap; - + Node mTargetNode; GridPlacement mGridPlacement; static QPoint parseFromString(const QString& s); diff --git a/plugins/gui/src/graph_widget/graph_graphics_view.cpp b/plugins/gui/src/graph_widget/graph_graphics_view.cpp index 0da4263517a..f366d96afea 100644 --- a/plugins/gui/src/graph_widget/graph_graphics_view.cpp +++ b/plugins/gui/src/graph_widget/graph_graphics_view.cpp @@ -393,7 +393,7 @@ namespace hal { mDragItem = static_cast(item); mDragMousedownPosition = event->pos(); - mDragStartGridpos = closestLayouterPos(mapToScene(mDragMousedownPosition))[0]; + mDragStartGridpos = closestLayouterPos(mapToScene(mDragMousedownPosition)).first; } else { @@ -477,7 +477,7 @@ namespace hal event->acceptProposedAction(); QSizeF size(mDragItem->width(), mDragItem->height()); QPointF mouse = event->posF(); - QPointF snap = closestLayouterPos(mapToScene(mouse.x(), mouse.y()))[1]; + 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 @@ -500,7 +500,7 @@ namespace hal void GraphGraphicsView::dragLeaveEvent(QDragLeaveEvent* event) { Q_UNUSED(event) - static_cast(scene())->stopDragShadow(); + if (scene()) static_cast(scene())->stopDragShadow(); } void GraphGraphicsView::dragMoveEvent(QDragMoveEvent* event) @@ -508,23 +508,24 @@ namespace hal if (event->source() == this && event->proposedAction() == Qt::MoveAction) { bool swapModifier = event->keyboardModifiers() == mDragModifier; - QVector snap = closestLayouterPos(mapToScene(event->pos())); + QPair snap = closestLayouterPos(mapToScene(event->pos())); - if (snap[0] == mDragCurrentGridpos && swapModifier == mDragCurrentModifier) + if (snap.first == mDragCurrentGridpos && swapModifier == mDragCurrentModifier) { return; } - mDragCurrentGridpos = snap[0]; + 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[0]); + + QMap::const_iterator node_iter = layouter->positionToNodeMap().find(snap.first); NodeDragShadow::DragCue cue = NodeDragShadow::DragCue::Rejected; // disallow dropping an item on itself - if (snap[0] != mDragStartGridpos) + if (snap.first != mDragStartGridpos) { if (swapModifier) { @@ -545,7 +546,7 @@ namespace hal } mDropAllowed = (cue != NodeDragShadow::DragCue::Rejected); - static_cast(scene())->moveDragShadow(snap[1], cue); + static_cast(scene())->moveDragShadow(snap.second, cue); } } @@ -555,7 +556,7 @@ namespace hal { event->acceptProposedAction(); GraphicsScene* s = static_cast(scene()); - s->stopDragShadow(); + if (s) s->stopDragShadow(); if (mDropAllowed) { auto context = mGraphWidget->getContext(); @@ -564,7 +565,7 @@ namespace hal // convert scene coordinates into layouter grid coordinates QPointF targetPos = s->dropTarget(); - QPoint targetLayouterPos = closestLayouterPos(targetPos)[0]; + QPoint targetLayouterPos = closestLayouterPos(targetPos).first; QPoint sourceLayouterPos = layouter->gridPointByItem(mDragItem); if (targetLayouterPos == sourceLayouterPos) @@ -575,24 +576,9 @@ namespace hal // assert(targetLayouterPos != sourceLayouterPos); bool modifierPressed = event->keyboardModifiers() == mDragModifier; - if (modifierPressed) - { - // swap mode; swap gates - - Node nodeFrom = layouter->positionToNodeMap().value(sourceLayouterPos); - Node nodeTo = layouter->positionToNodeMap().value(targetLayouterPos); - assert(!nodeFrom.isNull()); // assert that value was found - assert(!nodeTo.isNull()); - layouter->swapNodePositions(nodeFrom, nodeTo); - // re-layout the nets - context->scheduleSceneUpdate(); - } - else - { - ActionMoveNode* act = new ActionMoveNode(context->id(),sourceLayouterPos,targetLayouterPos); - act->exec(); - } - context->setDirty(true); + ActionMoveNode* act = new ActionMoveNode(context->id(), sourceLayouterPos, targetLayouterPos, modifierPressed); + if (act->exec()) + context->setDirty(true); } } else @@ -1860,12 +1846,12 @@ namespace hal return; QPointF scene_mouse_pos = mapToScene(mouse_pos); - QPoint layouter_pos = closestLayouterPos(scene_mouse_pos)[0]; + QPoint layouter_pos = closestLayouterPos(scene_mouse_pos).first; m_debug_gridpos = layouter_pos; } #endif - QVector GraphGraphicsView::closestLayouterPos(const QPointF& scene_pos) const + QPair GraphGraphicsView::closestLayouterPos(const QPointF& scene_pos) const { auto context = mGraphWidget->getContext(); assert(context); @@ -1881,7 +1867,7 @@ namespace hal QVector y_vals = layouter->yValues(); LayouterPoint x_point = closestLayouterPoint(scene_pos.x(), default_width, min_x, x_vals); LayouterPoint y_point = closestLayouterPoint(scene_pos.y(), default_height, min_y, y_vals); - return QVector({QPoint(x_point.mIndex, y_point.mIndex), QPoint(x_point.mPos, y_point.mPos)}); + return qMakePair(QPoint(x_point.mIndex, y_point.mIndex), QPointF(x_point.mPos, y_point.mPos)); } GraphGraphicsView::LayouterPoint GraphGraphicsView::closestLayouterPoint(qreal scene_pos, int default_spacing, int min_index, QVector sections) const @@ -1892,64 +1878,34 @@ namespace hal { int distance = sections.first() - scene_pos; int nSections = distance / default_spacing; // this rounds down - qreal posThis = sections.first() - nSections * default_spacing; - qreal distThis = qAbs(scene_pos - posThis); - qreal posPrev = posThis - default_spacing; - qreal distPrev = qAbs(scene_pos - posPrev); - if (distPrev < distThis) - { - index -= nSections + 1; - pos = posPrev; - } - else - { - index -= nSections; - pos = posThis; - } + index -= (nSections + 1); + pos = sections.first() + index * default_spacing; } - else if (sections.last() < scene_pos) + else if (sections.last() <= scene_pos) { int distance = scene_pos - sections.last(); int nSections = distance / default_spacing; // this rounds down - qreal posThis = sections.last() + nSections * default_spacing; - qreal distThis = qAbs(scene_pos - posThis); - qreal posNext = posThis + default_spacing; - qreal distNext = qAbs(scene_pos - posNext); - if (distNext < distThis) - { - index += nSections + sections.size(); - pos = posNext; - } - else - { - index += nSections + sections.size() - 1; - pos = posThis; - } + index += (sections.size() + nSections -1); + pos = sections.last() + nSections * default_spacing; } else { - // binary search for first value in sections larger than or equal to scene_pos - const qreal* needle = std::lower_bound(sections.constBegin(), sections.constEnd(), scene_pos); - int i = needle - sections.begin(); // position of needle in the vector - index += i; - // check if we're closer to this or the next position - qreal posThis = *needle; - qreal distThis = qAbs(scene_pos - posThis); - qreal posPrev = (i > 0) ? sections[i - 1] : (sections.first() - default_spacing); - qreal distPrev = qAbs(scene_pos - posPrev); - if (distPrev < distThis) + // search for first value in sections larger than or equal to scene_pos + auto it = sections.constBegin(); + auto jt = it+1; + while (jt != sections.constEnd()) { - index--; - pos = posPrev; - } - else - { - pos = posThis; + if (scene_pos < *jt) break; // found value in inteval [it..[jt + ++it; + ++jt; + ++index; } + pos = *it; } return LayouterPoint{index, pos}; } + GraphicsScene::GridType GraphGraphicsView::gridType() { return mGridType; diff --git a/plugins/gui/src/graph_widget/graph_widget.cpp b/plugins/gui/src/graph_widget/graph_widget.cpp index 04107045ed2..d42ce96eeaa 100644 --- a/plugins/gui/src/graph_widget/graph_widget.cpp +++ b/plugins/gui/src/graph_widget/graph_widget.cpp @@ -206,7 +206,7 @@ namespace hal mStoreViewport.mValid = true; mStoreViewport.mRect = mView->mapToScene(mView->viewport()->geometry()).boundingRect(); mStoreViewport.mGrid = mView->closestLayouterPos(mView->mapToScene(QPoint(viewportCenter))); - // qDebug() << "store" << viewportCenter << mStoreViewport.mGrid[0] << mStoreViewport.mGrid[1] << mStoreViewport.mRect; + // qDebug() << "store" << viewportCenter << mStoreViewport.mGrid.first << mStoreViewport.mGrid.second << mStoreViewport.mRect; } QRectF GraphWidget::restoreViewport(bool reset) @@ -216,8 +216,8 @@ namespace hal if (reset) mStoreViewport.mValid = false; - QPointF centerPos(mContext->getLayouter()->gridXposition(mStoreViewport.mGrid[0].x()), mContext->getLayouter()->gridYposition(mStoreViewport.mGrid[0].y())); - QPointF topLeft = mStoreViewport.mRect.topLeft() - mStoreViewport.mGrid[1] + centerPos; + QPointF centerPos(mContext->getLayouter()->gridXposition(mStoreViewport.mGrid.first.x()), mContext->getLayouter()->gridYposition(mStoreViewport.mGrid.first.y())); + QPointF topLeft = mStoreViewport.mRect.topLeft() - mStoreViewport.mGrid.second + centerPos; return QRectF(topLeft, mStoreViewport.mRect.size()); } diff --git a/plugins/gui/src/grouping/grouping_color_serializer.cpp b/plugins/gui/src/grouping/grouping_color_serializer.cpp index 097cf87d98c..1832465b641 100644 --- a/plugins/gui/src/grouping/grouping_color_serializer.cpp +++ b/plugins/gui/src/grouping/grouping_color_serializer.cpp @@ -146,7 +146,7 @@ namespace hal { QJsonArray mcArr; const ModuleModel* mm = gNetlistRelay->getModuleModel(); - if (!mm) std::string(); + if (!mm) return std::string(); serializeColorRecursion(mcArr,mm); diff --git a/plugins/gui/src/plugin_relay/gui_plugin_manager.cpp b/plugins/gui/src/plugin_relay/gui_plugin_manager.cpp index d8e9b12ba4c..96dba50feb4 100644 --- a/plugins/gui/src/plugin_relay/gui_plugin_manager.cpp +++ b/plugins/gui/src/plugin_relay/gui_plugin_manager.cpp @@ -772,7 +772,6 @@ namespace hal { settings->setValue("name", mName); settings->setValue("version", mVersion); settings->setValue("description", mDescription); - settings->setValue("file_path", mFilePath); settings->setValue("file_modified", mFileModified); settings->setValue("dependencies", mDependencies); settings->setValue("feature_code", (int) mFeature); @@ -788,7 +787,6 @@ namespace hal { mName = settings->value("name").toString(); mVersion = settings->value("version").toString(); mDescription = settings->value("description").toString(); - mFilePath = settings->value("file_path").toString(); mFileModified = settings->value("file_modified").toDateTime(); mDependencies = settings->value("dependencies").toStringList(); mFeature = (FacExtensionInterface::Feature) settings->value("feature_code").toInt(); @@ -796,6 +794,7 @@ namespace hal { mUserInterface = settings->value("user_interface").toBool(); mGuiExtensions = settings->value("extends_gui").toBool(); mCliOptions = settings->value("cli_options").toString(); + mFilePath = QString::fromStdString(plugin_manager::get_plugin_path(mName.toStdString()).string()); } void GuiPluginEntry::updateFromLoaded(const BasePluginInterface *bpif, bool isUser, const QDateTime& modified) diff --git a/plugins/gui/src/user_action/action_move_node.cpp b/plugins/gui/src/user_action/action_move_node.cpp index 63e6d9bd9a2..2ea039cd8e1 100644 --- a/plugins/gui/src/user_action/action_move_node.cpp +++ b/plugins/gui/src/user_action/action_move_node.cpp @@ -47,6 +47,9 @@ namespace hal : mContextId(ctxID), mTo(to), mSwap(false) { if (!checkContextId()) return; + + // This special constructor is mainly used in compound statement. + // At construction target position might still be occupied, so don't do any checks before exec() } ActionMoveNode::ActionMoveNode(u32 ctxID, const QPoint& from, const QPoint& to, bool swap) @@ -54,17 +57,20 @@ namespace hal { if (!checkContextId()) return; GraphContext* ctx = gGraphContextManager->getContextById(mContextId); - auto it = ctx->getLayouter()->positionToNodeMap().find(from); - if (it == ctx->getLayouter()->positionToNodeMap().constEnd()) + + // get the node we want to move + Node ndToMove = ctx->getLayouter()->positionToNodeMap().value(from); + if (ndToMove.isNull()) { mContextId = 0; // node not found, exit return; } - Node ndToMove = it.value(); // get the node we want to move - if(mSwap) + mTargetNode = ctx->getLayouter()->positionToNodeMap().value(to); + if(!mTargetNode.isNull() && !mSwap) { - + mContextId = 0; // move to an occupied position without swap modifier + return; } switch (ndToMove.type()) @@ -122,24 +128,33 @@ namespace hal ActionMoveNode* undo = new ActionMoveNode(mContextId, GuiApiClasses::View::getGridPlacement(mContextId)); mUndoAction = undo; - // test whether there is a user object - Node ndToMove; - switch (mObject.type()) { - case UserActionObjectType::Gate: - ndToMove = Node(mObject.id(),Node::Gate); - break; - case UserActionObjectType::Module: - ndToMove = Node(mObject.id(),Node::Module); - break; - default: - break; - } - if (ndToMove.type() != Node::None) + if (mGridPlacement.isEmpty()) { + // No placement given by constructor + // load current placement and modify from and to position mGridPlacement = undo->mGridPlacement; - auto it = ctx->getLayouter()->positionToNodeMap().find(mTo); - if (it == ctx->getLayouter()->positionToNodeMap().constEnd()) - mGridPlacement[ndToMove] = mTo; + + // test whether there is a user object to move + Node ndToMove; + switch (mObject.type()) { + case UserActionObjectType::Gate: + ndToMove = Node(mObject.id(),Node::Gate); + break; + case UserActionObjectType::Module: + ndToMove = Node(mObject.id(),Node::Module); + break; + default: + break; + } + if (ndToMove.type() == Node::None) return false; + + if (!mTargetNode.isNull()) + { + // there is a node at target position + if (!mSwap) return false; + mGridPlacement[mTargetNode] = ctx->getLayouter()->nodeToPositionMap().value(ndToMove); + } + mGridPlacement[ndToMove] = mTo; } LayoutLocker llock; diff --git a/src/plugin_system/plugin_manager.cpp b/src/plugin_system/plugin_manager.cpp index 7bdad3c70e5..6cf7ba42c66 100644 --- a/src/plugin_system/plugin_manager.cpp +++ b/src/plugin_system/plugin_manager.cpp @@ -51,17 +51,6 @@ namespace hal // stores name of plugin while loading std::string m_current_loading; - std::filesystem::path get_plugin_path(std::string plugin_name) - { - std::filesystem::path retval; - if (plugin_name.empty()) return retval; - std::string file_name = plugin_name + "." + LIBRARY_FILE_EXTENSION; - retval = utils::get_file(file_name, m_plugin_folders); - if (!retval.empty() || !strlen(ALTERNATE_LIBRARY_FILE_EXTENSION)) return retval; - file_name = plugin_name + "." + ALTERNATE_LIBRARY_FILE_EXTENSION; - return utils::get_file(file_name, m_plugin_folders); - } - bool solve_dependencies(std::string plugin_name, std::set dep_file_name) { if (plugin_name.empty()) @@ -100,6 +89,17 @@ namespace hal } // namespace + std::filesystem::path get_plugin_path(std::string plugin_name) + { + std::filesystem::path retval; + if (plugin_name.empty()) return retval; + std::string file_name = plugin_name + "." + LIBRARY_FILE_EXTENSION; + retval = utils::get_file(file_name, m_plugin_folders); + if (!retval.empty() || !strlen(ALTERNATE_LIBRARY_FILE_EXTENSION)) return retval; + file_name = plugin_name + "." + ALTERNATE_LIBRARY_FILE_EXTENSION; + return utils::get_file(file_name, m_plugin_folders); + } + bool has_valid_file_extension(std::filesystem::path file_name) { #if defined(__APPLE__) && defined(__MACH__)