mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-10 23:07:59 +00:00
Merge pull request #10366 from Chocobo1/logger
Avoid performance penalty when logger is full
This commit is contained in:
commit
d1b0c230ed
@ -149,8 +149,10 @@ Application::Application(const QString &id, int &argc, char **argv)
|
|||||||
#if !defined(DISABLE_GUI)
|
#if !defined(DISABLE_GUI)
|
||||||
setAttribute(Qt::AA_UseHighDpiPixmaps, true); // opt-in to the high DPI pixmap support
|
setAttribute(Qt::AA_UseHighDpiPixmaps, true); // opt-in to the high DPI pixmap support
|
||||||
setQuitOnLastWindowClosed(false);
|
setQuitOnLastWindowClosed(false);
|
||||||
|
#if !defined(Q_OS_WIN)
|
||||||
setDesktopFileName("org.qbittorrent.qBittorrent");
|
setDesktopFileName("org.qbittorrent.qBittorrent");
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_WIN) && !defined(DISABLE_GUI)
|
#if defined(Q_OS_WIN) && !defined(DISABLE_GUI)
|
||||||
connect(this, &QGuiApplication::commitDataRequest, this, &Application::shutdownCleanup, Qt::DirectConnection);
|
connect(this, &QGuiApplication::commitDataRequest, this, &Application::shutdownCleanup, Qt::DirectConnection);
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
|
|
||||||
#include "base/global.h"
|
#include "base/global.h"
|
||||||
@ -40,7 +39,6 @@
|
|||||||
FileLogger::FileLogger(const QString &path, const bool backup, const int maxSize, const bool deleteOld, const int age, const FileLogAgeType ageType)
|
FileLogger::FileLogger(const QString &path, const bool backup, const int maxSize, const bool deleteOld, const int age, const FileLogAgeType ageType)
|
||||||
: m_backup(backup)
|
: m_backup(backup)
|
||||||
, m_maxSize(maxSize)
|
, m_maxSize(maxSize)
|
||||||
, m_logFile(nullptr)
|
|
||||||
{
|
{
|
||||||
m_flusher.setInterval(0);
|
m_flusher.setInterval(0);
|
||||||
m_flusher.setSingleShot(true);
|
m_flusher.setSingleShot(true);
|
||||||
@ -59,26 +57,20 @@ FileLogger::FileLogger(const QString &path, const bool backup, const int maxSize
|
|||||||
|
|
||||||
FileLogger::~FileLogger()
|
FileLogger::~FileLogger()
|
||||||
{
|
{
|
||||||
if (!m_logFile) return;
|
|
||||||
closeLogFile();
|
closeLogFile();
|
||||||
delete m_logFile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileLogger::changePath(const QString &newPath)
|
void FileLogger::changePath(const QString &newPath)
|
||||||
{
|
{
|
||||||
QString tmpPath = Utils::Fs::fromNativePath(newPath);
|
const QDir dir(newPath);
|
||||||
QDir dir(tmpPath);
|
dir.mkpath(newPath);
|
||||||
dir.mkpath(tmpPath);
|
const QString tmpPath = dir.absoluteFilePath("qbittorrent.log");
|
||||||
tmpPath = dir.absoluteFilePath("qbittorrent.log");
|
|
||||||
|
|
||||||
if (tmpPath != m_path) {
|
if (tmpPath != m_path) {
|
||||||
m_path = tmpPath;
|
m_path = tmpPath;
|
||||||
|
|
||||||
if (m_logFile) {
|
closeLogFile();
|
||||||
closeLogFile();
|
m_logFile.setFileName(m_path);
|
||||||
delete m_logFile;
|
|
||||||
}
|
|
||||||
m_logFile = new QFile(m_path);
|
|
||||||
openLogFile();
|
openLogFile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,8 +79,10 @@ void FileLogger::deleteOld(const int age, const FileLogAgeType ageType)
|
|||||||
{
|
{
|
||||||
const QDateTime date = QDateTime::currentDateTime();
|
const QDateTime date = QDateTime::currentDateTime();
|
||||||
const QDir dir(Utils::Fs::branchPath(m_path));
|
const QDir dir(Utils::Fs::branchPath(m_path));
|
||||||
|
const QFileInfoList fileList = dir.entryInfoList(QStringList("qbittorrent.log.bak*")
|
||||||
|
, (QDir::Files | QDir::Writable), (QDir::Time | QDir::Reversed));
|
||||||
|
|
||||||
for (const QFileInfo &file : asConst(dir.entryInfoList(QStringList("qbittorrent.log.bak*"), QDir::Files | QDir::Writable, QDir::Time | QDir::Reversed))) {
|
for (const QFileInfo &file : fileList) {
|
||||||
QDateTime modificationDate = file.lastModified();
|
QDateTime modificationDate = file.lastModified();
|
||||||
switch (ageType) {
|
switch (ageType) {
|
||||||
case DAYS:
|
case DAYS:
|
||||||
@ -106,7 +100,7 @@ void FileLogger::deleteOld(const int age, const FileLogAgeType ageType)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileLogger::setBackup(bool value)
|
void FileLogger::setBackup(const bool value)
|
||||||
{
|
{
|
||||||
m_backup = value;
|
m_backup = value;
|
||||||
}
|
}
|
||||||
@ -118,9 +112,9 @@ void FileLogger::setMaxSize(const int value)
|
|||||||
|
|
||||||
void FileLogger::addLogMessage(const Log::Msg &msg)
|
void FileLogger::addLogMessage(const Log::Msg &msg)
|
||||||
{
|
{
|
||||||
if (!m_logFile) return;
|
if (!m_logFile.isOpen()) return;
|
||||||
|
|
||||||
QTextStream str(m_logFile);
|
QTextStream str(&m_logFile);
|
||||||
|
|
||||||
switch (msg.type) {
|
switch (msg.type) {
|
||||||
case Log::INFO:
|
case Log::INFO:
|
||||||
@ -138,7 +132,7 @@ void FileLogger::addLogMessage(const Log::Msg &msg)
|
|||||||
|
|
||||||
str << QDateTime::fromMSecsSinceEpoch(msg.timestamp).toString(Qt::ISODate) << " - " << msg.message << endl;
|
str << QDateTime::fromMSecsSinceEpoch(msg.timestamp).toString(Qt::ISODate) << " - " << msg.message << endl;
|
||||||
|
|
||||||
if (m_backup && (m_logFile->size() >= m_maxSize)) {
|
if (m_backup && (m_logFile.size() >= m_maxSize)) {
|
||||||
closeLogFile();
|
closeLogFile();
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
QString backupLogFilename = m_path + ".bak";
|
QString backupLogFilename = m_path + ".bak";
|
||||||
@ -158,22 +152,21 @@ void FileLogger::addLogMessage(const Log::Msg &msg)
|
|||||||
|
|
||||||
void FileLogger::flushLog()
|
void FileLogger::flushLog()
|
||||||
{
|
{
|
||||||
if (m_logFile)
|
if (m_logFile.isOpen())
|
||||||
m_logFile->flush();
|
m_logFile.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileLogger::openLogFile()
|
void FileLogger::openLogFile()
|
||||||
{
|
{
|
||||||
if (!m_logFile->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)
|
if (!m_logFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)
|
||||||
|| !m_logFile->setPermissions(QFile::ReadOwner | QFile::WriteOwner)) {
|
|| !m_logFile.setPermissions(QFile::ReadOwner | QFile::WriteOwner)) {
|
||||||
delete m_logFile;
|
m_logFile.close();
|
||||||
m_logFile = nullptr;
|
LogMsg(tr("An error occurred while trying to open the log file. Logging to file is disabled."), Log::CRITICAL);
|
||||||
Logger::instance()->addMessage(tr("An error occurred while trying to open the log file. Logging to file is disabled."), Log::CRITICAL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileLogger::closeLogFile()
|
void FileLogger::closeLogFile()
|
||||||
{
|
{
|
||||||
m_flusher.stop();
|
m_flusher.stop();
|
||||||
m_logFile->close();
|
m_logFile.close();
|
||||||
}
|
}
|
||||||
|
@ -29,11 +29,10 @@
|
|||||||
#ifndef FILELOGGER_H
|
#ifndef FILELOGGER_H
|
||||||
#define FILELOGGER_H
|
#define FILELOGGER_H
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
class QFile;
|
|
||||||
|
|
||||||
namespace Log
|
namespace Log
|
||||||
{
|
{
|
||||||
struct Msg;
|
struct Msg;
|
||||||
@ -71,7 +70,7 @@ private:
|
|||||||
QString m_path;
|
QString m_path;
|
||||||
bool m_backup;
|
bool m_backup;
|
||||||
int m_maxSize;
|
int m_maxSize;
|
||||||
QFile *m_logFile;
|
QFile m_logFile;
|
||||||
QTimer m_flusher;
|
QTimer m_flusher;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,20 +28,31 @@
|
|||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include "base/utils/string.h"
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
QVector<T> loadFromBuffer(const boost::circular_buffer_space_optimized<T> &src, const int offset = 0)
|
||||||
|
{
|
||||||
|
QVector<T> ret;
|
||||||
|
ret.reserve(src.size() - offset);
|
||||||
|
std::copy((src.begin() + offset), src.end(), std::back_inserter(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Logger *Logger::m_instance = nullptr;
|
Logger *Logger::m_instance = nullptr;
|
||||||
|
|
||||||
Logger::Logger()
|
Logger::Logger()
|
||||||
: m_lock(QReadWriteLock::Recursive)
|
: m_messages(MAX_LOG_MESSAGES)
|
||||||
, m_msgCounter(0)
|
, m_peers(MAX_LOG_MESSAGES)
|
||||||
, m_peerCounter(0)
|
, m_lock(QReadWriteLock::Recursive)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger::~Logger() {}
|
|
||||||
|
|
||||||
Logger *Logger::instance()
|
Logger *Logger::instance()
|
||||||
{
|
{
|
||||||
return m_instance;
|
return m_instance;
|
||||||
@ -68,9 +79,6 @@ void Logger::addMessage(const QString &message, const Log::MsgType &type)
|
|||||||
const Log::Msg temp = {m_msgCounter++, QDateTime::currentMSecsSinceEpoch(), type, message.toHtmlEscaped()};
|
const Log::Msg temp = {m_msgCounter++, QDateTime::currentMSecsSinceEpoch(), type, message.toHtmlEscaped()};
|
||||||
m_messages.push_back(temp);
|
m_messages.push_back(temp);
|
||||||
|
|
||||||
if (m_messages.size() >= MAX_LOG_MESSAGES)
|
|
||||||
m_messages.pop_front();
|
|
||||||
|
|
||||||
emit newLogMessage(temp);
|
emit newLogMessage(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,9 +89,6 @@ void Logger::addPeer(const QString &ip, const bool blocked, const QString &reaso
|
|||||||
const Log::Peer temp = {m_peerCounter++, QDateTime::currentMSecsSinceEpoch(), ip.toHtmlEscaped(), blocked, reason.toHtmlEscaped()};
|
const Log::Peer temp = {m_peerCounter++, QDateTime::currentMSecsSinceEpoch(), ip.toHtmlEscaped(), blocked, reason.toHtmlEscaped()};
|
||||||
m_peers.push_back(temp);
|
m_peers.push_back(temp);
|
||||||
|
|
||||||
if (m_peers.size() >= MAX_LOG_MESSAGES)
|
|
||||||
m_peers.pop_front();
|
|
||||||
|
|
||||||
emit newLogPeer(temp);
|
emit newLogPeer(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,12 +100,12 @@ QVector<Log::Msg> Logger::getMessages(const int lastKnownId) const
|
|||||||
const int size = m_messages.size();
|
const int size = m_messages.size();
|
||||||
|
|
||||||
if ((lastKnownId == -1) || (diff >= size))
|
if ((lastKnownId == -1) || (diff >= size))
|
||||||
return m_messages;
|
return loadFromBuffer(m_messages);
|
||||||
|
|
||||||
if (diff <= 0)
|
if (diff <= 0)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
return m_messages.mid(size - diff);
|
return loadFromBuffer(m_messages, (size - diff));
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<Log::Peer> Logger::getPeers(const int lastKnownId) const
|
QVector<Log::Peer> Logger::getPeers(const int lastKnownId) const
|
||||||
@ -111,12 +116,12 @@ QVector<Log::Peer> Logger::getPeers(const int lastKnownId) const
|
|||||||
const int size = m_peers.size();
|
const int size = m_peers.size();
|
||||||
|
|
||||||
if ((lastKnownId == -1) || (diff >= size))
|
if ((lastKnownId == -1) || (diff >= size))
|
||||||
return m_peers;
|
return loadFromBuffer(m_peers);
|
||||||
|
|
||||||
if (diff <= 0)
|
if (diff <= 0)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
return m_peers.mid(size - diff);
|
return loadFromBuffer(m_peers, (size - diff));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogMsg(const QString &message, const Log::MsgType &type)
|
void LogMsg(const QString &message, const Log::MsgType &type)
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
#ifndef LOGGER_H
|
#ifndef LOGGER_H
|
||||||
#define LOGGER_H
|
#define LOGGER_H
|
||||||
|
|
||||||
|
#include <boost/circular_buffer.hpp>
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QReadWriteLock>
|
#include <QReadWriteLock>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
@ -89,14 +91,14 @@ signals:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Logger();
|
Logger();
|
||||||
~Logger();
|
~Logger() = default;
|
||||||
|
|
||||||
static Logger *m_instance;
|
static Logger *m_instance;
|
||||||
QVector<Log::Msg> m_messages;
|
boost::circular_buffer_space_optimized<Log::Msg> m_messages;
|
||||||
QVector<Log::Peer> m_peers;
|
boost::circular_buffer_space_optimized<Log::Peer> m_peers;
|
||||||
mutable QReadWriteLock m_lock;
|
mutable QReadWriteLock m_lock;
|
||||||
int m_msgCounter;
|
int m_msgCounter = 0;
|
||||||
int m_peerCounter;
|
int m_peerCounter = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper function
|
// Helper function
|
||||||
|
@ -40,8 +40,8 @@
|
|||||||
ExecutionLogWidget::ExecutionLogWidget(QWidget *parent, const Log::MsgTypes &types)
|
ExecutionLogWidget::ExecutionLogWidget(QWidget *parent, const Log::MsgTypes &types)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, m_ui(new Ui::ExecutionLogWidget)
|
, m_ui(new Ui::ExecutionLogWidget)
|
||||||
, m_msgList(new LogListWidget(MAX_LOG_MESSAGES, Log::MsgTypes(types)))
|
, m_msgList(new LogListWidget(MAX_LOG_MESSAGES, types, this))
|
||||||
, m_peerList(new LogListWidget(MAX_LOG_MESSAGES))
|
, m_peerList(new LogListWidget(MAX_LOG_MESSAGES, Log::ALL, this))
|
||||||
{
|
{
|
||||||
m_ui->setupUi(this);
|
m_ui->setupUi(this);
|
||||||
|
|
||||||
@ -63,8 +63,6 @@ ExecutionLogWidget::ExecutionLogWidget(QWidget *parent, const Log::MsgTypes &typ
|
|||||||
|
|
||||||
ExecutionLogWidget::~ExecutionLogWidget()
|
ExecutionLogWidget::~ExecutionLogWidget()
|
||||||
{
|
{
|
||||||
delete m_msgList;
|
|
||||||
delete m_peerList;
|
|
||||||
delete m_ui;
|
delete m_ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,38 +73,35 @@ void ExecutionLogWidget::showMsgTypes(const Log::MsgTypes &types)
|
|||||||
|
|
||||||
void ExecutionLogWidget::addLogMessage(const Log::Msg &msg)
|
void ExecutionLogWidget::addLogMessage(const Log::Msg &msg)
|
||||||
{
|
{
|
||||||
QString text;
|
QString colorName;
|
||||||
QDateTime time = QDateTime::fromMSecsSinceEpoch(msg.timestamp);
|
|
||||||
QColor color;
|
|
||||||
|
|
||||||
switch (msg.type) {
|
switch (msg.type) {
|
||||||
case Log::INFO:
|
case Log::INFO:
|
||||||
color.setNamedColor("blue");
|
colorName = QLatin1String("blue");
|
||||||
break;
|
break;
|
||||||
case Log::WARNING:
|
case Log::WARNING:
|
||||||
color.setNamedColor("orange");
|
colorName = QLatin1String("orange");
|
||||||
break;
|
break;
|
||||||
case Log::CRITICAL:
|
case Log::CRITICAL:
|
||||||
color.setNamedColor("red");
|
colorName = QLatin1String("red");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
color = QApplication::palette().color(QPalette::WindowText);
|
colorName = QApplication::palette().color(QPalette::WindowText).name();
|
||||||
}
|
}
|
||||||
|
|
||||||
text = "<font color='grey'>" + time.toString(Qt::SystemLocaleShortDate) + "</font> - <font color='" + color.name() + "'>" + msg.message + "</font>";
|
const QDateTime time = QDateTime::fromMSecsSinceEpoch(msg.timestamp);
|
||||||
|
const QString text = QString(QLatin1String("<font color='grey'>%1</font> - <font color='%2'>%3</font>"))
|
||||||
|
.arg(time.toString(Qt::SystemLocaleShortDate), colorName, msg.message);
|
||||||
m_msgList->appendLine(text, msg.type);
|
m_msgList->appendLine(text, msg.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecutionLogWidget::addPeerMessage(const Log::Peer &peer)
|
void ExecutionLogWidget::addPeerMessage(const Log::Peer &peer)
|
||||||
{
|
{
|
||||||
QString text;
|
const QDateTime time = QDateTime::fromMSecsSinceEpoch(peer.timestamp);
|
||||||
QDateTime time = QDateTime::fromMSecsSinceEpoch(peer.timestamp);
|
const QString msg = QString(QLatin1String("<font color='grey'>%1</font> - <font color='red'>%2</font>"))
|
||||||
|
.arg(time.toString(Qt::SystemLocaleShortDate), peer.ip);
|
||||||
if (peer.blocked)
|
|
||||||
text = "<font color='grey'>" + time.toString(Qt::SystemLocaleShortDate) + "</font> - "
|
|
||||||
+ tr("<font color='red'>%1</font> was blocked %2", "x.y.z.w was blocked").arg(peer.ip, peer.reason);
|
|
||||||
else
|
|
||||||
text = "<font color='grey'>" + time.toString(Qt::SystemLocaleShortDate) + "</font> - " + tr("<font color='red'>%1</font> was banned", "x.y.z.w was banned").arg(peer.ip);
|
|
||||||
|
|
||||||
|
const QString text = peer.blocked
|
||||||
|
? tr("%1 was blocked %2", "0.0.0.0 was blocked due to reason").arg(msg, peer.reason)
|
||||||
|
: tr("%1 was banned", "0.0.0.0 was banned").arg(msg);
|
||||||
m_peerList->appendLine(text, Log::NORMAL);
|
m_peerList->appendLine(text, Log::NORMAL);
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,6 @@
|
|||||||
<height>300</height>
|
<height>300</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
|
||||||
<string notr="true">Form</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
#include "base/global.h"
|
#include "base/global.h"
|
||||||
#include "guiiconprovider.h"
|
#include "guiiconprovider.h"
|
||||||
|
|
||||||
LogListWidget::LogListWidget(int maxLines, const Log::MsgTypes &types, QWidget *parent)
|
LogListWidget::LogListWidget(const int maxLines, const Log::MsgTypes &types, QWidget *parent)
|
||||||
: QListWidget(parent)
|
: QListWidget(parent)
|
||||||
, m_maxLines(maxLines)
|
, m_maxLines(maxLines)
|
||||||
, m_types(types)
|
, m_types(types)
|
||||||
@ -47,8 +47,8 @@ LogListWidget::LogListWidget(int maxLines, const Log::MsgTypes &types, QWidget *
|
|||||||
// Allow multiple selections
|
// Allow multiple selections
|
||||||
setSelectionMode(QAbstractItemView::ExtendedSelection);
|
setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
// Context menu
|
// Context menu
|
||||||
QAction *copyAct = new QAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy"), this);
|
auto *copyAct = new QAction(GuiIconProvider::instance()->getIcon("edit-copy"), tr("Copy"), this);
|
||||||
QAction *clearAct = new QAction(GuiIconProvider::instance()->getIcon("edit-clear"), tr("Clear"), this);
|
auto *clearAct = new QAction(GuiIconProvider::instance()->getIcon("edit-clear"), tr("Clear"), this);
|
||||||
connect(copyAct, &QAction::triggered, this, &LogListWidget::copySelection);
|
connect(copyAct, &QAction::triggered, this, &LogListWidget::copySelection);
|
||||||
connect(clearAct, &QAction::triggered, this, &LogListWidget::clear);
|
connect(clearAct, &QAction::triggered, this, &LogListWidget::clear);
|
||||||
addAction(copyAct);
|
addAction(copyAct);
|
||||||
@ -78,10 +78,12 @@ void LogListWidget::keyPressEvent(QKeyEvent *event)
|
|||||||
|
|
||||||
void LogListWidget::appendLine(const QString &line, const Log::MsgType &type)
|
void LogListWidget::appendLine(const QString &line, const Log::MsgType &type)
|
||||||
{
|
{
|
||||||
auto *item = new QListWidgetItem;
|
|
||||||
// We need to use QLabel here to support rich text
|
// We need to use QLabel here to support rich text
|
||||||
QLabel *lbl = new QLabel(line);
|
auto *lbl = new QLabel(line);
|
||||||
|
lbl->setTextFormat(Qt::RichText);
|
||||||
lbl->setContentsMargins(4, 2, 4, 2);
|
lbl->setContentsMargins(4, 2, 4, 2);
|
||||||
|
|
||||||
|
auto *item = new QListWidgetItem;
|
||||||
item->setSizeHint(lbl->sizeHint());
|
item->setSizeHint(lbl->sizeHint());
|
||||||
item->setData(Qt::UserRole, type);
|
item->setData(Qt::UserRole, type);
|
||||||
insertItem(0, item);
|
insertItem(0, item);
|
||||||
@ -96,9 +98,10 @@ void LogListWidget::appendLine(const QString &line, const Log::MsgType &type)
|
|||||||
|
|
||||||
void LogListWidget::copySelection()
|
void LogListWidget::copySelection()
|
||||||
{
|
{
|
||||||
static const QRegularExpression htmlTag("<[^>]+>");
|
const QRegularExpression htmlTag("<[^>]+>");
|
||||||
|
|
||||||
QStringList strings;
|
QStringList strings;
|
||||||
for (QListWidgetItem* it : asConst(selectedItems()))
|
for (QListWidgetItem *it : asConst(selectedItems()))
|
||||||
strings << static_cast<QLabel*>(itemWidget(it))->text().remove(htmlTag);
|
strings << static_cast<QLabel*>(itemWidget(it))->text().remove(htmlTag);
|
||||||
|
|
||||||
QApplication::clipboard()->setText(strings.join('\n'));
|
QApplication::clipboard()->setText(strings.join('\n'));
|
||||||
|
@ -53,7 +53,7 @@ protected:
|
|||||||
void keyPressEvent(QKeyEvent *event) override;
|
void keyPressEvent(QKeyEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_maxLines;
|
const int m_maxLines;
|
||||||
Log::MsgTypes m_types;
|
Log::MsgTypes m_types;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user