| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393 |
- #include "qscidisplaywindow.h"
- #include "MediatorDisplay.h"
- #include "textfind.h"
- #include "common.h"
- #include "styleset.h"
- #include <QScrollBar>
- #include <QFileInfo>
- #include <QProcess>
- #include <QMessageBox>
- #include <stdexcept>
- QsciDisplayWindow::QsciDisplayWindow(QWidget *parent):QsciScintilla(parent), m_textFindWin(nullptr), m_preFirstLineNum(0), m_isShowFindItem(true)
- {
- //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, false);
- 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
- connect(this, &QsciDisplayWindow::delayWork, this, &QsciDisplayWindow::slot_delayWork, Qt::QueuedConnection);
- }
- QsciDisplayWindow::~QsciDisplayWindow()
- {
- if (m_textFindWin != nullptr)
- {
- delete m_textFindWin;
- m_textFindWin = nullptr;
- }
- }
- 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();
- }
- }
- const int MAXLINEHIGHLIGHT = 400;
- void QsciDisplayWindow::slot_delayWork()
- {
- 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);
- }
- }
- }
- 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();
- }
- }
- //
- //int nbDigitsFromNbLines(size_t nbLines)
- //{
- // int nbDigits = 0; // minimum number of digit should be 4
- // if (nbLines < 10) nbDigits = 1;
- // else if (nbLines < 100) nbDigits = 2;
- // else if (nbLines < 1000) nbDigits = 3;
- // else if (nbLines < 10000) nbDigits = 4;
- // else if (nbLines < 100000) nbDigits = 5;
- // else if (nbLines < 1000000) nbDigits = 6;
- // else // rare case
- // {
- // nbDigits = 7;
- // nbLines /= 1000000;
- //
- // while (nbLines)
- // {
- // nbLines /= 10;
- // ++nbDigits;
- // }
- // }
- // return nbDigits;
- //}
- 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 < 3 ? 3 : nbDigits;
-
- auto pixelWidth = 8 + nbDigits * execute(SCI_TEXTWIDTH, STYLE_LINENUMBER, reinterpret_cast<sptr_t>("8"));
- execute(SCI_SETMARGINWIDTHN, 3, 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;
- }
- void QsciDisplayWindow::travEveryBlockToSave(std::function<void(QString&, int)> savefun, QList<BlockUserData*>* externLineInfo)
- {
- }
- 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->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()
- {
- QString path, cmd;
- #ifdef _WIN32
- path = m_filePath.replace("/", "\\");
- cmd = QString("explorer.exe /select,%1").arg(path);
- #else
- path = m_filePath.replace("\\", "/");
- cmd = QString("open -R %1").arg(path);
- #endif
- QProcess process;
- process.startDetached(cmd);
- }
|