|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "toonzqt/expressionfield.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "texpression.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tparser.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tconvert.h"
|
|
Toshihiro Shimizu |
890ddd |
#include <qsyntaxhighlighter></qsyntaxhighlighter>
|
|
Toshihiro Shimizu |
890ddd |
#include <qcompleter></qcompleter>
|
|
Toshihiro Shimizu |
890ddd |
#include <qkeyevent></qkeyevent>
|
|
Toshihiro Shimizu |
890ddd |
#include <qabstractitemview></qabstractitemview>
|
|
Toshihiro Shimizu |
890ddd |
#include <qscrollbar></qscrollbar>
|
|
Toshihiro Shimizu |
890ddd |
#include <qstringlistmodel></qstringlistmodel>
|
|
Toshihiro Shimizu |
890ddd |
#include <qstandarditemmodel></qstandarditemmodel>
|
|
Toshihiro Shimizu |
890ddd |
#include <qstandarditem></qstandarditem>
|
|
Toshihiro Shimizu |
890ddd |
#include <qtooltip></qtooltip>
|
|
Toshihiro Shimizu |
890ddd |
#include <qlistview></qlistview>
|
|
Toshihiro Shimizu |
890ddd |
#include <qlabel></qlabel>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
using namespace DVGui;
|
|
Toshihiro Shimizu |
890ddd |
using namespace TSyntax;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class ExpressionField::SyntaxHighlighter : public QSyntaxHighlighter
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
const Grammar *m_grammar;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
bool m_open;
|
|
Toshihiro Shimizu |
890ddd |
SyntaxHighlighter(QTextDocument *parent)
|
|
Toshihiro Shimizu |
890ddd |
: QSyntaxHighlighter(parent), m_grammar(0), m_open(true)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
~SyntaxHighlighter()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void setGrammar(const Grammar *grammar) { m_grammar = grammar; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void highlightBlock(const QString &text)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
Parser parser(m_grammar);
|
|
Toshihiro Shimizu |
890ddd |
std::vector<syntaxtoken> tokens;</syntaxtoken>
|
|
Toshihiro Shimizu |
890ddd |
Parser::SyntaxStatus status = parser.checkSyntax(tokens, text.toStdString());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int nextPos = 0;
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0; i < (int)tokens.size(); i++) {
|
|
Toshihiro Shimizu |
890ddd |
QTextCharFormat fmt;
|
|
Toshihiro Shimizu |
890ddd |
int pos = tokens[i].m_pos;
|
|
Toshihiro Shimizu |
890ddd |
int length = tokens[i].m_length;
|
|
Toshihiro Shimizu |
890ddd |
int type = tokens[i].m_type;
|
|
Toshihiro Shimizu |
890ddd |
nextPos = pos + length;
|
|
Toshihiro Shimizu |
890ddd |
switch (type) {
|
|
Toshihiro Shimizu |
890ddd |
case TSyntax::Unknown:
|
|
Toshihiro Shimizu |
890ddd |
fmt.setForeground(Qt::black);
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
case TSyntax::Number:
|
|
Toshihiro Shimizu |
890ddd |
fmt.setForeground(QColor(0x50, 0x7d, 0x0));
|
|
Toshihiro Shimizu |
890ddd |
break; // number
|
|
Toshihiro Shimizu |
890ddd |
case TSyntax::Constant:
|
|
Toshihiro Shimizu |
890ddd |
fmt.setForeground(QColor(0x50, 0x7d, 0x0));
|
|
Toshihiro Shimizu |
890ddd |
break; // constant
|
|
Toshihiro Shimizu |
890ddd |
case TSyntax::Variable:
|
|
Toshihiro Shimizu |
890ddd |
fmt.setForeground(QColor(0x0, 0x88, 0xc8));
|
|
Toshihiro Shimizu |
890ddd |
break; // var
|
|
Toshihiro Shimizu |
890ddd |
case TSyntax::Operator:
|
|
Toshihiro Shimizu |
890ddd |
fmt.setForeground(QColor(50, 0, 255));
|
|
Toshihiro Shimizu |
890ddd |
break; // infix
|
|
Toshihiro Shimizu |
890ddd |
case TSyntax::Parenthesis:
|
|
Toshihiro Shimizu |
890ddd |
fmt.setForeground(QColor(50, 50, 255));
|
|
Toshihiro Shimizu |
890ddd |
break; // braket
|
|
Toshihiro Shimizu |
890ddd |
case TSyntax::Function:
|
|
Toshihiro Shimizu |
890ddd |
fmt.setForeground(QColor(0x0, 0x50, 0x7d));
|
|
Toshihiro Shimizu |
890ddd |
break; // fname
|
|
Toshihiro Shimizu |
890ddd |
case TSyntax::Comma:
|
|
Toshihiro Shimizu |
890ddd |
fmt.setForeground(QColor(50, 20, 255));
|
|
Toshihiro Shimizu |
890ddd |
break; // f ;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
case TSyntax::UnexpectedToken:
|
|
Toshihiro Shimizu |
890ddd |
fmt.setForeground(QColor(0xdc, 0x0, 0x0));
|
|
Toshihiro Shimizu |
890ddd |
break; // expression not found
|
|
Toshihiro Shimizu |
890ddd |
case TSyntax::Eos:
|
|
Toshihiro Shimizu |
890ddd |
fmt.setForeground(QColor(255, 127, 0));
|
|
Toshihiro Shimizu |
890ddd |
break; // EOS
|
|
Toshihiro Shimizu |
890ddd |
case TSyntax::Mismatch:
|
|
Toshihiro Shimizu |
890ddd |
fmt.setForeground(QColor(255, 0, 0));
|
|
Toshihiro Shimizu |
890ddd |
break; // token mismatch
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
default:
|
|
Toshihiro Shimizu |
890ddd |
fmt.setForeground(QColor(127, 127, 255));
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
if (type == 4)
|
|
Toshihiro Shimizu |
890ddd |
fmt.setToolTip("Infix");
|
|
Toshihiro Shimizu |
890ddd |
if (length == 0)
|
|
Toshihiro Shimizu |
890ddd |
length = 1;
|
|
Toshihiro Shimizu |
890ddd |
setFormat(pos, length, fmt);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class MyListView : public QListView
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
QLabel *m_tooltip;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
MyListView() : QListView()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
setObjectName("SuggestionPopup");
|
|
Toshihiro Shimizu |
890ddd |
setStyleSheet("#SuggestionPopup {background-color:#FFFFFF; border:1px solid black;}");
|
|
Toshihiro Shimizu |
890ddd |
setWindowFlags(Qt::Popup);
|
|
Toshihiro Shimizu |
890ddd |
setMouseTracking(true);
|
|
Toshihiro Shimizu |
890ddd |
m_tooltip = new QLabel(0, Qt::ToolTip);
|
|
Toshihiro Shimizu |
890ddd |
//Stesso stile del popuop che lo contiene.
|
|
Toshihiro Shimizu |
890ddd |
m_tooltip->hide();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_tooltip->setObjectName("helpTooltip");
|
|
Toshihiro Shimizu |
890ddd |
m_tooltip->setAlignment(Qt::AlignLeft);
|
|
Toshihiro Shimizu |
890ddd |
m_tooltip->setIndent(1);
|
|
Toshihiro Shimizu |
890ddd |
m_tooltip->setWordWrap(false);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
void showEvent(QShowEvent *)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
showToolTip(currentIndex());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
void hideEvent(QHideEvent *)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_tooltip->hide();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
void currentChanged(const QModelIndex ¤t, const QModelIndex &previous)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
showToolTip(current);
|
|
Toshihiro Shimizu |
890ddd |
QListView::currentChanged(current, previous);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
void showToolTip(const QModelIndex &index)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!index.isValid()) {
|
|
Toshihiro Shimizu |
890ddd |
m_tooltip->hide();
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
QVariant data = model()->data(index, Qt::ToolTipRole);
|
|
Toshihiro Shimizu |
890ddd |
if (!data.isValid()) {
|
|
Toshihiro Shimizu |
890ddd |
m_tooltip->hide();
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
QRect rect = visualRect(index);
|
|
Toshihiro Shimizu |
890ddd |
m_tooltip->setText(data.toString());
|
|
Toshihiro Shimizu |
890ddd |
QPoint pos = viewport()->mapToGlobal(QPoint(-m_tooltip->sizeHint().width(), rect.top()));
|
|
Toshihiro Shimizu |
890ddd |
m_tooltip->setGeometry(QRect(pos, m_tooltip->sizeHint()));
|
|
Toshihiro Shimizu |
890ddd |
m_tooltip->show();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
protected:
|
|
Toshihiro Shimizu |
890ddd |
void resizeEvent(QResizeEvent *e)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
QListView::resizeEvent(e);
|
|
Toshihiro Shimizu |
890ddd |
if (m_tooltip->isVisible())
|
|
Toshihiro Shimizu |
890ddd |
showToolTip(currentIndex());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ExpressionField::ExpressionField(QWidget *parent)
|
|
Toshihiro Shimizu |
890ddd |
: QTextEdit(parent), m_editing(false), m_grammar(0), m_syntaxHighlighter(0), m_completerPopup(0), m_completerStartPos(0)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
setFrameStyle(QFrame::StyledPanel);
|
|
Toshihiro Shimizu |
890ddd |
setObjectName("ExpressionField");
|
|
Toshihiro Shimizu |
890ddd |
setLineWrapMode(NoWrap);
|
|
Toshihiro Shimizu |
890ddd |
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
Toshihiro Shimizu |
890ddd |
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
Toshihiro Shimizu |
890ddd |
setTabChangesFocus(true);
|
|
Toshihiro Shimizu |
890ddd |
// setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed));
|
|
Toshihiro Shimizu |
890ddd |
connect(this, SIGNAL(textChanged()), this, SLOT(onTextChanged()));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef MACOSX
|
|
Toshihiro Shimizu |
890ddd |
setFixedHeight(23);
|
|
Toshihiro Shimizu |
890ddd |
#else
|
|
Toshihiro Shimizu |
890ddd |
setFixedHeight(20); // +40);
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_completerPopup = new MyListView();
|
|
Toshihiro Shimizu |
890ddd |
QStandardItemModel *model = new QStandardItemModel();
|
|
Toshihiro Shimizu |
890ddd |
m_completerPopup->setModel(model);
|
|
Toshihiro Shimizu |
890ddd |
m_completerPopup->setFocusPolicy(Qt::NoFocus);
|
|
Toshihiro Shimizu |
890ddd |
m_completerPopup->setFocusProxy(this);
|
|
Toshihiro Shimizu |
890ddd |
m_completerPopup->installEventFilter(this);
|
|
Toshihiro Shimizu |
890ddd |
connect(
|
|
Toshihiro Shimizu |
890ddd |
m_completerPopup, SIGNAL(clicked(const QModelIndex &)),
|
|
Toshihiro Shimizu |
890ddd |
this, SLOT(insertCompletion(const QModelIndex &)));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_syntaxHighlighter = new SyntaxHighlighter(document());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
ExpressionField::~ExpressionField()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
delete m_syntaxHighlighter;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void ExpressionField::showEvent(QShowEvent *e)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
QTextEdit::showEvent(e);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void ExpressionField::hideEvent(QHideEvent *e)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
QTextEdit::hideEvent(e);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void ExpressionField::setExpression(string expression)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
setPlainText(QString::fromStdString(expression));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
string ExpressionField::getExpression() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return toPlainText().toStdString();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool ExpressionField::event(QEvent *e)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (e->type() == QEvent::ToolTip) {
|
|
Toshihiro Shimizu |
890ddd |
QHelpEvent *helpEvent = static_cast<qhelpevent *="">(e);</qhelpevent>
|
|
Toshihiro Shimizu |
890ddd |
// openCompletionPopup();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} else if (e->type() == QEvent::ShortcutOverride) {
|
|
Toshihiro Shimizu |
890ddd |
e->accept();
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
//else
|
|
Toshihiro Shimizu |
890ddd |
return QTextEdit::event(e);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void ExpressionField::keyPressEvent(QKeyEvent *e)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// setStyleSheet("background-color: cyan");
|
|
Toshihiro Shimizu |
890ddd |
if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
|
|
Toshihiro Shimizu |
890ddd |
m_editing = false;
|
|
Toshihiro Shimizu |
890ddd |
emit expressionChanged();
|
|
Toshihiro Shimizu |
890ddd |
} else if (e->key() == Qt::Key_F10) {
|
|
Toshihiro Shimizu |
890ddd |
setAutoFillBackground(true);
|
|
Toshihiro Shimizu |
890ddd |
QPalette p = palette();
|
|
Toshihiro Shimizu |
890ddd |
p.setColor(QPalette::Base, Qt::cyan);
|
|
Toshihiro Shimizu |
890ddd |
p.setColor(QPalette::Background, Qt::cyan);
|
|
Toshihiro Shimizu |
890ddd |
setPalette(p);
|
|
Toshihiro Shimizu |
890ddd |
update();
|
|
Toshihiro Shimizu |
890ddd |
setStyleSheet("#ExpressionField {background-color:cyan;}");
|
|
Toshihiro Shimizu |
890ddd |
} else if (e->key() == Qt::Key_F11) {
|
|
Toshihiro Shimizu |
890ddd |
m_completerPopup->installEventFilter(this);
|
|
Toshihiro Shimizu |
890ddd |
QRect cr = cursorRect();
|
|
Toshihiro Shimizu |
890ddd |
QSize size(100, 200);
|
|
Toshihiro Shimizu |
890ddd |
QPoint pos = mapToGlobal(QPoint(cr.left(), cr.top() - size.height()));
|
|
Toshihiro Shimizu |
890ddd |
m_completerPopup->setGeometry(QRect(pos, size));
|
|
Toshihiro Shimizu |
890ddd |
m_completerPopup->show();
|
|
Toshihiro Shimizu |
890ddd |
QTextEdit::keyPressEvent(e);
|
|
Toshihiro Shimizu |
890ddd |
} else {
|
|
Toshihiro Shimizu |
890ddd |
QTextEdit::keyPressEvent(e);
|
|
Toshihiro Shimizu |
890ddd |
if (m_completerPopup->isVisible()) {
|
|
Toshihiro Shimizu |
890ddd |
updateCompleterPopup();
|
|
Toshihiro Shimizu |
890ddd |
} else if (Qt::Key_A <= e->key() && e->key() <= Qt::Key_Z || string("+&|!*/=?,:-").find(e->key()) != string::npos) {
|
|
Toshihiro Shimizu |
890ddd |
openCompleterPopup();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
setFocus();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool ExpressionField::eventFilter(QObject *obj, QEvent *e)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (e->type() == QEvent::KeyPress) {
|
|
Toshihiro Shimizu |
890ddd |
QKeyEvent *keyEvent = static_cast<qkeyevent *="">(e);</qkeyevent>
|
|
Toshihiro Shimizu |
890ddd |
switch (keyEvent->key()) {
|
|
Toshihiro Shimizu |
890ddd |
case Qt::Key_Return:
|
|
Toshihiro Shimizu |
890ddd |
case Qt::Key_Enter:
|
|
Toshihiro Shimizu |
890ddd |
insertCompletion(m_completerPopup->currentIndex());
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
case Qt::Key_Left:
|
|
Toshihiro Shimizu |
890ddd |
case Qt::Key_Right:
|
|
Toshihiro Shimizu |
890ddd |
event(keyEvent);
|
|
Toshihiro Shimizu |
890ddd |
m_completerPopup->hide();
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
case Qt::Key_Escape:
|
|
Toshihiro Shimizu |
890ddd |
m_completerPopup->hide();
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
case Qt::Key_Down:
|
|
Toshihiro Shimizu |
890ddd |
case Qt::Key_Up:
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
default:
|
|
Toshihiro Shimizu |
890ddd |
event(e);
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
} else if (e->type() == QEvent::MouseButtonPress) {
|
|
Toshihiro Shimizu |
890ddd |
m_completerPopup->hide();
|
|
Toshihiro Shimizu |
890ddd |
event(e);
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
} else if (e->type() == QEvent::ShortcutOverride) {
|
|
Toshihiro Shimizu |
890ddd |
e->accept();
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
return QObject::eventFilter(obj, e);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void ExpressionField::onTextChanged()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (!m_editing) {
|
|
Toshihiro Shimizu |
890ddd |
m_editing = true;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// setStyleSheet("background: rgb(250,200,200)");
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void ExpressionField::focusInEvent(QFocusEvent *e)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_syntaxHighlighter->m_open = true;
|
|
Toshihiro Shimizu |
890ddd |
m_syntaxHighlighter->rehighlight();
|
|
Toshihiro Shimizu |
890ddd |
QTextEdit::focusInEvent(e);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void ExpressionField::focusOutEvent(QFocusEvent *e)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_syntaxHighlighter->m_open = false;
|
|
Toshihiro Shimizu |
890ddd |
m_syntaxHighlighter->rehighlight();
|
|
Toshihiro Shimizu |
890ddd |
QTextEdit::focusOutEvent(e);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void ExpressionField::onCursorPositionChanged()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void ExpressionField::openCompleterPopup()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int n = computeSuggestions();
|
|
Toshihiro Shimizu |
890ddd |
if (n < 2)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
if (updateCompleterPopup())
|
|
Toshihiro Shimizu |
890ddd |
m_completerPopup->show();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool ExpressionField::updateCompleterPopup()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int start = m_completerStartPos;
|
|
Toshihiro Shimizu |
890ddd |
int pos = textCursor().position();
|
|
Toshihiro Shimizu |
890ddd |
string text = getExpression();
|
|
Toshihiro Shimizu |
890ddd |
if (m_suggestions.empty() || start < 0 || start > pos || pos > (int)text.length()) {
|
|
Toshihiro Shimizu |
890ddd |
if (m_completerPopup->isVisible())
|
|
Toshihiro Shimizu |
890ddd |
m_completerPopup->hide();
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QStandardItemModel *model = new QStandardItemModel();
|
|
Toshihiro Shimizu |
890ddd |
string prefix = toLower(text.substr(start, pos - start));
|
|
Toshihiro Shimizu |
890ddd |
int prefixLength = prefix.length();
|
|
Toshihiro Shimizu |
890ddd |
int count = 0;
|
|
Toshihiro Shimizu |
890ddd |
for (int i = 0; i < (int)m_suggestions.size(); i++) {
|
|
Toshihiro Shimizu |
890ddd |
string item = m_suggestions[i].first;
|
|
Toshihiro Shimizu |
890ddd |
if ((int)item.length() >= prefixLength && toLower(item.substr(0, prefixLength)) == prefix) {
|
|
Toshihiro Shimizu |
890ddd |
QStandardItem *item = new QStandardItem();
|
|
Toshihiro Shimizu |
890ddd |
item->setData(QString::fromStdString(m_suggestions[i].first), Qt::EditRole);
|
|
Toshihiro Shimizu |
890ddd |
if (m_suggestions[i].second != "")
|
|
Toshihiro Shimizu |
890ddd |
item->setData(QString::fromStdString(m_suggestions[i].second), Qt::ToolTipRole);
|
|
Toshihiro Shimizu |
890ddd |
model->appendRow(item);
|
|
Toshihiro Shimizu |
890ddd |
count++;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
if (count == 0) {
|
|
Toshihiro Shimizu |
890ddd |
if (m_completerPopup->isVisible())
|
|
Toshihiro Shimizu |
890ddd |
m_completerPopup->hide();
|
|
Toshihiro Shimizu |
890ddd |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
m_completerPopup->setModel(model);
|
|
Toshihiro Shimizu |
890ddd |
m_completerPopup->setCurrentIndex(model->index(0, 0));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QTextCursor cursor(textCursor());
|
|
Toshihiro Shimizu |
890ddd |
cursor.setPosition(m_completerStartPos);
|
|
Toshihiro Shimizu |
890ddd |
QRect cr = cursorRect(cursor);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int w = m_completerPopup->sizeHintForColumn(0) + m_completerPopup->verticalScrollBar()->sizeHint().width() + 5;
|
|
Toshihiro Shimizu |
890ddd |
int h = (m_completerPopup->sizeHintForRow(0) * qMin(7, model->rowCount()) + 3) + 3;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QSize size(w, h);
|
|
Toshihiro Shimizu |
890ddd |
QPoint popupPos = mapToGlobal(QPoint(cr.left(), cr.bottom() + 3));
|
|
Toshihiro Shimizu |
890ddd |
m_completerPopup->setGeometry(QRect(popupPos, size));
|
|
Toshihiro Shimizu |
890ddd |
return true;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int ExpressionField::computeSuggestions()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_completerStartPos = -1;
|
|
Toshihiro Shimizu |
890ddd |
m_suggestions.clear();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
string text = getExpression();
|
|
Toshihiro Shimizu |
890ddd |
int pos = textCursor().position();
|
|
Toshihiro Shimizu |
890ddd |
int start = pos;
|
|
Toshihiro Shimizu |
890ddd |
if (start > 0) {
|
|
Toshihiro Shimizu |
890ddd |
start--;
|
|
Toshihiro Shimizu |
890ddd |
while (start > 0) {
|
|
Toshihiro Shimizu |
890ddd |
char c = text[start - 1];
|
|
Toshihiro Shimizu |
890ddd |
if (isascii(c) && isalpha(c) || c == '_' || c == '.' && (start - 2 < 0 || isascii(text[start - 2]) && isalpha(text[start - 2]))) {
|
|
Toshihiro Shimizu |
890ddd |
} else
|
|
Toshihiro Shimizu |
890ddd |
break;
|
|
Toshihiro Shimizu |
890ddd |
start--;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
if (start >= (int)text.length())
|
|
Toshihiro Shimizu |
890ddd |
return 0;
|
|
Toshihiro Shimizu |
890ddd |
m_completerStartPos = start;
|
|
Toshihiro Shimizu |
890ddd |
text = text.substr(0, start);
|
|
Toshihiro Shimizu |
890ddd |
TSyntax::Parser parser(m_grammar);
|
|
Toshihiro Shimizu |
890ddd |
parser.getSuggestions(m_suggestions, text);
|
|
Toshihiro Shimizu |
890ddd |
return (int)m_suggestions.size();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void ExpressionField::insertCompletion()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (!m_completerPopup->isVisible())
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
QModelIndex index = m_completerPopup->currentIndex();
|
|
Toshihiro Shimizu |
890ddd |
if (!index.isValid())
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
QString item = m_completerPopup->model()->data(index, Qt::EditRole).toString();
|
|
Toshihiro Shimizu |
890ddd |
QTextCursor tc = textCursor();
|
|
Toshihiro Shimizu |
890ddd |
int pos = tc.position();
|
|
Toshihiro Shimizu |
890ddd |
// tc.movePosition(m_completionStartPos, QTextCursor::KeepAnchor);
|
|
Toshihiro Shimizu |
890ddd |
tc.insertText(item);
|
|
Toshihiro Shimizu |
890ddd |
m_completerPopup->hide();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void ExpressionField::insertCompletion(const QModelIndex &index)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
if (index.isValid()) {
|
|
Toshihiro Shimizu |
890ddd |
QString item = m_completerPopup->model()->data(index, Qt::EditRole).toString();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
QTextCursor tc = textCursor();
|
|
Toshihiro Shimizu |
890ddd |
int pos = tc.position();
|
|
Toshihiro Shimizu |
890ddd |
if (pos - m_completerStartPos >= 1)
|
|
Toshihiro Shimizu |
890ddd |
tc.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor, pos - m_completerStartPos);
|
|
Toshihiro Shimizu |
890ddd |
tc.insertText(item);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
m_completerPopup->hide();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void ExpressionField::setGrammar(const Grammar *grammar)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_grammar = grammar;
|
|
Toshihiro Shimizu |
890ddd |
m_syntaxHighlighter->setGrammar(grammar);
|
|
Toshihiro Shimizu |
890ddd |
};
|