test_sdk/gui/gtl_gui_log_viewer.cpp

619 lines
22 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "gtl_gui_log_viewer.h"
#include <QHeaderView>
#include <QLayout>
#include <QLabel>
#include <QSpacerItem>
#include <QSpinBox>
#include <QMessageBox>
namespace gtl
{
namespace gui
{
/* * * * * * * * * * * * * * * * * * * * * * * * * *
*
* log_viewer
*/
log_viewer::log_viewer(QWidget *parent)
: QWidget{parent}
{
QVBoxLayout* mainLayout = new QVBoxLayout;
setLayout( mainLayout );
m_view = new MyTableVeiw(this);
m_view->verticalHeader()->setVisible(false);
m_view->setAutoScroll(false);
m_view->verticalHeader()->setDefaultSectionSize(5);
m_view->setSelectionMode(QAbstractItemView::ContiguousSelection);
// * * * * * * * * * * * * * * *
// * change color of selected cell
const QColor hlClr = Qt::white; // highlight color to set
const QColor txtClr = Qt::black; // highlighted text color to set
QPalette p = palette();
p.setColor(QPalette::Highlight, hlClr);
p.setColor(QPalette::HighlightedText, txtClr);
setPalette(p);
connect(m_view, &QTableView::clicked, this, &log_viewer::slt_table_click);
connect(m_view->verticalScrollBar(), &QScrollBar::rangeChanged, this, &log_viewer::slt_set_scroll_range);
connect(m_view->verticalScrollBar(), &QScrollBar::valueChanged, this, &log_viewer::slt_set_scroll_value);
m_model = new log_viewer_model(this);
connect(gtl::logger::getInstance(), &gtl::logger::sgn_send_to_viewer, m_model, &log_viewer_model::slt_append_string);
m_proxy_model = new filter_proxy_model(this);
m_proxy_model->setSourceModel(m_model);
m_view->setModel(m_proxy_model);
m_view->horizontalHeader()->setSectionResizeMode(4, QHeaderView::Stretch);
connect(m_model, &QAbstractTableModel::rowsAboutToBeInserted, this, &log_viewer::slt_rows_about_to_be_inserted);
connect(m_model, &QAbstractTableModel::rowsInserted, this, &log_viewer::slt_data_changed);
// * * * * * * * * * * * * * * *
// *
// * levels
// *
// * * * * * * * * * * * * * * *
m_cbb_level = new QComboBox();
connect(m_cbb_level, &QComboBox::currentIndexChanged, this, &log_viewer::slt_check_levels);
m_cbb_level->addItem("info");
m_cbb_level->addItem("warning");
m_cbb_level->addItem("error");
m_cbb_level->addItem("debug");
// * * * * * * * * * * * * * * *
// *
// * searc text
// *
// * * * * * * * * * * * * * * *
m_le_search_string = new QLineEdit();
m_le_search_string->setClearButtonEnabled(true);
m_le_search_string->setPlaceholderText("Search text ...");
connect(m_le_search_string, &QLineEdit::textChanged, this, &log_viewer::slt_update_search_string);
// * * * * * * * * * * * * * * *
// *
// * date time filter
// *
// * * * * * * * * * * * * * * *
QHBoxLayout* hl_date_time = new QHBoxLayout;
m_le_dt_from = new QLineEdit();
m_le_dt_from->setClearButtonEnabled(true);
m_action_le_dt_from = m_le_dt_from->addAction(this->style()->standardIcon(QStyle::SP_TitleBarNormalButton), QLineEdit::LeadingPosition);
m_le_dt_from->setPlaceholderText("from ...");
connect(m_action_le_dt_from, &QAction::triggered, this, &log_viewer::slt_dialog_set_datetime);
connect(m_le_dt_from, &QLineEdit::textChanged, this, &log_viewer::slt_update_dt);
m_le_dt_to = new QLineEdit();
m_le_dt_to->setClearButtonEnabled(true);
m_action_le_dt_to = m_le_dt_to->addAction(this->style()->standardIcon(QStyle::SP_TitleBarNormalButton), QLineEdit::LeadingPosition);
m_le_dt_to->setPlaceholderText("to ...");
connect(m_action_le_dt_to, &QAction::triggered, this, &log_viewer::slt_dialog_set_datetime);
connect(m_le_dt_to, &QLineEdit::textChanged, this, &log_viewer::slt_update_dt);
QLabel* l_date_time = new QLabel(" - ");
hl_date_time->addWidget(m_le_dt_from);
hl_date_time->addWidget(l_date_time);
hl_date_time->addWidget(m_le_dt_to);
// * * * * * * * * * * * * * * *
// *
// * btn reset search
// *
// * * * * * * * * * * * * * * *
m_b_reset_search = new QPushButton();
connect(m_b_reset_search, &QPushButton::clicked, this, &log_viewer::slt_reset_search);
m_b_reset_search->setText("Reset search");
// * * * * * * * * * * * * * * *
// *
// * btn clear data
// *
// * * * * * * * * * * * * * * *
m_b_clear_data = new QPushButton();
connect(m_b_clear_data, &QPushButton::clicked, [this]()
{
m_model->clear();
});
m_b_clear_data->setText("Clear");
QHBoxLayout* hl_common = new QHBoxLayout;
hl_common->addWidget(m_cbb_level);
hl_common->addWidget(m_le_search_string);
hl_common->addLayout(hl_date_time);
hl_common->addWidget(m_b_reset_search);
hl_common->addWidget(m_b_clear_data);
mainLayout->addLayout(hl_common);
mainLayout->addWidget(m_view);
}
void log_viewer::slt_check_levels(int index)
{
QString str_mass_filter = "";
switch(index)
{
case 0:
str_mass_filter += "INFO|WARNING|ERROR";
break;
case 1:
str_mass_filter += "WARNING|ERROR";
break;
case 2:
str_mass_filter += "ERROR";
break;
case 3:
str_mass_filter += "DEBUG";
break;
}
m_proxy_model->set_filter_level(str_mass_filter);
}
void log_viewer::slt_update_search_string(void)
{
if(m_le_search_string->text().isEmpty())
m_proxy_model->set_disable_search_string();
else
{
m_proxy_model->set_search_string(m_le_search_string->text());
m_proxy_model->set_enable_search_string();
}
}
void log_viewer::slt_reset_search(void)
{
m_le_search_string->setText("");
m_le_dt_from->setText("");
m_le_dt_to->setText("");
m_proxy_model->set_search_string("");
m_proxy_model->set_disable_search_string();
m_proxy_model->set_disable_date_filter();
}
void log_viewer::slt_dialog_set_datetime(void)
{
QAction *action_sender = (QAction *)sender();
QVBoxLayout* layout = new QVBoxLayout;
QTime timeNow = QTime::currentTime();
QSpacerItem *space_left = new QSpacerItem(10, 10, QSizePolicy::Expanding);
QSpacerItem *space_right = new QSpacerItem(10, 10, QSizePolicy::Expanding);
QLabel *l_hour = new QLabel(":");
QLabel *l_minute = new QLabel(":");
QSpinBox *hour = new QSpinBox();
hour->setMinimum(0);
hour->setMaximum(23);
hour->setValue(timeNow.hour());
QSpinBox *minute = new QSpinBox();
minute->setMinimum(0);
minute->setMaximum(59);
minute->setValue(timeNow.minute());
QSpinBox *second = new QSpinBox();
second->setMinimum(0);
second->setMaximum(59);
second->setValue(timeNow.second());
QHBoxLayout* layout_time = new QHBoxLayout;
layout_time->addSpacerItem(space_left);
layout_time->addWidget(hour);
layout_time->addWidget(l_hour);
layout_time->addWidget(minute);
layout_time->addWidget(l_minute);
layout_time->addWidget(second);
layout_time->addSpacerItem(space_right);
QPushButton *btn_ok = new QPushButton("&ОК");
btn_ok->setObjectName("btn_ok");
QPushButton *btn_cancel = new QPushButton("&Cancel");
btn_cancel->setObjectName("btn_cancel");
QHBoxLayout *layout_btn = new QHBoxLayout;
layout_btn->addWidget(btn_ok);
layout_btn->addWidget(btn_cancel);
m_calendar_widget = new QCalendarWidget(this);
layout->addWidget(m_calendar_widget);
layout->addLayout(layout_time);
layout->addLayout(layout_btn);
m_dialog_set_datetime = new QDialog(this);
m_dialog_set_datetime->setLayout(layout);
m_dialog_set_datetime->setWindowTitle("Select date and time");
connect(btn_ok, &QPushButton::clicked, m_dialog_set_datetime, &QDialog::accept);
connect(btn_cancel, &QPushButton::clicked, m_dialog_set_datetime, &QDialog::reject);
QString result_str;
if(m_dialog_set_datetime->exec() == QDialog::Accepted)
{
result_str = m_calendar_widget->selectedDate().toString("dd.MM.yyyy ") +
QString("%1:").arg(hour->value(), 2, 10, QLatin1Char('0')) +
QString("%1:").arg(minute->value(), 2, 10, QLatin1Char('0')) +
QString("%1").arg(second->value(), 2, 10, QLatin1Char('0'));
if(action_sender == m_action_le_dt_from)
m_le_dt_from->setText(result_str);
else if(action_sender == m_action_le_dt_to)
m_le_dt_to->setText(result_str);
}
}
void log_viewer::slt_update_dt(void)
{
if( (false == m_le_dt_from->text().isEmpty()) &&
(false == m_le_dt_to->text().isEmpty()) )
{
QDateTime dt_from = QDateTime::fromString(m_le_dt_from->text(), "dd.MM.yyyy hh:mm:ss");
QDateTime dt_to = QDateTime::fromString(m_le_dt_to->text(), "dd.MM.yyyy hh:mm:ss");
if(dt_from > dt_to)
{
QMessageBox::warning(this,
"Warning",
"Date From must be earlier than Date To",
QMessageBox::Ok,
QMessageBox::Ok );
m_proxy_model->set_disable_date_filter();
}
else
{
m_proxy_model->set_datetime_filter(dt_from, dt_to);
m_proxy_model->set_enable_date_filter();
}
}
else
m_proxy_model->set_disable_date_filter();
}
void log_viewer::slt_rows_about_to_be_inserted()
{
m_prev_index = m_view->currentIndex();
m_prev_value = m_view->verticalScrollBar()->value();
}
void log_viewer::slt_data_changed(void)
{
// this condition is necessary for the correct display of the last rows of the table
if((m_scroll_max - m_view->verticalScrollBar()->value()) > 4 )
m_view->scrollTo( m_prev_index, QAbstractItemView::PositionAtCenter );
else
m_view->scrollTo( m_prev_index, QAbstractItemView::PositionAtTop );
m_prev_value = m_view->verticalScrollBar()->value();
}
void log_viewer::slt_set_scroll_range(int min, int max)
{
m_scroll_min = min;
m_scroll_max = max;
}
void log_viewer::slt_table_click(const QModelIndex &index)
{
m_prev_index = index;
m_view->setCurrentIndex(index);
m_prev_value = m_view->verticalScrollBar()->value();
}
void log_viewer::slt_set_scroll_value()
{
int curr_value = m_view->verticalScrollBar()->value();
// if scroll in top position - then start autoscroll
if(curr_value == m_scroll_min)
{
m_prev_index = QModelIndex();
m_view->setCurrentIndex(m_prev_index);
m_prev_value = curr_value;
return;
}
// if not select cell
if(m_prev_index == QModelIndex())
{
m_prev_index = m_view->indexAt(m_view->rect().center());
m_view->setCurrentIndex(m_prev_index);
m_prev_value = curr_value;
}
// if move slider or page UP/DOWN
if(m_view->verticalScrollBar()->isSliderDown() || m_view->verticalScrollBar()->hasFocus() || m_view->verticalScrollBar()->underMouse())
{
if(m_prev_value < curr_value)
{
int row = m_prev_index.row() + (curr_value - m_prev_value);
if(row > m_scroll_max)
row = m_scroll_max;
m_prev_index = QModelIndex(m_view->model()->index(row, m_prev_index.column()));
m_view->setCurrentIndex(m_prev_index);
m_prev_value = curr_value;
}
else if(m_prev_value > curr_value)
{
int row = m_prev_index.row() - (m_prev_value - curr_value);
if(row < m_scroll_min)
row = m_scroll_min;
m_prev_index = QModelIndex(m_view->model()->index(row, m_prev_index.column()));
m_view->setCurrentIndex(m_prev_index);
m_prev_value = curr_value;
}
else
{
m_prev_value = curr_value;
}
}
else // if mouse whell active
{
if(m_view->flag_whell_rotate == MyTableVeiw::Rotate::DOWN)
{
m_view->flag_whell_rotate = MyTableVeiw::Rotate::NONE;
if(m_prev_value < curr_value)
{
int row = m_prev_index.row() + (curr_value - m_prev_value);
if(row > m_scroll_max)
row = m_scroll_max;
m_prev_index = QModelIndex(m_view->model()->index(row, m_prev_index.column()));
m_view->setCurrentIndex(m_prev_index);
m_prev_value = curr_value;
}
else
{
m_prev_value = curr_value;
}
}
else if(m_view->flag_whell_rotate ==MyTableVeiw::Rotate::UP)
{
m_view->flag_whell_rotate = MyTableVeiw::Rotate::NONE;
if(m_prev_value > curr_value)
{
int row = m_prev_index.row() - (m_prev_value - curr_value);
if(row < m_scroll_min)
row = m_scroll_min;
m_prev_index = QModelIndex(m_view->model()->index(row, m_prev_index.column()));
m_view->setCurrentIndex(m_prev_index);
m_prev_value = curr_value;
}
else
{
m_prev_value = curr_value;
}
}
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * *
*
* MySortFilterProxyModel
*/
filter_proxy_model::filter_proxy_model(QObject *parent)
: QSortFilterProxyModel(parent)
{
m_filter_level = "INFO|WARNING|ERROR|DEBUG";
m_search_string = "";
m_enable_text_search = false;
m_enable_date_filter = false;
}
bool filter_proxy_model::filterAcceptsRow(int sourceRow,
const QModelIndex &sourceParent) const
{
// TEXT TAG: find rows containing search strings in Tag and Text
if(m_enable_text_search)
{
if(false == m_search_string.isEmpty())
{
QModelIndex indexTag = sourceModel()->index(sourceRow, 3, sourceParent);
QModelIndex indexText = sourceModel()->index(sourceRow, 4, sourceParent);
if( (false == (sourceModel()->data(indexTag).toString().contains(m_search_string, Qt::CaseInsensitive))) &&
(false == (sourceModel()->data(indexText).toString().contains(m_search_string, Qt::CaseInsensitive))) )
return false;
}
}
// DATE TIME: find rows with correct date time
if(m_enable_date_filter)
{
// get date
QModelIndex index = sourceModel()->index(sourceRow, 1, sourceParent);
QString check_dt = sourceModel()->data(index).toString() + " ";
// get time
index = sourceModel()->index(sourceRow, 2, sourceParent);
check_dt += sourceModel()->data(index).toString();
if(false == check_date_in_range( QDateTime::fromString(check_dt, "dd.MM.yyyy hh:mm:ss.zzz")) )
return false;
}
// LEVEL: find rows with selected levels
QModelIndex indexLevel = sourceModel()->index(sourceRow, 0, sourceParent);
if(false == m_filter_level.isEmpty())
{
QStringList list = m_filter_level.split("|");
if(!list.isEmpty())
{
foreach(QString str, list)
{
if((sourceModel()->data(indexLevel).toString().contains(str) ) )
{
return true;
}
}
}
}
return false;
}
bool filter_proxy_model::check_date_in_range(QDateTime date) const
{
return ((date >= m_dt_from) &&
(date <= m_dt_to));
}
void filter_proxy_model::set_filter_level(const QString &level)
{
m_filter_level = level;
invalidateFilter();
}
void filter_proxy_model::set_search_string(const QString &str)
{
m_search_string = str;
}
void filter_proxy_model::set_enable_search_string(void)
{
m_enable_text_search = true;
invalidateFilter();
}
void filter_proxy_model::set_disable_search_string(void)
{
m_enable_text_search = false;
invalidateFilter();
}
void filter_proxy_model::set_datetime_filter(QDateTime from, QDateTime to)
{
m_dt_from = from;
m_dt_to = to;
}
void filter_proxy_model::set_enable_date_filter(void)
{
m_enable_date_filter = true;
invalidateFilter();
}
void filter_proxy_model::set_disable_date_filter(void)
{
m_enable_date_filter = false;
invalidateFilter();
}
/* * * * * * * * * * * * * * * * * * * * * * * * * *
*
* LogViewerModel
*/
log_viewer_model::log_viewer_model( QObject* parent ) : QAbstractTableModel( parent )
{
}
int log_viewer_model::rowCount( const QModelIndex& parent ) const
{
Q_UNUSED( parent )
return m_logs.count();
}
int log_viewer_model::columnCount( const QModelIndex& parent ) const
{
Q_UNUSED( parent )
return LAST;
}
QVariant log_viewer_model::headerData( int section, Qt::Orientation orientation, int role ) const
{
if( role != Qt::DisplayRole ) {
return QVariant();
}
if( orientation == Qt::Vertical ) {
return section;
}
switch( section ) {
case LEVEL:
return "Level";
case DATE:
return "Date";
case TIME:
return "Time";
case TAG:
return "Tag";
case TEXT:
return "Text";
}
return QVariant();
}
QVariant log_viewer_model::data( const QModelIndex& index, int role ) const
{
if( !index.isValid() ||
m_logs.count() <= index.row() ||
( role != Qt::DisplayRole))
{
return QVariant();
}
return m_logs[ index.row() ][ Column( index.column() ) ];
}
void log_viewer_model::slt_append_string( const QString& level, const QString& date, const QString& time, const QString& tag, const QString& text )
{
LogViewerData log;
log[ LEVEL ] = level;
log[ DATE ] = date;
log[ TIME ] = time;
log[ TAG ] = tag;
log[ TEXT ] = text;
beginInsertRows( QModelIndex(), 0, 0 );
m_logs.insert(0, log );
endInsertRows();
emit sgnl_set_data();
}
bool log_viewer_model::setData( const QModelIndex& index, const QVariant& value, int role ) {
if( !index.isValid() || role != Qt::EditRole || m_logs.count() <= index.row() ) {
return false;
}
m_logs[ index.row() ][ Column( index.column() ) ] = value;
emit dataChanged( index, index );
return true;
}
void log_viewer_model::set_level_value(uint8_t val)
{
m_select_levels = val;
}
void log_viewer_model::clear()
{
beginResetModel();
m_logs.clear();
endResetModel();
}
}
}