From 79c5d147a30d9aba16de9945afe3ceced2b68a5f Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 2 Dec 2020 13:09:47 +0100 Subject: [PATCH] Added more logic gates and fixed placement issues --- include/Window.hpp | 3 ++ src/Window.cpp | 64 +++++++++++++++++++------ ui/Window.ui | 101 ++++++++++++++++++++++++++++++++++++++-- ui/assets/README.md | 3 +- ui/assets/nand.png | Bin 0 -> 813 bytes ui/assets/nor.png | Bin 0 -> 1062 bytes ui/assets/not.png | Bin 0 -> 800 bytes ui/assets/resources.qrc | 5 ++ ui/assets/xnor.png | Bin 0 -> 1204 bytes ui/assets/xor.png | Bin 0 -> 1110 bytes 10 files changed, 157 insertions(+), 19 deletions(-) create mode 100644 ui/assets/nand.png create mode 100644 ui/assets/nor.png create mode 100644 ui/assets/not.png create mode 100644 ui/assets/xnor.png create mode 100644 ui/assets/xor.png diff --git a/include/Window.hpp b/include/Window.hpp index 9026803..ab06d71 100644 --- a/include/Window.hpp +++ b/include/Window.hpp @@ -25,6 +25,7 @@ private: void ToggleSimulation(); void ToggleComponentPlacer(); void LoadGhostLabel(const QString& resource); + Component* componentAt(const QPoint& point); Ui::Window* ui; bool simulating; @@ -37,4 +38,6 @@ private: GhostLabel* ghostImage; QString resourcePath; QActionGroup* componentGroup; + + std::vector components; }; \ No newline at end of file diff --git a/src/Window.cpp b/src/Window.cpp index 29f6cba..f33bb90 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -20,30 +20,49 @@ Window::Window() : ui->centralwidget->setAttribute(Qt::WA_TransparentForMouseEvents); setMouseTracking(true); - LoadGhostLabel(":/components/and.png"); - componentGroup = new QActionGroup(this); + componentGroup->addAction(ui->actionAddNOT); componentGroup->addAction(ui->actionAddAND); + componentGroup->addAction(ui->actionAddNAND); componentGroup->addAction(ui->actionAddOR); + componentGroup->addAction(ui->actionAddNOR); + componentGroup->addAction(ui->actionAddXOR); + componentGroup->addAction(ui->actionAddXNOR); componentGroup->setExclusionPolicy(QActionGroup::ExclusionPolicy::ExclusiveOptional); - connect(ui->actionStart, &QAction::triggered, this, &Window::ToggleSimulation); - connect(ui->actionAddAND, &QAction::triggered, this, [this]() {resourcePath = ":/components/and.png"; ToggleComponentPlacer(); }); - connect(ui->actionAddOR, &QAction::triggered, this, [this]() {resourcePath = ":/components/or.png"; ToggleComponentPlacer(); }); + connect(ui->actionStart, &QAction::triggered, this, &Window::ToggleSimulation); + connect(ui->actionAddNOT, &QAction::triggered, this, [this]() {resourcePath = ":/components/not.png"; ToggleComponentPlacer(); }); + connect(ui->actionAddAND, &QAction::triggered, this, [this]() {resourcePath = ":/components/and.png"; ToggleComponentPlacer(); }); + connect(ui->actionAddNAND, &QAction::triggered, this, [this]() {resourcePath = ":/components/nand.png"; ToggleComponentPlacer(); }); + connect(ui->actionAddOR, &QAction::triggered, this, [this]() {resourcePath = ":/components/or.png"; ToggleComponentPlacer(); }); + connect(ui->actionAddNOR, &QAction::triggered, this, [this]() {resourcePath = ":/components/nor.png"; ToggleComponentPlacer(); }); + connect(ui->actionAddXOR, &QAction::triggered, this, [this]() {resourcePath = ":/components/xor.png"; ToggleComponentPlacer(); }); + connect(ui->actionAddXNOR, &QAction::triggered, this, [this]() {resourcePath = ":/components/xnor.png"; ToggleComponentPlacer(); }); } Window::~Window() { delete ui; ui = nullptr; + + delete componentGroup; + componentGroup = nullptr; + + delete ghostImage; + ghostImage = nullptr; + + for (Component* c : components) + { + delete c; + c = nullptr; + } } void Window::mousePressEvent(QMouseEvent* event) { if (simulating) return; - ui->centralwidget->findChildren(); - QFrame* child = static_cast(ui->centralwidget->childAt(event->pos())); + Component* child = componentAt(event->pos()); QAction* toggledAction = componentGroup->checkedAction(); if (toggledAction == nullptr) @@ -51,9 +70,6 @@ void Window::mousePressEvent(QMouseEvent* event) if (child == nullptr) return; - if (!child->isAncestorOf(ui->centralwidget)) - child = static_cast(child->parentWidget()); - dragInfo.component = static_cast(child); dragInfo.relativePos = event->pos() - child->pos(); } @@ -62,13 +78,15 @@ void Window::mousePressEvent(QMouseEvent* event) if (child != nullptr) return; - // TODO: I'll just let this leak for now, I just wanna eat dinner... Component* leak = new Component(this, resourcePath); QPoint pos = event->pos() - QPoint {50, 25}; leak->setGeometry(QRect(pos.x(), pos.y(), 100, 50)); leak->setFrameShape(QFrame::NoFrame); leak->setFrameShadow(QFrame::Plain); leak->setVisible(true); + leak->setAttribute(Qt::WA_TransparentForMouseEvents); + + components.push_back(leak); } } @@ -78,7 +96,7 @@ void Window::mouseMoveEvent(QMouseEvent* event) dragInfo.component->move(event->pos() - dragInfo.relativePos); if (ghostImage != nullptr) - ghostImage->move(event->pos() - QPoint{50, 25}); // TODO: Hardcoded + ghostImage->move(event->pos() - QPoint{50, ui->toolBar->height() + 25}); // TODO: Hardcoded event->accept(); } @@ -101,6 +119,9 @@ void Window::ToggleComponentPlacer() { delete ghostImage; ghostImage = nullptr; + + for (Component* c : components) + c->setAttribute(Qt::WA_TransparentForMouseEvents, false); } else { @@ -111,10 +132,14 @@ void Window::ToggleComponentPlacer() void Window::LoadGhostLabel(const QString& resource) { if (ghostImage == nullptr) { - ghostImage = new GhostLabel(this); - ghostImage->setGeometry({ 0, 0, 100, 50 }); + ghostImage = new GhostLabel(ui->centralwidget); + QPoint mousePos = ui->centralwidget->mapFromGlobal(QCursor::pos()); + ghostImage->setGeometry({ mousePos.x() - 50, mousePos.y() - 25, 100, 50 }); ghostImage->setScaledContents(true); ghostImage->setVisible(true); + + for (Component* c : components) + c->setAttribute(Qt::WA_TransparentForMouseEvents, true); } QPainter p; @@ -127,3 +152,14 @@ void Window::LoadGhostLabel(const QString& resource) ghostImage->setPixmap(QPixmap::fromImage(image)); } + +Component* Window::componentAt(const QPoint& point) +{ + for (Component* c : components) + { + if (c->geometry().contains(point)) + return c; + } + + return nullptr; +} diff --git a/ui/Window.ui b/ui/Window.ui index 46d567b..72a389c 100644 --- a/ui/Window.ui +++ b/ui/Window.ui @@ -30,8 +30,13 @@ + + + + + @@ -53,7 +58,7 @@ true - true + false @@ -66,7 +71,7 @@ Create an AND gate - 1 + 2 @@ -85,7 +90,97 @@ Create an OR gate - 2 + 4 + + + + + true + + + + :/components/not.png:/components/not.png + + + AddNOT + + + Create a NOT gate + + + 1 + + + + + true + + + + :/components/nand.png:/components/nand.png + + + AddNAND + + + Create a NAND gate + + + 3 + + + + + true + + + + :/components/nor.png:/components/nor.png + + + AddNOR + + + Create a NOR gate + + + 5 + + + + + true + + + + :/components/xor.png:/components/xor.png + + + AddXOR + + + Create an XOR gate + + + 6 + + + + + true + + + + :/components/xnor.png:/components/xnor.png + + + AddXNOR + + + Create an XNOR gate + + + 7 diff --git a/ui/assets/README.md b/ui/assets/README.md index 502fa00..4a7922f 100644 --- a/ui/assets/README.md +++ b/ui/assets/README.md @@ -1,6 +1,5 @@ Start/Stop icons taken from https://iconsmind.com/ (modified) -Logic Gates taken from Wikimedia Commons. The authors are -* jjbeard (AND, OR) +Logic Gates taken from Wikimedia Commons. https://commons.wikimedia.org/wiki/Logic_gates_unified_symbols The Wikimedia icons are part of the public domain \ No newline at end of file diff --git a/ui/assets/nand.png b/ui/assets/nand.png new file mode 100644 index 0000000000000000000000000000000000000000..37cb74d36208956a9920fa88668f74b340d3d846 GIT binary patch literal 813 zcmeAS@N?(olHy`uVBq!ia0vp^DL`z*!2%>1Y_^#KNtSd+Uq=Rpjs4tz5?O(Kg=CK) zUj~LMH3o);76yi2K%s^g3=E|P3=FRl7#OT(FffQ0%-I!a1C(G&@^*J&_}|`tW3}q&s4Xh2r2%^3>}`Q zikqaCp72Uusgt%T@pw?A#N_>sZ){T?r*+I+k`~nRY07fRv_n6lEb=r;?^f^rF8A*F z_FenW+0Om`e$MBgb?3id2yo{8E1sqG`hH-^>F;(D<@b5RZCCF?zEX3cTD)nKjl^QEl0 z^EeV!$_3h5J_NeIQ;=QOTCiY_->laPQhSRzzch#4=8@VGnw@8S$Wd|6)udi)R_U1= z6wN1W&3y4Ut*-EhoDKF$CcEq>HD=VoOp_F^)L6kpHI%8_KeqPLX~A$^ma}0CHixDwPW~JnR(1NU+J)Y(Y1f^ zd?)JUgHM)Jzh#bGsn9(~S4Hur*hX>dM59ET%^U6f1nZeEt-C&9wPsg)!NN)6wpVvn zWnWwQdAhl9pT+vT5U)EwA8oRox}Rrl*tg&3rgWCr{*7_wHN6tB@)z4ypZk(&Ee&kI zG^JYN8c~vxSdwa$T$Bo=7>o=IEp!cxbd4-R3{0(zjjap}v<(b^WPP;Uauf}@`6-!c XmAEzVu`QDZYGCkm^>bP0l+XkKi(XQ1 literal 0 HcmV?d00001 diff --git a/ui/assets/nor.png b/ui/assets/nor.png new file mode 100644 index 0000000000000000000000000000000000000000..b82bcc0b9a5e154ee3ed166ac63e109b6e9e2d47 GIT binary patch literal 1062 zcmeAS@N?(olHy`uVBq!ia0vp^DL`z*!2%>1Y_^#KNtSd+Uq=Rpjs4tz5?O(Kg=CK) zUj~LMH3o);76yi2K%s^g3=E|P3=FRl7#OT(FffQ0%-I!a1C(G&@^*J&_}|`tW2WwWwg)i0cOMeKaVwyy1M zJl2T^_`ltH9btIUUPN>K{hZBV?iT~BWPEys4y{-#CdR$g+mmDa+|Rvb#U(p$3*Y9VzdGkzZ!5*cS>qZgVsx2KQH!u3e+wF6`quZ!9 zcdw!1lsoY}6HeS&ZtK=kaBP*E|2ki%3gykU+k-v%qOU|uIO=3E=kQ@&PbWEp^%E5? z|JC%_rPJPDJ+*bi?JqXII~BxFwAjs!dUI;yKHEhpl4(0H==ogEUK(Bc<7CR;V=1cz zd(Lj6obVmN> zo3{*dx^?{)owZ(eHQnVJS7J4NN6gY(YD7xQv2+-|2(&iQb&RK=|6S1ja1=Ix0( zdVWV*uy*#-`xfh;Uubsvv4U-0nM!TVshEONqpj1z(&w2^No%q%O8&A_edq2gcJDJc zp7VM0F}2q1iKb%CxtB{XHwe`I4F4s&df%;+(#oF|pYID@T^`%#`C50w?oT!QkMdp7 zcKg-3VGrA4sW>mS>h-;5uhw3dXSp?{NMB0cBkKqAE$QvQVwGByEp5K2ls;OJEfpWJ zcP4YP3g;_TSB=u}v_JQP7CUJ~$F|J+TW$;tbmvVfn$h7sZx`r@{^rS7y&JG;*+q%^ z{0n!d-1_8qT&TyfJY$EP_@Q#mwd=O-HPZZUQg-;^8a+?5jh9rE`Rz9Y zwD)SXyk8xYrN80i#d?*F{8H_fJRhTTn?ARE4i$@hYH2Mqf6`OF$l&{4k82X=y?wDZ zXSt}WrRd2r39G#2?q~k#&z@S>`g6-Zt$R|YZ b%}>cptHiA#vSKADqceEA`njxgN@xNA$oA4` literal 0 HcmV?d00001 diff --git a/ui/assets/not.png b/ui/assets/not.png new file mode 100644 index 0000000000000000000000000000000000000000..b78f2d9adfa5d5e768b8526ecfa05e4b1cc6ec1f GIT binary patch literal 800 zcmeAS@N?(olHy`uVBq!ia0vp^DL`z*!2%>1Y_^#KNtSd+Uq=Rpjs4tz5?O(Kg=CK) zUj~LMH3o);76yi2K%s^g3=E|P3=FRl7#OT(FffQ0%-I!a1C(G&@^*J&_}|`tW_`1{A4z6}&e|c@=0`L6`gcdtr;@5Io6yv3JnP)EFZritBjWe#= zG|%68mdE&f^|Q)-pMTcvKfG(xB3`S@rgN^Yx;n*g^0MT5+Kt}~pS>Kbfuf-YXES`hw&84H(*ZHo zV8*nli{C69SA8ow@R}hwaEmffvC4bThMy}^{DF!C@1->ST$7SNN8!Sn`xOl{&6DnL zGLD*KoZ|5=zP2%poyqstU2cQ;UMrct(%BsD^IrLydxTn+ADSTEW7YM}YJXU5^6|_3 zOncY0JL>Oxw9(~J^QKK*E=hmh`)}CF&}dw0(0QbX+0;IEtL5qw1!>ct)@a{+cJ0Z+ zFA|$Wc0XFWVf&t@-`8Cymbe`F7SG0NsPpZ<@7gZDf(>R{&mG%wBmP?0NmlV}3I0p_ zZxp{XYq_udB37*KxlH%h<{MAzVxQd?-tPL+I3pmwO4n;~<{y#enP*yh&$}dDo$+d4 zxAE1pE*}$@C;fT4z(?eTl=rgpk920HE$X;?BWy;;=Cv1Yyx1w4zF6IO?e;S!&h=ZC z`*()f*GpI^W^IiuiJbmo>ZbWw*QT1)vd@_G&|=oM2hV`XNVUW@q9i4;B-JXpC>2OC z7#SE^=o%R58d-!Gm|7WGSQ(mX8yHv_7~EJcx)Mc0ZhlH;S|x4`D}SvO1!`dMboFyt I=akR{06KM38~^|S literal 0 HcmV?d00001 diff --git a/ui/assets/resources.qrc b/ui/assets/resources.qrc index 5ac7291..3f9044c 100644 --- a/ui/assets/resources.qrc +++ b/ui/assets/resources.qrc @@ -6,5 +6,10 @@ and.png or.png + nand.png + nor.png + not.png + xnor.png + xor.png diff --git a/ui/assets/xnor.png b/ui/assets/xnor.png new file mode 100644 index 0000000000000000000000000000000000000000..27050955b4927127130da5eaf115ff2c98f2043a GIT binary patch literal 1204 zcmV;l1WWsgP)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00002 zVoOIv0RM-N%)bBt00(qQO+^Rd0vrV<2dpN40ssI5yh%hsRA}Dq*~C&{;eDTXzBBVaGtV=0t6SabRzVY-7Q#Y2 zD@rJb?6JwmmY8WsS3+4Ngf=Z|d{`1narx6~bJceZl$ApGRd4lvE*m9;<5n4!KS&?D zh42iTwFzOue?DDjpk{Yj?0vsnfV08Gyix8<<2nE@3SpC)lHR<=Lf_~pztz6w^v7XXJmm8 zR)bYSc&H+KJ<^HctUEN@T5u)1jIS=pI3auwo)*Fj6di=_5DtR5LRixYRzEFlu;={OAV-8Sxq2XVLO2bk z3gL@RusS%!I3E;RmY1+4SG2ThN@(c})u^(Xik8*`Linf?tgbDjEe3%hX=zO=?e#3b zQeSYQsQy>Q7_;1+YW-~Wo*MJ?#TH*z52QcX_pf?(HKbr*pZ;p~^>Au$^`Q3Zx!)Th z?d3y@>e)BMcU_GR^NqB*(7w%B+e`atF7Wgxp7V|-)bu(GoPYvWU#c))d+`Vc=gWgPzrtlq2u<7kT9$K@Zh zpNmYgXi}QncC))e^5K|1nZC9#9ZA~F>l*2xED?JjZ>3>qGbhgk-J?Ybx)EjDxZR$F zalmc)U=*iJpA^CmWm>r2n!=*ol1IYfoYo0pIj&4e?Ac`v!)j*|M7!rJOEy%V(K?|4 zFA3qt5|7#=Ew!u2L40Sl+|(zn>?IhUJkFGhJbkSeGdyQ)%153rJItwmq;WB=Oqq@P z%vW#i)|r;)tqA8YL(dqK=`ys{I*)0RyC$cfbg@#er;pj|C!cx60wePKt-IB&ZvF4{ zH~x~9dOw!(cK`qYC3HntbYx+4WjbSWWnpw>05UK!I4v+TEiyP%Ff}?eI65#lD=;uR zFfc+K+ui^G03~!qSaf7zbY(hiZ)9m^c>ppnF*q$SGA%MVR4_F004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00002 zVoOIv0RM-N%)bBt00(qQO+^Rd0vrV-DMH2&PXGV|UP(kjRA}Dq*X+*FEI}p;X_SO1Yt?`P#O_Q6cI=eQshH5MI?nm z^p|4H#0jD(nHm}Y%rt+R)x+IRH=?-r9JyzR``a&@%em{U@80|Dz1G?^)KEhWO>3nw zA@tx8QAHavV6WG0*6qBRgtAcxsi<;guO~t{qt-+J~TBA^M(tG zMR{8Y+i;3OA>2~Kzn6HJKu?$yCWPO>1|jS^30B`sCw(3B z$tEF;fz?8!HJ(q49M5nh=UQ5&Dt@WEvVhD7$H3_o{e0SP9!4!zs-fiqIjzF^a{qX4 zj9cB1w&H>M%}99`e*Q;4yINB+@VzJMxwI~XG;&KS`q_PW#hI9Lx6yinv{yL46dcS2 z@}O1VDeu*HgV-a4n=r?C?x69ul*50mshBXn4J(95AxqZes+=bd=8V@eXmzSM{*_qm z$bm7O&hr(;=j`RoB#W+2b319>Oej7a(UR$HJ*n(E>GqjX4$6|Tw|F59!?^WD7U=G+ zDA0A(Y~v~e31iTe#b8vHOdk-!CpB6)->&IJ`FRlqhqC&F@C;5(MeKDo4Z}_o31ZUY z`HBtsD_Y02;z=QVT4ex#i7gIPY!DyoEH2=0Nh^CZmZlwN)qgyFjxK9GYImwfo@o8n z7n{G7uig%5&V2PYsn41sZ$&t989HHkrpwUZ^|{Z2;`7LB(ns2>+Uw~fe(;62Jnb$W z#eLQdHPq1mPJaTp8ehMpH`rDH001R)MObuXVRU6WV{&C-bY%cCFflkSFfuJNI8-n- zIx{vpG%+hMFgh?WyHC)q0000bbVXQnWMOn=I&E)cX=Zr