127 lines
5.3 KiB
C++
127 lines
5.3 KiB
C++
#include "ElaPlainTextEdit.h"
|
|
|
|
#include <QClipboard>
|
|
#include <QGuiApplication>
|
|
#include <QMimeData>
|
|
#include <QPainter>
|
|
#include <QPropertyAnimation>
|
|
|
|
#include "ElaEventBus.h"
|
|
#include "ElaMenu.h"
|
|
#include "ElaPlainTextEditPrivate.h"
|
|
#include "ElaPlainTextEditStyle.h"
|
|
#include "ElaScrollBar.h"
|
|
#include "ElaTheme.h"
|
|
ElaPlainTextEdit::ElaPlainTextEdit(QWidget *parent) : QPlainTextEdit(parent), d_ptr(new ElaPlainTextEditPrivate()) {
|
|
Q_D(ElaPlainTextEdit);
|
|
d->q_ptr = this;
|
|
setObjectName("ElaPlainTextEdit");
|
|
setStyleSheet("#ElaPlainTextEdit{background-color:transparent;}");
|
|
setHorizontalScrollBar(new ElaScrollBar(this));
|
|
setVerticalScrollBar(new ElaScrollBar(this));
|
|
setMouseTracking(true);
|
|
// 事件总线
|
|
d->_focusEvent = new ElaEvent("WMWindowClicked", "onWMWindowClickedEvent", d);
|
|
d->_focusEvent->registerAndInit();
|
|
|
|
d->_style = new ElaPlainTextEditStyle(style());
|
|
setStyle(d->_style);
|
|
d->onThemeChanged(eTheme->getThemeMode());
|
|
connect(eTheme, &ElaTheme::themeModeChanged, d, &ElaPlainTextEditPrivate::onThemeChanged);
|
|
}
|
|
|
|
ElaPlainTextEdit::ElaPlainTextEdit(const QString &text, QWidget *parent) : ElaPlainTextEdit(parent) { setPlainText(text); }
|
|
|
|
ElaPlainTextEdit::~ElaPlainTextEdit() {
|
|
Q_D(ElaPlainTextEdit);
|
|
delete d->_style;
|
|
}
|
|
|
|
void ElaPlainTextEdit::focusInEvent(QFocusEvent *event) {
|
|
Q_D(ElaPlainTextEdit);
|
|
if (event->reason() == Qt::MouseFocusReason) {
|
|
QPropertyAnimation *markAnimation = new QPropertyAnimation(d->_style, "pExpandMarkWidth");
|
|
connect(markAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant &value) { update(); });
|
|
markAnimation->setDuration(300);
|
|
markAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
|
markAnimation->setStartValue(d->_style->getExpandMarkWidth());
|
|
markAnimation->setEndValue(width() / 2 - 3);
|
|
markAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
|
}
|
|
QPlainTextEdit::focusInEvent(event);
|
|
}
|
|
|
|
void ElaPlainTextEdit::focusOutEvent(QFocusEvent *event) {
|
|
Q_D(ElaPlainTextEdit);
|
|
if (event->reason() != Qt::PopupFocusReason) {
|
|
QPropertyAnimation *markAnimation = new QPropertyAnimation(d->_style, "pExpandMarkWidth");
|
|
connect(markAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant &value) { update(); });
|
|
markAnimation->setDuration(300);
|
|
markAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
|
markAnimation->setStartValue(d->_style->getExpandMarkWidth());
|
|
markAnimation->setEndValue(0);
|
|
markAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
|
}
|
|
QPlainTextEdit::focusOutEvent(event);
|
|
}
|
|
|
|
void ElaPlainTextEdit::contextMenuEvent(QContextMenuEvent *event) {
|
|
ElaMenu *menu = new ElaMenu(this);
|
|
menu->setMenuItemHeight(27);
|
|
menu->setAttribute(Qt::WA_DeleteOnClose);
|
|
QAction *action = nullptr;
|
|
if (!isReadOnly()) {
|
|
action = menu->addElaIconAction(ElaIconType::ArrowRotateLeft, "撤销", QKeySequence::Undo);
|
|
action->setEnabled(isUndoRedoEnabled() ? document()->isUndoAvailable() : false);
|
|
connect(action, &QAction::triggered, this, &ElaPlainTextEdit::undo);
|
|
|
|
action = menu->addElaIconAction(ElaIconType::ArrowRotateRight, "恢复", QKeySequence::Redo);
|
|
action->setEnabled(isUndoRedoEnabled() ? document()->isRedoAvailable() : false);
|
|
connect(action, &QAction::triggered, this, &ElaPlainTextEdit::redo);
|
|
menu->addSeparator();
|
|
}
|
|
#ifndef QT_NO_CLIPBOARD
|
|
if (!isReadOnly()) {
|
|
action = menu->addElaIconAction(ElaIconType::KnifeKitchen, "剪切", QKeySequence::Cut);
|
|
action->setEnabled(!isReadOnly() && !textCursor().selectedText().isEmpty());
|
|
connect(action, &QAction::triggered, this, &ElaPlainTextEdit::cut);
|
|
}
|
|
|
|
action = menu->addElaIconAction(ElaIconType::Copy, "复制", QKeySequence::Copy);
|
|
action->setEnabled(!textCursor().selectedText().isEmpty());
|
|
connect(action, &QAction::triggered, this, &ElaPlainTextEdit::copy);
|
|
|
|
if (!isReadOnly()) {
|
|
action = menu->addElaIconAction(ElaIconType::Paste, "粘贴", QKeySequence::Paste);
|
|
action->setEnabled(!isReadOnly() && !QGuiApplication::clipboard()->text().isEmpty());
|
|
connect(action, &QAction::triggered, this, &ElaPlainTextEdit::paste);
|
|
}
|
|
#endif
|
|
if (!isReadOnly()) {
|
|
action = menu->addElaIconAction(ElaIconType::DeleteLeft, "删除");
|
|
action->setEnabled(!isReadOnly() && !toPlainText().isEmpty() && !textCursor().selectedText().isEmpty());
|
|
connect(action, &QAction::triggered, this, [=](bool checked) {
|
|
if (!textCursor().selectedText().isEmpty()) {
|
|
textCursor().deleteChar();
|
|
}
|
|
});
|
|
}
|
|
if (!menu->isEmpty()) {
|
|
menu->addSeparator();
|
|
}
|
|
action = menu->addAction("全选");
|
|
action->setShortcut(QKeySequence::SelectAll);
|
|
action->setEnabled(!toPlainText().isEmpty() && !(textCursor().selectedText() == toPlainText()));
|
|
connect(action, &QAction::triggered, this, &ElaPlainTextEdit::selectAll);
|
|
menu->popup(event->globalPos());
|
|
this->setFocus();
|
|
}
|
|
|
|
void ElaPlainTextEdit::paintEvent(QPaintEvent *event) {
|
|
Q_D(ElaPlainTextEdit);
|
|
if (palette().color(QPalette::Text) != ElaThemeColor(d->_themeMode, BasicText)) {
|
|
d->onThemeChanged(d->_themeMode);
|
|
}
|
|
QPlainTextEdit::paintEvent(event);
|
|
}
|