Compare commits
2 Commits
8c866d090f
...
ed118376d5
Author | SHA1 | Date |
---|---|---|
|
ed118376d5 | |
|
31c896c9dc |
|
@ -1 +1 @@
|
|||
Subproject commit f2034769ce887367e97a5fbaced5b14aa8039fd3
|
||||
Subproject commit d259eab41fd08fbde83cf1a7b01f4def6a09e895
|
|
@ -57,8 +57,6 @@ add_library(
|
|||
document/commands/baseaddrcommand.h
|
||||
document/commands/encodingchangecommand.cpp
|
||||
document/commands/encodingchangecommand.h
|
||||
document/buffer/qwindriverbuffer.h
|
||||
document/buffer/qwindriverbuffer.cpp
|
||||
document/qstoragedevice.h
|
||||
document/qstoragedevice.cpp
|
||||
document/qhexcursor.cpp
|
||||
|
@ -71,8 +69,6 @@ add_library(
|
|||
document/qhexrenderer.h
|
||||
QHexEdit2/chunks.cpp
|
||||
QHexEdit2/chunks.h
|
||||
QHexEdit2/chunks_win.cpp
|
||||
QHexEdit2/chunks_win.h
|
||||
qhexview.h
|
||||
qhexview.cpp)
|
||||
|
||||
|
|
|
@ -1,310 +0,0 @@
|
|||
#include "chunks_win.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
||||
#define READ_CHUNK_MASK Q_INT64_C(0xfffffffffffffd00)
|
||||
|
||||
/*this file is modified by wingsummer in order to fit the QHexView*/
|
||||
|
||||
// ***************************************** Constructors and file settings
|
||||
|
||||
Chunks_win::Chunks_win(QObject *parent) : QObject(parent) {}
|
||||
|
||||
Chunks_win::Chunks_win(const QStorageInfo &ioDevice, QObject *parent)
|
||||
: QObject(parent) {
|
||||
setIODevice(ioDevice);
|
||||
}
|
||||
|
||||
Chunks_win::~Chunks_win() {
|
||||
if (_handle != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(_handle);
|
||||
}
|
||||
}
|
||||
|
||||
bool Chunks_win::setIODevice(const QStorageInfo &ioDevice) {
|
||||
if (ioDevice.isValid()) {
|
||||
auto device = ioDevice.device();
|
||||
auto devicePrefix = QStringLiteral("\\\\.\\");
|
||||
QString dd = devicePrefix +
|
||||
device.mid(devicePrefix.length(),
|
||||
device.length() - devicePrefix.length() - 1);
|
||||
|
||||
_handle = CreateFileA(dd.toLatin1(), GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
|
||||
OPEN_EXISTING, 0, NULL);
|
||||
if (_handle == INVALID_HANDLE_VALUE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DISK_GEOMETRY diskGeometry;
|
||||
DWORD bytesReturned;
|
||||
if (!DeviceIoControl(_handle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
|
||||
&diskGeometry, sizeof(diskGeometry),
|
||||
&bytesReturned, NULL)) {
|
||||
|
||||
CloseHandle(_handle);
|
||||
return false;
|
||||
}
|
||||
|
||||
// dont use ioDevice.bytesTotal(),
|
||||
// because it's use GetDiskFreeSpaceEx API to get
|
||||
this->CHUNK_SIZE = diskGeometry.BytesPerSector;
|
||||
_size = diskGeometry.Cylinders.QuadPart *
|
||||
diskGeometry.TracksPerCylinder * diskGeometry.SectorsPerTrack *
|
||||
diskGeometry.BytesPerSector;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
_chunks.clear();
|
||||
_pos = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// ***************************************** Getting data out of Chunks_win
|
||||
|
||||
QByteArray Chunks_win::data(qsizetype pos, qsizetype maxSize) {
|
||||
qsizetype ioDelta = 0;
|
||||
qsizetype chunkIdx = 0;
|
||||
|
||||
Chunk_win chunk;
|
||||
QByteArray buffer;
|
||||
|
||||
// Do some checks and some arrangements
|
||||
|
||||
if (pos >= _size)
|
||||
return buffer;
|
||||
|
||||
if (maxSize < 0)
|
||||
maxSize = _size;
|
||||
else if ((pos + maxSize) > _size)
|
||||
maxSize = _size - pos;
|
||||
|
||||
while (maxSize > 0) {
|
||||
chunk.absPos = std::numeric_limits<qsizetype>::max();
|
||||
bool chunksLoopOngoing = true;
|
||||
while ((chunkIdx < _chunks.count()) && chunksLoopOngoing) {
|
||||
// In this section, we track changes before our required data and
|
||||
// we take the editdet data, if availible. ioDelta is a difference
|
||||
// counter to justify the read pointer to the original data, if
|
||||
// data in between was deleted or inserted.
|
||||
|
||||
chunk = _chunks[chunkIdx];
|
||||
if (chunk.absPos > pos)
|
||||
chunksLoopOngoing = false;
|
||||
else {
|
||||
chunkIdx += 1;
|
||||
qsizetype count;
|
||||
qsizetype chunkOfs = pos - chunk.absPos;
|
||||
if (qsizetype(maxSize) > chunk.data.size() - chunkOfs) {
|
||||
count = chunk.data.size() - chunkOfs;
|
||||
ioDelta += CHUNK_SIZE - chunk.data.size();
|
||||
} else
|
||||
count = maxSize;
|
||||
if (count > 0) {
|
||||
buffer += chunk.data.mid(chunkOfs, count);
|
||||
maxSize -= count;
|
||||
pos += count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((maxSize > 0) && (pos < chunk.absPos)) {
|
||||
// In this section, we read data from the original source. This only
|
||||
// will happen, whe no copied data is available
|
||||
|
||||
qint64 byteCount;
|
||||
QByteArray readBuffer;
|
||||
if (chunk.absPos - pos > qsizetype(maxSize))
|
||||
byteCount = maxSize;
|
||||
else
|
||||
byteCount = chunk.absPos - pos;
|
||||
|
||||
maxSize -= byteCount;
|
||||
|
||||
// Set the pointer to the start of the sector you want to read
|
||||
LARGE_INTEGER sectorOffset;
|
||||
auto sorquot = (pos + ioDelta) / CHUNK_SIZE;
|
||||
auto sorrem = (pos + ioDelta) % CHUNK_SIZE;
|
||||
|
||||
sectorOffset.QuadPart = sorquot * CHUNK_SIZE;
|
||||
Q_ASSERT(SetFilePointerEx(_handle, sectorOffset, NULL, FILE_BEGIN));
|
||||
|
||||
readBuffer.fill(0, CHUNK_SIZE);
|
||||
DWORD bytesRead;
|
||||
Q_ASSERT(ReadFile(_handle, readBuffer.data(), CHUNK_SIZE,
|
||||
&bytesRead, NULL));
|
||||
readBuffer = readBuffer.mid(sorrem, byteCount);
|
||||
buffer += readBuffer;
|
||||
pos += readBuffer.size();
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
bool Chunks_win::write(QIODevice *iODevice, qsizetype pos, qsizetype count) {
|
||||
if (count == -1)
|
||||
count = _size;
|
||||
|
||||
// fix the bug
|
||||
bool ok = (iODevice->isOpen() && iODevice->isWritable()) ||
|
||||
iODevice->open(QIODevice::WriteOnly);
|
||||
if (ok) {
|
||||
for (auto idx = pos; idx < qsizetype(count); idx += CHUNK_SIZE) {
|
||||
QByteArray ba = data(idx, CHUNK_SIZE);
|
||||
iODevice->write(ba);
|
||||
}
|
||||
iODevice->close();
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
// ***************************************** Search API
|
||||
|
||||
qsizetype Chunks_win::indexOf(const QByteArray &ba, qsizetype from) {
|
||||
qsizetype result = -1;
|
||||
QByteArray buffer;
|
||||
|
||||
for (auto pos = from; (pos < _size) && (result < 0); pos += CHUNK_SIZE) {
|
||||
buffer = data(pos, CHUNK_SIZE + ba.size() - 1);
|
||||
int findPos = buffer.indexOf(ba);
|
||||
if (findPos >= 0)
|
||||
result = pos + findPos;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
qsizetype Chunks_win::lastIndexOf(const QByteArray &ba, qsizetype from) {
|
||||
qint64 result = -1;
|
||||
QByteArray buffer;
|
||||
|
||||
for (auto pos = from; (pos > 0) && (result < 0); pos -= CHUNK_SIZE) {
|
||||
auto sPos = pos - CHUNK_SIZE - ba.size() + 1;
|
||||
/*if (sPos < 0)
|
||||
sPos = 0;*/
|
||||
buffer = data(sPos, pos - sPos);
|
||||
int findPos = buffer.lastIndexOf(ba);
|
||||
if (findPos >= 0)
|
||||
result = sPos + findPos;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// ***************************************** Char manipulations
|
||||
|
||||
bool Chunks_win::insert(qsizetype pos, char b) {
|
||||
if (pos > _size)
|
||||
return false;
|
||||
qsizetype chunkIdx;
|
||||
if (pos == _size) {
|
||||
chunkIdx = getChunkIndex(pos - 1);
|
||||
} else
|
||||
chunkIdx = getChunkIndex(pos);
|
||||
auto posInBa = pos - _chunks[chunkIdx].absPos;
|
||||
_chunks[chunkIdx].data.insert(int(posInBa), b);
|
||||
_chunks[chunkIdx].dataChanged.insert(int(posInBa), char(1));
|
||||
for (int idx = chunkIdx + 1; idx < _chunks.size(); idx++)
|
||||
_chunks[idx].absPos += 1;
|
||||
_size += 1;
|
||||
_pos = pos;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Chunks_win::overwrite(qsizetype pos, char b) {
|
||||
if (pos >= _size)
|
||||
return false;
|
||||
auto chunkIdx = getChunkIndex(pos);
|
||||
auto posInBa = pos - _chunks[chunkIdx].absPos;
|
||||
_chunks[chunkIdx].data[int(posInBa)] = b;
|
||||
_chunks[chunkIdx].dataChanged[int(posInBa)] = char(1);
|
||||
_pos = pos;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Chunks_win::removeAt(qsizetype pos) {
|
||||
if (pos >= _size)
|
||||
return false;
|
||||
auto chunkIdx = getChunkIndex(pos);
|
||||
auto posInBa = pos - _chunks[chunkIdx].absPos;
|
||||
_chunks[chunkIdx].data.remove(int(posInBa), 1);
|
||||
_chunks[chunkIdx].dataChanged.remove(int(posInBa), 1);
|
||||
for (int idx = chunkIdx + 1; idx < _chunks.size(); idx++)
|
||||
_chunks[idx].absPos -= 1;
|
||||
_size -= 1;
|
||||
_pos = pos;
|
||||
return true;
|
||||
}
|
||||
|
||||
// ***************************************** Utility functions
|
||||
|
||||
char Chunks_win::operator[](qsizetype pos) {
|
||||
auto d = data(pos, 1);
|
||||
if (d.isEmpty())
|
||||
return '0';
|
||||
return d.at(0);
|
||||
}
|
||||
|
||||
qsizetype Chunks_win::pos() { return _pos; }
|
||||
|
||||
qsizetype Chunks_win::size() { return _size; }
|
||||
|
||||
qsizetype Chunks_win::getChunkIndex(qsizetype absPos) {
|
||||
// This routine checks, if there is already a copied chunk available. If so,
|
||||
// it returns a reference to it. If there is no copied chunk available,
|
||||
// original data will be copied into a new chunk.
|
||||
|
||||
qsizetype foundIdx = -1;
|
||||
qsizetype insertIdx = 0;
|
||||
qsizetype ioDelta = 0;
|
||||
|
||||
// fix the bug by wingsummer
|
||||
if (absPos < 0) {
|
||||
Chunk_win newChunk;
|
||||
newChunk.data = QByteArray(CHUNK_SIZE, 0);
|
||||
newChunk.absPos = 0;
|
||||
newChunk.dataChanged = nullptr;
|
||||
_chunks.insert(insertIdx, newChunk);
|
||||
return insertIdx;
|
||||
}
|
||||
|
||||
for (int idx = 0; idx < _chunks.size(); idx++) {
|
||||
Chunk_win chunk = _chunks[idx];
|
||||
if ((absPos >= chunk.absPos) &&
|
||||
(absPos < (chunk.absPos + chunk.data.size()))) {
|
||||
foundIdx = idx;
|
||||
break;
|
||||
}
|
||||
if (absPos < chunk.absPos) {
|
||||
insertIdx = idx;
|
||||
break;
|
||||
}
|
||||
ioDelta += chunk.data.size() - CHUNK_SIZE;
|
||||
insertIdx = idx + 1;
|
||||
}
|
||||
|
||||
if (foundIdx == -1) {
|
||||
Chunk_win newChunk;
|
||||
auto readAbsPos = absPos - ioDelta;
|
||||
auto readPos = (readAbsPos & READ_CHUNK_MASK);
|
||||
|
||||
// Set the pointer to the start of the sector you want to read
|
||||
LARGE_INTEGER sectorOffset;
|
||||
sectorOffset.QuadPart = readPos;
|
||||
Q_ASSERT(SetFilePointerEx(_handle, sectorOffset, NULL, FILE_BEGIN));
|
||||
|
||||
newChunk.data.fill(0, CHUNK_SIZE);
|
||||
DWORD bytesRead = 0;
|
||||
Q_ASSERT(ReadFile(_handle, newChunk.data.data(), CHUNK_SIZE, &bytesRead,
|
||||
NULL));
|
||||
newChunk.data.resize(bytesRead);
|
||||
|
||||
newChunk.absPos = absPos - (readAbsPos - readPos);
|
||||
newChunk.dataChanged = QByteArray(newChunk.data.size(), char(0));
|
||||
_chunks.insert(insertIdx, newChunk);
|
||||
foundIdx = insertIdx;
|
||||
}
|
||||
return foundIdx;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,78 +0,0 @@
|
|||
#ifndef Chunks_winWIN_H
|
||||
#define Chunks_winWIN_H
|
||||
|
||||
/** \cond docNever */
|
||||
|
||||
/*! The Chunks_win class is the storage backend for QHexEdit.
|
||||
*
|
||||
* When QHexEdit loads data, Chunks_win access them using a QIODevice interface.
|
||||
* When the app uses a QByteArray interface, QBuffer is used to provide again a
|
||||
* QIODevice like interface. No data will be changed, therefore Chunks_win opens
|
||||
* the QIODevice in QIODevice::ReadOnly mode. After every access Chunks_win
|
||||
* closes the QIODevice, that's why external applications can overwrite files
|
||||
* while QHexEdit shows them.
|
||||
*
|
||||
* When the the user starts to edit the data, Chunks_win creates a local copy of
|
||||
* a chunk of data (4 kilobytes) and notes all changes there. Parallel to that
|
||||
* chunk, there is a second chunk, which keep track of which bytes are changed
|
||||
* and which not.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
// note: this class is only for storage device reading
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
||||
#include <QStorageInfo>
|
||||
#include <Windows.h>
|
||||
|
||||
struct Chunk_win {
|
||||
QByteArray data;
|
||||
QByteArray dataChanged;
|
||||
qsizetype absPos;
|
||||
};
|
||||
|
||||
class Chunks_win : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
// Constructors and file settings
|
||||
Chunks_win(QObject *parent = nullptr);
|
||||
Chunks_win(const QStorageInfo &ioDevice, QObject *parent);
|
||||
|
||||
~Chunks_win();
|
||||
|
||||
bool setIODevice(const QStorageInfo &ioDevice);
|
||||
|
||||
// Getting data out of Chunks_win
|
||||
QByteArray data(qsizetype pos = 0, qsizetype maxSize = -1);
|
||||
bool write(QIODevice *iODevice, qsizetype pos = 0, qsizetype count = -1);
|
||||
|
||||
// Search API
|
||||
qsizetype indexOf(const QByteArray &ba, qsizetype from);
|
||||
qsizetype lastIndexOf(const QByteArray &ba, qsizetype from);
|
||||
|
||||
// Char manipulations
|
||||
bool insert(qsizetype pos, char b);
|
||||
bool overwrite(qsizetype pos, char b);
|
||||
bool removeAt(qsizetype pos);
|
||||
|
||||
// Utility functions
|
||||
char operator[](qsizetype pos);
|
||||
qsizetype pos();
|
||||
qsizetype size();
|
||||
|
||||
private:
|
||||
qsizetype getChunkIndex(qsizetype absPos);
|
||||
QIODevice *_ioDevice;
|
||||
qsizetype _pos;
|
||||
qsizetype _size;
|
||||
qsizetype CHUNK_SIZE;
|
||||
HANDLE _handle = INVALID_HANDLE_VALUE;
|
||||
QList<Chunk_win> _chunks;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // Chunks_win_H
|
|
@ -1,69 +0,0 @@
|
|||
#include "qwindriverbuffer.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
||||
#include "document/qstoragedevice.h"
|
||||
|
||||
/*
|
||||
* this file is implemented by wingsummer,
|
||||
* 使用 QHexEdit2 的代码来实现轻松访问上 GB 的文件,
|
||||
* 该类作者并未实现
|
||||
*/
|
||||
|
||||
QWinDriverBuffer::QWinDriverBuffer(QObject *parent) : QHexBuffer(parent) {
|
||||
_chunks = new Chunks_win(parent);
|
||||
}
|
||||
|
||||
QWinDriverBuffer::~QWinDriverBuffer() {}
|
||||
|
||||
uchar QWinDriverBuffer::at(qsizetype idx) {
|
||||
return uchar(_chunks->data(idx, 1)[0]);
|
||||
}
|
||||
|
||||
qsizetype QWinDriverBuffer::length() const { return _chunks->size(); }
|
||||
|
||||
void QWinDriverBuffer::insert(qsizetype offset, const QByteArray &data) {
|
||||
for (int i = 0; i < data.length(); i++) {
|
||||
_chunks->insert(offset + i, data.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
void QWinDriverBuffer::remove(qsizetype offset, qsizetype length) {
|
||||
for (uint i = 0; i < uint(length); i++) {
|
||||
_chunks->removeAt(offset + i);
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray QWinDriverBuffer::read(qsizetype offset, qsizetype length) {
|
||||
return _chunks->data(offset, length);
|
||||
}
|
||||
|
||||
bool QWinDriverBuffer::read(QIODevice *device) {
|
||||
if (device == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto driver = qobject_cast<QStorageDevice *>(device);
|
||||
if (driver == nullptr) {
|
||||
delete device;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto storage = driver->storage(); // only use name
|
||||
delete device;
|
||||
|
||||
_chunks->setIODevice(storage);
|
||||
return true;
|
||||
}
|
||||
|
||||
void QWinDriverBuffer::write(QIODevice *device) { _chunks->write(device); }
|
||||
|
||||
qsizetype QWinDriverBuffer::indexOf(const QByteArray &ba, qsizetype from) {
|
||||
return _chunks->indexOf(ba, from);
|
||||
}
|
||||
|
||||
qsizetype QWinDriverBuffer::lastIndexOf(const QByteArray &ba, qsizetype from) {
|
||||
return _chunks->lastIndexOf(ba, from);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,35 +0,0 @@
|
|||
#ifndef QWINDRIVERBUFFER_H
|
||||
#define QWINDRIVERBUFFER_H
|
||||
|
||||
#include <qnamespace.h>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
||||
#include "QHexEdit2/chunks_win.h"
|
||||
#include "qhexbuffer.h"
|
||||
#include <QFile>
|
||||
|
||||
class QWinDriverBuffer : public QHexBuffer {
|
||||
|
||||
public:
|
||||
explicit QWinDriverBuffer(QObject *parent = nullptr);
|
||||
~QWinDriverBuffer() override;
|
||||
uchar at(qsizetype idx) override;
|
||||
qsizetype length() const override;
|
||||
void insert(qsizetype offset, const QByteArray &data) override;
|
||||
void remove(qsizetype offset, qsizetype length) override;
|
||||
QByteArray read(qsizetype offset, qsizetype length) override;
|
||||
bool read(QIODevice *device) override;
|
||||
void write(QIODevice *device) override;
|
||||
|
||||
qsizetype indexOf(const QByteArray &ba, qsizetype from) override;
|
||||
qsizetype lastIndexOf(const QByteArray &ba, qsizetype from) override;
|
||||
|
||||
private:
|
||||
Chunks_win *_chunks;
|
||||
uchar *m_memory;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // QWINDRIVERBUFFER_H
|
|
@ -17,7 +17,6 @@
|
|||
#include <QFile>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include "buffer/qwindriverbuffer.h"
|
||||
#include "qstoragedevice.h"
|
||||
#endif
|
||||
|
||||
|
@ -558,7 +557,7 @@ QHexDocument *QHexDocument::fromStorageDriver(const QStorageInfo &storage,
|
|||
#ifdef Q_OS_WIN
|
||||
auto f = new QStorageDevice;
|
||||
f->setStorage(storage);
|
||||
auto hexbuffer = new QWinDriverBuffer();
|
||||
auto hexbuffer = new QFileBuffer();
|
||||
if (hexbuffer->read(f)) {
|
||||
return new QHexDocument(hexbuffer, readonly);
|
||||
} else {
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
#include "qstoragedevice.h"
|
||||
#include "qstorageinfo.h"
|
||||
|
||||
QStorageDevice::QStorageDevice() : QIODevice() {}
|
||||
#ifdef Q_OS_WIN
|
||||
|
||||
#include <QDebug>
|
||||
#include <memory>
|
||||
|
||||
QStorageDevice::QStorageDevice(QObject *parent)
|
||||
: QIODevice(parent), CHUNK_SIZE(0), _size(0) {
|
||||
_buffer.setTextModeEnabled(false);
|
||||
}
|
||||
|
||||
void QStorageDevice::setStorage(const QStorageInfo &storage) {
|
||||
_storage = storage;
|
||||
|
@ -9,6 +16,147 @@ void QStorageDevice::setStorage(const QStorageInfo &storage) {
|
|||
|
||||
QStorageInfo QStorageDevice::storage() const { return _storage; }
|
||||
|
||||
qint64 QStorageDevice::readData(char *data, qint64 maxlen) { return -1; }
|
||||
bool QStorageDevice::isSequential() const { return false; }
|
||||
|
||||
qint64 QStorageDevice::writeData(const char *data, qint64 len) { return -1; }
|
||||
bool QStorageDevice::open(OpenMode mode) {
|
||||
if (_buffer.isOpen()) {
|
||||
setErrorString(QStringLiteral("A Storage file is still opened"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mode == OpenModeFlag::ReadOnly || mode == OpenModeFlag::WriteOnly ||
|
||||
mode == OpenModeFlag::ReadWrite) {
|
||||
auto device = _storage.device();
|
||||
auto devicePrefix = QStringLiteral("\\\\.\\");
|
||||
QString dd = devicePrefix +
|
||||
device.mid(devicePrefix.length(),
|
||||
device.length() - devicePrefix.length() - 1);
|
||||
|
||||
// Open the physical drive using WinAPI
|
||||
auto hDevice =
|
||||
CreateFileW(reinterpret_cast<LPCWSTR>(dd.utf16()), GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
|
||||
OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, nullptr);
|
||||
|
||||
if (hDevice == INVALID_HANDLE_VALUE) {
|
||||
qWarning() << "Failed to open device:" << device;
|
||||
return false;
|
||||
}
|
||||
|
||||
DISK_GEOMETRY diskGeometry;
|
||||
DWORD bytesReturned;
|
||||
if (!DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
|
||||
&diskGeometry, sizeof(diskGeometry),
|
||||
&bytesReturned, NULL)) {
|
||||
CloseHandle(hDevice);
|
||||
return false;
|
||||
}
|
||||
|
||||
CloseHandle(hDevice);
|
||||
|
||||
this->CHUNK_SIZE = diskGeometry.BytesPerSector;
|
||||
|
||||
// dont use ioDevice.bytesTotal(),
|
||||
// because it's use GetDiskFreeSpaceEx API to get.
|
||||
// QFile::size() is zero
|
||||
_size = diskGeometry.Cylinders.QuadPart *
|
||||
diskGeometry.TracksPerCylinder * diskGeometry.SectorsPerTrack *
|
||||
diskGeometry.BytesPerSector;
|
||||
|
||||
if (!_buffer.open(mode)) {
|
||||
// _buffer.setFileName({});
|
||||
return false;
|
||||
}
|
||||
|
||||
return QIODevice::open(QIODevice::ReadOnly);
|
||||
} else {
|
||||
qWarning() << "Only OpenModeFlag::ReadOnly and OpenModeFlag::WriteOnly "
|
||||
"are supported";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void QStorageDevice::close() {
|
||||
if (_buffer.isOpen()) {
|
||||
_buffer.close();
|
||||
}
|
||||
QIODevice::close();
|
||||
}
|
||||
|
||||
qint64 QStorageDevice::size() const { return _size; }
|
||||
|
||||
bool QStorageDevice::seek(qint64 pos) {
|
||||
if (!_buffer.isOpen()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return QIODevice::seek(pos);
|
||||
}
|
||||
|
||||
bool QStorageDevice::canReadLine() const { return false; }
|
||||
|
||||
qint64 QStorageDevice::readData(char *data, qint64 maxlen) {
|
||||
if (!isOpen() || !maxlen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (maxlen > std::numeric_limits<DWORD>::max() ||
|
||||
(maxlen < 0 && _size > 1024 * 1024 * 1024)) {
|
||||
qWarning() << "Read a lot mount of data once is not allowed";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (maxlen < 0) {
|
||||
maxlen = _size;
|
||||
}
|
||||
|
||||
auto rp = std::div(this->pos(), CHUNK_SIZE);
|
||||
_buffer.seek(rp.quot * CHUNK_SIZE);
|
||||
|
||||
DWORD bytesRead = 0;
|
||||
|
||||
if (rp.rem) {
|
||||
auto buf = std::make_unique<char[]>(maxlen);
|
||||
_buffer.read(buf.get(), maxlen);
|
||||
std::memcpy(data, buf.get() + rp.rem, maxlen);
|
||||
} else {
|
||||
_buffer.read(data, maxlen);
|
||||
}
|
||||
|
||||
return maxlen;
|
||||
}
|
||||
|
||||
qint64 QStorageDevice::writeData(const char *data, qint64 len) {
|
||||
// qt will check writeable attr
|
||||
if (!isOpen()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure maxSize is a multiple of the sector size
|
||||
auto r = std::div(len, CHUNK_SIZE);
|
||||
auto alignLen = r.quot * CHUNK_SIZE;
|
||||
|
||||
auto rp = std::div(this->pos(), CHUNK_SIZE);
|
||||
_buffer.seek(rp.quot * CHUNK_SIZE);
|
||||
if (rp.rem) {
|
||||
}
|
||||
|
||||
_buffer.write(data, alignLen);
|
||||
|
||||
if (r.rem) {
|
||||
_buffer.seek(this->pos() + alignLen);
|
||||
auto buf = std::make_unique<char[]>(CHUNK_SIZE);
|
||||
_buffer.read(buf.get(), CHUNK_SIZE);
|
||||
DWORD byteWritten_A = 0;
|
||||
std::memcpy(buf.get(), data + alignLen, r.rem);
|
||||
|
||||
if (_buffer.write(buf.get(), CHUNK_SIZE)) {
|
||||
qWarning() << "Failed to write data to device";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,13 +1,19 @@
|
|||
#ifndef QSTORAGEDEVICE_H
|
||||
#define QSTORAGEDEVICE_H
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
||||
#include <QIODevice>
|
||||
#include <QStorageInfo>
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
class QStorageDevice : public QIODevice {
|
||||
Q_OBJECT
|
||||
public:
|
||||
QStorageDevice();
|
||||
QStorageDevice(QObject *parent = nullptr);
|
||||
|
||||
void setStorage(const QStorageInfo &storage);
|
||||
|
||||
|
@ -15,11 +21,24 @@ public:
|
|||
|
||||
private:
|
||||
QStorageInfo _storage;
|
||||
QFile _buffer;
|
||||
DWORD CHUNK_SIZE;
|
||||
qint64 _size;
|
||||
|
||||
// QIODevice interface
|
||||
public:
|
||||
virtual bool isSequential() const override;
|
||||
virtual bool open(OpenMode mode) override;
|
||||
virtual void close() override;
|
||||
virtual qint64 size() const override;
|
||||
virtual bool seek(qint64 pos) override;
|
||||
virtual bool canReadLine() const override;
|
||||
|
||||
protected:
|
||||
virtual qint64 readData(char *data, qint64 maxlen) override;
|
||||
virtual qint64 writeData(const char *data, qint64 len) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // QSTORAGEDEVICE_H
|
||||
|
|
|
@ -93,7 +93,7 @@ add_library(QCodeEditor2 STATIC ${SOURCE_FILES} ${DOCUMENT_SRC} ${WIDGETS_SRC}
|
|||
${QNFA_SRC} ${SNIPPET_SRC})
|
||||
|
||||
target_compile_definitions(QCodeEditor2 PUBLIC _QCODE_EDIT_BUILD_
|
||||
_QCODE_EDIT_EMBED_ _QCODE_MODEL_)
|
||||
_QCODE_EDIT_EMBED_)
|
||||
|
||||
target_include_directories(
|
||||
QCodeEditor2
|
||||
|
@ -106,5 +106,4 @@ target_include_directories(
|
|||
target_link_libraries(
|
||||
QCodeEditor2
|
||||
PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Gui
|
||||
Qt${QT_VERSION_MAJOR}::Xml Qt${QT_VERSION_MAJOR}::PrintSupport
|
||||
QCodeModel2)
|
||||
Qt${QT_VERSION_MAJOR}::Xml Qt${QT_VERSION_MAJOR}::PrintSupport)
|
||||
|
|
|
@ -26,10 +26,6 @@
|
|||
#include <QKeyEvent>
|
||||
#include <QTextCursor>
|
||||
|
||||
#ifdef _QCODE_MODEL_
|
||||
#include "qcodebuffer.h"
|
||||
#endif
|
||||
|
||||
/*!
|
||||
|
||||
*/
|
||||
|
@ -84,11 +80,6 @@ void QCodeCompletionEngine::removeTrigger(const QString &s) {
|
|||
|
||||
/*!
|
||||
|
||||
*/
|
||||
void QCodeCompletionEngine::setCodeModel(QCodeModel *m) { Q_UNUSED(m) }
|
||||
|
||||
/*!
|
||||
|
||||
*/
|
||||
QEditor *QCodeCompletionEngine::editor() const { return pEdit; }
|
||||
|
||||
|
@ -253,38 +244,9 @@ bool QCodeCompletionEngine::eventFilter(QObject *o, QEvent *e) {
|
|||
*/
|
||||
void QCodeCompletionEngine::complete(const QDocumentCursor &c,
|
||||
const QString &trigger) {
|
||||
#ifdef _QCODE_MODEL_
|
||||
// TODO :
|
||||
// * use a more efficient design by avoiding deep copy of the data
|
||||
// * only lex the requested part (stop at cursor or topmost frame required
|
||||
// for proper class hierarchy)
|
||||
|
||||
QDocumentCursor cc = c;
|
||||
cc.movePosition(1, QDocumentCursor::Start, QDocumentCursor::KeepAnchor);
|
||||
|
||||
// qDebug("%s", qPrintable(cc.selectedText()));
|
||||
|
||||
QCodeBuffer buffer(cc.selectedText());
|
||||
// QCodeBuffer buffer(c.document()->text());
|
||||
complete(&buffer, trigger);
|
||||
#else
|
||||
Q_UNUSED(c)
|
||||
Q_UNUSED(trigger)
|
||||
qWarning("From complete(QDocumentCursor, QString)");
|
||||
qWarning("QCodeCompletionEngine is not self-sufficient : subclasses should "
|
||||
"reimplement at least one of the complete() method...");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
\brief Overloaded completion callback
|
||||
*/
|
||||
void QCodeCompletionEngine::complete(QCodeStream *s, const QString &trigger) {
|
||||
Q_UNUSED(s)
|
||||
Q_UNUSED(trigger)
|
||||
|
||||
qWarning("From complete(QCodeStream*, QString)");
|
||||
qWarning("QCodeCompletionEngine is not self-sufficient : subclasses should"
|
||||
"reimplement at least on of the complete() method...");
|
||||
}
|
||||
|
|
|
@ -57,8 +57,6 @@ public:
|
|||
void addTrigger(const QString &s);
|
||||
void removeTrigger(const QString &s);
|
||||
|
||||
virtual void setCodeModel(QCodeModel *m);
|
||||
|
||||
virtual void retranslate();
|
||||
|
||||
signals:
|
||||
|
@ -74,7 +72,6 @@ protected:
|
|||
virtual void run();
|
||||
virtual bool eventFilter(QObject *o, QEvent *e);
|
||||
|
||||
virtual void complete(QCodeStream *s, const QString &trigger);
|
||||
virtual void complete(const QDocumentCursor &c, const QString &trigger);
|
||||
|
||||
private:
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
cmake_minimum_required(VERSION 3.6)
|
||||
project(QCodeModel2 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Gui)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Gui)
|
||||
|
||||
add_definitions(-D_QCODE_MODEL_BUILD_STATIC_)
|
||||
|
||||
add_library(
|
||||
QCodeModel2 STATIC
|
||||
qcm-config.h
|
||||
qcodemodel.h
|
||||
qcodeproxymodel.h
|
||||
qcodenode.h
|
||||
qcodenodepool.h
|
||||
qsourcecodewatcher.h
|
||||
qcodeview.h
|
||||
qcodeserializer.h
|
||||
qcodestream.h
|
||||
qcodedevice.h
|
||||
qcodebuffer.h
|
||||
qcodelexer.h
|
||||
qcodeparser.h
|
||||
qcodeloader.h
|
||||
qcodemodel.cpp
|
||||
qcodeproxymodel.cpp
|
||||
qcodenode.cpp
|
||||
qcodenodepool.cpp
|
||||
qsourcecodewatcher.cpp
|
||||
qcodeview.cpp
|
||||
qcodeserializer.cpp
|
||||
qcodestream.cpp
|
||||
qcodedevice.cpp
|
||||
qcodebuffer.cpp
|
||||
qcodelexer.cpp
|
||||
qcodeparser.cpp
|
||||
qcodeloader.cpp
|
||||
resources.qrc)
|
||||
|
||||
target_include_directories(QCodeModel2 PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
target_link_libraries(QCodeModel2 PRIVATE Qt${QT_VERSION_MAJOR}::Widgets
|
||||
Qt${QT_VERSION_MAJOR}::Gui)
|
||||
|
||||
target_compile_definitions(QCodeModel2 PUBLIC -D_QCODE_MODEL_BUILD_STATIC_)
|
|
@ -1,84 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
|
||||
**
|
||||
** This file is part of the Edyuk project <http://edyuk.org>
|
||||
**
|
||||
** This file may be used under the terms of the GNU General Public License
|
||||
** version 3 as published by the Free Software Foundation and appearing in the
|
||||
** file GPL.txt included in the packaging of this file.
|
||||
**
|
||||
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qcodebuffer.h"
|
||||
|
||||
/*!
|
||||
\file qcodebuffer.cpp
|
||||
\brief Implementation of the QCodebuffer class.
|
||||
*/
|
||||
|
||||
#include <QString>
|
||||
|
||||
/*!
|
||||
\class QCodebuffer
|
||||
\brief Code stream that operates on a static string buffer
|
||||
*/
|
||||
|
||||
/*!
|
||||
\brief Constructs a code buffer from an Unicode string
|
||||
|
||||
\note The string is converted to local8Bit()
|
||||
*/
|
||||
QCodeBuffer::QCodeBuffer(const QString &s)
|
||||
: QCodeStream(), iPos(0), sBuffer(s.toLocal8Bit()) {
|
||||
sBuffer.replace("\r\n", "\n");
|
||||
sBuffer.replace("\r", "\n");
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Constructs a code buffer from a byte array
|
||||
*/
|
||||
QCodeBuffer::QCodeBuffer(const QByteArray &s)
|
||||
: QCodeStream(), iPos(0), sBuffer(s) {
|
||||
sBuffer.replace("\r\n", "\n");
|
||||
sBuffer.replace("\r", "\n");
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief return the char pointed to by the internal pointer and update the
|
||||
pointer
|
||||
*/
|
||||
char QCodeBuffer::getChar() {
|
||||
if (iPos < sBuffer.length())
|
||||
return sBuffer.at(iPos++);
|
||||
else
|
||||
return '\0';
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Move back by one character
|
||||
*/
|
||||
void QCodeBuffer::ungetChar(char) {
|
||||
if (iPos > 0)
|
||||
--iPos;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return the content of the current line
|
||||
*/
|
||||
QByteArray QCodeBuffer::readLine() {
|
||||
char c;
|
||||
QByteArray s;
|
||||
|
||||
while ((c = getChar())) {
|
||||
if (c == '\n')
|
||||
break;
|
||||
|
||||
s += c;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
|
||||
**
|
||||
** This file is part of the Edyuk project <http://edyuk.org>
|
||||
**
|
||||
** This file may be used under the terms of the GNU General Public License
|
||||
** version 3 as published by the Free Software Foundation and appearing in the
|
||||
** file GPL.txt included in the packaging of this file.
|
||||
**
|
||||
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qcodedevice.h"
|
||||
|
||||
/*!
|
||||
\file qcodedevice.cpp
|
||||
\brief Implementation of the QcodeDevice class.
|
||||
*/
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QStringList>
|
||||
|
||||
QString stripped(const QString &s) { return QDir::cleanPath(s); }
|
||||
|
||||
QString makeAbsolute(const QString &rel, const QString &abs) {
|
||||
if (QFileInfo(rel).isAbsolute())
|
||||
return stripped(rel);
|
||||
|
||||
QFileInfo info(abs);
|
||||
QStringList ref, mov = QString(rel).replace("\\", "/").split("/");
|
||||
ref = (info.isFile() ? info.absolutePath() : info.absoluteFilePath())
|
||||
.replace("\\", "/")
|
||||
.split("/");
|
||||
|
||||
foreach (QString s, mov) {
|
||||
if (s == ".")
|
||||
continue;
|
||||
|
||||
if (s == "..") {
|
||||
if (ref.count())
|
||||
ref.removeLast();
|
||||
} else {
|
||||
ref << s;
|
||||
}
|
||||
}
|
||||
|
||||
return stripped(ref.join("/"));
|
||||
}
|
||||
|
||||
/*!
|
||||
\class QCodeDevice
|
||||
\brief Code stream that operates on local files
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
||||
*/
|
||||
QCodeDevice::QCodeDevice(const QString &f) : m_pos(0), m_beg(0) {
|
||||
setContextFile(f);
|
||||
|
||||
QFile file(f);
|
||||
|
||||
if (file.open(QFile::ReadOnly | QFile::Text)) {
|
||||
buffer = file.readAll();
|
||||
} else {
|
||||
qWarning("Device not found : %s", qPrintable(f));
|
||||
}
|
||||
}
|
||||
|
||||
bool QCodeDevice::tryFetchOtherContext(const QString &f) {
|
||||
m_pos = 0;
|
||||
m_beg = 0;
|
||||
buffer.clear();
|
||||
|
||||
QString fn = makeAbsolute(f, contextFile());
|
||||
QFile file(fn);
|
||||
|
||||
if (!file.open(QFile::ReadOnly | QFile::Text)) {
|
||||
qWarning("Unable to read %s", qPrintable(fn));
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer = file.readAll();
|
||||
setContextFile(fn);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
char QCodeDevice::getChar() {
|
||||
return (m_pos < buffer.length()) ? buffer.at(m_pos++) : 0;
|
||||
}
|
||||
|
||||
void QCodeDevice::ungetChar(char) {
|
||||
if (m_beg >= m_pos)
|
||||
return;
|
||||
|
||||
--m_pos;
|
||||
}
|
||||
|
||||
QByteArray QCodeDevice::readLine() {
|
||||
QByteArray b = buffer.mid(buffer.indexOf('\n', m_pos) - m_pos);
|
||||
|
||||
m_pos += b.length();
|
||||
return b;
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
|
||||
**
|
||||
** This file is part of the Edyuk project <http://edyuk.org>
|
||||
**
|
||||
** This file may be used under the terms of the GNU General Public License
|
||||
** version 3 as published by the Free Software Foundation and appearing in the
|
||||
** file GPL.txt included in the packaging of this file.
|
||||
**
|
||||
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _QCODE_DEVICE_H_
|
||||
#define _QCODE_DEVICE_H_
|
||||
|
||||
#include "qcodestream.h"
|
||||
|
||||
/*!
|
||||
\file qcodedevice.h
|
||||
\brief Definition of the QCodeDevice class.
|
||||
*/
|
||||
|
||||
class QIODevice;
|
||||
|
||||
class QCM_EXPORT QCodeDevice : public QCodeStream {
|
||||
public:
|
||||
QCodeDevice(const QString &f);
|
||||
|
||||
virtual char getChar();
|
||||
virtual void ungetChar(char c);
|
||||
|
||||
virtual QByteArray readLine();
|
||||
|
||||
virtual bool tryFetchOtherContext(const QString &f);
|
||||
|
||||
private:
|
||||
int m_pos, m_beg;
|
||||
QByteArray buffer;
|
||||
};
|
||||
|
||||
#endif // _QCODE_DEVICE_H_
|
|
@ -1,44 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
|
||||
**
|
||||
** This file is part of the Edyuk project <http://edyuk.org>
|
||||
**
|
||||
** This file may be used under the terms of the GNU General Public License
|
||||
** version 3 as published by the Free Software Foundation and appearing in the
|
||||
** file GPL.txt included in the packaging of this file.
|
||||
**
|
||||
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qcodelexer.h"
|
||||
|
||||
/*!
|
||||
\file qcodelexer.cpp
|
||||
\brief Implementation of the QCodeLexer class.
|
||||
*/
|
||||
|
||||
#include "qcodestream.h"
|
||||
|
||||
/*!
|
||||
\class QCodeLexer
|
||||
\brief Base class for code lexers
|
||||
*/
|
||||
|
||||
QCodeLexer::QCodeLexer() {}
|
||||
|
||||
QCodeLexer::QCodeLexer(QCodeStream *s) : input(s) {}
|
||||
|
||||
QCodeLexer::~QCodeLexer() {}
|
||||
|
||||
void QCodeLexer::setInput(QCodeStream *s, LexMode m) {
|
||||
Q_UNUSED(m)
|
||||
|
||||
input = s;
|
||||
}
|
||||
|
||||
QString QCodeLexer::contextFile() const {
|
||||
return input ? input->contextFile() : QString();
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
|
||||
**
|
||||
** This file is part of the Edyuk project <http://edyuk.org>
|
||||
**
|
||||
** This file may be used under the terms of the GNU General Public License
|
||||
** version 3 as published by the Free Software Foundation and appearing in the
|
||||
** file GPL.txt included in the packaging of this file.
|
||||
**
|
||||
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _QCODE_LEXER_H_
|
||||
#define _QCODE_LEXER_H_
|
||||
|
||||
#include "qcm-config.h"
|
||||
|
||||
/*!
|
||||
\file qcodelexer.h
|
||||
\brief Definition of the QCodeLexer class.
|
||||
*/
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
|
||||
class QCodeStream;
|
||||
|
||||
class QCM_EXPORT QCodeLexer {
|
||||
public:
|
||||
enum LexMode { Normal, KeepLineSeparators };
|
||||
|
||||
QCodeLexer();
|
||||
QCodeLexer(QCodeStream *s);
|
||||
virtual ~QCodeLexer();
|
||||
|
||||
virtual void setInput(QCodeStream *s, LexMode m = Normal);
|
||||
|
||||
virtual QToken nextToken() = 0;
|
||||
virtual QToken previousToken() = 0;
|
||||
|
||||
virtual QTokenList tokens() = 0;
|
||||
|
||||
virtual int lineForToken(int tokenId, int minLine = 0) const = 0;
|
||||
|
||||
QString contextFile() const;
|
||||
|
||||
protected:
|
||||
QCodeStream *input;
|
||||
};
|
||||
|
||||
#endif // _QCODE_LEXER_H_
|
|
@ -1,238 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
|
||||
**
|
||||
** This file is part of the Edyuk project <http://edyuk.org>
|
||||
**
|
||||
** This file may be used under the terms of the GNU General Public License
|
||||
** version 3 as published by the Free Software Foundation and appearing in the
|
||||
** file GPL.txt included in the packaging of this file.
|
||||
**
|
||||
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qcodeloader.h"
|
||||
|
||||
/*!
|
||||
\file qcodeloader.cpp
|
||||
\brief Implementation of the QCodeLoader class.
|
||||
*/
|
||||
|
||||
#include "qcodemodel.h"
|
||||
#include "qcodenode.h"
|
||||
#include "qcodeparser.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QFileInfo>
|
||||
#include <QTimer>
|
||||
|
||||
/*!
|
||||
\class QCodeLoader
|
||||
\brief A parsers management class
|
||||
|
||||
QCodeLoader owns a collection of QCodeParser object
|
||||
and request them to generate project trees from files.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\brief ctor
|
||||
*/
|
||||
QCodeLoader::QCodeLoader(QObject *p) : QThread(p) {}
|
||||
|
||||
/*!
|
||||
\brief dtor
|
||||
*/
|
||||
QCodeLoader::~QCodeLoader() {
|
||||
// qDeleteAll(m_parsers);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Add a parser to the collection
|
||||
|
||||
\warning The parser is not taken over. It won't get deleted
|
||||
from QCodeLoader dtor.
|
||||
*/
|
||||
void QCodeLoader::addParser(QCodeParser *p) {
|
||||
if (!m_parsers.contains(p))
|
||||
m_parsers << p;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Remove a parser from the collection
|
||||
|
||||
\warning The parser is NOT deleted.
|
||||
*/
|
||||
void QCodeLoader::removeParser(QCodeParser *p) { m_parsers.removeAll(p); }
|
||||
|
||||
/*!
|
||||
\brief Update the content of a given node to
|
||||
*/
|
||||
void QCodeLoader::update(QCodeNode *group, const QString &file) {
|
||||
if (!group)
|
||||
return;
|
||||
|
||||
if (!QFile::exists(file)) {
|
||||
QStack<QCodeNode *> l;
|
||||
|
||||
l.push(group);
|
||||
|
||||
while (l.count()) {
|
||||
QCodeNode *n = l.pop();
|
||||
|
||||
if (n->context() == file) {
|
||||
QCodeNode *p = n->parent;
|
||||
|
||||
n->detach();
|
||||
delete n;
|
||||
|
||||
while (p && p->children.isEmpty() && (p != group)) {
|
||||
n = p;
|
||||
p = p->parent;
|
||||
|
||||
n->detach();
|
||||
delete n;
|
||||
}
|
||||
} else {
|
||||
foreach (QCodeNode *c, n->children)
|
||||
l.push(c);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// qDebug("update(%s, %s)", group->role(QCodeNode::Name).constData(),
|
||||
// qPrintable(file));
|
||||
|
||||
foreach (QCodeParser *p, m_parsers) {
|
||||
if (!p->canParse(file))
|
||||
continue;
|
||||
|
||||
QCodeNode *ln = 0;
|
||||
QByteArray roles("l@");
|
||||
roles += p->language().toLocal8Bit();
|
||||
|
||||
foreach (QCodeNode *c, group->children) {
|
||||
if (c->roles == roles) {
|
||||
ln = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ln) {
|
||||
ln = p->getNode();
|
||||
ln->roles = roles;
|
||||
ln->attach(group);
|
||||
}
|
||||
|
||||
p->update(ln, file);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Attempt to open load class hierarchy from a set of files
|
||||
\return true on success
|
||||
\param group Name of the toplevel group which will get created on
|
||||
success \param files Files to load \param dest Destination model
|
||||
*/
|
||||
bool QCodeLoader::load(const QString &group, QStringList files,
|
||||
QCodeModel *dest) {
|
||||
// qDebug("load(%s, (%s), %p)", qPrintable(group), qPrintable(files.join(",
|
||||
// ")), dest);
|
||||
bool done = false;
|
||||
|
||||
QCodeNode *g = new QCodeNode;
|
||||
g->roles = QByteArray("g@") + QFileInfo(group).fileName().toLocal8Bit() +
|
||||
"@" + group.toLocal8Bit();
|
||||
dest->appendTopLevelNode(g);
|
||||
|
||||
foreach (QCodeParser *p, m_parsers) {
|
||||
QStringList lf;
|
||||
|
||||
foreach (QString fn, files)
|
||||
if (p->canParse(fn))
|
||||
lf << fn;
|
||||
|
||||
if (lf.isEmpty())
|
||||
continue;
|
||||
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!done)
|
||||
return false;
|
||||
|
||||
OpenRequest r;
|
||||
r.files = files;
|
||||
r.group = group;
|
||||
r.model = dest;
|
||||
|
||||
m_request.enqueue(r);
|
||||
|
||||
if (!isRunning())
|
||||
QTimer::singleShot(0, this, SLOT(start()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
void QCodeLoader::run() {
|
||||
QTimer::singleShot(0, this, SLOT(process()));
|
||||
|
||||
exec();
|
||||
|
||||
// process();
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
void QCodeLoader::process() {
|
||||
while (m_request.count()) {
|
||||
OpenRequest r = m_request.dequeue();
|
||||
|
||||
bool done = false;
|
||||
|
||||
QCodeNode *g;
|
||||
QList<QCodeNode *> gl = r.model->topLevelNodes();
|
||||
|
||||
foreach (g, gl) {
|
||||
if (g->role(QCodeNode::Context) != r.group)
|
||||
continue;
|
||||
|
||||
foreach (QCodeParser *p, m_parsers) {
|
||||
QStringList lf;
|
||||
|
||||
foreach (QString fn, r.files)
|
||||
if (p->canParse(fn))
|
||||
lf << fn;
|
||||
|
||||
if (lf.isEmpty())
|
||||
continue;
|
||||
|
||||
done = true;
|
||||
|
||||
QCodeNode *ln = p->getNode();
|
||||
ln->roles = QByteArray("l@") + p->language().toLocal8Bit();
|
||||
|
||||
foreach (QString fn, lf) {
|
||||
r.files.removeAll(fn);
|
||||
|
||||
p->update(ln, fn);
|
||||
}
|
||||
|
||||
ln->attach(g);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
quit();
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
|
||||
**
|
||||
** This file is part of the Edyuk project <http://edyuk.org>
|
||||
**
|
||||
** This file may be used under the terms of the GNU General Public License
|
||||
** version 3 as published by the Free Software Foundation and appearing in the
|
||||
** file GPL.txt included in the packaging of this file.
|
||||
**
|
||||
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _QCODE_LOADER_H_
|
||||
#define _QCODE_LOADER_H_
|
||||
|
||||
#include "qcm-config.h"
|
||||
|
||||
/*!
|
||||
\file qcodeloader.h
|
||||
\brief Definition of the QCodeLoader class.
|
||||
*/
|
||||
|
||||
#include <QList>
|
||||
#include <QQueue>
|
||||
#include <QStringList>
|
||||
#include <QThread>
|
||||
|
||||
struct QCodeNode;
|
||||
class QCodeModel;
|
||||
class QCodeParser;
|
||||
|
||||
class QCM_EXPORT QCodeLoader : public QThread {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QCodeLoader(QObject *p = nullptr);
|
||||
virtual ~QCodeLoader();
|
||||
|
||||
public slots:
|
||||
void update(QCodeNode *group, const QString &file);
|
||||
bool load(const QString &group, QStringList files, QCodeModel *dest);
|
||||
|
||||
void addParser(QCodeParser *p);
|
||||
void removeParser(QCodeParser *p);
|
||||
|
||||
protected:
|
||||
virtual void run();
|
||||
|
||||
protected slots:
|
||||
virtual void process();
|
||||
|
||||
private:
|
||||
struct OpenRequest {
|
||||
QString group;
|
||||
QStringList files;
|
||||
QCodeModel *model;
|
||||
};
|
||||
|
||||
QQueue<OpenRequest> m_request;
|
||||
QList<QCodeParser *> m_parsers;
|
||||
};
|
||||
|
||||
#endif // !_QCODE_LOADER_H_
|
|
@ -1,150 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
|
||||
**
|
||||
** This file is part of the Edyuk project <http://edyuk.org>
|
||||
**
|
||||
** This file may be used under the terms of the GNU General Public License
|
||||
** version 3 as published by the Free Software Foundation and appearing in the
|
||||
** file GPL.txt included in the packaging of this file.
|
||||
**
|
||||
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qcodeparser.h"
|
||||
|
||||
/*!
|
||||
\file qcodeparser.cpp
|
||||
\brief Implementation of the QCodeParser class.
|
||||
*/
|
||||
|
||||
#include "qcodedevice.h"
|
||||
#include "qcodelexer.h"
|
||||
#include "qcodemodel.h"
|
||||
#include "qcodenode.h"
|
||||
#include "qcodenodepool.h"
|
||||
#include "qcodestream.h"
|
||||
|
||||
#include "qsourcecodewatcher.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QTime>
|
||||
|
||||
/*!
|
||||
\class QCodeParser
|
||||
\brief Base class for code parsers
|
||||
|
||||
\see QCodeLexer
|
||||
\see QCodeLoader
|
||||
*/
|
||||
|
||||
/*!
|
||||
\brief ctor
|
||||
*/
|
||||
QCodeParser::QCodeParser() : m_pool(0) {}
|
||||
|
||||
/*!
|
||||
\brief dtor
|
||||
*/
|
||||
QCodeParser::~QCodeParser() {}
|
||||
|
||||
/*!
|
||||
\return The node pool to which this parser has access
|
||||
*/
|
||||
QCodeNodePool *QCodeParser::nodePool() const { return m_pool; }
|
||||
|
||||
/*!
|
||||
\brief Set the node pool from which the parser should
|
||||
allocate its node (a null pointer causes heap allocation
|
||||
to be used all the time.)
|
||||
*/
|
||||
void QCodeParser::setNodePool(QCodeNodePool *p) { m_pool = p; }
|
||||
|
||||
/*!
|
||||
\return A valid QCodeNode object
|
||||
If the parser has access to a nodePool(), it allocates
|
||||
the new node from it, otherwise it allocates it on heap.
|
||||
*/
|
||||
QCodeNode *QCodeParser::getNode() {
|
||||
return m_pool ? m_pool->alloc() : new QCodeNode;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Parse a single file and construct code tree
|
||||
\param f file to parse
|
||||
\return The group node (named after the file) containing parsing result
|
||||
*/
|
||||
QCodeNode *QCodeParser::parse(const QString &f) {
|
||||
if (!QFile::exists(f) || !QFileInfo(f).isReadable())
|
||||
return 0;
|
||||
|
||||
QCodeDevice stream(f);
|
||||
QCodeNode *node = getNode();
|
||||
QCodeLexer *lex = lexer(&stream);
|
||||
|
||||
node->roles = QByteArray("g@") + f.toLocal8Bit() + "@" + f.toLocal8Bit();
|
||||
|
||||
update(node, lex);
|
||||
|
||||
delete lex;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Update the content of a node according to the content of a file
|
||||
\param n node to update (most probably a group...)
|
||||
\param file file from which to extract code hierarchy
|
||||
*/
|
||||
void QCodeParser::update(QCodeNode *n, const QString &file) {
|
||||
if (!QFile::exists(file) || !QFileInfo(file).isReadable()) {
|
||||
QStack<QCodeNode *> l;
|
||||
|
||||
l.push(n);
|
||||
|
||||
while (l.count()) {
|
||||
QCodeNode *tn = l.pop();
|
||||
|
||||
if (tn->context() == file) {
|
||||
QCodeNode *p = tn->parent;
|
||||
|
||||
tn->detach();
|
||||
delete tn;
|
||||
|
||||
while (p && p->children.isEmpty() &&
|
||||
(p->type() != QCodeNode::Group)) {
|
||||
tn = p;
|
||||
p = p->parent;
|
||||
|
||||
tn->detach();
|
||||
delete tn;
|
||||
}
|
||||
} else {
|
||||
foreach (QCodeNode *c, tn->children)
|
||||
l.push(c);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// qDebug("updating %s in %s", qPrintable(file),
|
||||
// n->role(QCodeNode::Name).constData());
|
||||
|
||||
QCodeDevice stream(file);
|
||||
|
||||
QSourceCodeWatcher *w = QSourceCodeWatcher::watcher(n, this);
|
||||
|
||||
if (w && !w->files().contains(file))
|
||||
w->addPath(file);
|
||||
|
||||
QCodeLexer *lex = lexer(&stream);
|
||||
|
||||
update(n, lex);
|
||||
|
||||
delete lex;
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
|
||||
**
|
||||
** This file is part of the Edyuk project <http://edyuk.org>
|
||||
**
|
||||
** This file may be used under the terms of the GNU General Public License
|
||||
** version 3 as published by the Free Software Foundation and appearing in the
|
||||
** file GPL.txt included in the packaging of this file.
|
||||
**
|
||||
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _QCODE_PARSER_H_
|
||||
#define _QCODE_PARSER_H_
|
||||
|
||||
#include "qcm-config.h"
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
struct QCodeNode;
|
||||
class QCodeModel;
|
||||
class QCodeLexer;
|
||||
class QCodeStream;
|
||||
class QCodeNodePool;
|
||||
|
||||
class QCM_EXPORT QCodeParser {
|
||||
friend class QCodeLoader;
|
||||
|
||||
public:
|
||||
QCodeParser();
|
||||
virtual ~QCodeParser();
|
||||
|
||||
virtual QString language() const = 0;
|
||||
virtual bool canParse(const QString &fn) const = 0;
|
||||
|
||||
QCodeNodePool *nodePool() const;
|
||||
void setNodePool(QCodeNodePool *p);
|
||||
|
||||
QCodeNode *parse(const QString &f);
|
||||
|
||||
virtual QCodeLexer *lexer(QCodeStream *s) = 0;
|
||||
|
||||
virtual void update(QCodeNode *n, const QString &file);
|
||||
virtual void update(QCodeNode *n, QCodeLexer *l, bool check = true) = 0;
|
||||
|
||||
protected:
|
||||
QCodeNode *getNode();
|
||||
|
||||
private:
|
||||
QCodeNodePool *m_pool;
|
||||
};
|
||||
|
||||
#endif // !_QCODE_PARSER_H_
|
|
@ -1,40 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
|
||||
**
|
||||
** This file is part of the Edyuk project <http://edyuk.org>
|
||||
**
|
||||
** This file may be used under the terms of the GNU General Public License
|
||||
** version 3 as published by the Free Software Foundation and appearing in the
|
||||
** file GPL.txt included in the packaging of this file.
|
||||
**
|
||||
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _QCODE_PROXY_MODEL_H_
|
||||
#define _QCODE_PROXY_MODEL_H_
|
||||
|
||||
#include "qcm-config.h"
|
||||
|
||||
/*!
|
||||
\file qcodeproxymodel.h
|
||||
\brief Definition of the QCodeProxyModel class.
|
||||
*/
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
class QCM_EXPORT QCodeProxyModel : public QSortFilterProxyModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QCodeProxyModel(QObject *p = nullptr);
|
||||
virtual ~QCodeProxyModel();
|
||||
|
||||
protected:
|
||||
virtual bool lessThan(const QModelIndex &left,
|
||||
const QModelIndex &right) const;
|
||||
};
|
||||
|
||||
#endif // !_QCODE_PROXY_MODEL_H_
|
|
@ -1,38 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
|
||||
**
|
||||
** This file is part of the Edyuk project <http://edyuk.org>
|
||||
**
|
||||
** This file may be used under the terms of the GNU General Public License
|
||||
** version 3 as published by the Free Software Foundation and appearing in the
|
||||
** file GPL.txt included in the packaging of this file.
|
||||
**
|
||||
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qcodestream.h"
|
||||
|
||||
/*!
|
||||
\file qcodestream.cpp
|
||||
\brief Implementation of the QCodeStream class.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QCodeStream
|
||||
\brief Base class for code input streams
|
||||
*/
|
||||
|
||||
QString QCodeStream::contextFile() const {
|
||||
// qDebug(" <= context query : %s", qPrintable(sContext));
|
||||
return sContext;
|
||||
}
|
||||
|
||||
void QCodeStream::setContextFile(const QString &f) {
|
||||
// qDebug(" => context switch : %s", qPrintable(f));
|
||||
sContext = f;
|
||||
}
|
||||
|
||||
bool QCodeStream::tryFetchOtherContext(const QString &) { return false; }
|
|
@ -1,48 +0,0 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
|
||||
**
|
||||
** This file is part of the Edyuk project <http://edyuk.org>
|
||||
**
|
||||
** This file may be used under the terms of the GNU General Public License
|
||||
** version 3 as published by the Free Software Foundation and appearing in the
|
||||
** file GPL.txt included in the packaging of this file.
|
||||
**
|
||||
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _QCODE_STREAM_H_
|
||||
#define _QCODE_STREAM_H_
|
||||
|
||||
#include "qcm-config.h"
|
||||
|
||||
/*!
|
||||
\file qcodestream.h
|
||||
\brief Definition of the QCodeStream class.
|
||||
*/
|
||||
|
||||
#include <QString>
|
||||
|
||||
class QByteArray;
|
||||
|
||||
class QCM_EXPORT QCodeStream {
|
||||
public:
|
||||
virtual ~QCodeStream() {}
|
||||
|
||||
virtual char getChar() = 0;
|
||||
virtual void ungetChar(char c) = 0;
|
||||
|
||||
virtual QByteArray readLine() = 0;
|
||||
|
||||
virtual QString contextFile() const;
|
||||
virtual void setContextFile(const QString &f);
|
||||
|
||||
virtual bool tryFetchOtherContext(const QString &f);
|
||||
|
||||
private:
|
||||
QString sContext;
|
||||
};
|
||||
|
||||
#endif // !_QCODE_STREAM_H_
|
|
@ -1,20 +0,0 @@
|
|||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>completion/CVclass.png</file>
|
||||
<file>completion/CVenum.png</file>
|
||||
<file>completion/CVenumerator.png</file>
|
||||
<file>completion/CVglobal_meth.png</file>
|
||||
<file>completion/CVglobal_var.png</file>
|
||||
<file>completion/CVnamespace.png</file>
|
||||
<file>completion/CVpackage_meth.png</file>
|
||||
<file>completion/CVpackage_var.png</file>
|
||||
<file>completion/CVprivate_meth.png</file>
|
||||
<file>completion/CVprivate_var.png</file>
|
||||
<file>completion/CVprotected_meth.png</file>
|
||||
<file>completion/CVprotected_var.png</file>
|
||||
<file>completion/CVpublic_meth.png</file>
|
||||
<file>completion/CVpublic_var.png</file>
|
||||
<file>completion/CVtypedef.png</file>
|
||||
<file>completion/classnew.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -10,10 +10,12 @@ set(CMAKE_CXX_STANDARD 17)
|
|||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(PROJECT_VERSION 1.0.0)
|
||||
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Network Concurrent
|
||||
PrintSupport LinguistTools)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED
|
||||
COMPONENTS Widgets Network Concurrent PrintSupport LinguistTools)
|
||||
find_package(
|
||||
QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Network Concurrent
|
||||
PrintSupport Xml LinguistTools)
|
||||
find_package(
|
||||
Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Network Concurrent
|
||||
PrintSupport Xml LinguistTools)
|
||||
|
||||
add_definitions(-DWINGHEX_VERSION="${PROJECT_VERSION}"
|
||||
-DAPP_ORG="WingCloudStudio" -DAPP_NAME="${PROJECT_NAME}")
|
||||
|
@ -58,7 +60,6 @@ option(BUILD_STATIC "Build the static library" TRUE)
|
|||
|
||||
add_subdirectory(3rdparty/QHexView)
|
||||
add_subdirectory(3rdparty/qcodeedit2)
|
||||
add_subdirectory(3rdparty/qcodemodel2)
|
||||
add_subdirectory(3rdparty/Qt-Advanced-Docking-System)
|
||||
add_subdirectory(3rdparty/AngelScript/sdk/angelscript/projects/cmake)
|
||||
add_subdirectory(3rdparty/QConsoleWidget)
|
||||
|
@ -179,7 +180,6 @@ set(CLASS_SRC
|
|||
src/class/skinmanager.h
|
||||
src/class/workspacemanager.cpp
|
||||
src/class/workspacemanager.h
|
||||
src/class/setting.h
|
||||
src/class/eventfilter.h
|
||||
src/class/qkeysequences.h
|
||||
src/class/qkeysequences.cpp
|
||||
|
@ -218,8 +218,6 @@ set(CLASS_SRC
|
|||
src/class/ascompletion.h
|
||||
src/class/asbuilder.h
|
||||
src/class/asbuilder.cpp
|
||||
src/class/qaslexer.cpp
|
||||
src/class/qaslexer.h
|
||||
src/class/qasparser.cpp
|
||||
src/class/qasparser.h
|
||||
src/class/qdocumentsearch.cpp
|
||||
|
@ -304,10 +302,25 @@ set(CODEEDIT_WIDGET
|
|||
src/qcodeeditwidget/qformatconfig.cpp
|
||||
src/qcodeeditwidget/qformatconfig.ui)
|
||||
|
||||
set(PLUGIN_SRC
|
||||
src/plugin/iwingplugin.h src/plugin/pluginsystem.cpp
|
||||
src/plugin/pluginsystem.h src/plugin/settingpage.h
|
||||
src/plugin/settingpage.cpp)
|
||||
set(CODE_MODEL
|
||||
src/codemodel/qcm-config.h
|
||||
src/codemodel/qcodemodel.cpp
|
||||
src/codemodel/qcodemodel.h
|
||||
src/codemodel/qcodenode.cpp
|
||||
src/codemodel/qcodenode.h
|
||||
src/codemodel/qcodenodepool.cpp
|
||||
src/codemodel/qcodenodepool.h
|
||||
src/codemodel/qcodeproxymodel.cpp
|
||||
src/codemodel/qcodeproxymodel.h
|
||||
src/codemodel/qcodeserializer.cpp
|
||||
src/codemodel/qcodeserializer.h
|
||||
src/codemodel/qcodeview.cpp
|
||||
src/codemodel/qcodeview.h
|
||||
src/codemodel/qsourcecodewatcher.cpp
|
||||
src/codemodel/qsourcecodewatcher.h)
|
||||
|
||||
set(PLUGIN_SRC src/plugin/iwingplugin.h src/plugin/pluginsystem.cpp
|
||||
src/plugin/pluginsystem.h src/plugin/settingpage.h)
|
||||
|
||||
# localization support
|
||||
file(
|
||||
|
@ -400,6 +413,7 @@ set(PROJECT_SOURCES
|
|||
src/dbghelper.h
|
||||
${QPATHEDIT_SRC}
|
||||
${WIDGET_FRAME_SRC}
|
||||
${CODE_MODEL}
|
||||
${RIBBON_SRC}
|
||||
${CLASS_SRC}
|
||||
${MODEL_SRC}
|
||||
|
@ -454,12 +468,12 @@ if(WINGHEX_USE_FRAMELESS)
|
|||
Qt${QT_VERSION_MAJOR}::PrintSupport
|
||||
Qt${QT_VERSION_MAJOR}::GuiPrivate
|
||||
Qt${QT_VERSION_MAJOR}::CorePrivate
|
||||
Qt${QT_VERSION_MAJOR}::Xml
|
||||
SingleApplication::SingleApplication
|
||||
QWKCore
|
||||
QWKWidgets
|
||||
QHexView
|
||||
QCodeEditor2
|
||||
QCodeModel2
|
||||
QJsonModel
|
||||
angelscript
|
||||
QConsoleWidget
|
||||
|
@ -473,10 +487,10 @@ else()
|
|||
Qt${QT_VERSION_MAJOR}::PrintSupport
|
||||
Qt${QT_VERSION_MAJOR}::GuiPrivate
|
||||
Qt${QT_VERSION_MAJOR}::CorePrivate
|
||||
Qt${QT_VERSION_MAJOR}::Xml
|
||||
SingleApplication::SingleApplication
|
||||
QHexView
|
||||
QCodeEditor2
|
||||
QCodeModel2
|
||||
QJsonModel
|
||||
angelscript
|
||||
QConsoleWidget
|
||||
|
|
After Width: | Height: | Size: 319 B |
Before Width: | Height: | Size: 367 B After Width: | Height: | Size: 367 B |
Before Width: | Height: | Size: 421 B After Width: | Height: | Size: 421 B |
Before Width: | Height: | Size: 241 B After Width: | Height: | Size: 241 B |
Before Width: | Height: | Size: 342 B After Width: | Height: | Size: 342 B |
Before Width: | Height: | Size: 313 B After Width: | Height: | Size: 313 B |
Before Width: | Height: | Size: 310 B After Width: | Height: | Size: 310 B |
Before Width: | Height: | Size: 332 B After Width: | Height: | Size: 332 B |
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 295 B |
Before Width: | Height: | Size: 347 B After Width: | Height: | Size: 347 B |
After Width: | Height: | Size: 354 B |
After Width: | Height: | Size: 356 B |
Before Width: | Height: | Size: 314 B After Width: | Height: | Size: 314 B |
Before Width: | Height: | Size: 346 B After Width: | Height: | Size: 346 B |
After Width: | Height: | Size: 352 B |
After Width: | Height: | Size: 353 B |
Before Width: | Height: | Size: 321 B After Width: | Height: | Size: 321 B |
Before Width: | Height: | Size: 320 B After Width: | Height: | Size: 320 B |
After Width: | Height: | Size: 327 B |
After Width: | Height: | Size: 329 B |
Before Width: | Height: | Size: 293 B After Width: | Height: | Size: 293 B |
After Width: | Height: | Size: 355 B |
Before Width: | Height: | Size: 287 B After Width: | Height: | Size: 287 B |
After Width: | Height: | Size: 427 B |
Before Width: | Height: | Size: 908 B After Width: | Height: | Size: 908 B |
|
@ -13,7 +13,7 @@
|
|||
AppManager *AppManager::_instance = nullptr;
|
||||
|
||||
AppManager::AppManager(int &argc, char *argv[])
|
||||
: SingleApplication(argc, argv) {
|
||||
: SingleApplication(argc, argv, true) {
|
||||
ASSERT_SINGLETON;
|
||||
|
||||
setApplicationName(APP_NAME);
|
||||
|
@ -36,17 +36,6 @@ AppManager::AppManager(int &argc, char *argv[])
|
|||
QFont font(set.appFontFamily(), set.appfontSize());
|
||||
setFont(font);
|
||||
|
||||
connect(&set, &SettingManager::sigAppFontFamilyChanged, this,
|
||||
[](const QString &fontfam) {
|
||||
QFont font(fontfam);
|
||||
setFont(font);
|
||||
});
|
||||
connect(&set, &SettingManager::sigAppfontSizeChanged, this, [](int v) {
|
||||
auto font = qApp->font();
|
||||
font.setPointSize(v);
|
||||
qApp->setFont(font);
|
||||
});
|
||||
|
||||
SkinManager::instance();
|
||||
LanguageManager::instance();
|
||||
|
||||
|
|
|
@ -3,10 +3,11 @@
|
|||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QObject>
|
||||
|
||||
BEGIN_AS_NAMESPACE
|
||||
|
||||
asBuilder::asBuilder(QObject *parent) : QObject(parent) {
|
||||
asBuilder::asBuilder() {
|
||||
engine = nullptr;
|
||||
module = nullptr;
|
||||
|
||||
|
@ -136,7 +137,8 @@ int asBuilder::LoadScriptSection(const QString &filename) {
|
|||
|
||||
if (!f.open(QFile::ReadOnly)) {
|
||||
// Write a message to the engine's message callback
|
||||
auto msg = tr("Failed to open script file ") + QStringLiteral("'") +
|
||||
auto msg = QObject::tr("Failed to open script file ") +
|
||||
QStringLiteral("'") +
|
||||
QFileInfo(filename).absoluteFilePath() + QStringLiteral("'");
|
||||
engine->WriteMessage(filename.toUtf8(), 0, 0, asMSGTYPE_ERROR,
|
||||
msg.toUtf8());
|
||||
|
@ -402,11 +404,12 @@ int asBuilder::ProcessScriptSection(const QByteArray &script, int length,
|
|||
if (p >= 0) {
|
||||
// TODO: Show the correct line number for the
|
||||
// error
|
||||
auto str = tr("Invalid file name for #include; "
|
||||
"it contains a line-break: ") +
|
||||
QStringLiteral("'") +
|
||||
includefile.left(p) +
|
||||
QStringLiteral("'");
|
||||
auto str =
|
||||
QObject::tr(
|
||||
"Invalid file name for #include; "
|
||||
"it contains a line-break: ") +
|
||||
QStringLiteral("'") + includefile.left(p) +
|
||||
QStringLiteral("'");
|
||||
engine->WriteMessage(sectionname.toUtf8(), 0, 0,
|
||||
asMSGTYPE_ERROR,
|
||||
str.toUtf8());
|
||||
|
@ -452,8 +455,9 @@ int asBuilder::ProcessScriptSection(const QByteArray &script, int length,
|
|||
// TODO: Show the correct line number for
|
||||
// the error
|
||||
auto str =
|
||||
tr("Invalid file name for #include; "
|
||||
"it contains a line-break: ") +
|
||||
QObject::tr(
|
||||
"Invalid file name for #include; "
|
||||
"it contains a line-break: ") +
|
||||
QStringLiteral("'") +
|
||||
includefile.left(p) +
|
||||
QStringLiteral("'");
|
||||
|
@ -469,9 +473,10 @@ int asBuilder::ProcessScriptSection(const QByteArray &script, int length,
|
|||
OverwriteCode(start, pos - start);
|
||||
}
|
||||
} else {
|
||||
auto str = tr("Invalid file name for #include; "
|
||||
"it contains a line-break or "
|
||||
"unpaired symbol");
|
||||
auto str = QObject::tr(
|
||||
"Invalid file name for #include; "
|
||||
"it contains a line-break or "
|
||||
"unpaired symbol");
|
||||
engine->WriteMessage(sectionname.toUtf8(), 0, 0,
|
||||
asMSGTYPE_ERROR,
|
||||
str.toUtf8());
|
||||
|
@ -496,7 +501,8 @@ int asBuilder::ProcessScriptSection(const QByteArray &script, int length,
|
|||
// TODO: Report the correct line number
|
||||
engine->WriteMessage(
|
||||
sectionname.toUtf8(), 0, 0, asMSGTYPE_ERROR,
|
||||
tr("Invalid #pragma directive").toUtf8());
|
||||
QObject::tr("Invalid #pragma directive")
|
||||
.toUtf8());
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#endif
|
||||
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
#include <QVector>
|
||||
|
||||
|
@ -57,10 +56,9 @@ typedef int (*PRAGMACALLBACK_t)(const QByteArray &pragmaText,
|
|||
// Helper class for loading and pre-processing script files to
|
||||
// support include directives and metadata declarations
|
||||
|
||||
class asBuilder : public QObject {
|
||||
Q_OBJECT
|
||||
class asBuilder {
|
||||
public:
|
||||
explicit asBuilder(QObject *parent = nullptr);
|
||||
explicit asBuilder();
|
||||
|
||||
// Start a new module
|
||||
int StartNewModule(asIScriptEngine *engine, const char *moduleName);
|
||||
|
|
|
@ -1,36 +1,16 @@
|
|||
#ifndef _AS_COMPLETION_H_
|
||||
#define _AS_COMPLETION_H_
|
||||
|
||||
#include "control/qcodecompletionwidget.h"
|
||||
#include "qcodecompletionengine.h"
|
||||
#include "qcodenode.h"
|
||||
|
||||
#include <QHash>
|
||||
|
||||
class QByteArray;
|
||||
|
||||
class QCodeCompletionBackend {
|
||||
friend class AsCompletion;
|
||||
|
||||
public:
|
||||
QCodeCompletionBackend();
|
||||
virtual ~QCodeCompletionBackend();
|
||||
|
||||
QList<QCodeNode *> rootNodes() const;
|
||||
QCodeNode *findNode(const QByteArray &type) const;
|
||||
|
||||
void init();
|
||||
|
||||
private:
|
||||
QCodeModel *pModel;
|
||||
QStringList m_buffer, m_pathlist;
|
||||
};
|
||||
|
||||
class AsCompletion : public QCodeCompletionEngine {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AsCompletion(QObject *p = nullptr);
|
||||
AsCompletion(QCodeModel *m, QObject *p = nullptr);
|
||||
|
||||
virtual ~AsCompletion();
|
||||
|
||||
|
@ -39,52 +19,13 @@ public:
|
|||
virtual QString language() const override;
|
||||
virtual QStringList extensions() const override;
|
||||
|
||||
void init();
|
||||
|
||||
QCodeCompletionBackend *backend() const;
|
||||
|
||||
protected:
|
||||
virtual void setCodeModel(QCodeModel *m) override;
|
||||
virtual void complete(QCodeStream *s, const QString &trigger) override;
|
||||
|
||||
public:
|
||||
void hierarchy(QCodeNode *n, QList<QCodeNode *> &l,
|
||||
QHash<QByteArray, QByteArray> &tpl);
|
||||
|
||||
QCodeNode *lookup(const QByteArray &t);
|
||||
QCodeNode *nsAwareLookup(const QByteArray &t);
|
||||
QCodeNode *lookup(QCodeNode *n, const QByteArray &t,
|
||||
QList<QCodeNode *> *extra = 0);
|
||||
|
||||
QCodeNode *localLookup(const QList<QCodeNode *> &cxt, QByteArray &tt,
|
||||
QByteArray &type, bool &ptr,
|
||||
QHash<QByteArray, QByteArray> &tpl);
|
||||
|
||||
QCodeNode *decrementalLookup(const QList<QCodeNode *> &cxt, QByteArray &tt,
|
||||
QByteArray &type, bool &ptr,
|
||||
QHash<QByteArray, QByteArray> &tpl,
|
||||
int k = -1);
|
||||
|
||||
void getMembers(QList<QByteArray>::const_iterator beg,
|
||||
QList<QByteArray>::const_iterator end,
|
||||
const QHash<QByteArray, QByteArray> &variables,
|
||||
QList<QByteArray> cxt, QList<QCodeNode *> &l, int *filter);
|
||||
|
||||
QByteArray functionLookup(QCodeNode *n, const QByteArray &s);
|
||||
QByteArray functionLookup(QCodeModel *m, const QByteArray &s);
|
||||
virtual void complete(const QDocumentCursor &c,
|
||||
const QString &trigger) override;
|
||||
|
||||
private:
|
||||
QCodeCompletionWidget *pPopup;
|
||||
QPointer<QCodeModel> pModel;
|
||||
|
||||
static unsigned long instances;
|
||||
static QCodeCompletionBackend *pBackend;
|
||||
|
||||
QCodeNode *m_locals;
|
||||
QList<QByteArray> context;
|
||||
QList<QByteArray> m_namespaces;
|
||||
QHash<QByteArray, QByteArray> variables;
|
||||
bool scope_local, scope_system, scope_file;
|
||||
// QCodeCompletionWidget *pPopup;
|
||||
// QPointer<QCodeModel> pModel;
|
||||
};
|
||||
|
||||
#endif // _CPP_COMPLETION_H_
|
||||
|
|
|
@ -56,7 +56,8 @@ void asDebugger::lineCallback(asIScriptContext *ctx) {
|
|||
return;
|
||||
|
||||
const char *file = 0;
|
||||
int lineNbr = ctx->GetLineNumber(0, nullptr, &file);
|
||||
int col = 0;
|
||||
int lineNbr = ctx->GetLineNumber(0, &col, &file);
|
||||
|
||||
// why?
|
||||
// LineCallBack will be called each only a sentence,
|
||||
|
@ -69,7 +70,8 @@ void asDebugger::lineCallback(asIScriptContext *ctx) {
|
|||
auto dbgContext =
|
||||
reinterpret_cast<ContextDbgInfo *>(ctx->GetUserData());
|
||||
if (dbgContext->line == lineNbr && dbgContext->file == file &&
|
||||
dbgContext->stackCount == ctx->GetCallstackSize()) {
|
||||
dbgContext->stackCount == ctx->GetCallstackSize() &&
|
||||
dbgContext->col < col) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -107,6 +109,7 @@ void asDebugger::lineCallback(asIScriptContext *ctx) {
|
|||
Q_ASSERT(dbgContext);
|
||||
dbgContext->file = file;
|
||||
dbgContext->line = lineNbr;
|
||||
dbgContext->col = col;
|
||||
dbgContext->stackCount = ctx->GetCallstackSize();
|
||||
|
||||
emit onRunCurrentLine(file, lineNbr);
|
||||
|
|
|
@ -133,6 +133,7 @@ private:
|
|||
struct ContextDbgInfo {
|
||||
QString file;
|
||||
int line = -1;
|
||||
int col = -1;
|
||||
int stackCount = -1;
|
||||
};
|
||||
|
||||
|
|
|
@ -37,6 +37,28 @@ LanguageManager::LanguageManager() {
|
|||
}
|
||||
|
||||
_defaultLocale = QLocale::system();
|
||||
|
||||
if (m_langs.isEmpty()) {
|
||||
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
|
||||
if (QLocale::China == _defaultLocale.territory()
|
||||
#else
|
||||
if (QLocale::China == _defaultLocale.country()
|
||||
#endif
|
||||
) {
|
||||
QMessageBox::critical(
|
||||
nullptr, QStringLiteral("程序损坏"),
|
||||
QStringLiteral(
|
||||
"语言文件已损坏,请尝试重装软件以解决这个问题。"));
|
||||
} else {
|
||||
QMessageBox::critical(
|
||||
nullptr, QStringLiteral("Corruption"),
|
||||
QStringLiteral("The language file has been damaged. "
|
||||
"Please try reinstalling the software to "
|
||||
"solve the problem."));
|
||||
}
|
||||
qApp->exit(-1);
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (auto p = m_localeMap.begin(); p != m_localeMap.end(); ++p) {
|
||||
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
|
||||
|
@ -44,7 +66,7 @@ LanguageManager::LanguageManager() {
|
|||
#else
|
||||
if (p->country() == _defaultLocale.country() &&
|
||||
#endif
|
||||
p->language() == p->language() &&
|
||||
p->language() == _defaultLocale.language() &&
|
||||
p->script() == _defaultLocale.script()) {
|
||||
found = true;
|
||||
break;
|
||||
|
|
|
@ -1,689 +0,0 @@
|
|||
#include "qaslexer.h"
|
||||
#include "qcodestream.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QChar>
|
||||
#include <QRegularExpression>
|
||||
#include <QStack>
|
||||
|
||||
//#define _TRACE_FILTERING_
|
||||
|
||||
#ifdef _TRACE_FILTERING_
|
||||
static QByteArray filterIndent;
|
||||
|
||||
#define FILTER_IN filterIndent += " ";
|
||||
#define FILTER_OUT filterIndent.chop(1);
|
||||
|
||||
#define FILTER_TRACE(fmt, data) qDebug("%s" fmt, filterIndent.constData(), data)
|
||||
|
||||
#else
|
||||
|
||||
#define FILTER_IN
|
||||
#define FILTER_OUT
|
||||
|
||||
#define FILTER_TRACE(fmt, data)
|
||||
|
||||
#endif
|
||||
|
||||
QHash<QToken, QToken> QAsLexer::m_macros;
|
||||
|
||||
QAsLexer::QAsLexer() : QCodeLexer(), bTokenized(false), bKeepMacros(false) {
|
||||
// initMacros();
|
||||
}
|
||||
|
||||
QAsLexer::QAsLexer(QCodeStream *s)
|
||||
: QCodeLexer(s), bTokenized(false), bKeepMacros(false) {
|
||||
// initMacros();
|
||||
refreshTokens(Normal);
|
||||
}
|
||||
|
||||
void QAsLexer::initMacros(const QTokenList &l) {
|
||||
if (m_macros.count())
|
||||
return;
|
||||
|
||||
// qDebug("loaded %i macros", l.count());
|
||||
|
||||
for (QToken m : l) {
|
||||
m = m.trimmed();
|
||||
int idx = m.indexOf('=');
|
||||
|
||||
if (idx == -1) {
|
||||
m_macros[m];
|
||||
continue;
|
||||
}
|
||||
|
||||
m_macros[m.left(idx)] = m.mid(idx + 1);
|
||||
}
|
||||
}
|
||||
|
||||
bool QAsLexer::keepMacroBlocks() const { return bKeepMacros; }
|
||||
|
||||
void QAsLexer::setKeepMacroBlocks(bool keep) { bKeepMacros = keep; }
|
||||
|
||||
void QAsLexer::setInput(QCodeStream *s, LexMode m) {
|
||||
QCodeLexer::setInput(s);
|
||||
|
||||
bTokenized = false;
|
||||
|
||||
refreshTokens(m);
|
||||
}
|
||||
|
||||
QToken QAsLexer::nextToken() {
|
||||
if (!bTokenized) {
|
||||
qWarning("Empty token buffer (no stream passed to lexer)");
|
||||
}
|
||||
|
||||
if (tokenPointer < tokenBuffer.constEnd())
|
||||
return *(tokenPointer++);
|
||||
|
||||
return QToken();
|
||||
}
|
||||
|
||||
QToken QAsLexer::previousToken() {
|
||||
if (!bTokenized) {
|
||||
qWarning("Empty token buffer (no stream passed to lexer)");
|
||||
}
|
||||
|
||||
if (tokenPointer >= tokenBuffer.constBegin())
|
||||
return *(tokenPointer--);
|
||||
|
||||
return QToken();
|
||||
}
|
||||
|
||||
QTokenList QAsLexer::tokens() {
|
||||
if (!bTokenized) {
|
||||
qWarning("Empty token buffer (no stream passed to lexer)");
|
||||
}
|
||||
|
||||
return tokenBuffer;
|
||||
}
|
||||
|
||||
int QAsLexer::lineForToken(int tokenId, int minLine) const {
|
||||
// minLine = 0;
|
||||
|
||||
int line = minLine;
|
||||
if (minLine)
|
||||
minLine = 0;
|
||||
|
||||
minLine *= 2;
|
||||
// qDebug("looking for token %i", tokenId);
|
||||
|
||||
while (minLine < m_jumps.count()) {
|
||||
if (tokenId < m_jumps.at(minLine))
|
||||
break;
|
||||
|
||||
line = m_jumps.at(++minLine);
|
||||
// line += m_jumps.at(++minLine);
|
||||
|
||||
// qDebug("gap : %i", line);
|
||||
|
||||
++minLine;
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void s_flush(T &buffer, QList<T> &data, bool a,
|
||||
const QHash<QToken, QToken> ¯os,
|
||||
QList<int> &suspicious) {
|
||||
if (buffer.length() && a) {
|
||||
QHash<QToken, QToken>::const_iterator it = macros.constFind(buffer);
|
||||
|
||||
if (it != macros.constEnd()) {
|
||||
suspicious << data.count();
|
||||
}
|
||||
|
||||
data << buffer;
|
||||
}
|
||||
|
||||
buffer.clear();
|
||||
}
|
||||
|
||||
#define flush(buffer, data, include) \
|
||||
s_flush(buffer, data, include | bKeepMacros, m_macros, m_suspicious)
|
||||
|
||||
static bool next(QCodeStream *s, char &ascii, QChar &uni) {
|
||||
uni = ascii = s->getChar();
|
||||
|
||||
return ascii;
|
||||
}
|
||||
|
||||
static void previous(QCodeStream *s, char c) { s->ungetChar(c); }
|
||||
|
||||
void QAsLexer::refreshTokens(LexMode m) {
|
||||
if (input->contextFile().contains(QRegularExpression("[\\\\/]arch[\\\\/]")))
|
||||
return;
|
||||
|
||||
int seq = 0;
|
||||
int line = 0;
|
||||
char c, tmp;
|
||||
QChar uc, utmp;
|
||||
QByteArray buffer, log, sep;
|
||||
|
||||
QStack<bool> branch;
|
||||
tokenBuffer.clear();
|
||||
|
||||
branch.push(true);
|
||||
|
||||
QHash<QToken, QToken> macros = m_macros;
|
||||
|
||||
while (next(input, c, uc)) {
|
||||
log += c;
|
||||
|
||||
if (isspace(c)) {
|
||||
flush(buffer, tokenBuffer, branch.top());
|
||||
|
||||
while (c && isspace(c)) {
|
||||
if (c == '\n') {
|
||||
// qDebug("EOL after %i tokens", tokenBuffer.count());
|
||||
++line;
|
||||
|
||||
if (m_jumps.count() &&
|
||||
m_jumps.at(m_jumps.count() - 2) == tokenBuffer.count())
|
||||
m_jumps[m_jumps.count() - 1] = line;
|
||||
else
|
||||
m_jumps << tokenBuffer.count() << line; // << 1;
|
||||
|
||||
if (m == KeepLineSeparators)
|
||||
tokenBuffer << sep;
|
||||
}
|
||||
|
||||
next(input, c, uc);
|
||||
}
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case '!':
|
||||
case '=':
|
||||
|
||||
flush(buffer, tokenBuffer, branch.top());
|
||||
|
||||
if (next(input, tmp, utmp)) {
|
||||
if (tmp == '=') {
|
||||
buffer += c;
|
||||
buffer += tmp;
|
||||
|
||||
flush(buffer, tokenBuffer, branch.top());
|
||||
|
||||
break;
|
||||
} else {
|
||||
previous(input, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
if (branch.top() || bKeepMacros)
|
||||
tokenBuffer << QByteArray(1, c);
|
||||
|
||||
break;
|
||||
|
||||
case '.':
|
||||
do {
|
||||
++seq;
|
||||
} while (next(input, tmp, utmp) && tmp == '.');
|
||||
|
||||
if (seq == 3) {
|
||||
if (!(branch.top() || bKeepMacros))
|
||||
break;
|
||||
|
||||
flush(buffer, tokenBuffer, branch.top());
|
||||
tokenBuffer << "...";
|
||||
previous(input, tmp);
|
||||
seq = 0;
|
||||
break;
|
||||
} else if (tmp) {
|
||||
do {
|
||||
previous(input, tmp);
|
||||
} while (--seq);
|
||||
}
|
||||
|
||||
case '~':
|
||||
|
||||
case '?':
|
||||
|
||||
case '(':
|
||||
case '{':
|
||||
case '}':
|
||||
case '[':
|
||||
case ']':
|
||||
case ')':
|
||||
|
||||
case ',':
|
||||
case ';':
|
||||
|
||||
// "single" characters
|
||||
|
||||
if (!(branch.top() || bKeepMacros))
|
||||
break;
|
||||
|
||||
flush(buffer, tokenBuffer, branch.top());
|
||||
tokenBuffer << QByteArray(1, c);
|
||||
|
||||
break;
|
||||
|
||||
case '^':
|
||||
case '|':
|
||||
case '&':
|
||||
// bitwises
|
||||
|
||||
flush(buffer, tokenBuffer, branch.top());
|
||||
|
||||
if (next(input, tmp, utmp)) {
|
||||
if (tmp == c) {
|
||||
if (branch.top() || bKeepMacros)
|
||||
tokenBuffer << QByteArray(2, c);
|
||||
|
||||
break;
|
||||
} else if (tmp == '=') {
|
||||
buffer += c;
|
||||
buffer += tmp;
|
||||
|
||||
flush(buffer, tokenBuffer, branch.top());
|
||||
|
||||
break;
|
||||
} else
|
||||
previous(input, tmp);
|
||||
}
|
||||
|
||||
if (branch.top() || bKeepMacros)
|
||||
tokenBuffer << QByteArray(1, c);
|
||||
|
||||
break;
|
||||
|
||||
case '*':
|
||||
case '%':
|
||||
case '+':
|
||||
case '-':
|
||||
// operators
|
||||
|
||||
flush(buffer, tokenBuffer, branch.top());
|
||||
|
||||
if (next(input, tmp, utmp)) {
|
||||
if ((tmp == '=') || (c == '-' && tmp == '>') ||
|
||||
(((c == '-') || (c == '+')) && (c == tmp))) {
|
||||
buffer += c;
|
||||
buffer += tmp;
|
||||
|
||||
flush(buffer, tokenBuffer, branch.top());
|
||||
|
||||
break;
|
||||
} else
|
||||
previous(input, tmp);
|
||||
}
|
||||
|
||||
if (branch.top() || bKeepMacros)
|
||||
tokenBuffer << QByteArray(1, c);
|
||||
|
||||
break;
|
||||
|
||||
case '<':
|
||||
case '>':
|
||||
// template or shift
|
||||
|
||||
flush(buffer, tokenBuffer, branch.top());
|
||||
|
||||
if (next(input, tmp, utmp)) {
|
||||
if (tmp == c) {
|
||||
if (branch.top() || bKeepMacros)
|
||||
tokenBuffer << QByteArray(2, c);
|
||||
|
||||
break;
|
||||
} else if (tmp == '=') {
|
||||
buffer += c;
|
||||
buffer += tmp;
|
||||
|
||||
flush(buffer, tokenBuffer, branch.top());
|
||||
|
||||
break;
|
||||
} else
|
||||
previous(input, tmp);
|
||||
}
|
||||
|
||||
if (branch.top() || bKeepMacros)
|
||||
tokenBuffer << QByteArray(1, c);
|
||||
|
||||
break;
|
||||
|
||||
case ':':
|
||||
// label or scope resolution
|
||||
|
||||
flush(buffer, tokenBuffer, branch.top());
|
||||
|
||||
if (next(input, tmp, utmp)) {
|
||||
if (tmp == c) {
|
||||
if (branch.top() || bKeepMacros)
|
||||
tokenBuffer << QByteArray(2, c);
|
||||
|
||||
break;
|
||||
} else
|
||||
previous(input, tmp);
|
||||
}
|
||||
|
||||
if (branch.top() || bKeepMacros)
|
||||
tokenBuffer << QByteArray(1, c);
|
||||
|
||||
break;
|
||||
|
||||
case '#': {
|
||||
// macros
|
||||
|
||||
flush(buffer, tokenBuffer, branch.top());
|
||||
|
||||
buffer += c;
|
||||
|
||||
char prev = c;
|
||||
bool first = true;
|
||||
|
||||
while (next(input, tmp, utmp))
|
||||
if (!utmp.isSpace())
|
||||
break;
|
||||
|
||||
buffer += tmp;
|
||||
|
||||
// skip up to EOL
|
||||
while (next(input, tmp, utmp)) {
|
||||
if (first && utmp.isSpace()) {
|
||||
first = false;
|
||||
|
||||
if (buffer == "#ifdef") {
|
||||
// check for __cplusplus ???
|
||||
branch.push(false);
|
||||
} else if (buffer == "#ifndef") {
|
||||
branch.push(branch.top());
|
||||
} else if (buffer == "#else") {
|
||||
|
||||
if (branch.count() > 1)
|
||||
branch.push(!branch.pop() && branch.top());
|
||||
else
|
||||
qWarning("unpreced #else");
|
||||
|
||||
} else if (buffer == "#elif") {
|
||||
|
||||
while (next(input, tmp, utmp))
|
||||
if (!utmp.isSpace())
|
||||
break;
|
||||
|
||||
if (branch.count() > 1)
|
||||
branch.top() = (tmp == '!') && branch.top();
|
||||
else
|
||||
qWarning("unpreced #elif");
|
||||
|
||||
} else if (buffer == "#if") {
|
||||
|
||||
while (next(input, tmp, utmp))
|
||||
if (!utmp.isSpace())
|
||||
break;
|
||||
|
||||
branch.push((tmp == '!') && branch.top());
|
||||
|
||||
} else if (buffer == "#endif") {
|
||||
|
||||
if (branch.count() > 1)
|
||||
branch.pop();
|
||||
else
|
||||
qWarning("too much #endif directives in %s",
|
||||
qPrintable(input->contextFile()));
|
||||
} else if (buffer == "#include") {
|
||||
|
||||
if (tokenBuffer.isEmpty()) {
|
||||
while (next(input, tmp, utmp))
|
||||
if (!utmp.isSpace())
|
||||
break;
|
||||
|
||||
if (tmp == '\"') {
|
||||
while (next(input, tmp, utmp)) {
|
||||
if (tmp == '\"')
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (buffer == "#define") {
|
||||
buffer.clear();
|
||||
|
||||
while (next(input, tmp, utmp) && !utmp.isSpace()) {
|
||||
buffer += tmp;
|
||||
}
|
||||
|
||||
// add local macro
|
||||
macros[buffer];
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp == '\n' && prev != '\\') {
|
||||
++line;
|
||||
|
||||
// qDebug("EOL after %i tokens", tokenBuffer.count());
|
||||
|
||||
if (m_jumps.count() &&
|
||||
m_jumps.at(m_jumps.count() - 2) == tokenBuffer.count())
|
||||
m_jumps[m_jumps.count() - 1] = line;
|
||||
else
|
||||
m_jumps << tokenBuffer.count() << line; // << 1;
|
||||
|
||||
buffer.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
prev = tmp;
|
||||
buffer += tmp;
|
||||
}
|
||||
|
||||
buffer.clear();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case '/':
|
||||
// comments
|
||||
|
||||
flush(buffer, tokenBuffer, branch.top());
|
||||
|
||||
if (next(input, tmp, utmp)) {
|
||||
if (tmp == '/') {
|
||||
// buffer += "//";
|
||||
|
||||
while (next(input, c, uc)) {
|
||||
if (c == '\n') {
|
||||
++line;
|
||||
// qDebug("EOL after %i tokens",
|
||||
// tokenBuffer.count());
|
||||
|
||||
if (m_jumps.count() &&
|
||||
m_jumps.at(m_jumps.count() - 2) ==
|
||||
tokenBuffer.count())
|
||||
m_jumps[m_jumps.count() - 1] = line;
|
||||
else
|
||||
m_jumps << tokenBuffer.count() << line; // << 1;
|
||||
|
||||
break;
|
||||
}
|
||||
// buffer += c;
|
||||
}
|
||||
|
||||
// flush(buffer, tokenBuffer);
|
||||
|
||||
} else if (tmp == '*') {
|
||||
|
||||
// buffer += "/*";
|
||||
|
||||
while (next(input, c, uc)) {
|
||||
if (c == '\n') {
|
||||
++line;
|
||||
// qDebug("EOL after %i tokens",
|
||||
// tokenBuffer.count());
|
||||
|
||||
if (m_jumps.count() &&
|
||||
m_jumps.at(m_jumps.count() - 2) ==
|
||||
tokenBuffer.count())
|
||||
m_jumps[m_jumps.count() - 1] = line;
|
||||
else
|
||||
m_jumps << tokenBuffer.count() << line; // << 1;
|
||||
|
||||
} else if ((c == '*') && next(input, tmp, utmp)) {
|
||||
if (tmp == '/')
|
||||
break;
|
||||
|
||||
previous(input, tmp);
|
||||
}
|
||||
|
||||
// buffer += c;
|
||||
}
|
||||
|
||||
// buffer += "* /";
|
||||
|
||||
// flush(buffer, tokenBuffer);
|
||||
|
||||
} else if (tmp == '=') {
|
||||
buffer = "/=";
|
||||
flush(buffer, tokenBuffer, branch.top());
|
||||
|
||||
} else {
|
||||
buffer = "/";
|
||||
flush(buffer, tokenBuffer, branch.top());
|
||||
|
||||
previous(input, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
buffer.clear();
|
||||
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
case '\"': {
|
||||
flush(buffer, tokenBuffer, branch.top());
|
||||
|
||||
// quotes
|
||||
bool escape = false;
|
||||
|
||||
while (next(input, tmp, utmp)) {
|
||||
if (tmp == '\\') {
|
||||
buffer += tmp;
|
||||
escape = !escape;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((tmp == c) && !escape)
|
||||
break;
|
||||
|
||||
escape = false;
|
||||
buffer += tmp;
|
||||
}
|
||||
|
||||
buffer.prepend(c);
|
||||
buffer.append(c);
|
||||
|
||||
flush(buffer, tokenBuffer, branch.top());
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case '\0':
|
||||
flush(buffer, tokenBuffer, branch.top());
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
if (uc.isLetterOrNumber() || c == '_') {
|
||||
// valid identifier char
|
||||
|
||||
buffer += c;
|
||||
} else {
|
||||
// invalid id char not previously parsed
|
||||
|
||||
// qWarning("=> unparsed char : \'%c\' [log=\"%s\"]",
|
||||
// c, log.constData());
|
||||
|
||||
buffer.clear();
|
||||
// flush(buffer, tokenBuffer, branch.top());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
flush(buffer, tokenBuffer, branch.top());
|
||||
|
||||
if (branch.count() > 1)
|
||||
qWarning("Unterminated conditionnals in %s",
|
||||
qPrintable(input->contextFile()));
|
||||
|
||||
// lets filter that mess :
|
||||
int offset = 0;
|
||||
|
||||
while (m_suspicious.count()) {
|
||||
int pos = m_suspicious.takeFirst() + offset;
|
||||
|
||||
QHash<QToken, QToken>::const_iterator it =
|
||||
macros.constFind(tokenBuffer.at(pos));
|
||||
|
||||
if (it != macros.constEnd()) {
|
||||
if (it->length()) {
|
||||
tokenBuffer[pos] = *it;
|
||||
} else {
|
||||
// remove the macro and its arguments if any
|
||||
tokenBuffer.removeAt(pos);
|
||||
int prev = offset;
|
||||
--offset;
|
||||
|
||||
if (pos < tokenBuffer.count() && tokenBuffer.at(pos) == "(") {
|
||||
int nest = 0;
|
||||
|
||||
while (pos < tokenBuffer.count()) {
|
||||
QToken tok = tokenBuffer.takeAt(pos);
|
||||
|
||||
if (tok == "(")
|
||||
++nest;
|
||||
else if (tok == ")")
|
||||
--nest;
|
||||
|
||||
--offset;
|
||||
|
||||
if (!nest)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// update the gap list used to query line numbers
|
||||
prev = offset - prev;
|
||||
|
||||
// qDebug("removed %i suspicious tokens", -prev);
|
||||
|
||||
for (int i = 0; i < m_jumps.count(); i += 2) {
|
||||
if (m_jumps.at(i) <= pos)
|
||||
continue;
|
||||
|
||||
// qDebug("gap (%i, %i) becomes (%i, %i)", m_jumps[i],
|
||||
// m_jumps[i + 1], m_jumps[i] + prev, m_jumps[i + 1]);
|
||||
m_jumps[i] += prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = m_jumps.count() - 2; i > 0; i -= 2) {
|
||||
int j = i - 2;
|
||||
|
||||
while ((j >= 0) && (m_jumps[j] == m_jumps[i])) {
|
||||
// qDebug("merged gap (%i, %i) and (%i, %i)", m_jumps[i], m_jumps[i
|
||||
// + 1], m_jumps[j], m_jumps[j + 1]);
|
||||
m_jumps.removeAt(i);
|
||||
m_jumps.removeAt(j + 1);
|
||||
|
||||
i = j;
|
||||
j -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
bTokenized = true;
|
||||
|
||||
/*
|
||||
qDebug("stream %s tokenized :\n-----",
|
||||
qPrintable(input->contextFile()));
|
||||
|
||||
foreach ( QToken k, tokenBuffer )
|
||||
qDebug("\t%s", k.constData());
|
||||
|
||||
qDebug("-----\n");
|
||||
*/
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
#ifndef _QAS_LEXER_H_
|
||||
#define _QAS_LEXER_H_
|
||||
|
||||
#include "qcodelexer.h"
|
||||
|
||||
#include <QHash>
|
||||
|
||||
class QAsLexer : public QCodeLexer {
|
||||
public:
|
||||
QAsLexer();
|
||||
QAsLexer(QCodeStream *s);
|
||||
|
||||
bool keepMacroBlocks() const;
|
||||
void setKeepMacroBlocks(bool keep);
|
||||
|
||||
virtual void setInput(QCodeStream *s, LexMode m = Normal);
|
||||
|
||||
virtual QToken nextToken();
|
||||
virtual QToken previousToken();
|
||||
|
||||
virtual QTokenList tokens();
|
||||
virtual int lineForToken(int tokenId, int minLine = 0) const;
|
||||
|
||||
void initMacros(const QTokenList &l);
|
||||
|
||||
protected:
|
||||
void refreshTokens(LexMode m);
|
||||
|
||||
QList<int> m_jumps;
|
||||
QList<int> m_suspicious;
|
||||
QTokenList tokenBuffer;
|
||||
bool bTokenized, bKeepMacros;
|
||||
static QHash<QToken, QToken> m_macros;
|
||||
QTokenList::const_iterator tokenPointer;
|
||||
};
|
||||
|
||||
#endif // _QCPP_LEXER_H_
|
|
@ -1,87 +1,24 @@
|
|||
#ifndef _QAS_PARSER_H_
|
||||
#define _QAS_PARSER_H_
|
||||
|
||||
#include "qcodelexer.h"
|
||||
#include "qcodeparser.h"
|
||||
#include "class/asbuilder.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QScopedPointer>
|
||||
|
||||
class QAsParser : public QCodeParser {
|
||||
class asCScriptCode;
|
||||
|
||||
class QAsParser : protected asBuilder {
|
||||
public:
|
||||
enum KeywordId {
|
||||
KEYWORD_NONE = -1,
|
||||
|
||||
KEYWORD_ATTRIBUTE,
|
||||
KEYWORD_AUTO,
|
||||
KEYWORD_BOOL,
|
||||
KEYWORD_BREAK,
|
||||
KEYWORD_CASE,
|
||||
KEYWORD_CATCH,
|
||||
KEYWORD_CHAR,
|
||||
KEYWORD_CLASS,
|
||||
KEYWORD_CONST,
|
||||
KEYWORD_CONTINUE,
|
||||
KEYWORD_DEFAULT,
|
||||
KEYWORD_DELETE,
|
||||
KEYWORD_DO,
|
||||
KEYWORD_DOUBLE,
|
||||
KEYWORD_ELSE,
|
||||
KEYWORD_ENUM,
|
||||
KEYWORD_EXPLICIT,
|
||||
KEYWORD_EXTERN,
|
||||
KEYWORD_FLOAT,
|
||||
KEYWORD_FOR,
|
||||
KEYWORD_FRIEND,
|
||||
KEYWORD_FUNCTION,
|
||||
KEYWORD_GOTO,
|
||||
KEYWORD_IF,
|
||||
KEYWORD_INLINE,
|
||||
KEYWORD_INT,
|
||||
KEYWORD_INTERNAL,
|
||||
KEYWORD_LONG,
|
||||
KEYWORD_NAMESPACE,
|
||||
KEYWORD_NEW,
|
||||
KEYWORD_OPERATOR,
|
||||
KEYWORD_PRIVATE,
|
||||
KEYWORD_PROTECTED,
|
||||
KEYWORD_PUBLIC,
|
||||
KEYWORD_RETURN,
|
||||
KEYWORD_SHORT,
|
||||
KEYWORD_SIGNED,
|
||||
KEYWORD_STATIC,
|
||||
KEYWORD_SWITCH,
|
||||
KEYWORD_SIZEOF,
|
||||
KEYWORD_TEMPLATE,
|
||||
KEYWORD_THIS,
|
||||
KEYWORD_THROW,
|
||||
KEYWORD_TRY,
|
||||
KEYWORD_TYPEDEF,
|
||||
KEYWORD_TYPENAME,
|
||||
KEYWORD_UNSIGNED,
|
||||
KEYWORD_USING,
|
||||
KEYWORD_VIRTUAL,
|
||||
KEYWORD_VOID,
|
||||
KEYWORD_WHILE,
|
||||
|
||||
KEYWORD_COUNT
|
||||
};
|
||||
|
||||
QAsParser();
|
||||
explicit QAsParser(asIScriptEngine *engine);
|
||||
virtual ~QAsParser();
|
||||
|
||||
virtual QCodeLexer *lexer(QCodeStream *s);
|
||||
|
||||
virtual QString language() const;
|
||||
virtual bool canParse(const QString &fn) const;
|
||||
virtual void update(QCodeNode *n, QCodeLexer *src, bool check = true);
|
||||
|
||||
inline QCodeNode *getNode() { return QCodeParser::getNode(); }
|
||||
|
||||
void update(QCodeNode *n, QCodeLexer *l, QTokenList &tokens, int id,
|
||||
int end, bool bNeedCxt = true, QTokenList *ns = 0);
|
||||
public:
|
||||
bool parse(const QString &filename);
|
||||
|
||||
private:
|
||||
QString sContext;
|
||||
asIScriptEngine *_engine;
|
||||
|
||||
QScopedPointer<asCScriptCode> m_code;
|
||||
};
|
||||
|
||||
#endif // !_QCPP_PARSER_H_
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
#ifndef SETTING_H
|
||||
#define SETTING_H
|
||||
|
||||
#include <QApplication>
|
||||
#include <QSettings>
|
||||
|
||||
#define HANDLE_CONFIG \
|
||||
QSettings set(QStringLiteral(APP_ORG), QStringLiteral(APP_NAME))
|
||||
|
||||
#define CONFIG set
|
||||
|
||||
#define WRITE_CONFIG(config, dvalue) set.setValue(config, dvalue)
|
||||
|
||||
#define READ_CONFIG(config, dvalue) set.value(config, dvalue)
|
||||
|
||||
#define READ_CONFIG_SAFE(var, config, dvalue, func) \
|
||||
{ \
|
||||
auto b = false; \
|
||||
var = READ_CONFIG(config, dvalue).func(&b); \
|
||||
if (!b) { \
|
||||
var = dvalue; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_CONFIG_INT(var, config, dvalue) \
|
||||
READ_CONFIG_SAFE(var, config, dvalue, toInt)
|
||||
|
||||
#define READ_CONFIG_BOOL(var, config, dvalue) \
|
||||
var = READ_CONFIG(config, dvalue).toBool()
|
||||
|
||||
#define READ_CONFIG_QSIZETYPE(var, config, dvalue) \
|
||||
READ_CONFIG_SAFE(var, config, dvalue, toLongLong)
|
||||
|
||||
#define READ_CONFIG_INT_POSITIVE(var, config, dvalue) \
|
||||
{ \
|
||||
Q_ASSERT(dvalue > 0); \
|
||||
READ_CONFIG_SAFE(var, config, dvalue, toInt); \
|
||||
if (var <= 0) { \
|
||||
var = dvalue; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_CONFIG_DOUBLE_POSITIVE(var, config, dvalue) \
|
||||
{ \
|
||||
Q_ASSERT(dvalue > 0); \
|
||||
READ_CONFIG_SAFE(var, config, dvalue, toDouble); \
|
||||
if (var <= 0) { \
|
||||
var = dvalue; \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif // SETTING_H
|
|
@ -1,11 +1,60 @@
|
|||
#include "settingmanager.h"
|
||||
#include "setting.h"
|
||||
|
||||
#include "class/logger.h"
|
||||
#include "class/skinmanager.h"
|
||||
#include "utilities.h"
|
||||
#include <QFileInfo>
|
||||
#include <QMetaEnum>
|
||||
#include <QSettings>
|
||||
|
||||
#define HANDLE_CONFIG \
|
||||
QSettings set(QStringLiteral(APP_ORG), QStringLiteral(APP_NAME))
|
||||
|
||||
#define CONFIG set
|
||||
|
||||
#define WRITE_CONFIG(config, dvalue) \
|
||||
if (this->_setUnsaved.testFlag(SETTING_ITEM::config)) { \
|
||||
set.setValue(config, dvalue); \
|
||||
_setUnsaved.setFlag(SettingManager::SETTING_ITEM::config, false); \
|
||||
}
|
||||
|
||||
#define READ_CONFIG(config, dvalue) set.value(config, dvalue)
|
||||
|
||||
#define READ_CONFIG_SAFE(var, config, dvalue, func) \
|
||||
{ \
|
||||
auto b = false; \
|
||||
var = READ_CONFIG(config, dvalue).func(&b); \
|
||||
if (!b) { \
|
||||
var = dvalue; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_CONFIG_INT(var, config, dvalue) \
|
||||
READ_CONFIG_SAFE(var, config, dvalue, toInt)
|
||||
|
||||
#define READ_CONFIG_BOOL(var, config, dvalue) \
|
||||
var = READ_CONFIG(config, dvalue).toBool()
|
||||
|
||||
#define READ_CONFIG_QSIZETYPE(var, config, dvalue) \
|
||||
READ_CONFIG_SAFE(var, config, dvalue, toLongLong)
|
||||
|
||||
#define READ_CONFIG_INT_POSITIVE(var, config, dvalue) \
|
||||
{ \
|
||||
Q_ASSERT(dvalue > 0); \
|
||||
READ_CONFIG_SAFE(var, config, dvalue, toInt); \
|
||||
if (var <= 0) { \
|
||||
var = dvalue; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_CONFIG_DOUBLE_POSITIVE(var, config, dvalue) \
|
||||
{ \
|
||||
Q_ASSERT(dvalue > 0); \
|
||||
READ_CONFIG_SAFE(var, config, dvalue, toDouble); \
|
||||
if (var <= 0) { \
|
||||
var = dvalue; \
|
||||
} \
|
||||
}
|
||||
|
||||
const auto DOCK_LAYOUT = QStringLiteral("dock.layout");
|
||||
const auto SCRIPT_DOCK_LAYOUT = QStringLiteral("script.layout");
|
||||
|
@ -127,8 +176,6 @@ void SettingManager::load() {
|
|||
}
|
||||
}
|
||||
|
||||
emit sigAppFontFamilyChanged(m_appFontFamily);
|
||||
emit sigAppfontSizeChanged(m_appfontSize);
|
||||
emit sigEditorfontSizeChanged(m_editorfontSize);
|
||||
emit sigCopylimitChanged(m_copylimit);
|
||||
emit sigDecodeStrlimitChanged(m_decodeStrlimit);
|
||||
|
@ -159,25 +206,42 @@ bool SettingManager::allowUsrScriptInRoot() const {
|
|||
}
|
||||
|
||||
void SettingManager::setAllowUsrScriptInRoot(bool newAllowUsrScriptInRoot) {
|
||||
m_allowUsrScriptInRoot = newAllowUsrScriptInRoot;
|
||||
if (m_allowUsrScriptInRoot != newAllowUsrScriptInRoot) {
|
||||
m_allowUsrScriptInRoot = newAllowUsrScriptInRoot;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::SCRIPT_ALLOW_USRSCRIPT_INROOT);
|
||||
}
|
||||
}
|
||||
|
||||
void SettingManager::setUsrHideCats(const QStringList &newUsrHideCats) {
|
||||
m_usrHideCats = newUsrHideCats;
|
||||
if (m_usrHideCats != newUsrHideCats) {
|
||||
m_usrHideCats = newUsrHideCats;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::SCRIPT_USRHIDECATS);
|
||||
}
|
||||
}
|
||||
|
||||
void SettingManager::setSysHideCats(const QStringList &newSysHideCats) {
|
||||
m_sysHideCats = newSysHideCats;
|
||||
if (m_sysHideCats != newSysHideCats) {
|
||||
m_sysHideCats = newSysHideCats;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::SCRIPT_SYSHIDECATS);
|
||||
}
|
||||
}
|
||||
|
||||
int SettingManager::logLevel() const { return m_logLevel; }
|
||||
|
||||
void SettingManager::setLogLevel(int newLogLevel) { m_logLevel = newLogLevel; }
|
||||
void SettingManager::setLogLevel(int newLogLevel) {
|
||||
if (m_logLevel != newLogLevel) {
|
||||
m_logLevel = newLogLevel;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::OTHER_LOG_LEVEL);
|
||||
}
|
||||
}
|
||||
|
||||
bool SettingManager::useNativeTitleBar() const { return m_useNativeTitleBar; }
|
||||
|
||||
void SettingManager::setUseNativeTitleBar(bool newUseNativeTitleBar) {
|
||||
m_useNativeTitleBar = newUseNativeTitleBar;
|
||||
if (m_useNativeTitleBar != newUseNativeTitleBar) {
|
||||
m_useNativeTitleBar = newUseNativeTitleBar;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::OTHER_USE_NATIVE_TITLEBAR);
|
||||
}
|
||||
}
|
||||
|
||||
bool SettingManager::useNativeFileDialog() const {
|
||||
|
@ -185,7 +249,10 @@ bool SettingManager::useNativeFileDialog() const {
|
|||
}
|
||||
|
||||
void SettingManager::setUseNativeFileDialog(bool newUseNativeFileDialog) {
|
||||
m_useNativeFileDialog = newUseNativeFileDialog;
|
||||
if (m_useNativeFileDialog != newUseNativeFileDialog) {
|
||||
m_useNativeFileDialog = newUseNativeFileDialog;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::OTHER_USESYS_FILEDIALOG);
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray SettingManager::scriptDockLayout() const {
|
||||
|
@ -194,7 +261,10 @@ QByteArray SettingManager::scriptDockLayout() const {
|
|||
|
||||
void SettingManager::setScriptDockLayout(
|
||||
const QByteArray &newScriptDockLayout) {
|
||||
m_scriptDockLayout = newScriptDockLayout;
|
||||
if (m_scriptDockLayout != newScriptDockLayout) {
|
||||
m_scriptDockLayout = newScriptDockLayout;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::SCRIPT_DOCK_LAYOUT);
|
||||
}
|
||||
}
|
||||
|
||||
QStringList SettingManager::sysHideCats() const { return m_sysHideCats; }
|
||||
|
@ -207,7 +277,10 @@ QList<RecentFileManager::RecentInfo> SettingManager::recentScriptFiles() const {
|
|||
|
||||
void SettingManager::setRecentScriptFiles(
|
||||
const QList<RecentFileManager::RecentInfo> &newRecentScriptFiles) {
|
||||
m_recentScriptFiles = newRecentScriptFiles;
|
||||
if (m_recentScriptFiles != newRecentScriptFiles) {
|
||||
m_recentScriptFiles = newRecentScriptFiles;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::SCRIPT_RECENTFILES);
|
||||
}
|
||||
}
|
||||
|
||||
QString SettingManager::appFontFamily() const { return m_appFontFamily; }
|
||||
|
@ -215,20 +288,26 @@ QString SettingManager::appFontFamily() const { return m_appFontFamily; }
|
|||
void SettingManager::setAppFontFamily(const QString &newAppFontFamily) {
|
||||
if (m_appFontFamily != newAppFontFamily) {
|
||||
m_appFontFamily = newAppFontFamily;
|
||||
emit sigAppFontFamilyChanged(newAppFontFamily);
|
||||
_setUnsaved.setFlag(SETTING_ITEM::APP_FONTFAMILY);
|
||||
}
|
||||
}
|
||||
|
||||
bool SettingManager::editorShowHeader() const { return m_editorShowHeader; }
|
||||
|
||||
void SettingManager::setEditorShowHeader(bool newEditorShowAddr) {
|
||||
m_editorShowHeader = newEditorShowAddr;
|
||||
if (m_editorShowHeader != newEditorShowAddr) {
|
||||
m_editorShowHeader = newEditorShowAddr;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::EDITOR_SHOW_ADDR);
|
||||
}
|
||||
}
|
||||
|
||||
bool SettingManager::enablePlugin() const { return m_enablePlugin; }
|
||||
|
||||
void SettingManager::setEnablePlugin(bool newEnablePlugin) {
|
||||
m_enablePlugin = newEnablePlugin;
|
||||
if (m_enablePlugin != newEnablePlugin) {
|
||||
m_enablePlugin = newEnablePlugin;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::PLUGIN_ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
QList<RecentFileManager::RecentInfo> SettingManager::recentHexFiles() const {
|
||||
|
@ -237,7 +316,10 @@ QList<RecentFileManager::RecentInfo> SettingManager::recentHexFiles() const {
|
|||
|
||||
void SettingManager::setRecentFiles(
|
||||
const QList<RecentFileManager::RecentInfo> &newRecentFiles) {
|
||||
m_recentHexFiles = newRecentFiles;
|
||||
if (m_recentHexFiles != newRecentFiles) {
|
||||
m_recentHexFiles = newRecentFiles;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::EDITOR_RECENTFILES);
|
||||
}
|
||||
}
|
||||
|
||||
Qt::WindowState SettingManager::defaultWinState() const {
|
||||
|
@ -254,7 +336,10 @@ void SettingManager::setDefaultWinState(Qt::WindowState newDefaultWinState) {
|
|||
newDefaultWinState = Qt::WindowMaximized;
|
||||
break;
|
||||
}
|
||||
m_defaultWinState = newDefaultWinState;
|
||||
if (m_defaultWinState != newDefaultWinState) {
|
||||
m_defaultWinState = newDefaultWinState;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::APP_WINDOWSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
void SettingManager::save(SETTINGS cat) {
|
||||
|
@ -339,9 +424,11 @@ void SettingManager::reset(SETTINGS cat) {
|
|||
qsizetype SettingManager::decodeStrlimit() const { return m_decodeStrlimit; }
|
||||
|
||||
void SettingManager::setDecodeStrlimit(qsizetype newDecodeStrlimit) {
|
||||
newDecodeStrlimit =
|
||||
qBound(qsizetype(100), newDecodeStrlimit, qsizetype(1024));
|
||||
if (m_decodeStrlimit != newDecodeStrlimit) {
|
||||
m_decodeStrlimit =
|
||||
qBound(qsizetype(100), newDecodeStrlimit, qsizetype(1024));
|
||||
m_decodeStrlimit = newDecodeStrlimit;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::EDITOR_DECSTRLIMIT);
|
||||
emit sigDecodeStrlimitChanged(m_decodeStrlimit);
|
||||
}
|
||||
}
|
||||
|
@ -349,8 +436,10 @@ void SettingManager::setDecodeStrlimit(qsizetype newDecodeStrlimit) {
|
|||
qsizetype SettingManager::copylimit() const { return m_copylimit; }
|
||||
|
||||
void SettingManager::setCopylimit(qsizetype newCopylimit) {
|
||||
newCopylimit = qBound(qsizetype(100), newCopylimit, qsizetype(1024));
|
||||
if (m_copylimit != newCopylimit) {
|
||||
m_copylimit = qBound(qsizetype(100), newCopylimit, qsizetype(1024));
|
||||
m_copylimit = newCopylimit;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::EDITOR_COPY_LIMIT);
|
||||
emit sigDecodeStrlimitChanged(m_copylimit);
|
||||
}
|
||||
}
|
||||
|
@ -358,19 +447,28 @@ void SettingManager::setCopylimit(qsizetype newCopylimit) {
|
|||
QString SettingManager::editorEncoding() const { return m_editorEncoding; }
|
||||
|
||||
void SettingManager::setEditorEncoding(const QString &newEditorEncoding) {
|
||||
m_editorEncoding = newEditorEncoding;
|
||||
if (m_editorEncoding != newEditorEncoding) {
|
||||
m_editorEncoding = newEditorEncoding;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::EDITOR_ENCODING);
|
||||
}
|
||||
}
|
||||
|
||||
bool SettingManager::editorShowtext() const { return m_editorShowtext; }
|
||||
|
||||
void SettingManager::setEditorShowtext(bool newEditorShowtext) {
|
||||
m_editorShowtext = newEditorShowtext;
|
||||
if (m_editorShowtext != newEditorShowtext) {
|
||||
m_editorShowtext = newEditorShowtext;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::EDITOR_SHOW_TEXT);
|
||||
}
|
||||
}
|
||||
|
||||
bool SettingManager::editorShowcol() const { return m_editorShowcol; }
|
||||
|
||||
void SettingManager::setEditorShowcol(bool newEditorShowcol) {
|
||||
m_editorShowcol = newEditorShowcol;
|
||||
if (m_editorShowcol != newEditorShowcol) {
|
||||
m_editorShowcol = newEditorShowcol;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::EDITOR_SHOW_COL);
|
||||
}
|
||||
}
|
||||
|
||||
int SettingManager::editorfontSize() const { return m_editorfontSize; }
|
||||
|
@ -378,6 +476,7 @@ int SettingManager::editorfontSize() const { return m_editorfontSize; }
|
|||
void SettingManager::setEditorfontSize(int newEditorfontSize) {
|
||||
if (m_editorfontSize != newEditorfontSize) {
|
||||
m_editorfontSize = newEditorfontSize;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::EDITOR_FONTSIZE);
|
||||
emit sigEditorfontSizeChanged(newEditorfontSize);
|
||||
}
|
||||
}
|
||||
|
@ -387,20 +486,26 @@ int SettingManager::appfontSize() const { return m_appfontSize; }
|
|||
void SettingManager::setAppfontSize(int newAppfontSize) {
|
||||
if (m_appfontSize != newAppfontSize) {
|
||||
m_appfontSize = newAppfontSize;
|
||||
emit sigAppfontSizeChanged(newAppfontSize);
|
||||
_setUnsaved.setFlag(SETTING_ITEM::APP_FONTSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
bool SettingManager::enablePlgInRoot() const { return m_enablePlgInRoot; }
|
||||
|
||||
void SettingManager::setEnablePlgInRoot(bool newEnablePlgInRoot) {
|
||||
m_enablePlgInRoot = newEnablePlgInRoot;
|
||||
if (m_enablePlgInRoot != newEnablePlgInRoot) {
|
||||
m_enablePlgInRoot = newEnablePlgInRoot;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::PLUGIN_ENABLE_ROOT);
|
||||
}
|
||||
}
|
||||
|
||||
QString SettingManager::defaultLang() const { return m_defaultLang; }
|
||||
|
||||
void SettingManager::setDefaultLang(const QString &newDefaultLang) {
|
||||
m_defaultLang = newDefaultLang;
|
||||
if (m_defaultLang != newDefaultLang) {
|
||||
m_defaultLang = newDefaultLang;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::APP_LANGUAGE);
|
||||
}
|
||||
}
|
||||
|
||||
SettingManager &SettingManager::instance() {
|
||||
|
@ -413,9 +518,17 @@ SettingManager::~SettingManager() {}
|
|||
QByteArray SettingManager::dockLayout() const { return m_dockLayout; }
|
||||
|
||||
void SettingManager::setDockLayout(const QByteArray &newDockLayout) {
|
||||
m_dockLayout = newDockLayout;
|
||||
if (m_dockLayout != newDockLayout) {
|
||||
m_dockLayout = newDockLayout;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::DOCK_LAYOUT);
|
||||
}
|
||||
}
|
||||
|
||||
int SettingManager::themeID() const { return m_themeID; }
|
||||
|
||||
void SettingManager::setThemeID(int newThemeID) { m_themeID = newThemeID; }
|
||||
void SettingManager::setThemeID(int newThemeID) {
|
||||
if (m_themeID != newThemeID) {
|
||||
m_themeID = newThemeID;
|
||||
_setUnsaved.setFlag(SETTING_ITEM::SKIN_THEME);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,40 @@ public:
|
|||
ALL = APP | PLUGIN | EDITOR | SCRIPT | OTHER
|
||||
};
|
||||
Q_DECLARE_FLAGS(SETTINGS, SETTING)
|
||||
private:
|
||||
// Flags to indicate whether the modification has been made.
|
||||
// There are a maximum of 32 flags,
|
||||
// but it is impossible to have more than this.
|
||||
enum class SETTING_ITEM : quint32 {
|
||||
DOCK_LAYOUT = 1u,
|
||||
SCRIPT_DOCK_LAYOUT = 1u << 1,
|
||||
APP_LASTUSED_PATH = 1u << 2,
|
||||
SKIN_THEME = 1u << 3,
|
||||
APP_FONTFAMILY = 1u << 4,
|
||||
APP_FONTSIZE = 1u << 5,
|
||||
APP_WINDOWSIZE = 1u << 6,
|
||||
APP_LANGUAGE = 1u << 7,
|
||||
PLUGIN_ENABLE = 1u << 8,
|
||||
PLUGIN_ENABLE_ROOT = 1u << 9,
|
||||
EDITOR_FONTSIZE = 1u << 10,
|
||||
EDITOR_SHOW_ADDR = 1u << 11,
|
||||
EDITOR_SHOW_COL = 1u << 12,
|
||||
EDITOR_SHOW_TEXT = 1u << 13,
|
||||
EDITOR_ENCODING = 1u << 14,
|
||||
EDITOR_FIND_MAXCOUNT = 1u << 15,
|
||||
EDITOR_COPY_LIMIT = 1u << 16,
|
||||
EDITOR_DECSTRLIMIT = 1u << 17,
|
||||
EDITOR_RECENTFILES = 1u << 18,
|
||||
SCRIPT_RECENTFILES = 1u << 19,
|
||||
SCRIPT_ALLOW_USRSCRIPT_INROOT = 1u << 20,
|
||||
SCRIPT_USRHIDECATS = 1u << 21,
|
||||
SCRIPT_SYSHIDECATS = 1u << 22,
|
||||
OTHER_USESYS_FILEDIALOG = 1u << 23,
|
||||
OTHER_USE_NATIVE_TITLEBAR = 1u << 24,
|
||||
OTHER_LOG_LEVEL = 1u << 25
|
||||
};
|
||||
Q_DECLARE_FLAGS(SETTING_ITEMS, SETTING_ITEM)
|
||||
|
||||
public:
|
||||
static SettingManager &instance();
|
||||
|
||||
|
@ -113,9 +147,6 @@ signals:
|
|||
void sigDecodeStrlimitChanged(int v);
|
||||
void sigCopylimitChanged(int v);
|
||||
|
||||
void sigAppfontSizeChanged(int v);
|
||||
void sigAppFontFamilyChanged(const QString &font);
|
||||
|
||||
void logLevelChanged();
|
||||
|
||||
private:
|
||||
|
@ -164,6 +195,7 @@ private:
|
|||
|
||||
private:
|
||||
QFont _defaultFont;
|
||||
SETTING_ITEMS _setUnsaved;
|
||||
};
|
||||
|
||||
#endif // SETTINGMANAGER_H
|
||||
|
|
|
@ -18,21 +18,8 @@
|
|||
|
||||
#include <qglobal.h>
|
||||
|
||||
/*!
|
||||
\macro QCM_EXPORT
|
||||
Allow a cross-platform and sure possibility to link in static or dynamic
|
||||
way, depending to what's needed...
|
||||
*/
|
||||
#ifdef _QCODE_MODEL_BUILD_DLL_
|
||||
#if (defined(QT_SHARED) || defined(QT_DLL)) && !defined(QT_PLUGIN)
|
||||
#define QCM_EXPORT Q_DECL_EXPORT
|
||||
#endif
|
||||
#else
|
||||
#ifdef _QCODE_MODEL_BUILD_STATIC_
|
||||
#ifndef QCM_EXPORT
|
||||
#define QCM_EXPORT
|
||||
#else
|
||||
#define QCM_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class QByteArray;
|
|
@ -20,9 +20,7 @@
|
|||
\brief Implementation of the QCodeModel class.
|
||||
*/
|
||||
|
||||
#include "qcodeloader.h"
|
||||
#include "qcodenode.h"
|
||||
#include "qcodeparser.h"
|
||||
|
||||
#define Q_EXTRACT_INDEX(i, d) \
|
||||
QCodeNode *d = static_cast<QCodeNode *>(i.internalPointer());
|
||||
|
@ -60,7 +58,7 @@ void QCodeModel::q_uncache(QCodeNode *n, QByteArray cxt = QByteArray()) {
|
|||
/*!
|
||||
\brief ctor
|
||||
*/
|
||||
QCodeModel::QCodeModel(QObject *p) : QAbstractItemModel(p), m_loader(0) {}
|
||||
QCodeModel::QCodeModel(QObject *p) : QAbstractItemModel(p) {}
|
||||
|
||||
/*!
|
||||
\brief dtor
|
||||
|
@ -73,67 +71,6 @@ QCodeModel::~QCodeModel() { clearTopLevelNodes(); }
|
|||
*/
|
||||
QList<QCodeNode *> QCodeModel::topLevelNodes() const { return m_topLevel; }
|
||||
|
||||
/*!
|
||||
\return The current code loader used by this model
|
||||
*/
|
||||
QCodeLoader *QCodeModel::codeLoader() const { return m_loader; }
|
||||
|
||||
/*!
|
||||
\brief Set the code loader used by this model
|
||||
*/
|
||||
void QCodeModel::setCodeLoader(QCodeLoader *p) { m_loader = p; }
|
||||
|
||||
/*!
|
||||
\brief Update a file within a group
|
||||
\param group group of files to remove (as passed to addGroup())
|
||||
\param file file to update
|
||||
*/
|
||||
void QCodeModel::updateGroup(const QString &group, const QString &file) {
|
||||
QByteArray grp = group.toLocal8Bit();
|
||||
|
||||
foreach (QCodeNode *n, m_topLevel) {
|
||||
// qDebug("group %s ?", n->context().constData());
|
||||
|
||||
if (n->role(QCodeNode::Context) == grp) {
|
||||
m_loader->update(n, file);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// qDebug("group %s not found", qPrintable(group));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Add a group of files of whathever type (typically from a project)
|
||||
\param group group of files to add
|
||||
\param files list of files to load to populate the tree
|
||||
*/
|
||||
void QCodeModel::addGroup(const QString &group, const QStringList &files) {
|
||||
if (!m_loader)
|
||||
return;
|
||||
|
||||
foreach (QCodeNode *n, m_topLevel)
|
||||
if (n->context() == group)
|
||||
return;
|
||||
|
||||
// qDebug("loading %i files into group %s", files.count(),
|
||||
// qPrintable(group));
|
||||
m_loader->load(group, files, this);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Remove a group of files from the model
|
||||
\param group group of files to remove (as passed to addGroup())
|
||||
*/
|
||||
void QCodeModel::removeGroup(const QString &group) {
|
||||
foreach (QCodeNode *n, m_topLevel) {
|
||||
if (n->role(QCodeNode::Context) == group) {
|
||||
removeTopLevelNode(n);
|
||||
delete n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Please read Qt docs on Model/View framework for more informations
|
||||
*/
|
||||
|
@ -343,7 +280,8 @@ bool QCodeModel::isCachable(QCodeNode *n, QByteArray &cxt) const {
|
|||
cxt += qn;
|
||||
|
||||
return true;
|
||||
} else if ((t == QCodeNode::Enum) || (t == QCodeNode::Class) ||
|
||||
} else if ((t == QCodeNode::Enum) || (t == QCodeNode::Union) ||
|
||||
(t == QCodeNode::Class) || (t == QCodeNode::Struct) ||
|
||||
(t == QCodeNode::Typedef)) {
|
||||
cxt += qn;
|
||||
|
|
@ -23,8 +23,6 @@
|
|||
#include <QStack>
|
||||
|
||||
struct QCodeNode;
|
||||
class QCodeParser;
|
||||
class QCodeLoader;
|
||||
|
||||
class QCM_EXPORT QCodeModel : public QAbstractItemModel {
|
||||
Q_OBJECT
|
||||
|
@ -34,7 +32,7 @@ class QCM_EXPORT QCodeModel : public QAbstractItemModel {
|
|||
public:
|
||||
enum ExtraRoles { TypeRole = Qt::UserRole, VisibilityRole };
|
||||
|
||||
QCodeModel(QObject *p = 0);
|
||||
QCodeModel(QObject *p = nullptr);
|
||||
virtual ~QCodeModel();
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
|
@ -64,14 +62,6 @@ public:
|
|||
|
||||
virtual bool isCachable(QCodeNode *n, QByteArray &cxt) const;
|
||||
|
||||
QCodeLoader *codeLoader() const;
|
||||
void setCodeLoader(QCodeLoader *p);
|
||||
|
||||
public slots:
|
||||
void updateGroup(const QString &group, const QString &file);
|
||||
void addGroup(const QString &group, const QStringList &files);
|
||||
void removeGroup(const QString &group);
|
||||
|
||||
protected:
|
||||
void beginInsertRows(const QModelIndex idx, int beg, int end);
|
||||
void beginRemoveRows(const QModelIndex idx, int beg, int end);
|
||||
|
@ -94,8 +84,6 @@ private:
|
|||
|
||||
QList<QCodeNode *> m_topLevel;
|
||||
|
||||
QCodeLoader *m_loader;
|
||||
|
||||
QStack<CacheOp> m_cache_ops;
|
||||
QHash<QByteArray, QCodeNode *> m_cache;
|
||||
};
|
|
@ -23,10 +23,17 @@
|
|||
|
||||
#include "qsourcecodewatcher.h"
|
||||
|
||||
/*
|
||||
|
||||
|
||||
|
||||
*/
|
||||
enum CacheIndex {
|
||||
ICON_ENUM,
|
||||
ICON_ENUMERATOR,
|
||||
ICON_UNION,
|
||||
ICON_CLASS,
|
||||
ICON_STRUCT,
|
||||
ICON_TYPEDEF,
|
||||
ICON_NAMESPACE,
|
||||
ICON_FUNCTION = ICON_NAMESPACE + 2,
|
||||
|
@ -39,11 +46,15 @@ static QIcon icon(int cacheIndex) {
|
|||
static bool setup = false;
|
||||
|
||||
if (!setup) {
|
||||
q_icon_cache[ICON_UNION] = QIcon(":/completion/CVunion.png");
|
||||
|
||||
q_icon_cache[ICON_ENUM] = QIcon(":/completion/CVenum.png");
|
||||
q_icon_cache[ICON_ENUMERATOR] = QIcon(":/completion/CVenumerator.png");
|
||||
|
||||
q_icon_cache[ICON_CLASS] = QIcon(":/completion/CVclass.png");
|
||||
|
||||
q_icon_cache[ICON_STRUCT] = QIcon(":/completion/CVstruct.png");
|
||||
|
||||
q_icon_cache[ICON_TYPEDEF] = QIcon(":/completion/CVtypedef.png");
|
||||
|
||||
q_icon_cache[ICON_NAMESPACE] = QIcon(":/completion/CVnamespace.png");
|
||||
|
@ -60,6 +71,9 @@ static QIcon icon(int cacheIndex) {
|
|||
q_icon_cache[ICON_FUNCTION + QCodeNode::VISIBILITY_PRIVATE] =
|
||||
QIcon(":/completion/CVprivate_meth.png");
|
||||
|
||||
q_icon_cache[ICON_FUNCTION + QCodeNode::VISIBILITY_SIGNAL] =
|
||||
QIcon(":/completion/CVprotected_signal.png");
|
||||
|
||||
q_icon_cache[ICON_VARIABLE + QCodeNode::VISIBILITY_DEFAULT] =
|
||||
QIcon(":/completion/CVglobal_var.png");
|
||||
|
||||
|
@ -349,12 +363,27 @@ QVariant QCodeNode::data(int r) const {
|
|||
return d;
|
||||
}
|
||||
|
||||
case Struct: {
|
||||
QByteArray d("struct ");
|
||||
d += role(Name);
|
||||
|
||||
QByteArray a = role(Ancestors);
|
||||
|
||||
if (a.length())
|
||||
d += " : " + a;
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
case Enum:
|
||||
return QByteArray("enum ") + role(Name);
|
||||
|
||||
case Enumerator:
|
||||
return role(Name) + " = " + role(Value);
|
||||
|
||||
case Union:
|
||||
return QByteArray("union ") + role(Name);
|
||||
|
||||
case Namespace:
|
||||
return QByteArray("namespace ") + role(Name);
|
||||
|
||||
|
@ -382,12 +411,20 @@ QVariant QCodeNode::data(int r) const {
|
|||
// storage class
|
||||
if (m_specifiers & QCodeNode::SPECIFIER_AUTO)
|
||||
specifier += " auto ";
|
||||
else if (m_specifiers & QCodeNode::SPECIFIER_REGISTER)
|
||||
specifier += " register ";
|
||||
else if (m_specifiers & QCodeNode::SPECIFIER_STATIC)
|
||||
specifier += " static ";
|
||||
else if (m_specifiers & QCodeNode::SPECIFIER_EXTERN)
|
||||
specifier += " extern ";
|
||||
else if (m_specifiers & QCodeNode::SPECIFIER_MUTABLE)
|
||||
specifier += " mutable ";
|
||||
|
||||
// cv qualifier (for class members)
|
||||
if (m_specifiers & QCodeNode::SPECIFIER_CONST)
|
||||
specifier += " const ";
|
||||
else if (m_specifiers & QCodeNode::SPECIFIER_VOLATILE)
|
||||
specifier += " volatile ";
|
||||
|
||||
if (specifier.length())
|
||||
signature += " [" + specifier.simplified() + "]";
|
||||
|
@ -412,6 +449,17 @@ QVariant QCodeNode::data(int r) const {
|
|||
|
||||
if (m_qualifiers & QCodeNode::QUALIFIER_CONST)
|
||||
qualifier += " const ";
|
||||
else if (m_qualifiers & QCodeNode::QUALIFIER_VOLATILE)
|
||||
qualifier += " volatile ";
|
||||
else if (m_qualifiers & QCodeNode::QUALIFIER_STATIC)
|
||||
qualifier += " static ";
|
||||
|
||||
if (m_qualifiers & QCodeNode::QUALIFIER_PURE_VIRTUAL)
|
||||
qualifier.prepend(" pure virtual ");
|
||||
else if (m_qualifiers & QCodeNode::QUALIFIER_INLINE)
|
||||
qualifier.prepend(" inline ");
|
||||
else if (m_qualifiers & QCodeNode::QUALIFIER_VIRTUAL)
|
||||
qualifier.prepend(" virtual ");
|
||||
|
||||
int m_visibility = role(Visibility).toInt();
|
||||
|
||||
|
@ -419,6 +467,8 @@ QVariant QCodeNode::data(int r) const {
|
|||
qualifier.prepend(" public ");
|
||||
else if (m_visibility == QCodeNode::VISIBILITY_PROTECTED)
|
||||
qualifier.prepend(" protected ");
|
||||
else if (m_visibility == QCodeNode::VISIBILITY_SIGNAL)
|
||||
qualifier.prepend(" signal ");
|
||||
else if (m_visibility == QCodeNode::VISIBILITY_PRIVATE)
|
||||
qualifier.prepend(" private ");
|
||||
else
|
||||
|
@ -450,12 +500,18 @@ QVariant QCodeNode::data(int r) const {
|
|||
case Class:
|
||||
return icon(ICON_CLASS);
|
||||
|
||||
case Struct:
|
||||
return icon(ICON_STRUCT);
|
||||
|
||||
case Enum:
|
||||
return icon(ICON_ENUM);
|
||||
|
||||
case Enumerator:
|
||||
return icon(ICON_ENUMERATOR);
|
||||
|
||||
case Union:
|
||||
return icon(ICON_UNION);
|
||||
|
||||
case Namespace:
|
||||
return icon(ICON_NAMESPACE);
|
||||
|
|
@ -62,6 +62,7 @@ struct QCM_EXPORT QCodeNode {
|
|||
Language = 'l',
|
||||
|
||||
Class = 'c',
|
||||
Struct = 's',
|
||||
|
||||
Function = 'f',
|
||||
|
||||
|
@ -70,6 +71,8 @@ struct QCM_EXPORT QCodeNode {
|
|||
Enum = 'e',
|
||||
Enumerator = 'r',
|
||||
|
||||
Union = 'u',
|
||||
|
||||
Namespace = 'n',
|
||||
|
||||
Typedef = 't'
|
||||
|
@ -84,6 +87,7 @@ struct QCM_EXPORT QCodeNode {
|
|||
enum NodeVisibility {
|
||||
VISIBILITY_DEFAULT = -1,
|
||||
VISIBILITY_PUBLIC,
|
||||
VISIBILITY_SIGNAL,
|
||||
VISIBILITY_PROTECTED,
|
||||
VISIBILITY_PRIVATE
|
||||
};
|
||||
|
@ -91,7 +95,11 @@ struct QCM_EXPORT QCodeNode {
|
|||
enum Specifier {
|
||||
SPECIFIER_NONE = 0,
|
||||
SPECIFIER_CONST = 1,
|
||||
SPECIFIER_VOLATILE = 2,
|
||||
SPECIFIER_MUTABLE = 4,
|
||||
SPECIFIER_AUTO = 8,
|
||||
SPECIFIER_STATIC = 16,
|
||||
SPECIFIER_REGISTER = 32,
|
||||
SPECIFIER_EXTERN = 64
|
||||
};
|
||||
|
||||
|
@ -100,8 +108,12 @@ struct QCM_EXPORT QCodeNode {
|
|||
enum Qualifier {
|
||||
QUALIFIER_NONE = 0,
|
||||
QUALIFIER_CONST = 1,
|
||||
QUALIFIER_ABSTRACT = 2,
|
||||
QUALIFIER_EXTERN = 8
|
||||
QUALIFIER_VOLATILE = 2,
|
||||
QUALIFIER_STATIC = 4,
|
||||
QUALIFIER_EXTERN = 8,
|
||||
QUALIFIER_VIRTUAL = 16,
|
||||
QUALIFIER_PURE_VIRTUAL = 32,
|
||||
QUALIFIER_INLINE = 64
|
||||
};
|
||||
|
||||
typedef QFlags<Qualifier> FunctionQualifier;
|
|
@ -26,6 +26,7 @@
|
|||
static QList<int> priority = QList<int>()
|
||||
<< QCodeNode::Group << QCodeNode::Language
|
||||
<< QCodeNode::Namespace << QCodeNode::Class
|
||||
<< QCodeNode::Struct << QCodeNode::Union
|
||||
<< QCodeNode::Enum << QCodeNode::Typedef
|
||||
<< QCodeNode::Function << QCodeNode::Variable;
|
||||
|
|
@ -13,31 +13,28 @@
|
|||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _QCODE_BUFFER_H_
|
||||
#define _QCODE_BUFFER_H_
|
||||
#ifndef _QCODE_PROXY_MODEL_H_
|
||||
#define _QCODE_PROXY_MODEL_H_
|
||||
|
||||
#include "qcodestream.h"
|
||||
#include "qcm-config.h"
|
||||
|
||||
/*!
|
||||
\file qcodebuffer.h
|
||||
\brief Definition of the QCodeBuffer class.
|
||||
\file qcodeproxymodel.h
|
||||
\brief Definition of the QCodeProxyModel class.
|
||||
*/
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
class QCM_EXPORT QCodeProxyModel : public QSortFilterProxyModel {
|
||||
Q_OBJECT
|
||||
|
||||
class QCM_EXPORT QCodeBuffer : public QCodeStream {
|
||||
public:
|
||||
QCodeBuffer(const QString &s);
|
||||
QCodeBuffer(const QByteArray &s);
|
||||
QCodeProxyModel(QObject *p = nullptr);
|
||||
virtual ~QCodeProxyModel();
|
||||
|
||||
virtual char getChar();
|
||||
virtual void ungetChar(char c);
|
||||
|
||||
virtual QByteArray readLine();
|
||||
|
||||
private:
|
||||
int iPos;
|
||||
QByteArray sBuffer;
|
||||
protected:
|
||||
virtual bool lessThan(const QModelIndex &left,
|
||||
const QModelIndex &right) const;
|
||||
};
|
||||
|
||||
#endif // _QCODE_BUFFER_H_
|
||||
#endif // !_QCODE_PROXY_MODEL_H_
|
|
@ -98,7 +98,9 @@ void QCodeSerializer::deserialize(QIODevice *device, bool *ok, QString *source,
|
|||
QCodeNode *n, *previous = 0, *parent = 0;
|
||||
|
||||
line = device->readLine();
|
||||
|
||||
auto match = header_matcher.match(line);
|
||||
|
||||
if (!match.hasMatch()) {
|
||||
qWarning("Header mismatch : %s", line.constData());
|
||||
|
|
@ -31,8 +31,8 @@ class QCM_EXPORT QCodeView : public QTreeView {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QCodeView(QWidget *p = 0);
|
||||
QCodeView(QCodeModel *m, QWidget *p = 0);
|
||||
QCodeView(QWidget *p = nullptr);
|
||||
QCodeView(QCodeModel *m, QWidget *p = nullptr);
|
||||
virtual ~QCodeView();
|
||||
|
||||
virtual void setModel(QAbstractItemModel *model);
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
#include "qcodemodel.h"
|
||||
#include "qcodenode.h"
|
||||
#include "qcodeparser.h"
|
||||
|
||||
#include <QTimerEvent>
|
||||
|
||||
|
@ -68,7 +67,8 @@ void QSourceCodeWatcher::timerEvent(QTimerEvent *e) {
|
|||
++it;
|
||||
} else {
|
||||
// process
|
||||
m_parser->update(m_target, it.key());
|
||||
// m_parser->update(m_target, it.key());
|
||||
// TODO
|
||||
it = m_state.erase(it);
|
||||
}
|
||||
}
|
|
@ -1,17 +1,17 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
|
||||
**
|
||||
** This file is part of the Edyuk project <http://edyuk.org>
|
||||
**
|
||||
** This file may be used under the terms of the GNU General Public License
|
||||
** version 3 as published by the Free Software Foundation and appearing in the
|
||||
** file GPL.txt included in the packaging of this file.
|
||||
**
|
||||
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
**
|
||||
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
|
||||
**
|
||||
** This file is part of the Edyuk project <http://edyuk.org>
|
||||
**
|
||||
** This file may be used under the terms of the GNU General Public License
|
||||
** version 3 as published by the Free Software Foundation and appearing in the
|
||||
** file GPL.txt included in the packaging of this file.
|
||||
**
|
||||
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
||||
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _QSOURCE_CODE_WATCHER_H_
|
||||
#define _QSOURCE_CODE_WATCHER_H_
|
|
@ -22,8 +22,8 @@
|
|||
#include "qdocumentline.h"
|
||||
#include "qeditor.h"
|
||||
|
||||
#include "qcodemodel.h"
|
||||
#include "qcodenode.h"
|
||||
#include "codemodel/qcodemodel.h"
|
||||
#include "codemodel/qcodenode.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QFocusEvent>
|
||||
|
@ -32,7 +32,7 @@
|
|||
#include <QScrollBar>
|
||||
|
||||
QCodeCompletionWidget::QCodeCompletionWidget(QEditor *p)
|
||||
: QListView(0), offset(0) {
|
||||
: QListView(nullptr), offset(0) {
|
||||
// setWindowFlags(Qt::FramelessWindowHint | Qt::SubWindow);
|
||||
setBatchSize(10);
|
||||
setMovement(Static);
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include <QListView>
|
||||
#include <QPointer>
|
||||
|
||||
#include "qcodenode.h"
|
||||
#include "codemodel/qcodenode.h"
|
||||
#include "qdocumentcursor.h"
|
||||
#include "qeditor.h"
|
||||
|
||||
|
@ -60,7 +60,7 @@ public:
|
|||
|
||||
typedef QFlags<FilterFlag> Filter;
|
||||
|
||||
QCodeCompletionWidget(QEditor *p = 0);
|
||||
QCodeCompletionWidget(QEditor *p = nullptr);
|
||||
|
||||
QEditor *editor() const;
|
||||
void setEditor(QEditor *e);
|
||||
|
|
|
@ -1119,24 +1119,35 @@ RibbonTabContent *MainWindow::buildAboutPage(RibbonTabContent *tab) {
|
|||
void MainWindow::buildUpSettingDialog() {
|
||||
m_setdialog = new SettingDialog(this);
|
||||
auto generalPage = new GeneralSettingDialog(m_setdialog);
|
||||
connect(generalPage, &SettingPage::optionNeedRestartChanged, m_setdialog,
|
||||
&SettingDialog::toastTakeEffectReboot);
|
||||
m_setdialog->addPage(generalPage);
|
||||
auto editorPage = new EditorSettingDialog(m_setdialog);
|
||||
connect(editorPage, &SettingPage::optionNeedRestartChanged, m_setdialog,
|
||||
&SettingDialog::toastTakeEffectReboot);
|
||||
m_setdialog->addPage(editorPage);
|
||||
auto plgPage = new PluginSettingDialog(m_setdialog);
|
||||
connect(plgPage, &SettingPage::optionNeedRestartChanged, m_setdialog,
|
||||
&SettingDialog::toastTakeEffectReboot);
|
||||
plgPage->buildUp(m_settingPages);
|
||||
m_setdialog->addPage(plgPage);
|
||||
|
||||
auto scriptPage = new ScriptSettingDialog(m_setdialog);
|
||||
|
||||
connect(scriptPage, &SettingPage::optionNeedRestartChanged, m_setdialog,
|
||||
&SettingDialog::toastTakeEffectReboot);
|
||||
m_setdialog->addPage(scriptPage);
|
||||
|
||||
for (auto &page : m_settingPages) {
|
||||
if (!page->isInPluginPage()) {
|
||||
connect(page, &SettingPage::optionNeedRestartChanged, m_setdialog,
|
||||
&SettingDialog::toastTakeEffectReboot);
|
||||
m_setdialog->addPage(page);
|
||||
}
|
||||
}
|
||||
|
||||
auto otherPage = new OtherSettingsDialog(m_setdialog);
|
||||
connect(otherPage, &SettingPage::optionNeedRestartChanged, m_setdialog,
|
||||
&SettingDialog::toastTakeEffectReboot);
|
||||
m_setdialog->addPage(otherPage);
|
||||
|
||||
m_setdialog->build();
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "aboutsoftwaredialog.h"
|
||||
#include "class/ascompletion.h"
|
||||
#include "class/languagemanager.h"
|
||||
#include "class/qasparser.h"
|
||||
#include "class/qkeysequences.h"
|
||||
#include "class/settingmanager.h"
|
||||
#include "class/skinmanager.h"
|
||||
|
@ -12,8 +13,6 @@
|
|||
#include "class/wingmessagebox.h"
|
||||
#include "control/toast.h"
|
||||
#include "qcodeeditwidget/qeditconfig.h"
|
||||
#include "qcodeloader.h"
|
||||
#include "qcodemodel.h"
|
||||
#include "qdocumentline.h"
|
||||
#include "qeditor.h"
|
||||
#include "qformatscheme.h"
|
||||
|
@ -77,21 +76,9 @@ ScriptingDialog::ScriptingDialog(QWidget *parent)
|
|||
}
|
||||
QDocument::setDefaultFormatScheme(format);
|
||||
|
||||
m_codeModel = new QCodeModel(this);
|
||||
m_codeModel->setCodeLoader(new QCodeLoader(this));
|
||||
|
||||
// m_codeProxy = new QCodeProxyModel(this);
|
||||
// m_codeProxy->setSourceModel(m_codeModel);
|
||||
// m_codeProxy->setDynamicSortFilter(true);
|
||||
|
||||
// m_codeView = new QCodeView(this);
|
||||
// m_codeView->setModel(m_codeProxy);
|
||||
// m_codeView->setSortingEnabled(true);
|
||||
// m_codeView->header()->hide();
|
||||
|
||||
m_language = new QLanguageFactory(format, this);
|
||||
m_language->addDefinitionPath(QStringLiteral(":/qcodeedit"));
|
||||
m_language->addCompletionEngine(new AsCompletion(m_codeModel, this));
|
||||
m_language->addCompletionEngine(new AsCompletion(this));
|
||||
|
||||
auto lmic = QLineMarksInfoCenter::instance();
|
||||
lmic->loadMarkTypes(QCE::fetchDataFile(":/qcodeedit/marks.qxm"));
|
||||
|
@ -1047,6 +1034,10 @@ void ScriptingDialog::on_openfile() {
|
|||
if (!filename.isEmpty()) {
|
||||
m_lastusedpath = QFileInfo(filename).absoluteDir().absolutePath();
|
||||
openFile(filename);
|
||||
|
||||
// TODO test
|
||||
// QAsParser parser(m_consoleout->machine()->engine());
|
||||
// parser.parse(filename);
|
||||
}
|
||||
|
||||
RecentFileManager::RecentInfo info;
|
||||
|
|
|
@ -14,8 +14,6 @@
|
|||
#include "model/dbgbreakpointmodel.h"
|
||||
#include "model/dbgcallstackmodel.h"
|
||||
#include "model/dbgvarshowmodel.h"
|
||||
#include "qcodeproxymodel.h"
|
||||
#include "qcodeview.h"
|
||||
#include "qlanguagefactory.h"
|
||||
#include "utilities.h"
|
||||
|
||||
|
@ -235,9 +233,7 @@ private:
|
|||
ads::CDockManager *m_dock = nullptr;
|
||||
ads::CDockAreaWidget *m_editorViewArea = nullptr;
|
||||
QLanguageFactory *m_language = nullptr;
|
||||
QCodeView *m_codeView = nullptr;
|
||||
QCodeModel *m_codeModel = nullptr;
|
||||
QCodeProxyModel *m_codeProxy = nullptr;
|
||||
|
||||
QByteArray _defaultLayout;
|
||||
|
||||
ScriptEditor *m_curEditor = nullptr;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "ui_settingdialog.h"
|
||||
|
||||
#include "class/wingmessagebox.h"
|
||||
#include "control/toast.h"
|
||||
#include "utilities.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
@ -57,6 +58,17 @@ void SettingDialog::showConfig(int index) {
|
|||
_dialog->exec();
|
||||
}
|
||||
|
||||
void SettingDialog::toastTakeEffectReboot() {
|
||||
auto page = qobject_cast<WingHex::SettingPage *>(sender());
|
||||
if (page) {
|
||||
auto icon = page->categoryIcon();
|
||||
auto avsize = icon.availableSizes();
|
||||
Q_ASSERT(!avsize.isEmpty());
|
||||
Toast::toast(_dialog, icon.pixmap(avsize.first()),
|
||||
tr("TakeEffectRestart"));
|
||||
}
|
||||
}
|
||||
|
||||
void SettingDialog::on_buttonBox_clicked(QAbstractButton *button) {
|
||||
auto btnbox = ui->buttonBox;
|
||||
if (button == btnbox->button(QDialogButtonBox::Ok)) {
|
||||
|
|
|
@ -20,6 +20,9 @@ public:
|
|||
void build(); // you can only call once
|
||||
void showConfig(int index = -1);
|
||||
|
||||
public slots:
|
||||
void toastTakeEffectReboot();
|
||||
|
||||
private slots:
|
||||
void on_buttonBox_clicked(QAbstractButton *button);
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
namespace WingHex {
|
||||
|
||||
Q_DECL_UNUSED constexpr auto SDKVERSION = 12;
|
||||
Q_DECL_UNUSED constexpr auto SDKVERSION = 13;
|
||||
|
||||
Q_DECL_UNUSED static QString GETPLUGINQM(const QString &name) {
|
||||
return QCoreApplication::applicationDirPath() +
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
#include "settingpage.h"
|
||||
|
||||
using namespace WingHex;
|
||||
|
||||
SettingPage::SettingPage(QWidget *parent) : QWidget(parent) {}
|
|
@ -8,7 +8,10 @@ namespace WingHex {
|
|||
class SettingPage : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SettingPage(QWidget *parent = nullptr);
|
||||
explicit SettingPage(QWidget *parent = nullptr) : QWidget(parent) {}
|
||||
|
||||
signals:
|
||||
void optionNeedRestartChanged();
|
||||
|
||||
public:
|
||||
virtual QIcon categoryIcon() const = 0;
|
||||
|
|
|
@ -5,6 +5,7 @@ void RegisterColor(asIScriptEngine *engine) {
|
|||
// Register the QColor type
|
||||
int r = engine->RegisterObjectType("color", sizeof(QColor),
|
||||
asOBJ_VALUE | asOBJ_POD |
|
||||
asOBJ_APP_CLASS_ALLINTS |
|
||||
asGetTypeTraits<QColor>());
|
||||
Q_ASSERT(r >= 0);
|
||||
|
||||
|
|
|
@ -30,12 +30,31 @@ GeneralSettingDialog::GeneralSettingDialog(QWidget *parent)
|
|||
ui->lblSoftVersion->setText(WINGHEX_VERSION);
|
||||
ui->lblScriptVersion->setText(ANGELSCRIPT_VERSION_STRING);
|
||||
|
||||
Utilities::addSpecialMark(ui->lblLanguage);
|
||||
Utilities::addSpecialMark(ui->lblTheme);
|
||||
Utilities::addSpecialMark(ui->lblFont);
|
||||
Utilities::addSpecialMark(ui->lblFontSize);
|
||||
Utilities::addSpecialMark(ui->lblWinState);
|
||||
|
||||
connect(ui->cbLanguage, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this, &GeneralSettingDialog::optionNeedRestartChanged);
|
||||
connect(ui->cbTheme, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this, &GeneralSettingDialog::optionNeedRestartChanged);
|
||||
connect(ui->cbFont, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this, &GeneralSettingDialog::optionNeedRestartChanged);
|
||||
connect(ui->sbFontSize, &QSpinBox::editingFinished, this,
|
||||
&GeneralSettingDialog::optionNeedRestartChanged);
|
||||
connect(ui->cbWinState, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this, &GeneralSettingDialog::optionNeedRestartChanged);
|
||||
|
||||
reload();
|
||||
}
|
||||
|
||||
GeneralSettingDialog::~GeneralSettingDialog() { delete ui; }
|
||||
|
||||
void GeneralSettingDialog::reload() {
|
||||
this->blockSignals(true);
|
||||
|
||||
auto &set = SettingManager::instance();
|
||||
|
||||
auto langs = LanguageManager::instance().langsDisplay();
|
||||
|
@ -67,6 +86,8 @@ void GeneralSettingDialog::reload() {
|
|||
}
|
||||
|
||||
ui->cbWinState->setCurrentIndex(s);
|
||||
|
||||
this->blockSignals(false);
|
||||
}
|
||||
|
||||
QIcon GeneralSettingDialog::categoryIcon() const { return ICONRES("general"); }
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
<number>8</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<widget class="QLabel" name="lblLanguage">
|
||||
<property name="text">
|
||||
<string>Language</string>
|
||||
</property>
|
||||
|
@ -67,7 +67,7 @@
|
|||
<widget class="QComboBox" name="cbLanguage"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<widget class="QLabel" name="lblTheme">
|
||||
<property name="text">
|
||||
<string>Theme</string>
|
||||
</property>
|
||||
|
@ -110,7 +110,7 @@
|
|||
<number>8</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<widget class="QLabel" name="lblFont">
|
||||
<property name="text">
|
||||
<string>Font</string>
|
||||
</property>
|
||||
|
@ -120,7 +120,7 @@
|
|||
<widget class="QFontComboBox" name="cbFont"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<widget class="QLabel" name="lblFontSize">
|
||||
<property name="text">
|
||||
<string>FontSize</string>
|
||||
</property>
|
||||
|
@ -137,7 +137,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<widget class="QLabel" name="lblWinState">
|
||||
<property name="text">
|
||||
<string>WinState</string>
|
||||
</property>
|
||||
|
|
|
@ -19,20 +19,28 @@ OtherSettingsDialog::OtherSettingsDialog(QWidget *parent)
|
|||
|
||||
#ifndef WINGHEX_USE_FRAMELESS
|
||||
ui->cbNativeTitile->setEnabled(false);
|
||||
ui->cbNativeTitile->setChecked(false);
|
||||
#endif
|
||||
|
||||
Utilities::addSpecialMark(ui->cbNativeTitile);
|
||||
Utilities::addSpecialMark(ui->lblLevel);
|
||||
connect(ui->cbNativeTitile, &QCheckBox::stateChanged, this,
|
||||
&OtherSettingsDialog::optionNeedRestartChanged);
|
||||
connect(ui->cbLogLevel, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this, &OtherSettingsDialog::optionNeedRestartChanged);
|
||||
|
||||
reload();
|
||||
}
|
||||
|
||||
OtherSettingsDialog::~OtherSettingsDialog() { delete ui; }
|
||||
|
||||
void OtherSettingsDialog::reload() {
|
||||
this->blockSignals(true);
|
||||
auto &set = SettingManager::instance();
|
||||
ui->cbNativeFileDialog->setChecked(set.useNativeFileDialog());
|
||||
#ifdef WINGHEX_USE_FRAMELESS
|
||||
ui->cbNativeTitile->setChecked(set.useNativeTitleBar());
|
||||
#endif
|
||||
this->blockSignals(false);
|
||||
}
|
||||
|
||||
QIcon OtherSettingsDialog::categoryIcon() const { return ICONRES("other"); }
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
<widget class="QComboBox" name="cbLogLevel"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<widget class="QLabel" name="lblLevel">
|
||||
<property name="text">
|
||||
<string>Level</string>
|
||||
</property>
|
||||
|
|
|
@ -1,13 +1,21 @@
|
|||
#include "pluginsettingdialog.h"
|
||||
#include "../class/settingmanager.h"
|
||||
#include "../dbghelper.h"
|
||||
#include "../plugin/pluginsystem.h"
|
||||
#include "../utilities.h"
|
||||
#include "dbghelper.h"
|
||||
#include "plugin/pluginsystem.h"
|
||||
#include "ui_pluginsettingdialog.h"
|
||||
#include "utilities.h"
|
||||
|
||||
PluginSettingDialog::PluginSettingDialog(QWidget *parent)
|
||||
: WingHex::SettingPage(parent), ui(new Ui::PluginSettingDialog) {
|
||||
ui->setupUi(this);
|
||||
|
||||
Utilities::addSpecialMark(ui->cbEnablePlugin);
|
||||
Utilities::addSpecialMark(ui->cbEnablePluginRoot);
|
||||
connect(ui->cbEnablePlugin, &QCheckBox::stateChanged, this,
|
||||
&PluginSettingDialog::optionNeedRestartChanged);
|
||||
connect(ui->cbEnablePluginRoot, &QCheckBox::stateChanged, this,
|
||||
&PluginSettingDialog::optionNeedRestartChanged);
|
||||
|
||||
reload();
|
||||
|
||||
auto &plgsys = PluginSystem::instance();
|
||||
|
@ -33,9 +41,11 @@ void PluginSettingDialog::buildUp(const QList<SettingPage *> &pages) {
|
|||
}
|
||||
|
||||
void PluginSettingDialog::reload() {
|
||||
this->blockSignals(true);
|
||||
auto &set = SettingManager::instance();
|
||||
ui->cbEnablePlugin->setChecked(set.enablePlugin());
|
||||
ui->cbEnablePluginRoot->setChecked(set.enablePlgInRoot());
|
||||
this->blockSignals(false);
|
||||
}
|
||||
|
||||
QIcon PluginSettingDialog::categoryIcon() const { return ICONRES("plugin"); }
|
||||
|
|
|
@ -9,6 +9,11 @@
|
|||
ScriptSettingDialog::ScriptSettingDialog(QWidget *parent)
|
||||
: WingHex::SettingPage(parent), ui(new Ui::ScriptSettingDialog) {
|
||||
ui->setupUi(this);
|
||||
|
||||
Utilities::addSpecialMark(ui->cbAllowUsrScript);
|
||||
connect(ui->cbAllowUsrScript, &QCheckBox::stateChanged, this,
|
||||
&ScriptSettingDialog::optionNeedRestartChanged);
|
||||
|
||||
loadData();
|
||||
}
|
||||
|
||||
|
@ -18,7 +23,9 @@ void ScriptSettingDialog::loadData() {
|
|||
auto &sm = ScriptManager::instance();
|
||||
auto &set = SettingManager::instance();
|
||||
|
||||
this->blockSignals(true);
|
||||
ui->cbAllowUsrScript->setChecked(set.allowUsrScriptInRoot());
|
||||
this->blockSignals(false);
|
||||
|
||||
auto usrCats = sm.usrScriptsDbCats();
|
||||
auto hidden = set.usrHideCats();
|
||||
|
|