View Issue Details

IDProjectCategoryView StatusLast Update
0015131ScribusInternalpublic2018-02-05 11:53
Reporteru ltd. Assigned To 
PrioritynormalSeverityfeatureReproducibilityalways
Status newResolutionopen 
Platformamd64OSalike debianOS Version9
Product Version1.5.4.svn 
Summary0015131: Add fast & precise duplicate to core+scripter
DescriptionThe scripter still uses the system clipboard to duplicate objects.

Here comes a dramatically smaller version: not a selection but a single object will be duplicated; it is serialized and deserialized within one method in scribus.cpp

This has another advantage: the Python user can request a name for the duplicate and the actual duplicate name can be returned.
Additional InformationThe scripter duplication patch is using the Python3 scripter update (Ticket 0015030)

Two patch parts:
1. Scribus only (without scripter)
2. Scripter only (without scribus)
Tagspatch, script
PatchYes

Activities

u ltd.

2018-02-05 09:49

reporter  

scribus-20180205-095552-jonas-duplicate.patch (15,924 bytes)   
Index: scribus/loadsaveplugin.cpp
===================================================================
--- scribus/loadsaveplugin.cpp	(Revision 22369)
+++ scribus/loadsaveplugin.cpp	(Arbeitskopie)
@@ -437,6 +437,14 @@
 	return QImage();
 }
 
+bool LoadSavePlugin::writeObject(ScribusDoc *doc, ScXmlStreamWriter& docu, const QString& baseDir, PageItem * item) {
+	return false;
+}
+bool LoadSavePlugin::readObject(ScribusDoc *doc, ScXmlStreamReader& reader, const QString& baseDir, PageItem **item) {
+	return false;
+}
+
+
 bool FileFormat::loadFile(const QString & fileName, int flags, int index) const
 {
 	if (plug && load)
@@ -498,6 +506,8 @@
 {
 }
 
+
+
 bool FileFormat::loadElements(const QString & data, QString fileDir, int toLayer, double Xp_in, double Yp_in, bool loc) const
 {
 	return (plug && load) ? plug->loadElements(data, fileDir, toLayer, Xp_in, Yp_in, loc) : false;
@@ -573,5 +583,13 @@
 	return (plug && load && thumb) ? plug->readThumbnail(fileName) : QImage();
 }
 
+bool FileFormat::writeObject(ScribusDoc *doc, ScXmlStreamWriter& docu, const QString& baseDir, PageItem * item) const {
+	qDebug() << "FileFormat::writeObject()";
+	return (plug && load) ? plug->writeObject(doc, docu, baseDir, item) : false;
+}
+bool FileFormat::readObject(ScribusDoc *doc, ScXmlStreamReader& reader, const QString& baseDir, PageItem **item) const {
+	qDebug() << "FileFormat::readObject()";
+	return (plug && load) ? plug->readObject(doc, reader, baseDir, item) : false;
+}
 
 
Index: scribus/loadsaveplugin.h
===================================================================
--- scribus/loadsaveplugin.h	(Revision 22369)
+++ scribus/loadsaveplugin.h	(Arbeitskopie)
@@ -22,7 +22,10 @@
 #include "scfonts.h"
 #include "scribusdoc.h"
 #include "undomanager.h"
+#include "scxmlstreamwriter.h"
+#include "scxmlstreamreader.h"
 
+
 /*!
  * @brief Superclass for all file import/export/load/save plugins
  *
@@ -116,6 +119,9 @@
 		virtual bool readPageCount(const QString& fileName, int *num1, int *num2, QStringList & masterPageNames);
 		virtual QImage readThumbnail(const QString& fileName);
 		
+		virtual bool writeObject(ScribusDoc *doc, ScXmlStreamWriter& docu, const QString& baseDir, PageItem * item);
+		virtual bool readObject(ScribusDoc *doc, ScXmlStreamReader& reader, const QString& baseDir, PageItem **item);
+		
 	protected:
 
 		/// Check a loadFlags combination
@@ -258,6 +264,9 @@
 		// this format.
 		LoadSavePlugin * plug;
 //		LoadSavePlugin * const plug;
+		
+		bool writeObject(ScribusDoc *doc, ScXmlStreamWriter& docu, const QString& baseDir, PageItem * item) const;
+		bool readObject(ScribusDoc *doc, ScXmlStreamReader& reader, const QString& baseDir, PageItem **item) const;
 };
 
 
Index: scribus/plugins/fileloader/scribus150format/scribus150format.cpp
===================================================================
--- scribus/plugins/fileloader/scribus150format/scribus150format.cpp	(Revision 22369)
+++ scribus/plugins/fileloader/scribus150format/scribus150format.cpp	(Arbeitskopie)
@@ -3698,10 +3698,33 @@
 	return true;
 }
 
-bool Scribus150Format::readObject(ScribusDoc* doc, ScXmlStreamReader& reader, ItemInfo& info, const QString& baseDir, bool loadPage, QString renamedPageName)
+// Why making it easy when complicated works too? ... Why not simply return PageItem ...
+// This call comes from extern. (probably scribus.cpp)
+// The PageItem serialized in reader must have the appropriate Layer set.
+bool Scribus150Format::readObject(ScribusDoc *doc, ScXmlStreamReader& reader, const QString& baseDir, PageItem **item) {
+	//qDebug() << "Scribus150Format::readObject()    item = " << (uint64_t)((void*)(item));
+	ScXmlStreamAttributes attrs = reader.scAttributes();
+	LayerToPaste = attrs.valueAsInt("LAYER");
+	ItemInfo info;
+	bool retV = readObject(doc, reader, info, baseDir, false, QString());
+	//qDebug() << "Scribus150Format::readObject()    retV = " << retV;
+	if (retV)
+		*item = info.item;
+	//qDebug() << "Scribus150Format::readObject()    item = " << (*item)->itemName();
+	return retV;
+}
+
+// This call comes from intern (scribus150format.cpp)
+bool Scribus150Format::readObject(ScribusDoc *doc, ScXmlStreamReader& reader, ItemInfo& info, const QString& baseDir, bool loadPage, QString renamedPageName)
 {
 	QStringRef tagName = reader.name();
 	ScXmlStreamAttributes attrs = reader.scAttributes();
+	/*qDebug() << "attrs: size=" << attrs.size();
+	if (!attrs.isEmpty()) {
+		QXmlStreamAttribute qxsa = attrs.first();
+		qDebug() << "    Name  = " << qxsa.name();
+		qDebug() << "    Value = " << qxsa.value();
+	}*/
 
 	if (!loadPage)
 	{
@@ -3728,6 +3751,7 @@
 	}
 	layerFound = false;
 	clipPath = "";
+	//qDebug() << "Scribus150Format::readObject(intern)    beep. ItemKind=" <<itemKind;
 	PageItem* newItem = pasteItem(doc, attrs, baseDir, itemKind, pagenr);
 	newItem->setRedrawBounding();
 	if (tagName == "MASTEROBJECT")
@@ -4807,6 +4831,7 @@
 	QColor tmpc;
 	PageItem *currItem=NULL;
 	QString tmp, clPath;
+	//qDebug() << "Scribus150Format::pasteItem(intern)    beep0. itemType=" << pt << "   (Could be " << attrs.valueAsInt("PTYPE") << ".)";
 	switch (pt)
 	{
 	// OBSOLETE CR 2005-02-06
@@ -4915,6 +4940,7 @@
 	case PageItem::NoteFrame:
 	case PageItem::TextFrame:
 		z = doc->itemAdd(pt, PageItem::Unspecified, x, y, w, h, pw, CommonStrings::None, Pcolor, itemKind);
+		//qDebug() << "Scribus150Format::pasteItem(intern)    beep2. z=" << z;
 		currItem = doc->Items->at(z);
 		if (pagenr > -2) 
 			currItem->setOwnerPage(pagenr);
@@ -4981,8 +5007,10 @@
 		Q_ASSERT(false);
 		break;
 	}
-
+	//qDebug() << "Scribus150Format::pasteItem(intern)    beep2. pagenr=" << pagenr << ", currItem=" << (uint64_t)((void*)currItem);
+	
 	currItem->setGroupClipping(attrs.valueAsBool("groupClips", true));
+	//qDebug() << "Scribus150Format::pasteItem(intern)    beep25.";
 	currItem->FrameType = attrs.valueAsInt("FRTYPE", 0);
 	int startArrowIndex = attrs.valueAsInt("startArrowIndex", 0);
 	if ((startArrowIndex < 0) || (startArrowIndex > static_cast<int>(doc->arrowStyles().size())))
@@ -4990,6 +5018,7 @@
 		qDebug() << QString("scribus150format: invalid arrow index: %").arg(startArrowIndex);
 		startArrowIndex = 0;
 	}
+	//qDebug() << "Scribus150Format::pasteItem(intern)    beep3.";
 	currItem->setStartArrowIndex(startArrowIndex);
 	int endArrowIndex = attrs.valueAsInt("endArrowIndex", 0);
 	if ((endArrowIndex < 0) || (endArrowIndex > static_cast<int>(doc->arrowStyles().size())))
@@ -5122,6 +5151,7 @@
 		pstyle.setNumOther(static_cast<bool>(attrs.valueAsInt("NumeartionOther")));
 	if (attrs.hasAttribute("NumerationHigher"))
 		pstyle.setNumHigher(static_cast<bool>(attrs.valueAsInt("NumerationHigher")));
+	//qDebug() << "Scribus150Format::pasteItem(intern)    beep3.";
 	currItem->itemText.setDefaultStyle(pstyle);
 
 	if (attrs.hasAttribute("PSTYLE"))
@@ -5149,6 +5179,8 @@
 	currItem->setIsAnnotation( attrs.valueAsInt("ANNOTATION", 0));
 	currItem->annotation().setType( attrs.valueAsInt("ANTYPE", 0));
 	QString AnName = attrs.valueAsString("ANNAME","");
+	//qDebug() << "Scribus150Format::pasteItem(intern)    beep38. XML:ANNAME =      " << AnName;
+	//qDebug() << "Scribus150Format::pasteItem(intern)    beep39. currItem->AnName =" << currItem->itemName();
 	if (!AnName.isEmpty())
 	{
 		if (currItem->itemName() == AnName)
@@ -5159,6 +5191,7 @@
 			currItem->AutoName = false;
 		}
 	}
+	//qDebug() << "Scribus150Format::pasteItem(intern)    beep4. currItem->AutoName = " << currItem->AutoName;
 
 	currItem->annotation().setAction( attrs.valueAsString("ANACTION","") );
 	currItem->annotation().setE_act ( attrs.valueAsString("ANEACT","") );
Index: scribus/plugins/fileloader/scribus150format/scribus150format.h
===================================================================
--- scribus/plugins/fileloader/scribus150format/scribus150format.h	(Revision 22369)
+++ scribus/plugins/fileloader/scribus150format/scribus150format.h	(Arbeitskopie)
@@ -4,8 +4,8 @@
 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.
 */
-#ifndef SCRIBUS134FORMAT_H
-#define SCRIBUS134FORMAT_H
+#ifndef SCRIBUS150FORMAT_H
+#define SCRIBUS150FORMAT_H
 
 #include "pluginapi.h"
 #include "loadsaveplugin.h"
@@ -63,9 +63,13 @@
 		virtual bool readColors(const QString& fileName, ColorList & colors);
 		virtual bool readPageCount(const QString& fileName, int *num1, int *num2, QStringList & masterPageNames);
 		virtual void getReplacedFontData(bool & getNewReplacement, QMap<QString,QString> &getReplacedFonts, QList<ScFace> &getDummyScFaces);
-
+		
+		
+		bool writeObject(ScribusDoc *doc, ScXmlStreamWriter& docu, const QString& baseDir, PageItem * item); // Gets overloaded by writeObject(...., ItemSelection master)
+		bool readObject(ScribusDoc *doc, ScXmlStreamReader& reader, const QString& baseDir, PageItem **item);
+	
 	private:
-
+	
 		enum ItemSelection {
 			ItemSelectionMaster = 0,
 			ItemSelectionPage   = 1,
@@ -190,6 +194,7 @@
 
 		void WritePages(ScribusDoc *doc, ScXmlStreamWriter& docu, QProgressBar *dia2, uint maxC, bool master);
 		void WriteObjects(ScribusDoc *doc, ScXmlStreamWriter& docu, const QString& baseDir, QProgressBar *dia2, uint maxC, ItemSelection master, QList<PageItem*> *items = 0);
+		bool writeObject(ScribusDoc *doc, ScXmlStreamWriter& docu, const QString& baseDir, ItemSelection master, QList<PageItem*> *items, PageItem* item);
 		void SetItemProps(ScXmlStreamWriter& docu, PageItem* item, const QString& baseDir);
 
 		QMap<QString, QString> parStyleMap;
Index: scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp
===================================================================
--- scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp	(Revision 22369)
+++ scribus/plugins/fileloader/scribus150format/scribus150format_save.cpp	(Arbeitskopie)
@@ -49,7 +49,7 @@
 {
 	QString fileDir = ScPaths::applicationDataDir();
 	QString documentStr;
-	documentStr.reserve(524288);
+	documentStr.reserve(524288); // FIXME: Magic Number
 	ScXmlStreamWriter writer(&documentStr);
 	writer.setAutoFormatting(true);
 //	writer.writeStartDocument();
@@ -1761,12 +1761,18 @@
 	}
 }
 
+
+bool  Scribus150Format::writeObject(ScribusDoc *doc, ScXmlStreamWriter& docu, const QString& baseDir, PageItem* item) {
+	qDebug() << "Scribus150Format::writeObject()";
+	return writeObject(doc, docu, baseDir, ItemSelectionElements, NULL, item);
+}
+
 void Scribus150Format::WriteObjects(ScribusDoc *doc, ScXmlStreamWriter& docu, const QString& baseDir, QProgressBar *dia2, uint maxC, ItemSelection master, QList<PageItem*> *some_items)
 {
 	uint ObCount = maxC;
 	QList<PageItem*> *items = NULL;
 	QList<PageItem*> itemList;
-	PageItem *item = NULL;
+	PageItem *item;
 	uint objects = 0;
 	switch (master)
 	{
@@ -1800,6 +1806,13 @@
 		if (dia2 != 0)
 			dia2->setValue(ObCount);
 		item = items->at(j);
+		writeObject(doc, docu, baseDir, master, items, item);
+	}
+}
+
+
+bool Scribus150Format::writeObject(ScribusDoc *doc, ScXmlStreamWriter& docu, const QString& baseDir, ItemSelection master, QList<PageItem*> *items, PageItem* item)
+{
 		switch (master)
 		{
 			case ItemSelectionMaster:
@@ -2015,7 +2028,7 @@
 			else
 				docu.writeAttribute("NEXTITEM", -1);
 			
-			if (item->prevInChain() != 0 && items->contains(item->prevInChain()))
+			if (item->prevInChain() != 0 && items && items->contains(item->prevInChain()))
 				docu.writeAttribute("BACKITEM", qHash(item->prevInChain()) & 0x7FFFFFFF);
 			else
 			{
@@ -2467,7 +2480,7 @@
 			docu.writeEndElement();
 		}
 		docu.writeEndElement();
-	}
+	return true;
 }
 
 void Scribus150Format::SetItemProps(ScXmlStreamWriter& docu, PageItem* item, const QString& baseDir)
Index: scribus/scribus.cpp
===================================================================
--- scribus/scribus.cpp	(Revision 22369)
+++ scribus/scribus.cpp	(Arbeitskopie)
@@ -23,6 +23,7 @@
 
 #include <QAction>
 #include <QApplication>
+#include <QBuffer>
 #include <QByteArray>
 #include <QCloseEvent>
 #include <QColor>
@@ -150,6 +151,8 @@
 #include "scribusdoc.h"
 #include "scribusview.h"
 #include "scribuswin.h"
+#include "scxmlstreamreader.h"
+#include "scxmlstreamwriter.h"
 #include "selection.h"
 #include "serializer.h"
 #include "styleoptions.h"
@@ -4552,6 +4555,63 @@
 	close();
 }
 
+
+PageItem* ScribusMainWindow::slotDuplicateSingle(PageItem * source, QString *newname) {
+	// Seems the best way to serialize object and re-include it. 
+	// This is similar to what slotEditCopy+slotEditPaste would do, but 
+	// they use the system clipboard and copy a whole selection.
+	// Instead of serializing the strings one could have mad a simple
+	// copy of the PageItem using it's constructor.
+	// But this way we can be sure to transfer
+	// all the information.
+	
+	const FileFormat *fmt = LoadSavePlugin::getFormatById(FORMATID_SLA150IMPORT);
+	if (!fmt) {
+		qDebug() << "Couldn't find LoadSavePlugin.";
+		return NULL;
+	}
+	fmt->setupTargets(doc, 0, doc->scMW(), 0, &(PrefsManager::instance()->appPrefs.fontPrefs.AvailFonts));
+	
+	
+	QString XMLBuffer = QString("");
+	//qDebug() << "slotDuplicateSingle(): XMLBuffer: " << XMLBuffer;
+	ScXmlStreamWriter docu (&XMLBuffer);
+	//docu.writeComment("abc\"defg\n");
+	bool res = fmt->writeObject(doc, docu, ScPaths::applicationDataDir(), source);
+	//qDebug() << "slotDuplicateSingle(): " << res << " --> XMLBuffer: " << XMLBuffer;
+	
+	if (!res || !XMLBuffer.count()) {
+		qDebug() << "slotDuplicateSingle(): Couldn't serialize PageItem.";
+		return NULL;
+	}
+	
+	//qDebug() << "slotDuplicateSingle(): new XMLBuffer:" << XMLBuffer;
+	ScXmlStreamReader reader(XMLBuffer.toUtf8().constData());
+
+	while (reader.readNext() != ScXmlStreamReader::StartElement) {}
+	
+	ScXmlStreamAttributes sxsa = reader.scAttributes();
+	
+	assert (!sxsa.isEmpty());
+	/*
+	qDebug() << "slotDuplicateSingle(): attrs: size=" << sxsa.size();
+	QXmlStreamAttribute qxsa = sxsa.first();
+	qDebug() << "slotDuplicateSingle():     Name  = " << qxsa.name();
+	qDebug() << "slotDuplicateSingle():     Value = " << qxsa.value();
+	*/
+	PageItem *retV;
+	fmt->readObject(doc, reader, ScPaths::applicationDataDir(), &retV);
+	
+	if (newname != NULL && !newname->isEmpty())
+		retV->setItemName(*newname);
+	retV->setXYPos(source->xPos(), source->yPos());
+	
+	slotDocCh();
+	
+	return retV;
+}
+
+
 void ScribusMainWindow::slotEditCut()
 {
 	if (!HaveDoc)
@@ -4681,10 +4741,8 @@
 	{
 		if ((currItem->isSingleSel) && (currItem->isGroup()))
 			return;
-		//do not copy notes frames
-		if (doc->m_Selection->count() ==1 && currItem->isNoteFrame())
-			return;
-		//deselect notesframes
+		
+		// do not copy notes frames -> deselect them
 		Selection tempSelection(*(doc->m_Selection));
 		for (int i = 0; i < doc->m_Selection->count(); ++i)
 		{
@@ -4693,7 +4751,10 @@
 		}
 		if (tempSelection.count() < doc->m_Selection->count())
 			*(doc->m_Selection) = tempSelection;
-
+		
+		if (doc->m_Selection->isEmpty() == 0)
+			return;
+		
 		ScriXmlDoc ss;
 		QString BufferS = ss.WriteElem(doc, doc->m_Selection);
 		if (!internalCopy)
@@ -4949,7 +5010,7 @@
 		else
 			currItem->update();
 		view->DrawNew();
-	}
+	} // if appMode == modeEdit/modeEditTable && selItem->isTextFrame()/isTable()
 	else
 	{
 		if (ScMimeData::clipboardHasScribusElem() || ScMimeData::clipboardHasScribusFragment() || internalCopy)
Index: scribus/scribus.h
===================================================================
--- scribus/scribus.h	(Revision 22369)
+++ scribus/scribus.h	(Arbeitskopie)
@@ -371,6 +371,8 @@
 	bool doPrint(PrintOptions &options, QString& error);
 	/** \brief exits the application */
 	void slotFileQuit();
+	/** \brief Duplicate a single PageItem. */
+	PageItem* slotDuplicateSingle(PageItem * source, QString *newname);
 	/** \brief put the marked text/object into the clipboard and remove
 	 * it from the document */
 	void slotEditCut();
scribus-20180205-095552-jonas-duplicate_python_invokation.patch (10,836 bytes)   
Index: scribus/plugins/scriptplugin/cmdobj.h
===================================================================
--- scribus/plugins/scriptplugin/cmdobj.h	(Revision 22369)
+++ scribus/plugins/scriptplugin/cmdobj.h	(Arbeitskopie)
@@ -283,23 +283,46 @@
 PyObject *scribus_getcharstylenames(PyObject * /*self*/);
 
 
+/* Jonas Bechtel, 2018-02-04 */
 /*! docstring */
+PyDoc_STRVAR(scribus_renameobject__doc__,
+QT_TR_NOOP("renameObject([\"newname\", <\"oldname\">]) -> string\n\
+\n\
+Renames the object \"oldname\" (or the selected object) to \"oldname\".\n\
+"));
+PyObject *scribus_renameobject(PyObject * /* self */, PyObject *args);
+
+
+
+/* Jonas Bechtel, 2018-02-03 */
+/*! docstring */
 PyDoc_STRVAR(scribus_duplicateobject__doc__,
-QT_TR_NOOP("duplicateObject([\"name\"]) -> string\n\
+QT_TR_NOOP("duplicateObject([<\"newname\", <\"name\">>]) -> string\n\
 \n\
-creates a Duplicate of the selected Object (or Selection Group).\n\
+Creates a duplicate of the selected or named single object.\n\
+The duplicate will have the name \"newname\", if provided.\n\
 "));
+PyObject *scribus_duplicateobject(PyObject * /* self */, PyObject *args);
+
+
+/*! docstring */
+PyDoc_STRVAR(scribus_duplicateobject_legacy__doc__,
+QT_TR_NOOP("duplicateObject_legacy([\"name\"]) -> None\n\
+\n\
+creates a duplicate of the selected or named object (or selection group).\n\
+[Remark: you will find that object in your system's clipboard then].\n\
+"));
 /**
  Christian Hausknecht, 2006-07-12
  duplicate an object
 */
-PyObject *scribus_duplicateobject(PyObject * /* self */, PyObject *args);
+PyObject *scribus_duplicateobject_legacy(PyObject * /* self */, PyObject *args);
 
 /*! docstring */
 PyDoc_STRVAR(scribus_copyobject__doc__,
 QT_TR_NOOP("copyObject([\"name\"]) -> string\n\
 \n\
-copies the selected Object (or Selection Group).\n\
+copies the selected object (or selection group).\n\
 "));
 /**
  Gregory Pittman, 2012-01-12
Index: scribus/plugins/scriptplugin/cmdobj.cpp
===================================================================
--- scribus/plugins/scriptplugin/cmdobj.cpp	(Revision 22369)
+++ scribus/plugins/scriptplugin/cmdobj.cpp	(Arbeitskopie)
@@ -16,7 +16,9 @@
 #include "selection.h"
 #include "util_math.h"
 
+#include "scriptercore.h"
 
+
 PyObject *scribus_newrect(PyObject* /* self */, PyObject* args)
 {
 	double x, y, w, h;
@@ -43,7 +45,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
+	return Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
 }
 
 
@@ -69,7 +71,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
+	return Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
 }
 
 
@@ -94,7 +96,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
+	return Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
 }
 
 
@@ -119,7 +121,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
+	return Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->Items->at(i)->itemName().toUtf8());
 }
 
 PyObject *scribus_newtable(PyObject* /* self */, PyObject* args)
@@ -155,7 +157,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(table->itemName().toUtf8());
+	return Legacy_PyString_FromString(table->itemName().toUtf8());
 }
 
 PyObject *scribus_newline(PyObject* /* self */, PyObject* args)
@@ -215,7 +217,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(i)->setItemName(objName);
 	}
-	return PyString_FromString(it->itemName().toUtf8());
+	return Legacy_PyString_FromString(it->itemName().toUtf8());
 }
 
 
@@ -292,7 +294,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(ic)->setItemName(objName);
 	}
-	return PyString_FromString(it->itemName().toUtf8());
+	return Legacy_PyString_FromString(it->itemName().toUtf8());
 }
 
 
@@ -374,7 +376,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(ic)->setItemName(objName);
 	}
-	return PyString_FromString(it->itemName().toUtf8());
+	return Legacy_PyString_FromString(it->itemName().toUtf8());
 }
 
 PyObject *scribus_bezierline(PyObject* /* self */, PyObject* args)
@@ -465,7 +467,7 @@
 		if (!ItemExists(objName))
 			ScCore->primaryMainWindow()->doc->Items->at(ic)->setItemName(objName);
 	}
-	return PyString_FromString(it->itemName().toUtf8());
+	return Legacy_PyString_FromString(it->itemName().toUtf8());
 }
 
 
@@ -506,7 +508,7 @@
 		if (!ItemExists(objName))
 			i->setItemName(objName);
 	}
-	return PyString_FromString(i->itemName().toUtf8());
+	return Legacy_PyString_FromString(i->itemName().toUtf8());
 }
 
 
@@ -527,6 +529,9 @@
 	ScCore->primaryMainWindow()->doc->itemSelection_DeleteItem();
 //	Py_INCREF(Py_None);
 //	return Py_None;
+	
+	emit scripterCore->checkpoint(10);
+	
 	Py_RETURN_NONE;
 }
 
@@ -760,7 +765,7 @@
 	styleList = PyList_New(0);
 	for (int i=0; i < ScCore->primaryMainWindow()->doc->paragraphStyles().count(); ++i)
 	{
-		if (PyList_Append(styleList, PyString_FromString(ScCore->primaryMainWindow()->doc->paragraphStyles()[i].name().toUtf8())))
+		if (PyList_Append(styleList, Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->paragraphStyles()[i].name().toUtf8())))
 		{
 			// An exception will have already been set by PyList_Append apparently.
 			return NULL;
@@ -777,7 +782,7 @@
 	charStyleList = PyList_New(0);
 	for (int i=0; i < ScCore->primaryMainWindow()->doc->charStyles().count(); ++i)
 	{
-		if (PyList_Append(charStyleList, PyString_FromString(ScCore->primaryMainWindow()->doc->charStyles()[i].name().toUtf8())))
+		if (PyList_Append(charStyleList, Legacy_PyString_FromString(ScCore->primaryMainWindow()->doc->charStyles()[i].name().toUtf8())))
 		{
 			// An exception will have already been set by PyList_Append apparently.
 			return NULL;
@@ -786,16 +791,82 @@
 	return charStyleList;
 }
 
+PyObject *scribus_renameobject(PyObject * /* self */, PyObject *args)
+{
+	char* origname = const_cast<char*>("");
+	char* newname = const_cast<char*>("");
+	if (!PyArg_ParseTuple(args, "es|es", "utf-8", &newname, "utf-8", &origname)) {
+		Py_RETURN_NONE;
+	}
+	if(!checkHaveDocument()) {
+		Py_RETURN_NONE;
+	}
+	
+	PageItem *src = GetUniqueItem(QString::fromUtf8(origname));
+	if (src == NULL) {
+		qDebug() << QString("Cannot get item \"%1\".").arg(origname);
+		Py_RETURN_NONE;
+	}
+	
+	src->setItemName(newname);
+	if (src->itemName() != newname)
+	{
+		PyErr_SetString(
+			NameExistsError,
+			QObject::tr("An object with the requested name already exists.",
+			            "python error").toUtf8().constData());
+		src->setItemName(origname);
+		qDebug() << QString("Wanted back to \"%1\", got \"%2\".").arg(origname, src->itemName());
+		Py_RETURN_NONE;
+	}
+	
+	emit scripterCore->checkpoint(5);
+	
+	return Legacy_PyString_FromString(src->itemName().toUtf8());
+}
+
 PyObject *scribus_duplicateobject(PyObject * /* self */, PyObject *args)
 {
 	char* name = const_cast<char*>("");
+	char* newname = const_cast<char*>("");
+	if (!PyArg_ParseTuple(args, "|eses", "utf-8", &newname, "utf-8", &name)) {
+		Py_RETURN_NONE;
+	}
+	if(!checkHaveDocument()) {
+		Py_RETURN_NONE;
+	}
+	// We require a name given and duplicate only one object at one time.
+	PageItem *src = GetUniqueItem(QString::fromUtf8(name));
+	if (src == NULL) {
+		qDebug() << "Cannot duplicate NULL.";
+		Py_RETURN_NONE;
+	}
+	
+	QString qnewname = QString::fromUtf8(newname);
+	
+	// do the duplicate
+	PageItem *dst = ScCore->primaryMainWindow()->slotDuplicateSingle(src, &qnewname);
+	
+	if (dst == NULL) {
+		emit scripterCore->checkpoint(4);
+		Py_RETURN_NONE;
+	}
+	
+	emit scripterCore->checkpoint(12);
+	
+	return Legacy_PyString_FromString(dst->itemName().toUtf8());
+}
+
+PyObject *scribus_duplicateobject_legacy(PyObject * /* self */, PyObject *args)
+{
+	char* name = const_cast<char*>("");
 	if (!PyArg_ParseTuple(args, "|es", "utf-8", &name)) {
-		return NULL;
+		Py_RETURN_NONE;
 	}
 	if(!checkHaveDocument()) {
-		return NULL;
+		Py_RETURN_NONE;
 	}
-	// Is there a special name given? Yes -> add this to selection
+	// Is there a special name given? Yes -> make a selection of it
 	PageItem *i = GetUniqueItem(QString::fromUtf8(name));
 	if (i != NULL) {
 		ScCore->primaryMainWindow()->doc->m_Selection->clear();
@@ -802,12 +873,15 @@
 		ScCore->primaryMainWindow()->doc->m_Selection->addItem(i);
 	}
 	else
-		return NULL;
+		Py_RETURN_NONE;
 	// do the duplicate
 	ScCore->primaryMainWindow()->slotEditCopy();
 	ScCore->primaryMainWindow()->slotEditPaste();
 //	Py_INCREF(Py_None);
 //	return Py_None;
+	
+	emit scripterCore->checkpoint(20);
+	
 	Py_RETURN_NONE;
 }
 
@@ -855,8 +929,8 @@
 /*! HACK: this removes "warning: 'blah' defined but not used" compiler warnings
 with header files structure untouched (docstrings are kept near declarations)
 PV */
-void cmdobjdocwarnings()
+inline void cmdobjdocwarnings()
 {
 	QStringList s;
-	s << scribus_newrect__doc__ <<scribus_newellipse__doc__ << scribus_newimage__doc__ << scribus_newtext__doc__ << scribus_newtable__doc__ << scribus_newline__doc__ <<scribus_polyline__doc__ << scribus_polygon__doc__ << scribus_bezierline__doc__ <<scribus_pathtext__doc__ <<scribus_deleteobj__doc__ <<scribus_textflow__doc__ <<scribus_objectexists__doc__ <<scribus_setstyle__doc__ <<scribus_getstylenames__doc__ <<scribus_getcharstylenames__doc__ <<scribus_duplicateobject__doc__ <<scribus_copyobject__doc__ <<scribus_pasteobject__doc__;
+	s << scribus_newrect__doc__ <<scribus_newellipse__doc__ << scribus_newimage__doc__ << scribus_newtext__doc__ << scribus_newtable__doc__ << scribus_newline__doc__ <<scribus_polyline__doc__ << scribus_polygon__doc__ << scribus_bezierline__doc__ <<scribus_pathtext__doc__ <<scribus_deleteobj__doc__ <<scribus_textflow__doc__ <<scribus_objectexists__doc__ <<scribus_setstyle__doc__ <<scribus_setcharstyle__doc__ <<scribus_getstylenames__doc__ <<scribus_getcharstylenames__doc__ <<scribus_renameobject__doc__ <<scribus_duplicateobject__doc__ <<scribus_duplicateobject__doc__ <<scribus_duplicateobject_legacy__doc__ <<scribus_copyobject__doc__ <<scribus_pasteobject__doc__;
 }

u ltd.

2018-02-05 09:51

reporter   ~0044916

This is a feature request, not an issue - sorry for wrong metadata.

Issue History

Date Modified Username Field Change
2018-02-05 09:49 u ltd. New Issue
2018-02-05 09:49 u ltd. File Added: scribus-20180205-095552-jonas-duplicate.patch
2018-02-05 09:49 u ltd. File Added: scribus-20180205-095552-jonas-duplicate_python_invokation.patch
2018-02-05 09:49 u ltd. Tag Attached: patch
2018-02-05 09:49 u ltd. Tag Attached: script
2018-02-05 09:51 u ltd. Note Added: 0044916
2018-02-05 10:11 jghali Severity tweak => feature
2018-02-05 11:53 JLuc Additional Information Updated