mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 05:49:53 +08:00
clean up HGMarkdownHighlighter
Signed-off-by: Le Tan <tamlokveer@gmail.com>
This commit is contained in:
parent
22bf96c6e3
commit
33f62915e1
@ -8,26 +8,88 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QtGui>
|
#include <QtGui>
|
||||||
|
#include <QtDebug>
|
||||||
#include "hgmarkdownhighlighter.h"
|
#include "hgmarkdownhighlighter.h"
|
||||||
|
|
||||||
|
#ifndef QT_NO_DEBUG
|
||||||
|
#define V_HIGHLIGHT_DEBUG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const int WorkerThread::initCapacity = 1024;
|
||||||
|
|
||||||
|
WorkerThread::WorkerThread()
|
||||||
|
: QThread(NULL), content(NULL), result(NULL),
|
||||||
|
capacity(0)
|
||||||
|
{
|
||||||
|
resizeBuffer(initCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
WorkerThread::~WorkerThread()
|
WorkerThread::~WorkerThread()
|
||||||
{
|
{
|
||||||
if (result != NULL)
|
if (result) {
|
||||||
pmh_free_elements(result);
|
pmh_free_elements(result);
|
||||||
free(content);
|
result = NULL;
|
||||||
|
}
|
||||||
|
if (content) {
|
||||||
|
delete [] content;
|
||||||
|
capacity = 0;
|
||||||
|
content = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WorkerThread::resizeBuffer(int newCap)
|
||||||
|
{
|
||||||
|
if (newCap == capacity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (capacity > 0) {
|
||||||
|
Q_ASSERT(content);
|
||||||
|
delete [] content;
|
||||||
|
}
|
||||||
|
capacity = newCap;
|
||||||
|
content = new char [capacity];
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkerThread::prepareAndStart(const char *data)
|
||||||
|
{
|
||||||
|
Q_ASSERT(data);
|
||||||
|
int len = strlen(data);
|
||||||
|
if (len >= capacity) {
|
||||||
|
resizeBuffer(qMax(2 * capacity, len + 1));
|
||||||
|
}
|
||||||
|
Q_ASSERT(content);
|
||||||
|
memcpy(content, data, len);
|
||||||
|
content[len] = '\0';
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
pmh_free_elements(result);
|
||||||
|
result = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
pmh_element** WorkerThread::retriveResult()
|
||||||
|
{
|
||||||
|
Q_ASSERT(result);
|
||||||
|
pmh_element** ret = result;
|
||||||
|
result = NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void WorkerThread::run()
|
void WorkerThread::run()
|
||||||
{
|
{
|
||||||
if (content == NULL)
|
if (content == NULL)
|
||||||
return;
|
return;
|
||||||
|
Q_ASSERT(!result);
|
||||||
pmh_markdown_to_elements(content, pmh_EXT_NONE, &result);
|
pmh_markdown_to_elements(content, pmh_EXT_NONE, &result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Will be freeed by parent automatically
|
||||||
HGMarkdownHighlighter::HGMarkdownHighlighter(QTextDocument *parent,
|
HGMarkdownHighlighter::HGMarkdownHighlighter(QTextDocument *parent,
|
||||||
int aWaitInterval) : QObject(parent)
|
int aWaitInterval) : QObject(parent)
|
||||||
{
|
{
|
||||||
highlightingStyles = NULL;
|
workerThread = new WorkerThread();
|
||||||
workerThread = NULL;
|
|
||||||
cached_elements = NULL;
|
cached_elements = NULL;
|
||||||
waitInterval = aWaitInterval;
|
waitInterval = aWaitInterval;
|
||||||
timer = new QTimer(this);
|
timer = new QTimer(this);
|
||||||
@ -37,20 +99,36 @@ HGMarkdownHighlighter::HGMarkdownHighlighter(QTextDocument *parent,
|
|||||||
document = parent;
|
document = parent;
|
||||||
connect(document, SIGNAL(contentsChange(int,int,int)),
|
connect(document, SIGNAL(contentsChange(int,int,int)),
|
||||||
this, SLOT(handleContentsChange(int,int,int)));
|
this, SLOT(handleContentsChange(int,int,int)));
|
||||||
|
connect(workerThread, SIGNAL(finished()), this, SLOT(threadFinished()));
|
||||||
this->parse();
|
this->parse();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HGMarkdownHighlighter::setStyles(QVector<HighlightingStyle> &styles)
|
HGMarkdownHighlighter::~HGMarkdownHighlighter()
|
||||||
{
|
{
|
||||||
this->highlightingStyles = &styles;
|
if (workerThread) {
|
||||||
|
if (workerThread->isRunning()) {
|
||||||
|
workerThread->wait();
|
||||||
|
}
|
||||||
|
delete workerThread;
|
||||||
|
workerThread = NULL;
|
||||||
|
}
|
||||||
|
if (cached_elements) {
|
||||||
|
pmh_free_elements(cached_elements);
|
||||||
|
cached_elements = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define STY(type, format) styles->append((HighlightingStyle){type, format})
|
void HGMarkdownHighlighter::setStyles(const QVector<HighlightingStyle> &styles)
|
||||||
|
{
|
||||||
|
this->highlightingStyles = styles;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define STY(type, format) styles.append({type, format})
|
||||||
|
|
||||||
void HGMarkdownHighlighter::setDefaultStyles()
|
void HGMarkdownHighlighter::setDefaultStyles()
|
||||||
{
|
{
|
||||||
QVector<HighlightingStyle> *styles = new QVector<HighlightingStyle>();
|
QVector<HighlightingStyle> &styles = this->highlightingStyles;
|
||||||
|
styles.clear();
|
||||||
|
|
||||||
QTextCharFormat headers; headers.setForeground(QBrush(Qt::darkBlue));
|
QTextCharFormat headers; headers.setForeground(QBrush(Qt::darkBlue));
|
||||||
headers.setBackground(QBrush(QColor(230,230,240)));
|
headers.setBackground(QBrush(QColor(230,230,240)));
|
||||||
@ -100,8 +178,6 @@ void HGMarkdownHighlighter::setDefaultStyles()
|
|||||||
|
|
||||||
QTextCharFormat blockquote; blockquote.setForeground(QBrush(Qt::darkRed));
|
QTextCharFormat blockquote; blockquote.setForeground(QBrush(Qt::darkRed));
|
||||||
STY(pmh_BLOCKQUOTE, blockquote);
|
STY(pmh_BLOCKQUOTE, blockquote);
|
||||||
|
|
||||||
this->setStyles(*styles);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HGMarkdownHighlighter::clearFormatting()
|
void HGMarkdownHighlighter::clearFormatting()
|
||||||
@ -116,18 +192,23 @@ void HGMarkdownHighlighter::clearFormatting()
|
|||||||
void HGMarkdownHighlighter::highlight()
|
void HGMarkdownHighlighter::highlight()
|
||||||
{
|
{
|
||||||
if (cached_elements == NULL) {
|
if (cached_elements == NULL) {
|
||||||
qDebug() << "cached_elements is NULL";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (highlightingStyles == NULL)
|
if (highlightingStyles.isEmpty())
|
||||||
this->setDefaultStyles();
|
this->setDefaultStyles();
|
||||||
|
|
||||||
this->clearFormatting();
|
this->clearFormatting();
|
||||||
|
|
||||||
for (int i = 0; i < highlightingStyles->size(); i++)
|
// To make sure content is not changed by highlight operations.
|
||||||
|
// May be resource-consuming. Can be removed if no need.
|
||||||
|
#ifdef V_HIGHLIGHT_DEBUG
|
||||||
|
QString oriContent = document->toPlainText();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (int i = 0; i < highlightingStyles.size(); i++)
|
||||||
{
|
{
|
||||||
HighlightingStyle style = highlightingStyles->at(i);
|
const HighlightingStyle &style = highlightingStyles[i];
|
||||||
pmh_element *elem_cursor = cached_elements[style.type];
|
pmh_element *elem_cursor = cached_elements[style.type];
|
||||||
while (elem_cursor != NULL)
|
while (elem_cursor != NULL)
|
||||||
{
|
{
|
||||||
@ -176,26 +257,26 @@ void HGMarkdownHighlighter::highlight()
|
|||||||
}
|
}
|
||||||
|
|
||||||
document->markContentsDirty(0, document->characterCount());
|
document->markContentsDirty(0, document->characterCount());
|
||||||
|
|
||||||
|
#ifdef V_HIGHLIGHT_DEBUG
|
||||||
|
if (oriContent != document->toPlainText()) {
|
||||||
|
qWarning() << "warning: content was changed before and after highlighting";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HGMarkdownHighlighter::parse()
|
void HGMarkdownHighlighter::parse()
|
||||||
{
|
{
|
||||||
if (workerThread != NULL && workerThread->isRunning()) {
|
if (workerThread->isRunning()) {
|
||||||
parsePending = true;
|
parsePending = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString content = document->toPlainText();
|
QString content = document->toPlainText();
|
||||||
QByteArray ba = content.toUtf8();
|
QByteArray ba = content.toUtf8();
|
||||||
char *content_cstring = strdup((char *)ba.data());
|
|
||||||
|
|
||||||
if (workerThread != NULL)
|
|
||||||
delete workerThread;
|
|
||||||
workerThread = new WorkerThread();
|
|
||||||
workerThread->content = content_cstring;
|
|
||||||
connect(workerThread, SIGNAL(finished()), this, SLOT(threadFinished()));
|
|
||||||
parsePending = false;
|
parsePending = false;
|
||||||
workerThread->start();
|
workerThread->prepareAndStart((const char *)ba.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
void HGMarkdownHighlighter::threadFinished()
|
void HGMarkdownHighlighter::threadFinished()
|
||||||
@ -205,11 +286,10 @@ void HGMarkdownHighlighter::threadFinished()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cached_elements != NULL)
|
if (cached_elements != NULL) {
|
||||||
pmh_free_elements(cached_elements);
|
pmh_free_elements(cached_elements);
|
||||||
cached_elements = workerThread->result;
|
}
|
||||||
workerThread->result = NULL;
|
cached_elements = workerThread->retriveResult();
|
||||||
|
|
||||||
this->highlight();
|
this->highlight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,10 +24,21 @@ QT_END_NAMESPACE
|
|||||||
class WorkerThread : public QThread
|
class WorkerThread : public QThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
WorkerThread();
|
||||||
~WorkerThread();
|
~WorkerThread();
|
||||||
|
void prepareAndStart(const char *data);
|
||||||
|
pmh_element** retriveResult();
|
||||||
|
|
||||||
|
protected:
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void resizeBuffer(int newCap);
|
||||||
|
|
||||||
char *content;
|
char *content;
|
||||||
|
int capacity;
|
||||||
pmh_element **result;
|
pmh_element **result;
|
||||||
|
static const int initCapacity;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HighlightingStyle
|
struct HighlightingStyle
|
||||||
@ -42,7 +53,8 @@ class HGMarkdownHighlighter : public QObject
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
HGMarkdownHighlighter(QTextDocument *parent = 0, int aWaitInterval = 2000);
|
HGMarkdownHighlighter(QTextDocument *parent = 0, int aWaitInterval = 2000);
|
||||||
void setStyles(QVector<HighlightingStyle> &styles);
|
~HGMarkdownHighlighter();
|
||||||
|
void setStyles(const QVector<HighlightingStyle> &styles);
|
||||||
int waitInterval;
|
int waitInterval;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
@ -56,7 +68,7 @@ private:
|
|||||||
WorkerThread *workerThread;
|
WorkerThread *workerThread;
|
||||||
bool parsePending;
|
bool parsePending;
|
||||||
pmh_element **cached_elements;
|
pmh_element **cached_elements;
|
||||||
QVector<HighlightingStyle> *highlightingStyles;
|
QVector<HighlightingStyle> highlightingStyles;
|
||||||
|
|
||||||
void clearFormatting();
|
void clearFormatting();
|
||||||
void highlight();
|
void highlight();
|
||||||
|
@ -28,7 +28,9 @@ VEditor::VEditor(const QString &path, const QString &name, bool modifiable,
|
|||||||
|
|
||||||
VEditor::~VEditor()
|
VEditor::~VEditor()
|
||||||
{
|
{
|
||||||
delete noteFile;
|
if (noteFile) {
|
||||||
|
delete noteFile;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VEditor::setupUI()
|
void VEditor::setupUI()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user