View Issue Details

IDProjectCategoryView StatusLast Update
0017052ScribusScripterpublic2023-11-18 22:53
Reporterale Assigned To 
PrioritynormalSeverityfeatureReproducibilityN/A
Status newResolutionopen 
Product Version1.7.0.svn 
Summary0017052: [PATCH] scripter: add functions to get the items in a group
Descriptionit should be possible to manipulate the items in a group without ungrouping it.

two functions are needed:

- get all direct items in the group: getGroupItems()
- get all items in the group recursively: getAllGroupItems()
TagsNo tags attached.
PatchYes

Activities

ale

2023-11-18 21:34

manager   ~0050487

Last edited: 2023-11-18 21:34

i have created

getGroupItems(["name", recursive=False, type=0]) -> [dict]


i will be creating a few tests and if everything is fine i can soon propose a patch for it.

ale

2023-11-18 22:53

manager   ~0050488

here it is. with a test file that tests a few use cases and shows how to use the new function.
get-group-items.diff (4,969 bytes)   
diff --git a/scribus/plugins/scriptplugin/cmdmani.cpp b/scribus/plugins/scriptplugin/cmdmani.cpp
index ce0ea2ba3eee7cc56b3bba9b615ac95df82a8a9f..4c6ceec57659598fcbb232d2ca9193fcea6278c8 100644
--- a/scribus/plugins/scriptplugin/cmdmani.cpp
+++ b/scribus/plugins/scriptplugin/cmdmani.cpp
@@ -12,6 +12,7 @@ for which a new license (GPL+exception) is in place.
 #include "sctextstream.h"
 #include "selection.h"
 #include "undomanager.h"
+#include <QQueue>
 
 PyObject *scribus_loadimage(PyObject* /* self */, PyObject* args)
 {
@@ -451,6 +452,62 @@ PyObject *scribus_scalegroup(PyObject* /* self */, PyObject* args)
 	Py_RETURN_NONE;
 }
 
+PyObject *scribus_getGroupItems(PyObject * /*self*/, PyObject* args, PyObject* kw)
+{
+	if (!checkHaveDocument())
+		return nullptr;
+
+	char *name = const_cast<char*>("");
+	unsigned int recursive = 0;
+	unsigned int type = 0;
+	char* kwargs[] = {const_cast<char*>("name"), const_cast<char*>("recursive"), const_cast<char*>("type"), nullptr};
+	if (!PyArg_ParseTupleAndKeywords(args, kw, "|espi", kwargs, "utf-8", &name, &recursive, &type))
+		return nullptr;
+
+	PageItem *pageItem = GetUniqueItem(QString::fromUtf8(name));
+	if (pageItem == nullptr)
+		return nullptr;
+
+	if (!pageItem->isGroup())
+		return nullptr;
+
+	auto items = PyList_New(0);
+
+	QQueue<PageItem*> queue;
+	queue.enqueue(pageItem);
+
+	while (!queue.isEmpty())
+	{
+		const auto pageItem = queue.dequeue();
+		for (auto groupItem: pageItem->groupItemList)
+		{
+			if (recursive && groupItem->isGroup())
+			{
+				queue.enqueue(groupItem);
+				continue;
+			}
+			if (type == 0 || groupItem->itemType() == type) {
+				auto itemDict = PyDict_New();
+				PyDict_SetItem(itemDict,
+					PyUnicode_FromString("name"),
+					PyUnicode_FromString(groupItem->itemName().toUtf8().constData())
+				);
+				PyDict_SetItem(itemDict,
+					PyUnicode_FromString("type"),
+					PyLong_FromUnsignedLong((unsigned long) groupItem->itemType())
+				);
+				PyDict_SetItem(itemDict,
+					PyUnicode_FromString("order"),
+					PyLong_FromUnsignedLong((unsigned long) groupItem->uniqueNr)
+				);
+				PyList_Append(items, itemDict);
+			}
+		}
+	}
+
+	return items;
+}
+
 PyObject *scribus_getselectedobject(PyObject* /* self */, PyObject* args)
 {
 	int i = 0;
@@ -707,6 +764,7 @@ void cmdmanidocwarnings()
 	s << scribus_combinepolygons__doc__
 	  << scribus_deselectall__doc__
 	  << scribus_flipobject__doc__
+	  << scribus_getGroupItems__doc__
 	  << scribus_getselectedobject__doc__
 	  << scribus_groupobjects__doc__
 	  << scribus_islocked__doc__
diff --git a/scribus/plugins/scriptplugin/cmdmani.h b/scribus/plugins/scriptplugin/cmdmani.h
index e4d4253a74c17fd8b3f2c3de175932446c1439a3..f42d53bc83dbf2cc9463cc89b0c37451d78894c4 100644
--- a/scribus/plugins/scriptplugin/cmdmani.h
+++ b/scribus/plugins/scriptplugin/cmdmani.h
@@ -148,6 +148,21 @@ May raise ValueError if an invalid scale factor is passed.\n\
 /*! Scale group with object name */
 PyObject *scribus_scalegroup(PyObject * /*self*/, PyObject* args);
 
+/*! docstring */
+PyDoc_STRVAR(scribus_getGroupItems__doc__,
+QT_TR_NOOP("getGroupItems([\"name\", recursive=False, type=0]) -> [dict]\n\n\
+Return the list of items in the group.\n\
+\n\
+`recursive`: if True and some of the items are groups, also include their items (recursively).\n\
+`type`: if not 0, only retain items of this type.\n\
+\n\
+Each item is defined as a dictionary containing:\n\
+`{'name': str, 'type': int, 'order': int}`\n\
+\n\
+If \"name\" is not given the currently selected item is used."));
+/*! List the items in a group. */
+PyObject *scribus_getGroupItems(PyObject * /*self*/, PyObject* args, PyObject* kw);
+
 /*! docstring */
 PyDoc_STRVAR(scribus_loadimage__doc__,
 QT_TR_NOOP("loadImage(\"filename\" [, \"name\"])\n\
diff --git a/scribus/plugins/scriptplugin/scriptplugin.cpp b/scribus/plugins/scriptplugin/scriptplugin.cpp
index 2836dfb9672dd54a06ee5ff98f8084e54a9b9f7c..a5ca29ba30deefebb0b42374c4154a98eb65366b 100644
--- a/scribus/plugins/scriptplugin/scriptplugin.cpp
+++ b/scribus/plugins/scriptplugin/scriptplugin.cpp
@@ -364,6 +364,7 @@ PyMethodDef scribus_methods[] = {
 	{const_cast<char*>("getFontNames"), (PyCFunction)scribus_getfontnames, METH_NOARGS, tr(scribus_getfontnames__doc__)},
 	{const_cast<char*>("getFontSize"), scribus_getfontsize, METH_VARARGS, tr(scribus_getfontsize__doc__)},
 	{const_cast<char*>("getFrameText"), scribus_getframetext, METH_VARARGS, tr(scribus_getframetext__doc__)},
+	{const_cast<char*>("getGroupItems"), (PyCFunction)scribus_getGroupItems, METH_VARARGS|METH_KEYWORDS, tr(scribus_getGroupItems__doc__)},
 	{const_cast<char*>("getGuiLanguage"), (PyCFunction)scribus_getlanguage, METH_NOARGS, tr(scribus_getlanguage__doc__)},
 	{const_cast<char*>("getHGuides"), (PyCFunction)scribus_getHguides, METH_NOARGS, tr(scribus_getHguides__doc__)},
 	{const_cast<char*>("getImageColorSpace"), scribus_getimagecolorspace, METH_VARARGS, tr(scribus_getimagecolorspace__doc__) },
get-group-items.diff (4,969 bytes)   
getGroupItems.py (3,838 bytes)   
#!/usr/bin/env python3
import sys
import subprocess

try:
    import scribus
except ImportError:
    pass

def run_script() :
    scribus.newDocument(scribus.PAPER_A4_MM, (10, 10, 10, 10), \
        scribus.PORTRAIT, 1, scribus.UNIT_MILLIMETERS, scribus.PAGE_1, 0, 1)

    # Test a group with text and an image frames

    scribus.createText(10, 10, 20, 20, 'text-01')
    scribus.insertText('some text', 0, 'text-01')
    scribus.createImage(10, 30, 20, 20, 'image-02')
    group_name = scribus.groupObjects(['text-01', 'image-02'])
    scribus.setItemName('group-03', group_name)

    group_items = scribus.getGroupItems('group-03')
    assert sorted([item['name'] for item in group_items]) == \
        sorted(['text-01', 'image-02'])
    assert sorted([item['type'] for item in group_items]) == sorted([4, 2])

    group_items = scribus.getGroupItems('group-03', type=4)
    assert sorted([item['name'] for item in group_items]) == \
        ['text-01']

    scribus.unGroupObjects('group-03')

    # the group does not exist anymore: this should now fail
    try:
        group_items = scribus.getGroupItems('group-03')
        assert False
    except scribus.NoValidObjectError:
        assert True

    # Test recursivity with a group with text frame, an image one and a group

    scribus.createEllipse(10, 50, 20, 20, 'ellipse-04')
    scribus.createRect(10, 70, 20, 20, 'square-05')

    group_name = scribus.groupObjects(['ellipse-04', 'square-05'])
    scribus.setItemName('group-06', group_name)

    group_name = scribus.groupObjects(['text-01', 'image-02', 'group-06'])
    scribus.setItemName('group-07', group_name)

    group_items = scribus.getGroupItems('group-07')
    assert sorted([item['name'] for item in group_items]) == \
        sorted(['text-01', 'image-02', 'group-06'])

    group_items = scribus.getGroupItems('group-07', recursive=True)
    assert sorted([item['name'] for item in group_items]) == \
        sorted(['text-01', 'image-02', 'ellipse-04', 'square-05'])
    assert sorted([item['type'] for item in group_items]) == sorted([4, 2, 6, 6])

    group_items = scribus.getGroupItems('group-07')
    assert sorted([item['name'] for item in group_items]) == \
        sorted(['text-01', 'image-02', 'group-06'])

    group_items = scribus.getGroupItems('group-07', recursive=True, type=4)
    assert sorted([item['name'] for item in group_items]) == \
        ['text-01']

    group_items = scribus.getGroupItems('group-07', recursive=True, type=6)
    assert sorted([item['name'] for item in group_items]) == \
        sorted(['ellipse-04', 'square-05'])

    scribus.unGroupObjects('group-07')

    # Test getting by type with multiple of the same

    scribus.createText(10, 90, 20, 20, 'text-08')
    scribus.insertText('more text', 0, 'text-08')

    group_name = scribus.groupObjects(['text-01', 'image-02', 'text-08'])
    scribus.setItemName('group-09', group_name)

    group_items = scribus.getGroupItems('group-09', type=4)
    assert sorted([item['name'] for item in group_items]) == \
        ['text-01', 'text-08']

    # use the current selection
    
    scribus.deselectAll()
    scribus.selectObject('group-09')

    group_items = scribus.getGroupItems()
    assert sorted([item['name'] for item in group_items]) == \
        sorted(['text-01', 'image-02', 'text-08'])

    scribus.unGroupObjects('group-09')

    # scribus.saveDocAs('getGroupItems.sla') # enable for starting manual testing

def run_scribus():
    # if len(sys.argv) < 2:
    #     print(f'Usage: python3 {sys.argv[0]} filename')
    #     return

    call_args = ['scribus', '-g', '-py', sys.argv[0]]
    # call_args += ['--', sys.argv[1]]
    subprocess.call(call_args)

def main():
    try:
        scribus
        run_script()
    except NameError:
        run_scribus()

if __name__ == "__main__":
    main()
getGroupItems.py (3,838 bytes)   

Issue History

Date Modified Username Field Change
2023-11-18 08:21 ale New Issue
2023-11-18 21:34 ale Note Added: 0050487
2023-11-18 21:34 ale Note Edited: 0050487
2023-11-18 22:53 ale Note Added: 0050488
2023-11-18 22:53 ale File Added: get-group-items.diff
2023-11-18 22:53 ale File Added: getGroupItems.py
2023-11-18 22:53 ale Summary scripter: add functions to get the items in a group => [PATCH] scripter: add functions to get the items in a group
2023-11-18 22:53 ale Patch No => Yes