Merge lp:~mblayman/entertainer/bye-feedz into lp:entertainer

Proposed by Matt Layman
Status: Merged
Merged at revision: not available
Proposed branch: lp:~mblayman/entertainer/bye-feedz
Merge into: lp:entertainer
Diff against target: 6235 lines (+421/-4001)
53 files modified
Makefile (+0/-22)
cfg/content.conf (+0/-4)
docs/DEPENDENCIES (+2/-1)
entertainer (+0/-1)
entertainerlib/backend/backend_server.py (+6/-36)
entertainerlib/backend/components/feeds/__init__.py (+0/-2)
entertainerlib/backend/components/feeds/feed_fetcher.py (+0/-138)
entertainerlib/backend/components/feeds/feed_manager.py (+0/-100)
entertainerlib/backend/components/feeds/feed_utils.py (+0/-239)
entertainerlib/backend/core/message_type_priority.py (+3/-12)
entertainerlib/client/backend_connection.py (+0/-27)
entertainerlib/client/client.py (+4/-11)
entertainerlib/client/medialibrary/feeds.py (+0/-192)
entertainerlib/client/medialibrary/music.py (+2/-0)
entertainerlib/client/medialibrary/videos.py (+2/-1)
entertainerlib/client/translation_setup.py (+2/-3)
entertainerlib/configuration.py (+0/-12)
entertainerlib/db/models.py (+1/-53)
entertainerlib/dialog.py (+0/-298)
entertainerlib/download.py (+3/-3)
entertainerlib/gui/screens/factory.py (+2/-25)
entertainerlib/gui/screens/feed.py (+0/-102)
entertainerlib/gui/screens/feed_entry.py (+0/-112)
entertainerlib/gui/screens/main.py (+3/-101)
entertainerlib/gui/screens/rss.py (+0/-228)
entertainerlib/gui/user_interface.py (+6/-6)
entertainerlib/indexing/handlers.py (+28/-28)
entertainerlib/indexing/indexer.py (+3/-0)
entertainerlib/network/local/client.py (+7/-7)
entertainerlib/tests/data/FeedConfigTools/test.opml (+0/-19)
entertainerlib/tests/data/OPMLParser/lifereaMultiple/.liferea_1.4/feedlist.opml (+0/-1)
entertainerlib/tests/data/OPMLParser/lifereaSingle/.liferea/feedlist.opml (+0/-1)
entertainerlib/tests/data/OPMLParser/noXML.txt (+0/-1)
entertainerlib/tests/data/OPMLParser/opmlInOpml.opml (+0/-21)
entertainerlib/tests/data/OPMLParser/test.opml (+0/-20)
entertainerlib/tests/mock.py (+1/-77)
entertainerlib/tests/test_configuration.py (+0/-6)
entertainerlib/tests/test_feedconfigtools.py (+0/-69)
entertainerlib/tests/test_feedentryparser.py (+0/-49)
entertainerlib/tests/test_filehandlers.py (+1/-0)
entertainerlib/tests/test_frontendfeed.py (+0/-95)
entertainerlib/tests/test_frontendfeedentry.py (+0/-92)
entertainerlib/tests/test_frontendfeedlibrary.py (+0/-107)
entertainerlib/tests/test_models.py (+0/-45)
entertainerlib/tests/test_music.py (+8/-6)
entertainerlib/tests/test_opmlparser.py (+0/-103)
entertainerlib/tests/test_screenfactory.py (+6/-30)
entertainerlib/tests/test_userinterface.py (+1/-3)
entertainerlib/tests/test_videometadatasearch.py (+0/-1)
entertainerlib/uis/manager.ui (+330/-1251)
entertainerlib/uis/open_feed_source_dialog.ui (+0/-198)
themes/Black/theme.conf (+0/-19)
tools/loc.py (+0/-23)
To merge this branch: bzr merge lp:~mblayman/entertainer/bye-feedz
Reviewer Review Type Date Requested Status
Matt Layman Approve
Review via email: mp+22751@code.launchpad.net

Commit message

All feed code is now removed. Lots of pylint cleanup too.

Description of the change

This branch removes all the feed related logic. It is highly doubtful that anyone is using Entertainer as a feed reader and the maintenance burden for keeping that code is not worth it. Therefore, I'm getting rid of it to focus on core features of a media center (video, music, photo).

To post a comment you must log in.
Revision history for this message
Matt Layman (mblayman) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile'
2--- Makefile 2009-05-06 03:40:22 +0000
3+++ Makefile 2010-04-03 15:04:16 +0000
4@@ -12,16 +12,6 @@
5 CTAGS_FLAGS=-R -o ${CTAGS_FILENAME}
6 CTAGS_CLEAN=rm -f ${CTAGS_FILENAME}
7
8-DOCS_DIR=cd docs
9-DOCS_TEMP_DIR=docs
10-DOCS_CREATE_TEMP_DIR=if ! test -d "${DOCS_TEMP_DIR}"; then mkdir ${DOCS_TEMP_DIR}; fi
11-DOCS_PDF=pdflatex
12-DOCS_PDF_FLAGS=-output-directory=${DOCS_TEMP_DIR} -output-format=pdf
13-DOCS_HTML=latex2html
14-DOCS_HTML_FLAGS=-dir ${DOCS_TEMP_DIR}
15-DOCS_CLEAN=rm -rf docs entertainer-docs.tar.gz
16-DOCS_TAR=${DOCS_DIR}; tar -czf entertainer-docs.tar.gz docs
17-
18 TOOLS_DIR=cd tools
19 TRANSLATE= ${PYTHON} translations_generator.py
20
21@@ -43,17 +33,7 @@
22 tags:
23 ${CTAGS} ${CTAGS_FLAGS} entertainerlib
24
25-docs: docs-html docs-pdf
26- ${DOCS_TAR}
27-
28-docs-html:
29- ${DOCS_DIR};${DOCS_CREATE_TEMP_DIR};${DOCS_HTML} ${DOCS_HTML_FLAGS} user_guide.tex
30-
31-docs-pdf:
32- ${DOCS_DIR};${DOCS_CREATE_TEMP_DIR};${DOCS_PDF} ${DOCS_PDF_FLAGS} user_guide.tex
33-
34 clean:
35- ${DOCS_DIR};${DOCS_CLEAN}
36 ${CTAGS_CLEAN}
37
38 depgraph:
39@@ -62,5 +42,3 @@
40 cat /tmp/entertainer.deps | sfood-cluster -f /tmp/entertainer-clusters > /tmp/clustered
41 cat /tmp/clustered | sfood-graph -p | dot -T png > docs/entertainer-depgraph.png
42
43-
44-
45
46=== modified file 'cfg/content.conf'
47--- cfg/content.conf 2009-08-16 22:19:22 +0000
48+++ cfg/content.conf 2010-04-03 15:04:16 +0000
49@@ -10,10 +10,6 @@
50 location = Bath,England
51 display_in_menu = True
52
53-[RSS]
54-feeds = http://theironlion.net/blog/feed;http://www.joshuascotton.com/main/archives/tag/entertainer/feed;http://laymanstermsdev.wordpress.com/feed
55-fetch_interval = 15
56-
57 [CD]
58 display_eject_in_menu = False
59
60
61=== modified file 'docs/DEPENDENCIES'
62--- docs/DEPENDENCIES 2009-11-09 22:43:06 +0000
63+++ docs/DEPENDENCIES 2010-04-03 15:04:16 +0000
64@@ -1,9 +1,10 @@
65 python-cairo
66 python-cddb
67 python-clutter
68+python-cluttergst
69+python-cluttergtk
70 python-ctypes
71 python-eyed3
72-python-feedparser
73 python-gobject
74 python-gst0.10
75 python-gtk2
76
77=== removed file 'docs/developer_documentation.pdf'
78Binary files docs/developer_documentation.pdf 2008-12-14 19:58:40 +0000 and docs/developer_documentation.pdf 1970-01-01 00:00:00 +0000 differ
79=== removed file 'docs/entertainer-depgraph.png'
80Binary files docs/entertainer-depgraph.png 2009-02-01 19:35:11 +0000 and docs/entertainer-depgraph.png 1970-01-01 00:00:00 +0000 differ
81=== modified file 'entertainer'
82--- entertainer 2009-05-10 17:36:49 +0000
83+++ entertainer 2010-04-03 15:04:16 +0000
84@@ -1,7 +1,6 @@
85 #!/usr/bin/env python
86 # Copyright (c) 2009 Entertainer Developers - See COPYING - GPLv2
87 '''Main client executable'''
88-'''Main frontend executable'''
89
90 from entertainerlib.client import main
91
92
93=== modified file 'entertainerlib/backend/backend_server.py'
94--- entertainerlib/backend/backend_server.py 2009-09-08 02:02:58 +0000
95+++ entertainerlib/backend/backend_server.py 2010-04-03 15:04:16 +0000
96@@ -3,37 +3,20 @@
97
98 import gobject
99
100-from entertainerlib.configuration import Configuration
101-from entertainerlib.logger import Logger
102-
103-# Entertainer backend core
104-from entertainerlib.backend.core.message import Message
105+from entertainerlib.backend.components.mediacache.media_cache_manager import (
106+ MediaCacheManager)
107 from entertainerlib.backend.core.message_bus import MessageBus
108 from entertainerlib.backend.core.message_scheduler import MessageScheduler
109 from entertainerlib.backend.core.connection_server import ConnectionServer
110 from entertainerlib.backend.core.message_type_priority import (
111 MessageType, MessagePriority)
112-
113-# Entertainer backend components
114-from entertainerlib.backend.components.feeds.feed_manager import FeedManager
115-from entertainerlib.backend.components.mediacache.media_cache_manager import (
116- MediaCacheManager)
117+from entertainerlib.configuration import Configuration
118+from entertainerlib.logger import Logger
119
120 class BackendServer:
121- """
122- Entertainer backend server.
123-
124- This is a backend of Entertainer media center. Backend is responsible of
125- many vital things like updateing media library cache, recording scheduled
126- TV-shows, fetching RSS-feeds etc.
127- """
128+ '''Backend is responsible for things like updating media library cache.'''
129
130 def __init__(self):
131- """
132- Initialize backend
133-
134- This method creates and initializes all backend components.
135- """
136 gobject.threads_init()
137
138 self.config = Configuration()
139@@ -45,13 +28,11 @@
140 self.connection_server = None
141
142 self.scheduler = None
143- self.feed_manager = None
144 self.media_manager = None
145
146 # The order of the initialize method calls is significant! Don't change
147- # the order unless you know what your doing!
148+ # the order unless you know what you are doing!
149 self.initialize_configuration()
150- self.initialize_feed_manager()
151 self.initialize_media_cache_manager()
152 self.initialize_connection_server()
153 self.initialize_scheduler()
154@@ -73,19 +54,8 @@
155 def initialize_scheduler(self):
156 """Initialize message scheduler."""
157 self.scheduler = MessageScheduler(self.message_bus)
158- self.scheduler.addMessage(Message(MessageType.UPDATE_FEEDS),
159- 60 * self.config.feed_fetch_interval)
160 self.logger.debug("Message scheduler intialized successfully")
161
162- def initialize_feed_manager(self):
163- """Initialize feed manager."""
164- self.feed_manager = FeedManager(self.message_bus)
165- feed_mgr_dict = { MessageType.UPDATE_FEEDS : MessagePriority.HIGH,
166- MessageType.REBUILD_FEED_CACHE : MessagePriority.HIGH }
167- self.message_bus.registerMessageHandler(self.feed_manager,
168- feed_mgr_dict)
169- self.logger.debug("Feed Manager intialized successfully")
170-
171 def initialize_media_cache_manager(self):
172 '''Initialize the media cache manager'''
173 self.media_manager = MediaCacheManager()
174
175=== removed directory 'entertainerlib/backend/components/feeds'
176=== removed file 'entertainerlib/backend/components/feeds/__init__.py'
177--- entertainerlib/backend/components/feeds/__init__.py 2009-05-06 03:40:22 +0000
178+++ entertainerlib/backend/components/feeds/__init__.py 1970-01-01 00:00:00 +0000
179@@ -1,2 +0,0 @@
180-# Copyright (c) 2009 Entertainer Developers - See COPYING - GPLv2
181-'''Feed component'''
182
183=== removed file 'entertainerlib/backend/components/feeds/feed_fetcher.py'
184--- entertainerlib/backend/components/feeds/feed_fetcher.py 2009-05-10 17:36:49 +0000
185+++ entertainerlib/backend/components/feeds/feed_fetcher.py 1970-01-01 00:00:00 +0000
186@@ -1,138 +0,0 @@
187-# Copyright (c) 2009 Entertainer Developers - See COPYING - GPLv2
188-'''Update all feeds to local cache'''
189-
190-import threading
191-import feedparser
192-from time import strptime
193-from datetime import datetime
194-from pysqlite2 import dbapi2 as sqlite
195-
196-from entertainerlib.configuration import Configuration
197-from entertainerlib.logger import Logger
198-
199-# Messaging system
200-from entertainerlib.backend.core.message import Message
201-from entertainerlib.backend.core.message_type_priority import MessageType
202-
203-class FeedFetcher(threading.Thread):
204- """Update all feeds to the local feed cache database."""
205-
206- # Number of entries to keep in cache for each feed
207- NUMBER_OF_ENTRIES = 50
208-
209- def __init__(self, message_bus, feeds):
210- """
211- Create a new feed fetch thread
212- @param message_bus: MessageBus object
213- @param feeds: List of feeds (List of URL-strings)
214- """
215- threading.Thread.__init__(self)
216- self.setName("FeedFetcher")
217- self.message_bus = message_bus
218- self.logger = Logger().getLogger('backend.components.feed.FeedFetcher')
219- self.config = Configuration()
220- self.feeds = feeds
221-
222- def run(self):
223- """Update feed cache in a seperated thread"""
224- db_conn = sqlite.connect(self.config.FEED_DB)
225- db_cursor = db_conn.cursor()
226- for element in self.feeds:
227- if element:
228- has_new_entries = False
229- data = feedparser.parse(element)
230- if data.bozo:
231- self.logger.warning("Malformed feed skipped: " + element)
232- continue # move to the next feed
233- try:
234- dt = data.feed.date_parsed
235- last_update = datetime(dt[0], dt[1], dt[2],
236- dt[3], dt[4], dt[5])
237- except AttributeError:
238- dt = data.entries[0].date_parsed
239- last_update = datetime(dt[0], dt[1], dt[2],
240- dt[3], dt[4], dt[5])
241-
242- #Check if this feed has new entries
243- db_cursor.execute("""SELECT date,time
244- FROM feed
245- WHERE url=:url""",
246- { "url": data.feed.link})
247- result = db_cursor.fetchall()
248-
249- if(len(result) == 0):
250- # Set in past so that all entries are added to the database!
251- current_update = datetime(1970, 01, 01, 00, 00, 00)
252-
253- # This is a completely new feed
254- feed_row = (data.feed.link,
255- data.feed.title,
256- data.feed.subtitle,
257- data.channel.description,
258- last_update.strftime("%Y-%m-%d"),
259- last_update.strftime("%H:%M:%S"))
260- db_cursor.execute(
261- """INSERT INTO feed(url,title,subtitle,
262- description,date,time) VALUES (?,?,?,?,?,?)""", \
263- feed_row)
264- db_conn.commit()
265- has_new_entries = True
266- else:
267- # This feed is already in cache. Check if it has new entries
268- tmp = str(result[0][0]) + " " + str(result[0][1])
269- current_update = datetime(*strptime(tmp,
270- "%Y-%m-%d %H:%M:%S")[0:6])
271- if last_update > current_update:
272- db_cursor.execute(
273- "UPDATE feed SET date=?,time=? WHERE url=?",
274- (last_update.strftime("%Y-%m-%d"),
275- last_update.strftime("%H:%M:%S"), data.feed.link))
276- db_conn.commit()
277- has_new_entries = True
278-
279- # If this feed has new entries we update the cache
280- if has_new_entries:
281- for i in range(len(data.entries)):
282- ed = data.entries[i].date_parsed
283- e_timestamp = datetime(ed[0], ed[1], ed[2],
284- ed[3], ed[4], ed[5])
285-
286- # If entry is new (not cached in previous update)
287- if e_timestamp > current_update:
288- entry_row = (data.feed.link,
289- data.entries[i].title,
290- data.entries[i].description,
291- "NO", # This entry hasn't been read yet
292- data.entries[i].id,
293- e_timestamp.strftime("%Y-%m-%d"),
294- e_timestamp.strftime("%H:%M:%S"))
295- db_cursor.execute("""INSERT INTO
296- entry(feed_url,title,description,isread,id,date,time)
297- VALUES (?,?,?,?,?,?,?)""", entry_row)
298- db_conn.commit()
299-
300- # Remove old entries from cache if there are
301- # more entries than limit allows
302- db_cursor.execute("""SELECT date, time
303- FROM entry
304- WHERE feed_url=:url
305- ORDER BY date, time""",
306- { "url" : data.feed.link})
307- result = db_cursor.fetchall()
308- if len(result) > self.NUMBER_OF_ENTRIES:
309- limit_date = result[self.NUMBER_OF_ENTRIES][0]
310- limit_time = result[self.NUMBER_OF_ENTRIES][1]
311- db_cursor.execute("""DELETE FROM entry
312- WHERE feed_url=:url
313- AND date < :date
314- AND time < :time""",
315- { "url" : str(data.feed.link),
316- "date" : str(limit_date) ,
317- "time": str(limit_time)})
318- db_conn.commit()
319-
320- # Notify that feed database has been updated
321- db_conn.close()
322- self.logger.info("Feed cache has been updated")
323- self.message_bus.notifyMessage(Message(MessageType.FEED_DB_UPDATED))
324-
325
326=== removed file 'entertainerlib/backend/components/feeds/feed_manager.py'
327--- entertainerlib/backend/components/feeds/feed_manager.py 2009-08-16 23:01:49 +0000
328+++ entertainerlib/backend/components/feeds/feed_manager.py 1970-01-01 00:00:00 +0000
329@@ -1,100 +0,0 @@
330-# Copyright (c) 2009 Entertainer Developers - See COPYING - GPLv2
331-'''FeedManager - Manage feeds'''
332-
333-import os
334-from pysqlite2 import dbapi2 as sqlite
335-from entertainerlib.backend.components.feeds.feed_fetcher import FeedFetcher
336-
337-from entertainerlib.configuration import Configuration
338-from entertainerlib.logger import Logger
339-
340-# Messaging system
341-from entertainerlib.backend.core.message_type_priority import MessageType
342-from entertainerlib.backend.core.message_handler import MessageHandler
343-
344-class FeedManager(MessageHandler):
345- """Backend feed manager keeps feeds cache database updated."""
346-
347- def __init__(self, message_bus):
348- """
349- Create a new FeedManager object
350- @param message_bus: MessageBus object
351- """
352- self.message_bus = message_bus
353- self.logger = Logger().getLogger(
354- 'backend.components.feeds.FeedManager')
355- self.config = Configuration()
356-
357- if not os.path.exists(self.config.FEED_DB):
358- self.createFeedCacheDatabase()
359- MessageHandler.__init__(self)
360- self.updateFeedCache()
361-
362- def updateFeedCache(self):
363- """
364- Update all feeds to cache in a new thread and after
365- that emit FEED_DB_UPDATED message to the messagebus.
366- """
367- fetch_thread = FeedFetcher(self.message_bus, self.config.feeds)
368- fetch_thread.start()
369-
370- def createFeedCacheDatabase(self):
371- """Create a feed cache database file and tables."""
372- db_conn = sqlite.connect(self.config.FEED_DB)
373- db_cursor = db_conn.cursor()
374- db_cursor.execute("""CREATE TABLE feed(
375- url TEXT,
376- title TEXT,
377- subtitle TEXT,
378- description TEXT,
379- time TIME,
380- date DATE,
381- PRIMARY KEY(url))""")
382-
383- db_cursor.execute("""CREATE TABLE entry(
384- feed_url TEXT,
385- title TEXT,
386- description TEXT,
387- isread TEXT,
388- time TIME,
389- date DATE,
390- id TEXT,
391- PRIMARY KEY(id))""")
392- db_conn.commit()
393- db_conn.close()
394-
395- def wipeFeedCacheDatabase(self):
396- """Wipes the feed cache database file and tables."""
397- # all we need to do to wipe the cache database is to drop the two
398- # tables containing the data: feed and entry
399- db_conn = sqlite.connect(self.config.FEED_DB)
400- db_cursor = db_conn.cursor()
401- db_cursor.execute("""DROP TABLE IF EXISTS feed""")
402- db_cursor.execute("""DROP TABLE IF EXISTS entry""")
403- db_conn.commit()
404- db_conn.close()
405-
406- # Implementes MessageHandler interface
407- def handleMessage(self, message):
408- """
409- Handle the received message
410- @param message: Received Message object
411- """
412- if message.get_type() == MessageType.UPDATE_FEEDS:
413- self.updateFeedCache()
414- elif message.get_type() == MessageType.REBUILD_FEED_CACHE:
415- #rebuild feed cache
416- self.rebuildFeedCacheDatabase()
417-
418- def rebuildFeedCacheDatabase(self):
419- """Destroy all current data and index everything from the scratch."""
420- self.logger.info("Feed cache rebuilding requested")
421- # we remove the tables from the database the create them again,
422- # this wipes the tables
423- self.wipeFeedCacheDatabase()
424- self.createFeedCacheDatabase()
425- # there will be no data in the tables so we need to populate
426- # the feed cache
427- self.updateFeedCache()
428- self.logger.info("Feed cache rebuilt")
429-
430
431=== removed file 'entertainerlib/backend/components/feeds/feed_utils.py'
432--- entertainerlib/backend/components/feeds/feed_utils.py 2009-11-11 10:12:34 +0000
433+++ entertainerlib/backend/components/feeds/feed_utils.py 1970-01-01 00:00:00 +0000
434@@ -1,239 +0,0 @@
435-# Copyright (c) 2009 Entertainer Developers - See COPYING - GPLv2
436-'''Utilities for fetching feeds'''
437-
438-import os
439-import urllib
440-from xml.dom import minidom
441-
442-import gtk
443-
444-from entertainerlib.configuration import Configuration
445-
446-
447-class FeedEntryParser:
448- """Will handle encoding and html for displaying feed entries"""
449-
450- def strip_tags(self, text, valid_tags=None):
451- """
452- Strips a text string of all markup tags except the tags specified
453- @param text the text to be stripped
454- @param valid_tags a list of the allowed tags
455- """
456-
457- #setup variables
458- valid_tag_list = []
459- output = ""
460- in_tag = False
461- in_tag_name = False
462- tag = ""
463- tag_attributes = ""
464-
465- if valid_tags is None:
466- valid_tags = []
467-
468- #append closing tags to tag list
469- for next_tag in valid_tags:
470- valid_tag_list.append(next_tag)
471- valid_tag_list.append("/"+next_tag)
472-
473- #setup a list to parse from input
474- parse_list = list(text)
475-
476- i = 0
477- while i < len(parse_list):
478- c = parse_list[i]
479- if c == "<":
480- #we are into the tag and the tag name
481- in_tag = True
482- in_tag_name = True
483- parse_list.pop(i)
484- elif in_tag:
485- #we are in a tag
486- if c == " " and in_tag_name:
487- #tag name has ended we are now into tag_attributes
488- in_tag_name = False
489- tag_attributes += parse_list.pop(i)
490- elif c == ">":
491- #tag has finished let's clean up
492- in_tag = False
493- parse_list.pop(i)
494- #check if tag matches
495- if tag in valid_tag_list:
496- output += ("<" + tag + tag_attributes + ">")
497- tag = ""
498- tag_attributes = ""
499- elif in_tag_name:
500- #we are in a tag name lets append current char to tag
501- tag += parse_list.pop(i)
502- else:
503- #we are in tag attributes lets append current char to
504- #attributes
505- tag_attributes += parse_list.pop(i)
506- else:
507- #not in a tag so append current char to output
508- output += parse_list.pop(i)
509-
510- return output
511-
512- def strip_non_pango_tags(self, text):
513- """
514- Strips a text string of all non-pango tags
515- @param text the text to be stripped
516- """
517- return self.strip_tags(text,
518- ["span", "b", "big", "i", "s", "sub", "sup", "small", "tt", "u"])
519-
520- def convert(self, text):
521- """
522- This converts a text string into a format acceptable by a clutter
523- label object
524-
525- @param text the text to be converted
526- """
527-
528- return self.strip_non_pango_tags(text).replace('&nbsp;', ' ')
529-
530-
531-class OPMLParser:
532- """Enables handling and parsing of opml files"""
533-
534- def get_rss_feeds(self, filename):
535- """
536- returns list of rss feeds in the opml file
537- @param filename The OPML file
538- @return list(String) List of RSS feed urls
539- """
540- feeds = []
541- if os.path.isfile(filename):
542- #this loads the xml from the opml file into xmldoc
543- xmldoc = minidom.parse(filename)
544- else:
545- xmldoc = minidom.parse(urllib.urlopen(filename))
546- #the rss feeds are in the xmlUrl attributes of the outline tags
547- #we loop through all the outline nodes in the opml file and add
548- #the contents of any xmlUrl attributes to the feeds variable
549- for node in xmldoc.getElementsByTagName('outline'):
550- url = node.getAttribute('xmlUrl')
551- #drop any items which are .opml files or empty string
552- #We do not recursively parse opml links as we could end up with an
553- #infinite loop
554- if (url.strip() != "") and ((url.strip() [-5:]) != ".opml"):
555- feeds.append(url)
556- #returns the list of rss feeds from the opml file
557- return feeds
558-
559- def get_liferea_opml(self, home_dir=os.path.expanduser("~")):
560- """
561- this returns either a empty string or the path to the current liferea
562- opml file
563-
564- @param home_dir String defaults to ~
565- @return String Path to opml file
566- """
567- #we'll be storing the latest liferea config folder in path and the
568- #version number, if any, in curVersion
569- path = ""
570- curVersion = float(0.0)
571-
572- #loop through home and pick out any config folders matching .liferea*
573- filenames = [filename for filename in os.listdir(home_dir)
574- if filename.startswith(".liferea")]
575-
576- if (len(filenames) <= 0):
577- #if there aren't any folders return an empty string
578- return ""
579- elif (len(filenames) == 1):
580- #if there's only 1 path found set it as the path
581- path = filenames[0]
582- else:
583- #in this case we have multiple posibilities
584- #liferea will store the config folder as .liferea or .liferea_9.9
585- #with 9.9 being the version number
586- #all we have todo is pick the largest version number or just the
587- #.liferea folder in that older
588- for fname in filenames:
589- if (fname [-3:] == "rea"):
590- if (curVersion == 0.0):
591- path = fname
592- elif (float(fname [-3:])> curVersion):
593- curVersion = float(fname [-3:])
594- path = fname
595-
596- #check if the path variable gives us a valid path and return it if it
597- #does or an empty string if it doesn't
598- if os.path.isfile(home_dir + "/" + path + "/feedlist.opml"):
599- return home_dir + "/" + path + "/feedlist.opml"
600- else:
601- return ""
602-
603-class FeedConfigTools:
604- """Enables Handling of Feed Config Widgets"""
605-
606- def __init__(self):
607- """Initialize to get access to the Configuration object"""
608- self.config = Configuration()
609-
610- def add_file_feeds_to_widget(self, files, model, feeds, check=True):
611- """
612- This changes the input values so that the feeds in the files update
613- the other inputs
614-
615- @param files list(String)
616- @param model GTKModel?
617- @param feeds list(String)
618- """
619- feed_list = []
620- for opml_file in files:
621- #get the list of feeds from each file
622- opml_feeds = OPMLParser().get_rss_feeds(opml_file)
623- #add the feeds to the rss_list
624- for feed in opml_feeds:
625- feed_list.append(feed)
626- #only check if check is set to True
627- if(check):
628- #check if the user really wants to add
629- dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL,
630- gtk.MESSAGE_WARNING, gtk.BUTTONS_OK_CANCEL,
631- "This will add " + str(len(feed_list)) +
632- " feeds to your feed list. Continue?")
633-
634- status = dialog.run()
635- #If user has ok'd the request we can now add the feeds properly,
636- #else leave it
637- if(status == gtk.RESPONSE_OK):
638- #now we need append the feeds to self.feeds and content manager
639- self.add_feeds_to_widget(feed_list, model, feeds)
640- dialog.destroy()
641- else:
642- #now we need append the feeds to self.feeds and content manager
643- self.add_feeds_to_widget(feed_list, model, feeds)
644-
645- def add_feeds_to_widget(self, feed_list, model, feeds):
646- """
647- This changes the input values so that the feeds in feed_list update
648- the other inputs
649-
650- @param feed_list list(String)
651- @param model GTKModel?
652- @param feeds list(String)
653- """
654- try:
655- for feed in feed_list:
656- #drop any items which are .opml files
657- #We do not recursively parse opml links as we could end up
658- #with an infinite loop
659- if (feed [-5:]) != ".opml":
660- #this is adding the feed to the content manager widget
661- model.append([feed])
662- feeds.append(feed)
663- #now we can parse the new feeds and add them
664- str_folders = ";".join(feeds)
665- self.config.write_content_value("RSS", "feeds", str_folders)
666- except IOError:
667- #Catching IOError
668- error = gtk.MessageDialog(None, gtk.DIALOG_MODAL,
669- gtk.MESSAGE_ERROR, gtk.BUTTONS_OK,
670- "IOError: There seems to be a problem with your selection.")
671- error.run()
672- error.destroy()
673-
674
675=== modified file 'entertainerlib/backend/core/message_type_priority.py'
676--- entertainerlib/backend/core/message_type_priority.py 2009-09-08 00:53:03 +0000
677+++ entertainerlib/backend/core/message_type_priority.py 2010-04-03 15:04:16 +0000
678@@ -21,21 +21,12 @@
679 # Indicates that Content Management UI has been used to update contents.
680 CONTENT_CONF_UPDATED = 0
681
682- # Indicates that Feed cache has been updated.
683- FEED_DB_UPDATED = 1
684-
685- # Indicates that Feed cache should be updated.
686- UPDATE_FEEDS = 2
687-
688 # Require to rebuild image cache
689- REBUILD_IMAGE_CACHE = 3
690+ REBUILD_IMAGE_CACHE = 1
691
692 # Require to rebuild music cache
693- REBUILD_MUSIC_CACHE = 4
694+ REBUILD_MUSIC_CACHE = 2
695
696 # Require to rebuild video cache
697- REBUILD_VIDEO_CACHE = 5
698-
699- # Require to rebuild feed cache
700- REBUILD_FEED_CACHE = 6
701+ REBUILD_VIDEO_CACHE = 3
702
703
704=== removed file 'entertainerlib/client/backend_connection.py'
705--- entertainerlib/client/backend_connection.py 2009-09-08 02:40:16 +0000
706+++ entertainerlib/client/backend_connection.py 1970-01-01 00:00:00 +0000
707@@ -1,27 +0,0 @@
708-# Copyright (c) 2009 Entertainer Developers - See COPYING - GPLv2
709-'''Connection to the Entertainer backend'''
710-
711-from entertainerlib.backend.core.message import Message
712-from entertainerlib.backend.core.message_bus_proxy import MessageBusProxy
713-from entertainerlib.backend.core.message_type_priority import MessageType
714-from entertainerlib.backend.core.message_handler import MessageHandler
715-
716-class BackendConnection(MessageHandler):
717- """Connection to the Entertainer backend messagebus."""
718-
719- def __init__(self):
720- MessageHandler.__init__(self)
721- messages = {}
722- name = "Entertainer Frontend"
723- self.message_bus_proxy = MessageBusProxy(messages, self, name)
724- self.message_bus_proxy.connectToMessageBus()
725- self.message_bus_proxy.start()
726-
727- def close_connection(self):
728- """Close connection to backend"""
729- self.message_bus_proxy.disconnectFromMessageBus()
730-
731- def request_feed_update(self):
732- """Request backend to fetch all feeds from the Internet."""
733- self.message_bus_proxy.sendMessage(Message(MessageType.UPDATE_FEEDS))
734-
735
736=== modified file 'entertainerlib/client/client.py'
737--- entertainerlib/client/client.py 2010-01-03 22:58:00 +0000
738+++ entertainerlib/client/client.py 2010-04-03 15:04:16 +0000
739@@ -10,8 +10,6 @@
740 from twisted.internet.protocol import ClientCreator
741 from twisted.python.log import startLogging
742
743-from entertainerlib.client.backend_connection import BackendConnection
744-from entertainerlib.client.medialibrary.feeds import FeedLibrary
745 from entertainerlib.client.medialibrary.music import MusicLibrary
746 from entertainerlib.client.medialibrary.images import ImageLibrary
747 from entertainerlib.client.medialibrary.videos import VideoLibrary
748@@ -21,20 +19,17 @@
749 from entertainerlib.network.local.client import EntertainerLocalClientProtocol
750
751
752-class Client:
753- '''This is a client application of the Entertainer. Entertainer's client
754+class Client(object):
755+ '''This is a client application of Entertainer. Entertainer's client
756 hooks into the server, and then provides a user interface for the data the
757 server creates.'''
758
759 def __init__(self):
760 config = Configuration()
761- self.backend_connection = BackendConnection()
762- feed_library = FeedLibrary(self.backend_connection)
763 music_library = MusicLibrary()
764 image_library = ImageLibrary()
765 video_library = VideoLibrary()
766- self.ui = UserInterface(
767- feed_library, image_library, music_library, video_library,
768+ self.ui = UserInterface(image_library, music_library, video_library,
769 self.quit_client)
770
771 if config.tray_icon_enabled:
772@@ -56,9 +51,7 @@
773 gtk.gdk.threads_leave()
774
775 def quit_client(self):
776- '''Clean up the connection to the backend then close the client.'''
777- self.backend_connection.close_connection()
778-
779+ '''Close the client.'''
780 reactor.stop()
781 sys.exit(0)
782
783
784=== removed file 'entertainerlib/client/medialibrary/feeds.py'
785--- entertainerlib/client/medialibrary/feeds.py 2009-07-29 03:09:34 +0000
786+++ entertainerlib/client/medialibrary/feeds.py 1970-01-01 00:00:00 +0000
787@@ -1,192 +0,0 @@
788-# Copyright (c) 2009 Entertainer Developers - See COPYING - GPLv2
789-'''FeedLibrary - Library for RSS-feeds'''
790-
791-from pysqlite2 import dbapi2 as sqlite
792-
793-from entertainerlib.configuration import Configuration
794-
795-class FeedLibrary(object):
796- '''This library can be used to handle RSS feeds in Entertainer.'''
797-
798- def __init__(self, backend_connection):
799- self.config = Configuration()
800-
801- self.backend_connection = backend_connection
802- self.empty = False
803- if self.number_of_feeds() == 0:
804- self.empty = True
805-
806- def is_empty(self):
807- '''Boolean used to indicated if the feed library is empty.'''
808- return self.empty
809-
810- def get_feeds(self, order='TITLE'):
811- '''Return a list of Feed objects from the library based on the order of
812- TITLE or UNREAD.'''
813- if self.is_empty():
814- return []
815- else:
816- feeds = []
817- connection = sqlite.connect(self.config.FEED_DB)
818- cursor = connection.cursor()
819- cursor.execute("SELECT url FROM feed ORDER BY title")
820- for row in cursor:
821- feeds.append(Feed(row[0]))
822- connection.close()
823- if order == "UNREAD":
824- feeds.sort(self.compare_feeds_by_unread)
825- return feeds
826-
827- def compare_feeds_by_unread(self, feed_x, feed_y):
828- '''Compare which feed has more unread and return a value that follows
829- Python's cmp convention of +, 0, or -.'''
830- return cmp(
831- feed_y.get_number_of_unread(),
832- feed_x.get_number_of_unread())
833-
834- def get_latest_entries(self, max_return=10):
835- '''Return the latest entries as a list of tuples with each tuple
836- containing a Feed object and an Entry object.'''
837- if self.is_empty():
838- return []
839- else:
840- latest = []
841- connection = sqlite.connect(self.config.FEED_DB)
842- cursor = connection.cursor()
843- cursor.execute("""SELECT DISTINCT feed.url, entry.id
844- FROM feed, entry
845- WHERE entry.feed_url = feed.url
846- ORDER BY entry.date DESC, entry.time DESC
847- LIMIT 0,:max""",
848- { "max" : max_return } )
849- for row in cursor:
850- feed = Feed(row[0])
851- entry = feed.get_entry(row[1])
852- latest.append((feed, entry))
853- connection.close()
854- return latest
855-
856- def number_of_feeds(self):
857- '''Return the number of feeds in the library.'''
858- if self.is_empty():
859- return 0
860- else:
861- connection = sqlite.connect(self.config.FEED_DB)
862- cursor = connection.cursor()
863- cursor.execute("SELECT COUNT(url) FROM feed")
864- result = cursor.fetchall()
865- connection.close()
866- return result[0][0]
867-
868- def number_of_unread_entries(self):
869- '''Return the number of unread entries.'''
870- if self.is_empty():
871- return 0
872- else:
873- connection = sqlite.connect(self.config.FEED_DB)
874- cursor = connection.cursor()
875- cursor.execute(
876- """SELECT COUNT(feed_url) FROM entry WHERE isread='NO'""")
877- result = cursor.fetchall()
878- connection.close()
879- return result[0][0]
880-
881- def request_feed_update(self):
882- '''Request backend to fetch and update all the feeds.'''
883- self.backend_connection.request_feed_update()
884-
885- def mark_all_as_read(self):
886- '''Mark all feed entries as read.'''
887- for feed in self.get_feeds():
888- for entry in feed.entries:
889- entry.read = True
890-
891-
892-class Feed(object):
893- '''Representation of a RSS feed.'''
894-
895- def __init__(self, url):
896- self.config = Configuration()
897-
898- self.url = url
899- self.entries = []
900- connection = sqlite.connect(self.config.FEED_DB)
901- cursor = connection.cursor()
902- cursor.execute("""SELECT title, subtitle, description, time, date
903- FROM feed
904- WHERE url=:url""",
905- { "url" : self.url })
906- result = cursor.fetchall()
907- self.title = result[0][0]
908- self.subtitle = result[0][1]
909- self.description = result[0][2]
910- self.time = result[0][3]
911- self.date = result[0][4]
912- cursor.execute("""SELECT title, description, id, time, date, isread
913- FROM entry
914- WHERE entry.feed_url=:url
915- ORDER BY date DESC, time DESC""",
916- { "url" : self.url })
917- for row in cursor:
918- if row[5] == "YES":
919- isread = True
920- else:
921- isread = False
922- self.entries.append(
923- Entry(row[0], row[1], row[2], row[3], row[4], isread))
924- connection.close()
925-
926- def get_entry(self, identifier):
927- '''Return an entry with the provided identifier.'''
928- for entry in self.entries:
929- if entry.identifier == identifier:
930- return entry
931-
932- def get_number_of_unread(self):
933- '''Return the number of unread entries.'''
934- connection = sqlite.connect(self.config.FEED_DB)
935- cursor = connection.cursor()
936- cursor.execute("""SELECT COUNT(feed_url)
937- FROM entry
938- WHERE isread='NO'
939- AND feed_url=:url""",
940- { "url" : self.url })
941- result = cursor.fetchall()
942- connection.close()
943- return int(result[0][0])
944-
945-
946-class Entry(object):
947- '''Representation of an individual RSS feed entry.'''
948-
949- def __init__(self, title, description, identifier, time, date, read=False):
950- self.config = Configuration()
951- self.title = title
952- self.description = description
953- self.identifier = identifier
954- self.time = time
955- self.date = date
956- self._read = read
957-
958- def _get_read(self):
959- '''Get the read property.'''
960- return self._read
961-
962- def _set_read(self, read):
963- '''Set the read property and update the database.'''
964- self._read = read
965-
966- if read:
967- readval = "YES"
968- else:
969- readval = "NO"
970- connection = sqlite.connect(self.config.FEED_DB)
971- cursor = connection.cursor()
972- cursor.execute(
973- """UPDATE entry SET isread=:val WHERE id=:id""",
974- {"val" : readval, "id" : self.identifier})
975- connection.commit()
976- connection.close()
977-
978- read = property(_get_read, _set_read)
979-
980
981=== modified file 'entertainerlib/client/medialibrary/music.py'
982--- entertainerlib/client/medialibrary/music.py 2010-01-03 22:58:00 +0000
983+++ entertainerlib/client/medialibrary/music.py 2010-04-03 15:04:16 +0000
984@@ -171,6 +171,7 @@
985
986 def __init__(self, filename, title, number, artist, album, year, length,
987 lyrics, create_album_callback):
988+ Playable.__init__(self)
989
990 # Check that these fields are integers
991 for field in [number, year, length]:
992@@ -318,6 +319,7 @@
993 '''Representation of a CD track.'''
994
995 def __init__(self, number, title, length):
996+ Playable.__init__(self)
997 self.title = title
998 self.uri = "cdda://" + str(number)
999 self.length = length
1000
1001=== modified file 'entertainerlib/client/medialibrary/videos.py'
1002--- entertainerlib/client/medialibrary/videos.py 2009-09-08 02:40:16 +0000
1003+++ entertainerlib/client/medialibrary/videos.py 2010-04-03 15:04:16 +0000
1004@@ -4,10 +4,10 @@
1005 import os
1006 from pysqlite2 import dbapi2 as sqlite
1007
1008+from entertainerlib.client.medialibrary.playable import Playable
1009 from entertainerlib.configuration import Configuration
1010 from entertainerlib.logger import Logger
1011
1012-from entertainerlib.client.medialibrary.playable import Playable
1013
1014 class VideoLibrary:
1015 """Interface for Entertainer's video cache."""
1016@@ -120,6 +120,7 @@
1017
1018 def __init__(self):
1019 """Initialize the VideoItem object"""
1020+ Playable.__init__(self)
1021 self.config = Configuration()
1022
1023 #Setting default values
1024
1025=== modified file 'entertainerlib/client/translation_setup.py'
1026--- entertainerlib/client/translation_setup.py 2009-11-11 10:22:36 +0000
1027+++ entertainerlib/client/translation_setup.py 2010-04-03 15:04:16 +0000
1028@@ -1,11 +1,10 @@
1029 # Copyright (c) 2009 Entertainer Developers - See COPYING - GPLv2
1030 '''Translation Setup Code'''
1031
1032+import gettext
1033 import locale
1034 import os
1035
1036-import gettext
1037-import gtk
1038 from xdg import BaseDirectory
1039
1040 class TranslationSetup:
1041@@ -27,7 +26,7 @@
1042 # this hack it's really needed.
1043 try:
1044 locale.setlocale(locale.LC_ALL, "")
1045- except locale.Error, e:
1046+ except locale.Error:
1047 pass
1048
1049 # Find locale data from a dev branch if we can
1050
1051=== modified file 'entertainerlib/configuration.py'
1052--- entertainerlib/configuration.py 2009-08-27 03:18:41 +0000
1053+++ entertainerlib/configuration.py 2010-04-03 15:04:16 +0000
1054@@ -38,7 +38,6 @@
1055
1056 self.MEDIA_DB = Database(os.path.join(self.cache_dir, 'media'))
1057
1058- self.FEED_DB = os.path.join(self.cache_dir, 'feed.db')
1059 self.IMAGE_DB = os.path.join(self.cache_dir, 'image.db')
1060 self.MUSIC_DB = os.path.join(self.cache_dir, 'music.db')
1061 self.VIDEO_DB = os.path.join(self.cache_dir, 'video.db')
1062@@ -133,11 +132,6 @@
1063 return self.content.getboolean("General", "display_icon")
1064
1065 @property
1066- def feed_fetch_interval(self):
1067- '''Time interval (in minutes) for feed fetching.'''
1068- return self.content.getint("RSS", "fetch_interval")
1069-
1070- @property
1071 def port(self):
1072 '''Server's port number.'''
1073 return self.content.getint("General", "backend_port")
1074@@ -149,12 +143,6 @@
1075 return self._is_valid_media_folder(media.split(';'))
1076
1077 @property
1078- def feeds(self):
1079- '''List of feeds.'''
1080- rss_feeds = self.content.get("RSS", "feeds")
1081- return rss_feeds.split(';')
1082-
1083- @property
1084 def weather_location(self):
1085 '''User's weather location.'''
1086 return self.content.get("Weather", "location")
1087
1088=== modified file 'entertainerlib/db/models.py'
1089--- entertainerlib/db/models.py 2009-06-17 02:53:31 +0000
1090+++ entertainerlib/db/models.py 2010-04-03 15:04:16 +0000
1091@@ -3,7 +3,7 @@
1092 # pylint: disable-msg=W0621,W0223
1093
1094 from storm.base import Storm
1095-from storm.properties import Bool, DateTime, Int, Unicode
1096+from storm.properties import DateTime, Int, Unicode
1097 from storm.references import Reference, ReferenceSet
1098
1099
1100@@ -14,58 +14,6 @@
1101 '''Convert model into a static dict.'''
1102 raise NotImplementedError
1103
1104-class NewsFeed(BaseModel):
1105- '''A source url for news'''
1106-
1107- __storm_table__ = 'newsfeed'
1108- id = Int(primary=True)
1109- url = Unicode()
1110- title = Unicode()
1111- description = Unicode()
1112- entries = ReferenceSet('NewsFeed.id', 'NewsEntry.feed_id')
1113-
1114- def to_dict(self, recurse=True):
1115- '''See BaseModel.to_dict.'''
1116- ret = {
1117- 'id': self.id,
1118- 'url': self.url,
1119- 'title': self.title,
1120- 'description': self.description,
1121- }
1122- if recurse:
1123- ret['entries'] = [entry.to_dict(recurse=False)
1124- for entry in self.entries]
1125- return ret
1126-
1127-
1128-class NewsEntry(BaseModel):
1129- '''A news article'''
1130-
1131- __storm_table__ = 'newsentry'
1132- id = Int(primary=True)
1133- url = Unicode()
1134- title = Unicode()
1135- description = Unicode()
1136- creation_date = DateTime()
1137- is_read = Bool()
1138- feed_id = Int()
1139- feed = Reference(feed_id, 'NewsFeed.id')
1140-
1141- def to_dict(self, recurse=True):
1142- '''See BaseModel.to_dict.'''
1143- ret = {
1144- 'id': self.id,
1145- 'url': self.url,
1146- 'title': self.title,
1147- 'description': self.description,
1148- 'creation_date': self.creation_date,
1149- 'is_read': self.is_read,
1150- }
1151- if recurse:
1152- ret['feed_id'] = self.feed_id
1153- ret['feed'] = self.feed.to_dict(recurse=False)
1154- return ret
1155-
1156
1157 class PhotoAlbum(BaseModel):
1158 '''A photo group'''
1159
1160=== modified file 'entertainerlib/dialog.py'
1161--- entertainerlib/dialog.py 2009-11-13 16:25:41 +0000
1162+++ entertainerlib/dialog.py 2010-04-03 15:04:16 +0000
1163@@ -16,8 +16,6 @@
1164 from entertainerlib.configuration import Configuration
1165 from entertainerlib.logger import Logger
1166 from entertainerlib.gui.theme import Theme
1167-from entertainerlib.backend.components.feeds.feed_utils import (OPMLParser,
1168- FeedConfigTools)
1169 from entertainerlib.weather import Weather
1170
1171
1172@@ -52,8 +50,6 @@
1173 if (self.dialog):
1174 callback_dic = {
1175 # Dialog-wide callbacks
1176- "on_button_open_list_clicked" :
1177- self.on_button_open_list_clicked,
1178 "on_close_button_clicked" : self.on_close_button_clicked,
1179 "on_ManagerDialog_destroy" : self.on_dialog_closed,
1180
1181@@ -71,23 +67,6 @@
1182 "on_button_media_rebuild_clicked" :
1183 self.on_button_media_rebuild_clicked,
1184
1185- # Feed tab
1186- "on_button_add_feed_clicked" :
1187- self.on_button_add_feed_clicked,
1188- "on_button_remove_feed_clicked" :
1189- self.on_button_remove_feed_clicked,
1190- "on_button_edit_feed_clicked" :
1191- self.on_button_edit_feed_clicked,
1192- "on_fetch_interval_spinbutton_value_changed" :
1193- self.on_fetch_interval_spinbutton_value_changed,
1194- "on_url_dialog_delete_event" : self.on_url_dialog_delete_event,
1195- "on_url_dialog_ok_button_clicked" :
1196- self.on_url_dialog_ok_button_clicked,
1197- "on_url_dialog_cancel_button_clicked" :
1198- self.on_url_dialog_cancel_button_clicked,
1199- "on_button_feed_rebuild_clicked" :
1200- self.on_button_feed_rebuild_clicked,
1201-
1202 # Weather tab
1203 "on_button_add_weather_clicked" :
1204 self.on_button_add_weather_clicked,
1205@@ -253,68 +232,6 @@
1206 self.config.write_content_value("Media", "download_metadata",
1207 widget.get_active())
1208
1209- def on_button_add_feed_clicked(self, widget):
1210- """Opens add feed dialog. """
1211- widget = self.builder.get_object("treeview_feeds")
1212- url_dialog = self.builder.get_object("url_dialog")
1213- model = widget.get_model()
1214- # Open dialog
1215- url_dialog.set_title(_("Add RSS-feed"))
1216- status = url_dialog.run()
1217- # If folder was selected we add it to model and update config file
1218- if(status == gtk.RESPONSE_OK):
1219- model.append([self.url])
1220- self.feeds.append(self.url)
1221- str_folders = ";".join(self.feeds)
1222- self.config.write_content_value("RSS", "feeds", str_folders)
1223-
1224- def on_button_remove_feed_clicked(self, widget):
1225- """Remove currently selected reed from RSS-feeds"""
1226- widget = self.builder.get_object("treeview_feeds")
1227- model = widget.get_model()
1228- selection = widget.get_selection().get_selected()
1229- if selection[1] == None:
1230- return
1231- rm_folder = model.get_value(selection[1], 0)
1232- self.feeds.remove(rm_folder)
1233- str_folders = ";".join(self.feeds)
1234- self.config.write_content_value("RSS", "feeds", str_folders)
1235- model.remove(selection[1])
1236-
1237- def on_button_edit_feed_clicked(self, widget):
1238- """Edit currently selected feed"""
1239- widget = self.builder.get_object("treeview_feeds")
1240- url_dialog = self.builder.get_object("url_dialog")
1241- url_entry = self.builder.get_object("url_entry")
1242- model = widget.get_model()
1243- selection = widget.get_selection().get_selected()
1244- if selection[1] == None:
1245- return
1246- feed = model.get_value(selection[1], 0)
1247- url_entry.set_text(feed)
1248- url_dialog.set_title(_("Edit feed"))
1249- status = url_dialog.run()
1250- if status == gtk.RESPONSE_OK:
1251- # Update list model
1252- model.set_value(selection[1], 0, self.url)
1253- # Update configure file
1254- pos = self.feeds.index(feed)
1255- self.feeds.remove(feed)
1256- self.feeds.insert(pos, self.url)
1257- str_feeds = ";".join(self.feeds)
1258- self.config.write_content_value("RSS", "feeds", str_feeds)
1259-
1260- def on_button_open_list_clicked(self, widget):
1261- """Opens the open feed source dialog"""
1262- open_dialog = OpenFeedSourceDialog(
1263- self.builder.get_object("treeview_feeds"), self.feeds)
1264- open_dialog.dialog.connect("destroy",
1265- open_dialog.on_closeButton_clicked)
1266-
1267- def on_fetch_interval_spinbutton_value_changed(self, widget):
1268- self.config.write_content_value("RSS", "fetch_interval",
1269- widget.get_value_as_int())
1270-
1271 def on_spinbutton_slideshow_step_value_changed(self, widget):
1272 """Activation of slideshow effects"""
1273 self.config.write_content_value("Photographs", "slideshow_step",
1274@@ -328,32 +245,6 @@
1275 self.config.write_content_value("Media", "download_album_art",
1276 widget.get_active())
1277
1278- def on_url_dialog_ok_button_clicked(self, widget):
1279- """URL dialog OK button pressed. Sets self.url"""
1280- url_dialog = self.builder.get_object("url_dialog")
1281- url_entry = self.builder.get_object("url_entry")
1282- url_dialog.hide()
1283- self.url = url_entry.get_text()
1284- url_entry.set_text("")
1285- url_dialog.response(gtk.RESPONSE_OK)
1286-
1287- def on_url_dialog_cancel_button_clicked(self, widget):
1288- """URL dialog cancelled. Hides dialog"""
1289- url_dialog = self.builder.get_object("url_dialog")
1290- url_entry = self.builder.get_object("url_entry")
1291- url_dialog.hide()
1292- url_entry.set_text("")
1293- url_dialog.response(gtk.RESPONSE_CANCEL)
1294-
1295- def on_url_dialog_delete_event(self, widget, data):
1296- """Dialog's X clicked. Hides dialog"""
1297- url_dialog = self.builder.get_object("url_dialog")
1298- url_entry = self.builder.get_object("url_entry")
1299- url_dialog.hide()
1300- url_entry.set_text("")
1301- url_dialog.response(gtk.RESPONSE_CANCEL)
1302- return True
1303-
1304 def on_button_add_weather_clicked(self, widget):
1305 """
1306 Open location search dialog
1307@@ -489,35 +380,6 @@
1308 error.run()
1309 error.destroy()
1310
1311- def on_button_feed_rebuild_clicked(self, widget):
1312- """
1313- Rebuild feed cache requested
1314- @param widget: GTK-Widget
1315- """
1316- #We need the user to confirm the rebuild feed cache request
1317- dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING,
1318- gtk.BUTTONS_OK_CANCEL,
1319- _("This will completely remove any feed entries in the cache!"))
1320- status = dialog.run()
1321- #If user has ok'd the request send the message to the message bus
1322- if(status == gtk.RESPONSE_OK):
1323- try:
1324- proxy = MessageBusProxy(client_name = "Manager GUI")
1325- proxy.connectToMessageBus()
1326- proxy.sendMessage(Message(MessageType.REBUILD_FEED_CACHE))
1327- proxy.disconnectFromMessageBus()
1328- except socket.error:
1329- error = gtk.MessageDialog(
1330- None, gtk.DIALOG_MODAL,
1331- gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, _(
1332- "Entertainer backend is not running. "
1333- "Cache cannot be rebuilt."
1334- ))
1335- error.run()
1336- error.destroy()
1337-
1338- dialog.destroy()
1339-
1340 def on_theme_add_button_clicked(self, widget):
1341 """Add theme button clicked"""
1342 themelist = self.builder.get_object("theme_list")
1343@@ -654,31 +516,6 @@
1344 lyrics_checkbox = self.builder.get_object("lyrics_checkbox")
1345 lyrics_checkbox.set_active(self.config.download_lyrics)
1346
1347- # == RSS-feeds ==
1348- feedlist_widget = self.builder.get_object("treeview_feeds")
1349- feed_model = gtk.ListStore(str)
1350-
1351- rss_cell = gtk.CellRendererText()
1352- rss_column = gtk.TreeViewColumn(_("Feeds"), rss_cell, text=0)
1353- feedlist_widget.append_column(rss_column)
1354-
1355- self.feeds = self.config.feeds
1356-
1357- # Fill model with folders read from config file
1358- for i in range(len(self.feeds)):
1359- feed_model.insert(i, [self.feeds[i]])
1360-
1361- feedlist_widget.set_model(feed_model)
1362-
1363- # Interval spinner
1364- interval_spinner = self.builder.get_object("fetch_interval_spinbutton")
1365- interval_val = self.config.feed_fetch_interval
1366- if interval_val < 15:
1367- interval_val = 15
1368- elif interval_val > 900:
1369- interval_val = 900
1370- interval_spinner.set_value(interval_val)
1371-
1372 # == Weather ==
1373 locationlist_widget = self.builder.get_object("treeview_locations")
1374 location_model = gtk.ListStore(str)
1375@@ -976,138 +813,3 @@
1376 return [row[0], row[1], "INFO",
1377 row[2] + ": " + row[3][4:]]
1378
1379-
1380-class OpenFeedSourceDialog:
1381- '''Feed source reader dialog'''
1382-
1383- UI_DIR = os.path.join(os.path.dirname(__file__), "uis")
1384-
1385- widgets = None
1386- dialog = None
1387- tree_widget = None
1388- feeds = None
1389- url = None
1390-
1391- def __init__(self, the_widget, the_feeds):
1392- """initialises the gtk window and displays it"""
1393-
1394- #feeds is a pointer to a list of feeds from the config file
1395- self.feeds = the_feeds
1396-
1397- #needed so we can add feeds to the feed list widget
1398- self.tree_widget = the_widget
1399-
1400- # Load UI with gtk.Builder
1401- uifile = os.path.join(self.UI_DIR, "open_feed_source_dialog.ui")
1402- self.builder = gtk.Builder()
1403- self.builder.set_translation_domain('entertainer')
1404- self.builder.add_from_file(uifile)
1405-
1406- # Get content management dialog and bind signal callbacks
1407- self.dialog = self.builder.get_object("open_source_dialog")
1408- if (self.dialog):
1409- callback_dic = {
1410- "on_fileOpen_clicked" : self.on_fileOpen_clicked,
1411- "on_lifereaButton_clicked" : self.on_lifereaButton_clicked,
1412- "on_enterURL_clicked" : self.on_enterURL_clicked,
1413- "on_closeButton_clicked" : self.on_closeButton_clicked,
1414- "on_url_dialog_ok_button_clicked" :
1415- self.on_url_dialog_ok_button_clicked,
1416- "on_url_dialog_cancel_button_clicked" :
1417- self.on_url_dialog_cancel_button_clicked,
1418- "on_url_dialog_delete_event" : self.on_url_dialog_delete_event,
1419- "on_destroy" : self.on_closeButton_clicked
1420- }
1421-
1422- self.builder.connect_signals(callback_dic)
1423-
1424- # Initilize dialog widgets with correct values and show dialog
1425- self.dialog.resize(300, 200)
1426- self.dialog.run()
1427-
1428- def on_fileOpen_clicked(self, widget):
1429- """Opens add file dialog and then adds all feeds in the opml file
1430- selected """
1431-
1432- #get the model for the feed list widget so we can add the new feeds
1433- model = self.tree_widget.get_model()
1434-
1435- #create select file dialog
1436- dialog = gtk.FileChooserDialog(_("Select OPML file"), None,
1437- gtk.FILE_CHOOSER_ACTION_OPEN,
1438- (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN,
1439- gtk.RESPONSE_OK))
1440-
1441- #set dialog up to filter for only opml files
1442- file_filter = gtk.FileFilter()
1443- file_filter.set_name(_("OPML files"))
1444- file_filter.add_pattern("*.opml")
1445- dialog.add_filter(file_filter)
1446-
1447- #set dialog up to allow multiple selections
1448- dialog.set_select_multiple(True)
1449-
1450- #run the dialog
1451- status = dialog.run()
1452-
1453- # if file was selected, get list of feeds from it and add to
1454- #model and update config file
1455- if(status == gtk.RESPONSE_OK):
1456- FeedConfigTools().add_file_feeds_to_widget(
1457- dialog.get_filenames(), model, self.feeds)
1458- dialog.destroy()
1459-
1460- def on_lifereaButton_clicked(self, widget):
1461- """Adds any liferea feeds it finds to the feed widget and config file
1462- """
1463- #get the model
1464- model = self.tree_widget.get_model()
1465- #get the liferea feeds and then send everything to the
1466- #add_file_feeds_to_widget method
1467- FeedConfigTools().add_file_feeds_to_widget(
1468- [OPMLParser().get_liferea_opml()], model, self.feeds)
1469-
1470- def on_enterURL_clicked(self, widget):
1471- """gets a opml file link from a user and adds any feeds it finds to the
1472- feed widget and config file"""
1473- url_dialog = self.builder.get_object("url_dialog")
1474- model = self.tree_widget.get_model()
1475- # Open dialog
1476- url_dialog.set_title(_("Add OPML File"))
1477- status = url_dialog.run()
1478- # If folder was selected we add it to model and update config file
1479- if(status == gtk.RESPONSE_OK):
1480- FeedConfigTools().add_file_feeds_to_widget([self.url],
1481- model, self.feeds)
1482-
1483- def on_closeButton_clicked(self, widget):
1484- self.dialog.hide()
1485- self.dialog.destroy()
1486-
1487- def on_url_dialog_ok_button_clicked(self, widget):
1488- """URL dialog OK button pressed. Sets self.url"""
1489- url_dialog = self.builder.get_object("url_dialog")
1490- url_entry = self.builder.get_object("url_entry")
1491- url_dialog.hide()
1492- self.url = url_entry.get_text()
1493- url_entry.set_text("")
1494- url_dialog.response(gtk.RESPONSE_OK)
1495-
1496- def on_url_dialog_cancel_button_clicked(self, widget):
1497- """URL dialog cancelled. Hides dialog"""
1498- url_dialog = self.builder.get_object("url_dialog")
1499- url_entry = self.builder.get_object("url_entry")
1500- url_dialog.hide()
1501- url_entry.set_text("")
1502- url_dialog.response(gtk.RESPONSE_CANCEL)
1503-
1504- def on_url_dialog_delete_event(self, widget, data):
1505- """Dialog's X clicked. Hides dialog"""
1506- url_dialog = self.builder.get_object("url_dialog")
1507- url_entry = self.builder.get_object("url_entry")
1508- url_dialog.hide()
1509- url_entry.set_text("")
1510- url_dialog.response(gtk.RESPONSE_CANCEL)
1511- return True
1512-
1513-
1514
1515=== modified file 'entertainerlib/download.py'
1516--- entertainerlib/download.py 2009-07-14 04:24:07 +0000
1517+++ entertainerlib/download.py 2010-04-03 15:04:16 +0000
1518@@ -95,7 +95,7 @@
1519 # Strip
1520 str_input = str_input.strip ()
1521
1522- # TODO: Convert accented to unaccented
1523+ # XXX: Convert accented to unaccented
1524 str_input = str_input.replace (" - ", " ")
1525 str_input = str_input.replace (": ", " ")
1526 str_input = str_input.replace (" & ", " and ")
1527@@ -144,7 +144,7 @@
1528 self.search_artist = st_artist
1529 self.search_album_no_vol = st_album_no_vol
1530
1531- # TODO: Improve to decrease wrong cover downloads, maybe add severity?
1532+ # XXX: Improve to decrease wrong cover downloads, maybe add severity?
1533 # Assemble list of search keywords (and thus search queries)
1534 if st_album == u'Unknown':
1535 self.keywords.append ("%s Best of" % (st_artist))
1536@@ -400,7 +400,7 @@
1537
1538 # Convert title and artist to use in url, special symbols have to be
1539 # replaced by a '%' not '%xx'
1540- # TODO: Find out what the special symbols are (', &, ...)
1541+ # XXX: Find out what the special symbols are (', &, ...)
1542 # not letters, digits, spaces and ()$^*=:;|#@}{][!,.-_\
1543 self.artist = urllib.quote(self.artist.encode('utf-8'),
1544 "'&()$^*=:;|#@}{][!,\\")
1545
1546=== modified file 'entertainerlib/gui/screens/factory.py'
1547--- entertainerlib/gui/screens/factory.py 2009-12-22 00:34:27 +0000
1548+++ entertainerlib/gui/screens/factory.py 2010-04-03 15:04:16 +0000
1549@@ -5,8 +5,6 @@
1550 from entertainerlib.gui.screens.album import Album
1551 from entertainerlib.gui.screens.audio_play import AudioPlay
1552 from entertainerlib.gui.screens.disc import Disc
1553-from entertainerlib.gui.screens.feed import Feed
1554-from entertainerlib.gui.screens.feed_entry import FeedEntry
1555 from entertainerlib.gui.screens.main import Main
1556 from entertainerlib.gui.screens.movie import Movie
1557 from entertainerlib.gui.screens.music import Music
1558@@ -14,7 +12,6 @@
1559 from entertainerlib.gui.screens.photo_albums import PhotoAlbums
1560 from entertainerlib.gui.screens.photographs import Photographs
1561 from entertainerlib.gui.screens.question import Question
1562-from entertainerlib.gui.screens.rss import Rss
1563 from entertainerlib.gui.screens.tv_episodes import TvEpisodes
1564 from entertainerlib.gui.screens.tv_series import TvSeries
1565 from entertainerlib.gui.screens.video import Video
1566@@ -25,15 +22,14 @@
1567 class ScreenFactory(object):
1568 '''Generate a screen based on the type provided.'''
1569
1570- def __init__(self, feed_library, image_library, music_library,
1571- video_library, media_player, move_to_new_screen_callback,
1572+ def __init__(self, image_library, music_library, video_library,
1573+ media_player, move_to_new_screen_callback,
1574 move_to_previous_screen_callback):
1575 '''All the possible common things that a screen could use to initialize
1576 are factory instance variables. Any additional specific information
1577 needed for a screen will be provided in a dictionary that is received
1578 by the generate_screen method.'''
1579
1580- self.feed_library = feed_library
1581 self.image_library = image_library
1582 self.music_library = music_library
1583 self.video_library = video_library
1584@@ -54,8 +50,6 @@
1585 'artist' : self._generate_artist,
1586 'audio_cd' : self._generate_disc,
1587 'audio_play' : self._generate_audio_play,
1588- 'entry' : self._generate_feed_entry,
1589- 'feed' : self._generate_feed,
1590 'main' : self._generate_main,
1591 'movie' : self._generate_movie,
1592 'music' : self._generate_music,
1593@@ -63,7 +57,6 @@
1594 'photo_albums' : self._generate_photo_albums,
1595 'photographs' : self._generate_photographs,
1596 'question' : self._generate_question,
1597- 'rss' : self._generate_rss,
1598 'tv_episodes' : self._generate_tv_episodes,
1599 'tv_series' : self._generate_tv_series,
1600 'video' : self._generate_video,
1601@@ -99,18 +92,8 @@
1602 kwargs['music_library'] = self.music_library
1603 return Disc(**kwargs)
1604
1605- def _generate_feed(self, kwargs):
1606- '''Generate a Feed screen.'''
1607- kwargs['move_to_new_screen_callback'] = self.move_to_new_screen_callback
1608- return Feed(**kwargs)
1609-
1610- def _generate_feed_entry(self, kwargs):
1611- '''Generate a FeedEntry screen.'''
1612- return FeedEntry(**kwargs)
1613-
1614 def _generate_main(self, kwargs):
1615 '''Generate a Main screen.'''
1616- kwargs['feed_library'] = self.feed_library
1617 kwargs['media_player'] = self.media_player
1618 kwargs['move_to_new_screen_callback'] = self.move_to_new_screen_callback
1619 return Main(**kwargs)
1620@@ -149,12 +132,6 @@
1621 self.move_to_previous_screen_callback
1622 return Question(**kwargs)
1623
1624- def _generate_rss(self, kwargs):
1625- '''Generate a Rss screen.'''
1626- kwargs['feed_library'] = self.feed_library
1627- kwargs['move_to_new_screen_callback'] = self.move_to_new_screen_callback
1628- return Rss(**kwargs)
1629-
1630 def _generate_tv_series(self, kwargs):
1631 '''Generate a TvSeries screen.'''
1632 kwargs['move_to_new_screen_callback'] = self.move_to_new_screen_callback
1633
1634=== removed file 'entertainerlib/gui/screens/feed.py'
1635--- entertainerlib/gui/screens/feed.py 2009-07-29 03:09:34 +0000
1636+++ entertainerlib/gui/screens/feed.py 1970-01-01 00:00:00 +0000
1637@@ -1,102 +0,0 @@
1638-# Copyright (c) 2009 Entertainer Developers - See COPYING - GPLv2
1639-'''Feed - Screen that contains a list of entries in one feed'''
1640-
1641-import pango
1642-
1643-from entertainerlib.gui.screens.screen import Screen
1644-from entertainerlib.gui.widgets.label import Label
1645-from entertainerlib.gui.widgets.list_indicator import ListIndicator
1646-from entertainerlib.gui.widgets.texture import Texture
1647-from entertainerlib.gui.widgets.text_menu import TextMenu
1648-from entertainerlib.backend.components.feeds.feed_utils import FeedEntryParser
1649-
1650-class Feed(Screen):
1651- '''Screen is displayed when headlines are accessed for a specific feed.'''
1652-
1653- def __init__(self, feed, move_to_new_screen_callback):
1654- Screen.__init__(self, 'Feed', move_to_new_screen_callback)
1655-
1656- self.theme = self.config.theme
1657- self.feed = feed
1658- self.menu = None
1659-
1660- self.menu = self._create_entry_menu()
1661- self.add(self.menu)
1662-
1663- # Screen Title (Displayed at the bottom left corner)
1664- screen_title = Label(0.13, "screentitle", 0, 0.87, _("Feed"))
1665- self.add(screen_title)
1666-
1667- # RSS Icon
1668- icon = Texture(self.theme.getImage("rss_icon"), 0.05, 0.07)
1669- self.add(icon)
1670-
1671- # RSS Feed Title
1672- title_text = FeedEntryParser().convert(self.feed.title)
1673- title = Label(0.065, "title", 0.13, 0.07, title_text)
1674- title.set_use_markup(True)
1675- title.width = 0.6
1676- title.set_ellipsize(pango.ELLIPSIZE_END)
1677- self.add(title)
1678-
1679- # RSS Feed description
1680- desc_text = FeedEntryParser().convert(self.feed.subtitle)
1681- desc = Label(0.03646, "subtitle", 0.13, 0.14, desc_text)
1682- desc.set_use_markup(True)
1683- desc.width = 0.6
1684- desc.set_ellipsize(pango.ELLIPSIZE_END)
1685- self.add(desc)
1686-
1687- # Last update
1688- update = Label(0.0313, "title", 0.78, 0.1, _("Updated"))
1689- self.add(update)
1690- date_text = self.feed.time[:5] + " - " + self.feed.date
1691- date = Label(0.0313, "subtitle", 0.78, 0.14, date_text)
1692- self.add(date)
1693-
1694- #List indicator
1695- self.li = ListIndicator(0.57, 0.9, 0.2, 0.045, ListIndicator.VERTICAL)
1696- self.li.set_maximum(len(self.feed.entries))
1697- self.add(self.li)
1698-
1699- self._display_selected_feed()
1700-
1701- self.menu.connect('selected', self._on_menu_selected)
1702- self.menu.connect('moved', self._display_selected_feed)
1703-
1704- def _create_entry_menu(self):
1705- """Create Entries-menu. This menu contains list of entries."""
1706- menu = TextMenu(0.2438, 0.2604, 0.5124, 0.0781)
1707-
1708- parser = FeedEntryParser()
1709- feeds = self.feed.entries
1710- feeds_list = [[parser.strip_tags(feed.title), None, feed] \
1711- for feed in feeds]
1712- menu.async_add(feeds_list)
1713-
1714- menu.active = True
1715-
1716- return menu
1717-
1718- def _handle_up(self):
1719- '''Handle UserEvent.NAVIGATE_UP.'''
1720- self.menu.up()
1721-
1722- def _handle_down(self):
1723- '''Handle UserEvent.NAVIGATE_DOWN.'''
1724- self.menu.down()
1725-
1726- def _handle_select(self, event=None):
1727- '''Handle UserEvent.NAVIGATE_SELECT.'''
1728- entry = self.menu.selected_userdata
1729- kwargs = { 'feed' : self.feed, 'entry' : entry }
1730- self.callback("entry", kwargs)
1731-
1732- def _on_menu_selected(self, event=None):
1733- '''Handle a *select command* if an item was selected.'''
1734- self._handle_select()
1735-
1736- def _display_selected_feed(self, event=None):
1737- '''Update of the list indicator'''
1738- self.li.set_current(self.menu.selected_index + 1)
1739-
1740
1741=== removed file 'entertainerlib/gui/screens/feed_entry.py'
1742--- entertainerlib/gui/screens/feed_entry.py 2009-08-04 01:09:03 +0000
1743+++ entertainerlib/gui/screens/feed_entry.py 1970-01-01 00:00:00 +0000
1744@@ -1,112 +0,0 @@
1745-# Copyright (c) 2009 Entertainer Developers - See COPYING - GPLv2
1746-'''FeedEntry - Screen displays one entry of some RSS feed'''
1747-
1748-import pango
1749-
1750-from entertainerlib.gui.screens.screen import Screen
1751-from entertainerlib.gui.user_event import UserEvent
1752-from entertainerlib.gui.widgets.label import Label
1753-from entertainerlib.gui.widgets.scroll_area import ScrollArea
1754-from entertainerlib.gui.widgets.texture import Texture
1755-from entertainerlib.backend.components.feeds.feed_utils import FeedEntryParser
1756-
1757-class FeedEntry(Screen):
1758- '''Screen displays one feed entry.'''
1759-
1760- def __init__(self, feed, entry):
1761- Screen.__init__(self, 'FeedEntry')
1762-
1763- self.theme = self.config.theme
1764- self.feed = feed
1765- self.entry = entry
1766-
1767- # Screen Title (Displayed at the bottom left corner)
1768- screen_title_text = FeedEntryParser().convert(self.feed.title)
1769- screen_title = Label(0.13, "screentitle", 0, 0.87, screen_title_text)
1770- screen_title.set_ellipsize(pango.ELLIPSIZE_END)
1771- screen_title.width = 0.8
1772- screen_title.set_use_markup(True)
1773- self.add(screen_title)
1774-
1775- # RSS Icon
1776- icon = Texture(self.theme.getImage("rss_icon"), 0.05, 0.07)
1777- self.add(icon)
1778-
1779- # Entry Title
1780- title_text = FeedEntryParser().convert(self.feed.title)
1781- title = Label(0.065, "title", 0.13, 0.07, title_text)
1782- title.set_use_markup(True)
1783- title.width = 0.6
1784- title.set_ellipsize(pango.ELLIPSIZE_END)
1785- self.add(title)
1786-
1787- # RSS Feed descrption
1788- full_text = self.entry.title
1789- try:
1790- sub_title = full_text[:full_text.index('\n')]
1791- except ValueError:
1792- sub_title = full_text
1793- desc_text = FeedEntryParser().convert(sub_title)
1794- desc = Label(0.0365, "subtitle", 0.13, 0.14, desc_text)
1795- desc.set_use_markup(True)
1796- desc.set_ellipsize(pango.ELLIPSIZE_END)
1797- desc.width = 0.6
1798- self.add(desc)
1799-
1800- # Last update
1801- update = Label(0.0313, "title", 0.78, 0.1, _("Updated"))
1802- self.add(update)
1803- date_text = self.entry.time[:5] + " - " + self.entry.date
1804- date = Label(0.0313, "subtitle", 0.78, 0.14, date_text)
1805- self.add(date)
1806-
1807- # Entry descrption
1808- if len(self.entry.description.strip()) == 0:
1809- entry_text = Label(0.04167, "text", 0.35, 0.48,
1810- _("Entry has no content"))
1811- self.add(entry_text)
1812- else:
1813- entry_text_data = FeedEntryParser().convert(self.entry.description)
1814- entry_text = Label(0.0365, "text", 0, 0, entry_text_data)
1815- entry_text.set_use_markup(True)
1816- entry_text.set_size(0.5857, 0.5208)
1817-
1818- self.scroll_area = ScrollArea(0.2072, 0.3, 0.5857, 0.4948,
1819- entry_text)
1820- self.add(self.scroll_area)
1821-
1822- # Add the additional actions that are needed but not handled by default
1823- self.event_handlers.update({
1824- UserEvent.NAVIGATE_FIRST_PAGE : self._handle_first_page,
1825- UserEvent.NAVIGATE_LAST_PAGE : self._handle_last_page,
1826- UserEvent.NAVIGATE_PREVIOUS_PAGE : self._handle_previous_page,
1827- UserEvent.NAVIGATE_NEXT_PAGE : self._handle_next_page
1828- })
1829-
1830- # We're at the end without any problems so lets set the entry as read.
1831- self.entry.read = True
1832-
1833- def _handle_up(self):
1834- '''Handle UserEvent.NAVIGATE_UP.'''
1835- self.scroll_area.scroll_up()
1836-
1837- def _handle_down(self):
1838- '''Handle UserEvent.NAVIGATE_DOWN.'''
1839- self.scroll_area.scroll_down()
1840-
1841- def _handle_first_page(self):
1842- '''Handle UserEvent.NAVIGATE_FIRST_PAGE.'''
1843- self.scroll_area.scroll_to_top()
1844-
1845- def _handle_last_page(self):
1846- '''Handle UserEvent.NAVIGATE_LAST_PAGE.'''
1847- self.scroll_area.scroll_to_bottom()
1848-
1849- def _handle_previous_page(self):
1850- '''Handle UserEvent.NAVIGATE_PREVIOUS_PAGE.'''
1851- self.scroll_area.scroll_page_up()
1852-
1853- def _handle_next_page(self):
1854- '''Handle UserEvent.NAVIGATE_NEXT_PAGE.'''
1855- self.scroll_area.scroll_page_down()
1856-
1857
1858=== modified file 'entertainerlib/gui/screens/main.py'
1859--- entertainerlib/gui/screens/main.py 2009-12-19 16:27:15 +0000
1860+++ entertainerlib/gui/screens/main.py 2010-04-03 15:04:16 +0000
1861@@ -8,8 +8,6 @@
1862 from entertainerlib.gui.widgets.label import Label
1863 from entertainerlib.gui.widgets.scroll_menu import ScrollMenu
1864 from entertainerlib.gui.widgets.texture import Texture
1865-from entertainerlib.gui.widgets.text_menu import TextMenu
1866-from entertainerlib.backend.components.feeds.feed_utils import FeedEntryParser
1867
1868 class Main(Screen):
1869 '''Screen displayed when frontend is opened and provides main navigation.'''
1870@@ -22,10 +20,9 @@
1871 UP = 0
1872 DOWN = 1
1873
1874- def __init__(self, feed_library, media_player, move_to_new_screen_callback):
1875+ def __init__(self, media_player, move_to_new_screen_callback):
1876 Screen.__init__(self, 'Main', move_to_new_screen_callback)
1877
1878- self.feed_library = feed_library
1879 self.media_player = media_player
1880 self.media_player.connect("stop", self.update)
1881 self.media_player.connect("play", self.update)
1882@@ -40,9 +37,6 @@
1883 self.preview.set_opacity(0x00)
1884 self.add(self.preview)
1885
1886- self.rss_preview_menu = self._create_rss_preview_menu()
1887- self.preview.add(self.rss_preview_menu)
1888-
1889 self.menu = self._create_main_menu()
1890 self.add(self.menu)
1891
1892@@ -52,7 +46,6 @@
1893
1894 self.menu.connect('selected', self._handle_select)
1895 self.menu.connect('moved', self._on_menu_moved)
1896- self.menu.connect('activated', self._on_menu_activated)
1897
1898 self.menu.active = True
1899
1900@@ -73,7 +66,6 @@
1901 menu.add_item(_("Videos"), "videos")
1902 menu.add_item(_("Music"), "music")
1903 menu.add_item(_("Photographs"), "photo")
1904- menu.add_item(_("Headlines"), "rss")
1905
1906 if self.config.display_weather_in_client:
1907 menu.add_item(_("Weather"), "weather")
1908@@ -91,25 +83,6 @@
1909
1910 return menu
1911
1912- def _create_rss_preview_menu(self):
1913- '''Create the RSS preview menu that will show feed highlights. An
1914- uninitialized menu will be returned to prevent move errors if there
1915- is nothing in the feed library.'''
1916- menu = TextMenu(0.035, 0.12, 0.549, 0.078)
1917-
1918- if self.feed_library.is_empty() is False:
1919- parser = FeedEntryParser()
1920- entries = self.feed_library.get_latest_entries(5)
1921- entries_list = [[parser.strip_tags(entry[0].title + " - " + \
1922- entry[1].title), entry[1].date, \
1923- { 'feed' : entry[0], 'entry' : entry[1] }] for entry in entries]
1924- menu.async_add(entries_list)
1925-
1926- menu.connect('selected', self._handle_select)
1927- menu.connect('activated', self._on_rss_menu_activated)
1928-
1929- return menu
1930-
1931 def _create_playing_preview(self):
1932 '''Create the Now Playing preview sidebar.'''
1933 preview = clutter.Group()
1934@@ -170,36 +143,8 @@
1935 'length': self.media_player.get_media_duration_string()}
1936 self._preview_title.set_text(title_text)
1937
1938- def _create_rss_preview(self):
1939- '''Create the RSS preview sidebar.'''
1940- preview = clutter.Group()
1941-
1942- # RSS Icon
1943- icon = Texture(self.theme.getImage("rss_icon"), 0, 0.04)
1944- icon.set_scale(0.6, 0.6)
1945- preview.add(icon)
1946-
1947- # RSS Feed Title
1948- title = Label(0.075, "title", 0.045, 0.03, _("Recent headlines"))
1949- preview.add(title)
1950-
1951- if self.feed_library.is_empty() is False:
1952- menu = self._create_rss_preview_menu()
1953- preview.add(menu)
1954- self.rss_preview_menu = menu
1955- else:
1956- # No headlines available in the library
1957- info = Label(0.05, "title", 0.1, 0.35, _("No headlines available"))
1958- preview.add(info)
1959- self.rss_preview_menu = None
1960-
1961- return preview
1962-
1963 def _update_preview_area(self):
1964 '''Update the preview area to display the current menu item.'''
1965- if self.rss_preview_menu:
1966- rss_preview_menu_active = self.rss_preview_menu.active
1967-
1968 self.preview.remove_all()
1969 item = self.menu.get_selected()
1970
1971@@ -209,10 +154,6 @@
1972
1973 if item.get_name() == "playing":
1974 self.preview.add(self._create_playing_preview())
1975- elif item.get_name() == "rss":
1976- self.preview.add(self._create_rss_preview())
1977- if self.rss_preview_menu:
1978- self.rss_preview_menu.active = rss_preview_menu_active
1979 else:
1980 update = False
1981
1982@@ -224,14 +165,6 @@
1983 self.behaviour.apply(self.preview)
1984 fade_in.start()
1985
1986- def _can_move_horizontally(self):
1987- '''Return a boolean indicating if horizontal movement is allowed.'''
1988- item = self.menu.get_selected()
1989- if self.feed_library.is_empty() or item.get_name() != 'rss':
1990- return False
1991- else:
1992- return True
1993-
1994 def update(self, event=None):
1995 """
1996 Update screen widgets. This is called always when screen is poped from
1997@@ -249,26 +182,11 @@
1998
1999 def _handle_up(self):
2000 '''Handle UserEvent.NAVIGATE_UP.'''
2001- if self.menu.active:
2002- self.menu.scroll_up()
2003- else:
2004- self.rss_preview_menu.up()
2005+ self.menu.scroll_up()
2006
2007 def _handle_down(self):
2008 '''Handle UserEvent.NAVIGATE_DOWN.'''
2009- if self.menu.active:
2010- self.menu.scroll_down()
2011- else:
2012- self.rss_preview_menu.down()
2013-
2014- def _handle_left(self):
2015- '''Handle UserEvent.NAVIGATE_LEFT.'''
2016- if self._can_move_horizontally():
2017- self.rss_preview_menu.active = True
2018-
2019- def _handle_right(self):
2020- '''Handle UserEvent.NAVIGATE_RIGHT.'''
2021- self.menu.active = True
2022+ self.menu.scroll_down()
2023
2024 def _handle_select(self, event=None):
2025 '''Handle UserEvent.NAVIGATE_SELECT.'''
2026@@ -286,24 +204,8 @@
2027 self.callback("weather")
2028 elif item.get_name() == "photo":
2029 self.callback("photo_albums")
2030- elif item.get_name() == "rss":
2031- if self.menu.active:
2032- self.callback("rss")
2033- else:
2034- menu_item = self.rss_preview_menu.selected_item
2035- kwargs = menu_item.userdata
2036- self.callback("entry", kwargs)
2037
2038 def _on_menu_moved(self, event):
2039 '''Update preview area when selected item changed on the menu.'''
2040 self._update_preview_area()
2041
2042- def _on_menu_activated(self, event=None):
2043- '''Handle the main menu activation.'''
2044- if self.rss_preview_menu is not None:
2045- self.rss_preview_menu.active = False
2046-
2047- def _on_rss_menu_activated(self, event=None):
2048- '''Handle the rss menu activation.'''
2049- self.menu.active = False
2050-
2051
2052=== removed file 'entertainerlib/gui/screens/rss.py'
2053--- entertainerlib/gui/screens/rss.py 2009-07-29 03:09:34 +0000
2054+++ entertainerlib/gui/screens/rss.py 1970-01-01 00:00:00 +0000
2055@@ -1,228 +0,0 @@
2056-# Copyright (c) 2009 Entertainer Developers - See COPYING - GPLv2
2057-'''Rss - Screen displays RSS feeds'''
2058-
2059-import pango
2060-
2061-from entertainerlib.gui.screens.screen import Screen
2062-from entertainerlib.gui.widgets.label import Label
2063-from entertainerlib.gui.widgets.texture import Texture
2064-from entertainerlib.gui.widgets.text_menu import TextMenu
2065-from entertainerlib.gui.widgets.list_indicator import ListIndicator
2066-from entertainerlib.backend.components.feeds.feed_utils import FeedEntryParser
2067-
2068-class Rss(Screen):
2069- '''Screen displays RSS-feed titles and number of entries.'''
2070-
2071- def __init__(self, feed_library, move_to_new_screen_callback):
2072- Screen.__init__(self, 'Rss', move_to_new_screen_callback)
2073-
2074- self.feed_order = 'UNREAD' # Feeds ordered by number of unread entries
2075- self.theme = self.config.theme
2076- self.library = feed_library
2077- self.parser = FeedEntryParser()
2078-
2079- # Screen Title (Displayed at the bottom left corner)
2080- screen_title = Label(0.13, "screentitle", 0, 0.87, _("Headlines"))
2081- self.add(screen_title)
2082-
2083- # RSS Icon
2084- icon = Texture(self.theme.getImage("rss_icon"), 0.05, 0.07)
2085- self.add(icon)
2086-
2087- # RSS Title
2088- title = Label(0.0833, "title", 0.13, 0.07, _("RSS Feeds"))
2089- self.add(title)
2090-
2091- #We set the menus to None here so we can check if they exist later on
2092- self.menu = None
2093- self.context_menu = None
2094-
2095- # Display information box if there are not feeds available
2096- if self.library.is_empty() or len(self.library.get_feeds()) == 0:
2097- self._create_no_feeds_information()
2098- else:
2099- # Menus
2100- self._create_context_menu()
2101- self.menu = self._create_feed_menu()
2102- self.add(self.menu)
2103- self.li = None
2104- self._create_feed_menu_indicator()
2105- self.menu.active = True
2106- self.context_menu.active = False
2107-
2108- # Feeds Title
2109- feeds_title = Label(0.04167, "title", 0.3953, 0.2, _("Feeds"))
2110- self.add(feeds_title)
2111-
2112- # Unread Title
2113- unread_title = Label(0.04167, "title", 0.8053, 0.2, _("Unread"))
2114- self.add(unread_title)
2115-
2116- # Feed description text
2117- desc_text = self.parser.strip_tags(
2118- self.menu.selected_userdata.description)
2119-
2120- self.description = Label(0.03646, "text", 0.3953, 0.9, desc_text)
2121- self.description.set_ellipsize(pango.ELLIPSIZE_END)
2122- self.description.set_use_markup(True)
2123- self.description.set_size(0.5088, 0.0651)
2124- self.add(self.description)
2125-
2126- self.menu.connect('selected', self._handle_select)
2127- self.menu.connect('moved', self._display_selected_feed)
2128- self.menu.connect('activated', self._menu_activation)
2129- self.context_menu.connect('selected', self._handle_select)
2130- self.context_menu.connect('activated',
2131- self._context_menu_activation)
2132-
2133- def _create_feed_menu(self):
2134- """
2135- Create Feed-menu. This menu contains list of Feeds. It also displays
2136- number of unread entries per feed.
2137- """
2138- menu = TextMenu(0.3807, 0.2604, 0.5124, 0.0781)
2139-
2140- feeds = self.library.get_feeds(self.feed_order)
2141- feeds_list = [[self.parser.strip_tags(feed.title), \
2142- str(feed.get_number_of_unread()), feed] \
2143- for feed in feeds]
2144- menu.async_add(feeds_list)
2145-
2146- return menu
2147-
2148- def _create_feed_menu_indicator(self):
2149- '''Create a ListIndicator for feed menu.'''
2150- self.li = ListIndicator(0.7, 0.9, 0.2, 0.045, ListIndicator.VERTICAL)
2151- self.li.set_maximum(len(self.library.get_feeds(self.feed_order)))
2152- self.add(self.li)
2153-
2154- def _create_context_menu(self):
2155- """
2156- Create RSS-feed context menu and add it to the screen.
2157- This menu contains buttons for update and sorting.
2158- """
2159- self.context_menu = TextMenu(0.0732, 0.2604, 0.2196, 0.0781)
2160-
2161- self.context_menu.add_item(_("Update feeds"))
2162- self.context_menu.add_item(_("Mark all as read"))
2163- self.context_menu.add_item(_("Sort by name"))
2164- self.context_menu.add_item(_("Sort by unread"))
2165-
2166- self.context_menu.active = False
2167- self.add(self.context_menu)
2168-
2169- def _create_no_feeds_information(self):
2170- """
2171- Create textures and labels for information screen. This is displayed
2172- instead of feeds list if there are no feeds available. This screen helps
2173- users to add new feeds to the system.
2174- """
2175- # Create warning icon
2176- warning_icon = Texture(self.theme.getImage("warning_icon"), 0.28, 0.27)
2177- self.add(warning_icon)
2178-
2179- # Create warning title
2180- info_title = Label(0.0625, "title", 0.3367, 0.2709,
2181- _("No headlines available!"))
2182- self.add(info_title)
2183-
2184- # Create warning help text
2185- message = _(
2186- "To use headlines you have to add some RSS feeds with the Content "
2187- "management tool. To do this, start the Content management tool, "
2188- "open the 'RSS Feeds' tab and click the 'Add' button. Now you can "
2189- "write an RSS feed URL in the text entry. You can get RSS feed "
2190- "URLs from webpages that support RSS.")
2191- info = Label(0.0417, "menuitem_inactive", 0.2804, 0.45, message)
2192- info.set_size(0.5, 0.5208)
2193- self.add(info)
2194-
2195- def update(self, event=None):
2196- """
2197- Update screen widgets. This is called always when screen is poped from
2198- the screen history.
2199- """
2200- feeds = self.library.get_feeds(self.feed_order)
2201- for idx, item in enumerate(self.menu.items):
2202- feed = feeds[idx]
2203- item.userdata = feed
2204- item.update(self.parser.strip_tags(feed.title),
2205- str(feed.get_number_of_unread()))
2206-
2207- def _handle_up(self):
2208- '''Handle UserEvent.NAVIGATE_UP.'''
2209- if self.menu.active:
2210- self.menu.up()
2211- else:
2212- self.context_menu.up()
2213-
2214- def _handle_down(self):
2215- '''Handle UserEvent.NAVIGATE_DOWN.'''
2216- if self.menu.active:
2217- self.menu.down()
2218- else:
2219- self.context_menu.down()
2220-
2221- def _handle_left(self):
2222- '''Handle UserEvent.NAVIGATE_LEFT.'''
2223- if self.menu.active:
2224- self._context_menu_activation()
2225-
2226- def _handle_right(self):
2227- '''Handle UserEvent.NAVIGATE_RIGHT.'''
2228- if not self.menu.active:
2229- self._menu_activation()
2230-
2231- def _handle_select(self, event=None):
2232- '''Handle UserEvent.NAVIGATE_SELECT.'''
2233- if not self.menu.active:
2234- index = self.context_menu.selected_index
2235- if index == 0:
2236- # Send message to bus and update screen
2237- self.library.request_feed_update()
2238- self.update()
2239- elif index == 1:
2240- # Tell feedlibrary to mark all as read and then update screen
2241- self.library.mark_all_as_read()
2242- self.update()
2243- elif index == 2:
2244- # Sort feeds by title ASC and update screen
2245- self.feed_order = 'TITLE'
2246- self.update()
2247- elif index == 3:
2248- # Sort feeds by UNREAD DESC and update screen
2249- self.feed_order = 'UNREAD'
2250- self.update()
2251- else:
2252- # Feed selected from the menu. Change screen.
2253- feed = self.menu.selected_userdata
2254- kwargs = { 'feed' : feed }
2255- self.callback("feed", kwargs)
2256-
2257- def handle_user_event(self, event=None):
2258- '''Handle screen specific user events unless the library is empty.'''
2259- if self.library.is_empty() or len(self.library.get_feeds()) == 0:
2260- return
2261- else:
2262- Screen.handle_user_event(self, event)
2263-
2264- def _display_selected_feed(self, actor=None):
2265- '''Update of the list indicator and the description label'''
2266- self.li.set_current(self.menu.selected_index + 1)
2267- feed = self.menu.selected_userdata
2268- self.description.set_text(self.parser.strip_tags(feed.description))
2269-
2270- def _menu_activation(self, actor=None):
2271- '''Handle the menu activation'''
2272- self.menu.active = True
2273- self.context_menu.active = False
2274- self.li.show_position()
2275- self.description.show()
2276-
2277- def _context_menu_activation(self, actor=None):
2278- '''Handle the context menu activation'''
2279- self.menu.active = False
2280- self.context_menu.active = True
2281- self.li.hide_position()
2282- self.description.hide()
2283-
2284
2285=== modified file 'entertainerlib/gui/user_interface.py'
2286--- entertainerlib/gui/user_interface.py 2009-12-22 02:44:49 +0000
2287+++ entertainerlib/gui/user_interface.py 2010-04-03 15:04:16 +0000
2288@@ -12,6 +12,8 @@
2289 import gobject
2290 import gtk
2291
2292+from entertainerlib.client.media_player import MediaPlayer
2293+from entertainerlib.configuration import Configuration
2294 from entertainerlib.gui.widgets.volume_indicator import VolumeIndicator
2295 from entertainerlib.gui.screen_history import ScreenHistory
2296 from entertainerlib.gui.screens.factory import ScreenFactory
2297@@ -20,16 +22,14 @@
2298 from entertainerlib.gui.transitions.transition import Transition
2299 from entertainerlib.gui.user_event import UserEvent
2300 from entertainerlib.gui.widgets.menu_overlay import MenuOverlay
2301-from entertainerlib.client.media_player import MediaPlayer
2302-from entertainerlib.configuration import Configuration
2303 from entertainerlib.logger import Logger
2304
2305
2306 class UserInterface:
2307 '''A main GUI window of the Entertainer client.'''
2308
2309- def __init__(self, feed_library, image_library, music_library,
2310- video_library, quit_client_callback):
2311+ def __init__(self, image_library, music_library, video_library,
2312+ quit_client_callback):
2313 self.quit_client_callback = quit_client_callback
2314 self.config = Configuration()
2315
2316@@ -111,8 +111,8 @@
2317
2318 # Screen factory to create new screens
2319 self.screen_factory = ScreenFactory(
2320- feed_library, image_library, music_library, video_library,
2321- self.player, self.move_to_new_screen, self.move_to_previous_screen)
2322+ image_library, music_library, video_library, self.player,
2323+ self.move_to_new_screen, self.move_to_previous_screen)
2324
2325 def default_key_to_user_event():
2326 '''Return the default user event provided by an unmapped keyboard
2327
2328=== modified file 'entertainerlib/indexing/handlers.py'
2329--- entertainerlib/indexing/handlers.py 2009-07-12 17:31:52 +0000
2330+++ entertainerlib/indexing/handlers.py 2010-04-03 15:04:16 +0000
2331@@ -32,16 +32,16 @@
2332
2333 def _add_file(self, filename):
2334 '''Add a video.'''
2335- file = models.VideoFile()
2336- file.filename = unicode(filename)
2337+ video_file = models.VideoFile()
2338+ video_file.filename = unicode(filename)
2339 thumbnailer = VideoThumbnailer(filename)
2340 thumbnailer.create_thumbnail()
2341- file.thumbnail = thumbnailer.filename
2342+ video_file.thumbnail = thumbnailer.filename
2343
2344- self._store.add(file)
2345+ self._store.add(video_file)
2346 self._store.commit()
2347
2348- return file
2349+ return video_file
2350
2351 def _update_file(self, filename):
2352 '''Update on existing video.'''
2353@@ -63,17 +63,17 @@
2354
2355 def _add_file(self, filename):
2356 '''Add an image to the store.'''
2357- file = models.PhotoImage()
2358- file.filename = unicode(filename)
2359+ photo_file = models.PhotoImage()
2360+ photo_file.filename = unicode(filename)
2361
2362 thumbnailer = ImageThumbnailer(filename)
2363 thumbnailer.create_thumbnail()
2364- file.thumbnail = unicode(thumbnailer.filename)
2365+ photo_file.thumbnail = unicode(thumbnailer.filename)
2366
2367- self._store.add(file)
2368+ self._store.add(photo_file)
2369 self._store.commit()
2370
2371- return file
2372+ return photo_file
2373
2374 def _update_file(self, filename):
2375 '''Update an existing image in the store.'''
2376@@ -95,50 +95,50 @@
2377
2378 def _add_file(self, filename):
2379 '''Add a file to the store.'''
2380- file = models.MusicTrack()
2381+ music_file = models.MusicTrack()
2382 album = models.MusicAlbum()
2383
2384- file.filename = filename
2385+ music_file.filename = filename
2386
2387 tags = TagGetter(filename)
2388
2389- file.comment = tags.comment
2390- file.lyrics = u''
2391- file.title = tags.title
2392- file.tracknumber = tags.track_number
2393+ music_file.comment = tags.comment
2394+ music_file.lyrics = u''
2395+ music_file.title = tags.title
2396+ music_file.tracknumber = tags.track_number
2397 album.artist = tags.artist
2398 album.title = tags.album
2399 album.genre = tags.genre
2400- file.album = album
2401+ music_file.album = album
2402
2403 self._store.add(album)
2404- self._store.add(file)
2405+ self._store.add(music_file)
2406 self._store.commit()
2407
2408 # TODO: get album art
2409- return file
2410+ return music_file
2411
2412 def _update_file(self, filename):
2413 '''Update a file already in the store.'''
2414- file = self._store.find(models.MusicTrack,
2415+ music_file = self._store.find(models.MusicTrack,
2416 models.MusicTrack.filename == filename).one()
2417- album = file.album
2418+ album = music_file.album
2419
2420 tags = TagGetter(filename)
2421
2422- file.comment = tags.comment
2423- file.lyrics = u''
2424- file.title = tags.title
2425- file.tracknumber = tags.track_number
2426+ music_file.comment = tags.comment
2427+ music_file.lyrics = u''
2428+ music_file.title = tags.title
2429+ music_file.tracknumber = tags.track_number
2430 album.artist = tags.artist
2431 album.title = tags.album
2432 album.genre = tags.genre
2433- file.album = album
2434+ music_file.album = album
2435
2436 self._store.add(album)
2437- self._store.add(file)
2438+ self._store.add(music_file)
2439 self._store.commit()
2440
2441 # TODO: get album art
2442- return file
2443+ return music_file
2444
2445
2446=== modified file 'entertainerlib/indexing/indexer.py'
2447--- entertainerlib/indexing/indexer.py 2009-07-12 17:31:52 +0000
2448+++ entertainerlib/indexing/indexer.py 2010-04-03 15:04:16 +0000
2449@@ -1,4 +1,7 @@
2450 '''Indexer module.'''
2451+
2452+# Pylint thinks that handlers isn't being used when it clearly is. Ignore it.
2453+# pylint: disable-msg=W0611
2454 from entertainerlib.indexing import handlers
2455 from entertainerlib.configuration import Configuration
2456 from entertainerlib.logger import Logger
2457
2458=== modified file 'entertainerlib/network/local/client.py'
2459--- entertainerlib/network/local/client.py 2009-04-04 05:30:04 +0000
2460+++ entertainerlib/network/local/client.py 2010-04-03 15:04:16 +0000
2461@@ -1,10 +1,10 @@
2462 '''Classes to produce a local storage implementation.'''
2463 # pylint: disable-msg=W0223
2464
2465-from twisted.internet.defer import inlineCallbacks
2466+#from twisted.internet.defer import inlineCallbacks
2467 from twisted.protocols import amp
2468
2469-from entertainerlib.network.local.commands import TenMusicTracks
2470+#from entertainerlib.network.local.commands import TenMusicTracks
2471 from entertainerlib.network.storage import Storage
2472
2473
2474@@ -15,11 +15,11 @@
2475 '''See `twisted.protocols.Protocal.connectionMade`.'''
2476 self.get_ten_tracks(1)
2477
2478- @inlineCallbacks
2479- def get_ten_tracks(self, index):
2480- '''Get ten tracks starting with the given index.'''
2481- result = yield self.callRemote(TenMusicTracks, index=index)
2482- print result
2483+# @inlineCallbacks
2484+# def get_ten_tracks(self, index):
2485+# '''Get ten tracks starting with the given index.'''
2486+# result = yield self.callRemote(TenMusicTracks, index=index)
2487+# print result
2488
2489
2490 class LocalStorage(Storage):
2491
2492=== removed directory 'entertainerlib/tests/data/FeedConfigTools'
2493=== removed file 'entertainerlib/tests/data/FeedConfigTools/test.opml'
2494--- entertainerlib/tests/data/FeedConfigTools/test.opml 2008-08-02 03:18:53 +0000
2495+++ entertainerlib/tests/data/FeedConfigTools/test.opml 1970-01-01 00:00:00 +0000
2496@@ -1,19 +0,0 @@
2497-<?xml version="1.0"?>
2498-<opml version="1.0">
2499- <head>
2500- <title>Liferea Feed List Export</title>
2501- </head>
2502- <body>
2503- <outline title="Tech" text="Tech" description="Tech" type="folder">
2504- <outline title="Hack a Day" text="Hack a Day" description="Hack a Day" type="rss" htmlUrl="http://www.hackaday.com" xmlUrl="http://www.hackaday.com/rss.xml"/>
2505- <outline title="OSS" text="OSS" description="OSS" type="folder">
2506- <outline title="Linux" text="Linux" description="Linux" type="folder">
2507- <outline title="edevelop.org - Pants ON" text="edevelop.org - Pants ON" description="edevelop.org - Pants ON" type="rss" htmlUrl="http://edevelop.org" xmlUrl="http://edevelop.org/planet/rss20.xml"/>
2508- </outline>
2509- </outline>
2510- <outline title="3D CG" text="3D CG" description="3D CG" type="folder">
2511- <outline title="BlenderArt Magazine: The unofficial Blender 3D magazine" text="BlenderArt Magazine: The unofficial Blender 3D magazine" description="BlenderArt Magazine: The unofficial Blender 3D magazine" type="rss" htmlUrl="http://www.blenderart.org" xmlUrl="http://feeds.feedburner.com/BlenderartMagazine"/>
2512- </outline>
2513- </outline>
2514- </body>
2515-</opml>
2516
2517=== removed directory 'entertainerlib/tests/data/OPMLParser'
2518=== removed directory 'entertainerlib/tests/data/OPMLParser/lifereaMultiple'
2519=== removed directory 'entertainerlib/tests/data/OPMLParser/lifereaMultiple/.liferea_1.4'
2520=== removed file 'entertainerlib/tests/data/OPMLParser/lifereaMultiple/.liferea_1.4/feedlist.opml'
2521--- entertainerlib/tests/data/OPMLParser/lifereaMultiple/.liferea_1.4/feedlist.opml 2008-02-08 16:37:34 +0000
2522+++ entertainerlib/tests/data/OPMLParser/lifereaMultiple/.liferea_1.4/feedlist.opml 1970-01-01 00:00:00 +0000
2523@@ -1,1 +0,0 @@
2524-test
2525
2526=== removed directory 'entertainerlib/tests/data/OPMLParser/lifereaNoFile'
2527=== removed directory 'entertainerlib/tests/data/OPMLParser/lifereaNoFolder'
2528=== removed directory 'entertainerlib/tests/data/OPMLParser/lifereaSingle'
2529=== removed directory 'entertainerlib/tests/data/OPMLParser/lifereaSingle/.liferea'
2530=== removed file 'entertainerlib/tests/data/OPMLParser/lifereaSingle/.liferea/feedlist.opml'
2531--- entertainerlib/tests/data/OPMLParser/lifereaSingle/.liferea/feedlist.opml 2008-02-08 16:37:34 +0000
2532+++ entertainerlib/tests/data/OPMLParser/lifereaSingle/.liferea/feedlist.opml 1970-01-01 00:00:00 +0000
2533@@ -1,1 +0,0 @@
2534-test
2535
2536=== removed file 'entertainerlib/tests/data/OPMLParser/noXML.txt'
2537--- entertainerlib/tests/data/OPMLParser/noXML.txt 2008-02-08 16:37:34 +0000
2538+++ entertainerlib/tests/data/OPMLParser/noXML.txt 1970-01-01 00:00:00 +0000
2539@@ -1,1 +0,0 @@
2540-This is not an xml file
2541
2542=== removed file 'entertainerlib/tests/data/OPMLParser/opmlInOpml.opml'
2543--- entertainerlib/tests/data/OPMLParser/opmlInOpml.opml 2008-02-08 16:37:34 +0000
2544+++ entertainerlib/tests/data/OPMLParser/opmlInOpml.opml 1970-01-01 00:00:00 +0000
2545@@ -1,21 +0,0 @@
2546-<?xml version="1.0"?>
2547-<opml version="1.0">
2548- <head>
2549- <title>Liferea Feed List Export</title>
2550- </head>
2551- <body>
2552- <outline title="BBC News | News Front Page | UK Edition" text="BBC News | News Front Page | UK Edition" description="BBC News | News Front Page | UK Edition" type="rss" htmlUrl="http://news.bbc.co.uk/go/rss/-/1/hi/default.stm" xmlUrl="http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/front_page/rss.xml"/>
2553- <outline title="BBC News | News Front Page | UK Edition" text="BBC News | News Front Page | UK Edition" description="BBC News | News Front Page | UK Edition" type="rss" htmlUrl="http://news.bbc.co.uk/go/rss/-/1/hi/default.stm" xmlUrl="http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/front_page/rss.opml"/>
2554- <outline title="Tech" text="Tech" description="Tech" type="folder">
2555- <outline title="Hack a Day" text="Hack a Day" description="Hack a Day" type="rss" htmlUrl="http://www.hackaday.com" xmlUrl="http://www.hackaday.com/rss.xml"/>
2556- <outline title="OSS" text="OSS" description="OSS" type="folder">
2557- <outline title="Linux" text="Linux" description="Linux" type="folder">
2558- <outline title="edevelop.org - Pants ON" text="edevelop.org - Pants ON" description="edevelop.org - Pants ON" type="rss" htmlUrl="http://edevelop.org" xmlUrl="http://edevelop.org/planet/rss20.xml"/>
2559- </outline>
2560- </outline>
2561- <outline title="3D CG" text="3D CG" description="3D CG" type="folder">
2562- <outline title="BlenderArt Magazine: The unofficial Blender 3D magazine" text="BlenderArt Magazine: The unofficial Blender 3D magazine" description="BlenderArt Magazine: The unofficial Blender 3D magazine" type="rss" htmlUrl="http://www.blenderart.org" xmlUrl="http://feeds.feedburner.com/BlenderartMagazine"/>
2563- </outline>
2564- </outline>
2565- </body>
2566-</opml>
2567
2568=== removed file 'entertainerlib/tests/data/OPMLParser/test.opml'
2569--- entertainerlib/tests/data/OPMLParser/test.opml 2008-02-08 16:37:34 +0000
2570+++ entertainerlib/tests/data/OPMLParser/test.opml 1970-01-01 00:00:00 +0000
2571@@ -1,20 +0,0 @@
2572-<?xml version="1.0"?>
2573-<opml version="1.0">
2574- <head>
2575- <title>Liferea Feed List Export</title>
2576- </head>
2577- <body>
2578- <outline title="BBC News | News Front Page | UK Edition" text="BBC News | News Front Page | UK Edition" description="BBC News | News Front Page | UK Edition" type="rss" htmlUrl="http://news.bbc.co.uk/go/rss/-/1/hi/default.stm" xmlUrl="http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/front_page/rss.xml"/>
2579- <outline title="Tech" text="Tech" description="Tech" type="folder">
2580- <outline title="Hack a Day" text="Hack a Day" description="Hack a Day" type="rss" htmlUrl="http://www.hackaday.com" xmlUrl="http://www.hackaday.com/rss.xml"/>
2581- <outline title="OSS" text="OSS" description="OSS" type="folder">
2582- <outline title="Linux" text="Linux" description="Linux" type="folder">
2583- <outline title="edevelop.org - Pants ON" text="edevelop.org - Pants ON" description="edevelop.org - Pants ON" type="rss" htmlUrl="http://edevelop.org" xmlUrl="http://edevelop.org/planet/rss20.xml"/>
2584- </outline>
2585- </outline>
2586- <outline title="3D CG" text="3D CG" description="3D CG" type="folder">
2587- <outline title="BlenderArt Magazine: The unofficial Blender 3D magazine" text="BlenderArt Magazine: The unofficial Blender 3D magazine" description="BlenderArt Magazine: The unofficial Blender 3D magazine" type="rss" htmlUrl="http://www.blenderart.org" xmlUrl="http://feeds.feedburner.com/BlenderartMagazine"/>
2588- </outline>
2589- </outline>
2590- </body>
2591-</opml>
2592
2593=== modified file 'entertainerlib/tests/mock.py'
2594--- entertainerlib/tests/mock.py 2010-01-03 22:58:00 +0000
2595+++ entertainerlib/tests/mock.py 2010-04-03 15:04:16 +0000
2596@@ -6,30 +6,13 @@
2597
2598 import gobject
2599
2600-from entertainerlib.client.medialibrary.feeds import Entry, Feed, FeedLibrary
2601 from entertainerlib.client.medialibrary.images import Image, ImageLibrary
2602-from entertainerlib.client.medialibrary.music import Album, MusicLibrary, Track
2603+from entertainerlib.client.medialibrary.music import MusicLibrary
2604 from entertainerlib.client.medialibrary.videos import (Movie, TVEpisode,
2605 TVSeries, VideoLibrary)
2606
2607 THIS_DIR = os.path.dirname(__file__)
2608
2609-class MockAlbum(Album):
2610- '''Mock entertainerlib.client.medialibrary.music.Album'''
2611-
2612- def __init__(self, title=None, cursor=None, make_track=True):
2613- self.title = 'Ganging Up on the Sun'
2614- self.total_length = 120
2615- if make_track:
2616- self.mock_track = MockTrack(make_album=False)
2617-
2618- self.tracks = [self.mock_track]
2619-
2620- def has_album_art(self):
2621- '''See `Album.has_album_art`.'''
2622- return False
2623-
2624-
2625 class MockClutterKeyboardEvent(object):
2626 '''Mock clutter keyboard events'''
2627
2628@@ -43,50 +26,6 @@
2629 return self._keyval
2630
2631
2632-class MockEntry(Entry):
2633- '''Mock entertainerlib.client.medialibrary.feeds.Entry'''
2634-
2635- def __init__(self, title=None, description=None, identifier=None,
2636- time=None, date=None, read=False):
2637- self.date = 'January 31st'
2638- self.description = "What!? I have to describe this thing?"
2639- self.time = 'Too early'
2640- self.title = 'Fake Entry'
2641- self._read = read
2642-
2643- def _get_read(self):
2644- '''Get the read property.'''
2645- return self._read
2646-
2647- def _set_read(self, read):
2648- '''Set the read property. Used to prevent a connection to the db.'''
2649- self._read = read
2650-
2651- read = property(_get_read, _set_read)
2652-
2653-
2654-class MockFeed(Feed):
2655- '''Mock entertainerlib.client.medialibrary.feeds.Feed'''
2656-
2657- def __init__(self, url=None):
2658- self.date = 'January 31st'
2659- self.subtitle = 'Whoa, a subtitle.'
2660- self.time = 'Too early'
2661- self.title = 'Fake Feed'
2662- self.entries = []
2663-
2664-
2665-class MockFeedLibrary(FeedLibrary):
2666- '''Mock entertainerlib.client.medialibrary.feeds.FeedLibrary'''
2667-
2668- def __init__(self, backend_connection=None):
2669- '''Override the intial behavior.'''
2670-
2671- def is_empty(self):
2672- '''See `FeedLibrary.is_empty`.'''
2673- return True
2674-
2675-
2676 class MockImage(Image):
2677 '''Mock entertainerlib.client.medialibrary.images.Image'''
2678
2679@@ -260,21 +199,6 @@
2680 '''See `TVSeries.has_cover_art`.'''
2681 return False
2682
2683-class MockTrack(Track):
2684- '''Mock entertainerlib.client.medialibrary.music.Track'''
2685-
2686- def __init__(self, filename=None, title=None, tracknumber=None, artist=None,
2687- album=None, genre=None, bitrate=None, year=None, rating=None,
2688- length=None, comment=None, lyrics=None, make_album=True):
2689- self.artist = 'Guster'
2690- self.length = 60
2691- self.lyrics = 'Here are some lyrics'
2692- self.title = 'One Man Wrecking Machine'
2693- self.tracknumber = 0
2694- if make_album:
2695- self.album = MockAlbum(make_track=False)
2696-
2697-
2698 class MockVideoLibrary(VideoLibrary):
2699 '''Mock entertainerlib.client.medialibrary.videos.VideoLibrary'''
2700
2701
2702=== modified file 'entertainerlib/tests/test_configuration.py'
2703--- entertainerlib/tests/test_configuration.py 2009-08-27 03:18:41 +0000
2704+++ entertainerlib/tests/test_configuration.py 2010-04-03 15:04:16 +0000
2705@@ -24,14 +24,8 @@
2706 self.assertEqual(self.configuration.theme_path,
2707 os.path.join(self.test_cfg_dir, 'data', 'themes', 'Default'))
2708 self.assertFalse(self.configuration.tray_icon_enabled)
2709- self.assertEqual(self.configuration.feed_fetch_interval, 15)
2710 self.assertEqual(self.configuration.port, 45054)
2711 self.assertEqual(self.configuration.media_folders, [''])
2712- self.assertEqual(self.configuration.feeds, [
2713- 'http://theironlion.net/blog/feed',
2714- 'http://www.joshuascotton.com/main/archives/tag/entertainer/feed',
2715- 'http://laymanstermsdev.wordpress.com/feed'
2716- ])
2717 self.assertEqual(self.configuration.weather_location, 'Bath,England')
2718 self.assertTrue(self.configuration.display_weather_in_client)
2719 self.assertTrue(self.configuration.download_metadata)
2720
2721=== removed file 'entertainerlib/tests/test_feedconfigtools.py'
2722--- entertainerlib/tests/test_feedconfigtools.py 2009-11-11 10:12:34 +0000
2723+++ entertainerlib/tests/test_feedconfigtools.py 1970-01-01 00:00:00 +0000
2724@@ -1,69 +0,0 @@
2725-# Copyright (c) 2009 Entertainer Developers - See COPYING - GPLv2
2726-'''Test FeedConfigTools'''
2727-
2728-import os
2729-
2730-import gtk
2731-
2732-from entertainerlib.backend.components.feeds.feed_utils import FeedConfigTools
2733-from entertainerlib.tests import EntertainerTest
2734-
2735-THIS_DIR = os.path.dirname(__file__)
2736-
2737-
2738-class FeedConfigToolsTest(EntertainerTest):
2739- # pylint: disable-msg=C0301
2740- # This pylint warning can be removed when the backend stuff gets removed,
2741- # and the pieces we keep get rearranged.
2742- '''Test for entertainerlib.backend.components.feeds.feed_utils.FeedConfigTools'''
2743-
2744- def setUp(self):
2745- """Sets up everything for the test"""
2746- EntertainerTest.setUp(self)
2747-
2748- #setup feeds and model
2749- self.feeds = self.config.feeds
2750- self.model = gtk.ListStore(str)
2751- for i in range(len(self.feeds)):
2752- self.model.insert(i, [self.feeds[i]])
2753-
2754- self.files = [THIS_DIR + "/data/FeedConfigTools/test.opml"]
2755-
2756- self.feedList = [
2757- u'http://www.hackaday.com/rss.xml',
2758- u'http://edevelop.org/planet/rss20.xml',
2759- u'http://feeds.feedburner.com/BlenderartMagazine'
2760- ]
2761-
2762- self.result_feed_list = self.feeds + self.feedList
2763-
2764- self.feed_config_tools = FeedConfigTools()
2765-
2766- def tearDown(self):
2767- """restores config to how it should be to start off"""
2768- EntertainerTest.tearDown(self)
2769-
2770- def testAddFileFeedsToWidget001(self):
2771- """Tests if self.feeds is updated correctly"""
2772- self.feed_config_tools.add_file_feeds_to_widget(
2773- self.files, self.model, self.feeds, False)
2774- self.assertEqual(self.feeds, self.result_feed_list)
2775-
2776- def testAddFileFeedsToWidget002(self):
2777- """Tests if self.config is updated correctly"""
2778- self.feed_config_tools.add_file_feeds_to_widget(
2779- self.files, self.model, self.feeds, False)
2780- self.assertEqual(self.config.feeds, self.result_feed_list)
2781-
2782- def testAddFeedsToWidget001(self):
2783- """Tests if self.feeds is updated correctly"""
2784- self.feed_config_tools.add_feeds_to_widget(
2785- self.feedList, self.model, self.feeds)
2786- self.assertEqual(self.feeds, self.result_feed_list)
2787-
2788- def testAddFeedsToWidget002(self):
2789- """Tests if self.config is updated correctly"""
2790- self.feed_config_tools.add_feeds_to_widget(
2791- self.feedList, self.model, self.feeds)
2792- self.assertEqual(self.config.feeds, self.result_feed_list)
2793-
2794
2795=== removed file 'entertainerlib/tests/test_feedentryparser.py'
2796--- entertainerlib/tests/test_feedentryparser.py 2009-05-10 17:36:49 +0000
2797+++ entertainerlib/tests/test_feedentryparser.py 1970-01-01 00:00:00 +0000
2798@@ -1,49 +0,0 @@
2799-# Copyright (c) 2009 Entertainer Developers - See COPYING - GPLv2
2800-'''Test feed entry parser'''
2801-# pylint: disable-msg=C0301
2802-
2803-from entertainerlib.tests import EntertainerTest
2804-from entertainerlib.backend.components.feeds.feed_utils import FeedEntryParser
2805-
2806-
2807-class FeedEntryParserTest(EntertainerTest):
2808- '''Test the FeedEntryParser'''
2809-
2810- def setUp(self):
2811- """Sets up everything for the test"""
2812- EntertainerTest.setUp(self)
2813-
2814- #test strings
2815- self.testString001 = "<body><b>Hello World</body></b>"
2816- self.testString002 = "<body><span id=\"001\"><u><b>&nbsp;He<i>l</i>lo <big>World</b></big><s>!</s><sub>!</sub><div><sup>!</sup><small>!</small><tt></div>...</tt></u></span></body>"
2817- self.resultString001 = "Hello World"
2818- self.resultString002 = "<span id=\"001\"><u><b>&nbsp;He<i>l</i>lo <big>World</b></big><s>!</s><sub>!</sub><sup>!</sup><small>!</small><tt>...</tt></u></span>"
2819- self.resultString003 = "<body>Hello World</body>"
2820- self.resultString004 = "<span id=\"001\"><u><b> He<i>l</i>lo <big>World</b></big><s>!</s><sub>!</sub><sup>!</sup><small>!</small><tt>...</tt></u></span>"
2821-
2822- def testStripTags001(self):
2823- """tests if FeedEntryParser strips all tags from input using default
2824- tags
2825- """
2826- output = FeedEntryParser().strip_tags(self.testString001)
2827- self.assertEqual(output, self.resultString001)
2828-
2829- def testStripTags002(self):
2830- """tests if FeedEntryParser strips all tags from input using
2831- non-default tags
2832- """
2833- output = FeedEntryParser().strip_tags(self.testString001, ["body"])
2834- self.assertEqual(output, self.resultString003)
2835-
2836- def testStripNonPangoTags(self):
2837- """testStripNonPangoTags: tests if FeedEntryParser strips all
2838- non-pango tags from input
2839- """
2840- output = FeedEntryParser().strip_non_pango_tags(self.testString002)
2841- self.assertEqual(output, self.resultString002)
2842-
2843- def testConvert(self):
2844- """tests if FeedEntryParser converts input to correct output"""
2845- output = FeedEntryParser().convert(self.testString002)
2846- self.assertEqual(output, self.resultString004)
2847-
2848
2849=== modified file 'entertainerlib/tests/test_filehandlers.py'
2850--- entertainerlib/tests/test_filehandlers.py 2009-07-12 17:31:52 +0000
2851+++ entertainerlib/tests/test_filehandlers.py 2010-04-03 15:04:16 +0000
2852@@ -1,4 +1,5 @@
2853 '''Tests for entertainerlib.indexing.handlers.'''
2854+# pylint: disable-msg=W0212
2855 import os
2856
2857 from storm.locals import Store
2858
2859=== removed file 'entertainerlib/tests/test_frontendfeed.py'
2860--- entertainerlib/tests/test_frontendfeed.py 2009-07-29 03:09:34 +0000
2861+++ entertainerlib/tests/test_frontendfeed.py 1970-01-01 00:00:00 +0000
2862@@ -1,95 +0,0 @@
2863-# Copyright (c) 2009 Entertainer Developers - See COPYING - GPLv2
2864-'''Tests feeds from the client'''
2865-
2866-from pysqlite2 import dbapi2 as sqlite
2867-
2868-from entertainerlib.client.medialibrary.feeds import Feed
2869-from entertainerlib.tests import EntertainerTest
2870-
2871-class FrontendFeedTest(EntertainerTest):
2872- '''Test reading feeds from the client'''
2873-
2874- def setUp(self):
2875- EntertainerTest.setUp(self)
2876-
2877- db_conn = sqlite.connect(self.config.FEED_DB)
2878- db_cursor = db_conn.cursor()
2879- db_cursor.execute("""DROP TABLE IF EXISTS feed""")
2880- db_cursor.execute("""DROP TABLE IF EXISTS entry""")
2881- db_cursor.execute(
2882- """CREATE TABLE feed(url TEXT, title TEXT, subtitle TEXT,
2883- description TEXT, time TIME, date DATE, PRIMARY KEY(url))""")
2884- db_cursor.execute(
2885- """CREATE TABLE entry(feed_url TEXT, title TEXT, description TEXT,
2886- isread TEXT, time TIME, date DATE, id TEXT, PRIMARY KEY(id))""")
2887- db_conn.commit()
2888-
2889- for i in range(10):
2890- feed_row = ("url"+str(i), "title"+str(i), "subtitle"+str(i),
2891- "description"+str(i), "2008-01-01", "12:00:00")
2892- db_cursor.execute(
2893- """INSERT INTO feed(url,title,subtitle,description,date,time)
2894- VALUES (?,?,?,?,?,?)""", feed_row)
2895- db_conn.commit()
2896-
2897- for i in range(9):
2898- if i % 2 == 0:
2899- read = "NO"
2900- else:
2901- read = "YES"
2902- entry_row = ("url1", "entry"+str(i), "desc", read, str(i),
2903- "2008-01-01", "12:00:00")
2904- db_cursor.execute(
2905- """INSERT INTO entry(feed_url,title,description,isread,id,date,
2906- time) VALUES (?,?,?,?,?,?,?)""", entry_row)
2907- db_conn.commit()
2908- db_conn.close()
2909-
2910- self.feed = Feed("url1")
2911-
2912- def tearDown(self):
2913- EntertainerTest.tearDown(self)
2914-
2915- db_conn = sqlite.connect(self.config.FEED_DB)
2916- db_cursor = db_conn.cursor()
2917- db_cursor.execute("""DROP TABLE IF EXISTS feed""")
2918- db_cursor.execute("""DROP TABLE IF EXISTS entry""")
2919- db_conn.commit()
2920- db_conn.close()
2921-
2922- def test_title(self):
2923- '''Test that title contains the correct value.'''
2924- self.assertEqual("title1", self.feed.title)
2925-
2926- def test_description(self):
2927- '''Test that description contains the correct value.'''
2928- self.assertEqual("description1", self.feed.description)
2929-
2930- def test_entries(self):
2931- '''Test that the entries are returned by testing the count.'''
2932- self.assertEqual(9, len(self.feed.entries))
2933-
2934- def test_get_entry(self):
2935- '''Entry of the given identifier is properly returned.'''
2936- self.assertEqual("entry3", self.feed.get_entry("3").title)
2937-
2938- def test_get_number_of_unread(self):
2939- '''Test the number of unread entries is returned.'''
2940- self.assertEqual(5, self.feed.get_number_of_unread())
2941-
2942- def test_subtitle(self):
2943- '''Test that subtitle contains the correct value.'''
2944- self.assertEqual("subtitle1", self.feed.subtitle)
2945-
2946- def test_url(self):
2947- '''Test that url contains the correct value.'''
2948- self.assertEqual("url1", self.feed.url)
2949-
2950- def test_time(self):
2951- '''Test that time contains the correct value.'''
2952- self.assertEqual("12:00:00", self.feed.time)
2953-
2954- def test_date(self):
2955- '''Test that date contains the correct value.'''
2956- self.assertEqual("2008-01-01", self.feed.date)
2957-
2958
2959=== removed file 'entertainerlib/tests/test_frontendfeedentry.py'
2960--- entertainerlib/tests/test_frontendfeedentry.py 2009-06-30 01:06:01 +0000
2961+++ entertainerlib/tests/test_frontendfeedentry.py 1970-01-01 00:00:00 +0000
2962@@ -1,92 +0,0 @@
2963-# Copyright (c) 2009 Entertainer Developers - See COPYING - GPLv2
2964-'''Tests feed entries on the client'''
2965-# pylint: disable-msg=W0212
2966-
2967-from pysqlite2 import dbapi2 as sqlite
2968-
2969-from entertainerlib.client.medialibrary.feeds import Feed, Entry
2970-from entertainerlib.tests import EntertainerTest
2971-
2972-class FrontendFeedEntryTest(EntertainerTest):
2973- '''Tests feed entries on the client'''
2974-
2975- entry_title = "Test Entry"
2976- entry_desc = "This is a test description"
2977- entry_id = "1"
2978- entry_time = "13:02"
2979- entry_date = "02/02/08"
2980-
2981- def setUp(self):
2982- EntertainerTest.setUp(self)
2983-
2984- db_conn = sqlite.connect(self.config.FEED_DB)
2985- db_cursor = db_conn.cursor()
2986- db_cursor.execute(
2987- """CREATE TABLE feed(url TEXT, title TEXT, subtitle TEXT,
2988- description TEXT, time TIME, date DATE, PRIMARY KEY(url))""")
2989- db_cursor.execute(
2990- """CREATE TABLE entry(feed_url TEXT, title TEXT, description TEXT,
2991- isread TEXT, time TIME, date DATE, id TEXT, PRIMARY KEY(id))""")
2992- db_conn.commit()
2993- entry_row = ("url2", "entry1", "desc", "NO", "1", "2008-01-01",
2994- "12:00:00")
2995- db_cursor.execute("""INSERT INTO entry(
2996- feed_url, title, description, isread, id, date, time)
2997- VALUES (?,?,?,?,?,?,?)""", entry_row)
2998-
2999- db_conn.commit()
3000- feed_row = ("url2", "title2", "subtitle2", "description2", "2008-01-01",
3001- "12:00:00")
3002- db_cursor.execute(
3003- """INSERT INTO feed(url, title, subtitle, description, date, time)
3004- VALUES (?,?,?,?,?,?)""", feed_row)
3005- db_conn.commit()
3006- db_conn.close()
3007-
3008- self.entry = Entry(self.entry_title, self.entry_desc, self.entry_id,
3009- self.entry_time, self.entry_date, False)
3010-
3011- def tearDown(self):
3012- EntertainerTest.tearDown(self)
3013-
3014- db_conn = sqlite.connect(self.config.FEED_DB)
3015- db_cursor = db_conn.cursor()
3016- db_cursor.execute("""DROP TABLE IF EXISTS feed""")
3017- db_cursor.execute("""DROP TABLE IF EXISTS entry""")
3018- db_conn.commit()
3019- db_conn.close()
3020-
3021- def test_init_read_entry(self):
3022- '''Test if Entry can handle the additional read parameter.'''
3023- new_entry = Entry(self.entry_title, self.entry_desc, self.entry_id,
3024- self.entry_time, self.entry_date, True)
3025- self.assertTrue(new_entry.read)
3026-
3027- def test_title(self):
3028- '''Test the title property.'''
3029- self.assertEqual(self.entry_title, self.entry.title)
3030-
3031- def test_description(self):
3032- '''Test the description property.'''
3033- self.assertEqual(self.entry_desc, self.entry.description)
3034-
3035- def test_identifier(self):
3036- '''Test the identifier property.'''
3037- self.assertEqual(self.entry_id, self.entry.identifier)
3038-
3039- def test_time(self):
3040- '''Test the time property.'''
3041- self.assertEqual(self.entry_time, self.entry.time)
3042-
3043- def test_date(self):
3044- '''Test the date property.'''
3045- self.assertEqual(self.entry_date, self.entry.date)
3046-
3047- def test_read(self):
3048- '''Test the read property and check the if the database updated.'''
3049- self.assertFalse(self.entry.read)
3050- feed = Feed("url2")
3051- self.entry._set_read(True)
3052- self.assertTrue(self.entry.read)
3053- self.assertEqual(feed.get_number_of_unread(), 0)
3054-
3055
3056=== removed file 'entertainerlib/tests/test_frontendfeedlibrary.py'
3057--- entertainerlib/tests/test_frontendfeedlibrary.py 2009-09-08 02:40:16 +0000
3058+++ entertainerlib/tests/test_frontendfeedlibrary.py 1970-01-01 00:00:00 +0000
3059@@ -1,107 +0,0 @@
3060-# Copyright (c) 2009 Entertainer Developers - See COPYING - GPLv2
3061-'''Tests feed library from the client'''
3062-
3063-from pysqlite2 import dbapi2 as sqlite
3064-
3065-from entertainerlib.client.medialibrary.feeds import FeedLibrary
3066-from entertainerlib.tests import EntertainerTest
3067-
3068-class FrontendFeedLibraryTest(EntertainerTest):
3069- """
3070- Tests the client.medialibrary.feeds.FeedLibrary object
3071- @todo comment tests
3072- @todo the test database doesn't seem to be working
3073- """
3074-
3075- def setUp(self):
3076- EntertainerTest.setUp(self)
3077-
3078- db_conn = sqlite.connect(self.config.FEED_DB)
3079- db_cursor = db_conn.cursor()
3080- db_cursor.execute(
3081- """CREATE TABLE feed(url TEXT, title TEXT, subtitle TEXT,
3082- description TEXT, time TIME, date DATE, PRIMARY KEY(url))""")
3083-
3084- db_cursor.execute(
3085- """CREATE TABLE entry(feed_url TEXT, title TEXT, description TEXT,
3086- isread TEXT, time TIME, date DATE, id TEXT, PRIMARY KEY(id))""")
3087- db_conn.commit()
3088-
3089- for i in range(10):
3090- feed_row = ("url"+str(i), "title"+str(i), "subtitle"+str(i),
3091- "description"+str(i), "2008-01-01", "12:00:00")
3092- db_cursor.execute(
3093- """INSERT INTO feed(url,title,subtitle,description,date,time)
3094- VALUES (?,?,?,?,?,?)""", feed_row)
3095- db_conn.commit()
3096- for i in range(9):
3097- if i % 2 == 0:
3098- read = "NO"
3099- else:
3100- read = "YES"
3101- entry_row = ("url2", "entry"+str(i), "desc", read, str(i),
3102- "2008-01-01", "12:00:0"+str(i))
3103- db_cursor.execute(
3104- """INSERT INTO entry(feed_url, title, description, isread, id,
3105- date, time) VALUES (?,?,?,?,?,?,?)""", entry_row)
3106- db_conn.commit()
3107- db_conn.close()
3108-
3109- self.library = FeedLibrary(None)
3110-
3111- def tearDown(self):
3112- EntertainerTest.tearDown(self)
3113-
3114- db_conn = sqlite.connect(self.config.FEED_DB)
3115- db_cursor = db_conn.cursor()
3116- db_cursor.execute("""DROP TABLE IF EXISTS feed""")
3117- db_cursor.execute("""DROP TABLE IF EXISTS entry""")
3118- db_conn.commit()
3119- db_conn.close()
3120-
3121- def testIsEmptyWhenFull(self):
3122- """
3123- testIsEmptyWhenFull: Tests FeedLibrary.is_empty() when there are feeds
3124- in database
3125- """
3126- self.assertFalse(self.library.is_empty())
3127-
3128- def testGetFeeds(self):
3129- """
3130- testGetFeeds: Tests FeedLibrary.get_feeds() sorted by TITLE
3131- """
3132- feedlist = self.library.get_feeds('TITLE')
3133- for i in range(10):
3134- self.assertEqual(feedlist[i].url, "url"+str(i))
3135-
3136- def testGetFeedsByUnread(self):
3137- """
3138- testGetFeedsByUnread: Tests FeedLibrary.get_feeds() sorted by unread
3139- """
3140- feedlist = self.library.get_feeds('UNREAD')
3141- self.assertEqual(feedlist[0].url, "url2")
3142-
3143- def test_get_latest_entries(self):
3144- '''Test that the latest entries are returned.'''
3145- latest = self.library.get_latest_entries(1)
3146- self.assertEqual("12:00:08", str(latest[0][1].time))
3147-
3148- def testNumberOfFeeds(self):
3149- """
3150- testNumberOfFeeds: Tests FeedLibrary.number_of_feeds()
3151- """
3152- self.assertEqual(self.library.number_of_feeds(), 10)
3153-
3154- def testNumberOfUnreadEntries(self):
3155- """
3156- testNumberOfUnreadEntries: Tests FeedLibrary.number_of_unread_entries()
3157- """
3158- self.assertEqual(self.library.number_of_unread_entries(), 5)
3159-
3160- def testMarkAllAsRead(self):
3161- """
3162- testMarkAllAsRead: tests if all entries are marked as read
3163- """
3164- self.library.mark_all_as_read()
3165- self.assertEqual(self.library.number_of_unread_entries(), 0)
3166-
3167
3168=== modified file 'entertainerlib/tests/test_models.py'
3169--- entertainerlib/tests/test_models.py 2009-06-17 03:43:51 +0000
3170+++ entertainerlib/tests/test_models.py 2010-04-03 15:04:16 +0000
3171@@ -20,51 +20,6 @@
3172 class TestBaseModel(ModelTestCase):
3173 '''BaseModel test case.'''
3174
3175-class TestNewsFeed(ModelTestCase):
3176- '''NewsFeed test case'''
3177-
3178- def testCreate(self):
3179- '''Test creation of new NewsFeed'''
3180-
3181- store = Store(self.db)
3182-
3183- newsfeed = models.NewsFeed()
3184- newsfeed.url = u'http://theironlion.net/blog/feed'
3185- newsfeed.title = u'The Iron Lion'
3186- newsfeed.description = u'Paul Hummer\'s Blog'
3187- store.add(newsfeed)
3188- store.commit()
3189-
3190- self.assertTrue(Store.of(newsfeed) is store)
3191-
3192- newsfeed_from_database = store.find(models.NewsFeed,
3193- models.NewsFeed.title == u'The Iron Lion').one()
3194-
3195- self.assertTrue(newsfeed is newsfeed_from_database)
3196-
3197-
3198-class TestNewsEntry(ModelTestCase):
3199- '''NewsEntry test case'''
3200-
3201- def testCreate(self):
3202- '''Test creation of new NewsEntry'''
3203-
3204- store = Store(self.db)
3205- newsentry = models.NewsEntry()
3206- newsentry.url = u'http://theironlion.net/blog/foo-bar-baz'
3207- newsentry.title = u'Foo Bar Baz'
3208- newsentry.description = u'There once was a girl from Nantucket'
3209- newsentry.is_read = 0
3210- store.add(newsentry)
3211-
3212- store.commit()
3213-
3214- self.assertTrue(Store.of(newsentry) is store)
3215-
3216- newsentry_from_database = store.find(models.NewsEntry,
3217- models.NewsEntry.title == u'Foo Bar Baz').one()
3218- self.assertTrue(newsentry is newsentry_from_database)
3219-
3220
3221 class TestPhotoAlbum(ModelTestCase):
3222 '''PhotoAlbum test case'''
3223
3224=== modified file 'entertainerlib/tests/test_music.py'
3225--- entertainerlib/tests/test_music.py 2010-01-03 22:58:00 +0000
3226+++ entertainerlib/tests/test_music.py 2010-04-03 15:04:16 +0000
3227@@ -1,5 +1,6 @@
3228 # Copyright (c) 2009 Entertainer Developers - See COPYING - GPLv2
3229 '''Tests Music'''
3230+# pylint: disable-msg=W0212
3231
3232 import os
3233
3234@@ -129,6 +130,7 @@
3235 bad_track = Track('', '', 1, '', 'foo-bar-baz**', 2, 3, '',
3236 self.music_library._create_album)
3237 try:
3238+ # pylint: disable-msg=W0612
3239 album = bad_track.album
3240 self.fail()
3241 except AlbumHasNoTracks:
3242@@ -264,7 +266,7 @@
3243 self.music_library = MusicLibrary()
3244 self.album = self.music_library._create_album('album1')
3245
3246- def testAlbumConstructor(self):
3247+ def test_constructor(self):
3248 """Test that an Album object is properly constructed"""
3249 self.assertTrue(isinstance(self.album, Album))
3250 self.assertEqual(self.album.artist, 'artist0')
3251@@ -272,13 +274,13 @@
3252 self.assertEqual(self.album.title, 'album1')
3253 self.assertEqual(self.album.year, 0)
3254
3255- def testAlbumConstructorNot(self):
3256+ def test_constructor_not(self):
3257 """Test that an AlbumHasNoTracks exception is raised when the created
3258 album doesn't exist in the cache"""
3259 self.assertRaises(AlbumHasNoTracks, self.music_library._create_album,
3260 'foo')
3261
3262- def testAlbumHasAlbumArt(self):
3263+ def test_has_album_art(self):
3264 """Test that album art exists for the file"""
3265 album_artist = "artist0 - album1"
3266 album_artist = album_artist.encode("base64")
3267@@ -288,12 +290,12 @@
3268 if os.path.exists(album_art):
3269 os.remove(album_art)
3270
3271- def testAlbumHasAlbumArtNot(self):
3272+ def test_has_album_art_not(self):
3273 """Test that missing album art is reported back"""
3274 other_album = self.music_library._create_album('album1')
3275 self.assertFalse(other_album.has_album_art())
3276
3277- def testAlbumGetAlbumArtUrl(self):
3278+ def test_album_art_url(self):
3279 """Test that the path to the album's art is returned"""
3280 result = self.album.album_art_url
3281 album_artist = "artist0 - album1"
3282@@ -301,7 +303,7 @@
3283 album_art = os.path.join(self.art_path, album_artist + ".jpg")
3284 self.assertEqual(result, album_art)
3285
3286- def testAlbumGetTracks(self):
3287+ def test_tracks(self):
3288 """Test that all tracks for an album are returned"""
3289 result = self.album.tracks
3290 self.assertEqual(len(result), 4)
3291
3292=== removed file 'entertainerlib/tests/test_opmlparser.py'
3293--- entertainerlib/tests/test_opmlparser.py 2009-05-10 17:36:49 +0000
3294+++ entertainerlib/tests/test_opmlparser.py 1970-01-01 00:00:00 +0000
3295@@ -1,103 +0,0 @@
3296-# Copyright (c) 2009 Entertainer Developers - See COPYING - GPLv2
3297-'''Tests OPMLParser'''
3298-# pylint: disable-msg=C0301
3299-
3300-import os
3301-import xml.parsers.expat
3302-
3303-from entertainerlib.backend.components.feeds.feed_utils import OPMLParser
3304-from entertainerlib.tests import EntertainerTest
3305-
3306-THIS_DIR = os.path.dirname(__file__)
3307-
3308-
3309-class OPMLParserTest(EntertainerTest):
3310- '''Test OPMLParser'''
3311-
3312- def setUp(self):
3313- '''See unittest.TestCase'''
3314- EntertainerTest.setUp(self)
3315-
3316- #set up lists and paths
3317- self.testURL = "http://www.scripting.com/feeds/top100.opml"
3318- self.multipleLifereaFolders = (THIS_DIR +
3319- '/data/OPMLParser/lifereaMultiple')
3320- self.singleLifereaFolder = (THIS_DIR +
3321- '/data/OPMLParser/lifereaSingle')
3322- self.noLifereaFolder = (THIS_DIR +
3323- '/data/OPMLParser/lifereaNoFolder')
3324- self.noLifereaFile = (THIS_DIR +
3325- '/data/OPMLParser/lifereaNoFile')
3326- self.okFilePath = (THIS_DIR +
3327- '/data/OPMLParser/test.opml')
3328- self.badFilePath = THIS_DIR + '/data/OPMLParser/null.opml'
3329- self.notXMLFile = THIS_DIR + '/data/OPMLParser/noXML.txt'
3330- self.insideFilePath = (THIS_DIR +
3331- '/data/OPMLParser/opmlInOpml.opml')
3332- self.feedList = [
3333- "http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/front_page/rss.xml",
3334- "http://www.hackaday.com/rss.xml",
3335- "http://edevelop.org/planet/rss20.xml",
3336- "http://feeds.feedburner.com/BlenderartMagazine"]
3337-
3338- def testGetRssFeeds001(self):
3339- """Check if OPMLParser can parse a normal file"""
3340- output = OPMLParser().get_rss_feeds(self.okFilePath)
3341- self.assertEqual(output, self.feedList)
3342-
3343- def testGetRssFeeds002(self):
3344- """Check if OPMLParser can handle a non-existant file"""
3345- self.assertRaises(IOError, OPMLParser().get_rss_feeds,
3346- self.badFilePath)
3347-
3348- def testGetRssFeeds003(self):
3349- """Check if OPMLParser discards opml links inside the file
3350- This is the same file as for testGetRssFeeds001 with an extra link to
3351- an opml file.
3352-
3353- The OPMLParser should discard the opml file and return the rest of the
3354- links
3355- """
3356- output = OPMLParser().get_rss_feeds(self.insideFilePath)
3357- self.assertEqual(output, self.feedList)
3358-
3359- def testGetRssFeeds004(self):
3360- """Check if OPMLParser can handle a file which is not an opml file or
3361- even an xml file
3362- """
3363- self.assertRaises(xml.parsers.expat.ExpatError,
3364- OPMLParser().get_rss_feeds, self.notXMLFile)
3365-
3366- def testGetRssFeeds005(self):
3367- """Check if OPMLParser can handle a URL"""
3368- output = OPMLParser().get_rss_feeds(self.testURL)
3369- self.assertTrue(output != [])
3370-
3371- def testGetLifereaOpml001(self):
3372- """Check if OPMLParser can pick the opml file for liferea"""
3373- output = OPMLParser().get_liferea_opml(self.singleLifereaFolder)
3374- self.assertEqual(output,
3375- self.singleLifereaFolder+"/.liferea/feedlist.opml")
3376-
3377- def testGetLifereaOpml002(self):
3378- """Check if OPMLParser can pick the opml file for the latest version
3379- of liferea out of a selection of folders
3380- """
3381- output = OPMLParser().get_liferea_opml(self.multipleLifereaFolders)
3382- self.assertEqual(output,
3383- self.multipleLifereaFolders+"/.liferea_1.4/feedlist.opml")
3384-
3385- def testGetLifereaOpml003(self):
3386- """Check if OPMLParser returns an empty string if it can't find the
3387- liferea opml folder
3388- """
3389- output = OPMLParser().get_liferea_opml(self.noLifereaFolder)
3390- self.assertEqual(output, "")
3391-
3392- def testGetLifereaOpml004(self):
3393- """Check if OPMLParser returns an empty string if it can't find the
3394- liferea opml file
3395- """
3396- output = OPMLParser().get_liferea_opml(self.noLifereaFile)
3397- self.assertEqual(output, "")
3398-
3399
3400=== modified file 'entertainerlib/tests/test_screenfactory.py'
3401--- entertainerlib/tests/test_screenfactory.py 2009-06-17 02:49:44 +0000
3402+++ entertainerlib/tests/test_screenfactory.py 2010-04-03 15:04:16 +0000
3403@@ -4,13 +4,12 @@
3404
3405 import os
3406
3407+from entertainerlib.client.medialibrary import music
3408 from entertainerlib.gui.screens.album import Album
3409 from entertainerlib.gui.screens.artist import Artist
3410 from entertainerlib.gui.screens.audio_play import AudioPlay
3411 from entertainerlib.gui.screens.disc import Disc
3412 from entertainerlib.gui.screens.factory import ScreenFactory
3413-from entertainerlib.gui.screens.feed import Feed
3414-from entertainerlib.gui.screens.feed_entry import FeedEntry
3415 from entertainerlib.gui.screens.main import Main
3416 from entertainerlib.gui.screens.movie import Movie
3417 from entertainerlib.gui.screens.music import Music
3418@@ -18,23 +17,17 @@
3419 from entertainerlib.gui.screens.photo_albums import PhotoAlbums
3420 from entertainerlib.gui.screens.photographs import Photographs
3421 from entertainerlib.gui.screens.question import Question
3422-from entertainerlib.gui.screens.rss import Rss
3423 from entertainerlib.gui.screens.tv_episodes import TvEpisodes
3424 from entertainerlib.gui.screens.tv_series import TvSeries
3425 from entertainerlib.gui.screens.video_osd import VideoOSD
3426 from entertainerlib.gui.screens.video import Video
3427 from entertainerlib.gui.screens.weather import WeatherScreen
3428 from entertainerlib.tests import EntertainerTest
3429-from entertainerlib.tests.mock import MockAlbum
3430-from entertainerlib.tests.mock import MockEntry
3431-from entertainerlib.tests.mock import MockFeed
3432-from entertainerlib.tests.mock import MockFeedLibrary
3433 from entertainerlib.tests.mock import MockImage
3434 from entertainerlib.tests.mock import MockImageLibrary
3435 from entertainerlib.tests.mock import MockMediaPlayer
3436 from entertainerlib.tests.mock import MockMovie
3437 from entertainerlib.tests.mock import MockMusicLibrary
3438-from entertainerlib.tests.mock import MockTrack
3439 from entertainerlib.tests.mock import MockTVSeries
3440 from entertainerlib.tests.mock import MockVideoLibrary
3441
3442@@ -45,12 +38,11 @@
3443 def setUp(self):
3444 EntertainerTest.setUp(self)
3445
3446- feed_library = MockFeedLibrary()
3447 image_libary = MockImageLibrary()
3448 music_library = MockMusicLibrary()
3449 media_player = MockMediaPlayer()
3450 video_library = MockVideoLibrary()
3451- self.factory = ScreenFactory(feed_library, image_libary, music_library,
3452+ self.factory = ScreenFactory(image_libary, music_library,
3453 video_library, media_player, None, None)
3454
3455 self.kwargs = {}
3456@@ -61,7 +53,7 @@
3457
3458 def test__generate_album(self):
3459 '''Test _generate_album returns a Album screen'''
3460- self.kwargs['album'] = MockAlbum()
3461+ self.kwargs['album'] = music.Album('', '', 240, 2010, '', [])
3462 screen = self.factory._generate_album(self.kwargs)
3463 self.assertTrue(isinstance(screen, Album))
3464
3465@@ -73,7 +65,9 @@
3466
3467 def test__generate_audio_play(self):
3468 '''Test _generate_audio_play returns a AudioPlay screen'''
3469- self.kwargs['track'] = MockTrack()
3470+ album = music.Album('', '', 240, 2010, '', [])
3471+ track = music.Track('', '', 1, '', album, 2010, 60, '', None)
3472+ self.kwargs['track'] = track
3473 screen = self.factory._generate_audio_play(self.kwargs)
3474 self.assertTrue(isinstance(screen, AudioPlay))
3475
3476@@ -82,19 +76,6 @@
3477 screen = self.factory._generate_disc(self.kwargs)
3478 self.assertTrue(isinstance(screen, Disc))
3479
3480- def test__generate_feed(self):
3481- '''Test _generate_feed returns a Feed screen'''
3482- self.kwargs['feed'] = MockFeed()
3483- screen = self.factory._generate_feed(self.kwargs)
3484- self.assertTrue(isinstance(screen, Feed))
3485-
3486- def test__generate_feed_entry(self):
3487- '''Test _generate_feed_entry returns a FeedEntry screen'''
3488- self.kwargs['entry'] = MockEntry()
3489- self.kwargs['feed'] = MockFeed()
3490- screen = self.factory._generate_feed_entry(self.kwargs)
3491- self.assertTrue(isinstance(screen, FeedEntry))
3492-
3493 def test__generate_main(self):
3494 '''Test _generate_main returns a Main screen'''
3495 screen = self.factory._generate_main(self.kwargs)
3496@@ -140,11 +121,6 @@
3497 screen = self.factory._generate_question(self.kwargs)
3498 self.assertTrue(isinstance(screen, Question))
3499
3500- def test__generate_rss(self):
3501- '''Test _generate_rss returns a Rss screen'''
3502- screen = self.factory._generate_rss(self.kwargs)
3503- self.assertTrue(isinstance(screen, Rss))
3504-
3505 def test__generate_tv_series(self):
3506 '''Test _generate_tv_series returns a TvSeries screen'''
3507 self.kwargs['tv_series'] = MockTVSeries()
3508
3509=== modified file 'entertainerlib/tests/test_userinterface.py'
3510--- entertainerlib/tests/test_userinterface.py 2009-06-17 03:22:28 +0000
3511+++ entertainerlib/tests/test_userinterface.py 2010-04-03 15:04:16 +0000
3512@@ -8,7 +8,6 @@
3513 from entertainerlib.gui.user_interface import UserInterface
3514 from entertainerlib.tests import EntertainerTest
3515 from entertainerlib.tests.mock import MockClutterKeyboardEvent
3516-from entertainerlib.tests.mock import MockFeedLibrary
3517
3518
3519 class UserInterfaceTest(EntertainerTest):
3520@@ -17,8 +16,7 @@
3521 def setUp(self):
3522 EntertainerTest.setUp(self)
3523
3524- feed_library = MockFeedLibrary()
3525- self.ui = UserInterface(feed_library, None, None, None, None)
3526+ self.ui = UserInterface(None, None, None, None)
3527
3528 def test_create(self):
3529 '''Test correct UserInterface initialization'''
3530
3531=== modified file 'entertainerlib/tests/test_videometadatasearch.py'
3532--- entertainerlib/tests/test_videometadatasearch.py 2009-05-09 15:45:18 +0000
3533+++ entertainerlib/tests/test_videometadatasearch.py 2010-04-03 15:04:16 +0000
3534@@ -1,7 +1,6 @@
3535 # Copyright (c) 2009 Entertainer Developers - See COPYING - GPLv2
3536 '''Tests VideoMetadataSearch'''
3537
3538-# XXX: rockstar - Modules should not get this deep
3539 from entertainerlib.backend.components.mediacache.video_metadata_search import (
3540 VideoMetadataSearch)
3541 from entertainerlib.tests import EntertainerTest
3542
3543=== modified file 'entertainerlib/uis/manager.ui'
3544--- entertainerlib/uis/manager.ui 2009-11-11 10:22:36 +0000
3545+++ entertainerlib/uis/manager.ui 2010-04-03 15:04:16 +0000
3546@@ -1,24 +1,24 @@
3547 <?xml version="1.0"?>
3548-<!--*- mode: xml -*-->
3549 <interface>
3550+ <!-- interface-requires gtk+ 2.12 -->
3551+ <!-- interface-naming-policy toplevel-contextual -->
3552 <object class="GtkAdjustment" id="adjustment1">
3553+ <property name="value">60</property>
3554+ <property name="lower">15</property>
3555 <property name="upper">900</property>
3556- <property name="lower">15</property>
3557- <property name="page_increment">10</property>
3558 <property name="step_increment">1</property>
3559- <property name="page_size">0</property>
3560- <property name="value">60</property>
3561+ <property name="page_increment">0</property>
3562 </object>
3563 <object class="GtkAdjustment" id="adjustment2">
3564+ <property name="value">1</property>
3565 <property name="upper">100</property>
3566- <property name="lower">0</property>
3567+ <property name="step_increment">1</property>
3568 <property name="page_increment">10</property>
3569- <property name="step_increment">1</property>
3570- <property name="page_size">10</property>
3571- <property name="value">1</property>
3572+ <property name="page_size">0</property>
3573 </object>
3574 <object class="GtkListStore" id="model1">
3575 <columns>
3576+ <!-- column-name gchararray -->
3577 <column type="gchararray"/>
3578 </columns>
3579 <data>
3580@@ -37,199 +37,141 @@
3581 </data>
3582 </object>
3583 <object class="GtkDialog" id="ManagerDialog">
3584+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3585 <property name="border_width">5</property>
3586- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3587 <property name="title" translatable="yes">Entertainer Manager</property>
3588- <property name="type">GTK_WINDOW_TOPLEVEL</property>
3589- <property name="window_position">GTK_WIN_POS_NONE</property>
3590 <property name="modal">True</property>
3591- <property name="resizable">True</property>
3592- <property name="destroy_with_parent">False</property>
3593 <property name="icon_name">applications-multimedia</property>
3594- <property name="decorated">True</property>
3595- <property name="skip_taskbar_hint">False</property>
3596- <property name="skip_pager_hint">False</property>
3597- <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
3598- <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
3599- <property name="focus_on_map">True</property>
3600- <property name="urgency_hint">False</property>
3601+ <property name="type_hint">dialog</property>
3602 <property name="has_separator">False</property>
3603- <signal handler="on_ManagerDialog_destroy" last_modification_time="Sun, 23 Aug 2009 00:27:03 GMT" name="destroy"/>
3604+ <signal name="destroy" handler="on_ManagerDialog_destroy"/>
3605 <child internal-child="vbox">
3606 <object class="GtkVBox" id="dialog-layout">
3607 <property name="visible">True</property>
3608- <property name="homogeneous">False</property>
3609 <property name="spacing">2</property>
3610- <child internal-child="action_area">
3611- <object class="GtkHButtonBox" id="dialog-closebutton-area">
3612- <property name="visible">True</property>
3613- <property name="layout_style">GTK_BUTTONBOX_END</property>
3614- <child>
3615- <object class="GtkButton" id="close_button">
3616- <property name="visible">True</property>
3617- <property name="can_focus">True</property>
3618- <property name="label">gtk-close</property>
3619- <property name="use_stock">True</property>
3620- <property name="relief">GTK_RELIEF_NORMAL</property>
3621- <property name="focus_on_click">True</property>
3622- <signal handler="on_close_button_clicked" name="clicked"/>
3623- </object>
3624- </child>
3625- </object>
3626- <packing>
3627- <property name="padding">0</property>
3628- <property name="expand">False</property>
3629- <property name="fill">True</property>
3630- <property name="pack_type">GTK_PACK_END</property>
3631- </packing>
3632- </child>
3633 <child>
3634 <object class="GtkNotebook" id="tabs">
3635 <property name="visible">True</property>
3636+ <property name="can_focus">True</property>
3637+ <property name="has_focus">True</property>
3638 <property name="can_default">True</property>
3639 <property name="has_default">True</property>
3640- <property name="can_focus">True</property>
3641- <property name="has_focus">True</property>
3642- <property name="show_tabs">True</property>
3643- <property name="show_border">True</property>
3644- <property name="tab_pos">GTK_POS_TOP</property>
3645- <property name="scrollable">False</property>
3646- <property name="enable_popup">False</property>
3647 <child>
3648 <object class="GtkVBox" id="vbox_media">
3649 <property name="visible">True</property>
3650- <property name="homogeneous">False</property>
3651- <property name="spacing">0</property>
3652 <child>
3653 <object class="GtkVBox" id="vbox1">
3654 <property name="visible">True</property>
3655- <property name="homogeneous">False</property>
3656- <property name="spacing">0</property>
3657 <child>
3658 <object class="GtkFrame" id="frame_video_lib1">
3659+ <property name="visible">True</property>
3660 <property name="border_width">5</property>
3661- <property name="visible">True</property>
3662 <property name="label_xalign">0</property>
3663- <property name="label_yalign">0.5</property>
3664- <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
3665 <child>
3666 <object class="GtkVBox" id="vbox2">
3667 <property name="visible">True</property>
3668- <property name="homogeneous">False</property>
3669- <property name="spacing">0</property>
3670 <child>
3671 <object class="GtkLabel" id="label_media_folder_tip1">
3672 <property name="visible">True</property>
3673- <property name="label" translatable="yes">Entertainer will catalog the media in the folders below.</property>
3674- <property name="use_underline">False</property>
3675- <property name="use_markup">False</property>
3676- <property name="justify">GTK_JUSTIFY_LEFT</property>
3677- <property name="wrap">True</property>
3678- <property name="selectable">False</property>
3679 <property name="xalign">0</property>
3680 <property name="yalign">0</property>
3681 <property name="xpad">5</property>
3682- <property name="ypad">0</property>
3683- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
3684- <property name="width_chars">-1</property>
3685+ <property name="label" translatable="yes">Entertainer will catalog the media in the folders below.</property>
3686+ <property name="wrap">True</property>
3687 <property name="single_line_mode">True</property>
3688- <property name="angle">0</property>
3689 </object>
3690 <packing>
3691+ <property name="expand">False</property>
3692 <property name="padding">5</property>
3693- <property name="expand">False</property>
3694- <property name="fill">True</property>
3695+ <property name="position">0</property>
3696 </packing>
3697 </child>
3698 <child>
3699 <object class="GtkHBox" id="hbox2">
3700 <property name="visible">True</property>
3701- <property name="homogeneous">False</property>
3702- <property name="spacing">0</property>
3703 <child>
3704 <object class="GtkScrolledWindow" id="scrolledwindow1">
3705- <property name="border_width">5</property>
3706 <property name="visible">True</property>
3707 <property name="can_focus">True</property>
3708- <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
3709- <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
3710- <property name="shadow_type">GTK_SHADOW_NONE</property>
3711- <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
3712+ <property name="border_width">5</property>
3713+ <property name="hscrollbar_policy">automatic</property>
3714+ <property name="vscrollbar_policy">automatic</property>
3715 <child>
3716 <object class="GtkTreeView" id="treeview_media">
3717 <property name="visible">True</property>
3718 <property name="can_focus">True</property>
3719 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
3720- <property name="headers_visible">True</property>
3721- <property name="rules_hint">False</property>
3722- <property name="reorderable">False</property>
3723 <property name="enable_search">False</property>
3724- <property name="fixed_height_mode">False</property>
3725- <property name="hover_selection">False</property>
3726- <property name="hover_expand">False</property>
3727 </object>
3728 </child>
3729 </object>
3730 <packing>
3731- <property name="padding">0</property>
3732- <property name="expand">True</property>
3733- <property name="fill">True</property>
3734+ <property name="position">0</property>
3735 </packing>
3736 </child>
3737 <child>
3738 <object class="GtkVButtonBox" id="vbuttonbox1">
3739+ <property name="visible">True</property>
3740 <property name="border_width">5</property>
3741- <property name="visible">True</property>
3742- <property name="layout_style">GTK_BUTTONBOX_DEFAULT_STYLE</property>
3743 <property name="spacing">2</property>
3744 <child>
3745 <object class="GtkButton" id="button_add_folder">
3746+ <property name="label">gtk-add</property>
3747 <property name="visible">True</property>
3748+ <property name="can_focus">True</property>
3749+ <property name="has_focus">True</property>
3750 <property name="can_default">True</property>
3751 <property name="has_default">True</property>
3752- <property name="can_focus">True</property>
3753- <property name="has_focus">True</property>
3754- <property name="label">gtk-add</property>
3755+ <property name="receives_default">False</property>
3756 <property name="use_stock">True</property>
3757- <property name="relief">GTK_RELIEF_NORMAL</property>
3758- <property name="focus_on_click">True</property>
3759- <signal handler="on_button_add_media_clicked" last_modification_time="Sat, 11 Jul 2009 19:03:28 GMT" name="clicked"/>
3760+ <signal name="clicked" handler="on_button_add_media_clicked"/>
3761 </object>
3762+ <packing>
3763+ <property name="expand">False</property>
3764+ <property name="fill">False</property>
3765+ <property name="position">0</property>
3766+ </packing>
3767 </child>
3768 <child>
3769 <object class="GtkButton" id="button_remove_folder">
3770- <property name="visible">True</property>
3771- <property name="can_focus">True</property>
3772 <property name="label">gtk-remove</property>
3773+ <property name="visible">True</property>
3774+ <property name="can_focus">True</property>
3775+ <property name="receives_default">False</property>
3776 <property name="use_stock">True</property>
3777- <property name="relief">GTK_RELIEF_NORMAL</property>
3778- <property name="focus_on_click">True</property>
3779- <signal handler="on_button_remove_media_clicked" last_modification_time="Sat, 11 Jul 2009 19:03:39 GMT" name="clicked"/>
3780+ <signal name="clicked" handler="on_button_remove_media_clicked"/>
3781 </object>
3782+ <packing>
3783+ <property name="expand">False</property>
3784+ <property name="fill">False</property>
3785+ <property name="position">1</property>
3786+ </packing>
3787 </child>
3788 <child>
3789 <object class="GtkButton" id="button_edit_folder">
3790- <property name="visible">True</property>
3791- <property name="can_focus">True</property>
3792 <property name="label">gtk-edit</property>
3793+ <property name="visible">True</property>
3794+ <property name="can_focus">True</property>
3795+ <property name="receives_default">False</property>
3796 <property name="use_stock">True</property>
3797- <property name="relief">GTK_RELIEF_NORMAL</property>
3798- <property name="focus_on_click">True</property>
3799- <signal handler="on_button_edit_media_clicked" last_modification_time="Sat, 11 Jul 2009 19:03:49 GMT" name="clicked"/>
3800+ <signal name="clicked" handler="on_button_edit_media_clicked"/>
3801 </object>
3802+ <packing>
3803+ <property name="expand">False</property>
3804+ <property name="fill">False</property>
3805+ <property name="position">2</property>
3806+ </packing>
3807 </child>
3808 </object>
3809 <packing>
3810+ <property name="expand">False</property>
3811 <property name="padding">5</property>
3812- <property name="expand">False</property>
3813- <property name="fill">True</property>
3814+ <property name="position">1</property>
3815 </packing>
3816 </child>
3817 </object>
3818 <packing>
3819- <property name="padding">0</property>
3820- <property name="expand">True</property>
3821- <property name="fill">True</property>
3822+ <property name="position">1</property>
3823 </packing>
3824 </child>
3825 </object>
3826@@ -238,563 +180,207 @@
3827 <object class="GtkLabel" id="label_media_library">
3828 <property name="visible">True</property>
3829 <property name="label" translatable="yes">&lt;b&gt;Media Library&lt;/b&gt;</property>
3830- <property name="use_underline">False</property>
3831 <property name="use_markup">True</property>
3832- <property name="justify">GTK_JUSTIFY_LEFT</property>
3833- <property name="wrap">False</property>
3834- <property name="selectable">False</property>
3835- <property name="xalign">0.5</property>
3836- <property name="yalign">0.5</property>
3837- <property name="xpad">0</property>
3838- <property name="ypad">0</property>
3839- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
3840- <property name="width_chars">-1</property>
3841- <property name="single_line_mode">False</property>
3842- <property name="angle">0</property>
3843 </object>
3844 </child>
3845 </object>
3846 <packing>
3847- <property name="padding">0</property>
3848 <property name="expand">False</property>
3849- <property name="fill">True</property>
3850+ <property name="position">0</property>
3851 </packing>
3852 </child>
3853 <child>
3854 <object class="GtkVBox" id="vbox23">
3855+ <property name="visible">True</property>
3856 <property name="border_width">5</property>
3857- <property name="visible">True</property>
3858- <property name="homogeneous">False</property>
3859- <property name="spacing">0</property>
3860 <child>
3861 <object class="GtkCheckButton" id="video_metadata_checkbox">
3862- <property name="visible">True</property>
3863- <property name="can_focus">True</property>
3864 <property name="label" translatable="yes">Download movie and TV-series metadata</property>
3865+ <property name="visible">True</property>
3866+ <property name="can_focus">True</property>
3867+ <property name="receives_default">False</property>
3868 <property name="use_underline">True</property>
3869- <property name="relief">GTK_RELIEF_NORMAL</property>
3870- <property name="focus_on_click">True</property>
3871- <property name="active">False</property>
3872- <property name="inconsistent">False</property>
3873 <property name="draw_indicator">True</property>
3874- <signal handler="on_checkbutton_video_metadata_toggled" last_modification_time="Sat, 11 Jul 2009 19:09:32 GMT" name="toggled"/>
3875+ <signal name="toggled" handler="on_checkbutton_video_metadata_toggled"/>
3876 </object>
3877 <packing>
3878- <property name="padding">1</property>
3879 <property name="expand">False</property>
3880 <property name="fill">False</property>
3881+ <property name="padding">1</property>
3882+ <property name="position">0</property>
3883 </packing>
3884 </child>
3885 <child>
3886 <object class="GtkCheckButton" id="art_checkbox">
3887- <property name="visible">True</property>
3888- <property name="can_focus">True</property>
3889 <property name="label" translatable="yes">Download album cover art</property>
3890+ <property name="visible">True</property>
3891+ <property name="can_focus">True</property>
3892+ <property name="receives_default">False</property>
3893 <property name="use_underline">True</property>
3894- <property name="relief">GTK_RELIEF_NORMAL</property>
3895- <property name="focus_on_click">True</property>
3896- <property name="active">False</property>
3897- <property name="inconsistent">False</property>
3898 <property name="draw_indicator">True</property>
3899- <signal handler="on_art_checkbox_toggled" name="toggled"/>
3900+ <signal name="toggled" handler="on_art_checkbox_toggled"/>
3901 </object>
3902 <packing>
3903- <property name="padding">1</property>
3904 <property name="expand">False</property>
3905 <property name="fill">False</property>
3906+ <property name="padding">1</property>
3907+ <property name="position">1</property>
3908 </packing>
3909 </child>
3910 <child>
3911 <object class="GtkCheckButton" id="lyrics_checkbox">
3912- <property name="visible">True</property>
3913- <property name="can_focus">True</property>
3914 <property name="label" translatable="yes">Download song lyrics</property>
3915+ <property name="visible">True</property>
3916+ <property name="can_focus">True</property>
3917+ <property name="receives_default">False</property>
3918 <property name="use_underline">True</property>
3919- <property name="relief">GTK_RELIEF_NORMAL</property>
3920- <property name="focus_on_click">True</property>
3921- <property name="active">False</property>
3922- <property name="inconsistent">False</property>
3923 <property name="draw_indicator">True</property>
3924- <signal handler="on_lyrics_checkbox_toggled" name="toggled"/>
3925+ <signal name="toggled" handler="on_lyrics_checkbox_toggled"/>
3926 </object>
3927 <packing>
3928- <property name="padding">1</property>
3929 <property name="expand">False</property>
3930 <property name="fill">False</property>
3931+ <property name="padding">1</property>
3932+ <property name="position">2</property>
3933 </packing>
3934 </child>
3935 </object>
3936 <packing>
3937- <property name="padding">0</property>
3938 <property name="expand">False</property>
3939- <property name="fill">True</property>
3940+ <property name="position">1</property>
3941 </packing>
3942 </child>
3943 <child>
3944 <object class="GtkButton" id="button_media_rebuild">
3945- <property name="border_width">5</property>
3946- <property name="visible">True</property>
3947- <property name="can_focus">True</property>
3948 <property name="label" translatable="yes">Rebuild media cache</property>
3949+ <property name="visible">True</property>
3950+ <property name="can_focus">True</property>
3951+ <property name="receives_default">False</property>
3952+ <property name="border_width">5</property>
3953 <property name="use_underline">True</property>
3954- <property name="relief">GTK_RELIEF_NORMAL</property>
3955- <property name="focus_on_click">True</property>
3956 </object>
3957 <packing>
3958- <property name="padding">0</property>
3959 <property name="expand">False</property>
3960 <property name="fill">False</property>
3961+ <property name="position">2</property>
3962 </packing>
3963 </child>
3964 </object>
3965 <packing>
3966- <property name="padding">0</property>
3967- <property name="expand">True</property>
3968- <property name="fill">True</property>
3969+ <property name="position">0</property>
3970 </packing>
3971 </child>
3972 </object>
3973- <packing>
3974- <property name="tab_expand">False</property>
3975- <property name="tab_fill">True</property>
3976- </packing>
3977 </child>
3978 <child type="tab">
3979 <object class="GtkLabel" id="label_media">
3980 <property name="visible">True</property>
3981- <property name="has_default">True</property>
3982 <property name="can_focus">True</property>
3983 <property name="has_focus">True</property>
3984+ <property name="can_default">True</property>
3985+ <property name="has_default">True</property>
3986 <property name="label" translatable="yes">Media</property>
3987- <property name="use_underline">False</property>
3988- <property name="use_markup">False</property>
3989- <property name="justify">GTK_JUSTIFY_LEFT</property>
3990- <property name="wrap">False</property>
3991- <property name="selectable">False</property>
3992- <property name="xalign">0.5</property>
3993- <property name="yalign">0.5</property>
3994- <property name="xpad">0</property>
3995- <property name="ypad">0</property>
3996- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
3997- <property name="width_chars">-1</property>
3998- <property name="single_line_mode">False</property>
3999- <property name="angle">0</property>
4000- </object>
4001- </child>
4002- <child>
4003- <object class="GtkVBox" id="vbox_feeds">
4004- <property name="visible">True</property>
4005- <property name="homogeneous">False</property>
4006- <property name="spacing">0</property>
4007- <child>
4008- <object class="GtkFrame" id="frame_rss_feeds3">
4009- <property name="border_width">5</property>
4010- <property name="visible">True</property>
4011- <property name="label_xalign">0</property>
4012- <property name="label_yalign">0.5</property>
4013- <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
4014- <child>
4015- <object class="GtkVBox" id="vbox17">
4016- <property name="visible">True</property>
4017- <property name="homogeneous">False</property>
4018- <property name="spacing">0</property>
4019- <child>
4020- <object class="GtkLabel" id="label_rss_tip3">
4021- <property name="visible">True</property>
4022- <property name="label" translatable="yes">Below is a list of RSS feeds that are displayed in Entertainer.</property>
4023- <property name="use_underline">False</property>
4024- <property name="use_markup">False</property>
4025- <property name="justify">GTK_JUSTIFY_LEFT</property>
4026- <property name="wrap">False</property>
4027- <property name="selectable">False</property>
4028- <property name="xalign">0</property>
4029- <property name="yalign">0.5</property>
4030- <property name="xpad">5</property>
4031- <property name="ypad">0</property>
4032- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
4033- <property name="width_chars">-1</property>
4034- <property name="single_line_mode">False</property>
4035- <property name="angle">0</property>
4036- </object>
4037- <packing>
4038- <property name="padding">5</property>
4039- <property name="expand">False</property>
4040- <property name="fill">True</property>
4041- </packing>
4042- </child>
4043- <child>
4044- <object class="GtkHBox" id="hbox16">
4045- <property name="visible">True</property>
4046- <property name="homogeneous">False</property>
4047- <property name="spacing">0</property>
4048- <child>
4049- <object class="GtkScrolledWindow" id="scrolledwindow_rss3">
4050- <property name="border_width">5</property>
4051- <property name="visible">True</property>
4052- <property name="can_focus">True</property>
4053- <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
4054- <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
4055- <property name="shadow_type">GTK_SHADOW_NONE</property>
4056- <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
4057- <child>
4058- <object class="GtkTreeView" id="treeview_feeds">
4059- <property name="visible">True</property>
4060- <property name="can_focus">True</property>
4061- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
4062- <property name="headers_visible">True</property>
4063- <property name="rules_hint">False</property>
4064- <property name="reorderable">False</property>
4065- <property name="enable_search">False</property>
4066- <property name="fixed_height_mode">False</property>
4067- <property name="hover_selection">False</property>
4068- <property name="hover_expand">False</property>
4069- </object>
4070- </child>
4071- </object>
4072- <packing>
4073- <property name="padding">0</property>
4074- <property name="expand">True</property>
4075- <property name="fill">True</property>
4076- </packing>
4077- </child>
4078- <child>
4079- <object class="GtkVButtonBox" id="vbuttonbox8">
4080- <property name="border_width">5</property>
4081- <property name="visible">True</property>
4082- <property name="layout_style">GTK_BUTTONBOX_DEFAULT_STYLE</property>
4083- <property name="spacing">2</property>
4084- <child>
4085- <object class="GtkButton" id="button_add_feed">
4086- <property name="visible">True</property>
4087- <property name="tooltip-text" translatable="yes">Add RSS Feed</property>
4088- <property name="can_focus">True</property>
4089- <property name="label">gtk-add</property>
4090- <property name="use_stock">True</property>
4091- <property name="relief">GTK_RELIEF_NORMAL</property>
4092- <property name="focus_on_click">True</property>
4093- <signal handler="on_button_add_feed_clicked" name="clicked"/>
4094- </object>
4095- </child>
4096- <child>
4097- <object class="GtkButton" id="button_remove_feed">
4098- <property name="visible">True</property>
4099- <property name="tooltip-text" translatable="yes">Remove RSS Feed</property>
4100- <property name="can_focus">True</property>
4101- <property name="label">gtk-remove</property>
4102- <property name="use_stock">True</property>
4103- <property name="relief">GTK_RELIEF_NORMAL</property>
4104- <property name="focus_on_click">True</property>
4105- <signal handler="on_button_remove_feed_clicked" name="clicked"/>
4106- </object>
4107- </child>
4108- <child>
4109- <object class="GtkButton" id="button_edit_feed">
4110- <property name="visible">True</property>
4111- <property name="tooltip-text" translatable="yes">Edit current item</property>
4112- <property name="can_focus">True</property>
4113- <property name="label">gtk-edit</property>
4114- <property name="use_stock">True</property>
4115- <property name="relief">GTK_RELIEF_NORMAL</property>
4116- <property name="focus_on_click">True</property>
4117- <signal handler="on_button_edit_feed_clicked" name="clicked"/>
4118- </object>
4119- </child>
4120- <child>
4121- <object class="GtkButton" id="button_open_list">
4122- <property name="visible">True</property>
4123- <property name="tooltip-text" translatable="yes">Add feeds from a datasource</property>
4124- <property name="can_focus">True</property>
4125- <property name="label">gtk-open</property>
4126- <property name="use_stock">True</property>
4127- <property name="relief">GTK_RELIEF_NORMAL</property>
4128- <property name="focus_on_click">True</property>
4129- <signal handler="on_button_open_list_clicked" name="clicked"/>
4130- </object>
4131- </child>
4132- </object>
4133- <packing>
4134- <property name="padding">5</property>
4135- <property name="expand">False</property>
4136- <property name="fill">True</property>
4137- </packing>
4138- </child>
4139- </object>
4140- <packing>
4141- <property name="padding">0</property>
4142- <property name="expand">True</property>
4143- <property name="fill">True</property>
4144- </packing>
4145- </child>
4146- </object>
4147- </child>
4148- <child type="label">
4149- <object class="GtkLabel" id="label_rss_sources3">
4150- <property name="visible">True</property>
4151- <property name="label" translatable="yes">&lt;b&gt;RSS feeds&lt;/b&gt;</property>
4152- <property name="use_underline">False</property>
4153- <property name="use_markup">True</property>
4154- <property name="justify">GTK_JUSTIFY_LEFT</property>
4155- <property name="wrap">False</property>
4156- <property name="selectable">False</property>
4157- <property name="xalign">0.5</property>
4158- <property name="yalign">0.5</property>
4159- <property name="xpad">0</property>
4160- <property name="ypad">0</property>
4161- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
4162- <property name="width_chars">-1</property>
4163- <property name="single_line_mode">False</property>
4164- <property name="angle">0</property>
4165- </object>
4166- </child>
4167- </object>
4168- <packing>
4169- <property name="padding">0</property>
4170- <property name="expand">False</property>
4171- <property name="fill">True</property>
4172- </packing>
4173- </child>
4174- <child>
4175- <object class="GtkHBox" id="hbox17">
4176- <property name="border_width">5</property>
4177- <property name="visible">True</property>
4178- <property name="homogeneous">False</property>
4179- <property name="spacing">0</property>
4180- <child>
4181- <object class="GtkLabel" id="label12">
4182- <property name="visible">True</property>
4183- <property name="label" translatable="yes">Update all feeds every</property>
4184- <property name="use_underline">False</property>
4185- <property name="use_markup">False</property>
4186- <property name="justify">GTK_JUSTIFY_LEFT</property>
4187- <property name="wrap">False</property>
4188- <property name="selectable">False</property>
4189- <property name="xalign">0.5</property>
4190- <property name="yalign">0.5</property>
4191- <property name="xpad">0</property>
4192- <property name="ypad">0</property>
4193- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
4194- <property name="width_chars">-1</property>
4195- <property name="single_line_mode">False</property>
4196- <property name="angle">0</property>
4197- </object>
4198- <packing>
4199- <property name="padding">0</property>
4200- <property name="expand">False</property>
4201- <property name="fill">True</property>
4202- </packing>
4203- </child>
4204- <child>
4205- <object class="GtkSpinButton" id="fetch_interval_spinbutton">
4206- <property name="visible">True</property>
4207- <property name="can_focus">True</property>
4208- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
4209- <property name="climb_rate">1</property>
4210- <property name="digits">0</property>
4211- <property name="numeric">True</property>
4212- <property name="update_policy">GTK_UPDATE_ALWAYS</property>
4213- <property name="snap_to_ticks">False</property>
4214- <property name="wrap">False</property>
4215- <property name="adjustment">adjustment1</property>
4216- <signal handler="on_fetch_interval_spinbutton_value_changed" name="value_changed"/>
4217- </object>
4218- <packing>
4219- <property name="padding">5</property>
4220- <property name="expand">False</property>
4221- <property name="fill">True</property>
4222- </packing>
4223- </child>
4224- <child>
4225- <object class="GtkLabel" id="label13">
4226- <property name="visible">True</property>
4227- <property name="label" translatable="yes">minutes.</property>
4228- <property name="use_underline">False</property>
4229- <property name="use_markup">False</property>
4230- <property name="justify">GTK_JUSTIFY_LEFT</property>
4231- <property name="wrap">False</property>
4232- <property name="selectable">False</property>
4233- <property name="xalign">0.5</property>
4234- <property name="yalign">0.5</property>
4235- <property name="xpad">0</property>
4236- <property name="ypad">0</property>
4237- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
4238- <property name="width_chars">-1</property>
4239- <property name="single_line_mode">False</property>
4240- <property name="angle">0</property>
4241- </object>
4242- <packing>
4243- <property name="padding">0</property>
4244- <property name="expand">False</property>
4245- <property name="fill">True</property>
4246- </packing>
4247- </child>
4248- </object>
4249- <packing>
4250- <property name="padding">0</property>
4251- <property name="expand">False</property>
4252- <property name="fill">True</property>
4253- </packing>
4254- </child>
4255- <child>
4256- <object class="GtkButton" id="button_feed_rebuild">
4257- <property name="border_width">5</property>
4258- <property name="visible">True</property>
4259- <property name="can_focus">True</property>
4260- <property name="label" translatable="yes">Rebuild RSS feed cache</property>
4261- <property name="use_underline">True</property>
4262- <property name="relief">GTK_RELIEF_NORMAL</property>
4263- <property name="focus_on_click">True</property>
4264- <signal handler="on_button_feed_rebuild_clicked" last_modification_time="Sat, 22 Aug 2009 18:13:42 GMT" name="clicked"/>
4265- </object>
4266- <packing>
4267- <property name="padding">0</property>
4268- <property name="expand">False</property>
4269- <property name="fill">False</property>
4270- </packing>
4271- </child>
4272 </object>
4273 <packing>
4274- <property name="tab_expand">False</property>
4275- <property name="tab_fill">True</property>
4276+ <property name="tab_fill">False</property>
4277 </packing>
4278 </child>
4279- <child type="tab">
4280- <object class="GtkLabel" id="label_rss3">
4281- <property name="visible">True</property>
4282- <property name="label" translatable="yes">RSS feeds</property>
4283- <property name="use_underline">False</property>
4284- <property name="use_markup">False</property>
4285- <property name="justify">GTK_JUSTIFY_LEFT</property>
4286- <property name="wrap">False</property>
4287- <property name="selectable">False</property>
4288- <property name="xalign">0.5</property>
4289- <property name="yalign">0.5</property>
4290- <property name="xpad">0</property>
4291- <property name="ypad">0</property>
4292- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
4293- <property name="width_chars">-1</property>
4294- <property name="single_line_mode">False</property>
4295- <property name="angle">0</property>
4296- </object>
4297- </child>
4298 <child>
4299 <object class="GtkVBox" id="vbox5">
4300 <property name="visible">True</property>
4301- <property name="homogeneous">False</property>
4302- <property name="spacing">0</property>
4303 <child>
4304 <object class="GtkFrame" id="frame_video_lib3">
4305+ <property name="visible">True</property>
4306 <property name="border_width">5</property>
4307- <property name="visible">True</property>
4308 <property name="label_xalign">0</property>
4309- <property name="label_yalign">0.5</property>
4310- <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
4311 <child>
4312 <object class="GtkVBox" id="weather_location_list_area">
4313 <property name="visible">True</property>
4314- <property name="homogeneous">False</property>
4315- <property name="spacing">0</property>
4316 <child>
4317 <object class="GtkLabel" id="label_weather_tip">
4318 <property name="visible">True</property>
4319+ <property name="xalign">0</property>
4320+ <property name="xpad">5</property>
4321 <property name="label" translatable="yes">Get weather conditions from the locations listed below.</property>
4322- <property name="use_underline">False</property>
4323- <property name="use_markup">False</property>
4324- <property name="justify">GTK_JUSTIFY_LEFT</property>
4325- <property name="wrap">False</property>
4326- <property name="selectable">False</property>
4327- <property name="xalign">0</property>
4328- <property name="yalign">0.5</property>
4329- <property name="xpad">5</property>
4330- <property name="ypad">0</property>
4331- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
4332- <property name="width_chars">-1</property>
4333 <property name="single_line_mode">True</property>
4334- <property name="angle">0</property>
4335 </object>
4336 <packing>
4337+ <property name="expand">False</property>
4338 <property name="padding">5</property>
4339- <property name="expand">False</property>
4340- <property name="fill">True</property>
4341+ <property name="position">0</property>
4342 </packing>
4343 </child>
4344 <child>
4345 <object class="GtkHBox" id="hbox4">
4346 <property name="visible">True</property>
4347- <property name="homogeneous">False</property>
4348- <property name="spacing">0</property>
4349 <child>
4350 <object class="GtkScrolledWindow" id="scrolledwindow3">
4351- <property name="border_width">5</property>
4352 <property name="visible">True</property>
4353 <property name="can_focus">True</property>
4354- <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
4355- <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
4356- <property name="shadow_type">GTK_SHADOW_NONE</property>
4357- <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
4358+ <property name="border_width">5</property>
4359+ <property name="hscrollbar_policy">automatic</property>
4360+ <property name="vscrollbar_policy">automatic</property>
4361 <child>
4362 <object class="GtkTreeView" id="treeview_locations">
4363 <property name="visible">True</property>
4364 <property name="can_focus">True</property>
4365 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
4366- <property name="headers_visible">True</property>
4367- <property name="rules_hint">False</property>
4368- <property name="reorderable">False</property>
4369 <property name="enable_search">False</property>
4370- <property name="fixed_height_mode">False</property>
4371- <property name="hover_selection">False</property>
4372- <property name="hover_expand">False</property>
4373 </object>
4374 </child>
4375 </object>
4376 <packing>
4377- <property name="padding">0</property>
4378- <property name="expand">True</property>
4379- <property name="fill">True</property>
4380+ <property name="position">0</property>
4381 </packing>
4382 </child>
4383 <child>
4384 <object class="GtkVButtonBox" id="vbuttonbox3">
4385+ <property name="visible">True</property>
4386 <property name="border_width">5</property>
4387- <property name="visible">True</property>
4388- <property name="layout_style">GTK_BUTTONBOX_DEFAULT_STYLE</property>
4389 <property name="spacing">2</property>
4390 <child>
4391 <object class="GtkButton" id="button_add_weather">
4392+ <property name="label">gtk-new</property>
4393 <property name="visible">True</property>
4394+ <property name="can_focus">True</property>
4395+ <property name="has_focus">True</property>
4396 <property name="can_default">True</property>
4397 <property name="has_default">True</property>
4398- <property name="can_focus">True</property>
4399- <property name="has_focus">True</property>
4400- <property name="label">gtk-new</property>
4401+ <property name="receives_default">False</property>
4402 <property name="use_stock">True</property>
4403- <property name="relief">GTK_RELIEF_NORMAL</property>
4404- <property name="focus_on_click">True</property>
4405- <signal handler="on_button_add_weather_clicked" name="clicked"/>
4406+ <signal name="clicked" handler="on_button_add_weather_clicked"/>
4407 </object>
4408+ <packing>
4409+ <property name="expand">False</property>
4410+ <property name="fill">False</property>
4411+ <property name="position">0</property>
4412+ </packing>
4413 </child>
4414 <child>
4415 <object class="GtkButton" id="button_remove_weather">
4416- <property name="visible">True</property>
4417- <property name="can_focus">True</property>
4418 <property name="label">gtk-clear</property>
4419+ <property name="visible">True</property>
4420+ <property name="can_focus">True</property>
4421+ <property name="receives_default">False</property>
4422 <property name="use_stock">True</property>
4423- <property name="relief">GTK_RELIEF_NORMAL</property>
4424- <property name="focus_on_click">True</property>
4425- <signal handler="on_button_remove_weather_clicked" name="clicked"/>
4426+ <signal name="clicked" handler="on_button_remove_weather_clicked"/>
4427 </object>
4428+ <packing>
4429+ <property name="expand">False</property>
4430+ <property name="fill">False</property>
4431+ <property name="position">1</property>
4432+ </packing>
4433 </child>
4434 </object>
4435 <packing>
4436+ <property name="expand">False</property>
4437 <property name="padding">5</property>
4438- <property name="expand">False</property>
4439- <property name="fill">True</property>
4440+ <property name="position">1</property>
4441 </packing>
4442 </child>
4443 </object>
4444 <packing>
4445- <property name="padding">0</property>
4446- <property name="expand">True</property>
4447- <property name="fill">True</property>
4448+ <property name="position">1</property>
4449 </packing>
4450 </child>
4451 </object>
4452@@ -803,203 +389,151 @@
4453 <object class="GtkLabel" id="label_weather_options">
4454 <property name="visible">True</property>
4455 <property name="label" translatable="yes">&lt;b&gt;Weather locations&lt;/b&gt;</property>
4456- <property name="use_underline">False</property>
4457 <property name="use_markup">True</property>
4458- <property name="justify">GTK_JUSTIFY_LEFT</property>
4459- <property name="wrap">False</property>
4460- <property name="selectable">False</property>
4461- <property name="xalign">0.5</property>
4462- <property name="yalign">0.5</property>
4463- <property name="xpad">0</property>
4464- <property name="ypad">0</property>
4465- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
4466- <property name="width_chars">-1</property>
4467- <property name="single_line_mode">False</property>
4468- <property name="angle">0</property>
4469 </object>
4470 </child>
4471 </object>
4472 <packing>
4473- <property name="padding">0</property>
4474 <property name="expand">False</property>
4475- <property name="fill">True</property>
4476+ <property name="position">0</property>
4477 </packing>
4478 </child>
4479 <child>
4480 <object class="GtkVBox" id="vbox7">
4481+ <property name="visible">True</property>
4482 <property name="border_width">5</property>
4483- <property name="visible">True</property>
4484- <property name="homogeneous">False</property>
4485- <property name="spacing">0</property>
4486 <child>
4487 <object class="GtkCheckButton" id="weather_display_checkbox">
4488- <property name="visible">True</property>
4489- <property name="can_focus">True</property>
4490 <property name="label" translatable="yes">Display weather option in main menu</property>
4491+ <property name="visible">True</property>
4492+ <property name="can_focus">True</property>
4493+ <property name="receives_default">False</property>
4494 <property name="use_underline">True</property>
4495- <property name="relief">GTK_RELIEF_NORMAL</property>
4496- <property name="focus_on_click">True</property>
4497 <property name="active">True</property>
4498- <property name="inconsistent">False</property>
4499 <property name="draw_indicator">True</property>
4500- <signal handler="on_weather_display_checkbox_toggled" name="toggled"/>
4501+ <signal name="toggled" handler="on_weather_display_checkbox_toggled"/>
4502 </object>
4503 <packing>
4504- <property name="padding">0</property>
4505- <property name="expand">True</property>
4506- <property name="fill">True</property>
4507+ <property name="position">0</property>
4508 </packing>
4509 </child>
4510 </object>
4511 <packing>
4512- <property name="padding">0</property>
4513 <property name="expand">False</property>
4514- <property name="fill">True</property>
4515+ <property name="position">1</property>
4516 </packing>
4517 </child>
4518 </object>
4519 <packing>
4520- <property name="tab_expand">False</property>
4521- <property name="tab_fill">True</property>
4522+ <property name="position">1</property>
4523 </packing>
4524 </child>
4525 <child type="tab">
4526 <object class="GtkLabel" id="label_weather">
4527 <property name="visible">True</property>
4528+ <property name="yalign">0.40999999642372131</property>
4529 <property name="label" translatable="yes">Weather</property>
4530- <property name="use_underline">False</property>
4531- <property name="use_markup">False</property>
4532- <property name="justify">GTK_JUSTIFY_LEFT</property>
4533- <property name="wrap">False</property>
4534- <property name="selectable">False</property>
4535- <property name="xalign">0.5</property>
4536- <property name="yalign">0.409999996424</property>
4537- <property name="xpad">0</property>
4538- <property name="ypad">0</property>
4539- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
4540- <property name="width_chars">-1</property>
4541- <property name="single_line_mode">False</property>
4542- <property name="angle">0</property>
4543 </object>
4544+ <packing>
4545+ <property name="position">1</property>
4546+ <property name="tab_fill">False</property>
4547+ </packing>
4548 </child>
4549 <child>
4550 <object class="GtkVBox" id="vbox25">
4551 <property name="visible">True</property>
4552- <property name="homogeneous">False</property>
4553- <property name="spacing">0</property>
4554 <child>
4555 <object class="GtkFrame" id="frame8">
4556+ <property name="visible">True</property>
4557 <property name="border_width">5</property>
4558- <property name="visible">True</property>
4559 <property name="label_xalign">0</property>
4560- <property name="label_yalign">0.5</property>
4561- <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
4562 <child>
4563 <object class="GtkVBox" id="vbox27">
4564 <property name="visible">True</property>
4565- <property name="homogeneous">False</property>
4566- <property name="spacing">0</property>
4567 <child>
4568 <object class="GtkLabel" id="label38">
4569 <property name="visible">True</property>
4570+ <property name="xalign">0</property>
4571+ <property name="xpad">5</property>
4572 <property name="label" translatable="yes">Below is a list of accessible themes.</property>
4573- <property name="use_underline">False</property>
4574- <property name="use_markup">False</property>
4575- <property name="justify">GTK_JUSTIFY_LEFT</property>
4576- <property name="wrap">False</property>
4577- <property name="selectable">False</property>
4578- <property name="xalign">0</property>
4579- <property name="yalign">0.5</property>
4580- <property name="xpad">5</property>
4581- <property name="ypad">0</property>
4582- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
4583- <property name="width_chars">-1</property>
4584- <property name="single_line_mode">False</property>
4585- <property name="angle">0</property>
4586 </object>
4587 <packing>
4588+ <property name="expand">False</property>
4589 <property name="padding">5</property>
4590- <property name="expand">False</property>
4591- <property name="fill">True</property>
4592+ <property name="position">0</property>
4593 </packing>
4594 </child>
4595 <child>
4596 <object class="GtkHBox" id="hbox21">
4597 <property name="visible">True</property>
4598- <property name="homogeneous">False</property>
4599- <property name="spacing">0</property>
4600 <child>
4601 <object class="GtkScrolledWindow" id="scrolledwindow8">
4602- <property name="border_width">5</property>
4603 <property name="visible">True</property>
4604 <property name="can_focus">True</property>
4605- <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
4606- <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
4607- <property name="shadow_type">GTK_SHADOW_NONE</property>
4608- <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
4609+ <property name="border_width">5</property>
4610+ <property name="hscrollbar_policy">automatic</property>
4611+ <property name="vscrollbar_policy">automatic</property>
4612 <child>
4613 <object class="GtkTreeView" id="theme_list">
4614 <property name="visible">True</property>
4615 <property name="can_focus">True</property>
4616 <property name="headers_visible">False</property>
4617- <property name="rules_hint">False</property>
4618- <property name="reorderable">False</property>
4619 <property name="enable_search">False</property>
4620- <property name="fixed_height_mode">False</property>
4621- <property name="hover_selection">False</property>
4622- <property name="hover_expand">False</property>
4623- <signal handler="on_theme_list_cursor_changed" last_modification_time="Sat, 22 Aug 2009 21:26:24 GMT" name="cursor_changed"/>
4624+ <signal name="cursor_changed" handler="on_theme_list_cursor_changed"/>
4625 </object>
4626 </child>
4627 </object>
4628 <packing>
4629- <property name="padding">0</property>
4630- <property name="expand">True</property>
4631- <property name="fill">True</property>
4632+ <property name="position">0</property>
4633 </packing>
4634 </child>
4635 <child>
4636 <object class="GtkVButtonBox" id="vbuttonbox9">
4637+ <property name="visible">True</property>
4638 <property name="border_width">5</property>
4639- <property name="visible">True</property>
4640- <property name="layout_style">GTK_BUTTONBOX_START</property>
4641 <property name="spacing">2</property>
4642+ <property name="layout_style">start</property>
4643 <child>
4644 <object class="GtkButton" id="theme_add_button">
4645+ <property name="label">gtk-add</property>
4646 <property name="visible">True</property>
4647+ <property name="can_focus">True</property>
4648 <property name="can_default">True</property>
4649- <property name="can_focus">True</property>
4650- <property name="label">gtk-add</property>
4651+ <property name="receives_default">False</property>
4652 <property name="use_stock">True</property>
4653- <property name="relief">GTK_RELIEF_NORMAL</property>
4654- <property name="focus_on_click">True</property>
4655- <signal handler="on_theme_add_button_clicked" last_modification_time="Sat, 22 Aug 2009 23:52:40 GMT" name="clicked"/>
4656+ <signal name="clicked" handler="on_theme_add_button_clicked"/>
4657 </object>
4658+ <packing>
4659+ <property name="expand">False</property>
4660+ <property name="fill">False</property>
4661+ <property name="position">0</property>
4662+ </packing>
4663 </child>
4664 <child>
4665 <object class="GtkButton" id="theme_remove_button">
4666+ <property name="label">gtk-remove</property>
4667 <property name="visible">True</property>
4668+ <property name="can_focus">True</property>
4669 <property name="can_default">True</property>
4670- <property name="can_focus">True</property>
4671- <property name="label">gtk-remove</property>
4672+ <property name="receives_default">False</property>
4673 <property name="use_stock">True</property>
4674- <property name="relief">GTK_RELIEF_NORMAL</property>
4675- <property name="focus_on_click">True</property>
4676- <signal handler="on_theme_remove_button_clicked" last_modification_time="Sat, 22 Aug 2009 23:55:25 GMT" name="clicked"/>
4677+ <signal name="clicked" handler="on_theme_remove_button_clicked"/>
4678 </object>
4679+ <packing>
4680+ <property name="expand">False</property>
4681+ <property name="fill">False</property>
4682+ <property name="position">1</property>
4683+ </packing>
4684 </child>
4685 </object>
4686 <packing>
4687- <property name="padding">0</property>
4688 <property name="expand">False</property>
4689- <property name="fill">True</property>
4690+ <property name="position">1</property>
4691 </packing>
4692 </child>
4693 </object>
4694 <packing>
4695- <property name="padding">0</property>
4696- <property name="expand">True</property>
4697- <property name="fill">True</property>
4698+ <property name="position">1</property>
4699 </packing>
4700 </child>
4701 </object>
4702@@ -1008,371 +542,196 @@
4703 <object class="GtkLabel" id="label25">
4704 <property name="visible">True</property>
4705 <property name="label" translatable="yes">&lt;b&gt;Themes&lt;/b&gt;</property>
4706- <property name="use_underline">False</property>
4707 <property name="use_markup">True</property>
4708- <property name="justify">GTK_JUSTIFY_LEFT</property>
4709- <property name="wrap">False</property>
4710- <property name="selectable">False</property>
4711- <property name="xalign">0.5</property>
4712- <property name="yalign">0.5</property>
4713- <property name="xpad">0</property>
4714- <property name="ypad">0</property>
4715- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
4716- <property name="width_chars">-1</property>
4717- <property name="single_line_mode">False</property>
4718- <property name="angle">0</property>
4719 </object>
4720 </child>
4721 </object>
4722 <packing>
4723- <property name="padding">0</property>
4724- <property name="expand">True</property>
4725- <property name="fill">True</property>
4726+ <property name="position">0</property>
4727 </packing>
4728 </child>
4729 <child>
4730 <object class="GtkFrame" id="frame9">
4731+ <property name="visible">True</property>
4732 <property name="border_width">5</property>
4733- <property name="visible">True</property>
4734 <property name="label_xalign">0</property>
4735- <property name="label_yalign">0.5</property>
4736- <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
4737 <child>
4738 <object class="GtkHBox" id="hbox22">
4739 <property name="visible">True</property>
4740- <property name="homogeneous">False</property>
4741- <property name="spacing">0</property>
4742 <child>
4743 <object class="GtkImage" id="theme_image">
4744 <property name="visible">True</property>
4745- <property name="icon_size">4</property>
4746+ <property name="ypad">5</property>
4747 <property name="icon_name">gtk-missing-image</property>
4748- <property name="xalign">0.5</property>
4749- <property name="yalign">0.5</property>
4750- <property name="xpad">0</property>
4751- <property name="ypad">5</property>
4752 </object>
4753 <packing>
4754- <property name="padding">5</property>
4755 <property name="expand">False</property>
4756 <property name="fill">False</property>
4757+ <property name="padding">5</property>
4758+ <property name="position">0</property>
4759 </packing>
4760 </child>
4761 <child>
4762 <object class="GtkVBox" id="vbox26">
4763 <property name="visible">True</property>
4764- <property name="homogeneous">False</property>
4765- <property name="spacing">0</property>
4766 <child>
4767 <object class="GtkHBox" id="hbox23">
4768+ <property name="visible">True</property>
4769 <property name="border_width">2</property>
4770- <property name="visible">True</property>
4771- <property name="homogeneous">False</property>
4772- <property name="spacing">0</property>
4773 <child>
4774 <object class="GtkLabel" id="label28">
4775 <property name="visible">True</property>
4776 <property name="label" translatable="yes">&lt;b&gt;Name: &lt;/b&gt;</property>
4777- <property name="use_underline">False</property>
4778 <property name="use_markup">True</property>
4779- <property name="justify">GTK_JUSTIFY_LEFT</property>
4780- <property name="wrap">False</property>
4781- <property name="selectable">False</property>
4782- <property name="xalign">0.5</property>
4783- <property name="yalign">0.5</property>
4784- <property name="xpad">0</property>
4785- <property name="ypad">0</property>
4786- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
4787- <property name="width_chars">-1</property>
4788- <property name="single_line_mode">False</property>
4789- <property name="angle">0</property>
4790 </object>
4791 <packing>
4792- <property name="padding">0</property>
4793 <property name="expand">False</property>
4794 <property name="fill">False</property>
4795+ <property name="position">0</property>
4796 </packing>
4797 </child>
4798 <child>
4799 <object class="GtkLabel" id="name_label">
4800 <property name="visible">True</property>
4801- <property name="label" translatable="yes"/>
4802- <property name="use_underline">False</property>
4803- <property name="use_markup">False</property>
4804- <property name="justify">GTK_JUSTIFY_LEFT</property>
4805- <property name="wrap">False</property>
4806- <property name="selectable">False</property>
4807- <property name="xalign">0.5</property>
4808- <property name="yalign">0.5</property>
4809- <property name="xpad">0</property>
4810- <property name="ypad">0</property>
4811- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
4812- <property name="width_chars">-1</property>
4813- <property name="single_line_mode">False</property>
4814- <property name="angle">0</property>
4815 </object>
4816 <packing>
4817- <property name="padding">0</property>
4818 <property name="expand">False</property>
4819 <property name="fill">False</property>
4820+ <property name="position">1</property>
4821 </packing>
4822 </child>
4823 </object>
4824 <packing>
4825- <property name="padding">0</property>
4826- <property name="expand">True</property>
4827- <property name="fill">True</property>
4828+ <property name="position">0</property>
4829 </packing>
4830 </child>
4831 <child>
4832 <object class="GtkHBox" id="hbox24">
4833+ <property name="visible">True</property>
4834 <property name="border_width">2</property>
4835- <property name="visible">True</property>
4836- <property name="homogeneous">False</property>
4837- <property name="spacing">0</property>
4838 <child>
4839 <object class="GtkLabel" id="label29">
4840 <property name="visible">True</property>
4841 <property name="label" translatable="yes">&lt;b&gt;Author: &lt;/b&gt;</property>
4842- <property name="use_underline">False</property>
4843 <property name="use_markup">True</property>
4844- <property name="justify">GTK_JUSTIFY_LEFT</property>
4845- <property name="wrap">False</property>
4846- <property name="selectable">False</property>
4847- <property name="xalign">0.5</property>
4848- <property name="yalign">0.5</property>
4849- <property name="xpad">0</property>
4850- <property name="ypad">0</property>
4851- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
4852- <property name="width_chars">-1</property>
4853- <property name="single_line_mode">False</property>
4854- <property name="angle">0</property>
4855 </object>
4856 <packing>
4857- <property name="padding">0</property>
4858 <property name="expand">False</property>
4859 <property name="fill">False</property>
4860+ <property name="position">0</property>
4861 </packing>
4862 </child>
4863 <child>
4864 <object class="GtkLabel" id="author_label">
4865 <property name="visible">True</property>
4866- <property name="label" translatable="yes"/>
4867- <property name="use_underline">False</property>
4868- <property name="use_markup">False</property>
4869- <property name="justify">GTK_JUSTIFY_LEFT</property>
4870- <property name="wrap">False</property>
4871- <property name="selectable">False</property>
4872- <property name="xalign">0.5</property>
4873- <property name="yalign">0.5</property>
4874- <property name="xpad">0</property>
4875- <property name="ypad">0</property>
4876- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
4877- <property name="width_chars">-1</property>
4878- <property name="single_line_mode">False</property>
4879- <property name="angle">0</property>
4880 </object>
4881 <packing>
4882- <property name="padding">0</property>
4883 <property name="expand">False</property>
4884 <property name="fill">False</property>
4885+ <property name="position">1</property>
4886 </packing>
4887 </child>
4888 </object>
4889 <packing>
4890- <property name="padding">0</property>
4891- <property name="expand">True</property>
4892- <property name="fill">True</property>
4893+ <property name="position">1</property>
4894 </packing>
4895 </child>
4896 <child>
4897 <object class="GtkHBox" id="hbox25">
4898+ <property name="visible">True</property>
4899 <property name="border_width">2</property>
4900- <property name="visible">True</property>
4901- <property name="homogeneous">False</property>
4902- <property name="spacing">0</property>
4903 <child>
4904 <object class="GtkLabel" id="label30">
4905 <property name="visible">True</property>
4906 <property name="label" translatable="yes">&lt;b&gt;License: &lt;/b&gt;</property>
4907- <property name="use_underline">False</property>
4908 <property name="use_markup">True</property>
4909- <property name="justify">GTK_JUSTIFY_LEFT</property>
4910- <property name="wrap">False</property>
4911- <property name="selectable">False</property>
4912- <property name="xalign">0.5</property>
4913- <property name="yalign">0.5</property>
4914- <property name="xpad">0</property>
4915- <property name="ypad">0</property>
4916- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
4917- <property name="width_chars">-1</property>
4918- <property name="single_line_mode">False</property>
4919- <property name="angle">0</property>
4920 </object>
4921 <packing>
4922- <property name="padding">0</property>
4923 <property name="expand">False</property>
4924 <property name="fill">False</property>
4925+ <property name="position">0</property>
4926 </packing>
4927 </child>
4928 <child>
4929 <object class="GtkLabel" id="license_label">
4930 <property name="visible">True</property>
4931- <property name="label" translatable="yes"/>
4932- <property name="use_underline">False</property>
4933- <property name="use_markup">False</property>
4934- <property name="justify">GTK_JUSTIFY_LEFT</property>
4935- <property name="wrap">False</property>
4936- <property name="selectable">False</property>
4937- <property name="xalign">0.5</property>
4938- <property name="yalign">0.5</property>
4939- <property name="xpad">0</property>
4940- <property name="ypad">0</property>
4941- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
4942- <property name="width_chars">-1</property>
4943- <property name="single_line_mode">False</property>
4944- <property name="angle">0</property>
4945 </object>
4946 <packing>
4947- <property name="padding">0</property>
4948 <property name="expand">False</property>
4949 <property name="fill">False</property>
4950+ <property name="position">1</property>
4951 </packing>
4952 </child>
4953 </object>
4954 <packing>
4955- <property name="padding">0</property>
4956- <property name="expand">True</property>
4957- <property name="fill">True</property>
4958+ <property name="position">2</property>
4959 </packing>
4960 </child>
4961 <child>
4962 <object class="GtkHBox" id="hbox26">
4963+ <property name="visible">True</property>
4964 <property name="border_width">2</property>
4965- <property name="visible">True</property>
4966- <property name="homogeneous">False</property>
4967- <property name="spacing">0</property>
4968 <child>
4969 <object class="GtkLabel" id="label31">
4970 <property name="visible">True</property>
4971 <property name="label" translatable="yes">&lt;b&gt;Copyright: &lt;/b&gt;</property>
4972- <property name="use_underline">False</property>
4973 <property name="use_markup">True</property>
4974- <property name="justify">GTK_JUSTIFY_LEFT</property>
4975- <property name="wrap">False</property>
4976- <property name="selectable">False</property>
4977- <property name="xalign">0.5</property>
4978- <property name="yalign">0.5</property>
4979- <property name="xpad">0</property>
4980- <property name="ypad">0</property>
4981- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
4982- <property name="width_chars">-1</property>
4983- <property name="single_line_mode">False</property>
4984- <property name="angle">0</property>
4985 </object>
4986 <packing>
4987- <property name="padding">0</property>
4988 <property name="expand">False</property>
4989 <property name="fill">False</property>
4990+ <property name="position">0</property>
4991 </packing>
4992 </child>
4993 <child>
4994 <object class="GtkLabel" id="copyright_label">
4995 <property name="visible">True</property>
4996- <property name="label" translatable="yes"/>
4997- <property name="use_underline">False</property>
4998- <property name="use_markup">False</property>
4999- <property name="justify">GTK_JUSTIFY_LEFT</property>
5000- <property name="wrap">False</property>
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches