helper.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. * helper.cpp, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #include "StdInc.h"
  11. #include "helper.h"
  12. #include "mainwindow_moc.h"
  13. #include "settingsView/csettingsview_moc.h"
  14. #include "modManager/cmodlistview_moc.h"
  15. #include "../lib/CConfigHandler.h"
  16. #include <QObject>
  17. #include <QScroller>
  18. #ifdef VCMI_ANDROID
  19. #include <QAndroidJniObject>
  20. #include <QtAndroid>
  21. #endif
  22. #ifdef VCMI_IOS
  23. #include "ios/revealdirectoryinfiles.h"
  24. #endif
  25. #ifdef VCMI_MOBILE
  26. static QScrollerProperties generateScrollerProperties()
  27. {
  28. QScrollerProperties result;
  29. result.setScrollMetric(QScrollerProperties::OvershootDragResistanceFactor, 0.25);
  30. result.setScrollMetric(QScrollerProperties::OvershootDragDistanceFactor, 0.25);
  31. result.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QScrollerProperties::OvershootAlwaysOff);
  32. return result;
  33. }
  34. #endif
  35. namespace Helper
  36. {
  37. void loadSettings()
  38. {
  39. settings.init("config/settings.json", "vcmi:settings");
  40. persistentStorage.init("config/persistentStorage.json", "");
  41. }
  42. void reLoadSettings()
  43. {
  44. loadSettings();
  45. for(const auto widget : qApp->allWidgets())
  46. if(auto settingsView = qobject_cast<CSettingsView *>(widget))
  47. {
  48. settingsView->loadSettings();
  49. break;
  50. }
  51. getMainWindow()->updateTranslation();
  52. getMainWindow()->getModView()->reload();
  53. }
  54. void enableScrollBySwiping(QObject * scrollTarget)
  55. {
  56. #ifdef VCMI_MOBILE
  57. QScroller::grabGesture(scrollTarget, QScroller::LeftMouseButtonGesture);
  58. QScroller * scroller = QScroller::scroller(scrollTarget);
  59. scroller->setScrollerProperties(generateScrollerProperties());
  60. #endif
  61. }
  62. QString getRealPath(QString path)
  63. {
  64. #ifdef VCMI_ANDROID
  65. if(path.contains("content://", Qt::CaseInsensitive))
  66. {
  67. auto str = QAndroidJniObject::fromString(path);
  68. return QAndroidJniObject::callStaticObjectMethod("eu/vcmi/vcmi/util/FileUtil", "getFilenameFromUri", "(Ljava/lang/String;Landroid/content/Context;)Ljava/lang/String;", str.object<jstring>(), QtAndroid::androidContext().object()).toString();
  69. }
  70. else
  71. return path;
  72. #else
  73. return path;
  74. #endif
  75. }
  76. void performNativeCopy(QString src, QString dst)
  77. {
  78. #ifdef VCMI_ANDROID
  79. auto percentEncodeNonAscii = [](const QString &input) -> QString
  80. {
  81. QByteArray utf8 = input.toUtf8();
  82. QByteArray encoded;
  83. for(unsigned char c : utf8)
  84. {
  85. // If ASCII (0x00 to 0x7F), keep as is
  86. if(c < 0x80)
  87. encoded.append(c);
  88. else
  89. {
  90. // Non-ASCII: encode as %HH
  91. encoded.append('%');
  92. encoded.append(QByteArray::number(static_cast<uint>(c), 16).toUpper().rightJustified(2, '0'));
  93. }
  94. }
  95. return QString::fromUtf8(encoded);
  96. };
  97. // %-encode unencoded parts of string.
  98. // This is needed because QT returns a mixed content url with %-encoded and unencoded parts. If Android > 13 this causes problems reading this files. E.g. when using spaces and unicode characters in folder or filename.
  99. // Related, but seems not completly fixed (at least in our setup): https://bugreports.qt.io/browse/QTBUG-114435
  100. auto safeEncode = [&](QString uri) -> QString
  101. {
  102. if(!uri.startsWith("content://", Qt::CaseInsensitive))
  103. return uri;
  104. uri.replace(" ", "%20");
  105. return percentEncodeNonAscii(uri);
  106. };
  107. auto srcStr = QAndroidJniObject::fromString(safeEncode(src));
  108. auto dstStr = QAndroidJniObject::fromString(safeEncode(dst));
  109. QAndroidJniObject::callStaticObjectMethod("eu/vcmi/vcmi/util/FileUtil", "copyFileFromUri", "(Ljava/lang/String;Ljava/lang/String;Landroid/content/Context;)V", srcStr.object<jstring>(), dstStr.object<jstring>(), QtAndroid::androidContext().object());
  110. #else
  111. QFile::copy(src, dst);
  112. #endif
  113. }
  114. void revealDirectoryInFileBrowser(QString path)
  115. {
  116. const auto dirUrl = QUrl::fromLocalFile(QFileInfo{path}.absoluteFilePath());
  117. #ifdef VCMI_IOS
  118. iOS_utils::revealDirectoryInFiles(dirUrl);
  119. #else
  120. QDesktopServices::openUrl(dirUrl);
  121. #endif
  122. }
  123. MainWindow * getMainWindow()
  124. {
  125. foreach(QWidget *w, qApp->allWidgets())
  126. if(auto mainWin = qobject_cast<MainWindow*>(w))
  127. return mainWin;
  128. return nullptr;
  129. }
  130. }