def initNetwork(): BDD.network_is_connected = threading.Event() BDD.network_cache = [] try: f = open(os.path.join(xdg.get_data_home(), "network_cache.txt"), "r") queue = f.readlines() f.close() for e in queue: BDD.network_cache.append(eval(e)) except IOError: logger.debug("No network cache file") try: API_KEY = "04537e40b5501f85610cf4e4bbf1d97a" # this is a sample key API_SECRET = "b36376228a6e72314ffd503b8e3c9f5e" # In order to perform a write operation you need to authenticate yourself username = settings.get_option("music/audioscrobbler_login", "") password_hash = md5(settings.get_option("music/audioscrobbler_password", "")) BDD.network = LastFMNetwork( api_key=API_KEY, api_secret=API_SECRET, username=username, password_hash=password_hash ) logger.debug("Connection successfuly established with Last.fm") BDD.network_is_connected.set() except NetworkError: logger.debug("Connection to Last.fm failed")
def loadModuleMenus(self, module): if(module == 'pictures' or module == 'videos'): pictures = QtGui.QMenu(_(module[0].capitalize() + module[1:])) #pictures.addAction(_("Check for doubloons")) pictures.addAction(_('Check for doubloons'), self.core.managers[module].containerBrowser.checkForDoubloons) pictures.addAction(_("Move to UC structure"), lambda: self.moveToUCStructure(module)) pictures.addSeparator() panelGroup = QtGui.QActionGroup(self) browserMode = settings.get_option(module + '/browser_mode', 'panel') panes = pictures.addAction( _('Multi-panes'), lambda: self.core.managers[module].setBrowserMode('panes')) panes.setCheckable(True) if(browserMode == 'panes'): panes.setChecked(True) panes.setActionGroup(panelGroup) panel = pictures.addAction(_('All in one panel'), lambda: self.core.managers[module].setBrowserMode('panel')) panel.setCheckable(True) if(browserMode == 'panel'): panel.setChecked(True) panel.setActionGroup(panelGroup) self.addMenu(pictures) elif(module == 'music'): def reloadCovers(): progressNotifier = self.core.statusBar.addProgressNotifier() self.core.BDD.reloadCovers(progressNotifier) music = QtGui.QMenu(_('Music')) music.addAction(_('Reload covers'), reloadCovers) self.addMenu(music)
def execute_with_filters(self, query, section, params=[]): filters = settings.get_option(section + "/filters", {}) for key in filters.iterkeys(): if filters[key]["enabled"]: try: where += " OR " except NameError: where = "WHERE " for t in filters[key]["criterions"]: try: filter += filters[key]["link"] + t[0] + t[1] + "? " except NameError: filter = t[0] + t[1] + "? " params.append(t[2]) where += "(" + filter + ")" del filter try: query += where except NameError: pass self.c.execute(query, params)
def onReady(self): if len(settings.get_option('music/folders', [])) == 0: if(QtGui.QMessageBox.question(self, _('No indexed folders'), _('Set indexed folders now ?'), QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) == QtGui.QMessageBox.Yes): from qt.gui import modales d = modales.SettingsEditor('folders') d.exec_() self.loadMusic()
def loadTracks(self, mode): """ Charge les données de toutes les pistes selon une structure donnée """ if settings.get_option("music/use_performer", False): artist_query = "IFNULL(performer, artist) AS artist" else: artist_query = "artist" query = ( "SELECT track_ID, path, title, album, " + artist_query + ", genre, length, playcount, rating, year, num FROM tracks " ) filters = settings.get_option("music/filters", {}) params = [] for key in filters.iterkeys(): if filters[key]["enabled"]: try: where += " OR " except NameError: where = "WHERE " for t in filters[key]["criterions"]: try: filter += filters[key]["link"] + t[0] + t[1] + "? " except NameError: filter = t[0] + t[1] + "? " params.append(t[2]) where += "(" + filter + ")" del filter try: query += where except NameError: pass query += " ORDER BY " liste = eval(mode) for e in liste: query += e + ", " print (query) self.c.execute(query[:-2], params) return self.c.fetchall()
def process(): bdd = BDD() account = settings.get_option("music/audioscrobbler_login", None) if account is not None: library = BDD.network.get_user("Maitre_Piccolo").get_library() bdd.execute_with_filters("SELECT DISTINCT artist FROM tracks ", "music") artists = bdd.c.fetchall() bdd.execute_with_filters("SELECT COUNT(DISTINCT artist, album) FROM tracks ", "music") length = float(len(bdd.c.fetchone()[0])) nb_errors = 0 i = 0 P_Bar.set_fraction(i) for artist in artists: try: albums = library.get_albums(artist[0]) # if tracks empty check with only artist d = bdd.conn.cursor() for album in albums: album_title = album.item.get_title() tracks = library.get_tracks(artist[0], album_title) for track in tracks: title = track.item.get_title() bdd.c.execute( "SELECT COUNT(title) FROM tracks WHERE artist = ? AND album != ? COLLATE NOCASE AND title = ? COLLATE NOCASE", (artist[0], album_title, title), ) # Ex : ZZ Top -> Eliminator -> Legs [Last.fm count 50][otherAlbumCount 0] and ZZ Top -> Greatest Hits -> Legs [Last.fm count 2][otherAlbumCount 1] # We don't want the second to erase the first BUT if we only have Greatest Hits we want the big score otherAlbumCount = bdd.c.fetchone()[0] if otherAlbumCount > 0: # If song is in another album, we have to set the album t = (track.playcount, artist[0], album_title, title) d.execute( "UPDATE tracks SET compteur = ? WHERE artist = ? AND album = ? COLLATE NOCASE AND title = ? COLLATE NOCASE", t, ) else: # There is no song with anoter album so we apply on all albums (useful if we have ONLY "Greatest Hits" album like, etc...) t = (track.playcount, artist[0], title) d.execute( "UPDATE tracks SET compteur = ? WHERE artist = ? AND title = ? COLLATE NOCASE", t, ) i += 1 P_Bar.set_fraction(float(i) / length) except WSError: logger.debug("Error with artist " + artist[0] + " and album " + album_title) nb_errors += 1 P_Bar.set_text(str(nb_errors) + " " + _("errors")) bdd.conn.commit() P_Bar.set_text(_("Sync ended with") + " " + str(nb_errors) + " " + _("errors"))
def __init__(self, type, elementSelector): AbstractPanel.__init__(self, type) self.module = type self.elementSelector = elementSelector self.categories = {} self.universes = {} self.model = UCModel() TreeView = ContainerBrowser(self.model) self.TreeView = TreeView self.treeViews = {'folder':TreeView, 'category':TreeView, 'universe':TreeView} TreeView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) TreeView.customContextMenuRequested.connect(self.showContextMenu) #filterModel = QtGui.QSortFilterProxyModel() #filterModel.setSourceModel(self.model) TreeView.setModel(self.model) TreeView.activated.connect(self.onContainerActivated) #TreeView.setDragDropMode(QtGui.QAbstractItemView.DragDrop) self.modesCB = QtGui.QComboBox() modesModel = QtGui.QStandardItemModel() modesModel.appendRow([QtGui.QStandardItem('category'), QtGui.QStandardItem(_("Categories"))]) modesModel.appendRow([QtGui.QStandardItem('universe'), QtGui.QStandardItem(_("Universes"))]) modesModel.appendRow([QtGui.QStandardItem('folder'), QtGui.QStandardItem(_("Folders"))]) self.modesCB.setModel(modesModel) self.modesCB.setModelColumn(1) self.modesCB.currentIndexChanged.connect(self.load) refreshButton = QtGui.QPushButton(QtGui.QIcon.fromTheme('view-refresh'), None) refreshButton.clicked.connect(self.load) self.showAntagonistic = QtGui.QCheckBox() self.showAntagonistic.setToolTip(_('Show antagonistic')) self.showAntagonistic.setChecked(settings.get_option(self.module + 's/show_antagonistic', False)) self.showAntagonistic.stateChanged.connect(self.toggleAntagonistic) layout = QtGui.QVBoxLayout() modeBox = QtGui.QHBoxLayout() modeBox.addWidget(self.showAntagonistic, 0) modeBox.addWidget(self.modesCB, 1) modeBox.addWidget(refreshButton, 0) layout.addLayout(modeBox, 0) layout.addWidget(TreeView, 1) self.searchEntry = QtGui.QLineEdit() self.searchEntry.returnPressed.connect(self.load) layout.addWidget(self.searchEntry, 0) self.setLayout(layout) self.setMinimumWidth(300) self.load()
def __init__(self, module): gtk.Table.__init__(self) i = 0 self.attach(gtk.Label(_('Indexed extensions') + ' :'), 0, 1, i, i+1) self.extensions = gtk.Entry() self.extensions.set_text(settings.get_option(module + '/indexed_extensions', '')) self.attach(self.extensions, 1, 2, i, i+1) i += 1 self.preload = gtk.CheckButton(_('Preload this module')) self.preload.set_active(settings.get_option(module + '/preload', False)) self.preload.set_tooltip_text(_('If true, will be preloaded before application start, else will be loaded on demand (slightly faster startup)')) self.attach(self.preload, 0, 2, i, i+1) i += 1 self.attach(gtk.Label(_('Panel thumbnail size') + ' :'), 0, 1, i, i+1) self.CB_icon_size_panel = gtk.combo_box_new_text() self.CB_icon_size_panel.append_text('16') self.CB_icon_size_panel.append_text('24') self.CB_icon_size_panel.append_text('32') self.CB_icon_size_panel.append_text('48') self.CB_icon_size_panel.append_text('64') self.CB_icon_size_panel.set_active(settings.get_option(module + '/panel_icon_size', 32) /16) self.attach(self.CB_icon_size_panel, 1, 2, i, i+1)
def loadMusic(self): self.loadedModules.append('music') from qt.music.musicpanel import BrowserPanel from qt.music.playerwidget import PlayerWidget backend = settings.get_option('music/playback_lib', 'Phonon') if backend == 'Phonon': from media.phononplayer import Player elif backend == 'GStreamer': from media.player import Player elif backend == 'VLC': from media.vlcplayer import Player player = Player() from qt.music.queue import QueueManager playerWidget = PlayerWidget(player) self.playerWidget = playerWidget index = self.NB_Main.currentIndex() self.NB_Main.removeTab(index) self.HPaned_Music = QtGui.QSplitter(self) self.queueManager = QueueManager(playerWidget) self.browserPanel = BrowserPanel(self.BDD, self.queueManager) self.HPaned_Music.addWidget(self.browserPanel) rightLayout = QtGui.QVBoxLayout() rightLayout.addWidget(self.queueManager) #dockPlayer = QtGui.QDockWidget('Player') #dockPlayer.setFeatures(QtGui.QDockWidget.DockWidgetFloatable | QtGui.QDockWidget.DockWidgetMovable) #dockPlayer.setWidget(playerWidget) rightLayout.addWidget(playerWidget) rightWidget = QtGui.QWidget() rightWidget.setLayout(rightLayout) self.HPaned_Music.addWidget(rightWidget) self.HPaned_Music.setStretchFactor(0,0) self.HPaned_Music.setStretchFactor(1,1) self.NB_Main.insertTab(index, self.HPaned_Music, _('Music')) self.NB_Main.setCurrentIndex(index) self.moduleLoaded.emit('music')
def __init__(self, name, label, cell=None, model_text=None, pixbuf=None, default_width=50, expand=False): kwargs = {} if(model_text is not None): kwargs['text'] = model_text if(pixbuf is not None): kwargs['pixbuf'] = pixbuf gtk.TreeViewColumn.__init__(self, label, cell, **kwargs) self.name = name width = settings.get_option('music/' + self.name + '_width', default_width) self.set_min_width(default_width) #self.set_max_width(width) self.set_expand(expand) self.set_resizable(True) self.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) self.connect('notify::width', self.on_width_change)
def loadState(self): @util.threaded def addTracks(IDs, queue): bdd = BDD() self.addSelection(bdd.getTracksFromIDs(IDs), queue) queues = settings.get_option('session/queues', None) if(queues is not None): for key in queues.iterkeys(): if type(key).__name__== 'int': addTracks(queues[key], self.addQueue()) else: self.addPlaylist(key, queues[key]) else: self.addQueue()
def loadModuleMenus(self, core, module): if(module == 'pictures' or module == 'videos'): pictures = gtk.MenuItem(_(module[0].capitalize() + module[1:])) menu = gtk.Menu() item = gtk.MenuItem(_("Check for doubloons")) item.connect_object('activate', self.checkDoubloons, module) menu.append(item) browserMode = settings.get_option(module + '/browser_mode', 'panel') item = gtk.MenuItem(_("Move to UC structure")) item.connect_object('activate', self.moveToUCStructure, module) menu.append(item) panes = gtk.RadioMenuItem(None, _('Multi-panes')) if browserMode == 'panes': panes.set_active(True) panes.connect_object('toggled', self.core.managers[module].setBrowserMode, 'panes') panel = gtk.RadioMenuItem(panes, _('All in one panel')) if browserMode == 'panel': panel.set_active(True) panel.connect_object('toggled', self.core.managers[module].setBrowserMode, 'panel') menu.append(panes) menu.append(panel) pictures.set_submenu(menu) self.append(pictures) elif(module == 'music'): music = gtk.MenuItem(_("Music")) menu = gtk.Menu() item = gtk.MenuItem(_("Reload covers")) item.connect_object('activate', self.core.BDD.reloadCovers, self.core.statusBar.addProgressNotifier()) menu.append(item) music.set_submenu(menu) self.append(music) self.show_all()
def __init__(self, module): self.module = module gtk.Dialog.__init__(self, title=_("Preparing for files moving"), buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)) self.Box_Main = gtk.VBox() self.get_content_area().pack_start(self.Box_Main) self.button = gtk.FileChooserButton(gtk.FileChooserDialog(_("Choose the structure root folder"), self, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))) self.button.set_filename(settings.get_option(module + '/structure_folder', '~/' + module + '/Bullseye')) self.Box_Main.pack_start(self.button) CB = gtk.ComboBox() self.Box_Main.pack_start(CB) self.showAntagonistic = gtk.CheckButton(_("Show antagonistic")) self.Box_Main.pack_start(self.showAntagonistic) #self.c_manager = CriterionManager() #self.Box_Main.pack_start(self.c_manager) self.show_all()
def loadState(self): """ TODO Use one sql query by queue (using parametized IN clause) and thread this self.memcursor.execute('''SELECT id, matbefore, matafter, name, date FROM main WHERE name IN (%s)''' % ','.join('?'*len(offset)), (offset,)) """ bdd = BDD() queues = settings.get_option('session/queues', None) if(queues is not None): for key in queues.iterkeys(): if type(key).__name__=='int': self.addQueue() self.addSelection(bdd.getTracksFromIDs(queues[key])) else: playlist = self.addQueue(key) for track_id in queues[key]: self.addSelection(bdd.getTracks({'track_ID':track_id})) playlist.Liste.connect("row-changed", playlist.setModified) else: self.addQueue()
def fill_model(self, garbageFromConnect=None, force_reload=False, mot='', e=None): ''' Remplit la liste arborescente avec les pistes de la BDD selon l'arborescence du mode séléctionné @param data = [TreeStore, mode] @param e = threading event pour prévenir qu'on a fini TODO : ajouter le ratio d'écoutes par conteneur, qui s'applique uniquement sur les pistes notées ratio = total_ecoutes_conteneur / nb_pistes_notees_conteneur ''' indices = {"title":2, "artist":4, "album":3, "genre":5, "rating":8, "year":9} global icon_size icon_size = settings.get_option('music/panel_icon_size', 32) def getValueOfLevel(track_line, level): ''' @param track_line : la ligne de la piste dans le tableau self.tracks[mode] @level : le niveau de profondeur dans le mode d'affichage ex de mode ('artist, 'album', 'title') level 0 = artist, level 2 = title, etc... ''' try: value = track_line[indices[mode[level]]] if indices[mode[level]] == 8: value = str(value) except IndexError: value = None return value def isSameContainer(track_line, niveau, cond): same = True for i in xrange(niveau+1): same = same and getValueOfLevel(track_line, i) == cond[i] return same def traiter_conteneur( niveau, ligne, selection, add_all=False, cond=[]): ''' Cette méthode crée une selection des pistes intéressantes Pourquoi une séléction complète avant d'ajouter quoique ce soit? Parcequ'il faut d'abord vérifier les noeuds supérieurs avant d'ajouter un noeud inférieur. Cela impliquerait une suppresion de noeud inférieur sous condition, ce qui est très mal senti par le TreeView et son modèle étant donné que le thread n'est pas celui de sa naissance. @param ligne : la ligne à laquelle la fonction commence (intérêt de la localité de ce paramètre = possibilité de multi-threading) @param selection : dictionnaire parent, chaque clé représente une ligne et est associée à un autre dictionnaire (sauf pour le dernier niveau) géré de la même manière ''' if(niveau == profondeur_max): #Si on est au dernier niveau du mode d'affichage, c'est que c'est une piste if(add_all or tracks[ligne][2].lower().find(mot) != -1): selection['children'][ligne] = {'props':{'count':tracks[ligne][7], 'rating':tracks[ligne][8], 'rated':int(tracks[ligne][8] != 0)} } #self.expand.append(ligne) #fils = model.append(pere, [icon_track, tracks[ligne][0], tracks[ligne][2], 1, 1]) #TreeView.expand_to_path(model.get_path(fils)) #La ligne est traitée en intégralité, on passe à la suivante : i = ligne + 1 else: #Il faut continuer de "creuser" et ajouter tous les fils de ce père elt = getValueOfLevel(tracks[ligne], niveau) cond = list(cond) cond.append(elt) #On ajoute le premier fils #fils = model.append(pere, [icon, 1, getValueOfLevel(tracks[ligne], niveau), 1, 1]) if(add_all == False and getValueOfLevel(tracks[ligne], niveau).lower().find(mot) != -1): add_all = True new = {'children':{}, 'props':{'count':0, 'rating':0, 'rated':0}} #Tant qu'il reste du monde et qu'on est toujours sur le même conteneur : #while(ligne < len(tracks) and elt == getValueOfLevel(tracks[ligne], niveau)): while(ligne < len(tracks) and isSameContainer(tracks[ligne], niveau, cond)): #Même valeur sur ce niveau, donc on descend d'un et on répète le schéma ligne = traiter_conteneur(niveau+1, ligne, new, add_all, cond) if(len(new['children']) > 0 or getValueOfLevel(tracks[ligne-1], niveau).lower().find(mot) != -1): #Si un père contient le mot ou a des fils selection['children'][ligne-1] = new if(add_all == False): self.expand[niveau].append(ligne-1) #selection[niveau] = {} #else: #del self.selection[niveau][-1] #if(len(sons[niveau]) > 0 or getValueOfLevel(tracks[ligne], niveau).find(mot) != -1): #pere = model.append(pere, [icon, 1, getValueOfLevel(tracks[ligne], niveau), 1, 1]) #for son in sons[niveau]: #fils = model.append(pere, [icon, 1, getValueOfLevel(tracks[ligne], niveau), 1, 1]) #On a pas traité en intégralité cette ligne donc on reste dessus : i = ligne try: #we add playcount to parent selection['props']['count'] += selection['children'][i-1]['props']['count'] selection['props']['rating'] += selection['children'][i-1]['props']['rating'] selection['props']['rated'] += selection['children'][i-1]['props']['rated'] except KeyError: pass return i #On a enfin fini de boucler le premier père accroché à la racine, on passe donc au suivant si il y en a : #EN FAIT NON, C'EST FOIREUX :D #if(getValueOfLevel(tracks[ligne], niveau-1) != elt_pere): #traiter_conteneur(None, 0, None) #cle = 0 #for c in mode: #cle += ord(c) #selection = [[], [], []] try: if(force_reload is True): self.tracks[self.mode] = self.BDD.loadTracks(self.mode) tracks = self.tracks[self.mode] else: tracks = self.tracks[self.mode] except KeyError: self.tracks[self.mode] = self.BDD.loadTracks(self.mode) tracks = self.tracks[self.mode] mode = eval(self.mode) profondeur_max = len(mode) - 1 self.expand = [] def getIcon(track_line, level): ''' @param track_line : la ligne de la piste dans le tableau self.tracks[mode] @level : le niveau de profondeur dans le mode d'affichage ex de mode ('artist, 'album', 'title') level 0 = artist, level 2 = title, etc... ''' try: path = os.path.join(xdg.get_thumbnail_dir(mode[level] + '/medium'), track_line[indices[mode[level]]].replace ('/', ' ') + '.jpg') icon = QtGui.QIImage(path).scaled(icon_size) except: icon = icons[mode[level]] return icon def ajouter_selection(pere, niveau, selection): #icon = icons[mode[niveau]] for ligne in selection['children'].iterkeys(): child = selection['children'][ligne] if(child['props']['rated'] == 0): burn = 0 else: burn = float(child['props']['count']) / float(child['props']['rated'] +1) #icon = getIcon(tracks[ligne], niveau) child_node = pere.append(LibraryItem(pere, None, tracks[ligne][0], getValueOfLevel(tracks[ligne], niveau), child['props']['count'], child['props']['rating'], burn, "%.2f" % burn, False, mode[niveau])) if(niveau < len(mode)-1): if ligne in self.expand[niveau]: print('expand : ' + str(ligne) + ' - ' + getValueOfLevel(tracks[ligne], niveau)) self.expand_paths.append(self.model.createIndex(child_node.row(), 0, child_node)) #self.TreeView.expand_row(self.model.get_path(fils), False) ajouter_selection(child_node, niveau+1, child) #if(niveau == 1): #child_node = pere.append(LibraryItem(None, 0, None, 0, 0, 0, None, True)) def expand(): for path in self.expand_paths: self.TreeView.expand(path) def traiter_tous_les_conteneurs(): #time.sleep(1) self.notLoading.wait() self.notLoading.clear() niveau = 0 ligne = 0 i = 0 while(ligne < len(tracks)): self.expand = [[], [], [], [], []] self.expand_paths = [] self.selection = {'children':{}, 'props':{'count':0, 'rating':0, 'rated':0}} ligne = traiter_conteneur(0, ligne, self.selection) self.model.beginInsertRows(QtCore.QModelIndex(), i, i+1) i+=1 ajouter_selection(self.model.rootItem, 0, self.selection) #glib.idle_add(ajouter_selection, None, 0, self.selection) self.model.endInsertRows() self.expandRequested.emit(self.expand_paths) #expand() #self.TreeView.expand_all() if(e != None): e.set() #On a fini donc on prévient les autres threads qui nous attendaient self.notLoading.set() self.model.reset() a = threading.Thread(target=traiter_tous_les_conteneurs) a.start()
from common import messager, settings, xdg from qt.util import treemodel from data.elements import Track from qt.gui import menus, modales import threading import time icon_track = QtGui.QPixmap('icons/track.png') icon_artist = QtGui.QPixmap('icons/artist.png') icon_album = QtGui.QPixmap('icons/album.png') icon_genre = QtGui.QPixmap('icons/genre.png') icon_year = QtGui.QPixmap('icons/year.png') icon_rating = QtGui.QPixmap('icons/star.png') icons = {"title":icon_track, "artist":icon_artist, "album":icon_album, "genre":icon_genre, "rating":icon_rating, "year":icon_year} icon_size = settings.get_option('music/panel_icon_size', 32) class BrowserPanel(QtGui.QTabWidget): def __init__(self, db, queueManager): QtGui.QTabWidget.__init__(self) self.addTab(LibraryPanel(db, queueManager), _('Library')) self.addTab(PlaylistBrowser(db, queueManager), _('Playlists')) self.resize(settings.get_option('music/paned_position', 200), 500) class LibraryPanel(QtGui.QWidget): """ TODO check errors (arkenstone, little richard) TODO réimplémenter mousePressEvent pour avoir l'image lors du drag """ expandRequested = QtCore.Signal(list)
def __init__(self, type, elementSelector): AbstractPanel.__init__(self, type) self.elementSelector = elementSelector #Ini panel catégories : container_ID, container_type, container_label, container_rating, container_icon self.model = gtk.TreeStore(int, str, str, int, gtk.gdk.Pixbuf, str, str) #messager.diffuser('liste_sections', self, [self.module, "category", self.model]) TreeView = ContainerBrowser(self.model) TreeView.set_headers_visible(False) self.treeViews = {'folder':TreeView, 'category':TreeView, 'universe':TreeView} modeCB = gtk.ComboBox() TreeView.connect("row-activated", self.onContainerActivated) TreeView.connect("drag-data-received", self.on_drag_data_receive) TreeView.connect("button-press-event", self.onContainerClicked) #Le TreeView sera la destination à toucher avec la souris TreeView.enable_model_drag_dest([('text/plain', 0, 0)], gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_MOVE) modeModel = gtk.ListStore(str, str) modeModel.append(["category", "Categories"]) modeModel.append(["universe", _("Universes")]) modeModel.append(["folder", _("Folders")]) cell = gtk.CellRendererText() modeCB.pack_start(cell) modeCB.add_attribute(cell, "text", 1) modeCB.set_model(modeModel) modeCB.set_active(0) modeCB.connect("changed", self.changer_mode) self.modeCB = modeCB messager.inscrire(self.reload_sections, "new_category") messager.inscrire(self.reload_sections, "new_universe") B_refresh = gtk.ToolButton(gtk.STOCK_REFRESH) B_refresh.connect('clicked', self.load) self.showAntagonistic = gtk.CheckButton(_("Show antagonistic")) self.showAntagonistic.set_active(settings.get_option(self.module + 's/show_antagonistic', False)) self.showAntagonistic.connect('toggled', self.toggleAntagonisitc) #On assemble tout graphiquement gtk.VBox.__init__(self) Box_mode = gtk.HBox() Box_mode.pack_start(self.showAntagonistic, False) Box_mode.pack_start(modeCB) Box_mode.pack_start(B_refresh, False) self.pack_start(Box_mode, False) SW = gtk.ScrolledWindow() SW.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) SW.add(TreeView) self.pack_start(SW) self.searchEntry = gtk.Entry() self.searchEntry.connect('activate', self.load) self.pack_start(self.searchEntry, False) self.set_size_request(300, -1) self.filters = {} self.load()
def __init__(self, moduleKey): QtGui.QWidget.__init__(self) self.fullScreen = False if(moduleKey == 'pictures'): self.module = 'picture' from qt.uc_sections.iconselector import ImageSelector from qt.uc_sections.pictures.imagewidget import SimpleImageWidget from qt.uc_sections.panel import UC_Panel, UC_Panes from qt.uc_sections.propertiespanel import PropertiesPanel mainLayout = QtGui.QVBoxLayout() layout = QtGui.QHBoxLayout() imageWidget = SimpleImageWidget() self.elementViewer = imageWidget self.elementSelector = ImageSelector(self) if(settings.get_option(self.module + 's/browser_mode', 'panel') == 'panes'): self.containerBrowser = UC_Panes(self.module, self.elementSelector) else: self.containerBrowser = UC_Panel(self.module, self.elementSelector) self.propertiesPanel = PropertiesPanel() layout.addWidget(self.containerBrowser, 0) layout.addWidget(imageWidget, 1) layout.addWidget(self.propertiesPanel, 0) mainLayout.addLayout(layout, 1) mainLayout.addWidget(self.elementSelector, 0) imageWidget.mouseDoubleClickEvent = self.toggleFullScreen imageWidget.keyPressEvent = self.onViewWidgetKeyPress if(moduleKey == 'videos'): self.module = 'video' from qt.uc_sections.iconselector import VideoSelector from qt.uc_sections.panel import UC_Panel backend = settings.get_option('videos/playback_lib', 'Phonon') from qt.uc_sections.videos.videoplayerwidget import VideoPlayerWidget if(backend == 'VLC'): from media import vlcplayer self.elementViewer = VideoPlayerWidget(vlcplayer.Player()) elif(backend == 'MPlayer'): from media import mplayers self.elementViewer = VideoPlayerWidget(mplayers.Player()) elif(backend == 'Phonon'): from media import phononplayer self.elementViewer = VideoPlayerWidget(phononplayer.Player()) else: from media import player self.elementViewer = VideoPlayerWidget(player.Player()) mainLayout = QtGui.QVBoxLayout() layout = QtGui.QHBoxLayout() self.elementSelector = VideoSelector(self) if(settings.get_option(self.module + 's/browser_mode', 'panel') == 'panes'): self.containerBrowser = UC_Panes(self.module, self.elementSelector) else: self.containerBrowser = UC_Panel(self.module, self.elementSelector) layout.addWidget(self.containerBrowser, 0) layout.addWidget(self.elementViewer, 1) mainLayout.addLayout(layout, 1) mainLayout.addWidget(self.elementSelector, 0) self.elementViewer.mouseDoubleClickEvent = self.toggleFullScreen self.setLayout(mainLayout) self.upLayout = layout
def __init__(self, moduleType, window): gtk.VBox.__init__(self) from uc_sections import iconselector from uc_sections.panel import UC_Panel, UC_Panes self.fullScreen = False if(moduleType == 'pictures'): self.module = 'picture' from uc_sections.pictures.image_widget import ImageWidget Box_UpperP = gtk.HBox() display = window.get_screen().get_display() imageWidget = ImageWidget(display) Box_ControlsP = gtk.HBox() self.elementSelector = iconselector.ImageSelector(imageWidget, Box_ControlsP) SW_IconsP = gtk.ScrolledWindow() SW_IconsP.set_size_request(-1, 170) SW_IconsP.add(self.elementSelector) #self._imagePanel = UC_Panel("image", self._imageSelector) if(settings.get_option(self.module + 's/browser_mode', 'panel') == 'panes'): self.containerBrowser = UC_Panes(self.module, self.elementSelector) else: self.containerBrowser = UC_Panel(self.module, self.elementSelector) Box_UpperP.pack_start(self.containerBrowser ,False) Box_UpperP.pack_end(imageWidget) self.pack_start(Box_UpperP) self.pack_start(SW_IconsP, False) self.pack_start(Box_ControlsP, False) self.show_all() imageWidget.connect("button-press-event", self.toggleFullScreen) self.DA_Parent = imageWidget.get_parent() elif(moduleType == 'videos'): self.module = 'video' backend = settings.get_option('videos/playback_lib', 'GStreamer') from uc_sections.videos.videoplayerwidget import VideoPlayerWidget if(backend == 'VLC'): from media import vlcplayer self.videoPlayerWidget = VideoPlayerWidget(vlcplayer.Player()) elif(backend == 'MPlayer'): from media import mplayers self.videoPlayerWidget = VideoPlayerWidget(mplayers.Player()) #Right_music_box.pack_start(self.player, False) else: from media import player self.videoPlayerWidget = VideoPlayerWidget(player.Player()) #ZoneVideo = self.interface.get_object("DA_Video") self.elementSelector = iconselector.VideoSelector(self.videoPlayerWidget) SW_IconsV = gtk.ScrolledWindow() SW_IconsV.set_size_request(-1, 170) SW_IconsV.add(self.elementSelector) if(settings.get_option(self.module + 's/browser_mode', 'panel') == 'panes'): self.containerBrowser = UC_Panes(self.module, self.elementSelector) else: self.containerBrowser = UC_Panel(self.module, self.elementSelector) #HPaned_Video = gtk.HPaned() #HPaned_Video.pack1(self.containerBrowser) #HPaned_Video.pack2(SW_IconsV) upperBox = gtk.HBox() upperBox.pack_start(self.containerBrowser ,False) upperBox.pack_end(self.videoPlayerWidget) self.pack_start(upperBox) self.pack_start(SW_IconsV, False) self.show_all() self.videoPlayerWidget.connect("button-press-event", self.toggleFullScreen) self.DA_Parent = self.videoPlayerWidget.get_parent()
def process(): bdd = BDD() account = settings.get_option("music/audioscrobbler_login", None) if account is not None: library = BDD.network.get_user("Maitre_Piccolo").get_library() query = "SELECT DISTINCT artist, album FROM tracks " filters = settings.get_option("music/filters", {}) params = [] for key in filters.iterkeys(): if filters[key]["enabled"]: try: where += " OR " except NameError: where = "WHERE " for t in filters[key]["criterions"]: try: filter += filters[key]["link"] + t[0] + t[1] + "? " except NameError: filter = t[0] + t[1] + "? " params.append(t[2]) where += "(" + filter + ")" del filter try: query += where except NameError: pass bdd.c.execute(query, params) couples = bdd.c.fetchall() length = float(len(couples)) nb_errors = 0 i = 0 P_Bar.set_fraction(i) for row in couples: try: tracks = library.get_tracks(row[0], row[1]) # if tracks empty check with only artist d = bdd.conn.cursor() for track in tracks: title = track.item.get_title() bdd.c.execute( "SELECT COUNT(title) FROM tracks WHERE artist = ? AND title = ? COLLATE NOCASE", (row[0], title), ) matchingTracksCount = bdd.c.fetchone()[0] if ( matchingTracksCount == 1 ): # We assume it's the good one (useful if the album is somthing like "Greatest Hits", etc...) t = (track.playcount, row[0], title) d.execute( "UPDATE tracks SET compteur = ? WHERE artist = ? AND title = ? COLLATE NOCASE", t ) elif matchingTracksCount > 1: # In doubt, we update only the ones with matching album t = (track.playcount, row[0], row[1], title) d.execute( "UPDATE tracks SET compteur = ? WHERE artist = ? AND album = ? AND title = ? COLLATE NOCASE", t, ) i += 1 P_Bar.set_fraction(float(i) / length) except WSError: logger.debug("Error with artist " + row[0] + " and album " + row[1]) nb_errors += 1 P_Bar.set_text(str(nb_errors) + " " + _("errors")) bdd.conn.commit() P_Bar.set_text(_("Sync ended with") + " " + str(nb_errors) + _("errors"))
def __init__(self, module, elementSelector): AbstractPanel.__init__(self, module) self.elementSelector = elementSelector #Ini panel dossiers self.folderModel = gtk.TreeStore(str, str, str, int, gtk.gdk.Pixbuf, str, str) TreeView = ContainerBrowser(self.folderModel, 'folder') #TreeView.set_headers_visible(False) #Ini panel catégories : container_ID, container_type, container_label, container_icon, background, foreground self.categoriesModel = gtk.TreeStore(int, str, str, int, gtk.gdk.Pixbuf, str, str) self.universesModel = gtk.TreeStore(int, str, str, int, gtk.gdk.Pixbuf, str, str) TV_universes = ContainerBrowser(self.universesModel, 'universe') TV_categories = ContainerBrowser(self.categoriesModel, 'category') self.treeViews = {'universe':TV_universes, 'category':TV_categories, 'folder':TreeView} modeCB = gtk.ComboBox() tvLayout = gtk.HBox() for key in ('folder', 'category', 'universe'): tv = self.treeViews[key] if key != 'folder': tv.connect("drag-data-received", self.on_drag_data_receive) tv.connect("button-press-event", self.onContainerClicked) tv.enable_model_drag_dest([('text/plain', 0, 0)],gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_MOVE) else: tv.connect("button-press-event", self.on_folder_click) tv.connect("row-activated", self.onContainerActivated) SW = gtk.ScrolledWindow() SW.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) SW.add(tv) tvLayout.pack_start(SW) # DEPRECATED #self.columns = {} #self.columns["universe"] = col #self.columns["category"] = col messager.inscrire(self.reload_sections, "new_category") messager.inscrire(self.reload_sections, "new_universe") B_refresh = gtk.ToolButton(gtk.STOCK_REFRESH) B_refresh.connect('clicked', self.load) modeModel = gtk.ListStore(str, str) modeModel.append([None, _('None')]) modeModel.append(["category", _("Categories")]) modeModel.append(["universe", _("Universes")]) modeModel.append(["folder", _("Folders")]) cell = gtk.CellRendererText() modeCB.pack_start(cell) modeCB.add_attribute(cell, "text", 1) modeCB.set_model(modeModel) modeCB.set_active(0) modeCB.connect("changed", self.filteringTreeViewChanged) self.filterLabel = gtk.Label(_('No active filters')) #On assemble tout graphiquement gtk.VBox.__init__(self) BB = gtk.HBox() BB.pack_start(B_refresh, False) BB.pack_start(modeCB, False) BB.pack_start(self.filterLabel, True) self.pack_start(BB, False) self.searchEntry = gtk.Entry() self.searchEntry.connect('activate', self.load) self.pack_start(tvLayout) self.pack_start(self.searchEntry, False) self.set_size_request(700, -1) self.toggled = {'category': False, 'universe': False, 'folder':False} self.filters = {} filterIndex = settings.get_option(self.module + 's/container_filter', 0) if filterIndex != 0: modeCB.set_active(filterIndex) # trigger filteringTreeViewChanged() and thus load else: self.load()
from operator import attrgetter from common import settings, util, xdg from data.elements import Container from data.bdd import BDD from PySide import QtGui, QtCore from qt.util import treemodel from abstract.ucpanel import UCPanelInterface logger = logging.getLogger(__name__) icon_size = settings.get_option('pictures/panel_icon_size', 64) class AbstractPanel(UCPanelInterface, QtGui.QWidget): expandRequested = QtCore.Signal(str, list) def __init__(self, moduleType): UCPanelInterface.__init__(self, moduleType) QtGui.QWidget.__init__(self) self.expandRequested.connect(self.expandNodes) def addRating(self, node, rating): node.container.rating += rating def append(self, model, container, parentNode=None, backgroundColor='white'):
def __init__(self, parent=None): QtGui.QMainWindow.__init__(self, parent) #print os.is_file(QtGui.QIcon.themeSearchPaths()[-1]) if not QtGui.QIcon.hasThemeIcon("document-open"): import fallbackicons QtGui.QIcon.setThemeName('oxygen') self.move(settings.get_option('gui/window_x', 50), settings.get_option('gui/window_y', 50)) self.resize(settings.get_option('gui/window_width', 700), settings.get_option('gui/window_height', 500)) if(settings.get_option('gui/maximized', False)): self.maximized = True self.showMaximized() else: self.maximized = False self.setFont(QtGui.QFont("Verdana")) self.setWindowTitle("Bullseye") try: self.setWindowIcon(QtGui.QIcon("icons/bullseye.png")) except:pass self.NB_Main = QtGui.QTabWidget(self) self.NB_Main.setTabPosition(QtGui.QTabWidget.West) from data.bdd import MainBDD self.BDD = MainBDD() self.loadedModules = [] self.managers = {} # Managers are the big widget representing a module if(settings.get_option('music/preload', False)): self.loadMusic() else: button = QtGui.QPushButton('load') button.clicked.connect(self.loadMusic) self.NB_Main.addTab(button, _('Music')) if(settings.get_option('pictures/preload', False)): self.loadModule('pictures', True) else: button = QtGui.QPushButton('load') button.clicked.connect(lambda: self.loadModule('pictures')) self.NB_Main.addTab(button, _('Pictures')) if(settings.get_option('videos/preload', False)): self.loadSection('videos', True) else: button = QtGui.QPushButton('load') button.clicked.connect(lambda: self.loadModule('videos')) self.NB_Main.addTab(button, _('Videos')) from qt.gui.menubar import MenuBar, StatusBar #layout.addWidget(MenuBar()) #layout.addWidget(self.NB_Main) #self.setLayout(layout) self.statusBar = StatusBar() self.setMenuBar(MenuBar(self)) self.setCentralWidget(self.NB_Main) self.setStatusBar(self.statusBar) self.NB_Main.currentChanged.connect(self.onModuleChanged) self.ready.connect(self.onReady) @util.threaded def emitReady(): import time time.sleep(0.5) self.ready.emit() emitReady()
def __init__(self, manager, label): QtGui.QTableView.__init__(self) self.starDelegate = StarDelegate() # Trick to prevent garbage collector issue #self.setItemDelegate(self.delegate) # The right way, but style option doesn't get initialized correctly causing no alternate colors for rows self.setItemDelegateForColumn(6, self.starDelegate) self.setEditTriggers(QtGui.QAbstractItemView.DoubleClicked | QtGui.QAbstractItemView.SelectedClicked) # Visual tweaks self.setAlternatingRowColors(True) #self.setStyleSheet("{ border: none;}") self.setShowGrid(False) self.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) self.verticalHeader().hide() self.setSortingEnabled(True) self.setDragDropMode(QtGui.QAbstractItemView.DragDrop) self.setDragEnabled(True) self.setAcceptDrops(True) # *** Data attributes *** self.modified = False # pour les playlists enregistrées self.manager = manager #police, icon_playing, icon_stopping, ID, path, titre, album, artiste, length, count, pixbuf_note, note, bridge_src key self.model = QueueModel() filterModel = QtGui.QSortFilterProxyModel() filterModel.setSourceModel(self.model) self.filterModel = filterModel self.setModel(self.filterModel) header = self.horizontalHeader() # Give the visual index for each logical index self.columnsPos = settings.get_option('music/columns_order', [0, 1, 2, 3, 4, 5, 6]) logical = 0 while logical < 7: current = header.visualIndex(logical) if current != self.columnsPos[logical]: header.moveSection(current, self.columnsPos[logical]) self.columnsPos[logical] = current logical += 1 #self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) #self.customContextMenuRequested.connect(self.showContextMenu) # Column tweaks - need to be done after model is setted self.setColumnWidth(1, settings.get_option('music/col_artist_width', 50)) self.setColumnWidth(2, settings.get_option('music/col_album_width', 50)) header = self.horizontalHeader() header.setMovable(True) header.sectionMoved.connect(self.columnMoved) #header.setStretchLastSection(True) #self.horizontalHeader().setResizeMode(QtGui.QHeaderView.ResizeToContents) header.setResizeMode(0, QtGui.QHeaderView.ResizeToContents) header.setResizeMode(1, QtGui.QHeaderView.Stretch) header.setResizeMode(2, QtGui.QHeaderView.Stretch) header.setResizeMode(3, QtGui.QHeaderView.Stretch) header.setResizeMode(6, QtGui.QHeaderView.Fixed) self.activated.connect(self.onActivated) self.model.rowsMoved.connect(self.onReorder)
def initialiser_composants(self): self.widgets = {} # Général Box_General = gtk.VBox() #self.CB_gui_framework = gtk.combo_box_new_text() #libs = {'Gtk 2':0, 'Qt 4':1} #self.CB_gui_framework.append_text('Gtk 2') #self.CB_gui_framework.append_text('Qt 4') self.picture_enabled = gtk.CheckButton(_('Enable pictures manager')) self.picture_enabled.set_active(settings.get_option('pictures/enabled', False)) self.video_enabled = gtk.CheckButton(_('Enable videos manager')) self.video_enabled.set_active(settings.get_option('videos/enabled', False)) # Option : Cacher les menus de la barre d'outils en fonction de la section #Box_General.pack_start(self.CB_gui_framework) Box_General.pack_start(self.picture_enabled) Box_General.pack_start(self.video_enabled) self.Box_Main.pack_start(Box_General) self.widgets['general'] = Box_General # --- Folders section --- Box_folders = gtk.VBox() TV_folders = gtk.TreeView() self.folders = gtk.ListStore(str, bool) cell = gtk.CellRendererText() Col_Label = gtk.TreeViewColumn(_('Folders'), cell, text=0) cell_toggle = gtk.CellRendererToggle() Col_Recursive = gtk.TreeViewColumn(_('Dig'), cell_toggle, active=1) cell_toggle.connect('toggled', self.toggle_recursive_folder) TV_folders.append_column(Col_Label) TV_folders.append_column(Col_Recursive) TV_folders.set_model(self.folders) for folder in settings.get_option('music/folders', []): self.folders.append([folder[0], folder[1]]) def add_folder(*args): dialog = gtk.FileChooserDialog(action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, buttons=(gtk.STOCK_OPEN, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)) dialog.set_current_folder_uri('~') dialog.run() fichier = dialog.get_filename() dialog.destroy() self.folders.append([fichier, False]) def remove_folder(*args): try: model, iter = TV_folders.get_selection().get_selected() model.remove(iter) except TypeError: warning = gtk.MessageDialog(self, 0, gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, message_format=_('You must select a folder before clicking the remove button')) warning.run() warning.destroy() B_add_folder = gtk.Button(_('Add'), gtk.STOCK_ADD) B_add_folder.connect('clicked', add_folder) B_remove_folder = gtk.Button(_('Remove'), gtk.STOCK_REMOVE) B_remove_folder.connect('clicked', remove_folder) Box_folders.pack_start(TV_folders) Box = gtk.HBox() Box.pack_start(B_add_folder) Box.pack_start(B_remove_folder) Box_folders.pack_start(Box, False) self.Box_Main.pack_start(Box_folders) self.widgets['folders'] = Box_folders # ******* Music section ********* Box_music = gtk.Table(2,2) i = 0 Box_music.attach(gtk.Label(_('Playback library') + ' :'), 0, 1, i, i+1, gtk.FILL|gtk.EXPAND, gtk.FILL) self.CB_music_playback_lib = gtk.combo_box_new_text() libs = {'GStreamer':0, 'MPlayer':1, 'VLC':2} self.CB_music_playback_lib.append_text('GStreamer') self.CB_music_playback_lib.append_text('MPlayer') self.CB_music_playback_lib.append_text('VLC') try: self.CB_music_playback_lib.set_active(libs[settings.get_option('music/playback_lib', 'GStreamer')]) except KeyError: self.CB_music_playback_lib.set_active(libs['GStreamer']) Box_music.attach(self.CB_music_playback_lib, 1, 2, i, i+1, gtk.FILL, gtk.FILL) i += 1 Box_music.attach(gtk.Label(_('Panel icon size') + ' :'), 0, 1, i, i+1, gtk.FILL, gtk.FILL) self.CB_icon_size_panel_music = gtk.combo_box_new_text() self.CB_icon_size_panel_music.append_text('16') self.CB_icon_size_panel_music.append_text('24') self.CB_icon_size_panel_music.append_text('32') self.CB_icon_size_panel_music.append_text('48') self.CB_icon_size_panel_music.append_text('64') self.CB_icon_size_panel_music.set_active(settings.get_option('music/panel_icon_size', 32) / 16) Box_music.attach(self.CB_icon_size_panel_music, 1, 2, i, i+1, gtk.FILL|gtk.EXPAND, gtk.FILL) i+= 1 self.usePerformerTag = gtk.CheckButton(_('Show performer instead of artist in library browser')) self.usePerformerTag.set_active(settings.get_option('music/use_performer', False)) Box_music.attach(self.usePerformerTag, 0, 2, i, i+1, gtk.FILL, gtk.FILL) self.Box_Main.pack_start(Box_music) self.widgets['music'] = Box_music self.Box_mfilters = FilterManager(settings.get_option('music/filters', {})) self.Box_Main.pack_start(self.Box_mfilters) self.widgets['music_filters'] = self.Box_mfilters # Audioscrobbler section Box_audioscrobbler = gtk.Table(2, 2) Box_audioscrobbler.attach(gtk.Label(_('Login') + ' : '), 0, 1, 0, 1, gtk.FILL, gtk.FILL) self.audioscrobbler_login = gtk.Entry() self.audioscrobbler_login.set_text(settings.get_option('music/audioscrobbler_login', '')) Box_audioscrobbler.attach(self.audioscrobbler_login, 1, 2, 0, 1, gtk.FILL|gtk.EXPAND, gtk.FILL) Box_audioscrobbler.attach(gtk.Label(_('Password') + ' : '), 0, 1, 1, 2, gtk.FILL, gtk.FILL) self.audioscrobbler_password = gtk.Entry() self.audioscrobbler_password.set_text(settings.get_option('music/audioscrobbler_password', '')) Box_audioscrobbler.attach(self.audioscrobbler_password, 1, 2, 1, 2, gtk.FILL|gtk.EXPAND, gtk.FILL) self.Box_Main.pack_start(Box_audioscrobbler) self.widgets['audioscrobbler'] = Box_audioscrobbler # Pictures section Box_pictures = gtk.Table(2,2) i = 0 self.picture_preload = gtk.CheckButton(_('Preload pictures manager')) self.picture_preload.set_active(settings.get_option('pictures/preload', False)) self.picture_preload.set_tooltip_text(_('If true, will be preloaded before application start, else will be loaded on demand (slightly faster startup)')) Box_pictures.attach(self.picture_preload, 0, 2, i, i+1, gtk.FILL, gtk.FILL) i += 1 Box_pictures.attach(gtk.Label(_('Panel thumbnail size') + ' : '), 0, 1, i, i+1, gtk.FILL, gtk.FILL) self.CB_icon_size_panel_pictures = gtk.combo_box_new_text() self.CB_icon_size_panel_pictures.append_text('16') self.CB_icon_size_panel_pictures.append_text('24') self.CB_icon_size_panel_pictures.append_text('32') self.CB_icon_size_panel_pictures.append_text('48') self.CB_icon_size_panel_pictures.append_text('64') self.CB_icon_size_panel_pictures.set_active(settings.get_option('pictures/panel_icon_size', 32) /16) Box_pictures.attach(self.CB_icon_size_panel_pictures, 1, 2, i, i+1, gtk.FILL|gtk.EXPAND, gtk.FILL) self.Box_Main.pack_start(Box_pictures) self.widgets['pictures'] = Box_pictures #Videos section #Box_pictures = gtk.Table(2,2) #i = 0 #self.picture_preload = gtk.CheckButton(_('Preload pictures manager')) #self.picture_preload.set_active(settings.get_option('pictures/preload', False)) #self.picture_preload.set_tooltip_text(_('If true, will be preloaded before application start, else will be loaded on demand (slightly faster startup)')) #Box_pictures.attach(self.picture_preload, 0, 2, i, i+1) #i += 1 #Box_pictures.attach(gtk.Label(_('Panel thumbnail size')), 0, 1, i, i+1) #self.CB_icon_size_panel_pictures = gtk.combo_box_new_text() #self.CB_icon_size_panel_pictures.append_text('16') #self.CB_icon_size_panel_pictures.append_text('24') #self.CB_icon_size_panel_pictures.append_text('32') #self.CB_icon_size_panel_pictures.append_text('48') #self.CB_icon_size_panel_pictures.append_text('64') #self.CB_icon_size_panel_pictures.set_active(settings.get_option('pictures/panel_icon_size', 32) /16) #Box_pictures.attach(self.CB_icon_size_panel_pictures, 1, 2, i, i+1) #self.Box_Main.pack_start(Box_pictures) #self.widgets['pictures'] = Box_pictures self.createUCBox('videos') i = 3 self.widgets['videos'].attach(gtk.Label(_('Playback library') + ' :'), 0, 1, i, i+1, gtk.FILL, gtk.FILL) self.CB_video_playback_lib = gtk.combo_box_new_text() libs = {'GStreamer':0, 'MPlayer':1, 'VLC':2} self.CB_video_playback_lib.append_text('GStreamer') self.CB_video_playback_lib.append_text('MPlayer') self.CB_video_playback_lib.append_text('VLC') try: self.CB_video_playback_lib.set_active(libs[settings.get_option('videos/playback_lib', 'GStreamer')]) except KeyError: self.CB_video_playback_lib.set_active(libs['GStreamer']) self.widgets['videos'].attach(self.CB_video_playback_lib, 1, 2, i, i+1, gtk.FILL, gtk.FILL)
def __init__(self, db, queueManager): QtGui.QTabWidget.__init__(self) self.addTab(LibraryPanel(db, queueManager), _('Library')) self.addTab(PlaylistBrowser(db, queueManager), _('Playlists')) self.resize(settings.get_option('music/paned_position', 200), 500)
def __init__(self, module, elementSelector): AbstractPanel.__init__(self, module) self.module = module self.elementSelector = elementSelector # --- TreeView work --- self.categoriesModel = UCModel() self.universesModel = UCModel() self.folderModel = UCModel() self.treeViews = { 'folder': ContainerBrowser(self.folderModel, 'folder'), 'category': ContainerBrowser(self.categoriesModel, 'category'), 'universe': ContainerBrowser(self.universesModel, 'universe') } tvLayout = QtGui.QHBoxLayout() for key in ('folder', 'category', 'universe'): tv = self.treeViews[key] if key != 'folder': tv.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) tv.customContextMenuRequested.connect(self.showContextMenu) tv.activated.connect(self.onContainerActivated) tv.clicked.connect(self.onContainerClicked) tvLayout.addWidget(tv) self.refreshStyle.connect(self.refreshView) # --- Other work --- self.modesCB = QtGui.QComboBox() modesModel = QtGui.QStandardItemModel() modesModel.appendRow([QtGui.QStandardItem(None), QtGui.QStandardItem(_("None"))]) modesModel.appendRow([QtGui.QStandardItem('category'), QtGui.QStandardItem(_("Categories"))]) modesModel.appendRow([QtGui.QStandardItem('universe'), QtGui.QStandardItem(_("Universes"))]) modesModel.appendRow([QtGui.QStandardItem('folder'), QtGui.QStandardItem(_("Folders"))]) self.modesCB.setModel(modesModel) self.modesCB.setModelColumn(1) self.modesCB.currentIndexChanged[int].connect(self.filteringTreeViewChanged) self.filterLabel = QtGui.QLabel(_('No active filters')) self.searchEntry = QtGui.QLineEdit() self.searchEntry.returnPressed.connect(self.load) # --- On assemble tout graphiquement --- mainLayout = QtGui.QVBoxLayout() buttonBar = QtGui.QToolBar() buttonBar.addAction(QtGui.QIcon.fromTheme('view-refresh'), None, self.load) buttonBar.addWidget(self.modesCB) buttonBar.addSeparator() buttonBar.addWidget(self.filterLabel) mainLayout.addWidget(buttonBar, 0) mainLayout.addLayout(tvLayout, 1) mainLayout.addWidget(self.searchEntry, 0) self.setLayout(mainLayout) self.toggled = {'category': False, 'universe': False, 'folder':False} filterIndex = settings.get_option(self.module + 's/container_filter', 0) if filterIndex != 0: self.modesCB.setCurrentIndex(filterIndex) self.filteringTreeViewChanged(filterIndex) else: self.load()
def __init__(self, BDD, queueManager): QtGui.QWidget.__init__(self) self.BDD = BDD self.queueManager = queueManager self.tracks = {} self.mode = '("artist", "album", "title")' self.TreeView = QtGui.QTreeView() self.TreeView.setExpandsOnDoubleClick(False) self.TreeView.setSortingEnabled(True) self.TreeView.mouseReleaseEvent = self.mouseReleaseEvent self.model = LibraryModel() self.notLoading = threading.Event() self.notLoading.set() self.fill_model() #TreeNode(self.model, None, LibraryItem(None, 1, "ok", 1, 1, 1, 1, False)) #self.model.append(LibraryItem(None, 1, "ok", 1, 1, 1, 1, False)) self.TreeView.setModel(self.model) self.TreeView.activated.connect(self.enqueue) self.expandRequested.connect(self.expandIndexes) self.TreeView.setDragEnabled(True) self.TreeView.setAcceptDrops(True) self.TreeView.setDragDropMode(QtGui.QAbstractItemView.InternalMove) # *** TreeView visual tweaks self.TreeView.setColumnWidth(1, settings.get_option('music/col_label_panel_width', 170)) header = self.TreeView.header() header.setStretchLastSection(False) header.setDefaultSectionSize(60) header.setResizeMode(0, QtGui.QHeaderView.ResizeToContents) header.setResizeMode(1, QtGui.QHeaderView.Stretch) header.setResizeMode(2, QtGui.QHeaderView.Fixed) header.setResizeMode(3, QtGui.QHeaderView.Fixed) header.setResizeMode(4, QtGui.QHeaderView.Fixed) self.TreeView.setAnimated(True) # --- Mode selector --- modesModel = QtGui.QStandardItemModel() modesModel.appendRow([QtGui.QStandardItem('("artist", "album", "title")'), QtGui.QStandardItem(_("Artist"))]) modesModel.appendRow([QtGui.QStandardItem('("album", "title")'), QtGui.QStandardItem(_("Album"))]) modesModel.appendRow([QtGui.QStandardItem('("rating", "title")'), QtGui.QStandardItem(_("Rating"))]) modesModel.appendRow([QtGui.QStandardItem('("genre", "album", "title")'), QtGui.QStandardItem(_("Genre"))]) modesModel.appendRow([QtGui.QStandardItem('("year", "artist", "album", "title")'), QtGui.QStandardItem(_("Year - Genre"))]) modesModel.appendRow([QtGui.QStandardItem('("year", "genre", "artist", "album", "title")'), QtGui.QStandardItem(_("Year"))]) modesModel.appendRow([QtGui.QStandardItem('("rating", "year", "genre", "artist", "album", "title")'), QtGui.QStandardItem(_("Rating - Year - Genre"))]) self.modeCB = QtGui.QComboBox() self.modeCB.setModel(modesModel) self.modeCB.setModelColumn(1) self.modeCB.currentIndexChanged[int].connect(self.changeMode) refreshButton = QtGui.QPushButton(QtGui.QIcon.fromTheme('view-refresh'), _('Refresh')) refreshButton.clicked.connect(lambda: self.fill_model(None, True)) modLayout = QtGui.QHBoxLayout() modLayout.addWidget(self.modeCB, 1) modLayout.addWidget(refreshButton) searchLine = QtGui.QLineEdit() searchLine.returnPressed.connect(lambda: self.searchFor(searchLine)) layout = QtGui.QVBoxLayout() layout.addLayout(modLayout) layout.addWidget(self.TreeView) layout.addWidget(searchLine, 1) #self.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)) self.setLayout(layout)
def check_for_new_files(self, progressWidget, folders=None): """ Méthode principale pour remplir la base - Est executée dans un thread secondaire @param dossier : le dossier père qui sera scanné @param progressWidget : la barre de progrès pour informer de l'état d'avancement du scan TODO walk + list (see Bluemindo) TODO use trigger to check existence - not needed with current process TODO PERF trick : essayer de checker l'existence avec un trigger mais sans récupérer les tags TODO prompter les fichiers mal nommés """ if folders is None: folders = settings.get_option("music/folders", []) # Redéfinition d'une connexion puisque cette fonction tourne dans un thread secondaire : conn = sqlite3.connect(os.path.join(xdg.get_data_home(), "data.db")) conn.row_factory = sqlite3.Row c = conn.cursor() recovered_paths = [] error_paths = [] def add_files(files): """ Ajoute des nouveaux fichiers à la BDD @param files : liste de tuples(type, dossier, fichier, extension) @param progressWidget : barre de progrès représentant l'avancement """ registered_paths = [] c.execute("SELECT path FROM tracks") for row in c: registered_paths.append(row[0]) c.execute("SELECT folder, filename, folder FROM pictures") for row in c: registered_paths.append(row[0] + os.sep + row[1]) c.execute("SELECT folder, filename, folder FROM videos") for row in c: registered_paths.append(row[0] + os.sep + row[1]) new_paths = list(set(recovered_paths) - set(registered_paths)) new_files = {"music": [], "picture": [], "video": []} # *** REQUETE PARAMETREE AVEC CLAUSE IN -> for row in conn.execute('SELECT path FROM tracks WHERE path IN (%s)' % ("?," * len(tracks_path))[:-1], tracks_path): longueur = float(len(files["music_files"])) progressWidget.setFraction(0) i = 0 for track in files["music_files"]: path = track[0] + os.sep + track[1] if path in new_paths: new_files["music"].append(get_track_data(path, track[2])) i += 1 progressWidget.setFraction((float(i) / longueur)) longueur = float(len(files["picture_files"])) progressWidget.setFraction(0) i = 0 for element in files["picture_files"]: path = element[0] + os.sep + element[1] if path in new_paths: new_files["picture"].append(get_UC_element_data("picture", element[0], element[1])) i += 1 progressWidget.setFraction((float(i) / longueur)) longueur = float(len(files["video_files"])) progressWidget.setFraction(0) i = 0 for element in files["video_files"]: path = element[0] + os.sep + element[1] if path in new_paths: new_files["video"].append(get_UC_element_data("video", element[0], element[1])) i += 1 progressWidget.setFraction((float(i) / longueur)) for section in new_files.iterkeys(): if section == "music": conn.executemany( "INSERT INTO tracks (path, title, album, artist, genre, length, rating, playcount, year, performer) VALUES (?,?,?,?,?, ?, ?, ?, ?, ?)", new_files[section], ) else: conn.executemany( "INSERT INTO " + section + "s (folder, filename, rating, categorie_ID, univers_ID, size) VALUES (?, ?, ?, ?, ?, ?)", new_files[section], ) progressWidget.setFraction(0) conn.commit() def get_UC_element_data(type, dossier, fichier): t = (unicode(dossier), unicode(fichier), 0, 1, 1, os.path.getsize(os.path.join(dossier, fichier))) return t def get_track_data(fichier, extension): tags = Tags.fromPath(fichier) fichier = unicode(fichier) t = ( fichier, tags["title"], tags["album"], tags["artist"], tags["genre"], tags["length"], 0, 0, tags["year"], tags["performer"], ) # conn.execute('INSERT INTO tracks (path, title, album, artist, genre, length, note, compteur, year) VALUES (?,?,?,?,?, ?, ?, ?, ?)', t) return t def scanner_dossier(dossier, dig=False, files={"music_files": [], "picture_files": [], "video_files": []}): """ Scanne récursivement un dossier et ses sous-dossiers pour repérer les fichiers intéressants @param dossier : le dossier qui sera scanné @param files : un dictionnaire contenant des listes de tuples contenant les infos des nouveaux fichiers """ def add_new_CU(type, dossier, fichier, extension): try: t = (unicode(dossier), unicode(fichier)) c.execute("SELECT COUNT(" + type + "_ID) FROM " + type + "s WHERE folder = ? AND filename = ?", t) if c.fetchone()[0] == 0: # Si le fichier n'est pas déjà dans la base files.append((type, dossier, fichier, extension)) except UnicodeDecodeError: logger.debug("Fichier avec nom foireux : " + dossier + fichier) def check_interest(dossier, fichier, extension): if extension == ".mp3" or extension == ".ogg": try: t = (unicode(dossier + os.sep + fichier),) # c.execute('SELECT COUNT(track_ID) FROM tracks WHERE path = ?', t) # if(c.fetchone()[0] == 0): #Si le fichier n'est pas déjà dans la base files["music_files"].append((dossier, fichier, extension)) recovered_paths.append(unicode(dossier + os.sep + fichier)) except UnicodeDecodeError: error_paths.append(dossier + os.sep + fichier) elif extension == ".flv" or extension == ".mkv" or extension == ".avi": try: files["video_files"].append((dossier, fichier)) recovered_paths.append(unicode(dossier + os.sep + fichier)) except UnicodeDecodeError: error_paths.append(dossier + os.sep + fichier) elif extension in (".jpg", ".gif", ".png", ".bmp"): try: if dossier != "thumbnails/images": # *** A COMPLETER *** files["picture_files"].append((dossier, fichier)) recovered_paths.append(unicode(dossier + os.sep + fichier)) except UnicodeDecodeError: error_paths.append(dossier + os.sep + fichier) # elif extension == '.pdf': # add_new_CU('document', dossier, fichier, extension) progressWidget.pulse() for f in os.listdir(dossier): if f[0] != ".": if os.path.isfile(os.path.join(dossier, f)): (shortname, extension) = os.path.splitext(f) check_interest(dossier, f, extension) else: if dig: scanner_dossier(dossier + os.sep + f, files) return files for folder in folders: new_files = scanner_dossier(folder[0], folder[1]) add_files(new_files) for path in error_paths: logging.debug("Chemin foireux : " + path) progressWidget.emitDone()