mirror of
https://github.com/YACReader/yacreader
synced 2025-07-18 13:04:28 -04:00
Update QsLog to 2.1 snapshot 46b643d5bcbc
This commit is contained in:
277
third_party/QsLog/QsLogWindow.cpp
vendored
Normal file
277
third_party/QsLog/QsLogWindow.cpp
vendored
Normal file
@ -0,0 +1,277 @@
|
||||
// Copyright (c) 2015, Axel Gembe <axel@gembe.net>
|
||||
// All rights reserved.
|
||||
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
|
||||
// * Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice, this
|
||||
// list of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
// * The name of the contributors may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
// OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "QsLogWindow.h"
|
||||
#include "QsLogWindowModel.h"
|
||||
#include "QsLog.h"
|
||||
#include "QsLogMessage.h"
|
||||
#include "ui_QsLogWindow.h"
|
||||
|
||||
#include <QIcon>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QClipboard>
|
||||
#include <QKeyEvent>
|
||||
#include <QFileDialog>
|
||||
#include <QtGlobal>
|
||||
#include <cstddef>
|
||||
|
||||
static const QIcon& pauseIcon()
|
||||
{
|
||||
static QIcon icon(QString::fromLatin1(":/QsLogWindow/images/icon-pause-16.png"));
|
||||
return icon;
|
||||
}
|
||||
|
||||
static const QIcon& playIcon()
|
||||
{
|
||||
static QIcon icon(QString::fromLatin1(":/QsLogWindow/images/icon-resume-16.png"));
|
||||
return icon;
|
||||
}
|
||||
|
||||
|
||||
class QsLogging::WindowLogFilterProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
WindowLogFilterProxyModel(Level level, QObject* parent = 0)
|
||||
: QSortFilterProxyModel(parent)
|
||||
, mLevel(level)
|
||||
, mLastVisibleRow(0)
|
||||
{
|
||||
}
|
||||
|
||||
Level level() const
|
||||
{
|
||||
return mLevel;
|
||||
}
|
||||
|
||||
void setLevel(const Level level)
|
||||
{
|
||||
mLevel = level;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void setPaused(bool paused)
|
||||
{
|
||||
mLastVisibleRow = paused ? rowCount() : 0;
|
||||
if (!paused) {
|
||||
invalidateFilter();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
|
||||
{
|
||||
Q_UNUSED(source_parent);
|
||||
if (!mLastVisibleRow) {
|
||||
LogWindowModel* model = dynamic_cast<LogWindowModel*>(sourceModel());
|
||||
const LogMessage& d = model->at(source_row);
|
||||
return d.level >= mLevel;
|
||||
}
|
||||
|
||||
return source_row <= mLastVisibleRow;
|
||||
}
|
||||
|
||||
private:
|
||||
Level mLevel;
|
||||
int mLastVisibleRow;
|
||||
};
|
||||
|
||||
QsLogging::Window::Window(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, mUi(nullptr)
|
||||
, mProxyModel(nullptr)
|
||||
, mIsPaused(false)
|
||||
, mHasAutoScroll(true)
|
||||
{
|
||||
mUi.reset(new Ui::LogWindow());
|
||||
mUi->setupUi(this);
|
||||
|
||||
connect(mUi->toolButtonPause, SIGNAL(clicked()), SLOT(OnPauseClicked()));
|
||||
connect(mUi->toolButtonSave, SIGNAL(clicked()), SLOT(OnSaveClicked()));
|
||||
connect(mUi->toolButtonClear, SIGNAL(clicked()), SLOT(OnClearClicked()));
|
||||
connect(mUi->toolButtonCopy, SIGNAL(clicked()), SLOT(OnCopyClicked()));
|
||||
connect(mUi->comboBoxLevel, SIGNAL(currentIndexChanged(int)), SLOT(OnLevelChanged(int)));
|
||||
connect(mUi->checkBoxAutoScroll, SIGNAL(toggled(bool)), SLOT(OnAutoScrollChanged(bool)));
|
||||
connect(&mModel, SIGNAL(rowsInserted(const QModelIndex&, int, int)),
|
||||
SLOT(ModelRowsInserted(const QModelIndex&, int, int)));
|
||||
|
||||
// Install the sort / filter model
|
||||
mProxyModel.reset(new WindowLogFilterProxyModel(InfoLevel, this));
|
||||
mProxyModel->setSourceModel(&mModel);
|
||||
mUi->tableViewMessages->setModel(mProxyModel.get());
|
||||
|
||||
mUi->tableViewMessages->installEventFilter(this);
|
||||
|
||||
mUi->tableViewMessages->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
#if QT_VERSION >= 0x050000
|
||||
mUi->tableViewMessages->horizontalHeader()->setSectionResizeMode(LogWindowModel::TimeColumn, QHeaderView::ResizeToContents);
|
||||
mUi->tableViewMessages->horizontalHeader()->setSectionResizeMode(LogWindowModel::LevelNameColumn, QHeaderView::ResizeToContents);
|
||||
mUi->tableViewMessages->horizontalHeader()->setSectionResizeMode(LogWindowModel::MessageColumn, QHeaderView::Stretch);
|
||||
mUi->tableViewMessages->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
#else
|
||||
mUi->tableViewMessages->horizontalHeader()->setResizeMode(LogWindowModel::TimeColumn, QHeaderView::ResizeToContents);
|
||||
mUi->tableViewMessages->horizontalHeader()->setResizeMode(LogWindowModel::LevelNameColumn, QHeaderView::ResizeToContents);
|
||||
mUi->tableViewMessages->horizontalHeader()->setResizeMode(LogWindowModel::MessageColumn, QHeaderView::Stretch);
|
||||
mUi->tableViewMessages->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
|
||||
#endif
|
||||
|
||||
// Initialize log level selection
|
||||
for (int l = TraceLevel; l < OffLevel; l++) {
|
||||
const QString ln = LocalizedLevelName(static_cast<Level>(l));
|
||||
mUi->comboBoxLevel->addItem(ln, l);
|
||||
}
|
||||
mUi->comboBoxLevel->setCurrentIndex(InfoLevel);
|
||||
}
|
||||
|
||||
QsLogging::Window::~Window() noexcept = default;
|
||||
|
||||
bool QsLogging::Window::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
if (obj == mUi->tableViewMessages) {
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
|
||||
if (keyEvent->key() == Qt::Key_C && (keyEvent->modifiers() & Qt::ControlModifier)) {
|
||||
copySelection();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
return QDialog::eventFilter(obj, event);
|
||||
}
|
||||
}
|
||||
|
||||
void QsLogging::Window::addLogMessage(const QsLogging::LogMessage &m)
|
||||
{
|
||||
mModel.addEntry(m);
|
||||
}
|
||||
|
||||
void QsLogging::Window::OnPauseClicked()
|
||||
{
|
||||
mUi->toolButtonPause->setIcon(mIsPaused ? pauseIcon() : playIcon());
|
||||
mUi->toolButtonPause->setText(mIsPaused ? tr("&Pause") : tr("&Resume"));
|
||||
|
||||
mIsPaused = !mIsPaused;
|
||||
|
||||
mProxyModel->setPaused(mIsPaused);
|
||||
}
|
||||
|
||||
void QsLogging::Window::OnSaveClicked()
|
||||
{
|
||||
saveSelection();
|
||||
}
|
||||
|
||||
void QsLogging::Window::OnClearClicked()
|
||||
{
|
||||
mModel.clear();
|
||||
}
|
||||
|
||||
void QsLogging::Window::OnCopyClicked()
|
||||
{
|
||||
copySelection();
|
||||
}
|
||||
|
||||
void QsLogging::Window::OnLevelChanged(int value)
|
||||
{
|
||||
mProxyModel->setLevel(static_cast<Level>(value));
|
||||
}
|
||||
|
||||
void QsLogging::Window::OnAutoScrollChanged(bool checked)
|
||||
{
|
||||
mHasAutoScroll = checked;
|
||||
}
|
||||
|
||||
void QsLogging::Window::ModelRowsInserted(const QModelIndex& parent, int start, int last)
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
Q_UNUSED(start);
|
||||
Q_UNUSED(last);
|
||||
if (mHasAutoScroll && !mIsPaused) {
|
||||
mUi->tableViewMessages->scrollToBottom();
|
||||
}
|
||||
}
|
||||
|
||||
void QsLogging::Window::copySelection() const
|
||||
{
|
||||
const QString text = getSelectionText();
|
||||
if (text.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QApplication::clipboard()->setText(text);
|
||||
}
|
||||
|
||||
void QsLogging::Window::saveSelection()
|
||||
{
|
||||
const QString text = getSelectionText();
|
||||
if (text.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QFileDialog dialog(this);
|
||||
dialog.setWindowTitle(tr("Save log"));
|
||||
dialog.setNameFilter(tr("Log file (*.log)"));
|
||||
dialog.setAcceptMode(QFileDialog::AcceptSave);
|
||||
dialog.setDefaultSuffix("log");
|
||||
dialog.exec();
|
||||
|
||||
const QStringList sel = dialog.selectedFiles();
|
||||
if (sel.size() < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
QFile file(sel.at(0));
|
||||
if (file.open(QIODevice::WriteOnly)) {
|
||||
QTextStream stream(&file);
|
||||
stream << text;
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
QString QsLogging::Window::getSelectionText() const
|
||||
{
|
||||
QModelIndexList rows = mUi->tableViewMessages->selectionModel()->selectedRows();
|
||||
std::sort(rows.begin(), rows.end());
|
||||
|
||||
QString text;
|
||||
|
||||
if (rows.count() == 0) {
|
||||
for (int i = 0; i < mProxyModel->rowCount(); i++) {
|
||||
const int srow = mProxyModel->mapToSource(mProxyModel->index(i, 0)).row();
|
||||
text += mModel.at(srow).formatted + "\n";
|
||||
}
|
||||
} else {
|
||||
for (QModelIndexList::const_iterator i = rows.begin();i != rows.end();++i) {
|
||||
const int srow = mProxyModel->mapToSource(*i).row();
|
||||
text += mModel.at(srow).formatted + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
#include "QsLogWindow.moc"
|
Reference in New Issue
Block a user