My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
qucs_actions.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qucsactions.cpp
3  -----------------
4  begin : Sat May 1 2004
5  copyright : (C) 2004 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 <stdlib.h>
19 #include <limits.h>
20 
21 #include <qaction.h>
22 #include <qprocess.h>
23 #include <qlineedit.h>
24 #include <qstatusbar.h>
25 #include <qtabwidget.h>
26 #include <qmessagebox.h>
27 #include <qfiledialog.h>
28 #include <qregexp.h>
29 #include <qvalidator.h>
30 
31 #include "main.h"
32 #include "qucs.h"
33 #include "schematic.h"
34 #include "textdoc.h"
35 #include "mouseactions.h"
36 #include "components/ground.h"
37 #include "components/subcirport.h"
38 #include "components/equation.h"
39 #include "dialogs/matchdialog.h"
40 #include "dialogs/changedialog.h"
41 #include "dialogs/searchdialog.h"
42 #include "dialogs/librarydialog.h"
43 #include "dialogs/importdialog.h"
44 #include "dialogs/packagedialog.h"
45 
46 // for editing component name on schematic
47 QRegExp Expr_CompProp;
48 QRegExpValidator Val_CompProp(Expr_CompProp, 0);
49 
50 
51 // -----------------------------------------------------------------------
52 // This function is called from all toggle actions.
53 bool QucsApp::performToggleAction(bool on, QAction *Action,
54  pToggleFunc Function, pMouseFunc MouseMove, pMouseFunc2 MousePress)
55 {
56  editText->setHidden(true); // disable text edit of component property
57 
58  if(!on) {
59  MouseMoveAction = 0;
60  MousePressAction = 0;
63  activeAction = 0; // no action active
64  return false;
65  }
66 
67  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
68  do {
69  if(Function) if((Doc->*Function)()) {
70  Action->blockSignals(true);
71  Action->setOn(false); // release toolbar button
72  Action->blockSignals(false);
73  Doc->viewport()->update();
74  break;
75  }
76 
77  if(activeAction) {
78  activeAction->blockSignals(true); // do not call toggle slot
79  activeAction->setOn(false); // set last toolbar button off
80  activeAction->blockSignals(false);
81  }
82  activeAction = Action;
83 
84  MouseMoveAction = MouseMove;
85  MousePressAction = MousePress;
88 
89  } while(false); // to perform "break"
90 
91  Doc->viewport()->update();
92  view->drawn = false;
93  return true;
94 }
95 
96 // -----------------------------------------------------------------------
97 // Is called, when "set on grid" action is activated.
98 void QucsApp::slotOnGrid(bool on)
99 {
100  performToggleAction(on, onGrid, &Schematic::elementsOnGrid,
102 }
103 
104 // -----------------------------------------------------------------------
105 // Is called when the rotate toolbar button is pressed.
107 {
108  performToggleAction(on, editRotate, &Schematic::rotateElements,
110 }
111 
112 // -----------------------------------------------------------------------
113 // Is called when the mirror toolbar button is pressed.
115 {
116  performToggleAction(on, editMirror, &Schematic::mirrorXComponents,
118 }
119 
120 // -----------------------------------------------------------------------
121 // Is called when the mirror toolbar button is pressed.
123 {
124  performToggleAction(on, editMirrorY, &Schematic::mirrorYComponents,
126 }
127 
128 // -----------------------------------------------------------------------
129 // Is called when the activate/deactivate toolbar button is pressed.
131 {
132  TextDoc * Doc = (TextDoc *) DocumentTab->currentPage ();
133  if (isTextDocument (Doc)) {
134  Doc->clearParagraphBackground (Doc->tmpPosX);
135  Doc->commentSelected ();
136 
137  editActivate->blockSignals (true);
138  editActivate->setOn (false); // release toolbar button
139  editActivate->blockSignals (false);
140  }
141  else
142  performToggleAction (on, editActivate,
145 }
146 
147 // ------------------------------------------------------------------------
148 // Is called if "Delete"-Button is pressed.
150 {
151  TextDoc *Doc = (TextDoc*)DocumentTab->currentPage();
152  if(Doc->inherits("QTextEdit")) {
153  Doc->viewport()->setFocus();
154  Doc->del();
155 
156  editDelete->blockSignals(true);
157  editDelete->setOn(false); // release toolbar button
158  editDelete->blockSignals(false);
159  }
160  else
161  performToggleAction(on, editDelete, &Schematic::deleteElements,
163 }
164 
165 // -----------------------------------------------------------------------
166 // Is called if "Wire"-Button is pressed.
167 void QucsApp::slotSetWire(bool on)
168 {
169  performToggleAction(on, insWire, 0,
171 }
172 
173 // -----------------------------------------------------------------------
175 {
176  performToggleAction(on, insLabel, 0,
178 }
179 
180 // -----------------------------------------------------------------------
182 {
183  performToggleAction(on, setMarker, 0,
185 }
186 
187 // -----------------------------------------------------------------------
188 // Is called, when "move component text" action is activated.
190 {
191  performToggleAction(on, moveText, 0,
193 }
194 
195 // -----------------------------------------------------------------------
196 // Is called, when "Zoom in" action is activated.
197 void QucsApp::slotZoomIn(bool on)
198 {
199  TextDoc *Doc = (TextDoc*)DocumentTab->currentPage();
200  if(Doc->inherits("QTextEdit")) {
201  Doc->zoomBy(2.0f);
202  magPlus->blockSignals(true);
203  magPlus->setOn(false);
204  magPlus->blockSignals(false);
205  }
206  else
207  performToggleAction(on, magPlus, 0,
209 }
210 
211 // -----------------------------------------------------------------------
212 // Is called when the select toolbar button is pressed.
213 void QucsApp::slotSelect(bool on)
214 {
215  QWidget *w = DocumentTab->currentPage();
216  if(w->inherits("QTextEdit")) {
217  ((TextDoc*)w)->viewport()->setFocus();
218 
219  select->blockSignals(true);
220  select->setOn(true);
221  select->blockSignals(false);
222  return;
223  }
224 
225  // goto to insertWire mode if ESC pressed during wiring
226  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
230  Doc->viewport()->update();
231  view->drawn = false;
232 
233  select->blockSignals(true);
234  select->setOn(false);
235  select->blockSignals(false);
236  return;
237  }
238 
239  if(performToggleAction(on, select, 0, 0, &MouseActions::MPressSelect)) {
242  }
243 }
244 
245 // -----------------------------------------------------------------------
247 {
248  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
249  if(Doc->inherits("QTextEdit")) {
250  ((TextDoc*)Doc)->viewport()->setFocus();
251  ((TextDoc*)Doc)->paste();
252 
253  editPaste->blockSignals(true);
254  editPaste->setOn(false); // release toolbar button
255  editPaste->blockSignals(false);
256  return;
257  }
258 
259  editText->setHidden(true); // disable text edit of component property
260 
261  if(!on) {
262  MouseMoveAction = 0;
263  MousePressAction = 0;
264  MouseReleaseAction = 0;
266  activeAction = 0; // no action active
267  if(view->drawn) Doc->viewport()->update();
268  return;
269  }
270 
271  if(!view->pasteElements(Doc)) {
272  editPaste->blockSignals(true); // do not call toggle slot
273  editPaste->setOn(false); // set toolbar button off
274  editPaste->blockSignals(false);
275  return; // if clipboard empty
276  }
277 
278  if(activeAction) {
279  activeAction->blockSignals(true); // do not call toggle slot
280  activeAction->setOn(false); // set last toolbar button off
281  activeAction->blockSignals(false);
282  }
284 
285  view->drawn = false;
287  view->movingRotated = 0;
288  MousePressAction = 0;
289  MouseReleaseAction = 0;
291 }
292 
293 // -----------------------------------------------------------------------
295 {
296  TextDoc * Doc = (TextDoc *) DocumentTab->currentPage ();
297  Doc->viewport()->setFocus ();
298  Doc->clearParagraphBackground (Doc->tmpPosX);
299  Doc->insertSkeleton ();
300 
301  int x, y;
302  Doc->getCursorPosition (&x, &y);
303  Doc->slotCursorPosChanged (x, y);
304 }
305 
306 // -----------------------------------------------------------------------
307 // Is called when the mouse is clicked upon the equation toolbar button.
309 {
310  editText->setHidden(true); // disable text edit of component property
311  MouseReleaseAction = 0;
313 
314  if(!on) {
315  MouseMoveAction = 0;
316  MousePressAction = 0;
317  activeAction = 0; // no action active
318  return;
319  }
320  if(activeAction) {
321  activeAction->blockSignals(true); // do not call toggle slot
322  activeAction->setOn(false); // set last toolbar button off
323  activeAction->blockSignals(false);
324  }
326 
327  if(view->selElem)
328  delete view->selElem; // delete previously selected component
329 
330  view->selElem = new Equation();
331 
332  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
333  if(view->drawn) Doc->viewport()->update();
334  view->drawn = false;
337 }
338 
339 // -----------------------------------------------------------------------
340 // Is called when the mouse is clicked upon the ground toolbar button.
342 {
343  editText->setHidden(true); // disable text edit of component property
344  MouseReleaseAction = 0;
346 
347  if(!on) {
348  MouseMoveAction = 0;
349  MousePressAction = 0;
350  activeAction = 0; // no action active
351  return;
352  }
353  if(activeAction) {
354  activeAction->blockSignals(true); // do not call toggle slot
355  activeAction->setOn(false); // set last toolbar button off
356  activeAction->blockSignals(false);
357  }
359 
360  if(view->selElem)
361  delete view->selElem; // delete previously selected component
362 
363  view->selElem = new Ground();
364 
365  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
366  if(view->drawn) Doc->viewport()->update();
367  view->drawn = false;
370 }
371 
372 // -----------------------------------------------------------------------
373 // Is called when the mouse is clicked upon the port toolbar button.
375 {
376  editText->setHidden(true); // disable text edit of component property
377  MouseReleaseAction = 0;
379 
380  if(!on) {
381  MouseMoveAction = 0;
382  MousePressAction = 0;
383  activeAction = 0; // no action active
384  return;
385  }
386  if(activeAction) {
387  activeAction->blockSignals(true); // do not call toggle slot
388  activeAction->setOn(false); // set last toolbar button off
389  activeAction->blockSignals(false);
390  }
392 
393  if(view->selElem)
394  delete view->selElem; // delete previously selected component
395 
396  view->selElem = new SubCirPort();
397 
398  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
399  if(view->drawn) Doc->viewport()->update();
400  view->drawn = false;
403 }
404 
405 // --------------------------------------------------------------
406 // Is called, when "Undo"-Button is pressed.
408 {
409  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
410  if(Doc->inherits("QTextEdit")) {
411  ((TextDoc*)Doc)->viewport()->setFocus();
412  ((TextDoc*)Doc)->undo();
413  return;
414  }
415 
416  editText->setHidden(true); // disable text edit of component property
417 
418  Doc->undo();
419  Doc->viewport()->update();
420  view->drawn = false;
421 }
422 
423 // --------------------------------------------------------------
424 // Is called, when "Undo"-Button is pressed.
426 {
427  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
428  if(Doc->inherits("QTextEdit")) {
429  ((TextDoc*)Doc)->viewport()->setFocus();
430  ((TextDoc*)Doc)->redo();
431  return;
432  }
433 
434  editText->setHidden(true); // disable text edit of component property
435 
436  Doc->redo();
437  Doc->viewport()->update();
438  view->drawn = false;
439 }
440 
441 // --------------------------------------------------------------
442 // Is called, when "Align top" action is activated.
444 {
445  editText->setHidden(true); // disable text edit of component property
446 
447  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
448  if(!Doc->aligning(0))
449  QMessageBox::information(this, tr("Info"),
450  tr("At least two elements must be selected !"));
451  Doc->viewport()->update();
452  view->drawn = false;
453 }
454 
455 // --------------------------------------------------------------
456 // Is called, when "Align bottom" action is activated.
458 {
459  editText->setHidden(true); // disable text edit of component property
460 
461  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
462  if(!Doc->aligning(1))
463  QMessageBox::information(this, tr("Info"),
464  tr("At least two elements must be selected !"));
465  Doc->viewport()->update();
466  view->drawn = false;
467 }
468 
469 // --------------------------------------------------------------
470 // Is called, when "Align left" action is activated.
472 {
473  editText->setHidden(true); // disable text edit of component property
474 
475  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
476  if(!Doc->aligning(2))
477  QMessageBox::information(this, tr("Info"),
478  tr("At least two elements must be selected !"));
479  Doc->viewport()->update();
480  view->drawn = false;
481 }
482 
483 // --------------------------------------------------------------
484 // Is called, when "Align right" action is activated.
486 {
487  editText->setHidden(true); // disable text edit of component property
488 
489  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
490  if(!Doc->aligning(3))
491  QMessageBox::information(this, tr("Info"),
492  tr("At least two elements must be selected !"));
493  Doc->viewport()->update();
494  view->drawn = false;
495 }
496 
497 // --------------------------------------------------------------
498 // Is called, when "Distribute horizontally" action is activated.
500 {
501  editText->setHidden(true); // disable text edit of component property
502 
503  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
504  Doc->distributeHorizontal();
505  Doc->viewport()->update();
506  view->drawn = false;
507 }
508 
509 // --------------------------------------------------------------
510 // Is called, when "Distribute vertically" action is activated.
512 {
513  editText->setHidden(true); // disable text edit of component property
514 
515  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
516  Doc->distributeVertical();
517  Doc->viewport()->update();
518  view->drawn = false;
519 }
520 
521 // --------------------------------------------------------------
522 // Is called, when "Center horizontally" action is activated.
524 {
525  editText->setHidden(true); // disable text edit of component property
526 
527  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
528  if(!Doc->aligning(4))
529  QMessageBox::information(this, tr("Info"),
530  tr("At least two elements must be selected !"));
531  Doc->viewport()->update();
532  view->drawn = false;
533 }
534 
535 // --------------------------------------------------------------
536 // Is called, when "Center vertically" action is activated.
538 {
539  editText->setHidden(true); // disable text edit of component property
540 
541  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
542  if(!Doc->aligning(5))
543  QMessageBox::information(this, tr("Info"),
544  tr("At least two elements must be selected !"));
545  Doc->viewport()->update();
546  view->drawn = false;
547 }
548 
549 // ---------------------------------------------------------------------
550 // Is called when the "select all" action is activated.
552 {
553  editText->setHidden(true); // disable text edit of component property
554 
555  QWidget *Doc = DocumentTab->currentPage();
556  if(Doc->inherits("QTextEdit")) {
557  ((TextDoc*)Doc)->viewport()->setFocus();
558  ((TextDoc*)Doc)->selectAll(true);
559  }
560  else {
561  ((Schematic*)Doc)->selectElements(INT_MIN, INT_MIN, INT_MAX, INT_MAX, true);
562  ((Schematic*)Doc)->viewport()->update();
563  view->drawn = false;
564  }
565 }
566 
567 // ---------------------------------------------------------------------
568 // Is called when the "select markers" action is activated.
570 {
571  editText->setHidden(true); // disable text edit of component property
572 
573  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
574  Doc->selectMarkers();
575  Doc->viewport()->update();
576  view->drawn = false;
577 }
578 
579 // ------------------------------------------------------------------------
580 // Is called by slotShowLastMsg(), by slotShowLastNetlist() and from the
581 // component edit dialog.
582 void QucsApp::editFile(const QString& File)
583 {
584  QStringList com;
585  com << QucsSettings.Editor;
586  if (!File.isEmpty()) com << File;
587  QProcess *QucsEditor = new QProcess(com);
588  QucsEditor->setCommunication(0);
589  if(!QucsEditor->start()) {
590  QMessageBox::critical(this, tr("Error"), tr("Cannot start text editor!"));
591  delete QucsEditor;
592  return;
593  }
594 
595  // to kill it before qucs ends
596  connect(this, SIGNAL(signalKillEmAll()), QucsEditor, SLOT(kill()));
597 }
598 
599 // ------------------------------------------------------------------------
600 // Is called to show the output messages of the last simulation.
602 {
603  editFile(QucsHomeDir.filePath("log.txt"));
604 }
605 
606 // ------------------------------------------------------------------------
607 // Is called to show the netlist of the last simulation.
609 {
610  editFile(QucsHomeDir.filePath("netlist.txt"));
611 }
612 
613 // ------------------------------------------------------------------------
614 // Is called to start the text editor.
616 {
617  editFile(QString(""));
618 }
619 
620 // ------------------------------------------------------------------------
621 // Is called to start the filter synthesis program.
623 {
624  QProcess *QucsFilter =
625  new QProcess(QString(QucsSettings.BinDir + "qucsfilter"));
626  if(!QucsFilter->start()) {
627  QMessageBox::critical(this, tr("Error"),
628  tr("Cannot start filter synthesis program!"));
629  delete QucsFilter;
630  return;
631  }
632 
633  // to kill it before qucs ends
634  connect(this, SIGNAL(signalKillEmAll()), QucsFilter, SLOT(kill()));
635 }
636 
637 // ------------------------------------------------------------------------
638 // Is called to start the transmission line calculation program.
640 {
641  QProcess *QucsLine =
642  new QProcess(QString(QucsSettings.BinDir + "qucstrans"));
643  if(!QucsLine->start()) {
644  QMessageBox::critical(this, tr("Error"),
645  tr("Cannot start line calculation program!"));
646  delete QucsLine;
647  return;
648  }
649 
650  // to kill it before qucs ends
651  connect(this, SIGNAL(signalKillEmAll()), QucsLine, SLOT(kill()));
652 }
653 
654 // ------------------------------------------------------------------------
655 // Is called to start the component library program.
657 {
658  QProcess *QucsLibrary =
659  new QProcess(QString(QucsSettings.BinDir + "qucslib"));
660  if(!QucsLibrary->start()) {
661  QMessageBox::critical(this, tr("Error"),
662  tr("Cannot start library program!"));
663  delete QucsLibrary;
664  return;
665  }
666 
667  // to kill it before qucs ends
668  connect(this, SIGNAL(signalKillEmAll()), QucsLibrary, SLOT(kill()));
669 }
670 
671 // --------------------------------------------------------------
672 // Is called to show a dialog for creating matching circuits.
674 {
675  MatchDialog *d = new MatchDialog(this);
676  d->exec();
677 }
678 
679 // ------------------------------------------------------------------------
680 // Is called to start the attenuator calculation program.
682 {
683  QProcess *QucsAtt =
684  new QProcess(QString(QucsSettings.BinDir + "qucsattenuator"));
685  if(!QucsAtt->start()) {
686  QMessageBox::critical(this, tr("Error"),
687  tr("Cannot start attenuator calculation program!"));
688  delete QucsAtt;
689  return;
690  }
691 
692  // to kill it before qucs ends
693  connect(this, SIGNAL(signalKillEmAll()), QucsAtt, SLOT(kill()));
694 }
695 
696 // --------------------------------------------------------------
698 {
699  showHTML("index.html");
700 }
701 
702 // --------------------------------------------------------------
704 {
705  showHTML("start.html");
706 }
707 
708 // --------------------------------------------------------------
709 void QucsApp::showHTML(const QString& Page)
710 {
711  QStringList com;
712  com << QucsSettings.BinDir + "qucshelp" << Page;
713  QProcess *QucsHelp = new QProcess(com);
714  QucsHelp->setCommunication(0);
715  if(!QucsHelp->start()) {
716  QMessageBox::critical(this, tr("Error"), tr("Cannot start qucshelp!"));
717  delete QucsHelp;
718  return;
719  }
720 
721  // to kill it before qucs ends
722  connect(this, SIGNAL(signalKillEmAll()), QucsHelp, SLOT(kill()));
723 }
724 
725 // ---------------------------------------------------------------------
726 // Is called when the find action is activated.
728 {
730 }
731 
732 // ---------------------------------------------------------------------
733 // Is called when the find-again action is activated.
735 {
736  SearchDia->searchText(true, 1);
737 }
738 
739 // --------------------------------------------------------------
741 {
742  QWidget *Doc = DocumentTab->currentPage();
743  if(Doc->inherits("QTextEdit")) {
744  ((TextDoc*)Doc)->viewport()->setFocus();
745  SearchDia->initSearch(true);
746  }
747  else {
748  ChangeDialog *d = new ChangeDialog((Schematic*)Doc);
749  if(d->exec() == QDialog::Accepted) {
750  ((Schematic*)Doc)->setChanged(true, true);
751  ((Schematic*)Doc)->viewport()->update();
752  }
753  }
754 }
755 
756 // --------------------------------------------------------------
758 {
759  editText->setHidden(true); // disable text edit of component property
760 
761  if(ProjName.isEmpty()) {
762  QMessageBox::critical(this, tr("Error"), tr("No project open!"));
763  return;
764  }
765 
766 
767  QStringList List = QFileDialog::getOpenFileNames(
768  QucsFileFilter, lastDir.isEmpty() ? QString(".") : lastDir,
769  this, 0, tr("Select files to copy"));
770 
771  if(List.isEmpty()) {
772  statusBar()->message(tr("No files copied."), 2000);
773  return;
774  }
775 
776 
777  char *Buffer = (char*)malloc(0x10000);
778  if(!Buffer) return; // should never happen
779 
780  QStringList FileList = List; // make a copy as recommended by Qt
781  QStringList::Iterator it = FileList.begin();
782  QFileInfo Info(*it);
783  lastDir = Info.dirPath(true); // remember last directory
784 
785  // copy all files to project directory
786  int Num;
787  QFile origFile, destFile;
788  while(it != FileList.end()) {
789  Info.setFile(*it);
790  origFile.setName(*it);
791  destFile.setName(QucsWorkDir.absPath() +
792  QDir::separator() + Info.fileName());
793 
794  if(!origFile.open(IO_ReadOnly)) {
795  QMessageBox::critical(this, tr("Error"), tr("Cannot open \"%1\" !").arg(*it));
796  it++;
797  continue;
798  }
799 
800  if(destFile.exists())
801  if(QMessageBox::information(this, tr("Overwrite"),
802  tr("File \"%1\" already exists.\nOverwrite ?").arg(*it), QMessageBox::Yes,
803  QMessageBox::No|QMessageBox::Default|QMessageBox::Escape)
804  != QMessageBox::Yes) {
805  origFile.close();
806  it++;
807  continue;
808  }
809 
810  if(!destFile.open(IO_WriteOnly)) {
811  QMessageBox::critical(this, tr("Error"), tr("Cannot create \"%1\" !").arg(*it));
812  origFile.close();
813  it++;
814  continue;
815  }
816 
817  // copy data
818  do {
819  Num = origFile.readBlock(Buffer, 0x10000);
820  if(Num < 0) {
821  QMessageBox::critical(this, tr("Error"), tr("Cannot read \"%1\" !").arg(*it));
822  break;
823  }
824  Num = destFile.writeBlock(Buffer, Num);
825  if(Num < 0) {
826  QMessageBox::critical(this, tr("Error"), tr("Cannot write \"%1\" !").arg(*it));
827  break;
828  }
829  } while(Num == 0x10000);
830 
831  origFile.close();
832  destFile.close();
833  it++;
834  }
835 
836  free(Buffer);
837  readProjectFiles(); // re-read the content ListView
838  statusBar()->message(tr("Ready."));
839 }
840 
841 // -----------------------------------------------------------
842 void QucsApp::slotCursorLeft()
843 {
844  if(!editText->isHidden()) return; // for edit of component property ?
845 
846  QPtrList<Element> movingElements;
847  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
848  int markerCount = Doc->copySelectedElements(&movingElements);
849 
850  if((movingElements.count() - markerCount) < 1) {
851  if(markerCount > 0) { // only move marker if nothing else selected
852  Doc->markerLeftRight(true, &movingElements);
853  movingElements.clear();
854  }
855  else {
856  if(Doc->scrollLeft(Doc->horizontalScrollBar()->lineStep()))
857  Doc->scrollBy(-Doc->horizontalScrollBar()->lineStep(), 0);
858  }
859 
860  Doc->viewport()->update();
861  view->drawn = false;
862  return;
863  }
864 
865  view->moveElements(&movingElements, -Doc->GridX, 0); // move "GridX" to left
866  view->MAx3 = 1; // sign for moved elements
867  view->endElementMoving(Doc, &movingElements);
868 }
869 
870 // -----------------------------------------------------------
871 void QucsApp::slotCursorRight()
872 {
873  if(!editText->isHidden()) return; // for edit of component property ?
874 
875  QPtrList<Element> movingElements;
876  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
877  int markerCount = Doc->copySelectedElements(&movingElements);
878 
879  if((movingElements.count() - markerCount) < 1) {
880  if(markerCount > 0) { // only move marker if nothing else selected
881  Doc->markerLeftRight(false, &movingElements);
882  movingElements.clear();
883  }
884  else {
885  if(Doc->scrollRight(-Doc->horizontalScrollBar()->lineStep()))
886  Doc->scrollBy(Doc->horizontalScrollBar()->lineStep(), 0);
887  }
888 
889  Doc->viewport()->update();
890  view->drawn = false;
891  return;
892  }
893 
894  view->moveElements(&movingElements, Doc->GridX, 0); // move "GridX" to right
895  view->MAx3 = 1; // sign for moved elements
896  view->endElementMoving(Doc, &movingElements);
897 }
898 
899 // -----------------------------------------------------------
900 void QucsApp::slotCursorUp()
901 {
902  if(!editText->isHidden()) { // for edit of component property ?
903  if(view->MAx3 == 0) return; // edit component namen ?
905  Property *pp = pc->Props.at(view->MAx3-1); // current property
906  int Begin = pp->Description.find('[');
907  if(Begin < 0) return; // no selection list ?
908  int End = pp->Description.find(editText->text(), Begin); // current
909  if(End < 0) return; // should never happen
910  End = pp->Description.findRev(',', End);
911  if(End < Begin) return; // was first item ?
912  End--;
913  int Pos = pp->Description.findRev(',', End);
914  if(Pos < Begin) Pos = Begin; // is first item ?
915  Pos++;
916  if(pp->Description.at(Pos) == ' ') Pos++; // remove leading space
917  editText->setText(pp->Description.mid(Pos, End-Pos+1));
918  editText->selectAll();
919  return;
920  }
921 
922  QPtrList<Element> movingElements;
923  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
924  int markerCount = Doc->copySelectedElements(&movingElements);
925 
926  if((movingElements.count() - markerCount) < 1) {
927  if(markerCount > 0) { // only move marker if nothing else selected
928  Doc->markerUpDown(true, &movingElements);
929  movingElements.clear();
930  }
931  else {
932  if(Doc->scrollUp(Doc->verticalScrollBar()->lineStep()))
933  Doc->scrollBy(0, -Doc->verticalScrollBar()->lineStep());
934  }
935 
936  Doc->viewport()->update();
937  view->drawn = false;
938  return;
939  }
940 
941  view->moveElements(&movingElements, 0, -Doc->GridY); // move "GridY" up
942  view->MAx3 = 1; // sign for moved elements
943  view->endElementMoving(Doc, &movingElements);
944 }
945 
946 // -----------------------------------------------------------
947 void QucsApp::slotCursorDown()
948 {
949  if(!editText->isHidden()) { // for edit of component property ?
950  if(view->MAx3 == 0) return; // edit component namen ?
952  Property *pp = pc->Props.at(view->MAx3-1); // current property
953  int Pos = pp->Description.find('[');
954  if(Pos < 0) return; // no selection list ?
955  Pos = pp->Description.find(editText->text(), Pos); // current list item
956  if(Pos < 0) return; // should never happen
957  Pos = pp->Description.find(',', Pos);
958  if(Pos < 0) return; // was last item ?
959  Pos++;
960  if(pp->Description.at(Pos) == ' ') Pos++; // remove leading space
961  int End = pp->Description.find(',', Pos);
962  if(End < 0) { // is last item ?
963  End = pp->Description.find(']', Pos);
964  if(End < 0) return; // should never happen
965  }
966  editText->setText(pp->Description.mid(Pos, End-Pos));
967  editText->selectAll();
968  return;
969  }
970 
971  QPtrList<Element> movingElements;
972  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
973  int markerCount = Doc->copySelectedElements(&movingElements);
974 
975  if((movingElements.count() - markerCount) < 1) {
976  if(markerCount > 0) { // only move marker if nothing else selected
977  Doc->markerUpDown(false, &movingElements);
978  movingElements.clear();
979  }
980  else {
981  if(Doc->scrollDown(-Doc->verticalScrollBar()->lineStep()))
982  Doc->scrollBy(0, Doc->verticalScrollBar()->lineStep());
983  }
984 
985  Doc->viewport()->update();
986  view->drawn = false;
987  return;
988  }
989 
990  view->moveElements(&movingElements, 0, Doc->GridY); // move "GridY" down
991  view->MAx3 = 1; // sign for moved elements
992  view->endElementMoving(Doc, &movingElements);
993 }
994 
995 // -----------------------------------------------------------
996 // Is called if user clicked on component text of if return is
997 // pressed in the component text QLineEdit.
998 // In "view->MAx3" is the number of the current property.
1000 {
1001  QString s;
1002  QFont f = QucsSettings.font;
1003  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
1004  f.setPointSizeFloat( Doc->Scale * float(f.pointSize()) );
1005  editText->setFont(f);
1006 
1007  Property *pp = 0;
1009  if(!pc) return; // should never happen
1010  view->MAx1 = pc->cx + pc->tx;
1011  view->MAy1 = pc->cy + pc->ty;
1012 
1013  int z, n=0; // "n" is number of property on screen
1014  pp = pc->Props.first();
1015  for(z=view->MAx3; z>0; z--) { // calculate "n"
1016  if(!pp) { // should never happen
1017  editText->setHidden(true);
1018  return;
1019  }
1020  if(pp->display) n++; // is visible ?
1021  pp = pc->Props.next();
1022  }
1023 
1024  pp = 0;
1025  if(view->MAx3 > 0) pp = pc->Props.at(view->MAx3-1); // current property
1026  else s = pc->Name;
1027 
1028  if(!editText->isHidden()) { // is called the first time ?
1029  // no -> apply value to current property
1030  if(view->MAx3 == 0) { // component name ?
1031  Component *pc2;
1032  if(!editText->text().isEmpty())
1033  if(pc->Name != editText->text()) {
1034  for(pc2 = Doc->Components->first(); pc2!=0; pc2 = Doc->Components->next())
1035  if(pc2->Name == editText->text())
1036  break; // found component with the same name ?
1037  if(!pc2) {
1038  pc->Name = editText->text();
1039  Doc->setChanged(true, true); // only one undo state
1040  }
1041  }
1042  }
1043  else if(pp) { // property was applied
1044  if(pp->Value != editText->text()) {
1045  pp->Value = editText->text();
1046  Doc->recreateComponent(pc); // because of "Num" and schematic symbol
1047  Doc->setChanged(true, true); // only one undo state
1048  }
1049  }
1050 
1051  n++; // next row on screen
1052  (view->MAx3)++; // next property
1053  pp = pc->Props.at(view->MAx3-1); // search for next property
1054 
1055  Doc->viewport()->update();
1056  view->drawn = false;
1057 
1058  if(!pp) { // was already last property ?
1059  editText->setHidden(true);
1060  return;
1061  }
1062 
1063 
1064  while(!pp->display) { // search for next visible property
1065  (view->MAx3)++; // next property
1066  pp = pc->Props.next();
1067  if(!pp) { // was already last property ?
1068  editText->setHidden(true);
1069  return;
1070  }
1071  }
1072  }
1073 
1074  // avoid seeing the property text behind the line edit
1075  if(pp) // Is it first property or component name ?
1076  s = pp->Value;
1077  editText->setMinimumWidth(editText->fontMetrics().width(s)+4);
1078 
1079 
1080  Doc->contentsToViewport(int(Doc->Scale * float(view->MAx1 - Doc->ViewX1)),
1081  int(Doc->Scale * float(view->MAy1 - Doc->ViewY1)),
1082  view->MAx2, view->MAy2);
1083  editText->setReadOnly(false);
1084  if(pp) { // is it a property ?
1085  s = pp->Value;
1086  view->MAx2 += editText->fontMetrics().width(pp->Name+"=");
1087  if(pp->Description.find('[') >= 0) // is selection list ?
1088  editText->setReadOnly(true);
1089  Expr_CompProp.setPattern("[^\"]*");
1090  if(!pc->showName) n--;
1091  }
1092  else // it is the component name
1093  Expr_CompProp.setPattern("[\\w_]+");
1094  Val_CompProp.setRegExp(Expr_CompProp);
1095  editText->setValidator(&Val_CompProp);
1096 
1097  z = editText->fontMetrics().lineSpacing();
1098  view->MAy2 += n*z;
1099  editText->setText(s);
1100  editText->setPaletteBackgroundColor(QucsSettings.BGColor);
1101  editText->setFocus();
1102  editText->selectAll();
1103  editText->reparent(Doc->viewport(), 0, QPoint(view->MAx2, view->MAy2), true);
1104 }
1105 
1106 // -----------------------------------------------------------
1107 // Is called if the text of the property edit changed, to match
1108 // the width of the edit field.
1109 void QucsApp::slotResizePropEdit(const QString& t)
1110 {
1111  editText->resize(editText->fontMetrics().width(t)+4,
1112  editText->fontMetrics().lineSpacing());
1113 }
1114 
1115 // -----------------------------------------------------------
1116 void QucsApp::slotCreateLib()
1117 {
1118  editText->setHidden(true); // disable text edit of component property
1119 
1120  if(ProjName.isEmpty()) {
1121  QMessageBox::critical(this, tr("Error"), tr("Please open project with subcircuits!"));
1122  return;
1123  }
1124 
1125  (new LibraryDialog(this, ConSchematics))->exec();
1126 }
1127 
1128 // -----------------------------------------------------------
1129 void QucsApp::slotImportData()
1130 {
1131  editText->setHidden(true); // disable text edit of component property
1132 
1133  if(ProjName.isEmpty()) {
1134  QMessageBox::critical(this, tr("Error"), tr("Please open project first!"));
1135  return;
1136  }
1137 
1138  ImportDialog *d = new ImportDialog(this);
1139  if(d->exec() == QDialog::Accepted)
1140  readProjectFiles(); // re-read all project files
1141 }
1142 
1143 // -----------------------------------------------------------
1144 void QucsApp::slotExportGraphAsCsv()
1145 {
1146  editText->setHidden(true); // disable text edit of component property
1147 
1148  for(;;) {
1149  if(view->focusElement)
1150  if(view->focusElement->Type == isGraph)
1151  break;
1152 
1153  QMessageBox::critical(this, tr("Error"), tr("Please select a diagram graph!"));
1154  return;
1155  }
1156 
1157  QString s = QFileDialog::getSaveFileName(
1158  lastDir.isEmpty() ? QString(".") : lastDir,
1159  tr("CSV file")+" (*.csv);;" + tr("Any File")+" (*)",
1160  this, 0, tr("Enter an Output File Name"));
1161  if(s.isEmpty())
1162  return;
1163 
1164  QFileInfo Info(s);
1165  lastDir = Info.dirPath(true); // remember last directory
1166  if(Info.extension().isEmpty())
1167  s += ".csv";
1168 
1169  QFile File(s);
1170  if(File.exists())
1171  if(QMessageBox::information(this, tr("Info"),
1172  tr("Output file already exists!")+"\n"+tr("Overwrite it?"),
1173  tr("&Yes"), tr("&No"), 0,1,1))
1174  return;
1175 
1176  if(!File.open(IO_WriteOnly)) {
1177  QMessageBox::critical(this, QObject::tr("Error"),
1178  QObject::tr("Cannot create output file!"));
1179  return;
1180  }
1181 
1182  QTextStream Stream(&File);
1183 
1184 
1185  DataX *pD;
1186  Graph *g = (Graph*)view->focusElement;
1187  // First output the names of independent and dependent variables.
1188  for(pD = g->cPointsX.first(); pD!=0; pD = g->cPointsX.next())
1189  Stream << '\"' << pD->Var << "\";";
1190  Stream << "\"r " << g->Var << "\";\"i " << g->Var << "\"\n";
1191 
1192 
1193  int n, m;
1194  double *py = g->cPointsY;
1195  int Count = g->countY * g->cPointsX.getFirst()->count;
1196  for(n = 0; n < Count; n++) {
1197  m = n;
1198  for(pD = g->cPointsX.first(); pD!=0; pD = g->cPointsX.next()) {
1199  Stream << *(pD->Points + m%pD->count) << ';';
1200  m /= pD->count;
1201  }
1202 
1203  Stream << *(py) << ';' << *(py+1) << '\n';
1204  py += 2;
1205  }
1206 
1207  File.close();
1208 }
1209 
1210 // ----------------------------------------------------------
1211 void QucsApp::slotCreatePackage()
1212 {
1213  editText->setHidden(true); // disable text edit of component property
1214 
1215  PackageDialog *d = new PackageDialog(this, true);
1216  d->exec();
1217 }
1218 
1219 // ----------------------------------------------------------
1220 void QucsApp::slotExtractPackage()
1221 {
1222  editText->setHidden(true); // disable text edit of component property
1223  PackageDialog *d = new PackageDialog(this, false);
1224  d->show();
1225  d->extractPackage();
1226  readProjects();
1227 }