My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
mouseactions.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  mouseactions.cpp
3  ------------------
4  begin : Thu Aug 28 2003
5  copyright : (C) 2003 by Michael Margraf
6  email : michael.margraf@alumni.tu-berlin.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qucs.h"
19 #include "main.h"
20 #include "node.h"
21 #include "schematic.h"
22 #include "mouseactions.h"
23 #include "components/component.h"
24 #include "components/spicedialog.h"
25 #include "components/spicefile.h"
28 #include "diagrams/diagramdialog.h"
29 #include "diagrams/markerdialog.h"
30 #include "diagrams/tabdiagram.h"
31 #include "diagrams/timingdiagram.h"
32 #include "dialogs/labeldialog.h"
33 
34 #include <qinputdialog.h>
35 #include <qclipboard.h>
36 #include <qapplication.h>
37 #include <qmessagebox.h>
38 #include <qpopupmenu.h>
39 #include <qevent.h>
40 #include <qaction.h>
41 #include <qtabwidget.h>
42 
43 #include <limits.h>
44 #include <stdlib.h>
45 
46 
47 #define DOC_X_POS(x) (int(float(x)/Doc->Scale) + Doc->ViewX1)
48 #define DOC_Y_POS(y) (int(float(y)/Doc->Scale) + Doc->ViewY1)
49 #define DOC_X_FPOS (float(Event->pos().x())/Doc->Scale + float(Doc->ViewX1))
50 #define DOC_Y_FPOS (float(Event->pos().y())/Doc->Scale + float(Doc->ViewY1))
51 
52 #define SCR_X_POS(x) int(float(x - Doc->ViewX1) * Doc->Scale)
53 #define SCR_Y_POS(y) int(float(y - Doc->ViewY1) * Doc->Scale)
54 
55 QAction *formerAction; // remember action before drag n'drop etc.
56 
57 
59 {
60  selElem = 0; // no component/diagram is selected
61  isMoveEqual = false; // mouse cursor move x and y the same way
62  focusElement = 0;
63 
64  // ...............................................................
65  // initialize menu appearing by right mouse button click on component
66  ComponentMenu = new QPopupMenu(QucsMain);
67  focusMEvent = new QMouseEvent(QEvent::MouseButtonPress, QPoint(0,0),
68  Qt::NoButton, Qt::NoButton);
69 }
70 
71 
73 {
74  delete ComponentMenu;
75  delete focusMEvent;
76 }
77 
78 // -----------------------------------------------------------
79 void MouseActions::setPainter(Schematic *Doc, QPainter *p)
80 {
81  // contents to viewport transformation
82  p->translate(-Doc->contentsX(), -Doc->contentsY());
83  p->scale(Doc->Scale, Doc->Scale);
84  p->translate(-Doc->ViewX1, -Doc->ViewY1);
85  p->setPen(Qt::DotLine);
86  p->setRasterOp(Qt::NotROP); // background should not be erased
87 }
88 
89 // -----------------------------------------------------------
91 {
92  QClipboard *cb = QApplication::clipboard(); // get system clipboard
93  QString s = cb->text(QClipboard::Clipboard);
94  QTextStream stream(&s, IO_ReadOnly);
95  movingElements.clear();
96  if(!Doc->paste(&stream, &movingElements)) return false;
97 
98  Element *pe;
99  int xmax, xmin, ymax, ymin;
100  xmin = ymin = INT_MAX;
101  xmax = ymax = INT_MIN;
102  // First, get the max and min coordinates of all selected elements.
103  for(pe = movingElements.first(); pe != 0; pe = movingElements.next()) {
104  if(pe->Type == isWire) {
105  if(pe->x1 < xmin) xmin = pe->x1;
106  if(pe->x2 > xmax) xmax = pe->x2;
107  if(pe->y1 < ymin) ymin = pe->y1;
108  if(pe->y2 > ymax) ymax = pe->y2;
109  }
110  else {
111  if(pe->cx < xmin) xmin = pe->cx;
112  if(pe->cx > xmax) xmax = pe->cx;
113  if(pe->cy < ymin) ymin = pe->cy;
114  if(pe->cy > ymax) ymax = pe->cy;
115  }
116  }
117 
118  xmin = -((xmax+xmin) >> 1); // calculate midpoint
119  ymin = -((ymax+ymin) >> 1);
120  Doc->setOnGrid(xmin, ymin);
121 
122  // moving with mouse cursor in the midpoint
123  for(pe = movingElements.first(); pe != 0; pe = movingElements.next())
124  if(pe->Type & isLabel) {
125  pe->cx += xmin; pe->x1 += xmin;
126  pe->cy += ymin; pe->y1 += ymin;
127  }
128  else
129  pe->setCenter(xmin, ymin, true);
130 
131  return true;
132 }
133 
134 // -----------------------------------------------------------
136 {
137  LabelDialog *Dia = new LabelDialog(pl, Doc);
138  int Result = Dia->exec();
139  if(Result == 0) return;
140 
141  QString Name = Dia->NodeName->text();
142  QString Value = Dia->InitValue->text();
143  delete Dia;
144 
145  if(Name.isEmpty() && Value.isEmpty()) { // if nothing entered, delete label
146  pl->pOwner->Label = 0; // delete name of wire
147  delete pl;
148  }
149  else {
150 /* Name.replace(' ', '_'); // label must not contain spaces
151  while(Name.at(0) == '_') Name.remove(0,1); // must not start with '_'
152  if(Name.isEmpty()) return;
153  if(Name == pl->Name) return;*/
154  if(Result == 1) return; // nothing changed
155 
156  int old_x2 = pl->x2;
157  pl->setName(Name); // set new name
158  pl->initValue = Value;
159  if(pl->cx > (pl->x1+(pl->x2>>1)))
160  pl->x1 -= pl->x2 - old_x2; // don't change position due to text width
161  }
162 
163  Doc->sizeOfAll(Doc->UsedX1, Doc->UsedY1, Doc->UsedX2, Doc->UsedY2);
164  Doc->viewport()->update();
165  drawn = false;
166  Doc->setChanged(true, true);
167 }
168 
169 // -----------------------------------------------------------
170 // Reinserts all elements (moved by the user) back into the schematic.
171 void MouseActions::endElementMoving(Schematic *Doc, QPtrList<Element> *movElements)
172 {
173  Element *pe;
174  for(pe = movElements->first(); pe!=0; pe = movElements->next()) {
175 // pe->isSelected = false; // deselect first (maybe afterwards pe == NULL)
176  switch(pe->Type) {
177  case isWire:
178  if(pe->x1 == pe->x2)
179  if(pe->y1 == pe->y2) {
180  // Delete wires with zero length, but preserve label.
181  if(((Wire*)pe)->Label) {
182  Doc->insertNodeLabel((WireLabel*)((Wire*)pe)->Label);
183  ((Wire*)pe)->Label = 0;
184  }
185  delete (Wire*)pe;
186  break;
187  }
188 
189  Doc->insertWire((Wire*)pe);
190  break;
191  case isDiagram:
192  Doc->Diagrams->append((Diagram*)pe);
193  break;
194  case isPainting:
195  Doc->Paintings->append((Painting*)pe);
196  break;
197  case isComponent:
198  case isAnalogComponent:
199  case isDigitalComponent:
200  Doc->insertRawComponent((Component*)pe, false);
201  break;
202  case isMovingLabel:
203  case isHMovingLabel:
204  case isVMovingLabel:
205  Doc->insertNodeLabel((WireLabel*)pe);
206  break;
207  case isMarker:
208  ((Marker*)pe)->pGraph->Markers.append((Marker*)pe);
209  break;
210  }
211  }
212 
213  movElements->clear();
214  if((MAx3 != 0) || (MAy3 != 0)) // moved or put at the same place ?
215  Doc->setChanged(true, true);
216 
217  // enlarge viewarea if components lie outside the view
218  Doc->sizeOfAll(Doc->UsedX1, Doc->UsedY1, Doc->UsedX2, Doc->UsedY2);
219  Doc->enlargeView(Doc->UsedX1, Doc->UsedY1, Doc->UsedX2, Doc->UsedY2);
220  Doc->viewport()->update();
221  drawn = false;
222 }
223 
224 // -----------------------------------------------------------
225 // Moves elements in "movElements" by x/y
226 void MouseActions::moveElements(QPtrList<Element> *movElements, int x, int y)
227 {
228  Wire *pw;
229  Element *pe;
230  for(pe = movElements->first(); pe != 0; pe = movElements->next()) {
231  if(pe->Type == isWire) {
232  pw = (Wire*)pe; // connected wires are not moved completely
233 
234  if(((unsigned long)pw->Port1) > 3) {
235  pw->x1 += x; pw->y1 += y;
236  if(pw->Label) { pw->Label->cx += x; pw->Label->cy += y; }
237  }
238  else { if(long(pw->Port1) & 1) { pw->x1 += x; }
239  if(long(pw->Port1) & 2) { pw->y1 += y; } }
240 
241  if(((unsigned long)pw->Port2) > 3) { pw->x2 += x; pw->y2 += y; }
242  else { if(long(pw->Port2) & 1) pw->x2 += x;
243  if(long(pw->Port2) & 2) pw->y2 += y; }
244 
245  if(pw->Label) { // root of node label must lie on wire
246  if(pw->Label->cx < pw->x1) pw->Label->cx = pw->x1;
247  if(pw->Label->cy < pw->y1) pw->Label->cy = pw->y1;
248  if(pw->Label->cx > pw->x2) pw->Label->cx = pw->x2;
249  if(pw->Label->cy > pw->y2) pw->Label->cy = pw->y2;
250  }
251 
252  }
253  else pe->setCenter(x, y, true);
254  }
255 }
256 
257 
258 // ***********************************************************************
259 // ********** **********
260 // ********** Functions for serving mouse moving **********
261 // ********** **********
262 // ***********************************************************************
263 void MouseActions::MMoveElement(Schematic *Doc, QMouseEvent *Event)
264 {
265  if(selElem == 0) return;
266 
267  int x = Event->pos().x();
268  int y = Event->pos().y();
269  int fx = DOC_X_POS(x);
270  int fy = DOC_Y_POS(y);
271  int gx = fx;
272  int gy = fy;
273  Doc->setOnGrid(gx, gy);
274 
275 
276  QPainter painter(Doc->viewport());
277  setPainter(Doc, &painter);
278 
279  if(selElem->Type == isPainting) {
280  QPainter paintUnscaled(Doc->viewport());
281  paintUnscaled.setRasterOp(Qt::NotROP); // not erasing background
282 
283  x -= Doc->contentsX();
284  y -= Doc->contentsY();
285  ((Painting*)selElem)->MouseMoving(&painter, fx, fy, gx, gy,
286  &paintUnscaled, x, y, drawn);
287  drawn = true;
288  return;
289  } // of "if(isPainting)"
290 
291 
292  // ********** it is a component or diagram
293  if(drawn) selElem->paintScheme(&painter); // erase old scheme
294  drawn = true;
295  selElem->setCenter(gx, gy);
296  selElem->paintScheme(&painter); // paint scheme at new position
297 }
298 
299 // -----------------------------------------------------------
300 void MouseActions::MMoveWire2(Schematic *Doc, QMouseEvent *Event)
301 {
302  QPainter painter(Doc->viewport());
303  setPainter(Doc, &painter);
304 
305  if(drawn)
306  if(MAx1 == 0) {
307  painter.drawLine(MAx3, MAy3, MAx3, MAy2); // erase old
308  painter.drawLine(MAx3, MAy2, MAx2, MAy2); // erase old
309  }
310  else {
311  painter.drawLine(MAx3, MAy3, MAx2, MAy3); // erase old
312  painter.drawLine(MAx2, MAy3, MAx2, MAy2); // erase old
313  }
314  else drawn = true;
315 
316  MAx2 = DOC_X_POS(Event->pos().x());
317  MAy2 = DOC_Y_POS(Event->pos().y());
318  Doc->setOnGrid(MAx2, MAy2);
319 
320  if(MAx1 == 0) {
321  painter.drawLine(MAx3, MAy3, MAx3, MAy2); // paint
322  painter.drawLine(MAx3, MAy2, MAx2, MAy2); // paint
323  }
324  else {
325  painter.drawLine(MAx3, MAy3, MAx2, MAy3); // paint
326  painter.drawLine(MAx2, MAy3, MAx2, MAy2); // paint
327  }
328 
330 }
331 
332 // -----------------------------------------------------------
333 void MouseActions::MMoveWire1(Schematic *Doc, QMouseEvent *Event)
334 {
335  QPainter painter(Doc->viewport());
336  painter.setPen(Qt::DotLine);
337  painter.setRasterOp(Qt::NotROP); // background should not be erased
338 
339  if(drawn) {
340  painter.drawLine(0, MAy3, MAx2, MAy3); // erase old
341  painter.drawLine(MAx3, 0, MAx3, MAy2);
342  }
343 
344  MAx3 = DOC_X_POS(Event->pos().x());
345  MAy3 = DOC_Y_POS(Event->pos().y());
346  Doc->setOnGrid(MAx3, MAy3);
347  MAx3 = SCR_X_POS(MAx3) - Doc->contentsX();
348  MAy3 = SCR_Y_POS(MAy3) - Doc->contentsY();
349 
350  MAx2 = Doc->visibleWidth();
351  MAy2 = Doc->visibleHeight();
352 
353  drawn = true;
354  painter.drawLine(0, MAy3, MAx2, MAy3); // paint
355  painter.drawLine(MAx3, 0, MAx3, MAy2);
356 }
357 
358 // -----------------------------------------------------------
359 // Paints a rectangle to select elements within it.
360 void MouseActions::MMoveSelect(Schematic *Doc, QMouseEvent *Event)
361 {
362  QPainter painter(Doc->viewport());
363  setPainter(Doc, &painter);
364 
365  if(drawn) painter.drawRect(MAx1, MAy1, MAx2, MAy2); // erase old rectangle
366  drawn = true;
367  MAx2 = DOC_X_POS(Event->pos().x()) - MAx1;
368  MAy2 = DOC_Y_POS(Event->pos().y()) - MAy1;
369  if(isMoveEqual) { // x and y size must be equal ?
370  if(abs(MAx2) > abs(MAy2)) {
371  if(MAx2<0) MAx2 = -abs(MAy2); else MAx2 = abs(MAy2);
372  }
373  else { if(MAy2<0) MAy2 = -abs(MAx2); else MAy2 = abs(MAx2); }
374  }
375  painter.drawRect(MAx1, MAy1, MAx2, MAy2); // paint new rectangle
376 }
377 
378 // -----------------------------------------------------------
379 void MouseActions::MMoveResizePainting(Schematic *Doc, QMouseEvent *Event)
380 {
381  QPainter painter(Doc->viewport());
382  setPainter(Doc, &painter);
383 
384  MAx1 = DOC_X_POS(Event->pos().x());
385  MAy1 = DOC_Y_POS(Event->pos().y());
386  Doc->setOnGrid(MAx1, MAy1);
387  ((Painting*)focusElement)->MouseResizeMoving(MAx1, MAy1, &painter);
388 }
389 
390 // -----------------------------------------------------------
391 // Moves components by keeping the mouse button pressed.
392 void MouseActions::MMoveMoving(Schematic *Doc, QMouseEvent *Event)
393 {
394  QPainter painter(Doc->viewport());
395  setPainter(Doc, &painter);
396 
397  MAx2 = DOC_X_POS(Event->pos().x());
398  MAy2 = DOC_Y_POS(Event->pos().y());
399 
400  Doc->setOnGrid(MAx2, MAy2);
401  MAx3 = MAx1 = MAx2 - MAx1;
402  MAy3 = MAy1 = MAy2 - MAy1;
403 
404  movingElements.clear();
406  Doc->viewport()->repaint();
407 
408  Wire *pw;
409  // Changes the position of all moving elements by dx/dy
410  for(Element *pe=movingElements.first(); pe!=0; pe=movingElements.next()) {
411  if(pe->Type == isWire) {
412  pw = (Wire*)pe; // connecting wires are not moved completely
413 
414  if(((unsigned long)pw->Port1) > 3) { pw->x1 += MAx1; pw->y1 += MAy1; }
415  else { if(long(pw->Port1) & 1) { pw->x1 += MAx1; }
416  if(long(pw->Port1) & 2) { pw->y1 += MAy1; } }
417 
418  if(((unsigned long)pw->Port2) > 3) { pw->x2 += MAx1; pw->y2 += MAy1; }
419  else { if(long(pw->Port2) & 1) pw->x2 += MAx1;
420  if(long(pw->Port2) & 2) pw->y2 += MAy1; }
421 
422  if(pw->Label) { // root of node label must lie on wire
423  if(pw->Label->cx < pw->x1) pw->Label->cx = pw->x1;
424  if(pw->Label->cy < pw->y1) pw->Label->cy = pw->y1;
425  if(pw->Label->cx > pw->x2) pw->Label->cx = pw->x2;
426  if(pw->Label->cy > pw->y2) pw->Label->cy = pw->y2;
427  }
428 
429  }
430  else pe->setCenter(MAx1, MAy1, true);
431 
432  pe->paintScheme(&painter);
433  }
434 
435  drawn = true;
436  MAx1 = MAx2;
437  MAy1 = MAy2;
440 
441 }
442 
443 // -----------------------------------------------------------
444 // Moves components by keeping the mouse button pressed.
445 void MouseActions::MMoveMoving2(Schematic *Doc, QMouseEvent *Event)
446 {
447  QPainter painter(Doc->viewport());
448  setPainter(Doc, &painter);
449 
450  MAx2 = DOC_X_POS(Event->pos().x());
451  MAy2 = DOC_Y_POS(Event->pos().y());
452 
453  Element *pe;
454  if(drawn) // erase old scheme
455  for(pe = movingElements.first(); pe != 0; pe = movingElements.next())
456  pe->paintScheme(&painter);
457 // if(pe->Type == isWire) if(((Wire*)pe)->Label)
458 // if(!((Wire*)pe)->Label->isSelected)
459 // ((Wire*)pe)->Label->paintScheme(&painter);
460 
461  drawn = true;
462  if((Event->state() & Qt::ControlButton) == 0)
463  Doc->setOnGrid(MAx2, MAy2); // use grid only if CTRL key not pressed
464  MAx1 = MAx2 - MAx1;
465  MAy1 = MAy2 - MAy1;
466  MAx3 += MAx1; MAy3 += MAy1; // keep track of the complete movement
467 
468  moveElements(&movingElements, MAx1, MAy1); // moves elements by MAx1/MAy1
469 
470  // paint afterwards to avoid conflict between wire and label painting
471  for(pe = movingElements.first(); pe != 0; pe = movingElements.next())
472  pe->paintScheme(&painter);
473 // if(pe->Type == isWire) if(((Wire*)pe)->Label)
474 // if(!((Wire*)pe)->Label->isSelected)
475 // ((Wire*)pe)->Label->paintScheme(&painter);
476 
477  MAx1 = MAx2;
478  MAy1 = MAy2;
479 }
480 
481 // -----------------------------------------------------------
482 // Moves components after paste from clipboard.
483 void MouseActions::MMovePaste(Schematic *Doc, QMouseEvent *Event)
484 {
485  QPainter painter(Doc->viewport());
486  setPainter(Doc, &painter);
487 
488  MAx1 = DOC_X_POS(Event->pos().x());
489  MAy1 = DOC_Y_POS(Event->pos().y());
490  moveElements(Doc,MAx1,MAy1);
491  paintElementsScheme(&painter);
492 
493  drawn = true;
496 }
497 
498 // -----------------------------------------------------------
499 // Moves scroll bar of diagram (e.g. tabular) according the mouse cursor.
500 void MouseActions::MMoveScrollBar(Schematic *Doc, QMouseEvent *Event)
501 {
503  int x = DOC_X_POS(Event->pos().x());
504  int y = DOC_Y_POS(Event->pos().y());
505 
506  if(d->scrollTo(MAx2, x - MAx1, y - MAy1)) {
507  Doc->setChanged(true, true, 'm'); // 'm' = only the first time
508 
509  QPainter p(Doc->viewport());
510  ViewPainter Painter;
511  Painter.init(&p, Doc->Scale, -Doc->ViewX1, -Doc->ViewY1,
512  Doc->contentsX(), Doc->contentsY());
513  Painter.fillRect(d->cx-d->x1, d->cy-d->y2, d->x2+d->x1, d->y2+d->y1,
515  d->paint(&Painter);
516  }
517 }
518 
519 // -----------------------------------------------------------
520 // Paints a cross under the mouse cursor to show the delete modus.
521 void MouseActions::MMoveDelete(Schematic *Doc, QMouseEvent *Event)
522 {
523  QPainter painter(Doc->viewport());
524  painter.setRasterOp(Qt::NotROP); // background should not be erased
525 
526  if(drawn) {
527  painter.drawLine(MAx3-15, MAy3-15, MAx3+15, MAy3+15); // erase old
528  painter.drawLine(MAx3-15, MAy3+15, MAx3+15, MAy3-15);
529  }
530  drawn = true;
531 
532  MAx3 = Event->pos().x() - Doc->contentsX();
533  MAy3 = Event->pos().y() - Doc->contentsY();
534 
535  painter.drawLine(MAx3-15, MAy3-15, MAx3+15, MAy3+15); // paint
536  painter.drawLine(MAx3-15, MAy3+15, MAx3+15, MAy3-15);
537 }
538 
539 // -----------------------------------------------------------
540 // Paints a label above the mouse cursor to show the set wire label modus.
541 void MouseActions::MMoveLabel(Schematic *Doc, QMouseEvent *Event)
542 {
543  QPainter painter(Doc->viewport());
544  painter.setRasterOp(Qt::NotROP); // background should not be erased
545 
546  if(drawn) {
547  painter.drawLine(MAx3, MAy3, MAx3+10, MAy3-10); // erase old
548  painter.drawLine(MAx3+10, MAy3-10, MAx3+20, MAy3-10);
549  painter.drawLine(MAx3+10, MAy3-10, MAx3+10, MAy3-17);
550 
551  painter.drawLine(MAx3+12, MAy3-12, MAx3+15, MAy3-23); // "A"
552  painter.drawLine(MAx3+14, MAy3-17, MAx3+17, MAy3-17);
553  painter.drawLine(MAx3+19, MAy3-12, MAx3+16, MAy3-23);
554  }
555  drawn = true;
556 
557  MAx3 = Event->pos().x() - Doc->contentsX();
558  MAy3 = Event->pos().y() - Doc->contentsY();
559 
560  painter.drawLine(MAx3, MAy3, MAx3+10, MAy3-10); // paint new
561  painter.drawLine(MAx3+10, MAy3-10, MAx3+20, MAy3-10);
562  painter.drawLine(MAx3+10, MAy3-10, MAx3+10, MAy3-17);
563 
564  painter.drawLine(MAx3+12, MAy3-12, MAx3+15, MAy3-23); // "A"
565  painter.drawLine(MAx3+14, MAy3-17, MAx3+17, MAy3-17);
566  painter.drawLine(MAx3+19, MAy3-12, MAx3+16, MAy3-23);
567 }
568 
569 // -----------------------------------------------------------
570 // Paints a triangle above the mouse cursor to show the set marker modus.
571 void MouseActions::MMoveMarker(Schematic *Doc, QMouseEvent *Event)
572 {
573  QPainter painter(Doc->viewport());
574  painter.setRasterOp(Qt::NotROP); // background should not be erased
575 
576  if(drawn) {
577  painter.drawLine(MAx3, MAy3-2, MAx3-8, MAy3-10); // erase old
578  painter.drawLine(MAx3+1, MAy3-3, MAx3+8, MAy3-10);
579  painter.drawLine(MAx3-7, MAy3-10, MAx3+7, MAy3-10);
580  }
581  drawn = true;
582 
583  MAx3 = Event->pos().x() - Doc->contentsX();
584  MAy3 = Event->pos().y() - Doc->contentsY();
585 
586  painter.drawLine(MAx3, MAy3-2, MAx3-8, MAy3-10); // paint new
587  painter.drawLine(MAx3+1, MAy3-3, MAx3+8, MAy3-10);
588  painter.drawLine(MAx3-7, MAy3-10, MAx3+7, MAy3-10);
589 }
590 
591 // -----------------------------------------------------------
592 // Paints rounded arrows above the mouse cursor to show the
593 // "mirror about y axis" modus.
594 void MouseActions::MMoveMirrorY(Schematic *Doc, QMouseEvent *Event)
595 {
596  QPainter painter(Doc->viewport());
597  painter.setRasterOp(Qt::NotROP); // background should not be erased
598 
599  if(drawn) {
600  painter.drawLine(MAx3-11, MAy3-4, MAx3-9, MAy3-9); // erase old
601  painter.drawLine(MAx3-11, MAy3-3, MAx3-6, MAy3-3);
602  painter.drawLine(MAx3+11, MAy3-4, MAx3+9, MAy3-9);
603  painter.drawLine(MAx3+11, MAy3-3, MAx3+6, MAy3-3);
604  painter.drawArc(MAx3-10, MAy3-8, 21, 10, 16*20, 16*140);
605  }
606  drawn = true;
607 
608  MAx3 = Event->pos().x() - Doc->contentsX();
609  MAy3 = Event->pos().y() - Doc->contentsY();
610 
611  painter.drawLine(MAx3-11, MAy3-4, MAx3-9, MAy3-9); // paint new
612  painter.drawLine(MAx3-11, MAy3-3, MAx3-6, MAy3-3);
613  painter.drawLine(MAx3+11, MAy3-4, MAx3+9, MAy3-9);
614  painter.drawLine(MAx3+11, MAy3-3, MAx3+6, MAy3-3);
615  painter.drawArc(MAx3-10, MAy3-8, 21, 10, 16*20, 16*140);
616 }
617 
618 // -----------------------------------------------------------
619 // Paints rounded arrows beside the mouse cursor to show the
620 // "mirror about x axis" modus.
621 void MouseActions::MMoveMirrorX(Schematic *Doc, QMouseEvent *Event)
622 {
623  QPainter painter(Doc->viewport());
624  painter.setRasterOp(Qt::NotROP); // background should not be erased
625 
626  if(drawn) {
627  painter.drawLine(MAx3-4, MAy3-11, MAx3-9, MAy3-9); // erase old
628  painter.drawLine(MAx3-3, MAy3-11, MAx3-3, MAy3-6);
629  painter.drawLine(MAx3-4, MAy3+11, MAx3-9, MAy3+9);
630  painter.drawLine(MAx3-3, MAy3+11, MAx3-3, MAy3+6);
631  painter.drawArc(MAx3-8, MAy3-10, 10, 21, 16*110, 16*140);
632  }
633  drawn = true;
634 
635  MAx3 = Event->pos().x() - Doc->contentsX();
636  MAy3 = Event->pos().y() - Doc->contentsY();
637 
638  painter.drawLine(MAx3-4, MAy3-11, MAx3-9, MAy3-9); // paint new
639  painter.drawLine(MAx3-3, MAy3-11, MAx3-3, MAy3-6);
640  painter.drawLine(MAx3-4, MAy3+11, MAx3-9, MAy3+9);
641  painter.drawLine(MAx3-3, MAy3+11, MAx3-3, MAy3+6);
642  painter.drawArc(MAx3-8, MAy3-10, 10, 21, 16*110, 16*140);
643 }
644 
645 // -----------------------------------------------------------
646 // Paints a rounded arrow above the mouse cursor to show the "rotate" modus.
647 void MouseActions::MMoveRotate(Schematic *Doc, QMouseEvent *Event)
648 {
649  QPainter painter(Doc->viewport());
650  painter.setRasterOp(Qt::NotROP); // background should not be erased
651 
652  if(drawn) {
653  painter.drawLine(MAx3-6, MAy3+8, MAx3-6, MAy3+1); // erase old
654  painter.drawLine(MAx3-7, MAy3+8, MAx3-12, MAy3+8);
655  painter.drawArc(MAx3-10, MAy3-10, 21, 21, -16*20, 16*240);
656  }
657  drawn = true;
658 
659  MAx3 = Event->pos().x() - Doc->contentsX();
660  MAy3 = Event->pos().y() - Doc->contentsY();
661 
662  painter.drawLine(MAx3-6, MAy3+8, MAx3-6, MAy3+1); // paint new
663  painter.drawLine(MAx3-7, MAy3+8, MAx3-12, MAy3+8);
664  painter.drawArc(MAx3-10, MAy3-10, 21, 21, -16*20, 16*240);
665 }
666 
667 // -----------------------------------------------------------
668 // Paints a rectangle beside the mouse cursor to show the "activate" modus.
669 void MouseActions::MMoveActivate(Schematic *Doc, QMouseEvent *Event)
670 {
671  QPainter painter(Doc->viewport());
672  painter.setRasterOp(Qt::NotROP); // background should not be erased
673 
674  if(drawn) {
675  painter.drawRect(MAx3, MAy3-9, 14, 10); // erase old
676  painter.drawLine(MAx3, MAy3-9, MAx3+13, MAy3);
677  painter.drawLine(MAx3, MAy3, MAx3+13, MAy3-9);
678  }
679  drawn = true;
680 
681  MAx3 = Event->pos().x() - Doc->contentsX();
682  MAy3 = Event->pos().y() - Doc->contentsY();
683 
684  painter.drawRect(MAx3, MAy3-9, 14, 10); // paint new
685  painter.drawLine(MAx3, MAy3-9, MAx3+13, MAy3);
686  painter.drawLine(MAx3, MAy3, MAx3+13, MAy3-9);
687 }
688 
689 // -----------------------------------------------------------
690 // Paints a grid beside the mouse cursor to show the "on grid" modus.
691 void MouseActions::MMoveOnGrid(Schematic *Doc, QMouseEvent *Event)
692 {
693  QPainter painter(Doc->viewport());
694  painter.setRasterOp(Qt::NotROP); // background should not be erased
695 
696  if(drawn) {
697  painter.drawLine(MAx3+10, MAy3+ 3, MAx3+25, MAy3+3); // erase old
698  painter.drawLine(MAx3+10, MAy3+ 7, MAx3+25, MAy3+7);
699  painter.drawLine(MAx3+10, MAy3+11, MAx3+25, MAy3+11);
700  painter.drawLine(MAx3+13, MAy3, MAx3+13, MAy3+15);
701  painter.drawLine(MAx3+17, MAy3, MAx3+17, MAy3+15);
702  painter.drawLine(MAx3+21, MAy3, MAx3+21, MAy3+15);
703  }
704  drawn = true;
705 
706  MAx3 = Event->pos().x() - Doc->contentsX();
707  MAy3 = Event->pos().y() - Doc->contentsY();
708 
709  painter.drawLine(MAx3+10, MAy3+ 3, MAx3+25, MAy3+3); // paint new
710  painter.drawLine(MAx3+10, MAy3+ 7, MAx3+25, MAy3+7);
711  painter.drawLine(MAx3+10, MAy3+11, MAx3+25, MAy3+11);
712  painter.drawLine(MAx3+13, MAy3, MAx3+13, MAy3+15);
713  painter.drawLine(MAx3+17, MAy3, MAx3+17, MAy3+15);
714  painter.drawLine(MAx3+21, MAy3, MAx3+21, MAy3+15);
715 }
716 
717 // -----------------------------------------------------------
718 // Paints symbol beside the mouse to show the "move component text" modus.
719 void MouseActions::MMoveMoveTextB(Schematic *Doc, QMouseEvent *Event)
720 {
721  QPainter painter(Doc->viewport());
722  painter.setRasterOp(Qt::NotROP); // background should not be erased
723 
724  if(drawn) {
725  painter.drawLine(MAx3+14, MAy3 , MAx3+16, MAy3); // erase old
726  painter.drawLine(MAx3+23, MAy3 , MAx3+25, MAy3);
727  painter.drawLine(MAx3+13, MAy3 , MAx3+13, MAy3+ 3);
728  painter.drawLine(MAx3+13, MAy3+ 7, MAx3+13, MAy3+10);
729  painter.drawLine(MAx3+14, MAy3+10, MAx3+16, MAy3+10);
730  painter.drawLine(MAx3+23, MAy3+10, MAx3+25, MAy3+10);
731  painter.drawLine(MAx3+26, MAy3 , MAx3+26, MAy3+ 3);
732  painter.drawLine(MAx3+26, MAy3+ 7, MAx3+26, MAy3+10);
733  }
734  drawn = true;
735 
736  MAx3 = Event->pos().x() - Doc->contentsX();
737  MAy3 = Event->pos().y() - Doc->contentsY();
738 
739  painter.drawLine(MAx3+14, MAy3 , MAx3+16, MAy3); // paint new
740  painter.drawLine(MAx3+23, MAy3 , MAx3+25, MAy3);
741  painter.drawLine(MAx3+13, MAy3 , MAx3+13, MAy3+ 3);
742  painter.drawLine(MAx3+13, MAy3+ 7, MAx3+13, MAy3+10);
743  painter.drawLine(MAx3+14, MAy3+10, MAx3+16, MAy3+10);
744  painter.drawLine(MAx3+23, MAy3+10, MAx3+25, MAy3+10);
745  painter.drawLine(MAx3+26, MAy3 , MAx3+26, MAy3+ 3);
746  painter.drawLine(MAx3+26, MAy3+ 7, MAx3+26, MAy3+10);
747 }
748 
749 // -----------------------------------------------------------
750 void MouseActions::MMoveMoveText(Schematic *Doc, QMouseEvent *Event)
751 {
752  QPainter painter(Doc->viewport());
753  setPainter(Doc, &painter);
754 
755  if(drawn)
756  painter.drawRect(MAx1, MAy1, MAx2, MAy2); // erase old
757  drawn = true;
758 
759  int newX = DOC_X_POS(Event->pos().x());
760  int newY = DOC_Y_POS(Event->pos().y());
761  MAx1 += newX - MAx3;
762  MAy1 += newY - MAy3;
763  MAx3 = newX;
764  MAy3 = newY;
765 
766  painter.drawRect(MAx1, MAy1, MAx2, MAy2); // paint new
767 }
768 
769 // -----------------------------------------------------------
770 // Paints symbol beside the mouse to show the "Zoom in" modus.
771 void MouseActions::MMoveZoomIn(Schematic *Doc, QMouseEvent *Event)
772 {
773  QPainter painter(Doc->viewport());
774  painter.setRasterOp(Qt::NotROP); // background should not be erased
775 
776  if(drawn) {
777  painter.drawLine(MAx3+14, MAy3 , MAx3+22, MAy3); // erase old
778  painter.drawLine(MAx3+18, MAy3-4 , MAx3+18, MAy3+4);
779  painter.drawEllipse(MAx3+12, MAy3-6, 13, 13);
780  }
781  drawn = true;
782 
783  MAx3 = Event->pos().x() - Doc->contentsX();
784  MAy3 = Event->pos().y() - Doc->contentsY();
785 
786  painter.drawLine(MAx3+14, MAy3 , MAx3+22, MAy3); // paint new
787  painter.drawLine(MAx3+18, MAy3-4 , MAx3+18, MAy3+4);
788  painter.drawEllipse(MAx3+12, MAy3-6, 13, 13);
789 }
790 
791 
792 // ************************************************************************
793 // ********** **********
794 // ********** Functions for serving mouse button clicking **********
795 // ********** **********
796 // ************************************************************************
797 
798 // Is called from several MousePress functions to show right button menu.
799 void MouseActions::rightPressMenu(Schematic *Doc, QMouseEvent *Event, float fX, float fY)
800 {
801  MAx1 = int(fX);
802  MAy1 = int(fY);
803  focusElement = Doc->selectElement(fX, fY, false);
804 
805  if(focusElement) // remove special function (4 least significant bits)
807 
808 
809  // define menu
810  ComponentMenu->clear();
811  while(true) {
812  if(focusElement) {
813  focusElement->isSelected = true;
814  ComponentMenu->insertItem(
815  QObject::tr("Edit Properties"), QucsMain, SLOT(slotEditElement()));
816 
817  if((focusElement->Type & isComponent) == 0) break;
818  }
819  else {
820  QucsMain->symEdit->addTo(ComponentMenu);
822  }
823  if(!QucsMain->moveText->isOn())
825  break;
826  }
827  while(true) {
828  if(focusElement)
829  if(focusElement->Type == isGraph) break;
830  if(!QucsMain->onGrid->isOn())
831  QucsMain->onGrid->addTo(ComponentMenu);
833  if(!QucsMain->editPaste->isOn())
835  break;
836  }
837  if(!QucsMain->editDelete->isOn())
839  if(focusElement) if(focusElement->Type == isMarker) {
840  ComponentMenu->insertSeparator();
841  QString s = QObject::tr("power matching");
842  if( ((Marker*)focusElement)->pGraph->Var == "Sopt" )
843  s = QObject::tr("noise matching");
844  ComponentMenu->insertItem(s, QucsMain, SLOT(slotPowerMatching()));
845  if( ((Marker*)focusElement)->pGraph->Var.left(2) == "S[" )
846  ComponentMenu->insertItem(QObject::tr("2-port matching"), QucsMain,
847  SLOT(slot2PortMatching()));
848  }
849  do {
850  if(focusElement) {
851  if(focusElement->Type == isDiagram) break;
852  if(focusElement->Type == isGraph) {
854  break;
855  }
856  }
857  ComponentMenu->insertSeparator();
859  if(!QucsMain->editActivate->isOn())
861  if(!QucsMain->editRotate->isOn())
863  if(!QucsMain->editMirror->isOn())
865  if(!QucsMain->editMirrorY->isOn())
867 
868  // right-click menu to go into hierarchy
869  if(focusElement) {
871  if(((Component*)focusElement)->Model == "Sub")
872  if(!QucsMain->intoH->isOn())
873  QucsMain->intoH->addTo(ComponentMenu);
874  }
875  // right-click menu to pop out of hierarchy
876  if(!focusElement)
877  if(!QucsMain->popH->isOn())
878  QucsMain->popH->addTo(ComponentMenu);
879  } while(false);
880 
881  *focusMEvent = *Event; // remember event for "edit component" action
882  ComponentMenu->popup(Event->globalPos());
883  Doc->viewport()->update();
884  drawn = false;
885 }
886 
887 // -----------------------------------------------------------
888 void MouseActions::MPressLabel(Schematic *Doc, QMouseEvent*, float fX, float fY)
889 {
890  int x = int(fX), y = int(fY);
891  Wire *pw = 0;
892  WireLabel *pl=0;
893  Node *pn = Doc->selectedNode(x, y);
894  if(!pn) {
895  pw = Doc->selectedWire(x, y);
896  if(!pw) return;
897  }
898 
899  QString Name, Value;
900  Element *pe=0;
901  // is wire line already labeled ?
902  if(pw) pe = Doc->getWireLabel(pw->Port1);
903  else pe = Doc->getWireLabel(pn);
904  if(pe) {
905  if(pe->Type & isComponent) {
906  QMessageBox::information(0, QObject::tr("Info"),
907  QObject::tr("The ground potential cannot be labeled!"));
908  return;
909  }
910  pl = ((Conductor*)pe)->Label;
911  }
912 
913  LabelDialog *Dia = new LabelDialog(pl, Doc);
914  if(Dia->exec() == 0) return;
915 
916  Name = Dia->NodeName->text();
917  Value = Dia->InitValue->text();
918  delete Dia;
919 
920  if(Name.isEmpty() && Value.isEmpty() ) { // if nothing entered, delete name
921  if(pe) {
922  if(((Conductor*)pe)->Label)
923  delete ((Conductor*)pe)->Label; // delete old name
924  ((Conductor*)pe)->Label = 0;
925  }
926  else {
927  if(pw) pw->setName("", ""); // delete name of wire
928  else pn->setName("", "");
929  }
930  }
931  else {
932 /* Name.replace(' ', '_'); // label must not contain spaces
933  while(Name.at(0) == '_') Name.remove(0,1); // must not start with '_'
934  if(Name.isEmpty()) return;
935 */
936  if(pe) {
937  if(((Conductor*)pe)->Label)
938  delete ((Conductor*)pe)->Label; // delete old name
939  ((Conductor*)pe)->Label = 0;
940  }
941 
942  int xl = x+30;
943  int yl = y-30;
944  Doc->setOnGrid(xl, yl);
945  // set new name
946  if(pw) pw->setName(Name, Value, x-pw->x1 + y-pw->y1, xl, yl);
947  else pn->setName(Name, Value, xl, yl);
948  }
949 
950  Doc->sizeOfAll(Doc->UsedX1, Doc->UsedY1, Doc->UsedX2, Doc->UsedY2);
951  Doc->viewport()->update();
952  drawn = false;
953  Doc->setChanged(true, true);
954 }
955 
956 // -----------------------------------------------------------
957 void MouseActions::MPressSelect(Schematic *Doc, QMouseEvent *Event, float fX, float fY)
958 {
959  bool Ctrl;
960  if(Event->state() & Qt::ControlButton) Ctrl = true;
961  else Ctrl = false;
962 
963  int No=0;
964  MAx1 = int(fX);
965  MAy1 = int(fY);
966  focusElement = Doc->selectElement(fX, fY, Ctrl, &No);
967  isMoveEqual = false; // moving not neccessarily square
968 
969 
970  if(focusElement)
971  switch(focusElement->Type) {
972  case isPaintingResize: // resize painting ?
978  Doc->grabKeyboard(); // no keyboard inputs during move actions
979  return;
980 
981  case isDiagramResize: // resize diagram ?
982  if(((Diagram*)focusElement)->Name.left(4) != "Rect")
983  if(((Diagram*)focusElement)->Name.at(0) != 'T')
984  if(((Diagram*)focusElement)->Name != "Curve")
985  isMoveEqual = true; // diagram must be square
986 
988  MAx1 = focusElement->cx;
989  MAx2 = focusElement->x2;
990  if(((Diagram*)focusElement)->State & 1) {
991  MAx1 += MAx2;
992  MAx2 *= -1;
993  }
994  MAy1 = focusElement->cy;
995  MAy2 = -focusElement->y2;
996  if(((Diagram*)focusElement)->State & 2) {
997  MAy1 += MAy2;
998  MAy2 *= -1;
999  }
1000 
1005  Doc->grabKeyboard(); // no keyboard inputs during move actions
1006  return;
1007 
1008  case isDiagramHScroll: // scroll in tabular ?
1009  MAy1 = MAx1;
1010 
1011  case isDiagramVScroll:
1013 
1014  No = ((TabDiagram*)focusElement)->scroll(MAy1);
1015 
1016  switch(No) {
1017  case 1:
1018  Doc->setChanged(true, true, 'm'); // 'm' = only the first time
1019  break;
1020  case 2: // move scroll bar with mouse cursor
1024  Doc->grabKeyboard(); // no keyboard inputs during move actions
1025 
1026  // Remember inital scroll bar position.
1027  MAx2 = int(((TabDiagram*)focusElement)->xAxis.limit_min);
1028  return;
1029  }
1030  Doc->viewport()->update();
1031  drawn = false;
1032  return;
1033 
1034  case isComponentText: // property text of component ?
1036 
1037  MAx3 = No;
1039  return;
1040 
1041  case isNode:
1042  if (QucsSettings.NodeWiring) {
1043  MAx1 = 0; // paint wire corner first up, then left/right
1044  MAx3 = focusElement->cx; // works even if node is not on grid
1045  MAy3 = focusElement->cy;
1048  QucsMain->MouseReleaseAction = 0; // if function is called from elsewhere
1050 
1051  formerAction = QucsMain->select; // to restore action afterwards
1053 
1054  QucsMain->select->blockSignals(true);
1055  QucsMain->select->setOn(false);
1056  QucsMain->select->blockSignals(false);
1057 
1058  QucsMain->insWire->blockSignals(true);
1059  QucsMain->insWire->setOn(true);
1060  QucsMain->insWire->blockSignals(false);
1061  return;
1062  }
1063  }
1064 
1065 
1066 
1069  Doc->grabKeyboard(); // no keyboard inputs during move actions
1070  Doc->viewport()->update();
1071  drawn = false;
1072 
1073  if(focusElement == 0) {
1074  MAx2 = 0; // if not clicking on an element => open a rectangle
1075  MAy2 = 0;
1078  }
1079  else { // element could be moved
1080  if(!Ctrl) {
1081  if(!focusElement->isSelected)// Don't move selected elements if clicked
1082  Doc->deselectElements(focusElement); // element was not selected.
1083  focusElement->isSelected = true;
1084  }
1085  Doc->setOnGrid(MAx1, MAy1);
1087  }
1088 }
1089 
1090 // -----------------------------------------------------------
1091 void MouseActions::MPressDelete(Schematic *Doc, QMouseEvent*, float fX, float fY)
1092 {
1093  Element *pe = Doc->selectElement(fX, fY, false);
1094  if(pe) {
1095  pe->isSelected = true;
1096  Doc->deleteElements();
1097 
1098  Doc->sizeOfAll(Doc->UsedX1, Doc->UsedY1, Doc->UsedX2, Doc->UsedY2);
1099  Doc->viewport()->update();
1100  drawn = false;
1101  }
1102 }
1103 
1104 // -----------------------------------------------------------
1105 void MouseActions::MPressActivate(Schematic *Doc, QMouseEvent*, float fX, float fY)
1106 {
1107  MAx1 = int(fX);
1108  MAy1 = int(fY);
1109  if(!Doc->activateSpecifiedComponent(MAx1, MAy1)) {
1110 // if(Event->button() != Qt::LeftButton) return;
1111  MAx2 = 0; // if not clicking on a component => open a rectangle
1112  MAy2 = 0;
1116  }
1117  Doc->viewport()->update();
1118  drawn = false;
1119 }
1120 
1121 // -----------------------------------------------------------
1122 void MouseActions::MPressMirrorX(Schematic *Doc, QMouseEvent*, float fX, float fY)
1123 {
1124  // no use in mirroring wires or diagrams
1125  Component *c = Doc->selectedComponent(int(fX), int(fY));
1126  if(c) {
1127  if(c->Ports.count() < 1) return; // only mirror components with ports
1128  c->mirrorX();
1129  Doc->setCompPorts(c);
1130  }
1131  else {
1132  Painting *p = Doc->selectedPainting(fX, fY);
1133  if(p == 0) return;
1134  p->mirrorX();
1135  }
1136 
1137  Doc->viewport()->update();
1138  drawn = false;
1139  Doc->setChanged(true, true);
1140 }
1141 
1142 // -----------------------------------------------------------
1143 void MouseActions::MPressMirrorY(Schematic *Doc, QMouseEvent*, float fX, float fY)
1144 {
1145  // no use in mirroring wires or diagrams
1146  Component *c = Doc->selectedComponent(int(fX), int(fY));
1147  if(c) {
1148  if(c->Ports.count() < 1) return; // only mirror components with ports
1149  c->mirrorY();
1150  Doc->setCompPorts(c);
1151  }
1152  else {
1153  Painting *p = Doc->selectedPainting(fX, fY);
1154  if(p == 0) return;
1155  p->mirrorY();
1156  }
1157 
1158  Doc->viewport()->update();
1159  drawn = false;
1160  Doc->setChanged(true, true);
1161 }
1162 
1163 // -----------------------------------------------------------
1164 void MouseActions::MPressRotate(Schematic *Doc, QMouseEvent*, float fX, float fY)
1165 {
1166  Element *e = Doc->selectElement(int(fX), int(fY), false);
1167  if(e == 0) return;
1168  e->Type &= isSpecialMask; // remove special functions
1169 
1170 
1171  WireLabel *pl;
1172  int x1, y1, x2, y2;
1173 // e->isSelected = false;
1174  switch(e->Type) {
1175  case isComponent:
1176  case isAnalogComponent:
1177  case isDigitalComponent:
1178  if(((Component*)e)->Ports.count() < 1)
1179  break; // do not rotate components without ports
1180  ((Component*)e)->rotate();
1181  Doc->setCompPorts((Component*)e);
1182  // enlarge viewarea if component lies outside the view
1183  ((Component*)e)->entireBounds(x1,y1,x2,y2, Doc->textCorr());
1184  Doc->enlargeView(x1, y1, x2, y2);
1185  break;
1186 
1187  case isWire:
1188  pl = ((Wire*)e)->Label;
1189  ((Wire*)e)->Label = 0; // prevent label to be deleted
1190  Doc->Wires->setAutoDelete(false);
1191  Doc->deleteWire((Wire*)e);
1192  ((Wire*)e)->Label = pl;
1193  ((Wire*)e)->rotate();
1194  Doc->setOnGrid(e->x1, e->y1);
1195  Doc->setOnGrid(e->x2, e->y2);
1196  if(pl) Doc->setOnGrid(pl->cx, pl->cy);
1197  Doc->insertWire((Wire*)e);
1198  Doc->Wires->setAutoDelete(true);
1199  if (Doc->Wires->containsRef ((Wire*)e))
1200  Doc->enlargeView(e->x1, e->y1, e->x2, e->y2);
1201  break;
1202 
1203  case isPainting:
1204  ((Painting*)e)->rotate();
1205  // enlarge viewarea if component lies outside the view
1206  ((Painting*)e)->Bounding(x1,y1,x2,y2);
1207  Doc->enlargeView(x1, y1, x2, y2);
1208  break;
1209 
1210  default:
1211  return;
1212  }
1213  Doc->viewport()->update();
1214  drawn = false;
1215  Doc->setChanged(true, true);
1216 }
1217 
1218 // -----------------------------------------------------------
1219 void MouseActions::MPressElement(Schematic *Doc, QMouseEvent *Event, float, float)
1220 {
1221  if(selElem == 0) return;
1222  QPainter painter(Doc->viewport());
1223  setPainter(Doc, &painter);
1224 
1225 
1226  int x1, y1, x2, y2, rot;
1227  if(selElem->Type & isComponent) {
1228  Component *Comp = (Component*)selElem;
1229  switch(Event->button()) {
1230  case Qt::LeftButton :
1231  // left mouse button inserts component into the schematic
1232  Comp->textSize(x1, y1);
1233  Doc->insertComponent(Comp);
1234  Comp->textSize(x2, y2);
1235  if(Comp->tx < Comp->x1) Comp->tx -= x2 - x1;
1236 
1237  // enlarge viewarea if component lies outside the view
1238  Comp->entireBounds(x1,y1,x2,y2, Doc->textCorr());
1239  Doc->enlargeView(x1, y1, x2, y2);
1240 
1241  drawn = false;
1242  Doc->viewport()->update();
1243  Doc->setChanged(true, true);
1244  rot = Comp->rotated;
1245  Comp = Comp->newOne(); // component is used, so create a new one
1246  rot -= Comp->rotated;
1247  rot &= 3;
1248  while(rot--) Comp->rotate(); // keep last rotation for single component
1249  break;
1250 
1251  case Qt::RightButton : // right mouse button rotates the component
1252  if(Comp->Ports.count() == 0)
1253  break; // do not rotate components without ports
1254  Comp->paintScheme(&painter); // erase old component scheme
1255  Comp->rotate();
1256  Comp->paintScheme(&painter); // paint new component scheme
1257  break;
1258 
1259  default: ; // avoids compiler warnings
1260  }
1261  selElem = Comp;
1262  return;
1263 
1264  } // of "if(isComponent)"
1265  else if(selElem->Type == isDiagram) {
1266  if(Event->button() != Qt::LeftButton) return;
1267 
1268  Diagram *Diag = (Diagram*)selElem;
1269  QFileInfo Info(Doc->DocName);
1270  // dialog is Qt::WDestructiveClose !!!
1271  DiagramDialog *dia =
1272  new DiagramDialog(Diag,
1273  Info.dirPath() + QDir::separator() + Doc->DataSet, Doc);
1274  if(dia->exec() == QDialog::Rejected) { // don't insert if dialog canceled
1275  Doc->viewport()->update();
1276  drawn = false;
1277  return;
1278  }
1279 
1280  Doc->Diagrams->append(Diag);
1281  Doc->enlargeView(Diag->cx, Diag->cy-Diag->y2, Diag->cx+Diag->x2, Diag->cy);
1282  Doc->setChanged(true, true); // document has been changed
1283 
1284  Doc->viewport()->repaint();
1285  Diag = Diag->newOne(); // the component is used, so create a new one
1286  Diag->paintScheme(&painter);
1287  selElem = Diag;
1288  return;
1289  } // of "if(isDiagram)"
1290 
1291 
1292  // *********** it is a painting !!!
1293  if(((Painting*)selElem)->MousePressing()) {
1294  Doc->Paintings->append((Painting*)selElem);
1295  ((Painting*)selElem)->Bounding(x1,y1,x2,y2);
1296  Doc->enlargeView(x1, y1, x2, y2);
1297  selElem = ((Painting*)selElem)->newOne();
1298 
1299  Doc->viewport()->update();
1300  Doc->setChanged(true, true);
1301 
1302  MMoveElement(Doc, Event); // needed before next mouse pressing
1303  drawn = false;
1304  }
1305 }
1306 
1307 // -----------------------------------------------------------
1308 // Is called if starting point of wire is pressed
1309 void MouseActions::MPressWire1(Schematic *Doc, QMouseEvent*, float fX, float fY)
1310 {
1311  QPainter painter(Doc->viewport());
1312  painter.setPen(Qt::DotLine);
1313  painter.setRasterOp(Qt::NotROP); // background should not be erased
1314 
1315  if(drawn) {
1316  painter.drawLine(0, MAy3, MAx2, MAy3); // erase old mouse cross
1317  painter.drawLine(MAx3, 0, MAx3, MAy2);
1318  }
1319  drawn = false;
1320 
1321  MAx1 = 0; // paint wire corner first up, then left/right
1322  MAx3 = int(fX);
1323  MAy3 = int(fY);
1324  Doc->setOnGrid(MAx3, MAy3);
1325 
1326  formerAction = 0; // keep wire action active after first wire finished
1329  // Double-click action is set in "MMoveWire2" to not initiate it
1330  // during "Wire1" actions.
1331 }
1332 
1333 // -----------------------------------------------------------
1334 // Is called if ending point of wire is pressed
1335 void MouseActions::MPressWire2(Schematic *Doc, QMouseEvent *Event, float fX, float fY)
1336 {
1337  QPainter painter(Doc->viewport());
1338  setPainter(Doc, &painter);
1339 
1340  int set1 = 0, set2 = 0;
1341  switch(Event->button()) {
1342  case Qt::LeftButton :
1343  if(MAx1 == 0) { // which wire direction first ?
1344  if(MAy2 != MAy3)
1345  set1 = Doc->insertWire(new Wire(MAx3, MAy3, MAx3, MAy2));
1346  if(MAx2 != MAx3) {
1347  set2 = set1;
1348  set1 = Doc->insertWire(new Wire(MAx3, MAy2, MAx2, MAy2));
1349  }
1350  }
1351  else {
1352  if(MAx2 != MAx3)
1353  set1 = Doc->insertWire(new Wire(MAx3, MAy3, MAx2, MAy3));
1354  if(MAy2 != MAy3) {
1355  set2 = set1;
1356  set1 = Doc->insertWire(new Wire(MAx2, MAy3, MAx2, MAy2));
1357  }
1358  }
1359 
1360  if(set1 & 2) {
1361  // if last port is connected, then...
1362  if(formerAction) {
1363  // ...restore old action
1364  QucsMain->select->setOn(true);
1365  }
1366  else {
1367  // ...start a new wire
1371  }
1372  }
1373 
1374  Doc->viewport()->update();
1375  drawn = false;
1376  if(set1 | set2) Doc->setChanged(true, true);
1377  MAx3 = MAx2;
1378  MAy3 = MAy2;
1379  break;
1380 
1381  case Qt::RightButton : // right mouse button changes the wire corner
1382  if(MAx1 == 0) {
1383  painter.drawLine(MAx3, MAy3, MAx3, MAy2); // erase old
1384  painter.drawLine(MAx3, MAy2, MAx2, MAy2); // erase old
1385  }
1386  else {
1387  painter.drawLine(MAx3, MAy3, MAx2, MAy3); // erase old
1388  painter.drawLine(MAx2, MAy3, MAx2, MAy2); // erase old
1389  }
1390 
1391  MAx2 = int(fX);
1392  MAy2 = int(fY);
1393  Doc->setOnGrid(MAx2, MAy2);
1394 
1395  MAx1 ^= 1; // change the painting direction of wire corner
1396  if(MAx1 == 0) {
1397  painter.drawLine(MAx3, MAy3, MAx3, MAy2); // paint
1398  painter.drawLine(MAx3, MAy2, MAx2, MAy2); // paint
1399  }
1400  else {
1401  painter.drawLine(MAx3, MAy3, MAx2, MAy3); // paint
1402  painter.drawLine(MAx2, MAy3, MAx2, MAy2); // paint
1403  }
1404  break;
1405 
1406  default: ; // avoids compiler warnings
1407  }
1408 }
1409 
1410 // -----------------------------------------------------------
1411 // Is called for setting a marker on a diagram's graph
1412 void MouseActions::MPressMarker(Schematic *Doc, QMouseEvent*, float fX, float fY)
1413 {
1414  MAx1 = int(fX);
1415  MAy1 = int(fY);
1416  Marker *pm = Doc->setMarker(MAx1, MAy1);
1417 
1418  if(pm) {
1419  int x0 = pm->Diag->cx;
1420  int y0 = pm->Diag->cy;
1421  Doc->enlargeView(x0+pm->x1, y0-pm->y1-pm->y2, x0+pm->x1+pm->x2, y0-pm->y1);
1422  }
1423  Doc->viewport()->update();
1424  drawn = false;
1425 }
1426 
1427 // -----------------------------------------------------------
1428 void MouseActions::MPressOnGrid(Schematic *Doc, QMouseEvent*, float fX, float fY)
1429 {
1430  Element *pe = Doc->selectElement(fX, fY, false);
1431  if(pe) {
1432  pe->Type &= isSpecialMask; // remove special functions (4 lowest bits)
1433 
1434  // onGrid is toggle action -> no other element can be selected
1435  pe->isSelected = true;
1436  Doc->elementsOnGrid();
1437 
1438  Doc->sizeOfAll(Doc->UsedX1, Doc->UsedY1, Doc->UsedX2, Doc->UsedY2);
1439  Doc->viewport()->update();
1440  drawn = false;
1441  }
1442 }
1443 
1444 // -----------------------------------------------------------
1445 void MouseActions::MPressMoveText(Schematic *Doc, QMouseEvent*, float fX, float fY)
1446 {
1447  MAx1 = int(fX);
1448  MAy1 = int(fY);
1450 
1451  if(focusElement) {
1452  MAx3 = MAx1;
1453  MAy3 = MAy1;
1454  MAx1 = ((Component*)focusElement)->cx + ((Component*)focusElement)->tx;
1455  MAy1 = ((Component*)focusElement)->cy + ((Component*)focusElement)->ty;
1456  Doc->viewport()->update();
1457  drawn = false;
1460  Doc->grabKeyboard(); // no keyboard inputs during move actions
1461  }
1462 }
1463 
1464 // -----------------------------------------------------------
1465 void MouseActions::MPressZoomIn(Schematic *Doc, QMouseEvent*, float fX, float fY)
1466 {
1467  MAx1 = int(fX);
1468  MAy1 = int(fY);
1469  MAx2 = 0; // rectangle size
1470  MAy2 = 0;
1471 
1474  Doc->grabKeyboard(); // no keyboard inputs during move actions
1475  Doc->viewport()->update();
1476  drawn = false;
1477 }
1478 
1479 
1480 // ***********************************************************************
1481 // ********** **********
1482 // ********** Functions for serving mouse button releasing **********
1483 // ********** **********
1484 // ***********************************************************************
1485 void MouseActions::MReleaseSelect(Schematic *Doc, QMouseEvent *Event)
1486 {
1487  bool ctrl;
1488  if(Event->state() & Qt::ControlButton) ctrl = true;
1489  else ctrl = false;
1490 
1491  if(!ctrl) Doc->deselectElements(focusElement);
1492 
1493  if(focusElement) if(Event->button() == Qt::LeftButton)
1494  if(focusElement->Type == isWire) {
1495  Doc->selectWireLine(focusElement, ((Wire*)focusElement)->Port1, ctrl);
1496  Doc->selectWireLine(focusElement, ((Wire*)focusElement)->Port2, ctrl);
1497  }
1498 
1499  Doc->releaseKeyboard(); // allow keyboard inputs again
1503  QucsMain->MouseMoveAction = 0; // no element moving
1504  Doc->viewport()->update();
1505  drawn = false;
1506 }
1507 
1508 // -----------------------------------------------------------
1509 // Is called after the rectangle for selection is released.
1510 void MouseActions::MReleaseSelect2(Schematic *Doc, QMouseEvent *Event)
1511 {
1512  if(Event->button() != Qt::LeftButton) return;
1513 
1514  bool Ctrl;
1515  if(Event->state() & Qt::ControlButton) Ctrl = true;
1516  else Ctrl = false;
1517 
1518  // selects all elements within the rectangle
1519  Doc->selectElements(MAx1, MAy1, MAx1+MAx2, MAy1+MAy2, Ctrl);
1520 
1521  Doc->releaseKeyboard(); // allow keyboard inputs again
1526  Doc->viewport()->update();
1527  drawn = false;
1528 }
1529 
1530 // -----------------------------------------------------------
1531 void MouseActions::MReleaseActivate(Schematic *Doc, QMouseEvent *Event)
1532 {
1533  if(Event->button() != Qt::LeftButton) return;
1534 
1535  // activates all components within the rectangle
1537 
1542  Doc->viewport()->update();
1543  drawn = false;
1544 }
1545 
1546 // -----------------------------------------------------------
1547 // Is called after moving selected elements.
1548 void MouseActions::MReleaseMoving(Schematic *Doc, QMouseEvent*)
1549 {
1550  // Allow all mouse buttons, because for others than the left one,
1551  // a menu has already created.
1553  Doc->releaseKeyboard(); // allow keyboard inputs again
1554 
1559 }
1560 
1561 // -----------------------------------------------------------
1562 void MouseActions::MReleaseResizeDiagram(Schematic *Doc, QMouseEvent *Event)
1563 {
1564  if(Event->button() != Qt::LeftButton) return;
1565 
1566  MAx3 = focusElement->cx;
1567  MAy3 = focusElement->cy;
1568  if(MAx2 < 0) { // resize diagram
1569  if(MAx2 > -10) MAx2 = -10; // not smaller than 10 pixels
1570  focusElement->x2 = -MAx2;
1571  focusElement->cx = MAx1+MAx2;
1572  }
1573  else {
1574  if(MAx2 < 10) MAx2 = 10;
1575  focusElement->x2 = MAx2;
1576  focusElement->cx = MAx1;
1577  }
1578  if(MAy2 < 0) {
1579  if(MAy2 > -10) MAy2 = -10;
1580  focusElement->y2 = -MAy2;
1581  focusElement->cy = MAy1;
1582  }
1583  else {
1584  if(MAy2 < 10) MAy2 = 10;
1585  focusElement->y2 = MAy2;
1586  focusElement->cy = MAy1+MAy2;
1587  }
1588  MAx3 -= focusElement->cx;
1589  MAy3 -= focusElement->cy;
1590 
1591  Diagram *pd = (Diagram*)focusElement;
1592  pd->updateGraphData();
1593  for(Graph *pg = pd->Graphs.first(); pg != 0; pg = pd->Graphs.next())
1594  for(Marker *pm = pg->Markers.first(); pm!=0; pm = pg->Markers.next()) {
1595  pm->x1 += MAx3; // correct changes due to move of diagram corner
1596  pm->y1 += MAy3;
1597  }
1598 
1599  int x1, x2, y1, y2;
1600  pd->Bounding(x1, x2, y1, y2);
1601  Doc->enlargeView(x1, x2, y1, y2);
1602 
1607  Doc->releaseKeyboard(); // allow keyboard inputs again
1608 
1609  Doc->viewport()->update();
1610  drawn = false;
1611  Doc->setChanged(true, true);
1612 }
1613 
1614 // -----------------------------------------------------------
1615 void MouseActions::MReleaseResizePainting(Schematic *Doc, QMouseEvent *Event)
1616 {
1617  if(Event->button() != Qt::LeftButton) return;
1618 
1623  Doc->releaseKeyboard(); // allow keyboard inputs again
1624 
1625  Doc->viewport()->update();
1626  drawn = false;
1627  Doc->setChanged(true, true);
1628 }
1629 
1630 // -----------------------------------------------------------
1632 {
1633  Element *pe;
1634  for(pe = movingElements.first(); pe != 0; pe = movingElements.next())
1635  pe->paintScheme(p);
1636 }
1637 
1638 // -----------------------------------------------------------
1639 void MouseActions::moveElements(Schematic *Doc, int& x1, int& y1)
1640 {
1641  Element *pe;
1642  Doc->setOnGrid(x1, y1);
1643 
1644  for(pe=movingElements.first(); pe!=0; pe=movingElements.next()) {
1645  if(pe->Type & isLabel) {
1646  pe->cx += x1; pe->x1 += x1;
1647  pe->cy += y1; pe->y1 += y1;
1648  }
1649  else
1650  pe->setCenter(x1, y1, true);
1651  }
1652 }
1653 
1654 // -----------------------------------------------------------
1655 void MouseActions::rotateElements(Schematic *Doc, int& x1, int& y1)
1656 {
1657  int x2, y2;
1658  Element *pe;
1659  Doc->setOnGrid(x1, y1);
1660 
1661  for(pe = movingElements.first(); pe != 0; pe = movingElements.next()) {
1662  switch(pe->Type) {
1663  case isComponent:
1664  case isAnalogComponent:
1665  case isDigitalComponent:
1666  ((Component*)pe)->rotate(); // rotate !before! rotating the center
1667  x2 = x1 - pe->cx;
1668  pe->setCenter(pe->cy - y1 + x1, x2 + y1);
1669  break;
1670  case isWire:
1671  x2 = pe->x1;
1672  pe->x1 = pe->y1 - y1 + x1;
1673  pe->y1 = x1 - x2 + y1;
1674  x2 = pe->x2;
1675  pe->x2 = pe->y2 - y1 + x1;
1676  pe->y2 = x1 - x2 + y1;
1677  break;
1678  case isPainting:
1679  ((Painting*)pe)->rotate(); // rotate !before! rotating the center
1680  ((Painting*)pe)->getCenter(x2, y2);
1681  pe->setCenter(y2 - y1 + x1, x1 - x2 + y1);
1682  break;
1683  default:
1684  x2 = x1 - pe->cx; // if diagram -> only rotate cx/cy
1685  pe->setCenter(pe->cy - y1 + x1, x2 + y1);
1686  break;
1687  }
1688  }
1689 }
1690 
1691 // -----------------------------------------------------------
1692 void MouseActions::MReleasePaste(Schematic *Doc, QMouseEvent *Event)
1693 {
1694  int x1, y1, x2, y2, rot;
1695  QFileInfo Info(Doc->DocName);
1696  QPainter painter(Doc->viewport());
1697 
1698  Element *pe;
1699  switch(Event->button()) {
1700  case Qt::LeftButton :
1701  // insert all moved elements into document
1702  for(pe = movingElements.first(); pe!=0; pe = movingElements.next()) {
1703  pe->isSelected = false;
1704  switch(pe->Type) {
1705  case isWire:
1706  if(pe->x1 == pe->x2) if(pe->y1 == pe->y2) break;
1707  Doc->insertWire((Wire*)pe);
1708  if (Doc->Wires->containsRef ((Wire*)pe))
1709  Doc->enlargeView(pe->x1, pe->y1, pe->x2, pe->y2);
1710  else pe = NULL;
1711  break;
1712  case isDiagram:
1713  Doc->Diagrams->append((Diagram*)pe);
1714  ((Diagram*)pe)->loadGraphData(Info.dirPath() + QDir::separator() +
1715  Doc->DataSet);
1716  Doc->enlargeView(pe->cx, pe->cy-pe->y2, pe->cx+pe->x2, pe->cy);
1717  break;
1718  case isPainting:
1719  Doc->Paintings->append((Painting*)pe);
1720  ((Painting*)pe)->Bounding(x1,y1,x2,y2);
1721  Doc->enlargeView(x1, y1, x2, y2);
1722  break;
1723  case isMovingLabel:
1724  pe->Type = isNodeLabel;
1725  Doc->placeNodeLabel((WireLabel*)pe);
1726  break;
1727  case isComponent:
1728  case isAnalogComponent:
1729  case isDigitalComponent:
1730  Doc->insertComponent((Component*)pe);
1731  ((Component*)pe)->entireBounds(x1,y1,x2,y2, Doc->textCorr());
1732  Doc->enlargeView(x1, y1, x2, y2);
1733  break;
1734  }
1735  }
1736 
1737  pasteElements(Doc);
1738  // keep rotation sticky for pasted elements
1739  rot = movingRotated;
1740  x1 = y1 = 0;
1741  while(rot--) rotateElements(Doc,x1,y1);
1742 
1747 
1748  drawn = false;
1749  Doc->viewport()->update();
1750  Doc->setChanged(true, true);
1751  break;
1752 
1753  // ............................................................
1754  case Qt::RightButton : // right button rotates the elements
1755  setPainter(Doc, &painter);
1756 
1757  if(drawn) // erase old scheme
1758  paintElementsScheme(&painter);
1759  drawn = true;
1760 
1761  x1 = DOC_X_POS(Event->pos().x());
1762  y1 = DOC_Y_POS(Event->pos().y());
1763  rotateElements(Doc,x1,y1);
1764  paintElementsScheme(&painter);
1765  // save rotation
1766  movingRotated++;
1767  movingRotated &= 3;
1768  break;
1769 
1770  default: ; // avoids compiler warnings
1771  }
1772 }
1773 
1774 // -----------------------------------------------------------
1775 void MouseActions::MReleaseMoveText(Schematic *Doc, QMouseEvent *Event)
1776 {
1777  if(Event->button() != Qt::LeftButton) return;
1778 
1781  Doc->releaseKeyboard(); // allow keyboard inputs again
1782 
1783  ((Component*)focusElement)->tx = MAx1 - ((Component*)focusElement)->cx;
1784  ((Component*)focusElement)->ty = MAy1 - ((Component*)focusElement)->cy;
1785  Doc->viewport()->update();
1786  drawn = false;
1787  Doc->setChanged(true, true);
1788 }
1789 
1790 // -----------------------------------------------------------
1791 void MouseActions::MReleaseZoomIn(Schematic *Doc, QMouseEvent *Event)
1792 {
1793  if(Event->button() != Qt::LeftButton) return;
1794 
1795  MAx1 = Event->pos().x();
1796  MAy1 = Event->pos().y();
1797  float DX = float(abs(MAx2));
1798  float DY = float(abs(MAy2));
1799  if((Doc->Scale * DX) < 6.0) {
1800  DX = 1.5; // a simple click zooms by constant factor
1801  Doc->zoom(DX);
1802 
1803  DX -= 1.0;
1804  MAx1 = int(DX * float(Event->pos().x()));
1805  MAy1 = int(DX * float(Event->pos().y()));
1806  }
1807  else {
1808  float xScale = float(Doc->visibleWidth()) / DX;
1809  float yScale = float(Doc->visibleHeight()) / DY;
1810  if(xScale > yScale) xScale = yScale;
1811  yScale = Doc->Scale;
1812  xScale /= yScale;
1813  Doc->zoom(xScale);
1814 
1815  if(MAx2 > 0) MAx1 -= int(float(MAx2)*yScale);
1816  if(MAy2 > 0) MAy1 -= int(float(MAy2)*yScale);
1817  MAx1 = int(float(MAx1) * xScale) - Doc->contentsX();
1818  MAy1 = int(float(MAy1) * xScale) - Doc->contentsY();
1819  }
1820  Doc->scrollBy(MAx1, MAy1);
1821 
1824  Doc->releaseKeyboard(); // allow keyboard inputs again
1825 }
1826 
1827 
1828 // ***********************************************************************
1829 // ********** **********
1830 // ********** Functions for mouse button double clicking **********
1831 // ********** **********
1832 // ***********************************************************************
1833 void MouseActions::editElement(Schematic *Doc, QMouseEvent *Event)
1834 {
1835  if(focusElement == 0) return;
1836 
1837  Graph *pg;
1838  Component *c;
1839  Diagram *dia;
1840  DiagramDialog *ddia;
1841  MarkerDialog *mdia;
1842  int x1, y1, x2, y2;
1843 
1844  QFileInfo Info(Doc->DocName);
1845  float fX = DOC_X_FPOS, fY = DOC_Y_FPOS;
1846 
1847  switch(focusElement->Type) {
1848  case isComponent:
1849  case isAnalogComponent:
1850  case isDigitalComponent:
1851  c = (Component*)focusElement;
1852  if(c->Model == "GND") return;
1853 
1854  if(c->Model == "SPICE") {
1855  SpiceDialog *sd = new SpiceDialog((SpiceFile*)c, Doc);
1856  if(sd->exec() != 1) break; // dialog is WDestructiveClose
1857  }
1858  else if(c->Model == ".Opt") {
1859  OptimizeDialog *od = new OptimizeDialog((Optimize_Sim*)c, Doc);
1860  if(od->exec() != 1) break; // dialog is WDestructiveClose
1861  }
1862  else {
1863  ComponentDialog * cd = new ComponentDialog(c, Doc);
1864  if(cd->exec() != 1) break; // dialog is WDestructiveClose
1865 
1866  Doc->Components->findRef(c);
1867  Doc->Components->take();
1868  Doc->setComponentNumber(c); // for ports/power sources
1869  Doc->Components->append(c);
1870  }
1871 
1872  Doc->setChanged(true, true);
1873  c->entireBounds(x1,y1,x2,y2, Doc->textCorr());
1874  Doc->enlargeView(x1,y1,x2,y2);
1875  break;
1876 
1877  case isDiagram :
1878  dia = (Diagram*)focusElement;
1879  if(dia->Name.at(0) == 'T') { // don't open dialog on scrollbar
1880  if(dia->Name == "Time") {
1881  if(dia->cy < int(fY)) {
1882  if(((TimingDiagram*)focusElement)->scroll(MAx1))
1883  Doc->setChanged(true, true, 'm'); // 'm' = only the first time
1884  break;
1885  }
1886  }
1887  else {
1888  if(dia->cx > int(fX)) {
1889  if(((TabDiagram*)focusElement)->scroll(MAy1))
1890  Doc->setChanged(true, true, 'm'); // 'm' = only the first time
1891  break;
1892  }
1893  }
1894  }
1895 
1896  ddia = new DiagramDialog(dia,
1897  Info.dirPath() + QDir::separator() + Doc->DataSet, Doc);
1898  if(ddia->exec() != QDialog::Rejected) // is WDestructiveClose
1899  Doc->setChanged(true, true);
1900 
1901  dia->Bounding(x1, x2, y1, y2);
1902  Doc->enlargeView(x1, x2, y1, y2);
1903  break;
1904 
1905  case isGraph :
1906  pg = (Graph*)focusElement;
1907  // searching diagram for this graph
1908  for(dia = Doc->Diagrams->last(); dia != 0; dia = Doc->Diagrams->prev())
1909  if(dia->Graphs.findRef(pg) >= 0)
1910  break;
1911  if(!dia) break;
1912 
1913 
1914  ddia = new DiagramDialog(dia,
1915  Info.dirPath() + QDir::separator() + Doc->DataSet, Doc, pg);
1916  if(ddia->exec() != QDialog::Rejected) // is WDestructiveClose
1917  Doc->setChanged(true, true);
1918  break;
1919 
1920  case isWire:
1921  MPressLabel(Doc, Event, fX, fY);
1922  break;
1923 
1924  case isNodeLabel:
1925  case isHWireLabel:
1926  case isVWireLabel:
1928  break;
1929 
1930  case isPainting:
1931  if( ((Painting*)focusElement)->Dialog() )
1932  Doc->setChanged(true, true);
1933  break;
1934 
1935  case isMarker:
1936  mdia = new MarkerDialog((Marker*)focusElement, Doc);
1937  if(mdia->exec() > 1)
1938  Doc->setChanged(true, true);
1939  break;
1940  }
1941 
1942  // Very strange: Now an open VHDL editor gets all the keyboard input !?!
1943  // I don't know why it only happens here, nor am I sure whether it only
1944  // happens here. Anyway, I hope the best and give the focus back to the
1945  // current document.
1946  Doc->setFocus();
1947 
1948  Doc->viewport()->update();
1949  drawn = false;
1950 }
1951 
1952 // -----------------------------------------------------------
1953 void MouseActions::MDoubleClickSelect(Schematic *Doc, QMouseEvent *Event)
1954 {
1955  Doc->releaseKeyboard(); // allow keyboard inputs again
1956  QucsMain->editText->setHidden(true);
1957  editElement(Doc, Event);
1958 }
1959 
1960 // -----------------------------------------------------------
1961 void MouseActions::MDoubleClickWire2(Schematic *Doc, QMouseEvent *Event)
1962 {
1963  MPressWire2(Doc, Event, DOC_X_FPOS, DOC_Y_FPOS);
1964 
1965  if(formerAction)
1966  QucsMain->select->setOn(true); // restore old action
1967  else {
1971  }
1972 }