63 if (!QFileInfo(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)).exists()) {
64 QDir().mkpath(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation));
66 d->logFile.setFileName(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) +
"/krita.log");
67 d->sysInfoFile.setFileName(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) +
"/krita-sysinfo.log");
69 QFileInfo fi(
d->logFile.fileName());
70 if (fi.size() > 100 * 1000 * 1000) {
71 if (
d->logFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
74 qWarning() <<
"Could not clear the >100MB" <<
d->logFile.fileName() <<
":" <<
d->logFile.errorString();
81 if (!
d->logFile.open(QFile::Append | QFile::Text)) {
82 qWarning() <<
"Could not open" <<
d->logFile.fileName() <<
"for writing:" <<
d->logFile.errorString();
84 if (!
d->sysInfoFile.open(QFile::WriteOnly | QFile::Text)) {
85 qWarning() <<
"Could not open" <<
d->sysInfoFile.fileName() <<
"for writing:" <<
d->sysInfoFile.errorString();
111 systemInfo.append(
"Krita\n");
116 QString packageFamilyName;
117 QString packageFullName;
118 systemInfo.append(
"\n Installation type: ");
119 if (tryGetCurrentPackageFamilyName(&packageFamilyName) && tryGetCurrentPackageFullName(&packageFullName)) {
120 systemInfo.append(
"Store / MSIX package\n Family Name: ")
121 .append(packageFamilyName)
122 .append(
"\n Full Name: ")
123 .append(packageFullName);
125 systemInfo.append(
"installer / portable package");
129#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
131 systemInfo.append(
"\n Hidpi: ").append(QCoreApplication::testAttribute(Qt::AA_EnableHighDpiScaling) ?
"true" :
"false");
135 systemInfo.append(
"\n Sandbox: ").append((entitlements.
sandbox()) ?
"true" :
"false");
137 systemInfo.append(
"\n\n");
139 systemInfo.append(
"Qt\n");
140 systemInfo.append(
"\n Version (compiled): ").append(QT_VERSION_STR);
141 systemInfo.append(
"\n Version (loaded): ").append(qVersion());
142 systemInfo.append(
"\n\n");
145 systemInfo.append(
"OS Information\n");
146 systemInfo.append(
"\n Build ABI: ").append(QSysInfo::buildAbi());
147 systemInfo.append(
"\n Build CPU: ").append(QSysInfo::buildCpuArchitecture());
148 systemInfo.append(
"\n CPU: ").append(QSysInfo::currentCpuArchitecture());
149 systemInfo.append(
"\n Kernel Type: ").append(QSysInfo::kernelType());
150 systemInfo.append(
"\n Kernel Version: ").append(QSysInfo::kernelVersion());
151 systemInfo.append(
"\n Pretty Productname: ").append(QSysInfo::prettyProductName());
152 systemInfo.append(
"\n Product Type: ").append(QSysInfo::productType());
153 systemInfo.append(
"\n Product Version: ").append(QSysInfo::productVersion());
156 QString manufacturer =
157 QAndroidJniObject::getStaticObjectField(
"android/os/Build",
"MANUFACTURER",
"Ljava/lang/String;").toString();
158 const QString model =
159 QAndroidJniObject::getStaticObjectField(
"android/os/Build",
"MODEL",
"Ljava/lang/String;").toString();
160 manufacturer[0] = manufacturer[0].toUpper();
161 systemInfo.append(
"\n Product Model: ").append(manufacturer +
" " + model);
162#elif defined(Q_OS_LINUX)
163 systemInfo.append(
"\n Desktop: ").append(qgetenv(
"XDG_CURRENT_DESKTOP"));
165 systemInfo.append(
"\n Appimage build: ").append(qEnvironmentVariableIsSet(
"APPIMAGE") ?
"Yes" :
"No");
166#elif defined(Q_OS_WIN)
167 systemInfo.append(
"\n Result of IsWindows10OrGreater(): ").append(IsWindows10OrGreater() ?
"Yes" :
"No");
169 systemInfo.append(
"\n\n");
176 if (!s_instance->d->active) {
180 systemInfo.append(
"Locale\n");
181 systemInfo.append(
"\n Languages: ").append(KLocalizedString::languages().join(
", "));
182 systemInfo.append(
"\n C locale: ").append(std::setlocale(LC_ALL,
nullptr));
183 systemInfo.append(
"\n QLocale current: ").append(QLocale().bcp47Name());
184 systemInfo.append(
"\n QLocale system: ").append(QLocale::system().bcp47Name());
185 const QTextCodec *codecForLocale = QTextCodec::codecForLocale();
186 systemInfo.append(
"\n QTextCodec for locale: ").append(codecForLocale->name());
189 systemInfo.append(
"\n Process ACP: ");
191 if (GetCPInfoExW(CP_ACP, 0, &cpInfo)) {
192 systemInfo.append(QString::fromWCharArray(cpInfo.CodePageName));
195 systemInfo.append(QString::number(GetACP()));
198 int result = GetLocaleInfoEx(LOCALE_NAME_SYSTEM_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, lcData,
sizeof(lcData) /
sizeof(lcData[0]));
200 systemInfo.append(
"\n System locale default ACP: ");
201 int systemACP = lcData[1] << 16 | lcData[0];
202 if (systemACP == CP_ACP) {
203 systemInfo.append(
"N/A");
204 }
else if (GetCPInfoExW(systemACP, 0, &cpInfo)) {
205 systemInfo.append(QString::fromWCharArray(cpInfo.CodePageName));
208 systemInfo.append(QString::number(systemACP));
213 systemInfo.append(
"\n\n");
214 s_instance->d->sysInfoFile.write(systemInfo.toUtf8());
229 QMutexLocker locker(&s_instance->d->mutex);
231 if (!s_instance->d->active)
return;
232 if (!s_instance->d->logFile.isOpen())
return;
234 s_instance->d->logFile.write(QDateTime::currentDateTime().toString(Qt::RFC2822Date).toUtf8());
235 s_instance->d->logFile.write(
": ");
236 s_instance->d->logFile.write(message.toUtf8());
237 s_instance->d->logFile.write(
"\n");
238 s_instance->d->logFile.flush();
243 QMutexLocker locker(&s_instance->d->mutex);
245 if (!s_instance->d->active)
return;
246 if (!s_instance->d->sysInfoFile.isOpen())
return;
248 s_instance->d->sysInfoFile.write(message.toUtf8());
249 s_instance->d->sysInfoFile.write(
"\n");
251 s_instance->d->sysInfoFile.flush();
257 Q_ASSERT(s_instance->d->sysInfoFile.isOpen());
260 QString sessionHeader = QString(
"SESSION: %1. Executing %2\n\n")
261 .arg(QDateTime::currentDateTime().toString(Qt::RFC2822Date))
262 .arg(qApp->arguments().join(
' '));
264 s_instance->d->logFile.write(sessionHeader.toUtf8());
266 QString KritaAndQtVersion;
268 .append(
", Qt version compiled: ").append(QT_VERSION_STR)
269 .append(
", loaded: ").append(qVersion())
270 .append(
". Process ID: ")
271 .append(QString::number(qApp->applicationPid())).append(
"\n");
273 KritaAndQtVersion.append(
"-- -- -- -- -- -- -- --\n");
274 s_instance->d->logFile.write(KritaAndQtVersion.toUtf8());
275 s_instance->d->logFile.flush();
276 log(QString(
"Style: %1. Available styles: %2")
277 .arg(qApp->style()->objectName(),
278 QStyleFactory::keys().join(
", ")));
282 if (androidExitInfo.
isValid()) {
293 info.append(
"Display Information");
294 info.append(
"\nNumber of screens: ").append(QString::number(screens.size()));
296 for (
int i = 0; i < screens.size(); ++i ) {
297 QScreen *screen = screens[i];
298 info.append(
"\n\tScreen: ").append(QString::number(i));
299 info.append(
"\n\t\tName: ").append(screen->name());
300 info.append(
"\n\t\tDepth: ").append(QString::number(screen->depth()));
301 info.append(
"\n\t\tScale: ").append(QString::number(screen->devicePixelRatio()));
302 info.append(
"\n\t\tPhysical DPI").append(QString::number(screen->physicalDotsPerInch()));
303 info.append(
"\n\t\tLogical DPI").append(QString::number(screen->logicalDotsPerInch()));
304 info.append(
"\n\t\tPhysical Size: ").append(QString::number(screen->physicalSize().width()))
306 .append(QString::number(screen->physicalSize().height()));
307 info.append(
"\n\t\tPosition: ").append(QString::number(screen->geometry().x()))
309 .append(QString::number(screen->geometry().y()));
310 info.append(
"\n\t\tResolution in pixels: ").append(QString::number(screen->geometry().width()))
312 .append(QString::number(screen->geometry().height()));
313 info.append(
"\n\t\tManufacturer: ").append(screen->manufacturer());
314 info.append(
"\n\t\tModel: ").append(screen->model());
315 info.append(
"\n\t\tRefresh Rate: ").append(QString::number(screen->refreshRate()));
316 info.append(
"\n\t\tSerial Number: ").append(screen->serialNumber());
325 if (!
d->logFile.exists()) {
return; }
328 if (
d->logFile.open(QFile::ReadOnly)) {
329 QString
log = QString::fromUtf8(
d->logFile.readAll());
331 log.append(
"\nKRITA DID NOT CLOSE CORRECTLY\n");
332 QString crashLog = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral(
"/kritacrash.log");
334 if (f.open(QFile::ReadOnly)) {
335 QString crashes = QString::fromUtf8(f.readAll());
338 QStringList crashlist = crashes.split(
"-------------------");
339 log.append(QString(
"\nThere were %1 crashes in total in the crash log.\n").arg(crashlist.size()));
341 if (crashes.size() > 0) {
342 log.append(crashlist.last());
346 if (
d->logFile.open(QFile::WriteOnly)) {
347 d->logFile.write(
log.toUtf8());
355 if (
d->logFile.open(QFile::ReadOnly)) {
356 QString
log = QString::fromUtf8(
d->logFile.readAll());
360 int sectionCount = logItems.size();
362 for (
int i = sectionCount -
s_maxLogs; i < sectionCount; ++i) {
363 if (logItems.size() > i ) {
364 keptItems.append(logItems[i]);
368 if (
d->logFile.open(QFile::WriteOnly)) {
369 d->logFile.write(keptItems.join(
"\nSESSION:").toUtf8());