2015-10-12 00:23:37 +00:00
#!/usr/bin/env python3
2013-06-30 15:38:06 +00:00
2017-03-20 13:06:01 +00:00
# Copyright (C) 2013-2017 Christian Thomas Jacobs.
2013-06-30 15:38:06 +00:00
# This file is part of PyQSO.
# PyQSO is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PyQSO is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with PyQSO. If not, see <http://www.gnu.org/licenses/>.
2017-05-17 16:18:05 +00:00
from gi . repository import Gtk
2013-06-30 15:38:06 +00:00
import logging
2017-02-07 14:17:14 +00:00
try :
import configparser
except ImportError :
import ConfigParser as configparser
2013-06-30 22:04:37 +00:00
import os . path
2013-07-01 00:20:06 +00:00
import base64
2013-07-27 18:22:54 +00:00
try :
2016-01-27 16:23:09 +00:00
import Hamlib
have_hamlib = True
2013-09-14 20:10:52 +00:00
except ImportError :
2016-01-27 16:23:09 +00:00
logging . warning ( " Could not import the Hamlib module! " )
have_hamlib = False
2017-02-10 18:50:34 +00:00
try :
import geocoder
have_geocoder = True
except ImportError :
logging . warning ( " Could not import the geocoder module! " )
have_geocoder = False
2013-07-01 22:23:43 +00:00
2017-07-07 11:22:32 +00:00
from pyqso . adif import AVAILABLE_FIELD_NAMES_ORDERED , MODES
2017-05-07 15:38:36 +00:00
from pyqso . auxiliary_dialogs import error
2013-06-30 22:04:37 +00:00
2015-11-29 22:25:41 +00:00
PREFERENCES_FILE = os . path . expanduser ( " ~/.config/pyqso/preferences.ini " )
2016-01-27 16:23:09 +00:00
2017-04-01 13:57:07 +00:00
class PreferencesDialog :
2015-10-03 16:51:25 +00:00
2016-01-27 16:23:09 +00:00
""" A dialog to specify the PyQSO preferences. """
2017-03-31 09:28:26 +00:00
def __init__ ( self , application ) :
2017-04-01 13:57:07 +00:00
""" Set up the various pages of the preferences dialog.
: arg application : The PyQSO application containing the main Gtk window , etc .
"""
2016-01-27 16:23:09 +00:00
logging . debug ( " Setting up the preferences dialog... " )
2017-03-31 09:28:26 +00:00
self . application = application
2017-04-01 13:57:07 +00:00
self . builder = self . application . builder
2017-07-05 23:36:17 +00:00
glade_file_path = os . path . join ( os . path . realpath ( os . path . dirname ( __file__ ) ) , " res " , " pyqso.glade " )
2017-04-02 13:02:40 +00:00
self . builder . add_objects_from_file ( glade_file_path , ( " preferences_dialog " , ) )
2017-04-01 13:57:07 +00:00
self . dialog = self . builder . get_object ( " preferences_dialog " )
2013-06-30 15:38:06 +00:00
2017-05-07 15:38:36 +00:00
self . general = GeneralPage ( self . dialog , self . builder )
self . view = ViewPage ( self . dialog , self . builder )
self . records = RecordsPage ( self . dialog , self . builder )
2017-07-07 11:22:32 +00:00
self . import_export = ImportExportPage ( self . dialog , self . builder )
2017-05-07 15:38:36 +00:00
self . hamlib = HamlibPage ( self . dialog , self . builder )
2018-03-10 15:49:44 +00:00
self . world_map = WorldMapPage ( self . dialog , self . builder )
2013-06-30 15:38:06 +00:00
2017-04-01 13:57:07 +00:00
self . dialog . show_all ( )
2013-06-30 15:38:06 +00:00
2016-01-27 16:23:09 +00:00
logging . debug ( " Preferences dialog ready! " )
2013-07-27 18:22:54 +00:00
2016-01-27 16:23:09 +00:00
return
2014-03-23 01:54:24 +00:00
2016-01-27 16:23:09 +00:00
def commit ( self ) :
""" Commit the user preferences to the configuration file. """
2013-06-30 15:38:06 +00:00
2016-01-27 16:23:09 +00:00
logging . debug ( " Committing the user preferences to the configuration file... " )
2013-09-15 03:29:44 +00:00
2016-01-27 16:23:09 +00:00
config = configparser . ConfigParser ( )
2013-06-30 15:38:06 +00:00
2016-01-27 16:23:09 +00:00
# General
config . add_section ( " general " )
2017-04-01 13:57:07 +00:00
for key in list ( self . general . data . keys ( ) ) :
config . set ( " general " , key . lower ( ) , str ( self . general . data [ key ] ) )
2015-10-03 16:51:25 +00:00
2016-01-27 16:23:09 +00:00
# View
config . add_section ( " view " )
2017-04-01 13:57:07 +00:00
for key in list ( self . view . data . keys ( ) ) :
config . set ( " view " , key . lower ( ) , str ( self . view . data [ key ] ) )
# Records
config . add_section ( " records " )
for key in list ( self . records . data . keys ( ) ) :
config . set ( " records " , key . lower ( ) , str ( self . records . data [ key ] ) )
2013-06-30 23:56:32 +00:00
2017-07-07 11:22:32 +00:00
# Import/Export
config . add_section ( " import_export " )
for key in list ( self . import_export . data . keys ( ) ) :
config . set ( " import_export " , key . lower ( ) , str ( self . import_export . data [ key ] ) )
2013-06-30 23:56:32 +00:00
2016-01-27 16:23:09 +00:00
# Hamlib
config . add_section ( " hamlib " )
2017-04-01 13:57:07 +00:00
for key in list ( self . hamlib . data . keys ( ) ) :
config . set ( " hamlib " , key . lower ( ) , str ( self . hamlib . data [ key ] ) )
2013-07-27 18:22:54 +00:00
2018-03-10 15:49:44 +00:00
# World Map
config . add_section ( " world_map " )
for key in list ( self . world_map . data . keys ( ) ) :
config . set ( " world_map " , key . lower ( ) , str ( self . world_map . data [ key ] ) )
2016-01-27 16:23:09 +00:00
# Write the preferences to file.
with open ( os . path . expanduser ( PREFERENCES_FILE ) , ' w ' ) as f :
config . write ( f )
2014-03-23 01:54:24 +00:00
2016-01-27 16:23:09 +00:00
return
2013-06-30 23:56:32 +00:00
2013-06-30 22:04:37 +00:00
2017-04-01 13:57:07 +00:00
class GeneralPage :
2016-01-27 16:23:09 +00:00
""" The section of the preferences dialog containing general preferences. """
2017-05-07 15:38:36 +00:00
def __init__ ( self , parent , builder ) :
2017-07-07 11:22:32 +00:00
""" Set up the General page of the Preferences dialog. """
2016-01-27 16:23:09 +00:00
2017-05-07 15:38:36 +00:00
self . parent = parent
2017-04-01 13:57:07 +00:00
self . builder = builder
self . sources = { }
2016-01-27 16:23:09 +00:00
# Remember that the have_config conditional in the PyQSO class may be out-of-date the next time the user opens up the preferences dialog
# because a configuration file may have been created after launching the application. Let's check to see if one exists again...
config = configparser . ConfigParser ( )
have_config = ( config . read ( PREFERENCES_FILE ) != [ ] )
2017-04-01 13:58:06 +00:00
2017-05-17 16:18:05 +00:00
# Show toolbox.
2017-04-01 13:57:07 +00:00
self . sources [ " SHOW_TOOLBOX " ] = self . builder . get_object ( " general_show_toolbox_checkbutton " )
2016-01-27 16:23:09 +00:00
( section , option ) = ( " general " , " show_toolbox " )
if ( have_config and config . has_option ( section , option ) ) :
2017-07-09 10:42:42 +00:00
self . sources [ " SHOW_TOOLBOX " ] . set_active ( config . getboolean ( section , option ) )
2016-01-27 16:23:09 +00:00
else :
self . sources [ " SHOW_TOOLBOX " ] . set_active ( False )
2017-05-17 16:18:05 +00:00
# Show statistics.
2017-04-01 13:57:07 +00:00
self . sources [ " SHOW_YEARLY_STATISTICS " ] = self . builder . get_object ( " general_show_yearly_statistics_checkbutton " )
2016-01-27 16:23:09 +00:00
( section , option ) = ( " general " , " show_yearly_statistics " )
if ( have_config and config . has_option ( section , option ) ) :
2017-07-09 10:42:42 +00:00
self . sources [ " SHOW_YEARLY_STATISTICS " ] . set_active ( config . getboolean ( section , option ) )
2016-01-27 16:23:09 +00:00
else :
self . sources [ " SHOW_YEARLY_STATISTICS " ] . set_active ( False )
2017-05-17 16:18:05 +00:00
# Default logbook.
2017-04-01 13:57:07 +00:00
self . sources [ " DEFAULT_LOGBOOK " ] = self . builder . get_object ( " general_default_logbook_checkbutton " )
2017-02-07 16:39:43 +00:00
( section , option ) = ( " general " , " default_logbook " )
if ( have_config and config . has_option ( section , option ) ) :
2017-07-09 10:42:42 +00:00
self . sources [ " DEFAULT_LOGBOOK " ] . set_active ( config . getboolean ( section , option ) )
2017-02-07 16:39:43 +00:00
else :
self . sources [ " DEFAULT_LOGBOOK " ] . set_active ( False )
2017-04-14 20:45:59 +00:00
self . sources [ " DEFAULT_LOGBOOK " ] . connect ( " toggled " , self . on_default_logbook_toggled )
2017-02-07 16:39:43 +00:00
2017-04-01 13:57:07 +00:00
self . sources [ " DEFAULT_LOGBOOK_PATH " ] = self . builder . get_object ( " general_default_logbook_entry " )
2017-02-07 16:39:43 +00:00
( section , option ) = ( " general " , " default_logbook " )
# Disable the text entry box if the default logbook checkbox is not checked.
if ( have_config and config . has_option ( section , option ) ) :
self . sources [ " DEFAULT_LOGBOOK_PATH " ] . set_sensitive ( self . sources [ " DEFAULT_LOGBOOK " ] . get_active ( ) )
2017-05-17 16:18:05 +00:00
self . builder . get_object ( " general_default_logbook_button " ) . set_sensitive ( self . sources [ " DEFAULT_LOGBOOK " ] . get_active ( ) )
2017-02-07 16:39:43 +00:00
else :
self . sources [ " DEFAULT_LOGBOOK_PATH " ] . set_sensitive ( False )
2017-05-17 16:18:05 +00:00
self . builder . get_object ( " general_default_logbook_button " ) . set_sensitive ( False )
2017-02-07 16:39:43 +00:00
( section , option ) = ( " general " , " default_logbook_path " )
if ( have_config and config . has_option ( section , option ) ) :
self . sources [ " DEFAULT_LOGBOOK_PATH " ] . set_text ( config . get ( section , option ) )
2016-01-27 16:23:09 +00:00
2017-05-17 16:18:05 +00:00
self . builder . get_object ( " general_default_logbook_button " ) . connect ( " clicked " , self . on_default_logbook_clicked )
# Keep 'Add Record' dialog open.
2017-04-01 13:57:07 +00:00
self . sources [ " KEEP_OPEN " ] = self . builder . get_object ( " general_keep_open_checkbutton " )
2016-01-27 16:23:09 +00:00
( section , option ) = ( " general " , " keep_open " )
if ( have_config and config . has_option ( section , option ) ) :
2017-07-09 10:42:42 +00:00
self . sources [ " KEEP_OPEN " ] . set_active ( config . getboolean ( section , option ) )
2016-01-27 16:23:09 +00:00
else :
self . sources [ " KEEP_OPEN " ] . set_active ( False )
2017-02-10 18:50:34 +00:00
2016-01-27 16:23:09 +00:00
return
2017-04-01 13:57:07 +00:00
@property
def data ( self ) :
2017-05-09 16:25:45 +00:00
""" User preferences regarding General settings. """
2016-01-27 16:23:09 +00:00
data = { }
data [ " SHOW_TOOLBOX " ] = self . sources [ " SHOW_TOOLBOX " ] . get_active ( )
data [ " SHOW_YEARLY_STATISTICS " ] = self . sources [ " SHOW_YEARLY_STATISTICS " ] . get_active ( )
2017-02-07 16:39:43 +00:00
data [ " DEFAULT_LOGBOOK " ] = self . sources [ " DEFAULT_LOGBOOK " ] . get_active ( )
data [ " DEFAULT_LOGBOOK_PATH " ] = os . path . expanduser ( self . sources [ " DEFAULT_LOGBOOK_PATH " ] . get_text ( ) )
2016-01-27 16:23:09 +00:00
data [ " KEEP_OPEN " ] = self . sources [ " KEEP_OPEN " ] . get_active ( )
return data
2017-04-14 20:45:59 +00:00
def on_default_logbook_toggled ( self , widget , data = None ) :
2017-02-07 16:39:43 +00:00
if ( widget . get_active ( ) ) :
self . sources [ " DEFAULT_LOGBOOK_PATH " ] . set_sensitive ( True )
2017-05-17 16:18:05 +00:00
self . builder . get_object ( " general_default_logbook_button " ) . set_sensitive ( True )
2017-02-07 16:39:43 +00:00
else :
self . sources [ " DEFAULT_LOGBOOK_PATH " ] . set_sensitive ( False )
2017-05-17 16:18:05 +00:00
self . builder . get_object ( " general_default_logbook_button " ) . set_sensitive ( False )
return
def on_default_logbook_clicked ( self , widget ) :
""" Let the user select the default logbook file via a file chooser dialog,
and set the path in the adjacent entry box . """
dialog = Gtk . FileChooserDialog ( " Select SQLite Database File " ,
self . parent ,
Gtk . FileChooserAction . OPEN ,
( Gtk . STOCK_CANCEL , Gtk . ResponseType . CANCEL ,
Gtk . STOCK_OPEN , Gtk . ResponseType . OK ) )
response = dialog . run ( )
if ( response == Gtk . ResponseType . OK ) :
path = dialog . get_filename ( )
self . sources [ " DEFAULT_LOGBOOK_PATH " ] . set_text ( path )
dialog . destroy ( )
2017-02-07 16:39:43 +00:00
return
2013-06-30 23:56:32 +00:00
2017-02-10 18:55:42 +00:00
2017-04-01 13:57:07 +00:00
class ViewPage :
2016-01-27 16:23:09 +00:00
""" The section of the preferences dialog containing view-related preferences. """
2017-05-07 15:38:36 +00:00
def __init__ ( self , parent , builder ) :
2017-07-07 11:22:32 +00:00
""" Set up the View page of the Preferences dialog. """
2016-01-27 16:23:09 +00:00
2017-05-07 15:38:36 +00:00
self . parent = parent
2017-04-01 13:57:07 +00:00
self . builder = builder
self . sources = { }
2016-01-27 16:23:09 +00:00
config = configparser . ConfigParser ( )
have_config = ( config . read ( PREFERENCES_FILE ) != [ ] )
2017-04-01 13:57:07 +00:00
# Visible fields
for field_name in AVAILABLE_FIELD_NAMES_ORDERED :
self . sources [ field_name ] = self . builder . get_object ( " visible_fields_ %s " % ( field_name . lower ( ) ) )
if ( have_config and config . has_option ( " view " , field_name . lower ( ) ) ) :
2017-07-09 10:42:42 +00:00
self . sources [ field_name ] . set_active ( config . getboolean ( " view " , field_name . lower ( ) ) )
2017-04-01 13:57:07 +00:00
else :
self . sources [ field_name ] . set_active ( True )
2016-01-27 16:23:09 +00:00
return
2017-04-01 13:57:07 +00:00
@property
def data ( self ) :
2017-05-09 16:25:45 +00:00
""" User preferences regarding View settings. """
2016-01-27 16:23:09 +00:00
data = { }
for field_name in AVAILABLE_FIELD_NAMES_ORDERED :
data [ field_name ] = self . sources [ field_name ] . get_active ( )
return data
2013-06-30 23:56:32 +00:00
2017-04-01 13:57:07 +00:00
class RecordsPage :
2016-01-27 16:23:09 +00:00
""" The section of the preferences dialog containing record-related preferences. """
2017-05-07 15:38:36 +00:00
def __init__ ( self , parent , builder ) :
2017-07-07 11:22:32 +00:00
""" Set up the Record page of the Preferences dialog. """
2016-01-27 16:23:09 +00:00
2017-05-07 15:38:36 +00:00
self . parent = parent
2017-04-01 13:57:07 +00:00
self . builder = builder
self . sources = { }
2016-01-27 16:23:09 +00:00
# Remember that the have_config conditional in the PyQSO class may be out-of-date the next time the user opens up the preferences dialog
# because a configuration file may have been created after launching the application. Let's check to see if one exists again...
config = configparser . ConfigParser ( )
have_config = ( config . read ( PREFERENCES_FILE ) != [ ] )
2017-04-01 13:57:07 +00:00
# Autocomplete
self . sources [ " AUTOCOMPLETE_BAND " ] = self . builder . get_object ( " records_autocomplete_band_checkbutton " )
2016-01-27 16:23:09 +00:00
( section , option ) = ( " records " , " autocomplete_band " )
if ( have_config and config . has_option ( section , option ) ) :
2017-07-09 10:42:42 +00:00
self . sources [ " AUTOCOMPLETE_BAND " ] . set_active ( config . getboolean ( section , option ) )
2016-01-27 16:23:09 +00:00
else :
self . sources [ " AUTOCOMPLETE_BAND " ] . set_active ( True )
2017-04-01 13:57:07 +00:00
self . sources [ " USE_UTC " ] = self . builder . get_object ( " records_autocomplete_utc_checkbutton " )
2016-01-27 16:23:09 +00:00
( section , option ) = ( " records " , " use_utc " )
if ( have_config and config . has_option ( section , option ) ) :
2017-07-09 10:42:42 +00:00
self . sources [ " USE_UTC " ] . set_active ( config . getboolean ( section , option ) )
2016-01-27 16:23:09 +00:00
else :
self . sources [ " USE_UTC " ] . set_active ( True )
2017-04-01 13:57:07 +00:00
# Default values
2016-01-27 16:23:09 +00:00
# Mode
2017-04-01 13:57:07 +00:00
self . sources [ " DEFAULT_MODE " ] = self . builder . get_object ( " default_values_mode_combo " )
2016-01-27 16:23:09 +00:00
for mode in sorted ( MODES . keys ( ) ) :
self . sources [ " DEFAULT_MODE " ] . append_text ( mode )
( section , option ) = ( " records " , " default_mode " )
if ( have_config and config . has_option ( section , option ) ) :
mode = config . get ( section , option )
else :
mode = " "
self . sources [ " DEFAULT_MODE " ] . set_active ( sorted ( MODES . keys ( ) ) . index ( mode ) )
2017-04-14 20:45:59 +00:00
self . sources [ " DEFAULT_MODE " ] . connect ( " changed " , self . on_mode_changed )
2016-01-27 16:23:09 +00:00
# Submode
2017-04-01 13:57:07 +00:00
self . sources [ " DEFAULT_SUBMODE " ] = self . builder . get_object ( " default_values_submode_combo " )
2016-01-27 16:23:09 +00:00
for submode in MODES [ mode ] :
self . sources [ " DEFAULT_SUBMODE " ] . append_text ( submode )
( section , option ) = ( " records " , " default_submode " )
if ( have_config and config . has_option ( section , option ) ) :
submode = config . get ( section , option )
else :
submode = " "
self . sources [ " DEFAULT_SUBMODE " ] . set_active ( MODES [ mode ] . index ( submode ) )
# Power
2017-04-01 13:57:07 +00:00
self . sources [ " DEFAULT_POWER " ] = self . builder . get_object ( " default_values_tx_power_entry " )
2016-01-27 16:23:09 +00:00
( section , option ) = ( " records " , " default_power " )
if ( have_config and config . has_option ( section , option ) ) :
self . sources [ " DEFAULT_POWER " ] . set_text ( config . get ( section , option ) )
else :
self . sources [ " DEFAULT_POWER " ] . set_text ( " " )
2017-05-07 13:01:28 +00:00
# Frequency unit
self . sources [ " DEFAULT_FREQUENCY_UNIT " ] = self . builder . get_object ( " default_values_frequency_unit_combo " )
units = [ " Hz " , " kHz " , " MHz " , " GHz " ]
for unit in units :
self . sources [ " DEFAULT_FREQUENCY_UNIT " ] . append_text ( unit )
( section , option ) = ( " records " , " default_frequency_unit " )
if ( have_config and config . has_option ( section , option ) ) :
self . sources [ " DEFAULT_FREQUENCY_UNIT " ] . set_active ( units . index ( config . get ( section , option ) ) )
else :
self . sources [ " DEFAULT_FREQUENCY_UNIT " ] . set_active ( units . index ( " MHz " ) )
2017-04-01 13:57:07 +00:00
# Callsign lookup
self . sources [ " CALLSIGN_DATABASE " ] = self . builder . get_object ( " callsign_lookup_database_combo " )
2016-01-27 16:23:09 +00:00
callsign_database = [ " " , " qrz.com " , " hamqth.com " ]
for database in callsign_database :
self . sources [ " CALLSIGN_DATABASE " ] . append_text ( database )
( section , option ) = ( " records " , " callsign_database " )
if ( have_config and config . has_option ( section , option ) ) :
self . sources [ " CALLSIGN_DATABASE " ] . set_active ( callsign_database . index ( config . get ( section , option ) ) )
else :
self . sources [ " CALLSIGN_DATABASE " ] . set_active ( callsign_database . index ( " " ) )
# Login details
2017-04-01 13:57:07 +00:00
self . sources [ " CALLSIGN_DATABASE_USERNAME " ] = self . builder . get_object ( " callsign_lookup_login_details_username_entry " )
2016-01-27 16:23:09 +00:00
( section , option ) = ( " records " , " callsign_database_username " )
if ( have_config and config . has_option ( section , option ) ) :
self . sources [ " CALLSIGN_DATABASE_USERNAME " ] . set_text ( config . get ( section , option ) )
2017-04-01 13:57:07 +00:00
self . sources [ " CALLSIGN_DATABASE_PASSWORD " ] = self . builder . get_object ( " callsign_lookup_login_details_password_entry " )
2016-01-27 16:23:09 +00:00
( section , option ) = ( " records " , " callsign_database_password " )
if ( have_config and config . has_option ( section , option ) ) :
password = base64 . b64decode ( config . get ( section , option ) ) . decode ( " utf-8 " )
self . sources [ " CALLSIGN_DATABASE_PASSWORD " ] . set_text ( password )
2017-04-01 13:57:07 +00:00
self . sources [ " IGNORE_PREFIX_SUFFIX " ] = self . builder . get_object ( " callsign_lookup_ignore_prefix_suffix_checkbutton " )
2016-01-27 16:23:09 +00:00
( section , option ) = ( " records " , " ignore_prefix_suffix " )
if ( have_config and config . has_option ( section , option ) ) :
2017-07-09 10:42:42 +00:00
self . sources [ " IGNORE_PREFIX_SUFFIX " ] . set_active ( config . getboolean ( section , option ) )
2016-01-27 16:23:09 +00:00
else :
self . sources [ " IGNORE_PREFIX_SUFFIX " ] . set_active ( True )
return
2017-04-01 13:57:07 +00:00
@property
def data ( self ) :
2017-05-09 16:25:45 +00:00
""" User preferences regarding Records settings. """
2016-01-27 16:23:09 +00:00
data = { }
data [ " AUTOCOMPLETE_BAND " ] = self . sources [ " AUTOCOMPLETE_BAND " ] . get_active ( )
data [ " USE_UTC " ] = self . sources [ " USE_UTC " ] . get_active ( )
data [ " DEFAULT_MODE " ] = self . sources [ " DEFAULT_MODE " ] . get_active_text ( )
data [ " DEFAULT_SUBMODE " ] = self . sources [ " DEFAULT_SUBMODE " ] . get_active_text ( )
data [ " DEFAULT_POWER " ] = self . sources [ " DEFAULT_POWER " ] . get_text ( )
2017-05-07 13:01:28 +00:00
data [ " DEFAULT_FREQUENCY_UNIT " ] = self . sources [ " DEFAULT_FREQUENCY_UNIT " ] . get_active_text ( )
2016-01-27 16:23:09 +00:00
data [ " CALLSIGN_DATABASE " ] = self . sources [ " CALLSIGN_DATABASE " ] . get_active_text ( )
data [ " CALLSIGN_DATABASE_USERNAME " ] = self . sources [ " CALLSIGN_DATABASE_USERNAME " ] . get_text ( )
2017-04-01 13:57:07 +00:00
data [ " CALLSIGN_DATABASE_PASSWORD " ] = base64 . b64encode ( self . sources [ " CALLSIGN_DATABASE_PASSWORD " ] . get_text ( ) . encode ( " utf-8 " ) ) . decode ( " utf-8 " ) # Need to convert from bytes to str here.
2016-01-27 16:23:09 +00:00
data [ " IGNORE_PREFIX_SUFFIX " ] = self . sources [ " IGNORE_PREFIX_SUFFIX " ] . get_active ( )
return data
2017-04-14 20:45:59 +00:00
def on_mode_changed ( self , combo ) :
2016-01-27 16:23:09 +00:00
""" If the MODE field has changed its value, then fill the SUBMODE field with all the available SUBMODE options for that new MODE. """
self . sources [ " DEFAULT_SUBMODE " ] . get_model ( ) . clear ( )
mode = combo . get_active_text ( )
for submode in MODES [ mode ] :
self . sources [ " DEFAULT_SUBMODE " ] . append_text ( submode )
2017-07-25 23:20:56 +00:00
self . sources [ " DEFAULT_SUBMODE " ] . set_active ( MODES [ mode ] . index ( " " ) )
2016-01-27 16:23:09 +00:00
return
2017-07-07 11:22:32 +00:00
class ImportExportPage :
2015-04-29 21:45:58 +00:00
2017-07-07 11:22:32 +00:00
""" The section of the preferences dialog containing import/export-related preferences. """
2016-01-27 16:23:09 +00:00
2017-05-07 15:38:36 +00:00
def __init__ ( self , parent , builder ) :
2017-07-07 11:22:32 +00:00
""" Set up the Import/Export page of the Preferences dialog. """
2016-01-27 16:23:09 +00:00
2017-05-07 15:38:36 +00:00
self . parent = parent
2017-04-01 13:57:07 +00:00
self . builder = builder
self . sources = { }
2016-01-27 16:23:09 +00:00
# Remember that the have_config conditional in the PyQSO class may be out-of-date the next time the user opens up the preferences dialog
# because a configuration file may have been created after launching the application. Let's check to see if one exists again...
config = configparser . ConfigParser ( )
have_config = ( config . read ( PREFERENCES_FILE ) != [ ] )
2017-04-01 13:57:07 +00:00
# Import
self . sources [ " MERGE_COMMENT " ] = self . builder . get_object ( " adif_import_merge_comment_checkbutton " )
2017-07-07 11:22:32 +00:00
( section , option ) = ( " import_export " , " merge_comment " )
2016-01-27 16:23:09 +00:00
if ( have_config and config . has_option ( section , option ) ) :
2017-07-09 10:42:42 +00:00
self . sources [ " MERGE_COMMENT " ] . set_active ( config . getboolean ( section , option ) )
2016-01-27 16:23:09 +00:00
else :
self . sources [ " MERGE_COMMENT " ] . set_active ( False )
return
2017-04-01 13:57:07 +00:00
@property
def data ( self ) :
2017-07-07 11:22:32 +00:00
""" User preferences regarding Import/Export settings. """
2016-01-27 16:23:09 +00:00
data = { }
data [ " MERGE_COMMENT " ] = self . sources [ " MERGE_COMMENT " ] . get_active ( )
return data
2017-04-01 13:57:07 +00:00
class HamlibPage :
""" The section of the preferences dialog containing Hamlib-related preferences. """
2017-05-07 15:38:36 +00:00
def __init__ ( self , parent , builder ) :
2017-07-07 11:22:32 +00:00
""" Set up the Hamlib page of the Preferences dialog. """
2017-04-01 13:57:07 +00:00
2017-05-07 15:38:36 +00:00
self . parent = parent
2017-04-01 13:57:07 +00:00
self . builder = builder
self . sources = { }
config = configparser . ConfigParser ( )
have_config = ( config . read ( PREFERENCES_FILE ) != [ ] )
self . sources [ " AUTOFILL " ] = self . builder . get_object ( " hamlib_support_checkbutton " )
( section , option ) = ( " hamlib " , " autofill " )
if ( have_config and config . has_option ( section , option ) ) :
2017-07-09 10:42:42 +00:00
self . sources [ " AUTOFILL " ] . set_active ( config . getboolean ( section , option ) )
2017-04-01 13:57:07 +00:00
else :
self . sources [ " AUTOFILL " ] . set_active ( False )
# Get the list of rig models
models = [ " RIG_MODEL_NONE " ]
if ( have_hamlib ) :
try :
for item in dir ( Hamlib ) :
if ( item . startswith ( " RIG_MODEL_ " ) ) :
models . append ( item )
except :
logging . error ( " Could not obtain rig models list via Hamlib! " )
else :
logging . debug ( " Hamlib module not present. Could not obtain a list of rig models. " )
self . sources [ " RIG_MODEL " ] = self . builder . get_object ( " hamlib_support_model_combo " )
for model in models :
self . sources [ " RIG_MODEL " ] . append_text ( model )
( section , option ) = ( " hamlib " , " rig_model " )
if ( have_config and config . has_option ( " hamlib " , " rig_model " ) ) :
self . sources [ " RIG_MODEL " ] . set_active ( models . index ( config . get ( " hamlib " , " rig_model " ) ) )
else :
self . sources [ " RIG_MODEL " ] . set_active ( models . index ( " RIG_MODEL_NONE " ) ) # Set to RIG_MODEL_NONE as the default option.
# Path to rig
self . sources [ " RIG_PATHNAME " ] = self . builder . get_object ( " hamlib_support_path_entry " )
( section , option ) = ( " hamlib " , " rig_pathname " )
if ( have_config and config . has_option ( section , option ) ) :
self . sources [ " RIG_PATHNAME " ] . set_text ( config . get ( section , option ) )
return
@property
def data ( self ) :
2017-05-09 16:25:45 +00:00
""" User preferences regarding Hamlib settings. """
2017-04-01 13:57:07 +00:00
data = { }
data [ " AUTOFILL " ] = self . sources [ " AUTOFILL " ] . get_active ( )
data [ " RIG_PATHNAME " ] = self . sources [ " RIG_PATHNAME " ] . get_text ( )
data [ " RIG_MODEL " ] = self . sources [ " RIG_MODEL " ] . get_active_text ( )
return data
2018-03-10 15:49:44 +00:00
class WorldMapPage :
""" The section of the preferences dialog containing World Map preferences. """
def __init__ ( self , parent , builder ) :
""" Set up the World Map page of the Preferences dialog. """
self . parent = parent
self . builder = builder
self . sources = { }
# Remember that the have_config conditional in the PyQSO class may be out-of-date the next time the user opens up the preferences dialog
# because a configuration file may have been created after launching the application. Let's check to see if one exists again...
config = configparser . ConfigParser ( )
have_config = ( config . read ( PREFERENCES_FILE ) != [ ] )
2018-03-31 21:36:02 +00:00
# Option to pinpoint QTH on grey line map.
2018-03-10 15:49:44 +00:00
self . sources [ " SHOW_QTH " ] = self . builder . get_object ( " world_map_show_qth_checkbutton " )
( section , option ) = ( " world_map " , " show_qth " )
if ( have_config and config . has_option ( section , option ) ) :
self . sources [ " SHOW_QTH " ] . set_active ( config . getboolean ( section , option ) )
else :
self . sources [ " SHOW_QTH " ] . set_active ( False )
self . sources [ " QTH_NAME " ] = self . builder . get_object ( " world_map_qth_name_entry " )
button = self . builder . get_object ( " world_map_qth_lookup " )
button . connect ( " clicked " , self . lookup_callback ) # Uses geocoding to find the latitude-longitude coordinates.
self . sources [ " QTH_LATITUDE " ] = self . builder . get_object ( " world_map_qth_coordinates_latitude_entry " )
self . sources [ " QTH_LONGITUDE " ] = self . builder . get_object ( " world_map_qth_coordinates_longitude_entry " )
( section , option ) = ( " world_map " , " show_qth " )
# Disable the text entry boxes if the SHOW_QTH checkbox is not checked.
if ( have_config and config . has_option ( section , option ) ) :
self . sources [ " QTH_NAME " ] . set_sensitive ( self . sources [ " SHOW_QTH " ] . get_active ( ) )
self . sources [ " QTH_LATITUDE " ] . set_sensitive ( self . sources [ " SHOW_QTH " ] . get_active ( ) )
self . sources [ " QTH_LONGITUDE " ] . set_sensitive ( self . sources [ " SHOW_QTH " ] . get_active ( ) )
button . set_sensitive ( self . sources [ " SHOW_QTH " ] . get_active ( ) )
else :
self . sources [ " QTH_NAME " ] . set_sensitive ( False )
self . sources [ " QTH_LATITUDE " ] . set_sensitive ( False )
self . sources [ " QTH_LONGITUDE " ] . set_sensitive ( False )
button . set_sensitive ( False )
( section , option ) = ( " world_map " , " qth_name " )
if ( have_config and config . has_option ( section , option ) ) :
self . sources [ " QTH_NAME " ] . set_text ( config . get ( section , option ) )
( section , option ) = ( " world_map " , " qth_latitude " )
if ( have_config and config . has_option ( section , option ) ) :
self . sources [ " QTH_LATITUDE " ] . set_text ( config . get ( section , option ) )
( section , option ) = ( " world_map " , " qth_longitude " )
if ( have_config and config . has_option ( section , option ) ) :
self . sources [ " QTH_LONGITUDE " ] . set_text ( config . get ( section , option ) )
self . sources [ " SHOW_QTH " ] . connect ( " toggled " , self . on_show_qth_toggled )
# Option to show Maidenhead grid squares.
self . sources [ " SHOW_GRID_SQUARES " ] = self . builder . get_object ( " world_map_show_grid_squares_checkbutton " )
( section , option ) = ( " world_map " , " show_grid_squares " )
if ( have_config and config . has_option ( section , option ) ) :
self . sources [ " SHOW_GRID_SQUARES " ] . set_active ( config . getboolean ( section , option ) )
else :
self . sources [ " SHOW_GRID_SQUARES " ] . set_active ( False )
# Option to shade in worked Maidenhead grid squares.
self . sources [ " SHADE_WORKED_GRID_SQUARES " ] = self . builder . get_object ( " world_map_shade_worked_grid_squares_checkbutton " )
( section , option ) = ( " world_map " , " shade_worked_grid_squares " )
if ( have_config and config . has_option ( section , option ) ) :
self . sources [ " SHADE_WORKED_GRID_SQUARES " ] . set_active ( config . getboolean ( section , option ) )
else :
self . sources [ " SHADE_WORKED_GRID_SQUARES " ] . set_active ( False )
return
@property
def data ( self ) :
""" User preferences regarding World Map settings. """
data = { }
data [ " SHOW_QTH " ] = self . sources [ " SHOW_QTH " ] . get_active ( )
data [ " QTH_NAME " ] = self . sources [ " QTH_NAME " ] . get_text ( )
data [ " QTH_LATITUDE " ] = self . sources [ " QTH_LATITUDE " ] . get_text ( )
data [ " QTH_LONGITUDE " ] = self . sources [ " QTH_LONGITUDE " ] . get_text ( )
data [ " SHOW_GRID_SQUARES " ] = self . sources [ " SHOW_GRID_SQUARES " ] . get_active ( )
data [ " SHADE_WORKED_GRID_SQUARES " ] = self . sources [ " SHADE_WORKED_GRID_SQUARES " ] . get_active ( )
return data
def on_show_qth_toggled ( self , widget , data = None ) :
if ( widget . get_active ( ) ) :
self . sources [ " QTH_NAME " ] . set_sensitive ( True )
self . sources [ " QTH_LATITUDE " ] . set_sensitive ( True )
self . sources [ " QTH_LONGITUDE " ] . set_sensitive ( True )
self . builder . get_object ( " world_map_qth_lookup " ) . set_sensitive ( True )
else :
self . sources [ " QTH_NAME " ] . set_sensitive ( False )
self . sources [ " QTH_LATITUDE " ] . set_sensitive ( False )
self . sources [ " QTH_LONGITUDE " ] . set_sensitive ( False )
self . builder . get_object ( " world_map_qth_lookup " ) . set_sensitive ( False )
return
def lookup_callback ( self , widget = None ) :
""" Perform geocoding of the QTH location to obtain latitude-longitude coordinates. """
if ( not have_geocoder ) :
error ( parent = self . parent , message = " Geocoder module could not be imported. Geocoding aborted. " )
return
logging . debug ( " Geocoding QTH location... " )
name = self . sources [ " QTH_NAME " ] . get_text ( )
try :
g = geocoder . google ( name )
latitude , longitude = g . latlng
self . sources [ " QTH_LATITUDE " ] . set_text ( str ( latitude ) )
self . sources [ " QTH_LONGITUDE " ] . set_text ( str ( longitude ) )
logging . debug ( " QTH coordinates found: ( %s , %s ) " , str ( latitude ) , str ( longitude ) )
except ValueError as e :
error ( parent = self . parent , message = " Unable to lookup QTH coordinates. Is the QTH name correct? " )
logging . exception ( e )
except Exception as e :
error ( parent = self . parent , message = " Unable to lookup QTH coordinates. Check connection to the internets? Lookup limit reached? " )
logging . exception ( e )
return