test_sdk/gui/gtl_gui_log_viewer.cpp

619 lines
22 KiB
C++
Raw Normal View History

#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();
}
}
}