Qucs-GUI  0.0.19
/home/travis/build/Qucs/qucs/qucs/qucs/textdoc.cpp
Go to the documentation of this file.
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 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines