diff --git a/pyqso/dx_cluster.py b/pyqso/dx_cluster.py index 44c0f28..1b22632 100644 --- a/pyqso/dx_cluster.py +++ b/pyqso/dx_cluster.py @@ -26,6 +26,9 @@ except ImportError: import ConfigParser as configparser import os.path +from pyqso.telnet_connection_dialog import TelnetConnectionDialog +from pyqso.auxiliary_dialogs import error + BOOKMARKS_FILE = os.path.expanduser('~/.config/pyqso/bookmarks.ini') @@ -77,32 +80,24 @@ class DXCluster: def new_server(self, widget=None): """ Get Telnet server host and login details specified in the Gtk.Entry boxes in the Telnet connection dialog and attempt a connection. """ - # Build connection dialog - logging.debug("Setting up the Telnet connection dialog...") - glade_file_path = os.path.join(os.path.realpath(os.path.dirname(__file__)), os.pardir, "res/pyqso.glade") - self.builder.add_objects_from_file(glade_file_path, ("telnet_connection_dialog",)) - dialog = self.builder.get_object("telnet_connection_dialog") - connection_info = {"HOST": self.builder.get_object("host_entry"), - "PORT": self.builder.get_object("port_entry"), - "USERNAME": self.builder.get_object("username_entry"), - "PASSWORD": self.builder.get_object("password_entry"), - "BOOKMARK": self.builder.get_object("bookmark_checkbox")} - - response = dialog.run() + # Get connection details. + tcd = TelnetConnectionDialog(self.application) + response = tcd.dialog.run() if(response == Gtk.ResponseType.OK): - host = connection_info["HOST"].get_text() - port = connection_info["PORT"].get_text() - username = connection_info["USERNAME"].get_text() - password = connection_info["PASSWORD"].get_text() + host = tcd.host + port = tcd.port + username = tcd.username + password = tcd.password + bookmark = tcd.bookmark + tcd.dialog.destroy() # Handle empty hostname. - if(host == ""): + if(not host): logging.error("No hostname specified.") - dialog.destroy() return # Handle empty port number. - if(port == ""): + if(not port): logging.warning("No port specified. Assuming default port 23...") port = 23 else: @@ -112,17 +107,16 @@ class DXCluster: except ValueError as e: logging.error("Could not cast the DX cluster's port information to an integer.") logging.exception(e) - dialog.destroy() return # Save the server details in a new bookmark, if desired. - if(connection_info["BOOKMARK"].get_active()): + if(bookmark): try: config = configparser.ConfigParser() config.read(BOOKMARKS_FILE) # Use the host name as the bookmark's identifier. - if(username != ""): + if(username): bookmark_identifier = "%s@%s:%d" % (username, host, port) else: bookmark_identifier = "%s:%d" % (host, port) @@ -151,13 +145,11 @@ class DXCluster: # Maybe the bookmarks file could not be written to? logging.error("Bookmark could not be saved. Check bookmarks file permissions? Going ahead with the server connection anyway...") - dialog.destroy() - # Attempt a connection with the server. self.telnet_connect(host, port, username, password) else: - dialog.destroy() + tcd.dialog.destroy() return def populate_bookmarks(self): @@ -227,16 +219,20 @@ class DXCluster: :arg str password: The user's password. This is an optional argument. """ - if(host == "" or host is None): - logging.error("No hostname specified.") + # Handle empty host/port string (or the case where host/port are None). + if(not host): + message = "Unable to connect to a DX cluster because no hostname was specified." + logging.error(message) + error(parent=self.application.window, message=message) return - if(port == "" or port is None): + if(not port): logging.warning("No port specified. Assuming default port 23...") - port = 23 # Use the default Telnet port + port = 23 # Use the default Telnet port. try: - logging.debug("Attempting connection to Telnet server %s:%d" % (host, port)) + logging.debug("Attempting connection to Telnet server %s:%d..." % (host, port)) self.connection = telnetlib.Telnet(host, port) + assert(self.connection) if(username): self.connection.read_until("login: ".encode()) @@ -245,11 +241,15 @@ class DXCluster: self.connection.read_until("password: ".encode()) self.connection.write((password + "\n").encode()) except Exception as e: - logging.error("Could not create a connection to the Telnet server.") + message = "Could not create a connection to the Telnet server %s:%d. Check connection to the internets? Check connection details?" % (host, port) + logging.error(message) logging.exception(e) + error(parent=self.application.window, message=message) self.connection = None return + logging.debug("Connection to %s:%d established." % (host, port)) + self.set_items_sensitive(False) self.check_io_event = GObject.timeout_add(1000, self.on_telnet_io) diff --git a/pyqso/telnet_connection_dialog.py b/pyqso/telnet_connection_dialog.py new file mode 100644 index 0000000..01b727a --- /dev/null +++ b/pyqso/telnet_connection_dialog.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2017 Christian Thomas 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 . + +import os +import logging + + +class TelnetConnectionDialog: + + """ A handler for the Gtk.Dialog through which a user can specify Telnet connection details. """ + + def __init__(self, application): + """ Create and show the Telnet connection dialog to the user. + + :arg application: The PyQSO application containing the main Gtk window, etc. + """ + + logging.debug("Building new Telnet connection dialog...") + + self.builder = application.builder + glade_file_path = os.path.join(os.path.realpath(os.path.dirname(__file__)), os.pardir, "res/pyqso.glade") + self.builder.add_objects_from_file(glade_file_path, ("telnet_connection_dialog",)) + self.dialog = self.builder.get_object("telnet_connection_dialog") + self.sources = {"HOST": self.builder.get_object("host_entry"), + "PORT": self.builder.get_object("port_entry"), + "USERNAME": self.builder.get_object("username_entry"), + "PASSWORD": self.builder.get_object("password_entry"), + "BOOKMARK": self.builder.get_object("bookmark_checkbox")} + + self.dialog.show_all() + + logging.debug("Telnet connection dialog built.") + + return + + @property + def host(self): + """ Return the Telnet server's host name. + + :returns: The server's host name. + :rtype: str + """ + return self.sources["HOST"].get_text() + + @property + def port(self): + """ Return the Telnet server's port number (as a string). + + :returns: The server's port number (as a string). + :rtype: str + """ + return self.sources["PORT"].get_text() + + @property + def username(self): + """ Return the user's username. + + :returns: The user's username. + :rtype: str + """ + return self.sources["USERNAME"].get_text() + + @property + def password(self): + """ Return the user's password. + + :returns: The user's password. + :rtype: str + """ + return self.sources["PASSWORD"].get_text() + + @property + def bookmark(self): + """ Return True if a new bookmark should be created, otherwise return False. + + :returns: True if a new bookmark should be created, otherwise False. + :rtype: bool + """ + return self.sources["BOOKMARK"].get_active()