Added sorting of band activity and call activity window

This commit is contained in:
Jordan Sherer 2018-08-23 11:59:20 -04:00
parent 726484a05a
commit c01238f5e0
2 changed files with 188 additions and 17 deletions

View File

@ -1110,6 +1110,18 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
removeActivity->setDisabled(selectedOffset == -1);
menu->addAction(removeActivity);
menu->addSeparator();
auto sortMenu = menu->addMenu(QString("Sort by..."));
buildSortByMenu(sortMenu, "bandActivity", "offset", {
{"Frequency Offset", "offset"},
{"Last heard timestamp (oldest first)", "timestamp"},
{"Last heard timestamp (newest first)", "-timestamp"},
{"SNR (weakest first)", "snr"},
{"SNR (strongest first)", "-snr"}
});
menu->addSeparator();
menu->addAction(clearAction3);
menu->addAction(clearActionAll);
@ -1156,6 +1168,19 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
removeStation->setDisabled(missingCallsign || isAllCall);
menu->addAction(removeStation);
menu->addSeparator();
auto sortMenu = menu->addMenu(QString("Sort by..."));
buildSortByMenu(sortMenu, "callActivity", "callsign", {
{"Callsign", "callsign"},
{"Distance (closest first)", "distance"},
{"Distance (farthest first)", "-distance"},
{"Last heard timestamp (oldest first)", "timestamp"},
{"Last heard timestamp (newest first)", "-timestamp"},
{"SNR (weakest first)", "snr"},
{"SNR (strongest first)", "-snr"}
});
menu->addSeparator();
menu->addAction(clearAction4);
menu->addAction(clearActionAll);
@ -1521,6 +1546,9 @@ void MainWindow::writeSettings()
m_settings->setValue("pwrBandTuneMemory",m_pwrBandTuneMemory);
m_settings->setValue ("FT8AP", ui->actionEnable_AP_FT8->isChecked ());
m_settings->setValue ("JT65AP", ui->actionEnable_AP_JT65->isChecked ());
m_settings->setValue("SortBy", QVariant(m_sortCache));
// TODO: jsherer - need any other customizations?
/*m_settings->setValue("PanelLeftGeometry", ui->tableWidgetRXAll->geometry());
@ -1636,6 +1664,8 @@ void MainWindow::readSettings()
ui->actionEnable_AP_FT8->setChecked (m_settings->value ("FT8AP", false).toBool());
ui->actionEnable_AP_JT65->setChecked (m_settings->value ("JT65AP", false).toBool());
m_sortCache = m_settings->value("SortBy").toMap();
// TODO: jsherer - any other customizations?
//ui->mainSplitter->setSizes(m_settings->value("MainSplitter", QVariant::fromValue(ui->mainSplitter->sizes())).value<QList<int> >());
//ui->tableWidgetRXAll->restoreGeometry(m_settings->value("PanelLeftGeometry", ui->tableWidgetRXAll->saveGeometry()).toByteArray());
@ -6387,7 +6417,7 @@ void MainWindow::prepareBacon(){
QString MainWindow::calculateDistance(QString const& value)
QString MainWindow::calculateDistance(QString const& value, int *pDistance)
{
QString grid = value.trimmed();
if(grid.isEmpty() || grid.length() < 4){
@ -6402,9 +6432,11 @@ QString MainWindow::calculateDistance(QString const& value)
&nAz,&nEl,&nDmiles,&nDkm,&nHotAz,&nHotABetter,6,6);
if(m_config.miles()){
if(pDistance) *pDistance = nDmiles;
return QString("%1 mi").arg(nDmiles);
}
if(pDistance) *pDistance = nDkm;
return QString("%1 km").arg(nDkm);
}
@ -7116,6 +7148,37 @@ void MainWindow::on_qthMacroButton_clicked(){
addMessageText(qth);
}
void MainWindow::setSortBy(QString key, QString value){
m_sortCache[key] = QVariant(value);
displayBandActivity();
displayCallActivity();
}
QString MainWindow::getSortBy(QString key, QString defaultValue){
return m_sortCache.value(key, QVariant(defaultValue)).toString();
}
void MainWindow::buildSortByMenu(QMenu * menu, QString key, QString defaultValue, QMap<QString, QString> values){
auto currentSortBy = getSortBy(key, defaultValue);
QActionGroup * g = new QActionGroup(menu);
g->setExclusive(true);
foreach(auto k, values.keys()){
auto v = values[k];
auto a = menu->addAction(k);
a->setCheckable(true);
a->setChecked(v == currentSortBy);
a->setActionGroup(g);
connect(a, &QAction::triggered, this, [this, a, key, v](){
if(a->isChecked()){
setSortBy(key, v);
}
});
}
}
void MainWindow::buildQueryMenu(QMenu * menu, QString call){
bool isAllCall = isAllCallIncluded(call);
@ -9055,6 +9118,15 @@ void MainWindow::displayActivity(bool force) {
m_rxDisplayDirty = false;
}
template<typename T>
QList<T> listCopyReverse(QList<T> const &list){
QList<T> newList = QList<T>();
for(auto iter = list.rbegin(); iter != list.rend(); iter++){
newList.append(*iter);
}
return newList;
}
void MainWindow::displayBandActivity() {
auto now = QDateTime::currentDateTimeUtc();
@ -9073,25 +9145,64 @@ void MainWindow::displayBandActivity() {
// Clear the table
clearTableWidget(ui->tableWidgetRXAll);
// Sort directed & recent messages first
// Sort!
QList < int > keys = m_bandActivity.keys();
qSort(keys.begin(), keys.end(), [this](const int left, int right) {
#if 0
if (m_rxDirectedCache.contains(left / 10 * 10)) {
return true;
}
if (m_rxDirectedCache.contains(right / 10 * 10)) {
auto compareTimestamp = [this](const int left, int right) {
auto leftItems = m_bandActivity[left];
auto rightItems = m_bandActivity[right];
if(leftItems.isEmpty()){
return false;
}
if (m_rxRecentCache.contains(left / 10 * 10)) {
if(rightItems.isEmpty()){
return true;
}
if (m_rxRecentCache.contains(right / 10 * 10)) {
auto leftLast = leftItems.last();
auto rightLast = rightItems.last();
return leftLast.utcTimestamp < rightLast.utcTimestamp;
};
auto compareSNR = [this](const int left, int right) {
auto leftItems = m_bandActivity[left];
auto rightItems = m_bandActivity[right];
if(leftItems.isEmpty()){
return false;
}
#endif
return left < right;
});
if(rightItems.isEmpty()){
return true;
}
auto leftLast = leftItems.last();
auto rightLast = rightItems.last();
return leftLast.snr < rightLast.snr;
};
auto sortBy = getSortBy("bandActivity", "offset");
bool reverse = false;
if(sortBy.startsWith("-")){
sortBy = sortBy.mid(1);
reverse = true;
}
if(sortBy == "timestamp"){
qSort(keys.begin(), keys.end(), compareTimestamp);
} else if(sortBy == "snr"){
qSort(keys.begin(), keys.end(), compareSNR);
} else {
// compare offset
qSort(keys.begin(), keys.end());
}
if(reverse){
keys = listCopyReverse(keys);
}
// Build the table
foreach(int offset, keys) {
@ -9217,10 +9328,66 @@ void MainWindow::displayCallActivity() {
}
// Build the table
QList < QString > calls = m_callActivity.keys();
qSort(calls.begin(), calls.end());
QList < QString > keys = m_callActivity.keys();
auto compareDistance = [this](const QString left, QString right) {
auto leftActivity = m_callActivity[left];
auto rightActivity = m_callActivity[right];
if(leftActivity.grid.isEmpty()){
return false;
}
if(rightActivity.grid.isEmpty()){
return true;
}
int leftDistance = 0;
int rightDistance = 0;
calculateDistance(leftActivity.grid, &leftDistance);
calculateDistance(rightActivity.grid, &rightDistance);
return leftDistance < rightDistance;
};
auto compareTimestamp = [this](const QString left, QString right) {
auto leftActivity = m_callActivity[left];
auto rightActivity = m_callActivity[right];
return leftActivity.utcTimestamp < rightActivity.utcTimestamp;
};
auto compareSNR = [this](const QString left, QString right) {
auto leftActivity = m_callActivity[left];
auto rightActivity = m_callActivity[right];
return leftActivity.snr < rightActivity.snr;
};
auto sortBy = getSortBy("callActivity", "callsign");
bool reverse = false;
if(sortBy.startsWith("-")){
sortBy = sortBy.mid(1);
reverse = true;
}
if(sortBy == "distance"){
qSort(keys.begin(), keys.end(), compareDistance);
} else if(sortBy == "timestamp"){
qSort(keys.begin(), keys.end(), compareTimestamp);
} else if(sortBy == "snr"){
qSort(keys.begin(), keys.end(), compareSNR);
} else {
// compare callsign
qSort(keys.begin(), keys.end());
}
if(reverse){
keys = listCopyReverse(keys);
}
int callsignAging = m_config.callsign_aging();
foreach(QString call, calls) {
foreach(QString call, keys) {
CallDetail d = m_callActivity[call];
if (callsignAging && d.utcTimestamp.secsTo(now) / 60 >= callsignAging) {

View File

@ -257,6 +257,9 @@ private slots:
void on_cqMacroButton_clicked();
void on_qtcMacroButton_clicked();
void on_qthMacroButton_clicked();
void setSortBy(QString key, QString value);
QString getSortBy(QString key, QString defaultValue);
void buildSortByMenu(QMenu * menu, QString key, QString defaultValue, QMap<QString, QString> values);
void buildQueryMenu(QMenu *, QString callsign);
void on_queryButton_pressed();
void on_macrosMacroButton_pressed();
@ -280,7 +283,7 @@ private slots:
void pauseBacon();
void checkBacon();
void prepareBacon();
QString calculateDistance(QString const& grid);
QString calculateDistance(QString const& grid, int *pDistance=nullptr);
void on_rptSpinBox_valueChanged(int n);
void killFile();
void on_tuneButton_clicked (bool);
@ -730,6 +733,7 @@ private:
QDateTime date;
};
QMap<QString, QVariant> m_sortCache; // table key -> sort by
QPriorityQueue<PrioritizedMessage> m_txMessageQueue; // messages to be sent
QQueue<QString> m_txFrameQueue; // frames to be sent
QQueue<ActivityDetail> m_rxActivityQueue; // all rx activity queue