QString ActionsWidget::getBlockButtonText() const { auto user = peer()->asUser(); if (!user || (user->id == AuthSession::CurrentUserPeerId())) return QString(); if (user->blockStatus() == UserData::BlockStatus::Unknown) return QString(); if (user->isBlocked()) { if (user->botInfo) { return lang(lng_profile_unblock_bot); } return lang(lng_profile_unblock_user); } else if (user->botInfo) { return lang(lng_profile_block_bot); } return lang(lng_profile_block_user); }
QList<Token> TextModelLavaan::tokenise(QTextBlock &block) { BlockStatus *status = blockStatus(block); Token token; QList<Token> tokens; enum ParseStatus { OutsideToken, InSingleQuotedToken, InDoubleQuotedToken, InUnquotedToken, InFunctionCall, InNumber, InOperator, AComment }; ParseStatus parseState = OutsideToken; int tokenStart = 0; QString text = block.text() + "\n"; for (int i = 0; i < text.length(); i++) { QChar c = text.at(i); switch (parseState) { case OutsideToken: { if (c == ' ' || c == '\t' || c == '\n') { // do nothing } else if (c == '#') { parseState = AComment; tokenStart = i; } else if (c == '\'') { parseState = InSingleQuotedToken; tokenStart = i + 1; } else if (c == '\"') { parseState = InDoubleQuotedToken; tokenStart = i + 1; } else if (c.isDigit()) { parseState = InNumber; tokenStart = i; } else if (c == '~' || c == '=' || c == ':' || c == '>' || c == '<') { parseState = InOperator; tokenStart = i; } else if (c == '+') { token.text = "+"; token.pos = i; token.type = Plus; tokens.append(token); } else if (c == '*') { token.text = "*"; token.pos = i; token.type = Times; tokens.append(token); } else if (c == ',') { token.text = ","; token.pos = i; token.type = Comma; tokens.append(token); } else if (c == ')') { token.text = ")"; token.pos = i; token.type = FunctionClose; tokens.append(token); } else if (c.isLetter()) { parseState = InUnquotedToken; tokenStart = i; } else { token.text = text.at(i); token.pos = i; token.type = UnknownToken; tokens.append(token); status->setError("Unexpected character", i, 1); return tokens; } break; } case InNumber: { if (c == ' ' || c == '\t' || c == '*' || c == '+' || c == '#' || c == '\n' || c == '~' || c == '=' || c == ':' || c == '>' || c == '<' || c == ')' || c == ',') { token.text = text.mid(tokenStart, i - tokenStart); token.pos = tokenStart; bool isNumber; token.text.toDouble(&isNumber); if (isNumber) { token.type = Number; tokens.append(token); } else { token.type = Variable; tokens.append(token); status->setError("Variable names which begin with a number must appear in quotes", tokenStart, i - tokenStart); return tokens; } parseState = OutsideToken; i--; // push back } break; } case InSingleQuotedToken: { if (c == '\'') { token.text = text.mid(tokenStart, i - tokenStart); token.pos = tokenStart; token.type = Variable; tokens.append(token); parseState = OutsideToken; } else if (c == '\n') { token.text = text.mid(tokenStart); token.pos = tokenStart; token.type = Variable; tokens.append(token); status->setError("No closing quote", tokenStart - 1, token.text.length()); } break; } case InDoubleQuotedToken: { if (c == '"') { token.text = text.mid(tokenStart, i - tokenStart); token.pos = tokenStart; token.type = Variable; tokens.append(token); parseState = OutsideToken; } else if (c == '\n') { token.text = text.mid(tokenStart); token.pos = tokenStart; token.type = Variable; tokens.append(token); status->setError("No closing quote", tokenStart - 1, token.text.length()); } break; } case InOperator: { if (c != '~' && c != '=' && c != ':' && c != '>' && c != '<') { token.text = text.mid(tokenStart, i - tokenStart); token.pos = tokenStart; token.type = Operator; tokens.append(token); parseState = OutsideToken; i--; } break; } case InFunctionCall: { if (c == '(') { token.text = text.mid(tokenStart, i - tokenStart + 1); token.pos = tokenStart; token.type = FunctionOpen; tokens.append(token); parseState = OutsideToken; } else if (c != ' ' && c != '\t') { token.text = text.mid(tokenStart, i - tokenStart); token.pos = tokenStart; token.type = FunctionOpen; tokens.append(token); status->setError("function call requires ()", token.pos, token.text.length()); return tokens; } break; } case AComment: { if (c == '\n') { token.text = text.mid(tokenStart, text.length() - tokenStart - 1); token.pos = tokenStart; token.type = Comment; tokens.append(token); } break; } default: { if (c.isLetterOrNumber() == false) { QString tokenText = text.mid(tokenStart, i - tokenStart); if (tokenText == "start" || tokenText == "c" || tokenText == "equal") { parseState = InFunctionCall; i--; } else { token.text = tokenText; token.pos = tokenStart; token.type = Variable; tokens.append(token); parseState = OutsideToken; i--; // push back } } break; } } } /*QString debug; foreach (Token token, tokens) { debug.append(token.text).append(", "); } qDebug() << debug << "\n";*/ return tokens; }
void TextModelLavaan::checkEverything() { bool foundError = false; for (int i = 0; i < blockCount(); i++) { QTextBlock block = findBlockByNumber(i); checkBlock(block); BlockStatus *status = blockStatus(block); if (foundError == false && status->isError()) { setErrorState(true, status->message, i, status->pos, status->length); foundError = true; QTextCursor cursor(block); blockSignals(true); /*QTextCharFormat format; format.setUnderlineStyle(QTextCharFormat::WaveUnderline); format.setUnderlineColor(Qt::red); if (status->length == -1) { if (i != _currentBlock) { if (status->inserted == false) { cursor.movePosition(QTextCursor::StartOfBlock); cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, status->pos); cursor.insertText(" "); cursor.insertText(" ", format); status->inserted = true; } else { cursor.movePosition(QTextCursor::StartOfBlock); cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, status->pos + 1); cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 4); cursor.mergeCharFormat(format); } } } else { cursor.movePosition(QTextCursor::StartOfBlock); cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, status->pos); cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, status->length); cursor.mergeCharFormat(format); }*/ qDebug() << "error " << status->pos << " " << status->length << "\n"; blockSignals(false); } } if ( ! foundError) setErrorState(false); }
void TextModelLavaan::checkBlock(QTextBlock &block) { blockSignals(true); BlockStatus *status = blockStatus(block); /*if (block == _currentBlock && status->isError() && status->inserted) { blockSignals(true); QTextCursor cursor(block); cursor.movePosition(QTextCursor::StartOfBlock); cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor, status->pos); cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, 5); cursor.removeSelectedText(); status->inserted = false; blockSignals(false); }*/ QList<Token> tokens = parse(block); QTextCursor manipCursor(block); manipCursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); manipCursor.setCharFormat(QTextCharFormat()); foreach (const Token &token, tokens) { manipCursor.movePosition(QTextCursor::StartOfBlock); manipCursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, token.pos); manipCursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, token.text.size()); //qDebug() << token.pos << ", " << token.text << token.type << "\n"; QTextCharFormat format; switch (token.type) { case Comment: format.setForeground(QBrush(Qt::darkGreen)); format.setFontItalic(true); break; case Variable: format.setForeground(QBrush(Qt::blue)); break; case Operator: format.setForeground(QBrush(QColor(217, 119, 0))); break; case Number: format.setForeground(Qt::red); break; case FunctionOpen: case FunctionClose: format.setForeground(Qt::darkRed); break; default: format.setForeground(QBrush(Qt::black)); break; } manipCursor.setCharFormat(format); }
QList<Token> TextModelLavaan::parse(QTextBlock &block) { BlockStatus *status = blockStatus(block); status->clearError(); QList<Token> tokens = tokenise(block); if (status->isError()) { qDebug() << "error : " << status->message << "\n"; return tokens; } if (tokens.length() == 0 || tokens.at(0).type == Comment) return tokens; Token &first = tokens[0]; if (first.type != Variable) { status->setError("Expected a variable", first.pos, first.text.length()); return tokens; } else if (tokens.length() == 1) { status->setError("Expected an operator", first.pos + first.text.length(), -1); return tokens; } if (tokens.length() >= 2) { Token &second = tokens[1]; if (second.type == Comment) { status->setError("Expected an operator", first.pos + first.text.length(), -1); return tokens; } else if (second.type == Operator) { if (second.text != "~~" && second.text != "~" && second.text != "=~" && second.text != "==" && second.text != ">" && second.text != "<" && second.text != ":=") { status->setError("Unrecognised operator", second.pos, second.text.length()); return tokens; } else if (tokens.length() == 2) { status->setError("Expected an expression", second.pos + second.text.length(), -1); return tokens; } } else { status->setError("Expected an operator", second.pos, second.text.length()); return tokens; } } int i = 2; checkExpression(tokens, i, status); if (status->isError()) return tokens; while (i < tokens.length()) { Token token = tokens.at(i); if (token.type == Comment) break; if (token.type != Plus) { status->setError("Expected a plus", token.pos, token.text.length()); return tokens; } i++; if (i >= tokens.length()) { status->setError("Expected an expression", token.pos + token.text.length(), -1); return tokens; } checkExpression(tokens, i, status); if (status->isError()) return tokens; } return tokens; }