This file is indexed.

/usr/bin/pyqso is in pyqso 0.3-1.1.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#!/usr/bin/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 <http://www.gnu.org/licenses/>.

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 = ["/usr/share/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 <http://www.gnu.org/licenses/>.""")
        about.set_comments("PyQSO: A contact logging tool for amateur radio operators.")
        possible_icon_paths = ["/usr/share/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!