Added drag&drop to insert component or bus instances

This commit is contained in:
Borna Rajković 2022-05-23 08:48:13 +02:00
parent 0a658a4aba
commit cbff8ff5f2
10 changed files with 196 additions and 13 deletions

View File

@ -38,5 +38,5 @@ add_executable(SchemeEditor
comdel/parser/comdellexer.cpp comdel/parser/comdellexer.cpp
main.cpp main.cpp
mainwindow.ui mainwindow.ui
comdel/domain/comdelvalidator.cpp comdel/domain/comdelvalidator.h comdel/display/attribute_dialog.cpp comdel/display/attribute_dialog.h comdel/display/name_dialog.cpp comdel/display/name_dialog.h comdel/domain/comdel_generator.cpp comdel/domain/comdel_generator.h) comdel/domain/comdelvalidator.cpp comdel/domain/comdelvalidator.h comdel/display/attribute_dialog.cpp comdel/display/attribute_dialog.h comdel/display/name_dialog.cpp comdel/display/name_dialog.h comdel/domain/comdel_generator.cpp comdel/domain/comdel_generator.h comdel/display/library_list.cpp comdel/display/library_list.h)
target_link_libraries(SchemeEditor Qt5::Core Qt5::Gui Qt5::Widgets) target_link_libraries(SchemeEditor Qt5::Core Qt5::Gui Qt5::Widgets)

View File

@ -6,6 +6,7 @@
#include <QMenu> #include <QMenu>
#include <QGraphicsSceneContextMenuEvent> #include <QGraphicsSceneContextMenuEvent>
#include <iostream> #include <iostream>
#include <QDebug>
namespace display { namespace display {
@ -35,6 +36,34 @@ void Component::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
menu.exec(event->screenPos()); menu.exec(event->screenPos());
} }
void Pin::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
QMenu menu;
menu.addAction("Connect pin", [&]() {});
menu.exec(event->screenPos());
}
void Pin::mousePressEvent(QGraphicsSceneMouseEvent *event) {
if(event->button() == Qt::MouseButton::LeftButton) {
auto view = dynamic_cast<Schema*>(this->scene()->views()[0]);
view->state = Schema::CREATING_CONNECTION;
view->context.pin = this;
view->context.startingPoint = view->mapToScene(event->pos().toPoint());
}
}
void Pin::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
auto view = dynamic_cast<Schema*>(this->scene()->views()[0]);
if(view->state == Schema::CREATING_CONNECTION) {
}
}
void Pin::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
if(event->button() == Qt::MouseButton::LeftButton) {
auto view = dynamic_cast<Schema*>(this->scene()->views()[0]);
view->state = Schema::DEFAULT;
}
}
void Bus::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) { void Bus::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
QMenu menu; QMenu menu;
@ -107,4 +136,5 @@ void Bus::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
} }
menu.exec(event->screenPos()); menu.exec(event->screenPos());
} }
} // namespace display } // namespace display

View File

@ -5,6 +5,8 @@
#include <comdel/domain/wireinstance.h> #include <comdel/domain/wireinstance.h>
#include <QGraphicsItemGroup> #include <QGraphicsItemGroup>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsSceneMouseEvent>
#include "comdel/domain/connectioninstance.h" #include "comdel/domain/connectioninstance.h"
namespace display { namespace display {
@ -17,6 +19,12 @@ public:
Pin(domain::Pin pin): pin(pin) { Pin(domain::Pin pin): pin(pin) {
pin.getDisplayPin().render(this); pin.getDisplayPin().render(this);
} }
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
}; };
class Component: public QGraphicsItemGroup class Component: public QGraphicsItemGroup

View File

@ -11,8 +11,8 @@ Library::Library()
auto layout = new QVBoxLayout(); auto layout = new QVBoxLayout();
this->setLayout(layout); this->setLayout(layout);
componentList = new QListWidget(); componentList = new LibraryList(this);
busList = new QListWidget(); busList = new LibraryList(this);
layout->setMargin(4); layout->setMargin(4);
layout->addWidget(new QLabel("Components:")); layout->addWidget(new QLabel("Components:"));
@ -34,14 +34,14 @@ void Library::setLibrary(std::optional<domain::Library> library) {
} }
for(auto& component: library->getComponents()) { for(auto& component: library->getComponents()) {
auto item = new QListWidgetItem{QString::fromStdString(component.getName())}; auto item = new LibraryListItem{component.getName(), "comdel/component", component.getName(), componentList};
item->setToolTip(QString::fromStdString(component.getTooltip())); item->setToolTip(QString::fromStdString(component.getTooltip()));
componentList->addItem(item); componentList->addItem(item);
} }
for(auto& bus: library->getBuses()) { for(auto& bus: library->getBuses()) {
if(bus.getType() == domain::Bus::REGULAR) { if(bus.getType() == domain::Bus::REGULAR) {
auto item = new QListWidgetItem{QString::fromStdString(bus.getName())}; auto item = new LibraryListItem{bus.getName(), "comdel/bus", bus.getName(), busList};
item->setToolTip(QString::fromStdString(bus.getTooltip())); item->setToolTip(QString::fromStdString(bus.getTooltip()));
busList->addItem(item); busList->addItem(item);
} }

View File

@ -5,6 +5,7 @@
#include <QWidget> #include <QWidget>
#include <comdel/domain/library.h> #include <comdel/domain/library.h>
#include "library_list.h"
namespace display { namespace display {
@ -18,8 +19,8 @@ public:
private: private:
std::optional<domain::Library> library; std::optional<domain::Library> library;
QListWidget *componentList; LibraryList *componentList;
QListWidget *busList; LibraryList *busList;
}; };

View File

@ -0,0 +1,31 @@
//
// Created by bbr on 22.05.22..
//
#include "library_list.h"
#include <QMouseEvent>
#include <QDrag>
#include <QMimeData>
namespace display {
LibraryList::LibraryList(QWidget *parent): QListWidget(parent) {
setDragDropMode(DragOnly);
}
QMimeData *LibraryList::mimeData(const QList<QListWidgetItem *> items) const {
for(auto qItem: items) {
// we only allow one item to be dragged at a time
auto item = dynamic_cast<LibraryListItem*>(qItem);
auto* md = new QMimeData();
md->setData(QString::fromStdString(item->mimeType), QByteArray::fromStdString(item->value));
return md;
}
return nullptr;
}
LibraryListItem::LibraryListItem(std::string title, std::string mimeType, std::string value, QListWidget *parent): QListWidgetItem(parent), mimeType(mimeType), value(value) {
setText(QString::fromStdString(title));
}
} // display

View File

@ -0,0 +1,34 @@
//
// Created by bbr on 22.05.22..
//
#ifndef SCHEMEEDITOR_LIBRARY_LIST_H
#define SCHEMEEDITOR_LIBRARY_LIST_H
#include <QListWidget>
#include <QList>
#include <QMimeData>
namespace display {
class LibraryList: public QListWidget {
Q_OBJECT
public:
LibraryList(QWidget *parent);
protected:
QMimeData *mimeData(const QList<QListWidgetItem*> items) const override;
};
class LibraryListItem: public QListWidgetItem {
public:
std::string mimeType;
std::string value;
LibraryListItem(std::string title, std::string mimeType, std::string value, QListWidget *parent);
};
} // display
#endif //SCHEMEEDITOR_LIBRARY_LIST_H

View File

@ -1,15 +1,22 @@
#include "component_display.h" #include "component_display.h"
#include "schema_display.h" #include "schema_display.h"
#include <QDrag>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QMimeData>
#include <iostream>
namespace display { namespace display {
Schema::Schema() Schema::Schema()
{ {
this->setScene(&scene); this->setScene(&scene);
this->setAcceptDrops(true);
} }
void Schema::setSchema(domain::Schema* _schema) void Schema::setSchema(domain::Schema* _schema, domain::Library* _library)
{ {
std::map<std::string, display::ComponentGroup*> components; std::map<std::string, display::ComponentGroup*> components;
std::map<std::string, display::BusGroup*> buses; std::map<std::string, display::BusGroup*> buses;
@ -17,6 +24,7 @@ void Schema::setSchema(domain::Schema* _schema)
scene.clear(); scene.clear();
connections.clear(); connections.clear();
this->schema = _schema; this->schema = _schema;
this->library = _library;
if(schema != nullptr) { if(schema != nullptr) {
for(auto &instance: schema->componentInstances) { for(auto &instance: schema->componentInstances) {
auto group = new display::ComponentGroup(instance); auto group = new display::ComponentGroup(instance);
@ -49,4 +57,51 @@ void Schema::updateConnections() {
} }
} }
void Schema::dragEnterEvent(QDragEnterEvent *event) {
if(event->mimeData()->hasFormat("comdel/component") ||
event->mimeData()->hasFormat("comdel/bus")) {
event->acceptProposedAction();
} else {
std::cout<<"false"<< std::endl;
}
}
void Schema::dropEvent(QDropEvent *event) {
if(event->mimeData()->hasFormat("comdel/component")) {
auto component = library->getComponent(event->mimeData()->data("comdel/component").toStdString());
auto attributes = std::vector<domain::InstanceAttribute>();
for(auto attr: component.getAttributes()) {
attributes.emplace_back(attr.getName(), attr.getDefault(), attr);
}
auto currentPos = this->mapToScene(event->pos());
auto instance = std::make_shared<domain::ComponentInstance>(component.getInstanceName(), attributes, std::make_pair(currentPos.x(), currentPos.y()), component);
schema->componentInstances.push_back(instance);
auto group = new display::ComponentGroup(instance);
scene.addItem(group);
event->acceptProposedAction();
}
if(event->mimeData()->hasFormat("comdel/bus")) {
auto bus = library->getBus(event->mimeData()->data("comdel/bus").toStdString());
auto currentPos = this->mapToScene(event->pos());
auto instance = std::make_shared<domain::BusInstance>(bus.getName(), std::make_pair(currentPos.x(), currentPos.y()), bus, 50);
schema->busInstances.push_back(instance);
auto group = new display::BusGroup(instance);
scene.addItem(group);
event->acceptProposedAction();
}
}
void Schema::dragMoveEvent(QDragMoveEvent *event) {
event->acceptProposedAction();
}
} // namespace display } // namespace display

View File

@ -6,6 +6,7 @@
#include <QWidget> #include <QWidget>
#include <comdel/domain/schema.h> #include <comdel/domain/schema.h>
#include <comdel/domain/library.h>
namespace display { namespace display {
@ -13,19 +14,42 @@ namespace display {
class Schema: public QGraphicsView class Schema: public QGraphicsView
{ {
Q_OBJECT
public: public:
enum State {
DEFAULT,
CREATING_CONNECTION
};
struct Context {
display::Pin *pin;
QPointF startingPoint;
};
State state = DEFAULT;
Context context;
Schema(); Schema();
std::vector<BusConnection*> connections; std::vector<BusConnection*> connections;
void setSchema(domain::Schema* schema); void setSchema(domain::Schema* schema, domain::Library* library);
void updateConnections(); void updateConnections();
protected:
void dragEnterEvent(QDragEnterEvent *event) override;
void dropEvent(QDropEvent *event) override;
void dragMoveEvent(QDragMoveEvent *event) override;
private: private:
QGraphicsScene scene; QGraphicsScene scene;
domain::Schema* schema; domain::Schema* schema;
domain::Library* library;
}; };
} // namespace display } // namespace display

View File

@ -96,7 +96,7 @@ void MainWindow::onLoadLibrary() {
// on library load we create a new schema // on library load we create a new schema
schema = new domain::Schema(); schema = new domain::Schema();
schemaDisplay->setSchema(schema); schemaDisplay->setSchema(schema, &(*library));
} }
} else { } else {
@ -145,7 +145,7 @@ void MainWindow::onLoadSchema() {
if(generator.getErrors().empty()) { if(generator.getErrors().empty()) {
libraryDisplay->setLibrary(library); libraryDisplay->setLibrary(library);
schemaDisplay->setSchema(schema); schemaDisplay->setSchema(schema, &(*library));
} }
} }
} }
@ -251,7 +251,7 @@ void MainWindow::clear() {
library = std::nullopt; library = std::nullopt;
libraryDisplay->setLibrary(library); libraryDisplay->setLibrary(library);
schemaDisplay->setSchema(schema); schemaDisplay->setSchema(schema, nullptr);
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()