TinkerCell Core 1.0
TinkerCell's Core library providing all basic functionalities
TextEditor.cpp
Go to the documentation of this file.
00001 /****************************************************************************
00002 
00003 Copyright (c) 2008 Deepak Chandran
00004 Contact: Deepak Chandran (dchandran1@gmail.com)
00005 See COPYRIGHT.TXT
00006 
00007 This file defines the TextEditor class. The TextEditor and Canvas are two ways to define a network.
00008 The Canvas is used for graphical reprentation of a network, whereas the TextEditor is used for
00009 text-based representation of a network.
00010 
00011 ****************************************************************************/
00012 #include <iostream>
00013 #include "NetworkHandle.h"
00014 #include "ConsoleWindow.h"
00015 #include "NetworkWindow.h"
00016 #include "MainWindow.h"
00017 #include "TextEditor.h"
00018 #include "ItemFamily.h"
00019 #include "ItemHandle.h"
00020 #include "Tool.h"
00021 #include "UndoCommands.h"
00022 #include <QTextBlock>
00023 #include <QTextCharFormat>
00024 #include <QFont>
00025 #include <QVBoxLayout>
00026 #include <QRegExp>
00027 #include <QGroupBox>
00028 #include <QTextCursor>
00029 #include <QListWidgetItem>
00030 #include <QTableWidget>
00031 #include <QTableWidgetItem>
00032 #include <QHeaderView>
00033 
00034 namespace Tinkercell
00035 {
00036         bool TextEditor::SideBarEnabled = true;
00037         void TextEditor::push(QUndoCommand * c)
00038         {
00039                 if (!network)
00040                 {
00041                         delete c;
00042                         return;
00043                 }
00044                 
00045                 QString text = tr("text changed");
00046                 if (c)
00047                         text = c->text();
00048                 QUndoCommand * composite = new CompositeCommand(text, new TextUndoCommand(this, prevText, toPlainText()), c);
00049 
00050                 network->history.push( composite );
00051         }
00052 
00053         void TextEditor::undo()
00054         {
00055                 if (network)
00056                         network->history.undo();
00057         }
00058 
00059         void TextEditor::redo()
00060         {
00061                 if (network)
00062                         network->history.redo();
00063         }
00064 
00065         void TextEditor::copy()
00066         {
00067                 CodeEditor::copy();
00068         }
00069 
00070         void TextEditor::cut()
00071         {
00072                 CodeEditor::cut();
00073                 int i = -1;
00074                 if (network)
00075                         i = network->history.count();
00076                 emit textChanged(this, tr(""), tr(""), prevText);
00077                 if (network && i > -1 && i == network->history.count())
00078                         push(0);
00079                 prevText = toPlainText();
00080         }
00081 
00082         void TextEditor::paste()
00083         {
00084                 CodeEditor::paste();
00085                 int i = -1;
00086                 if (network)
00087                         i = network->history.count();
00088                 emit textChanged(this, tr(""), tr(""), prevText);
00089                 if (network && i > -1 && i == network->history.count())
00090                         push(0);
00091                 prevText = toPlainText();
00092         }
00093 
00094         void TextEditor::selectAll()
00095         {
00096                 CodeEditor::selectAll();
00097         }
00098 
00099         void TextEditor::print(QPrinter * printer)
00100         {
00101                 CodeEditor::print(printer);
00102         }
00103 
00104         TextEditor::TextEditor( NetworkHandle * network, QWidget * parent) : CodeEditor(parent), network(network), networkWindow(0)
00105         {
00106                 contextEditorMenu = 0;
00107                 contextSelectionMenu = 0;
00108                 setUndoRedoEnabled(false);
00109                 prevBlockNumber = -1;
00110                 changedBlockNumber = -1;
00111                 setWordWrapMode(QTextOption::NoWrap);
00112                 connect(this,SIGNAL(textChanged()),this,SLOT(textChangedSlot()));
00113         }
00114 
00115         TextEditor::~TextEditor()
00116         {
00117                 /*for (int i=0; i < allItems.size(); ++i)
00118                         if (allItems[i])
00119                         {
00120                                 for (int j=(i+1); j < allItems.size(); ++j)
00121                                 {
00122                                         if (allItems[j] == allItems[i])
00123                                                 allItems[j] = 0;
00124                                 }
00125                                 if (!allItems[i]->handle() || (allItems[i]->handle() && allItems[i]->handle()->parent == 0))
00126                                         delete allItems[i];
00127                                 allItems[i] = 0;
00128                         }*/
00129         }
00130 
00131         QString TextEditor::selectedText() const
00132         {
00133                 return textCursor().selectedText();
00134         }
00135 
00136         void TextEditor::contextMenuEvent ( QContextMenuEvent * event )
00137         {
00138                 if (!network || !network->mainWindow || !event) return;
00139 
00140                 if (selectedText().isEmpty())
00141                         network->mainWindow->contextEditorMenu.exec(event->globalPos());
00142                 else
00143                         network->mainWindow->contextSelectionMenu.exec(event->globalPos());
00144         }
00145 
00146         QList<ItemHandle*>& TextEditor::items()
00147         {
00148                 return allItems;
00149         }
00150 
00151         void TextEditor::setItems( const QList<ItemHandle*>& newItems)
00152         {
00153                 QList<QUndoCommand*> commands;
00154 
00155                 if (localHandle())
00156                 {
00157                         QString parentNameWithDot = localHandle()->fullName() + tr("\\.");
00158                         QString parentNameWithUnderscore = localHandle()->fullName("_") + tr("_");
00159                         for (int i=0; i < newItems.size(); ++i)
00160                                 if (newItems[i])
00161                                 {
00162                                         if (newItems[i]->name.startsWith(parentNameWithDot))
00163                                                 newItems[i]->name.replace(QRegExp( tr("^") + parentNameWithDot ), tr(""));
00164                                         else                                    
00165                                         if (newItems[i]->name.startsWith(parentNameWithUnderscore))
00166                                                 newItems[i]->name.replace(QRegExp( tr("^") + parentNameWithUnderscore ), tr(""));
00167                                 }
00168                 }
00169 
00170                 commands << new RemoveHandlesCommand(this,allItems,false)
00171                                             << new InsertHandlesCommand(this,newItems,false);
00172         
00173                 emit itemsRemoved(network, allItems);
00174         
00175                 if (prevBlockText.isEmpty())
00176                         push( new CompositeCommand(tr("line ") + QString::number(prevBlockNumber+1) + tr(" changed"),commands)  );
00177                 else
00178                         push( new CompositeCommand(prevBlockText,commands)  );
00179 
00180                 emit itemsInserted(network, newItems);
00181         }
00182 
00183         void TextEditor::insert( ItemHandle * item )
00184         {
00185                 if (item && !allItems.contains(item))
00186                 {
00187                         if (localHandle())
00188                         {
00189                                 QString parentNameWithDot = localHandle()->fullName() + tr("\\.");
00190                                 QString parentNameWithUnderscore = localHandle()->fullName("_") + tr("_");
00191                                 if (item->name.startsWith(parentNameWithDot))
00192                                         item->name.replace(QRegExp( tr("^") + parentNameWithDot ), tr(""));
00193                                 else
00194                                 if (item->name.startsWith(parentNameWithUnderscore))
00195                                         item->name.replace(QRegExp( tr("^") + parentNameWithUnderscore ), tr(""));
00196                         }
00197 
00198                         push( new InsertHandlesCommand(this,item) );
00199 
00200                         QList<ItemHandle*> handles;
00201                         handles << item;
00202                         emit itemsInserted(network, handles);
00203                 }
00204         }
00205 
00206         void TextEditor::insert( const QList<ItemHandle*>& newItems)
00207         {
00208                 if (localHandle())
00209                 {
00210                         QString parentNameWithDot = localHandle()->fullName() + tr("\\.");
00211                         QString parentNameWithUnderscore = localHandle()->fullName("_") + tr("_");
00212                         for (int i=0; i < newItems.size(); ++i)
00213                                 if (newItems[i])
00214                                 {
00215                                         if (newItems[i]->name.startsWith(parentNameWithDot))
00216                                                 newItems[i]->name.replace(QRegExp( tr("^") + parentNameWithDot ), tr(""));
00217                                         else                                    
00218                                         if (newItems[i]->name.startsWith(parentNameWithUnderscore))
00219                                                 newItems[i]->name.replace(QRegExp( tr("^") + parentNameWithUnderscore ), tr(""));
00220                                 }
00221                 }
00222 
00223                 push( new InsertHandlesCommand(this,newItems) );
00224 
00225                 emit itemsInserted(network, newItems);
00226         }
00227 
00228         void TextEditor::remove( ItemHandle * item)
00229         {
00230                 if (item && allItems.contains(item))
00231                 {
00232                         push( new RemoveHandlesCommand(this,item) );
00233 
00234                         QList<ItemHandle*> handles;
00235                         handles << item;
00236                         emit itemsRemoved(network, handles);
00237                 }
00238 
00239         }
00240 
00241         void TextEditor::remove( const QList<ItemHandle*>& handles)
00242         {
00243                 push( new RemoveHandlesCommand(this,handles) );
00244 
00245                 emit itemsRemoved(network, handles);
00246         }
00247 
00248         void TextEditor::textChangedSlot()
00249         {
00250                 changedBlockNumber = textCursor().blockNumber();
00251                 if (prevBlockNumber == changedBlockNumber)
00252                         changedBlockText = textCursor().block().text();
00253         }
00254         
00255         void TextEditor::mousePressEvent ( QMouseEvent * event )
00256         {
00257                 if (networkWindow)
00258                         networkWindow->setAsCurrentWindow();
00259                 
00260                 CodeEditor::mousePressEvent(event);
00261         }
00262 
00263         void TextEditor::keyPressEvent ( QKeyEvent * event )
00264         {
00265                 if (networkWindow)
00266                         networkWindow->setAsCurrentWindow();
00267 
00268                 int n0 = textCursor().blockNumber();
00269 
00270                 if (event->matches(QKeySequence::Redo)) //redo
00271                 {
00272                         if (network)
00273                                 network->history.redo();
00274                         return;
00275                 }
00276                 else
00277                         if (event->matches(QKeySequence::Undo))  //undo
00278                         {
00279                                 if (network)
00280                                         network->history.undo();
00281                                 return;
00282                         }
00283                         else
00284                                 if (event->matches(QKeySequence::Copy)) //redo
00285                                 {
00286                                         copy();
00287                                         return;
00288                                 }
00289                                 else
00290                                         if (event->matches(QKeySequence::Cut))  //undo
00291                                         {
00292                                                 cut();
00293                                                 return;
00294                                         }
00295                                         else
00296                                                 if (event->matches(QKeySequence::Paste))  //undo
00297                                                 {
00298                                                         paste();
00299                                                         return;
00300                                                 }
00301                                                 else
00302                                                         CodeEditor::keyPressEvent(event);
00303 
00304                 int n1 = textCursor().blockNumber();
00305 
00306                 if (n0 != n1)
00307                 {
00308                         if (changedBlockNumber > -1)
00309                         {
00310                                 int i = -1;
00311                                 if (network)
00312                                         i = network->history.count();
00313                                 emit textChanged(this, prevBlockText, changedBlockText, prevText);
00314                                 if (network && i > -1 && i == network->history.count())
00315                                         push(0);
00316                                 prevText = toPlainText();
00317                         }
00318                         prevBlockText = textCursor().block().text();
00319                         prevBlockNumber = n1;
00320                         changedBlockNumber = -1;
00321 
00322                         emit lineChanged(this, n1,prevBlockText);
00323                 }
00324         }
00325 
00326         void TextEditor::mouseReleaseEvent ( QMouseEvent * event )
00327         {
00328                 int n1 = textCursor().blockNumber();
00329                 if (changedBlockNumber > -1)
00330                 {
00331                         emit textChanged(this, prevBlockText, changedBlockText, prevText);
00332                         prevText = toPlainText();
00333                 }
00334 
00335                 prevBlockText = textCursor().block().text();
00336                 prevBlockNumber = n1;
00337                 changedBlockNumber = -1;
00338 
00339                 emit lineChanged(this, n1,prevBlockText);
00340         }
00341 
00342         TextUndoCommand::TextUndoCommand(TextEditor * editor, const QString& oldText, const QString& newText)
00343                 : textEdit(editor)
00344         {
00345                 if (editor)
00346                 {
00347                         this->oldText = oldText;
00348                         this->newText = newText;
00349                 }
00350         }
00351 
00352         void TextUndoCommand::redo()
00353         {
00354                 if (textEdit)
00355                 {
00356                         int pos = textEdit->textCursor().position();
00357                         textEdit->setPlainText( newText );
00358                         QTextCursor cursor = textEdit->textCursor();
00359                         cursor.setPosition(pos);
00360                         textEdit->setTextCursor(cursor);
00361                 }
00362         }
00363 
00364         void TextUndoCommand::undo()
00365         {
00366                 if (textEdit)
00367                 {
00368                         int pos = textEdit->textCursor().position();
00369                         textEdit->setPlainText( oldText );
00370                         QTextCursor cursor = textEdit->textCursor();
00371                         cursor.setPosition(pos);
00372                         textEdit->setTextCursor(cursor);
00373                 }
00374         }
00375         
00376         MainWindow * TextEditor::mainWindow() const
00377         {
00378                 if (network)
00379                         return network->mainWindow;
00380                 return 0;
00381         }
00382         
00383         ConsoleWindow * TextEditor::console() const
00384         {
00385                 if (network && network->mainWindow)
00386                         return network->mainWindow->console();
00387                 return 0;
00388         }
00389         
00390         ItemHandle * TextEditor::localHandle() const
00391         {
00392                 if (networkWindow)
00393                         return networkWindow->handle;
00394                 return 0;
00395         }
00396         
00397         ItemHandle * TextEditor::globalHandle() const
00398         {
00399                 if (network)
00400                         return network->globalHandle();
00401                 return 0;
00402         }
00403         
00404         void TextEditor::popOut()
00405         {
00406                 if (networkWindow)
00407                         networkWindow->popOut();
00408         }
00409         
00410         void TextEditor::popIn()
00411         {
00412                 if (networkWindow)
00413                         networkWindow->popIn();
00414         }
00415 
00416 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines