Improve performance of Fox and contest log view windows

This include inverting  the order of table view rows  so the newest is
at the top, without that the Qt MVC interactions when using a database
table based model is too slow and complex to manage.

The table views  now have sort by column capability  in the normal way
(click column  header to  reverse sort order)  for timely  logging and
non-disruption  of  Tx  starts  the  log  view  should  be  sorted  in
descending time order and scrolled to the last row added. Without that
Fox and  contest logging will work  but serious delays may  be invoked
that disrupt operation.
This commit is contained in:
Bill Somerville 2018-12-06 05:41:16 +00:00
parent 1c48b39b58
commit b8e4517718
20 changed files with 133 additions and 63 deletions

View File

@ -28,3 +28,4 @@ void CallsignDelegate::setModelData (QWidget * editor, QAbstractItemModel * mode
{
model->setData (index, static_cast<QLineEdit *> (editor)->text (), Qt::EditRole);
}

View File

@ -6,6 +6,8 @@
#include <locale.h>
#include <fftw3.h>
#include <QSharedMemory>
#include <QTemporaryFile>
#include <QDateTime>
#include <QApplication>
#include <QRegularExpression>
@ -21,6 +23,7 @@
#include <QCommandLineParser>
#include <QCommandLineOption>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include "revision_utils.hpp"
@ -288,6 +291,12 @@ int main(int argc, char *argv[])
throw std::runtime_error {("Database Error: " + db.lastError ().text ()).toStdString ()};
}
// better performance traded for a risk of d/b corruption
// on system crash or application crash
// db.exec ("PRAGMA synchronous=OFF"); // system crash risk
// db.exec ("PRAGMA journal_mode=MEMORY"); // application crash risk
db.exec ("PRAGMA locking_mode=EXCLUSIVE");
int result;
do
{

View File

@ -59,6 +59,12 @@ CabrilloLog::impl::impl (Configuration const * configuration)
setHeaderData (fieldIndex ("exchange_sent"), Qt::Horizontal, tr ("Sent"));
setHeaderData (fieldIndex ("exchange_rcvd"), Qt::Horizontal, tr ("Rcvd"));
setHeaderData (fieldIndex ("band"), Qt::Horizontal, tr ("Band"));
// This descending order by time is important, it makes the view
// place the latest row at the top, without this the model/view
// interactions are both sluggish and unhelpful.
setSort (fieldIndex ("when"), Qt::DescendingOrder);
SQL_error_check (*this, &QSqlTableModel::select);
}
@ -113,11 +119,11 @@ bool CabrilloLog::add_QSO (Frequency frequency, QDateTime const& when, QString c
{
m_->revert (); // discard any uncommitted changes
}
m_->setEditStrategy (QSqlTableModel::OnManualSubmit);
ConditionalTransaction transaction {*m_};
auto ok = m_->insertRecord (-1, record);
if (ok)
{
m_->select (); // to refresh views
}
transaction.submit ();
m_->setEditStrategy (QSqlTableModel::OnFieldChange);
return ok;
}

View File

@ -51,6 +51,12 @@ FoxLog::impl::impl ()
setHeaderData (fieldIndex ("report_sent"), Qt::Horizontal, tr ("Sent"));
setHeaderData (fieldIndex ("report_rcvd"), Qt::Horizontal, tr ("Rcvd"));
setHeaderData (fieldIndex ("band"), Qt::Horizontal, tr ("Band"));
// This descending order by time is important, it makes the view
// place the latest row at the top, without this the model/view
// interactions are both sluggish and unhelpful.
setSort (fieldIndex ("when"), Qt::DescendingOrder);
SQL_error_check (*this, &QSqlTableModel::select);
}
@ -104,11 +110,14 @@ bool FoxLog::add_QSO (QDateTime const& when, QString const& call, QString const&
{
m_->revert (); // discard any uncommitted changes
}
m_->setEditStrategy (QSqlTableModel::OnManualSubmit);
ConditionalTransaction transaction {*m_};
auto ok = m_->insertRecord (-1, record);
if (ok)
{
m_->select (); // to refresh views
ok = transaction.submit (false);
}
m_->setEditStrategy (QSqlTableModel::OnFieldChange);
return ok;
}

View File

@ -84,13 +84,23 @@ AbstractLogWindow::AbstractLogWindow (QString const& settings_key, QSettings * s
: QWidget {parent}
, m_ {this, settings_key, settings, configuration}
{
// ensure view scrolls to latest new row
connect (&m_->model_, &QAbstractItemModel::rowsInserted, this, [this] (QModelIndex const& parent, int /*first*/, int last) {
// note col 0 is hidden so use col 1
// queued connection required otherwise row may not be available
// in time
if (m_->log_view_) m_->log_view_->scrollTo (m_->log_view_->model ()->index (last, 1, parent));
}, Qt::QueuedConnection);
// this attempt to scroll to the last new record doesn't work, some
// sort of issue with model indexes and optimized DB fetches. For
// now sorting by the same column and direction as the underlying DB
// select and that DB select being in descending order so new rows
// at the end appear at view row 0 gets the job done
// // ensure view scrolls to latest new row
// connect (&m_->model_, &QAbstractItemModel::rowsInserted, this, [this] (QModelIndex const& parent, int first, int last) {
// // note col 0 is hidden so use col 1
// // queued connection required otherwise row may not be available
// // in time
// auto index = m_->model_.index (last, 1, parent);
// if (m_->log_view_)
// {
// m_->log_view_->scrollTo (index);
// }
// }, Qt::QueuedConnection);
}
AbstractLogWindow::~AbstractLogWindow ()
@ -105,24 +115,27 @@ void AbstractLogWindow::set_log_view (QTableView * log_view)
SettingsGroup g {m_->settings_, m_->settings_key_};
restoreGeometry (m_->settings_->value ("window/geometry").toByteArray ());
m_->log_view_ = log_view;
m_->log_view_->setContextMenuPolicy (Qt::ActionsContextMenu);
m_->log_view_->setAlternatingRowColors (true);
m_->log_view_->setSelectionBehavior (QAbstractItemView::SelectRows);
m_->log_view_->setSelectionMode (QAbstractItemView::ExtendedSelection);
m_->log_view_->setVerticalScrollMode (QAbstractItemView::ScrollPerPixel);
m_->model_.setSourceModel (m_->log_view_->model ());
m_->log_view_->setModel (&m_->model_);
m_->log_view_->setColumnHidden (0, true);
set_log_view_font (m_->configuration_->decoded_text_font ());
log_view->setSortingEnabled (true);
log_view->setContextMenuPolicy (Qt::ActionsContextMenu);
log_view->setAlternatingRowColors (true);
log_view->setSelectionBehavior (QAbstractItemView::SelectRows);
log_view->setSelectionMode (QAbstractItemView::ExtendedSelection);
log_view->setVerticalScrollMode (QAbstractItemView::ScrollPerPixel);
m_->model_.setSourceModel (log_view->model ());
log_view->setModel (&m_->model_);
log_view->setColumnHidden (0, true);
auto horizontal_header = log_view->horizontalHeader ();
horizontal_header->setResizeContentsPrecision (0); // visible region only
horizontal_header->setSectionResizeMode (QHeaderView::ResizeToContents);
horizontal_header->setSectionsMovable (true);
m_->log_view_->verticalHeader ()->setSectionResizeMode (QHeaderView::ResizeToContents);
set_log_view_font (m_->configuration_->decoded_text_font ());
m_->log_view_->scrollToBottom ();
auto vertical_header = log_view->horizontalHeader ();
vertical_header->setResizeContentsPrecision (0); // visible region only
vertical_header->setSectionResizeMode (QHeaderView::ResizeToContents);
// actions
auto delete_action = new QAction {tr ("&Delete ..."), m_->log_view_};
m_->log_view_->insertAction (nullptr, delete_action);
auto delete_action = new QAction {tr ("&Delete ..."), log_view};
log_view->insertAction (nullptr, delete_action);
connect (delete_action, &QAction::triggered, [this] (bool /*checked*/) {
m_->delete_QSOs ();
});
@ -130,8 +143,8 @@ void AbstractLogWindow::set_log_view (QTableView * log_view)
void AbstractLogWindow::set_log_view_font (QFont const& font)
{
// m_->log_view_->setFont (font);
// m_->log_view_->horizontalHeader ()->setFont (font);
// m_->log_view_->verticalHeader ()->setFont (font);
m_->log_view_->setFont (font);
m_->log_view_->horizontalHeader ()->setFont (font);
m_->log_view_->verticalHeader ()->setFont (font);
m_->model_.set_font (font);
}

View File

@ -67,7 +67,8 @@ CabrilloLogWindow::CabrilloLogWindow (QSettings * settings, Configuration const
m_->ui_.log_table_view->setItemDelegateForColumn (2, new DateTimeAsSecsSinceEpochDelegate {this});
m_->ui_.log_table_view->setItemDelegateForColumn (3, new CallsignDelegate {this});
m_->ui_.log_table_view->setItemDelegateForColumn (6, new ForeignKeyDelegate {configuration->bands (), 0, this});
m_->ui_.log_table_view->horizontalHeader ()->moveSection (6, 1); // band to first column
auto h_header = m_->ui_.log_table_view->horizontalHeader ();
h_header->moveSection (6, 1); // band to first column
}
CabrilloLogWindow::~CabrilloLogWindow ()

View File

@ -1,6 +1,8 @@
#include "echoplot.h"
#include "commons.h"
#include <math.h>
#include <QPainter>
#include <QPen>
#include <QDebug>
#include "moc_echoplot.cpp"

View File

@ -4,17 +4,20 @@
// For more details see the accompanying file LICENSE_WHEATLEY.TXT
///////////////////////////////////////////////////////////////////////////
#ifndef EPLOTTER_H
#define EPLOTTER_H
#ifndef EPLOTTER_H_
#define EPLOTTER_H_
#include <QtWidgets>
#include <QFrame>
#include <QSize>
#include <QImage>
#include <cstring>
#include <QString>
#define VERT_DIVS 7 //specify grid screen divisions
#define HORZ_DIVS 20
class QPaintEvent;
class QResizeEvent;
class EPlotter : public QFrame
{
Q_OBJECT

View File

@ -3,6 +3,7 @@
#include "commons.h"
#include <QSettings>
#include <QApplication>
#include <QKeyEvent>
#include "fastplot.h"
#include "SettingsGroup.hpp"

View File

@ -1,5 +1,5 @@
#ifndef FASTGRAPH_H
#define FASTGRAPH_H
#ifndef FASTGRAPH_H_
#define FASTGRAPH_H_
#include <QDialog>
#include <QScopedPointer>
@ -9,6 +9,8 @@ namespace Ui {
}
class QSettings;
class QCloseEvent;
class QKeyEvent;
class FastGraph : public QDialog
{

View File

@ -1,6 +1,10 @@
#include "fastplot.h"
#include "commons.h"
#include <math.h>
#include <QPainter>
#include <QPen>
#include <QMouseEvent>
#include <QDateTime>
#include <QDebug>
#include "moc_fastplot.cpp"

View File

@ -4,13 +4,16 @@
// For more details see the accompanying file LICENSE_WHEATLEY.TXT
///////////////////////////////////////////////////////////////////////////
#ifndef FPLOTTER_H
#define FPLOTTER_H
#ifndef FPLOTTER_H_
#define FPLOTTER_H_
#include <QtWidgets>
#include <QFrame>
#include <QImage>
#include <cstring>
#include <QString>
#include <QPixmap>
#include <QVector>
#include <QColor>
class QMouseEvent;
class FPlotter : public QFrame
{

View File

@ -1,6 +1,6 @@
// -*- Mode: C++ -*-
#ifndef LogQSO_H
#define LogQSO_H
#ifndef LogQSO_H_
#define LogQSO_H_
#include <QDialog>

View File

@ -1,12 +1,20 @@
//---------------------------------------------------------- MainWindow
#include "mainwindow.h"
#include <cinttypes>
#include <cstring>
#include <limits>
#include <functional>
#include <fstream>
#include <iterator>
#include <algorithm>
#include <fftw3.h>
#include <QStringListModel>
#include <QSettings>
#include <QKeyEvent>
#include <QSharedMemory>
#include <QFileDialog>
#include <QTextBlock>
#include <QProgressBar>
#include <QLineEdit>
#include <QRegExpValidator>
#include <QRegExp>
@ -3100,7 +3108,7 @@ void MainWindow::readFromStdout() //readFromStdout
if(w.at(0)==m_config.my_callsign() or w.at(0)==Radio::base_callsign(m_config.my_callsign())) {
//### Check for ui->dxCallEntry->text()==foxCall before logging! ###
ui->stopTxButton->click ();
on_logQSOButton_clicked();
logQSOTimer.start(0);
}
if((w.at(2)==m_config.my_callsign() or w.at(2)==Radio::base_callsign(m_config.my_callsign()))
and ui->tx3->text().length()>0) {
@ -3118,7 +3126,7 @@ void MainWindow::readFromStdout() //readFromStdout
ui->tx3->text().length()>0) {
if(w.at(2)=="RR73") {
ui->stopTxButton->click ();
on_logQSOButton_clicked();
logQSOTimer.start(0);
} else {
if(w.at(1)==Radio::base_callsign(ui->dxCallEntry->text()) and
(w.at(2).mid(0,1)=="+" or w.at(2).mid(0,1)=="-")) {
@ -4453,7 +4461,7 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
m_nextCall=""; //### Temporary: disable use of "TU;" message
if(SpecOp::RTTY == m_config.special_op_id() and m_nextCall!="") {
// We're in RTTY contest and have "nextCall" queued up: send a "TU; ..." message
on_logQSOButton_clicked();
logQSOTimer.start(0);
ui->tx3->setText(ui->tx3->text().remove("TU; "));
useNextCall();
QString t="TU; " + ui->tx3->text();
@ -4462,7 +4470,7 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
} else {
// if(SpecOp::RTTY == m_config.special_op_id()) {
if(false) {
on_logQSOButton_clicked();
logQSOTimer.start(0);
m_ntx=6;
ui->txrb6->setChecked(true);
} else {
@ -8216,7 +8224,7 @@ list2Done:
{
writeFoxQSO (QString {" Log: %1 %2 %3 %4 %5"}.arg (m_hisCall).arg (m_hisGrid)
.arg (m_rptSent).arg (m_rptRcvd).arg (m_lastBand));
on_logQSOButton_clicked();
logQSOTimer.start(0);
m_foxRateQueue.enqueue (now); //Add present time in seconds
//to Rate queue.
}

View File

@ -1,12 +1,12 @@
// -*- Mode: C++ -*-
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#ifdef QT5
#include <QtWidgets>
#else
#include <QtGui>
#endif
#include <QMainWindow>
#include <QLabel>
#include <QThread>
#include <QProcess>
#include <QProgressBar>
#include <QTimer>
#include <QDateTime>
#include <QList>
@ -58,6 +58,8 @@ namespace Ui {
class MainWindow;
}
class QSharedMemory;
class QSplashScreen;
class QSettings;
class QLineEdit;
class QFont;
@ -102,6 +104,8 @@ public:
QWidget *parent = nullptr);
~MainWindow();
int decoderBusy () const {return m_decoderBusy;}
public slots:
void showSoundInError(const QString& errorMsg);
void showSoundOutError(const QString& errorMsg);

View File

@ -1,5 +1,11 @@
#include "plotter.h"
#include <math.h>
#include <QAction>
#include <QMenu>
#include <QPainter>
#include <QDateTime>
#include <QPen>
#include <QMouseEvent>
#include <QDebug>
#include "commons.h"
#include "moc_plotter.cpp"

View File

@ -5,18 +5,14 @@
// For more details see the accompanying file LICENSE_WHEATLEY.TXT
///////////////////////////////////////////////////////////////////////////
#ifndef PLOTTER_H
#define PLOTTER_H
#ifndef PLOTTER_H_
#define PLOTTER_H_
#ifdef QT5
#include <QtWidgets>
#else
#include <QtGui>
#endif
#include <QFrame>
#include <QSize>
#include <QImage>
#include <QVector>
#include <cstring>
#include <QColor>
#define VERT_DIVS 7 //specify grid screen divisions
#define HORZ_DIVS 20

View File

@ -3,6 +3,8 @@
#include <algorithm>
#include <QApplication>
#include <QSettings>
#include <QDateTime>
#include <QKeyEvent>
#include "ui_widegraph.h"
#include "commons.h"
#include "Configuration.hpp"

View File

@ -1,6 +1,6 @@
// -*- Mode: C++ -*-
#ifndef WIDEGRAPH_H
#define WIDEGRAPH_H
#ifndef WIDEGRAPH_H_
#define WIDEGRAPH_H_
#include <QDialog>
#include <QScopedPointer>

View File

@ -19,7 +19,7 @@ HEADERS += \
widgets/echoplot.h widgets/echograph.h widgets/fastgraph.h \
widgets/fastplot.h widgets/MessageBox.hpp widgets/colorhighlighting.h \
widgets/ExportCabrillo.h widgets/AbstractLogWindow.hpp \
widgets/FoxLogWindow.cpp widgets/CabrilloLogWindow.cpp
widgets/FoxLogWindow.hpp widgets/CabrilloLogWindow.hpp
FORMS += \
widgets/mainwindow.ui widgets/about.ui \