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 #include <QApplication>
8 #include <QMessageBox>
9 
10 #include "commonstrings.h"
11 
12 #include "importpdf.h"
13 #include "importpdfplugin.h"
14 #include "prefscontext.h"
15 #include "prefsfile.h"
16 #include "prefsmanager.h"
17 #include "scpage.h"
18 #include "scpaths.h"
19 #include "scraction.h"
20 #include "scribuscore.h"
21 #include "undomanager.h"
22 #include "util_formats.h"
23 #include "util.h"
24 
25 #include "ui/customfdialog.h"
26 #include "ui/scmessagebox.h"
27 #include "ui/scmwmenumanager.h"
28 
importpdf_getPluginAPIVersion()29 int importpdf_getPluginAPIVersion()
30 {
31 	return PLUGIN_API_VERSION;
32 }
33 
importpdf_getPlugin()34 ScPlugin* importpdf_getPlugin()
35 {
36 	ImportPdfPlugin* plug = new ImportPdfPlugin();
37 	Q_CHECK_PTR(plug);
38 	return plug;
39 }
40 
importpdf_freePlugin(ScPlugin * plugin)41 void importpdf_freePlugin(ScPlugin* plugin)
42 {
43 	ImportPdfPlugin* plug = qobject_cast<ImportPdfPlugin*>(plugin);
44 	Q_ASSERT(plug);
45 	delete plug;
46 }
47 
ImportPdfPlugin()48 ImportPdfPlugin::ImportPdfPlugin() :
49 	importAction(new ScrAction(ScrAction::DLL, QPixmap(), QPixmap(), "", QKeySequence(), this))
50 {
51 	// Set action info in languageChange, so we only have to do it in one
52 	// place. This includes registering file format support.
53 	registerFormats();
54 	languageChange();
55 }
56 
languageChange()57 void ImportPdfPlugin::languageChange()
58 {
59 	importAction->setText( tr("Import PDF..."));
60 	FileFormat* fmt = getFormatByExt("pdf");
61 	fmt->trName = FormatsManager::instance()->nameOfFormat(FormatsManager::PDF); // Human readable name
62 	fmt->filter = FormatsManager::instance()->extensionsForFormat(FormatsManager::PDF); // QFileDialog filter
63 	if (ScCore->haveGS())
64 	{
65 		FileFormat* fmt2 = getFormatByExt("eps");
66 		fmt2->trName = FormatsManager::instance()->nameOfFormat(FormatsManager::EPS);
67 		fmt2->filter = FormatsManager::instance()->extensionsForFormat(FormatsManager::EPS);
68 		FileFormat* fmt3 = getFormatByExt("ps");
69 		fmt3->trName = FormatsManager::instance()->nameOfFormat(FormatsManager::PS);
70 		fmt3->filter = FormatsManager::instance()->extensionsForFormat(FormatsManager::PS);
71 	}
72 }
73 
~ImportPdfPlugin()74 ImportPdfPlugin::~ImportPdfPlugin()
75 {
76 	unregisterAll();
77 }
78 
fullTrName() const79 QString ImportPdfPlugin::fullTrName() const
80 {
81 	return QObject::tr("PDF Importer");
82 }
83 
84 
getAboutData() const85 const ScActionPlugin::AboutData* ImportPdfPlugin::getAboutData() const
86 {
87 	AboutData* about = new AboutData;
88 	about->authors = "Franz Schmid <franz@scribus.info>";
89 	about->shortDescription = tr("Imports PDF Files");
90 	about->description = tr("Imports most PDF files into the current document, converting their vector data into Scribus objects.");
91 	about->license = "GPL";
92 	Q_CHECK_PTR(about);
93 	return about;
94 }
95 
deleteAboutData(const AboutData * about) const96 void ImportPdfPlugin::deleteAboutData(const AboutData* about) const
97 {
98 	Q_ASSERT(about);
99 	delete about;
100 }
101 
registerFormats()102 void ImportPdfPlugin::registerFormats()
103 {
104 	FileFormat fmt(this);
105 	fmt.trName = FormatsManager::instance()->nameOfFormat(FormatsManager::PDF); // Human readable name
106 	fmt.formatId = 0;
107 	fmt.filter = FormatsManager::instance()->extensionsForFormat(FormatsManager::PDF); // QFileDialog filter
108 	fmt.fileExtensions = QStringList() << "pdf";
109 	fmt.load = true;
110 	fmt.save = false;
111 	fmt.thumb = true;
112 	fmt.mimeTypes = FormatsManager::instance()->mimetypeOfFormat(FormatsManager::PDF); // MIME types
113 	fmt.priority = 64; // Priority
114 	registerFormat(fmt);
115 
116 	if (ScCore->haveGS())
117 	{
118 		FileFormat fmt2(this);
119 		fmt2.trName = FormatsManager::instance()->nameOfFormat(FormatsManager::EPS); // Human readable name
120 		fmt2.formatId = 0;
121 		fmt2.filter = FormatsManager::instance()->extensionsForFormat(FormatsManager::EPS);// QFileDialog filter
122 		fmt2.fileExtensions = QStringList() << "eps" << "epsf" << "epsi" << "eps2" << "eps3" << "epi" << "ept";
123 		fmt2.load = true;
124 		fmt2.save = false;
125 		fmt2.mimeTypes = FormatsManager::instance()->mimetypeOfFormat(FormatsManager::EPS); // MIME types
126 		fmt2.priority = 64; // Priority
127 		registerFormat(fmt2);
128 
129 		FileFormat fmt3(this);
130 		fmt3.trName = FormatsManager::instance()->nameOfFormat(FormatsManager::PS); // Human readable name
131 		fmt3.formatId = 0;
132 		fmt3.filter = FormatsManager::instance()->extensionsForFormat(FormatsManager::PS);// QFileDialog filter
133 		fmt3.fileExtensions = QStringList() << "ps";
134 		fmt3.load = true;
135 		fmt3.save = false;
136 		fmt3.mimeTypes = FormatsManager::instance()->mimetypeOfFormat(FormatsManager::PS); // MIME types
137 		fmt3.priority = 64; // Priority
138 		registerFormat(fmt3);
139 	}
140 }
141 
fileSupported(QIODevice *,const QString & fileName) const142 bool ImportPdfPlugin::fileSupported(QIODevice* /* file */, const QString & fileName) const
143 {
144 	return true;
145 }
146 
loadFile(const QString & fileName,const FileFormat &,int flags,int)147 bool ImportPdfPlugin::loadFile(const QString & fileName, const FileFormat &, int flags, int /*index*/)
148 {
149 	// There's only one format to handle, so we just call import(...)
150 	return import(fileName, flags);
151 }
152 
import(QString fileName,int flags)153 bool ImportPdfPlugin::import(QString fileName, int flags)
154 {
155 	if (!checkFlags(flags))
156 		return false;
157 	if (fileName.isEmpty())
158 	{
159 		flags |= lfInteractive;
160 		PrefsContext* prefs = PrefsManager::instance().prefsFile->getPluginContext("importpdf");
161 		QString wdir = prefs->get("wdir", ".");
162 		CustomFDialog diaf(ScCore->primaryMainWindow(), wdir, QObject::tr("Open"), tr("All Supported Formats")+" (*.pdf *.PDF);;All Files (*)");
163 		if (diaf.exec() != QDialog::Accepted)
164 			return false;
165 		fileName = diaf.selectedFile();
166 		prefs->set("wdir", fileName.left(fileName.lastIndexOf("/")));
167 	}
168 	m_Doc = ScCore->primaryMainWindow()->doc;
169 	bool emptyDoc = (m_Doc == nullptr);
170 	bool hasCurrentPage = (m_Doc && m_Doc->currentPage());
171 
172 	QFileInfo fi(fileName);
173 	QStringList exts = QStringList() << "eps" << "epsf" << "epsi" << "eps2" << "eps3" << "epi" << "ept" << "ps" << "ai";
174 	QString lowerExt = fi.suffix().toLower();
175 
176 	QString undoActionName = Um::ImportPDF;
177 	if (lowerExt == QLatin1String("ai"))
178 		undoActionName = Um::ImportAI;
179 	else if (exts.contains(fi.suffix().toLower()))
180 		undoActionName = Um::ImportEPS;
181 
182 	TransactionSettings trSettings;
183 	trSettings.targetName   = hasCurrentPage ? m_Doc->currentPage()->getUName() : "";
184 	trSettings.targetPixmap = Um::IImageFrame;
185 	trSettings.actionName   = undoActionName;
186 	trSettings.description  = fileName;
187 	trSettings.actionPixmap = Um::IXFIG;
188 
189 	UndoTransaction activeTransaction;
190 	if (emptyDoc || !(flags & lfInteractive) || !(flags & lfScripted))
191 		UndoManager::instance()->setUndoEnabled(false);
192 	if (UndoManager::undoEnabled())
193 		activeTransaction = UndoManager::instance()->beginTransaction(trSettings);
194 
195 	bool isCleanedFile = false;
196 	QString cleanFile = "";
197 	if (exts.contains(fi.suffix().toLower()))
198 	{
199 		if (!ScCore->haveGS())
200 		{
201 			qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
202 			ScMessageBox::warning(ScCore->primaryMainWindow(), CommonStrings::trWarning, tr("The Import plugin cannot handle Postscript files"));
203 			qApp->changeOverrideCursor(QCursor(Qt::WaitCursor));
204 			return false;
205 		}
206 
207 		// Destill the eps/ps with ghostscript to get a clean pdf file
208 		bool cancel = false;
209 		QString errFile = getShortPathName(ScPaths::tempFileDir())+ "/ps.err";
210 		cleanFile = getShortPathName(ScPaths::tempFileDir()) + "/" + fi.baseName() + ".pdf";
211 		QStringList args;
212 		args.append( "-q" );
213 		args.append( "-dNOPAUSE" );
214 		args.append( "-sDEVICE=pdfwrite" );
215 		args.append( "-dBATCH" );
216 		args.append( "-dSAFER" );
217 		if (extensionIndicatesEPS(fi.suffix().toLower()))
218 			args.append("-dEPSCrop");
219 		args.append("-dCompatibilityLevel=1.4");
220 		args.append( QString("-sOutputFile=%1").arg(QDir::toNativeSeparators(cleanFile)) );
221 		args.append( QDir::toNativeSeparators(fileName) );
222 		System(getShortPathName(PrefsManager::instance().ghostscriptExecutable()), args, errFile, errFile, &cancel);
223 		args.clear();
224 		isCleanedFile = true;
225 	}
226 	bool ret = false;
227 	PdfPlug *dia = new PdfPlug(m_Doc, flags);
228 	Q_CHECK_PTR(dia);
229 	if (isCleanedFile)
230 		ret = dia->import(cleanFile, trSettings, flags, !(flags & lfScripted));
231 	else
232 		ret = dia->import(fileName, trSettings, flags, !(flags & lfScripted));
233 	if (activeTransaction)
234 		activeTransaction.commit();
235 	if (emptyDoc || !(flags & lfInteractive) || !(flags & lfScripted))
236 		UndoManager::instance()->setUndoEnabled(true);
237 	delete dia;
238 	if (isCleanedFile)
239 		QFile::remove(cleanFile);
240 	return ret;
241 }
242 
readThumbnail(const QString & fileName)243 QImage ImportPdfPlugin::readThumbnail(const QString& fileName)
244 {
245 	if (fileName.isEmpty())
246 		return QImage();
247 	UndoManager::instance()->setUndoEnabled(false);
248 	m_Doc = nullptr;
249 	PdfPlug *dia = new PdfPlug(m_Doc, lfCreateThumbnail);
250 	Q_CHECK_PTR(dia);
251 	QImage ret = dia->readThumbnail(fileName);
252 	UndoManager::instance()->setUndoEnabled(true);
253 	delete dia;
254 	return ret;
255 }
256