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  *   Riku Leino, tsoots@gmail.com                                          *
9  ***************************************************************************/
10 #include "satemplate.h"
11 #include "satdialog.h"
12 
13 #include "api/api_application.h"
14 #include "scpaths.h"
15 #include "ui/scmessagebox.h"
16 #include "scribuscore.h"
17 #include "scribusdoc.h"
18 #include "scribusview.h"
19 #include "prefsfile.h"
20 #include "prefsmanager.h"
21 
saveastemplateplugin_getPluginAPIVersion()22 int saveastemplateplugin_getPluginAPIVersion()
23 {
24 	return PLUGIN_API_VERSION;
25 }
26 
saveastemplateplugin_getPlugin()27 ScPlugin* saveastemplateplugin_getPlugin()
28 {
29 	SaveAsTemplatePlugin* plug = new SaveAsTemplatePlugin();
30 	Q_CHECK_PTR(plug);
31 	return plug;
32 }
33 
saveastemplateplugin_freePlugin(ScPlugin * plugin)34 void saveastemplateplugin_freePlugin(ScPlugin* plugin)
35 {
36 	SaveAsTemplatePlugin* plug = qobject_cast<SaveAsTemplatePlugin*>(plugin);
37 	Q_ASSERT(plug);
38 	delete plug;
39 }
40 
SaveAsTemplatePlugin()41 SaveAsTemplatePlugin::SaveAsTemplatePlugin()
42 {
43 	// Set action info in languageChange, so we only have to do
44 	// it in one place.
45 	languageChange();
46 }
47 
~SaveAsTemplatePlugin()48 SaveAsTemplatePlugin::~SaveAsTemplatePlugin() {};
49 
languageChange()50 void SaveAsTemplatePlugin::languageChange()
51 {
52 	// Note that we leave the unused members unset. They'll be initialised
53 	// with their default ctors during construction.
54 	// Action name
55 	m_actionInfo.name = "SaveAsDocumentTemplate";
56 	// Action text for menu, including accel
57 	m_actionInfo.text = tr("Save as &Template...");
58 	// Shortcut
59 	m_actionInfo.keySequence = "Ctrl+Alt+S";
60 	// Menu
61 	m_actionInfo.menu = "File";
62 	m_actionInfo.menuAfterName = "fileSaveAs";
63 	m_actionInfo.enabledOnStartup = true;
64 	m_actionInfo.needsNumObjects = -1;
65 }
66 
fullTrName() const67 QString SaveAsTemplatePlugin::fullTrName() const
68 {
69 	return QObject::tr("Save As Template");
70 }
71 
getAboutData() const72 const ScActionPlugin::AboutData* SaveAsTemplatePlugin::getAboutData() const
73 {
74 	AboutData* about = new AboutData;
75 	Q_CHECK_PTR(about);
76 	about->authors = QString::fromUtf8("Riku Leino <riku@scribus.info>");
77 	about->shortDescription = tr("Save a document as a template");
78 	about->description = tr("Save a document as a template. Good way to ease the "
79 	                        "initial work for documents with a constant look");
80     // about->version
81     // about->releaseDate
82     // about->copyright
83 	about->license = "GPL";
84 	return about;
85 }
86 
deleteAboutData(const AboutData * about) const87 void SaveAsTemplatePlugin::deleteAboutData(const AboutData* about) const
88 {
89 	Q_ASSERT(about);
90 	delete about;
91 }
92 
run(ScribusDoc * doc,const QString & target)93 bool SaveAsTemplatePlugin::run(ScribusDoc* doc, const QString& target)
94 /*{
95 	Q_ASSERT(target.isEmpty());
96 	Sat = new MenuSAT();
97 	Sat->RunSATPlug();
98 	delete Sat;
99 	Sat = 0;
100 	return true;
101 }
102 */
103 /* jghali's fix when the new file dialog is cancelled SaT is still active in the menu - PL */
104 {
105 	m_Doc=doc;
106  	if ( m_Doc )
107 	{
108 		Q_ASSERT(target.isEmpty());
109 		MenuSAT* Sat = new MenuSAT();
110 		Sat->RunSATPlug(m_Doc);
111 		delete Sat;
112 		Sat = nullptr;
113 	}
114 	return true;
115 }
RunSATPlug(ScribusDoc * doc)116 void MenuSAT::RunSATPlug(ScribusDoc* doc)
117 {
118 	QDir templates(ScPaths::applicationDataDir());
119 	if (!templates.exists("templates"))
120 	{
121 		templates.mkdir("templates");
122 	}
123 	QString currentPath(QDir::currentPath());
124 	QString currentFile(doc->documentFileName());
125 	bool hasName = doc->hasName;
126 	bool isModified = doc->isModified();
127 	QString userTemplatesDir = ScPaths::instance().userTemplateDir(true);
128 	PrefsContext* dirs = PrefsManager::instance().prefsFile->getContext("dirs");
129 	QString oldCollect = dirs->get("collect", ".");
130 	if (userTemplatesDir.isEmpty())
131 	{
132 		ScMessageBox::warning(doc->scMW(), QObject::tr("No User Template Location Defined"), "<qt>" +
133 										QObject::tr("You have not configured where to save document templates.<br>Please go to the Paths section in the Scribus application Preferences to set a location.") + "</qt>",
134 										QMessageBox::Ok,	// GUI default
135 										QMessageBox::Ok);	// batch default
136 		return;
137 	}
138 
139 	if (userTemplatesDir.right(1) == "/")
140 		userTemplatesDir.chop(1);
141 
142 	dirs->set("collect", userTemplatesDir);
143 	if (doc->scMW()->fileCollect().isEmpty())
144 		return;
145 	if (oldCollect != ".")
146 		dirs->set("collect", oldCollect);
147 	QString docPath = doc->documentFileName();
148 	QString docDir = docPath.left(docPath.lastIndexOf('/'));
149 	QString docName = docPath.right(docPath.length() - docPath.lastIndexOf('/') - 1);
150 	docName = docName.left(docName.lastIndexOf(".s"));
151 
152 	if (currentFile == doc->documentFileName())
153 		return;
154 	SATDialog* satdia = new SATDialog(doc->scMW(),docName,
155 									  static_cast<int>(doc->pageWidth() + 0.5),
156 									  static_cast<int>(doc->pageHeight() + 0.5));
157 	if (satdia->exec())
158 	{
159 		sat* s = new sat(doc, satdia, docPath.right(docPath.length() - docPath.lastIndexOf('/') - 1),docDir);
160 		s->createImages();
161 		s->createTmplXml();
162 		delete s;
163 	}
164 	// Restore the state that was before ScMW->Collect()
165 	doc->setDocumentFileName(currentFile);
166 	doc->hasName = hasName;
167 	doc->setModified(isModified);
168 	QString newCaption=currentFile;
169 	if (isModified)
170 		newCaption.append('*');
171 	doc->scMW()->updateActiveWindowCaption(newCaption);
172 	doc->scMW()->removeRecent(docPath);
173 	QDir::setCurrent(currentPath);
174 	delete satdia;
175 }
176 
177 // --------------------- CLASS sat ------------------------------------------------//
178 
sat(ScribusDoc * doc,SATDialog * satdia,const QString & fileName,const QString & tmplDir)179 sat::sat(ScribusDoc* doc, SATDialog* satdia, const QString& fileName, const QString& tmplDir)
180 {
181 	lang = ScCore->getGuiLanguage();
182 	m_Doc = doc;
183 	dia = satdia;
184 	dir = tmplDir;
185 	if (dir.right(1) == "/")
186 		dir = tmplDir.left(tmplDir.length() - 1);
187 	file = fileName;
188 	tmplXmlFile = findTemplateXml(dir);
189 }
190 
createTmplXml()191 void sat::createTmplXml()
192 {
193 	QFile tmplXml(tmplXmlFile);
194 	if (tmplXml.exists())
195 	{
196 		appendTmplXml();
197 		return; // We don't want to overwrite the template.xml file
198 	}
199 	QString xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
200 	xml += "<templates>\n";
201 	xml += getTemplateTag();
202 	xml += "</templates>\n";
203 	if ( tmplXml.open( QIODevice::WriteOnly ) )
204 	{
205 		QTextStream stream(&tmplXml);
206 		stream.setCodec("UTF-8");
207 		stream << xml;
208 		tmplXml.close();
209 	}
210 }
211 
createImages()212 void sat::createImages()
213 {
214 	QString tnsmallName = dia->nameEdit->text() + "tn.png";
215 	QString tnlargeName = dia->nameEdit->text() + ".png";
216 	double pageh = m_Doc->pageHeight();
217 	double pagew = m_Doc->pageWidth();
218 	int pageSizeSmall = 0;
219 	int pageSizeLarge = 0;
220 	if (pageh > pagew)
221 	{
222 		pageSizeSmall = static_cast<int>(pageh / 10);
223 		pageSizeLarge = static_cast<int>(pageh / 3);
224 	}
225 	else
226 	{
227 		pageSizeSmall = static_cast<int>(pagew / 10);
228 		pageSizeLarge = static_cast<int>(pagew / 3);
229 	}
230 	QImage tnsmall = m_Doc->view()->PageToPixmap(0,pageSizeSmall);
231 	QImage tnlarge = m_Doc->view()->PageToPixmap(0,pageSizeLarge);
232 	tnsmall.save(dir+"/"+tnsmallName,"PNG",70);
233 	tnlarge.save(dir+"/"+tnlargeName, "PNG", 70);
234 }
235 
appendTmplXml()236 void sat::appendTmplXml()
237 {
238 	QFile tmplXml(tmplXmlFile);
239 	if (tmplXml.open(QIODevice::ReadOnly))
240 	{
241 		QTextStream stream(&tmplXml);
242 		QString tmp = stream.readLine();
243 		QString file = "";
244 		while (!tmp.isNull())
245 		{
246 			file += tmp + "\n";
247 			tmp = stream.readLine();
248 			if (tmp.indexOf("</templates>") != -1)
249 				file += getTemplateTag();
250 		}
251 		tmplXml.close();
252 		if ( tmplXml.open( QIODevice::WriteOnly ) )
253 		{
254 			QTextStream stream2(&tmplXml);
255 			stream2.setCodec("UTF-8");
256 			stream2 << file;
257 			tmplXml.close();
258 		}
259 	}
260 }
261 
getTemplateTag()262 QString sat::getTemplateTag()
263 {
264 	QString category = dia->catsCombo->currentText();
265 	if (category.isEmpty())
266 		category = QObject::tr("Own Templates");
267 	else
268 		category = dia->cats.key(category, category);
269 	QDate now = QDate::currentDate();
270 	QString cat = QString(category);
271 	replaceIllegalChars(cat);
272 	QString tag = "\t<template category=\""+cat+"\">\n";
273 	QString name = QString(dia->nameEdit->text());
274 	replaceIllegalChars(name);
275 	tag += "\t\t<name>"+name+"</name>\n";
276 	tag += "\t\t<file>"+file+"</file>\n";
277 	tag += "\t\t<tnail>"+name+"tn.png"+"</tnail>\n";
278 	tag += "\t\t<img>"+name+".png"+"</img>\n";
279 	QString psize = QString(dia->psizeEdit->text());
280 	replaceIllegalChars(psize);
281 	tag += "\t\t<psize>"+psize+"</psize>\n";
282 	QString colors = QString(dia->colorsEdit->text());
283 	replaceIllegalChars(colors);
284 	tag += "\t\t<color>"+colors+"</color>\n";
285 	QString descr = QString(dia->descrEdit->toPlainText());
286 	replaceIllegalChars(descr);
287 	tag += "\t\t<descr>"+descr+"</descr>\n";
288 	QString usage = QString(dia->usageEdit->toPlainText());
289 	replaceIllegalChars(usage);
290 	tag += "\t\t<usage>"+usage+"</usage>\n";
291 	QString scribus_version(ScribusAPI::getVersion());
292 	replaceIllegalChars(scribus_version);
293 	tag += "\t\t<scribus_version>" + scribus_version + "</scribus_version>\n";
294 	QString date = QString(now.toString(Qt::ISODate));
295 	replaceIllegalChars(date);
296 	tag += "\t\t<date>" + date + "</date>\n";
297 	QString author = QString(dia->authorEdit->text());
298 	replaceIllegalChars(author);
299 	tag += "\t\t<author>"+author+"</author>\n";
300 	QString email = QString(dia->emailEdit->text());
301 	replaceIllegalChars(email);
302 	tag += "\t\t<email>"+email+"</email>\n";
303 	tag += "\t</template>\n";
304 
305 	return tag;
306 }
307 
replaceIllegalChars(QString & s)308 void sat::replaceIllegalChars(QString& s)
309 {
310 	s.replace("&amp;", "&");
311 	s.replace("&lt;", "<");
312 	s.replace("&gt;", ">");
313 	s.replace("&quot;", "\"");
314 	s.replace("&apos;", "\'");
315 	s.replace("&", "&amp;");
316 	s.replace("<", "&lt;");
317 	s.replace(">", "&gt;");
318 	s.replace("\"", "&quot;");
319 	s.replace("\'", "&apos;");
320 }
321 
findTemplateXml(const QString & dir)322 QString sat::findTemplateXml(const QString& dir)
323 {
324 	QString tmp = dir + "/template." + lang + ".xml";
325 	if (QFile(tmp).exists())
326 		return tmp;
327 
328 	if (lang.length() > 2)
329 	{
330 		tmp = dir + "/template." + lang.left(2) + ".xml";
331 		if (QFile(tmp).exists())
332 			return tmp;
333 	}
334 	return dir + "/template.xml";
335 }
336 
~sat()337 sat::~sat()
338 {
339 }
340