remove cell background colors, add treeview search capabilities and status icons

git-svn-id: svn://svn.berlios.de/gpodder/trunk@301 b0d088ad-0a06-0410-aad2-9ed5178a7e87
This commit is contained in:
Thomas Perl 2007-04-03 06:27:46 +00:00
parent fc0950fc62
commit d71d72761b
8 changed files with 77 additions and 323 deletions

View file

@ -1,3 +1,20 @@
Tue, 3 Apr 2007 08:18:28 +0200 <thp@perli.net>
* src/gpodder/libpodcasts.py: Remove background color code in model;
add icons; add new get_file_type() function to check if an episode
is either audio or video; add full description to liststore model
* src/gpodder/libgpodder.py: Remove code related to configurable
treeview row colors
* src/gpodder/gpodder.py: Remove code for treeview colors; add new
"status" column with icon; set rules hint on treeAvailable to get
alternating tree view row colors (if gtk theme supports it); add
type-to-search capabilities to treeAvailable by providing the
new treeAvailable_search_equal function
* data/gpodder.glade: Remove properties tab for colors
* bin/gpodder: Pushed version + release date
* TODO: Removing background colors is a GoodThing(tm), so we are now
compatible with high contrast themes and dark gtk themes (this has
been a problem with custom cell backgrounds); mark the item as done
Mon, 2 Apr 2007 16:31:46 +0200 <thp@perli.net>
* src/gpodder/gpodder.py: Added some intelligence for enabling and
disabling the "cancel download" toolbar button depending on the

8
TODO
View file

@ -14,14 +14,6 @@
* Finally, could it mark via a different color code when a podcast
has been played. (John Connor; johnc.connor gmail.com)
* First, please don't use hard coded background colors when you use the
foreground color from the current gtk theme at the same time. Right now
you assume people always have a theme with dark text color, which is
just not true. My theme uses a bright text color and that makes the
podcasts list unreadable, which uses yellow/white as background. Also
think about people using gnomes highcontrast inverse theme (white text
color). (suggested by Holger Bauer -- umarmung@email.de)
* My second suggestion is to include a systray icon similar to the ones
many music players have. It would be great if I could hide/show the
gpodder window by clicking on it. Getting current download status on

View file

@ -32,8 +32,8 @@ or played back on the user's desktop.
# PLEASE DO NOT CHANGE FORMAT OF __version__ LINE (setup.py reads this)
__author__ = "Thomas Perl <thp@perli.net>"
__version__ = "0.9.0+svn20070401"
__date__ = "2007-04-01"
__version__ = "0.9.0+svn20070402"
__date__ = "2007-04-02"
__copyright__ = "Copyright (c) 2005-2007 %s. All rights reserved." % __author__
__licence__ = "GPL"

View file

@ -2029,245 +2029,6 @@
</packing>
</child>
<child>
<widget class="GtkTable" id="table6">
<property name="border_width">10</property>
<property name="visible">True</property>
<property name="n_rows">6</property>
<property name="n_columns">2</property>
<property name="homogeneous">False</property>
<property name="row_spacing">5</property>
<property name="column_spacing">5</property>
<child>
<widget class="GtkLabel" id="label57">
<property name="visible">True</property>
<property name="label" translatable="yes">Download in progress:</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkColorButton" id="colorDownloading">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="use_alpha">False</property>
<property name="title" translatable="yes">Color for podcasts currently being downloaded</property>
<property name="focus_on_click">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label56">
<property name="visible">True</property>
<property name="label" translatable="yes">Default color:</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkColorButton" id="colorDefault">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="use_alpha">False</property>
<property name="title" translatable="yes">Default color for episodes list</property>
<property name="focus_on_click">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label59">
<property name="visible">True</property>
<property name="label" translatable="yes">Downloaded episodes:</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label58">
<property name="visible">True</property>
<property name="label" translatable="yes">Deleted episodes:</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkColorButton" id="colorDownloaded">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="use_alpha">False</property>
<property name="title" translatable="yes">Color for downloaded podcasts</property>
<property name="focus_on_click">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkColorButton" id="colorDeleted">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="use_alpha">False</property>
<property name="title" translatable="yes">Color for already downloaded but deleted podcasts</property>
<property name="focus_on_click">True</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkButton" id="btnRevertToDefault">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Revert to default colors</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_btnRevertToDefault_clicked" last_modification_time="Sun, 28 Jan 2007 09:12:05 GMT"/>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
</widget>
<packing>
<property name="tab_expand">False</property>
<property name="tab_fill">True</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label55">
<property name="visible">True</property>
<property name="label" translatable="yes">Colors</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="type">tab</property>
</packing>
</child>
<child>
<widget class="GtkTable" id="table5">
<property name="border_width">10</property>

View file

@ -113,35 +113,36 @@ class Gpodder(SimpleGladeApp):
self.comboAvailable.pack_start( cellrenderer, True)
self.comboAvailable.add_attribute( cellrenderer, 'text', 1)
# See http://www.pygtk.org/pygtk2tutorial/sec-CellRenderers.html
# enable alternating colors hint
self.treeAvailable.set_rules_hint( True)
iconcell = gtk.CellRendererPixbuf()
iconcolumn = gtk.TreeViewColumn( _("Status"), iconcell)
iconcolumn.add_attribute( iconcell, "icon-name", 4)
namecell = gtk.CellRendererText()
namecell.set_property('cell-background', 'white')
#namecell.set_property('ellipsize', pango.ELLIPSIZE_END)
namecolumn = gtk.TreeViewColumn( _("Episode"), namecell, text=1)
namecolumn.set_sizing( gtk.TREE_VIEW_COLUMN_AUTOSIZE)
namecolumn.add_attribute(namecell, "cell-background", 4)
sizecell = gtk.CellRendererText()
sizecell.set_property('cell-background', 'white')
sizecolumn = gtk.TreeViewColumn( _("Size"), sizecell, text=2)
sizecolumn.add_attribute(sizecell, "cell-background", 4)
releasecell = gtk.CellRendererText()
releasecell.set_property('cell-background', 'white')
releasecolumn = gtk.TreeViewColumn( _("Released"), releasecell, text=5)
releasecolumn.add_attribute(releasecell, "cell-background", 4)
desccell = gtk.CellRendererText()
desccell.set_property('cell-background', 'white')
desccell.set_property('ellipsize', pango.ELLIPSIZE_END)
desccolumn = gtk.TreeViewColumn( _("Description"), desccell, text=6)
desccolumn.add_attribute(desccell, "cell-background", 4)
for itemcolumn in ( namecolumn, sizecolumn, releasecolumn, desccolumn ):
for itemcolumn in ( iconcolumn, namecolumn, sizecolumn, releasecolumn, desccolumn ):
itemcolumn.set_resizable( True)
itemcolumn.set_reorderable( True)
self.treeAvailable.append_column( itemcolumn)
# enable search in treeavailable
self.treeAvailable.set_search_equal_func( self.treeAvailable_search_equal)
# enable multiple selection support
self.treeAvailable.get_selection().set_mode( gtk.SELECTION_MULTIPLE)
self.treeDownloads.get_selection().set_mode( gtk.SELECTION_MULTIPLE)
@ -191,6 +192,23 @@ class Gpodder(SimpleGladeApp):
#-- Gpodder.new }
#-- Gpodder custom methods {
def treeAvailable_search_equal( self, model, column, key, iter, data = None):
if model == None:
return True
key = key.lower()
# columns, as defined in libpodcasts' get model method
# 1 = episode title, 7 = description
columns = (1, 7)
for column in columns:
value = model.get_value( iter, column).lower()
if value.find( key) != -1:
return False
return True
def downloads_changed( self):
if self.wNotebook.get_current_page() == 0:
self.toolCancel.set_sensitive( False)
@ -1129,8 +1147,6 @@ class Gpodderproperties(SimpleGladeApp):
self.updatetags.set_sensitive( False)
new_label = '%s (%s)' % ( self.updatetags.get_label(), _('needs python-eyed3') )
self.updatetags.set_label( new_label)
# colors
self.reload_colors()
# device type
self.comboboxDeviceType.set_active( 0)
if gl.device_type == 'ipod':
@ -1152,22 +1168,6 @@ class Gpodderproperties(SimpleGladeApp):
#-- Gpodderproperties.new }
#-- Gpodderproperties custom methods {
def on_btnRevertToDefault_clicked( self, widget, *args):
gl = gPodderLib()
gl.set_default_colors()
self.reload_colors()
def reload_colors( self):
gl = gPodderLib()
try:
self.colorDefault.set_color( gtk.gdk.color_parse( gl.colors['default']))
self.colorDownloading.set_color( gtk.gdk.color_parse( gl.colors['downloading']))
self.colorDownloaded.set_color( gtk.gdk.color_parse( gl.colors['downloaded']))
self.colorDeleted.set_color( gtk.gdk.color_parse( gl.colors['deleted']))
except:
log( '(gPodderProperties) Could not parse color strings.')
def update_mountpoint( self, ipod):
if ipod == None or ipod.mount_point == None:
self.iPodMountpoint.set_label( '')
@ -1297,13 +1297,6 @@ class Gpodderproperties(SimpleGladeApp):
gl.ipod_mount = self.iPodMountpoint.get_label()
gl.mp3_player_folder = self.filesystemMountpoint.get_label()
gl.opml_url = self.opmlURL.get_text()
try:
gl.set_color( 'default', self.colorDefault.get_color())
gl.set_color( 'downloading', self.colorDownloading.get_color())
gl.set_color( 'downloaded', self.colorDownloaded.get_color())
gl.set_color( 'deleted', self.colorDeleted.get_color())
except:
log('(gPodderProperties) Could not parse and save color values.')
if gl.downloaddir != self.chooserDownloadTo.get_filename():
new_download_dir = self.chooserDownloadTo.get_filename()

View file

@ -251,11 +251,6 @@ class Gpodderproperties(SimpleGladeApp):
print "on_comboPlayerApp_changed called with self.%s" % widget.get_name()
#-- Gpodderproperties.on_comboPlayerApp_changed }
#-- Gpodderproperties.on_btnRevertToDefault_clicked {
def on_btnRevertToDefault_clicked(self, widget, *args):
print "on_btnRevertToDefault_clicked called with self.%s" % widget.get_name()
#-- Gpodderproperties.on_btnRevertToDefault_clicked }
#-- Gpodderproperties.on_comboboxDeviceType_changed {
def on_comboboxDeviceType_changed(self, widget, *args):
print "on_comboboxDeviceType_changed called with self.%s" % widget.get_name()

View file

@ -78,14 +78,6 @@ from ConfigParser import ConfigParser
from xml.sax import saxutils
# default colors for episodes list
default_colors = {
'default': '#FFFFFF',
'downloading': '#FFBC99',
'downloaded': '#99FF99',
'deleted': '#DDFFCC',
}
# global recursive lock for thread exclusion
globalLock = threading.RLock()
@ -112,8 +104,6 @@ class gPodderLibClass( object):
gpodderconf_section = 'gpodder-conf-1'
def __init__( self):
global default_colors
self.gpodderdir = expanduser( "~/.config/gpodder/")
self.createIfNecessary( self.gpodderdir)
self.__download_dir = None
@ -141,9 +131,6 @@ class gPodderLibClass( object):
self.main_window_x = 0
self.main_window_y = 0
self.mp3_player_folder = ""
self.colors = {}
for key in default_colors.keys():
self.colors[key] = default_colors[key]
self.__download_history = DownloadHistory( self.get_download_history_filename())
self.loadConfig()
@ -176,15 +163,6 @@ class gPodderLibClass( object):
# save settings for next startup
self.saveConfig()
def set_color( self, key, value):
# calculate hex value from gtk.gdk.Color object
self.colors[key] = '#%02x%02x%02x' % ( value.red*256/65536, value.green*256/65536, value.blue*256/65536, )
def set_default_colors( self):
global default_colors
for key in default_colors.keys():
self.colors[key] = default_colors[key]
def clean_up_downloads( self, delete_partial = False):
# Clean up temporary files left behind by old gPodder versions
if delete_partial:
@ -223,8 +201,6 @@ class gPodderLibClass( object):
self.write_to_parser( parser, 'main_window_x', self.main_window_x)
self.write_to_parser( parser, 'main_window_y', self.main_window_y)
self.write_to_parser( parser, 'mp3_player_folder', self.mp3_player_folder)
for color in self.colors.keys():
self.write_to_parser( parser, 'color_' + color, self.colors[color])
fn = self.getConfigFilename()
fp = open( fn, "w")
parser.write( fp)
@ -315,8 +291,6 @@ class gPodderLibClass( object):
log( 'write_to_parser: could not write config (option=%s, value=%s)', option, value)
def loadConfig( self):
global default_colors
was_oldstyle = False
try:
fn = self.getConfigFilename()
@ -348,8 +322,6 @@ class gPodderLibClass( object):
self.main_window_x = self.get_int_from_parser( parser, 'main_window_x', 0)
self.main_window_y = self.get_int_from_parser( parser, 'main_window_y', 0)
self.mp3_player_folder = self.get_from_parser( parser, 'mp3_player_folder', '/media/usbdisk')
for color in self.colors.keys():
self.colors[color] = self.get_from_parser( parser, 'color_'+color, default_colors[color])
else:
log( 'config file %s has no section %s', fn, gpodderconf_section)
if not self.proxy_use_environment:

View file

@ -239,26 +239,37 @@ class podcastChannel(ListType):
the URL of the episodes and returns True if the episode is currently
being downloaded and False otherwise.
"""
new_model = gtk.ListStore( gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_BOOLEAN, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
new_model = gtk.ListStore( gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_BOOLEAN, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
gl = libgpodder.gPodderLib()
last_pubdate = self.newest_pubdate_downloaded()
for item in self.get_all_episodes():
if self.is_downloaded( item) and want_color:
background_color = gl.colors['downloaded']
file_type = self.get_file_type( item)
if file_type == 'audio':
status_icon = 'audio-x-generic'
elif file_type == 'video':
status_icon = 'video-x-generic'
else:
status_icon = 'unknown'
elif downloading_callback and downloading_callback( item.url) and want_color:
background_color = gl.colors['downloading']
status_icon = gtk.STOCK_GO_DOWN
elif libgpodder.gPodderLib().history_is_downloaded( item.url) and want_color:
background_color = gl.colors['deleted']
status_icon = gtk.STOCK_DELETE
elif last_pubdate and item.compare_pubdate( last_pubdate) >= 0:
status_icon = 'document-new'
else:
background_color = gl.colors['default']
status_icon = None
new_iter = new_model.append()
new_model.set( new_iter, 0, item.url)
new_model.set( new_iter, 1, item.title)
new_model.set( new_iter, 2, item.getSize())
new_model.set( new_iter, 3, True)
new_model.set( new_iter, 4, background_color)
new_model.set( new_iter, 4, status_icon)
new_model.set( new_iter, 5, item.cute_pubdate())
new_model.set( new_iter, 6, item.one_line_description())
new_model.set( new_iter, 7, item.description)
return new_model
@ -351,6 +362,19 @@ class podcastChannel(ListType):
return os.path.join( self.save_dir, 'cover')
cover_file = property(fget=get_cover_file)
def get_file_type( self, item):
types = {
'audio': [ 'mp3', 'ogg', 'wav', 'wma', 'aac', 'm4a' ],
'video': [ 'mp4', 'avi', 'mpg', 'mpeg', 'm4v', 'mov' ]
}
extension = splitext( self.getPodcastFilename( item.url))[1][1:]
for type in types:
if extension in types[type]:
return type
return 'unknown'
def getPodcastFilename( self, url):
# strip question mark (and everything behind it), fix %20 errors