Rabbit Remote Control 0.1.0-bate14
Loading...
Searching...
No Matches
main.cpp
1// Author: Kang Lin <kl222@126.com>
2
15
16#include <QSplashScreen>
17#include <QtGlobal>
18#include <QLoggingCategory>
19#include <QApplication>
20#include <QSettings>
21#include <QDebug>
22#include <QtGlobal>
23#include <QSharedPointer>
24#include <QException>
25#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
26 #include <QRegularExpression>
27#endif
28#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
29 #include <QRandomGenerator>
30#endif
31#if defined(Q_OS_ANDROID) && ((QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && (QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)))
32 #include <QtAndroid>
33#endif
34
35#include "RabbitCommonTools.h"
36
37#ifdef HAVE_UPDATE
38#include "FrmUpdater.h"
39#endif
40#ifdef BUILD_QUIWidget
41 #include "QUIWidget/QUIWidget.h"
42#endif
43
44#include "StatsAppUsage.h"
45#include "mainwindow.h"
46
47static Q_LOGGING_CATEGORY(log, "App")
48
49// Android平台的专用初始化函数(必须在QGuiApplication之前)
50void InitAndroidVirtualKeyboard()
51{
52 // 设置输入法模块(必须在QGuiApplication之前)
53 qputenv("QT_IM_MODULE", "qtvirtualkeyboard");
54
55 // Android特定环境变量
56 //qputenv("QT_VIRTUALKEYBOARD_ANDROID_HEIGHT", "400"); // 设置键盘高度
57 // 设置键盘样式
58 //qputenv("QT_VIRTUALKEYBOARD_STYLE", QByteArray("default")); // 可选: default, retro, etc.
59
60 // 设置布局(可选中文)
61 //qputenv("QT_VIRTUALKEYBOARD_LAYOUT", "en_US");
62 // qputenv("QT_VIRTUALKEYBOARD_LAYOUT", "zh_CN");
63
64 // 禁用硬件键盘检测(强制显示虚拟键盘)
65 //qputenv("QT_VIRTUALKEYBOARD_FORCE_ANDROID", "1");
66
67 // 设置手写识别(如果需要)
68 //qputenv("QT_VIRTUALKEYBOARD_HANDWRITING", QByteArray("1"));
69
70 // 启用调试
71 //qputenv("QT_DEBUG_IM", "1");
72}
73
74int main(int argc, char *argv[])
75{
76 int nRet = 0;
77
78//#if defined (_DEBUG) || !defined(BUILD_SHARED_LIBS)
79// Q_INIT_RESOURCE(translations_RabbitRemoteControlApp);
80//#endif
81
82//#if HAVE_VirtualKeyboard && defined(Q_OS_ANDROID)
83// InitAndroidVirtualKeyboard();
84//#endif
85
86 // 检查环境变量是否设置成功
87 QByteArray imModule = qgetenv("QT_IM_MODULE");
88 qDebug(log) << "QT_IM_MODULE set to:" << imModule;
89
90 QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
91
92 /* 移到 snapcraft.yaml 和 io.github.KangLin.RabbitRemoteControl.yml
93 // 修复 qtwebengine 沙箱权限问题
94 if(!qEnvironmentVariable("SNAP").isEmpty()) {
95 qputenv("QTWEBENGINE_DISABLE_SANDBOX", "1");
96 }//*/
97
98 //qputenv("QT_MEDIA_BACKEND", "ffmpeg");
99
100//*
101#if (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) \
102 && (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)))
103 // https://doc.qt.io/qt-6/zh/wayland-and-qt.html
104 // 修复使用 Qt6 时,最大化时,工具栏位置错误。
105 // 现在很多 linux 用 wayland 或 wayland-egl 作为桌面显示,这样会出现一个问题,
106 // 由于没有坐标系统,导致无边框窗体无法拖动和定位(即 QWidge::move 失效)。
107 // Qt6 开始强制默认优先用 wayland ,Qt5 默认有 xcb 则优先用 xcb),
108 // 所以需要在 main 函数最前面加一行 `qputenv("QT_QPA_PLATFORM", "xcb")`;
109
110 QString szPlatform = qEnvironmentVariable("QT_QPA_PLATFORM");
111 if(szPlatform.isEmpty()
112 || -1 != szPlatform.indexOf(QRegularExpression("wayland.*")))
113 qputenv("QT_QPA_PLATFORM", "xcb");
114 qInfo(log) << "QT_QPA_PLATFORM:" << szPlatform << "\nCurrent Qt Platform is:"
115 << qEnvironmentVariable("QT_QPA_PLATFORM")
116 << "; This can be modified with the environment variables QT_QPA_PLATFORM:\n"
117 << "export QT_QPA_PLATFORM=xcb\n Optional: xcb; vnc";
118#endif//*/
119
120#if (QT_VERSION > QT_VERSION_CHECK(5,6,0)) && (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
121 QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
122#endif
123
124 QApplication::setApplicationVersion(RabbitRemoteControl_VERSION);
125 QApplication::setApplicationName("RabbitRemoteControl");
126#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
127 QApplication::setDesktopFileName(QLatin1String("io.github.KangLin.RabbitRemoteControl.desktop"));
128#endif
129
130 QApplication app(argc, argv);
131
132 QInputMethod *inputMethod = app.inputMethod();
133 qDebug(log) << "Input method available:" << (inputMethod != nullptr);
134 if(inputMethod)
135 qDebug(log) << "Input method locale:" << inputMethod->locale();
136
137 RabbitCommon::CTools::Instance()->Init();
138
139 qInfo(log) << app.applicationName() + " " + app.applicationVersion()
140 + " " + QObject::tr("Start") + " ......"
141 << "\n" << app.arguments();
142
143 {
144#if defined(Q_OS_ANDROID)
145 //See: https://www.qt.io/blog/android-and-qt-splash-screen
146 #if QT_VERSION > QT_VERSION_CHECK(6, 2, 0)
147 QNativeInterface::QAndroidApplication::hideSplashScreen();
148 #elif QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
149 QtAndroid::hideSplashScreen();
150 #endif
151
152 QStringList permissions;
153 permissions << "android.permission.WRITE_EXTERNAL_STORAGE"
154 << "android.permission.READ_EXTERNAL_STORAGE"
155 << "android.permission.INTERNET"
156 << "android.permission.WAKE_LOCK"
157 << "android.permission.REQUEST_INSTALL_PACKAGES"
158 << "android.permission.ACCESS_NETWORK_STATE"
159 << "android.permission.BLUETOOTH"
160 << "android.permission.ACCESS_FINE_LOCATION"
161 << "android.permission.VIBRATE"
162 << "android.permission.CAMERA"
163 << "android.permission.CALL_PHONE"
164 << "android.permission.WAKE_LOCK"
165 << "android.permission.DEVICE_POWER";
166 RabbitCommon::CTools::AndroidRequestPermission(permissions);
167#endif
168
169 QSharedPointer<QTranslator> tApp =
170 RabbitCommon::CTools::Instance()->InstallTranslator("RabbitRemoteControlApp");
171
172 app.setApplicationDisplayName(QObject::tr("Rabbit Remote Control"));
173 app.setOrganizationName(QObject::tr("Kang Lin Studio"));
174
175 ShowMessageInSplashScreen(QObject::tr("Start") + " ......");
176
177#ifdef HAVE_UPDATE
178 // Check update version
179 QScopedPointer<CFrmUpdater> pUpdater(new CFrmUpdater());
180#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
181 if(qEnvironmentVariable("SNAP").isEmpty()
182 && qEnvironmentVariable("FLATPAK_ID").isEmpty())
183#else
184 if(qgetenv("SNAP").isEmpty()
185 && qgetenv("FLATPAK_ID").isEmpty())
186#endif
187 {
188 if(pUpdater) {
189 pUpdater->setAttribute(Qt::WA_DeleteOnClose, false);
190 QIcon icon(":/app");
191 if(!icon.isNull()) {
192 auto sizeList = icon.availableSizes();
193 if(!sizeList.isEmpty()) {
194 QPixmap p = icon.pixmap(*sizeList.begin());
195 pUpdater->SetTitle(p.toImage());
196 }
197 }
198
199 CFrmUpdater::ErrCode err = CFrmUpdater::ErrCode::Success;
200 try {
201 ShowMessageInSplashScreen(QObject::tr("Generate update json file ......"));
202 err = pUpdater->GenerateUpdateJson();
203 pUpdater->GenerateUpdateXml();
204 } catch(...) {
205 qCritical(log) << "Generate update fail";
206 }
207 qInfo(log) << app.applicationName() + " " + app.applicationVersion()
208 + " " + QObject::tr("Generate update json file End");
209 if(CFrmUpdater::ErrCode::Arguments == err)
210 return 0;
211
212 } else {
213 qCritical(log) << "new CFrmUpdater() fail";
214 }
215 }
216#endif // #ifdef HAVE_UPDATE
217
218 CStatsAppUsage* pStats = nullptr;
219 /*
220 QTimer::singleShot(RabbitCommon::CTools::GetRandomNumber(10, 50), [&]() {
221 pStats = new CStatsAppUsage("v" + QApplication::applicationVersion());
222 app.processEvents();
223 });//*/
224
225 ShowMessageInSplashScreen(QObject::tr("Create main window ......"));
226
227 MainWindow* w = new MainWindow();
228
229 try {
230 // For time-consuming operations
231 nRet = w->Initial();
232 if(!nRet) {
233 RC_SHOW_WINDOW(w);
234 ShowMessageInSplashScreen();
235 nRet = app.exec();
236 }
237 } catch (std::exception &e) {
238 qCritical(log) << "exception:" << e.what();
239 } catch (...) {
240 qCritical(log) << "app exec exception";
241 }
242
243 delete w;
244
245 if(pStats) {
246 pStats->Stop();
247 delete pStats;
248 }
249
250 if(tApp)
251 RabbitCommon::CTools::Instance()->RemoveTranslator(tApp);
252 }
253
254 qInfo(log) << app.applicationName() + " " + app.applicationVersion() + " " + "End";
255
256 RabbitCommon::CTools::Instance()->Clean();
257
258//#if defined (_DEBUG) || !defined(BUILD_SHARED_LIBS)
259// Q_CLEANUP_RESOURCE(translations_RabbitRemoteControlApp);
260//#endif
261
262 return nRet;
263}
应用使用统计信息
The MainWindow class.
Definition mainwindow.h:37
MainWindow(QWidget *parent=nullptr)
int Initial()
For time-consuming operations.