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 "scpaths.h"
8 #include <QApplication>
9 #include <QDebug>
10 #include <QDir>
11 #include <QProcess>
12 #include <QStandardPaths>
13 
14 #include "prefsmanager.h"
15 #include "scconfig.h"
16 #include "scribusapp.h"
17 
18 // On Qt/Mac we need CoreFoundation to discover the location
19 // of the app bundle.
20 #ifdef Q_OS_MAC
21 #include <CoreFoundation/CoreFoundation.h>
22 #endif
23 
24 #ifdef _WIN32
25 #include <windows.h>
26 #include <shlobj.h>
27 #endif
28 
29 #if defined(Q_OS_WIN32) || defined (Q_OS_OS2)
30 const char ScPaths::envPathSeparator = ';';
31 #else
32 const char ScPaths::envPathSeparator = ':';
33 #endif
34 
35 // Init the singleton's "self" address to nullptr
36 ScPaths* ScPaths::m_instance = nullptr;
37 
38 // Singleton's public constructor
instance()39 const ScPaths& ScPaths::instance()
40 {
41 	if (!ScPaths::m_instance)
42 		ScPaths::m_instance = new ScPaths();
43 	return *ScPaths::m_instance;
44 }
45 
46 // Singleton's public destructor
destroy()47 void ScPaths::destroy()
48 {
49 	delete ScPaths::m_instance;
50 }
51 
52 // Protected "real" constructor
ScPaths()53 ScPaths::ScPaths()
54 {
55 // On *nix, all paths are initialized to compile-time defaults passed in
56 // as preprocessor macros and set by autoconf.
57 #if !defined(Q_OS_MAC) && !defined(_WIN32) && defined(WANT_RELOCATABLE)
58 	QString appPath = qApp->applicationDirPath();
59 	m_docDir = appPath + "/../" + QString(DOCDIR);
60 	m_iconDir = appPath + "/../" + QString(ICONDIR);
61 	m_libDir = appPath + "/../" + QString(LIBDIR);
62 	m_pluginDir = appPath + "/../" + QString(PLUGINDIR);
63 	m_qmlDir = appPath + "/../" + QString(QMLDIR);
64 	m_sampleScriptDir = appPath + "/../" + QString(SAMPLESDIR);
65 	m_scriptDir = appPath + "/../" + QString(SCRIPTSDIR);
66 	m_shareDir = appPath + "/../" + QString(SHAREDIR);
67 	m_templateDir = appPath + "/../" + QString(TEMPLATEDIR);
68 #elif !defined(Q_OS_MAC) && !defined(_WIN32)
69 	m_docDir = QString(DOCDIR);
70 	m_iconDir = QString(ICONDIR);
71 	m_libDir = QString(LIBDIR);
72 	m_pluginDir = QString(PLUGINDIR);
73 	m_qmlDir = QString(QMLDIR);
74 	m_sampleScriptDir = QString(SAMPLESDIR);
75 	m_scriptDir = QString(SCRIPTSDIR);
76 	m_shareDir = QString(SHAREDIR);
77 	m_templateDir = QString(TEMPLATEDIR);
78 #endif
79 
80 // On MacOS/X, override the compile-time settings with a location
81 // obtained from the system.
82 #ifdef Q_OS_MAC
83 	QString pathPtr(bundleDir());
84 	qDebug() << QString("scpaths: bundle at %1").arg(pathPtr);
85 	m_shareDir = QString("%1/Contents/share/scribus/").arg(pathPtr);
86 	m_docDir = QString("%1/Contents/share/doc/scribus/").arg(pathPtr);
87 	m_fontDir = QString("%1/Contents/share/scribus/fonts/").arg(pathPtr);
88 	m_iconDir = QString("%1/Contents/share/scribus/icons/").arg(pathPtr);
89 	m_sampleScriptDir = QString("%1/Contents/share/scribus/samples/").arg(pathPtr);
90 	m_scriptDir = QString("%1/Contents/share/scribus/scripts/").arg(pathPtr);
91 	m_templateDir = QString("%1/Contents/share/scribus/templates/").arg(pathPtr);
92 	m_libDir = QString("%1/Contents/lib/").arg(pathPtr);
93 	m_pluginDir = QString("%1/Contents/lib/").arg(pathPtr);
94 	m_qmlDir = QString("%1/Contents/share/scribus/qml/").arg(pathPtr);
95 	//QApplication::setLibraryPaths(QStringList(QString("%1/Contents/lib/qtplugins/").arg(pathPtr)));
96 	QApplication::addLibraryPath(QString("%1/Contents/PlugIns/").arg(pathPtr));
97 	// on OSX this goes to the sys console, so user only sees it when they care -- AV
98 	qDebug() << QString("scpaths: doc dir=%1").arg(m_docDir);
99 	qDebug() << QString("scpaths: icon dir=%1").arg(m_iconDir);
100 	qDebug() << QString("scpaths: font dir=%1").arg(m_fontDir);
101 	qDebug() << QString("scpaths: sample dir=%1").arg(m_sampleScriptDir);
102 	qDebug() << QString("scpaths: script dir=%1").arg(m_scriptDir);
103 	qDebug() << QString("scpaths: template dir=%1").arg(m_templateDir);
104 	qDebug() << QString("scpaths: lib dir=%1").arg(m_libDir);
105 	qDebug() << QString("scpaths: plugin dir=%1").arg(m_pluginDir);
106 	qDebug() << QString("scpaths: QML dir=%1").arg(m_qmlDir);
107 	qDebug() << QString("scpaths: qtplugins=%1").arg(QApplication::libraryPaths().join(":"));
108 
109 #elif defined(_WIN32)
110 	QFileInfo appInfo(qApp->applicationDirPath());
111 	QString appPath = qApp->applicationDirPath();
112 	QString cleanAppPath = appInfo.canonicalFilePath();
113 	if (!cleanAppPath.isEmpty())
114 		appPath = cleanAppPath;
115 
116 	m_shareDir = QString("%1/share/").arg(appPath);
117 	m_docDir = QString("%1/share/doc/").arg(appPath);
118 	m_fontDir = QString("%1/share/fonts/").arg(appPath);
119 	m_iconDir = QString("%1/share/icons/").arg(appPath);
120 	m_sampleScriptDir = QString("%1/share/samples/").arg(appPath);
121 	m_scriptDir = QString("%1/share/scripts/").arg(appPath);
122 	m_templateDir = QString("%1/share/templates/").arg(appPath);
123 	m_libDir = QString("%1/libs/").arg(appPath);
124 	m_pluginDir = QString("%1/plugins/").arg(appPath);
125 	m_qmlDir = QString("%1/share/qml/").arg(appPath);
126 
127 	QString qtpluginDir = QString("%1/qtplugins/").arg(appPath);
128 	if (QDir(qtpluginDir).exists())
129 		QApplication::setLibraryPaths( QStringList(qtpluginDir) );
130 #endif
131 
132 // 	if (!m_shareDir.endsWith("/"))        m_shareDir += "/";
133 // 	if (!m_docDir.endsWith("/"))          m_docDir += "/";
134 // 	if (!m_fontDir.endsWith("/"))         m_fontDir += "/";
135 	if (!m_iconDir.endsWith("/"))         m_iconDir += "/";
136 // 	if (!m_sampleScriptDir.endsWith("/")) m_sampleScriptDir += "/";
137 // 	if (!m_scriptDir.endsWith("/"))       m_scriptDir += "/";
138 // 	if (!m_templateDir.endsWith("/"))     m_templateDir += "/";
139 // 	if (!m_libDir.endsWith("/"))          m_libDir += "/";
140 // 	if (!m_pluginDir.endsWith("/"))       m_pluginDir += "/";
141 }
142 
143 ScPaths::~ScPaths() = default;
144 
bundleDir() const145 QString ScPaths::bundleDir() const
146 {
147 	// On MacOS/X, override the compile-time settings with a location
148 // obtained from the system.
149 #ifdef Q_OS_MAC
150 	// Set up the various app paths to look inside the app bundle
151 	CFURLRef pluginRef = CFBundleCopyBundleURL(CFBundleGetMainBundle());
152 	CFStringRef macPath = CFURLCopyFileSystemPath(pluginRef, kCFURLPOSIXPathStyle);
153 	const char *pathPtr = CFStringGetCStringPtr(macPath, CFStringGetSystemEncoding());
154 	if (pathPtr!=nullptr && strlen(pathPtr)>0)
155 	{
156 		// make sure we get the Scribus.app directory, not some subdir
157 		// strip trailing '/':
158 		qDebug("Path = %s", pathPtr);
159 		char *p = const_cast<char*>(pathPtr + strlen(pathPtr) - 1);
160 		while (*p == '/')
161 			--p;
162 		++p;
163 		*p = '\0';
164 		if (strcmp("/bin", p-4) == 0) {
165 			p -= 4;
166 			*p = '\0';
167 		}
168 		if (strcmp("/MacOS", p-6) == 0) {
169 			p -= 6;
170 			*p = '\0';
171 		}
172 		if (strcmp("/Contents", p-9) == 0) {
173 			p -= 9;
174 			*p = '\0';
175 		}
176 		CFRelease(pluginRef);
177 		CFRelease(macPath);
178 		return QString("%1").arg(pathPtr);
179 	}
180 	char buf[2048];
181 	CFStringGetCString (macPath, buf, 2048, kCFStringEncodingUTF8);
182 	QString q_pathPtr=QString::fromUtf8(buf);
183 	if (q_pathPtr.endsWith("/bin"))
184 		q_pathPtr.chop(4);
185 	if (q_pathPtr.endsWith("/MacOS"))
186 		q_pathPtr.chop(6);
187 	if (q_pathPtr.endsWith("/Contents"))
188 		q_pathPtr.chop(9);
189 	CFRelease(pluginRef);
190 	CFRelease(macPath);
191 	return q_pathPtr;
192 #endif
193 	return QString();
194 }
195 
defaultImageEditorApp()196 QString ScPaths::defaultImageEditorApp()
197 {
198 #ifdef Q_OS_MAC
199 	QString appName("/Applications/GIMP.app");
200 	QFile app(appName);
201 	if (app.exists())
202 		return appName;
203 #endif
204 	return "gimp";
205 }
206 
docDir() const207 const QString&  ScPaths::docDir() const
208 {
209 	return m_docDir;
210 }
211 
iconDir() const212 const QString&  ScPaths::iconDir() const
213 {
214 	return m_iconDir;
215 }
216 
fontDir() const217 const QString&  ScPaths::fontDir() const
218 {
219 	return m_fontDir;
220 }
221 
libDir() const222 const QString&  ScPaths::libDir() const
223 {
224 	return m_libDir;
225 }
226 
pluginDir() const227 const QString&  ScPaths::pluginDir() const
228 {
229 	return m_pluginDir;
230 }
231 
sampleScriptDir() const232 const QString&  ScPaths::sampleScriptDir() const
233 {
234 	return m_sampleScriptDir;
235 }
236 
scriptDir() const237 const QString& ScPaths::scriptDir() const
238 {
239 	return m_scriptDir;
240 }
241 
templateDir() const242 const QString& ScPaths::templateDir() const
243 {
244 	return m_templateDir;
245 }
246 
shareDir() const247 const QString& ScPaths::shareDir() const
248 {
249 	return m_shareDir;
250 }
251 
qmlDir() const252 const QString& ScPaths::qmlDir() const
253 {
254 	return m_qmlDir;
255 }
256 
translationDir() const257 QString ScPaths::translationDir() const
258 {
259 	return (m_shareDir + "translations/");
260 }
261 
dictDir() const262 QString ScPaths::dictDir() const
263 {
264 	return(m_shareDir + "dicts/");
265 }
266 
spellDirs() const267 QStringList ScPaths::spellDirs() const
268 {
269 	QDir d;
270 	QStringList spellDirs;
271 	spellDirs.append(userDictDir(ScPaths::Spell, false));
272 	spellDirs.append(m_shareDir + "dicts/spelling/");
273 #ifdef Q_OS_MAC
274 	QString macPortsPath("/opt/local/share/hunspell/");
275 	QString finkPath("/sw/share/hunspell/");
276 	QString osxLibreOfficePath("/Applications/LibreOffice.app/Contents/Resources/extensions");
277 	QString osxUserLibreOfficePath(QDir::homePath()+"/Applications/LibreOffice.app/Contents/Resources/extensions");
278 	d.setPath(macPortsPath);
279 	if (d.exists())
280 		spellDirs.append(macPortsPath);
281 	d.setPath(finkPath);
282 	if (d.exists())
283 		spellDirs.append(finkPath);
284 	d.setPath(osxLibreOfficePath);
285 	if (d.exists())
286 	{
287 		QStringList dictDirFilters("dict-*");
288 		const QStringList dictDirList(d.entryList(dictDirFilters, QDir::Dirs, QDir::Name));
289 		for (const QString& dir : dictDirList)
290 			spellDirs.append(osxLibreOfficePath + "/" + dir + "/");
291 	}
292 	d.setPath(osxUserLibreOfficePath);
293 	if (d.exists())
294 	{
295 		QStringList dictDirFilters("dict-*");
296 		const QStringList dictDirList(d.entryList(dictDirFilters, QDir::Dirs, QDir::Name));
297 		for (const QString& dir : dictDirList)
298 			spellDirs.append(osxUserLibreOfficePath + "/" + dir + "/");
299 	}
300 
301 #elif defined(_WIN32)
302 	QString windowsLOPath("LibreOffice 3.5/share/extensions");
303 	QString progFiles = windowsSpecialDir(CSIDL_PROGRAM_FILES);
304 	d.setPath(progFiles+windowsLOPath);
305 	if (d.exists())
306 	{
307 		QStringList dictDirFilters("dict-*");
308 		const QStringList dictDirList(d.entryList(dictDirFilters, QDir::Dirs, QDir::Name));
309 		for (const QString& dir : dictDirList)
310 			spellDirs.append(progFiles+windowsLOPath + "/" + dir + "/");
311 	}
312 #elif defined(Q_OS_LINUX)
313 	QString linuxLocalPath("/usr/local/share/hunspell/");
314 	QString linuxHunspellPath("/usr/share/hunspell/");
315 	QString linuxMyspellPath("/usr/share/myspell/");
316 	d.setPath(linuxHunspellPath);
317 	if (d.exists())
318 		spellDirs.append(linuxHunspellPath);
319 	d.setPath(linuxMyspellPath);
320 	if (d.exists())
321 		spellDirs.append(linuxMyspellPath);
322 	d.setPath(linuxLocalPath);
323 	if (d.exists())
324 		spellDirs.append(linuxLocalPath);
325 #endif
326 	return spellDirs;
327 }
328 
hyphDirs() const329 QStringList ScPaths::hyphDirs() const
330 {
331 	QDir d;
332 	QStringList hyphDirs;
333 	hyphDirs.append(userDictDir(ScPaths::Hyph, false));
334 	hyphDirs.append(m_shareDir + "dicts/hyph/");
335 #ifdef Q_OS_MAC
336 	QString macPortsPath("/opt/local/share/hunspell/");
337 	QString finkPath("/sw/share/hunspell/");
338 	QString osxLibreOfficePath("/Applications/LibreOffice.app/Contents/Resources/extensions");
339 	QString osxUserLibreOfficePath(QDir::homePath()+"/Applications/LibreOffice.app/Contents/Resources/extensions");
340 	d.setPath(macPortsPath);
341 	if (d.exists())
342 		hyphDirs.append(macPortsPath);
343 	d.setPath(finkPath);
344 	if (d.exists())
345 		hyphDirs.append(finkPath);
346 	d.setPath(osxLibreOfficePath);
347 	if (d.exists())
348 	{
349 		QStringList dictDirFilters("dict-*");
350 		const QStringList dictDirList(d.entryList(dictDirFilters, QDir::Dirs, QDir::Name));
351 		for (const QString& dir : dictDirList)
352 			hyphDirs.append(osxLibreOfficePath + "/" + dir + "/");
353 	}
354 	d.setPath(osxUserLibreOfficePath);
355 	if (d.exists())
356 	{
357 		QStringList dictDirFilters("dict-*");
358 		const QStringList dictDirList(d.entryList(dictDirFilters, QDir::Dirs, QDir::Name));
359 		for (const QString& dir : dictDirList)
360 			hyphDirs.append(osxUserLibreOfficePath + "/" + dir + "/");
361 	}
362 
363 #elif defined(_WIN32)
364 	QString windowsLOPath("LibreOffice 3.5/share/extensions");
365 	QString progFiles = windowsSpecialDir(CSIDL_PROGRAM_FILES);
366 	d.setPath(progFiles+windowsLOPath);
367 	if (d.exists())
368 	{
369 		QStringList dictDirFilters("dict-*");
370 		const QStringList dictDirList(d.entryList(dictDirFilters, QDir::Dirs, QDir::Name));
371 		for (const QString& dir : dictDirList)
372 			hyphDirs.append(progFiles+windowsLOPath + "/" + dir + "/");
373 	}
374 #elif defined(Q_OS_LINUX)
375 	QString linuxLocalPath("/usr/local/share/hunspell/");
376 	QString linuxHunspellPath("/usr/share/hunspell/");
377 	QString linuxMyspellPath("/usr/share/myspell/");
378 	QString linuxHyphen1Path("/usr/share/hyphen/");
379 	d.setPath(linuxHyphen1Path);
380 	if (d.exists())
381 		hyphDirs.append(linuxHyphen1Path);
382 	d.setPath(linuxHunspellPath);
383 	if (d.exists())
384 		hyphDirs.append(linuxHunspellPath);
385 	d.setPath(linuxMyspellPath);
386 	if (d.exists())
387 		hyphDirs.append(linuxMyspellPath);
388 	d.setPath(linuxLocalPath);
389 	if (d.exists())
390 		hyphDirs.append(linuxLocalPath);
391 #endif
392 	return hyphDirs;
393 }
394 
systemFontDirs()395 QStringList ScPaths::systemFontDirs()
396 {
397 	QStringList fontDirs;
398 #ifdef Q_OS_MAC
399 	fontDirs.append(QDir::homePath() + "/Library/Fonts/");
400 	fontDirs.append("/Library/Fonts/");
401 	fontDirs.append("/Network/Library/Fonts/");
402 	fontDirs.append("/System/Library/Fonts/");
403 #elif defined(_WIN32)
404 	QDir d;
405 	QString localFontDir = windowsSpecialDir(CSIDL_LOCAL_APPDATA)+"Microsoft/Windows/Fonts"; // Added by Windows 10 1809
406 	QString roamingFontDir = windowsSpecialDir(CSIDL_APPDATA)+"Microsoft/Windows/Fonts"; // Added by Windows 10 1809
407 	d.setPath(localFontDir);
408 	if (d.exists())
409 		fontDirs.append(localFontDir);
410 	d.setPath(roamingFontDir);
411 	if (d.exists())
412 		fontDirs.append(roamingFontDir);
413 	fontDirs.append(windowsSpecialDir(CSIDL_FONTS));
414 #endif
415 	return fontDirs;
416 }
417 
systemProfilesDirs()418 QStringList ScPaths::systemProfilesDirs()
419 {
420 	QStringList iccProfDirs;
421 #ifdef Q_OS_MAC
422 	iccProfDirs.append(QDir::homePath()+"/Library/ColorSync/Profiles/");
423 	iccProfDirs.append("/System/Library/ColorSync/Profiles/");
424 	iccProfDirs.append("/Library/ColorSync/Profiles/");
425 #elif defined(Q_OS_LINUX)
426 	iccProfDirs.append(QDir::homePath()+"/color/icc/");
427 	iccProfDirs.append(QDir::homePath()+"/.color/icc/");
428 	iccProfDirs.append(QDir::homePath()+"/.local/share/icc/");
429 	iccProfDirs.append(QDir::homePath()+"/.local/share/color/icc/");
430 	iccProfDirs.append("/usr/share/color/icc/");
431 	iccProfDirs.append("/usr/local/share/color/icc/");
432 	iccProfDirs.append("/var/lib/color/icc/");
433 #elif defined(_WIN32)
434 	// On Windows it's more complicated, profiles location depends on OS version
435 	WCHAR sysDir[MAX_PATH + 1];
436 	OSVERSIONINFO osVersion;
437 	ZeroMemory(&osVersion, sizeof(OSVERSIONINFO));
438 	osVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); // Necessary for GetVersionEx to succeed
439 	GetVersionEx(&osVersion);  // Get Windows version infos
440 	GetSystemDirectoryW(sysDir, MAX_PATH); // windowsSpecialDir(CSIDL_SYSTEM) fails on Win9x
441 	QString winSysDir = QString::fromUtf16((const ushort*) sysDir);
442 	winSysDir = winSysDir.replace('\\','/');
443 	if (osVersion.dwPlatformId == VER_PLATFORM_WIN32_NT) // Windows NT/2k/XP
444 	{
445 		if (osVersion.dwMajorVersion >= 5) // for 2k and XP dwMajorVersion == 5
446 			iccProfDirs.append(winSysDir + "/Spool/Drivers/Color/");
447 	}
448 	else if (osVersion.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) // Windows 9x/Me
449 	{
450 		if (osVersion.dwMajorVersion >= 4 && osVersion.dwMinorVersion >= 10) // Win98 or WinMe
451 			iccProfDirs.append(winSysDir + "/Color/");
452 	}
453 #endif
454 	return iccProfDirs;
455 }
456 
dirsFromEnvVar(const QString & envVar,const QString & dirToFind)457 QStringList ScPaths::dirsFromEnvVar(const QString& envVar, const QString& dirToFind)
458 {
459 	QChar sep(ScPaths::envPathSeparator);
460 	QStringList dirs;
461 #if defined(Q_OS_MAC) || defined(Q_OS_UNIX)
462 	const QStringList env(QProcess::systemEnvironment());
463 	QString path_data;
464 	for (const QString& line : env)
465 	{
466 		if (line.indexOf(envVar) == 0)
467 			path_data = line.mid(envVar.length()+1); //eg, Strip "XDG_DATA_DIRS="
468 	}
469 	const QStringList splitpath_data(path_data.split(sep, Qt::SkipEmptyParts));
470 	for (const QString &dir : splitpath_data)
471 	{
472 		QFileInfo info(dir+dirToFind);
473 		if (info.exists())
474 			dirs.append(dir+dirToFind);
475 	}
476 #endif
477 	return dirs;
478 }
479 
480 
481 
systemCreatePalettesDirs()482 QStringList ScPaths::systemCreatePalettesDirs()
483 {
484 	QStringList createDirs;
485 #ifdef Q_OS_MAC
486 	createDirs.append(QDir::homePath()+"/create/swatches/");
487 	createDirs.append(QDir::homePath()+"/.create/swatches/");
488 #elif defined(Q_OS_LINUX)
489 	createDirs.append(QDir::homePath()+"/create/swatches/");
490 	createDirs.append(QDir::homePath()+"/.create/swatches/");
491 	createDirs.append("/usr/share/create/swatches/");
492 	createDirs.append("/usr/local/share/create/swatches/");
493 #elif defined(_WIN32)
494 	QString localAppData = windowsSpecialDir(CSIDL_LOCAL_APPDATA);
495 	QString commonAppData = windowsSpecialDir(CSIDL_COMMON_APPDATA);
496 	QString programFilesCommon = windowsSpecialDir(CSIDL_PROGRAM_FILES_COMMON);
497 	createDirs.append(windowsSpecialDir(CSIDL_APPDATA) + "create/swatches/");
498 	if (!localAppData.isEmpty())
499 		createDirs.append(localAppData + "create/swatches/");
500 	if (!commonAppData.isEmpty())
501 		createDirs.append(commonAppData + "create/swatches/");
502 	if (!programFilesCommon.isEmpty())
503 		createDirs.append(programFilesCommon + "create/swatches/");
504 #endif
505 	return createDirs;
506 }
507 
oldApplicationDataDir()508 QString ScPaths::oldApplicationDataDir()
509 {
510 #ifdef Q_OS_WIN32
511 	QString appData = windowsSpecialDir(CSIDL_APPDATA);
512 	if (QDir(appData).exists())
513 #ifdef APPLICATION_DATA_DIR
514 	return (appData + "/" + APPLICATION_DATA_DIR + "/");
515 #else
516 	return (appData + "/Scribus/");
517 #endif
518 #endif
519 
520 #ifdef APPLICATION_DATA_DIR
521 	return QDir::homePath() + "/" + APPLICATION_DATA_DIR + "/";
522 #else
523 	#ifdef Q_OS_MAC
524 		return (QDir::homePath() + "/Library/Preferences/Scribus/");
525 	#else
526 		return (QDir::homePath() + "/.scribus/");
527 	#endif
528 #endif
529 }
530 
applicationDataDir(bool createIfNotExists)531 QString ScPaths::applicationDataDir(bool createIfNotExists)
532 {
533 	QString dataDir;
534 #ifdef APPLICATION_DATA_DIR
535 	dataDir =  QDir::homePath() + "/" + APPLICATION_DATA_DIR + "/";
536 #else
537 	dataDir =  QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/";
538 #endif
539 	QDir prefsDirectory(dataDir);
540 	if (createIfNotExists && !prefsDirectory.exists())
541 		prefsDirectory.mkpath(prefsDirectory.absolutePath());
542 	return dataDir;
543 }
544 
preferencesDir(bool createIfNotExists)545 QString ScPaths::preferencesDir(bool createIfNotExists)
546 {
547 	//If we have been passed a dir on cmd line, use this. Start up errors if it does not exist.
548 	if (!ScQApp->userPrefsDir().isEmpty())
549 		return ScQApp->userPrefsDir();
550 	QString prefsDir;
551 #ifdef APPLICATION_CONFIG_DIR
552 	prefsDir =  QDir::homePath() + "/" + APPLICATION_CONFIG_DIR + "/";
553 #else
554 	//Jean wants to make all prefs for Scribus be in the roaming directory on Windows so return the same as applicationDataDir
555 	#ifdef Q_OS_WIN32
556 		prefsDir =  QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/";
557 	#else
558 		prefsDir =  QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/";
559 	#endif
560 #endif
561 	QDir prefsDirectory(prefsDir);
562 	if (createIfNotExists && !prefsDirectory.exists())
563 		prefsDirectory.mkpath(prefsDirectory.absolutePath());
564 	return prefsDir;
565 }
566 
imageCacheDir()567 QString ScPaths::imageCacheDir()
568 {
569 	return applicationDataDir() + "cache/img/";
570 }
571 
pluginDataDir(bool createIfNotExists)572 QString ScPaths::pluginDataDir(bool createIfNotExists)
573 {
574 	QDir useFilesDirectory(applicationDataDir() + "plugins/");
575 	if (createIfNotExists && !useFilesDirectory.exists())
576 		useFilesDirectory.mkpath(useFilesDirectory.absolutePath());
577 	return useFilesDirectory.absolutePath() + "/";
578 }
579 
userDictDir(ScPaths::DictType dictType,bool createIfNotExists)580 QString ScPaths::userDictDir(ScPaths::DictType dictType, bool createIfNotExists)
581 {
582 	QString dictSuffix;
583 	if (dictType == ScPaths::Hyph)
584 		dictSuffix = "hyph/";
585 	if (dictType == ScPaths::Spell)
586 		dictSuffix = "spell/";
587 	QDir useFilesDirectory(applicationDataDir() + "dicts/" + dictSuffix);
588 	if (createIfNotExists && !useFilesDirectory.exists())
589 		useFilesDirectory.mkpath(useFilesDirectory.absolutePath());
590 	return useFilesDirectory.absolutePath() + "/";
591 }
592 
userFontDir(bool createIfNotExists)593 QString ScPaths::userFontDir(bool createIfNotExists)
594 {
595 	QDir useFilesDirectory(applicationDataDir() + "fonts/");
596 	if (createIfNotExists && !useFilesDirectory.exists())
597 		useFilesDirectory.mkpath(useFilesDirectory.absolutePath());
598 	return useFilesDirectory.absolutePath() + "/";
599 }
600 
userHelpFilesDir(bool createIfNotExists)601 QString ScPaths::userHelpFilesDir(bool createIfNotExists)
602 {
603 	QDir useFilesDirectory(applicationDataDir() + "helpfiles/");
604 	if (createIfNotExists && !useFilesDirectory.exists())
605 		useFilesDirectory.mkpath(useFilesDirectory.absolutePath());
606 	return useFilesDirectory.absolutePath() + "/";
607 }
608 
userPaletteFilesDir(bool createIfNotExists)609 QString ScPaths::userPaletteFilesDir(bool createIfNotExists)
610 {
611 	QDir useFilesDirectory(applicationDataDir() + "palettes/");
612 	if (createIfNotExists && !useFilesDirectory.exists())
613 	{
614 		useFilesDirectory.mkpath(useFilesDirectory.absolutePath());
615 		useFilesDirectory.mkpath(useFilesDirectory.absolutePath() + "/locked");
616 	}
617 	return useFilesDirectory.absolutePath() + "/";
618 }
619 
userTemplateDir(bool createIfNotExists)620 QString ScPaths::userTemplateDir(bool createIfNotExists)
621 {
622 	if (PrefsManager::instance().appPrefs.pathPrefs.documentTemplates.isEmpty())
623 		return QString();
624 	QDir useFilesDirectory(PrefsManager::instance().appPrefs.pathPrefs.documentTemplates);
625 	if (createIfNotExists && !useFilesDirectory.exists())
626 		useFilesDirectory.mkpath(useFilesDirectory.absolutePath());
627 	return useFilesDirectory.absolutePath() + "/";
628 }
629 
userDocumentDir()630 QString ScPaths::userDocumentDir()
631 {
632 	QString userDocs = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
633 	if (QDir(userDocs).exists())
634 		return userDocs + "/";
635 	return QStandardPaths::writableLocation(QStandardPaths::HomeLocation) + "/";
636 }
637 
scrapbookDir(bool createIfNotExists)638 QString ScPaths::scrapbookDir(bool createIfNotExists)
639 {
640 	QDir useFilesDirectory(applicationDataDir() + "scrapbook/");
641 	if (createIfNotExists)
642 	{
643 		if (!useFilesDirectory.exists())
644 			useFilesDirectory.mkpath(useFilesDirectory.absolutePath());
645 		if (!useFilesDirectory.exists("main"))
646 			useFilesDirectory.mkpath(useFilesDirectory.absolutePath() + "/main");
647 		if (!useFilesDirectory.exists("tmp"))
648 			useFilesDirectory.mkpath(useFilesDirectory.absolutePath() + "/tmp");
649 	}
650 	return useFilesDirectory.absolutePath() + "/";
651 }
652 
tempFileDir()653 QString ScPaths::tempFileDir()
654 {
655 #ifdef Q_OS_WIN32
656 	QString tempPath;
657 	WCHAR wTempPath[1024];
658 	DWORD result = GetTempPathW(1024, wTempPath);
659 	if (result)
660 	{
661 		tempPath = QString::fromUtf16((const unsigned short*) wTempPath);
662 		tempPath.replace('\\', '/');
663 		tempPath += "/";
664 		// GetTempPath may return Windows directory, better not use this one
665 		// for temporary files
666 		if (QDir(tempPath).exists() && tempPath != windowsSpecialDir(CSIDL_WINDOWS))
667 			return tempPath;
668 	}
669 #endif
670 
671 	QDir tempAppDirectory(applicationDataDir() + "temp/");
672 	if (!tempAppDirectory.exists())
673 		tempAppDirectory.mkpath(tempAppDirectory.absolutePath());
674 	return tempAppDirectory.absolutePath() + "/";
675 }
676 
downloadDir()677 QString ScPaths::downloadDir()
678 {
679 	QDir downloadDirectory(applicationDataDir() + "downloads/");
680 	if (!downloadDirectory.exists())
681 		downloadDirectory.mkpath(downloadDirectory.absolutePath());
682 	return downloadDirectory.absolutePath() + "/";
683 }
684 
windowsSpecialDir(int folder)685 QString ScPaths::windowsSpecialDir(int folder)
686 {
687 	QString qstr;
688 #ifdef Q_OS_WIN32
689 	WCHAR dir[256];
690 	if (SHGetSpecialFolderPathW(nullptr, dir, folder , false))
691 	{
692 		qstr = QString::fromUtf16((const unsigned short*) dir);
693 		if (!qstr.endsWith("\\"))
694 			qstr += "\\";
695 		qstr.replace('\\', '/');
696 	}
697 #else
698 	Q_ASSERT(false);
699 #endif
700 	return qstr;
701 }
702