Qucs-GUI
0.0.19
|
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