1
2
3 #include "tsystem.h"
4
5 using namespace std;
6
7 #include <set>
8 #include "tfilepath_io.h"
9 #include "tconvert.h"
10
11 #ifndef TNZCORE_LIGHT
12
13 #include <QDateTime>
14 #include <QStringList>
15 #include <QProcess>
16 #include <QDir>
17 #include <QFile>
18 #include <QFileInfo>
19 #include <QSettings>
20 #include <QVariant>
21 #include <QThread>
22 #include <QUrl>
23 #include <QCoreApplication>
24 #include <QUuid>
25
26 #include <QDesktopServices>
27 #include <QHostInfo>
28
29 #ifdef _WIN32
30 #include <shlobj.h>
31 #include <shellapi.h>
32 #include <winnt.h>
33 #endif
34
35 namespace {
36
toQString(const TFilePath & path)37 inline QString toQString(const TFilePath &path) {
38 return QString::fromStdWString(path.getWideString());
39 }
40
41 int HasMainLoop = -1;
42
43 } // namespace
44 //-----------------------------------------------------------------------------------
45
TFileStatus(const TFilePath & path)46 TFileStatus::TFileStatus(const TFilePath &path) {
47 m_fileInfo = QFileInfo(QString::fromStdWString(path.getWideString()));
48 m_exist = m_fileInfo.exists();
49 }
50
51 //-----------------------------------------------------------------------------------
52
getGroup() const53 QString TFileStatus::getGroup() const {
54 if (!m_exist) return QString();
55 return m_fileInfo.group();
56 }
57
58 //-----------------------------------------------------------------------------------
59
getUser() const60 QString TFileStatus::getUser() const {
61 if (!m_exist) return QString();
62 return m_fileInfo.owner();
63 }
64
65 //-----------------------------------------------------------------------------------
66
getSize() const67 TINT64 TFileStatus::getSize() const {
68 if (!m_exist) return 0;
69 return m_fileInfo.size();
70 }
71
72 //-----------------------------------------------------------------------------------
73
getLastAccessTime() const74 QDateTime TFileStatus::getLastAccessTime() const {
75 if (!m_exist) return QDateTime();
76 return m_fileInfo.lastRead();
77 }
78
79 //-----------------------------------------------------------------------------------
80
getLastModificationTime() const81 QDateTime TFileStatus::getLastModificationTime() const {
82 if (!m_exist) return QDateTime();
83 return m_fileInfo.lastModified();
84 }
85
86 //-----------------------------------------------------------------------------------
87
getCreationTime() const88 QDateTime TFileStatus::getCreationTime() const {
89 if (!m_exist) return QDateTime();
90 return m_fileInfo.created();
91 }
92
93 //-----------------------------------------------------------------------------------
94
getPermissions() const95 QFile::Permissions TFileStatus::getPermissions() const {
96 if (!m_exist) return 0;
97 return m_fileInfo.permissions();
98 }
99
100 //-----------------------------------------------------------------------------------
101
isDirectory() const102 bool TFileStatus::isDirectory() const {
103 if (!m_exist) return 0;
104 return m_fileInfo.isDir();
105 }
106
107 //-----------------------------------------------------------------------------------
108
isLink() const109 bool TFileStatus::isLink() const { return m_fileInfo.isSymLink(); }
110
111 //-----------------------------------------------------------------------------------
112
doHaveMainLoop()113 bool TSystem::doHaveMainLoop() {
114 if (HasMainLoop == -1)
115 assert(!"you MUST call the TSystem::hasMainLoop function in the main of the program!");
116 return HasMainLoop == 1;
117 }
118
119 //-----------------------------------------------------------------------------------
120
hasMainLoop(bool state)121 void TSystem::hasMainLoop(bool state) {
122 assert(HasMainLoop == -1);
123 HasMainLoop = state ? 1 : 0;
124 }
125
126 //-----------------------------------------------------------------------------------
127
getHostName()128 QString TSystem::getHostName() { return QHostInfo::localHostName(); }
129
130 //------------------------------------------------------------
131
getUserName()132 QString TSystem::getUserName() {
133 QStringList list = QProcess::systemEnvironment();
134 int j;
135 for (j = 0; j < list.size(); j++) {
136 QString value = list.at(j);
137 QString user;
138 #ifdef _WIN32
139 if (value.startsWith("USERNAME=")) user = value.right(value.size() - 9);
140 #else
141 if (value.startsWith("USER=")) user = value.right(value.size() - 5);
142 #endif
143 if (!user.isEmpty()) return user;
144 }
145 return QString("none");
146 }
147
148 //------------------------------------------------------------
149
getTempDir()150 TFilePath TSystem::getTempDir() {
151 return TFilePath(QDir::tempPath().toStdString());
152 }
153
154 //------------------------------------------------------------
155
getTestDir(string name)156 TFilePath TSystem::getTestDir(string name) {
157 return TFilePath("C:") + TFilePath(name);
158 }
159
160 //------------------------------------------------------------
161
getSystemValue(const TFilePath & name)162 QString TSystem::getSystemValue(const TFilePath &name) {
163 QStringList strlist = toQString(name).split("\\", QString::SkipEmptyParts);
164
165 assert(strlist.size() > 3);
166 assert(strlist.at(0) == "SOFTWARE");
167
168 QSettings qs(QSettings::SystemScope, strlist.at(1), strlist.at(2));
169
170 int i;
171 QString varName;
172
173 for (i = 3; i < strlist.size(); i++) {
174 varName += strlist.at(i);
175 if (i < strlist.size() - 1) varName += "//";
176 }
177
178 return qs.value(varName).toString();
179 }
180
181 //------------------------------------------------------------
182
getBinDir()183 TFilePath TSystem::getBinDir() {
184 TFilePath fp =
185 TFilePath(QCoreApplication::applicationFilePath().toStdString());
186 return fp.getParentDir();
187 }
188
189 //------------------------------------------------------------
190
getDllDir()191 TFilePath TSystem::getDllDir() { return getBinDir(); }
192 //------------------------------------------------------------
193
getUniqueFile(QString field)194 TFilePath TSystem::getUniqueFile(QString field) {
195 QString uuid = QUuid::createUuid()
196 .toString()
197 .replace("-", "")
198 .replace("{", "")
199 .replace("}", "")
200 .toLatin1()
201 .data();
202
203 QString path = QDir::tempPath() + QString("\\") + field + uuid;
204
205 return TFilePath(path.toStdString());
206 }
207
208 //------------------------------------------------------------
209
210 namespace {
getPathsToCreate(const TFilePath & path)211 TFilePathSet getPathsToCreate(const TFilePath &path) {
212 TFilePathSet pathList;
213 if (path.isEmpty()) return pathList;
214 TFilePath parentDir = path;
215 while (!TFileStatus(parentDir).doesExist()) {
216 if (parentDir == parentDir.getParentDir()) return TFilePathSet();
217 pathList.push_back(parentDir);
218 parentDir = parentDir.getParentDir();
219 }
220 return pathList;
221 }
222
setPathsPermissions(const TFilePathSet & pathSet,QFile::Permissions permissions)223 void setPathsPermissions(const TFilePathSet &pathSet,
224 QFile::Permissions permissions) {
225 TFilePathSet::const_iterator it;
226 for (it = pathSet.begin(); it != pathSet.end(); it++) {
227 QFile f(toQString(*it));
228 f.setPermissions(permissions);
229 }
230 }
231 }
232
233 // gestire exception
mkDir(const TFilePath & path)234 void TSystem::mkDir(const TFilePath &path) {
235 TFilePathSet pathSet = getPathsToCreate(path);
236 QString qPath = toQString(path);
237 assert(!qPath.contains("+"));
238 if (!QDir::current().mkpath(qPath))
239 throw TSystemException(path, "can't create folder!");
240
241 setPathsPermissions(
242 pathSet, QFile::ReadUser | QFile::WriteUser | QFile::ExeUser |
243 QFile::ReadGroup | QFile::WriteGroup | QFile::ExeGroup |
244 QFile::ReadOther | QFile::WriteOther | QFile::ExeOther);
245 }
246
247 //------------------------------------------------------------
248 // gestire exception
rmDir(const TFilePath & path)249 void TSystem::rmDir(const TFilePath &path) {
250 if (!QDir(toQString(path.getParentDir()))
251 .rmdir(QString::fromStdString(path.getName())))
252 throw TSystemException(path, "can't remove folder!");
253 }
254
255 // vinz
256
257 //------------------------------------------------------------
258
259 namespace {
rmDirTree(const QString & path)260 void rmDirTree(const QString &path) {
261 int i;
262 QFileInfoList fil = QDir(path).entryInfoList();
263 for (i = 0; i < fil.size(); i++) {
264 QFileInfo fi = fil.at(i);
265 if (fi.fileName() == QString(".") || fi.fileName() == QString(".."))
266 continue;
267 QString son = fi.absoluteFilePath();
268 if (QFileInfo(son).isDir())
269 rmDirTree(son);
270 else if (QFileInfo(son).isFile())
271 if (!QFile::remove(son))
272 throw TSystemException("can't remove file" + son.toStdString());
273 }
274 if (!QDir::current().rmdir(path))
275 throw TSystemException("can't remove path!");
276 }
277
278 } // namespace
279
280 //------------------------------------------------------------
281
rmDirTree(const TFilePath & path)282 void TSystem::rmDirTree(const TFilePath &path) { ::rmDirTree(toQString(path)); }
283
284 //------------------------------------------------------------
285
copyDir(const TFilePath & dst,const TFilePath & src)286 void TSystem::copyDir(const TFilePath &dst, const TFilePath &src) {
287 QFileInfoList fil = QDir(toQString(src)).entryInfoList();
288
289 QDir::current().mkdir(toQString(dst));
290
291 int i;
292 for (i = 0; i < fil.size(); i++) {
293 QFileInfo fi = fil.at(i);
294 if (fi.fileName() == QString(".") || fi.fileName() == QString(".."))
295 continue;
296 if (fi.isDir()) {
297 TFilePath srcDir = TFilePath(fi.filePath().toStdString());
298 TFilePath dstDir = dst + srcDir.getName();
299 copyDir(dstDir, srcDir);
300 } else {
301 TFilePath srcFi = dst + TFilePath(fi.fileName());
302 QFile::copy(fi.filePath(), toQString(srcFi));
303 }
304 }
305 }
306
307 //------------------------------------------------------------
308 /*
309 void TSystem::touchFile(const TFilePath &path)
310 {
311 QFile f(toQString(path));
312
313 if (!f.open(QIODevice::ReadWrite))
314 throw TSystemException(path, "can't touch file!");
315 else
316 f.close();
317 }
318 */
319 //------------------------------------------------------------
320 /*
321 #ifdef _WIN32
322
323 wstring getFormattedMessage(DWORD lastError)
324 {
325 LPVOID lpMsgBuf;
326 FormatMessage(
327 FORMAT_MESSAGE_ALLOCATE_BUFFER |
328 FORMAT_MESSAGE_FROM_SYSTEM |
329 FORMAT_MESSAGE_IGNORE_INSERTS,
330 NULL,
331 lastError,
332 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
333 (LPTSTR) &lpMsgBuf,
334 0,
335 NULL
336 );
337
338 int wSize = MultiByteToWideChar(0,0,(char*)lpMsgBuf,-1,0,0);
339 if(!wSize)
340 return wstring();
341
342 wchar_t* wBuffer = new wchar_t [wSize+1];
343 MultiByteToWideChar(0,0,(char*)lpMsgBuf,-1,wBuffer,wSize);
344 wBuffer[wSize]='\0';
345 wstring wmsg(wBuffer);
346
347 delete []wBuffer;
348 LocalFree(lpMsgBuf);
349 return wmsg;
350 }
351
352 //------------------------------------------------------------
353
354 #endif
355 */
356 //------------------------------------------------------------
357
copyFile(const TFilePath & dst,const TFilePath & src,bool overwrite)358 void TSystem::copyFile(const TFilePath &dst, const TFilePath &src,
359 bool overwrite) {
360 assert(dst != TFilePath());
361
362 if (dst == src) return;
363
364 // Create the containing folder before trying to copy or it will crash!
365 touchParentDir(dst);
366
367 const QString &qDst = toQString(dst);
368 if (overwrite && QFile::exists(qDst)) QFile::remove(qDst);
369
370 if (!QFile::copy(toQString(src), qDst))
371 throw TSystemException(dst, "can't copy file!");
372 }
373
374 //------------------------------------------------------------
375
renameFile(const TFilePath & dst,const TFilePath & src,bool overwrite)376 void TSystem::renameFile(const TFilePath &dst, const TFilePath &src,
377 bool overwrite) {
378 assert(dst != TFilePath());
379
380 if (dst == src) return;
381
382 const QString &qDst = toQString(dst);
383 if (overwrite && QFile::exists(qDst)) QFile::remove(qDst);
384
385 if (!QFile::rename(toQString(src), qDst))
386 throw TSystemException(dst, "can't rename file!");
387 }
388
389 //------------------------------------------------------------
390
391 // gestire gli errori con GetLastError?
deleteFile(const TFilePath & fp)392 void TSystem::deleteFile(const TFilePath &fp) {
393 if (!QFile::remove(toQString(fp)))
394 throw TSystemException(fp, "can't delete file!");
395 }
396
397 //------------------------------------------------------------
398
hideFile(const TFilePath & fp)399 void TSystem::hideFile(const TFilePath &fp) {
400 #ifdef _WIN32
401 if (!SetFileAttributesW(fp.getWideString().c_str(), FILE_ATTRIBUTE_HIDDEN))
402 throw TSystemException(fp, "can't hide file!");
403 #else // MACOSX, and others
404 TSystem::renameFile(TFilePath(fp.getParentDir() + L"." + fp.getLevelNameW()),
405 fp);
406 #endif
407 }
408
409 //------------------------------------------------------------
410
411 class CaselessFilepathLess final
412 : public std::binary_function<TFilePath, TFilePath, bool> {
413 public:
operator ()(const TFilePath & a,const TFilePath & b) const414 bool operator()(const TFilePath &a, const TFilePath &b) const {
415 // Perform case sensitive compare, fallback to case insensitive.
416 const wstring a_str = a.getWideString();
417 const wstring b_str = b.getWideString();
418
419 unsigned int i = 0;
420 int case_compare = -1;
421 while (a_str[i] || b_str[i]) {
422 if (a_str[i] != b_str[i]) {
423 const wchar_t a_wchar = towlower(a_str[i]);
424 const wchar_t b_wchar = towlower(b_str[i]);
425 if (a_wchar < b_wchar) {
426 return true;
427 } else if (a_wchar > b_wchar) {
428 return false;
429 } else if (case_compare == -1) {
430 case_compare = a_str[i] < b_str[i];
431 }
432 }
433 i++;
434 }
435 return (case_compare == 1);
436 }
437 };
438
439 //------------------------------------------------------------
440 /*! return the folder path list which is readable and executable
441 */
readDirectory_Dir_ReadExe(TFilePathSet & dst,const TFilePath & path)442 void TSystem::readDirectory_Dir_ReadExe(TFilePathSet &dst,
443 const TFilePath &path) {
444 QStringList dirItems;
445 readDirectory_DirItems(dirItems, path);
446
447 for (const QString &item : dirItems) {
448 TFilePath son = path + TFilePath(item.toStdWString());
449 dst.push_back(son);
450 }
451 }
452
453 //------------------------------------------------------------
454 // return the folder item list which is readable and executable
455 // (returns only names, not full path)
readDirectory_DirItems(QStringList & dst,const TFilePath & path)456 void TSystem::readDirectory_DirItems(QStringList &dst, const TFilePath &path) {
457 if (!TFileStatus(path).isDirectory())
458 throw TSystemException(path, " is not a directory");
459
460 QDir dir(toQString(path));
461
462 #ifdef _WIN32
463 // equivalent to sorting with QDir::LocaleAware
464 auto const strCompare = [](const QString &s1, const QString &s2) {
465 return QString::localeAwareCompare(s1, s2) < 0;
466 };
467
468 std::set<QString, decltype(strCompare)> entries(strCompare);
469
470 WIN32_FIND_DATA find_dir_data;
471 QString dir_search_path = dir.absolutePath() + "\\*";
472 auto addEntry = [&]() {
473 // QDir::NoDotAndDotDot condition
474 if (wcscmp(find_dir_data.cFileName, L".") != 0 &&
475 wcscmp(find_dir_data.cFileName, L"..") != 0) {
476 // QDir::AllDirs condition
477 if (find_dir_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY &&
478 (find_dir_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == 0) {
479 entries.insert(QString::fromWCharArray(find_dir_data.cFileName));
480 }
481 }
482 };
483 HANDLE hFind =
484 FindFirstFile((const wchar_t *)dir_search_path.utf16(), &find_dir_data);
485 if (hFind != INVALID_HANDLE_VALUE) {
486 addEntry();
487 while (FindNextFile(hFind, &find_dir_data)) addEntry();
488 }
489 for (const QString &name : entries) dst.push_back(QString(name));
490
491 #else
492 dst = dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Readable,
493 QDir::Name | QDir::LocaleAware);
494 #endif
495 }
496
497 //------------------------------------------------------------
498 /*! to retrieve the both lists with groupFrames option = on and off.
499 */
readDirectory(TFilePathSet & groupFpSet,TFilePathSet & allFpSet,const TFilePath & path)500 void TSystem::readDirectory(TFilePathSet &groupFpSet, TFilePathSet &allFpSet,
501 const TFilePath &path) {
502 if (!TFileStatus(path).isDirectory())
503 throw TSystemException(path, " is not a directory");
504
505 std::set<TFilePath, CaselessFilepathLess> fileSet_group;
506 std::set<TFilePath, CaselessFilepathLess> fileSet_all;
507
508 QStringList fil;
509 #ifdef _WIN32
510 WIN32_FIND_DATA find_dir_data;
511 QString dir_search_path = QDir(toQString(path)).absolutePath() + "\\*";
512 auto addEntry = [&]() {
513 // QDir::NoDotAndDotDot condition
514 if (wcscmp(find_dir_data.cFileName, L".") != 0 &&
515 wcscmp(find_dir_data.cFileName, L"..") != 0) {
516 // QDir::Files condition
517 if ((find_dir_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 &&
518 (find_dir_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) == 0) {
519 fil.append(QString::fromWCharArray(find_dir_data.cFileName));
520 }
521 }
522 };
523 HANDLE hFind =
524 FindFirstFile((const wchar_t *)dir_search_path.utf16(), &find_dir_data);
525 if (hFind != INVALID_HANDLE_VALUE) {
526 addEntry();
527 while (FindNextFile(hFind, &find_dir_data)) addEntry();
528 }
529 #else
530 fil = QDir(toQString(path))
531 .entryList(QDir::Files | QDir::NoDotAndDotDot | QDir::Readable);
532 #endif
533 if (fil.size() == 0) return;
534
535 for (int i = 0; i < fil.size(); i++) {
536 QString fi = fil.at(i);
537
538 TFilePath son = path + TFilePath(fi.toStdWString());
539
540 // store all file paths
541 fileSet_all.insert(son);
542
543 // in case of the sequencial files
544 if (son.getDots() == "..") son = son.withFrame();
545
546 // store the group. insersion avoids duplication of the item
547 fileSet_group.insert(son);
548 }
549
550 groupFpSet.insert(groupFpSet.end(), fileSet_group.begin(),
551 fileSet_group.end());
552 allFpSet.insert(allFpSet.end(), fileSet_all.begin(), fileSet_all.end());
553 }
554
555 //------------------------------------------------------------
556
readDirectory(TFilePathSet & dst,const QDir & dir,bool groupFrames)557 void TSystem::readDirectory(TFilePathSet &dst, const QDir &dir,
558 bool groupFrames) {
559 if (!(dir.exists() && QFileInfo(dir.path()).isDir()))
560 throw TSystemException(TFilePath(dir.path().toStdWString()),
561 " is not a directory");
562 QStringList entries;
563 #ifdef _WIN32
564 WIN32_FIND_DATA find_dir_data;
565 QString dir_search_path = dir.absolutePath() + "\\*";
566 QDir::Filters filter = dir.filter();
567
568 // store name filters
569 bool hasNameFilter = false;
570 QList<QRegExp> nameFilters;
571 for (const QString &nameFilter : dir.nameFilters()) {
572 if (nameFilter == "*") {
573 hasNameFilter = false;
574 break;
575 }
576 QRegExp regExp(nameFilter);
577 regExp.setPatternSyntax(QRegExp::Wildcard);
578 nameFilters.append(regExp);
579 hasNameFilter = true;
580 }
581
582 auto addEntry = [&]() {
583 // QDir::NoDotAndDotDot condition
584 if (wcscmp(find_dir_data.cFileName, L".") != 0 &&
585 wcscmp(find_dir_data.cFileName, L"..") != 0) {
586 // QDir::Files condition
587 if ((filter & QDir::Files) == 0 &&
588 (find_dir_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
589 return;
590 // QDir::Dirs condition
591 if ((filter & QDir::Dirs) == 0 &&
592 (find_dir_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
593 return;
594 // QDir::Hidden condition
595 if ((filter & QDir::Hidden) == 0 &&
596 (find_dir_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
597 return;
598
599 QString fileName = QString::fromWCharArray(find_dir_data.cFileName);
600
601 // name filter
602 if (hasNameFilter) {
603 bool matched = false;
604 for (const QRegExp ®Exp : nameFilters) {
605 if (regExp.exactMatch(fileName)) {
606 matched = true;
607 break;
608 }
609 }
610 if (!matched) return;
611 }
612
613 entries.append(fileName);
614 }
615 };
616 HANDLE hFind =
617 FindFirstFile((const wchar_t *)dir_search_path.utf16(), &find_dir_data);
618 if (hFind != INVALID_HANDLE_VALUE) {
619 addEntry();
620 while (FindNextFile(hFind, &find_dir_data)) addEntry();
621 }
622 #else
623 entries = (dir.entryList(dir.filter() | QDir::NoDotAndDotDot));
624 #endif
625
626 TFilePath dirPath(dir.path().toStdWString());
627
628 std::set<TFilePath, CaselessFilepathLess> fpSet;
629
630 int e, eCount = entries.size();
631 for (e = 0; e != eCount; ++e) {
632 TFilePath path(dirPath + TFilePath(entries.at(e).toStdWString()));
633
634 if (groupFrames && path.getDots() == "..") path = path.withFrame();
635
636 fpSet.insert(path);
637 }
638
639 dst.insert(dst.end(), fpSet.begin(), fpSet.end());
640 }
641
642 //------------------------------------------------------------
643
readDirectory(TFilePathSet & dst,const TFilePath & path,bool groupFrames,bool onlyFiles,bool getHiddenFiles)644 void TSystem::readDirectory(TFilePathSet &dst, const TFilePath &path,
645 bool groupFrames, bool onlyFiles,
646 bool getHiddenFiles) {
647 QDir dir(toQString(path));
648
649 QDir::Filters filters(QDir::Files);
650 if (!onlyFiles) filters |= QDir::Dirs;
651 if (getHiddenFiles) filters |= QDir::Hidden;
652 dir.setFilter(filters);
653
654 readDirectory(dst, dir, groupFrames);
655 }
656
657 //------------------------------------------------------------
658
readDirectory(TFilePathSet & dst,const TFilePathSet & pathSet,bool groupFrames,bool onlyFiles,bool getHiddenFiles)659 void TSystem::readDirectory(TFilePathSet &dst, const TFilePathSet &pathSet,
660 bool groupFrames, bool onlyFiles,
661 bool getHiddenFiles) {
662 for (TFilePathSet::const_iterator it = pathSet.begin(); it != pathSet.end();
663 it++)
664 readDirectory(dst, *it, groupFrames, onlyFiles);
665 }
666
667 //------------------------------------------------------------
668
readDirectory(const TFilePath & path,bool groupFrames,bool onlyFiles,bool getHiddenFiles)669 TFilePathSet TSystem::readDirectory(const TFilePath &path, bool groupFrames,
670 bool onlyFiles, bool getHiddenFiles) {
671 TFilePathSet filePathSet;
672 readDirectory(filePathSet, path, groupFrames, onlyFiles, getHiddenFiles);
673 return filePathSet;
674 }
675
676 //------------------------------------------------------------
677
readDirectory(const TFilePathSet & pathSet,bool groupFrames,bool onlyFiles,bool getHiddenFiles)678 TFilePathSet TSystem::readDirectory(const TFilePathSet &pathSet,
679 bool groupFrames, bool onlyFiles,
680 bool getHiddenFiles) {
681 TFilePathSet dst;
682 readDirectory(dst, pathSet, groupFrames, onlyFiles, getHiddenFiles);
683 return dst;
684 }
685
686 //------------------------------------------------------------
687
readDirectoryTree(TFilePathSet & dst,const TFilePath & path,bool groupFrames,bool onlyFiles)688 void TSystem::readDirectoryTree(TFilePathSet &dst, const TFilePath &path,
689 bool groupFrames, bool onlyFiles) {
690 if (!TFileStatus(path).isDirectory())
691 throw TSystemException(path, " is not a directory");
692
693 QFileInfoList fil = QDir(toQString(path)).entryInfoList();
694 int i;
695 for (i = 0; i < fil.size(); i++) {
696 QFileInfo fi = fil.at(i);
697 if (fi.fileName() == QString(".") || fi.fileName() == QString(".."))
698 continue;
699 TFilePath son = TFilePath(fi.filePath().toStdWString());
700 if (TFileStatus(son).isDirectory()) {
701 if (!onlyFiles) dst.push_back(son);
702 readDirectoryTree(dst, son, groupFrames, onlyFiles);
703 } else
704 dst.push_back(son);
705 }
706 }
707
708 //------------------------------------------------------------
709
readDirectoryTree(TFilePathSet & dst,const TFilePathSet & pathSet,bool groupFrames,bool onlyFiles)710 void TSystem::readDirectoryTree(TFilePathSet &dst, const TFilePathSet &pathSet,
711 bool groupFrames, bool onlyFiles) {
712 for (TFilePathSet::const_iterator it = pathSet.begin(); it != pathSet.end();
713 it++)
714 readDirectoryTree(dst, *it, groupFrames, onlyFiles);
715 }
716
717 //------------------------------------------------------------
718
readDirectoryTree(const TFilePath & path,bool groupFrames,bool onlyFiles)719 TFilePathSet TSystem::readDirectoryTree(const TFilePath &path, bool groupFrames,
720 bool onlyFiles) {
721 TFilePathSet dst;
722 readDirectoryTree(dst, path, groupFrames, onlyFiles);
723 return dst;
724 }
725
726 //------------------------------------------------------------
727
readDirectoryTree(const TFilePathSet & pathSet,bool groupFrames,bool onlyFiles)728 TFilePathSet TSystem::readDirectoryTree(const TFilePathSet &pathSet,
729 bool groupFrames, bool onlyFiles) {
730 TFilePathSet dst;
731 readDirectoryTree(dst, pathSet, groupFrames, onlyFiles);
732 return dst;
733 }
734
735 //------------------------------------------------------------
736
packLevelNames(const TFilePathSet & fps)737 TFilePathSet TSystem::packLevelNames(const TFilePathSet &fps) {
738 std::set<TFilePath> tmpSet;
739 TFilePathSet::const_iterator cit;
740 for (cit = fps.begin(); cit != fps.end(); ++cit)
741 tmpSet.insert(cit->getParentDir() + cit->getLevelName());
742
743 TFilePathSet fps2;
744 for (std::set<TFilePath>::const_iterator c_sit = tmpSet.begin();
745 c_sit != tmpSet.end(); ++c_sit) {
746 fps2.push_back(*c_sit);
747 }
748 return fps2;
749 }
750
751 //------------------------------------------------------------
752
getDisks()753 TFilePathSet TSystem::getDisks() {
754 TFilePathSet filePathSet;
755 QFileInfoList fil = QDir::drives();
756 int i;
757 for (i = 0; i < fil.size(); i++)
758 filePathSet.push_back(TFilePath(fil.at(i).filePath().toStdWString()));
759
760 return filePathSet;
761 }
762
763 //------------------------------------------------------------
764
765 class LocalThread final : public QThread {
766 public:
currentThread()767 static LocalThread *currentThread() {
768 return (LocalThread *)QThread::currentThread();
769 }
sleep(TINT64 delay)770 void sleep(TINT64 delay) { msleep(delay); }
771 };
772
sleep(TINT64 delay)773 void TSystem::sleep(TINT64 delay) {
774 LocalThread::currentThread()->sleep(delay);
775 }
776
777 //--------------------------------------------------------------
778
getProcessorCount()779 int TSystem::getProcessorCount() { return QThread::idealThreadCount(); }
780
781 //--------------------------------------------------------------
782
doesExistFileOrLevel(const TFilePath & fp)783 bool TSystem::doesExistFileOrLevel(const TFilePath &fp) {
784 if (TFileStatus(fp).doesExist()) return true;
785
786 if (fp.isLevelName()) {
787 const TFilePath &parentDir = fp.getParentDir();
788 if (!TFileStatus(parentDir).doesExist()) return false;
789
790 TFilePathSet files;
791 try {
792 files = TSystem::readDirectory(parentDir, false, true, true);
793 } catch (...) {
794 }
795
796 TFilePathSet::iterator it, end = files.end();
797 for (it = files.begin(); it != end; ++it) {
798 if (it->getLevelNameW() == fp.getLevelNameW()) return true;
799 }
800 } else if (fp.getType() == "psd") {
801 QString name(QString::fromStdWString(fp.getWideName()));
802 name.append(QString::fromStdString(fp.getDottedType()));
803
804 int sepPos = name.indexOf("#");
805 int dotPos = name.indexOf(".", sepPos);
806 int removeChars = dotPos - sepPos;
807 int doubleUnderscorePos = name.indexOf("__", sepPos);
808 if (doubleUnderscorePos > 0) removeChars = doubleUnderscorePos - sepPos;
809
810 name.remove(sepPos, removeChars);
811
812 TFilePath psdpath(fp.getParentDir() + TFilePath(name.toStdWString()));
813 if (TFileStatus(psdpath).doesExist()) return true;
814 }
815
816 return false;
817 }
818
819 //--------------------------------------------------------------
820
copyFileOrLevel_throw(const TFilePath & dst,const TFilePath & src)821 void TSystem::copyFileOrLevel_throw(const TFilePath &dst,
822 const TFilePath &src) {
823 if (src.isLevelName()) {
824 TFilePathSet files;
825 files = TSystem::readDirectory(src.getParentDir(), false);
826
827 TFilePathSet::iterator it, end = files.end();
828 for (it = files.begin(); it != end; ++it) {
829 if (it->getLevelNameW() == src.getLevelNameW()) {
830 TFilePath src1 = *it;
831 TFilePath dst1 = dst.withFrame(it->getFrame());
832
833 TSystem::copyFile(dst1, src1);
834 }
835 }
836 } else
837 TSystem::copyFile(dst, src);
838 }
839
840 //--------------------------------------------------------------
841
renameFileOrLevel_throw(const TFilePath & dst,const TFilePath & src,bool renamePalette)842 void TSystem::renameFileOrLevel_throw(const TFilePath &dst,
843 const TFilePath &src,
844 bool renamePalette) {
845 if (renamePalette && ((src.getType() == "tlv") || (src.getType() == "tzp") ||
846 (src.getType() == "tzu"))) {
847 // Special case: since renames cannot be 'grouped' in the UI, palettes are
848 // automatically
849 // renamed here if required
850 const char *type = (src.getType() == "tlv") ? "tpl" : "plt";
851
852 TFilePath srcpltname(src.withNoFrame().withType(type));
853 TFilePath dstpltname(dst.withNoFrame().withType(type));
854
855 if (TSystem::doesExistFileOrLevel(src) &&
856 TSystem::doesExistFileOrLevel(srcpltname))
857 TSystem::renameFile(dstpltname, srcpltname, false);
858 }
859
860 if (src.isLevelName()) {
861 TFilePathSet files;
862 files = TSystem::readDirectory(src.getParentDir(), false);
863
864 for (TFilePathSet::iterator it = files.begin(); it != files.end(); it++) {
865 if (it->getLevelName() == src.getLevelName()) {
866 TFilePath src1 = *it;
867 TFilePath dst1 = dst.withFrame(it->getFrame());
868
869 TSystem::renameFile(dst1, src1);
870 }
871 }
872 } else
873 TSystem::renameFile(dst, src);
874 }
875
876 //--------------------------------------------------------------
877
removeFileOrLevel_throw(const TFilePath & fp)878 void TSystem::removeFileOrLevel_throw(const TFilePath &fp) {
879 if (fp.isLevelName()) {
880 TFilePathSet files;
881 files = TSystem::readDirectory(fp.getParentDir(), false, true, true);
882
883 TFilePathSet::iterator it, end = files.end();
884 for (it = files.begin(); it != end; ++it) {
885 if (it->getLevelName() == fp.getLevelName()) TSystem::deleteFile(*it);
886 }
887 } else
888 TSystem::deleteFile(fp);
889 }
890
891 //--------------------------------------------------------------
892
hideFileOrLevel_throw(const TFilePath & fp)893 void TSystem::hideFileOrLevel_throw(const TFilePath &fp) {
894 if (fp.isLevelName()) {
895 TFilePathSet files;
896 files = TSystem::readDirectory(fp.getParentDir(), false);
897
898 TFilePathSet::iterator it, end = files.end();
899 for (it = files.begin(); it != end; ++it) {
900 if (it->getLevelNameW() == fp.getLevelNameW()) TSystem::hideFile(*it);
901 }
902 } else
903 TSystem::hideFile(fp);
904 }
905
906 //--------------------------------------------------------------
907
moveFileOrLevelToRecycleBin_throw(const TFilePath & fp)908 void TSystem::moveFileOrLevelToRecycleBin_throw(const TFilePath &fp) {
909 if (fp.isLevelName()) {
910 TFilePathSet files;
911 files = TSystem::readDirectory(fp.getParentDir(), false, true, true);
912
913 TFilePathSet::iterator it, end = files.end();
914 for (it = files.begin(); it != end; ++it) {
915 if (it->getLevelNameW() == fp.getLevelNameW())
916 TSystem::moveFileToRecycleBin(*it);
917 }
918 } else
919 TSystem::moveFileToRecycleBin(fp);
920 }
921
922 //--------------------------------------------------------------
923
copyFileOrLevel(const TFilePath & dst,const TFilePath & src)924 bool TSystem::copyFileOrLevel(const TFilePath &dst, const TFilePath &src) {
925 try {
926 copyFileOrLevel_throw(dst, src);
927 } catch (...) {
928 return false;
929 }
930 return true;
931 }
932
933 //--------------------------------------------------------------
934
renameFileOrLevel(const TFilePath & dst,const TFilePath & src,bool renamePalette)935 bool TSystem::renameFileOrLevel(const TFilePath &dst, const TFilePath &src,
936 bool renamePalette) {
937 try {
938 renameFileOrLevel_throw(dst, src, renamePalette);
939 } catch (...) {
940 return false;
941 }
942 return true;
943 }
944
945 //--------------------------------------------------------------
946
removeFileOrLevel(const TFilePath & fp)947 bool TSystem::removeFileOrLevel(const TFilePath &fp) {
948 try {
949 removeFileOrLevel_throw(fp);
950 } catch (...) {
951 return false;
952 }
953 return true;
954 }
955
956 //--------------------------------------------------------------
957
hideFileOrLevel(const TFilePath & fp)958 bool TSystem::hideFileOrLevel(const TFilePath &fp) {
959 try {
960 hideFileOrLevel_throw(fp);
961 } catch (...) {
962 return false;
963 }
964 return true;
965 }
966
967 //--------------------------------------------------------------
968
moveFileOrLevelToRecycleBin(const TFilePath & fp)969 bool TSystem::moveFileOrLevelToRecycleBin(const TFilePath &fp) {
970 try {
971 moveFileOrLevelToRecycleBin_throw(fp);
972 } catch (...) {
973 return false;
974 }
975 return true;
976 }
977
978 //--------------------------------------------------------------
979
touchParentDir(const TFilePath & fp)980 bool TSystem::touchParentDir(const TFilePath &fp) {
981 TFilePath parentDir = fp.getParentDir();
982 TFileStatus fs(parentDir);
983 if (fs.isDirectory())
984 return true;
985 else if (fs.doesExist())
986 return false;
987 try {
988 mkDir(parentDir);
989 } catch (...) {
990 return false;
991 }
992 return true;
993 }
994
995 //--------------------------------------------------------------
996
showDocument(const TFilePath & path)997 bool TSystem::showDocument(const TFilePath &path) {
998 #ifdef _WIN32
999 int ret = (int)ShellExecuteW(0, L"open", path.getWideString().c_str(), 0, 0,
1000 SW_SHOWNORMAL);
1001 if (ret <= 32) {
1002 return false;
1003 throw TSystemException(path, "Can't open");
1004 }
1005 return true;
1006 #else
1007 string cmd = "open ";
1008 string thePath(::to_string(path));
1009 UINT pos = 0, count = 0;
1010 // string newPath;
1011 char newPath[2048];
1012
1013 while (pos < thePath.size()) {
1014 char c = thePath[pos];
1015 if (c == ' ') newPath[count++] = '\\';
1016
1017 newPath[count++] = c;
1018 ++pos;
1019 }
1020 newPath[count] = 0;
1021
1022 cmd = cmd + string(newPath);
1023 system(cmd.c_str());
1024 return true;
1025 #endif
1026 }
1027
1028 #else
1029
1030 #include <windows.h>
1031
sleep(TINT64 delay)1032 void TSystem::sleep(TINT64 delay) { Sleep((DWORD)delay); }
1033
1034 // gestire gli errori con GetLastError?
deleteFile(const TFilePath & fp)1035 void TSystem::deleteFile(const TFilePath &fp) { assert(false); }
1036
rmDirTree(const TFilePath & path)1037 void TSystem::rmDirTree(const TFilePath &path) { assert(false); }
1038
1039 //------------------------------------------------------------
1040
1041 //------------------------------------------------------------
1042
1043 #endif // TNZCORE_LIGHT
1044
1045 //--------------------------------------------------------------
1046
TSystemException(const TFilePath & fname,int err)1047 TSystemException::TSystemException(const TFilePath &fname, int err)
1048 : m_fname(fname)
1049 , m_err(err)
1050 , m_msg(L"")
1051
1052 {}
1053
1054 //--------------------------------------------------------------
1055
TSystemException(const TFilePath & fname,const std::string & msg)1056 TSystemException::TSystemException(const TFilePath &fname,
1057 const std::string &msg)
1058 : m_fname(fname), m_err(-1), m_msg(::to_wstring(msg)) {}
1059 //--------------------------------------------------------------
1060
TSystemException(const TFilePath & fname,const wstring & msg)1061 TSystemException::TSystemException(const TFilePath &fname, const wstring &msg)
1062 : m_fname(fname), m_err(-1), m_msg(msg) {}
1063
1064 //--------------------------------------------------------------
1065
TSystemException(const std::string & msg)1066 TSystemException::TSystemException(const std::string &msg)
1067 : m_fname(""), m_err(-1), m_msg(::to_wstring(msg)) {}
1068 //--------------------------------------------------------------
1069
TSystemException(const wstring & msg)1070 TSystemException::TSystemException(const wstring &msg)
1071 : m_fname(""), m_err(-1), m_msg(msg) {}
1072