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 "importcdr.h"
21 #include "../revenge/rawpainter.h"
22 #include <libcdr/libcdr.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 
CdrPlug(ScribusDoc * doc,int flags)54 CdrPlug::CdrPlug(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 CdrPlug::readThumbnail(const QString& fName)
68 {
69 	QFileInfo fi = QFileInfo(fName);
70 	double b, h;
71 	b = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
72 	h = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
73 	docWidth = b;
74 	docHeight = h;
75 	progressDialog = nullptr;
76 	m_Doc = new ScribusDoc();
77 	m_Doc->setup(0, 1, 1, 1, 1, "Custom", "Custom");
78 	m_Doc->setPage(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false);
79 	m_Doc->addPage(0);
80 	m_Doc->setGUI(false, ScCore->primaryMainWindow(), nullptr);
81 	baseX = m_Doc->currentPage()->xOffset();
82 	baseY = m_Doc->currentPage()->yOffset();
83 	Elements.clear();
84 	m_Doc->setLoading(true);
85 	m_Doc->DoDrawing = false;
86 	m_Doc->scMW()->setScriptRunning(true);
87 	QString CurDirP = QDir::currentPath();
88 	QDir::setCurrent(fi.path());
89 	if (convert(fName))
90 	{
91 		tmpSel->clear();
92 		QDir::setCurrent(CurDirP);
93 		if (Elements.count() > 1)
94 			m_Doc->groupObjectsList(Elements);
95 		m_Doc->DoDrawing = true;
96 		m_Doc->m_Selection->delaySignalsOn();
97 		QImage tmpImage;
98 		if (Elements.count() > 0)
99 		{
100 			for (int dre=0; dre<Elements.count(); ++dre)
101 			{
102 				tmpSel->addItem(Elements.at(dre), true);
103 			}
104 			tmpSel->setGroupRect();
105 			double xs = tmpSel->width();
106 			double ys = tmpSel->height();
107 			tmpImage = Elements.at(0)->DrawObj_toImage(500);
108 			tmpImage.setText("XSize", QString("%1").arg(xs));
109 			tmpImage.setText("YSize", QString("%1").arg(ys));
110 		}
111 		m_Doc->scMW()->setScriptRunning(false);
112 		m_Doc->setLoading(false);
113 		m_Doc->m_Selection->delaySignalsOff();
114 		delete m_Doc;
115 		return tmpImage;
116 	}
117 	QDir::setCurrent(CurDirP);
118 	m_Doc->DoDrawing = true;
119 	m_Doc->scMW()->setScriptRunning(false);
120 	delete m_Doc;
121 	return QImage();
122 }
123 
import(const QString & fNameIn,const TransactionSettings & trSettings,int flags,bool showProgress)124 bool CdrPlug::import(const QString& fNameIn, const TransactionSettings& trSettings, int flags, bool showProgress)
125 {
126 	bool success = false;
127 	interactive = (flags & LoadSavePlugin::lfInteractive);
128 	importerFlags = flags;
129 	cancel = false;
130 	double b, h;
131 	bool ret = false;
132 	QFileInfo fi = QFileInfo(fNameIn);
133 	if ( !ScCore->usingGUI() )
134 	{
135 		interactive = false;
136 		showProgress = false;
137 	}
138 	if ( showProgress )
139 	{
140 		ScribusMainWindow* mw=(m_Doc==nullptr) ? ScCore->primaryMainWindow() : m_Doc->scMW();
141 		progressDialog = new MultiProgressDialog( tr("Importing: %1").arg(fi.fileName()), CommonStrings::tr_Cancel, mw );
142 		QStringList barNames, barTexts;
143 		barNames << "GI";
144 		barTexts << tr("Analyzing File:");
145 		QList<bool> barsNumeric;
146 		barsNumeric << false;
147 		progressDialog->addExtraProgressBars(barNames, barTexts, barsNumeric);
148 		progressDialog->setOverallTotalSteps(3);
149 		progressDialog->setOverallProgress(0);
150 		progressDialog->setProgress("GI", 0);
151 		progressDialog->show();
152 		connect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelRequested()));
153 		qApp->processEvents();
154 	}
155 	else
156 		progressDialog = nullptr;
157 /* Set default Page to size defined in Preferences */
158 	b = 0.0;
159 	h = 0.0;
160 	if (progressDialog)
161 	{
162 		progressDialog->setOverallProgress(1);
163 		qApp->processEvents();
164 	}
165 	if (b == 0.0)
166 		b = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
167 	if (h == 0.0)
168 		h = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
169 	docWidth = b;
170 	docHeight = h;
171 	baseX = 0;
172 	baseY = 0;
173 	if (!interactive || (flags & LoadSavePlugin::lfInsertPage))
174 	{
175 		m_Doc->setPage(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false);
176 		m_Doc->addPage(0);
177 		m_Doc->view()->addPage(0, true);
178 		baseX = 0;
179 		baseY = 0;
180 	}
181 	else
182 	{
183 		if (!m_Doc || (flags & LoadSavePlugin::lfCreateDoc))
184 		{
185 			m_Doc=ScCore->primaryMainWindow()->doFileNew(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false, 0, false, 0, 1, "Custom", true);
186 			ScCore->primaryMainWindow()->HaveNewDoc();
187 			ret = true;
188 			baseX = 0;
189 			baseY = 0;
190 			baseX = m_Doc->currentPage()->xOffset();
191 			baseY = m_Doc->currentPage()->yOffset();
192 		}
193 	}
194 	if ((!ret) && (interactive))
195 	{
196 		baseX = m_Doc->currentPage()->xOffset();
197 		baseY = m_Doc->currentPage()->yOffset();
198 	}
199 	if ((ret) || (!interactive))
200 	{
201 		if (docWidth > docHeight)
202 			m_Doc->setPageOrientation(1);
203 		else
204 			m_Doc->setPageOrientation(0);
205 		m_Doc->setPageSize("Custom");
206 	}
207 	if ((!(flags & LoadSavePlugin::lfLoadAsPattern)) && (m_Doc->view() != nullptr))
208 		m_Doc->view()->deselectItems();
209 	Elements.clear();
210 	m_Doc->setLoading(true);
211 	m_Doc->DoDrawing = false;
212 	if ((!(flags & LoadSavePlugin::lfLoadAsPattern)) && (m_Doc->view() != nullptr))
213 		m_Doc->view()->updatesOn(false);
214 	m_Doc->scMW()->setScriptRunning(true);
215 	qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
216 	QString CurDirP = QDir::currentPath();
217 	QDir::setCurrent(fi.path());
218 	if (convert(fNameIn))
219 	{
220 		tmpSel->clear();
221 		QDir::setCurrent(CurDirP);
222 		if ((Elements.count() > 1) && (!(importerFlags & LoadSavePlugin::lfCreateDoc)))
223 			m_Doc->groupObjectsList(Elements);
224 		m_Doc->DoDrawing = true;
225 		m_Doc->scMW()->setScriptRunning(false);
226 		m_Doc->setLoading(false);
227 		qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
228 		if ((Elements.count() > 0) && (!ret) && (interactive))
229 		{
230 			if (flags & LoadSavePlugin::lfScripted)
231 			{
232 				bool loadF = m_Doc->isLoading();
233 				m_Doc->setLoading(false);
234 				m_Doc->changed();
235 				m_Doc->setLoading(loadF);
236 				if (!(flags & LoadSavePlugin::lfLoadAsPattern))
237 				{
238 					m_Doc->m_Selection->delaySignalsOn();
239 					for (int dre=0; dre<Elements.count(); ++dre)
240 					{
241 						m_Doc->m_Selection->addItem(Elements.at(dre), true);
242 					}
243 					m_Doc->m_Selection->delaySignalsOff();
244 					m_Doc->m_Selection->setGroupRect();
245 					if (m_Doc->view() != nullptr)
246 						m_Doc->view()->updatesOn(true);
247 				}
248 			}
249 			else
250 			{
251 				m_Doc->DragP = true;
252 				m_Doc->DraggedElem = nullptr;
253 				m_Doc->DragElements.clear();
254 				m_Doc->m_Selection->delaySignalsOn();
255 				for (int dre=0; dre<Elements.count(); ++dre)
256 				{
257 					tmpSel->addItem(Elements.at(dre), true);
258 				}
259 				tmpSel->setGroupRect();
260 				ScElemMimeData* md = ScriXmlDoc::writeToMimeData(m_Doc, tmpSel);
261 				m_Doc->itemSelection_DeleteItem(tmpSel);
262 				m_Doc->view()->updatesOn(true);
263 				if (importedPatterns.count() != 0)
264 				{
265 					for (int cd = 0; cd < importedPatterns.count(); cd++)
266 					{
267 						m_Doc->docPatterns.remove(importedPatterns[cd]);
268 					}
269 				}
270 				if (importedColors.count() != 0)
271 				{
272 					for (int cd = 0; cd < importedColors.count(); cd++)
273 					{
274 						m_Doc->PageColors.remove(importedColors[cd]);
275 					}
276 				}
277 				m_Doc->m_Selection->delaySignalsOff();
278 				// We must copy the TransationSettings object as it is owned
279 				// by handleObjectImport method afterwards
280 				TransactionSettings* transacSettings = new TransactionSettings(trSettings);
281 				m_Doc->view()->handleObjectImport(md, transacSettings);
282 				m_Doc->DragP = false;
283 				m_Doc->DraggedElem = nullptr;
284 				m_Doc->DragElements.clear();
285 			}
286 		}
287 		else
288 		{
289 			m_Doc->changed();
290 			m_Doc->reformPages();
291 			if (!(flags & LoadSavePlugin::lfLoadAsPattern))
292 				m_Doc->view()->updatesOn(true);
293 		}
294 		success = true;
295 	}
296 	else
297 	{
298 		QDir::setCurrent(CurDirP);
299 		m_Doc->DoDrawing = true;
300 		m_Doc->scMW()->setScriptRunning(false);
301 		m_Doc->view()->updatesOn(true);
302 		qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
303 	}
304 	if (interactive)
305 		m_Doc->setLoading(false);
306 	//CB If we have a gui we must refresh it if we have used the progressbar
307 	if (!(flags & LoadSavePlugin::lfLoadAsPattern))
308 	{
309 		if ((showProgress) && (!interactive))
310 			m_Doc->view()->DrawNew();
311 	}
312 	qApp->restoreOverrideCursor();
313 	return success;
314 }
315 
~CdrPlug()316 CdrPlug::~CdrPlug()
317 {
318 	delete progressDialog;
319 	delete tmpSel;
320 }
321 
convert(const QString & fn)322 bool CdrPlug::convert(const QString& fn)
323 {
324 	importedColors.clear();
325 	importedPatterns.clear();
326 
327 	QFile file(fn);
328 	if  (!file.exists())
329 	{
330 		qDebug() << "File " << QFile::encodeName(fn).data() << " does not exist";
331 		return false;
332 	}
333 	QFileInfo fi = QFileInfo(fn);
334 	QString ext = fi.suffix().toLower();
335 #if HAVE_REVENGE
336 	librevenge::RVNGFileStream input(QFile::encodeName(fn).data());
337 #else
338 	WPXFileStream input(QFile::encodeName(fn).data());
339 #endif
340 	bool fail = false;
341 	if (ext == "cdr")
342 	{
343 		if (!libcdr::CDRDocument::isSupported(&input))
344 		{
345 			qDebug() << "ERROR: Unsupported file format!";
346 			fail = true;
347 		}
348 		if (!fail)
349 		{
350 			RawPainter painter(m_Doc, baseX, baseY, docWidth, docHeight, importerFlags, &Elements, &importedColors, &importedPatterns, tmpSel, "cdr");
351 			if (!libcdr::CDRDocument::parse(&input, &painter))
352 				fail = true;
353 		}
354 		if (fail)
355 		{
356 			qDebug() << "ERROR: Parsing failed!";
357 			if (progressDialog)
358 				progressDialog->close();
359 		/*	if (importerFlags & LoadSavePlugin::lfCreateDoc)
360 			{
361 				ScribusMainWindow* mw=(m_Doc==0) ? ScCore->primaryMainWindow() : m_Doc->scMW();
362 				qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
363 				ScMessageBox::warning(mw, CommonStrings::trWarning, tr("Parsing failed!\n\nPlease submit your file (if possible) to the\nDocument Liberation Project http://www.documentliberation.org"));
364 				qApp->changeOverrideCursor(QCursor(Qt::WaitCursor));
365 			}*/
366 			return false;
367 		}
368 	}
369 	else if (ext == "cmx")
370 	{
371 		if (!libcdr::CMXDocument::isSupported(&input))
372 		{
373 			qDebug() << "ERROR: Unsupported file format!";
374 			return false;
375 		}
376 		RawPainter painter(m_Doc, baseX, baseY, docWidth, docHeight, importerFlags, &Elements, &importedColors, &importedPatterns, tmpSel, "cmx");
377 		if (!libcdr::CMXDocument::parse(&input, &painter))
378 		{
379 			qDebug() << "ERROR: Parsing failed!";
380 			if (progressDialog)
381 				progressDialog->close();
382 			if (importerFlags & LoadSavePlugin::lfCreateDoc)
383 			{
384 				ScribusMainWindow* mw=(m_Doc==nullptr) ? ScCore->primaryMainWindow() : m_Doc->scMW();
385 				qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
386 				ScMessageBox::warning(mw, CommonStrings::trWarning, tr("Parsing failed!\n\nPlease submit your file (if possible) to the\nDocument Liberation Project http://www.documentliberation.org"));
387 				qApp->changeOverrideCursor(QCursor(Qt::WaitCursor));
388 			}
389 			return false;
390 		}
391 	}
392 	else
393 		return false;
394 	if (Elements.count() == 0)
395 	{
396 		if (importedColors.count() != 0)
397 		{
398 			for (int cd = 0; cd < importedColors.count(); cd++)
399 			{
400 				m_Doc->PageColors.remove(importedColors[cd]);
401 			}
402 		}
403 		if (importedPatterns.count() != 0)
404 		{
405 			for (int cd = 0; cd < importedPatterns.count(); cd++)
406 			{
407 				m_Doc->docPatterns.remove(importedPatterns[cd]);
408 			}
409 		}
410 	}
411 	if (progressDialog)
412 		progressDialog->close();
413 	return true;
414 }
415