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 <QByteArray>
9 #include <QCursor>
10 #include <QDrag>
11 #include <QFile>
12 #include <QList>
13 #include <QMessageBox>
14 #include <QMimeData>
15 #include <QRegExp>
16 #include <QStack>
17 #include <QDebug>
18 
19 #include <cstdlib>
20 #include "importpm.h"
21 #include "../revenge/rawpainter.h"
22 #include <libpagemaker/libpagemaker.h>
23 
24 #include "commonstrings.h"
25 #include "ui/customfdialog.h"
26 #include "fileloader.h"
27 #include "loadsaveplugin.h"
28 #include "ui/missing.h"
29 #include "ui/multiprogressdialog.h"
30 #include "pagesize.h"
31 #include "prefscontext.h"
32 #include "prefsfile.h"
33 #include "prefsmanager.h"
34 #include "prefstable.h"
35 #include "ui/propertiespalette.h"
36 #include "rawimage.h"
37 #include "scclocale.h"
38 #include "sccolorengine.h"
39 #include "scconfig.h"
40 #include "scmimedata.h"
41 #include "scpaths.h"
42 #include "scpattern.h"
43 #include "scribus.h"
44 #include "scribusXml.h"
45 #include "scribuscore.h"
46 #include "scribusview.h"
47 #include "sctextstream.h"
48 #include "selection.h"
49 #include "undomanager.h"
50 #include "util.h"
51 #include "util_formats.h"
52 #include "util_math.h"
53 
PmPlug(ScribusDoc * doc,int flags)54 PmPlug::PmPlug(ScribusDoc* doc, int flags)
55 {
56 	baseX = baseY = 0;
57 	docWidth = docHeight = 1;
58 
59 	tmpSel = new Selection(this, false);
60 	m_Doc = doc;
61 	importerFlags = flags;
62 	interactive = (flags & LoadSavePlugin::lfInteractive);
63 	progressDialog = nullptr;
64 	cancel = false;
65 }
66 
readThumbnail(const QString & fName)67 QImage PmPlug::readThumbnail(const QString& fName)
68 {
69 	QFileInfo fi = QFileInfo(fName);
70 	docWidth = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
71 	docHeight = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
72 	progressDialog = nullptr;
73 	m_Doc = new ScribusDoc();
74 	m_Doc->setup(0, 1, 1, 1, 1, "Custom", "Custom");
75 	m_Doc->setPage(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false);
76 	m_Doc->addPage(0);
77 	m_Doc->setGUI(false, ScCore->primaryMainWindow(), nullptr);
78 	baseX = m_Doc->currentPage()->xOffset();
79 	baseY = m_Doc->currentPage()->yOffset();
80 	Elements.clear();
81 	m_Doc->setLoading(true);
82 	m_Doc->DoDrawing = false;
83 	m_Doc->scMW()->setScriptRunning(true);
84 	QString CurDirP = QDir::currentPath();
85 	QDir::setCurrent(fi.path());
86 	if (convert(fName))
87 	{
88 		tmpSel->clear();
89 		QDir::setCurrent(CurDirP);
90 		if (Elements.count() > 1)
91 			m_Doc->groupObjectsList(Elements);
92 		m_Doc->DoDrawing = true;
93 		m_Doc->m_Selection->delaySignalsOn();
94 		QImage tmpImage;
95 		if (Elements.count() > 0)
96 		{
97 			for (int dre=0; dre<Elements.count(); ++dre)
98 			{
99 				tmpSel->addItem(Elements.at(dre), true);
100 			}
101 			tmpSel->setGroupRect();
102 			double xs = tmpSel->width();
103 			double ys = tmpSel->height();
104 			tmpImage = Elements.at(0)->DrawObj_toImage(500);
105 			tmpImage.setText("XSize", QString("%1").arg(xs));
106 			tmpImage.setText("YSize", QString("%1").arg(ys));
107 		}
108 		m_Doc->scMW()->setScriptRunning(false);
109 		m_Doc->setLoading(false);
110 		m_Doc->m_Selection->delaySignalsOff();
111 		delete m_Doc;
112 		return tmpImage;
113 	}
114 	QDir::setCurrent(CurDirP);
115 	m_Doc->DoDrawing = true;
116 	m_Doc->scMW()->setScriptRunning(false);
117 	delete m_Doc;
118 	return QImage();
119 }
120 
import(const QString & fNameIn,const TransactionSettings & trSettings,int flags,bool showProgress)121 bool PmPlug::import(const QString& fNameIn, const TransactionSettings& trSettings, int flags, bool showProgress)
122 {
123 	bool success = false;
124 	interactive = (flags & LoadSavePlugin::lfInteractive);
125 	importerFlags = flags;
126 	cancel = false;
127 	bool ret = false;
128 	QFileInfo fi = QFileInfo(fNameIn);
129 	if ( !ScCore->usingGUI() )
130 	{
131 		interactive = false;
132 		showProgress = false;
133 	}
134 	if ( showProgress )
135 	{
136 		ScribusMainWindow* mw=(m_Doc==nullptr) ? ScCore->primaryMainWindow() : m_Doc->scMW();
137 		progressDialog = new MultiProgressDialog( tr("Importing: %1").arg(fi.fileName()), CommonStrings::tr_Cancel, mw );
138 		QStringList barNames, barTexts;
139 		barNames << "GI";
140 		barTexts << tr("Analyzing File:");
141 		QList<bool> barsNumeric;
142 		barsNumeric << false;
143 		progressDialog->addExtraProgressBars(barNames, barTexts, barsNumeric);
144 		progressDialog->setOverallTotalSteps(3);
145 		progressDialog->setOverallProgress(0);
146 		progressDialog->setProgress("GI", 0);
147 		progressDialog->show();
148 		connect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelRequested()));
149 		qApp->processEvents();
150 	}
151 	else
152 		progressDialog = nullptr;
153 /* Set default Page to size defined in Preferences */
154 	double w = 0.0;
155 	double h = 0.0;
156 	if (progressDialog)
157 	{
158 		progressDialog->setOverallProgress(1);
159 		qApp->processEvents();
160 	}
161 	if (w == 0.0)
162 		w = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
163 	if (h == 0.0)
164 		h = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
165 	docWidth = w;
166 	docHeight = h;
167 	baseX = 0;
168 	baseY = 0;
169 	if (!interactive || (flags & LoadSavePlugin::lfInsertPage))
170 	{
171 		m_Doc->setPage(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false);
172 		m_Doc->addPage(0);
173 		m_Doc->view()->addPage(0, true);
174 		baseX = 0;
175 		baseY = 0;
176 	}
177 	else
178 	{
179 		if (!m_Doc || (flags & LoadSavePlugin::lfCreateDoc))
180 		{
181 			m_Doc=ScCore->primaryMainWindow()->doFileNew(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false, 0, false, 0, 1, "Custom", true);
182 			ScCore->primaryMainWindow()->HaveNewDoc();
183 			ret = true;
184 			baseX = 0;
185 			baseY = 0;
186 			baseX = m_Doc->currentPage()->xOffset();
187 			baseY = m_Doc->currentPage()->yOffset();
188 		}
189 	}
190 	if ((!ret) && (interactive))
191 	{
192 		baseX = m_Doc->currentPage()->xOffset();
193 		baseY = m_Doc->currentPage()->yOffset();
194 	}
195 	if ((ret) || (!interactive))
196 	{
197 		if (docWidth > docHeight)
198 			m_Doc->setPageOrientation(1);
199 		else
200 			m_Doc->setPageOrientation(0);
201 		m_Doc->setPageSize("Custom");
202 	}
203 	if ((!(flags & LoadSavePlugin::lfLoadAsPattern)) && (m_Doc->view() != nullptr))
204 		m_Doc->view()->deselectItems();
205 	Elements.clear();
206 	m_Doc->setLoading(true);
207 	m_Doc->DoDrawing = false;
208 	if ((!(flags & LoadSavePlugin::lfLoadAsPattern)) && (m_Doc->view() != nullptr))
209 		m_Doc->view()->updatesOn(false);
210 	m_Doc->scMW()->setScriptRunning(true);
211 	qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
212 	QString CurDirP = QDir::currentPath();
213 	QDir::setCurrent(fi.path());
214 	if (convert(fNameIn))
215 	{
216 		tmpSel->clear();
217 		QDir::setCurrent(CurDirP);
218 		if ((Elements.count() > 1) && (!(importerFlags & LoadSavePlugin::lfCreateDoc)))
219 			m_Doc->groupObjectsList(Elements);
220 		m_Doc->DoDrawing = true;
221 		m_Doc->scMW()->setScriptRunning(false);
222 		m_Doc->setLoading(false);
223 		qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
224 		if ((Elements.count() > 0) && (!ret) && (interactive))
225 		{
226 			if (flags & LoadSavePlugin::lfScripted)
227 			{
228 				bool loadF = m_Doc->isLoading();
229 				m_Doc->setLoading(false);
230 				m_Doc->changed();
231 				m_Doc->setLoading(loadF);
232 				if (!(flags & LoadSavePlugin::lfLoadAsPattern))
233 				{
234 					m_Doc->m_Selection->delaySignalsOn();
235 					for (int dre=0; dre<Elements.count(); ++dre)
236 					{
237 						m_Doc->m_Selection->addItem(Elements.at(dre), true);
238 					}
239 					m_Doc->m_Selection->delaySignalsOff();
240 					m_Doc->m_Selection->setGroupRect();
241 					if (m_Doc->view() != nullptr)
242 						m_Doc->view()->updatesOn(true);
243 				}
244 			}
245 			else
246 			{
247 				m_Doc->DragP = true;
248 				m_Doc->DraggedElem = nullptr;
249 				m_Doc->DragElements.clear();
250 				m_Doc->m_Selection->delaySignalsOn();
251 				for (int i=0; i<Elements.count(); ++i)
252 				{
253 					tmpSel->addItem(Elements.at(i), true);
254 				}
255 				tmpSel->setGroupRect();
256 				ScElemMimeData* md = ScriXmlDoc::writeToMimeData(m_Doc, tmpSel);
257 				m_Doc->itemSelection_DeleteItem(tmpSel);
258 				m_Doc->view()->updatesOn(true);
259 				if (importedPatterns.count() != 0)
260 				{
261 					for (int i = 0; i < importedPatterns.count(); i++)
262 					{
263 						m_Doc->docPatterns.remove(importedPatterns[i]);
264 					}
265 				}
266 				if (importedColors.count() != 0)
267 				{
268 					for (int i = 0; i < importedColors.count(); i++)
269 					{
270 						m_Doc->PageColors.remove(importedColors[i]);
271 					}
272 				}
273 				m_Doc->m_Selection->delaySignalsOff();
274 				// We must copy the TransationSettings object as it is owned
275 				// by handleObjectImport method afterwards
276 				TransactionSettings* transacSettings = new TransactionSettings(trSettings);
277 				m_Doc->view()->handleObjectImport(md, transacSettings);
278 				m_Doc->DragP = false;
279 				m_Doc->DraggedElem = nullptr;
280 				m_Doc->DragElements.clear();
281 			}
282 		}
283 		else
284 		{
285 			m_Doc->changed();
286 			m_Doc->reformPages();
287 			if (!(flags & LoadSavePlugin::lfLoadAsPattern))
288 				m_Doc->view()->updatesOn(true);
289 		}
290 		success = true;
291 	}
292 	else
293 	{
294 		QDir::setCurrent(CurDirP);
295 		m_Doc->DoDrawing = true;
296 		m_Doc->scMW()->setScriptRunning(false);
297 		m_Doc->view()->updatesOn(true);
298 		qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
299 	}
300 	if (interactive)
301 		m_Doc->setLoading(false);
302 	//CB If we have a gui we must refresh it if we have used the progressbar
303 	if (!(flags & LoadSavePlugin::lfLoadAsPattern))
304 	{
305 		if ((showProgress) && (!interactive))
306 			m_Doc->view()->DrawNew();
307 	}
308 	qApp->restoreOverrideCursor();
309 	return success;
310 }
311 
~PmPlug()312 PmPlug::~PmPlug()
313 {
314 	delete progressDialog;
315 	delete tmpSel;
316 }
317 
convert(const QString & fn)318 bool PmPlug::convert(const QString& fn)
319 {
320 	importedColors.clear();
321 	importedPatterns.clear();
322 
323 	QFile file(fn);
324 	if (!file.exists())
325 	{
326 		qDebug() << "File " << QFile::encodeName(fn).data() << " does not exist";
327 		return false;
328 	}
329 
330 	librevenge::RVNGFileStream input(QFile::encodeName(fn).data());
331 	if (!libpagemaker::PMDocument::isSupported(&input))
332 	{
333 		qDebug() << "ERROR: Unsupported file format!";
334 		return false;
335 	}
336 	RawPainter painter(m_Doc, baseX, baseY, docWidth, docHeight, importerFlags, &Elements, &importedColors, &importedPatterns, tmpSel, "pmd");
337 	if (!libpagemaker::PMDocument::parse(&input, &painter))
338 	{
339 		qDebug() << "ERROR: Import failed!";
340 		if (progressDialog)
341 			progressDialog->close();
342 		if (importerFlags & LoadSavePlugin::lfCreateDoc)
343 		{
344 			ScribusMainWindow* mw=(m_Doc==nullptr) ? ScCore->primaryMainWindow() : m_Doc->scMW();
345 			qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
346 			ScMessageBox::warning(mw, CommonStrings::trWarning, tr("Parsing failed!\n\nPlease submit your file (if possible) to the\nDocument Liberation Project http://www.documentliberation.org"));
347 			qApp->changeOverrideCursor(QCursor(Qt::WaitCursor));
348 		}
349 		return false;
350 	}
351 	if (Elements.count() == 0)
352 	{
353 		if (importedColors.count() != 0)
354 		{
355 			for (int i = 0; i < importedColors.count(); i++)
356 			{
357 				m_Doc->PageColors.remove(importedColors[i]);
358 			}
359 		}
360 		if (importedPatterns.count() != 0)
361 		{
362 			for (int i = 0; i < importedPatterns.count(); i++)
363 			{
364 				m_Doc->docPatterns.remove(importedPatterns[i]);
365 			}
366 		}
367 	}
368 	if (progressDialog)
369 		progressDialog->close();
370 	return true;
371 }
372