1 /*
2 For general Scribus (>=1.3.2) copyright and licensing information please refer
3 to the COPYING file provided with the program. Following this notice may exist
4 a copyright and/or license notice that predates the release of Scribus 1.3.2
5 for which a new license (GPL+exception) is in place.
6 */
7 
8 #include "cmdutil.h"
9 #include "prefsmanager.h"
10 #include "resourcecollection.h"
11 #include "scpage.h"
12 #include "scribuscore.h"
13 #include "scribusdoc.h"
14 #include "scribusview.h"
15 #include "selection.h"
16 #include "tableborder.h"
17 #include "units.h"
18 
19 #include <QMap>
20 
21 /// Convert a value in points to a value in the current document units
PointToValue(double Val)22 double PointToValue(double Val)
23 {
24 	return pts2value(Val, ScCore->primaryMainWindow()->doc->unitIndex());
25 }
26 
27 /// Convert a value in the current document units to a value in points
ValueToPoint(double Val)28 double ValueToPoint(double Val)
29 {
30 	return value2pts(Val, ScCore->primaryMainWindow()->doc->unitIndex());
31 }
32 
33 /// Convert an X co-ordinate part in page units to a document co-ordinate
34 /// in system units.
pageUnitXToDocX(double pageUnitX)35 double pageUnitXToDocX(double pageUnitX)
36 {
37 	return ValueToPoint(pageUnitX) + ScCore->primaryMainWindow()->doc->currentPage()->xOffset();
38 }
39 
40 // Convert doc units to page units
docUnitXToPageX(double pageUnitX)41 double docUnitXToPageX(double pageUnitX)
42 {
43 	return PointToValue(pageUnitX - ScCore->primaryMainWindow()->doc->currentPage()->xOffset());
44 }
45 
46 /// Convert a Y co-ordinate part in page units to a document co-ordinate
47 /// in system units. The document co-ordinates have their origin somewere
48 /// up and left of the first page, where page co-ordinates have their
49 /// origin on the top left of the current page.
pageUnitYToDocY(double pageUnitY)50 double pageUnitYToDocY(double pageUnitY)
51 {
52 	return ValueToPoint(pageUnitY) + ScCore->primaryMainWindow()->doc->currentPage()->yOffset();
53 }
54 
docUnitYToPageY(double pageUnitY)55 double docUnitYToPageY(double pageUnitY)
56 {
57 	return PointToValue(pageUnitY - ScCore->primaryMainWindow()->doc->currentPage()->yOffset());
58 }
59 
GetItem(const QString & name)60 PageItem *GetItem(const QString& name)
61 {
62 	ScribusDoc* currentDoc = ScCore->primaryMainWindow()->doc;
63 	if (!name.isEmpty())
64 	{
65 		for (int i = 0; i < currentDoc->Items->count(); ++i)
66 		{
67 			if (currentDoc->Items->at(i)->itemName() == name)
68 				return currentDoc->Items->at(i);
69 		}
70 	}
71 	else
72 	{
73 		if (currentDoc->m_Selection->count() != 0)
74 			return currentDoc->m_Selection->itemAt(0);
75 	}
76 	return nullptr;
77 }
78 
ReplaceColor(const QString & col,const QString & rep)79 void ReplaceColor(const QString& col, const QString& rep)
80 {
81 	QMap<QString, QString> colorMap;
82 	colorMap.insert(col, rep);
83 
84 	ResourceCollection colorRsc;
85 	colorRsc.mapColor(col, rep);
86 
87 	if (!ScCore->primaryMainWindow()->HaveDoc)
88 		return;
89 	ScribusDoc* doc = ScCore->primaryMainWindow()->doc;
90 
91 	// Update tools colors
92 	PrefsManager::replaceToolColors(doc->itemToolPrefs(), colorRsc.colors());
93 	// Update objects and styles colors
94 	doc->replaceNamedResources(colorRsc);
95 	// Temporary code until LineStyle is effectively used
96 	doc->replaceLineStyleColors(colorMap);
97 }
98 
99 /* 04/07/10 returns selection if is not name specified  pv  */
GetUniqueItem(const QString & name)100 PageItem* GetUniqueItem(const QString& name)
101 {
102 	if (name.length() == 0)
103 	{
104 		if (ScCore->primaryMainWindow()->doc->m_Selection->count() != 0)
105 			return ScCore->primaryMainWindow()->doc->m_Selection->itemAt(0);
106 		PyErr_SetString(NoValidObjectError, QString("Cannot use empty string for object name when there is no selection").toLocal8Bit().constData());
107 		return nullptr;
108 	}
109 	return getPageItemByName(name);
110 }
111 
getPageItemByName(const QString & name)112 PageItem* getPageItemByName(const QString& name)
113 {
114 	if (name.length() == 0)
115 	{
116 		PyErr_SetString(PyExc_ValueError, QString("Cannot accept empty name for pageitem").toLocal8Bit().constData());
117 		return nullptr;
118 	}
119 
120 	ScribusDoc* currentDoc = ScCore->primaryMainWindow()->doc;
121 	for (int i = 0; i < currentDoc->Items->count(); ++i)
122 	{
123 		if (name == currentDoc->Items->at(i)->itemName())
124 			return currentDoc->Items->at(i);
125 	}
126 
127 	PyErr_SetString(NoValidObjectError, QString("Object not found").toLocal8Bit().constData());
128 	return nullptr;
129 }
130 
131 
132 /*!
133  * Checks to see if a pageItem named 'name' exists and return true
134  * if it does exist. Returns false if there is no such object, or
135  * if the empty string ("") is passed.
136  */
ItemExists(const QString & name)137 bool ItemExists(const QString& name)
138 {
139 	if (name.length() == 0)
140 		return false;
141 
142 	ScribusDoc* currentDoc = ScCore->primaryMainWindow()->doc;
143 	for (int i = 0; i < currentDoc->Items->count(); ++i)
144 	{
145 		if (name == currentDoc->Items->at(i)->itemName())
146 			return true;
147 	}
148 	return false;
149 }
150 
151 /*!
152  * Checks to see if there is a document open.
153  * If there is an open document, returns true.
154  * If there is no open document, sets a Python
155  * exception and returns false.
156  * 2004-10-27 Craig Ringer
157  */
checkHaveDocument()158 bool checkHaveDocument()
159 {
160 	if (ScCore->primaryMainWindow()->HaveDoc)
161 		return true;
162 	// Caller is required to check for false return from this function
163 	// and return nullptr.
164 	PyErr_SetString(NoDocOpenError, QString("Command does not make sense without an open document").toLocal8Bit().constData());
165 	return false;
166 }
167 
checkValidPageNumber(int page)168 bool checkValidPageNumber(int page)
169 {
170 	const int numPages = ScCore->primaryMainWindow()->doc->Pages->count();
171 	if (page < 0 || page >= numPages)
172 	{
173 		PyErr_SetString(PyExc_ValueError, QObject::tr("%1 is not a valid page number.", "python error").arg(page).toLocal8Bit().constData());
174 		return false;
175 	}
176 	return true;
177 }
178 
getSelectedItemsByName()179 QStringList getSelectedItemsByName()
180 {
181 	/*
182 	QStringList names;
183 	QPtrListIterator<PageItem> it(ScCore->primaryMainWindow()->view->SelItem);
184 	for ( ; it.current() != 0 ; ++it)
185 		names.append(it.current()->itemName());
186 	return names;
187 	*/
188 	return ScCore->primaryMainWindow()->doc->m_Selection->getSelectedItemsByName();
189 }
190 
setSelectedItemsByName(const QStringList & itemNames)191 bool setSelectedItemsByName(const QStringList& itemNames)
192 {
193 	ScribusDoc* currentDoc =  ScCore->primaryMainWindow()->doc;
194 	ScribusView* currentView = ScCore->primaryMainWindow()->view;
195 
196 	currentView->deselectItems();
197 
198 	// For each named item
199 	for (auto it = itemNames.begin() ; it != itemNames.end() ; it++)
200 	{
201 		// Search for the named item
202 		PageItem* item = nullptr;
203 		for (int j = 0; j < currentDoc->Items->count(); j++)
204 		{
205 			if (*it == currentDoc->Items->at(j)->itemName())
206 				item = currentDoc->Items->at(j);
207 		}
208 		if (!item)
209 			return false;
210 		// And select it
211 		currentView->selectItem(item);
212 	}
213 	return true;
214 }
215 
parseBorder(PyObject * borderLines,bool * ok)216 TableBorder parseBorder(PyObject* borderLines, bool* ok)
217 {
218 	TableBorder border;
219 
220 	if (!PyList_Check(borderLines))
221 	{
222 		PyErr_SetString(PyExc_ValueError, QObject::tr("Expected a list of border lines", "python error").toLocal8Bit().constData());
223 		*ok = false;
224 		return border;
225 	}
226 
227 	// Get the sequence of border lines.
228 	PyObject* borderLinesList = PySequence_List(borderLines);
229 	if (borderLinesList == nullptr)
230 	{
231 		PyErr_SetString(PyExc_ValueError, QObject::tr("Expected a list of border lines", "python error").toLocal8Bit().constData());
232 		*ok = false;
233 		return border;
234 	}
235 
236 	// Parse each tuple decribing a border line and append it to the border.
237 	int nBorderLines = PyList_Size(borderLinesList);
238 	for (int i = 0; i < nBorderLines; ++i)
239 	{
240 		double width = 0.0;
241 		double shade = 100.0;
242 		int style;
243 		char* color;
244 		PyObject* props = PyList_GET_ITEM(borderLinesList, i);
245 		if (!PyArg_ParseTuple(props, "dies|d", &width, &style, "utf-8", &color, &shade))
246 		{
247 			PyErr_SetString(PyExc_ValueError, QObject::tr("Border lines are specified as (width,style,color,shade) tuples", "python error").toLocal8Bit().constData());
248 			*ok = false;
249 			return border;
250 		}
251 		if (width <= 0.0)
252 		{
253 			PyErr_SetString(PyExc_ValueError, QObject::tr("Border line width must be > 0.0", "python error").toLocal8Bit().constData());
254 			*ok = false;
255 			return border;
256 		}
257 		border.addBorderLine(TableBorderLine(width, static_cast<Qt::PenStyle>(style), QString::fromUtf8(color), shade));
258 	}
259 	Py_DECREF(borderLinesList);
260 
261 	*ok = true;
262 	return border;
263 }
264 
PyUnicode_asQString(PyObject * arg)265 QString PyUnicode_asQString(PyObject* arg)
266 {
267 	const char* utf8Str = PyUnicode_AsUTF8(arg);
268 	if (!utf8Str)
269 		return QString();
270 	return QString::fromUtf8(utf8Str);
271 }
272 
273