def update_profile(self, username, password, cookie, tokens, dump=False): if not self.profile: self.profile = gutil.load_profile(username) self.profile['username'] = username self.profile['remember-password'] = self.remember_check.get_active() self.profile['auto-signin'] = self.signin_check.get_active() if self.profile['remember-password']: self.profile['password'] = password else: self.profile['password'] = '' gutil.dump_profile(self.profile) if username not in self.conf['profiles']: self.conf['profiles'].append(username) if self.profile['auto-signin']: self.conf['default'] = username Config.dump_conf(self.conf) self.app.cookie = cookie self.app.tokens = tokens # dump auth info if dump: self.dump_auth(username, cookie, tokens) self.app.profile = self.profile self.app.window.set_default_size(*self.profile['window-size']) self.hide()
def signin(self): username = self.username_combo.get_child().get_text() password = self.password_entry.get_text() cookie, tokens = auth.get_auth_info(username, password) print('cookie:', cookie) print('tokens:', tokens) if cookie and tokens: if not self.profile: self.profile = Config.load_profile(username) self.profile['username'] = username self.profile['remember-password'] = self.remember_check.get_active() self.profile['auto-signin'] = self.signin_check.get_active() if self.profile['remember-password']: self.profile['password'] = password else: self.profile['password'] = '' Config.dump_profile(self.profile) if username not in self.conf['profiles']: self.conf['profiles'].append(username) if self.profile['auto-signin']: self.conf['default'] = username Config.dump_conf(self.conf) self.app.cookie = cookie self.app.tokens = tokens self.app.profile = self.profile self.app.window.set_default_size(*self.profile['window-size']) self.destroy() else: self.infobar.show_all()
def update_profile(self, username, password, cookie, tokens, dump=False): if not self.profile: self.profile = gutil.load_profile(username) self.profile["username"] = username self.profile["remember-password"] = self.remember_check.get_active() self.profile["auto-signin"] = self.signin_check.get_active() if self.profile["remember-password"]: self.profile["password"] = password else: self.profile["password"] = "" gutil.dump_profile(self.profile) if username not in self.conf["profiles"]: self.conf["profiles"].append(username) if self.profile["auto-signin"]: self.conf["default"] = username Config.dump_conf(self.conf) self.app.cookie = cookie self.app.tokens = tokens # dump auth info if dump: self.dump_auth(username, cookie, tokens) self.app.profile = self.profile self.app.window.set_default_size(*self.profile["window-size"]) self.hide()
def display_files(self, pcs_files): '''重新格式化一下文件列表, 去除不需要的信息 这一操作主要是为了便于接下来的查找工作. 文件的path都被提取出来, 然后放到了一个list中. ''' tree_iters = [] for pcs_file in pcs_files: path = pcs_file['path'] pixbuf, type_ = self.app.mime.get(path, pcs_file['isdir'], icon_size=self.ICON_SIZE) name = os.path.split(path)[NAME_COL] tooltip = gutil.escape(name) size = pcs_file.get('size', 0) if pcs_file['isdir']: human_size = '--' else: human_size = util.get_human_size(pcs_file['size'])[0] mtime = pcs_file.get('server_mtime', 0) human_mtime = time.ctime(mtime) tree_iter = self.liststore.append([ pixbuf, name, path, tooltip, size, human_size, pcs_file['isdir'], mtime, human_mtime, type_, json.dumps(pcs_file) ]) tree_iters.append(tree_iter) cache_path = Config.get_cache_path(self.app.profile['username']) gutil.async_call(gutil.update_liststore_image, self.liststore, tree_iters, PIXBUF_COL, pcs_files, cache_path, self.ICON_SIZE)
def display_filelist(self, filelist): '''重新格式化一下文件列表, 去除不需要的信息 这一操作主要是为了便于接下来的查找工作. 文件的path都被提取出来, 然后放到了一个list中. ''' if not filelist or filelist['errno'] != 0: return if 'list' in filelist: key = 'list' elif 'info' in filelist: key = 'info' else: print('Error: current filelist format not supported!') print(filelist) return cache_path = Config.get_cache_path(self.app.profile['username']) for pcs_file in filelist[key]: path = pcs_file['path'] self.filelist.append(pcs_file) self.pathlist.append(path) pixbuf, type_ = self.app.mime.get(path, pcs_file['isdir']) disname = os.path.split(path)[DISNAME_COL] #tooltip = gutil.escape(disname) tooltip = disname tree_iter = self.liststore.append([ pixbuf, disname, path, tooltip, type_ ]) gutil.update_liststore_image( self.liststore, tree_iter, PIXBUF_COL, pcs_file, cache_path, )
def update_img(self, req_data, error=None): if error or not req_data: return vcode_path = os.path.join(Config.get_tmp_path(self.form['username']), 'bcloud-signin-vcode') with open(vcode_path, 'wb') as fh: fh.write(req_data) self.vcode_img.set_from_file(vcode_path)
def __init__(self, app, auto_signin=True): super().__init__( _('Sign in now'), app.window, Gtk.DialogFlags.MODAL) self.app = app self.auto_signin = auto_signin self.set_default_size(460, 260) self.set_border_width(15) self.conf = Config.load_conf() self.profile = None box = self.get_content_area() box.set_spacing(8) username_ls = Gtk.ListStore(str) for username in self.conf['profiles']: username_ls.append([username,]) self.username_combo = Gtk.ComboBox.new_with_entry() self.username_combo.set_model(username_ls) self.username_combo.set_entry_text_column(0) self.username_combo.set_tooltip_text(_('Username/Email/Phone...')) box.pack_start(self.username_combo, False, False, 0) self.username_combo.connect('changed', self.on_username_changed) self.password_entry = Gtk.Entry() self.password_entry.set_placeholder_text(_('Password ..')) self.password_entry.props.visibility = False box.pack_start(self.password_entry, False, False, 0) self.remember_check = Gtk.CheckButton(_('Remember Password')) self.remember_check.props.margin_top = 20 self.remember_check.props.margin_left = 20 box.pack_start(self.remember_check, False, False, 0) self.remember_check.connect('toggled', self.on_remember_check_toggled) self.signin_check = Gtk.CheckButton(_('Signin Automatically')) self.signin_check.set_sensitive(False) self.signin_check.props.margin_left = 20 box.pack_start(self.signin_check, False, False, 0) self.signin_check.connect('toggled', self.on_signin_check_toggled) signin_button = Gtk.Button(_('Sign in')) signin_button.props.margin_top = 10 box.pack_start(signin_button, False, False, 0) signin_button.connect('clicked', self.on_signin_button_clicked) self.infobar = Gtk.InfoBar() self.infobar.set_message_type(Gtk.MessageType.ERROR) box.pack_end(self.infobar, False, False, 0) info_content = self.infobar.get_content_area() info_label = Gtk.Label(_('Failed to sign in, please try again.')) info_content.pack_start(info_label, False, False, 0) box.show_all() self.infobar.hide() GLib.timeout_add(500, self.load_defualt_profile)
def load_auth(self, username): auth_file = os.path.join(Config.get_tmp_path(username), 'auth.json') if os.path.exists(auth_file): if time.time() - os.stat(auth_file).st_mtime < DELTA: with open(auth_file) as fh: c, tokens = json.load(fh) cookie = RequestCookie(c) return cookie, tokens return None, None
def load_auth(self, username): auth_file = Config.check_auth_file(username) # 如果缓存授权信息没过期, 就直接读取它. if auth_file: if time.time() - os.stat(auth_file).st_mtime < DELTA: with open(auth_file) as fh: c, tokens = json.load(fh) cookie = RequestCookie(c) return cookie, tokens return None, None
def update_img(self, request, error=None): if error or not request: # TODO: add a refresh button return vcode_path = os.path.join( Config.get_tmp_path(self.app.profile['username']), 'bcloud-download-vcode.jpg') with open(vcode_path, 'wb') as fh: fh.write(request.data) self.img.set_from_file(vcode_path)
def on_load_url(filelist, error=None): self.url_entry.props.secondary_icon_name = REFRESH_ICON if timestamp != self.url_entry.timestamp: logger.debug("SharePage.load_url, dirname not match, ignored") return if error or not filelist: self.app.toast(_("Failed to get files, please reload this page")) logger.warn("SharePage.load_url: %s, %s, %s" % (self.curr_url, filelist, error)) self.has_next = False return state = self.select_all_button.get_active() tree_iters = [] # 插入.. 点击后返回上个目录 if filelist and self.dirname and self.dirname != "/": parent_dirname = os.path.dirname(self.dirname) pixbuf, type_ = self.app.mime.get(parent_dirname, True, icon_size=ICON_SIZE) large_pixbuf, type_ = self.app.mime.get(parent_dirname, True, icon_size=LARGE_ICON_SIZE) self.liststore.append([state, pixbuf, large_pixbuf, "..", parent_dirname, True, 0, "0", 0, ""]) for file_ in filelist: isdir = file_["isdir"] == "1" pixbuf, type_ = self.app.mime.get(file_["path"], isdir, icon_size=ICON_SIZE) large_pixbuf, type_ = self.app.mime.get(file_["path"], isdir, icon_size=LARGE_ICON_SIZE) size = int(file_.get("size", 0)) human_size = util.get_human_size(size)[0] mtime = int(file_.get("server_mtime", 0)) human_mtime = time.ctime(mtime) tree_iter = self.liststore.append( [ state, pixbuf, large_pixbuf, file_["server_filename"], file_["path"], isdir, size, human_size, mtime, human_mtime, ] ) tree_iters.append(tree_iter) cache_path = Config.get_cache_path(self.app.profile["username"]) gutil.async_call( gutil.update_share_image, self.liststore, tree_iters, ICON_COL, LARGE_ICON_COL, filelist, cache_path, ICON_SIZE, LARGE_ICON_SIZE, )
def update_avatar(self): '''更新用户头像''' def do_update_avatar(img_path, error=None): if error or not img_path: logger.error('Failed to get user avatar: %s, %s' % (img_path, error)) else: self.img_avatar.set_from_file(img_path) cache_path = Config.get_cache_path(self.profile['username']) self.img_avatar.props.tooltip_text = self.profile['username'] gutil.async_call(gutil.update_avatar, self.cookie, cache_path, callback=do_update_avatar)
def update_img(self, req_data, error=None): if error or not req_data: self.refresh_vcode() logger.error("SigninDialog.update_img: %s, %s" % (req_data, error)) return vcode_path = os.path.join(Config.get_tmp_path(self.username), "bcloud-signin-vcode.jpg") with open(vcode_path, "wb") as fh: fh.write(req_data) self.vcode_img.set_from_file(vcode_path) self.loading_spin.stop() self.loading_spin.hide() self.vcode_entry.set_sensitive(True)
def use_profile(self, username): model = self.username_combo.get_model() for row in model: if row[0] == username: self.username_combo.set_active_iter(row.iter) break self.profile = Config.load_profile(username) self.password_entry.set_text(self.profile['password']) self.remember_check.set_active(self.profile['remember-password']) if self.profile['remember-password']: self.signin_check.set_active(self.profile['auto-signin']) else: self.signin_check.set_active(False)
def update_img(self, req_data, error=None): if error or not req_data: self.refresh_vcode() logger.error('SigninDialog.update_img: %s, %s' % (req_data, error)) return vcode_path = os.path.join(Config.get_tmp_path(self.username), 'bcloud-signin-vcode.jpg') with open(vcode_path, 'wb') as fh: fh.write(req_data) self.vcode_img.set_from_file(vcode_path) self.loading_spin.stop() self.loading_spin.hide() self.vcode_entry.set_sensitive(True)
def display_files(self, pcs_files): '''重新格式化一下文件列表, 去除不需要的信息 这一操作主要是为了便于接下来的查找工作. 文件的path都被提取出来, 然后放到了一个list中. ''' tree_iters = [] md5Dict = {} for pcs_file in pcs_files: md5 = pcs_file.get('md5', "") if md5 in md5Dict: md5Dict[md5] += 1 else: md5Dict[md5] = 1 for pcs_file in pcs_files: path = pcs_file['path'] pixbuf, type_ = self.app.mime.get(path, pcs_file['isdir'], icon_size=self.ICON_SIZE) name = os.path.split(path)[NAME_COL] tooltip = gutil.escape(name) size = pcs_file.get('size', 0) md5 = pcs_file.get('md5', "") if pcs_file['isdir']: human_size = '--' foregroundColor = "#3a5d96" count = 0 else: human_size = util.get_human_size(pcs_file['size'])[0] count = md5Dict[md5] if count > 1: foregroundColor = "#ff5050" else: foregroundColor = "#2e2e2e" mtime = pcs_file.get('server_mtime', 0) human_mtime = time.ctime(mtime) fid = pcs_file.get('fs_id', 0) tree_iter = self.liststore.append([ pixbuf, name, path, tooltip, size, human_size, pcs_file['isdir'], mtime, human_mtime, type_, json.dumps(pcs_file), fid, md5, foregroundColor, count ]) tree_iters.append(tree_iter) cache_path = Config.get_cache_path(self.app.profile['username']) gutil.async_call(gutil.update_liststore_image, self.liststore, tree_iters, PIXBUF_COL, pcs_files, cache_path, self.ICON_SIZE)
def update_avatar(self): """更新用户头像""" def do_update_avatar(info, error=None): if error or not info: logger.error("Failed to get user avatar: %s, %s" % (info, error)) else: uk, uname, img_path = info self.img_avatar.set_from_file(img_path) self.img_avatar.props.tooltip_text = "\n".join([self.profile["username"], uname]) if not self.profile["display-avatar"]: return self.img_avatar.props.tooltip_text = "" cache_path = Config.get_cache_path(self.profile["username"]) gutil.async_call(gutil.update_avatar, self.cookie, self.tokens, cache_path, callback=do_update_avatar)
def update_avatar(self): '''更新用户头像''' def do_update_avatar(info, error=None): if error or not info: logger.error('Failed to get user avatar: %s, %s' % (info, error)) else: uk, uname, img_path = info self.img_avatar.set_from_file(img_path) self.img_avatar.props.tooltip_text = '\n'.join([ self.profile['username'], uname, ]) self.img_avatar.props.tooltip_text = '' cache_path = Config.get_cache_path(self.profile['username']) gutil.async_call(gutil.update_avatar, self.cookie, self.tokens, cache_path, callback=do_update_avatar)
def dump_auth(self, username, cookie, tokens): auth_file = os.path.join(Config.get_tmp_path(username), 'auth.json') with open(auth_file, 'w') as fh: json.dump([str(cookie), tokens], fh)
def on_app_startup(self, app): GLib.set_application_name(Config.APPNAME) self.icon_theme = Gtk.IconTheme.get_default() self.icon_theme.append_search_path(Config.ICON_PATH) self.mime = MimeProvider(self) self.color_schema = Config.load_color_schema() self.set_dark_theme(True) self.window = Gtk.ApplicationWindow.new(application=app) self.window.set_default_size(*gutil.DEFAULT_PROFILE['window-size']) self.window.set_default_icon_name(Config.NAME) self.window.props.window_position = Gtk.WindowPosition.CENTER self.window.props.hide_titlebar_when_maximized = True self.window.connect('check-resize', self.on_main_window_resized) self.window.connect('delete-event', self.on_main_window_deleted) app.add_window(self.window) self.window.drag_dest_set(Gtk.DestDefaults.ALL, DROP_TARGET_LIST, Gdk.DragAction.COPY) self.window.connect('drag-data-received', self.on_main_window_drag_data_received) app_menu = Gio.Menu.new() app_menu.append(_('Preferences'), 'app.preferences') app_menu.append(_('Sign out'), 'app.signout') app_menu.append(_('About'), 'app.about') app_menu.append(_('Quit'), 'app.quit') app.set_app_menu(app_menu) preferences_action = Gio.SimpleAction.new('preferences', None) preferences_action.connect('activate', self.on_preferences_action_activated) app.add_action(preferences_action) signout_action = Gio.SimpleAction.new('signout', None) signout_action.connect('activate', self.on_signout_action_activated) app.add_action(signout_action) about_action = Gio.SimpleAction.new('about', None) about_action.connect('activate', self.on_about_action_activated) app.add_action(about_action) quit_action = Gio.SimpleAction.new('quit', None) quit_action.connect('activate', self.on_quit_action_activated) app.add_action(quit_action) paned = Gtk.Paned() self.window.add(paned) left_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5) left_box.get_style_context().add_class(Gtk.STYLE_CLASS_SIDEBAR) paned.add1(left_box) paned.child_set_property(left_box, 'shrink', False) paned.child_set_property(left_box, 'resize', False) nav_window = Gtk.ScrolledWindow() nav_window.props.hscrollbar_policy = Gtk.PolicyType.NEVER left_box.pack_start(nav_window, True, True, 0) # icon_name, disname, tooltip, color self.nav_liststore = Gtk.ListStore(str, str, str, Gdk.RGBA) nav_treeview = Gtk.TreeView(model=self.nav_liststore) nav_treeview.get_style_context().add_class(Gtk.STYLE_CLASS_SIDEBAR) self.nav_selection = nav_treeview.get_selection() nav_treeview.props.headers_visible = False nav_treeview.set_tooltip_column(TOOLTIP_COL) icon_cell = Gtk.CellRendererPixbuf() icon_cell.props.xalign = 1 icon_col = Gtk.TreeViewColumn('Icon', icon_cell, icon_name=ICON_COL) icon_col.props.fixed_width = 40 nav_treeview.append_column(icon_col) name_cell = Gtk.CellRendererText() name_col = Gtk.TreeViewColumn('Places', name_cell, text=NAME_COL, foreground_rgba=COLOR_COL) nav_treeview.append_column(name_col) nav_selection = nav_treeview.get_selection() nav_selection.connect('changed', self.on_nav_selection_changed) nav_window.add(nav_treeview) self.progressbar = Gtk.ProgressBar() self.progressbar.set_show_text(True) self.progressbar.set_text(_('Unknown')) left_box.pack_end(self.progressbar, False, False, 0) self.img_avatar = Gtk.Image() self.img_avatar.props.halign = Gtk.Align.CENTER left_box.pack_end(self.img_avatar, False, False, 5) self.notebook = Gtk.Notebook() self.notebook.props.show_tabs = False paned.add2(self.notebook)
# in http://www.gnu.org/licenses/gpl-3.0.html import os import random import time import traceback from gi.repository import Gdk from gi.repository import Gio from gi.repository import GLib from gi.repository import GObject from gi.repository import Gtk from gi.repository import Notify from bcloud import Config Config.check_first() _ = Config._ from bcloud import const from bcloud.const import TargetInfo, TargetType from bcloud import gutil from bcloud.log import logger from bcloud import util from bcloud.MimeProvider import MimeProvider from bcloud.PreferencesDialog import PreferencesDialog from bcloud.CategoryPage import * from bcloud.CloudPage import CloudPage from bcloud.DownloadPage import DownloadPage from bcloud.HomePage import HomePage from bcloud.PreferencesDialog import PreferencesDialog from bcloud.SharePage import SharePage from bcloud.SigninDialog import SigninDialog
def __init__(self, app, auto_signin=True): super().__init__(_('Sign in now'), app.window, Gtk.DialogFlags.MODAL) self.app = app self.auto_signin = auto_signin self.set_default_size(460, 260) self.set_border_width(15) self.conf = Config.load_conf() self.profile = None box = self.get_content_area() box.set_spacing(8) username_ls = Gtk.ListStore(str) for username in self.conf['profiles']: username_ls.append([ username, ]) self.username_combo = Gtk.ComboBox.new_with_entry() self.username_combo.set_model(username_ls) self.username_combo.set_entry_text_column(0) self.username_combo.set_tooltip_text(_('Username/Email/Phone...')) box.pack_start(self.username_combo, False, False, 0) self.username_combo.connect('changed', self.on_username_changed) self.password_entry = Gtk.Entry() self.password_entry.set_placeholder_text(_('Password ..')) self.password_entry.props.visibility = False self.password_entry.connect('changed', self.on_password_entry_changed) self.password_entry.connect('activate', self.on_password_entry_activate) box.pack_start(self.password_entry, False, False, 0) self.remember_check = Gtk.CheckButton.new_with_label( _('Remember Password')) self.remember_check.props.margin_top = 20 if Config.GTK_GE_312: self.remember_check.props.margin_start = 20 else: self.remember_check.props.margin_left = 20 box.pack_start(self.remember_check, False, False, 0) self.remember_check.connect('toggled', self.on_remember_check_toggled) self.signin_check = Gtk.CheckButton.new_with_label( _('Signin Automatically')) self.signin_check.set_sensitive(False) if Config.GTK_GE_312: self.signin_check.props.margin_start = 20 else: self.signin_check.props.margin_left = 20 box.pack_start(self.signin_check, False, False, 0) self.signin_check.connect('toggled', self.on_signin_check_toggled) self.signin_button = Gtk.Button.new_with_label(_('Sign in')) self.signin_button.props.margin_top = 10 self.signin_button.connect('clicked', self.on_signin_button_clicked) box.pack_start(self.signin_button, False, False, 0) self.infobar = Gtk.InfoBar() self.infobar.set_message_type(Gtk.MessageType.ERROR) box.pack_end(self.infobar, False, False, 0) info_content = self.infobar.get_content_area() self.info_label = Gtk.Label.new( _('Failed to sign in, please try again.')) info_content.pack_start(self.info_label, False, False, 0) box.show_all() self.infobar.hide() if not gutil.keyring_available: self.signin_check.set_active(False) self.signin_check.set_sensitive(False) self.remember_check.set_active(False) self.remember_check.set_sensitive(False) GLib.timeout_add(500, self.load_defualt_profile)
def on_load_url(filelist, error=None): self.url_entry.props.secondary_icon_name = REFRESH_ICON if timestamp != self.url_entry.timestamp: logger.debug('SharePage.load_url, dirname not match, ignored') return if error: self.app.toast( _('Failed to get files, please reload this page')) logger.warn('SharePage.load_url: %s, %s, %s' % (self.curr_url, filelist, error)) self.has_next = False return state = self.select_all_button.get_active() tree_iters = [] # 插入.. 点击后返回上个目录 if self.dirname and self.dirname != '/': parent_dirname = os.path.dirname(self.dirname) pixbuf, type_ = self.app.mime.get(parent_dirname, True, icon_size=ICON_SIZE) large_pixbuf, type_ = self.app.mime.get( parent_dirname, True, icon_size=LARGE_ICON_SIZE) self.liststore.append([ state, pixbuf, large_pixbuf, '..', parent_dirname, True, 0, '0', 0, '', ]) for file_ in filelist: if file_['isdir'] == '1' or file_['isdir'] == 1: isdir = True else: isdir = False pixbuf, type_ = self.app.mime.get(file_['path'], isdir, icon_size=ICON_SIZE) large_pixbuf, type_ = self.app.mime.get( file_['path'], isdir, icon_size=LARGE_ICON_SIZE) size = int(file_.get('size', 0)) human_size = util.get_human_size(size)[0] mtime = int(file_.get('server_mtime', 0)) human_mtime = time.ctime(mtime) tree_iter = self.liststore.append([ state, pixbuf, large_pixbuf, file_['server_filename'], file_['path'], isdir, size, human_size, mtime, human_mtime, ]) tree_iters.append(tree_iter) cache_path = Config.get_cache_path(self.app.profile['username']) gutil.async_call(gutil.update_share_image, self.liststore, tree_iters, ICON_COL, LARGE_ICON_COL, filelist, cache_path, ICON_SIZE, LARGE_ICON_SIZE)