[education/labplot] src: [scripting] don't show enums as functions in the completion popup and more cleanup.

Alexander Semke <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit fb183f482cda00be8c91219f71d80b39f78b4022 by Alexander Semke.
Committed on 02/08/2026 at 09:45.
Pushed by asemke into branch 'master'.

[scripting] don't show enums as functions in the completion popup and more cleanup.

M  +60   -14   src/backend/script/python/PythonScriptRuntime.cpp
M  +2    -2    src/backend/script/python/PythonScriptingHelper.h
M  +14   -12   src/frontend/script/ScriptCompletionModel.cpp
M  +2    -2    src/frontend/script/ScriptCompletionModel.h

https://invent.kde.org/education/labplot/-/commit/fb183f482cda00be8c91219f71d80b39f78b4022

diff --git a/src/backend/script/python/PythonScriptRuntime.cpp b/src/backend/script/python/PythonScriptRuntime.cpp
index ab14f238c3..99cc1b8abe 100644
--- a/src/backend/script/python/PythonScriptRuntime.cpp
+++ b/src/backend/script/python/PythonScriptRuntime.cpp
@@ -864,7 +864,7 @@ QString PythonScriptRuntime::pyUnicodeToQString(PyObject* obj) {
 }
 
 // Global helper function for code completion (avoids Python.h in frontend)
-QStringList getPylabplotSymbolsHelper() {
+QStringList pylabplotSymbolsHelper() {
 	return PythonScriptRuntime::getPylabplotSymbols();
 }
 
@@ -911,7 +911,7 @@ QStringList PythonScriptRuntime::getPylabplotSymbols() {
 }
 
 // Global helper to get class members (avoids Python.h in frontend)
-QList<PylabplotMemberInfo> getPylabplotClassMembersHelper(const QString& className) {
+QList<PylabplotMemberInfo> pylabplotClassMembersHelper(const QString& className) {
 	QList<PylabplotMemberInfo> members;
 
 	if (!Py_IsInitialized())
@@ -1019,6 +1019,27 @@ QList<PylabplotMemberInfo> getPylabplotClassMembersHelper(const QString& classNa
 			PylabplotMemberInfo info;
 			info.name = name;
 
+			// Check if it's an enum type - enums are classes that inherit from enum.Enum
+			PyObject* typeObj = PyObject_Type(attr);
+			if (typeObj) {
+				PyObject* typeNameObj = PyObject_GetAttrString(typeObj, "__name__");
+				if (typeNameObj && PyUnicode_Check(typeNameObj)) {
+					QString typeName = PythonScriptRuntime::pyUnicodeToQString(typeNameObj);
+					// Check if it's an enum class (EnumType or EnumMeta)
+					if (typeName.contains(QLatin1String("Enum")) && !name.contains(QLatin1String("Enum"))) {
+						info.isProperty = true;
+						info.isMethod = false;
+						Py_DECREF(typeNameObj);
+						Py_DECREF(typeObj);
+						Py_DECREF(attr);
+						members.append(info);
+						continue;
+					}
+					Py_DECREF(typeNameObj);
+				}
+				Py_DECREF(typeObj);
+			}
+
 			// Check if it's a callable (method)
 			info.isMethod = PyCallable_Check(attr);
 			info.isProperty = !info.isMethod;
@@ -1029,19 +1050,44 @@ QList<PylabplotMemberInfo> getPylabplotClassMembersHelper(const QString& classNa
 				PyObject* docObj = PyObject_GetAttrString(attr, "__doc__");
 				if (docObj && PyUnicode_Check(docObj)) {
 					QString doc = PythonScriptRuntime::pyUnicodeToQString(docObj);
-					// Extract first line as brief doc
+
+					// Clean up the signature: remove 'self', 'arg__N', type hints, '/'
+					// Example: "setColumnCount(self, arg__1: int, /) setColumn..."
+					// Should become: "setColumnCount(count)"
+
+					// Extract first line as signature
 					int newlinePos = doc.indexOf(QLatin1Char('\n'));
-					if (newlinePos > 0)
-						info.docstring = doc.left(newlinePos).trimmed();
-					else
-						info.docstring = doc.trimmed();
-
-					// Try to extract signature from docstring
-					// Common format: "method(arg1, arg2) -> returnType"
-					static QRegularExpression sigPattern(QStringLiteral(R"((\w+\([^)]*\)))"));
-					QRegularExpressionMatch match = sigPattern.match(info.docstring);
-					if (match.hasMatch())
-						info.signature = match.captured(1);
+					QString firstLine = (newlinePos > 0) ? doc.left(newlinePos).trimmed() : doc.trimmed();
+
+					// Try to extract just the method signature part
+					static QRegularExpression sigPattern(QStringLiteral(R"(^(\w+)\s*\([^)]*\))"));
+					QRegularExpressionMatch match = sigPattern.match(firstLine);
+
+					if (match.hasMatch()) {
+						QString rawSig = match.captured(0);
+
+						// Clean up: remove self, type hints, arg__N placeholders
+						rawSig.remove(QStringLiteral("self, "));
+						rawSig.remove(QStringLiteral("self"));
+						rawSig.remove(QRegularExpression(QStringLiteral(R"(arg__\d+)")));  // Remove arg__1, arg__2, etc
+						rawSig.remove(QRegularExpression(QStringLiteral(R"(:\s*\w+)")));   // Remove type hints like ": int"
+						rawSig.remove(QStringLiteral(", /"));
+						rawSig.remove(QStringLiteral("/"));
+						rawSig.remove(QStringLiteral(", ,"));  // Clean up double commas
+
+						info.signature = rawSig.simplified();
+					}
+
+					// Extract docstring (skip first line if it's the signature)
+					if (newlinePos > 0) {
+						QString remainingDoc = doc.mid(newlinePos + 1).trimmed();
+						// Take first meaningful line as docstring
+						int nextNewline = remainingDoc.indexOf(QLatin1Char('\n'));
+						if (nextNewline > 0)
+							info.docstring = remainingDoc.left(nextNewline).trimmed();
+						else
+							info.docstring = remainingDoc;
+					}
 				}
 				if (docObj)
 					Py_DECREF(docObj);
diff --git a/src/backend/script/python/PythonScriptingHelper.h b/src/backend/script/python/PythonScriptingHelper.h
index 83a5ed4254..2402f0ea5c 100644
--- a/src/backend/script/python/PythonScriptingHelper.h
+++ b/src/backend/script/python/PythonScriptingHelper.h
@@ -23,9 +23,9 @@ struct PylabplotMemberInfo {
 
 // Helper function to get pylabplot symbols without requiring Python.h
 // This allows frontend code to query symbols without Python header dependencies
-QStringList getPylabplotSymbolsHelper();
+QStringList pylabplotSymbolsHelper();
 
 // Get members (methods and properties) of a specific pylabplot class
-QList<PylabplotMemberInfo> getPylabplotClassMembersHelper(const QString& className);
+QList<PylabplotMemberInfo> pylabplotClassMembersHelper(const QString& className);
 
 #endif // PYTHONSCRIPTINGHELPER_H
diff --git a/src/frontend/script/ScriptCompletionModel.cpp b/src/frontend/script/ScriptCompletionModel.cpp
index 5352d1514b..fde9fcfecd 100644
--- a/src/frontend/script/ScriptCompletionModel.cpp
+++ b/src/frontend/script/ScriptCompletionModel.cpp
@@ -72,7 +72,7 @@ bool ScriptCompletionModel::initPylabplotSymbols() {
 	DEBUG(Q_FUNC_INFO)
 
 	// Get pylabplot symbols via global helper (avoids Python.h dependency)
-	QStringList symbolNames = getPylabplotSymbolsHelper();
+	QStringList symbolNames = pylabplotSymbolsHelper();
 
 	if (symbolNames.isEmpty()) {
 		WARN("No pylabplot symbols extracted - Python may not be initialized")
@@ -165,7 +165,7 @@ void ScriptCompletionModel::startCompletionRequest() {
 		// Member completion - get members of the object
 		QString typeName = inferType(objectName, scriptText);
 		if (!typeName.isEmpty()) {
-			QList<CompletionItem> members = getMembersForType(typeName);
+			QList<CompletionItem> members = membersForType(typeName);
 			// Filter by prefix
 			for (const auto& member : members) {
 				if (prefix.isEmpty() || member.name.startsWith(prefix, Qt::CaseInsensitive))
@@ -234,14 +234,16 @@ QVariant ScriptCompletionModel::data(const QModelIndex& index, int role) const {
 
 	switch (role) {
 	case Qt::DisplayRole:
-		if (index.column() == Name)
-			return item.name;
-		else if (index.column() == Prefix) {
-			// Show signature or type indicator
-			if (!item.signature.isEmpty())
-				return item.signature;
-			else if (item.isFunction)
-				return QStringLiteral("()");
+		if (index.column() == Name) {
+			// Show name with type indicator or signature
+			QString display = item.name;
+
+			// Add simple indicator based on type
+			if (item.isFunction || item.isClass) {
+				display += QStringLiteral("()");
+			}
+
+			return display;
 		}
 		break;
 
@@ -360,7 +362,7 @@ QString ScriptCompletionModel::inferType(const QString& varName, const QString&
 	return QString(); // Unknown type
 }
 
-QList<ScriptCompletionModel::CompletionItem> ScriptCompletionModel::getMembersForType(const QString& typeName) {
+QList<ScriptCompletionModel::CompletionItem> ScriptCompletionModel::membersForType(const QString& typeName) {
 	QList<CompletionItem> members;
 
 	if (typeName.isEmpty())
@@ -371,7 +373,7 @@ QList<ScriptCompletionModel::CompletionItem> ScriptCompletionModel::getMembersFo
 		return m_memberCache[typeName];
 
 	// Use runtime introspection to get real class members from Python
-	auto pylabplotMembers = getPylabplotClassMembersHelper(typeName);
+	auto pylabplotMembers = pylabplotClassMembersHelper(typeName);
 
 	// Convert to CompletionItem format
 	for (const auto& memberInfo : pylabplotMembers) {
diff --git a/src/frontend/script/ScriptCompletionModel.h b/src/frontend/script/ScriptCompletionModel.h
index 9ea9407c62..d6781d5ea6 100644
--- a/src/frontend/script/ScriptCompletionModel.h
+++ b/src/frontend/script/ScriptCompletionModel.h
@@ -69,8 +69,8 @@ private:
 
 	void updateUserVariables(const QString& scriptText);
 	void initPythonBuiltins();
-	CompletionContext detectContext(KTextEditor::View* view, const KTextEditor::Cursor& cursor, QString& objectName);
-	QList<CompletionItem> getMembersForType(const QString& typeName);
+	CompletionContext detectContext(KTextEditor::View*, const KTextEditor::Cursor&, QString& objectName);
+	QList<CompletionItem> membersForType(const QString& typeName);
 	QString inferType(const QString& varName, const QString& scriptText);
 };
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.