clWidgets.py

00001 #!/usr/bin/env python
00002 # -*- coding: utf-8 -*-
00003 
00004 # ----------------------------------------------------------------------------
00005 # pyjama - python jamendo audioplayer
00006 # Copyright (c) 2008 Daniel Nögel
00007 #
00008 # This program is free software: you can redistribute it and/or modify
00009 # it under the terms of the GNU General Public License as published by
00010 # the Free Software Foundation, either version 3 of the License, or
00011 # (at your option) any later version.
00012 #
00013 # This program is distributed in the hope that it will be useful,
00014 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 # GNU General Public License for more details.
00017 # You should have received a copy of the GNU General Public License
00018 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
00019 # ----------------------------------------------------------------------------
00020 
00021 
00022 ## @package clWidgets
00023 # This module holds a lot of widgets
00024 # which which are used more often.
00025 
00026 
00027 # GUI
00028 import pygtk
00029 pygtk.require('2.0')
00030 import gtk
00031 import gobject
00032 
00033 # Time formatting
00034 from time import gmtime, time, sleep
00035 
00036 # math
00037 from math import ceil
00038 import copy
00039 import os
00040 
00041 import urllib
00042 
00043 # Benutzerklassen
00044 import functions
00045 
00046 from threading import Thread
00047 
00048 # Gettext - Übersetzung
00049 functions.translation_gettext()
00050 #def _(string):
00051 #    return string
00052 
00053 ## shows an error when user makes to much jamendo queries
00054 def tofast(window):
00055     dia = MyDialog(_('to fast'),
00056                               window.get_toplevel(),
00057                               gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, 
00058                                 (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT),        gtk.STOCK_DIALOG_WARNING, _('Some requests may only be send once a second\nin order not to slow down jamendo\'s database'))
00059     dia.run()
00060     dia.destroy()
00061     window.toolbar.on_bHistoryBack_clicked(None)
00062 
00063 ## removes some special characters from strings to be shown 
00064 # in albumwidgets
00065 def clear(string):
00066     if string == None: return string
00067     string = string.replace("\r", "")
00068     string = string.replace("\t", "")
00069     string = string.replace(",", "")
00070     string = string.replace("&", "&amp;")
00071 #    string = string.replace("«", "")
00072 #    string = string.replace("»", "")
00073 #    string = functions.decode_htmlentities(string)
00074     return string.strip()
00075     
00076 def threaded(f):
00077     def wrapper(*args, **kwargs):
00078         t = Thread(target=f, args=args, kwargs=kwargs)
00079         t.start()
00080     return wrapper
00081 #~ @threaded
00082 #~ class PulsingBar(gtk.ProgressBar):
00083     #~ def __init__(self):
00084         #~ self.__pulsing = False
00085         #~ 
00086         #~ gtk.ProgressBar.__init__(self)
00087 #~ 
00088     #~ @threaded
00089     #~ def pulsing(self):
00090         #~ gtk.gdk.threads_enter()
00091         #~ self.pulse()
00092         #~ while gtk.events_pending(): gtk.main_iteration()
00093         #~ gtk.gdk.threads_leave()
00094         #~ return self.__pulsing
00095         #~ 
00096     #~ @threaded
00097     #~ def start(self):
00098         #~ self.__pulsing = True
00099         #~ gobject.timeout_add(10, self.pulsing)
00100 #~ 
00101     #~ @threaded
00102     #~ def stop(self):
00103         #~ self.__pulsing = False
00104 
00105     
00106 
00107 class InfoLabel(gtk.HBox):
00108     def __init__(self, pyjama):
00109         self.pyjama = pyjama
00110         self.markuplbCaption = "<span size=\"medium\">TEXT</span>"
00111 
00112         gtk.HBox.__init__(self, False)
00113 
00114         self.icon_size = self.pyjama.settings.get_value("PYJAMA", "info_label_icon_size", 24)
00115 
00116         self.lbl = gtk.Label()
00117         self.lbl.show()
00118 
00119         self.img = gtk.Image()
00120         self.img.show()
00121 
00122         self.pack_start(self.img, False, True)
00123         self.pack_start(self.lbl, True, True)
00124 
00125         size = gtk.icon_size_register("usersize1", self.icon_size, self.icon_size)
00126 
00127     def set_text(self, text):
00128 #        self.pyjama.window.f.set_label(text)
00129         self.lbl.set_markup(self.markuplbCaption.replace("TEXT", text))
00130 
00131     def set_image(self, image=None, size=None):
00132         if image == None:
00133             self.img.clear()
00134             return
00135 
00136         if size is None:
00137             size = gtk.icon_size_from_name("usersize1")
00138 
00139         if image in gtk.stock_list_ids():
00140             self.img.set_from_stock(image, size)
00141             return
00142 
00143         if not os.path.exists(image):
00144             # try to find the image in pyjama's
00145             # image folder:
00146             if not os.path.exists(os.path.join(functions.install_dir(), "images", image)):
00147                 print ("Could not find '%s'" % image)
00148                 return -1
00149             else:
00150                 image = os.path.join(functions.install_dir(), "images", image)
00151 
00152         try:
00153             pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(image, self.icon_size, self.icon_size)
00154             self.img.set_from_pixbuf(pixbuf)
00155         except ValueError:
00156             print ("Error loading the image")
00157             return -2
00158 
00159 ## Context menu for TreeViewList
00160 # When creating a ListMenu the event
00161 # 'populate_listmenu' will be raised
00162 class ListMenu(gtk.Menu):
00163     ## The Constructor
00164     # @param self Object Pointer
00165     # @param pyjama Pyjama Reference
00166     def __init__(self, pyjama):
00167         self.pyjama = pyjama
00168         gtk.Menu.__init__(self)
00169 
00170 #        # Add remove button if an entry is selected:
00171 #        model, tmpIter = pyjama.window.tvList.get_selection().get_selected()
00172 #        if tmpIter != None:
00173 #            #path = pyjama.window.liststore.get_path(tmpIter)[0]
00174 #            mnu = gtk.ImageMenuItem("Remove from List")
00175 #            self.append(mnu)
00176 #            mnu.show()
00177 #            mnu.connect("activate", self.cb_mnu_remove_clicked)
00178 
00179 #            img = gtk.Image()
00180 #            img.set_from_stock(gtk.STOCK_REMOVE, gtk.ICON_SIZE_MENU)
00181 #            mnu.set_image(img)
00182 
00183 
00184         pyjama.Events.raise_event("populate_listmenu", self)
00185 
00186         self.show()
00187 
00188     def cb_mnu_remove_clicked(self, widget):
00189         self.pyjama.window.on_bDelete_clicked(None)
00190 
00191 
00192 ## Context menu for the playlist
00193 # When creating a PlaylistMenu the event
00194 # 'populate_playlistmenu' will be raised
00195 class PlaylistMenu(gtk.Menu):
00196     ## The Constructor
00197     # @param self Object Pointer
00198     # @param pyjama Pyjama Reference
00199     def __init__(self, pyjama):
00200         self.pyjama = pyjama
00201         gtk.Menu.__init__(self)
00202 
00203         # Add remove button if an entry is selected:
00204         model, tmpIter = pyjama.window.tvPlaylist.get_selection().get_selected()
00205         if tmpIter != None:
00206             #path = pyjama.window.liststore.get_path(tmpIter)[0]
00207 
00208             ## Show Artist Menu
00209             mnu = gtk.ImageMenuItem(_("Show artist's page"))
00210             self.append(mnu)
00211             mnu.show()
00212             mnu.connect("activate", self.cb_mnu_artist_clicked)
00213             img = gtk.Image()
00214             pb = gtk.gdk.pixbuf_new_from_file_at_size(os.path.join(functions.install_dir(), "images", "personal.png"), 16, 16)
00215             img.set_from_pixbuf(pb)
00216             mnu.set_image(img)
00217 
00218             ## Show Album Menu
00219             mnu = gtk.ImageMenuItem(_("Show album's page"))
00220             self.append(mnu)
00221             mnu.show()
00222             mnu.connect("activate", self.cb_mnu_album_clicked)
00223             img = gtk.Image()
00224             pb = gtk.gdk.pixbuf_new_from_file_at_size(os.path.join(functions.install_dir(), "images", "cd.png"), 16, 16)
00225             img.set_from_pixbuf(pb)
00226             mnu.set_image(img)
00227 
00228             x = gtk.SeparatorMenuItem()
00229             x.show()
00230             self.append(x)
00231 
00232 
00233             pyjama.Events.raise_event("populate_playlistmenu", self)
00234 
00235 
00236             x = gtk.SeparatorMenuItem()
00237             x.show()
00238             self.append(x)
00239 
00240             ## Remove Menu
00241             mnu = gtk.ImageMenuItem(_("Remove from Playlist"))
00242             self.append(mnu)
00243             mnu.show()
00244             mnu.connect("activate", self.cb_mnu_remove_clicked)
00245             img = gtk.Image()
00246             img.set_from_stock(gtk.STOCK_REMOVE, gtk.ICON_SIZE_MENU)
00247             mnu.set_image(img)
00248 
00249 
00250         self.show()
00251 
00252     def cb_mnu_artist_clicked(self, widget):
00253         model, tmpIter = self.pyjama.window.tvPlaylist.get_selection().get_selected()
00254         if tmpIter != None:
00255             path = model.get_path(tmpIter)
00256             if path != (): path = path[0]
00257 
00258             track = self.pyjama.player.playlist[path]
00259 
00260             artistdetails = self.pyjama.db.artistinfos(track.artist_id)
00261             self.pyjama.layouts.show_layout("artist", artistdetails)
00262 
00263     def cb_mnu_album_clicked(self, widget):
00264         model, tmpIter = self.pyjama.window.tvPlaylist.get_selection().get_selected()
00265         if tmpIter != None:
00266             path = model.get_path(tmpIter)
00267             if path != (): path = path[0]
00268             track = self.pyjama.player.playlist[path]
00269 
00270             albumdetails = self.pyjama.jamendo.albuminfos(track.album_id)
00271             if not albumdetails: return
00272             self.pyjama.layouts.show_layout("album", albumdetails)
00273 
00274     def cb_mnu_remove_clicked(self, widget):
00275         self.pyjama.window.on_bDelete_clicked(None)
00276 
00277 ## Dialog Class
00278 class MyDialog(gtk.Dialog):
00279     def __init__(self, caption, toplevel, flags, buttons, image, desc, sep=True, allow_resize=False):
00280             gtk.Dialog.__init__(self, caption, toplevel, flags, buttons)
00281             img = gtk.Image()
00282             img.set_from_stock(image, gtk.ICON_SIZE_DIALOG)
00283             hbox = gtk.HBox()
00284             self.vbox.pack_start(hbox)
00285             hbox.pack_start(img)
00286             label = gtk.Label()
00287             label.set_single_line_mode(False)
00288             label.set_line_wrap(True)
00289             label.set_markup(desc)
00290             hbox.pack_start(label)
00291 
00292             self.set_has_separator(sep)
00293             self.set_resizable(allow_resize)
00294 
00295             self.show_all()
00296 
00297 ## Process Dialog
00298 # This dialog can be used to show a dialog
00299 # with a progressbar in it
00300 class ProcessDialog(gtk.Dialog):
00301     def __init__(self, pyjama, caption):
00302         gtk.Dialog.__init__(self, caption)
00303 
00304         self.set_modal(True)
00305 #        self.set_size_request(400, 300)
00306 
00307         self.progressbar = gtk.ProgressBar()
00308         self.label = gtk.Label()
00309         self.label.set_line_wrap(True)
00310         self.label.set_single_line_mode(False)
00311 
00312         self.vbox.pack_start(self.label, False, True)
00313         self.vbox.pack_start(self.progressbar, False, True)
00314 
00315         self.show_all()
00316 
00317     def set_status(self, percentage=None, text=None):
00318         if percentage is not None:
00319             self.progressbar.set_fraction(percentage/100)
00320         if text is not None:
00321             self.progressbar.set_text(text)
00322 
00323     def set_description(self, desc):
00324         self.label.set_markup(desc)
00325 
00326 ## Treeview on the bottom with artist-album-tracks fields
00327 class TreeViewList(gtk.TreeView):
00328 
00329     #   columns
00330     (
00331       COLUMN_ARTIST,
00332       COLUMN_ALBUM,
00333       COLUMN_TRACKNUM,
00334       COLUMN_TRACK,
00335       COLUMN_LICENSE,
00336       COLUMN_ARTISTID,
00337       COLUMN_ALBUMID,
00338       COLUMN_TRACKID,
00339       COLUMN_LICENSEURL
00340     ) = range(9)
00341 
00342     def __init__(self):
00343         # create model
00344         model = self.__create_model()
00345 
00346         # create tree view
00347         gtk.TreeView.__init__(self, model)
00348         self.set_rules_hint(True)
00349         self.set_rubber_banding(True)
00350         self.set_show_expanders(True)
00351         #self.set_reorderable(True)
00352         self.get_selection().set_mode(gtk.SELECTION_SINGLE)#gtk.SELECTION_MULTIPLE
00353         self.__add_columns(self)
00354 
00355         self.show()
00356 
00357     def get_item(self, path):
00358         model = self.get_model()
00359         retIter = model.get_iter(path)
00360         ret = model.get(retIter, 0, 1, 2, 3, 4, 5, 6, 7, 8)
00361         return ret
00362         
00363 
00364     def clear(self):
00365         model = self.get_model()
00366         model.clear()
00367 
00368 
00369     def add_item(self, item):
00370         model = self.get_model()
00371         #articles.append(new_item)
00372         if item[self.COLUMN_TRACKNUM] != "":
00373             item[self.COLUMN_TRACKNUM] = "%02d" % int(item[self.COLUMN_TRACKNUM])
00374 
00375         iter = model.append()
00376         model.set (iter,
00377             self.COLUMN_ARTIST, item[self.COLUMN_ARTIST],
00378             self.COLUMN_ALBUM, item[self.COLUMN_ALBUM],
00379             self.COLUMN_TRACKNUM, item[self.COLUMN_TRACKNUM],
00380             self.COLUMN_TRACK, item[self.COLUMN_TRACK],
00381             self.COLUMN_LICENSE, "",
00382             self.COLUMN_ARTISTID, item[self.COLUMN_ARTISTID],
00383             self.COLUMN_ALBUMID, item[self.COLUMN_ALBUMID],
00384             self.COLUMN_TRACKID, item[self.COLUMN_TRACKID],
00385             self.COLUMN_LICENSEURL, item[self.COLUMN_LICENSE]
00386        )
00387 
00388     def __create_model(self):
00389 
00390         # create list store
00391         model = gtk.ListStore(
00392             gobject.TYPE_STRING,
00393             gobject.TYPE_STRING,
00394             gobject.TYPE_STRING,
00395             gobject.TYPE_STRING,
00396             gobject.TYPE_STRING,
00397             gobject.TYPE_INT,
00398             gobject.TYPE_INT,
00399             gobject.TYPE_INT,
00400             gobject.TYPE_STRING
00401        )
00402        
00403 #        # add items
00404 #        for item in articles:
00405 #            iter = model.append()
00406 
00407 #            model.set (iter,
00408 #                  COLUMN_ARTIST, item[COLUMN_ARTIST],
00409 #                  COLUMN_ALBUM, item[COLUMN_ALBUM],
00410 #                  COLUMN_TRACK, item[COLUMN_TRACK]
00411 #           )
00412         return model
00413 
00414 
00415     def __add_columns(self, treeview):
00416 
00417         model = treeview.get_model()
00418 
00419         # artist column
00420         renderer = gtk.CellRendererText()
00421         renderer.set_data("column", self.COLUMN_ARTIST)
00422 
00423         column = gtk.TreeViewColumn(_("Artist"), renderer, text=self.COLUMN_ARTIST)
00424         treeview.append_column(column)
00425         column.set_sort_column_id(0)
00426         column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
00427         column.set_resizable(True)
00428         column.set_fixed_width(150)
00429 
00430 
00431 
00432         # album column
00433         renderer = gtk.CellRendererText()
00434         renderer.set_data("column", self.COLUMN_ALBUM)
00435 
00436         column = gtk.TreeViewColumn(_("Album"), renderer, text=self.COLUMN_ALBUM)
00437         treeview.append_column(column)
00438         column.set_sort_column_id(1)
00439         column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
00440         column.set_resizable(True)
00441         column.set_fixed_width(150)
00442 
00443         # tracknum column
00444         renderer = gtk.CellRendererText()
00445         renderer.set_data("column", self.COLUMN_TRACKNUM)
00446 
00447         column = gtk.TreeViewColumn("#", renderer, text=self.COLUMN_TRACKNUM)
00448         treeview.append_column(column)
00449         column.set_sort_column_id(2)
00450         column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
00451         column.set_resizable(True)
00452         column.set_fixed_width(40)
00453 
00454         # track column
00455         renderer = gtk.CellRendererText()
00456         renderer.set_data("column", self.COLUMN_TRACK)
00457 
00458         column = gtk.TreeViewColumn(_("Track"), renderer, text=self.COLUMN_TRACK)
00459         treeview.append_column(column)
00460         column.set_sort_column_id(3)
00461         column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
00462         column.set_resizable(True)
00463         column.set_fixed_width(150)
00464         
00465 #        # license column
00466 #        renderer = gtk.CellRendererText()
00467 #        renderer.set_data("column", self.COLUMN_LICENSE)
00468 
00469 #        column = gtk.TreeViewColumn(_("Licence"), renderer, text=self.COLUMN_LICENSE)
00470 #        treeview.append_column(column)
00471 #        column.set_sort_column_id(4)
00472 #        column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
00473 #        column.set_resizable(True)
00474 #        column.set_fixed_width(100)
00475 
00476         # license column
00477         renderer = gtk.CellRendererPixbuf()
00478         renderer.set_data("column", self.COLUMN_LICENSE)
00479 #        renderer.set_property('cell-background', 'yellow')
00480 
00481         column = gtk.TreeViewColumn(_("Licence"), renderer)
00482         treeview.append_column(column)
00483 #        column.set_sort_column_id(4)
00484         column.set_cell_data_func(renderer, self.make_pb)
00485         column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
00486         column.set_resizable(True)
00487         column.set_fixed_width(100)
00488 
00489     def make_pb(self, tvcolumn, cell, model, iter):
00490         url = model.get_value(iter, self.COLUMN_LICENSEURL)
00491         if url is None or url == "":
00492 #            pb = gtk.gdk.pixbuf_new_from_file_at_size(img_file, -1, 20)
00493             cell.set_property('pixbuf', None)
00494             return
00495 
00496         if "creativecommons" in url:
00497             try:
00498                 attribution = url.split("/")[4]
00499                 img_file = os.path.join(functions.install_dir(), "images", "license_images", "cc_small", "%s.png" % attribution)
00500                 if os.path.exists(img_file):
00501                     pb = gtk.gdk.pixbuf_new_from_file_at_size(img_file, -1, 20)
00502     #            pb = self.render_icon(stock, gtk.ICON_SIZE_MENU, None)
00503                     cell.set_property('pixbuf', pb)
00504                 else:
00505                     return
00506             except:
00507                 return
00508         elif "nolicense" in url:
00509             img_file = os.path.join(functions.install_dir(), "images", "license_images", "pd.png")
00510             if os.path.exists(img_file):
00511                 pb = gtk.gdk.pixbuf_new_from_file_at_size(img_file, -1, 20)
00512                 cell.set_property('pixbuf', pb)
00513         elif "artlibre" in url:
00514             img_file = os.path.join(functions.install_dir(), "images", "license_images",
00515  "artlibre.png")
00516             if os.path.exists(img_file):
00517                 pb = gtk.gdk.pixbuf_new_from_file_at_size(img_file, -1, 20)
00518                 cell.set_property('pixbuf', pb)
00519 
00520 ## widget showing stars as raiting for an album
00521 class Rating(gtk.HBox):
00522     def __init__(self):
00523         gtk.HBox.__init__(self)
00524         self.img=[]
00525         for img in range(0, 10):
00526             self.img.append(gtk.Image())
00527             pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(os.path.join(functions.install_dir(), "images", "star.png"), 16, 16)
00528             #pixbuf = self.img[img].render_icon(gtk.STOCK_ABOUT, gtk.ICON_SIZE_MENU, detail=None)
00529             self.img[img].set_from_pixbuf(pixbuf)
00530             self.pack_start(self.img[img], True, True, 0)
00531             self.img[img].show()
00532             
00533     def set_rating(self, rating):
00534         for img in self.img:
00535             img.hide()
00536             
00537         rating = int(ceil(float(rating)))
00538         
00539         for img in range(0, rating):
00540             self.img[img].show()
00541 
00542 ## my statusbar widget
00543 class StatusBar(gtk.HBox):
00544     def __init__(self, *argv):
00545         self.statusbars = {}
00546 
00547         gtk.HBox.__init__(self, False)
00548         
00549         for item in argv:
00550             self.statusbars[item] = {'statusbar':gtk.Statusbar()} 
00551             self.statusbars[item]['conid'] = self.statusbars[item]['statusbar'].get_context_id("Status")
00552             self.statusbars[item]['msgid'] = self.statusbars[item]['statusbar'].push(self.statusbars[item]['conid'], "")
00553             self.statusbars[item]['curtext'] =  None
00554             if item != argv[len(argv)-1]:
00555                 self.statusbars[item]['statusbar'].set_has_resize_grip(False)
00556                 self.statusbars[item]['sep'] = gtk.VSeparator()
00557                 self.pack_start(self.statusbars[item]['statusbar'], True, True, 0)
00558                 self.pack_start(self.statusbars[item]['sep'], False, False, 0)
00559                 self.statusbars[item]['statusbar'].show()
00560                 self.statusbars[item]['sep'].show()
00561             else:
00562                 self.statusbars[item]['statusbar'].set_has_resize_grip(True)
00563                 self.pack_start(self.statusbars[item]['statusbar'], False, True, 0)
00564                 self.statusbars[item]['statusbar'].show()
00565 #                self.progressBar = gtk.ProgressBar()
00566 #                self.progressBar.set_size_request(30,5)
00567 #                self.progressBar.hide()
00568 #                self.statusbars[item]['statusbar'].add(self.progressBar)
00569 
00570     def set_text(self, statusbar, text):
00571         if self.statusbars[statusbar]['curtext'] != text:
00572             self.statusbars[statusbar]['msgid'] = self.statusbars[statusbar]['statusbar'].push(self.statusbars[statusbar]['conid'], text)
00573             self.statusbars[statusbar]['statusbar'].set_tooltip_text(text)
00574             self.statusbars[statusbar]['curtext'] = text
00575 
00576 ## ComboBox for setting results per page
00577 class ResultsPerPageCombo(gtk.ComboBox):
00578     def __init__(self):
00579         liststore = gtk.ListStore(gobject.TYPE_STRING)
00580         gtk.ComboBox.__init__(self,liststore)
00581         cell = gtk.CellRendererText()
00582 
00583         ## Used to tell apart user generated
00584         # and auto computed changes of the
00585         # active item
00586         self.auto_setting_item = False
00587 
00588         self.pack_start(cell, True)
00589         self.add_attribute(cell, 'text', 0)
00590         self.set_tooltip_text(_("How many results should be shown?"))
00591 
00592         self.cbResultsPerPage = gtk.combo_box_new_text()
00593 
00594         self.modelist = ["10", "20", "30", "40", "50", "60", "70", "80", "90", "100"]
00595         for mode in self.modelist:
00596             self.append_text(mode)
00597         self.set_active(0)
00598 
00599     def set_item(self, mode):
00600         self.auto_setting_item = True
00601         self.set_property("active", self.modelist.index(str(mode)))
00602         self.auto_setting_item = False
00603 
00604 ## holds some basic jamendo order keywords
00605 class OrderCombo(gtk.ComboBox):
00606     def __init__(self):
00607         liststore = gtk.ListStore(gobject.TYPE_STRING)
00608         gtk.ComboBox.__init__(self, liststore)
00609         cell = gtk.CellRendererText()
00610 
00611         ## Used to tell apart user generated
00612         # and auto computed changes of the
00613         # active item
00614         self.auto_setting_item = False
00615 
00616         self.pack_start(cell, True)
00617         self.add_attribute(cell, 'text', 0)
00618         self.set_tooltip_text(_("Select how to order results"))
00619         
00620         self.modelist = ["rating", "ratingweek", "ratingmonth", "date", "downloaded", "listened", "starred", "playlisted"]
00621         for mode in self.modelist:
00622             self.append_text(mode)
00623         self.set_active(1)
00624         
00625     def set_item(self, mode):
00626         self.auto_setting_item = True
00627         self.set_active(self.modelist.index(mode))
00628         self.auto_setting_item = False
00629 
00630 ## holds some pre-selected tags
00631 class TagsCombo(gtk.ComboBoxEntry): #Entry
00632     def __init__(self, pyjama):
00633         liststore = gtk.ListStore(gobject.TYPE_STRING)
00634         gtk.ComboBoxEntry.__init__(self, liststore, ) #Entry
00635 
00636         ## Used to tell apart user generated
00637         # and auto computed changes of the
00638         # active item
00639         self.auto_setting_item = False
00640 
00641         cell = gtk.CellRendererText()
00642         self.pack_start(cell, False)
00643         self.set_wrap_width(4)
00644         self.set_tooltip_text(_("Select tags to show"))
00645 
00646         self.set_model(liststore)
00647 #        self.add_attribute(cell, 'text', 0)     
00648 
00649         self.entry = self.child
00650 
00651 
00652         default = "ambient experimental instrumental electro alternativ hiphop guitar metal pop punk rock techno triphop world trance progressive gothic hardcore minimal funk dance psychedelic 8bit"
00653         lst = default.split(" ")
00654         lst.sort()
00655         default = " ".join(lst)
00656         #~ if pyjama.settings.config.has_option("JAMENDO", "TAGs") == False:
00657         tags = pyjama.settings.get_value("JAMENDO", "newtags", default)
00658             #~ pyjama.settings.set_value("JAMENDO", "TAGs", default)
00659         #~ else:
00660             #~ tags = pyjama.settings.get_value("JAMENDO", "TAGs", default)
00661 #        if not ("--all--") in tags: tags = ("--all-- %s") % tags
00662         if not _("--all--") in tags: tags = "%s %s" % (_("--all--") , tags)
00663 #        if not _("--custom--") in tags: tags = _("%s --custom--") % tags
00664         tags = tags.split(" ")
00665         while "" in tags: tags.remove("")
00666         self.modelist = tags
00667 
00668 
00669         for mode in self.modelist:
00670             #self.append_text(mode)
00671             liststore.append([mode])
00672 
00673         self.set_active(0)    
00674         
00675     def set_item(self, mode):
00676         self.auto_setting_item = True
00677         try:
00678             self.set_active(self.modelist.index(mode))
00679         except ValueError:
00680             # This should not happen at all - but it did once ;)
00681             self.set_active(0)
00682 
00683         self.auto_setting_item = False
00684 
00685 ## A label sensible to mouse movements
00686 class MouseLabel(gtk.Label):
00687     def __init__(self,t):
00688         gtk.Label.__init__(self, t)
00689 
00690         eventbox = gtk.EventBox()
00691         eventbox.add(self)
00692         eventbox.add_events (gtk.gdk.BUTTON_RELEASE)
00693         boat = gtk.gdk.Cursor(gtk.gdk.WATCH)
00694         eventbox.window.set_cursor(boat)
00695         eventbox.connect("realize", self.on_realize)
00696 
00697     def on_realize(self, widget):
00698         print "asd"
00699     #     self.set_cursor(watch)
00700 
00701 ## A button with a StockItem on it
00702 class StockButton(gtk.Button):
00703     def __init__(self, stock, size=gtk.ICON_SIZE_MENU, text=None):
00704         gtk.Button.__init__(self, text)
00705 
00706         pixbuf = self.render_icon(stock, size, detail=None)
00707         self.img = gtk.Image()
00708         self.img.set_from_pixbuf(pixbuf)
00709         #set_from_stock(stock_id, size)
00710         self.set_image(self.img)
00711         
00712        
00713         self.tag = None
00714         
00715     def setimage(self, stock, size=gtk.ICON_SIZE_MENU):
00716         pixbuf = self.render_icon(stock, size, detail=None)
00717         #self.img = gtk.Image()
00718         self.img.set_from_pixbuf(pixbuf)
00719         self.set_image(self.img)
00720 
00721 
00722 ## A Button with an image from a file
00723 class ImageButton(gtk.Button):
00724     def __init__(self, sFile, w, h=None, text=None):
00725         gtk.Button.__init__(self, text)
00726         self.img = gtk.Image()
00727 
00728         # if h is None, assume w being a stock size
00729         # convert stock size to pixel
00730         if h is None:
00731             w, h = gtk.icon_size_lookup(w)
00732         self.setimage(sFile, w, h)
00733 
00734     def setimage(self, sFile, w, h):
00735         if not os.path.exists(sFile):
00736             if os.path.exists(os.path.join(functions.install_dir(), "images", sFile)):
00737                 sFile = os.path.join(functions.install_dir(), "images", sFile)
00738         pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(sFile, w, h)
00739         self.img.set_from_pixbuf(pixbuf)
00740         #set_from_stock(stock_id, size)
00741         self.set_image(self.img)
00742 
00743     def setstock(self, stock, size=gtk.ICON_SIZE_MENU):
00744         pixbuf = self.render_icon(stock, size, detail=None)
00745         self.img.set_from_pixbuf(pixbuf)
00746         self.set_image(self.img)
00747 
00748 class MyLinkButton(gtk.Button):
00749     def __init__(self, uri, text=""):
00750         gtk.Button.__init__(self)
00751         self.lbl = gtk.Label()
00752         self.lbl.show()
00753         self.add(self.lbl)
00754         self.lbl.set_markup("<u><span foreground='blue'>%s</span></u>" % text)
00755         self.text = text
00756         self.uri = uri
00757         self.set_relief(gtk.RELIEF_NONE)
00758 
00759     def set_label(self, text):
00760         self.lbl.set_markup("<u><span foreground='blue'>%s</span></u>" % text)
00761         self.text = text
00762 
00763     def get_text(self):
00764         return self.text
00765 
00766 ## Widget showing cover, artist name and album name from an album id
00767 # also having a hover-menu
00768 target = [
00769     ('STRING', 0, 0),
00770     ('text/plain', 0, 0),
00771     ('application/x-rootwin-drop', 0, 1)
00772 ]
00773 
00774 class AlbumInfo(gtk.Frame):
00775     def __init__(self, parent, album, small=False):
00776         self.imagewidth = 100
00777         self.imageheight = 100
00778         self.album = album
00779         self.par = parent
00780         self.over_button = True
00781         gtk.Frame.__init__(self)
00782         self.set_label_align(0.5, 0.5)
00783         self.set_shadow_type(gtk.SHADOW_ETCHED_OUT)
00784         if small:
00785             self.set_size_request(100,110) #(150,160) before controls
00786         else:
00787             self.set_size_request(150,160) #(150,160) before controls
00788         
00789         # Album
00790         self.lAlbum = MyLinkButton((album['album_name']), clear(album['album_name'][:20]))         
00791         self.lAlbum.set_tooltip_text(album['album_name'])
00792         self.lAlbum.show()
00793         self.set_label_widget(self.lAlbum)
00794         self.lAlbum.connect("clicked", self.lAlbum_clicked)
00795         
00796         self.hbox = gtk.HBox(homogeneous=False, spacing=0)
00797         self.vbox = gtk.VBox(homogeneous=False, spacing=0)
00798 
00799         self.eventFrame = gtk.EventBox()
00800         self.add(self.eventFrame)
00801         self.eventFrame.add(self.hbox)
00802         #self.add(self.hbox) #==> eventFrame
00803         
00804         self.hbox.pack_start(self.vbox)
00805         self.vbox.set_size_request(100,150)
00806         self.hbox.show()
00807         self.vbox.show()
00808 
00809         # ControlBox        
00810         self.vbControl = gtk.VBox()
00811         self.hbox.pack_start(self.vbControl)
00812         self.vbControl.hide()
00813         # Play
00814         self.bControlPlay = StockButton(gtk.STOCK_MEDIA_PLAY)
00815         self.bControlPlay.set_tooltip_text(_("Append this album on playlist and play it"))
00816         self.vbControl.pack_start(self.bControlPlay, False, True, 0)
00817         self.bControlPlay.connect("clicked", self.on_bControlPlay)
00818         self.bControlPlay.show()
00819         # Add
00820         self.bControlAdd = StockButton(gtk.STOCK_ADD)
00821         self.bControlAdd.set_tooltip_text(_("Append this album on playlist"))
00822         self.vbControl.pack_start(self.bControlAdd, False, True, 0)
00823         self.bControlAdd.connect("clicked", self.on_bControlAdd)
00824         self.bControlAdd.show()
00825 
00826         # Star
00827         # will be implemented via plugin
00828 #        self.bControlStar = ImageButton(os.path.join(functions.install_dir(), "images", "star.png"), 16, 16)
00829 #        self.bControlStar.set_tooltip_text(_("Add this album to favorites [not implemented, yet]"))
00830 #        self.vbControl.pack_start(self.bControlStar, False, True, 10)
00831 #        self.bControlStar.connect("clicked", self.on_bControlStar)
00832 #        self.bControlStar.show()
00833 
00834         # Event-Box
00835         self.eventFrame.set_above_child(False) # ???
00836         self.eventFrame.add_events (gtk.gdk.ENTER_NOTIFY_MASK)
00837         self.eventFrame.add_events (gtk.gdk.LEAVE_NOTIFY_MASK)
00838         self.eventFrame.connect("enter-notify-event", self.show_vbControl)
00839         self.eventFrame.connect("leave-notify-event", self.hide_vbControl)
00840         self.eventFrame.connect("button_release_event", self.image_clicked, album)
00841         self.eventFrame.show()
00842         
00843         # Image
00844         imagepath = self.par.get_album_image(album['album_id'],100)
00845 
00846         self.image = gtk.Image()
00847         self.vbox.pack_start(self.image, False, False, 0)#, 25, 1)
00848         self.image.set_from_file(imagepath)
00849         self.image.show()
00850         #self.eventbox = gtk.EventBox()
00851         #self.eventbox.add(self.image)
00852         #self.eventbox.set_above_child(False)
00853         #self.eventbox.add_events (gtk.gdk.BUTTON_RELEASE)
00854         #self.eventbox.connect("button_release_event", self.image_clicked, album)
00855         #self.eventbox.connect("enter-notify-event", self.show_vbControl)
00856         #self.eventbox.connect("leave-notify-event", self.hide_vbControl)
00857         #self.eventbox.show()
00858         #self.vbox.pack_start(self.eventbox, False, False, 0)#, 25, 1)
00859         self.__setcolor(self.eventFrame) # ???
00860 
00861         #
00862         # Drag & Drop
00863         #
00864 #        self.eventFrame.drag_source_set(gtk.gdk.BUTTON1_MASK | gtk.gdk.BUTTON3_MASK,target, gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE)
00865         #self.image.drag_source_set_icon(get_colormap(), drag_icon, drag_mask)
00866 #        self.eventFrame.connect('drag_data_get', self.source_drag_data_get)
00867 #        self.eventFrame.connect('drag_data_delete', self.source_drag_data_delete)
00868 
00869         # Artist
00870         artist = album['artist_name']
00871         self.lArtist = MyLinkButton(clear(artist), clear(artist)) #gtk.Label()
00872         self.lArtist.set_tooltip_text(artist)
00873         self.lArtist.connect("clicked", self.lArtist_clicked)
00874         self.vbox.pack_start(self.lArtist, False, False, 0)#, 10, 110)
00875         self.lArtist.show()
00876 
00877         if self.par.debug_extreme:
00878             print ("Created AlbumInfo for %s[...]") % str(album['album_name'][:20])
00879 
00880 
00881         self.par.Events.raise_event("albuminfo_created", self)
00882 
00883     def source_drag_data_get(self, btn, context, selection_data, info, time):
00884         print "start dragging"
00885         if info == 1:
00886             print 'I was dropped on the rootwin'
00887         else:
00888             selection_data.set(selection_data.target, 8, "I'm Data!")
00889 
00890     def source_drag_data_delete(self, btn, context, data):
00891         print 'Delete the data!'
00892 
00893     def lArtist_clicked(self, ev1="", ev2=""):
00894         print self.album['artist_id'], "!!!"
00895         artistdetails = self.par.db.artistinfos(self.album['artist_id'])
00896         self.par.layouts.show_layout("artist", artistdetails)
00897 
00898     def lAlbum_clicked(self, ev1="", ev2=""):
00899         #print ev2
00900         #print self.album['album_id']
00901         albumdetails = self.par.jamendo.albuminfos(self.album['album_id'])
00902         if not albumdetails: return
00903         self.par.layouts.show_layout("album", albumdetails)
00904 
00905     def image_clicked(self, ev, ev2, ev3):
00906         x,y = self.image.get_pointer()
00907         if x > 0 and x < 100 and y > 0 and y < 100:
00908             #print self.album
00909             #self.par.layout['top'].hide()
00910             #print self.par.jamendo.albuminfos(self.album['album_id'])
00911             self.lAlbum_clicked()
00912         
00913     def __setcolor(self, widget):
00914         if self.par.nocolor:
00915             return None 
00916         style = widget.get_style()
00917         color = widget.get_colormap()
00918         bg = color.alloc_color(self.par.window.bgcolor)
00919         fg = color.alloc_color(0, 0, 0, 0)
00920         style.bg[gtk.STATE_NORMAL] = bg
00921         style.fg[gtk.STATE_NORMAL] = fg
00922         widget.set_style(style)
00923         
00924     def show_vbControl(self, ev1, ev2):
00925         self.vbControl.show()
00926 
00927     
00928     def hide_vbControl(self, ev1, ev2):
00929         x,y = self.vbControl.get_pointer()
00930         if x > 0 and x < 35 and y > 0 and y < 90: return None
00931         self.vbControl.hide()
00932 
00933 
00934     def on_bControlPlay(self, ev1):
00935         tracks = self.par.db.albumtracks(self.album['album_id'])
00936         track_count = len(tracks)
00937 
00938         if track_count == 0:
00939             print ("Album not in database, yet.")
00940             #print album['public_date']
00941             dia = MyDialog(_('Album non existant.'),
00942                               self.par.window.get_toplevel(),
00943                               gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, 
00944                                 (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT), gtk.STOCK_DIALOG_WARNING, _('This album is not in the database.\nPerhaps Jamendo did not unloack that album, yet\n or you are using a old local database.'))
00945             dia.run()
00946             dia.destroy()
00947             return None
00948         self.par.appendtracks(tracks, play=True)
00949         
00950     def on_bControlAdd(self, ev1):
00951         tracks = self.par.db.albumtracks(self.album['album_id'])
00952         track_count = len(tracks)
00953 
00954         if track_count == 0:
00955             print ("Album not in database, yet.")
00956             #print album['public_date']
00957             dia = MyDialog(_('Album non existant.'),
00958                               self.par.window.get_toplevel(),
00959                               gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, 
00960                                 (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT), gtk.STOCK_DIALOG_WARNING, _('This album is not in the database.\nPerhaps Jamendo did not unloack that album, yet\n or you are using a old local database.'))
00961             dia.run()
00962             dia.destroy()
00963             return None
00964 
00965         self.par.appendtracks(tracks)
00966 
00967 class EqualizerBox(gtk.HBox):
00968     def __init__(self, pyjama):
00969         self.pyjama = pyjama
00970 
00971         gtk.HBox.__init__(self)
00972 
00973         ## Number of eq-bands
00974         self.n = self.pyjama.player.equalizer_bands
00975 
00976         ## used to store eq-values for each band
00977         self.values = []
00978         for i in range(self.n):
00979             val = self.pyjama.settings.get_value("SOUND", "band%i" % i, 0.0, float)
00980             self.values.append(val)
00981 
00982         ## also stores eq-values for each band - stored for discrard-fct
00983         # won't changed
00984         self.start_values = copy.copy(self.values)
00985 
00986         if self.n==10:
00987             labels=('29 Hz','59 Hz','119 Hz','227 Hz','474 Hz','947 Hz',
00988                 '1.98 kHz','3.7 kHz','7.5 kHz','15.0 kHz')
00989         elif self.n==3:
00990             labels=('100 Hz','1.1 kHz','11.0 kHz')
00991         else:
00992             labels=[]
00993             for a in range(self.n):
00994                 labels.append("")
00995 
00996         ## Adjustments
00997         self.adjs={} 
00998 
00999         self.show()
01000 
01001         frame = gtk.Frame("Equalizer")
01002         frame.show()
01003         self.pack_start(frame, False, False, 20)
01004 
01005         hbox_bottom = gtk.HBox()
01006         hbox_bottom.show()
01007 
01008         frame.add(hbox_bottom)
01009         for i in range(self.n):
01010             self.adjs[i]=gtk.Adjustment(value=self.values[i],
01011                                         lower=-24, upper=12, 
01012                                         step_incr=0.1)
01013             self.adjs[i].connect("value_changed", self.cb_eq_value_changed,i)
01014             scale=gtk.VScale(self.adjs[i])
01015             scale.set_inverted(True)
01016             scale.set_size_request(-1, 200)
01017             scale.show()
01018             vbox=gtk.VBox()
01019             vbox.pack_start(scale)
01020             vbox.pack_start(gtk.Label(labels[i]), False, True, 5)
01021             button=gtk.Button("clear")
01022             #button.set_relief(gtk.RELIEF_NONE)
01023             button.connect("clicked", self.cb_eq_clear_clicked,i)
01024             button.show()
01025             
01026             vbox.pack_start(button, False, False, 0)
01027             vbox.show_all()
01028             hbox_bottom.pack_start(vbox, False, False, 3)
01029 
01030     def cb_eq_clear_clicked(self, widget, num):
01031         self.values[num]=0
01032         self.adjs[num].set_value(0)
01033 
01034         self.pyjama.player.set_equalizer(self.values)
01035                 
01036     def cb_eq_value_changed(self, widget, num):
01037         self.values[num]=widget.get_value()
01038 
01039         self.pyjama.player.set_equalizer(self.values)
01040 
01041     def save(self):
01042         for i in range(self.n):
01043             self.pyjama.settings.set_value("SOUND", "band%i" % i, self.values[i], float)
01044 
01045     def discard(self):
01046         self.pyjama.player.set_equalizer(self.start_values)
01047 
01048     def dialog(self):
01049         dia = gtk.Dialog()
01050         dia.vbox.pack_start(self)
01051 
01052         dia.set_modal(True)
01053         dia.set_title("Equalizer")
01054         dia.set_icon_from_file(os.path.join(functions.install_dir(), "images", "view-media-equalizer.png"))
01055 
01056 
01057         dia.add_button(gtk.STOCK_CANCEL, -2)
01058         dia.add_button(gtk.STOCK_OK, -1)
01059 
01060 
01061         ret = dia.run()
01062         if ret == -1:
01063             self.save()
01064         else:
01065             self.discard()
01066         dia.destroy()

Generated on Thu Jun 4 19:08:24 2009 for Pyjama by  doxygen 1.5.8