diff --git a/Changelog b/Changelog index e50c82ce..062f8062 100644 --- a/Changelog +++ b/Changelog @@ -1,4 +1,5 @@ TBC - 0.39.0 +- [NEW] - DXC - Added Full-text search - [NEW] - Select S in RST Edit when focused (issue #454) - [CHANGED] - HamlibDrv - Added multiplatform reliable sleep - [CHANGED] - Backup policy diff --git a/QLog.pro b/QLog.pro index 8729b4ea..aba89815 100644 --- a/QLog.pro +++ b/QLog.pro @@ -106,6 +106,7 @@ SOURCES += \ models/LogbookModel.cpp \ models/RigTypeModel.cpp \ models/RotTypeModel.cpp \ + models/SearchFilterProxyModel.cpp \ models/ShortcutEditorModel.cpp \ models/SqlListModel.cpp \ models/WsjtxTableModel.cpp \ @@ -241,6 +242,7 @@ HEADERS += \ models/LogbookModel.h \ models/RigTypeModel.h \ models/RotTypeModel.h \ + models/SearchFilterProxyModel.h \ models/ShortcutEditorModel.h \ models/SqlListModel.h \ models/WsjtxTableModel.h \ diff --git a/models/SearchFilterProxyModel.cpp b/models/SearchFilterProxyModel.cpp new file mode 100644 index 00000000..a549780a --- /dev/null +++ b/models/SearchFilterProxyModel.cpp @@ -0,0 +1,25 @@ +#include "SearchFilterProxyModel.h" + +SearchFilterProxyModel::SearchFilterProxyModel(QObject *parent) + : QSortFilterProxyModel{parent} +{} + +void SearchFilterProxyModel::setSearchString(const QString &searchString) +{ + this->searchString = searchString; + invalidateFilter(); +} + +bool SearchFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const +{ + // full-text search + for ( int col = 0; col < sourceModel()->columnCount(); ++col ) + { + QModelIndex index = sourceModel()->index(source_row, col, source_parent); + QString data = index.data(Qt::DisplayRole).toString(); + + if ( data.contains(searchString, Qt::CaseInsensitive) ) + return true; + } + return false; +} diff --git a/models/SearchFilterProxyModel.h b/models/SearchFilterProxyModel.h new file mode 100644 index 00000000..4047afe0 --- /dev/null +++ b/models/SearchFilterProxyModel.h @@ -0,0 +1,21 @@ +#ifndef SEARCHFILTERPROXYMODEL_H +#define SEARCHFILTERPROXYMODEL_H + +#include + +class SearchFilterProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT + +public: + SearchFilterProxyModel(QObject* parent = nullptr); + void setSearchString(const QString& searchString); + +protected: + bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override; + +private: + QString searchString; +}; + +#endif // SEARCHFILTERPROXYMODEL_H diff --git a/ui/DxWidget.cpp b/ui/DxWidget.cpp index 225695a5..29594fb7 100644 --- a/ui/DxWidget.cpp +++ b/ui/DxWidget.cpp @@ -403,18 +403,24 @@ DxWidget::DxWidget(QWidget *parent) : ui->setupUi(this); + setSearchClosed(); + ui->serverSelect->setStyleSheet(QStringLiteral("QComboBox {color: red}")); - dxTableModel = new DxTableModel(this); wcyTableModel = new WCYTableModel(this); wwvTableModel = new WWVTableModel(this); toAllTableModel = new ToAllTableModel(this); + dxTableProxyModel = new SearchFilterProxyModel(ui->dxTable); + dxTableModel = new DxTableModel(dxTableProxyModel); + dxTableProxyModel->setSourceModel(dxTableModel); + QAction *separator = new QAction(this); separator->setSeparator(true); - ui->dxTable->setModel(dxTableModel); + ui->dxTable->setModel(dxTableProxyModel); ui->dxTable->addAction(ui->actionFilter); + ui->dxTable->addAction(ui->actionSearch); ui->dxTable->addAction(ui->actionDisplayedColumns); ui->dxTable->addAction(ui->actionClear); ui->dxTable->addAction(separator); @@ -1198,9 +1204,11 @@ void DxWidget::entryDoubleClicked(QModelIndex index) { FCT_IDENTIFICATION; - emit tuneDx(dxTableModel->getCallsign(index), - dxTableModel->getFrequency(index), - dxTableModel->getBandPlanode(index)); + const QModelIndex &source_index = dxTableProxyModel->mapToSource(index); + + emit tuneDx(dxTableModel->getCallsign(source_index), + dxTableModel->getFrequency(source_index), + dxTableModel->getBandPlanode(source_index)); } void DxWidget::actionFilter() @@ -1300,6 +1308,37 @@ void DxWidget::prepareQSOSpot(QSqlRecord qso) } } +void DxWidget::setSearch(const QString &text) +{ + FCT_IDENTIFICATION; + + dxTableProxyModel->setSearchString(text); +} + +void DxWidget::setSearchStatus(bool visible) +{ + FCT_IDENTIFICATION; + + ui->searchEdit->setVisible(visible); + ui->searchEdit->setFocus(); + ui->searchCloseButton->setVisible(visible); + + if (!visible) + ui->searchEdit->clear(); +} + +void DxWidget::setSearchVisible() +{ + FCT_IDENTIFICATION; + setSearchStatus(!ui->searchEdit->isVisible()); +} + +void DxWidget::setSearchClosed() +{ + FCT_IDENTIFICATION; + setSearchStatus(false); +} + void DxWidget::actionCommandSpotQSO() { FCT_IDENTIFICATION; diff --git a/ui/DxWidget.h b/ui/DxWidget.h index 575d52ed..2d58649d 100644 --- a/ui/DxWidget.h +++ b/ui/DxWidget.h @@ -13,6 +13,7 @@ #include "data/ToAllSpot.h" #include "core/LogLocale.h" #include "core/DxServerString.h" +#include "models/SearchFilterProxyModel.h" // in sec #define DEDUPLICATION_TIME 3 @@ -112,7 +113,6 @@ class DeleteHighlightedDXServerWhenDelPressedEventFilter : public QObject bool eventFilter(QObject *obj, QEvent *event); }; - class DxWidget : public QWidget { Q_OBJECT @@ -134,6 +134,10 @@ public slots: void setLastQSO(QSqlRecord); void reloadSetting(); void prepareQSOSpot(QSqlRecord); + void setSearch(const QString &); + void setSearchStatus(bool); + void setSearchVisible(); + void setSearchClosed(); private slots: void actionCommandSpotQSO(); @@ -172,6 +176,7 @@ private slots: WCYTableModel* wcyTableModel; WWVTableModel* wwvTableModel; ToAllTableModel* toAllTableModel; + SearchFilterProxyModel* dxTableProxyModel; QTcpSocket* socket; Ui::DxWidget *ui; QRegularExpression moderegexp; diff --git a/ui/DxWidget.ui b/ui/DxWidget.ui index 1486199b..4b6bf55b 100644 --- a/ui/DxWidget.ui +++ b/ui/DxWidget.ui @@ -225,6 +225,43 @@ + + + + 0 + + + + + Qt::ClickFocus + + + Full-text search + + + Search + + + true + + + + + + + Close Search + + + + + + + .. + + + + + @@ -587,6 +624,23 @@ Clear all data + + + Search... + + + DXC - Search + + + Ctrl+D + + + Qt::ApplicationShortcut + + + true + + @@ -880,6 +934,54 @@ + + actionSearch + triggered() + DxWidget + setSearchVisible() + + + -1 + -1 + + + 170 + 255 + + + + + searchCloseButton + clicked() + DxWidget + setSearchClosed() + + + 325 + 462 + + + 170 + 255 + + + + + searchEdit + textChanged(QString) + DxWidget + setSearch(QString) + + + 170 + 463 + + + 170 + 255 + + + send() @@ -903,5 +1005,8 @@ actionForgetPassword() actionKeepSpots() actionClear() + setSearch(QString) + setSearchVisible() + setSearchClosed() diff --git a/ui/MainWindow.ui b/ui/MainWindow.ui index b0d614ff..54343bb8 100644 --- a/ui/MainWindow.ui +++ b/ui/MainWindow.ui @@ -52,7 +52,7 @@ 0 0 913 - 22 + 23