#include "qt.h" #include #include #include #include #include #include #if (defined Q_OS_UNIX) && !(defined NO_USB) #include "usb/usb.h" #endif #ifdef PLUGIN #include #else #include #endif Q_DECLARE_METATYPE (RegularExpression*) Q_DECLARE_METATYPE (TextBlock*) Q_DECLARE_METATYPE (TextCharFormat*) Q_DECLARE_METATYPE (TextCursor*) Q_DECLARE_METATYPE (SyntaxHighlighter*) Q_DECLARE_METATYPE (QTextDocument*) QObject* ini() { static QObject* qt = nullptr; if (qt == nullptr) { qt = new QT; #ifdef PLUGIN ini_lisp(); // see 'ecl_fun_plugin.h' #endif } return qt; } SyntaxHighlighter::SyntaxHighlighter(QTextDocument* doc) : QSyntaxHighlighter(doc) {} void SyntaxHighlighter::highlightBlock(const QString& text) { // override ecl_fun("editor:highlight-block", VAR(SyntaxHighlighter*, this), text); } // new QVariant QT::makeObject(const QVariant& vName, const QVariant& vArg) { QString name(vName.toString()); QVariant vObject; if (name == "QTextCharFormat") { vObject = VAR_NEW(TextCharFormat); } else if (name == "QSyntaxHighlighter") { auto doc = VAL(vArg, QTextDocument*); if (doc != nullptr) { vObject = VAR_NEW_1(SyntaxHighlighter, doc); } } else if (name == "QRegularExpression") { vObject = VAR_NEW(RegularExpression); } return vObject; } // connect QVariant QT::connectDocumentChanged(const QVariant& vDocument, const QVariant& vWhich) { auto doc = VAL(vDocument, QTextDocument*); if (doc != nullptr) { QString which = vWhich.toString(); if (which == "edit") { connect(doc, &QTextDocument::blockCountChanged, [](int count) { ecl_fun("editor:edit-line-count-changed", count); }); connect(doc, &QTextDocument::contentsChanged, []() { ecl_fun("editor:edit-contents-changed"); }); } else if (which == "command") { connect(doc, &QTextDocument::blockCountChanged, [](int count) { ecl_fun("editor:command-line-count-changed", count); }); connect(doc, &QTextDocument::contentsChanged, []() { ecl_fun("editor:command-contents-changed"); }); } connect(doc, &QTextDocument::cursorPositionChanged, [](const QTextCursor& cursor) { TextCursor cursor2(cursor); ecl_fun("editor:cursor-position-changed", VAR(TextCursor*, &cursor2)); }); return true; } return false; } QVariant QT::connectKeyPressed() { #ifdef Q_OS_IOS GuiApplication* sender = static_cast(qGuiApp); connect(sender, &GuiApplication::keyPressed, [](const QString& key, const QString& objectName) { ecl_fun("editor:key-pressed", key, objectName); }); #endif return QVariant(); } // methods // // pointers stored in a QVariant are type checked (if QObject derived) QVariant QT::block2(const QVariant& vCursor) { auto cursor = VAL(vCursor, TextCursor*); if (cursor != nullptr) { TextBlock* tmp = new TextBlock(cursor->block()); DELETE_LATER(tmp); return VAR(TextBlock*, tmp); } return QVariant(); } QVariant QT::blockNumber(const QVariant& vBlock) { auto block = VAL(vBlock, TextBlock*); if (block != nullptr) { return block->blockNumber(); } return QVariant(); } QVariant QT::characterAt(const QVariant& vDocument, const QVariant& vPos) { auto document = VAL(vDocument, QTextDocument*); if (document != nullptr) { return VAR(QChar, document->characterAt(vPos.toInt())); } return QVariant(); } QVariant QT::clearUndoRedoStacks(const QVariant& vDocument) { auto document = VAL(vDocument, QTextDocument*); if (document != nullptr) { document->clearUndoRedoStacks(); } return QVariant(); } QVariant QT::currentBlockState(const QVariant& vHighlighter) { auto highlighter = VAL(vHighlighter, SyntaxHighlighter*); if (highlighter != nullptr) { return highlighter->currentBlockState(); } return QVariant(); } QVariant QT::exactMatch(const QVariant& vRegExp, const QVariant& vText) { auto regExp = VAL(vRegExp, RegularExpression*); if (regExp != nullptr) { QString text = vText.toString(); return (regExp->match(text).capturedLength() == text.length()); } return QVariant(); } QVariant QT::find2(const QVariant& vDocument, const QVariant& vWhat, const QVariant& vPos) { auto document = VAL(vDocument, QTextDocument*); if (document != nullptr) { #if QT_VERSION < 0x060000 const int type = vWhat.type(); #else const int type = vWhat.typeId(); #endif QTextCursor cursor; if (type == QMetaType::QString) { cursor = document->find(vWhat.toString(), vPos.toInt()); } else { auto regexp = VAL(vWhat, RegularExpression*); if (regexp != nullptr) { cursor = document->find(*regexp, vPos.toInt()); } } return QVariantList() << cursor.selectionStart() << cursor.selectionEnd() << cursor.selectedText(); } return QVariant(); } QVariant QT::findBlockByLineNumber(const QVariant& vDocument, const QVariant& vNumber) { auto document = VAL(vDocument, QTextDocument*); if (document != nullptr) { TextBlock* tmp = new TextBlock(document->findBlockByLineNumber(vNumber.toInt())); DELETE_LATER(tmp); return VAR(TextBlock*, tmp); } return QVariant(); } QVariant QT::lineCount(const QVariant& vDocument) { auto document = VAL(vDocument, QTextDocument*); if (document != nullptr) { return document->lineCount(); } return QVariant(); } QVariant QT::next(const QVariant& vBlock) { auto block = VAL(vBlock, TextBlock*); if (block != nullptr) { TextBlock* tmp = new TextBlock(block->next()); DELETE_LATER(tmp); return VAR(TextBlock*, tmp); } return QVariant(); } QVariant QT::position2(const QVariant& vCursor) { auto cursor = VAL(vCursor, TextCursor*); if (cursor != nullptr) { return cursor->position(); } return QVariant(); } QVariant QT::positionInBlock(const QVariant& vCursor) { auto cursor = VAL(vCursor, TextCursor*); if (cursor != nullptr) { return cursor->positionInBlock(); } return QVariant(); } QVariant QT::previous(const QVariant& vBlock) { auto block = VAL(vBlock, TextBlock*); if (block != nullptr) { TextBlock* tmp = new TextBlock(block->previous()); DELETE_LATER(tmp); return VAR(TextBlock*, tmp); } return QVariant(); } QVariant QT::previousBlockState(const QVariant& vHighlighter) { auto highlighter = VAL(vHighlighter, SyntaxHighlighter*); if (highlighter != nullptr) { return highlighter->previousBlockState(); } return QVariant(); } QVariant QT::setCurrentBlockState(const QVariant& vHighlighter, const QVariant& vState) { auto highlighter = VAL(vHighlighter, SyntaxHighlighter*); if (highlighter != nullptr) { highlighter->setCurrentBlockState(vState.toInt()); } return QVariant(); } QVariant QT::setFormat(const QVariant& vObject, const QVariant& vFormat) { auto format = VAL(vObject, TextCharFormat*); if (format != nullptr) { auto map = VAL(vFormat, QVariantMap); format->setForeground(QColor(map.value("color").toString())); if (map.contains("bold")) { format->setFontWeight(QFont::Bold); } if (map.contains("italic")) { format->setFontItalic(true); } return true; } auto highlighter = VAL(vObject, SyntaxHighlighter*); if (highlighter != nullptr) { auto args = VAL(vFormat, QVariantList); auto start = args.at(0).toInt(); auto count = args.at(1).toInt(); auto format = VAL(args.at(2), TextCharFormat*); if (format != nullptr) { highlighter->setFormat(start, count, *format); } else { highlighter->setFormat(start, count, QColor(args.at(2).toString())); } return true; } return false; } QVariant QT::setPattern(const QVariant& vObject, const QVariant& vArg) { auto regexp = VAL(vObject, RegularExpression*); if (regexp != nullptr) { regexp->setPattern(vArg.toString()); regexp->optimize(); } return QVariant(); } QVariant QT::text(const QVariant& vBlock) { auto block = VAL(vBlock, TextBlock*); if (block != nullptr) { return block->text(); } return QVariant(); } QVariant QT::textDocument(const QVariant& vDocument) { auto document = VAL(vDocument, QQuickTextDocument*); if (document != nullptr) { return VAR(QTextDocument*, document->textDocument()); } return QVariant(); } // etc QVariant QT::localIp() { // Returns the local IP string. Private networks may use: // 10.*.*.* // 172.16.*.* // 192.168.*.* const auto addresses = QNetworkInterface::allAddresses(); QStringList ips; for (QHostAddress adr : addresses) { if (adr.protocol() == QAbstractSocket::IPv4Protocol) { QString ip(adr.toString()); if (ip.startsWith("10.") || ip.startsWith("172.16.") || ip.startsWith("192.168.")) { ips << ip; } } } if (!ips.isEmpty()) { // hack for rare, ambiguous cases ips.sort(); return ips.first(); } return QVariant(); } // USB #if (defined Q_OS_UNIX) && !(defined NO_USB) QVariant QT::connectUsb() { if (usb == nullptr) { usb = new USB(); if (usb->connect2()) { connect(usb, &USB::receivingDone, [](const QByteArray& data) { ecl_fun("ed:received-from-ulisp", QString::fromUtf8(data)); }); return true; } } return QVariant(); } QVariant QT::sendToUlisp(const QVariant &vData) { if (usb != nullptr) { usb->write2(vData.toByteArray()); } return QVariant(); } #endif