62 if (!QFileInfo(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)).exists()) {
63 QDir().mkpath(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation));
65 d->logFile.setFileName(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) +
"/krita.log");
66 d->sysInfoFile.setFileName(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) +
"/krita-sysinfo.log");
68 QFileInfo fi(
d->logFile.fileName());
69 if (fi.size() > 100 * 1000 * 1000) {
70 d->logFile.open(QIODevice::WriteOnly | QIODevice::Truncate);
77 d->logFile.open(QFile::Append | QFile::Text);
78 d->sysInfoFile.open(QFile::WriteOnly | QFile::Text);
103 systemInfo.append(
"Krita\n");
108 QString packageFamilyName;
109 QString packageFullName;
110 systemInfo.append(
"\n Installation type: ");
111 if (tryGetCurrentPackageFamilyName(&packageFamilyName) && tryGetCurrentPackageFullName(&packageFullName)) {
112 systemInfo.append(
"Store / MSIX package\n Family Name: ")
113 .append(packageFamilyName)
114 .append(
"\n Full Name: ")
115 .append(packageFullName);
117 systemInfo.append(
"installer / portable package");
121#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
123 systemInfo.append(
"\n Hidpi: ").append(QCoreApplication::testAttribute(Qt::AA_EnableHighDpiScaling) ?
"true" :
"false");
127 systemInfo.append(
"\n Sandbox: ").append((entitlements.
sandbox()) ?
"true" :
"false");
129 systemInfo.append(
"\n\n");
131 systemInfo.append(
"Qt\n");
132 systemInfo.append(
"\n Version (compiled): ").append(QT_VERSION_STR);
133 systemInfo.append(
"\n Version (loaded): ").append(qVersion());
134 systemInfo.append(
"\n\n");
137 systemInfo.append(
"OS Information\n");
138 systemInfo.append(
"\n Build ABI: ").append(QSysInfo::buildAbi());
139 systemInfo.append(
"\n Build CPU: ").append(QSysInfo::buildCpuArchitecture());
140 systemInfo.append(
"\n CPU: ").append(QSysInfo::currentCpuArchitecture());
141 systemInfo.append(
"\n Kernel Type: ").append(QSysInfo::kernelType());
142 systemInfo.append(
"\n Kernel Version: ").append(QSysInfo::kernelVersion());
143 systemInfo.append(
"\n Pretty Productname: ").append(QSysInfo::prettyProductName());
144 systemInfo.append(
"\n Product Type: ").append(QSysInfo::productType());
145 systemInfo.append(
"\n Product Version: ").append(QSysInfo::productVersion());
148 QString manufacturer =
149 QAndroidJniObject::getStaticObjectField(
"android/os/Build",
"MANUFACTURER",
"Ljava/lang/String;").toString();
150 const QString model =
151 QAndroidJniObject::getStaticObjectField(
"android/os/Build",
"MODEL",
"Ljava/lang/String;").toString();
152 manufacturer[0] = manufacturer[0].toUpper();
153 systemInfo.append(
"\n Product Model: ").append(manufacturer +
" " + model);
154#elif defined(Q_OS_LINUX)
155 systemInfo.append(
"\n Desktop: ").append(qgetenv(
"XDG_CURRENT_DESKTOP"));
157 systemInfo.append(
"\n Appimage build: ").append(qEnvironmentVariableIsSet(
"APPIMAGE") ?
"Yes" :
"No");
158#elif defined(Q_OS_WIN)
159 systemInfo.append(
"\n Result of IsWindows10OrGreater(): ").append(IsWindows10OrGreater() ?
"Yes" :
"No");
161 systemInfo.append(
"\n\n");
168 if (!s_instance->d->active) {
172 systemInfo.append(
"Locale\n");
173 systemInfo.append(
"\n Languages: ").append(KLocalizedString::languages().join(
", "));
174 systemInfo.append(
"\n C locale: ").append(std::setlocale(LC_ALL,
nullptr));
175 systemInfo.append(
"\n QLocale current: ").append(QLocale().bcp47Name());
176 systemInfo.append(
"\n QLocale system: ").append(QLocale::system().bcp47Name());
177 const QTextCodec *codecForLocale = QTextCodec::codecForLocale();
178 systemInfo.append(
"\n QTextCodec for locale: ").append(codecForLocale->name());
181 systemInfo.append(
"\n Process ACP: ");
183 if (GetCPInfoExW(CP_ACP, 0, &cpInfo)) {
184 systemInfo.append(QString::fromWCharArray(cpInfo.CodePageName));
187 systemInfo.append(QString::number(GetACP()));
190 int result = GetLocaleInfoEx(LOCALE_NAME_SYSTEM_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, lcData,
sizeof(lcData) /
sizeof(lcData[0]));
192 systemInfo.append(
"\n System locale default ACP: ");
193 int systemACP = lcData[1] << 16 | lcData[0];
194 if (systemACP == CP_ACP) {
195 systemInfo.append(
"N/A");
196 }
else if (GetCPInfoExW(systemACP, 0, &cpInfo)) {
197 systemInfo.append(QString::fromWCharArray(cpInfo.CodePageName));
200 systemInfo.append(QString::number(systemACP));
205 systemInfo.append(
"\n\n");
206 s_instance->d->sysInfoFile.write(systemInfo.toUtf8());
221 QMutexLocker locker(&s_instance->d->mutex);
223 if (!s_instance->d->active)
return;
224 if (!s_instance->d->logFile.isOpen())
return;
226 s_instance->d->logFile.write(QDateTime::currentDateTime().toString(Qt::RFC2822Date).toUtf8());
227 s_instance->d->logFile.write(
": ");
228 s_instance->d->logFile.write(message.toUtf8());
229 s_instance->d->logFile.write(
"\n");
230 s_instance->d->logFile.flush();
235 QMutexLocker locker(&s_instance->d->mutex);
237 if (!s_instance->d->active)
return;
238 if (!s_instance->d->sysInfoFile.isOpen())
return;
240 s_instance->d->sysInfoFile.write(message.toUtf8());
241 s_instance->d->sysInfoFile.write(
"\n");
243 s_instance->d->sysInfoFile.flush();
249 Q_ASSERT(s_instance->d->sysInfoFile.isOpen());
252 QString sessionHeader = QString(
"SESSION: %1. Executing %2\n\n")
253 .arg(QDateTime::currentDateTime().toString(Qt::RFC2822Date))
254 .arg(qApp->arguments().join(
' '));
256 s_instance->d->logFile.write(sessionHeader.toUtf8());
258 QString KritaAndQtVersion;
260 .append(
", Qt version compiled: ").append(QT_VERSION_STR)
261 .append(
", loaded: ").append(qVersion())
262 .append(
". Process ID: ")
263 .append(QString::number(qApp->applicationPid())).append(
"\n");
265 KritaAndQtVersion.append(
"-- -- -- -- -- -- -- --\n");
266 s_instance->d->logFile.write(KritaAndQtVersion.toUtf8());
267 s_instance->d->logFile.flush();
268 log(QString(
"Style: %1. Available styles: %2")
269 .arg(qApp->style()->objectName(),
270 QStyleFactory::keys().join(
", ")));
279 info.append(
"Display Information");
280 info.append(
"\nNumber of screens: ").append(QString::number(screens.size()));
282 for (
int i = 0; i < screens.size(); ++i ) {
283 QScreen *screen = screens[i];
284 info.append(
"\n\tScreen: ").append(QString::number(i));
285 info.append(
"\n\t\tName: ").append(screen->name());
286 info.append(
"\n\t\tDepth: ").append(QString::number(screen->depth()));
287 info.append(
"\n\t\tScale: ").append(QString::number(screen->devicePixelRatio()));
288 info.append(
"\n\t\tPhysical DPI").append(QString::number(screen->physicalDotsPerInch()));
289 info.append(
"\n\t\tLogical DPI").append(QString::number(screen->logicalDotsPerInch()));
290 info.append(
"\n\t\tPhysical Size: ").append(QString::number(screen->physicalSize().width()))
292 .append(QString::number(screen->physicalSize().height()));
293 info.append(
"\n\t\tPosition: ").append(QString::number(screen->geometry().x()))
295 .append(QString::number(screen->geometry().y()));
296 info.append(
"\n\t\tResolution in pixels: ").append(QString::number(screen->geometry().width()))
298 .append(QString::number(screen->geometry().height()));
299 info.append(
"\n\t\tManufacturer: ").append(screen->manufacturer());
300 info.append(
"\n\t\tModel: ").append(screen->model());
301 info.append(
"\n\t\tRefresh Rate: ").append(QString::number(screen->refreshRate()));
302 info.append(
"\n\t\tSerial Number: ").append(screen->serialNumber());
311 if (
d->logFile.exists()) {
314 d->logFile.open(QFile::ReadOnly);
315 QString
log = QString::fromUtf8(
d->logFile.readAll());
317 log.append(
"\nKRITA DID NOT CLOSE CORRECTLY\n");
318 QString crashLog = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral(
"/kritacrash.log");
319 if (QFileInfo(crashLog).exists()) {
321 f.open(QFile::ReadOnly);
322 QString crashes = QString::fromUtf8(f.readAll());
325 QStringList crashlist = crashes.split(
"-------------------");
326 log.append(QString(
"\nThere were %1 crashes in total in the crash log.\n").arg(crashlist.size()));
328 if (crashes.size() > 0) {
329 log.append(crashlist.last());
333 d->logFile.open(QFile::WriteOnly);
334 d->logFile.write(
log.toUtf8());
342 d->logFile.open(QFile::ReadOnly);
343 QString
log = QString::fromUtf8(
d->logFile.readAll());
347 int sectionCount = logItems.size();
349 for (
int i = sectionCount -
s_maxLogs; i < sectionCount; ++i) {
350 if (logItems.size() > i ) {
351 keptItems.append(logItems[i]);
355 d->logFile.open(QFile::WriteOnly);
356 d->logFile.write(keptItems.join(
"\nSESSION:").toUtf8());