mouseactions.cpp
------------------
begin : Thu Aug 28 2003
copyright : (C) 2003 by Michael Margraf
email : michael.margraf@alumni.tu-berlin.de
***************************************************************************/
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "mouseactions.h"
#include "components/component.h"
#include "components/componentdialog.h"
#include "components/optimizedialog.h"
#include "components/spicedialog.h"
#include "components/spicefile.h"
#include "components/vacomponent.h"
#include "diagrams/diagramdialog.h"
#include "diagrams/markerdialog.h"
#include "diagrams/tabdiagram.h"
#include "diagrams/timingdiagram.h"
#include "dialogs/labeldialog.h"
#include "dialogs/textboxdialog.h"
#include "dialogs/tuner.h"
#include "extsimkernels/customsimdialog.h"
#include "extsimkernels/spicelibcompdialog.h"
#include "main.h"
#include "module.h"
#include "node.h"
#include "qucs.h"
#include "schematic.h"
#include "spicecomponents/sp_customsim.h"
#include <QAction>
#include <QApplication>
#include <QClipboard>
#include <QDebug>
#include <QEvent>
#include <QLineEdit>
#include <QMenu>
#include <QMessageBox>
#include <QMouseEvent>
#include <QTextStream>
#include <qt3_compat/q3ptrlist.h>
#include <climits>
#include <cstdlib>
#define MIN_SELECT_SIZE 5.0
QAction *formerAction;
MouseActions::MouseActions(QucsApp *App_)
{
App = App_;
if(selElem != nullptr){
selElem = nullptr;
}
isMoveEqual = false;
focusElement = 0;
ComponentMenu = new QMenu(QucsMain);
focusMEvent = new QMouseEvent(QEvent::MouseButtonPress,
QPointF(0, 0),
QPointF(0, 0),
Qt::NoButton,
Qt::NoButton,
Qt::NoModifier);
}
MouseActions::~MouseActions()
{
delete ComponentMenu;
delete focusMEvent;
}
void MouseActions::setPainter(Schematic *Doc)
{
Doc->PostPaintEvent(_Translate, -Doc->contentsX(), -Doc->contentsY());
Doc->PostPaintEvent(_Scale, Doc->getScale(), Doc->getScale());
Doc->PostPaintEvent(_Translate, -Doc->getViewX1(), -Doc->getViewY1());
Doc->PostPaintEvent(_NotRop);
}
bool MouseActions::pasteElements(Schematic *Doc)
{
QClipboard *cb = QApplication::clipboard();
QString s = cb->text(QClipboard::Clipboard);
QTextStream stream(&s, QIODevice::ReadOnly);
movingElements.clear();
if (!Doc->paste(&stream, &movingElements))
return false;
int xmax, xmin, ymax, ymin;
xmin = ymin = INT_MAX;
xmax = ymax = INT_MIN;
for (auto* pe : movingElements) {
if (pe->Type == isWire) {
if (pe->x1 < xmin)
xmin = pe->x1;
if (pe->x2 > xmax)
xmax = pe->x2;
if (pe->y1 < ymin)
ymin = pe->y1;
if (pe->y2 > ymax)
ymax = pe->y2;
} else {
if (pe->cx < xmin)
xmin = pe->cx;
if (pe->cx > xmax)
xmax = pe->cx;
if (pe->cy < ymin)
ymin = pe->cy;
if (pe->cy > ymax)
ymax = pe->cy;
}
}
xmin = -((xmax + xmin) >> 1);
ymin = -((ymax + ymin) >> 1);
Doc->setOnGrid(xmin, ymin);
for (auto* pe : movingElements)
if (pe->Type & isLabel) {
pe->cx += xmin;
pe->x1 += xmin;
pe->cy += ymin;
pe->y1 += ymin;
} else
pe->setCenter(xmin, ymin, true);
return true;
}
void MouseActions::editLabel(Schematic *Doc, WireLabel *pl)
{
LabelDialog *Dia = new LabelDialog(pl, Doc);
int Result = Dia->exec();
if (Result == 0)
return;
QString Name = Dia->NodeName->text();
QString Value = Dia->InitValue->text();
delete Dia;
if (Name.isEmpty() && Value.isEmpty()) {
pl->pOwner->Label = 0;
delete pl;
} else {
while(Name.at(0) == '_') Name.remove(0,1); // must not start with '_'
if(Name.isEmpty()) return;
if(Name == pl->Name) return;*/
if (Result == 1)
return;
int old_x2 = pl->x2;
pl->setName(Name);
pl->initValue = Value;
if (pl->cx > (pl->x1 + (pl->x2 >> 1)))
pl->x1 -= pl->x2 - old_x2;
}
Doc->updateAllBoundingRect();
Doc->viewport()->update();
Doc->setChanged(true, true);
}
void MouseActions::endElementMoving(Schematic *Doc,
QList<Element*> *movElements) {
for (auto* pe : *movElements) {
switch (pe->Type) {
case isWire:
if (pe->x1 == pe->x2)
if (pe->y1 == pe->y2) {
if (((Wire *)pe)->Label) {
Doc->insertNodeLabel((WireLabel *)((Wire *)pe)->Label);
((Wire *)pe)->Label = nullptr;
}
delete (Wire *)pe;
break;
}
Doc->insertWire((Wire *)pe);
break;
case isDiagram:
Doc->a_Diagrams->append((Diagram *)pe);
break;
case isPainting:
Doc->a_Paintings->append((Painting *)pe);
break;
case isComponent:
case isAnalogComponent:
case isDigitalComponent:
Doc->insertRawComponent((Component *)pe, false);
break;
case isMovingLabel:
case isHMovingLabel:
case isVMovingLabel:
Doc->insertNodeLabel((WireLabel *)pe);
break;
case isMarker:
assert(dynamic_cast<Marker *>(pe));
break;
}
}
movElements->clear();
if ((MAx3 != 0) || (MAy3 != 0))
Doc->setChanged(true, true);
auto totalBounds = Doc->allBoundingRect();
Doc->enlargeView(totalBounds.left(), totalBounds.top(), totalBounds.right(), totalBounds.bottom());
Doc->viewport()->update();
}
void MouseActions::moveElements(QList<Element*> *movElements, int x, int y)
{
Wire *pw;
for (auto* pe : *movElements) {
if (pe->Type == isWire) {
pw = (Wire *) pe;
if (((uintptr_t) pw->Port1) > 3) {
pw->x1 += x;
pw->y1 += y;
if (pw->Label) {
pw->Label->cx += x;
pw->Label->cy += y;
}
} else {
if ((uintptr_t) (pw->Port1) & 1) {
pw->x1 += x;
}
if ((uintptr_t) (pw->Port1) & 2) {
pw->y1 += y;
}
}
if (((uintptr_t) pw->Port2) > 3) {
pw->x2 += x;
pw->y2 += y;
} else {
if ((uintptr_t) (pw->Port2) & 1)
pw->x2 += x;
if ((uintptr_t) (pw->Port2) & 2)
pw->y2 += y;
}
if (pw->Label) {
if (pw->Label->cx < pw->x1)
pw->Label->cx = pw->x1;
if (pw->Label->cy < pw->y1)
pw->Label->cy = pw->y1;
if (pw->Label->cx > pw->x2)
pw->Label->cx = pw->x2;
if (pw->Label->cy > pw->y2)
pw->Label->cy = pw->y2;
}
} else
pe->setCenter(x, y, true);
}
}
void MouseActions::MMoveElement(Schematic *Doc, QMouseEvent *Event)
{
if (selElem == nullptr)
return;
QPoint contentsCoordinates = Event->pos();
QPoint modelCoordinates = Doc->contentsToModel(contentsCoordinates);
int x = contentsCoordinates.x();
int y = contentsCoordinates.y();
int fx = modelCoordinates.x();
int fy = modelCoordinates.y();
int gx = fx;
int gy = fy;
Doc->setOnGrid(gx, gy);
setPainter(Doc);
if (selElem->Type == isPainting) {
Doc->PostPaintEvent(_NotRop, 0, 0, 0, 0);
((Painting *) selElem)->MouseMoving(Doc, x, y, gx, gy, Doc, fx, fy);
Doc->viewport()->update();
return;
}
selElem->setCenter(gx, gy);
selElem->paintScheme(Doc);
Doc->viewport()->update();
}
* @brief draws wire aiming cross
* @param Doc - pointer to Schematics object
* @param aimX - model x-coordinate of aim
* @param aimY - model y-coordinate of aim
*/
static void paintAim(Schematic *Doc, int aimX, int aimY) {
const QRect viewportAimBounds =
QRect{0, 0, Doc->viewport()->width(), Doc->viewport()->height()}
.marginsRemoved(QMargins{2, 2, 2, 2});
const QRect aimBounds{
Doc->viewportToModel(viewportAimBounds.topLeft()),
Doc->viewportToModel(viewportAimBounds.bottomRight())
};
Doc->PostPaintEvent(_Line, aimBounds.left(), aimY, aimBounds.right(), aimY);
Doc->PostPaintEvent(_Line, aimX, aimBounds.top(), aimX, aimBounds.bottom());
}
static void paintGhostLineH(Schematic *Doc, int fx, int fy, int fxx)
{
Doc->PostPaintEvent(_Line, fx, fy - 1, fxx, fy - 1);
Doc->PostPaintEvent(_Line, fx, fy + 1, fxx, fy + 1);
}
static void paintGhostLineV(Schematic *Doc, int fx, int fy, int fyy)
{
Doc->PostPaintEvent(_Line, fx - 1, fy, fx - 1, fyy);
Doc->PostPaintEvent(_Line, fx + 1, fy, fx + 1, fyy);
}
* @brief MouseActions::MMoveWire2 Paint wire as it is being drawn with mouse.
* @param Doc
* @param Event
*/
void MouseActions::MMoveWire2(Schematic *Doc, QMouseEvent *Event)
{
auto inModel = Doc->contentsToModel(Event->pos());
MAx2 = inModel.x();
MAy2 = inModel.y();
Doc->setOnGrid(MAx2, MAy2);
paintAim(Doc, MAx2, MAy2);
Doc->showEphemeralWire({MAx3, MAy3}, {MAx2, MAy2});
QucsMain->MouseDoubleClickAction = &MouseActions::MDoubleClickWire2;
Doc->viewport()->update();
}
* @brief MouseActions::MMoveWire1 Paint hair cross for "insert wire" mode
* @param Doc
* @param Event
*/
void MouseActions::MMoveWire1(Schematic *Doc, QMouseEvent *Event)
{
auto inModel = Doc->contentsToModel(Event->pos());
MAx3 = inModel.x();
MAy3 = inModel.y();
Doc->setOnGrid(MAx3, MAy3);
paintAim(Doc, MAx3, MAy3);
inModel = Doc->contentsToModel(
QPoint{
Doc->contentsX() + Doc->viewport()->width() - 1 - 2,
Doc->contentsY() + Doc->viewport()->height() - 1 - 2
}
);
MAx2 = inModel.x();
MAx2 = inModel.y();
Doc->viewport()->update();
}
* @brief MouseActions::MMoveSelect Paints a rectangle for select area.
* @param Doc
* @param Event
*/
void MouseActions::MMoveSelect(Schematic *Doc, QMouseEvent *Event)
{
auto inModel = Doc->contentsToModel(Event->pos());
MAx2 = inModel.x() - MAx1;
MAy2 = inModel.y() - MAy1;
if (isMoveEqual) {
if (abs(MAx2) > abs(MAy2)) {
if (MAx2 < 0)
MAx2 = -abs(MAy2);
else
MAx2 = abs(MAy2);
} else {
if (MAy2 < 0)
MAy2 = -abs(MAx2);
else
MAy2 = abs(MAx2);
}
}
Doc->PostPaintEvent(_SelectionRect, MAx1, MAy1, MAx2, MAy2);
}
void MouseActions::MMoveResizePainting(Schematic *Doc, QMouseEvent *Event)
{
setPainter(Doc);
auto inModel = Doc->contentsToModel(Event->pos());
MAx1 = inModel.x();
MAy1 = inModel.y();
Doc->setOnGrid(MAx1, MAy1);
((Painting *) focusElement)->MouseResizeMoving(MAx1, MAy1, Doc);
}
void MouseActions::MMoveMoving(Schematic *Doc, QMouseEvent *Event)
{
setPainter(Doc);
auto inModel = Doc->contentsToModel(Event->pos());
MAx2 = inModel.x();
MAy2 = inModel.y();
Doc->setOnGrid(MAx2, MAy2);
MAx3 = MAx1 = MAx2 - MAx1;
MAy3 = MAy1 = MAy2 - MAy1;
movingElements.clear();
{
Q3PtrList<Element> temp_buffer;
temp_buffer.setAutoDelete(false);
Doc->copySelectedElements(&temp_buffer);
for (auto* e : temp_buffer) { movingElements.append(e); }
}
Doc->viewport()->repaint();
Wire *pw;
for (Element *pe : movingElements) {
if (pe->Type == isWire) {
pw = (Wire *) pe;
if (((uintptr_t) pw->Port1) > 3) {
pw->x1 += MAx1;
pw->y1 += MAy1;
} else {
if ((uintptr_t) (pw->Port1) & 1) {
pw->x1 += MAx1;
}
if ((uintptr_t) (pw->Port1) & 2) {
pw->y1 += MAy1;
}
}
if (((uintptr_t) pw->Port2) > 3) {
pw->x2 += MAx1;
pw->y2 += MAy1;
} else {
if ((uintptr_t) (pw->Port2) & 1)
pw->x2 += MAx1;
if ((uintptr_t) (pw->Port2) & 2)
pw->y2 += MAy1;
}
if (pw->Label) {
if (pw->Label->cx < pw->x1)
pw->Label->cx = pw->x1;
if (pw->Label->cy < pw->y1)
pw->Label->cy = pw->y1;
if (pw->Label->cx > pw->x2)
pw->Label->cx = pw->x2;
if (pw->Label->cy > pw->y2)
pw->Label->cy = pw->y2;
}
} else
pe->setCenter(MAx1, MAy1, true);
pe->paintScheme(Doc);
}
MAx1 = MAx2;
MAy1 = MAy2;
QucsMain->MouseMoveAction = &MouseActions::MMoveMoving2;
QucsMain->MouseReleaseAction = &MouseActions::MReleaseMoving;
QucsMain->editRotate->blockSignals(true);
QucsMain->insLabel->blockSignals(true);
QucsMain->setMarker->blockSignals(true);
}
void MouseActions::MMoveMoving2(Schematic *Doc, QMouseEvent *Event)
{
setPainter(Doc);
auto inModel = Doc->contentsToModel(Event->pos());
MAx2 = inModel.x();
MAy2 = inModel.y();
if ((Event->modifiers().testFlag(Qt::ControlModifier)) == 0)
Doc->setOnGrid(MAx2, MAy2);
MAx1 = MAx2 - MAx1;
MAy1 = MAy2 - MAy1;
MAx3 += MAx1;
MAy3 += MAy1;
moveElements(&movingElements, MAx1, MAy1);
for (auto* pe : movingElements)
pe->paintScheme(Doc);
MAx1 = MAx2;
MAy1 = MAy2;
}
* @brief MouseActions::MMovePaste Moves components after paste from clipboard.
* @param Doc
* @param Event
*/
void MouseActions::MMovePaste(Schematic *Doc, QMouseEvent *Event)
{
auto inModel = Doc->contentsToModel(Event->pos());
MAx1 = inModel.x();
MAy1 = inModel.y();
moveElements(Doc, MAx1, MAy1);
paintElementsScheme(Doc);
QucsMain->MouseMoveAction = &MouseActions::MMoveMoving2;
QucsMain->MouseReleaseAction = &MouseActions::MReleasePaste;
}
void MouseActions::MMoveScrollBar(Schematic *Doc, QMouseEvent *Event)
{
TabDiagram *d = (TabDiagram *) focusElement;
auto inModel = Doc->contentsToModel(Event->pos());
int x = inModel.x();
int y = inModel.y();
if (d->scrollTo(MAx2, x - MAx1, y - MAy1)) {
Doc->setChanged(true, true, 'm');
}
}
* @brief MouseActions::MMoveDelete
* Paints a cross under the mouse cursor to show the delete mode.
* @param Doc Schematic document
* @param Event
*/
void MouseActions::MMoveDelete(Schematic *Doc, QMouseEvent *Event)
{
auto inModel = Doc->contentsToModel(Event->pos());
MAx3 = inModel.x();
MAy3 = inModel.y();
Doc->PostPaintEvent(_Line, MAx3 - 15, MAy3 - 15, MAx3 + 15, MAy3 + 15, 0, 0, false);
Doc->PostPaintEvent(_Line, MAx3 - 15, MAy3 + 15, MAx3 + 15, MAy3 - 15, 0, 0, false);
}
* @brief MouseActions::MMoveLabel Paints a label above the mouse cursor for "set wire label".
* @param Doc
* @param Event
*/
void MouseActions::MMoveLabel(Schematic *Doc, QMouseEvent *Event)
{
auto inModel = Doc->contentsToModel(Event->pos());
MAx3 = inModel.x();
MAy3 = inModel.y();
Doc->PostPaintEvent(_Line, MAx3, MAy3, MAx3 + 10, MAy3 - 10);
Doc->PostPaintEvent(_Line, MAx3 + 10, MAy3 - 10, MAx3 + 20, MAy3 - 10);
Doc->PostPaintEvent(_Line, MAx3 + 10, MAy3 - 10, MAx3 + 10, MAy3 - 17);
Doc->PostPaintEvent(_Line, MAx3 + 12, MAy3 - 12, MAx3 + 15, MAy3 - 23);
Doc->PostPaintEvent(_Line, MAx3 + 14, MAy3 - 17, MAx3 + 17, MAy3 - 17);
Doc->PostPaintEvent(_Line, MAx3 + 19, MAy3 - 12, MAx3 + 16, MAy3 - 23);
}
* @brief MouseActions::MMoveMarker Paints a triangle above the mouse for "set marker on graph"
* @param Doc
* @param Event
*/
void MouseActions::MMoveMarker(Schematic *Doc, QMouseEvent *Event)
{
auto inModel = Doc->contentsToModel(Event->pos());
MAx3 = inModel.x();
MAy3 = inModel.y();
Doc->PostPaintEvent(_Line, MAx3, MAy3 - 2, MAx3 - 8, MAy3 - 10);
Doc->PostPaintEvent(_Line, MAx3 + 1, MAy3 - 3, MAx3 + 8, MAy3 - 10);
Doc->PostPaintEvent(_Line, MAx3 - 7, MAy3 - 10, MAx3 + 7, MAy3 - 10);
}
* @brief MouseActions::MMoveSetLimits Sets the cursor to a magnifying glass with a wave.
* @param Doc
* @param Event
*/
void MouseActions::MMoveSetLimits(Schematic *Doc, QMouseEvent *Event)
{
auto inModel = Doc->contentsToModel(Event->pos());
MAx3 = inModel.x();
MAy3 = inModel.y();
}
* @brief MouseActions::MMoveMirrorX Paints rounded "mirror about y axis" mouse cursor
* @param Doc
* @param Event
*/
void MouseActions::MMoveMirrorY(Schematic *Doc, QMouseEvent *Event)
{
auto inModel = Doc->contentsToModel(Event->pos());
MAx3 = inModel.x();
MAy3 = inModel.y();
Doc->PostPaintEvent(_Line, MAx3 - 11, MAy3 - 4, MAx3 - 9, MAy3 - 9);
Doc->PostPaintEvent(_Line, MAx3 - 11, MAy3 - 3, MAx3 - 6, MAy3 - 3);
Doc->PostPaintEvent(_Line, MAx3 + 11, MAy3 - 4, MAx3 + 9, MAy3 - 9);
Doc->PostPaintEvent(_Line, MAx3 + 11, MAy3 - 3, MAx3 + 6, MAy3 - 3);
Doc->PostPaintEvent(_Arc, MAx3 - 10, MAy3 - 8, 21, 10, 16 * 20, 16 * 140, false);
}
* @brief MouseActions::MMoveMirrorX Paints rounded "mirror about x axis" mouse cursor
* @param Doc
* @param Event
*/
void MouseActions::MMoveMirrorX(Schematic *Doc, QMouseEvent *Event)
{
auto inModel = Doc->contentsToModel(Event->pos());
MAx3 = inModel.x();
MAy3 = inModel.y();
Doc->PostPaintEvent(_Line, MAx3 - 4, MAy3 - 11, MAx3 - 9, MAy3 - 9);
Doc->PostPaintEvent(_Line, MAx3 - 3, MAy3 - 11, MAx3 - 3, MAy3 - 6);
Doc->PostPaintEvent(_Line, MAx3 - 4, MAy3 + 11, MAx3 - 9, MAy3 + 9);
Doc->PostPaintEvent(_Line, MAx3 - 3, MAy3 + 11, MAx3 - 3, MAy3 + 6);
Doc->PostPaintEvent(_Arc, MAx3 - 8, MAy3 - 10, 10, 21, 16 * 110, 16 * 140, false);
}
* @brief MouseActions::MMoveMirrorX Paints "rotate" mouse cursor
* @param Doc
* @param Event
*/
void MouseActions::MMoveRotate(Schematic *Doc, QMouseEvent *Event)
{
auto inModel = Doc->contentsToModel(Event->pos());
MAx3 = inModel.x();
MAy3 = inModel.y();
Doc->PostPaintEvent(_Line, MAx3 - 6, MAy3 + 8, MAx3 - 6, MAy3 + 1);
Doc->PostPaintEvent(_Line, MAx3 - 7, MAy3 + 8, MAx3 - 12, MAy3 + 8);
Doc->PostPaintEvent(_Arc, MAx3 - 10, MAy3 - 10, 21, 21, -16 * 20, 16 * 240, false);
}
* @brief MouseActions::MMoveActivate Paints a crossed box mouse cursor to "(de)activate" components.
* @param Doc
* @param Event
*/
void MouseActions::MMoveActivate(Schematic *Doc, QMouseEvent *Event)
{
auto inModel = Doc->contentsToModel(Event->pos());
MAx3 = inModel.x();
MAy3 = inModel.y();
Doc->PostPaintEvent(_Rect, MAx3, MAy3 - 9, 14, 10);
Doc->PostPaintEvent(_Line, MAx3, MAy3 - 9, MAx3 + 13, MAy3);
Doc->PostPaintEvent(_Line, MAx3, MAy3, MAx3 + 13, MAy3 - 9);
}
* @brief MouseActions::MMoveOnGrid Paints a grid beside the mouse cursor, put "on grid" mode.
* @param Doc
* @param Event
*/
void MouseActions::MMoveOnGrid(Schematic *Doc, QMouseEvent *Event)
{
auto inModel = Doc->contentsToModel(Event->pos());
MAx3 = inModel.x();
MAy3 = inModel.y();
Doc->PostPaintEvent(_Line, MAx3 + 10, MAy3 + 3, MAx3 + 25, MAy3 + 3);
Doc->PostPaintEvent(_Line, MAx3 + 10, MAy3 + 7, MAx3 + 25, MAy3 + 7);
Doc->PostPaintEvent(_Line, MAx3 + 10, MAy3 + 11, MAx3 + 25, MAy3 + 11);
Doc->PostPaintEvent(_Line, MAx3 + 13, MAy3, MAx3 + 13, MAy3 + 15);
Doc->PostPaintEvent(_Line, MAx3 + 17, MAy3, MAx3 + 17, MAy3 + 15);
Doc->PostPaintEvent(_Line, MAx3 + 21, MAy3, MAx3 + 21, MAy3 + 15);
}
* @brief MouseActions::MMoveMoveTextB Paints mouse symbol for "move component text" mode.
* @param Doc
* @param Event
*/
void MouseActions::MMoveMoveTextB(Schematic *Doc, QMouseEvent *Event)
{
auto inModel = Doc->contentsToModel(Event->pos());
MAx3 = inModel.x();
MAy3 = inModel.y();
Doc->PostPaintEvent(_Line, MAx3 + 14, MAy3, MAx3 + 16, MAy3);
Doc->PostPaintEvent(_Line, MAx3 + 23, MAy3, MAx3 + 25, MAy3);
Doc->PostPaintEvent(_Line, MAx3 + 13, MAy3, MAx3 + 13, MAy3 + 3);
Doc->PostPaintEvent(_Line, MAx3 + 13, MAy3 + 7, MAx3 + 13, MAy3 + 10);
Doc->PostPaintEvent(_Line, MAx3 + 14, MAy3 + 10, MAx3 + 16, MAy3 + 10);
Doc->PostPaintEvent(_Line, MAx3 + 23, MAy3 + 10, MAx3 + 25, MAy3 + 10);
Doc->PostPaintEvent(_Line, MAx3 + 26, MAy3, MAx3 + 26, MAy3 + 3);
Doc->PostPaintEvent(_Line, MAx3 + 26, MAy3 + 7, MAx3 + 26, MAy3 + 10);
}
* @brief MouseActions::MMoveMoveText Paint rectangle around component text being mouse moved
* @param Doc
* @param Event
*/
void MouseActions::MMoveMoveText(Schematic *Doc, QMouseEvent *Event)
{
auto inModel = Doc->contentsToModel(Event->pos());
int newX = inModel.x();
int newY = inModel.y();
MAx1 += newX - MAx3;
MAy1 += newY - MAy3;
MAx3 = newX;
MAy3 = newY;
Doc->PostPaintEvent(_Rect, MAx1, MAy1, MAx2, MAy2);
}
* @brief MouseActions::MMoveZoomIn Paints symbol beside the mouse to show the "Zoom in" modus.
* @param Doc
* @param Event
*/
void MouseActions::MMoveZoomIn(Schematic *Doc, QMouseEvent *Event)
{
auto inModel = Doc->contentsToModel(Event->pos());
MAx3 = inModel.x();
MAy3 = inModel.y();
Doc->PostPaintEvent(_Line, MAx3 + 14, MAy3, MAx3 + 22, MAy3);
Doc->PostPaintEvent(_Line, MAx3 + 18, MAy3 - 4, MAx3 + 18, MAy3 + 4);
Doc->PostPaintEvent(_Ellipse, MAx3 + 12, MAy3 - 6, 13, 13, 0, 0, false);
Doc->viewport()->update();
}
void MouseActions::rightPressMenu(Schematic *Doc, QMouseEvent *Event, float fX, float fY)
{
MAx1 = int(fX);
MAy1 = int(fY);
focusElement = Doc->selectElement(fX, fY, false);
if (focusElement)
focusElement->Type &= isSpecialMask;
ComponentMenu->clear();
while (true) {
if (focusElement) {
focusElement->isSelected = true;
QAction *editProp = new QAction(QObject::tr("Edit Properties"), QucsMain);
QObject::connect(editProp, SIGNAL(triggered(bool)), QucsMain, SLOT(slotEditElement()));
ComponentMenu->addAction(editProp);
if ((focusElement->Type & isComponent) == 0)
break;
} else {
ComponentMenu->addAction(QucsMain->symEdit);
ComponentMenu->addAction(QucsMain->fileSettings);
}
if (!QucsMain->moveText->isChecked())
ComponentMenu->addAction(QucsMain->moveText);
break;
}
while (true) {
if (focusElement)
if (focusElement->Type == isGraph)
break;
if (!QucsMain->onGrid->isChecked())
ComponentMenu->addAction(QucsMain->onGrid);
ComponentMenu->addAction(QucsMain->editCopy);
if (!QucsMain->editPaste->isChecked())
ComponentMenu->addAction(QucsMain->editPaste);
break;
}
while (true) {
if (focusElement) {
if (focusElement->Type == isDiagram) {
Diagram* diagram = static_cast<Diagram*>(focusElement);
if (diagram->Name == "Rect" &&
(!diagram->xAxis.autoScale || !diagram->yAxis.autoScale || !diagram->zAxis.autoScale)) {
ComponentMenu->addAction(QucsMain->resetDiagramLimits);
}
QAction *actExport = new QAction(QObject::tr("Export as image"), QucsMain);
QObject::connect(actExport,
SIGNAL(triggered(bool)),
QucsMain,
SLOT(slotSaveDiagramToGraphicsFile()));
ComponentMenu->addAction(actExport);
}
}
break;
}
if (!QucsMain->editDelete->isChecked())
ComponentMenu->addAction(QucsMain->editDelete);
if (focusElement)
if (focusElement->Type == isMarker) {
ComponentMenu->addSeparator();
QString s = QObject::tr("power matching");
if (((Marker *) focusElement)->pGraph->Var == "Sopt")
s = QObject::tr("noise matching");
QAction *actPwrMatching = new QAction(s, QucsMain);
QObject::connect(actPwrMatching,
SIGNAL(triggered(bool)),
QucsMain,
SLOT(slotPowerMatching()));
ComponentMenu->addAction(actPwrMatching);
if (((Marker *) focusElement)->pGraph->Var.left(2) == "S[") {
QAction *act2PortMatching = new QAction(QObject::tr("2-port matching"), QucsMain);
QObject::connect(act2PortMatching,
SIGNAL(triggered(bool)),
QucsMain,
SLOT(slot2PortMatching()));
ComponentMenu->addAction(act2PortMatching);
}
}
do {
if (focusElement) {
if (focusElement->Type == isDiagram)
break;
if (focusElement->Type == isGraph) {
ComponentMenu->addAction(QucsMain->graph2csv);
break;
}
}
ComponentMenu->addSeparator();
if (focusElement)
if (focusElement->Type & isComponent)
if (!QucsMain->editActivate->isChecked())
ComponentMenu->addAction(QucsMain->editActivate);
if (!QucsMain->editRotate->isChecked())
ComponentMenu->addAction(QucsMain->editRotate);
if (!QucsMain->editMirror->isChecked())
ComponentMenu->addAction(QucsMain->editMirror);
if (!QucsMain->editMirrorY->isChecked())
ComponentMenu->addAction(QucsMain->editMirrorY);
if (focusElement) {
if (focusElement->Type & isComponent)
if (((Component *) focusElement)->Model == "Sub")
if (!QucsMain->intoH->isChecked())
ComponentMenu->addAction(QucsMain->intoH);
}
if (!focusElement)
if (!QucsMain->popH->isChecked())
ComponentMenu->addAction(QucsMain->popH);
} while (false);
#if QT_VERSION >= 0x060000
ComponentMenu->popup(Event->globalPosition().toPoint());
#else
ComponentMenu->popup(Event->globalPos());
#endif
Doc->viewport()->update();
}
void MouseActions::MPressLabel(Schematic *Doc, QMouseEvent *, float fX, float fY)
{
int x = int(fX), y = int(fY);
Wire *pw = 0;
WireLabel *pl = 0;
Node *pn = Doc->selectedNode(x, y);
if (!pn) {
pw = Doc->selectedWire(x, y);
if (!pw)
return;
}
QString Name, Value;
Element *pe = 0;
if (pw)
pe = Doc->getWireLabel(pw->Port1);
else
pe = Doc->getWireLabel(pn);
if (pe) {
if (pe->Type & isComponent) {
QMessageBox::information(0,
QObject::tr("Info"),
QObject::tr("The ground potential cannot be labeled!"));
return;
}
pl = ((Conductor *) pe)->Label;
}
LabelDialog *Dia = new LabelDialog(pl, Doc);
if (Dia->exec() == 0)
return;
Name = Dia->NodeName->text();
Value = Dia->InitValue->text();
delete Dia;
if (Name.isEmpty() && Value.isEmpty()) {
if (pe) {
if (((Conductor *) pe)->Label)
delete ((Conductor *) pe)->Label;
((Conductor *) pe)->Label = 0;
} else {
if (pw)
pw->setName("", "");
else
pn->setName("", "");
}
} else {
while(Name.at(0) == '_') Name.remove(0,1); // must not start with '_'
if(Name.isEmpty()) return;
*/
if (pe) {
delete ((Conductor *) pe)->Label;
((Conductor *) pe)->Label = nullptr;
}
int xl = x + 30;
int yl = y - 30;
Doc->setOnGrid(xl, yl);
if (pw)
pw->setName(Name, Value, x - pw->x1 + y - pw->y1, xl, yl);
else
pn->setName(Name, Value, xl, yl);
}
Doc->updateAllBoundingRect();
Doc->viewport()->update();
Doc->setChanged(true, true);
}
void MouseActions::MPressSelect(Schematic *Doc, QMouseEvent *Event, float fX, float fY)
{
bool Ctrl;
if (Event->modifiers().testFlag(Qt::ControlModifier))
Ctrl = true;
else
Ctrl = false;
int No = 0;
MAx1 = int(fX);
MAy1 = int(fY);
focusElement = Doc->selectElement(fX, fY, Ctrl, &No);
isMoveEqual = false;
if (focusElement)
qDebug() << "MPressSelect: focusElement->Type"
<< QStringLiteral("0x%1").arg(focusElement->Type, 0, 16);
else
qDebug() << "MPressSelect";
if (focusElement)
switch (focusElement->Type) {
case isPaintingResize:
focusElement->Type = isPainting;
QucsMain->MouseReleaseAction = &MouseActions::MReleaseResizePainting;
QucsMain->MouseMoveAction = &MouseActions::MMoveResizePainting;
QucsMain->MousePressAction = 0;
QucsMain->MouseDoubleClickAction = 0;
Doc->grabKeyboard();
Doc->highlightWireLabels();
return;
case isDiagramResize:
if (((Diagram *) focusElement)->Name.left(4) != "Rect")
if (((Diagram *) focusElement)->Name.at(0) != 'T')
if (((Diagram *) focusElement)->Name != "Curve")
isMoveEqual = true;
focusElement->Type = isDiagram;
MAx1 = focusElement->cx;
MAx2 = focusElement->x2;
if (((Diagram *) focusElement)->State & 1) {
MAx1 += MAx2;
MAx2 *= -1;
}
MAy1 = focusElement->cy;
MAy2 = -focusElement->y2;
if (((Diagram *) focusElement)->State & 2) {
MAy1 += MAy2;
MAy2 *= -1;
}
QucsMain->MouseReleaseAction = &MouseActions::MReleaseResizeDiagram;
QucsMain->MouseMoveAction = &MouseActions::MMoveSelect;
QucsMain->MousePressAction = 0;
QucsMain->MouseDoubleClickAction = 0;
Doc->grabKeyboard();
Doc->highlightWireLabels();
return;
case isDiagramHScroll:
case isDiagramVScroll:
if (focusElement->Type == isDiagramHScroll)
{
MAy1 = MAx1;
}
focusElement->Type = isDiagram;
No = ((TabDiagram *) focusElement)->scroll(MAy1);
switch (No) {
case 1:
Doc->setChanged(true, true, 'm');
break;
case 2:
QucsMain->MouseMoveAction = &MouseActions::MMoveScrollBar;
QucsMain->MousePressAction = 0;
QucsMain->MouseDoubleClickAction = 0;
Doc->grabKeyboard();
MAx2 = int(((TabDiagram *) focusElement)->xAxis.limit_min);
Doc->highlightWireLabels();
return;
}
Doc->highlightWireLabels();
Doc->viewport()->update();
return;
case isComponentText:
focusElement->Type &= (~isComponentText) | isComponent;
MAx3 = No;
QucsMain->slotApplyCompText();
Doc->highlightWireLabels();
return;
case isNode:
if (QucsSettings.NodeWiring) {
MAx1 = 0;
MAx3 = focusElement->cx;
MAy3 = focusElement->cy;
QucsMain->MouseMoveAction = &MouseActions::MMoveWire2;
QucsMain->MousePressAction = &MouseActions::MPressWire2;
QucsMain->MouseReleaseAction = 0;
QucsMain->MouseDoubleClickAction = 0;
formerAction = QucsMain->select;
QucsMain->activeAction = QucsMain->insWire;
QucsMain->select->blockSignals(true);
QucsMain->select->setChecked(false);
QucsMain->select->blockSignals(false);
QucsMain->insWire->blockSignals(true);
QucsMain->insWire->setChecked(true);
QucsMain->insWire->blockSignals(false);
Doc->highlightWireLabels();
return;
}
}
QucsMain->MousePressAction = 0;
QucsMain->MouseDoubleClickAction = 0;
Doc->grabKeyboard();
Doc->viewport()->update();
if (focusElement == 0) {
MAx2 = 0;
MAy2 = 0;
QucsMain->MouseReleaseAction = &MouseActions::MReleaseSelect2;
QucsMain->MouseMoveAction = &MouseActions::MMoveSelect;
} else {
if (!Ctrl) {
if (!focusElement->isSelected)
Doc->deselectElements(focusElement);
focusElement->isSelected = true;
}
Doc->setOnGrid(MAx1, MAy1);
QucsMain->MouseMoveAction = &MouseActions::MMoveMoving;
}
Doc->highlightWireLabels();
}
void MouseActions::MPressDelete(Schematic *Doc, QMouseEvent *, float fX, float fY)
{
Element *pe = Doc->selectElement(fX, fY, false);
if (pe) {
pe->isSelected = true;
Doc->deleteElements();
Doc->updateAllBoundingRect();
Doc->viewport()->update();
}
}
void MouseActions::MPressActivate(Schematic *Doc, QMouseEvent *, float fX, float fY)
{
MAx1 = int(fX);
MAy1 = int(fY);
if (!Doc->activateSpecifiedComponent(MAx1, MAy1)) {
MAx2 = 0;
MAy2 = 0;
QucsMain->MousePressAction = 0;
QucsMain->MouseReleaseAction = &MouseActions::MReleaseActivate;
QucsMain->MouseMoveAction = &MouseActions::MMoveSelect;
}
Doc->viewport()->update();
}
void MouseActions::MPressMirrorX(Schematic *Doc, QMouseEvent *, float fX, float fY)
{
Component *c = Doc->selectedComponent(int(fX), int(fY));
if (c) {
if (c->Ports.count() < 1)
return;
c->mirrorX();
Doc->setCompPorts(c);
} else {
Painting *p = Doc->selectedPainting(fX, fY);
if (p == 0)
return;
p->mirrorX();
}
Doc->viewport()->update();
Doc->setChanged(true, true);
}
void MouseActions::MPressMirrorY(Schematic *Doc, QMouseEvent *, float fX, float fY)
{
Component *c = Doc->selectedComponent(int(fX), int(fY));
if (c) {
if (c->Ports.count() < 1)
return;
c->mirrorY();
Doc->setCompPorts(c);
} else {
Painting *p = Doc->selectedPainting(fX, fY);
if (p == 0)
return;
p->mirrorY();
}
Doc->viewport()->update();
Doc->setChanged(true, true);
}
void MouseActions::MPressRotate(Schematic *Doc, QMouseEvent *, float fX, float fY)
{
Element *e = Doc->selectElement(int(fX), int(fY), false);
if (e == 0)
return;
e->Type &= isSpecialMask;
WireLabel *pl;
int x1, y1, x2, y2;
switch (e->Type) {
case isComponent:
case isAnalogComponent:
case isDigitalComponent:
if (((Component *) e)->Ports.count() < 1)
break;
((Component *) e)->rotate();
Doc->setCompPorts((Component *) e);
((Component *) e)->entireBounds(x1, y1, x2, y2);
Doc->enlargeView(x1, y1, x2, y2);
break;
case isWire:
pl = ((Wire *) e)->Label;
((Wire *) e)->Label = 0;
Doc->a_Wires->setAutoDelete(false);
Doc->deleteWire((Wire *) e);
((Wire *) e)->Label = pl;
((Wire *) e)->rotate();
Doc->setOnGrid(e->x1, e->y1);
Doc->setOnGrid(e->x2, e->y2);
if (pl)
Doc->setOnGrid(pl->cx, pl->cy);
Doc->insertWire((Wire *) e);
Doc->a_Wires->setAutoDelete(true);
if (Doc->a_Wires->containsRef((Wire *) e))
Doc->enlargeView(e->x1, e->y1, e->x2, e->y2);
break;
case isPainting:
((Painting *) e)->rotate(0, 0);
((Painting *) e)->Bounding(x1, y1, x2, y2);
Doc->enlargeView(x1, y1, x2, y2);
break;
default:
return;
}
Doc->viewport()->update();
Doc->setChanged(true, true);
}
void MouseActions::MPressElement(Schematic *Doc, QMouseEvent *Event, float, float)
{
if (selElem == 0)
return;
int x1, y1, x2, y2, rot;
if (selElem->Type & isComponent) {
Component *Comp = (Component *) selElem;
QString entryName = Comp->Name;
switch (Event->button()) {
case Qt::LeftButton:
Comp->setSchematic(Doc);
Comp->textSize(x1, y1);
Doc->insertComponent(Comp);
Comp->textSize(x2, y2);
if (Comp->tx < Comp->x1)
Comp->tx -= x2 - x1;
Comp->entireBounds(x1, y1, x2, y2);
Doc->enlargeView(x1, y1, x2, y2);
Doc->viewport()->update();
Doc->setChanged(true, true);
rot = Comp->rotated;
if (Module::vaComponents.contains(entryName)) {
QString filename = Module::vaComponents[entryName];
Comp = dynamic_cast<vacomponent *>(Comp)->newOne(filename);
qDebug() << " => recast = Comp;" << Comp->Name << "filename: " << filename;
} else {
Comp = Comp->newOne();
}
rot -= Comp->rotated;
rot &= 3;
while (rot--)
Comp->rotate();
break;
case Qt::RightButton:
if (Comp->Ports.count() == 0)
break;
Comp->paintScheme(Doc);
Doc->viewport()->repaint();
Comp->rotate();
Doc->setOnGrid(Comp->cx,Comp->cy);
Comp->paintScheme(Doc);
break;
default:;
}
selElem = Comp;
return;
}
else if (selElem->Type == isDiagram) {
if (Event->button() != Qt::LeftButton)
return;
Diagram *Diag = (Diagram *) selElem;
QFileInfo Info(Doc->getDocName());
DiagramDialog *dia = new DiagramDialog(Diag, Doc);
if (dia->exec() == QDialog::Rejected) {
Doc->viewport()->update();
return;
}
Doc->a_Diagrams->append(Diag);
Doc->enlargeView(Diag->cx, Diag->cy - Diag->y2, Diag->cx + Diag->x2, Diag->cy);
Doc->setChanged(true, true);
Doc->viewport()->repaint();
Diag = Diag->newOne();
Diag->paintScheme(Doc);
selElem = Diag;
return;
}
if (((Painting *) selElem)->MousePressing(Doc)) {
Doc->a_Paintings->append((Painting *) selElem);
((Painting *) selElem)->Bounding(x1, y1, x2, y2);
selElem = ((Painting *) selElem)->newOne();
Doc->viewport()->update();
Doc->setChanged(true, true);
MMoveElement(Doc, Event);
}
}
* @brief MouseActions::MPressWire1 Is called if starting point of wire is pressed
* @param Doc
* @param fX
* @param fY
*/
void MouseActions::MPressWire1(Schematic *Doc, QMouseEvent *, float fX, float fY)
{
#if 0
Doc->PostPaintEvent (_Line, 0, MAy3, MAx2, MAy3);
Doc->PostPaintEvent (_Line, MAx3, 0, MAx3, MAy2);
#endif
MAx1 = 0;
MAx3 = int(fX);
MAy3 = int(fY);
Doc->setOnGrid(MAx3, MAy3);
paintAim(Doc, MAx3, MAy3);
formerAction = 0;
QucsMain->MouseMoveAction = &MouseActions::MMoveWire2;
QucsMain->MousePressAction = &MouseActions::MPressWire2;
Doc->viewport()->update();
}
* @brief MouseActions::MPressWire2 Is called if ending point of wire is pressed
* @param Doc
* @param Event
* @param fX
* @param fY
*/
void MouseActions::MPressWire2(Schematic *Doc, QMouseEvent *Event, float fX, float fY)
{
switch (Event->button()) {
case Qt::LeftButton: {
auto [hasChanges, lastNode] = Doc->connectWithWire({MAx3, MAy3}, {MAx2, MAy2});
if (lastNode == nullptr || lastNode->conn_count() > 1) {
if (formerAction) {
QucsMain->select->setChecked(true);
} else {
QucsMain->MouseMoveAction = &MouseActions::MMoveWire1;
QucsMain->MousePressAction = &MouseActions::MPressWire1;
QucsMain->MouseDoubleClickAction = 0;
}
}
if (hasChanges)
Doc->setChanged(true, true);
MAx3 = MAx2;
MAy3 = MAy2;
break;
}
case Qt::RightButton:
Doc->a_wirePlanner.next();
#if 0
if(MAx1 == 0) {
Doc->PostPaintEvent (_Line, MAx3, MAy3, MAx3, MAy2);
Doc->PostPaintEvent (_Line, MAx3, MAy2, MAx2, MAy2);
}
else {
Doc->PostPaintEvent (_Line, MAx3, MAy3, MAx2, MAy3);
Doc->PostPaintEvent (_Line, MAx2, MAy3, MAx2, MAy2);
}
#endif
MAx2 = int(fX);
MAy2 = int(fY);
Doc->setOnGrid(MAx2, MAy2);
MAx1 ^= 1;
Doc->showEphemeralWire({MAx3, MAy3}, {MAx2, MAy2});
break;
default:;
}
paintAim(Doc, MAx2, MAy2);
Doc->viewport()->update();
}
void MouseActions::MPressMarker(Schematic *Doc, QMouseEvent *, float fX, float fY)
{
MAx1 = int(fX);
MAy1 = int(fY);
Marker *pm = Doc->setMarker(MAx1, MAy1);
if (pm) {
assert(pm->diag());
int x0 = pm->diag()->cx;
int y0 = pm->diag()->cy;
Doc->enlargeView(x0 + pm->x1, y0 - pm->y1 - pm->y2, x0 + pm->x1 + pm->x2, y0 - pm->y1);
}
Doc->viewport()->update();
}
* @brief MouseActions::MPressSetLimits Sets the start point of the diagram limits.
* @param Doc
* @param Event
*/
void MouseActions::MPressSetLimits(Schematic *Doc, QMouseEvent*, float fX, float fY)
{
MAx1 = int(fX);
MAy1 = int(fY);
for (Diagram* diagram = Doc->a_Diagrams->last(); diagram != 0; diagram = Doc->a_Diagrams->prev()) {
if (diagram->getSelected(fX, fY) && diagram->Name == "Rect") {
qDebug() << "In a rectangular diagram, setting up for area selection.";
mouseDownPoint = QPointF(fX - diagram->cx, diagram->cy - fY);
pActiveDiagram = diagram;
QucsMain->MouseMoveAction = &MouseActions::MMoveSelect;
QucsMain->MouseReleaseAction = &MouseActions::MReleaseSetLimits;
Doc->grabKeyboard();
break;
}
}
Doc->viewport()->update();
}
void MouseActions::MPressOnGrid(Schematic *Doc, QMouseEvent *, float fX, float fY)
{
Element *pe = Doc->selectElement(fX, fY, false);
if (pe) {
pe->Type &= isSpecialMask;
pe->isSelected = true;
Doc->elementsOnGrid();
Doc->updateAllBoundingRect();
Doc->highlightWireLabels();
Doc->viewport()->update();
}
}
void MouseActions::MPressMoveText(Schematic *Doc, QMouseEvent *, float fX, float fY)
{
MAx1 = int(fX);
MAy1 = int(fY);
focusElement = Doc->selectCompText(MAx1, MAy1, MAx2, MAy2);
if (focusElement) {
MAx3 = MAx1;
MAy3 = MAy1;
MAx1 = ((Component *) focusElement)->cx + ((Component *) focusElement)->tx;
MAy1 = ((Component *) focusElement)->cy + ((Component *) focusElement)->ty;
Doc->viewport()->update();
QucsMain->MouseMoveAction = &MouseActions::MMoveMoveText;
QucsMain->MouseReleaseAction = &MouseActions::MReleaseMoveText;
Doc->grabKeyboard();
}
}
void MouseActions::MPressZoomIn(Schematic *Doc, QMouseEvent *, float fX, float fY)
{
qDebug() << "zoom into box";
MAx1 = int(fX);
MAy1 = int(fY);
MAx2 = 0;
MAy2 = 0;
QucsMain->MouseMoveAction = &MouseActions::MMoveSelect;
QucsMain->MouseReleaseAction = &MouseActions::MReleaseZoomIn;
Doc->grabKeyboard();
Doc->viewport()->update();
}
void MouseActions::MReleaseSelect(Schematic *Doc, QMouseEvent *Event)
{
bool ctrl;
if (Event->modifiers().testFlag(Qt::ControlModifier))
ctrl = true;
else
ctrl = false;
if (!ctrl)
Doc->deselectElements(focusElement);
if (focusElement)
if (Event->button() == Qt::LeftButton)
if (focusElement->Type == isWire) {
Doc->selectWireLine(focusElement, ((Wire *) focusElement)->Port1, ctrl);
Doc->selectWireLine(focusElement, ((Wire *) focusElement)->Port2, ctrl);
}
Doc->releaseKeyboard();
QucsMain->MousePressAction = &MouseActions::MPressSelect;
QucsMain->MouseReleaseAction = &MouseActions::MReleaseSelect;
QucsMain->MouseDoubleClickAction = &MouseActions::MDoubleClickSelect;
QucsMain->MouseMoveAction = 0;
Doc->highlightWireLabels();
Doc->viewport()->update();
}
void MouseActions::MReleaseSelect2(Schematic *Doc, QMouseEvent *Event)
{
if (Event->button() != Qt::LeftButton)
return;
bool IsCtrl = Event->modifiers().testFlag(Qt::ControlModifier);
bool IsShift = Event->modifiers().testFlag(Qt::ShiftModifier);
Doc->selectElements(
QRect{MAx1, MAy1, MAx2, MAy2}.normalized(), IsCtrl, !IsShift);
Doc->releaseKeyboard();
QucsMain->MouseMoveAction = 0;
QucsMain->MousePressAction = &MouseActions::MPressSelect;
QucsMain->MouseReleaseAction = &MouseActions::MReleaseSelect;
QucsMain->MouseDoubleClickAction = &MouseActions::MDoubleClickSelect;
Doc->highlightWireLabels();
Doc->clearPostedPaintEvents();
Doc->viewport()->update();
}
void MouseActions::MReleaseActivate(Schematic *Doc, QMouseEvent *Event)
{
if (Event->button() != Qt::LeftButton)
return;
Doc->activateCompsWithinRect(MAx1, MAy1, MAx1 + MAx2, MAy1 + MAy2);
QucsMain->MouseMoveAction = &MouseActions::MMoveActivate;
QucsMain->MousePressAction = &MouseActions::MPressActivate;
QucsMain->MouseReleaseAction = 0;
QucsMain->MouseDoubleClickAction = 0;
Doc->highlightWireLabels();
Doc->viewport()->update();
}
void MouseActions::MReleaseMoving(Schematic *Doc, QMouseEvent *)
{
endElementMoving(Doc, &movingElements);
Doc->releaseKeyboard();
QucsMain->MouseMoveAction = nullptr;
QucsMain->MousePressAction = &MouseActions::MPressSelect;
QucsMain->MouseReleaseAction = &MouseActions::MReleaseSelect;
QucsMain->MouseDoubleClickAction = &MouseActions::MDoubleClickSelect;
QucsMain->editRotate->setChecked(false);
QucsMain->editRotate->blockSignals(false);
QucsMain->insLabel->blockSignals(false);
QucsMain->setMarker->blockSignals(false);
}
void MouseActions::MReleaseResizeDiagram(Schematic *Doc, QMouseEvent *Event)
{
if (Event->button() != Qt::LeftButton)
return;
MAx3 = focusElement->cx;
MAy3 = focusElement->cy;
if (MAx2 < 0) {
if (MAx2 > -10)
MAx2 = -10;
focusElement->x2 = -MAx2;
focusElement->cx = MAx1 + MAx2;
} else {
if (MAx2 < 10)
MAx2 = 10;
focusElement->x2 = MAx2;
focusElement->cx = MAx1;
}
if (MAy2 < 0) {
if (MAy2 > -10)
MAy2 = -10;
focusElement->y2 = -MAy2;
focusElement->cy = MAy1;
} else {
if (MAy2 < 10)
MAy2 = 10;
focusElement->y2 = MAy2;
focusElement->cy = MAy1 + MAy2;
}
MAx3 -= focusElement->cx;
MAy3 -= focusElement->cy;
Diagram *pd = (Diagram *) focusElement;
pd->updateGraphData();
for (Graph *pg : pd->Graphs)
for (Marker *pm : pg->Markers) {
pm->x1 += MAx3;
pm->y1 += MAy3;
}
int x1, x2, y1, y2;
pd->Bounding(x1, x2, y1, y2);
Doc->enlargeView(x1, x2, y1, y2);
QucsMain->MouseMoveAction = nullptr;
QucsMain->MousePressAction = &MouseActions::MPressSelect;
QucsMain->MouseReleaseAction = &MouseActions::MReleaseSelect;
QucsMain->MouseDoubleClickAction = &MouseActions::MDoubleClickSelect;
Doc->releaseKeyboard();
Doc->viewport()->update();
Doc->setChanged(true, true);
}
void MouseActions::MReleaseResizePainting(Schematic *Doc, QMouseEvent *Event)
{
if (Event->button() != Qt::LeftButton)
return;
QucsMain->MouseMoveAction = nullptr;
QucsMain->MousePressAction = &MouseActions::MPressSelect;
QucsMain->MouseReleaseAction = &MouseActions::MReleaseSelect;
QucsMain->MouseDoubleClickAction = &MouseActions::MDoubleClickSelect;
Doc->releaseKeyboard();
Doc->viewport()->update();
Doc->setChanged(true, true);
}
void MouseActions::MReleaseSetLimits(Schematic *Doc, QMouseEvent *Event)
{
Doc->releaseKeyboard();
auto inModel = Doc->contentsToModel(Event->pos());
MAx2 = inModel.x();
MAy2 = inModel.y();
qDebug() << "Mouse released after setting limits.";
for (Diagram* diagram = Doc->a_Diagrams->last(); diagram != 0; diagram = Doc->a_Diagrams->prev()) {
if (diagram->getSelected(MAx2, MAy2) && diagram == pActiveDiagram) {
qDebug() << "In the same diagram, setting limits";
mouseUpPoint = QPointF(MAx2 - diagram->cx, diagram->cy - MAy2);
QRectF select = QRectF(mouseDownPoint, mouseUpPoint).normalized();
if (select.width() < MIN_SELECT_SIZE || select.height() < MIN_SELECT_SIZE)
break;
diagram->setLimitsBySelectionRect(select);
diagram->updateGraphData();
Doc->setChanged(true, true);
break;
}
}
QucsMain->MouseMoveAction = &MouseActions::MMoveSetLimits;
QucsMain->MouseReleaseAction = nullptr;
Doc->viewport()->update();
}
void MouseActions::paintElementsScheme(Schematic *p)
{
for (auto* pe : movingElements)
pe->paintScheme(p);
}
void MouseActions::moveElements(Schematic *Doc, int &x1, int &y1)
{
Doc->setOnGrid(x1, y1);
for (auto* pe : movingElements) {
if (pe->Type & isLabel) {
pe->cx += x1;
pe->x1 += x1;
pe->cy += y1;
pe->y1 += y1;
} else
pe->setCenter(x1, y1, true);
}
}
void MouseActions::rotateElements(Schematic *Doc, int &x1, int &y1)
{
int x2;
Doc->setOnGrid(x1, y1);
for (auto* pe : movingElements) {
switch (pe->Type) {
case isComponent:
case isAnalogComponent:
case isDigitalComponent:
((Component *) pe)->rotate();
x2 = x1 - pe->cx;
pe->setCenter(pe->cy - y1 + x1, x2 + y1);
break;
case isWire:
x2 = pe->x1;
pe->x1 = pe->y1 - y1 + x1;
pe->y1 = x1 - x2 + y1;
x2 = pe->x2;
pe->x2 = pe->y2 - y1 + x1;
pe->y2 = x1 - x2 + y1;
break;
case isPainting:
((Painting *) pe)->rotate(x1, y1);
break;
default:
x2 = x1 - pe->cx;
pe->setCenter(pe->cy - y1 + x1, x2 + y1);
break;
}
}
}
void MouseActions::MReleasePaste(Schematic *Doc, QMouseEvent *Event)
{
int x1, y1, x2, y2, rot;
QFileInfo Info(Doc->getDocName());
switch (Event->button()) {
case Qt::LeftButton:
for (auto* pe : movingElements) {
pe->isSelected = false;
switch (pe->Type) {
case isWire:
if (pe->x1 == pe->x2)
if (pe->y1 == pe->y2)
break;
Doc->insertWire((Wire *) pe);
if (Doc->a_Wires->containsRef((Wire *) pe))
Doc->enlargeView(pe->x1, pe->y1, pe->x2, pe->y2);
else
pe = NULL;
break;
case isDiagram:
Doc->a_Diagrams->append((Diagram *) pe);
((Diagram *) pe)
->loadGraphData(Info.absolutePath() + QDir::separator() + Doc->getDataSet());
Doc->enlargeView(pe->cx, pe->cy - pe->y2, pe->cx + pe->x2, pe->cy);
break;
case isPainting:
Doc->a_Paintings->append((Painting *) pe);
((Painting *) pe)->Bounding(x1, y1, x2, y2);
Doc->enlargeView(x1, y1, x2, y2);
break;
case isMovingLabel:
pe->Type = isNodeLabel;
Doc->placeNodeLabel((WireLabel *) pe);
break;
case isComponent:
case isAnalogComponent:
case isDigitalComponent:
Doc->insertComponent((Component *) pe);
((Component *) pe)->entireBounds(x1, y1, x2, y2);
Doc->enlargeView(x1, y1, x2, y2);
break;
}
}
pasteElements(Doc);
rot = movingRotated;
x1 = y1 = 0;
while (rot--)
rotateElements(Doc, x1, y1);
QucsMain->MouseMoveAction = &MouseActions::MMovePaste;
QucsMain->MousePressAction = 0;
QucsMain->MouseReleaseAction = 0;
QucsMain->MouseDoubleClickAction = 0;
Doc->viewport()->update();
Doc->setChanged(true, true);
break;
case Qt::RightButton: {
auto inModel = Doc->contentsToModel(Event->pos());
x1 = inModel.x();
y1 = inModel.y();
rotateElements(Doc, x1, y1);
paintElementsScheme(Doc);
movingRotated++;
movingRotated &= 3;
break;
}
default:;
}
}
void MouseActions::MReleaseMoveText(Schematic *Doc, QMouseEvent *Event)
{
if (Event->button() != Qt::LeftButton)
return;
QucsMain->MouseMoveAction = &MouseActions::MMoveMoveTextB;
QucsMain->MouseReleaseAction = 0;
Doc->releaseKeyboard();
((Component *) focusElement)->tx = MAx1 - ((Component *) focusElement)->cx;
((Component *) focusElement)->ty = MAy1 - ((Component *) focusElement)->cy;
Doc->viewport()->update();
Doc->setChanged(true, true);
}
void MouseActions::MReleaseZoomIn(Schematic *Doc, QMouseEvent *Event)
{
if (Event->button() != Qt::LeftButton)
return;
MAx1 = Event->pos().x();
MAy1 = Event->pos().y();
const QPoint click{Event->pos().x() , Event->pos().y()};
Doc->zoomAroundPoint(1.5, click, false);
QucsMain->MouseMoveAction = &MouseActions::MMoveZoomIn;
QucsMain->MouseReleaseAction = 0;
Doc->releaseKeyboard();
}
void MouseActions::editElement(Schematic *Doc, QMouseEvent *Event)
{
if (focusElement == 0)
return;
Graph *pg;
Component *c;
Diagram *dia;
DiagramDialog *ddia;
MarkerDialog *mdia;
int x1, y1, x2, y2;
QFileInfo Info(Doc->getDocName());
auto inModel = Doc->contentsToModel(Event->pos());
float fX = static_cast<float>(inModel.x());
float fY = static_cast<float>(inModel.y());
switch (focusElement->Type) {
case isComponent:
case isAnalogComponent:
case isDigitalComponent:
c = (Component *) focusElement;
if (c->Model == "GND")
return;
if (c->Model == "SpLib") {
SpiceLibCompDialog *sld = new SpiceLibCompDialog(c, Doc);
if (sld->exec() != -1) {
break;
}
} else if ((c->Model == ".CUSTOMSIM") || (c->Model == ".XYCESCR") || (c->Model == "INCLSCR")) {
CustomSimDialog *sd = new CustomSimDialog((SpiceCustomSim *) c, Doc);
if (sd->exec() != 1)
break;
} else if (c->Model == "SPICE") {
SpiceDialog *sd = new SpiceDialog(App, (SpiceFile *) c, Doc);
if (sd->exec() != 1)
break;
} else if (c->Model == ".Opt") {
OptimizeDialog *od = new OptimizeDialog((Optimize_Sim *) c, Doc);
if (od->exec() != 1)
break;
} else if (c->Model == "SPICEINIT") {
TextBoxDialog *od = new TextBoxDialog("Edit .spiceinit configuration", c, Doc);
if (od->exec() != 1)
break;
} else {
ComponentDialog *cd = new ComponentDialog(c, Doc);
if (cd->exec() != 1)
break;
Doc->a_Components->findRef(c);
Doc->a_Components->take();
Doc->setComponentNumber(c);
Doc->a_Components->append(c);
}
Doc->setChanged(true, true);
c->entireBounds(x1, y1, x2, y2);
Doc->enlargeView(x1, y1, x2, y2);
break;
case isDiagram:
dia = (Diagram *) focusElement;
if (dia->Name.at(0) == 'T'
&& Event->type() == QMouseEvent::MouseButtonDblClick) {
if (dia->Name == "Time") {
if (dia->cy < int(fY)) {
if (((TimingDiagram *) focusElement)->scroll(MAx1))
Doc->setChanged(true, true, 'm');
break;
}
} else {
if (dia->cx > int(fX)) {
if (((TabDiagram *) focusElement)->scroll(MAy1))
Doc->setChanged(true, true, 'm');
break;
}
}
}
ddia = new DiagramDialog(dia, Doc);
if (ddia->exec() != QDialog::Rejected)
Doc->setChanged(true, true);
dia->Bounding(x1, x2, y1, y2);
Doc->enlargeView(x1, x2, y1, y2);
break;
case isGraph:
pg = (Graph *) focusElement;
for (dia = Doc->a_Diagrams->last(); dia != 0; dia = Doc->a_Diagrams->prev())
if (dia->Graphs.indexOf(pg) >= 0)
break;
if (!dia)
break;
ddia = new DiagramDialog(dia, Doc, pg);
if (ddia->exec() != QDialog::Rejected)
Doc->setChanged(true, true);
break;
case isWire:
MPressLabel(Doc, Event, fX, fY);
break;
case isNodeLabel:
case isHWireLabel:
case isVWireLabel:
editLabel(Doc, (WireLabel *) focusElement);
Doc->highlightWireLabels();
break;
case isPainting:
if (((Painting *) focusElement)->Dialog(Doc))
Doc->setChanged(true, true);
break;
case isMarker:
mdia = new MarkerDialog((Marker *) focusElement, Doc);
if (mdia->exec() > 1)
Doc->setChanged(true, true);
break;
}
Doc->setFocus();
Doc->viewport()->update();
}
void MouseActions::MDoubleClickSelect(Schematic *Doc, QMouseEvent *Event)
{
Doc->releaseKeyboard();
QucsMain->editText->setHidden(true);
editElement(Doc, Event);
}
* @brief MouseActions::MDoubleClickWire2 Double click terminates wire insertion.
* @param Doc
* @param Event
*/
void MouseActions::MDoubleClickWire2(Schematic *Doc, QMouseEvent *Event)
{
auto inModel = Doc->contentsToModel(Event->pos());
MPressWire2(Doc, Event, static_cast<float>(inModel.x()), static_cast<float>(inModel.y()));
if (formerAction)
QucsMain->select->setChecked(true);
else {
QucsMain->MouseMoveAction = &MouseActions::MMoveWire1;
QucsMain->MousePressAction = &MouseActions::MPressWire1;
QucsMain->MouseDoubleClickAction = 0;
}
}
void MouseActions::MPressTune(Schematic *Doc, QMouseEvent *Event, float fX, float fY)
{
Q_UNUSED(Event);
int No = 0;
MAx1 = int(fX);
MAy1 = int(fY);
focusElement = Doc->selectElement(fX, fY, false, &No);
isMoveEqual = false;
if (focusElement)
qDebug() << "MPressTune: focusElement->Type"
<< QStringLiteral("0x%1").arg(focusElement->Type, 0, 16);
else
qDebug() << "MPressTune";
if (focusElement && App->TuningMode) {
Component *pc = nullptr;
Property *pp = nullptr;
switch (focusElement->Type) {
case isComponent:
case isAnalogComponent:
pc = (Component *) focusElement;
if (!pc)
return;
if (pc->Props.isEmpty())
return;
pp = pc->Props.at(0);
break;
case isComponentText:
focusElement->Type &= (~isComponentText) | isComponent;
pc = (Component *) focusElement;
pp = 0;
if (!pc)
return;
if (No > 0) {
No--;
pp = pc->Props.at(No);
}
if (!pp)
return;
break;
default:
return;
}
if (pc == nullptr || pp == nullptr)
return;
if (!App->tunerDia->containsProperty(pp)) {
if (isPropertyTunable(pc, pp)) {
tunerElement *tune = new tunerElement(App->tunerDia, pc, pp, No);
tune->schematicName = Doc->getDocName();
if (tune != NULL)
App->tunerDia->addTunerElement(tune);
} else {
QMessageBox::warning(nullptr,
"Property not correct",
"You selected a non-tunable property",
QMessageBox::Ok);
return;
}
}
}
}