My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
qucs.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qucs.cpp
3  ----------
4  begin : Thu Aug 28 2003
5  copyright : (C) 2003, 2004, 2005, 2006 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 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 
22 #include <limits.h>
23 
24 #include <qaccel.h>
25 #include <qimage.h>
26 #include <qsplitter.h>
27 #include <qvbox.h>
28 #include <qhbox.h>
29 #include <qlabel.h>
30 #include <qmessagebox.h>
31 #include <qdir.h>
32 #include <qpainter.h>
33 #include <qfiledialog.h>
34 #include <qinputdialog.h>
35 #include <qapplication.h>
36 #include <qclipboard.h>
37 #include <qfont.h>
38 #include <qtextedit.h>
39 #include <qcheckbox.h>
40 #include <qaction.h>
41 #include <qtabwidget.h>
42 #include <qcombobox.h>
43 #include <qiconview.h>
44 #include <qpushbutton.h>
45 #include <qlistview.h>
46 #include <qlistbox.h>
47 #include <qprinter.h>
48 #include <qfiledialog.h>
49 #include <qpixmap.h>
50 #include <qtoolbutton.h>
51 #include <qstatusbar.h>
52 #include <qtoolbar.h>
53 #include <qpopupmenu.h>
54 #include <qmenubar.h>
55 #include <qprocess.h>
56 #include <qlineedit.h>
57 #include <qstringlist.h>
58 #include <qdragobject.h>
59 #include <qsyntaxhighlighter.h>
60 
61 #include "main.h"
62 #include "qucs.h"
63 #include "qucsdoc.h"
64 #include "textdoc.h"
65 #include "syntax.h"
66 #include "schematic.h"
67 #include "mouseactions.h"
68 #include "wire.h"
69 #include "module.h"
70 #include "components/components.h"
71 #include "paintings/paintings.h"
72 #include "diagrams/diagrams.h"
73 #include "dialogs/savedialog.h"
74 #include "dialogs/newprojdialog.h"
75 #include "dialogs/settingsdialog.h"
79 #include "dialogs/searchdialog.h"
80 #include "dialogs/sweepdialog.h"
81 #include "dialogs/labeldialog.h"
82 #include "dialogs/matchdialog.h"
83 #include "dialogs/simmessage.h"
84 #include "dialogs/vtabwidget.h"
86 #include "octave_window.h"
87 
88 extern const char *empty_xpm[];
89 
90 QDir QucsWorkDir; // current project path
91 QDir QucsHomeDir; // Qucs user directory where all projects are located
92 
93 
94 // IconView without dragging icon bitmap
95 class myIconView : public QIconView
96 {
97 public:
98  myIconView(QWidget* parent_) : QIconView(parent_, 0, 0) {};
100 
101 protected:
102  QDragObject *dragObject() {
103  QIconViewItem *Item = currentItem();
104  if(!Item) return 0;
105 
106  // no picture during dragging, but bounding rectangles in QListView
107  QIconDrag *DragPic = new QIconDrag( viewport() );
108  DragPic->setPixmap( QPixmap(empty_xpm), QPoint(0, 0) );
109  DragPic->append( QIconDragItem(),
110  QRect( Item->pixmapRect().width() / -2,
111  Item->pixmapRect().height() / -2,
112  Item->pixmapRect().width(), Item->pixmapRect().height() ),
113  QRect( Item->textRect().width() / -2,
114  Item->pixmapRect().height() / 2 + 5,
115  Item->textRect().width(), Item->textRect().height() ) );
116  return DragPic;
117  };
118 };
119 
120 
121 
123 {
124  setCaption("Qucs " PACKAGE_VERSION);
125 
126  QucsFileFilter =
127  tr("Schematic")+" (*.sch);;"+
128  tr("Data Display")+" (*.dpl);;"+
129  tr("Qucs Documents")+" (*.sch *.dpl);;"+
130  tr("VHDL Sources")+" (*.vhdl *.vhd);;"+
131  tr("Verilog Sources")+" (*.v);;"+
132  tr("Verilog-A Sources")+" (*.va);;"+
133  tr("Octave Scripts")+" (*.m *.oct);;"+
134  tr("Any File")+" (*)";
135  QucsWorkDir.setPath(QDir::homeDirPath()+QDir::convertSeparators ("/.qucs"));
136  QucsHomeDir.setPath(QDir::homeDirPath()+QDir::convertSeparators ("/.qucs"));
137 
138  move (QucsSettings.x, QucsSettings.y);
139  resize(QucsSettings.dx, QucsSettings.dy);
140 
141  MouseMoveAction = 0;
142  MousePressAction = 0;
143  MouseReleaseAction = 0;
145 
146  initView();
147  initActions();
148  initMenuBar();
149  initToolBar();
150  initStatusBar();
151  viewToolBar->setOn(true);
152  viewStatusBar->setOn(true);
153  viewBrowseDock->setOn(true);
154  slotViewOctaveDock(false);
155  initCursorMenu();
156  HierarchyHistory.setAutoDelete(true);
158 
159  // default settings of the printer
160  Printer = new QPrinter(QPrinter::HighResolution);
161 #if defined (QT_VERSION) && QT_VERSION > 0x030200
162  Printer->setOptionEnabled(QPrinter::PrintSelection, true);
163  Printer->setOptionEnabled(QPrinter::PrintPageRange, false);
164  Printer->setOptionEnabled(QPrinter::PrintToFile, true);
165 #endif
166  Printer->setColorMode(QPrinter::Color);
167  Printer->setFullPage(true);
168 
169  SearchDia = new SearchDialog(this);
170 
171  // creates a document called "untitled"
172  new Schematic(this, "");
173 
174  select->setOn(true); // switch on the 'select' action
175  switchSchematicDoc(true); // "untitled" document is schematic
176 
177  // load documents given as command line arguments
178  for(int z=1; z<qApp->argc(); z++) {
179  QString arg = qApp->argv()[z];
180  if(*(arg) != '-') {
181  // allow uri's: file:/home/linuxuser/Desktop/example.sch
182  if(arg.contains(":/")) {
183  QString f = QDir::convertSeparators(QUriDrag::uriToLocalFile(arg));
184  if(f.isEmpty()) f = arg;
185  gotoPage(f);
186  } else {
187  gotoPage(arg);
188  }
189  }
190  }
191 }
192 
194 {
196  delete Printer;
197 }
198 
199 
200 // #######################################################################
201 // ########## ##########
202 // ########## Creates the working area (QTabWidget etc.) ##########
203 // ########## ##########
204 // #######################################################################
205 void QucsApp::initContentListView()
206 {
207  Content->clear(); // remove all documents
208  ConOthers = new QListViewItem(Content, tr("Others"));
209  ConDatasets = new QListViewItem(Content, tr("Datasets"));
210  ConDisplays = new QListViewItem(Content, tr("Data Displays"));
211  ConOctave = new QListViewItem(Content, tr("Octave"));
212  ConVerilog = new QListViewItem(Content, tr("Verilog"));
213  ConVerilogA = new QListViewItem(Content, tr("Verilog-A"));
214  ConSources = new QListViewItem(Content, tr("VHDL"));
215  ConSchematics = new QListViewItem(Content, tr("Schematics"));
216 }
217 
218 void QucsApp::initView()
219 {
220  // set application icon
221  setIcon (QPixmap(QucsSettings.BitmapDir + "big.qucs.xpm"));
222 
223  DocumentTab = new QTabWidget(this);
224  setCentralWidget(DocumentTab);
225  connect(DocumentTab,
226  SIGNAL(currentChanged(QWidget*)), SLOT(slotChangeView(QWidget*)));
227 
228  dock = new VTabbedDockWidget(QDockWindow::InDock, this);
229  TabView = new VTabWidget(VTabInterface::TabLeft,dock); // tabs on the left side
230 
231 
232  connect(dock, SIGNAL(visibilityChanged(bool)), SLOT(slotToggleDock(bool)));
233 
234  view = new MouseActions();
235 
236  editText = new QLineEdit(this); // for editing component properties
237  editText->setFrame(false);
238  editText->setHidden(true);
239  editText->setPaletteBackgroundColor(QucsSettings.BGColor);
240  connect(editText, SIGNAL(returnPressed()), SLOT(slotApplyCompText()));
241  connect(editText, SIGNAL(textChanged(const QString&)),
242  SLOT(slotResizePropEdit(const QString&)));
243  connect(editText, SIGNAL(lostFocus()), SLOT(slotHideEdit()));
244 
245  // ----------------------------------------------------------
246  // "Project Tab" of the left QTabWidget
247  QVBox *ProjGroup = new QVBox(this);
248  QHBox *ProjButts = new QHBox(ProjGroup);
249  QPushButton *ProjNew = new QPushButton(tr("New"),ProjButts);
250  connect(ProjNew, SIGNAL(clicked()), SLOT(slotProjNewButt()));
251  QPushButton *ProjOpen = new QPushButton(tr("Open"),ProjButts);
252  connect(ProjOpen, SIGNAL(clicked()), SLOT(slotProjOpenButt()));
253  QPushButton *ProjDel = new QPushButton(tr("Delete"),ProjButts);
254  connect(ProjDel, SIGNAL(clicked()), SLOT(slotProjDelButt()));
255 
256  Projects = new QListBox(ProjGroup);
257  TabView->addPage(ProjGroup, tr("Projects"));
258  TabView->setTabToolTip(TabView->id(ProjGroup),
259  tr("content of project directory"));
260 
261  connect(Projects, SIGNAL(doubleClicked(QListBoxItem*)),
262  SLOT(slotOpenProject(QListBoxItem*)));
263 
264  // ----------------------------------------------------------
265  // "Content Tab" of the left QTabWidget
266  Content = new QListView(this);
267  Content->setRootIsDecorated(true); // open/close decoration for root items
268  Content->setSorting(-1); // no sorting
269  Content->addColumn(tr("Content of"));
270  Content->addColumn(tr("Note"));
271  Content->setColumnWidthMode(0,QListView::Manual);
272  Content->setColumnWidth(0, 150);
273 
274  initContentListView();
275  TabView->addPage(Content,tr("Content"));
276  TabView->setTabToolTip(TabView->id(Content), tr("content of current project"));
277 
278  connect(Content, SIGNAL(doubleClicked(QListViewItem*)),
279  SLOT(slotOpenContent(QListViewItem*)));
280  connect(Content, SIGNAL(clicked(QListViewItem*)),
281  SLOT(slotSelectSubcircuit(QListViewItem*)));
282  connect(Content, SIGNAL(expanded(QListViewItem*)),
283  SLOT(slotExpandContentList(QListViewItem*)));
284 
285  // ----------------------------------------------------------
286  // "Component Tab" of the left QTabWidget
287  QVBox *CompGroup = new QVBox(this);
288  CompChoose = new QComboBox(CompGroup);
289  CompComps = new myIconView(CompGroup);
290  TabView->addPage(CompGroup,tr("Components"));
291  TabView->setTabToolTip(TabView->id(CompGroup), tr("components and diagrams"));
292  fillComboBox(true);
293 
294  slotSetCompView(0);
295  connect(CompChoose, SIGNAL(activated(int)), SLOT(slotSetCompView(int)));
296  connect(CompComps, SIGNAL(clicked(QIconViewItem*)),
297  SLOT(slotSelectComponent(QIconViewItem*)));
298  dock->setWidget(TabView);
299  setDockEnabled(dock,DockTop,false);
300  setDockEnabled(dock,DockBottom,false);
301  moveDockWindow(dock,DockLeft);
302  TabView->setCurrentPage(0);
303 
304  // ----------------------------------------------------------
305  // Octave docking window
306  octDock = new QDockWindow(QDockWindow::InDock, this);
307  octDock->setCloseMode(QDockWindow::Always);
308  connect(octDock, SIGNAL(visibilityChanged(bool)), SLOT(slotToggleOctave(bool)));
309  octave = new OctaveWindow(octDock);
310  moveDockWindow(octDock, Qt::DockBottom);
311 
312  // ............................................
313  readProjects(); // reads all projects and inserts them into the ListBox
314 }
315 
316 // ---------------------------------------------------------------
317 // Returns a pointer to the QucsDoc object whose number is "No".
318 // If No < 0 then a pointer to the current document is returned.
320 {
321  QWidget *w;
322  if(No < 0)
323  w = DocumentTab->currentPage();
324  else
325  w = DocumentTab->page(No);
326 
327  if(w) {
328  if(isTextDocument (w))
329  return (QucsDoc*) ((TextDoc*)w);
330  else
331  return (QucsDoc*) ((Schematic*)w);
332  }
333 
334  return 0;
335 }
336 
337 // ---------------------------------------------------------------
338 // Returns a pointer to the QucsDoc object whose file name is "Name".
339 QucsDoc * QucsApp::findDoc (QString File, int * Pos)
340 {
341  QucsDoc * d;
342  int No = 0;
343  File = QDir::convertSeparators (File);
344  while ((d = getDoc (No++)) != 0)
345  if (QDir::convertSeparators (d->DocName) == File) {
346  if (Pos) *Pos = No - 1;
347  return d;
348  }
349  return 0;
350 }
351 
352 // ---------------------------------------------------------------
353 // Put the component groups into the ComboBox. It is possible to
354 // only put the paintings in it, because of "symbol painting mode".
355 void QucsApp::fillComboBox (bool setAll)
356 {
357  CompChoose->setSizeLimit (11); // Increase this if you add items below.
358  CompChoose->clear ();
359 
360  QStringList cats = Category::getCategories ();
361  for (QStringList::Iterator it = cats.begin (); it != cats.end (); ++it) {
362  if (*it != QObject::tr("paintings")) {
363  if (setAll) CompChoose->insertItem (*it);
364  }
365  else CompChoose->insertItem (*it);
366  }
367 }
368 
369 // ----------------------------------------------------------
370 // Whenever the Component Library ComboBox is changed, this slot fills the
371 // Component IconView with the appropriat components.
372 void QucsApp::slotSetCompView (int index)
373 {
374  editText->setHidden (true); // disable text edit of component property
375 
376  QPtrList<Module> Comps;
377  CompComps->clear (); // clear the IconView
378  if (CompChoose->count () <= 0) return;
379  QString item = CompChoose->text (index);
380  if ((index + 1) >= CompChoose->count ()) // because of symbol edit mode
381  Comps = Category::getModules (QObject::tr("paintings"));
382  else
383  Comps = Category::getModules (item);
384 
385  char * File;
386  QString Name;
387  Module * Mod;
388  for (Mod = Comps.first(); Mod; Mod = Comps.next ()) {
389  if (Mod->info) {
390  *(Mod->info) (Name, File, false);
391  new QIconViewItem (CompComps, Name,
392  QImage (QucsSettings.BitmapDir + QString (File) + ".png"));
393  }
394  }
395 }
396 
397 // ------------------------------------------------------------------
398 // Is called when the mouse is clicked within the Component QIconView.
399 void QucsApp::slotSelectComponent(QIconViewItem *item)
400 {
401  editText->setHidden(true); // disable text edit of component property
402 
403  // delete previously selected elements
404  if(view->selElem != 0) delete view->selElem;
405  view->selElem = 0; // no component/diagram/painting selected
406 
407  if(item == 0) { // mouse button pressed not over an item ?
408  CompComps->clearSelection(); // deselect component in ViewList
409  return;
410  }
411 
412  if(view->drawn)
413  ((QScrollView*)DocumentTab->currentPage())->viewport()->update();
414  view->drawn = false;
415 
416  // toggle last toolbar button off
417  if(activeAction) {
418  activeAction->blockSignals(true); // do not call toggle slot
419  activeAction->setOn(false); // set last toolbar button off
420  activeAction->blockSignals(false);
421  }
422  activeAction = 0;
423 
426  MouseReleaseAction = 0;
428 
429  pInfoFunc Infos = 0;
430  int i = CompComps->index (item);
431  QPtrList<Module> Comps;
432  if((CompChoose->currentItem()+1) >= CompChoose->count())
433  // the only one in "symbol-painting" mode
434  Comps = Category::getModules (QObject::tr("paintings"));
435  else
436  Comps = Category::getModules (CompChoose->currentText ());
437  Infos = Comps.at(i)->info;
438 
439  char * Dummy2;
440  QString Dummy1;
441  if (Infos)
442  view->selElem = (*Infos) (Dummy1, Dummy2, true);
443 }
444 
445 // ####################################################################
446 // ##### Functions for the menu that appears when left-clicking #####
447 // ##### on a file in the "Content" ListView. #####
448 // ####################################################################
449 
450 void QucsApp::initCursorMenu()
451 {
452  ContentMenu = new QPopupMenu(Content);
453  ContentMenu->insertItem(tr("Open"), this, SLOT(slotCMenuOpen()));
454  ContentMenu->insertItem(tr("Rename"), this, SLOT(slotCMenuRename()));
455  ContentMenu->insertItem(tr("Delete"), this, SLOT(slotCMenuDelete()));
456  ContentMenu->insertItem(tr("Delete Group"), this, SLOT(slotCMenuDelGroup()));
457 
458  connect(Content,
459  SIGNAL(contextMenuRequested(QListViewItem*, const QPoint&, int)),
460  SLOT(slotShowContentMenu(QListViewItem*, const QPoint&, int)));
461 }
462 
463 // ----------------------------------------------------------
464 // Shows the menu.
465 void QucsApp::slotShowContentMenu(QListViewItem *item, const QPoint& point, int)
466 {
467  if(item)
468  if(item->parent() != 0) { // no component, but item "schematic", ...
469  if(item->parent()->nextSibling()) // "Others" section in listview ?
470  ContentMenu->setItemEnabled(ContentMenu->idAt(3), true);
471  else
472  ContentMenu->setItemEnabled(ContentMenu->idAt(3), false);
473  ContentMenu->popup(point);
474  }
475 }
476 
477 // ----------------------------------------------------------
479 {
480  QListViewItem *Item = Content->selectedItem();
481  if(Item == 0) return;
482 
483  slotOpenContent(Item);
484 }
485 
486 // ----------------------------------------------------------
488 {
489  QListViewItem *Item = Content->selectedItem();
490  if(!Item) return;
491 
492  QString Name = Item->text(0);
493  if (findDoc (QucsWorkDir.filePath(Name))) {
494  QMessageBox::critical(this, tr("Error"),
495  tr("Cannot rename an open file!"));
496  return;
497  }
498 
499  QString Suffix = Name.section('.',-1); // remember suffix
500  QString Base = Name.section('.',0,-2);
501  if(Base.isEmpty()) Base = Name;
502 
503  bool ok;
504  QString s = QInputDialog::getText(tr("Rename file"), tr("Enter new name:"),
505  QLineEdit::Normal, Base, &ok, this);
506  if(!ok) return;
507  if(s.isEmpty()) return;
508 
509  QString NewName;
510  if(s.contains('.'))
511  NewName = s;
512  else
513  NewName = s+"."+Suffix;
514  QDir file(QucsWorkDir.path());
515  if(!file.rename(Name, NewName)) {
516  QMessageBox::critical(this, tr("Error"), tr("Cannot rename file: ")+Name);
517  return;
518  }
519  Item->setText(0, NewName);
520 }
521 
522 // ----------------------------------------------------------
524 {
525  QListViewItem *item = Content->selectedItem();
526  if(item == 0) return;
527  QString FileName = QucsWorkDir.filePath(item->text(0));
528 
529  if (findDoc (FileName)) {
530  QMessageBox::critical(this, tr("Error"),
531  tr("Cannot delete an open file!"));
532  return;
533  }
534 
535  int No;
536  No = QMessageBox::warning(this, tr("Warning"),
537  tr("This will delete the file permanently! Continue ?"),
538  tr("No"), tr("Yes"));
539  if(No != 1) return;
540 
541  if(!QFile::remove(FileName)) {
542  QMessageBox::critical(this, tr("Error"),
543  tr("Cannot delete schematic: ")+item->text(0));
544  return;
545  }
546 
547  item->parent()->takeItem(item);
548  delete item;
549 }
550 
551 // ----------------------------------------------------------
552 QString QucsApp::fileType (const QString& Ext)
553 {
554  QString Type = tr("unknown");
555  if (Ext == "v")
556  Type = tr("Verilog source");
557  else if (Ext == "va")
558  Type = tr("Verilog-A source");
559  else if (Ext == "vhd" || Ext == "vhdl")
560  Type = tr("VHDL source");
561  else if (Ext == "dat")
562  Type = tr("data file");
563  else if (Ext == "dpl")
564  Type = tr("data display");
565  else if (Ext == "sch")
566  Type = tr("schematic");
567  else if (Ext == "sym")
568  Type = tr("symbol");
569  else if (Ext == "vhdl.cfg" || Ext == "vhdl.cfg")
570  Type = tr("VHDL configuration");
571  else if (Ext == "cfg")
572  Type = tr("configuration");
573  return Type;
574 }
575 
576 // ----------------------------------------------------------
577 // Deletes all files with that name (and suffix sch, dpl, dat, vhdl, etc.).
579 {
580  QListViewItem * item = Content->selectedItem ();
581  if (item == 0)
582  return;
583  QString s = item->text (0);
584  s = QucsDoc::fileBase (s); // cut off suffix from file name
585 
586  const char * extensions[] =
587  { "sch", "dpl", "dat", "vhdl", "vhd", "v", "sym",
588  "vhdl.cfg", "vhd.cfg", "va", 0 };
589 
590  int i;
591  for (i = 0; extensions[i] != 0; i++) {
592  QString Short = s + "." + extensions[i];
593  QString Name = QucsWorkDir.filePath (Short);
594  // search, if files are open
595  if (findDoc (Name)) {
596  QMessageBox::critical(this, tr("Error"),
597  tr("Cannot delete the open file \"%1\"!").arg(Short));
598  return;
599  }
600  }
601 
602  // check existence of files
603  QString Str = "\n";
604  for (i = 0; extensions[i] != 0; i++) {
605  QString Short = s + "." + extensions[i];
606  QString Long = QucsWorkDir.filePath (Short);
607  bool exists = QFile::exists (Long);
608  if (exists)
609  Str += Short + "\n";
610  }
611  int No;
612  No = QMessageBox::warning (this, tr("Warning"),
613  tr("This will delete the files%1permanently! Continue ?").arg(Str),
614  tr("No"), tr("Yes"));
615  if (No != 1)
616  return;
617 
618  // file removal
619  for (i = 0; extensions[i] != 0; i++) {
620  QString Short = s + "." + extensions[i];
621  QString Name = QucsWorkDir.filePath (Short);
622  bool exists = QFile::exists (Name);
623  if (exists) {
624  // remove files
625  if (!QFile::remove (Name)) {
626  QMessageBox::critical(this, tr("Error"),
627  tr("Cannot delete %1: \"%2\"!").arg(fileType (extensions[i])).
628  arg(Short));
629  continue;
630  }
631  // remove items from listview
632  item = Content->findItem (Short, 0);
633  if (item) {
634  item->parent()->takeItem (item);
635  delete item;
636  }
637  }
638  }
639 }
640 
641 
642 // ################################################################
643 // ##### Functions that handle the project operations. #####
644 // ################################################################
645 
646 // Checks for qucs directory and reads all existing Qucs projects.
647 void QucsApp::readProjects()
648 {
649  QDir ProjDir(QDir::homeDirPath());
650  if(!ProjDir.cd(".qucs")) { // work directory exists ?
651  if(!ProjDir.mkdir(".qucs")) { // no, then create it
652  QMessageBox::warning(this, tr("Warning"),
653  tr("Cannot create work directory !"));
654  return;
655  }
656  ProjDir.cd(".qucs");
657  }
658 
659  // get all directories
660  QStringList PrDirs = ProjDir.entryList("*", QDir::Dirs, QDir::Name);
661  PrDirs.pop_front(); // delete "." from list
662  PrDirs.pop_front(); // delete ".." from list
663 
664  Projects->clear();
665  QStringList::iterator it;
666  // inserts all project directories
667  for(it = PrDirs.begin(); it != PrDirs.end(); it++)
668  if ((*it).right(4) == "_prj") { // project directories end with "_prj"
669  (*it) = (*it).left((*it).length()-4); // remove "_prj" from name
670  Projects->insertItem(*it);
671  }
672 }
673 
674 // ----------------------------------------------------------
675 // Is called, when "Create New Project" button is pressed.
676 void QucsApp::slotProjNewButt()
677 {
678  editText->setHidden(true); // disable text edit of component property
679 
680  NewProjDialog *d = new NewProjDialog(this);
681  if(d->exec() != QDialog::Accepted) return;
682 
683  QDir projDir(QucsHomeDir.path());
684  if(projDir.mkdir(d->ProjName->text()+"_prj")) {
685  Projects->insertItem(d->ProjName->text(),0); // at first position
686  if(d->OpenProj->isChecked())
687  slotOpenProject(Projects->firstItem());
688  }
689  else QMessageBox::information(this, tr("Info"),
690  tr("Cannot create project directory !"));
691 }
692 
693 // ----------------------------------------------------------
694 // Checks whether this file is a qucs file and whether it is an subcircuit.
695 // It returns the number of subcircuit ports.
696 int QucsApp::testFile(const QString& DocName)
697 {
698  QFile file(DocName);
699  if(!file.open(IO_ReadOnly)) {
700  return -1;
701  }
702 
703  QString Line;
704  // .........................................
705  // To strongly speed up the file read operation the whole file is
706  // read into the memory in one piece.
707  QTextStream ReadWhole(&file);
708  QString FileString = ReadWhole.read();
709  file.close();
710  QTextStream stream(&FileString, IO_ReadOnly);
711 
712 
713  // read header ........................
714  do {
715  if(stream.atEnd()) {
716  file.close();
717  return -2;
718  }
719  Line = stream.readLine();
720  Line = Line.stripWhiteSpace();
721  } while(Line.isEmpty());
722 
723  if(Line.left(16) != "<Qucs Schematic ") { // wrong file type ?
724  file.close();
725  return -3;
726  }
727 
728  Line = Line.mid(16, Line.length()-17);
729  if(!checkVersion(Line)) { // wrong version number ?
730  file.close();
731  return -4;
732  }
733 
734  // read content ....................
735  while(!stream.atEnd()) {
736  Line = stream.readLine();
737  if(Line == "<Components>") break;
738  }
739 
740  int z=0;
741  while(!stream.atEnd()) {
742  Line = stream.readLine();
743  if(Line == "</Components>") {
744  file.close();
745  return z; // return number of ports
746  }
747 
748  Line = Line.stripWhiteSpace();
749  QString s = Line.section(' ',0,0); // component type
750  if(s == "<Port") z++;
751  }
752  return -5; // component field not closed
753 }
754 
755 // ----------------------------------------------------------
756 // Reads all files in the project directory and sort them into the
757 // content ListView
758 void QucsApp::readProjectFiles()
759 {
760  // Delete the content files, but don't delete the parent items !!!
761  while(ConSchematics->firstChild())
762  delete ConSchematics->firstChild();
763  while(ConDisplays->firstChild())
764  delete ConDisplays->firstChild();
765  while(ConDatasets->firstChild())
766  delete ConDatasets->firstChild();
767  while(ConSources->firstChild())
768  delete ConSources->firstChild();
769  while(ConVerilog->firstChild())
770  delete ConVerilog->firstChild();
771  while(ConVerilogA->firstChild())
772  delete ConVerilogA->firstChild();
773  while(ConOthers->firstChild())
774  delete ConOthers->firstChild();
775  while(ConOctave->firstChild())
776  delete ConOctave->firstChild();
777 
778  int n;
779  // put all files into "Content"-ListView
780  QStringList Elements = QucsWorkDir.entryList("*", QDir::Files, QDir::Name);
781  QStringList::iterator it;
782  QString Str;
783  for(it = Elements.begin(); it != Elements.end(); ++it) {
784  Str = QucsDoc::fileSuffix (*it);
785  if(Str == "sch") {
786  n = testFile(QucsWorkDir.filePath((*it).ascii()));
787  if(n >= 0) {
788  if(n > 0)
789  new QListViewItem(ConSchematics, (*it).ascii(),
790  QString::number(n)+tr("-port"));
791  else new QListViewItem(ConSchematics, (*it).ascii());
792  }
793  }
794  else if(Str == "dpl")
795  new QListViewItem(ConDisplays, (*it).ascii());
796  else if(Str == "dat")
797  new QListViewItem(ConDatasets, (*it).ascii());
798  else if((Str == "vhdl") || (Str == "vhd"))
799  new QListViewItem(ConSources, (*it).ascii());
800  else if(Str == "v")
801  new QListViewItem(ConVerilog, (*it).ascii());
802  else if(Str == "va")
803  new QListViewItem(ConVerilogA, (*it).ascii());
804  else if((Str == "m") || (Str == "oct"))
805  new QListViewItem(ConOctave, (*it).ascii());
806  else
807  new QListViewItem(ConOthers, (*it).ascii());
808  }
809 }
810 
811 // ----------------------------------------------------------
812 // Opens an existing project.
813 void QucsApp::openProject(const QString& Path, const QString& Name)
814 {
815  editText->setHidden(true); // disable text edit of component property
816 
817  if(!closeAllFiles()) return; // close files and ask for saving them
818  new Schematic(this, "");
819  view->drawn = false;
820 
822 
823  QDir ProjDir(QDir::cleanDirPath(Path));
824  if(!ProjDir.exists() || !ProjDir.isReadable()) { // check project directory
825  QMessageBox::critical(this, tr("Error"),
826  tr("Cannot access project directory: ")+Path);
827  return;
828  }
829  QucsWorkDir.setPath(ProjDir.path());
830  octave->adjustDirectory();
831 
832  Content->setColumnText(0,tr("Content of '")+Name+tr("'")); // column text
833  ConSchematics->setOpen(false); // get sure to have it closed
834  ConSchematics->setOpen(true); // also calls readProjectFiles()
835 
836  TabView->setCurrentPage(1); // switch to "Content"-Tab
837  ProjName = Name; // remember the name of project
838 
839  // show name in title of main window
840  setCaption("Qucs " PACKAGE_VERSION + tr(" - Project: ")+Name);
841 }
842 
843 // ----------------------------------------------------------
844 // Is called when the open project menu is called.
845 void QucsApp::slotMenuOpenProject()
846 {
847  QFileDialog *d = new QFileDialog(QucsHomeDir.path());
848  d->setCaption(tr("Choose Project Directory for Opening"));
849  d->setShowHiddenFiles(true);
850  d->setMode(QFileDialog::DirectoryOnly);
851  if(d->exec() != QDialog::Accepted) return;
852 
853  QString s = d->selectedFile();
854  if(s.isEmpty()) return;
855 
856  s = s.left(s.length()-1); // cut off trailing '/'
857  int i = s.findRev('/');
858  if(i > 0) s = s.mid(i+1); // cut out the last subdirectory
859  s.remove("_prj");
860  openProject(d->selectedFile(), s);
861 }
862 
863 // ----------------------------------------------------------
864 // Is called, when "Open Project" button is pressed.
865 void QucsApp::slotProjOpenButt()
866 {
867  editText->setHidden(true); // disable text edit of component property
868 
869  QListBoxItem *item = Projects->selectedItem();
870  if(item) slotOpenProject(item);
871  else QMessageBox::information(this, tr("Info"),
872  tr("No project is selected !"));
873 }
874 
875 // ----------------------------------------------------------
876 // Is called when project is double-clicked to open it.
877 void QucsApp::slotOpenProject(QListBoxItem *item)
878 {
879  openProject(QucsHomeDir.filePath(item->text()+"_prj"), item->text());
880 }
881 
882 // ----------------------------------------------------------
883 // Is called when the close project menu is called.
884 void QucsApp::slotMenuCloseProject()
885 {
886  editText->setHidden(true); // disable text edit of component property
887 
888  if(!closeAllFiles()) return; // close files and ask for saving them
889  new Schematic(this, "");
890  view->drawn = false;
891 
893  setCaption("Qucs " PACKAGE_VERSION + tr(" - Project: "));
894  QucsWorkDir.setPath(QDir::homeDirPath()+QDir::convertSeparators ("/.qucs"));
895  octave->adjustDirectory();
896 
897  Content->setColumnText(0,tr("Content of")); // column text
898  initContentListView();
899 
900  TabView->setCurrentPage(0); // switch to "Projects"-Tab
901  ProjName = "";
902 }
903 
904 // ----------------------------------------------------------
905 bool QucsApp::deleteDirectoryContent(QDir& Dir)
906 {
907  // removes every file, remove("*") does not work
908  QStringList Files = Dir.entryList("*", QDir::Files); // all files
909  QStringList::iterator it;
910  for(it = Files.begin(); it != Files.end(); it++) {
911  if(!Dir.remove(*it)) {
912  QMessageBox::information(this, tr("Info"),
913  tr("Cannot delete file: ")+(*it));
914  return false;
915  }
916  }
917 
918  QDir myDir(Dir);
919  // Remove all directories recursively.
920  Files = Dir.entryList("*", QDir::Dirs);
921  Files.pop_front(); // delete "." from list
922  Files.pop_front(); // delete ".." from list
923  for(it = Files.begin(); it != Files.end(); it++) {
924  myDir.cd(*it);
925  if(!deleteDirectoryContent(myDir))
926  return false;
927  myDir.cdUp();
928  if(!myDir.rmdir(*it)) {
929  QMessageBox::information(this, tr("Info"),
930  tr("Cannot remove directory: ")+(*it));
931  return false;
932  }
933  }
934  return true;
935 }
936 
937 // ----------------------------------------------------------
938 bool QucsApp::deleteProject(const QString& Path, const QString& Name)
939 {
940  editText->setHidden(true); // disable text edit of component property
941 
942  if(Name == ProjName) {
943  QMessageBox::information(this, tr("Info"),
944  tr("Cannot delete an open project !"));
945  return false;
946  }
947 
948  // first ask, if really delete project ?
949  if(QMessageBox::warning(this, tr("Warning"),
950  tr("This will destroy all the project files permanently ! Continue ?"),
951  tr("&Yes"), tr("&No"), 0,1,1)) return false;
952 
953  QDir projDir = QDir(Path);
954  if(!deleteDirectoryContent(projDir))
955  return false;
956 
957  projDir.cdUp(); // leave project directory for deleting
958  if(!projDir.rmdir(Name+"_prj")) {
959  QMessageBox::information(this, tr("Info"),
960  tr("Cannot remove project directory !"));
961  return false;
962  }
963 
964  return true;
965 }
966 
967 // ----------------------------------------------------------
968 // Is called, when "Delete Project" menu is activated.
969 void QucsApp::slotMenuDelProject()
970 {
971  QFileDialog *d = new QFileDialog(QucsHomeDir.path());
972  d->setCaption(tr("Choose Project Directory for Deleting"));
973  d->setShowHiddenFiles(true);
974  d->setMode(QFileDialog::DirectoryOnly);
975  if(d->exec() != QDialog::Accepted) return;
976 
977  QString s = d->selectedFile();
978  if(s.isEmpty()) return;
979 
980  s = s.left(s.length()-1); // cut off trailing '/'
981  int i = s.findRev('/');
982  if(i > 0) s = s.mid(i+1); // cut out the last subdirectory
983  s = s.left(s.length()-4); // remove "_prj" from name
984  deleteProject(d->selectedFile(), s);
985  readProjects(); // re-reads all projects and inserts them into the ListBox
986 }
987 
988 // ----------------------------------------------------------
989 // Is called, when "Delete Project" button is pressed.
990 void QucsApp::slotProjDelButt()
991 {
992  QListBoxItem *item = Projects->selectedItem();
993  if(!item) {
994  QMessageBox::information(this, tr("Info"),
995  tr("No project is selected !"));
996  return;
997  }
998 
999  if(!deleteProject(QucsHomeDir.filePath(item->text()+"_prj"),
1000  item->text())) return;
1001  Projects->removeItem(Projects->currentItem()); // remove from project list
1002 }
1003 
1004 
1005 // ################################################################
1006 // ##### Functions that handle the file operations for the #####
1007 // ##### documents. #####
1008 // ################################################################
1009 
1011 {
1012  statusBar()->message(tr("Creating new schematic..."));
1013  editText->setHidden(true); // disable text edit of component property
1014 
1015  new Schematic(this, "");
1016 
1017  statusBar()->message(tr("Ready."));
1018 }
1019 
1020 // --------------------------------------------------------------
1022 {
1023  statusBar()->message(tr("Creating new text editor..."));
1024  editText->setHidden(true); // disable text edit of component property
1025 
1026  new TextDoc(this, "");
1027 
1028  statusBar()->message(tr("Ready."));
1029 }
1030 
1031 // --------------------------------------------------------------
1032 // Changes to the document "Name". If already open then it goes to it
1033 // directly, otherwise it loads it.
1034 bool QucsApp::gotoPage(const QString& Name)
1035 {
1036  int No = DocumentTab->currentPageIndex();
1037 
1038  int i = 0;
1039  QucsDoc * d = findDoc (Name, &i); // search, if page is already loaded
1040 
1041  if(d) { // open page found ?
1042  d->becomeCurrent(true);
1043  DocumentTab->setCurrentPage(i); // make new document the current
1044  return true;
1045  }
1046 
1047  QFileInfo Info(Name);
1048  if(Info.extension(false) == "sch" || Info.extension(false) == "dpl" ||
1049  Info.extension(false) == "sym")
1050  d = new Schematic(this, Name);
1051  else
1052  d = new TextDoc(this, Name);
1053 
1054  if(!d->load()) { // load document if possible
1055  delete d;
1056  DocumentTab->setCurrentPage(No);
1057  view->drawn = false;
1058  return false;
1059  }
1060  slotChangeView(DocumentTab->currentPage());
1061 
1062  // if only an untitled document was open -> close it
1063  if(getDoc(0)->DocName.isEmpty())
1064  if(!getDoc(0)->DocChanged)
1065  delete DocumentTab->page(0);
1066 
1067  view->drawn = false;
1068  return true;
1069 }
1070 
1071 QString lastDirOpenSave; // to remember last directory and file
1072 
1073 // --------------------------------------------------------------
1075 {
1076  editText->setHidden(true); // disable text edit of component property
1077 
1078  statusBar()->message(tr("Opening file..."));
1079 
1080  QString s = QFileDialog::getOpenFileName(
1081  lastDirOpenSave.isEmpty() ? QString(".") : lastDirOpenSave,
1082  QucsFileFilter, this, 0, tr("Enter a Schematic Name"));
1083 
1084  if(s.isEmpty())
1085  statusBar()->message(tr("Opening aborted"), 2000);
1086  else {
1087  gotoPage(s);
1088  lastDirOpenSave = s; // remember last directory and file
1089  statusBar()->message(tr("Ready."));
1090  }
1091 }
1092 
1093 // --------------------------------------------------------------
1094 bool QucsApp::saveFile(QucsDoc *Doc)
1095 {
1096  if(!Doc)
1097  Doc = getDoc();
1098 
1099  if(Doc->DocName.isEmpty())
1100  return saveAs();
1101 
1102  int Result = Doc->save();
1103  if(Result < 0) return false;
1104 
1105  updatePortNumber(Doc, Result);
1106  return true;
1107 }
1108 
1109 // --------------------------------------------------------------
1111 {
1112  statusBar()->message(tr("Saving file..."));
1113  DocumentTab->blockSignals(true); // no user interaction during that time
1114  editText->setHidden(true); // disable text edit of component property
1115 
1116  if(!saveFile()) {
1117  DocumentTab->blockSignals(false);
1118  statusBar()->message(tr("Saving aborted"), 2000);
1119  statusBar()->message(tr("Ready."));
1120  return;
1121  }
1122 
1123  DocumentTab->blockSignals(false);
1124  statusBar()->message(tr("Ready."));
1125 }
1126 
1127 // --------------------------------------------------------------
1128 bool QucsApp::saveAs()
1129 {
1130  QWidget *w = DocumentTab->currentPage();
1131  QucsDoc *Doc = getDoc();
1132 
1133  int n = -1;
1134  bool intoView = true;
1135  QString s, Filter;
1136  QFileInfo Info;
1137  while(true) {
1138  intoView = true;
1139  s = Doc->DocName;
1140  Info.setFile(s);
1141  if(s.isEmpty()) { // which is default directory ?
1142  if(ProjName.isEmpty()) {
1143  if(lastDirOpenSave.isEmpty()) s = QDir::currentDirPath();
1144  else s = lastDirOpenSave;
1145  }
1146  else s = QucsWorkDir.path();
1147  }
1148 
1149  // list of known file extensions
1150  QString ext = "vhdl;vhd;v;va;sch;dpl;m;oct";
1151  QStringList extlist = QStringList::split (';', ext);
1152 
1153  if(isTextDocument (w))
1154  Filter = tr("VHDL Sources")+" (*.vhdl *.vhd);;" +
1155  tr("Verilog Sources")+" (*.v);;"+
1156  tr("Verilog-A Sources")+" (*.va);;"+
1157  tr("Octave Scripts")+" (*.m *.oct);;"+
1158  tr("Any File")+" (*)";
1159  else
1160  Filter = QucsFileFilter;
1161  s = QFileDialog::getSaveFileName(s, Filter,
1162  this, "", tr("Enter a Document Name"));
1163  if(s.isEmpty()) return false;
1164  Info.setFile(s); // try to guess the best extension ...
1165  ext = Info.extension(false);
1166  if(ext.isEmpty() ||
1167  !extlist.contains(ext)) { // ... if no one was specified or is unknown
1168  if(isTextDocument (w))
1169  s += ".vhdl";
1170  else
1171  s += ".sch";
1172  }
1173 
1174  Info.setFile(s);
1175  if(QFile::exists(s)) {
1176  n = QMessageBox::warning(this, tr("Warning"),
1177  tr("The file '")+Info.fileName()+tr("' already exists!\n")+
1178  tr("Saving will overwrite the old one! Continue?"),
1179  tr("No"), tr("Yes"), tr("Cancel"));
1180  if(n == 2) return false; // cancel
1181  if(n == 0) continue;
1182  intoView = false; // file already exists
1183  }
1184 
1185  // search, if document is open
1186  QucsDoc * d = findDoc (s);
1187  if(d) {
1188  QMessageBox::information(this, tr("Info"),
1189  tr("Cannot overwrite an open document"));
1190  return false;
1191  }
1192 
1193  break;
1194  }
1195  Doc->setName(s);
1196  lastDirOpenSave = Info.dirPath(true); // remember last directory and file
1197 
1198  if(intoView) { // insert new name in Content ListView ?
1199  if(Info.dirPath(true) == QucsWorkDir.absPath())
1200  if(!ProjName.isEmpty()) {
1201  s = Info.fileName(); // remove path from file name
1202  QString ext = Info.extension (false);
1203  if(ext == "sch")
1204  Content->setSelected(new QListViewItem(ConSchematics, s), true);
1205  else if(ext == "dpl")
1206  Content->setSelected(new QListViewItem(ConDisplays, s), true);
1207  else if(ext == "dat")
1208  Content->setSelected(new QListViewItem(ConDatasets, s), true);
1209  else if((ext == "vhdl") || (ext == "vhd"))
1210  Content->setSelected(new QListViewItem(ConSources, s), true);
1211  else if(ext == "v")
1212  Content->setSelected(new QListViewItem(ConVerilog, s), true);
1213  else if(ext == "va")
1214  Content->setSelected(new QListViewItem(ConVerilogA, s), true);
1215  else if(ext == "m" || ext == "oct")
1216  Content->setSelected(new QListViewItem(ConOctave, s), true);
1217  else
1218  Content->setSelected(new QListViewItem(ConOthers, s), true);
1219  }
1220  }
1221 
1222  n = Doc->save(); // SAVE
1223  if(n < 0) return false;
1224 
1225  updatePortNumber(Doc, n);
1226  return true;
1227 }
1228 
1229 // --------------------------------------------------------------
1231 {
1232  statusBar()->message(tr("Saving file under new filename..."));
1233  DocumentTab->blockSignals(true); // no user interaction during the time
1234  editText->setHidden(true); // disable text edit of component property
1235 
1236  if(!saveAs()) {
1237  DocumentTab->blockSignals(false);
1238  statusBar()->message(tr("Saving aborted"), 3000);
1239  statusBar()->message(tr("Ready."));
1240  return;
1241  }
1242 
1243  DocumentTab->blockSignals(false);
1244  statusBar()->message(tr("Ready."));
1245 }
1246 
1247 
1248 // --------------------------------------------------------------
1250 {
1251  statusBar()->message(tr("Saving all files..."));
1252  editText->setHidden(true); // disable text edit of component property
1253  DocumentTab->blockSignals(true); // no user interaction during the time
1254 
1255  int No=0;
1256  QucsDoc *Doc; // search, if page is already loaded
1257  while((Doc=getDoc(No++)) != 0) {
1258  if(Doc->DocName.isEmpty()) // make document the current ?
1259  DocumentTab->setCurrentPage(No-1);
1260  saveFile(Doc);
1261  }
1262 
1263  DocumentTab->blockSignals(false);
1264  // Call update() to update subcircuit symbols in current document.
1265  ((QScrollView*)DocumentTab->currentPage())->viewport()->update();
1266  view->drawn = false;
1267  statusBar()->message(tr("Ready."));
1268 }
1269 
1270 // --------------------------------------------------------------
1272 {
1273  statusBar()->message(tr("Closing file..."));
1274  editText->setHidden(true); // disable text edit of component property
1275 
1276  QucsDoc *Doc = getDoc();
1277  if(Doc->DocChanged) {
1278  switch(QMessageBox::warning(this,tr("Closing Qucs document"),
1279  tr("The document contains unsaved changes!\n")+
1280  tr("Do you want to save the changes before closing?"),
1281  tr("&Save"), tr("&Discard"), tr("Cancel"), 0, 2)) {
1282  case 0 : slotFileSave();
1283  break;
1284  case 2 : return;
1285  }
1286  }
1287 
1288  delete Doc;
1289 
1290  if(DocumentTab->count() < 1) // if no document left, create an untitled
1291  new Schematic(this, "");
1292 
1293  statusBar()->message(tr("Ready."));
1294 }
1295 
1296 // --------------------------------------------------------------
1298 {
1299  SaveDialog *sd = new SaveDialog(this);
1300  sd->setApp(this);
1301  for(int i=0; i < DocumentTab->count(); ++i) {
1302  QucsDoc *doc = getDoc(i);
1303  if(doc->DocChanged)
1304  sd->addUnsavedDoc(doc);
1305  }
1306  int Result = SaveDialog::DontSave;
1307  if(!sd->isEmpty())
1308  Result = sd->exec();
1309  delete sd;
1310 
1311  if(Result == SaveDialog::AbortClosing)
1312  return false;
1313 
1314  QucsDoc *doc = 0;
1315  while((doc = getDoc()) != 0)
1316  delete doc;
1317 
1318  switchEditMode(true); // set schematic edit mode
1319  return true;
1320 }
1321 
1322 // --------------------------------------------------------------
1323 // Is called when another document is selected via the TabBar.
1324 void QucsApp::slotChangeView(QWidget *w)
1325 {
1326  editText->setHidden (true); // disable text edit of component property
1327 
1328  QucsDoc * Doc;
1329 
1330  // for text documents
1331  if (isTextDocument (w)) {
1332  TextDoc *d = (TextDoc*)w;
1333  Doc = (QucsDoc*)d;
1334  // update menu entries, etc. if neccesary
1335  if(mainAccel->isEnabled())
1336  switchSchematicDoc (false);
1337  }
1338  // for schematic documents
1339  else {
1340  Schematic *d = (Schematic*)w;
1341  Doc = (QucsDoc*)d;
1342  // already in schematic?
1343  if(mainAccel->isEnabled()) {
1344  // which mode: schematic or symbol editor ?
1345  if((CompChoose->count() > 1) == d->symbolMode)
1346  changeSchematicSymbolMode (d);
1347  }
1348  else {
1349  switchSchematicDoc(true);
1350  changeSchematicSymbolMode(d);
1351  }
1352  }
1353 
1354  Doc->becomeCurrent(true);
1355  view->drawn = false;
1356 
1357  if(!HierarchyHistory.isEmpty())
1358  if(*(HierarchyHistory.getLast()) != "*") {
1359  HierarchyHistory.clear(); // no subcircuit history anymore
1360  popH->setEnabled(false);
1361  }
1362 }
1363 
1364 // --------------------------------------------------------------
1365 // Changes to the next document in the TabBar.
1366 void QucsApp::slotNextTab()
1367 {
1368  int No = DocumentTab->currentPageIndex() + 1;
1369  if(No >= DocumentTab->count())
1370  No = 0;
1371 
1372  // make new document the current (calls "slotChangeView(int)" indirectly)
1373  DocumentTab->setCurrentPage(No);
1374  view->drawn = false;
1375 }
1376 
1377 // --------------------------------------------------------------
1379 {
1380  editText->setHidden (true); // disable text edit of component property
1381 
1382  QWidget * w = DocumentTab->currentPage ();
1383  if (isTextDocument (w)) {
1384  QucsDoc * Doc = (QucsDoc *) ((TextDoc *) w);
1385  QString ext = Doc->fileSuffix ();
1386  // Octave properties
1387  if (ext == "m" || ext == "oct") {
1388  }
1389  // Verilog-A properties
1390  else if (ext == "va") {
1391  VASettingsDialog * d = new VASettingsDialog ((TextDoc *) w);
1392  d->exec ();
1393  }
1394  // VHDL and Verilog-HDL properties
1395  else {
1396  DigiSettingsDialog * d = new DigiSettingsDialog ((TextDoc *) w);
1397  d->exec ();
1398  }
1399  }
1400  // schematic properties
1401  else {
1402  SettingsDialog * d = new SettingsDialog ((Schematic *) w);
1403  d->exec ();
1404  }
1405  view->drawn = false;
1406 }
1407 
1408 // --------------------------------------------------------------
1410 {
1411  editText->setHidden(true); // disable text edit of component property
1412 
1413  QucsSettingsDialog *d = new QucsSettingsDialog(this);
1414  d->exec();
1415  view->drawn = false;
1416 }
1417 
1418 
1419 // --------------------------------------------------------------
1420 void QucsApp::updatePortNumber(QucsDoc *currDoc, int No)
1421 {
1422  if(No<0) return;
1423 
1424  QString pathName = currDoc->DocName;
1425  QString ext = currDoc->fileSuffix ();
1426  QFileInfo Info (pathName);
1427  QString Model, File, Name = Info.fileName();
1428 
1429  if (ext == "sch") {
1430  Model = "Sub";
1431 
1432  // enter new port number into ListView
1433  QListViewItem *p;
1434  for(p = ConSchematics->firstChild(); p!=0; p = p->nextSibling()) {
1435  if(p->text(0) == Name) {
1436  if(No == 0) p->setText(1,"");
1437  else p->setText(1,QString::number(No)+tr("-port"));
1438  break;
1439  }
1440  }
1441  }
1442  else if (ext == "vhdl" || ext == "vhd") {
1443  Model = "VHDL";
1444  }
1445  else if (ext == "v") {
1446  Model = "Verilog";
1447  }
1448 
1449  // update all occurencies of subcircuit in all open documents
1450  No = 0;
1451  QWidget *w;
1452  Component *pc_tmp;
1453  while((w=DocumentTab->page(No++)) != 0) {
1454  if(isTextDocument (w)) continue;
1455 
1456  // start from the last to omit re-appended components
1457  Schematic *Doc = (Schematic*)w;
1458  for(Component *pc=Doc->Components->last(); pc!=0; ) {
1459  if(pc->Model == Model) {
1460  File = pc->Props.getFirst()->Value;
1461  if((File == pathName) || (File == Name)) {
1462  pc_tmp = Doc->Components->prev();
1463  Doc->recreateComponent(pc); // delete and re-append component
1464  if(!pc_tmp) break;
1465  Doc->Components->findRef(pc_tmp);
1466  pc = Doc->Components->current();
1467  continue;
1468  }
1469  }
1470  pc = Doc->Components->prev();
1471  }
1472  }
1473 }
1474 
1475 
1476 // --------------------------------------------------------------
1477 void QucsApp::printCurrentDocument(bool fitToPage)
1478 {
1479  statusBar()->message(tr("Printing..."));
1480  editText->setHidden(true); // disable text edit of component property
1481 
1482  if(isTextDocument (DocumentTab->currentPage()))
1483  Printer->setOrientation(QPrinter::Portrait);
1484  else
1485  Printer->setOrientation(QPrinter::Landscape);
1486 
1487  //Printer->setPrintRange(QPrinter::AllPages);
1488 
1489  if(Printer->setup(this)) { // printer dialog
1490 
1491  QPainter Painter(Printer);
1492  if(!Painter.device()) // valid device available ?
1493  goto Error;
1494 
1495  for(int z=Printer->numCopies(); z>0 ; z--) {
1496  if(Printer->aborted())
1497  break;
1498 
1499  getDoc()->print(Printer, &Painter,
1500  Printer->printRange() == QPrinter::AllPages, fitToPage);
1501  if(z > 1)
1502  if(!Printer->newPage())
1503  goto Error;
1504  }
1505  }
1506 
1507  statusBar()->message(tr("Ready."));
1508  return;
1509 
1510 Error:
1511  statusBar()->message(tr("Printer Error."));
1512 }
1513 
1514 // --------------------------------------------------------------
1516 {
1517  printCurrentDocument(false);
1518 }
1519 
1520 // --------------------------------------------------------------
1521 // Fit printed content to page size.
1523 {
1524  printCurrentDocument(true);
1525 }
1526 
1527 // --------------------------------------------------------------------
1528 // Exits the application.
1530 {
1531  statusBar()->message(tr("Exiting application..."));
1532  editText->setHidden(true); // disable text edit of component property
1533 
1534  int exit = QMessageBox::information(this,
1535  tr("Quit..."), tr("Do you really want to quit?"),
1536  tr("Yes"), tr("No"));
1537 
1538  if(exit == 0)
1539  if(closeAllFiles()) {
1540  emit signalKillEmAll(); // kill all subprocesses
1541  qApp->quit();
1542  }
1543 
1544  statusBar()->message(tr("Ready."));
1545 }
1546 
1547 //-----------------------------------------------------------------
1548 // To get all close events.
1549 void QucsApp::closeEvent(QCloseEvent* Event)
1550 {
1551  if(closeAllFiles()) {
1552  emit signalKillEmAll(); // kill all subprocesses
1553  Event->accept();
1554  qApp->quit();
1555  }
1556  else
1557  Event->ignore();
1558 }
1559 
1560 // --------------------------------------------------------------------
1562 {
1563  statusBar()->message(tr("Cutting selection..."));
1564 
1565  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
1566  if(isTextDocument (Doc)) {
1567  ((TextDoc*)Doc)->viewport()->setFocus();
1568  ((TextDoc*)Doc)->cut();
1569  return;
1570  }
1571 
1572  editText->setHidden(true); // disable text edit of component property
1573  QClipboard *cb = QApplication::clipboard(); // get system clipboard
1574 
1575  QString s = Doc->copySelected(true);
1576  if(!s.isEmpty()) {
1577  cb->setText(s, QClipboard::Clipboard);
1578  Doc->viewport()->update();
1579  }
1580 
1581  statusBar()->message(tr("Ready."));
1582 }
1583 
1584 // --------------------------------------------------------------------
1586 {
1587  statusBar()->message(tr("Copying selection to clipboard..."));
1588 
1589  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
1590  if(isTextDocument (Doc)) {
1591  ((TextDoc*)Doc)->viewport()->setFocus();
1592  ((TextDoc*)Doc)->copy();
1593  return;
1594  }
1595 
1596  editText->setHidden(true); // disable text edit of component property
1597  QClipboard *cb = QApplication::clipboard(); // get system clipboard
1598 
1599  QString s = Doc->copySelected(false);
1600  if(!s.isEmpty())
1601  cb->setText(s, QClipboard::Clipboard);
1602 
1603  statusBar()->message(tr("Ready."));
1604 }
1605 
1606 // --------------------------------------------------------------------
1607 // Is called when the toolbar button is pressed to go into a subcircuit.
1609 {
1610  editText->setHidden(true); // disable text edit of component property
1611 
1612  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
1613  Component *pc = Doc->searchSelSubcircuit();
1614  if(pc == 0) return;
1615 
1616  QString *ps = new QString("*");
1617  HierarchyHistory.append(ps); // sign not to clear HierarchyHistory
1618 
1619  QString s = QucsWorkDir.filePath(pc->Props.getFirst()->Value);
1620  if(!gotoPage(s)) {
1621  HierarchyHistory.remove();
1622  return;
1623  }
1624 
1625  *(HierarchyHistory.getLast()) = Doc->DocName; // remember for the way back
1626  popH->setEnabled(true);
1627 }
1628 
1629 // --------------------------------------------------------------------
1630 // Is called when the toolbar button is pressed to leave a subcircuit.
1632 {
1633  editText->setHidden(true); // disable text edit of component property
1634 
1635  if(HierarchyHistory.count() == 0) return;
1636 
1637  QString Doc = *(HierarchyHistory.getLast());
1638  *(HierarchyHistory.last()) = "*"; // sign not to clear HierarchyHistory
1639 
1640  if(!gotoPage(Doc)) {
1641  *(HierarchyHistory.getLast()) = Doc;
1642  return;
1643  }
1644 
1645  HierarchyHistory.remove();
1646  if(HierarchyHistory.count() == 0)
1647  popH->setEnabled(false);
1648 }
1649 
1650 // --------------------------------------------------------------
1652 {
1653  editText->setHidden(true); // disable text edit of component property
1654  getDoc()->showAll();
1655 }
1656 
1657 // -----------------------------------------------------------
1658 // Sets the scale factor to 1.
1660 {
1661  editText->setHidden(true); // disable text edit of component property
1662  getDoc()->showNoZoom();
1663 }
1664 
1665 // -----------------------------------------------------------
1667 {
1668  editText->setHidden(true); // disable text edit of component property
1669  getDoc()->zoomBy(0.7f);
1670 }
1671 
1672 // -----------------------------------------------------------------------
1673 // Is called when the simulate toolbar button is pressed.
1674 void QucsApp::slotSimulate()
1675 {
1676  editText->setHidden(true); // disable text edit of component property
1677 
1678  QucsDoc *Doc;
1679  QWidget *w = DocumentTab->currentPage();
1680  if(isTextDocument (w)) {
1681  Doc = (QucsDoc*)((TextDoc*)w);
1682  if(Doc->SimTime.isEmpty() && ((TextDoc*)Doc)->simulation) {
1684  if(d->exec() == QDialog::Rejected)
1685  return;
1686  }
1687  }
1688  else
1689  Doc = (QucsDoc*)((Schematic*)w);
1690 
1691  if(Doc->DocName.isEmpty()) // if document 'untitled' ...
1692  if(!saveAs()) return; // ... save schematic before
1693 
1694  // Perhaps the document was modified from another program ?
1695  QFileInfo Info(Doc->DocName);
1696  if(Doc->lastSaved.isValid()) {
1697  if(Doc->lastSaved < Info.lastModified()) {
1698  int No = QMessageBox::warning(this, tr("Warning"),
1699  tr("The document was modified by another program !") + '\n' +
1700  tr("Do you want to reload or keep this version ?"),
1701  tr("Reload"), tr("Keep it"));
1702  if(No == 0)
1703  Doc->load();
1704  }
1705  }
1706 
1708 
1709  if(Info.extension(false) == "m" || Info.extension(false) == "oct") {
1710  // It is an Octave script.
1711  if(Doc->DocChanged)
1712  Doc->save();
1713  slotViewOctaveDock(true);
1714  octave->runOctaveScript(Doc->DocName);
1715  return;
1716  }
1717 
1718  SimMessage *sim = new SimMessage(w, this);
1719  // disconnect is automatically performed, if one of the involved objects
1720  // is destroyed !
1721  connect(sim, SIGNAL(SimulationEnded(int, SimMessage*)), this,
1722  SLOT(slotAfterSimulation(int, SimMessage*)));
1723  connect(sim, SIGNAL(displayDataPage(QString&, QString&)),
1724  this, SLOT(slotChangePage(QString&, QString&)));
1725 
1726  sim->show();
1727  if(!sim->startProcess()) return;
1728 
1729  // to kill it before qucs ends
1730  connect(this, SIGNAL(signalKillEmAll()), sim, SLOT(slotClose()));
1731 }
1732 
1733 // ------------------------------------------------------------------------
1734 // Is called after the simulation process terminates.
1735 void QucsApp::slotAfterSimulation(int Status, SimMessage *sim)
1736 {
1737  if(Status != 0) return; // errors ocurred ?
1738 
1739  if(sim->ErrText->lines() > 1) // were there warnings ?
1740  slotShowWarnings();
1741 
1742  int i=0;
1743  QWidget *w; // search, if page is still open
1744  while((w=DocumentTab->page(i++)) != 0)
1745  if(w == sim->DocWidget)
1746  break;
1747 
1748  if(sim->showBias == 0) { // paint dc bias into schematic ?
1749  sim->slotClose(); // close and delete simulation window
1750  if(w) { // schematic still open ?
1751  SweepDialog *Dia = new SweepDialog((Schematic*)sim->DocWidget);
1752  Dia->show();
1753  }
1754  }
1755  else {
1756  if(sim->SimRunScript) {
1757  // run script
1758  octave->startOctave();
1759  octave->runOctaveScript(sim->Script);
1760  }
1761  if(sim->SimOpenDpl) {
1762  // switch to data display
1763  if(sim->DataDisplay.right(2) == ".m" ||
1764  sim->DataDisplay.right(4) == ".oct") { // Is it an Octave script?
1765  octave->startOctave();
1766  octave->runOctaveScript(sim->DataDisplay);
1767  }
1768  else
1769  slotChangePage(sim->DocName, sim->DataDisplay);
1770  sim->slotClose(); // close and delete simulation window
1771  }
1772  else
1773  if(w) if(!isTextDocument (sim->DocWidget))
1774  // load recent simulation data (if document is still open)
1775  ((Schematic*)sim->DocWidget)->reloadGraphs();
1776  }
1777 
1778  if(!isTextDocument (sim->DocWidget))
1779  ((Schematic*)sim->DocWidget)->viewport()->update();
1780 
1781  // put all dataset files into "Content"-ListView (update)
1782 /* QStringList Elements = ProjDir.entryList("*.dat", QDir::Files, QDir::Name);
1783  for(it = Elements.begin(); it != Elements.end(); ++it)
1784  new QListViewItem(ConDatasets, (*it).ascii());*/
1785 }
1786 
1787 // ------------------------------------------------------------------------
1788 void QucsApp::slotDCbias()
1789 {
1790  getDoc()->showBias = 0;
1791  slotSimulate();
1792 }
1793 
1794 // ------------------------------------------------------------------------
1795 // Changes to the corresponding data display page or vice versa.
1796 void QucsApp::slotChangePage(QString& DocName, QString& DataDisplay)
1797 {
1798  if(DataDisplay.isEmpty()) return;
1799 
1800  QFileInfo Info(DocName);
1801  QString Name = Info.dirPath() + QDir::separator() + DataDisplay;
1802 
1803  QWidget *w = DocumentTab->currentPage();
1804 
1805  int z = 0; // search, if page is already loaded
1806  QucsDoc * d = findDoc (Name, &z);
1807 
1808  if(d)
1809  DocumentTab->setCurrentPage(z);
1810  else { // no open page found ?
1811  QString ext = QucsDoc::fileSuffix (DataDisplay);
1812  if (ext != "vhd" && ext != "vhdl" && ext != "v" && ext != "va" &&
1813  ext != "oct" && ext != "m")
1814  d = new Schematic (this, Name);
1815  else
1816  d = new TextDoc (this, Name);
1817 
1818  QFile file(Name);
1819  if(file.open(IO_ReadOnly)) { // try to load document
1820  file.close();
1821  if(!d->load()) {
1822  delete d;
1823  view->drawn = false;
1824  return;
1825  }
1826  }
1827  else {
1828  if(file.open(IO_ReadWrite)) { // if document doesn't exist, create
1829  new QListViewItem(ConDisplays, DataDisplay); // add new name
1830  d->DataDisplay = Info.fileName();
1831  }
1832  else {
1833  QMessageBox::critical(this, tr("Error"), tr("Cannot create ")+Name);
1834  return;
1835  }
1836  file.close();
1837  }
1838 
1839  d->becomeCurrent(true);
1840  }
1841 
1842 
1843  if(DocumentTab->currentPage() == w) // if page not ...
1844  if(!isTextDocument (w))
1845  ((Schematic*)w)->reloadGraphs(); // ... changes, reload here !
1846 
1847  TabView->setCurrentPage (2); // switch to "Component"-Tab
1848  if (Name.right(4) == ".dpl") {
1849  int i = Category::getModulesNr (QObject::tr("diagrams"));
1850  CompChoose->setCurrentItem (i); // switch to diagrams
1851  slotSetCompView (i);
1852  }
1853 }
1854 
1855 // -------------------------------------------------------------------
1856 // Changes to the data display of current page.
1858 {
1859  QucsDoc *d = getDoc();
1860  if(d->DataDisplay.isEmpty()) {
1861  QMessageBox::critical(this, tr("Error"), tr("No page set !"));
1862  return;
1863  }
1864 
1865  if(d->DocName.right(2) == ".m" ||
1866  d->DocName.right(4) == ".oct")
1867  slotViewOctaveDock(true);
1868  else
1869  slotChangePage(d->DocName, d->DataDisplay);
1870 }
1871 
1872 // -------------------------------------------------------------------
1873 // Is called when a double-click is made in the content ListView.
1874 void QucsApp::slotOpenContent(QListViewItem *item)
1875 {
1876  editText->setHidden(true); // disable text edit of component property
1877 
1878  if(item == 0) return; // no item was double clicked
1879  if(item->parent() == 0) return; // no document, but item "schematic", ...
1880 
1881 /*
1882  QucsWorkDir.setPath(QucsHomeDir.path());
1883  QString p = ProjName+"_prj";
1884  if(!QucsWorkDir.cd(p)) {
1885  QMessageBox::critical(this, tr("Error"),
1886  tr("Cannot access project directory: ")+
1887  QucsWorkDir.path()+QDir::separator()+p);
1888  return;
1889  }*/
1890 
1891  QFileInfo Info(QucsWorkDir.filePath(item->text(0)));
1892  QString Suffix = Info.extension(false);
1893 
1894  if (Suffix == "sch" || Suffix == "dpl" || Suffix == "vhdl" ||
1895  Suffix == "v" || Suffix == "va" ||
1896  Suffix == "m" || Suffix == "oct") {
1897  gotoPage(Info.absFilePath());
1898 
1899  if(item->text(1).isEmpty()) // is subcircuit ?
1900  if(Suffix == "sch") return;
1901 
1902  select->blockSignals(true); // switch on the 'select' action ...
1903  select->setOn(true);
1904  select->blockSignals(false);
1905 
1906  activeAction = select;
1907  MouseMoveAction = 0;
1911  return;
1912  }
1913 
1914  if(Suffix == "dat") {
1915  editFile(Info.absFilePath()); // open datasets with text editor
1916  return;
1917  }
1918 
1919 
1920  // File is no Qucs file, so go through list and search a user
1921  // defined program to open it.
1922  QStringList com;
1923  QStringList::Iterator it = QucsSettings.FileTypes.begin();
1924  while(it != QucsSettings.FileTypes.end()) {
1925  if(Suffix == (*it).section('/',0,0)) {
1926  com = QStringList::split(" ", (*it).section('/',1,1));
1927  com << Info.absFilePath();
1928  QProcess *Program = new QProcess(com);
1929  Program->setCommunication(0);
1930  if(!Program->start()) {
1931  QMessageBox::critical(this, tr("Error"),
1932  tr("Cannot start \"%1\"!").arg(Info.absFilePath()));
1933  delete Program;
1934  }
1935  return;
1936  }
1937  it++;
1938  }
1939 
1940  // If no appropriate program was found, open as text file.
1941  editFile(Info.absFilePath()); // open datasets with text editor
1942 }
1943 
1944 // ---------------------------------------------------------
1945 // Is called when the mouse is clicked within the Content QListView.
1946 void QucsApp::slotSelectSubcircuit(QListViewItem *item)
1947 {
1948  editText->setHidden(true); // disable text edit of component property
1949 
1950  if(item == 0) { // mouse button pressed not over an item ?
1951  Content->clearSelection(); // deselect component in ListView
1952  return;
1953  }
1954 
1955 
1956  bool isVHDL = false;
1957  bool isVerilog = false;
1958  if(item->parent() == 0) return;
1959  if(item->parent()->text(0) == tr("Schematics")) {
1960  if(item->text(1).isEmpty())
1961  return; // return, if not a subcircuit
1962  }
1963  else if(item->parent()->text(0) == tr("VHDL"))
1964  isVHDL = true;
1965  else if(item->parent()->text(0) == tr("Verilog"))
1966  isVerilog = true;
1967  else
1968  return;
1969 
1970  // delete previously selected elements
1971  if(view->selElem != 0) delete view->selElem;
1972  view->selElem = 0;
1973 
1974  // toggle last toolbar button off
1975  if(activeAction) {
1976  activeAction->blockSignals(true); // do not call toggle slot
1977  activeAction->setOn(false); // set last toolbar button off
1978  activeAction->blockSignals(false);
1979  }
1980  activeAction = 0;
1981 
1982  Component *Comp;
1983  if(isVHDL)
1984  Comp = new VHDL_File();
1985  else if(isVerilog)
1986  Comp = new Verilog_File();
1987  else
1988  Comp = new Subcircuit();
1989  Comp->Props.first()->Value = item->text(0);
1990  Comp->recreate(0);
1991  view->selElem = Comp;
1992 
1993  if(view->drawn)
1994  ((QScrollView*)DocumentTab->currentPage())->viewport()->update();
1995  view->drawn = false;
1998  MouseReleaseAction = 0;
2000 }
2001 
2002 // ---------------------------------------------------------
2003 // Is called when one of the Content ListView parents was expanded
2004 // to show the files. It re-reads all files.
2005 void QucsApp::slotExpandContentList(QListViewItem*)
2006 {
2007  readProjectFiles();
2008 }
2009 
2010 // ---------------------------------------------------------
2011 // This function is called if the document type changes, i.e.
2012 // from schematic to text document or vice versa.
2013 void QucsApp::switchSchematicDoc (bool SchematicMode)
2014 {
2015  mainAccel->setEnabled (SchematicMode);
2016 
2017  // text document
2018  if (!SchematicMode) {
2019  if (activeAction) {
2020  activeAction->blockSignals (true); // do not call toggle slot
2021  activeAction->setOn (false); // set last toolbar button off
2022  activeAction->blockSignals (false);
2023  }
2024  activeAction = select;
2025  select->blockSignals (true);
2026  select->setOn (true);
2027  select->blockSignals (false);
2028  }
2029  // schematic document
2030  else {
2031  MouseMoveAction = 0;
2035  }
2036 
2037  selectMarker->setEnabled (SchematicMode);
2038  alignTop->setEnabled (SchematicMode);
2039  alignBottom->setEnabled (SchematicMode);
2040  alignLeft->setEnabled (SchematicMode);
2041  alignRight->setEnabled (SchematicMode);
2042  centerHor->setEnabled (SchematicMode);
2043  centerVert->setEnabled (SchematicMode);
2044  distrHor->setEnabled (SchematicMode);
2045  distrVert->setEnabled (SchematicMode);
2046  onGrid->setEnabled (SchematicMode);
2047  moveText->setEnabled (SchematicMode);
2048  filePrintFit->setEnabled (SchematicMode);
2049  editRotate->setEnabled (SchematicMode);
2050  editMirror->setEnabled (SchematicMode);
2051  editMirrorY->setEnabled (SchematicMode);
2052  intoH->setEnabled (SchematicMode);
2053  popH->setEnabled (SchematicMode);
2054  dcbias->setEnabled (SchematicMode);
2055  insWire->setEnabled (SchematicMode);
2056  insLabel->setEnabled (SchematicMode);
2057  insPort->setEnabled (SchematicMode);
2058  insGround->setEnabled (SchematicMode);
2059  insEquation->setEnabled (SchematicMode);
2060  setMarker->setEnabled (SchematicMode);
2061 
2062  editFind->setEnabled (!SchematicMode);
2063  editFindAgain->setEnabled (!SchematicMode);
2064  insEntity->setEnabled (!SchematicMode);
2065 }
2066 
2067 // ---------------------------------------------------------
2068 void QucsApp::switchEditMode(bool SchematicMode)
2069 {
2070  fillComboBox(SchematicMode);
2071  slotSetCompView(0);
2072 
2073  intoH->setEnabled(SchematicMode);
2074  popH->setEnabled(SchematicMode);
2075  editActivate->setEnabled(SchematicMode);
2076  changeProps->setEnabled(SchematicMode);
2077  insEquation->setEnabled(SchematicMode);
2078  insGround->setEnabled(SchematicMode);
2079  insPort->setEnabled(SchematicMode);
2080  insWire->setEnabled(SchematicMode);
2081  insLabel->setEnabled(SchematicMode);
2082  setMarker->setEnabled(SchematicMode);
2083  selectMarker->setEnabled(SchematicMode);
2084  simulate->setEnabled(SchematicMode);
2085 }
2086 
2087 // ---------------------------------------------------------
2088 void QucsApp::changeSchematicSymbolMode(Schematic *Doc)
2089 {
2090  if(Doc->symbolMode) {
2091  // go into select modus to avoid placing a forbidden element
2092  select->setOn(true);
2093 
2094  switchEditMode(false);
2095  }
2096  else
2097  switchEditMode(true);
2098 }
2099 
2100 // ---------------------------------------------------------
2101 bool QucsApp::isTextDocument(QWidget *w) {
2102  if (w->inherits("QTextEdit"))
2103  return true;
2104  return false;
2105 }
2106 
2107 // ---------------------------------------------------------
2108 // Is called if the "symEdit" action is activated, i.e. if the user
2109 // switches between the two painting mode: Schematic and (subcircuit)
2110 // symbol.
2112 {
2113  QWidget *w = DocumentTab->currentPage();
2114 
2115  // in a text document (e.g. VHDL)
2116  if (isTextDocument (w)) {
2117  TextDoc *TDoc = (TextDoc*)w;
2118  // set 'DataDisplay' document of text file to symbol file
2119  QFileInfo Info(TDoc->DocName);
2120  QString sym = Info.baseName(true)+".sym";
2121  TDoc->DataDisplay = sym;
2122 
2123  // symbol file already loaded?
2124  int paint_mode = 0;
2125  if (!findDoc (QucsWorkDir.filePath(sym)))
2126  paint_mode = 1;
2127 
2128  // change current page to appropriate symbol file
2129  slotChangePage(TDoc->DocName,TDoc->DataDisplay);
2130 
2131  // set 'DataDisplay' document of symbol file to original text file
2132  Schematic *SDoc = (Schematic*)DocumentTab->currentPage();
2133  SDoc->DataDisplay = Info.fileName();
2134 
2135  // change into symbol mode
2136  if (paint_mode) // but only switch coordinates if newly loaded
2137  SDoc->switchPaintMode();
2138  SDoc->symbolMode = true;
2139  changeSchematicSymbolMode(SDoc);
2140  SDoc->becomeCurrent(true);
2141  SDoc->viewport()->update();
2142  view->drawn = false;
2143  }
2144  // in a normal schematic, data display or symbol file
2145  else {
2146  Schematic *SDoc = (Schematic*)w;
2147  // in a symbol file
2148  if(SDoc->DocName.right(4) == ".sym") {
2149  slotChangePage(SDoc->DocName, SDoc->DataDisplay);
2150  }
2151  // in a normal schematic
2152  else {
2153  editText->setHidden(true); // disable text edit of component property
2154  SDoc->switchPaintMode(); // twist the view coordinates
2155  changeSchematicSymbolMode(SDoc);
2156  SDoc->becomeCurrent(true);
2157  SDoc->viewport()->update();
2158  view->drawn = false;
2159  }
2160  }
2161 }
2162 
2163 // -----------------------------------------------------------
2165 {
2166  if(!view->focusElement) return;
2167  if(view->focusElement->Type != isMarker) return;
2168  Marker *pm = (Marker*)view->focusElement;
2169 
2170 // double Z0 = 50.0;
2171  QString Var = pm->pGraph->Var;
2172  double Imag = pm->VarPos[pm->nVarPos+1];
2173  if(Var == "Sopt") // noise matching ?
2174  Imag *= -1.0;
2175 
2176  MatchDialog *Dia = new MatchDialog(this);
2177  Dia->TwoCheck->setChecked(false);
2178  Dia->TwoCheck->setEnabled(false);
2179 // Dia->Ref1Edit->setText(QString::number(Z0));
2180  Dia->S11magEdit->setText(QString::number(pm->VarPos[pm->nVarPos]));
2181  Dia->S11degEdit->setText(QString::number(Imag));
2182  Dia->setFrequency(pm->VarPos[0]);
2183 
2184  slotToPage();
2185  if(Dia->exec() != QDialog::Accepted)
2186  return;
2187 }
2188 
2189 // -----------------------------------------------------------
2191 {
2192  if(!view->focusElement) return;
2193  if(view->focusElement->Type != isMarker) return;
2194  Marker *pm = (Marker*)view->focusElement;
2195 
2196  QString DataSet;
2197  Schematic *Doc = (Schematic*)DocumentTab->currentPage();
2198  int z = pm->pGraph->Var.find(':');
2199  if(z <= 0) DataSet = Doc->DataSet;
2200  else DataSet = pm->pGraph->Var.mid(z+1);
2201  double Freq = pm->VarPos[0];
2202 
2203  QFileInfo Info(Doc->DocName);
2204  DataSet = Info.dirPath()+QDir::separator()+DataSet;
2205 
2206  Diagram *Diag = new Diagram();
2207 
2208  Graph *pg = new Graph("S[1,1]");
2209  Diag->Graphs.append(pg);
2210  if(!Diag->loadVarData(DataSet, pg)) {
2211  QMessageBox::critical(0, tr("Error"), tr("Could not load S[1,1]."));
2212  return;
2213  }
2214 
2215  pg = new Graph("S[1,2]");
2216  Diag->Graphs.append(pg);
2217  if(!Diag->loadVarData(DataSet, pg)) {
2218  QMessageBox::critical(0, tr("Error"), tr("Could not load S[1,2]."));
2219  return;
2220  }
2221 
2222  pg = new Graph("S[2,1]");
2223  Diag->Graphs.append(pg);
2224  if(!Diag->loadVarData(DataSet, pg)) {
2225  QMessageBox::critical(0, tr("Error"), tr("Could not load S[2,1]."));
2226  return;
2227  }
2228 
2229  pg = new Graph("S[2,2]");
2230  Diag->Graphs.append(pg);
2231  if(!Diag->loadVarData(DataSet, pg)) {
2232  QMessageBox::critical(0, tr("Error"), tr("Could not load S[2,2]."));
2233  return;
2234  }
2235 
2236  DataX *Data = Diag->Graphs.getFirst()->cPointsX.first();
2237  if(Data->Var != "frequency") {
2238  QMessageBox::critical(0, tr("Error"), tr("Wrong dependency!"));
2239  return;
2240  }
2241 
2242  double *Value = Data->Points;
2243  // search for values for chosen frequency
2244  for(z=0; z<Data->count; z++)
2245  if(*(Value++) == Freq) break;
2246 
2247  // get S-parameters
2248  double S11real = *(Diag->Graphs.first()->cPointsY + 2*z);
2249  double S11imag = *(Diag->Graphs.current()->cPointsY + 2*z + 1);
2250  double S12real = *(Diag->Graphs.next()->cPointsY + 2*z);
2251  double S12imag = *(Diag->Graphs.current()->cPointsY + 2*z + 1);
2252  double S21real = *(Diag->Graphs.next()->cPointsY + 2*z);
2253  double S21imag = *(Diag->Graphs.current()->cPointsY + 2*z + 1);
2254  double S22real = *(Diag->Graphs.next()->cPointsY + 2*z);
2255  double S22imag = *(Diag->Graphs.current()->cPointsY + 2*z + 1);
2256 
2257  delete Diag;
2258 
2259  MatchDialog *Dia = new MatchDialog(this);
2260  Dia->TwoCheck->setEnabled(false);
2261  Dia->setFrequency(Freq);
2262  Dia->S11magEdit->setText(QString::number(S11real));
2263  Dia->S11degEdit->setText(QString::number(S11imag));
2264  Dia->S12magEdit->setText(QString::number(S12real));
2265  Dia->S12degEdit->setText(QString::number(S12imag));
2266  Dia->S21magEdit->setText(QString::number(S21real));
2267  Dia->S21degEdit->setText(QString::number(S21imag));
2268  Dia->S22magEdit->setText(QString::number(S22real));
2269  Dia->S22degEdit->setText(QString::number(S22imag));
2270 
2271  slotToPage();
2272  if(Dia->exec() != QDialog::Accepted)
2273  return;
2274 }
2275 
2276 // -----------------------------------------------------------
2277 // Is called if the "edit" action is clicked on right mouse button menu.
2279 {
2280  if(view->focusMEvent)
2281  view->editElement((Schematic*)DocumentTab->currentPage(), view->focusMEvent);
2282 }
2283 
2284 // -----------------------------------------------------------
2285 // Hides the edit for component property. Called e.g. if QLineEdit
2286 // looses the focus.
2287 void QucsApp::slotHideEdit()
2288 {
2289  editText->setHidden(true);
2290 }