![]() |
TinkerCell Core 1.0
TinkerCell's Core library providing all basic functionalities
|
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 }