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