Compare commits

...

7 Commits

198 changed files with 5588 additions and 3363 deletions

View File

@ -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);

View File

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

View File

@ -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

View File

@ -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;

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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());

View File

@ -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();
}

View File

@ -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

View File

@ -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,

View File

@ -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);

View File

@ -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;
}
/*! @} */

View File

@ -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:
};

View File

@ -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;
}
/*!

View File

@ -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);

View File

@ -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;
}
/*! @} */

View File

@ -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;

View File

@ -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 *) {}
/* @} */

View File

@ -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;

View File

@ -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}

View File

@ -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

View File

@ -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;

315
mkinstaller/pyscript/installer.py Executable file
View File

@ -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

View File

@ -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>

14
resource.h Normal file
View File

@ -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

View File

@ -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>

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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>

View File

@ -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

View File

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

View File

@ -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_

View File

@ -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() {}

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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 />")));
}
}

View File

@ -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;

View File

@ -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 &parameterTypes = fun->parameterTypes;
auto &parameterNames = 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 &section) {
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; }

View File

@ -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 &section);
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_

412
src/class/qcodenode.cpp Normal file
View File

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

View File

@ -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_

View File

@ -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() {

View File

@ -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

View File

@ -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;
}

View File

@ -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)

View File

@ -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"

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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_

View File

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

View File

@ -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_

View File

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

View File

@ -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;
}
}
}

View File

@ -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_

View File

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

View File

@ -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_

View File

@ -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;
}

View File

@ -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_

View File

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

View File

@ -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 &params);
protected:
virtual void contextMenuEvent(QContextMenuEvent *e);
protected slots:
void indexActivated(const QModelIndex &idx);
private:
QCodeModel *m_model;
};
#endif // !_QCODE_VIEW_H_

View File

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

View File

@ -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_

View File

@ -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