2
JuffEd - An advanced text editor
3
Copyright 2007-2009 Mikhail Murzin
5
This program is free software; you can redistribute it and/or
6
modify it under the terms of the GNU General Public License
7
version 2 as published by the Free Software Foundation.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
#include "AutocompleteSettings.h"
23
#include "CommandStorage.h"
24
#include "Functions.h"
26
#include "LexerStorage.h"
27
#include "MainSettings.h"
28
#include "JuffScintilla.h"
29
#include "PrintSettings.h"
30
#include "TextDocSettings.h"
33
#include <qscilexer.h>
34
//#include <qscimacro.h>
35
#include <qsciprinter.h>
36
#include <qsciscintilla.h>
38
#include <QtCore/QDir>
39
#include <QtCore/QFile>
40
#include <QtCore/QTextCodec>
41
#include <QtCore/QTextStream>
42
#include <QtGui/QMenu>
43
#include <QtGui/QMessageBox>
44
#include <QtGui/QPrintDialog>
45
#include <QtGui/QScrollBar>
46
#include <QtGui/QSplitter>
52
class SciDoc::Interior {
56
codec_ = QTextCodec::codecForLocale();
57
charsetName_ = codec_->name();
59
edit1_ = createEdit();
60
edit2_ = createEdit();
61
edit2_->setDocument(edit1_->document());
64
spl_ = new QSplitter(Qt::Vertical);
65
spl_->addWidget(edit1_);
66
spl_->addWidget(edit2_);
68
spl_->setSizes(QList<int>() << 0 << spl_->height());
70
searchStartingLine_ = -1;
71
searchStartingCol_ = -1;
72
searchSteppedOver_ = false;
73
searchStartingScroll_ = 0;
81
JuffScintilla* createEdit() {
82
JuffScintilla* edit = new JuffScintilla();
84
edit->setIndentationGuidesForegroundColor(TextDocSettings::defaultFontColor());
85
edit->setIndentationGuidesBackgroundColor(TextDocSettings::defaultBgColor());
86
edit->setFolding(QsciScintilla::BoxedTreeFoldStyle);
87
edit->setAutoIndent(true);
88
edit->setBraceMatching(QsciScintilla::SloppyBraceMatch);
89
edit->setMatchedBraceBackgroundColor(TextDocSettings::matchedBraceBgColor());
91
edit->setMarginLineNumbers(1, true);
92
edit->setMarginSensitivity(1, true);
93
edit->setMarginWidth(2, 12);
94
// set the 1st margin accept markers
95
// number 1 and 2 (binary mask 00000110 == 6)
96
edit->setMarginMarkerMask(1, 6);
97
edit->markerDefine(QsciScintilla::RightTriangle, 1);
98
edit->markerDefine(QsciScintilla::Background, 2);
99
edit->setMarkerForegroundColor(QColor(100, 100, 100));
100
edit->setMarkerBackgroundColor(TextDocSettings::markersColor());
101
// edit->setMarginsBackgroundColor(QColor(50, 50, 50));
102
// edit->setMarginsForegroundColor(QColor(150, 150, 150));
103
// edit->setFoldMarginColors(QColor(150, 150, 150), QColor(50, 50, 50));
109
JuffScintilla* edit1_;
110
JuffScintilla* edit2_;
111
JuffScintilla* curEdit_;
115
QString charsetName_;
116
int searchStartingLine_;
117
int searchStartingCol_;
118
bool searchSteppedOver_;
119
int searchStartingScroll_;
123
SciDoc::SciDoc(const QString& fileName) : Document(fileName) {
124
docInt_ = new Interior();
126
wrapText(TextDocSettings::widthAdjust());
127
showLineNumbers(TextDocSettings::showLineNumbers());
128
showInvisibleSymbols(TextDocSettings::showInvisibleSymbols());
130
if ( !fileName.isEmpty() && !isNoname(fileName) ) {
132
docInt_->edit1_->setModified(false);
134
// syntax highlighting
135
QString lexName = LexerStorage::instance()->lexerName(fileName);
139
QFile file(fileName);
140
if ( file.open(QIODevice::ReadOnly) ) {
141
QString line = QString::fromLocal8Bit(file.readLine().constData());
142
QRegExp re(".*(\r?\n?)");
143
if ( re.exactMatch(line) ) {
144
QString ending = re.cap(1);
145
if ( ending == "\r\n" ) {
146
docInt_->edit1_->setEolMode(QsciScintilla::EolWindows);
148
else if ( ending == "\r" ) {
149
docInt_->edit1_->setEolMode(QsciScintilla::EolMac);
152
docInt_->edit1_->setEolMode(QsciScintilla::EolUnix);
162
connect(docInt_->edit1_, SIGNAL(modificationChanged(bool)), this, SIGNAL(modified(bool)));
163
connect(docInt_->edit1_, SIGNAL(cursorPositionChanged(int, int)), this, SLOT(onCursorMove(int, int)));
164
connect(docInt_->edit2_, SIGNAL(cursorPositionChanged(int, int)), this, SLOT(onCursorMove(int, int)));
165
connect(docInt_->edit1_, SIGNAL(contextMenuCalled(int, int)), this, SIGNAL(contextMenuCalled(int, int)));
166
connect(docInt_->edit2_, SIGNAL(contextMenuCalled(int, int)), this, SIGNAL(contextMenuCalled(int, int)));
167
connect(docInt_->edit1_, SIGNAL(marginClicked(int, int, Qt::KeyboardModifiers)), SLOT(onMarginClicked(int, int, Qt::KeyboardModifiers)));
168
connect(docInt_->edit2_, SIGNAL(marginClicked(int, int, Qt::KeyboardModifiers)), SLOT(onMarginClicked(int, int, Qt::KeyboardModifiers)));
169
connect(docInt_->edit1_, SIGNAL(linesChanged()), SLOT(onLinesCountChanged()));
170
connect(docInt_->edit1_, SIGNAL(focusReceived()), SLOT(onEditReceivedFocus()));
171
connect(docInt_->edit2_, SIGNAL(focusReceived()), SLOT(onEditReceivedFocus()));
175
QAction* unindentAct = new QAction(this);
176
unindentAct->setShortcut(QKeySequence("Shift+Tab"));
177
connect(unindentAct, SIGNAL(activated()), this, SLOT(unindent()));
178
widget()->addAction(unindentAct);
181
void SciDoc::init() {
182
docInt_->spl_->setFocusProxy(docInt_->edit2_);
183
docInt_->edit2_->setFocus();
190
void SciDoc::setFileName(const QString& fileName) {
191
Document::setFileName(fileName);
192
QString lexName = LexerStorage::instance()->lexerName(fileName);
193
if ( lexName != docInt_->syntax_ ) {
198
void SciDoc::print() {
200
QPrintDialog dlg(&prn, widget());
201
if (dlg.exec() == QDialog::Accepted) {
202
prn.setWrapMode(TextDocSettings::widthAdjust() || PrintSettings::alwaysWrap() ? QsciScintilla::WrapWord : QsciScintilla::WrapNone);
204
int line1(-1), line2(-1), col1(-1), col2(-1);
205
JuffScintilla* edit = getActiveEdit();
207
QsciLexer* lexer = edit->lexer();
208
if ( !PrintSettings::keepBgColor() ) {
209
lexer->setDefaultPaper(Qt::white);
210
lexer->setPaper(Qt::white);
211
lexer->setDefaultColor(Qt::black);
213
if ( !PrintSettings::keepColors() ) {
214
lexer->setColor(Qt::black);
216
edit->getSelection(&line1, &col1, &line2, &col2);
217
if (line1 >=0 && line2 >= 0 && col1 >= 0 && col2 >= 0) {
218
// We have selection. Print it.
221
prn.printRange(edit, line1, line2);
224
// We don't have selection. Print the whole text.
225
prn.printRange(edit, 0);
227
QFont font = TextDocSettings::font();
228
LexerStorage::instance()->updateLexers(font);
233
QWidget* SciDoc::widget() {
234
return docInt_->spl_;
237
JuffScintilla* SciDoc::getActiveEdit() const {
238
return docInt_->curEdit_;
241
bool SciDoc::isModified() const {
242
return docInt_->edit1_->isModified();
245
void SciDoc::setModified(bool mod) {
246
return docInt_->edit1_->setModified(mod);
249
void SciDoc::undo() {
250
JuffScintilla* edit = getActiveEdit();
257
void SciDoc::redo() {
258
JuffScintilla* edit = getActiveEdit();
266
JuffScintilla* edit = getActiveEdit();
273
void SciDoc::copy() {
274
JuffScintilla* edit = getActiveEdit();
281
void SciDoc::paste() {
282
JuffScintilla* edit = getActiveEdit();
289
void SciDoc::unindent() {
292
int line1(-1), line2(-1), col1(-1), col2(-1);
293
JuffScintilla* edit = getActiveEdit();
297
if ( edit->hasSelectedText() ) {
298
edit->getSelection(&line1, &col1, &line2, &col2);
302
if (line1 <= line2 && line1 >= 0) {
303
for (int l = line1; l <= line2; ++l) {
309
edit->getCursorPosition(&line1, &col1);
311
edit->unindent(line1);
318
void prepareForFind(QsciScintilla* edit, const QString& s, const DocFindFlags& flags) {
320
if ( flags.backwards && edit->hasSelectedText() ) {
321
int fromRow, fromCol, toRow, toCol;
322
edit->getSelection(&fromRow, &fromCol, &toRow, &toCol);
323
if ( fromRow == toRow ) {
324
QString selection = edit->selectedText();
325
if ( flags.isRegExp ) {
327
r.setCaseSensitivity(flags.matchCase ? Qt::CaseSensitive : Qt::CaseInsensitive);
328
if ( r.exactMatch(selection) ) {
329
edit->setCursorPosition(fromRow, fromCol);
333
if ( !flags.matchCase ) {
335
selection = selection.toLower();
337
if ( selection.compare(str) == 0 ) {
338
edit->setCursorPosition(fromRow, fromCol);
345
void stepOver(JuffScintilla* edit, bool back) {
348
row = edit->lines() - 1;
349
col = edit->text(row).length();
356
edit->setCursorPosition(row, col);
359
void SciDoc::find(const QString& str, const DocFindFlags& flags) {
365
JuffScintilla* edit = getActiveEdit();
369
edit->getCursorPosition(&(docInt_->searchStartingLine_), &(docInt_->searchStartingCol_));
370
docInt_->searchSteppedOver_ = false;
371
docInt_->searchStartingScroll_ = edit->verticalScrollBar()->value();
373
startFind(edit, str, flags);
376
void SciDoc::startFind(JuffScintilla* edit, const QString& str, const DocFindFlags& flags) {
377
prepareForFind(edit, str, flags);
379
bool found = edit->find(str, flags);
382
if ( !docInt_->searchSteppedOver_ ) {
383
docInt_->searchSteppedOver_ = true;
384
stepOver(edit, flags.backwards);
385
startFind(edit, str, flags);
388
edit->setCursorPosition(docInt_->searchStartingLine_, docInt_->searchStartingCol_);
389
edit->verticalScrollBar()->setValue(docInt_->searchStartingScroll_);
390
QMessageBox::information(edit, tr("Information"), tr("Text '%1' was not found").arg(str));
396
void SciDoc::replace(const QString& str1, const QString& str2, const DocFindFlags& flags) {
399
if ( str1.isEmpty() )
402
JuffScintilla* edit = getActiveEdit();
406
prepareForFind(edit, str1, flags);
408
edit->getCursorPosition(&(docInt_->searchStartingLine_), &(docInt_->searchStartingCol_));
409
docInt_->searchSteppedOver_ = false;
410
docInt_->searchStartingScroll_ = edit->verticalScrollBar()->value();
412
bool replaceAll = false;
414
startReplace(edit, str1, str2, flags, replaceAll, count);
417
void SciDoc::startReplace(JuffScintilla* edit, const QString& str1, const QString& str2, const DocFindFlags& flags, bool& replaceAll, int& count) {
418
bool cancelled = false;
419
while ( edit->find(str1, flags) ) {
420
if ( !doReplace(edit, str1, str2, flags, replaceAll) ) {
429
// reached the end or the beginning
430
if ( !docInt_->searchSteppedOver_ ) {
431
docInt_->searchSteppedOver_ = true;
432
stepOver(edit, flags.backwards);
433
startReplace(edit, str1, str2, flags, replaceAll, count);
436
edit->setCursorPosition(docInt_->searchStartingLine_, docInt_->searchStartingCol_);
437
edit->verticalScrollBar()->setValue(docInt_->searchStartingScroll_);
438
QMessageBox::information(edit, tr("Information"), tr("Replacement finished (%1 replacements were made)").arg(count));
444
enum Answer { Yes, No, All, Cancel };
446
Answer confirm(QWidget* w) {
448
QMessageBox::StandardButton btn = QMessageBox::question(w, QObject::tr("Confirmation"),
449
QObject::tr("Replace this text?"),
450
QMessageBox::Yes | QMessageBox::No | QMessageBox::YesToAll | QMessageBox::Cancel,
454
case QMessageBox::Yes:
457
case QMessageBox::No:
460
case QMessageBox::Cancel:
463
case QMessageBox::YesToAll:
472
bool SciDoc::doReplace(JuffScintilla* edit, const QString& str1, const QString& str2, const DocFindFlags& flags, bool& replaceAll) {
473
QString selectedText = edit->selectedText();
474
QString targetText(str2);
475
if ( flags.isRegExp ) {
476
QRegExp regExp(str1);
477
regExp.setCaseSensitivity(flags.matchCase ? Qt::CaseSensitive : Qt::CaseInsensitive);
478
if ( regExp.exactMatch(selectedText) ) {
479
QStringList matches = regExp.capturedTexts();
480
int n = matches.size();
481
for ( int i = 0; i < n; ++i ) {
482
targetText.replace(QString("\\%1").arg(i), matches[i]);
490
// ask for confirmation if replace all hasn't been chosen yet
492
Answer conf = confirm(widget());
493
if ( conf == Cancel )
495
else if ( conf == Yes ) {
496
edit->replaceSelected(targetText, flags.backwards);
497
edit->selectAll(false);
499
else if ( conf == All ) {
500
edit->replaceSelected(targetText, flags.backwards);
501
edit->selectAll(false);
506
// just replace, because there has been chosen "select all"
507
edit->replaceSelected(targetText, flags.backwards);
508
edit->selectAll(false);
513
void SciDoc::showLineNumbers(bool show) {
516
docInt_->edit1_->showLineNumbers(show);
517
docInt_->edit2_->showLineNumbers(show);
520
void SciDoc::wrapText(bool wrap) {
524
docInt_->edit1_->setWrapMode(QsciScintilla::WrapWord);
525
docInt_->edit2_->setWrapMode(QsciScintilla::WrapWord);
528
docInt_->edit1_->setWrapMode(QsciScintilla::WrapNone);
529
docInt_->edit2_->setWrapMode(QsciScintilla::WrapNone);
531
TextDocSettings::setWidthAdjust(wrap);
534
void SciDoc::showInvisibleSymbols(bool show) {
535
docInt_->edit1_->setWhitespaceVisibility(show ? QsciScintilla::WsVisible : QsciScintilla::WsInvisible);
536
docInt_->edit1_->setWrapVisualFlags(show ? QsciScintilla::WrapFlagByBorder : QsciScintilla::WrapFlagNone);
537
docInt_->edit2_->setWhitespaceVisibility(show ? QsciScintilla::WsVisible : QsciScintilla::WsInvisible);
538
docInt_->edit2_->setWrapVisualFlags(show ? QsciScintilla::WrapFlagByBorder : QsciScintilla::WrapFlagNone);
539
TextDocSettings::setShowInvisibleSymbols(show);
545
void SciDoc::stripTrailingSpaces() {
546
JuffScintilla* edit = getActiveEdit();
551
getCursorPos(line, col);
552
QString text = edit->text();
553
QStringList lines = text.split(QRegExp("\r\n|\r|\n"));
554
QRegExp rx("[ \t]+$");
556
foreach (QString str, lines) {
557
int pos = str.indexOf(rx);
559
edit->setSelection(i, 0, i, str.length());
561
replaceSelectedText(str);
565
setCursorPos(line, col);
568
bool SciDoc::save(const QString& fileName, const QString& charset, QString& error) {
571
if ( MainSettings::stripTrailingSpaces() )
572
stripTrailingSpaces();
574
QFile file(fileName);
575
if ( file.open(QIODevice::WriteOnly) ) {
577
text = docInt_->edit1_->text();
578
QTextCodec* codec = QTextCodec::codecForName(charset.toAscii());
579
if ( !charset.isEmpty() && codec ) {
580
file.write(codec->fromUnicode(text));
583
file.write(docInt_->codec_->fromUnicode(text));
586
Document::save(fileName, charset, error);
590
error = tr("Can't open file for writing");
595
void SciDoc::reload() {
596
if ( !Juff::isNoname(fileName()) ) {
598
getCursorPos(line, col);
599
int scroll = curScrollPos();
602
if ( line >=0 && col >= 0 ) {
603
setCursorPos(line, col);
604
setScrollPos(scroll);
609
void SciDoc::readDoc(bool keepCharset /* = false*/) {
611
QFile file(fileName());
612
if ( file.open(QIODevice::ReadOnly) ) {
614
if ( !keepCharset ) {
615
QString codecName = guessCharset();
616
QTextCodec* codec = QTextCodec::codecForName(codecName.toAscii());
618
docInt_->codec_ = codec;
619
docInt_->charsetName_ = codecName;
623
QTextStream ts(&file);
624
ts.setCodec(docInt_->codec_);
625
docInt_->edit1_->setText(ts.readAll());
629
void SciDoc::applySettings() {
632
QFont font = TextDocSettings::font();
633
LexerStorage::instance()->updateLexers(font);
634
showLineNumbers(TextDocSettings::showLineNumbers());
636
QsciScintilla* edits[] = { docInt_->edit1_, docInt_->edit2_ };
637
for (int i = 0; i < 2; ++i ) {
638
QsciScintilla* edit = edits[i];
641
edit->setTabWidth(TextDocSettings::tabStopWidth());
642
edit->setIndentationsUseTabs(!TextDocSettings::replaceTabsWithSpaces());
644
int lInd = TextDocSettings::lineLengthIndicator();
646
edit->setEdgeMode(QsciScintilla::EdgeLine);
647
edit->setEdgeColumn(lInd);
650
edit->setEdgeMode(QsciScintilla::EdgeNone);
653
edit->setCaretLineVisible(TextDocSettings::highlightCurrentLine());
654
edit->setCaretLineBackgroundColor(LexerStorage::instance()->curLineColor(docInt_->syntax_));
655
edit->setIndentationGuides(TextDocSettings::showIndents());
656
edit->setBackspaceUnindents(TextDocSettings::backspaceUnindents());
657
edit->setMarkerBackgroundColor(TextDocSettings::markersColor());
658
if ( QsciLexer* lexer = edit->lexer() ) {
659
edit->setCaretForegroundColor(lexer->defaultColor());
660
edit->setIndentationGuidesForegroundColor(TextDocSettings::indentsColor());
661
edit->setIndentationGuidesBackgroundColor(lexer->defaultPaper());
663
edit->setMatchedBraceBackgroundColor(TextDocSettings::matchedBraceBgColor());
666
QColor selBgColor = TextDocSettings::selectionBgColor();
667
edit->setSelectionBackgroundColor(selBgColor);
668
if ( selBgColor.red() + selBgColor.green() + selBgColor.blue() < 3 * 255 / 2)
669
edit->setSelectionForegroundColor(QColor(255, 255, 255));
671
edit->setSelectionForegroundColor(QColor(0, 0, 0));
674
edit->setAutoCompletionThreshold(AutocompleteSettings::threshold());
675
edit->setAutoCompletionReplaceWord(AutocompleteSettings::replaceWord());
676
edit->setAutoCompletionCaseSensitivity(AutocompleteSettings::caseSensitive());
677
if ( AutocompleteSettings::useDocument() ) {
678
if ( AutocompleteSettings::useApis() )
679
edit->setAutoCompletionSource(QsciScintilla::AcsAll);
681
edit->setAutoCompletionSource(QsciScintilla::AcsDocument);
684
if ( AutocompleteSettings::useApis() )
685
edit->setAutoCompletionSource(QsciScintilla::AcsAPIs);
687
edit->setAutoCompletionSource(QsciScintilla::AcsNone);
692
void SciDoc::updateActivated() {
693
wrapText(TextDocSettings::widthAdjust());
694
showLineNumbers(TextDocSettings::showLineNumbers());
697
void SciDoc::addContextMenuActions(const ActionList& list) {
698
docInt_->edit1_->addContextMenuActions(list);
699
docInt_->edit2_->addContextMenuActions(list);
703
int SciDoc::lineCount() const {
704
return docInt_->edit1_->lines();
707
QString SciDoc::getLine(int line) const {
708
return docInt_->edit1_->text(line);
711
void SciDoc::zoomIn() {
712
docInt_->edit1_->zoomIn();
713
docInt_->edit2_->zoomIn();
716
void SciDoc::zoomOut() {
717
docInt_->edit1_->zoomOut();
718
docInt_->edit2_->zoomOut();
721
void SciDoc::zoom100() {
722
docInt_->edit1_->zoomTo(0);
723
docInt_->edit2_->zoomTo(0);
726
void SciDoc::onCursorMove(int line, int col) {
727
JuffScintilla* edit = getActiveEdit();
728
if ( edit == sender() )
729
emit cursorPositionChanged(line, col);
733
void SciDoc::gotoLine(int line) {
736
JuffScintilla* edit = getActiveEdit();
740
edit->setCursorPosition(line, 0);
743
int SciDoc::curLine() const {
744
int line = -1, col = -1;
745
JuffScintilla* edit = getActiveEdit();
749
edit->getCursorPosition(&line, &col);
753
QString SciDoc::text() const {
754
return docInt_->edit1_->text();
757
QString SciDoc::text(int line) const {
758
return docInt_->edit1_->text(line);
761
QString SciDoc::wordUnderCursor() const {
762
JuffScintilla* edit = getActiveEdit();
766
return edit->wordUnderCursor();
769
QString SciDoc::selectedText() const {
770
JuffScintilla* edit = getActiveEdit();
774
return edit->selectedText();
777
void SciDoc::getCursorPos(int& line, int& col) const {
778
JuffScintilla* edit = getActiveEdit();
782
edit->getCursorPosition(&line, &col);
785
void SciDoc::setCursorPos(int line, int col) {
786
JuffScintilla* edit = getActiveEdit();
790
edit->setCursorPosition(line, col);
794
void SciDoc::getSelection(int& line1, int& col1, int& line2, int& col2) const {
795
JuffScintilla* edit = getActiveEdit();
799
edit->getSelection(&line1, &col1, &line2, &col2);
802
void SciDoc::setSelection(int line1, int col1, int line2, int col2) {
803
JuffScintilla* edit = getActiveEdit();
807
edit->setSelection(line1, col1, line2, col2);
810
void SciDoc::insertText(const QString& text) {
811
JuffScintilla* edit = getActiveEdit();
816
getCursorPos(row, col);
817
int newLines = text.count(QRegExp("\r\n|\n|\r"));
820
setCursorPos(row, col + text.length());
823
void SciDoc::removeSelectedText() {
824
JuffScintilla* edit = getActiveEdit();
828
edit->removeSelectedText();
831
void SciDoc::replaceSelectedText(const QString& text) {
832
JuffScintilla* edit = getActiveEdit();
836
edit->beginUndoAction();
837
removeSelectedText();
839
edit->endUndoAction();
842
int SciDoc::curScrollPos() const {
843
JuffScintilla* edit = getActiveEdit();
847
QScrollBar* scr = edit->verticalScrollBar();
856
void SciDoc::setScrollPos(int pos) {
857
JuffScintilla* edit = getActiveEdit();
861
QScrollBar* scr = edit->verticalScrollBar();
868
void SciDoc::onMarginClicked (int margin, int line, Qt::KeyboardModifiers state) {
872
// margin that contains line numbers
877
IntList SciDoc::markers() const {
880
while ( (line = docInt_->edit1_->markerFindNext(line, 2)) >= 0 ) {
886
void SciDoc::toggleMarker(int line) {
887
JuffScintilla* edit = getActiveEdit();
891
if ( edit->markersAtLine(line) & 2 ) {
892
edit->markerDelete(line, 1);
893
edit->markerDelete(line, 2);
896
edit->markerAdd(line, 1);
897
edit->markerAdd(line, 2);
900
// Markers will be added to/deleted from the 2nd edit
901
// automatically since they share the same document
904
void SciDoc::toggleMarker() {
905
JuffScintilla* edit = getActiveEdit();
910
edit->getCursorPosition(&line, &col);
914
void SciDoc::nextMarker() {
915
JuffScintilla* edit = getActiveEdit();
919
int row(-1), col(-1);
920
edit->getCursorPosition(&row, &col);
922
int mLine = edit->markerFindNext(row + 1, 2);
927
mLine = edit->markerFindNext(0, 2);
934
void SciDoc::prevMarker() {
935
JuffScintilla* edit = getActiveEdit();
939
int row(-1), col(-1);
940
edit->getCursorPosition(&row, &col);
942
int mLine = edit->markerFindPrevious(row - 1 , 2);
947
mLine = edit->markerFindPrevious(lineCount() - 1, 2);
954
void SciDoc::removeAllMarkers() {
955
docInt_->edit1_->markerDeleteAll();
957
// Markers will be deleted from the 2nd edit
958
// automatically since they share the same document
961
QString SciDoc::charset() const {
962
return docInt_->charsetName_;
965
void SciDoc::setCharset(const QString& charset, bool confirm /*= false*/) {
968
QTextCodec* codec = QTextCodec::codecForName(charset.toAscii());
970
int ret = QMessageBox::Yes;
971
if ( confirm && isModified() && !isNoname(fileName()) ) {
972
QString str = tr("All unsaved changes will be lost.\nDo you want to proceed?");
973
ret = QMessageBox::question(widget(), tr("Warning"),
974
str, QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
976
if ( ret == QMessageBox::Yes ) {
977
docInt_->codec_ = codec;
978
docInt_->charsetName_ = charset;
979
if ( !isNoname(fileName()) ) {
987
QString SciDoc::syntax() const {
988
return docInt_->syntax_;
991
void SciDoc::setSyntax(const QString& lexName) {
992
if ( lexName.isEmpty() )
995
docInt_->syntax_ = lexName;
997
QsciLexer* lexer = LexerStorage::instance()->lexer(lexName);
999
loadAutocompletionAPI(lexName, lexer);
1001
docInt_->edit1_->setLexer(lexer);
1002
docInt_->edit2_->setLexer(lexer);
1005
void SciDoc::loadAutocompletionAPI(const QString& lexName, QsciLexer* lexer) {
1006
if ( NULL == lexer )
1009
QDir dir(AppInfo::configDirPath() + "/apis");
1010
QString fileName = lexName.toLower() + ".api";
1011
fileName.replace(QString("+"), "plus").replace(QString("#"), "sharp");
1012
if ( dir.entryList(QDir::Files).contains(fileName) ) {
1013
QsciAPIs* apis = new QsciAPIs(lexer);
1014
if ( apis->load(dir.absoluteFilePath(fileName)) ) {
1016
lexer->setAPIs(apis);
1024
EolMode SciDoc::eolMode() const {
1025
if ( docInt_->edit1_->eolMode() == QsciScintilla::EolWindows ) {
1028
else if ( docInt_->edit1_->eolMode() == QsciScintilla::EolMac ) {
1036
void SciDoc::setEolMode(EolMode eol) {
1039
docInt_->edit1_->convertEols(QsciScintilla::EolWindows);
1040
docInt_->edit1_->setEolMode(QsciScintilla::EolWindows);
1044
docInt_->edit1_->convertEols(QsciScintilla::EolMac);
1045
docInt_->edit1_->setEolMode(QsciScintilla::EolMac);
1049
docInt_->edit1_->convertEols(QsciScintilla::EolUnix);
1050
docInt_->edit1_->setEolMode(QsciScintilla::EolUnix);
1055
/*QsciMacro* SciDoc::newMacro() {
1056
JuffScintilla* edit = getActiveEdit();
1060
return new QsciMacro(edit);
1063
void SciDoc::runMacro(const QString& mcr) {
1064
JuffScintilla* edit = getActiveEdit();
1068
QsciMacro macro(edit);
1069
if ( macro.load(mcr) ) {
1074
void SciDoc::goToMatchingBrace() {
1075
JuffScintilla* edit = getActiveEdit();
1079
edit->moveToMatchingBrace();
1082
void SciDoc::selectToMatchingBrace() {
1083
JuffScintilla* edit = getActiveEdit();
1087
edit->selectToMatchingBrace();
1090
void SciDoc::commentLine(JuffScintilla* edit, int line, const QString& str1, const QString& comment) {
1091
QString str2 = comment + str1;
1092
edit->setSelection(line, 0, line + 1, 0);
1093
replaceSelectedText(str2);
1096
void SciDoc::uncommentLine(JuffScintilla* edit, int line, const QString& str1, const QString& comment) {
1097
int pos = str1.indexOf(comment);
1098
QString str2 = str1;
1099
str2.replace(pos, comment.length(), "");
1100
edit->setSelection(line, 0, line + 1, 0);
1101
replaceSelectedText(str2);
1104
void SciDoc::toggleLineComment() {
1107
JuffScintilla* edit = getActiveEdit();
1112
QString& s = docInt_->syntax_;
1113
if ( s == "C++" || s == "PHP" || s == "C#" || s == "Java" || s == "JavaScript" )
1115
else if ( s == "Bash" || s == "Python" || s == "CMake" || s == "Makefile" )
1117
else if ( s == "Fortran" )
1119
// TODO : need to add more syntaxes
1121
if ( comment.isEmpty() )
1124
if ( edit->hasSelectedText() ) {
1125
int line1, col1, line2, col2, curLine, curCol;
1126
edit->getSelection(&line1, &col1, &line2, &col2);
1127
edit->getCursorPosition(&curLine, &curCol);
1129
QString str1 = text(line1);
1130
QString ln = str1.simplified();
1131
bool toComment = true;
1132
if ( ln.startsWith(comment) ) {
1139
edit->beginUndoAction();
1140
for ( int line = line1; line <= line2; ++line ) {
1143
if ( !str1.simplified().startsWith(comment) )
1144
commentLine(edit, line, str1, comment);
1147
if ( str1.simplified().startsWith(comment) )
1148
uncommentLine(edit, line, str1, comment);
1151
edit->endUndoAction();
1153
edit->setCursorPosition(curLine, curCol + comment.length() * (toComment ? 1 : -1) );
1155
edit->setCursorPosition(curLine, curCol);
1159
edit->getCursorPosition(&line1, &col1);
1160
QString str1 = text(line1);
1162
QString ln = str1.simplified();
1163
if ( ln.startsWith(comment) ) {
1164
uncommentLine(edit, line1, str1, comment);
1165
edit->setCursorPosition(line1, col1 - comment.length());
1168
commentLine(edit, line1, str1, comment);
1169
edit->setCursorPosition(line1, col1 + comment.length());
1174
void SciDoc::toggleBlockComment() {
1177
JuffScintilla* edit = getActiveEdit();
1181
QString commBeg, commEnd;
1182
QString& s = docInt_->syntax_;
1183
if ( s == "C++" || s == "Java" || s == "C#" || s == "PHP" || s == "CSS" || s == "JavaScript" ) {
1187
else if ( docInt_->syntax_ == "HTML" || docInt_->syntax_ == "XML" ) {
1191
else if ( docInt_->syntax_ == "Python" ) {
1195
// TODO : need to add more syntaxes
1197
if ( commBeg.isEmpty() || commEnd.isEmpty() )
1200
if ( edit->hasSelectedText() ) {
1201
int line1, col1, line2, col2, curLine, curCol;
1202
edit->getSelection(&line1, &col1, &line2, &col2);
1203
edit->getCursorPosition(&curLine, &curCol);
1205
QString str1 = edit->selectedText();
1206
bool toComment = true;
1207
if ( str1.startsWith(commBeg) && str1.endsWith(commEnd) )
1212
str2 = commBeg + str1 + commEnd;
1215
str2.chop(commEnd.length());
1216
str2.remove(0, commBeg.length());
1218
replaceSelectedText(str2);
1219
if ( line1 == line2 ) {
1220
if ( curCol == col1 )
1221
edit->setCursorPosition(curLine, curCol);
1223
edit->setCursorPosition(curLine, curCol + (commBeg.length() + commEnd.length()) * (toComment ? 1 : -1));
1226
if ( curLine == line2 && curCol == col2)
1227
edit->setCursorPosition(curLine, curCol + commEnd.length() * (toComment ? 1 : -1) );
1229
edit->setCursorPosition(curLine, curCol);
1234
void SciDoc::duplicateLine() {
1237
JuffScintilla* edit = getActiveEdit();
1241
if ( edit->hasSelectedText() )
1242
edit->SendScintilla(QsciScintilla::SCI_SELECTIONDUPLICATE);
1244
edit->SendScintilla(QsciScintilla::SCI_LINEDUPLICATE);
1247
void SciDoc::moveLineUp() {
1250
JuffScintilla* edit = getActiveEdit();
1254
edit->SendScintilla(QsciScintilla::SCI_LINETRANSPOSE);
1255
edit->SendScintilla(QsciScintilla::SCI_LINEUP);
1258
void SciDoc::deleteCurrentLine() {
1261
JuffScintilla* edit = getActiveEdit();
1265
edit->SendScintilla(QsciScintilla::SCI_LINEDELETE);
1268
void SciDoc::toUpperCase()
1272
JuffScintilla* edit = getActiveEdit();
1276
edit->SendScintilla(QsciScintilla::SCI_UPPERCASE);
1279
void SciDoc::toLowerCase()
1283
JuffScintilla* edit = getActiveEdit();
1287
edit->SendScintilla(QsciScintilla::SCI_LOWERCASE);
1290
void SciDoc::changeSplitOrientation() {
1293
if ( docInt_->spl_->orientation() == Qt::Vertical ) {
1294
docInt_->spl_->setOrientation(Qt::Horizontal);
1297
docInt_->spl_->setOrientation(Qt::Vertical);
1301
void SciDoc::onLinesCountChanged() {
1302
emit linesCountChanged(lineCount());
1305
void SciDoc::onEditReceivedFocus() {
1306
JuffScintilla* edit = qobject_cast<JuffScintilla*>(sender());
1310
docInt_->curEdit_ = edit;