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 if (
d->logFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
73 qWarning() <<
"Could not clear the >100MB" <<
d->logFile.fileName() <<
":" <<
d->logFile.errorString();
80 if (!
d->logFile.open(QFile::Append | QFile::Text)) {
81 qWarning() <<
"Could not open" <<
d->logFile.fileName() <<
"for writing:" <<
d->logFile.errorString();
83 if (!
d->sysInfoFile.open(QFile::WriteOnly | QFile::Text)) {
84 qWarning() <<
"Could not open" <<
d->sysInfoFile.fileName() <<
"for writing:" <<
d->sysInfoFile.errorString();
110 systemInfo.append(
"Krita\n");
115 QString packageFamilyName;
116 QString packageFullName;
117 systemInfo.append(
"\n Installation type: ");
118 if (tryGetCurrentPackageFamilyName(&packageFamilyName) && tryGetCurrentPackageFullName(&packageFullName)) {
119 systemInfo.append(
"Store / MSIX package\n Family Name: ")
120 .append(packageFamilyName)
121 .append(
"\n Full Name: ")
122 .append(packageFullName);
124 systemInfo.append(
"installer / portable package");
128#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
130 systemInfo.append(
"\n Hidpi: ").append(QCoreApplication::testAttribute(Qt::AA_EnableHighDpiScaling) ?
"true" :
"false");
134 systemInfo.append(
"\n Sandbox: ").append((entitlements.
sandbox()) ?
"true" :
"false");
136 systemInfo.append(
"\n\n");
138 systemInfo.append(
"Qt\n");
139 systemInfo.append(
"\n Version (compiled): ").append(QT_VERSION_STR);
140 systemInfo.append(
"\n Version (loaded): ").append(qVersion());
141 systemInfo.append(
"\n\n");
144 systemInfo.append(
"OS Information\n");
145 systemInfo.append(
"\n Build ABI: ").append(QSysInfo::buildAbi());
146 systemInfo.append(
"\n Build CPU: ").append(QSysInfo::buildCpuArchitecture());
147 systemInfo.append(
"\n CPU: ").append(QSysInfo::currentCpuArchitecture());
148 systemInfo.append(
"\n Kernel Type: ").append(QSysInfo::kernelType());
149 systemInfo.append(
"\n Kernel Version: ").append(QSysInfo::kernelVersion());
150 systemInfo.append(
"\n Pretty Productname: ").append(QSysInfo::prettyProductName());
151 systemInfo.append(
"\n Product Type: ").append(QSysInfo::productType());
152 systemInfo.append(
"\n Product Version: ").append(QSysInfo::productVersion());
155 QString manufacturer =
156 QAndroidJniObject::getStaticObjectField(
"android/os/Build",
"MANUFACTURER",
"Ljava/lang/String;").toString();
157 const QString model =
158 QAndroidJniObject::getStaticObjectField(
"android/os/Build",
"MODEL",
"Ljava/lang/String;").toString();
159 manufacturer[0] = manufacturer[0].toUpper();
160 systemInfo.append(
"\n Product Model: ").append(manufacturer +
" " + model);
161#elif defined(Q_OS_LINUX)
162 systemInfo.append(
"\n Desktop: ").append(qgetenv(
"XDG_CURRENT_DESKTOP"));
164 systemInfo.append(
"\n Appimage build: ").append(qEnvironmentVariableIsSet(
"APPIMAGE") ?
"Yes" :
"No");
165#elif defined(Q_OS_WIN)
166 systemInfo.append(
"\n Result of IsWindows10OrGreater(): ").append(IsWindows10OrGreater() ?
"Yes" :
"No");
168 systemInfo.append(
"\n\n");
175 if (!s_instance->d->active) {
179 systemInfo.append(
"Locale\n");
180 systemInfo.append(
"\n Languages: ").append(KLocalizedString::languages().join(
", "));
181 systemInfo.append(
"\n C locale: ").append(std::setlocale(LC_ALL,
nullptr));
182 systemInfo.append(
"\n QLocale current: ").append(QLocale().bcp47Name());
183 systemInfo.append(
"\n QLocale system: ").append(QLocale::system().bcp47Name());
184 const QTextCodec *codecForLocale = QTextCodec::codecForLocale();
185 systemInfo.append(
"\n QTextCodec for locale: ").append(codecForLocale->name());
188 systemInfo.append(
"\n Process ACP: ");
190 if (GetCPInfoExW(CP_ACP, 0, &cpInfo)) {
191 systemInfo.append(QString::fromWCharArray(cpInfo.CodePageName));
194 systemInfo.append(QString::number(GetACP()));
197 int result = GetLocaleInfoEx(LOCALE_NAME_SYSTEM_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, lcData,
sizeof(lcData) /
sizeof(lcData[0]));
199 systemInfo.append(
"\n System locale default ACP: ");
200 int systemACP = lcData[1] << 16 | lcData[0];
201 if (systemACP == CP_ACP) {
202 systemInfo.append(
"N/A");
203 }
else if (GetCPInfoExW(systemACP, 0, &cpInfo)) {
204 systemInfo.append(QString::fromWCharArray(cpInfo.CodePageName));
207 systemInfo.append(QString::number(systemACP));
212 systemInfo.append(
"\n\n");
213 s_instance->d->sysInfoFile.write(systemInfo.toUtf8());
228 QMutexLocker locker(&s_instance->d->mutex);
230 if (!s_instance->d->active)
return;
231 if (!s_instance->d->logFile.isOpen())
return;
233 s_instance->d->logFile.write(QDateTime::currentDateTime().toString(Qt::RFC2822Date).toUtf8());
234 s_instance->d->logFile.write(
": ");
235 s_instance->d->logFile.write(message.toUtf8());
236 s_instance->d->logFile.write(
"\n");
237 s_instance->d->logFile.flush();
242 QMutexLocker locker(&s_instance->d->mutex);
244 if (!s_instance->d->active)
return;
245 if (!s_instance->d->sysInfoFile.isOpen())
return;
247 s_instance->d->sysInfoFile.write(message.toUtf8());
248 s_instance->d->sysInfoFile.write(
"\n");
250 s_instance->d->sysInfoFile.flush();
256 Q_ASSERT(s_instance->d->sysInfoFile.isOpen());
259 QString sessionHeader = QString(
"SESSION: %1. Executing %2\n\n")
260 .arg(QDateTime::currentDateTime().toString(Qt::RFC2822Date))
261 .arg(qApp->arguments().join(
' '));
263 s_instance->d->logFile.write(sessionHeader.toUtf8());
265 QString KritaAndQtVersion;
267 .append(
", Qt version compiled: ").append(QT_VERSION_STR)
268 .append(
", loaded: ").append(qVersion())
269 .append(
". Process ID: ")
270 .append(QString::number(qApp->applicationPid())).append(
"\n");
272 KritaAndQtVersion.append(
"-- -- -- -- -- -- -- --\n");
273 s_instance->d->logFile.write(KritaAndQtVersion.toUtf8());
274 s_instance->d->logFile.flush();
275 log(QString(
"Style: %1. Available styles: %2")
276 .arg(qApp->style()->objectName(),
277 QStyleFactory::keys().join(
", ")));
286 info.append(
"Display Information");
287 info.append(
"\nNumber of screens: ").append(QString::number(screens.size()));
289 for (
int i = 0; i < screens.size(); ++i ) {
290 QScreen *screen = screens[i];
291 info.append(
"\n\tScreen: ").append(QString::number(i));
292 info.append(
"\n\t\tName: ").append(screen->name());
293 info.append(
"\n\t\tDepth: ").append(QString::number(screen->depth()));
294 info.append(
"\n\t\tScale: ").append(QString::number(screen->devicePixelRatio()));
295 info.append(
"\n\t\tPhysical DPI").append(QString::number(screen->physicalDotsPerInch()));
296 info.append(
"\n\t\tLogical DPI").append(QString::number(screen->logicalDotsPerInch()));
297 info.append(
"\n\t\tPhysical Size: ").append(QString::number(screen->physicalSize().width()))
299 .append(QString::number(screen->physicalSize().height()));
300 info.append(
"\n\t\tPosition: ").append(QString::number(screen->geometry().x()))
302 .append(QString::number(screen->geometry().y()));
303 info.append(
"\n\t\tResolution in pixels: ").append(QString::number(screen->geometry().width()))
305 .append(QString::number(screen->geometry().height()));
306 info.append(
"\n\t\tManufacturer: ").append(screen->manufacturer());
307 info.append(
"\n\t\tModel: ").append(screen->model());
308 info.append(
"\n\t\tRefresh Rate: ").append(QString::number(screen->refreshRate()));
309 info.append(
"\n\t\tSerial Number: ").append(screen->serialNumber());
318 if (!
d->logFile.exists()) {
return; }
321 if (
d->logFile.open(QFile::ReadOnly)) {
322 QString
log = QString::fromUtf8(
d->logFile.readAll());
324 log.append(
"\nKRITA DID NOT CLOSE CORRECTLY\n");
325 QString crashLog = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral(
"/kritacrash.log");
327 if (f.open(QFile::ReadOnly)) {
328 QString crashes = QString::fromUtf8(f.readAll());
331 QStringList crashlist = crashes.split(
"-------------------");
332 log.append(QString(
"\nThere were %1 crashes in total in the crash log.\n").arg(crashlist.size()));
334 if (crashes.size() > 0) {
335 log.append(crashlist.last());
339 if (
d->logFile.open(QFile::WriteOnly)) {
340 d->logFile.write(
log.toUtf8());
348 if (
d->logFile.open(QFile::ReadOnly)) {
349 QString
log = QString::fromUtf8(
d->logFile.readAll());
353 int sectionCount = logItems.size();
355 for (
int i = sectionCount -
s_maxLogs; i < sectionCount; ++i) {
356 if (logItems.size() > i ) {
357 keptItems.append(logItems[i]);
361 if (
d->logFile.open(QFile::WriteOnly)) {
362 d->logFile.write(keptItems.join(
"\nSESSION:").toUtf8());