class WindowHelper: def __init__(self, window, plugin, search_func): self._window = window self._plugin = plugin self._search_func = search_func self._popup = None self._install_menu() def deactivate(self): self._uninstall_menu() self._window = None self._plugin = None def update_ui(self): pass def _uninstall_menu(self): manager = self._window.get_ui_manager() manager.remove_ui(self._ui_id) manager.remove_action_group(self._action_group) manager.ensure_update() def _install_menu(self): manager = self._window.get_ui_manager() self._action_group = gtk.ActionGroup("GeditAPQuickOpenPluginActions") self._action_group.add_actions([("APQuickOpen", gtk.STOCK_OPEN, _("Axy Quick open"), '<Ctrl><Alt>O', _("Axy Quickly open documents"), self.on_quick_open_activate)]) manager.insert_action_group(self._action_group, -1) self._ui_id = manager.add_ui_from_string(ui_str) def _create_popup(self): self._popup = Popup(self._window, self.on_result, self._search_func) self._popup.set_default_size(*self._plugin.get_popup_size()) self._popup.set_transient_for(self._window) self._popup.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self._window.get_group().add_window(self._popup) self._popup.connect('destroy', self.on_popup_destroy) def on_quick_open_activate(self, action): if not self._popup: self._create_popup() self._popup.show() def on_popup_destroy(self, popup): alloc = popup.get_allocation() self._plugin.set_popup_size((alloc.width, alloc.height)) self._popup = None def on_result(self, path): path = os.path.join(get_core(self._window).get_path(), path) uri = gio.File(path).get_uri() gedit.commands.load_uri(self._window, uri, None, -1) return True
def appui_ok6(self): nompro = self.champ0.text() refpro = self.champ1.text() descpro = self.champ2.text() if self.affect_statut.currentText() == 'Commercialisé': statpro = 0 else: statpro = 1 site1 = self.affect_site.currentText() refs_existantes = self.data.lister_references() if refpro in refs_existantes: self.pop1 = Popup() self.pop1.ref_exist_err() else: if (bool(nompro) & bool(refpro) ): ## faire un if imbriqué pour ref existe déjà ou pas try: self.data.ajout_produit(nompro, refpro, descpro, statpro, site1) self.champ0.setText("") self.champ1.setText("") self.champ2.setText("") self.label.setText("Nouveau produit entré en base.") except OperationalError: self.label.setText( "Une erreur est survenue. Vérifiez votre connexion avec le serveur de données." ) else: self.pop = Popup() self.pop.champ_vide_err("'Nom' et 'Référence'")
class Fen1(QDialog ): # afficher tous les produits ainsi que leurs sites de production def __init__(self): QDialog.__init__(self) self.setWindowTitle("IkeoOoooooo") self.setGeometry(500, 140, 400, 270) self.setStyleSheet("background-color: #003399; color: #FFFFFF") try: self.data = Bdd() except mysql.connector.errors.InterfaceError: self.pop = Popup() self.pop.connex_err() self.label = QLabel() self.label.setText( "Voici la liste des produits ainsi que leurs sites de production :" ) self.label.setAlignment(Qt.AlignCenter) self.table = QLabel() self.table.setStyleSheet( "border: 1px solid #FFCC00; font: 10pt Tahoma; color: #FFCC00") self.table.setText(self.affichage1()) layout = QVBoxLayout() layout.addWidget(self.label) layout.addWidget(self.table) self.setLayout(layout) def affichage1(self): dps = self.data.lister_produits_sites() aff1 = "\n" for key, values in dps.items(): aff2 = "\t".join(values) aff1 += " {:<23}\t>:\t{:<25} \n".format(key, aff2) return aff1
def __init__(self, parent_mode, title, width_req=0, height_req=0, align=ALIGN.DEFAULT, close_cb=None, additional_formatting=True, immediate_action=False): Popup.__init__(self, parent_mode, title, width_req=width_req, height_req=height_req, align=align, close_cb=close_cb) self.inputs = [] self.lines = [] self.current_input = 0 self.additional_formatting = additional_formatting self.immediate_action = immediate_action #We need to replicate some things in order to wrap our inputs self.encoding = parent_mode.encoding
def __init__(self): QDialog.__init__(self) self.setWindowTitle("IkeoOoooooo") self.setGeometry(500, 150, 300, 250) self.setStyleSheet("background-color: #003399; color: #FFFFFF") try: self.data = Bdd() except mysql.connector.errors.InterfaceError: self.pop = Popup() self.pop.connex_err() self.label = QLabel() self.label2 = QLabel() self.label3 = QLabel() self.label.setText("Voici la liste de nos sites de production :") self.label2.setText(self.affichage5()) self.label.setAlignment(Qt.AlignCenter) self.label2.setAlignment(Qt.AlignCenter) self.label2.setStyleSheet( "border: 4px solid #FFCC00; font: 10pt Tahoma; color: #FFCC00") layout = QVBoxLayout() layout.addWidget(self.label) layout.addWidget(self.label2) layout.addWidget(self.label3) self.setLayout(layout)
def download_success(self): self.cancle_download() self.popup = Popup(self) self.popup.download_complete() self.popup.show()
def confirm(self): self.location = self.get_location() self.popup = Popup(self) self.popup.weather_complete() self.popup.show() self.popup.new_signal.connect(self.complete)
def show_popup(self): '''Show the text notification popup.''' text = self.msgtext.GetValue() if text: # Text is set, show dialog. Status of text notification. self.textnotif = 'show' font = self.data.system['msg_font'] colors = self.data.system['popup_colors'] icon = os.path.join(self.mfcdir, self.data.system['icon_close']) popup = Popup(parent=self, style=self.bdist, text=text, font=font, colors=colors, icon=icon) popw, poph = popup.size dispw, disph = wx.GetDisplaySize() offx = (dispw - popw) / 2 offy = (disph - poph) / 2 popup.Position(ptOrigin=(0, 0), size=(offx, offy)) popup.Popup() else: # No text, no Popup, set __textnotif 'close'. self.textnotif = 'close'
def __init__(self, frame, namespace=None): """ Create a Jython Console. namespace is an optional and should be a dictionary or Map """ self.frame = frame self.history = History(self) if namespace != None: self.locals = namespace else: self.locals = {} self.buffer = [] # buffer for multi-line commands self.interp = Interpreter(self, self.locals) sys.stdout = StdOutRedirector(self) self.text_pane = JTextPane(keyTyped = self.keyTyped, keyPressed = self.keyPressed) self.__initKeyMap() self.doc = self.text_pane.document self.__propertiesChanged() self.__inittext() self.initialLocation = self.doc.createPosition(self.doc.length-1) # Don't pass frame to popups. JWindows with null owners are not focusable # this fixes the focus problem on Win32, but make the mouse problem worse self.popup = Popup(None, self.text_pane) self.tip = Tip(None) # get fontmetrics info so we can position the popup metrics = self.text_pane.getFontMetrics(self.text_pane.getFont()) self.dotWidth = metrics.charWidth('.') self.textHeight = metrics.getHeight()
def rename_success(self): self.display_update() self.cancle_rename() self.popup = Popup(self) self.popup.rename_complete() self.popup.show()
def upload_success(self): self.display_update() self.cancle_upload() self.popup = Popup(self) self.popup.upload_complete() self.popup.show()
def show_popup(self, title, text, callback=None, buttons=['OK']): popup = Popup(self.app, self.screen, title, text, buttons) self.add(popup) old_focus = self.focus # save focus at time of popup call self.focus = popup def wrapped_callback(btn): nonlocal popup # otherwise assignment to this variable will mark it as local log.info('popup wrapped_callback, restoring focus to {}'.format( old_focus)) self.focus = old_focus # restore focus popup.visible = False #popup.screen.clear() self.widgets.remove(popup) self.screen.clear() self.screen.refresh() del popup popup = None if callback: callback(btn) self.screen.clear() popup.callback = wrapped_callback
def __init__(self, items, x, y, alwaysHighlight = False, delegate = None, *args, **kwargs): # activestyle = tk.None suppresses the box in OS X and underline elsewhere. defaults = {'activestyle': tk.NONE, 'borderwidth': 0, 'exportselection': False, # Approximate the colors used in OS X: 'selectbackground': '#0950CF', 'selectforeground': '#FFF', # Normally tk has a weird fake-3D effect - remove that. 'relief': tk.FLAT} self._popup = Popup(x = x, y = y) self._listbox = tk.Listbox(self._popup, *args, **dict(defaults, **kwargs)) self._listbox.pack() self.alwaysHighlight = alwaysHighlight self._priorSelection = None self.delegate = delegate self.items = items self._listbox.bind('<<ListboxSelect>>', self._selectionChanged) self._listbox.bind('<Return>', self.selectHighlighted) self._listbox.bind('<Button-1>', self.selectHighlighted) self._listbox.bind('<Enter>', self._snapHighlightToMouse) self._listbox.bind('<Motion>', self._snapHighlightToMouse) if not self.alwaysHighlight: self._listbox.bind('<Leave>', self.unhighlight)
def __init__(self, view): Popup.__init__(self) self.set_size_request(WIDTH, HEIGHT) self.__view = view sw = gtk.ScrolledWindow() self.add(sw) sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.__tree_model = gtk.ListStore(str, str, object) self.__tree = gtk.TreeView(self.__tree_model) self.__tree.set_headers_visible(False) self.__tree.get_selection().connect('changed', self.__on_selection_changed) cell = gtk.CellRendererText() column = gtk.TreeViewColumn(None, cell, text=0) self.__tree.append_column(column) sw.add(self.__tree) sw.show_all() self.set_default_size(WIDTH, HEIGHT) # A small amount of background shows between the scrollbar and the list; # which looks ugly if it is the only gray thing in the window, so change # the window background to white self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(65535, 65535, 65535)) self.__doc_popup= DocPopup(fixed_width=True, fixed_height=True, max_height=HEIGHT, can_focus=False) self._in_change = False self.showing = False
def show_popup(self): '''Show the text notification popup.''' text = self.__msgtext.GetValue() if text: # Text is set, show dialog. Status of text notification. self.__textnotif = 'show' font = self.__data.get_sys('msg_font') colors = self.__data.get_sys('popup_colors') icon = os.path.join(self.__dir, self.__data.get_sys('icon_close')) popup = Popup(parent=self, style=self.__bdist, text=text, font=font, colors=colors, icon=icon) popw, poph = popup.get_size() dispw, disph = wx.GetDisplaySize() offx = (dispw - popw) / 2 offy = (disph - poph) / 2 popup.Position(ptOrigin=(0, 0), size=(offx, offy)) popup.Popup() else: # No text, no Popup, set __textnotif 'close'. self.__textnotif = 'close'
def _create_popup(self): self._popup = Popup(self._window, self.on_result, self._search_func) self._popup.set_default_size(*self._plugin.get_popup_size()) self._popup.set_transient_for(self._window) self._popup.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self._window.get_group().add_window(self._popup) self._popup.connect('destroy', self.on_popup_destroy)
def addCategory(self): pop=Popup(self.sender().text(),unicode(self.catList.currentText())) if pop.exec_(): newCat=pop.getNewCategory() self.cats.append(newCat) self.catList.addItem(newCat) self.catList.setCurrentIndex(self.catLen) self.catLen+=1
def __init__(self): self.root = tk.Tk() self.model = Model() self.view = View(self.root, self.model, self) self.popup = Popup(self.model) self.plot = Plot(self.model) self.config = configparser.ConfigParser() self.config.read("config.ini")
def delete_success(self): self.remove_file() self.cancle_delete() self.popup = Popup(self) self.popup.delete_complete() self.popup.show()
def do_remove(self, child): if child == self.__view: self.__view = None child.unparent() elif child == self.__scrollbar: self.__scrollbar = None child.unparent else: Popup.do_remove(child)
def upload_success(self): self.display_update() self.cancle_upload() self.popup = Popup(self) self.popup.upload_complete() self.popup.show() self.file_to_main_signal.emit()
def do_map(self): Popup.do_map(self) self.__view.map() if self.focused and self.__vscrolled: self.__scrollbar.map() else: # the scrollbar needs to be realized to accept the scroll events we forward it self.__scrollbar.realize()
def _create_popup(self): paths = [] # Open documents paths.append(CurrentDocumentsDirectory(self._window)) doc = self._window.get_active_document() # Current document directory if doc and doc.is_local(): gfile = doc.get_location() paths.append(gfile.get_parent()) # File browser root directory bus = self._window.get_message_bus() try: msg = bus.send_sync('/plugins/filebrowser', 'get_root') if msg: uri = msg.get_value('uri') if uri: gfile = gio.File(uri) if gfile.is_native(): paths.append(gfile) except StandardError: pass # Recent documents paths.append( RecentDocumentsDirectory(screen=self._window.get_screen())) # Local bookmarks for path in self._local_bookmarks(): paths.append(path) # Desktop directory desktopdir = self._desktop_dir() if desktopdir: paths.append(gio.File(desktopdir)) # Home directory paths.append(gio.File(os.path.expanduser('~'))) self._popup = Popup(self._window, paths, self.on_activated) self._popup.set_default_size(*self._plugin.get_popup_size()) self._popup.set_transient_for(self._window) self._popup.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self._window.get_group().add_window(self._popup) self._popup.connect('destroy', self.on_popup_destroy)
def addHabit(self): popup = Popup(self.window) popup.promptUser(True) self.window.wait_window(popup.window) if popup.isValid: name = popup.input.get() habit = Habit(name, 0, False, self.fr_list) self.habits.append(habit) habit.display()
def pwd_check(self, pwd1, pwd2): flag = False if pwd1 == pwd2: flag = True else: self.popup = Popup(self) self.popup.pwd_coincidence_check() self.popup.show() return flag
def _create_popup(self): self._popup = Popup(self._window, self.on_selected) self._popup.set_default_size(*self._plugin.get_popup_size()) self._popup.set_transient_for(self._window) self._popup.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self._window.get_group().add_window(self._popup) self._popup.connect("destroy", self._destroy_popup)
def __init__(self): QDialog.__init__(self) self.setWindowTitle("IkeoOoooooo") self.setGeometry(500, 50, 500, 450) self.setStyleSheet("background-color: #003399; color: #FFFFFF") try: self.data = Bdd() except mysql.connector.errors.InterfaceError: self.pop = Popup() self.pop.connex_err()
def rename_success(self): self.display_update() self.cancle_rename() self.popup = Popup(self) self.popup.rename_complete() self.popup.show() self.file_to_main_signal.emit() #
def __init__(self, parent_mode, title, width_req=-1, height_req=-1, close_cb=None): Popup.__init__(self, parent_mode, title, width_req, height_req, close_cb) self.inputs = [] self.spaces = [] self.current_input = 0
class Fen2(QDialog): # afficher la facture d'un client à une date choisie def __init__(self): QDialog.__init__(self) self.setWindowTitle("IkeoOoooooo") self.setGeometry(500, 50, 400, 450) self.setStyleSheet("background-color: #003399; color: #FFFFFF") try: self.data = Bdd() except mysql.connector.errors.InterfaceError: self.pop = Popup() self.pop.connex_err() self.vide = QLabel() self.texte_invit = QLabel() self.texte_invit.setText("Choisir un client :") self.texte_invit2 = QLabel() self.texte_invit2.setText("Date de facturation (AAAA-MM-JJ) :") self.listeclients = QComboBox() self.listeclients.addItems(self.data.lister_clients()) self.champ = QLineEdit() self.btok = QPushButton("Rechercher") self.btok.clicked.connect(self.appui_ok2) self.label = QLabel() self.label.setStyleSheet("font: 10pt Tahoma; color: #FFCC00") layout = QVBoxLayout() layout.addWidget(self.vide) layout.addWidget(self.texte_invit) layout.addWidget(self.listeclients) layout.addWidget(self.texte_invit2) layout.addWidget(self.champ) layout.addWidget(self.vide) layout.addWidget(self.btok) layout.addWidget(self.vide) layout.addWidget(self.label) layout.addWidget(self.vide) self.setLayout(layout) def appui_ok2(self): date = self.champ.text() client = self.listeclients.currentText() client = client.split(", ") idclient = client[-1] if date: try: achats = self.data.afficher_facture_date(idclient, date) aff1 = " \t{:<23}\t>:\t{:<25} \n".format("Article", "Quantité") for i in achats: aff1 += " \t{:<23}\t>:\t{:<25} \n".format(i[0], i[1]) self.label.setText(aff1) except: self.label.setText( "Une erreur est survenue. Veuillez vérifier votre connexion au serveur et réessayer." )
def do_expose_event(self, event): Popup.do_expose_event(self, event) if self.__can_focus and not self.focused and self.__vscrolled: layout = self.__create_f2_layout() width, height = layout.get_pixel_size() cr = event.window.cairo_create() cr.set_source_rgb(0., 0., 0.) cr.rectangle(0, self.allocation.height - height, self.allocation.width, 1) cr.fill() cr.move_to(self.allocation.width - width - 5, self.allocation.height - height) cr.show_layout(layout)
def editName(self): popup = Popup(self.parent) popup.promptUser(False) self.parent.wait_window(popup.window) if popup.isValid: self.name = popup.input.get() self.name_var.set(self.name) name = self.name if len(name) > 22: name = name[0:20] + '...' self.name_var.set(name)
def __init__(self, fixed_height=False, fixed_width=False, max_height=MAX_HEIGHT, can_focus=True): Popup.__init__(self) self.__fixed_height = fixed_height self.__fixed_width = fixed_width self.__max_height = max_height self.__can_focus = can_focus self.__view = gtk.TextView() self.__view.set_editable(False) bg_color = gtk.gdk.Color(0xffff, 0xffff, 0xbfbf) self.__view.modify_base(gtk.STATE_NORMAL, bg_color) self.modify_bg(gtk.STATE_NORMAL, bg_color) self.set_app_paintable(True) self.__view.modify_text(gtk.STATE_NORMAL, gtk.gdk.Color(0, 0, 0)) self.__view.set_parent(self) self.__view.show() self.__view.grab_focus() global_settings.watch('doc-tooltip-font-is-custom', self.__update_font) global_settings.watch('doc-tooltip-font-name', self.__update_font) self.__update_font() self.__scrollbar = gtk.VScrollbar() self.__scrollbar.set_parent(self) self.__scrollbar.show() self.__view.emit('set-scroll-adjustments', None, self.__scrollbar.get_adjustment()) self.__view.connect('scroll-event', self.on_scroll_event) self.__vscrolled = False self.set_resizable(False) buf = self.__view.get_buffer() self.__bold_tag = buf.create_tag(None, weight=pango.WEIGHT_BOLD) self.__heading_type_tag = buf.create_tag(None, weight=pango.WEIGHT_BOLD, pixels_below_lines=5) self.__inline_type_tag = self.__bold_tag self.__value_tag = buf.create_tag(None, family="monospace") self.__target = None self.focused = False self.connect('destroy', self.on_destroy)
class Fen3( QDialog ): # saisir une facture (et de la mémoriser en base) A TERMINER def __init__(self): QDialog.__init__(self) self.setWindowTitle("IkeoOoooooo") self.setGeometry(500, 50, 500, 450) self.setStyleSheet("background-color: #003399; color: #FFFFFF") try: self.data = Bdd() except mysql.connector.errors.InterfaceError: self.pop = Popup() self.pop.connex_err()
def __init__(self,parent_mode,title,width_req=0,height_req=0, align=ALIGN.DEFAULT, close_cb=None, additional_formatting=True, immediate_action=False): Popup.__init__(self,parent_mode,title, width_req=width_req, height_req=height_req, align=align, close_cb=close_cb) self.inputs = [] self.lines = [] self.current_input = 0 self.additional_formatting = additional_formatting self.immediate_action = immediate_action #We need to replicate some things in order to wrap our inputs self.encoding = parent_mode.encoding
def show_popup(self): """Show the text notification popup.""" text = self.__msgtext.GetValue() if text: # Text is set, show dialog. Status of text notification. self.__textnotif = "show" font = self.__data.get_sys("msg_font") colors = self.__data.get_sys("popup_colors") icon = os.path.join(self.__dir, self.__data.get_sys("icon_close")) popup = Popup(parent=self, style=self.__bdist, text=text, font=font, colors=colors, icon=icon) popw, poph = popup.get_size() dispw, disph = wx.GetDisplaySize() offx = (dispw - popw) / 2 offy = (disph - poph) / 2 popup.Position(ptOrigin=(0, 0), size=(offx, offy)) popup.Popup()
def show_priority_popup(self): if self.marked: self.popup = SelectablePopup(self,"Set File Priority",self.do_priority) self.popup.add_line("_Do Not Download",data=deluge.common.FILE_PRIORITY["Do Not Download"]) self.popup.add_line("_Normal Priority",data=deluge.common.FILE_PRIORITY["Normal Priority"]) self.popup.add_line("_High Priority",data=deluge.common.FILE_PRIORITY["High Priority"]) self.popup.add_line("H_ighest Priority",data=deluge.common.FILE_PRIORITY["Highest Priority"])
def _create_popup(self): paths = [] # Open documents paths.append(CurrentDocumentsDirectory(self._window)) doc = self._window.get_active_document() # Current document directory if doc and doc.is_local(): gfile = doc.get_location() paths.append(gfile.get_parent()) # File browser root directory if pluma.version[0] > 2 or ( pluma.version[0] == 2 and (pluma.version[1] > 26 or (pluma.version[1] == 26 and pluma.version[2] >= 2)) ): bus = self._window.get_message_bus() try: msg = bus.send_sync("/plugins/filebrowser", "get_root") if msg: uri = msg.get_value("uri") if uri: gfile = gio.File(uri) if gfile.is_native(): paths.append(gfile) except StandardError: pass # Recent documents paths.append(RecentDocumentsDirectory(screen=self._window.get_screen())) # Local bookmarks for path in self._local_bookmarks(): paths.append(path) # Desktop directory desktopdir = self._desktop_dir() if desktopdir: paths.append(gio.File(desktopdir)) # Home directory paths.append(gio.File(os.path.expanduser("~"))) self._popup = Popup(self._window, paths, self.on_activated) self._popup.set_default_size(*self._plugin.get_popup_size()) self._popup.set_transient_for(self._window) self._popup.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self._window.get_group().add_window(self._popup) self._popup.connect("destroy", self.on_popup_destroy)
def _create_popup(self): self._popup = Popup(self._window, self.on_result, self._search_func) self._popup.set_default_size(*self._plugin.get_popup_size()) self._popup.set_transient_for(self._window) self._popup.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self._window.get_group().add_window(self._popup) self._popup.connect("destroy", self.on_popup_destroy)
def __init__(self, frame): self.frame = frame # TODO do I need a reference to frame after the constructor? self.history = History(self) self.bs = 0 # what is this? # command buffer self.buffer = [] self.locals = {"gvSIG": sys.gvSIG} self.interp = Interpreter(self, self.locals) sys.stdout = StdOutRedirector(self) # create a textpane self.output = JTextPane(keyTyped=self.keyTyped, keyPressed=self.keyPressed) # TODO rename output to textpane # CTRL UP AND DOWN don't work keyBindings = [ (KeyEvent.VK_ENTER, 0, "jython.enter", self.enter), (KeyEvent.VK_DELETE, 0, "jython.delete", self.delete), (KeyEvent.VK_HOME, 0, "jython.home", self.home), (KeyEvent.VK_UP, 0, "jython.up", self.history.historyUp), (KeyEvent.VK_DOWN, 0, "jython.down", self.history.historyDown), (KeyEvent.VK_PERIOD, 0, "jython.showPopup", self.showPopup), (KeyEvent.VK_ESCAPE, 0, "jython.hide", self.hide), ("(", 0, "jython.showTip", self.showTip), (")", 0, "jython.hideTip", self.hideTip), # (KeyEvent.VK_UP, InputEvent.CTRL_MASK, DefaultEditorKit.upAction, self.output.keymap.getAction(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0))), # (KeyEvent.VK_DOWN, InputEvent.CTRL_MASK, DefaultEditorKit.downAction, self.output.keymap.getAction(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0))) ] # TODO rename newmap to keymap newmap = JTextComponent.addKeymap("jython", self.output.keymap) for (key, modifier, name, function) in keyBindings: newmap.addActionForKeyStroke(KeyStroke.getKeyStroke(key, modifier), ActionDelegator(name, function)) self.output.keymap = newmap self.doc = self.output.document # self.panel.add(BorderLayout.CENTER, JScrollPane(self.output)) self.__propertiesChanged() self.__inittext() self.initialLocation = self.doc.createPosition(self.doc.length - 1) # Don't pass frame to popups. JWindows with null owners are not focusable # this fixes the focus problem on Win32, but make the mouse problem worse self.popup = Popup(None, self.output) self.tip = Tip(None) # get fontmetrics info so we can position the popup metrics = self.output.getFontMetrics(self.output.getFont()) self.dotWidth = metrics.charWidth(".") self.textHeight = metrics.getHeight() # add some handles to our objects self.locals["console"] = self self.caret = self.output.getCaret()
def _show_torrent_filter_popup(self): self.popup = SelectablePopup(self,"Filter Torrents",self._torrent_filter) self.popup.add_line("_All",data=FILTER.ALL) self.popup.add_line("Ac_tive",data=FILTER.ACTIVE) self.popup.add_line("_Downloading",data=FILTER.DOWNLOADING,foreground="green") self.popup.add_line("_Seeding",data=FILTER.SEEDING,foreground="cyan") self.popup.add_line("_Paused",data=FILTER.PAUSED) self.popup.add_line("_Error",data=FILTER.ERROR,foreground="red") self.popup.add_line("_Checking",data=FILTER.CHECKING,foreground="blue") self.popup.add_line("Q_ueued",data=FILTER.QUEUED,foreground="yellow")
def __init__(self, fixed_height=False, fixed_width=False, max_height=MAX_HEIGHT, can_focus=True): Popup.__init__(self) self.__fixed_height = fixed_height self.__fixed_width = fixed_width self.__max_height = max_height self.__can_focus = can_focus self.__font = pango.FontDescription("Sans 9") self.__view = gtk.TextView() self.__view.set_editable(False) bg_color = gtk.gdk.Color(0xffff, 0xffff, 0xbfbf) self.__view.modify_base(gtk.STATE_NORMAL, bg_color) self.modify_bg(gtk.STATE_NORMAL, bg_color) self.__view.modify_text(gtk.STATE_NORMAL, gtk.gdk.Color(0, 0, 0)) self.__view.modify_font(self.__font) self.__view.set_parent(self) self.__view.show() self.__view.grab_focus() self.__scrollbar = gtk.VScrollbar() self.__scrollbar.set_parent(self) self.__scrollbar.show() self.__view.emit('set-scroll-adjustments', None, self.__scrollbar.get_adjustment()) self.__vscrolled = False self.set_resizable(False) buf = self.__view.get_buffer() self.__bold_tag = buf.create_tag(None, weight=pango.WEIGHT_BOLD) self.__heading_type_tag = buf.create_tag(None, weight=pango.WEIGHT_BOLD, pixels_below_lines=5) self.__inline_type_tag = self.__bold_tag self.__value_tag = buf.create_tag(None, family="monospace") self.__target = None self.focused = False
def refresh(self,lines=None): # show a message popup if there's anything queued if self.popup == None and self.messages: title,msg = self.messages.popleft() self.popup = MessagePopup(self,title,msg) # Update the status bars self.stdscr.clear() self.add_string(0,self.statusbars.topbar) hstr = "%sPress [h] for help"%(" "*(self.cols - len(self.statusbars.bottombar) - 10)) self.add_string(self.rows - 1, "%s%s"%(self.statusbars.bottombar,hstr)) if self.files_sep: self.add_string((self.rows/2)-1,self.files_sep) off = 1 if self.torrent_state: for f in self._info_fields: if off >= (self.rows/2): break if f[1] != None: args = [] try: for key in f[2]: args.append(self.torrent_state[key]) except: log.debug("Could not get info field: %s",e) continue info = f[1](*args) else: info = self.torrent_state[f[2][0]] self.add_string(off,"{!info!}%s: {!input!}%s"%(f[0],info)) off += 1 else: self.add_string(1, "Waiting for torrent state") off = self.rows/2 self.add_string(off,self.column_string) if self.file_list: off += 1 self.more_to_draw = False self.draw_files(self.file_list,0,off,0) #self.stdscr.redrawwin() self.stdscr.noutrefresh() if self.popup: self.popup.refresh() curses.doupdate()
def _create_popup(self): paths = [] # Open documents paths.append(CurrentDocumentsDirectory(self.window)) doc = self.window.get_active_document() # Current document directory if doc and doc.is_local(): gfile = doc.get_location() paths.append(gfile.get_parent()) # File browser root directory bus = self.window.get_message_bus() if bus.is_registered('/plugins/filebrowser', 'get_root'): msg = bus.send_sync('/plugins/filebrowser', 'get_root') if msg: gfile = msg.props.location if gfile and gfile.is_native(): paths.append(gfile) # Recent documents paths.append(RecentDocumentsDirectory()) # Local bookmarks for path in self._local_bookmarks(): paths.append(path) # Desktop directory desktopdir = self._desktop_dir() if desktopdir: paths.append(Gio.file_new_for_path(desktopdir)) # Home directory paths.append(Gio.file_new_for_path(os.path.expanduser('~'))) self._popup = Popup(self.window, paths, self.on_activated) self.window.get_group().add_window(self._popup) self._popup.set_default_size(*self.get_popup_size()) self._popup.set_transient_for(self.window) self._popup.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) self._popup.connect('destroy', self.on_popup_destroy)
def _show_torrent_add_popup(self): dl = "" ap = 1 try: dl = self.coreconfig["download_location"] except KeyError: pass try: if self.coreconfig["add_paused"]: ap = 0 except KeyError: pass self.popup = InputPopup(self,"Add Torrent (Esc to cancel)",close_cb=self._do_add) self.popup.add_text_input("Enter path to torrent file:","file") self.popup.add_text_input("Enter save path:","path",dl) self.popup.add_select_input("Add Paused:","add_paused",["Yes","No"],[True,False],ap) self.popup.add_spaces(1) self.popup.add_select_input("Path is:","path_type",["Auto","File","URL"],[0,1,2],0)
class WindowHelper: def __init__(self, window, plugin): self._window = window self._plugin = plugin self._popup = None self._install_menu() def deactivate(self): self._uninstall_menu() self._window = None self._plugin = None def update_ui(self): pass def _uninstall_menu(self): manager = self._window.get_ui_manager() manager.remove_ui(self._ui_id) manager.remove_action_group(self._action_group) manager.ensure_update() def _install_menu(self): manager = self._window.get_ui_manager() self._action_group = gtk.ActionGroup("CeditQuickOpenPluginActions") self._action_group.add_actions([ ("QuickOpen", gtk.STOCK_OPEN, _("Quick open"), '<Ctrl><Alt>O', _("Quickly open documents"), self.on_quick_open_activate) ]) manager.insert_action_group(self._action_group, -1) self._ui_id = manager.add_ui_from_string(ui_str) def _create_popup(self): paths = [] # Open documents paths.append(CurrentDocumentsDirectory(self._window)) doc = self._window.get_active_document() # Current document directory if doc and doc.is_local(): gfile = doc.get_location() paths.append(gfile.get_parent()) # File browser root directory bus = self._window.get_message_bus() try: msg = bus.send_sync('/plugins/filebrowser', 'get_root') if msg: uri = msg.get_value('uri') if uri: gfile = gio.File(uri) if gfile.is_native(): paths.append(gfile) except StandardError: pass # Recent documents paths.append(RecentDocumentsDirectory(screen=self._window.get_screen())) # Local bookmarks for path in self._local_bookmarks(): paths.append(path) # Desktop directory desktopdir = self._desktop_dir() if desktopdir: paths.append(gio.File(desktopdir)) # Home directory paths.append(gio.File(os.path.expanduser('~'))) self._popup = Popup(self._window, paths, self.on_activated) self._popup.set_default_size(*self._plugin.get_popup_size()) self._popup.set_transient_for(self._window) self._popup.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self._window.get_group().add_window(self._popup) self._popup.connect('destroy', self.on_popup_destroy) def _local_bookmarks(self): filename = os.path.expanduser('~/.gtk-bookmarks') if not os.path.isfile(filename): return [] paths = [] for line in file(filename, 'r').xreadlines(): uri = line.strip().split(" ")[0] f = gio.File(uri) if f.is_native(): try: info = f.query_info("standard::type") if info and info.get_file_type() == gio.FILE_TYPE_DIRECTORY: paths.append(f) except glib.GError: pass return paths def _desktop_dir(self): config = os.getenv('XDG_CONFIG_HOME') if not config: config = os.path.expanduser('~/.config') config = os.path.join(config, 'user-dirs.dirs') desktopdir = None if os.path.isfile(config): for line in file(config, 'r').xreadlines(): line = line.strip() if line.startswith('XDG_DESKTOP_DIR'): parts = line.split('=', 1) desktopdir = os.path.expandvars(parts[1].strip('"').strip("'")) break if not desktopdir: desktopdir = os.path.expanduser('~/Desktop') return desktopdir # Callbacks def on_quick_open_activate(self, action): if not self._popup: self._create_popup() self._popup.show() def on_popup_destroy(self, popup): alloc = popup.get_allocation() self._plugin.set_popup_size((alloc.width, alloc.height)) self._popup = None def on_activated(self, gfile): cedit.commands.load_uri(self._window, gfile.get_uri(), None, -1) return True
def _doRead(self): # Read the character effected_lines = None c = self.stdscr.getch() if self.popup: if self.popup.handle_read(c): self.popup = None self.refresh() return if c > 31 and c < 256: if chr(c) == 'Q': from twisted.internet import reactor if client.connected(): def on_disconnect(result): reactor.stop() client.disconnect().addCallback(on_disconnect) else: reactor.stop() return if self.formatted_rows==None or self.popup: return elif self.entering_search: self.__update_search(c) self.refresh([]) return #log.error("pressed key: %d\n",c) #if c == 27: # handle escape # log.error("CANCEL") # Navigate the torrent list if c == curses.KEY_UP: if self.cursel == 1: return if not self._scroll_up(1): effected_lines = [self.cursel-1,self.cursel] elif c == curses.KEY_PPAGE: self._scroll_up(int(self.rows/2)) elif c == curses.KEY_DOWN: if self.cursel >= self.numtorrents: return if not self._scroll_down(1): effected_lines = [self.cursel-2,self.cursel-1] elif c == curses.KEY_NPAGE: self._scroll_down(int(self.rows/2)) elif c == curses.KEY_HOME: self._scroll_up(self.cursel) elif c == curses.KEY_END: self._scroll_down(self.numtorrents-self.cursel) elif c == curses.KEY_RIGHT: # We enter a new mode for the selected torrent here tid = self.current_torrent_id() if tid: self.show_torrent_details(tid) return # Enter Key elif (c == curses.KEY_ENTER or c == 10) and self.numtorrents: if self.cursel not in self.marked: self.marked.append(self.cursel) self.last_mark = self.cursel torrent_actions_popup(self,self._selected_torrent_ids(),details=True) return else: if c > 31 and c < 256: if chr(c) == '/': self.search_string = "" self.cursor = 0 self.entering_search = True elif chr(c) == 'n' and self.search_string: self.__do_search() elif chr(c) == 'j': if not self._scroll_up(1): effected_lines = [self.cursel-1,self.cursel] elif chr(c) == 'k': if not self._scroll_down(1): effected_lines = [self.cursel-2,self.cursel-1] elif chr(c) == 'i': cid = self.current_torrent_id() if cid: def cb(): self.__torrent_info_id = None self.popup = Popup(self,"Info",close_cb=cb) self.popup.add_line("Getting torrent info...") self.__torrent_info_id = cid elif chr(c) == 'm': self._mark_unmark(self.cursel) effected_lines = [self.cursel-1] elif chr(c) == 'M': if self.last_mark >= 0: if (self.cursel+1) > self.last_mark: mrange = range(self.last_mark,self.cursel+1) else: mrange = range(self.cursel-1,self.last_mark) self.marked.extend(mrange[1:]) effected_lines = mrange else: self._mark_unmark(self.cursel) effected_lines = [self.cursel-1] elif chr(c) == 'c': self.marked = [] self.last_mark = -1 elif chr(c) == 'a': self._show_torrent_add_popup() elif chr(c) == 'f': self._show_torrent_filter_popup() elif chr(c) == 'h': self.popup = Popup(self,"Help",init_lines=self.__help_lines) elif chr(c) == 'p': self.show_preferences() return elif chr(c) == 'e': self.__show_events() return elif chr(c) == 'l': self.__legacy_mode() return self.refresh(effected_lines)
def refresh(self,lines=None): #log.error("ref") #import traceback #traceback.print_stack() # Something has requested we scroll to the top of the list if self._go_top: self.cursel = 1 self.curoff = 1 self._go_top = False # show a message popup if there's anything queued if self.popup == None and self.messages: title,msg = self.messages.popleft() self.popup = MessagePopup(self,title,msg) if not lines: self.stdscr.clear() # Update the status bars if self._curr_filter == None: self.add_string(0,self.statusbars.topbar) else: self.add_string(0,"%s {!filterstatus!}Current filter: %s"%(self.statusbars.topbar,self._curr_filter)) self.add_string(1,self.column_string) if self.entering_search: self.add_string(self.rows - 1,"{!black,white!}Search torrents: %s"%self.search_string) else: hstr = "%sPress [h] for help"%(" "*(self.cols - len(self.statusbars.bottombar) - 10)) self.add_string(self.rows - 1, "%s%s"%(self.statusbars.bottombar,hstr)) # add all the torrents if self.formatted_rows == []: msg = "No torrents match filter".center(self.cols) self.add_string(3, "{!info!}%s"%msg) elif self.formatted_rows: tidx = self.curoff currow = 2 if lines: todraw = [] for l in lines: todraw.append(self.formatted_rows[l]) lines.reverse() else: todraw = self.formatted_rows[tidx-1:] for row in todraw: # default style fg = "white" bg = "black" attr = None if lines: tidx = lines.pop()+1 currow = tidx-self.curoff+2 if tidx in self.marked: bg = "blue" attr = "bold" if tidx == self.cursel: bg = "white" attr = "bold" if tidx in self.marked: fg = "blue" else: fg = "black" if row[1] == "Downloading": fg = "green" elif row[1] == "Seeding": fg = "cyan" elif row[1] == "Error": fg = "red" elif row[1] == "Queued": fg = "yellow" elif row[1] == "Checking": fg = "blue" if attr: colorstr = "{!%s,%s,%s!}"%(fg,bg,attr) else: colorstr = "{!%s,%s!}"%(fg,bg) self.add_string(currow,"%s%s"%(colorstr,row[0]),trim=False) tidx += 1 currow += 1 if (currow > (self.rows - 2)): break else: self.add_string(1, "Waiting for torrents from core...") #self.stdscr.redrawwin() if self.entering_search: curses.curs_set(2) self.stdscr.move(self.rows-1,self.cursor+17) else: curses.curs_set(0) self.stdscr.noutrefresh() if self.popup: self.popup.refresh() curses.doupdate()
class AllTorrents(BaseMode, component.Component): def __init__(self, stdscr, encoding=None): self.formatted_rows = None self.torrent_names = None self.cursel = 1 self.curoff = 1 # TODO: this should really be 0 indexed self.column_string = "" self.popup = None self.messages = deque() self.marked = [] self.last_mark = -1 self._sorted_ids = None self._go_top = False self._curr_filter = None self.entering_search = False self.search_string = None self.cursor = 0 self.coreconfig = component.get("ConsoleUI").coreconfig self.legacy_mode = None self.__status_dict = {} self.__torrent_info_id = None BaseMode.__init__(self, stdscr, encoding) component.Component.__init__(self, "AllTorrents", 1, depend=["SessionProxy"]) curses.curs_set(0) self.stdscr.notimeout(0) self.__split_help() self.update_config() component.start(["AllTorrents"]) self._info_fields = [ ("Name",None,("name",)), ("State", None, ("state",)), ("Down Speed", format_utils.format_speed, ("download_payload_rate",)), ("Up Speed", format_utils.format_speed, ("upload_payload_rate",)), ("Progress", format_utils.format_progress, ("progress",)), ("ETA", deluge.common.ftime, ("eta",)), ("Path", None, ("save_path",)), ("Downloaded",deluge.common.fsize,("all_time_download",)), ("Uploaded", deluge.common.fsize,("total_uploaded",)), ("Share Ratio", format_utils.format_float, ("ratio",)), ("Seeders",format_utils.format_seeds_peers,("num_seeds","total_seeds")), ("Peers",format_utils.format_seeds_peers,("num_peers","total_peers")), ("Active Time",deluge.common.ftime,("active_time",)), ("Seeding Time",deluge.common.ftime,("seeding_time",)), ("Date Added",deluge.common.fdate,("time_added",)), ("Availability", format_utils.format_float, ("distributed_copies",)), ("Pieces", format_utils.format_pieces, ("num_pieces","piece_length")), ] self.__status_keys = ["name","state","download_payload_rate","upload_payload_rate", "progress","eta","all_time_download","total_uploaded", "ratio", "num_seeds","total_seeds","num_peers","total_peers", "active_time", "seeding_time","time_added","distributed_copies", "num_pieces", "piece_length","save_path"] # component start/update def start(self): component.get("SessionProxy").get_torrents_status(self.__status_dict, self.__status_fields).addCallback(self.set_state,False) def update(self): component.get("SessionProxy").get_torrents_status(self.__status_dict, self.__status_fields).addCallback(self.set_state,True) if self.__torrent_info_id: component.get("SessionProxy").get_torrent_status(self.__torrent_info_id, self.__status_keys).addCallback(self._on_torrent_status) def update_config(self): self.config = ConfigManager("console.conf",DEFAULT_PREFS) self.__cols_to_show = [pref for pref in column_pref_names if self.config["show_%s"%pref]] self.__columns = [prefs_to_names[col] for col in self.__cols_to_show] self.__status_fields = column.get_required_fields(self.__columns) for rf in ["state","name","queue"]: # we always need these, even if we're not displaying them if not rf in self.__status_fields: self.__status_fields.append(rf) self.__update_columns() def __split_help(self): self.__help_lines = format_utils.wrap_string(HELP_STR,(self.cols/2)-2) def resume(self): self._go_top = True component.start(["AllTorrents"]) self.refresh() def __update_columns(self): self.column_widths = [self.config["%s_width"%c] for c in self.__cols_to_show] req = sum(filter(lambda x:x >= 0,self.column_widths)) if (req > self.cols): # can't satisfy requests, just spread out evenly cw = int(self.cols/len(self.__columns)) for i in range(0,len(self.column_widths)): self.column_widths[i] = cw else: rem = self.cols - req var_cols = len(filter(lambda x: x < 0,self.column_widths)) if (var_cols > 0): vw = int(rem/var_cols) for i in range(0, len(self.column_widths)): if (self.column_widths[i] < 0): self.column_widths[i] = vw self.column_string = "{!header!}%s"%("".join(["%s%s"%(self.__columns[i]," "*(self.column_widths[i]-len(self.__columns[i]))) for i in range(0,len(self.__columns))])) def set_state(self, state, refresh): self.curstate = state # cache in case we change sort order newnames = [] newrows = [] self._sorted_ids = self._sort_torrents(self.curstate) for torrent_id in self._sorted_ids: ts = self.curstate[torrent_id] newnames.append(ts["name"]) newrows.append((format_utils.format_row([column.get_column_value(name,ts) for name in self.__columns],self.column_widths),ts["state"])) self.numtorrents = len(state) self.formatted_rows = newrows self.torrent_names = newnames if refresh: self.refresh() def get_torrent_name(self, torrent_id): for p,i in enumerate(self._sorted_ids): if torrent_id == i: return self.torrent_names[p] return None def _scroll_up(self, by): prevoff = self.curoff self.cursel = max(self.cursel - by,1) if ((self.cursel - 1) < self.curoff): self.curoff = max(self.cursel - 1,1) return prevoff != self.curoff def _scroll_down(self, by): prevoff = self.curoff self.cursel = min(self.cursel + by,self.numtorrents) if ((self.curoff + self.rows - 5) < self.cursel): self.curoff = self.cursel - self.rows + 5 return prevoff != self.curoff def current_torrent_id(self): if self._sorted_ids: return self._sorted_ids[self.cursel-1] else: return None def _selected_torrent_ids(self): ret = [] for i in self.marked: ret.append(self._sorted_ids[i-1]) return ret def _on_torrent_status(self, state): if (self.popup): self.popup.clear() name = state["name"] off = int((self.cols/4)-(len(name)/2)) self.popup.set_title(name) for i,f in enumerate(self._info_fields): if f[1] != None: args = [] try: for key in f[2]: args.append(state[key]) except: log.debug("Could not get info field: %s",e) continue info = f[1](*args) else: info = state[f[2][0]] nl = len(f[0])+4 if (nl+len(info))>self.popup.width: self.popup.add_line("{!info!}%s: {!input!}%s"%(f[0],info[:(self.popup.width - nl)])) info = info[(self.popup.width - nl):] n = self.popup.width-3 chunks = [info[i:i+n] for i in xrange(0, len(info), n)] for c in chunks: self.popup.add_line(" %s"%c) else: self.popup.add_line("{!info!}%s: {!input!}%s"%(f[0],info)) self.refresh() else: self.__torrent_info_id = None def on_resize(self, *args): BaseMode.on_resize_norefresh(self, *args) self.__update_columns() self.__split_help() if self.popup: self.popup.handle_resize() self.refresh() def _queue_sort(self, v1, v2): if v1 == v2: return 0 if v2 < 0: return -1 if v1 < 0: return 1 if v1 > v2: return 1 if v2 > v1: return -1 def _sort_torrents(self, state): "sorts by queue #" return sorted(state,cmp=self._queue_sort,key=lambda s:state.get(s)["queue"]) def _format_queue(self, qnum): if (qnum >= 0): return "%d"%(qnum+1) else: return "" def show_torrent_details(self,tid): def dodeets(arg): if arg and True in arg[0]: self.stdscr.clear() component.get("ConsoleUI").set_mode(TorrentDetail(self,tid,self.stdscr,self.encoding)) else: self.messages.append(("Error","An error occured trying to display torrent details")) component.stop(["AllTorrents"]).addCallback(dodeets) def show_preferences(self): def _on_get_config(config): client.core.get_listen_port().addCallback(_on_get_listen_port,config) def _on_get_listen_port(port,config): client.core.get_cache_status().addCallback(_on_get_cache_status,port,config) def _on_get_cache_status(status,port,config): def doprefs(arg): if arg and True in arg[0]: self.stdscr.clear() component.get("ConsoleUI").set_mode(Preferences(self,config,self.config,port,status,self.stdscr,self.encoding)) else: self.messages.append(("Error","An error occured trying to display preferences")) component.stop(["AllTorrents"]).addCallback(doprefs) client.core.get_config().addCallback(_on_get_config) def __show_events(self): def doevents(arg): if arg and True in arg[0]: self.stdscr.clear() component.get("ConsoleUI").set_mode(EventView(self,self.stdscr,self.encoding)) else: self.messages.append(("Error","An error occured trying to display events")) component.stop(["AllTorrents"]).addCallback(doevents) def __legacy_mode(self): def dolegacy(arg): if arg and True in arg[0]: self.stdscr.clear() if not self.legacy_mode: self.legacy_mode = Legacy(self.stdscr,self.encoding) component.get("ConsoleUI").set_mode(self.legacy_mode) self.legacy_mode.refresh() curses.curs_set(2) else: self.messages.append(("Error","An error occured trying to switch to legacy mode")) component.stop(["AllTorrents"]).addCallback(dolegacy) def _torrent_filter(self, idx, data): if data==FILTER.ALL: self.__status_dict = {} self._curr_filter = None elif data==FILTER.ACTIVE: self.__status_dict = {"state":"Active"} self._curr_filter = "Active" elif data==FILTER.DOWNLOADING: self.__status_dict = {"state":"Downloading"} self._curr_filter = "Downloading" elif data==FILTER.SEEDING: self.__status_dict = {"state":"Seeding"} self._curr_filter = "Seeding" elif data==FILTER.PAUSED: self.__status_dict = {"state":"Paused"} self._curr_filter = "Paused" elif data==FILTER.CHECKING: self.__status_dict = {"state":"Checking"} self._curr_filter = "Checking" elif data==FILTER.ERROR: self.__status_dict = {"state":"Error"} self._curr_filter = "Error" elif data==FILTER.QUEUED: self.__status_dict = {"state":"Queued"} self._curr_filter = "Queued" self._go_top = True return True def _show_torrent_filter_popup(self): self.popup = SelectablePopup(self,"Filter Torrents",self._torrent_filter) self.popup.add_line("_All",data=FILTER.ALL) self.popup.add_line("Ac_tive",data=FILTER.ACTIVE) self.popup.add_line("_Downloading",data=FILTER.DOWNLOADING,foreground="green") self.popup.add_line("_Seeding",data=FILTER.SEEDING,foreground="cyan") self.popup.add_line("_Paused",data=FILTER.PAUSED) self.popup.add_line("_Error",data=FILTER.ERROR,foreground="red") self.popup.add_line("_Checking",data=FILTER.CHECKING,foreground="blue") self.popup.add_line("Q_ueued",data=FILTER.QUEUED,foreground="yellow") def __report_add_status(self, succ_cnt, fail_cnt, fail_msgs): if fail_cnt == 0: self.report_message("Torrents Added","{!success!}Successfully added %d torrent(s)"%succ_cnt) else: msg = ("{!error!}Failed to add the following %d torrent(s):\n {!error!}"%fail_cnt)+"\n {!error!}".join(fail_msgs) if succ_cnt != 0: msg += "\n \n{!success!}Successfully added %d torrent(s)"%succ_cnt self.report_message("Torrent Add Report",msg) def _do_add(self, result): log.debug("Adding Torrent(s): %s (dl path: %s) (paused: %d)",result["file"],result["path"],result["add_paused"]) ress = {"succ":0, "fail":0, "fmsg":[]} def fail_cb(msg,t_file,ress): log.debug("failed to add torrent: %s: %s"%(t_file,msg)) ress["fail"]+=1 ress["fmsg"].append("%s: %s"%(t_file,msg)) if (ress["succ"]+ress["fail"]) >= ress["total"]: self.__report_add_status(ress["succ"],ress["fail"],ress["fmsg"]) def suc_cb(tid,t_file,ress): if tid: log.debug("added torrent: %s (%s)"%(t_file,tid)) ress["succ"]+=1 if (ress["succ"]+ress["fail"]) >= ress["total"]: self.__report_add_status(ress["succ"],ress["fail"],ress["fmsg"]) else: fail_cb("Already in session (probably)",t_file,ress) add_torrent(result["file"],result,suc_cb,fail_cb,ress) def _show_torrent_add_popup(self): dl = "" ap = 1 try: dl = self.coreconfig["download_location"] except KeyError: pass try: if self.coreconfig["add_paused"]: ap = 0 except KeyError: pass self.popup = InputPopup(self,"Add Torrent (Esc to cancel)",close_cb=self._do_add) self.popup.add_text_input("Enter path to torrent file:","file") self.popup.add_text_input("Enter save path:","path",dl) self.popup.add_select_input("Add Paused:","add_paused",["Yes","No"],[True,False],ap) self.popup.add_spaces(1) self.popup.add_select_input("Path is:","path_type",["Auto","File","URL"],[0,1,2],0) def report_message(self,title,message): self.messages.append((title,message)) def clear_marks(self): self.marked = [] self.last_mark = -1 def set_popup(self,pu): self.popup = pu self.refresh() def refresh(self,lines=None): #log.error("ref") #import traceback #traceback.print_stack() # Something has requested we scroll to the top of the list if self._go_top: self.cursel = 1 self.curoff = 1 self._go_top = False # show a message popup if there's anything queued if self.popup == None and self.messages: title,msg = self.messages.popleft() self.popup = MessagePopup(self,title,msg) if not lines: self.stdscr.clear() # Update the status bars if self._curr_filter == None: self.add_string(0,self.statusbars.topbar) else: self.add_string(0,"%s {!filterstatus!}Current filter: %s"%(self.statusbars.topbar,self._curr_filter)) self.add_string(1,self.column_string) if self.entering_search: self.add_string(self.rows - 1,"{!black,white!}Search torrents: %s"%self.search_string) else: hstr = "%sPress [h] for help"%(" "*(self.cols - len(self.statusbars.bottombar) - 10)) self.add_string(self.rows - 1, "%s%s"%(self.statusbars.bottombar,hstr)) # add all the torrents if self.formatted_rows == []: msg = "No torrents match filter".center(self.cols) self.add_string(3, "{!info!}%s"%msg) elif self.formatted_rows: tidx = self.curoff currow = 2 if lines: todraw = [] for l in lines: todraw.append(self.formatted_rows[l]) lines.reverse() else: todraw = self.formatted_rows[tidx-1:] for row in todraw: # default style fg = "white" bg = "black" attr = None if lines: tidx = lines.pop()+1 currow = tidx-self.curoff+2 if tidx in self.marked: bg = "blue" attr = "bold" if tidx == self.cursel: bg = "white" attr = "bold" if tidx in self.marked: fg = "blue" else: fg = "black" if row[1] == "Downloading": fg = "green" elif row[1] == "Seeding": fg = "cyan" elif row[1] == "Error": fg = "red" elif row[1] == "Queued": fg = "yellow" elif row[1] == "Checking": fg = "blue" if attr: colorstr = "{!%s,%s,%s!}"%(fg,bg,attr) else: colorstr = "{!%s,%s!}"%(fg,bg) self.add_string(currow,"%s%s"%(colorstr,row[0]),trim=False) tidx += 1 currow += 1 if (currow > (self.rows - 2)): break else: self.add_string(1, "Waiting for torrents from core...") #self.stdscr.redrawwin() if self.entering_search: curses.curs_set(2) self.stdscr.move(self.rows-1,self.cursor+17) else: curses.curs_set(0) self.stdscr.noutrefresh() if self.popup: self.popup.refresh() curses.doupdate() def _mark_unmark(self,idx): if idx in self.marked: self.marked.remove(idx) self.last_mark = -1 else: self.marked.append(idx) self.last_mark = idx def __do_search(self): # search forward for the next torrent matching self.search_string for i,n in enumerate(self.torrent_names[self.cursel:]): if n.find(self.search_string) >= 0: self.cursel += (i+1) if ((self.curoff + self.rows - 5) < self.cursel): self.curoff = self.cursel - self.rows + 5 return def __update_search(self, c): if c == curses.KEY_BACKSPACE or c == 127: if self.search_string and self.cursor > 0: self.search_string = self.search_string[:self.cursor - 1] + self.search_string[self.cursor:] self.cursor-=1 elif c == curses.KEY_DC: if self.search_string and self.cursor < len(self.search_string): self.search_string = self.search_string[:self.cursor] + self.search_string[self.cursor+1:] elif c == curses.KEY_LEFT: self.cursor = max(0,self.cursor-1) elif c == curses.KEY_RIGHT: self.cursor = min(len(self.search_string),self.cursor+1) elif c == curses.KEY_HOME: self.cursor = 0 elif c == curses.KEY_END: self.cursor = len(self.search_string) elif c == 27: self.search_string = None self.entering_search = False elif c == 10 or c == curses.KEY_ENTER: self.entering_search = False if self.search_string: self.__do_search() else: self.search_string = None elif c > 31 and c < 256: stroke = chr(c) uchar = "" while not uchar: try: uchar = stroke.decode(self.encoding) except UnicodeDecodeError: c = self.stdscr.getch() stroke += chr(c) if uchar: if self.cursor == len(self.search_string): self.search_string += uchar else: # Insert into string self.search_string = self.search_string[:self.cursor] + uchar + self.search_string[self.cursor:] # Move the cursor forward self.cursor+=1 def _doRead(self): # Read the character effected_lines = None c = self.stdscr.getch() if self.popup: if self.popup.handle_read(c): self.popup = None self.refresh() return if c > 31 and c < 256: if chr(c) == 'Q': from twisted.internet import reactor if client.connected(): def on_disconnect(result): reactor.stop() client.disconnect().addCallback(on_disconnect) else: reactor.stop() return if self.formatted_rows==None or self.popup: return elif self.entering_search: self.__update_search(c) self.refresh([]) return #log.error("pressed key: %d\n",c) #if c == 27: # handle escape # log.error("CANCEL") # Navigate the torrent list if c == curses.KEY_UP: if self.cursel == 1: return if not self._scroll_up(1): effected_lines = [self.cursel-1,self.cursel] elif c == curses.KEY_PPAGE: self._scroll_up(int(self.rows/2)) elif c == curses.KEY_DOWN: if self.cursel >= self.numtorrents: return if not self._scroll_down(1): effected_lines = [self.cursel-2,self.cursel-1] elif c == curses.KEY_NPAGE: self._scroll_down(int(self.rows/2)) elif c == curses.KEY_HOME: self._scroll_up(self.cursel) elif c == curses.KEY_END: self._scroll_down(self.numtorrents-self.cursel) elif c == curses.KEY_RIGHT: # We enter a new mode for the selected torrent here tid = self.current_torrent_id() if tid: self.show_torrent_details(tid) return # Enter Key elif (c == curses.KEY_ENTER or c == 10) and self.numtorrents: if self.cursel not in self.marked: self.marked.append(self.cursel) self.last_mark = self.cursel torrent_actions_popup(self,self._selected_torrent_ids(),details=True) return else: if c > 31 and c < 256: if chr(c) == '/': self.search_string = "" self.cursor = 0 self.entering_search = True elif chr(c) == 'n' and self.search_string: self.__do_search() elif chr(c) == 'j': if not self._scroll_up(1): effected_lines = [self.cursel-1,self.cursel] elif chr(c) == 'k': if not self._scroll_down(1): effected_lines = [self.cursel-2,self.cursel-1] elif chr(c) == 'i': cid = self.current_torrent_id() if cid: def cb(): self.__torrent_info_id = None self.popup = Popup(self,"Info",close_cb=cb) self.popup.add_line("Getting torrent info...") self.__torrent_info_id = cid elif chr(c) == 'm': self._mark_unmark(self.cursel) effected_lines = [self.cursel-1] elif chr(c) == 'M': if self.last_mark >= 0: if (self.cursel+1) > self.last_mark: mrange = range(self.last_mark,self.cursel+1) else: mrange = range(self.cursel-1,self.last_mark) self.marked.extend(mrange[1:]) effected_lines = mrange else: self._mark_unmark(self.cursel) effected_lines = [self.cursel-1] elif chr(c) == 'c': self.marked = [] self.last_mark = -1 elif chr(c) == 'a': self._show_torrent_add_popup() elif chr(c) == 'f': self._show_torrent_filter_popup() elif chr(c) == 'h': self.popup = Popup(self,"Help",init_lines=self.__help_lines) elif chr(c) == 'p': self.show_preferences() return elif chr(c) == 'e': self.__show_events() return elif chr(c) == 'l': self.__legacy_mode() return self.refresh(effected_lines)
class QuickOpenPlugin(GObject.Object, Gedit.WindowActivatable): __gtype_name__ = "QuickOpenPlugin" window = GObject.property(type=Gedit.Window) def __init__(self): GObject.Object.__init__(self) def do_activate(self): self._popup_size = (450, 300) self._popup = None self._install_menu() def do_deactivate(self): self._uninstall_menu() def get_popup_size(self): return self._popup_size def set_popup_size(self, size): self._popup_size = size def _uninstall_menu(self): manager = self.window.get_ui_manager() manager.remove_ui(self._ui_id) manager.remove_action_group(self._action_group) manager.ensure_update() def _install_menu(self): manager = self.window.get_ui_manager() self._action_group = Gtk.ActionGroup(name="GeditQuickOpenPluginActions") self._action_group.add_actions([ ("QuickOpen", Gtk.STOCK_OPEN, _("Quick open"), '<Primary><Alt>o', _("Quickly open documents"), self.on_quick_open_activate) ]) manager.insert_action_group(self._action_group) self._ui_id = manager.add_ui_from_string(ui_str) def _create_popup(self): paths = [] # Open documents paths.append(CurrentDocumentsDirectory(self.window)) doc = self.window.get_active_document() # Current document directory if doc and doc.is_local(): gfile = doc.get_location() paths.append(gfile.get_parent()) # File browser root directory bus = self.window.get_message_bus() if bus.is_registered('/plugins/filebrowser', 'get_root'): msg = bus.send_sync('/plugins/filebrowser', 'get_root') if msg: gfile = msg.props.location if gfile and gfile.is_native(): paths.append(gfile) # Recent documents paths.append(RecentDocumentsDirectory()) # Local bookmarks for path in self._local_bookmarks(): paths.append(path) # Desktop directory desktopdir = self._desktop_dir() if desktopdir: paths.append(Gio.file_new_for_path(desktopdir)) # Home directory paths.append(Gio.file_new_for_path(os.path.expanduser('~'))) self._popup = Popup(self.window, paths, self.on_activated) self.window.get_group().add_window(self._popup) self._popup.set_default_size(*self.get_popup_size()) self._popup.set_transient_for(self.window) self._popup.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) self._popup.connect('destroy', self.on_popup_destroy) def _local_bookmarks(self): filename = os.path.expanduser('~/.gtk-bookmarks') if not os.path.isfile(filename): return [] paths = [] for line in file(filename, 'r').xreadlines(): uri = line.strip().split(" ")[0] f = Gio.file_new_for_uri(uri) if f.is_native(): try: info = f.query_info(Gio.FILE_ATTRIBUTE_STANDARD_TYPE, Gio.FileQueryInfoFlags.NONE, None) if info and info.get_file_type() == Gio.FileType.DIRECTORY: paths.append(f) except: pass return paths def _desktop_dir(self): config = os.getenv('XDG_CONFIG_HOME') if not config: config = os.path.expanduser('~/.config') config = os.path.join(config, 'user-dirs.dirs') desktopdir = None if os.path.isfile(config): for line in file(config, 'r').xreadlines(): line = line.strip() if line.startswith('XDG_DESKTOP_DIR'): parts = line.split('=', 1) desktopdir = os.path.expandvars(parts[1].strip('"').strip("'")) break if not desktopdir: desktopdir = os.path.expanduser('~/Desktop') return desktopdir # Callbacks def on_quick_open_activate(self, action, user_data=None): if not self._popup: self._create_popup() self._popup.show() def on_popup_destroy(self, popup, user_data=None): alloc = popup.get_allocation() self.set_popup_size((alloc.width, alloc.height)) self._popup = None def on_activated(self, gfile, user_data=None): Gedit.commands_load_location(self.window, gfile, None, -1, -1) return True
class Console: PROMPT = sys.ps1 PROCESS = sys.ps2 BANNER = ["Jython Completion Shell", InteractiveConsole.getDefaultBanner()] include_single_underscore_methods = False include_double_underscore_methods = False def __init__(self, namespace=None): """ Create a Jython Console. namespace is an optional and should be a dictionary or Map """ self.history = History(self) if namespace != None: self.locals = namespace else: self.locals = {} self.buffer = [] # buffer for multi-line commands self.interp = Interpreter(self, self.locals) sys.stdout = StdOutRedirector(self) self.text_pane = JTextPane(keyTyped = self.keyTyped, keyPressed = self.keyPressed) self.__initKeyMap() self.doc = self.text_pane.document self.__propertiesChanged() self.__inittext() self.initialLocation = self.doc.createPosition(self.doc.length-1) # Don't pass frame to popups. JWindows with null owners are not focusable # this fixes the focus problem on Win32, but make the mouse problem worse self.popup = Popup(None, self.text_pane) self.tip = Tip(None) # get fontmetrics info so we can position the popup metrics = self.text_pane.getFontMetrics(self.text_pane.getFont()) self.dotWidth = metrics.charWidth('.') self.textHeight = metrics.getHeight() # add some handles to our objects self.locals['console'] = self def insertText(self, text): """insert text at the current caret position""" # seems like there should be a better way to do this.... # might be better as a method on the text component? caretPosition = self.text_pane.getCaretPosition() self.text_pane.select(caretPosition, caretPosition) self.text_pane.replaceSelection(text) self.text_pane.setCaretPosition(caretPosition + len(text)) def getText(self): """get text from last line of console""" offsets = self.__lastLine() text = self.doc.getText(offsets[0], offsets[1]-offsets[0]) return text.rstrip() def getDisplayPoint(self): """Get the point where the popup window should be displayed""" screenPoint = self.text_pane.getLocationOnScreen() caretPoint = self.text_pane.caret.getMagicCaretPosition() # BUG: sometimes caretPoint is None # To duplicate type "java.aw" and hit '.' to complete selection while popup is visible x = screenPoint.getX() + caretPoint.getX() + self.dotWidth y = screenPoint.getY() + caretPoint.getY() + self.textHeight return Point(int(x),int(y)) def hide(self, event=None): """Hide the popup or tip window if visible""" if self.popup.visible: self.popup.hide() if self.tip.visible: self.tip.hide() def hideTip(self, event=None): self.tip.hide() self.insertText(')') def showTip(self, event=None): # get the display point before writing text # otherwise magicCaretPosition is None displayPoint = self.getDisplayPoint() if self.popup.visible: self.popup.hide() line = self.getText() self.insertText('(') (name, argspec, tip) = jintrospect.getCallTipJava(line, self.locals) if tip: self.tip.showTip(tip, displayPoint) def showPopup(self, event=None): """show code completion popup""" try: line = self.getText() list = jintrospect.getAutoCompleteList(line, self.locals, includeSingle=self.include_single_underscore_methods, includeDouble=self.include_double_underscore_methods) if len(list) > 0: self.popup.showMethodCompletionList(list, self.getDisplayPoint()) except Exception, e: print >> sys.stderr, "Error getting completion list: ", e
class WindowHelper: def __init__(self, window, plugin): self._window = window self._plugin = plugin self._popup = None self._install_menu() def deactivate(self): self._uninstall_menu() self._window = None self._plugin = None def update_ui(self): pass def _install_menu(self): manager = self._window.get_ui_manager() self._action_group = gtk.ActionGroup("GeditQuickHighlightModePluginActions") self._action_group.add_actions([( "QuickHighlightMode", gtk.STOCK_OPEN, _("Quick Highlight Mode"), "<Ctrl><Shift>H", _("Quickly switch between document syntax highlight modes"), self.on_lang_switcher_activate )]) manager.insert_action_group(self._action_group, -1) self._ui_id = manager.add_ui_from_string(ui_str) def _uninstall_menu(self): manager = self._window.get_ui_manager() manager.remove_ui(self._ui_id) manager.remove_action_group(self._action_group) manager.ensure_update() def _create_popup(self): self._popup = Popup(self._window, self.on_selected) self._popup.set_default_size(*self._plugin.get_popup_size()) self._popup.set_transient_for(self._window) self._popup.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self._window.get_group().add_window(self._popup) self._popup.connect("destroy", self._destroy_popup) def _destroy_popup(self, popup): alloc = popup.get_allocation() self._plugin.set_popup_size((alloc.width, alloc.height)) self._popup = None # Events def on_lang_switcher_activate(self, action): if not self._popup: self._create_popup() self._popup.show() def on_selected(self, lang): doc = self._window.get_active_document() doc.set_language(lang) return True
class Menu(object): def __init__(self, items, x, y, alwaysHighlight = False, delegate = None, *args, **kwargs): # activestyle = tk.None suppresses the box in OS X and underline elsewhere. defaults = {'activestyle': tk.NONE, 'borderwidth': 0, 'exportselection': False, # Approximate the colors used in OS X: 'selectbackground': '#0950CF', 'selectforeground': '#FFF', # Normally tk has a weird fake-3D effect - remove that. 'relief': tk.FLAT} self._popup = Popup(x = x, y = y) self._listbox = tk.Listbox(self._popup, *args, **dict(defaults, **kwargs)) self._listbox.pack() self.alwaysHighlight = alwaysHighlight self._priorSelection = None self.delegate = delegate self.items = items self._listbox.bind('<<ListboxSelect>>', self._selectionChanged) self._listbox.bind('<Return>', self.selectHighlighted) self._listbox.bind('<Button-1>', self.selectHighlighted) self._listbox.bind('<Enter>', self._snapHighlightToMouse) self._listbox.bind('<Motion>', self._snapHighlightToMouse) if not self.alwaysHighlight: self._listbox.bind('<Leave>', self.unhighlight) @property def items(self): return self.__items @items.setter def items(self, items): if items == getattr(self, '__items', None): return self._listbox['height'] = len(items) self._listbox['width' ] = max(len(item) for item in items) self.__items = items self._listbox.delete(0, tk.END) for item in items: self._listbox.insert(tk.END, str(item)) if self.alwaysHighlight: self._listbox.selection_set(0) self._selectionChanged() @property def columns(self): return self._listbox['width'] @columns.setter def columns(self, columns): self._listbox['width'] = columns def destroy(self): self._listbox.destroy() self._popup .destroy() def _snapHighlightToMouse(self, event): ''' This is a private method. Don't touch it. ''' self._setHighlight(self._listbox.nearest(event.y)) def _setHighlight(self, index): ''' This is a private method. Don't touch it. ''' self._listbox.selection_clear(0, tk.END) self._listbox.selection_set(index) self._selectionChanged() def unhighlight(self, *args): self._listbox.selection_clear(0, tk.END) def _selectionChanged(self, *args): ''' This is a private method. Don't touch it. ''' currentSelection = self.items[self._listbox.curselection()[0]] if currentSelection == self._priorSelection: return self._priorSelection = currentSelection self.onHighlight(currentSelection) def selectHighlighted(self, *args): ''' Triggers onSelect for the highlighted item. ''' self.onSelect(self.items[self._listbox.curselection()[0]]) def moveHighlight(self, amount): newIndex = self._listbox.curselection()[0] + amount newIndex = max(0, min(newIndex, len(self.items) - 1)) self._setHighlight(newIndex) def hide(self): self._popup.withdraw() def show(self): self._popup.deiconify() @event def onHighlight(self, item): pass @event def onSelect(self, item): pass
def _doRead(self): c = self.stdscr.getch() if self.popup: if self.popup.handle_read(c): self.popup = None self.refresh() return if c > 31 and c < 256: if chr(c) == 'Q': from twisted.internet import reactor if client.connected(): def on_disconnect(result): reactor.stop() client.disconnect().addCallback(on_disconnect) else: reactor.stop() return elif chr(c) == 'q': self.back_to_overview() return if c == 27 or c == curses.KEY_LEFT: self.back_to_overview() return if not self.torrent_state: # actions below only makes sense if there is a torrent state return # Navigate the torrent list if c == curses.KEY_UP: self.file_list_up() elif c == curses.KEY_PPAGE: pass elif c == curses.KEY_DOWN: self.file_list_down() elif c == curses.KEY_NPAGE: pass # Enter Key elif c == curses.KEY_ENTER or c == 10: self.marked[self.current_file[1]] = True self.show_priority_popup() # space elif c == 32: self.expcol_cur_file() else: if c > 31 and c < 256: if chr(c) == 'm': if self.current_file: self.__mark_unmark(self.current_file[1]) elif chr(c) == 'c': self.marked = {} elif chr(c) == 'a': torrent_actions_popup(self,[self.torrentid],details=False) return elif chr(c) == 'h': self.popup = Popup(self,"Help",init_lines=self.__help_lines) self.refresh()
class TorrentDetail(BaseMode, component.Component): def __init__(self, alltorrentmode, torrentid, stdscr, encoding=None): self.alltorrentmode = alltorrentmode self.torrentid = torrentid self.torrent_state = None self.popup = None self.messages = deque() self._status_keys = ["files", "name","state","download_payload_rate","upload_payload_rate", "progress","eta","all_time_download","total_uploaded", "ratio", "num_seeds","total_seeds","num_peers","total_peers", "active_time", "seeding_time","time_added","distributed_copies", "num_pieces", "piece_length","save_path","file_progress","file_priorities","message"] self._info_fields = [ ("Name",None,("name",)), ("State", None, ("state",)), ("Status",None,("message",)), ("Down Speed", format_utils.format_speed, ("download_payload_rate",)), ("Up Speed", format_utils.format_speed, ("upload_payload_rate",)), ("Progress", format_utils.format_progress, ("progress",)), ("ETA", deluge.common.ftime, ("eta",)), ("Path", None, ("save_path",)), ("Downloaded",deluge.common.fsize,("all_time_download",)), ("Uploaded", deluge.common.fsize,("total_uploaded",)), ("Share Ratio", lambda x:x < 0 and "∞" or "%.3f"%x, ("ratio",)), ("Seeders",format_utils.format_seeds_peers,("num_seeds","total_seeds")), ("Peers",format_utils.format_seeds_peers,("num_peers","total_peers")), ("Active Time",deluge.common.ftime,("active_time",)), ("Seeding Time",deluge.common.ftime,("seeding_time",)), ("Date Added",deluge.common.fdate,("time_added",)), ("Availability", lambda x:x < 0 and "∞" or "%.3f"%x, ("distributed_copies",)), ("Pieces", format_utils.format_pieces, ("num_pieces","piece_length")), ] self.file_list = None self.current_file = None self.current_file_idx = 0 self.file_limit = maxint self.file_off = 0 self.more_to_draw = False self.column_string = "" self.files_sep = None self.marked = {} BaseMode.__init__(self, stdscr, encoding) component.Component.__init__(self, "TorrentDetail", 1, depend=["SessionProxy"]) self.__split_help() self.column_names = ["Filename", "Size", "Progress", "Priority"] self.__update_columns() component.start(["TorrentDetail"]) curses.curs_set(0) self.stdscr.notimeout(0) # component start/update def start(self): component.get("SessionProxy").get_torrent_status(self.torrentid, self._status_keys).addCallback(self.set_state) def update(self): component.get("SessionProxy").get_torrent_status(self.torrentid, self._status_keys).addCallback(self.set_state) def set_state(self, state): log.debug("got state") need_prio_update = False if not self.file_list: # don't keep getting the files once we've got them once if state.get("files"): self.files_sep = "{!green,black,bold,underline!}%s"%(("Files (torrent has %d files)"%len(state["files"])).center(self.cols)) self.file_list,self.file_dict = self.build_file_list(state["files"],state["file_progress"],state["file_priorities"]) self._status_keys.remove("files") else: self.files_sep = "{!green,black,bold,underline!}%s"%(("Files (File list unknown)").center(self.cols)) need_prio_update = True self.__fill_progress(self.file_list,state["file_progress"]) for i,prio in enumerate(state["file_priorities"]): if self.file_dict[i][6] != prio: need_prio_update = True self.file_dict[i][6] = prio if need_prio_update: self.__fill_prio(self.file_list) del state["file_progress"] del state["file_priorities"] self.torrent_state = state self.refresh() def __split_help(self): self.__help_lines = format_utils.wrap_string(HELP_STR,(self.cols/2)-2) # split file list into directory tree. this function assumes all files in a # particular directory are returned together. it won't work otherwise. # returned list is a list of lists of the form: # [file/dir_name,index,size,children,expanded,progress,priority] # for directories index values count down from maxint (for marking usage), # for files the index is the value returned in the # state object for use with other libtorrent calls (i.e. setting prio) # # Also returns a dictionary that maps index values to the file leaves # for fast updating of progress and priorities def build_file_list(self, file_tuples,prog,prio): ret = [] retdict = {} diridx = maxint for f in file_tuples: cur = ret ps = f["path"].split("/") fin = ps[-1] for p in ps: if not cur or p != cur[-1][0]: cl = [] if p == fin: ent = [p,f["index"],f["size"],cl,False, format_utils.format_progress(prog[f["index"]]*100), prio[f["index"]]] retdict[f["index"]] = ent else: ent = [p,diridx,-1,cl,False,0,-1] retdict[diridx] = ent diridx-=1 cur.append(ent) cur = cl else: cur = cur[-1][3] self.__build_sizes(ret) self.__fill_progress(ret,prog) return (ret,retdict) # fill in the sizes of the directory entries based on their children def __build_sizes(self, fs): ret = 0 for f in fs: if f[2] == -1: val = self.__build_sizes(f[3]) ret += val f[2] = val else: ret += f[2] return ret # fills in progress fields in all entries based on progs # returns the # of bytes complete in all the children of fs def __fill_progress(self,fs,progs): if not progs: return 0 tb = 0 for f in fs: if f[3]: # dir, has some children bd = self.__fill_progress(f[3],progs) f[5] = format_utils.format_progress((bd/f[2])*100) else: # file, update own prog and add to total bd = f[2]*progs[f[1]] f[5] = format_utils.format_progress(progs[f[1]]*100) tb += bd return tb def __fill_prio(self,fs): for f in fs: if f[3]: # dir, so fill in children and compute our prio self.__fill_prio(f[3]) s = set([e[6] for e in f[3]]) # pull out all child prios and turn into a set if len(s) > 1: f[6] = -2 # mixed else: f[6] = s.pop() def __update_columns(self): self.column_widths = [-1,15,15,20] req = sum(filter(lambda x:x >= 0,self.column_widths)) if (req > self.cols): # can't satisfy requests, just spread out evenly cw = int(self.cols/len(self.column_names)) for i in range(0,len(self.column_widths)): self.column_widths[i] = cw else: rem = self.cols - req var_cols = len(filter(lambda x: x < 0,self.column_widths)) vw = int(rem/var_cols) for i in range(0, len(self.column_widths)): if (self.column_widths[i] < 0): self.column_widths[i] = vw self.column_string = "{!green,black,bold!}%s"%("".join(["%s%s"%(self.column_names[i]," "*(self.column_widths[i]-len(self.column_names[i]))) for i in range(0,len(self.column_names))])) def report_message(self,title,message): self.messages.append((title,message)) def clear_marks(self): self.marked = {} def set_popup(self,pu): self.popup = pu self.refresh() def draw_files(self,files,depth,off,idx): for fl in files: # kick out if we're going to draw too low on the screen if (off >= self.rows-1): self.more_to_draw = True return -1,-1 self.file_limit = idx if idx >= self.file_off: # set fg/bg colors based on if we are selected/marked or not # default values fg = "white" bg = "black" if fl[1] in self.marked: bg = "blue" if idx == self.current_file_idx: self.current_file = fl bg = "white" if fl[1] in self.marked: fg = "blue" else: fg = "black" color_string = "{!%s,%s!}"%(fg,bg) #actually draw the dir/file string if fl[3] and fl[4]: # this is an expanded directory xchar = 'v' elif fl[3]: # collapsed directory xchar = '>' else: # file xchar = '-' r = format_utils.format_row(["%s%s %s"%(" "*depth,xchar,fl[0]), deluge.common.fsize(fl[2]),fl[5], format_utils.format_priority(fl[6])], self.column_widths) self.add_string(off,"%s%s"%(color_string,r),trim=False) off += 1 if fl[3] and fl[4]: # recurse if we have children and are expanded off,idx = self.draw_files(fl[3],depth+1,off,idx+1) if off < 0: return (off,idx) else: idx += 1 return (off,idx) def on_resize(self, *args): BaseMode.on_resize_norefresh(self, *args) self.__update_columns() self.__split_help() if self.popup: self.popup.handle_resize() self.refresh() def refresh(self,lines=None): # show a message popup if there's anything queued if self.popup == None and self.messages: title,msg = self.messages.popleft() self.popup = MessagePopup(self,title,msg) # Update the status bars self.stdscr.clear() self.add_string(0,self.statusbars.topbar) hstr = "%sPress [h] for help"%(" "*(self.cols - len(self.statusbars.bottombar) - 10)) self.add_string(self.rows - 1, "%s%s"%(self.statusbars.bottombar,hstr)) if self.files_sep: self.add_string((self.rows/2)-1,self.files_sep) off = 1 if self.torrent_state: for f in self._info_fields: if off >= (self.rows/2): break if f[1] != None: args = [] try: for key in f[2]: args.append(self.torrent_state[key]) except: log.debug("Could not get info field: %s",e) continue info = f[1](*args) else: info = self.torrent_state[f[2][0]] self.add_string(off,"{!info!}%s: {!input!}%s"%(f[0],info)) off += 1 else: self.add_string(1, "Waiting for torrent state") off = self.rows/2 self.add_string(off,self.column_string) if self.file_list: off += 1 self.more_to_draw = False self.draw_files(self.file_list,0,off,0) #self.stdscr.redrawwin() self.stdscr.noutrefresh() if self.popup: self.popup.refresh() curses.doupdate() # expand or collapse the current file def expcol_cur_file(self): self.current_file[4] = not self.current_file[4] self.refresh() def file_list_down(self): if (self.current_file_idx + 1) > self.file_limit: if self.more_to_draw: self.current_file_idx += 1 self.file_off += 1 else: return else: self.current_file_idx += 1 self.refresh() def file_list_up(self): self.current_file_idx = max(0,self.current_file_idx-1) self.file_off = min(self.file_off,self.current_file_idx) self.refresh() def back_to_overview(self): component.stop(["TorrentDetail"]) component.deregister(self) self.stdscr.clear() component.get("ConsoleUI").set_mode(self.alltorrentmode) self.alltorrentmode.resume() # build list of priorities for all files in the torrent # based on what is currently selected and a selected priority. def build_prio_list(self, files, ret_list, parent_prio, selected_prio): # has a priority been set on my parent (if so, I inherit it) for f in files: if f[3]: # dir, check if i'm setting on whole dir, then recurse if f[1] in self.marked: # marked, recurse and update all children with new prio parent_prio = selected_prio self.build_prio_list(f[3],ret_list,parent_prio,selected_prio) parent_prio = -1 else: # not marked, just recurse self.build_prio_list(f[3],ret_list,parent_prio,selected_prio) else: # file, need to add to list if f[1] in self.marked or parent_prio >= 0: # selected (or parent selected), use requested priority ret_list.append((f[1],selected_prio)) else: # not selected, just keep old priority ret_list.append((f[1],f[6])) def do_priority(self, idx, data): plist = [] self.build_prio_list(self.file_list,plist,-1,data) plist.sort() priorities = [p[1] for p in plist] log.debug("priorities: %s", priorities) client.core.set_torrent_file_priorities(self.torrentid, priorities) if len(self.marked) == 1: self.marked = {} return True # show popup for priority selections def show_priority_popup(self): if self.marked: self.popup = SelectablePopup(self,"Set File Priority",self.do_priority) self.popup.add_line("_Do Not Download",data=deluge.common.FILE_PRIORITY["Do Not Download"]) self.popup.add_line("_Normal Priority",data=deluge.common.FILE_PRIORITY["Normal Priority"]) self.popup.add_line("_High Priority",data=deluge.common.FILE_PRIORITY["High Priority"]) self.popup.add_line("H_ighest Priority",data=deluge.common.FILE_PRIORITY["Highest Priority"]) def __mark_unmark(self,idx): if idx in self.marked: del self.marked[idx] else: self.marked[idx] = True def _doRead(self): c = self.stdscr.getch() if self.popup: if self.popup.handle_read(c): self.popup = None self.refresh() return if c > 31 and c < 256: if chr(c) == 'Q': from twisted.internet import reactor if client.connected(): def on_disconnect(result): reactor.stop() client.disconnect().addCallback(on_disconnect) else: reactor.stop() return elif chr(c) == 'q': self.back_to_overview() return if c == 27 or c == curses.KEY_LEFT: self.back_to_overview() return if not self.torrent_state: # actions below only makes sense if there is a torrent state return # Navigate the torrent list if c == curses.KEY_UP: self.file_list_up() elif c == curses.KEY_PPAGE: pass elif c == curses.KEY_DOWN: self.file_list_down() elif c == curses.KEY_NPAGE: pass # Enter Key elif c == curses.KEY_ENTER or c == 10: self.marked[self.current_file[1]] = True self.show_priority_popup() # space elif c == 32: self.expcol_cur_file() else: if c > 31 and c < 256: if chr(c) == 'm': if self.current_file: self.__mark_unmark(self.current_file[1]) elif chr(c) == 'c': self.marked = {} elif chr(c) == 'a': torrent_actions_popup(self,[self.torrentid],details=False) return elif chr(c) == 'h': self.popup = Popup(self,"Help",init_lines=self.__help_lines) self.refresh()