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 "export.h"
8 #include "dialog.h"
9
10 #include <QCursor>
11 #include <QDir>
12 #include <QMessageBox>
13 #include <QPixmap>
14 #include <QString>
15 #include <QSharedPointer>
16
17 #include "scribus.h"
18 #include "scribusdoc.h"
19 #include "scribusview.h"
20 #include "scraction.h"
21 #include "ui/scmwmenumanager.h"
22 #include "util.h"
23 #include "commonstrings.h"
24 #include "scpaths.h"
25
scribusexportpixmap_getPluginAPIVersion()26 int scribusexportpixmap_getPluginAPIVersion()
27 {
28 return PLUGIN_API_VERSION;
29 }
30
scribusexportpixmap_getPlugin()31 ScPlugin* scribusexportpixmap_getPlugin()
32 {
33 PixmapExportPlugin* plug = new PixmapExportPlugin();
34 Q_CHECK_PTR(plug);
35 return plug;
36 }
37
scribusexportpixmap_freePlugin(ScPlugin * plugin)38 void scribusexportpixmap_freePlugin(ScPlugin* plugin)
39 {
40 PixmapExportPlugin* plug = qobject_cast<PixmapExportPlugin*>(plugin);
41 Q_ASSERT(plug);
42 delete plug;
43 }
44
PixmapExportPlugin()45 PixmapExportPlugin::PixmapExportPlugin()
46 {
47 // Set action info in languageChange, so we only have to do
48 // it in one place. This includes registering file formats.
49 languageChange();
50 }
51
~PixmapExportPlugin()52 PixmapExportPlugin::~PixmapExportPlugin()
53 {
54 };
55
languageChange()56 void PixmapExportPlugin::languageChange()
57 {
58 // Note that we leave the unused members unset. They'll be initialised
59 // with their default ctors during construction.
60 // Action name
61 m_actionInfo.name = "ExportAsImage";
62 // Action text for menu, including accel
63 m_actionInfo.text = tr("Save as &Image...");
64 // Keyboard shortcut
65 m_actionInfo.keySequence = "CTRL+SHIFT+E";
66 // Menu
67 m_actionInfo.menu = "FileExport";
68 m_actionInfo.enabledOnStartup = false;
69 m_actionInfo.needsNumObjects = -1;
70 }
71
fullTrName() const72 QString PixmapExportPlugin::fullTrName() const
73 {
74 return tr("Export As Image");
75 }
76
getAboutData() const77 const ScActionPlugin::AboutData* PixmapExportPlugin::getAboutData() const
78 {
79 AboutData* about = new AboutData;
80 Q_CHECK_PTR(about);
81 about->authors = QString::fromUtf8("Petr Van\xc4\x9bk <petr@scribus.info>");
82 about->shortDescription = tr("Export As Image");
83 about->description = tr("Exports selected pages as bitmap images.");
84 // about->version
85 // about->releaseDate
86 // about->copyright
87 about->license = "GPL";
88 return about;
89 }
90
deleteAboutData(const AboutData * about) const91 void PixmapExportPlugin::deleteAboutData(const AboutData* about) const
92 {
93 Q_ASSERT(about);
94 delete about;
95 }
96
run(ScribusDoc * doc,const QString & target)97 bool PixmapExportPlugin::run(ScribusDoc* doc, const QString& target)
98 {
99 Q_ASSERT(target.isEmpty());
100 Q_ASSERT(!doc->masterPageMode());
101 QSharedPointer<ExportBitmap> ex( new ExportBitmap() );
102 QSharedPointer<ExportForm> dia( new ExportForm(nullptr, doc, ex->pageDPI, ex->quality, ex->bitmapType) );
103
104 // interval widgets handling
105 QString tmp;
106 dia->rangeVal->setText(tmp.setNum(doc->currentPageNumber()+1));
107 QFileInfo docFileInfo(doc->documentFileName());
108 dia->prefixLineEdit->setText(docFileInfo.baseName());
109 // main "loop"
110 if (dia->exec() != QDialog::Accepted)
111 return true;
112
113 std::vector<int> pageNs;
114 ex->pageDPI = dia->DPIBox->value();
115 ex->enlargement = dia->enlargementBox->value();
116 ex->quality = dia->qualityBox->value();
117 ex->exportDir = QDir::fromNativeSeparators(dia->outputDirectory->text());
118 ex->bitmapType = dia->bitmapType->currentText();
119 ex->filenamePrefix = dia->prefixLineEdit->text();
120
121 // check availability of the destination
122 QFileInfo fi(ex->exportDir);
123 if (!fi.isDir())
124 {
125 ScMessageBox::warning(doc->scMW(), tr("Save as Image"),
126 tr("The target location %1 must be an existing directory").arg(ex->exportDir));
127 return false;
128 }
129 if (!fi.isWritable())
130 {
131 ScMessageBox::warning(doc->scMW(), tr("Save as Image"),
132 tr("The target location %1 must be writable").arg(ex->exportDir));
133 return false;
134 }
135
136 QApplication::changeOverrideCursor(QCursor(Qt::WaitCursor));
137 doc->scMW()->mainWindowProgressBar->reset();
138 bool res;
139 if (dia->onePageRadio->isChecked())
140 res = ex->exportCurrent(doc, !dia->noBackground->isChecked());
141 else
142 {
143 if (dia->allPagesRadio->isChecked())
144 parsePagesString("*", &pageNs, doc->DocPages.count());
145 else
146 parsePagesString(dia->rangeVal->text(), &pageNs, doc->DocPages.count());
147 res = ex->exportInterval(doc, pageNs, !dia->noBackground->isChecked());
148 }
149 doc->scMW()->mainWindowProgressBar->reset();
150 QApplication::changeOverrideCursor(Qt::ArrowCursor);
151 // QApplication::restoreOverrideCursor();
152 if (res)
153 doc->scMW()->setStatusBarInfoText( tr("Export successful"));
154
155 return true;
156 }
157
158
ExportBitmap()159 ExportBitmap::ExportBitmap()
160 {
161 pageDPI = 72;
162 quality = -1;
163 enlargement = 100.0;
164 exportDir = QDir::currentPath();
165 bitmapType = QString("png");
166 overwrite = false;
167 }
168
getFileName(ScribusDoc * doc,uint pageNr)169 QString ExportBitmap::getFileName(ScribusDoc* doc, uint pageNr)
170 {
171 return QDir::cleanPath(QDir::toNativeSeparators(exportDir + "/" + getFileNameByPage(doc, pageNr, bitmapType.toLower(), filenamePrefix)));
172 }
173
~ExportBitmap()174 ExportBitmap::~ExportBitmap()
175 {
176 }
177
exportPage(ScribusDoc * doc,uint pageNr,bool background,bool single=true)178 bool ExportBitmap::exportPage(ScribusDoc* doc, uint pageNr, bool background, bool single = true)
179 {
180 uint over = 0;
181 bool saved = false, doFileSave = true;
182 QString fileName(getFileName(doc, pageNr));
183
184 if (!doc->Pages->at(pageNr))
185 return false;
186 ScPage* page = doc->Pages->at(pageNr);
187
188 /* a little magic here - I need to compute the "maxGr" value...
189 * We need to know the right size of the page for landscape,
190 * portrait and user defined sizes.
191 */
192 double pixmapSize = (page->height() > page->width()) ? page->height() : page->width();
193 PageToPixmapFlags flags;
194 if (background)
195 flags |= Pixmap_DrawBackground;
196 QImage im(doc->view()->PageToPixmap(pageNr, qRound(pixmapSize * enlargement * (pageDPI / 72.0) / 100.0), flags));
197 if (im.isNull())
198 {
199 ScMessageBox::warning(doc->scMW(), tr("Save as Image"), tr("Insufficient memory for this image size."));
200 doc->scMW()->setStatusBarInfoText( tr("Insufficient memory for this image size."));
201 return false;
202 }
203 int dpm = qRound(100.0 / 2.54 * pageDPI);
204 im.setDotsPerMeterY(dpm);
205 im.setDotsPerMeterX(dpm);
206 if (QFile::exists(fileName) && !overwrite)
207 {
208 doFileSave = false;
209 QString fn = QDir::toNativeSeparators(fileName);
210 // QApplication::restoreOverrideCursor();
211 QApplication::changeOverrideCursor(Qt::ArrowCursor);
212 over = ScMessageBox::question(doc->scMW(), tr("File exists. Overwrite?"),
213 fn +"\n"+ tr("exists already. Overwrite?"),
214 // hack for multiple overwriting (petr)
215 (single) ? QMessageBox::Yes | QMessageBox::No : QMessageBox::Yes | QMessageBox::No | QMessageBox::YesToAll,
216 QMessageBox::NoButton, // GUI default
217 QMessageBox::YesToAll); // batch default
218 QApplication::changeOverrideCursor(QCursor(Qt::WaitCursor));
219 if (over == QMessageBox::Yes || over == QMessageBox::YesToAll)
220 doFileSave = true;
221 if (over == QMessageBox::YesToAll)
222 overwrite = true;
223 }
224 if (doFileSave)
225 saved = im.save(fileName, bitmapType.toLocal8Bit().constData(), quality);
226 if (!saved && doFileSave)
227 {
228 ScMessageBox::warning(doc->scMW(), tr("Save as Image"), tr("Error writing the output file(s)."));
229 doc->scMW()->setStatusBarInfoText( tr("Error writing the output file(s)."));
230 }
231 return saved;
232 }
233
exportCurrent(ScribusDoc * doc,bool background)234 bool ExportBitmap::exportCurrent(ScribusDoc* doc, bool background)
235 {
236 return exportPage(doc, doc->currentPageNumber(), background, true);
237 }
238
exportInterval(ScribusDoc * doc,std::vector<int> & pageNs,bool background)239 bool ExportBitmap::exportInterval(ScribusDoc* doc, std::vector<int> &pageNs, bool background)
240 {
241 doc->scMW()->mainWindowProgressBar->setMaximum(pageNs.size());
242 for (uint a = 0; a < pageNs.size(); ++a)
243 {
244 doc->scMW()->mainWindowProgressBar->setValue(a);
245 if (!exportPage(doc, pageNs[a]-1, background, false))
246 return false;
247 }
248 return true;
249 }
250