"""
FtpCube
Copyright (C) Michael Gilfix
This file is part of FtpCube.
You should have received a file COPYING containing license terms
along with this program; if not, write to Michael Gilfix
(mgilfix@eecs.tufts.edu) for a copy.
This version of FtpCube is open source; you can redistribute it and/or
modify it under the terms listed in the file COPYING.
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.
"""
import wx
class EventRegistry:
"""Registry for custom event handlers.
This registry contains event handlers for custom events. Any number of
widgets an register to receive events. Each registered listener will
recieve an event callback when the event occurs in the order in which
the listeners were registered. This registry is necessary to allow
unrelated widgets to post events."""
def __init__(self):
"""Creates an empty event registry."""
self.registry = { }
def registerEventListener(self, event_type, listener):
"""Registers an event listener for the specified event type."""
if self.registry.has_key(event_type):
if listener not in self.registry[event_type]:
self.registry[event_type].append(listener)
else:
self.registry[event_type] = [ listener ]
def unregisterEventListener(self, event_type, listener):
"""Unregisters an event listener for the specified event type."""
list = self.registry[event_type]
if list is not None:
list.remove(listener)
if len(list) == 0:
del self.registry[event_type]
def postEvent(self, event):
"""Posts an event to all registered listeners.
Returns of the event listeners to which the event was posted. Calling
code should not modify the returned list."""
event_type = event.GetEventType()
if not self.registry[event_type]:
return None
listeners = self.registry[event_type]
for listener in listeners:
wx.PostEvent(listener, event)
return listeners
# Initialize the registry
registry = EventRegistry()
def getEventRegistry():
"""Returns the event registry instance."""
return registry
#######################################################################
# Events for main window widgets
#######################################################################
EVT_DIRECTORY_CHANGE_TYPE = wx.NewEventType()
EVT_DIRECTORY_CHANGE = wx.PyEventBinder(EVT_DIRECTORY_CHANGE_TYPE, 1)
class DirectoryChangeEvent(wx.PyEvent):
"""Directory change event.
This event is generated when the remote directory has been successfully
changed. The event includes the new directory path."""
def __init__(self, directory):
wx.PyEvent.__init__(self)
self.SetEventType(EVT_DIRECTORY_CHANGE_TYPE)
self.directory = directory
#######################################################################
# Events for file window widgets
#######################################################################
class BrowserWindowEvent(wx.PyEvent):
"""Browser window events.
These events should be generated when the browser window should be
updated. The following events are defined:
EVT_LIST_UPDATE: Update of the browser window listing
EVT_LIST_REFRESH: Refresh of the browser window listing
"""
EVT_LIST_UPDATE = wx.NewId()
EVT_LIST_REFRESH = wx.NewId()
def __init__(self, evt_type, kind, msg):
wx.PyEvent.__init__(self)
self.SetEventType(evt_type)
self.kind = kind
self.msg = msg
EVT_REMOTE_WINDOW_TYPE = wx.NewEventType()
EVT_REMOTE_WINDOW = wx.PyEventBinder(EVT_REMOTE_WINDOW_TYPE, 1)
class RemoteWindowEvent(BrowserWindowEvent):
"""Remote browser window events.
The following events are defined:
EVT_CWD: Change of the remote working directory
"""
EVT_CWD = wx.NewId() # remote change of working directory
def __init__(self, kind, msg):
BrowserWindowEvent.__init__(self, EVT_REMOTE_WINDOW_TYPE, kind, msg)
EVT_LOCAL_WINDOW_TYPE = wx.NewEventType()
EVT_LOCAL_WINDOW = wx.PyEventBinder(EVT_LOCAL_WINDOW_TYPE, 1)
class LocalWindowEvent(BrowserWindowEvent):
"""Local browser window events."""
def __init__(self, kind, msg):
BrowserWindowEvent.__init__(self, EVT_LOCAL_WINDOW_TYPE, kind, msg)
#######################################################################
# Events for the console widget
#######################################################################
EVT_CONSOLE_TYPE = wx.NewEventType()
EVT_CONSOLE = wx.PyEventBinder(EVT_CONSOLE_TYPE, 1)
class ConsoleEvent(wx.PyEvent):
"""Console event.
This event is triggering for messages that should be displayed
within the application console."""
def __init__(self, kind, msg):
wx.PyEvent.__init__(self)
self.SetEventType(EVT_CONSOLE_TYPE)
self.kind = kind
self.msg = msg
#######################################################################
# Events for notification of thread activity to thread widgets
#######################################################################
EVT_THREAD_TYPE = wx.NewEventType()
EVT_THREAD = wx.PyEventBinder(EVT_THREAD_TYPE, 1)
class ThreadEvent(wx.PyEvent):
"""Thread-related events.
This class is used to signify the activities of connection threads
to the higher level UI. It defines several kinds of thread activities:
EVT_CREATE: Creation of a new connection thread
EVT_DESTROY: Destruction of a connection thread
EVT_CONNECT: Connection to a file transfer site
EVT_LIST: Receipt of a file transfer listing
EVT_CWD: Receipt of the current working directory
EVT_RENAME: Execution of a rename operation
EVT_DELETE: Execution of a delete operation
EVT_MKDIR: Execution of a create new directory operation
EVT_RMDIR: Execution of a remove directory operation
EVT_CHMOD: Execution of a change permissions operation
"""
EVT_CREATE = wx.NewId()
EVT_DESTROY = wx.NewId()
EVT_CONNECT = wx.NewId()
EVT_LIST = wx.NewId()
EVT_CWD = wx.NewId()
EVT_RENAME = wx.NewId()
EVT_DELETE = wx.NewId()
EVT_MKDIR = wx.NewId()
EVT_RMDIR = wx.NewId()
EVT_CHMOD = wx.NewId()
def __init__(self, id, kind, data=None):
wx.PyEvent.__init__(self)
self.SetEventType(EVT_THREAD_TYPE)
self.id = id
self.kind = kind
self.data = data
#######################################################################
# Events for receipt of thread status
#######################################################################
EVT_THREAD_STATUS_TYPE = wx.NewEventType()
EVT_THREAD_STATUS = wx.PyEventBinder(EVT_THREAD_STATUS_TYPE, 1)
class ThreadStatusEvent(wx.PyEvent):
"""Events related to thread status.
When status objects receive events and want to communicate those
events back to the connection threads associated with the status,
this event can be generated."""
EVT_DESTROY_CONNECT = wx.NewId()
EVT_RETRY_CONNECT = wx.NewId()
EVT_UPDATE_PROGRESS = wx.NewId()
EVT_FINISH_TRANSFER = wx.NewId()
def __init__(self, kind, data=None):
wx.PyEvent.__init__(self)
self.SetEventType(EVT_THREAD_STATUS_TYPE)
self.kind = kind
self.data = data
#######################################################################
# Events for interfacing with the control queue, thread, download, and
# failure widgets
#######################################################################
EVT_QUEUE_TYPE = wx.NewEventType()
EVT_QUEUE = wx.PyEventBinder(EVT_QUEUE_TYPE, 1)
EVT_DEQUEUE_TYPE = wx.NewEventType()
EVT_DEQUEUE = wx.PyEventBinder(EVT_DEQUEUE_TYPE, 1)
EVT_TRANSFER_TYPE = wx.NewEventType()
EVT_TRANSFER = wx.PyEventBinder(EVT_TRANSFER_TYPE, 1)
EVT_FAILURE_TYPE = wx.NewEventType()
EVT_FAILURE = wx.PyEventBinder(EVT_FAILURE_TYPE, 1)
class QueueEvent(wx.PyEvent):
"""Base queue event for the file transfer queue.
Each queued event uses a directionary that defines the following
attributes:
'file': The file to transfer
'host': The host with which to perform the transfer
'port': The port to which to connect
'username': The username to use for this transfer
'password': The password to use for this transfer
'remote_path': The remote directory path
'local_path': The local directory path
'size': The size of the file being transferred
'attempt': The current attempt count
'max_attempts': The max number of attempts for this file
'direction': The transfer direction
'flags': The flags indicating the kind of file
'method': The transfer method to use
'transport': The transport used for the file transfer
"""
def __init__(self, evt_type, **kwargs):
wx.PyEvent.__init__(self)
self.SetEventType(evt_type)
self.file = kwargs['file']
self.host = kwargs['host']
self.port = kwargs['port']
self.username = kwargs['username']
self.password = kwargs['password']
self.remote_path = kwargs['remote_path']
self.local_path = kwargs['local_path']
self.size = kwargs['size']
self.attempt = kwargs['attempt']
self.max_attempts = kwargs['max_attempts']
self.direction = kwargs['direction']
self.flags = kwargs['flags']
self.method = kwargs['method']
self.transport = kwargs['transport']
def toHash(self):
"""Returns a dictionary containing the queue event information."""
return {
'file' : self.file,
'host' : self.host,
'port' : self.port,
'username' : self.username,
'password' : self.password,
'remote_path' : self.remote_path,
'local_path' : self.local_path,
'size' : self.size,
'attempt' : self.attempt,
'max_attempts' : self.max_attempts,
'direction' : self.direction,
'flags' : self.flags,
'method' : self.method,
'transport' : self.transport
}
class EnqueueEvent(QueueEvent):
"""Enqueue event adding a new file transfer entry to the queue."""
def __init__(self, **kwargs):
QueueEvent.__init__(self, EVT_QUEUE_TYPE, **kwargs)
class DequeueEvent(QueueEvent):
"""Dequeue event removing a file transfer entry from the queue."""
def __init__(self, **kwargs):
QueueEvent.__init__(self, EVT_DEQUEUE_TYPE, **kwargs)
class TransferEvent(QueueEvent):
"""Transfer (download/upload) event within the queue."""
def __init__(self, **kwargs):
QueueEvent.__init__(self, EVT_TRANSFER_TYPE, **kwargs)
class FailureEvent(QueueEvent):
"""Failure event processing a transfer from the queue.
This class defines an additional keyword argument:
'error': The error message indicating the type of error that occurred.
"""
def __init__(self, **kwargs):
QueueEvent.__init__(self, EVT_FAILURE_TYPE, **kwargs)
self.error = kwargs['error']
def toHash(self):
"""Returns a dictionary containing the failure event information.
This includes the addition Failure event keywords."""
hash = QueueEvent.toHash(self)
hash.update({ 'error' : self.error })
return hash
|