Send crash reports to gist. Only Windows.
--HG-- branch : develop
This commit is contained in:
parent
776d8be8bb
commit
5abfea36bc
|
@ -34,6 +34,7 @@
|
||||||
#include "../exception/vexceptionwrongid.h"
|
#include "../exception/vexceptionwrongid.h"
|
||||||
#include "vmaingraphicsview.h"
|
#include "vmaingraphicsview.h"
|
||||||
#include "../container/calculator.h"
|
#include "../container/calculator.h"
|
||||||
|
#include "../version.h"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
@ -44,6 +45,7 @@
|
||||||
#include <QTemporaryFile>
|
#include <QTemporaryFile>
|
||||||
|
|
||||||
const qreal VApplication::PrintDPI = 96.0;
|
const qreal VApplication::PrintDPI = 96.0;
|
||||||
|
const QString VApplication::GistFileName = QStringLiteral("gist.json");
|
||||||
|
|
||||||
#define DefWidth 1.2//mm
|
#define DefWidth 1.2//mm
|
||||||
|
|
||||||
|
@ -1848,3 +1850,152 @@ bool VApplication::SafeCopy(const QString &source, const QString &destination, Q
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN) && defined(Q_CC_GNU)
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
// Catch exception and create report. Use if program build with Mingw compiler.
|
||||||
|
// See more about catcher https://github.com/jrfonseca/drmingw/blob/master/README.md
|
||||||
|
void VApplication::DrMingw()
|
||||||
|
{
|
||||||
|
QFile drmingw("exchndl.dll");
|
||||||
|
if(drmingw.exists())
|
||||||
|
{// If don't want create reports just delete exchndl.dll from installer
|
||||||
|
LoadLibrary(L"exchndl.dll");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
void VApplication::CollectReports() const
|
||||||
|
{
|
||||||
|
// Seek file "binary_name.RPT"
|
||||||
|
const QString reportName = QString("%1/%2.RPT").arg(applicationDirPath())
|
||||||
|
.arg(QFileInfo(arguments().at(0)).baseName());
|
||||||
|
QFile reportFile(reportName);
|
||||||
|
if (reportFile.exists())
|
||||||
|
{ // Hooray we have found crash
|
||||||
|
if (settings == nullptr)
|
||||||
|
{
|
||||||
|
return;// Settings was not opened.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings->value("configuration/send_report/state", 1).toBool())
|
||||||
|
{ // Try send report
|
||||||
|
// Remove gist.json file before close app.
|
||||||
|
connect(this, &VApplication::aboutToQuit, this, &VApplication::CleanGist, Qt::UniqueConnection);
|
||||||
|
SendReport(reportName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Just collect report to /reports directory
|
||||||
|
CollectReport(reportName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
void VApplication::CollectReport(const QString &reportName) const
|
||||||
|
{
|
||||||
|
const QString reportsDir = QString("%1/reports").arg(qApp->applicationDirPath());
|
||||||
|
QDir reports(reportsDir);
|
||||||
|
if (reports.exists() == false)
|
||||||
|
{
|
||||||
|
reports.mkpath("."); // Create directory for reports if need
|
||||||
|
}
|
||||||
|
|
||||||
|
const QDateTime now = QDateTime::currentDateTime();
|
||||||
|
const QString timestamp = now.toString(QLatin1String("yyyyMMdd-hhmmsszzz"));
|
||||||
|
const QString filename = QString("%1/reports/crash-%2.RPT").arg(qApp->applicationDirPath()).arg(timestamp);
|
||||||
|
|
||||||
|
QFile reportFile(reportName);
|
||||||
|
reportFile.copy(filename); // Collect new crash
|
||||||
|
reportFile.remove(); // Clear after yourself
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
void VApplication::CleanGist() const
|
||||||
|
{
|
||||||
|
QFile gistFile(GistFileName);
|
||||||
|
if (gistFile.exists())
|
||||||
|
{
|
||||||
|
gistFile.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
void VApplication::SendReport(const QString &reportName) const
|
||||||
|
{
|
||||||
|
QString content;
|
||||||
|
QFile reportFile(reportName);
|
||||||
|
if (!reportFile.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTextStream in(&reportFile);
|
||||||
|
while (!in.atEnd())
|
||||||
|
{
|
||||||
|
content.append(in.readLine()+"\r\n");// Windows end of line
|
||||||
|
}
|
||||||
|
reportFile.close();
|
||||||
|
|
||||||
|
// Additional information
|
||||||
|
content.append(QString("-------------------------------")+"\r\n");
|
||||||
|
content.append(QString("Version:%1").arg(APP_VERSION)+"\r\n");
|
||||||
|
content.append(QString("Based on Qt %2 (32 bit)").arg(QT_VERSION_STR)+"\r\n");
|
||||||
|
content.append(QString("Built on %3 at %4").arg(__DATE__).arg(__TIME__)+"\r\n");
|
||||||
|
|
||||||
|
// Creating json with report
|
||||||
|
// Example:
|
||||||
|
//{
|
||||||
|
// "description":"Crash report",
|
||||||
|
// "public":"true",
|
||||||
|
// "files":{
|
||||||
|
// "file1.txt":{
|
||||||
|
// "content":"Report text here"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Useful to know when crash was created
|
||||||
|
const QDateTime now = QDateTime::currentDateTime();
|
||||||
|
const QString timestamp = now.toString(QLatin1String("yyyy/MM/dd hh:mm:ss:zzz"));
|
||||||
|
const QString report = QString("Crash report was created %2").arg(timestamp);
|
||||||
|
|
||||||
|
QJsonObject reportObject;
|
||||||
|
reportObject.insert(QStringLiteral("description"), QJsonValue(report));
|
||||||
|
reportObject.insert(QStringLiteral("public"), QJsonValue(QString("true")));
|
||||||
|
|
||||||
|
QJsonObject contentObject;
|
||||||
|
contentObject.insert(QStringLiteral("content"), QJsonValue(content));
|
||||||
|
|
||||||
|
QJsonObject fileObject;
|
||||||
|
fileObject.insert(QFileInfo(reportName).fileName(), QJsonValue(contentObject));
|
||||||
|
reportObject.insert(QStringLiteral("files"), QJsonValue(fileObject));
|
||||||
|
|
||||||
|
QFile gistFile(GistFileName);
|
||||||
|
if (!gistFile.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
|
||||||
|
{
|
||||||
|
qDebug("Couldn't open gist file.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save data to file
|
||||||
|
QJsonDocument saveRep(reportObject);
|
||||||
|
gistFile.write(saveRep.toJson());
|
||||||
|
gistFile.close();
|
||||||
|
|
||||||
|
QFile curlFile("curl.exe");
|
||||||
|
if (curlFile.exists())
|
||||||
|
{// Trying send report
|
||||||
|
// Change token 28df778e0ef75e3724f7b9622fb70b9c69187779 if need
|
||||||
|
QString arg = QString("curl.exe -k -H \"Authorization: bearer 28df778e0ef75e3724f7b9622fb70b9c69187779\" "
|
||||||
|
"-H \"Accept: application/json\" -H \"Content-type: application/json\" -X POST "
|
||||||
|
"--data @gist.json https://api.github.com/gists");
|
||||||
|
QProcess::startDetached(arg);
|
||||||
|
reportFile.remove();// Clear after yourself
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{// We can not send than just collect
|
||||||
|
CollectReport(reportName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif //defined(Q_OS_WIN) && defined(Q_CC_GNU)
|
||||||
|
|
|
@ -103,6 +103,13 @@ public:
|
||||||
static QStringList LabelLanguages();
|
static QStringList LabelLanguages();
|
||||||
QString STDescription(const QString &id)const;
|
QString STDescription(const QString &id)const;
|
||||||
static bool SafeCopy(const QString &source, const QString &destination, QString &error);
|
static bool SafeCopy(const QString &source, const QString &destination, QString &error);
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN) && defined(Q_CC_GNU)
|
||||||
|
static void DrMingw();
|
||||||
|
void CollectReports() const;
|
||||||
|
private slots:
|
||||||
|
void CleanGist() const;
|
||||||
|
#endif
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(VApplication)
|
Q_DISABLE_COPY(VApplication)
|
||||||
Unit _patternUnit;
|
Unit _patternUnit;
|
||||||
|
@ -153,6 +160,13 @@ private:
|
||||||
void BiasTokens(int position, int bias, QMap<int, QString> &tokens) const;
|
void BiasTokens(int position, int bias, QMap<int, QString> &tokens) const;
|
||||||
void InitMeasurement(const QString &name, const VTranslation &m, const VTranslation &g,
|
void InitMeasurement(const QString &name, const VTranslation &m, const VTranslation &g,
|
||||||
const VTranslation &d);
|
const VTranslation &d);
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN) && defined(Q_CC_GNU)
|
||||||
|
static const QString GistFileName;
|
||||||
|
|
||||||
|
void CollectReport(const QString &reportName) const;
|
||||||
|
void SendReport(const QString &reportName) const;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -44,14 +44,17 @@
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
ConfigurationPage::ConfigurationPage(QWidget *parent)
|
ConfigurationPage::ConfigurationPage(QWidget *parent)
|
||||||
: QWidget(parent), autoSaveCheck(nullptr), autoTime(nullptr), langCombo(nullptr), labelCombo(nullptr),
|
: QWidget(parent), autoSaveCheck(nullptr), autoTime(nullptr), langCombo(nullptr), labelCombo(nullptr),
|
||||||
unitCombo(nullptr), osOptionCheck(nullptr), langChanged(false), unitChanged(false), labelLangChanged(false)
|
unitCombo(nullptr), osOptionCheck(nullptr), langChanged(false), unitChanged(false), labelLangChanged(false),
|
||||||
|
sendReportCheck(nullptr)
|
||||||
{
|
{
|
||||||
QGroupBox *saveGroup = SaveGroup();
|
QGroupBox *saveGroup = SaveGroup();
|
||||||
QGroupBox *langGroup = LangGroup();
|
QGroupBox *langGroup = LangGroup();
|
||||||
|
QGroupBox *sendGroup = SendGroup();
|
||||||
|
|
||||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
mainLayout->addWidget(saveGroup);
|
mainLayout->addWidget(saveGroup);
|
||||||
mainLayout->addWidget(langGroup);
|
mainLayout->addWidget(langGroup);
|
||||||
|
mainLayout->addWidget(sendGroup);
|
||||||
mainLayout->addStretch(1);
|
mainLayout->addStretch(1);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
}
|
}
|
||||||
|
@ -76,6 +79,8 @@ void ConfigurationPage::Apply()
|
||||||
|
|
||||||
qApp->getSettings()->setValue("configuration/osSeparator", osOptionCheck->isChecked());
|
qApp->getSettings()->setValue("configuration/osSeparator", osOptionCheck->isChecked());
|
||||||
|
|
||||||
|
qApp->getSettings()->setValue("configuration/send_report/state", sendReportCheck->isChecked());
|
||||||
|
|
||||||
if (langChanged)
|
if (langChanged)
|
||||||
{
|
{
|
||||||
QString locale = qvariant_cast<QString>(langCombo->itemData(langCombo->currentIndex()));
|
QString locale = qvariant_cast<QString>(langCombo->itemData(langCombo->currentIndex()));
|
||||||
|
@ -273,6 +278,35 @@ QGroupBox *ConfigurationPage::LangGroup()
|
||||||
return langGroup;
|
return langGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
QGroupBox *ConfigurationPage::SendGroup()
|
||||||
|
{
|
||||||
|
QSettings *settings = qApp->getSettings();
|
||||||
|
SCASSERT(settings != nullptr);
|
||||||
|
|
||||||
|
QGroupBox *sendGroup = new QGroupBox(tr("Send crash reports"));
|
||||||
|
|
||||||
|
sendReportCheck = new QCheckBox(tr("Send crash reports (recommended)"));
|
||||||
|
bool sendReportValue = settings->value("configuration/send_report/state", 1).toBool();
|
||||||
|
sendReportCheck->setChecked(sendReportValue);
|
||||||
|
|
||||||
|
QLabel *description = new QLabel(tr("After each crash Valentina collect information that may help us fix a "
|
||||||
|
"problem. We do not collect any personal information. Find more about what "
|
||||||
|
"<a href=\"https://bitbucket.org/dismine/valentina/wiki/manual/"
|
||||||
|
"Crash_reports\">kind of information</a> we collect."));
|
||||||
|
description->setTextFormat(Qt::RichText);
|
||||||
|
description->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||||
|
description->setOpenExternalLinks(true);
|
||||||
|
description->setWordWrap(true);
|
||||||
|
|
||||||
|
QVBoxLayout *sendLayout = new QVBoxLayout;
|
||||||
|
sendLayout->addWidget(sendReportCheck);
|
||||||
|
sendLayout->addWidget(description);
|
||||||
|
|
||||||
|
sendGroup->setLayout(sendLayout);
|
||||||
|
return sendGroup;
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
void ConfigurationPage::SetLabelComboBox(const QStringList &list)
|
void ConfigurationPage::SetLabelComboBox(const QStringList &list)
|
||||||
{
|
{
|
||||||
|
|
|
@ -58,9 +58,11 @@ private:
|
||||||
bool langChanged;
|
bool langChanged;
|
||||||
bool unitChanged;
|
bool unitChanged;
|
||||||
bool labelLangChanged;
|
bool labelLangChanged;
|
||||||
|
QCheckBox *sendReportCheck;
|
||||||
|
|
||||||
QGroupBox *SaveGroup();
|
QGroupBox *SaveGroup();
|
||||||
QGroupBox *LangGroup();
|
QGroupBox *LangGroup();
|
||||||
|
QGroupBox *SendGroup();
|
||||||
void SetLabelComboBox(const QStringList &list);
|
void SetLabelComboBox(const QStringList &list);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -122,48 +122,6 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
|
||||||
// Catch exception and create report. Use if program build with Mingw compiler.
|
|
||||||
// See more about catcher https://github.com/jrfonseca/drmingw/blob/master/README.md
|
|
||||||
void DrMingw()
|
|
||||||
{
|
|
||||||
#if defined(Q_OS_WIN) && defined(Q_CC_GNU)
|
|
||||||
// Put exchndl.dll near binary file
|
|
||||||
QFile drmingw("exchndl.dll");
|
|
||||||
if(drmingw.exists())
|
|
||||||
{// If don't want create reports just delete exchndl.dll from installer
|
|
||||||
LoadLibrary(L"exchndl.dll");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
|
||||||
// Check if last run was crash.
|
|
||||||
// Each new crash we will lose old crashes reports if don't move them in save place.
|
|
||||||
// See more about catcher https://github.com/jrfonseca/drmingw/blob/master/README.md
|
|
||||||
void CollectReport()
|
|
||||||
{
|
|
||||||
// Seek file "binary_name.RPT"
|
|
||||||
const QString reportName = QString("%1/%2.RPT").arg(qApp->applicationDirPath())
|
|
||||||
.arg(QFileInfo(qApp->arguments().at(0)).baseName());
|
|
||||||
QFile reportFile(reportName);
|
|
||||||
if (reportFile.exists())
|
|
||||||
{ // Hooray we have found crash
|
|
||||||
const QString reportsDir = QString("%1/reports").arg(qApp->applicationDirPath());
|
|
||||||
QDir reports(reportsDir);
|
|
||||||
if (reports.exists() == false)
|
|
||||||
{
|
|
||||||
reports.mkpath("."); // Create directory for reports if need
|
|
||||||
}
|
|
||||||
|
|
||||||
const QDateTime now = QDateTime::currentDateTime();
|
|
||||||
const QString timestamp = now.toString(QLatin1String("yyyyMMdd-hhmmsszzz"));
|
|
||||||
const QString filename = QString("%1/reports/crash-%2.RPT").arg(qApp->applicationDirPath()).arg(timestamp);
|
|
||||||
reportFile.copy(filename); // Collect new crash
|
|
||||||
reportFile.remove(); // Clear after yourself
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
@ -176,11 +134,6 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
VApplication app(argc, argv);
|
VApplication app(argc, argv);
|
||||||
|
|
||||||
#if defined(Q_OS_WIN) && defined(Q_CC_GNU)
|
|
||||||
DrMingw();
|
|
||||||
CollectReport();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef QT_DEBUG
|
#ifdef QT_DEBUG
|
||||||
// Because our "noisy" message handler uses the GUI subsystem for message
|
// Because our "noisy" message handler uses the GUI subsystem for message
|
||||||
// boxes, we can't install it until after the QApplication is constructed. But it
|
// boxes, we can't install it until after the QApplication is constructed. But it
|
||||||
|
@ -198,6 +151,11 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
app.OpenSettings();
|
app.OpenSettings();
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN) && defined(Q_CC_GNU)
|
||||||
|
VApplication::DrMingw();
|
||||||
|
app.CollectReports();
|
||||||
|
#endif
|
||||||
|
|
||||||
QString checkedLocale = qApp->getSettings()->value("configuration/locale", QLocale::system().name()).toString();
|
QString checkedLocale = qApp->getSettings()->value("configuration/locale", QLocale::system().name()).toString();
|
||||||
|
|
||||||
QTranslator qtTranslator;
|
QTranslator qtTranslator;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user