Compare commits
7 Commits
ed118376d5
...
93a3a8aefd
Author | SHA1 | Date |
---|---|---|
|
93a3a8aefd | |
|
5686edde5b | |
|
4f4db8b5f8 | |
|
63b4583ccd | |
|
a16a8033b5 | |
|
b4881d7e3c | |
|
84d9596ada |
|
@ -12,25 +12,17 @@ Chunks::Chunks(QObject *parent) : QObject(parent) {}
|
|||
|
||||
Chunks::Chunks(QIODevice *ioDevice, QObject *parent) : QObject(parent) {
|
||||
setIODevice(ioDevice);
|
||||
if (ioDevice)
|
||||
ioDevice->setParent(this);
|
||||
}
|
||||
|
||||
Chunks::~Chunks() {}
|
||||
|
||||
bool Chunks::setIODevice(QIODevice *ioDevice) {
|
||||
_ioDevice = ioDevice;
|
||||
if (_ioDevice &&
|
||||
(_ioDevice->isOpen() ||
|
||||
_ioDevice->open(QIODevice::ReadOnly))) // Try to open IODevice
|
||||
{
|
||||
_size = _ioDevice->size();
|
||||
_ioDevice->close();
|
||||
} else // Fallback is an empty buffer
|
||||
{
|
||||
QBuffer *buf = new QBuffer(this);
|
||||
_ioDevice = buf;
|
||||
_size = 0;
|
||||
if (ioDevice && ioDevice->isOpen()) {
|
||||
ioDevice->setParent(this);
|
||||
_size = ioDevice->size();
|
||||
_ioDevice = ioDevice;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
_chunks.clear();
|
||||
_pos = 0;
|
||||
|
@ -56,8 +48,6 @@ QByteArray Chunks::data(qsizetype pos, qsizetype maxSize) {
|
|||
else if ((pos + maxSize) > _size)
|
||||
maxSize = _size - pos;
|
||||
|
||||
_ioDevice->open(QIODevice::ReadOnly);
|
||||
|
||||
while (maxSize > 0) {
|
||||
chunk.absPos = std::numeric_limits<qsizetype>::max();
|
||||
bool chunksLoopOngoing = true;
|
||||
|
@ -105,7 +95,7 @@ QByteArray Chunks::data(qsizetype pos, qsizetype maxSize) {
|
|||
pos += quint64(readBuffer.size());
|
||||
}
|
||||
}
|
||||
_ioDevice->close();
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
@ -113,15 +103,12 @@ bool Chunks::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);
|
||||
bool ok = iODevice->isOpen() && iODevice->isWritable();
|
||||
if (ok) {
|
||||
for (auto idx = pos; idx < qsizetype(count); idx += BUFFER_SIZE) {
|
||||
QByteArray ba = data(idx, BUFFER_SIZE);
|
||||
iODevice->write(ba);
|
||||
}
|
||||
iODevice->close();
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
@ -253,10 +240,8 @@ qsizetype Chunks::getChunkIndex(qsizetype absPos) {
|
|||
Chunk newChunk;
|
||||
qsizetype readAbsPos = absPos - ioDelta;
|
||||
qsizetype readPos = (readAbsPos & READ_CHUNK_MASK);
|
||||
_ioDevice->open(QIODevice::ReadOnly);
|
||||
_ioDevice->seek(qint64(readPos));
|
||||
newChunk.data = _ioDevice->read(CHUNK_SIZE);
|
||||
_ioDevice->close();
|
||||
newChunk.absPos = absPos - (readAbsPos - readPos);
|
||||
newChunk.dataChanged = QByteArray(newChunk.data.size(), char(0));
|
||||
_chunks.insert(insertIdx, newChunk);
|
||||
|
|
|
@ -34,8 +34,7 @@ QByteArray QFileBuffer::read(qsizetype offset, qsizetype length) {
|
|||
}
|
||||
|
||||
bool QFileBuffer::read(QIODevice *device) {
|
||||
_chunks->setIODevice(device);
|
||||
return true;
|
||||
return _chunks->setIODevice(device);
|
||||
}
|
||||
|
||||
void QFileBuffer::write(QIODevice *device) { _chunks->write(device); }
|
||||
|
|
|
@ -24,8 +24,8 @@ public:
|
|||
qsizetype lastIndexOf(const QByteArray &ba, qsizetype from) override;
|
||||
|
||||
private:
|
||||
Chunks *_chunks;
|
||||
uchar *m_memory;
|
||||
Chunks *_chunks = nullptr;
|
||||
uchar *m_memory = nullptr;
|
||||
};
|
||||
|
||||
#endif // QFILEBUFFER_H
|
||||
|
|
|
@ -538,7 +538,8 @@ QHexDocument *QHexDocument::fromLargeFile(const QString &filename,
|
|||
if (!filename.isEmpty()) {
|
||||
f->setFileName(filename);
|
||||
QHexBuffer *hexbuffer = new QFileBuffer();
|
||||
if (hexbuffer->read(f)) {
|
||||
if (f->open(readonly ? QFile::ReadOnly : QFile::ReadWrite) &&
|
||||
hexbuffer->read(f)) {
|
||||
return new QHexDocument(hexbuffer,
|
||||
readonly); // modified by wingsummer
|
||||
} else {
|
||||
|
@ -558,7 +559,9 @@ QHexDocument *QHexDocument::fromStorageDriver(const QStorageInfo &storage,
|
|||
auto f = new QStorageDevice;
|
||||
f->setStorage(storage);
|
||||
auto hexbuffer = new QFileBuffer();
|
||||
if (hexbuffer->read(f)) {
|
||||
if (f->open(readonly ? QStorageDevice::ReadOnly
|
||||
: QStorageDevice::ReadWrite) &&
|
||||
hexbuffer->read(f)) {
|
||||
return new QHexDocument(hexbuffer, readonly);
|
||||
} else {
|
||||
delete hexbuffer;
|
||||
|
|
|
@ -3,12 +3,10 @@
|
|||
#ifdef Q_OS_WIN
|
||||
|
||||
#include <QDebug>
|
||||
#include <memory>
|
||||
|
||||
QStorageDevice::QStorageDevice(QObject *parent)
|
||||
: QIODevice(parent), CHUNK_SIZE(0), _size(0) {
|
||||
_buffer.setTextModeEnabled(false);
|
||||
}
|
||||
: QIODevice(parent), hDevice(INVALID_HANDLE_VALUE), CHUNK_SIZE(0),
|
||||
_size(0) {}
|
||||
|
||||
void QStorageDevice::setStorage(const QStorageInfo &storage) {
|
||||
_storage = storage;
|
||||
|
@ -16,10 +14,12 @@ void QStorageDevice::setStorage(const QStorageInfo &storage) {
|
|||
|
||||
QStorageInfo QStorageDevice::storage() const { return _storage; }
|
||||
|
||||
DWORD QStorageDevice::cacheSize() const { return 20 * 1024 * CHUNK_SIZE; }
|
||||
|
||||
bool QStorageDevice::isSequential() const { return false; }
|
||||
|
||||
bool QStorageDevice::open(OpenMode mode) {
|
||||
if (_buffer.isOpen()) {
|
||||
if (hDevice != INVALID_HANDLE_VALUE) {
|
||||
setErrorString(QStringLiteral("A Storage file is still opened"));
|
||||
return false;
|
||||
}
|
||||
|
@ -32,11 +32,15 @@ bool QStorageDevice::open(OpenMode mode) {
|
|||
device.mid(devicePrefix.length(),
|
||||
device.length() - devicePrefix.length() - 1);
|
||||
|
||||
DWORD flag =
|
||||
(mode.testFlag(OpenModeFlag::ReadOnly) ? GENERIC_READ : 0) |
|
||||
(mode.testFlag(OpenModeFlag::WriteOnly) ? GENERIC_WRITE : 0);
|
||||
|
||||
// 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);
|
||||
hDevice = CreateFileW(
|
||||
reinterpret_cast<LPCWSTR>(dd.utf16()), flag,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING,
|
||||
FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, nullptr);
|
||||
|
||||
if (hDevice == INVALID_HANDLE_VALUE) {
|
||||
qWarning() << "Failed to open device:" << device;
|
||||
|
@ -45,17 +49,19 @@ bool QStorageDevice::open(OpenMode mode) {
|
|||
|
||||
DISK_GEOMETRY diskGeometry;
|
||||
DWORD bytesReturned;
|
||||
if (!DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
|
||||
if (!DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY, nullptr, 0,
|
||||
&diskGeometry, sizeof(diskGeometry),
|
||||
&bytesReturned, NULL)) {
|
||||
&bytesReturned, nullptr)) {
|
||||
CloseHandle(hDevice);
|
||||
hDevice = INVALID_HANDLE_VALUE;
|
||||
return false;
|
||||
}
|
||||
|
||||
CloseHandle(hDevice);
|
||||
|
||||
this->CHUNK_SIZE = diskGeometry.BytesPerSector;
|
||||
|
||||
_cache.buffer = std::make_unique<char[]>(cacheSize());
|
||||
_cache.length = 0;
|
||||
|
||||
// dont use ioDevice.bytesTotal(),
|
||||
// because it's use GetDiskFreeSpaceEx API to get.
|
||||
// QFile::size() is zero
|
||||
|
@ -63,12 +69,7 @@ bool QStorageDevice::open(OpenMode mode) {
|
|||
diskGeometry.TracksPerCylinder * diskGeometry.SectorsPerTrack *
|
||||
diskGeometry.BytesPerSector;
|
||||
|
||||
if (!_buffer.open(mode)) {
|
||||
// _buffer.setFileName({});
|
||||
return false;
|
||||
}
|
||||
|
||||
return QIODevice::open(QIODevice::ReadOnly);
|
||||
return QIODevice::open(mode);
|
||||
} else {
|
||||
qWarning() << "Only OpenModeFlag::ReadOnly and OpenModeFlag::WriteOnly "
|
||||
"are supported";
|
||||
|
@ -77,8 +78,10 @@ bool QStorageDevice::open(OpenMode mode) {
|
|||
}
|
||||
|
||||
void QStorageDevice::close() {
|
||||
if (_buffer.isOpen()) {
|
||||
_buffer.close();
|
||||
if (hDevice != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(hDevice);
|
||||
hDevice = INVALID_HANDLE_VALUE;
|
||||
_cache.clear();
|
||||
}
|
||||
QIODevice::close();
|
||||
}
|
||||
|
@ -86,7 +89,7 @@ void QStorageDevice::close() {
|
|||
qint64 QStorageDevice::size() const { return _size; }
|
||||
|
||||
bool QStorageDevice::seek(qint64 pos) {
|
||||
if (!_buffer.isOpen()) {
|
||||
if (hDevice == INVALID_HANDLE_VALUE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -96,7 +99,7 @@ bool QStorageDevice::seek(qint64 pos) {
|
|||
bool QStorageDevice::canReadLine() const { return false; }
|
||||
|
||||
qint64 QStorageDevice::readData(char *data, qint64 maxlen) {
|
||||
if (!isOpen() || !maxlen) {
|
||||
if (hDevice == INVALID_HANDLE_VALUE || !maxlen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -111,18 +114,35 @@ qint64 QStorageDevice::readData(char *data, qint64 maxlen) {
|
|||
}
|
||||
|
||||
auto rp = std::div(this->pos(), CHUNK_SIZE);
|
||||
_buffer.seek(rp.quot * CHUNK_SIZE);
|
||||
auto off = rp.quot * CHUNK_SIZE;
|
||||
|
||||
DWORD bytesRead = 0;
|
||||
if (_cache.offset < 0 || this->pos() < _cache.offset ||
|
||||
this->pos() + maxlen >= _cache.offset + _cache.length) {
|
||||
OVERLAPPED overlapped{0};
|
||||
LARGE_INTEGER offset;
|
||||
offset.QuadPart = off;
|
||||
overlapped.Offset = offset.LowPart;
|
||||
overlapped.OffsetHigh = offset.HighPart;
|
||||
|
||||
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);
|
||||
if (!ReadFile(hDevice, _cache.buffer.get(), cacheSize(), nullptr,
|
||||
&overlapped)) {
|
||||
auto lastError = GetLastError();
|
||||
if (lastError == ERROR_IO_PENDING) {
|
||||
if (!GetOverlappedResult(hDevice, &overlapped, &_cache.length,
|
||||
TRUE)) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
_cache.offset = off;
|
||||
}
|
||||
|
||||
std::memcpy(data, _cache.buffer.get() + this->pos() - _cache.offset,
|
||||
maxlen);
|
||||
|
||||
return maxlen;
|
||||
}
|
||||
|
||||
|
@ -133,26 +153,93 @@ qint64 QStorageDevice::writeData(const char *data, qint64 len) {
|
|||
}
|
||||
|
||||
// Ensure maxSize is a multiple of the sector size
|
||||
auto r = std::div(len, CHUNK_SIZE);
|
||||
auto rp = std::div(this->pos(), CHUNK_SIZE);
|
||||
auto header = CHUNK_SIZE - rp.rem;
|
||||
auto r = std::div(len - header, CHUNK_SIZE);
|
||||
auto alignLen = r.quot * CHUNK_SIZE;
|
||||
|
||||
auto rp = std::div(this->pos(), CHUNK_SIZE);
|
||||
_buffer.seek(rp.quot * CHUNK_SIZE);
|
||||
OVERLAPPED overlapped{0};
|
||||
LARGE_INTEGER offset;
|
||||
DWORD length = 0;
|
||||
|
||||
if (rp.rem) {
|
||||
// read some and write back
|
||||
offset.QuadPart = rp.quot * CHUNK_SIZE;
|
||||
|
||||
auto buffer = std::make_unique<char[]>(CHUNK_SIZE);
|
||||
|
||||
if (!ReadFile(hDevice, buffer.get(), CHUNK_SIZE, nullptr,
|
||||
&overlapped)) {
|
||||
auto lastError = GetLastError();
|
||||
if (lastError == ERROR_IO_PENDING) {
|
||||
if (!GetOverlappedResult(hDevice, &overlapped, &length, TRUE)) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
std::memcpy(buffer.get(), data, CHUNK_SIZE - rp.rem);
|
||||
|
||||
if (!WriteFile(hDevice, buffer.get(), CHUNK_SIZE, nullptr,
|
||||
&overlapped)) {
|
||||
auto lastError = GetLastError();
|
||||
if (lastError == ERROR_IO_PENDING) {
|
||||
if (!GetOverlappedResult(hDevice, &overlapped, &length, TRUE)) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_buffer.write(data, alignLen);
|
||||
offset.QuadPart += CHUNK_SIZE;
|
||||
overlapped.Offset = offset.LowPart;
|
||||
overlapped.OffsetHigh = offset.HighPart;
|
||||
|
||||
// write aligned
|
||||
if (!WriteFile(hDevice, data - header, alignLen, nullptr, &overlapped)) {
|
||||
auto lastError = GetLastError();
|
||||
if (lastError == ERROR_IO_PENDING) {
|
||||
if (!GetOverlappedResult(hDevice, &overlapped, &length, TRUE)) {
|
||||
return header;
|
||||
}
|
||||
} else {
|
||||
return header;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
offset.QuadPart += alignLen;
|
||||
overlapped.Offset = offset.LowPart;
|
||||
overlapped.OffsetHigh = offset.HighPart;
|
||||
|
||||
if (_buffer.write(buf.get(), CHUNK_SIZE)) {
|
||||
qWarning() << "Failed to write data to device";
|
||||
return -1;
|
||||
auto buffer = std::make_unique<char[]>(CHUNK_SIZE);
|
||||
if (!ReadFile(hDevice, buffer.get(), CHUNK_SIZE, nullptr,
|
||||
&overlapped)) {
|
||||
auto lastError = GetLastError();
|
||||
if (lastError == ERROR_IO_PENDING) {
|
||||
if (!GetOverlappedResult(hDevice, &overlapped, &length, TRUE)) {
|
||||
return header + alignLen;
|
||||
}
|
||||
} else {
|
||||
return header + alignLen;
|
||||
}
|
||||
}
|
||||
std::memcpy(buffer.get(), data + len - r.rem, r.rem);
|
||||
|
||||
if (!WriteFile(hDevice, buffer.get(), CHUNK_SIZE, nullptr,
|
||||
&overlapped)) {
|
||||
auto lastError = GetLastError();
|
||||
if (lastError == ERROR_IO_PENDING) {
|
||||
if (!GetOverlappedResult(hDevice, &overlapped, &length, TRUE)) {
|
||||
return header + alignLen;
|
||||
}
|
||||
} else {
|
||||
return header + alignLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <QIODevice>
|
||||
#include <QStorageInfo>
|
||||
#include <memory>
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
|
@ -19,9 +20,24 @@ public:
|
|||
|
||||
QStorageInfo storage() const;
|
||||
|
||||
private:
|
||||
struct Buffer {
|
||||
qint64 offset = -1;
|
||||
// length is usually 20 * 1024 * CHUNK_SIZE = 10 MB
|
||||
std::unique_ptr<char[]> buffer;
|
||||
DWORD length = 0;
|
||||
|
||||
void clear() {
|
||||
offset = -1;
|
||||
length = 0;
|
||||
}
|
||||
} _cache;
|
||||
|
||||
DWORD cacheSize() const;
|
||||
|
||||
private:
|
||||
QStorageInfo _storage;
|
||||
QFile _buffer;
|
||||
HANDLE hDevice;
|
||||
DWORD CHUNK_SIZE;
|
||||
qint64 _size;
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
*/
|
||||
QCodeCompletionEngine::QCodeCompletionEngine(QObject *p)
|
||||
: QObject(p), m_max(0) {
|
||||
: QObject(p), m_max(0), m_trigWordLen(-1) {
|
||||
pForcedTrigger = new QAction(tr("&Trigger completion"), this);
|
||||
|
||||
connect(pForcedTrigger, SIGNAL(triggered()), this, SLOT(complete()));
|
||||
|
@ -88,7 +88,7 @@ QEditor *QCodeCompletionEngine::editor() const { return pEdit; }
|
|||
*/
|
||||
void QCodeCompletionEngine::setEditor(QEditor *e) {
|
||||
if (pEdit) {
|
||||
pEdit->removeAction(pForcedTrigger, "&Edit");
|
||||
pEdit->removeAction(pForcedTrigger, tr("&Edit"));
|
||||
// pEdit->removeEventFilter(this);
|
||||
|
||||
disconnect(pEdit, SIGNAL(textEdited(QKeyEvent *)), this,
|
||||
|
@ -99,10 +99,9 @@ void QCodeCompletionEngine::setEditor(QEditor *e) {
|
|||
|
||||
if (pEdit) {
|
||||
// pEdit->installEventFilter(this);
|
||||
pEdit->addAction(pForcedTrigger, "&Edit");
|
||||
|
||||
connect(pEdit, SIGNAL(textEdited(QKeyEvent *)), this,
|
||||
SLOT(textEdited(QKeyEvent *)));
|
||||
pEdit->addAction(pForcedTrigger, tr("&Edit"));
|
||||
connect(pEdit, &QEditor::textEdited, this,
|
||||
&QCodeCompletionEngine::textEdited);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,8 +140,14 @@ void QCodeCompletionEngine::textEdited(QKeyEvent *k) {
|
|||
|
||||
auto count = txt.length();
|
||||
|
||||
if (txt.isEmpty() || m_triggers.isEmpty())
|
||||
if (txt.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_triggers.isEmpty()) {
|
||||
triggerWordLenComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
// qDebug("should trigger completion? (bis)");
|
||||
|
||||
|
@ -161,7 +166,6 @@ void QCodeCompletionEngine::textEdited(QKeyEvent *k) {
|
|||
}
|
||||
|
||||
// qDebug("text : %s", qPrintable(txt));
|
||||
|
||||
for (auto &trig : m_triggers) {
|
||||
if (txt.endsWith(trig)) {
|
||||
cur = editor()->cursor();
|
||||
|
@ -175,8 +179,11 @@ void QCodeCompletionEngine::textEdited(QKeyEvent *k) {
|
|||
|
||||
// trigger completion
|
||||
complete(cur, trig);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
triggerWordLenComplete();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -250,3 +257,17 @@ void QCodeCompletionEngine::complete(const QDocumentCursor &c,
|
|||
qWarning("QCodeCompletionEngine is not self-sufficient : subclasses should "
|
||||
"reimplement at least one of the complete() method...");
|
||||
}
|
||||
|
||||
void QCodeCompletionEngine::triggerWordLenComplete() {
|
||||
if (m_trigWordLen > 0) {
|
||||
QDocumentCursor cur = editor()->cursor();
|
||||
emit completionTriggered({});
|
||||
complete(cur, {});
|
||||
}
|
||||
}
|
||||
|
||||
qsizetype QCodeCompletionEngine::trigWordLen() const { return m_trigWordLen; }
|
||||
|
||||
void QCodeCompletionEngine::setTrigWordLen(qsizetype newTrigWordLen) {
|
||||
m_trigWordLen = newTrigWordLen;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ public:
|
|||
QAction *triggerAction() const;
|
||||
|
||||
QEditor *editor() const;
|
||||
void setEditor(QEditor *e);
|
||||
virtual void setEditor(QEditor *e);
|
||||
|
||||
QStringList triggers() const;
|
||||
|
||||
|
@ -59,6 +59,9 @@ public:
|
|||
|
||||
virtual void retranslate();
|
||||
|
||||
qsizetype trigWordLen() const;
|
||||
void setTrigWordLen(qsizetype newTrigWordLen);
|
||||
|
||||
signals:
|
||||
void popup();
|
||||
void cloned(QCodeCompletionEngine *e);
|
||||
|
@ -74,8 +77,13 @@ protected:
|
|||
|
||||
virtual void complete(const QDocumentCursor &c, const QString &trigger);
|
||||
|
||||
private:
|
||||
void triggerWordLenComplete();
|
||||
|
||||
private:
|
||||
qsizetype m_max;
|
||||
qsizetype m_trigWordLen;
|
||||
|
||||
QString m_trig;
|
||||
QDocumentCursor m_cur;
|
||||
QAction *pForcedTrigger;
|
||||
|
|
|
@ -3948,8 +3948,8 @@ void QEditor::repaintCursor() {
|
|||
bool QEditor::isCursorVisible() const {
|
||||
QPoint pos = m_cursor.documentPosition();
|
||||
|
||||
const QRect cursor(pos.x(), pos.y(), 1,
|
||||
QDocument::fontMetrics().lineSpacing());
|
||||
// const QRect cursor(pos.x(), pos.y(), 1,
|
||||
// QDocument::fontMetrics().lineSpacing());
|
||||
const QRect display(horizontalOffset(), verticalOffset(),
|
||||
viewport()->width(), viewport()->height());
|
||||
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
/****************************************************************************
|
||||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This file is part of the Edyuk project <http://edyuk.org>
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
****************************************************************************/
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "qcalltip.h"
|
||||
|
||||
|
@ -23,6 +25,8 @@
|
|||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
|
||||
#include <QToolTip>
|
||||
|
||||
/*!
|
||||
\class QCallTip
|
||||
\brief A widget dedicated to calltips display
|
||||
|
@ -32,6 +36,11 @@ QCallTip::QCallTip(QWidget *p) : QWidget(p), m_index(0) {
|
|||
setCursor(Qt::ArrowCursor);
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
auto palette = QToolTip::palette();
|
||||
_background = palette.color(QPalette::ToolTipBase);
|
||||
_foreground = palette.color(QPalette::ToolTipText);
|
||||
_borderColor = palette.color(QPalette::Shadow);
|
||||
}
|
||||
|
||||
QCallTip::~QCallTip() {}
|
||||
|
@ -49,6 +58,8 @@ void QCallTip::paintEvent(QPaintEvent *e) {
|
|||
Q_UNUSED(e)
|
||||
|
||||
QPainter p(this);
|
||||
p.setOpacity(_opacity);
|
||||
|
||||
QFontMetrics fm = fontMetrics();
|
||||
|
||||
m_up = m_down = QRect();
|
||||
|
@ -66,21 +77,18 @@ void QCallTip::paintEvent(QPaintEvent *e) {
|
|||
bg.setWidth(bg.width() + arrowWidth);
|
||||
}
|
||||
|
||||
p.fillRect(bg, QColor(0xca, 0xff, 0x70));
|
||||
p.fillRect(bg, _background);
|
||||
// p.drawRect(bg);
|
||||
|
||||
p.save();
|
||||
|
||||
p.setPen(QColor(0x00, 0x00, 0x00));
|
||||
p.setPen(_borderColor);
|
||||
p.drawLine(0, height() - 1, bg.width() - 1, height() - 1);
|
||||
p.drawLine(bg.width() - 1, height() - 1, bg.width() - 1, 0);
|
||||
|
||||
p.setPen(QColor(0xc0, 0xc0, 0xc0));
|
||||
p.drawLine(0, height() - 1, 0, 0);
|
||||
p.drawLine(0, 0, bg.width() - 1, 0);
|
||||
|
||||
p.restore();
|
||||
|
||||
int top = height() / 3, bottom = height() - height() / 3;
|
||||
|
||||
if (bPrev) {
|
||||
|
@ -107,8 +115,11 @@ void QCallTip::paintEvent(QPaintEvent *e) {
|
|||
offset += arrowWidth;
|
||||
}
|
||||
|
||||
p.setPen(_foreground);
|
||||
p.drawText(offset, fm.ascent() + 2, m_tips.at(m_index));
|
||||
|
||||
p.restore();
|
||||
|
||||
setFixedSize(bg.size() + QSize(1, 1));
|
||||
}
|
||||
|
||||
|
@ -124,7 +135,7 @@ void QCallTip::keyPressEvent(QKeyEvent *e) {
|
|||
return;
|
||||
}
|
||||
|
||||
QString prefix, text = e->text();
|
||||
QString text = e->text();
|
||||
|
||||
switch (e->key()) {
|
||||
case Qt::Key_Escape:
|
||||
|
@ -231,3 +242,39 @@ void QCallTip::mousePressEvent(QMouseEvent *e) {
|
|||
}
|
||||
|
||||
void QCallTip::mouseReleaseEvent(QMouseEvent *e) { e->accept(); }
|
||||
|
||||
qreal QCallTip::opacity() const { return _opacity; }
|
||||
|
||||
void QCallTip::setOpacity(qreal newOpacity) {
|
||||
if (qFuzzyCompare(_opacity, newOpacity))
|
||||
return;
|
||||
_opacity = newOpacity;
|
||||
emit opacityChanged();
|
||||
}
|
||||
|
||||
QColor QCallTip::borderColor() const { return _borderColor; }
|
||||
|
||||
void QCallTip::setBorderColor(const QColor &newBorderColor) {
|
||||
if (_borderColor == newBorderColor)
|
||||
return;
|
||||
_borderColor = newBorderColor;
|
||||
emit borderColorChanged();
|
||||
}
|
||||
|
||||
QColor QCallTip::foreground() const { return _foreground; }
|
||||
|
||||
void QCallTip::setForeground(const QColor &newForeground) {
|
||||
if (_foreground == newForeground)
|
||||
return;
|
||||
_foreground = newForeground;
|
||||
emit foregroundChanged();
|
||||
}
|
||||
|
||||
QColor QCallTip::background() const { return _background; }
|
||||
|
||||
void QCallTip::setBackground(const QColor &newBackground) {
|
||||
if (_background == newBackground)
|
||||
return;
|
||||
_background = newBackground;
|
||||
emit backgroundChanged();
|
||||
}
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
/****************************************************************************
|
||||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This file is part of the Edyuk project <http://edyuk.org>
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** 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.
|
||||
**
|
||||
****************************************************************************/
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef _QCALL_TIP_H_
|
||||
#define _QCALL_TIP_H_
|
||||
|
@ -26,6 +28,17 @@
|
|||
#include <QWidget>
|
||||
|
||||
class QCE_EXPORT QCallTip : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QColor background READ background WRITE setBackground NOTIFY
|
||||
backgroundChanged FINAL)
|
||||
Q_PROPERTY(QColor foreground READ foreground WRITE setForeground NOTIFY
|
||||
foregroundChanged FINAL)
|
||||
Q_PROPERTY(QColor borderColor READ borderColor WRITE setBorderColor NOTIFY
|
||||
borderColorChanged FINAL)
|
||||
Q_PROPERTY(
|
||||
qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged FINAL)
|
||||
|
||||
public:
|
||||
QCallTip(QWidget *p = nullptr);
|
||||
virtual ~QCallTip();
|
||||
|
@ -33,18 +46,43 @@ public:
|
|||
QStringList tips() const;
|
||||
void setTips(const QStringList &l);
|
||||
|
||||
QColor background() const;
|
||||
void setBackground(const QColor &newBackground);
|
||||
|
||||
QColor foreground() const;
|
||||
void setForeground(const QColor &newForeground);
|
||||
|
||||
QColor borderColor() const;
|
||||
void setBorderColor(const QColor &newBorderColor);
|
||||
|
||||
qreal opacity() const;
|
||||
void setOpacity(qreal newOpacity);
|
||||
|
||||
signals:
|
||||
void backgroundChanged();
|
||||
void foregroundChanged();
|
||||
void borderColorChanged();
|
||||
|
||||
void opacityChanged();
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent *e);
|
||||
virtual void keyPressEvent(QKeyEvent *e);
|
||||
virtual void focusInEvent(QFocusEvent *e);
|
||||
virtual void focusOutEvent(QFocusEvent *e);
|
||||
virtual void mousePressEvent(QMouseEvent *e);
|
||||
virtual void mouseReleaseEvent(QMouseEvent *e);
|
||||
virtual void paintEvent(QPaintEvent *e) override;
|
||||
virtual void keyPressEvent(QKeyEvent *e) override;
|
||||
virtual void focusInEvent(QFocusEvent *e) override;
|
||||
virtual void focusOutEvent(QFocusEvent *e) override;
|
||||
virtual void mousePressEvent(QMouseEvent *e) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
|
||||
private:
|
||||
int m_index;
|
||||
QStringList m_tips;
|
||||
QRect m_up, m_down;
|
||||
|
||||
QColor _background;
|
||||
QColor _foreground;
|
||||
QColor _borderColor;
|
||||
|
||||
qreal _opacity = 1;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -102,12 +102,12 @@ void QFoldPanel::mousePressEvent(QMouseEvent *e) {
|
|||
/*!
|
||||
|
||||
*/
|
||||
bool QFoldPanel::paint(QPainter *p, QEditor *e) {
|
||||
void QFoldPanel::paint(QPainter *p, QEditor *e) {
|
||||
QDocument *doc = editor()->document();
|
||||
QLanguageDefinition *def = e->languageDefinition();
|
||||
|
||||
if (!def || !doc) {
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
m_rects.clear();
|
||||
|
@ -249,8 +249,6 @@ bool QFoldPanel::paint(QPainter *p, QEditor *e) {
|
|||
|
||||
pos += len;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QRect QFoldPanel::drawIcon(QPainter *p, QEditor *, int x, int y,
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent *e);
|
||||
virtual bool paint(QPainter *p, QEditor *e);
|
||||
virtual void paint(QPainter *p, QEditor *e);
|
||||
|
||||
QRect drawIcon(QPainter *p, QEditor *e, int x, int y, bool expand);
|
||||
|
||||
|
|
|
@ -63,9 +63,9 @@ QString QLineChangePanel::type() const { return "Line changes"; }
|
|||
/*!
|
||||
\internal
|
||||
*/
|
||||
bool QLineChangePanel::paint(QPainter *p, QEditor *e) {
|
||||
void QLineChangePanel::paint(QPainter *p, QEditor *e) {
|
||||
if (!e || !e->document())
|
||||
return true;
|
||||
return;
|
||||
|
||||
const QFontMetrics fm(e->document()->font());
|
||||
|
||||
|
@ -99,8 +99,6 @@ bool QLineChangePanel::paint(QPainter *p, QEditor *e) {
|
|||
|
||||
posY += ls * span;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! @} */
|
||||
|
|
|
@ -42,7 +42,7 @@ public:
|
|||
virtual QString type() const;
|
||||
|
||||
protected:
|
||||
virtual bool paint(QPainter *p, QEditor *e);
|
||||
virtual void paint(QPainter *p, QEditor *e);
|
||||
|
||||
private:
|
||||
};
|
||||
|
|
|
@ -65,9 +65,9 @@ QString QLineMarkPanel::type() const { return "Line marks"; }
|
|||
/*!
|
||||
\internal
|
||||
*/
|
||||
bool QLineMarkPanel::paint(QPainter *p, QEditor *e) {
|
||||
void QLineMarkPanel::paint(QPainter *p, QEditor *e) {
|
||||
if (!e || !e->document())
|
||||
return true;
|
||||
return;
|
||||
|
||||
m_rects.clear();
|
||||
m_lines.clear();
|
||||
|
@ -130,7 +130,6 @@ bool QLineMarkPanel::paint(QPainter *p, QEditor *e) {
|
|||
// qDebug("</session>");
|
||||
|
||||
// setFixedWidth(sfm.width(txt) + 5);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
@ -45,7 +45,7 @@ signals:
|
|||
void onToggleMark(int lineIndex);
|
||||
|
||||
protected:
|
||||
virtual bool paint(QPainter *p, QEditor *e);
|
||||
virtual void paint(QPainter *p, QEditor *e);
|
||||
virtual void mousePressEvent(QMouseEvent *e);
|
||||
virtual void mouseReleaseEvent(QMouseEvent *e);
|
||||
virtual void contextMenuEvent(QContextMenuEvent *e);
|
||||
|
|
|
@ -100,7 +100,7 @@ void QLineNumberPanel::editorChange(QEditor *e) {
|
|||
/*!
|
||||
|
||||
*/
|
||||
bool QLineNumberPanel::paint(QPainter *p, QEditor *e) {
|
||||
void QLineNumberPanel::paint(QPainter *p, QEditor *e) {
|
||||
/*
|
||||
possible Unicode caracter for wrapping arrow :
|
||||
0x21B3
|
||||
|
@ -225,7 +225,6 @@ bool QLineNumberPanel::paint(QPainter *p, QEditor *e) {
|
|||
// p->drawLine(width()-1, 0, width()-1, pageBottom);
|
||||
|
||||
// setFixedWidth(sfm.width(txt) + 5);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! @} */
|
||||
|
|
|
@ -43,7 +43,7 @@ public slots:
|
|||
|
||||
protected:
|
||||
virtual void editorChange(QEditor *e);
|
||||
virtual bool paint(QPainter *p, QEditor *e);
|
||||
virtual void paint(QPainter *p, QEditor *e);
|
||||
|
||||
bool m_verbose;
|
||||
int mutable m_minWidth = 0;
|
||||
|
|
|
@ -243,6 +243,8 @@ void QPanel::hideEvent(QHideEvent *e) {
|
|||
\internal
|
||||
*/
|
||||
void QPanel::paintEvent(QPaintEvent *e) {
|
||||
QWidget::paintEvent(e);
|
||||
|
||||
if (!m_editor || !m_editor->document()) {
|
||||
e->ignore();
|
||||
return;
|
||||
|
@ -251,22 +253,12 @@ void QPanel::paintEvent(QPaintEvent *e) {
|
|||
e->accept();
|
||||
|
||||
QPainter p(this);
|
||||
|
||||
if (!paint(&p, m_editor))
|
||||
QWidget::paintEvent(e);
|
||||
paint(&p, m_editor);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
bool QPanel::paint(QPainter *, QEditor *) {
|
||||
/*
|
||||
qWarning("Bad panel implementation : "
|
||||
"QPanel::paint(QPainter*, QEditor*)"
|
||||
" is a stub that should not get called."
|
||||
"\nCheck out the code of %s", qPrintable(type()));
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
void QPanel::paint(QPainter *, QEditor *) {}
|
||||
|
||||
/* @} */
|
||||
|
|
|
@ -70,7 +70,7 @@ protected:
|
|||
virtual void showEvent(QShowEvent *e);
|
||||
virtual void hideEvent(QHideEvent *e);
|
||||
virtual void paintEvent(QPaintEvent *e);
|
||||
virtual bool paint(QPainter *p, QEditor *e);
|
||||
virtual void paint(QPainter *p, QEditor *e);
|
||||
|
||||
private:
|
||||
QPointer<QEditor> m_editor;
|
||||
|
|
|
@ -214,16 +214,18 @@ set(CLASS_SRC
|
|||
src/class/appmanager.h
|
||||
src/class/appmanager.cpp
|
||||
src/class/angelscripthelper.h
|
||||
src/class/qasparser.cpp
|
||||
src/class/qasparser.h
|
||||
src/class/ascompletion.cpp
|
||||
src/class/ascompletion.h
|
||||
src/class/asbuilder.h
|
||||
src/class/asbuilder.cpp
|
||||
src/class/qasparser.cpp
|
||||
src/class/qasparser.h
|
||||
src/class/qdocumentsearch.cpp
|
||||
src/class/qdocumentsearch.h
|
||||
src/class/ascontextmgr.h
|
||||
src/class/ascontextmgr.cpp)
|
||||
src/class/ascontextmgr.cpp
|
||||
src/class/qcodenode.cpp
|
||||
src/class/qcodenode.h)
|
||||
|
||||
if(WINGHEX_USE_FRAMELESS)
|
||||
set(WIDGET_FRAME_SRC
|
||||
|
@ -302,23 +304,6 @@ set(CODEEDIT_WIDGET
|
|||
src/qcodeeditwidget/qformatconfig.cpp
|
||||
src/qcodeeditwidget/qformatconfig.ui)
|
||||
|
||||
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)
|
||||
|
||||
|
@ -413,7 +398,6 @@ set(PROJECT_SOURCES
|
|||
src/dbghelper.h
|
||||
${QPATHEDIT_SRC}
|
||||
${WIDGET_FRAME_SRC}
|
||||
${CODE_MODEL}
|
||||
${RIBBON_SRC}
|
||||
${CLASS_SRC}
|
||||
${MODEL_SRC}
|
||||
|
|
103
favicon.rc
103
favicon.rc
|
@ -1,3 +1,104 @@
|
|||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// 中文(简体,中国) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
|
||||
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
|
||||
#pragma code_page(936)
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,0,1
|
||||
PRODUCTVERSION 1,0,0,1
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x1L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "080404b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "羽云工作室(WingCloudStudio)"
|
||||
VALUE "FileDescription", "一个自由强大跨平台的十六进制编辑器"
|
||||
VALUE "FileVersion", "1.0.0"
|
||||
VALUE "InternalName", "WingHexExplorer2.exe"
|
||||
VALUE "LegalCopyright", "AGPL-3.0"
|
||||
VALUE "OriginalFilename", "WingHexExplorer2.exe"
|
||||
VALUE "ProductName", "羽云十六进制编辑器2"
|
||||
VALUE "ProductVersion", "1.0.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x804, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // 中文(简体,中国) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_ICON1 ICON "appicon.ico"
|
||||
IDI_ICON1 ICON "appicon.ico"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,14 @@
|
|||
[Desktop Entry]
|
||||
Name=WingHexExplorer2
|
||||
Name[zh_CN]=羽云十六进制编辑器
|
||||
Categories=Utility;
|
||||
Exec=/opt/WingHexExplorer2/WingHexExplorer2 %F
|
||||
Encoding=UTF-8
|
||||
Type=Application
|
||||
StartupNotify=false
|
||||
Terminal=false
|
||||
Icon=/opt/WingHexExplorer2/share/icon.png
|
||||
StartupWMClass=WingHexExplorer
|
||||
Comment=a free and powerful opensource hexeditor based on QT
|
||||
Comment[zh_CN]=一个基于 QT 的自由和强大的开源十六进制编辑器
|
||||
MimeType=application/x-winghex;text/plain;application/octet-stream;
|
|
@ -0,0 +1,315 @@
|
|||
#! /usr/bin/env python3
|
||||
# -*- coding:utf-8 -*-
|
||||
# @Time : 2024/08/27
|
||||
# @Author : 寂静的羽夏(wingsummer)
|
||||
# @FileName: installer.py
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import shutil
|
||||
import hashlib
|
||||
import psutil
|
||||
import subprocess
|
||||
|
||||
from colorama import Fore, Style
|
||||
|
||||
PACKAGE_NAME = "WingHexExplorer2"
|
||||
INSTALL_PATH = f"/opt/{PACKAGE_NAME}"
|
||||
APP_DESKTOP_PATH = "/usr/share/applications"
|
||||
DESKTOP_FILE_NAME = "com.wingsummer.winghexexplorer2.desktop"
|
||||
|
||||
|
||||
def is_root():
|
||||
return os.geteuid() == 0
|
||||
|
||||
|
||||
def check_is_running(processName):
|
||||
'''
|
||||
Check if there is any running process that contains the given name processName.
|
||||
'''
|
||||
# Iterate over the all the running process
|
||||
for proc in psutil.process_iter():
|
||||
try:
|
||||
# Check if process name contains the given name string.
|
||||
if processName.lower() in proc.name().lower():
|
||||
return True
|
||||
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
||||
pass
|
||||
return False
|
||||
|
||||
|
||||
def run_command_interactive(command):
|
||||
"""
|
||||
Run a command interactively, printing its stdout in real-time.
|
||||
|
||||
:param command: List of command arguments (e.g., ["your_command", "arg1", "arg2"])
|
||||
:return: The return code of the command
|
||||
"""
|
||||
process = subprocess.Popen(
|
||||
command,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT, # Capture both stdout and stderr
|
||||
text=True # Ensure the output is in text mode
|
||||
)
|
||||
|
||||
while True:
|
||||
output = process.stdout.readline()
|
||||
if output == "" and process.poll() is not None:
|
||||
break
|
||||
if output:
|
||||
print(Fore.GREEN + output.strip() + Style.RESET_ALL)
|
||||
|
||||
return_code = process.wait()
|
||||
return return_code
|
||||
|
||||
|
||||
def create_dir(dir):
|
||||
if not os.path.exists(dir):
|
||||
os.mkdir(dir)
|
||||
|
||||
|
||||
def update(build_path):
|
||||
if (os.path.exists(INSTALL_PATH) == False):
|
||||
print(
|
||||
Fore.RED + "[Error] The installing path not exists! Please use 'install' instead." + Style.RESET_ALL)
|
||||
exit(3)
|
||||
|
||||
installer_path = os.path.dirname(os.path.abspath(__file__))
|
||||
projectbase = os.path.abspath(os.path.join(installer_path, "../.."))
|
||||
|
||||
print(Fore.GREEN + ">> Checking file integrity..." + Style.RESET_ALL)
|
||||
|
||||
if (os.path.exists(build_path) == False):
|
||||
print(
|
||||
Fore.RED + "[Error] Not found a CMake build directory!" + Style.RESET_ALL)
|
||||
exit(-1)
|
||||
|
||||
if (os.path.exists(os.path.join(build_path, "CMakeCache.txt")) == False):
|
||||
print(
|
||||
Fore.RED + "[Error] This is not a CMake build directory!" + Style.RESET_ALL)
|
||||
exit(-1)
|
||||
|
||||
version_file_src = os.path.join(build_path, "WINGHEX_VERSION")
|
||||
if (os.path.exists(version_file_src) == False):
|
||||
print(
|
||||
Fore.RED + "[Error] WINGHEX_VERSION file not found, maybe not a CMake build directory!" + Style.RESET_ALL)
|
||||
exit(-1)
|
||||
|
||||
version_qt_src = os.path.join(build_path, "QT_VERSION")
|
||||
if (os.path.exists(version_qt_src) == False):
|
||||
print(
|
||||
Fore.RED + "[Error] QT_VERSION file not found, maybe not a CMake build directory!" + Style.RESET_ALL)
|
||||
exit(-1)
|
||||
|
||||
# ok, start copying files
|
||||
exemain_src = os.path.join(build_path, PACKAGE_NAME)
|
||||
if (os.path.exists(exemain_src) == False):
|
||||
print(
|
||||
Fore.RED + f"[Error] {PACKAGE_NAME} is not found!" + Style.RESET_ALL)
|
||||
exit(-3)
|
||||
|
||||
# calculate the md5 checksum
|
||||
with open(exemain_src, 'rb') as file_to_check:
|
||||
data = file_to_check.read()
|
||||
md5_returned = hashlib.md5(data).hexdigest().upper()
|
||||
|
||||
print(Fore.GREEN + ">> Get MD5: " + md5_returned + Style.RESET_ALL)
|
||||
print(Fore.GREEN + ">> Installing..." + Style.RESET_ALL)
|
||||
|
||||
shutil.copy2(exemain_src, os.path.join(INSTALL_PATH, PACKAGE_NAME))
|
||||
|
||||
create_dir(os.path.join(INSTALL_PATH, "plugin"))
|
||||
create_dir(os.path.join(INSTALL_PATH, "scripts"))
|
||||
create_dir(os.path.join(INSTALL_PATH, "aslib"))
|
||||
|
||||
shutil.copytree(os.path.join(installer_path, "share"),
|
||||
os.path.join(INSTALL_PATH, "share"), dirs_exist_ok=True)
|
||||
|
||||
shutil.copytree(os.path.join(build_path, "lang"),
|
||||
os.path.join(INSTALL_PATH, "lang"), dirs_exist_ok=True)
|
||||
|
||||
print(Fore.GREEN + ">> Copying License and other materials..." + Style.RESET_ALL)
|
||||
|
||||
material_files = ["LICENSE", "authorband.svg",
|
||||
"licenseband.svg", "screenshot.png", "README.md", "TODO.txt"]
|
||||
|
||||
for f in material_files:
|
||||
shutil.copyfile(os.path.join(projectbase, f),
|
||||
os.path.join(INSTALL_PATH, f))
|
||||
|
||||
shutil.copyfile(os.path.join(projectbase, "images", "author.jpg"),
|
||||
os.path.join(INSTALL_PATH, "author.jpg"))
|
||||
|
||||
with open(os.path.join(INSTALL_PATH, "md5sums"), 'w') as md5_file:
|
||||
md5_file.write(md5_returned)
|
||||
|
||||
shutil.copyfile(os.path.join(installer_path, DESKTOP_FILE_NAME),
|
||||
os.path.join(APP_DESKTOP_PATH, DESKTOP_FILE_NAME))
|
||||
|
||||
run_command_interactive(
|
||||
["xdg-mime", "install", "/opt/WingHexExplorer2/share/x-winghex.xml"])
|
||||
run_command_interactive(
|
||||
["xdg-mime", "default", "/usr/share/applications/com.wingsummer.winghexexplorer2.desktop", "application/x-winghex"])
|
||||
run_command_interactive(
|
||||
["xdg-icon-resource", "install", "--context", "mimetypes", "--size", "32", "/opt/WingHexExplorer2/share/winghexpro32.png", "application-x-winghex"])
|
||||
run_command_interactive(
|
||||
["xdg-icon-resource", "install", "--context", "mimetypes", "--size", "64", "/opt/WingHexExplorer2/share/winghexpro64.png", "application-x-winghex"])
|
||||
run_command_interactive(
|
||||
["xdg-icon-resource", "install", "--context", "mimetypes", "--size", "128", "/opt/WingHexExplorer2/share/winghexpro128.png", "application-x-winghex"])
|
||||
run_command_interactive(
|
||||
["update-mime-database", "/usr/share/mime"])
|
||||
run_command_interactive(
|
||||
["xdg-icon-resource", "forceupdate"])
|
||||
run_command_interactive(
|
||||
["gtk-update-icon-caches", "/usr/share/icons/hicolor"])
|
||||
run_command_interactive(
|
||||
["update-desktop-database", "/usr/share/applications"])
|
||||
print(Fore.GREEN + ">> Installation finished..." + Style.RESET_ALL)
|
||||
|
||||
|
||||
def install(build_path):
|
||||
if (os.path.exists(INSTALL_PATH)):
|
||||
print(
|
||||
Fore.RED + "[Error] The installing path exists! Please use 'update' instead or 'uninstall' before it." + Style.RESET_ALL)
|
||||
exit(3)
|
||||
os.makedirs(INSTALL_PATH)
|
||||
update(build_path)
|
||||
|
||||
|
||||
def remove(path):
|
||||
""" param <path> could either be relative or absolute. """
|
||||
if os.path.isfile(path) or os.path.islink(path):
|
||||
os.remove(path) # remove the file
|
||||
elif os.path.isdir(path):
|
||||
shutil.rmtree(path) # remove dir and all contains
|
||||
|
||||
|
||||
def is_empty(path):
|
||||
if os.path.exists(path) and not os.path.isfile(path):
|
||||
# Checking if the directory is empty or not
|
||||
if not os.listdir(path):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def uninstall():
|
||||
run_command_interactive(
|
||||
["xdg-mime", "uninstall", "/opt/WingHexExplorer2/share/x-winghex.xml"])
|
||||
run_command_interactive(
|
||||
["xdg-icon-resource", "uninstall", "--context", "mimetypes", "--size", "32", "application-x-winghex"])
|
||||
run_command_interactive(
|
||||
["xdg-icon-resource", "uninstall", "--context", "mimetypes", "--size", "64", "application-x-winghex"])
|
||||
run_command_interactive(
|
||||
["xdg-icon-resource", "uninstall", "--context", "mimetypes", "--size", "128", "application-x-winghex"])
|
||||
run_command_interactive(
|
||||
["update-mime-database", "/usr/share/mime"])
|
||||
run_command_interactive(
|
||||
["xdg-icon-resource", "forceupdate"])
|
||||
run_command_interactive(
|
||||
["update-icon-caches", "/usr/share/icons/hicolor"])
|
||||
remove(os.path.join(APP_DESKTOP_PATH, DESKTOP_FILE_NAME))
|
||||
run_command_interactive(
|
||||
["update-desktop-database", "/usr/share/applications"])
|
||||
remove(INSTALL_PATH)
|
||||
print(Fore.GREEN + ">> Uninstallation finished..." + Style.RESET_ALL)
|
||||
|
||||
|
||||
CFG_PATH = ".config/WingCloudStudio"
|
||||
AUTO_START = ".config/autostart"
|
||||
CONF_FILE = "WingHexExplorer2.conf"
|
||||
CONTENT_PATH = ".local/share/WingCloudStudio"
|
||||
|
||||
|
||||
def clear_usrdata(usr):
|
||||
usr_path = ""
|
||||
if (usr == "root"):
|
||||
usr_path = "/root"
|
||||
else:
|
||||
usr_path = f"/home/{usr}"
|
||||
|
||||
desktop_file = os.path.join(usr_path, AUTO_START, DESKTOP_FILE_NAME)
|
||||
remove(desktop_file)
|
||||
|
||||
cfgpath = os.path.join(usr_path, CFG_PATH)
|
||||
|
||||
remove(os.path.join(cfgpath, CONF_FILE))
|
||||
if is_empty(cfgpath):
|
||||
remove(cfgpath)
|
||||
|
||||
cfgpath = os.path.join(usr_path, CONTENT_PATH, PACKAGE_NAME)
|
||||
remove(cfgpath)
|
||||
|
||||
cfgpath = os.path.join(usr_path, CONTENT_PATH)
|
||||
if is_empty(cfgpath):
|
||||
remove(cfgpath)
|
||||
|
||||
print(Fore.GREEN + f">> Purged ${usr}..." + Style.RESET_ALL)
|
||||
|
||||
|
||||
def purge():
|
||||
uninstall()
|
||||
for p in os.listdir("/home"):
|
||||
if p == "lost+found":
|
||||
continue
|
||||
clear_usrdata(p)
|
||||
clear_usrdata("root")
|
||||
print(Fore.GREEN + ">> Clean-up finished..." + Style.RESET_ALL)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="installer.py", description=f"A installing manager for {PACKAGE_NAME}")
|
||||
parser.add_argument(
|
||||
"action",
|
||||
choices=["install", "update", "uninstall", "purge"],
|
||||
nargs="?",
|
||||
default="install",
|
||||
help="Action to perform: install (default), update, uninstall, or purge."
|
||||
)
|
||||
parser.add_argument(
|
||||
"-b", "--build",
|
||||
type=str,
|
||||
required=False,
|
||||
help="Path to the building files for installation (required for 'install' and 'update' action)."
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
if check_is_running(PACKAGE_NAME):
|
||||
print(
|
||||
Fore.RED + f"[Error] You should exit {PACKAGE_NAME} berfore installation." + Style.RESET_ALL)
|
||||
exit(1)
|
||||
|
||||
if not is_root():
|
||||
print(
|
||||
Fore.RED + "[Error] root is required for installation." + Style.RESET_ALL)
|
||||
exit(2)
|
||||
|
||||
# checking build toolkits
|
||||
if args.action == "install":
|
||||
if not args.build:
|
||||
print(
|
||||
Fore.RED + "[Error] --build path is required for installation." + Style.RESET_ALL)
|
||||
exit(2)
|
||||
install(args.build)
|
||||
elif args.action == "update":
|
||||
if not args.build:
|
||||
print(
|
||||
Fore.RED + "[Error] --build path is required for installation." + Style.RESET_ALL)
|
||||
exit(2)
|
||||
update(args.build)
|
||||
elif args.action == "uninstall":
|
||||
uninstall()
|
||||
elif args.action == "purge":
|
||||
purge()
|
||||
|
||||
exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
else:
|
||||
print(
|
||||
Fore.RED + "[Error] Please run this script in main mode" + Style.RESET_ALL)
|
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
Binary file not shown.
After Width: | Height: | Size: 33 KiB |
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
|
||||
<mime-type type="application/x-winghex">
|
||||
<glob pattern="*.wingpro"/>
|
||||
<icon name="application-x-winghex"/>
|
||||
<comment>WingHexExplorer WorkSpace</comment>
|
||||
<comment xml:lang="zh_CN">羽云十六进制编辑器项目文件</comment>
|
||||
</mime-type>
|
||||
</mime-info>
|
|
@ -0,0 +1,14 @@
|
|||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by Project1.rc
|
||||
|
||||
// 新对象的下一组默认值
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
|
@ -119,6 +119,32 @@
|
|||
<file alias="replace.png">images/replace.png</file>
|
||||
<file alias="undo.png">images/undo.png</file>
|
||||
<file alias="goto.png">images/goto.png</file>
|
||||
|
||||
</qresource>
|
||||
<qresource prefix="/completion">
|
||||
<file>images/completion/classnew.png</file>
|
||||
<file>images/completion/CTvirtuals.png</file>
|
||||
<file>images/completion/CVclass.png</file>
|
||||
<file>images/completion/CVenum.png</file>
|
||||
<file>images/completion/CVenumerator.png</file>
|
||||
<file>images/completion/CVglobal_meth.png</file>
|
||||
<file>images/completion/CVglobal_var.png</file>
|
||||
<file>images/completion/CVnamespace.png</file>
|
||||
<file>images/completion/CVpackage_meth.png</file>
|
||||
<file>images/completion/CVpackage_var.png</file>
|
||||
<file>images/completion/CVprivate_meth.png</file>
|
||||
<file>images/completion/CVprivate_signal.png</file>
|
||||
<file>images/completion/CVprivate_slot.png</file>
|
||||
<file>images/completion/CVprivate_var.png</file>
|
||||
<file>images/completion/CVprotected_meth.png</file>
|
||||
<file>images/completion/CVprotected_signal.png</file>
|
||||
<file>images/completion/CVprotected_slot.png</file>
|
||||
<file>images/completion/CVprotected_var.png</file>
|
||||
<file>images/completion/CVpublic_meth.png</file>
|
||||
<file>images/completion/CVpublic_signal.png</file>
|
||||
<file>images/completion/CVpublic_slot.png</file>
|
||||
<file>images/completion/CVpublic_var.png</file>
|
||||
<file>images/completion/CVstruct.png</file>
|
||||
<file>images/completion/CVtypedef.png</file>
|
||||
<file>images/completion/CVunion.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "angelobjstring.h"
|
||||
#include "AngelScript/sdk/add_on/datetime/datetime.h"
|
||||
#include "AngelScript/sdk/add_on/scriptarray/scriptarray.h"
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef ANGELOBJSTRING_H
|
||||
#define ANGELOBJSTRING_H
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef ANGELSCRIPTHELPER_H
|
||||
#define ANGELSCRIPTHELPER_H
|
||||
|
||||
|
|
|
@ -1,7 +1,25 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "appmanager.h"
|
||||
|
||||
#include <QFont>
|
||||
|
||||
#include "class/logger.h"
|
||||
#include "languagemanager.h"
|
||||
#include "settingmanager.h"
|
||||
#include "skinmanager.h"
|
||||
|
@ -32,6 +50,8 @@ AppManager::AppManager(int &argc, char *argv[])
|
|||
sendMessage(buffer);
|
||||
}
|
||||
|
||||
Logger::instance();
|
||||
|
||||
auto &set = SettingManager::instance();
|
||||
QFont font(set.appFontFamily(), set.appfontSize());
|
||||
setFont(font);
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef APPMANAGER_H
|
||||
#define APPMANAGER_H
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "asbuilder.h"
|
||||
|
||||
#include <QDir>
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef ASBUILDER_H
|
||||
#define ASBUILDER_H
|
||||
|
||||
|
|
|
@ -1,11 +1,27 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "ascompletion.h"
|
||||
|
||||
#include "qasparser.h"
|
||||
#include "qcalltip.h"
|
||||
#include "qdocumentcursor.h"
|
||||
#include "qdocumentline.h"
|
||||
|
||||
// #include "plugin.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QLibraryInfo>
|
||||
#include <QQueue>
|
||||
|
@ -14,117 +30,32 @@
|
|||
#include <QTimer>
|
||||
#include <QtDebug>
|
||||
|
||||
//#define TRACE_COMPLETION
|
||||
#include "control/qcodecompletionwidget.h"
|
||||
|
||||
/*
|
||||
TODO :
|
||||
- better support for template methods based upon parameters ?
|
||||
- add support for some more operators ?
|
||||
- improve visibility guesses by taking friendship into account
|
||||
- improve visibility guesses by taking inheritance visibility
|
||||
into account
|
||||
- improve visibility guesses by taking context hierarchy into
|
||||
account
|
||||
*/
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, DOT_TRIGGER, QStringLiteral("."))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, SEMI_COLON_TRIGGER, QStringLiteral("::"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, LEFT_PARE_TRIGGER, QStringLiteral("("))
|
||||
|
||||
Q_DECL_UNUSED static void remove(QByteArray &b, char c, int i = 0) {
|
||||
i = qMax(i, 0);
|
||||
while (i < b.length()) {
|
||||
int len = 0;
|
||||
AsCompletion::AsCompletion(asIScriptEngine *engine, QObject *p)
|
||||
: QCodeCompletionEngine(p), parser(engine), _engine(engine),
|
||||
pPopup(new QCodeCompletionWidget()) {
|
||||
Q_ASSERT(engine);
|
||||
|
||||
while (((i + len) < b.length()) && (b.at(i + len) == c))
|
||||
++len;
|
||||
|
||||
if (!len)
|
||||
++i;
|
||||
else
|
||||
b.remove(i, len);
|
||||
}
|
||||
}
|
||||
|
||||
static void remove(QByteArray &b, const char *str, int i = 0) {
|
||||
i = qMax(i, 0);
|
||||
auto length = qstrlen(str);
|
||||
|
||||
while (i < b.length()) {
|
||||
if (!qstrncmp(b.constData() + i, str, length))
|
||||
b.remove(i, length);
|
||||
else
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
static bool isWord(char c) { return isalnum(c) || (c == '_'); }
|
||||
|
||||
static void substitute(QByteArray &b, const QByteArray &tpl,
|
||||
const QByteArray &crt) {
|
||||
// qDebug() << "substituting " << tpl << " with " << crt << " in " << b;
|
||||
if (b.isEmpty() || tpl.isEmpty())
|
||||
return;
|
||||
|
||||
int i = 0;
|
||||
bool _word = false;
|
||||
|
||||
while (i < b.length()) {
|
||||
int j = i + tpl.length();
|
||||
if (!_word &&
|
||||
!qstrncmp(b.constData() + i, tpl.constData(), tpl.length()) &&
|
||||
((j >= b.length()) || !isWord(b.at(j)))) {
|
||||
b.replace(i, tpl.length(), crt);
|
||||
i += crt.length();
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
|
||||
_word = i ? isWord(b.at(i - 1)) : false;
|
||||
}
|
||||
|
||||
// qDebug() << b;
|
||||
}
|
||||
|
||||
static void blockRemove(QByteArray &b, char in, char out) {
|
||||
int i = 0, s;
|
||||
|
||||
while (i < b.length()) {
|
||||
if (b.at(i) == in) {
|
||||
s = i;
|
||||
|
||||
int count = 0;
|
||||
|
||||
do {
|
||||
if (b.at(i) == in)
|
||||
++count;
|
||||
else if (b.at(i) == out)
|
||||
--count;
|
||||
|
||||
++i;
|
||||
|
||||
} while (count && (i < b.length()));
|
||||
|
||||
b.remove(s, i - s + 1);
|
||||
i = s;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AsCompletion::AsCompletion(QObject *p) : QCodeCompletionEngine(p) {
|
||||
|
||||
addTrigger(".");
|
||||
addTrigger("->");
|
||||
addTrigger("::");
|
||||
addTrigger(*DOT_TRIGGER);
|
||||
addTrigger(*SEMI_COLON_TRIGGER);
|
||||
|
||||
// unleash the power of call tips
|
||||
addTrigger("(");
|
||||
addTrigger(*LEFT_PARE_TRIGGER);
|
||||
|
||||
// EDYUK_SHORTCUT(triggerAction(), "C++ completion", tr("Ctrl+Space"));
|
||||
// TODO parse the std aslib
|
||||
|
||||
setTrigWordLen(3);
|
||||
}
|
||||
|
||||
AsCompletion::~AsCompletion() {}
|
||||
|
||||
QCodeCompletionEngine *AsCompletion::clone() {
|
||||
AsCompletion *e = new AsCompletion();
|
||||
AsCompletion *e = new AsCompletion(_engine, pPopup->editor());
|
||||
|
||||
for (auto &t : triggers())
|
||||
e->addTrigger(t);
|
||||
|
@ -134,7 +65,7 @@ QCodeCompletionEngine *AsCompletion::clone() {
|
|||
return e;
|
||||
}
|
||||
|
||||
QString AsCompletion::language() const { return "AngelScript"; }
|
||||
QString AsCompletion::language() const { return QStringLiteral("AngelScript"); }
|
||||
|
||||
QStringList AsCompletion::extensions() const {
|
||||
QStringList l;
|
||||
|
@ -145,4 +76,197 @@ QStringList AsCompletion::extensions() const {
|
|||
return l;
|
||||
}
|
||||
|
||||
void AsCompletion::complete(const QDocumentCursor &c, const QString &trigger) {}
|
||||
void AsCompletion::complete(const QDocumentCursor &c, const QString &trigger) {
|
||||
if (pPopup->isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO parse current code
|
||||
// auto codes = c.document()->text(true, false);
|
||||
// parser.parse(codes, this->editor()->fileName());
|
||||
|
||||
// QList<QCodeNode *> nodes = parser.codeNodes();
|
||||
auto txt = c.line().text().left(c.columnNumber());
|
||||
auto code = txt.toUtf8();
|
||||
|
||||
auto p = code.data();
|
||||
auto len = code.length();
|
||||
auto end = p + len;
|
||||
|
||||
struct Token {
|
||||
qsizetype pos;
|
||||
asETokenClass type;
|
||||
QByteArray content;
|
||||
};
|
||||
|
||||
QVector<Token> tokens;
|
||||
qsizetype pos = 0;
|
||||
for (; p < end;) {
|
||||
asUINT tokenLen = 0;
|
||||
auto tt = _engine->ParseToken(p, len, &tokenLen);
|
||||
Token token;
|
||||
token.pos = pos;
|
||||
token.type = tt;
|
||||
token.content = QByteArray(p, tokenLen);
|
||||
tokens << token;
|
||||
p += tokenLen;
|
||||
pos += tokenLen;
|
||||
}
|
||||
|
||||
QByteArray fn;
|
||||
QList<QCodeNode *> nodes;
|
||||
|
||||
auto r =
|
||||
std::find_if(tokens.rbegin(), tokens.rend(), [](const Token &token) {
|
||||
return token.type != asTC_WHITESPACE;
|
||||
});
|
||||
if (r == tokens.rend()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QCodeCompletionWidget::Filter filter =
|
||||
QCodeCompletionWidget::FilterFlag::KeepAll;
|
||||
auto &_headerNodes = parser.headerNodes();
|
||||
fn = r->content;
|
||||
|
||||
if (trigger.isEmpty()) {
|
||||
auto eb = tokens.back();
|
||||
if (eb.type == asTC_KEYWORD) {
|
||||
// only support these
|
||||
if (eb.content == *SEMI_COLON_TRIGGER) {
|
||||
complete(c, *SEMI_COLON_TRIGGER);
|
||||
} else if (eb.content == *DOT_TRIGGER) {
|
||||
complete(c, *DOT_TRIGGER);
|
||||
}
|
||||
return;
|
||||
} else if (eb.type == asTC_IDENTIFIER) {
|
||||
if (r != tokens.rend()) {
|
||||
auto pr = std::next(r);
|
||||
if (pr->content == *SEMI_COLON_TRIGGER) {
|
||||
if (pr != tokens.rend()) {
|
||||
auto prr = std::next(pr);
|
||||
auto ns = prr->content;
|
||||
|
||||
if (prr->type == asTC_IDENTIFIER) {
|
||||
for (auto &n : _headerNodes) {
|
||||
auto name = n->qualifiedName();
|
||||
if (name == ns) {
|
||||
nodes << n;
|
||||
}
|
||||
}
|
||||
|
||||
auto cur = c;
|
||||
cur.movePosition(pr->pos + pr->content.length() -
|
||||
txt.length());
|
||||
pPopup->setCursor(cur);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
// pPopup->setTemporaryNodes(temp);
|
||||
pPopup->setFilter(filter);
|
||||
pPopup->setCompletions(nodes);
|
||||
pPopup->popup();
|
||||
} else {
|
||||
if (trigger == *SEMI_COLON_TRIGGER) {
|
||||
for (auto &n : _headerNodes) {
|
||||
auto name = n->qualifiedName();
|
||||
if (name == fn) {
|
||||
nodes << n;
|
||||
}
|
||||
}
|
||||
} else if (trigger == *LEFT_PARE_TRIGGER) {
|
||||
if (r != tokens.rend()) {
|
||||
auto pr = std::next(r);
|
||||
if (pr->content == *SEMI_COLON_TRIGGER) {
|
||||
if (pr != tokens.rend()) {
|
||||
auto prr = std::next(pr);
|
||||
auto ns = prr->content;
|
||||
if (prr->type == asTC_IDENTIFIER) {
|
||||
for (auto &n : _headerNodes) {
|
||||
auto name = n->qualifiedName();
|
||||
if (name == ns) {
|
||||
nodes << n;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nodes.count()) {
|
||||
if (trigger == *LEFT_PARE_TRIGGER) {
|
||||
QStringList tips;
|
||||
|
||||
// qDebug("fn %s", fn.constData());
|
||||
|
||||
for (auto &n : nodes) {
|
||||
for (auto &f : n->children()) {
|
||||
if (f->type() != QCodeNode::Function ||
|
||||
f->role(QCodeNode::Name) != fn) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto tip =
|
||||
QString::fromUtf8(f->role(QCodeNode::Arguments))
|
||||
.prepend('(')
|
||||
.append(')');
|
||||
|
||||
if (!tips.contains(tip))
|
||||
tips << tip;
|
||||
}
|
||||
}
|
||||
|
||||
if (!tips.isEmpty()) {
|
||||
QRect r = editor()->cursorRect();
|
||||
QDocumentCursor cursor = editor()->cursor();
|
||||
QDocumentLine line = cursor.line();
|
||||
|
||||
int hx = editor()->horizontalOffset(),
|
||||
cx = line.cursorToX(cursor.columnNumber());
|
||||
|
||||
auto ct = new QCallTip(editor()->viewport());
|
||||
ct->move(cx - hx, r.y() + r.height());
|
||||
ct->setTips(tips);
|
||||
ct->show();
|
||||
ct->setFocus();
|
||||
|
||||
#ifdef TRACE_COMPLETION
|
||||
qDebug("parsing + scoping + search + pre-display : elapsed "
|
||||
"%i ms",
|
||||
time.elapsed());
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
// pPopup->setTemporaryNodes(temp);
|
||||
pPopup->setFilter(QCodeCompletionWidget::Filter(filter));
|
||||
pPopup->setCompletions(nodes);
|
||||
|
||||
#ifdef TRACE_COMPLETION
|
||||
qDebug(
|
||||
"parsing + scoping + search + pre-display : elapsed %i ms",
|
||||
time.elapsed());
|
||||
#endif
|
||||
|
||||
pPopup->popup();
|
||||
}
|
||||
} else {
|
||||
// qDeleteAll(temp);
|
||||
qDebug("completion failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AsCompletion::setEditor(QEditor *e) {
|
||||
QCodeCompletionEngine::setEditor(e);
|
||||
pPopup->setEditor(e);
|
||||
}
|
||||
|
|
|
@ -1,16 +1,32 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef _AS_COMPLETION_H_
|
||||
#define _AS_COMPLETION_H_
|
||||
|
||||
#include "class/qasparser.h"
|
||||
#include "qcodecompletionengine.h"
|
||||
|
||||
#include <QHash>
|
||||
|
||||
class QByteArray;
|
||||
class QCodeCompletionWidget;
|
||||
|
||||
class AsCompletion : public QCodeCompletionEngine {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AsCompletion(QObject *p = nullptr);
|
||||
explicit AsCompletion(asIScriptEngine *engine, QObject *p = nullptr);
|
||||
|
||||
virtual ~AsCompletion();
|
||||
|
||||
|
@ -19,13 +35,16 @@ public:
|
|||
virtual QString language() const override;
|
||||
virtual QStringList extensions() const override;
|
||||
|
||||
virtual void setEditor(QEditor *e) override;
|
||||
|
||||
protected:
|
||||
virtual void complete(const QDocumentCursor &c,
|
||||
const QString &trigger) override;
|
||||
|
||||
private:
|
||||
// QCodeCompletionWidget *pPopup;
|
||||
// QPointer<QCodeModel> pModel;
|
||||
QAsParser parser;
|
||||
asIScriptEngine *_engine;
|
||||
QCodeCompletionWidget *pPopup;
|
||||
};
|
||||
|
||||
#endif // _CPP_COMPLETION_H_
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "ascontextmgr.h"
|
||||
|
||||
asContextMgr::asContextMgr() : CContextMgr() {}
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef ASCONTEXTMGR_H
|
||||
#define ASCONTEXTMGR_H
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "asdebugger.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef ASDEBUGGER_H
|
||||
#define ASDEBUGGER_H
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef FOCUSOUTEVENTFILTER_H
|
||||
#define FOCUSOUTEVENTFILTER_H
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "framelesshelper.h"
|
||||
|
||||
#include "widgetframe/windowbutton.h"
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef FRAMELESSHELPER_H
|
||||
#define FRAMELESSHELPER_H
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "languagemanager.h"
|
||||
|
||||
#include "wingmessagebox.h"
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef LANGUAGEMANAGER_H
|
||||
#define LANGUAGEMANAGER_H
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "logger.h"
|
||||
#include <QApplication>
|
||||
#include <QDateTime>
|
||||
|
@ -10,8 +27,6 @@
|
|||
#define ERRLOG(msg) "<font color=\"red\">" + msg + "</font>"
|
||||
#define WARNLOG(msg) "<font color=\"gold\">" + msg + "</font>"
|
||||
|
||||
Logger *Logger::ins = new Logger;
|
||||
|
||||
Logger::Logger(QObject *parent)
|
||||
: QObject(parent), _stream(new QTextStream(stdout)) {
|
||||
_stream->device()->setTextModeEnabled(true);
|
||||
|
@ -53,44 +68,50 @@ Logger::~Logger() {
|
|||
_file->close();
|
||||
}
|
||||
|
||||
Logger *Logger::instance() { return ins; }
|
||||
Logger &Logger::instance() {
|
||||
static Logger ins;
|
||||
return ins;
|
||||
}
|
||||
|
||||
Logger::Level Logger::logLevel() const { return _level; }
|
||||
|
||||
void Logger::_log(const QString &message) { emit ins->log(message); }
|
||||
void Logger::_log(const QString &message) { emit instance().log(message); }
|
||||
|
||||
void Logger::trace(const QString &message) {
|
||||
if (instance()->_level >= q5TRACE) {
|
||||
if (instance()._level >= q5TRACE) {
|
||||
QString str = message;
|
||||
emit ins->log(tr("[Trace]") + str.replace("\n", "<br />"));
|
||||
emit instance().log(tr("[Trace]") + str.replace("\n", "<br />"));
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::warning(const QString &message) {
|
||||
if (instance()->_level >= q2WARN) {
|
||||
if (instance()._level >= q2WARN) {
|
||||
QString str = message;
|
||||
emit ins->log(WARNLOG(tr("[Warn]") + str.replace("\n", "<br />")));
|
||||
emit instance().log(
|
||||
WARNLOG(tr("[Warn]") + str.replace("\n", "<br />")));
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::info(const QString &message) {
|
||||
if (instance()->_level >= q3INFO) {
|
||||
if (instance()._level >= q3INFO) {
|
||||
QString str = message;
|
||||
emit ins->log(INFOLOG(tr("[Info]") + str.replace("\n", "<br />")));
|
||||
emit instance().log(
|
||||
INFOLOG(tr("[Info]") + str.replace("\n", "<br />")));
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::debug(const QString &message) {
|
||||
if (instance()->_level >= q4DEBUG) {
|
||||
if (instance()._level >= q4DEBUG) {
|
||||
QString str = message;
|
||||
emit ins->log(tr("[Debug]") + str.replace("\n", "<br />"));
|
||||
emit instance().log(tr("[Debug]") + str.replace("\n", "<br />"));
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::critical(const QString &message) {
|
||||
if (instance()->_level >= q0FATAL) {
|
||||
if (instance()._level >= q0FATAL) {
|
||||
QString str = message;
|
||||
emit ins->log(ERRLOG(tr("[Error]") + str.replace("\n", "<br />")));
|
||||
emit instance().log(
|
||||
ERRLOG(tr("[Error]") + str.replace("\n", "<br />")));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef LOGGER_H
|
||||
#define LOGGER_H
|
||||
|
||||
|
@ -25,7 +42,7 @@ public:
|
|||
};
|
||||
|
||||
public:
|
||||
static Logger *instance();
|
||||
static Logger &instance();
|
||||
|
||||
Level logLevel() const;
|
||||
|
||||
|
@ -57,7 +74,6 @@ private:
|
|||
Q_DISABLE_COPY_MOVE(Logger)
|
||||
|
||||
private:
|
||||
static Logger *ins;
|
||||
Level _level = Level::q4DEBUG;
|
||||
QSharedPointer<QFile> _file = nullptr;
|
||||
QSharedPointer<QTextStream> _stream = nullptr;
|
||||
|
|
|
@ -1,12 +1,167 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "qasparser.h"
|
||||
|
||||
#include "AngelScript/sdk/angelscript/source/as_builder.h"
|
||||
#include "AngelScript/sdk/angelscript/source/as_parser.h"
|
||||
#include "codemodel/qcodemodel.h"
|
||||
#include "class/qcodenode.h"
|
||||
|
||||
QAsParser::QAsParser(asIScriptEngine *engine) : asBuilder(), _engine(engine) {}
|
||||
#include <QDebug>
|
||||
|
||||
QAsParser::~QAsParser() {}
|
||||
/*
|
||||
* Completion only support: Internal classes, enums and methods,
|
||||
* Standard libraries and included headers,
|
||||
* global classes, enums and methods in opened codes
|
||||
*
|
||||
* If you want to make it more powerful, PR will be welcomed.
|
||||
*/
|
||||
|
||||
QAsParser::QAsParser(asIScriptEngine *engine) : asBuilder(), _engine(engine) {
|
||||
addGlobalFunctionCompletion(engine);
|
||||
addClassCompletion(engine);
|
||||
addEnumCompletion(engine);
|
||||
}
|
||||
|
||||
QAsParser::~QAsParser() {
|
||||
qDeleteAll(_headerNodes);
|
||||
_headerNodes.clear();
|
||||
}
|
||||
|
||||
QByteArray QAsParser::getFnParamDeclString(asIScriptFunction *fn,
|
||||
bool includeNamespace,
|
||||
bool includeParamNames) {
|
||||
auto fun = dynamic_cast<asCScriptFunction *>(fn);
|
||||
if (fun == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
asCString str;
|
||||
|
||||
auto ¶meterTypes = fun->parameterTypes;
|
||||
auto ¶meterNames = fun->parameterNames;
|
||||
auto &nameSpace = fun->nameSpace;
|
||||
auto &inOutFlags = fun->inOutFlags;
|
||||
auto &defaultArgs = fun->defaultArgs;
|
||||
|
||||
if (parameterTypes.GetLength() > 0) {
|
||||
asUINT n;
|
||||
for (n = 0; n < parameterTypes.GetLength() - 1; n++) {
|
||||
str += parameterTypes[n].Format(nameSpace, includeNamespace);
|
||||
if (parameterTypes[n].IsReference() && inOutFlags.GetLength() > n) {
|
||||
if (inOutFlags[n] == asTM_INREF)
|
||||
str += "in";
|
||||
else if (inOutFlags[n] == asTM_OUTREF)
|
||||
str += "out";
|
||||
else if (inOutFlags[n] == asTM_INOUTREF)
|
||||
str += "inout";
|
||||
}
|
||||
|
||||
if (includeParamNames && n < parameterNames.GetLength() &&
|
||||
parameterNames[n].GetLength() != 0) {
|
||||
str += " ";
|
||||
str += parameterNames[n];
|
||||
}
|
||||
|
||||
if (defaultArgs.GetLength() > n && defaultArgs[n]) {
|
||||
asCString tmp;
|
||||
tmp.Format(" = %s", defaultArgs[n]->AddressOf());
|
||||
str += tmp;
|
||||
}
|
||||
|
||||
str += ", ";
|
||||
}
|
||||
|
||||
// Add the last parameter
|
||||
str += parameterTypes[n].Format(nameSpace, includeNamespace);
|
||||
if (parameterTypes[n].IsReference() && inOutFlags.GetLength() > n) {
|
||||
if (inOutFlags[n] == asTM_INREF)
|
||||
str += "in";
|
||||
else if (inOutFlags[n] == asTM_OUTREF)
|
||||
str += "out";
|
||||
else if (inOutFlags[n] == asTM_INOUTREF)
|
||||
str += "inout";
|
||||
}
|
||||
|
||||
if (includeParamNames && n < parameterNames.GetLength() &&
|
||||
parameterNames[n].GetLength() != 0) {
|
||||
str += " ";
|
||||
str += parameterNames[n];
|
||||
}
|
||||
|
||||
if (defaultArgs.GetLength() > n && defaultArgs[n]) {
|
||||
asCString tmp;
|
||||
tmp.Format(" = %s", defaultArgs[n]->AddressOf());
|
||||
str += tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return QByteArray(str.AddressOf(), str.GetLength());
|
||||
}
|
||||
|
||||
QByteArray QAsParser::getFnRealName(asIScriptFunction *fn) {
|
||||
auto fun = dynamic_cast<asCScriptFunction *>(fn);
|
||||
if (fun == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
asCString str;
|
||||
asCString name = fun->GetName();
|
||||
|
||||
if (name.GetLength() == 0)
|
||||
str += "_unnamed_function_";
|
||||
else if (name.SubString(0, 4) == "$beh" && name.GetLength() == 5) {
|
||||
if (name[4] == '0' + asBEHAVE_CONSTRUCT)
|
||||
str += fun->objectType->name;
|
||||
else if (name[4] == '0' + asBEHAVE_FACTORY)
|
||||
str += fun->returnType.GetTypeInfo()->name;
|
||||
else if (name[4] == '0' + asBEHAVE_DESTRUCT)
|
||||
str += "~" + fun->objectType->name;
|
||||
else
|
||||
str += name;
|
||||
} else {
|
||||
str = name;
|
||||
}
|
||||
|
||||
return QByteArray(str.AddressOf(), str.GetLength());
|
||||
}
|
||||
|
||||
QByteArray QAsParser::getFnRetTypeString(asIScriptFunction *fn,
|
||||
bool includeNamespace) {
|
||||
auto fun = dynamic_cast<asCScriptFunction *>(fn);
|
||||
if (fun == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto &returnType = fun->returnType;
|
||||
auto &objectType = fun->objectType;
|
||||
auto &name = fun->name;
|
||||
auto &nameSpace = fun->nameSpace;
|
||||
|
||||
if (!(returnType.GetTokenType() == ttVoid && objectType &&
|
||||
(name == objectType->name ||
|
||||
(name.GetLength() > 0 && name[0] == '~') || name == "$beh0" ||
|
||||
name == "$beh2"))) {
|
||||
auto str = returnType.Format(nameSpace, includeNamespace);
|
||||
return QByteArray(str.AddressOf(), str.GetLength());
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool QAsParser::parse(const QString &filename) {
|
||||
if (StartNewModule(_engine, "as_parser") != 0) {
|
||||
|
@ -21,6 +176,7 @@ bool QAsParser::parse(const QString &filename) {
|
|||
ClearAll();
|
||||
|
||||
auto mod = dynamic_cast<asCModule *>(GetModule());
|
||||
Q_ASSERT(mod);
|
||||
asCParser parser(mod->m_builder);
|
||||
|
||||
m_code.reset(new asCScriptCode);
|
||||
|
@ -28,9 +184,274 @@ bool QAsParser::parse(const QString &filename) {
|
|||
|
||||
parser.ParseScript(m_code.get());
|
||||
|
||||
auto nodes = parser.GetScriptNode();
|
||||
auto pnodes = parser.GetScriptNode();
|
||||
|
||||
QCodeModel model;
|
||||
QList<QCodeNode *> qnodes;
|
||||
|
||||
// do {
|
||||
// auto node = asNode2CodeNode(pnodes);
|
||||
|
||||
// auto p = pnodes->firstChild;
|
||||
// while (p) {
|
||||
// auto cnode = asNode2CodeNode(pnodes);
|
||||
// cnode->parent = node;
|
||||
// node->children.append(cnode);
|
||||
|
||||
// p = pnodes->next;
|
||||
// }
|
||||
|
||||
// qnodes.append(node);
|
||||
// pnodes = pnodes->next;
|
||||
// } while (pnodes != nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QAsParser::parse(const QString &code, const QString §ion) {
|
||||
return ProcessScriptSection(code.toUtf8(), code.length(), section, 0);
|
||||
}
|
||||
|
||||
const QList<QCodeNode *> &QAsParser::headerNodes() const {
|
||||
return _headerNodes;
|
||||
}
|
||||
|
||||
void QAsParser::addGlobalFunctionCompletion(asIScriptEngine *engine) {
|
||||
Q_ASSERT(engine);
|
||||
|
||||
QHash<QByteArray, QList<FnInfo>> _maps;
|
||||
|
||||
for (asUINT i = 0; i < engine->GetGlobalFunctionCount(); ++i) {
|
||||
auto fn = engine->GetGlobalFunctionByIndex(i);
|
||||
|
||||
FnInfo fnInfo;
|
||||
auto ns = fn->GetNamespace();
|
||||
fnInfo.retType = getFnRetTypeString(fn, true);
|
||||
fnInfo.fnName = fn->GetName();
|
||||
fnInfo.params = getFnParamDeclString(fn, false, true);
|
||||
fnInfo.isConst = fn->IsReadOnly();
|
||||
|
||||
_maps[ns] << fnInfo;
|
||||
}
|
||||
|
||||
for (auto p = _maps.keyValueBegin(); p != _maps.keyValueEnd(); p++) {
|
||||
auto node = new QCodeNode;
|
||||
_headerNodes << node;
|
||||
if (p->first.isEmpty()) {
|
||||
node->setNodeType(QCodeNode::Group);
|
||||
} else {
|
||||
node->setNodeType(QCodeNode::Namespace);
|
||||
}
|
||||
node->setRole(QCodeNode::Name, p->first);
|
||||
|
||||
auto pnodes = &node->children();
|
||||
auto nodeParent = node;
|
||||
|
||||
for (auto &fn : p->second) {
|
||||
auto node = newFnCodeNode(fn);
|
||||
node->setParent(nodeParent);
|
||||
pnodes->append(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QAsParser::addEnumCompletion(asIScriptEngine *engine) {
|
||||
Q_ASSERT(engine);
|
||||
|
||||
QHash<QByteArray, QList<EnumInfo>> _maps;
|
||||
|
||||
for (asUINT i = 0; i < engine->GetEnumCount(); ++i) {
|
||||
auto etype = engine->GetEnumByIndex(i);
|
||||
etype->AddRef();
|
||||
|
||||
EnumInfo einfo;
|
||||
auto ns = etype->GetNamespace();
|
||||
einfo.name = etype->GetName();
|
||||
|
||||
for (asUINT i = 0; i < etype->GetEnumValueCount(); ++i) {
|
||||
int v;
|
||||
auto e = etype->GetEnumValueByIndex(i, &v);
|
||||
einfo.enums.append(qMakePair(QByteArray(e), v));
|
||||
}
|
||||
|
||||
etype->Release();
|
||||
|
||||
_maps[ns] << einfo;
|
||||
}
|
||||
|
||||
for (auto p = _maps.keyValueBegin(); p != _maps.keyValueEnd(); p++) {
|
||||
auto node = new QCodeNode;
|
||||
_headerNodes << node;
|
||||
if (p->first.isEmpty()) {
|
||||
node->setNodeType(QCodeNode::Group);
|
||||
} else {
|
||||
node->setNodeType(QCodeNode::Namespace);
|
||||
}
|
||||
node->setRole(QCodeNode::Name, p->first);
|
||||
|
||||
auto pnodes = &node->children();
|
||||
auto nodeParent = node;
|
||||
for (auto &e : p->second) {
|
||||
auto node = new QCodeNode;
|
||||
node->setNodeType(QCodeNode::Enum);
|
||||
node->setRole(QCodeNode::Name, e.name);
|
||||
node->setParent(nodeParent);
|
||||
pnodes->append(node);
|
||||
|
||||
auto enode = newEnumCodeNode(e);
|
||||
_headerNodes << enode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QAsParser::addClassCompletion(asIScriptEngine *engine) {
|
||||
auto eng = dynamic_cast<asCScriptEngine *>(engine);
|
||||
Q_ASSERT(eng);
|
||||
|
||||
QHash<QByteArray, QList<ClassInfo>> _maps;
|
||||
|
||||
for (asUINT i = 0; i < engine->GetObjectTypeCount(); ++i) {
|
||||
auto obj = eng->registeredObjTypes[i];
|
||||
obj->AddRef();
|
||||
|
||||
ClassInfo cls;
|
||||
cls.name = obj->GetName();
|
||||
auto ns = obj->GetNamespace();
|
||||
|
||||
for (asUINT i = 0; i < obj->GetBehaviourCount(); ++i) {
|
||||
asEBehaviours bv;
|
||||
auto b = obj->GetBehaviourByIndex(i, &bv);
|
||||
|
||||
switch (bv) {
|
||||
case asBEHAVE_CONSTRUCT:
|
||||
case asBEHAVE_DESTRUCT: {
|
||||
// only these are supported
|
||||
b->AddRef();
|
||||
FnInfo fn;
|
||||
fn.fnName = getFnRealName(b);
|
||||
fn.params = getFnParamDeclString(b, false, true);
|
||||
fn.isConst = b->IsReadOnly();
|
||||
cls.methods << fn;
|
||||
b->Release();
|
||||
}
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for (asUINT i = 0; i < obj->GetMethodCount(); ++i) {
|
||||
auto m = obj->GetMethodByIndex(i, true);
|
||||
|
||||
m->AddRef();
|
||||
FnInfo fn;
|
||||
fn.retType = getFnRetTypeString(m, true);
|
||||
fn.fnName = getFnRealName(m);
|
||||
fn.params = getFnParamDeclString(m, false, true);
|
||||
fn.isConst = m->IsReadOnly();
|
||||
cls.methods << fn;
|
||||
m->Release();
|
||||
}
|
||||
|
||||
for (asUINT i = 0; i < obj->GetPropertyCount(); ++i) {
|
||||
auto p = obj->properties[i];
|
||||
|
||||
PropertyInfo pi;
|
||||
pi.name = QByteArray(p->name.AddressOf(), p->name.GetLength());
|
||||
auto tn = p->type.Format(obj->nameSpace);
|
||||
pi.type = QByteArray(tn.AddressOf(), tn.GetLength());
|
||||
pi.isPrivate = pi.isPrivate;
|
||||
pi.isProtected = pi.isProtected;
|
||||
pi.isRef = pi.isRef;
|
||||
|
||||
cls.properties << pi;
|
||||
}
|
||||
|
||||
obj->Release();
|
||||
|
||||
_maps[ns] << cls;
|
||||
}
|
||||
|
||||
for (auto p = _maps.keyValueBegin(); p != _maps.keyValueEnd(); p++) {
|
||||
auto node = new QCodeNode;
|
||||
_headerNodes << node;
|
||||
if (p->first.isEmpty()) {
|
||||
node->setNodeType(QCodeNode::Group);
|
||||
} else {
|
||||
node->setNodeType(QCodeNode::Namespace);
|
||||
}
|
||||
node->setRole(QCodeNode::Name, p->first);
|
||||
|
||||
auto pnodes = &node->children();
|
||||
auto nodeParent = node;
|
||||
for (auto &cls : p->second) {
|
||||
auto node = new QCodeNode;
|
||||
node->setNodeType(QCodeNode::Class);
|
||||
node->setRole(QCodeNode::Name, cls.name);
|
||||
node->setParent(nodeParent);
|
||||
pnodes->append(node);
|
||||
|
||||
auto clsnode = new QCodeNode;
|
||||
_headerNodes << clsnode;
|
||||
clsnode->setNodeType(QCodeNode::Class);
|
||||
clsnode->setRole(QCodeNode::Name, cls.name);
|
||||
for (auto &m : cls.methods) {
|
||||
auto node = newFnCodeNode(m);
|
||||
node->setParent(clsnode);
|
||||
clsnode->children().append(node);
|
||||
}
|
||||
|
||||
for (auto &p : cls.properties) {
|
||||
auto node = new QCodeNode;
|
||||
node->setNodeType(QCodeNode::Variable);
|
||||
node->setRole(QCodeNode::Name, p.name);
|
||||
node->setRole(QCodeNode::Type, p.type);
|
||||
|
||||
QByteArray visibility;
|
||||
if (p.isPrivate) {
|
||||
visibility.setNum(QCodeNode::VISIBILITY_PRIVATE);
|
||||
} else if (p.isProtected) {
|
||||
visibility.setNum(QCodeNode::VISIBILITY_PROTECTED);
|
||||
} else {
|
||||
visibility.setNum(QCodeNode::VISIBILITY_PUBLIC);
|
||||
}
|
||||
|
||||
node->setRole(QCodeNode::Visibility, visibility);
|
||||
node->setParent(clsnode);
|
||||
clsnode->children().append(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QCodeNode *QAsParser::newFnCodeNode(const FnInfo &info) {
|
||||
auto node = new QCodeNode;
|
||||
node->setNodeType(QCodeNode::Function);
|
||||
node->setNodeType(QCodeNode::Function);
|
||||
node->setRole(QCodeNode::Return, info.retType);
|
||||
node->setRole(QCodeNode::Name, info.fnName);
|
||||
node->setRole(QCodeNode::Arguments, info.params);
|
||||
QByteArray qualifiers;
|
||||
if (info.isConst) {
|
||||
qualifiers.setNum(QCodeNode::QUALIFIER_CONST);
|
||||
}
|
||||
node->setRole(QCodeNode::Qualifiers, qualifiers);
|
||||
return node;
|
||||
}
|
||||
|
||||
QCodeNode *QAsParser::newEnumCodeNode(const EnumInfo &info) {
|
||||
auto enode = new QCodeNode;
|
||||
enode->setNodeType(QCodeNode::Enum);
|
||||
enode->setRole(QCodeNode::Name, info.name);
|
||||
for (auto &ev : info.enums) {
|
||||
auto node = new QCodeNode;
|
||||
node->setNodeType(QCodeNode::Enumerator);
|
||||
node->setRole(QCodeNode::Name, ev.first);
|
||||
QByteArray value;
|
||||
value.setNum(ev.second);
|
||||
node->setRole(QCodeNode::Value, value);
|
||||
node->setParent(enode);
|
||||
enode->children().append(node);
|
||||
}
|
||||
return enode;
|
||||
}
|
||||
|
||||
QList<QCodeNode *> QAsParser::codeNodes() const { return _nodes; }
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef _QAS_PARSER_H_
|
||||
#define _QAS_PARSER_H_
|
||||
|
||||
|
@ -6,19 +23,73 @@
|
|||
#include <QScopedPointer>
|
||||
|
||||
class asCScriptCode;
|
||||
class asCScriptNode;
|
||||
class QCodeNode;
|
||||
|
||||
class QAsParser : protected asBuilder {
|
||||
public:
|
||||
explicit QAsParser(asIScriptEngine *engine);
|
||||
virtual ~QAsParser();
|
||||
|
||||
private:
|
||||
struct FnInfo {
|
||||
QByteArray retType;
|
||||
QByteArray fnName;
|
||||
QByteArray params;
|
||||
bool isConst = false;
|
||||
};
|
||||
|
||||
struct EnumInfo {
|
||||
QByteArray name;
|
||||
QList<QPair<QByteArray, int>> enums;
|
||||
};
|
||||
|
||||
struct PropertyInfo {
|
||||
QByteArray name;
|
||||
QByteArray type;
|
||||
bool isProtected = false;
|
||||
bool isPrivate = false;
|
||||
bool isRef = false;
|
||||
};
|
||||
|
||||
struct ClassInfo {
|
||||
QByteArray name;
|
||||
QList<FnInfo> methods;
|
||||
QList<PropertyInfo> properties;
|
||||
};
|
||||
|
||||
private:
|
||||
QByteArray getFnParamDeclString(asIScriptFunction *fn,
|
||||
bool includeNamespace,
|
||||
bool includeParamNames);
|
||||
|
||||
QByteArray getFnRealName(asIScriptFunction *fn);
|
||||
|
||||
QByteArray getFnRetTypeString(asIScriptFunction *fn, bool includeNamespace);
|
||||
|
||||
public:
|
||||
bool parse(const QString &filename);
|
||||
bool parse(const QString &code, const QString §ion);
|
||||
|
||||
QList<QCodeNode *> codeNodes() const;
|
||||
|
||||
const QList<QCodeNode *> &headerNodes() const;
|
||||
|
||||
private:
|
||||
void addGlobalFunctionCompletion(asIScriptEngine *engine);
|
||||
void addEnumCompletion(asIScriptEngine *engine);
|
||||
void addClassCompletion(asIScriptEngine *engine);
|
||||
|
||||
private:
|
||||
QCodeNode *newFnCodeNode(const FnInfo &info);
|
||||
|
||||
QCodeNode *newEnumCodeNode(const EnumInfo &info);
|
||||
|
||||
private:
|
||||
asIScriptEngine *_engine;
|
||||
|
||||
QScopedPointer<asCScriptCode> m_code;
|
||||
QList<QCodeNode *> _headerNodes;
|
||||
QList<QCodeNode *> _nodes;
|
||||
};
|
||||
|
||||
#endif // !_QCPP_PARSER_H_
|
||||
|
|
|
@ -0,0 +1,412 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** 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 "qcodenode.h"
|
||||
|
||||
#include <QIcon>
|
||||
#include <QVariant>
|
||||
|
||||
enum CacheIndex {
|
||||
ICON_ENUM,
|
||||
ICON_ENUMERATOR,
|
||||
// ICON_UNION,
|
||||
ICON_CLASS,
|
||||
// ICON_STRUCT,
|
||||
ICON_TYPEDEF,
|
||||
ICON_NAMESPACE,
|
||||
ICON_FUNCTION = ICON_NAMESPACE + 2,
|
||||
ICON_VARIABLE = ICON_FUNCTION + 5
|
||||
};
|
||||
|
||||
using IconHash = QHash<int, QIcon>;
|
||||
Q_GLOBAL_STATIC(IconHash, q_icon_cache)
|
||||
|
||||
inline static QIcon getIcon(const QString &name) {
|
||||
return QIcon(QStringLiteral(":/completion/images/completion/") + name +
|
||||
QStringLiteral(".png"));
|
||||
}
|
||||
|
||||
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] = getIcon(QStringLiteral("CVenum"));
|
||||
(*q_icon_cache)[ICON_ENUMERATOR] =
|
||||
getIcon(QStringLiteral("CVenumerator"));
|
||||
|
||||
(*q_icon_cache)[ICON_CLASS] = getIcon(QStringLiteral("CVclass"));
|
||||
|
||||
// q_icon_cache[ICON_STRUCT] = QIcon(":/completion/CVstruct.png");
|
||||
|
||||
(*q_icon_cache)[ICON_TYPEDEF] = getIcon(QStringLiteral("CVtypedef"));
|
||||
|
||||
(*q_icon_cache)[ICON_NAMESPACE] =
|
||||
getIcon(QStringLiteral("CVnamespace"));
|
||||
|
||||
(*q_icon_cache)[ICON_FUNCTION + QCodeNode::VISIBILITY_DEFAULT] =
|
||||
getIcon(QStringLiteral("CVglobal_meth"));
|
||||
|
||||
(*q_icon_cache)[ICON_FUNCTION + QCodeNode::VISIBILITY_PUBLIC] =
|
||||
getIcon(QStringLiteral("CVpublic_meth"));
|
||||
|
||||
(*q_icon_cache)[ICON_FUNCTION + QCodeNode::VISIBILITY_PROTECTED] =
|
||||
getIcon(QStringLiteral("CVprotected_meth"));
|
||||
|
||||
(*q_icon_cache)[ICON_FUNCTION + QCodeNode::VISIBILITY_PRIVATE] =
|
||||
getIcon(QStringLiteral("CVprivate_meth"));
|
||||
|
||||
// q_icon_cache[ICON_FUNCTION + QCodeNode::VISIBILITY_SIGNAL] =
|
||||
// QIcon(":/completion/CVprotected_signal.png");
|
||||
|
||||
(*q_icon_cache)[ICON_VARIABLE + QCodeNode::VISIBILITY_DEFAULT] =
|
||||
getIcon(QStringLiteral("CVglobal_var"));
|
||||
|
||||
(*q_icon_cache)[ICON_VARIABLE + QCodeNode::VISIBILITY_PUBLIC] =
|
||||
getIcon(QStringLiteral("CVpublic_var"));
|
||||
|
||||
(*q_icon_cache)[ICON_VARIABLE + QCodeNode::VISIBILITY_PROTECTED] =
|
||||
getIcon(QStringLiteral("CVprotected_var"));
|
||||
|
||||
(*q_icon_cache)[ICON_VARIABLE + QCodeNode::VISIBILITY_PRIVATE] =
|
||||
getIcon(QStringLiteral("CVprivate_var"));
|
||||
|
||||
setup = true;
|
||||
}
|
||||
|
||||
return q_icon_cache->value(cacheIndex);
|
||||
}
|
||||
|
||||
QCodeNode::QCodeNode() : line(-1), _parent(nullptr) {}
|
||||
|
||||
QCodeNode::~QCodeNode() {
|
||||
QCodeNode::detach();
|
||||
|
||||
_parent = nullptr;
|
||||
|
||||
clear();
|
||||
}
|
||||
|
||||
void QCodeNode::attach(QCodeNode *p) {
|
||||
detach();
|
||||
|
||||
if (!p || p->_children.contains(this))
|
||||
return;
|
||||
|
||||
int row = p->_children.length();
|
||||
|
||||
_parent = p;
|
||||
p->_children.insert(row, this);
|
||||
}
|
||||
|
||||
void QCodeNode::detach() {
|
||||
if (!_parent)
|
||||
return;
|
||||
|
||||
int row = _parent->_children.indexOf(this);
|
||||
|
||||
if (row < 0)
|
||||
return;
|
||||
|
||||
_parent->_children.removeAt(row);
|
||||
_parent = 0;
|
||||
}
|
||||
|
||||
QCodeNode *QCodeNode::parent() const { return _parent; }
|
||||
|
||||
void QCodeNode::setParent(QCodeNode *newParent) { _parent = newParent; }
|
||||
|
||||
int QCodeNode::getLine() const { return line; }
|
||||
|
||||
void QCodeNode::setLine(int newLine) { line = newLine; }
|
||||
|
||||
void QCodeNode::clear() {
|
||||
QList<QCodeNode *> c = _children;
|
||||
|
||||
removeAll();
|
||||
|
||||
qDeleteAll(c);
|
||||
}
|
||||
|
||||
void QCodeNode::removeAll() {
|
||||
if (_children.isEmpty())
|
||||
return;
|
||||
|
||||
for (auto &n : _children) {
|
||||
n->_parent = nullptr;
|
||||
}
|
||||
|
||||
_children.clear();
|
||||
}
|
||||
|
||||
int QCodeNode::type() const {
|
||||
return roles.value(NodeType, QByteArray(1, 0)).at(0);
|
||||
}
|
||||
|
||||
QByteArray QCodeNode::context() const {
|
||||
int t = type();
|
||||
|
||||
if ((t == Group) || (t == Namespace))
|
||||
return QByteArray();
|
||||
|
||||
const QCodeNode *p = this;
|
||||
|
||||
while (p->_parent) {
|
||||
int t = p->_parent->type();
|
||||
|
||||
if ((t == Group) || (t == Namespace))
|
||||
break;
|
||||
|
||||
p = p->_parent;
|
||||
}
|
||||
|
||||
return p ? p->role(Context) : role(Context);
|
||||
}
|
||||
|
||||
QByteArray QCodeNode::qualifiedName(bool ext) const {
|
||||
int t = type();
|
||||
|
||||
if (t == Group)
|
||||
return QByteArray();
|
||||
|
||||
QByteArray cxt;
|
||||
if (ext) {
|
||||
if (_parent && _parent->type() == Namespace) {
|
||||
cxt += _parent->role(Name);
|
||||
}
|
||||
cxt += "::";
|
||||
}
|
||||
|
||||
cxt += role(Name);
|
||||
|
||||
if (t == Function) {
|
||||
cxt += "(";
|
||||
cxt += role(Arguments);
|
||||
cxt += ")";
|
||||
}
|
||||
|
||||
return cxt;
|
||||
}
|
||||
|
||||
QVariant QCodeNode::data(int r) const {
|
||||
const int t = type();
|
||||
|
||||
switch (r) {
|
||||
case Qt::DisplayRole: {
|
||||
if (t == Function)
|
||||
return role(Name) + "(" + role(Arguments) + ")";
|
||||
|
||||
return role(Name);
|
||||
}
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
case Qt::StatusTipRole: {
|
||||
switch (t) {
|
||||
case Class: {
|
||||
QByteArray d("class ");
|
||||
d += role(Name);
|
||||
|
||||
QByteArray a = role(Ancestors);
|
||||
|
||||
if (a.length())
|
||||
d += " : " + a;
|
||||
|
||||
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);
|
||||
|
||||
case Typedef:
|
||||
return QByteArray("typedef ") + role(Alias) + " " + role(Name);
|
||||
|
||||
case Variable: {
|
||||
QByteArray signature, specifier;
|
||||
|
||||
signature += role(Type);
|
||||
signature += " ";
|
||||
signature += role(Name);
|
||||
|
||||
int m_visibility = role(Visibility).toInt();
|
||||
int m_specifiers = role(Specifiers).toInt();
|
||||
|
||||
// visibility (for class members)
|
||||
if (m_visibility == QCodeNode::VISIBILITY_PUBLIC)
|
||||
specifier = " public ";
|
||||
else if (m_visibility == QCodeNode::VISIBILITY_PROTECTED)
|
||||
specifier = " protected ";
|
||||
else
|
||||
specifier = " private ";
|
||||
|
||||
// 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() + "]";
|
||||
|
||||
return signature;
|
||||
// return role(Type) + " " + role(Name);
|
||||
}
|
||||
|
||||
case Function: {
|
||||
QByteArray signature, qualifier, ret = role(Return);
|
||||
|
||||
if (ret.length())
|
||||
signature += ret + " ";
|
||||
|
||||
signature += role(Name);
|
||||
|
||||
signature += "(";
|
||||
signature += role(Arguments);
|
||||
signature += ")";
|
||||
|
||||
int m_qualifiers = role(Qualifiers).toInt();
|
||||
|
||||
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();
|
||||
|
||||
if (m_visibility == QCodeNode::VISIBILITY_PUBLIC)
|
||||
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
|
||||
qualifier.prepend(" global ");
|
||||
|
||||
if (ret.isEmpty()) {
|
||||
if (role(Name).startsWith("~"))
|
||||
qualifier += " destructor ";
|
||||
else
|
||||
qualifier += " constructor ";
|
||||
}
|
||||
|
||||
if (qualifier.length())
|
||||
signature += " [" + qualifier.simplified() + "]";
|
||||
|
||||
// return role(Name) + " " + role(Name);
|
||||
return signature;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::DecorationRole: {
|
||||
switch (t) {
|
||||
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);
|
||||
|
||||
case Typedef:
|
||||
return icon(ICON_TYPEDEF);
|
||||
|
||||
case Variable:
|
||||
return icon(ICON_VARIABLE + role(Visibility).toInt());
|
||||
|
||||
case Function:
|
||||
return icon(ICON_FUNCTION + role(Visibility).toInt());
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QByteArray QCodeNode::role(RoleIndex r) const { return roles.value(r); }
|
||||
|
||||
void QCodeNode::setRole(RoleIndex r, const QByteArray &b) { roles[r] = b; }
|
||||
|
||||
void QCodeNode::setNodeType(DefaultNodeTypes t) {
|
||||
setRole(NodeType, QByteArray(1, t));
|
||||
}
|
|
@ -16,17 +16,13 @@
|
|||
#ifndef _QCODE_NODE_H_
|
||||
#define _QCODE_NODE_H_
|
||||
|
||||
#include "qcm-config.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <QVariant>
|
||||
|
||||
class QVariant;
|
||||
|
||||
class QCodeModel;
|
||||
class QCodeNodePool;
|
||||
|
||||
struct QCM_EXPORT QCodeNode {
|
||||
class QCodeNode final {
|
||||
public:
|
||||
enum RoleIndex {
|
||||
NodeType = 0,
|
||||
Name = 1,
|
||||
|
@ -57,12 +53,11 @@ struct QCM_EXPORT QCodeNode {
|
|||
Context = -1
|
||||
};
|
||||
|
||||
enum DefaultNodeTypes {
|
||||
enum DefaultNodeTypes : char {
|
||||
Group = 'g',
|
||||
Language = 'l',
|
||||
|
||||
Class = 'c',
|
||||
Struct = 's',
|
||||
// Struct = 's',
|
||||
|
||||
Function = 'f',
|
||||
|
||||
|
@ -71,7 +66,7 @@ struct QCM_EXPORT QCodeNode {
|
|||
Enum = 'e',
|
||||
Enumerator = 'r',
|
||||
|
||||
Union = 'u',
|
||||
// Union = 'u',
|
||||
|
||||
Namespace = 'n',
|
||||
|
||||
|
@ -87,7 +82,6 @@ struct QCM_EXPORT QCodeNode {
|
|||
enum NodeVisibility {
|
||||
VISIBILITY_DEFAULT = -1,
|
||||
VISIBILITY_PUBLIC,
|
||||
VISIBILITY_SIGNAL,
|
||||
VISIBILITY_PROTECTED,
|
||||
VISIBILITY_PRIVATE
|
||||
};
|
||||
|
@ -95,12 +89,9 @@ 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
|
||||
SPECIFIER_AUTO = 2,
|
||||
SPECIFIER_STATIC = 4,
|
||||
SPECIFIER_EXTERN = 8
|
||||
};
|
||||
|
||||
typedef QFlags<Specifier> TypeSpecifier;
|
||||
|
@ -108,44 +99,47 @@ struct QCM_EXPORT QCodeNode {
|
|||
enum Qualifier {
|
||||
QUALIFIER_NONE = 0,
|
||||
QUALIFIER_CONST = 1,
|
||||
QUALIFIER_VOLATILE = 2,
|
||||
QUALIFIER_STATIC = 4,
|
||||
QUALIFIER_EXTERN = 8,
|
||||
QUALIFIER_VIRTUAL = 16,
|
||||
QUALIFIER_PURE_VIRTUAL = 32,
|
||||
QUALIFIER_INLINE = 64
|
||||
QUALIFIER_EXTERN = 2,
|
||||
QUALIFIER_VIRTUAL = 4,
|
||||
QUALIFIER_INLINE = 8
|
||||
};
|
||||
|
||||
typedef QFlags<Qualifier> FunctionQualifier;
|
||||
|
||||
public:
|
||||
QCodeNode();
|
||||
QCodeNode(QCodeNodePool *p);
|
||||
virtual ~QCodeNode();
|
||||
~QCodeNode();
|
||||
|
||||
void operator delete(void *p);
|
||||
int type() const;
|
||||
QByteArray context() const;
|
||||
QByteArray qualifiedName(bool ext = false) const;
|
||||
|
||||
virtual int type() const;
|
||||
virtual QByteArray context() const;
|
||||
virtual QByteArray qualifiedName(bool language = true) const;
|
||||
|
||||
virtual QVariant data(int role) const;
|
||||
virtual void setData(int role, const QVariant &v);
|
||||
QVariant data(int role) const;
|
||||
|
||||
QByteArray role(RoleIndex r) const;
|
||||
void setRole(RoleIndex r, const QByteArray &b);
|
||||
|
||||
virtual void clear();
|
||||
virtual void removeAll();
|
||||
QList<QCodeNode *> &children() { return _children; }
|
||||
|
||||
virtual void attach(QCodeNode *p);
|
||||
virtual void detach();
|
||||
void setNodeType(DefaultNodeTypes t);
|
||||
|
||||
int line;
|
||||
QByteArray roles;
|
||||
QCodeNode *parent;
|
||||
QCodeModel *model;
|
||||
QCodeNodePool *m_pool;
|
||||
QList<QCodeNode *> children;
|
||||
void clear();
|
||||
void removeAll();
|
||||
|
||||
void attach(QCodeNode *p);
|
||||
void detach();
|
||||
|
||||
QCodeNode *parent() const;
|
||||
void setParent(QCodeNode *newParent);
|
||||
|
||||
int getLine() const;
|
||||
void setLine(int newLine);
|
||||
|
||||
private:
|
||||
int line = -1;
|
||||
QMap<RoleIndex, QByteArray> roles;
|
||||
QCodeNode *_parent = nullptr;
|
||||
QList<QCodeNode *> _children;
|
||||
};
|
||||
|
||||
#endif // !_QCODE_NODE_H_
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "qkeysequences.h"
|
||||
|
||||
QKeySequences::QKeySequences() {
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef QKEYSEQUENCES_H
|
||||
#define QKEYSEQUENCES_H
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "recentfilemanager.h"
|
||||
#include "control/toast.h"
|
||||
#include "utilities.h"
|
||||
|
@ -6,7 +23,8 @@
|
|||
#include <QFile>
|
||||
#include <QMenu>
|
||||
|
||||
RecentFileManager::RecentFileManager(QMenu *menu) : QObject(), m_menu(menu) {
|
||||
RecentFileManager::RecentFileManager(QMenu *menu, bool fileNameOnly)
|
||||
: QObject(), m_menu(menu), _fileNameOnly(fileNameOnly) {
|
||||
Q_ASSERT(menu);
|
||||
menu->setToolTipsVisible(true);
|
||||
}
|
||||
|
@ -95,20 +113,24 @@ QString RecentFileManager::getDisplayFileName(const RecentInfo &info) {
|
|||
}
|
||||
|
||||
QString RecentFileManager::getDisplayTooltip(const RecentInfo &info) {
|
||||
auto tt = QStringLiteral("<p>") + tr("[file]") + info.fileName +
|
||||
QString tt;
|
||||
if (_fileNameOnly) {
|
||||
tt = info.fileName;
|
||||
} else {
|
||||
tt = QStringLiteral("<p>") + tr("[file]") + info.fileName +
|
||||
QStringLiteral("</p>");
|
||||
|
||||
tt += QStringLiteral("<p>") + tr("[isWorkSpace]") +
|
||||
(info.isWorkSpace ? tr("True") : tr("False")) +
|
||||
QStringLiteral("</p>");
|
||||
|
||||
tt += QStringLiteral("<p>") + tr("[isWorkSpace]") +
|
||||
(info.isWorkSpace ? tr("True") : tr("False")) +
|
||||
QStringLiteral("</p>");
|
||||
|
||||
if (info.start >= 0 && info.stop > 0) {
|
||||
tt += QStringLiteral("<p>") + tr("[start]") +
|
||||
QString::number(info.start) + QStringLiteral("</p>");
|
||||
tt += QStringLiteral("<p>") + tr("[stop]") +
|
||||
QString::number(info.stop) + QStringLiteral("</p>");
|
||||
if (info.start >= 0 && info.stop > 0) {
|
||||
tt += QStringLiteral("<p>") + tr("[start]") +
|
||||
QString::number(info.start) + QStringLiteral("</p>");
|
||||
tt += QStringLiteral("<p>") + tr("[stop]") +
|
||||
QString::number(info.stop) + QStringLiteral("</p>");
|
||||
}
|
||||
}
|
||||
|
||||
return tt;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef RECENTFILEMANAGER_H
|
||||
#define RECENTFILEMANAGER_H
|
||||
|
||||
|
@ -55,7 +72,7 @@ public:
|
|||
};
|
||||
|
||||
public:
|
||||
explicit RecentFileManager(QMenu *menu);
|
||||
explicit RecentFileManager(QMenu *menu, bool fileNameOnly);
|
||||
~RecentFileManager();
|
||||
void addRecentFile(const RecentInfo &info);
|
||||
void clearFile();
|
||||
|
@ -64,7 +81,7 @@ public:
|
|||
const QList<RecentInfo> &saveRecent() const;
|
||||
|
||||
signals:
|
||||
void triggered(const RecentInfo &rinfo);
|
||||
void triggered(const RecentFileManager::RecentInfo &rinfo);
|
||||
|
||||
private:
|
||||
bool existsPath(const RecentInfo &info);
|
||||
|
@ -76,6 +93,8 @@ private:
|
|||
QWidget *m_parent;
|
||||
QList<RecentInfo> m_recents;
|
||||
QList<QAction *> hitems;
|
||||
|
||||
bool _fileNameOnly;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(RecentFileManager::RecentInfo)
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "scriptconsolemachine.h"
|
||||
|
||||
#include "AngelScript/sdk/add_on/scripthelper/scripthelper.h"
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef SCRIPTCONSOLEMACHINE_H
|
||||
#define SCRIPTCONSOLEMACHINE_H
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "scripteditortheme.h"
|
||||
|
||||
#include <QFile>
|
||||
|
@ -86,7 +103,7 @@ bool ScriptEditorTheme::loadTheme(const QString &filename) {
|
|||
|
||||
if (readAttr(attr, QStringLiteral("fontfamily"),
|
||||
styleAttr)) {
|
||||
if (QFontDatabase().hasFamily(styleAttr)) {
|
||||
if (QFontDatabase::hasFamily(styleAttr)) {
|
||||
scheme.fontFamily = styleAttr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef SCRIPTEDITORTHEME_H
|
||||
#define SCRIPTEDITORTHEME_H
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "scriptmachine.h"
|
||||
|
||||
#include "AngelScript/sdk/add_on/datetime/datetime.h"
|
||||
|
@ -11,6 +28,7 @@
|
|||
#include "AngelScript/sdk/add_on/scriptmath/scriptmath.h"
|
||||
#include "AngelScript/sdk/add_on/scriptmath/scriptmathcomplex.h"
|
||||
#include "AngelScript/sdk/add_on/weakref/weakref.h"
|
||||
#include "class/qasparser.h"
|
||||
#include "plugin/pluginsystem.h"
|
||||
#include "scriptaddon/scriptcolor.h"
|
||||
#include "scriptaddon/scriptqstring.h"
|
||||
|
@ -164,6 +182,9 @@ bool ScriptMachine::configureEngine(asIScriptEngine *engine) {
|
|||
PluginSystem::instance().angelApi()->installAPI(
|
||||
engine, typeInfo(RegisteredType::tString));
|
||||
|
||||
// TODO TEST
|
||||
QAsParser varname(engine);
|
||||
|
||||
_immediateContext = engine->CreateContext();
|
||||
_immediateContext->SetExceptionCallback(
|
||||
asMETHOD(ScriptMachine, exceptionCallback), this, asCALL_THISCALL);
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef SCRIPTMACHINE_H
|
||||
#define SCRIPTMACHINE_H
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "scriptmanager.h"
|
||||
|
||||
#include "dbghelper.h"
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef SCRIPTMANAGER_H
|
||||
#define SCRIPTMANAGER_H
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "settingmanager.h"
|
||||
|
||||
#include "class/logger.h"
|
||||
|
@ -7,6 +24,14 @@
|
|||
#include <QMetaEnum>
|
||||
#include <QSettings>
|
||||
|
||||
QString getRealContent(const QString &value) { return value; }
|
||||
|
||||
template <typename T>
|
||||
QString getRealContent(QGlobalStatic<T> &value) {
|
||||
static_assert(std::is_same<QString &, decltype(*value)>());
|
||||
return *value;
|
||||
}
|
||||
|
||||
#define HANDLE_CONFIG \
|
||||
QSettings set(QStringLiteral(APP_ORG), QStringLiteral(APP_NAME))
|
||||
|
||||
|
@ -14,11 +39,11 @@
|
|||
|
||||
#define WRITE_CONFIG(config, dvalue) \
|
||||
if (this->_setUnsaved.testFlag(SETTING_ITEM::config)) { \
|
||||
set.setValue(config, dvalue); \
|
||||
set.setValue(getRealContent(config), dvalue); \
|
||||
_setUnsaved.setFlag(SettingManager::SETTING_ITEM::config, false); \
|
||||
}
|
||||
|
||||
#define READ_CONFIG(config, dvalue) set.value(config, dvalue)
|
||||
#define READ_CONFIG(config, dvalue) set.value(getRealContent(config), dvalue)
|
||||
|
||||
#define READ_CONFIG_SAFE(var, config, dvalue, func) \
|
||||
{ \
|
||||
|
@ -56,38 +81,58 @@
|
|||
} \
|
||||
}
|
||||
|
||||
const auto DOCK_LAYOUT = QStringLiteral("dock.layout");
|
||||
const auto SCRIPT_DOCK_LAYOUT = QStringLiteral("script.layout");
|
||||
const auto APP_LASTUSED_PATH = QStringLiteral("app.lastusedpath");
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, DOCK_LAYOUT, QStringLiteral("dock.layout"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, SCRIPT_DOCK_LAYOUT,
|
||||
QStringLiteral("script.layout"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, APP_LASTUSED_PATH,
|
||||
QStringLiteral("app.lastusedpath"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, SKIN_THEME, QStringLiteral("skin.theme"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, APP_FONTFAMILY,
|
||||
QStringLiteral("app.fontfamily"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, APP_FONTSIZE, QStringLiteral("app.fontsize"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, APP_WINDOWSIZE,
|
||||
QStringLiteral("app.windowsize"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, APP_LANGUAGE, QStringLiteral("app.lang"))
|
||||
|
||||
const auto SKIN_THEME = QStringLiteral("skin.theme");
|
||||
const auto APP_FONTFAMILY = QStringLiteral("app.fontfamily");
|
||||
const auto APP_FONTSIZE = QStringLiteral("app.fontsize");
|
||||
const auto APP_WINDOWSIZE = QStringLiteral("app.windowsize");
|
||||
const auto APP_LANGUAGE = QStringLiteral("app.lang");
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, PLUGIN_ENABLE,
|
||||
QStringLiteral("plugin.enableplugin"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, PLUGIN_ENABLE_ROOT,
|
||||
QStringLiteral("plugin.rootenableplugin"))
|
||||
|
||||
const auto PLUGIN_ENABLE = QStringLiteral("plugin.enableplugin");
|
||||
const auto PLUGIN_ENABLE_ROOT = QStringLiteral("plugin.rootenableplugin");
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, EDITOR_FONTSIZE,
|
||||
QStringLiteral("editor.fontsize"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, EDITOR_SHOW_ADDR,
|
||||
QStringLiteral("editor.showaddr"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, EDITOR_SHOW_COL,
|
||||
QStringLiteral("editor.showcol"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, EDITOR_SHOW_TEXT,
|
||||
QStringLiteral("editor.showtext"))
|
||||
|
||||
const auto EDITOR_FONTSIZE = QStringLiteral("editor.fontsize");
|
||||
const auto EDITOR_SHOW_ADDR = QStringLiteral("editor.showaddr");
|
||||
const auto EDITOR_SHOW_COL = QStringLiteral("editor.showcol");
|
||||
const auto EDITOR_SHOW_TEXT = QStringLiteral("editor.showtext");
|
||||
const auto EDITOR_ENCODING = QStringLiteral("editor.encoding");
|
||||
const auto EDITOR_FIND_MAXCOUNT = QStringLiteral("editor.findmaxcount");
|
||||
const auto EDITOR_COPY_LIMIT = QStringLiteral("editor.copylimit");
|
||||
const auto EDITOR_DECSTRLIMIT = QStringLiteral("editor.decstrlimit");
|
||||
const auto EDITOR_RECENTFILES = QStringLiteral("editor.recentfiles");
|
||||
const auto SCRIPT_RECENTFILES = QStringLiteral("script.recentfiles");
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, EDITOR_ENCODING,
|
||||
QStringLiteral("editor.encoding"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, EDITOR_FIND_MAXCOUNT,
|
||||
QStringLiteral("editor.findmaxcount"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, EDITOR_COPY_LIMIT,
|
||||
QStringLiteral("editor.copylimit"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, EDITOR_DECSTRLIMIT,
|
||||
QStringLiteral("editor.decstrlimit"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, EDITOR_RECENTFILES,
|
||||
QStringLiteral("editor.recentfiles"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, SCRIPT_RECENTFILES,
|
||||
QStringLiteral("script.recentfiles"))
|
||||
|
||||
const auto SCRIPT_ALLOW_USRSCRIPT_INROOT =
|
||||
QStringLiteral("script.allowUsrScriptRoot");
|
||||
const auto SCRIPT_USRHIDECATS = QStringLiteral("script.usrHideCats");
|
||||
const auto SCRIPT_SYSHIDECATS = QStringLiteral("script.sysHideCats");
|
||||
|
||||
const auto OTHER_USESYS_FILEDIALOG = QStringLiteral("sys.nativeDialog");
|
||||
const auto OTHER_USE_NATIVE_TITLEBAR = QStringLiteral("sys.nativeTitleBar");
|
||||
const auto OTHER_LOG_LEVEL = QStringLiteral("sys.loglevel");
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, SCRIPT_ALLOW_USRSCRIPT_INROOT,
|
||||
QStringLiteral("script.allowUsrScriptRoot"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, SCRIPT_USRHIDECATS,
|
||||
QStringLiteral("script.usrHideCats"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, SCRIPT_SYSHIDECATS,
|
||||
QStringLiteral("script.sysHideCats"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, OTHER_USESYS_FILEDIALOG,
|
||||
QStringLiteral("sys.nativeDialog"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, OTHER_USE_NATIVE_TITLEBAR,
|
||||
QStringLiteral("sys.nativeTitleBar"))
|
||||
Q_GLOBAL_STATIC_WITH_ARGS(QString, OTHER_LOG_LEVEL,
|
||||
QStringLiteral("sys.loglevel"))
|
||||
|
||||
SettingManager::SettingManager() {
|
||||
_defaultFont = qApp->font();
|
||||
|
@ -112,6 +157,7 @@ void SettingManager::load() {
|
|||
m_themeID = qBound(0, m_themeID,
|
||||
QMetaEnum::fromType<SkinManager::Theme>().keyCount());
|
||||
m_defaultLang = READ_CONFIG(APP_LANGUAGE, QString()).toString();
|
||||
|
||||
m_dockLayout = READ_CONFIG(DOCK_LAYOUT, QByteArray()).toByteArray();
|
||||
m_scriptDockLayout =
|
||||
READ_CONFIG(SCRIPT_DOCK_LAYOUT, QByteArray()).toByteArray();
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef SETTINGMANAGER_H
|
||||
#define SETTINGMANAGER_H
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "skinmanager.h"
|
||||
|
||||
#include "dbghelper.h"
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef SKINMANAGER_H
|
||||
#define SKINMANAGER_H
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "wingangelapi.h"
|
||||
|
||||
#include "AngelScript/sdk/angelscript/include/angelscript.h"
|
||||
|
@ -28,13 +45,7 @@ WingAngelAPI::WingAngelAPI() {
|
|||
_fnbuffer.reserve(signalCount);
|
||||
}
|
||||
|
||||
WingAngelAPI::~WingAngelAPI() {
|
||||
for (auto &p : _fnbuffer) {
|
||||
auto f = reinterpret_cast<std::function<void(void *)> *>(p);
|
||||
delete f;
|
||||
}
|
||||
_fnbuffer.clear();
|
||||
}
|
||||
WingAngelAPI::~WingAngelAPI() { _fnbuffer.clear(); }
|
||||
|
||||
int WingAngelAPI::sdkVersion() const { return WingHex::SDKVERSION; }
|
||||
|
||||
|
@ -1305,30 +1316,32 @@ bool WingAngelAPI::read2Ref(qsizetype offset, void *ref, int typeId) {
|
|||
if (typeId == asTYPEID_VOID)
|
||||
return false;
|
||||
else if (typeId == asTYPEID_BOOL)
|
||||
*reinterpret_cast<bool *>(ref) = (reader.readInt8(offset) != 0);
|
||||
*reinterpret_cast<bool *>(ref) =
|
||||
(emit reader.readInt8(offset) != 0);
|
||||
else if (typeId == asTYPEID_INT8)
|
||||
*reinterpret_cast<qint8 *>(ref) = reader.readInt8(offset);
|
||||
*reinterpret_cast<qint8 *>(ref) = emit reader.readInt8(offset);
|
||||
else if (typeId == asTYPEID_INT16)
|
||||
*reinterpret_cast<qint16 *>(ref) = reader.readInt16(offset);
|
||||
*reinterpret_cast<qint16 *>(ref) = emit reader.readInt16(offset);
|
||||
else if (typeId == asTYPEID_INT32)
|
||||
*reinterpret_cast<qint32 *>(ref) = reader.readInt32(offset);
|
||||
*reinterpret_cast<qint32 *>(ref) = emit reader.readInt32(offset);
|
||||
else if (typeId == asTYPEID_INT64)
|
||||
*reinterpret_cast<qint64 *>(ref) = reader.readInt64(offset);
|
||||
*reinterpret_cast<qint64 *>(ref) = emit reader.readInt64(offset);
|
||||
else if (typeId == asTYPEID_UINT8)
|
||||
*reinterpret_cast<quint8 *>(ref) = quint8(reader.readInt8(offset));
|
||||
*reinterpret_cast<quint8 *>(ref) =
|
||||
quint8(emit reader.readInt8(offset));
|
||||
else if (typeId == asTYPEID_UINT16)
|
||||
*reinterpret_cast<quint16 *>(ref) =
|
||||
quint16(reader.readInt16(offset));
|
||||
quint16(emit reader.readInt16(offset));
|
||||
else if (typeId == asTYPEID_UINT32)
|
||||
*reinterpret_cast<quint32 *>(ref) =
|
||||
quint32(reader.readInt32(offset));
|
||||
quint32(emit reader.readInt32(offset));
|
||||
else if (typeId == asTYPEID_UINT64)
|
||||
*reinterpret_cast<quint64 *>(ref) =
|
||||
quint64(reader.readInt64(offset));
|
||||
quint64(emit reader.readInt64(offset));
|
||||
else if (typeId == asTYPEID_FLOAT)
|
||||
*reinterpret_cast<float *>(ref) = reader.readFloat(offset);
|
||||
*reinterpret_cast<float *>(ref) = emit reader.readFloat(offset);
|
||||
else if (typeId == asTYPEID_DOUBLE)
|
||||
*reinterpret_cast<double *>(ref) = reader.readDouble(offset);
|
||||
*reinterpret_cast<double *>(ref) = emit reader.readDouble(offset);
|
||||
else if ((typeId & asTYPEID_MASK_OBJECT) == 0) {
|
||||
bool ok = false;
|
||||
// Check if the value matches one of the defined enums
|
||||
|
@ -1380,7 +1393,7 @@ bool WingAngelAPI::read2Ref(qsizetype offset, void *ref, int typeId) {
|
|||
// TODO support other type, now only string
|
||||
if (type->GetTypeId() == (typeId & ~asTYPEID_OBJHANDLE)) {
|
||||
*reinterpret_cast<QString *>(value) =
|
||||
reader.readString(offset);
|
||||
emit reader.readString(offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1481,22 +1494,26 @@ bool WingAngelAPI::_HexReader_write(qsizetype offset, void *ref, int typeId) {
|
|||
if (typeId == asTYPEID_VOID)
|
||||
return false;
|
||||
else if (typeId == asTYPEID_BOOL)
|
||||
controller.writeInt8(offset,
|
||||
*reinterpret_cast<bool *>(ref) ? 1 : 0);
|
||||
emit controller.writeInt8(offset,
|
||||
*reinterpret_cast<bool *>(ref) ? 1 : 0);
|
||||
else if (typeId == asTYPEID_INT8 || typeId == asTYPEID_UINT8)
|
||||
controller.writeInt8(offset, *reinterpret_cast<qint8 *>(ref));
|
||||
emit controller.writeInt8(offset, *reinterpret_cast<qint8 *>(ref));
|
||||
else if (typeId == asTYPEID_INT16 || typeId == asTYPEID_UINT16)
|
||||
controller.writeInt16(offset, *reinterpret_cast<qint16 *>(ref));
|
||||
emit controller.writeInt16(offset,
|
||||
*reinterpret_cast<qint16 *>(ref));
|
||||
else if (typeId == asTYPEID_INT32 || typeId == asTYPEID_UINT32)
|
||||
controller.writeInt32(offset, *reinterpret_cast<qint32 *>(ref));
|
||||
emit controller.writeInt32(offset,
|
||||
*reinterpret_cast<qint32 *>(ref));
|
||||
else if (typeId == asTYPEID_INT64 || typeId == asTYPEID_UINT64)
|
||||
controller.writeInt64(offset, *reinterpret_cast<qint64 *>(ref));
|
||||
emit controller.writeInt64(offset,
|
||||
*reinterpret_cast<qint64 *>(ref));
|
||||
else if (typeId == asTYPEID_FLOAT)
|
||||
controller.writeFloat(offset, *reinterpret_cast<float *>(ref));
|
||||
emit controller.writeFloat(offset, *reinterpret_cast<float *>(ref));
|
||||
else if (typeId == asTYPEID_DOUBLE)
|
||||
controller.writeDouble(offset, *reinterpret_cast<double *>(ref));
|
||||
emit controller.writeDouble(offset,
|
||||
*reinterpret_cast<double *>(ref));
|
||||
else if ((typeId & asTYPEID_MASK_OBJECT) == 0)
|
||||
controller.writeInt32(offset, *reinterpret_cast<int *>(ref));
|
||||
emit controller.writeInt32(offset, *reinterpret_cast<int *>(ref));
|
||||
else if (typeId & asTYPEID_SCRIPTOBJECT) {
|
||||
// Dereference handles, so we can see what it points to
|
||||
void *value = ref;
|
||||
|
@ -1509,7 +1526,7 @@ bool WingAngelAPI::_HexReader_write(qsizetype offset, void *ref, int typeId) {
|
|||
int enumVal;
|
||||
t->GetEnumValueByIndex(n, &enumVal);
|
||||
if (enumVal == *(int *)value) {
|
||||
controller.writeInt32(offset, enumVal);
|
||||
emit controller.writeInt32(offset, enumVal);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1526,7 +1543,7 @@ bool WingAngelAPI::_HexReader_write(qsizetype offset, void *ref, int typeId) {
|
|||
if (value) {
|
||||
// TODO support other type, now only string
|
||||
if (type->GetTypeId() == (typeId & ~asTYPEID_OBJHANDLE)) {
|
||||
controller.writeString(
|
||||
emit controller.writeString(
|
||||
offset, *reinterpret_cast<QString *>(value));
|
||||
}
|
||||
}
|
||||
|
@ -1546,22 +1563,27 @@ bool WingAngelAPI::_HexReader_insert(qsizetype offset, void *ref, int typeId) {
|
|||
if (typeId == asTYPEID_VOID)
|
||||
return false;
|
||||
else if (typeId == asTYPEID_BOOL)
|
||||
controller.insertInt8(offset,
|
||||
*reinterpret_cast<bool *>(ref) ? 1 : 0);
|
||||
emit controller.insertInt8(offset,
|
||||
*reinterpret_cast<bool *>(ref) ? 1 : 0);
|
||||
else if (typeId == asTYPEID_INT8 || typeId == asTYPEID_UINT8)
|
||||
controller.insertInt8(offset, *reinterpret_cast<qint8 *>(ref));
|
||||
emit controller.insertInt8(offset, *reinterpret_cast<qint8 *>(ref));
|
||||
else if (typeId == asTYPEID_INT16 || typeId == asTYPEID_UINT16)
|
||||
controller.insertInt16(offset, *reinterpret_cast<qint16 *>(ref));
|
||||
emit controller.insertInt16(offset,
|
||||
*reinterpret_cast<qint16 *>(ref));
|
||||
else if (typeId == asTYPEID_INT32 || typeId == asTYPEID_UINT32)
|
||||
controller.insertInt32(offset, *reinterpret_cast<qint32 *>(ref));
|
||||
emit controller.insertInt32(offset,
|
||||
*reinterpret_cast<qint32 *>(ref));
|
||||
else if (typeId == asTYPEID_INT64 || typeId == asTYPEID_UINT64)
|
||||
controller.insertInt64(offset, *reinterpret_cast<qint64 *>(ref));
|
||||
emit controller.insertInt64(offset,
|
||||
*reinterpret_cast<qint64 *>(ref));
|
||||
else if (typeId == asTYPEID_FLOAT)
|
||||
controller.insertFloat(offset, *reinterpret_cast<float *>(ref));
|
||||
emit controller.insertFloat(offset,
|
||||
*reinterpret_cast<float *>(ref));
|
||||
else if (typeId == asTYPEID_DOUBLE)
|
||||
controller.insertDouble(offset, *reinterpret_cast<double *>(ref));
|
||||
emit controller.insertDouble(offset,
|
||||
*reinterpret_cast<double *>(ref));
|
||||
else if ((typeId & asTYPEID_MASK_OBJECT) == 0)
|
||||
controller.insertInt32(offset, *reinterpret_cast<int *>(ref));
|
||||
emit controller.insertInt32(offset, *reinterpret_cast<int *>(ref));
|
||||
else if (typeId & asTYPEID_SCRIPTOBJECT) {
|
||||
// Dereference handles, so we can see what it points to
|
||||
void *value = ref;
|
||||
|
@ -1574,7 +1596,7 @@ bool WingAngelAPI::_HexReader_insert(qsizetype offset, void *ref, int typeId) {
|
|||
int enumVal;
|
||||
t->GetEnumValueByIndex(n, &enumVal);
|
||||
if (enumVal == *(int *)value) {
|
||||
controller.insertInt32(offset, enumVal);
|
||||
emit controller.insertInt32(offset, enumVal);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1591,7 +1613,7 @@ bool WingAngelAPI::_HexReader_insert(qsizetype offset, void *ref, int typeId) {
|
|||
if (value) {
|
||||
// TODO support other type, now only string
|
||||
if (type->GetTypeId() == (typeId & ~asTYPEID_OBJHANDLE)) {
|
||||
controller.insertString(
|
||||
emit controller.insertString(
|
||||
offset, *reinterpret_cast<QString *>(value));
|
||||
}
|
||||
}
|
||||
|
@ -1611,21 +1633,21 @@ bool WingAngelAPI::_HexReader_append(qsizetype offset, void *ref, int typeId) {
|
|||
if (typeId == asTYPEID_VOID)
|
||||
return false;
|
||||
else if (typeId == asTYPEID_BOOL)
|
||||
controller.appendInt8(*reinterpret_cast<bool *>(ref) ? 1 : 0);
|
||||
emit controller.appendInt8(*reinterpret_cast<bool *>(ref) ? 1 : 0);
|
||||
else if (typeId == asTYPEID_INT8 || typeId == asTYPEID_UINT8)
|
||||
controller.appendInt8(*reinterpret_cast<qint8 *>(ref));
|
||||
emit controller.appendInt8(*reinterpret_cast<qint8 *>(ref));
|
||||
else if (typeId == asTYPEID_INT16 || typeId == asTYPEID_UINT16)
|
||||
controller.appendInt16(*reinterpret_cast<qint16 *>(ref));
|
||||
emit controller.appendInt16(*reinterpret_cast<qint16 *>(ref));
|
||||
else if (typeId == asTYPEID_INT32 || typeId == asTYPEID_UINT32)
|
||||
controller.appendInt32(*reinterpret_cast<qint32 *>(ref));
|
||||
emit controller.appendInt32(*reinterpret_cast<qint32 *>(ref));
|
||||
else if (typeId == asTYPEID_INT64 || typeId == asTYPEID_UINT64)
|
||||
controller.appendInt64(*reinterpret_cast<qint64 *>(ref));
|
||||
emit controller.appendInt64(*reinterpret_cast<qint64 *>(ref));
|
||||
else if (typeId == asTYPEID_FLOAT)
|
||||
controller.appendFloat(*reinterpret_cast<float *>(ref));
|
||||
emit controller.appendFloat(*reinterpret_cast<float *>(ref));
|
||||
else if (typeId == asTYPEID_DOUBLE)
|
||||
controller.appendDouble(*reinterpret_cast<double *>(ref));
|
||||
emit controller.appendDouble(*reinterpret_cast<double *>(ref));
|
||||
else if ((typeId & asTYPEID_MASK_OBJECT) == 0)
|
||||
controller.appendInt32(*reinterpret_cast<int *>(ref));
|
||||
emit controller.appendInt32(*reinterpret_cast<int *>(ref));
|
||||
else if (typeId & asTYPEID_SCRIPTOBJECT) {
|
||||
// Dereference handles, so we can see what it points to
|
||||
void *value = ref;
|
||||
|
@ -1638,7 +1660,7 @@ bool WingAngelAPI::_HexReader_append(qsizetype offset, void *ref, int typeId) {
|
|||
int enumVal;
|
||||
t->GetEnumValueByIndex(n, &enumVal);
|
||||
if (enumVal == *(int *)value) {
|
||||
controller.appendInt32(enumVal);
|
||||
emit controller.appendInt32(enumVal);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1655,7 +1677,7 @@ bool WingAngelAPI::_HexReader_append(qsizetype offset, void *ref, int typeId) {
|
|||
if (value) {
|
||||
// TODO support other type, now only string
|
||||
if (type->GetTypeId() == (typeId & ~asTYPEID_OBJHANDLE)) {
|
||||
controller.appendString(
|
||||
emit controller.appendString(
|
||||
*reinterpret_cast<QString *>(value));
|
||||
}
|
||||
}
|
||||
|
@ -1842,7 +1864,7 @@ bool WingAngelAPI::_DataVisual_updateTextList(int stringID,
|
|||
bool o = false;
|
||||
auto ret = cArray2QStringList(data, stringID, &o);
|
||||
if (o) {
|
||||
return visual.updateTextList(ret);
|
||||
return emit visual.updateTextList(ret);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -1856,7 +1878,7 @@ bool WingAngelAPI::_DataVisual_updateTextTable(
|
|||
if (o) {
|
||||
auto hn = cArray2QStringList(headerNames, stringID, &o);
|
||||
if (o) {
|
||||
return visual.updateTextTable(json, h, hn);
|
||||
return emit visual.updateTextTable(json, h, hn);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,29 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef WINGANGELAPI_H
|
||||
#define WINGANGELAPI_H
|
||||
|
||||
#include "AngelScript/sdk/add_on/scriptarray/scriptarray.h"
|
||||
#include "plugin/iwingplugin.h"
|
||||
|
||||
#include <any>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
class asIScriptEngine;
|
||||
|
||||
|
@ -45,11 +64,11 @@ private:
|
|||
template <class T>
|
||||
void registerAPI(asIScriptEngine *engine, const std::function<T> &fn,
|
||||
const char *sig) {
|
||||
auto *f = new std::function<T>(fn);
|
||||
_fnbuffer.push_back(fn);
|
||||
auto r = engine->RegisterGlobalFunction(
|
||||
sig, asMETHOD(std::function<T>, operator()),
|
||||
asCALL_THISCALL_ASGLOBAL, f);
|
||||
_fnbuffer << f;
|
||||
asCALL_THISCALL_ASGLOBAL,
|
||||
std::any_cast<std::function<T>>(&_fnbuffer.back()));
|
||||
Q_ASSERT(r >= 0);
|
||||
}
|
||||
|
||||
|
@ -118,7 +137,7 @@ private:
|
|||
const CScriptArray &headerNames);
|
||||
|
||||
private:
|
||||
QVector<void *> _fnbuffer;
|
||||
std::vector<std::any> _fnbuffer;
|
||||
};
|
||||
|
||||
#endif // WINGANGELAPI_H
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "wingfiledialog.h"
|
||||
#include "../dialog/framelessdialogbase.h"
|
||||
#include "settingmanager.h"
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef WINGFILEDIALOG_H
|
||||
#define WINGFILEDIALOG_H
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "winginputdialog.h"
|
||||
#include "../dialog/framelessdialogbase.h"
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef WINGINPUTDIALOG_H
|
||||
#define WINGINPUTDIALOG_H
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "wingmessagebox.h"
|
||||
#include "class/eventfilter.h"
|
||||
#include "dialog/framelessdialogbase.h"
|
||||
|
@ -42,7 +59,9 @@ void WingMessageBox::aboutQt(QWidget *parent, const QString &title) {
|
|||
"information.</p>")
|
||||
.arg(QStringLiteral("qt.io/licensing"), QStringLiteral("qt.io"));
|
||||
|
||||
auto msgbox = new QMessageBox(parent);
|
||||
auto d = new FramelessDialogBase(parent);
|
||||
|
||||
auto msgbox = new QMessageBox;
|
||||
msgbox->setText(translatedTextAboutQtCaption);
|
||||
msgbox->setInformativeText(translatedTextAboutQtText);
|
||||
|
||||
|
@ -52,20 +71,19 @@ void WingMessageBox::aboutQt(QWidget *parent, const QString &title) {
|
|||
|
||||
msgbox->setWindowFlag(Qt::Widget);
|
||||
|
||||
FramelessDialogBase d(parent);
|
||||
d.buildUpContent(msgbox);
|
||||
d.setMaximumSize(0, 0);
|
||||
d.setWindowTitle(title.isEmpty() ? QMessageBox::tr("About Qt") : title);
|
||||
d->buildUpContent(msgbox);
|
||||
d->setMaximumSize(0, 0);
|
||||
d->setWindowTitle(title.isEmpty() ? QMessageBox::tr("About Qt") : title);
|
||||
|
||||
auto e = new EventFilter(QEvent::Resize, &d);
|
||||
QObject::connect(e, &EventFilter::eventTriggered, &d,
|
||||
[&d] { Utilities::moveToCenter(&d); });
|
||||
d.installEventFilter(e);
|
||||
auto e = new EventFilter(QEvent::Resize, d);
|
||||
QObject::connect(e, &EventFilter::eventTriggered, d,
|
||||
[d] { Utilities::moveToCenter(d); });
|
||||
d->installEventFilter(e);
|
||||
|
||||
QObject::connect(msgbox, &QMessageBox::finished, &d,
|
||||
QObject::connect(msgbox, &QMessageBox::finished, d,
|
||||
&FramelessDialogBase::done);
|
||||
|
||||
d.exec();
|
||||
d->exec();
|
||||
}
|
||||
|
||||
QMessageBox::StandardButton
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef WINGMESSAGEBOX_H
|
||||
#define WINGMESSAGEBOX_H
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "wingprogressdialog.h"
|
||||
|
||||
WingProgressDialog::WingProgressDialog(const QString &labelText,
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef WINGPROGRESSDIALOG_H
|
||||
#define WINGPROGRESSDIALOG_H
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "workspacemanager.h"
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef WORKSPACEMANAGER_H
|
||||
#define WORKSPACEMANAGER_H
|
||||
|
||||
|
|
|
@ -1,33 +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 _QCM_CONFIG_H_
|
||||
#define _QCM_CONFIG_H_
|
||||
|
||||
#include <qglobal.h>
|
||||
|
||||
#ifndef QCM_EXPORT
|
||||
#define QCM_EXPORT
|
||||
#endif
|
||||
|
||||
class QByteArray;
|
||||
|
||||
template <typename T>
|
||||
class QList;
|
||||
|
||||
typedef QByteArray QToken;
|
||||
typedef QList<QToken> QTokenList;
|
||||
|
||||
#endif // _QCM_CONFIG_H_
|
|
@ -1,437 +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 "qcodemodel.h"
|
||||
|
||||
/*!
|
||||
\file qcodemodel.cpp
|
||||
\brief Implementation of the QCodeModel class.
|
||||
*/
|
||||
|
||||
#include "qcodenode.h"
|
||||
|
||||
#define Q_EXTRACT_INDEX(i, d) \
|
||||
QCodeNode *d = static_cast<QCodeNode *>(i.internalPointer());
|
||||
|
||||
#include <QStack>
|
||||
|
||||
void QCodeModel::q_cache(QCodeNode *n, QByteArray cxt = QByteArray()) {
|
||||
if (isCachable(n, cxt)) {
|
||||
m_cache.insert(cxt, n);
|
||||
|
||||
// qDebug("Caching %s [0x%x] in 0x%x", cxt.constData(), n, this);
|
||||
}
|
||||
|
||||
foreach (QCodeNode *child, n->children)
|
||||
q_cache(child, cxt);
|
||||
}
|
||||
|
||||
void QCodeModel::q_uncache(QCodeNode *n, QByteArray cxt = QByteArray()) {
|
||||
if (isCachable(n, cxt)) {
|
||||
m_cache.remove(cxt);
|
||||
|
||||
// qDebug("De-Caching %s", cxt.constData());
|
||||
}
|
||||
|
||||
foreach (QCodeNode *child, n->children)
|
||||
q_uncache(child, cxt);
|
||||
}
|
||||
|
||||
/*!
|
||||
\class QCodeModel
|
||||
\brief Class used to store code hierarchies and display them through
|
||||
model/view
|
||||
*/
|
||||
|
||||
/*!
|
||||
\brief ctor
|
||||
*/
|
||||
QCodeModel::QCodeModel(QObject *p) : QAbstractItemModel(p) {}
|
||||
|
||||
/*!
|
||||
\brief dtor
|
||||
*/
|
||||
QCodeModel::~QCodeModel() { clearTopLevelNodes(); }
|
||||
|
||||
/*!
|
||||
\return A list of code nodes occupying the top level of the model
|
||||
(unparented ones)
|
||||
*/
|
||||
QList<QCodeNode *> QCodeModel::topLevelNodes() const { return m_topLevel; }
|
||||
|
||||
/*!
|
||||
\brief Please read Qt docs on Model/View framework for more informations
|
||||
*/
|
||||
void QCodeModel::beginInsertRows(const QModelIndex idx, int beg, int end) {
|
||||
QAbstractItemModel::beginInsertRows(idx, beg, end);
|
||||
|
||||
Q_EXTRACT_INDEX(idx, parent)
|
||||
|
||||
m_cache_ops.push(CacheOp(parent, beg, end));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Please read Qt docs on Model/View framework for more informations
|
||||
*/
|
||||
void QCodeModel::beginRemoveRows(const QModelIndex idx, int beg, int end) {
|
||||
QAbstractItemModel::beginRemoveRows(idx, beg, end);
|
||||
|
||||
Q_EXTRACT_INDEX(idx, parent)
|
||||
|
||||
const QList<QCodeNode *> &l = parent ? parent->children : m_topLevel;
|
||||
|
||||
QByteArray cxt;
|
||||
|
||||
if (parent)
|
||||
cxt = parent->qualifiedName();
|
||||
|
||||
// qDebug("uncaching %i out of %i", l.count(), end - beg + 1);
|
||||
|
||||
for (int i = beg; (i <= end) && (i < l.count()); ++i)
|
||||
q_uncache(l.at(i), cxt);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Please read Qt docs on Model/View framework for more informations
|
||||
*/
|
||||
void QCodeModel::endInsertRows() {
|
||||
if (m_cache_ops.count()) {
|
||||
CacheOp op = m_cache_ops.pop();
|
||||
|
||||
const QList<QCodeNode *> &l =
|
||||
op.parent ? op.parent->children : m_topLevel;
|
||||
|
||||
QByteArray cxt;
|
||||
|
||||
if (op.parent)
|
||||
cxt = op.parent->qualifiedName();
|
||||
|
||||
for (int i = op.begin; i <= op.end; ++i)
|
||||
q_cache(l.at(i), cxt);
|
||||
} else {
|
||||
// qDebug("Odd things happenning over there...");
|
||||
}
|
||||
|
||||
QAbstractItemModel::endInsertRows();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Please read Qt docs on Model/View framework for more informations
|
||||
*/
|
||||
void QCodeModel::endRemoveRows() { QAbstractItemModel::endRemoveRows(); }
|
||||
|
||||
/*!
|
||||
\brief Append a top level code node to the model
|
||||
*/
|
||||
void QCodeModel::appendTopLevelNode(QCodeNode *n) {
|
||||
if (!n)
|
||||
return;
|
||||
|
||||
int row = m_topLevel.count();
|
||||
|
||||
beginInsertRows(QModelIndex(), row, row);
|
||||
|
||||
m_topLevel.insert(row, n);
|
||||
|
||||
QStack<QCodeNode *> nodes;
|
||||
nodes.push(n);
|
||||
|
||||
while (nodes.count()) {
|
||||
n = nodes.pop();
|
||||
n->model = this;
|
||||
|
||||
foreach (QCodeNode *c, n->children)
|
||||
nodes.push(c);
|
||||
}
|
||||
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief remove a top level code node from the model
|
||||
*/
|
||||
void QCodeModel::removeTopLevelNode(QCodeNode *n) {
|
||||
int row = n ? m_topLevel.indexOf(n) : -1;
|
||||
|
||||
if (row == -1)
|
||||
return;
|
||||
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
|
||||
m_topLevel.removeAt(row);
|
||||
|
||||
QStack<QCodeNode *> nodes;
|
||||
nodes.push(n);
|
||||
|
||||
while (nodes.count()) {
|
||||
n = nodes.pop();
|
||||
n->model = 0;
|
||||
|
||||
foreach (QCodeNode *c, n->children)
|
||||
nodes.push(c);
|
||||
}
|
||||
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief remove all top level nodes from the model
|
||||
\warning All the nodes get DELETED.
|
||||
*/
|
||||
void QCodeModel::clearTopLevelNodes() {
|
||||
int row = m_topLevel.count() - 1;
|
||||
|
||||
if (row == -1)
|
||||
return;
|
||||
|
||||
beginRemoveRows(QModelIndex(), 0, row);
|
||||
|
||||
qDeleteAll(m_topLevel);
|
||||
m_topLevel.clear();
|
||||
|
||||
/*
|
||||
QCodeNode *n;
|
||||
QStack<QCodeNode*> nodes;
|
||||
|
||||
foreach ( n, m_topLevel )
|
||||
nodes.push(n);
|
||||
|
||||
while ( nodes.count() )
|
||||
{
|
||||
n = nodes.pop();
|
||||
n->model = 0;
|
||||
|
||||
foreach ( QCodeNode *c, n->children )
|
||||
nodes.push(c);
|
||||
}
|
||||
*/
|
||||
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Find a node in the internal cache
|
||||
\param language concerned programming language
|
||||
\param name bare name of the node (e.g class name, typedef, function
|
||||
name, variable name, ...) \return the first node found or 0 if none matching
|
||||
*/
|
||||
QCodeNode *QCodeModel::findNode(const QByteArray &language,
|
||||
const QByteArray &name) {
|
||||
QByteArray id = name;
|
||||
|
||||
if (language.length())
|
||||
id.prepend("::").prepend(language);
|
||||
|
||||
QHash<QByteArray, QCodeNode *>::const_iterator i = m_cache.constFind(id);
|
||||
|
||||
if (i != m_cache.constEnd()) {
|
||||
// qDebug("%s found... [%s] : 0x%x", name.constData(), id.constData(),
|
||||
// *i);
|
||||
return *i;
|
||||
}
|
||||
|
||||
// qDebug("%s not found... [%s]", name.constData(), id.constData());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Find nodes in the internal cache
|
||||
\param name prefix to match against the bare name of the nodes (e.g
|
||||
class name, typedef, function name, variable name, ...) \return the first
|
||||
node found or 0 if none matching
|
||||
*/
|
||||
QList<QCodeNode *> QCodeModel::findRootNodes(const QByteArray &name) {
|
||||
QList<QCodeNode *> l;
|
||||
|
||||
foreach (QCodeNode *g, m_topLevel)
|
||||
foreach (QCodeNode *r, g->children)
|
||||
if (r->role(QCodeNode::Name) == name)
|
||||
l << r;
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return whether the given node is worth caching
|
||||
\param n node to test
|
||||
\param cxt cache context
|
||||
*/
|
||||
bool QCodeModel::isCachable(QCodeNode *n, QByteArray &cxt) const {
|
||||
int t = n->type();
|
||||
QByteArray qn = n->role(QCodeNode::Name);
|
||||
|
||||
if (cxt.length())
|
||||
qn.prepend("::");
|
||||
|
||||
if (cxt.isEmpty() && (t != QCodeNode::Group)) {
|
||||
cxt += qn;
|
||||
|
||||
return true;
|
||||
} else if ((t == QCodeNode::Enum) || (t == QCodeNode::Union) ||
|
||||
(t == QCodeNode::Class) || (t == QCodeNode::Struct) ||
|
||||
(t == QCodeNode::Typedef)) {
|
||||
cxt += qn;
|
||||
|
||||
return true;
|
||||
} else if (t == QCodeNode::Namespace) {
|
||||
|
||||
cxt += qn;
|
||||
|
||||
return true;
|
||||
|
||||
} else if (t == QCodeNode::Language) {
|
||||
|
||||
cxt += n->role(QCodeNode::Name); // + "/";
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Please read Qt docs on Model/View framework for more informations
|
||||
*/
|
||||
bool QCodeModel::hasChildren(const QModelIndex &parent) const {
|
||||
return rowCount(parent);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Please read Qt docs on Model/View framework for more informations
|
||||
*/
|
||||
int QCodeModel::rowCount(const QModelIndex &parent) const {
|
||||
if (!parent.isValid())
|
||||
return m_topLevel.count();
|
||||
|
||||
Q_EXTRACT_INDEX(parent, item)
|
||||
|
||||
return item ? item->children.count() : 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Please read Qt docs on Model/View framework for more informations
|
||||
*/
|
||||
int QCodeModel::columnCount(const QModelIndex &) const { return 1; }
|
||||
|
||||
/*!
|
||||
\brief Please read Qt docs on Model/View framework for more informations
|
||||
*/
|
||||
QVariant QCodeModel::data(const QModelIndex &index, int role) const {
|
||||
if (!index.isValid() || index.column())
|
||||
return QVariant();
|
||||
|
||||
Q_EXTRACT_INDEX(index, item)
|
||||
|
||||
return item ? item->data(role) : QVariant();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Please read Qt docs on Model/View framework for more informations
|
||||
*/
|
||||
Qt::ItemFlags QCodeModel::flags(const QModelIndex &index) const {
|
||||
if (!index.isValid())
|
||||
return Qt::ItemIsEnabled;
|
||||
|
||||
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Please read Qt docs on Model/View framework for more informations
|
||||
*/
|
||||
QVariant QCodeModel::headerData(int, Qt::Orientation, int) const {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Please read Qt docs on Model/View framework for more informations
|
||||
*/
|
||||
QCodeNode *QCodeModel::node(const QModelIndex &idx) const {
|
||||
Q_EXTRACT_INDEX(idx, n)
|
||||
|
||||
return idx.isValid() ? n : 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Please read Qt docs on Model/View framework for more informations
|
||||
*/
|
||||
QModelIndex QCodeModel::index(QCodeNode *n) const {
|
||||
return n ? createIndex(n->parent ? n->parent->children.indexOf(n)
|
||||
: m_topLevel.indexOf(n),
|
||||
0, n)
|
||||
: QModelIndex();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Please read Qt docs on Model/View framework for more informations
|
||||
*/
|
||||
QModelIndex QCodeModel::index(int row, int column,
|
||||
const QModelIndex &parent) const {
|
||||
if ((row < 0) || column)
|
||||
return QModelIndex();
|
||||
|
||||
Q_EXTRACT_INDEX(parent, item)
|
||||
QCodeNode *abs = 0;
|
||||
|
||||
// qDebug("asking index...");
|
||||
|
||||
if (!parent.isValid() && (row < m_topLevel.count())) {
|
||||
abs = m_topLevel.at(row);
|
||||
} else if (item && (row < item->children.count())) {
|
||||
abs = item->children.at(row);
|
||||
}
|
||||
|
||||
#ifdef _TRACE_MODEL_
|
||||
|
||||
qDebug("%s(%i, %i) : %s",
|
||||
item ? qPrintable(item->data(Qt::DisplayRole).toString()) : "root",
|
||||
row, column,
|
||||
abs ? qPrintable(abs->data(Qt::DisplayRole).toString()) : "!none!");
|
||||
|
||||
#endif
|
||||
|
||||
return abs ? createIndex(row, column, abs) : QModelIndex();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Please read Qt docs on Model/View framework for more informations
|
||||
*/
|
||||
QModelIndex QCodeModel::parent(const QModelIndex &index) const {
|
||||
if (!index.isValid()) {
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QCodeNode *parent = 0;
|
||||
Q_EXTRACT_INDEX(index, child)
|
||||
|
||||
if (child)
|
||||
parent = child->parent;
|
||||
|
||||
#ifdef _TRACE_MODEL_
|
||||
|
||||
qDebug("%s->parent() = %s",
|
||||
child ? qPrintable(child->data(Qt::DisplayRole).toString())
|
||||
: "@invalid@",
|
||||
parent ? qPrintable(parent->data(Qt::DisplayRole).toString())
|
||||
: "!none!");
|
||||
|
||||
#endif
|
||||
|
||||
if (!parent)
|
||||
return QModelIndex();
|
||||
|
||||
const int row = parent->parent ? parent->parent->children.indexOf(parent)
|
||||
: m_topLevel.indexOf(parent);
|
||||
|
||||
return createIndex(row, 0, parent);
|
||||
}
|
|
@ -1,91 +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_MODEL_H_
|
||||
#define _QCODE_MODEL_H_
|
||||
|
||||
#include "qcm-config.h"
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QHash>
|
||||
#include <QStack>
|
||||
|
||||
struct QCodeNode;
|
||||
|
||||
class QCM_EXPORT QCodeModel : public QAbstractItemModel {
|
||||
Q_OBJECT
|
||||
|
||||
friend struct QCodeNode;
|
||||
|
||||
public:
|
||||
enum ExtraRoles { TypeRole = Qt::UserRole, VisibilityRole };
|
||||
|
||||
QCodeModel(QObject *p = nullptr);
|
||||
virtual ~QCodeModel();
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const;
|
||||
|
||||
QModelIndex index(QCodeNode *n) const;
|
||||
QCodeNode *node(const QModelIndex &idx) const;
|
||||
|
||||
QModelIndex index(int row, int column,
|
||||
const QModelIndex &parent = QModelIndex()) const;
|
||||
QModelIndex parent(const QModelIndex &index) const;
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
bool hasChildren(const QModelIndex &parent = QModelIndex()) const;
|
||||
|
||||
QList<QCodeNode *> topLevelNodes() const;
|
||||
|
||||
void appendTopLevelNode(QCodeNode *n);
|
||||
void removeTopLevelNode(QCodeNode *n);
|
||||
void clearTopLevelNodes();
|
||||
|
||||
QList<QCodeNode *> findRootNodes(const QByteArray &name);
|
||||
QCodeNode *findNode(const QByteArray &language, const QByteArray &name);
|
||||
|
||||
virtual bool isCachable(QCodeNode *n, QByteArray &cxt) const;
|
||||
|
||||
protected:
|
||||
void beginInsertRows(const QModelIndex idx, int beg, int end);
|
||||
void beginRemoveRows(const QModelIndex idx, int beg, int end);
|
||||
void endInsertRows();
|
||||
void endRemoveRows();
|
||||
|
||||
private:
|
||||
struct CacheOp {
|
||||
inline CacheOp() : parent(0), begin(-1), end(-1) {}
|
||||
inline CacheOp(QCodeNode *n, int b, int e)
|
||||
: parent(n), begin(b), end(e) {}
|
||||
|
||||
QCodeNode *parent;
|
||||
int begin;
|
||||
int end;
|
||||
};
|
||||
|
||||
void q_cache(QCodeNode *n, QByteArray cxt);
|
||||
void q_uncache(QCodeNode *n, QByteArray cxt);
|
||||
|
||||
QList<QCodeNode *> m_topLevel;
|
||||
|
||||
QStack<CacheOp> m_cache_ops;
|
||||
QHash<QByteArray, QCodeNode *> m_cache;
|
||||
};
|
||||
|
||||
#endif // !_QCODE_MODEL_H_
|
|
@ -1,558 +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 "qcodenode.h"
|
||||
|
||||
#include <QIcon>
|
||||
#include <QVariant>
|
||||
|
||||
#include "qcodemodel.h"
|
||||
#include "qcodenodepool.h"
|
||||
|
||||
#include "qsourcecodewatcher.h"
|
||||
|
||||
/*
|
||||
|
||||
|
||||
|
||||
*/
|
||||
enum CacheIndex {
|
||||
ICON_ENUM,
|
||||
ICON_ENUMERATOR,
|
||||
ICON_UNION,
|
||||
ICON_CLASS,
|
||||
ICON_STRUCT,
|
||||
ICON_TYPEDEF,
|
||||
ICON_NAMESPACE,
|
||||
ICON_FUNCTION = ICON_NAMESPACE + 2,
|
||||
ICON_VARIABLE = ICON_FUNCTION + 5
|
||||
};
|
||||
|
||||
static QHash<int, QIcon> q_icon_cache;
|
||||
|
||||
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");
|
||||
|
||||
q_icon_cache[ICON_FUNCTION + QCodeNode::VISIBILITY_DEFAULT] =
|
||||
QIcon(":/completion/CVglobal_meth.png");
|
||||
|
||||
q_icon_cache[ICON_FUNCTION + QCodeNode::VISIBILITY_PUBLIC] =
|
||||
QIcon(":/completion/CVpublic_meth.png");
|
||||
|
||||
q_icon_cache[ICON_FUNCTION + QCodeNode::VISIBILITY_PROTECTED] =
|
||||
QIcon(":/completion/CVprotected_meth.png");
|
||||
|
||||
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");
|
||||
|
||||
q_icon_cache[ICON_VARIABLE + QCodeNode::VISIBILITY_PUBLIC] =
|
||||
QIcon(":/completion/CVpublic_var.png");
|
||||
|
||||
q_icon_cache[ICON_VARIABLE + QCodeNode::VISIBILITY_PROTECTED] =
|
||||
QIcon(":/completion/CVprotected_var.png");
|
||||
|
||||
q_icon_cache[ICON_VARIABLE + QCodeNode::VISIBILITY_PRIVATE] =
|
||||
QIcon(":/completion/CVprivate_var.png");
|
||||
|
||||
setup = true;
|
||||
}
|
||||
|
||||
return q_icon_cache.value(cacheIndex);
|
||||
}
|
||||
|
||||
QByteArray section(const QByteArray &b, char c, int beg, int end = -1) {
|
||||
QList<QByteArray> l = b.split(c);
|
||||
|
||||
// qDebug("split %s into %i parts...", b.constData(), l.length());
|
||||
// qDebug("parts %i to %i", beg, end);
|
||||
|
||||
if (beg < 0)
|
||||
beg = l.length() + beg;
|
||||
|
||||
if (end < 0)
|
||||
end = l.length() + end;
|
||||
|
||||
int start = qMin(beg, end), stop = qMax(beg, end);
|
||||
|
||||
// qDebug("parts %i to %i", start, stop);
|
||||
|
||||
if ((start >= l.length()) || (stop < 0))
|
||||
return QByteArray();
|
||||
|
||||
QByteArray sec = l.at(start);
|
||||
|
||||
while (++start <= stop)
|
||||
sec.prepend(c).prepend(l.at(start));
|
||||
|
||||
return sec;
|
||||
}
|
||||
|
||||
void setSection(QByteArray &b, char c, int beg, int end = -1,
|
||||
const QByteArray &r = QByteArray()) {
|
||||
QList<QByteArray> l = b.split(c);
|
||||
|
||||
if (beg < 0)
|
||||
beg = l.length() + beg;
|
||||
|
||||
if (end < 0)
|
||||
end = l.length() + end;
|
||||
|
||||
int offset = 0, length = 0;
|
||||
int start = qMin(beg, end), stop = qMax(beg, end);
|
||||
|
||||
if ((start >= l.length()) || (stop < 0))
|
||||
return;
|
||||
|
||||
for (int i = 0; i < start; ++i)
|
||||
offset += l.at(i).length() + 1;
|
||||
|
||||
for (int i = start; i <= stop; ++i)
|
||||
length += l.at(i).length() + 1;
|
||||
|
||||
--length;
|
||||
|
||||
/*
|
||||
qDebug("set section [%i, %i]=>[%i, %i] of \"%s\" to \"%s\"",
|
||||
beg, end,
|
||||
offset, offset + length,
|
||||
b.constData(),
|
||||
r.constData());
|
||||
*/
|
||||
|
||||
b.replace(offset, length, r);
|
||||
}
|
||||
|
||||
void QCodeNode::operator delete(void *p) {
|
||||
QCodeNode *n = static_cast<QCodeNode *>(p);
|
||||
|
||||
if (!n)
|
||||
return;
|
||||
else if (n->m_pool)
|
||||
n->m_pool->free(n);
|
||||
else
|
||||
::operator delete(p);
|
||||
}
|
||||
|
||||
QCodeNode::QCodeNode() : line(-1), parent(0), model(0), m_pool(0) {}
|
||||
|
||||
QCodeNode::QCodeNode(QCodeNodePool *p)
|
||||
: line(-1), parent(0), model(0), m_pool(p) {}
|
||||
|
||||
QCodeNode::~QCodeNode() {
|
||||
detach();
|
||||
|
||||
model = 0;
|
||||
parent = 0;
|
||||
m_pool = 0;
|
||||
|
||||
clear();
|
||||
|
||||
QSourceCodeWatcher *w = QSourceCodeWatcher::watcher(this, 0);
|
||||
|
||||
if (w)
|
||||
delete w;
|
||||
}
|
||||
|
||||
void QCodeNode::attach(QCodeNode *p) {
|
||||
detach();
|
||||
|
||||
if (!p || p->children.contains(this))
|
||||
return;
|
||||
|
||||
bool modelChange = model != p->model;
|
||||
|
||||
if (modelChange) {
|
||||
QStack<QCodeNode *> tree;
|
||||
|
||||
tree.push(this);
|
||||
|
||||
while (tree.length()) {
|
||||
QCodeNode *n = tree.pop();
|
||||
|
||||
n->model = p->model;
|
||||
|
||||
foreach (QCodeNode *c, n->children)
|
||||
tree.push(c);
|
||||
}
|
||||
}
|
||||
|
||||
int row = p->children.length();
|
||||
|
||||
if (model)
|
||||
model->beginInsertRows(model->index(p), row, row);
|
||||
|
||||
parent = p;
|
||||
p->children.insert(row, this);
|
||||
|
||||
if (model)
|
||||
model->endInsertRows();
|
||||
}
|
||||
|
||||
void QCodeNode::detach() {
|
||||
if (!parent)
|
||||
return;
|
||||
|
||||
int row = parent->children.indexOf(this);
|
||||
|
||||
if (row < 0)
|
||||
return;
|
||||
|
||||
if (model)
|
||||
model->beginRemoveRows(model->index(parent), row, row);
|
||||
|
||||
parent->children.removeAt(row);
|
||||
parent = 0;
|
||||
|
||||
if (model)
|
||||
model->endRemoveRows();
|
||||
|
||||
if (model) {
|
||||
QStack<QCodeNode *> tree;
|
||||
|
||||
tree.push(this);
|
||||
|
||||
while (tree.length()) {
|
||||
QCodeNode *n = tree.pop();
|
||||
|
||||
n->model = 0;
|
||||
|
||||
foreach (QCodeNode *c, n->children)
|
||||
tree.push(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QCodeNode::clear() {
|
||||
QList<QCodeNode *> c = children;
|
||||
|
||||
removeAll();
|
||||
|
||||
qDeleteAll(c);
|
||||
}
|
||||
|
||||
void QCodeNode::removeAll() {
|
||||
if (children.isEmpty())
|
||||
return;
|
||||
|
||||
if (model)
|
||||
model->beginRemoveRows(model->index(this), 0, children.length() - 1);
|
||||
|
||||
foreach (QCodeNode *n, children) {
|
||||
n->model = 0;
|
||||
n->parent = 0;
|
||||
}
|
||||
|
||||
children.clear();
|
||||
|
||||
if (model)
|
||||
model->endRemoveRows();
|
||||
}
|
||||
|
||||
int QCodeNode::type() const {
|
||||
return roles.length() ? role(NodeType).at(0) : 0;
|
||||
}
|
||||
|
||||
QByteArray QCodeNode::context() const {
|
||||
int t = type();
|
||||
|
||||
if ((t == Group) || (t == Language) || (t == Namespace))
|
||||
return QByteArray();
|
||||
|
||||
const QCodeNode *p = this;
|
||||
|
||||
while (p->parent) {
|
||||
int t = p->parent->type();
|
||||
|
||||
if ((t == Group) || (t == Language) || (t == Namespace))
|
||||
break;
|
||||
|
||||
p = p->parent;
|
||||
}
|
||||
|
||||
return p ? p->role(Context) : role(Context);
|
||||
}
|
||||
|
||||
QByteArray QCodeNode::qualifiedName(bool language) const {
|
||||
int t = type();
|
||||
|
||||
if (t == Group)
|
||||
return QByteArray();
|
||||
else if (t == Language)
|
||||
return language ? role(Name) : QByteArray();
|
||||
|
||||
QByteArray cxt = parent ? parent->qualifiedName(language) : QByteArray();
|
||||
|
||||
if (cxt.length()) {
|
||||
// if ( parent->type() == Language )
|
||||
// cxt += "/";
|
||||
// else
|
||||
cxt += "::";
|
||||
}
|
||||
|
||||
// cxt += role(Name);
|
||||
|
||||
cxt += role(Name);
|
||||
|
||||
if (t == Function) {
|
||||
cxt += "(";
|
||||
cxt += role(Arguments);
|
||||
cxt += ")";
|
||||
}
|
||||
|
||||
return cxt;
|
||||
}
|
||||
|
||||
QVariant QCodeNode::data(int r) const {
|
||||
const int t = type();
|
||||
|
||||
switch (r) {
|
||||
case Qt::DisplayRole: {
|
||||
if (t == Function)
|
||||
return role(Name) + "(" + role(Arguments) + ")";
|
||||
|
||||
// if ( t == Enumerator )
|
||||
// ;
|
||||
|
||||
return role(Name);
|
||||
}
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
case Qt::StatusTipRole: {
|
||||
switch (t) {
|
||||
case Class: {
|
||||
QByteArray d("class ");
|
||||
d += role(Name);
|
||||
|
||||
QByteArray a = role(Ancestors);
|
||||
|
||||
if (a.length())
|
||||
d += " : " + a;
|
||||
|
||||
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);
|
||||
|
||||
case Typedef:
|
||||
return QByteArray("typedef ") + role(Alias) + " " + role(Name);
|
||||
|
||||
case Variable: {
|
||||
QByteArray signature, specifier;
|
||||
|
||||
signature += role(Type);
|
||||
signature += " ";
|
||||
signature += role(Name);
|
||||
|
||||
int m_visibility = role(Visibility).toInt();
|
||||
int m_specifiers = role(Specifiers).toInt();
|
||||
|
||||
// visibility (for class members)
|
||||
if (m_visibility == QCodeNode::VISIBILITY_PUBLIC)
|
||||
specifier = " public ";
|
||||
else if (m_visibility == QCodeNode::VISIBILITY_PROTECTED)
|
||||
specifier = " protected ";
|
||||
else
|
||||
specifier = " private ";
|
||||
|
||||
// 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() + "]";
|
||||
|
||||
return signature;
|
||||
// return role(Type) + " " + role(Name);
|
||||
}
|
||||
|
||||
case Function: {
|
||||
QByteArray signature, qualifier, ret = role(Return);
|
||||
|
||||
if (ret.length())
|
||||
signature += ret + " ";
|
||||
|
||||
signature += role(Name);
|
||||
|
||||
signature += "(";
|
||||
signature += role(Arguments);
|
||||
signature += ")";
|
||||
|
||||
int m_qualifiers = role(Qualifiers).toInt();
|
||||
|
||||
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();
|
||||
|
||||
if (m_visibility == QCodeNode::VISIBILITY_PUBLIC)
|
||||
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
|
||||
qualifier.prepend(" global ");
|
||||
|
||||
if (ret.isEmpty()) {
|
||||
if (role(Name).startsWith("~"))
|
||||
qualifier += " destructor ";
|
||||
else
|
||||
qualifier += " constructor ";
|
||||
}
|
||||
|
||||
if (qualifier.length())
|
||||
signature += " [" + qualifier.simplified() + "]";
|
||||
|
||||
// return role(Name) + " " + role(Name);
|
||||
return signature;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case Qt::DecorationRole: {
|
||||
switch (t) {
|
||||
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);
|
||||
|
||||
case Typedef:
|
||||
return icon(ICON_TYPEDEF);
|
||||
|
||||
case Variable:
|
||||
return icon(ICON_VARIABLE + role(Visibility).toInt());
|
||||
|
||||
case Function:
|
||||
return icon(ICON_FUNCTION + role(Visibility).toInt());
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
case QCodeModel::TypeRole:
|
||||
return type();
|
||||
|
||||
case QCodeModel::VisibilityRole:
|
||||
return role(Visibility).toInt();
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void QCodeNode::setData(int role, const QVariant &v) {
|
||||
Q_UNUSED(v)
|
||||
Q_UNUSED(role)
|
||||
}
|
||||
|
||||
QByteArray QCodeNode::role(RoleIndex r) const {
|
||||
return section(roles, '@', (int)r, (int)r);
|
||||
}
|
||||
|
||||
void QCodeNode::setRole(RoleIndex r, const QByteArray &b) {
|
||||
setSection(roles, '@', (int)r, (int)r, b);
|
||||
}
|
|
@ -1,93 +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 "qcodenodepool.h"
|
||||
|
||||
/*!
|
||||
\file qcodenodepool.cpp
|
||||
\brief Implementation of the QCodeNodePool class.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "qcodenode.h"
|
||||
|
||||
/*!
|
||||
\class QCodeNodePool
|
||||
\brief Custom allocator for QCodeNode objects
|
||||
*/
|
||||
|
||||
QCodeNodePool::QCodeNodePool(int size)
|
||||
: m_size(size), m_last(0), m_free(0), m_own(true),
|
||||
m_nodes(static_cast<QCodeNode *>(malloc(size * sizeof(QCodeNode)))) {}
|
||||
|
||||
QCodeNodePool::QCodeNodePool(void *data, int size)
|
||||
: m_size(size), m_last(0), m_free(0), m_own(false),
|
||||
m_nodes(static_cast<QCodeNode *>(data)) {}
|
||||
|
||||
QCodeNodePool::~QCodeNodePool() {
|
||||
if (m_own && m_nodes)
|
||||
free(m_nodes);
|
||||
}
|
||||
|
||||
int QCodeNodePool::count() const { return m_last; }
|
||||
|
||||
int QCodeNodePool::bufferSize() const { return m_size; }
|
||||
|
||||
int QCodeNodePool::occupied() const { return (100 * m_last) / m_size; }
|
||||
|
||||
int QCodeNodePool::remaining() const {
|
||||
return (100 * (m_size - m_last)) / m_size;
|
||||
}
|
||||
|
||||
QCodeNode *QCodeNodePool::alloc() {
|
||||
if (m_last == m_size) {
|
||||
// try to fill blanks...
|
||||
if (m_free > 0) {
|
||||
}
|
||||
|
||||
// fallback use malloc()
|
||||
return new QCodeNode(0);
|
||||
} else {
|
||||
return new (m_nodes + m_last++) QCodeNode(this);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void QCodeNodePool::free(QCodeNode *n) {
|
||||
if ((n < m_nodes) || (n >= (m_nodes + m_size))) {
|
||||
// not from pool... fallback to regular allocator
|
||||
delete n;
|
||||
} else {
|
||||
|
||||
if ((void *)(n + 1) == (void *)(m_nodes + m_last)) {
|
||||
--m_last;
|
||||
|
||||
QCodeNode &n = m_nodes[m_last];
|
||||
|
||||
while (!n.m_pool && !n.parent && !n.model && (m_last > 0) &&
|
||||
(m_free > 0)) {
|
||||
--m_free;
|
||||
--m_last;
|
||||
|
||||
n = m_nodes[m_last];
|
||||
}
|
||||
|
||||
} else {
|
||||
++m_free;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,49 +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_NODE_POOL_H_
|
||||
#define _QCODE_NODE_POOL_H_
|
||||
|
||||
#include "qcm-config.h"
|
||||
|
||||
/*!
|
||||
\file qcodenodepool.h
|
||||
\brief Definition of the QCodeNodePool class.
|
||||
*/
|
||||
|
||||
struct QCodeNode;
|
||||
|
||||
class QCM_EXPORT QCodeNodePool {
|
||||
public:
|
||||
QCodeNodePool(int size);
|
||||
QCodeNodePool(void *data, int size);
|
||||
~QCodeNodePool();
|
||||
|
||||
int count() const;
|
||||
int bufferSize() const;
|
||||
int occupied() const;
|
||||
int remaining() const;
|
||||
|
||||
QCodeNode *alloc();
|
||||
void free(QCodeNode *n);
|
||||
|
||||
private:
|
||||
int m_size, m_last, m_free;
|
||||
|
||||
bool m_own;
|
||||
QCodeNode *m_nodes;
|
||||
};
|
||||
|
||||
#endif // !_QCODE_NODE_POOL_H_
|
|
@ -1,76 +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 "qcodeproxymodel.h"
|
||||
|
||||
/*!
|
||||
\file qcodeproxymodel.cpp
|
||||
\brief Implementation of the QCodeProxyModel class.
|
||||
*/
|
||||
|
||||
#include "qcodemodel.h"
|
||||
#include "qcodenode.h"
|
||||
|
||||
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;
|
||||
|
||||
/*!
|
||||
\class QCodeProxyModel
|
||||
\brief Special proxy model for code models
|
||||
*/
|
||||
|
||||
QCodeProxyModel::QCodeProxyModel(QObject *p) : QSortFilterProxyModel(p) {
|
||||
setDynamicSortFilter(true);
|
||||
}
|
||||
|
||||
QCodeProxyModel::~QCodeProxyModel() {}
|
||||
|
||||
bool QCodeProxyModel::lessThan(const QModelIndex &left,
|
||||
const QModelIndex &right) const {
|
||||
int lt = priority.indexOf(
|
||||
sourceModel()->data(left, QCodeModel::TypeRole).toInt()),
|
||||
rt = priority.indexOf(
|
||||
sourceModel()->data(right, QCodeModel::TypeRole).toInt());
|
||||
|
||||
// if ( lt == rt )
|
||||
// return QSortFilterProxyModel::lessThan(left, right);
|
||||
|
||||
/*
|
||||
foreach ( int p, priority )
|
||||
{
|
||||
if ( lt == p )
|
||||
return false;
|
||||
else if ( rt == p )
|
||||
return true;
|
||||
}
|
||||
|
||||
int lv = sourceModel()->data(left, QCodeModel::VisibilityRole).toInt(),
|
||||
rv = sourceModel()->data(right, QCodeModel::VisibilityRole).toInt();
|
||||
|
||||
if ( lv != rv )
|
||||
return lv > rv;
|
||||
*/
|
||||
|
||||
QString ld = sourceModel()->data(left, Qt::DisplayRole).toString(),
|
||||
rd = sourceModel()->data(right, Qt::DisplayRole).toString();
|
||||
|
||||
// return !((lt == rt) ? (QString::localeAwareCompare(ld, rd) < 0) : (lt <
|
||||
// rt));
|
||||
return !((lt == rt) ? (ld.toUpper() < rd.toUpper()) : (lt < rt));
|
||||
}
|
|
@ -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,200 +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 "qcodeserializer.h"
|
||||
|
||||
/*!
|
||||
\file qcodeserializer.cpp
|
||||
\brief Implementation of the QCodeSerializer class.
|
||||
*/
|
||||
|
||||
#include "qcodemodel.h"
|
||||
#include "qcodenode.h"
|
||||
#include "qcodenodepool.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QIODevice>
|
||||
#include <QRegularExpression>
|
||||
#include <QTextStream>
|
||||
|
||||
/*
|
||||
File format :
|
||||
* header : '{' MIME type (text/x-tag) ',' version ',' source '}'
|
||||
* each line represents on node as a at ('@') separated list of roles
|
||||
* each space at the begining of the line represents a parenting level
|
||||
|
||||
*/
|
||||
|
||||
#define Q_VERSION(maj, min, patch) ((maj << 8) | (min << 8) | patch)
|
||||
|
||||
static int _version = Q_VERSION(2, 0, 0);
|
||||
static int _version_min = Q_VERSION(2, 0, 0), _version_max = Q_VERSION(2, 0, 0);
|
||||
static QString header_pattern("{text/x-tag,%1,%2}");
|
||||
static QRegularExpression
|
||||
header_matcher("^\\{text/x-tag,([0-9a-fA-F]+),([^}]+)\\}\n$");
|
||||
|
||||
/*!
|
||||
\class QCodeSerializer
|
||||
\brief Serializer/deserializer for code trees
|
||||
*/
|
||||
|
||||
QCodeSerializer::QCodeSerializer() : m_model(0), m_pool(0) {}
|
||||
|
||||
QCodeSerializer::~QCodeSerializer() {}
|
||||
|
||||
QCodeModel *QCodeSerializer::targetModel() const { return m_model; }
|
||||
|
||||
void QCodeSerializer::setTargetModel(QCodeModel *m) { m_model = m; }
|
||||
|
||||
QCodeNodePool *QCodeSerializer::nodePool() const { return m_pool; }
|
||||
|
||||
void QCodeSerializer::setNodePool(QCodeNodePool *p) { m_pool = p; }
|
||||
|
||||
void QCodeSerializer::serialize(QCodeNode *n, QTextStream &out, int indent) {
|
||||
if (!n)
|
||||
return;
|
||||
|
||||
if (indent > 0)
|
||||
out << QByteArray(indent, ' ');
|
||||
else
|
||||
out << header_pattern.arg(QString::number(_version))
|
||||
.arg(QString::fromLocal8Bit(n->role(QCodeNode::Context)))
|
||||
<< Qt::endl;
|
||||
|
||||
out << n->roles << "\n";
|
||||
|
||||
foreach (QCodeNode *c, n->children)
|
||||
serialize(c, out, indent + 1);
|
||||
}
|
||||
|
||||
void QCodeSerializer::deserialize(const QString &file, bool *ok,
|
||||
QString *source, const QDateTime &t) {
|
||||
QFile f(file);
|
||||
|
||||
if (f.open(QFile::Text | QFile::ReadOnly))
|
||||
deserialize(&f, ok, source, t);
|
||||
}
|
||||
|
||||
void QCodeSerializer::deserialize(QIODevice *device, bool *ok, QString *source,
|
||||
const QDateTime &t) {
|
||||
if (!device)
|
||||
return;
|
||||
|
||||
QByteArray line;
|
||||
int indent = 0, spaces;
|
||||
QCodeNode *n, *previous = 0, *parent = 0;
|
||||
|
||||
line = device->readLine();
|
||||
|
||||
auto match = header_matcher.match(line);
|
||||
|
||||
if (!match.hasMatch()) {
|
||||
qWarning("Header mismatch : %s", line.constData());
|
||||
|
||||
if (ok)
|
||||
*ok = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int version = match.captured(1).toInt(0, 0);
|
||||
|
||||
if ((version < _version_min) || (version > _version_max)) {
|
||||
qWarning("Version mismatch : %i !E [%i, %i]", version, _version_min,
|
||||
_version_max);
|
||||
|
||||
if (ok)
|
||||
*ok = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (source)
|
||||
*source = match.captured(2);
|
||||
|
||||
if (t.isValid() && ok) {
|
||||
// check time stamps if someone pay attention to success/failure
|
||||
QFileInfo info(*source);
|
||||
|
||||
if (info.lastModified() > t) {
|
||||
// source modified after tag file... must reload...
|
||||
|
||||
*ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
while (!device->atEnd()) {
|
||||
spaces = 0;
|
||||
char c;
|
||||
bool ok = device->getChar(&c);
|
||||
|
||||
while (ok && isspace(c) && (c != '\n')) {
|
||||
++spaces;
|
||||
ok = device->getChar(&c);
|
||||
}
|
||||
|
||||
if (!ok || c == '\n')
|
||||
continue;
|
||||
|
||||
if (spaces > indent) {
|
||||
// down one level
|
||||
parent = previous;
|
||||
|
||||
// if ( parent )
|
||||
// qDebug("down a level : parent = %s",
|
||||
// parent->role(QCodeNode::Name).constData());
|
||||
} else if (spaces < indent) {
|
||||
|
||||
// up one (or more) level
|
||||
for (int i = 0; (i < (indent - spaces)) && parent && parent->parent;
|
||||
++i)
|
||||
parent = parent ? parent->parent : 0;
|
||||
|
||||
// if ( parent )
|
||||
// qDebug("up one level : parent = %s",
|
||||
// parent->role(QCodeNode::Name).constData());
|
||||
} else {
|
||||
// qDebug("adding child %s", line.constData());
|
||||
}
|
||||
|
||||
n = m_pool ? m_pool->alloc() : new QCodeNode;
|
||||
|
||||
while (ok && c != '\n') {
|
||||
n->roles += c;
|
||||
ok = device->getChar(&c);
|
||||
}
|
||||
|
||||
// n->roles = device->readLine();
|
||||
// n->roles.prepend(c);
|
||||
|
||||
n->roles.squeeze();
|
||||
|
||||
if (parent)
|
||||
n->attach(parent);
|
||||
|
||||
indent = spaces;
|
||||
previous = n;
|
||||
}
|
||||
|
||||
while (parent && parent->parent)
|
||||
parent = parent->parent;
|
||||
|
||||
if (parent && m_model)
|
||||
m_model->appendTopLevelNode(parent);
|
||||
|
||||
if (ok)
|
||||
*ok = true;
|
||||
}
|
|
@ -1,60 +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_SERIALIZER_H_
|
||||
#define _QCODE_SERIALIZER_H_
|
||||
|
||||
#include "qcm-config.h"
|
||||
|
||||
/*!
|
||||
\file qcodeserializer.h
|
||||
\brief Definition of the QCodeSerializer class.
|
||||
*/
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QThread>
|
||||
|
||||
struct QCodeNode;
|
||||
class QCodeModel;
|
||||
class QCodeNodePool;
|
||||
|
||||
class QIODevice;
|
||||
class QTextStream;
|
||||
|
||||
class QCM_EXPORT QCodeSerializer {
|
||||
public:
|
||||
QCodeSerializer();
|
||||
virtual ~QCodeSerializer();
|
||||
|
||||
QCodeModel *targetModel() const;
|
||||
void setTargetModel(QCodeModel *m);
|
||||
|
||||
QCodeNodePool *nodePool() const;
|
||||
void setNodePool(QCodeNodePool *p);
|
||||
|
||||
void serialize(QCodeNode *n, QTextStream &out, int indent = 0);
|
||||
|
||||
void deserialize(const QString &file, bool *ok = 0, QString *source = 0,
|
||||
const QDateTime &t = QDateTime());
|
||||
|
||||
void deserialize(QIODevice *device, bool *ok = 0, QString *source = 0,
|
||||
const QDateTime &t = QDateTime());
|
||||
|
||||
private:
|
||||
QCodeModel *m_model;
|
||||
QCodeNodePool *m_pool;
|
||||
};
|
||||
|
||||
#endif // !_QCODE_SERIALIZER_H_
|
|
@ -1,156 +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 "qcodeview.h"
|
||||
|
||||
/*!
|
||||
\file qcodeview.cpp
|
||||
\brief Implementation of the QCodeView class.
|
||||
*/
|
||||
|
||||
#include "qcodemodel.h"
|
||||
#include "qcodenode.h"
|
||||
|
||||
#include <QAbstractProxyModel>
|
||||
#include <QContextMenuEvent>
|
||||
#include <QFileInfo>
|
||||
|
||||
/*!
|
||||
\class QCodeView
|
||||
\brief Specialized tree view to display code models
|
||||
*/
|
||||
|
||||
QCodeView::QCodeView(QWidget *p) : QTreeView(p) {
|
||||
setAutoScroll(true);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
|
||||
connect(this, SIGNAL(activated(QModelIndex)), this,
|
||||
SLOT(indexActivated(QModelIndex)));
|
||||
}
|
||||
|
||||
QCodeView::QCodeView(QCodeModel *m, QWidget *p) : QTreeView(p), m_model(0) {
|
||||
setAutoScroll(true);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
|
||||
connect(this, SIGNAL(activated(QModelIndex)), this,
|
||||
SLOT(indexActivated(QModelIndex)));
|
||||
|
||||
setModel(m);
|
||||
}
|
||||
|
||||
QCodeView::~QCodeView() {}
|
||||
|
||||
void QCodeView::setModel(QAbstractItemModel *model) {
|
||||
QAbstractProxyModel *proxy = qobject_cast<QAbstractProxyModel *>(model);
|
||||
|
||||
if (proxy) {
|
||||
m_model = qobject_cast<QCodeModel *>(proxy->sourceModel());
|
||||
} else {
|
||||
m_model = qobject_cast<QCodeModel *>(model);
|
||||
}
|
||||
|
||||
if (!m_model)
|
||||
qFatal("QCodeView can only display a QCodeModel");
|
||||
|
||||
QTreeView::setModel(model);
|
||||
}
|
||||
|
||||
void QCodeView::contextMenuEvent(QContextMenuEvent *e) {
|
||||
e->accept();
|
||||
|
||||
QModelIndex idx = indexAt(e->pos());
|
||||
|
||||
if (!idx.isValid())
|
||||
return;
|
||||
}
|
||||
|
||||
void QCodeView::indexActivated(const QModelIndex &idx) {
|
||||
static QStringList exts = QStringList() << "cpp"
|
||||
<< "cxx"
|
||||
<< "c"
|
||||
<< "cc";
|
||||
|
||||
if (!m_model)
|
||||
return;
|
||||
|
||||
QCodeNode *n = 0;
|
||||
QAbstractProxyModel *proxy = qobject_cast<QAbstractProxyModel *>(model());
|
||||
|
||||
if (proxy) {
|
||||
n = m_model->node(proxy->mapToSource(idx));
|
||||
} else {
|
||||
n = m_model->node(idx);
|
||||
}
|
||||
|
||||
if (!n)
|
||||
return;
|
||||
|
||||
QString cxt = n->context();
|
||||
|
||||
if (n->type() == QCodeNode::Function) {
|
||||
// open the source file instead (after checking whether it lies in
|
||||
// header...)
|
||||
QFileInfo inf(cxt);
|
||||
|
||||
foreach (const QString &ext, exts) {
|
||||
QString scxt = cxt;
|
||||
scxt.chop(inf.suffix().length());
|
||||
scxt += ext;
|
||||
|
||||
if (QFile::exists(scxt)) {
|
||||
cxt = scxt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (n->line != -1) {
|
||||
emit actionRequested("open", QStringList() << cxt << "-l"
|
||||
<< QString::number(n->line));
|
||||
return;
|
||||
}
|
||||
|
||||
int i;
|
||||
QString ptp, rxp, qn = n->qualifiedName(false);
|
||||
|
||||
// qDebug("%s [%s] {%s}", qPrintable(qn),
|
||||
// qPrintable(n->data(Qt::DisplayRole).toString()),
|
||||
// n->role(QCodeNode::NodeType).constData());
|
||||
|
||||
// qn.remove(0, qn.indexOf("/") + 1);
|
||||
|
||||
ptp = qn;
|
||||
rxp = QRegularExpression::escape(qn);
|
||||
|
||||
rxp.replace(
|
||||
QRegularExpression("\\s*(::|\\\\[()\\[\\]{}|*$+.?^]|[,&<>])\\s*"),
|
||||
"\\s*\\1\\s*");
|
||||
rxp.replace(" ", "\\s+");
|
||||
|
||||
i = rxp.indexOf("(");
|
||||
|
||||
QString tmp = rxp.mid(i);
|
||||
tmp.replace(
|
||||
QRegularExpression("(\\\\s[+*])[\\w_]+\\\\s\\*(,|\\\\\\)\\\\s\\*$)"),
|
||||
"\\1[\\w_]*\\s*\\2");
|
||||
rxp = rxp.left(i) + tmp;
|
||||
|
||||
ptp.replace(QRegularExpression(" (::|[()<>]) "), "\\1");
|
||||
i = ptp.indexOf("(");
|
||||
|
||||
if (i != -1)
|
||||
ptp = ptp.left(i);
|
||||
|
||||
emit actionRequested("open", QStringList()
|
||||
<< cxt << "-s" << ptp << "-rx" << rxp);
|
||||
}
|
|
@ -1,53 +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_VIEW_H_
|
||||
#define _QCODE_VIEW_H_
|
||||
|
||||
#include "qcm-config.h"
|
||||
|
||||
/*!
|
||||
\file qcodeview.h
|
||||
\brief Definition of the QCodeView class.
|
||||
*/
|
||||
|
||||
#include <QTreeView>
|
||||
|
||||
class QCodeModel;
|
||||
|
||||
class QCM_EXPORT QCodeView : public QTreeView {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QCodeView(QWidget *p = nullptr);
|
||||
QCodeView(QCodeModel *m, QWidget *p = nullptr);
|
||||
virtual ~QCodeView();
|
||||
|
||||
virtual void setModel(QAbstractItemModel *model);
|
||||
|
||||
signals:
|
||||
void actionRequested(const QString &action, const QStringList ¶ms);
|
||||
|
||||
protected:
|
||||
virtual void contextMenuEvent(QContextMenuEvent *e);
|
||||
|
||||
protected slots:
|
||||
void indexActivated(const QModelIndex &idx);
|
||||
|
||||
private:
|
||||
QCodeModel *m_model;
|
||||
};
|
||||
|
||||
#endif // !_QCODE_VIEW_H_
|
|
@ -1,94 +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 "qsourcecodewatcher.h"
|
||||
|
||||
#include "qcodemodel.h"
|
||||
#include "qcodenode.h"
|
||||
|
||||
#include <QTimerEvent>
|
||||
|
||||
QList<QSourceCodeWatcher *> QSourceCodeWatcher::m_instances;
|
||||
|
||||
QSourceCodeWatcher *QSourceCodeWatcher::watcher(QCodeNode *t, QCodeParser *c) {
|
||||
if (!t)
|
||||
return 0;
|
||||
|
||||
for (int i = 0; i < m_instances.count(); ++i) {
|
||||
if (m_instances.at(i)->m_target == t) {
|
||||
return m_instances[i];
|
||||
}
|
||||
}
|
||||
|
||||
return c ? new QSourceCodeWatcher(t, c, t->model) : 0;
|
||||
}
|
||||
|
||||
QSourceCodeWatcher::QSourceCodeWatcher(QCodeNode *n, QCodeParser *c, QObject *p)
|
||||
: QFileSystemWatcher(p), m_target(n), m_parser(c) {
|
||||
connect(this, SIGNAL(fileChanged(QString)), this,
|
||||
SLOT(sourceChanged(QString)));
|
||||
|
||||
m_instances << this;
|
||||
|
||||
// qDebug("%i watchers", m_instances.count());
|
||||
}
|
||||
|
||||
QSourceCodeWatcher::~QSourceCodeWatcher() {
|
||||
m_instances.removeAll(this);
|
||||
|
||||
// qDebug("%i watchers left", m_instances.count());
|
||||
}
|
||||
|
||||
void QSourceCodeWatcher::timerEvent(QTimerEvent *e) {
|
||||
if (e->timerId() != m_timer.timerId())
|
||||
return QFileSystemWatcher::timerEvent(e);
|
||||
|
||||
if (!m_parser)
|
||||
return;
|
||||
|
||||
QHash<QString, char>::iterator it = m_state.begin();
|
||||
|
||||
while (it != m_state.end()) {
|
||||
if (*it & Duplicate) {
|
||||
// postpone...
|
||||
*it = Recent;
|
||||
++it;
|
||||
} else {
|
||||
// process
|
||||
// m_parser->update(m_target, it.key());
|
||||
// TODO
|
||||
it = m_state.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_state.count()) {
|
||||
m_timer.start(50, this);
|
||||
}
|
||||
}
|
||||
|
||||
void QSourceCodeWatcher::sourceChanged(const QString &filepath) {
|
||||
if (!m_target)
|
||||
return;
|
||||
|
||||
m_timer.stop();
|
||||
|
||||
if (!m_state.contains(filepath)) {
|
||||
m_state[filepath] = Recent;
|
||||
} else {
|
||||
m_state[filepath] = Recent | Duplicate;
|
||||
}
|
||||
|
||||
m_timer.start(50, this);
|
||||
}
|
|
@ -1,57 +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 _QSOURCE_CODE_WATCHER_H_
|
||||
#define _QSOURCE_CODE_WATCHER_H_
|
||||
|
||||
#include "qcm-config.h"
|
||||
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QHash>
|
||||
#include <QTimer>
|
||||
|
||||
struct QCodeNode;
|
||||
class QCodeParser;
|
||||
|
||||
class QCM_EXPORT QSourceCodeWatcher : public QFileSystemWatcher {
|
||||
friend struct QCodeNode;
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static QSourceCodeWatcher *watcher(QCodeNode *t, QCodeParser *c = 0);
|
||||
|
||||
protected:
|
||||
QSourceCodeWatcher(QCodeNode *n, QCodeParser *c, QObject *p = 0);
|
||||
virtual ~QSourceCodeWatcher();
|
||||
|
||||
virtual void timerEvent(QTimerEvent *e);
|
||||
|
||||
private slots:
|
||||
void sourceChanged(const QString &filepath);
|
||||
|
||||
private:
|
||||
enum State { Recent = 1, Duplicate = 2 };
|
||||
|
||||
QHash<QString, char> m_state;
|
||||
|
||||
QBasicTimer m_timer;
|
||||
QCodeNode *m_target;
|
||||
QCodeParser *m_parser;
|
||||
|
||||
static QList<QSourceCodeWatcher *> m_instances;
|
||||
};
|
||||
|
||||
#endif // !_QSOURCE_CODE_WATCHER_H_
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "editorview.h"
|
||||
|
||||
#include "QHexView/document/buffer/qfilebuffer.h"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue