def on_dnd_received(self, treeview, drag_context, x, y, selection, _info, timestamp): drop_info = treeview.get_dest_row_at_pos(x, y) if selection.get_data(): if not os.path.isdir( self.config.musicdir[self.config.profile_num]): return # DND from outside sonata: uri = selection.get_data().strip().decode('utf-8') path = urllib.request.url2pathname(uri) paths = path.rsplit('\n') mpdpaths = [] # Strip off paranthesis so that we can DND entire music dir # if we wish. musicdir = self.config.musicdir[self.config.profile_num][:-1] for i, path in enumerate(paths): paths[i] = path.rstrip('\r') if paths[i].startswith('file://'): paths[i] = paths[i][7:] elif paths[i].startswith('file:'): paths[i] = paths[i][5:] if paths[i].startswith(musicdir): paths[i] = paths[i][len(musicdir):] if len(paths[i]) == 0: paths[i] = "/" listallinfo = self.mpd.listallinfo(paths[i]) for item in listallinfo: if 'file' in item: mpdpaths.append(item['file']) # Add local file, available in mpd 0.14. This currently # work because python-mpd does not support unix socket # paths, won't which is needed for authentication for # local files. It's also therefore untested. if os.path.isdir(paths[i]): filenames = misc.get_files_recursively(paths[i]) else: filenames = [paths[i]] for filename in filenames: if os.path.exists(filename): mpdpaths.append("file://" + urllib.parse.quote(filename)) if len(mpdpaths) > 0: # Items found, add to list at drop position: if drop_info: destpath, position = drop_info if position in (Gtk.TreeViewDropPosition.BEFORE, Gtk.TreeViewDropPosition.INTO_OR_BEFORE): songid = destpath[0] else: songid = destpath[0] + 1 else: songid = len(self.store) for mpdpath in mpdpaths: self.mpd.addid(mpdpath, songid) self.iterate_now() return # Otherwise, it's a DND just within the current playlist model = self.store _foobar, selected = self.selection.get_selected_rows() # calculate all this now before we start moving stuff drag_sources = [] for path in selected: index = path[0] treeiter = model.get_iter(path) songid = self.get_songid(treeiter, model) drag_sources.append([index, treeiter, songid]) # Keep track of the moved iters so we can select them afterwards moved_iters = [] # Will manipulate model to prevent the entire playlist from refreshing offset = 0 self.mpd.command_list_ok_begin() for index, treeiter, songid in drag_sources: if drop_info: destpath, position = drop_info dest = destpath[0] + offset if dest < index: offset = offset + 1 pop_from = index move_to = dest if position in (Gtk.TreeViewDropPosition.BEFORE, Gtk.TreeViewDropPosition.INTO_OR_BEFORE): insert_to = dest if dest < index + 1: pop_from = index + 1 else: move_to = dest - 1 else: insert_to = dest + 1 if dest < index: pop_from = index + 1 move_to = insert_to else: dest = len(self.store) - 1 insert_to = dest + 1 self.mpd.moveid(songid, move_to) moved_iters.append(model.insert(insert_to, tuple(model[index]))) model.remove(treeiter) # now fixup for source in drag_sources: if dest < index: # we moved it back, so all indexes inbetween increased by 1 if dest < source[0] < index: source[0] += 1 else: # we moved it ahead, so all indexes inbetween # decreased by 1 if index < source[0] < dest: source[0] -= 1 self.mpd.command_list_end() # we are manipulating the model manually for speed, so... self.update_skip = True # Gdk.DragContext.get_action() returns a bitmask of actions if drag_context.get_actions() & Gdk.DragAction.MOVE: Gdk.drag_finish(drag_context, True, True, timestamp) self.header_hide_all_indicators(self.view, False) self.iterate_now() selection = treeview.get_selection() selection.unselect_all() for i in moved_iters: selection.select_iter(i) if moved_iters: treeview.scroll_to_cell(model.get_path(moved_iters[0]), None)
def on_dnd(self, treeview, drag_context, x, y, selection, _info, timestamp): drop_info = treeview.get_dest_row_at_pos(x, y) if selection.data is not None: if not os.path.isdir(self.config.musicdir[self.config.profile_num]): return # DND from outside sonata: uri = selection.data.strip() path = urllib.request.url2pathname(uri) paths = path.rsplit('\n') mpdpaths = [] # Strip off paranthesis so that we can DND entire music dir # if we wish. musicdir = self.config.musicdir[self.config.profile_num][:-1] for i, path in enumerate(paths): paths[i] = path.rstrip('\r') if paths[i].startswith('file://'): paths[i] = paths[i][7:] elif paths[i].startswith('file:'): paths[i] = paths[i][5:] if paths[i].startswith(musicdir): paths[i] = paths[i][len(musicdir):] if len(paths[i]) == 0: paths[i] = "/" listallinfo = self.mpd.listallinfo(paths[i]) for item in listallinfo: if 'file' in item: mpdpaths.append(item['file']) # Add local file, available in mpd 0.14. This currently # work because python-mpd does not support unix socket # paths, won't which is needed for authentication for # local files. It's also therefore untested. if os.path.isdir(paths[i]): filenames = misc.get_files_recursively(paths[i]) else: filenames = [paths[i]] for filename in filenames: if os.path.exists(filename): mpdpaths.append("file://" + urllib.parse.quote(filename)) if len(mpdpaths) > 0: # Items found, add to list at drop position: if drop_info: destpath, position = drop_info if position in (Gtk.TreeViewDropPosition.BEFORE, Gtk.TreeViewDropPosition.INTO_OR_BEFORE): songid = destpath[0] else: songid = destpath[0] + 1 else: songid = len(self.currentdata) for mpdpath in mpdpaths: self.mpd.addid(mpdpath, songid) self.iterate_now() return # Otherwise, it's a DND just within the current playlist model = treeview.get_model() _foobar, selected = self.current_selection.get_selected_rows() # calculate all this now before we start moving stuff drag_sources = [] for path in selected: index = path[0] i = model.get_iter(path) songid = self.current_get_songid(i, model) text = model.get_value(i, 1) drag_sources.append([index, i, songid, text]) # Keep track of the moved iters so we can select them afterwards moved_iters = [] # We will manipulate self.current_songs and model to prevent # the entire playlist from refreshing offset = 0 self.mpd.command_list_ok_begin() for source in drag_sources: index, i, songid, text = source if drop_info: destpath, position = drop_info dest = destpath[0] + offset if dest < index: offset = offset + 1 if position in (Gtk.TreeViewDropPosition.BEFORE, Gtk.TreeViewDropPosition.INTO_OR_BEFORE): self.current_songs.insert(dest, self.current_songs[index]) if dest < index + 1: self.current_songs.pop(index + 1) self.mpd.moveid(songid, dest) else: self.current_songs.pop(index) self.mpd.moveid(songid, dest - 1) model.insert(dest, model[index]) moved_iters += [model.get_iter((dest,))] model.remove(i) else: self.current_songs.insert(dest + 1, self.current_songs[index]) if dest < index: self.current_songs.pop(index + 1) self.mpd.moveid(songid, dest + 1) else: self.current_songs.pop(index) self.mpd.moveid(songid, dest) model.insert(dest + 1, model[index]) moved_iters += [model.get_iter((dest + 1,))] model.remove(i) else: #dest = int(self.status['playlistlength']) - 1 dest = len(self.currentdata) - 1 self.mpd.moveid(songid, dest) self.current_songs.insert(dest + 1, self.current_songs[index]) self.current_songs.pop(index) model.insert(dest + 1, model[index]) moved_iters += [model.get_iter((dest + 1,))] model.remove(i) # now fixup for source in drag_sources: if dest < index: # we moved it back, so all indexes inbetween increased by 1 if dest < source[0] < index: source[0] += 1 else: # we moved it ahead, so all indexes inbetween # decreased by 1 if index < source[0] < dest: source[0] -= 1 self.mpd.command_list_end() # we are manipulating the model manually for speed, so... self.current_update_skip = True if drag_context.action == Gdk.DragAction.MOVE: drag_context.finish(True, True, timestamp) self.header_hide_all_indicators(self.current, False) self.iterate_now() GLib.idle_add(self.dnd_retain_selection, treeview.get_selection(), moved_iters)
def on_dnd_received(self, treeview, drag_context, x, y, selection, _info, timestamp): drop_info = treeview.get_dest_row_at_pos(x, y) if selection.get_data(): if not os.path.isdir(self.config.current_musicdir): return # DND from outside sonata: uri = selection.get_data().strip().decode('utf-8') path = urllib.request.url2pathname(uri) paths = path.rsplit('\n') mpdpaths = [] # Strip off paranthesis so that we can DND entire music dir # if we wish. musicdir = self.config.current_musicdir[:-1] for i, path in enumerate(paths): paths[i] = path.rstrip('\r') if paths[i].startswith('file://'): paths[i] = paths[i][7:] elif paths[i].startswith('file:'): paths[i] = paths[i][5:] if paths[i].startswith(musicdir): paths[i] = paths[i][len(musicdir):] if len(paths[i]) == 0: paths[i] = "/" listallinfo = self.mpd.listallinfo(paths[i]) for item in listallinfo: if 'file' in item: mpdpaths.append(item['file']) # Add local file, available in mpd 0.14. This currently # work because python-mpd does not support unix socket # paths, won't which is needed for authentication for # local files. It's also therefore untested. if os.path.isdir(paths[i]): filenames = misc.get_files_recursively(paths[i]) else: filenames = [paths[i]] for filename in filenames: if os.path.exists(filename): mpdpaths.append("file://" + urllib.parse.quote(filename)) if len(mpdpaths) > 0: # Items found, add to list at drop position: if drop_info: destpath, position = drop_info if position in (Gtk.TreeViewDropPosition.BEFORE, Gtk.TreeViewDropPosition.INTO_OR_BEFORE): songid = destpath[0] else: songid = destpath[0] + 1 else: songid = len(self.store) for mpdpath in mpdpaths: self.mpd.addid(mpdpath, songid) self.iterate_now() return # Otherwise, it's a DND just within the current playlist model = self.store _foobar, selected = self.selection.get_selected_rows() # calculate all this now before we start moving stuff drag_sources = [] for path in selected: index = path[0] treeiter = model.get_iter(path) songid = self.get_songid(treeiter, model) drag_sources.append([index, treeiter, songid]) # Keep track of the moved iters so we can select them afterwards moved_iters = [] # Will manipulate model to prevent the entire playlist from refreshing offset = 0 self.mpd.command_list_ok_begin() for index, treeiter, songid in drag_sources: if drop_info: destpath, position = drop_info dest = destpath[0] + offset if dest < index: offset = offset + 1 pop_from = index move_to = dest if position in (Gtk.TreeViewDropPosition.BEFORE, Gtk.TreeViewDropPosition.INTO_OR_BEFORE): insert_to = dest if dest < index + 1: pop_from = index + 1 else: move_to = dest - 1 else: insert_to = dest + 1 if dest < index: pop_from = index + 1 move_to = insert_to else: dest = len(self.store) - 1 insert_to = dest + 1 self.mpd.moveid(songid, move_to) moved_iters.append(model.insert(insert_to, tuple(model[index]))) model.remove(treeiter) # now fixup for source in drag_sources: if dest < index: # we moved it back, so all indexes inbetween increased by 1 if dest < source[0] < index: source[0] += 1 else: # we moved it ahead, so all indexes inbetween # decreased by 1 if index < source[0] < dest: source[0] -= 1 self.mpd.command_list_end() # we are manipulating the model manually for speed, so... self.update_skip = True # Gdk.DragContext.get_action() returns a bitmask of actions if drag_context.get_actions() & Gdk.DragAction.MOVE: Gdk.drag_finish(drag_context, True, True, timestamp) self.header_hide_all_indicators(self.view, False) self.iterate_now() selection = treeview.get_selection() selection.unselect_all() for i in moved_iters: selection.select_iter(i) if moved_iters: treeview.scroll_to_cell(model.get_path(moved_iters[0]), None)