Qucs-GUI  0.0.19
/home/travis/build/Qucs/qucs/qucs/qucs/qucs_actions.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                                qucs_actions.cpp
00003                               -----------------
00004     begin                : Sat May 1 2004
00005     copyright            : (C) 2004 by Michael Margraf
00006     email                : michael.margraf@alumni.tu-berlin.de
00007  ***************************************************************************/
00008 
00009 /* Copyright (C) 2014 Guilherme Brondani Torri <guitorri@gmail.com>        */
00010 
00011 /***************************************************************************
00012  *                                                                         *
00013  *   This program is free software; you can redistribute it and/or modify  *
00014  *   it under the terms of the GNU General Public License as published by  *
00015  *   the Free Software Foundation; either version 2 of the License, or     *
00016  *   (at your option) any later version.                                   *
00017  *                                                                         *
00018  ***************************************************************************/
00019 
00024 #include <QtCore>
00025 #include <stdlib.h>
00026 #include <limits.h>
00027 
00028 #include <QProcess>
00029 #include <Q3PtrList>
00030 #include <QRegExpValidator>
00031 #include <QLineEdit>
00032 #include <QAction>
00033 #include <QStatusBar>
00034 #include <QMessageBox>
00035 #include <QFileDialog>
00036 #include <QMenu>
00037 #include <QComboBox>
00038 #include <QDockWidget>
00039 #include <QTreeWidgetItem>
00040 
00041 #include "projectView.h"
00042 #include "main.h"
00043 #include "qucs.h"
00044 #include "schematic.h"
00045 #include "textdoc.h"
00046 #include "mouseactions.h"
00047 #include "messagedock.h"
00048 #include "components/ground.h"
00049 #include "components/subcirport.h"
00050 #include "components/equation.h"
00051 #include "dialogs/matchdialog.h"
00052 #include "dialogs/changedialog.h"
00053 #include "dialogs/searchdialog.h"
00054 #include "dialogs/librarydialog.h"
00055 #include "dialogs/loaddialog.h"
00056 #include "dialogs/importdialog.h"
00057 #include "dialogs/packagedialog.h"
00058 #include "dialogs/aboutdialog.h"
00059 #include "module.h"
00060 
00061 // for editing component name on schematic
00062 QRegExp  Expr_CompProp;
00063 QRegExpValidator Val_CompProp(Expr_CompProp, 0);
00064 
00065 // -----------------------------------------------------------------------
00066 // This function is called from all toggle actions.
00067 bool QucsApp::performToggleAction(bool on, QAction *Action,
00068   pToggleFunc Function, pMouseFunc MouseMove, pMouseFunc2 MousePress)
00069 {
00070   slotHideEdit(); // disable text edit of component property
00071 
00072   if(!on) {
00073     MouseMoveAction = 0;
00074     MousePressAction = 0;
00075     MouseReleaseAction = 0;
00076     MouseDoubleClickAction = 0;
00077     activeAction = 0;   // no action active
00078     return false;
00079   }
00080 
00081   Schematic *Doc = (Schematic*)DocumentTab->currentPage();
00082   do {
00083     if(Function) if((Doc->*Function)()) {
00084       Action->blockSignals(true);
00085       Action->setChecked(false);  // release toolbar button
00086       Action->blockSignals(false);
00087       Doc->viewport()->update();
00088       break;
00089     }
00090 
00091     if(activeAction) {
00092       activeAction->blockSignals(true); // do not call toggle slot
00093       activeAction->setChecked(false);       // set last toolbar button off
00094       activeAction->blockSignals(false);
00095     }
00096     activeAction = Action;
00097 
00098     MouseMoveAction = MouseMove;
00099     MousePressAction = MousePress;
00100     MouseReleaseAction = 0;
00101     MouseDoubleClickAction = 0;
00102 
00103   } while(false);   // to perform "break"
00104 
00105   Doc->viewport()->update();
00106   view->drawn = false;
00107   return true;
00108 }
00109 
00110 // -----------------------------------------------------------------------
00111 // Is called, when "set on grid" action is triggered.
00112 void QucsApp::slotOnGrid(bool on)
00113 {
00114   performToggleAction(on, onGrid, &Schematic::elementsOnGrid,
00115     &MouseActions::MMoveOnGrid, &MouseActions::MPressOnGrid);
00116 }
00117 
00118 // -----------------------------------------------------------------------
00119 // Is called when the rotate toolbar button is pressed.
00120 void QucsApp::slotEditRotate(bool on)
00121 {
00122   performToggleAction(on, editRotate, &Schematic::rotateElements,
00123     &MouseActions::MMoveRotate, &MouseActions::MPressRotate);
00124 }
00125 
00126 // -----------------------------------------------------------------------
00127 // Is called when the mirror toolbar button is pressed.
00128 void QucsApp::slotEditMirrorX(bool on)
00129 {
00130   performToggleAction(on, editMirror, &Schematic::mirrorXComponents,
00131     &MouseActions::MMoveMirrorX, &MouseActions::MPressMirrorX);
00132 }
00133 
00134 // -----------------------------------------------------------------------
00135 // Is called when the mirror toolbar button is pressed.
00136 void QucsApp::slotEditMirrorY(bool on)
00137 {
00138   performToggleAction(on, editMirrorY, &Schematic::mirrorYComponents,
00139     &MouseActions::MMoveMirrorY, &MouseActions::MPressMirrorY);
00140 }
00141 
00142 // -----------------------------------------------------------------------
00143 // Is called when the activate/deactivate toolbar button is pressed.
00144 // It also comments out the selected text on a text document
00145 // \todo update the status or tooltip message
00146 void QucsApp::slotEditActivate (bool on)
00147 {
00148   TextDoc * Doc = (TextDoc *) DocumentTab->currentPage ();
00149   if (isTextDocument (Doc)) {
00150     //TODO Doc->clearParagraphBackground (Doc->tmpPosX);
00151     Doc->commentSelected ();
00152 
00153     editActivate->blockSignals (true);
00154     editActivate->setOn (false);  // release toolbar button
00155     editActivate->blockSignals (false);
00156   }
00157   else
00158     performToggleAction (on, editActivate,
00159         &Schematic::activateSelectedComponents,
00160         &MouseActions::MMoveActivate, &MouseActions::MPressActivate);
00161 }
00162 
00163 // ------------------------------------------------------------------------
00164 // Is called if "Delete"-Button is pressed.
00165 void QucsApp::slotEditDelete(bool on)
00166 {
00167   TextDoc *Doc = (TextDoc*)DocumentTab->currentPage();
00168   if(isTextDocument(Doc)) {
00169     Doc->viewport()->setFocus();
00170     //Doc->del();
00171     Doc->textCursor().deleteChar();
00172 
00173     editDelete->blockSignals(true);
00174     editDelete->setChecked(false);  // release toolbar button
00175     editDelete->blockSignals(false);
00176   }
00177   else
00178     performToggleAction(on, editDelete, &Schematic::deleteElements,
00179           &MouseActions::MMoveDelete, &MouseActions::MPressDelete);
00180 }
00181 
00182 // -----------------------------------------------------------------------
00183 // Is called if "Wire"-Button is pressed.
00184 void QucsApp::slotSetWire(bool on)
00185 {
00186   performToggleAction(on, insWire, 0,
00187     &MouseActions::MMoveWire1, &MouseActions::MPressWire1);
00188 }
00189 
00190 // -----------------------------------------------------------------------
00191 void QucsApp::slotInsertLabel(bool on)
00192 {
00193   performToggleAction(on, insLabel, 0,
00194     &MouseActions::MMoveLabel, &MouseActions::MPressLabel);
00195 }
00196 
00197 // -----------------------------------------------------------------------
00198 void QucsApp::slotSetMarker(bool on)
00199 {
00200   performToggleAction(on, setMarker, 0,
00201     &MouseActions::MMoveMarker, &MouseActions::MPressMarker);
00202 }
00203 
00204 // -----------------------------------------------------------------------
00205 // Is called, when "move component text" action is triggered.
00206 void QucsApp::slotMoveText(bool on)
00207 {
00208   performToggleAction(on, moveText, 0,
00209     &MouseActions::MMoveMoveTextB, &MouseActions::MPressMoveText);
00210 }
00211 
00212 // -----------------------------------------------------------------------
00213 // Is called, when "Zoom in" action is triggered.
00214 void QucsApp::slotZoomIn(bool on)
00215 {
00216   TextDoc *Doc = (TextDoc*)DocumentTab->currentPage();
00217   if(isTextDocument(Doc)) {
00218     Doc->zoomBy(1.5f);
00219     magPlus->blockSignals(true);
00220     magPlus->setChecked(false);
00221     magPlus->blockSignals(false);
00222   }
00223   else
00224     performToggleAction(on, magPlus, 0,
00225     &MouseActions::MMoveZoomIn, &MouseActions::MPressZoomIn);
00226 }
00227 
00228 
00229 void QucsApp::slotEscape()
00230 {
00231     select->setChecked(true);
00232     slotSearchClear();
00233 }
00234 
00235 // -----------------------------------------------------------------------
00236 // Is called when the select toolbar button is pressed.
00237 void QucsApp::slotSelect(bool on)
00238 {
00239   QWidget *w = DocumentTab->currentPage();
00240   if(isTextDocument(w)) {
00241     ((TextDoc*)w)->viewport()->setFocus();
00242       select->blockSignals(true);
00243       select->setChecked(true);
00244       select->blockSignals(false);
00245     return;
00246   }
00247 
00248   // goto to insertWire mode if ESC pressed during wiring
00249   Schematic *Doc = (Schematic*)DocumentTab->currentPage();
00250   if(MouseMoveAction == &MouseActions::MMoveWire2) {
00251     MouseMoveAction = &MouseActions::MMoveWire1;
00252     MousePressAction = &MouseActions::MPressWire1;
00253     Doc->viewport()->update();
00254     view->drawn = false;
00255 
00256     select->blockSignals(true);
00257     select->setChecked(false);
00258     select->blockSignals(false);
00259     return;
00260   }
00261 
00262   if(performToggleAction(on, select, 0, 0, &MouseActions::MPressSelect)) {
00263     MouseReleaseAction = &MouseActions::MReleaseSelect;
00264     MouseDoubleClickAction = &MouseActions::MDoubleClickSelect;
00265   }
00266 }
00267 
00268 // --------------------------------------------------------------------
00269 void QucsApp::slotEditCut()
00270 {
00271   statusBar()->message(tr("Cutting selection..."));
00272   slotHideEdit(); // disable text edit of component property
00273 
00274   QWidget *Doc = DocumentTab->currentPage();
00275   if(isTextDocument (Doc)) {
00276     ((TextDoc *)Doc)->cut();
00277   } else {
00278     ((Schematic *)Doc)->cut();
00279   }
00280 
00281   statusBar()->message(tr("Ready."));
00282 }
00283 
00284 // --------------------------------------------------------------------
00285 void QucsApp::slotEditCopy()
00286 {
00287   statusBar()->message(tr("Copying selection to clipboard..."));
00288 
00289   QWidget *Doc = DocumentTab->currentPage();
00290   if(isTextDocument (Doc)) {
00291     ((TextDoc *)Doc)->copy();
00292   } else {
00293     ((Schematic *)Doc)->copy();
00294   }
00295 
00296   statusBar()->message(tr("Ready."));
00297 }
00298 
00299 // -----------------------------------------------------------------------
00300 void QucsApp::slotEditPaste(bool on)
00301 {
00302   // get the current document
00303   QWidget *Doc = DocumentTab->currentPage();
00304 
00305   // if the current document is a text document paste in
00306   // the contents of the clipboard as text
00307   if(isTextDocument (Doc))
00308   {
00309     ((TextDoc*)Doc)->paste();
00310 
00311     editPaste->blockSignals(true);
00312     editPaste->setChecked(false);  // release toolbar button
00313     editPaste->blockSignals(false);
00314     return;
00315   } 
00316   else {
00317     // if it's not a text doc, prevent the user from editing
00318     // while we perform the paste operation
00319     slotHideEdit();
00320 
00321     if(!on)
00322     {
00323       MouseMoveAction = 0;
00324       MousePressAction = 0;
00325       MouseReleaseAction = 0;
00326       MouseDoubleClickAction = 0;
00327       activeAction = 0;   // no action active
00328       if(view->drawn) {
00329         ((Schematic *)Doc)->viewport()->update();
00330       }
00331       return;
00332     }
00333 
00334     if(!view->pasteElements((Schematic *)Doc))
00335     {
00336       editPaste->blockSignals(true); // do not call toggle slot
00337       editPaste->setChecked(false);       // set toolbar button off
00338       editPaste->blockSignals(false);
00339       return;   // if clipboard empty
00340     }
00341 
00342     if(activeAction)
00343     {
00344       activeAction->blockSignals(true); // do not call toggle slot
00345       activeAction->setChecked(false);       // set last toolbar button off
00346       activeAction->blockSignals(false);
00347     }
00348     activeAction = editPaste;
00349 
00350     view->drawn = false;
00351     MouseMoveAction = &MouseActions::MMovePaste;
00352     view->movingRotated = 0;
00353     MousePressAction = 0;
00354     MouseReleaseAction = 0;
00355     MouseDoubleClickAction = 0;
00356   }
00357 }
00358 
00359 // -----------------------------------------------------------------------
00360 void QucsApp::slotInsertEntity ()
00361 {
00362   TextDoc * Doc = (TextDoc *) DocumentTab->currentPage ();
00363   Doc->viewport()->setFocus ();
00364   //TODO Doc->clearParagraphBackground (Doc->tmpPosX);
00365   Doc->insertSkeleton ();
00366 
00367   //int x, y;
00368   //Doc->getCursorPosition (&x, &y);
00369   //x = Doc->textCursor().blockNumber();
00370   //y = Doc->textCursor().columnNumber();
00371   Doc->slotCursorPosChanged();
00372 }
00373 
00374 // -----------------------------------------------------------------------
00375 // Is called when the mouse is clicked upon the equation toolbar button.
00376 void QucsApp::slotInsertEquation(bool on)
00377 {
00378   slotHideEdit(); // disable text edit of component property
00379   MouseReleaseAction = 0;
00380   MouseDoubleClickAction = 0;
00381 
00382   if(!on) {
00383     MouseMoveAction = 0;
00384     MousePressAction = 0;
00385     activeAction = 0;   // no action active
00386     return;
00387   }
00388   if(activeAction) {
00389     activeAction->blockSignals(true); // do not call toggle slot
00390     activeAction->setChecked(false);       // set last toolbar button off
00391     activeAction->blockSignals(false);
00392   }
00393   activeAction = insEquation;
00394 
00395   if(view->selElem)
00396     delete view->selElem;  // delete previously selected component
00397 
00398   view->selElem = new Equation();
00399 
00400   Schematic *Doc = (Schematic*)DocumentTab->currentPage();
00401   if(view->drawn) Doc->viewport()->update();
00402   view->drawn = false;
00403   MouseMoveAction = &MouseActions::MMoveElement;
00404   MousePressAction = &MouseActions::MPressElement;
00405 }
00406 
00407 // -----------------------------------------------------------------------
00408 // Is called when the mouse is clicked upon the ground toolbar button.
00409 void QucsApp::slotInsertGround(bool on)
00410 {
00411   slotHideEdit(); // disable text edit of component property
00412   MouseReleaseAction = 0;
00413   MouseDoubleClickAction = 0;
00414 
00415   if(!on) {
00416     MouseMoveAction = 0;
00417     MousePressAction = 0;
00418     activeAction = 0;   // no action active
00419     return;
00420   }
00421   if(activeAction) {
00422     activeAction->blockSignals(true); // do not call toggle slot
00423     activeAction->setChecked(false);       // set last toolbar button off
00424     activeAction->blockSignals(false);
00425   }
00426   activeAction = insGround;
00427 
00428   if(view->selElem)
00429     delete view->selElem;  // delete previously selected component
00430 
00431   view->selElem = new Ground();
00432 
00433   Schematic *Doc = (Schematic*)DocumentTab->currentPage();
00434   if(view->drawn) Doc->viewport()->update();
00435   view->drawn = false;
00436   MouseMoveAction = &MouseActions::MMoveElement;
00437   MousePressAction = &MouseActions::MPressElement;
00438 }
00439 
00440 // -----------------------------------------------------------------------
00441 // Is called when the mouse is clicked upon the port toolbar button.
00442 void QucsApp::slotInsertPort(bool on)
00443 {
00444   slotHideEdit(); // disable text edit of component property
00445   MouseReleaseAction = 0;
00446   MouseDoubleClickAction = 0;
00447 
00448   if(!on) {
00449     MouseMoveAction = 0;
00450     MousePressAction = 0;
00451     activeAction = 0;   // no action active
00452     return;
00453   }
00454   if(activeAction) {
00455     activeAction->blockSignals(true); // do not call toggle slot
00456     activeAction->setChecked(false);       // set last toolbar button off
00457     activeAction->blockSignals(false);
00458   }
00459   activeAction = insPort;
00460 
00461   if(view->selElem)
00462     delete view->selElem;  // delete previously selected component
00463 
00464   view->selElem = new SubCirPort();
00465 
00466   Schematic *Doc = (Schematic*)DocumentTab->currentPage();
00467   if(view->drawn) Doc->viewport()->update();
00468   view->drawn = false;
00469   MouseMoveAction = &MouseActions::MMoveElement;
00470   MousePressAction = &MouseActions::MPressElement;
00471 }
00472 
00473 // --------------------------------------------------------------
00474 // Is called, when "Undo"-Button is pressed.
00475 void QucsApp::slotEditUndo()
00476 {
00477   Schematic *Doc = (Schematic*)DocumentTab->currentPage();
00478   if(isTextDocument(Doc)) {
00479     ((TextDoc*)Doc)->viewport()->setFocus();
00480     ((TextDoc*)Doc)->undo();
00481     return;
00482   }
00483 
00484   slotHideEdit(); // disable text edit of component property
00485 
00486   Doc->undo();
00487   Doc->viewport()->update();
00488   view->drawn = false;
00489 }
00490 
00491 // --------------------------------------------------------------
00492 // Is called, when "Undo"-Button is pressed.
00493 void QucsApp::slotEditRedo()
00494 {
00495   Schematic *Doc = (Schematic*)DocumentTab->currentPage();
00496   if(isTextDocument(Doc)) {
00497     ((TextDoc*)Doc)->viewport()->setFocus();
00498     ((TextDoc*)Doc)->redo();
00499     return;
00500   }
00501 
00502   slotHideEdit(); // disable text edit of component property
00503 
00504   Doc->redo();
00505   Doc->viewport()->update();
00506   view->drawn = false;
00507 }
00508 
00509 // --------------------------------------------------------------
00510 // Is called, when "Align top" action is triggered.
00511 void QucsApp::slotAlignTop()
00512 {
00513   slotHideEdit(); // disable text edit of component property
00514 
00515   Schematic *Doc = (Schematic*)DocumentTab->currentPage();
00516   if(!Doc->aligning(0))
00517     QMessageBox::information(this, tr("Info"),
00518           tr("At least two elements must be selected !"));
00519   Doc->viewport()->update();
00520   view->drawn = false;
00521 }
00522 
00523 // --------------------------------------------------------------
00524 // Is called, when "Align bottom" action is triggered.
00525 void QucsApp::slotAlignBottom()
00526 {
00527   slotHideEdit(); // disable text edit of component property
00528 
00529   Schematic *Doc = (Schematic*)DocumentTab->currentPage();
00530   if(!Doc->aligning(1))
00531     QMessageBox::information(this, tr("Info"),
00532           tr("At least two elements must be selected !"));
00533   Doc->viewport()->update();
00534   view->drawn = false;
00535 }
00536 
00537 // --------------------------------------------------------------
00538 // Is called, when "Align left" action is triggered.
00539 void QucsApp::slotAlignLeft()
00540 {
00541   slotHideEdit(); // disable text edit of component property
00542 
00543   Schematic *Doc = (Schematic*)DocumentTab->currentPage();
00544   if(!Doc->aligning(2))
00545     QMessageBox::information(this, tr("Info"),
00546           tr("At least two elements must be selected !"));
00547   Doc->viewport()->update();
00548   view->drawn = false;
00549 }
00550 
00551 // --------------------------------------------------------------
00552 // Is called, when "Align right" action is triggered.
00553 void QucsApp::slotAlignRight()
00554 {
00555   slotHideEdit(); // disable text edit of component property
00556 
00557   Schematic *Doc = (Schematic*)DocumentTab->currentPage();
00558   if(!Doc->aligning(3))
00559     QMessageBox::information(this, tr("Info"),
00560           tr("At least two elements must be selected !"));
00561   Doc->viewport()->update();
00562   view->drawn = false;
00563 }
00564 
00565 // --------------------------------------------------------------
00566 // Is called, when "Distribute horizontally" action is triggered.
00567 void QucsApp::slotDistribHoriz()
00568 {
00569   slotHideEdit(); // disable text edit of component property
00570 
00571   Schematic *Doc = (Schematic*)DocumentTab->currentPage();
00572   Doc->distributeHorizontal();
00573   Doc->viewport()->update();
00574   view->drawn = false;
00575 }
00576 
00577 // --------------------------------------------------------------
00578 // Is called, when "Distribute vertically" action is triggered.
00579 void QucsApp::slotDistribVert()
00580 {
00581   slotHideEdit(); // disable text edit of component property
00582 
00583   Schematic *Doc = (Schematic*)DocumentTab->currentPage();
00584   Doc->distributeVertical();
00585   Doc->viewport()->update();
00586   view->drawn = false;
00587 }
00588 
00589 // --------------------------------------------------------------
00590 // Is called, when "Center horizontally" action is triggered.
00591 void QucsApp::slotCenterHorizontal()
00592 {
00593   slotHideEdit(); // disable text edit of component property
00594 
00595   Schematic *Doc = (Schematic*)DocumentTab->currentPage();
00596   if(!Doc->aligning(4))
00597     QMessageBox::information(this, tr("Info"),
00598           tr("At least two elements must be selected !"));
00599   Doc->viewport()->update();
00600   view->drawn = false;
00601 }
00602 
00603 // --------------------------------------------------------------
00604 // Is called, when "Center vertically" action is triggered.
00605 void QucsApp::slotCenterVertical()
00606 {
00607   slotHideEdit(); // disable text edit of component property
00608 
00609   Schematic *Doc = (Schematic*)DocumentTab->currentPage();
00610   if(!Doc->aligning(5))
00611     QMessageBox::information(this, tr("Info"),
00612           tr("At least two elements must be selected !"));
00613   Doc->viewport()->update();
00614   view->drawn = false;
00615 }
00616 
00617 // ---------------------------------------------------------------------
00618 // Is called when the "select all" action is triggered.
00619 void QucsApp::slotSelectAll()
00620 {
00621   slotHideEdit(); // disable text edit of component property
00622 
00623   QWidget *Doc = DocumentTab->currentPage();
00624   if(isTextDocument(Doc)) {
00625     ((TextDoc*)Doc)->viewport()->setFocus();
00626     //((TextDoc*)Doc)->selectAll(true);
00627     ((TextDoc*)Doc)->selectAll();
00628   }
00629   else {
00630     ((Schematic*)Doc)->selectElements(INT_MIN, INT_MIN, INT_MAX, INT_MAX, true);
00631     ((Schematic*)Doc)->viewport()->update();
00632     view->drawn = false;
00633   }
00634 }
00635 
00636 // ---------------------------------------------------------------------
00637 // Is called when the "select markers" action is triggered.
00638 void QucsApp::slotSelectMarker()
00639 {
00640   slotHideEdit(); // disable text edit of component property
00641 
00642   Schematic *Doc = (Schematic*)DocumentTab->currentPage();
00643   Doc->selectMarkers();
00644   Doc->viewport()->update();
00645   view->drawn = false;
00646 }
00647 
00648 
00649 extern QString lastDirOpenSave; // to remember last directory and file
00650 
00651 // ------------------------------------------------------------------------
00652 // Is called by slotShowLastMsg(), by slotShowLastNetlist() and from the
00653 // component edit dialog.
00654 void QucsApp::editFile(const QString& File)
00655 {
00656     if ((QucsSettings.Editor.toLower() == "qucs") | QucsSettings.Editor.isEmpty())
00657     {
00658         // The Editor is 'qucs' or empty, open a net document tab
00659         if (File.isEmpty()) {
00660             QucsApp::slotTextNew();
00661         }
00662         else
00663         {
00664             slotHideEdit(); // disable text edit of component property
00665 
00666             statusBar()->message(tr("Opening file..."));
00667 
00668             QFileInfo finfo(File);
00669 
00670             if(!finfo.exists())
00671                 statusBar()->message(tr("Opening aborted, file not found."), 2000);
00672             else {
00673                 gotoPage(File);
00674                 lastDirOpenSave = File;   // remember last directory and file
00675                 statusBar()->message(tr("Ready."));
00676             }
00677         }
00678     }
00679     else
00680     {
00681       // use an external editor
00682       QString prog;
00683       QStringList args;
00684 
00685       if (QucsSettings.Editor.toLower().contains("qucsedit")) {
00686 
00687 #ifdef __MINGW32__
00688   prog = "qucsedit.exe";
00689 #elif __APPLE__
00690   prog = "qucsedit.app/Contents/MacOS/qucsedit";
00691 #else
00692   prog = "qucsedit";
00693 #endif
00694 
00695         QFileInfo editor(QucsSettings.BinDir + prog);
00696         prog = QDir::toNativeSeparators(editor.canonicalFilePath());
00697       }
00698       else { // user defined editor
00699           QFileInfo editor(QucsSettings.Editor);
00700           prog = QDir::toNativeSeparators(editor.canonicalFilePath());
00701       }
00702 
00703       if (!File.isEmpty()) {
00704           args << File;
00705       }
00706 
00707       QProcess *QucsEditor = new QProcess();
00708       QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
00709       env.insert("PATH", env.value("PATH") );
00710       QucsEditor->setProcessEnvironment(env);
00711 
00712       qDebug() << "Command: " << prog << args.join(" ");
00713 
00714       QucsEditor->start(prog, args);
00715 
00716       if( !QucsEditor->waitForStarted(1000) ) {
00717         QMessageBox::critical(this, tr("Error"), tr("Cannot start text editor! \n\n%1").arg(prog));
00718         delete QucsEditor;
00719         return;
00720       }
00721       qDebug() << QucsEditor->readAllStandardError();
00722 
00723       // to kill it before qucs ends
00724       connect(this, SIGNAL(signalKillEmAll()), QucsEditor, SLOT(kill()));
00725     }
00726 }
00727 
00728 // ------------------------------------------------------------------------
00729 // Is called to show the output messages of the last simulation.
00730 void QucsApp::slotShowLastMsg()
00731 {
00732   editFile(QucsSettings.QucsHomeDir.filePath("log.txt"));
00733 }
00734 
00735 // ------------------------------------------------------------------------
00736 // Is called to show the netlist of the last simulation.
00737 void QucsApp::slotShowLastNetlist()
00738 {
00739   editFile(QucsSettings.QucsHomeDir.filePath("netlist.txt"));
00740 }
00741 
00742 // ------------------------------------------------------------------------
00743 // Is called to start the text editor.
00744 void QucsApp::slotCallEditor()
00745 {
00746   editFile(QString(""));
00747 }
00748 
00749 // ------------------------------------------------------------------------
00750 // Is called to start the filter synthesis program.
00751 void QucsApp::slotCallFilter()
00752 {
00753   launchTool("qucsfilter", "filter synthesis");
00754 }
00755 
00756 void QucsApp::slotCallActiveFilter()
00757 {
00758   launchTool("qucsactivefilter", "active filter synthesis");
00759 }
00760 
00761 // ------------------------------------------------------------------------
00762 // Is called to start the transmission line calculation program.
00763 void QucsApp::slotCallLine()
00764 {
00765   launchTool("qucstrans", "line calculation");
00766 }
00767 
00768 // ------------------------------------------------------------------------
00769 // Is called to start the component library program.
00770 void QucsApp::slotCallLibrary()
00771 {
00772   launchTool("qucslib", "library");
00773 }
00774 
00775 // --------------------------------------------------------------
00776 // Is called to show a dialog for creating matching circuits.
00777 void QucsApp::slotCallMatch()
00778 {
00779   MatchDialog *d = new MatchDialog(this);
00780   d->exec();
00781 }
00782 
00783 // ------------------------------------------------------------------------
00784 // Is called to start the attenuator calculation program.
00785 void QucsApp::slotCallAtt()
00786 {
00787   launchTool("qucsattenuator", "attenuator calculation");
00788 }
00789 
00790 // ------------------------------------------------------------------------
00791 // Is called to start the resistor color code calculation program.
00792 void QucsApp::slotCallRes()
00793 {
00794   launchTool("qucsrescodes", "resistor color code calculation");
00795 }
00796 
00804 void QucsApp::launchTool(const QString& prog, const QString& progDesc, const QString& args) {
00805   QProcess *tool = new QProcess();
00806 
00807 #ifdef __MINGW32__
00808   QString cmd = QDir::toNativeSeparators("\""+QucsSettings.BinDir + prog + ".exe\"") + " " + args;
00809 #elif __APPLE__
00810   QString cmd = QDir::toNativeSeparators(QucsSettings.BinDir + prog + ".app/Contents/MacOS/" + prog) + " " + args;
00811 #else
00812   QString cmd = QDir::toNativeSeparators(QucsSettings.BinDir + prog) + " " + args;
00813 #endif
00814 
00815   tool->setWorkingDirectory(QucsSettings.BinDir);
00816   qDebug() << "Command :" << cmd;
00817   tool->start(cmd);
00818   
00819   if(!tool->waitForStarted(1000) ) {
00820     QMessageBox::critical(this, tr("Error"),
00821                           tr("Cannot start %1 program! \n\n(%2)").arg(progDesc, cmd));
00822     delete tool;
00823     return;
00824   }
00825 
00826   // to kill the application first before qucs finishes exiting
00827   connect(this, SIGNAL(signalKillEmAll()), tool, SLOT(kill()));
00828 }
00829 
00830 
00831 // --------------------------------------------------------------
00832 void QucsApp::slotHelpIndex()
00833 {
00834   showHTML("index.html");
00835 }
00836 
00837 // --------------------------------------------------------------
00838 void QucsApp::slotGettingStarted()
00839 {
00840   showHTML("start.html");
00841 }
00842 
00843 // --------------------------------------------------------------
00844 void QucsApp::showHTML(const QString& Page)
00845 {
00846   launchTool("qucshelp", "help", Page);
00847 }
00848 
00849 // ---------------------------------------------------------------------
00850 // Is called when the find action is triggered.
00851 void QucsApp::slotEditFind()
00852 {
00853   SearchDia->initSearch(DocumentTab->currentPage(),
00854       ((TextDoc *)DocumentTab->currentPage())->textCursor().selectedText(), false);
00855 }
00856 
00857 // --------------------------------------------------------------
00858 void QucsApp::slotChangeProps()
00859 {
00860   QWidget *Doc = DocumentTab->currentPage();
00861   if(isTextDocument(Doc)) {
00862     ((TextDoc*)Doc)->viewport()->setFocus();
00863 
00864     SearchDia->initSearch(Doc,
00865         ((TextDoc *)Doc)->textCursor().selectedText(), true);
00866   }
00867   else {
00868     ChangeDialog *d = new ChangeDialog((Schematic*)Doc);
00869     if(d->exec() == QDialog::Accepted) {
00870       ((Schematic*)Doc)->setChanged(true, true);
00871       ((Schematic*)Doc)->viewport()->update();
00872     }
00873   }
00874 }
00875 
00876 // --------------------------------------------------------------
00877 void QucsApp::slotAddToProject()
00878 {
00879   slotHideEdit(); // disable text edit of component property
00880 
00881   if(ProjName.isEmpty()) {
00882     QMessageBox::critical(this, tr("Error"), tr("No project open!"));
00883     return;
00884   }
00885 
00886 
00887   QStringList List = QFileDialog::getOpenFileNames(this, tr("Select files to copy"),
00888     lastDir.isEmpty() ? QString(".") : lastDir, QucsFileFilter);
00889 
00890   if(List.isEmpty()) {
00891     statusBar()->message(tr("No files copied."), 2000);
00892     return;
00893   }
00894 
00895 
00896   char *Buffer = (char*)malloc(0x10000);
00897   if(!Buffer) return;  // should never happen
00898 
00899   QStringList FileList = List;  // make a copy as recommended by Qt
00900   QStringList::Iterator it = FileList.begin();
00901   QFileInfo Info(*it);
00902   lastDir = Info.dirPath(true);  // remember last directory
00903 
00904   // copy all files to project directory
00905   int Num;
00906   QFile origFile, destFile;
00907   while(it != FileList.end()) {
00908     Info.setFile(*it);
00909     origFile.setFileName(*it);
00910     destFile.setFileName(QucsSettings.QucsWorkDir.absPath() +
00911                      QDir::separator() + Info.fileName());
00912 
00913     if(!origFile.open(QIODevice::ReadOnly)) {
00914       QMessageBox::critical(this, tr("Error"), tr("Cannot open \"%1\" !").arg(*it));
00915       it++;
00916       continue;
00917     }
00918 
00919     if(destFile.exists())
00920       if(QMessageBox::information(this, tr("Overwrite"),
00921            tr("File \"%1\" already exists.\nOverwrite ?").arg(*it), QMessageBox::Yes,
00922            QMessageBox::No|QMessageBox::Default|QMessageBox::Escape)
00923          != QMessageBox::Yes) {
00924         origFile.close();
00925         it++;
00926         continue;
00927       }
00928 
00929     if(!destFile.open(QIODevice::WriteOnly)) {
00930       QMessageBox::critical(this, tr("Error"), tr("Cannot create \"%1\" !").arg(*it));
00931       origFile.close();
00932       it++;
00933       continue;
00934     }
00935 
00936     // copy data
00937     do {
00938       Num = origFile.readBlock(Buffer, 0x10000);
00939       if(Num < 0) {
00940         QMessageBox::critical(this, tr("Error"), tr("Cannot read \"%1\" !").arg(*it));
00941         break;
00942       }
00943       Num = destFile.writeBlock(Buffer, Num);
00944       if(Num < 0) {
00945         QMessageBox::critical(this, tr("Error"), tr("Cannot write \"%1\" !").arg(*it));
00946         break;
00947       }
00948     } while(Num == 0x10000);
00949 
00950     origFile.close();
00951     destFile.close();
00952     it++;
00953   }
00954 
00955   free(Buffer);
00956   slotUpdateTreeview();
00957   statusBar()->message(tr("Ready."));
00958 }
00959 
00960 // -----------------------------------------------------------
00961 void QucsApp::slotCursorLeft(bool left)
00962 {
00963   int sign = 1;
00964   if(left){
00965     sign = -1;
00966   }
00967   if(!editText->isHidden()) return;  // for edit of component property ?
00968 
00969   Q3PtrList<Element> movingElements;
00970   Schematic *Doc = (Schematic*)DocumentTab->currentPage();
00971   int markerCount = Doc->copySelectedElements(&movingElements);
00972 
00973   if((movingElements.count() - markerCount) < 1) {
00974     if(markerCount > 0) {  // only move marker if nothing else selected
00975       Doc->markerLeftRight(left, &movingElements);
00976     } else if(left) {
00977       if(Doc->scrollLeft(Doc->horizontalScrollBar()->lineStep()))
00978         Doc->scrollBy(-Doc->horizontalScrollBar()->lineStep(), 0);
00979     }else{ // right
00980       if(Doc->scrollRight(-Doc->horizontalScrollBar()->lineStep()))
00981         Doc->scrollBy(Doc->horizontalScrollBar()->lineStep(), 0);
00982     }
00983 
00984     Doc->viewport()->update();
00985     view->drawn = false;
00986     return;
00987   } else { // random selection. move all of them
00988     view->moveElements(&movingElements, sign*Doc->GridX, 0);
00989     view->MAx3 = 1;  // sign for moved elements
00990     view->endElementMoving(Doc, &movingElements);
00991   }
00992 }
00993 
00994 // -----------------------------------------------------------
00995 void QucsApp::slotCursorUp(bool up)
00996 {
00997   if(editText->isHidden()) {  // for edit of component property ?
00998   }else if(up){
00999     if(view->MAx3 == 0) return;  // edit component namen ?
01000     Component *pc = (Component*)view->focusElement;
01001     Property *pp = pc->Props.at(view->MAx3-1);  // current property
01002     int Begin = pp->Description.indexOf('[');
01003     if(Begin < 0) return;  // no selection list ?
01004     int End = pp->Description.indexOf(editText->text(), Begin); // current
01005     if(End < 0) return;  // should never happen
01006     End = pp->Description.findRev(',', End);
01007     if(End < Begin) return;  // was first item ?
01008     End--;
01009     int Pos = pp->Description.findRev(',', End);
01010     if(Pos < Begin) Pos = Begin;   // is first item ?
01011     Pos++;
01012     if(pp->Description.at(Pos) == ' ') Pos++; // remove leading space
01013     editText->setText(pp->Description.mid(Pos, End-Pos+1));
01014     editText->selectAll();
01015     return;
01016   }else{ // down
01017     if(view->MAx3 == 0) return;  // edit component namen ?
01018     Component *pc = (Component*)view->focusElement;
01019     Property *pp = pc->Props.at(view->MAx3-1);  // current property
01020     int Pos = pp->Description.indexOf('[');
01021     if(Pos < 0) return;  // no selection list ?
01022     Pos = pp->Description.indexOf(editText->text(), Pos); // current list item
01023     if(Pos < 0) return;  // should never happen
01024     Pos = pp->Description.indexOf(',', Pos);
01025     if(Pos < 0) return;  // was last item ?
01026     Pos++;
01027     if(pp->Description.at(Pos) == ' ') Pos++; // remove leading space
01028     int End = pp->Description.indexOf(',', Pos);
01029     if(End < 0) {  // is last item ?
01030       End = pp->Description.indexOf(']', Pos);
01031       if(End < 0) return;  // should never happen
01032     }
01033     editText->setText(pp->Description.mid(Pos, End-Pos));
01034     editText->selectAll();
01035     return;
01036   }
01037 
01038   Q3PtrList<Element> movingElements;
01039   Schematic *Doc = (Schematic*)DocumentTab->currentPage();
01040   int markerCount = Doc->copySelectedElements(&movingElements);
01041 
01042   if((movingElements.count() - markerCount) < 1) { // all selections are markers
01043     if(markerCount > 0) {  // only move marker if nothing else selected
01044       Doc->markerUpDown(up, &movingElements);
01045     } else if(up) { // nothing selected at all
01046       if(Doc->scrollUp(Doc->verticalScrollBar()->lineStep()))
01047         Doc->scrollBy(0, -Doc->verticalScrollBar()->lineStep());
01048     } else { // down
01049       if(Doc->scrollDown(-Doc->verticalScrollBar()->lineStep()))
01050         Doc->scrollBy(0, Doc->verticalScrollBar()->lineStep());
01051     }
01052 
01053     Doc->viewport()->update();
01054     view->drawn = false;
01055     return;
01056   }else{ // some random selection, put it back
01057     view->moveElements(&movingElements, 0, ((up)?-1:1) * Doc->GridY);
01058     view->MAx3 = 1;  // sign for moved elements
01059     view->endElementMoving(Doc, &movingElements);
01060   }
01061 }
01062 
01063 // -----------------------------------------------------------
01064 // Is called if user clicked on component text of if return is
01065 // pressed in the component text QLineEdit.
01066 // In "view->MAx3" is the number of the current property.
01067 void QucsApp::slotApplyCompText()
01068 {
01069   QString s;
01070   QFont f = QucsSettings.font;
01071   Schematic *Doc = (Schematic*)DocumentTab->currentPage();
01072   f.setPointSizeFloat( Doc->Scale * float(f.pointSize()) );
01073   editText->setFont(f);
01074 
01075   Property  *pp = 0;
01076   Component *pc = (Component*)view->focusElement;
01077   if(!pc) return;  // should never happen
01078   view->MAx1 = pc->cx + pc->tx;
01079   view->MAy1 = pc->cy + pc->ty;
01080 
01081   int z, n=0;  // "n" is number of property on screen
01082   pp = pc->Props.first();
01083   for(z=view->MAx3; z>0; z--) {  // calculate "n"
01084     if(!pp) {  // should never happen
01085       slotHideEdit();
01086       return;
01087     }
01088     if(pp->display) n++;   // is visible ?
01089     pp = pc->Props.next();
01090   }
01091 
01092   pp = 0;
01093   if(view->MAx3 > 0)  pp = pc->Props.at(view->MAx3-1); // current property
01094   else s = pc->Name;
01095 
01096   if(!editText->isHidden()) {   // is called the first time ?
01097     // no -> apply value to current property
01098     if(view->MAx3 == 0) {   // component name ?
01099       Component *pc2;
01100       if(!editText->text().isEmpty())
01101         if(pc->Name != editText->text()) {
01102           for(pc2 = Doc->Components->first(); pc2!=0; pc2 = Doc->Components->next())
01103             if(pc2->Name == editText->text())
01104               break;  // found component with the same name ?
01105           if(!pc2) {
01106             pc->Name = editText->text();
01107             Doc->setChanged(true, true);  // only one undo state
01108           }
01109         }
01110     }
01111     else if(pp) {  // property was applied
01112       if(pp->Value != editText->text()) {
01113         pp->Value = editText->text();
01114         Doc->recreateComponent(pc);  // because of "Num" and schematic symbol
01115         Doc->setChanged(true, true); // only one undo state
01116       }
01117     }
01118 
01119     n++;     // next row on screen
01120     (view->MAx3)++;  // next property
01121     pp = pc->Props.at(view->MAx3-1);  // search for next property
01122 
01123     Doc->viewport()->update();
01124     view->drawn = false;
01125 
01126     if(!pp) {     // was already last property ?
01127       slotHideEdit();
01128       return;
01129     }
01130 
01131 
01132     while(!pp->display) {  // search for next visible property
01133       (view->MAx3)++;  // next property
01134       pp = pc->Props.next();
01135       if(!pp) {     // was already last property ?
01136         slotHideEdit();
01137         return;
01138       }
01139     }
01140   }
01141 
01142   // avoid seeing the property text behind the line edit
01143   if(pp)  // Is it first property or component name ?
01144     s = pp->Value;
01145   editText->setMinimumWidth(editText->fontMetrics().width(s)+4);
01146 
01147 
01148   Doc->contentsToViewport(int(Doc->Scale * float(view->MAx1 - Doc->ViewX1)),
01149        int(Doc->Scale * float(view->MAy1 - Doc->ViewY1)),
01150        view->MAx2, view->MAy2);
01151   editText->setReadOnly(false);
01152   if(pp) {  // is it a property ?
01153     s = pp->Value;
01154     view->MAx2 += editText->fontMetrics().width(pp->Name+"=");
01155     if(pp->Description.indexOf('[') >= 0)  // is selection list ?
01156       editText->setReadOnly(true);
01157     Expr_CompProp.setPattern("[^\"]*");
01158     if(!pc->showName) n--;
01159   }
01160   else   // it is the component name
01161     Expr_CompProp.setPattern("[\\w_]+");
01162   Val_CompProp.setRegExp(Expr_CompProp);
01163   editText->setValidator(&Val_CompProp);
01164 
01165   z = editText->fontMetrics().lineSpacing();
01166   view->MAy2 += n*z;
01167   editText->setText(s);
01168   editText->setPaletteBackgroundColor(QucsSettings.BGColor);
01169   editText->setFocus();
01170   editText->selectAll();
01171   editText->reparent(Doc->viewport(), 0, QPoint(view->MAx2, view->MAy2), true);
01172 }
01173 
01174 // -----------------------------------------------------------
01175 // Is called if the text of the property edit changed, to match
01176 // the width of the edit field.
01177 void QucsApp::slotResizePropEdit(const QString& t)
01178 {
01179   editText->resize(editText->fontMetrics().width(t)+4,
01180                    editText->fontMetrics().lineSpacing());
01181 }
01182 
01183 // -----------------------------------------------------------
01184 void QucsApp::slotCreateLib()
01185 {
01186   slotHideEdit(); // disable text edit of component property
01187 
01188   if(ProjName.isEmpty()) {
01189     QMessageBox::critical(this, tr("Error"), tr("Please open project with subcircuits!"));
01190     return;
01191   }
01192 
01193   LibraryDialog *d = new LibraryDialog(this);
01194   d->fillSchematicList(Content->exportSchematic());
01195   d->exec();
01196 }
01197 
01198 // -----------------------------------------------------------
01199 void QucsApp::slotImportData()
01200 {
01201   slotHideEdit(); // disable text edit of component property
01202 
01203   if(ProjName.isEmpty()) {
01204     QMessageBox::critical(this, tr("Error"), tr("Please open project first!"));
01205     return;
01206   }
01207 
01208   ImportDialog *d = new ImportDialog(this);
01209   if(d->exec() == QDialog::Accepted)
01210     slotUpdateTreeview();
01211 }
01212 
01213 // -----------------------------------------------------------
01214 void QucsApp::slotExportGraphAsCsv()
01215 {
01216   slotHideEdit(); // disable text edit of component property
01217 
01218   for(;;) {
01219     if(view->focusElement)
01220       if(view->focusElement->Type == isGraph)
01221         break;
01222 
01223     QMessageBox::critical(this, tr("Error"), tr("Please select a diagram graph!"));
01224     return;
01225   }
01226 
01227   /*QString s = Q3FileDialog::getSaveFileName(
01228      lastDir.isEmpty() ? QString(".") : lastDir,
01229      tr("CSV file")+" (*.csv);;" + tr("Any File")+" (*)",
01230      this, 0, tr("Enter an Output File Name"));
01231      */
01232   QString s = QFileDialog::getSaveFileName(this, tr("Enter an Output File Name"),
01233     lastDir.isEmpty() ? QString(".") : lastDir, tr("CSV file")+" (*.csv);;" + tr("Any File")+" (*)");
01234 
01235   if(s.isEmpty())
01236     return;
01237 
01238   QFileInfo Info(s);
01239   lastDir = Info.dirPath(true);  // remember last directory
01240   if(Info.extension().isEmpty())
01241     s += ".csv";
01242 
01243   QFile File(s);
01244   if(File.exists())
01245     if(QMessageBox::information(this, tr("Info"),
01246           tr("Output file already exists!")+"\n"+tr("Overwrite it?"),
01247           tr("&Yes"), tr("&No"), 0,1,1))
01248       return;
01249 
01250   if(!File.open(QIODevice::WriteOnly)) {
01251     QMessageBox::critical(this, QObject::tr("Error"),
01252                           QObject::tr("Cannot create output file!"));
01253     return;
01254   }
01255 
01256   QTextStream Stream(&File);
01257 
01258 
01259   DataX const *pD;
01260   Graph *g = (Graph*)view->focusElement;
01261   // First output the names of independent and dependent variables.
01262   for(unsigned ii=0; (pD=g->axis(ii)); ++ii)
01263     Stream << '\"' << pD->Var << "\";";
01264   Stream << "\"r " << g->Var << "\";\"i " << g->Var << "\"\n";
01265 
01266 
01267   int n, m;
01268   double *py = g->cPointsY;
01269   int Count = g->countY * g->axis(0)->count;
01270   for(n = 0; n < Count; n++) {
01271     m = n;
01272    for(unsigned ii=0; (pD=g->axis(ii)); ++ii) {
01273       Stream << *(pD->Points + m%pD->count) << ';';
01274       m /= pD->count;
01275     }
01276 
01277     Stream << *(py) << ';' << *(py+1) << '\n';
01278     py += 2;
01279   }
01280 
01281   File.close();
01282 }
01283 
01284 // ----------------------------------------------------------
01285 void QucsApp::slotCreatePackage()
01286 {
01287   slotHideEdit(); // disable text edit of component property
01288 
01289   PackageDialog *d = new PackageDialog(this, true);
01290   d->exec();
01291 }
01292 
01293 // ----------------------------------------------------------
01294 void QucsApp::slotExtractPackage()
01295 {
01296   slotHideEdit(); // disable text edit of component property
01297   PackageDialog *d = new PackageDialog(this, false);
01298   d->show();
01299   d->extractPackage();
01300   readProjects();
01301 }
01302 
01303 void QucsApp::slotOpenRecent()
01304 {
01305   QAction *action = qobject_cast<QAction *>(sender());
01306   if (action) {
01307     gotoPage(action->data().toString());
01308     updateRecentFilesList(action->data().toString());
01309   }
01310 }
01311 
01312 void QucsApp::slotUpdateRecentFiles()
01313 {
01314   QMutableStringListIterator it(QucsSettings.RecentDocs);
01315   while(it.hasNext()) {
01316     if (!QFile::exists(it.next())) {
01317         it.remove();
01318     }
01319   }
01320 
01321   for (int i = 0; i < MaxRecentFiles; ++i) {
01322     if (i < QucsSettings.RecentDocs.size()) {
01323       fileRecentAction[i]->setText(QucsSettings.RecentDocs[i]);
01324       fileRecentAction[i]->setData(QucsSettings.RecentDocs[i]);
01325       fileRecentAction[i]->setVisible(true);
01326     } else {
01327       fileRecentAction[i]->setVisible(false);
01328     }
01329   }
01330 }
01331 
01332 void QucsApp::slotClearRecentFiles()
01333 {
01334   QucsSettings.RecentDocs.clear();
01335   slotUpdateRecentFiles();
01336 }
01337 
01341 void QucsApp::slotLoadModule()
01342 {
01343     qDebug() << "slotLoadModule";
01344 
01345     LoadDialog *ld = new LoadDialog(this);
01346     ld->setApp(this);
01347 
01348     // fech list of _symbol.json
01349     // \todo fetch timestamp of VA, JSON, if VA newer, need to reload.
01350 
01351     QDir projDir = QucsSettings.QucsWorkDir.absolutePath();
01352 
01353     QStringList files;
01354     QString fileSuffix = "*_symbol.json";
01355 
01356     files = projDir.entryList(QStringList(fileSuffix),
01357                                  QDir::Files | QDir::NoSymLinks);
01358 
01359     // no JSON files or no a project?
01360     if (!files.size()){
01361         QMessageBox::critical(this, tr("Error"),
01362                      tr("Symbol files not found in: %1\n\n"
01363                         "Is the project open?\n"
01364                         "Have you saved the Verilog-A symbols?")
01365                        .arg(QString(projDir.absolutePath())));
01366         return;
01367     }
01368 
01369     // initialize dialog
01370 
01371     // pass list of potential symbol files
01372     ld->symbolFiles << files;
01373     ld->projDir = projDir;
01374     ld->initDialog();
01375 
01376     // \todo check what is already loaded, offer skip, reload
01377 
01378     //pass stuff to ld dialog
01379     // run, let user do the selections
01380 
01381     if (ld->exec() == QDialog::Accepted) {
01382 
01383       Module::vaComponents = ld->selectedComponents;
01384 
01385       // dialog write new bitmap into JSON
01386       // load, unload, reload
01387       // inform if symbol changed
01388       // populate Module::vaComponents
01389       // vaComponents are selected with the dialog
01390       // dialog should populate acording to checkboxes
01391       // build vaComponents QMap
01392 
01393       // remove all modules before registering/loaded again
01394       // look for modules in the category,
01395       // \todo investigate if it is leaking objects somewhere
01396       QStringList removeList;
01397       QHashIterator<QString, Module *> it( Module::Modules );
01398       while(it.hasNext()) {
01399         it.next();
01400         if (it.value()->category == QObject::tr("verilog-a user devices")) {
01401           removeList << it.key();
01402           delete it.value();
01403         }
01404       }
01405       for (int i = 0; i < removeList.size(); ++i){
01406         Module::Modules.remove(removeList.at(i));
01407       }
01408 
01409       if (! Module::vaComponents.isEmpty()) {
01410         // Register whatever is in Module::vaComponents
01411         Module::registerDynamicComponents();
01412 
01413         // update the combobox, set new category in view
01414         // pick up new category 'verilog-a user components' from `Module::category`
01415         //set new category into view
01416         QucsApp::fillComboBox(true);
01417         CompChoose->setCurrentItem(CompChoose->count()-1);
01418         slotSetCompView(CompChoose->count()-1);
01419 
01420         // icons of dynamically registered components ready to be dragged
01421       }
01422     }
01423 
01424     delete ld;
01425 
01426 }
01427 
01428 
01440 void QucsApp::slotBuildModule()
01441 {
01442     qDebug() << "slotBuildModule";
01443 
01444     // reset message dock on entry
01445     messageDock->reset();
01446 
01447     messageDock->builderTabs->setTabIcon(0,QPixmap());
01448     messageDock->builderTabs->setTabIcon(1,QPixmap());
01449 
01450 
01451     QString make;
01452 
01453 #ifdef __MINGW32__
01454     make = "mingw32-make.exe";    // must be on the path!
01455 #else
01456     make = "make";                // must be on the path!
01457 #endif
01458 
01459     QDir prefix = QDir(QucsSettings.BinDir+"../");
01460 
01461     QDir include = QDir(QucsSettings.BinDir+"../include/qucs-core");
01462 
01463     QString workDir = QucsSettings.QucsWorkDir.absolutePath();
01464 
01465     // need to cd into project to make sure output is droped there?
01466     // need to cd - into previous location?
01467     QDir::setCurrent(workDir);
01468 
01469     QProcess *builder = new QProcess();
01470     builder->setProcessChannelMode(QProcess::MergedChannels);
01471     // get current va document
01472     QucsDoc *Doc = getDoc();
01473     QString vaModule = Doc->fileBase(Doc->DocName);
01474 
01475     QString admsXml = QucsSettings.AdmsXmlBinDir.canonicalPath();
01476 
01477 #ifdef __MINGW32__
01478     admsXml = QDir::toNativeSeparators(admsXml+"/"+"admsXml.exe");
01479 #else
01480     admsXml = QDir::toNativeSeparators(admsXml+"/"+"admsXml");
01481 #endif
01482 
01483     // admsXml emmits C++
01484     QStringList Arguments;
01485     Arguments << "-f" <<  QDir::toNativeSeparators(include.absoluteFilePath("va2cpp.makefile"))
01486               << QString("ADMSXML=%1").arg(admsXml)
01487               << QString("PREFIX=%1").arg(QDir::toNativeSeparators(prefix.absolutePath()))
01488               << QString("MODEL=%1").arg(vaModule);
01489 
01490     QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
01491     env.insert("PATH", env.value("PATH") );
01492     builder->setProcessEnvironment(env);
01493 
01494     // prepend command to log
01495     QString cmdString = QString("%1 %2\n").arg(make, Arguments.join(" "));
01496     messageDock->admsOutput->appendPlainText(cmdString);
01497 
01498     qDebug() << "Command :" << make << Arguments.join(" ");
01499     builder->start(make, Arguments);
01500 
01501     // admsXml seems to communicate all via stdout, or is it because of make?
01502     QString vaStatus;
01503     if (!builder->waitForFinished()) {
01504         vaStatus = builder->errorString();
01505         qDebug() << "Make failed:" << vaStatus;
01506     }
01507     else {
01508         vaStatus = builder->readAll();
01509         qDebug() << "Make stdout"  << vaStatus;
01510     }
01511 
01512     //build libs
01513     qDebug() << "\nbuild libs\n";
01514 
01515     Arguments.clear();
01516 
01517     Arguments << "-f" <<  QDir::toNativeSeparators(include.absoluteFilePath("cpp2lib.makefile"))
01518               << QString("PREFIX=\"%1\"").arg(QDir::toNativeSeparators(prefix.absolutePath()))
01519               << QString("PROJDIR=\"%1\"").arg(QDir::toNativeSeparators(workDir))
01520               << QString("MODEL=%1").arg(vaModule);
01521 
01522     // prepend command to log
01523     cmdString = QString("%1 %2\n").arg(make, Arguments.join(" "));
01524     messageDock->cppOutput->appendPlainText(cmdString);
01525 
01526     builder->start(make, Arguments);
01527 
01528     QString cppStatus;
01529 
01530     if (!builder->waitForFinished()) {
01531         cppStatus = builder->errorString();
01532         qDebug() << "Make failed:" << cppStatus;
01533     }
01534     else {
01535         cppStatus = builder->readAll();
01536         qDebug() << "Make output:" << cppStatus;
01537     }
01538     delete builder;
01539 
01540     // push make output to message dock
01541     messageDock->admsOutput->appendPlainText(vaStatus);
01542     messageDock->cppOutput->appendPlainText(cppStatus);
01543 
01544     // shot the message docks
01545     messageDock->msgDock->show();
01546 
01547 }
01548 
01549 // ----------------------------------------------------------
01550 void QucsApp::slotHelpAbout()
01551 {
01552   AboutDialog *ad = new AboutDialog(this);
01553   ad->exec();
01554 }
01555 
01556 // vim:ts=8:sw=2:noet
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines