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 "vmaingraphicsview.h"
|
||||
#include "../container/calculator.h"
|
||||
#include "../version.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
|
@ -44,6 +45,7 @@
|
|||
#include <QTemporaryFile>
|
||||
|
||||
const qreal VApplication::PrintDPI = 96.0;
|
||||
const QString VApplication::GistFileName = QStringLiteral("gist.json");
|
||||
|
||||
#define DefWidth 1.2//mm
|
||||
|
||||
|
@ -1848,3 +1850,152 @@ bool VApplication::SafeCopy(const QString &source, const QString &destination, Q
|
|||
|
||||
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();
|
||||
QString STDescription(const QString &id)const;
|
||||
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:
|
||||
Q_DISABLE_COPY(VApplication)
|
||||
Unit _patternUnit;
|
||||
|
@ -153,6 +160,13 @@ private:
|
|||
void BiasTokens(int position, int bias, QMap<int, QString> &tokens) const;
|
||||
void InitMeasurement(const QString &name, const VTranslation &m, const VTranslation &g,
|
||||
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)
|
||||
: 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 *langGroup = LangGroup();
|
||||
QGroupBox *sendGroup = SendGroup();
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addWidget(saveGroup);
|
||||
mainLayout->addWidget(langGroup);
|
||||
mainLayout->addWidget(sendGroup);
|
||||
mainLayout->addStretch(1);
|
||||
setLayout(mainLayout);
|
||||
}
|
||||
|
@ -76,6 +79,8 @@ void ConfigurationPage::Apply()
|
|||
|
||||
qApp->getSettings()->setValue("configuration/osSeparator", osOptionCheck->isChecked());
|
||||
|
||||
qApp->getSettings()->setValue("configuration/send_report/state", sendReportCheck->isChecked());
|
||||
|
||||
if (langChanged)
|
||||
{
|
||||
QString locale = qvariant_cast<QString>(langCombo->itemData(langCombo->currentIndex()));
|
||||
|
@ -273,6 +278,35 @@ QGroupBox *ConfigurationPage::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)
|
||||
{
|
||||
|
|
|
@ -58,9 +58,11 @@ private:
|
|||
bool langChanged;
|
||||
bool unitChanged;
|
||||
bool labelLangChanged;
|
||||
QCheckBox *sendReportCheck;
|
||||
|
||||
QGroupBox *SaveGroup();
|
||||
QGroupBox *LangGroup();
|
||||
QGroupBox *SendGroup();
|
||||
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[])
|
||||
{
|
||||
|
@ -176,11 +134,6 @@ int main(int argc, char *argv[])
|
|||
|
||||
VApplication app(argc, argv);
|
||||
|
||||
#if defined(Q_OS_WIN) && defined(Q_CC_GNU)
|
||||
DrMingw();
|
||||
CollectReport();
|
||||
#endif
|
||||
|
||||
#ifdef QT_DEBUG
|
||||
// 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
|
||||
|
@ -198,6 +151,11 @@ int main(int argc, char *argv[])
|
|||
|
||||
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();
|
||||
|
||||
QTranslator qtTranslator;
|
||||
|
|
Loading…
Reference in New Issue
Block a user