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 	begin                : Feb 2015
9 	copyright            : (C) 2015 by Craig Bradney
10 	email                : cbradney@scribus.info
11 ***************************************************************************/
12 
13 /***************************************************************************
14 *                                                                         *
15 *   mainWindow program is free software; you can redistribute it and/or modify  *
16 *   it under the terms of the GNU General Public License as published by  *
17 *   the Free Software Foundation; either version 2 of the License, or     *
18 *   (at your option) any later version.                                   *
19 *                                                                         *
20 ***************************************************************************/
21 
22 #include <QByteArray>
23 #include <QComboBox>
24 #include <QCryptographicHash>
25 #include <QDebug>
26 #include <QDesktopServices>
27 #include <QDomDocument>
28 #include <QFile>
29 #include <QFileInfo>
30 #include <QLabel>
31 #include <QList>
32 #include <QMessageBox>
33 #include <QString>
34 #include <QStringList>
35 #include <QTableWidget>
36 #include <QTextCodec>
37 #include <QTextStream>
38 
39 #include "downloadmanager/scdlmgr.h"
40 #include "langmgr.h"
41 #include "resourcemanager.h"
42 #include "resourcemanagerlicense.h"
43 #include "scpaths.h"
44 #include "scribusapp.h"
45 #include "third_party/zip/scribus_zip.h"
46 #include "util.h"
47 #include "util_file.h"
48 
ResourceManager(QWidget * parent)49 ResourceManager::ResourceManager(QWidget* parent)
50 {
51 	setupUi(this);
52 	downloadButton->setEnabled(false);
53 	downloadProgressBar->setValue(0);
54 	downloadProgressBar->setVisible(false);
55 	dataReceivedLabel->setVisible(false);
56 	showInFSButton->setEnabled(false);
57 	languageChange();
58 
59 	connect(categoryComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(categoryChanged()));
60 	connect(installedTableWidget, SIGNAL(itemSelectionChanged()), this, SLOT(installedSelectionChanged()));
61 	connect(updateAvailableButton, SIGNAL(clicked()), this, SLOT(updateDownloadLists()));
62 	connect(showInFSButton, SIGNAL(clicked()), this, SLOT(showInFileBrowser()));
63 	connect(showLicenseButton, SIGNAL(clicked()), this, SLOT(showLicense()));
64 	connect(downloadButton, SIGNAL(clicked()), this, SLOT(startDownload()));
65 }
66 
languageChange()67 void ResourceManager::languageChange()
68 {
69 #if defined(Q_OS_MAC)
70 	showInFSButton->setText( tr( "Show In Finder" ) );
71 #endif
72 #if defined(Q_OS_WIN32)
73 	showInFSButton->setText( tr( "Show In Explorer" ) );
74 #endif
75 
76 	m_resourceCategories.clear();
77 	m_resourceCategories.insert(RM_FONTS, tr("Fonts"));
78 	m_resourceCategories.insert(RM_HYPH, tr("Hyphenation Dictionaries"));
79 	m_resourceCategories.insert(RM_SPELL, tr("Spelling Dictionaries"));
80 	m_resourceCategories.insert(RM_HELP, tr("Help Manuals"));
81 	m_resourceCategories.insert(RM_PALETTES, tr("Palettes"));
82 	//m_resourceCategories.insert(RM_TEMPLATES, tr("Templates"));
83 	//m_resourceCategories.insert(RM_PROFILES, tr("Color Profiles"));
84 //	m_resourceCategories.insert(RM_TEST, tr("Test"));
85 
86 	m_dataFiles.clear();
87 	m_dataFiles.insert(RM_FONTS, "scribus_fonts.xml");
88 	m_dataFiles.insert(RM_HYPH, "scribus_hyph_dicts.xml");
89 	m_dataFiles.insert(RM_SPELL, "scribus_spell_dicts.xml");
90 	m_dataFiles.insert(RM_HELP, "scribus_help.xml");
91 	m_dataFiles.insert(RM_PALETTES, "scribus_palettes.xml");
92 	//m_dataFiles.insert(RM_TEMPLATES, "scribus_templates.xml");
93 	//m_dataFiles.insert(RM_PROFILES, "scribus_profiles.xml");
94 //	m_dataFiles.insert(RM_TEST, "test.txt");
95 
96 
97 	installedTableWidget->clear();
98 	availableTableWidget->clear();
99 	categoryComboBox->clear();
100 	categoryComboBox->setInsertPolicy(QComboBox::InsertAlphabetically);
101 
102 	QMapIterator<int, QString> i(m_resourceCategories);
103 	while (i.hasNext())
104 	{
105 		i.next();
106 		categoryComboBox->addItem(i.value(), i.key());
107 	}
108 	categoryChanged();
109 }
110 
readAvailableFonts()111 void ResourceManager::readAvailableFonts()
112 {
113 	QFile dataFile(ScPaths::downloadDir() + m_dataFiles[RM_FONTS]);
114 	if (!dataFile.exists())
115 		return;
116 	if (!dataFile.open(QIODevice::ReadOnly))
117 		return;
118 
119 	QTextStream ts(&dataFile);
120 	ts.setCodec(QTextCodec::codecForName("UTF-8"));
121 	QString errorMsg;
122 	int eline;
123 	int ecol;
124 	QDomDocument doc( m_dataFiles[RM_FONTS] );
125 	QString data(ts.readAll());
126 	dataFile.close();
127 	if ( !doc.setContent( data, &errorMsg, &eline, &ecol ))
128 	{
129 //		qDebug()<<errorMsg<<eline<<ecol;
130 		if (data.contains("404 not found", Qt::CaseInsensitive))
131 			qDebug()<<"File not found on server";
132 		else
133 			qDebug()<<"Could not open file"<<dataFile.fileName();
134 		return;
135 	}
136 	m_availableList.clear();
137 
138 	QDomElement docElem = doc.documentElement();
139 	for (QDomNode n = docElem.firstChild(); !n.isNull(); n = n.nextSibling())
140 	{
141 		QDomElement e = n.toElement();
142 		if (e.isNull())
143 			continue;
144 		if (e.tagName() != "font")
145 			continue;
146 		if (!e.hasAttribute("type") || !e.hasAttribute("filetype"))
147 			continue;
148 
149 		struct DownloadItem d;
150 		d.desc=e.attribute("description");
151 		d.download=false;
152 		d.files=e.attribute("files");
153 		d.extractfiles=e.attribute("extractfiles");
154 		d.url=e.attribute("URL");
155 		d.version=e.attribute("version");
156 		d.lang=e.attribute("language");
157 		d.license=e.attribute("license");
158 		d.filetype=e.attribute("filetype");
159 		d.movetofile=e.attribute("movetofilename");
160 		d.type=e.attribute("type").toUpper();
161 		QUrl url(d.url);
162 		if (url.isValid() && !url.isEmpty() && !url.host().isEmpty())
163 			m_availableList.append(d);
164 //		else
165 //			qDebug()<<"rm : availFonts : invalid URL"<<d.url;
166 	}
167 }
168 
readAvailableHelp()169 void ResourceManager::readAvailableHelp()
170 {
171 	QFile dataFile(ScPaths::downloadDir() + m_dataFiles[RM_HELP]);
172 	if (!dataFile.exists())
173 		return;
174 	if (!dataFile.open(QIODevice::ReadOnly))
175 		return;
176 
177 	QTextStream ts(&dataFile);
178 	ts.setCodec(QTextCodec::codecForName("UTF-8"));
179 	QString errorMsg;
180 	int eline;
181 	int ecol;
182 	QDomDocument doc( QString(m_dataFiles[RM_HELP]).remove(".xml") );
183 	QString data(ts.readAll());
184 	dataFile.close();
185 	if ( !doc.setContent( data, &errorMsg, &eline, &ecol ))
186 	{
187 		if (data.contains("404 not found", Qt::CaseInsensitive))
188 			qDebug()<<"File not found on server";
189 		else
190 			qDebug()<<"Could not open file"<<dataFile.fileName();
191 		return;
192 	}
193 	m_availableList.clear();
194 
195 	QDomElement docElem = doc.documentElement();
196 	for (QDomNode n = docElem.firstChild(); !n.isNull(); n = n.nextSibling())
197 	{
198 		QDomElement e = n.toElement();
199 		if (e.isNull())
200 			continue;
201 		if (e.tagName() != "help")
202 			continue;
203 		if (!e.hasAttribute("type") || !e.hasAttribute("filetype"))
204 			continue;
205 		if (e.attribute("type") != "scribusofficial")
206 			continue;
207 
208 		struct DownloadItem d;
209 		d.desc=e.attribute("description");
210 		d.download=false;
211 		d.files=e.attribute("files");
212 		d.extractfiles="";
213 		d.url=e.attribute("URL");
214 		d.version=e.attribute("version");
215 		d.lang=e.attribute("language");
216 		d.license=e.attribute("license");
217 		d.filetype=e.attribute("filetype");
218 		d.type=e.attribute("type");
219 		QUrl url(d.url);
220 		if (url.isValid() && !url.isEmpty() && !url.host().isEmpty())
221 			m_availableList.append(d);
222 	}
223 }
224 
readAvailablePalettes()225 void ResourceManager::readAvailablePalettes()
226 {
227 	QFile dataFile(ScPaths::downloadDir() + m_dataFiles[RM_PALETTES]);
228 	if (!dataFile.exists())
229 		return;
230 	if (!dataFile.open(QIODevice::ReadOnly))
231 		return;
232 
233 	QTextStream ts(&dataFile);
234 	ts.setCodec(QTextCodec::codecForName("UTF-8"));
235 	QString errorMsg;
236 	int eline;
237 	int ecol;
238 	QDomDocument doc( QString(m_dataFiles[RM_PALETTES]).remove(".xml") );
239 	QString data(ts.readAll());
240 	dataFile.close();
241 	if ( !doc.setContent( data, &errorMsg, &eline, &ecol ))
242 	{
243 		if (data.contains("404 not found", Qt::CaseInsensitive))
244 			qDebug()<<"File not found on server";
245 		else
246 			qDebug()<<"Could not open file"<<dataFile.fileName();
247 		return;
248 	}
249 	m_availableList.clear();
250 
251 	QDomElement docElem = doc.documentElement();
252 	for (QDomNode n = docElem.firstChild(); !n.isNull(); n = n.nextSibling())
253 	{
254 		QDomElement e = n.toElement();
255 		if (e.isNull())
256 			continue;
257 		if (e.tagName() != "palette")
258 			continue;
259 		if (!e.hasAttribute("type") || !e.hasAttribute("filetype"))
260 			continue;
261 
262 		struct DownloadItem d;
263 		d.desc=e.attribute("description");
264 		d.download=false;
265 		d.files=e.attribute("files");
266 		d.extractfiles="";
267 		d.url=e.attribute("URL");
268 		d.version=e.attribute("version");
269 		d.lang=e.attribute("language");
270 		d.license=e.attribute("license");
271 		d.filetype=e.attribute("filetype");
272 		d.type=e.attribute("type");
273 		d.source=e.attribute("source");
274 		QUrl url(d.url);
275 		if (url.isValid() && !url.isEmpty() && !url.host().isEmpty())
276 			m_availableList.append(d);
277 	}
278 }
279 
installedSelectionChanged()280 void ResourceManager::installedSelectionChanged()
281 {
282 	auto selectedItems = installedTableWidget->selectedItems();
283 	if (selectedItems.count() <= 0)
284 	{
285 		showInFSButton->setEnabled(false);
286 		return;
287 	}
288 
289 	showInFSButton->setEnabled(true);
290 }
291 
updateInstalledFonts()292 void ResourceManager::updateInstalledFonts()
293 {
294 	m_dictionaryMap.clear();
295 	QString fontDir(findDestinationFolder());
296 	for (const DownloadItem& d : qAsConst(m_availableList))
297 	{
298 		if (d.filetype!="zip")
299 		{
300 			if (QFileInfo::exists(fontDir+d.files))
301 				m_dictionaryMap.insert(d.desc, fontDir+d.files);
302 		}
303 		else
304 		{
305 			QFileInfo zfi(d.files);
306 			if (QFileInfo::exists(fontDir+zfi.baseName()))
307 				m_dictionaryMap.insert(d.desc, fontDir+zfi.baseName());
308 		}
309 	}
310 
311 	installedTableWidget->clear();
312 	installedTableWidget->setRowCount(m_dictionaryMap.count());
313 	installedTableWidget->setColumnCount(2);
314 	installedTableWidget->setSortingEnabled(false);
315 	installedTableWidget->setSelectionBehavior(QTableWidget::SelectRows);
316 
317 	QMapIterator<QString, QString> i(m_dictionaryMap);
318 	int row = 0;
319 	while (i.hasNext())
320 	{
321 		i.next();
322 		int column = 0;
323 		QTableWidgetItem *newItem1 = new QTableWidgetItem(i.key());
324 		newItem1->setFlags(newItem1->flags() & ~Qt::ItemIsEditable);
325 		installedTableWidget->setItem(row, column++, newItem1);
326 		QTableWidgetItem *newItem2 = new QTableWidgetItem(i.value());
327 		newItem2->setFlags(newItem1->flags());
328 		installedTableWidget->setItem(row, column++, newItem2);
329 		++row;
330 	}
331 
332 	QStringList headers;
333 	headers << tr("Description") << tr("Location") ;
334 	installedTableWidget->setHorizontalHeaderLabels(headers);
335 	installedTableWidget->resizeColumnsToContents();
336 	installedTableWidget->setSortingEnabled(true);
337 	installedTableWidget->sortByColumn(0, Qt::AscendingOrder);
338 }
339 
updateInstalledHyph()340 void ResourceManager::updateInstalledHyph()
341 {
342 	bool dictsFound=LanguageManager::instance()->findHyphDictionaries(m_dictionaryPaths);
343 	if (!dictsFound)
344 		return;
345 	m_dictionaryMap.clear();
346 	LanguageManager::instance()->findHyphDictionarySets(m_dictionaryPaths, m_dictionaryMap);
347 
348 	installedTableWidget->clear();
349 	installedTableWidget->setRowCount(m_dictionaryMap.count());
350 	installedTableWidget->setColumnCount(4);
351 	installedTableWidget->setSortingEnabled(false);
352 	installedTableWidget->setSelectionBehavior(QTableWidget::SelectRows);
353 
354 	QMapIterator<QString, QString> i(m_dictionaryMap);
355 	int row = 0;
356 	while (i.hasNext())
357 	{
358 		 i.next();
359 		 int column = 0;
360 //		 qDebug()<<i.key()<<i.value()<<LanguageManager::instance()->getLangFromAbbrev(i.key(), false);
361 		 QTableWidgetItem *newItem1 = new QTableWidgetItem(LanguageManager::instance()->getLangFromAbbrev(i.key()));
362 		 newItem1->setFlags(newItem1->flags() & ~Qt::ItemIsEditable);
363 		 installedTableWidget->setItem(row, column++, newItem1);
364 		 QTableWidgetItem *newItem2 = new QTableWidgetItem(i.key());
365 		 newItem2->setFlags(newItem1->flags());
366 		 installedTableWidget->setItem(row, column++, newItem2);
367 		 QTableWidgetItem *newItem3 = new QTableWidgetItem(i.value());
368 		 newItem3->setFlags(newItem1->flags());
369 		 newItem3->setToolTip(i.value());
370 		 installedTableWidget->setItem(row, column++, newItem3);
371 		 QTableWidgetItem *newItem4 = new QTableWidgetItem(i.value());
372 		 newItem4->setFlags(newItem1->flags());
373 		 newItem4->setToolTip(i.value());
374 		 installedTableWidget->setItem(row, column++, newItem4);
375 		 ++row;
376 	}
377 
378 	QStringList headers;
379 	headers << tr("Language") << tr("Code") << tr("Location") << tr("Licence");
380 	installedTableWidget->setHorizontalHeaderLabels(headers);
381 	installedTableWidget->resizeColumnsToContents();
382 	installedTableWidget->setSortingEnabled(true);
383 	installedTableWidget->sortByColumn(0, Qt::AscendingOrder);
384 }
385 
updateInstalledSpell()386 void ResourceManager::updateInstalledSpell()
387 {
388 	bool dictsFound=LanguageManager::instance()->findSpellingDictionaries(m_dictionaryPaths);
389 	if (!dictsFound)
390 		return;
391 	m_dictionaryMap.clear();
392 	LanguageManager::instance()->findSpellingDictionarySets(m_dictionaryPaths, m_dictionaryMap);
393 
394 	installedTableWidget->clear();
395 	installedTableWidget->setRowCount(m_dictionaryMap.count());
396 	installedTableWidget->setColumnCount(3);
397 	installedTableWidget->setSortingEnabled(false);
398 	installedTableWidget->setSelectionBehavior(QTableWidget::SelectRows);
399 
400 	QMapIterator<QString, QString> i(m_dictionaryMap);
401 	int row = 0;
402 	while (i.hasNext())
403 	{
404 		 i.next();
405 		 int column = 0;
406 //		 qDebug()<<i.key()<<i.value()<<LanguageManager::instance()->getLangFromAbbrev(i.key(), false);
407 		 QTableWidgetItem *newItem1 = new QTableWidgetItem(LanguageManager::instance()->getLangFromAbbrev(i.key()));
408 		 newItem1->setFlags(newItem1->flags() & ~Qt::ItemIsEditable);
409 		 installedTableWidget->setItem(row, column++, newItem1);
410 		 QTableWidgetItem *newItem2 = new QTableWidgetItem(i.key());
411 		 newItem2->setFlags(newItem1->flags());
412 		 installedTableWidget->setItem(row, column++, newItem2);
413 		 QTableWidgetItem *newItem3 = new QTableWidgetItem(i.value());
414 		 newItem3->setFlags(newItem1->flags());
415 		 newItem3->setToolTip(i.value());
416 		 installedTableWidget->setItem(row, column++, newItem3);
417 		 ++row;
418 	}
419 
420 	QStringList headers;
421 	headers << tr("Language") << tr("Code") << tr("Location");
422 	installedTableWidget->setHorizontalHeaderLabels(headers);
423 	installedTableWidget->resizeColumnsToContents();
424 	installedTableWidget->setSortingEnabled(true);
425 	installedTableWidget->sortByColumn(0, Qt::AscendingOrder);
426 }
427 
updateInstalledTemplates()428 void ResourceManager::updateInstalledTemplates()
429 {
430 	m_dictionaryMap.clear();
431 	installedTableWidget->clear();
432 }
433 
updateInstalledHelp()434 void ResourceManager::updateInstalledHelp()
435 {
436 	m_dictionaryMap.clear();
437 	QString helpDir(findDestinationFolder());
438 	for (const DownloadItem &d : qAsConst(m_availableList))
439 	{
440 		if (QFileInfo::exists(helpDir+d.lang))
441 			m_dictionaryMap.insert(d.desc, helpDir+d.lang);
442 	}
443 	installedTableWidget->clear();
444 	installedTableWidget->setRowCount(m_dictionaryMap.count());
445 	installedTableWidget->setColumnCount(2);
446 	installedTableWidget->setSortingEnabled(false);
447 	installedTableWidget->setSelectionBehavior(QTableWidget::SelectRows);
448 
449 	QMapIterator<QString, QString> i(m_dictionaryMap);
450 	int row = 0;
451 	while (i.hasNext())
452 	{
453 		i.next();
454 		int column = 0;
455 		QTableWidgetItem *newItem1 = new QTableWidgetItem(i.key());
456 		newItem1->setFlags(newItem1->flags() & ~Qt::ItemIsEditable);
457 		installedTableWidget->setItem(row, column++, newItem1);
458 		QTableWidgetItem *newItem2 = new QTableWidgetItem(i.value());
459 		newItem2->setFlags(newItem1->flags());
460 		installedTableWidget->setItem(row, column++, newItem2);
461 		++row;
462 	}
463 
464 	QStringList headers;
465 	headers << tr("Description") << tr("Location") ;
466 	installedTableWidget->setHorizontalHeaderLabels(headers);
467 	installedTableWidget->resizeColumnsToContents();
468 	installedTableWidget->setSortingEnabled(true);
469 	installedTableWidget->sortByColumn(0, Qt::AscendingOrder);
470 }
471 
updateInstalledPalettes()472 void ResourceManager::updateInstalledPalettes()
473 {
474 	m_dictionaryMap.clear();
475 	QString palDir(findDestinationFolder());
476 	for (const DownloadItem& d : qAsConst(m_availableList))
477 	{
478 		if (QFileInfo::exists(palDir+d.files))
479 			m_dictionaryMap.insert(d.desc, palDir+d.files);
480 	}
481 
482 	installedTableWidget->clear();
483 	installedTableWidget->setRowCount(m_dictionaryMap.count());
484 	installedTableWidget->setColumnCount(2);
485 	installedTableWidget->setSortingEnabled(false);
486 	installedTableWidget->setSelectionBehavior(QTableWidget::SelectRows);
487 
488 	QMapIterator<QString, QString> i(m_dictionaryMap);
489 	int row = 0;
490 	while (i.hasNext())
491 	{
492 		i.next();
493 		int column = 0;
494 		QTableWidgetItem *newItem1 = new QTableWidgetItem(i.key());
495 		newItem1->setFlags(newItem1->flags() & ~Qt::ItemIsEditable);
496 		installedTableWidget->setItem(row, column++, newItem1);
497 		QTableWidgetItem *newItem2 = new QTableWidgetItem(i.value());
498 		newItem2->setFlags(newItem1->flags());
499 		installedTableWidget->setItem(row, column++, newItem2);
500 		++row;
501 	}
502 
503 	QStringList headers;
504 	headers << tr("Description") << tr("Location") ;
505 	installedTableWidget->setHorizontalHeaderLabels(headers);
506 	installedTableWidget->resizeColumnsToContents();
507 	installedTableWidget->setSortingEnabled(true);
508 	installedTableWidget->sortByColumn(0, Qt::AscendingOrder);
509 }
510 
updateInstalledTest()511 void ResourceManager::updateInstalledTest()
512 {
513 	m_dictionaryMap.clear();
514 	installedTableWidget->clear();
515 }
516 
updateAvailableFonts()517 void ResourceManager::updateAvailableFonts()
518 {
519 	availableTableWidget->clear();
520 	if (m_availableList.isEmpty())
521 	{
522 		downloadButton->setEnabled(false);
523 		return;
524 	}
525 	availableTableWidget->setRowCount(m_availableList.count());
526 	availableTableWidget->setColumnCount(4);
527 	availableTableWidget->setSortingEnabled(false);
528 
529 	int row = 0;
530 	for (const DownloadItem& d :  qAsConst(m_availableList))
531 	{
532 		int column = 0;
533 //		qDebug()<<d.version<<d.files<<d.url<<d.desc<<d.license;
534 		QTableWidgetItem *newItem1 = new QTableWidgetItem(d.desc);
535 		newItem1->setFlags(newItem1->flags() & ~Qt::ItemIsEditable & ~Qt::ItemIsSelectable);
536 		availableTableWidget->setItem(row, column++, newItem1);
537 		QTableWidgetItem *newItem2 = new QTableWidgetItem(d.type);
538 		newItem2->setFlags(newItem1->flags());
539 		availableTableWidget->setItem(row, column++, newItem2);
540 		QTableWidgetItem *newItem3 = new QTableWidgetItem();
541 		newItem3->setCheckState(m_dictionaryMap.contains(d.desc) ? Qt::Checked : Qt::Unchecked);
542 		newItem3->setFlags(newItem1->flags() & ~Qt::ItemIsUserCheckable);
543 		availableTableWidget->setItem(row, column++, newItem3);
544 		QTableWidgetItem *newItem4 = new QTableWidgetItem();
545 		newItem4->setFlags(newItem1->flags());
546 		newItem4->setCheckState(d.download ? Qt::Checked : Qt::Unchecked);
547 		availableTableWidget->setItem(row, column++, newItem4);
548 		++row;
549 	}
550 
551 	QStringList headers;
552 	headers << tr("Description") << tr("Type") << tr("Installed") << tr("Download");
553 	availableTableWidget->setHorizontalHeaderLabels(headers);
554 	availableTableWidget->resizeColumnsToContents();
555 	availableTableWidget->setSortingEnabled(true);
556 	availableTableWidget->sortByColumn(0, Qt::AscendingOrder);
557 	downloadButton->setEnabled(true);
558 }
559 
updateAvailableHyph()560 void ResourceManager::updateAvailableHyph()
561 {
562 	QFile dataFile(ScPaths::downloadDir() + m_dataFiles[RM_HYPH]);
563 	if (!dataFile.exists())
564 		return;
565 	if (!dataFile.open(QIODevice::ReadOnly))
566 		return;
567 
568 	QTextStream ts(&dataFile);
569 	ts.setCodec(QTextCodec::codecForName("UTF-8"));
570 	QString errorMsg;
571 	int eline;
572 	int ecol;
573 	QDomDocument doc( QString(m_dataFiles[RM_HYPH]).remove(".xml") );
574 	QString data(ts.readAll());
575 	dataFile.close();
576 	if ( !doc.setContent( data, &errorMsg, &eline, &ecol ))
577 	{
578 		if (data.contains("404 not found", Qt::CaseInsensitive))
579 			qDebug()<<"File not found on server";
580 		else
581 			qDebug()<<"Could not open file"<<dataFile.fileName();
582 		return;
583 	}
584 	m_availableList.clear();
585 
586 	QDomElement docElem = doc.documentElement();
587 	for (QDomNode n = docElem.firstChild(); !n.isNull(); n = n.nextSibling())
588 	{
589 		QDomElement e = n.toElement();
590 		if (e.isNull())
591 			continue;
592 		if (e.tagName() != "dictionary")
593 			continue;
594 		if (!e.hasAttribute("type") || !e.hasAttribute("filetype"))
595 			continue;
596 		if (e.attribute("type") != "hyph")
597 			continue;
598 
599 		struct DownloadItem d;
600 		d.desc=e.attribute("description");
601 		d.download=false;
602 		d.files=e.attribute("files");
603 		d.extractfiles=e.attribute("extractfiles");
604 		d.url=e.attribute("URL");
605 		d.version=e.attribute("version");
606 		d.lang=e.attribute("language");
607 		d.license=e.attribute("license");
608 		d.filetype=e.attribute("filetype");
609 		d.type=e.attribute("type");
610 		QUrl url(d.url);
611 		if (url.isValid() && !url.isEmpty() && !url.host().isEmpty())
612 			m_availableList.append(d);
613 		//else
614 		//	qDebug()<<"hysettings : availDicts : invalid URL"<<d.url;
615 	}
616 	availableTableWidget->clear();
617 	if (m_availableList.isEmpty())
618 	{
619 		downloadButton->setEnabled(false);
620 		return;
621 	}
622 	availableTableWidget->setRowCount(m_availableList.count());
623 	availableTableWidget->setColumnCount(5);
624 	availableTableWidget->setSortingEnabled(false);
625 
626 	int row = 0;
627 	for (const DownloadItem& d : qAsConst(m_availableList))
628 	{
629 		int column = 0;
630 		//qDebug()<<d.version<<d.files<<d.url<<d.desc<<d.license;
631 		QTableWidgetItem *newItem1 = new QTableWidgetItem(d.desc);
632 		newItem1->setFlags(newItem1->flags() & ~Qt::ItemIsEditable & ~Qt::ItemIsSelectable);
633 		availableTableWidget->setItem(row, column++, newItem1);
634 		QTableWidgetItem *newItem2 = new QTableWidgetItem(d.lang);
635 		newItem2->setFlags(newItem1->flags());
636 		availableTableWidget->setItem(row, column++, newItem2);
637 		QTableWidgetItem *newItem3 = new QTableWidgetItem();
638 		newItem3->setCheckState(m_dictionaryMap.contains(d.lang) ? Qt::Checked : Qt::Unchecked);
639 		newItem3->setFlags(newItem1->flags() & ~Qt::ItemIsUserCheckable);
640 		availableTableWidget->setItem(row, column++, newItem3);
641 		QTableWidgetItem *newItem4 = new QTableWidgetItem(d.license);
642 		availableTableWidget->setItem(row, column++, newItem4);
643 		newItem4->setFlags(newItem4->flags() & ~Qt::ItemIsEditable);
644 		QTableWidgetItem *newItem5 = new QTableWidgetItem();
645 		newItem5->setFlags(newItem1->flags());
646 		newItem5->setCheckState(d.download ? Qt::Checked : Qt::Unchecked);
647 		availableTableWidget->setItem(row, column++, newItem5);
648 		++row;
649 	}
650 
651 	QStringList headers;
652 	headers << tr("Language") << tr("Code") << tr("Installed") << tr("License") << tr("Download");
653 	availableTableWidget->setHorizontalHeaderLabels(headers);
654 	availableTableWidget->resizeColumnsToContents();
655 	availableTableWidget->setSortingEnabled(true);
656 	availableTableWidget->sortByColumn(0, Qt::AscendingOrder);
657 	downloadButton->setEnabled(true);
658 }
659 
updateAvailableSpell()660 void ResourceManager::updateAvailableSpell()
661 {
662 	QFile dataFile(ScPaths::downloadDir() + m_dataFiles[RM_SPELL]);
663 	if (!dataFile.exists())
664 		return;
665 	if (!dataFile.open(QIODevice::ReadOnly))
666 		return;
667 
668 	QTextStream ts(&dataFile);
669 	ts.setCodec(QTextCodec::codecForName("UTF-8"));
670 	QString errorMsg;
671 	int eline;
672 	int ecol;
673 	QDomDocument doc( QString(m_dataFiles[RM_SPELL]).remove(".xml") );
674 	QString data(ts.readAll());
675 	dataFile.close();
676 	if ( !doc.setContent( data, &errorMsg, &eline, &ecol ))
677 	{
678 		if (data.contains("404 not found", Qt::CaseInsensitive))
679 			qDebug()<<"File not found on server";
680 		else
681 			qDebug()<<"Could not open file"<<dataFile.fileName();
682 		return;
683 	}
684 	m_availableList.clear();
685 
686 	QDomElement docElem = doc.documentElement();
687 	for (QDomNode n = docElem.firstChild(); !n.isNull(); n = n.nextSibling())
688 	{
689 		QDomElement e = n.toElement();
690 		if (e.isNull())
691 			continue;
692 		if (e.tagName() != "dictionary")
693 			continue;
694 		if (!e.hasAttribute("type") || !e.hasAttribute("filetype"))
695 			continue;
696 		if (e.attribute("type") != "spell")
697 			continue;
698 
699 		struct DownloadItem d;
700 		d.desc=e.attribute("description");
701 		d.download=false;
702 		d.files=e.attribute("files");
703 		d.extractfiles=e.attribute("extractfiles");
704 		d.url=e.attribute("URL");
705 		d.version=e.attribute("version");
706 		d.lang=e.attribute("language");
707 		d.license=e.attribute("license");
708 		d.filetype=e.attribute("filetype");
709 		d.type=e.attribute("type");
710 		QUrl url(d.url);
711 		if (url.isValid() && !url.isEmpty() && !url.host().isEmpty())
712 			m_availableList.append(d);
713 		//else
714 		//	qDebug()<<"hysettings : availDicts : invalid URL"<<d.url;
715 	}
716 	availableTableWidget->clear();
717 	if (m_availableList.isEmpty())
718 	{
719 		downloadButton->setEnabled(false);
720 		return;
721 	}
722 	availableTableWidget->setRowCount(m_availableList.count());
723 	availableTableWidget->setColumnCount(5);
724 	availableTableWidget->setSortingEnabled(false);
725 
726 	int row = 0;
727 	for (const DownloadItem& d : qAsConst(m_availableList))
728 	{
729 		int column = 0;
730 		//qDebug()<<d.version<<d.files<<d.url<<d.desc<<d.license;
731 		QTableWidgetItem *newItem1 = new QTableWidgetItem(d.desc);
732 		newItem1->setFlags(newItem1->flags() & ~Qt::ItemIsEditable & ~Qt::ItemIsSelectable);
733 		availableTableWidget->setItem(row, column++, newItem1);
734 		QTableWidgetItem *newItem2 = new QTableWidgetItem(d.lang);
735 		newItem2->setFlags(newItem1->flags());
736 		availableTableWidget->setItem(row, column++, newItem2);
737 		QTableWidgetItem *newItem3 = new QTableWidgetItem();
738 		newItem3->setCheckState(m_dictionaryMap.contains(d.lang) ? Qt::Checked : Qt::Unchecked);
739 		newItem3->setFlags(newItem1->flags() & ~Qt::ItemIsUserCheckable);
740 		availableTableWidget->setItem(row, column++, newItem3);
741 		QTableWidgetItem *newItem4 = new QTableWidgetItem(d.license);
742 		availableTableWidget->setItem(row, column++, newItem4);
743 		newItem4->setFlags(newItem4->flags() & ~Qt::ItemIsEditable);
744 		QTableWidgetItem *newItem5 = new QTableWidgetItem();
745 		newItem5->setFlags(newItem1->flags());
746 		newItem5->setCheckState(d.download ? Qt::Checked : Qt::Unchecked);
747 		availableTableWidget->setItem(row, column++, newItem5);
748 		++row;
749 	}
750 
751 	QStringList headers;
752 	headers << tr("Language") << tr("Code") << tr("Installed") << tr("License") << tr("Download");
753 	availableTableWidget->setHorizontalHeaderLabels(headers);
754 	availableTableWidget->resizeColumnsToContents();
755 	availableTableWidget->setSortingEnabled(true);
756 	availableTableWidget->sortByColumn(0, Qt::AscendingOrder);
757 	downloadButton->setEnabled(true);
758 }
759 
updateAvailableTemplates()760 void ResourceManager::updateAvailableTemplates()
761 {
762 	availableTableWidget->clear();
763 }
764 
updateAvailableHelp()765 void ResourceManager::updateAvailableHelp()
766 {
767 	availableTableWidget->clear();
768 	if (m_availableList.isEmpty())
769 	{
770 		downloadButton->setEnabled(false);
771 		return;
772 	}
773 	availableTableWidget->setRowCount(m_availableList.count());
774 	availableTableWidget->setColumnCount(5);
775 	availableTableWidget->setSortingEnabled(false);
776 
777 	int row = 0;
778 	for (const DownloadItem& d :  qAsConst(m_availableList))
779 	{
780 		int column = 0;
781 		QTableWidgetItem *newItem1 = new QTableWidgetItem(d.desc);
782 		newItem1->setFlags(newItem1->flags() & ~Qt::ItemIsEditable & ~Qt::ItemIsSelectable);
783 		availableTableWidget->setItem(row, column++, newItem1);
784 		QTableWidgetItem *newItem2 = new QTableWidgetItem(d.lang);
785 		newItem2->setFlags(newItem1->flags());
786 		availableTableWidget->setItem(row, column++, newItem2);
787 		QTableWidgetItem *newItem3 = new QTableWidgetItem();
788 		newItem3->setCheckState(m_dictionaryMap.contains(d.lang) ? Qt::Checked : Qt::Unchecked);
789 		newItem3->setFlags(newItem1->flags() & ~Qt::ItemIsUserCheckable);
790 		availableTableWidget->setItem(row, column++, newItem3);
791 		QTableWidgetItem *newItem4 = new QTableWidgetItem(d.license);
792 		availableTableWidget->setItem(row, column++, newItem4);
793 		newItem4->setFlags(newItem4->flags() & ~Qt::ItemIsEditable);
794 		QTableWidgetItem *newItem5 = new QTableWidgetItem();
795 		newItem5->setFlags(newItem1->flags());
796 		newItem5->setCheckState(d.download ? Qt::Checked : Qt::Unchecked);
797 		availableTableWidget->setItem(row, column++, newItem5);
798 		++row;
799 	}
800 
801 	QStringList headers;
802 	headers << tr("Description") << tr("Language") << tr("Installed") << tr("License") << tr("Download");
803 	availableTableWidget->setHorizontalHeaderLabels(headers);
804 	availableTableWidget->resizeColumnsToContents();
805 	availableTableWidget->setSortingEnabled(true);
806 	availableTableWidget->sortByColumn(0, Qt::AscendingOrder);
807 	downloadButton->setEnabled(true);
808 }
809 
updateAvailablePalettes()810 void ResourceManager::updateAvailablePalettes()
811 {
812 	availableTableWidget->clear();
813 	if (m_availableList.isEmpty())
814 	{
815 		downloadButton->setEnabled(false);
816 		return;
817 	}
818 	availableTableWidget->setRowCount(m_availableList.count());
819 	availableTableWidget->setColumnCount(5);
820 	availableTableWidget->setSortingEnabled(false);
821 
822 	int row = 0;
823 	for (const DownloadItem &d : qAsConst(m_availableList))
824 	{
825 		int column = 0;
826 		QTableWidgetItem *newItem1 = new QTableWidgetItem(d.desc);
827 		newItem1->setFlags(newItem1->flags() & ~Qt::ItemIsEditable & ~Qt::ItemIsSelectable);
828 		availableTableWidget->setItem(row, column++, newItem1);
829 		QTableWidgetItem *newItem2 = new QTableWidgetItem(d.source);
830 		newItem2->setFlags(newItem1->flags());
831 		availableTableWidget->setItem(row, column++, newItem2);
832 		QTableWidgetItem *newItem3 = new QTableWidgetItem();
833 		newItem3->setCheckState(m_dictionaryMap.contains(d.desc) ? Qt::Checked : Qt::Unchecked);
834 		newItem3->setFlags(newItem1->flags() & ~Qt::ItemIsUserCheckable);
835 		availableTableWidget->setItem(row, column++, newItem3);
836 		QTableWidgetItem *newItem4 = new QTableWidgetItem(d.license);
837 		availableTableWidget->setItem(row, column++, newItem4);
838 		newItem4->setFlags(newItem4->flags() & ~Qt::ItemIsEditable);
839 		QTableWidgetItem *newItem5 = new QTableWidgetItem();
840 		newItem5->setFlags(newItem1->flags());
841 		newItem5->setCheckState(d.download ? Qt::Checked : Qt::Unchecked);
842 		availableTableWidget->setItem(row, column++, newItem5);
843 		++row;
844 	}
845 
846 	QStringList headers;
847 	headers << tr("Description") << tr("Source") << tr("Installed") << tr("License") << tr("Download");
848 	availableTableWidget->setHorizontalHeaderLabels(headers);
849 	availableTableWidget->resizeColumnsToContents();
850 	availableTableWidget->setSortingEnabled(true);
851 	availableTableWidget->sortByColumn(0, Qt::AscendingOrder);
852 	downloadButton->setEnabled(true);
853 }
854 
updateAvailableTest()855 void ResourceManager::updateAvailableTest()
856 {
857 	availableTableWidget->clear();
858 }
859 
findDestinationFolder()860 QString ResourceManager::findDestinationFolder()
861 {
862 	QString destinationFolder;
863 	int category = categoryComboBox->currentData().toInt();
864 	switch (category)
865 	{
866 		case RM_FONTS:
867 			destinationFolder=ScPaths::userFontDir(true);
868 			break;
869 		case RM_HYPH:
870 			destinationFolder=ScPaths::userDictDir(ScPaths::Hyph, true);
871 			break;
872 		case RM_SPELL:
873 			destinationFolder=ScPaths::userDictDir(ScPaths::Spell, true);
874 			break;
875 		case RM_TEMPLATES:
876 			//temporary
877 			destinationFolder=ScPaths::tempFileDir();
878 			//TODO!!!! destinationFolder=ScPaths::getUserDictDir(true);
879 			break;
880 		case RM_HELP:
881 			destinationFolder=ScPaths::userHelpFilesDir(true);
882 			break;
883 		case RM_PALETTES:
884 			destinationFolder=ScPaths::userPaletteFilesDir(true);
885 			break;
886 		case RM_TEST:
887 			destinationFolder=ScPaths::downloadDir();
888 			break;
889 	}
890 	return destinationFolder;
891 }
892 
categoryChanged()893 void ResourceManager::categoryChanged()
894 {
895 	int category = categoryComboBox->currentData().toInt();
896 	switch (category)
897 	{
898 		case RM_FONTS:
899 			readAvailableFonts();
900 			updateInstalledFonts();
901 			updateAvailableFonts();
902 			break;
903 		case RM_HYPH:
904 			updateInstalledHyph();
905 			updateAvailableHyph();
906 			break;
907 		case RM_SPELL:
908 			updateInstalledSpell();
909 			updateAvailableSpell();
910 			break;
911 		case RM_TEMPLATES:
912 			updateInstalledTemplates();
913 			updateAvailableTemplates();
914 			break;
915 		case RM_HELP:
916 			readAvailableHelp();
917 			updateInstalledHelp();
918 			updateAvailableHelp();
919 			break;
920 		case RM_PALETTES:
921 			readAvailablePalettes();
922 			updateInstalledPalettes();
923 			updateAvailablePalettes();
924 			break;
925 		case RM_TEST:
926 			updateInstalledTest();
927 			updateAvailableTest();
928 			break;
929 	}
930 }
931 
updateDownloadLists()932 void ResourceManager::updateDownloadLists()
933 {
934 	updateAvailableButton->setEnabled(false);
935 	downloadButton->setEnabled(false);
936 	downloadProgressBar->setValue(0);
937 	downloadProgressBar->setVisible(true);
938 	dataReceivedLabel->setVisible(true);
939 	downloadProgressBar->setRange(0, m_dataFiles.count());
940 	for (const QString& f : qAsConst(m_dataFiles))
941 		ScQApp->dlManager()->addURL("http://services.scribus.net/" + f, true, ScPaths::downloadDir(), ScPaths::downloadDir());
942 	for (const QString& f : qAsConst(m_dataFiles))
943 		ScQApp->dlManager()->addURL("http://services.scribus.net/" + f + ".sha256", true, ScPaths::downloadDir(), ScPaths::downloadDir());
944 	connect(ScQApp->dlManager(), SIGNAL(finished()), this, SLOT(downloadListFinished()));
945 	connect(ScQApp->dlManager(), SIGNAL(fileReceived(const QString&)), this, SLOT(updateProgressBar()));
946 	connect(ScQApp->dlManager(), SIGNAL(fileFailed(const QString&)), this, SLOT(updateProgressBar()));
947 	connect(ScQApp->dlManager(), SIGNAL(fileFailed(const QString&)), this, SLOT(updateProgressBar()));
948 	connect(ScQApp->dlManager(), SIGNAL(fileDownloadProgress(qint64, qint64)), this, SLOT(updateProgressData(qint64, qint64)));
949 	ScQApp->dlManager()->startDownloads();
950 }
951 
downloadListFinished()952 void ResourceManager::downloadListFinished()
953 {
954 	disconnect(ScQApp->dlManager(), SIGNAL(finished()), this, SLOT(downloadListFinished()));
955 	disconnect(ScQApp->dlManager(), SIGNAL(fileReceived(const QString&)), this, SLOT(updateProgressBar()));
956 	disconnect(ScQApp->dlManager(), SIGNAL(fileFailed(const QString&)), this, SLOT(updateProgressBar()));
957 	disconnect(ScQApp->dlManager(), SIGNAL(fileDownloadProgress(qint64, qint64)), this, SLOT(updateProgressData(qint64, qint64)));
958 
959 	int category = categoryComboBox->currentData().toInt();
960 	bool fileOk = checkFileHash(ScPaths::downloadDir(), m_dataFiles[category], m_dataFiles[category] + ".sha256", QCryptographicHash::Sha256);
961 	switch (category)
962 	{
963 		case RM_FONTS:
964 			if (fileOk)
965 				updateAvailableFonts();
966 			break;
967 		case RM_HYPH:
968 			if (fileOk)
969 				updateAvailableHyph();
970 			break;
971 		case RM_SPELL:
972 			if (fileOk)
973 				updateAvailableSpell();
974 			break;
975 		case RM_TEMPLATES:
976 			if (fileOk)
977 				updateAvailableTemplates();
978 			break;
979 		case RM_HELP:
980 			if (fileOk)
981 				updateAvailableHelp();
982 			else
983 				qDebug()<<"Help Failure :(";
984 			break;
985 		case RM_PALETTES:
986 			if (fileOk)
987 				updateAvailablePalettes();
988 			else
989 				qDebug()<<"Palette Failure :(";
990 			break;
991 		case RM_TEST:
992 			if (fileOk)
993 				qDebug()<<"Success!!!";
994 			else
995 				qDebug()<<"Failure :(";
996 			break;
997 	}
998 	updateAvailableButton->setEnabled(true);
999 	downloadButton->setEnabled(true);
1000 	downloadProgressBar->setValue(0);
1001 	downloadProgressBar->setVisible(false);
1002 	dataReceivedLabel->setVisible(false);
1003 }
1004 
downloadFilesFinished()1005 void ResourceManager::downloadFilesFinished()
1006 {
1007 	disconnect(ScQApp->dlManager(), SIGNAL(finished()), this, SLOT(downloadFilesFinished()));
1008 	disconnect(ScQApp->dlManager(), SIGNAL(fileReceived(const QString&)), this, SLOT(updateProgressBar()));
1009 	disconnect(ScQApp->dlManager(), SIGNAL(fileFailed(const QString&)), this, SLOT(updateProgressBar()));
1010 	disconnect(ScQApp->dlManager(), SIGNAL(fileDownloadProgress(qint64, qint64)), this, SLOT(updateProgressData(qint64, qint64)));
1011 
1012 	downloadProgressBar->setValue(0);
1013 	downloadProgressBar->setVisible(false);
1014 	dataReceivedLabel->setVisible(false);
1015 	downloadButton->setEnabled(true);
1016 
1017 	int category = categoryComboBox->currentData().toInt();
1018 	switch (category)
1019 	{
1020 		case RM_FONTS:
1021 			for (const DownloadItem& d : qAsConst(m_downloadList))
1022 			{
1023 				if (d.filetype=="zip")
1024 				{
1025 					QString fn(ScPaths::userFontDir(true)+d.files);
1026 					QFile dledFile(fn);
1027 					QFileInfo fi(dledFile);
1028 					if (!dledFile.exists())
1029 						qDebug()<<"File doesn\'t exist"<<fn;
1030 					else
1031 					{
1032 						ScZipHandler* fun = new ScZipHandler();
1033 						if (!fun->open(fn))
1034 							qDebug()<<"Zip file doesn\'t open"<<fn;
1035 						else
1036 						{
1037 							const QStringList zipFileContents(fun->files());
1038 							QStringList extractFiles(d.extractfiles.split(";", Qt::SkipEmptyParts));
1039 							QString toDir(ScPaths::userFontDir(false)+fi.baseName()+"/");
1040 							QDir dir(ScPaths::userFontDir(false));
1041 							if (!dir.exists(fi.baseName()))
1042 								dir.mkdir(fi.baseName());
1043 							for (const QString& f2e : zipFileContents)
1044 							{
1045 								fun->extract(f2e, toDir, ScZipHandler::SkipPaths);
1046 							}
1047 						}
1048 						delete fun;
1049 					}
1050 				}
1051 				if (d.filetype=="plain")
1052 				{
1053 					//do nothing as the file is alread in place from dl mgr
1054 				}
1055 			}
1056 			break;
1057 		case RM_HYPH:
1058 		case RM_SPELL:
1059 			{
1060 				int fileType = category == RM_HYPH ? ScPaths::Hyph : ScPaths::Spell;
1061 				for (const DownloadItem& d : qAsConst(m_downloadList))
1062 				{
1063 					if (d.filetype=="zip")
1064 					{
1065 						QString fn(ScPaths::userDictDir(static_cast<ScPaths::DictType>(fileType), true)+d.files);
1066 						if (!QFileInfo::exists(fn))
1067 							qDebug()<<"File doesn\'t exist"<<fn;
1068 						else
1069 						{
1070 							ScZipHandler* fun = new ScZipHandler();
1071 							if (!fun->open(fn))
1072 								qDebug()<<"Zip file doesn\'t open"<<fn;
1073 							else
1074 							{
1075 								const QStringList zipContents(fun->files());
1076 								QStringList extractFiles(d.extractfiles.split(";", Qt::SkipEmptyParts));
1077 								QString toDir(ScPaths::userDictDir(static_cast<ScPaths::DictType>(fileType), false));
1078 								QDir dir(toDir);
1079 								if (dir.exists())
1080 								{
1081 									for (const QString& f2e : zipContents)
1082 									{
1083 										if (extractFiles.contains(f2e))
1084 											fun->extract(f2e, toDir, ScZipHandler::SkipPaths);
1085 									}
1086 								}
1087 							}
1088 							delete fun;
1089 						}
1090 					}
1091 					if (d.filetype=="plain")
1092 					{
1093 						//do nothing as the file is alread in place from dl mgr
1094 					}
1095 				}
1096 			}
1097 			break;
1098 		case RM_HELP:
1099 			for (const DownloadItem& d : qAsConst(m_downloadList))
1100 			{
1101 				//qDebug()<<d.desc<<d.download<<d.files<<d.type;
1102 				if (d.filetype=="zip")
1103 				{
1104 					QString fn(ScPaths::userHelpFilesDir(true)+d.files);
1105 					//qDebug()<<fn;
1106 					QFile dledFile(fn);
1107 					QFileInfo fi(dledFile);
1108 					QFile dledFileSHA256(fn+".sha256");
1109 					QFileInfo fiSHA256(dledFileSHA256);
1110 					if (!dledFile.exists() || !dledFileSHA256.exists())
1111 						qDebug()<<"File doesn\'t exist"<<fn<<fn+".sha256";
1112 					else
1113 					{
1114 						if (checkFileHash(ScPaths::userHelpFilesDir(false), fi.fileName(), fiSHA256.fileName(), QCryptographicHash::Sha256))
1115 						{
1116 							ScZipHandler* fun = new ScZipHandler();
1117 							if (!fun->open(fn))
1118 								qDebug()<<"Zip file doesn\'t open"<<fn;
1119 							else
1120 							{
1121 								const QStringList zipFileContents(fun->files());
1122 								QStringList extractFiles(d.extractfiles.split(";", Qt::SkipEmptyParts));
1123 								QString toDir(ScPaths::userHelpFilesDir(false)+d.lang+"/");
1124 								QDir dir(ScPaths::userHelpFilesDir(false));
1125 								if (!dir.exists(d.lang))
1126 									dir.mkdir(d.lang);
1127 								for (const QString& f2e : zipFileContents)
1128 								{
1129 									//qDebug()<<"Unzipping"<<f2e<<"to"<<toDir;
1130 									fun->extract(f2e, toDir, ScZipHandler::ExtractPaths);
1131 								}
1132 							}
1133 							delete fun;
1134 						}
1135 						else
1136 							qDebug()<<"checksum failed for"<<fn + ".sha256";
1137 						dledFile.remove();
1138 						dledFileSHA256.remove();
1139 					}
1140 				}
1141 				if (d.filetype=="plain")
1142 				{
1143 					//do nothing as the file is alread in place from dl mgr
1144 				}
1145 			}
1146 			break;
1147 	}
1148 	categoryChanged();
1149 }
1150 
downloadLicenseFinished()1151 void ResourceManager::downloadLicenseFinished()
1152 {
1153 	disconnect(ScQApp->dlManager(), SIGNAL(finished()), this, SLOT(downloadLicenseFinished()));
1154 }
1155 
downloadLicenseFileFinished(const QString & licenceFileName)1156 void ResourceManager::downloadLicenseFileFinished(const QString &licenceFileName)
1157 {
1158 	disconnect(ScQApp->dlManager(), SIGNAL(fileReceived(const QString&)), this, SLOT(downloadLicenseFileFinished(const QString&)));
1159 	QFile dataFile(licenceFileName);
1160 	QTextStream ts(&dataFile);
1161 	QString data;
1162 	if (dataFile.exists())
1163 	{
1164 		if (!dataFile.open(QIODevice::ReadOnly))
1165 			return;
1166 		data = ts.readAll();
1167 		dataFile.close();
1168 	}
1169 	ResourceManagerLicense* rml = new ResourceManagerLicense(parentWidget());
1170 	rml->setText(data);
1171 	if (rml->exec())
1172 		rml->deleteLater();
1173 	if (dataFile.exists())
1174 		dataFile.remove();
1175 }
1176 
downloadLicenseFileFailed(const QString &)1177 void ResourceManager::downloadLicenseFileFailed(const QString&)
1178 {
1179 	disconnect(ScQApp->dlManager(), SIGNAL(fileFailed(const QString&)), this, SLOT(downloadLicenseFileFailed(const QString&)));
1180 	QMessageBox msgBox;
1181 	msgBox.setText("The license file failed to download");
1182 	msgBox.setStandardButtons(QMessageBox::Ok);
1183 	msgBox.exec();
1184 }
1185 
updateProgressBar()1186 void ResourceManager::updateProgressBar()
1187 {
1188 	downloadProgressBar->setValue(downloadProgressBar->value() + 1);
1189 }
1190 
updateProgressData(qint64 bytesReceived,qint64 bytesTotal)1191 void ResourceManager::updateProgressData(qint64 bytesReceived, qint64 bytesTotal)
1192 {
1193 	QString totalText;
1194 	if (bytesTotal == -1)
1195 		totalText = QString("%1 kB").arg(bytesReceived/1000);
1196 	else
1197 //	{
1198 		totalText = QString("%1 / %2 kB").arg(bytesReceived/1000).arg(bytesTotal/1000);
1199 //		QString totalTextWidth = QString("%1 / %2 kB").arg(bytesTotal).arg(bytesTotal);
1200 //		dataReceivedLabel->setMinimumWidth(QWidget::fontMetrics().width(totalTextWidth));
1201 //	}
1202 	dataReceivedLabel->setText(totalText);
1203 }
1204 
startDownload()1205 void ResourceManager::startDownload()
1206 {
1207 	int rows = availableTableWidget->rowCount();
1208 	int columns = availableTableWidget->columnCount();
1209 	QStringList filesToDownload;
1210 	for (int i = 0; i < rows; ++i)
1211 	{
1212 		QTableWidgetItem *dlItem = availableTableWidget->item(i, columns - 1);
1213 		if (dlItem->checkState() == Qt::Checked)
1214 			filesToDownload << availableTableWidget->item(i, 0)->text();
1215 	}
1216 	if (filesToDownload.isEmpty())
1217 		return;
1218 //	qDebug()<<filesToDownload;
1219 	downloadButton->setEnabled(false);
1220 	m_downloadList.clear();
1221 	downloadProgressBar->setValue(0);
1222 	downloadProgressBar->setVisible(true);
1223 	dataReceivedLabel->setVisible(true);
1224 //	dlLabel->setVisible(true);
1225 	int dlCount = 0;
1226 
1227 	//Set up destination
1228 	QString destinationFolder(findDestinationFolder());
1229 	int category = categoryComboBox->currentData().toInt();
1230 	switch (category)
1231 	{
1232 		case RM_FONTS:
1233 			foreach(DownloadItem d, m_availableList)
1234 			{
1235 				if (!filesToDownload.contains(d.desc))
1236 					continue;
1237 				if (d.filetype=="zip")
1238 				{
1239 					const QStringList plainURLs(d.files.split(";", Qt::SkipEmptyParts));
1240 					for (const QString& s : plainURLs)
1241 					{
1242 //							qDebug()<<"Requesting:"<<d.url+"/"+s;
1243 						ScQApp->dlManager()->addURL(d.url+"/"+s, true, ScPaths::downloadDir(), destinationFolder, d.files);
1244 						++dlCount;
1245 					}
1246 					m_downloadList.append(d);
1247 					d.download=true;
1248 				}
1249 				if (d.filetype=="plain")
1250 				{
1251 					const QStringList plainURLs(d.files.split(";", Qt::SkipEmptyParts));
1252 					for (const QString& s : plainURLs)
1253 					{
1254 						ScQApp->dlManager()->addURL(d.url+"/"+s, true, ScPaths::downloadDir(), destinationFolder);
1255 						++dlCount;
1256 					}
1257 					m_downloadList.append(d);
1258 					d.download=true;
1259 				}
1260 			}
1261 			break;
1262 		case RM_HYPH:
1263 		case RM_SPELL:
1264 			foreach(DownloadItem d, m_availableList)
1265 			{
1266 //				qDebug()<<d.desc;
1267 				if (!filesToDownload.contains(d.desc))
1268 					continue;
1269 				if (d.filetype=="zip")
1270 				{
1271 //						qDebug()<<"zip type:"<<d.url<<d.files;
1272 					const QStringList plainURLs(d.files.split(";", Qt::SkipEmptyParts));
1273 					for (const QString& s : plainURLs)
1274 					{
1275 						ScQApp->dlManager()->addURL(d.url+"/"+s, true, ScPaths::downloadDir(), destinationFolder);
1276 						++dlCount;
1277 					}
1278 					m_downloadList.append(d);
1279 					d.download=true;
1280 				}
1281 				if (d.filetype=="plain")
1282 				{
1283 //						qDebug()<<"plain type:"<<d.url<<d.files;
1284 					const QStringList plainURLs(d.files.split(";", Qt::SkipEmptyParts));
1285 					for (const QString& s : plainURLs)
1286 					{
1287 						ScQApp->dlManager()->addURL(d.url+"/"+s, true, ScPaths::downloadDir(), destinationFolder);
1288 						++dlCount;
1289 					}
1290 					m_downloadList.append(d);
1291 					d.download=true;
1292 				}
1293 			}
1294 			break;
1295 		case RM_HELP:
1296 			foreach(DownloadItem d, m_availableList)
1297 			{
1298 //				qDebug()<<d.desc;
1299 				if (!filesToDownload.contains(d.desc))
1300 					continue;
1301 				if (d.filetype=="zip")
1302 				{
1303 //						qDebug()<<"zip type:"<<d.url<<d.files;
1304 					const QStringList plainURLs(d.files.split(";", Qt::SkipEmptyParts));
1305 					for (const QString& s : plainURLs)
1306 					{
1307 						ScQApp->dlManager()->addURL(d.url+"/"+s, true, ScPaths::downloadDir(), destinationFolder);
1308 						ScQApp->dlManager()->addURL(d.url+"/"+s+".sha256", true, ScPaths::downloadDir(), destinationFolder);
1309 						dlCount+=2;
1310 					}
1311 					m_downloadList.append(d);
1312 					d.download=true;
1313 				}
1314 			}
1315 			break;
1316 		case RM_PALETTES:
1317 			foreach(DownloadItem d, m_availableList)
1318 			{
1319 //				qDebug()<<d.desc;
1320 				if (!filesToDownload.contains(d.desc))
1321 					continue;
1322 				if (d.filetype == "zip")
1323 				{
1324 //						qDebug()<<"zip type:"<<d.url<<d.files;
1325 					const QStringList plainURLs(d.files.split(";", Qt::SkipEmptyParts));
1326 					for (const QString& s : plainURLs)
1327 					{
1328 						ScQApp->dlManager()->addURL(d.url+"/"+s, true, ScPaths::downloadDir(), destinationFolder);
1329 						ScQApp->dlManager()->addURL(d.url+"/"+s+".sha256", true, ScPaths::downloadDir(), destinationFolder);
1330 						dlCount+=2;
1331 					}
1332 					m_downloadList.append(d);
1333 					d.download=true;
1334 				}
1335 			}
1336 			break;
1337 		default:
1338 			break;
1339 	}
1340 	if (dlCount>0)
1341 	{
1342 		downloadProgressBar->setRange(0, dlCount);
1343 		connect(ScQApp->dlManager(), SIGNAL(finished()), this, SLOT(downloadFilesFinished()));
1344 		connect(ScQApp->dlManager(), SIGNAL(fileReceived(const QString&)), this, SLOT(updateProgressBar()));
1345 		connect(ScQApp->dlManager(), SIGNAL(fileFailed(const QString&)), this, SLOT(updateProgressBar()));
1346 		connect(ScQApp->dlManager(), SIGNAL(fileDownloadProgress(qint64, qint64)), this, SLOT(updateProgressData(qint64, qint64)));
1347 		ScQApp->dlManager()->startDownloads();
1348 	}
1349 }
1350 
showInFileBrowser()1351 void ResourceManager::showInFileBrowser()
1352 {
1353 	QString filePath;
1354 	QTableWidgetItem* item;
1355 
1356 	auto selectedItems = installedTableWidget->selectedItems();
1357 	if (selectedItems.count() <= 0)
1358 		return;
1359 
1360 	int currentRow = installedTableWidget->currentRow();
1361 
1362 	int category = categoryComboBox->currentData().toInt();
1363 	switch (category)
1364 	{
1365 	case RM_FONTS:
1366 		item = installedTableWidget->item(currentRow, 1);
1367 		filePath = item->text();
1368 		break;
1369 	case RM_HYPH:
1370 		item = installedTableWidget->item(currentRow, 2);
1371 		filePath = item->text();
1372 		break;
1373 	case RM_SPELL:
1374 		item = installedTableWidget->item(currentRow, 2);
1375 		filePath = item->text() + ".dic";
1376 		break;
1377 	case RM_TEMPLATES:
1378 		break;
1379 	case RM_HELP:
1380 		item = installedTableWidget->item(currentRow, 1);
1381 		filePath = item->text();
1382 		break;
1383 	case RM_PALETTES:
1384 		item = installedTableWidget->item(currentRow, 1);
1385 		filePath = item->text();
1386 		break;
1387 	case RM_TEST:
1388 		break;
1389 	}
1390 
1391 	if (!filePath.isEmpty())
1392 	{
1393 		QString dirPath = QFileInfo(filePath).canonicalPath();
1394 		QUrl fileUrl = QUrl::fromLocalFile(dirPath);
1395 		QDesktopServices::openUrl(fileUrl);
1396 	}
1397 }
1398 
showLicense()1399 void ResourceManager::showLicense()
1400 {
1401 	bool localFile=false;
1402 	int rows=availableTableWidget->rowCount();
1403 	QString licenceFileName;
1404 	QString lang;
1405 	//Find our item we want to show the license for. If downloaded, set localFile true
1406 	for (int i = 0; i<rows; ++i)
1407 	{
1408 		QTableWidgetItem *dlItemI=availableTableWidget->item(i, 2);
1409 		QTableWidgetItem *dlItemL=availableTableWidget->item(i, 3);
1410 		localFile=dlItemI->checkState();
1411 		if (dlItemL->isSelected())
1412 		{
1413 			licenceFileName = dlItemL->text();
1414 			lang = availableTableWidget->item(i, 0)->text();
1415 			break;
1416 		}
1417 	}
1418 	if (!licenceFileName.isEmpty())
1419 	{
1420 		bool doDownload=true;
1421 		QString data;
1422 		//Set up destination and get from local file if it exists
1423 		if (localFile)
1424 		{
1425 			QString destinationFolder=findDestinationFolder();
1426 			QFile dataFile(destinationFolder + licenceFileName);
1427 			if (dataFile.exists() && dataFile.open(QIODevice::ReadOnly))
1428 			{
1429 				QTextStream ts(&dataFile);
1430 				data = ts.readAll();
1431 				dataFile.close();
1432 				doDownload=false;
1433 			}
1434 		}
1435 		//If we need to download the file
1436 		if (doDownload)
1437 		{
1438 			QStringList filesToDownload;
1439 			filesToDownload<<lang;
1440 			//There's only one here... foreach?
1441 /*			int category = categoryComboBox->currentData().toInt();
1442 			switch (category)
1443 			{
1444 				case RM_HYPH:
1445 				case RM_SPELL:
1446 				case RM_PALETTES:
1447 */
1448 			for (const DownloadItem& d : qAsConst(m_availableList))
1449 			{
1450 				if (!filesToDownload.contains(d.desc))
1451 					continue;
1452 				ScQApp->dlManager()->addURL(d.url+"/"+licenceFileName, true, ScPaths::downloadDir(), ScPaths::tempFileDir());
1453 				connect(ScQApp->dlManager(), SIGNAL(finished()), this, SLOT(downloadLicenseFinished()));
1454 				connect(ScQApp->dlManager(), SIGNAL(fileReceived(const QString&)), this, SLOT(downloadLicenseFileFinished(const QString&)));
1455 				connect(ScQApp->dlManager(), SIGNAL(fileFailed(const QString&)), this, SLOT(downloadLicenseFileFailed(const QString&)));
1456 				ScQApp->dlManager()->startDownloads();
1457 			}
1458 		}
1459 	}
1460 }
1461 
1462