js8call/JS8_Main/FrequencyList.h
rruchte 97e4a07bc4 Addresses #193
- Enables custom descriptions for frequencies
- Handle unreadable/unwritable frequencies file
- Add delete key shortcut to frequencies and scheduled frequency change tables
2026-02-23 23:25:06 -05:00

207 lines
5.9 KiB
C++

#ifndef FREQUENCY_LIST_HPP__
#define FREQUENCY_LIST_HPP__
#include "IARURegions.h"
#include "JS8_Include/pimpl_h.h"
#include "Modes.h"
#include "Radio.h"
#include <QList>
#include <QSortFilterProxyModel>
class Bands;
//
// Class FrequencyList_v3
//
// Encapsulates a collection of frequencies with associated modes.
// The implementation is a table containing the list of IARU region,
// Frequency and mode tuples which are editable. A third column is
// modeled in the model which is an immutable double representation
// of the corresponding Frequency item scaled to mega-Hertz. The final,
// column column allows entry of a description for the entry.
//
// The list is ordered. A filter on IARU region and mode is
// available and is set by the filter(Region, Mode) method. The
// Region value IARURegions::ALL and the Mode value Modes::ALL may be
// optionally given which passes all rows in the filtered column.
//
// Responsibilities
//
// Stores internally a list of unique region, frequency mode tuples.
// Provides methods to add and delete list elements. Provides range
// iterators for a filtered view of the underlying table.
//
// Collaborations
//
// Implements the QSortFilterProxyModel interface for a list of spot
// frequencies.
//
class FrequencyList_v3 final : public QSortFilterProxyModel {
Q_OBJECT;
public:
using Region = IARURegions::Region;
using Frequency = Radio::Frequency;
using Mode = Modes::Mode;
struct Item {
Frequency frequency_;
Mode mode_;
Region region_;
QString description_;
};
using FrequencyItems = QList<Item>;
using BandSet = QSet<QString>;
enum Column {
region_column,
mode_column,
frequency_column,
frequency_mhz_column,
description_column,
SENTINAL
};
// an iterator that meets the requirements of the C++ for range statement
class const_iterator {
public:
const_iterator(FrequencyList_v3 const *parent, int row)
: parent_{parent}, row_{row} {}
Item const &operator*() const;
Item const *operator->() const;
bool operator!=(const_iterator const &) const;
bool operator==(const_iterator const &) const;
const_iterator &operator++();
private:
FrequencyList_v3 const *parent_;
int row_;
};
explicit FrequencyList_v3(Bands const *, QObject *parent = nullptr);
~FrequencyList_v3();
// Load and store underlying items
FrequencyItems frequency_list(FrequencyItems);
FrequencyItems const &frequency_list() const;
FrequencyItems frequency_list(QModelIndexList const &) const;
void frequency_list_merge(FrequencyItems const &);
// Iterators for the sorted and filtered items
//
// Note that these iterators are on the final sorted and filtered
// rows, if you need to access the underlying unfiltered and
// unsorted frequencies then use the frequency_list() member to
// access the underlying list of rows.
const_iterator begin() const;
const_iterator end() const;
// Find a row with a given frequency
const_iterator find(Frequency) const;
// Bands of the frequencies
BandSet all_bands(Region = IARURegions::ALL, Mode = Modes::ALL) const;
BandSet filtered_bands() const;
// Find the row of the nearest best working frequency given a
// frequency. Returns -1 if no suitable working frequency is found
// in the list.
int best_working_frequency(Frequency) const;
// Find the row of the nearest best working frequency given a band
// name. Returns -1 if no suitable working frequency is found in the
// list.
int best_working_frequency(QString const &band) const;
// Set filter
Q_SLOT void filter(Region, Mode);
// Reset
Q_SLOT void reset_to_defaults();
// Model API
QModelIndex add(Item);
bool remove(Item);
bool removeDisjointRows(QModelIndexList);
// Proxy API
bool filterAcceptsRow(int source_row,
QModelIndex const &parent) const override;
// Custom roles.
static int constexpr SortRole = Qt::UserRole;
private:
class impl;
pimpl<impl> m_;
};
inline bool operator==(FrequencyList_v3::Item const &lhs,
FrequencyList_v3::Item const &rhs) {
return lhs.frequency_ == rhs.frequency_ && lhs.region_ == rhs.region_ &&
lhs.mode_ == rhs.mode_ && lhs.description_ == rhs.description_;
}
QDataStream &operator<<(QDataStream &, FrequencyList_v3::Item const &);
QDataStream &operator>>(QDataStream &, FrequencyList_v3::Item &);
#if !defined(QT_NO_DEBUG_STREAM)
QDebug operator<<(QDebug, FrequencyList_v3::Item const &);
#endif
Q_DECLARE_METATYPE(FrequencyList_v3::Item);
Q_DECLARE_METATYPE(FrequencyList_v3::FrequencyItems);
//
// Obsolete versions of FrequencyList no longer used but needed to
// allow loading and saving of old settings contents without damage
//
class FrequencyList_v2 final {
public:
using Region = IARURegions::Region;
using Frequency = Radio::Frequency;
using Mode = Modes::Mode;
struct Item {
Frequency frequency_;
Mode mode_;
Region region_;
};
using FrequencyItems = QList<Item>;
private:
FrequencyItems frequency_list_;
};
QDataStream &operator<<(QDataStream &, FrequencyList_v2::Item const &);
QDataStream &operator>>(QDataStream &, FrequencyList_v2::Item &);
Q_DECLARE_METATYPE(FrequencyList_v2::Item);
Q_DECLARE_METATYPE(FrequencyList_v2::FrequencyItems);
class FrequencyList final {
public:
using Frequency = Radio::Frequency;
using Mode = Modes::Mode;
struct Item {
Frequency frequency_;
Mode mode_;
};
using FrequencyItems = QList<Item>;
private:
FrequencyItems frequency_list_;
};
QDataStream &operator<<(QDataStream &, FrequencyList::Item const &);
QDataStream &operator>>(QDataStream &, FrequencyList::Item &);
Q_DECLARE_METATYPE(FrequencyList::Item);
Q_DECLARE_METATYPE(FrequencyList::FrequencyItems);
#endif