View Issue Details

IDProjectCategoryView StatusLast Update
0016863ScribusImport / Exportpublic2023-11-26 12:32
Reporterfsimonis Assigned To 
PrioritynormalSeveritymajorReproducibilityalways
Status newResolutionopen 
Product Version1.7.0.svn 
Summary0016863: Prototype for bulk adding items and groups in vectorized pdf importer
DescriptionHi there,

I had an idea on how to implement a solution for the slow vectorized pdf imports.
The issue boils down to the PageItem creation, which always creates a unique name, which is implemented with repeated tries and a linear lookup, so O(n²).
The vectorized pdf importer renders every letter as a polygon, which brings scribus to its knees.

The proposed prototype (see patch) adds the option for deferred naming to PageItems.
Direct naming, generates a unique name as usual.
Deferred naming skips this step and sets the name to "pending".

The scribusdoc now provides addItemDeferred(), which behaves identical to addItem except that it defers the name generation of the item.
Then I added a new class named bulkadder, which provides a wrapper around ScribusDoc::addItem() and ScibusDoc::groupSelection().
It maintains a list of created PageItems and provides a function to process them.

Processing works as follows:
- build a set of existing names
- create an empty map from ItemType -> last successful suffix
- for each saved item
  - use the type to get the last successful suffix or 0 as well as the translated item name
  - find the first suffix that isn't a known name
  - save the last successful suffix
  - update the name of the item
- clear the saved items

I am now able to import a pdf of 320 pages with ~350000 polygons into scribus .

In release mode (without IPO/LTO !), this takes about 27 seconds, including 8 seconds after the progress dialogue disappears.

To put this in context of my previous issue 0016604: The first 20 pages loaded in 20 seconds. This now completes in under 2 seconds.

As I said, this is a prototype.
The patch extends the API of Scribus and touches some internals.
I also had to add an override for the m_item_name of PageItem, which doesn't perform a name lookup (for obvious reasons).

I also am not sure on how to test this feature.
Please let me know if you like me to change anything.

Regards F
Additional InformationRelated to 0016604
Tagsimport, pdf import, performance, speed
PatchYes

Activities

fsimonis

2022-11-20 16:58

reporter  

0001-Add-deferred-naming-and-bulkadder.patch (64,321 bytes)   
From 1418d06569444dcce4813ae93d34406970bc102b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Simonis?= <simonisfrederic@gmail.com>
Date: Sun, 20 Nov 2022 14:06:19 +0100
Subject: [PATCH] Add deferred naming and bulkadder

---
 scribus/CMakeLists.txt                   |   1 +
 scribus/bulkadder.cpp                    | 108 +++++++++++++++++++++++
 scribus/bulkadder.h                      |  53 +++++++++++
 scribus/pageitem.cpp                     |  85 +++++++++++++-----
 scribus/pageitem.h                       |  11 +++
 scribus/pageitem_arc.cpp                 |   4 +
 scribus/pageitem_arc.h                   |   1 +
 scribus/pageitem_group.cpp               |   5 ++
 scribus/pageitem_group.h                 |   1 +
 scribus/pageitem_imageframe.cpp          |   7 +-
 scribus/pageitem_imageframe.h            |   1 +
 scribus/pageitem_latexframe.cpp          |   6 +-
 scribus/pageitem_latexframe.h            |   1 +
 scribus/pageitem_line.cpp                |   5 ++
 scribus/pageitem_line.h                  |   1 +
 scribus/pageitem_noteframe.cpp           |  14 ++-
 scribus/pageitem_noteframe.h             |   5 ++
 scribus/pageitem_osgframe.cpp            |   5 +-
 scribus/pageitem_osgframe.h              |   1 +
 scribus/pageitem_pathtext.cpp            |   6 +-
 scribus/pageitem_pathtext.h              |   1 +
 scribus/pageitem_polygon.cpp             |   5 ++
 scribus/pageitem_polygon.h               |   1 +
 scribus/pageitem_polyline.cpp            |   5 ++
 scribus/pageitem_polyline.h              |   1 +
 scribus/pageitem_regularpolygon.cpp      |   5 +-
 scribus/pageitem_regularpolygon.h        |   1 +
 scribus/pageitem_spiral.cpp              |   5 +-
 scribus/pageitem_spiral.h                |   1 +
 scribus/pageitem_symbol.cpp              |   5 ++
 scribus/pageitem_symbol.h                |   1 +
 scribus/pageitem_table.cpp               |   7 +-
 scribus/pageitem_table.h                 |   1 +
 scribus/pageitem_textframe.cpp           |   8 +-
 scribus/pageitem_textframe.h             |   1 +
 scribus/plugins/import/pdf/slaoutput.cpp |  44 ++++-----
 scribus/plugins/import/pdf/slaoutput.h   |   2 +
 scribus/scribusdoc.cpp                   |  66 ++++++++++----
 scribus/scribusdoc.h                     |  10 +++
 39 files changed, 417 insertions(+), 74 deletions(-)
 create mode 100644 scribus/bulkadder.cpp
 create mode 100644 scribus/bulkadder.h

diff --git a/scribus/CMakeLists.txt b/scribus/CMakeLists.txt
index 9e82181..fc29160 100644
--- a/scribus/CMakeLists.txt
+++ b/scribus/CMakeLists.txt
@@ -71,6 +71,7 @@ set(SCRIBUS_SOURCES
 	actionmanager.cpp
 	actionsearch.cpp
 	appmodehelper.cpp
+	bulkadder.cpp
 	canvas.cpp
 	canvasgesture_cellselect.cpp
 	canvasgesture_columnresize.cpp
diff --git a/scribus/bulkadder.cpp b/scribus/bulkadder.cpp
new file mode 100644
index 0000000..512ee2e
--- /dev/null
+++ b/scribus/bulkadder.cpp
@@ -0,0 +1,108 @@
+/*
+For general Scribus (>=1.3.2) copyright and licensing information please refer
+to the COPYING file provided with the program. Following this notice may exist
+a copyright and/or license notice that predates the release of Scribus 1.3.2
+for which a new license (GPL+exception) is in place.
+*/
+/***************************************************************************
+ *   Copyright (C) 2005 by Riku Leino                                      *
+ *   riku@scribus.info                                                     *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.             *
+ ***************************************************************************/
+
+#include <set>
+#include <map>
+
+#include "bulkadder.h"
+
+namespace {
+void findName(PageItem *item, std::set<QString> &names,
+              std::map<PageItem::ItemType, int> &lastSuccess) {
+  auto type = item->itemType();
+  QString baseName = item->nameFromType(type);
+
+  int nameNum = lastSuccess[type];
+  QString tmp;
+  tmp.setNum(nameNum);
+  tmp.prepend(baseName);
+  while (names.count(tmp) != 0) {
+    ++nameNum;
+    tmp.setNum(nameNum);
+    tmp.prepend(baseName);
+  }
+  lastSuccess[type] = nameNum;
+  names.insert(tmp);
+  item->setSafeItemName(tmp);
+}
+
+std::set<QString> gatherNames(ScribusDoc *doc) {
+  std::set<QString> names;
+  std::vector<PageItem *> groups;
+  groups.reserve(32);
+
+  // Process root elements of the doc and remember groups
+  for (PageItem *item : *doc->Items) {
+    names.insert(item->itemName());
+    if (item->isGroup())
+      groups.push_back(item);
+  }
+
+  // Process groups
+  while (!groups.empty()) {
+    PageItem *item = groups.back();
+    groups.pop_back();
+    for (PageItem *item : item->groupItemList) {
+      names.insert(item->itemName());
+      if (item->isGroup())
+        groups.push_back(item);
+    }
+  }
+  return names;
+}
+} // namespace
+
+int BulkAdder::itemAdd(const PageItem::ItemType itemType,
+                       const PageItem::ItemFrameType frameType, double x,
+                       double y, double b, double h, double w,
+                       const QString &fill, const QString &outline,
+                       PageItem::ItemKind itemKind) {
+  int id = m_doc->itemAddDeferred(itemType, frameType, x, y, b, h, w, fill,
+                                  outline, itemKind);
+  m_pending.push_back(m_doc->Items->at(id));
+  return id;
+}
+
+
+PageItem* BulkAdder::groupObjectsSelection(Selection* customSelection)
+{
+  auto group = m_doc->groupObjectsSelectionDeferred(customSelection);
+  m_pending.push_back(group);
+  return group;
+}
+
+void BulkAdder::process() {
+  if (m_pending.empty()) {
+    return;
+  }
+
+  auto names = gatherNames(m_doc);
+  std::map<PageItem::ItemType, int> lastSuccess;
+  for (auto item : m_pending) {
+    findName(item, names, lastSuccess);
+  }
+  m_pending.clear();
+}
diff --git a/scribus/bulkadder.h b/scribus/bulkadder.h
new file mode 100644
index 0000000..2d630cd
--- /dev/null
+++ b/scribus/bulkadder.h
@@ -0,0 +1,53 @@
+/*
+For general Scribus (>=1.3.2) copyright and licensing information please refer
+to the COPYING file provided with the program. Following this notice may exist
+a copyright and/or license notice that predates the release of Scribus 1.3.2
+for which a new license (GPL+exception) is in place.
+*/
+/***************************************************************************
+ *   Copyright (C) 2005 by Riku Leino                                      *
+ *   riku@scribus.info                                                     *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.             *
+ ***************************************************************************/
+
+#ifndef BULKADDER_H
+#define BULKADDER_H
+
+#include "pageitem.h"
+#include "scribusdoc.h"
+#include "scribusapi.h"
+
+class SCRIBUS_API BulkAdder {
+  public:
+    BulkAdder(ScribusDoc * document) : m_doc(document) {};
+
+    ~BulkAdder() {
+      process();
+    };
+
+    int itemAdd(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline, PageItem::ItemKind itemKind = PageItem::StandardItem);
+
+	  PageItem* groupObjectsSelection(Selection* customSelection = nullptr);
+
+    void process();
+
+  private:
+    ScribusDoc *  m_doc;
+    std::vector<PageItem*> m_pending;
+};
+
+#endif
diff --git a/scribus/pageitem.cpp b/scribus/pageitem.cpp
index b175029..501a54f 100644
--- a/scribus/pageitem.cpp
+++ b/scribus/pageitem.cpp
@@ -396,6 +396,9 @@ PageItem::PageItem(const PageItem & other)
 
 
 PageItem::PageItem(ScribusDoc *doc, ItemType newType, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
+ : PageItem(doc, newType, x, y, w, h, w2, fill, outline, NameTiming::Direct){};
+
+PageItem::PageItem(ScribusDoc *doc, ItemType newType, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
 	// Initialize superclass(es)
 	: QObject(doc), SingleObservable<PageItem>(doc->itemsChanged()), TextContext(this),
 	// Initialize member variables
@@ -455,70 +458,64 @@ PageItem::PageItem(ScribusDoc *doc, ItemType newType, double x, double y, double
 			// because c++'s typeinfos are still saying it's
 			// a plain pageitem
 			// This is fixed in the PageItem_LatexFrame constructor
-			m_itemName = tr("Image");
 			setUPixmap(Um::IImageFrame);
 			break;
 		case TextFrame:
-			m_itemName = tr("Text");
 			setUPixmap(Um::ITextFrame);
 			break;
 		case Line:
-			m_itemName = tr("Line");
 			setUPixmap(Um::ILine);
 			break;
 		case Polygon:
-			m_itemName = tr("Polygon");
 			setUPixmap(Um::IPolygon);
 			break;
 		case PolyLine:
-			m_itemName = tr("Polyline");
 			setUPixmap(Um::IPolyline);
 			break;
 		case PathText:
-			m_itemName = tr("PathText");
 			setUPixmap(Um::IPathText);
 			break;
 		case Symbol:
-			m_itemName = tr("Symbol");
 			setUPixmap(Um::IPolygon);
 			break;
 		case Group:
-			m_itemName = tr("Group");
 			setUPixmap(Um::IPolygon);
 			break;
 		case RegularPolygon:
-			m_itemName = tr("RegularPolygon");
 			setUPixmap(Um::IPolygon);
 			break;
 		case Arc:
-			m_itemName = tr("Arc");
 			setUPixmap(Um::IPolygon);
 			break;
 		case Spiral:
-			m_itemName = tr("Spiral");
 			setUPixmap(Um::IPolygon);
 			break;
 		case Table:
-			m_itemName = tr("Table");
 			//setUPixmap(Um::IPolygon); // TODO: Fix this.
 			break;
 		default:
-			m_itemName = "Item";
 			break;
 	}
 	m_Doc->TotalItems++;
+
+  if (nameTiming == NameTiming::Deferred) {
+    // It is the callers responsibilty to create a usable name
+    m_itemName = "pending";
+  } else {
+    m_itemName = nameFromType(m_itemType);
 	
-	QString oldName(m_itemName);
-	int nameNum = m_Doc->TotalItems;
-	m_itemName += tmp.setNum(m_Doc->TotalItems);
-	while (m_Doc->itemNameExists(m_itemName))
-	{
-		++nameNum;
-		m_itemName = oldName + tmp.setNum(nameNum);
-	}
+    QString oldName(m_itemName);
+    int nameNum = m_Doc->TotalItems;
+    m_itemName += tmp.setNum(m_Doc->TotalItems);
+    while (m_Doc->itemNameExists(m_itemName))
+    {
+      ++nameNum;
+      m_itemName = oldName + tmp.setNum(nameNum);
+    }
 	
-	uniqueNr = m_Doc->TotalItems;
-	setUName(m_itemName);
+    //uniqueNr = m_Doc->TotalItems;
+    setUName(m_itemName);
+  }
 	m_annotation.setBorderColor(outline);
 
 	ImageIntent = Intent_Relative_Colorimetric;
@@ -723,6 +720,39 @@ PageItem::~PageItem()
 //			unWeldChild();
 }
 
+QString PageItem::nameFromType(ItemType type) {
+  switch (type) {
+    case ImageFrame:
+    case OSGFrame:
+    case LatexFrame:
+      return tr("Image");
+    case TextFrame:
+      return tr("Text");
+    case Line:
+      return tr("Line");
+    case Polygon:
+      return tr("Polygon");
+    case PolyLine:
+      return tr("Polyline");
+    case PathText:
+      return tr("PathText");
+    case Symbol:
+      return tr("Symbol");
+    case Group:
+      return tr("Group");
+    case RegularPolygon:
+      return tr("RegularPolygon");
+    case Arc:
+      return tr("Arc");
+    case Spiral:
+      return tr("Spiral");
+    case Table:
+      return tr("Table");
+    default:
+      return "Item";
+  }
+}
+
 bool PageItem::isMasterItem() const
 {
 	if (Parent == nullptr)
@@ -2402,6 +2432,15 @@ void PageItem::DrawPolyL(QPainter *p, const QPolygon& pts)
 	p->drawPolygon(pts.constData() + firstVal, pts.size() - firstVal);
 }
 
+void PageItem::setSafeItemName(const QString& uniqueName)
+{
+	if (m_itemName == uniqueName || uniqueName.isEmpty())
+		return;
+
+  m_itemName = uniqueName;
+	setUName(m_itemName);
+}
+
 void PageItem::setItemName(const QString& newName)
 {
 	if (m_itemName == newName || newName.isEmpty())
diff --git a/scribus/pageitem.h b/scribus/pageitem.h
index 73125b5..74250fb 100644
--- a/scribus/pageitem.h
+++ b/scribus/pageitem.h
@@ -38,6 +38,7 @@ for which a new license (GPL+exception) is in place.
 #include <QVector>
 #include <QTemporaryFile>
 
+#include "deferredtask.h"
 #include "scribusapi.h"
 #include "annotation.h"
 #include "commonstrings.h"
@@ -219,6 +220,11 @@ public:	// Start enumerator definitions
 		Round		= 2,
 		Other		= 3
 	};
+
+  enum struct NameTiming : bool {
+    Direct,
+    Deferred
+  };
 		//End enumerator definitions
 
 	// This property may not hang around for too long, but should be useful
@@ -234,6 +240,7 @@ public:	// Start enumerator definitions
 public: // Start public functions
 
 	PageItem(ScribusDoc *doc, ItemType newType, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+	PageItem(ScribusDoc *doc, ItemType newType, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	~PageItem() override;
 
 	/* these do essentially the same as a dynamic cast but might be more readable */
@@ -813,6 +820,8 @@ public: // Start public functions
 	 */
 	void setItemName(const QString& newName);
 
+	void setSafeItemName(const QString& uniqueName);
+
 	/**
 	* @brief Set the masterpage the object is on
 	* @param mpName name of the master page
@@ -1267,6 +1276,8 @@ public: // Start public functions
 	bool hasFill() { return ((fillColor() != CommonStrings::None) || (GrType != 0)); }
 	bool hasStroke() { return ((lineColor() != CommonStrings::None) || (GrTypeStroke != 0) || (!NamedLStyle.isEmpty()) || (!patternStrokeVal.isEmpty())); }
 
+  QString nameFromType(ItemType type);
+
 		// End public functions
 
 public:	// Start public variables
diff --git a/scribus/pageitem_arc.cpp b/scribus/pageitem_arc.cpp
index d840fb3..7401a4a 100644
--- a/scribus/pageitem_arc.cpp
+++ b/scribus/pageitem_arc.cpp
@@ -21,6 +21,7 @@ for which a new license (GPL+exception) is in place.
  *                                                                         *
  ***************************************************************************/
 
+#include <fcntl.h>
 #if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES)
 #define _USE_MATH_DEFINES
 #endif
@@ -47,6 +48,9 @@ for which a new license (GPL+exception) is in place.
 using namespace std;
 
 PageItem_Arc::PageItem_Arc(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
+	: PageItem_Arc(pa, x, y, w, h, w2, fill, outline, NameTiming::Direct){};
+
+PageItem_Arc::PageItem_Arc(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
 	: PageItem(pa, PageItem::Arc, x, y, w, h, w2, fill, outline)
 {
 	arcHeight = h;
diff --git a/scribus/pageitem_arc.h b/scribus/pageitem_arc.h
index 25cf024..74842aa 100644
--- a/scribus/pageitem_arc.h
+++ b/scribus/pageitem_arc.h
@@ -37,6 +37,7 @@ class SCRIBUS_API PageItem_Arc : public PageItem
 
 public:
 	PageItem_Arc(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+	PageItem_Arc(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	PageItem_Arc(const PageItem & p) : PageItem(p) {}
 	~PageItem_Arc() {};
 
diff --git a/scribus/pageitem_group.cpp b/scribus/pageitem_group.cpp
index f6f0b95..7669448 100644
--- a/scribus/pageitem_group.cpp
+++ b/scribus/pageitem_group.cpp
@@ -52,6 +52,11 @@ PageItem_Group::PageItem_Group(ScribusDoc *pa, double x, double y, double w, dou
 {
 }
 
+PageItem_Group::PageItem_Group(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem(pa, PageItem::Group, x, y, w, h, 0, CommonStrings::None, CommonStrings::None, nameTiming)
+{
+}
+
 PageItem_Group::~PageItem_Group()
 {
 //	while (!groupItemList.isEmpty())
diff --git a/scribus/pageitem_group.h b/scribus/pageitem_group.h
index fcead53..8edc224 100644
--- a/scribus/pageitem_group.h
+++ b/scribus/pageitem_group.h
@@ -37,6 +37,7 @@ class SCRIBUS_API PageItem_Group : public PageItem
 
 public:
 	PageItem_Group(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+	PageItem_Group(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	PageItem_Group(const PageItem & p) : PageItem(p) {}
 	~PageItem_Group();
 
diff --git a/scribus/pageitem_imageframe.cpp b/scribus/pageitem_imageframe.cpp
index 0702b41..fb7ec85 100644
--- a/scribus/pageitem_imageframe.cpp
+++ b/scribus/pageitem_imageframe.cpp
@@ -55,8 +55,13 @@ for which a new license (GPL+exception) is in place.
 #include "util.h"
 
 
+PageItem_ImageFrame::PageItem_ImageFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem(pa, PageItem::ImageFrame, x, y, w, h, w2, fill, outline, nameTiming)
+{
+}
+
 PageItem_ImageFrame::PageItem_ImageFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
-	: PageItem(pa, PageItem::ImageFrame, x, y, w, h, w2, fill, outline)
+	: PageItem(pa, PageItem::ImageFrame, x, y, w, h, w2, fill, outline, NameTiming::Direct)
 {
 }
 
diff --git a/scribus/pageitem_imageframe.h b/scribus/pageitem_imageframe.h
index a0b4d3b..355f708 100644
--- a/scribus/pageitem_imageframe.h
+++ b/scribus/pageitem_imageframe.h
@@ -37,6 +37,7 @@ class SCRIBUS_API PageItem_ImageFrame : public PageItem
 
 public:
 	PageItem_ImageFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+	PageItem_ImageFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	PageItem_ImageFrame(const PageItem & p) : PageItem(p) {}
 	~PageItem_ImageFrame();
 
diff --git a/scribus/pageitem_latexframe.cpp b/scribus/pageitem_latexframe.cpp
index 6cba246..2f3681d 100644
--- a/scribus/pageitem_latexframe.cpp
+++ b/scribus/pageitem_latexframe.cpp
@@ -41,7 +41,11 @@ for which a new license (GPL+exception) is in place.
 #include "util.h"
 
 PageItem_LatexFrame::PageItem_LatexFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
-		: PageItem_ImageFrame(pa, x, y, w, h, w2, fill, outline)
+		: PageItem_LatexFrame(pa, x, y, w, h, w2, fill, outline, NameTiming::Direct)
+{}
+
+PageItem_LatexFrame::PageItem_LatexFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+		: PageItem_ImageFrame(pa, x, y, w, h, w2, fill, outline, nameTiming)
 {
 	setUPixmap(Um::ILatexFrame);
 	m_itemName = tr("Render") + QString::number(m_Doc->TotalItems);
diff --git a/scribus/pageitem_latexframe.h b/scribus/pageitem_latexframe.h
index 87a90eb..07e1ce4 100644
--- a/scribus/pageitem_latexframe.h
+++ b/scribus/pageitem_latexframe.h
@@ -46,6 +46,7 @@ class SCRIBUS_API PageItem_LatexFrame : public PageItem_ImageFrame
 
 	public:
 		PageItem_LatexFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+		PageItem_LatexFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 		~PageItem_LatexFrame();
 		
 		PageItem_LatexFrame * asLatexFrame() override { return this; }
diff --git a/scribus/pageitem_line.cpp b/scribus/pageitem_line.cpp
index da254c2..2665ef6 100644
--- a/scribus/pageitem_line.cpp
+++ b/scribus/pageitem_line.cpp
@@ -52,6 +52,11 @@ PageItem_Line::PageItem_Line(ScribusDoc *pa, double x, double y, double w, doubl
 {
 }
 
+PageItem_Line::PageItem_Line(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem(pa, PageItem::Line, x, y, w, h, w2, fill, outline, nameTiming)
+{
+}
+
 void PageItem_Line::DrawObj_Item(ScPainter *p, const QRectF& /*e*/)
 {
 	if (m_Doc->RePos)
diff --git a/scribus/pageitem_line.h b/scribus/pageitem_line.h
index 60b9ade..1646224 100644
--- a/scribus/pageitem_line.h
+++ b/scribus/pageitem_line.h
@@ -37,6 +37,7 @@ class SCRIBUS_API PageItem_Line : public PageItem
 
 public:
 	PageItem_Line(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+	PageItem_Line(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	PageItem_Line(const PageItem & p) : PageItem(p) {}
 	~PageItem_Line() {};
 	
diff --git a/scribus/pageitem_noteframe.cpp b/scribus/pageitem_noteframe.cpp
index 51b0f8e..f217d35 100644
--- a/scribus/pageitem_noteframe.cpp
+++ b/scribus/pageitem_noteframe.cpp
@@ -16,7 +16,10 @@
 #include "text/boxes.h"
 
 PageItem_NoteFrame::PageItem_NoteFrame(NotesStyle *nStyle, ScribusDoc *doc, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
-	: PageItem_TextFrame(doc, x, y, w, h, w2, fill, outline)
+  : PageItem_NoteFrame(nStyle, doc, x, y, w, h, w2, fill, outline, NameTiming::Direct) {}
+
+PageItem_NoteFrame::PageItem_NoteFrame(NotesStyle *nStyle, ScribusDoc *doc, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem_TextFrame(doc, x, y, w, h, w2, fill, outline, nameTiming)
 {
 	m_nstyle = nStyle;
 	itemText.clear();
@@ -44,12 +47,17 @@ PageItem_NoteFrame::PageItem_NoteFrame(NotesStyle *nStyle, ScribusDoc *doc, doub
 }
 
 PageItem_NoteFrame::PageItem_NoteFrame(ScribusDoc *doc, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
-	: PageItem_TextFrame(doc, x, y, w, h, w2, fill, outline)
+	: PageItem_NoteFrame(doc, x, y, w, h, w2, fill, outline, NameTiming::Direct) {}
+
+PageItem_NoteFrame::PageItem_NoteFrame(ScribusDoc *doc, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem_TextFrame(doc, x, y, w, h, w2, fill, outline, nameTiming)
 {
 	m_textFlowMode = TextFlowUsesFrameShape;
 }
 
-PageItem_NoteFrame::PageItem_NoteFrame(PageItem_TextFrame* inFrame, NotesStyle *nStyle) : PageItem_TextFrame(inFrame->doc(),inFrame->xPos(), inFrame->yPos(),inFrame->width(), inFrame->height(),inFrame->lineWidth(), inFrame->fillColor(), inFrame->lineColor())
+PageItem_NoteFrame::PageItem_NoteFrame(PageItem_TextFrame* inFrame, NotesStyle *nStyle) : PageItem_NoteFrame(inFrame, nStyle, NameTiming::Direct) {};
+
+PageItem_NoteFrame::PageItem_NoteFrame(PageItem_TextFrame* inFrame, NotesStyle *nStyle, NameTiming nameTiming) : PageItem_TextFrame(inFrame->doc(),inFrame->xPos(), inFrame->yPos(),inFrame->width(), inFrame->height(),inFrame->lineWidth(), inFrame->fillColor(), inFrame->lineColor(), nameTiming)
 {
 	m_nstyle = nStyle;
 	m_masterFrame = inFrame;
diff --git a/scribus/pageitem_noteframe.h b/scribus/pageitem_noteframe.h
index 5f62395..f1dbd33 100644
--- a/scribus/pageitem_noteframe.h
+++ b/scribus/pageitem_noteframe.h
@@ -14,6 +14,11 @@ private:
 	PageItem_NoteFrame(NotesStyle *nStyle, ScribusDoc *doc, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
 	PageItem_NoteFrame(ScribusDoc *doc, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
 	PageItem_NoteFrame(PageItem_TextFrame* inFrame, NotesStyle *nStyle);
+
+	PageItem_NoteFrame(NotesStyle *nStyle, ScribusDoc *doc, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
+	PageItem_NoteFrame(ScribusDoc *doc, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
+	PageItem_NoteFrame(PageItem_TextFrame* inFrame, NotesStyle *nStyle, NameTiming nameTiming);
+
 	~PageItem_NoteFrame() { }
 
 public:
diff --git a/scribus/pageitem_osgframe.cpp b/scribus/pageitem_osgframe.cpp
index 03f46f2..14845c0 100644
--- a/scribus/pageitem_osgframe.cpp
+++ b/scribus/pageitem_osgframe.cpp
@@ -42,7 +42,10 @@ for which a new license (GPL+exception) is in place.
 #include "util.h"
 
 PageItem_OSGFrame::PageItem_OSGFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
-		: PageItem_ImageFrame(pa, x, y, w, h, w2, fill, outline)
+		: PageItem_ImageFrame(pa, x, y, w, h, w2, fill, outline, NameTiming::Direct) {}
+
+PageItem_OSGFrame::PageItem_OSGFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+		: PageItem_ImageFrame(pa, x, y, w, h, w2, fill, outline, nameTiming)
 {
 	setUPixmap(Um::ILatexFrame);
 	m_itemName = tr("OSG") + QString::number(m_Doc->TotalItems);
diff --git a/scribus/pageitem_osgframe.h b/scribus/pageitem_osgframe.h
index f184bef..f08f972 100644
--- a/scribus/pageitem_osgframe.h
+++ b/scribus/pageitem_osgframe.h
@@ -74,6 +74,7 @@ class SCRIBUS_API PageItem_OSGFrame : public PageItem_ImageFrame
 			ShadedIllustration				= 14
 		};
 		PageItem_OSGFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+		PageItem_OSGFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 		~PageItem_OSGFrame();
 		
 		PageItem_OSGFrame * asOSGFrame() override { return this; }
diff --git a/scribus/pageitem_pathtext.cpp b/scribus/pageitem_pathtext.cpp
index 66a9f6f..dd758de 100644
--- a/scribus/pageitem_pathtext.cpp
+++ b/scribus/pageitem_pathtext.cpp
@@ -54,7 +54,11 @@ for which a new license (GPL+exception) is in place.
 using namespace std;
 
 PageItem_PathText::PageItem_PathText(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
-	: PageItem(pa, PageItem::PathText, x, y, w, h, w2, fill, outline)
+	: PageItem_PathText(pa, x, y, w, h, w2, fill, outline, NameTiming::Direct) {};
+
+
+PageItem_PathText::PageItem_PathText(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem(pa, PageItem::PathText, x, y, w, h, w2, fill, outline, nameTiming)
 {
 	firstChar = 0;
 	m_maxChars = itemText.length();
diff --git a/scribus/pageitem_pathtext.h b/scribus/pageitem_pathtext.h
index 4d0d351..181e361 100644
--- a/scribus/pageitem_pathtext.h
+++ b/scribus/pageitem_pathtext.h
@@ -36,6 +36,7 @@ class SCRIBUS_API PageItem_PathText : public PageItem
 
 public:
 	PageItem_PathText(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+	PageItem_PathText(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	PageItem_PathText(const PageItem & p) : PageItem(p) {}
 	~PageItem_PathText() {};
 	
diff --git a/scribus/pageitem_polygon.cpp b/scribus/pageitem_polygon.cpp
index 87c7023..aee8948 100644
--- a/scribus/pageitem_polygon.cpp
+++ b/scribus/pageitem_polygon.cpp
@@ -48,6 +48,11 @@ PageItem_Polygon::PageItem_Polygon(ScribusDoc *pa, double x, double y, double w,
 {
 }
 
+PageItem_Polygon::PageItem_Polygon(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem(pa, PageItem::Polygon, x, y, w, h, w2, fill, outline, nameTiming)
+{
+}
+
 void PageItem_Polygon::DrawObj_Item(ScPainter *p, const QRectF& /*e*/)
 {
 	if (!m_Doc->RePos)
diff --git a/scribus/pageitem_polygon.h b/scribus/pageitem_polygon.h
index d501d92..d71ab7e 100644
--- a/scribus/pageitem_polygon.h
+++ b/scribus/pageitem_polygon.h
@@ -37,6 +37,7 @@ class SCRIBUS_API PageItem_Polygon : public PageItem
 
 public:
 	PageItem_Polygon(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+	PageItem_Polygon(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	PageItem_Polygon(const PageItem & p) : PageItem(p) {}
 	~PageItem_Polygon() {};
 
diff --git a/scribus/pageitem_polyline.cpp b/scribus/pageitem_polyline.cpp
index 648c89d..67ffe43 100644
--- a/scribus/pageitem_polyline.cpp
+++ b/scribus/pageitem_polyline.cpp
@@ -51,6 +51,11 @@ PageItem_PolyLine::PageItem_PolyLine(ScribusDoc *pa, double x, double y, double
 {
 }
 
+PageItem_PolyLine::PageItem_PolyLine(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem(pa, PageItem::PolyLine, x, y, w, h, w2, fill, outline, nameTiming)
+{
+}
+
 void PageItem_PolyLine::DrawObj_Item(ScPainter *p, const QRectF& /*e*/)
 {
 	if (m_Doc->RePos || PoLine.size() < 4)
diff --git a/scribus/pageitem_polyline.h b/scribus/pageitem_polyline.h
index 300f1fb..1213a28 100644
--- a/scribus/pageitem_polyline.h
+++ b/scribus/pageitem_polyline.h
@@ -36,6 +36,7 @@ class SCRIBUS_API PageItem_PolyLine : public PageItem
 
 public:
 	PageItem_PolyLine(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+	PageItem_PolyLine(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	PageItem_PolyLine(const PageItem & p) : PageItem(p) {}
 	~PageItem_PolyLine() {};
 	
diff --git a/scribus/pageitem_regularpolygon.cpp b/scribus/pageitem_regularpolygon.cpp
index e66e26f..229d76b 100644
--- a/scribus/pageitem_regularpolygon.cpp
+++ b/scribus/pageitem_regularpolygon.cpp
@@ -48,7 +48,10 @@ for which a new license (GPL+exception) is in place.
 using namespace std;
 
 PageItem_RegularPolygon::PageItem_RegularPolygon(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
-	: PageItem(pa, PageItem::RegularPolygon, x, y, w, h, w2, fill, outline)
+	: PageItem_RegularPolygon(pa, x, y, w, h, w2, fill, outline, NameTiming::Direct) {}
+
+PageItem_RegularPolygon::PageItem_RegularPolygon(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem(pa, PageItem::RegularPolygon, x, y, w, h, w2, fill, outline, nameTiming)
 {
 	polyCorners = m_Doc->itemToolPrefs().polyCorners;
 	polyFactor = m_Doc->itemToolPrefs().polyFactor;
diff --git a/scribus/pageitem_regularpolygon.h b/scribus/pageitem_regularpolygon.h
index 5f2a4a2..72f8b81 100644
--- a/scribus/pageitem_regularpolygon.h
+++ b/scribus/pageitem_regularpolygon.h
@@ -37,6 +37,7 @@ class SCRIBUS_API PageItem_RegularPolygon : public PageItem
 
 public:
 	PageItem_RegularPolygon(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+	PageItem_RegularPolygon(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	PageItem_RegularPolygon(const PageItem & p) : PageItem(p) {}
 	~PageItem_RegularPolygon() {};
 
diff --git a/scribus/pageitem_spiral.cpp b/scribus/pageitem_spiral.cpp
index af13a41..2c4cd24 100644
--- a/scribus/pageitem_spiral.cpp
+++ b/scribus/pageitem_spiral.cpp
@@ -48,7 +48,10 @@ for which a new license (GPL+exception) is in place.
 using namespace std;
 
 PageItem_Spiral::PageItem_Spiral(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
-	: PageItem(pa, PageItem::Spiral, x, y, w, h, w2, fill, outline)
+	: PageItem_Spiral(pa, x, y, w, h, w2, fill, outline, NameTiming::Direct) {}
+
+PageItem_Spiral::PageItem_Spiral(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem(pa, PageItem::Spiral, x, y, w, h, w2, fill, outline, nameTiming)
 {
 	spiralStartAngle = m_Doc->itemToolPrefs().spiralStartAngle;
 	spiralEndAngle = m_Doc->itemToolPrefs().spiralEndAngle;
diff --git a/scribus/pageitem_spiral.h b/scribus/pageitem_spiral.h
index da3b190..b3be70f 100644
--- a/scribus/pageitem_spiral.h
+++ b/scribus/pageitem_spiral.h
@@ -37,6 +37,7 @@ class SCRIBUS_API PageItem_Spiral : public PageItem
 
 public:
 	PageItem_Spiral(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+	PageItem_Spiral(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	PageItem_Spiral(const PageItem & p) : PageItem(p) {}
 	~PageItem_Spiral() {};
 
diff --git a/scribus/pageitem_symbol.cpp b/scribus/pageitem_symbol.cpp
index ec51ed3..c80d223 100644
--- a/scribus/pageitem_symbol.cpp
+++ b/scribus/pageitem_symbol.cpp
@@ -52,6 +52,11 @@ PageItem_Symbol::PageItem_Symbol(ScribusDoc *pa, double x, double y, double w, d
 {
 }
 
+PageItem_Symbol::PageItem_Symbol(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem(pa, PageItem::Symbol, x, y, w, h, 0, CommonStrings::None, CommonStrings::None, nameTiming)
+{
+}
+
 void PageItem_Symbol::DrawObj_Item(ScPainter *p, const QRectF& /*e*/)
 {
 	if (m_Doc->RePos)
diff --git a/scribus/pageitem_symbol.h b/scribus/pageitem_symbol.h
index a18042b..b783472 100644
--- a/scribus/pageitem_symbol.h
+++ b/scribus/pageitem_symbol.h
@@ -37,6 +37,7 @@ class SCRIBUS_API PageItem_Symbol : public PageItem
 
 public:
 	PageItem_Symbol(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+  PageItem_Symbol(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	PageItem_Symbol(const PageItem & p) : PageItem(p) {}
 	~PageItem_Symbol() {};
 
diff --git a/scribus/pageitem_table.cpp b/scribus/pageitem_table.cpp
index 96dfd73..0957360 100644
--- a/scribus/pageitem_table.cpp
+++ b/scribus/pageitem_table.cpp
@@ -46,8 +46,11 @@ const double PageItem_Table::MinimumRowHeight = 3.0;
 // The minimum column width.
 const double PageItem_Table::MinimumColumnWidth = 3.0;
 
-PageItem_Table::PageItem_Table(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, int numRows, int numColumns) :
-	PageItem(pa, PageItem::Table, x, y, w, h, w2, fill, outline),
+PageItem_Table::PageItem_Table(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, int numRows, int numColumns)
+  : PageItem_Table(pa, x, y, w, h, w2, fill, outline, NameTiming::Direct, numRows, numColumns) {}
+
+PageItem_Table::PageItem_Table(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline,NameTiming nameTiming, int numRows, int numColumns ) :
+	PageItem(pa, PageItem::Table, x, y, w, h, w2, fill, outline, nameTiming),
 	m_rows(0), m_columns(0), m_tablePainter(new CollapsedTablePainter(this))
 {
 	initialize(numRows, numColumns);
diff --git a/scribus/pageitem_table.h b/scribus/pageitem_table.h
index f810247..d0d45fc 100644
--- a/scribus/pageitem_table.h
+++ b/scribus/pageitem_table.h
@@ -88,6 +88,7 @@ public:
 public:
 	/// Construct a new table item with @a numRows rows and @a numColumns columns.
 	PageItem_Table(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, int numRows = 1, int numColumns = 1);
+	PageItem_Table(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming,  int numRows = 1, int numColumns = 1 );
 
 	/// Destructor.
 	~PageItem_Table();
diff --git a/scribus/pageitem_textframe.cpp b/scribus/pageitem_textframe.cpp
index d0fb1c1..a7bd093 100644
--- a/scribus/pageitem_textframe.cpp
+++ b/scribus/pageitem_textframe.cpp
@@ -74,11 +74,17 @@ for which a new license (GPL+exception) is in place.
 using namespace std;
 
 PageItem_TextFrame::PageItem_TextFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
-	: PageItem(pa, PageItem::TextFrame, x, y, w, h, w2, fill, outline)
+	: PageItem(pa, PageItem::TextFrame, x, y, w, h, w2, fill, outline, NameTiming::Direct)
+{
+}
+
+PageItem_TextFrame::PageItem_TextFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem(pa, PageItem::TextFrame, x, y, w, h, w2, fill, outline, NameTiming::Direct)
 {
 	init();
 }
 
+
 PageItem_TextFrame::PageItem_TextFrame(const PageItem & p) : PageItem(p)
 {
 	init();
diff --git a/scribus/pageitem_textframe.h b/scribus/pageitem_textframe.h
index 5c50745..8674b34 100644
--- a/scribus/pageitem_textframe.h
+++ b/scribus/pageitem_textframe.h
@@ -48,6 +48,7 @@ class SCRIBUS_API PageItem_TextFrame : public PageItem
 
 public:
 	PageItem_TextFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+	PageItem_TextFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	PageItem_TextFrame(const PageItem & p);
 	~PageItem_TextFrame() {}
 
diff --git a/scribus/plugins/import/pdf/slaoutput.cpp b/scribus/plugins/import/pdf/slaoutput.cpp
index 960388b..633a5da 100644
--- a/scribus/plugins/import/pdf/slaoutput.cpp
+++ b/scribus/plugins/import/pdf/slaoutput.cpp
@@ -288,8 +288,8 @@ QString AnoOutputDev::getColor(GfxColorSpace *color_space, const GfxColor *color
 }
 
 SlaOutputDev::SlaOutputDev(ScribusDoc* doc, QList<PageItem*> *Elements, QStringList *importedColors, int flags)
+  : m_doc(doc), m_bulkadder(doc)
 {
-	m_doc = doc;
 	m_Elements = Elements;
 	pushGroup();
 	m_importedColors = importedColors;
@@ -400,7 +400,7 @@ bool SlaOutputDev::annotations_callback(Annot *annota, void *user_data)
 bool SlaOutputDev::handleTextAnnot(Annot* annota, double xCoor, double yCoor, double width, double height)
 {
 	AnnotText *anl = (AnnotText*)annota;
-	int z = m_doc->itemAdd(PageItem::TextFrame, PageItem::Rectangle, xCoor, yCoor, width, height, 0, CommonStrings::None, CommonStrings::None);
+	int z = m_bulkadder.itemAdd(PageItem::TextFrame, PageItem::Rectangle, xCoor, yCoor, width, height, 0, CommonStrings::None, CommonStrings::None);
 	PageItem *ite = m_doc->Items->at(z);
 	int flg = annota->getFlags();
 	if (!(flg & 16))
@@ -547,7 +547,7 @@ bool SlaOutputDev::handleLinkAnnot(Annot* annota, double xCoor, double yCoor, do
 	}
 	if (validLink)
 	{
-		int z = m_doc->itemAdd(PageItem::TextFrame, PageItem::Rectangle, xCoor, yCoor, width, height, 0, CommonStrings::None, CommonStrings::None);
+		int z = m_bulkadder.itemAdd(PageItem::TextFrame, PageItem::Rectangle, xCoor, yCoor, width, height, 0, CommonStrings::None, CommonStrings::None);
 		PageItem *ite = m_doc->Items->at(z);
 		int flg = annota->getFlags();
 		if (!(flg & 16))
@@ -713,7 +713,7 @@ bool SlaOutputDev::handleWidgetAnnot(Annot* annota, double xCoor, double yCoor,
 				delete annotOutDev;
 			}
 			const auto& graphicState = m_graphicStack.top();
-			int z = m_doc->itemAdd(PageItem::TextFrame, PageItem::Rectangle, xCoor, yCoor, width, height, 0, graphicState.fillColor, CommonStrings::None);
+			int z = m_bulkadder.itemAdd(PageItem::TextFrame, PageItem::Rectangle, xCoor, yCoor, width, height, 0, graphicState.fillColor, CommonStrings::None);
 			PageItem *ite = m_doc->Items->at(z);
 			int flg = annota->getFlags();
 			if (!(flg & 16))
@@ -1279,7 +1279,7 @@ void SlaOutputDev::endPage()
 			}
 			if (!m_tmpSel->isEmpty())
 			{
-				PageItem *ite = m_doc->groupObjectsSelection(m_tmpSel);
+				PageItem *ite = m_bulkadder.groupObjectsSelection(m_tmpSel);
 				ite->setItemName(it.key());
 				m_Elements->append(ite);
 				if (m_groupStack.count() != 0)
@@ -1313,7 +1313,7 @@ void SlaOutputDev::restoreState(GfxState *state)
 					m_tmpSel->addItem(gElements.Items.at(dre), true);
 					m_Elements->removeAll(gElements.Items.at(dre));
 				}
-				PageItem *ite = m_doc->groupObjectsSelection(m_tmpSel);
+				PageItem *ite = m_bulkadder.groupObjectsSelection(m_tmpSel);
 				if (ite)
 				{
 					QPainterPath clippath = m_graphicStack.top().clipPath;
@@ -1408,7 +1408,7 @@ void SlaOutputDev::endTransparencyGroup(GfxState *state)
 			m_tmpSel->addItem(gElements.Items.at(dre), true);
 			m_Elements->removeAll(gElements.Items.at(dre));
 		}
-		PageItem *ite = m_doc->groupObjectsSelection(m_tmpSel);
+		PageItem *ite = m_bulkadder.groupObjectsSelection(m_tmpSel);
 		ite->setFillTransparency(1.0 - state->getFillOpacity());
 		ite->setFillBlendmode(getBlendMode(state));
 		ScPattern pat(m_doc);
@@ -1438,7 +1438,7 @@ void SlaOutputDev::endTransparencyGroup(GfxState *state)
 		m_Elements->removeAll(gElements.Items.at(dre));
 	}
 	if ((gElements.Items.count() != 1) || (gElements.isolated))
-		ite = m_doc->groupObjectsSelection(m_tmpSel);
+		ite = m_bulkadder.groupObjectsSelection(m_tmpSel);
 	else
 		ite = gElements.Items.first();
 	if (ite->isGroup())
@@ -1588,9 +1588,9 @@ void SlaOutputDev::stroke(GfxState *state)
 
 	int z;
 	if (m_pathIsClosed)
-		z = m_doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, state->getTransformedLineWidth(), CommonStrings::None, graphicState.strokeColor);
+		z = m_bulkadder.itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, state->getTransformedLineWidth(), CommonStrings::None, graphicState.strokeColor);
 	else
-		z = m_doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, xCoor, yCoor, 10, 10, state->getTransformedLineWidth(), CommonStrings::None, graphicState.strokeColor);
+		z = m_bulkadder.itemAdd(PageItem::PolyLine, PageItem::Unspecified, xCoor, yCoor, 10, 10, state->getTransformedLineWidth(), CommonStrings::None, graphicState.strokeColor);
 	PageItem* ite = m_doc->Items->at(z);
 	ite->PoLine = out.copy();
 	ite->ClipEdited = true;
@@ -1689,9 +1689,9 @@ void SlaOutputDev::createFillItem(GfxState *state, Qt::FillRule fillRule)
 		graphicState.fillColor = getColor(state->getFillColorSpace(), state->getFillColor(), &graphicState.fillShade);
 		int z;
 		if (m_pathIsClosed)
-			z = m_doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, graphicState.fillColor, CommonStrings::None);
+			z = m_bulkadder.itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, graphicState.fillColor, CommonStrings::None);
 		else
-			z = m_doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, graphicState.fillColor, CommonStrings::None);
+			z = m_bulkadder.itemAdd(PageItem::PolyLine, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, graphicState.fillColor, CommonStrings::None);
 		PageItem* ite = m_doc->Items->at(z);
 		ite->PoLine.fromQPainterPath(clippedPath, true);
 		ite->ClipEdited = true;
@@ -1813,7 +1813,7 @@ bool SlaOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading, do
 	m_coords = output;
 
 	const auto& graphicState = m_graphicStack.top();
-	int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), bb.width(), bb.height(), 0, graphicState.fillColor, CommonStrings::None);
+	int z = m_bulkadder.itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), bb.width(), bb.height(), 0, graphicState.fillColor, CommonStrings::None);
 	PageItem* ite = m_doc->Items->at(z);
 	if (checkClip())
 	{
@@ -1935,7 +1935,7 @@ bool SlaOutputDev::radialShadedFill(GfxState *state, GfxRadialShading *shading,
 	m_coords = output;
 
 	const auto& graphicState = m_graphicStack.top();
-	int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, graphicState.fillColor, CommonStrings::None);
+	int z = m_bulkadder.itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, graphicState.fillColor, CommonStrings::None);
 	PageItem* ite = m_doc->Items->at(z);
 	if (checkClip())
 	{
@@ -1998,7 +1998,7 @@ bool SlaOutputDev::gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangle
 	const double *ctm = state->getCTM();
 	m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]);
 	const auto& graphicState = m_graphicStack.top();
-	int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, graphicState.fillColor, CommonStrings::None);
+	int z = m_bulkadder.itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, graphicState.fillColor, CommonStrings::None);
 	PageItem* ite = m_doc->Items->at(z);
 	ite->ClipEdited = true;
 	ite->FrameType = 3;
@@ -2079,7 +2079,7 @@ bool SlaOutputDev::patchMeshShadedFill(GfxState *state, GfxPatchMeshShading *sha
 	const double *ctm = state->getCTM();
 	m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]);
 	const auto& graphicState = m_graphicStack.top();
-	int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, graphicState.fillColor, CommonStrings::None);
+	int z = m_bulkadder.itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, graphicState.fillColor, CommonStrings::None);
 	PageItem* ite = m_doc->Items->at(z);
 	ite->ClipEdited = true;
 	ite->FrameType = 3;
@@ -2257,7 +2257,7 @@ bool SlaOutputDev::tilingPatternFill(GfxState *state, Gfx * /*gfx*/, Catalog *ca
 		m_doc->itemSelection_FlipV();
 		PageItem *ite;
 		if (m_doc->m_Selection->count() > 1)
-			ite = m_doc->groupObjectsSelection();
+			ite = m_bulkadder.groupObjectsSelection();
 		else
 			ite = m_doc->m_Selection->itemAt(0);
 		ite->setFillTransparency(1.0 - state->getFillOpacity());
@@ -2296,7 +2296,7 @@ bool SlaOutputDev::tilingPatternFill(GfxState *state, Gfx * /*gfx*/, Catalog *ca
 	m_coords = output;
 
 	const auto& graphicState = m_graphicStack.top();
-	int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, graphicState.fillColor, CommonStrings::None);
+	int z = m_bulkadder.itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, graphicState.fillColor, CommonStrings::None);
 	ite = m_doc->Items->at(z);
 
 	m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]);
@@ -2683,7 +2683,7 @@ void SlaOutputDev::createImageFrame(QImage& image, GfxState *state, int numColor
 	without_rotation = m_ctm * without_rotation.rotate(angle);
 	QRectF trect_wr = without_rotation.mapRect(QRectF(0, 0, 1, 1));
 
-	int z = m_doc->itemAdd(PageItem::ImageFrame, PageItem::Rectangle, xCoor + torigin.x(), yCoor + torigin.y(), trect_wr.width(), trect_wr.height(), 0, CommonStrings::None, CommonStrings::None);
+	int z = m_bulkadder.itemAdd(PageItem::ImageFrame, PageItem::Rectangle, xCoor + torigin.x(), yCoor + torigin.y(), trect_wr.width(), trect_wr.height(), 0, CommonStrings::None, CommonStrings::None);
 	PageItem* ite = m_doc->Items->at(z);
 	ite->ClipEdited = true;
 	ite->FrameType = 3;
@@ -3268,7 +3268,7 @@ void SlaOutputDev::drawChar(GfxState* state, double x, double y, double dx, doub
 			}
 			if ((textPath.size() > 3) && ((wh.x() != 0.0) || (wh.y() != 0.0)) && (textRenderingMode != 7))
 			{
-				int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, CommonStrings::None, CommonStrings::None);
+				int z = m_bulkadder.itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, CommonStrings::None, CommonStrings::None);
 				PageItem* ite = m_doc->Items->at(z);
 
 				// todo: merge this between vector and text implementations.
@@ -3332,7 +3332,7 @@ void SlaOutputDev::endType3Char(GfxState *state)
 		}
 		PageItem *ite;
 		if (m_doc->m_Selection->count() > 1)
-			ite = m_doc->groupObjectsSelection();
+			ite = m_bulkadder.groupObjectsSelection();
 		else
 			ite = m_doc->m_Selection->itemAt(0);
 		if (!f3e.colored)
@@ -3389,7 +3389,7 @@ void SlaOutputDev::endTextObject(GfxState *state)
 			}
 			PageItem *ite;
 			if (gElements.Items.count() != 1)
-				ite = m_doc->groupObjectsSelection(m_tmpSel);
+				ite = m_bulkadder.groupObjectsSelection(m_tmpSel);
 			else
 				ite = gElements.Items.first();
 			ite->setGroupClipping(false);
diff --git a/scribus/plugins/import/pdf/slaoutput.h b/scribus/plugins/import/pdf/slaoutput.h
index 4a64da8..b4d7010 100644
--- a/scribus/plugins/import/pdf/slaoutput.h
+++ b/scribus/plugins/import/pdf/slaoutput.h
@@ -29,6 +29,7 @@ for which a new license (GPL+exception) is in place.
 #include "scribusview.h"
 #include "selection.h"
 #include "vgradient.h"
+#include "bulkadder.h"
 
 #include <poppler/Object.h>
 #include <poppler/OutputDev.h>
@@ -285,6 +286,7 @@ protected:
 	void pushGroup(const QString& maskName = "", bool forSoftMask = false, bool alpha = false, bool inverted = false);
 
 	ScribusDoc* m_doc;
+  BulkAdder m_bulkadder;
 	Qt::PenCapStyle m_lineEnd { Qt::FlatCap };
 	Qt::PenJoinStyle m_lineJoin { Qt::MiterJoin };
 	QList<PageItem*>* m_Elements;
diff --git a/scribus/scribusdoc.cpp b/scribus/scribusdoc.cpp
index c182667..e9812ad 100644
--- a/scribus/scribusdoc.cpp
+++ b/scribus/scribusdoc.cpp
@@ -5156,6 +5156,16 @@ bool ScribusDoc::copyPageToMasterPage(int pageNumber, int leftPage, int maxLeftP
 }
 
 PageItem* ScribusDoc::createPageItem(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline)
+{
+  return implCreatePageItem(itemType, frameType, x, y, b, h, w, fill, outline, PageItem::NameTiming::Direct);
+}
+
+PageItem* ScribusDoc::createPageItemDeferred(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline)
+{
+  return implCreatePageItem(itemType, frameType, x, y, b, h, w, fill, outline, PageItem::NameTiming::Deferred);
+}
+
+PageItem* ScribusDoc::implCreatePageItem(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline, PageItem::NameTiming nameTiming)
 {
 	PageItem* newItem=nullptr;
 	switch (itemType)
@@ -5163,66 +5173,66 @@ PageItem* ScribusDoc::createPageItem(const PageItem::ItemType itemType, const Pa
 		//Q_ASSERTs here will warn on creation issues when a coder specifies the frameType incorrectly
 		//for items that do not have/need a frameType for creation.
 		case PageItem::ImageFrame:
-			newItem = new PageItem_ImageFrame(this, x, y, b, h, w, m_docPrefsData.itemToolPrefs.imageFillColor, m_docPrefsData.itemToolPrefs.imageStrokeColor);
+			newItem = new PageItem_ImageFrame(this, x, y, b, h, w, m_docPrefsData.itemToolPrefs.imageFillColor, m_docPrefsData.itemToolPrefs.imageStrokeColor, nameTiming);
 //			Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Unspecified);
 			break;
 		case PageItem::TextFrame:
-			newItem = new PageItem_TextFrame(this, x, y, b, h, w, CommonStrings::None, outline);
+			newItem = new PageItem_TextFrame(this, x, y, b, h, w, CommonStrings::None, outline, nameTiming);
 //			Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Unspecified);
 			break;
 		case PageItem::Line:
 			{
 				//CB 5521 Remove false minimum line width
 				double lineWidth = w; // == 0.0 ? 1.0 : w;
-				newItem = new PageItem_Line(this, x, y, b, h, lineWidth, CommonStrings::None, outline);
+				newItem = new PageItem_Line(this, x, y, b, h, lineWidth, CommonStrings::None, outline, nameTiming);
 //				Q_ASSERT(frameType==PageItem::Unspecified);
 			}
 			break;
 		case PageItem::Table:
-			newItem = new PageItem_Table(this, x, y, b, h, w, fill, outline);
+			newItem = new PageItem_Table(this, x, y, b, h, w, fill, outline, nameTiming);
 //			Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Unspecified);
 			break;
 		case PageItem::Polygon:
-			newItem = new PageItem_Polygon(this, x, y, b, h, w, fill, outline);
+			newItem = new PageItem_Polygon(this, x, y, b, h, w, fill, outline, nameTiming);
 //			Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Ellipse || frameType==PageItem::Unspecified);
 			break;
 		case PageItem::PolyLine:
-			newItem = new PageItem_PolyLine(this, x, y, b, h, w, fill, outline);
+			newItem = new PageItem_PolyLine(this, x, y, b, h, w, fill, outline, nameTiming);
 //			Q_ASSERT(frameType==PageItem::Unspecified);
 			break;
 		case PageItem::PathText:
 			//Currently used only in fileloader
-			newItem = new PageItem_PathText(this, x, y, b, h, w, fill, outline);
+			newItem = new PageItem_PathText(this, x, y, b, h, w, fill, outline, nameTiming);
 //			Q_ASSERT(frameType==PageItem::Unspecified);
 			break;
 		case PageItem::LatexFrame:
-			newItem = new PageItem_LatexFrame(this, x, y, b, h, w, m_docPrefsData.itemToolPrefs.imageFillColor, m_docPrefsData.itemToolPrefs.imageStrokeColor);
+			newItem = new PageItem_LatexFrame(this, x, y, b, h, w, m_docPrefsData.itemToolPrefs.imageFillColor, m_docPrefsData.itemToolPrefs.imageStrokeColor, nameTiming);
 //			Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Unspecified);
 			break;
 #ifdef HAVE_OSG
 		case PageItem::OSGFrame:
-			newItem = new PageItem_OSGFrame(this, x, y, b, h, w, m_docPrefsData.itemToolPrefs.imageFillColor, m_docPrefsData.itemToolPrefs.imageStrokeColor);
+			newItem = new PageItem_OSGFrame(this, x, y, b, h, w, m_docPrefsData.itemToolPrefs.imageFillColor, m_docPrefsData.itemToolPrefs.imageStrokeColor, nameTiming);
 //			Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Unspecified);
 			break;
 #endif
 		case PageItem::Symbol:
-			newItem = new PageItem_Symbol(this, x, y, b, h, w, CommonStrings::None, CommonStrings::None);
+			newItem = new PageItem_Symbol(this, x, y, b, h, w, CommonStrings::None, CommonStrings::None, nameTiming);
 //			Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Unspecified);
 			break;
 		case PageItem::Group:
-			newItem = new PageItem_Group(this, x, y, b, h, w, CommonStrings::None, CommonStrings::None);
+			newItem = new PageItem_Group(this, x, y, b, h, w, CommonStrings::None, CommonStrings::None, nameTiming);
 //			Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Unspecified);
 			break;
 		case PageItem::RegularPolygon:
-			newItem = new PageItem_RegularPolygon(this, x, y, b, h, w, fill, outline);
+			newItem = new PageItem_RegularPolygon(this, x, y, b, h, w, fill, outline, nameTiming);
 //			Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Ellipse || frameType==PageItem::Unspecified);
 			break;
 		case PageItem::Arc:
-			newItem = new PageItem_Arc(this, x, y, b, h, w, fill, outline);
+			newItem = new PageItem_Arc(this, x, y, b, h, w, fill, outline, nameTiming);
 //			Q_ASSERT(frameType==PageItem::Rectangle || frameType==PageItem::Ellipse || frameType==PageItem::Unspecified);
 			break;
 		case PageItem::Spiral:
-			newItem = new PageItem_Spiral(this, x, y, b, h, w, fill, outline);
+			newItem = new PageItem_Spiral(this, x, y, b, h, w, fill, outline, nameTiming);
 //			Q_ASSERT(frameType==PageItem::Unspecified);
 			break;
 		default:
@@ -5238,6 +5248,16 @@ PageItem* ScribusDoc::createPageItem(const PageItem::ItemType itemType, const Pa
 }
 
 int ScribusDoc::itemAdd(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline, PageItem::ItemKind itemKind)
+{
+  return implItemAdd(itemType,frameType, x, y, b, h, w, fill, outline, itemKind, PageItem::NameTiming::Direct);
+}
+
+int ScribusDoc::itemAddDeferred(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline, PageItem::ItemKind itemKind)
+{
+  return implItemAdd(itemType,frameType, x, y, b, h, w, fill, outline, itemKind, PageItem::NameTiming::Deferred);
+}
+
+int ScribusDoc::implItemAdd(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline, PageItem::ItemKind itemKind, PageItem::NameTiming nameTiming)
 {
 	UndoTransaction activeTransaction;
 	if (UndoManager::undoEnabled()) // && !m_itemCreationTransaction)
@@ -5252,7 +5272,7 @@ int ScribusDoc::itemAdd(const PageItem::ItemType itemType, const PageItem::ItemF
 		itemAddDetails(PageItem::TextFrame, frameType, newItem);
 	}
 	else
-		newItem = createPageItem(itemType, frameType, x, y, b, h, w, fill, outline); 
+		newItem = implCreatePageItem(itemType, frameType, x, y, b, h, w, fill, outline, nameTiming); 
 	
 	Q_CHECK_PTR(newItem);
 	if (newItem == nullptr)
@@ -14797,6 +14817,16 @@ void ScribusDoc::scaleGroup(double scx, double scy, bool scaleText, Selection* c
 }
 
 PageItem* ScribusDoc::groupObjectsSelection(Selection* customSelection)
+{
+  return implGroupObjectsSelection(customSelection, PageItem::NameTiming::Direct);
+}
+
+PageItem* ScribusDoc::groupObjectsSelectionDeferred(Selection* customSelection)
+{
+  return implGroupObjectsSelection(customSelection, PageItem::NameTiming::Deferred);
+}
+
+PageItem* ScribusDoc::implGroupObjectsSelection(Selection* customSelection, PageItem::NameTiming nameTiming)
 {
 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
 	if (itemSelection->count() < 1)
@@ -14836,10 +14866,12 @@ PageItem* ScribusDoc::groupObjectsSelection(Selection* customSelection)
 	double gy = miny;
 	double gw = maxx - minx;
 	double gh = maxy - miny;
-	int z = itemAdd(PageItem::Group, PageItem::Rectangle, gx, gy, gw, gh, 0, CommonStrings::None, CommonStrings::None);
+	int z = implItemAdd(PageItem::Group, PageItem::Rectangle, gx, gy, gw, gh, 0, CommonStrings::None, CommonStrings::None, PageItem::StandardItem, nameTiming);
 	PageItem *groupItem = Items->takeAt(z);
 	Items->insert(lowestItem, groupItem);
-	groupItem->setItemName( tr("Group%1").arg(GroupCounter));
+  if (nameTiming == PageItem::NameTiming::Direct) {
+    groupItem->setItemName( tr("Group%1").arg(GroupCounter));
+  }
 	groupItem->AutoName = false;
 	groupItem->groupWidth = gw;
 	groupItem->groupHeight = gh;
diff --git a/scribus/scribusdoc.h b/scribus/scribusdoc.h
index 7300113..9894bb8 100644
--- a/scribus/scribusdoc.h
+++ b/scribus/scribusdoc.h
@@ -821,6 +821,9 @@ public:
 	 * @brief Just create but don't add to items list and don't create undo record
 	 */
 	PageItem* createPageItem(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline);
+
+	PageItem* createPageItemDeferred(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline);
+
 	
 	/**
 	 * @brief Add an Item to the document.
@@ -842,6 +845,8 @@ public:
 	*/
 	int itemAdd(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline, PageItem::ItemKind itemKind = PageItem::StandardItem);
 
+	int itemAddDeferred(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline, PageItem::ItemKind itemKind = PageItem::StandardItem);
+
 	/** Add an item to the page based on the x/y position. Item will be fitted to the closest guides/margins */
 	int itemAddArea(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double w, const QString& fill, const QString& outline, PageItem::ItemKind itemKind = PageItem::StandardItem);
 	
@@ -1094,6 +1099,7 @@ public:
 
 	QList<PageItem*>* groupOfItem(QList<PageItem*>* itemList, PageItem* item);
 	PageItem* groupObjectsSelection(Selection* customSelection = nullptr);
+	PageItem* groupObjectsSelectionDeferred(Selection* customSelection = nullptr);
 	PageItem* groupObjectsList(QList<PageItem*> &itemList);
 	void groupObjectsToItem(PageItem* groupItem, QList<PageItem*> &itemList);
 	PageItem * itemSelection_GroupObjects  (bool changeLock, bool lock, Selection* customSelection = nullptr, PageItem_Group* groupItem = nullptr);
@@ -1763,6 +1769,10 @@ private:
 
 	void multipleDuplicateByPage(const ItemMultipleDuplicateData& mdData, Selection& selection, QString& tooltip);
 
+	int implItemAdd(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline, PageItem::ItemKind itemKind, PageItem::NameTiming nameTiming);
+	PageItem* implCreatePageItem(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline, PageItem::NameTiming nameTiming);
+	PageItem* implGroupObjectsSelection(Selection* customSelection, PageItem::NameTiming nameTiming);
+
 public:
 	const QList<Mark*>& marksList() { return m_docMarksList; }
 	const QList<TextNote*>& notesList() { return m_docNotesList; }
-- 
2.38.1

ale

2022-11-22 07:09

manager   ~0049812

i wonder if it would not be easier to separate the value the user can set (scripter included), from the value that scribus is using internally.

then you can simply use a counter (and even have slices of future ids allocated by different threads) and not worry about collisions at all.

fsimonis

2022-11-22 10:04

reporter   ~0049813

I considered this as well, however, I am not sure how these names are linked to the file format. The last thing I want to do is to break the compatibility of saves.
So, I decided to keep the PageItem representation largely untouched for this prototype.

I am sceptic if using IDs will solve this issue though. The problem of requiring unique names will persist. No matter what naming strategy one chooses, the user can always manually create naming collisions.
My gut feeling tells me that removing names altogether will be the long-term solution here. No names, no need to keep them unique.

ale

2022-11-22 11:59

manager   ~0049814

if scribus is the unique creator of the item names it uses internally, then it can keep an internal counter, stored in the document, and track the latest created value.

it's almost the same as scribus does right now.
the difference being that, then, scribus can be sure that the newly created item name is free to be used, without any need to check for it.
just like databases do with auto increment fields.

users can then query the item name and use it to manipulate the document in scripts, but not change it.
since some users love using specific names for some items, it should be possible to define a second optional field with a user defined item name. scribus does not even need (but can) make sure that those names are unique.

it's probably a bit more work to get there, than what you did in your patch.
but (i hope) it can lead to less and simpler code in the long term.
and also faster code.

imo, the current move to scribus 1.7 could be the right time to make such a change (since almost nobody is already using 1.7)

i could help defining the scope / details of such a project, but i'm not sure that, right now, i'm in for the programming part.

fsimonis

2022-11-22 16:57

reporter   ~0049815

If scribus uses unique ids instead of names would simplify this a lot.

This will make the API a bit confusing though as addItem already returns the "number" of the added item.

As far I can tell, there are various ways of referring to items in the API:
* the "number" returned by itemAdd()
* the PageItem* returned by createItem(), referred to by doc.Items->at("number") and used inside groups
* the name, used by scripters and ui elements

I find this rather confusing as is and one additional way of referring to PageItems won't help. ;)

Anyhow, I am happy to (re)dive into the code if you define the API and general scope.

ale

2022-11-24 07:13

manager   ~0049816

i'll try to work on something.

feedback from jean or craig is also welcome.

fsimonis

2023-11-18 13:10

reporter   ~0050483

FYI, I recently updated the patch to the current version and uploaded it to this note to keep this somewhat up-to-date.

Furthermore, I'll keep a working version at https://github.com/fsimonis/scribus/tree/bulkadder together with some other patches.
I update it whenever I need this feature again.
0001-Add-deferred-naming-and-bulkadder-2.patch (64,422 bytes)   
From 0abc3a3b5b8e5afe1804a71953080081a3473b10 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Simonis?= <simonisfrederic@gmail.com>
Date: Sun, 20 Nov 2022 14:06:19 +0100
Subject: [PATCH] Add deferred naming and bulkadder

---
 scribus/CMakeLists_Sources.txt           |   1 +
 scribus/bulkadder.cpp                    | 108 +++++++++++++++++++++++
 scribus/bulkadder.h                      |  53 +++++++++++
 scribus/pageitem.cpp                     |  85 +++++++++++++-----
 scribus/pageitem.h                       |  11 +++
 scribus/pageitem_arc.cpp                 |   4 +
 scribus/pageitem_arc.h                   |   1 +
 scribus/pageitem_group.cpp               |   5 ++
 scribus/pageitem_group.h                 |   1 +
 scribus/pageitem_imageframe.cpp          |   7 +-
 scribus/pageitem_imageframe.h            |   1 +
 scribus/pageitem_latexframe.cpp          |   6 +-
 scribus/pageitem_latexframe.h            |   1 +
 scribus/pageitem_line.cpp                |   5 ++
 scribus/pageitem_line.h                  |   1 +
 scribus/pageitem_noteframe.cpp           |  14 ++-
 scribus/pageitem_noteframe.h             |   5 ++
 scribus/pageitem_osgframe.cpp            |   5 +-
 scribus/pageitem_osgframe.h              |   1 +
 scribus/pageitem_pathtext.cpp            |   6 +-
 scribus/pageitem_pathtext.h              |   1 +
 scribus/pageitem_polygon.cpp             |   5 ++
 scribus/pageitem_polygon.h               |   1 +
 scribus/pageitem_polyline.cpp            |   5 ++
 scribus/pageitem_polyline.h              |   1 +
 scribus/pageitem_regularpolygon.cpp      |   5 +-
 scribus/pageitem_regularpolygon.h        |   1 +
 scribus/pageitem_spiral.cpp              |   5 +-
 scribus/pageitem_spiral.h                |   1 +
 scribus/pageitem_symbol.cpp              |   5 ++
 scribus/pageitem_symbol.h                |   1 +
 scribus/pageitem_table.cpp               |   7 +-
 scribus/pageitem_table.h                 |   1 +
 scribus/pageitem_textframe.cpp           |   8 +-
 scribus/pageitem_textframe.h             |   1 +
 scribus/plugins/import/pdf/slaoutput.cpp |  44 ++++-----
 scribus/plugins/import/pdf/slaoutput.h   |   2 +
 scribus/scribusdoc.cpp                   |  66 ++++++++++----
 scribus/scribusdoc.h                     |  10 +++
 40 files changed, 417 insertions(+), 76 deletions(-)
 create mode 100644 scribus/bulkadder.cpp
 create mode 100644 scribus/bulkadder.h

diff --git a/scribus/CMakeLists_Sources.txt b/scribus/CMakeLists_Sources.txt
index 5da6c19..4a9ed9f 100644
--- a/scribus/CMakeLists_Sources.txt
+++ b/scribus/CMakeLists_Sources.txt
@@ -25,6 +25,7 @@ set(SCRIBUS_SOURCES
 	actionmanager.cpp
 	actionsearch.cpp
 	appmodehelper.cpp
+  bulkadder.cpp
 	canvas.cpp
 	canvasgesture_cellselect.cpp
 	canvasgesture_columnresize.cpp
diff --git a/scribus/bulkadder.cpp b/scribus/bulkadder.cpp
new file mode 100644
index 0000000..512ee2e
--- /dev/null
+++ b/scribus/bulkadder.cpp
@@ -0,0 +1,108 @@
+/*
+For general Scribus (>=1.3.2) copyright and licensing information please refer
+to the COPYING file provided with the program. Following this notice may exist
+a copyright and/or license notice that predates the release of Scribus 1.3.2
+for which a new license (GPL+exception) is in place.
+*/
+/***************************************************************************
+ *   Copyright (C) 2005 by Riku Leino                                      *
+ *   riku@scribus.info                                                     *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.             *
+ ***************************************************************************/
+
+#include <set>
+#include <map>
+
+#include "bulkadder.h"
+
+namespace {
+void findName(PageItem *item, std::set<QString> &names,
+              std::map<PageItem::ItemType, int> &lastSuccess) {
+  auto type = item->itemType();
+  QString baseName = item->nameFromType(type);
+
+  int nameNum = lastSuccess[type];
+  QString tmp;
+  tmp.setNum(nameNum);
+  tmp.prepend(baseName);
+  while (names.count(tmp) != 0) {
+    ++nameNum;
+    tmp.setNum(nameNum);
+    tmp.prepend(baseName);
+  }
+  lastSuccess[type] = nameNum;
+  names.insert(tmp);
+  item->setSafeItemName(tmp);
+}
+
+std::set<QString> gatherNames(ScribusDoc *doc) {
+  std::set<QString> names;
+  std::vector<PageItem *> groups;
+  groups.reserve(32);
+
+  // Process root elements of the doc and remember groups
+  for (PageItem *item : *doc->Items) {
+    names.insert(item->itemName());
+    if (item->isGroup())
+      groups.push_back(item);
+  }
+
+  // Process groups
+  while (!groups.empty()) {
+    PageItem *item = groups.back();
+    groups.pop_back();
+    for (PageItem *item : item->groupItemList) {
+      names.insert(item->itemName());
+      if (item->isGroup())
+        groups.push_back(item);
+    }
+  }
+  return names;
+}
+} // namespace
+
+int BulkAdder::itemAdd(const PageItem::ItemType itemType,
+                       const PageItem::ItemFrameType frameType, double x,
+                       double y, double b, double h, double w,
+                       const QString &fill, const QString &outline,
+                       PageItem::ItemKind itemKind) {
+  int id = m_doc->itemAddDeferred(itemType, frameType, x, y, b, h, w, fill,
+                                  outline, itemKind);
+  m_pending.push_back(m_doc->Items->at(id));
+  return id;
+}
+
+
+PageItem* BulkAdder::groupObjectsSelection(Selection* customSelection)
+{
+  auto group = m_doc->groupObjectsSelectionDeferred(customSelection);
+  m_pending.push_back(group);
+  return group;
+}
+
+void BulkAdder::process() {
+  if (m_pending.empty()) {
+    return;
+  }
+
+  auto names = gatherNames(m_doc);
+  std::map<PageItem::ItemType, int> lastSuccess;
+  for (auto item : m_pending) {
+    findName(item, names, lastSuccess);
+  }
+  m_pending.clear();
+}
diff --git a/scribus/bulkadder.h b/scribus/bulkadder.h
new file mode 100644
index 0000000..2d630cd
--- /dev/null
+++ b/scribus/bulkadder.h
@@ -0,0 +1,53 @@
+/*
+For general Scribus (>=1.3.2) copyright and licensing information please refer
+to the COPYING file provided with the program. Following this notice may exist
+a copyright and/or license notice that predates the release of Scribus 1.3.2
+for which a new license (GPL+exception) is in place.
+*/
+/***************************************************************************
+ *   Copyright (C) 2005 by Riku Leino                                      *
+ *   riku@scribus.info                                                     *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.             *
+ ***************************************************************************/
+
+#ifndef BULKADDER_H
+#define BULKADDER_H
+
+#include "pageitem.h"
+#include "scribusdoc.h"
+#include "scribusapi.h"
+
+class SCRIBUS_API BulkAdder {
+  public:
+    BulkAdder(ScribusDoc * document) : m_doc(document) {};
+
+    ~BulkAdder() {
+      process();
+    };
+
+    int itemAdd(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline, PageItem::ItemKind itemKind = PageItem::StandardItem);
+
+	  PageItem* groupObjectsSelection(Selection* customSelection = nullptr);
+
+    void process();
+
+  private:
+    ScribusDoc *  m_doc;
+    std::vector<PageItem*> m_pending;
+};
+
+#endif
diff --git a/scribus/pageitem.cpp b/scribus/pageitem.cpp
index 0bc2596..0f56fde 100644
--- a/scribus/pageitem.cpp
+++ b/scribus/pageitem.cpp
@@ -376,6 +376,9 @@ PageItem::PageItem(const PageItem & other)
 
 
 PageItem::PageItem(ScribusDoc *doc, ItemType newType, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
+ : PageItem(doc, newType, x, y, w, h, w2, fill, outline, NameTiming::Direct){};
+
+PageItem::PageItem(ScribusDoc *doc, ItemType newType, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
 	// Initialize superclass(es)
 	: QObject(doc), SingleObservable<PageItem>(doc->itemsChanged()), TextContext(this),
 	// Initialize member variables
@@ -435,70 +438,64 @@ PageItem::PageItem(ScribusDoc *doc, ItemType newType, double x, double y, double
 			// because c++'s typeinfos are still saying it's
 			// a plain pageitem
 			// This is fixed in the PageItem_LatexFrame constructor
-			m_itemName = tr("Image");
 			setUPixmap(Um::IImageFrame);
 			break;
 		case TextFrame:
-			m_itemName = tr("Text");
 			setUPixmap(Um::ITextFrame);
 			break;
 		case Line:
-			m_itemName = tr("Line");
 			setUPixmap(Um::ILine);
 			break;
 		case Polygon:
-			m_itemName = tr("Polygon");
 			setUPixmap(Um::IPolygon);
 			break;
 		case PolyLine:
-			m_itemName = tr("Polyline");
 			setUPixmap(Um::IPolyline);
 			break;
 		case PathText:
-			m_itemName = tr("PathText");
 			setUPixmap(Um::IPathText);
 			break;
 		case Symbol:
-			m_itemName = tr("Symbol");
 			setUPixmap(Um::IPolygon);
 			break;
 		case Group:
-			m_itemName = tr("Group");
 			setUPixmap(Um::IPolygon);
 			break;
 		case RegularPolygon:
-			m_itemName = tr("RegularPolygon");
 			setUPixmap(Um::IPolygon);
 			break;
 		case Arc:
-			m_itemName = tr("Arc");
 			setUPixmap(Um::IPolygon);
 			break;
 		case Spiral:
-			m_itemName = tr("Spiral");
 			setUPixmap(Um::IPolygon);
 			break;
 		case Table:
-			m_itemName = tr("Table");
 			//setUPixmap(Um::IPolygon); // TODO: Fix this.
 			break;
 		default:
-			m_itemName = "Item";
 			break;
 	}
 	m_Doc->TotalItems++;
+
+  if (nameTiming == NameTiming::Deferred) {
+    // It is the callers responsibilty to create a usable name
+    m_itemName = "pending";
+  } else {
+    m_itemName = nameFromType(m_itemType);
 	
-	QString oldName(m_itemName);
-	int nameNum = m_Doc->TotalItems;
-	m_itemName += tmp.setNum(m_Doc->TotalItems);
-	while (m_Doc->itemNameExists(m_itemName))
-	{
-		++nameNum;
-		m_itemName = oldName + tmp.setNum(nameNum);
-	}
+    QString oldName(m_itemName);
+    int nameNum = m_Doc->TotalItems;
+    m_itemName += tmp.setNum(m_Doc->TotalItems);
+    while (m_Doc->itemNameExists(m_itemName))
+    {
+      ++nameNum;
+      m_itemName = oldName + tmp.setNum(nameNum);
+    }
 	
-	uniqueNr = m_Doc->TotalItems;
-	setUName(m_itemName);
+    //uniqueNr = m_Doc->TotalItems;
+    setUName(m_itemName);
+  }
 	m_annotation.setBorderColor(outline);
 
 	ImageIntent = Intent_Relative_Colorimetric;
@@ -703,6 +700,39 @@ PageItem::~PageItem()
 //			unWeldChild();
 }
 
+QString PageItem::nameFromType(ItemType type) {
+  switch (type) {
+    case ImageFrame:
+    case OSGFrame:
+    case LatexFrame:
+      return tr("Image");
+    case TextFrame:
+      return tr("Text");
+    case Line:
+      return tr("Line");
+    case Polygon:
+      return tr("Polygon");
+    case PolyLine:
+      return tr("Polyline");
+    case PathText:
+      return tr("PathText");
+    case Symbol:
+      return tr("Symbol");
+    case Group:
+      return tr("Group");
+    case RegularPolygon:
+      return tr("RegularPolygon");
+    case Arc:
+      return tr("Arc");
+    case Spiral:
+      return tr("Spiral");
+    case Table:
+      return tr("Table");
+    default:
+      return "Item";
+  }
+}
+
 bool PageItem::isMasterItem() const
 {
 	if (Parent == nullptr)
@@ -2385,6 +2415,15 @@ void PageItem::DrawPolyL(QPainter *p, const QPolygon& pts)
 	p->drawPolygon(pts.constData() + firstVal, pts.size() - firstVal);
 }
 
+void PageItem::setSafeItemName(const QString& uniqueName)
+{
+	if (m_itemName == uniqueName || uniqueName.isEmpty())
+		return;
+
+  m_itemName = uniqueName;
+	setUName(m_itemName);
+}
+
 void PageItem::setItemName(const QString& newName)
 {
 	if (m_itemName == newName || newName.isEmpty())
diff --git a/scribus/pageitem.h b/scribus/pageitem.h
index 780dcc5..2dbd4d7 100644
--- a/scribus/pageitem.h
+++ b/scribus/pageitem.h
@@ -39,6 +39,7 @@ for which a new license (GPL+exception) is in place.
 #include <QVector>
 #include <QTemporaryFile>
 
+#include "deferredtask.h"
 #include "scribusapi.h"
 #include "annotation.h"
 #include "commonstrings.h"
@@ -221,6 +222,11 @@ public:	// Start enumerator definitions
 		Round		= 2,
 		Other		= 3
 	};
+
+  enum struct NameTiming : bool {
+    Direct,
+    Deferred
+  };
 		//End enumerator definitions
 
 	// This property may not hang around for too long, but should be useful
@@ -236,6 +242,7 @@ public:	// Start enumerator definitions
 public: // Start public functions
 
 	PageItem(ScribusDoc *doc, ItemType newType, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+	PageItem(ScribusDoc *doc, ItemType newType, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	~PageItem() override;
 
 	/* these do essentially the same as a dynamic cast but might be more readable */
@@ -833,6 +840,8 @@ public: // Start public functions
 	 */
 	void setItemName(const QString& newName);
 
+	void setSafeItemName(const QString& uniqueName);
+
 	/**
 	* @brief Set the masterpage the object is on
 	* @param mpName name of the master page
@@ -1289,6 +1298,8 @@ public: // Start public functions
 	bool hasFill() { return ((fillColor() != CommonStrings::None) || (GrType != 0)); }
 	bool hasStroke() { return ((lineColor() != CommonStrings::None) || (GrTypeStroke != 0) || (!NamedLStyle.isEmpty()) || (!patternStrokeVal.isEmpty())); }
 
+  QString nameFromType(ItemType type);
+
 		// End public functions
 
 public:	// Start public variables
diff --git a/scribus/pageitem_arc.cpp b/scribus/pageitem_arc.cpp
index 2b17717..e53efdd 100644
--- a/scribus/pageitem_arc.cpp
+++ b/scribus/pageitem_arc.cpp
@@ -21,6 +21,7 @@ for which a new license (GPL+exception) is in place.
  *                                                                         *
  ***************************************************************************/
 
+#include <fcntl.h>
 #if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES)
 #define _USE_MATH_DEFINES
 #endif
@@ -47,6 +48,9 @@ for which a new license (GPL+exception) is in place.
 using namespace std;
 
 PageItem_Arc::PageItem_Arc(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
+	: PageItem_Arc(pa, x, y, w, h, w2, fill, outline, NameTiming::Direct){};
+
+PageItem_Arc::PageItem_Arc(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
 	: PageItem(pa, PageItem::Arc, x, y, w, h, w2, fill, outline)
 {
 	arcHeight = h;
diff --git a/scribus/pageitem_arc.h b/scribus/pageitem_arc.h
index 5f94fcf..b89b05f 100644
--- a/scribus/pageitem_arc.h
+++ b/scribus/pageitem_arc.h
@@ -37,6 +37,7 @@ class SCRIBUS_API PageItem_Arc : public PageItem
 
 public:
 	PageItem_Arc(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+	PageItem_Arc(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	PageItem_Arc(const PageItem& p);
 	~PageItem_Arc() {};
 
diff --git a/scribus/pageitem_group.cpp b/scribus/pageitem_group.cpp
index c5b1590..622383c 100644
--- a/scribus/pageitem_group.cpp
+++ b/scribus/pageitem_group.cpp
@@ -52,6 +52,11 @@ PageItem_Group::PageItem_Group(ScribusDoc *pa, double x, double y, double w, dou
 {
 }
 
+PageItem_Group::PageItem_Group(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem(pa, PageItem::Group, x, y, w, h, 0, CommonStrings::None, CommonStrings::None, nameTiming)
+{
+}
+
 PageItem_Group::~PageItem_Group()
 {
 //	while (!groupItemList.isEmpty())
diff --git a/scribus/pageitem_group.h b/scribus/pageitem_group.h
index 4a66413..3045f3c 100644
--- a/scribus/pageitem_group.h
+++ b/scribus/pageitem_group.h
@@ -37,6 +37,7 @@ class SCRIBUS_API PageItem_Group : public PageItem
 
 public:
 	PageItem_Group(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+	PageItem_Group(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	PageItem_Group(const PageItem & p) : PageItem(p) {}
 	~PageItem_Group();
 
diff --git a/scribus/pageitem_imageframe.cpp b/scribus/pageitem_imageframe.cpp
index af9679c..9421728 100644
--- a/scribus/pageitem_imageframe.cpp
+++ b/scribus/pageitem_imageframe.cpp
@@ -55,8 +55,13 @@ for which a new license (GPL+exception) is in place.
 #include "util.h"
 
 
+PageItem_ImageFrame::PageItem_ImageFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem(pa, PageItem::ImageFrame, x, y, w, h, w2, fill, outline, nameTiming)
+{
+}
+
 PageItem_ImageFrame::PageItem_ImageFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
-	: PageItem(pa, PageItem::ImageFrame, x, y, w, h, w2, fill, outline)
+	: PageItem(pa, PageItem::ImageFrame, x, y, w, h, w2, fill, outline, NameTiming::Direct)
 {
 }
 
diff --git a/scribus/pageitem_imageframe.h b/scribus/pageitem_imageframe.h
index 9cb065b..877edce 100644
--- a/scribus/pageitem_imageframe.h
+++ b/scribus/pageitem_imageframe.h
@@ -37,6 +37,7 @@ class SCRIBUS_API PageItem_ImageFrame : public PageItem
 
 public:
 	PageItem_ImageFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+	PageItem_ImageFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	PageItem_ImageFrame(const PageItem & p) : PageItem(p) {}
 	~PageItem_ImageFrame();
 
diff --git a/scribus/pageitem_latexframe.cpp b/scribus/pageitem_latexframe.cpp
index 633f04a..6aafee6 100644
--- a/scribus/pageitem_latexframe.cpp
+++ b/scribus/pageitem_latexframe.cpp
@@ -41,7 +41,11 @@ for which a new license (GPL+exception) is in place.
 #include "util.h"
 
 PageItem_LatexFrame::PageItem_LatexFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
-		: PageItem_ImageFrame(pa, x, y, w, h, w2, fill, outline)
+		: PageItem_LatexFrame(pa, x, y, w, h, w2, fill, outline, NameTiming::Direct)
+{}
+
+PageItem_LatexFrame::PageItem_LatexFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+		: PageItem_ImageFrame(pa, x, y, w, h, w2, fill, outline, nameTiming)
 {
 	setUPixmap(Um::ILatexFrame);
 	m_itemName = tr("Render") + QString::number(m_Doc->TotalItems);
diff --git a/scribus/pageitem_latexframe.h b/scribus/pageitem_latexframe.h
index 5196655..7da6cca 100644
--- a/scribus/pageitem_latexframe.h
+++ b/scribus/pageitem_latexframe.h
@@ -46,6 +46,7 @@ class SCRIBUS_API PageItem_LatexFrame : public PageItem_ImageFrame
 
 	public:
 		PageItem_LatexFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+		PageItem_LatexFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 		~PageItem_LatexFrame();
 		
 		PageItem_LatexFrame * asLatexFrame() override { return this; }
diff --git a/scribus/pageitem_line.cpp b/scribus/pageitem_line.cpp
index e3b9cef..9c38a4c 100644
--- a/scribus/pageitem_line.cpp
+++ b/scribus/pageitem_line.cpp
@@ -52,6 +52,11 @@ PageItem_Line::PageItem_Line(ScribusDoc *pa, double x, double y, double w, doubl
 {
 }
 
+PageItem_Line::PageItem_Line(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem(pa, PageItem::Line, x, y, w, h, w2, fill, outline, nameTiming)
+{
+}
+
 void PageItem_Line::DrawObj_Item(ScPainter *p, const QRectF& /*e*/)
 {
 	if (m_Doc->RePos)
diff --git a/scribus/pageitem_line.h b/scribus/pageitem_line.h
index 28fdaf9..cdf59fc 100644
--- a/scribus/pageitem_line.h
+++ b/scribus/pageitem_line.h
@@ -37,6 +37,7 @@ class SCRIBUS_API PageItem_Line : public PageItem
 
 public:
 	PageItem_Line(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+	PageItem_Line(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	PageItem_Line(const PageItem & p) : PageItem(p) {}
 	~PageItem_Line() {};
 	
diff --git a/scribus/pageitem_noteframe.cpp b/scribus/pageitem_noteframe.cpp
index 51b0f8e..f217d35 100644
--- a/scribus/pageitem_noteframe.cpp
+++ b/scribus/pageitem_noteframe.cpp
@@ -16,7 +16,10 @@
 #include "text/boxes.h"
 
 PageItem_NoteFrame::PageItem_NoteFrame(NotesStyle *nStyle, ScribusDoc *doc, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
-	: PageItem_TextFrame(doc, x, y, w, h, w2, fill, outline)
+  : PageItem_NoteFrame(nStyle, doc, x, y, w, h, w2, fill, outline, NameTiming::Direct) {}
+
+PageItem_NoteFrame::PageItem_NoteFrame(NotesStyle *nStyle, ScribusDoc *doc, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem_TextFrame(doc, x, y, w, h, w2, fill, outline, nameTiming)
 {
 	m_nstyle = nStyle;
 	itemText.clear();
@@ -44,12 +47,17 @@ PageItem_NoteFrame::PageItem_NoteFrame(NotesStyle *nStyle, ScribusDoc *doc, doub
 }
 
 PageItem_NoteFrame::PageItem_NoteFrame(ScribusDoc *doc, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
-	: PageItem_TextFrame(doc, x, y, w, h, w2, fill, outline)
+	: PageItem_NoteFrame(doc, x, y, w, h, w2, fill, outline, NameTiming::Direct) {}
+
+PageItem_NoteFrame::PageItem_NoteFrame(ScribusDoc *doc, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem_TextFrame(doc, x, y, w, h, w2, fill, outline, nameTiming)
 {
 	m_textFlowMode = TextFlowUsesFrameShape;
 }
 
-PageItem_NoteFrame::PageItem_NoteFrame(PageItem_TextFrame* inFrame, NotesStyle *nStyle) : PageItem_TextFrame(inFrame->doc(),inFrame->xPos(), inFrame->yPos(),inFrame->width(), inFrame->height(),inFrame->lineWidth(), inFrame->fillColor(), inFrame->lineColor())
+PageItem_NoteFrame::PageItem_NoteFrame(PageItem_TextFrame* inFrame, NotesStyle *nStyle) : PageItem_NoteFrame(inFrame, nStyle, NameTiming::Direct) {};
+
+PageItem_NoteFrame::PageItem_NoteFrame(PageItem_TextFrame* inFrame, NotesStyle *nStyle, NameTiming nameTiming) : PageItem_TextFrame(inFrame->doc(),inFrame->xPos(), inFrame->yPos(),inFrame->width(), inFrame->height(),inFrame->lineWidth(), inFrame->fillColor(), inFrame->lineColor(), nameTiming)
 {
 	m_nstyle = nStyle;
 	m_masterFrame = inFrame;
diff --git a/scribus/pageitem_noteframe.h b/scribus/pageitem_noteframe.h
index f583be5..e9b1d77 100644
--- a/scribus/pageitem_noteframe.h
+++ b/scribus/pageitem_noteframe.h
@@ -14,6 +14,11 @@ private:
 	PageItem_NoteFrame(NotesStyle *nStyle, ScribusDoc *doc, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
 	PageItem_NoteFrame(ScribusDoc *doc, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
 	PageItem_NoteFrame(PageItem_TextFrame* inFrame, NotesStyle *nStyle);
+
+	PageItem_NoteFrame(NotesStyle *nStyle, ScribusDoc *doc, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
+	PageItem_NoteFrame(ScribusDoc *doc, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
+	PageItem_NoteFrame(PageItem_TextFrame* inFrame, NotesStyle *nStyle, NameTiming nameTiming);
+
 	~PageItem_NoteFrame() { }
 
 public:
diff --git a/scribus/pageitem_osgframe.cpp b/scribus/pageitem_osgframe.cpp
index 03f46f2..14845c0 100644
--- a/scribus/pageitem_osgframe.cpp
+++ b/scribus/pageitem_osgframe.cpp
@@ -42,7 +42,10 @@ for which a new license (GPL+exception) is in place.
 #include "util.h"
 
 PageItem_OSGFrame::PageItem_OSGFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
-		: PageItem_ImageFrame(pa, x, y, w, h, w2, fill, outline)
+		: PageItem_ImageFrame(pa, x, y, w, h, w2, fill, outline, NameTiming::Direct) {}
+
+PageItem_OSGFrame::PageItem_OSGFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+		: PageItem_ImageFrame(pa, x, y, w, h, w2, fill, outline, nameTiming)
 {
 	setUPixmap(Um::ILatexFrame);
 	m_itemName = tr("OSG") + QString::number(m_Doc->TotalItems);
diff --git a/scribus/pageitem_osgframe.h b/scribus/pageitem_osgframe.h
index f184bef..f08f972 100644
--- a/scribus/pageitem_osgframe.h
+++ b/scribus/pageitem_osgframe.h
@@ -74,6 +74,7 @@ class SCRIBUS_API PageItem_OSGFrame : public PageItem_ImageFrame
 			ShadedIllustration				= 14
 		};
 		PageItem_OSGFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+		PageItem_OSGFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 		~PageItem_OSGFrame();
 		
 		PageItem_OSGFrame * asOSGFrame() override { return this; }
diff --git a/scribus/pageitem_pathtext.cpp b/scribus/pageitem_pathtext.cpp
index 534bc57..1fce474 100644
--- a/scribus/pageitem_pathtext.cpp
+++ b/scribus/pageitem_pathtext.cpp
@@ -54,7 +54,11 @@ for which a new license (GPL+exception) is in place.
 using namespace std;
 
 PageItem_PathText::PageItem_PathText(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
-	: PageItem(pa, PageItem::PathText, x, y, w, h, w2, fill, outline)
+	: PageItem_PathText(pa, x, y, w, h, w2, fill, outline, NameTiming::Direct) {};
+
+
+PageItem_PathText::PageItem_PathText(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem(pa, PageItem::PathText, x, y, w, h, w2, fill, outline, nameTiming)
 {
 	firstChar = 0;
 	m_maxChars = itemText.length();
diff --git a/scribus/pageitem_pathtext.h b/scribus/pageitem_pathtext.h
index d5ae975..272586b 100644
--- a/scribus/pageitem_pathtext.h
+++ b/scribus/pageitem_pathtext.h
@@ -36,6 +36,7 @@ class SCRIBUS_API PageItem_PathText : public PageItem
 
 public:
 	PageItem_PathText(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+	PageItem_PathText(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	PageItem_PathText(const PageItem & p) : PageItem(p) {}
 	~PageItem_PathText() {};
 	
diff --git a/scribus/pageitem_polygon.cpp b/scribus/pageitem_polygon.cpp
index 87c7023..aee8948 100644
--- a/scribus/pageitem_polygon.cpp
+++ b/scribus/pageitem_polygon.cpp
@@ -48,6 +48,11 @@ PageItem_Polygon::PageItem_Polygon(ScribusDoc *pa, double x, double y, double w,
 {
 }
 
+PageItem_Polygon::PageItem_Polygon(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem(pa, PageItem::Polygon, x, y, w, h, w2, fill, outline, nameTiming)
+{
+}
+
 void PageItem_Polygon::DrawObj_Item(ScPainter *p, const QRectF& /*e*/)
 {
 	if (!m_Doc->RePos)
diff --git a/scribus/pageitem_polygon.h b/scribus/pageitem_polygon.h
index 62cbec4..8f065e4 100644
--- a/scribus/pageitem_polygon.h
+++ b/scribus/pageitem_polygon.h
@@ -37,6 +37,7 @@ class SCRIBUS_API PageItem_Polygon : public PageItem
 
 public:
 	PageItem_Polygon(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+	PageItem_Polygon(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	PageItem_Polygon(const PageItem & p) : PageItem(p) {}
 	~PageItem_Polygon() {};
 
diff --git a/scribus/pageitem_polyline.cpp b/scribus/pageitem_polyline.cpp
index 49d3445..97e71a7 100644
--- a/scribus/pageitem_polyline.cpp
+++ b/scribus/pageitem_polyline.cpp
@@ -51,6 +51,11 @@ PageItem_PolyLine::PageItem_PolyLine(ScribusDoc *pa, double x, double y, double
 {
 }
 
+PageItem_PolyLine::PageItem_PolyLine(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem(pa, PageItem::PolyLine, x, y, w, h, w2, fill, outline, nameTiming)
+{
+}
+
 void PageItem_PolyLine::DrawObj_Item(ScPainter *p, const QRectF& /*e*/)
 {
 	if (m_Doc->RePos || PoLine.size() < 4)
diff --git a/scribus/pageitem_polyline.h b/scribus/pageitem_polyline.h
index 9e8bf26..8344c39 100644
--- a/scribus/pageitem_polyline.h
+++ b/scribus/pageitem_polyline.h
@@ -36,6 +36,7 @@ class SCRIBUS_API PageItem_PolyLine : public PageItem
 
 public:
 	PageItem_PolyLine(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+	PageItem_PolyLine(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	PageItem_PolyLine(const PageItem & p) : PageItem(p) {}
 	~PageItem_PolyLine() {};
 	
diff --git a/scribus/pageitem_regularpolygon.cpp b/scribus/pageitem_regularpolygon.cpp
index 2494757..49076f6 100644
--- a/scribus/pageitem_regularpolygon.cpp
+++ b/scribus/pageitem_regularpolygon.cpp
@@ -48,7 +48,10 @@ for which a new license (GPL+exception) is in place.
 using namespace std;
 
 PageItem_RegularPolygon::PageItem_RegularPolygon(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
-	: PageItem(pa, PageItem::RegularPolygon, x, y, w, h, w2, fill, outline)
+	: PageItem_RegularPolygon(pa, x, y, w, h, w2, fill, outline, NameTiming::Direct) {}
+
+PageItem_RegularPolygon::PageItem_RegularPolygon(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem(pa, PageItem::RegularPolygon, x, y, w, h, w2, fill, outline, nameTiming)
 {
 	polyCorners = m_Doc->itemToolPrefs().polyCorners;
 	polyFactor = m_Doc->itemToolPrefs().polyFactor;
diff --git a/scribus/pageitem_regularpolygon.h b/scribus/pageitem_regularpolygon.h
index e55cf45..1d36248 100644
--- a/scribus/pageitem_regularpolygon.h
+++ b/scribus/pageitem_regularpolygon.h
@@ -37,6 +37,7 @@ class SCRIBUS_API PageItem_RegularPolygon : public PageItem
 
 public:
 	PageItem_RegularPolygon(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+	PageItem_RegularPolygon(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	PageItem_RegularPolygon(const PageItem& p);
 	~PageItem_RegularPolygon() {};
 
diff --git a/scribus/pageitem_spiral.cpp b/scribus/pageitem_spiral.cpp
index b30aab6..f0c7fda 100644
--- a/scribus/pageitem_spiral.cpp
+++ b/scribus/pageitem_spiral.cpp
@@ -48,7 +48,10 @@ for which a new license (GPL+exception) is in place.
 using namespace std;
 
 PageItem_Spiral::PageItem_Spiral(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
-	: PageItem(pa, PageItem::Spiral, x, y, w, h, w2, fill, outline)
+	: PageItem_Spiral(pa, x, y, w, h, w2, fill, outline, NameTiming::Direct) {}
+
+PageItem_Spiral::PageItem_Spiral(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem(pa, PageItem::Spiral, x, y, w, h, w2, fill, outline, nameTiming)
 {
 	spiralStartAngle = m_Doc->itemToolPrefs().spiralStartAngle;
 	spiralEndAngle = m_Doc->itemToolPrefs().spiralEndAngle;
diff --git a/scribus/pageitem_spiral.h b/scribus/pageitem_spiral.h
index a40e085..78001b4 100644
--- a/scribus/pageitem_spiral.h
+++ b/scribus/pageitem_spiral.h
@@ -38,6 +38,7 @@ class SCRIBUS_API PageItem_Spiral : public PageItem
 public:
 	PageItem_Spiral(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
 	PageItem_Spiral(const PageItem& p);
+	PageItem_Spiral(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	~PageItem_Spiral() {};
 
 	PageItem_Spiral * asSpiral() override { return this; }
diff --git a/scribus/pageitem_symbol.cpp b/scribus/pageitem_symbol.cpp
index 6e731d8..4b879c9 100644
--- a/scribus/pageitem_symbol.cpp
+++ b/scribus/pageitem_symbol.cpp
@@ -52,6 +52,11 @@ PageItem_Symbol::PageItem_Symbol(ScribusDoc *pa, double x, double y, double w, d
 {
 }
 
+PageItem_Symbol::PageItem_Symbol(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem(pa, PageItem::Symbol, x, y, w, h, 0, CommonStrings::None, CommonStrings::None, nameTiming)
+{
+}
+
 void PageItem_Symbol::DrawObj_Item(ScPainter *p, const QRectF& /*e*/)
 {
 	if (m_Doc->RePos)
diff --git a/scribus/pageitem_symbol.h b/scribus/pageitem_symbol.h
index 6b11834..5612c2e 100644
--- a/scribus/pageitem_symbol.h
+++ b/scribus/pageitem_symbol.h
@@ -37,6 +37,7 @@ class SCRIBUS_API PageItem_Symbol : public PageItem
 
 public:
 	PageItem_Symbol(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+  PageItem_Symbol(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	PageItem_Symbol(const PageItem & p) : PageItem(p) {}
 	~PageItem_Symbol() {};
 
diff --git a/scribus/pageitem_table.cpp b/scribus/pageitem_table.cpp
index 072746c..989a5c3 100644
--- a/scribus/pageitem_table.cpp
+++ b/scribus/pageitem_table.cpp
@@ -46,8 +46,11 @@ const double PageItem_Table::MinimumRowHeight = 3.0;
 // The minimum column width.
 const double PageItem_Table::MinimumColumnWidth = 3.0;
 
-PageItem_Table::PageItem_Table(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, int numRows, int numColumns) :
-	PageItem(pa, PageItem::Table, x, y, w, h, w2, fill, outline),
+PageItem_Table::PageItem_Table(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, int numRows, int numColumns)
+  : PageItem_Table(pa, x, y, w, h, w2, fill, outline, NameTiming::Direct, numRows, numColumns) {}
+
+PageItem_Table::PageItem_Table(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline,NameTiming nameTiming, int numRows, int numColumns ) :
+	PageItem(pa, PageItem::Table, x, y, w, h, w2, fill, outline, nameTiming),
 	m_rows(0), m_columns(0), m_tablePainter(new CollapsedTablePainter(this))
 {
 	initialize(numRows, numColumns);
diff --git a/scribus/pageitem_table.h b/scribus/pageitem_table.h
index 825886c..32fd846 100644
--- a/scribus/pageitem_table.h
+++ b/scribus/pageitem_table.h
@@ -88,6 +88,7 @@ public:
 public:
 	/// Construct a new table item with @a numRows rows and @a numColumns columns.
 	PageItem_Table(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, int numRows = 1, int numColumns = 1);
+	PageItem_Table(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming,  int numRows = 1, int numColumns = 1 );
 
 	/// Destructor.
 	~PageItem_Table();
diff --git a/scribus/pageitem_textframe.cpp b/scribus/pageitem_textframe.cpp
index 2fc63a5..4e57c08 100644
--- a/scribus/pageitem_textframe.cpp
+++ b/scribus/pageitem_textframe.cpp
@@ -74,11 +74,17 @@ for which a new license (GPL+exception) is in place.
 using namespace std;
 
 PageItem_TextFrame::PageItem_TextFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline)
-	: PageItem(pa, PageItem::TextFrame, x, y, w, h, w2, fill, outline)
+	: PageItem(pa, PageItem::TextFrame, x, y, w, h, w2, fill, outline, NameTiming::Direct)
+{
+}
+
+PageItem_TextFrame::PageItem_TextFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming)
+	: PageItem(pa, PageItem::TextFrame, x, y, w, h, w2, fill, outline, NameTiming::Direct)
 {
 	init();
 }
 
+
 PageItem_TextFrame::PageItem_TextFrame(const PageItem & p) : PageItem(p)
 {
 	init();
diff --git a/scribus/pageitem_textframe.h b/scribus/pageitem_textframe.h
index a973d84..3c4f369 100644
--- a/scribus/pageitem_textframe.h
+++ b/scribus/pageitem_textframe.h
@@ -48,6 +48,7 @@ class SCRIBUS_API PageItem_TextFrame : public PageItem
 
 public:
 	PageItem_TextFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline);
+	PageItem_TextFrame(ScribusDoc *pa, double x, double y, double w, double h, double w2, const QString& fill, const QString& outline, NameTiming nameTiming);
 	PageItem_TextFrame(const PageItem & p);
 	~PageItem_TextFrame() {}
 
diff --git a/scribus/plugins/import/pdf/slaoutput.cpp b/scribus/plugins/import/pdf/slaoutput.cpp
index 4e31e4b..77c0824 100644
--- a/scribus/plugins/import/pdf/slaoutput.cpp
+++ b/scribus/plugins/import/pdf/slaoutput.cpp
@@ -288,8 +288,8 @@ QString AnoOutputDev::getColor(GfxColorSpace *color_space, const GfxColor *color
 }
 
 SlaOutputDev::SlaOutputDev(ScribusDoc* doc, QList<PageItem*> *Elements, QStringList *importedColors, int flags)
+  : m_doc(doc), m_bulkadder(doc)
 {
-	m_doc = doc;
 	m_Elements = Elements;
 	pushGroup();
 	m_importedColors = importedColors;
@@ -400,7 +400,7 @@ bool SlaOutputDev::annotations_callback(Annot *annota, void *user_data)
 bool SlaOutputDev::handleTextAnnot(Annot* annota, double xCoor, double yCoor, double width, double height)
 {
 	AnnotText *anl = (AnnotText*)annota;
-	int z = m_doc->itemAdd(PageItem::TextFrame, PageItem::Rectangle, xCoor, yCoor, width, height, 0, CommonStrings::None, CommonStrings::None);
+	int z = m_bulkadder.itemAdd(PageItem::TextFrame, PageItem::Rectangle, xCoor, yCoor, width, height, 0, CommonStrings::None, CommonStrings::None);
 	PageItem *ite = m_doc->Items->at(z);
 	int flg = annota->getFlags();
 	if (!(flg & 16))
@@ -547,7 +547,7 @@ bool SlaOutputDev::handleLinkAnnot(Annot* annota, double xCoor, double yCoor, do
 	}
 	if (validLink)
 	{
-		int z = m_doc->itemAdd(PageItem::TextFrame, PageItem::Rectangle, xCoor, yCoor, width, height, 0, CommonStrings::None, CommonStrings::None);
+		int z = m_bulkadder.itemAdd(PageItem::TextFrame, PageItem::Rectangle, xCoor, yCoor, width, height, 0, CommonStrings::None, CommonStrings::None);
 		PageItem *ite = m_doc->Items->at(z);
 		int flg = annota->getFlags();
 		if (!(flg & 16))
@@ -713,7 +713,7 @@ bool SlaOutputDev::handleWidgetAnnot(Annot* annota, double xCoor, double yCoor,
 				delete annotOutDev;
 			}
 			const auto& graphicState = m_graphicStack.top();
-			int z = m_doc->itemAdd(PageItem::TextFrame, PageItem::Rectangle, xCoor, yCoor, width, height, 0, graphicState.fillColor, CommonStrings::None);
+			int z = m_bulkadder.itemAdd(PageItem::TextFrame, PageItem::Rectangle, xCoor, yCoor, width, height, 0, graphicState.fillColor, CommonStrings::None);
 			PageItem *ite = m_doc->Items->at(z);
 			int flg = annota->getFlags();
 			if (!(flg & 16))
@@ -1279,7 +1279,7 @@ void SlaOutputDev::endPage()
 			}
 			if (!m_tmpSel->isEmpty())
 			{
-				PageItem *ite = m_doc->groupObjectsSelection(m_tmpSel);
+				PageItem *ite = m_bulkadder.groupObjectsSelection(m_tmpSel);
 				ite->setItemName(it.key());
 				m_Elements->append(ite);
 				if (m_groupStack.count() != 0)
@@ -1313,7 +1313,7 @@ void SlaOutputDev::restoreState(GfxState *state)
 					m_tmpSel->addItem(gElements.Items.at(dre), true);
 					m_Elements->removeAll(gElements.Items.at(dre));
 				}
-				PageItem *ite = m_doc->groupObjectsSelection(m_tmpSel);
+				PageItem *ite = m_bulkadder.groupObjectsSelection(m_tmpSel);
 				if (ite)
 				{
 					QPainterPath clippath = m_graphicStack.top().clipPath;
@@ -1408,7 +1408,7 @@ void SlaOutputDev::endTransparencyGroup(GfxState *state)
 			m_tmpSel->addItem(gElements.Items.at(dre), true);
 			m_Elements->removeAll(gElements.Items.at(dre));
 		}
-		PageItem *ite = m_doc->groupObjectsSelection(m_tmpSel);
+		PageItem *ite = m_bulkadder.groupObjectsSelection(m_tmpSel);
 		ite->setFillTransparency(1.0 - state->getFillOpacity());
 		ite->setFillBlendmode(getBlendMode(state));
 		ScPattern pat(m_doc);
@@ -1438,7 +1438,7 @@ void SlaOutputDev::endTransparencyGroup(GfxState *state)
 		m_Elements->removeAll(gElements.Items.at(dre));
 	}
 	if ((gElements.Items.count() != 1) || (gElements.isolated))
-		ite = m_doc->groupObjectsSelection(m_tmpSel);
+		ite = m_bulkadder.groupObjectsSelection(m_tmpSel);
 	else
 		ite = gElements.Items.first();
 	if (ite->isGroup())
@@ -1588,9 +1588,9 @@ void SlaOutputDev::stroke(GfxState *state)
 
 	int z;
 	if (m_pathIsClosed)
-		z = m_doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, state->getTransformedLineWidth(), CommonStrings::None, graphicState.strokeColor);
+		z = m_bulkadder.itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, state->getTransformedLineWidth(), CommonStrings::None, graphicState.strokeColor);
 	else
-		z = m_doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, xCoor, yCoor, 10, 10, state->getTransformedLineWidth(), CommonStrings::None, graphicState.strokeColor);
+		z = m_bulkadder.itemAdd(PageItem::PolyLine, PageItem::Unspecified, xCoor, yCoor, 10, 10, state->getTransformedLineWidth(), CommonStrings::None, graphicState.strokeColor);
 	PageItem* ite = m_doc->Items->at(z);
 	ite->PoLine = out.copy();
 	ite->ClipEdited = true;
@@ -1689,9 +1689,9 @@ void SlaOutputDev::createFillItem(GfxState *state, Qt::FillRule fillRule)
 		graphicState.fillColor = getColor(state->getFillColorSpace(), state->getFillColor(), &graphicState.fillShade);
 		int z;
 		if (m_pathIsClosed)
-			z = m_doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, graphicState.fillColor, CommonStrings::None);
+			z = m_bulkadder.itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, graphicState.fillColor, CommonStrings::None);
 		else
-			z = m_doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, graphicState.fillColor, CommonStrings::None);
+			z = m_bulkadder.itemAdd(PageItem::PolyLine, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, graphicState.fillColor, CommonStrings::None);
 		PageItem* ite = m_doc->Items->at(z);
 		ite->PoLine.fromQPainterPath(clippedPath, true);
 		ite->ClipEdited = true;
@@ -1813,7 +1813,7 @@ bool SlaOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading, do
 	m_coords = output;
 
 	const auto& graphicState = m_graphicStack.top();
-	int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), bb.width(), bb.height(), 0, graphicState.fillColor, CommonStrings::None);
+	int z = m_bulkadder.itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), bb.width(), bb.height(), 0, graphicState.fillColor, CommonStrings::None);
 	PageItem* ite = m_doc->Items->at(z);
 	if (checkClip())
 	{
@@ -1935,7 +1935,7 @@ bool SlaOutputDev::radialShadedFill(GfxState *state, GfxRadialShading *shading,
 	m_coords = output;
 
 	const auto& graphicState = m_graphicStack.top();
-	int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, graphicState.fillColor, CommonStrings::None);
+	int z = m_bulkadder.itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, graphicState.fillColor, CommonStrings::None);
 	PageItem* ite = m_doc->Items->at(z);
 	if (checkClip())
 	{
@@ -1998,7 +1998,7 @@ bool SlaOutputDev::gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangle
 	const double *ctm = state->getCTM();
 	m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]);
 	const auto& graphicState = m_graphicStack.top();
-	int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, graphicState.fillColor, CommonStrings::None);
+	int z = m_bulkadder.itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, graphicState.fillColor, CommonStrings::None);
 	PageItem* ite = m_doc->Items->at(z);
 	ite->ClipEdited = true;
 	ite->FrameType = 3;
@@ -2079,7 +2079,7 @@ bool SlaOutputDev::patchMeshShadedFill(GfxState *state, GfxPatchMeshShading *sha
 	const double *ctm = state->getCTM();
 	m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]);
 	const auto& graphicState = m_graphicStack.top();
-	int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, graphicState.fillColor, CommonStrings::None);
+	int z = m_bulkadder.itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, graphicState.fillColor, CommonStrings::None);
 	PageItem* ite = m_doc->Items->at(z);
 	ite->ClipEdited = true;
 	ite->FrameType = 3;
@@ -2257,7 +2257,7 @@ bool SlaOutputDev::tilingPatternFill(GfxState *state, Gfx * /*gfx*/, Catalog *ca
 		m_doc->itemSelection_FlipV();
 		PageItem *ite;
 		if (m_doc->m_Selection->count() > 1)
-			ite = m_doc->groupObjectsSelection();
+			ite = m_bulkadder.groupObjectsSelection();
 		else
 			ite = m_doc->m_Selection->itemAt(0);
 		ite->setFillTransparency(1.0 - state->getFillOpacity());
@@ -2296,7 +2296,7 @@ bool SlaOutputDev::tilingPatternFill(GfxState *state, Gfx * /*gfx*/, Catalog *ca
 	m_coords = output;
 
 	const auto& graphicState = m_graphicStack.top();
-	int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, graphicState.fillColor, CommonStrings::None);
+	int z = m_bulkadder.itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, graphicState.fillColor, CommonStrings::None);
 	ite = m_doc->Items->at(z);
 
 	m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]);
@@ -2683,7 +2683,7 @@ void SlaOutputDev::createImageFrame(QImage& image, GfxState *state, int numColor
 	without_rotation = m_ctm * without_rotation.rotate(angle);
 	QRectF trect_wr = without_rotation.mapRect(QRectF(0, 0, 1, 1));
 
-	int z = m_doc->itemAdd(PageItem::ImageFrame, PageItem::Rectangle, xCoor + torigin.x(), yCoor + torigin.y(), trect_wr.width(), trect_wr.height(), 0, CommonStrings::None, CommonStrings::None);
+	int z = m_bulkadder.itemAdd(PageItem::ImageFrame, PageItem::Rectangle, xCoor + torigin.x(), yCoor + torigin.y(), trect_wr.width(), trect_wr.height(), 0, CommonStrings::None, CommonStrings::None);
 	PageItem* ite = m_doc->Items->at(z);
 	ite->ClipEdited = true;
 	ite->FrameType = 3;
@@ -3268,7 +3268,7 @@ void SlaOutputDev::drawChar(GfxState* state, double x, double y, double dx, doub
 			}
 			if ((textPath.size() > 3) && ((wh.x() != 0.0) || (wh.y() != 0.0)) && (textRenderingMode != 7))
 			{
-				int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, CommonStrings::None, CommonStrings::None);
+				int z = m_bulkadder.itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, CommonStrings::None, CommonStrings::None);
 				PageItem* ite = m_doc->Items->at(z);
 
 				// todo: merge this between vector and text implementations.
@@ -3332,7 +3332,7 @@ void SlaOutputDev::endType3Char(GfxState *state)
 		}
 		PageItem *ite;
 		if (m_doc->m_Selection->count() > 1)
-			ite = m_doc->groupObjectsSelection();
+			ite = m_bulkadder.groupObjectsSelection();
 		else
 			ite = m_doc->m_Selection->itemAt(0);
 		if (!f3e.colored)
@@ -3389,7 +3389,7 @@ void SlaOutputDev::endTextObject(GfxState *state)
 			}
 			PageItem *ite;
 			if (gElements.Items.count() != 1)
-				ite = m_doc->groupObjectsSelection(m_tmpSel);
+				ite = m_bulkadder.groupObjectsSelection(m_tmpSel);
 			else
 				ite = gElements.Items.first();
 			ite->setGroupClipping(false);
diff --git a/scribus/plugins/import/pdf/slaoutput.h b/scribus/plugins/import/pdf/slaoutput.h
index 4a64da8..b4d7010 100644
--- a/scribus/plugins/import/pdf/slaoutput.h
+++ b/scribus/plugins/import/pdf/slaoutput.h
@@ -29,6 +29,7 @@ for which a new license (GPL+exception) is in place.
 #include "scribusview.h"
 #include "selection.h"
 #include "vgradient.h"
+#include "bulkadder.h"
 
 #include <poppler/Object.h>
 #include <poppler/OutputDev.h>
@@ -285,6 +286,7 @@ protected:
 	void pushGroup(const QString& maskName = "", bool forSoftMask = false, bool alpha = false, bool inverted = false);
 
 	ScribusDoc* m_doc;
+  BulkAdder m_bulkadder;
 	Qt::PenCapStyle m_lineEnd { Qt::FlatCap };
 	Qt::PenJoinStyle m_lineJoin { Qt::MiterJoin };
 	QList<PageItem*>* m_Elements;
diff --git a/scribus/scribusdoc.cpp b/scribus/scribusdoc.cpp
index ea22d94..747e4ab 100644
--- a/scribus/scribusdoc.cpp
+++ b/scribus/scribusdoc.cpp
@@ -5188,6 +5188,16 @@ bool ScribusDoc::copyPageToMasterPage(int pageNumber, int leftPage, int maxLeftP
 }
 
 PageItem* ScribusDoc::createPageItem(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline)
+{
+  return implCreatePageItem(itemType, frameType, x, y, b, h, w, fill, outline, PageItem::NameTiming::Direct);
+}
+
+PageItem* ScribusDoc::createPageItemDeferred(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline)
+{
+  return implCreatePageItem(itemType, frameType, x, y, b, h, w, fill, outline, PageItem::NameTiming::Deferred);
+}
+
+PageItem* ScribusDoc::implCreatePageItem(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline, PageItem::NameTiming nameTiming)
 {
 	PageItem* newItem = nullptr;
 	switch (itemType)
@@ -5195,66 +5205,66 @@ PageItem* ScribusDoc::createPageItem(const PageItem::ItemType itemType, const Pa
 		//Q_ASSERTs here will warn on creation issues when a coder specifies the frameType incorrectly
 		//for items that do not have/need a frameType for creation.
 		case PageItem::ImageFrame:
-			newItem = new PageItem_ImageFrame(this, x, y, b, h, w, m_docPrefsData.itemToolPrefs.imageFillColor, m_docPrefsData.itemToolPrefs.imageStrokeColor);
+			newItem = new PageItem_ImageFrame(this, x, y, b, h, w, m_docPrefsData.itemToolPrefs.imageFillColor, m_docPrefsData.itemToolPrefs.imageStrokeColor, nameTiming);
 //			Q_ASSERT(frameType == PageItem::Rectangle || frameType == PageItem::Unspecified);
 			break;
 		case PageItem::TextFrame:
-			newItem = new PageItem_TextFrame(this, x, y, b, h, w, CommonStrings::None, outline);
+			newItem = new PageItem_TextFrame(this, x, y, b, h, w, CommonStrings::None, outline, nameTiming);
 //			Q_ASSERT(frameType == PageItem::Rectangle || frameType == PageItem::Unspecified);
 			break;
 		case PageItem::Line:
 			{
 				//CB 5521 Remove false minimum line width
 				double lineWidth = w; // == 0.0 ? 1.0 : w;
-				newItem = new PageItem_Line(this, x, y, b, h, lineWidth, CommonStrings::None, outline);
+				newItem = new PageItem_Line(this, x, y, b, h, lineWidth, CommonStrings::None, outline, nameTiming);
 //				Q_ASSERT(frameType == PageItem::Unspecified);
 			}
 			break;
 		case PageItem::Table:
-			newItem = new PageItem_Table(this, x, y, b, h, w, fill, outline);
+			newItem = new PageItem_Table(this, x, y, b, h, w, fill, outline,nameTiming);
 //			Q_ASSERT(frameType == PageItem::Rectangle || frameType == PageItem::Unspecified);
 			break;
 		case PageItem::Polygon:
-			newItem = new PageItem_Polygon(this, x, y, b, h, w, fill, outline);
+			newItem = new PageItem_Polygon(this, x, y, b, h, w, fill, outline, nameTiming);
 //			Q_ASSERT(frameType == PageItem::Rectangle || frameType == PageItem::Ellipse || frameType == PageItem::Unspecified);
 			break;
 		case PageItem::PolyLine:
-			newItem = new PageItem_PolyLine(this, x, y, b, h, w, fill, outline);
+			newItem = new PageItem_PolyLine(this, x, y, b, h, w, fill, outline, nameTiming);
 //			Q_ASSERT(frameType == PageItem::Unspecified);
 			break;
 		case PageItem::PathText:
 			//Currently used only in fileloader
-			newItem = new PageItem_PathText(this, x, y, b, h, w, fill, outline);
+			newItem = new PageItem_PathText(this, x, y, b, h, w, fill, outline, nameTiming);
 //			Q_ASSERT(frameType == PageItem::Unspecified);
 			break;
 		case PageItem::LatexFrame:
-			newItem = new PageItem_LatexFrame(this, x, y, b, h, w, m_docPrefsData.itemToolPrefs.imageFillColor, m_docPrefsData.itemToolPrefs.imageStrokeColor);
+			newItem = new PageItem_LatexFrame(this, x, y, b, h, w, m_docPrefsData.itemToolPrefs.imageFillColor, m_docPrefsData.itemToolPrefs.imageStrokeColor, nameTiming);
 //			Q_ASSERT(frameType == PageItem::Rectangle || frameType == PageItem::Unspecified);
 			break;
 #ifdef HAVE_OSG
 		case PageItem::OSGFrame:
-			newItem = new PageItem_OSGFrame(this, x, y, b, h, w, m_docPrefsData.itemToolPrefs.imageFillColor, m_docPrefsData.itemToolPrefs.imageStrokeColor);
+			newItem = new PageItem_OSGFrame(this, x, y, b, h, w, m_docPrefsData.itemToolPrefs.imageFillColor, m_docPrefsData.itemToolPrefs.imageStrokeColor, nameTiming);
 //			Q_ASSERT(frameType == PageItem::Rectangle || frameType == PageItem::Unspecified);
 			break;
 #endif
 		case PageItem::Symbol:
-			newItem = new PageItem_Symbol(this, x, y, b, h, w, CommonStrings::None, CommonStrings::None);
+			newItem = new PageItem_Symbol(this, x, y, b, h, w, CommonStrings::None, CommonStrings::None,nameTiming);
 //			Q_ASSERT(frameType == PageItem::Rectangle || frameType == PageItem::Unspecified);
 			break;
 		case PageItem::Group:
-			newItem = new PageItem_Group(this, x, y, b, h, w, CommonStrings::None, CommonStrings::None);
+			newItem = new PageItem_Group(this, x, y, b, h, w, CommonStrings::None, CommonStrings::None, nameTiming);
 //			Q_ASSERT(frameType == PageItem::Rectangle || frameType == PageItem::Unspecified);
 			break;
 		case PageItem::RegularPolygon:
-			newItem = new PageItem_RegularPolygon(this, x, y, b, h, w, fill, outline);
+			newItem = new PageItem_RegularPolygon(this, x, y, b, h, w, fill, outline, nameTiming);
 //			Q_ASSERT(frameType == PageItem::Rectangle || frameType == PageItem::Ellipse || frameType == PageItem::Unspecified);
 			break;
 		case PageItem::Arc:
-			newItem = new PageItem_Arc(this, x, y, b, h, w, fill, outline);
+			newItem = new PageItem_Arc(this, x, y, b, h, w, fill, outline, nameTiming);
 //			Q_ASSERT(frameType == PageItem::Rectangle || frameType == PageItem::Ellipse || frameType == PageItem::Unspecified);
 			break;
 		case PageItem::Spiral:
-			newItem = new PageItem_Spiral(this, x, y, b, h, w, fill, outline);
+			newItem = new PageItem_Spiral(this, x, y, b, h, w, fill, outline, nameTiming);
 //			Q_ASSERT(frameType == PageItem::Unspecified);
 			break;
 		default:
@@ -5270,6 +5280,16 @@ PageItem* ScribusDoc::createPageItem(const PageItem::ItemType itemType, const Pa
 }
 
 int ScribusDoc::itemAdd(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline, PageItem::ItemKind itemKind)
+{
+  return implItemAdd(itemType,frameType, x, y, b, h, w, fill, outline, itemKind, PageItem::NameTiming::Direct);
+}
+
+int ScribusDoc::itemAddDeferred(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline, PageItem::ItemKind itemKind)
+{
+  return implItemAdd(itemType,frameType, x, y, b, h, w, fill, outline, itemKind, PageItem::NameTiming::Deferred);
+}
+
+int ScribusDoc::implItemAdd(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline, PageItem::ItemKind itemKind, PageItem::NameTiming nameTiming)
 {
 	UndoTransaction activeTransaction;
 	if (UndoManager::undoEnabled()) // && !m_itemCreationTransaction)
@@ -5284,7 +5304,7 @@ int ScribusDoc::itemAdd(const PageItem::ItemType itemType, const PageItem::ItemF
 		itemAddDetails(PageItem::TextFrame, frameType, newItem);
 	}
 	else
-		newItem = createPageItem(itemType, frameType, x, y, b, h, w, fill, outline); 
+		newItem = implCreatePageItem(itemType, frameType, x, y, b, h, w, fill, outline, nameTiming); 
 	
 	Q_CHECK_PTR(newItem);
 	if (newItem == nullptr)
@@ -15168,6 +15188,16 @@ void ScribusDoc::scaleGroup(double scx, double scy, bool scaleText, Selection* c
 }
 
 PageItem* ScribusDoc::groupObjectsSelection(Selection* customSelection)
+{
+  return implGroupObjectsSelection(customSelection, PageItem::NameTiming::Direct);
+}
+
+PageItem* ScribusDoc::groupObjectsSelectionDeferred(Selection* customSelection)
+{
+  return implGroupObjectsSelection(customSelection, PageItem::NameTiming::Deferred);
+}
+
+PageItem* ScribusDoc::implGroupObjectsSelection(Selection* customSelection, PageItem::NameTiming nameTiming)
 {
 	Selection* itemSelection = (customSelection != nullptr) ? customSelection : m_Selection;
 	if (itemSelection->count() < 1)
@@ -15207,10 +15237,12 @@ PageItem* ScribusDoc::groupObjectsSelection(Selection* customSelection)
 	double gy = miny;
 	double gw = maxx - minx;
 	double gh = maxy - miny;
-	int z = itemAdd(PageItem::Group, PageItem::Rectangle, gx, gy, gw, gh, 0, CommonStrings::None, CommonStrings::None);
+	int z = implItemAdd(PageItem::Group, PageItem::Rectangle, gx, gy, gw, gh, 0, CommonStrings::None, CommonStrings::None, PageItem::StandardItem, nameTiming);
 	PageItem *groupItem = Items->takeAt(z);
 	Items->insert(lowestItem, groupItem);
-	groupItem->setItemName( tr("Group%1").arg(GroupCounter));
+  if (nameTiming == PageItem::NameTiming::Direct) {
+    groupItem->setItemName( tr("Group%1").arg(GroupCounter));
+  }
 	groupItem->AutoName = false;
 	groupItem->groupWidth = gw;
 	groupItem->groupHeight = gh;
diff --git a/scribus/scribusdoc.h b/scribus/scribusdoc.h
index d7051e0..81e3317 100644
--- a/scribus/scribusdoc.h
+++ b/scribus/scribusdoc.h
@@ -822,6 +822,9 @@ public:
 	 * @brief Just create but don't add to items list and don't create undo record
 	 */
 	PageItem* createPageItem(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline);
+
+	PageItem* createPageItemDeferred(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline);
+
 	
 	/**
 	 * @brief Add an Item to the document.
@@ -843,6 +846,8 @@ public:
 	*/
 	int itemAdd(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline, PageItem::ItemKind itemKind = PageItem::StandardItem);
 
+	int itemAddDeferred(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline, PageItem::ItemKind itemKind = PageItem::StandardItem);
+
 	/** Add an item to the page based on the x/y position. Item will be fitted to the closest guides/margins */
 	int itemAddArea(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double w, const QString& fill, const QString& outline, PageItem::ItemKind itemKind = PageItem::StandardItem);
 	
@@ -1095,6 +1100,7 @@ public:
 
 	QList<PageItem*>* groupOfItem(QList<PageItem*>* itemList, PageItem* item);
 	PageItem* groupObjectsSelection(Selection* customSelection = nullptr);
+	PageItem* groupObjectsSelectionDeferred(Selection* customSelection = nullptr);
 	PageItem* groupObjectsList(QList<PageItem*> &itemList);
 	void groupObjectsToItem(PageItem* groupItem, QList<PageItem*> &itemList);
 	PageItem * itemSelection_GroupObjects  (bool changeLock, bool lock, Selection* customSelection = nullptr, PageItem_Group* groupItem = nullptr);
@@ -1762,6 +1768,10 @@ private:
 
 	void multipleDuplicateByPage(const ItemMultipleDuplicateData& mdData, Selection& selection, QString& tooltip);
 
+	int implItemAdd(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline, PageItem::ItemKind itemKind, PageItem::NameTiming nameTiming);
+	PageItem* implCreatePageItem(const PageItem::ItemType itemType, const PageItem::ItemFrameType frameType, double x, double y, double b, double h, double w, const QString& fill, const QString& outline, PageItem::NameTiming nameTiming);
+	PageItem* implGroupObjectsSelection(Selection* customSelection, PageItem::NameTiming nameTiming);
+
 public:
 	bool usesMarksAndNotes() const { return m_docUsesMarksAndNotes; }
 	void setUsesMarksAndNotes(bool b) { m_docUsesMarksAndNotes = b; }
-- 
2.42.1

Issue History

Date Modified Username Field Change
2022-11-20 16:58 fsimonis New Issue
2022-11-20 16:58 fsimonis File Added: 0001-Add-deferred-naming-and-bulkadder.patch
2022-11-22 07:09 ale Note Added: 0049812
2022-11-22 10:04 fsimonis Note Added: 0049813
2022-11-22 11:59 ale Note Added: 0049814
2022-11-22 16:57 fsimonis Note Added: 0049815
2022-11-24 07:13 ale Note Added: 0049816
2023-11-18 13:10 fsimonis Note Added: 0050483
2023-11-18 13:10 fsimonis File Added: 0001-Add-deferred-naming-and-bulkadder-2.patch
2023-11-26 12:31 JLuc Tag Attached: performance
2023-11-26 12:32 JLuc Tag Attached: import
2023-11-26 12:32 JLuc Tag Attached: pdf import
2023-11-26 12:32 JLuc Tag Attached: speed