Qucs-GUI
0.0.19
|
00001 /*************************************************************************** 00002 textdoc.cpp 00003 ------------- 00004 Copyright (C) 2006 by Michael Margraf <michael.margraf@alumni.tu-berlin.de> 00005 Copyright (C) 2014 by Guilherme Brondani Torri <guitorri@gmail.com> 00006 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00018 #ifdef HAVE_CONFIG_H 00019 # include <config.h> 00020 #endif 00021 #include <QAction> 00022 #include <QMessageBox> 00023 00024 #include "main.h" 00025 #include "qucs.h" 00026 #include "textdoc.h" 00027 #include "syntax.h" 00028 #include "components/vhdlfile.h" 00029 #include "components/verilogfile.h" 00030 #include "components/vafile.h" 00031 00042 TextDoc::TextDoc(QucsApp *App_, const QString& Name_) : QPlainTextEdit(), QucsDoc(App_, Name_) 00043 { 00044 TextFont = QFont("Courier New"); 00045 TextFont.setPointSize(QucsSettings.font.pointSize()-1); 00046 TextFont.setStyleHint(QFont::Courier); 00047 TextFont.setFixedPitch(true); 00048 document()->setDefaultFont(TextFont); 00049 00050 simulation = true; 00051 Library = ""; 00052 Libraries = ""; 00053 SetChanged = false; 00054 devtype = DEV_DEF; 00055 00056 tmpPosX = tmpPosY = 1; // set to 1 to trigger line highlighting 00057 Scale = (float)TextFont.pointSize(); 00058 setLanguage (Name_); 00059 00060 viewport()->setFocus(); 00061 00062 setWordWrapMode(QTextOption::NoWrap); 00063 setPaletteBackgroundColor(QucsSettings.BGColor); 00064 connect(this, SIGNAL(textChanged()), SLOT(slotSetChanged())); 00065 connect(this, SIGNAL(cursorPositionChanged()), 00066 SLOT(slotCursorPosChanged())); 00067 if (App_) { 00068 connect(this, SIGNAL(signalCursorPosChanged(int, int)), 00069 App_, SLOT(printCursorPosition(int, int))); 00070 connect(this, SIGNAL(signalUndoState(bool)), 00071 App_, SLOT(slotUpdateUndo(bool))); 00072 connect(this, SIGNAL(signalRedoState(bool)), 00073 App_, SLOT(slotUpdateRedo(bool))); 00074 connect(this, SIGNAL(signalFileChanged(bool)), 00075 App_, SLOT(slotFileChanged(bool))); 00076 } 00077 00078 syntaxHighlight = new SyntaxHighlighter(this); 00079 syntaxHighlight->setLanguage(language); 00080 syntaxHighlight->setDocument(document()); 00081 00082 connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine())); 00083 highlightCurrentLine(); 00084 } 00085 00089 TextDoc::~TextDoc() 00090 { 00091 delete syntaxHighlight; 00092 } 00093 00099 void TextDoc::setLanguage (const QString& FileName) 00100 { 00101 QFileInfo Info (FileName); 00102 QString ext = Info.extension (false); 00103 if (ext == "vhd" || ext == "vhdl") 00104 setLanguage (LANG_VHDL); 00105 else if (ext == "v") 00106 setLanguage (LANG_VERILOG); 00107 else if (ext == "va") 00108 setLanguage (LANG_VERILOGA); 00109 else if (ext == "m" || ext == "oct") 00110 setLanguage (LANG_OCTAVE); 00111 else 00112 setLanguage (LANG_NONE); 00113 } 00114 00120 void TextDoc::setLanguage (int lang) 00121 { 00122 language = lang; 00123 } 00124 00129 bool TextDoc::saveSettings (void) 00130 { 00131 QFile file (DocName + ".cfg"); 00132 if (!file.open (QIODevice::WriteOnly)) 00133 return false; 00134 00135 QTextStream stream (&file); 00136 stream << "Textfile settings file, Qucs " PACKAGE_VERSION "\n" 00137 << "Simulation=" << simulation << "\n" 00138 << "Duration=" << SimTime << "\n" 00139 << "Module=" << (!simulation) << "\n" 00140 << "Library=" << Library << "\n" 00141 << "Libraries=" << Libraries << "\n" 00142 << "ShortDesc=" << ShortDesc << "\n" 00143 << "LongDesc=" << LongDesc << "\n" 00144 << "Icon=" << Icon << "\n" 00145 << "Recreate=" << recreate << "\n" 00146 << "DeviceType=" << devtype << "\n"; 00147 00148 file.close (); 00149 SetChanged = false; 00150 return true; 00151 } 00152 00157 bool TextDoc::loadSettings (void) 00158 { 00159 QFile file (DocName + ".cfg"); 00160 if (!file.open (QIODevice::ReadOnly)) 00161 return false; 00162 00163 QTextStream stream (&file); 00164 QString Line, Setting; 00165 00166 bool ok; 00167 while (!stream.atEnd ()) { 00168 Line = stream.readLine (); 00169 Setting = Line.section ('=', 0, 0); 00170 Line = Line.section ('=', 1).trimmed (); 00171 if (Setting == "Simulation") { 00172 simulation = Line.toInt (&ok); 00173 } else if (Setting == "Duration") { 00174 SimTime = Line; 00175 } else if (Setting == "Module") { 00176 } else if (Setting == "Library") { 00177 Library = Line; 00178 } else if (Setting == "Libraries") { 00179 Libraries = Line; 00180 } else if (Setting == "ShortDesc") { 00181 ShortDesc = Line; 00182 } else if (Setting == "LongDesc") { 00183 LongDesc = Line; 00184 } else if (Setting == "Icon") { 00185 Icon = Line; 00186 } else if (Setting == "Recreate") { 00187 recreate = Line.toInt (&ok); 00188 } else if (Setting == "DeviceType") { 00189 devtype = Line.toInt (&ok); 00190 } 00191 } 00192 00193 file.close (); 00194 return true; 00195 } 00196 00201 void TextDoc::setName (const QString& Name_) 00202 { 00203 DocName = Name_; 00204 setLanguage (DocName); 00205 00206 QFileInfo Info (DocName); 00207 00208 DataSet = Info.baseName (true) + ".dat"; 00209 DataDisplay = Info.baseName (true) + ".dpl"; 00210 if(Info.extension(false) == "m" || Info.extension(false) == "oct") 00211 SimTime = "1"; 00212 } 00213 00219 void TextDoc::becomeCurrent (bool) 00220 { 00221 slotCursorPosChanged(); 00222 viewport()->setFocus (); 00223 00224 emit signalUndoState(document()->isUndoAvailable()); 00225 emit signalRedoState(document()->isRedoAvailable()); 00226 00227 // update appropriate menu entries 00228 App->symEdit->setMenuText (tr("Edit Text Symbol")); 00229 App->symEdit->setStatusTip (tr("Edits the symbol for this text document")); 00230 App->symEdit->setWhatsThis ( 00231 tr("Edit Text Symbol\n\nEdits the symbol for this text document")); 00232 00233 if (language == LANG_VHDL) { 00234 App->insEntity->setMenuText (tr("VHDL entity")); 00235 App->insEntity->setStatusTip (tr("Inserts skeleton of VHDL entity")); 00236 App->insEntity->setWhatsThis ( 00237 tr("VHDL entity\n\nInserts the skeleton of a VHDL entity")); 00238 } 00239 else if (language == LANG_VERILOG || language == LANG_VERILOGA) { 00240 App->insEntity->setMenuText (tr("Verilog module")); 00241 App->insEntity->setStatusTip (tr("Inserts skeleton of Verilog module")); 00242 App->insEntity->setWhatsThis ( 00243 tr("Verilog module\n\nInserts the skeleton of a Verilog module")); 00244 App->buildModule->setEnabled(true); 00245 } 00246 else if (language == LANG_OCTAVE) { 00247 App->insEntity->setMenuText (tr("Octave function")); 00248 App->insEntity->setStatusTip (tr("Inserts skeleton of Octave function")); 00249 App->insEntity->setWhatsThis ( 00250 tr("Octave function\n\nInserts the skeleton of a Octave function")); 00251 } 00252 App->simulate->setEnabled (true); 00253 App->editActivate->setEnabled (true); 00254 } 00255 00256 bool TextDoc::baseSearch(const QString &str, bool CaseSensitive, bool wordOnly, bool backward) 00257 { 00258 QFlag flag = 0; 00259 bool finded; 00260 00261 if (CaseSensitive) { 00262 flag = QTextDocument::FindCaseSensitively; 00263 } 00264 if (backward) { 00265 flag = flag | QTextDocument::FindBackward; 00266 } 00267 if (wordOnly) { 00268 flag = flag | QTextDocument::FindWholeWords; 00269 } 00270 00271 finded = find(str, flag); 00272 if (!finded) { 00273 if (!backward) { 00274 moveCursor(QTextCursor::Start); 00275 } else { 00276 moveCursor(QTextCursor::End); 00277 } 00278 finded = find(str, flag); 00279 if (!finded) { 00280 QMessageBox::information(this, 00281 tr("Find..."), tr("Cannot find target: %1").arg(str), 00282 QMessageBox::Ok | QMessageBox::Default | QMessageBox::Escape); 00283 } 00284 } 00285 return finded; 00286 } 00287 00288 // implement search function 00289 // if target not find, auto revert to head, find again 00290 // if still not find, pop out message 00291 void TextDoc::search(const QString &str, bool CaseSensitive, bool wordOnly, bool backward) 00292 { 00293 baseSearch(str, CaseSensitive, wordOnly, backward); 00294 } 00295 00296 // implement replace function 00297 void TextDoc::replace(const QString &str, const QString &str2, bool needConfirmed, 00298 bool CaseSensitive, bool wordOnly, bool backward) 00299 { 00300 bool finded = baseSearch(str, CaseSensitive, wordOnly, backward); 00301 int i; 00302 00303 if(finded) { 00304 i = QMessageBox::Yes; 00305 if (needConfirmed) { 00306 i = QMessageBox::information(this, 00307 tr("Replace..."), tr("Replace occurrence ?"), 00308 QMessageBox::Yes | QMessageBox::Default, 00309 QMessageBox::No | QMessageBox::Escape); 00310 } 00311 if(i == QMessageBox::Yes) { 00312 insertPlainText(str2); 00313 } 00314 } 00315 } 00316 00317 00321 void TextDoc::slotCursorPosChanged() 00322 { 00323 QTextCursor pos = textCursor(); 00324 int x = pos.blockNumber(); 00325 int y = pos.columnNumber(); 00326 emit signalCursorPosChanged(x+1, y+1); 00327 tmpPosX = x; 00328 tmpPosY = y; 00329 } 00330 00334 void TextDoc::slotSetChanged() 00335 { 00336 if((document()->isModified() && !DocChanged) || SetChanged) { 00337 DocChanged = true; 00338 } 00339 else if((!document()->isModified() && DocChanged)) { 00340 DocChanged = false; 00341 } 00342 emit signalFileChanged(DocChanged); 00343 emit signalUndoState(document()->isUndoAvailable()); 00344 emit signalRedoState(document()->isRedoAvailable()); 00345 } 00346 00354 QMenu *TextDoc::createStandardContextMenu() 00355 { 00356 QMenu *popup = QPlainTextEdit::createStandardContextMenu(); 00357 00358 if (language != LANG_OCTAVE) { 00359 App->fileSettings->addTo((QWidget *)popup); 00360 } 00361 return popup; 00362 } 00363 00368 bool TextDoc::load () 00369 { 00370 QFile file (DocName); 00371 if (!file.open (QIODevice::ReadOnly)) 00372 return false; 00373 setLanguage (DocName); 00374 00375 QTextStream stream (&file); 00376 insertPlainText(stream.read ()); 00377 document()->setModified(false); 00378 slotSetChanged (); 00379 file.close (); 00380 lastSaved = QDateTime::currentDateTime (); 00381 loadSettings (); 00382 SimOpenDpl = simulation ? true : false; 00383 refreshLanguage(); 00384 return true; 00385 } 00386 00387 00392 int TextDoc::save () 00393 { 00394 saveSettings (); 00395 00396 QFile file (DocName); 00397 if (!file.open (QIODevice::WriteOnly)) 00398 return -1; 00399 setLanguage (DocName); 00400 00401 QTextStream stream (&file); 00402 stream << toPlainText(); 00403 document()->setModified (false); 00404 slotSetChanged (); 00405 file.close (); 00406 00407 QFileInfo Info (DocName); 00408 lastSaved = Info.lastModified (); 00409 00411 QList<QTextEdit::ExtraSelection> extraSelections; 00412 this->setExtraSelections(extraSelections); 00413 refreshLanguage(); 00414 00415 return 0; 00416 } 00417 00425 float TextDoc::zoomBy(float s) 00426 { 00427 if(s == 2.0) { 00428 QFont f = document()->defaultFont(); 00429 f.setPointSize(f.pointSize()*2); 00430 document()->setDefaultFont(f); 00431 } 00432 else { 00433 QFont f = document()->defaultFont(); 00434 f.setPointSize(f.pointSize()*s); 00435 document()->setDefaultFont(f); 00436 } 00437 return Scale; 00438 } 00439 00443 void TextDoc::showNoZoom() 00444 { 00445 TextFont = QFont("Courier New"); 00446 TextFont.setPointSize(QucsSettings.font.pointSize()-1); 00447 TextFont.setStyleHint(QFont::Courier); 00448 TextFont.setFixedPitch(true); 00449 document()->setDefaultFont(TextFont); 00450 } 00451 00457 bool TextDoc::loadSimulationTime(QString& Time) 00458 { 00459 if(!SimTime.isEmpty()) { 00460 Time = SimTime; 00461 return true; 00462 } 00463 return false; 00464 } 00465 00470 void TextDoc::commentSelected () 00471 { 00472 QTextCursor cursor = this->textCursor(); 00473 00474 if(!cursor.hasSelection()) 00475 return; // No selection available 00476 00477 // get range of selection 00478 int start = cursor.selectionStart(); 00479 int end = cursor.selectionEnd(); 00480 00481 cursor.setPosition(start); 00482 int firstLine = cursor.blockNumber(); 00483 cursor.setPosition(end, QTextCursor::KeepAnchor); 00484 int lastLine = cursor.blockNumber(); 00485 00486 // use comment string indicator depending on language 00487 QString co; 00488 00489 switch (language) { 00490 case LANG_VHDL: 00491 co = "--"; 00492 break; 00493 case LANG_VERILOG: 00494 case LANG_VERILOGA: 00495 co = "//"; 00496 break; 00497 case LANG_OCTAVE: 00498 co = "%"; 00499 break; 00500 default: 00501 co = ""; 00502 break; 00503 } 00504 00505 QStringList newlines; 00506 for (int i=firstLine; i<=lastLine; i++) { 00507 QString line = document()->findBlockByLineNumber(i).text(); 00508 if (line.startsWith(co)){ 00509 // uncomment 00510 line.remove(0,co.length()); 00511 newlines << line; 00512 } 00513 else { 00514 // comment 00515 line = line.insert(0, co); 00516 newlines << line; 00517 } 00518 } 00519 insertPlainText(newlines.join("\n")); 00520 } 00521 00525 void TextDoc::insertSkeleton () 00526 { 00527 if (language == LANG_VHDL) 00528 appendPlainText("entity is\n port ( : in bit);\nend;\n" 00529 "architecture of is\n signal : bit;\nbegin\n\nend;\n\n"); 00530 else if (language == LANG_VERILOG) 00531 appendPlainText ("module ( );\ninput ;\noutput ;\nbegin\n\nend\n" 00532 "endmodule\n\n"); 00533 else if (language == LANG_OCTAVE) 00534 appendPlainText ("function = ( )\n" 00535 "endfunction\n\n"); 00536 } 00537 00542 QString TextDoc::getModuleName (void) 00543 { 00544 switch (language) { 00545 case LANG_VHDL: 00546 { 00547 VHDL_File_Info VInfo (toPlainText()); 00548 return VInfo.EntityName; 00549 } 00550 case LANG_VERILOG: 00551 { 00552 Verilog_File_Info VInfo (toPlainText()); 00553 return VInfo.ModuleName; 00554 } 00555 case LANG_VERILOGA: 00556 { 00557 VerilogA_File_Info VInfo (toPlainText()); 00558 return VInfo.ModuleName; 00559 } 00560 case LANG_OCTAVE: 00561 { 00562 QFileInfo Info (DocName); 00563 return Info.baseName (true); 00564 } 00565 default: 00566 return ""; 00567 } 00568 } 00569 00573 void TextDoc::highlightCurrentLine() 00574 { 00575 QList<QTextEdit::ExtraSelection> extraSelections; 00576 00577 if (!isReadOnly()) { 00578 QTextEdit::ExtraSelection selection; 00579 00580 QColor lineColor = QColor(Qt::blue).lighter(195); 00581 00582 selection.format.setBackground(lineColor); 00583 selection.format.setProperty(QTextFormat::FullWidthSelection, true); 00584 selection.cursor = textCursor(); 00585 selection.cursor.clearSelection(); 00586 extraSelections.append(selection); 00587 } 00588 00589 setExtraSelections(extraSelections); 00590 } 00591 00592 void TextDoc::refreshLanguage() 00593 { 00594 this->setLanguage(DocName); 00595 syntaxHighlight->setLanguage(language); 00596 syntaxHighlight->setDocument(document()); 00597 }