feat: 调整控制台基类以实现代码高亮和提示(WIP);修复代码编辑器光标重绘残留;

This commit is contained in:
寂静的羽夏 2024-11-10 22:11:41 +08:00
parent 912dfaf227
commit 48cf02cfa9
33 changed files with 912 additions and 902 deletions

View File

@ -1,3 +0,0 @@
*.pro.user*

View File

@ -1,28 +0,0 @@
cmake_minimum_required(VERSION 3.5)
project(
QConsoleWidget
VERSION 2.14.1
LANGUAGES CXX)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
if(MSVC)
string(APPEND CMAKE_CXX_FLAGS " /utf-8")
string(APPEND CMAKE_C_FLAGS " /utf-8")
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()
add_library(
QConsoleWidget STATIC src/QConsoleIODevice.cpp src/QConsoleIODevice.h
src/QConsoleWidget.cpp src/QConsoleWidget.h)
target_link_libraries(QConsoleWidget PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)

View File

@ -7,7 +7,6 @@
class QConsoleWidget;
class QConsoleIODevice : public QIODevice {
Q_OBJECT
public:

View File

@ -1,7 +1,12 @@
#include "QConsoleWidget.h"
#include "QConsoleIODevice.h"
#include <QAbstractItemView>
#include "class/langservice.h"
#include "qdocumentline.h"
#include "qformatscheme.h"
#include "qlanguagefactory.h"
#include "utilities.h"
#include <QApplication>
#include <QClipboard>
#include <QDebug>
@ -12,24 +17,20 @@
#include <QMimeData>
#include <QMouseEvent>
#include <QScrollBar>
#include <QStandardPaths>
#include <QStringListModel>
#include <QTextBlock>
#include <QTextCursor>
#include <QTextDocumentFragment>
QConsoleWidget::QConsoleWidget(QWidget *parent)
: QPlainTextEdit(parent), mode_(Output), completer_(0) {
: QEditor(false, parent), mode_(Output), completer_(nullptr) {
iodevice_ = new QConsoleIODevice(this, this);
QTextCharFormat fmt = currentCharFormat();
for (int i = 0; i < nConsoleChannels; i++)
chanFormat_[i] = fmt;
// QTextCharFormat fmt = currentCharFormat();
// for (int i = 0; i < nConsoleChannels; i++)
// chanFormat_[i] = fmt;
chanFormat_[StandardOutput].setForeground(Qt::darkBlue);
chanFormat_[StandardError].setForeground(Qt::red);
setTextInteractionFlags(Qt::TextEditorInteraction);
// setTextInteractionFlags();
setUndoRedoEnabled(false);
}
@ -40,11 +41,11 @@ void QConsoleWidget::setMode(ConsoleMode m) {
return;
if (m == Input) {
QTextCursor cursor = textCursor();
cursor.movePosition(QTextCursor::End);
setTextCursor(cursor);
setCurrentCharFormat(chanFormat_[StandardInput]);
inpos_ = cursor.position();
auto cursor = this->cursor();
cursor.movePosition(QDocumentCursor::End);
setCursor(cursor);
// setCurrentCharFormat(chanFormat_[StandardInput]);
inpos_ = cursor;
mode_ = Input;
}
@ -56,25 +57,25 @@ void QConsoleWidget::setMode(ConsoleMode m) {
QString QConsoleWidget::getCommandLine() {
if (mode_ == Output)
return QString();
// select text in edit zone (from the input pos to the end)
QTextCursor textCursor = this->textCursor();
textCursor.movePosition(QTextCursor::End);
textCursor.setPosition(inpos_, QTextCursor::KeepAnchor);
QString code = textCursor.selectedText();
code.replace(QChar::ParagraphSeparator, QChar::LineFeed);
return code;
auto textCursor = this->cursor();
auto ltxt = textCursor.line().text();
QString code = ltxt.mid(inpos_.columnNumber());
return code.replace(QChar::ParagraphSeparator, QChar::LineFeed);
}
void QConsoleWidget::clear() { document()->clear(); }
void QConsoleWidget::handleReturnKey() {
QString code = getCommandLine();
// start new block
appendPlainText(QString());
setMode(Output);
auto textCursor = this->cursor();
auto line = textCursor.line();
textCursor.moveTo(line.lineNumber(), line.length());
textCursor.insertLine();
QTextCursor textCursor = this->textCursor();
textCursor.movePosition(QTextCursor::End);
setTextCursor(textCursor);
setMode(Output);
setCursor(textCursor);
// Update the history
if (!code.isEmpty())
@ -87,107 +88,23 @@ void QConsoleWidget::handleReturnKey() {
emit consoleCommand(code);
}
void QConsoleWidget::handleTabKey() {
QTextCursor tc = this->textCursor();
int anchor = tc.anchor();
int position = tc.position();
tc.setPosition(inpos_);
tc.setPosition(position, QTextCursor::KeepAnchor);
QString text = tc.selectedText().trimmed();
tc.setPosition(anchor, QTextCursor::MoveAnchor);
tc.setPosition(position, QTextCursor::KeepAnchor);
if (text.isEmpty()) {
tc.insertText(" ");
} else {
updateCompleter();
if (completer_ && completer_->completionCount() == 1) {
insertCompletion(completer_->currentCompletion());
completer_->popup()->hide();
}
}
}
void QConsoleWidget::updateCompleter() {
if (!completer_)
return;
// if the completer is first shown, mark
// the text position
QTextCursor textCursor = this->textCursor();
if (!completer_->popup()->isVisible()) {
completion_pos_ = textCursor.position();
// qDebug() << "show completer, pos " << completion_pos_;
}
// Get the text between the current cursor position
// and the start of the input
textCursor.setPosition(inpos_, QTextCursor::KeepAnchor);
QString commandText = textCursor.selectedText();
// qDebug() << "code to complete: " << commandText;
// Call the completer to update the completion model
// Place and show the completer if there are available completions
int count;
if ((count = completer_->updateCompletionModel(commandText))) {
// qDebug() << "found " << count << " completions";
// Get a QRect for the cursor at the start of the
// current word and then translate it down 8 pixels.
textCursor = this->textCursor();
textCursor.movePosition(QTextCursor::StartOfWord);
QRect cr = this->cursorRect(textCursor);
cr.translate(0, 8);
cr.setWidth(
completer_->popup()->sizeHintForColumn(0) +
completer_->popup()->verticalScrollBar()->sizeHint().width());
completer_->complete(cr);
} else {
// qDebug() << "no completions - hiding";
completer_->popup()->hide();
}
}
void QConsoleWidget::checkCompletionTriggers(const QString &txt) {
if (!completer_ || completion_triggers_.isEmpty() || txt.isEmpty())
return;
foreach (const QString &tr, completion_triggers_) {
if (tr.endsWith(txt)) {
QTextCursor tc = this->textCursor();
tc.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor,
tr.length());
if (tc.selectedText() == tr) {
updateCompleter();
return;
}
}
}
}
void QConsoleWidget::insertCompletion(const QString &completion) {
QTextCursor tc = textCursor();
tc.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor,
tc.position() - inpos_ - completer_->insertPos());
tc.insertText(completion, chanFormat_[StandardInput]);
setTextCursor(tc);
}
void QConsoleWidget::setCompleter(QConsoleWidgetCompleter *c) {
void QConsoleWidget::setCompleter(QCodeCompletionWidget *c) {
if (completer_) {
completer_->setWidget(0);
QObject::disconnect(completer_, SIGNAL(activated(const QString &)),
this, SLOT(insertCompletion(const QString &)));
// completer_->setWidget(0);
// QObject::disconnect(completer_, SIGNAL(activated(const QString &)),
// this, SLOT(insertCompletion(const QString &)));
}
completer_ = c;
if (completer_) {
completer_->setWidget(this);
QObject::connect(completer_, SIGNAL(activated(const QString &)), this,
SLOT(insertCompletion(const QString &)));
// completer_->setWidget(this);
// QObject::connect(completer_, SIGNAL(activated(const QString &)),
// this,
// SLOT(insertCompletion(const QString &)));
}
}
void QConsoleWidget::keyPressEvent(QKeyEvent *e) {
if (completer_ && completer_->popup()->isVisible()) {
if (completer_ && completer_->isVisible()) {
// The following keys are forwarded by the completer to the widget
switch (e->key()) {
case Qt::Key_Tab:
@ -202,7 +119,7 @@ void QConsoleWidget::keyPressEvent(QKeyEvent *e) {
}
}
QTextCursor textCursor = this->textCursor();
auto textCursor = this->cursor();
bool selectionInEditZone = isSelectionInEditZone();
// check for user abort request
@ -244,7 +161,8 @@ void QConsoleWidget::keyPressEvent(QKeyEvent *e) {
QApplication::clipboard()->mimeData();
const QString text = clipboard->text();
if (!text.isNull()) {
textCursor.insertText(text, channelCharFormat(StandardInput));
textCursor.insertText(text/*,
channelCharFormat(StandardInput)*/);
}
}
@ -253,7 +171,7 @@ void QConsoleWidget::keyPressEvent(QKeyEvent *e) {
}
int key = e->key();
int shiftMod = e->modifiers() == Qt::ShiftModifier;
// int shiftMod = e->modifiers() == Qt::ShiftModifier;
if (history_.isActive() && key != Qt::Key_Up && key != Qt::Key_Down)
history_.deactivate();
@ -262,8 +180,9 @@ void QConsoleWidget::keyPressEvent(QKeyEvent *e) {
// for all keys except modifiers
if (!isCursorInEditZone() && key != Qt::Key_Control &&
key != Qt::Key_Shift && key != Qt::Key_Alt) {
textCursor.movePosition(QTextCursor::End);
setTextCursor(textCursor);
auto line = textCursor.line();
textCursor.moveTo(line.lineNumber(), line.length());
setCursor(textCursor);
}
switch (key) {
@ -286,8 +205,8 @@ void QConsoleWidget::keyPressEvent(QKeyEvent *e) {
e->accept();
case Qt::Key_Left:
if (textCursor.position() > inpos_)
QPlainTextEdit::keyPressEvent(e);
if (textCursor > inpos_)
QEditor::keyPressEvent(e);
else {
QApplication::beep();
e->accept();
@ -300,10 +219,10 @@ void QConsoleWidget::keyPressEvent(QKeyEvent *e) {
cut();
else {
// cursor must be in edit zone
if (textCursor.position() < inpos_)
if (textCursor < inpos_)
QApplication::beep();
else
QPlainTextEdit::keyPressEvent(e);
QEditor::keyPressEvent(e);
}
break;
@ -313,23 +232,16 @@ void QConsoleWidget::keyPressEvent(QKeyEvent *e) {
cut();
else {
// cursor must be in edit zone
if (textCursor.position() <= inpos_)
if (textCursor <= inpos_)
QApplication::beep();
else
QPlainTextEdit::keyPressEvent(e);
QEditor::keyPressEvent(e);
}
break;
case Qt::Key_Tab:
e->accept();
handleTabKey();
return;
case Qt::Key_Home:
e->accept();
textCursor.setPosition(inpos_, shiftMod ? QTextCursor::KeepAnchor
: QTextCursor::MoveAnchor);
setTextCursor(textCursor);
setCursor(inpos_);
break;
case Qt::Key_Enter:
@ -344,58 +256,47 @@ void QConsoleWidget::keyPressEvent(QKeyEvent *e) {
break;
default:
e->accept();
setCurrentCharFormat(chanFormat_[StandardInput]);
QPlainTextEdit::keyPressEvent(e);
// check if the last key triggers a completion
checkCompletionTriggers(e->text());
// setCurrentCharFormat(chanFormat_[StandardInput]);
if (isCursorInEditZone()) {
QEditor::keyPressEvent(e);
} else {
e->ignore();
}
break;
}
if (completer_ && completer_->popup()->isVisible()) {
// if the completer is visible check if it should be updated
if (this->textCursor().position() < completion_pos_)
completer_->popup()->hide();
else
updateCompleter();
}
}
void QConsoleWidget::contextMenuEvent(QContextMenuEvent *event) {
QMenu *menu = createStandardContextMenu();
// QMenu *menu = createStandardContextMenu();
QAction *a;
if ((a = menu->findChild<QAction *>("edit-cut")))
a->setEnabled(canCut());
if ((a = menu->findChild<QAction *>("edit-delete")))
a->setEnabled(canCut());
if ((a = menu->findChild<QAction *>("edit-paste")))
a->setEnabled(canPaste());
// QAction *a;
// if ((a = menu->findChild<QAction *>("edit-cut")))
// a->setEnabled(canCut());
// if ((a = menu->findChild<QAction *>("edit-delete")))
// a->setEnabled(canCut());
// if ((a = menu->findChild<QAction *>("edit-paste")))
// a->setEnabled(canPaste());
menu->exec(event->globalPos());
delete menu;
// menu->exec(event->globalPos());
// delete menu;
}
bool QConsoleWidget::isSelectionInEditZone() const {
QTextCursor textCursor = this->textCursor();
auto textCursor = this->cursor();
if (!textCursor.hasSelection())
return false;
int selectionStart = textCursor.selectionStart();
int selectionEnd = textCursor.selectionEnd();
auto selectionStart = textCursor.selectionStart();
auto selectionEnd = textCursor.selectionEnd();
return selectionStart >= inpos_ && selectionEnd >= inpos_;
return selectionStart > inpos_ && selectionEnd >= inpos_;
}
bool QConsoleWidget::isCursorInEditZone() const {
return textCursor().position() >= inpos_;
}
bool QConsoleWidget::isCursorInEditZone() const { return cursor() >= inpos_; }
bool QConsoleWidget::canPaste() const {
QTextCursor textCursor = this->textCursor();
if (textCursor.position() < inpos_)
return false;
if (textCursor.anchor() < inpos_)
auto textCursor = this->cursor();
if (textCursor < inpos_)
return false;
return true;
}
@ -403,70 +304,57 @@ bool QConsoleWidget::canPaste() const {
void QConsoleWidget::replaceCommandLine(const QString &str) {
// Select the text after the last command prompt ...
QTextCursor textCursor = this->textCursor();
textCursor.movePosition(QTextCursor::End);
textCursor.setPosition(inpos_, QTextCursor::KeepAnchor);
auto textCursor = this->cursor();
auto line = textCursor.line();
textCursor.moveTo(line.lineNumber(), line.length());
// ... and replace it with new string.
textCursor.insertText(str, chanFormat_[StandardInput]);
auto bcursor = inpos_;
bcursor.setSelectionBoundary(textCursor);
bcursor.replaceSelectedText(str);
bcursor.movePosition(str.length());
// move to the end of the document
textCursor.movePosition(QTextCursor::End);
setTextCursor(textCursor);
setCursor(bcursor);
}
QString QConsoleWidget::getHistoryPath() {
QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) +
QDir::separator() + APP_NAME);
QDir dir(Utilities::getAppDataPath());
return dir.absoluteFilePath(QStringLiteral(".command_history.lst"));
}
void QConsoleWidget::write(const QString &message, const QTextCharFormat &fmt) {
QTextCharFormat currfmt = currentCharFormat();
QTextCursor tc = textCursor();
// QTextCharFormat currfmt = currentCharFormat();
auto tc = cursor();
if (mode() == Input) {
// in Input mode output messages are inserted
// before the edit block
// get offset of current pos from the end
int editpos = tc.position();
tc.movePosition(QTextCursor::End);
editpos = tc.position() - editpos;
auto editpos = tc;
auto line = editpos.line();
tc.moveTo(line, 0);
tc.insertLine();
tc.insertText(message /*, fmt*/);
// convert the input pos as relative from the end
inpos_ = tc.position() - inpos_;
// insert block
tc.movePosition(QTextCursor::StartOfBlock);
tc.insertBlock();
tc.movePosition(QTextCursor::PreviousBlock);
tc.insertText(message, fmt);
tc.movePosition(QTextCursor::End);
// restore input pos
inpos_ = tc.position() - inpos_;
// restore the edit pos
tc.movePosition(QTextCursor::Left, QTextCursor::MoveAnchor, editpos);
setTextCursor(tc);
setCurrentCharFormat(currfmt);
setCursor(editpos);
// setCurrentCharFormat(currfmt);
} else {
// in output mode messages are appended
QTextCursor tc1 = tc;
tc1.movePosition(QTextCursor::End);
auto tc1 = tc;
tc1.movePosition(QDocumentCursor::End);
// check is cursor was not at the end
// (e.g. had been moved per mouse action)
bool needsRestore = tc1.position() != tc.position();
// insert text
setTextCursor(tc1);
textCursor().insertText(message, fmt);
setCursor(tc1);
tc.insertText(message /*, fmt*/);
ensureCursorVisible();
// restore cursor if needed
if (needsRestore)
setTextCursor(tc);
setCursor(tc);
}
}

View File

@ -1,14 +1,17 @@
#ifndef _QCONSOLEWIDGET_H_
#define _QCONSOLEWIDGET_H_
#include <QCompleter>
#include <QPlainTextEdit>
#include <QIODevice>
#include <QTextCharFormat>
#include <QTextStream>
class QConsoleIODevice;
class QConsoleWidgetCompleter;
#include "control/qcodecompletionwidget.h"
#include "qeditor.h"
#include "qlanguagefactory.h"
class QConsoleWidget : public QPlainTextEdit {
class QConsoleIODevice;
class QConsoleWidget : public QEditor {
Q_OBJECT
public:
@ -23,8 +26,8 @@ public:
};
Q_ENUM(ConsoleChannel)
QConsoleWidget(QWidget *parent = 0);
~QConsoleWidget();
explicit QConsoleWidget(QWidget *parent = nullptr);
virtual ~QConsoleWidget();
ConsoleMode mode() const { return mode_; }
void setMode(ConsoleMode m);
@ -35,20 +38,16 @@ public:
void setChannelCharFormat(ConsoleChannel ch, const QTextCharFormat &fmt) {
chanFormat_[ch] = fmt;
}
const QStringList &completionTriggers() const {
return completion_triggers_;
}
void setCompletionTriggers(const QStringList &l) {
completion_triggers_ = l;
}
virtual QSize sizeHint() const override { return QSize(600, 400); }
// write a formatted message to the console
void write(const QString &message, const QTextCharFormat &fmt);
static const QStringList &history() { return history_.strings_; }
void setCompleter(QConsoleWidgetCompleter *c);
void setCompleter(QCodeCompletionWidget *c);
// get the current command line
QString getCommandLine();
void clear();
public slots:
// write to StandardOutput
@ -67,10 +66,7 @@ protected:
bool canPaste() const;
bool canCut() const { return isSelectionInEditZone(); }
void handleReturnKey();
void handleTabKey();
void updateCompleter();
void checkCompletionTriggers(const QString &txt);
// reimp QPlainTextEdit functions
void keyPressEvent(QKeyEvent *e) override;
void contextMenuEvent(QContextMenuEvent *event) override;
// Returns true if there is a selection in edit zone
@ -82,11 +78,6 @@ protected:
static QString getHistoryPath();
protected slots:
// insert the completion from completer
void insertCompletion(const QString &completion);
private:
struct History {
QStringList strings_;
@ -109,12 +100,13 @@ private:
static History history_;
ConsoleMode mode_;
int inpos_, completion_pos_;
QStringList completion_triggers_;
QDocumentCursor inpos_;
QString currentMultiLineCode_;
QConsoleIODevice *iodevice_;
QTextCharFormat chanFormat_[nConsoleChannels];
QConsoleWidgetCompleter *completer_;
QCodeCompletionWidget *completer_;
QLanguageFactory *m_language = nullptr;
};
QTextStream &waitForInput(QTextStream &s);
@ -122,22 +114,4 @@ QTextStream &inputMode(QTextStream &s);
QTextStream &outChannel(QTextStream &s);
QTextStream &errChannel(QTextStream &s);
class QConsoleWidgetCompleter : public QCompleter {
public:
/*
* Update the completion model given a string. The given string
* is the current console text between the cursor and the start of
* the line.
*
* Return the completion count
*/
virtual int updateCompletionModel(const QString &str) = 0;
/*
* Return the position in the command line where the completion
* should be inserted
*/
virtual int insertPos() = 0;
};
#endif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

View File

@ -1,9 +0,0 @@
INCLUDEPATH += $$PWD
DEPENDPATH += $$PWD
SOURCES += $$PWD/QConsoleWidget.cpp \
$$PWD/QConsoleIODevice.cpp
HEADERS += $$PWD/QConsoleWidget.h \
$$PWD/QConsoleIODevice.h

View File

@ -171,7 +171,7 @@ QDocument::QDocument(QObject *p)
: QObject(p), m_impl(new QDocumentPrivate(this)) {
if (!QDocumentPrivate::m_font) {
// must not happen if config dialog plugged in...
setFont(QFont("Monospace", 10));
setFont(qApp->font());
}
setText(QString());
@ -476,7 +476,7 @@ void QDocument::stopChunkLoading() {
emit lineCountChanged(lineCount());
emit m_impl->emitContentsChange(0, m_impl->m_lines.count());
m_impl->emitContentsChange(0, m_impl->m_lines.count());
}
/*!
@ -1010,11 +1010,11 @@ int QDocument::y(const QDocumentLine &l) const {
\note the width of the returned rectangle is the DOCUMENT's width
*/
QRect QDocument::lineRect(int line) const {
const int yoff = y(line);
const int yoff = y(line) - 1;
return (yoff != -1)
? QRect(0, yoff, width(),
this->line(line).lineSpan() * m_impl->m_lineSpacing)
this->line(line).lineSpan() * m_impl->m_lineSpacing + 1)
: QRect();
}
@ -3400,30 +3400,6 @@ void QDocumentCursorHandle::setColumnMemory(bool y) {
clearFlag(ColumnMemory);
}
void QDocumentCursorHandle::setPosition(int pos, int m) {
Q_UNUSED(pos)
Q_UNUSED(m)
qWarning("Set position to cursor using character index : forbidden...");
/*
if ( m == QDocumentCursor::MoveAnchor )
{
m_begLine = m_doc->findLine(pos);
m_begOffset = (m_begLine.isValid() ? pos : 0);
m_endLine = QDocumentLine();
m_endOffset = 0;
m_max = m_begLine.cursorToX(m_begOffset);
} else {
m_endLine = m_doc->findLine(pos);
m_endOffset = (m_begLine.isValid() ? pos : 0);
//m_max = 0;
}
*/
}
bool QDocumentCursorHandle::movePosition(int count, int op, int m) {
if (!m_doc)
return false;
@ -4941,7 +4917,7 @@ int QDocumentPrivate::position(const QDocumentLineHandle *l) const {
return pos;
}
QDocumentLineHandle *QDocumentPrivate::lineForPosition(int &position) const {
QDocumentLineHandle *QDocumentPrivate::lineForPosition(int position) const {
int pos = 0, idx = 0;
while ((pos + m_lines.at(idx)->length()) < position)

View File

@ -67,7 +67,7 @@ public:
void draw(QPainter *p, QDocument::PaintContext &cxt);
QDocumentLineHandle *lineForPosition(int &position) const;
QDocumentLineHandle *lineForPosition(int position) const;
int position(const QDocumentLineHandle *l) const;
QDocumentLineHandle *at(int line) const;

View File

@ -418,16 +418,6 @@ void QDocumentCursor::shift(int offset) {
m_handle->shift(offset);
}
/*!
\brief Set the text position of the cursor (within the whole document)
Remark made about position() applies.
*/
void QDocumentCursor::setPosition(int pos, MoveMode m) {
if (m_handle)
m_handle->setPosition(pos, m);
}
/*!
\brief Moves the cursor position
\param offset number of times the selected move will be done
@ -515,7 +505,7 @@ void QDocumentCursor::eraseLine() {
*/
void QDocumentCursor::insertLine(bool keepAnchor) {
if (m_handle)
m_handle->insertText("\n", keepAnchor);
m_handle->insertText(QStringLiteral("\n"), keepAnchor);
}
/*!

View File

@ -132,7 +132,6 @@ public:
QDocumentLine anchorLine() const;
void shift(int offset);
void setPosition(int pos, MoveMode m = MoveAnchor);
bool movePosition(int offset, MoveOperation op = NextCharacter,
MoveMode m = MoveAnchor);

View File

@ -90,7 +90,6 @@ public:
int position() const;
void shift(int offset);
void setPosition(int pos, int m);
bool movePosition(int offset, int op, int m);
void insertText(const QString &s, bool keepAnchor = false);

View File

@ -203,7 +203,7 @@ QString QEditor::defaultInputBindingId() {
void QEditor::registerInputBinding(QEditorInputBindingInterface *b) {
m_registeredBindings[b->id()] = b;
for (QEditor *e : m_editors)
for (auto &e : m_editors)
e->updateBindingsMenu();
}
@ -213,7 +213,7 @@ void QEditor::registerInputBinding(QEditorInputBindingInterface *b) {
void QEditor::unregisterInputBinding(QEditorInputBindingInterface *b) {
m_registeredBindings.remove(b->id());
for (QEditor *e : m_editors)
for (auto &e : m_editors)
e->updateBindingsMenu();
}
@ -281,7 +281,7 @@ int QEditor::defaultFlags() { return m_defaultFlags; }
void QEditor::setDefaultFlags(int flags) {
m_defaultFlags = flags & Accessible;
for (QEditor *e : m_editors) {
for (auto &e : m_editors) {
bool ontoWrap = (m_defaultFlags & LineWrap) && !(e->m_state & LineWrap);
bool outOfWrap =
!(m_defaultFlags & LineWrap) && (e->m_state & LineWrap);
@ -318,7 +318,7 @@ QString QEditor::defaultCodecName() { return m_defaultCodecName; }
affected by the change of the default codecName.
*/
void QEditor::setDefaultCodec(const QString &name, int update) {
for (QEditor *e : m_editors) {
for (auto &e : m_editors) {
if (e->codecName() == m_defaultCodecName) {
if (update & UpdateOld)
e->setCodec(name);
@ -644,8 +644,8 @@ void QEditor::init(bool actions) {
m_bindingsActions = new QActionGroup(m_bindingsMenu);
// m_bindingsActions->setExclusive(true);
connect(m_bindingsActions, SIGNAL(triggered(QAction *)), this,
SLOT(bindingSelected(QAction *)));
connect(m_bindingsActions, &QActionGroup::triggered, this,
&QEditor::bindingSelected);
aDefaultBinding = new QAction(tr("Default"), m_bindingsMenu);
aDefaultBinding->setCheckable(true);
@ -669,8 +669,8 @@ void QEditor::init(bool actions) {
m_lineEndingsActions = new QActionGroup(m_lineEndingsMenu);
m_lineEndingsActions->setExclusive(true);
connect(m_lineEndingsActions, SIGNAL(triggered(QAction *)), this,
SLOT(lineEndingSelected(QAction *)));
connect(m_lineEndingsActions, &QActionGroup::triggered, this,
&QEditor::lineEndingSelected);
m_lineEndingsActions->addAction(tr("Conservative"))
->setData("conservative");
@ -681,7 +681,7 @@ void QEditor::init(bool actions) {
QList<QAction *> lle = m_lineEndingsActions->actions();
for (QAction *a : lle) {
for (auto &a : lle) {
a->setCheckable(true);
m_lineEndingsMenu->addAction(a);
}
@ -746,12 +746,16 @@ void QEditor::setFlag(EditFlag f, bool b) {
/*!
\return whether it is possible to call undo()
*/
bool QEditor::canUndo() const { return m_doc ? m_doc->canUndo() : false; }
bool QEditor::canUndo() const {
return m_doc ? (m_undoRedoEnabled && m_doc->canUndo()) : false;
}
/*!
\return whether it is possible to call redo()
*/
bool QEditor::canRedo() const { return m_doc ? m_doc->canRedo() : false; }
bool QEditor::canRedo() const {
return m_doc ? (m_undoRedoEnabled && m_doc->canRedo()) : false;
}
/*!
\brief Set line wrapping
@ -1333,7 +1337,7 @@ void QEditor::addInputBinding(QEditorInputBindingInterface *b) {
QList<QAction *> actions = m_bindingsActions->actions();
for (QAction *a : actions) {
for (auto &a : actions) {
if (a->data().toString() != id)
a->setChecked(true);
}
@ -1356,7 +1360,7 @@ void QEditor::removeInputBinding(QEditorInputBindingInterface *b) {
QList<QAction *> actions = m_bindingsActions->actions();
for (QAction *a : actions) {
for (auto &a : actions) {
if (a->data().toString() != id)
a->setChecked(false);
}
@ -1382,7 +1386,7 @@ void QEditor::setInputBinding(QEditorInputBindingInterface *b) {
QList<QAction *> actions = m_bindingsActions->actions();
for (QAction *a : actions) {
for (auto &a : actions) {
if (a)
a->setChecked(a->data().toString() != id);
}
@ -1400,7 +1404,7 @@ void QEditor::updateBindingsMenu() {
aDefaultBinding->setChecked(m_bindings.contains(m_defaultBinding));
for (QAction *a : actions) {
for (auto &a : actions) {
int idx = bindings.indexOf(a->data().toString());
if (idx == -1) {
@ -1410,7 +1414,7 @@ void QEditor::updateBindingsMenu() {
} else {
bindings.removeAt(idx);
for (QEditorInputBindingInterface *b : m_bindings)
for (auto &b : m_bindings)
if (a->data().toString() == b->id())
a->setChecked(true);
}
@ -1684,6 +1688,8 @@ void QEditor::setPlaceHolder(int i) {
viewport()->update();
}
void QEditor::setUndoRedoEnabled(bool b) { m_undoRedoEnabled = b; }
/*!
\brief Move to next placeholder
@ -1835,7 +1841,7 @@ void QEditor::emitCursorPositionChanged() {
\brief Undo the last editing operation, if any on the stack
*/
void QEditor::undo() {
if (m_doc) {
if (m_doc && m_undoRedoEnabled) {
if (m_definition)
m_definition->clearMatches(m_doc);
@ -1852,7 +1858,7 @@ void QEditor::undo() {
\brief Redo the last undone editing operation, if any on the stack
*/
void QEditor::redo() {
if (m_doc) {
if (m_doc && m_undoRedoEnabled) {
if (m_definition)
m_definition->clearMatches(m_doc);
@ -1985,7 +1991,7 @@ void QEditor::indentSelection() {
if (!protectedCursor(m_cursor))
insert(m_cursor, txt);
for (const QDocumentCursor &m : m_mirrors)
for (auto &m : m_mirrors)
if (!protectedCursor(m))
insert(m, txt);
@ -2025,7 +2031,7 @@ void QEditor::unindentSelection() {
if (!protectedCursor(m_cursor))
unindent(m_cursor);
for (const QDocumentCursor &m : m_mirrors)
for (auto &m : m_mirrors)
unindent(m);
m_doc->endMacro();
@ -2064,7 +2070,7 @@ void QEditor::commentSelection() {
if (!protectedCursor(m_cursor))
insert(m_cursor, txt);
for (const QDocumentCursor &m : m_mirrors)
for (auto &m : m_mirrors)
if (!protectedCursor(m))
insert(m, txt);
@ -2110,7 +2116,7 @@ void QEditor::uncommentSelection() {
if (!protectedCursor(m_cursor))
removeFromStart(m_cursor, txt);
for (const QDocumentCursor &m : m_mirrors)
for (auto &m : m_mirrors)
if (!protectedCursor(m))
removeFromStart(m, txt);
@ -2207,7 +2213,7 @@ void QEditor::paintEvent(QPaintEvent *e) {
}
// cursor mirrors :D
for (const QDocumentCursor &m : m_mirrors) {
for (auto &m : m_mirrors) {
if (ctx.blinkingCursor)
ctx.extra << m.handle();
@ -2319,7 +2325,7 @@ bool QEditor::protectedCursor(const QDocumentCursor &c) const {
\internal
*/
void QEditor::keyPressEvent(QKeyEvent *e) {
for (QEditorInputBindingInterface *b : m_bindings)
for (auto &b : m_bindings)
if (b->keyPressEvent(e, this))
return;
@ -2439,7 +2445,7 @@ void QEditor::keyPressEvent(QKeyEvent *e) {
bool pke = isProcessingKeyEvent(e, &offset);
bool prot = protectedCursor(m_cursor);
for (const QDocumentCursor &c : m_mirrors)
for (auto &c : m_mirrors)
prot |= protectedCursor(c);
if (!pke || prot) {
@ -2516,7 +2522,7 @@ void QEditor::keyPressEvent(QKeyEvent *e) {
break;
}
for (QEditorInputBindingInterface *b : m_bindings)
for (auto &b : m_bindings)
b->postKeyPressEvent(e, this);
}
@ -2524,7 +2530,7 @@ void QEditor::keyPressEvent(QKeyEvent *e) {
\internal
*/
void QEditor::inputMethodEvent(QInputMethodEvent *e) {
for (QEditorInputBindingInterface *b : m_bindings)
for (auto &b : m_bindings)
if (b->inputMethodEvent(e, this))
return;
@ -2543,7 +2549,7 @@ void QEditor::inputMethodEvent(QInputMethodEvent *e) {
m_cursor.endEditBlock();
for (QEditorInputBindingInterface *b : m_bindings)
for (auto &b : m_bindings)
b->postInputMethodEvent(e, this);
}
@ -2551,7 +2557,7 @@ void QEditor::inputMethodEvent(QInputMethodEvent *e) {
\internal
*/
void QEditor::mouseMoveEvent(QMouseEvent *e) {
for (QEditorInputBindingInterface *b : m_bindings)
for (auto &b : m_bindings)
if (b->mouseMoveEvent(e, this))
return;
@ -2636,7 +2642,7 @@ void QEditor::mouseMoveEvent(QMouseEvent *e) {
break;
}
for (QEditorInputBindingInterface *b : m_bindings)
for (auto &b : m_bindings)
b->postMouseMoveEvent(e, this);
}
@ -2644,7 +2650,7 @@ void QEditor::mouseMoveEvent(QMouseEvent *e) {
\internal
*/
void QEditor::mousePressEvent(QMouseEvent *e) {
for (QEditorInputBindingInterface *b : m_bindings)
for (auto &b : m_bindings)
if (b->mousePressEvent(e, this))
return;
@ -2809,7 +2815,7 @@ void QEditor::mouseReleaseEvent(QMouseEvent *e) {
if (m_drag.isActive())
m_drag.stop();
for (QEditorInputBindingInterface *b : m_bindings)
for (auto &b : m_bindings)
b->postMouseReleaseEvent(e, this);
}
@ -2817,7 +2823,7 @@ void QEditor::mouseReleaseEvent(QMouseEvent *e) {
\internal
*/
void QEditor::mouseDoubleClickEvent(QMouseEvent *e) {
for (QEditorInputBindingInterface *b : m_bindings)
for (auto &b : m_bindings)
if (b->mouseDoubleClickEvent(e, this))
return;
@ -3945,6 +3951,7 @@ QRect QEditor::selectionRect() const {
if (s.startLine == s.endLine)
return QEditor::cursorRect(m_cursor);
Q_ASSERT(m_doc);
int y = m_doc->y(s.startLine);
QRect r = m_doc->lineRect(s.endLine);
int height = r.y() + r.height() - y;
@ -4155,6 +4162,8 @@ void QEditor::addCursorMirror(const QDocumentCursor &c) {
m_mirrors.last().setAutoUpdated(true);
}
bool QEditor::undoRedoEnabled() const { return m_undoRedoEnabled; }
/*!
\internal
\brief Copy the selection to the clipboard

View File

@ -272,12 +272,14 @@ public slots:
void clearPlaceHolders();
void removePlaceHolder(int i);
void addPlaceHolder(const PlaceHolder &p, bool autoUpdate = true);
void addPlaceHolder(const QEditor::PlaceHolder &p, bool autoUpdate = true);
void nextPlaceHolder();
void previousPlaceHolder();
void setPlaceHolder(int i);
void setUndoRedoEnabled(bool b);
virtual void setFileName(const QString &f);
public:
@ -384,6 +386,8 @@ public:
void clearCursorMirrors();
void addCursorMirror(const QDocumentCursor &c);
bool undoRedoEnabled() const;
protected slots:
void documentWidthChanged(int newWidth);
void documentHeightChanged(int newWidth);
@ -433,6 +437,8 @@ protected:
int m_curPlaceHolder, m_cphOffset;
QList<PlaceHolder> m_placeHolders;
bool m_undoRedoEnabled = true;
int m_state;
bool m_selection;
QRect m_crect, m_margins;

View File

@ -62,7 +62,6 @@ add_subdirectory(3rdparty/QHexView)
add_subdirectory(3rdparty/qcodeedit2)
add_subdirectory(3rdparty/Qt-Advanced-Docking-System)
add_subdirectory(3rdparty/AngelScript/sdk/angelscript/projects/cmake)
add_subdirectory(3rdparty/QConsoleWidget)
add_subdirectory(3rdparty/QJsonModel)
set(ANGEL_SCRIPT_ADDON_ROOT
@ -114,6 +113,12 @@ set(RIBBON_SRC
set(QPATHEDIT_SRC 3rdparty/QPathEdit/qpathedit.cpp
3rdparty/QPathEdit/qpathedit.h)
set(QCONSOLEWIDGET_SRC
3rdparty/QConsoleWidget/QConsoleIODevice.cpp
3rdparty/QConsoleWidget/QConsoleIODevice.h
3rdparty/QConsoleWidget/QConsoleWidget.cpp
3rdparty/QConsoleWidget/QConsoleWidget.h)
set(DIALOG_SRC
src/dialog/framelessmainwindow.h
src/dialog/framelessmainwindow.cpp
@ -225,7 +230,9 @@ set(CLASS_SRC
src/class/ascontextmgr.h
src/class/ascontextmgr.cpp
src/class/qcodenode.cpp
src/class/qcodenode.h)
src/class/qcodenode.h
src/class/langservice.h
src/class/langservice.cpp)
if(WINGHEX_USE_FRAMELESS)
set(WIDGET_FRAME_SRC
@ -399,6 +406,7 @@ set(PROJECT_SOURCES
main.cpp
src/utilities.h
src/dbghelper.h
${QCONSOLEWIDGET_SRC}
${QPATHEDIT_SRC}
${WIDGET_FRAME_SRC}
${RIBBON_SRC}
@ -463,7 +471,6 @@ if(WINGHEX_USE_FRAMELESS)
QCodeEditor2
QJsonModel
angelscript
QConsoleWidget
qt${QT_VERSION_MAJOR}advanceddocking)
else()
target_link_libraries(
@ -480,7 +487,6 @@ else()
QCodeEditor2
QJsonModel
angelscript
QConsoleWidget
qt${QT_VERSION_MAJOR}advanceddocking)
endif()

File diff suppressed because it is too large Load Diff

54
src/class/langservice.cpp Normal file
View File

@ -0,0 +1,54 @@
#include "langservice.h"
#include "class/ascompletion.h"
#include "class/skinmanager.h"
#include "qdocument.h"
#include "qeditor.h"
#include "qformatscheme.h"
#include "qsnippetmanager.h"
LangService &LangService::instance() {
static LangService ins;
return ins;
}
void LangService::init(asIScriptEngine *engine) {
QFormatScheme *format = nullptr;
switch (SkinManager::instance().currentTheme()) {
case SkinManager::Theme::Dark:
format =
new QFormatScheme(QStringLiteral(":/qcodeedit/as_dark.qxf"), this);
break;
case SkinManager::Theme::Light:
format =
new QFormatScheme(QStringLiteral(":/qcodeedit/as_light.qxf"), this);
break;
}
QDocument::setDefaultFormatScheme(format);
m_language = new QLanguageFactory(format, this);
m_language->addDefinitionPath(QStringLiteral(":/qcodeedit"));
m_language->addCompletionEngine(new AsCompletion(engine, this));
m_snippetManager = new QSnippetManager(this);
m_snipbind = new QSnippetBinding(m_snippetManager);
}
LangService::LangService() : QObject(nullptr) {}
LangService::~LangService() { delete m_snipbind; }
QSnippetManager *LangService::snippetManager() const {
return m_snippetManager;
}
QLanguageFactory *LangService::languageFactory() const { return m_language; }
void LangService::applyLanguageSerivce(QEditor *editor) {
Q_ASSERT(editor);
m_language->setLanguage(editor, QStringLiteral("AngelScript"));
editor->addInputBinding(m_snipbind);
}
QSnippetBinding *LangService::snippetBinding() const { return m_snipbind; }

39
src/class/langservice.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef LANGSERVICE_H
#define LANGSERVICE_H
#include "qlanguagefactory.h"
#include "qsnippetbinding.h"
#include "angelscript.h"
#include <QObject>
class LangService : QObject {
Q_OBJECT
public:
static LangService &instance();
void init(asIScriptEngine *engine);
QSnippetBinding *snippetBinding() const;
QLanguageFactory *languageFactory() const;
void applyLanguageSerivce(QEditor *editor);
QSnippetManager *snippetManager() const;
private:
LangService();
~LangService();
private:
QSnippetBinding *m_snipbind = nullptr;
QLanguageFactory *m_language = nullptr;
QSnippetManager *m_snippetManager = nullptr;
Q_DISABLE_COPY_MOVE(LangService)
};
#endif // LANGSERVICE_H

View File

@ -404,7 +404,7 @@ void QAsParser::addClassCompletion(asIScriptEngine *engine) {
pnodes->append(node);
auto clsnode = new QCodeNode;
_headerNodes << clsnode;
_clsNodes << clsnode;
clsnode->setNodeType(QCodeNode::Class);
clsnode->setRole(QCodeNode::Name, cls.name);
for (auto &m : cls.methods) {
@ -468,4 +468,6 @@ QCodeNode *QAsParser::newEnumCodeNode(const EnumInfo &info) {
return enode;
}
QList<QCodeNode *> QAsParser::classNodes() const { return _clsNodes; }
QList<QCodeNode *> QAsParser::codeNodes() const { return _nodes; }

View File

@ -75,6 +75,8 @@ public:
const QList<QCodeNode *> &headerNodes() const;
QList<QCodeNode *> classNodes() const;
private:
void addGlobalFunctionCompletion(asIScriptEngine *engine);
void addEnumCompletion(asIScriptEngine *engine);
@ -89,6 +91,7 @@ private:
asIScriptEngine *_engine;
QScopedPointer<asCScriptCode> m_code;
QList<QCodeNode *> _headerNodes;
QList<QCodeNode *> _clsNodes;
QList<QCodeNode *> _nodes;
};

View File

@ -23,7 +23,7 @@
#include <QShortcut>
ScriptingConsole::ScriptingConsole(QWidget *parent) : QConsoleWidget(parent) {
m_stdoutFmtTitle = this->currentCharFormat();
// m_stdoutFmtTitle = this->currentCharFormat();
m_stdoutFmtWarn = m_stdoutFmtContent =
channelCharFormat(ConsoleChannel::StandardOutput);
@ -152,7 +152,7 @@ void ScriptingConsole::appendCommandPrompt(bool storeOnly) {
if (storeOnly) {
commandPrompt += QStringLiteral("... > ");
} else {
auto cursor = this->textCursor();
auto cursor = this->cursor();
if (!cursor.atBlockStart()) {
commandPrompt = QStringLiteral("\n");
}

View File

@ -18,7 +18,7 @@
#ifndef ScriptingConsole_H
#define ScriptingConsole_H
#include "QConsoleWidget/src/QConsoleWidget.h"
#include "QConsoleWidget/QConsoleWidget.h"
#include "class/scriptconsolemachine.h"
#include <QMutex>

View File

@ -24,7 +24,6 @@
AboutSoftwareDialog::AboutSoftwareDialog(QWidget *parent)
: QWidget(parent), ui(new Ui::AboutSoftwareDialog) {
ui->setupUi(this);
auto data = LanguageManager::instance().data();
ui->tbAbout->setMarkdown(data.about);
ui->tbBaseObj->setMarkdown(data.component);
@ -32,6 +31,7 @@ AboutSoftwareDialog::AboutSoftwareDialog(QWidget *parent)
ui->tbDev->setMarkdown(data.dev);
ui->tbTr->setMarkdown(data.trans);
ui->lblVersion->setText(qApp->applicationVersion());
ui->lblBuildDate->setText(QStringLiteral(__DATE__));
QFile license(QStringLiteral(":/com.wingsummer.winghex/LICENSE"));
auto ret = license.open(QFile::ReadOnly);

View File

@ -15,19 +15,7 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
@ -63,10 +51,7 @@
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>10</number>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_3">
<property name="sizePolicy">
@ -89,6 +74,30 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>BuildDate</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblBuildDate">
<property name="text">
<string notr="true">-</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>

View File

@ -24,6 +24,7 @@
#include "aboutsoftwaredialog.h"
#include "checksumdialog.h"
#include "class/appmanager.h"
#include "class/langservice.h"
#include "class/languagemanager.h"
#include "class/logger.h"
#include "class/qkeysequences.h"
@ -146,6 +147,10 @@ MainWindow::MainWindow(QWidget *parent) : FramelessMainWindow(parent) {
m_scriptDialog->initConsole();
ScriptManager::instance().attach(m_scriptConsole);
auto &langins = LangService::instance();
langins.init(m_scriptConsole->machine()->engine());
langins.applyLanguageSerivce(m_scriptConsole);
// load the model
Q_ASSERT(m_scriptConsole && m_scriptConsole->machine());
m_varshowtable->setModel(m_scriptConsole->consoleMachine()->model());
@ -2870,6 +2875,14 @@ ads::CDockAreaWidget *MainWindow::editorViewArea() const {
void MainWindow::closeEvent(QCloseEvent *event) {
m_isOnClosing = true;
// first checking the scripting dialog
if (!m_scriptDialog->about2Close()) {
event->ignore();
m_isOnClosing = false;
return;
}
// then checking itself
if (!m_views.isEmpty()) {
QStringList unSavedFiles;
QList<EditorView *> need2CloseView;
@ -2918,6 +2931,7 @@ void MainWindow::closeEvent(QCloseEvent *event) {
auto &set = SettingManager::instance();
set.setDockLayout(m_dock->saveState());
m_scriptDialog->saveDockLayout();
set.setRecentFiles(m_recentmanager->saveRecent());
set.save();

View File

@ -20,20 +20,19 @@
#include "QWingRibbon/ribbontabcontent.h"
#include "Qt-Advanced-Docking-System/src/DockAreaWidget.h"
#include "aboutsoftwaredialog.h"
#include "class/ascompletion.h"
#include "class/langservice.h"
#include "class/languagemanager.h"
#include "class/qkeysequences.h"
#include "class/settingmanager.h"
#include "class/skinmanager.h"
#include "class/wingfiledialog.h"
#include "class/wingmessagebox.h"
#include "control/toast.h"
#include "qcodeeditwidget/qeditconfig.h"
#include "qcodeeditwidget/qsnippetedit.h"
#include "qdocumentline.h"
#include "qeditor.h"
#include "qformatscheme.h"
#include "qlinemarksinfocenter.h"
#include "qsnippetmanager.h"
#include <QDesktopServices>
#include <QHeaderView>
@ -79,25 +78,8 @@ ScriptingDialog::ScriptingDialog(QWidget *parent)
buildUpSettingDialog();
QFormatScheme *format = nullptr;
switch (SkinManager::instance().currentTheme()) {
case SkinManager::Theme::Dark:
format =
new QFormatScheme(QStringLiteral(":/qcodeedit/as_dark.qxf"), this);
break;
case SkinManager::Theme::Light:
format =
new QFormatScheme(QStringLiteral(":/qcodeedit/as_light.qxf"), this);
break;
}
QDocument::setDefaultFormatScheme(format);
m_language = new QLanguageFactory(format, this);
m_language->addDefinitionPath(QStringLiteral(":/qcodeedit"));
auto snippet = new QSnippetManager(this);
m_snipbind = new QSnippetBinding(snippet);
QFormatScheme *format = QDocument::defaultFormatScheme();
Q_ASSERT(format);
auto lmic = QLineMarksInfoCenter::instance();
lmic->loadMarkTypes(QCE::fetchDataFile(":/qcodeedit/marks.qxm"));
@ -124,7 +106,7 @@ ScriptingDialog::ScriptingDialog(QWidget *parent)
this->setUpdatesEnabled(true);
}
ScriptingDialog::~ScriptingDialog() { delete m_snipbind; }
ScriptingDialog::~ScriptingDialog() {}
void ScriptingDialog::initConsole() {
Q_ASSERT(m_consoleout);
@ -232,8 +214,55 @@ void ScriptingDialog::initConsole() {
updateRunDebugMode();
});
}
m_language->addCompletionEngine(new AsCompletion(machine->engine(), this));
bool ScriptingDialog::about2Close() {
if (m_views.isEmpty()) {
return true;
}
QStringList unSavedFiles;
QList<ScriptEditor *> need2CloseView;
for (auto &view : m_views) {
if (view->editor()->isContentModified()) {
unSavedFiles << view->fileName();
} else {
need2CloseView << view;
}
}
for (auto &view : need2CloseView) {
emit view->closeRequested();
}
if (unSavedFiles.isEmpty()) {
return true;
}
this->show();
this->raise();
auto ret =
unSavedFiles.isEmpty()
? QMessageBox::No
: WingMessageBox::warning(this, qAppName(), tr("ConfirmScriptSave"),
QMessageBox::Yes | QMessageBox::No |
QMessageBox::Cancel);
if (ret == QMessageBox::Yes) {
for (auto &p : m_views) {
emit p->closeRequested();
}
return m_views.isEmpty();
} else if (ret == QMessageBox::No) {
for (auto &p : m_views) {
p->closeDockWidget(); // force close
}
return true;
}
return false;
}
void ScriptingDialog::saveDockLayout() {
@ -687,6 +716,13 @@ ads::CDockWidget *ScriptingDialog::buildDockWidget(ads::CDockManager *dock,
return dw;
}
QMessageBox::StandardButton ScriptingDialog::saveRequest() {
auto ret = WingMessageBox::warning(this, qAppName(), tr("ConfirmSave"),
QMessageBox::Yes | QMessageBox::No |
QMessageBox::Cancel);
return ret;
}
void ScriptingDialog::registerEditorView(ScriptEditor *editor) {
connect(editor, &ScriptEditor::closeRequested, this, [this] {
auto editor = qobject_cast<ScriptEditor *>(sender());
@ -703,6 +739,23 @@ void ScriptingDialog::registerEditorView(ScriptEditor *editor) {
on_stopscript();
}
if (editor->editor()->isContentModified()) {
auto ret = saveRequest();
if (ret == QMessageBox::Cancel) {
return;
} else if (ret == QMessageBox::Yes) {
if (!editor->save()) {
if (WingMessageBox::critical(this, this->windowTitle(),
tr("ScriptSaveFailedClose"),
QMessageBox::Yes |
QMessageBox::No) ==
QMessageBox::No) {
return;
}
}
}
}
m_views.removeOne(editor);
if (currentEditor() == editor) {
m_curEditor = nullptr;
@ -723,8 +776,7 @@ void ScriptingDialog::registerEditorView(ScriptEditor *editor) {
editor->deleteDockWidget();
});
m_language->setLanguage(editor->editor(), QStringLiteral("AngelScript"));
editor->editor()->addInputBinding(m_snipbind);
LangService::instance().applyLanguageSerivce(editor->editor());
m_views.append(editor);
@ -898,6 +950,10 @@ void ScriptingDialog::buildUpSettingDialog() {
auto edit = new QEditConfig(m_setdialog);
m_setdialog->addPage(edit);
auto snip =
new QSnippetEdit(LangService::instance().snippetManager(), m_setdialog);
m_setdialog->addPage(snip);
m_setdialog->build();
}

View File

@ -32,9 +32,9 @@
#include "model/dbgcallstackmodel.h"
#include "model/dbgvarshowmodel.h"
#include "qlanguagefactory.h"
#include "qsnippetbinding.h"
#include "utilities.h"
#include <QMessageBox>
#include <QShortcut>
#include <QStatusBar>
#include <QTableView>
@ -75,6 +75,8 @@ public:
void initConsole();
bool about2Close();
void saveDockLayout();
private:
@ -112,6 +114,8 @@ private:
QWidget *content,
ToolButtonIndex index = TOOL_VIEWS);
QMessageBox::StandardButton saveRequest();
private:
template <typename Func>
inline QToolButton *
@ -251,8 +255,6 @@ protected:
private:
ads::CDockManager *m_dock = nullptr;
ads::CDockAreaWidget *m_editorViewArea = nullptr;
QLanguageFactory *m_language = nullptr;
QSnippetBinding *m_snipbind = nullptr;
QByteArray _defaultLayout;
QByteArray _savedLayout;

View File

@ -42,8 +42,7 @@
QEditConfig::QEditConfig(QWidget *w)
: WingHex::SettingPage(w), ui(new Ui::QEditConfig()) {
ui->setupUi(this);
reset();
reload();
}
QEditConfig::~QEditConfig() { delete ui; }
@ -104,29 +103,7 @@ void QEditConfig::apply() {
because it directly maps to the effect a "cancel" button would
have on the widget
*/
void QEditConfig::cancel() {
// reload the current config
ui->cbFont->setFont(QDocument::font());
ui->spnFontSize->setValue(QDocument::font().pointSize());
ui->spnTabWidth->setValue(QDocument::tabStop());
QDocument::WhiteSpaceMode ws = QDocument::showSpaces();
ui->chkShowTabsInText->setChecked(ws & QDocument::ShowTabs);
ui->chkShowLeadingWhitespace->setChecked(ws & QDocument::ShowLeading);
ui->chkShowTrailingWhitespace->setChecked(ws & QDocument::ShowTrailing);
QDocument::LineEnding le = QDocument::defaultLineEnding();
ui->chkDetectLE->setChecked(le == QDocument::Conservative);
ui->cbLineEndings->setCurrentIndex(le ? le - 1 : 0);
int flags = QEditor::defaultFlags();
ui->chkReplaceTabs->setChecked(flags & QEditor::ReplaceTabs);
ui->chkAutoRemoveTrailingWhitespace->setChecked(flags &
QEditor::RemoveTrailing);
ui->chkPreserveTrailingIndent->setChecked(flags &
QEditor::PreserveTrailingIndent);
}
void QEditConfig::cancel() { reload(); }
/*!
\brief Restore default values for all subcontrols
@ -151,11 +128,35 @@ void QEditConfig::reset() {
ui->chkDetectLE->setChecked(true);
ui->cbLineEndings->setCurrentIndex(0);
ui->chkReplaceTabs->setChecked(false);
ui->chkReplaceTabs->setChecked(true);
ui->chkAutoRemoveTrailingWhitespace->setChecked(false);
ui->chkPreserveTrailingIndent->setChecked(true);
}
void QEditConfig::reload() {
// reload the current config
ui->cbFont->setFont(QDocument::font());
ui->spnFontSize->setValue(QDocument::font().pointSize());
ui->spnTabWidth->setValue(QDocument::tabStop());
QDocument::WhiteSpaceMode ws = QDocument::showSpaces();
ui->chkShowTabsInText->setChecked(ws & QDocument::ShowTabs);
ui->chkShowLeadingWhitespace->setChecked(ws & QDocument::ShowLeading);
ui->chkShowTrailingWhitespace->setChecked(ws & QDocument::ShowTrailing);
QDocument::LineEnding le = QDocument::defaultLineEnding();
ui->chkDetectLE->setChecked(le == QDocument::Conservative);
ui->cbLineEndings->setCurrentIndex(le ? le - 1 : 0);
int flags = QEditor::defaultFlags();
ui->chkReplaceTabs->setChecked(flags & QEditor::ReplaceTabs);
ui->chkAutoRemoveTrailingWhitespace->setChecked(flags &
QEditor::RemoveTrailing);
ui->chkPreserveTrailingIndent->setChecked(flags &
QEditor::PreserveTrailingIndent);
}
/*!
\brief Fills a settings map from the state of the subcontrols
*/
@ -269,7 +270,6 @@ void QEditConfig::on_spnFontSize_valueChanged(int size) {
ui->lblSampleText->setFont(font);
QDocument::setFont(font);
emit keyChanged("font", font);
}
/*!
@ -280,16 +280,13 @@ void QEditConfig::on_cbFont_currentFontChanged(QFont font) {
ui->lblSampleText->setFont(font);
QDocument::setFont(font);
emit keyChanged("font", font);
}
/*!
\brief Slot used to apply tab width settings
*/
void QEditConfig::on_spnTabWidth_valueChanged(int n) {
QDocument::setTabStop(n);
emit keyChanged("tab_width", n);
}
/*!
@ -300,7 +297,6 @@ void QEditConfig::on_chkReplaceTabs_toggled(bool y) {
foreach (QEditor *e, QEditor::m_editors) {
e->setFlag(QEditor::ReplaceTabs, y);
}
emit keyChanged("replace_tabs", y);
}
/*!
@ -312,8 +308,6 @@ void QEditConfig::on_chkShowTabsInText_toggled(bool y) {
else
QDocument::setShowSpaces(QDocument::showSpaces() &
~QDocument::ShowTabs);
emit keyChanged("show_tabs_in_text", y);
}
/*!
@ -326,8 +320,6 @@ void QEditConfig::on_chkShowLeadingWhitespace_toggled(bool y) {
else
QDocument::setShowSpaces(QDocument::showSpaces() &
~QDocument::ShowLeading);
emit keyChanged("show_leading_whitespace", y);
}
/*!
@ -340,15 +332,12 @@ void QEditConfig::on_chkShowTrailingWhitespace_toggled(bool y) {
else
QDocument::setShowSpaces(QDocument::showSpaces() &
~QDocument::ShowTrailing);
emit keyChanged("show_trailing_whitespace", y);
}
void QEditConfig::on_cbLineEndings_currentIndexChanged(int idx) {
QDocument::LineEnding le = QDocument::LineEnding(idx + 1);
QDocument::setDefaultLineEnding(le);
emit keyChanged("line_endings", (int)le);
}
/*!
@ -362,7 +351,6 @@ void QEditConfig::on_chkDetectLE_toggled(bool y) {
}
QDocument::setDefaultLineEnding(le);
emit keyChanged("line_endings", (int)le);
}
/*!
@ -373,7 +361,6 @@ void QEditConfig::on_chkAutoRemoveTrailingWhitespace_toggled(bool y) {
foreach (QEditor *e, QEditor::m_editors) {
e->setFlag(QEditor::RemoveTrailing, y);
}
emit keyChanged("remove_trailing", y);
}
/*!
@ -384,7 +371,6 @@ void QEditConfig::on_chkPreserveTrailingIndent_toggled(bool y) {
foreach (QEditor *e, QEditor::m_editors) {
e->setFlag(QEditor::PreserveTrailingIndent, y);
}
emit keyChanged("preserve_trailing_indent", y);
}
/*! @} */

View File

@ -25,12 +25,12 @@ public:
virtual void cancel() override;
virtual void reset() override;
private:
void reload();
public slots:
void loadKeys(const QMap<QString, QVariant> &keys);
signals:
void keyChanged(const QString &key, const QVariant &value);
private slots:
void on_spnFontSize_valueChanged(int size);
void on_cbFont_currentFontChanged(QFont font);

View File

@ -34,14 +34,14 @@
*/
QSnippetEdit::QSnippetEdit(QWidget *p)
: QWidget(p), ui(new Ui::QSnippetEdit), m_editedSnippet(-1),
: WingHex::SettingPage(p), ui(new Ui::QSnippetEdit), m_editedSnippet(-1),
m_manager(nullptr) {
ui->setupUi(this);
setEnabled(false);
}
QSnippetEdit::QSnippetEdit(QSnippetManager *mgr, QWidget *p)
: QWidget(p), ui(new Ui::QSnippetEdit), m_editedSnippet(-1),
: WingHex::SettingPage(p), ui(new Ui::QSnippetEdit), m_editedSnippet(-1),
m_manager(nullptr) {
ui->setupUi(this);
setSnippetManager(mgr);
@ -49,6 +49,18 @@ QSnippetEdit::QSnippetEdit(QSnippetManager *mgr, QWidget *p)
QSnippetManager *QSnippetEdit::snippetManager() const { return m_manager; }
QIcon QSnippetEdit::categoryIcon() const { return QIcon(); }
QString QSnippetEdit::name() const { return tr("Snippets"); }
QString QSnippetEdit::id() const { return QStringLiteral("Snippets"); }
void QSnippetEdit::apply() {}
void QSnippetEdit::reset() {}
void QSnippetEdit::cancel() {}
void QSnippetEdit::setSnippetManager(QSnippetManager *mgr) {
if (m_manager) {
disconnect(m_manager, SIGNAL(snippetAdded(QSnippet *)), this,

View File

@ -16,6 +16,7 @@
#ifndef _QSNIPPET_EDIT_H_
#define _QSNIPPET_EDIT_H_
#include "plugin/settingpage.h"
#include "qce-config.h"
/*!
@ -32,7 +33,7 @@ namespace Ui {
class QSnippetEdit;
}
class QCE_EXPORT QSnippetEdit : public QWidget {
class QCE_EXPORT QSnippetEdit : public WingHex::SettingPage {
Q_OBJECT
public:
@ -41,6 +42,18 @@ public:
QSnippetManager *snippetManager() const;
// PageBase interface
public:
QIcon categoryIcon() const;
QString name() const;
QString id() const;
// SettingPage interface
public:
void apply();
void reset();
void cancel();
public slots:
void setSnippetManager(QSnippetManager *mgr);

View File

@ -14,20 +14,6 @@
<string/>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="4" column="0">
<widget class="QToolButton" name="tbCreateSnippet">
<property name="text">
<string>+</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QToolButton" name="tbDeleteSnippet">
<property name="text">
<string>-</string>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QLineEdit" name="leSnippetName">
<property name="sizePolicy">
@ -50,10 +36,10 @@
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
<enum>QFrame::Shape::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
<enum>QFrame::Shadow::Raised</enum>
</property>
</widget>
</item>
@ -112,22 +98,6 @@
</item>
</widget>
</item>
<item row="4" column="3" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="3">
<widget class="QLabel" name="label_5">
<property name="sizePolicy">
@ -144,6 +114,36 @@
</property>
</widget>
</item>
<item row="4" column="3" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="0">
<widget class="QPushButton" name="tbCreateSnippet">
<property name="text">
<string notr="true">+</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QPushButton" name="tbDeleteSnippet">
<property name="text">
<string notr="true">-</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
@ -159,7 +159,6 @@
<tabstop>leSnippetName</tabstop>
<tabstop>leSnippetScope</tabstop>
<tabstop>tbCreateSnippet</tabstop>
<tabstop>tbDeleteSnippet</tabstop>
</tabstops>
<resources/>
<connections/>