mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2025-07-12 06:35:23 -04:00
edit new frequency table fields inline; refresh filter periodically;
This commit is contained in:
parent
923de0ef38
commit
85cb05a812
@ -185,6 +185,7 @@
|
|||||||
#include "item_delegates/ForeignKeyDelegate.hpp"
|
#include "item_delegates/ForeignKeyDelegate.hpp"
|
||||||
#include "item_delegates/FrequencyDelegate.hpp"
|
#include "item_delegates/FrequencyDelegate.hpp"
|
||||||
#include "item_delegates/FrequencyDeltaDelegate.hpp"
|
#include "item_delegates/FrequencyDeltaDelegate.hpp"
|
||||||
|
#include "item_delegates/MessageItemDelegate.hpp"
|
||||||
#include "Transceiver/TransceiverFactory.hpp"
|
#include "Transceiver/TransceiverFactory.hpp"
|
||||||
#include "Transceiver/Transceiver.hpp"
|
#include "Transceiver/Transceiver.hpp"
|
||||||
#include "models/Bands.hpp"
|
#include "models/Bands.hpp"
|
||||||
@ -437,31 +438,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Class MessageItemDelegate
|
|
||||||
//
|
|
||||||
// Item delegate for message entry such as free text message macros.
|
|
||||||
//
|
|
||||||
class MessageItemDelegate final
|
|
||||||
: public QStyledItemDelegate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit MessageItemDelegate (QObject * parent = nullptr)
|
|
||||||
: QStyledItemDelegate {parent}
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget * createEditor (QWidget * parent
|
|
||||||
, QStyleOptionViewItem const& /* option*/
|
|
||||||
, QModelIndex const& /* index */
|
|
||||||
) const override
|
|
||||||
{
|
|
||||||
auto editor = new QLineEdit {parent};
|
|
||||||
editor->setFrame (false);
|
|
||||||
editor->setValidator (new QRegularExpressionValidator {message_alphabet, editor});
|
|
||||||
return editor;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Internal implementation of the Configuration class.
|
// Internal implementation of the Configuration class.
|
||||||
class Configuration::impl final
|
class Configuration::impl final
|
||||||
@ -1268,6 +1245,7 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network
|
|||||||
ui_->frequencies_table_view->verticalHeader ()->setResizeContentsPrecision (0);
|
ui_->frequencies_table_view->verticalHeader ()->setResizeContentsPrecision (0);
|
||||||
ui_->frequencies_table_view->sortByColumn (FrequencyList_v2::frequency_column, Qt::AscendingOrder);
|
ui_->frequencies_table_view->sortByColumn (FrequencyList_v2::frequency_column, Qt::AscendingOrder);
|
||||||
ui_->frequencies_table_view->setColumnHidden (FrequencyList_v2::frequency_mhz_column, true);
|
ui_->frequencies_table_view->setColumnHidden (FrequencyList_v2::frequency_mhz_column, true);
|
||||||
|
ui_->frequencies_table_view->setColumnHidden (FrequencyList_v2::source_column, true);
|
||||||
|
|
||||||
// delegates
|
// delegates
|
||||||
ui_->frequencies_table_view->setItemDelegateForColumn (FrequencyList_v2::frequency_column, new FrequencyDelegate {this});
|
ui_->frequencies_table_view->setItemDelegateForColumn (FrequencyList_v2::frequency_column, new FrequencyDelegate {this});
|
||||||
@ -2052,7 +2030,6 @@ TransceiverFactory::ParameterPack Configuration::impl::gather_rig_data ()
|
|||||||
void Configuration::impl::accept ()
|
void Configuration::impl::accept ()
|
||||||
{
|
{
|
||||||
// Called when OK button is clicked.
|
// Called when OK button is clicked.
|
||||||
|
|
||||||
if (!validate ())
|
if (!validate ())
|
||||||
{
|
{
|
||||||
return; // not accepting
|
return; // not accepting
|
||||||
@ -2627,59 +2604,19 @@ FrequencyList_v2::FrequencyItems Configuration::impl::read_frequencies_file (QSt
|
|||||||
FrequencyList_v2::FrequencyItems list;
|
FrequencyList_v2::FrequencyItems list;
|
||||||
FrequencyList_v2_100::FrequencyItems list_v100;
|
FrequencyList_v2_100::FrequencyItems list_v100;
|
||||||
|
|
||||||
// read file as json if ends with qrg.json
|
// read file as json if ends with qrg.json.
|
||||||
if (file_name.endsWith(".qrg.json", Qt::CaseInsensitive))
|
if (file_name.endsWith(".qrg.json", Qt::CaseInsensitive))
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(frequencies_file.readAll());
|
list = FrequencyList_v2::from_json_file(&frequencies_file);
|
||||||
if (doc.isNull())
|
}
|
||||||
{
|
catch (ReadFileException const &e)
|
||||||
MessageBox::critical_message (this, tr ("Error reading frequencies file"), tr ("%1 - Invalid Format").arg (file_name));
|
{
|
||||||
return list;
|
MessageBox::critical_message(this, tr("Error reading frequency file"), e.message_);
|
||||||
}
|
}
|
||||||
QJsonObject obj = doc.object();
|
return list;
|
||||||
if (obj.isEmpty())
|
}
|
||||||
{
|
|
||||||
MessageBox::critical_message (this, tr ("Error reading frequencies file"), tr ("%1 - Information Missing ").arg (file_name));
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
QJsonArray arr = obj["frequencies"].toArray();
|
|
||||||
if (arr.isEmpty())
|
|
||||||
{
|
|
||||||
MessageBox::critical_message (this, tr ("Error reading frequencies file"), tr ("No Frequencies were found"));
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
int valid_entry_count = 0;
|
|
||||||
int skipped_entry_count = 0;
|
|
||||||
for (auto const &item: arr)
|
|
||||||
{
|
|
||||||
QString mode_s, region_s;
|
|
||||||
QJsonObject obj = item.toObject();
|
|
||||||
FrequencyList_v2::Item freq;
|
|
||||||
region_s = obj["region"].toString();
|
|
||||||
mode_s = obj["mode"].toString();
|
|
||||||
|
|
||||||
freq.frequency_ = obj["frequency"].toString().toDouble() * 1e6;
|
|
||||||
freq.region_ = IARURegions::value(region_s);
|
|
||||||
freq.mode_ = Modes::value(mode_s);
|
|
||||||
freq.description_ = obj["description"].toString();
|
|
||||||
freq.source_ = obj["source"].toString();
|
|
||||||
freq.start_time_ = QDateTime::fromString(obj["start_time"].toString(), Qt::ISODate);
|
|
||||||
freq.end_time_ = QDateTime::fromString(obj["end_time"].toString(), Qt::ISODate);
|
|
||||||
//MessageBox::critical_message (this, tr ("Entry"), tr ("Entry: %1 ").arg(freq.toString()+"[sane:" +freq.isSane() + "] [region:" + obj["region"].toString() + "] [mode:" + obj["mode"].toString()+"] "));
|
|
||||||
if ((freq.mode_ != Modes::ALL || QString::compare("ALL", mode_s)) &&
|
|
||||||
(freq.region_ != IARURegions::ALL || QString::compare("ALL", region_s, Qt::CaseInsensitive)) &&
|
|
||||||
freq.isSane())
|
|
||||||
{
|
|
||||||
list.push_back(freq);
|
|
||||||
valid_entry_count++;
|
|
||||||
} else
|
|
||||||
skipped_entry_count++;
|
|
||||||
}
|
|
||||||
MessageBox::information_message(this, tr("Loaded Frequencies from %1").arg(file_name),
|
|
||||||
tr("Entries Valid/Skipped %1").arg(QString::number(valid_entry_count) + "/" +
|
|
||||||
QString::number(skipped_entry_count)));
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
quint32 magic;
|
quint32 magic;
|
||||||
ids >> magic;
|
ids >> magic;
|
||||||
@ -2727,9 +2664,13 @@ void Configuration::impl::save_frequencies ()
|
|||||||
auto file_name = QFileDialog::getSaveFileName (this, tr ("Save Working Frequencies"), writeable_data_dir_.absolutePath (), tr ("Frequency files (*.qrg *.qrg.json);;All files (*.*)"));
|
auto file_name = QFileDialog::getSaveFileName (this, tr ("Save Working Frequencies"), writeable_data_dir_.absolutePath (), tr ("Frequency files (*.qrg *.qrg.json);;All files (*.*)"));
|
||||||
if (!file_name.isNull ())
|
if (!file_name.isNull ())
|
||||||
{
|
{
|
||||||
|
bool b_write_json = file_name.endsWith(".qrg.json", Qt::CaseInsensitive);
|
||||||
|
|
||||||
QFile frequencies_file {file_name};
|
QFile frequencies_file {file_name};
|
||||||
frequencies_file.open (QFile::WriteOnly);
|
frequencies_file.open (QFile::WriteOnly);
|
||||||
|
|
||||||
QDataStream ods {&frequencies_file};
|
QDataStream ods {&frequencies_file};
|
||||||
|
|
||||||
auto selection_model = ui_->frequencies_table_view->selectionModel ();
|
auto selection_model = ui_->frequencies_table_view->selectionModel ();
|
||||||
if (selection_model->hasSelection ()
|
if (selection_model->hasSelection ()
|
||||||
&& MessageBox::Yes == MessageBox::query_message (this
|
&& MessageBox::Yes == MessageBox::query_message (this
|
||||||
@ -2739,9 +2680,9 @@ void Configuration::impl::save_frequencies ()
|
|||||||
"Click No to save all.")))
|
"Click No to save all.")))
|
||||||
{
|
{
|
||||||
selection_model->select (selection_model->selection (), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
|
selection_model->select (selection_model->selection (), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
|
||||||
if (file_name.endsWith(".qrg.json", Qt::CaseInsensitive))
|
if (b_write_json)
|
||||||
{
|
{
|
||||||
next_frequencies_.to_json_stream(&ods, "0x" + QString::number(qrg_magic, 16).toUpper(),
|
next_frequencies_.to_json_file(&frequencies_file, "0x" + QString::number(qrg_magic, 16).toUpper(),
|
||||||
"0x" + QString::number(qrg_version, 16).toUpper(),
|
"0x" + QString::number(qrg_version, 16).toUpper(),
|
||||||
next_frequencies_.frequency_list(selection_model->selectedRows()));
|
next_frequencies_.frequency_list(selection_model->selectedRows()));
|
||||||
} else
|
} else
|
||||||
@ -2751,9 +2692,9 @@ void Configuration::impl::save_frequencies ()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (file_name.endsWith(".qrg.json", Qt::CaseInsensitive))
|
if (b_write_json)
|
||||||
{
|
{
|
||||||
next_frequencies_.to_json_stream(&ods,
|
next_frequencies_.to_json_file(&frequencies_file,
|
||||||
"0x" + QString::number(qrg_magic, 16).toUpper(),
|
"0x" + QString::number(qrg_magic, 16).toUpper(),
|
||||||
"0x" + QString::number(qrg_version, 16).toUpper(),
|
"0x" + QString::number(qrg_version, 16).toUpper(),
|
||||||
next_frequencies_.frequency_list());
|
next_frequencies_.frequency_list());
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
//
|
//
|
||||||
// Implements the QAbstractTableModel interface as an immutable table
|
// Implements the QAbstractTableModel interface as an immutable table
|
||||||
// where rows are bands and columns are band name, lower frequency
|
// where rows are bands and columns are band name, lower frequency
|
||||||
// limit and, upper ferquency limit respectively.
|
// limit and, upper frequency limit respectively.
|
||||||
//
|
//
|
||||||
class Bands final
|
class Bands final
|
||||||
: public QAbstractTableModel
|
: public QAbstractTableModel
|
||||||
|
@ -23,11 +23,13 @@
|
|||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QException>
|
||||||
|
|
||||||
#include "Radio.hpp"
|
#include "Radio.hpp"
|
||||||
#include "Bands.hpp"
|
#include "Bands.hpp"
|
||||||
#include "pimpl_impl.hpp"
|
#include "pimpl_impl.hpp"
|
||||||
#include "revision_utils.hpp"
|
#include "revision_utils.hpp"
|
||||||
|
#include "Logger.hpp"
|
||||||
|
|
||||||
#include "moc_FrequencyList.cpp"
|
#include "moc_FrequencyList.cpp"
|
||||||
|
|
||||||
@ -378,7 +380,6 @@ QString FrequencyList_v2::Item::toString () const
|
|||||||
<< end_time_.toString(Qt::ISODate) << ", "
|
<< end_time_.toString(Qt::ISODate) << ", "
|
||||||
<< description_ << ", "
|
<< description_ << ", "
|
||||||
<< source_ << ')';
|
<< source_ << ')';
|
||||||
|
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -423,6 +424,7 @@ public:
|
|||||||
, bands_ {bands}
|
, bands_ {bands}
|
||||||
, region_filter_ {IARURegions::ALL}
|
, region_filter_ {IARURegions::ALL}
|
||||||
, mode_filter_ {Modes::ALL}
|
, mode_filter_ {Modes::ALL}
|
||||||
|
, filter_on_time_ {false}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,6 +451,7 @@ public:
|
|||||||
FrequencyItems frequency_list_;
|
FrequencyItems frequency_list_;
|
||||||
Region region_filter_;
|
Region region_filter_;
|
||||||
Mode mode_filter_;
|
Mode mode_filter_;
|
||||||
|
bool filter_on_time_;
|
||||||
};
|
};
|
||||||
|
|
||||||
FrequencyList_v2::FrequencyList_v2 (Bands const * bands, QObject * parent)
|
FrequencyList_v2::FrequencyList_v2 (Bands const * bands, QObject * parent)
|
||||||
@ -564,7 +567,7 @@ bool FrequencyList_v2::removeDisjointRows (QModelIndexList rows)
|
|||||||
|
|
||||||
// We must work with source model indexes because we don't want row
|
// We must work with source model indexes because we don't want row
|
||||||
// removes to invalidate model indexes we haven't yet processed. We
|
// removes to invalidate model indexes we haven't yet processed. We
|
||||||
// achieve that by processing them in decending row order.
|
// achieve that by processing them in descending row order.
|
||||||
for (int r = 0; r < rows.size (); ++r)
|
for (int r = 0; r < rows.size (); ++r)
|
||||||
{
|
{
|
||||||
rows[r] = mapToSource (rows[r]);
|
rows[r] = mapToSource (rows[r]);
|
||||||
@ -585,10 +588,16 @@ bool FrequencyList_v2::removeDisjointRows (QModelIndexList rows)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrequencyList_v2::filter (Region region, Mode mode)
|
void FrequencyList_v2::filter (Region region, Mode mode, bool filter_on_time)
|
||||||
{
|
{
|
||||||
m_->region_filter_ = region;
|
m_->region_filter_ = region;
|
||||||
m_->mode_filter_ = mode;
|
m_->mode_filter_ = mode;
|
||||||
|
m_->filter_on_time_ = filter_on_time;
|
||||||
|
invalidateFilter ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrequencyList_v2::filter_refresh ()
|
||||||
|
{
|
||||||
invalidateFilter ();
|
invalidateFilter ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,6 +615,11 @@ bool FrequencyList_v2::filterAcceptsRow (int source_row, QModelIndex const& /* p
|
|||||||
result = (Modes::ALL == item.mode_ && m_->mode_filter_ != Modes::FreqCal)
|
result = (Modes::ALL == item.mode_ && m_->mode_filter_ != Modes::FreqCal)
|
||||||
|| m_->mode_filter_ == item.mode_;
|
|| m_->mode_filter_ == item.mode_;
|
||||||
}
|
}
|
||||||
|
if (result && m_->filter_on_time_)
|
||||||
|
{
|
||||||
|
result = (!item.start_time_.isValid() || item.start_time_ <= QDateTime::currentDateTimeUtc ()) &&
|
||||||
|
(!item.end_time_.isValid() || item.end_time_ >= QDateTime::currentDateTimeUtc ());
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -796,7 +810,7 @@ QVariant FrequencyList_v2::impl::data (QModelIndex const& index, int role) const
|
|||||||
item = Qt::AlignRight + Qt::AlignVCenter;
|
item = Qt::AlignRight + Qt::AlignVCenter;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case description_column:
|
case description_column:
|
||||||
switch (role)
|
switch (role)
|
||||||
@ -810,14 +824,14 @@ QVariant FrequencyList_v2::impl::data (QModelIndex const& index, int role) const
|
|||||||
|
|
||||||
case Qt::ToolTipRole:
|
case Qt::ToolTipRole:
|
||||||
case Qt::AccessibleDescriptionRole:
|
case Qt::AccessibleDescriptionRole:
|
||||||
item = tr ("Description");
|
item = tr("Description");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Qt::TextAlignmentRole:
|
case Qt::TextAlignmentRole:
|
||||||
item = Qt::AlignLeft + Qt::AlignVCenter;
|
item = Qt::AlignLeft + Qt::AlignVCenter;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case source_column:
|
case source_column:
|
||||||
switch (role)
|
switch (role)
|
||||||
@ -826,9 +840,6 @@ QVariant FrequencyList_v2::impl::data (QModelIndex const& index, int role) const
|
|||||||
case Qt::DisplayRole:
|
case Qt::DisplayRole:
|
||||||
case Qt::EditRole:
|
case Qt::EditRole:
|
||||||
case Qt::AccessibleTextRole:
|
case Qt::AccessibleTextRole:
|
||||||
item = frequency_item.start_time_ == frequency_item.end_time_
|
|
||||||
? tr ("Equal")
|
|
||||||
: tr ("NOTEQUAL");
|
|
||||||
item = frequency_item.source_;
|
item = frequency_item.source_;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -847,6 +858,8 @@ QVariant FrequencyList_v2::impl::data (QModelIndex const& index, int role) const
|
|||||||
switch (role)
|
switch (role)
|
||||||
{
|
{
|
||||||
case SortRole:
|
case SortRole:
|
||||||
|
item = frequency_item.start_time_;
|
||||||
|
break;
|
||||||
case Qt::DisplayRole:
|
case Qt::DisplayRole:
|
||||||
case Qt::EditRole:
|
case Qt::EditRole:
|
||||||
case Qt::AccessibleTextRole:
|
case Qt::AccessibleTextRole:
|
||||||
@ -868,6 +881,8 @@ QVariant FrequencyList_v2::impl::data (QModelIndex const& index, int role) const
|
|||||||
switch (role)
|
switch (role)
|
||||||
{
|
{
|
||||||
case SortRole:
|
case SortRole:
|
||||||
|
item = frequency_item.end_time_;
|
||||||
|
break;
|
||||||
case Qt::DisplayRole:
|
case Qt::DisplayRole:
|
||||||
case Qt::EditRole:
|
case Qt::EditRole:
|
||||||
case Qt::AccessibleTextRole:
|
case Qt::AccessibleTextRole:
|
||||||
@ -902,45 +917,111 @@ bool FrequencyList_v2::impl::setData (QModelIndex const& model_index, QVariant c
|
|||||||
roles << role;
|
roles << role;
|
||||||
|
|
||||||
auto& item = frequency_list_[row];
|
auto& item = frequency_list_[row];
|
||||||
switch (model_index.column ())
|
switch (model_index.column())
|
||||||
{
|
{
|
||||||
case region_column:
|
case region_column:
|
||||||
{
|
|
||||||
auto region = IARURegions::value (value.toString ());
|
|
||||||
if (region != item.region_)
|
|
||||||
{
|
|
||||||
item.region_ = region;
|
|
||||||
Q_EMIT dataChanged (model_index, model_index, roles);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case mode_column:
|
|
||||||
{
|
|
||||||
auto mode = Modes::value (value.toString ());
|
|
||||||
if (mode != item.mode_)
|
|
||||||
{
|
|
||||||
item.mode_ = mode;
|
|
||||||
Q_EMIT dataChanged (model_index, model_index, roles);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case frequency_column:
|
|
||||||
if (value.canConvert<Frequency> ())
|
|
||||||
{
|
{
|
||||||
Radio::Frequency frequency {qvariant_cast <Radio::Frequency> (value)};
|
auto region = IARURegions::value(value.toString());
|
||||||
if (frequency != item.frequency_)
|
if (region != item.region_)
|
||||||
{
|
{
|
||||||
item.frequency_ = frequency;
|
item.region_ = region;
|
||||||
// mark derived column (1) changed as well
|
Q_EMIT dataChanged(model_index, model_index, roles);
|
||||||
Q_EMIT dataChanged (index (model_index.row (), 1), model_index, roles);
|
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case mode_column:
|
||||||
|
{
|
||||||
|
auto mode = Modes::value(value.toString());
|
||||||
|
if (mode != item.mode_)
|
||||||
|
{
|
||||||
|
item.mode_ = mode;
|
||||||
|
Q_EMIT dataChanged(model_index, model_index, roles);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case frequency_column:
|
||||||
|
{
|
||||||
|
if (value.canConvert<Frequency>())
|
||||||
|
{
|
||||||
|
Radio::Frequency frequency{qvariant_cast<Radio::Frequency>(value)};
|
||||||
|
if (frequency != item.frequency_)
|
||||||
|
{
|
||||||
|
item.frequency_ = frequency;
|
||||||
|
// mark derived column (1) changed as well
|
||||||
|
Q_EMIT dataChanged(index(model_index.row(), 1), model_index, roles);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case description_column:
|
||||||
|
{
|
||||||
|
if (value.toString() != item.description_)
|
||||||
|
{
|
||||||
|
item.description_ = value.toString();
|
||||||
|
Q_EMIT dataChanged(model_index, model_index, roles);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case source_column:
|
||||||
|
{
|
||||||
|
if (value.toString() != item.source_)
|
||||||
|
{
|
||||||
|
item.source_ = value.toString();
|
||||||
|
Q_EMIT dataChanged(model_index, model_index, roles);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case start_time_column:
|
||||||
|
{
|
||||||
|
QDateTime start_time = QDateTime::fromString(value.toString(), Qt::ISODate);
|
||||||
|
LOG_INFO(QString{"start_time = %1 - isEmpty %2"}.arg(value.toString()).arg(value.toString().isEmpty()));
|
||||||
|
if (value.toString().isEmpty())
|
||||||
|
{ // empty string is valid
|
||||||
|
start_time = QDateTime();
|
||||||
|
}
|
||||||
|
if (start_time.isValid() || start_time.isNull())
|
||||||
|
{
|
||||||
|
item.start_time_ = start_time;
|
||||||
|
if (item.end_time_.isValid() && !item.start_time_.isNull() && item.end_time_ < item.start_time_)
|
||||||
|
{
|
||||||
|
item.end_time_ = item.start_time_;
|
||||||
|
}
|
||||||
|
Q_EMIT dataChanged(model_index, index(model_index.row(), end_time_column), roles);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case end_time_column:
|
||||||
|
{
|
||||||
|
QDateTime end_time = QDateTime::fromString(value.toString(), Qt::ISODate);
|
||||||
|
if (value.toString().isEmpty())
|
||||||
|
{ // empty string is valid
|
||||||
|
end_time = QDateTime();
|
||||||
|
}
|
||||||
|
if (end_time.isValid() || end_time.isNull())
|
||||||
|
{
|
||||||
|
item.end_time_ = end_time;
|
||||||
|
if (item.start_time_.isValid() && !item.end_time_.isNull() && end_time <= item.start_time_)
|
||||||
|
{
|
||||||
|
item.start_time_ = end_time;
|
||||||
|
}
|
||||||
|
Q_EMIT dataChanged(index(model_index.row(), start_time_column), model_index, roles);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1104,8 +1185,57 @@ auto FrequencyList_v2::all_bands (Region region, Mode mode) const -> BandSet
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FrequencyList_v2::FrequencyItems FrequencyList_v2::from_json_file(QFile *input_file)
|
||||||
|
{
|
||||||
|
FrequencyList_v2::FrequencyItems list;
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(input_file->readAll());
|
||||||
|
if (doc.isNull())
|
||||||
|
{
|
||||||
|
throw ReadFileException {tr ("Failed to parse JSON file")};
|
||||||
|
}
|
||||||
|
QJsonObject obj = doc.object();
|
||||||
|
if (obj.isEmpty())
|
||||||
|
{
|
||||||
|
throw ReadFileException{tr("Information Missing")};
|
||||||
|
}
|
||||||
|
QJsonArray arr = obj["frequencies"].toArray();
|
||||||
|
if (arr.isEmpty())
|
||||||
|
{
|
||||||
|
throw ReadFileException{tr ("No Frequencies were found")};
|
||||||
|
}
|
||||||
|
int valid_entry_count = 0;
|
||||||
|
int skipped_entry_count = 0;
|
||||||
|
for (auto const &item: arr)
|
||||||
|
{
|
||||||
|
QString mode_s, region_s;
|
||||||
|
QJsonObject obj = item.toObject();
|
||||||
|
FrequencyList_v2::Item freq;
|
||||||
|
region_s = obj["region"].toString();
|
||||||
|
mode_s = obj["mode"].toString();
|
||||||
|
|
||||||
|
freq.frequency_ = obj["frequency"].toString().toDouble() * 1e6;
|
||||||
|
freq.region_ = IARURegions::value(region_s);
|
||||||
|
freq.mode_ = Modes::value(mode_s);
|
||||||
|
freq.description_ = obj["description"].toString();
|
||||||
|
freq.source_ = obj["source"].toString();
|
||||||
|
freq.start_time_ = QDateTime::fromString(obj["start_time"].toString(), Qt::ISODate);
|
||||||
|
freq.end_time_ = QDateTime::fromString(obj["end_time"].toString(), Qt::ISODate);
|
||||||
|
if ((freq.mode_ != Modes::ALL || QString::compare("ALL", mode_s)) &&
|
||||||
|
(freq.region_ != IARURegions::ALL || QString::compare("ALL", region_s, Qt::CaseInsensitive)) &&
|
||||||
|
freq.isSane())
|
||||||
|
{
|
||||||
|
list.push_back(freq);
|
||||||
|
valid_entry_count++;
|
||||||
|
} else
|
||||||
|
skipped_entry_count++;
|
||||||
|
}
|
||||||
|
//MessageBox::information_message(this, tr("Loaded Frequencies from %1").arg(file_name),
|
||||||
|
// tr("Entries Valid/Skipped %1").arg(QString::number(valid_entry_count) + "/" +
|
||||||
|
// QString::number(skipped_entry_count)));
|
||||||
|
return list;
|
||||||
|
}
|
||||||
// write JSON format to a file
|
// write JSON format to a file
|
||||||
void FrequencyList_v2::to_json_stream(QDataStream *ods, QString magic_s, QString version_s,
|
void FrequencyList_v2::to_json_file(QFile *output_file, QString magic_s, QString version_s,
|
||||||
FrequencyItems const &frequency_items)
|
FrequencyItems const &frequency_items)
|
||||||
{
|
{
|
||||||
QJsonObject jobject{
|
QJsonObject jobject{
|
||||||
@ -1122,25 +1252,7 @@ void FrequencyList_v2::to_json_stream(QDataStream *ods, QString magic_s, QString
|
|||||||
jobject["frequencies"] = array;
|
jobject["frequencies"] = array;
|
||||||
|
|
||||||
QJsonDocument d = QJsonDocument(jobject);
|
QJsonDocument d = QJsonDocument(jobject);
|
||||||
ods->writeRawData(d.toJson().data(), d.toJson().size());
|
output_file->write(d.toJson());
|
||||||
}
|
|
||||||
|
|
||||||
QTextStream& qStdOut()
|
|
||||||
{
|
|
||||||
static QTextStream ts( stdout );
|
|
||||||
return ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
FrequencyList_v2::FrequencyItems FrequencyList_v2::from_json_file(QFile *input_file)
|
|
||||||
{
|
|
||||||
// attempt to read the file as JSON
|
|
||||||
FrequencyList_v2::FrequencyItems list;
|
|
||||||
QByteArray jsonData = input_file->readAll();
|
|
||||||
QJsonDocument jsonDoc(QJsonDocument::fromJson(jsonData));
|
|
||||||
QJsonArray array = jsonDoc.object().value("frequencies").toArray();
|
|
||||||
qStdOut() << "Frequencies read";
|
|
||||||
qStdOut() << array.count();
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// previous version 100 of the FrequencyList_v2 class
|
// previous version 100 of the FrequencyList_v2 class
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QException>
|
||||||
|
|
||||||
#include "Radio.hpp"
|
#include "Radio.hpp"
|
||||||
#include "IARURegions.hpp"
|
#include "IARURegions.hpp"
|
||||||
@ -56,19 +57,19 @@ public:
|
|||||||
Frequency frequency_;
|
Frequency frequency_;
|
||||||
Mode mode_;
|
Mode mode_;
|
||||||
Region region_;
|
Region region_;
|
||||||
QString toString () const;
|
|
||||||
bool isSane() const;
|
|
||||||
QJsonObject toJson () const;
|
|
||||||
QString description_;
|
QString description_;
|
||||||
QString source_;
|
QString source_;
|
||||||
QDateTime start_time_;
|
QDateTime start_time_;
|
||||||
QDateTime end_time_;
|
QDateTime end_time_;
|
||||||
|
QString toString () const;
|
||||||
|
bool isSane() const;
|
||||||
|
QJsonObject toJson () const;
|
||||||
|
|
||||||
};
|
};
|
||||||
using FrequencyItems = QList<Item>;
|
using FrequencyItems = QList<Item>;
|
||||||
using BandSet = QSet<QString>;
|
using BandSet = QSet<QString>;
|
||||||
|
|
||||||
enum Column {region_column, mode_column, frequency_column, frequency_mhz_column, description_column, start_time_column, end_time_column, source_column, SENTINAL};
|
enum Column {region_column, mode_column, frequency_column, frequency_mhz_column, description_column, start_time_column, end_time_column, source_column, SENTINAL};
|
||||||
|
|
||||||
// an iterator that meets the requirements of the C++ for range statement
|
// an iterator that meets the requirements of the C++ for range statement
|
||||||
class const_iterator
|
class const_iterator
|
||||||
@ -89,7 +90,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
FrequencyList_v2 const * parent_;
|
FrequencyList_v2 const * parent_;
|
||||||
int row_;
|
int row_;
|
||||||
//qint32 qrg_version_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit FrequencyList_v2 (Bands const *, QObject * parent = nullptr);
|
explicit FrequencyList_v2 (Bands const *, QObject * parent = nullptr);
|
||||||
@ -101,8 +101,8 @@ public:
|
|||||||
FrequencyItems const& frequency_list () const;
|
FrequencyItems const& frequency_list () const;
|
||||||
FrequencyItems frequency_list (QModelIndexList const&) const;
|
FrequencyItems frequency_list (QModelIndexList const&) const;
|
||||||
void frequency_list_merge (FrequencyItems const&);
|
void frequency_list_merge (FrequencyItems const&);
|
||||||
void to_json_stream(QDataStream *, QString, QString, FrequencyItems const&);
|
void to_json_file(QFile *, QString, QString, FrequencyItems const&);
|
||||||
FrequencyList_v2::FrequencyItems from_json_file(QFile *);
|
static FrequencyItems from_json_file(QFile *);
|
||||||
|
|
||||||
// Iterators for the sorted and filtered items
|
// Iterators for the sorted and filtered items
|
||||||
//
|
//
|
||||||
@ -131,7 +131,7 @@ public:
|
|||||||
int best_working_frequency (QString const& band) const;
|
int best_working_frequency (QString const& band) const;
|
||||||
|
|
||||||
// Set filter
|
// Set filter
|
||||||
Q_SLOT void filter (Region, Mode);
|
Q_SLOT void filter (Region, Mode, bool);
|
||||||
|
|
||||||
// Reset
|
// Reset
|
||||||
Q_SLOT void reset_to_defaults ();
|
Q_SLOT void reset_to_defaults ();
|
||||||
@ -144,6 +144,9 @@ public:
|
|||||||
// Proxy API
|
// Proxy API
|
||||||
bool filterAcceptsRow (int source_row, QModelIndex const& parent) const override;
|
bool filterAcceptsRow (int source_row, QModelIndex const& parent) const override;
|
||||||
|
|
||||||
|
// Refresh the filter based on the current filter settings (underlying data may have changed)
|
||||||
|
void filter_refresh ();
|
||||||
|
|
||||||
// Custom roles.
|
// Custom roles.
|
||||||
static int constexpr SortRole = Qt::UserRole;
|
static int constexpr SortRole = Qt::UserRole;
|
||||||
|
|
||||||
@ -158,7 +161,11 @@ bool operator == (FrequencyList_v2::Item const& lhs, FrequencyList_v2::Item cons
|
|||||||
return
|
return
|
||||||
lhs.frequency_ == rhs.frequency_
|
lhs.frequency_ == rhs.frequency_
|
||||||
&& lhs.region_ == rhs.region_
|
&& lhs.region_ == rhs.region_
|
||||||
&& lhs.mode_ == rhs.mode_;
|
&& lhs.mode_ == rhs.mode_
|
||||||
|
&& lhs.description_ == rhs.description_
|
||||||
|
&& lhs.source_ == rhs.source_
|
||||||
|
&& lhs.start_time_ == rhs.start_time_
|
||||||
|
&& lhs.end_time_ == rhs.end_time_;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDataStream& operator << (QDataStream&, FrequencyList_v2::Item const&);
|
QDataStream& operator << (QDataStream&, FrequencyList_v2::Item const&);
|
||||||
@ -224,4 +231,18 @@ QDataStream& operator >> (QDataStream&, FrequencyList::Item&);
|
|||||||
Q_DECLARE_METATYPE (FrequencyList::Item);
|
Q_DECLARE_METATYPE (FrequencyList::Item);
|
||||||
Q_DECLARE_METATYPE (FrequencyList::FrequencyItems);
|
Q_DECLARE_METATYPE (FrequencyList::FrequencyItems);
|
||||||
|
|
||||||
|
class ReadFileException : public QException {
|
||||||
|
public:
|
||||||
|
ReadFileException (QString const& message)
|
||||||
|
: message_ {message}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void raise () const override { throw *this; }
|
||||||
|
ReadFileException * clone () const override { return new ReadFileException {*this}; }
|
||||||
|
|
||||||
|
QString filename_;
|
||||||
|
QString message_;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1035,6 +1035,8 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
|||||||
m_wideGraph->setMode(m_mode);
|
m_wideGraph->setMode(m_mode);
|
||||||
|
|
||||||
connect (&minuteTimer, &QTimer::timeout, this, &MainWindow::on_the_minute);
|
connect (&minuteTimer, &QTimer::timeout, this, &MainWindow::on_the_minute);
|
||||||
|
connect (&minuteTimer, &QTimer::timeout, this, &MainWindow::invalidate_frequencies_filter);
|
||||||
|
|
||||||
minuteTimer.setSingleShot (true);
|
minuteTimer.setSingleShot (true);
|
||||||
minuteTimer.start (ms_minute_error () + 60 * 1000);
|
minuteTimer.start (ms_minute_error () + 60 * 1000);
|
||||||
|
|
||||||
@ -1079,6 +1081,14 @@ void MainWindow::splash_done ()
|
|||||||
m_splash && m_splash->close ();
|
m_splash && m_splash->close ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::invalidate_frequencies_filter ()
|
||||||
|
{
|
||||||
|
// every interval, invalidate the frequency filter, so that if any
|
||||||
|
// working frequency goes in/out of scope, we pick it up.
|
||||||
|
m_config.frequencies ()->filter_refresh ();
|
||||||
|
ui->bandComboBox->update ();
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::on_the_minute ()
|
void MainWindow::on_the_minute ()
|
||||||
{
|
{
|
||||||
if (minuteTimer.isSingleShot ())
|
if (minuteTimer.isSingleShot ())
|
||||||
@ -7159,7 +7169,7 @@ void MainWindow::on_actionFreqCal_triggered()
|
|||||||
void MainWindow::switch_mode (Mode mode)
|
void MainWindow::switch_mode (Mode mode)
|
||||||
{
|
{
|
||||||
m_fastGraph->setMode(m_mode);
|
m_fastGraph->setMode(m_mode);
|
||||||
m_config.frequencies ()->filter (m_config.region (), mode);
|
m_config.frequencies ()->filter (m_config.region (), mode, true); // filter on current time
|
||||||
auto const& row = m_config.frequencies ()->best_working_frequency (m_freqNominal);
|
auto const& row = m_config.frequencies ()->best_working_frequency (m_freqNominal);
|
||||||
ui->bandComboBox->setCurrentIndex (row);
|
ui->bandComboBox->setCurrentIndex (row);
|
||||||
if (row >= 0) {
|
if (row >= 0) {
|
||||||
|
@ -824,6 +824,7 @@ private:
|
|||||||
void subProcessError (QProcess *, QProcess::ProcessError);
|
void subProcessError (QProcess *, QProcess::ProcessError);
|
||||||
void statusUpdate () const;
|
void statusUpdate () const;
|
||||||
void update_watchdog_label ();
|
void update_watchdog_label ();
|
||||||
|
void invalidate_frequencies_filter ();
|
||||||
void on_the_minute ();
|
void on_the_minute ();
|
||||||
void add_child_to_event_filter (QObject *);
|
void add_child_to_event_filter (QObject *);
|
||||||
void remove_child_from_event_filter (QObject *);
|
void remove_child_from_event_filter (QObject *);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user