WSL/SLF GitLab Repository

Logger.cc 6.76 KB
Newer Older
1
2
3
4
5
/*****************************************************************************/
/*  Copyright 2019 WSL Institute for Snow and Avalanche Research  SLF-DAVOS  */
/*****************************************************************************/
/* This file is part of INIshell.
   INIshell is free software: you can redistribute it and/or modify
6
   it under the terms of the GNU General Public License as published by
7
8
9
10
11
12
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   INIshell is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
   GNU General Public License for more details.
14

15
16
   You should have received a copy of the GNU General Public License
   along with INIshell.  If not, see <http://www.gnu.org/licenses/>.
17
18
*/

19
#include "Logger.h"
20
#include "src/main/colors.h"
21
#include "src/main/common.h"
22
#include "src/main/Error.h"
23
#include "src/main/inishell.h"
24
#include "src/main/settings.h"
25
26

#include <QCoreApplication>
27
#include <QDateTime>
28
#include <QFileDialog>
29
#include <QFileInfo>
30
#include <QGridLayout>
31
#include <QKeySequence>
32
33
#include <QListWidgetItem>
#include <QPushButton>
34
#include <QTextStream>
35
36
#include <QTime>

37
38
39
40
41
42
43
/**
 * @class Logger
 * @brief Default constructor for the Logger.
 * @details This class is constructed as once and stays alive as a logging window.
 * @param[in] parent The parent window (should be main window).
 */
Logger::Logger(QWidget *parent) : QWidget(parent, Qt::Window) //dedicated window
44
{
45
	/* log list, close and save buttons */
46
	loglist_ = new QListWidget(this);
47
48
	auto *close_button = new QPushButton(getIcon("application-exit"), tr("&Close"));
	close_button->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
Michael Reisecker's avatar
Michael Reisecker committed
49
	connect(close_button, &QPushButton::clicked, this, &Logger::closeLogger);
50
51
	auto *save_button = new QPushButton(getIcon("document-save-as"), tr("&Save as..."));
	save_button->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
Michael Reisecker's avatar
Michael Reisecker committed
52
	connect(save_button, &QPushButton::clicked, this, &Logger::saveLog);
53
	auto *clear_button = new QPushButton(getIcon("edit-clear-all"), tr("C&lear"));
Michael Reisecker's avatar
Michael Reisecker committed
54
	connect(clear_button, &QPushButton::clicked, this, &Logger::clearLog);
55
	clear_button->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
Michael Reisecker's avatar
Michael Reisecker committed
56
57

	/* layout of the buttons */
58
59
60
61
62
63
64
65
66
67
68
69
70
71
	auto *button_layout = new QHBoxLayout; //two buttons on the left
	auto *left_frame = new QFrame;
	auto *left_layout = new QHBoxLayout;
	left_layout->setContentsMargins(0, 0, 0, 0);
	left_layout->addWidget(close_button);
	left_layout->addWidget(clear_button);
	left_frame->setLayout(left_layout);
	button_layout->addWidget(left_frame, 0, Qt::AlignLeft);
	auto *right_frame = new QFrame; //one button on the right
	auto *right_layout = new QHBoxLayout;
	right_layout->setContentsMargins(0, 0, 0, 0);
	right_layout->addWidget(save_button);
	right_frame->setLayout(right_layout);
	button_layout->addWidget(right_frame, 0, Qt::AlignRight);
72

73
	/* main layout */
Michael Reisecker's avatar
Michael Reisecker committed
74
75
76
	auto *log_layout = new QVBoxLayout;
	log_layout->addWidget(loglist_);
	log_layout->addLayout(button_layout);
77
78
	this->setLayout(log_layout);

79
	this->setWindowTitle(tr("Log Messages") + " ~ " + QCoreApplication::applicationName());
80
	this->setWindowFlags(Qt::Dialog); //prevent double title bar on osX
81
82
}

83
84
85
86
/**
 * @brief Add a text message to the Logger window.
 * @param[in] message The log message.
 * @param[in] color Color of the log message.
87
 * @param[in] no_timestamp Set true to disable the timestamp for this message.
88
 */
89
void Logger::log(const QString &message, const QString &color, const bool &no_timestamp)
90
{
91
92
	const QString timestamp( QTime::currentTime().toString("[hh:mm:ss] ") );
	auto *msg = new QListWidgetItem((no_timestamp? QString() : timestamp) + message, loglist_);
93
	msg->setForeground(colors::getQColor(color));
94
95
	loglist_->setCurrentRow(loglist_->count() - 1); //move cursor to last msg
	loglist_->setCurrentRow(-1); //... but don't select
96
97
}

98
99
100
/**
 * @brief Log some system and Qt version info.
 */
101
102
void Logger::logSystemInfo()
{
103
	log(QDateTime::currentDateTime().toString("[yyyy-MM-dd hh:mm:ss] ") + QCoreApplication::applicationName() +
104
	    " " + QCoreApplication::applicationVersion(), "normal", true);
105
	log(tr("Running on ") + QSysInfo::prettyProductName() + ", " + QSysInfo::kernelVersion() + ", "
Michael Reisecker's avatar
Michael Reisecker committed
106
	    + QSysInfo::buildAbi() + tr("; built with Qt ") + QT_VERSION_STR);
107
108
}

109
110
111
112
113
114
115
/**
 * @brief Event listener for the ESC key.
 * @details Close the logger on pressing ESC.
 * @param event The key press event that is received.
 */
void Logger::keyPressEvent(QKeyEvent *event)
{
116
	if (event->key() == Qt::Key_Escape || keyToSequence(event) == QKeySequence::Close)
117
		this->close();
118
119
	else if (keyToSequence(event) == QKeySequence::Print)
		emit getMainWindow()->viewPreview();
120
121
}

122
/**
123
 * @brief Save button: save the log to a file.
124
 */
125
126
void Logger::saveLog()
{
127
128
129
	QString start_path(getSetting("auto::history::last_log_write", "path"));
	if (start_path.isEmpty())
		start_path = QDir::currentPath();
130
	const QString date = QDateTime::currentDateTime().toString(Qt::DateFormat::ISODate).replace(":", "-");
131
	const QString file_name = QFileDialog::getSaveFileName(this, tr("Save Log"), start_path + "/inishell_log_" + date + ".html",
132
	    tr("HTML files") + " (*.html *.htm);;" + tr("Text Files") + " (*.log *.txt *.dat);;" + tr("All Files") + " (*)", nullptr,
133
134
	    QFileDialog::DontUseNativeDialog); //native is all but smooth on GNOME
	//QTBUG: https://bugreports.qt.io/browse/QTBUG-67866?focusedCommentId=408617&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-408617
135
	if (file_name.isNull())
136
137
		return;

138
	/* open the file to save log to */
139
	QFile outfile(file_name);
140
141
	if (!outfile.open(QIODevice::WriteOnly | QIODevice::Text)) {
		Error(tr("Could not open file for writing"), QString(),
142
		    file_name + ":\n" + outfile.errorString());
143
144
145
146
		return;
	}
	QTextStream out_ss(&outfile);

147
	QFileInfo file_info(file_name);
148
149
150
151
	bool html = false;
	if (file_info.completeSuffix().toLower() == "html" || file_info.completeSuffix().toLower() == "htm")
		html = true;

152
	/* save as html or plain text */
153
154
	for (int ii = 0; ii < loglist_->count(); ++ii) {
		QString item_text = loglist_->item(ii)->text();
155
		if (html) { //use the Logger's entries' colors
156
157
158
159
160
161
			const QString color = loglist_->item(ii)->foreground().color().name();
			item_text = html::color(item_text, color);
		}
		out_ss << item_text << (html? "<br>" : "\n");
	}
	outfile.close();
162
	setSetting("auto::history::last_log_write", "path", file_info.absoluteDir().path());
163
164
}

165
/**
166
 * @brief Close button: close the window.
167
168
 * @details The window is closed but stays in scope.
 */
169
170
171
172
void Logger::closeLogger()
{
	this->close();
}
Michael Reisecker's avatar
Michael Reisecker committed
173

174
175
176
/**
 * @brief Clear button: clear the log.
 */
Michael Reisecker's avatar
Michael Reisecker committed
177
178
179
void Logger::clearLog()
{
	loglist_->clear();
180
	topStatus(QString());
Michael Reisecker's avatar
Michael Reisecker committed
181
}