Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- # Copyright 2016 Paolo Pelloni
- #
- # Permission is hereby granted, free of charge, to any person obtaining
- # a copy of this software and associated documentation files (the
- # "Software"), to deal in the Software without restriction, including
- # without limitation the rights to use, copy, modify, merge, publish,
- # distribute, sublicense, and/or sell copies of the Software, and to
- # permit persons to whom the Software is furnished to do so, subject
- # to the following conditions:
- #
- # The above copyright notice and this permission notice shall be included
- # in all copies or substantial portions of the Software.
- #
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- ########################################################################
- # CONSTANTS
- ########################################################################
- VERSION = "1.0"
- ########################################################################
- # App main class
- ########################################################################
- class FixRhyGtk:
- def __init__(self, argv):
- try:
- opts, args = getopt.getopt(argv, 'd', '' )
- except:
- print "fixrhygtk [-d]"
- sys.exit(1)
- # checking for debug
- self.debug = False
- for opt in opts:
- if opt == '-d':
- self.debug = True
- self.modified = False
- self.loaded = False
- self._lock = threading.Lock()
- self.init_settings()
- self.load_settings()
- self.backup_filename = self.DB_filename + ".backup"
- glade_filename = 'fixrhygtk.glade'
- if os.path.isfile(glade_filename) == False:
- glade_filename = '/usr/share/fixrhygtk/' + glade_filename
- if self.debug:
- print "No local glade file, looking for", glade_filename
- if os.path.isfile(glade_filename) == False:
- print "No glade file found, exiting!"
- sys.exit(1)
- self.load_from_glade(glade_filename)
- self.tbtn_filter.set_sensitive(False)
- self.tbtn_filter.set_active(self.only_missing)
- self.tbtn_find_next.set_sensitive(False)
- self.setup_treeview()
- self.main_window.show()
- self.check_rhythmbox(False)
- ####################################################################
- # Load resources from glade file
- ####################################################################
- def load_from_glade(self, glade_filename):
- self.builder = Gtk.Builder()
- self.builder.add_from_file(glade_filename)
- self.builder.connect_signals(self)
- self.builder.connect_signals({"onDeleteWindow": Gtk.main_quit})
- self.main_window = self.builder.get_object("MainWindow")
- self.main_box = self.builder.get_object("MainBox")
- self.main_scroll_window = self.builder.get_object("MainScrollWindow")
- self.main_treeview_selection = self.builder.get_object("TreeViewSelection")
- self.status_bar = self.builder.get_object("MyStatusBar")
- self.status_bar_context_id = self.status_bar.get_context_id("info")
- self.tbtn_filter = self.builder.get_object("tbtn_filter")
- self.tbtn_find_next = self.builder.get_object("tbtn_find_next")
- self.progress_window = self.builder.get_object("ProgressWindow")
- self.progress_bar = self.builder.get_object("ProgressBar")
- self.progress_label = self.builder.get_object("ProgressLabel")
- self.main_treeview = self.builder.get_object("MainTreeView")
- self.about_dialog = self.builder.get_object("AboutDialog")
- ####################################################################
- # Configuration
- ####################################################################
- ####################################################################
- # Initialise and eventually create settings
- ####################################################################
- def init_settings(self):
- self.settings_path = "org.gnome.fixrhygtk"
- self.settings = Gio.Settings(self.settings_path)
- ####################################################################
- # Loads settings
- ####################################################################
- def load_settings(self):
- self.DB_filename = self.settings.get_string("db-filename")
- self.only_missing = self.settings.get_boolean("show-only-missing")
- self.force = self.settings.get_boolean("force")
- ####################################################################
- # Save settings
- ####################################################################
- def save_settings(self):
- self.settings.set_string("db-filename", self.DB_filename)
- self.settings.set_boolean("show-only-missing", self.only_missing)
- self.settings.set_boolean("force", self.force)
- self.settings.sync()
- ####################################################################
- # Prepares the treeview
- ####################################################################
- def setup_treeview(self):
- self.add_column("Artist", 0, False)
- self.add_column("Album", 1, False)
- self.add_column("Year", 2, False)
- self.add_column("Sort Artist", 3, True)
- self.add_column("Sort Album", 4, True)
- self.add_column("Track", 5, False)
- self.add_column("Title", 6, False)
- self.liststore = Gtk.ListStore(str, str, str, str, str, str, str)
- self.main_treeview.set_model(self.liststore)
- ####################################################################
- # Updates the treeview
- ####################################################################
- def update_list_view(self):
- self.cell0 = Gtk.CellRendererText()
- ####################################################################
- # Add a column to the treeview
- ####################################################################
- def add_column(self, title, column_id, is_editable ):
- rendered_text = Gtk.CellRendererText()
- rendered_text.connect('edited', self.field_edited_handler, column_id)
- rendered_text.set_property('editable', is_editable)
- column = Gtk.TreeViewColumn(title, rendered_text, text=column_id)
- column.set_sort_column_id(column_id)
- column.set_resizable(True)
- self.main_treeview.append_column(column)
- ####################################################################
- # Event handlers
- ####################################################################
- ####################################################################
- # Main Window event handlers
- ####################################################################
- def on_main_window_destroy(self, *args):
- if self.modified:
- confirm_text = "Data has not been saved. If you proceed all the changes will be lost. Do you want to quit?"
- confirm_dialog = Gtk.MessageDialog(None, Gtk.DialogFlags.MODAL, Gtk.MessageType.WARNING, Gtk.ButtonsType.YES_NO, confirm_text)
- confirm_dialog.set_transient_for(self.main_window)
- response = confirm_dialog.run()
- confirm_dialog.destroy()
- if Gtk.ResponseType(response) is not Gtk.ResponseType.YES:
- return
- Gtk.main_quit(*args)
- ####################################################################
- # toolbars button event handlers
- ####################################################################
- def on_tbtn_load_clicked(self, widget):
- if self.modified:
- confirm_text = "Data has not been saved. If you proceed all the changes will be lost. Do you want to reload data?"
- confirm_dialog = Gtk.MessageDialog(None, Gtk.DialogFlags.MODAL, Gtk.MessageType.WARNING, Gtk.ButtonsType.YES_NO, confirm_text)
- response = confirm_dialog.run()
- confirm_dialog.destroy()
- if Gtk.ResponseType(response) is not Gtk.ResponseType.YES:
- return
- self.liststore.clear()
- self.thread = threading.Thread(target=self.load_DB)
- self.thread.start()
- self.update_list_view()
- def on_tbtn_save_clicked(self, widget):
- self.save_DB()
- def on_tbtn_find_clicked(self, widget):
- search_dialog = self.builder.get_object("SearchDialog")
- search_dialog_text = self.builder.get_object("search_entry")
- search_dialog_text.set_text("")
- search_dialog.set_focus(search_dialog_text)
- response = search_dialog.run()
- search_dialog.hide()
- if Gtk.ResponseType(response) is not Gtk.ResponseType.CANCEL:
- self.searching = search_dialog_text.get_text()
- self.tbtn_find_next.set_sensitive(True)
- self.last_searched = self.search_treeview(self.searching, None)
- def on_tbtn_find_next_clicked(self, widget):
- self.last_searched = self.search_treeview(self.searching, self.last_searched)
- def on_tbtn_filter_toggled(self, widget):
- if self.debug:
- print "toggled"
- if not self.loaded:
- return
- self.only_missing = not self.only_missing
- self.liststore.clear()
- thread = threading.Thread(target=self.show_data,args=(self.only_missing,))
- thread.start()
- def on_tbtn_info_clicked(self, widget):
- self.show_tracks_info()
- def on_tbtn_fill_clicked(self, widget):
- self.try_filling()
- def on_tbtn_fill_ask_clicked(self, widget):
- self.try_filling_ask()
- def on_tbtn_fill_text_clicked(self, widget):
- self.try_filling_text()
- def on_tbtn_preferences_clicked(self, widget):
- pref_window = self.builder.get_object("SettingsDialog")
- pref_fcb = self.builder.get_object("fcb_db")
- pref_checkbox = self.builder.get_object("chk_show_missing")
- pref_checkboxf = self.builder.get_object("chk_force")
- db_file = Gio.File.new_for_path(self.DB_filename)
- pref_fcb.set_file(db_file)
- pref_checkbox.set_active(self.only_missing)
- pref_window.set_modal(True)
- resp = pref_window.run()
- if Gtk.ResponseType(resp) is Gtk.ResponseType.OK:
- db_file = pref_fcb.get_file()
- self.DB_filename = db_file.get_path()
- self.only_missing = pref_checkbox.get_active()
- self.force = pref_checkboxf.get_active()
- self.save_settings()
- pref_window.hide()
- def on_tbtn_about_clicked(self, widget):
- self.about_dialog.set_version(VERSION)
- self.about_dialog.run()
- self.about_dialog.hide()
- def on_btn_previous_clicked(self, widget):
- if self.info_pos > 0:
- self.info_pos = self.info_pos - 1
- self.show_tracks_info_data()
- def on_btn_next_clicked(self, widget):
- if self.info_pos < (len(self.i_pathlist)-1):
- self.info_pos = self.info_pos + 1
- self.show_tracks_info_data()
- ####################################################################
- # Responds to treeview right clic
- ####################################################################
- def on_tvButtonPress(self, widget, event):
- if event.type == Gdk.EventType.BUTTON_PRESS and event.button == 3:
- x = int(event.x)
- y = int(event.y)
- pthinfo = self.main_treeview.get_path_at_pos(x, y)
- if pthinfo is not None:
- path, col, cellx, celly = pthinfo
- self.main_treeview.grab_focus()
- self.main_treeview.set_cursor(path, col, 0)
- (model, pathlist) = self.main_treeview_selection.get_selected_rows()
- tree_iter = model.get_iter(pathlist[0])
- if tree_iter is not None:
- selected_artist = model.get_value(tree_iter, 0)
- selected_album = model.get_value(tree_iter, 1)
- selected_year = model.get_value(tree_iter, 2)
- selected_sort_artist = model.get_value(tree_iter, 3)
- selected_sort_album = model.get_value(tree_iter, 4)
- selected_track = model.get_value(tree_iter, 5)
- selected_title = model.get_value(tree_iter, 6)
- self.popup_menu = Gtk.Menu()
- option1 = Gtk.MenuItem(selected_artist)
- option1.connect("activate", self.menu_clicked_handler, selected_artist, selected_year)
- self.popup_menu.append(option1)
- t = selected_artist
- if ' ' in selected_artist:
- if selected_artist.startswith('The'):
- t = selected_artist[4:] + ", The"
- else:
- first_space = selected_artist.find(' ')
- t = selected_artist[first_space+1:] + ", " + selected_artist[:first_space]
- option2 = Gtk.MenuItem(t)
- option2.connect('activate', self.menu_clicked_handler, t, selected_year)
- self.popup_menu.append(option2)
- self.popup_menu.show_all()
- self.popup_menu.popup(None, None, None, None, event.button, event.time)
- ####################################################################
- # Cellrenderer edited
- ####################################################################
- def field_edited_handler(self, widget, path, text, column):
- if self.debug:
- print "edited", widget, path, column, text
- self.liststore[path][column] = text
- self.update_list_view()
- return True
- ####################################################################
- # Popup menu handlers
- ####################################################################
- def menu_clicked_handler(self, widget, artist, album):
- if self.debug:
- print "clicked", artist, album
- (model, pathlist) = self.main_treeview_selection.get_selected_rows()
- for path in pathlist:
- tree_iter = model.get_iter(path)
- selected_artist = model.get_value(tree_iter, 0)
- selected_album = model.get_value(tree_iter, 1)
- selected_year = model.get_value(tree_iter, 2)
- selected_track = model.get_value(tree_iter, 5)
- selected_title = model.get_value(tree_iter, 6)
- model.set_value(tree_iter, 3, artist)
- model.set_value(tree_iter, 4, album)
- self.update_record(selected_artist, selected_album, selected_track, selected_title,
- artist, album ,self.force)
- ####################################################################
- # Other methods
- ####################################################################
- ####################################################################
- # Load DB from file into XML managing structure
- ####################################################################
- def load_DB(self):
- if self.debug:
- print "Checking file"
- if os.path.isfile(self.DB_filename) == False:
- print "No file", self.DB_filename, "found!"
- return
- if os.access(self.DB_filename, os.W_OK) == False:
- print "No access to file", self.DB_filename, "!"
- return
- self.status_bar.push(self.status_bar_context_id, 'Loading database...' + self.DB_filename)
- self.tree = ET.ElementTree(file=self.DB_filename)
- self.status_bar.push(self.status_bar_context_id, 'Database loaded')
- self.modified = False
- self.loaded = True
- with self._lock:
- self.show_data(self.only_missing)
- self.tbtn_filter.set_sensitive(True)
- ####################################################################
- # Saves the structure to the xml file
- ####################################################################
- def save_DB(self):
- if not self.loaded:
- return
- self.progress_bar.set_fraction(0)
- self.progress_label.set_text("Saving database")
- self.progress_window.show()
- while Gtk.events_pending():
- Gtk.main_iteration()
- # backup file
- self.status_bar.push(self.status_bar_context_id, 'Creating a backup...')
- shutil.copy2(self.DB_filename, self.backup_filename)
- self.progress_bar.set_fraction(0.5)
- self.progress_bar.pulse()
- while Gtk.events_pending():
- Gtk.main_iteration()
- # write modified one
- self.tree.write(self.DB_filename, xml_declaration=True)
- self.status_bar.push(self.status_bar_context_id, 'Database saved: ' + self.DB_filename)
- self.modified = False
- self.progress_window.hide()
- ####################################################################
- # Informations on track
- ####################################################################
- def show_tracks_info(self):
- (self.i_model, self.i_pathlist) = self.main_treeview_selection.get_selected_rows()
- if self.debug:
- print len(self.i_pathlist)
- if len(self.i_pathlist) == 0:
- return
- self.info_dialog = self.builder.get_object("InfoDialog")
- if len(self.i_pathlist) == 1:
- buttons = False
- else:
- buttons = True
- btn_prev = self.builder.get_object("btn_previous")
- btn_prev.set_sensitive(buttons)
- btn_next = self.builder.get_object("btn_next")
- btn_next.set_sensitive(buttons)
- self.info_pos = 0
- self.show_tracks_info_data()
- self.info_dialog.run()
- self.info_dialog.hide()
- ####################################################################
- # Show track information (only for self.info_pos)
- ####################################################################
- def show_tracks_info_data(self):
- tree_iter = self.i_model.get_iter(self.i_pathlist[self.info_pos])
- txt_title = self.builder.get_object("txt_title")
- title = self.i_model.get_value(tree_iter, 6)
- txt_title.set_text(title)
- txt_artist = self.builder.get_object("txt_artist")
- artist = self.i_model.get_value(tree_iter, 0)
- txt_artist.set_text(artist)
- txt_album = self.builder.get_object("txt_album")
- album = self.i_model.get_value(tree_iter, 1)
- txt_album.set_text(album)
- txt_track = self.builder.get_object("txt_track")
- track = self.i_model.get_value(tree_iter, 5)
- txt_track.set_text(track)
- txt_artist_sort = self.builder.get_object("txt_artist_sort")
- artist_sort = self.i_model.get_value(tree_iter, 3)
- if artist_sort is not None:
- txt_artist_sort.set_text(artist_sort)
- else:
- txt_artist_sort.set_text('')
- txt_album_sort = self.builder.get_object("txt_album_sort")
- album_sort = self.i_model.get_value(tree_iter, 4)
- if album_sort is not None:
- txt_album_sort.set_text(album_sort)
- else:
- txt_album_sort.set_text('')
- txt_date = self.builder.get_object("txt_date")
- txt_date.set_text(self.i_model.get_value(tree_iter, 2))
- song = self.track_info(artist, album, track, title)
- if song is None:
- return
- txt_disk = self.builder.get_object("txt_disk")
- txt_disk.set_text(song.findtext('disc-number', ' '))
- txt_composer = self.builder.get_object("txt_composer")
- txt_composer.set_text(song.findtext('composer', ' '))
- txt_genre = self.builder.get_object("txt_genre")
- txt_genre.set_text(song.findtext('genre', ' '))
- txt_duration = self.builder.get_object("txt_duration")
- txt_duration.set_text(self.duration_convert(song.findtext('duration', ' ')))
- txt_filesize = self.builder.get_object("txt_filesize")
- txt_filesize.set_text(song.findtext('file-size', ' '))
- txt_playcount = self.builder.get_object("txt_playcount")
- txt_playcount.set_text(song.findtext('play-count', ' '))
- txt_comment = self.builder.get_object("txt_comment")
- txt_comment.set_text(song.findtext('comment', ' '))
- ####################################################################
- # Shows loaded data in the treeview (all or only one missing sort informations)
- ####################################################################
- def show_data(self, show_only_missing):
- if self.debug:
- print "Showing > " + str(show_only_missing)
- if not self.loaded:
- return
- root = self.tree.getroot()
- count = 0
- songs = 0
- for entry in root:
- if entry.attrib == {'type': 'song'}:
- songs = songs + 1
- artist_sort_name = entry.findtext('mb-artistsortname', None)
- album_sort_name = entry.findtext('album-sortname', None)
- if show_only_missing == False or artist_sort_name == None or album_sort_name == None:
- artist_name = entry.find('artist').text
- album_name = entry.find('album').text
- date_pubblished = entry.find('date').text
- year_pubblished = str(self.posix_to_year(date_pubblished))
- if year_pubblished == None:
- year_pubblished = "SW"
- track_title = entry.findtext('title', ' ')
- track_number = entry.findtext('track-number', ' ')
- self.liststore.append([artist_name, album_name, year_pubblished, artist_sort_name,
- album_sort_name, track_number, track_title])
- count = count + 1
- if self.debug:
- print "end"
- msg = str(songs) + " songs loaded, " + str(count) + " listed"
- self.status_bar.push(self.status_bar_context_id, msg)
- #self.update_list_view()
- ####################################################################
- # Searches for the first entry in the treeview
- ####################################################################
- def search_treeview(self, src, current):
- if current is None:
- current = self.liststore.get_iter_first()
- else:
- current = self.liststore.iter_next(current)
- while current is not None:
- if src in self.liststore.get_value(current, 0):
- if self.debug:
- print self.liststore.get_value(current, 0)
- col = self.main_treeview.get_column(3)
- self.main_treeview.set_cursor_on_cell(self.liststore.get_path(current), col, self.cell0, True)
- return current
- current = self.liststore.iter_next(current)
- self.not_found(src)
- ####################################################################
- # Shows a not found dialog
- ####################################################################
- def not_found(self, txt):
- confirm_text = txt + " not found!"
- confirm_dialog = Gtk.MessageDialog(None, Gtk.DialogFlags.MODAL, Gtk.MessageType.WARNING, Gtk.ButtonsType.OK, confirm_text)
- confirm_dialog.set_transient_for(self.main_window)
- response = confirm_dialog.run()
- confirm_dialog.destroy()
- ####################################################################
- # Try filling the line with the most obvious proposort_album
- ####################################################################
- def try_filling(self):
- if self.debug:
- print "Get selected lines"
- (model, pathlist) = self.main_treeview_selection.get_selected_rows()
- for path in pathlist:
- tree_iter = model.get_iter(path)
- selected_artist = model.get_value(tree_iter, 0)
- selected_album = model.get_value(tree_iter, 1)
- selected_year = model.get_value(tree_iter, 2)
- selected_sort_artist = model.get_value(tree_iter, 3)
- selected_sort_album = model.get_value(tree_iter, 4)
- selected_track = model.get_value(tree_iter, 5)
- selected_title = model.get_value(tree_iter, 6)
- if self.debug:
- print selected_artist, " ", selected_album, " ", selected_year
- if ' ' in selected_artist:
- if selected_artist.startswith('The'):
- proposed_sort_artist = selected_artist[4:] + ", The"
- else:
- first_space = selected_artist.find(' ')
- proposed_sort_artist = selected_artist[first_space+1:] + ", " + selected_artist[:first_space]
- else:
- proposed_sort_artist = selected_artist
- proposed_sort_album = selected_year
- model.set_value(tree_iter, 3, proposed_sort_artist)
- model.set_value(tree_iter, 4, proposed_sort_album)
- self.update_record(selected_artist, selected_album, selected_track, selected_title,
- proposed_sort_artist, proposed_sort_album ,self.force)
- ####################################################################
- # try filling the line with the most obvious proposort_album but asking for best choice
- ####################################################################
- def try_filling_ask(self):
- if self.debug:
- print "Get selected lines"
- (model, pathlist) = self.main_treeview_selection.get_selected_rows()
- already_found = [] # here I will store the one found and asked
- already_chosen = [] # and here the user selection
- for path in pathlist:
- tree_iter = model.get_iter(path)
- selected_artist = model.get_value(tree_iter, 0)
- selected_album = model.get_value(tree_iter, 1)
- selected_year = model.get_value(tree_iter, 2)
- selected_sort_artist = model.get_value(tree_iter, 3)
- selected_sort_album = model.get_value(tree_iter, 4)
- selected_track = model.get_value(tree_iter, 5)
- selected_title = model.get_value(tree_iter, 6)
- if self.debug:
- print selected_artist, " ", selected_album, " ", selected_year
- if selected_artist not in already_found:
- options = []
- if self.debug:
- print "options cleared"
- options_index = 0
- selection_dialog = Gtk.Dialog(title = "Choose the sort artist")
- label = Gtk.Label("Choose sort artist ")
- selection_dialog.vbox.pack_start(label, True, True, 0)
- label.show()
- selection_dialog.get_action_area().set_orientation(Gtk.Orientation.VERTICAL)
- selection_dialog.set_modal(True)
- selection_dialog.set_transient_for(self.main_window)
- options.append(selected_artist)
- selection_dialog.add_button(selected_artist, options_index) # option 1 is artist as it is
- index = 0
- while index < len(selected_artist):
- index = selected_artist.find(' ', index)
- if index == -1:
- break
- t = selected_artist[index+1:] + ", " + selected_artist[:index]
- options_index = options_index + 1
- index = index + 1
- options.append(t)
- selection_dialog.add_button(t, options_index)
- index = index + 1
- selection_dialog.add_button("Stop and exit", -6)
- selected = selection_dialog.run()
- selection_dialog.destroy()
- if selected == -6:
- return
- while Gtk.events_pending():
- Gtk.main_iteration()
- if self.debug:
- print selected
- proposed_sort_artist = options[selected]
- if self.debug:
- print proposed_sort_artist
- already_found.append(selected_artist)
- already_chosen.append(proposed_sort_artist)
- else:
- proposed_sort_artist = already_chosen[already_found.index(selected_artist)]
- proposed_sort_album = selected_year
- model.set_value(tree_iter, 3, proposed_sort_artist)
- model.set_value(tree_iter, 4, proposed_sort_album)
- self.update_record(selected_artist, selected_album, selected_track, selected_title,
- proposed_sort_artist, proposed_sort_album ,self.force)
- ####################################################################
- # try filling the line with text given by user
- ####################################################################
- def try_filling_text(self):
- if self.debug:
- print "Get selected lines"
- (model, pathlist) = self.main_treeview_selection.get_selected_rows()
- sort_dialog = self.builder.get_object("SortDialog")
- cbe_artist = self.builder.get_object("box_artist_sort")
- cbe_artist.get_model().clear()
- cbe_album = self.builder.get_object("box_album_sort")
- tree_iter = model.get_iter(pathlist[0])
- selected_artist = model.get_value(tree_iter, 0)
- cbe_artist.get_child().set_text(selected_artist)
- index = 0
- while index < len(selected_artist):
- index = selected_artist.find(' ', index)
- if index == -1:
- break
- t = selected_artist[index+1:] + ", " + selected_artist[:index]
- index = index + 1
- cbe_artist.append_text(t)
- cbe_album.get_child().set_text(model.get_value(tree_iter,2))
- response = sort_dialog.run()
- sort_dialog.hide()
- if response == Gtk.ResponseType.CANCEL:
- return
- proposed_sort_artist = cbe_artist.get_child().get_text()
- proposed_sort_album = cbe_album.get_child().get_text()
- if self.debug:
- print "Got:", proposed_sort_artist, proposed_sort_album
- for path in pathlist:
- tree_iter = model.get_iter(path)
- selected_artist = model.get_value(tree_iter, 0)
- selected_album = model.get_value(tree_iter, 1)
- selected_year = model.get_value(tree_iter, 2)
- selected_sort_artist = model.get_value(tree_iter, 3)
- selected_sort_album = model.get_value(tree_iter, 4)
- selected_track = model.get_value(tree_iter, 5)
- selected_title = model.get_value(tree_iter, 6)
- if self.debug:
- print selected_artist, " ", selected_album, " ", selected_year
- model.set_value(tree_iter, 3, proposed_sort_artist)
- model.set_value(tree_iter, 4, proposed_sort_album)
- self.update_record(selected_artist, selected_album, selected_track, selected_title,
- proposed_sort_artist, proposed_sort_album ,self.force)
- ####################################################################
- # Returns the track information
- ####################################################################
- def track_info(self, artist, album, track, title):
- root = self.tree.getroot()
- if self.debug:
- print "Searching for:", artist, album, track, title
- for entry in root:
- if entry.attrib == {'type': 'song'}:
- if entry.find('artist').text == artist:
- if entry.find('album').text == album:
- if entry.find('title').text == title:
- if entry.find('track-number').text == track:
- return entry
- return None
- ####################################################################
- # update the record in the xml structure
- ####################################################################
- def update_record(self, artist, album, track, title, sort_artist, sort_album, is_forced):
- self.modified = True
- root = self.tree.getroot()
- if self.debug:
- print "Trying update, looking for", artist, album, track, title
- for entry in root:
- process = False
- if entry.attrib == {'type': 'song'}:
- if entry.find('artist').text == artist:
- if entry.find('album').text == album:
- if entry.find('title').text == title:
- process = True
- if process:
- artist_name = entry.find('mb-artistsortname')
- if artist_name == None:
- se = ET.SubElement(entry, 'mb-artistsortname')
- se.text = sort_artist
- if self.debug:
- print "Set sort artist", sort_artist
- else:
- if artist_name.text == sort_artist:
- if self.debug:
- print "Sort artist already OK"
- else:
- if is_forced:
- entry.remove(artist_name)
- se = ET.SubElement(entry, 'mb-artistsortname')
- se.text = sort_artist
- if self.debug:
- print "Sort artist different, force changed"
- else:
- if self.debug:
- print "Sort artist different, left unchanged"
- album_name = entry.find('album-sortname')
- if album_name == None:
- se = ET.SubElement(entry, 'album-sortname')
- se.text = sort_album
- if self.debug:
- print "Set sort album",sort_album
- else:
- if album_name.text == sort_album:
- if self.debug:
- print "Sort album already OK"
- else:
- if is_forced:
- entry.remove(album_name)
- se = ET.SubElement(entry, 'album-sortname')
- se.text = sort_album
- if self.debug:
- print "Sort album different, force changed"
- else:
- if self.debug:
- print "Sort album different, left unchanged"
- ####################################################################
- # convert rythmbox date format to 'human' year
- ####################################################################
- def posix_to_year(self, psx_str):
- psx = int(psx_str)
- year = 2039
- check = 744365
- leap_count = 1
- while check > 650000:
- if psx == check:
- return year
- if leap_count < 3:
- leap_count = leap_count + 1
- check = check - 365
- year = year - 1
- else:
- leap_count = 0
- check = check - 366
- year = year - 1
- return None
- ####################################################################
- # checks if rhythmbox is already running and in case gives a warning
- ####################################################################
- def check_rhythmbox(self, exit_if):
- output = commands.getoutput("ps -A")
- if "rhythmbox" in output:
- if exit_if:
- confirm_text = "Rhythmbos is currently running. Please close it and then launch fixrhygtk!"
- confirm_dialog = Gtk.MessageDialog(None, Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, confirm_text)
- confirm_dialog.set_transient_for(self.main_window)
- response = confirm_dialog.run()
- confirm_dialog.destroy()
- sys.exit(1)
- else:
- confirm_text = "Rhythmbos is currently running."
- confirm_text = confirm_text + " If you go on you may corrupt the database or loose all the changes. Do you want to continue?"
- confirm_dialog = Gtk.MessageDialog(None, Gtk.DialogFlags.MODAL, Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO, confirm_text)
- confirm_dialog.set_transient_for(self.main_window)
- response = confirm_dialog.run()
- confirm_dialog.destroy()
- if Gtk.ResponseType(response) is not Gtk.ResponseType.YES:
- sys.exit(1)
- ####################################################################
- # Converts duration if min/sec
- ####################################################################
- def duration_convert(self, _duration):
- duration = int(_duration)
- hours = int(duration/3600)
- duration = duration - hours*3600
- minutes = int(duration/60)
- seconds = duration - minutes*60
- if hours > 0:
- d = '%dh ' % hours
- else:
- d = ''
- if minutes > 0:
- d = d + '%dm ' % minutes
- else:
- d = d + ''
- d = d + '%ds' % seconds
- return d
- ########################################################################
- # App initialisation
- ########################################################################
- import sys
- import getopt
- import shutil
- import os
- import threading
- import commands
- import xml.etree.cElementTree as ET
- reload(sys)
- sys.setdefaultencoding( "UTF-8" )
- print "fixrhygtk ", VERSION
- try:
- import gi
- gi.require_version('Gtk', '3.0')
- except:
- print "Cannot import gi :("
- pass
- try:
- from gi.repository import Gtk, Gdk, Gio
- except:
- print "Cannot import gtk.glade :("
- sys.exit(1)
- if __name__ == "__main__":
- frg = FixRhyGtk(sys.argv[1:])
- Gtk.main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement