| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  | #include "StationList.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <utility>
 | 
					
						
							|  |  |  | #include <algorithm>
 | 
					
						
							|  |  |  | #include <cmath>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <QMetaType>
 | 
					
						
							|  |  |  | #include <QAbstractTableModel>
 | 
					
						
							|  |  |  | #include <QObject>
 | 
					
						
							|  |  |  | #include <QString>
 | 
					
						
							|  |  |  | #include <QVector>
 | 
					
						
							|  |  |  | #include <QStringList>
 | 
					
						
							|  |  |  | #include <QMimeData>
 | 
					
						
							|  |  |  | #include <QDataStream>
 | 
					
						
							|  |  |  | #include <QByteArray>
 | 
					
						
							| 
									
										
										
										
											2020-09-26 13:57:21 +01:00
										 |  |  | #include <QTextStream>
 | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  | #include <QDebug>
 | 
					
						
							| 
									
										
										
										
											2016-04-06 17:11:02 +00:00
										 |  |  | #include <QDebugStateSaver>
 | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "pimpl_impl.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 23:58:00 +00:00
										 |  |  | #include "Radio.hpp"
 | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  | #include "Bands.hpp"
 | 
					
						
							| 
									
										
										
										
											2015-11-13 23:44:48 +00:00
										 |  |  | #include "FrequencyList.hpp"
 | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if !defined (QT_NO_DEBUG_STREAM)
 | 
					
						
							|  |  |  | QDebug operator << (QDebug debug, StationList::Station const& station) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-04-06 17:11:02 +00:00
										 |  |  |   QDebugStateSaver saver {debug}; | 
					
						
							| 
									
										
										
										
											2020-09-26 13:57:21 +01:00
										 |  |  |   return debug.nospace () << station.toString (); | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-26 13:57:21 +01:00
										 |  |  | QString StationList::Station::toString () const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   QString string; | 
					
						
							|  |  |  |   QTextStream ots {&string}; | 
					
						
							|  |  |  |   ots << "Station(" | 
					
						
							|  |  |  |       << band_name_ << ", " | 
					
						
							|  |  |  |       << Radio::frequency_MHz_string (offset_) << ", " | 
					
						
							|  |  |  |       << antenna_description_ << ')'; | 
					
						
							|  |  |  |   return string; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  | QDataStream& operator << (QDataStream& os, StationList::Station const& station) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return os << station.band_name_ | 
					
						
							|  |  |  |             << station.offset_ | 
					
						
							|  |  |  |             << station.antenna_description_; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QDataStream& operator >> (QDataStream& is, StationList::Station& station) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return is >> station.band_name_ | 
					
						
							|  |  |  |             >> station.offset_ | 
					
						
							|  |  |  |             >> station.antenna_description_; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class StationList::impl final | 
					
						
							|  |  |  |   : public QAbstractTableModel | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-06-06 12:56:25 +01:00
										 |  |  |   Q_OBJECT | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  | public: | 
					
						
							|  |  |  |   impl (Bands const * bands, Stations stations, QObject * parent) | 
					
						
							|  |  |  |     : QAbstractTableModel {parent} | 
					
						
							|  |  |  |     , bands_ {bands} | 
					
						
							|  |  |  |     , stations_ {stations} | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  |   Stations station_list (Stations); | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  |   QModelIndex add (Station); | 
					
						
							|  |  |  |   FrequencyDelta offset (Frequency) const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Implement the QAbstractTableModel interface.
 | 
					
						
							|  |  |  |   int rowCount (QModelIndex const& parent = QModelIndex {}) const override; | 
					
						
							|  |  |  |   int columnCount (QModelIndex const& parent = QModelIndex {}) const override; | 
					
						
							|  |  |  |   Qt::ItemFlags flags (QModelIndex const& = QModelIndex {}) const override; | 
					
						
							|  |  |  |   QVariant data (QModelIndex const&, int role) const override; | 
					
						
							|  |  |  |   QVariant headerData (int section, Qt::Orientation, int = Qt::DisplayRole) const override; | 
					
						
							|  |  |  |   bool setData (QModelIndex const&, QVariant const& value, int role = Qt::EditRole) override; | 
					
						
							|  |  |  |   bool removeRows (int row, int count, QModelIndex const& parent = QModelIndex {}) override; | 
					
						
							|  |  |  |   bool insertRows (int row, int count, QModelIndex const& parent = QModelIndex {}) override; | 
					
						
							|  |  |  |   Qt::DropActions supportedDropActions () const override; | 
					
						
							|  |  |  |   QStringList mimeTypes () const override; | 
					
						
							|  |  |  |   QMimeData * mimeData (QModelIndexList const&) const override; | 
					
						
							|  |  |  |   bool dropMimeData (QMimeData const *, Qt::DropAction, int row, int column, QModelIndex const& parent) override; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Helper method for band validation.
 | 
					
						
							|  |  |  |   QModelIndex first_matching_band (QString const& band_name) const | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     // find first exact match in bands
 | 
					
						
							|  |  |  |     auto matches = bands_->match (bands_->index (0, 0) | 
					
						
							|  |  |  |                                   , Qt::DisplayRole | 
					
						
							|  |  |  |                                   , band_name | 
					
						
							|  |  |  |                                   , 1 | 
					
						
							|  |  |  |                                   , Qt::MatchExactly); | 
					
						
							|  |  |  |     return matches.isEmpty () ? QModelIndex {} : matches.first (); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static int constexpr num_columns {3}; | 
					
						
							|  |  |  |   static auto constexpr mime_type = "application/wsjt.antenna-descriptions"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Bands const * bands_; | 
					
						
							|  |  |  |   Stations stations_; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-06 12:56:25 +01:00
										 |  |  | #include "StationList.moc"
 | 
					
						
							|  |  |  | #include "moc_StationList.cpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  | StationList::StationList (Bands const * bands, QObject * parent) | 
					
						
							|  |  |  |   : StationList {bands, {}, parent} | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | StationList::StationList (Bands const * bands, Stations stations, QObject * parent) | 
					
						
							|  |  |  |   : QSortFilterProxyModel {parent} | 
					
						
							|  |  |  |   , m_ {bands, stations, parent} | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   setSourceModel (&*m_); | 
					
						
							|  |  |  |   setSortRole (SortRole); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | StationList::~StationList () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  | auto StationList::station_list (Stations stations) -> Stations | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  |   return m_->station_list (stations); | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  | auto StationList::station_list () const -> Stations const& | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  |   return m_->stations_; | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QModelIndex StationList::add (Station s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return mapFromSource (m_->add (s)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool StationList::remove (Station s) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  |   auto row = m_->stations_.indexOf (s); | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  |   if (0 > row) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return removeRow (row); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool StationList::removeDisjointRows (QModelIndexList rows) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   bool result {true}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // We must work with source model indexes because we don't want row
 | 
					
						
							|  |  |  |   // removes to invalidate model indexes we haven't yet processed. We
 | 
					
						
							|  |  |  |   // achieve that by processing them in decending row order.
 | 
					
						
							|  |  |  |   for (int r = 0; r < rows.size (); ++r) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       rows[r] = mapToSource (rows[r]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // reverse sort by row
 | 
					
						
							| 
									
										
										
										
											2018-11-25 22:13:15 +00:00
										 |  |  |   std::sort (rows.begin (), rows.end (), [] (QModelIndex const& lhs, QModelIndex const& rhs) | 
					
						
							|  |  |  |              { | 
					
						
							|  |  |  |                return rhs.row () < lhs.row (); // reverse row ordering
 | 
					
						
							|  |  |  |              }); | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  |   Q_FOREACH (auto index, rows) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (result && !m_->removeRow (index.row ())) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           result = false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | auto StationList::offset (Frequency f) const -> FrequencyDelta | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return m_->offset (f); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  | auto StationList::impl::station_list (Stations stations) -> Stations | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   beginResetModel (); | 
					
						
							|  |  |  |   std::swap (stations_, stations); | 
					
						
							|  |  |  |   endResetModel (); | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  |   return stations; | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QModelIndex StationList::impl::add (Station s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   // Any band that isn't in the list may be added
 | 
					
						
							|  |  |  |   if (!stations_.contains (s)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       auto row = stations_.size (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       beginInsertRows (QModelIndex {}, row, row); | 
					
						
							|  |  |  |       stations_.append (s); | 
					
						
							|  |  |  |       endInsertRows (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return index (row, 0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return QModelIndex {}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | auto StationList::impl::offset (Frequency f) const -> FrequencyDelta | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   // Lookup band for frequency
 | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  |   auto const& band = bands_->find (f); | 
					
						
							| 
									
										
										
										
											2015-05-31 11:51:31 +00:00
										 |  |  |   if (!band.isEmpty ()) | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       // Lookup station for band
 | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  |       for (int i = 0; i < stations_.size (); ++i) | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2015-05-31 11:51:31 +00:00
										 |  |  |           if (stations_[i].band_name_ == band) | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  |             { | 
					
						
							|  |  |  |               return stations_[i].offset_; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  |   return 0;                     // no offset
 | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int StationList::impl::rowCount (QModelIndex const& parent) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return parent.isValid () ? 0 : stations_.size (); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int StationList::impl::columnCount (QModelIndex const& parent) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return parent.isValid () ? 0 : num_columns; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Qt::ItemFlags StationList::impl::flags (QModelIndex const& index) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   auto result = QAbstractTableModel::flags (index); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   auto row = index.row (); | 
					
						
							|  |  |  |   auto column = index.column (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (index.isValid () | 
					
						
							|  |  |  |       && row < stations_.size () | 
					
						
							|  |  |  |       && column < num_columns) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  |       if (description_column == column) | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |           result |= Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           result |= Qt::ItemIsEditable | Qt::ItemIsDropEnabled; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       result |= Qt::ItemIsDropEnabled; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QVariant StationList::impl::data (QModelIndex const& index, int role) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   QVariant item; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   auto row = index.row (); | 
					
						
							|  |  |  |   auto column = index.column (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (index.isValid () | 
					
						
							|  |  |  |       && row < stations_.size ()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       switch (column) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  |         case band_column: | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  |           switch (role) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |             case SortRole: | 
					
						
							|  |  |  |               { | 
					
						
							|  |  |  |                 // Lookup band.
 | 
					
						
							|  |  |  |                 auto band_index = first_matching_band (stations_.at (row).band_name_); | 
					
						
							|  |  |  |                 // Use the sort role value of the band.
 | 
					
						
							|  |  |  |                 item = band_index.data (Bands::SortRole); | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case Qt::DisplayRole: | 
					
						
							|  |  |  |             case Qt::EditRole: | 
					
						
							|  |  |  |             case Qt::AccessibleTextRole: | 
					
						
							|  |  |  |               item = stations_.at (row).band_name_; | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case Qt::ToolTipRole: | 
					
						
							|  |  |  |             case Qt::AccessibleDescriptionRole: | 
					
						
							|  |  |  |               item = tr ("Band name"); | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case Qt::TextAlignmentRole: | 
					
						
							|  |  |  |               item = Qt::AlignHCenter + Qt::AlignVCenter; | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  |         case offset_column: | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  |           { | 
					
						
							|  |  |  |             auto frequency_offset = stations_.at (row).offset_; | 
					
						
							|  |  |  |             switch (role) | 
					
						
							|  |  |  |               { | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  |               case SortRole: | 
					
						
							|  |  |  |               case Qt::EditRole: | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  |               case Qt::AccessibleTextRole: | 
					
						
							|  |  |  |                 item = frequency_offset; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |               case Qt::DisplayRole: | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  |                 item = Radio::pretty_frequency_MHz_string (frequency_offset) + " MHz"; | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  |                 break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |               case Qt::ToolTipRole: | 
					
						
							|  |  |  |               case Qt::AccessibleDescriptionRole: | 
					
						
							|  |  |  |                 item = tr ("Frequency offset"); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |               case Qt::TextAlignmentRole: | 
					
						
							|  |  |  |                 item = Qt::AlignRight + Qt::AlignVCenter; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  |         case description_column: | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  |           switch (role) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |             case SortRole: | 
					
						
							|  |  |  |             case Qt::EditRole: | 
					
						
							|  |  |  |             case Qt::DisplayRole: | 
					
						
							|  |  |  |             case Qt::AccessibleTextRole: | 
					
						
							|  |  |  |               item = stations_.at (row).antenna_description_; | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case Qt::ToolTipRole: | 
					
						
							|  |  |  |             case Qt::AccessibleDescriptionRole: | 
					
						
							|  |  |  |               item = tr ("Antenna description"); | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case Qt::TextAlignmentRole: | 
					
						
							|  |  |  |               item = Qt::AlignLeft + Qt::AlignVCenter; | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return item; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QVariant StationList::impl::headerData (int section, Qt::Orientation orientation, int role) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   QVariant header; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (Qt::DisplayRole == role && Qt::Horizontal == orientation) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       switch (section) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  |         case band_column: header = tr ("Band"); break; | 
					
						
							|  |  |  |         case offset_column: header = tr ("Offset"); break; | 
					
						
							|  |  |  |         case description_column: header = tr ("Antenna Description"); break; | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       header = QAbstractTableModel::headerData (section, orientation, role); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return header; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool StationList::impl::setData (QModelIndex const& model_index, QVariant const& value, int role) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   bool changed {false}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   auto row = model_index.row (); | 
					
						
							|  |  |  |   auto size = stations_.size (); | 
					
						
							|  |  |  |   if (model_index.isValid () | 
					
						
							|  |  |  |       && Qt::EditRole == role | 
					
						
							|  |  |  |       && row < size) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       QVector<int> roles; | 
					
						
							|  |  |  |       roles << role; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       switch (model_index.column ()) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  |         case band_column: | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  |           { | 
					
						
							|  |  |  |             // Check if band name is valid.
 | 
					
						
							|  |  |  |             auto band_index = first_matching_band (value.toString ()); | 
					
						
							|  |  |  |             if (band_index.isValid ()) | 
					
						
							|  |  |  |               { | 
					
						
							|  |  |  |                 stations_[row].band_name_ = band_index.data ().toString (); | 
					
						
							|  |  |  |                 Q_EMIT dataChanged (model_index, model_index, roles); | 
					
						
							|  |  |  |                 changed = true; | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  |         case offset_column: | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  |           { | 
					
						
							| 
									
										
										
										
											2017-01-08 23:58:00 +00:00
										 |  |  |             if (value.canConvert<FrequencyDelta> ()) | 
					
						
							|  |  |  |               { | 
					
						
							|  |  |  |                 FrequencyDelta offset {qvariant_cast<Radio::FrequencyDelta> (value)}; | 
					
						
							|  |  |  |                 if (offset != stations_[row].offset_) | 
					
						
							|  |  |  |                   { | 
					
						
							|  |  |  |                     stations_[row].offset_ = offset; | 
					
						
							|  |  |  |                     Q_EMIT dataChanged (model_index, model_index, roles); | 
					
						
							|  |  |  |                     changed = true; | 
					
						
							|  |  |  |                   } | 
					
						
							|  |  |  |               } | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  |           } | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  |         case description_column: | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  |           stations_[row].antenna_description_ = value.toString (); | 
					
						
							|  |  |  |           Q_EMIT dataChanged (model_index, model_index, roles); | 
					
						
							|  |  |  |           changed = true; | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return changed; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool StationList::impl::removeRows (int row, int count, QModelIndex const& parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (0 < count && (row + count) <= rowCount (parent)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       beginRemoveRows (parent, row, row + count - 1); | 
					
						
							|  |  |  |       for (auto r = 0; r < count; ++r) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           stations_.removeAt (row); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       endRemoveRows (); | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool StationList::impl::insertRows (int row, int count, QModelIndex const& parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (0 < count) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       beginInsertRows (parent, row, row + count - 1); | 
					
						
							|  |  |  |       for (auto r = 0; r < count; ++r) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           stations_.insert (row, Station ()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       endInsertRows (); | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Qt::DropActions StationList::impl::supportedDropActions () const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return Qt::CopyAction | Qt::MoveAction; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QStringList StationList::impl::mimeTypes () const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   QStringList types; | 
					
						
							|  |  |  |   types << mime_type; | 
					
						
							|  |  |  |   types << "application/wsjt.Frequencies"; | 
					
						
							|  |  |  |   return types; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QMimeData * StationList::impl::mimeData (QModelIndexList const& items) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   QMimeData * mime_data = new QMimeData {}; | 
					
						
							|  |  |  |   QByteArray encoded_data; | 
					
						
							|  |  |  |   QDataStream stream {&encoded_data, QIODevice::WriteOnly}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Q_FOREACH (auto const& item, items) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (item.isValid ()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           stream << QString {data (item, Qt::DisplayRole).toString ()}; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   mime_data->setData (mime_type, encoded_data); | 
					
						
							|  |  |  |   return mime_data; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool StationList::impl::dropMimeData (QMimeData const * data, Qt::DropAction action, int /* row */, int /* column */, QModelIndex const& parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (Qt::IgnoreAction == action) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   if (parent.isValid () | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  |       && description_column == parent.column () | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  |       && data->hasFormat (mime_type)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       QByteArray encoded_data {data->data (mime_type)}; | 
					
						
							|  |  |  |       QDataStream stream {&encoded_data, QIODevice::ReadOnly}; | 
					
						
							|  |  |  |       auto dest_index = parent; | 
					
						
							|  |  |  |       while (!stream.atEnd ()) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           QString text; | 
					
						
							|  |  |  |           stream >> text; | 
					
						
							|  |  |  |           setData (dest_index, text); | 
					
						
							|  |  |  |           dest_index = index (dest_index.row () + 1, dest_index.column (), QModelIndex {}); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else if (data->hasFormat ("application/wsjt.Frequencies")) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       QByteArray encoded_data {data->data ("application/wsjt.Frequencies")}; | 
					
						
							|  |  |  |       QDataStream stream {&encoded_data, QIODevice::ReadOnly}; | 
					
						
							|  |  |  |       while (!stream.atEnd ()) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2017-08-09 16:06:17 +00:00
										 |  |  |           FrequencyList_v2::Item item; | 
					
						
							| 
									
										
										
										
											2015-11-13 23:44:48 +00:00
										 |  |  |           stream >> item; | 
					
						
							|  |  |  |           auto const& band = bands_->find (item.frequency_); | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  |           if (stations_.cend () == std::find_if (stations_.cbegin () | 
					
						
							|  |  |  |                                                  , stations_.cend () | 
					
						
							| 
									
										
										
										
											2015-05-31 11:51:31 +00:00
										 |  |  |                                                  , [&band] (Station const& s) {return s.band_name_ == band;})) | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  |             { | 
					
						
							| 
									
										
										
										
											2015-05-28 23:22:17 +00:00
										 |  |  |               // not found so add it
 | 
					
						
							| 
									
										
										
										
											2015-05-31 11:51:31 +00:00
										 |  |  |               add (Station {band, 0, QString {}}); | 
					
						
							| 
									
										
										
										
											2015-04-06 01:57:47 +00:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   return false; | 
					
						
							|  |  |  | } |