#include "textdocument.h"
#include "textcursor.h"
#include "textcursor_p.h"
#include "textdocument_p.h"
#include <QBuffer>
#include <QIODevice>
#include <QObject>
#include <QString>
#include <QString>
#include <QFile>
#include <QFileInfo>
#include <QList>
#include <QTextCharFormat>
#include <QVariant>
#include <QDesktopServices>
#include <qalgorithms.h>
// #define DEBUG_CACHE_HITS
#ifndef TEXTDOCUMENT_FIND_INTERVAL_PERCENTAGE
#define TEXTDOCUMENT_FIND_INTERVAL_PERCENTAGE 1000
#endif
#ifndef TEXTDOCUMENT_MAX_INTERVAL
#define TEXTDOCUMENT_MAX_INTERVAL 1000
#endif
#ifdef TEXTDOCUMENT_FIND_SLEEP
static void findSleep(const TextDocument *document)
{
Q_ASSERT(document);
const int duration = document->property("TEXTDOCUMENT_FIND_SLEEP").toInt();
if (duration > 0) {
usleep(duration * 1000);
}
}
#endif
TextDocument::TextDocument(QObject *parent)
: QObject(parent), d(new TextDocumentPrivate(this))
{
}
TextDocument::~TextDocument()
{
{
QWriteLocker locker(d->readWriteLock);
foreach(TextCursorSharedPrivate *cursor, d->textCursors) {
cursor->document = 0;
}
Chunk *c = d->first;
while (c) {
if (!(d->options & KeepTemporaryFiles) && !c->swap.isEmpty())
QFile::remove(c->swap);
Chunk *tmp = c;
c = c->next;
delete tmp;
}
foreach(TextSection *section, d->sections) {
section->d.document = 0;
section->d.textEdit = 0;
delete section;
}
if (d->ownDevice)
delete d->device.data();
}
delete d->readWriteLock;
delete d;
}
bool TextDocument::load(QIODevice *device, DeviceMode mode, QTextCodec *codec)
{
QWriteLocker locker(d->readWriteLock);
Q_ASSERT(device);
if (!device->isReadable())
return false;
Options options = d->options;
if (options & ConvertCarriageReturns && mode == Sparse) {
qWarning("TextDocument::load() ConvertCarriageReturns is incompatible with Sparse");
options &= ~ConvertCarriageReturns;
}
if ((options & (AutoDetectCarriageReturns|ConvertCarriageReturns)) == (AutoDetectCarriageReturns|ConvertCarriageReturns))
options &= ~AutoDetectCarriageReturns;
foreach(TextSection *section, d->sections) {
emit sectionRemoved(section);
section->d.document = 0;
delete section;
}
d->sections.clear();
if (d->documentSize > 0) {
emit charactersRemoved(0, d->documentSize);
}
Chunk *c = d->first;
while (c) {
Chunk *tmp = c;
c = c->next;
delete tmp;
}
d->textCodec = codec;
d->documentSize = device->size();
if (d->documentSize <= d->chunkSize && mode == Sparse && !(options & NoImplicitLoadAll))
mode = LoadAll;
#if 0
if (codec && mode == Sparse) {
qWarning("Sparse mode doesn't really work with unicode data yet. I am working on it.\n--\nAnders");
}
#endif
d->first = d->last = 0;
if (d->device) {
if (d->ownDevice && d->device.data() != device) // this is done when saving to the same file
delete d->device.data();
}
d->ownDevice = false;
d->device = device;
d->deviceMode = mode;
#ifndef NO_TEXTDOCUMENT_CHUNK_CACHE
d->cachedChunk = 0;
d->cachedChunkPos = -1;
d->cachedChunkData.clear();
#endif
#ifndef NO_TEXTDOCUMENT_READ_CACHE
d->cachePos = -1;
d->cache.clear();
#endif
switch (d->deviceMode) {
case LoadAll: {
device->seek(0);
QTextStream ts(device);
if (d->textCodec)
ts.setCodec(d->textCodec);
Chunk *current = 0;
d->documentSize = 0; // in case of unicode
do {
Chunk *c = new Chunk;
c->data = ts.read(d->chunkSize);
if (options & AutoDetectCarriageReturns) {
if (c->data.contains(QLatin1Char('\n'))) {
options |= ConvertCarriageReturns;
}
options &= ~AutoDetectCarriageReturns;
}
if (options & ConvertCarriageReturns)
c->data.remove(QLatin1Char('\r'));
d->documentSize += c->data.size();
if (current) {
current->next = c;
c->previous = current;
} else {
d->first = c;
}
current = c;
} while (!ts.atEnd());
d->last = current;
break; }
case Sparse: {
int index = 0;
Chunk *current = 0;
do {
Chunk *chunk = new Chunk;
chunk->from = index;
chunk->length = qMin<int>(d->documentSize - index, d->chunkSize);
if (!current) {
d->first = chunk;
} else {
chunk->previous = current;
current->next = chunk;
}
current = chunk;
index += chunk->length;
} while (index < d->documentSize);
d->last = current;
break; }
}
// if (d->first)
// d->first->firstLineIndex = 0;
emit charactersAdded(0, d->documentSize);
emit documentSizeChanged(d->documentSize);
emit textChanged();
setModified(false);
return true;
}
bool TextDocument::load(const QString &fileName, DeviceMode mode, QTextCodec *codec)
{
if (mode == LoadAll) {
QFile from(fileName);
return from.open(QIODevice::ReadOnly) && load(&from, mode, codec);
} else {
QFile *file = new QFile(fileName);
if (file->open(QIODevice::ReadOnly) && load(file, mode, codec)) {
d->ownDevice = true;
return true;
} else {
delete file;
d->ownDevice = false;
return false;
}
}
}
void TextDocument::clear()
{
setText(QString());
}
QString TextDocument::read(int pos, int size) const
{
QReadLocker locker(d->readWriteLock);
Q_ASSERT(size >= 0);
if (size == 0 || pos == d->documentSize) {
return QString();
}
Q_ASSERT(pos < d->documentSize);
#ifndef NO_TEXTDOCUMENT_READ_CACHE
#ifdef DEBUG_CACHE_HITS
static int hits = 0;
static int misses = 0;
#endif
if (d->cachePos != -1 && pos >= d->cachePos && d->cache.size() - (pos - d->cachePos) >= size) {
#ifdef DEBUG_CACHE_HITS
qWarning() << "read hits" << ++hits << "misses" << misses;
#endif
return d->cache.mid(pos - d->cachePos, size);
}
#ifdef DEBUG_CACHE_HITS
qWarning() << "read hits" << hits << "misses" << ++misses;
#endif
#endif
QString ret(size, '\0');
int written = 0;
int offset;
Chunk *c = d->chunkAt(pos, &offset);
Q_ASSERT(c);
int chunkPos = pos - offset;
while (written < size && c) {
const int max = qMin(size - written, c->size() - offset);
const QString data = d->chunkData(c, chunkPos);
chunkPos += data.size();
ret.replace(written, max, data.constData() + offset, max);
written += max;
offset = 0;
c = c->next;
}
if (written < size) {
ret.truncate(written);
}
Q_ASSERT(!c || written == size);
#ifndef NO_TEXTDOCUMENT_READ_CACHE
d->cachePos = pos;
d->cache = ret;
#endif
return ret;
}
QStringRef TextDocument::readRef(int pos, int size) const
{
QReadLocker locker(d->readWriteLock);
int offset;
Chunk *c = d->chunkAt(pos, &offset);
if (c && pos + offset + size <= c->size()) {
const QString string = d->chunkData(c, pos - offset);
return string.midRef(offset, size);
}
return QStringRef();
}
bool TextDocument::save(const QString &file)
{
QFile from(file);
return from.open(QIODevice::WriteOnly) && save(&from);
}
bool TextDocument::save()
{
return d->device && save(d->device.data());
}
static bool isSameFile(const QIODevice *left, const QIODevice *right)
{
if (left == right)
return true;
if (const QFile *lf = qobject_cast<con
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
testBrowser.zip (22个子文件)
testBrowser
textbrowserwidget.cpp 850B
testBrowser.pro.user 22KB
textbrowserwidget.ui 2KB
testBrowser.pro 1KB
main.cpp 186B
textedit
textedit.cpp 45KB
textsection.cpp 2KB
textsection.h 2KB
textdocument.cpp 58KB
textedit_p.h 4KB
editor.cpp 344B
editor.h 263B
textcursor.h 4KB
textcursor_p.h 7KB
textdocument_p.h 11KB
textcursor.cpp 24KB
textsection_p.h 1KB
textdocument.h 7KB
textlayout_p.cpp 14KB
textedit.h 6KB
textlayout_p.h 4KB
textbrowserwidget.h 542B
共 22 条
- 1
资源评论
smilesa
- 粉丝: 7
- 资源: 16
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- C183579-123578-c1235789.jpg
- Qt5.14 绘画板 Qt Creator C++项目
- python实现Excel表格合并
- Java实现读取Excel批量发送邮件.zip
- 【java毕业设计】商城后台管理系统源码(springboot+vue+mysql+说明文档).zip
- 【java毕业设计】开发停车位管理系统(调用百度地图API)源码(springboot+vue+mysql+说明文档).zip
- 星耀软件库(升级版).apk.1
- 基于Django后端和Vue前端的多语言购物车项目设计源码
- 基于Python与Vue的浮光在线教育平台源码设计
- 31129647070291Eclipson MXS R.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功