Skip to content

Commit 31cbf84

Browse files
committed
QJSCompleter: allow to register custom completions
1 parent 395ae58 commit 31cbf84

File tree

2 files changed

+90
-4
lines changed

2 files changed

+90
-4
lines changed

include/internal/QJSCompleter.hpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22

33
// Qt
44
#include <QCompleter> // Required for inheritance
5+
#include <QStringList>
56
#include <verdigris>
67

8+
class QObject;
9+
class QStringListModel;
10+
711
/**
812
* @brief Class, that describes completer with
913
* javascript specific types and functions.
@@ -18,4 +22,24 @@ class QJSCompleter : public QCompleter
1822
* @param parent Pointer to parent QObject.
1923
*/
2024
explicit QJSCompleter(QObject *parent = nullptr);
25+
26+
/**
27+
* @brief Register a QObject instance to make its properties and methods available for completion.
28+
* @param name The name/prefix used to access this object in JavaScript (e.g., "Foo" for "Foo.method()")
29+
* @param object The QObject instance whose meta-object will be introspected
30+
*/
31+
void registerObject(const QString& name, QObject* object);
32+
33+
/**
34+
* @brief Unregister a previously registered object.
35+
* @param name The name of the object to unregister
36+
*/
37+
void unregisterObject(const QString& name);
38+
39+
private:
40+
void updateCompletions();
41+
42+
QStringList m_baseCompletions;
43+
QStringList m_registeredCompletions;
44+
QStringListModel* m_model = nullptr;
2145
};

src/internal/QJSCompleter.cpp

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@
55
// Qt
66
#include <QFile>
77
#include <QStringListModel>
8+
#include <QMetaObject>
9+
#include <QMetaMethod>
10+
#include <QMetaProperty>
811

912
#include <wobjectimpl.h>
1013
W_OBJECT_IMPL(QJSCompleter)
1114

1215
QJSCompleter::QJSCompleter(QObject *parent) : QCompleter(parent)
1316
{
1417
// Setting up JavaScript types
15-
QStringList list;
16-
1718
Q_INIT_RESOURCE(qcodeeditor_resources);
1819
QFile fl(":/languages/js.xml");
1920

@@ -33,12 +34,73 @@ QJSCompleter::QJSCompleter(QObject *parent) : QCompleter(parent)
3334
for (auto &&key : keys)
3435
{
3536
auto names = language.names(key);
36-
list.append(names);
37+
m_baseCompletions.append(names);
3738
}
3839

39-
setModel(new QStringListModel(list, this));
40+
m_model = new QStringListModel(this);
41+
setModel(m_model);
42+
updateCompletions();
43+
4044
setCompletionColumn(0);
4145
setModelSorting(QCompleter::CaseInsensitivelySortedModel);
4246
setCaseSensitivity(Qt::CaseSensitive);
4347
setWrapAround(true);
4448
}
49+
50+
void QJSCompleter::registerObject(const QString& name, QObject* object)
51+
{
52+
if (!object)
53+
return;
54+
55+
// Get the meta-object for introspection
56+
const QMetaObject* metaObj = object->metaObject();
57+
58+
// Extract all properties
59+
m_registeredCompletions.reserve(metaObj->propertyCount() + metaObj->methodCount());
60+
for (int i = 0; i < metaObj->propertyCount(); ++i)
61+
{
62+
m_registeredCompletions.append(QStringLiteral("%1.%2").arg(name, metaObj->property(i).name()));
63+
}
64+
65+
// Extract all methods (slots, signals, and invokable methods)
66+
for (int i = 0; i < metaObj->methodCount(); ++i)
67+
{
68+
QMetaMethod method = metaObj->method(i);
69+
auto methodName = method.name();
70+
71+
// Skip internal Qt methods
72+
if (methodName.startsWith("_q_"))
73+
continue;
74+
if (methodName.startsWith("destroyed") || methodName.startsWith("deleteLater"))
75+
continue;
76+
77+
m_registeredCompletions.append(QStringLiteral("%1.%2").arg(name, methodName));
78+
}
79+
80+
updateCompletions();
81+
}
82+
83+
void QJSCompleter::unregisterObject(const QString& name)
84+
{
85+
// Remove all completions that start with "name."
86+
QString prefix = name + ".";
87+
m_registeredCompletions.erase(
88+
std::remove_if(m_registeredCompletions.begin(), m_registeredCompletions.end(),
89+
[&prefix](const QString& completion) {
90+
return completion.startsWith(prefix);
91+
}),
92+
m_registeredCompletions.end()
93+
);
94+
95+
updateCompletions();
96+
}
97+
98+
void QJSCompleter::updateCompletions()
99+
{
100+
QStringList allCompletions = m_baseCompletions;
101+
allCompletions.append(m_registeredCompletions);
102+
allCompletions.removeDuplicates();
103+
104+
if (m_model)
105+
m_model->setStringList(allCompletions);
106+
}

0 commit comments

Comments
 (0)