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 + -
显示快捷键?