def _sync_children(self): from list import List from preferences import Preferences Preferences.sync() List.sync() User.sync()
class GUI: def __init__(self): """Initializes the window and create pointers for all the important widgets. This function also runs some code to add functionality. """ # Initialize the window and several other objects in the instance self.initialize_window() # Properties instance to handle the preferences window self.preferences = Preferences(self.main_window) # Now setup the variables needed for file access try: self.setup_file_access() except Exception, e: # In case of error, the user must change the preferences log(e.__class__.__name__) log(e) self.preferences.run() self.setup_file_access() self.modified = set() # Store the names of the modified files # The next variable takes care of each file by holding the choices made for # it. The values of the dictionary are Annotator objects, where information # about the annotations made in the file self.results = {} # This flag determines whether signal handling should take place. It is True # when the interface is being adjusted programatically self.backend = False
def testSaveLoad(self): prefs = Preferences('prefstest.conf') self.assertEqual(None, prefs.btDevice) self.assertEqual('bluetooth', prefs.connectionMethod) self.assertEqual('', prefs.customDevice) self.assertEqual(0, prefs.gammuIndex) prefs.btDevice = BluetoothDevice('00:00:00:00', 42, 'deviceName', 'serviceName') prefs.connectionMethod = 'connection' prefs.customDevice = '/dev/rfcomm0' prefs.gammuIndex = 2 prefs.save() prefsLoaded = Preferences('prefstest.conf') prefsLoaded.load() self.assertNotEqual(None, prefsLoaded.btDevice, "Device has not been loaded") self.assertEqual('00:00:00:00', prefsLoaded.btDevice.address) self.assertEqual(42, prefsLoaded.btDevice.port) self.assertEqual('deviceName', prefsLoaded.btDevice.deviceName) self.assertEqual('serviceName', prefsLoaded.btDevice.serviceName) self.assertEqual('connection', prefsLoaded.connectionMethod) self.assertEqual('/dev/rfcomm0', prefsLoaded.customDevice) self.assertEqual(2, prefsLoaded.gammuIndex)
class Main: def __init__(self): pygame.init() pygame.display.init() pygame.font.init() self.screen_w = pygame.display.Info().current_w self.screen_h = pygame.display.Info().current_h self.w = int(self.screen_h * 1.2) self.h = int(self.screen_h * 0.8) self.preferences = Preferences() self.fullscreen = self.preferences.get("fullscreen") self.go_mode() pygame.mouse.set_visible(False) pygame.display.set_caption(Constants.CAPTION) def go_mode(self): if self.fullscreen: self.mode = (self.screen_w, self.screen_h) if not self.mode in pygame.display.list_modes(): self.mode = pygame.display.list_modes()[0] self.screen = pygame.display.set_mode(self.mode, pygame.FULLSCREEN) else: self.mode = (self.w, self.h) self.screen = pygame.display.set_mode(self.mode) self.unit = int(self.mode[1] / Constants.UNITS) def main(self): self.boot_screen() while True: if not self.title_screen(): break if self.preferences.edit_flag: self.preferences.save() fullscreen = self.preferences.get("fullscreen") if self.fullscreen != fullscreen: self.fullscreen = fullscreen self.go_mode() else: self.play_game() def boot_screen(self): bs = BootScreen(self.screen, self.unit) bs.main() return bs.running def title_screen(self): self.go_mode() ts = TitleScreen(self.screen, self.unit, self.preferences) ts.main() return ts.running def play_game(self): gm = Game(self.screen, self.unit, self.preferences) gm.main() return gm.running
def write(domain, key, value=None, user=kCFPreferencesCurrentUser, host=kCFPreferencesAnyHost): """Writes value as the value for key in domain, also accepts a dictionary of multiple key_value pairs to write""" domain = Preferences(domain, user, host) if type(key) is dict: domain.set_multiple(key) elif value is not None: domain[key] = value
def delete(domain, key=None, user=kCFPreferencesCurrentUser, host=kCFPreferencesAnyHost): """Removes the default named key from domain, also accepts a list of keys to remove""" domain = Preferences(domain, user, host) if type(key) is list: domain.delete_multiple(key) else: del domain[key]
def on_actionPreferences_triggered(self): '''Display preferences dialog. ''' prefs = Preferences(self.book_manager, parent=self) #prefs.setModal(True) #prefs.show() prefs.exec_() self.reload_books_list() self.reload_search_menu()
def signInIfNecessary(parent=None): """Sign into SRS Collector, and return the API key.""" apiKey = Preferences.apiKey() if not apiKey: dialog = SignInDialog() dialog.exec_() apiKey = dialog.apiKey if apiKey: Preferences.setApiKey(apiKey) return apiKey
def read(domain, key=None, default=None, user=kCFPreferencesCurrentUser, host=kCFPreferencesAnyHost): """Prints the value for the default of domain identified by key, also accepts a list of keys""" domain = Preferences(domain, user, host) if key is None: return domain if type(key) is list: return domain.get_multiple(key) return domain[key]
def _do_load(self): self.load_config() component.get("TorrentView").add_text_column(DISPLAY_NAME, col_type=[str, str], status_field=[STATUS_NAME, STATUS_ID]) component.get("TorrentView").treeview.connect( "button-press-event", self.on_tv_button_press) self.menu = self._create_context_menu() self.sep = component.get("MenuBar").add_torrentmenu_separator() component.get("MenuBar").torrentmenu.append(self.menu) self.label_sidebar = LabelSidebar() self.preferences = Preferences() self.add_torrent_ext = AddTorrentExt() self.enable_dnd() self.status_item = None self.initialized = True
def importCards(): """Import cards from the server.""" apiKey = SignInDialog.signInIfNecessary() if apiKey: try: Importer().run(apiKey) except UpgradeRequiredException: showInfo("Please upgrade your copy of the SRS Collector addon.") except urllib2.HTTPError as e: if e.code == 401: Preferences.setApiKey(None) showInfo("Sign in expired. Please try again.") else: showInfo("Unknown network error.") except urllib2.URLError: # Generally a DNS error. showInfo("Network error. Are you online?")
class RhythmWeb(rb.Plugin, Loggable): config = None preferences = None def __init__(self): base_path = os.path.dirname(__file__) config_path = os.path.join(base_path, 'cfg', 'rb-serve.conf') config = Configuration() config.load_configuration(config_path) serve.log.get_factory().configure(config) self.base_path = base_path self.config = config self.config_path = config_path resource_path = os.path.join(base_path, 'resources') config.put('*resources', resource_path) def activate(self, shell): config = self.config config.print_configuration(self) rbhandler = RBHandler(shell) components = {'config' : config, 'RB' : rbhandler} application = CGIApplication('RhythmWeb', self.base_path, components) server = CGIServer(application, config) server.start() shell.server = server self.preferences = Preferences(config, self.config_path) def deactivate(self, shell): if not shell.server is None: shell.server.stop() del shell.server del self.config del self.config_path del self.base_path if not self.preferences.button == None: self.preferences.button.disconnect(self.connect_id_pref2) del self.preferences def create_configure_dialog(self, dialog=None): dialog = self.preferences.show_dialog() self.connect_id_pref2 = self.preferences.button.connect('clicked', lambda x: dialog.destroy() ) return dialog
def on_preferences_activated(self, event=None): """Raises the preferences dialog. If it's already open, it's focused""" if self._preferences_dialog is not None: self._preferences_dialog.present() return self._preferences_dialog = Preferences(self) self._preferences_dialog.run() self._preferences_dialog = None
def __init__(self): pygame.init() #get preferences self.preferences = Preferences() # self.nickname = raw_input('Choose a username: '******'Choose a color (red, green, blue, yellow, white): ') #resolution, flags, depth, display self.unit=Constants.RESOLUTION[0]/Constants.UNITS self.banner = Banner() self.score_width=self.unit*15 if self.preferences.fullscreen: self.screen = pygame.display.set_mode((Constants.RESOLUTION[0]+self.score_width,\ Constants.RESOLUTION[1]),pygame.FULLSCREEN) else: self.screen = pygame.display.set_mode((Constants.RESOLUTION[0]+self.score_width,\ Constants.RESOLUTION[1]),0,32) pygame.display.set_caption(Constants.CAPTION) #game area surface self.gamescreen = pygame.Surface(Constants.RESOLUTION) #score area rectangle surface self.scorescreen = pygame.Surface((self.score_width,Constants.RESOLUTION[1])) #Snake and foods manager self.me=Snake(color=pygame.color.THECOLORS[self.preferences.get("color")],\ nickname=self.preferences.get("nickname")) self.f=Foods() self.others = {} #Score manager self.scores=Scores((self.score_width,Constants.RESOLUTION[1])) #add our own score, the server will send us the remaining one at connection self.scores.new_score(self.preferences.get("nickname"),\ pygame.color.THECOLORS[self.preferences.get("color")]) #game area background color self.gamescreen.fill(Constants.COLOR_BG) self.scorescreen.fill((100,100,100)) #timers self.clock=pygame.time.Clock(); self.current_time=0 self.move_snake_timer=Timer(1.0/Constants.SNAKE_SPEED*1000,self.current_time,periodic=True) self.blink_snake_timer=Timer(1.0/Constants.SNAKE_BLINKING_SPEED*1000,self.current_time,periodic=True) self.blink_banner_timer=Timer(500,self.current_time,periodic=True) self.new_apple_timer=Timer(Constants.NEW_APPLE_PERIOD*1000,self.current_time,periodic=True)
def __init__(self, photolist, photoframe): self.gui = Gtk.Builder() self.gui.add_from_file(os.path.join(constants.SHARED_DATA_DIR, 'menu.ui')) self.photoimage = photoframe.photoimage self.photolist = photolist self.preferences = Preferences(photolist) self.about = AboutDialog() self.is_show = False
def OnOpen(self, event): # get a valid path from user dirDialog = wx.DirDialog(self, "Choose a directory for open:", \ style=wx.DD_DEFAULT_STYLE) if platform.system() == 'Windows': dirDialog.SetPath('D:\\Projects\\treeseal-example') # TESTING else: dirDialog.SetPath('/home/phil/Projects/treeseal-example') # TESTING if dirDialog.ShowModal() == wx.ID_OK: self.UpdateRootDir(dirDialog.GetPath()) else: self.UpdateRootDir(None) return # check pre-conditions if not os.path.exists(self.metaDir): wx.MessageBox('Path "' + self.rootDir + '" is no valid root dir.', \ 'Error', wx.OK | wx.ICON_ERROR) self.UpdateRootDir(None) return if not os.path.exists(self.dbFile): wx.MessageBox('Cannot find database file "' + self.dbFile + '".', \ 'Error', wx.OK | wx.ICON_ERROR) self.UpdateRootDir(None) return if not os.path.exists(self.sigFile): dial = wx.MessageBox('Cannot find database signature file "' + self.sigFile + '".\n\nUse database without verification?', \ 'Warning', wx.YES_NO | wx.ICON_WARNING | wx.NO_DEFAULT) if not dial == wx.YES: self.UpdateRootDir(None) return else: cs = Checksum() cs.calculateForFile(self.dbFile) if not cs.isValidUsingSavedFile(self.sigFile): dial = wx.MessageBox('Database or database signature file have been corrupted.\n\nUse database without verification?', \ 'Warning', wx.YES_NO | wx.ICON_WARNING | wx.NO_DEFAULT) if not dial == wx.YES: self.UpdateRootDir(None) return # close eventually existing previous instance self.list.ClearInstance() self.SetStatusBarText() # load preferences or create default ones self.preferences = Preferences() if os.path.exists(self.preferencesFile): self.preferences.load(self.preferencesFile) else: self.preferences.save(self.preferencesFile)
def activate(self, shell): config = self.config config.print_configuration(self) rbhandler = RBHandler(shell) components = {'config' : config, 'RB' : rbhandler} application = CGIApplication('RhythmWeb', self.base_path, components) server = CGIServer(application, config) server.start() shell.server = server self.preferences = Preferences(config, self.config_path)
def __init__(self): pygame.init() pygame.display.init() pygame.font.init() self.screen_w = pygame.display.Info().current_w self.screen_h = pygame.display.Info().current_h self.w = int(self.screen_h * 1.2) self.h = int(self.screen_h * 0.8) self.preferences = Preferences() self.fullscreen = self.preferences.get("fullscreen") self.go_mode() pygame.mouse.set_visible(False) pygame.display.set_caption(Constants.CAPTION)
def home(request): context = RequestContext(request) context_dict = get_context_dict(request) menu_path = os.path.join(conf.settings.PROJECT_ROOT, 'menu.txt') menu = MenuParser(menu_path) menu = menu.parse_menu() preferences = context_dict['userprofile'].preferences preferences = Preferences.createFromString(preferences) matches = menu.match_with(preferences) html = "" for item in matches.get_items(): # TODO: make menu object iterable html += "<div style='margin-bottom: 4px; width: 400px; float left;'>" html += "<font style='text-decoration: underline;'>"+item.name+"</font><font color='black'> for "+item.meal+" @ "+item.location+"</font>" html += "</div>" context_dict['matches'] = html return render_to_response("foodfinder/home.html", context_dict, context)
def confirm_and_reset_defaults(self, widget): if utilityFunctions.decision_popup(self.parent, 'Reset appearance to defaults?', 'Are you sure you want to reset your appearance preferences to default values?'): self.choices = Preferences.default_appearance_preferences() # Visual Effects # Set the view combo box to "Double" which is the second entry model = self.view_box.get_model() self.view_box.set_active_iter(model.iter_next(model.get_iter_first())) # Set the font buttons to display the default font values for fb, fi in zip(self.font_buttons, self.font_idents): fb.set_font_name(self.choices[fi]) fb.emit("font_set") # Set the color buttons to display the default color values for cb, ci in zip(self.color_buttons, self.color_idents): cb.set_rgba(utilityFunctions.string_to_RGBA(self.choices[ci]))
def __init__(self): appdata = str(QDesktopServices.storageLocation(QDesktopServices.DataLocation)) MusicGuruBase.__init__(self, appdata) ApplicationBase.__init__(self) if not op.exists(appdata): os.makedirs(appdata) logging.basicConfig(filename=op.join(appdata, 'debug.log'), level=logging.WARNING) self.prefs = Preferences() self.prefs.load() self.selectedBoardItems = [] self.selectedLocation = None self.mainWindow = MainWindow(app=self) self.locationsPanel = LocationsPanel(app=self) self.detailsPanel = DetailsPanel(app=self) self.ignoreBox = IgnoreBox(app=self) self.progress = Progress(self.mainWindow) self.aboutBox = AboutBox(self.mainWindow, self) self.connect(self.progress, SIGNAL('finished(QString)'), self.jobFinished) self.connect(self, SIGNAL('applicationFinishedLaunching()'), self.applicationFinishedLaunching)
def __init__(self): """Initializes the window and create pointers for all the important widgets. This function also runs some code to add functionality. """ # Initialize the window and several other objects in the instance self.initialize_window() # Properties instance to handle the preferences window self.preferences = Preferences(self.main_window) # Now setup the variables needed for file access try: self.setup_file_access() except Exception, e: # In case of error, the user must change the preferences log(e.__class__.__name__) log(e) self.preferences.run() self.setup_file_access()
def _do_load(self): self._config = deluge.configmanager.ConfigManager( GTKUI_CONFIG, defaults=GTKUI_DEFAULTS) component.get("TorrentView").add_text_column(DISPLAY_NAME, status_field=[STATUS_NAME]) self.label_selection_menu = LabelSelectionMenu() self.sep = component.get("MenuBar").add_torrentmenu_separator() component.get("MenuBar").torrentmenu.append(self.label_selection_menu) self.label_sidebar = LabelSidebar() self.preferences = Preferences() self.add_torrent_ext = AddTorrentExt() self.enable_dnd() self.initialized = True
def __init__(self): super(App, self).__init__("HipStatus") self.icon = _menu_bar_icon(0) self.preferences = Preferences() self._validate_preferences() self.keychain = Keychain(self.preferences.email()) self._validate_keychain() self.hipchat = HipChat(self.keychain.read_token()) self.office365 = Office365(self.preferences.email(), self.keychain.read_o365()) self.menu_pause_button = rumps.MenuItem("Pause HipStatus", self.timer_pause) self.menu_preferences = rumps.MenuItem('Preferences...') self.menu = [self.menu_pause_button, rumps.separator, self.menu_preferences, rumps.separator] self.menu_preferences_message = rumps.MenuItem("", self.preferences_message) if self.preferences.default_message(): self.menu_preferences_message.title = self.preferences.default_message() else: self.menu_preferences_message.title = "None..." self.menu_preferences_email = rumps.MenuItem("Change email address", self.preferences_update_email) self.menu_preferences_o365 = rumps.MenuItem("Update saved Office 365 password", self.preferences_update_o365) self.menu_preferences_token = rumps.MenuItem("Update saved HipChat token", self.preferences_update_token) self.menu_preferences_get_token = rumps.MenuItem("Get your HipChat token", open_browser) self.menu_preferences.add(rumps.MenuItem('Status message...')) self.menu_preferences.add(self.menu_preferences_message) self.menu_preferences.add(rumps.separator) self.menu_preferences.add(rumps.MenuItem('Preferences...')) self.menu_preferences.add(self.menu_preferences_email) self.menu_preferences.add(self.menu_preferences_o365) self.menu_preferences.add(self.menu_preferences_token) self.menu_preferences.add(rumps.separator) self.menu_preferences.add(self.menu_preferences_get_token) self.main_timer = rumps.Timer(self.timer_trigger, 300) self.main_timer.start()
class App(rumps.App): """This is the main class that runs the HipStatus app""" def __init__(self): super(App, self).__init__("HipStatus") self.icon = _menu_bar_icon(0) self.preferences = Preferences() self._validate_preferences() self.keychain = Keychain(self.preferences.email()) self._validate_keychain() self.hipchat = HipChat(self.keychain.read_token()) self.office365 = Office365(self.preferences.email(), self.keychain.read_o365()) self.menu_pause_button = rumps.MenuItem("Pause HipStatus", self.timer_pause) self.menu_preferences = rumps.MenuItem('Preferences...') self.menu = [self.menu_pause_button, rumps.separator, self.menu_preferences, rumps.separator] self.menu_preferences_message = rumps.MenuItem("", self.preferences_message) if self.preferences.default_message(): self.menu_preferences_message.title = self.preferences.default_message() else: self.menu_preferences_message.title = "None..." self.menu_preferences_email = rumps.MenuItem("Change email address", self.preferences_update_email) self.menu_preferences_o365 = rumps.MenuItem("Update saved Office 365 password", self.preferences_update_o365) self.menu_preferences_token = rumps.MenuItem("Update saved HipChat token", self.preferences_update_token) self.menu_preferences_get_token = rumps.MenuItem("Get your HipChat token", open_browser) self.menu_preferences.add(rumps.MenuItem('Status message...')) self.menu_preferences.add(self.menu_preferences_message) self.menu_preferences.add(rumps.separator) self.menu_preferences.add(rumps.MenuItem('Preferences...')) self.menu_preferences.add(self.menu_preferences_email) self.menu_preferences.add(self.menu_preferences_o365) self.menu_preferences.add(self.menu_preferences_token) self.menu_preferences.add(rumps.separator) self.menu_preferences.add(self.menu_preferences_get_token) self.main_timer = rumps.Timer(self.timer_trigger, 300) self.main_timer.start() def _validate_preferences(self): if not self.preferences.email().strip(): logging.warning("No email address on record in preferences") self.preferences_update_email(None) def _validate_keychain(self): try: self.keychain.read_o365() except KeychainValueNotFound: logging.warning("Office 365 password not found") self.keychain.write_o365("Enter Password") self.preferences_update_o365(None, menu_call=False) try: self.keychain.read_token() except KeychainValueNotFound: logging.warning("HipChat API token not found") self.keychain.write_token("Enter Token") self.preferences_update_token(None, menu_call=False) @rumps.notifications def notification_center(self, info): logging.debug("Notification has been clicked") if 'update_o365' in info: self.preferences_update_o365(None) elif 'update_token' in info: self.preferences_update_token(None) elif 'update_email' in info: self.preferences_update_email(None) elif 'open_ticket' in info: webbrowser.open(info['open_ticket']) else: pass def preferences_message(self, sender): text = self.preferences.default_message() if text is None: text = '' prompt = rumps.Window("Leave blank to not set a status message", "Enter a message to display when you are set to 'Do not disturb'", text, dimensions=(275, 25)) result = prompt.run() self.preferences.default_message(result.text) if self.preferences.default_message(): self.menu_preferences_message.title = self.preferences.default_message() else: self.menu_preferences_message.title = "None..." def preferences_update_email(self, sender): text = self.preferences.email() logging.info("Prompting for new email") prompt = rumps.Window("", "Enter your email address", text, dimensions=(275, 25)) result = prompt.run() self.preferences.email(result.text) def preferences_update_o365(self, sender, message="", menu_call=True): text = self.keychain.read_o365() logging.info("Prompting for Office 365 password...") prompt = SecureRumpsWindow(message, "Enter your Office 365 password:"******"", menu_call=True): text = self.keychain.read_token() message = "Paste your key using Ctrl+Click on the text field" logging.info("Prompting for HipChat API token...") prompt = rumps.Window(message, "Enter your HipChat API token:", text, dimensions=(375, 25)) prompt.add_button('Get HipChat token...') result = prompt.run() if result.clicked == 2: open_browser() self.preferences_update_token(None, "Log into HipChat in the browser to copy your token, paste using " "Ctrl+Click on the text field", menu_call=menu_call) else: token = result.text self.keychain.write_token(token) if menu_call: self.hipchat.update_token(self.keychain.read_token()) def timer_pause(self, sender): if not sender.state: self.icon = _menu_bar_icon(1) sender.title = "Resume HipStatus" logging.info("User has paused HipStatus") else: self.icon = _menu_bar_icon(0) sender.title = "Pause HipStatus" logging.info("User has resumed HipStatus") sender.state = not sender.state def timer_trigger(self, sender): now = datetime.datetime.now() delta = (5 - (now.minute % 5)) * 60 - now.second logging.debug("Timer will execute in {} seconds".format(delta)) t = threading.Thread(target=self._update_status, args=[delta]) t.start() def _update_status(self, delay): time.sleep(delay) if self.menu_pause_button.state: logging.info("HipStatus is paused: status will not be updated") return now = datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") try: hipchat_user = self.hipchat.get_status(self.preferences.email()) except Unauthorized: rumps.notification("Authentication error to HipChat",'', "It looks like something may be wrong with your API token. Click here to update, or use " "the 'Preferences...' menu option.", data={'update_token': ''}) return except UserNotFound: rumps.notification("Could not find the user in HipChat", self.preferences.email(), "Your saved email address could not be found in HipChat. Click here to update, or use " "the 'Preferences...' menu option.", data={'update_email': ''}) return except (RateLimited, ServerError, ServiceUnavailable): rumps.notification("There seems to be a problem with HipChat", '', "There was an error indicating an issue " "on HipChat's end. If the issue persists click here to open an IT Help ticket.", data={'open_ticket': ticket_url}) return if not hipchat_user['presence']: logging.info("The user is not online") return busy_hipstatus = True if hipchat_user['presence']['show'] != 'chat' else False try: office365_calendar = self.office365.calendar_status(now) except Unauthorized: rumps.notification("Authentication error to Office 365", '', "Something may be wrong with your Office 365 email address/password. Click here to try " "updating your password.", data={'update_o365': ''}) return except ServerError: rumps.notification("There seems to be a problem with Office 365", '', "There was an error indicating an " "issue on Office 365's end. If the issue persists click here to open an IT Help ticket.", data={'open_ticket': ticket_url}) return if office365_calendar['value']: busy_office365 = True if office365_calendar['value'][0]['ShowAs'] == 'Busy' else False else: busy_office365 = False if busy_hipstatus == busy_office365: logging.info("Status unchanged") return message = '' update_data = { 'name': hipchat_user['name'], 'email': hipchat_user['email'], 'mention_name': hipchat_user['mention_name'], 'title': hipchat_user['title'], 'timezone': self.preferences.timezone(), 'is_group_admin': hipchat_user['is_group_admin'], 'presence': { 'status': None, 'show': None, } } if busy_hipstatus and not busy_office365: logging.info("Setting HipChat status to 'Available'") update_data['presence']['status'] = '' update_data['presence']['show'] = None message = "You are now 'Available'" elif busy_office365 and not busy_hipstatus: logging.info("Setting HipChat status to 'Do not disturb'") update_data['presence']['status'] = self.preferences.default_message() update_data['presence']['show'] = 'dnd' message = "You are now set to 'Do not disturb'" self.hipchat.update_status(update_data) rumps.notification("Status Updated", message, "Your status in HipChat has been updated", sound=False)
markdowner.on_focus_gained() self.web.setFocus() self.web.eval("focusField(%d);" % self.currentField) note.tags = tags try: time.sleep(0.001) self.updateTags() except AttributeError as e: print e # TODO: log error utility.end_safe_block(const.MARKDOWN_PREFS) def init_hook(self, mw, widget, parentWindow, addMode=False): addHook("editFocusGained", self.on_focus_gained) Preferences.init() if preferences.PREFS.get(const.MARKDOWN): editor.Editor.on_focus_gained = on_focus_gained editor.Editor.__init__ = wrap(editor.Editor.__init__, init_hook) editor.Editor.create_button = create_button editor.Editor.toggleMarkdown = toggleMarkdown editor.Editor.toggleHeading = toggleHeading editor.Editor.toggleAbbreviation = toggleAbbreviation editor.Editor.toggleHyperlink = toggleHyperlink editor.Editor.remove_garbage = remove_garbage editor.Editor.unlink = unlink editor.Editor.justifyFull = justifyFull editor.Editor.justifyRight = justifyRight editor.Editor.justifyLeft = justifyLeft
class PopUpMenu(object): def __init__(self, photolist, photoframe): self.gui = Gtk.Builder() self.gui.add_from_file(os.path.join(constants.SHARED_DATA_DIR, 'menu.ui')) self.photoimage = photoframe.photoimage self.photolist = photolist self.preferences = Preferences(photolist) self.about = AboutDialog() self.is_show = False def start(self, widget, event): self.set_recent_menu() if SETTINGS.get_boolean('window-fix'): self.gui.get_object('menuitem6').set_active(True) photo = self.photoimage.photo accessible = photo.can_open() if photo else False self.set_open_menu_sensitive(accessible) is_fullscreen = SETTINGS.get_boolean('fullscreen') self.gui.get_object('menuitem8').set_active(is_fullscreen) self.gui.connect_signals(self) menu = self.gui.get_object('menu') menu.popup(None, None, None, None, event.button, event.time) self.is_show = True def set_recent_menu(self): RecentMenu(self.gui, self.photolist) def set_open_menu_sensitive(self, state): self.gui.get_object('menuitem5').set_sensitive(state) def on_menuitem5_activate(self, *args): "open_photo" self.photoimage.photo.open() def on_next_photo(self, *args): self.photolist.next_photo(*args) def on_menuitem8_toggled(self, widget, *args): "_full_screen_cb" SETTINGS.set_boolean('fullscreen', widget.get_active()) def on_menuitem6_toggled(self, widget): "_fix_window_cb" SETTINGS.set_boolean('window-fix', widget.get_active()) def on_prefs(self, *args): self.preferences.start(*args) def on_help(self, widget): Gtk.show_uri(None, 'ghelp:gphotoframe', Gdk.CURRENT_TIME) def on_about(self, *args): self.about.start() def on_quit(self, *args): self.photolist.queue.clear_cache() reactor.stop() def on_menu_hide(self, *args): self.is_show = False
def view_preferences(self): self.manager.current = 'preferences' self.preferences = Preferences()
class Indicator: # ----------------------------------------------------------------------- # def __init__(self, player): # apparently appindicator will not quit on Ctrl-C by default. fix # bellow allows it to do so in Ctrl-C run the default action kernel # action which allows indicator to exit signal.signal(signal.SIGINT, signal.SIG_DFL) # expose the passing player to tht class self._player = player # remove registration to dbus, disabling MPRIS integration, mainly this # is done because current anoise MPRIS integration does not notify the # GUI element of play/pause/next/forward changes internally an attempt # at dbus manager that listens for anoise mpris notification fails due # to double signaling and handling of multiple MPRIS subscribed clients # and inability to distinguish which come from anoise self._player.sound_menu.remove_from_connection() #: DEBUG SETTING, used during development #: hide window ui, if it's the GUI class (rather then Indicator class) # if self._player.window.__class__.__name__ == 'GUI': # self._player.window.window.hide() # build the preferences window self._preferences_window = Preferences(self) # expose the default gtk settings self._gtk_settings = Gtk.Settings.get_default() # expose the default icon theme self._default_icon_theme = Gtk.IconTheme.get_default() # expose "hicolor" theme as fallback theme self._fallback_icon_theme = Gtk.IconTheme() self._fallback_icon_theme.set_custom_theme('hicolor') # expose found appindicator and appindicator-pause icons self._appindicator_icon, self._appindicator_icon_pause = \ self._get_indicator_icons() # build the appindicator self._appindicator, builder = self._make_appindicator() # expose the play/pause menu item to the class self._menuitem_play = builder.get_object('play_pause_toggle') # expose now playing menu item self._menuitem_now_playing = builder.get_object('now_playing') # expose now playing image self._image_now_playing = builder.get_object('image_now_playing') # expose play image self._image_play = builder.get_object('image_play') # expose pause image self._image_pause = builder.get_object('image_pause') # disable startup autoplay (ugh, terrible approach) # runs before indicator is made visible to show the "paused" icon self._disable_startup_autoplay() # set the indicator status to active self._appindicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE) # update the noise icon in the ui and the appindicator self._update_now_playing() # ----------------------------------------------------------------------- # def set_timer(self, enable, seconds): # method is run by preferences window code, which is why it's public # it's strange that this code is run in the UI code. # if window ui and appindicator will both install you will end up with # two timers, so seems like runing both "ui"s is not a good idea # exclusive, unless preferences can be a singleton if enable: self.timer = threading.Timer(seconds, self._set_future_pause) self.timer.start() else: self.timer.cancel() # ----------------------------------------------------------------------- # def _disable_startup_autoplay(self): """ Disable auto play on aplication startup. This is done by patching the self._player._sound_menu_play with function that pauses the player insteady of playing it, and the restores the original function after it was ran once. Unfortunately this is the only way to do this at this point. """ # set all the gui statuses to "pause" self._pause() # preserve the original function original_func = self._player._sound_menu_play # create a patched function which pauses the play when run the FIRST # time and then restores the original _sound_menu_play to the player # object (sad, should not need to patch) def _sound_menu_play(*args, **kwargs): # pause self._player._sound_menu_pause() self._player._sound_menu_play = original_func # now patch the play function with our patched function self._player._sound_menu_play = _sound_menu_play # ----------------------------------------------------------------------- # def _make_appindicator(self): """ Return constructed AppIndicator and it's menu. Also return the menu builder so we can update few of it's items """ # get full glade file. assumption here is that the ui file in the same # folder as this script ui_file_path = os.path.join( os.path.realpath(os.path.dirname(__file__)), 'appindicator.ui') # force showing of images despite whatever the global setting is self._gtk_settings.props.gtk_button_images = True # build the apindicator menu from the glade file builder = Gtk.Builder() builder.add_from_file(ui_file_path) # create the appindicator appindicator = AppIndicator3.Indicator.new( APPINDICATOR_ID, self._appindicator_icon, AppIndicator3.IndicatorCategory.APPLICATION_STATUS) # get the appindicator menu menu = builder.get_object('appindicator_menu') # setup the signals for the appindicator menu items builder.connect_signals(self) # get the play/pause menu iterm menuitem_play = builder.get_object('play_pause_toggle') # setup to trigger play/pause menu action on appindicator middle click appindicator.set_secondary_activate_target(menuitem_play) # set all menu items visible menu.show_all() # attach to the menu to the appindicator appindicator.set_menu(menu) return appindicator, builder # ----------------------------------------------------------------------- # def _get_indicator_icons(self): icons = [] # for over both default and fallback theme to get icons for theme in [self._default_icon_theme, self._fallback_icon_theme]: # try to find both regular and pause icons for icon_name in [APPINDICATOR_ICON, APPINDICATOR_ICON_PAUSE]: # break out of the loop if we failed to find any of the icons # and set the icon collection to an empty list if theme.has_icon(icon_name) is True: icon_info = theme.lookup_icon(icon_name, Gtk.IconSize.MENU, 0) # get icon file path icons.append(icon_info.get_filename()) else: icons = [] break # if we found both icons break out if len(icons) == 2 or all(icons) is True: break # if we could not find 2 icons fallback to very generic icons if len(icons) != 2 or all(icons) is False: icons = APPINDICATOR_ICONS_FALLBACK return icons # ----------------------------------------------------------------------- # def _on_toggle_play_pause_activate(self, widget): if self._player.is_playing: self._player._sound_menu_pause() self._pause() else: self._player._sound_menu_play() self._play() # ----------------------------------------------------------------------- # def _on_next_activate(self, widget): # tell the player to play next track self._player._set_new_play('next') # update noise status self._update_now_playing() # ----------------------------------------------------------------------- # def _on_previous_activate(self, widget): # tell the player to play track self._player._set_new_play('previous') # update noise status self._update_now_playing() # ----------------------------------------------------------------------- # def _on_preferences_window_show_activate(self, widget): self._preferences_window.show() # ----------------------------------------------------------------------- # def _on_about_activate(self, widget): # open default web browser to the homepage webbrowser.open_new('http://anoise.tuxfamily.org') # ----------------------------------------------------------------------- # def _on_quit_activate(self, widget): # try to cancel the timer catching all (really?) exceptions try: self.timer.cancel() except Exception: pass # tell gtk main loop to quit Gtk.main_quit() # ----------------------------------------------------------------------- # def _update_now_playing(self): # try to get the noise icon file, otherwise fallback to the default # note: it does not throw a specific error we can test for so # we are testing for Exception try: # get the icon file name for the existing noise icon_file = self._player.noise.get_icon().replace('file://', '') fallback_icon_name = None except Exception: # retrieve the default application icon from the icon as a pixbuf icon_file = APPINDICATOR_ICON fallback_icon_name = PLAYING_NOW_FALLBACK_ICON # get the now playing noise now_playing = self._player.noise.get_name() # form "Not Playing: <noise>" string for the indicator new_label = "Now Playing: %s" % now_playing # update the indicator now playing label to the noise name self._menuitem_now_playing.set_label(new_label) # update the now playing menu icon # # if fallback icon name is not set then we set the found noise icon # otherwise we set the set the image to the fallback icons if fallback_icon_name is None: self._image_now_playing.set_from_file(icon_file) else: self._image_now_playing.set_from_icon_name(fallback_icon_name, Gtk.IconSize.MENU) # update the now playing menu item with the now playing image self._menuitem_now_playing.set_image(self._image_now_playing) # ----------------------------------------------------------------------- # def _play(self): # tell player to play self._menuitem_play.set_label("P_ause") self._menuitem_play.set_image(self._image_pause) self._appindicator.set_icon(self._appindicator_icon) self._update_now_playing() # ----------------------------------------------------------------------- # def _pause(self): # pause the player self._menuitem_play.set_label("_Play") self._menuitem_play.set_image(self._image_play) self._appindicator.set_icon(self._appindicator_icon_pause) self._update_now_playing() # ----------------------------------------------------------------------- # def _set_future_pause(self): self._preferences_window.set_show_timer() self._player._sound_menu_pause() self._pause()
def __init__(self, context, editor): PanelView.__init__(self, context) self._editor = editor self._base_handlers = {} self.set_orientation(Gtk.Orientation.VERTICAL) self._preferences = Preferences() grid = Gtk.Grid() grid.set_orientation(Gtk.Orientation.VERTICAL) self.add(grid) # toolbar btn_follow = Gtk.ToggleToolButton.new_from_stock(Gtk.STOCK_CONNECT) btn_follow.set_tooltip_text(_("Follow Editor")) btn_follow.set_active( self._preferences.get("outline-connect-to-editor")) self._base_handlers[btn_follow] = btn_follow.connect( "toggled", self._on_follow_toggled) btn_expand = Gtk.ToolButton.new_from_stock(Gtk.STOCK_ZOOM_IN) btn_expand.set_tooltip_text(_("Expand All")) self._base_handlers[btn_expand] = btn_expand.connect( "clicked", self._on_expand_clicked) btn_collapse = Gtk.ToolButton.new_from_stock(Gtk.STOCK_ZOOM_OUT) btn_collapse.set_tooltip_text(_("Collapse All")) self._base_handlers[btn_collapse] = btn_collapse.connect( "clicked", self._on_collapse_clicked) self._toolbar = Gtk.Toolbar() self._toolbar.set_style(Gtk.ToolbarStyle.ICONS) self._toolbar.set_icon_size(Gtk.IconSize.MENU) self._toolbar.insert(btn_follow, -1) self._toolbar.insert(Gtk.SeparatorToolItem(), -1) self._toolbar.insert(btn_expand, -1) self._toolbar.insert(btn_collapse, -1) self._toolbar.insert(Gtk.SeparatorToolItem(), -1) self._toolbar.set_hexpand(True) grid.add(self._toolbar) # tree view column = Gtk.TreeViewColumn() pixbuf_renderer = Gtk.CellRendererPixbuf() column.pack_start(pixbuf_renderer, False) column.add_attribute(pixbuf_renderer, "pixbuf", 1) text_renderer = Gtk.CellRendererText() column.pack_start(text_renderer, True) column.add_attribute(text_renderer, "markup", 0) self._offset_map = OutlineOffsetMap() self._store = Gtk.TreeStore(str, GdkPixbuf.Pixbuf, object) # label, icon, node object self._view = Gtk.TreeView(model=self._store) self._view.append_column(column) self._view.set_headers_visible(False) self._cursor_changed_id = self._view.connect("cursor-changed", self._on_cursor_changed) self._base_handlers[self._view] = self._view.connect( "row-activated", self._on_row_activated) scrolled = Gtk.ScrolledWindow() scrolled.add(self._view) scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) scrolled.set_vexpand(True) grid.add(scrolled) # this holds a list of the currently expanded paths self._expandedPaths = None
class GtkUI(object): def __init__(self, args): self.daemon_bps = (0, 0, 0) # Setup signals try: import gnome.ui import gnome #Suppress: Warning: Attempt to add property GnomeProgram::*** after class was initialised original_filters = warnings.filters[:] warnings.simplefilter("ignore") try: self.gnome_prog = gnome.init("Deluge", deluge.common.get_version()) finally: warnings.filters = original_filters self.gnome_client = gnome.ui.master_client() def on_die(*args): reactor.stop() self.gnome_client.connect("die", on_die) log.debug("GNOME session 'die' handler registered!") except Exception, e: log.warning( "Unable to register a 'die' handler with the GNOME session manager: %s", e) if deluge.common.windows_check(): from win32api import SetConsoleCtrlHandler from win32con import CTRL_CLOSE_EVENT from win32con import CTRL_SHUTDOWN_EVENT def win_handler(ctrl_type): log.debug("ctrl_type: %s", ctrl_type) if ctrl_type in (CTRL_CLOSE_EVENT, CTRL_SHUTDOWN_EVENT): reactor.stop() return 1 SetConsoleCtrlHandler(win_handler) if deluge.common.osx_check() and gtk.gdk.WINDOWING == "quartz": import gtkosx_application self.osxapp = gtkosx_application.gtkosx_application_get() def on_die(*args): reactor.stop() self.osxapp.connect("NSApplicationWillTerminate", on_die) # Set process name again to fix gtk issue setproctitle(getproctitle()) # Attempt to register a magnet URI handler with gconf, but do not overwrite # if already set by another program. common.associate_magnet_links(False) # Make sure gtkui.conf has at least the defaults set self.config = deluge.configmanager.ConfigManager( "gtkui.conf", DEFAULT_PREFS) # We need to check on exit if it was started in classic mode to ensure we # shutdown the daemon. self.started_in_classic = self.config["classic_mode"] # Start the IPC Interface before anything else.. Just in case we are # already running. self.queuedtorrents = QueuedTorrents() self.ipcinterface = IPCInterface(args) # Initialize gdk threading gtk.gdk.threads_init() gobject.threads_init() # We make sure that the UI components start once we get a core URI client.set_disconnect_callback(self.__on_disconnect) self.trackericons = TrackerIcons() self.sessionproxy = SessionProxy() # Initialize various components of the gtkui self.mainwindow = MainWindow() self.menubar = MenuBar() self.toolbar = ToolBar() self.torrentview = TorrentView() self.torrentdetails = TorrentDetails() self.sidebar = SideBar() self.filtertreeview = FilterTreeView() self.preferences = Preferences() self.systemtray = SystemTray() self.statusbar = StatusBar() self.addtorrentdialog = AddTorrentDialog() if deluge.common.osx_check() and gtk.gdk.WINDOWING == "quartz": def nsapp_open_file(osxapp, filename): # Ignore command name which is raised at app launch (python opening main script). if filename == sys.argv[0]: return True from deluge.ui.gtkui.ipcinterface import process_args process_args([filename]) self.osxapp.connect("NSApplicationOpenFile", nsapp_open_file) from menubar_osx import menubar_osx menubar_osx(self, self.osxapp) self.osxapp.ready() # Initalize the plugins self.plugins = PluginManager() # Show the connection manager self.connectionmanager = ConnectionManager() from twisted.internet.task import LoopingCall rpc_stats = LoopingCall(self.print_rpc_stats) rpc_stats.start(10) reactor.callWhenRunning(self._on_reactor_start) # Start the gtk main loop gtk.gdk.threads_enter() reactor.run() self.shutdown() gtk.gdk.threads_leave()
class IssueView(PanelView): """ """ _log = getLogger("IssueView") def __init__(self, context, editor): PanelView.__init__(self, context) self._log.debug("init") self._editor = editor self._handlers = {} self._preferences = Preferences() self._preferences.connect("preferences-changed", self._on_preferences_changed) self._show_tasks = self._preferences.get("issues-show-tasks") self._show_warnings = self._preferences.get("issues-show-warnings") self._icons = { Issue.SEVERITY_WARNING : GdkPixbuf.Pixbuf.new_from_file(Resources().get_icon("warning.png")), Issue.SEVERITY_ERROR : GdkPixbuf.Pixbuf.new_from_file(Resources().get_icon("error.png")), Issue.SEVERITY_INFO : None, Issue.SEVERITY_TASK : GdkPixbuf.Pixbuf.new_from_file(Resources().get_icon("task.png")) } grid = Gtk.Grid() self.add(grid) self._store = Gtk.ListStore(GdkPixbuf.Pixbuf, str, str, object) self._view = Gtk.TreeView(model=self._store) column = Gtk.TreeViewColumn() column.set_title(_("Message")) pixbuf_renderer = Gtk.CellRendererPixbuf() column.pack_start(pixbuf_renderer, False) column.add_attribute(pixbuf_renderer, "pixbuf", 0) text_renderer = Gtk.CellRendererText() column.pack_start(text_renderer, True) column.add_attribute(text_renderer, "markup", 1) self._view.append_column(column) column = Gtk.TreeViewColumn() column.set_title(_("File")) text_renderer2 = Gtk.CellRendererText() column.pack_start(text_renderer2, True) column.add_attribute(text_renderer2, "markup", 2) self._view.insert_column(column, -1) self._handlers[self._view] = self._view.connect("row-activated", self._on_row_activated) self._scr = Gtk.ScrolledWindow() self._scr.add(self._view) self._scr.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self._scr.set_shadow_type(Gtk.ShadowType.IN) self._scr.set_hexpand(True) self._scr.set_vexpand(True) grid.add(self._scr) # toolbar self._button_warnings = Gtk.ToggleToolButton() self._button_warnings.set_tooltip_text(_("Show/Hide Warnings")) image = Gtk.Image() image.set_from_file(Resources().get_icon("warning.png")) self._button_warnings.set_icon_widget(image) self._button_warnings.set_active(self._show_warnings) self._handlers[self._button_warnings] = self._button_warnings.connect("toggled", self.__on_warnings_toggled) self._button_tasks = Gtk.ToggleToolButton() self._button_tasks.set_tooltip_text(_("Show/Hide Tasks")) imageTask = Gtk.Image() imageTask.set_from_file(Resources().get_icon("task.png")) self._button_tasks.set_icon_widget(imageTask) self._button_tasks.set_active(self._show_tasks) self._handlers[self._button_tasks] = self._button_tasks.connect("toggled", self.__on_tasks_toggled) toolbar = Gtk.Toolbar() toolbar.set_orientation(Gtk.Orientation.VERTICAL) toolbar.set_style(Gtk.ToolbarStyle.ICONS) toolbar.set_icon_size(Gtk.IconSize.MENU) toolbar.insert(self._button_warnings, -1) toolbar.insert(self._button_tasks, -1) toolbar.set_vexpand(True) grid.add(toolbar) # theme like gtk3 ctx = self._scr.get_style_context() ctx.set_junction_sides(Gtk.JunctionSides.RIGHT) ctx = toolbar.get_style_context() ctx.set_junction_sides(Gtk.JunctionSides.LEFT | Gtk.JunctionSides.RIGHT) ctx.add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR) self._issues = [] self.show_all() self._log.debug("init finished") def get_label(self): return _("Issues") def get_icon(self): return Gtk.Image.new_from_stock(Gtk.STOCK_DIALOG_INFO, Gtk.IconSize.MENU) def _on_row_activated(self, view, path, column): """ A row has been double-clicked on """ issue = self._store.get(self._store.get_iter(path), 3)[0] self._context.activate_editor(issue.file) #~ # FIXME: this doesn't work correctly #~ if not self._context.active_editor is None: #~ self._context.active_editor.select(issue.start, issue.end) self._editor.select(issue.start, issue.end) def _on_preferences_changed(self, prefs, key, value): if key == "issues-show-warnings" or key == "issues-show-tasks": # update filter self._store.clear() for issue, local in self._issues: self._append_issue_filtered(issue, local) def __on_tasks_toggled(self, togglebutton): self._show_tasks = togglebutton.get_active() self._preferences.set("issues-show-tasks", self._show_tasks) def __on_warnings_toggled(self, togglebutton): self._show_warnings = togglebutton.get_active() self._preferences.set("issues-show-warnings", self._show_warnings) def clear(self): """ Remove all issues from the view """ self._store.clear() self._issues = [] def append_issue(self, issue, local=True): """ Append a new Issue to the view @param issue: the Issue object @param local: indicates whether the Issue occured in the edited file or not """ self._issues.append((issue, local)) self._append_issue_filtered(issue, local) def _append_issue_filtered(self, issue, local): if issue.severity == Issue.SEVERITY_WARNING: if self._show_warnings: self._do_append_issue(issue, local) elif issue.severity == Issue.SEVERITY_TASK: if self._show_tasks: self._do_append_issue(issue, local) else: self._do_append_issue(issue, local) def _do_append_issue(self, issue, local): if local: message = issue.message filename = escape(issue.file.basename) else: message = "<span color='%s'>%s</span>" % (self._preferences.get("light-foreground-color"), issue.message) filename = "<span color='%s'>%s</span>" % (self._preferences.get("light-foreground-color"), issue.file.basename) self._store.append([self._icons[issue.severity], message, filename, issue])
def __init__(self, context, editor): PanelView.__init__(self, context) self._log.debug("init") self._editor = editor self._handlers = {} self._preferences = Preferences() self._preferences.connect("preferences-changed", self._on_preferences_changed) self._show_tasks = self._preferences.get("issues-show-tasks") self._show_warnings = self._preferences.get("issues-show-warnings") self._icons = { Issue.SEVERITY_WARNING : GdkPixbuf.Pixbuf.new_from_file(Resources().get_icon("warning.png")), Issue.SEVERITY_ERROR : GdkPixbuf.Pixbuf.new_from_file(Resources().get_icon("error.png")), Issue.SEVERITY_INFO : None, Issue.SEVERITY_TASK : GdkPixbuf.Pixbuf.new_from_file(Resources().get_icon("task.png")) } grid = Gtk.Grid() self.add(grid) self._store = Gtk.ListStore(GdkPixbuf.Pixbuf, str, str, object) self._view = Gtk.TreeView(model=self._store) column = Gtk.TreeViewColumn() column.set_title(_("Message")) pixbuf_renderer = Gtk.CellRendererPixbuf() column.pack_start(pixbuf_renderer, False) column.add_attribute(pixbuf_renderer, "pixbuf", 0) text_renderer = Gtk.CellRendererText() column.pack_start(text_renderer, True) column.add_attribute(text_renderer, "markup", 1) self._view.append_column(column) column = Gtk.TreeViewColumn() column.set_title(_("File")) text_renderer2 = Gtk.CellRendererText() column.pack_start(text_renderer2, True) column.add_attribute(text_renderer2, "markup", 2) self._view.insert_column(column, -1) self._handlers[self._view] = self._view.connect("row-activated", self._on_row_activated) self._scr = Gtk.ScrolledWindow() self._scr.add(self._view) self._scr.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self._scr.set_shadow_type(Gtk.ShadowType.IN) self._scr.set_hexpand(True) self._scr.set_vexpand(True) grid.add(self._scr) # toolbar self._button_warnings = Gtk.ToggleToolButton() self._button_warnings.set_tooltip_text(_("Show/Hide Warnings")) image = Gtk.Image() image.set_from_file(Resources().get_icon("warning.png")) self._button_warnings.set_icon_widget(image) self._button_warnings.set_active(self._show_warnings) self._handlers[self._button_warnings] = self._button_warnings.connect("toggled", self.__on_warnings_toggled) self._button_tasks = Gtk.ToggleToolButton() self._button_tasks.set_tooltip_text(_("Show/Hide Tasks")) imageTask = Gtk.Image() imageTask.set_from_file(Resources().get_icon("task.png")) self._button_tasks.set_icon_widget(imageTask) self._button_tasks.set_active(self._show_tasks) self._handlers[self._button_tasks] = self._button_tasks.connect("toggled", self.__on_tasks_toggled) toolbar = Gtk.Toolbar() toolbar.set_orientation(Gtk.Orientation.VERTICAL) toolbar.set_style(Gtk.ToolbarStyle.ICONS) toolbar.set_icon_size(Gtk.IconSize.MENU) toolbar.insert(self._button_warnings, -1) toolbar.insert(self._button_tasks, -1) toolbar.set_vexpand(True) grid.add(toolbar) # theme like gtk3 ctx = self._scr.get_style_context() ctx.set_junction_sides(Gtk.JunctionSides.RIGHT) ctx = toolbar.get_style_context() ctx.set_junction_sides(Gtk.JunctionSides.LEFT | Gtk.JunctionSides.RIGHT) ctx.add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR) self._issues = [] self.show_all() self._log.debug("init finished")
def __init__(self): self.preferences = Preferences("settings_default.yaml") self.mapping = None
def openPrefs(self): prefs = Preferences() prefs.exec()
class MainWindow(QMainWindow, Ui_MainWindow): def __init__(self): super(MainWindow, self).__init__() self.setupUi(self) self.tableWidget_dropzone.setColumnCount(6) self.tableWidget_dropzone.setRowCount(9) self.tableWidget_dropzone.setAcceptDrops(True) self.tableWidget_dropzone.setColumnWidth(0, 128) self.tableWidget_dropzone.setColumnWidth(1, 64) self.tableWidget_dropzone.setColumnWidth(2, 128) self.tableWidget_dropzone.setColumnWidth(3, 64) self.tableWidget_dropzone.setColumnWidth(4, 128) self.tableWidget_dropzone.setColumnWidth(5, 64) self.tableWidget_dropzone.setHorizontalHeaderLabels([ 'A1 Sample IDs', 'Gender', 'A2 Sample IDs', 'Gender', 'A3 Sample IDs', 'Gender' ]) self.tableWidget_dropzone.setVerticalHeaderLabels( ['', 'R1', 'R2', 'R3', 'R4', 'R5', 'R6', 'R7', 'R8']) self.tableWidget_dropzone.setSpan(0, 0, 1, 2) self.tableWidget_dropzone.setSpan(0, 2, 1, 2) self.tableWidget_dropzone.setSpan(0, 4, 1, 2) # populate stuff # arrayUpload_settings = QSettings('vll', 'arrayUpload') # path_array_data_folder = arrayUpload_settings.value('path_array_data_folder', type=str) # dataComboBox1 = DataCombo(path_array_data_folder) # dataComboBox2 = DataCombo(path_array_data_folder) # dataComboBox3 = DataCombo(path_array_data_folder) # # self.tableWidget_dropzone.setCellWidget(0, 0, dataComboBox1) # self.tableWidget_dropzone.setCellWidget(0, 2, dataComboBox2) # self.tableWidget_dropzone.setCellWidget(0, 4, dataComboBox3) self.populateExcelComboBox() self.populateDataComboBoxes() self.populateInvestigators() # other settings self.dateEdit.setDateTime(QDateTime.currentDateTime()) # actions self.actionPreferences.triggered.connect(self.show_preferences) self.load_samples_comboBox.activated.connect(self.loadExcel) def repopulate(self): self.populateExcelComboBox() self.populateDataComboBoxes() self.populateInvestigators() def populateInvestigators(self): arrayUpload_settings = QSettings('vll', 'arrayUpload') investigators_list = arrayUpload_settings.value('investigators', type=list) investigators_list.insert(0, " -- none selected -- ") self.comboBox_investigator.clear() for i in investigators_list: self.comboBox_investigator.addItem(i) def populateDataComboBoxes(self): arrayUpload_settings = QSettings('vll', 'arrayUpload') path_array_data_folder = arrayUpload_settings.value( 'path_array_data_folder', type=str) dataComboBox1 = DataCombo(path_array_data_folder) dataComboBox2 = DataCombo(path_array_data_folder) dataComboBox3 = DataCombo(path_array_data_folder) self.tableWidget_dropzone.setCellWidget(0, 0, dataComboBox1) self.tableWidget_dropzone.setCellWidget(0, 2, dataComboBox2) self.tableWidget_dropzone.setCellWidget(0, 4, dataComboBox3) def populateExcelComboBox(self): self.load_samples_comboBox.clear() arrayUpload_settings = QSettings('vll', 'arrayUpload') path_sample_excel_files_folder = arrayUpload_settings.value( 'path_sample_excel_files_folder', type=str) files = os.listdir(path=path_sample_excel_files_folder) files_xls = [] for f in files: if f.endswith(".xls"): files_xls.append(f) sfiles_xls = natsorted(files_xls) sfiles_xls.insert(0, " -- none selected -- ") for f in sfiles_xls: if f[0] != '$': self.load_samples_comboBox.addItem(f) def loadExcel(self): arrayUpload_settings = QSettings('vll', 'arrayUpload') path_sample_excel_files_folder = arrayUpload_settings.value( 'path_sample_excel_files_folder', type=str) self.tableWidget_XLS.clear() cexcel = self.load_samples_comboBox.currentText() cexcel_path = path_sample_excel_files_folder + "/" + cexcel if cexcel != " -- none selected -- ": book = xlrd.open_workbook(cexcel_path, 'r') sheet = book.sheet_by_index(0) self.tableWidget_XLS.setColumnCount(sheet.ncols + 10) self.tableWidget_XLS.setRowCount(sheet.nrows + 10) self.check_change = False for row_index in range(0, sheet.nrows): for col_index in range(0, sheet.ncols): content = sheet.cell(row_index, col_index).value item = QTableWidgetItem(content) self.tableWidget_XLS.setItem(row_index, col_index, item) self.tableWidget_XLS.setDragEnabled(True) self.check_change = True def load_samples(self): files = os.listdir("C:/Users/parla/Documents/") sfiles = natsorted(files) sfiles.insert(0, " -- none selected -- ") for f in sfiles: # print(f) if f.endswith('.xls') or f.endswith(' -- none selected -- '): self.load_samples_comboBox.addItem(f) def show_preferences(self): self.p = Preferences(self) self.p.show()
def show_preferences(self): self.p = Preferences(self) self.p.show()
class Client(): def __init__(self, path="../database"): self.session_files = [] self.books = self.getBooks(path) self.preferences = Preferences() self.preferences.readConfig() self.session = copy.deepcopy(self.preferences) self.db = Database() self.openDefaultDatabase() self.presenter = Presenter() self.songs = [] self.uploaded_song = {} def getBooks(self, path): pattern = path + "/*.db3" files = [] for file in glob.glob(pattern): files.append(file.replace('\\', '/')) log.config(files) return files def openDefaultDatabase(self): for book in self.books: # database paths if self.preferences.database.default in book: self.db.open(book) return def updateSessionData(self, session_obj): self.session = session_obj # Calls database object to create image files for each page in the song. # Returns the list of file paths where the images have been stored. def getPageImagesForSong(self, page_ids): paths = [] # Make a database request for each page id, for page_id in page_ids: file_path = "../tmp/image" + str(page_id) + ".png" # Database object writes the png file. # If the file is already written (arranger can do this) # don't re-write the file. if file_path not in paths: self.db.getImageData(page_id, file_path) # But we need redundant paths returned for arranger's sake. paths.append(file_path) self.session_files.extend(paths) return paths # Get the audio stream from the database and create a file. # Play the audio stream through the configured player. def getAudio(self, media_id): file_prefix = "../tmp/audio" + str(media_id) # The database will add the appropriate extension based on data type. audio_file = self.db.writeAudioData(media_id, file_prefix) if audio_file.endswith("mid"): xternal = self.preferences.external.midi elif audio_file.endswith("mp3"): xternal = self.preferences.external.mp3 else: xternal = self.preferences.external.web link = audio_file command = xternal.replace('<link>', link) command = command.split(',') log.info("Client::getAudio External audio process:", command) p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) return log.info("Client::getAudio Database wrote audio file:", audio_file) command = [] for subcmd in xternal.split(','): if subcmd == '<file>': subcmd = audio_file command.append(subcmd) log.info("Client::getAudio External audio process:", command) p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) self.session_files.append(audio_file) def getSplashConfiguration(self): splash = { 'type': 'splash', 'label1': self.preferences.splash.label1, 'label2': self.preferences.splash.label2 } return splash # Read the presentations/hymn, /scripture, /other folders (dive deep) # and return the list of html files found with their relative paths. def getPresentationFiles(self): # Get a list of just the paths of files in the org cache. org_cache = [] paths = getOrganizerCache() for dictionary in paths: org_cache.append(dictionary['path']) all_files = getFilesInDir(self.preferences.presentation.path) for path in all_files: if path in org_cache: continue # Already in the paths list. if '/hymn/' in path: ptype = "hymn" elif '/scripture/' in path: ptype = 'scripture' else: ptype = 'other' paths.append({'type': ptype, 'path': path}) log.info('Client::getPresentationFiles Found', len(paths), 'files in:', self.preferences.presentation.path) self.saveOrganizerSequence(paths) return paths # Start the presenter external program as per preference configuration. def launchPresenter(self, path): dot = path.rfind('.') extension = path[dot + 1:] external = getattr(self.preferences.external, extension) command = [] for arg in external.split(','): if '<file>' in arg: arg = arg.replace('<file>', path) command.append(arg) if sys.platform == "linux": my_env = os.environ.copy() my_env['LD_LIBRARY_PATH'] = '/usr/lib/libreoffice/program' p = subprocess.Popen(command, env=my_env) elif sys.platform == "win32": command[-1] = command[-1].replace('/', '\\') log.info("Launching presenter:", command) p = subprocess.Popen(command) # Get a list of verses and pages for give song def getVerseAndPages(self, data): song_id = int(data['id']) idx = data['idx'] for song in self.songs: if int(song['id']) == song_id: log.debug("Client::getVerseAndPages found song id:", song_id) break stanzas = {} log.debug('Client->database::getVerseAndPages verse id:', song['music']) status = self.db.getVerseAndPages(song['music'], stanzas) if status == "error": return None pres_file = '../presentations/hymn/' + song['title'] + '.pptx' result = {'type': 'stanzas', 'id': song['music']} result['values'] = stanzas result['idx'] = idx result['path'] = pres_file if os.path.exists(pres_file): result['exists'] = True else: result['exists'] = False return result # Creates a song presentation from a supplied dict def createSongPresentation(self, song_id_list, page_list, ratio): song = None if len(song_id_list) > 1: song = self.compileMedley(song_id_list) else: for hymn in self.songs: if hymn['id'] == song_id_list[0]: song = hymn song['type'] = 'single' break if song == None: return None # Remove redundant page_ids from page_list ('set' does this) unique_page_ids = list(set(page_list)) if not len(unique_page_ids): return None unique_paths = self.getPageImagesForSong(unique_page_ids) # Build a path list that contains any duplicates because # Chorus elements often need to be pasted twice in the # presentation file. pres_file = '../presentations/hymn/' + song['title'] + '.pptx' pres_file = pres_file.replace('?', '') log.info("Creating song presentation:", pres_file) paths = [] for pg_id in page_list: index = unique_page_ids.index(pg_id) paths.append(unique_paths[index]) if self.presenter.createSongFile(pres_file, song, paths, self.preferences, ratio): if os.path.exists(pres_file): exists = True else: exists = False response = { 'type': 'icon', 'icon_type': 'hymnal', 'path': pres_file, 'exists': exists } return response else: return None def compileMedley(self, song_id_list): # Medley: Find each song object and create a unique # medley object compilation to send to presenter. medley = {} for hymn in self.songs: # Only go through all songs once. for id in song_id_list: # This is a list of unique ids. if hymn['id'] == id: # Found a matching id. If medley not initialized... if len(medley) == 0: # Copy the first hymn converting each key to list for key, item in hymn.items(): medley[key] = [item] # Make a list of each item else: # Append each item to its key in dict. for key, item in hymn.items(): medley[key].append(item) medley['type'] = 'medley' medley['titles'] = medley['title'] medley['title'] = 'Medley-' for number in medley['number']: medley['title'] += str(number) + ',' medley['title'] = medley['title'][:-1] return medley # Create a scripture presentation from data dictionary def createScripturePresentation(self, data): ref = data['ref'] font_sz = data['font_sz'] text = data['text'] version = data['version'] ratio = data['ratio'] text += "\n(" + version + ")" path = "../presentations/scripture/" + ref.replace(':', '_') + ".pptx" if os.path.exists(path): exists = True else: exists = False self.presenter.createScriptureFile(path, font_sz, ref, text, self.preferences, ratio) response = { 'type': 'icon', 'icon_type': 'bible', 'path': path, 'exists': exists } return response def getEditorInitialData(self): versions = self.getAvailableBibleVersions() log.config('Client::getEditorInitialData Available bible versions:', ', '.join(versions)) rtn_dict = {'type': 'editor', 'bibles': versions} return rtn_dict # Get the available bible versions on this system. def getAvailableBibleVersions(self): version_path = self.preferences.bible.sword_path log.info('Client::getAvailableBibleVersions searching ', version_path) version_names = [] version_configs = glob.glob(version_path + "/*.conf") for file in version_configs: if "globals.conf" in file: continue # Open file and read first line. with open(file, 'r') as vfile: line = vfile.readline() vname = line[1:-2] version_names.append(vname) version_names.sort() return version_names # Look up a scripture in a particular version of the bible. # The data object has 2 pertinent attributes: # data.version -- the version of the bible to look up: # data.passage -- the passage (e.g. Acts 2:38) def getBibleVerse(self, data): external = self.preferences.external.bible command = [] for arg in external.split(','): if '<version>' in arg: arg = arg.replace('<version>', data['version']) elif '<passage>' in arg: arg = arg.replace('<passage>', data['ref']) command.append(arg) log.info('Client::getBibleVerse Request:', command) try: p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) log.info('Client::getBibleVerse Successful command execution.') except: log.error("Client::getBibleVerse Unexpected error:", sys.exc_info()[0]) ''' Diatheke output is: <book> <chapter>:<verse>: <verse text>EOL and continues until the last verse is printed. Then it prints another EOL, a ": " and repeats the (last) verse, then another EOL and prints the (<bible_version>). ''' if p.returncode != 0 and p.returncode != None: #log.error('Client::getBibleVerse', p.stderr.decode()) log.error('Client::getBibleVerse Scripture not found:', data['ref']) try: log.error('Client::getBibleVerse', p.stdout.read().decode()) except: log.error('Client::getBibleVerse unable to read stdout') pass return { 'type': 'scripture', 'status': 'error', 'command': external, 'code': p.returncode } try: raw_result = p.stdout.read().decode() # Remove the duplicate scripture (rfind(':')) and convert to list. delim = '\n' if sys.platform == "win32": scripture = raw_result.replace('\r', '').split(delim)[0:-2] else: scripture = raw_result.split(delim)[0:-3] log.info(raw_result) except: log.error('Client::getBibleVerse unable to process stdout') # To preemptively let the browser know whether the file exists # so that it can display an Are You Sure dialog without sending # multiple messages to get it done. path = "../presentations/scripture/" + data['ref'] + ".pptx" if os.path.exists(path): exists = True log.warning('Client::getBibleVerse File exists:', path) else: exists = False result = { 'type': 'scripture', 'status': 'ok', 'text': scripture, 'command': external, 'passage': data['ref'], 'version': data['version'], 'exists': exists, 'path': path } return result # Organizer confirm file (in browser) causes this to be called. def deleteFile(self, path): if os.path.exists(path): log.info('Client::deleteFile Organizer request to delete file:', path) try: os.remove(path) log.info('Client::deleteFile Deleted file:', path) return "ok" except: log.warn('Client::deleteFile Failed to delete file:', path) return "fail" else: log.error('Client::deleteFile File does not exist:', path) return "does not exist" # Update the .organizer file with the current sequence of files # that were displayed at the time. The items argument is a list # of dicts with 'path' and 'icon' keys sent from the browser. def saveOrganizerSequence(self, items): with open("../cache/.organizer.txt", 'w') as organizer: for item in items: organizer.write('type=' + item['type'] + '\n') organizer.write('path=' + item['path'] + '\n\n') log.info('Client::saveOrganizerSequence Saved', len(items), 'presentation paths to organizer cache.') # Clean up the temporary image and media files created this session. def cleanupTempFiles(self): count = 0 for file in set(self.session_files): count += 1 if os.path.exists(file): try: os.remove(file) count += 1 except: log.warning('Unable to delete file:', file) pass log.info('Client::cleanupTempFiles Deleted', count, 'temporary session files.') # Opens a process to select a folder. Returns the folder # image files (.png) as a list. def getFolder(self, starting=''): command = self.preferences.external.browse_folder if len(starting): command = command.replace('<file>', starting) command = command.split(',') log.info('Client::getFolder Browsing for folder command:', command) p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) folder = p.stdout.read().decode().strip() # Stdout will be blank if cancel was pressed. We return nothing. if len(folder) < 2: log.info( 'Client::getFolder Browsing for folder dialog was canceled by user.' ) return None image_files = glob.glob(folder + '/*.png') audio_files = glob.glob(folder + '/*.mid') for file in glob.glob(folder + '/.mp3'): audio_files.append(file) image_files.sort() audio_files.sort() result = {'type': 'folder', 'folder': folder} result['image_files'] = image_files result['audio_files'] = audio_files log.info('Client::getFolder Found:', len(image_files), 'and', len(audio_files), 'in', folder) return result # The song argument is a dictionary received from the browser. # It contains everything necessary to create a new hymn record # in the database. def uploadHymn(self, song): # Need to connect to the database (book) indicated in song dict. # Save the current one in case of error (we'll reset). reconnect = None log.info('Client::uploadHymn request:', song) if song['book'] not in self.db.file: for book in self.books: if song['book'] in book: reconnect = self.db.file # Current connection self.db.open(book) # New connection break # Upload each page, making sure each is successful. pageid_list = [] for path in song['paths']: page_id = self.db.uploadPage(path) if page_id == None: if reconnect != None: self.db.open(reconnect) message = "Error uploading " + path log.error(message) return { 'type': 'upload', 'status': 'error', 'message': message } # Save the page ids to for mapping (next loop) pageid_list.append(page_id) # Create a verse record. Required format to send to database is # a stanza comma-separated string for the SEQUENCE of part names. stanzas = ','.join(song['sequence']) # Use the pageid_list list created above with the song['verses'] and the # song['sequence'] to create a page string that represents the # full arrangement. page_sequence = "" for verse in song['sequence']: page_string = "" for index in song[verse]: page_string += "," + str(pageid_list[index]) page_sequence += "|" + page_string[1:] # Strip the first , page_sequence = page_sequence[1:] # Strip the first | # Commit the verse record to the database. verse_id = self.db.newVerseRecord(stanzas, page_sequence) if verse_id == None: if reconnect != None: self.db.open(reconnect) message = "Client::uploadHymn Error creating verse record." log.error(message, stanzas, page_sequence) return {'type': 'upload', 'status': 'error', 'message': message} # Create the audio record. Database figures out the type based # on the extension. media_id = self.db.newAudioRecord(song['audio']) if media_id == None: if reconnect != None: self.db.open(reconnect) message = "Client::uploadHymn Error uploading media file." log.error(message, song['audio']) return {'type': 'upload', 'status': 'error', 'message': message} # Create author records for lyricist and composer. The database # will return either a new record id (not a duplicate name), an # existing record id (matches exactly a name already there), or # None if it has trouble creating the record. lyricist_id = self.db.newAuthorRecord(song['lyricist']) if lyricist_id == None: if reconnect != None: self.db.open(reconnect) message = "Client::uploadHymn Error creating lyricist record." log.error(message, song['lyricist']) return {'type': 'upload', 'status': 'error', 'message': message} composer_id = self.db.newAuthorRecord(song['composer']) if composer_id == None: if reconnect != None: self.db.open(reconnect) message = "Client::uploadHymn Error creating composer record." log.error(message, song['composer']) return {'type': 'upload', 'status': 'error', 'message': message} # Create the meta record, which is basically a container of all # of the record ids for the inserts above (and a little more). meta = self.db.newMetaRecord(song['number'], song['title'], lyricist_id, song['ldate'], composer_id, song['mdate'], song['copyright'], verse_id, media_id) if meta == None: if reconnect != None: self.db.open(reconnect) message = "Client::uploadHymn Error creating meta record." log.error(message) return {'type': 'upload', 'status': 'error', 'message': message} # Successful upload has occurred. Leave the database connected, # since the next thing that will be done is to get self.uploaded_song = song songs = [] self.db.getAllSongs(songs) return {'type': 'upload', 'status': 'success', 'song': song}
def headerLabelType(self): """ Returns the type of the header label. """ return Preferences.HeaderLabel(self.grpHeaderLabel.checkedId())
class GtkUI(object): def __init__(self, args): self.daemon_bps = (0,0,0) # Setup signals try: import gnome.ui import gnome self.gnome_prog = gnome.init("Deluge", deluge.common.get_version()) self.gnome_client = gnome.ui.master_client() def on_die(*args): reactor.stop() self.gnome_client.connect("die", on_die) log.debug("GNOME session 'die' handler registered!") except Exception, e: log.warning("Unable to register a 'die' handler with the GNOME session manager: %s", e) if deluge.common.windows_check(): from win32api import SetConsoleCtrlHandler from win32con import CTRL_CLOSE_EVENT from win32con import CTRL_SHUTDOWN_EVENT def win_handler(ctrl_type): log.debug("ctrl_type: %s", ctrl_type) if ctrl_type in (CTRL_CLOSE_EVENT, CTRL_SHUTDOWN_EVENT): reactor.stop() return 1 SetConsoleCtrlHandler(win_handler) # Attempt to register a magnet URI handler with gconf, but do not overwrite # if already set by another program. common.associate_magnet_links(False) # Make sure gtkui.conf has at least the defaults set self.config = deluge.configmanager.ConfigManager("gtkui.conf", DEFAULT_PREFS) # We need to check on exit if it was started in classic mode to ensure we # shutdown the daemon. self.started_in_classic = self.config["classic_mode"] # Start the IPC Interface before anything else.. Just in case we are # already running. self.queuedtorrents = QueuedTorrents() self.ipcinterface = IPCInterface(args) # Initialize gdk threading gtk.gdk.threads_init() # We make sure that the UI components start once we get a core URI client.set_disconnect_callback(self.__on_disconnect) self.trackericons = TrackerIcons() self.sessionproxy = SessionProxy() # Initialize various components of the gtkui self.mainwindow = MainWindow() self.menubar = MenuBar() self.toolbar = ToolBar() self.torrentview = TorrentView() self.torrentdetails = TorrentDetails() self.sidebar = SideBar() self.filtertreeview = FilterTreeView() self.preferences = Preferences() self.systemtray = SystemTray() self.statusbar = StatusBar() self.addtorrentdialog = AddTorrentDialog() # Initalize the plugins self.plugins = PluginManager() # Late import because of setting up translations from connectionmanager import ConnectionManager # Show the connection manager self.connectionmanager = ConnectionManager() from twisted.internet.task import LoopingCall rpc_stats = LoopingCall(self.print_rpc_stats) rpc_stats.start(10) reactor.callWhenRunning(self._on_reactor_start) # Initialize gdk threading gtk.gdk.threads_enter() reactor.run() self.shutdown() gtk.gdk.threads_leave()
class TTS_CLI: def __init__(self): self.preferences = Preferences() parser = argparse.ArgumentParser( description="Manipulate Tabletop Simulator files") parser.add_argument("-d", "--directory", help="Override TTS cache directory") parser.add_argument("-l", "--loglevel", help="Set logging level", choices=['debug', 'info', 'warn', 'error']) subparsers = parser.add_subparsers(dest='parser', title='command', description='Valid commands.') subparsers.required = True # add list command parser_list = subparsers.add_parser('list', help="List installed mods.", description=''' List installed mods. If no id is provided, then this will return a list of all installed modules. If an id is provided, then this will list the contents of that modules. ''') group_list = parser_list.add_mutually_exclusive_group() group_list.add_argument("-w", "--workshop", action="store_const", metavar='save_type', dest='save_type', const=SaveType.workshop, help="List workshop files (the default).") group_list.add_argument("-s", "--save", action="store_const", metavar='save_type', dest='save_type', const=SaveType.save, help="List saves.") group_list.add_argument("-c", "--chest", action="store_const", metavar='save_type', dest='save_type', const=SaveType.chest, help="List chest files.") parser_list.add_argument("id", nargs='?', help="ID of specific mod to list details of.") parser_list.set_defaults(func=self.do_list) # export command parser_export = subparsers.add_parser( 'export', help="Export a mod.", description='Export a mod in a format suitible for later import.') group_export = parser_export.add_mutually_exclusive_group() group_export.add_argument("-w", "--workshop", action="store_const", dest='save_type', metavar='save_type', const=SaveType.workshop, help="ID is of workshop file (the default).") group_export.add_argument("-s", "--save", action="store_const", dest='save_type', metavar='save_type', const=SaveType.save, help="ID is of savegame file.") group_export.add_argument("-c", "--chest", action="store_const", dest='save_type', metavar='save_type', const=SaveType.chest, help="ID is of chest file.") parser_export.add_argument( "id", help="ID of mod/name of savegame to export.") parser_export.add_argument("-o", "--output", help="Location/file to export to.") parser_export.add_argument("-f", "--force", action="store_true", help="Force creation of export file.") parser_export.add_argument( "-d", "--download", action="store_true", help="Attempt to download missing cache files. (EXPERIMENTAL)") parser_export.set_defaults(func=self.do_export) # import command parser_import = subparsers.add_parser( 'import', help="Import a mod.", description="Import an previously exported mod.") parser_import.add_argument("file", help="Mod pak file to import.") parser_import.set_defaults(func=self.do_import) # download command parser_download = subparsers.add_parser( 'download', help='Download mod files.', description= 'Attempt to download any missing files for an installed mod.') group_download = parser_download.add_mutually_exclusive_group() group_download.add_argument("-w", "--workshop", action="store_const", dest='save_type', metavar='save_type', const=SaveType.workshop, help="ID is of workshop file.") group_download.add_argument("-s", "--save", action="store_const", dest='save_type', metavar='save_type', const=SaveType.save, help="ID is of savegame file.") group_download.add_argument("-c", "--chest", action="store_const", dest='save_type', metavar='save_type', const=SaveType.chest, help="ID is of chest file.") group_download_target = parser_download.add_mutually_exclusive_group( required=True) group_download_target.add_argument("-a", "--all", action="store_true", help="Download all.") group_download_target.add_argument( "id", nargs='?', help="ID of mod/name of savegame to download.") parser_download.set_defaults(func=self.do_download) # cache command parser_cache = subparsers.add_parser('cache', help='Work with the cache.') subparsers_cache = parser_cache.add_subparsers( dest='parser_cache', title='cache_command', description='Valid sub-commands.') subparsers_cache.required = True parser_cache_create = subparsers_cache.add_parser( 'create', help='(re)create cache directory') parser_cache_create.set_defaults(func=self.do_cache_create) # config command parser_config = subparsers.add_parser('config', help='Configure tts manager.') subparsers_config = parser_config.add_subparsers( dest='parser_config', title='config_command', description='Valid sub-commands.') subparsers_config.required = True parser_config_list = subparsers_config.add_parser( 'list', help='List configuration.') parser_config_list.set_defaults(func=self.do_config_list) parser_config_validate = subparsers_config.add_parser( 'validate', help='Validate configuration.') parser_config_validate.set_defaults(func=self.do_config_validate) parser_config_reset = subparsers_config.add_parser( 'reset', help='Reset configuration.') parser_config_reset.set_defaults(func=self.do_config_reset) parser_config_set = subparsers_config.add_parser( 'set', help='Set configuration parameters.') parser_config_set.set_defaults(func=self.do_config_set) parser_config_set.add_argument("-m", "--mod_location", choices=['documents', 'gamedata'], help="Where mods are stored.") parser_config_set.add_argument("-t", "--tts_location", help="TTS Install directory") args = parser.parse_args() # set logging if args.loglevel: logmap = { 'debug': logging.DEBUG, 'info': logging.INFO, 'warn': logging.WARN, 'error': logging.ERROR } logger().setLevel(logmap[args.loglevel]) else: logger().setLevel(logging.WARN) # load filesystem values if args.directory: self.filesystem = FileSystem(os.path.abspath(args.directory)) else: self.filesystem = self.preferences.get_filesystem() if (args.parser == 'list' or args.parser == 'export') and not args.save_type: # set default args.save_type = SaveType.workshop if (args.parser == 'config' and args.parser_config == 'set' and not args.mod_location and not args.tts_location): parser_config_set.error("At least one of -m or -t is required.") rc, message = args.func(args) if message: print(message) sys.exit(rc) def do_config_set(self, args): if args.mod_location: self.preferences.locationIsUser = args.mod_location == 'documents' if args.tts_location: self.preferences.TTSLocation = args.mod_location self.preferences.save() return 0, "Preferences set" def do_config_reset(self, args): self.preferences.reset() return 0, "Preferences Reset." def do_config_list(self, args): return 0, self.preferences def do_config_validate(self, args): if self.preferences.validate(): return 0, "Configuration validated OK." else: return 1, "Configuration failed to validate." def do_cache_create(self, args): try: self.filesystem.create_dirs() except OSError as exception: return 1, "OS error: {0}".format(exception) return 0, "All directories created OK." def list_by_type(self, save_type): result = "" for (name, id) in describe_files_by_type(self.filesystem, save_type): result += "\n%s (%s)" % (name, id) return 0, result def list_item(self, data, filename, ident): if not data: # self.list_installed() return save = Save(savedata=data, ident=ident, filename=filename, filesystem=self.filesystem) return 0, save def do_download(self, args): successful = True if not args.all: if not args.save_type: args.save_type = self.filesystem.get_json_filename_type( args.id) if not args.save_type: return 1, "Unable to determine type of id %s" % args.id successful = download_file(self.filesystem, args.id, args.save_type) else: if args.save_type: for ident in self.filesystem.get_filenames_by_type( args.save_type): if not download_file(self.filesystem, ident, args.save_type): successful = False break else: for save_type in SaveType: for ident in self.filesystem.get_filenames_by_type( save_type): if not download_file(self.filesystem, ident, save_type): successful = False break if successful: return 0, "All files downloaded." else: return 1, "Some files failed to download." def do_list(self, args): rc = 0 result = None if not args.id: rc, result = self.list_by_type(args.save_type) else: if not args.save_type: args.save_type = self.filesystem.get_json_filename_type( args.id) if not args.save_type: return 1, "Unable to determine type of id %s" % args.id filename = self.filesystem.get_json_filename_for_type( args.id, args.save_type) data = load_json_file(filename) rc, result = self.list_item(data, filename, args.id) return rc, result def do_export(self, args): filename = None if args.output: if os.path.isdir(args.output): filename = os.path.join(args.output, args.id + ".pak") else: filename = args.output else: filename = args.id + ".pak" data = None json_filename = None if not args.save_type: args.save_type = self.filesystem.get_json_filename_type(args.id) if not args.save_type: return 1, "Unable to determine type of id %s" % args.id json_filename = self.filesystem.get_json_filename_for_type( args.id, args.save_type) if not json_filename: return 1, "Unable to find filename for id %s (wrong -s/-w/-c specified?)" % args.id data = load_json_file(json_filename) if not data: return 1, "Unable to load data for file %s" % json_filename save = Save(savedata=data, filename=json_filename, ident=args.id, save_type=args.save_type, filesystem=self.filesystem) if not save.isInstalled: if not args.download: return 1, "Unable to find all urls required by %s. Rerun with -d to try and download them or open it within TTS.\n%s" % ( args.id, save) else: logger().info("Downloading missing files...") successful = save.download() if successful: logger().info("Files downloaded successfully.") else: return 1, "Some files failed to download" if os.path.isfile(filename) and not args.force: return 1, "%s already exists. Please specify another file or use '-f'" % filename logger().info("Exporting json file %s to %s" % (args.id, filename)) save.export(filename) # TODO: exception handling return 0, "Exported %s to %s" % (args.id, filename) def do_import(self, args): return 0, save_helper.importPak(self.filesystem, args.file)
def on_actionPreferences_triggered(self): if not self.preferences_dialog: self.preferences_dialog = Preferences(self.data['preferences']) self.preferences_dialog.rejected.connect(self.update_preferences) self.preferences_dialog.show()
def __init__(self, pyroom_config): self.current = 0 self.buffers = [] self.config = pyroom_config.config self.gui = GUI(pyroom_config, self) self.preferences = Preferences(gui=self.gui, pyroom_config=pyroom_config) try: self.recent_manager = gtk.recent_manager_get_default() except AttributeError: self.recent_manager = None self.status = self.gui.status self.window = self.gui.window self.window.add_accel_group(make_accel_group(self)) self.textbox = self.gui.textbox self.UNNAMED_FILENAME = FILE_UNNAMED self.autosave_timeout_id = '' self.autosave_elapsed = '' self.new_buffer() self.textbox.connect('key-press-event', self.key_press_event) self.textbox.set_pixels_below_lines( int(self.config.get("visual", "linespacing"))) self.textbox.set_pixels_above_lines( int(self.config.get("visual", "linespacing"))) self.textbox.set_pixels_inside_wrap( int(self.config.get("visual", "linespacing"))) # Autosave timer object autosave.start_autosave(self) self.window.show_all() self.window.fullscreen() # Handle multiple monitors screen = gtk.gdk.screen_get_default() root_window = screen.get_root_window() mouse_x, mouse_y, mouse_mods = root_window.get_pointer() current_monitor_number = screen.get_monitor_at_point(mouse_x, mouse_y) monitor_geometry = screen.get_monitor_geometry(current_monitor_number) self.window.move(monitor_geometry.x, monitor_geometry.y) self.window.set_geometry_hints(None, min_width=monitor_geometry.width, min_height=monitor_geometry.height, max_width=monitor_geometry.width, max_height=monitor_geometry.height) # Defines the glade file functions for use on closing a buffer self.wTree = gtk.glade.XML( os.path.join(pyroom_config.pyroom_absolute_path, "interface.glade"), "SaveBuffer") self.dialog = self.wTree.get_widget("SaveBuffer") self.dialog.set_transient_for(self.window) dic = { "on_button-close_clicked": self.unsave_dialog, "on_button-cancel_clicked": self.cancel_dialog, "on_button-save_clicked": self.save_dialog, } self.wTree.signal_autoconnect(dic) #Defines the glade file functions for use on exit self.aTree = gtk.glade.XML( os.path.join(pyroom_config.pyroom_absolute_path, "interface.glade"), "QuitSave") self.quitdialog = self.aTree.get_widget("QuitSave") self.quitdialog.set_transient_for(self.window) dic = { "on_button-close2_clicked": self.quit_quit, "on_button-cancel2_clicked": self.cancel_quit, "on_button-save2_clicked": self.save_quit, } self.aTree.signal_autoconnect(dic) self.keybindings = define_keybindings(self) # this sucks, shouldn't have to call this here, textbox should # have its background and padding color from GUI().__init__() already self.gui.apply_theme()
class NoduleCADx(QMainWindow): def __init__(self): super().__init__() loadUi('mainwindow.ui', self) self.setWindowFlags(Qt.WindowMaximizeButtonHint | Qt.WindowMinimizeButtonHint | Qt.WindowCloseButtonHint) self.display_dialog = None # ColumnWidth of Patient List self.treeWidget.setColumnWidth(0, 70) self.treeWidget.setColumnWidth(1, 100) self.treeWidget.setColumnWidth(2, 100) self.treeWidget.setColumnWidth(3, 50) self.treeWidget.setColumnWidth(4, 50) # ColumnWidth of Scan and Nodule List self.noduletreeWidget.setColumnWidth(0, 70) self.noduletreeWidget.setColumnWidth(1, 100) self.noduletreeWidget.setColumnWidth(2, 100) self.noduletreeWidget.setColumnWidth(3, 50) self.noduletreeWidget.setColumnWidth(4, 100) self.noduletreeWidget.setColumnWidth(5, 100) self.noduletreeWidget.setColumnWidth(6, 100) self.noduletreeWidget.setColumnWidth(7, 100) self.noduletreeWidget.setColumnWidth(8, 100) self.preferences_dialog = None # pkg_name is the JSON file saved all the detected information (including scan path) # create a pkg_name.json if it doesn't exist. if not os.path.exists(pkg_name): with open(pkg_name, 'w') as json_file: initial_json = { 'app': 'Nodule CADx', 'version': '1.0.0', "preferences": { "threshold": "0.8", "project_directory": os.getcwd(), "automatic_classification": True, "windowlevel": "?" }, 'members': [] } json.dump(initial_json, json_file, indent=2) # load pkg_name.json with open(pkg_name, 'r') as f: self.data = json.load(f) # load nodulenet and classification model and refresh patient list. self.nodulenet_model = None self.classification_model = None self.load_model() self.refresh_patient_list() def load_model(self): """ Load (1)NoduleNet and (2)Classification model. Since I didn't install NoduleNet on my macOS, so only load it on Windows10. """ # NoduleNet model if use_win10: args = parser.parse_args() initial_checkpoint = args.weight net = args.net net = getattr(this_module, net)(config) if initial_checkpoint: print('[Loading model from %s]' % initial_checkpoint) checkpoint = torch.load(initial_checkpoint, map_location='cpu') net.load_state_dict(checkpoint['state_dict'], ) else: print('No model weight file specified') net.set_mode('eval') net.use_mask = True net.use_rcnn = True self.nodulenet_model = net else: self.nodulenet_model = None # Classification model self.classification_model = joblib.load( 'model/classification_model.pkl') @pyqtSlot() def on_reportButton_clicked(self): """ Export system report in CSV format. """ report = [[ 'Name', 'Date of Birth', 'Sex', 'Final-Score', 'Management', 'Scan Path', 'Nodule', 'Diameter', 'Type', 'Calcification', 'Spiculation', 'Perifissural', 'Endobronchial', 'Score' ]] for m in self.data['members']: report.append([ m['patient_name'], m['date_of_birth'], m['sex'], m['score'], m['management'] ]) for s in m['scans']: report.append([''] * 5 + [s['scan_path']]) for i, n in enumerate(s['nodules'], start=1): type_name = self.get_type_name(n['type']) report.append([''] * 6 + [ f'Nodule{i}', n['diameter'], type_name, n['calcification'], n['spiculation'], n['perifissural'], n['endobronchial'], n['score'] ]) with open('report.csv', 'w') as csvfile: writer = csv.writer(csvfile) writer.writerows(report) @staticmethod def get_type_name(nodule_type): """ Get type name for display. """ if nodule_type == '1': return 'non-solid' elif nodule_type == '2': return 'non/part' elif nodule_type == '3': return 'part-solid' elif nodule_type == '4': return 'part/solid' elif nodule_type == '5': return 'solid' def refresh_patient_list(self): """ refresh patient list (upper block of main window). """ self.treeWidget.clear() for m in self.data['members']: scan_item = QTreeWidgetItem(self.treeWidget, [ '\u2713' if m['updated'] else '\u2717', m['patient_name'], m['date_of_birth'], m['sex'], m['score'], m['management'] ]) for i in range(scan_item.columnCount()): scan_item.setTextAlignment(i, Qt.AlignHCenter) def refresh_scan_list(self, member): """ refresh scan and nodule list (lower block of main window). """ self.noduletreeWidget.clear() for scan in member['scans']: p = QTreeWidgetItem(self.noduletreeWidget, [ '\u2713' if scan['updated'] else '\u2717', scan['scan_date'], scan['scan_path'] ]) if scan['updated']: for count, nodule in enumerate(scan['nodules'], start=1): type_name = self.get_type_name(nodule['type']) n_item = QTreeWidgetItem(p, [ '', '', f'Nodule{count}', str(nodule['prob']), str(nodule['diameter']), type_name, str(nodule['calcification']), str(nodule['spiculation']), str(nodule['perifissural']), str(nodule['endobronchial']), nodule['score'] ]) for i in range(n_item.columnCount()): n_item.setTextAlignment(i, Qt.AlignHCenter) for i in range(p.columnCount()): p.setTextAlignment(i, Qt.AlignHCenter) self.noduletreeWidget.expandAll() @pyqtSlot() def on_actionPreferences_triggered(self): if not self.preferences_dialog: self.preferences_dialog = Preferences(self.data['preferences']) self.preferences_dialog.rejected.connect(self.update_preferences) self.preferences_dialog.show() def update_preferences(self): """ update preferences when OK in preferences dialog is clicked. """ self.data['preferences'] = self.preferences_dialog.preferences def on_treeWidget_itemClicked(self): index_member = self.treeWidget.currentIndex().row() self.refresh_scan_list(member=self.data['members'][index_member]) @pyqtSlot() def on_loadscanButton_clicked(self): fname, _filter = QFileDialog.getOpenFileName(self, 'open file', '~/Desktop', 'Scan (*.mhd *.nrrd)') # make up some patient information for .mhd file from LUNA16 faker = Faker() patient_name = faker.name() birth_date = faker.date() patient_sex = faker.profile()['sex'] scan_date = faker.date() # For general DICOM series ''' reader = sitk.ImageSeriesReader() reader = sitk.ImageSeriesReader() dir = '/Users/apple/Desktop/神農/一些參考/Patient CT EDU (Anonym-TR123)' seriesIDs = reader.GetGDCMSeriesIDs(dir) dcm_series = reader.GetGDCMSeriesFileNames(dir, seriesIDs[0]) reader.SetFileNames(dcm_series) reader.MetaDataDictionaryArrayUpdateOn() # Execute() is needed to GetMetaData img = reader.Execute() patient_name = reader.GetMetaData(0,'0010|0010').strip() birth_date = reader.GetMetaData(0,'0010|0030').strip() patient_sex = reader.GetMetaData(0,'0010|0040').strip() ''' exist = False for i, m in enumerate(self.data['members']): if patient_name == m['patient_name']: self.data['members'][i]['scans'].append({ 'updated': False, 'scan_path': fname, 'scan_date': scan_date, 'nodules': [] }) self.data['members'][i]['updated'] = False exist = True if not exist: self.data['members'].append({ 'updated': False, 'patient_name': patient_name, 'date_of_birth': birth_date, 'sex': patient_sex, 'score': '?', 'management': '?', 'scans': [{ 'updated': False, 'scan_path': fname, 'scan_date': scan_date, 'nodules': [] }] }) self.refresh_patient_list() @pyqtSlot() def on_displayButton_clicked(self): index_member = self.treeWidget.currentIndex().row() nodule_select = None if self.noduletreeWidget.selectedItems()[0].parent(): directory = self.noduletreeWidget.selectedItems()[0].parent().text( 2) nodule_select = self.noduletreeWidget.currentIndex().row() index_scan = self.noduletreeWidget.indexFromItem( self.noduletreeWidget.selectedItems()[0].parent()).row() else: directory = self.noduletreeWidget.selectedItems()[0].text(2) index_scan = self.noduletreeWidget.indexFromItem( self.noduletreeWidget.selectedItems()[0]).row() self.display_dialog = CthreeD() self.display_dialog.updata_data_signal.connect( partial(self.update_data, index_member, index_scan)) self.display_dialog.show() self.display_dialog.w = self.display_dialog.imgLabel_1.width() self.display_dialog.h = self.display_dialog.imgLabel_1.height() self.display_dialog.load_dicomfile( directory=directory, nodule_select=nodule_select, scan=self.data['members'][index_member]['scans'][index_scan]) def update_data(self, index_member, index_scan, data_csv): self.data['members'][index_member]['scans'][index_scan]['nodules'] = [] for row in data_csv: self.data['members'][index_member]['scans'][index_scan][ 'nodules'].append(row) self.refresh_scan_list(member=self.data['members'][index_member]) self.management(index_member) def mousePressEvent(self, event): if app.focusWidget(): self.setFocus() # TODO Not complete enough def management(self, index_member=None): """ Get highest Lung-RADS score and match the date to show management """ # diameter for solid component is needed for class 4 if nodule type is part-solid scores = [] scans_date = [] max_solid_component_diameter = 0 for s in self.data['members'][index_member]['scans']: y, m, d = s['scan_date'].split(sep='-') scans_date.append(datetime(int(y), int(m), int(d))) for n in s['nodules']: scores.append(n['score']) if n['type'] == '3': if eval(n['diameter'] ) * 0.5 > max_solid_component_diameter: max_solid_component_diameter = eval( n['diameter']) * 0.5 newest = datetime(1000, 1, 1) for scan_date in scans_date: if scan_date > newest: newest = scan_date management = '' if '?' in scores: max_score = '?' management = '?' else: breaker = False max_score = '0' for s in ['4X', '4B', '4A', '3', '2', '1', '0']: if scores.__len__() == 0: print('no nodule') max_score = '1' break for score in scores: if score == s: max_score = s breaker = True break if breaker: break if max_score == '0': management = 'Additional lung cancer screening CT images and/or comparison to ' \ 'prior chest CT examinations is needed' elif max_score == '1' or max_score == '2': management = f'LDCT @ {newest.date()+relativedelta(years=1)}' elif max_score == '3': management = f'LDCT @ {newest.date()+relativedelta(months=6)}' elif max_score == '4A': management = f'LDCT @ {newest.date()+relativedelta(months=3)}' if max_solid_component_diameter >= 8: management += ' (PET/CT may be used)' elif max_score == '4B' or max_score == '4X': management = f'Chest CT w/ or w/o contrast, PET/CT and/or tissue sampling may be used' # TODO 這邊是如果有新生大結節才要的 # management += '1 month LDCT may be recommended to # address potentially infectious or inflammatory conditions' self.data['members'][index_member]['score'] = max_score self.data['members'][index_member]['management'] = management self.refresh_patient_list() @pyqtSlot() def on_detectButton_clicked(self): # show status on statusbar self.statusBar().showMessage( 'Model predicting, please wait for a while ...') self.statusBar().repaint() QApplication.instance().processEvents() # TODO Check if selected scan is already detected index_member = self.treeWidget.currentIndex().row() index_scan = self.noduletreeWidget.currentIndex().row() if use_win10: csv_data = detect( self.data['members'][index_member]['scans'][index_scan] ['scan_path'], self.nodulenet_model, self.classification_model, self.data['preferences']) else: csv_data = None self.update_data(index_member, index_scan, csv_data) self.data['members'][index_member]['scans'][index_scan][ 'updated'] = True self.refresh_scan_list(self.data['members'][index_member]) status = [ scan['updated'] for scan in self.data['members'][index_member]['scans'] ] if False not in status: self.data['members'][index_member]['updated'] = True self.refresh_patient_list() self.statusBar().showMessage('Done.', msecs=5000) self.management(index_member) @pyqtSlot() def on_savechangesButton_clicked(self): messagebox = QMessageBox.warning( self, 'Are you sure you want to save changes?', 'You cannot undo this action, re-detect scans if necessary.', QMessageBox.Ok | QMessageBox.Cancel, QMessageBox.Ok) if messagebox == QMessageBox.Ok: with open(pkg_name, 'w') as json_file: json.dump(self.data, json_file, indent=2)
def init(self, context): self._log.debug("init") self._preferences = Preferences() self._show_tasks = self._preferences.get_bool("IssuesShowTasks", True) self._show_warnings = self._preferences.get_bool( "IssuesShowWarnings", True) self._context = context self._icons = { Issue.SEVERITY_WARNING: pixbuf_new_from_file(find_resource("icons/warning.png")), Issue.SEVERITY_ERROR: pixbuf_new_from_file(find_resource("icons/error.png")), Issue.SEVERITY_INFO: None, Issue.SEVERITY_TASK: pixbuf_new_from_file(find_resource("icons/task.png")) } self._store = gtk.ListStore(Pixbuf, str, str, object) self._view = gtk.TreeView(self._store) column = gtk.TreeViewColumn() column.set_title("Message") pixbuf_renderer = gtk.CellRendererPixbuf() column.pack_start(pixbuf_renderer, False) column.add_attribute(pixbuf_renderer, "pixbuf", 0) text_renderer = gtk.CellRendererText() column.pack_start(text_renderer, True) column.add_attribute(text_renderer, "markup", 1) self._view.append_column(column) self._view.insert_column_with_attributes(-1, "File", gtk.CellRendererText(), markup=2) self._handlers[self._view] = self._view.connect( "row-activated", self._on_row_activated) self._scr = gtk.ScrolledWindow() self._scr.add(self._view) self._scr.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self._scr.set_shadow_type(gtk.SHADOW_IN) self.pack_start(self._scr, True) # toolbar self._button_warnings = gtk.ToggleToolButton() self._button_warnings.set_tooltip_text("Show/Hide Warnings") image = gtk.Image() image.set_from_file(find_resource("icons/warning.png")) self._button_warnings.set_icon_widget(image) self._button_warnings.set_active(self._show_warnings) self._handlers[self._button_warnings] = self._button_warnings.connect( "toggled", self.__on_warnings_toggled) self._button_tasks = gtk.ToggleToolButton() self._button_tasks.set_tooltip_text("Show/Hide Tasks") imageTask = gtk.Image() imageTask.set_from_file(find_resource("icons/task.png")) self._button_tasks.set_icon_widget(imageTask) self._button_tasks.set_active(self._show_tasks) self._handlers[self._button_tasks] = self._button_tasks.connect( "toggled", self.__on_tasks_toggled) toolbar = gtk.Toolbar() toolbar.set_orientation(gtk.ORIENTATION_VERTICAL) toolbar.set_style(gtk.TOOLBAR_ICONS) toolbar.set_icon_size(gtk.ICON_SIZE_MENU) toolbar.insert(self._button_warnings, -1) toolbar.insert(self._button_tasks, -1) self.pack_start(toolbar, False) self._issues = [] self._preferences.register_monitor(self) self._log.debug("init finished")
class IndicatorSysmonitor(object): SENSORS_DISABLED = False def __init__(self): self._preferences_dialog = None self._help_dialog = None self.ind = Gtk.Button.new() self.ind.set_label("Init...") self._create_menu() self.alive = Event() self.alive.set() self.sensor_mgr = SensorManager() self.load_settings() def _create_menu(self): """Creates the main menu and shows it.""" # create menu {{{ menu = Gtk.Menu() # add System Monitor menu item full_sysmon = Gtk.MenuItem(_('System Monitor')) full_sysmon.connect('activate', self.on_full_sysmon_activated) menu.add(full_sysmon) menu.add(Gtk.SeparatorMenuItem()) # add preferences menu item pref_menu = Gtk.MenuItem(_('Preferences')) pref_menu.connect('activate', self.on_preferences_activated) menu.add(pref_menu) # add help menu item help_menu = Gtk.MenuItem(_('Help')) help_menu.connect('activate', self._on_help) menu.add(help_menu) menu.show_all() self.popup = menu self.ind.connect('clicked', self.popup_menu) logging.info("Menu shown") # }}} menu done! def popup_menu(self, *args): self.popup.popup(None, None, None, None, 0, Gtk.get_current_event_time()) def update_indicator_guide(self): guide = self.sensor_mgr.get_guide() def update(self, data): # data is the dict of all sensors and their values # { name, label } # look through data and find out if there are any icons to be set for sensor in data: test_str = data[sensor].lower() if "use_icon" in test_str: path = data[sensor].split(":")[1] print(path) self.ind.set_icon_full(path, "") # now strip the icon output from data so that it is not displayed remaining = test_str.split("use_icon")[0].strip() if not remaining: remaining = " " data[sensor] = remaining if "clear_icon" in test_str: self.ind.set_icon_full(self.tindicator, "") remaining = test_str.split("clear_icon")[0].strip() if not remaining: remaining = " " data[sensor] = remaining label = self.sensor_mgr.get_label(data) def update_label(label): self.ind.set_label(label) return False if label and self.ind: GLib.idle_add(update_label, label.strip()) def load_settings(self): self.sensor_mgr.load_settings() self.sensor_mgr.initiate_fetcher(self) self.update_indicator_guide() # @staticmethod def save_settings(self): self.sensor_mgr.save_settings() def update_settings(self): self.sensor_mgr.initiate_fetcher(self) # actions raised from menu def on_preferences_activated(self, event=None): """Raises the preferences dialog. If it's already open, it's focused""" if self._preferences_dialog is not None: self._preferences_dialog.present() return self._preferences_dialog = Preferences(self) self._preferences_dialog.run() self._preferences_dialog = None def on_full_sysmon_activated(self, event=None): os.system('gnome-system-monitor &') def on_exit(self, event=None, data=None): """Action call when the main programs is closed.""" # cleanup temporary indicator icon os.remove(self.tindicator) # close the open dialogs if self._help_dialog is not None: self._help_dialog.destroy() if self._preferences_dialog is not None: self._preferences_dialog.destroy() logging.info("Terminated") self.alive.clear() # DM: why bother with Event() ??? try: Gtk.main_quit() except RuntimeError: pass def _on_help(self, event=None, data=None): """Raise a dialog with info about the app.""" if self._help_dialog is not None: self._help_dialog.present() return self._help_dialog = Gtk.MessageDialog( None, Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, None) self._help_dialog.set_title(_("Help")) self._help_dialog.set_markup(HELP_MSG) self._help_dialog.run() self._help_dialog.destroy() self._help_dialog = None
class IssueView(BottomView, IPreferencesMonitor): """ """ _log = getLogger("IssueView") label = "Issues" icon = gtk.STOCK_DIALOG_INFO scope = View.SCOPE_EDITOR def __init__(self, context, editor): BottomView.__init__(self, context) self._editor = editor self._handlers = {} def init(self, context): self._log.debug("init") self._preferences = Preferences() self._show_tasks = self._preferences.get_bool("IssuesShowTasks", True) self._show_warnings = self._preferences.get_bool( "IssuesShowWarnings", True) self._context = context self._icons = { Issue.SEVERITY_WARNING: pixbuf_new_from_file(find_resource("icons/warning.png")), Issue.SEVERITY_ERROR: pixbuf_new_from_file(find_resource("icons/error.png")), Issue.SEVERITY_INFO: None, Issue.SEVERITY_TASK: pixbuf_new_from_file(find_resource("icons/task.png")) } self._store = gtk.ListStore(Pixbuf, str, str, object) self._view = gtk.TreeView(self._store) column = gtk.TreeViewColumn() column.set_title("Message") pixbuf_renderer = gtk.CellRendererPixbuf() column.pack_start(pixbuf_renderer, False) column.add_attribute(pixbuf_renderer, "pixbuf", 0) text_renderer = gtk.CellRendererText() column.pack_start(text_renderer, True) column.add_attribute(text_renderer, "markup", 1) self._view.append_column(column) self._view.insert_column_with_attributes(-1, "File", gtk.CellRendererText(), markup=2) self._handlers[self._view] = self._view.connect( "row-activated", self._on_row_activated) self._scr = gtk.ScrolledWindow() self._scr.add(self._view) self._scr.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self._scr.set_shadow_type(gtk.SHADOW_IN) self.pack_start(self._scr, True) # toolbar self._button_warnings = gtk.ToggleToolButton() self._button_warnings.set_tooltip_text("Show/Hide Warnings") image = gtk.Image() image.set_from_file(find_resource("icons/warning.png")) self._button_warnings.set_icon_widget(image) self._button_warnings.set_active(self._show_warnings) self._handlers[self._button_warnings] = self._button_warnings.connect( "toggled", self.__on_warnings_toggled) self._button_tasks = gtk.ToggleToolButton() self._button_tasks.set_tooltip_text("Show/Hide Tasks") imageTask = gtk.Image() imageTask.set_from_file(find_resource("icons/task.png")) self._button_tasks.set_icon_widget(imageTask) self._button_tasks.set_active(self._show_tasks) self._handlers[self._button_tasks] = self._button_tasks.connect( "toggled", self.__on_tasks_toggled) toolbar = gtk.Toolbar() toolbar.set_orientation(gtk.ORIENTATION_VERTICAL) toolbar.set_style(gtk.TOOLBAR_ICONS) toolbar.set_icon_size(gtk.ICON_SIZE_MENU) toolbar.insert(self._button_warnings, -1) toolbar.insert(self._button_tasks, -1) self.pack_start(toolbar, False) self._issues = [] self._preferences.register_monitor(self) self._log.debug("init finished") def _on_row_activated(self, view, path, column): """ A row has been double-clicked on """ issue = self._store.get(self._store.get_iter(path), 3)[0] self._context.activate_editor(issue.file) #~ # FIXME: this doesn't work correctly #~ if not self._context.active_editor is None: #~ self._context.active_editor.select(issue.start, issue.end) self._editor.select(issue.start, issue.end) def _on_value_changed(self, key, value): if key == "IssuesShowWarnings" or key == "IssuesShowTasks": # update filter self._store.clear() for issue, local in self._issues: self.__append_issue_filtered(issue, local) def __on_tasks_toggled(self, togglebutton): self._show_tasks = togglebutton.get_active() self._preferences.set("IssuesShowTasks", self._show_tasks) def __on_warnings_toggled(self, togglebutton): self._show_warnings = togglebutton.get_active() self._preferences.set("IssuesShowWarnings", self._show_warnings) def clear(self): """ Remove all issues from the view """ self.assure_init() self._store.clear() self._issues = [] def append_issue(self, issue, local=True): """ Append a new Issue to the view @param issue: the Issue object @param local: indicates whether the Issue occured in the edited file or not """ self.assure_init() self._issues.append((issue, local)) self.__append_issue_filtered(issue, local) def __append_issue_filtered(self, issue, local): if issue.severity == Issue.SEVERITY_WARNING: if self._show_warnings: self.__do_append_issue(issue, local) elif issue.severity == Issue.SEVERITY_TASK: if self._show_tasks: self.__do_append_issue(issue, local) else: self.__do_append_issue(issue, local) def __do_append_issue(self, issue, local): if local: message = issue.message filename = escape(issue.file.basename) else: message = "<span color='%s'>%s</span>" % (self._preferences.get( "LightForeground", "#7f7f7f"), issue.message) filename = "<span color='%s'>%s</span>" % (self._preferences.get( "LightForeground", "#7f7f7f"), issue.file.basename) self._store.append( [self._icons[issue.severity], message, filename, issue]) def destroy(self): del self._editor self._preferences.remove_monitor(self) for obj in self._handlers: obj.disconnect(self._handlers[obj]) BottomView.destroy(self)
def open_preferences_window(self): """Opens settings window.""" settings = Preferences(self) if settings.exec(): self.server_IP = settings.server_IP.text()
class ANoise: """Control the sound indicator""" def __init__(self): # These 3 are need GObject.threads_init() DBusGMainLoop(set_as_default=True) Gst.init(None) self.sound_menu = SoundMenuControls('anoise') self.noise = Noise() self.win_preferences = Preferences(self) # Need in a few DE try: self.window = GUI(self) except: pass self.player = Gst.ElementFactory.make(PLAYBIN, "player") self.player.connect("about-to-finish", self._loop) self.player.set_property('uri', self.noise.get_current_filename()) self.is_playing = True dummy_i18n = (_("Coffee Shop"), _("Fire"), _("Forest"), _("Night"), _("Rain"), _("River"), _("Sea"), _("Storm"), _("Wind") ) # Need i18n # Overwrite libraty methods self.sound_menu._sound_menu_is_playing = self._sound_menu_is_playing self.sound_menu._sound_menu_play = self._sound_menu_play self.sound_menu._sound_menu_pause = self._sound_menu_pause self.sound_menu._sound_menu_next = self._sound_menu_next self.sound_menu._sound_menu_previous = self._sound_menu_previous self.sound_menu._sound_menu_raise = self._sound_menu_raise # Autostart when click on sound indicator icon threading.Timer(2, self._sound_menu_play).start() def _loop(self, message): """Start again the same sound in the EOS""" self.player.set_property('uri', self.noise.get_current_filename()) def _sound_menu_is_playing(self): """Called in the first click""" return self.is_playing def _sound_menu_play(self): """Play""" self.is_playing = True # Need to overwrite this for an issue with autstart self.sound_menu.song_changed('', '', self.noise.get_name(), self.noise.get_icon()) self.player.set_state(Gst.State.PLAYING) self.sound_menu.signal_playing() def _sound_menu_pause(self): """Pause""" self.is_playing = False # Need to overwrite this for an issue with autstart self.player.set_state(Gst.State.PAUSED) self.sound_menu.signal_paused() def _set_new_play(self, what): """Next or Previous""" self.noise.refresh_all_ogg() # Get Next/Previous if what == 'next': self.noise.set_next() if what == 'previous': self.noise.set_previous() # From pause? self.player.set_state(Gst.State.READY) if not self.is_playing: self.is_playing = True # Set new sound self.player.set_property('uri', self.noise.get_current_filename()) # Play self._sound_menu_play() def _sound_menu_previous(self): """Previous""" self._set_new_play('previous') def _sound_menu_next(self): """Next""" self._set_new_play('next') def _sound_menu_raise(self): """Click on player""" self.win_preferences.show() def set_timer(self, enable, seconds): if enable: self.timer = threading.Timer(seconds, self._set_future_pause) self.timer.start() else: self.timer.cancel() def _set_future_pause(self): self.win_preferences.set_show_timer() self._sound_menu_pause()
def storeSliderValue(self): if self.sizeButton.isChecked(): if self.editMode == editModes.newTextBox: Preferences.updateKeyValue('textSize', self.slider.value()) elif self.editMode == editModes.marker: Preferences.updateKeyValue('markerSize', self.slider.value()) elif self.editMode == editModes.freehand: Preferences.updateKeyValue('freehandSize', self.slider.value()) elif self.editMode == editModes.forms: Preferences.updateKeyValue('formSize', self.slider.value()) elif self.colorButton.isChecked(): normRGB = colorsys.hsv_to_rgb(self.slider.value() / 100, 1, 1) if self.editMode == editModes.marker: Preferences.updateKeyValue( 'markerColor', tuple(map(lambda x: str(x), normRGB))) elif self.editMode == editModes.freehand: Preferences.updateKeyValue( 'freehandColor', tuple(map(lambda x: str(x), normRGB))) elif self.editMode == editModes.forms: Preferences.updateKeyValue( 'formColor', tuple(map(lambda x: str(x), normRGB))) self.settingsChanged.emit()
class GtkUI(GtkPluginBase): def __init__(self, plugin_name): super(GtkUI, self).__init__(plugin_name) self.initialized = False self.retries = 0 def enable(self): self.timestamp = None self.label_data = None client.labelplus.is_initialized().addCallback(self.cb_check) def cb_check(self, result): if result == True: client.labelplus.get_label_data(self.timestamp).addCallback( self.cb_data_init) elif self.retries < MAX_RETRIES: reactor.callLater(WAIT_TIME, self.enable) self.retries += 1 def cb_data_init(self, data): self.timestamp = data[0] self.label_data = data[1] self.label_data[ID_ALL]["name"] = _(ID_ALL) self.label_data[ID_NONE]["name"] = _(ID_NONE) self._do_load() def _do_load(self): self._config = deluge.configmanager.ConfigManager( GTKUI_CONFIG, defaults=GTKUI_DEFAULTS) component.get("TorrentView").add_text_column(DISPLAY_NAME, status_field=[STATUS_NAME]) self.label_selection_menu = LabelSelectionMenu() self.sep = component.get("MenuBar").add_torrentmenu_separator() component.get("MenuBar").torrentmenu.append(self.label_selection_menu) self.label_sidebar = LabelSidebar() self.preferences = Preferences() self.add_torrent_ext = AddTorrentExt() self.enable_dnd() self.initialized = True def disable(self): self.retries = MAX_RETRIES if self.initialized: self.initialized = False self._config.save() deluge.configmanager.close(self._config) self.disable_dnd() component.get("MenuBar").torrentmenu.remove(self.sep) component.get("MenuBar").torrentmenu.remove(self.label_selection_menu) self.label_selection_menu.destroy() del self.label_selection_menu self.label_sidebar.unload() del self.label_sidebar self.preferences.unload() self.add_torrent_ext.unload() component.get("TorrentView").remove_column(DISPLAY_NAME) def update(self): if self.initialized: client.labelplus.get_label_data(self.timestamp).addCallback( self.cb_update_data) def cb_update_data(self, data): if data is not None: self.timestamp = data[0] self.label_data = data[1] self.label_data[ID_ALL]["name"] = _(ID_ALL) self.label_data[ID_NONE]["name"] = _(ID_NONE) self.label_sidebar.update_counts(self.label_data) def get_labels(self): data = self.label_data labels = [] for id in data: if id not in RESERVED_IDS: labels.append((id, data[id]["name"])) return labels def get_label_counts(self): return self.label_data def enable_dnd(self): def get_drag_icon(widget, x, y): num = widget.get_selection().count_selected_rows() if num > 1: pixbuf = self.icon_multiple else: pixbuf = self.icon_single return (pixbuf, 0, 0) def get_ids(widget, path, col, selection, *args): selection.set("TEXT", 8, "OK") return True def receive_ids(widget, path, col, pos, selection, *args): if selection.data == "OK": model = widget.get_model() id = model[path][0] if id == ID_NONE: id = None if id not in RESERVED_IDS: torrents = component.get("TorrentView").get_selected_torrents() client.labelplus.set_torrent_labels(id, torrents) return True def peek_ids(widget, path, col, pos, selection, *args): if selection.data == "OK": model = widget.get_model() id = model[path][0] if id == ID_NONE: id = None if id not in RESERVED_IDS: return True class ModuleFilter(object): def filter(self, record): record.msg = "[%s] %s" % (PLUGIN_NAME, record.msg) return True dnd.log.setLevel(logging.INFO) dnd.log.addFilter(ModuleFilter()) src_target = dnd.DragTarget( name="torrent_ids", scope=gtk.TARGET_SAME_APP, action=gtk.gdk.ACTION_MOVE, data_func=get_ids, ) src_treeview = component.get("TorrentView").treeview self.icon_single = \ src_treeview.render_icon(gtk.STOCK_DND, gtk.ICON_SIZE_DND) self.icon_multiple = \ src_treeview.render_icon(gtk.STOCK_DND_MULTIPLE, gtk.ICON_SIZE_DND) self.src_proxy = dnd.TreeViewDragSourceProxy(src_treeview, get_drag_icon) self.src_proxy.add_target(src_target) dest_target = dnd.DragTarget( name="torrent_ids", scope=gtk.TARGET_SAME_APP, action=gtk.gdk.ACTION_MOVE, pos=gtk.TREE_VIEW_DROP_INTO_OR_BEFORE, data_func=receive_ids, aux_func=peek_ids, ) dest_treeview = self.label_sidebar.label_tree self.dest_proxy = dnd.TreeViewDragDestProxy(dest_treeview) self.dest_proxy.add_target(dest_target) def disable_dnd(self): self.dest_proxy.unload() self.src_proxy.unload()
class IndicatorSysmonitor(object): SENSORS_DISABLED = False def __init__(self): self._preferences_dialog = None self._help_dialog = None #fn, self.tindicator = tempfile.mkstemp(suffix=".svg") #with open(self.tindicator, "w") as f: # svg = '<?xml version="1.0" encoding="UTF-8" \ # standalone="no"?><svg id="empty" xmlns="http://www.w3.org/2000/svg" \ # height="22" width="1" version="1.0" \ # xmlns:xlink="http://www.w3.org/1999/xlink"></svg>' # f.write(svg) # f.close() #self.ind = appindicator.Indicator.new("indicator-sysmonitor", self.tindicator, \ # appindicator.IndicatorCategory.SYSTEM_SERVICES) self.ind = Gtk.Button.new() #self.ind.set_ordering_index(0) #self.ind.set_status(appindicator.IndicatorStatus.ACTIVE) self.ind.set_label("Init...") self._create_menu() self.alive = Event() self.alive.set() self.sensor_mgr = SensorManager() self.load_settings() def _create_menu(self): """Creates the main menu and shows it.""" # create menu {{{ menu = Gtk.Menu() # add System Monitor menu item full_sysmon = Gtk.MenuItem(_('System Monitor')) full_sysmon.connect('activate', self.on_full_sysmon_activated) menu.add(full_sysmon) menu.add(Gtk.SeparatorMenuItem()) # add preferences menu item pref_menu = Gtk.MenuItem(_('Preferences')) pref_menu.connect('activate', self.on_preferences_activated) menu.add(pref_menu) # add help menu item help_menu = Gtk.MenuItem(_('Help')) help_menu.connect('activate', self._on_help) menu.add(help_menu) # add preference menu item #exit_menu = Gtk.MenuItem(_('Quit')) #exit_menu.connect('activate', self.on_exit) #menu.add(exit_menu) menu.show_all() self.popup = menu self.ind.connect('clicked', self.popup_menu) logging.info("Menu shown") # }}} menu done! def popup_menu(self, *args): self.popup.popup(None, None, None, None, 0, Gtk.get_current_event_time()) def update_indicator_guide(self): guide = self.sensor_mgr.get_guide() #self.ind.set_property("label-guide", guide) def update(self, data): # data is the dict of all sensors and their values # { name, label } # look through data and find out if there are any icons to be set for sensor in data: test_str = data[sensor].lower() if "use_icon" in test_str: path = data[sensor].split(":")[1] print(path) self.ind.set_icon_full(path, "") # now strip the icon output from data so that it is not displayed remaining = test_str.split("use_icon")[0].strip() if not remaining: remaining = " " data[sensor] = remaining if "clear_icon" in test_str: self.ind.set_icon_full(self.tindicator, "") remaining = test_str.split("clear_icon")[0].strip() if not remaining: remaining = " " data[sensor] = remaining label = self.sensor_mgr.get_label(data) Gdk.threads_enter() self.ind.set_label(label.strip()) Gdk.threads_leave() #self.ind.set_title(label.strip()) def load_settings(self): self.sensor_mgr.load_settings() self.sensor_mgr.initiate_fetcher(self) self.update_indicator_guide() # @staticmethod def save_settings(self): self.sensor_mgr.save_settings() # actions raised from menu def on_preferences_activated(self, event=None): """Raises the preferences dialog. If it's already open, it's focused""" if self._preferences_dialog is not None: self._preferences_dialog.present() return self._preferences_dialog = Preferences(self) self._preferences_dialog.run() self._preferences_dialog = None def on_full_sysmon_activated(self, event=None): os.system('gnome-system-monitor &') def on_exit(self, event=None, data=None): """Action call when the main programs is closed.""" # cleanup temporary indicator icon os.remove(self.tindicator) # close the open dialogs if self._help_dialog is not None: self._help_dialog.destroy() if self._preferences_dialog is not None: self._preferences_dialog.destroy() logging.info("Terminated") self.alive.clear() # DM: why bother with Event() ??? try: Gtk.main_quit() except RuntimeError: pass def _on_help(self, event=None, data=None): """Raise a dialog with info about the app.""" if self._help_dialog is not None: self._help_dialog.present() return self._help_dialog = Gtk.MessageDialog( None, Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, None) self._help_dialog.set_title(_("Help")) self._help_dialog.set_markup(HELP_MSG) self._help_dialog.run() self._help_dialog.destroy() self._help_dialog = None
def initialize_with_dict(self): self.defaults_with_dict = {"x1": 1, "x2": 2, "x3": 3} P = Preferences(defaults=self.defaults_with_dict, filename=self.filename) return P
def initialize_with_keywords(self): P = Preferences(filename=self.filename, x1=1, x2=2, x3=3) return P
class GtkUI(GtkPluginBase): def __init__(self, plugin_name): super(GtkUI, self).__init__(plugin_name) self.initialized = False def enable(self): client.labelplus.is_initialized().addCallback(self.cb_check) def cb_check(self, result): if result == True: client.labelplus.get_label_data(None).addCallback(self.cb_data_init) else: reactor.callLater(1, self.enable) def cb_data_init(self, data): self.dialog = None self._config = None info = client.connection_info() self._daemon = "%s@%s:%s" % (info[2], info[0], info[1]) self.timestamp = data[0] self.label_data = data[1] self.label_data[ID_ALL]["name"] = _(ID_ALL) self.label_data[ID_NONE]["name"] = _(ID_NONE) self._do_load() def _do_load(self): self.load_config() component.get("TorrentView").add_text_column(DISPLAY_NAME, col_type=[str, str], status_field=[STATUS_NAME, STATUS_ID]) component.get("TorrentView").treeview.connect( "button-press-event", self.on_tv_button_press) self.menu = self._create_context_menu() self.sep = component.get("MenuBar").add_torrentmenu_separator() component.get("MenuBar").torrentmenu.append(self.menu) self.label_sidebar = LabelSidebar() self.preferences = Preferences() self.add_torrent_ext = AddTorrentExt() self.enable_dnd() self.status_item = None self.initialized = True def on_tv_button_press(self, widget, event): x, y = event.get_coords() path_info = widget.get_path_at_pos(int(x), int(y)) if not path_info: if event.button == 3: self._popup_jump_menu(widget, event) else: return if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS: if path_info[1] and path_info[1].get_title() == DISPLAY_NAME: id = self.get_selected_torrent_label() if (self.label_sidebar.page_selected() and id == self.label_sidebar.get_selected_label()): self._do_open_label_options(widget, event) else: self._do_go_to_label(widget) def disable(self): if self.initialized: self.initialized = False self._config.save() deluge.configmanager.close(GTKUI_CONFIG) self._remove_status_bar_item() self.disable_dnd() component.get("MenuBar").torrentmenu.remove(self.sep) component.get("MenuBar").torrentmenu.remove(self.menu) self._destroy_menu() self.label_sidebar.unload() del self.label_sidebar self.preferences.unload() self.add_torrent_ext.unload() component.get("TorrentView").remove_column(DISPLAY_NAME) def _create_context_menu(self): menu = gtk.MenuItem(DISPLAY_NAME) submenu = gtk.Menu() jump_menu = self._create_jump_menu() submenu.append(jump_menu) set_label_menu = self._create_set_label_menu() submenu.append(set_label_menu) label_options_item = self._create_label_options_item() submenu.append(label_options_item) def on_activate(widget): id = self.get_selected_torrent_label() if id not in RESERVED_IDS and id in self.label_data: label_options_item.show() else: label_options_item.hide() menu.connect("activate", on_activate) menu.set_submenu(submenu) menu.show_all() return menu def _create_label_options_item(self): def on_activate(widget): id = self.get_selected_torrent_label() if id not in RESERVED_IDS and id in self.label_data: name = self.label_data[id]["name"] self.label_sidebar.menu.dialog = LabelOptionsDialog(id, name) self.label_sidebar.menu.dialog.register_close_func( self.label_sidebar.menu.close_func) item = gtk.MenuItem(_("Label Options")) item.connect("activate", on_activate) return item def _create_set_label_menu(self): def on_select_label(widget, label_id): torrents = component.get("TorrentView").get_selected_torrents() client.labelplus.set_torrent_labels(label_id, torrents) def hide_unavailable(widget): parent_item.hide() id = self.get_selected_torrent_label() if id: parent = get_parent(id) if parent and parent not in RESERVED_IDS: if getattr(parent_item, "handler", None): parent_item.disconnect(parent_item.handler) handler = parent_item.connect("activate", on_select_label, parent) parent_item.handler = handler parent_item.show() items = [] menu_item = gtk.MenuItem(_(ID_NONE)) menu_item.connect("activate", on_select_label, ID_NONE) items.append(menu_item) parent_item = gtk.MenuItem(_("Parent")) items.append(parent_item) menu_item = gtk.SeparatorMenuItem() items.append(menu_item) menu = LabelSelectionMenu(_("Set Label"), on_select_label, items) menu.connect("activate", hide_unavailable) return menu def _create_jump_menu(self): def on_select_label(widget, label_id): self._do_go_to_label(widget, label_id) def hide_unavailable(widget): selected_item.hide() parent_item.hide() id = self.get_selected_torrent_label() if id: if getattr(selected_item, "handler", None): selected_item.disconnect(selected_item.handler) handler = selected_item.connect("activate", on_select_label, id) selected_item.handler = handler selected_item.show() elif self.label_sidebar.page_selected(): id = self.label_sidebar.get_selected_label() if id: parent = get_parent(id) if parent and parent not in RESERVED_IDS: if getattr(parent_item, "handler", None): parent_item.disconnect(parent_item.handler) handler = parent_item.connect("activate", on_select_label, parent) parent_item.handler = handler parent_item.show() items = [] menu_item = gtk.MenuItem(_(ID_ALL)) menu_item.connect("activate", on_select_label, ID_ALL) items.append(menu_item) menu_item = gtk.MenuItem(_(ID_NONE)) menu_item.connect("activate", on_select_label, ID_NONE) items.append(menu_item) selected_item = gtk.MenuItem(_("Selected")) items.append(selected_item) parent_item = gtk.MenuItem(_("Parent")) items.append(parent_item) menu_item = gtk.SeparatorMenuItem() items.append(menu_item) menu = LabelSelectionMenu(_("Jump To"), on_select_label, items) menu.connect("activate", hide_unavailable) return menu def _popup_jump_menu(self, widget, event): top = gtk.Menu() menu = gtk.MenuItem(DISPLAY_NAME) submenu = gtk.Menu() submenu.append(self._create_jump_menu()) menu.set_submenu(submenu) top.append(menu) top.show_all() top.popup(None, None, None, event.button, event.time) def _destroy_menu(self): self.menu.destroy() del self.menu def _do_go_to_label(self, widget, id=None): if not id: id = self.get_selected_torrent_label() if id is not None: self.label_sidebar.select_label(id) def load_config(self): self._config = deluge.configmanager.ConfigManager(GTKUI_CONFIG) source = get_version(self._config.config) target = get_version(GTKUI_DEFAULTS) if len(self._config.config) == 0: self._config._Config__config = copy.deepcopy(GTKUI_DEFAULTS) else: if source != target: map = GTKUI_MAPS.get((source, target), None) if map: self._config._Config__config = convert(self._config.config, map) else: self._config._Config__config = copy.deepcopy(GTKUI_DEFAULTS) else: self.normalize_config() if target >= 2: daemons = self._config["daemon"] if self._daemon not in daemons: daemons[self._daemon] = copy.deepcopy(DAEMON_DEFAULTS) def normalize_config(self): commons = dict(GTKUI_DEFAULTS["common"]) commons.update(self._config.config["common"]) self._config.config["common"] = commons saved_daemons = component.get("ConnectionManager").config["hosts"] if not saved_daemons: self._config["daemon"] = {} else: daemons = ["%s@%s:%s" % (x[3], x[1], x[2]) for x in saved_daemons] for daemon in self._config["daemon"].keys(): if "@localhost:" in daemon or "@127.0.0.1:" in daemon: continue if daemon != self._daemon and daemon not in daemons: del self._config["daemon"][daemon] def update(self): if self.initialized: client.labelplus.get_label_data(self.timestamp).addCallback( self.cb_update_data) if self._config["common"]["show_label_bandwidth"]: if not self.status_item: self._add_status_bar_item() reactor.callLater(1, self._status_bar_update) else: self._remove_status_bar_item() def cb_update_data(self, data): if data is not None: self.timestamp = data[0] self.label_data = data[1] self.label_data[ID_ALL]["name"] = _(ID_ALL) self.label_data[ID_NONE]["name"] = _(ID_NONE) self.label_sidebar.update_counts(self.label_data) def get_labels(self): data = self.label_data labels = [] for id in data: if id not in RESERVED_IDS: labels.append((id, data[id]["name"])) return labels def get_label_counts(self): return self.label_data def enable_dnd(self): def get_drag_icon(widget, x, y): num = widget.get_selection().count_selected_rows() if num > 1: pixbuf = self.icon_multiple else: pixbuf = self.icon_single return (pixbuf, 0, 0) def on_drag_end(widget, context): if self.label_sidebar.page_selected(): self.label_sidebar.label_tree.get_selection().emit("changed") def get_ids(widget, path, col, selection, *args): selection.set("TEXT", 8, "OK") return True def receive_ids(widget, path, col, pos, selection, *args): if selection.data == "OK": model = widget.get_model() id = model[path][0] if id == ID_NONE: id = None if id not in RESERVED_IDS: torrents = component.get("TorrentView").get_selected_torrents() client.labelplus.set_torrent_labels(id, torrents) return True def peek_ids(widget, path, col, pos, selection, *args): if selection.data == "OK": model = widget.get_model() id = model[path][0] if id == ID_NONE: id = None if id not in RESERVED_IDS: return True class ModuleFilter(object): def filter(self, record): record.msg = "[%s] %s" % (PLUGIN_NAME, record.msg) return True dnd.log.setLevel(logging.INFO) dnd.log.addFilter(ModuleFilter()) src_target = dnd.DragTarget( name="torrent_ids", scope=gtk.TARGET_SAME_APP, action=gtk.gdk.ACTION_MOVE, data_func=get_ids, ) src_treeview = component.get("TorrentView").treeview self.icon_single = \ src_treeview.render_icon(gtk.STOCK_DND, gtk.ICON_SIZE_DND) self.icon_multiple = \ src_treeview.render_icon(gtk.STOCK_DND_MULTIPLE, gtk.ICON_SIZE_DND) self.src_proxy = dnd.TreeViewDragSourceProxy(src_treeview, get_drag_icon, on_drag_end) self.src_proxy.add_target(src_target) dest_target = dnd.DragTarget( name="torrent_ids", scope=gtk.TARGET_SAME_APP, action=gtk.gdk.ACTION_MOVE, pos=gtk.TREE_VIEW_DROP_INTO_OR_BEFORE, data_func=receive_ids, aux_func=peek_ids, ) dest_treeview = self.label_sidebar.label_tree self.dest_proxy = dnd.TreeViewDragDestProxy(dest_treeview) self.dest_proxy.add_target(dest_target) def disable_dnd(self): self.dest_proxy.unload() self.src_proxy.unload() def _add_status_bar_item(self): self.status_item = component.get("StatusBar").add_item( image=get_resource("labelplus_icon.png"), text="", callback=self._do_open_label_options_bandwidth, tooltip="") self.status_item._ebox.hide_all() def _remove_status_bar_item(self): if self.status_item: component.get("StatusBar").remove_item(self.status_item) self.status_item = None def get_selected_torrent_label(self): label_id = None tv = component.get("TorrentView") torrents = tv.get_selected_torrents() if len(torrents) > 0: id = torrents[0] status = tv.get_torrent_status(id) if STATUS_ID in status: label_id = status[STATUS_ID] or ID_NONE for t in torrents: status = tv.get_torrent_status(t) t_label_id = status[STATUS_ID] or ID_NONE if t_label_id != label_id: label_id = None break return label_id def _do_open_label_options_bandwidth(self, widget, event): self._do_open_label_options(widget, event, 1) def _do_open_label_options(self, widget, event, page=0): def on_close(widget): self.dialog = None if self.dialog == None: id = self.label_sidebar.get_selected_label() if id == ID_ALL or not self.label_sidebar.page_selected(): id = self.get_selected_torrent_label() if id not in RESERVED_IDS and id in self.label_data: name = self.label_data[id]["full_name"] self.dialog = LabelOptionsDialog(id, name, page) self.dialog.register_close_func(on_close) def _status_bar_update(self): if self.status_item: id = self.get_selected_torrent_label() if not id and self.label_sidebar.page_selected(): id = self.label_sidebar.get_selected_label() if id == ID_NONE or (id not in RESERVED_IDS and id in self.label_data): self.status_item._ebox.show_all() tooltip = "Bandwidth Used By: %s" % self.label_data[id]["full_name"] include_sublabels = self._config["common"]["status_include_sublabel"] if include_sublabels and id != ID_NONE: tooltip += "/*" self.status_item.set_tooltip(tooltip) client.labelplus.get_label_bandwidth_usage( id, include_sublabels).addCallbacks( self._do_status_bar_update, self._err_status_bar_update) else: self.status_item._ebox.hide_all() reactor.callLater(STATUS_UPDATE_INTERVAL, self._status_bar_update) def _err_status_bar_update(self, result): reactor.callLater(STATUS_UPDATE_INTERVAL, self._status_bar_update) def _do_status_bar_update(self, result): if self.status_item: download_rate = result[0] download_unit = "B" upload_rate = result[1] upload_unit = "B" for (unit, bytes) in UNITS: if download_rate >= bytes: download_rate /= bytes download_unit = unit break for (unit, bytes) in UNITS: if upload_rate >= bytes: upload_rate /= bytes upload_unit = unit break self.status_item.set_text( "%.1f %s/s | %.1f %s/s" % ( download_rate, download_unit, upload_rate, upload_unit)) reactor.callLater(STATUS_UPDATE_INTERVAL, self._status_bar_update)
def initialize_with_absolute_path(self): absolute_path = os.path.join(CURRENT_PATH, self.filename) P = Preferences(defaults=self.defaults_with_dict, filename=absolute_path) return P
def open_preferences(self, widget): ConfigManager.disable_losefocus_temporary = True prefs = Preferences() prefs.show()
def __init__(self, player): # apparently appindicator will not quit on Ctrl-C by default. fix # bellow allows it to do so in Ctrl-C run the default action kernel # action which allows indicator to exit signal.signal(signal.SIGINT, signal.SIG_DFL) # expose the passing player to tht class self._player = player # remove registration to dbus, disabling MPRIS integration, mainly this # is done because current anoise MPRIS integration does not notify the # GUI element of play/pause/next/forward changes internally an attempt # at dbus manager that listens for anoise mpris notification fails due # to double signaling and handling of multiple MPRIS subscribed clients # and inability to distinguish which come from anoise self._player.sound_menu.remove_from_connection() #: DEBUG SETTING, used during development #: hide window ui, if it's the GUI class (rather then Indicator class) # if self._player.window.__class__.__name__ == 'GUI': # self._player.window.window.hide() # build the preferences window self._preferences_window = Preferences(self) # expose the default gtk settings self._gtk_settings = Gtk.Settings.get_default() # expose the default icon theme self._default_icon_theme = Gtk.IconTheme.get_default() # expose "hicolor" theme as fallback theme self._fallback_icon_theme = Gtk.IconTheme() self._fallback_icon_theme.set_custom_theme('hicolor') # expose found appindicator and appindicator-pause icons self._appindicator_icon, self._appindicator_icon_pause = \ self._get_indicator_icons() # build the appindicator self._appindicator, builder = self._make_appindicator() # expose the play/pause menu item to the class self._menuitem_play = builder.get_object('play_pause_toggle') # expose now playing menu item self._menuitem_now_playing = builder.get_object('now_playing') # expose now playing image self._image_now_playing = builder.get_object('image_now_playing') # expose play image self._image_play = builder.get_object('image_play') # expose pause image self._image_pause = builder.get_object('image_pause') # disable startup autoplay (ugh, terrible approach) # runs before indicator is made visible to show the "paused" icon self._disable_startup_autoplay() # set the indicator status to active self._appindicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE) # update the noise icon in the ui and the appindicator self._update_now_playing()
## 'reset_to_default(*args)'. ## ## It is also possible to incorporate automatic checks, that for example ## can check the instance or format of the saved value automatically. ## This requires overriding the method 'check_before_setting_attribute". ## ## For more information on all the methods and/or examples see the ## docstring [help(Preferences)]. ## ## ## Simple example: from preferences import Preferences prefs_defaults = {"X": 1, "Y": 2} prefs = Preferences(defaults=prefs_defaults, filename="preferences_test.txt") # At first use, attributes are initialized to default # If previous uses set them at different values, the default value will # not override the 'different value'. assert prefs.X == 1 and prefs.Y == 2 # True # By setting the following attributes, their new values are # automatically stored into the file. prefs.X = 3 prefs.Y = 4 # attributes can be defined without default values. prefs.Z = 5 # RESTART program (re-initializing 'prefs' gives the same results as
def __init__(self): self.preferences = Preferences() parser = argparse.ArgumentParser( description="Manipulate Tabletop Simulator files") parser.add_argument("-d", "--directory", help="Override TTS cache directory") parser.add_argument("-l", "--loglevel", help="Set logging level", choices=['debug', 'info', 'warn', 'error']) subparsers = parser.add_subparsers(dest='parser', title='command', description='Valid commands.') subparsers.required = True # add list command parser_list = subparsers.add_parser('list', help="List installed mods.", description=''' List installed mods. If no id is provided, then this will return a list of all installed modules. If an id is provided, then this will list the contents of that modules. ''') group_list = parser_list.add_mutually_exclusive_group() group_list.add_argument("-w", "--workshop", action="store_const", metavar='save_type', dest='save_type', const=SaveType.workshop, help="List workshop files (the default).") group_list.add_argument("-s", "--save", action="store_const", metavar='save_type', dest='save_type', const=SaveType.save, help="List saves.") group_list.add_argument("-c", "--chest", action="store_const", metavar='save_type', dest='save_type', const=SaveType.chest, help="List chest files.") parser_list.add_argument("id", nargs='?', help="ID of specific mod to list details of.") parser_list.set_defaults(func=self.do_list) # export command parser_export = subparsers.add_parser( 'export', help="Export a mod.", description='Export a mod in a format suitible for later import.') group_export = parser_export.add_mutually_exclusive_group() group_export.add_argument("-w", "--workshop", action="store_const", dest='save_type', metavar='save_type', const=SaveType.workshop, help="ID is of workshop file (the default).") group_export.add_argument("-s", "--save", action="store_const", dest='save_type', metavar='save_type', const=SaveType.save, help="ID is of savegame file.") group_export.add_argument("-c", "--chest", action="store_const", dest='save_type', metavar='save_type', const=SaveType.chest, help="ID is of chest file.") parser_export.add_argument( "id", help="ID of mod/name of savegame to export.") parser_export.add_argument("-o", "--output", help="Location/file to export to.") parser_export.add_argument("-f", "--force", action="store_true", help="Force creation of export file.") parser_export.add_argument( "-d", "--download", action="store_true", help="Attempt to download missing cache files. (EXPERIMENTAL)") parser_export.set_defaults(func=self.do_export) # import command parser_import = subparsers.add_parser( 'import', help="Import a mod.", description="Import an previously exported mod.") parser_import.add_argument("file", help="Mod pak file to import.") parser_import.set_defaults(func=self.do_import) # download command parser_download = subparsers.add_parser( 'download', help='Download mod files.', description= 'Attempt to download any missing files for an installed mod.') group_download = parser_download.add_mutually_exclusive_group() group_download.add_argument("-w", "--workshop", action="store_const", dest='save_type', metavar='save_type', const=SaveType.workshop, help="ID is of workshop file.") group_download.add_argument("-s", "--save", action="store_const", dest='save_type', metavar='save_type', const=SaveType.save, help="ID is of savegame file.") group_download.add_argument("-c", "--chest", action="store_const", dest='save_type', metavar='save_type', const=SaveType.chest, help="ID is of chest file.") group_download_target = parser_download.add_mutually_exclusive_group( required=True) group_download_target.add_argument("-a", "--all", action="store_true", help="Download all.") group_download_target.add_argument( "id", nargs='?', help="ID of mod/name of savegame to download.") parser_download.set_defaults(func=self.do_download) # cache command parser_cache = subparsers.add_parser('cache', help='Work with the cache.') subparsers_cache = parser_cache.add_subparsers( dest='parser_cache', title='cache_command', description='Valid sub-commands.') subparsers_cache.required = True parser_cache_create = subparsers_cache.add_parser( 'create', help='(re)create cache directory') parser_cache_create.set_defaults(func=self.do_cache_create) # config command parser_config = subparsers.add_parser('config', help='Configure tts manager.') subparsers_config = parser_config.add_subparsers( dest='parser_config', title='config_command', description='Valid sub-commands.') subparsers_config.required = True parser_config_list = subparsers_config.add_parser( 'list', help='List configuration.') parser_config_list.set_defaults(func=self.do_config_list) parser_config_validate = subparsers_config.add_parser( 'validate', help='Validate configuration.') parser_config_validate.set_defaults(func=self.do_config_validate) parser_config_reset = subparsers_config.add_parser( 'reset', help='Reset configuration.') parser_config_reset.set_defaults(func=self.do_config_reset) parser_config_set = subparsers_config.add_parser( 'set', help='Set configuration parameters.') parser_config_set.set_defaults(func=self.do_config_set) parser_config_set.add_argument("-m", "--mod_location", choices=['documents', 'gamedata'], help="Where mods are stored.") parser_config_set.add_argument("-t", "--tts_location", help="TTS Install directory") args = parser.parse_args() # set logging if args.loglevel: logmap = { 'debug': logging.DEBUG, 'info': logging.INFO, 'warn': logging.WARN, 'error': logging.ERROR } logger().setLevel(logmap[args.loglevel]) else: logger().setLevel(logging.WARN) # load filesystem values if args.directory: self.filesystem = FileSystem(os.path.abspath(args.directory)) else: self.filesystem = self.preferences.get_filesystem() if (args.parser == 'list' or args.parser == 'export') and not args.save_type: # set default args.save_type = SaveType.workshop if (args.parser == 'config' and args.parser_config == 'set' and not args.mod_location and not args.tts_location): parser_config_set.error("At least one of -m or -t is required.") rc, message = args.func(args) if message: print(message) sys.exit(rc)