diff -Nru tucan-0.3.8/about.py tucan-0.3.9/about.py --- tucan-0.3.8/about.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/about.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,69 +0,0 @@ - # -*- coding: iso-8859-15 -*- -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import pygtk -pygtk.require('2.0') -import gtk - -import cons - -NAME = "Tucan" -COPYRIGHT = u"© 2008-2009 The Tucan Project" -AUTHORS = ["Fran Lupion crak(at)tucaneando.com"] -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 . - """ - -class About(gtk.AboutDialog): - """""" - def __init__(self, widget=None): - """""" - gtk.AboutDialog.__init__(self) - self.set_position(gtk.WIN_POS_CENTER) - self.set_icon_from_file(cons.ICON_TUCAN) - self.set_logo(gtk.gdk.pixbuf_new_from_file(cons.ICON_TUCAN)) - self.set_name(NAME) - self.set_version(cons.TUCAN_VERSION) - self.set_copyright(COPYRIGHT) - self.set_license(LICENSE) - self.set_website(cons.WEBPAGE) - self.connect("response", self.close) - self.show_all() - self.run() - - def close(self, widget=None, other=None): - """""" - self.destroy() - -if __name__ == "__main__": - g = About() - gtk.main() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/accounts.py /tmp/DgSymrsclJ/tucan-0.3.9/accounts.py --- tucan-0.3.8/accounts.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/accounts.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,52 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import logging -logger = logging.getLogger(__name__) - -class Accounts: - """""" - def __init__(self, config, section, cookie): - """""" - self.config = config - self.active = False - self.section = section - self.cookie = cookie - self.accounts = self.config.get_accounts(self.section) - for account in self.accounts.values(): - if account[1]: - self.active = True - - def get_cookie(self, url=None): - """""" - result = None - for user, data in self.accounts.items(): - if data[1]: - cookie = self.cookie.get_cookie(user, data[0], url) - if cookie: - result = cookie - else: - self.accounts[user] = (data[0], False, False) - self.config.set_accounts(self.section, self.accounts) - logger.warning("Account %s disabled." % user) - if result: - return result - else: - self.active = False diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/advanced_packages.py /tmp/DgSymrsclJ/tucan-0.3.9/advanced_packages.py --- tucan-0.3.8/advanced_packages.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/advanced_packages.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,139 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import pygtk -pygtk.require('2.0') -import gtk - -from file_chooser import FileChooser - -import cons - -class AdvancedPackages(gtk.Dialog): - """""" - def __init__(self, default_path, packages): - """""" - gtk.Dialog.__init__(self) - self.set_icon_from_file(cons.ICON_PACKAGE) - self.set_title(_("Advanced Packages")) - self.set_size_request(600,400) - - self.packages = [] - self.history_path = default_path - - #treeview - frame = gtk.Frame() - self.vbox.pack_start(frame) - frame.set_border_width(10) - scroll = gtk.ScrolledWindow() - frame.add(scroll) - scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self.treeview = gtk.TreeView(gtk.ListStore(gtk.gdk.Pixbuf, str, str, str)) - scroll.add(self.treeview) - - self.treeview.set_rules_hint(True) - #self.treeview.set_headers_visible(False) - - tree_icon = gtk.TreeViewColumn('Icon') - icon_cell = gtk.CellRendererPixbuf() - tree_icon.pack_start(icon_cell, True) - tree_icon.add_attribute(icon_cell, 'pixbuf', 0) - self.treeview.append_column(tree_icon) - - tree_path = gtk.TreeViewColumn('Path') - path_cell = gtk.CellRendererText() - tree_path.pack_start(path_cell, True) - tree_path.add_attribute(path_cell, 'text', 1) - self.treeview.append_column(tree_path) - self.treeview.connect("row-activated", self.choose) - - tree_name = gtk.TreeViewColumn('Name') - name_cell = gtk.CellRendererText() - name_cell.set_property("editable", True) - name_cell.connect("edited", self.change, 2) - tree_name.pack_start(name_cell, True) - tree_name.add_attribute(name_cell, 'text', 2) - self.treeview.append_column(tree_name) - - tree_pass = gtk.TreeViewColumn('Password') - pass_cell = gtk.CellRendererText() - pass_cell.set_property("editable", True) - pass_cell.connect("edited", self.change, 3) - tree_pass.pack_start(pass_cell, True) - tree_pass.add_attribute(pass_cell, 'text', 3) - self.treeview.append_column(tree_pass) - - #fill treestore - package_icon = gtk.gdk.pixbuf_new_from_file(cons.ICON_PACKAGE) - model = self.treeview.get_model() - for package_name, package_links in packages: - model.append((package_icon, default_path, package_name, None)) - - #choose path - hbox = gtk.HBox() - self.vbox.pack_start(hbox, False, False, 5) - path_button = gtk.Button(None, gtk.STOCK_OPEN) - hbox.pack_start(path_button, False, False, 10) - path_button.set_size_request(90,40) - path_button.connect("clicked", self.choose_path) - path_label = gtk.Label(_("Choose new path for selected Package.")) - hbox.pack_start(path_label, False, False, 10) - - #action area - ok_button = gtk.Button(None, gtk.STOCK_OK) - self.action_area.pack_start(ok_button) - ok_button.connect("clicked", self.configure_packages) - - self.connect("response", self.close) - self.show_all() - self.run() - - def configure_packages(self, button=None): - """""" - model = self.treeview.get_model() - for package in model: - self.packages.append((package[1], package[2], package[3])) - self.close() - - def choose(self, treeview, path, view_column): - """""" - self.choose_path() - - def choose_path(self, button=None): - """""" - model, iter = self.treeview.get_selection().get_selected() - if iter: - f = FileChooser(self, self.on_choose, self.history_path) - self.history_path = f.history_path - - def on_choose(self, folder_path): - """""" - model, iter = self.treeview.get_selection().get_selected() - if iter: - model.set_value(iter, 1, folder_path) - - def change(self, cellrenderertext, path, new_text, column): - """""" - model = self.treeview.get_model() - model.set_value(model.get_iter(path), column, new_text) - - def close(self, widget=None, other=None): - """""" - self.destroy() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/CHANGELOG /tmp/DgSymrsclJ/tucan-0.3.9/CHANGELOG --- tucan-0.3.8/CHANGELOG 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/CHANGELOG 2009-10-07 00:02:31.000000000 +0100 @@ -1,3 +1,23 @@ +Tucan 0.3.9 Alpha 2009-10-07. +------------------------------ +- Command Line interface. +- Shutdown Addon. +- Clipboard monitor. +- New Update Manager. +- Single Package Mode. +- Download .part files. +- Report bugs from LogView. +- Statusbar limit cancel. +- Solved many GUI bugs. +- New anonymous Depositfiles plugin. +- New anonymous Hotfile plugin. +- Russian Localization. +- Greek Localization. +- Czech Localization. +- OSX support. +- Makefile updated. +- manpage updated. + Tucan 0.3.8 Alpha 2009-07-15. ------------------------------ - Download speed limiter. @@ -40,7 +60,7 @@ - Solved Limits bug. - New Anonymous 4Shared plugin. -Tucan 0.3.5 Alpha 2009-03-3. +Tucan 0.3.5 Alpha 2009-03-03. ------------------------------ - Uploads Window. - Update Manager. diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/config.py /tmp/DgSymrsclJ/tucan-0.3.9/config.py --- tucan-0.3.8/config.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/config.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,150 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import os -import shutil - -from ConfigParser import SafeConfigParser - -import service_config -import cons - -CONF = "tucan.conf" - -COMMENT = """# Tucan Manager's default configuration. -# Dont change anything unless you really know what are doing, -# instead use the preferences dialog of the GUI.""" - -SECTION_MAIN = "main" -SECTION_SERVICES = "services" -SECTION_ADVANCED = "advanced" - -OPTION_VERSION = "version" - -OPTION_LANGUAGE = "language" -OPTION_MAX_DOWNLOADS = "max_downloads" -OPTION_MAX_DOWNLOAD_SPEED = "max_download_speed" -OPTION_MAX_UPLOADS = "max_uploads" -OPTION_DOWNLOADS_FOLDER = "downloads_folder" - -OPTION_TRAY_CLOSE = "tray_close" -OPTION_ADVANCED_PACKAGES = "advanced_packages" -OPTION_SAVE_SESSION = "save_session" -OPTION_AUTO_UPDATE = "auto_update" -OPTION_SHOW_UPLOADS = "show_uploads" -OPTION_ENABLE_PROXY = "enable_proxy" -OPTION_PROXY_URL = "proxy_url" -OPTION_PROXY_PORT = "proxy_port" - -DEFAULTS = {SECTION_MAIN: {OPTION_VERSION: cons.TUCAN_VERSION, OPTION_LANGUAGE: "en", OPTION_MAX_DOWNLOADS: "5", OPTION_MAX_DOWNLOAD_SPEED: "0", OPTION_MAX_UPLOADS: "5", OPTION_DOWNLOADS_FOLDER: cons.DEFAULT_PATH} - , SECTION_SERVICES: {} - , SECTION_ADVANCED: {OPTION_TRAY_CLOSE: "False", OPTION_SAVE_SESSION: "True", OPTION_ADVANCED_PACKAGES: "False", OPTION_AUTO_UPDATE: "True",OPTION_SHOW_UPLOADS: "False", OPTION_ENABLE_PROXY: "False", OPTION_PROXY_URL: "", OPTION_PROXY_PORT: "0"}} - -class Config(SafeConfigParser): - """""" - def __init__(self): - """""" - SafeConfigParser.__init__(self) - self.configured = True - if not os.path.exists(cons.CONFIG_PATH): - os.mkdir(cons.CONFIG_PATH) - if not os.path.exists(cons.CONFIG_PATH + CONF): - self.create_config() - self.configured = False - else: - self.read(cons.CONFIG_PATH + CONF) - if not self.check_config(): - self.create_config() - self.configured = False - if not os.path.exists(cons.PLUGIN_PATH): - shutil.copytree(cons.DEFAULT_PLUGINS, cons.PLUGIN_PATH) - for service in os.listdir(cons.PLUGIN_PATH): - if os.path.isdir(os.path.join(cons.PLUGIN_PATH, service)): - path = os.path.join(cons.PLUGIN_PATH, service, "") - package, icon, name, enabled, config = self.service(path) - if name: - self.set(SECTION_SERVICES, name, path) - self.save() - - def check_config(self): - """""" - for section, options in DEFAULTS.items(): - if self.has_section(section): - if section == SECTION_MAIN: - if self.has_option(section, OPTION_VERSION): - if self.get(section, OPTION_VERSION) != cons.TUCAN_VERSION: - shutil.rmtree(cons.PLUGIN_PATH) - return False - else: - shutil.rmtree(cons.PLUGIN_PATH) - return False - for option, value in options.items(): - if option not in [option for option, value in self.items(section)]: - return False - else: - return False - return True - - def create_config(self): - """""" - for section, options in DEFAULTS.items(): - if not self.has_section(section): - self.add_section(section) - for option, value in options.items(): - self.set(section, option, value) - self.save() - - def get_services(self): - """""" - result = [] - for service, path in self.items(SECTION_SERVICES): - result.append(self.service(path)) - return sorted(result) - - def service(self, path): - """""" - result = path, None, None, None, None - config = service_config.ServiceConfig(path) - if config.check_config(): - icon = config.get_icon() - name = config.get(service_config.SECTION_MAIN, service_config.OPTION_NAME) - enabled = config.getboolean(service_config.SECTION_MAIN, service_config.OPTION_ENABLED) - result = os.path.split(os.path.split(path)[0])[1], icon, name, enabled, config - return result - - def get_proxy(self): - """""" - result = None, None - if self.has_section(SECTION_ADVANCED): - if self.getboolean(SECTION_ADVANCED, OPTION_ENABLE_PROXY): - result = self.get(SECTION_ADVANCED, OPTION_PROXY_URL), self.getint(SECTION_ADVANCED, OPTION_PROXY_PORT) - return result - - def save(self, comment=True): - """""" - f = open(cons.CONFIG_PATH + CONF, "w") - if comment: - f.write(COMMENT + "\n\n") - self.write(f) - f.close() - -if __name__ == "__main__": - c = Config() - print c.configured diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/cons.py /tmp/DgSymrsclJ/tucan-0.3.9/cons.py --- tucan-0.3.8/cons.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/cons.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,115 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import sys -import os -import locale -import subprocess -import logging - -# project constants -TUCAN_NAME = "Tucan Manager" -TUCAN_VERSION = "0.3.8 alpha" -WEBPAGE = "http://www.tucaneando.com" -DOC = "http://doc.tucaneando.com" - -# user agent -USER_AGENT = {"User-Agent":"Mozilla/5.0 (X11; U; Linux i686) Gecko/20081114 Firefox/3.0.4"} - -# status constants -STATUS_PEND = "pending" -STATUS_ACTIVE = "active" -STATUS_WAIT = "waiting" -STATUS_STOP = "stoped" -STATUS_CORRECT = "correct" -STATUS_ERROR = "error" - -#message constants -SEVERITY_INFO = "info" -SEVERITY_WARNING = "warning" -SEVERITY_ERROR = "error" - -#size unit constants -UNIT_KB = "KB" -UNIT_MB = "MB" -UNIT_GB = "GB" - -#speed unit constant -UNIT_SPEED = "KB/s" - -#time constants -MINUTE = 60 -HOUR = 3600 - -#service type constans -TYPE_ANONYMOUS = "Anonymous" -TYPE_USER = "User" -TYPE_PREMIUM = "Premium" -TYPE_UNSUPPORTED = "unsupported" - -#path constants -if "win" in sys.platform: - PATH = os.path.abspath(os.path.dirname(sys.argv[0])) - DEFAULT_PATH = os.path.join(os.path.expanduser("~"), "").decode(locale.getdefaultlocale()[1]) - if PATH not in sys.path: - sys.path.insert(0, PATH) -else: - PATH = os.path.join(sys.path[0], "") - DEFAULT_PATH = os.path.join(os.path.expanduser("~"), "") -CONFIG_PATH = os.path.join(DEFAULT_PATH, ".tucan" ,"") - -#log constants -LOG_FILE = os.path.join(CONFIG_PATH, "tucan.log") -LOGGER = "Tucan logger" - -#plugin constants -PLUGIN_PATH = os.path.join(CONFIG_PATH, "plugins") -DEFAULT_PLUGINS = os.path.join(PATH, "default_plugins", "") - -#session constants -SESSION_FILE = os.path.join(CONFIG_PATH, "last.session") - -#localization constants -NAME_LOCALES = "tucan" -PATH_LOCALES = os.path.join(PATH, "i18n") - -#media constants -PATH_MEDIA = os.path.join(PATH, "media", "") -ICON_TUCAN = PATH_MEDIA + "tucan.svg" -ICON_DOWNLOAD = PATH_MEDIA + "document-save.svg" -ICON_UPLOAD = PATH_MEDIA + "system-software-update.svg" -ICON_CLEAR = PATH_MEDIA + "edit-delete.svg" -ICON_DOWN = PATH_MEDIA + "go-down.svg" -ICON_UP = PATH_MEDIA + "go-up.svg" -ICON_START = PATH_MEDIA + "media-playback-start.svg" -ICON_STOP = PATH_MEDIA + "media-playback-stop.svg" -ICON_CHECK = PATH_MEDIA + "software-update-available.svg" -ICON_PACKAGE = PATH_MEDIA + "package-x-generic.svg" -ICON_PREFERENCES = PATH_MEDIA + "preferences-system.svg" -ICON_PREFERENCES_MAIN = PATH_MEDIA + "preferences-desktop.svg" -ICON_PREFERENCES_SERVICES = PATH_MEDIA + "contact-new.svg" -ICON_PREFERENCES_ADVANCED = PATH_MEDIA + "applications-system.svg" -ICON_LANGUAGE = PATH_MEDIA + "preferences-desktop-locale.svg" -ICON_FOLDER = PATH_MEDIA + "user-home.svg" -ICON_NETWORK = PATH_MEDIA + "network-error.svg" -ICON_ADVANCED = PATH_MEDIA + "application-x-executable.svg" -ICON_MISSING = PATH_MEDIA + "image-missing.svg" -ICON_ACCOUNT = PATH_MEDIA + "system-users.svg" -ICON_UPDATE = PATH_MEDIA + "software-update-urgent.svg" diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/core/accounts.py /tmp/DgSymrsclJ/tucan-0.3.9/core/accounts.py --- tucan-0.3.8/core/accounts.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/core/accounts.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,52 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import logging +logger = logging.getLogger(__name__) + +class Accounts: + """""" + def __init__(self, config, section, cookie): + """""" + self.config = config + self.active = False + self.section = section + self.cookie = cookie + self.accounts = self.config.get_accounts(self.section) + for account in self.accounts.values(): + if account[1]: + self.active = True + + def get_cookie(self, url=None): + """""" + result = None + for user, data in self.accounts.items(): + if data[1]: + cookie = self.cookie.get_cookie(user, data[0], url) + if cookie: + result = cookie + else: + self.accounts[user] = (data[0], False, False) + self.config.set_accounts(self.section, self.accounts) + logger.warning("Account %s disabled." % user) + if result: + return result + else: + self.active = False diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/core/config.py /tmp/DgSymrsclJ/tucan-0.3.9/core/config.py --- tucan-0.3.8/core/config.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/core/config.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,175 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import uuid +import os +import shutil + +from ConfigParser import SafeConfigParser + +import service_config +import cons + +CONF = "tucan.conf" + +COMMENT = """# Tucan Manager's default configuration. +# Dont change anything unless you really know what are doing, +# instead use the preferences dialog of the GUI.""" + +SECTION_MAIN = "main" +SECTION_SERVICES = "services" +SECTION_ADVANCED = "advanced" + +OPTION_VERSION = "version" +OPTION_UUID = "uuid" + +OPTION_LANGUAGE = "language" +OPTION_MAX_DOWNLOADS = "max_downloads" +OPTION_MAX_DOWNLOAD_SPEED = "max_download_speed" +OPTION_MAX_UPLOADS = "max_uploads" +OPTION_DOWNLOADS_FOLDER = "downloads_folder" + +OPTION_TRAY_CLOSE = "tray_close" +OPTION_ADVANCED_PACKAGES = "advanced_packages" +OPTION_SAVE_SESSION = "save_session" +OPTION_AUTO_UPDATE = "auto_update" +OPTION_SHOW_UPLOADS = "show_uploads" +OPTION_ENABLE_PROXY = "enable_proxy" +OPTION_PROXY_URL = "proxy_url" +OPTION_PROXY_PORT = "proxy_port" + +DEFAULTS = {SECTION_MAIN: {OPTION_VERSION: cons.TUCAN_VERSION, OPTION_LANGUAGE: "en", OPTION_MAX_DOWNLOADS: "5", OPTION_MAX_DOWNLOAD_SPEED: "0", OPTION_MAX_UPLOADS: "5", OPTION_DOWNLOADS_FOLDER: cons.DEFAULT_PATH.encode("utf-8")} + , SECTION_SERVICES: {} + , SECTION_ADVANCED: {OPTION_TRAY_CLOSE: "False", OPTION_SAVE_SESSION: "True", OPTION_ADVANCED_PACKAGES: "False", OPTION_AUTO_UPDATE: "True",OPTION_SHOW_UPLOADS: "False", OPTION_ENABLE_PROXY: "False", OPTION_PROXY_URL: "", OPTION_PROXY_PORT: "0"}} + +class Config(SafeConfigParser): + """""" + def __init__(self): + """""" + SafeConfigParser.__init__(self) + self.configured = True + if not os.path.exists(cons.CONFIG_PATH): + os.mkdir(cons.CONFIG_PATH) + if not os.path.exists(cons.CONFIG_PATH + CONF): + self.create_config() + self.configured = False + else: + self.read(cons.CONFIG_PATH + CONF) + if not self.check_config(): + self.create_config() + self.configured = False + if not os.path.exists(cons.PLUGIN_PATH): + shutil.copytree(cons.DEFAULT_PLUGINS, cons.PLUGIN_PATH) + for service in os.listdir(cons.PLUGIN_PATH): + if os.path.isdir(os.path.join(cons.PLUGIN_PATH, service)): + path = os.path.join(cons.PLUGIN_PATH, service, "") + package, icon, name, enabled, config = self.service(path) + if name: + self.set(SECTION_SERVICES, name, path.encode("utf-8")) + self.save() + + def check_config(self): + """""" + for section, options in DEFAULTS.items(): + if self.has_section(section): + if section == SECTION_MAIN: + if self.has_option(section, OPTION_VERSION): + if self.get(section, OPTION_VERSION) != cons.TUCAN_VERSION: + shutil.rmtree(cons.PLUGIN_PATH) + return False + else: + shutil.rmtree(cons.PLUGIN_PATH) + return False + for option, value in options.items(): + if option not in [option for option, value in self.items(section)]: + return False + else: + return False + return True + + def create_config(self): + """""" + for section, options in DEFAULTS.items(): + if not self.has_section(section): + self.add_section(section) + for option, value in options.items(): + self.set(section, option, value) + #set uuid + self.set(SECTION_MAIN, OPTION_UUID, str(uuid.uuid1())) + self.save() + + def get_uuid(self): + """""" + if self.has_option(SECTION_MAIN, OPTION_UUID): + return self.get(SECTION_MAIN, OPTION_UUID) + else: + new_uuid = str(uuid.uuid1()) + self.set(SECTION_MAIN, OPTION_UUID, new_uuid) + self.save() + return new_uuid + + def get_downloads_folder(self): + """""" + if self.has_option(SECTION_MAIN, OPTION_DOWNLOADS_FOLDER): + return self.get(SECTION_MAIN, OPTION_DOWNLOADS_FOLDER).decode("utf-8") + else: + return cons.DEFAULT_PATH + + def set_downloads_folder(self, path): + """""" + self.set(SECTION_MAIN, OPTION_DOWNLOADS_FOLDER, path.encode("utf-8")) + + def get_services(self): + """""" + result = [] + for service, path in self.items(SECTION_SERVICES): + result.append(self.service(path.decode("utf-8"))) + return sorted(result) + + def service(self, path): + """""" + result = path, None, None, None, None + config = service_config.ServiceConfig(path) + if config.check_config(): + icon = config.get_icon() + name = config.get(service_config.SECTION_MAIN, service_config.OPTION_NAME) + enabled = config.getboolean(service_config.SECTION_MAIN, service_config.OPTION_ENABLED) + result = os.path.split(os.path.split(path)[0])[1], icon, name, enabled, config + return result + + def get_proxy(self): + """""" + result = None, None + if self.has_section(SECTION_ADVANCED): + if self.getboolean(SECTION_ADVANCED, OPTION_ENABLE_PROXY): + result = self.get(SECTION_ADVANCED, OPTION_PROXY_URL), self.getint(SECTION_ADVANCED, OPTION_PROXY_PORT) + return result + + def save(self, comment=True): + """""" + f = open(cons.CONFIG_PATH + CONF, "w") + if comment: + f.write(COMMENT + "\n\n") + self.write(f) + f.close() + +if __name__ == "__main__": + c = Config() + print c.configured diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/core/cons.py /tmp/DgSymrsclJ/tucan-0.3.9/core/cons.py --- tucan-0.3.8/core/cons.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/core/cons.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,110 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import sys +import os +import locale +import logging + +#project constants +TUCAN_NAME = "Tucan Manager" +TUCAN_VERSION = "0.3.9 alpha" +WEBPAGE = "http://www.tucaneando.com" +DOC = "http://doc.tucaneando.com" + +#OS constants +OS_UNIX = False +OS_WINDOWS = False +OS_OSX = False +if sys.platform.startswith("win"): + OS_WINDOWS = True +elif "darwin" in sys.platform: + OS_OSX = True +else: + OS_UNIX = True + +#user agent +USER_AGENT = {"User-Agent":"Mozilla/5.0 (X11; U; Linux i686) Gecko/20081114 Firefox/3.0.4"} + +#status constants +STATUS_PEND = "pending" +STATUS_ACTIVE = "active" +STATUS_WAIT = "waiting" +STATUS_STOP = "stoped" +STATUS_CORRECT = "correct" +STATUS_ERROR = "error" + +#message constants +SEVERITY_INFO = "info" +SEVERITY_WARNING = "warning" +SEVERITY_ERROR = "error" + +#size unit constants +UNIT_KB = "KB" +UNIT_MB = "MB" +UNIT_GB = "GB" + +#speed unit constant +UNIT_SPEED = "KB/s" + +#time constants +MINUTE = 60 +HOUR = 3600 + +#service type constans +TYPE_ANONYMOUS = "Anonymous" +TYPE_USER = "User" +TYPE_PREMIUM = "Premium" +TYPE_UNSUPPORTED = "unsupported" + +#path constants +if OS_WINDOWS: + PATH = os.path.abspath(os.path.dirname(sys.argv[0])) + DEFAULT_PATH = os.path.join(os.path.expanduser("~"), "").decode(locale.getdefaultlocale()[1]) + if PATH not in sys.path: + sys.path.insert(0, PATH) +else: + if OS_OSX: + PATH = os.path.abspath(os.path.dirname(sys.argv[0])) + else: + PATH = os.path.join(sys.path[0], "") + DEFAULT_PATH = os.path.join(os.path.expanduser("~"), "") +CONFIG_PATH = os.path.join(DEFAULT_PATH, ".tucan" ,"") + +#log constants +LOG_FILE = os.path.join(CONFIG_PATH, "tucan.log") +LOG_FORMAT = "[%(asctime)s] %(name)s %(levelname)s: %(message)s" + +#plugin constants +PLUGIN_PATH = os.path.join(CONFIG_PATH, "plugins") +DEFAULT_PLUGINS = os.path.join(PATH, "default_plugins", "") + +#session constants +SESSION_FILE = os.path.join(CONFIG_PATH, "last.session") + +#localization constants +NAME_LOCALES = "tucan" +PATH_LOCALES = os.path.join(PATH, "i18n") + +#events constants +EVENT_ALL_COMPLETE = "all-complete" +EVENT_LIMIT_ON = "limit-exceeded-on" +EVENT_LIMIT_OFF = "limit-exceeded-off" +EVENT_LIMIT_CANCEL = "limit-exceeded-cancel" diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/core/core.py /tmp/DgSymrsclJ/tucan-0.3.9/core/core.py --- tucan-0.3.8/core/core.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/core/core.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,56 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import sys +import __builtin__ +import logging +logger = logging.getLogger(__name__) + +from events import Events +from service_manager import ServiceManager +from download_manager import DownloadManager + +import misc +import cons + +class Core(ServiceManager): + """""" + def __init__(self, configuration): + """""" + misc.main_info(logger) + + if not configuration.configured: + logger.warning("No configuration found!") + + #events system + __builtin__.events = Events() + + ServiceManager.__init__(self, configuration) + self.download_manager = DownloadManager(self.get_download_plugin, self.services) + + def stop_all(self): + """""" + for service in self.services: + for plugin in [service.anonymous_download_plugin, service.user_download_plugin, + service.premium_download_plugin, service.anonymous_upload_plugins, + service.user_upload_plugins, service.premium_upload_plugins]: + if plugin: + plugin.stop_all() + self.download_manager.quit() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/core/downloader.py /tmp/DgSymrsclJ/tucan-0.3.9/core/downloader.py --- tucan-0.3.8/core/downloader.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/core/downloader.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,131 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import os +import urllib2 +import threading +import time +import logging +logger = logging.getLogger(__name__) + +from url_open import URLOpen + +import cons + +BASE_SIZE = 4 +BUFFER_SIZE = BASE_SIZE * 1024 + +class Downloader(threading.Thread): + """""" + def __init__(self, path, url, file_name, wait, cookie, post_wait): + """""" + threading.Thread.__init__(self) + + self.max_speed = 0 + + self.post_wait = post_wait + self.status = cons.STATUS_WAIT + self.path = path + self.url = url + self.file = file_name + self.wait = wait + self.stop_flag = False + self.start_time = time.time() + self.time_remaining = 0 + self.total_size = 1 + self.actual_size = 0 + self.speed = 0 + self.tmp_time = 0 + self.tmp_size = 0 + #build opener + self.opener = URLOpen(cookie) + + def run(self): + """""" + name = os.path.join(self.path, self.file) + if self.wait: + while ((self.wait > 0) and not self.stop_flag): + time.sleep(1) + self.wait -= 1 + self.time_remaining = self.wait + if not self.stop_flag: + try: + if self.post_wait: + handle = self.post_wait(self.url) + else: + handle = self.opener.open(self.url) + if handle: + self.status = cons.STATUS_ACTIVE + logger.debug("%s :%s" % (self.file, handle.info().getheader("Content-Type"))) + self.total_size = int(handle.info().getheader("Content-Length")) + if not os.path.exists(self.path): + os.makedirs(self.path) + f = open("%s.part" % name, "wb") + self.start_time = time.time() + data = "None" + while ((len(data) > 0) and not self.stop_flag): + tmp_size = 0 + if self.max_speed > 0: + max_size = self.max_speed/BASE_SIZE + else: + max_size = 0 + start_seconds = time.time() + while (time.time() - start_seconds) < 1: + if max_size == 0 or tmp_size < max_size: + data = handle.read(BUFFER_SIZE) + f.write(data) + self.actual_size += len(data) + tmp_size += 1 + else: + time.sleep(0.1) + self.speed = BASE_SIZE * tmp_size + self.time_remaining = time.time() - self.start_time + f.flush() + os.fsync(f.fileno()) + f.close() + if self.stop_flag: + os.remove("%s.part" % name) + self.status = cons.STATUS_PEND + else: + self.stop_flag = True + if self.actual_size == self.total_size: + os.rename("%s.part" % name, name) + self.status = cons.STATUS_CORRECT + else: + self.status = cons.STATUS_ERROR + else: + self.stop_flag = True + self.status = cons.STATUS_PEND + except Exception, e: + self.stop_flag = True + logger.exception("%s: %s" % (self.file, e)) + if os.path.exists("%s.part" % name): + os.remove("%s.part" % name) + self.status = cons.STATUS_ERROR + + def get_speed(self): + """return int speed KB/s""" + elapsed_time = time.time() - self.tmp_time + size = self.actual_size - self.tmp_size + if size > 0: + self.speed = int(float(size/1024)/float(elapsed_time)) + self.tmp_time = time.time() + self.tmp_size = self.actual_size + return self.speed diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/core/download_manager.py /tmp/DgSymrsclJ/tucan-0.3.9/core/download_manager.py --- tucan-0.3.8/core/download_manager.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/core/download_manager.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,253 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import time +import threading + +import logging +logger = logging.getLogger(__name__) + +import cons + +class Link: + """""" + def __init__(self, url, plugin, type, service): + """""" + self.active = False + self.url = url + self.plugin = plugin + self.plugin_type = type + self.service = service + +class DownloadItem: + """""" + def __init__(self, path, name, links, total_size, size_unit): + """""" + self.path = path + self.name = name + self.status = cons.STATUS_PEND + self.links = [] + for url, plugin, type, service in links: + self.links.append(Link(url, plugin, type, service)) + self.progress = 0 + self.total_size = total_size + self.total_size_unit = size_unit + self.actual_size = 0 + self.actual_size_unit = cons.UNIT_KB + self.speed = 0 + self.prev_speed = 0 + self.time = 0 + + def update(self, status=cons.STATUS_STOP, progress=0, actual_size=0, size_unit=cons.UNIT_KB, speed=0, prev_speed=0, time=0): + """""" + self.status = status + self.progress = progress + self.actual_size = actual_size + self.actual_size_unit = size_unit + self.speed = speed + self.prev_speed = prev_speed + self.time = time + +class DownloadManager: + """""" + def __init__(self, get_plugin, services): + """""" + self.services = services + self.get_plugin = get_plugin + self.limits = [] + self.pending_downloads = [] + self.active_downloads = [] + self.complete_downloads = [] + self.timer = None + self.scheduling = False + + def delete_link(self, name, link): + """""" + for download in self.pending_downloads: + if download.name == name: + for url in download.links: + if link == url.url: + del download.links[download.links.index(url)] + return True + + def get_files(self): + """""" + result = [] + for downloads in [self.pending_downloads, self.active_downloads, self.complete_downloads]: + for download in downloads: + result.append(download) + self.update() + return result + + def clear(self, files): + """""" + result = False + complete = [tmp.name for tmp in self.complete_downloads] + pending = [tmp.name for tmp in self.pending_downloads] + for name in files: + if name in complete: + logger.info("Cleared %s" % name) + del self.complete_downloads[complete.index(name)] + del complete[complete.index(name)] + result = True + elif name in pending: + logger.info("Deleted %s" % name) + del self.pending_downloads[pending.index(name)] + del pending[pending.index(name)] + result = True + return result + + def add(self, path, name, links, total_size, size_unit): + """""" + if name not in [tmp.name for tmp in (self.active_downloads + self.pending_downloads)]: + self.pending_downloads.append(DownloadItem(path, name, links, total_size, size_unit)) + threading.Timer(1, self.scheduler).start() + return True + + def start(self, name): + """""" + for download in self.pending_downloads: + if name == download.name: + download.status = cons.STATUS_WAIT + for link in download.links: + link.plugin, link.type = self.get_plugin(link.service) + if link.plugin.add(download.path, link.url, download.name): + try: + self.pending_downloads.remove(download) + except: + pass + else: + self.active_downloads.append(download) + link.active = True + return True + else: + link.active = False + if download.status != cons.STATUS_ERROR: + download.status = cons.STATUS_PEND + + def stop(self, name): + """""" + for download in self.pending_downloads: + if name == download.name: + download.status = cons.STATUS_STOP + for download in self.active_downloads: + if name == download.name: + for link in download.links: + if link.active: + if link.plugin.stop(download.name): + if "return_slot" in dir(link.plugin): + link.plugin.return_slot() + link.active = False + self.pending_downloads.append(download) + self.active_downloads.remove(download) + download.update() + return True + + def update(self): + """""" + new_speed = 0 + permanent = True + speeds = [download.speed for download in self.active_downloads if download.status == cons.STATUS_ACTIVE] + current_active = len(speeds) + #print max_downloads, max_download_speed + #print current_active, speeds + remain_speed = max_download_speed + for speed in speeds: + remain_speed -= speed + #print remain_speed + if current_active > 0: + if remain_speed < 0: + new_speed = max_download_speed/current_active + permanent = False + for download in self.active_downloads: + plugin = None + for link in download.links: + if link.active: + plugin = link.plugin + break + if plugin: + if permanent: + if download.speed == 0: + if remain_speed <= 0: + new_speed = 20 + else: + new_speed = remain_speed + elif download.prev_speed >= download.speed: + new_speed = download.prev_speed + if remain_speed - 2 > 0: + new_speed += 2 + remain_speed -= 2 + else: + new_speed += remain_speed + remain_speed = 0 + else: + new_speed = download.speed + status, progress, actual_size, unit, speed, time = plugin.get_status(download.name, new_speed) + #print download.name, status, progress, actual_size, unit, speed, new_speed, time + if status: + download.update(status, progress, actual_size, unit, speed, new_speed, time) + if status in [cons.STATUS_PEND, cons.STATUS_ERROR]: + if status == cons.STATUS_ERROR: + logger.error("%s %s %s %s %s %s %s" % (download.name, status, progress, actual_size, unit, speed, time)) + if "return_slot" in dir(link.plugin): + plugin.return_slot() + link.active = False + self.pending_downloads.append(download) + self.active_downloads.remove(download) + self.scheduler() + elif status == cons.STATUS_CORRECT: + logger.info("%s %s %s %s %s %s %s" % (download.name, status, progress, actual_size, unit, speed, time)) + if "return_slot" in dir(link.plugin): + plugin.return_slot() + download.progress = 100 + self.complete_downloads.append(download) + self.active_downloads.remove(download) + + def scheduler(self): + """""" + if not self.scheduling: + self.scheduling = True + if len(self.pending_downloads + self.active_downloads) > 0: + logger.debug("scheduling") + try: + for download in self.pending_downloads: + if len(self.active_downloads) < max_downloads: + if download.status not in [cons.STATUS_STOP]: + if self.start(download.name): + logger.info("Started: %s" % download.name) + logger.debug("Active: %s" % [tmp.name for tmp in self.active_downloads]) + logger.debug("Pending: %s" % [tmp.name for tmp in self.pending_downloads]) + logger.debug("Complete: %s" % [tmp.name for tmp in self.complete_downloads]) + break + except Exception, e: + logger.exception(e) + if self.timer: + self.timer.cancel() + self.timer = threading.Timer(5, self.scheduler) + self.timer.start() + else: + events.trigger_all_complete() + self.scheduling = False + + def quit(self): + """""" + if self.timer: + self.scheduling = True + self.timer.cancel() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/core/download_plugin.py /tmp/DgSymrsclJ/tucan-0.3.9/core/download_plugin.py --- tucan-0.3.8/core/download_plugin.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/core/download_plugin.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,92 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import time + +from downloader import Downloader + +import cons + +class DownloadPlugin(object): + """""" + def __init__(self): + """""" + self.active_downloads = {} + + def start(self, path, url, file_name, wait=None, cookie=None, post_wait=None): + """""" + if file_name not in self.active_downloads: + th = Downloader(path, url, file_name, wait, cookie, post_wait) + th.start() + self.active_downloads[file_name] = th + return True + + def stop(self, file_name): + """""" + if file_name in self.active_downloads: + while self.active_downloads[file_name].isAlive(): + self.active_downloads[file_name].stop_flag = True + time.sleep(0.1) + del self.active_downloads[file_name] + return True + + def stop_all(self): + """""" + for th in self.active_downloads.values(): + while th.isAlive(): + th.stop_flag = True + + def get_status(self, file_name, speed=0): + """return (status, progress, actual_size, unit, speed, time)""" + result = cons.STATUS_ERROR, 0, 0, None, 0, 0 + th = None + if file_name in self.active_downloads: + th = self.active_downloads[file_name] + if self.active_downloads[file_name].stop_flag: + del self.active_downloads[file_name] + if th: + actual_size, unit = self.get_size(th.actual_size) + if th.status == cons.STATUS_ACTIVE: + progress = int((float(th.actual_size)/float(th.total_size))*100) + th.max_speed = speed + speed = th.speed + if speed > 0: + time = int(float((th.total_size - th.actual_size)/1024)/float(speed)) + else: + time = 0 + else: + if not th.status == cons.STATUS_CORRECT: + actual_size = 0 + progress = 0 + speed = 0 + time = int(th.time_remaining) + result = th.status, progress, actual_size, unit, speed, time + return result + + def get_size(self, num): + """""" + result = 0, cons.UNIT_KB + tmp = int(num/1024) + if tmp > 0: + result = tmp, cons.UNIT_KB + tmp = int(tmp/1024) + if tmp > 0: + result = tmp, cons.UNIT_MB + return result diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/core/events.py /tmp/DgSymrsclJ/tucan-0.3.9/core/events.py --- tucan-0.3.8/core/events.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/core/events.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,77 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import logging +logger = logging.getLogger(__name__) + +import cons + +class Events: + """""" + def __init__(self): + """""" + self.registered = {} + + def connect(self, event, callback, *kargs): + """""" + if event in self.registered: + result = len(self.registered[event]) + self.registered[event].append((callback, kargs)) + return result + else: + self.registered[event] = [(callback, kargs)] + return 0 + + def disconnect(self, event, id): + """""" + try: + if event in self.registered: + del self.registered[event][id] + except Exception, e: + logger.Error("Could not disconnect: %s %i" % (event, id)) + + def trigger(self, event, *kargs): + """""" + if event in self.registered: + for callback, kargs2 in self.registered[event]: + try: + callback(*(kargs+kargs2)) + except Exception, e: + logger.exception(e) + + def trigger_limit_off(self, module): + """""" + logger.debug("triggered: %s from %s" % (cons.EVENT_LIMIT_OFF, module)) + self.trigger(cons.EVENT_LIMIT_OFF, module) + + def trigger_limit_on(self, module): + """""" + logger.debug("triggered: %s from %s" % (cons.EVENT_LIMIT_ON, module)) + self.trigger(cons.EVENT_LIMIT_ON, module) + + def trigger_limit_cancel(self, module): + """""" + logger.debug("triggered: %s from %s" % (cons.EVENT_LIMIT_CANCEL, module)) + self.trigger(cons.EVENT_LIMIT_CANCEL, module) + + def trigger_all_complete(self): + """""" + logger.debug("triggered: %s" % cons.EVENT_ALL_COMPLETE) + self.trigger(cons.EVENT_ALL_COMPLETE) diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/core/log_stream.py /tmp/DgSymrsclJ/tucan-0.3.9/core/log_stream.py --- tucan-0.3.8/core/log_stream.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/core/log_stream.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,62 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +class LogStream: + """""" + def __init__(self): + """""" + self.new_buffer = [] + self.old_buffer = [] + + def write(self, message): + """""" + self.new_buffer.append(str(message)) + + def flush(self): + """""" + pass + + def read(self): + """""" + tmp = self.new_buffer + self.new_buffer = [] + self.old_buffer += tmp + return "\n".join(self.old_buffer) + + def readlines(self): + """""" + if len(self.new_buffer) > 0: + tmp = self.new_buffer + self.new_buffer = [] + self.old_buffer += tmp + return tmp + + def readnlines(self, length=0): + """""" + if len(self.new_buffer) > 0: + if length > 0: + cont = 1 + for line in self.new_buffer: + tmp = self.new_buffer[0] + del self.new_buffer[0] + self.old_buffer.append(tmp) + if cont >= length: + break + return self.old_buffer[-length:] diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/core/misc.py /tmp/DgSymrsclJ/tucan-0.3.9/core/misc.py --- tucan-0.3.8/core/misc.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/core/misc.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,54 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import sys +import urllib +import logging +logger = logging.getLogger(__name__) + +import url_open +import cons + +REPORT_URL = "http://crak.appspot.com/add" + +def main_info(log=logger): + """""" + log.info("%s %s" % (cons.TUCAN_NAME, cons.TUCAN_VERSION)) + log.debug("OS: %s" % sys.platform) + log.debug("Main path: %s" % cons.PATH) + log.debug("Configuration path: %s" % cons.CONFIG_PATH) + +def report_log(email="", comment=""): + """""" + try: + f = open(cons.LOG_FILE, "r") + log = f.read() + f.close() + except Exception, e: + logger.exception("%s" % e) + else: + form = urllib.urlencode([("uuid", configuration.get_uuid()), ("email", email), ("comment", urllib.quote(comment)), ("log", urllib.quote(log))]) + try: + id = url_open.URLOpen().open(REPORT_URL, form).read().strip() + logger.info("REPORT ID: %s" % id) + except Exception, e: + logger.exception("Could not report: %s" % e) + else: + return id diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/core/service_config.py /tmp/DgSymrsclJ/tucan-0.3.9/core/service_config.py --- tucan-0.3.8/core/service_config.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/core/service_config.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,165 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import os +import pickle +import base64 +import logging +logger = logging.getLogger(__name__) + +from ConfigParser import SafeConfigParser + +import cons + +SECTION_MAIN = "main" + +SECTION_ANONYMOUS_DOWNLOAD = "anonymous_download" +SECTION_USER_DOWNLOAD = "user_download" +SECTION_PREMIUM_DOWNLOAD = "premium_download" + +SECTION_ANONYMOUS_UPLOAD = "anonymous_upload" +SECTION_USER_UPLOAD = "user_upload" +SECTION_PREMIUM_UPLOAD = "premium_upload" + +OPTION_UPDATE = "update" +OPTION_NAME = "name" +OPTION_ICON = "icon" +OPTION_ENABLED = "enabled" + +OPTION_PREMIUM_COOKIE = "premium_cookie" +OPTION_USER_COOKIE = "user_cookie" + +OPTION_DOWNLOADS = "downloads" +OPTION_UPLOADS = "uploads" + +OPTION_PATH = "path" +OPTION_AUTHOR = "author" +OPTION_VERSION = "version" +OPTION_SLOTS = "slots" +OPTION_CAPTCHA = "captcha" +OPTION_ACCOUNTS = "accounts" + +CONF = "service.conf" + +class ServiceConfig(SafeConfigParser): + """""" + def __init__(self, path, fd=None): + """""" + SafeConfigParser.__init__(self) + self.path = path + if fd: + self.readfp(fd) + elif os.path.exists(os.path.join(self.path, CONF)): + self.read(os.path.join(self.path, CONF)) + + def check_config(self): + """""" + if self.has_section(SECTION_MAIN): + return True + + def enable(self, enabled): + """""" + self.set(SECTION_MAIN, OPTION_ENABLED, str(enabled)) + self.save() + + def get_name(self): + """""" + if self.has_option(SECTION_MAIN, OPTION_NAME): + return self.get(SECTION_MAIN, OPTION_NAME) + + def get_update(self): + """""" + if self.has_option(SECTION_MAIN, OPTION_UPDATE): + return self.getint(SECTION_MAIN, OPTION_UPDATE) + else: + return 0 + + def get_icon(self): + """""" + if self.has_option(SECTION_MAIN, OPTION_ICON): + if self.get(SECTION_MAIN, OPTION_ICON) != "None": + return self.path + self.get(SECTION_MAIN, OPTION_ICON) + + def premium_cookie(self): + """""" + get_cookie = None + if self.has_option(SECTION_MAIN, OPTION_PREMIUM_COOKIE): + get_cookie = self.get(SECTION_MAIN, OPTION_PREMIUM_COOKIE) + return OPTION_PREMIUM_COOKIE, get_cookie + + def user_cookie(self): + """""" + get_cookie = None + if self.has_option(SECTION_MAIN, OPTION_USER_COOKIE): + get_cookie = self.get(SECTION_MAIN, OPTION_USER_COOKIE) + return OPTION_USER_COOKIE, get_cookie + + def get_plugins(self, sections): + """""" + result = [] + for section, section_type in sections: + if ((self.has_section(section)) and (len(self.items(section)) > 0)): + result.append((section, self.get(section, OPTION_NAME), section_type)) + return result + + def get_download_plugins(self): + """""" + result = [] + if self.has_option(SECTION_MAIN, OPTION_DOWNLOADS): + if self.getboolean(SECTION_MAIN, OPTION_DOWNLOADS): + result = self.get_plugins([(SECTION_ANONYMOUS_DOWNLOAD, cons.TYPE_ANONYMOUS), (SECTION_USER_DOWNLOAD, cons.TYPE_USER), (SECTION_PREMIUM_DOWNLOAD, cons.TYPE_PREMIUM)]) + return result + + def get_upload_plugins(self): + """""" + result = [] + if self.has_option(SECTION_MAIN, OPTION_UPLOADS): + if self.getboolean(SECTION_MAIN, OPTION_UPLOADS): + result = self.get_plugins([(SECTION_ANONYMOUS_UPLOAD, cons.TYPE_ANONYMOUS), (SECTION_USER_UPLOAD, cons.TYPE_USER), (SECTION_PREMIUM_UPLOAD, cons.TYPE_PREMIUM)]) + return result + + def get_accounts(self, section): + """""" + result = {} + if self.has_section(section): + if os.path.exists(self.path + self.get(section, OPTION_ACCOUNTS)): + try: + f = open(self.path + self.get(section, OPTION_ACCOUNTS), "rb") + result = pickle.loads(base64.b64decode((f.read()))) + f.close() + except EOFError, e: + logger.error("Unable to load account: %s" % e) + return result + + def set_accounts(self, section, accounts): + """""" + if self.has_section(section): + f = open(self.path + self.get(section, OPTION_ACCOUNTS), "wb") + f.write(base64.b64encode(pickle.dumps(accounts))) + f.close() + + def save(self): + """""" + f = open(self.path + CONF, "w") + self.write(f) + f.close() + +if __name__ == "__main__": + c = ServiceConfig("/home/crak/.tucan/plugins/megaupload/") diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/core/service_manager.py /tmp/DgSymrsclJ/tucan-0.3.9/core/service_manager.py --- tucan-0.3.8/core/service_manager.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/core/service_manager.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,187 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import re +import sys +import logging +logger = logging.getLogger(__name__) + +from config import SECTION_MAIN, OPTION_MAX_DOWNLOADS, OPTION_MAX_DOWNLOAD_SPEED + +import cons + +class Service: + """""" + def __init__(self, name, icon): + """""" + self.icon_path = icon + self.name = name + self.anonymous_download_plugin = None + self.user_download_plugin = None + self.premium_download_plugin = None + self.anonymous_upload_plugins = None + self.user_upload_plugins = None + self.premium_upload_plugins = None + +class ServiceManager: + """""" + def __init__(self, configuration): + """""" + self.services = [] + if cons.PLUGIN_PATH not in sys.path: + sys.path.append(cons.PLUGIN_PATH) + for package, icon, service, enabled, config in configuration.get_services(): + s = Service(service, icon) + if enabled: + #download plugins + for plugin_module, plugin_name, plugin_type in config.get_download_plugins(): + logger.info("Loading: %s.%s" % (package, plugin_module)) + module = __import__(package + "." + plugin_module, None, None, ['']) + if plugin_type == cons.TYPE_ANONYMOUS: + s.anonymous_download_plugin = eval("module" + "." + plugin_name + "()") + elif plugin_type == cons.TYPE_USER: + s.user_download_plugin = eval("module" + "." + plugin_name + "()") + elif plugin_type == cons.TYPE_PREMIUM: + s.premium_download_plugin = eval("module" + "." + plugin_name + "(config)") + #upload plugins + for plugin_module, plugin_name, plugin_type in config.get_upload_plugins(): + logger.info("Loading: %s.%s" % (package, plugin_module)) + module = __import__(package + "." + plugin_module, None, None, ['']) + if plugin_type == cons.TYPE_ANONYMOUS: + s.anonymous_upload_plugin = eval("module" + "." + plugin_name + "()") + elif plugin_type == cons.TYPE_USER: + s.user_upload_plugin = eval("module" + "." + plugin_name + "()") + elif plugin_type == cons.TYPE_PREMIUM: + s.premium_upload_plugin = eval("module" + "." + plugin_name + "(config)") + self.services.append(s) + + def get_download_plugin(self, service_name): + """""" + for service in self.services: + if service.name == service_name: + if ((service.premium_download_plugin) and (service.premium_download_plugin.active)): + return service.premium_download_plugin, cons.TYPE_PREMIUM + else: + return service.anonymous_download_plugin, cons.TYPE_ANONYMOUS + + def get_upload_plugin(self, service_name): + """""" + for service in self.services: + if service.name == service_name: + return service.anonymous_upload_plugin + + def get_check_links(self, service_name): + """""" + for service in self.services: + if service.name == service_name: + if ((service.premium_download_plugin) and (service.premium_download_plugin.active)): + return service.premium_download_plugin.check_links, cons.TYPE_PREMIUM + else: + return service.anonymous_download_plugin.check_links, cons.TYPE_ANONYMOUS + + def get_check_files(self, service_name): + """""" + for service in self.services: + if service.name == service_name: + return service.check_files.check + + def filter_service(self, links): + """""" + services = {cons.TYPE_UNSUPPORTED: []} + for link in links: + found = False + if "http://" in link: + tmp = link.split("http://").pop() + if "<" in tmp: + tmp = tmp.split("<")[0] + elif " " in tmp: + tmp = tmp.split(" ")[0] + elif "[" in tmp: + tmp = tmp.split("[")[0] + elif "'" in tmp: + tmp = tmp.split("'")[0] + link = "http://" + tmp + for service in self.services: + if link.find(service.name) > 0: + found = True + if service.name in services: + services[service.name].append(link) + else: + services[service.name] = [link] + if not found: + services[cons.TYPE_UNSUPPORTED].append(link) + return services + + def create_packages(self, dict): + """""" + packages = [] + files = [] + for service, links in dict.items(): + for link in links: + found = False + for tmp_link in files: + if link[1] == tmp_link[1]: + found = True + if service not in tmp_link[2]: + tmp_link[2].append(service) + tmp_link[0].append(link[0]) + tmp_link[5].append(link[4]) + if not found: + files.append(([link[0]], link[1], [service], link[2], link[3], [link[4]])) + while len(files) > 0: + tmp_name = [] + first = files[0] + others = files[1:] + for link in others: + chars = re.split("[0-9]+", link[1]) + nums = re.split("[^0-9]+", link[1]) + tmp = "" + for i in chars: + if tmp+i == first[1][0:len(tmp+i)]: + tmp += i + for j in nums: + if tmp+j == first[1][0:len(tmp+j)]: + tmp += j + tmp_name.append(tmp) + final_name = "" + for name in tmp_name: + if len(name) > len(final_name): + final_name = name + if len(final_name) > 0: + packages.append((final_name, [first])) + del files[files.index(first)] + tmp_list = [] + for link in files: + if final_name in link[1]: + tmp_list.append(link) + for package_name, package_files in packages: + if package_name == final_name: + package_files += tmp_list + for i in tmp_list: + del files[files.index(i)] + else: + alone_name = first[1] + if "." in alone_name: + alone_name = alone_name.split(".") + alone_name.pop() + alone_name = ".".join(alone_name) + packages.append((alone_name, [first])) + del files[files.index(first)] + return packages diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/core/service_update.py /tmp/DgSymrsclJ/tucan-0.3.9/core/service_update.py --- tucan-0.3.8/core/service_update.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/core/service_update.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,125 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import os.path +import tempfile +import tarfile +import random +import urllib2 +import logging +logger = logging.getLogger(__name__) + +from ConfigParser import SafeConfigParser + +from url_open import URLOpen +from service_config import ServiceConfig + +import config +import cons + +SECTION_MAIN = "main" +SECTION_UPDATES = "updates" +OPTION_VERSION = "version" + +FORJA = "https://forja.rediris.es/svn/cusl3-tucan/branches/update_manager/" +BTD = "http://build-tucan-doc.googlecode.com/svn/branches/update_manager/" + +SERVERS = [BTD, FORJA] +UPDATE_FILE = "updates.conf" +CONF_FILE = "service.conf" +EXTENSION = ".tar.gz" + +class RemoteInfo(SafeConfigParser): + """""" + def __init__(self, server, fd): + """""" + SafeConfigParser.__init__(self) + self.readfp(fd) + self.server = server + self.version = self.get(SECTION_MAIN, OPTION_VERSION) + self.services = self.items(SECTION_UPDATES) + +class ServiceUpdate: + """""""" + def __init__(self, config, info=None): + """urllib2 does not support proxy and https""" + self.config = config + self.remote_version = None + self.updates = None + self.remote_info = info + + def get_updates(self): + """""" + self.updates = {} + tmp = SERVERS + random.shuffle(tmp) + if not self.remote_info: + for server in tmp: + try: + logger.debug("Update Server: %s" % server) + fd = URLOpen().open("%s%s" % (server, UPDATE_FILE)) + except Exception, e: + logger.exception(e) + else: + self.remote_info = RemoteInfo(server, fd) + break + if self.remote_info: + self.remote_version = self.remote_info.version + self.local_services = self.config.get_services() + for remote_service, remote_version in self.remote_info.services: + archive = "%s%s" % (self.remote_info.server, remote_service.split(".")[0] + EXTENSION) + #get local version + found = False + for local_service in self.local_services: + if local_service[2] == remote_service: + found = True + local_version = local_service[4].get_update() + if int(remote_version) > local_version: + self.updates[local_service[2]] = local_service[0], archive, local_service[1] + if not found: + self.updates[remote_service] = remote_service.split(".")[0], archive, None + if len(self.updates) > 0: + return True + + def install_service(self, service_name, service_dir, archive): + """""" + logger.warning("Updating: %s" % service_name) + try: + fd = tempfile.TemporaryFile() + fd.write(URLOpen().open(archive).read()) + fd.seek(0) + tar_package = tarfile.open("", 'r:gz', fd) + tar_package.extractall(cons.PLUGIN_PATH) + tar_package.close() + fd.close() + if not self.config.has_option(config.SECTION_SERVICES, service_name): + self.config.set(config.SECTION_SERVICES, service_name, os.path.join(cons.PLUGIN_PATH, service_dir, "")) + except Exception, e: + logger.exception(e) + else: + return True + +if __name__ == "__main__": + from config import Config + from url_open import set_proxy + set_proxy(None) + s = ServiceUpdate(Config()) + s.get_updates() + print s.updates diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/core/sessions.py /tmp/DgSymrsclJ/tucan-0.3.9/core/sessions.py --- tucan-0.3.8/core/sessions.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/core/sessions.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,79 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import os +import pickle +import logging +logger = logging.getLogger(__name__) + +from ConfigParser import SafeConfigParser + +import cons + +LAST_SESSION = "last.session" + +SECTION_DOWNLOADS = "downloads" +OPTION_PACKAGES = "packages" +OPTION_PACKAGES_INFO = "packages_info" + +PACKAGES = [('D.S03E01.PREAiR.DVDSCR.NOTYOU.cHoPPaHoLiK.part', [(['http://www.megaupload.com/?d=GW1WB3IV', 'http://rapidshare.com/files/143483416/D.S03E01.PREAiR.DVDSCR.NOTYOU.cHoPPaHoLiK.part1.rar'], 'D.S03E01.PREAiR.DVDSCR.NOTYOU.cHoPPaHoLiK.part1.rar', ['megaupload.com', 'rapidshare.com'], 200, 'MB', ['AnonymousMegaupload', 'AnonymousRapidshare']), (['http://www.megaupload.com/?d=TITR6R0P', 'http://rapidshare.com/files/143483557/D.S03E01.PREAiR.DVDSCR.NOTYOU.cHoPPaHoLiK.part2.rar'], 'D.S03E01.PREAiR.DVDSCR.NOTYOU.cHoPPaHoLiK.part2.rar', ['megaupload.com', 'rapidshare.com'], 200, 'MB', ['AnonymousMegaupload', 'AnonymousRapidshare']), (['http://www.megaupload.com/?d=DCJX0RKQ', 'http://rapidshare.com/files/143483236/D.S03E01.PREAiR.DVDSCR.NOTYOU.cHoPPaHoLiK.part3.rar'], 'D.S03E01.PREAiR.DVDSCR.NOTYOU.cHoPPaHoLiK.part3.rar', ['megaupload.com', 'rapidshare.com'], 135, 'MB', ['AnonymousMegaupload', 'AnonymousRapidshare'])]), ('Californication.2x01.samuelro.part', [(['http://rapidshare.com/files/149540090/Californication.2x01.samuelro.part1.rar'], 'Californication.2x01.samuelro.part1.rar', ['rapidshare.com'], 200, 'MB', ['AnonymousRapidshare']), (['http://rapidshare.com/files/149537924/Californication.2x01.samuelro.part2.rar'], 'Californication.2x01.samuelro.part2.rar', ['rapidshare.com'], 41, 'MB', ['AnonymousRapidshare'])]), ('Californication.2x02.samuelro.part', [(['http://rapidshare.com/files/151602033/Californication.2x02.samuelro.part1.rar'], 'Californication.2x02.samuelro.part1.rar', ['rapidshare.com'], 195, 'MB', ['AnonymousRapidshare']), (['http://rapidshare.com/files/151408776/Californication.2x02.samuelro.part2.rar'], 'Californication.2x02.samuelro.part2.rar', ['rapidshare.com'], 45, 'MB', ['AnonymousRapidshare'])])] + +PACKAGES_INFO = [('/home/crak/', 'D.S03E01.PREAiR.DVDSCR.NOTYOU.cHoPPaHoLiK.part', None), ('/home/crak/downloads/', 'Californication.2x01.samuelro.part', 'mierda'), ('/home/crak/downloads/', 'Californication.2x02.samuelro.part', 'cojones')] + +class Sessions(SafeConfigParser): + """""" + def load_session(self, path): + """""" + result = None, None + if os.path.exists(path): + self.read(path) + if self.has_section(SECTION_DOWNLOADS): + if ((self.has_option(SECTION_DOWNLOADS, OPTION_PACKAGES)) and (self.has_option(SECTION_DOWNLOADS, OPTION_PACKAGES_INFO))): + result = pickle.loads(self.get(SECTION_DOWNLOADS, OPTION_PACKAGES)), pickle.loads(self.get(SECTION_DOWNLOADS, OPTION_PACKAGES_INFO)) + return result + + def save_session(self, path, session_packages, session_info): + """""" + if not self.has_section(SECTION_DOWNLOADS): + self.add_section(SECTION_DOWNLOADS) + self.set(SECTION_DOWNLOADS, OPTION_PACKAGES, pickle.dumps(session_packages)) + self.set(SECTION_DOWNLOADS, OPTION_PACKAGES_INFO, pickle.dumps(session_info)) + self.save(path) + + def save(self, path): + """""" + try: + f = open("%s.tmp" % path, "w") + self.write(f) + f.flush() + os.fsync(f.fileno()) + f.close() + if os.path.exists(path): + os.remove(path) + os.rename("%s.tmp" % path, path) + except Exception, e: + if os.path.exists("%s.tmp" % path): + os.remove("%s.tmp" % path) + logger.exception(e) + +if __name__ == "__main__": + s = Sessions() + s.save_default_session(PACKAGES, PACKAGES_INFO) + print s.load_default_session() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/core/slots.py /tmp/DgSymrsclJ/tucan-0.3.9/core/slots.py --- tucan-0.3.8/core/slots.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/core/slots.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,65 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import time +import logging +logger = logging.getLogger(__name__) + +import cons + +class Slots: + """""" + def __init__(self, slots=1, wait=300): + """""" + self.time_limit = wait + self.limit = False + self.end_wait = 0 + self.max = slots + self.slots = slots + events.connect(cons.EVENT_LIMIT_CANCEL, self.cancel_limit) + + def get_slot(self): + """""" + if self.slots > 0: + if time.time() > self.end_wait: + events.trigger_limit_off(self.__module__) + self.limit = False + self.slots -= 1 + return True + + def add_wait(self): + """""" + logger.warning("Wait %i seconds." % self.time_limit) + self.limit = True + events.trigger_limit_on(self.__module__) + self.end_wait = time.time() + self.time_limit + + def return_slot(self): + """""" + if self.slots < self.max: + self.slots += 1 + return True + + def cancel_limit(self, module): + """""" + if module == self.__module__: + self.limit = False + self.end_wait = 0 + logger.info("Limit canceled manually: %s" % self.__module__) diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/core/tesseract.py /tmp/DgSymrsclJ/tucan-0.3.9/core/tesseract.py --- tucan-0.3.8/core/tesseract.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/core/tesseract.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,87 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import logging +logger = logging.getLogger(__name__) + +import os +import sys +import subprocess +import tempfile + +import ImageFile +import Image +import TiffImagePlugin + +import cons + +IMAGE_SUFFIX = ".tif" +TEXT_SUFFIX = ".txt" + +class Tesseract: + """""" + def __init__(self, data, filter=None): + """""" + if cons.OS_WINDOWS: + self.image_name = os.path.join(sys.path[0], "tmp.tif") + self.text_name = os.path.join(sys.path[0], "tmp") + self.tesseract = os.path.join(sys.path[0], "tesseract", "tesseract.exe") + else: + if cons.OS_OSX: + os.environ["TESSDATA_PREFIX"] = os.path.join(sys.path[0], "tesseract", "") + self.tesseract = os.path.join(sys.path[0], "tesseract", "tesseract") + else: + self.tesseract = "tesseract" + self.text = tempfile.NamedTemporaryFile(suffix=TEXT_SUFFIX) + self.image = tempfile.NamedTemporaryFile(suffix=IMAGE_SUFFIX) + self.image_name = self.image.name + self.text_name = self.text.name.rsplit(TEXT_SUFFIX, 1)[0] + p = ImageFile.Parser() + p.feed(data) + if filter: + image = filter(p.close()) + else: + image = p.close() + image.save(self.image_name) + + def get_captcha(self): + """""" + captcha = "" + try: + if cons.OS_WINDOWS: + if subprocess.call([self.tesseract, self.image_name, self.text_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE, creationflags=134217728) == 0: + f = file(self.text_name + TEXT_SUFFIX, "r") + captcha = f.readline().strip() + f.close() + else: + if subprocess.call([self.tesseract, self.image_name, self.text_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0: + captcha = self.text.file.readline().strip() + self.text.file.close() + self.image.file.close() + except Exception, e: + logger.critical("No tesseract available: %s" % e) + return "" + else: + return captcha + +if __name__ == "__main__": + f = file("tmp.tif", "r") + t = Tesseract(f.read()) + print t.get_captcha() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/core/uploader.py /tmp/DgSymrsclJ/tucan-0.3.9/core/uploader.py --- tucan-0.3.8/core/uploader.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/core/uploader.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,42 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +""" +import MultipartPostHandler, urllib2, cookielib + +cookies = cookielib.CookieJar() +opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookies), MultipartPostHandler.MultipartPostHandler) +params = { "username" : "bob", "password" : "riviera", "file" : open("filename", "rb") } +opener.open("http://wwww.bobsite.com/upload/", params) +""" + +import urllib +import urllib2 + +from HTMLParser import HTMLParser + +class Uploader(HTMLParser): + """""" + def __init__(self, file_name): + """""" + HTMLParser.__init__(self) + +if __name__ == "__main__": + c = Uploader("/home/crak/mierda.html") diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/core/url_open.py /tmp/DgSymrsclJ/tucan-0.3.9/core/url_open.py --- tucan-0.3.8/core/url_open.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/core/url_open.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,61 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import __builtin__ +import urllib2 +import logging +logger = logging.getLogger(__name__) + +import socket + +import cons + +def set_proxy(url, port=0): + """""" + if url: + __builtin__.PROXY = {"http": "%s:%i" % (url, port)} + socket.setdefaulttimeout(30) + logger.info("Using proxy: %s:%i" % (url, port)) + else: + if __builtin__.PROXY: + __builtin__.PROXY = None + socket.setdefaulttimeout(60) + logger.info("Proxy Disabled.") + +class URLOpen: + """""" + def __init__(self, cookie=None): + """""" + if PROXY: + self.opener = urllib2.build_opener(urllib2.ProxyHandler(PROXY), urllib2.HTTPCookieProcessor(cookie)) + else: + self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie)) + + def open(self, url, form=None): + """""" + if form: + return self.opener.open(urllib2.Request(url, None, cons.USER_AGENT), form) + else: + return self.opener.open(urllib2.Request(url, None, cons.USER_AGENT)) + +if __name__ == "__main__": + PROXY = {"http": "proxy.alu.uma.es:3128"} + o = URLOpen() + print o.open("http://www.google.com").read() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/debian/changelog /tmp/DgSymrsclJ/tucan-0.3.9/debian/changelog --- tucan-0.3.8/debian/changelog 2009-11-06 13:50:27.000000000 +0000 +++ tucan-0.3.9/debian/changelog 2009-11-06 13:33:34.000000000 +0000 @@ -1,12 +1,16 @@ -tucan (0.3.8-1~ppajaunty1) jaunty; urgency=low +tucan (0.3.9-0ubuntu1~ppa0) karmic; urgency=low - * Ubuntu PPA (no-change rebuild) + * Upgrade to Karmic + * Changed control - -- Savvas Radevic Tue, 21 Jul 2009 20:36:16 +0200 + -- Igor Gomes Fri, 06 Nov 2009 11:32:42 -0200 tucan (0.3.8-1) unstable; urgency=low * New upstream release + * debian-policy updated to 3.8.2 + * License upgraded to GPLv3 + * New upstream/mainteiner mail * Solved data loss (Closes: #531392) -- Fran Lupion (Crak) Wed, 15 Jul 2009 22:54:52 +0200 diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/debian/control /tmp/DgSymrsclJ/tucan-0.3.9/debian/control --- tucan-0.3.8/debian/control 2009-11-06 13:50:27.000000000 +0000 +++ tucan-0.3.9/debian/control 2009-11-06 13:22:59.000000000 +0000 @@ -1,7 +1,8 @@ Source: tucan Section: net Priority: optional -Maintainer: Fran Lupion (Crak) +Maintainer: Igor Gomes +XSBC-Original-Maintainer: Fran Lupion (Crak) Build-Depends: debhelper (>= 7) Standards-Version: 3.8.2 Homepage: http://www.tucaneando.com @@ -10,18 +11,7 @@ Architecture: all Depends: python (>= 2.5), python-gtk2, python-imaging, tesseract-ocr, tesseract-ocr-eng, librsvg2-common Description: Download and upload manager for 1-Click Hosters - Designed for automatic management of sites like: - - http://rapidshare.com/ - - http://megaupload.com/ - - http://gigasize.com/ - - http://mediafire.com/ - - http://4shared.com/ - - http://sendspace.com/ - - http://zshare.net/ - - http://filefactory.com/ - - http://easy-share.com/ - - http://badongo.com/ - - (...) + Designed for automatic management of sites like: Rapidshare, Magaupload, 4shared and many others. Main Features: - Graphical User Interface in GTK+. - Easy to expand with plugins. diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/debian/watch /tmp/DgSymrsclJ/tucan-0.3.9/debian/watch --- tucan-0.3.8/debian/watch 2009-11-06 13:50:27.000000000 +0000 +++ tucan-0.3.9/debian/watch 2009-11-06 13:27:56.000000000 +0000 @@ -2,5 +2,5 @@ version=3 # Full-site-with-pattern [Version [Action]] http://forja.rediris.es/frs/?group_id=408&release_id=668 \ - /frs/download.php/(.*)/tucan-(.*)\.tar\.gz \ + /frs/download.php/.*/tucan-(.*)\.tar\.gz \ debian uupdate diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/4shared/anonymous_download.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/4shared/anonymous_download.py --- tucan-0.3.8/default_plugins/4shared/anonymous_download.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/4shared/anonymous_download.py 2009-10-07 00:02:27.000000000 +0100 @@ -23,8 +23,8 @@ from parsers import CheckLinks, Parser -from download_plugin import DownloadPlugin -from slots import Slots +from core.download_plugin import DownloadPlugin +from core.slots import Slots WAIT = 40 @@ -49,6 +49,8 @@ else: logger.warning("Limit Exceded.") self.add_wait() + self.return_slot() + def delete(self, file_name): """""" diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/4shared/parsers.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/4shared/parsers.py --- tucan-0.3.8/default_plugins/4shared/parsers.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/4shared/parsers.py 2009-10-07 00:02:27.000000000 +0100 @@ -23,7 +23,7 @@ import HTMLParser -from url_open import URLOpen +from core.url_open import URLOpen class Parser(HTMLParser.HTMLParser): """""" @@ -64,28 +64,26 @@ name = None size = 0 unit = None - size_found = False + size_found = 0 next_line = 0 try: for line in URLOpen().open(url).readlines(): if '' in line: name = line.split('')[1].split('')[0] - elif 'File' in line: - size_found = True - if size_found: - next_line += 1 - if next_line == 5: - size_found = False - tmp = line.split(">")[1].split("<")[0].split() - unit = tmp[1] - if "," in tmp[0]: - size = int(tmp[0].replace(",", "")) - else: - size = int(tmp[0]) - if size > 1024: - if unit == "KB": - size = size / 1024 - unit = "MB" + elif '' in line: + size_found += 1 + elif size_found == 3: + size_found = -10 + tmp = line.split(">")[1].split("<")[0].split() + unit = tmp[1] + if "," in tmp[0]: + size = int(tmp[0].replace(",", "")) + else: + size = int(tmp[0]) + if size > 1024: + if unit == "KB": + size = size / 1024 + unit = "MB" if not name: name = url size = -1 diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/4shared/service.conf /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/4shared/service.conf --- tucan-0.3.8/default_plugins/4shared/service.conf 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/4shared/service.conf 2009-10-07 00:02:27.000000000 +0100 @@ -11,4 +11,4 @@ icon = favicon_4shared.ico downloads = True uploads = False -update = 200907150200 +update = 200910070050 diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/badongo/anonymous_download.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/badongo/anonymous_download.py --- tucan-0.3.8/default_plugins/badongo/anonymous_download.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/badongo/anonymous_download.py 2009-10-07 00:02:27.000000000 +0100 @@ -24,8 +24,8 @@ from parsers import CheckLinks, Parser -from download_plugin import DownloadPlugin -from slots import Slots +from core.download_plugin import DownloadPlugin +from core.slots import Slots class AnonymousDownload(DownloadPlugin, Slots): """""" @@ -49,6 +49,8 @@ else: logger.warning("Limit Exceded.") self.add_wait() + self.return_slot() + def post_wait(self, link): """Must return handler""" return self.opener.open(link, urllib.urlencode([("pr", "1")])) diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/badongo/parsers.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/badongo/parsers.py --- tucan-0.3.8/default_plugins/badongo/parsers.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/badongo/parsers.py 2009-10-07 00:02:27.000000000 +0100 @@ -27,8 +27,8 @@ from HTMLParser import HTMLParser -from tesseract import Tesseract -from url_open import URLOpen +from core.tesseract import Tesseract +from core.url_open import URLOpen BASE_URL = "http://www.badongo.com" @@ -115,6 +115,9 @@ if size == 0: size = 1 unit = tmp[1] + if unit == "B": + size = 1 + unit = "KB" if not name: name = url size = -1 diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/badongo/service.conf /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/badongo/service.conf --- tucan-0.3.8/default_plugins/badongo/service.conf 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/badongo/service.conf 2009-10-07 00:02:27.000000000 +0100 @@ -11,4 +11,4 @@ icon = favicon_badongo.ico downloads = True uploads = False -update = 200907150200 +update = 200910070050 diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/depositfiles/anonymous_download.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/depositfiles/anonymous_download.py --- tucan-0.3.8/default_plugins/depositfiles/anonymous_download.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/default_plugins/depositfiles/anonymous_download.py 2009-10-07 00:02:27.000000000 +0100 @@ -0,0 +1,63 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import urllib +import logging +logger = logging.getLogger(__name__) + +from parsers import CheckLinks, Parser + +from core.download_plugin import DownloadPlugin +from core.url_open import URLOpen +from core.slots import Slots + +class AnonymousDownload(DownloadPlugin, Slots): + """""" + def __init__(self): + """""" + Slots.__init__(self, 1, 120) + DownloadPlugin.__init__(self) + self.input = "" + + def check_links(self, url): + """""" + return CheckLinks().check(url) + + def add(self, path, link, file_name): + """""" + if self.get_slot(): + parser = Parser(link) + if parser.link: + self.input = parser.input + if self.start(path, parser.link, file_name, parser.wait, None, self.post_wait): + return True + else: + logger.warning("Limit Exceded.") + self.add_wait() + self.return_slot() + + def post_wait(self, link): + """Must return handle""" + return URLOpen().open(link, urllib.urlencode([("download", self.input)])) + + def delete(self, file_name): + """""" + if self.stop(file_name): + logger.warning("Stopped %s: %s" % (file_name, self.return_slot())) Binary files /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/depositfiles/favicon_depositfiles.ico and /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/depositfiles/favicon_depositfiles.ico differ diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/depositfiles/parsers.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/depositfiles/parsers.py --- tucan-0.3.8/default_plugins/depositfiles/parsers.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/default_plugins/depositfiles/parsers.py 2009-10-07 00:02:27.000000000 +0100 @@ -0,0 +1,112 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import urllib +import logging +logger = logging.getLogger(__name__) + +from HTMLParser import HTMLParser + +from core.url_open import URLOpen + +BASE_URL = "http://depositfiles.com" + +class Parser(HTMLParser): + def __init__(self, url): + """""" + HTMLParser.__init__(self) + self.link = None + self.form_action = None + self.input = None + self.wait = None + self.found = False + try: + opener = URLOpen() + self.feed(opener.open(url).read()) + self.close() + if self.form_action: + form = urllib.urlencode({"": self.input, "gateway_result":"1"}) + for line in opener.open("%s%s" % (BASE_URL, self.form_action), form).readlines(): + if self.wait: + self.feed(line) + else: + if '' in line: + self.wait = int(line.split('')[1].split('')[0]) + self.close() + except Exception, e: + logger.exception("%s :%s" % (url, e)) + + def handle_starttag(self, tag, attrs): + """""" + if self.wait: + if self.found: + if tag == "form": + self.link = attrs[0][1] + elif tag == "input": + for ref, value in attrs: + if ref == "value": + self.input = value + self.found = False + elif tag == "div": + if len(attrs) > 0 and attrs[0][1] == "download_url": + self.found = True + + else: + if self.found: + if tag == "form": + self.form_action = attrs[0][1] + elif tag == "input": + for ref, value in attrs: + if ref == "value": + self.input = value + self.found = False + elif tag == "div": + if attrs[0][1] == "downloadblock": + self.found = True + + + +class CheckLinks: + """""" + def check(self, url): + """""" + name = None + size = 0 + unit = None + try: + for line in URLOpen().open(url).readlines(): + if '')[0] + if '' in line: + tmp = line.split('')[1].split('')[0].split(" ") + unit = tmp.pop() + size = int(round(float(tmp.pop()))) + if not unit: + name = url + size = -1 + except Exception, e: + name = url + size = -1 + logger.exception("%s :%s" % (url, e)) + return name, size, unit + +if __name__ == "__main__": + c = Parser("http://depositfiles.com/files/7n5ulr17r") + #print CheckLinks().check("http://depositfiles.com/files/7n5ulr17r") diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/depositfiles/service.conf /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/depositfiles/service.conf --- tucan-0.3.8/default_plugins/depositfiles/service.conf 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/default_plugins/depositfiles/service.conf 2009-10-07 00:02:27.000000000 +0100 @@ -0,0 +1,14 @@ +[anonymous_download] +name = AnonymousDownload +author = Crak +captcha = False +version = 0.1 +slots = 1 + +[main] +enabled = False +name = depositfiles.com +icon = favicon_depositfiles.ico +downloads = True +uploads = False +update = 200910070050 diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/easy-share/anonymous_download.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/easy-share/anonymous_download.py --- tucan-0.3.8/default_plugins/easy-share/anonymous_download.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/easy-share/anonymous_download.py 2009-10-07 00:02:27.000000000 +0100 @@ -21,16 +21,16 @@ import logging logger = logging.getLogger(__name__) -from parsers import CheckLinks, Parser +from parsers import CheckLinks, WaitParser, CaptchaParser -from download_plugin import DownloadPlugin -from slots import Slots +from core.download_plugin import DownloadPlugin +from core.slots import Slots class AnonymousDownload(DownloadPlugin, Slots): """""" def __init__(self): """""" - Slots.__init__(self, 1, 5) + Slots.__init__(self, 1, 300) DownloadPlugin.__init__(self) def check_links(self, url): @@ -40,14 +40,21 @@ def add(self, path, link, file_name): """""" if self.get_slot(): - parser = Parser(link) - if self.start(path, link, file_name, parser.wait, None, self.post_wait): - return True + parser = WaitParser(link) + if parser.wait: + if self.start(path, link, file_name, parser.wait, None, self.post_wait): + return True + else: + logger.warning("Limit Exceded.") + self.add_wait() + self.return_slot() + def post_wait(self, link): - """Must return link and form""" - parser = Parser(link) - return parser.handle + """Must return handle""" + parser = CaptchaParser(link) + if parser.captcha_url: + return parser.handle def delete(self, file_name): """""" diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/easy-share/parsers.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/easy-share/parsers.py --- tucan-0.3.8/default_plugins/easy-share/parsers.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/easy-share/parsers.py 2009-10-07 00:02:27.000000000 +0100 @@ -26,20 +26,15 @@ import ImageOps -from tesseract import Tesseract -from url_open import URLOpen +from core.tesseract import Tesseract +from core.url_open import URLOpen BASE_URL = "http://www.easy-share.com" -class Parser(HTMLParser): +class WaitParser: + """""" def __init__(self, url): """""" - HTMLParser.__init__(self) - self.link = None - self.form_action = None - self.id = None - self.handle = None - self.captcha_url = None self.wait = None try: opener = URLOpen() @@ -49,13 +44,28 @@ for line in opener.open("%s%s" % (BASE_URL, line.split("'")[1])).readlines(): if "w=" in line: self.wait = int(line.split("'")[1]) + 1 - if self.wait: - logger.info("%s wait:%s seconds" % (url, self.wait)) - else: - for line in tmp: - self.feed(line) - self.close() - repeat = True + logger.info("%s wait %s seconds" % (url, self.wait)) + except Exception, e: + logger.exception("%s :%s" % (url, e)) + + +class CaptchaParser(HTMLParser): + """""" + def __init__(self, url): + """""" + HTMLParser.__init__(self) + self.link = None + self.form_action = None + self.id = None + self.handle = None + self.captcha_url = None + try: + opener = URLOpen() + for line in opener.open(url).readlines(): + self.feed(line) + self.close() + repeat = True + if self.captcha_url: while True: tes = Tesseract(opener.open(self.captcha_url).read(), self.filter_image) captcha = tes.get_captcha() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/easy-share/service.conf /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/easy-share/service.conf --- tucan-0.3.8/default_plugins/easy-share/service.conf 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/easy-share/service.conf 2009-10-07 00:02:27.000000000 +0100 @@ -11,4 +11,4 @@ icon = favicon_easy-share.ico downloads = True uploads = False -update = 200907150200 +update = 200910070050 diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/filefactory/anonymous_download.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/filefactory/anonymous_download.py --- tucan-0.3.8/default_plugins/filefactory/anonymous_download.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/filefactory/anonymous_download.py 2009-10-07 00:02:27.000000000 +0100 @@ -23,9 +23,8 @@ from parsers import CheckLinks, Parser -from download_plugin import DownloadPlugin -from slots import Slots - +from core.download_plugin import DownloadPlugin +from core.slots import Slots class AnonymousDownload(DownloadPlugin, Slots): """""" @@ -48,6 +47,7 @@ else: logger.warning("Limit Exceded.") self.add_wait() + self.return_slot() def delete(self, file_name): """""" diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/filefactory/parsers.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/filefactory/parsers.py --- tucan-0.3.8/default_plugins/filefactory/parsers.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/filefactory/parsers.py 2009-10-07 00:02:27.000000000 +0100 @@ -24,12 +24,7 @@ from HTMLParser import HTMLParser -#import sys -#sys.path.append("/home/crak/tucan/trunk") - -from url_open import URLOpen, set_proxy - -#set_proxy(None) +from core.url_open import URLOpen BASE_URL = "http://www.filefactory.com" @@ -37,39 +32,31 @@ def __init__(self, url): """""" HTMLParser.__init__(self) - self.form_found = False self.link_found = False self.time_found = False - self.form_action = None self.link = None self.wait = None try: - self.feed(URLOpen().open(url).read()) - - if self.form_action: - self.feed(URLOpen().open(self.form_action, urllib.urlencode({"freeBtn": "Free Download"})).read()) + for line in URLOpen().open(url).readlines(): + if 'alt="Download Now"' in line: + button_action = "%s%s" % (BASE_URL, line.split('')[0]) + self.feed(URLOpen().open(button_action, urllib.urlencode({"freeBtn": "Free Download"})).read()) self.close() except Exception, e: logger.exception("%s :%s" % (url, e)) def handle_starttag(self, tag, attrs): """""" - if tag == "form": - if self.form_found: - self.form_action = "%s%s" % (BASE_URL, attrs[0][1]) - self.form_found = False + if tag == "a": + if self.link_found: + self.link = attrs[0][1] + self.link_found = False elif tag == "div": if len(attrs) > 0: - if attrs[0][1] == "freeBtnContainer": - self.form_found = True + if attrs[0][1] == "basicBtn": + self.time_found = True elif attrs[0][1] == "downloadLink": self.link_found = True - elif attrs[0][1] == "linkContainer": - self.time_found = True - elif tag == "a": - if self.link_found: - self.link = attrs[0][1] - self.link_found = False elif tag == "input": if self.time_found: self.wait = int(attrs[2][1]) @@ -106,4 +93,5 @@ if __name__ == "__main__": c = Parser("http://www.filefactory.com/file/cc646e/n/Music_Within_2007_Sample_avi") + print c.link #print CheckLinks().check("http://www.filefactory.com/file/cc646e/n/Music_Within_2007_Sample_avi") diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/filefactory/service.conf /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/filefactory/service.conf --- tucan-0.3.8/default_plugins/filefactory/service.conf 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/filefactory/service.conf 2009-10-07 00:02:27.000000000 +0100 @@ -11,4 +11,4 @@ icon = favicon_filefactory.ico downloads = True uploads = False -update = 200907150200 +update = 200910070050 diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/gigasize/anonymous_download.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/gigasize/anonymous_download.py --- tucan-0.3.8/default_plugins/gigasize/anonymous_download.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/gigasize/anonymous_download.py 2009-10-07 00:02:27.000000000 +0100 @@ -28,15 +28,13 @@ import Image import ImageOps -from tesseract import Tesseract -from download_plugin import DownloadPlugin -from slots import Slots - -from url_open import URLOpen - from check_links import CheckLinks -import cons +from core.download_plugin import DownloadPlugin +from core.tesseract import Tesseract +from core.url_open import URLOpen +from core.slots import Slots +import core.cons as cons WAIT = 60 @@ -81,11 +79,15 @@ data = urllib.urlencode([("txtNumber", captcha), ("btnLogin.x", "124"), ("btnLogin.y", "12"), ("btnLogin", "Download")]) f = FormParser() for line in self.opener.open("http://www.gigasize.com/formdownload.php", data).readlines(): - if 'YOU HAVE REACHED YOUR HOURLY LIMIT
' in line: + if '
' in line: retry = False logger.warning("Limit Exceded.") self.add_wait() self.return_slot() + elif '
' in line: + retry = False + logger.error("No password support!") + self.return_slot() f.feed(line) self.form = f.form_action f.close() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/gigasize/check_links.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/gigasize/check_links.py --- tucan-0.3.8/default_plugins/gigasize/check_links.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/gigasize/check_links.py 2009-10-07 00:02:27.000000000 +0100 @@ -21,9 +21,8 @@ import urllib2 from HTMLParser import HTMLParser -from url_open import URLOpen - -import cons +from core.url_open import URLOpen +import core.cons as cons class CheckLinks(HTMLParser): """""" diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/gigasize/service.conf /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/gigasize/service.conf --- tucan-0.3.8/default_plugins/gigasize/service.conf 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/gigasize/service.conf 2009-10-07 00:02:27.000000000 +0100 @@ -11,4 +11,4 @@ icon = favicon_gigasize.ico downloads = True uploads = False -update = 200907150200 +update = 200910070050 diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/hotfile/anonymous_download.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/hotfile/anonymous_download.py --- tucan-0.3.8/default_plugins/hotfile/anonymous_download.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/default_plugins/hotfile/anonymous_download.py 2009-10-07 00:02:27.000000000 +0100 @@ -0,0 +1,67 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import urllib +import logging +logger = logging.getLogger(__name__) + +from parsers import CheckLinks, Parser, CaptchaParser + +from core.download_plugin import DownloadPlugin +from core.url_open import URLOpen +from core.slots import Slots + +class AnonymousDownload(DownloadPlugin, Slots): + """""" + def __init__(self): + """""" + Slots.__init__(self, 1, 300) + DownloadPlugin.__init__(self) + self.form = "" + + def check_links(self, url): + """""" + return CheckLinks().check(url) + + def add(self, path, link, file_name): + """""" + if self.get_slot(): + parser = Parser(link) + self.form = parser.form + if parser.link: + if self.start(path, parser.link, file_name, parser.wait, None, self.post_wait): + return True + + def post_wait(self, link): + """Must return handle""" + c = CaptchaParser(link, self.form) + if c.link: + return URLOpen().open(c.link) + elif c.action_captcha: + logger.warning("Wrong Captcha!") + else: + logger.warning("Limit Exceded.") + self.add_wait() + self.return_slot() + + def delete(self, file_name): + """""" + if self.stop(file_name): + logger.warning("Stopped %s: %s" % (file_name, self.return_slot())) Binary files /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/hotfile/favicon_hotfile.ico and /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/hotfile/favicon_hotfile.ico differ diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/hotfile/parsers.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/hotfile/parsers.py --- tucan-0.3.8/default_plugins/hotfile/parsers.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/default_plugins/hotfile/parsers.py 2009-10-07 00:02:27.000000000 +0100 @@ -0,0 +1,178 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import urllib +import logging +logger = logging.getLogger(__name__) + +from HTMLParser import HTMLParser + +import ImageOps + +from core.tesseract import Tesseract +from core.url_open import URLOpen + +BASE_URL = "http://hotfile.com" + +class CaptchaParser(HTMLParser): + def __init__(self, url, form): + """""" + HTMLParser.__init__(self) + self.link = None + self.action_captcha = None + self.captchaid = None + self.hash1 = None + self.hash2 = None + self.captcha_url = None + try: + opener = URLOpen() + tmp = opener.open(url, form).readlines() + for line in tmp: + self.feed(line) + self.close() + if self.action_captcha: + tes = Tesseract(opener.open(self.captcha_url).read(), self.filter_image) + captcha = tes.get_captcha() + logger.warning("Captcha: %s" % captcha) + form = urllib.urlencode([("action", self.action_captcha), ("captchaid", self.captchaid), ("hash1", self.hash1), ("hash2", self.hash2), ("captcha", captcha)]) + tmp = opener.open(url, form).readlines() + for line in tmp: + if '
Downloading ' in line: + if "href" in line: + tmp = line.split('')[0].split("/") + tmp.append(urllib.quote(tmp.pop())) + self.link = "/".join(tmp) + except Exception, e: + logger.exception("%s :%s" % (url, e)) + + def handle_starttag(self, tag, attrs): + """""" + if tag == "input": + if ("name", "action") in attrs: + for ref, value in attrs: + if ref == "value" and value == "checkcaptcha": + self.action_captcha = value + elif ("name", "captchaid") in attrs: + for ref, value in attrs: + if ref == "value": + self.captchaid = value + elif ("name", "hash1") in attrs: + for ref, value in attrs: + if ref == "value": + self.hash1 = value + elif ("name", "hash2") in attrs: + for ref, value in attrs: + if ref == "value": + self.hash2 = value + elif tag == "img": + self.captcha_url = "%s%s" % (BASE_URL, attrs[0][1]) + + def filter_image(self, image): + """""" + image = image.point(self.filter_pixel) + image = ImageOps.grayscale(image) + return image + + def filter_pixel(self, pixel): + """""" + if pixel > 110: + return 255 + if pixel > 90: + return 100 + else: + return 1 + +class Parser(HTMLParser): + def __init__(self, url): + """""" + HTMLParser.__init__(self) + self.link = None + self.form = None + self.tm = None + self.tmhash = None + self.waithash = None + self.wait = None + try: + opener = URLOpen() + self.feed(opener.open(url).read()) + self.close() + self.form = urllib.urlencode([("action", "capt"), ("tm", self.tm), ("tmhash", self.tmhash), ("wait", self.wait), ("waithash", self.waithash)]) + except Exception, e: + logger.exception("%s :%s" % (url, e)) + + def handle_starttag(self, tag, attrs): + """""" + if self.link: + if tag == "input": + if ("name", "tm") in attrs: + for ref, value in attrs: + if ref == "value": + self.tm = value + elif ("name", "tmhash") in attrs: + for ref, value in attrs: + if ref == "value": + self.tmhash = value + elif ("name", "wait") in attrs: + for ref, value in attrs: + if ref == "value": + self.wait = int(value) + elif ("name", "waithash") in attrs: + for ref, value in attrs: + if ref == "value": + self.waithash = value + else: + if tag == "form": + if len(attrs) > 3: + self.link = "%s%s" % (BASE_URL, attrs[1][1]) + +class CheckLinks: + """""" + def check(self, url): + """""" + name = None + size = 0 + unit = None + try: + for line in URLOpen().open(url).readlines(): + if '' in line: + name = line.split('Downloading ')[1].split('')[0] + tmp = line.split('|')[1].strip().split('')[0] + unit = tmp[-2:].upper() + size = int(round(float(tmp[:-2]))) + if not unit: + name = url + size = -1 + except Exception, e: + name = url + size = -1 + logger.exception("%s :%s" % (url, e)) + return name, size, unit + +if __name__ == "__main__": + c = Parser("http://hotfile.com/dl/7174149/00fbb47/Sander_Van_Doorn-Live_at_Sensation_White_Saint-Petersburg-12062009.mp3.html") + print c.link + print c.form + import time + for i in range(c.wait): + print i + time.sleep(1) + m = CaptchaParser(c.link, c.form) + print m.link + #print CheckLinks().check("http://hotfile.com/dl/10804393/9f439e8/Bruno_-_www.crostuff.net.part1.rar.html") diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/hotfile/service.conf /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/hotfile/service.conf --- tucan-0.3.8/default_plugins/hotfile/service.conf 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/default_plugins/hotfile/service.conf 2009-10-07 00:02:27.000000000 +0100 @@ -0,0 +1,14 @@ +[anonymous_download] +name = AnonymousDownload +author = Crak +captcha = True +version = 0.1 +slots = 1 + +[main] +enabled = False +name = hotfile.com +icon = favicon_hotfile.ico +downloads = True +uploads = False +update = 200910070050 diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/mediafire/anonymous_download.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/mediafire/anonymous_download.py --- tucan-0.3.8/default_plugins/mediafire/anonymous_download.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/mediafire/anonymous_download.py 2009-10-07 00:02:27.000000000 +0100 @@ -24,11 +24,9 @@ import logging logger = logging.getLogger(__name__) -from download_plugin import DownloadPlugin - from parsers import CheckLinks, FormParser -import cons +from core.download_plugin import DownloadPlugin class AnonymousDownload(DownloadPlugin): """""" diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/mediafire/parsers.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/mediafire/parsers.py --- tucan-0.3.8/default_plugins/mediafire/parsers.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/mediafire/parsers.py 2009-10-07 00:02:27.000000000 +0100 @@ -23,7 +23,8 @@ import logging logger = logging.getLogger(__name__) -from url_open import URLOpen +from core.tesseract import Tesseract +from core.url_open import URLOpen class FormParser: """""" @@ -46,25 +47,27 @@ handle = opener.open("http://www.mediafire.com/dynamic/download.php?%s" % (urllib.urlencode([("qk", tmp[0]), ("pk", tmp[1]), ("r", tmp[2])]))) tmp = handle.readlines() vars = {} + + tmp1 = tmp[2].split("function dz()")[0].split(";", 4) + sum = tmp[2].split("+mL+'/' ")[1].split(" 'g/'+mH+'/'+mY+'")[0] + + server = tmp1[1].split("'")[1] + link = tmp1[2].split("'")[1] + name = tmp1[3].split("'")[1] - server = tmp[11].split("'")[1] - link = tmp[12].split("'")[1] - name = tmp[13].split("'")[1] - - for var in tmp[14].split(";"): + for var in tmp1.pop().strip().split(";"): var = var.split("var") if len(var) > 1: var = var[1].strip().split("=") if ((len(var) > 1) and ("'" in var[1])): vars[var[0]] = var[1].split("'")[1] - for var in tmp[27].split(" ")[14].split("+"): + for var in sum.split("+"): if len(var) > 0: if var in vars.keys(): random += vars[var] else: error = True except Exception, e: - print e error = True logger.exception("%s: %s" % (url, e)) if server and random and link and name and not error: diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/mediafire/service.conf /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/mediafire/service.conf --- tucan-0.3.8/default_plugins/mediafire/service.conf 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/mediafire/service.conf 2009-10-07 00:02:27.000000000 +0100 @@ -11,4 +11,4 @@ icon = favicon_mediafire.ico downloads = True uploads = False -update = 200907150200 +update = 200910070050 diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/megaupload/anonymous_download.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/megaupload/anonymous_download.py --- tucan-0.3.8/default_plugins/megaupload/anonymous_download.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/megaupload/anonymous_download.py 2009-10-07 00:02:27.000000000 +0100 @@ -25,15 +25,14 @@ import logging logger = logging.getLogger(__name__) -from url_open import URLOpen - from captcha import CaptchaForm from check_links import CheckLinks -from download_plugin import DownloadPlugin -from slots import Slots +from core.download_plugin import DownloadPlugin +from core.url_open import URLOpen +from core.slots import Slots -import cons +import core.cons as cons WAIT = 45 @@ -52,7 +51,7 @@ return self.start(path, parser.link, file_name, WAIT, None, self.post_wait) def post_wait(self, link): - """Must return link and form""" + """Must return handle""" try: handle = URLOpen().open(link) except Exception, e: diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/megaupload/captcha.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/megaupload/captcha.py --- tucan-0.3.8/default_plugins/megaupload/captcha.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/megaupload/captcha.py 2009-10-07 00:02:27.000000000 +0100 @@ -23,9 +23,9 @@ logger = logging.getLogger(__name__) from HTMLParser import HTMLParser -from url_open import URLOpen -from tesseract import Tesseract +from core.url_open import URLOpen +from core.tesseract import Tesseract CAPTCHACODE = "captchacode" MEGAVAR = "megavar" diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/megaupload/check_links.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/megaupload/check_links.py --- tucan-0.3.8/default_plugins/megaupload/check_links.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/megaupload/check_links.py 2009-10-07 00:02:27.000000000 +0100 @@ -22,9 +22,9 @@ import logging logger = logging.getLogger(__name__) -from url_open import URLOpen +from core.url_open import URLOpen -import cons +import core.cons as cons class CheckLinks: """""" diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/megaupload/premium_cookie.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/megaupload/premium_cookie.py --- tucan-0.3.8/default_plugins/megaupload/premium_cookie.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/megaupload/premium_cookie.py 2009-10-07 00:02:27.000000000 +0100 @@ -21,7 +21,7 @@ import urllib import cookielib -from url_open import URLOpen +from core.url_open import URLOpen class PremiumCookie: """""" diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/megaupload/premium_download.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/megaupload/premium_download.py --- tucan-0.3.8/default_plugins/megaupload/premium_download.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/megaupload/premium_download.py 2009-10-07 00:02:27.000000000 +0100 @@ -22,14 +22,14 @@ import logging logger = logging.getLogger(__name__) -from accounts import Accounts -from service_config import SECTION_PREMIUM_DOWNLOAD, ServiceConfig -from download_plugin import DownloadPlugin - from premium_cookie import PremiumCookie from premium_parser import PremiumParser from check_links import CheckLinks +from core.accounts import Accounts +from core.service_config import SECTION_PREMIUM_DOWNLOAD, ServiceConfig +from core.download_plugin import DownloadPlugin + class PremiumDownload(DownloadPlugin, Accounts): """""" def __init__(self, config): diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/megaupload/service.conf /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/megaupload/service.conf --- tucan-0.3.8/default_plugins/megaupload/service.conf 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/megaupload/service.conf 2009-10-07 00:02:27.000000000 +0100 @@ -12,7 +12,7 @@ premium_cookie = PremiumCookie downloads = True uploads = False -update = 200907150200 +update = 200910070050 [premium_download] name = PremiumDownload diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/rapidshare/anonymous_download.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/rapidshare/anonymous_download.py --- tucan-0.3.8/default_plugins/rapidshare/anonymous_download.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/rapidshare/anonymous_download.py 2009-10-07 00:02:27.000000000 +0100 @@ -24,13 +24,12 @@ from HTMLParser import HTMLParser -from url_open import URLOpen - -from download_plugin import DownloadPlugin -from slots import Slots - from check_links import CheckLinks +from core.download_plugin import DownloadPlugin +from core.url_open import URLOpen +from core.slots import Slots + class FormParser(HTMLParser): """""" def __init__(self, url): diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/rapidshare/check_links.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/rapidshare/check_links.py --- tucan-0.3.8/default_plugins/rapidshare/check_links.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/rapidshare/check_links.py 2009-10-07 00:02:27.000000000 +0100 @@ -21,9 +21,9 @@ import logging logger = logging.getLogger(__name__) -from url_open import URLOpen +from core.url_open import URLOpen -import cons +import core.cons as cons class CheckLinks: """""" diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/rapidshare/premium_cookie.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/rapidshare/premium_cookie.py --- tucan-0.3.8/default_plugins/rapidshare/premium_cookie.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/rapidshare/premium_cookie.py 2009-10-07 00:02:27.000000000 +0100 @@ -21,7 +21,7 @@ import urllib import cookielib -from url_open import URLOpen +from core.url_open import URLOpen class PremiumCookie: """""" diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/rapidshare/premium_download.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/rapidshare/premium_download.py --- tucan-0.3.8/default_plugins/rapidshare/premium_download.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/rapidshare/premium_download.py 2009-10-07 00:02:27.000000000 +0100 @@ -24,16 +24,15 @@ from HTMLParser import HTMLParser -from accounts import Accounts -from service_config import SECTION_PREMIUM_DOWNLOAD -from download_plugin import DownloadPlugin - -from url_open import URLOpen - from premium_cookie import PremiumCookie from check_links import CheckLinks -import cons +from core.service_config import SECTION_PREMIUM_DOWNLOAD +from core.download_plugin import DownloadPlugin +from core.accounts import Accounts +from core.url_open import URLOpen + +import core.cons as cons class FormParser(HTMLParser): """""" diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/rapidshare/service.conf /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/rapidshare/service.conf --- tucan-0.3.8/default_plugins/rapidshare/service.conf 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/rapidshare/service.conf 2009-10-07 00:02:27.000000000 +0100 @@ -10,9 +10,9 @@ name = rapidshare.com icon = favicon_rapidshare.ico premium_cookie = PremiumCookie -uploads = False downloads = True -update = 200907150200 +uploads = False +update = 200910070050 [premium_download] name = PremiumDownload diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/sendspace/anonymous_download.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/sendspace/anonymous_download.py --- tucan-0.3.8/default_plugins/sendspace/anonymous_download.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/sendspace/anonymous_download.py 2009-10-07 00:02:27.000000000 +0100 @@ -23,15 +23,15 @@ from parsers import CheckLinks, Parser -from download_plugin import DownloadPlugin -from slots import Slots - +from core.download_plugin import DownloadPlugin +from core.url_open import URLOpen +from core.slots import Slots class AnonymousDownload(DownloadPlugin, Slots): """""" def __init__(self): """""" - Slots.__init__(self, 1, 30) + Slots.__init__(self, 1, 300) DownloadPlugin.__init__(self) def check_links(self, url): @@ -43,12 +43,23 @@ if self.get_slot(): parser = Parser(link) if parser.link: - if self.start(path, parser.link, file_name): + if self.start(path, parser.link, file_name, None, None, self.post_wait): return True - else: - logger.warning("Limit Exceded.") - self.add_wait() - + else: + logger.warning("Limit Exceded.") + self.add_wait() + self.return_slot() + + def post_wait(self, link): + """Must return handle""" + handle = URLOpen().open(link) + if "text/html" in handle.info().getheader("Content-Type"): + logger.warning("Limit Exceded.") + self.add_wait() + self.return_slot() + else: + return handle + def delete(self, file_name): """""" if self.stop(file_name): diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/sendspace/parsers.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/sendspace/parsers.py --- tucan-0.3.8/default_plugins/sendspace/parsers.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/sendspace/parsers.py 2009-10-07 00:02:27.000000000 +0100 @@ -22,10 +22,10 @@ import logging logger = logging.getLogger(__name__) -from url_open import URLOpen - import HTMLParser +from core.url_open import URLOpen + B64S = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"'; class Parser(HTMLParser.HTMLParser): @@ -34,6 +34,10 @@ """""" HTMLParser.HTMLParser.__init__(self) self.link = None + code = "" + vars = "" + var1 = "" + var2 = "" try: for line in URLOpen().open(url).readlines(): if "base64ToText" in line: @@ -49,8 +53,9 @@ def handle_starttag(self, tag, attrs): """""" if tag == "a": - if len(attrs) == 4: - self.link = urllib.quote(attrs[2][1], "/:") + for ref, value in attrs: + if ref == "href": + self.link = value def decode(self, code, num, text): """""" diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/sendspace/service.conf /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/sendspace/service.conf --- tucan-0.3.8/default_plugins/sendspace/service.conf 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/sendspace/service.conf 2009-10-07 00:02:27.000000000 +0100 @@ -11,4 +11,4 @@ icon = favicon_sendspace.ico downloads = True uploads = False -update = 200907150200 +update = 200910070050 diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/zshare/anonymous_download.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/zshare/anonymous_download.py --- tucan-0.3.8/default_plugins/zshare/anonymous_download.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/zshare/anonymous_download.py 2009-10-07 00:02:27.000000000 +0100 @@ -23,7 +23,7 @@ from parsers import CheckLinks, Parser -from download_plugin import DownloadPlugin +from core.download_plugin import DownloadPlugin WAIT = 50 diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/zshare/parsers.py /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/zshare/parsers.py --- tucan-0.3.8/default_plugins/zshare/parsers.py 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/zshare/parsers.py 2009-10-07 00:02:27.000000000 +0100 @@ -22,7 +22,7 @@ import logging logger = logging.getLogger(__name__) -from url_open import URLOpen +from core.url_open import URLOpen class Parser: """""" diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/default_plugins/zshare/service.conf /tmp/DgSymrsclJ/tucan-0.3.9/default_plugins/zshare/service.conf --- tucan-0.3.8/default_plugins/zshare/service.conf 2009-07-15 01:15:15.000000000 +0100 +++ tucan-0.3.9/default_plugins/zshare/service.conf 2009-10-07 00:02:27.000000000 +0100 @@ -11,4 +11,4 @@ icon = favicon_zshare.ico downloads = True uploads = False -update = 200907150200 +update = 200910070050 diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/downloader.py /tmp/DgSymrsclJ/tucan-0.3.9/downloader.py --- tucan-0.3.8/downloader.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/downloader.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,126 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import os -import urllib2 -import threading -import time -import logging -logger = logging.getLogger(__name__) - -from url_open import URLOpen - -import cons - -BASE_SIZE = 4 -BUFFER_SIZE = BASE_SIZE * 1024 - -class Downloader(threading.Thread): - """""" - def __init__(self, path, url, file_name, wait, cookie, post_wait): - """""" - threading.Thread.__init__(self) - - self.max_speed = 0 - - self.post_wait = post_wait - self.status = cons.STATUS_WAIT - self.path = path - self.url = url - self.file = file_name - self.wait = wait - self.stop_flag = False - self.start_time = time.time() - self.time_remaining = 0 - self.total_size = 1 - self.actual_size = 0 - self.speed = 0 - self.tmp_time = 0 - self.tmp_size = 0 - #build opener - self.opener = URLOpen(cookie) - - def run(self): - """""" - if self.wait: - while ((self.wait > 0) and not self.stop_flag): - time.sleep(1) - self.wait -= 1 - self.time_remaining = self.wait - if not self.stop_flag: - try: - if self.post_wait: - handle = self.post_wait(self.url) - else: - handle = self.opener.open(self.url) - if handle: - self.status = cons.STATUS_ACTIVE - logger.debug("%s :%s" % (self.file, handle.info().getheader("Content-Type"))) - self.total_size = int(handle.info().getheader("Content-Length")) - if not os.path.exists(unicode(self.path)): - os.mkdir(self.path) - f = open(unicode(os.path.join(self.path, self.file)), "wb") - self.start_time = time.time() - data = "None" - while ((len(data) > 0) and not self.stop_flag): - tmp_size = 0 - if self.max_speed > 0: - max_size = self.max_speed/BASE_SIZE - else: - max_size = 0 - start_seconds = time.time() - while (time.time() - start_seconds) < 1: - if max_size == 0 or tmp_size < max_size: - data = handle.read(BUFFER_SIZE) - f.write(data) - self.actual_size += len(data) - tmp_size += 1 - else: - time.sleep(0.1) - self.speed = BASE_SIZE * tmp_size - self.time_remaining = time.time() - self.start_time - f.close() - if not self.stop_flag: - self.stop_flag = True - if self.actual_size == self.total_size: - self.status = cons.STATUS_CORRECT - else: - self.status = cons.STATUS_ERROR - else: - self.stop_flag = True - self.status = cons.STATUS_PEND - #except TypeError, e: - # logger.exception("%s: %s" % (self.file, e)) - # self.stop_flag = True - # self.status = cons.STATUS_PEND - except Exception, e: - logger.exception("%s: %s" % (self.file, e)) - self.stop_flag = True - self.status = cons.STATUS_ERROR - - def get_speed(self): - """return int speed KB/s""" - elapsed_time = time.time() - self.tmp_time - size = self.actual_size - self.tmp_size - if size > 0: - self.speed = int(float(size/1024)/float(elapsed_time)) - self.tmp_time = time.time() - self.tmp_size = self.actual_size - return self.speed diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/download_manager.py /tmp/DgSymrsclJ/tucan-0.3.9/download_manager.py --- tucan-0.3.8/download_manager.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/download_manager.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,255 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import time -import threading - -import logging -logger = logging.getLogger(__name__) - -import cons - -class Link: - """""" - def __init__(self, url, plugin, type, service): - """""" - self.active = False - self.url = url - self.plugin = plugin - self.plugin_type = type - self.service = service - -class DownloadItem: - """""" - def __init__(self, path, name, links, total_size, size_unit): - """""" - self.path = path - self.name = name - self.status = cons.STATUS_PEND - self.links = [] - for url, plugin, type, service in links: - self.links.append(Link(url, plugin, type, service)) - self.progress = 0 - self.total_size = total_size - self.total_size_unit = size_unit - self.actual_size = 0 - self.actual_size_unit = cons.UNIT_KB - self.speed = 0 - self.prev_speed = 0 - self.time = 0 - - def update(self, status=cons.STATUS_STOP, progress=0, actual_size=0, size_unit=cons.UNIT_KB, speed=0, prev_speed=0, time=0): - """""" - self.status = status - self.progress = progress - self.actual_size = actual_size - self.actual_size_unit = size_unit - self.speed = speed - self.prev_speed = prev_speed - self.time = time - -class DownloadManager: - """""" - def __init__(self, get_plugin, services): - """""" - self.services = services - self.get_plugin = get_plugin - self.limits = [] - self.pending_downloads = [] - self.active_downloads = [] - self.complete_downloads = [] - self.timer = None - self.scheduling = False - - def get_limits(self): - """""" - for service in self.services: - if service.anonymous_download_plugin: - if "limit" in dir(service.anonymous_download_plugin): - if service.anonymous_download_plugin.limit: - if service.name not in [name[0] for name in self.limits]: - self.limits.append((service.name, cons.TYPE_ANONYMOUS, "[%s]" % time.strftime("%H:%M"), service.icon_path)) - else: - for limit in self.limits: - if service.name == limit[0]: - self.limits.remove(limit) - return self.limits - - def delete_link(self, name, link): - """""" - for download in self.pending_downloads: - if download.name == name: - for url in download.links: - if link == url.url: - del download.links[download.links.index(url)] - return True - - def get_files(self): - """""" - result = [] - for downloads in [self.pending_downloads, self.active_downloads, self.complete_downloads]: - for download in downloads: - result.append(download) - self.update() - return result - - def clear(self, files): - """""" - for name in files: - complete = [tmp.name for tmp in self.complete_downloads] - if name in complete: - logger.info("Cleared %s" % name) - del self.complete_downloads[complete.index(name)] - - def add(self, path, name, links, total_size, size_unit): - """""" - if name not in [tmp.name for tmp in (self.active_downloads + self.pending_downloads)]: - self.pending_downloads.append(DownloadItem(path, name, links, total_size, size_unit)) - threading.Timer(1, self.scheduler).start() - return True - - def start(self, name): - """""" - for download in self.pending_downloads: - if name == download.name: - download.status = cons.STATUS_WAIT - for link in download.links: - link.plugin, link.type = self.get_plugin(link.service) - if link.plugin.add(download.path, link.url, download.name): - link.active = True - self.active_downloads.append(download) - self.pending_downloads.remove(download) - return True - else: - link.active = False - if not download.status == cons.STATUS_ERROR: - download.status = cons.STATUS_PEND - - def stop(self, name): - """""" - for download in self.pending_downloads: - if name == download.name: - download.status = cons.STATUS_STOP - for download in self.active_downloads: - if name == download.name: - for link in download.links: - if link.active: - if link.plugin.stop(download.name): - if "return_slot" in dir(link.plugin): - link.plugin.return_slot() - link.active = False - self.pending_downloads.append(download) - self.active_downloads.remove(download) - download.update() - return True - - def update(self): - """""" - new_speed = 0 - permanent = True - speeds = [download.speed for download in self.active_downloads if download.status == cons.STATUS_ACTIVE] - current_active = len(speeds) - #print max_downloads, max_download_speed - #print current_active, speeds - remain_speed = max_download_speed - for speed in speeds: - remain_speed -= speed - #print remain_speed - if current_active > 0: - if remain_speed < 0: - new_speed = max_download_speed/current_active - permanent = False - for download in self.active_downloads: - plugin = None - for link in download.links: - if link.active: - plugin = link.plugin - break - if plugin: - if permanent: - if download.speed == 0: - if remain_speed <= 0: - new_speed = 20 - else: - new_speed = remain_speed - elif download.prev_speed >= download.speed: - new_speed = download.prev_speed - if remain_speed - 2 > 0: - new_speed += 2 - remain_speed -= 2 - else: - new_speed += remain_speed - remain_speed = 0 - else: - new_speed = download.speed - status, progress, actual_size, unit, speed, time = plugin.get_status(download.name, new_speed) - #print download.name, status, progress, actual_size, unit, speed, new_speed, time - if status: - download.update(status, progress, actual_size, unit, speed, new_speed, time) - #if status in [cons.STATUS_PEND, cons.STATUS_STOP]: - # logger.warning("%s %s %s %s %s %s %s" % (download.name, status, progress, actual_size, unit, speed, time)) - # if ((status == cons.STATUS_PEND) and ("add_wait" in dir(plugin))): - # plugin.add_wait() - # self.stop(download.name) - if status == cons.STATUS_ERROR: - logger.error("%s %s %s %s %s %s %s" % (download.name, status, progress, actual_size, unit, speed, time)) - if "return_slot" in dir(link.plugin): - plugin.return_slot() - link.active = False - self.pending_downloads.append(download) - self.active_downloads.remove(download) - self.scheduler() - elif status == cons.STATUS_CORRECT: - logger.info("%s %s %s %s %s %s %s" % (download.name, status, progress, actual_size, unit, speed, time)) - if "return_slot" in dir(link.plugin): - plugin.return_slot() - download.progress = 100 - self.complete_downloads.append(download) - self.active_downloads.remove(download) - - def scheduler(self): - """""" - if not self.scheduling: - self.scheduling = True - if len(self.pending_downloads) > 0: - logger.debug("scheduling") - for download in self.pending_downloads: - if len(self.active_downloads) < max_downloads: - if download.status not in [cons.STATUS_STOP]: - if self.start(download.name): - logger.info("Started: %s" % download.name) - logger.debug("Active: %s" % [tmp.name for tmp in self.active_downloads]) - logger.debug("Pending: %s" % [tmp.name for tmp in self.pending_downloads]) - logger.debug("Complete: %s" % [tmp.name for tmp in self.complete_downloads]) - break - if self.timer: - self.timer.cancel() - self.timer = threading.Timer(5, self.scheduler) - self.timer.start() - self.scheduling = False - - def quit(self): - """""" - if self.timer: - self.scheduling = True - self.timer.cancel() - for download in self.active_downloads: - for link in download.links: - link.plugin.stop_all() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/download_plugin.py /tmp/DgSymrsclJ/tucan-0.3.9/download_plugin.py --- tucan-0.3.8/download_plugin.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/download_plugin.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,90 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import time - -from downloader import Downloader - -import cons - -class DownloadPlugin(object): - """""" - def __init__(self): - """""" - self.active_downloads = {} - - def start(self, path, url, file_name, wait=None, cookie=None, post_wait=None): - """""" - if file_name not in self.active_downloads: - th = Downloader(path, url, file_name, wait, cookie, post_wait) - th.start() - self.active_downloads[file_name] = th - return True - - def stop(self, file_name): - """""" - if file_name in self.active_downloads: - while self.active_downloads[file_name].isAlive(): - self.active_downloads[file_name].stop_flag = True - time.sleep(0.1) - del self.active_downloads[file_name] - return True - - def stop_all(self): - """""" - for th in self.active_downloads.values(): - while th.isAlive(): - th.stop_flag = True - - def get_status(self, file_name, speed=0): - """return (status, progress, actual_size, unit, speed, time)""" - result = cons.STATUS_ERROR, 0, 0, None, 0, 0 - th = None - if file_name in self.active_downloads: - th = self.active_downloads[file_name] - if self.active_downloads[file_name].stop_flag: - del self.active_downloads[file_name] - if th: - actual_size, unit = self.get_size(th.actual_size) - if th.status == cons.STATUS_ACTIVE: - progress = int((float(th.actual_size)/float(th.total_size))*100) - th.max_speed = speed - speed = th.speed - if speed > 0: - time = int(float((th.total_size - th.actual_size)/1024)/float(speed)) - else: - time = 0 - else: - progress = 0 - speed = 0 - time = int(th.time_remaining) - result = th.status, progress, actual_size, unit, speed, time - return result - - def get_size(self, num): - """""" - result = 0, cons.UNIT_KB - tmp = int(num/1024) - if tmp > 0: - result = tmp, cons.UNIT_KB - tmp = int(tmp/1024) - if tmp > 0: - result = tmp, cons.UNIT_MB - return result diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/file_chooser.py /tmp/DgSymrsclJ/tucan-0.3.9/file_chooser.py --- tucan-0.3.8/file_chooser.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/file_chooser.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,88 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import os - -import pygtk -pygtk.require('2.0') -import gtk -import gobject - -import cons - -class FileChooser(gtk.FileChooserDialog): - """""" - def __init__(self, parent, func, default_path=None, files=False, save=False): - """""" - gtk.FileChooserDialog.__init__(self, None, parent) - - if default_path: - self.set_current_folder(default_path) - self.history_path = self.get_current_folder() - - if files: - self.set_title(_("Select Files")) - self.set_action(gtk.FILE_CHOOSER_ACTION_OPEN) - self.set_select_multiple(True) - elif save: - self.set_action(gtk.FILE_CHOOSER_ACTION_SAVE) - self.set_title(_("Save As")) - else: - self.set_title(_("Select a Folder")) - self.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) - - hidden_button = gtk.CheckButton(("Show hidden files.")) - hidden_button.set_active(self.get_show_hidden()) - self.vbox.pack_start(hidden_button, False, False, 5) - hidden_button.connect("clicked", self.show_hidden) - - button = gtk.Button(None, gtk.STOCK_CANCEL) - button.connect("clicked", self.close) - self.action_area.pack_start(button) - button = gtk.Button(None, gtk.STOCK_OK) - button.connect("clicked", self.on_choose_folder, func) - self.action_area.pack_start(button) - self.set_position(gtk.WIN_POS_CENTER) - - self.connect("response", self.close) - - self.show_all() - self.run() - - def show_hidden(self, button): - """""" - self.set_show_hidden(button.get_active()) - - def on_choose_folder(self, button, func): - """""" - for file_name in self.get_filenames(): - func(os.path.join(file_name)) - self.close() - - def close(self, widget=None, response=None): - """""" - self.history_path = self.get_current_folder() - self.set_show_hidden(False) - self.destroy() - -if __name__ == "__main__": - def mierda(name): - print name - f = FileChooser(None, mierda, "/home/crak/") diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/gui.py /tmp/DgSymrsclJ/tucan-0.3.9/gui.py --- tucan-0.3.8/gui.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/gui.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,378 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import os -import sys -import time -import threading -import webbrowser -import __builtin__ -import gettext -import logging -logger = logging.getLogger(__name__) - -import pygtk -pygtk.require('2.0') -import gtk -import gobject - -from about import About -from message import Message -from tray_icon import TrayIcon -from preferences import Preferences -from log_view import LogView - -from menu_bar import MenuBar -from toolbar import Toolbar - -import config -from sessions import Sessions -from file_chooser import FileChooser - -from tree import Tree -from input_links import InputLinks - -from service_manager import ServiceManager - -from service_update import ServiceUpdate - -import cons - -class Gui(gtk.Window, ServiceManager): - """""" - def __init__(self, conf): - """""" - #i18n - gettext.bindtextdomain(cons.NAME_LOCALES, cons.PATH_LOCALES) - gettext.textdomain(cons.NAME_LOCALES) - __builtin__._ = gettext.gettext - - #configuration - self.configuration = conf - - #show preferences if not configured - if not self.configuration.configured: - Preferences(self.configuration, True) - self.preferences_shown = False - - #l10n - lang = gettext.translation(cons.NAME_LOCALES, cons.PATH_LOCALES, languages=[self.configuration.get(config.SECTION_MAIN, config.OPTION_LANGUAGE)]) - lang.install() - - ServiceManager.__init__(self, self.configuration) - gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL) - - self.set_icon_from_file(cons.ICON_TUCAN) - self.set_title("%s - Version: %s" % (cons.TUCAN_NAME, cons.TUCAN_VERSION)) - self.set_position(gtk.WIN_POS_CENTER) - self.set_size_request(900, 500) - self.vbox = gtk.VBox() - self.add(self.vbox) - - #menu items - menu_load_session = _("Load Session"), lambda x: FileChooser(self, self.load_session, cons.CONFIG_PATH, True) - menu_save_session = _("Save Session"), lambda x: FileChooser(self, self.save_session, cons.CONFIG_PATH, save=True) - menu_quit = gtk.STOCK_QUIT, self.quit - menu_help = gtk.STOCK_HELP, self.help - menu_about = gtk.STOCK_ABOUT, About - menu_preferences = gtk.STOCK_PREFERENCES, self.preferences - menu_log = _("Show Logs"), LogView - show_uploads = gtk.CheckMenuItem(_("Show Uploads")), self.resize_pane, self.configuration.getboolean(config.SECTION_ADVANCED, config.OPTION_SHOW_UPLOADS) - - #menubar - file_menu = _("File"), [menu_load_session, menu_save_session, None, menu_quit] - view_menu = _("View"), [show_uploads, menu_log, None, menu_preferences] - help_menu = _("Help"), [menu_help, menu_about] - self.vbox.pack_start(MenuBar([file_menu, view_menu, help_menu]), False) - - #toolbar - download = _("Add Downloads"), gtk.image_new_from_file(cons.ICON_DOWNLOAD), self.add_links - upload = _("Add Uploads"), gtk.image_new_from_file(cons.ICON_UPLOAD), self.not_implemented #self.quit - clear = _("Clear Complete"), gtk.image_new_from_file(cons.ICON_CLEAR), self.clear_complete - up = _("Move Up"), gtk.image_new_from_file(cons.ICON_UP), self.move_up - down = _("Move Down"), gtk.image_new_from_file(cons.ICON_DOWN), self.move_down - start = _("Start Selected"), gtk.image_new_from_file(cons.ICON_START), self.start - stop = _("Stop Selected"), gtk.image_new_from_file(cons.ICON_STOP), self.stop - self.vbox.pack_start(Toolbar([download, upload, None, clear, None, up, down, None, start, stop]), False) - - copy = gtk.STOCK_COPY, self.copy_clipboard - delete = gtk.STOCK_REMOVE, self.delete - start = gtk.STOCK_MEDIA_PLAY, self.start - stop = gtk.STOCK_MEDIA_STOP, self.stop - - #trees - self.downloads = Tree([copy, None, delete], self.download_manager) - #self.uploads = Tree() - self.uploads = gtk.VBox() - - #sessions - self.session = Sessions() - if self.configuration.getboolean(config.SECTION_ADVANCED, config.OPTION_SAVE_SESSION): - self.load_default_session() - else: - if os.path.exists(cons.SESSION_FILE): - title = _("Tucan Manager - Restore previous session.") - message = _("Your last session closed unexpectedly.\nTucan will try to restore it now.") - m = Message(None, cons.SEVERITY_WARNING, title, message, both=True) - if m.accepted: - self.load_default_session() - - #pane - self.pane = gtk.VPaned() - self.vbox.pack_start(self.pane) - self.pane.pack1(self.downloads, True) - self.pane.pack2(self.uploads, True) - self.pane.set_position(self.get_size()[1]) - - self.connect("key-press-event", self.delete_key) - - if self.configuration.getboolean(config.SECTION_ADVANCED, config.OPTION_TRAY_CLOSE): - self.connect("delete_event", self.hide_on_delete) - else: - self.connect("delete_event", self.quit) - - self.show_all() - - #trayicon - tray_menu = [menu_preferences, menu_about, None, menu_quit] - self.tray_icon = TrayIcon(self.show, self.hide, tray_menu) - self.connect("hide", self.tray_icon.activate) - self.downloads.status_bar.connect("text-pushed", self.tray_icon.change_tooltip) - - #Autocheck services - if self.configuration.getboolean(config.SECTION_ADVANCED, config.OPTION_AUTO_UPDATE): - th = threading.Thread(group=None, target=self.check_updates, name=None) - th.start() - - #ugly polling - gobject.timeout_add(120000, self.save_default_session) - - def check_updates(self): - """""" - s = ServiceUpdate(self.configuration) - updates = s.get_updates() - if len(updates) > 0: - gobject.idle_add(self.update_manager, updates) - - def update_manager(self, updates): - """""" - if not self.preferences_shown: - self.preferences_shown = True - Preferences(self.configuration, True, updates) - self.preferences_shown = False - return False - - def delete_key(self, window, event): - """pressed del key""" - if event.keyval == 65535: - self.delete() - - def preferences(self, button=None): - """""" - if not self.preferences_shown: - self.preferences_shown = True - Preferences(self.configuration) - #sincronice statusbar - self.downloads.status_bar.synchronize() - self.preferences_shown = False - - def not_implemented(self, widget): - """""" - w = Message(self, cons.SEVERITY_WARNING, "Not Implemented!", "The functionality you are trying to use is not implemented yet.") - - def resize_pane(self, checkbox): - """""" - if checkbox.get_active(): - self.pane.set_position(-1) - else: - self.pane.set_position(self.get_size()[1]) - - def help(self, widget): - """""" - webbrowser.open(cons.DOC) - - def add_links(self, button): - """""" - default_path = self.configuration.get(config.SECTION_MAIN, config.OPTION_DOWNLOADS_FOLDER) - show_advanced_packages = self.configuration.getboolean(config.SECTION_ADVANCED, config.OPTION_ADVANCED_PACKAGES) - InputLinks(default_path, self.filter_service, self.get_check_links, self.create_packages, self.manage_packages, show_advanced_packages) - - def copy_clipboard(self, button): - """""" - model, iter = self.downloads.treeview.get_selection().get_selected() - if iter: - link_list = self.downloads.get_links(iter) - clipboard = gtk.Clipboard() - clipboard.clear() - clipboard.set_text("\n".join(link_list)) - - def load_session(self, path): - """""" - try: - packages, info = self.session.load_session(path) - if packages != None: - self.manage_packages(packages, info) - logger.debug("Session loaded: %s" % info) - except Exception, e: - logger.exception("Session not loaded: %s" % e) - gobject.idle_add(self.session_error) - - def session_error(self): - """""" - title = _("Tucan Manager - Session Error.") - message = _("There was a problem loading the last session. Links are unrecoverable.") - Message(self, cons.SEVERITY_ERROR, title, message) - - def save_session(self, path): - """""" - packages, info = self.downloads.get_packages() - self.session.save_session(path, packages, info) - logger.debug("Session saved: %s" % info) - - def load_default_session(self): - """""" - self.load_session(cons.SESSION_FILE) - - def save_default_session(self): - """""" - self.save_session(cons.SESSION_FILE) - return True - - def manage_packages(self, packages, packages_info): - """""" - tmp_packages = [] - if not len(packages_info) > 0: - default_path = self.configuration.get(config.SECTION_MAIN, config.OPTION_DOWNLOADS_FOLDER) - packages_info = [(default_path, name, None) for name, package_files in packages] - #create directories and password files - for info in packages_info: - package_path = unicode(os.path.join(info[0], info[1].replace(" ", "_"), "")) - if not os.path.exists(package_path): - os.mkdir(package_path) - if info[2]: - f = open(package_path + "password.txt", "w") - f.write(info[2] + "\n") - f.close() - #add packages to gui and manager - for package_name, package_downloads in packages: - info = packages_info[packages.index((package_name, package_downloads))] - package_name = info[1].replace(" ", "_") - package_path = os.path.join(info[0], package_name, "") - self.downloads.add_package(package_name, package_path, package_downloads, info[2]) - for download in package_downloads: - tmp = [] - for service in download[2]: - plugin, plugin_type = self.get_download_plugin(service) - tmp.append((download[0][download[2].index(service)], plugin, plugin_type, service)) - self.download_manager.add(package_path, download[1], tmp, download[3], download[4]) - - def start(self, button): - """Implementado solo para descargas""" - model, paths = self.downloads.treeview.get_selection().get_selected_rows() - if len(paths) > 0: - if len(paths[0]) > 1: - logger.info("Start file: %s" % self.download_manager.start(model.get_value(model.get_iter(paths[0]), 3))) - else: - logger.info("Start package.") - for item in self.downloads.package_files(model.get_iter(paths[0])): - self.download_manager.start(item) - - def stop(self, button): - """Implementado solo para descargas""" - model, paths = self.downloads.treeview.get_selection().get_selected_rows() - if len(paths) > 0: - if len(paths[0]) > 1: - logger.info("Stop file: %s" % self.download_manager.stop(model.get_value(model.get_iter(paths[0]), 3))) - else: - logger.info("Stop package.") - for item in self.downloads.package_files(model.get_iter(paths[0])): - self.download_manager.stop(item) - - def clear_complete(self, button): - """Implementado solo para descargas""" - files = self.downloads.clear() - logger.info("Cleared: %s" % files) - if len(files) > 0: - self.download_manager.clear(files) - - def move_up(self, button): - """Implementado solo para descargas""" - model, paths = self.downloads.treeview.get_selection().get_selected_rows() - if len(paths) > 0: - if not len(paths[0]) > 1: - logger.info("Move up: %s" % self.downloads.move_up(model.get_iter(paths[0]))) - - def move_down(self, button): - """Implementado solo para descargas""" - model, paths = self.downloads.treeview.get_selection().get_selected_rows() - if len(paths) > 0: - if not len(paths[0]) > 1: - logger.info("Move down: %s" % self.downloads.move_down(model.get_iter(paths[0]))) - - def delete(self, button=None): - """Implementado solo para descargas""" - model, paths = self.downloads.treeview.get_selection().get_selected_rows() - status = [cons.STATUS_STOP, cons.STATUS_PEND, cons.STATUS_ERROR] - if len(paths) > 0: - if len(paths[0]) > 2: - name, link = self.downloads.delete_link(status, model.get_iter(paths[0])) - if link: - logger.warning("Remove %s: %s" % (link, self.download_manager.delete_link(name, link))) - elif len(paths[0]) > 1: - name = self.downloads.delete_file(status, model.get_iter(paths[0])) - if name: - logger.warning("Remove %s: %s" % (name, self.download_manager.clear([name]))) - else: - files = self.downloads.delete_package(status, model.get_iter(paths[0])) - if len(files) > 0: - logger.warning("Remove package: %s" % self.download_manager.clear(files)) - - def quit(self, dialog=None, response=None): - """""" - if len(self.download_manager.active_downloads) > 0: - message = "Tucan still has active downloads.\n Are you sure you want to quit?" - m = Message(self, cons.SEVERITY_WARNING, "Tucan Manager - Active Downloads.", message, True, True) - if m.accepted: - self.close() - else: - #This way GTK won't destroy the window. - return True - else: - self.close() - - def close(self): - """""" - if self.configuration.getboolean(config.SECTION_ADVANCED, config.OPTION_SAVE_SESSION): - self.save_default_session() - else: - try: - os.remove(cons.SESSION_FILE) - except Exception, e: - logger.info(e) - self.hide() - self.tray_icon.set_visible(False) - self.stop_all() - gtk.main_quit() - tucan_exit(0) - -if __name__ == "__main__": - g = Gui() - gobject.threads_init() - gtk.main() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/i18n/cs/cs.po /tmp/DgSymrsclJ/tucan-0.3.9/i18n/cs/cs.po --- tucan-0.3.8/i18n/cs/cs.po 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/i18n/cs/cs.po 2009-10-07 00:02:27.000000000 +0100 @@ -0,0 +1,180 @@ +# Tucan Manager. +# Copyright (C) 2008-2009 The Tucan Project. +# Krtek , 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: 0.3\n" +"POT-Creation-Date: 2009-01-10 04:03+CET\n" +"PO-Revision-Date: 2009-07-27 02:07+GTM+1\n" +"Last-Translator: Krtek \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Generated-By: pygettext.py 1.5\n" + + +#: ./advanced_packages.py:37 +msgid "Advanced Packages" +msgstr "Rozšířené balíÄky" + +#: ./advanced_packages.py:96 +msgid "Choose new path for selected Package." +msgstr "Vyberte nové umístÄ›ní pro vybrané balíÄky." + +#: ./file_chooser.py:33 +msgid "Select a Folder" +msgstr "Vybrat složku" + +#: ./file_chooser.py:40 +msgid "Show hidden files." +msgstr "Ukázat skryté soubory." + +#: ./gui.py:84 +msgid "Load Session" +msgstr "Nahrát sezení" + +#: ./gui.py:85 +msgid "Save Session" +msgstr "Uložit sezení" + +#: ./gui.py:90 +msgid "Show Uploads" +msgstr "Ukázat nahrávané" + +#: ./gui.py:93 +msgid "File" +msgstr "Soubor" + +#: ./gui.py:94 +msgid "View" +msgstr "Pohled" + +#: ./gui.py:95 +msgid "Help" +msgstr "NápovÄ›da" + +#: ./gui.py:99 +msgid "Add Downloads" +msgstr "PÅ™idat stahované" + +#: ./gui.py:100 +msgid "Add Uploads" +msgstr "PÅ™idat nahrávané" + +#: ./gui.py:101 +msgid "Clear Complete" +msgstr "VyÄiÅ¡tit dokonÄené" + +#: ./gui.py:102 +msgid "Move Up" +msgstr "Posunout nahoru" + +#: ./gui.py:103 +msgid "Move Down" +msgstr "Posunout dolů" + +#: ./gui.py:104 +msgid "Start Selected" +msgstr "Zahájit vybrané" + +#: ./gui.py:105 +msgid "Stop Selected" +msgstr "Zastavit vybrané" + +#: ./input_links.py:54 +msgid "Input Links" +msgstr "Vložené odkazy" + +#: ./input_links.py:69 +msgid "Paste links here:" +msgstr "Vložte odkazy zde:" + +#: ./input_links.py:88 +msgid "Check Links" +msgstr "Zkontrolovat odkazy" + +#: ./input_links.py:131 +msgid "Show advanced Package configuration." +msgstr "Ukázat rozšířené nastavení balíÄku." + +#: ./input_links.py:207 +msgid "Checking links, please wait." +msgstr "Kontrola odkazů, prosím Äekejte." + +#: ./input_links.py:260 +msgid "Check Canceled!" +msgstr "Kontrola pÅ™eruÅ¡ena!" + +#: ./preferences.py:54 +msgid "General Configuration" +msgstr "Obecné nastavení" + +#: ./preferences.py:55 +msgid "Service Configuration" +msgstr "Nastavení služby" + +#: ./preferences.py:56 +msgid "Advanced Configuration" +msgstr "Rozšířené nastavení" + +#: ./preferences.py:120 +msgid "Choose language: " +msgstr "Vyberte jazyk: " + +#: ./preferences.py:138 +msgid "Max simultaneous downloads: " +msgstr "Maximum stahování zároveň: " + +#: ./preferences.py:173 +msgid "Downloads Folder: " +msgstr "Složka stahování: " + +#: ./preferences.py:260 +msgid "Restart Tucan to apply service changes." +msgstr "Restartujte Tucana, aby se zmÄ›ny projevily." + +#: ./preferences.py:279 +msgid "The choosed directory isn't a service, or it's not configured." +msgstr "Vybraný adresář není službou nebo není nastaven." + +#: ./preferences.py:307 +msgid "Before using this service, you must accept it's terms of service at " +msgstr "PÅ™ed používáním této služby musíte souhlasit s podmínkami služby na " + +#: ./preferences.py:308 +msgid "Terms of service" +msgstr "Podmínky služby" + +#: ./preferences.py:331 +msgid "Close to tray." +msgstr "Zavřít do panelu." + +#: ./preferences.py:335 +msgid "Save session on close." +msgstr "Uložit sezení pÅ™i odchodu." + +#: ./preferences.py:339 +msgid "Default advanced packages." +msgstr "Původní rozšířené nastavení." + +#: ./preferences.py:343 +msgid "Show uploads." +msgstr "Ukázat nahrávané." + +#: ./service_preferences.py:47 +msgid "Author" +msgstr "Autor" + +#: ./service_preferences.py:55 +msgid "Version" +msgstr "Verze" + +#: ./service_preferences.py:64 +msgid "Slots" +msgstr "Sloty" + +#: ./service_preferences.py:71 +msgid "Captcha" +msgstr "Captcha" Binary files /tmp/Mj7pJvsoYS/tucan-0.3.8/i18n/cs/LC_MESSAGES/tucan.mo and /tmp/DgSymrsclJ/tucan-0.3.9/i18n/cs/LC_MESSAGES/tucan.mo differ diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/i18n/de/de.po /tmp/DgSymrsclJ/tucan-0.3.9/i18n/de/de.po --- tucan-0.3.8/i18n/de/de.po 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/i18n/de/de.po 2009-10-07 00:02:27.000000000 +0100 @@ -10,8 +10,8 @@ "Last-Translator: c455\n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: utf-8\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: UTF-8\n" "Generated-By: pygettext.py 1.5\n" @@ -21,7 +21,7 @@ #: ./advanced_packages.py:96 msgid "Choose new path for selected Package." -msgstr "Wähle einen neuen Pfad für das gewählte Paket" +msgstr "Wähle einen neuen Pfad für das gewählte Paket." #: ./file_chooser.py:33 msgid "Select a Folder" @@ -141,7 +141,7 @@ #: ./preferences.py:307 msgid "Before using this service, you must accept it's terms of service at " -msgstr "Bevor dieser Service genutzt wird, müssen folgende Nutzungsbedingungen akzeptiert werden" +msgstr "Bevor dieser Service genutzt wird, müssen folgende Nutzungsbedingungen akzeptiert werden " #: ./preferences.py:308 msgid "Terms of service" Binary files /tmp/Mj7pJvsoYS/tucan-0.3.8/i18n/de/LC_MESSAGES/tucan.mo and /tmp/DgSymrsclJ/tucan-0.3.9/i18n/de/LC_MESSAGES/tucan.mo differ diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/i18n/fr/fr.po /tmp/DgSymrsclJ/tucan-0.3.9/i18n/fr/fr.po --- tucan-0.3.8/i18n/fr/fr.po 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/i18n/fr/fr.po 2009-10-07 00:02:27.000000000 +0100 @@ -1,32 +1,35 @@ # Tucan Manager. # Copyright (C) 2008-2009 The Tucan Project. -# Crak, 2009. +# Mathieu Divaret , 2009. # msgid "" msgstr "" -"Project-Id-Version: 0.3\n" -"POT-Creation-Date: 2009-01-10 04:03+CET\n" -"Last-Translator: Mathieu Divaret \n" -"Language-Team: \n" +"Project-Id-Version: 0.3.7\n" +"POT-Creation-Date: 2009-06-09 01:40+CET\n" +"PO-Revision-Date: 2009-06-09 01:50+CET\n" +"Last-Translator: Guilhem LETTRON \n" +"Language-Team: FRENCH \n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf8\n" -"Content-Transfer-Encoding: utf-8\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: UTF-8\n" +"Generated-By: pygettext.py 1.5\n" + #: ./advanced_packages.py:37 msgid "Advanced Packages" -msgstr "Paquets avancés" +msgstr "Gestion avancée" #: ./advanced_packages.py:96 msgid "Choose new path for selected Package." -msgstr "Choisissez un nouvel emplacement pour le paquet sélectionné" +msgstr "Choisir un nouvel emplacement pour le paquet sélectionné." #: ./file_chooser.py:33 msgid "Select a Folder" -msgstr "Choisissez un dossier" +msgstr "Sélectionnez un dossier" #: ./file_chooser.py:40 msgid "Show hidden files." -msgstr "Montrer les fichiers cachés." +msgstr "Voir les fichiers cachés." #: ./gui.py:84 msgid "Load Session" @@ -34,11 +37,11 @@ #: ./gui.py:85 msgid "Save Session" -msgstr "Sauvegarder une session" +msgstr "Sauver une session" #: ./gui.py:90 msgid "Show Uploads" -msgstr "Montrer les fichiers en partagés" +msgstr "Voir les envois" #: ./gui.py:93 msgid "File" @@ -54,15 +57,15 @@ #: ./gui.py:99 msgid "Add Downloads" -msgstr "Ajouter des fichiers à télécharger" +msgstr "Télécharger" #: ./gui.py:100 msgid "Add Uploads" -msgstr "Ajouter des fichiers à partager" +msgstr "Envoyer" #: ./gui.py:101 msgid "Clear Complete" -msgstr "Effacer les fichiers complets" +msgstr "Effacer les complets" #: ./gui.py:102 msgid "Move Up" @@ -74,19 +77,19 @@ #: ./gui.py:104 msgid "Start Selected" -msgstr "Démarrer les fichiers sélectionnés" +msgstr "Lancer" #: ./gui.py:105 msgid "Stop Selected" -msgstr "Arrêter les fichiers sélectionnés" +msgstr "Arrêter" #: ./input_links.py:54 msgid "Input Links" -msgstr "Insérer les liens" +msgstr "Insertion des liens" #: ./input_links.py:69 msgid "Paste links here:" -msgstr "Copier les liens ici:" +msgstr "Collez les liens ici:" #: ./input_links.py:88 msgid "Check Links" @@ -94,15 +97,15 @@ #: ./input_links.py:131 msgid "Show advanced Package configuration." -msgstr "Montrer la configuration des paquets avancés." +msgstr "Voir la gestion avancée." #: ./input_links.py:207 msgid "Checking links, please wait." -msgstr "Liens en cours de vérification, merci de patienter." +msgstr "Vérification des liens en cours." #: ./input_links.py:260 msgid "Check Canceled!" -msgstr "Vérification annulée!" +msgstr "Vérification annulée" #: ./preferences.py:54 msgid "General Configuration" @@ -114,39 +117,39 @@ #: ./preferences.py:56 msgid "Advanced Configuration" -msgstr "Configuration avancée" +msgstr "Gestion avancée" #: ./preferences.py:120 msgid "Choose language: " -msgstr "Choisissez la langue: " +msgstr "Choisissez une langue: " #: ./preferences.py:138 msgid "Max simultaneous downloads: " -msgstr "Nombre de téléchargements simultanés maximum: " +msgstr "Téléchargement simultanés Max: " #: ./preferences.py:173 msgid "Downloads Folder: " -msgstr "Dossier de réception: " +msgstr "Dossier destination: " #: ./preferences.py:260 msgid "Restart Tucan to apply service changes." -msgstr "Redémarrer Tucan pour appliquer les modifications." +msgstr "Redémarrez Tucan pour appliquer changements." #: ./preferences.py:279 msgid "The choosed directory isn't a service, or it's not configured." -msgstr "Le répertoire choisi n'est pas un service, où il n'est pas configuré." +msgstr "Le dossier choisi n'est pas un service ou n'est pas configuré." #: ./preferences.py:307 msgid "Before using this service, you must accept it's terms of service at " -msgstr "Avant d'utiliser ce service, vous devez en accepter les conditions d'utilisation" +msgstr "Avant d'utiliser ce service, vous devez accepter les conditions d'utilisation à " #: ./preferences.py:308 msgid "Terms of service" -msgstr "Conditions d'utilisation du service" +msgstr "Conditions d'utilisation" #: ./preferences.py:331 msgid "Close to tray." -msgstr "Minimiser dans la barre de tâches." +msgstr "Fermer dans la barre de tache." #: ./preferences.py:335 msgid "Save session on close." @@ -154,11 +157,11 @@ #: ./preferences.py:339 msgid "Default advanced packages." -msgstr "Paquets avancés par défaut." +msgstr "Gestion avancée par défaut." #: ./preferences.py:343 msgid "Show uploads." -msgstr "Montrer les fichiers partagés." +msgstr "Voir les envois par défaut." #: ./service_preferences.py:47 msgid "Author" @@ -170,8 +173,8 @@ #: ./service_preferences.py:64 msgid "Slots" -msgstr "Nombre de fichiers téléchargeables au même moment" +msgstr "Emplacements" #: ./service_preferences.py:71 msgid "Captcha" -msgstr "Captcha" +msgstr "Visuel protégé" Binary files /tmp/Mj7pJvsoYS/tucan-0.3.8/i18n/fr/LC_MESSAGES/tucan.mo and /tmp/DgSymrsclJ/tucan-0.3.9/i18n/fr/LC_MESSAGES/tucan.mo differ diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/i18n/gr/gr.po /tmp/DgSymrsclJ/tucan-0.3.9/i18n/gr/gr.po --- tucan-0.3.8/i18n/gr/gr.po 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/i18n/gr/gr.po 2009-10-07 00:02:27.000000000 +0100 @@ -0,0 +1,180 @@ +# Tucan Manager. +# Copyright (C) 2008-2009 The Tucan Project. +# , 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: 0.3\n" +"POT-Creation-Date: 2009-01-11 22:54+CET\n" +"PO-Revision-Date: 2009-10-04 22:10+CET\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: UTF-8\n" +"Generated-By: pygettext.py 1.5\n" + + +#: ./advanced_packages.py:37 +msgid "Advanced Packages" +msgstr "Πακέτα για Ï€ÏοχωÏημένους" + +#: ./advanced_packages.py:96 +msgid "Choose new path for selected Package." +msgstr "Επιλογή νέας τοποθεσίας για ετα επιλεγμένα πακέτα." + +#: ./file_chooser.py:33 +msgid "Select a Folder" +msgstr "Επιλέξτε Φάκελο" + +#: ./file_chooser.py:40 +msgid "Show hidden files." +msgstr "ΠÏοβάλετε ΚÏυφά ΑÏχεία." + +#: ./gui.py:84 +msgid "Load Session" +msgstr "ΦόÏτωση ΕÏγασίας" + +#: ./gui.py:85 +msgid "Save Session" +msgstr "Αποθήκευση ΕÏγασίας" + +#: ./gui.py:90 +msgid "Show Uploads" +msgstr "ΠÏοβολή Απεσταλμένων" + +#: ./gui.py:93 +msgid "File" +msgstr "ΑÏχείο" + +#: ./gui.py:94 +msgid "View" +msgstr "ΠÏοβολή" + +#: ./gui.py:95 +msgid "Help" +msgstr "Βοήθεια" + +#: ./gui.py:99 +msgid "Add Downloads" +msgstr "ΠÏοσθέστε ΑÏχεία για Λήψη" + +#: ./gui.py:100 +msgid "Add Uploads" +msgstr "ΠÏοσθέστε ΑÏχεία για Αποστολή" + +#: ./gui.py:101 +msgid "Clear Complete" +msgstr "ΟλοκλήÏωση ΚαθαÏισμοÏ" + +#: ./gui.py:102 +msgid "Move Up" +msgstr "Μετακίνηση Επάνω" + +#: ./gui.py:103 +msgid "Move Down" +msgstr "Μετακίνηση Κάτω" + +#: ./gui.py:104 +msgid "Start Selected" +msgstr "Εκκίνηση Επιλεγμένων" + +#: ./gui.py:105 +msgid "Stop Selected" +msgstr "Σταμάτημα Επιλεγμένων" + +#: ./input_links.py:54 +msgid "Input Links" +msgstr "Εισαγωγή ΔιεÏθυνσης" + +#: ./input_links.py:69 +msgid "Paste links here:" +msgstr "Επικολλήση ΔιευθÏνσεων:" + +#: ./input_links.py:88 +msgid "Check Links" +msgstr "Έλεγχος ΔιευθÏνσεων" + +#: ./input_links.py:131 +msgid "Show advanced Package configuration." +msgstr "" + +#: ./input_links.py:207 +msgid "Checking links, please wait." +msgstr "ΠαÏακαλώ ΠεÏιμένετε, Γίνετε ΕξακÏίβωση ΔιευθÏνσεων." + +#: ./input_links.py:260 +msgid "Check Canceled!" +msgstr "ΑκÏÏωση Ελέγχου" + +#: ./preferences.py:54 +msgid "General Configuration" +msgstr "Γενικές Ρυθμίσεις" + +#: ./preferences.py:55 +msgid "Service Configuration" +msgstr "Ρυθμίσεις ΥπηÏεσιών" + +#: ./preferences.py:56 +msgid "Advanced Configuration" +msgstr "Εξειδικευμένες Ρυθμίσεις" + +#: ./preferences.py:120 +msgid "Choose language: " +msgstr "Επιλογή Γλώσσας: " + +#: ./preferences.py:138 +msgid "Max simultaneous downloads: " +msgstr "ΤαυτόχÏονες Λήψεις: " + +#: ./preferences.py:173 +msgid "Downloads Folder: " +msgstr "Φάκελος Λήψεων: " + +#: ./preferences.py:260 +msgid "Restart Tucan to apply service changes." +msgstr "Επαννεκίνηση του Ï€ÏογÏάμματος για εφαÏμογή των Ïυθμίσεων." + +#: ./preferences.py:279 +msgid "The choosed directory isn't a service, or it's not configured." +msgstr "Ο επιλεγμένος φάκελος δεν ισχÏει ή δεν είναι Ïυθμισμένος." + +#: ./preferences.py:307 +msgid "Before using this service, you must accept it's terms of service at " +msgstr "ΠÏίν χÏεισιμοποιήσετε την υπηÏεσία Ï€Ïέπει να αποδεχτήτε τους ÏŒÏους " + +#: ./preferences.py:308 +msgid "Terms of service" +msgstr "ÎŒÏοι ΧÏήσης" + +#: ./preferences.py:331 +msgid "Close to tray." +msgstr "Κλείσιμο στη μπάÏα." + +#: ./preferences.py:335 +msgid "Save session on close." +msgstr "Αποθήκευση κατα το κλείσιμο." + +#: ./preferences.py:339 +msgid "Default advanced packages." +msgstr "ΠÏοεπιλεγμένες Ρυθμίσεις." + +#: ./preferences.py:343 +msgid "Show uploads." +msgstr "ΠÏοβολή Απεσταλμένων." + +#: ./service_preferences.py:47 +msgid "Author" +msgstr "ΣυγγÏαφέας" + +#: ./service_preferences.py:55 +msgid "Version" +msgstr "Έκδοση" + +#: ./service_preferences.py:64 +msgid "Slots" +msgstr "ΘÏÏες" + +#: ./service_preferences.py:71 +msgid "Captcha" +msgstr "Captcha" Binary files /tmp/Mj7pJvsoYS/tucan-0.3.8/i18n/gr/LC_MESSAGES/tucan.mo and /tmp/DgSymrsclJ/tucan-0.3.9/i18n/gr/LC_MESSAGES/tucan.mo differ diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/i18n/it/it.po /tmp/DgSymrsclJ/tucan-0.3.9/i18n/it/it.po --- tucan-0.3.8/i18n/it/it.po 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/i18n/it/it.po 2009-10-07 00:02:27.000000000 +0100 @@ -1,6 +1,6 @@ # Tucan Manager. -# Copyright (C) 2009 Tucan Project. -# Crak, 2009. +# Copyright (C) 2008-2009 The Tucan Project. +# kir, 2009. # msgid "" msgstr "" @@ -10,8 +10,8 @@ "Last-Translator: kir & cionci\n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: utf-8\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: UTF-8\n" "Generated-By: pygettext.py 1.5\n" @@ -29,7 +29,7 @@ #: ./gui.py:70 msgid "Load Session" -msgstr "Carica Sessione" +msgstr "Carica Sessione" #: ./gui.py:71 msgid "Save Session" Binary files /tmp/Mj7pJvsoYS/tucan-0.3.8/i18n/it/LC_MESSAGES/tucan.mo and /tmp/DgSymrsclJ/tucan-0.3.9/i18n/it/LC_MESSAGES/tucan.mo differ Binary files /tmp/Mj7pJvsoYS/tucan-0.3.8/i18n/pl/LC_MESSAGES/tucan.mo and /tmp/DgSymrsclJ/tucan-0.3.9/i18n/pl/LC_MESSAGES/tucan.mo differ diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/i18n/pl/pl.po /tmp/DgSymrsclJ/tucan-0.3.9/i18n/pl/pl.po --- tucan-0.3.8/i18n/pl/pl.po 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/i18n/pl/pl.po 2009-10-07 00:02:27.000000000 +0100 @@ -1,17 +1,17 @@ # Tucan Manager. # Copyright (C) 2008-2009 The Tucan Project. -# Translated by exc1te.org 2009. +# exc1te.org , 2009. # msgid "" msgstr "" "Project-Id-Version: 0.3\n" "POT-Creation-Date: 2009-01-10 04:03+CET\n" "PO-Revision-Date: 2009-01-10 04:32+CET\n" -"Last-Translator: ErNi_\n" -"Language-Team: exc1te \n" +"Last-Translator: exc1te.org \n" +"Language-Team: exc1te \n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: ISO-8859-2\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: UTF-8\n" "Generated-By: pygettext.py 1.5\n" Binary files /tmp/Mj7pJvsoYS/tucan-0.3.8/i18n/pt/LC_MESSAGES/tucan.mo and /tmp/DgSymrsclJ/tucan-0.3.9/i18n/pt/LC_MESSAGES/tucan.mo differ diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/i18n/pt/pt.po /tmp/DgSymrsclJ/tucan-0.3.9/i18n/pt/pt.po --- tucan-0.3.8/i18n/pt/pt.po 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/i18n/pt/pt.po 2009-10-07 00:02:27.000000000 +0100 @@ -1,18 +1,19 @@ # Tucan Manager. # Copyright (C) 2008-2009 The Tucan Project. -# Carlos Pais, 2009. +# Carlos Pais , 2009. # msgid "" msgstr "" "Project-Id-Version: 0.3\n" "POT-Creation-Date: 2009-04-17 22:54+CET\n" "POT-Creation-Date: 2009-04-17 22:54+CET\n" -"Last-Translator: Carlos Pais \n" +"Last-Translator: Carlos Pais \n" "PO-Revision-Date: \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" +"Content-Transfer-Encoding: UTF-8\n" + #: ./advanced_packages.py:37 msgid "Advanced Packages" @@ -20,7 +21,7 @@ #: ./advanced_packages.py:96 msgid "Choose new path for selected Package." -msgstr "Escolha um novo caminho para o Pacote seleccionado" +msgstr "Escolha um novo caminho para o Pacote seleccionado." #: ./file_chooser.py:33 msgid "Select a Folder" @@ -28,7 +29,7 @@ #: ./file_chooser.py:40 msgid "Show hidden files." -msgstr "Mostrar ficheiros escondidos" +msgstr "Mostrar ficheiros escondidos." #: ./gui.py:84 msgid "Load Session" @@ -88,7 +89,7 @@ #: ./input_links.py:69 msgid "Paste links here:" -msgstr "Colar links aqui" +msgstr "Colar links aqui:" #: ./input_links.py:88 msgid "Check Links" @@ -96,11 +97,11 @@ #: ./input_links.py:131 msgid "Show advanced Package configuration." -msgstr "Mostrar configuração avanaçada de pacotes" +msgstr "Mostrar configuração avanaçada de pacotes." #: ./input_links.py:207 msgid "Checking links, please wait." -msgstr "A verificar links, por favor espere" +msgstr "A verificar links, por favor espere." #: ./input_links.py:260 msgid "Check Canceled!" @@ -120,23 +121,23 @@ #: ./preferences.py:120 msgid "Choose language: " -msgstr "Escolha a língua" +msgstr "Escolha a língua: " #: ./preferences.py:138 msgid "Max simultaneous downloads: " -msgstr "Max downloads simultâneos" +msgstr "Max downloads simultâneos: " #: ./preferences.py:173 msgid "Downloads Folder: " -msgstr "Pasta de Downloads" +msgstr "Pasta de Downloads: " #: ./preferences.py:260 msgid "Restart Tucan to apply service changes." -msgstr "Reiniciar Tucan para aplicar as alterações de serviço" +msgstr "Reiniciar Tucan para aplicar as alterações de serviço." #: ./preferences.py:279 msgid "The choosed directory isn't a service, or it's not configured." -msgstr "A directoria escolhida não é um serviço ou não está configurada" +msgstr "A directoria escolhida não é um serviço ou não está configurada." #: ./preferences.py:307 msgid "Before using this service, you must accept it's terms of service at " @@ -148,19 +149,19 @@ #: ./preferences.py:331 msgid "Close to tray." -msgstr "Fechar para tray" +msgstr "Fechar para tray." #: ./preferences.py:335 msgid "Save session on close." -msgstr "Salvar sessão ao fechar" +msgstr "Salvar sessão ao fechar." #: ./preferences.py:339 msgid "Default advanced packages." -msgstr "Pacotes avançados originais" +msgstr "Pacotes avançados originais." #: ./preferences.py:343 msgid "Show uploads." -msgstr "Mostrar uploads" +msgstr "Mostrar uploads." #: ./service_preferences.py:47 msgid "Author" @@ -177,4 +178,3 @@ #: ./service_preferences.py:71 msgid "Captcha" msgstr "Captcha" - Binary files /tmp/Mj7pJvsoYS/tucan-0.3.8/i18n/ru/LC_MESSAGES/tucan.mo and /tmp/DgSymrsclJ/tucan-0.3.9/i18n/ru/LC_MESSAGES/tucan.mo differ diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/i18n/ru/ru.po /tmp/DgSymrsclJ/tucan-0.3.9/i18n/ru/ru.po --- tucan-0.3.8/i18n/ru/ru.po 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/i18n/ru/ru.po 2009-10-07 00:02:27.000000000 +0100 @@ -0,0 +1,180 @@ +# Tucan Manager. +# Copyright (C) 2008-2009 The Tucan Project. +# Paul Somebody , 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: 0.3.7\n" +"POT-Creation-Date: 2009-01-11 22:54+CET\n" +"PO-Revision-Date: 2009-07-22 02:44+CET\n" +"Last-Translator: Paul Somebody \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: UTF-8\n" +"Generated-By: pygettext.py 1.5\n" + + +#: ./advanced_packages.py:37 +msgid "Advanced Packages" +msgstr "Дополнительные пакеты" + +#: ./advanced_packages.py:96 +msgid "Choose new path for selected Package." +msgstr "Выберите новый путь Ð´Ð»Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð³Ð¾ пакета." + +#: ./file_chooser.py:33 +msgid "Select a Folder" +msgstr "Выберите папку" + +#: ./file_chooser.py:40 +msgid "Show hidden files." +msgstr "Показывать Ñкрытые файлы." + +#: ./gui.py:84 +msgid "Load Session" +msgstr "Загрузить ÑеÑÑию" + +#: ./gui.py:85 +msgid "Save Session" +msgstr "Сохранить ÑеÑÑию" + +#: ./gui.py:90 +msgid "Show Uploads" +msgstr "Показывать закачки" + +#: ./gui.py:93 +msgid "File" +msgstr "Файл" + +#: ./gui.py:94 +msgid "View" +msgstr "Вид" + +#: ./gui.py:95 +msgid "Help" +msgstr "Помощь" + +#: ./gui.py:99 +msgid "Add Downloads" +msgstr "Добавить загрузки" + +#: ./gui.py:100 +msgid "Add Uploads" +msgstr "Добавить закачки" + +#: ./gui.py:101 +msgid "Clear Complete" +msgstr "Удалить завершенные" + +#: ./gui.py:102 +msgid "Move Up" +msgstr "Выше" + +#: ./gui.py:103 +msgid "Move Down" +msgstr "Ðиже" + +#: ./gui.py:104 +msgid "Start Selected" +msgstr "ЗапуÑтить выбранные" + +#: ./gui.py:105 +msgid "Stop Selected" +msgstr "ОÑтановить выбранные" + +#: ./input_links.py:54 +msgid "Input Links" +msgstr "ВходÑщие ÑÑылки" + +#: ./input_links.py:69 +msgid "Paste links here:" +msgstr "Скопируйте ÑÑылки Ñюда." + +#: ./input_links.py:88 +msgid "Check Links" +msgstr "Проверить ÑÑылки" + +#: ./input_links.py:131 +msgid "Show advanced Package configuration." +msgstr "Показать дополнительные наÑтройки пакетов." + +#: ./input_links.py:207 +msgid "Checking links, please wait." +msgstr "СÑылки проверÑÑŽÑ‚ÑÑ, пожалуйÑта подождите." + +#: ./input_links.py:260 +msgid "Check Canceled!" +msgstr "Проверка была отменена!" + +#: ./preferences.py:54 +msgid "General Configuration" +msgstr "Общие наÑтройки" + +#: ./preferences.py:55 +msgid "Service Configuration" +msgstr "ÐаÑтройки ÑервиÑов" + +#: ./preferences.py:56 +msgid "Advanced Configuration" +msgstr "Дополнительные наÑтройки" + +#: ./preferences.py:120 +msgid "Choose language: " +msgstr "Выберите Ñзык: " + +#: ./preferences.py:138 +msgid "Max simultaneous downloads: " +msgstr "КоличеÑтво одновременных загрузок: " + +#: ./preferences.py:173 +msgid "Downloads Folder: " +msgstr "Папка загрузок: " + +#: ./preferences.py:260 +msgid "Restart Tucan to apply service changes." +msgstr "ПерезапуÑтите программу Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð½Ð°Ñтроек ÑервиÑов." + +#: ./preferences.py:279 +msgid "The choosed directory isn't a service, or it's not configured." +msgstr "Ð’Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð°Ñ Ð¿Ð°Ð¿ÐºÐ° не ÑвлÑетÑÑ ÑервиÑом, или она неправильно наÑтроена." + +#: ./preferences.py:307 +msgid "Before using this service, you must accept it's terms of service at " +msgstr "Прежде чем начать пользоватьÑÑ Ñтим ÑервиÑом вы должны принÑÑ‚ÑŒ его правила иÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾ адреÑу " + +#: ./preferences.py:308 +msgid "Terms of service" +msgstr "Правила иÑпользованиÑ" + +#: ./preferences.py:331 +msgid "Close to tray." +msgstr "Сворачивать в облаÑÑ‚ÑŒ уведомлений." + +#: ./preferences.py:335 +msgid "Save session on close." +msgstr "СохранÑÑ‚ÑŒ ÑеÑÑию при выходе." + +#: ./preferences.py:339 +msgid "Default advanced packages." +msgstr "Пакеты по умолчанию." + +#: ./preferences.py:343 +msgid "Show uploads." +msgstr "Показывать закачки." + +#: ./service_preferences.py:47 +msgid "Author" +msgstr "Ðвтор" + +#: ./service_preferences.py:55 +msgid "Version" +msgstr "ВерÑиÑ" + +#: ./service_preferences.py:64 +msgid "Slots" +msgstr "Слоты" + +#: ./service_preferences.py:71 +msgid "Captcha" +msgstr "Проверочный код" Binary files /tmp/Mj7pJvsoYS/tucan-0.3.8/i18n/se/LC_MESSAGES/tucan.mo and /tmp/DgSymrsclJ/tucan-0.3.9/i18n/se/LC_MESSAGES/tucan.mo differ diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/i18n/se/se.po /tmp/DgSymrsclJ/tucan-0.3.9/i18n/se/se.po --- tucan-0.3.8/i18n/se/se.po 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/i18n/se/se.po 2009-10-07 00:02:27.000000000 +0100 @@ -1,19 +1,20 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR ORGANIZATION -# FIRST AUTHOR , YEAR. +# Tucan Manager. +# Copyright (C) 2008-2009 The Tucan Project. +# Christian Widell , 2009. # msgid "" msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" +"Project-Id-Version: 0.3.7\n" "POT-Creation-Date: 2009-01-11 22:54+CET\n" "PO-Revision-Date: 2009-05-03 09:50+0100\n" -"Last-Translator: Christian Widell \n" +"Last-Translator: Christian Widell \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: UTF-8\n" "Generated-By: pygettext.py 1.5\n" + #: ./advanced_packages.py:37 msgid "Advanced Packages" msgstr "Avancerade paket" @@ -100,7 +101,7 @@ #: ./input_links.py:207 msgid "Checking links, please wait." -msgstr "Kontrollerar länkar, vänligen vänta" +msgstr "Kontrollerar länkar, vänligen vänta." #: ./input_links.py:260 msgid "Check Canceled!" @@ -120,15 +121,15 @@ #: ./preferences.py:120 msgid "Choose language: " -msgstr "Välj sprÃ¥k:" +msgstr "Välj sprÃ¥k: " #: ./preferences.py:138 msgid "Max simultaneous downloads: " -msgstr "Max antal parallela nedladdningar:" +msgstr "Max antal parallela nedladdningar: " #: ./preferences.py:173 msgid "Downloads Folder: " -msgstr "Nedladdningsmapp:" +msgstr "Nedladdningsmapp: " #: ./preferences.py:260 msgid "Restart Tucan to apply service changes." @@ -140,7 +141,7 @@ #: ./preferences.py:307 msgid "Before using this service, you must accept it's terms of service at " -msgstr "Innan du accepterar den här tjänsten mÃ¥ste du acceptera deras användningsvillkor pÃ¥" +msgstr "Innan du accepterar den här tjänsten mÃ¥ste du acceptera deras användningsvillkor pÃ¥ " #: ./preferences.py:308 msgid "Terms of service" @@ -148,7 +149,7 @@ #: ./preferences.py:331 msgid "Close to tray." -msgstr "Stäng till notifieringsyta" +msgstr "Stäng till notifieringsyta." #: ./preferences.py:335 msgid "Save session on close." @@ -177,4 +178,3 @@ #: ./service_preferences.py:71 msgid "Captcha" msgstr "Förhandsvisning" - Binary files /tmp/Mj7pJvsoYS/tucan-0.3.8/i18n/sk/LC_MESSAGES/tucan.mo and /tmp/DgSymrsclJ/tucan-0.3.9/i18n/sk/LC_MESSAGES/tucan.mo differ diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/i18n/sk/sk.po /tmp/DgSymrsclJ/tucan-0.3.9/i18n/sk/sk.po --- tucan-0.3.8/i18n/sk/sk.po 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/i18n/sk/sk.po 2009-10-07 00:02:27.000000000 +0100 @@ -1,21 +1,22 @@ # Tucan Manager. # Copyright (C) 2008-2009 The Tucan Project. -# Tomáš Vadina, 2009. +# Tomáš Vadina , 2009. # msgid "" msgstr "" "Project-Id-Version: 0.3.7 alpha\n" "POT-Creation-Date: 2009-01-11 22:54+CET\n" "PO-Revision-Date: 2009-04-30 10:30+0100\n" -"Last-Translator: Tomáš Vadina \n" -"Language-Team: kyberdev \n" +"Last-Translator: Tomáš Vadina \n" +"Language-Team: kyberdev \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" +"Content-Transfer-Encoding: UTF-8\n" "Generated-By: pygettext.py 1.5\n" "X-Poedit-Language: Slovak\n" "X-Poedit-Country: SLOVAKIA\n" + #: advanced_packages.py:37 msgid "Advanced Packages" msgstr "PokroÄilé balíky" @@ -122,15 +123,15 @@ #: preferences.py:120 msgid "Choose language: " -msgstr "VybraÅ¥ jazyk:" +msgstr "VybraÅ¥ jazyk: " #: preferences.py:138 msgid "Max simultaneous downloads: " -msgstr "Maximum simultánnych sÅ¥ahovaní:" +msgstr "Maximum simultánnych sÅ¥ahovaní: " #: preferences.py:173 msgid "Downloads Folder: " -msgstr "PrieÄinok sÅ¥ahovania:" +msgstr "PrieÄinok sÅ¥ahovania: " #: preferences.py:260 msgid "Restart Tucan to apply service changes." @@ -142,7 +143,7 @@ #: preferences.py:307 msgid "Before using this service, you must accept it's terms of service at " -msgstr "Skôr ako zaÄnete používaÅ¥ túto službu, musíte súhlasiÅ¥ s podmienkami jej používania na" +msgstr "Skôr ako zaÄnete používaÅ¥ túto službu, musíte súhlasiÅ¥ s podmienkami jej používania na " #: preferences.py:308 msgid "Terms of service" @@ -179,4 +180,3 @@ #: service_preferences.py:71 msgid "Captcha" msgstr "Captcha" - diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/input_files.py /tmp/DgSymrsclJ/tucan-0.3.9/input_files.py --- tucan-0.3.8/input_files.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/input_files.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,295 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import os - -import pygtk -pygtk.require('2.0') -import gtk -import gobject - -from file_chooser import FileChooser - -import cons - -SERVICES = [("Megaupload", 100, cons.UNIT_MB, ["Anonymous", "Premium"]), ("Rapidshare", 200, cons.UNIT_MB, ["Collector", "Premium"]), ("Gigasize", 100, cons.UNIT_MB, ["Anonymous"])] - -class InputFiles(gtk.Dialog): - """""" - def __init__(self, upload_services): - """""" - gtk.Dialog.__init__(self) - self.set_icon_from_file(cons.ICON_UPLOAD) - self.set_title(("Input Files")) - self.set_size_request(600,500) - - self.history_path = cons.DEFAULT_PATH - - main_hbox = gtk.HBox() - self.vbox.pack_start(main_hbox) - - self.file_icon = self.render_icon(gtk.STOCK_FILE, gtk.ICON_SIZE_BUTTON) - self.correct_icon = self.render_icon(gtk.STOCK_APPLY, gtk.ICON_SIZE_MENU) - self.incorrect_icon = self.render_icon(gtk.STOCK_CANCEL, gtk.ICON_SIZE_MENU) - - #package treeview - frame = gtk.Frame() - main_hbox.pack_start(frame, True) - frame.set_border_width(5) - scroll = gtk.ScrolledWindow() - frame.add(scroll) - scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self.package_treeview = gtk.TreeView(gtk.TreeStore(gtk.gdk.Pixbuf, str, str, str, bool)) - scroll.add(self.package_treeview) - - self.package_treeview.set_rules_hint(True) - self.package_treeview.set_headers_visible(False) - - tree_icon = gtk.TreeViewColumn('Icon') - icon_cell = gtk.CellRendererPixbuf() - tree_icon.pack_start(icon_cell, True) - tree_icon.add_attribute(icon_cell, 'pixbuf', 0) - self.package_treeview.append_column(tree_icon) - - tree_name = gtk.TreeViewColumn('Name') - name_cell = gtk.CellRendererText() - tree_name.pack_start(name_cell, True) - tree_name.add_attribute(name_cell, 'text', 1) - self.package_treeview.append_column(tree_name) - - tree_size = gtk.TreeViewColumn('Size') - size_cell = gtk.CellRendererText() - tree_size.pack_start(size_cell, False) - tree_size.add_attribute(size_cell, 'text', 2) - self.package_treeview.append_column(tree_size) - - service_vbox = gtk.VBox() - main_hbox.pack_start(service_vbox, False, False) - - # services treeview - frame = gtk.Frame() - service_vbox.pack_start(frame) - frame.set_size_request(200, -1) - frame.set_border_width(5) - frame.set_label_widget(gtk.image_new_from_file(cons.ICON_PREFERENCES_SERVICES)) - scroll = gtk.ScrolledWindow() - frame.add(scroll) - scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - services = gtk.ListStore(gtk.gdk.Pixbuf, str, int, str, bool, gobject.TYPE_PYOBJECT) - self.services_treeview = gtk.TreeView(services) - self.services_treeview.get_selection().connect("changed", self.select) - scroll.add(self.services_treeview) - - self.services_treeview.set_rules_hint(True) - self.services_treeview.set_headers_visible(False) - - tree_icon = gtk.TreeViewColumn('Icon') - icon_cell = gtk.CellRendererPixbuf() - tree_icon.pack_start(icon_cell, True) - tree_icon.add_attribute(icon_cell, 'pixbuf', 0) - self.services_treeview.append_column(tree_icon) - - tree_name = gtk.TreeViewColumn('Name') - name_cell = gtk.CellRendererText() - tree_name.pack_start(name_cell, True) - tree_name.add_attribute(name_cell, 'text', 1) - self.services_treeview.append_column(tree_name) - - tree_add = gtk.TreeViewColumn('Add') - add_cell = gtk.CellRendererToggle() - add_cell.connect("toggled", self.toggled) - tree_add.pack_start(add_cell, True) - tree_add.add_attribute(add_cell, 'active', 4) - self.services_treeview.append_column(tree_add) - - #plugins - self.plugins_frame = gtk.Frame() - service_vbox.pack_start(self.plugins_frame, False, False) - self.plugins_frame.set_size_request(200, 100) - self.plugins_frame.set_border_width(5) - - for service, size, unit, plugins in upload_services: - vbox = gtk.VBox() - first = None - for plugin in plugins: - first = gtk.RadioButton(first, plugin) - vbox.pack_start(first, False, False, 1) - services.append([self.correct_icon, service, size, unit, False, vbox]) - - #choose path - hbox = gtk.HBox() - self.vbox.pack_start(hbox, False, False, 5) - path_button = gtk.Button(None, gtk.STOCK_OPEN) - path_button.set_size_request(90,40) - hbox.pack_start(path_button, False, False, 5) - path_button.connect("clicked", self.choose_files) - path_label = gtk.Label(("Choose files to upload.")) - hbox.pack_start(path_label, False, False, 5) - aspect = gtk.AspectFrame() - hbox.pack_start(aspect, True, True) - aspect.set_shadow_type(gtk.SHADOW_NONE) - clear_button = gtk.Button(None, gtk.STOCK_CLEAR) - clear_button.set_size_request(190,40) - hbox.pack_start(clear_button, False, False, 5) - clear_button.connect("clicked", self.clear) - - #action area - cancel_button = gtk.Button(None, gtk.STOCK_CANCEL) - add_button = gtk.Button(None, gtk.STOCK_ADD) - self.action_area.pack_start(cancel_button) - self.action_area.pack_start(add_button) - cancel_button.connect("clicked", self.close) - add_button.connect("clicked", self.add_files) - - self.connect("response", self.close) - self.show_all() - self.set_focus(path_button) - self.run() - - def clear(self, button): - """""" - self.package_treeview.get_model().clear() - - def select(self, selection): - """""" - model, service_iter = selection.get_selected() - if iter: - if self.plugins_frame.get_child(): - self.plugins_frame.remove(self.plugins_frame.get_child()) - vbox = model.get_value(service_iter, 5) - self.plugins_frame.add(vbox) - vbox.show_all() - - def add_files(self, button): - """""" - result = [] - package_model = self.package_treeview.get_model() - services_model = self.services_treeview.get_model() - - file_iter = package_model.get_iter_root() - while file_iter: - services = [] - service_iter = package_model.iter_children(file_iter) - while service_iter: - service_name = package_model.get_value(service_iter, 1) - if package_model.get_value(service_iter, 4): - for service in services_model: - if service[1] == service_name: - for button in service[5].get_children(): - if button.get_active(): - services.append((service_name, button.get_label())) - service_iter = package_model.iter_next(service_iter) - if len(services) > 0: - tmp = package_model.get_value(file_iter, 2).split(" ") - size, unit = self.split_size(self.join_size(int(tmp[0]), tmp[1])) - result.append((package_model.get_value(file_iter, 3), int(size), unit, services)) - file_iter = package_model.iter_next(file_iter) - self.close() - print result - - def toggled(self, button, path): - """""" - active = True - if button.get_active(): - active = False - button.set_active(active) - - services_model = self.services_treeview.get_model() - package_model = self.package_treeview.get_model() - - services_model.set_value(services_model.get_iter(path), 4, active) - - file_iter = package_model.get_iter_root() - while file_iter: - service_iter = package_model.iter_children(file_iter) - found = False - while service_iter: - if services_model.get_value(services_model.get_iter(path), 1) == package_model.get_value(service_iter, 1): - found = True - break - service_iter = package_model.iter_next(service_iter) - if active: - if not found: - tmp = package_model.get_value(file_iter, 2).split(" ") - max_size = self.join_size(services_model.get_value(services_model.get_iter(path), 2), services_model.get_value(services_model.get_iter(path), 3)) - self.add_service(package_model, file_iter, services_model.get_value(services_model.get_iter(path), 1), self.join_size(int(tmp[0]), tmp[1]), max_size) - else: - if found: - package_model.remove(service_iter) - file_iter = package_model.iter_next(file_iter) - - def choose_files(self, button): - """""" - f = FileChooser(self, self.on_choose, self.history_path, True) - self.history_path = f.history_path - - def on_choose(self, path): - """""" - package_model = self.package_treeview.get_model() - services_model = self.services_treeview.get_model() - if os.path.isfile(path): - if path not in [row[1] for row in package_model]: - file_size = int(os.stat(path).st_size/1024) - size, unit = self.split_size(file_size) - file_iter = package_model.append(None, [self.file_icon, os.path.basename(path), "%i %s" %(size, unit), path, None]) - for row in services_model: - if row[4]: - self.add_service(package_model, file_iter, row[1], file_size, self.join_size(row[2], row[3])) - - def join_size(self, size, unit): - """""" - factor = 1 - if unit == cons.UNIT_KB: - factor = 1 - elif unit == cons.UNIT_MB: - factor = 1024 - elif unit == cons.UNIT_GB: - factor = 1024*1024 - return size*factor - - def split_size(self, size): - """""" - if size > 0: - tmp = size/1024 - if tmp > 0: - tmp2 = tmp/1024 - if tmp2 > 0: - return tmp2, cons.UNIT_GB - else: - return tmp, cons.UNIT_MB - else: - return size, cons.UNIT_KB - else: - return 1, cons.UNIT_KB - - def add_service(self, package_model, file_iter, service, file_size, max_size): - """""" - if max_size > file_size: - package_model.append(file_iter, [self.correct_icon, service, None, None, True]) - else: - package_model.append(file_iter, [self.incorrect_icon, service, None, None, False]) - self.package_treeview.expand_row(package_model.get_path(file_iter), True) - - def close(self, widget=None, other=None): - """""" - self.destroy() - -if __name__ == "__main__": - x = InputFiles(SERVICES) diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/input_links.py /tmp/DgSymrsclJ/tucan-0.3.9/input_links.py --- tucan-0.3.8/input_links.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/input_links.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,296 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import HTMLParser -import threading -import logging -logger = logging.getLogger(__name__) - -import pygtk -pygtk.require('2.0') -import gtk -import gobject - -from message import Wait, Message -from advanced_packages import AdvancedPackages - -import cons - -class ClipParser(HTMLParser.HTMLParser): - """""" - def __init__(self): - """""" - HTMLParser.HTMLParser.__init__(self) - self.url = [] - - def handle_starttag(self, tag, attrs): - """""" - if tag == "a": - for ref, link in attrs: - if ref == "href": - self.url.append(link) - -class InputLinks(gtk.Dialog): - """""" - def __init__(self, path, sort, check, create, manage, show_advanced_packages): - """""" - gtk.Dialog.__init__(self) - self.set_icon_from_file(cons.ICON_DOWNLOAD) - self.set_title(_("Input Links")) - self.set_size_request(600,500) - - self.cancel_check = False - - self.clipboard = gtk.clipboard_get() - self.clipboard.request_targets(self.get_clipboard) - - self.default_path = path - self.sort_links = sort - self.check_links = check - self.create_packages = create - self.packages = manage - - #textview - frame = gtk.Frame(_("Paste links here:")) - self.vbox.pack_start(frame) - frame.set_border_width(10) - hbox = gtk.HBox() - frame.add(hbox) - scroll = gtk.ScrolledWindow() - hbox.pack_start(scroll, True, True, 10) - scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) - #auto scroll - scroll.get_vadjustment().connect("changed", self.changed) - scroll.get_vadjustment().connect("value-changed", self.value_changed) - buffer = gtk.TextBuffer() - self.textview = gtk.TextView(buffer) - scroll.add(self.textview) - self.textview.set_wrap_mode(gtk.WRAP_CHAR) - - #check button - button_box = gtk.HButtonBox() - hbox.pack_start(button_box, False, False, 10) - vbox = gtk.VBox() - check_image = gtk.image_new_from_file(cons.ICON_CHECK) - vbox.pack_start(check_image) - check_label = gtk.Label(_("Check Links")) - vbox.pack_start(check_label) - check_button = gtk.Button() - check_button.add(vbox) - button_box.pack_start(check_button) - check_button.connect("clicked", self.check) - - #treeview - frame = gtk.Frame() - self.vbox.pack_start(frame) - frame.set_border_width(10) - scroll = gtk.ScrolledWindow() - frame.add(scroll) - scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - #auto scroll - scroll.get_vadjustment().connect("changed", self.changed) - scroll.get_vadjustment().connect("value-changed", self.value_changed) - - self.treeview = gtk.TreeView(gtk.TreeStore(gtk.gdk.Pixbuf, str, str, int, str, str, bool, bool)) - scroll.add(self.treeview) - - self.treeview.set_rules_hint(True) - self.treeview.set_headers_visible(False) - - tree_icon = gtk.TreeViewColumn('Icon') - icon_cell = gtk.CellRendererPixbuf() - tree_icon.pack_start(icon_cell, True) - tree_icon.add_attribute(icon_cell, 'pixbuf', 0) - self.treeview.append_column(tree_icon) - - tree_name = gtk.TreeViewColumn('Name') - name_cell = gtk.CellRendererText() - name_cell.set_property("editable", True) - name_cell.connect("edited", self.change_name) - tree_name.pack_start(name_cell, True) - tree_name.add_attribute(name_cell, 'text', 2) - self.treeview.append_column(tree_name) - - tree_add = gtk.TreeViewColumn('Add') - add_cell = gtk.CellRendererToggle() - add_cell.connect("toggled", self.toggled) - tree_add.pack_start(add_cell, True) - tree_add.add_attribute(add_cell, 'active', 6) - tree_add.add_attribute(add_cell, 'visible', 7) - self.treeview.append_column(tree_add) - - #advanced checkbutton - self.advanced_button = gtk.CheckButton(_("Show advanced Package configuration.")) - self.advanced_button.set_active(show_advanced_packages) - self.vbox.pack_start(self.advanced_button, False) - - #action area - cancel_button = gtk.Button(None, gtk.STOCK_CANCEL) - add_button = gtk.Button(None, gtk.STOCK_ADD) - self.action_area.pack_start(cancel_button) - self.action_area.pack_start(add_button) - cancel_button.connect("clicked", self.close) - add_button.connect("clicked", self.add_links) - - self.connect("response", self.close) - self.show_all() - self.run() - - def changed(self, vadjust): - """autoscroll""" - if not hasattr(vadjust, "need_scroll") or vadjust.need_scroll: - vadjust.set_value(vadjust.upper-vadjust.page_size) - vadjust.need_scroll = True - - def value_changed (self, vadjust): - """autoscroll""" - vadjust.need_scroll = abs(vadjust.value + vadjust.page_size - vadjust.upper) < vadjust.step_increment - - def change_name(self, cellrenderertext, path, new_text): - """""" - model = self.treeview.get_model() - model.set_value(model.get_iter(path), 2, new_text) - - def get_clipboard(self, clipboard, selection_data, data): - """""" - target_html = "text/html" - if target_html in list(selection_data): - selection = self.clipboard.wait_for_contents(target_html) - if selection: - for line in str(selection.data.decode("utf16")).split("\n"): - try: - parser = ClipParser() - parser.feed(line) - parser.close() - if len(parser.url) > 0: - self.textview.get_buffer().insert_at_cursor("\n".join(parser.url) + "\n") - except HTMLParser.HTMLParseError: - pass - def toggled(self, button, path): - """""" - model = self.treeview.get_model() - active = True - if button.get_active(): - active = False - button.set_active(active) - model.set_value(model.get_iter(path), 6, active) - - def add_links(self, button): - """""" - tmp = {} - store = self.treeview.get_model() - for column in store: - if column[2] != cons.TYPE_UNSUPPORTED: - tmp[column[2]] = [] - for value in column.iterchildren(): - if value[1] != value[2]: - if value[6]: - logger.info("Added: %s %s %s %s %s" % (value[1], value[2], value[3], value[4], value[5])) - tmp[column[2]].append((value[1], value[2], value[3], value[4], value[5])) - if tmp != {}: - self.hide() - packages = self.create_packages(tmp) - packages_info = None - if self.advanced_button.get_active(): - w = AdvancedPackages(self.default_path, packages) - packages_info = w.packages - if packages_info: - self.packages(packages, packages_info) - self.close() - else: - self.show() - else: - self.packages(packages, []) - self.close() - else: - title = _("Input Links - Nothing to add.") - message = _("There aren't links to add.\nPlease check the links before adding.") - m = Message(self, cons.SEVERITY_INFO, title, message, both=True) - if not m.accepted: - self.close() - - def check(self, button): - """""" - w = Wait(_("Checking links, please wait."), self) - w.connect("key-press-event", self.cancel) - th = threading.Thread(group=None, target=self.check_all, name=None, args=(w,)) - th.start() - - def check_all(self, wait): - """""" - store = self.treeview.get_model() - store.clear() - buffer = self.textview.get_buffer() - start, end = buffer.get_bounds() - link_list = [link.strip() for link in buffer.get_text(start, end).split("\n")] - - service_icon = self.treeview.render_icon(gtk.STOCK_INFO, gtk.ICON_SIZE_MENU) - unsupported_icon = self.treeview.render_icon(gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_MENU) - active_icon = self.treeview.render_icon(gtk.STOCK_APPLY, gtk.ICON_SIZE_MENU) - unchecked_icon = self.treeview.render_icon(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_MENU) - unactive_icon = self.treeview.render_icon(gtk.STOCK_CANCEL, gtk.ICON_SIZE_MENU) - try: - for service, links in self.sort_links(link_list).items(): - if links != []: - if service == cons.TYPE_UNSUPPORTED: - service_iter = store.append(None, [unsupported_icon, service, service, 0, None, None, False, False]) - for link in links: - store.append(service_iter, [unchecked_icon, link, link, 0, None, None, False, False]) - else: - service_iter = store.append(None, [service_icon, service, service, 0, None, None, False, False]) - for link in links: - if self.cancel_check: - self.cancel_check = False - raise Exception("Check Links cancelled") - check, plugin_type = self.check_links(service) - file_name, size, size_unit = check(link) - if file_name: - if size > 0: - icon = active_icon - marked = True - else: - icon = unchecked_icon - marked = False - else: - icon = unactive_icon - marked = False - file_name = link - logger.info("Checked: %s %s %s" % (file_name, size, size_unit)) - store.append(service_iter, [icon, link, file_name, size, size_unit, plugin_type, marked, marked]) - self.treeview.expand_row(store.get_path(service_iter), True) - except: - gobject.idle_add(wait.destroy) - else: - buffer.set_text("") - gobject.idle_add(wait.destroy) - - def cancel(self, window, event): - """Esc key""" - if event.keyval == 65307: - window.progress.set_text(_("Check Canceled!")) - self.cancel_check = True - - def close(self, widget=None, other=None): - """""" - self.destroy() - -if __name__ == "__main__": - x = InputLinks(None, None, None) - gtk.main() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/log_view.py /tmp/DgSymrsclJ/tucan-0.3.9/log_view.py --- tucan-0.3.8/log_view.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/log_view.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,147 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import pygtk -pygtk.require('2.0') -import gtk -import gobject - -import cons - -SEVERITY = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] -COLORS = {"DEBUG": "grey", "INFO": "green", "WARNING": "yellow", "ERROR": "red", "CRITICAL": "white"} - -class LogView(gtk.Dialog): - """""" - def __init__(self, widget=None): - """""" - gtk.Dialog.__init__(self) - self.set_title("Log View") - self.set_size_request(700,500) - self.set_icon(self.render_icon(gtk.STOCK_FILE, gtk.ICON_SIZE_MENU)) - - self.file = open(cons.LOG_FILE, "r") - self.back_buffer = gtk.TextBuffer() - self.back_buffer.set_text(self.file.read()) - - frame = gtk.Frame() - self.vbox.pack_start(frame) - frame.set_border_width(10) - hbox = gtk.HBox() - frame.add(hbox) - - #auto scroll - scroll = gtk.ScrolledWindow() - hbox.pack_start(scroll) - scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - scroll.get_vadjustment().connect("changed", self.changed) - scroll.get_vadjustment().connect("value-changed", self.value_changed) - - #textview - buffer = gtk.TextBuffer() - self.textview = gtk.TextView(buffer) - scroll.add(self.textview) - self.textview.set_wrap_mode(gtk.WRAP_NONE) - self.textview.set_editable(False) - self.textview.set_cursor_visible(False) - self.textview.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse("black")) - - table = buffer.get_tag_table() - for name, color in COLORS.items(): - tag = gtk.TextTag(name) - tag.set_property("foreground", color) - tag.set_property("left_margin", 10) - tag.set_property("right_margin", 10) - table.add(tag) - - #combo - hbox = gtk.HBox() - self.vbox.pack_start(hbox, False, False, 10) - buttonbox = gtk.HButtonBox() - hbox.pack_start(buttonbox, False, False, 10) - label = gtk.Label("Minimum severity shown.") - hbox.pack_start(label, False, False, 10) - aspect = gtk.AspectFrame() - aspect.set_shadow_type(gtk.SHADOW_NONE) - hbox.pack_start(aspect) - - self.combo = gtk.combo_box_new_text() - buttonbox.pack_start(self.combo) - self.combo.connect("changed", self.reload) - - for s in SEVERITY: - self.combo.append_text(s) - self.combo.set_active(2) - - #action area - button = gtk.Button(None, gtk.STOCK_CLOSE) - self.action_area.pack_start(button) - button.connect("clicked", self.close) - - self.connect("response", self.close) - self.show_all() - - gobject.timeout_add(1000, self.update) - self.run() - - def insert_color(self, buffer, line): - """""" - for s in SEVERITY[self.combo.get_active():]: - if s in line: - buffer.insert_with_tags(buffer.get_end_iter(), "%s\n" % line, buffer.get_tag_table().lookup(s)) - break - - def reload(self, textview): - """""" - buffer = self.textview.get_buffer() - buffer.set_text("") - ini, fin = self.back_buffer.get_bounds() - for line in self.back_buffer.get_text(ini, fin).split("\n"): - self.insert_color(buffer, line) - - def update(self): - """""" - try: - buffer = self.textview.get_buffer() - for line in self.file.readlines(): - self.back_buffer.insert(self.back_buffer.get_end_iter(), line) - self.insert_color(buffer, line.strip()) - except: - pass - else: - return True - - def changed(self, vadjust): - """autoscroll""" - if not hasattr(vadjust, "need_scroll") or vadjust.need_scroll: - vadjust.set_value(vadjust.upper-vadjust.page_size) - vadjust.need_scroll = True - - def value_changed (self, vadjust): - """autoscroll""" - vadjust.need_scroll = abs(vadjust.value + vadjust.page_size - vadjust.upper) < vadjust.step_increment - - def close(self, widget=None, other=None): - """""" - self.file.close() - self.destroy() - -if __name__ == "__main__": - c = LogView() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/Makefile /tmp/DgSymrsclJ/tucan-0.3.9/Makefile --- tucan-0.3.8/Makefile 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/Makefile 2009-10-07 00:02:31.000000000 +0100 @@ -30,9 +30,11 @@ ICONFILE = tucan.svg MANPAGE = tucan.1.gz DESKTOPFILE = tucan.desktop +COREDIR = core/ PLUGINDIR = default_plugins/ I18NDIR = i18n/ MEDIADIR = media/ +UIDIR = ui/ basic-install: mkdir -p $(BINDIR) $(MAINDIR) $(ICONDIR) $(MANDIR) $(DESKTOPDIR) @@ -40,9 +42,11 @@ install -p -m 0644 *.py $(MAINDIR) chmod 0755 $(MAINDIR)$(EXECFILE) + cp -pR $(COREDIR) $(MAINDIR) cp -pR $(PLUGINDIR) $(MAINDIR) cp -pR $(I18NDIR) $(MAINDIR) cp -pR $(MEDIADIR) $(MAINDIR) + cp -pR $(UIDIR) $(MAINDIR) install -p -m 0644 $(MEDIADIR)$(ICONFILE) $(ICONDIR) diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/media/mail-reply-sender.svg /tmp/DgSymrsclJ/tucan-0.3.9/media/mail-reply-sender.svg --- tucan-0.3.8/media/mail-reply-sender.svg 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/media/mail-reply-sender.svg 2009-10-07 00:02:26.000000000 +0100 @@ -0,0 +1,548 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Mail Reply + + + Garrett LeSage + + + + + Jakub Steiner, Andreas Nilsson + + + + + + mail + e-mail + reply + sender + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/menu_bar.py /tmp/DgSymrsclJ/tucan-0.3.9/menu_bar.py --- tucan-0.3.8/menu_bar.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/menu_bar.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,45 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import pygtk -pygtk.require('2.0') -import gtk - -class MenuBar(gtk.MenuBar): - """""" - def __init__(self, list): - """list = [(menu_name=str, [(item_image=stock_item, callback), None=separator])]""" - gtk.MenuBar.__init__(self) - for menu in list: - item = gtk.MenuItem(menu[0]) - self.append(item) - submenu = gtk.Menu() - for sub in menu[1]: - if sub == None: - subitem = gtk.SeparatorMenuItem() - elif isinstance(sub[0], gtk.CheckMenuItem): - subitem = sub[0] - subitem.set_active(sub[2]) - subitem.connect("toggled", sub[1]) - else: - subitem = gtk.ImageMenuItem(sub[0]) - subitem.connect("activate", sub[1]) - submenu.append(subitem) - item.set_submenu(submenu) diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/message.py /tmp/DgSymrsclJ/tucan-0.3.9/message.py --- tucan-0.3.8/message.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/message.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,113 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import pygtk -pygtk.require('2.0') -import gtk -import gobject - -import cons - -class Wait(gtk.Window): - """""" - def __init__(self, message, parent): - """""" - gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL) - self.set_transient_for(parent) - self.set_modal(True) - self.set_position(gtk.WIN_POS_CENTER) - self.set_property("skip-pager-hint", True) - self.set_property("skip-taskbar-hint", True) - self.set_resizable(False) - self.set_decorated(False) - self.set_size_request(300,100) - - self.progress = gtk.ProgressBar() - self.add(self.progress) - self.progress.set_text(message) - - self.show_all() - - gobject.timeout_add(100, self.pulse) - - def pulse(self): - """""" - self.progress.pulse() - return True - -class Message(gtk.Dialog): - """""" - def __init__(self, parent, severity, title, message, accept=False, both=False): - """""" - gtk.Dialog.__init__(self) - self.set_title(title) - self.set_position(gtk.WIN_POS_CENTER) - self.set_resizable(False) - self.set_transient_for(parent) - - self.accepted = False - - hbox = gtk.HBox() - self.vbox.pack_start(hbox, True, True, 10) - icon = gtk.STOCK_DIALOG_INFO - if severity == cons.SEVERITY_WARNING: - icon = gtk.STOCK_DIALOG_WARNING - elif severity == cons.SEVERITY_ERROR: - icon = gtk.STOCK_DIALOG_ERROR - hbox.pack_start(gtk.image_new_from_stock(icon, gtk.ICON_SIZE_DIALOG), True, False, 10) - self.set_icon(self.render_icon(icon, gtk.ICON_SIZE_MENU)) - - label = gtk.Label(message) - hbox.pack_start(label, True, False, 5) - label.set_width_chars(35) - label.set_line_wrap(True) - - #action area - if both: - close_button = gtk.Button(None, gtk.STOCK_CANCEL) - self.action_area.pack_start(close_button) - close_button.connect("clicked", self.close) - ok_button = gtk.Button(None, gtk.STOCK_OK) - self.action_area.pack_start(ok_button) - ok_button.connect("clicked", self.accept) - elif accept: - ok_button = gtk.Button(None, gtk.STOCK_OK) - self.action_area.pack_start(ok_button) - ok_button.connect("clicked", self.accept) - else: - close_button = gtk.Button(None, gtk.STOCK_CLOSE) - self.action_area.pack_start(close_button) - close_button.connect("clicked", self.close) - - self.connect("response", self.close) - self.show_all() - self.run() - - def accept(self, button): - """""" - self.accepted = True - self.close() - - def close(self, widget=None, other=None): - """""" - self.destroy() - -if __name__ == "__main__": - m = Message(None, cons.SEVERITY_WARNING, "Tucan Manager - Restore previous session.", "Your last session closed unexpectedly.\nTucan will try to restore it now.", both=True) diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/arch/PKGBUILD /tmp/DgSymrsclJ/tucan-0.3.9/packages/arch/PKGBUILD --- tucan-0.3.8/packages/arch/PKGBUILD 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/packages/arch/PKGBUILD 2009-10-07 00:02:31.000000000 +0100 @@ -3,13 +3,13 @@ # Note: The pakage's host puts a random number in tarball's link. New var added for this "pkgrediris". pkgname=tucan -pkgver=0.3.5 -pkgrel=2 -pkgrediris=1135 +pkgver=0.3.8 +pkgrel=1 +pkgrediris=1400 pkgdesc="Download and upload manager for hosting sites." arch=('i686' 'x86_64') -url="http://cusl3-tucan.forja.rediris.es/" -license=('GPLv2') +url="http://tucaneando.com/" +license=('GPLv3') groups=() depends=('python' 'pygtk' 'pil' 'tesseract' 'librsvg') makedepends=() @@ -18,7 +18,7 @@ backup=() install=${pkgname}.install source=(http://forja.rediris.es/frs/download.php/$pkgrediris/$pkgname-$pkgver.tar.gz) -md5sums=('229f88beef7ea52a29dabba08fab6d7a') +md5sums=('3e27a9b17f67d8523950522366b18b77') build() { diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/debian/changelog /tmp/DgSymrsclJ/tucan-0.3.9/packages/debian/changelog --- tucan-0.3.8/packages/debian/changelog 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/packages/debian/changelog 2009-10-07 00:02:28.000000000 +0100 @@ -1,12 +1,22 @@ +tucan (0.3.8-1) unstable; urgency=low + + * New upstream release + * debian-policy updated to 3.8.2 + * License upgraded to GPLv3 + * New upstream/maintainer mail + * Solved data loss (Closes: #531392) + + -- Fran Lupion (Crak) Wed, 15 Jul 2009 22:54:52 +0200 + tucan (0.3.7-1) unstable; urgency=low * New upstream release * Uploaded to debian (Closes: #520470) - -- Fran Lupion (Crak) Sun, 19 Apr 2009 19:39:32 +0200 + -- Fran Lupion (Crak) Sun, 19 Apr 2009 19:39:32 +0200 tucan (0.3.6-1) unstable; urgency=low * Initial release - -- Fran Lupion (Crak) Tue, 07 Apr 2009 19:23:20 +0200 + -- Fran Lupion (Crak) Tue, 07 Apr 2009 19:23:20 +0200 diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/debian/control /tmp/DgSymrsclJ/tucan-0.3.9/packages/debian/control --- tucan-0.3.8/packages/debian/control 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/packages/debian/control 2009-10-07 00:02:28.000000000 +0100 @@ -1,10 +1,10 @@ Source: tucan Section: net Priority: optional -Maintainer: Fran Lupion (Crak) +Maintainer: Fran Lupion (Crak) Build-Depends: debhelper (>= 7) -Standards-Version: 3.8.1 -Homepage: http://cusl3-tucan.forja.rediris.es/ +Standards-Version: 3.8.2 +Homepage: http://www.tucaneando.com Package: tucan Architecture: all @@ -16,6 +16,11 @@ - http://gigasize.com/ - http://mediafire.com/ - http://4shared.com/ + - http://sendspace.com/ + - http://zshare.net/ + - http://filefactory.com/ + - http://easy-share.com/ + - http://badongo.com/ - (...) Main Features: - Graphical User Interface in GTK+. diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/debian/copyright /tmp/DgSymrsclJ/tucan-0.3.9/packages/debian/copyright --- tucan-0.3.8/packages/debian/copyright 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/packages/debian/copyright 2009-10-07 00:02:28.000000000 +0100 @@ -1,14 +1,14 @@ This package was debianized by: - Fran Lupion (Crak) on Tue, 07 Apr 2009 19:23:20 +0200 + Fran Lupion (Crak) on Tue, 07 Apr 2009 19:23:20 +0200 It was downloaded from: - + Upstream Author: - Fran Lupion (Crak) + Fran Lupion (Crak) Copyright: @@ -18,7 +18,7 @@ This package 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 + the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This package is distributed in the hope that it will be useful, @@ -31,12 +31,12 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA On Debian systems, the complete text of the GNU General -Public License version 2 can be found in `/usr/share/common-licenses/GPL-2'. +Public License version 3 can be found in `/usr/share/common-licenses/GPL-3'. The Debian packaging is: - Copyright (C) 2009 Fran Lupion (Crak) + Copyright (C) 2009 Fran Lupion (Crak) -and is licensed under the GPL version 2, -see `/usr/share/common-licenses/GPL-2'. +and is licensed under the GPL version 3, +see `/usr/share/common-licenses/GPL-3'. diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/debian/files /tmp/DgSymrsclJ/tucan-0.3.9/packages/debian/files --- tucan-0.3.8/packages/debian/files 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/packages/debian/files 2009-10-07 00:02:28.000000000 +0100 @@ -1 +1 @@ -tucan_0.3.7-1_all.deb net optional +tucan_0.3.8-1_all.deb net optional diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/debian/scripts/tucan /tmp/DgSymrsclJ/tucan-0.3.9/packages/debian/scripts/tucan --- tucan-0.3.8/packages/debian/scripts/tucan 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/packages/debian/scripts/tucan 2009-10-07 00:02:28.000000000 +0100 @@ -1,2 +1,2 @@ #!/bin/sh -python /usr/share/tucan/tucan.py \ No newline at end of file +python /usr/share/tucan/tucan.py diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/debian/tucan.debhelper.log /tmp/DgSymrsclJ/tucan-0.3.9/packages/debian/tucan.debhelper.log --- tucan-0.3.8/packages/debian/tucan.debhelper.log 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/packages/debian/tucan.debhelper.log 1970-01-01 01:00:00.000000000 +0100 @@ -1,11 +0,0 @@ -dh_prep -dh_installchangelogs -dh_installdocs -dh_installmenu -dh_installman -dh_compress -dh_fixperms -dh_installdeb -dh_gencontrol -dh_md5sums -dh_builddeb diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/debian/tucan.substvars /tmp/DgSymrsclJ/tucan-0.3.9/packages/debian/tucan.substvars --- tucan-0.3.8/packages/debian/tucan.substvars 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/packages/debian/tucan.substvars 1970-01-01 01:00:00.000000000 +0100 @@ -1 +0,0 @@ -misc:Depends= diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/gentoo/layman.txt /tmp/DgSymrsclJ/tucan-0.3.9/packages/gentoo/layman.txt --- tucan-0.3.8/packages/gentoo/layman.txt 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/packages/gentoo/layman.txt 2009-10-07 00:02:31.000000000 +0100 @@ -0,0 +1,20 @@ + + + + + + + http://tucaneando.com/ + + + + Tucan unofficial overlay + + + + diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/gentoo/Manifest /tmp/DgSymrsclJ/tucan-0.3.9/packages/gentoo/Manifest --- tucan-0.3.8/packages/gentoo/Manifest 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/packages/gentoo/Manifest 1970-01-01 01:00:00.000000000 +0100 @@ -1,3 +0,0 @@ -DIST tucan-0.3.7.tar.gz 199208 RMD160 628a0818f251293e4e01b9c278411dac51a0ec69 SHA1 ec70756f6c2501a42a95f59f99da40eda551d951 SHA256 56eb1038f1ddef4a82f72f74cf472edbd26679d0f8d27c40e7e6703fe575b683 -EBUILD tucan-0.3.7.ebuild 823 RMD160 a85f98fee7718df7e7102781fe352c8cb551c2a9 SHA1 7d0596c485a88caca8a4e2a61b9e0a55ed962e74 SHA256 893dc541790d69218f8e867c4f4c8e00c25147a6f85b1ca9b240a92fd0609014 -MISC tucan-0.3.7.ebuild-back 1191 RMD160 204c7d0e3a5a87d16fdacd019508c892371b43df SHA1 3ef2aa062b518464f4c8a3282861a7f7311606ce SHA256 2b49446e17b248deab81955ba9fc73e07e1213db8c4581da3e7de117f7c2ac41 diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/gentoo/overlay/net-misc/tucan/Manifest /tmp/DgSymrsclJ/tucan-0.3.9/packages/gentoo/overlay/net-misc/tucan/Manifest --- tucan-0.3.8/packages/gentoo/overlay/net-misc/tucan/Manifest 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/packages/gentoo/overlay/net-misc/tucan/Manifest 2009-10-07 00:02:31.000000000 +0100 @@ -0,0 +1,5 @@ +DIST tucan-0.3.7.tar.gz 199208 RMD160 628a0818f251293e4e01b9c278411dac51a0ec69 SHA1 ec70756f6c2501a42a95f59f99da40eda551d951 SHA256 56eb1038f1ddef4a82f72f74cf472edbd26679d0f8d27c40e7e6703fe575b683 +DIST tucan-0.3.8.tar.gz 184714 RMD160 3acb31016dc6093e121948a77d857f2262e4218c SHA1 aa7ea520838359229d57fc50ef03b132c4e5a995 SHA256 dd9acb147bdb229a5acd52213b1ddc57fea02cc0eec065b51c9278f15a181b30 +EBUILD tucan-0.3.7.ebuild 822 RMD160 8bc43194da4e9ac199d04b5f6c7a151dbd942cb3 SHA1 d93e77a8a61636d67838bbafc250a76773242c80 SHA256 102fe408b94b5698f6893074ec39844f2ec2177e82ef291ad2d093d7fd06be4d +EBUILD tucan-0.3.8.ebuild 777 RMD160 9f0f26c42961980c1ed5e074d5d244de4060f35b SHA1 5649a9014e619fd43923d043d92dfeee239fb40c SHA256 c33b3a85a8c14ff15cc618f01b3d6ac8858e50f66ba758284202db20ef311d5c +EBUILD tucan-9999.ebuild 658 RMD160 8c1d8e0754fa5450a8e3d27956056f3cea59fc43 SHA1 d7694fb49853a5ac4b904facac7cb518b75d4d87 SHA256 e4857434eb6840dad08d6fcb1df0064dd4e88b7abed2a86ae3262302e19940f8 diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/gentoo/overlay/net-misc/tucan/tucan-0.3.7.ebuild /tmp/DgSymrsclJ/tucan-0.3.9/packages/gentoo/overlay/net-misc/tucan/tucan-0.3.7.ebuild --- tucan-0.3.8/packages/gentoo/overlay/net-misc/tucan/tucan-0.3.7.ebuild 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/packages/gentoo/overlay/net-misc/tucan/tucan-0.3.7.ebuild 2009-10-07 00:02:31.000000000 +0100 @@ -0,0 +1,33 @@ +# Copyright 1999-2009 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +inherit eutils + +DESCRIPTION="Software designed for automatic management of downloads and uploads at hosting sites like rapidshare or megaupload" +HOMEPAGE="http://cusl3-tucan.forja.rediris.es" +SRC_URI="http://forja.rediris.es/frs/download.php/1290/${P}.tar.gz" + +LICENSE="GPL-2" +SLOT="0" +KEYWORDS="~x86 ~amd64" + +IUSE="" +DEPEND="dev-lang/python + dev-python/pygtk + dev-python/imaging + app-text/tesseract[linguas_en] + gnome-base/librsvg" + +src_compile() { + sed -i \ + -e '/^DESTDIR/d' \ + Makefile || die "sed failed" +} + +src_install() { + emake DESTDIR="${D}"/usr install || die "emake install failed" + dodoc CHANGELOG README || die + newicon media/tucan.svg "${PN}.svg" + make_desktop_entry tucan Tucan +} diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/gentoo/overlay/net-misc/tucan/tucan-0.3.8.ebuild /tmp/DgSymrsclJ/tucan-0.3.9/packages/gentoo/overlay/net-misc/tucan/tucan-0.3.8.ebuild --- tucan-0.3.8/packages/gentoo/overlay/net-misc/tucan/tucan-0.3.8.ebuild 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/packages/gentoo/overlay/net-misc/tucan/tucan-0.3.8.ebuild 2009-10-07 00:02:31.000000000 +0100 @@ -0,0 +1,32 @@ +# Copyright 1999-2009 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +inherit eutils + +DESCRIPTION="Software designed for automatic management of downloads and uploads at hosting sites like rapidshare or megaupload" +HOMEPAGE="http://tucaneando.com/" +SRC_URI="http://forja.rediris.es/frs/download.php/1400/${P}.tar.gz" + +LICENSE="GPLv3" +SLOT="0" +KEYWORDS="~x86 ~amd64" + +IUSE="" +DEPEND="dev-lang/python + dev-python/pygtk + dev-python/imaging + app-text/tesseract[linguas_en] + gnome-base/librsvg" + +src_compile() { + sed -i \ + -e '/^DESTDIR/d' \ + Makefile || die "sed failed" +} + +src_install() { + emake DESTDIR="${D}"/usr install || die "emake install failed" + dodoc CHANGELOG README || die + newicon media/tucan.svg "${PN}.svg" +} diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/gentoo/overlay/net-misc/tucan/tucan-9999.ebuild /tmp/DgSymrsclJ/tucan-0.3.9/packages/gentoo/overlay/net-misc/tucan/tucan-9999.ebuild --- tucan-0.3.8/packages/gentoo/overlay/net-misc/tucan/tucan-9999.ebuild 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/packages/gentoo/overlay/net-misc/tucan/tucan-9999.ebuild 2009-10-07 00:02:31.000000000 +0100 @@ -0,0 +1,32 @@ +# Copyright 1999-2009 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +inherit subversion + +ESVN_REPO_URI="https://forja.rediris.es/svn/cusl3-tucan/trunk/" +ESVN_PROJECT="tucan-svn" +ESVN_STORE_DIR="${D}/svn-src" + +LICENSE="GPLv3" +SLOT="0" +KEYWORDS="" + +IUSE="" +DEPEND="dev-lang/python + dev-python/pygtk + dev-python/imaging + app-text/tesseract[linguas_en] + gnome-base/librsvg" + +src_compile() { + sed -i \ + -e '/^DESTDIR/d' \ + Makefile || die "sed failed" +} + +src_install() { + emake DESTDIR="${D}"/usr install || die "emake install failed" + dodoc CHANGELOG README || die + newicon media/tucan.svg "${PN}.svg" +} diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/gentoo/overlay/profiles/repo_name /tmp/DgSymrsclJ/tucan-0.3.9/packages/gentoo/overlay/profiles/repo_name --- tucan-0.3.8/packages/gentoo/overlay/profiles/repo_name 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/packages/gentoo/overlay/profiles/repo_name 2009-10-07 00:02:31.000000000 +0100 @@ -0,0 +1 @@ +tucan-overlay diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/gentoo/tucan-0.3.7.ebuild /tmp/DgSymrsclJ/tucan-0.3.9/packages/gentoo/tucan-0.3.7.ebuild --- tucan-0.3.8/packages/gentoo/tucan-0.3.7.ebuild 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/packages/gentoo/tucan-0.3.7.ebuild 1970-01-01 01:00:00.000000000 +0100 @@ -1,34 +0,0 @@ -# Copyright 1999-2009 Gentoo Foundation -# Distributed under the terms of the GNU General Public License v2 -# $Header: $ - -inherit eutils - -DESCRIPTION="Software designed for automatic management of downloads and uploads at hosting sites like rapidshare or megaupload" -HOMEPAGE="http://cusl3-tucan.forja.rediris.es" -SRC_URI="http://forja.rediris.es/frs/download.php/1290/${P}.tar.gz" - -LICENSE="GPL-2" -SLOT="0" -KEYWORDS="~x86 ~amd64" - -IUSE="" -DEPEND="dev-lang/python - dev-python/pygtk - dev-python/imaging - app-text/tesseract[linguas_en] - gnome-base/librsvg" - -src_compile() { - sed -i \ - -e '/^DESTDIR/d' \ - Makefile || die "sed failed" -} - -src_install() { - emake DESTDIR="${D}"/usr install || die "emake install failed" - dodoc CHANGELOG README || die - newicon media/tucan.svg "${PN}.svg" - make_desktop_entry tucan Tucan -} - diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/osx/environment.sh /tmp/DgSymrsclJ/tucan-0.3.9/packages/osx/environment.sh --- tucan-0.3.8/packages/osx/environment.sh 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/packages/osx/environment.sh 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,4 @@ +#!/bin/sh + +export PYTHONPATH=$GTK_PATH/lib/python2.5/site-packages/PIL:$GTK_PATH/lib/python2.5/site-packages/gtk-2.0:$GTK_PATH/lib/python2.5/site-packages + diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/osx/gtkrc /tmp/DgSymrsclJ/tucan-0.3.9/packages/osx/gtkrc --- tucan-0.3.8/packages/osx/gtkrc 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/packages/osx/gtkrc 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,424 @@ + +# Please keep this gtkrc in sync with the other ones from Clearlooks based themes. + +gtk-color-scheme = "base_color:#ffffff\nfg_color:#000000\ntooltip_fg_color:#000000\nselected_bg_color:#86ABD9\nselected_fg_color:#ffffff\ntext_color:#1A1A1A\nbg_color:#EDECEB\ntooltip_bg_color:#F5F5B5" + +style "default" { + xthickness = 1 + ythickness = 1 + + ####################### + # Style Properties + ####################### + GtkButton::child-displacement-x = 1 + GtkButton::child-displacement-y = 1 + GtkButton::default-border = { 0, 0, 0, 0 } + + GtkCheckButton::indicator-size = 14 + + GtkPaned::handle-size = 6 + + GtkRange::trough-border = 0 + GtkRange::slider-width = 15 + GtkRange::stepper-size = 15 + + GtkScale::slider-length = 23 + GtkScale::trough-side-details = 1 + + GtkScrollbar::min-slider-length = 30 + GtkMenuBar::internal-padding = 0 + GtkExpander::expander-size = 16 + GtkToolbar::internal-padding = 1 + GtkTreeView::expander-size = 14 + GtkTreeView::vertical-separator = 0 + + GtkMenu::horizontal-padding = 0 + GtkMenu::vertical-padding = 0 + + WnckTasklist::fade-overlay-rect = 0 + # The following line hints to gecko (and possibly other appliations) + # that the entry should be drawn transparently on the canvas. + # Without this, gecko will fill in the background of the entry. + GtkEntry::honors-transparent-bg-hint = 1 + + GtkEntry::progress-border = { 2, 2, 2, 2 } + + #################### + # Color Definitions + #################### + bg[NORMAL] = @bg_color + bg[PRELIGHT] = shade (1.02, @bg_color) + bg[SELECTED] = @selected_bg_color + bg[INSENSITIVE] = @bg_color + bg[ACTIVE] = shade (0.9, @bg_color) + + fg[NORMAL] = @fg_color + fg[PRELIGHT] = @fg_color + fg[SELECTED] = @selected_fg_color + fg[INSENSITIVE] = darker (@bg_color) + fg[ACTIVE] = @fg_color + + text[NORMAL] = @text_color + text[PRELIGHT] = @text_color + text[SELECTED] = @selected_fg_color + text[INSENSITIVE] = darker (@bg_color) + text[ACTIVE] = @selected_fg_color + + base[NORMAL] = @base_color + base[PRELIGHT] = shade (0.95, @bg_color) + base[SELECTED] = @selected_bg_color + base[INSENSITIVE] = @bg_color + base[ACTIVE] = shade (0.9, @selected_bg_color) + + engine "clearlooks" { + colorize_scrollbar = TRUE + reliefstyle = 1 + menubarstyle = 2 + toolbarstyle = 1 + animation = FALSE + radius = 3.0 + style = GUMMY + + # Set a hint to disable backward compatibility fallbacks. + hint = "use-hints" + } +} + +style "wide" { + xthickness = 2 + ythickness = 2 +} + +style "wider" { + xthickness = 3 + ythickness = 3 +} + +style "entry" { + xthickness = 3 + ythickness = 3 + + bg[SELECTED] = mix (0.4, @selected_bg_color, @base_color) + fg[SELECTED] = @text_color + + engine "clearlooks" { + focus_color = shade (0.65, @selected_bg_color) + } +} + +style "spinbutton" { + + engine "clearlooks" { + hint = "spinbutton" + } +} + +style "scale" { + xthickness = 2 + ythickness = 2 + + engine "clearlooks" { + hint = "scale" + } +} + +style "vscale" { + + engine "clearlooks" { + hint = "vscale" + } +} + +style "hscale" { + + engine "clearlooks" { + hint = "hscale" + } +} + +style "scrollbar" { + xthickness = 2 + ythickness = 2 + + engine "clearlooks" { + hint = "scrollbar" + } +} + +style "hscrollbar" { + + engine "clearlooks" { + hint = "hscrollbar" + } +} + +style "vscrollbar" { + + engine "clearlooks" { + hint = "vscrollbar" + } +} + +style "notebook_bg" { + + bg[NORMAL] = shade (1.02, @bg_color) +} + +style "button" { + xthickness = 3 + ythickness = 3 + + bg[NORMAL] = shade (1.04, @bg_color) + bg[PRELIGHT] = shade (1.06, @bg_color) + bg[ACTIVE] = shade (0.85, @bg_color) +} + +# The color is changed by the notebook_bg style, this style +# changes the x/ythickness +style "notebook" { + xthickness = 3 + ythickness = 3 +} + +style "statusbar" { + + engine "clearlooks" { + hint = "statusbar" + } +} + +style "comboboxentry" { + + engine "clearlooks" { + # Note: + # If you set the appears-as-list option on comboboxes in the theme, + # then you should set this hint on the combobox instead. + hint = "comboboxentry" + } +} + +style "menubar" { + + engine "clearlooks" { + hint = "menubar" + } +} + +style "menu" { + xthickness = 0 + ythickness = 0 + + bg[NORMAL] = shade (1.08, @bg_color) + + engine "clearlooks" { + radius = 0.0 + } +} + +style "menu_item" { + xthickness = 2 + ythickness = 3 + + fg[PRELIGHT] = @selected_fg_color +} + +# This style is there to modify the separator menu items. The goals are: +# 1. Get a specific height. +# 2. The line should go to the edges (ie. no border at the left/right) +style "separator_menu_item" { + xthickness = 1 + ythickness = 0 + + GtkSeparatorMenuItem::horizontal-padding = 0 + GtkWidget::wide-separators = 1 + GtkWidget::separator-width = 1 + GtkWidget::separator-height = 7 +} + +style "frame_title" { + + fg[NORMAL] = lighter (@fg_color) +} + +style "treeview" { + + engine "clearlooks" { + hint = "treeview" + } +} + +# The almost useless progress bar style +style "progressbar" { + xthickness = 1 + ythickness = 1 + + fg[PRELIGHT] = @selected_fg_color + + engine "clearlooks" { + # Explicitly set the radius for the progress bars inside menu items. + radius = 3.0 + + hint = "progressbar" + } +} + +# This style is based on the default style, so that the colors from the button +# style are overriden again. +style "treeview_header" = "default" { + xthickness = 2 + ythickness = 1 + + engine "clearlooks" { + hint = "treeview-header" + } +} + +style "tooltips" { + xthickness = 4 + ythickness = 4 + + bg[NORMAL] = @tooltip_bg_color + fg[NORMAL] = @tooltip_fg_color +} + +style "nautilus_location" { + + bg[NORMAL] = mix (0.60, shade (1.05, @bg_color), @selected_bg_color) +} + +# Wrokaroudn style for places where the text color is used instead of the fg color. +style "text_is_fg_color_workaround" { + + text[NORMAL] = @fg_color + text[PRELIGHT] = @fg_color + text[SELECTED] = @selected_fg_color + text[ACTIVE] = @fg_color + text[INSENSITIVE] = darker (@bg_color) +} + +# Workaround style for menus where the text color is used instead of the fg color. +style "menuitem_text_is_fg_color_workaround" { + + text[NORMAL] = @fg_color + text[PRELIGHT] = @selected_fg_color + text[SELECTED] = @selected_fg_color + text[ACTIVE] = @fg_color + text[INSENSITIVE] = darker (@bg_color) +} + +# Workaround style for places where the fg color is used instead of the text color. +style "fg_is_text_color_workaround" { + + fg[NORMAL] = @text_color + fg[PRELIGHT] = @text_color + fg[SELECTED] = @selected_fg_color + fg[ACTIVE] = @selected_fg_color + fg[INSENSITIVE] = darker (@bg_color) +} + +# Style to set the toolbar to use a flat style. This is because the "New" button in +# Evolution is not drawn transparent. So if there is a gradient in the background it will +# look really wrong. +# See http://bugzilla.gnome.org/show_bug.cgi?id=446953. +style "evo_new_button_workaround" { + + engine "clearlooks" { + toolbarstyle = 0 + } +} + + +############################################################################### +# The following part of the gtkrc applies the different styles to the widgets. +############################################################################### + +# The default style is applied to every widget +class "GtkWidget" style "default" + +class "GtkSeparator" style "wide" +class "GtkFrame" style "wide" +class "GtkCalendar" style "wide" +class "GtkEntry" style "entry" + +class "GtkSpinButton" style "spinbutton" +class "GtkScale" style "scale" +class "GtkVScale" style "vscale" +class "GtkHScale" style "hscale" +class "GtkScrollbar" style "scrollbar" +class "GtkHScrollbar" style "hscrollbar" +class "GtkVScrollbar" style "vscrollbar" + +# General matching follows. The order is choosen so that the right styles override +# each other. EG. progressbar needs to be more important than the menu match. +widget_class "*" style "notebook_bg" +# This is not perfect, it could be done better. +# (That is modify *every* widget in the notebook, and change those back that +# we really don't want changed) +widget_class "**" style "notebook_bg" +widget_class "**" style "notebook_bg" +widget_class "**" style "notebook_bg" +widget_class "**" style "notebook_bg" +widget_class "**" style "notebook_bg" + +widget_class "*" style "button" +widget_class "*" style "notebook" +widget_class "**" style "statusbar" + +widget_class "**" style "comboboxentry" +widget_class "**" style "comboboxentry" + +widget_class "**" style "menubar" +widget_class "**" style "menu" +widget_class "**" style "menu_item" +widget_class "**" style "separator_menu_item" + +widget_class "*.." style "frame_title" +widget_class "*.*" style "treeview" + +widget_class "*" style "progressbar" + +# Treeview headers (and similar stock GTK+ widgets) +widget_class "*.." style "treeview_header" +widget_class "*.." style "treeview_header" +widget_class "*.." style "treeview_header" +widget_class "*.." style "treeview_header" + +# The window of the tooltip is called "gtk-tooltip" +################################################################## +# FIXME: +# This will not work if one embeds eg. a button into the tooltip. +# As far as I can tell right now we will need to rework the theme +# quite a bit to get this working correctly. +# (It will involve setting different priorities, etc.) +################################################################## +widget "gtk-tooltip*" style "tooltips" + +########################################################################## +# Following are special cases and workarounds for issues in applications. +########################################################################## + +# Workaround for the evolution ETable (bug #527532) +widget_class "*.ETable.ECanvas" style "treeview_header" +# Workaround for the evolution ETree +widget_class "*.ETree.ECanvas" style "treeview_header" + +# Special case the nautilus-extra-view-widget +# ToDo: A more generic approach for all applications that have a widget like this. +widget "*.nautilus-extra-view-widget" style : highest "nautilus_location" + +# Work around for http://bugzilla.gnome.org/show_bug.cgi?id=382646 +# Note that this work around assumes that the combobox is _not_ in appears-as-list mode. +widget_class "*.." style "text_is_fg_color_workaround" +# This is the part of the workaround that fixes the menus +widget "*.gtk-combobox-popup-menu.*" style "menuitem_text_is_fg_color_workaround" + +# Work around the usage of GtkLabel inside GtkListItems to display text. +# This breaks because the label is shown on a background that is based on the base color. +widget_class "**" style "fg_is_text_color_workaround" +# GtkCList also uses the fg color to draw text on top of the base colors. +widget_class "*" style "fg_is_text_color_workaround" +# Nautilus when renaming files, and maybe other places. +widget_class "*" style "fg_is_text_color_workaround" + +# See the documentation of the style. +widget_class "EShellWindow.GtkVBox.BonoboDock.BonoboDockBand.BonoboDockItem*" style "evo_new_button_workaround" diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/osx/Info.plist /tmp/DgSymrsclJ/tucan-0.3.9/packages/osx/Info.plist --- tucan-0.3.8/packages/osx/Info.plist 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/packages/osx/Info.plist 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + TucanManager + CFBundleGetInfoString + 0.3.8 alpha + CFBundleIconFile + tucan.icns + CFBundleIdentifier + org.tucan + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleShortVersionString + 0.3.8 + CFBundleSignature + ???? + CFBundleVersion + 0.3.8 + NSHumanReadableCopyright + The Tucan Project, GPLv3. + LSMinimumSystemVersion + 10.5 + + diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/osx/instructions.txt /tmp/DgSymrsclJ/tucan-0.3.9/packages/osx/instructions.txt --- tucan-0.3.8/packages/osx/instructions.txt 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/packages/osx/instructions.txt 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,41 @@ +Build Tucan OSX +------------------------- +#prepare source ++ sh release_tucan.sh , rename as "src" ++ delete packages/ + +#create the .app ++ export PATH=$PATH:/Users/Crak/bin ++ ige-mac-bundler tucan.bundle ++ copy TucanManager to Contents/MacOS/ +!!! copy /lib/libigemacintegration.0.dylib to Contents/Resources/lib/ + +#clean up (save size!) ++ remove Contents/Resources/lib/gtk-2.0/2.10.0/print-backends ++ remove Contents/Resources/lib/gtk-2.0/2.10.0/engines/* (leave clearlooks) + +#compile binary +gcc `python-config --libs` `python-config --includes` -u _PyMac_Error -framework CoreFoundation -Wall tucan.c -o tucan + +#debug +IGE_DEBUG_LAUNCHER=yes TucanManager.app/Contents/MacOS/TucanManager + +#create .dmg +hdiutil create -size 80m -volname Tucan\ Manager -srcfolder build tucan-0.3.8.dmg + +#ERRORS +1. +[2009-08-08 15:39:41,999] easy-share.parsers ERROR: http://www.easy-share.com/1699551079.html :decoder jpeg not available +Traceback (most recent call last): + File "/Users/Crak/.tucan/plugins/easy-share/parsers.py", line 60, in __init__ + tes = Tesseract(opener.open(self.captcha_url).read(), self.filter_image) + File "/Users/Crak/Desktop/TucanManager.app/Contents/Resources/src/tesseract.py", line 57, in __init__ + p.feed(data) + File "/Library/Python/2.5/site-packages/PIL/ImageFile.py", line 411, in feed + im.mode, d, a, im.decoderconfig + File "/Library/Python/2.5/site-packages/PIL/Image.py", line 375, in _getdecoder + raise IOError("decoder %s not available" % decoder_name) +IOError: decoder jpeg not available + +2. +08/08/09 13:48:26 [0x0-0x1bf1bf].org.tucan[4796] glib.GError: Unable to load image-loading module: @executable_path/Resources/lib/gtk-2.0/2.10.0/loaders/libpixbufloader-ico.so: dlopen(@executable_path/Resources/lib/gtk-2.0/2.10.0/loaders/libpixbufloader-ico.so, 1): image not found diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/osx/tucan.bundle /tmp/DgSymrsclJ/tucan-0.3.9/packages/osx/tucan.bundle --- tucan-0.3.8/packages/osx/tucan.bundle 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/packages/osx/tucan.bundle 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,49 @@ + + + + + /Users/Crak/gtk/inst + ${env:HOME}/Desktop + + + + ${project}/Info.plist + + + ${prefix}/bin/pygtk-demo + + + + + ${project}/src + + + + + ${project}/tesseract + + + + ${project}/tucan.icns + + + + ${project}/gtkrc + + + + + ${project}/environment.sh + + + + + ${prefix}/lib/gtk-2.0 + + + + + ${prefix}/lib/python2.5 + + + diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/osx/tucan.c /tmp/DgSymrsclJ/tucan-0.3.9/packages/osx/tucan.c --- tucan-0.3.8/packages/osx/tucan.c 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/packages/osx/tucan.c 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,67 @@ +/* Main binary for OSX bundle. +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### +*/ + +#include +#include +#include +#include +#include + +#define TUCAN_FILE "/src/tucan.py" + +int main() +{ + int result = 0; + + CFBundleRef mainBundle = CFBundleGetMainBundle(); + CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle); + char path[PATH_MAX]; + + if (CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path, PATH_MAX)) + { + char *tucan_path; + + tucan_path = (char *)calloc(strlen(path) + strlen(TUCAN_FILE) + 1, sizeof(char)); + strcpy(tucan_path, path); + strcat(tucan_path, TUCAN_FILE); + printf("Tucan Path: %s\n", tucan_path); + + FILE *fp = fopen(tucan_path, "r"); + + Py_Initialize(); + + char *argv[1]; + argv[0] = tucan_path; + argv[1] = NULL; + + PySys_SetArgv(1, argv); + result = PyRun_SimpleFile(fp, tucan_path); + + //printf("PATH: %s\n", Py_GetPath()); + Py_Finalize(); + + free(tucan_path); + } + CFRelease(resourcesURL); + + return result; +} Binary files /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/osx/tucan.icns and /tmp/DgSymrsclJ/tucan-0.3.9/packages/osx/tucan.icns differ diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/packages/osx/TucanManager /tmp/DgSymrsclJ/tucan-0.3.9/packages/osx/TucanManager --- tucan-0.3.8/packages/osx/TucanManager 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/packages/osx/TucanManager 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,63 @@ +#!/bin/sh + +if test "x$IGE_DEBUG_LAUNCHER" != x; then + set -x +fi + +if test "x$IGE_DEBUG_GDB" != x; then + EXEC="gdb --args" +else + EXEC=exec +fi + +name="`basename $0`" +tmp="`pwd`/$0" +tmp=`dirname "$tmp"` +tmp=`dirname "$tmp"` +bundle=`dirname "$tmp"` +bundle_contents="$bundle"/Contents +bundle_res="$bundle_contents"/Resources +bundle_lib="$bundle_res"/lib +bundle_bin="$bundle_res"/bin +bundle_data="$bundle_res"/share +bundle_etc="$bundle_res"/etc + +export DYLD_LIBRARY_PATH="$bundle_lib" +export XDG_CONFIG_DIRS="$bundle_etc"/xdg +export XDG_DATA_DIRS="$bundle_data" +export GTK_DATA_PREFIX="$bundle_res" +export GTK_EXE_PREFIX="$bundle_res" +export GTK_PATH="$bundle_res" + +export GTK2_RC_FILES="$bundle_etc/gtk-2.0/gtkrc" +export GTK_IM_MODULE_FILE="$bundle_etc/gtk-2.0/gtk.immodules" +export GDK_PIXBUF_MODULE_FILE="$bundle_etc/gtk-2.0/gdk-pixbuf.loaders" +export PANGO_RC_FILE="$bundle_etc/pango/pangorc" + +# We need a UTF-8 locale. +lang=`defaults read .GlobalPreferences AppleLocale 2>/dev/null` +if test "$?" != "0"; then + lang=`defaults read .GlobalPreferences AppleCollationOrder 2>/dev/null | sed 's/_.*//'` +fi +if test "$?" == "0"; then + export LANG="`grep \"\`echo $lang\`_\" /usr/share/locale/locale.alias | \ + tail -n1 | sed 's/\./ /' | awk '{print $2}'`.UTF-8" +fi + +if test -f "$bundle_lib/charset.alias"; then + export CHARSETALIASDIR="$bundle_lib" +fi + +# Extra arguments can be added in environment.sh. +EXTRA_ARGS= +if test -f "$bundle_res/environment.sh"; then + source "$bundle_res/environment.sh" +fi + +# Strip out the argument added by the OS. +if [ x`echo "x$1" | sed -e "s/^x-psn_.*//"` == x ]; then + shift 1 +fi + +$EXEC "$bundle_contents"/MacOS/tucan $* $EXTRA_ARGS + diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/preferences.py /tmp/DgSymrsclJ/tucan-0.3.9/preferences.py --- tucan-0.3.8/preferences.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/preferences.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,428 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import __builtin__ -import gettext - -import pygtk -pygtk.require('2.0') -import gtk -import gobject -import pango - -import cons -import config -import service_config -import url_open - -from service_preferences import ServicePreferences -from message import Message -from file_chooser import FileChooser -from update_manager import UpdateManager - -LANGUAGES = [("English", "en"), ("French", "fr"), ("German", "de"), ("Italian", "it"), ("Polish", "pl"), ("Portuguese", "pt"), ("Slovak", "sk"), ("Spanish", "es"), ("Swedish", "se")] - -class Preferences(gtk.Dialog): - """""" - def __init__(self, configuration, show_services=False, updates=None): - """""" - gtk.Dialog.__init__(self) - self.set_icon_from_file(cons.ICON_PREFERENCES) - self.set_title("Tucan Preferences") - self.set_size_request(500,500) - - self.config = configuration - - self.notebook = gtk.Notebook() - self.notebook.set_property("homogeneous", True) - self.vbox.pack_start(self.notebook) - self.new_page(_("General Configuration"), cons.ICON_PREFERENCES_MAIN, self.init_main()) - self.new_page(_("Service Configuration"), cons.ICON_PREFERENCES_SERVICES, self.init_services()) - self.new_page(_("Advanced Configuration"), cons.ICON_PREFERENCES_ADVANCED, self.init_advanced()) - - #action area - cancel_button = gtk.Button(None, gtk.STOCK_CANCEL) - save_button = gtk.Button(None, gtk.STOCK_SAVE) - self.action_area.pack_start(cancel_button) - self.action_area.pack_start(save_button) - cancel_button.connect("clicked", self.close) - save_button.connect("clicked", self.save) - - self.connect("response", self.close) - self.show_all() - - if show_services: - self.notebook.set_current_page(1) - if updates: - gobject.idle_add(self.update_manager, None, updates) - self.run() - - def save(self, button): - """""" - self.config.set(config.SECTION_MAIN, config.OPTION_LANGUAGE, [lang[1] for lang in LANGUAGES][self.language.get_active()]) - - #live changes - self.config.set(config.SECTION_MAIN, config.OPTION_MAX_DOWNLOADS, str(self.max_downloads.get_value_as_int())) - __builtin__.max_downloads = self.max_downloads.get_value_as_int() - self.config.set(config.SECTION_MAIN, config.OPTION_MAX_DOWNLOAD_SPEED, str(self.max_download_speed.get_value_as_int())) - __builtin__.max_download_speed = self.max_download_speed.get_value_as_int() - - #self.config.set(config.SECTION_MAIN, config.OPTION_MAX_UPLOADS, str(self.max_uploads.get_value_as_int())) - self.config.set(config.SECTION_MAIN, config.OPTION_DOWNLOADS_FOLDER, self.downloads_folder.get_label()) - - model = self.treeview.get_model() - iter = model.get_iter_root() - while iter: - configuration = model.get_value(iter, 3) - configuration.enable(model.get_value(iter, 2)) - if not self.config.has_option(config.SECTION_SERVICES, model.get_value(iter,1)): - self.config.set(config.SECTION_SERVICES, model.get_value(iter,1), configuration.path) - iter = model.iter_next(iter) - - self.config.set(config.SECTION_ADVANCED, config.OPTION_TRAY_CLOSE, str(self.tray_close.get_active())) - self.config.set(config.SECTION_ADVANCED, config.OPTION_ADVANCED_PACKAGES, str(self.advanced_packages.get_active())) - self.config.set(config.SECTION_ADVANCED, config.OPTION_SAVE_SESSION, str(self.save_session.get_active())) - self.config.set(config.SECTION_ADVANCED, config.OPTION_AUTO_UPDATE, str(self.auto_update.get_active())) - self.config.set(config.SECTION_ADVANCED, config.OPTION_SHOW_UPLOADS, str(self.show_uploads.get_active())) - self.config.set(config.SECTION_ADVANCED, config.OPTION_ENABLE_PROXY, str(self.enable_proxy.get_active())) - self.config.set(config.SECTION_ADVANCED, config.OPTION_PROXY_URL, self.proxy_url.get_text()) - self.config.set(config.SECTION_ADVANCED, config.OPTION_PROXY_PORT, str(self.proxy_port.get_value_as_int())) - - #change proxy settings - if self.enable_proxy.get_active(): - proxy_url, proxy_port = self.config.get_proxy() - url_open.set_proxy(proxy_url, proxy_port) - else: - url_open.set_proxy(None) - - self.config.save() - self.close() - - def new_page(self, tab_name, tab_image, page): - """""" - vbox = gtk.VBox() - vbox.pack_start(gtk.image_new_from_file(tab_image)) - vbox.pack_start(gtk.Label(tab_name)) - vbox.show_all() - self.notebook.append_page(page, vbox) - self.notebook.set_tab_label_packing(page, True, True, gtk.PACK_START) - - def init_main(self): - """""" - vbox = gtk.VBox() - - frame = gtk.Frame() - frame.set_label_widget(gtk.image_new_from_file(cons.ICON_LANGUAGE)) - frame.set_border_width(5) - vbox.pack_start(frame, False, False) - hbox = gtk.HBox() - vbox1 = gtk.VBox() - frame.add(vbox1) - hbox = gtk.HBox() - vbox1.pack_start(hbox, False, False, 5) - label = gtk.Label(_("Choose language: ")) - hbox.pack_start(label, False, False, 10) - aspect = gtk.AspectFrame() - aspect.set_shadow_type(gtk.SHADOW_NONE) - hbox.pack_start(aspect) - self.language = gtk.combo_box_new_text() - for lang in [lang[0] for lang in LANGUAGES]: - self.language.append_text(lang) - self.language.set_active([lang[1] for lang in LANGUAGES].index(self.config.get(config.SECTION_MAIN, config.OPTION_LANGUAGE))) - hbox.pack_start(self.language, False, False, 10) - - frame = gtk.Frame() - frame.set_label_widget(gtk.image_new_from_file(cons.ICON_NETWORK)) - frame.set_border_width(5) - vbox.pack_start(frame, False, False) - vbox1 = gtk.VBox() - frame.add(vbox1) - hbox = gtk.HBox() - label = gtk.Label(_("Max simultaneous downloads: ")) - hbox.pack_start(label, False, False, 10) - aspect = gtk.AspectFrame() - aspect.set_shadow_type(gtk.SHADOW_NONE) - hbox.pack_start(aspect) - self.max_downloads = gtk.SpinButton(None, 1, 0) - self.max_downloads.set_range(1,20) - self.max_downloads.set_increments(1,0) - self.max_downloads.set_numeric(True) - self.max_downloads.set_value(self.config.getint(config.SECTION_MAIN, config.OPTION_MAX_DOWNLOADS)) - hbox.pack_start(self.max_downloads, False, False, 10) - vbox1.pack_start(hbox, False, False, 2) - hbox = gtk.HBox() - label = gtk.Label(_("Max download speed: ")) - hbox.pack_start(label, False, False, 10) - aspect = gtk.AspectFrame() - aspect.set_shadow_type(gtk.SHADOW_NONE) - hbox.pack_start(aspect) - self.max_download_speed = gtk.SpinButton(None, 4, 0) - self.max_download_speed.set_range(0,5000) - self.max_download_speed.set_increments(4,0) - self.max_download_speed.set_numeric(True) - self.max_download_speed.set_value(self.config.getint(config.SECTION_MAIN, config.OPTION_MAX_DOWNLOAD_SPEED)) - hbox.pack_start(self.max_download_speed, False, False, 10) - vbox1.pack_start(hbox, False, False, 2) - #hbox = gtk.HBox() - #label = gtk.Label(_("Max simultaneous uploads: ")) - #hbox.pack_start(label, False, False, 10) - #aspect = gtk.AspectFrame() - #aspect.set_shadow_type(gtk.SHADOW_NONE) - #hbox.pack_start(aspect) - #self.max_uploads = gtk.SpinButton(None, 1, 0) - #self.max_uploads.set_range(1,10) - #self.max_uploads.set_increments(1,0) - #self.max_uploads.set_numeric(True) - #self.max_uploads.set_value(self.config.getint(config.SECTION_MAIN, config.OPTION_MAX_UPLOADS)) - #hbox.pack_start(self.max_uploads, False, False, 10) - #vbox1.pack_start(hbox, False, False, 2) - - frame = gtk.Frame() - frame.set_label_widget(gtk.image_new_from_file(cons.ICON_FOLDER)) - frame.set_border_width(5) - vbox.pack_start(frame, False, False) - vbox1 = gtk.VBox() - frame.add(vbox1) - hbox = gtk.HBox() - vbox1.pack_start(hbox, False, False, 5) - - label = gtk.Label(_("Downloads Folder: ")) - hbox.pack_start(label, False, False, 10) - path = self.config.get(config.SECTION_MAIN, config.OPTION_DOWNLOADS_FOLDER) - self.downloads_folder = gtk.Label(path) - hbox.pack_start(self.downloads_folder, False, False, 10) - bbox = gtk.HButtonBox() - bbox.set_layout(gtk.BUTTONBOX_END) - hbox.pack_start(bbox, True, True, 10) - button = gtk.Button(None, gtk.STOCK_OPEN) - button.connect("clicked", self.choose_path) - bbox.pack_start(button) - - vbox.show_all() - return vbox - - def choose_path(self, button): - """""" - FileChooser(self, self.downloads_folder.set_label, self.downloads_folder.get_label()) - - def init_services(self): - """""" - vbox = gtk.VBox() - - frame = gtk.Frame() - frame.set_size_request(-1, 300) - vbox.pack_start(frame) - frame.set_border_width(10) - scroll = gtk.ScrolledWindow() - frame.add(scroll) - scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - store = gtk.ListStore(gtk.gdk.Pixbuf, str, bool, gobject.TYPE_PYOBJECT) - self.treeview = gtk.TreeView(store) - scroll.add(self.treeview) - self.treeview.connect("row-activated", self.service_preferences) - - self.treeview.set_rules_hint(True) - #self.treeview.set_headers_visible(False) - - tree_icon = gtk.TreeViewColumn('Icon') - icon_cell = gtk.CellRendererPixbuf() - icon_cell.set_property("width", 50) - tree_icon.pack_start(icon_cell, False) - tree_icon.add_attribute(icon_cell, 'pixbuf', 0) - self.treeview.append_column(tree_icon) - - tree_name = gtk.TreeViewColumn('Name') - name_cell = gtk.CellRendererText() - name_cell.set_property("width", 300) - name_cell.set_property("xalign", 0.1) - tree_name.pack_start(name_cell, True) - tree_name.add_attribute(name_cell, 'text', 1) - self.treeview.append_column(tree_name) - - tree_enable = gtk.TreeViewColumn('Enabled') - enable_cell = gtk.CellRendererToggle() - enable_cell.connect("toggled", self.toggled) - tree_enable.pack_start(enable_cell, True) - tree_enable.add_attribute(enable_cell, 'active', 2) - self.treeview.append_column(tree_enable) - - #fill store - for path, icon_path, name, enabled, configuration in self.config.get_services(): - self.add_service(path, icon_path, name, enabled, configuration) - - frame = gtk.Frame() - frame.set_border_width(10) - frame.set_shadow_type(gtk.SHADOW_NONE) - vbox.pack_start(frame, False, False) - bbox = gtk.HButtonBox() - bbox.set_layout(gtk.BUTTONBOX_EDGE) - frame.add(bbox) - button = gtk.Button(None, gtk.STOCK_FIND) - button.connect("clicked", self.update_manager) - bbox.pack_start(button) - button = gtk.Button(None, gtk.STOCK_REMOVE) - button.connect("clicked", self.delete_service) - bbox.pack_start(button) - aspect = gtk.AspectFrame() - aspect.set_shadow_type(gtk.SHADOW_NONE) - bbox.pack_start(aspect) - button = gtk.Button(None, gtk.STOCK_INFO) - button.connect("clicked", self.service_info) - bbox.pack_start(button) - - hbox = gtk.HBox() - vbox.pack_start(hbox, False, False, 5) - label = gtk.Label() - hbox.pack_start(label, False, False, 10) - label.set_markup("* " + _("Restart Tucan to apply service changes.") + "") - - return vbox - - def service_info(self, button): - """""" - model, iter = self.treeview.get_selection().get_selected() - if iter: - self.service_preferences(None, model.get_path(iter)) - - def add_service(self, path, icon_path, name, enabled, configuration): - """""" - if configuration: - if icon_path: - icon = gtk.gdk.pixbuf_new_from_file_at_size(icon_path, 32, 32) - else: - icon = gtk.gdk.pixbuf_new_from_file_at_size(cons.ICON_MISSING, 32, 32) - self.treeview.get_model().append((icon, name, enabled, configuration)) - else: - Message(self, cons.SEVERITY_ERROR, path , _("Service not configured.")) - - def update_manager(self, button, updates=None): - """""" - UpdateManager(self.config, self, updates) - self.treeview.get_model().clear() - for path, icon_path, name, enabled, configuration in self.config.get_services(): - self.add_service(path, icon_path, name, enabled, configuration) - - def delete_service(self, button): - """""" - model, iter = self.treeview.get_selection().get_selected() - if iter: - next_iter = model.iter_next(iter) - self.config.remove_option(config.SECTION_SERVICES, model.get_value(iter, 1)) - model.remove(iter) - if next_iter: - self.treeview.set_cursor_on_cell(model.get_path(next_iter)) - - def toggled(self, button, path): - """""" - model = self.treeview.get_model() - if button.get_active(): - active = False - else: - tos = _("Before using this service, you must accept it's terms of service at ") + model.get_value(model.get_iter(path), 1) - m = Message(self, cons.SEVERITY_INFO, _("Tucan Manager - Terms of service"), tos, True) - active = m.accepted - button.set_active(active) - model.set_value(model.get_iter(path), 2, active) - - def service_preferences(self, treeview, path, view_column=None): - """""" - model = self.treeview.get_model() - icon = model.get_value(model.get_iter(path), 0) - name = model.get_value(model.get_iter(path), 1) - config = model.get_value(model.get_iter(path), 3) - ServicePreferences(self, name, icon, config) - - def init_advanced(self): - """""" - frame = gtk.Frame() - frame.set_label_widget(gtk.image_new_from_file(cons.ICON_ADVANCED)) - frame.set_border_width(10) - hbox = gtk.HBox() - frame.add(hbox) - vbox = gtk.VBox() - hbox.pack_start(vbox, True, True, 10) - - self.tray_close = gtk.CheckButton(_("Close to tray.")) - vbox.pack_start(self.tray_close, False, False, 5) - self.tray_close.set_active(self.config.getboolean(config.SECTION_ADVANCED, config.OPTION_TRAY_CLOSE)) - - self.save_session = gtk.CheckButton(_("Save session on close.")) - vbox.pack_start(self.save_session, False, False, 5) - self.save_session.set_active(self.config.getboolean(config.SECTION_ADVANCED, config.OPTION_SAVE_SESSION)) - - self.advanced_packages = gtk.CheckButton(_("Default advanced packages.")) - vbox.pack_start(self.advanced_packages, False, False, 5) - self.advanced_packages.set_active(self.config.getboolean(config.SECTION_ADVANCED, config.OPTION_ADVANCED_PACKAGES)) - - self.auto_update = gtk.CheckButton(_("Automatic check for updates.")) - vbox.pack_start(self.auto_update, False, False, 5) - self.auto_update.set_active(self.config.getboolean(config.SECTION_ADVANCED, config.OPTION_AUTO_UPDATE)) - - self.show_uploads = gtk.CheckButton(_("Show uploads.")) - vbox.pack_start(self.show_uploads, False, False, 5) - self.show_uploads.set_active(self.config.getboolean(config.SECTION_ADVANCED, config.OPTION_SHOW_UPLOADS)) - - self.enable_proxy = gtk.CheckButton(_("Enable proxy:")) - vbox.pack_start(self.enable_proxy, False, False, 5) - self.enable_proxy.set_active(self.config.getboolean(config.SECTION_ADVANCED, config.OPTION_ENABLE_PROXY)) - self.enable_proxy.connect("toggled", self.change_state) - - self.proxy_box = gtk.HBox() - vbox.pack_start(self.proxy_box, False, False, 5) - self.proxy_box.pack_start(gtk.Label("HTTP Proxy:"), False, False, 5) - self.proxy_url = gtk.Entry() - self.proxy_box.pack_start(self.proxy_url, True, True, 5) - self.proxy_url.set_text(self.config.get(config.SECTION_ADVANCED, config.OPTION_PROXY_URL)) - - self.proxy_box.pack_start(gtk.Label("Port:"), False, False, 5) - self.proxy_port = gtk.SpinButton(None, 1, 0) - self.proxy_box.pack_start(self.proxy_port, False, False, 5) - self.proxy_port.set_range(0,65535) - self.proxy_port.set_increments(1,0) - self.proxy_port.set_numeric(True) - self.proxy_port.set_value(self.config.getint(config.SECTION_ADVANCED, config.OPTION_PROXY_PORT)) - - self.change_state() - - return frame - - def change_state(self, button=None): - """""" - self.proxy_box.set_sensitive(self.enable_proxy.get_active()) - - def close(self, widget=None, other=None): - """""" - enabled_services = 0 - model = self.treeview.get_model() - iter = model.get_iter_root() - while iter: - if model.get_value(iter, 3).getboolean(service_config.SECTION_MAIN, service_config.OPTION_ENABLED): - enabled_services += 1 - iter = model.iter_next(iter) - if enabled_services > 0: - self.destroy() - else: - Message(self, cons.SEVERITY_WARNING, _("Tucan Manager - No services enabled!") , _("Enable some services and restart Tucan.")) - self.run() - -if __name__ == "__main__": - import gettext - _ = gettext.gettext - x = Preferences(config.Config()) diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/README /tmp/DgSymrsclJ/tucan-0.3.9/README --- tucan-0.3.8/README 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/README 2009-10-07 00:02:31.000000000 +0100 @@ -15,6 +15,8 @@ - http://filefactory.com/ - http://easy-share.com/ - http://badongo.com/ + - http://depositfiles.com/ + - http://hotfile.com/ - (...) @@ -38,29 +40,33 @@ Plugins ========= - ---------------------------------------------------------------------------- + +===================+========================+=============================+ | Hosting site | Downloads | Uploads | - ---------------------------------------------------------------------------- + +===================+========================+=============================+ | rapidshare.com | anonymous and premium | | - ---------------------------------------------------------------------------- + +-------------------+------------------------+-----------------------------+ | megaupload.com | anonymous and premium | | - ---------------------------------------------------------------------------- + +-------------------+------------------------+-----------------------------+ | gigasize.com | anonymous | | - ---------------------------------------------------------------------------- + +-------------------+------------------------+-----------------------------+ | mediafire.com | anonymous | | - ---------------------------------------------------------------------------- + +-------------------+------------------------+-----------------------------+ | 4shared.com | anonymous | | - ---------------------------------------------------------------------------- + +-------------------+------------------------+-----------------------------+ | sendspace.com | anonymous | | - ---------------------------------------------------------------------------- + +-------------------+------------------------+-----------------------------+ | zshare.net | anonymous | | - ---------------------------------------------------------------------------- + +-------------------+------------------------+-----------------------------+ | filefactory.com | anonymous | | - ---------------------------------------------------------------------------- + +-------------------+------------------------+-----------------------------+ | easy-share.com | anonymous | | - ---------------------------------------------------------------------------- + +-------------------+------------------------+-----------------------------+ | badongo.com | anonymous | | - ---------------------------------------------------------------------------- + +-------------------+------------------------+-----------------------------+ + | depositfiles.com | anonymous | | + +-------------------+------------------------+-----------------------------+ + | hotfile.com | anonymous | | + +-------------------+------------------------+-----------------------------+ =================== @@ -73,35 +79,35 @@ - Tesseract OCR (with the english language pack) - SVG Rendering Library - -------------------------------------------------------------------- + +=========================+===================+====================+ | Package \ Distribution | Debian / Ubuntu | Gentoo | - -------------------------------------------------------------------- + +=========================+===================+====================+ | Python >= 2.5 | python | dev-lang/python | - -------------------------------------------------------------------- + +-------------------------+-------------------+--------------------+ | PyGTK | python-gtk2 | dev-python/pygtk | - -------------------------------------------------------------------- + +-------------------------+-------------------+--------------------+ | Python Imaging Library | python-imaging | dev-python/imaging | - -------------------------------------------------------------------- + +-------------------------+-------------------+--------------------+ | Tesseract OCR | tesseract-ocr | app-text/tesseract | | (english language pack) | tesseract-ocr-eng | (linguas_en) | - -------------------------------------------------------------------- + +-------------------------+-------------------+--------------------+ | SVG Rendering Library | librsvg2-common | gnome-base/librsvg | - -------------------------------------------------------------------- + +-------------------------+-------------------+--------------------+ - --------------------------------------------------- - | Arch | Fedora | OpenSuSE | - --------------------------------------------------- - | python | python | python | - --------------------------------------------------- - | pygtk | pygtk2 | python-gtk | - --------------------------------------------------- - | pil | python-imaging | python-imaging | - --------------------------------------------------- - | tesseract | tesseract | tesseract | - | | tesseract-langpack | | - --------------------------------------------------- - | librsvg | librsvg2 | librsvg | - --------------------------------------------------- + +===========+====================+================+================+ + | Arch | Fedora | OpenSuSE | Mandriva | + +===========+====================+================+================+ + | python | python | python | python | + +-----------+--------------------+----------------+----------------+ + | pygtk | pygtk2 | python-gtk | pygtk2.0 | + +-----------+--------------------+----------------+----------------+ + | pil | python-imaging | python-imaging | python-imaging | + +-----------+--------------------+----------------+----------------+ + | tesseract | tesseract | tesseract | tesseract | + | | tesseract-langpack | | | + +-----------+--------------------+----------------+----------------+ + | librsvg | librsvg2 | librsvg | librsvg | + +-----------+--------------------+----------------+----------------+ =================== diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/README.es /tmp/DgSymrsclJ/tucan-0.3.9/README.es --- tucan-0.3.8/README.es 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/README.es 2009-10-07 00:02:31.000000000 +0100 @@ -15,6 +15,8 @@ - http://filefactory.com/ - http://easy-share.com/ - http://badongo.com/ + - http://depositfiles.com/ + - http://hotfile.com/ - (...) @@ -38,29 +40,33 @@ Plugins ========= - ---------------------------------------------------------------------------- + +===================+========================+=============================+ | Hosting site | Downloads | Uploads | - ---------------------------------------------------------------------------- + +===================+========================+=============================+ | rapidshare.com | anonymous and premium | | - ---------------------------------------------------------------------------- + +-------------------+------------------------+-----------------------------+ | megaupload.com | anonymous and premium | | - ---------------------------------------------------------------------------- + +-------------------+------------------------+-----------------------------+ | gigasize.com | anonymous | | - ---------------------------------------------------------------------------- + +-------------------+------------------------+-----------------------------+ | mediafire.com | anonymous | | - ---------------------------------------------------------------------------- + +-------------------+------------------------+-----------------------------+ | 4shared.com | anonymous | | - ---------------------------------------------------------------------------- + +-------------------+------------------------+-----------------------------+ | sendspace.com | anonymous | | - ---------------------------------------------------------------------------- + +-------------------+------------------------+-----------------------------+ | zshare.net | anonymous | | - ---------------------------------------------------------------------------- + +-------------------+------------------------+-----------------------------+ | filefactory.com | anonymous | | - ---------------------------------------------------------------------------- + +-------------------+------------------------+-----------------------------+ | easy-share.com | anonymous | | - ---------------------------------------------------------------------------- + +-------------------+------------------------+-----------------------------+ | badongo.com | anonymous | | - ---------------------------------------------------------------------------- + +-------------------+------------------------+-----------------------------+ + | depositfiles.com | anonymous | | + +-------------------+------------------------+-----------------------------+ + | hotfile.com | anonymous | | + +-------------------+------------------------+-----------------------------+ =================== @@ -73,35 +79,35 @@ - Tesseract OCR (con el paquete del idioma inglés) - SVG Rendering Library - -------------------------------------------------------------------- + +=========================+===================+====================+ | Paquete \ Distribución | Debian / Ubuntu | Gentoo | - -------------------------------------------------------------------- + +=========================+===================+====================+ | Python >= 2.5 | python | dev-lang/python | - -------------------------------------------------------------------- + +-------------------------+-------------------+--------------------+ | PyGTK | python-gtk2 | dev-python/pygtk | - -------------------------------------------------------------------- + +-------------------------+-------------------+--------------------+ | Python Imaging Library | python-imaging | dev-python/imaging | - -------------------------------------------------------------------- + +-------------------------+-------------------+--------------------+ | Tesseract OCR | tesseract-ocr | app-text/tesseract | | (english language pack) | tesseract-ocr-eng | (linguas_en) | - -------------------------------------------------------------------- + +-------------------------+-------------------+--------------------+ | SVG Rendering Library | librsvg2-common | gnome-base/librsvg | - -------------------------------------------------------------------- + +-------------------------+-------------------+--------------------+ - --------------------------------------------------- - | Arch | Fedora | OpenSuSE | - --------------------------------------------------- - | python | python | python | - --------------------------------------------------- - | pygtk | pygtk2 | python-gtk | - --------------------------------------------------- - | pil | python-imaging | python-imaging | - --------------------------------------------------- - | tesseract | tesseract | tesseract | - | | tesseract-langpack | | - --------------------------------------------------- - | librsvg | librsvg2 | librsvg | - --------------------------------------------------- + +===========+====================+================+================+ + | Arch | Fedora | OpenSuSE | Mandriva | + +===========+====================+================+================+ + | python | python | python | python | + +-----------+--------------------+----------------+----------------+ + | pygtk | pygtk2 | python-gtk | pygtk2.0 | + +-----------+--------------------+----------------+----------------+ + | pil | python-imaging | python-imaging | python-imaging | + +-----------+--------------------+----------------+----------------+ + | tesseract | tesseract | tesseract | tesseract | + | | tesseract-langpack | | | + +-----------+--------------------+----------------+----------------+ + | librsvg | librsvg2 | librsvg | librsvg | + +-----------+--------------------+----------------+----------------+ =================== diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/service_config.py /tmp/DgSymrsclJ/tucan-0.3.9/service_config.py --- tucan-0.3.8/service_config.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/service_config.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,165 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import os -import pickle -import base64 -import logging -logger = logging.getLogger(__name__) - -from ConfigParser import SafeConfigParser - -import cons - -SECTION_MAIN = "main" - -SECTION_ANONYMOUS_DOWNLOAD = "anonymous_download" -SECTION_USER_DOWNLOAD = "user_download" -SECTION_PREMIUM_DOWNLOAD = "premium_download" - -SECTION_ANONYMOUS_UPLOAD = "anonymous_upload" -SECTION_USER_UPLOAD = "user_upload" -SECTION_PREMIUM_UPLOAD = "premium_upload" - -OPTION_UPDATE = "update" -OPTION_NAME = "name" -OPTION_ICON = "icon" -OPTION_ENABLED = "enabled" - -OPTION_PREMIUM_COOKIE = "premium_cookie" -OPTION_USER_COOKIE = "user_cookie" - -OPTION_DOWNLOADS = "downloads" -OPTION_UPLOADS = "uploads" - -OPTION_PATH = "path" -OPTION_AUTHOR = "author" -OPTION_VERSION = "version" -OPTION_SLOTS = "slots" -OPTION_CAPTCHA = "captcha" -OPTION_ACCOUNTS = "accounts" - -CONF = "service.conf" - -class ServiceConfig(SafeConfigParser): - """""" - def __init__(self, path, fd=None): - """""" - SafeConfigParser.__init__(self) - self.path = path - if fd: - self.readfp(fd) - elif os.path.exists(unicode(os.path.join(self.path, CONF))): - self.read(unicode(os.path.join(self.path, CONF))) - - def check_config(self): - """""" - if self.has_section(SECTION_MAIN): - return True - - def enable(self, enabled): - """""" - self.set(SECTION_MAIN, OPTION_ENABLED, str(enabled)) - self.save() - - def get_name(self): - """""" - if self.has_option(SECTION_MAIN, OPTION_NAME): - return self.get(SECTION_MAIN, OPTION_NAME) - - def get_update(self): - """""" - if self.has_option(SECTION_MAIN, OPTION_UPDATE): - return self.getint(SECTION_MAIN, OPTION_UPDATE) - else: - return 0 - - def get_icon(self): - """""" - if self.has_option(SECTION_MAIN, OPTION_ICON): - if self.get(SECTION_MAIN, OPTION_ICON) != "None": - return self.path + self.get(SECTION_MAIN, OPTION_ICON) - - def premium_cookie(self): - """""" - get_cookie = None - if self.has_option(SECTION_MAIN, OPTION_PREMIUM_COOKIE): - get_cookie = self.get(SECTION_MAIN, OPTION_PREMIUM_COOKIE) - return OPTION_PREMIUM_COOKIE, get_cookie - - def user_cookie(self): - """""" - get_cookie = None - if self.has_option(SECTION_MAIN, OPTION_USER_COOKIE): - get_cookie = self.get(SECTION_MAIN, OPTION_USER_COOKIE) - return OPTION_USER_COOKIE, get_cookie - - def get_plugins(self, sections): - """""" - result = [] - for section, section_type in sections: - if ((self.has_section(section)) and (len(self.items(section)) > 0)): - result.append((section, self.get(section, OPTION_NAME), section_type)) - return result - - def get_download_plugins(self): - """""" - result = [] - if self.has_option(SECTION_MAIN, OPTION_DOWNLOADS): - if self.getboolean(SECTION_MAIN, OPTION_DOWNLOADS): - result = self.get_plugins([(SECTION_ANONYMOUS_DOWNLOAD, cons.TYPE_ANONYMOUS), (SECTION_USER_DOWNLOAD, cons.TYPE_USER), (SECTION_PREMIUM_DOWNLOAD, cons.TYPE_PREMIUM)]) - return result - - def get_upload_plugins(self): - """""" - result = [] - if self.has_option(SECTION_MAIN, OPTION_UPLOADS): - if self.getboolean(SECTION_MAIN, OPTION_UPLOADS): - result = self.get_plugins([(SECTION_ANONYMOUS_UPLOAD, cons.TYPE_ANONYMOUS), (SECTION_USER_UPLOAD, cons.TYPE_USER), (SECTION_PREMIUM_UPLOAD, cons.TYPE_PREMIUM)]) - return result - - def get_accounts(self, section): - """""" - result = {} - if self.has_section(section): - if os.path.exists(self.path + self.get(section, OPTION_ACCOUNTS)): - try: - f = open(self.path + self.get(section, OPTION_ACCOUNTS), "rb") - result = pickle.loads(base64.b64decode((f.read()))) - f.close() - except EOFError, e: - logger.error("Unable to load account: %s" % e) - return result - - def set_accounts(self, section, accounts): - """""" - if self.has_section(section): - f = open(self.path + self.get(section, OPTION_ACCOUNTS), "wb") - f.write(base64.b64encode(pickle.dumps(accounts))) - f.close() - - def save(self): - """""" - f = open(self.path + CONF, "w") - self.write(f) - f.close() - -if __name__ == "__main__": - c = ServiceConfig("/home/crak/.tucan/plugins/megaupload/") diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/service_manager.py /tmp/DgSymrsclJ/tucan-0.3.9/service_manager.py --- tucan-0.3.8/service_manager.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/service_manager.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,218 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import __builtin__ -import re -import sys -import logging -logger = logging.getLogger(__name__) - -from config import SECTION_MAIN, OPTION_MAX_DOWNLOADS, OPTION_MAX_DOWNLOAD_SPEED -from download_manager import DownloadManager - -import cons - -class Service: - """""" - def __init__(self, name, icon): - """""" - self.icon_path = icon - self.name = name - self.anonymous_download_plugin = None - self.user_download_plugin = None - self.premium_download_plugin = None - self.anonymous_upload_plugins = None - self.user_upload_plugins = None - self.premium_upload_plugins = None - -class ServiceManager: - """""" - def __init__(self, configuration): - """""" - self.services = [] - __builtin__.max_downloads = configuration.getint(SECTION_MAIN, OPTION_MAX_DOWNLOADS) - __builtin__.max_download_speed = configuration.getint(SECTION_MAIN, OPTION_MAX_DOWNLOAD_SPEED) - self.download_manager = DownloadManager(self.get_download_plugin, self.services) - if cons.PLUGIN_PATH not in sys.path: - sys.path.append(cons.PLUGIN_PATH) - for package, icon, service, enabled, config in configuration.get_services(): - s = Service(service, icon) - if enabled: - #download plugins - for plugin_module, plugin_name, plugin_type in config.get_download_plugins(): - logger.info("Loading: %s.%s" % (package, plugin_module)) - module = __import__(package + "." + plugin_module, None, None, ['']) - if plugin_type == cons.TYPE_ANONYMOUS: - s.anonymous_download_plugin = eval("module" + "." + plugin_name + "()") - elif plugin_type == cons.TYPE_USER: - s.user_download_plugin = eval("module" + "." + plugin_name + "()") - elif plugin_type == cons.TYPE_PREMIUM: - s.premium_download_plugin = eval("module" + "." + plugin_name + "(config)") - #upload plugins - for plugin_module, plugin_name, plugin_type in config.get_upload_plugins(): - logger.info("Loading: %s.%s" % (package, plugin_module)) - module = __import__(package + "." + plugin_module, None, None, ['']) - if plugin_type == cons.TYPE_ANONYMOUS: - s.anonymous_upload_plugin = eval("module" + "." + plugin_name + "()") - elif plugin_type == cons.TYPE_USER: - s.user_upload_plugin = eval("module" + "." + plugin_name + "()") - elif plugin_type == cons.TYPE_PREMIUM: - s.premium_upload_plugin = eval("module" + "." + plugin_name + "(config)") - self.services.append(s) - - def prueba(self): - """""" - import url_open - import time - - url_open.set_proxy(None) - links = [("mediafire.com", "http://www.mediafire.com/download.php?z0gjmnwk1d0"), ("mediafire.com", "http://www.mediafire.com/download.php?d4j2nyyr4qy")] - for service, link in links: - name, size, unit = self.get_check_links(service)[0](link) - print name, size, unit - if name: - plugin, plugin_type = self.get_download_plugin(service) - self.download_manager.add("/home/crak/downloads/", name, [(link, plugin, plugin_type, service)], size, unit) - while len(self.download_manager.active_downloads + self.download_manager.pending_downloads) > 0: - print "\n" - self.download_manager.update() - time.sleep(1) - - def get_download_plugin(self, service_name): - """""" - for service in self.services: - if service.name == service_name: - if ((service.premium_download_plugin) and (service.premium_download_plugin.active)): - return service.premium_download_plugin, cons.TYPE_PREMIUM - else: - return service.anonymous_download_plugin, cons.TYPE_ANONYMOUS - - def get_upload_plugin(self, service_name): - """""" - for service in self.services: - if service.name == service_name: - return service.anonymous_upload_plugin - - def get_check_links(self, service_name): - """""" - for service in self.services: - if service.name == service_name: - if ((service.premium_download_plugin) and (service.premium_download_plugin.active)): - return service.premium_download_plugin.check_links, cons.TYPE_PREMIUM - else: - return service.anonymous_download_plugin.check_links, cons.TYPE_ANONYMOUS - - def get_check_files(self, service_name): - """""" - for service in self.services: - if service.name == service_name: - return service.check_files.check - - def filter_service(self, links): - """""" - services = {cons.TYPE_UNSUPPORTED: []} - for link in links: - found = False - if "http://" in link: - tmp = link.split("http://").pop() - if "<" in tmp: - tmp = tmp.split("<")[0] - elif " " in tmp: - tmp = tmp.split(" ")[0] - elif "[" in tmp: - tmp = tmp.split("[")[0] - elif "'" in tmp: - tmp = tmp.split("'")[0] - link = "http://" + tmp - for service in self.services: - if link.find(service.name) > 0: - found = True - if service.name in services: - services[service.name].append(link) - else: - services[service.name] = [link] - if not found: - services[cons.TYPE_UNSUPPORTED].append(link) - return services - - def create_packages(self, dict): - """""" - packages = [] - files = [] - for service, links in dict.items(): - for link in links: - found = False - for tmp_link in files: - if link[1] == tmp_link[1]: - found = True - if service not in tmp_link[2]: - tmp_link[2].append(service) - tmp_link[0].append(link[0]) - tmp_link[5].append(link[4]) - if not found: - files.append(([link[0]], link[1], [service], link[2], link[3], [link[4]])) - while len(files) > 0: - tmp_name = [] - first = files[0] - others = files[1:] - for link in others: - chars = re.split("[0-9]+", link[1]) - nums = re.split("[^0-9]+", link[1]) - tmp = "" - for i in chars: - if tmp+i == first[1][0:len(tmp+i)]: - tmp += i - for j in nums: - if tmp+j == first[1][0:len(tmp+j)]: - tmp += j - tmp_name.append(tmp) - final_name = "" - for name in tmp_name: - if len(name) > len(final_name): - final_name = name - if len(final_name) > 0: - packages.append((final_name, [first])) - del files[files.index(first)] - tmp_list = [] - for link in files: - if final_name in link[1]: - tmp_list.append(link) - for package_name, package_files in packages: - if package_name == final_name: - package_files += tmp_list - for i in tmp_list: - del files[files.index(i)] - else: - alone_name = first[1] - alone_name = alone_name.split(".") - alone_name.pop() - alone_name = ".".join(alone_name) - packages.append((alone_name, [first])) - del files[files.index(first)] - return packages - - def stop_all(self): - """""" - self.download_manager.quit() - -if __name__ == "__main__": - from config import Config - s = ServiceManager(Config()) - s.prueba() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/service_preferences.py /tmp/DgSymrsclJ/tucan-0.3.9/service_preferences.py --- tucan-0.3.8/service_preferences.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/service_preferences.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,332 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import pygtk -pygtk.require('2.0') -import gtk -import gobject - -import service_config -import cons - -class InfoPreferences(gtk.VBox): - """""" - def __init__(self, section, name, config, accounts=False): - """""" - gtk.VBox.__init__(self) - vbox = gtk.VBox() - - frame = gtk.Frame() - label = gtk.Label() - label.set_markup("" + name + "") - frame.set_label_widget(label) - frame.set_border_width(10) - self.pack_start(frame) - frame.add(vbox) - - hbox = gtk.HBox() - label = gtk.Label() - label.set_markup("" + _("Author") + ":") - hbox.pack_start(label, False, False, 10) - label = gtk.Label(config.get(section, service_config.OPTION_AUTHOR)) - hbox.pack_start(label, False) - aspect = gtk.AspectFrame() - aspect.set_shadow_type(gtk.SHADOW_NONE) - hbox.pack_start(aspect) - label = gtk.Label() - label.set_markup("" + _("Version") + ":") - hbox.pack_start(label, False) - label = gtk.Label(config.get(section, service_config.OPTION_VERSION)) - hbox.pack_start(label, False, False, 10) - vbox.pack_start(hbox, False, False, 5) - - if not accounts: - hbox = gtk.HBox() - label = gtk.Label() - label.set_markup("" + _("Slots") + ":") - hbox.pack_start(label, False, False, 10) - label = gtk.Label(config.get(section, service_config.OPTION_SLOTS)) - hbox.pack_start(label, False) - vbox.pack_start(hbox, False, False, 5) - hbox = gtk.HBox() - label = gtk.Label() - label.set_markup("" + _("Captcha") + ":") - hbox.pack_start(label, False, False, 10) - label = gtk.Label(config.get(section, service_config.OPTION_CAPTCHA)) - hbox.pack_start(label, False) - vbox.pack_start(hbox, False, False, 5) - -class AccountPreferences(InfoPreferences): - """""" - def __init__(self, section, name, config, get_cookie): - """""" - InfoPreferences.__init__(self, section, name, config, True) - - self.get_cookie = get_cookie - - frame = gtk.Frame() - frame.set_label_widget(gtk.image_new_from_file(cons.ICON_ACCOUNT)) - frame.set_border_width(10) - self.pack_start(frame, False, False, 1) - scroll = gtk.ScrolledWindow() - scroll.set_size_request(-1, 110) - scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - frame.add(scroll) - store = gtk.ListStore(gtk.gdk.Pixbuf, str, str, bool, bool, str) - self.treeview = gtk.TreeView(store) - scroll.add(self.treeview) - - self.treeview.set_rules_hint(True) - #self.treeview.set_headers_visible(False) - - tree_icon = gtk.TreeViewColumn('Active') - icon_cell = gtk.CellRendererPixbuf() - icon_cell.set_property("width", 50) - tree_icon.pack_start(icon_cell, True) - tree_icon.add_attribute(icon_cell, 'pixbuf', 0) - self.treeview.append_column(tree_icon) - - tree_name = gtk.TreeViewColumn('User Name') - name_cell = gtk.CellRendererText() - name_cell.set_property("width", 120) - name_cell.set_property("editable", True) - name_cell.connect("edited", self.change, 1) - tree_name.pack_start(name_cell, True) - tree_name.add_attribute(name_cell, 'text', 1) - self.treeview.append_column(tree_name) - - tree_pass = gtk.TreeViewColumn('Password') - pass_cell = gtk.CellRendererText() - pass_cell.set_property("width", 120) - pass_cell.set_property("editable", True) - pass_cell.connect("edited", self.change, 2) - pass_cell.connect("editing-started", self.show_password) - tree_pass.pack_start(pass_cell, True) - tree_pass.add_attribute(pass_cell, 'text', 5) - self.treeview.append_column(tree_pass) - - tree_enable = gtk.TreeViewColumn('Enable') - enable_cell = gtk.CellRendererToggle() - enable_cell.connect("toggled", self.toggled) - tree_enable.pack_start(enable_cell, False) - tree_enable.add_attribute(enable_cell, 'visible', 4) - tree_enable.add_attribute(enable_cell, 'active', 3) - self.treeview.append_column(tree_enable) - - self.active_service_icon = self.treeview.render_icon(gtk.STOCK_YES, gtk.ICON_SIZE_LARGE_TOOLBAR) - self.unactive_service_icon = self.treeview.render_icon(gtk.STOCK_NO, gtk.ICON_SIZE_LARGE_TOOLBAR) - - accounts = config.get_accounts(section) - for name in accounts.keys(): - password, enabled, active = accounts[name] - if active: - icon = self.active_service_icon - else: - icon = self.unactive_service_icon - store.append([icon, name, password, enabled, active, "".join(["*" for i in range(len(password))])]) - - frame = gtk.Frame() - frame.set_border_width(10) - frame.set_shadow_type(gtk.SHADOW_NONE) - self.pack_start(frame, False, False) - bbox = gtk.HButtonBox() - bbox.set_layout(gtk.BUTTONBOX_EDGE) - frame.add(bbox) - button = gtk.Button(None, gtk.STOCK_ADD) - button.connect("clicked", self.add) - bbox.pack_start(button) - button = gtk.Button(None, gtk.STOCK_REMOVE) - button.connect("clicked", self.remove) - bbox.pack_start(button) - aspect = gtk.AspectFrame() - aspect.set_shadow_type(gtk.SHADOW_NONE) - bbox.pack_start(aspect) - button = gtk.Button(None, gtk.STOCK_CONNECT) - button.connect("clicked", self.check) - bbox.pack_start(button) - - def show_password(self, cellrenderertext, editable, path): - """""" - model = self.treeview.get_model() - editable.props.text = model.get_value(model.get_iter(path), 2) - - def change(self, cellrenderertext, path, new_text, column): - """""" - model = self.treeview.get_model() - model.set_value(model.get_iter(path), column, new_text) - if column == 2: - model.set_value(model.get_iter(path), 5, "".join(["*" for i in range(len(new_text))])) - - def add(self, button): - """""" - model = self.treeview.get_model() - iter = model.append([self.unactive_service_icon, "", "", False, False, ""]) - self.treeview.set_cursor(model.get_path(iter), self.treeview.get_column(1), True) - - def remove(self, button): - """""" - model, iter = self.treeview.get_selection().get_selected() - if iter: - next_iter = model.iter_next(iter) - model.remove(iter) - if next_iter: - self.treeview.set_cursor_on_cell(model.get_path(next_iter)) - - def check(self, button): - """""" - model, iter = self.treeview.get_selection().get_selected() - if iter: - cookie = self.get_cookie(model.get_value(iter, 1), model.get_value(iter, 2)) - if cookie: - icon = self.active_service_icon - active = True - else: - icon = self.unactive_service_icon - active = False - model.set_value(iter, 0, icon) - model.set_value(iter, 3, active) - model.set_value(iter, 4, active) - - def toggled(self, button, path): - """""" - model = self.treeview.get_model() - if button.get_active(): - active = False - else: - active = True - button.set_active(active) - model.set_value(model.get_iter(path), 3, active) - - def get_accounts(self): - """""" - model = self.treeview.get_model() - iter = model.get_iter_root() - accounts = {} - while iter: - accounts[model.get_value(iter, 1)] = (model.get_value(iter, 2), model.get_value(iter, 3), model.get_value(iter, 4)) - iter = model.iter_next(iter) - return accounts - -class ServicePreferences(gtk.Dialog): - """""" - def __init__(self, parent, service, icon, config): - """""" - gtk.Dialog.__init__(self) - self.set_icon(icon) - self.set_title(service) - self.set_transient_for(parent) - self.set_size_request(600, 400) - - self.config = config - - hbox = gtk.HBox() - self.vbox.pack_start(hbox, True, True, 5) - frame = gtk.Frame() - hbox.pack_start(frame, False, False, 10) - - store = gtk.TreeStore(str, str, int) - self.treeview = gtk.TreeView(store) - self.treeview.get_selection().connect("changed", self.select) - frame.add(self.treeview) - - self.treeview.set_headers_visible(False) - - tree_name = gtk.TreeViewColumn('Name') - name_cell = gtk.CellRendererText() - name_cell.set_property("width", 100) - tree_name.pack_start(name_cell, True) - tree_name.add_attribute(name_cell, 'text', 1) - self.treeview.append_column(tree_name) - - self.notebook = gtk.Notebook() - hbox.pack_start(self.notebook, True, True, 10) - self.notebook.set_show_tabs(False) - - cont = 0 - plugin_list = [] - plugins = self.config.get_download_plugins() - if plugins: - plugin_list.append(("Download", plugins)) - plugins = self.config.get_upload_plugins() - if plugins: - plugin_list.append(("Upload", plugins)) - for item, plugins in plugin_list: - iter = store.append(None, [None, item, -1]) - for section, section_name, section_type in plugins: - page = gtk.VBox() - if section_type == cons.TYPE_ANONYMOUS: - page = InfoPreferences(section, section_name, self.config) - else: - if section_type == cons.TYPE_USER: - module, name = config.user_cookie() - elif section_type == cons.TYPE_PREMIUM: - module, name = config.premium_cookie() - if name: - module = __import__(service.split(".")[0] + "." + module, None, None, ['']) - get_cookie = eval("module" + "." + name + "()").get_cookie - page = AccountPreferences(section, section_name, self.config, get_cookie) - self.notebook.append_page(page, None) - subiter = store.append(iter, [section, section_type, cont]) - self.treeview.expand_to_path(store.get_path(subiter)) - if cont == 0: - self.treeview.set_cursor_on_cell(store.get_path(subiter)) - cont += 1 - #action area - cancel_button = gtk.Button(None, gtk.STOCK_CANCEL) - save_button = gtk.Button(None, gtk.STOCK_SAVE) - self.action_area.pack_start(cancel_button) - self.action_area.pack_start(save_button) - cancel_button.connect("clicked", self.close) - save_button.connect("clicked", self.save) - - self.connect("response", self.close) - self.show_all() - self.run() - - def select(self, selection): - """""" - model, iter = selection.get_selected() - if iter: - child_iter = model.iter_children(iter) - if child_iter: - selection.select_iter(child_iter) - else: - self.notebook.set_current_page(model.get_value(iter, 2)) - - def save(self, button): - """""" - model = self.treeview.get_model() - iter = model.get_iter_root() - while iter: - child_iter = model.iter_children(iter) - while child_iter: - page = self.notebook.get_nth_page((model.get_value(iter, 2))) - if ((page) and (model.get_value(child_iter, 1) != cons.TYPE_ANONYMOUS)): - self.config.set_accounts(model.get_value(child_iter, 0), page.get_accounts()) - child_iter = model.iter_next(child_iter) - iter = model.iter_next(iter) - self.close() - - def close(self, widget=None, other=None): - """""" - self.destroy() - -if __name__ == "__main__": - x = ServicePreferences("rapidshare.com", gtk.gdk.pixbuf_new_from_file(cons.ICON_MISSING), service_config.ServiceConfig("/home/crak/.tucan/plugins/megaupload/")) diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/service_update.py /tmp/DgSymrsclJ/tucan-0.3.9/service_update.py --- tucan-0.3.8/service_update.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/service_update.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,134 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import os -import urllib2 -import logging -logger = logging.getLogger(__name__) - -from HTMLParser import HTMLParser - -from service_config import ServiceConfig -import config - -import cons - -BASE = "https://forja.rediris.es/svn/cusl3-tucan/trunk" -PLUGINS = "https://forja.rediris.es/svn/cusl3-tucan/branches/default_plugins/" -CONF_FILE = "service.conf" - -class ServiceList(HTMLParser): - """""" - def __init__(self, url): - """""" - HTMLParser.__init__(self) - self.services = [] - try: - self.feed(urllib2.urlopen(urllib2.Request(url)).read()) - except (urllib2.URLError, urllib2.HTTPError), e: - logger.error(e) - self.close() - - def handle_starttag(self, tag, attrs): - """""" - if tag == "dir": - self.services.append(attrs[1][1]) - -class ServiceCheck(HTMLParser): - """""" - def __init__(self, url): - """""" - HTMLParser.__init__(self) - self.files = [] - self.feed(urllib2.urlopen(urllib2.Request(url)).read()) - self.close() - - def handle_starttag(self, tag, attrs): - """""" - if tag == "file": - self.files.append(attrs[1][1]) - -class ServiceUpdate: - """""""" - def __init__(self, config): - """urllib2 does not support proxy and https""" - self.config = config - self.local_services = config.get_services() - self.server_version = None - try: - for line in urllib2.urlopen(urllib2.Request("%s/cons.py" % BASE)).readlines(): - if "VERSION" in line: - self.server_version = line.split('"')[1].split('"')[0] - except Exception, e: - logger.exception(e) - - def get_updates(self): - """""" - new_services = {} - list = ServiceList(PLUGINS) - for remote_service in list.services: - check = ServiceCheck(PLUGINS + remote_service) - found = False - if CONF_FILE in check.files: - try: - #get remote version - config = ServiceConfig(None, urllib2.urlopen(urllib2.Request("%s%s%s" % (PLUGINS, remote_service, CONF_FILE)))) - remote_version = config.get_update() - except Exception, e: - logger.exception(e) - else: - #get local version - for local_service in self.local_services: - if local_service[0] == remote_service.split("/")[0]: - found = True - local_version = local_service[4].get_update() - if remote_version > local_version: - new_services[local_service[2]] = local_service[0], check.files, local_service[1] - if not found: - new_services[config.get_name()] = remote_service.split("/")[0], check.files, None - return new_services - - def install_service(self, service_name, service_dir, files): - """""" - for file_name in files: - try: - handle = urllib2.urlopen(urllib2.Request("%s%s/%s" % (PLUGINS, service_dir, file_name))) - except (urllib2.URLError, urllib2.HTTPError), e: - logger.error(e) - else: - #windows incompatibility - if "text" in handle.info()["Content-Type"]: - write_mode = "w" - else: - write_mode = "wb" - if not os.path.isdir(os.path.join(cons.PLUGIN_PATH, service_dir)): - os.mkdir(os.path.join(cons.PLUGIN_PATH, service_dir)) - logger.warning("Updating: %s" % os.path.join(cons.PLUGIN_PATH, service_dir, file_name)) - f = file(os.path.join(cons.PLUGIN_PATH, service_dir, file_name), write_mode) - f.write(handle.read()) - f.close() - if not self.config.has_option(config.SECTION_SERVICES, service_name): - self.config.set(config.SECTION_SERVICES, service_name, os.path.join(cons.PLUGIN_PATH, service_dir, "")) - -if __name__ == "__main__": - from config import Config - s = ServiceUpdate(Config()) - print s.server_version - print s.get_updates() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/session.py /tmp/DgSymrsclJ/tucan-0.3.9/session.py --- tucan-0.3.8/session.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/session.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,54 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import time -import os.path -import xml.etree.ElementTree - -import cons - -VERSION = "version" -TIMESTAMP = "timestamp" -CLOSED = "closed" - -class Session: - """""" - def __init__(self): - """""" - attrs = {VERSION: cons.TUCAN_VERSION, TIMESTAMP: time.strftime("%Y/%m/%d %H:%M"), CLOSED: "False"} - self.tree = xml.etree.ElementTree.ElementTree(xml.etree.ElementTree.Element("Session", attrs)) - - def load(self): - """""" - try: - self.tree._setroot(self.tree.parse(cons.SESSION_FILE)) - except: - print "error" - else: - print self.tree.getroot() - - def save(self): - """""" - self.tree.write(cons.SESSION_FILE) - -if __name__ == "__main__": - s = Session() - s.save() - s.load() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/sessions.py /tmp/DgSymrsclJ/tucan-0.3.9/sessions.py --- tucan-0.3.8/sessions.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/sessions.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,67 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import os -import pickle - -from ConfigParser import SafeConfigParser - -import cons - -LAST_SESSION = "last.session" - -SECTION_DOWNLOADS = "downloads" -OPTION_PACKAGES = "packages" -OPTION_PACKAGES_INFO = "packages_info" - -PACKAGES = [('D.S03E01.PREAiR.DVDSCR.NOTYOU.cHoPPaHoLiK.part', [(['http://www.megaupload.com/?d=GW1WB3IV', 'http://rapidshare.com/files/143483416/D.S03E01.PREAiR.DVDSCR.NOTYOU.cHoPPaHoLiK.part1.rar'], 'D.S03E01.PREAiR.DVDSCR.NOTYOU.cHoPPaHoLiK.part1.rar', ['megaupload.com', 'rapidshare.com'], 200, 'MB', ['AnonymousMegaupload', 'AnonymousRapidshare']), (['http://www.megaupload.com/?d=TITR6R0P', 'http://rapidshare.com/files/143483557/D.S03E01.PREAiR.DVDSCR.NOTYOU.cHoPPaHoLiK.part2.rar'], 'D.S03E01.PREAiR.DVDSCR.NOTYOU.cHoPPaHoLiK.part2.rar', ['megaupload.com', 'rapidshare.com'], 200, 'MB', ['AnonymousMegaupload', 'AnonymousRapidshare']), (['http://www.megaupload.com/?d=DCJX0RKQ', 'http://rapidshare.com/files/143483236/D.S03E01.PREAiR.DVDSCR.NOTYOU.cHoPPaHoLiK.part3.rar'], 'D.S03E01.PREAiR.DVDSCR.NOTYOU.cHoPPaHoLiK.part3.rar', ['megaupload.com', 'rapidshare.com'], 135, 'MB', ['AnonymousMegaupload', 'AnonymousRapidshare'])]), ('Californication.2x01.samuelro.part', [(['http://rapidshare.com/files/149540090/Californication.2x01.samuelro.part1.rar'], 'Californication.2x01.samuelro.part1.rar', ['rapidshare.com'], 200, 'MB', ['AnonymousRapidshare']), (['http://rapidshare.com/files/149537924/Californication.2x01.samuelro.part2.rar'], 'Californication.2x01.samuelro.part2.rar', ['rapidshare.com'], 41, 'MB', ['AnonymousRapidshare'])]), ('Californication.2x02.samuelro.part', [(['http://rapidshare.com/files/151602033/Californication.2x02.samuelro.part1.rar'], 'Californication.2x02.samuelro.part1.rar', ['rapidshare.com'], 195, 'MB', ['AnonymousRapidshare']), (['http://rapidshare.com/files/151408776/Californication.2x02.samuelro.part2.rar'], 'Californication.2x02.samuelro.part2.rar', ['rapidshare.com'], 45, 'MB', ['AnonymousRapidshare'])])] - -PACKAGES_INFO = [('/home/crak/', 'D.S03E01.PREAiR.DVDSCR.NOTYOU.cHoPPaHoLiK.part', None), ('/home/crak/downloads/', 'Californication.2x01.samuelro.part', 'mierda'), ('/home/crak/downloads/', 'Californication.2x02.samuelro.part', 'cojones')] - -class Sessions(SafeConfigParser): - """""" - def load_session(self, path): - """""" - result = None, None - if os.path.exists(path): - self.read(path) - if self.has_section(SECTION_DOWNLOADS): - if ((self.has_option(SECTION_DOWNLOADS, OPTION_PACKAGES)) and (self.has_option(SECTION_DOWNLOADS, OPTION_PACKAGES_INFO))): - result = pickle.loads(self.get(SECTION_DOWNLOADS, OPTION_PACKAGES)), pickle.loads(self.get(SECTION_DOWNLOADS, OPTION_PACKAGES_INFO)) - return result - - def save_session(self, path, session_packages, session_info): - """""" - if not self.has_section(SECTION_DOWNLOADS): - self.add_section(SECTION_DOWNLOADS) - self.set(SECTION_DOWNLOADS, OPTION_PACKAGES, pickle.dumps(session_packages)) - self.set(SECTION_DOWNLOADS, OPTION_PACKAGES_INFO, pickle.dumps(session_info)) - self.save(path) - - def save(self, path): - """""" - f = open(path, "w") - self.write(f) - f.close() - -if __name__ == "__main__": - s = Sessions() - s.save_default_session(PACKAGES, PACKAGES_INFO) - print s.load_default_session() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/slots.py /tmp/DgSymrsclJ/tucan-0.3.9/slots.py --- tucan-0.3.8/slots.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/slots.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,53 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import time -import logging -logger = logging.getLogger(__name__) - -class Slots: - """""" - def __init__(self, slots=1, wait=300): - """""" - self.time_limit = wait - self.limit = False - self.end_wait = 0 - self.max = slots - self.slots = slots - - def get_slot(self): - """""" - if self.slots > 0: - if time.time() > self.end_wait: - self.limit = False - self.slots -= 1 - return True - - def add_wait(self): - """""" - logger.warning("Wait %i seconds." % self.time_limit) - self.limit = True - self.end_wait = time.time() + self.time_limit - - def return_slot(self): - """""" - if self.slots < self.max: - self.slots += 1 - return True diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/statusbar.py /tmp/DgSymrsclJ/tucan-0.3.9/statusbar.py --- tucan-0.3.8/statusbar.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/statusbar.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,156 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import __builtin__ -import gettext - -import time -import logging -logger = logging.getLogger(__name__) - -import pygtk -pygtk.require('2.0') -import gtk -import gobject - -import cons - -class Statusbar(gtk.Statusbar): - """""" - def __init__(self, limits): - """""" - gtk.Statusbar.__init__(self) - self.set_has_resize_grip(False) - - #download speed limit - frame = gtk.Frame() - self.pack_start(frame, False, False) - hbox = gtk.HBox() - frame.add(hbox) - label = gtk.Label(_("Max speed: ")) - hbox.pack_start(label) - self.max_speed = gtk.SpinButton(None, 4, 0) - self.max_speed.set_property("shadow-type", gtk.SHADOW_NONE) - self.max_speed.set_range(0,5000) - self.max_speed.set_increments(4,0) - self.max_speed.set_numeric(True) - self.max_speed.set_value(__builtin__.max_download_speed) - hbox.pack_start(self.max_speed, False, False, 5) - - self.max_speed.connect("value-changed", self.change_speed) - - #show limits - self.get_limits = limits - - self.menu = gtk.Menu() - - label = gtk.Label("Limits: ") - self.pack_start(label, False) - - self.button = gtk.Button() - self.button.set_image(gtk.Arrow(gtk.ARROW_UP, gtk.SHADOW_NONE)) - self.pack_start(self.button, False) - - self.limits = [] - self.max_limits = 0 - - self.blinking = False - self.white = True - self.button.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#fff")) - - self.button.connect("clicked", self.show_stack) - self.show_all() - - gobject.timeout_add(60000, self.update_limits) - - def synchronize(self): - """""" - self.max_speed.set_value(__builtin__.max_download_speed) - - def change_speed(self, spinbutton): - """""" - __builtin__.max_download_speed = spinbutton.get_value_as_int() - - def update_limits(self): - """""" - self.limits = self.get_limits() - if len(self.limits) > self.max_limits: - if not self.blinking: - gobject.timeout_add(800, self.blink) - self.blinking = True - logger.debug("Limits: %s" % self.limits) - self.max_limits = len(self.limits) - return True - - def blink(self): - """""" - if self.white: - if self.blinking: - self.button.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#f99")) - self.white = False - return True - else: - return False - else: - self.button.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#fff")) - self.white = True - if self.blinking: - return True - else: - return False - - def show_stack(self, widget): - """""" - self.blinking = False - for limit in self.menu: - self.menu.remove(limit) - self.limits = self.get_limits() - if len(self.limits) == 0: - self.limits = [("None", "", "", None)] - for service, type, hour, icon_path in self.limits: - limit = gtk.MenuItem() - vbox = gtk.VBox() - hbox = gtk.HBox() - if icon_path: - icon = gtk.gdk.pixbuf_new_from_file(icon_path) - else: - icon = gtk.gdk.pixbuf_new_from_file(cons.ICON_MISSING) - hbox.pack_start(gtk.image_new_from_pixbuf(icon.scale_simple(24, 24, gtk.gdk.INTERP_BILINEAR))) - hbox.pack_start(gtk.Label(service), True, True, 5) - vbox.pack_start(hbox, True, False, 1) - hbox = gtk.HBox() - hbox.pack_start(gtk.Label(hour), True, True) - hbox.pack_start(gtk.Label(type), True, True, 5) - vbox.pack_start(hbox) - limit.add(vbox) - self.menu.append(limit) - self.menu.append(gtk.SeparatorMenuItem()) - self.menu.show_all() - self.menu.popup(None, None, self.menu_position, 1, 0, widget.get_allocation()) - - def menu_position(self, menu, rect): - """""" - width, height = menu.size_request() - window_x, window_y = self.parent.get_parent_window().get_position() - return rect.x + window_x - (width - rect.width), rect.y + window_y - height, True - -if __name__ == "__main__": - g = LimitStack() - gtk.main() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/tesseract.py /tmp/DgSymrsclJ/tucan-0.3.9/tesseract.py --- tucan-0.3.8/tesseract.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/tesseract.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,75 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import os -import sys -import subprocess -import tempfile - -import ImageFile -import Image -import TiffImagePlugin - -import cons - -IMAGE_SUFFIX = ".tif" -TEXT_SUFFIX = ".txt" - -class Tesseract: - """""" - def __init__(self, data, filter=None): - """""" - if "win" in sys.platform: - self.image_name = os.path.join(sys.path[0], "tmp.tif") - self.text_name = os.path.join(sys.path[0], "tmp") - self.tesseract = os.path.join(sys.path[0], "tesseract", "tesseract.exe") - else: - self.text = tempfile.NamedTemporaryFile(suffix=TEXT_SUFFIX) - self.image = tempfile.NamedTemporaryFile(suffix=IMAGE_SUFFIX) - self.image_name = self.image.name - self.text_name = self.text.name.rsplit(TEXT_SUFFIX, 1)[0] - self.tesseract = "tesseract" - p = ImageFile.Parser() - p.feed(data) - if filter: - image = filter(p.close()) - else: - image = p.close() - image.save(self.image_name) - - def get_captcha(self): - """""" - captcha = "" - if "win" in sys.platform: - if subprocess.call([self.tesseract, self.image_name, self.text_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE, creationflags=134217728) == 0: - f = file(self.text_name + TEXT_SUFFIX, "r") - captcha = f.readline().strip() - f.close() - else: - if subprocess.call([self.tesseract, self.image_name, self.text_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0: - captcha = self.text.file.readline().strip() - self.text.file.close() - self.image.file.close() - return captcha - -if __name__ == "__main__": - f = file("tmp.png", "r") - t = Tesseract(f.read()) - print t.get_captcha() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/TODO /tmp/DgSymrsclJ/tucan-0.3.9/TODO --- tucan-0.3.8/TODO 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/TODO 2009-10-07 00:02:31.000000000 +0100 @@ -5,4 +5,3 @@ - Upload System. - GenericTreeModel. - Fill all docstrings. -- Native support MACOSX. diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/toolbar.py /tmp/DgSymrsclJ/tucan-0.3.9/toolbar.py --- tucan-0.3.8/toolbar.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/toolbar.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,37 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import pygtk -pygtk.require('2.0') -import gtk - -class Toolbar(gtk.Toolbar): - """""" - def __init__(self, list): - """list = [(tool_name, image, callback),]""" - gtk.Toolbar.__init__(self) - self.set_style(gtk.TOOLBAR_BOTH) - for button in list: - if button == None: - item = gtk.SeparatorToolItem() - else: - item = gtk.ToolButton(button[1], button[0]) - item.connect("clicked", button[2]) - self.insert(item, -1) \ No newline at end of file diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/tray_icon.py /tmp/DgSymrsclJ/tucan-0.3.9/tray_icon.py --- tucan-0.3.8/tray_icon.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/tray_icon.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,71 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import pygtk -pygtk.require('2.0') -import gtk - -import cons - -class TrayIcon(gtk.StatusIcon): - """""" - def __init__(self, show, hide, menu): - """""" - gtk.StatusIcon.__init__(self) - self.set_tooltip("Tucan Manager - Version: %s" % cons.TUCAN_VERSION) - self.set_from_file(cons.ICON_TUCAN) - self.set_visible(True) - - self.window_visible = True - self.show_window = show - self.hide_window = hide - - self.menu = gtk.Menu() - for item in menu: - if item == None: - tmp = gtk.SeparatorMenuItem() - else: - tmp = gtk.ImageMenuItem(item[0]) - tmp.connect('activate', item[1]) - self.menu.append(tmp) - self.menu.show_all() - - self.connect('activate', self.activate) - self.connect('popup-menu', self.popup_menu) - - def activate(self, statusicon, event=None): - """""" - if self.window_visible: - self.hide_window() - self.window_visible = False - else: - self.show_window() - self.window_visible = True - - def popup_menu(self, statusicon, button, time): - """""" - self.menu.popup(None, None, gtk.status_icon_position_menu, button, time, self) - - def change_tooltip(self, statusbar, context, text): - """""" - #if context == "Downloads": - tmp = text.split("\t") - message = "Downloads: " + "".join(tmp[1:]) + "\n" + tmp[0].strip() - self.set_tooltip(message) diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/tree.py /tmp/DgSymrsclJ/tucan-0.3.9/tree.py --- tucan-0.3.8/tree.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/tree.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,410 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import pygtk -pygtk.require('2.0') -import gtk -import gobject -import pango - -from statusbar import Statusbar - -import cons - -class Tree(gtk.VBox): - """""" - def __init__(self, menu, manager): - """""" - gtk.VBox.__init__(self) - scroll = gtk.ScrolledWindow() - scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self.treeview = gtk.TreeView(gtk.TreeStore(gtk.gdk.Pixbuf, str, str, str, int, bool, str, str, str, str, str)) - scroll.add(self.treeview) - self.pack_start(scroll) - - self.menu = gtk.Menu() - for item in menu: - if item == None: - subitem = gtk.SeparatorMenuItem() - else: - subitem = gtk.ImageMenuItem(item[0]) - subitem.connect("activate", item[1]) - self.menu.append(subitem) - self.menu.show_all() - self.treeview.connect("button-press-event", self.mouse_menu) - - self.get_files = manager.get_files - - self.treeview.set_rules_hint(True) - self.treeview.set_headers_visible(False) - - #tree columns - tree_icon = gtk.TreeViewColumn('Icon') - icon_cell = gtk.CellRendererPixbuf() - tree_icon.pack_start(icon_cell, False) - tree_icon.add_attribute(icon_cell, 'pixbuf', 0) - self.treeview.append_column(tree_icon) - - tree_name = gtk.TreeViewColumn('Name') - name_cell = gtk.CellRendererText() - name_cell.set_property("width-chars", 60) - name_cell.set_property("ellipsize", pango.ELLIPSIZE_MIDDLE) - tree_name.pack_start(name_cell, True) - tree_name.add_attribute(name_cell, 'text', 3) - self.treeview.append_column(tree_name) - - tree_progress = gtk.TreeViewColumn('Progress') - tree_progress.set_min_width(150) - progress_cell = gtk.CellRendererProgress() - tree_progress.pack_start(progress_cell, True) - tree_progress.add_attribute(progress_cell, 'value', 4) - tree_progress.add_attribute(progress_cell, 'visible', 5) - self.treeview.append_column(tree_progress) - - tree_current_size = gtk.TreeViewColumn('Current Size') - current_size_cell = gtk.CellRendererText() - tree_current_size.pack_start(current_size_cell, False) - tree_current_size.add_attribute(current_size_cell, 'text', 6) - self.treeview.append_column(tree_current_size) - - tree_total_size = gtk.TreeViewColumn('Total Size') - total_size_cell = gtk.CellRendererText() - tree_total_size.pack_start(total_size_cell, False) - tree_total_size.add_attribute(total_size_cell, 'text', 7) - self.treeview.append_column(tree_total_size) - - tree_speed = gtk.TreeViewColumn('Speed') - speed_cell = gtk.CellRendererText() - tree_speed.pack_start(speed_cell, False) - tree_speed.add_attribute(speed_cell, 'text', 8) - self.treeview.append_column(tree_speed) - - tree_time = gtk.TreeViewColumn('Time Left') - time_cell = gtk.CellRendererText() - tree_time.pack_start(time_cell, False) - tree_time.add_attribute(time_cell, 'text', 9) - self.treeview.append_column(tree_time) - - tree_plugins = gtk.TreeViewColumn('Plugin') - plugins_cell = gtk.CellRendererText() - tree_plugins.pack_start(plugins_cell, False) - tree_plugins.add_attribute(plugins_cell, 'text', 10) - self.treeview.append_column(tree_plugins) - - #icons - self.package_icon = self.treeview.render_icon(gtk.STOCK_OPEN, gtk.ICON_SIZE_MENU) - self.active_service_icon = self.treeview.render_icon(gtk.STOCK_YES, gtk.ICON_SIZE_MENU) - self.unactive_service_icon = self.treeview.render_icon(gtk.STOCK_NO, gtk.ICON_SIZE_MENU) - self.correct_icon = self.treeview.render_icon(gtk.STOCK_APPLY, gtk.ICON_SIZE_MENU) - self.failed_icon = self.treeview.render_icon(gtk.STOCK_CANCEL, gtk.ICON_SIZE_MENU) - self.wait_icon = self.treeview.render_icon(gtk.STOCK_REFRESH, gtk.ICON_SIZE_MENU) - self.active_icon = self.treeview.render_icon(gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_MENU) - self.pending_icon = self.treeview.render_icon(gtk.STOCK_MEDIA_PAUSE, gtk.ICON_SIZE_MENU) - self.stoped_icon = self.treeview.render_icon(gtk.STOCK_MEDIA_STOP, gtk.ICON_SIZE_MENU) - self.icons = {cons.STATUS_CORRECT: self.correct_icon, cons.STATUS_ERROR: self.failed_icon, cons.STATUS_WAIT: self.wait_icon, cons.STATUS_ACTIVE: self.active_icon, cons.STATUS_PEND: self.pending_icon, cons.STATUS_STOP: self.stoped_icon} - - self.status_bar = Statusbar(manager.get_limits) - self.pack_start(self.status_bar, False) - self.status_bar.push(self.status_bar.get_context_id("Downloads"), " No Downloads Active.") - self.updating = False - - def mouse_menu(self, widget, event): - """right button""" - if event.button == 3: - model, paths = self.treeview.get_selection().get_selected_rows() - if len(paths) > 0: - self.menu.popup(None, None, None, event.button, event.time) - - def add_package(self, package_name, package_path, package, password): - """ - TreeStore(icon, status, password, name, progress, progress_visible, current_size, total_size, speed, time, services) - """ - tmp_size = [] - model = self.treeview.get_model() - package_iter = model.append(None, [self.package_icon, cons.STATUS_PEND, password, package_name, 0, True, None, None, None, None, package_path]) - for item in package: - tmp_size.append((item[3], item[4])) - item_iter = model.append(package_iter, [self.pending_icon, cons.STATUS_PEND, None, item[1], 0, True, None, str(item[3])+item[4], None, None, str(item[2])]) - self.treeview.expand_to_path(model.get_path(item_iter)) - for link in item[0]: - link_iter = model.append(item_iter, [self.unactive_service_icon, cons.STATUS_PEND, None, link, 0, False, None, None, None, None, item[5][item[0].index(link)]]) - package_size, package_unit = self.normalize(tmp_size) - model.set_value(package_iter, 7, str(package_size)+package_unit) - if not self.updating: - self.updating = True - gobject.timeout_add(1000, self.update) - return package_iter - - def update(self): - """(icon, status, None, name, progress, progress_visible, current_size, total_size, speed, time, services)""" - files = self.get_files() - if len(files) > 0: - model = self.treeview.get_model() - package_iter = model.get_iter_root() - active_downloads = 0 - complete_downloads = 0 - total_downloads = 0 - total_speed = 0 - while package_iter: - file_iter = model.iter_children(package_iter) - #package_status = model.set_value(package_iter, 0) - package_progress = 0 - package_speed = 0 - tmp_actual_size = [] - tmp_total_size = [] - while file_iter: - total_downloads += 1 - name = model.get_value(file_iter, 3) - for file in files: - if file.name == name: - model.set_value(file_iter, 0, self.icons[file.status]) - model.set_value(file_iter, 1, file.status) - if file.status in [cons.STATUS_ACTIVE, cons.STATUS_WAIT]: - active_downloads += 1 - elif file.status == cons.STATUS_CORRECT: - complete_downloads += 1 - model.set_value(file_iter, 4, file.progress) - package_progress += file.progress - if file.actual_size > 0: - model.set_value(file_iter, 6, str(file.actual_size)+file.actual_size_unit) - tmp_actual_size.append((file.actual_size, file.actual_size_unit)) - tmp_total_size.append((file.total_size, file.total_size_unit)) - if file.speed > 1: - model.set_value(file_iter, 8, str(file.speed)+cons.UNIT_SPEED) - package_speed += file.speed - elif file.speed == 0: - model.set_value(file_iter, 8, None) - if file.status == cons.STATUS_CORRECT: - if not file.time > 0: - file.time = 1 - file.actual_size = file.total_size - file.actual_size_unit = file.total_size_unit - model.set_value(file_iter, 9, self.calculate_time(file.time)) - link_iter = model.iter_children(file_iter) - while link_iter: - for tmp_link in file.links: - if tmp_link.url == model.get_value(link_iter, 3): - service_icon = self.unactive_service_icon - link_status = cons.STATUS_STOP - if tmp_link.active: - service_icon = self.active_service_icon - link_status = cons.STATUS_ACTIVE - model.set_value(link_iter, 0, service_icon) - model.set_value(link_iter, 1, link_status) - link_iter = model.iter_next(link_iter) - file_iter = model.iter_next(file_iter) - package_actual_size, package_actual_unit = self.normalize(tmp_actual_size) - package_total_size, package_total_unit = self.normalize(tmp_total_size) - if package_actual_size > 0: - if int(package_progress/model.iter_n_children(package_iter)) == 100: - model.set_value(package_iter, 4, 100) - else: - model.set_value(package_iter, 4, int((float(self.get_size(package_actual_size, package_actual_unit))/float(self.get_size(package_total_size, package_total_unit)))*100)) - model.set_value(package_iter, 6, str(package_actual_size)+package_actual_unit) - if package_speed > 0: - model.set_value(package_iter, 8, str(package_speed)+cons.UNIT_SPEED) - else: - model.set_value(package_iter, 8, None) - total_speed += package_speed - package_iter = model.iter_next(package_iter) - self.status_bar.pop(self.status_bar.get_context_id("Downloads")) - self.status_bar.push(self.status_bar.get_context_id("Downloads"), " Downstream %dKB/s \tTotal %d \t Complete %d \t Active %d" % (total_speed, total_downloads, complete_downloads, active_downloads)) - return True - - def normalize(self, sizes): - """""" - total = 0 - total_unit = cons.UNIT_KB - for size, unit in sizes: - total += self.get_size(size, unit) - tmp = int(total/1024) - if tmp > 0: - total = tmp - total_unit = cons.UNIT_MB - tmp = int(tmp/1024) - # if tmp > 0: - # total = tmp - # total_unit = cons.UNIT_GB - return total, total_unit - - def get_size(self, size, unit): - """""" - if unit == cons.UNIT_KB: - return size - elif unit == cons.UNIT_MB: - return size*1024 - #elif unit == cons.UNIT_GB: - # return size*1024*1024 - - def get_packages(self): - """""" - model = self.treeview.get_model() - package_iter = model.get_iter_root() - packages = [] - info = [] - while package_iter: - files = [] - file_iter = model.iter_children(package_iter) - while file_iter: - if model.get_value(file_iter, 1) != cons.STATUS_CORRECT: - links = [] - plugins = [] - link_iter = model.iter_children(file_iter) - while link_iter: - links.append(model.get_value(link_iter, 3)) - plugins.append(model.get_value(link_iter, 10)) - link_iter = model.iter_next(link_iter) - name = model.get_value(file_iter, 3) - tmp = model.get_value(file_iter, 7) - for unit in [cons.UNIT_KB, cons.UNIT_MB]: - tmp_size = tmp.split(unit) - if len(tmp_size) > 1: - size_unit = unit - size = int(tmp_size[0]) - break - tmp = model.get_value(file_iter, 10) - tmp = tmp.split(",") - service_list = [] - for service in tmp: - service_list.append(service.split("\'")[1]) - files.append((links, name, service_list, size, size_unit, plugins)) - file_iter = model.iter_next(file_iter) - if len(files) > 0: - name = model.get_value(package_iter, 3) - packages.append((name, files)) - path = model.get_value(package_iter, 10).split(name)[0] - info.append((path, name, model.get_value(package_iter, 2))) - package_iter = model.iter_next(package_iter) - return packages, info - - def get_links(self, iter): - """""" - links = [] - model = self.treeview.get_model() - file_iter = model.iter_children(iter) - if not file_iter: - links.append(model.get_value(iter, 3)) - while file_iter: - link_iter = model.iter_children(file_iter) - if not link_iter: - links.append(model.get_value(file_iter, 3)) - while link_iter: - links.append(model.get_value(link_iter, 3)) - link_iter = model.iter_next(link_iter) - file_iter = model.iter_next(file_iter) - return links - - def package_files(self, package_iter): - """""" - files = [] - model = self.treeview.get_model() - file_iter = model.iter_children(package_iter) - while file_iter: - if model.get_value(file_iter, 1) not in [cons.STATUS_ACTIVE, cons.STATUS_WAIT, cons.STATUS_CORRECT]: - files.append(model.get_value(file_iter, 3)) - file_iter = model.iter_next(file_iter) - return files - - def clear(self): - """""" - files = [] - model = self.treeview.get_model() - package_iter = model.get_iter_root() - while package_iter: - tmp_iter = package_iter - package_iter = model.iter_next(package_iter) - files += self.delete_package([cons.STATUS_CORRECT], tmp_iter) - return files - - def delete_package(self, status, package_iter): - """""" - tmp = [] - model = self.treeview.get_model() - file_iter = model.iter_children(package_iter) - while file_iter: - if model.get_value(file_iter, 1) in status: - tmp.append(model.get_value(file_iter, 3)) - file_iter = model.iter_next(file_iter) - if len(tmp) == model.iter_n_children(package_iter): - model.remove(package_iter) - else: - tmp = [] - return tmp - - def delete_file(self, status, iter): - """""" - model = self.treeview.get_model() - if model.get_value(iter, 1) in status: - if model.iter_n_children(model.iter_parent(iter)) > 1: - result = model.get_value(iter, 3) - model.remove(iter) - return result - - def delete_link(self, status, iter): - """""" - result = None, None - model = self.treeview.get_model() - file_iter = model.iter_parent(iter) - if model.iter_n_children(file_iter) > 1: - if model.get_value(iter, 1) == cons.STATUS_STOP: - result = model.get_value(file_iter, 3), model.get_value(iter, 3) - model.remove(iter) - return result - - def move_up(self, iter): - """""" - model = self.treeview.get_model() - package_iter = model.iter_parent(iter) - file_iter = model.iter_children(package_iter) - prev_iter = None - while ((file_iter) and (model.get_path(file_iter) != model.get_path(iter))): - prev_iter = file_iter - file_iter = model.iter_next(file_iter) - if prev_iter: - model.move_before(iter, prev_iter) - return True - - def move_down(self, iter): - """""" - model = self.treeview.get_model() - next_iter = model.iter_next(iter) - if next_iter: - model.move_after(iter, next_iter) - return True - - def calculate_time(self, time): - """""" - result = None - hours = 0 - minutes = 0 - while time >= cons.HOUR: - time = time - cons.HOUR - hours += 1 - while time >= cons.MINUTE: - time = time - cons.MINUTE - minutes += 1 - seconds = time - if hours > 0: - result = str(hours) + "h" + str(minutes) + "m" + str(seconds) + "s" - elif minutes > 0: - result = str(minutes) + "m" + str(seconds) + "s" - elif seconds > 0: - result = str(seconds) + "s" - return result Binary files /tmp/Mj7pJvsoYS/tucan-0.3.8/tucan.1.gz and /tmp/DgSymrsclJ/tucan-0.3.9/tucan.1.gz differ diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/tucan.py /tmp/DgSymrsclJ/tucan-0.3.9/tucan.py --- tucan-0.3.8/tucan.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/tucan.py 2009-10-07 00:02:31.000000000 +0100 @@ -20,72 +20,162 @@ ############################################################################### import __builtin__ -import os.path +import os import sys import logging +import optparse -import pygtk -pygtk.require('2.0') -import gtk -import gobject - -from gui import Gui - -import url_open -import config -import cons +import core.misc as misc +import core.url_open as url_open +import core.config as config +import core.cons as cons class Tucan: """""" def __init__(self): """""" #exception hook - self.old_exception_hook = sys.excepthook sys.excepthook = self.exception_hook + + #parse options + parser = optparse.OptionParser() + parser.add_option("-w", "--wizard", dest="wizard", help="setup: accounts, services, updates", metavar="TYPE") + parser.add_option("-d", "--daemon", action="store_true", dest="daemon", default=False, help="no interaction interface") + parser.add_option("-c", "--cli", action="store_true", dest="cli", default=False, help="command line interface") + parser.add_option("-i", "--input-links", dest="links_file", help="import links from FILE", metavar="FILE") + parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False, help="print log to stdout") + parser.add_option("-V", "--version", action="store_true", dest="version", default=False, help="print version and exit") + options, args = parser.parse_args() + + if options.version: + print "%s %s" % (cons.TUCAN_NAME, cons.TUCAN_VERSION) + sys.exit() #configuration - self.configuration = config.Config() + __builtin__.configuration = config.Config() sys.path.append(cons.PLUGIN_PATH) - #globals - __builtin__.max_downloads = self.configuration.getint(config.SECTION_MAIN, config.OPTION_MAX_DOWNLOADS) - __builtin__.max_download_speed = self.configuration.getint(config.SECTION_MAIN, config.OPTION_MAX_DOWNLOAD_SPEED) - #logging if os.path.exists(cons.LOG_FILE): if os.path.exists("%s.old" % cons.LOG_FILE): os.remove("%s.old" % cons.LOG_FILE) os.rename(cons.LOG_FILE, "%s.old" % cons.LOG_FILE) - logging.basicConfig(level=logging.DEBUG, format='[%(asctime)s] %(name)s %(levelname)s: %(message)s', filename=cons.LOG_FILE, filemode='w') + logging.basicConfig(level=logging.DEBUG, format=cons.LOG_FORMAT, filename=cons.LOG_FILE, filemode='w') self.logger = logging.getLogger(self.__class__.__name__) + + #start user interface + try: + self.set_globals(options) + if options.wizard: + self.set_verbose() + self.start_wizard(options.wizard) + elif options.daemon: + self.set_verbose() + self.start_daemon(options.links_file) + elif options.cli: + self.start_cli(options.links_file) + else: + if options.verbose: + self.set_verbose() + self.start_gui() + except KeyboardInterrupt: + self.exit("KeyboardInterrupt") + except Exception, e: + self.logger.exception(e) + print e + print "Reporting error, please wait..." + #print "REPORT ID: %s" % misc.report_log("Automatic", str(e)) + print "Unhandled Error! Check the log file for details." + self.exit(-1) + + def set_verbose(self, severity=logging.INFO): + """""" + console = logging.StreamHandler(sys.stdout) + console.setLevel(severity) + console.setFormatter(logging.Formatter('%(levelname)-7s %(name)s: %(message)s')) + logging.getLogger("").addHandler(console) + + def start_wizard(self, wizard_type): + """""" + from ui.console.wizard import Wizard + + w = Wizard() + if wizard_type == "accounts": + w.account_setup(configuration) + elif wizard_type == "services": + w.service_setup(configuration) + elif wizard_type == "updates": + w.update_setup(configuration) + else: + print "TYPE should be one of: accounts, services or updates" + + def start_daemon(self, file): + """""" + from ui.console.no_ui import NoUi + + d = NoUi(configuration, file) + d.run() + + def start_cli(self, file): + """""" + if cons.OS_WINDOWS: + print "No curses support." + self.exit() + else: + from curses.wrapper import wrapper + from ui.console.cli import Cli + + c = Cli(configuration, file) + wrapper(c.run) - self.logger.info(cons.TUCAN_VERSION) - self.logger.debug("Main path: %s" % cons.PATH) - self.logger.debug("Configuration path: %s" % cons.CONFIG_PATH) + def start_gui(self): + """""" + import pygtk + pygtk.require('2.0') + import gtk + import gobject + + from ui.gtk.gui import Gui + + try: + gtk.init_check() + except: + print "Could not connect to X server. Use 'tucan --cli' for curses interface." + else: + gobject.threads_init() + Gui(configuration) + gtk.main() + + def set_globals(self, options): + """""" + #custom exit + __builtin__.tucan_exit = self.exit #proxy settings - proxy_url, proxy_port = self.configuration.get_proxy() + __builtin__.PROXY = None + proxy_url, proxy_port = configuration.get_proxy() url_open.set_proxy(proxy_url, proxy_port) - - #global custom exit - __builtin__.tucan_exit = self.exit + + __builtin__.max_downloads = configuration.getint(config.SECTION_MAIN, config.OPTION_MAX_DOWNLOADS) + __builtin__.max_download_speed = configuration.getint(config.SECTION_MAIN, config.OPTION_MAX_DOWNLOAD_SPEED) def exception_hook(self, type, value, trace): """""" file_name = trace.tb_frame.f_code.co_filename line_no = trace.tb_lineno exception = type.__name__ - self.logger.critical("File %s line %i - %s: %s" % (file_name, line_no, exception, value)) - print self.old_exception_hook(type, value, trace) + try: + self.logger.critical("File %s line %i - %s: %s" % (file_name, line_no, exception, value)) + except: + pass + sys.__excepthook__(type, value, trace) self.exit(-1) def exit(self, arg=0): """""" self.logger.debug("Exit: %s" % arg) - exit(arg) + sys.exit(arg) if __name__ == "__main__": - gobject.threads_init() t = Tucan() - Gui(t.configuration) - gtk.main() + \ No newline at end of file diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/console/cli.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/console/cli.py --- tucan-0.3.8/ui/console/cli.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/console/cli.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,180 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import threading +import time +import curses +import logging +logger = logging.getLogger(__name__) + +from no_ui import NoUi +from core.log_stream import LogStream + +import core.cons as cons + +STATUS_LINES = 1 +DOWNLOAD_LINES = 60 +LOG_LINES = 50 +WIDTH = 100 + +class Cli(NoUi): + """""" + def __init__(self, *kwargs): + """""" + #set logger + self.stream = LogStream() + handler = logging.StreamHandler(self.stream) + handler.setLevel(logging.INFO) + handler.setFormatter(logging.Formatter('%(levelname)-7s %(message)s')) + logging.getLogger("").addHandler(handler) + + NoUi.__init__(self, *kwargs) + self.quit_question = False + self.win_height = 0 + self.win_chars = 0 + self.last_length = 0 + self.total_speed = 0 + + def run(self, screen): + """""" + self.screen = screen + self.screen.nodelay(1) + try: + curses.curs_set(0) + except: + logger.warning("Could not hide the cursor") + + #set default screen + self.status_pad = curses.newpad(STATUS_LINES, WIDTH) + self.main_pad = curses.newpad(DOWNLOAD_LINES, WIDTH) + self.log_pad = curses.newpad(LOG_LINES, WIDTH) + + #load links file + th = threading.Thread(group=None, target=self.load_file, name=None) + th.start() + + while True: + self.win_height, self.win_chars = self.screen.getmaxyx() + self.parse_input() + try: + log_len = self.update_main() + self.update_log(log_len) + except curses.error, e: + logger.warning(e) + else: + curses.doupdate() + time.sleep(0.5) + + def parse_input(self): + """""" + try: + input = self.screen.getkey() + except curses.error: + if not self.quit_question: + self.update_status() + else: + if self.quit_question: + if input.lower() == "y": + self.quit() + else: + self.quit_question = False + self.update_status() + else: + if input.lower() == "q": + self.quit_question = True + self.question() + else: + self.update_status() + + def update_main(self): + """""" + if self.win_height > 5: + cont = 0 + self.main_pad.erase() + self.total_speed = 0 + for download in self.download_manager.complete_downloads + self.download_manager.active_downloads: + service = "[]" + for link in download.links: + if link.active: + service = "[%s %s]" %(link.plugin_type, link.service) + self.total_speed += download.speed + percent = "%i%s" % (int(download.progress), "%") + speed = "%s KB/s" % download.speed + size = "%i%s / %i%s" % (download.actual_size, download.actual_size_unit, download.total_size, download.total_size_unit) + time = str(self.calculate_time(download.time)) + self.main_pad.addnstr(cont, 1, download.name, WIDTH) + self.main_pad.addnstr(cont+1, 5, "%s %s \t%s \t%s \t%s" % (percent, service, size, speed, time), WIDTH) + cont +=3 + self.download_manager.update() + #2 primeras lineas en blanco + cont +=2 + remain = self.win_height-cont + start = 0 + while remain <= 5: + remain += 3 + start += 3 + self.main_pad.noutrefresh(start, 0, 2, 0, cont-start, self.win_chars-1) + return remain + + def update_log(self, length): + """""" + if length: + lines = self.stream.readnlines(length) + if lines: + self.last_length = length + self.log_pad.erase() + for i in range(len(lines)): + self.log_pad.addnstr(i, 0, lines[i], WIDTH, curses.A_DIM) + self.log_pad.noutrefresh(0, 0, self.win_height-length, 0, self.win_height-1, self.win_chars-1) + + def update_status(self): + """""" + active = len(self.download_manager.active_downloads) + complete = len(self.download_manager.complete_downloads) + total = len(self.download_manager.pending_downloads + self.download_manager.active_downloads + self.download_manager.complete_downloads) + self.status_pad.erase() + self.status_pad.addnstr(0, 0, "Downstream: %s KB/s \tTotal %s \tActive %s \tComplete %s" % (self.total_speed, total, active, complete), WIDTH, curses.A_BOLD) + self.status_pad.noutrefresh(0, 0, 0, 0, 0, self.win_chars-1) + + def question(self): + """""" + self.status_pad.erase() + self.status_pad.addnstr(0, 0, "Are you sure you want to quit? [y/N]", WIDTH, curses.A_STANDOUT) + self.status_pad.noutrefresh(0, 0, 0, 0, 0, self.win_chars-1) + + def calculate_time(self, time): + """""" + result = None + hours = 0 + minutes = 0 + while time >= cons.HOUR: + time = time - cons.HOUR + hours += 1 + while time >= cons.MINUTE: + time = time - cons.MINUTE + minutes += 1 + seconds = time + if hours > 0: + result = str(hours) + "h" + str(minutes) + "m" + str(seconds) + "s" + elif minutes > 0: + result = str(minutes) + "m" + str(seconds) + "s" + elif seconds > 0: + result = str(seconds) + "s" + return result diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/console/no_ui.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/console/no_ui.py --- tucan-0.3.8/ui/console/no_ui.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/console/no_ui.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,100 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import os +import sys +import time +import __builtin__ +import gettext +import logging +logger = logging.getLogger(__name__) + +from core.core import Core + +import core.config as config +import core.cons as cons + +class NoUi(Core): + """""" + def __init__(self, conf, links_file): + """""" + self.configuration = conf + self.links_file = links_file + Core.__init__(self, self.configuration) + + def run(self): + """""" + self.load_file() + while len(self.download_manager.active_downloads + self.download_manager.pending_downloads) > 0: + self.download_manager.update() + time.sleep(1) + self.quit() + + def load_file(self): + """""" + if self.links_file: + try: + f = open(self.links_file, "r") + links = [link.lower().strip() for link in f.read().split("\n") if link and not link.startswith("#")] + f.close() + self.manage_packages(self.create_packages(self.check_links(links)), []) + except Exception, e: + logger.error(e) + + + def check_links(self, link_list): + """""" + result = {} + for service, links in self.filter_service(link_list).items(): + if service != cons.TYPE_UNSUPPORTED: + tmp = [] + check, plugin_type = self.get_check_links(service) + for link in links: + file_name, size, size_unit = check(link) + if file_name: + if size > 0: + tmp.append((link, file_name, size, size_unit, plugin_type)) + else: + file_name = link + logger.info("Checked: %s %s %s" % (file_name, size, size_unit)) + if len(tmp) > 0: + result[service] = tmp + return result + + def manage_packages(self, packages, packages_info): + """""" + if not len(packages_info) > 0: + default_path = self.configuration.get_downloads_folder() + packages_info = [(default_path, name, None) for name, package_files in packages] + for package_name, package_downloads in packages: + info = packages_info[packages.index((package_name, package_downloads))] + package_name = info[1].replace(" ", "_") + package_path = os.path.join(info[0], package_name, "") + for download in package_downloads: + tmp = [] + for service in download[2]: + plugin, plugin_type = self.get_download_plugin(service) + tmp.append((download[0][download[2].index(service)], plugin, plugin_type, service)) + self.download_manager.add(package_path, download[1], tmp, download[3], download[4]) + + def quit(self): + """""" + self.stop_all() + tucan_exit(0) diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/console/wizard.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/console/wizard.py --- tucan-0.3.8/ui/console/wizard.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/console/wizard.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,225 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import getpass +import logging +logger = logging.getLogger(__name__) + +from core.service_update import ServiceUpdate +from core.service_config import SECTION_PREMIUM_DOWNLOAD + +import core.misc +import core.cons as cons + +class Wizard: + """""" + def __init__(self): + """""" + core.misc.main_info() + + def account_setup(self, config): + """""" + logger.info("Setup accounts.") + quit = False + services = [service for service in config.get_services() if service[4].premium_cookie()[1] or service[4].user_cookie()[1]] + while not quit: + try: + cont = 0 + for service in services: + print " [%s]\t%s \t%i accounts." % (cont, service[2], len(service[4].get_accounts(SECTION_PREMIUM_DOWNLOAD))) + cont +=1 + input = raw_input("Choose [N] service or (Q)uit: ").strip() + if input.lower() == "q": + quit = True + elif int(input) in range(cont): + service = services[int(input)] + #module, class_name = service_config.user_cookie() + module, class_name = service[4].premium_cookie() + module = __import__("%s.%s" % (service[0], module), None, None, ['']) + self.account_setup2(service, eval("module" + "." + class_name + "()").get_cookie) + except ValueError: + pass + except Exception, e: + logger.error("Error. %s" % e) + logger.info("DONE") + + def account_setup2(self, service, get_cookie): + """""" + end = False + accounts = service[4].get_accounts(SECTION_PREMIUM_DOWNLOAD) + while not end: + try: + logger.info("Premium accounts for '%s'" % service[2]) + cont = 0 + for name, settings in accounts.items(): + print " [%s]\t'%s' %s and %s" % (cont, name, self.get_active(settings[2]), self.get_status(settings[1])) + cont += 1 + input = raw_input("Modify [N] account, (A)dd or (R)eturn: ").strip() + if input.lower() == "r": + service[4].set_accounts(SECTION_PREMIUM_DOWNLOAD, accounts) + end = True + elif input.lower() == "a": + user = self.get_user() + if user: + password = self.get_password() + if self.check_account(user, password, get_cookie): + accounts[user] = (password, True, True) + else: + accounts[user] = (password, False, False) + elif int(input) in range(cont): + name, settings = accounts.items()[int(input)] + input2 = raw_input("Set (U)ser, (P)assword, (E)nabled or (D)elete: ").strip() + if input2.lower() == "d": + del accounts[name] + logger.warning("'%s': DELETED!" % name) + elif input2.lower() == "u": + user = self.get_user() + if user: + logger.info("Changed '%s' to '%s'." % (name, user)) + del accounts[name] + if self.check_account(user, settings[0], get_cookie): + accounts[user] = (settings[0], True, True) + else: + accounts[user] = (settings[0], False, False) + elif input2.lower() == "p": + password = self.get_password() + if password: + if self.check_account(name, settings[0], get_cookie): + accounts[name] = (password, True, True) + else: + accounts[name] = (password, False, False) + elif input2.lower() == "e": + enabled = settings[1] + if enabled: + enabled = not enabled + else: + if self.check_account(name, settings[0], get_cookie): + enabled = not enabled + accounts[name] = (settings[0], enabled, settings[2]) + logger.info("'%s': %s" % (name, self.get_status(enabled))) + except ValueError: + pass + except Exception, e: + logger.error("Error. %s" % e) + + def check_account(self, user, password, get_cookie): + """""" + logger.info("Checking account '%s'..." % user) + try: + if get_cookie(user, password): + logger.info("'%s': SUCCESS!" % user) + return True + else: + logger.warning("'%s': INVALID ACCOUNT." % user) + except Exception, e: + logger.error("Error. %s" % e) + + def get_user(self): + """""" + user = raw_input("User: ").strip() + if user: + return user + else: + logger.error("No user name.") + + def get_password(self): + """""" + while True: + pass1 = getpass.getpass("Password: ") + if pass1: + pass2 = getpass.getpass("Retype Password: ") + if pass1 == pass2: + return pass1 + else: + logger.error("Passwords do not match.") + else: + logger.error("No password supplied.") + + + def get_active(self, status): + """""" + if status: + return "ACTIVE" + else: + return "INACTIVE" + + def get_status(self, status): + """""" + if status: + return "ENABLED" + else: + return "DISABLED" + + def list_enabled(self, services): + """""" + cont = 0 + for service in services: + print " [%s]\t%s \t%s" % (cont, self.get_status(service[3]), service[2]) + cont +=1 + return cont + + def service_setup(self, config): + """""" + logger.info("Enable services.") + quit = False + services = config.get_services() + cont = self.list_enabled(services) + while not quit: + try: + input = raw_input("Choose [N] service, (L)ist or (Q)uit: ").strip() + if input.lower() == "q": + quit = True + elif input.lower() == "l": + self.list_enabled(services) + elif int(input) in range(cont): + service = services[int(input)] + status = not service[3] + if status: + logger.info("You should read '%s' terms of service." % service[2]) + logger.info("'%s' %s" % (service[2], self.get_status(status))) + service[4].enable(status) + services = config.get_services() + except ValueError: + pass + except Exception, e: + logger.error("Invalid argument!") + logger.info("DONE") + + def update_setup(self, config): + """""" + try: + s = ServiceUpdate(config) + logger.info("Checking updates...") + s.get_updates() + new = 0 + updates = 0 + for key, value in s.updates.items(): + if value[2]: + updates +=1 + else: + new += 1 + logger.info("%i New and %i Updates" % (new, updates)) + for key, value in s.updates.items(): + s.install_service(key, value[0], value[1]) + except Exception, e: + logger.error("Error updating. %s" % e) + else: + config.save() + logger.info("DONE") diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/gtk/about.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/gtk/about.py --- tucan-0.3.8/ui/gtk/about.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/gtk/about.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,69 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import pygtk +pygtk.require('2.0') +import gtk + +import media +import core.cons as cons + +NAME = "Tucan" +COPYRIGHT = "(C) 2008-2009 The Tucan Project" +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 . + """ + +class About(gtk.AboutDialog): + """""" + def __init__(self, parent=None): + """""" + gtk.AboutDialog.__init__(self) + self.set_transient_for(parent) + self.set_position(gtk.WIN_POS_CENTER) + self.set_icon_from_file(media.ICON_TUCAN) + self.set_logo(gtk.gdk.pixbuf_new_from_file(media.ICON_TUCAN)) + self.set_name(NAME) + self.set_version(cons.TUCAN_VERSION) + self.set_copyright(COPYRIGHT) + self.set_license(LICENSE) + self.set_website(cons.WEBPAGE) + self.connect("response", self.close) + self.show_all() + self.run() + + def close(self, widget=None, other=None): + """""" + self.destroy() + +if __name__ == "__main__": + g = About() + gtk.main() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/gtk/advanced_packages.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/gtk/advanced_packages.py --- tucan-0.3.8/ui/gtk/advanced_packages.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/gtk/advanced_packages.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,212 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import time +import logging +logger = logging.getLogger(__name__) + +import pygtk +pygtk.require('2.0') +import gtk + +from file_chooser import FileChooser + +import media +import core.cons as cons + +class AdvancedPackages(gtk.Dialog): + """""" + def __init__(self, parent, default_path, packages): + """""" + gtk.Dialog.__init__(self) + self.set_icon_from_file(media.ICON_PACKAGE) + self.set_transient_for(parent) + self.set_title("%s - %s" % (cons.TUCAN_NAME, _("Advanced Packages"))) + self.set_position(gtk.WIN_POS_CENTER) + self.set_size_request(600,400) + + self.packages = packages + self.packages_info = [] + self.history_path = default_path + + #radio + frame = gtk.Frame() + self.vbox.pack_start(frame, False, False) + frame.set_border_width(10) + hbox = gtk.HBox() + frame.add(hbox) + multi = gtk.RadioButton(None, "Auto Package Mode") + multi.connect("toggled", self.change_mode, True) + hbox.pack_start(multi) + single = gtk.RadioButton(multi, "Single Package Mode") + single.connect("toggled", self.change_mode, False) + hbox.pack_start(single) + + #treeview + frame = gtk.Frame() + self.vbox.pack_start(frame) + frame.set_border_width(10) + scroll = gtk.ScrolledWindow() + frame.add(scroll) + scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self.multi_model = gtk.ListStore(gtk.gdk.Pixbuf, str, str, str, int) + self.single_model = gtk.ListStore(gtk.gdk.Pixbuf, str, str, str, int) + self.treeview = gtk.TreeView(self.multi_model) + self.treeview.get_selection().connect("changed", self.select) + scroll.add(self.treeview) + + self.treeview.set_rules_hint(True) + #self.treeview.set_headers_visible(False) + + tree_icon = gtk.TreeViewColumn('Icon') + icon_cell = gtk.CellRendererPixbuf() + tree_icon.pack_start(icon_cell, True) + tree_icon.add_attribute(icon_cell, 'pixbuf', 0) + self.treeview.append_column(tree_icon) + + tree_path = gtk.TreeViewColumn('Path') + path_cell = gtk.CellRendererText() + tree_path.pack_start(path_cell, True) + tree_path.add_attribute(path_cell, 'text', 1) + self.treeview.append_column(tree_path) + self.treeview.connect("row-activated", self.choose) + + tree_name = gtk.TreeViewColumn('Name') + name_cell = gtk.CellRendererText() + name_cell.set_property("editable", True) + name_cell.connect("edited", self.change, 2) + tree_name.pack_start(name_cell, True) + tree_name.add_attribute(name_cell, 'text', 2) + self.treeview.append_column(tree_name) + + tree_pass = gtk.TreeViewColumn('Password') + pass_cell = gtk.CellRendererText() + pass_cell.set_property("editable", True) + pass_cell.connect("edited", self.change, 3) + tree_pass.pack_start(pass_cell, True) + tree_pass.add_attribute(pass_cell, 'text', 3) + self.treeview.append_column(tree_pass) + + #fill treestore + package_icon = gtk.gdk.pixbuf_new_from_file_at_size(media.ICON_PACKAGE, 32, 32) + single_package_name = "package-%s" % time.strftime("%Y%m%d%H%M%S") + single_package_links = [] + for package_name, package_links in self.packages: + single_package_links += package_links + self.multi_model.append((package_icon, default_path, package_name, None, len(package_links))) + self.multi_packages = self.packages + self.single_package = [(single_package_name, single_package_links)] + self.single_model.append((package_icon, default_path, single_package_name, None, len(single_package_links))) + + #choose path + hbox = gtk.HBox() + self.vbox.pack_start(hbox, False, False, 5) + path_button = gtk.Button(None, gtk.STOCK_OPEN) + hbox.pack_start(path_button, False, False, 10) + path_button.set_size_request(90,40) + path_button.connect("clicked", self.choose_path) + path_label = gtk.Label(_("Choose new path for selected Package.")) + hbox.pack_start(path_label, False, False, 10) + aspect = gtk.AspectFrame() + aspect.set_shadow_type(gtk.SHADOW_NONE) + hbox.pack_start(aspect, True, True) + + #info + frame = gtk.Frame() + hbox.pack_start(frame) + frame.set_border_width(10) + self.info_name = gtk.Label() + self.info_name.set_markup("%s: " % ("Packages")) + frame.set_label_widget(self.info_name) + vbox = gtk.VBox() + frame.add(vbox) + self.info_label = gtk.Label(len(packages)) + vbox.pack_start(self.info_label, False, False, 5) + + #action area + cancel_button = gtk.Button(None, gtk.STOCK_CANCEL) + self.action_area.pack_start(cancel_button) + cancel_button.connect("clicked", self.close) + ok_button = gtk.Button(None, gtk.STOCK_OK) + self.action_area.pack_start(ok_button) + ok_button.connect("clicked", self.configure_packages) + + self.connect("response", self.close) + self.show_all() + self.run() + + def change_mode(self, button, multi): + """""" + if multi: + if button.get_active(): + logger.info("setting Auto Package Mode") + self.treeview.set_model(self.multi_model) + self.treeview.set_cursor_on_cell(0) + self.packages = self.multi_packages + else: + if button.get_active(): + logger.info("setting Single Package Mode") + self.treeview.set_model(self.single_model) + self.treeview.set_cursor_on_cell(0) + self.packages = self.single_package + + def set_info(self, num): + """""" + self.info_name.set_markup("%s: " % ("Files")) + self.info_label.set_text(str(num)) + + def select(self, selection): + """""" + model, iter = selection.get_selected() + if iter: + self.set_info(model.get_value(iter, 4)) + + def configure_packages(self, button=None): + """""" + model = self.treeview.get_model() + for package in model: + self.packages_info.append((package[1], package[2], package[3])) + self.close() + + def choose(self, treeview, path, view_column): + """""" + self.choose_path() + + def choose_path(self, button=None): + """""" + model, iter = self.treeview.get_selection().get_selected() + if iter: + f = FileChooser(self, self.on_choose, self.history_path) + self.history_path = f.history_path + + def on_choose(self, folder_path): + """""" + model, iter = self.treeview.get_selection().get_selected() + if iter: + model.set_value(iter, 1, folder_path) + + def change(self, cellrenderertext, path, new_text, column): + """""" + model = self.treeview.get_model() + model.set_value(model.get_iter(path), column, new_text) + + def close(self, widget=None, other=None): + """""" + self.destroy() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/gtk/file_chooser.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/gtk/file_chooser.py --- tucan-0.3.8/ui/gtk/file_chooser.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/gtk/file_chooser.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,88 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import os + +import pygtk +pygtk.require('2.0') +import gtk +import gobject + +import core.cons as cons + +class FileChooser(gtk.FileChooserDialog): + """""" + def __init__(self, parent, func, default_path=None, files=False, save=False): + """""" + gtk.FileChooserDialog.__init__(self, "%s - %s" % (cons.TUCAN_NAME,_("Select a Folder")), parent) + self.set_position(gtk.WIN_POS_CENTER) + + if default_path: + self.set_current_folder(default_path) + self.history_path = self.get_current_folder() + + if files: + self.set_title("%s - %s" % (cons.TUCAN_NAME, _("Select Files"))) + self.set_action(gtk.FILE_CHOOSER_ACTION_OPEN) + self.set_select_multiple(True) + elif save: + self.set_title("%s - %s" % (cons.TUCAN_NAME,_("Save As"))) + self.set_action(gtk.FILE_CHOOSER_ACTION_SAVE) + else: + self.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) + + hidden_button = gtk.CheckButton(("Show hidden files.")) + hidden_button.set_active(self.get_show_hidden()) + self.vbox.pack_start(hidden_button, False, False, 5) + hidden_button.connect("clicked", self.show_hidden) + + button = gtk.Button(None, gtk.STOCK_CANCEL) + button.connect("clicked", self.close) + self.action_area.pack_start(button) + button = gtk.Button(None, gtk.STOCK_OK) + button.connect("clicked", self.on_choose_folder, func) + self.action_area.pack_start(button) + self.set_position(gtk.WIN_POS_CENTER) + + self.connect("response", self.close) + + self.show_all() + self.run() + + def show_hidden(self, button): + """""" + self.set_show_hidden(button.get_active()) + + def on_choose_folder(self, button, func): + """""" + for file_name in self.get_filenames(): + func(os.path.join(file_name)) + self.close() + + def close(self, widget=None, response=None): + """""" + self.history_path = self.get_current_folder() + self.set_show_hidden(False) + self.destroy() + +if __name__ == "__main__": + def mierda(name): + print name + f = FileChooser(None, mierda, "/home/crak/") diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/gtk/gui.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/gtk/gui.py --- tucan-0.3.8/ui/gtk/gui.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/gtk/gui.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,425 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import os +import sys +import time +import threading +import webbrowser +import __builtin__ +import gettext +import logging +logger = logging.getLogger(__name__) + +import pygtk +pygtk.require('2.0') +import gtk +import gobject + +import tray_icon +import menu_bar +import toolbar + +from about import About +from message import Message +from preferences import Preferences +from log_view import LogView +from shutdown import Shutdown +from tree import Tree +from input_links import InputLinks +from file_chooser import FileChooser + +from core.core import Core +from core.sessions import Sessions +from core.log_stream import LogStream +from core.service_update import ServiceUpdate + +import media +import core.cons as cons +import core.config as config + +class Gui(gtk.Window, Core): + """""" + def __init__(self, conf): + """""" + #i18n + gettext.bindtextdomain(cons.NAME_LOCALES, cons.PATH_LOCALES) + gettext.textdomain(cons.NAME_LOCALES) + __builtin__._ = gettext.gettext + + #configuration + self.configuration = conf + + #set logger + log_stream = LogStream() + handler = logging.StreamHandler(log_stream) + handler.setLevel(logging.DEBUG) + handler.setFormatter(logging.Formatter(cons.LOG_FORMAT)) + logging.getLogger("").addHandler(handler) + + #show preferences if not configured + if not self.configuration.configured: + Preferences(self, self.configuration, True) + self.preferences_shown = False + + #l10n + lang = gettext.translation(cons.NAME_LOCALES, cons.PATH_LOCALES, languages=[self.configuration.get(config.SECTION_MAIN, config.OPTION_LANGUAGE)]) + lang.install() + + Core.__init__(self, self.configuration) + gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL) + + self.set_icon_from_file(media.ICON_TUCAN) + self.set_title("%s - Version: %s" % (cons.TUCAN_NAME, cons.TUCAN_VERSION)) + self.set_position(gtk.WIN_POS_CENTER) + self.set_size_request(900, 500) + self.vbox = gtk.VBox() + self.add(self.vbox) + + #menu items + menu_load_session = _("Load Session"), lambda x: FileChooser(self, self.load_session, cons.CONFIG_PATH, True) + menu_save_session = _("Save Session"), lambda x: FileChooser(self, self.save_session, cons.CONFIG_PATH, save=True) + menu_quit = gtk.STOCK_QUIT, self.quit + menu_help = gtk.STOCK_HELP, self.help + menu_about = gtk.STOCK_ABOUT, lambda x: About(self) + menu_preferences = gtk.STOCK_PREFERENCES, self.preferences + menu_log = _("Show Logs"), lambda x: LogView(self, log_stream) + show_uploads = gtk.CheckMenuItem(_("Show Uploads")), self.resize_pane, self.configuration.getboolean(config.SECTION_ADVANCED, config.OPTION_SHOW_UPLOADS) + shutdown = gtk.CheckMenuItem(_("Shutdown Computer")), self.shutdown, False + + m_file = _("File") + m_view = _("View") + m_help = _("Help") + m_addons = _("Addons") + + #integration menubar + integration = None + if cons.OS_OSX: + try: + about_menu = _("About TucanManager"), lambda x: About(self) + preferences_menu = _("Preferences"), self.preferences + file_menu = m_file, [menu_load_session, menu_save_session] + view_menu = m_view, [show_uploads, None, menu_log] + addons_menu = m_addons, [shutdown] + help_menu = m_help, [menu_help] + quit_menu = _("Quit"), self.quit + integration = gtk.Window(gtk.WINDOW_POPUP) + vbox = gtk.VBox() + integration.add(vbox) + vbox.pack_start(menu_bar.OSXMenuBar([file_menu, view_menu, addons_menu, help_menu], about_menu, preferences_menu, quit_menu)) + + except Exception, e: + integration = None + logger.critical("No OSX menu integration support.") + + #normal menubar + if not integration: + file_menu = m_file, [menu_load_session, menu_save_session, None, menu_quit] + view_menu = m_view, [show_uploads, menu_log, None, menu_preferences] + addons_menu = m_addons, [shutdown] + help_menu = m_help, [menu_help, menu_about] + self.vbox.pack_start(menu_bar.MenuBar([file_menu, view_menu, addons_menu, help_menu]), False) + + #toolbar + download = _("Add Downloads"), gtk.image_new_from_file(media.ICON_DOWNLOAD), self.add_links + upload = _("Add Uploads"), gtk.image_new_from_file(media.ICON_UPLOAD), self.not_implemented #self.quit + clear = _("Clear Complete"), gtk.image_new_from_file(media.ICON_CLEAR), self.clear_complete + up = _("Move Up"), gtk.image_new_from_file(media.ICON_UP), self.move_up + down = _("Move Down"), gtk.image_new_from_file(media.ICON_DOWN), self.move_down + start = _("Start Selected"), gtk.image_new_from_file(media.ICON_START), self.start + stop = _("Stop Selected"), gtk.image_new_from_file(media.ICON_STOP), self.stop + self.vbox.pack_start(toolbar.Toolbar([download, upload, None, clear, None, up, down, None, start, stop]), False) + + copy = gtk.STOCK_COPY, self.copy_clipboard + delete = gtk.STOCK_REMOVE, self.delete + start = gtk.STOCK_MEDIA_PLAY, self.start + stop = gtk.STOCK_MEDIA_STOP, self.stop + + #trees + self.downloads = Tree([copy, None, delete], self.download_manager) + #self.uploads = Tree() + self.uploads = gtk.VBox() + + #tray icon + if cons.OS_OSX: + try: + #dock integration + self.tray_icon = tray_icon.OSXDock(self.show, self.quit) + self.connect("hide", self.tray_icon.activate, True) + except Exception, e: + logger.critical("No OSX dock integration support.") + self.tray_icon = None + else: + #trayicon + tray_menu = [menu_preferences, menu_about, None, menu_quit] + self.tray_icon = tray_icon.TrayIcon(self.show, self.hide, tray_menu) + self.connect("hide", self.tray_icon.activate) + self.downloads.status_bar.connect("text-pushed", self.tray_icon.change_tooltip) + + #sessions + self.session = Sessions() + if self.configuration.getboolean(config.SECTION_ADVANCED, config.OPTION_SAVE_SESSION): + self.load_default_session() + else: + if os.path.exists(cons.SESSION_FILE): + title = _("Tucan Manager - Restore previous session.") + message = _("Your last session closed unexpectedly.\nTucan will try to restore it now.") + m = Message(None, cons.SEVERITY_WARNING, title, message, both=True) + if m.accepted: + self.load_default_session() + + #pane + self.pane = gtk.VPaned() + self.vbox.pack_start(self.pane) + self.pane.pack1(self.downloads, True) + self.pane.pack2(self.uploads, True) + self.pane.set_position(self.get_size()[1]) + + self.connect("key-press-event", self.delete_key) + + if self.configuration.getboolean(config.SECTION_ADVANCED, config.OPTION_TRAY_CLOSE): + self.connect("delete_event", self.hide_on_delete) + else: + self.connect("delete_event", self.quit) + + self.show_all() + + #Autocheck services + if self.configuration.getboolean(config.SECTION_ADVANCED, config.OPTION_AUTO_UPDATE): + th = threading.Thread(group=None, target=self.check_updates, name=None) + th.start() + + #ugly polling + gobject.timeout_add(120000, self.save_default_session) + + def check_updates(self): + """""" + s = ServiceUpdate(self.configuration) + if s.get_updates(): + gobject.idle_add(self.update_manager, s.remote_info) + + def update_manager(self, info): + """""" + if not self.preferences_shown: + self.preferences_shown = True + Preferences(self, self.configuration, True, info) + self.preferences_shown = False + return False + + def delete_key(self, window, event): + """pressed del key""" + if event.keyval == 65535: + self.delete() + + def preferences(self, button=None): + """""" + if not self.preferences_shown: + self.preferences_shown = True + Preferences(self, self.configuration) + self.downloads.status_bar.synchronize() + self.preferences_shown = False + + def not_implemented(self, widget): + """""" + w = Message(self, cons.SEVERITY_WARNING, "Not Implemented!", "The functionality you are trying to use is not implemented yet.") + + def resize_pane(self, checkbox): + """""" + if checkbox.get_active(): + self.pane.set_position(-1) + else: + self.pane.set_position(self.get_size()[1]) + + def shutdown(self, checkbox): + """""" + if checkbox.get_active(): + self.shutdown_id = events.connect(cons.EVENT_ALL_COMPLETE, Shutdown, self, self.quit) + else: + events.disconnect(cons.EVENT_ALL_COMPLETE, self.shutdown_id) + + def help(self, widget): + """""" + webbrowser.open(cons.DOC) + + def add_links(self, button): + """""" + default_path = self.configuration.get_downloads_folder() + show_advanced_packages = self.configuration.getboolean(config.SECTION_ADVANCED, config.OPTION_ADVANCED_PACKAGES) + InputLinks(self, default_path, self.filter_service, self.get_check_links, self.create_packages, self.manage_packages, show_advanced_packages) + + def copy_clipboard(self, button): + """""" + model, iter = self.downloads.treeview.get_selection().get_selected() + if iter: + link_list = self.downloads.get_links(iter) + clipboard = gtk.Clipboard() + clipboard.clear() + clipboard.set_text("\n".join(link_list)) + + def load_session(self, path): + """""" + try: + packages, info = self.session.load_session(path) + if packages != None: + self.manage_packages(packages, info) + logger.debug("Session loaded: %s" % info) + except Exception, e: + logger.exception("Session not loaded: %s" % e) + gobject.idle_add(self.session_error) + + def session_error(self): + """""" + title = _("Tucan Manager - Session Error.") + message = _("There was a problem loading the last session. Links are unrecoverable.") + Message(self, cons.SEVERITY_ERROR, title, message) + + def save_session(self, path): + """""" + packages, info = self.downloads.get_packages() + self.session.save_session(path, packages, info) + logger.debug("Session saved: %s" % info) + + def load_default_session(self): + """""" + self.load_session(cons.SESSION_FILE) + + def save_default_session(self): + """""" + self.save_session(cons.SESSION_FILE) + return True + + def manage_packages(self, packages, packages_info): + """""" + tmp_packages = [] + if not len(packages_info) > 0: + default_path = self.configuration.get_downloads_folder() + packages_info = [(default_path, name, None) for name, package_files in packages] + #create directories and password files + for info in packages_info: + package_path = os.path.join(info[0].decode("utf-8"), info[1].replace(" ", "_"), "") + if not os.path.exists(package_path): + os.makedirs(package_path) + if info[2]: + f = open(package_path + "password.txt", "w") + f.write(info[2] + "\n") + f.close() + #add packages to gui and manager + for package_name, package_downloads in packages: + info = packages_info[packages.index((package_name, package_downloads))] + package_name = info[1].replace(" ", "_") + package_path = os.path.join(info[0].decode("utf-8"), package_name, "") + self.downloads.add_package(package_name, package_path, package_downloads, info[2]) + for download in package_downloads: + tmp = [] + for service in download[2]: + plugin, plugin_type = self.get_download_plugin(service) + tmp.append((download[0][download[2].index(service)], plugin, plugin_type, service)) + self.download_manager.add(package_path, download[1], tmp, download[3], download[4]) + + def start(self, button): + """Implementado solo para descargas""" + model, paths = self.downloads.treeview.get_selection().get_selected_rows() + if len(paths) > 0: + if len(paths[0]) > 1: + logger.info("Start file: %s" % self.download_manager.start(model.get_value(model.get_iter(paths[0]), 3))) + else: + logger.info("Start package.") + for item in self.downloads.package_files(model.get_iter(paths[0])): + self.download_manager.start(item) + + def stop(self, button): + """Implementado solo para descargas""" + model, paths = self.downloads.treeview.get_selection().get_selected_rows() + if len(paths) > 0: + if len(paths[0]) > 1: + logger.info("Stop file: %s" % self.download_manager.stop(model.get_value(model.get_iter(paths[0]), 3))) + else: + logger.info("Stop package.") + for item in self.downloads.package_files(model.get_iter(paths[0])): + self.download_manager.stop(item) + + def clear_complete(self, button): + """Implementado solo para descargas""" + files = self.downloads.clear() + logger.info("Cleared: %s" % files) + if len(files) > 0: + self.download_manager.clear(files) + + def move_up(self, button): + """Implementado solo para descargas""" + model, paths = self.downloads.treeview.get_selection().get_selected_rows() + if len(paths) > 0: + if not len(paths[0]) > 1: + logger.info("Move up: %s" % self.downloads.move_up(model.get_iter(paths[0]))) + + def move_down(self, button): + """Implementado solo para descargas""" + model, paths = self.downloads.treeview.get_selection().get_selected_rows() + if len(paths) > 0: + if not len(paths[0]) > 1: + logger.info("Move down: %s" % self.downloads.move_down(model.get_iter(paths[0]))) + + def delete(self, button=None): + """Implementado solo para descargas""" + model, paths = self.downloads.treeview.get_selection().get_selected_rows() + status = [cons.STATUS_STOP, cons.STATUS_PEND, cons.STATUS_ERROR] + if len(paths) > 0: + if len(paths[0]) > 2: + name, link = self.downloads.delete_link(status, model.get_iter(paths[0])) + if link: + logger.warning("Remove %s: %s" % (link, self.download_manager.delete_link(name, link))) + elif len(paths[0]) > 1: + name = self.downloads.delete_file(status, model.get_iter(paths[0])) + if name: + logger.warning("Remove %s: %s" % (name, self.download_manager.clear([name]))) + else: + files = self.downloads.delete_package(status, model.get_iter(paths[0])) + if len(files) > 0: + logger.warning("Remove package: %s" % self.download_manager.clear(files)) + + def quit(self, dialog=None, response=None): + """""" + if len(self.download_manager.active_downloads) > 0: + message = "Tucan still has active downloads.\n Are you sure you want to quit?" + m = Message(self, cons.SEVERITY_WARNING, "Tucan Manager - Active Downloads.", message, True, True) + if m.accepted: + self.close() + else: + #This way GTK won't destroy the window. + return True + else: + self.close() + + def close(self): + """""" + self.hide() + if self.tray_icon: + self.tray_icon.close() + gtk.main_quit() + + if self.configuration.getboolean(config.SECTION_ADVANCED, config.OPTION_SAVE_SESSION): + self.save_default_session() + else: + try: + os.remove(cons.SESSION_FILE) + except Exception, e: + logger.info(e) + self.stop_all() + tucan_exit(0) diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/gtk/input_files.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/gtk/input_files.py --- tucan-0.3.8/ui/gtk/input_files.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/gtk/input_files.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,298 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import os + +import pygtk +pygtk.require('2.0') +import gtk +import gobject + +from file_chooser import FileChooser + +import media +import core.cons as cons + +SERVICES = [("Megaupload", 100, cons.UNIT_MB, ["Anonymous", "Premium"]), ("Rapidshare", 200, cons.UNIT_MB, ["Collector", "Premium"]), ("Gigasize", 100, cons.UNIT_MB, ["Anonymous"])] + +class InputFiles(gtk.Dialog): + """""" + def __init__(self, parent, upload_services): + """""" + gtk.Dialog.__init__(self) + self.set_transient_for(parent) + self.set_icon_from_file(media.ICON_UPLOAD) + self.set_title(("Input Files")) + self.set_position(gtk.WIN_POS_CENTER) + self.set_size_request(600,500) + + self.history_path = cons.DEFAULT_PATH + + main_hbox = gtk.HBox() + self.vbox.pack_start(main_hbox) + + self.file_icon = self.render_icon(gtk.STOCK_FILE, gtk.ICON_SIZE_BUTTON) + self.correct_icon = self.render_icon(gtk.STOCK_APPLY, gtk.ICON_SIZE_MENU) + self.incorrect_icon = self.render_icon(gtk.STOCK_CANCEL, gtk.ICON_SIZE_MENU) + + #package treeview + frame = gtk.Frame() + main_hbox.pack_start(frame, True) + frame.set_border_width(5) + scroll = gtk.ScrolledWindow() + frame.add(scroll) + scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self.package_treeview = gtk.TreeView(gtk.TreeStore(gtk.gdk.Pixbuf, str, str, str, bool)) + scroll.add(self.package_treeview) + + self.package_treeview.set_rules_hint(True) + self.package_treeview.set_headers_visible(False) + + tree_icon = gtk.TreeViewColumn('Icon') + icon_cell = gtk.CellRendererPixbuf() + tree_icon.pack_start(icon_cell, True) + tree_icon.add_attribute(icon_cell, 'pixbuf', 0) + self.package_treeview.append_column(tree_icon) + + tree_name = gtk.TreeViewColumn('Name') + name_cell = gtk.CellRendererText() + tree_name.pack_start(name_cell, True) + tree_name.add_attribute(name_cell, 'text', 1) + self.package_treeview.append_column(tree_name) + + tree_size = gtk.TreeViewColumn('Size') + size_cell = gtk.CellRendererText() + tree_size.pack_start(size_cell, False) + tree_size.add_attribute(size_cell, 'text', 2) + self.package_treeview.append_column(tree_size) + + service_vbox = gtk.VBox() + main_hbox.pack_start(service_vbox, False, False) + + # services treeview + frame = gtk.Frame() + service_vbox.pack_start(frame) + frame.set_size_request(200, -1) + frame.set_border_width(5) + frame.set_label_widget(gtk.image_new_from_file(media.ICON_PREFERENCES_SERVICES)) + scroll = gtk.ScrolledWindow() + frame.add(scroll) + scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + services = gtk.ListStore(gtk.gdk.Pixbuf, str, int, str, bool, gobject.TYPE_PYOBJECT) + self.services_treeview = gtk.TreeView(services) + self.services_treeview.get_selection().connect("changed", self.select) + scroll.add(self.services_treeview) + + self.services_treeview.set_rules_hint(True) + self.services_treeview.set_headers_visible(False) + + tree_icon = gtk.TreeViewColumn('Icon') + icon_cell = gtk.CellRendererPixbuf() + tree_icon.pack_start(icon_cell, True) + tree_icon.add_attribute(icon_cell, 'pixbuf', 0) + self.services_treeview.append_column(tree_icon) + + tree_name = gtk.TreeViewColumn('Name') + name_cell = gtk.CellRendererText() + tree_name.pack_start(name_cell, True) + tree_name.add_attribute(name_cell, 'text', 1) + self.services_treeview.append_column(tree_name) + + tree_add = gtk.TreeViewColumn('Add') + add_cell = gtk.CellRendererToggle() + add_cell.connect("toggled", self.toggled) + tree_add.pack_start(add_cell, True) + tree_add.add_attribute(add_cell, 'active', 4) + self.services_treeview.append_column(tree_add) + + #plugins + self.plugins_frame = gtk.Frame() + service_vbox.pack_start(self.plugins_frame, False, False) + self.plugins_frame.set_size_request(200, 100) + self.plugins_frame.set_border_width(5) + + for service, size, unit, plugins in upload_services: + vbox = gtk.VBox() + first = None + for plugin in plugins: + first = gtk.RadioButton(first, plugin) + vbox.pack_start(first, False, False, 1) + services.append([self.correct_icon, service, size, unit, False, vbox]) + + #choose path + hbox = gtk.HBox() + self.vbox.pack_start(hbox, False, False, 5) + path_button = gtk.Button(None, gtk.STOCK_OPEN) + path_button.set_size_request(90,40) + hbox.pack_start(path_button, False, False, 5) + path_button.connect("clicked", self.choose_files) + path_label = gtk.Label(("Choose files to upload.")) + hbox.pack_start(path_label, False, False, 5) + aspect = gtk.AspectFrame() + hbox.pack_start(aspect, True, True) + aspect.set_shadow_type(gtk.SHADOW_NONE) + clear_button = gtk.Button(None, gtk.STOCK_CLEAR) + clear_button.set_size_request(190,40) + hbox.pack_start(clear_button, False, False, 5) + clear_button.connect("clicked", self.clear) + + #action area + cancel_button = gtk.Button(None, gtk.STOCK_CANCEL) + add_button = gtk.Button(None, gtk.STOCK_ADD) + self.action_area.pack_start(cancel_button) + self.action_area.pack_start(add_button) + cancel_button.connect("clicked", self.close) + add_button.connect("clicked", self.add_files) + + self.connect("response", self.close) + self.show_all() + self.set_focus(path_button) + self.run() + + def clear(self, button): + """""" + self.package_treeview.get_model().clear() + + def select(self, selection): + """""" + model, service_iter = selection.get_selected() + if iter: + if self.plugins_frame.get_child(): + self.plugins_frame.remove(self.plugins_frame.get_child()) + vbox = model.get_value(service_iter, 5) + self.plugins_frame.add(vbox) + vbox.show_all() + + def add_files(self, button): + """""" + result = [] + package_model = self.package_treeview.get_model() + services_model = self.services_treeview.get_model() + + file_iter = package_model.get_iter_root() + while file_iter: + services = [] + service_iter = package_model.iter_children(file_iter) + while service_iter: + service_name = package_model.get_value(service_iter, 1) + if package_model.get_value(service_iter, 4): + for service in services_model: + if service[1] == service_name: + for button in service[5].get_children(): + if button.get_active(): + services.append((service_name, button.get_label())) + service_iter = package_model.iter_next(service_iter) + if len(services) > 0: + tmp = package_model.get_value(file_iter, 2).split(" ") + size, unit = self.split_size(self.join_size(int(tmp[0]), tmp[1])) + result.append((package_model.get_value(file_iter, 3), int(size), unit, services)) + file_iter = package_model.iter_next(file_iter) + self.close() + print result + + def toggled(self, button, path): + """""" + active = True + if button.get_active(): + active = False + button.set_active(active) + + services_model = self.services_treeview.get_model() + package_model = self.package_treeview.get_model() + + services_model.set_value(services_model.get_iter(path), 4, active) + + file_iter = package_model.get_iter_root() + while file_iter: + service_iter = package_model.iter_children(file_iter) + found = False + while service_iter: + if services_model.get_value(services_model.get_iter(path), 1) == package_model.get_value(service_iter, 1): + found = True + break + service_iter = package_model.iter_next(service_iter) + if active: + if not found: + tmp = package_model.get_value(file_iter, 2).split(" ") + max_size = self.join_size(services_model.get_value(services_model.get_iter(path), 2), services_model.get_value(services_model.get_iter(path), 3)) + self.add_service(package_model, file_iter, services_model.get_value(services_model.get_iter(path), 1), self.join_size(int(tmp[0]), tmp[1]), max_size) + else: + if found: + package_model.remove(service_iter) + file_iter = package_model.iter_next(file_iter) + + def choose_files(self, button): + """""" + f = FileChooser(self, self.on_choose, self.history_path, True) + self.history_path = f.history_path + + def on_choose(self, path): + """""" + package_model = self.package_treeview.get_model() + services_model = self.services_treeview.get_model() + if os.path.isfile(path): + if path not in [row[1] for row in package_model]: + file_size = int(os.stat(path).st_size/1024) + size, unit = self.split_size(file_size) + file_iter = package_model.append(None, [self.file_icon, os.path.basename(path), "%i %s" %(size, unit), path, None]) + for row in services_model: + if row[4]: + self.add_service(package_model, file_iter, row[1], file_size, self.join_size(row[2], row[3])) + + def join_size(self, size, unit): + """""" + factor = 1 + if unit == cons.UNIT_KB: + factor = 1 + elif unit == cons.UNIT_MB: + factor = 1024 + elif unit == cons.UNIT_GB: + factor = 1024*1024 + return size*factor + + def split_size(self, size): + """""" + if size > 0: + tmp = size/1024 + if tmp > 0: + tmp2 = tmp/1024 + if tmp2 > 0: + return tmp2, cons.UNIT_GB + else: + return tmp, cons.UNIT_MB + else: + return size, cons.UNIT_KB + else: + return 1, cons.UNIT_KB + + def add_service(self, package_model, file_iter, service, file_size, max_size): + """""" + if max_size > file_size: + package_model.append(file_iter, [self.correct_icon, service, None, None, True]) + else: + package_model.append(file_iter, [self.incorrect_icon, service, None, None, False]) + self.package_treeview.expand_row(package_model.get_path(file_iter), True) + + def close(self, widget=None, other=None): + """""" + self.destroy() + +if __name__ == "__main__": + x = InputFiles(None, SERVICES) diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/gtk/input_links.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/gtk/input_links.py --- tucan-0.3.8/ui/gtk/input_links.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/gtk/input_links.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,321 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import HTMLParser +import threading +import logging +logger = logging.getLogger(__name__) + +import pygtk +pygtk.require('2.0') +import gtk +import gobject + +from message import Wait, Message +from advanced_packages import AdvancedPackages + +import media +import core.cons as cons + +class ClipParser(HTMLParser.HTMLParser): + """""" + def __init__(self): + """""" + HTMLParser.HTMLParser.__init__(self) + self.url = [] + + def handle_starttag(self, tag, attrs): + """""" + if tag == "a": + for ref, link in attrs: + if ref == "href": + self.url.append(link) + +class InputLinks(gtk.Dialog): + """""" + def __init__(self, parent, path, sort, check, create, manage, show_advanced_packages): + """""" + gtk.Dialog.__init__(self) + self.set_transient_for(parent) + self.set_icon_from_file(media.ICON_DOWNLOAD) + self.set_title("%s - %s" % (cons.TUCAN_NAME, _("Input Links"))) + self.set_position(gtk.WIN_POS_CENTER) + self.set_size_request(600,500) + + self.cancel_check = False + + self.default_path = path + self.sort_links = sort + self.check_links = check + self.create_packages = create + self.packages = manage + + #textview + frame = gtk.Frame(_("Paste links here:")) + self.vbox.pack_start(frame) + frame.set_border_width(10) + hbox = gtk.HBox() + frame.add(hbox) + scroll = gtk.ScrolledWindow() + hbox.pack_start(scroll, True, True, 10) + scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) + #auto scroll + scroll.get_vadjustment().connect("changed", self.changed) + scroll.get_vadjustment().connect("value-changed", self.value_changed) + buffer = gtk.TextBuffer() + self.textview = gtk.TextView(buffer) + scroll.add(self.textview) + self.textview.set_wrap_mode(gtk.WRAP_CHAR) + + self.clipboard = gtk.clipboard_get() + self.clipboard.request_targets(self.get_clipboard) + + #check button + button_box = gtk.HButtonBox() + hbox.pack_start(button_box, False, False, 10) + vbox = gtk.VBox() + check_image = gtk.image_new_from_file(media.ICON_CHECK) + vbox.pack_start(check_image) + check_label = gtk.Label(_("Check Links")) + vbox.pack_start(check_label) + check_button = gtk.Button() + check_button.add(vbox) + button_box.pack_start(check_button) + check_button.connect("clicked", self.check) + + #treeview + frame = gtk.Frame() + self.vbox.pack_start(frame) + frame.set_border_width(10) + scroll = gtk.ScrolledWindow() + frame.add(scroll) + scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + #auto scroll + scroll.get_vadjustment().connect("changed", self.changed) + scroll.get_vadjustment().connect("value-changed", self.value_changed) + + self.treeview = gtk.TreeView(gtk.TreeStore(gtk.gdk.Pixbuf, str, str, int, str, str, bool, bool)) + scroll.add(self.treeview) + + self.treeview.set_rules_hint(True) + self.treeview.set_headers_visible(False) + + tree_icon = gtk.TreeViewColumn('Icon') + icon_cell = gtk.CellRendererPixbuf() + tree_icon.pack_start(icon_cell, True) + tree_icon.add_attribute(icon_cell, 'pixbuf', 0) + self.treeview.append_column(tree_icon) + + tree_name = gtk.TreeViewColumn('Name') + name_cell = gtk.CellRendererText() + name_cell.connect("edited", self.change_name) + tree_name.pack_start(name_cell, True) + tree_name.add_attribute(name_cell, 'text', 2) + tree_name.add_attribute(name_cell, 'editable', 7) + self.treeview.append_column(tree_name) + + tree_add = gtk.TreeViewColumn('Add') + add_cell = gtk.CellRendererToggle() + add_cell.connect("toggled", self.toggled) + tree_add.pack_start(add_cell, True) + tree_add.add_attribute(add_cell, 'active', 6) + tree_add.add_attribute(add_cell, 'visible', 7) + self.treeview.append_column(tree_add) + + #advanced checkbutton + hbox = gtk.HBox() + self.vbox.pack_start(hbox, False) + self.advanced_button = gtk.CheckButton(_("Show advanced Package configuration.")) + self.advanced_button.set_active(show_advanced_packages) + hbox.pack_start(self.advanced_button, False, False, 8) + + #action area + cancel_button = gtk.Button(None, gtk.STOCK_CANCEL) + add_button = gtk.Button(None, gtk.STOCK_ADD) + self.action_area.pack_start(cancel_button) + self.action_area.pack_start(add_button) + cancel_button.connect("clicked", self.close) + add_button.connect("clicked", self.add_links) + + self.connect("response", self.close) + self.show_all() + self.run() + + def changed(self, vadjust): + """autoscroll""" + if not hasattr(vadjust, "need_scroll") or vadjust.need_scroll: + vadjust.set_value(vadjust.upper-vadjust.page_size) + vadjust.need_scroll = True + + def value_changed (self, vadjust): + """autoscroll""" + vadjust.need_scroll = abs(vadjust.value + vadjust.page_size - vadjust.upper) < vadjust.step_increment + + def change_name(self, cellrenderertext, path, new_text): + """""" + model = self.treeview.get_model() + model.set_value(model.get_iter(path), 2, new_text) + + def get_clipboard(self, clipboard, selection_data, data): + """""" + urls = [] + if cons.OS_OSX: + target_html = "public.rtf" + if target_html in list(selection_data): + selection = self.clipboard.wait_for_contents(target_html) + if selection: + for line in str(selection.data.decode("utf8", "ignore")).split("\n"): + if '{HYPERLINK "' in line: + urls.append(line.split('{HYPERLINK "')[1].split('"}')[0]) + elif cons.OS_WINDOWS: + target_html = "HTML Format" + if target_html in list(selection_data): + try: + parser = ClipParser() + parser.feed(self.clipboard.wait_for_contents(target_html).data.decode("utf8", "ignore")) + parser.close() + if len(parser.url) > 0: + urls += parser.url + except HTMLParser.HTMLParseError: + pass + else: + target_html = "text/html" + if target_html in list(selection_data): + for line in str(self.clipboard.wait_for_contents(target_html).data.decode("utf16", "ignore")).split("\n"): + try: + parser = ClipParser() + parser.feed(line) + parser.close() + if len(parser.url) > 0: + urls += parser.url + except HTMLParser.HTMLParseError: + pass + if len(urls) > 0: + self.textview.get_buffer().insert_at_cursor("\n".join(urls) + "\n") + + def toggled(self, button, path): + """""" + model = self.treeview.get_model() + active = True + if button.get_active(): + active = False + button.set_active(active) + model.set_value(model.get_iter(path), 6, active) + + def add_links(self, button): + """""" + tmp = {} + store = self.treeview.get_model() + for column in store: + if column[2] != cons.TYPE_UNSUPPORTED: + tmp[column[2]] = [] + for value in column.iterchildren(): + if value[1] != value[2]: + if value[6]: + logger.info("Added: %s %s %s %s %s" % (value[1], value[2], value[3], value[4], value[5])) + tmp[column[2]].append((value[1], value[2], value[3], value[4], value[5])) + if tmp != {}: + packages = self.create_packages(tmp) + packages_info = None + if self.advanced_button.get_active(): + #self.hide() + w = AdvancedPackages(self, self.default_path, packages) + packages_info = w.packages_info + if packages_info: + self.packages(w.packages, packages_info) + self.close() + #else: + # self.show() + else: + self.packages(packages, []) + self.close() + else: + title = _("Input Links - Nothing to add.") + message = _("There aren't links to add.\nPlease check the links before adding.") + m = Message(self, cons.SEVERITY_INFO, title, message, both=True) + if not m.accepted: + self.close() + + def check(self, button): + """""" + buffer = self.textview.get_buffer() + start, end = buffer.get_bounds() + link_list = [link.lower() for link in buffer.get_text(start, end).split("\n") if link.strip()] + if len(link_list) > 0: + w = Wait(_("Checking links, please wait."), self) + w.connect("key-press-event", self.cancel) + th = threading.Thread(group=None, target=self.check_all, name=None, args=(link_list, w)) + th.start() + + def check_all(self, link_list, wait): + """""" + buffer = self.textview.get_buffer() + store = self.treeview.get_model() + store.clear() + + service_icon = self.treeview.render_icon(gtk.STOCK_INFO, gtk.ICON_SIZE_MENU) + unsupported_icon = self.treeview.render_icon(gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_MENU) + active_icon = self.treeview.render_icon(gtk.STOCK_APPLY, gtk.ICON_SIZE_MENU) + unchecked_icon = self.treeview.render_icon(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_MENU) + unactive_icon = self.treeview.render_icon(gtk.STOCK_CANCEL, gtk.ICON_SIZE_MENU) + try: + for service, links in self.sort_links(link_list).items(): + if links != []: + if service == cons.TYPE_UNSUPPORTED: + service_iter = store.append(None, [unsupported_icon, service, service, 0, None, None, False, False]) + for link in links: + store.append(service_iter, [unchecked_icon, link, link, 0, None, None, False, False]) + else: + service_iter = store.append(None, [service_icon, service, service, 0, None, None, False, False]) + for link in links: + if self.cancel_check: + self.cancel_check = False + raise Exception("Check Links cancelled") + check, plugin_type = self.check_links(service) + file_name, size, size_unit = check(link) + if file_name: + if size > 0: + icon = active_icon + marked = True + else: + icon = unchecked_icon + marked = False + else: + icon = unactive_icon + marked = False + file_name = link + logger.info("Checked: %s %s %s" % (file_name, size, size_unit)) + store.append(service_iter, [icon, link, file_name, size, size_unit, plugin_type, marked, marked]) + self.treeview.expand_row(store.get_path(service_iter), True) + except: + gobject.idle_add(wait.destroy) + else: + buffer.set_text("") + gobject.idle_add(wait.destroy) + + def cancel(self, window, event): + """Esc key""" + if event.keyval == 65307: + window.progress.set_text(_("Check Canceled!")) + self.cancel_check = True + + def close(self, widget=None, other=None): + """""" + self.destroy() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/gtk/log_view.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/gtk/log_view.py --- tucan-0.3.8/ui/gtk/log_view.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/gtk/log_view.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,162 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import logging +logger = logging.getLogger(__name__) + +import pygtk +pygtk.require('2.0') +import gtk +import gobject + +from report import Report + +import media +import core.cons as cons + +SEVERITY = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] +COLORS = {"DEBUG": "grey", "INFO": "green", "WARNING": "yellow", "ERROR": "red", "CRITICAL": "white"} + +class LogView(gtk.Dialog): + """""" + def __init__(self, parent, stream): + """""" + gtk.Dialog.__init__(self) + self.set_transient_for(parent) + self.set_title("%s - Log View" % cons.TUCAN_NAME) + self.set_position(gtk.WIN_POS_CENTER) + self.set_size_request(700,500) + self.set_icon(self.render_icon(gtk.STOCK_FILE, gtk.ICON_SIZE_MENU)) + + self.stream = stream + self.back_buffer = gtk.TextBuffer() + self.back_buffer.set_text(self.stream.read()) + + frame = gtk.Frame() + self.vbox.pack_start(frame) + frame.set_border_width(10) + hbox = gtk.HBox() + frame.add(hbox) + + #auto scroll + scroll = gtk.ScrolledWindow() + hbox.pack_start(scroll) + scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + scroll.get_vadjustment().connect("changed", self.changed) + scroll.get_vadjustment().connect("value-changed", self.value_changed) + + #textview + buffer = gtk.TextBuffer() + self.textview = gtk.TextView(buffer) + scroll.add(self.textview) + self.textview.set_wrap_mode(gtk.WRAP_NONE) + self.textview.set_editable(False) + self.textview.set_cursor_visible(False) + self.textview.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse("black")) + + table = buffer.get_tag_table() + for name, color in COLORS.items(): + tag = gtk.TextTag(name) + tag.set_property("foreground", color) + tag.set_property("left_margin", 10) + tag.set_property("right_margin", 10) + table.add(tag) + + #combo + hbox = gtk.HBox() + self.vbox.pack_start(hbox, False, False, 10) + buttonbox = gtk.HButtonBox() + hbox.pack_start(buttonbox, False, False, 10) + label = gtk.Label("Minimum severity shown.") + hbox.pack_start(label, False, False, 10) + aspect = gtk.AspectFrame() + aspect.set_shadow_type(gtk.SHADOW_NONE) + hbox.pack_start(aspect) + + self.combo = gtk.combo_box_new_text() + buttonbox.pack_start(self.combo) + self.combo.connect("changed", self.reload) + + for s in SEVERITY: + self.combo.append_text(s) + self.combo.set_active(2) + + #action area + button = gtk.Button("Report ") + self.action_area.pack_start(button) + pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(media.ICON_SEND, 24, 24) + button.set_image(gtk.image_new_from_pixbuf(pixbuf)) + button.connect("clicked", self.report) + button = gtk.Button(None, gtk.STOCK_CLOSE) + self.action_area.pack_start(button) + button.connect("clicked", self.close) + + self.connect("response", self.close) + self.show_all() + + gobject.timeout_add(1000, self.update) + self.run() + + def report(self, button=None): + """""" + Report(self) + + def insert_color(self, buffer, line): + """""" + for s in SEVERITY[self.combo.get_active():]: + if s in line and buffer.get_tag_table().lookup(s): + buffer.insert_with_tags(buffer.get_end_iter(), "%s\n" % line, buffer.get_tag_table().lookup(s)) + break + + def reload(self, textview): + """""" + buffer = self.textview.get_buffer() + buffer.set_text("") + ini, fin = self.back_buffer.get_bounds() + for line in self.back_buffer.get_text(ini, fin).split("\n"): + self.insert_color(buffer, line) + + def update(self): + """""" + try: + lines = self.stream.readlines() + if lines: + buffer = self.textview.get_buffer() + for line in lines: + self.back_buffer.insert(self.back_buffer.get_end_iter(), line) + self.insert_color(buffer, line.strip()) + except Exception, e: + logger.exception(e) + else: + return True + + def changed(self, vadjust): + """autoscroll""" + if not hasattr(vadjust, "need_scroll") or vadjust.need_scroll: + vadjust.set_value(vadjust.upper-vadjust.page_size) + vadjust.need_scroll = True + + def value_changed (self, vadjust): + """autoscroll""" + vadjust.need_scroll = abs(vadjust.value + vadjust.page_size - vadjust.upper) < vadjust.step_increment + + def close(self, widget=None, other=None): + """""" + self.destroy() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/gtk/media.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/gtk/media.py --- tucan-0.3.8/ui/gtk/media.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/gtk/media.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,49 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import os.path + +from core.cons import PATH + +#media constants +PATH_MEDIA = os.path.join(PATH, "media", "") +ICON_TUCAN = PATH_MEDIA + "tucan.svg" +ICON_DOWNLOAD = PATH_MEDIA + "document-save.svg" +ICON_UPLOAD = PATH_MEDIA + "system-software-update.svg" +ICON_CLEAR = PATH_MEDIA + "edit-delete.svg" +ICON_DOWN = PATH_MEDIA + "go-down.svg" +ICON_UP = PATH_MEDIA + "go-up.svg" +ICON_START = PATH_MEDIA + "media-playback-start.svg" +ICON_STOP = PATH_MEDIA + "media-playback-stop.svg" +ICON_CHECK = PATH_MEDIA + "software-update-available.svg" +ICON_PACKAGE = PATH_MEDIA + "package-x-generic.svg" +ICON_PREFERENCES = PATH_MEDIA + "preferences-system.svg" +ICON_PREFERENCES_MAIN = PATH_MEDIA + "preferences-desktop.svg" +ICON_PREFERENCES_SERVICES = PATH_MEDIA + "contact-new.svg" +ICON_PREFERENCES_ADVANCED = PATH_MEDIA + "applications-system.svg" +ICON_LANGUAGE = PATH_MEDIA + "preferences-desktop-locale.svg" +ICON_FOLDER = PATH_MEDIA + "user-home.svg" +ICON_NETWORK = PATH_MEDIA + "network-error.svg" +ICON_ADVANCED = PATH_MEDIA + "application-x-executable.svg" +ICON_MISSING = PATH_MEDIA + "image-missing.svg" +ICON_ACCOUNT = PATH_MEDIA + "system-users.svg" +ICON_UPDATE = PATH_MEDIA + "software-update-urgent.svg" +ICON_SEND = PATH_MEDIA + "mail-reply-sender.svg" + diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/gtk/menu_bar.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/gtk/menu_bar.py --- tucan-0.3.8/ui/gtk/menu_bar.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/gtk/menu_bar.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,81 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import logging +logger = logging.getLogger(__name__) + +import pygtk +pygtk.require('2.0') +import gtk + +import core.cons as cons + +class MenuBar(gtk.MenuBar): + """""" + def __init__(self, list): + """list = [(menu_name=str, [(item_image=stock_item, callback), None=separator])]""" + gtk.MenuBar.__init__(self) + for menu in list: + item = gtk.MenuItem(menu[0]) + self.append(item) + submenu = gtk.Menu() + for sub in menu[1]: + if sub == None: + subitem = gtk.SeparatorMenuItem() + elif isinstance(sub[0], gtk.CheckMenuItem): + subitem = sub[0] + subitem.set_active(sub[2]) + subitem.connect("toggled", sub[1]) + else: + subitem = gtk.ImageMenuItem(sub[0]) + subitem.connect("activate", sub[1]) + submenu.append(subitem) + item.set_submenu(submenu) + +if cons.OS_OSX: + try: + from igemacintegration import * + + except Exception: + pass + else: + class OSXMenuBar(MenuBar): + """""" + def __init__(self, menu, menu_about, menu_preferences, menu_quit): + """""" + MenuBar.__init__(self, menu) + self.show_all() + + macmenu = MacMenu() + macmenu.set_menu_bar(self) + + quit_item = gtk.MenuItem(menu_quit[0]) + quit_item.connect("activate", menu_quit[1]) + macmenu.set_quit_menu_item(quit_item) + + group = macmenu.add_app_menu_group() + item = gtk.MenuItem(menu_about[0]) + item.connect("activate", menu_about[1]) + group.add_app_menu_item(item, None) + + group = macmenu.add_app_menu_group() + item = gtk.MenuItem(menu_preferences[0]) + item.connect("activate", menu_preferences[1]) + group.add_app_menu_item(item, None) diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/gtk/message.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/gtk/message.py --- tucan-0.3.8/ui/gtk/message.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/gtk/message.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,114 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import pygtk +pygtk.require('2.0') +import gtk +import gobject + +import core.cons as cons + +class Wait(gtk.Window): + """""" + def __init__(self, message, parent): + """""" + gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL) + self.set_transient_for(parent) + self.set_modal(True) + self.set_position(gtk.WIN_POS_CENTER) + self.set_property("skip-pager-hint", True) + self.set_property("skip-taskbar-hint", True) + self.set_resizable(False) + self.set_decorated(False) + self.set_size_request(300,100) + + self.progress = gtk.ProgressBar() + self.add(self.progress) + self.progress.set_text(message) + + self.show_all() + + gobject.timeout_add(100, self.pulse) + + def pulse(self): + """""" + self.progress.pulse() + return True + +class Message(gtk.Dialog): + """""" + def __init__(self, parent, severity, title, message, accept=False, both=False, run=True): + """""" + gtk.Dialog.__init__(self) + self.set_title(title) + self.set_position(gtk.WIN_POS_CENTER) + self.set_resizable(False) + self.set_transient_for(parent) + + self.accepted = False + + hbox = gtk.HBox() + self.vbox.pack_start(hbox, True, True, 10) + icon = gtk.STOCK_DIALOG_INFO + if severity == cons.SEVERITY_WARNING: + icon = gtk.STOCK_DIALOG_WARNING + elif severity == cons.SEVERITY_ERROR: + icon = gtk.STOCK_DIALOG_ERROR + hbox.pack_start(gtk.image_new_from_stock(icon, gtk.ICON_SIZE_DIALOG), True, False, 10) + self.set_icon(self.render_icon(icon, gtk.ICON_SIZE_MENU)) + + self.label = gtk.Label(message) + hbox.pack_start(self.label, True, False, 5) + self.label.set_width_chars(35) + self.label.set_line_wrap(True) + + #action area + if both: + close_button = gtk.Button(None, gtk.STOCK_CANCEL) + self.action_area.pack_start(close_button) + close_button.connect("clicked", self.close) + ok_button = gtk.Button(None, gtk.STOCK_OK) + self.action_area.pack_start(ok_button) + ok_button.connect("clicked", self.accept) + elif accept: + ok_button = gtk.Button(None, gtk.STOCK_OK) + self.action_area.pack_start(ok_button) + ok_button.connect("clicked", self.accept) + else: + close_button = gtk.Button(None, gtk.STOCK_CLOSE) + self.action_area.pack_start(close_button) + close_button.connect("clicked", self.close) + + self.connect("response", self.close) + self.show_all() + if run: + self.run() + + def accept(self, button): + """""" + self.accepted = True + self.close() + + def close(self, widget=None, other=None): + """""" + self.destroy() + +if __name__ == "__main__": + m = Message(None, cons.SEVERITY_WARNING, "Tucan Manager - Restore previous session.", "Your last session closed unexpectedly.\nTucan will try to restore it now.", both=True) diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/gtk/preferences.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/gtk/preferences.py --- tucan-0.3.8/ui/gtk/preferences.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/gtk/preferences.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,443 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import __builtin__ +import logging +logger = logging.getLogger(__name__) + +import pygtk +pygtk.require('2.0') +import gtk +import gobject +import pango + +from service_preferences import ServicePreferences +from message import Message +from file_chooser import FileChooser +from update_manager import UpdateManager + +import core.config as config +import core.url_open as url_open +import core.service_config as service_config + +import media +import core.cons as cons + +LANGUAGES = [ ("Czech", "cs"), + ("English", "en"), + ("French", "fr"), + ("German", "de"), + ("Greek","gr"), + ("Italian", "it"), + ("Polish", "pl"), + ("Portuguese", "pt"), + ("Russian", "ru"), + ("Slovak", "sk"), + ("Spanish", "es"), + ("Swedish","se")] + +class Preferences(gtk.Dialog): + """""" + def __init__(self, parent, configuration, show_services=False, remote_info=None): + """""" + gtk.Dialog.__init__(self) + self.set_transient_for(parent) + self.set_icon_from_file(media.ICON_PREFERENCES) + self.set_title("%s - Preferences" % cons.TUCAN_NAME) + self.set_position(gtk.WIN_POS_CENTER) + self.set_size_request(500,500) + + self.config = configuration + + self.notebook = gtk.Notebook() + self.notebook.set_property("homogeneous", True) + self.vbox.pack_start(self.notebook) + self.new_page(_("General Configuration"), media.ICON_PREFERENCES_MAIN, self.init_main()) + self.new_page(_("Service Configuration"), media.ICON_PREFERENCES_SERVICES, self.init_services()) + self.new_page(_("Advanced Configuration"), media.ICON_PREFERENCES_ADVANCED, self.init_advanced()) + + #action area + cancel_button = gtk.Button(None, gtk.STOCK_CANCEL) + save_button = gtk.Button(None, gtk.STOCK_SAVE) + self.action_area.pack_start(cancel_button) + self.action_area.pack_start(save_button) + cancel_button.connect("clicked", self.close) + save_button.connect("clicked", self.save) + + self.connect("response", self.close) + self.show_all() + + if show_services: + self.notebook.set_current_page(1) + if remote_info: + gobject.idle_add(self.update_manager, None, remote_info) + self.run() + + def save(self, button): + """""" + self.config.set(config.SECTION_MAIN, config.OPTION_LANGUAGE, [lang[1] for lang in LANGUAGES][self.language.get_active()]) + + #live changes + self.config.set(config.SECTION_MAIN, config.OPTION_MAX_DOWNLOADS, str(self.max_downloads.get_value_as_int())) + __builtin__.max_downloads = self.max_downloads.get_value_as_int() + self.config.set(config.SECTION_MAIN, config.OPTION_MAX_DOWNLOAD_SPEED, str(self.max_download_speed.get_value_as_int())) + __builtin__.max_download_speed = self.max_download_speed.get_value_as_int() + + #self.config.set(config.SECTION_MAIN, config.OPTION_MAX_UPLOADS, str(self.max_uploads.get_value_as_int())) + self.config.set_downloads_folder(self.downloads_folder.get_label()) + + model = self.treeview.get_model() + iter = model.get_iter_root() + while iter: + configuration = model.get_value(iter, 3) + configuration.enable(model.get_value(iter, 2)) + if not self.config.has_option(config.SECTION_SERVICES, model.get_value(iter,1)): + self.config.set(config.SECTION_SERVICES, model.get_value(iter,1), configuration.path) + iter = model.iter_next(iter) + + self.config.set(config.SECTION_ADVANCED, config.OPTION_TRAY_CLOSE, str(self.tray_close.get_active())) + self.config.set(config.SECTION_ADVANCED, config.OPTION_ADVANCED_PACKAGES, str(self.advanced_packages.get_active())) + self.config.set(config.SECTION_ADVANCED, config.OPTION_SAVE_SESSION, str(self.save_session.get_active())) + self.config.set(config.SECTION_ADVANCED, config.OPTION_AUTO_UPDATE, str(self.auto_update.get_active())) + self.config.set(config.SECTION_ADVANCED, config.OPTION_SHOW_UPLOADS, str(self.show_uploads.get_active())) + self.config.set(config.SECTION_ADVANCED, config.OPTION_ENABLE_PROXY, str(self.enable_proxy.get_active())) + self.config.set(config.SECTION_ADVANCED, config.OPTION_PROXY_URL, self.proxy_url.get_text()) + self.config.set(config.SECTION_ADVANCED, config.OPTION_PROXY_PORT, str(self.proxy_port.get_value_as_int())) + + #change proxy settings + if self.enable_proxy.get_active(): + proxy_url, proxy_port = self.config.get_proxy() + url_open.set_proxy(proxy_url, proxy_port) + else: + url_open.set_proxy(None) + + self.config.save() + self.close() + + def new_page(self, tab_name, tab_image, page): + """""" + vbox = gtk.VBox() + vbox.pack_start(gtk.image_new_from_file(tab_image)) + vbox.pack_start(gtk.Label(tab_name)) + vbox.show_all() + self.notebook.append_page(page, vbox) + self.notebook.set_tab_label_packing(page, True, True, gtk.PACK_START) + + def init_main(self): + """""" + vbox = gtk.VBox() + + frame = gtk.Frame() + frame.set_label_widget(gtk.image_new_from_file(media.ICON_LANGUAGE)) + frame.set_border_width(5) + vbox.pack_start(frame, False, False) + hbox = gtk.HBox() + vbox1 = gtk.VBox() + frame.add(vbox1) + hbox = gtk.HBox() + vbox1.pack_start(hbox, False, False, 5) + label = gtk.Label(_("Choose language: ")) + hbox.pack_start(label, False, False, 10) + aspect = gtk.AspectFrame() + aspect.set_shadow_type(gtk.SHADOW_NONE) + hbox.pack_start(aspect) + self.language = gtk.combo_box_new_text() + for lang in [lang[0] for lang in LANGUAGES]: + self.language.append_text(lang) + self.language.set_active([lang[1] for lang in LANGUAGES].index(self.config.get(config.SECTION_MAIN, config.OPTION_LANGUAGE))) + hbox.pack_start(self.language, False, False, 10) + + frame = gtk.Frame() + frame.set_label_widget(gtk.image_new_from_file(media.ICON_NETWORK)) + frame.set_border_width(5) + vbox.pack_start(frame, False, False) + vbox1 = gtk.VBox() + frame.add(vbox1) + hbox = gtk.HBox() + label = gtk.Label(_("Max simultaneous downloads: ")) + hbox.pack_start(label, False, False, 10) + aspect = gtk.AspectFrame() + aspect.set_shadow_type(gtk.SHADOW_NONE) + hbox.pack_start(aspect) + self.max_downloads = gtk.SpinButton(None, 1, 0) + self.max_downloads.set_range(1,20) + self.max_downloads.set_increments(1,0) + self.max_downloads.set_numeric(True) + self.max_downloads.set_value(self.config.getint(config.SECTION_MAIN, config.OPTION_MAX_DOWNLOADS)) + hbox.pack_start(self.max_downloads, False, False, 10) + vbox1.pack_start(hbox, False, False, 2) + hbox = gtk.HBox() + label = gtk.Label(_("Max download speed: ")) + hbox.pack_start(label, False, False, 10) + aspect = gtk.AspectFrame() + aspect.set_shadow_type(gtk.SHADOW_NONE) + hbox.pack_start(aspect) + self.max_download_speed = gtk.SpinButton(None, 4, 0) + self.max_download_speed.set_range(0,5000) + self.max_download_speed.set_increments(4,0) + self.max_download_speed.set_numeric(True) + self.max_download_speed.set_value(self.config.getint(config.SECTION_MAIN, config.OPTION_MAX_DOWNLOAD_SPEED)) + hbox.pack_start(self.max_download_speed, False, False, 10) + vbox1.pack_start(hbox, False, False, 2) + #hbox = gtk.HBox() + #label = gtk.Label(_("Max simultaneous uploads: ")) + #hbox.pack_start(label, False, False, 10) + #aspect = gtk.AspectFrame() + #aspect.set_shadow_type(gtk.SHADOW_NONE) + #hbox.pack_start(aspect) + #self.max_uploads = gtk.SpinButton(None, 1, 0) + #self.max_uploads.set_range(1,10) + #self.max_uploads.set_increments(1,0) + #self.max_uploads.set_numeric(True) + #self.max_uploads.set_value(self.config.getint(config.SECTION_MAIN, config.OPTION_MAX_UPLOADS)) + #hbox.pack_start(self.max_uploads, False, False, 10) + #vbox1.pack_start(hbox, False, False, 2) + + frame = gtk.Frame() + frame.set_label_widget(gtk.image_new_from_file(media.ICON_FOLDER)) + frame.set_border_width(5) + vbox.pack_start(frame, False, False) + vbox1 = gtk.VBox() + frame.add(vbox1) + hbox = gtk.HBox() + vbox1.pack_start(hbox, False, False, 5) + + label = gtk.Label(_("Downloads Folder: ")) + hbox.pack_start(label, False, False, 10) + path = self.config.get_downloads_folder() + self.downloads_folder = gtk.Label(path) + self.downloads_folder.set_width_chars(30) + self.downloads_folder.set_alignment(0, 0.5) + self.downloads_folder.set_ellipsize(pango.ELLIPSIZE_START) + hbox.pack_start(self.downloads_folder, False, False, 10) + bbox = gtk.HButtonBox() + bbox.set_layout(gtk.BUTTONBOX_END) + hbox.pack_start(bbox, True, True, 10) + button = gtk.Button(None, gtk.STOCK_OPEN) + button.connect("clicked", self.choose_path) + bbox.pack_start(button) + + vbox.show_all() + return vbox + + def choose_path(self, button): + """""" + FileChooser(self, self.downloads_folder.set_label, self.downloads_folder.get_label()) + + def init_services(self): + """""" + vbox = gtk.VBox() + + frame = gtk.Frame() + frame.set_size_request(-1, 300) + vbox.pack_start(frame) + frame.set_border_width(10) + scroll = gtk.ScrolledWindow() + frame.add(scroll) + scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + store = gtk.ListStore(gtk.gdk.Pixbuf, str, bool, gobject.TYPE_PYOBJECT) + self.treeview = gtk.TreeView(store) + scroll.add(self.treeview) + self.treeview.connect("row-activated", self.service_preferences) + + self.treeview.set_rules_hint(True) + #self.treeview.set_headers_visible(False) + + tree_icon = gtk.TreeViewColumn('Icon') + icon_cell = gtk.CellRendererPixbuf() + icon_cell.set_property("width", 50) + tree_icon.pack_start(icon_cell, False) + tree_icon.add_attribute(icon_cell, 'pixbuf', 0) + self.treeview.append_column(tree_icon) + + tree_name = gtk.TreeViewColumn('Name') + name_cell = gtk.CellRendererText() + name_cell.set_property("width", 300) + name_cell.set_property("xalign", 0.1) + tree_name.pack_start(name_cell, True) + tree_name.add_attribute(name_cell, 'text', 1) + self.treeview.append_column(tree_name) + + tree_enable = gtk.TreeViewColumn('Enabled') + enable_cell = gtk.CellRendererToggle() + enable_cell.connect("toggled", self.toggled) + tree_enable.pack_start(enable_cell, True) + tree_enable.add_attribute(enable_cell, 'active', 2) + self.treeview.append_column(tree_enable) + + #fill store + for path, icon_path, name, enabled, configuration in self.config.get_services(): + self.add_service(path, icon_path, name, enabled, configuration) + + frame = gtk.Frame() + frame.set_border_width(10) + frame.set_shadow_type(gtk.SHADOW_NONE) + vbox.pack_start(frame, False, False) + bbox = gtk.HButtonBox() + bbox.set_layout(gtk.BUTTONBOX_EDGE) + frame.add(bbox) + button = gtk.Button(None, gtk.STOCK_FIND) + button.connect("clicked", self.update_manager) + bbox.pack_start(button) + button = gtk.Button(None, gtk.STOCK_REMOVE) + button.connect("clicked", self.delete_service) + bbox.pack_start(button) + aspect = gtk.AspectFrame() + aspect.set_shadow_type(gtk.SHADOW_NONE) + bbox.pack_start(aspect) + button = gtk.Button(None, gtk.STOCK_INFO) + button.connect("clicked", self.service_info) + bbox.pack_start(button) + + hbox = gtk.HBox() + vbox.pack_start(hbox, False, False, 5) + label = gtk.Label() + hbox.pack_start(label, False, False, 10) + label.set_markup("* " + _("Restart Tucan to apply service changes.") + "") + + return vbox + + def service_info(self, button): + """""" + model, iter = self.treeview.get_selection().get_selected() + if iter: + self.service_preferences(None, model.get_path(iter)) + + def add_service(self, path, icon_path, name, enabled, configuration): + """""" + if configuration: + try: + icon = gtk.gdk.pixbuf_new_from_file_at_size(icon_path, 32, 32) + except Exception: + icon = gtk.gdk.pixbuf_new_from_file_at_size(media.ICON_MISSING, 32, 32) + logger.info("Could not load: %s" % icon_path) + self.treeview.get_model().append((icon, name, enabled, configuration)) + else: + Message(self, cons.SEVERITY_ERROR, path , _("Service not configured.")) + + def update_manager(self, button=None, remote_info=None): + """""" + UpdateManager(self, self.config, remote_info) + self.treeview.get_model().clear() + for path, icon_path, name, enabled, configuration in self.config.get_services(): + self.add_service(path, icon_path, name, enabled, configuration) + + def delete_service(self, button): + """""" + model, iter = self.treeview.get_selection().get_selected() + if iter: + next_iter = model.iter_next(iter) + self.config.remove_option(config.SECTION_SERVICES, model.get_value(iter, 1)) + model.remove(iter) + if next_iter: + self.treeview.set_cursor_on_cell(model.get_path(next_iter)) + + def toggled(self, button, path): + """""" + model = self.treeview.get_model() + if button.get_active(): + active = False + else: + tos = _("Before using this service, you must accept it's terms of service at ") + model.get_value(model.get_iter(path), 1) + m = Message(self, cons.SEVERITY_INFO, _("Tucan Manager - Terms of service"), tos, True) + active = m.accepted + button.set_active(active) + model.set_value(model.get_iter(path), 2, active) + + def service_preferences(self, treeview, path, view_column=None): + """""" + model = self.treeview.get_model() + icon = model.get_value(model.get_iter(path), 0) + name = model.get_value(model.get_iter(path), 1) + config = model.get_value(model.get_iter(path), 3) + ServicePreferences(self, name, icon, config) + + def init_advanced(self): + """""" + frame = gtk.Frame() + frame.set_label_widget(gtk.image_new_from_file(media.ICON_ADVANCED)) + frame.set_border_width(10) + hbox = gtk.HBox() + frame.add(hbox) + vbox = gtk.VBox() + hbox.pack_start(vbox, True, True, 10) + + self.tray_close = gtk.CheckButton(_("Close to tray.")) + vbox.pack_start(self.tray_close, False, False, 5) + self.tray_close.set_active(self.config.getboolean(config.SECTION_ADVANCED, config.OPTION_TRAY_CLOSE)) + + self.save_session = gtk.CheckButton(_("Save session on close.")) + vbox.pack_start(self.save_session, False, False, 5) + self.save_session.set_active(self.config.getboolean(config.SECTION_ADVANCED, config.OPTION_SAVE_SESSION)) + + self.advanced_packages = gtk.CheckButton(_("Default advanced packages.")) + vbox.pack_start(self.advanced_packages, False, False, 5) + self.advanced_packages.set_active(self.config.getboolean(config.SECTION_ADVANCED, config.OPTION_ADVANCED_PACKAGES)) + + self.auto_update = gtk.CheckButton(_("Automatic check for updates.")) + vbox.pack_start(self.auto_update, False, False, 5) + self.auto_update.set_active(self.config.getboolean(config.SECTION_ADVANCED, config.OPTION_AUTO_UPDATE)) + + self.show_uploads = gtk.CheckButton(_("Show uploads.")) + vbox.pack_start(self.show_uploads, False, False, 5) + self.show_uploads.set_active(self.config.getboolean(config.SECTION_ADVANCED, config.OPTION_SHOW_UPLOADS)) + + self.enable_proxy = gtk.CheckButton(_("Enable proxy:")) + vbox.pack_start(self.enable_proxy, False, False, 5) + self.enable_proxy.set_active(self.config.getboolean(config.SECTION_ADVANCED, config.OPTION_ENABLE_PROXY)) + self.enable_proxy.connect("toggled", self.change_state) + + self.proxy_box = gtk.HBox() + vbox.pack_start(self.proxy_box, False, False, 5) + self.proxy_box.pack_start(gtk.Label("HTTP Proxy:"), False, False, 5) + self.proxy_url = gtk.Entry() + self.proxy_box.pack_start(self.proxy_url, True, True, 5) + self.proxy_url.set_text(self.config.get(config.SECTION_ADVANCED, config.OPTION_PROXY_URL)) + + self.proxy_box.pack_start(gtk.Label("Port:"), False, False, 5) + self.proxy_port = gtk.SpinButton(None, 1, 0) + self.proxy_box.pack_start(self.proxy_port, False, False, 5) + self.proxy_port.set_range(0,65535) + self.proxy_port.set_increments(1,0) + self.proxy_port.set_numeric(True) + self.proxy_port.set_value(self.config.getint(config.SECTION_ADVANCED, config.OPTION_PROXY_PORT)) + + self.change_state() + + return frame + + def change_state(self, button=None): + """""" + self.proxy_box.set_sensitive(self.enable_proxy.get_active()) + + def close(self, widget=None, other=None): + """""" + enabled_services = 0 + model = self.treeview.get_model() + iter = model.get_iter_root() + while iter: + if model.get_value(iter, 3).getboolean(service_config.SECTION_MAIN, service_config.OPTION_ENABLED): + enabled_services += 1 + iter = model.iter_next(iter) + if enabled_services > 0: + self.destroy() + else: + Message(self, cons.SEVERITY_WARNING, _("Tucan Manager - No services enabled!") , _("Enable some services and restart Tucan.")) + self.run() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/gtk/report.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/gtk/report.py --- tucan-0.3.8/ui/gtk/report.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/gtk/report.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,150 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import threading +import logging +logger = logging.getLogger(__name__) + +import pygtk +pygtk.require('2.0') +import gtk +import gobject + +from message import Message + +from core.misc import report_log +import core.cons as cons +import media + +class Report(gtk.Dialog): + """""" + def __init__(self, parent): + """""" + gtk.Dialog.__init__(self) + self.set_transient_for(parent) + self.set_title("%s - Report problem" % cons.TUCAN_NAME) + self.set_position(gtk.WIN_POS_CENTER) + self.set_size_request(400, 300) + self.set_icon_from_file(media.ICON_SEND) + + self.sending = False + + frame = gtk.Frame() + label = gtk.Label() + label.set_markup("%s: " % ("Email")) + frame.set_label_widget(label) + self.vbox.pack_start(frame, False) + frame.set_border_width(10) + self.email = gtk.Entry() + frame.add(self.email) + + frame = gtk.Frame() + label = gtk.Label() + label.set_markup("%s: " % ("Comment")) + frame.set_label_widget(label) + self.vbox.pack_start(frame) + frame.set_border_width(10) + hbox = gtk.HBox() + frame.add(hbox) + scroll = gtk.ScrolledWindow() + hbox.pack_start(scroll) + scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + + #textview + buffer = gtk.TextBuffer() + self.textview = gtk.TextView(buffer) + scroll.add(self.textview) + self.textview.set_wrap_mode(gtk.WRAP_WORD) + + #status + self.status_hbox = gtk.HBox() + self.vbox.pack_start(self.status_hbox, False, False, 5) + self.label = gtk.Label("Sending report.") + self.status_hbox.pack_start(self.label, False, False, 11) + self.progress = gtk.ProgressBar() + self.progress.pulse() + self.status_hbox.pack_start(self.progress, True, True, 11) + + #action area + cancel_button = gtk.Button(None, gtk.STOCK_CANCEL) + ok_button = gtk.Button(None, gtk.STOCK_OK) + self.action_area.pack_start(cancel_button) + self.action_area.pack_start(ok_button) + cancel_button.connect("clicked", self.close) + ok_button.connect("clicked", self.send) + + self.connect("response", self.close) + self.show_all() + self.status_hbox.hide() + self.run() + + def send(self, button): + """""" + self.status_hbox.show() + self.email.set_sensitive(False) + self.textview.set_editable(False) + self.textview.set_cursor_visible(False) + self.action_area.set_sensitive(False) + th = threading.Thread(group=None, target=self.th_send, name=None) + th.start() + + def th_send(self): + """""" + self.sending = True + gobject.timeout_add(100, self.pulse) + buffer = self.textview.get_buffer() + start, end = buffer.get_bounds() + comment = buffer.get_text(start, end).strip() + id = report_log(self.email.get_text(), comment) + self.sending = False + gobject.idle_add(self.reported, id) + + def reported(self, id): + """""" + if id: + label = "Report ID:" + self.status_hbox.remove(self.status_hbox.get_children().pop()) + id = gtk.Label(id) + id.set_selectable(True) + self.status_hbox.pack_end(id, True, False, 10) + id.show() + else: + label = "Report failed, try again later." + self.progress.hide() + self.label.set_text(label) + + close_button = gtk.Button(None, gtk.STOCK_CLOSE) + close_button.connect("clicked", self.close) + close_button.show() + for child in self.action_area.get_children(): + self.action_area.remove(child) + self.action_area.pack_start(close_button) + self.action_area.set_sensitive(True) + + def pulse(self): + """""" + if self.sending: + self.progress.pulse() + return True + + def close(self, widget=None, other=None): + """""" + if not self.sending: + self.destroy() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/gtk/service_preferences.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/gtk/service_preferences.py --- tucan-0.3.8/ui/gtk/service_preferences.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/gtk/service_preferences.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,334 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import pygtk +pygtk.require('2.0') +import gtk +import gobject + +import core.service_config as service_config +import core.cons as cons +import media + + +class InfoPreferences(gtk.VBox): + """""" + def __init__(self, section, name, config, accounts=False): + """""" + gtk.VBox.__init__(self) + vbox = gtk.VBox() + + frame = gtk.Frame() + label = gtk.Label() + label.set_markup("" + name + "") + frame.set_label_widget(label) + frame.set_border_width(10) + self.pack_start(frame) + frame.add(vbox) + + hbox = gtk.HBox() + label = gtk.Label() + label.set_markup("" + _("Author") + ":") + hbox.pack_start(label, False, False, 10) + label = gtk.Label(config.get(section, service_config.OPTION_AUTHOR)) + hbox.pack_start(label, False) + aspect = gtk.AspectFrame() + aspect.set_shadow_type(gtk.SHADOW_NONE) + hbox.pack_start(aspect) + label = gtk.Label() + label.set_markup("" + _("Version") + ":") + hbox.pack_start(label, False) + label = gtk.Label(config.get(section, service_config.OPTION_VERSION)) + hbox.pack_start(label, False, False, 10) + vbox.pack_start(hbox, False, False, 5) + + if not accounts: + hbox = gtk.HBox() + label = gtk.Label() + label.set_markup("" + _("Slots") + ":") + hbox.pack_start(label, False, False, 10) + label = gtk.Label(config.get(section, service_config.OPTION_SLOTS)) + hbox.pack_start(label, False) + vbox.pack_start(hbox, False, False, 5) + hbox = gtk.HBox() + label = gtk.Label() + label.set_markup("" + _("Captcha") + ":") + hbox.pack_start(label, False, False, 10) + label = gtk.Label(config.get(section, service_config.OPTION_CAPTCHA)) + hbox.pack_start(label, False) + vbox.pack_start(hbox, False, False, 5) + +class AccountPreferences(InfoPreferences): + """""" + def __init__(self, section, name, config, get_cookie): + """""" + InfoPreferences.__init__(self, section, name, config, True) + + self.get_cookie = get_cookie + + frame = gtk.Frame() + frame.set_label_widget(gtk.image_new_from_file(media.ICON_ACCOUNT)) + frame.set_border_width(10) + self.pack_start(frame, False, False, 1) + scroll = gtk.ScrolledWindow() + scroll.set_size_request(-1, 110) + scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + frame.add(scroll) + store = gtk.ListStore(gtk.gdk.Pixbuf, str, str, bool, bool, str) + self.treeview = gtk.TreeView(store) + scroll.add(self.treeview) + + self.treeview.set_rules_hint(True) + #self.treeview.set_headers_visible(False) + + tree_icon = gtk.TreeViewColumn('Active') + icon_cell = gtk.CellRendererPixbuf() + icon_cell.set_property("width", 50) + tree_icon.pack_start(icon_cell, True) + tree_icon.add_attribute(icon_cell, 'pixbuf', 0) + self.treeview.append_column(tree_icon) + + tree_name = gtk.TreeViewColumn('User Name') + name_cell = gtk.CellRendererText() + name_cell.set_property("width", 120) + name_cell.set_property("editable", True) + name_cell.connect("edited", self.change, 1) + tree_name.pack_start(name_cell, True) + tree_name.add_attribute(name_cell, 'text', 1) + self.treeview.append_column(tree_name) + + tree_pass = gtk.TreeViewColumn('Password') + pass_cell = gtk.CellRendererText() + pass_cell.set_property("width", 120) + pass_cell.set_property("editable", True) + pass_cell.connect("edited", self.change, 2) + pass_cell.connect("editing-started", self.show_password) + tree_pass.pack_start(pass_cell, True) + tree_pass.add_attribute(pass_cell, 'text', 5) + self.treeview.append_column(tree_pass) + + tree_enable = gtk.TreeViewColumn('Enable') + enable_cell = gtk.CellRendererToggle() + enable_cell.connect("toggled", self.toggled) + tree_enable.pack_start(enable_cell, False) + tree_enable.add_attribute(enable_cell, 'visible', 4) + tree_enable.add_attribute(enable_cell, 'active', 3) + self.treeview.append_column(tree_enable) + + self.active_service_icon = self.treeview.render_icon(gtk.STOCK_YES, gtk.ICON_SIZE_LARGE_TOOLBAR) + self.unactive_service_icon = self.treeview.render_icon(gtk.STOCK_NO, gtk.ICON_SIZE_LARGE_TOOLBAR) + + accounts = config.get_accounts(section) + for name in accounts.keys(): + password, enabled, active = accounts[name] + if active: + icon = self.active_service_icon + else: + icon = self.unactive_service_icon + store.append([icon, name, password, enabled, active, "".join(["*" for i in range(len(password))])]) + + frame = gtk.Frame() + frame.set_border_width(10) + frame.set_shadow_type(gtk.SHADOW_NONE) + self.pack_start(frame, False, False) + bbox = gtk.HButtonBox() + bbox.set_layout(gtk.BUTTONBOX_EDGE) + frame.add(bbox) + button = gtk.Button(None, gtk.STOCK_ADD) + button.connect("clicked", self.add) + bbox.pack_start(button) + button = gtk.Button(None, gtk.STOCK_REMOVE) + button.connect("clicked", self.remove) + bbox.pack_start(button) + aspect = gtk.AspectFrame() + aspect.set_shadow_type(gtk.SHADOW_NONE) + bbox.pack_start(aspect) + button = gtk.Button(None, gtk.STOCK_CONNECT) + button.connect("clicked", self.check) + bbox.pack_start(button) + + def show_password(self, cellrenderertext, editable, path): + """""" + model = self.treeview.get_model() + editable.props.text = model.get_value(model.get_iter(path), 2) + + def change(self, cellrenderertext, path, new_text, column): + """""" + model = self.treeview.get_model() + model.set_value(model.get_iter(path), column, new_text) + if column == 2: + model.set_value(model.get_iter(path), 5, "".join(["*" for i in range(len(new_text))])) + + def add(self, button): + """""" + model = self.treeview.get_model() + iter = model.append([self.unactive_service_icon, "", "", False, False, ""]) + self.treeview.set_cursor(model.get_path(iter), self.treeview.get_column(1), True) + + def remove(self, button): + """""" + model, iter = self.treeview.get_selection().get_selected() + if iter: + next_iter = model.iter_next(iter) + model.remove(iter) + if next_iter: + self.treeview.set_cursor_on_cell(model.get_path(next_iter)) + + def check(self, button): + """""" + model, iter = self.treeview.get_selection().get_selected() + if iter: + cookie = self.get_cookie(model.get_value(iter, 1), model.get_value(iter, 2)) + if cookie: + icon = self.active_service_icon + active = True + else: + icon = self.unactive_service_icon + active = False + model.set_value(iter, 0, icon) + model.set_value(iter, 3, active) + model.set_value(iter, 4, active) + + def toggled(self, button, path): + """""" + model = self.treeview.get_model() + if button.get_active(): + active = False + else: + active = True + button.set_active(active) + model.set_value(model.get_iter(path), 3, active) + + def get_accounts(self): + """""" + model = self.treeview.get_model() + iter = model.get_iter_root() + accounts = {} + while iter: + accounts[model.get_value(iter, 1)] = (model.get_value(iter, 2), model.get_value(iter, 3), model.get_value(iter, 4)) + iter = model.iter_next(iter) + return accounts + +class ServicePreferences(gtk.Dialog): + """""" + def __init__(self, parent, service, icon, config): + """""" + gtk.Dialog.__init__(self) + self.set_icon(icon) + self.set_title(service) + self.set_transient_for(parent) + self.set_size_request(600, 400) + + self.config = config + + hbox = gtk.HBox() + self.vbox.pack_start(hbox, True, True, 5) + frame = gtk.Frame() + hbox.pack_start(frame, False, False, 10) + + store = gtk.TreeStore(str, str, int) + self.treeview = gtk.TreeView(store) + self.treeview.get_selection().connect("changed", self.select) + frame.add(self.treeview) + + self.treeview.set_headers_visible(False) + + tree_name = gtk.TreeViewColumn('Name') + name_cell = gtk.CellRendererText() + name_cell.set_property("width", 100) + tree_name.pack_start(name_cell, True) + tree_name.add_attribute(name_cell, 'text', 1) + self.treeview.append_column(tree_name) + + self.notebook = gtk.Notebook() + hbox.pack_start(self.notebook, True, True, 10) + self.notebook.set_show_tabs(False) + + cont = 0 + plugin_list = [] + plugins = self.config.get_download_plugins() + if plugins: + plugin_list.append(("Download", plugins)) + plugins = self.config.get_upload_plugins() + if plugins: + plugin_list.append(("Upload", plugins)) + for item, plugins in plugin_list: + iter = store.append(None, [None, item, -1]) + for section, section_name, section_type in plugins: + page = gtk.VBox() + if section_type == cons.TYPE_ANONYMOUS: + page = InfoPreferences(section, section_name, self.config) + else: + if section_type == cons.TYPE_USER: + module, name = config.user_cookie() + elif section_type == cons.TYPE_PREMIUM: + module, name = config.premium_cookie() + if name: + module = __import__(service.split(".")[0] + "." + module, None, None, ['']) + get_cookie = eval("module" + "." + name + "()").get_cookie + page = AccountPreferences(section, section_name, self.config, get_cookie) + self.notebook.append_page(page, None) + subiter = store.append(iter, [section, section_type, cont]) + self.treeview.expand_to_path(store.get_path(subiter)) + if cont == 0: + self.treeview.set_cursor_on_cell(store.get_path(subiter)) + cont += 1 + #action area + cancel_button = gtk.Button(None, gtk.STOCK_CANCEL) + save_button = gtk.Button(None, gtk.STOCK_SAVE) + self.action_area.pack_start(cancel_button) + self.action_area.pack_start(save_button) + cancel_button.connect("clicked", self.close) + save_button.connect("clicked", self.save) + + self.connect("response", self.close) + self.show_all() + self.run() + + def select(self, selection): + """""" + model, iter = selection.get_selected() + if iter: + child_iter = model.iter_children(iter) + if child_iter: + selection.select_iter(child_iter) + else: + self.notebook.set_current_page(model.get_value(iter, 2)) + + def save(self, button): + """""" + model = self.treeview.get_model() + iter = model.get_iter_root() + while iter: + child_iter = model.iter_children(iter) + while child_iter: + page = self.notebook.get_nth_page((model.get_value(iter, 2))) + if ((page) and (model.get_value(child_iter, 1) != cons.TYPE_ANONYMOUS)): + self.config.set_accounts(model.get_value(child_iter, 0), page.get_accounts()) + child_iter = model.iter_next(child_iter) + iter = model.iter_next(iter) + self.close() + + def close(self, widget=None, other=None): + """""" + self.destroy() + +if __name__ == "__main__": + x = ServicePreferences("rapidshare.com", gtk.gdk.pixbuf_new_from_file(media.ICON_MISSING), service_config.ServiceConfig("/home/crak/.tucan/plugins/megaupload/")) diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/gtk/shutdown.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/gtk/shutdown.py --- tucan-0.3.8/ui/gtk/shutdown.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/gtk/shutdown.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,72 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import time +import logging +import subprocess +logger = logging.getLogger(__name__) + +import pygtk +pygtk.require('2.0') +import gtk +import gobject + +from message import Message + +import core.cons as cons + +class Shutdown: + """""" + def __init__(self, parent, quit): + """""" + self.time = 60 + title = "Tucan Manager - Shutting down!" + self.message = "The system is going to shut down in" + self.dialog = Message(parent, cons.SEVERITY_WARNING, title, "%s 1 minute." % self.message, True, True, False) + gobject.timeout_add(1000, self.counter) + self.dialog.run() + if self.dialog.accepted: + try: + if cons.OS_WINDOWS: + if subprocess.call(["shutdown.exe", "-f", "-s"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, creationflags=134217728) == 0: + quit() + elif cons.OS_OSX: + if subprocess.call(["osascript", "-e", "tell application \"Finder\" to shut down"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0: + quit() + else: + if subprocess.call(["sudo", "-n", "shutdown", "h", "now"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0: + quit() + Message(parent, cons.SEVERITY_ERROR, title, "Could not shut down the computer.") + except Exception, e: + logger.exception(e) + + def counter(self): + """""" + if self.time > 0: + self.time -= 1 + self.dialog.label.set_text("%s %i seconds." % (self.message, self.time)) + return True + else: + self.dialog.accepted = True + self.dialog.close() + +if __name__ == "__main__": + Shutdown(None, None) + \ No newline at end of file diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/gtk/statusbar.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/gtk/statusbar.py --- tucan-0.3.8/ui/gtk/statusbar.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/gtk/statusbar.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,153 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import time +import __builtin__ +import logging +logger = logging.getLogger(__name__) + +import pygtk +pygtk.require('2.0') +import gtk +import gobject + +import media +import core.cons as cons + +class Statusbar(gtk.Statusbar): + """""" + def __init__(self): + """""" + gtk.Statusbar.__init__(self) + self.set_has_resize_grip(False) + + self.services = configuration.get_services() + self.blinks = 0 + + #download speed limit + frame = gtk.Frame() + frame.set_shadow_type(gtk.SHADOW_IN) + self.pack_start(frame, False, False) + hbox = gtk.HBox() + frame.add(hbox) + label = gtk.Label(_("Max speed:")) + hbox.pack_start(label, False, False, 2) + self.max_speed = gtk.SpinButton(None, 4, 0) + self.max_speed.set_property("shadow-type", gtk.SHADOW_NONE) + self.max_speed.set_range(0,5000) + self.max_speed.set_increments(4,0) + self.max_speed.set_numeric(True) + self.max_speed.set_value(__builtin__.max_download_speed) + hbox.pack_start(self.max_speed, False, False, ) + + self.max_speed.connect("value-changed", self.change_speed) + + self.menu = gtk.Menu() + + self.limits = {} + events.connect(cons.EVENT_LIMIT_ON, self.add_limit) + events.connect(cons.EVENT_LIMIT_OFF, self.remove_limit) + + frame = gtk.Frame() + frame.set_shadow_type(gtk.SHADOW_IN) + self.pack_start(frame, False, False) + hbox = gtk.HBox() + frame.add(hbox) + label = gtk.Label("Limits:") + hbox.pack_start(label, False, False, 2) + self.button = gtk.Button() + self.button.set_image(gtk.Arrow(gtk.ARROW_UP, gtk.SHADOW_NONE)) + hbox.pack_start(self.button, False, False, 2) + self.button.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#fff")) + + self.button.connect("clicked", self.show_stack) + self.show_all() + + def synchronize(self): + """""" + self.max_speed.set_value(__builtin__.max_download_speed) + + def change_speed(self, spinbutton): + """""" + __builtin__.max_download_speed = spinbutton.get_value_as_int() + + def blink(self): + """""" + if self.blinks < 10: + self.blinks += 1 + if self.blinks % 2: + self.button.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#f99")) + else: + self.button.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#fff")) + return True + else: + self.blinks = 0 + + def add_limit(self, module): + """""" + tmp = module.split(".") + callback = lambda x: events.trigger_limit_cancel(module) + if not module in self.limits: + for name, icon_path, url, enabled, config in self.services: + if tmp[0] == name: + self.limits[module] = self.new_item(url, tmp[1], icon_path, callback) + gobject.timeout_add(500, self.blink) + break + + def remove_limit(self, module): + """""" + if module in self.limits: + del self.limits[module] + + def show_stack(self, widget): + """""" + for limit in self.menu: + self.menu.remove(limit) + if len(self.limits) == 0: + self.menu.append(self.new_item("None", "", None, lambda x: x)) + else: + for module, item in self.limits.items(): + self.menu.append(item) + self.menu.append(gtk.SeparatorMenuItem()) + self.menu.show_all() + self.menu.popup(None, None, self.menu_position, 1, 0, widget.get_allocation()) + + def new_item(self, service, service_type, icon_path, callback): + """""" + limit = gtk.MenuItem() + limit.connect("activate", callback) + vbox = gtk.VBox() + hbox = gtk.HBox() + vbox.pack_start(hbox) + if icon_path: + icon = gtk.gdk.pixbuf_new_from_file_at_size(icon_path, 32, 32) + else: + icon = gtk.gdk.pixbuf_new_from_file_at_size(media.ICON_MISSING, 32, 32) + hbox.pack_start(gtk.image_new_from_pixbuf(icon)) + hbox.pack_start(gtk.Label(service)) + vbox.pack_start(gtk.Label(service_type)) + limit.add(vbox) + return limit + + def menu_position(self, menu, rect): + """""" + width, height = menu.size_request() + window_x, window_y = self.parent.get_parent_window().get_position() + return rect.x + window_x - (width - rect.width), rect.y + window_y - height, True diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/gtk/toolbar.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/gtk/toolbar.py --- tucan-0.3.8/ui/gtk/toolbar.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/gtk/toolbar.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,37 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import pygtk +pygtk.require('2.0') +import gtk + +class Toolbar(gtk.Toolbar): + """""" + def __init__(self, list): + """list = [(tool_name, image, callback),]""" + gtk.Toolbar.__init__(self) + self.set_style(gtk.TOOLBAR_BOTH) + for button in list: + if button == None: + item = gtk.SeparatorToolItem() + else: + item = gtk.ToolButton(button[1], button[0]) + item.connect("clicked", button[2]) + self.insert(item, -1) \ No newline at end of file diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/gtk/tray_icon.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/gtk/tray_icon.py --- tucan-0.3.8/ui/gtk/tray_icon.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/gtk/tray_icon.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,110 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import logging +logger = logging.getLogger(__name__) + +import pygtk +pygtk.require('2.0') +import gtk + +import media +import core.cons as cons + +if cons.OS_OSX: + try: + from igemacintegration import * + except Exception: + pass + else: + class OSXDock(MacDock): + """""" + def __init__(self, show, quit): + """""" + MacDock.__init__(self) + + self.show_window = show + self.window_visible = True + + self.connect("quit-activate", quit) + self.connect("clicked", self.activate) + + def activate(self, statusicon, closed=False): + """""" + if self.window_visible: + if closed: + self.window_visible = False + else: + self.show_window() + self.window_visible = True + + def close(self): + """""" + pass + +class TrayIcon(gtk.StatusIcon): + """""" + def __init__(self, show, hide, menu): + """""" + gtk.StatusIcon.__init__(self) + self.set_tooltip("Tucan Manager - Version: %s" % cons.TUCAN_VERSION) + self.set_from_file(media.ICON_TUCAN) + self.set_visible(True) + + self.window_visible = True + self.show_window = show + self.hide_window = hide + + self.menu = gtk.Menu() + for item in menu: + if item == None: + tmp = gtk.SeparatorMenuItem() + else: + tmp = gtk.ImageMenuItem(item[0]) + tmp.connect('activate', item[1]) + self.menu.append(tmp) + self.menu.show_all() + + self.connect('activate', self.activate) + self.connect('popup-menu', self.popup_menu) + + def activate(self, statusicon, event=None): + """""" + if self.window_visible: + self.hide_window() + self.window_visible = False + else: + self.show_window() + self.window_visible = True + + def popup_menu(self, statusicon, button, time): + """""" + self.menu.popup(None, None, None, button, time, self) + + def change_tooltip(self, statusbar, context, text): + """""" + #if context == "Downloads": + tmp = text.split("\t") + message = "Downloads: " + "".join(tmp[1:]) + "\n" + tmp[0].strip() + self.set_tooltip(message) + + def close(self): + """""" + self.set_visible(False) diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/gtk/tree.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/gtk/tree.py --- tucan-0.3.8/ui/gtk/tree.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/gtk/tree.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,410 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import pygtk +pygtk.require('2.0') +import gtk +import gobject +import pango + +from statusbar import Statusbar + +import core.cons as cons + +class Tree(gtk.VBox): + """""" + def __init__(self, menu, manager): + """""" + gtk.VBox.__init__(self) + scroll = gtk.ScrolledWindow() + scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self.treeview = gtk.TreeView(gtk.TreeStore(gtk.gdk.Pixbuf, str, str, str, int, bool, str, str, str, str, str)) + scroll.add(self.treeview) + self.pack_start(scroll) + + self.menu = gtk.Menu() + for item in menu: + if item == None: + subitem = gtk.SeparatorMenuItem() + else: + subitem = gtk.ImageMenuItem(item[0]) + subitem.connect("activate", item[1]) + self.menu.append(subitem) + self.menu.show_all() + self.treeview.connect("button-press-event", self.mouse_menu) + + self.get_files = manager.get_files + + self.treeview.set_rules_hint(True) + self.treeview.set_headers_visible(False) + + #tree columns + tree_icon = gtk.TreeViewColumn('Icon') + icon_cell = gtk.CellRendererPixbuf() + tree_icon.pack_start(icon_cell, False) + tree_icon.add_attribute(icon_cell, 'pixbuf', 0) + self.treeview.append_column(tree_icon) + + tree_name = gtk.TreeViewColumn('Name') + name_cell = gtk.CellRendererText() + name_cell.set_property("width-chars", 60) + name_cell.set_property("ellipsize", pango.ELLIPSIZE_MIDDLE) + tree_name.pack_start(name_cell, True) + tree_name.add_attribute(name_cell, 'text', 3) + self.treeview.append_column(tree_name) + + tree_progress = gtk.TreeViewColumn('Progress') + tree_progress.set_min_width(150) + progress_cell = gtk.CellRendererProgress() + tree_progress.pack_start(progress_cell, True) + tree_progress.add_attribute(progress_cell, 'value', 4) + tree_progress.add_attribute(progress_cell, 'visible', 5) + self.treeview.append_column(tree_progress) + + tree_current_size = gtk.TreeViewColumn('Current Size') + current_size_cell = gtk.CellRendererText() + tree_current_size.pack_start(current_size_cell, False) + tree_current_size.add_attribute(current_size_cell, 'text', 6) + self.treeview.append_column(tree_current_size) + + tree_total_size = gtk.TreeViewColumn('Total Size') + total_size_cell = gtk.CellRendererText() + tree_total_size.pack_start(total_size_cell, False) + tree_total_size.add_attribute(total_size_cell, 'text', 7) + self.treeview.append_column(tree_total_size) + + tree_speed = gtk.TreeViewColumn('Speed') + speed_cell = gtk.CellRendererText() + tree_speed.pack_start(speed_cell, False) + tree_speed.add_attribute(speed_cell, 'text', 8) + self.treeview.append_column(tree_speed) + + tree_time = gtk.TreeViewColumn('Time Left') + time_cell = gtk.CellRendererText() + tree_time.pack_start(time_cell, False) + tree_time.add_attribute(time_cell, 'text', 9) + self.treeview.append_column(tree_time) + + tree_plugins = gtk.TreeViewColumn('Plugin') + plugins_cell = gtk.CellRendererText() + tree_plugins.pack_start(plugins_cell, False) + tree_plugins.add_attribute(plugins_cell, 'text', 10) + self.treeview.append_column(tree_plugins) + + #icons + self.package_icon = self.treeview.render_icon(gtk.STOCK_OPEN, gtk.ICON_SIZE_MENU) + self.active_service_icon = self.treeview.render_icon(gtk.STOCK_YES, gtk.ICON_SIZE_MENU) + self.unactive_service_icon = self.treeview.render_icon(gtk.STOCK_NO, gtk.ICON_SIZE_MENU) + self.correct_icon = self.treeview.render_icon(gtk.STOCK_APPLY, gtk.ICON_SIZE_MENU) + self.failed_icon = self.treeview.render_icon(gtk.STOCK_CANCEL, gtk.ICON_SIZE_MENU) + self.wait_icon = self.treeview.render_icon(gtk.STOCK_REFRESH, gtk.ICON_SIZE_MENU) + self.active_icon = self.treeview.render_icon(gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_MENU) + self.pending_icon = self.treeview.render_icon(gtk.STOCK_MEDIA_PAUSE, gtk.ICON_SIZE_MENU) + self.stoped_icon = self.treeview.render_icon(gtk.STOCK_MEDIA_STOP, gtk.ICON_SIZE_MENU) + self.icons = {cons.STATUS_CORRECT: self.correct_icon, cons.STATUS_ERROR: self.failed_icon, cons.STATUS_WAIT: self.wait_icon, cons.STATUS_ACTIVE: self.active_icon, cons.STATUS_PEND: self.pending_icon, cons.STATUS_STOP: self.stoped_icon} + + self.status_bar = Statusbar() + self.pack_start(self.status_bar, False) + self.status_bar.push(self.status_bar.get_context_id("Downloads"), " No Downloads Active.") + self.updating = False + + def mouse_menu(self, widget, event): + """right button""" + if event.button == 3: + model, paths = self.treeview.get_selection().get_selected_rows() + if len(paths) > 0: + self.menu.popup(None, None, None, event.button, event.time) + + def add_package(self, package_name, package_path, package, password): + """ + TreeStore(icon, status, password, name, progress, progress_visible, current_size, total_size, speed, time, services) + """ + tmp_size = [] + model = self.treeview.get_model() + package_iter = model.append(None, [self.package_icon, cons.STATUS_PEND, password, package_name, 0, True, None, None, None, None, package_path]) + for item in package: + tmp_size.append((item[3], item[4])) + item_iter = model.append(package_iter, [self.pending_icon, cons.STATUS_PEND, None, item[1], 0, True, None, str(item[3])+item[4], None, None, str(item[2])]) + self.treeview.expand_to_path(model.get_path(item_iter)) + for link in item[0]: + link_iter = model.append(item_iter, [self.unactive_service_icon, cons.STATUS_PEND, None, link, 0, False, None, None, None, None, item[5][item[0].index(link)]]) + package_size, package_unit = self.normalize(tmp_size) + model.set_value(package_iter, 7, str(package_size)+package_unit) + if not self.updating: + self.updating = True + gobject.timeout_add(1000, self.update) + return package_iter + + def update(self): + """(icon, status, None, name, progress, progress_visible, current_size, total_size, speed, time, services)""" + files = self.get_files() + if len(files) > 0: + model = self.treeview.get_model() + package_iter = model.get_iter_root() + active_downloads = 0 + complete_downloads = 0 + total_downloads = 0 + total_speed = 0 + while package_iter: + file_iter = model.iter_children(package_iter) + #package_status = model.set_value(package_iter, 0) + package_progress = 0 + package_speed = 0 + tmp_actual_size = [] + tmp_total_size = [] + while file_iter: + total_downloads += 1 + name = model.get_value(file_iter, 3) + for file in files: + if file.name == name: + model.set_value(file_iter, 0, self.icons[file.status]) + model.set_value(file_iter, 1, file.status) + if file.status in [cons.STATUS_ACTIVE, cons.STATUS_WAIT]: + active_downloads += 1 + elif file.status == cons.STATUS_CORRECT: + complete_downloads += 1 + model.set_value(file_iter, 4, file.progress) + package_progress += file.progress + if file.actual_size > 0: + model.set_value(file_iter, 6, str(file.actual_size)+file.actual_size_unit) + tmp_actual_size.append((file.actual_size, file.actual_size_unit)) + tmp_total_size.append((file.total_size, file.total_size_unit)) + if file.speed > 1: + model.set_value(file_iter, 8, str(file.speed)+cons.UNIT_SPEED) + package_speed += file.speed + elif file.speed == 0: + model.set_value(file_iter, 8, None) + if file.status == cons.STATUS_CORRECT: + if not file.time > 0: + file.time = 1 + file.actual_size = file.total_size + file.actual_size_unit = file.total_size_unit + model.set_value(file_iter, 9, self.calculate_time(file.time)) + link_iter = model.iter_children(file_iter) + while link_iter: + for tmp_link in file.links: + if tmp_link.url == model.get_value(link_iter, 3): + service_icon = self.unactive_service_icon + link_status = cons.STATUS_STOP + if tmp_link.active: + service_icon = self.active_service_icon + link_status = cons.STATUS_ACTIVE + model.set_value(link_iter, 0, service_icon) + model.set_value(link_iter, 1, link_status) + link_iter = model.iter_next(link_iter) + file_iter = model.iter_next(file_iter) + package_actual_size, package_actual_unit = self.normalize(tmp_actual_size) + package_total_size, package_total_unit = self.normalize(tmp_total_size) + if package_actual_size > 0: + if int(package_progress/model.iter_n_children(package_iter)) == 100: + model.set_value(package_iter, 4, 100) + else: + model.set_value(package_iter, 4, int((float(self.get_size(package_actual_size, package_actual_unit))/float(self.get_size(package_total_size, package_total_unit)))*100)) + model.set_value(package_iter, 6, str(package_actual_size)+package_actual_unit) + if package_speed > 0: + model.set_value(package_iter, 8, str(package_speed)+cons.UNIT_SPEED) + else: + model.set_value(package_iter, 8, None) + total_speed += package_speed + package_iter = model.iter_next(package_iter) + self.status_bar.pop(self.status_bar.get_context_id("Downloads")) + self.status_bar.push(self.status_bar.get_context_id("Downloads"), " Downstream %dKB/s \tTotal %d \t Complete %d \t Active %d" % (total_speed, total_downloads, complete_downloads, active_downloads)) + return True + + def normalize(self, sizes): + """""" + total = 0 + total_unit = cons.UNIT_KB + for size, unit in sizes: + total += self.get_size(size, unit) + tmp = int(total/1024) + if tmp > 0: + total = tmp + total_unit = cons.UNIT_MB + tmp = int(tmp/1024) + # if tmp > 0: + # total = tmp + # total_unit = cons.UNIT_GB + return total, total_unit + + def get_size(self, size, unit): + """""" + if unit == cons.UNIT_KB: + return size + elif unit == cons.UNIT_MB: + return size*1024 + #elif unit == cons.UNIT_GB: + # return size*1024*1024 + + def get_packages(self): + """""" + model = self.treeview.get_model() + package_iter = model.get_iter_root() + packages = [] + info = [] + while package_iter: + files = [] + file_iter = model.iter_children(package_iter) + while file_iter: + if model.get_value(file_iter, 1) != cons.STATUS_CORRECT: + links = [] + plugins = [] + link_iter = model.iter_children(file_iter) + while link_iter: + links.append(model.get_value(link_iter, 3)) + plugins.append(model.get_value(link_iter, 10)) + link_iter = model.iter_next(link_iter) + name = model.get_value(file_iter, 3) + tmp = model.get_value(file_iter, 7) + for unit in [cons.UNIT_KB, cons.UNIT_MB]: + tmp_size = tmp.split(unit) + if len(tmp_size) > 1: + size_unit = unit + size = int(tmp_size[0]) + break + tmp = model.get_value(file_iter, 10) + tmp = tmp.split(",") + service_list = [] + for service in tmp: + service_list.append(service.split("\'")[1]) + files.append((links, name, service_list, size, size_unit, plugins)) + file_iter = model.iter_next(file_iter) + if len(files) > 0: + name = model.get_value(package_iter, 3) + packages.append((name, files)) + path = model.get_value(package_iter, 10).split(name)[0] + info.append((path, name, model.get_value(package_iter, 2))) + package_iter = model.iter_next(package_iter) + return packages, info + + def get_links(self, iter): + """""" + links = [] + model = self.treeview.get_model() + file_iter = model.iter_children(iter) + if not file_iter: + links.append(model.get_value(iter, 3)) + while file_iter: + link_iter = model.iter_children(file_iter) + if not link_iter: + links.append(model.get_value(file_iter, 3)) + while link_iter: + links.append(model.get_value(link_iter, 3)) + link_iter = model.iter_next(link_iter) + file_iter = model.iter_next(file_iter) + return links + + def package_files(self, package_iter): + """""" + files = [] + model = self.treeview.get_model() + file_iter = model.iter_children(package_iter) + while file_iter: + if model.get_value(file_iter, 1) not in [cons.STATUS_ACTIVE, cons.STATUS_WAIT, cons.STATUS_CORRECT]: + files.append(model.get_value(file_iter, 3)) + file_iter = model.iter_next(file_iter) + return files + + def clear(self): + """""" + files = [] + model = self.treeview.get_model() + package_iter = model.get_iter_root() + while package_iter: + tmp_iter = package_iter + package_iter = model.iter_next(package_iter) + files += self.delete_package([cons.STATUS_CORRECT], tmp_iter) + return files + + def delete_package(self, status, package_iter): + """""" + tmp = [] + model = self.treeview.get_model() + file_iter = model.iter_children(package_iter) + while file_iter: + if model.get_value(file_iter, 1) in status: + tmp.append(model.get_value(file_iter, 3)) + file_iter = model.iter_next(file_iter) + if len(tmp) == model.iter_n_children(package_iter): + model.remove(package_iter) + else: + tmp = [] + return tmp + + def delete_file(self, status, iter): + """""" + model = self.treeview.get_model() + if model.get_value(iter, 1) in status: + if model.iter_n_children(model.iter_parent(iter)) > 1: + result = model.get_value(iter, 3) + model.remove(iter) + return result + + def delete_link(self, status, iter): + """""" + result = None, None + model = self.treeview.get_model() + file_iter = model.iter_parent(iter) + if model.iter_n_children(file_iter) > 1: + if model.get_value(iter, 1) == cons.STATUS_STOP: + result = model.get_value(file_iter, 3), model.get_value(iter, 3) + model.remove(iter) + return result + + def move_up(self, iter): + """""" + model = self.treeview.get_model() + package_iter = model.iter_parent(iter) + file_iter = model.iter_children(package_iter) + prev_iter = None + while ((file_iter) and (model.get_path(file_iter) != model.get_path(iter))): + prev_iter = file_iter + file_iter = model.iter_next(file_iter) + if prev_iter: + model.move_before(iter, prev_iter) + return True + + def move_down(self, iter): + """""" + model = self.treeview.get_model() + next_iter = model.iter_next(iter) + if next_iter: + model.move_after(iter, next_iter) + return True + + def calculate_time(self, time): + """""" + result = None + hours = 0 + minutes = 0 + while time >= cons.HOUR: + time = time - cons.HOUR + hours += 1 + while time >= cons.MINUTE: + time = time - cons.MINUTE + minutes += 1 + seconds = time + if hours > 0: + result = str(hours) + "h" + str(minutes) + "m" + str(seconds) + "s" + elif minutes > 0: + result = str(minutes) + "m" + str(seconds) + "s" + elif seconds > 0: + result = str(seconds) + "s" + return result diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/ui/gtk/update_manager.py /tmp/DgSymrsclJ/tucan-0.3.9/ui/gtk/update_manager.py --- tucan-0.3.8/ui/gtk/update_manager.py 1970-01-01 01:00:00.000000000 +0100 +++ tucan-0.3.9/ui/gtk/update_manager.py 2009-10-07 00:02:28.000000000 +0100 @@ -0,0 +1,211 @@ +############################################################################### +## Tucan Project +## +## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com +## +## 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, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################### + +import threading + +import pygtk +pygtk.require('2.0') +import gtk +import gobject + +from message import Message +from core.service_update import ServiceUpdate + +import media +import core.cons as cons + +class UpdateManager(gtk.Dialog, ServiceUpdate): + """""" + def __init__(self, parent, config, info=None): + """""" + gtk.Dialog.__init__(self) + ServiceUpdate.__init__(self, config) + self.set_transient_for(parent) + self.parent_widget = parent + + self.installing = False + self.remote_info = info + + self.set_icon_from_file(media.ICON_UPDATE) + self.set_title(("Update Manager")) + self.set_size_request(400,300) + + # treeview + frame = gtk.Frame() + self.vbox.pack_start(frame) + frame.set_size_request(200, -1) + frame.set_border_width(10) + label = gtk.Label() + label.set_markup("%s" % ("Update Services")) + frame.set_label_widget(label) + scroll = gtk.ScrolledWindow() + frame.add(scroll) + scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self.treeview = gtk.TreeView(gtk.ListStore(gtk.gdk.Pixbuf, str, bool, str, gobject.TYPE_PYOBJECT)) + scroll.add(self.treeview) + + self.treeview.set_rules_hint(True) + self.treeview.set_headers_visible(False) + + tree_icon = gtk.TreeViewColumn('Icon') + icon_cell = gtk.CellRendererPixbuf() + tree_icon.pack_start(icon_cell, True) + tree_icon.add_attribute(icon_cell, 'pixbuf', 0) + tree_icon.set_property('min-width', 100) + self.treeview.append_column(tree_icon) + + tree_name = gtk.TreeViewColumn('Name') + name_cell = gtk.CellRendererText() + tree_name.pack_start(name_cell, True) + tree_name.add_attribute(name_cell, 'text', 1) + tree_name.set_property('min-width', 200) + self.treeview.append_column(tree_name) + + tree_add = gtk.TreeViewColumn('Add') + add_cell = gtk.CellRendererToggle() + add_cell.connect("toggled", self.toggled) + tree_add.pack_start(add_cell, True) + tree_add.add_attribute(add_cell, 'active', 2) + self.treeview.append_column(tree_add) + + #status + hbox = gtk.HBox() + self.vbox.pack_start(hbox, False, False, 5) + + self.status_icon = gtk.image_new_from_stock(gtk.STOCK_REFRESH, gtk.ICON_SIZE_MENU) + hbox.pack_start(self.status_icon, False, False, 10) + self.status_label = gtk.Label("Checking for updates.") + hbox.pack_start(self.status_label, False, False, 5) + self.progress = gtk.ProgressBar() + hbox.pack_start(self.progress, True, True, 20) + + #action area + cancel_button = gtk.Button(None, gtk.STOCK_CANCEL) + add_button = gtk.Button(None, gtk.STOCK_ADD) + self.action_area.pack_start(cancel_button) + self.action_area.pack_start(add_button) + cancel_button.connect("clicked", self.close) + add_button.connect("clicked", self.install) + + self.connect("response", self.close) + self.show_all() + + self.progress.hide() + + gobject.timeout_add(200, self.check_version) + + self.run() + + def check_version(self): + """""" + self.get_updates() + if self.remote_version == None: + message = "Update Manager can't connect to server.\nTry again later." + Message(self, cons.SEVERITY_ERROR, "Tucan Manager - Not available!", message) + gobject.idle_add(self.close) + elif self.remote_version.split(" ")[0] <= cons.TUCAN_VERSION.split(" ")[0]: + self.check_updates() + else: + message = "Version %s released!\nPlease update and enjoy new services." % self.server_version + Message(self, cons.SEVERITY_ERROR, "Tucan Manager - Outdated!", message) + gobject.idle_add(self.close) + + def toggled(self, button, path): + """""" + model = self.treeview.get_model() + active = True + if button.get_active(): + active = False + button.set_active(active) + model.set_value(model.get_iter(path), 2, active) + + def check_updates(self): + """""" + model = self.treeview.get_model() + default_icon = gtk.gdk.pixbuf_new_from_file_at_size(media.ICON_UPDATE, 32, 32) + + updated = 0 + new = 0 + for service, options in self.updates.items(): + if options[2]: + icon = gtk.gdk.pixbuf_new_from_file_at_size(options[2], 32, 32) + updated += 1 + else: + icon = default_icon + new += 1 + if model: + model.append([icon, service, False, options[0], options[1]]) + + self.status_icon.set_from_stock(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_BUTTON) + self.status_label.set_label("%i New and %i Updated." % (new, updated)) + if updated == 0 and new == 0: + gobject.timeout_add(5000, self.close) + + def install(self, button): + """""" + self.progress.show() + self.status_icon.set_from_stock(gtk.STOCK_GO_DOWN, gtk.ICON_SIZE_MENU) + self.status_label.set_label("Installing") + self.action_area.set_sensitive(False) + th = threading.Thread(group=None, target=self.install_all, name=None) + th.start() + + def install_all(self): + """""" + self.installing = True + model = self.treeview.get_model() + + install_targets = [] + update_iter = model.get_iter_root() + while update_iter: + if model.get_value(update_iter, 2): + install_targets.append(model.get(update_iter, 1, 3, 4)) + update_iter = model.iter_next(update_iter) + if len(install_targets) > 0: + cont = 0 + self.progress.set_text("%i of %i" % (cont, len(install_targets))) + for service_name, service_dir, archive in install_targets: + if self.install_service(service_name, service_dir, archive): + cont += 1 + self.progress.set_fraction(float(cont)/len(install_targets)) + self.progress.set_text("%i of %i" % (cont, len(install_targets))) + if cont != len(install_targets): + message = "Problem updating some services \nTry again later." + else: + message = "Save your configuration and restart Tucan \nto apply service changes." + gobject.idle_add(self.restart, message) + self.installing = False + gobject.idle_add(self.close) + else: + self.installing = False + gobject.idle_add(self.close) + + def restart(self, message): + """""" + Message(self.parent_widget, cons.SEVERITY_WARNING, "Tucan Manager - Restart Needed.", message) + + def close(self, widget=None, other=None): + """""" + if not self.installing: + self.destroy() + +if __name__ == "__main__": + from config import Config + x = UpdateManager(None, Config(), None) diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/update_manager.py /tmp/DgSymrsclJ/tucan-0.3.9/update_manager.py --- tucan-0.3.8/update_manager.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/update_manager.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,189 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import pygtk -pygtk.require('2.0') -import gtk -import gobject - -from service_update import ServiceUpdate -from message import Message - -import cons - -class UpdateManager(gtk.Dialog, ServiceUpdate): - """""" - def __init__(self, config, parent, updates=None): - """""" - gtk.Dialog.__init__(self) - ServiceUpdate.__init__(self, config) - self.set_transient_for(parent) - - self.set_icon_from_file(cons.ICON_UPDATE) - self.set_title(("Update Manager")) - self.set_size_request(400,300) - - # treeview - frame = gtk.Frame() - self.vbox.pack_start(frame) - frame.set_size_request(200, -1) - frame.set_border_width(10) - label = gtk.Label() - label.set_markup("%s" % ("Update Services")) - frame.set_label_widget(label) - scroll = gtk.ScrolledWindow() - frame.add(scroll) - scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self.treeview = gtk.TreeView(gtk.ListStore(gtk.gdk.Pixbuf, str, bool, str, gobject.TYPE_PYOBJECT)) - scroll.add(self.treeview) - - self.treeview.set_rules_hint(True) - self.treeview.set_headers_visible(False) - - tree_icon = gtk.TreeViewColumn('Icon') - icon_cell = gtk.CellRendererPixbuf() - tree_icon.pack_start(icon_cell, True) - tree_icon.add_attribute(icon_cell, 'pixbuf', 0) - tree_icon.set_property('min-width', 100) - self.treeview.append_column(tree_icon) - - tree_name = gtk.TreeViewColumn('Name') - name_cell = gtk.CellRendererText() - tree_name.pack_start(name_cell, True) - tree_name.add_attribute(name_cell, 'text', 1) - tree_name.set_property('min-width', 200) - self.treeview.append_column(tree_name) - - tree_add = gtk.TreeViewColumn('Add') - add_cell = gtk.CellRendererToggle() - add_cell.connect("toggled", self.toggled) - tree_add.pack_start(add_cell, True) - tree_add.add_attribute(add_cell, 'active', 2) - self.treeview.append_column(tree_add) - - #status - hbox = gtk.HBox() - self.vbox.pack_start(hbox, False, False, 5) - - self.status_icon = gtk.image_new_from_stock(gtk.STOCK_REFRESH, gtk.ICON_SIZE_MENU) - hbox.pack_start(self.status_icon, False, False, 10) - self.status_label = gtk.Label("Checking for updates.") - hbox.pack_start(self.status_label, False, False, 5) - self.progress = gtk.ProgressBar() - hbox.pack_start(self.progress, True, True, 20) - - #action area - cancel_button = gtk.Button(None, gtk.STOCK_CANCEL) - add_button = gtk.Button(None, gtk.STOCK_ADD) - self.action_area.pack_start(cancel_button) - self.action_area.pack_start(add_button) - cancel_button.connect("clicked", self.close) - add_button.connect("clicked", self.install) - - self.connect("response", self.close) - self.show_all() - - self.progress.hide() - - if self.server_version.split(" ")[0] <= cons.TUCAN_VERSION.split(" ")[0]: - gobject.timeout_add(1000, self.check_updates, updates) - elif self.server_version == None: - message = "Update Manager can't connect to server.\nTry again later." - Message(self, cons.SEVERITY_ERROR, "Tucan Manager - Not available!", message) - gobject.idle_add(self.close) - else: - message = "Version %s released!\nPlease update and enjoy new services." % self.server_version - Message(self, cons.SEVERITY_ERROR, "Tucan Manager - Outdated!", message) - gobject.idle_add(self.close) - self.run() - - def toggled(self, button, path): - """""" - model = self.treeview.get_model() - active = True - if button.get_active(): - active = False - button.set_active(active) - model.set_value(model.get_iter(path), 2, active) - - def check_updates(self, updates=None): - """""" - model = self.treeview.get_model() - default_icon = gtk.gdk.pixbuf_new_from_file_at_size(cons.ICON_UPDATE, 32, 32) - - updated = 0 - new = 0 - if not updates: - updates = self.get_updates() - for service, options in updates.items(): - if options[2]: - icon = gtk.gdk.pixbuf_new_from_file_at_size(options[2], 32, 32) - updated += 1 - else: - icon = default_icon - new += 1 - if model: - model.append([icon, service, False, options[0], options[1]]) - - self.status_icon.set_from_stock(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_BUTTON) - self.status_label.set_label("%i New and %i Updated." % (new, updated)) - if updated == 0 and new == 0: - gobject.timeout_add(5000, self.close) - - def install(self, button): - """""" - model = self.treeview.get_model() - - self.status_icon.set_from_stock(gtk.STOCK_GO_DOWN, gtk.ICON_SIZE_MENU) - self.status_label.set_label("Installing") - self.progress.show() - - install_targets = [] - update_iter = model.get_iter_root() - while update_iter: - if model.get_value(update_iter, 2): - install_targets.append(model.get(update_iter, 1, 3, 4)) - update_iter = model.iter_next(update_iter) - if len(install_targets) > 0: - self.progress.grab_add() - cont = 0.0 - for service_name, service_dir, file_list in install_targets: - self.progress.set_text("%i of %i" % (int(cont), len(install_targets))) - #unfreezes widget - while gtk.events_pending(): - gtk.main_iteration_do(False) - self.install_service(service_name, service_dir, file_list) - cont += 1 - self.progress.set_fraction(cont/len(install_targets)) - self.progress.set_text("%i of %i" % (int(cont), len(install_targets))) - self.hide() - message = "Save your configuration and restart Tucan \nto apply service changes." - Message(self, cons.SEVERITY_WARNING, "Tucan Manager - Restart Needed.", message) - self.close() - else: - self.close() - - def close(self, widget=None, other=None): - """""" - self.destroy() - -if __name__ == "__main__": - from config import Config - x = UpdateManager(Config(), None) diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/uploader.py /tmp/DgSymrsclJ/tucan-0.3.9/uploader.py --- tucan-0.3.8/uploader.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/uploader.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,42 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -""" -import MultipartPostHandler, urllib2, cookielib - -cookies = cookielib.CookieJar() -opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookies), MultipartPostHandler.MultipartPostHandler) -params = { "username" : "bob", "password" : "riviera", "file" : open("filename", "rb") } -opener.open("http://wwww.bobsite.com/upload/", params) -""" - -import urllib -import urllib2 - -from HTMLParser import HTMLParser - -class Uploader(HTMLParser): - """""" - def __init__(self, file_name): - """""" - HTMLParser.__init__(self) - -if __name__ == "__main__": - c = Uploader("/home/crak/mierda.html") diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/url_open.py /tmp/DgSymrsclJ/tucan-0.3.9/url_open.py --- tucan-0.3.8/url_open.py 2009-07-15 01:15:18.000000000 +0100 +++ tucan-0.3.9/url_open.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,62 +0,0 @@ -############################################################################### -## Tucan Project -## -## Copyright (C) 2008-2009 Fran Lupion crak@tucaneando.com -## -## 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, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################### - -import __builtin__ - -import urllib2 -import logging -logger = logging.getLogger(__name__) - -import socket - -import cons - -def set_proxy(url, port=0): - """""" - if url: - PROXY = {"http": "%s:%i" % (url, port)} - socket.setdefaulttimeout(60) - logger.info("Using proxy: %s:%i" % (url, port)) - else: - PROXY = None - socket.setdefaulttimeout(120) - logger.info("Proxy Disabled.") - __builtin__.PROXY = PROXY - -class URLOpen: - """""" - def __init__(self, cookie=None): - """""" - if PROXY: - self.opener = urllib2.build_opener(urllib2.ProxyHandler(PROXY), urllib2.HTTPCookieProcessor(cookie)) - else: - self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie)) - - def open(self, url, form=None): - """""" - if form: - return self.opener.open(urllib2.Request(url, None, cons.USER_AGENT), form) - else: - return self.opener.open(urllib2.Request(url, None, cons.USER_AGENT)) - -if __name__ == "__main__": - PROXY = {"http": "proxy.alu.uma.es:3128"} - o = URLOpen() - print o.open("http://www.google.com").read() diff -Nru /tmp/Mj7pJvsoYS/tucan-0.3.8/VERSION /tmp/DgSymrsclJ/tucan-0.3.9/VERSION --- tucan-0.3.8/VERSION 2009-07-15 01:15:19.000000000 +0100 +++ tucan-0.3.9/VERSION 2009-10-07 00:02:33.000000000 +0100 @@ -1,2 +1,2 @@ -0.3.8 -rev 992 +0.3.9 +rev 1251