| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520 |
- #include "qscidisplaywindow.h"
- #include "MediatorDisplay.h"
- #include "textfind.h"
- #include "common.h"
- #include "styleset.h"
- #include "rcglobal.h"
- #include <QScrollBar>
- #include <QFileInfo>
- #include <QProcess>
- #include <QMessageBox>
- #include <stdexcept>
- #include <SciLexer.h>
- QsciDisplayWindow::QsciDisplayWindow(QWidget *parent):QsciScintilla(parent), m_textFindWin(nullptr), m_preFirstLineNum(0), m_isShowFindItem(true), m_hasHighlight(false)
- {
- //20210815 左右行同步还有问题,暂时不屏蔽,不实现
- connect(this->verticalScrollBar(), &QScrollBar::valueChanged, this, &QsciDisplayWindow::slot_scrollYValueChange);
- connect(this->horizontalScrollBar(), &QScrollBar::valueChanged, this, &QsciDisplayWindow::slot_scrollXValueChange);
- setAcceptDrops(false);
- m_findStartPos = 0;
- m_findEndPos = 0;
- m_findCurPos = 0;
- m_pScintillaFunc = (SCINTILLA_FUNC)this->SendScintillaPtrResult(SCI_GETDIRECTFUNCTION);
- m_pScintillaPtr = (SCINTILLA_PTR)this->SendScintillaPtrResult(SCI_GETDIRECTPOINTER);
- if (!m_pScintillaFunc)
- {
- throw std::runtime_error("ScintillaEditView::init : SCI_GETDIRECTFUNCTION message failed");
- }
- if (!m_pScintillaPtr)
- {
- throw std::runtime_error("ScintillaEditView::init : SCI_GETDIRECTPOINTER message failed");
- }
- //这个无比要设置false,否则双击后高亮单词,拷贝时会拷贝多个选择。
- execute(SCI_SETMULTIPLESELECTION, true);
- execute(SCI_SETMULTIPASTE, 1);
- execute(SCI_SETADDITIONALCARETSVISIBLE, false);
- execute(SCI_SETSELFORE, true, 0x0);
- execute(SCI_SETSELBACK, true, 0x00ffff);
- //QColor foldfgColor(StyleSet::foldfgColor);
- //QColor foldbgColor(StyleSet::foldbgColor);//默认0xff,0xff,0xff
- ////通过fold发现,尽量使用qscint的功能,因为他做了大量封装和简化
- //setFolding(BoxedTreeFoldStyle, 2);
- //setFoldMarginColors(foldfgColor, foldbgColor);
- //setMarginsBackgroundColor(StyleSet::marginsBackgroundColor); //0xea, 0xf7, 0xff //默认0xf0f0f0
- //双击后同样的字段进行高亮
- execute(SCI_INDICSETSTYLE, SCE_UNIVERSAL_FOUND_STYLE_SMART, INDIC_ROUNDBOX);
- execute(SCI_INDICSETALPHA, SCE_UNIVERSAL_FOUND_STYLE_SMART, 100);
- execute(SCI_INDICSETUNDER, SCE_UNIVERSAL_FOUND_STYLE_SMART, false);
- execute(SCI_INDICSETFORE, SCE_UNIVERSAL_FOUND_STYLE_SMART, 0x00ff00);
- setStyleOptions();
- //开启后可以保证长行在滚动条下完整显示
- execute(SCI_SETSCROLLWIDTHTRACKING, true);
- connect(this, &QsciScintilla::selectionChanged, this, &QsciDisplayWindow::slot_clearHightWord, Qt::QueuedConnection);
- connect(this, &QsciDisplayWindow::delayWork, this, &QsciDisplayWindow::slot_delayWork, Qt::QueuedConnection);
- }
- QsciDisplayWindow::~QsciDisplayWindow()
- {
- if (m_textFindWin != nullptr)
- {
- delete m_textFindWin;
- m_textFindWin = nullptr;
- }
- }
- void QsciDisplayWindow::setFoldColor(int margin, QColor fgClack, QColor bkColor)
- {
- SendScintilla(SCI_MARKERSETFORE, margin, fgClack);
- SendScintilla(SCI_MARKERSETBACK, margin, bkColor);
- }
- void QsciDisplayWindow::setStyleOptions()
- {
- if (StyleSet::m_curStyleId != BLACK_SE)
- {
- setMarginsForegroundColor(QColor(0x80, 0x80, 0x80)); //默认0x80, 0x80, 0x80
- }
- else
- setMarginsBackgroundColor(0xf0f0f0);
- setFoldMarginColors(0xf0f0f0, 0xf0f0f0);
- {
- //setCaretLineBackgroundColor(QColor(0xe8e8ff));
- setCaretLineBackgroundColor(QColor(0xFAF9DE));
- setMatchedBraceForegroundColor(QColor(191, 141, 255));
- setMatchedBraceBackgroundColor(QColor(222, 222, 222));
- setCaretForegroundColor(QColor(0, 0, 0));
- setFoldColor(SC_MARKNUM_FOLDEROPEN, QColor(Qt::white), QColor(128, 128, 128));
- setFoldColor(SC_MARKNUM_FOLDER, QColor(Qt::white), QColor(128, 128, 128));
- setFoldColor(SC_MARKNUM_FOLDERSUB, QColor(Qt::white), QColor(128, 128, 128));
- setFoldColor(SC_MARKNUM_FOLDERTAIL, QColor(Qt::white), QColor(128, 128, 128));
- setFoldColor(SC_MARKNUM_FOLDEREND, QColor(Qt::white), QColor(128, 128, 128));
- setFoldColor(SC_MARKNUM_FOLDEROPENMID, QColor(Qt::white), QColor(128, 128, 128));
- setFoldColor(SC_MARKNUM_FOLDERMIDTAIL, QColor(Qt::white), QColor(128, 128, 128));
- }
- }
- void QsciDisplayWindow::setIsShowFindItem(bool v)
- {
- m_isShowFindItem = v;
- }
- sptr_t QsciDisplayWindow::execute(quint32 Msg, uptr_t wParam, sptr_t lParam) const {
- try {
- return (m_pScintillaFunc) ? m_pScintillaFunc(m_pScintillaPtr, Msg, wParam, lParam) : -1;
- }
- catch (...)
- {
- return -1;
- }
- };
- void QsciDisplayWindow::mouseDoubleClickEvent(QMouseEvent * e)
- {
- QsciScintilla::mouseDoubleClickEvent(e);
- if (hasSelectedText())
- {
- emit delayWork();
- }
- }
- void QsciDisplayWindow::clearIndicator(int indicatorNumber) {
- size_t docStart = 0;
- size_t docEnd = length();
- execute(SCI_SETINDICATORCURRENT, indicatorNumber);
- execute(SCI_INDICATORCLEARRANGE, docStart, docEnd - docStart);
- };
- const int MAXLINEHIGHLIGHT = 400;
- void QsciDisplayWindow::slot_clearHightWord()
- {
- if (m_hasHighlight)
- {
- m_hasHighlight = false;
- clearIndicator(SCE_UNIVERSAL_FOUND_STYLE_SMART);
- }
- }
- void QsciDisplayWindow::highlightViewWithWord(QString & word2Hilite)
- {
- int originalStartPos = execute(SCI_GETTARGETSTART);
- int originalEndPos = execute(SCI_GETTARGETEND);
- int firstLine = static_cast<int>(this->execute(SCI_GETFIRSTVISIBLELINE));
- int nbLineOnScreen = this->execute(SCI_LINESONSCREEN);
- int nbLines = std::min(nbLineOnScreen, MAXLINEHIGHLIGHT) + 1;
- int lastLine = firstLine + nbLines;
- int startPos = 0;
- int endPos = 0;
- auto currentLine = firstLine;
- int prevDocLineChecked = -1; //invalid start
- auto searchMark = [this](int &startPos, int &endPos, QByteArray &word2Mark) {
- int targetStart = 0;
- int targetEnd = 0;
- long lens = word2Mark.length();
- while (targetStart >= 0)
- {
- execute(SCI_SETTARGETRANGE, startPos, endPos);
- targetStart = SendScintilla(SCI_SEARCHINTARGET, lens, word2Mark.data());
- if (targetStart == -1 || targetStart == -2)
- break;
- targetEnd = int(this->execute(SCI_GETTARGETEND));
- if (targetEnd > endPos)
- {
- //we found a result but outside our range, therefore do not process it
- break;
- }
- int foundTextLen = targetEnd - targetStart;
- if (foundTextLen > 0)
- {
- this->execute(SCI_SETINDICATORCURRENT, SCE_UNIVERSAL_FOUND_STYLE_SMART);
- this->execute(SCI_INDICATORFILLRANGE, targetStart, foundTextLen);
- }
- if (targetStart + foundTextLen == endPos)
- break;
- startPos = targetStart + foundTextLen;
- }
- };
- QByteArray whatMark = word2Hilite.toUtf8();
- SendScintilla(SCI_SETSEARCHFLAGS, SCFIND_REGEXP | SCFIND_MATCHCASE | SCFIND_WHOLEWORD | SCFIND_REGEXP_SKIPCRLFASONE);
- for (; currentLine < lastLine; ++currentLine)
- {
- int docLine = static_cast<int>(this->execute(SCI_DOCLINEFROMVISIBLE, currentLine));
- if (docLine == prevDocLineChecked)
- continue; //still on same line (wordwrap)
- prevDocLineChecked = docLine;
- startPos = static_cast<int>(this->execute(SCI_POSITIONFROMLINE, docLine));
- endPos = static_cast<int>(this->execute(SCI_POSITIONFROMLINE, docLine + 1));
- if (endPos == -1)
- { //past EOF
- endPos = this->length() - 1;
- searchMark(startPos, endPos, whatMark);
- break;
- }
- else
- {
- searchMark(startPos, endPos, whatMark);
- }
- }
- m_hasHighlight = true;
- // restore the original targets to avoid conflicts with the search/replace functions
- this->execute(SCI_SETTARGETRANGE, originalStartPos, originalEndPos);
- }
- void QsciDisplayWindow::slot_delayWork()
- {
- if (!hasSelectedText())
- {
- return;
- }
- QString word = selectedText();
- if (!word.isEmpty())
- {
- highlightViewWithWord(word);
- }
- #if 0
- if (!hasSelectedText())
- {
- return;
- }
- QString word = selectedText();
- if (!word.isEmpty())
- {
- QVector<int>resultPos;
- resultPos.reserve(50);
- int firstLine = execute(SCI_GETFIRSTVISIBLELINE);
- int nbLineOnScreen = execute(SCI_LINESONSCREEN);
- int nbLines = std::min(nbLineOnScreen, MAXLINEHIGHLIGHT) + 1;
- int lastLine = firstLine + nbLines;
- long startPos = execute(SCI_POSITIONFROMLINE, firstLine);
- long endPos = execute(SCI_POSITIONFROMLINE, lastLine);
- if (endPos == -1)
- {
- endPos = execute(SCI_GETLENGTH);
- }
- int curpos = execute(SCI_GETCURRENTPOS);
- int mainSelect = 1;
- struct Sci_TextToFind findOptions;
- findOptions.chrg.cpMin = startPos;
- findOptions.chrg.cpMax = endPos;
- std::string wordStr = word.toStdString();
- findOptions.lpstrText = wordStr.c_str();
- int pos = execute(SCI_FINDTEXT, SCFIND_MATCHCASE | SCFIND_WHOLEWORD, reinterpret_cast<sptr_t>(&findOptions));
- while (pos != -1)
- {
- resultPos.append(pos);
- if (pos <= curpos)
- {
- mainSelect = resultPos.size();
- }
- findOptions.chrg.cpMin = findOptions.chrgText.cpMax;
- pos = execute(SCI_FINDTEXT, SCFIND_MATCHCASE | SCFIND_WHOLEWORD, reinterpret_cast<sptr_t>(&findOptions));
- }
- for (int i = 0, size = resultPos.size(); i < size; ++i)
- {
- execute(SCI_ADDSELECTION, resultPos.at(i), resultPos.at(i) + word.size());
- }
- if (!resultPos.isEmpty())
- {
- execute(SCI_SETMAINSELECTION, mainSelect - 1);
- }
- }
- #endif
- }
- void QsciDisplayWindow::setMediator(MediatorDisplay* mediator)
- {
- m_mediator = mediator;
- }
- //滚动条值变化后的槽函数。一旦滚动则会出发这里,发送消息给中介,让中介去同步另外一方
- void QsciDisplayWindow::slot_scrollYValueChange(int value)
- {
- if (m_direction == RC_LEFT)
- {
- if (m_mediator->getLeftScrollValue() != value)
- {
- m_mediator->setLeftScrollValue(value);
- }
- }
- else
- {
- if (m_mediator->getRightScrollValue() != value)
- {
- m_mediator->setRightScrollValue(value);
- }
- }
- autoAdjustLineWidth(value);
- slot_delayWork();
- //qDebug("-- dir s n %d %d", m_direction, contentY());
- }
- //根据现有滚动条来决定是否更新屏幕线宽长度。每滚动2000个单位必须调整line宽
- void QsciDisplayWindow::autoAdjustLineWidth(int xScrollValue)
- {
- if (std::abs(xScrollValue - m_preFirstLineNum) > 400)
- {
- m_preFirstLineNum = xScrollValue;
- updateLineNumberWidth();
- }
- }
- void QsciDisplayWindow::updateLineNumberWidth()
- {
- auto linesVisible = execute(SCI_LINESONSCREEN);
- if (linesVisible)
- {
- int nbDigits = 0;
- auto firstVisibleLineVis = execute(SCI_GETFIRSTVISIBLELINE);
- auto lastVisibleLineVis = linesVisible + firstVisibleLineVis + 1;
- auto lastVisibleLineDoc = execute(SCI_DOCLINEFROMVISIBLE, lastVisibleLineVis);
- nbDigits = nbDigitsFromNbLines(lastVisibleLineDoc);
- nbDigits = nbDigits < 4 ? 4 : nbDigits;
-
- auto pixelWidth = 8 + nbDigits * execute(SCI_TEXTWIDTH, STYLE_LINENUMBER, reinterpret_cast<sptr_t>("8"));
- execute(SCI_SETMARGINWIDTHN, MARGIN_LINE_NUM, pixelWidth);
- }
- }
- //X方向滚动条值变化后的槽函数。一旦滚动则会出发这里,发送消息给中介,让中介去同步另外一方
- void QsciDisplayWindow::slot_scrollXValueChange(int value)
- {
- if (m_direction == RC_LEFT)
- {
- if (m_mediator->getLeftScrollXValue() != value)
- {
- m_mediator->setLeftScrollXValue(value);
- }
- }
- else
- {
- if (m_mediator->getRightScrollXValue() != value)
- {
- m_mediator->setRightScrollXValue(value);
- }
- }
- //qDebug("-- dir s n %d %d", m_direction, contentY());
- }
- void QsciDisplayWindow::setDirection(RC_DIRECTION direction)
- {
- m_direction = direction;
- }
- int QsciDisplayWindow::getCurVerticalScrollValue()
- {
- return this->verticalScrollBar()->value();
- }
- void QsciDisplayWindow::contextUserDefineMenuEvent(QMenu* menu)
- {
- //QAction* action;
- if (menu != nullptr)
- {
- menu->addAction(tr("Find Text"), this, SLOT(slot_findText()));
- menu->addAction(tr("Show File in Explorer"), this, SLOT(slot_showFileInExplorer()));
- menu->addAction(tr("Save As ..."), this, &QsciDisplayWindow::sign_saveAsFile);
- }
- menu->show();
- }
- void QsciDisplayWindow::inputMethodEvent(QInputMethodEvent* event)
- {
- if (!event->preeditString().isEmpty())
- {
- return;
- }
- QsciScintilla::inputMethodEvent(event);
- }
- void QsciDisplayWindow::slot_findText()
- {
- if (m_isShowFindItem)
- {
- if (m_textFindWin == nullptr)
- {
- m_textFindWin = new TextFind(m_direction);
- connect(m_textFindWin, &TextFind::signFindFile, this, &QsciDisplayWindow::slot_FindTextWithPara);
- m_textFindWin->activateWindow();
- m_textFindWin->show();
- }
- else
- {
- m_textFindWin->activateWindow();
- m_textFindWin->showNormal();
- }
- m_findCurPos = 0;
- }
- else
- {
- //不使用这里的查找,直接发信号到外面
- emit sign_find();
- }
- }
- void QsciDisplayWindow::slot_FindTextWithPara(int prevOrNext, QString text)
- {
- std::string str = text.toStdString();
- int length = SendScintilla(SCI_GETLENGTH);
- if (length > 0)
- {
- if (prevOrNext == 1)
- {
- SendScintilla(SCI_SETTARGETSTART, m_findCurPos);
- SendScintilla(SCI_SETTARGETEND, length);
- int ret = SendScintilla(SCI_SEARCHINTARGET, str.length(), str.c_str());
- if (ret >= 0)
- {
- m_findCurPos = ret + str.length();
- SendScintilla(SCI_GOTOPOS, ret);
- SendScintilla(SCI_SETSELECTION, ret, ret + str.length());
- }
- else
- {
- QMessageBox::information(this, tr("Not Find"), tr("Not Find Next!"));
- m_textFindWin->activateWindow();
- }
- }
- else if (prevOrNext == 0)
- {
- SendScintilla(SCI_SETTARGETSTART, m_findCurPos);
- SendScintilla(SCI_SETTARGETEND, 0);
- int ret = SendScintilla(SCI_SEARCHINTARGET, str.length(), str.c_str());
- if (ret >= 0)
- {
- m_findCurPos = ret - 1;
- SendScintilla(SCI_GOTOPOS, ret);
- SendScintilla(SCI_SETSELECTION, ret, ret + str.length());
- }
- else
- {
- QMessageBox::information(this, tr("Not Find"), tr("Not Find Prev!"));
- m_textFindWin->activateWindow();
- }
- }
- }
- }
- //定位到文件夹
- void QsciDisplayWindow::slot_showFileInExplorer()
- {
- showFileInExplorer(m_filePath);
- }
|