Exemple #1
0
class PlaylistTreeControl(CommonTreeControl):
    def __init__(self, controls):
        CommonTreeControl.__init__(self, controls)

        self.header_pressed = False

        self.menu = Popup()
        self.tree_menu = Popup()
        self.full_name = ""
        self.label = Gtk.Label()

        self.set_headers_visible(True)
        self.set_headers_clickable(True)
        self.set_reorderable(True)

        """Column icon"""
        self.icon_col = Gtk.TreeViewColumn(None, Gtk.CellRendererPixbuf(), icon_name=self.play_icon[0])
        self.icon_col.key = "*"
        self.icon_col.label = Gtk.Label("*")
        self._append_column(self.icon_col)

        """track number"""
        self.trkn_col = Gtk.TreeViewColumn(None, Gtk.CellRendererText(), text=self.tracknumber[0])
        self.trkn_col.key = "N"
        #self.trkn_col.set_clickable(True)
        self.trkn_col.label = Gtk.Label("№")
        self.trkn_col.item = Gtk.CheckMenuItem(_("Number"))
        self._append_column(self.trkn_col)

        """column composer"""
        self.comp_col = Gtk.TreeViewColumn(None, self.ellipsize_render, text=self.composer[0])
        self.comp_col.key = "Composer"
        self.comp_col.label = Gtk.Label(_("Composer"))
        self.comp_col.item = Gtk.CheckMenuItem(_("Composer"))
        self._append_column(self.comp_col)

        """column artist title"""
        self.description_col = Gtk.TreeViewColumn(None, self.ellipsize_render, text=self.text[0], font=self.font[0])
        self.description_col.key = "Track"
        self.description_col.label = Gtk.Label(_("Track"))
        self.description_col.item = Gtk.CheckMenuItem(_("Track"))
        self._append_column(self.description_col)

        """column artist"""
        self.artist_col = Gtk.TreeViewColumn(None, self.ellipsize_render, text=self.artist[0])
        self.artist_col.key = "Artist"
        self.artist_col.label = Gtk.Label(_("Artist"))
        self.artist_col.item = Gtk.CheckMenuItem(_("Artist"))
        self._append_column(self.artist_col)

        """column title"""
        self.title_col = Gtk.TreeViewColumn(None, self.ellipsize_render, text=self.title[0])
        self.title_col.key = "Title"
        self.title_col.label = Gtk.Label(_("Title"))
        self.title_col.item = Gtk.CheckMenuItem(_("Title"))
        self._append_column(self.title_col)

        """column year"""
        self.year_col = Gtk.TreeViewColumn(None, Gtk.CellRendererText(), text=self.year[0])
        self.year_col.key = "Year"
        self.year_col.set_sizing(Gtk.TREE_VIEW_COLUMN_AUTOSIZE)
        self.year_col.set_resizable(True)
        self.year_col.label = Gtk.Label(_("Year"))
        self.year_col.item = Gtk.CheckMenuItem(_("Year"))
        self._append_column(self.year_col)

        """column album"""
        self.album_col = Gtk.TreeViewColumn(None, self.ellipsize_render, text=self.album[0])
        self.album_col.key = "Album"

        if self.album_col.key not in FC().columns:
            FC().columns[self.album_col.key] = [False, 7, 90]
        self.album_col.label = Gtk.Label(_("Album"))
        self.album_col.item = Gtk.CheckMenuItem(_("Album"))
        self._append_column(self.album_col)

        """column time"""
        self.time_col = Gtk.TreeViewColumn(None, Gtk.CellRendererText(), text=self.time[0])
        self.time_col.key = "Time"
        self.time_col.label = Gtk.Label(_("Time"))
        self.time_col.item = Gtk.CheckMenuItem(_("Time"))
        self._append_column(self.time_col)

        self.configure_send_drag()
        self.configure_recive_drag()

        self.set_playlist_plain()

        self.connect("button-release-event", self.on_button_press)

        self.on_load()

        self.connect("columns-changed", self.on_columns_changed)

    def set_playlist_tree(self):
        self.rebuild_as_tree()

    def set_playlist_plain(self):
        self.rebuild_as_plain()

    def on_key_release(self, w, e):
        if is_modificator(e):
            return
        elif is_key(e, KEY_RETURN):
            self.controls.play_selected_song()
        elif is_key(e, KEY_DELETE):
            self.delete_selected()
        elif is_key(e, 'Left'):
            self.controls.seek_down()
        elif is_key(e, 'Right'):
            self.controls.seek_up()

    def get_bean_under_pointer_icon(self):
        for row in self.model:
            if row[self.play_icon[0]]:
                bean = self.get_bean_from_row(row)
                return bean

    def common_single_random(self):
        logging.debug("Repeat state " + str(FC().repeat_state))
        if FC().repeat_state == const.REPEAT_SINGLE:
            return self.get_current_bean_by_UUID()

        if FC().is_order_random:
            bean = self.get_random_bean()
            self.set_play_icon_to_bean(bean)
            return bean

    def next(self):
        bean = self.common_single_random()
        if bean:
            self.scroll_follow_play_icon()
            return bean

        bean = self.get_next_bean(FC().repeat_state == const.REPEAT_ALL)

        if not bean:
            self.controls.state_stop()
            return

        self.set_play_icon_to_bean(bean)
        self.scroll_follow_play_icon()

        logging.debug("Next bean " + str(bean) + bean.text)

        return bean

    def prev(self):
        if FC().repeat_state == const.REPEAT_SINGLE:
            return self.get_current_bean_by_UUID()

        bean = self.get_prev_bean(FC().repeat_state == const.REPEAT_ALL)

        if not bean:
            self.controls.state_stop()
            return

        self.set_play_icon_to_bean(bean)
        self.scroll_follow_play_icon()

        return bean


    @idle_task
    def scroll_follow_play_icon(self):
        paths = [(i,) for i, row in enumerate(self.model)]
        for row, path in zip(self.model, paths):
            if row[self.play_icon[0]]:
                start_path, end_path = self.get_visible_range()
                path = row.path
                if path >= end_path or path <= start_path:
                    self.scroll_to_cell(path)

    def append(self, paths):
        for i, path in enumerate(paths):
            if os.path.isdir(path):
                listdir = filter(lambda x: get_file_extension(x) in FC().all_support_formats or os.path.isdir(x),
                                 [os.path.join(path, f) for f in os.listdir(path)])
                for k, p in enumerate(listdir):
                    paths.insert(i + k + 1, p)
        rows = self.file_paths_to_rows(paths)
        if not rows:
            return
        #rows = self.playlist_filter(rows)
        for row in rows:
            self.model.append(None, row)
        thread.start_new_thread(self.safe_fill_treerows, ())

    def is_empty(self):
        return True if not self.model.get_iter_first() else False

    def on_button_press(self, w, e):
        if self.header_pressed:
            self.header_pressed = False
            return
        if is_empty_click(w, e):
            w.get_selection().unselect_all()
        if is_double_left_click(e):
            self.controls.play_selected_song()

        if is_rigth_click(e):
            right_click_optimization_for_trees(w, e)
            beans = self.get_selected_beans()
            if beans:
                self.tree_menu.clear()
                self.tree_menu.add_item(_('Play'), "media-playback-start", self.controls.play_selected_song, None)
                self.tree_menu.add_item(_('Delete from playlist'), "edit-delete", self.delete_selected, None)

                paths = []
                inet_paths = []
                local_paths = []
                for bean in beans:
                    if bean.path in paths:
                        continue
                    paths.append(bean.path)
                    if not bean.path or bean.path.startswith("http://"):
                        inet_paths.append(bean.path)
                    else:
                        local_paths.append(bean.path)

                if local_paths:
                    self.tree_menu.add_item(_('Copy To...'), "list-add", copy_to, local_paths)
                    self.tree_menu.add_item(_("Open in file manager"), None, open_in_filemanager, local_paths[0])
                if inet_paths:
                    self.tree_menu.add_item(_('Download'), "list-add",
                                            self.controls.dm.append_tasks, self.get_all_selected_beans())
                    self.tree_menu.add_item(_('Download To...'), "list-add",
                                            self.controls.dm.append_tasks_with_dialog, self.get_all_selected_beans())

                self.tree_menu.add_separator()

                if local_paths:
                    self.tree_menu.add_item(_('Edit Tags'), "accessories-text-editor", edit_tags, (self.controls, local_paths))
                    self.tree_menu.add_item(_('Format Converter'), "applications-utilities", convert_files, local_paths)
                text = self.get_selected_bean().text
                self.tree_menu.add_item(_('Copy To Search Line'), "edit-copy",
                                        self.controls.searchPanel.set_search_text, text)
                self.tree_menu.add_separator()
                self.tree_menu.add_item(_('Copy №-Title-Time'), "edit-copy", self.copy_info_to_clipboard)
                self.tree_menu.add_item(_('Copy Artist-Title-Album'), "edit-copy",
                                        self.copy_info_to_clipboard, True)
                self.tree_menu.add_separator()
                self.tree_menu.add_item(_('Love This Track(s) by Last.fm'), None,
                                        self.controls.love_this_tracks, self.get_all_selected_beans())
                self.tree_menu.add_item(_('Add to My Audio (VK)'), None,
                                        self.controls.add_to_my_playlist, self.get_all_selected_beans())
                self.tree_menu.add_item(_('Copy link'), None,
                                        self.controls.copy_link, self.get_all_selected_beans())

                self.tree_menu.show(e)

    def on_click_header(self, w, e):
        self.header_pressed = True
        if is_rigth_click(e):
            if "menu" in w.__dict__:
                w.menu.show(e)
            else:
                self.menu.show(e)

    def on_toggled_num(self, *a):
        FC().numbering_by_order = not FC().numbering_by_order
        number_music_tabs = self.controls.notetabs.get_n_pages() - 1
        for page in xrange(number_music_tabs, -1, -1):
            tab_content = self.controls.notetabs.get_nth_page(page)
            pl_tree = tab_content.get_child()
            if FC().numbering_by_order:
                pl_tree.update_tracknumber()
                pl_tree.num_order.set_active(True)
                continue
            pl_tree.num_tags.set_active(True)
            for row in pl_tree.model:
                if row[pl_tree.is_file[0]]:
                    audio = get_mutagen_audio(row[pl_tree.path[0]])
                    if audio and audio.has_key('tracknumber'):
                        row[pl_tree.tracknumber[0]] = re.search('\d*', audio['tracknumber'][0]).group()
                    if audio and audio.has_key('trkn'):
                        row[pl_tree.tracknumber[0]] = re.search('\d*', audio["trkn"][0]).group()

    def on_toggle(self, w, e, column):
        FC().columns[column.key][0] = not FC().columns[column.key][0]

        number_music_tabs = self.controls.notetabs.get_n_pages() - 1
        for key in self.__dict__.keys():
            if self.__dict__[key] is column:
                atr_name = key
                break

        for page in xrange(number_music_tabs, -1, -1):
            tab_content = self.controls.notetabs.get_nth_page(page)
            pl_tree = tab_content.get_child()
            ## TODO: check "local variable 'atr_name' might be referenced before assignment"
            pl_tree_column = pl_tree.__dict__[atr_name]
            if FC().columns[column.key][0]:
                pl_tree.move_column_after(pl_tree_column, pl_tree.icon_col)
                pl_tree_column.set_visible(True)
                if self is not pl_tree:
                    pl_tree_column.item.set_active(True)
            else:
                pl_tree_column.set_visible(False)
                if self is not pl_tree:
                    pl_tree_column.item.set_active(False)

    def _append_column(self, column):
        column.set_widget(column.label)
        column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
        column.set_min_width(20)
        column.set_resizable(True)
        if column.key is '*':
            column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
            column.set_fixed_width(32)
            column.set_min_width(32)
        if FC().columns[column.key][2] > 0:
            column.set_fixed_width(FC().columns[column.key][2])

        self.append_column(column)
        column.button = column.label.get_parent().get_parent().get_parent()
        column.button.connect("button-press-event", self.on_click_header)
        '''
        if column.key == 'N':
            self.trkn_col.button.menu = Popup()
            group = []
            self.num_order = Gtk.RadioMenuItem.new_with_label(group, _("Numbering by order"))
            self.num_order.connect("button-press-event", self.on_toggled_num)
            group.append(self.num_order)
            self.num_tags = Gtk.RadioMenuItem.new_with_label(group, _("Numbering by tags"))
            self.num_tags.connect("button-press-event", self.on_toggled_num)
            group.append(self.num_tags)
            self.trkn_col.button.menu.append(self.num_order)
            self.trkn_col.button.menu.append(self.num_tags)
            if FC().numbering_by_order:
                self.num_order.set_active(True)
            else:
                self.num_tags.set_active(True)
        '''

    def on_columns_changed(self, *a):
        global FLAG
        if FLAG:
            return
        FLAG = True

        number_music_tabs = self.controls.notetabs.get_n_pages() - 1
        for i, column in enumerate(self.get_columns()):
            FC().columns[column.key][1] = i
            if column.get_width() > 1:  # to avoid recording of zero width in config
                FC().columns[column.key][2] = column.get_width()

        for page in xrange(number_music_tabs, 0, -1):
            tab_content = self.controls.notetabs.get_nth_page(page)
            pl_tree = tab_content.get_child()
            col_list = pl_tree.get_columns()
            col_list.sort(self.to_order_columns, reverse=True)
            for column in col_list:
                pl_tree.move_column_after(column, None)
        FLAG = False

    def to_order_columns(self, x, y):
        return cmp(FC().columns[x.key][1], FC().columns[y.key][1])

    def on_load(self):
        col_list = self.get_columns()
        col_list.sort(self.to_order_columns, reverse=True)
        visible_columns = []
        for column in col_list:
            column.label.show()
            column.set_widget(column.label)
            column.set_clickable(True)
            if column.key != "*":
                column.set_reorderable(True)
            if FC().columns[column.key][0]:
                self.move_column_after(column, None)
                if "item" in column.__dict__:
                    column.item.connect("button-press-event", self.on_toggle, column)
                    self.menu.append(column.item)
                    column.item.set_active(True)
                visible_columns.append(column)
            else:
                if "item" in column.__dict__:
                    column.item.connect("button-press-event", self.on_toggle, column)
                    self.menu.append(column.item)
                    column.item.set_active(False)
                column.set_visible(False)
        '''if FC().columns["Track"][2] < 0:
             self.description_col.set_fixed_width(self.get_allocation().width - (FC().columns["Time"][2]+70))'''

    def change_rows_by_path(self, file_paths):
        for treerow in self.model:
            if treerow[self.is_file[0]] and treerow[self.path[0]] in file_paths:
                bean = self.get_bean_from_row(treerow)
                bean = update_id3(bean)
                row_ref = Gtk.TreeRowReference.new(self.model, treerow.path)
                self.fill_row(row_ref, bean)
        GLib.idle_add(self.controls.notetabs.save_current_tab, priority=GLib.PRIORITY_LOW)

    def file_paths_to_rows(self, paths):
        result = []
        for path in paths:
            bean = get_bean_from_file(path)
            beans = update_id3_for_m3u([bean])
            beans = update_id3_for_pls(beans)
            if beans and (len(beans) > 1 or is_playlist(bean.path)):
                    bean = bean.add_text(_('Playlist: ') + bean.text).add_font("bold").add_is_file(False)
                    bean.path = ''
                    beans.insert(0, bean)
            for bean in beans:
                result.append(self.get_row_from_bean(bean))
        return result

    def on_drag_data_received(self, treeview, context, x, y, selection, info, timestamp):
        logging.debug('Playlist on_drag_data_received')
        model = self.get_model().get_model()
        drop_info = self.get_dest_row_at_pos(x, y)

        if drop_info:
            path, position = drop_info
            iter = model.get_iter(path)

        files = sorted([file for file in get_files_from_gtk_selection_data(selection)
                if os.path.isdir(file) or get_file_extension(file) in FC().all_support_formats],
                key=lambda x: x[self.text[0]])
        if files:
            '''dnd from the outside of the player'''
            if self.is_empty():
                if len(files) == 1 and os.path.isdir(files[0]):
                    tabname = os.path.basename(files[0])
                else:
                    tabname = os.path.split(os.path.dirname(files[0]))[1]
                self.controls.notetabs.rename_tab(self.scroll, tabname)
            for i, file in enumerate(files):
                if os.path.isdir(file):
                    sorted_dirs = []
                    sorted_files = []
                    for f in sorted(os.listdir(file), key=lambda x: x):
                        f = os.path.join(file, f)
                        if os.path.isdir(f):
                            sorted_dirs.append(f)
                        elif get_file_extension(f) in FC().all_support_formats:
                            sorted_files.append(f)

                    listdir = sorted_dirs + sorted_files
                    '''
                    listdir = sorted(filter(lambda x: get_file_extension(x) in FC().all_support_formats or os.path.isdir(x),
                                     [os.path.join(file, f) for f in os.listdir(file)]), key=lambda x: x)
                    '''
                    for k, path in enumerate(listdir):
                        files.insert(i + k + 1, path)

            rows = self.file_paths_to_rows(files)
            if not rows:
                return
            rows = self.playlist_filter(rows)
            for row in rows:
                if drop_info:
                    if (position == Gtk.TREE_VIEW_DROP_BEFORE
                        or position == Gtk.TREE_VIEW_DROP_INTO_OR_BEFORE):
                        model.insert_before(None, iter, row)
                    else:
                        model.insert_after(None, iter, row)
                        iter = model.iter_next(iter)
                else:
                    model.append(None, row)

        else:
            '''dnd inside the player'''
            # ff - from_filter
            ff_tree = Gtk.drag_get_source_widget(context)
            ff_model, ff_paths = ff_tree.get_selection().get_selected_rows()
            treerows = [ff_model[ff_path] for ff_path in ff_paths]

            if self is ff_tree:
                '''internal dnd'''
                ff_row_refs = [Gtk.TreeRowReference.new(ff_model, ff_path) for ff_path in ff_paths]
                for ff_row_ref in ff_row_refs:
                    ff_iter = self.get_iter_from_row_reference(ff_row_ref)
                    f_iter = ff_model.convert_iter_to_child_iter(ff_iter)
                    if drop_info:
                        if (position == Gtk.TREE_VIEW_DROP_BEFORE
                            or position == Gtk.TREE_VIEW_DROP_INTO_OR_BEFORE):
                            model.move_before(f_iter, iter)
                        else:
                            model.move_after(f_iter, iter)
                            iter = model.iter_next(iter)
                    else:
                        model.move_before(f_iter, None)
                return

            else:
                '''dnd from other tree'''
                if self.is_empty():
                    path = treerows[0][self.path[0]]
                    if path:
                        if len(treerows) == 1 and os.path.isdir(path):
                            tabname = os.path.basename(path)
                        else:
                            tabname = os.path.split(os.path.dirname(path))[1]
                        self.controls.notetabs.rename_tab(self.scroll, tabname)
                    else:
                        pass
                for i, treerow in enumerate(treerows):

                    for k, ch_row in enumerate(treerow.iterchildren()):
                        treerows.insert(i + k + 1, ch_row)

                #treerows = self.playlist_filter(treerows)

                for i, treerow in enumerate(treerows):
                    if is_playlist(treerow[self.path[0]]):
                        rows = self.file_paths_to_rows([treerow[self.path[0]]])
                        if rows:
                            rows.reverse()
                            map(lambda row: treerows.insert(i + 1, row), rows)
                            continue
                    row = [col for col in treerow]
                    if drop_info:
                        if (position == Gtk.TREE_VIEW_DROP_BEFORE
                            or position == Gtk.TREE_VIEW_DROP_INTO_OR_BEFORE):
                            model.insert_before(None, iter, row)
                        else:
                            model.insert_after(None, iter, row)
                            iter = model.iter_next(iter)
                    else:
                        model.append(None, row)


        thread.start_new_thread(self.safe_fill_treerows, ())

        context.finish(True, False, timestamp)
        self.stop_emission('drag-data-received')
        return True
Exemple #2
0
class PlaylistTreeControl(CommonTreeControl):
    def __init__(self, controls):
        CommonTreeControl.__init__(self, controls)

        self.header_pressed = False

        self.menu = Popup()
        self.tree_menu = Popup()
        self.full_name = ""
        self.label = Gtk.Label()

        self.set_headers_visible(True)
        self.set_headers_clickable(True)
        self.set_reorderable(True)

        """Column icon"""
        self.icon_col = Gtk.TreeViewColumn(None, Gtk.CellRendererPixbuf(), icon_name=self.play_icon[0])
        self.icon_col.key = "*"
        self.icon_col.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
        self.icon_col.set_fixed_width(32)
        self.icon_col.set_min_width(32)
        self.icon_col.label = Gtk.Label("*")
        self._append_column(self.icon_col)

        """track number"""
        self.trkn_col = Gtk.TreeViewColumn(None, Gtk.CellRendererText(), text=self.tracknumber[0])
        self.trkn_col.key = "N"
        self.trkn_col.set_clickable(True)
        self.trkn_col.label = Gtk.Label("№")
        self.trkn_col.label.show()
        self.trkn_col.item = Gtk.CheckMenuItem(_("Number"))
        self.trkn_col.set_widget(self.trkn_col.label)
        self._append_column(self.trkn_col)

        """column composer"""
        self.comp_col = Gtk.TreeViewColumn(None, Gtk.CellRendererText(), text=self.composer[0])
        self.comp_col.key = "Composer"
        self.comp_col.set_resizable(True)
        self.comp_col.label = Gtk.Label(_("Composer"))
        self.comp_col.item = Gtk.CheckMenuItem(_("Composer"))
        self._append_column(self.comp_col)

        """column artist title"""
        self.description_col = Gtk.TreeViewColumn(None, Gtk.CellRendererText(), text=self.text[0], font=self.font[0])
        self.description_col.key = "Track"
        self.description_col.set_resizable(True)
        self.description_col.label = Gtk.Label(_("Track"))
        self.description_col.item = Gtk.CheckMenuItem(_("Track"))
        self._append_column(self.description_col)

        """column artist"""
        self.artist_col = Gtk.TreeViewColumn(None, Gtk.CellRendererText(), text=self.artist[0])
        self.artist_col.key = "Artist"
        self.artist_col.set_sizing(Gtk.TREE_VIEW_COLUMN_AUTOSIZE)
        self.artist_col.set_resizable(True)
        self.artist_col.label = Gtk.Label(_("Artist"))
        self.artist_col.item = Gtk.CheckMenuItem(_("Artist"))
        self._append_column(self.artist_col)

        """column title"""
        self.title_col = Gtk.TreeViewColumn(None, Gtk.CellRendererText(), text=self.title[0])
        self.title_col.key = "Title"
        self.title_col.set_sizing(Gtk.TREE_VIEW_COLUMN_AUTOSIZE)
        self.title_col.set_resizable(True)
        self.title_col.label = Gtk.Label(_("Title"))
        self.title_col.item = Gtk.CheckMenuItem(_("Title"))
        self._append_column(self.title_col)

        """column album"""
        self.album_col = Gtk.TreeViewColumn(None, Gtk.CellRendererText(), text=self.album[0])
        self.album_col.key = "Album"

        if self.album_col.key not in FC().columns:
            FC().columns[self.album_col.key] = [False, 7, 90]
        self.album_col.set_sizing(Gtk.TREE_VIEW_COLUMN_AUTOSIZE)
        self.album_col.set_resizable(True)
        self.album_col.label = Gtk.Label(_("Album"))
        self.album_col.item = Gtk.CheckMenuItem(_("Album"))
        self._append_column(self.album_col)

        """column time"""
        self.time_col = Gtk.TreeViewColumn(None, Gtk.CellRendererText(), text=self.time[0])
        self.time_col.key = "Time"
        self.time_col.label = Gtk.Label(_("Time"))
        self.time_col.item = Gtk.CheckMenuItem(_("Time"))
        self._append_column(self.time_col)

        self.configure_send_drag()
        self.configure_recive_drag()

        self.set_playlist_plain()

        self.connect("button-release-event", self.on_button_press)

        self.on_load()

        self.connect("columns-changed", self.on_columns_changed)

    def set_playlist_tree(self):
        self.rebuild_as_tree()

    def set_playlist_plain(self):
        self.rebuild_as_plain()

    def on_key_release(self, w, e):
        if is_modificator(e):
            return
        elif is_key(e, KEY_RETURN):
            self.controls.play_selected_song()
        elif is_key(e, KEY_DELETE):
            self.delete_selected()
        elif is_key(e, 'Left'):
            self.controls.seek_down()
        elif is_key(e, 'Right'):
            self.controls.seek_up()

    def get_bean_under_pointer_icon(self):
        for row in self.model:
            if row[self.play_icon[0]]:
                bean = self.get_bean_from_row(row)
                return bean

    def common_single_random(self):
        logging.debug("Repeat state " + str(FC().repeat_state))
        if FC().repeat_state == const.REPEAT_SINGLE:
            return self.get_current_bean_by_UUID()

        if FC().is_order_random:
            bean = self.get_random_bean()
            self.set_play_icon_to_bean(bean)
            return bean

    def next(self):
        bean = self.common_single_random()
        if bean:
            self.scroll_follow_play_icon()
            return bean

        bean = self.get_next_bean(FC().repeat_state == const.REPEAT_ALL)

        if not bean:
            self.controls.state_stop()
            return

        self.set_play_icon_to_bean(bean)
        self.scroll_follow_play_icon()

        logging.debug("Next bean " + str(bean) + bean.text)

        return bean

    def prev(self):
        if FC().repeat_state == const.REPEAT_SINGLE:
            return self.get_current_bean_by_UUID()

        bean = self.get_prev_bean(FC().repeat_state == const.REPEAT_ALL)

        if not bean:
            self.controls.state_stop()
            return

        self.set_play_icon_to_bean(bean)
        self.scroll_follow_play_icon()

        return bean


    @idle_task
    def scroll_follow_play_icon(self):
        paths = [(i,) for i, row in enumerate(self.model)]
        for row, path in zip(self.model, paths):
            if row[self.play_icon[0]]:
                start_path, end_path = self.get_visible_range()
                path = row.path
                if path >= end_path or path <= start_path:
                    self.scroll_to_cell(path)

    def append(self, paths):
        for i, path in enumerate(paths):
            if os.path.isdir(path):
                listdir = filter(lambda x: get_file_extension(x) in FC().all_support_formats or os.path.isdir(x),
                                 [os.path.join(path, f) for f in os.listdir(path)])
                for k, p in enumerate(listdir):
                    paths.insert(i + k + 1, p)
        rows = self.file_paths_to_rows(paths)
        if not rows:
            return
        #rows = self.playlist_filter(rows)
        for row in rows:
            self.model.append(None, row)
        thread.start_new_thread(self.safe_fill_treerows, ())

    def is_empty(self):
        return True if not self.model.get_iter_first() else False

    def on_button_press(self, w, e):
        if self.header_pressed:
            self.header_pressed = False
            return
        if is_empty_click(w, e):
            w.get_selection().unselect_all()
        if is_double_left_click(e):
            self.controls.play_selected_song()

        if is_rigth_click(e):
            right_click_optimization_for_trees(w, e)
            beans = self.get_selected_beans()
            if beans:
                self.tree_menu.clear()
                self.tree_menu.add_item(_('Play'), Gtk.STOCK_MEDIA_PLAY, self.controls.play_selected_song, None)
                self.tree_menu.add_item(_('Delete from playlist'), Gtk.STOCK_DELETE, self.delete_selected, None)

                paths = []
                inet_paths = []
                local_paths = []
                for bean in beans:
                    if bean.path in paths:
                        continue
                    paths.append(bean.path)
                    if not bean.path or bean.path.startswith("http://"):
                        inet_paths.append(bean.path)
                    else:
                        local_paths.append(bean.path)

                if local_paths:
                    self.tree_menu.add_item(_('Copy To...'), Gtk.STOCK_ADD, copy_to, local_paths)
                    self.tree_menu.add_item(_("Open in file manager"), None, open_in_filemanager, local_paths[0])
                if inet_paths:
                    self.tree_menu.add_item(_('Download'), Gtk.STOCK_ADD,
                                            self.controls.dm.append_tasks, self.get_all_selected_beans())
                    self.tree_menu.add_item(_('Download To...'), Gtk.STOCK_ADD,
                                            self.controls.dm.append_tasks_with_dialog, self.get_all_selected_beans())

                self.tree_menu.add_separator()

                if local_paths:
                    self.tree_menu.add_item(_('Edit Tags'), Gtk.STOCK_EDIT, edit_tags, (self.controls, local_paths))
                    self.tree_menu.add_item(_('Format Converter'), Gtk.STOCK_CONVERT, convert_files, local_paths)
                text = self.get_selected_bean().text
                self.tree_menu.add_item(_('Copy To Search Line'), Gtk.STOCK_COPY,
                                        self.controls.searchPanel.set_search_text, text)
                self.tree_menu.add_separator()
                self.tree_menu.add_item(_('Copy №-Title-Time'), Gtk.STOCK_COPY, self.copy_info_to_clipboard)
                self.tree_menu.add_item(_('Copy Artist-Title-Album'), Gtk.STOCK_COPY,
                                        self.copy_info_to_clipboard, True)
                self.tree_menu.add_separator()
                self.tree_menu.add_item(_('Love This Track(s) by Last.fm'), None,
                                        self.controls.love_this_tracks, self.get_all_selected_beans())
                self.tree_menu.add_item(_('Add to My Audio (VK)'), None,
                                        self.controls.add_to_my_playlist, self.get_all_selected_beans())
                self.tree_menu.add_item(_('Copy link'), None,
                                        self.controls.copy_link, self.get_all_selected_beans())

                self.tree_menu.show(e)

    def on_click_header(self, w, e):
        self.header_pressed = True
        if is_rigth_click(e):
            if "menu" in w.__dict__:
                w.menu.show(e)
            else:
                self.menu.show(e)

    def on_toggled_num(self, *a):
        FC().numbering_by_order = not FC().numbering_by_order
        number_music_tabs = self.controls.notetabs.get_n_pages() - 1
        for page in xrange(number_music_tabs, -1, -1):
            tab_content = self.controls.notetabs.get_nth_page(page)
            pl_tree = tab_content.get_child()
            if FC().numbering_by_order:
                pl_tree.update_tracknumber()
                pl_tree.num_order.set_active(True)
                continue
            pl_tree.num_tags.set_active(True)
            for row in pl_tree.model:
                if row[pl_tree.is_file[0]]:
                    audio = get_mutagen_audio(row[pl_tree.path[0]])
                    if audio and audio.has_key('tracknumber'):
                        row[pl_tree.tracknumber[0]] = re.search('\d*', audio['tracknumber'][0]).group()
                    if audio and audio.has_key('trkn'):
                        row[pl_tree.tracknumber[0]] = re.search('\d*', audio["trkn"][0]).group()

    def on_toggle(self, w, e, column):
        FC().columns[column.key][0] = not FC().columns[column.key][0]

        number_music_tabs = self.controls.notetabs.get_n_pages() - 1
        for key in self.__dict__.keys():
            if self.__dict__[key] is column:
                atr_name = key
                break

        for page in xrange(number_music_tabs, -1, -1):
            tab_content = self.controls.notetabs.get_nth_page(page)
            pl_tree = tab_content.get_child()
            ## TODO: check "local variable 'atr_name' might be referenced before assignment"
            pl_tree_column = pl_tree.__dict__[atr_name]
            if FC().columns[column.key][0]:
                pl_tree.move_column_after(pl_tree_column, pl_tree.icon_col)
                pl_tree_column.set_visible(True)
                if self is not pl_tree:
                    pl_tree_column.item.set_active(True)
            else:
                pl_tree_column.set_visible(False)
                if self is not pl_tree:
                    pl_tree_column.item.set_active(False)

    def _append_column(self, column):
        column.set_widget(column.label)
        column.set_sizing(Gtk.TREE_VIEW_COLUMN_FIXED)
        if column.key in ['*', 'N', 'Time']:
            column.set_sizing(Gtk.TREE_VIEW_COLUMN_AUTOSIZE)
        else:
            column.set_sizing(Gtk.TREE_VIEW_COLUMN_FIXED)
        if FC().columns[column.key][2] > 0:
            column.set_fixed_width(FC().columns[column.key][2])

        self.append_column(column)
        column.button = column.label.get_parent().get_parent().get_parent()
        column.button.connect("button-press-event", self.on_click_header)
        '''
        if column.key == 'N':
            self.trkn_col.button.menu = Popup()
            group = []
            self.num_order = Gtk.RadioMenuItem.new_with_label(group, _("Numbering by order"))
            self.num_order.connect("button-press-event", self.on_toggled_num)
            group.append(self.num_order)
            self.num_tags = Gtk.RadioMenuItem.new_with_label(group, _("Numbering by tags"))
            self.num_tags.connect("button-press-event", self.on_toggled_num)
            group.append(self.num_tags)
            self.trkn_col.button.menu.append(self.num_order)
            self.trkn_col.button.menu.append(self.num_tags)
            if FC().numbering_by_order:
                self.num_order.set_active(True)
            else:
                self.num_tags.set_active(True)
        '''

    def on_columns_changed(self, *a):
        global FLAG
        if FLAG:
            return
        FLAG = True

        number_music_tabs = self.controls.notetabs.get_n_pages() - 1
        for i, column in enumerate(self.get_columns()):
            FC().columns[column.key][1] = i
            if column.get_width() > 1:  # to avoid recording of zero width in config
                FC().columns[column.key][2] = column.get_width()

        for page in xrange(number_music_tabs, 0, -1):
            tab_content = self.controls.notetabs.get_nth_page(page)
            pl_tree = tab_content.get_child()
            col_list = pl_tree.get_columns()
            col_list.sort(self.to_order_columns, reverse=True)
            for column in col_list:
                pl_tree.move_column_after(column, None)
        FLAG = False

    def to_order_columns(self, x, y):
        return cmp(FC().columns[x.key][1], FC().columns[y.key][1])

    def on_load(self):
        col_list = self.get_columns()
        col_list.sort(self.to_order_columns, reverse=True)
        visible_columns = []
        for column in col_list:
            column.label.show()
            column.set_widget(column.label)
            column.set_clickable(True)
            if column.key != "*":
                column.set_reorderable(True)
            if FC().columns[column.key][0]:
                self.move_column_after(column, None)
                if "item" in column.__dict__:
                    column.item.connect("button-press-event", self.on_toggle, column)
                    self.menu.append(column.item)
                    column.item.set_active(True)
                visible_columns.append(column)
            else:
                if "item" in column.__dict__:
                    column.item.connect("button-press-event", self.on_toggle, column)
                    self.menu.append(column.item)
                    column.item.set_active(False)
                column.set_visible(False)
        '''if FC().columns["Track"][2] < 0:
             self.description_col.set_fixed_width(self.get_allocation().width - (FC().columns["Time"][2]+70))'''

    def change_rows_by_path(self, file_paths):
        for treerow in self.model:
            if treerow[self.is_file[0]] and treerow[self.path[0]] in file_paths:
                bean = self.get_bean_from_row(treerow)
                bean = update_id3(bean)
                row_ref = Gtk.TreeRowReference.new(self.model, treerow.path)
                self.fill_row(row_ref, bean)
        GLib.idle_add(self.controls.notetabs.save_current_tab, priority=GLib.PRIORITY_LOW)

    def file_paths_to_rows(self, paths):
        result = []
        for path in paths:
            bean = get_bean_from_file(path)
            beans = update_id3_for_m3u([bean])
            beans = update_id3_for_pls(beans)
            if beans and (len(beans) > 1 or is_playlist(bean.path)):
                    bean = bean.add_text(_('Playlist: ') + bean.text).add_font("bold").add_is_file(False)
                    bean.path = ''
                    beans.insert(0, bean)
            for bean in beans:
                result.append(self.get_row_from_bean(bean))
        return result

    def on_drag_data_received(self, treeview, context, x, y, selection, info, timestamp):
        logging.debug('Playlist on_drag_data_received')
        model = self.get_model().get_model()
        drop_info = self.get_dest_row_at_pos(x, y)

        if drop_info:
            path, position = drop_info
            iter = model.get_iter(path)

        files = sorted([file for file in get_files_from_gtk_selection_data(selection)
                if os.path.isdir(file) or get_file_extension(file) in FC().all_support_formats],
                key=lambda x: x[self.text[0]])
        if files:
            '''dnd from the outside of the player'''
            if self.is_empty():
                if len(files) == 1 and os.path.isdir(files[0]):
                    tabname = os.path.basename(files[0])
                else:
                    tabname = os.path.split(os.path.dirname(files[0]))[1]
                self.controls.notetabs.rename_tab(self.scroll, tabname)
            for i, file in enumerate(files):
                if os.path.isdir(file):
                    sorted_dirs = []
                    sorted_files = []
                    for f in sorted(os.listdir(file), key=lambda x: x):
                        f = os.path.join(file, f)
                        if os.path.isdir(f):
                            sorted_dirs.append(f)
                        elif get_file_extension(f) in FC().all_support_formats:
                            sorted_files.append(f)

                    listdir = sorted_dirs + sorted_files
                    '''
                    listdir = sorted(filter(lambda x: get_file_extension(x) in FC().all_support_formats or os.path.isdir(x),
                                     [os.path.join(file, f) for f in os.listdir(file)]), key=lambda x: x)
                    '''
                    for k, path in enumerate(listdir):
                        files.insert(i + k + 1, path)

            rows = self.file_paths_to_rows(files)
            if not rows:
                return
            rows = self.playlist_filter(rows)
            for row in rows:
                if drop_info:
                    if (position == Gtk.TREE_VIEW_DROP_BEFORE
                        or position == Gtk.TREE_VIEW_DROP_INTO_OR_BEFORE):
                        model.insert_before(None, iter, row)
                    else:
                        model.insert_after(None, iter, row)
                        iter = model.iter_next(iter)
                else:
                    model.append(None, row)

        else:
            '''dnd inside the player'''
            # ff - from_filter
            ff_tree = Gtk.drag_get_source_widget(context)
            ff_model, ff_paths = ff_tree.get_selection().get_selected_rows()
            treerows = [ff_model[ff_path] for ff_path in ff_paths]

            if self is ff_tree:
                '''internal dnd'''
                ff_row_refs = [Gtk.TreeRowReference.new(ff_model, ff_path) for ff_path in ff_paths]
                for ff_row_ref in ff_row_refs:
                    ff_iter = self.get_iter_from_row_reference(ff_row_ref)
                    f_iter = ff_model.convert_iter_to_child_iter(ff_iter)
                    if drop_info:
                        if (position == Gtk.TREE_VIEW_DROP_BEFORE
                            or position == Gtk.TREE_VIEW_DROP_INTO_OR_BEFORE):
                            model.move_before(f_iter, iter)
                        else:
                            model.move_after(f_iter, iter)
                            iter = model.iter_next(iter)
                    else:
                        model.move_before(f_iter, None)
                return

            else:
                '''dnd from other tree'''
                if self.is_empty():
                    path = treerows[0][self.path[0]]
                    if path:
                        if len(treerows) == 1 and os.path.isdir(path):
                            tabname = os.path.basename(path)
                        else:
                            tabname = os.path.split(os.path.dirname(path))[1]
                        self.controls.notetabs.rename_tab(self.scroll, tabname)
                    else:
                        pass
                for i, treerow in enumerate(treerows):

                    for k, ch_row in enumerate(treerow.iterchildren()):
                        treerows.insert(i + k + 1, ch_row)

                #treerows = self.playlist_filter(treerows)

                for i, treerow in enumerate(treerows):
                    if is_playlist(treerow[self.path[0]]):
                        rows = self.file_paths_to_rows([treerow[self.path[0]]])
                        if rows:
                            rows.reverse()
                            map(lambda row: treerows.insert(i + 1, row), rows)
                            continue
                    row = [col for col in treerow]
                    if drop_info:
                        if (position == Gtk.TREE_VIEW_DROP_BEFORE
                            or position == Gtk.TREE_VIEW_DROP_INTO_OR_BEFORE):
                            model.insert_before(None, iter, row)
                        else:
                            model.insert_after(None, iter, row)
                            iter = model.iter_next(iter)
                    else:
                        model.append(None, row)


        thread.start_new_thread(self.safe_fill_treerows, ())

        context.finish(True, False, timestamp)
        self.stop_emission('drag-data-received')
        return True
Exemple #3
0
class PlaylistTreeControl(CommonTreeControl):
    
    def __init__(self, controls):
        CommonTreeControl.__init__(self, controls)
        
        self.set_headers_visible(True)
        self.set_headers_clickable(True)
        self.set_reorderable(True)
        
        self.menu = Popup()

        """Column icon"""
        self.icon_col = gtk.TreeViewColumn(None, gtk.CellRendererPixbuf(), stock_id=self.play_icon[0])
        self.icon_col.key = "*"
        self.icon_col.set_fixed_width(5)
        self.icon_col.set_min_width(5)
        self.icon_col.label = gtk.Label("*")
        self._append_column(self.icon_col)
        
        """track number"""
        self.trkn_col = gtk.TreeViewColumn(None, gtk.CellRendererText(), text=self.tracknumber[0])
        self.trkn_col.key = "№"
        self.trkn_col.set_clickable(True)
        self.trkn_col.label = gtk.Label("№")
        self.trkn_col.label.show()
        self.trkn_col.item = gtk.CheckMenuItem(_("Number"))
        self.trkn_col.set_widget(self.trkn_col.label)
        self._append_column(self.trkn_col)
        
        """column composer"""
        self.comp_col = gtk.TreeViewColumn(None, gtk.CellRendererText(), text=self.composer[0])
        self.comp_col.key = "Composer"
        self.comp_col.set_resizable(True)
        self.comp_col.label = gtk.Label(_("Composer"))
        self.comp_col.item = gtk.CheckMenuItem(_("Composer"))
        self._append_column(self.comp_col)
        
        """column artist title"""
        self.description_col = gtk.TreeViewColumn(None, gtk.CellRendererText(), text=self.text[0], font=self.font[0])
        self.description_col.key = "Track"
        self.description_col.set_resizable(True)
        self.description_col.label = gtk.Label(_("Track"))
        self.description_col.item = gtk.CheckMenuItem(_("Track"))
        self._append_column(self.description_col)
                        
        """column artist"""
        self.artist_col = gtk.TreeViewColumn(None, gtk.CellRendererText(), text=self.artist[0])
        self.artist_col.key = "Artist"
        self.artist_col.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
        self.artist_col.set_resizable(True)
        self.artist_col.label = gtk.Label(_("Artist"))
        self.artist_col.item = gtk.CheckMenuItem(_("Artist"))
        self._append_column(self.artist_col)
               
        """column title"""
        self.title_col = gtk.TreeViewColumn(None, gtk.CellRendererText(), text=self.title[0])
        self.title_col.key = "Title"
        self.title_col.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
        self.title_col.set_resizable(True)
        self.title_col.label = gtk.Label(_("Title"))
        self.title_col.item = gtk.CheckMenuItem(_("Title"))
        self._append_column(self.title_col)
        
        """column album"""
        self.album_col = gtk.TreeViewColumn(None, gtk.CellRendererText(), text=self.album[0])
        self.album_col.key = "Album"
        
        
        if not FC().columns.has_key(self.album_col.key):
            FC().columns[self.album_col.key] = [False, 7, 90]
        self.album_col.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
        self.album_col.set_resizable(True)
        self.album_col.label = gtk.Label(_("Album"))
        self.album_col.item = gtk.CheckMenuItem(_("Album"))
        self._append_column(self.album_col)
        
        """column time"""
        self.time_col = gtk.TreeViewColumn(None, gtk.CellRendererText(), text=self.time[0])
        self.time_col.key = "Time"
        self.time_col.label = gtk.Label(_("Time"))
        self.time_col.item = gtk.CheckMenuItem(_("Time"))
        self._append_column(self.time_col)

        self.configure_send_drag()
        self.configure_recive_drag()
        
        self.set_playlist_plain()
        
        self.connect("button-release-event", self.on_button_press)
        
        self.on_load()
        
        self.connect("columns-changed", self.on_columns_changed)
        
    def set_playlist_tree(self):
        self.rebuild_as_tree()
                
    def set_playlist_plain(self):
        self.rebuild_as_plain()
        
    def on_key_release(self, w, e):
        if is_key(e, KEY_RETURN):
            self.controls.play_selected_song()
        elif is_key(e, KEY_DELETE):
            self.delete_selected()     
        elif is_key(e, 'Left'):
            self.controls.seek_down()
        elif is_key(e, 'Right'):
            self.controls.seek_up()
    
    def get_bean_under_pointer_icon(self):
        for row in self.model:
            if row[self.play_icon[0]]:
                bean = self.get_bean_from_row(row)
                return bean
            
            
    def common_single_random(self):
        logging.debug("Repeat state " + str(FC().repeat_state))
        if FC().repeat_state == const.REPEAT_SINGLE:
            return self.get_current_bean_by_UUID();
        
        if FC().is_order_random:               
            bean = self.get_random_bean()
            self.set_play_icon_to_bean(bean)
            return bean
    
    def next(self):
        bean = self.common_single_random()       
        if bean:
            self.scroll_follow_play_icon()  
            return bean
        
        bean = self.get_next_bean(FC().repeat_state == const.REPEAT_ALL)
        
        if not bean:
            self.controls.state_stop()
            return
        
        self.set_play_icon_to_bean(bean)
           
        self.scroll_follow_play_icon()            
        
        logging.debug("Next bean " + str(bean) + bean.text)
        
        return bean

    def prev(self):
        if FC().repeat_state == const.REPEAT_SINGLE:
            return self.get_current_bean_by_UUID()
        
        bean = self.get_prev_bean(FC().repeat_state == const.REPEAT_ALL)
        
        if not bean:
            self.controls.state_stop()
            return
        
                
        self.set_play_icon_to_bean(bean)
        
        self.scroll_follow_play_icon() 
        
        return bean
    
    def scroll_follow_play_icon(self):
        paths = [(i,) for i, row in enumerate(self.model)]
        for row, path in zip(self.model, paths):
            if row[self.play_icon[0]]:
                start_path, end_path = self.get_visible_range()
                if path > end_path or path < start_path:
                    self.scroll_to_cell(path)
    
    def append(self, bean):
        return super(PlaylistTreeControl, self).append(bean)

    def on_button_press(self, w, e):
        if is_empty_click(w, e):
            w.get_selection().unselect_all()
        if is_double_left_click(e):
            self.controls.play_selected_song()
            
        if is_rigth_click(e):
            right_click_optimization_for_trees(w, e)
            beans = self.get_selected_beans()
            if beans:
                menu = Popup()
                menu.add_item(_('Play'), gtk.STOCK_MEDIA_PLAY, self.controls.play_selected_song, None)
                menu.add_item(_('Delete from playlist'), gtk.STOCK_DELETE, self.delete_selected, None)
            
                paths = []
                inet_paths = []
                local_paths = []
                for bean in beans:
                    if bean.path in paths:
                        continue
                    paths.append(bean.path)
                    if not bean.path or bean.path.startswith("http://"):
                        inet_paths.append(bean.path)
                    else:
                        local_paths.append(bean.path)
                                                    
                if local_paths:
                    menu.add_item(_('Copy To...'), gtk.STOCK_ADD, copy_to, local_paths)
                    menu.add_item(_("Open in file manager"), None, open_in_filemanager, local_paths[0])
                if inet_paths:
                    menu.add_item(_('Download'), gtk.STOCK_ADD, self.controls.dm.append_tasks, self.get_all_selected_beans())
                    menu.add_item(_('Download To...'), gtk.STOCK_ADD, self.controls.dm.append_tasks_with_dialog, self.get_all_selected_beans())
                                
                menu.add_separator()
                
                if paths[0]:
                    menu.add_item(_('Edit Tags'), gtk.STOCK_EDIT, edit_tags, (self.controls, paths))
                    menu.add_item(_('Format Converter'), gtk.STOCK_CONVERT, convert_files, paths)
                text = self.get_selected_bean().text
                menu.add_item(_('Copy To Search Line'), gtk.STOCK_COPY, self.controls.searchPanel.set_search_text, text)
                menu.add_separator()
                menu.add_item(_('Copy №-Title-Time'), gtk.STOCK_COPY, self.copy_info_to_clipboard)
                menu.add_item(_('Copy Artist-Title-Album'), gtk.STOCK_COPY, self.copy_info_to_clipboard, True)
                menu.add_separator()
                menu.add_item(_('Love This Track(s) by Last.fm'), None, self.controls.love_this_tracks, self.get_all_selected_beans())
                menu.add_separator()
                if paths[0]:
                    menu.add_item(_("Open In File Manager"), None, open_in_filemanager, paths[0])
                menu.show(e)
                  
    def on_click_header(self, w, e):
        if is_rigth_click(e):
            if w.__dict__.has_key("menu"):
                w.menu.show(e)
            else:
                self.menu.show(e)
            
    def on_toggled_num(self, *a):
        FC().numbering_by_order = not FC().numbering_by_order
        number_music_tabs = self.controls.notetabs.get_n_pages() - 1
        for page in xrange(number_music_tabs, 0, -1):
            tab_content = self.controls.notetabs.get_nth_page(page)
            pl_tree = tab_content.get_child()
            if FC().numbering_by_order:
                pl_tree.update_tracknumber()
                pl_tree.num_order.set_active(True)
                continue
            pl_tree.num_tags.set_active(True)
            for row in pl_tree.model:
                if row[pl_tree.is_file[0]]:
                    audio = get_mutagen_audio(row[pl_tree.path[0]])
                    if audio and audio.has_key('tracknumber'):
                        row[pl_tree.tracknumber[0]] = re.search('\d*', audio['tracknumber'][0]).group()
                    if audio and audio.has_key('trkn'):
                        row[pl_tree.tracknumber[0]] = re.search('\d*', audio["trkn"][0]).group()
        
    def on_toggle(self, w, e, column):
        FC().columns[column.key][0] = not FC().columns[column.key][0]
        
        number_music_tabs = self.controls.notetabs.get_n_pages() - 1
        for key in self.__dict__.keys():
            if self.__dict__[key] is column:
                atr_name = key
                break
        for page in xrange(number_music_tabs, 0, -1):
            tab_content = self.controls.notetabs.get_nth_page(page)
            pl_tree = tab_content.get_child()
            pl_tree_column = pl_tree.__dict__[atr_name]
            if FC().columns[column.key][0]:
                pl_tree.move_column_after(pl_tree_column, pl_tree.icon_col)
                pl_tree_column.set_visible(True)
                if self is not pl_tree:
                    pl_tree_column.item.set_active(True)
            else:
                pl_tree_column.set_visible(False)
                if self is not pl_tree:
                    pl_tree_column.item.set_active(False)
    
    def _append_column(self, column):
        column.set_widget(column.label)
        column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
        if column.key in ['*', '№', 'Time']:
            column.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
        else:
            column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
        if FC().columns[column.key][2] > 0:
            column.set_fixed_width(FC().columns[column.key][2])
        
        self.append_column(column)
        column.button = column.label.get_parent().get_parent().get_parent()
        column.button.connect("button-press-event", self.on_click_header)
        if column.key == '№':
            self.trkn_col.button.menu = Popup()
            self.num_order = gtk.RadioMenuItem(None, _("Numbering by order"))
            self.num_order.connect("button-press-event", self.on_toggled_num)
            self.num_tags = gtk.RadioMenuItem(self.num_order, _("Numbering by tags"))
            self.num_tags.connect("button-press-event", self.on_toggled_num)
        
            self.trkn_col.button.menu.append(self.num_order)
            self.trkn_col.button.menu.append(self.num_tags)
            if FC().numbering_by_order:
                self.num_order.set_active(True)
            else:
                self.num_tags.set_active(True)
    
    def on_columns_changed(self, *a):
        global FLAG
        if FLAG:
            return
        FLAG = True 
        
        number_music_tabs = self.controls.notetabs.get_n_pages() - 1
        for i, column in enumerate(self.get_columns()):
            FC().columns[column.key][1] = i
            if column.get_width() > 1: #to avoid recording of zero width in config 
                FC().columns[column.key][2] = column.get_width()
        
        for page in xrange(number_music_tabs, 0, -1):
            tab_content = self.controls.notetabs.get_nth_page(page)
            pl_tree = tab_content.get_child()
            col_list = pl_tree.get_columns()
            col_list.sort(self.to_order_columns, reverse=True)
            for column in col_list:
                pl_tree.move_column_after(column, None)
        FLAG = False
        
    def to_order_columns(self, x, y):
        return cmp(FC().columns[x.key][1], FC().columns[y.key][1])  
                          
    def on_load(self):
        col_list = self.get_columns()
        col_list.sort(self.to_order_columns, reverse=True)
        visible_columns = []
        for column in col_list:
            column.label.show()
            column.set_widget(column.label)
            column.set_clickable(True)
            if column.key != "*":
                column.set_reorderable(True)            
            if FC().columns[column.key][0]:
                self.move_column_after(column, None)
                if column.__dict__.has_key("item"):
                    column.item.connect("button-press-event", self.on_toggle, column)
                    self.menu.append(column.item)
                    column.item.set_active(True)
                visible_columns.append(column)
            else:
                if column.__dict__.has_key("item"):
                    column.item.connect("button-press-event", self.on_toggle, column)
                    self.menu.append(column.item)
                    column.item.set_active(False)
                column.set_visible(False)
        '''if FC().columns["Track"][2] < 0:
Exemple #4
0
class PlaylistTreeControl(CommonTreeControl):
    def __init__(self, controls):
        CommonTreeControl.__init__(self, controls)

        self.set_headers_visible(True)
        self.set_headers_clickable(True)
        self.set_reorderable(True)

        self.menu = Popup()
        """Column icon"""
        self.icon_col = gtk.TreeViewColumn(None,
                                           gtk.CellRendererPixbuf(),
                                           stock_id=self.play_icon[0])
        self.icon_col.key = "*"
        self.icon_col.set_fixed_width(5)
        self.icon_col.set_min_width(5)
        self.icon_col.label = gtk.Label("*")
        self._append_column(self.icon_col)
        """track number"""
        self.trkn_col = gtk.TreeViewColumn(None,
                                           gtk.CellRendererText(),
                                           text=self.tracknumber[0])
        self.trkn_col.key = "№"
        self.trkn_col.set_clickable(True)
        self.trkn_col.label = gtk.Label("№")
        self.trkn_col.label.show()
        self.trkn_col.item = gtk.CheckMenuItem(_("Number"))
        self.trkn_col.set_widget(self.trkn_col.label)
        self._append_column(self.trkn_col)
        """column composer"""
        self.comp_col = gtk.TreeViewColumn(None,
                                           gtk.CellRendererText(),
                                           text=self.composer[0])
        self.comp_col.key = "Composer"
        self.comp_col.set_resizable(True)
        self.comp_col.label = gtk.Label(_("Composer"))
        self.comp_col.item = gtk.CheckMenuItem(_("Composer"))
        self._append_column(self.comp_col)
        """column artist title"""
        self.description_col = gtk.TreeViewColumn(None,
                                                  gtk.CellRendererText(),
                                                  text=self.text[0],
                                                  font=self.font[0])
        self.description_col.key = "Track"
        self.description_col.set_resizable(True)
        self.description_col.label = gtk.Label(_("Track"))
        self.description_col.item = gtk.CheckMenuItem(_("Track"))
        self._append_column(self.description_col)
        """column artist"""
        self.artist_col = gtk.TreeViewColumn(None,
                                             gtk.CellRendererText(),
                                             text=self.artist[0])
        self.artist_col.key = "Artist"
        self.artist_col.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
        self.artist_col.set_resizable(True)
        self.artist_col.label = gtk.Label(_("Artist"))
        self.artist_col.item = gtk.CheckMenuItem(_("Artist"))
        self._append_column(self.artist_col)
        """column title"""
        self.title_col = gtk.TreeViewColumn(None,
                                            gtk.CellRendererText(),
                                            text=self.title[0])
        self.title_col.key = "Title"
        self.title_col.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
        self.title_col.set_resizable(True)
        self.title_col.label = gtk.Label(_("Title"))
        self.title_col.item = gtk.CheckMenuItem(_("Title"))
        self._append_column(self.title_col)
        """column time"""
        self.time_col = gtk.TreeViewColumn(None,
                                           gtk.CellRendererText(),
                                           text=self.time[0])
        self.time_col.key = "Time"
        self.time_col.label = gtk.Label(_("Time"))
        self.time_col.item = gtk.CheckMenuItem(_("Time"))
        self._append_column(self.time_col)

        self.configure_send_drag()
        self.configure_recive_drag()

        self.set_playlist_plain()

        self.connect("button-release-event", self.on_button_release)

        self.on_load()

        self.connect("columns-changed", self.on_columns_changed)

    def set_playlist_tree(self):
        self.rebuild_as_tree()

    def set_playlist_plain(self):
        self.rebuild_as_plain()

    def on_key_release(self, w, e):
        if is_key(e, KEY_RETURN):
            self.controls.play_selected_song()
        elif is_key(e, KEY_DELETE):
            self.delete_selected()
        elif is_key(e, 'Left'):
            self.controls.seek_down()
        elif is_key(e, 'Right'):
            self.controls.seek_up()

    def common_single_random(self):
        logging.debug("Repeat state" + str(FC().repeat_state))
        if FC().repeat_state == const.REPEAT_SINGLE:
            return self.get_current_bean_by_UUID()

        if FC().is_order_random:
            bean = self.get_random_bean()
            self.set_play_icon_to_bean(bean)
            return bean

    def next(self):
        bean = self.common_single_random()
        if bean:
            return bean

        bean = self.get_next_bean(FC().repeat_state == const.REPEAT_ALL)

        if not bean:
            return

        self.set_play_icon_to_bean(bean)

        self.scroll_follow_play_icon()

        logging.debug("Next bean" + str(bean) + bean.text)

        return bean

    def prev(self):
        bean = self.common_single_random()
        if bean:
            return bean

        bean = self.get_prev_bean(FC().repeat_state == const.REPEAT_ALL)

        if not bean:
            return

        self.set_play_icon_to_bean(bean)

        self.scroll_follow_play_icon()

        return bean

    def scroll_follow_play_icon(self):
        paths = [(i, ) for i, row in enumerate(self.model)]
        for row, path in zip(self.model, paths):
            if row[self.play_icon[0]]:
                start_path, end_path = self.get_visible_range()
                if path > end_path or path < start_path:
                    self.scroll_to_cell(path)

    def append(self, bean):
        return super(PlaylistTreeControl, self).append(bean)

    def on_button_press(self, w, e):
        #self.controls.notetabs.set_active_tree(self)
        if is_rigth_click(e):
            """to avoid unselect all selected items"""
            self.stop_emission('button-press-event')
        if is_double_left_click(e):
            self.controls.play_selected_song()

    def on_button_release(self, w, e):
        if is_rigth_click_release(e):
            """to select item under cursor"""
            try:
                path, col, cellx, celly = self.get_path_at_pos(
                    int(e.x), int(e.y))  #@UnusedVariable
                self.get_selection().select_path(path)
            except TypeError:
                pass
            #menu.add_item('Save as', gtk.STOCK_SAVE_AS, self.controls.save_beans_to, self.get_all_selected_beans())

            beans = self.get_selected_beans()

            if beans:
                menu = Popup()
                menu.add_item(_('Play'), gtk.STOCK_MEDIA_PLAY,
                              self.controls.play_selected_song, None)
                menu.add_item(_('Download'), gtk.STOCK_ADD,
                              self.controls.dm.append_tasks,
                              self.get_all_selected_beans())
                menu.add_item(_('Download To...'), gtk.STOCK_ADD,
                              self.controls.dm.append_tasks_with_dialog,
                              self.get_all_selected_beans())
                menu.add_separator()
                paths = [bean.path for bean in beans]
                if paths[0]:
                    menu.add_item(_('Edit Tags'), gtk.STOCK_EDIT, edit_tags,
                                  (self.controls, paths))
                    menu.add_item(_('Format Converter'), gtk.STOCK_CONVERT,
                                  convert_files, paths)
                text = self.get_selected_bean().text
                menu.add_item(_('Copy To Search Line'), gtk.STOCK_COPY,
                              self.controls.searchPanel.set_search_text, text)
                menu.add_separator()
                menu.add_item(_('Copy №-Title-Time'), gtk.STOCK_COPY,
                              self.copy_info_to_clipboard)
                menu.add_item(_('Copy Artist-Title-Album'), gtk.STOCK_COPY,
                              self.copy_info_to_clipboard, True)
                menu.add_separator()
                menu.add_item(_('Love This Track(s)'), None,
                              self.controls.love_this_tracks,
                              self.get_all_selected_beans())
                menu.add_separator()
                if paths[0]:
                    menu.add_item(_("Open In File Manager"), None,
                                  open_in_filemanager, paths[0])
                menu.show(e)

    def on_click_header(self, w, e):
        if is_rigth_click(e):
            if w.__dict__.has_key("menu"):
                w.menu.show(e)
            else:
                self.menu.show(e)

    def on_toggled_num(self, *a):
        FC().numbering_by_order = not FC().numbering_by_order
        number_music_tabs = self.controls.notetabs.get_n_pages() - 1
        for page in xrange(number_music_tabs, 0, -1):
            tab_content = self.controls.notetabs.get_nth_page(page)
            pl_tree = tab_content.get_child()
            if FC().numbering_by_order:
                pl_tree.rebuild_as_plain()
                pl_tree.num_order.set_active(True)
                continue
            pl_tree.num_tags.set_active(True)
            for row in pl_tree.model:
                if row[pl_tree.is_file[0]]:
                    audio = get_mutagen_audio(row[pl_tree.path[0]])
                    if audio and audio.has_key('tracknumber'):
                        row[pl_tree.tracknumber[0]] = re.search(
                            '\d*', audio['tracknumber'][0]).group()
                    if audio and audio.has_key('trkn'):
                        row[pl_tree.tracknumber[0]] = re.search(
                            '\d*', audio["trkn"][0]).group()

    def on_toggle(self, w, e, column):
        FC().columns[column.key][0] = not FC().columns[column.key][0]

        number_music_tabs = self.controls.notetabs.get_n_pages() - 1
        for key in self.__dict__.keys():
            if self.__dict__[key] is column:
                atr_name = key
                break
        for page in xrange(number_music_tabs, 0, -1):
            tab_content = self.controls.notetabs.get_nth_page(page)
            pl_tree = tab_content.get_child()
            pl_tree_column = pl_tree.__dict__[atr_name]
            if FC().columns[column.key][0]:
                pl_tree.move_column_after(pl_tree_column, pl_tree.icon_col)
                pl_tree_column.set_visible(True)
                if self is not pl_tree:
                    pl_tree_column.item.set_active(True)
            else:
                pl_tree_column.set_visible(False)
                if self is not pl_tree:
                    pl_tree_column.item.set_active(False)

    def _append_column(self, column):
        column.set_widget(column.label)
        column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
        if column.key in ['*', '№', 'Time']:
            column.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
        else:
            column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
        if FC().columns[column.key][2] > 0:
            column.set_fixed_width(FC().columns[column.key][2])

        self.append_column(column)
        column.button = column.label.get_parent().get_parent().get_parent()
        column.button.connect("button-press-event", self.on_click_header)
        if column.key == '№':
            self.trkn_col.button.menu = Popup()
            self.num_order = gtk.RadioMenuItem(None, _("Numbering by order"))
            self.num_order.connect("button-press-event", self.on_toggled_num)
            self.num_tags = gtk.RadioMenuItem(self.num_order,
                                              _("Numbering by tags"))
            self.num_tags.connect("button-press-event", self.on_toggled_num)

            self.trkn_col.button.menu.append(self.num_order)
            self.trkn_col.button.menu.append(self.num_tags)
            if FC().numbering_by_order:
                self.num_order.set_active(True)
            else:
                self.num_tags.set_active(True)

    def on_columns_changed(self, *a):
        global FLAG
        if FLAG:
            return
        FLAG = True

        number_music_tabs = self.controls.notetabs.get_n_pages() - 1
        for i, column in enumerate(self.get_columns()):
            FC().columns[column.key][1] = i
            if column.get_width(
            ) > 1:  #to avoid recording of zero width in config
                FC().columns[column.key][2] = column.get_width()

        for page in xrange(number_music_tabs, 0, -1):
            tab_content = self.controls.notetabs.get_nth_page(page)
            pl_tree = tab_content.get_child()
            col_list = pl_tree.get_columns()
            col_list.sort(self.to_order_columns, reverse=True)
            for column in col_list:
                pl_tree.move_column_after(column, None)
        FLAG = False

    def to_order_columns(self, x, y):
        return cmp(FC().columns[x.key][1], FC().columns[y.key][1])

    def on_load(self):
        col_list = self.get_columns()
        col_list.sort(self.to_order_columns, reverse=True)
        visible_columns = []
        for column in col_list:
            column.label.show()
            column.set_widget(column.label)
            column.set_clickable(True)
            if column.key != "*":
                column.set_reorderable(True)
            if FC().columns[column.key][0]:
                self.move_column_after(column, None)
                if column.__dict__.has_key("item"):
                    column.item.connect("button-press-event", self.on_toggle,
                                        column)
                    self.menu.append(column.item)
                    column.item.set_active(True)
                visible_columns.append(column)
            else:
                if column.__dict__.has_key("item"):
                    column.item.connect("button-press-event", self.on_toggle,
                                        column)
                    self.menu.append(column.item)
                    column.item.set_active(False)
                column.set_visible(False)
        '''if FC().columns["Track"][2] < 0: