notepad--/qscidisplaywindow.cpp

394 lines
9.7 KiB
C++
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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);
}