#!/usr/bin/env python3 # Copyright (C) 2012-2016 Christian T. Jacobs. # 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 . from gi.repository import Gtk, GdkPixbuf import argparse import configparser import os import os.path import sys import signal # This will help Python find the PyQSO modules that need to be imported below. pyqso_path = os.path.join(os.path.realpath(os.path.dirname(__file__)), os.pardir) sys.path.insert(0, pyqso_path) import logging logging.basicConfig(level=logging.INFO) logging.info("PyQSO version 0.3") # PyQSO modules from pyqso.adif import * from pyqso.logbook import * from pyqso.menu import * from pyqso.toolbar import * from pyqso.toolbox import * from pyqso.preferences_dialog import * class PyQSO(Gtk.Window): """ The PyQSO application class. """ def __init__(self, logbook_path=None): """ Set up the main (root) window, start the event loop, and open a logbook (if the logbook's path is specified by the user in the command line). :arg str logbook_path: An optional argument containing the path of the logbook file to open. If no value is provided, this defaults to None and no logbook is opened. """ # Call the constructor of the super class (Gtk.Window) Gtk.Window.__init__(self, title="PyQSO") # Check that the directory for holding PyQSO configuration files exists. If it doesn't, create it now. try: os.makedirs(os.path.expanduser('~/.config/pyqso'), exist_ok=True) except Exception as e: logging.error("An error occurred whilst creating a directory for PyQSO configuration files. Try creating the directory '~/.config/pyqso' manually.") logging.exception(e) # Get any application-specific preferences from the configuration file config = configparser.ConfigParser() # Check that the configuration file actually exists (and is readable) # otherwise, we will resort to the defaults. have_config = (config.read(os.path.expanduser("~/.config/pyqso/preferences.ini")) != []) self.set_size_request(800, 600) # Default to an 800 x 600 resolution. self.set_position(Gtk.WindowPosition.CENTER) possible_icon_paths = [os.path.join(pyqso_path, "icons", "log_64x64.png")] for icon_path in possible_icon_paths: try: self.set_icon_from_file(icon_path) except Exception as error: print(error.message) # Kills the application if the close button is clicked on the main window itself. self.connect("delete-event", Gtk.main_quit) vbox_outer = Gtk.VBox() self.add(vbox_outer) self.statusbar = Gtk.Statusbar() context_id = self.statusbar.get_context_id("Status") self.statusbar.push(context_id, "No logbook is currently open.") # Create a Logbook so we can add/remove/edit logs and records, # once connected to the SQLite database. self.logbook = Logbook(self) self.logbook.set_scrollable(True) self.toolbox = Toolbox(self) # Set up menu and tool bars # These classes depend on the Logbook and Toolbox class, # so pack the logbook and toolbox after the menu and toolbar. self.menu = Menu(self) self.toolbar = Toolbar(self) vbox_outer.pack_start(self.menu, False, False, 0) vbox_outer.pack_start(self.toolbar, False, False, 0) vbox_outer.pack_start(self.logbook, True, True, 0) vbox_outer.pack_start(self.toolbox, True, True, 0) vbox_outer.pack_start(self.statusbar, False, False, 0) self.show_all() if(have_config): if(config.get("general", "show_toolbox") == "False"): self.toolbox.toggle_visible_callback() else: # Hide the Toolbox by default self.toolbox.toggle_visible_callback() if(logbook_path is not None): self.logbook.open(widget=None, path=logbook_path) return def show_about(self, widget): """ Show the About dialog, which includes license information. """ about = Gtk.AboutDialog() about.set_modal(True) about.set_transient_for(parent=self) about.set_program_name("PyQSO") about.set_version("0.3") about.set_authors(["Christian T. Jacobs (2E0ICL)"]) about.set_license("""This program 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. This program 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 this program. If not, see .""") about.set_comments("PyQSO: A contact logging tool for amateur radio operators.") possible_icon_paths = [os.path.join(pyqso_path, "icons", "log_64x64.png")] for icon_path in possible_icon_paths: try: about.set_logo(GdkPixbuf.Pixbuf.new_from_file_at_scale(icon_path, 64, 64, False)) except Exception as error: print(error.message) about.run() about.destroy() return def show_preferences(self, widget): """ Show the Preferences dialog. Any changes made by the user after clicking the 'Ok' button are saved in the .cfg file. """ preferences = PreferencesDialog(self) response = preferences.run() if(response == Gtk.ResponseType.OK): preferences.commit() preferences.destroy() return if(__name__ == "__main__"): # Get any command line arguments parser = argparse.ArgumentParser(prog="pyqso") parser.add_argument("-d", "--debug", action="store_true", default=False, help="Enable debugging. All debugging messages will be written to pyqso.debug.") parser.add_argument("-l", "--logbook", action="store", type=str, metavar="/path/to/my_logbook_file.db", default=None, help="Path to a Logbook file. If this file does not already exist, then it will be created.") args = parser.parse_args() # Output debugging messages to a file if(args.debug): # Get the root logger logger = logging.getLogger() logger.setLevel(logging.DEBUG) # Add a file handler handler = logging.FileHandler("pyqso.debug", mode="w") formatter = logging.Formatter(fmt="%(asctime)s %(levelname)s: %(message)s", datefmt="%Y-%m-%d %H:%M:%S") handler.setFormatter(formatter) logger.addHandler(handler) signal.signal(signal.SIGINT, signal.SIG_DFL) # Exit PyQSO if a SIGINT signal is captured. application = PyQSO(args.logbook) # Populate the main window and show it Gtk.main() # Start up the event loop!