File indexing completed on 2024-05-12 05:40:37
0001 /* 0002 Cahoots is a crossplatform real-time collaborative text editor. 0003 0004 Copyright (C) 2010 Chris Dimpfl, Anandi Hira, David Vega 0005 0006 This program is free software: you can redistribute it and/or modify 0007 it under the terms of the GNU General Public License as published by 0008 the Free Software Foundation, either version 3 of the License, or 0009 (at your option) any later version. 0010 0011 This program is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 GNU General Public License for more details. 0015 0016 You should have received a copy of the GNU General Public License 0017 along with this program. If not, see <http://www.gnu.org/licenses/>. 0018 */ 0019 #include "document.h" 0020 0021 #include <QDebug> 0022 #include <QDialog> 0023 #include <QFontMetrics> 0024 #include <QLayout> 0025 #include <QMessageBox> 0026 #include <QRegularExpression> 0027 #include <QTextDocumentFragment> 0028 0029 #include "controller/view_controller/sharednotecontroller.h" 0030 #include "markdownhighlighter.h" 0031 #include "ui_document.h" 0032 0033 #include "enu.h" 0034 #include "utilities.h" 0035 0036 Document::Document(SharedNoteController* ctrl, QWidget* parent) 0037 : QWidget(parent), m_shareCtrl(ctrl), ui(new Ui::Document), m_highlighter(nullptr) 0038 { 0039 ui->setupUi(this); 0040 0041 // Set up the editor 0042 delete ui->editorFrame; 0043 m_editor= new sharedNotes::CodeEditor(m_shareCtrl, this); 0044 0045 if(!m_shareCtrl) 0046 return; 0047 0048 setPlainText(m_shareCtrl->text()); 0049 0050 m_previewMarkdown= new QTextEdit(); 0051 m_previewMarkdown->setReadOnly(true); 0052 QFontMetricsF fm(m_editor->font()); 0053 m_editor->setTabStopDistance(fm.averageCharWidth() * 4.); 0054 ui->editorSplitter->insertWidget(0, m_editor); 0055 0056 m_previewMarkdown->setVisible(m_shareCtrl->markdownVisible()); 0057 0058 m_participantPane.reset(new ParticipantsPane(m_shareCtrl)); 0059 ui->participantSplitter->insertWidget(1, m_previewMarkdown); 0060 ui->participantSplitter->insertWidget(2, m_participantPane.get()); 0061 0062 connect(m_shareCtrl, &SharedNoteController::permissionChanged, this, [this](ParticipantModel::Permission perm) { 0063 m_editor->setReadOnly(ParticipantModel::Permission::readOnly == perm); 0064 }); 0065 0066 connect(m_shareCtrl, &SharedNoteController::markdownVisibleChanged, m_previewMarkdown, &QTextEdit::setVisible); 0067 connect(m_shareCtrl, &SharedNoteController::textChanged, m_previewMarkdown, &QTextEdit::setMarkdown); 0068 0069 connect(m_editor, &sharedNotes::CodeEditor::textChanged, this, &Document::contentChanged); 0070 0071 m_editor->setReadOnly(m_shareCtrl->permission() == ParticipantModel::Permission::readOnly); 0072 0073 // delete ui->findAllFrame; 0074 findAllToolbar= new FindToolBar(this); 0075 ui->editorVerticalLayout->insertWidget(1, findAllToolbar); 0076 findAllToolbar->hide(); 0077 0078 connect(findAllToolbar, &FindToolBar::findAll, m_editor, &sharedNotes::CodeEditor::findAll); 0079 // connect(findAllToolbar, &FindToolBar::findNext, this, &Document::findNext); 0080 connect(findAllToolbar, &FindToolBar::findPrevious, this, &Document::findPrevious); 0081 0082 // Emit signals to the mainwindow when redoability/undoability changes 0083 connect(m_editor, &sharedNotes::CodeEditor::undoAvailable, this, &Document::undoAvailable); 0084 connect(m_editor, &sharedNotes::CodeEditor::redoAvailable, this, &Document::redoAvailable); 0085 0086 connect(m_shareCtrl, &SharedNoteController::highligthedSyntaxChanged, this, &Document::updateHighlighter); 0087 0088 QList<int> sizeList; 0089 sizeList << 900 << 100 << 100; 0090 ui->codeChatSplitter->setSizes(sizeList); 0091 ui->participantSplitter->setSizes(sizeList); 0092 0093 startedCollaborating= false; 0094 0095 updateHighlighter(); 0096 auto text= m_shareCtrl->text(); 0097 if(!text.isEmpty()) 0098 setPlainText(text); 0099 } 0100 0101 Document::~Document() 0102 { 0103 delete ui; 0104 } 0105 /* 0106 * 0107 */ 0108 0109 void Document::displayParticipantPanel() 0110 { 0111 startedCollaborating= true; 0112 setParticipantsHidden(false); 0113 } 0114 0115 void Document::setEditorFont(QFont font) 0116 { 0117 m_editor->setFont(font); 0118 QFontMetrics fm(m_editor->font()); 0119 m_editor->setTabStopDistance(fm.averageCharWidth() * 4); 0120 } 0121 0122 void Document::setParticipantsFont(QFont font) 0123 { 0124 m_participantPane->setFont(font); 0125 } 0126 0127 void Document::undo() 0128 { 0129 if(m_editor->hasFocus()) 0130 { 0131 m_editor->undo(); 0132 } 0133 } 0134 0135 void Document::redo() 0136 { 0137 if(m_editor->hasFocus()) 0138 { 0139 m_editor->redo(); 0140 } 0141 } 0142 0143 void Document::cut() 0144 { 0145 if(m_editor->hasFocus()) 0146 { 0147 m_editor->cut(); 0148 } 0149 else if(m_participantPane->hasFocus()) 0150 { 0151 // do nothing 0152 } 0153 } 0154 0155 void Document::copy() 0156 { 0157 if(m_editor->hasFocus()) 0158 { 0159 m_editor->copy(); 0160 } 0161 else if(m_participantPane->hasFocus()) 0162 { 0163 // do nothing 0164 } 0165 } 0166 0167 void Document::paste() 0168 { 0169 if(m_editor->hasFocus()) 0170 { 0171 m_editor->paste(); 0172 } 0173 else if(m_participantPane->hasFocus()) 0174 { 0175 // do nothing 0176 } 0177 } 0178 0179 void Document::setParticipantsHidden(bool b) 0180 { 0181 if(b) 0182 { 0183 ui->participantSplitter->widget(2)->hide(); 0184 } 0185 else 0186 { 0187 ui->participantSplitter->widget(2)->show(); 0188 m_editor->resize(QSize(9000, 9000)); 0189 } 0190 } 0191 0192 void Document::shiftLeft() 0193 { 0194 m_editor->shiftLeft(); 0195 } 0196 0197 void Document::shiftRight() 0198 { 0199 m_editor->shiftRight(); 0200 } 0201 0202 void Document::unCommentSelection() 0203 { 0204 m_editor->unCommentSelection(); 0205 } 0206 0207 /*void Document::fill(NetworkMessageWriter* msg) 0208 { 0209 msg->string32(m_editor->toPlainText()); 0210 m_participantPane->fill(msg); 0211 } 0212 void Document::readFromMsg(NetworkMessageReader* msg) 0213 { 0214 if(nullptr != msg) 0215 { 0216 if(msg->action() == NetMsg::updateTextAndPermission) 0217 { 0218 QString text= msg->string32(); 0219 m_editor->setPlainText(text); 0220 m_participantPane->readFromMsg(msg); 0221 } 0222 else if(msg->action() == NetMsg::updatePermissionOneUser) 0223 { 0224 m_participantPane->readPermissionChanged(msg); 0225 } 0226 } 0227 }*/ 0228 0229 void Document::updateHighlighter() 0230 { 0231 using SNC= SharedNoteController::HighlightedSyntax; 0232 switch(m_shareCtrl->highligthedSyntax()) 0233 { 0234 case SNC::None: 0235 m_highlighter.reset(); 0236 break; 0237 case SNC::MarkDown: 0238 m_highlighter.reset(new MarkDownHighlighter(m_editor->document())); 0239 break; 0240 } 0241 } 0242 0243 bool Document::isUndoable() 0244 { 0245 return m_editor->document()->isUndoAvailable(); 0246 } 0247 0248 bool Document::isRedoable() 0249 { 0250 return m_editor->document()->isRedoAvailable(); 0251 } 0252 0253 bool Document::isModified() 0254 { 0255 return m_editor->document()->isModified(); 0256 } 0257 0258 bool Document::isChatHidden() 0259 { 0260 return ui->codeChatSplitter->widget(1)->isHidden(); 0261 } 0262 0263 bool Document::isParticipantsHidden() 0264 { 0265 return ui->participantSplitter->widget(2)->isHidden(); 0266 } 0267 0268 void Document::findAll() 0269 { 0270 findAllToolbar->show(); 0271 findAllToolbar->giveFocus(); 0272 } 0273 0274 void Document::findNext(QString searchString, Qt::CaseSensitivity sensitivity, bool wrapAround, Enu::FindMode mode) 0275 { 0276 if(!m_editor->findNext(searchString, sensitivity, wrapAround, mode)) 0277 { 0278 emit notFound(); 0279 } 0280 } 0281 0282 void Document::findPrev(QString searchString, Qt::CaseSensitivity sensitivity, bool wrapAround, Enu::FindMode mode) 0283 { 0284 if(!m_editor->findPrev(searchString, sensitivity, wrapAround, mode)) 0285 { 0286 emit notFound(); 0287 } 0288 } 0289 0290 void Document::replaceAll(QString searchString, QString replaceString, Qt::CaseSensitivity sensitivity, 0291 Enu::FindMode mode) 0292 { 0293 if(!m_editor->replaceAll(searchString, replaceString, sensitivity, mode)) 0294 { 0295 QMessageBox::information(m_editor, tr("Cahoots"), tr("The string was not found.")); 0296 } 0297 } 0298 0299 void Document::replace(QString replaceString) 0300 { 0301 if(!m_editor->replace(replaceString)) 0302 { 0303 emit notFound(); 0304 } 0305 } 0306 0307 void Document::findReplace(QString searchString, QString replaceString, Qt::CaseSensitivity sensitivity, 0308 bool wrapAround, Enu::FindMode mode) 0309 { 0310 if(!m_editor->findReplace(searchString, replaceString, sensitivity, wrapAround, mode)) 0311 { 0312 emit notFound(); 0313 } 0314 } 0315 QTextDocument* Document::getDocument() 0316 { 0317 if(nullptr != m_editor) 0318 return m_editor->document(); 0319 else 0320 return nullptr; 0321 } 0322 0323 QString Document::getPlainText() 0324 { 0325 return m_editor->toPlainText(); 0326 } 0327 0328 void Document::setPlainText(QString text) 0329 { 0330 m_editor->setPlainText(text); 0331 } 0332 0333 void Document::toggleLineWrap() 0334 { 0335 if(m_editor->lineWrapMode() == QPlainTextEdit::NoWrap) 0336 { 0337 m_editor->setLineWrapMode(QPlainTextEdit::WidgetWidth); 0338 } 0339 else 0340 { 0341 m_editor->setLineWrapMode(QPlainTextEdit::NoWrap); 0342 } 0343 } 0344 0345 void Document::setModified(bool b) 0346 { 0347 m_editor->document()->setModified(b); 0348 } 0349 0350 void Document::renderMarkdown() 0351 { 0352 // todo 0353 } 0354 0355 bool Document::docHasCollaborated() 0356 { 0357 return startedCollaborating; 0358 } 0359 0360 void Document::findNext(QString string) 0361 { 0362 m_editor->findNext(string, Qt::CaseInsensitive, true, Enu::Contains); 0363 } 0364 0365 void Document::findPrevious(QString string) 0366 { 0367 m_editor->findPrev(string, Qt::CaseInsensitive, true, Enu::Contains); 0368 } 0369 0370 ParticipantsPane* Document::getParticipantPane() const 0371 { 0372 return m_participantPane.get(); 0373 } 0374 0375 void Document::setParticipantPane(ParticipantsPane* participantPane) 0376 { 0377 m_participantPane.reset(participantPane); 0378 }