View Issue Details

IDProjectCategoryView StatusLast Update
0017618ScribusScripterpublic2025-09-07 19:52
Reporterale Assigned To 
PrioritynormalSeverityminorReproducibilityN/A
Status newResolutionopen 
Product Version1.7.1.svn 
Summary0017618: [PATCH] Modify the behavior of scripter's getSelectedTextRange()
DescriptionCurrently, getSelectedTextRange() returns (0, 0) if there is no selection.

On the the other side, there is no way (or at least I could not find one) for knowing where the cursor is.

I suggest to modify the behavior of getSelectedTextRange() to:

- return (pos, length) if there is a text selection,
- return (pos, 0) if the text frame is in edit mode but there is no selection,
- return None if the the selected frame is a text frame but it's not in edit mode,
- trigger an error if there is no active item or if the item is not a text frame.
TagsNo tags attached.
PatchYes

Relationships

related to 0017619 closedale Modify the behavior of scripter's selectText() and selectFrameText() 

Activities

ale

2025-09-07 19:51

manager   ~0053010

- selectText() now "tries" (like many other scripter functions) to set the frame in edit mode.
- detects the cursor position
text-selection.diff (5,801 bytes)   
From 7997270862a7dd8c89e1b6e3aeebc7350ed90d7b Mon Sep 17 00:00:00 2001
From: ale rimoldi <ale@graphicslab.org>
Date: Sun, 7 Sep 2025 21:46:25 +0200
Subject: getTextSelectionRange() also for no selection


diff --git a/scribus/plugins/scriptplugin/cmdtext.cpp b/scribus/plugins/scriptplugin/cmdtext.cpp
index 8a2d26502..378aa88da 100644
--- a/scribus/plugins/scriptplugin/cmdtext.cpp
+++ b/scribus/plugins/scriptplugin/cmdtext.cpp
@@ -1236,6 +1236,7 @@ PyObject *scribus_selectframetext(PyObject* /* self */, PyObject* args)
 		item->itemText.select(start, selcount, true);
 	item->itemText.setCursorPosition(start + selcount);
 	item->HasSel = (selcount != 0);
+	ScCore->primaryMainWindow()->doc->appMode = modeEdit;
 
 	Py_RETURN_NONE;
 }
@@ -1275,6 +1276,7 @@ PyObject *scribus_selecttext(PyObject* /* self */, PyObject* args)
 		item->itemText.select(start, selcount, true);
 	item->itemText.setCursorPosition(start + selcount);
 	item->HasSel = (selcount != 0);
+	ScCore->primaryMainWindow()->doc->appMode = modeEdit;
 
 	Py_RETURN_NONE;
 }
@@ -1294,7 +1296,20 @@ PyObject *scribus_getselectedtextrange(PyObject* /* self */, PyObject* args)
 		PyErr_SetString(WrongFrameTypeError, QObject::tr("Cannot get text selection for non-text frame.","python error").toLocal8Bit().constData());
 		return nullptr;
 	}
-	return Py_BuildValue("(ii)", item->itemText.startOfSelection(), item->itemText.selectionLength());
+
+	const StoryText& story = item->itemText;
+
+	if (story.hasSelection()) {
+		return Py_BuildValue("(ii)", story.startOfSelection(), story.selectionLength());
+	}
+
+	if (ScCore->primaryMainWindow()->doc->appMode == modeEdit) {
+		return Py_BuildValue("(ii)", story.cursorPosition(), 0);
+	}
+
+	// Return (None, None) if Scribus is not in edit mode
+	// (and no selection has been set with selectText())
+	return Py_BuildValue("(OO)", Py_None, Py_None);
 }
 
 PyObject *scribus_getframeselectedtextrange(PyObject* /* self */, PyObject* args)
@@ -1313,7 +1328,20 @@ PyObject *scribus_getframeselectedtextrange(PyObject* /* self */, PyObject* args
 		return nullptr;
 	}
 
-	return Py_BuildValue("(ii)", item->itemText.startOfSelection() - item->firstInFrame(), item->itemText.selectionLength());
+	// return Py_BuildValue("(ii)", item->itemText.startOfSelection() - item->firstInFrame(), item->itemText.selectionLength());
+	const StoryText& story = item->itemText;
+
+	if (story.hasSelection()) {
+		return Py_BuildValue("(ii)", story.startOfSelection() - item->firstInFrame(), story.selectionLength());
+	}
+
+	if (ScCore->primaryMainWindow()->doc->appMode == modeEdit) {
+		return Py_BuildValue("(ii)", story.cursorPosition() - item->firstInFrame(), 0);
+	}
+
+	// Return (None, None) if Scribus is not in edit mode
+	// (and no selection has been set with selectText())
+	return Py_BuildValue("(OO)", Py_None, Py_None);
 }
 
 PyObject *scribus_deletetext(PyObject* /* self */, PyObject* args)
diff --git a/scribus/plugins/scriptplugin/cmdtext.h b/scribus/plugins/scriptplugin/cmdtext.h
index 9a02dd373..df6c53324 100644
--- a/scribus/plugins/scriptplugin/cmdtext.h
+++ b/scribus/plugins/scriptplugin/cmdtext.h
@@ -526,11 +526,16 @@ PyDoc_STRVAR(scribus_selecttext__doc__,
 QT_TR_NOOP("selectText(start, count, [\"name\"])\n\
 \n\
 Selects \"count\" characters of text in the story of the text frame \"name\" starting from the\n\
-character \"start\". Character counting starts at 0. If \"count\" is zero, any\n\
-text selection will be cleared.  If \"name\" is not given the currently\n\
-selected item is used.\n\
+character \"start\".\n\
 \n\
-May throw IndexError if the selection is outside the bounds of the text.\n\
+Character counting starts at 0.\n\
+If \"count\" is zero, any text selection will be cleared.\n\
+If \"count\" is -1, the selection goes to the end of the frame.\n\
+\n\
+If \"name\" is not given the currently selected item is used.\n\
+\n\
+Throws IndexError if the selection is outside the bounds of the text.\n\
+Throws WrongFrameTypeError if the item is not a text frame.\n\
 "));
 /*! Select text */
 PyObject *scribus_selecttext(PyObject * /*self*/, PyObject* args);
@@ -540,11 +545,16 @@ PyDoc_STRVAR(scribus_getselectedtextrange__doc__,
 QT_TR_NOOP("getSelectedTextRange([\"name\"])\n\
 \n\
 Gets the start index and length of the current text selection in the text chain.\n\
+\n\
 Results relate to the entire story across multiple text frames.\n\
-Start will be 0 if none is selected\n\
-Length will be 0 if none is selected\n\
 \n\
-May throw IndexError if the selection is outside the bounds of the text.\n\
+If there is no text selection, Start is the cursor position and length is 0.\n\
+Both start and length will be None if the frame is not in edit mode.\n\
+(Calling \"selectText()\" sets the frame in edit mode, even if it's not visible.)\n\
+\n\
+If \"name\" is not given the currently selected item is used.\n\
+\n\
+Throws WrongFrameTypeError if the item is not a text frame.\n\
 "));
 /*! Select text */
 PyObject *scribus_getselectedtextrange(PyObject * /*self*/, PyObject* args);
@@ -553,11 +563,9 @@ PyObject *scribus_getselectedtextrange(PyObject * /*self*/, PyObject* args);
 PyDoc_STRVAR(scribus_getframeselectedtextrange__doc__,
 QT_TR_NOOP("getFrameSelectedTextRange([\"name\"])\n\
 \n\
-Gets the start index and length of the current text selection of the currently selected frame.\n\
-Start will be 0 if none is selected\n\
-Length will be 0 if none is selected\n\
+Gets the start index and length of the current text selection and only consider the currently selected frame.\n\
 \n\
-May throw IndexError if the selection is outside the bounds of the text.\n\
+See getFrameSelectedTextRange() for further details.\n\
 "));
 /*! Select text */
 PyObject *scribus_getframeselectedtextrange(PyObject * /*self*/, PyObject* args);
text-selection.diff (5,801 bytes)   

Issue History

Date Modified Username Field Change
2025-09-06 07:55 ale New Issue
2025-09-07 19:48 ale Relationship added related to 0017619
2025-09-07 19:51 ale Note Added: 0053010
2025-09-07 19:51 ale File Added: text-selection.diff
2025-09-07 19:52 ale Summary Modify the behavior of scripter's getSelectedTextRange() => [PATCH] Modify the behavior of scripter's getSelectedTextRange()
2025-09-07 19:52 ale Patch No => Yes