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