syntax highlighting - Resaltado de sintaxis Qt5 en QML
syntax-highlighting qtquick2 (5)
Con un TextArea
se puede usar textFormat: TextEdit.RichText
para el formateo. Podemos usar TextArea::getText()
para obtener el texto sin formato y establecer TextArea::text
con el texto enriquecido. Aquí hay un ejemplo falso que:
- Los identificadores en mayúsculas (por ejemplo, el botón) en púrpura
- identificadores en minúsculas (por ejemplo, xyz) en rojo
- convierte los números (ej. 123 456) en azul
- y los símbolos (ej. = +;) permanecen negros
Aquí está el fragmento:
TextArea {
id: output
property bool processing: false
text: "<p>x = 123;</p><p>y = 456;</p><p>z = x + y;</p>"
textFormat: TextEdit.RichText
selectByMouse: true
onTextChanged: {
if (!processing) {
processing = true;
var p = cursorPosition;
var mu = getText(0, length);
mu = mu.replace(/([A-Z][A-Za-z]*|[a-z][A-Za-z]*|[0-9]+|[ /t/n]|[''][^'']*['']|[^A-Za-z0-9/t/n ])/g, function (f) {
console.log("f: ", JSON.stringify(f));
if (f.match(/^[A-Z][A-Za-z]*$/))
return "<span style=''color:#800080''>" + f + "</span>";
if (f.match(/^[a-z][A-Za-z]*$/))
return "<span style=''color:#800000''>" + f + "</span>";
else if (f.match(/^[0-9]+$/))
return "<span style=''color:#0000ff''>" + f + "</span>";
else if (f.match(/^[ ]/))
return " "
else if (f.match(/^[/t/n]/))
return f;
else if (f.match(/^['']/))
return "<span style=''color:#008000''>" + f + "</span>";
else
return f;
} );
text = mu;
cursorPosition = p;
processing = false;
}
}
}
Estoy trabajando en una presentación de QtQuick 2.0
y me gustaría insertar algunos ejemplos de código. ¿Es posible crear fácilmente un elemento qml de resaltado de sintaxis?
¿Puedes darme ejemplos de tecnologías e ideas sobre cómo lograrlo?
Gracias
Echa un vistazo a QSyntaxHighlighter .
Si necesita un elemento QML que resalte la sintaxis, puede crear su propio artículo extendiendo QDeclarativeItem
y utilizando la utilidad anterior.
El elemento TextEdit
Qt Quick expone una propiedad textDocument
, de tipo QQuickTextDocument
. Esto está explícitamente expuesto, por lo que puede usar QSyntaxHighlighter
directamente con el documento.
No hay una manera obvia de lograr el resaltado de sintaxis en QML.
Uno podría implementar su propio elemento declarativo, realizando el resaltado real con QSyntaxHighlighter
pero luego tendría que definir sus propias reglas de resaltado para el idioma del código fuente en cuestión. No haría esa cantidad de codificación para una presentación.
En su lugar, mostraría el código en un elemento de WebView
con el resaltado ya aplicado como marca HTML estática o con la ayuda de una biblioteca de resaltado de JavaScript, por ejemplo, highlight.js .
Actualización 1
Si el elemento de WebView
es realmente inutilizable, incluso el elemento de Text
simple con su soporte rudimentario de HTML debería ser suficiente para manejar el código fuente que resalta el caso de uso de datos si se alimenta con HTML estático.
en su archivo de aplicación:
QApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
QQuickTextDocument* doc = childObject<QQuickTextDocument*>(engine, "textEditor", "textDocument");
Q_ASSERT(doc != 0);
// QSyntaxHighlighter derrived class
MySyntaxHighlighter* parser = new MySyntaxHighlighter(doc->textDocument());
// use parser, see QSyntaxHighlighter doc...
int ret = app.exec();
delete parser;
return ret;
La función de plantilla para obtener objetos secundarios (devuelve la primera aparición de objectName, así que use nombres únicos para identificar objetos en sus archivos qml):
template <class T> T childObject(QQmlApplicationEngine& engine,
const QString& objectName,
const QString& propertyName)
{
QList<QObject*> rootObjects = engine.rootObjects();
foreach (QObject* object, rootObjects)
{
QObject* child = object->findChild<QObject*>(objectName);
if (child != 0)
{
std::string s = propertyName.toStdString();
QObject* object = child->property(s.c_str()).value<QObject*>();
Q_ASSERT(object != 0);
T prop = dynamic_cast<T>(object);
Q_ASSERT(prop != 0);
return prop;
}
}
return (T) 0;
}
en su archivo qml use un TextEdit (dentro de un Flickable o lo que quiera) con la propiedad objectName establecida correctamente:
....
TextEdit {
id: edit
objectName: "textEditor"
width: flick.width
height: flick.height
focus: true
font.family: "Courier New"
font.pointSize: 12
wrapMode: TextEdit.NoWrap
onCursorRectangleChanged: flick.ensureVisible(cursorRectangle)
}
....