main.py

来自「CoralFTP是一款用Python语言编写的工作在GTK2环境下的FTP客户端」· Python 代码 · 共 390 行

PY
390
字号
#!/usr/bin/env python# -*- coding: utf-8 -*-# Copyright (C) 1994  Ling Li## 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 2 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 Library General Public License for more details.## You should have received a copy of the GNU General Public License# along with this program; if not, write to the Free Software# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.import gobject, gtk, gtk.glade, gtk.gdk, gconf, gnomefrom gtk import *import gettext, getopt, locale, logging, logging.handlers, os, sys, threadfrom Queue import Queuefrom coralftp_globals import *from local_view import *from remote_view import *from transfer_view import *from log_view import *from site_manager import *from configuration import *from utils import *class CoralFTP:    __site_manager = None    __clipboard = None    threads = {}    ftp_thread_count = 1    __enable_debug = False    def __init__(self):        """Application initialization."""        # Setup locale & gettext        locale.setlocale(locale.LC_ALL, '')        gettext.install('coralftp', coralftp_localedir, unicode=1)        gtk.glade.bindtextdomain('coralftp', coralftp_localedir)        gtk.glade.textdomain('coralftp')        gtk.rc_parse_string('''        style "about_dialog_program_name" { font_name = "Sans 32" }        style "main_window_status_bar" { font_name = "Sans 8" }        widget "about_dialog.*.program_name" style "about_dialog_program_name"        widget "main_window.*.status_bar.*" style "main_window_status_bar"        ''')        # Initialize GNOME        gnome.program_init('coralftp', '0.1')        gtk.threads_init()        # parse arguments        try:            self.opts, self.args = getopt.getopt(sys.argv[1:], 'd', ['debug'])        except getopt.GetoptError:            self.usage()            sys.exit(2)        for o, a in self.opts:            if o in ('-d', '--debug'):                self.__enable_debug = True        return    def start(self):        self.__config = gconf.client_get_default()        self.__config.add_dir(CONFIG_PREFIX, gconf.CLIENT_PRELOAD_NONE)        enable_disk_based_logging = config_value(            self.__config, 'general', 'enable_disk_based_logging')        logger = logging.getLogger()        if enable_disk_based_logging:            status_log_filename = config_value(                self.__config, 'general', 'status_log_filename')            if not status_log_filename or status_log_filename == '':                status_log_filename = '~/.coralftp/coralftp.log'            status_log_filename = os.path.expanduser(status_log_filename)            trim_status_log_file = config_value(                self.__config, 'general', 'trim_status_log_file')            if trim_status_log_file:                status_log_file_size = config_value(                    self.__config, 'general', 'status_log_file_size')                status_log_file_size = status_log_file_size * 1024 * 1024            else:                status_log_file_size = 0            hdlr = logging.handlers.RotatingFileHandler(                status_log_filename, 'a', status_log_file_size)        else:            hdlr = logging.StreamHandler()        formatter = logging.Formatter(            '%(asctime)s %(levelname)s %(message)s')        hdlr.setFormatter(formatter)        logger.addHandler(hdlr)        if self.__enable_debug:            logger.setLevel(logging.DEBUG)        else:            logger.setLevel(logging.INFO)        self.register_thread('main')        main = MainWindow(self)        main.log_view.updater("CoralFTP %s\n" % coralftp_version)        gtk.threads_enter()        gtk.main()        gtk.threads_leave()        self.__config.remove_dir(CONFIG_PREFIX)    def terminate(self):        gtk.main_quit()        logging.debug('main thread quit')    def get_site_manager(self):        if not self.__site_manager:            self.__site_manager = SiteManager()        return self.__site_manager    def __getattr__(self, name):        if name == 'config':            return self.__config        elif name == 'clipboard':            if not self.__clipboard:                display = gtk.gdk.display_get_default()                self.__clipboard = Clipboard(display, "CLIPBOARD")            return self.__clipboard        else:            raise AttributeError, name        return    def register_thread(self, name):        id = thread.get_ident()        if name == 'main':            self.threads[id] = 'main thread'            logging.debug('main thread(%d) registered' % id)        elif name == 'ftp':            self.threads[id] = 'ftp thread %d' % self.ftp_thread_count            logging.debug('ftp thread %d(%d) registerd' \                          % (id, self.ftp_thread_count))            self.ftp_thread_count = self.ftp_thread_count + 1        return    def get_thread_name(self):        id = thread.get_ident()        if self.threads.has_key(id):            return '%s(%d)' % (self.threads[id], id)        else:            return 'other thread(%d)' % idclass MainWindow:    MODE_FTP = 1     # In this mode, one pane is local view another pane is                     # remote view.    MODE_LOCAL = 2   # In this mode, both pane are all local view    MODE_FXP = 3     # In this mode, both pane are all remote view    STATUSBAR_TYPE_GENERAL = 1    STATUSBAR_TYPE_TRANSFER = 2    __mode = None    __statusbar = None    __statusbar_type = None        def __init__(self, coralftp):        self.__xml = get_glade_xml('main_window')        self.__xml.signal_autoconnect(self)        self.widget = self.__xml.get_widget('main_window')        self.vbox = self.__xml.get_widget('vbox')        self.__statusbar = self.__xml.get_widget('status_bar')        self.__coralftp = coralftp        self.__config = self.__coralftp.config        self.__setup_active_indicator()        self.widget.connect("destroy",                            lambda obj: self.__coralftp.terminate())        self.create_contents()        self.create_general_statusbar()        self.widget.show_all()        # setup start with site manager        start_with_site_manager = config_value(            self.__config, 'display', 'start_with_site_manager')        if start_with_site_manager:            idle_add(self.start_with_site_manager)        return    def __setup_active_indicator(self):        self.__config.notify_add(            config_key('display', 'active_side_indicator_color'),            lambda config, id, entry, *args: \            gtk.rc_parse_string( \            'style "active_view_indicator" { bg[NORMAL] = "%s" }' \            % entry.value.get_string()))                    # color of active side bar        active_side_indicator_color = config_value(            self.__config, 'display', 'active_side_indicator_color')        gtk.rc_parse_string('''            style "active_view_indicator" { bg[NORMAL] = "%s" }            widget "*.active_view_indicator" style "active_view_indicator"        ''' % active_side_indicator_color)        return    def create_contents(self):        # create a log buffer        self.__log_buffer = TextBuffer()        self.__mode = self.MODE_FTP        self.__left_view = LocalView(self)        self.__right_view = RemoteView(self)        self.__transfer_view = TransferView(self)        self.__log_view = LogView(self)        return    def create_statusbar(self):        if self.__statusbar != None:            self.__statusbar.foreach(lambda obj, data: obj.destroy(), None)        else:            event_box = EventBox()            self.vbox.pack_end(event_box, expand=FALSE, fill=TRUE)            self.__statusbar = Table(1, 24, TRUE)            event_box.add_child(self.__statusbar)        return    def save_statusbar_height(self, *args):        statusbar_window = self.__statusbar.get_parent_window()        w, self.__statusbar_height = statusbar_window.get_size()        return            def create_general_statusbar(self):        self.__statusbar_type = self.STATUSBAR_TYPE_GENERAL        self.create_statusbar()        ef = EXPAND | FILL        self.status1 = Frame()        self.status1.add(Label())        self.__statusbar.attach(self.status1, 0, 12, 0, 1, ef, ef, 0, 0)        self.status1 = self.status1.get_child()        self.status1.set_alignment(0, 0.5)        self.status1.show()        self.status2 = Frame()        self.status2.add(Label())        self.__statusbar.attach(self.status2, 12, 23, 0, 1, ef, ef, 0, 0)        self.status2 = self.status2.get_child()        self.status2.set_alignment(0, 0.5)        self.status2.show()        self.status3 = Statusbar()        self.__statusbar.attach(self.status3, 23, 24, 0, 1, ef, ef, 0, 0)        self.__statusbar.foreach(lambda obj: obj.show())        idle_add(self.save_statusbar_height)        return self.__statusbar    def create_transfer_statusbar(self):        self.__statusbar_type = self.STATUSBAR_TYPE_TRANSFER        self.create_statusbar()        ef = EXPAND | FILL        self.status1 = Frame()        self.status1.add(Label()) # Filename        self.__statusbar.attach(self.status1, 0, 12, 0, 1, ef, ef, 0, 0)        self.status1 = self.status1.get_child()        self.status1.show()        self.status1.set_alignment(0, 0.5)        self.status2 = ProgressBar()        self.status2.set_size_request(-1, self.__statusbar_height)        self.__statusbar.attach(self.status2, 12, 16, 0, 1, ef, ef, 0, 0)        self.status3 = Frame()        self.status3.add(Label())        self.__statusbar.attach(self.status3, 16, 17, 0, 1, ef, ef, 0, 0)        self.status3 = self.status3.get_child()        self.status3.show()        self.status4 = Frame()        self.status4.add(Label()) # "Elapsed: 00:00"        self.__statusbar.attach(self.status4, 17, 20, 0, 1, ef, ef, 0, 0)        self.status4 = self.status4.get_child()        self.status4.show()        self.status5 = Frame()        self.status5.add(Label()) # "Remaining: 00:00"        self.__statusbar.attach(self.status5, 20, 23, 0, 1, ef, ef, 0, 0)        self.status5 = self.status5.get_child()        self.status5.show()        self.status6 = Statusbar()        self.__statusbar.attach(self.status6, 23, 24, 0, 1, ef, ef, 0, 0)        self.__statusbar.foreach(lambda obj: obj.show())        return self.__statusbar    def set_statusbar_style(self, obj, data):        if type(obj) == Frame:            obj.set_shadow_type(SHADOW_IN)            obj.set_border_width(0)            obj.get_child().modify_font(data)        if type(obj) == ProgressBar:            obj.modify_font(data)    def set_active_view(self, view):        if view == self.__left_view:            self.__right_view.set_active_view(FALSE)            self.__left_view.set_active_view(TRUE)        elif view == self.__right_view:            self.__left_view.set_active_view(FALSE)            self.__right_view.set_active_view(TRUE)    def get_another_view(self, view):        if view == self.__left_view:            return self.__right_view        elif view == self.__right_view:            return self.__left_view        else:            raise ValueError    def __getattr__(self, name):        if name == 'transfer_view':            return self.__transfer_view        elif name == 'log_view':            return self.__log_view        elif name == 'log_buffer':            return self.__log_buffer        elif name == 'update_queue':            return self.__update_queue        elif name == 'mode':            return self.__mode        elif name == 'statusbar_type':            return self.__statusbar_type        elif name == 'right_view':            return self.__right_view        elif name == 'left_view':            return self.__left_view        elif name == 'remote_view':            if self.__mode == MainWindow.MODE_FTP:                if isinstance(self.__right_view, RemoteView):                    return self.__right_view                elif isinstance(self.__left_view, RemoteView):                    return self.__left_view        elif name == 'local_view':            if self.__mode == MainWindow.MODE_FTP:                if isinstance(self.__left_view, LocalView):                    return self.__left_view                elif isinstance(self.__right_view, LocalView):                    return self.__right_view        elif name == 'coralftp':            return self.__coralftp        elif name == 'config':            return self.__config        elif name == 'xml':            return self.__xml        else:            raise AttributeError, name    def start_with_site_manager(self):        self.on_mmi_site_manager_activate(None)        return    def on_mmi_preferences_activate(self, obj, *args):        d = ConfigurationDialog(self.__coralftp)        resp = d.run()    def on_mmi_site_manager_activate(self, obj, *args):        d = SiteManagerDialog(self.__coralftp)        resp = d.run()        if resp == RESPONSE_OK:            s = d.get_selected_site()        d.destroy()        if resp == RESPONSE_OK:            self.remote_view.connect_site(s)        d = None        return    def on_mmi_about_dialog_activate(self, *args):        about_dialog = get_glade_xml('about_dialog')        label_program_name = about_dialog.get_widget('program_name')        label_program_name.set_text('CoralFTP %s' % coralftp_version)        dlg = about_dialog.get_widget('about_dialog')        resp = dlg.run()        dlg.destroy()        return    def on_mmi_quick_connect_activate(self, *args):        self.__right_view.on_quick_connect_action_execute(*args)        return    def on_mmi_quit_activate(self, *args):        self.widget.emit('destroy')        return

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?