diff --git a/Bands.cpp b/Bands.cpp index 3759b634d..d182eb1dd 100644 --- a/Bands.cpp +++ b/Bands.cpp @@ -195,3 +195,29 @@ QVariant Bands::headerData (int section, Qt::Orientation orientation, int role) return result; } + +QString Bands::const_iterator::operator * () +{ + return ADIF_bands[row_].name_; +} + +bool Bands::const_iterator::operator != (const_iterator const& rhs) const +{ + return row_ != rhs.row_; +} + +auto Bands::const_iterator::operator ++ () -> const_iterator& +{ + ++row_; + return *this; +} + +auto Bands::begin () const -> Bands::const_iterator +{ + return const_iterator (0); +} + +auto Bands::end () const -> Bands::const_iterator +{ + return const_iterator (table_rows ()); +} diff --git a/Bands.hpp b/Bands.hpp index 1b61b4283..adfe21309 100644 --- a/Bands.hpp +++ b/Bands.hpp @@ -32,6 +32,23 @@ class Bands final public: using Frequency = Radio::Frequency; + // an iterator that meets the requirements of the C++ for range statement + class const_iterator + { + public: + const_iterator (int row) + : row_ {row} + { + } + + QString operator * (); + bool operator != (const_iterator const&) const; + const_iterator& operator ++ (); + + private: + int row_; + }; + explicit Bands (QObject * parent = nullptr); // @@ -40,6 +57,10 @@ public: QString find (Frequency) const; // find band Frequency is in static QString const& oob (); + // Iterators + const_iterator begin () const; + const_iterator end () const; + // Custom role for sorting. static int constexpr SortRole = Qt::UserRole; diff --git a/FrequencyList.cpp b/FrequencyList.cpp index f9f7b8436..015dfd3c2 100644 --- a/FrequencyList.cpp +++ b/FrequencyList.cpp @@ -173,8 +173,26 @@ int FrequencyList::best_working_frequency (Frequency f) const auto const& target_band = m_->bands_->find (f); if (!target_band.isEmpty ()) { - // find a frequency in the same band that is allowed for the - // target mode + // find a frequency in the same band that is allowed + for (int row = 0; row < rowCount (); ++row) + { + auto const& source_row = mapToSource (index (row, 0)).row (); + auto const& band = m_->bands_->find (m_->frequency_list_[source_row].frequency_); + if (band == target_band) + { + return row; + } + } + } + return result; +} + +int FrequencyList::best_working_frequency (QString const& target_band) const +{ + int result {-1}; + if (!target_band.isEmpty ()) + { + // find a frequency in the same band that is allowed for (int row = 0; row < rowCount (); ++row) { auto const& source_row = mapToSource (index (row, 0)).row (); @@ -553,3 +571,23 @@ auto FrequencyList::end () const -> FrequencyList::const_iterator { return const_iterator (this, rowCount ()); } + +auto FrequencyList::all_bands () const -> BandSet +{ + BandSet result; + for (auto const& item : m_->frequency_list_) + { + result << m_->bands_->find (item.frequency_); + } + return result; +} + +auto FrequencyList::filtered_bands () const -> BandSet +{ + BandSet result; + for (auto const& item : *this) + { + result << m_->bands_->find (item.frequency_); + } + return result; +} diff --git a/FrequencyList.hpp b/FrequencyList.hpp index 0be83abe1..c5c001a8d 100644 --- a/FrequencyList.hpp +++ b/FrequencyList.hpp @@ -14,18 +14,21 @@ class Bands; // // Class FrequencyList // -// Encapsulates a collection of frequencies. The implementation is a -// table containing the list of Frequency type elements which is -// editable and a second column which is an immutable double -// representation of the corresponding Frequency item scaled to -// mega-Hertz. +// Encapsulates a collection of frequencies with associated modes. +// The implementation is a table containing the list of 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 list is ordered. +// The list is ordered. A filter on mode is available and is set by +// the filter(Mode) method. The Mode value Modes::NULL_MODE passes +// all rows in the filter. // // Responsibilities // -// Stores internally a list of unique frequencies. Provides methods -// to add and delete list elements. +// Stores internally a list of unique frequency mode tuples. +// Provides methods to add and delete list elements. Provides range +// iterators for a filtered view of the underlying table. // // Collaborations // @@ -47,6 +50,7 @@ public: Mode mode_; }; using FrequencyItems = QList; + using BandSet = QSet; enum Column {mode_column, frequency_column, frequency_mhz_column}; @@ -81,16 +85,26 @@ public: // 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 + // access the underlying list of rows. const_iterator begin () const; const_iterator end () const; + // Bands of the frequencies + BandSet all_bands () const; + BandSet filtered_bands () const; + // Find the row of the nearest best working frequency given a - // frequency and mode + // 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 - void filter (Mode); + Q_SLOT void filter (Mode); // Reset Q_SLOT void reset_to_defaults (); diff --git a/mainwindow.cpp b/mainwindow.cpp index e874fdf57..9cfcc5393 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -52,6 +52,9 @@ namespace Radio::Frequency constexpr default_frequency {14076000}; QRegExp message_alphabet {"[- @A-Za-z0-9+./?#]*"}; + // These 10 bands are the hopping candidates and are globally coordinated + QStringList const hopping_bands = {"160m","80m","60m","40m","30m","20m","17m","15m","12m","10m"}; + bool message_is_73 (int type, QStringList const& msg_parts) { return type >= 0 @@ -390,20 +393,8 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme m_uploading=false; m_hopTest=false; m_bTxTime=false; - m_band00=-1; m_rxDone=false; - m_fWSPR["160"]=1.8366; //WSPR frequencies - m_fWSPR["80"]=3.5926; - m_fWSPR["60"]=5.2872; - m_fWSPR["40"]=7.0386; - m_fWSPR["30"]=10.1387; - m_fWSPR["20"]=14.0956; - m_fWSPR["17"]=18.1046; - m_fWSPR["15"]=21.0946; - m_fWSPR["12"]=24.9246; - m_fWSPR["10"]=28.1246; - signalMeter = new SignalMeter(ui->meterFrame); signalMeter->resize(50, 160); @@ -2224,16 +2215,8 @@ void MainWindow::startTx2() transmit (snr); signalMeter->setValue(0); if(m_mode.mid(0,4)=="WSPR" and !m_tune) { -<<<<<<< variant A - t = " Transmitting " + m_mode + " ----------------------- " + - QString {m_config.bands ()->find (m_dialFreq)->name_}; ->>>>>>> variant B t = " Transmiting " + m_mode + " ----------------------- " + m_config.bands ()->find (m_dialFreq); -####### Ancestor - t = " Transmiting " + m_mode + " ----------------------- " + - QString {m_config.bands ()->find (m_dialFreq)->name_}; -======= end ui->decodedTextBrowser->append(t.rightJustified (71, '-')); QFile f {m_dataDir.absoluteFilePath ("ALL_WSPR.TXT")}; @@ -3821,14 +3804,15 @@ void MainWindow::pskSetLocal () { // find the station row, if any, that matches the band we are on auto stations = m_config.stations (); - auto matches = stations->match (stations->index (0, 0) + auto matches = stations->match (stations->index (0, StationList::band_column) , Qt::DisplayRole , ui->bandComboBox->currentText () , 1 , Qt::MatchExactly); QString antenna_description; if (!matches.isEmpty ()) { - antenna_description = stations->index (matches.first ().row (), 2).data ().toString (); + antenna_description = stations->index (matches.first ().row () + , StationList::description_column).data ().toString (); } psk_Reporter->setLocalStation(m_config.my_callsign (), m_config.my_grid (), antenna_description, QString {"WSJT-X v" + version() + " " + @@ -4274,7 +4258,6 @@ void MainWindow::on_cbBandHop_toggled(bool b) void MainWindow::bandHopping() { - QString bandName[]={"160","80","60","40","30","20","17","15","12","10"}; QDateTime t = QDateTime::currentDateTimeUtc(); QString date = t.date().toString("yyyy MMM dd").trimmed(); QString utc = t.time().toString().trimmed(); @@ -4286,9 +4269,8 @@ void MainWindow::bandHopping() float sec=t.time().second() + 0.001*t.time().msec(); float uth=nhr + nmin/60.0 + sec/3600.0; int isun; - int iband0,iband; + int iband0; int ntxnext; - int i,j; static int icall=0; if(m_hopTest) uth+= 2.0*icall/60.0; @@ -4296,7 +4278,7 @@ void MainWindow::bandHopping() // Find grayline status, isun: 0=Sunrise, 1=Day, 2=Sunset, 3=Night hopping_(&nyear, &month, &nday, &uth, - const_cast (m_config.my_grid ().toLatin1().constData()), + m_config.my_grid ().toLatin1().constData(), &m_grayDuration, &m_pctx, &isun, &iband0, &ntxnext, 6); @@ -4306,97 +4288,72 @@ void MainWindow::bandHopping() m_nrx=1; } -if( m_bandHopping ) { - QString bname; - QStringList s; - if(isun==0) s=m_sunriseBands; - if(isun==1) s=m_dayBands; - if(isun==2) s=m_sunsetBands; - if(isun==3) s=m_nightBands; + if( m_bandHopping ) { + QStringList s; + if(isun==0) s=m_sunriseBands; + if(isun==1) s=m_dayBands; + if(isun==2) s=m_sunsetBands; + if(isun==3) s=m_nightBands; - Frequency f0=0; - iband=-1; - for(i=0; irowCount (); ++row) { - // Lookup the underlying source model index from the filtered model index - auto const& source_index = frequencies->mapToSource (frequencies->index (row, FrequencyList::frequency_column)); - // and use it to directly access the list of frequencies that the - // FrequencyList model wraps (we could also use the model data() - // member using the EditRole of the frequency_column but this way - // avoids going via a QVariant item) - auto const& f = frequencies->frequency_list ()[source_index.row ()].frequency_; - if(f==f0) { - on_bandComboBox_activated(row); //Set new band -// qDebug() << nhr << nmin << int(sec) << "Band selected" << i << 0.000001*f0 << 0.000001*f; - break; + auto const& row = m_config.frequencies ()->best_working_frequency (new_band); + if (row >= 0) { // band is configured + m_band00 = new_band; + ui->bandComboBox->setCurrentIndex (row); + on_bandComboBox_activated (row); + + m_cmnd=""; + QFile f1 {m_appDir + "/user_hardware.bat"}; + if(f1.exists()) { + m_cmnd=QDir::toNativeSeparators (m_appDir + "/user_hardware.bat ") + m_band00; + } + QFile f2 {m_appDir + "/user_hardware.cmd"}; + if(f2.exists()) { + m_cmnd=QDir::toNativeSeparators (m_appDir + "/user_hardware.cmd ") + m_band00; + } + QFile f3 {m_appDir + "/user_hardware.exe"}; + if(f3.exists()) { + m_cmnd=QDir::toNativeSeparators (m_appDir + "/user_hardware.exe ") + m_band00; + } + QFile f4 {m_appDir + "/user_hardware"}; + if(f4.exists()) { + m_cmnd=QDir::toNativeSeparators (m_appDir + "/user_hardware ") + m_band00; + } + if(m_cmnd!="") p3.start(m_cmnd); // Execute user's hardware controller + + // Produce a short tuneup signal + m_tuneup = false; + if (m_tuneBands.contains (m_band00)) { + m_tuneup = true; + on_tuneButton_clicked (true); + tuneATU_Timer->start (2500); + } } - } - m_cmnd=""; - QFile f1 {m_appDir + "/user_hardware.bat"}; - if(f1.exists()) { - m_cmnd=QDir::toNativeSeparators (m_appDir + "/user_hardware.bat ") + bname; + // Display grayline status + QString dailySequence[4]={"Sunrise grayline","Day","Sunset grayline","Night"}; + auto_tx_label->setText(dailySequence[isun]); } - QFile f2 {m_appDir + "/user_hardware.cmd"}; - if(f2.exists()) { - m_cmnd=QDir::toNativeSeparators (m_appDir + "/user_hardware.cmd ") + bname; - } - QFile f3 {m_appDir + "/user_hardware.exe"}; - if(f3.exists()) { - m_cmnd=QDir::toNativeSeparators (m_appDir + "/user_hardware.exe ") + bname; - } - QFile f4 {m_appDir + "/user_hardware"}; - if(f4.exists()) { - m_cmnd=QDir::toNativeSeparators (m_appDir + "/user_hardware ") + bname; - } - if(m_cmnd!="") p3.start(m_cmnd); // Execute user's hardware controller - -// Displat grayline status - QString dailySequence[4]={"Sunrise grayline","Day","Sunset grayline","Night"}; - auto_tx_label->setText(dailySequence[isun]); - -// Produce a short tuneup signal - s=m_tuneBands; - m_tuneup=false; - for(int i=0; istart(2500); - } -} //endif m_bandHopping - } void MainWindow::on_pushButton_clicked() diff --git a/mainwindow.h b/mainwindow.h index c670a6283..74bf5d99b 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -328,7 +328,7 @@ private: qint32 m_pctx; qint32 m_nseq; qint32 m_grayDuration; - qint32 m_band00; + QString m_band00; bool m_btxok; //True if OK to transmit bool m_diskData; @@ -454,8 +454,6 @@ private: QStringList m_nightBands; QStringList m_tuneBands; - QMap m_fWSPR; - QHash m_pfx; QHash m_sfx; @@ -552,7 +550,7 @@ extern "C" { void wspr_downsample_(short int d2[], int* k); void savec2_(char* fname, int* m_TRseconds, double* m_dialFreq, int len1); - void hopping_(int* nyear, int* month, int* nday, float* uth, char* MyGrid, + void hopping_(int* nyear, int* month, int* nday, float* uth, char const * MyGrid, int* nduration, int* npctx, int* isun, int* iband, int* ntxnext, int len); }