CoverArt Browser
v2.0
Browse your cover-art albums in Rhythmbox
|
00001 # -*- Mode: python; coding: utf-8; tab-width: 4; indent-tabs-mode: nil; -*- 00002 # 00003 # Copyright (C) 2012 - fossfreedom 00004 # Copyright (C) 2012 - Agustin Carrasco 00005 # 00006 # This program is free software; you can redistribute it and/or modify 00007 # it under the terms of the GNU General Public License as published by 00008 # the Free Software Foundation; either version 2, or (at your option) 00009 # any later version. 00010 # 00011 # This program is distributed in the hope that it will be useful, 00012 # but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 # GNU General Public License for more details. 00015 # 00016 # You should have received a copy of the GNU General Public License 00017 # along with this program; if not, write to the Free Software 00018 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 00019 import locale 00020 import gettext 00021 import os 00022 import shutil 00023 import webbrowser 00024 00025 from gi.repository import Gio 00026 from gi.repository import GObject 00027 from gi.repository import Gtk 00028 from gi.repository import PeasGtk 00029 from gi.repository import Peas 00030 from gi.repository import RB 00031 00032 import rb 00033 from stars import ReactiveStar 00034 from stars import StarSize 00035 import coverart_rb3compat as rb3compat 00036 00037 00038 def webkit_support(): 00039 ''' 00040 function that returns True/False if webkit technology is supported 00041 ''' 00042 gs = GSetting() 00043 settings = gs.get_setting(gs.Path.PLUGIN) 00044 return settings[gs.PluginKey.WEBKIT] 00045 00046 00047 class CoverLocale: 00048 ''' 00049 This class manages the locale 00050 ''' 00051 # storage for the instance reference 00052 __instance = None 00053 00054 class __impl: 00055 """ Implementation of the singleton interface """ 00056 # below public variables and methods that can be called for CoverLocale 00057 def __init__(self): 00058 ''' 00059 Initializes the singleton interface, assigning all the constants 00060 used to access the plugin's settings. 00061 ''' 00062 self.Locale = self._enum( 00063 RB='rhythmbox', 00064 LOCALE_DOMAIN='coverart_browser') 00065 00066 def switch_locale(self, locale_type): 00067 ''' 00068 Change the locale 00069 ''' 00070 locale.setlocale(locale.LC_ALL, '') 00071 locale.bindtextdomain(locale_type, RB.locale_dir()) 00072 locale.textdomain(locale_type) 00073 gettext.bindtextdomain(locale_type, RB.locale_dir()) 00074 gettext.textdomain(locale_type) 00075 gettext.install(locale_type) 00076 00077 def get_locale(self): 00078 ''' 00079 return the string representation of the users locale 00080 for example 00081 en_US 00082 ''' 00083 return locale.getdefaultlocale()[0] 00084 00085 def _enum(self, **enums): 00086 ''' 00087 Create an enumn. 00088 ''' 00089 return type('Enum', (), enums) 00090 00091 def __init__(self): 00092 """ Create singleton instance """ 00093 # Check whether we already have an instance 00094 if CoverLocale.__instance is None: 00095 # Create and remember instance 00096 CoverLocale.__instance = CoverLocale.__impl() 00097 00098 # Store instance reference as the only member in the handle 00099 self.__dict__['_CoverLocale__instance'] = CoverLocale.__instance 00100 00101 def __getattr__(self, attr): 00102 """ Delegate access to implementation """ 00103 return getattr(self.__instance, attr) 00104 00105 def __setattr__(self, attr, value): 00106 """ Delegate access to implementation """ 00107 return setattr(self.__instance, attr, value) 00108 00109 00110 class GSetting: 00111 ''' 00112 This class manages the different settings that the plugin has to 00113 access to read or write. 00114 ''' 00115 # storage for the instance reference 00116 __instance = None 00117 00118 class __impl: 00119 """ Implementation of the singleton interface """ 00120 # below public variables and methods that can be called for GSetting 00121 def __init__(self): 00122 ''' 00123 Initializes the singleton interface, assigning all the constants 00124 used to access the plugin's settings. 00125 ''' 00126 self.Path = self._enum( 00127 PLUGIN='org.gnome.rhythmbox.plugins.coverart_browser', 00128 RBSOURCE='org.gnome.rhythmbox.sources') 00129 00130 self.RBSourceKey = self._enum(VISIBLE_COLS='visible-columns') 00131 00132 self.PluginKey = self._enum( 00133 CUSTOM_STATUSBAR='custom-statusbar', 00134 DISPLAY_TEXT='display-text', 00135 DISPLAY_TEXT_POS='display-text-pos', 00136 RANDOM='random-queue', 00137 DISPLAY_TEXT_LOADING='display-text-loading', 00138 DISPLAY_TEXT_ELLIPSIZE='display-text-ellipsize', 00139 DISPLAY_TEXT_ELLIPSIZE_LENGTH='display-text-ellipsize-length', 00140 DISPLAY_FONT_SIZE='display-font-size', 00141 COVER_SIZE='cover-size', 00142 ADD_SHADOW='add-shadow', 00143 SHADOW_IMAGE='shadow-image', 00144 PANED_POSITION='paned-position', 00145 SORT_BY='sort-by', 00146 SORT_ORDER='sort-order', 00147 SORT_BY_ARTIST='sort-by-artist', 00148 SORT_ORDER_ARTIST='sort-order-artist', 00149 RATING='rating-threshold', 00150 AUTOSTART='autostart', 00151 TOOLBAR_POS='toolbar-pos', 00152 BUTTON_RELIEF='button-relief', 00153 THEME='theme', 00154 NEW_GENRE_ICON='new-genre-icon', 00155 ICON_PADDING='icon-padding', 00156 ICON_SPACING='icon-spacing', 00157 ICON_AUTOMATIC='icon-automatic', 00158 VIEW_NAME='view-name', 00159 FLOW_APPEARANCE='flow-appearance', 00160 FLOW_HIDE_CAPTION='flow-hide-caption', 00161 FLOW_SCALE='flow-scale', 00162 FLOW_BACKGROUND_COLOUR='flow-background-colour', 00163 FLOW_AUTOMATIC='flow-automatic', 00164 FLOW_WIDTH='flow-width', 00165 FLOW_MAX='flow-max-albums', 00166 WEBKIT='webkit-support', 00167 ARTIST_PANED_POSITION='artist-paned-pos', 00168 USE_FAVOURITES='use-favourites', 00169 ARTIST_INFO_PANED_POSITION='artist-info-paned-pos', 00170 LAST_GENRE_FOLDER='last-genre-folder', 00171 ENTRY_VIEW_MODE='entry-view-mode', 00172 FOLLOWING='following') 00173 00174 self.setting = {} 00175 00176 def get_setting(self, path): 00177 ''' 00178 Return an instance of Gio.Settings pointing at the selected path. 00179 ''' 00180 try: 00181 setting = self.setting[path] 00182 except: 00183 self.setting[path] = Gio.Settings.new(path) 00184 setting = self.setting[path] 00185 00186 return setting 00187 00188 def get_value(self, path, key): 00189 ''' 00190 Return the value saved on key from the settings path. 00191 ''' 00192 return self.get_setting(path)[key] 00193 00194 def set_value(self, path, key, value): 00195 ''' 00196 Set the passed value to key in the settings path. 00197 ''' 00198 self.get_setting(path)[key] = value 00199 00200 def _enum(self, **enums): 00201 ''' 00202 Create an enumn. 00203 ''' 00204 return type('Enum', (), enums) 00205 00206 def __init__(self): 00207 """ Create singleton instance """ 00208 # Check whether we already have an instance 00209 if GSetting.__instance is None: 00210 # Create and remember instance 00211 GSetting.__instance = GSetting.__impl() 00212 00213 # Store instance reference as the only member in the handle 00214 self.__dict__['_GSetting__instance'] = GSetting.__instance 00215 00216 def __getattr__(self, attr): 00217 """ Delegate access to implementation """ 00218 return getattr(self.__instance, attr) 00219 00220 def __setattr__(self, attr, value): 00221 """ Delegate access to implementation """ 00222 return setattr(self.__instance, attr, value) 00223 00224 00225 class Preferences(GObject.Object, PeasGtk.Configurable): 00226 ''' 00227 Preferences for the CoverArt Browser Plugins. It holds the settings for 00228 the plugin and also is the responsible of creating the preferences dialog. 00229 ''' 00230 __gtype_name__ = 'CoverArtBrowserPreferences' 00231 object = GObject.property(type=GObject.Object) 00232 GENRE_POPUP = 1 00233 GENRE_LIST = 2 00234 00235 def __init__(self): 00236 ''' 00237 Initialises the preferences, getting an instance of the settings saved 00238 by Gio. 00239 ''' 00240 GObject.Object.__init__(self) 00241 gs = GSetting() 00242 self.settings = gs.get_setting(gs.Path.PLUGIN) 00243 00244 self._first_run = True 00245 00246 def do_create_configure_widget(self): 00247 ''' 00248 Creates the plugin's preferences dialog 00249 ''' 00250 return self._create_display_contents(self) 00251 00252 def display_preferences_dialog(self, plugin): 00253 print ("DEBUG - display_preferences_dialog") 00254 if self._first_run: 00255 self._first_run = False 00256 00257 cl = CoverLocale() 00258 cl.switch_locale(cl.Locale.LOCALE_DOMAIN) 00259 00260 self._dialog = Gtk.Dialog(modal=True, destroy_with_parent=True) 00261 self._dialog.add_button(Gtk.STOCK_OK, Gtk.ResponseType.OK) 00262 self._dialog.set_title(_('Browser Preferences')) 00263 content_area = self._dialog.get_content_area() 00264 content_area.pack_start(self._create_display_contents(plugin), True, True, 0) 00265 00266 helpbutton = self._dialog.add_button(Gtk.STOCK_HELP, Gtk.ResponseType.HELP) 00267 helpbutton.connect('clicked', self._display_help) 00268 00269 self._dialog.show_all() 00270 00271 print ("shown") 00272 00273 while True: 00274 response = self._dialog.run() 00275 00276 print ("and run") 00277 00278 if response != Gtk.ResponseType.HELP: 00279 break 00280 00281 self._dialog.hide() 00282 00283 print ("DEBUG - display_preferences_dialog end") 00284 00285 def _display_help(self, *args): 00286 peas = Peas.Engine.get_default() 00287 uri = peas.get_plugin_info('coverart_browser').get_help_uri() 00288 00289 webbrowser.open(uri) 00290 00291 def _create_display_contents(self, plugin): 00292 print ("DEBUG - create_display_contents") 00293 # create the ui 00294 self._first_run = True 00295 cl = CoverLocale() 00296 cl.switch_locale(cl.Locale.LOCALE_DOMAIN) 00297 builder = Gtk.Builder() 00298 builder.set_translation_domain(cl.Locale.LOCALE_DOMAIN) 00299 builder.add_from_file(rb.find_plugin_file(plugin, 00300 'ui/coverart_browser_prefs.ui')) 00301 self.launchpad_button = builder.get_object('show_launchpad') 00302 self.launchpad_label = builder.get_object('launchpad_label') 00303 00304 builder.connect_signals(self) 00305 00306 #. TRANSLATORS: Do not translate this string. 00307 translators = _('translator-credits') 00308 00309 if translators != "translator-credits": 00310 self.launchpad_label.set_text(translators) 00311 else: 00312 self.launchpad_button.set_visible(False) 00313 00314 gs = GSetting() 00315 # bind the toggles to the settings 00316 toggle_statusbar = builder.get_object('custom_statusbar_checkbox') 00317 self.settings.bind(gs.PluginKey.CUSTOM_STATUSBAR, 00318 toggle_statusbar, 'active', Gio.SettingsBindFlags.DEFAULT) 00319 00320 toggle_text = builder.get_object('display_text_checkbox') 00321 self.settings.bind(gs.PluginKey.DISPLAY_TEXT, toggle_text, 'active', 00322 Gio.SettingsBindFlags.DEFAULT) 00323 00324 00325 box_text = builder.get_object('display_text_box') 00326 self.settings.bind(gs.PluginKey.DISPLAY_TEXT, box_text, 'sensitive', 00327 Gio.SettingsBindFlags.GET) 00328 00329 self.display_text_pos = self.settings[gs.PluginKey.DISPLAY_TEXT_POS] 00330 self.display_text_under_radiobutton = builder.get_object('display_text_under_radiobutton') 00331 self.display_text_within_radiobutton = builder.get_object('display_text_within_radiobutton') 00332 00333 if self.display_text_pos: 00334 self.display_text_under_radiobutton.set_active(True) 00335 else: 00336 self.display_text_within_radiobutton.set_active(True) 00337 00338 random_scale = builder.get_object('random_adjustment') 00339 self.settings.bind(gs.PluginKey.RANDOM, random_scale, 'value', 00340 Gio.SettingsBindFlags.DEFAULT) 00341 00342 toggle_text_ellipsize = builder.get_object( 00343 'display_text_ellipsize_checkbox') 00344 self.settings.bind(gs.PluginKey.DISPLAY_TEXT_ELLIPSIZE, 00345 toggle_text_ellipsize, 'active', Gio.SettingsBindFlags.DEFAULT) 00346 00347 box_text_ellipsize_length = builder.get_object( 00348 'display_text_ellipsize_length_box') 00349 self.settings.bind(gs.PluginKey.DISPLAY_TEXT_ELLIPSIZE, 00350 box_text_ellipsize_length, 'sensitive', Gio.SettingsBindFlags.GET) 00351 00352 spinner_text_ellipsize_length = builder.get_object( 00353 'display_text_ellipsize_length_spin') 00354 self.settings.bind(gs.PluginKey.DISPLAY_TEXT_ELLIPSIZE_LENGTH, 00355 spinner_text_ellipsize_length, 'value', 00356 Gio.SettingsBindFlags.DEFAULT) 00357 00358 spinner_font_size = builder.get_object( 00359 'display_font_spin') 00360 self.settings.bind(gs.PluginKey.DISPLAY_FONT_SIZE, 00361 spinner_font_size, 'value', 00362 Gio.SettingsBindFlags.DEFAULT) 00363 00364 cover_size_scale = builder.get_object('cover_size_adjustment') 00365 self.settings.bind(gs.PluginKey.COVER_SIZE, cover_size_scale, 'value', 00366 Gio.SettingsBindFlags.DEFAULT) 00367 00368 add_shadow = builder.get_object('add_shadow_checkbox') 00369 self.settings.bind(gs.PluginKey.ADD_SHADOW, add_shadow, 'active', 00370 Gio.SettingsBindFlags.DEFAULT) 00371 00372 rated_box = builder.get_object('rated_box') 00373 self.stars = ReactiveStar(size=StarSize.BIG) 00374 00375 self.stars.connect('changed', self.rating_changed_callback) 00376 00377 align = Gtk.Alignment.new(0.5, 0, 0, 0.1) 00378 align.add(self.stars) 00379 rated_box.add(align) 00380 00381 self.stars.set_rating(self.settings[gs.PluginKey.RATING]) 00382 00383 autostart = builder.get_object('autostart_checkbox') 00384 self.settings.bind(gs.PluginKey.AUTOSTART, 00385 autostart, 'active', Gio.SettingsBindFlags.DEFAULT) 00386 00387 toolbar_pos_combo = builder.get_object('show_in_combobox') 00388 renderer = Gtk.CellRendererText() 00389 toolbar_pos_combo.pack_start(renderer, True) 00390 toolbar_pos_combo.add_attribute(renderer, 'text', 1) 00391 self.settings.bind(gs.PluginKey.TOOLBAR_POS, toolbar_pos_combo, 00392 'active-id', Gio.SettingsBindFlags.DEFAULT) 00393 00394 light_source_combo = builder.get_object('light_source_combobox') 00395 renderer = Gtk.CellRendererText() 00396 light_source_combo.pack_start(renderer, True) 00397 light_source_combo.add_attribute(renderer, 'text', 1) 00398 self.settings.bind(gs.PluginKey.SHADOW_IMAGE, light_source_combo, 00399 'active-id', Gio.SettingsBindFlags.DEFAULT) 00400 00401 combo_liststore = builder.get_object('combo_liststore') 00402 00403 from coverart_utils import Theme 00404 00405 for theme in Theme(self).themes: 00406 combo_liststore.append([theme, theme]) 00407 00408 theme_combo = builder.get_object('theme_combobox') 00409 renderer = Gtk.CellRendererText() 00410 theme_combo.pack_start(renderer, True) 00411 theme_combo.add_attribute(renderer, 'text', 1) 00412 self.settings.bind(gs.PluginKey.THEME, theme_combo, 00413 'active-id', Gio.SettingsBindFlags.DEFAULT) 00414 00415 button_relief = builder.get_object('button_relief_checkbox') 00416 self.settings.bind(gs.PluginKey.BUTTON_RELIEF, button_relief, 'active', 00417 Gio.SettingsBindFlags.DEFAULT) 00418 00419 # create user data files 00420 cachedir = RB.user_cache_dir() + "/coverart_browser/usericons" 00421 if not os.path.exists(cachedir): 00422 os.makedirs(cachedir) 00423 00424 popup = cachedir + "/popups.xml" 00425 00426 temp = RB.find_user_data_file('plugins/coverart_browser/img/usericons/popups.xml') 00427 00428 # lets see if there is a legacy file - if necessary copy it to the cache dir 00429 if os.path.isfile(temp) and not os.path.isfile(popup): 00430 shutil.copyfile(temp, popup) 00431 00432 if not os.path.isfile(popup): 00433 template = rb.find_plugin_file(plugin, 'template/popups.xml') 00434 folder = os.path.split(popup)[0] 00435 if not os.path.exists(folder): 00436 os.makedirs(folder) 00437 shutil.copyfile(template, popup) 00438 00439 # now prepare the genre tab 00440 from coverart_utils import GenreConfiguredSpriteSheet 00441 from coverart_utils import get_stock_size 00442 00443 self._sheet = GenreConfiguredSpriteSheet(plugin, "genre", get_stock_size()) 00444 00445 self.alt_liststore = builder.get_object('alt_liststore') 00446 self.alt_user_liststore = builder.get_object('alt_user_liststore') 00447 self._iters = {} 00448 for key in list(self._sheet.keys()): 00449 store_iter = self.alt_liststore.append([key, self._sheet[key]]) 00450 self._iters[(key, self.GENRE_POPUP)] = store_iter 00451 00452 for key, value in self._sheet.genre_alternate.items(): 00453 if key.genre_type == GenreConfiguredSpriteSheet.GENRE_USER: 00454 store_iter = self.alt_user_liststore.append([key.name, 00455 self._sheet[self._sheet.genre_alternate[key]], 00456 self._sheet.genre_alternate[key]]) 00457 self._iters[(key.name, self.GENRE_LIST)] = store_iter 00458 00459 self.amend_mode = False 00460 self.blank_iter = None 00461 self.genre_combobox = builder.get_object('genre_combobox') 00462 self.genre_entry = builder.get_object('genre_entry') 00463 self.genre_view = builder.get_object('genre_view') 00464 self.save_button = builder.get_object('save_button') 00465 self.filechooserdialog = builder.get_object('filechooserdialog') 00466 last_genre_folder = self.settings[gs.PluginKey.LAST_GENRE_FOLDER] 00467 if last_genre_folder != "": 00468 self.filechooserdialog.set_current_folder(last_genre_folder) 00469 00470 padding_scale = builder.get_object('padding_adjustment') 00471 self.settings.bind(gs.PluginKey.ICON_PADDING, padding_scale, 'value', 00472 Gio.SettingsBindFlags.DEFAULT) 00473 00474 spacing_scale = builder.get_object('spacing_adjustment') 00475 self.settings.bind(gs.PluginKey.ICON_SPACING, spacing_scale, 'value', 00476 Gio.SettingsBindFlags.DEFAULT) 00477 00478 icon_automatic = builder.get_object('icon_automatic_checkbox') 00479 self.settings.bind(gs.PluginKey.ICON_AUTOMATIC, 00480 icon_automatic, 'active', Gio.SettingsBindFlags.DEFAULT) 00481 00482 #flow tab 00483 flow_combo = builder.get_object('flow_combobox') 00484 renderer = Gtk.CellRendererText() 00485 flow_combo.pack_start(renderer, True) 00486 flow_combo.add_attribute(renderer, 'text', 1) 00487 self.settings.bind(gs.PluginKey.FLOW_APPEARANCE, flow_combo, 00488 'active-id', Gio.SettingsBindFlags.DEFAULT) 00489 00490 flow_hide = builder.get_object('hide_caption_checkbox') 00491 self.settings.bind(gs.PluginKey.FLOW_HIDE_CAPTION, 00492 flow_hide, 'active', Gio.SettingsBindFlags.DEFAULT) 00493 00494 flow_scale = builder.get_object('cover_scale_adjustment') 00495 self.settings.bind(gs.PluginKey.FLOW_SCALE, flow_scale, 'value', 00496 Gio.SettingsBindFlags.DEFAULT) 00497 00498 flow_width = builder.get_object('cover_width_adjustment') 00499 self.settings.bind(gs.PluginKey.FLOW_WIDTH, flow_width, 'value', 00500 Gio.SettingsBindFlags.DEFAULT) 00501 00502 flow_max = builder.get_object('flow_max_adjustment') 00503 self.settings.bind(gs.PluginKey.FLOW_MAX, flow_max, 'value', 00504 Gio.SettingsBindFlags.DEFAULT) 00505 00506 flow_automatic = builder.get_object('automatic_checkbox') 00507 self.settings.bind(gs.PluginKey.FLOW_AUTOMATIC, 00508 flow_automatic, 'active', Gio.SettingsBindFlags.DEFAULT) 00509 00510 self.background_colour = self.settings[gs.PluginKey.FLOW_BACKGROUND_COLOUR] 00511 self.white_radiobutton = builder.get_object('white_radiobutton') 00512 self.black_radiobutton = builder.get_object('black_radiobutton') 00513 00514 if self.background_colour == 'W': 00515 self.white_radiobutton.set_active(True) 00516 else: 00517 self.black_radiobutton.set_active(True) 00518 00519 # return the dialog 00520 self._first_run = False 00521 print ("end create dialog contents") 00522 return builder.get_object('main_notebook') 00523 00524 def on_flow_combobox_changed(self, combobox): 00525 current_val = combobox.get_model()[combobox.get_active()][0] 00526 gs = GSetting() 00527 if self.settings[gs.PluginKey.FLOW_APPEARANCE] != current_val: 00528 if current_val == 'flow-vert': 00529 default_size = 150 00530 else: 00531 default_size = 600 00532 00533 self.settings[gs.PluginKey.FLOW_WIDTH] = default_size 00534 00535 if current_val == 'carousel': 00536 self.settings[gs.PluginKey.FLOW_HIDE_CAPTION] = True 00537 00538 def on_background_radio_toggled(self, button): 00539 if button.get_active(): 00540 gs = GSetting() 00541 if button == self.white_radiobutton: 00542 self.settings[gs.PluginKey.FLOW_BACKGROUND_COLOUR] = 'W' 00543 else: 00544 self.settings[gs.PluginKey.FLOW_BACKGROUND_COLOUR] = 'B' 00545 00546 def on_display_text_pos_radio_toggled(self, button): 00547 if self._first_run: 00548 return 00549 00550 if button.get_active(): 00551 gs = GSetting() 00552 if button == self.display_text_under_radiobutton: 00553 self.settings[gs.PluginKey.DISPLAY_TEXT_POS] = True 00554 else: 00555 self.settings[gs.PluginKey.DISPLAY_TEXT_POS] = False 00556 self.settings[gs.PluginKey.ADD_SHADOW] = False 00557 00558 def on_add_shadow_checkbox_toggled(self, button): 00559 if button.get_active(): 00560 #gs = GSetting() 00561 #self.settings[gs.PluginKey.DISPLAY_TEXT_POS] = True 00562 self.display_text_under_radiobutton.set_active(True) 00563 00564 def rating_changed_callback(self, stars): 00565 print("rating_changed_callback") 00566 gs = GSetting() 00567 self.settings[gs.PluginKey.RATING] = self.stars.get_rating() 00568 00569 def on_save_button_clicked(self, button): 00570 ''' 00571 action when genre edit area is saved 00572 ''' 00573 entry_value = self.genre_entry.get_text() 00574 treeiter = self.genre_combobox.get_active_iter() 00575 icon_value = self.alt_liststore[treeiter][0] 00576 # model 0 is the icon name, model 1 is the pixbuf 00577 00578 if self.amend_mode: 00579 key = self._sheet.amend_genre_info(self.current_genre, 00580 entry_value, icon_value) 00581 00582 self.alt_user_liststore[self._iters[(self.current_genre, 00583 self.GENRE_LIST)]][1] = self._sheet[self._sheet.genre_alternate[key]] 00584 self.alt_user_liststore[self._iters[(self.current_genre, 00585 self.GENRE_LIST)]][0] = key.name 00586 store_iter = self._iters[(self.current_genre, self.GENRE_LIST)] 00587 del self._iters[(self.current_genre, self.GENRE_LIST)] 00588 self._iters[(key.name, self.GENRE_LIST)] = store_iter 00589 00590 else: 00591 self.amend_mode = True 00592 key = self._sheet.amend_genre_info('', 00593 entry_value, icon_value) 00594 self.current_genre = key.name 00595 00596 store_iter = self.alt_user_liststore.append([key.name, 00597 self._sheet[self._sheet.genre_alternate[key]], 00598 self._sheet.genre_alternate[key]]) 00599 self._iters[(key.name, self.GENRE_LIST)] = store_iter 00600 selection = self.genre_view.get_selection() 00601 selection.select_iter(store_iter) 00602 00603 self.save_button.set_sensitive(False) 00604 self._toggle_new_genre_state() 00605 00606 00607 def on_genre_filechooserbutton_file_set(self, filechooser): 00608 ''' 00609 action when genre new icon button is pressed 00610 ''' 00611 key = self._sheet.add_genre_icon(self.filechooserdialog.get_filename()) 00612 store_iter = self.alt_liststore.append([key.name, self._sheet[key.name]]) 00613 self._iters[(key.name, self.GENRE_POPUP)] = store_iter 00614 00615 gs = GSetting() 00616 last_genre_folder = self.filechooserdialog.get_current_folder() 00617 00618 print(last_genre_folder) 00619 print(self.filechooserdialog.get_filename()) 00620 if last_genre_folder: 00621 self.settings[gs.PluginKey.LAST_GENRE_FOLDER] = last_genre_folder 00622 00623 def on_genre_view_selection_changed(self, view): 00624 ''' 00625 action when user selects a row in the list of genres 00626 ''' 00627 model, genre_iter = view.get_selected() 00628 if genre_iter: 00629 self.genre_entry.set_text(model[genre_iter][0]) 00630 index = model[genre_iter][2] 00631 if index != '': 00632 self.genre_combobox.set_active_iter(self._iters[(index, self.GENRE_POPUP)]) 00633 self.amend_mode = True 00634 self.current_genre = rb3compat.unicodestr(model[genre_iter][0], 'utf-8') 00635 else: 00636 self.genre_entry.set_text('') 00637 self.genre_combobox.set_active_iter(None) 00638 self.amend_mode = False 00639 00640 if self.blank_iter and self.amend_mode: 00641 try: 00642 index = model[self.blank_iter][0] 00643 if index == '': 00644 model.remove(self.blank_iter) 00645 self.blank_iter = None 00646 except: 00647 self.blank_iter = None 00648 00649 def on_add_button_clicked(self, button): 00650 ''' 00651 action when a new genre is added to the table 00652 ''' 00653 self.genre_entry.set_text('') 00654 self.genre_combobox.set_active(-1) 00655 self.amend_mode = False 00656 self.blank_iter = self.alt_user_liststore.append(['', None, '']) 00657 selection = self.genre_view.get_selection() 00658 selection.select_iter(self.blank_iter) 00659 00660 00661 def on_delete_button_clicked(self, button): 00662 ''' 00663 action when a genre is to be deleted 00664 ''' 00665 selection = self.genre_view.get_selection() 00666 00667 model, genre_iter = selection.get_selected() 00668 if genre_iter: 00669 index = rb3compat.unicodestr(model[genre_iter][0], 'utf-8') 00670 model.remove(genre_iter) 00671 00672 if index: 00673 del self._iters[(index, self.GENRE_LIST)] 00674 self._sheet.delete_genre(index) 00675 00676 self._toggle_new_genre_state() 00677 00678 def set_save_sensitivity(self, _): 00679 ''' 00680 action to toggle the state of the save button depending 00681 upon the values entered in the genre edit fields 00682 ''' 00683 entry_value = self.genre_entry.get_text() 00684 treeiter = self.genre_combobox.get_active_iter() 00685 00686 entry_value = rb3compat.unicodestr(entry_value, 'utf-8') 00687 enable = False 00688 try: 00689 test = self._iters[(entry_value, self.GENRE_LIST)] 00690 if RB.search_fold(self.current_genre) == RB.search_fold(entry_value): 00691 #if the current entry is the same then could save 00692 enable = True 00693 except: 00694 # reach here if this is a brand new entry 00695 enable = True 00696 00697 if treeiter == None or entry_value == None or entry_value == "": 00698 # no icon chosen, or no entry value then nothing to save 00699 enable = False 00700 00701 self.save_button.set_sensitive(enable) 00702 00703 def _toggle_new_genre_state(self): 00704 ''' 00705 fire an event - uses gsettings and an object such as a 00706 controller connects to receive the signal that a new or amended 00707 genre has been made 00708 ''' 00709 gs = GSetting() 00710 test = self.settings[gs.PluginKey.NEW_GENRE_ICON] 00711 00712 if test: 00713 test = False 00714 else: 00715 test = True 00716 00717 self.settings[gs.PluginKey.NEW_GENRE_ICON] = test 00718 00719 def on_show_launchpad_toggled(self, button): 00720 self.launchpad_label.set_visible(button.get_active()) 00721 00722