Merge lp://staging/~rockstar/entertainer/package-structure-apocalypse into lp://staging/entertainer/future
- package-structure-apocalypse
- Merge into entertainer-future
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Paul Hummer | ||||
Approved revision: | 382 | ||||
Merged at revision: | not available | ||||
Proposed branch: | lp://staging/~rockstar/entertainer/package-structure-apocalypse | ||||
Merge into: | lp://staging/entertainer/future | ||||
Diff against target: | None lines | ||||
To merge this branch: | bzr merge lp://staging/~rockstar/entertainer/package-structure-apocalypse | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Samuel Buffet (community) | Approve | ||
Matt Layman | Approve | ||
Review via email: mp+6249@code.staging.launchpad.net |
Commit message
Entertainer's package structure has been re-organized
Description of the change
Paul Hummer (rockstar) wrote : | # |
Samuel Buffet (samuel-buffet) wrote : | # |
Hi Paul,
Good to see Entertainer becoming a client/server application.
I have some points to discuss with you before I go on deeper in the review. Most of them are related with the tree structure you've chosen.
Under entertainerlib we have :
backend
client
db
glade
gui
network
test
My questions are.
Why db isn't under backend? and why gui is not under client?
I think it's more readable and more logic because gui which contains widgets/screens ... are all used only by the *client* and *db* is used by the server (I guess).
You write that you're about to remove entertainerlib.
That's the first set of questions I have taking a first look to this branch.
Samuel-
Note :
Entertainer is broken if the notification icon is activated. See below the traceback :
(/mnt/raid/
Traceback (most recent call last):
File "/mnt/raid/
main()
File "/mnt/raid/
client_client = Client()
File "/mnt/raid/
self.
File "/mnt/raid/
os.
RuntimeError: could not create GladeXML object
Matt Layman (mblayman) wrote : | # |
> Why db isn't under backend? and why gui is not under client?
>
> I think it's more readable and more logic because gui which contains
> widgets/screens ... are all used only by the *client* and *db* is used by the
> server (I guess).
I can't speak for db, but moving gui out of frontend was my request. I know that the frontend is currently the only thing that uses the gui module, but there is no true reason that gui needs to be a sub-module of frontend (it could theoretically be totally independent of the frontend). Moving gui out of frontend flattens the depth of the tree which I think is a good thing here. I have a feeling Paul would say the same thing about the db and the backend.
> Note :
> Entertainer is broken if the notification icon is activated. See below the
> traceback :
I agree that this needs to be fixed before the branch lands.
Matt Layman (mblayman) wrote : | # |
Paul,
Here are all my comments that I recorded as I went through the diff:
What was the rationale behind putting all the dialog classes into a single file? I would suggest that we at least call it dialogs if there are going to be multiple, but it doesn't make too much sense to me to put them all in the same file, especially if our dialogs might only grow more capabilities over time (like TV stuff).
entertainerlib/
* FRONTEND_OPENED and FRONTEND_CLOSED should probably change to CLIENT_*. The comments with those lines don't make sense because frontend was substituted with client.
entertainerlib/
* Initial comment isn't valid.
* client_client is weird.
entertainerlib/
* import order
* class doc string has Frontend
* logger name isn't correct, would client.Client
entertainerlib/
* import order
entertainerlib/
* import order
entertainerlib/
* import order
entertainerlib/
* import order
entertainerlib/
* import order
entertainerlib/
* import order
entertainerlib/
* import order
entertainerlib/
* import order
entertainerlib/
* import order
entertainerlib/
* import order
entertainerlib/
* import order
entertainerlib/
* Switch from frontend to client revealed some code that must is broken. set_client_visible has no implementation.
entertainerlib/
* import order
entertainerlib/
* import order
entertainerlib/
* import order
* Uses UserEvent.
entertainerlib/
* import order
entertainerlib/
* import order
entertainerlib/
* import order
entertainerlib/
* import order
entertainerlib/
* logger name doesn't need to refer to client anymore
entertainerlib/
* import order
entertainerlib/
* import order
entertainerlib/
* import order
entertainerlib/
* Removed, so you can link to bug 313815
setup.py
* There is no longer a client/glade directory so 'client/glade/*' shouldn't be needed anymore.
Paul Hummer (rockstar) wrote : | # |
On Thu, 07 May 2009 19:59:33 -0000, Samuel Buffet <email address hidden>
> My questions are.
>
> Why db isn't under backend? and why gui is not under client?
db is a core part of entertainer. I tried to make thinngs more easily
accessible, and once I get the network stuff in, it won't be used by just one
package.
> You write that you're about to remove entertainerlib.
> understand right now why you don't rename it in entertainerlib.
> that mean that the server's code will take place elsewhere?
Because there won't be just one entertainer server. There will be with 0.5,
but the end goal is to provide more options. I figure something like
entertainerlib.
etc.
Now you'll see why db didn't stay in the backend.
Also, most of the backend code is pure crap now, being replaced, and will be
completely removed. THAT's why I didn't move it to a new location. :)
>> Note :
>
> Entertainer is broken if the notification icon is activated. See below the
> traceback :
>
> (/mnt/raid/
> libglade-WARNING **: could not find glade file
> '/mnt/raid/
> Traceback (most recent call last): File
> "/mnt/raid/
> line 12, in <module> main() File
> "/mnt/raid/
> line 33, in main client_client = Client() File
> "/mnt/raid/
> line 51, in __init__ self.quit_client, self.toggle_
> File
> "/mnt/raid/
> line 42, in __init__ os.path.
> "system_
> object
>
I don't know yet what to with the system tray icon. No one uses it, it
doesn't really fit in with what Entertainer is (a media center, not a desktop
application) and I currently don't have any plans to support it in the local
server.
--
Paul Hummer
http://
1024/862FF08F C921 E962 58F8 5547 6723 0E8C 1C4D 8AC5 862F F08F
Paul Hummer (rockstar) wrote : | # |
> What was the rationale behind putting all the dialog classes into a single
> file? I would suggest that we at least call it dialogs if there are going
> to be multiple, but it doesn't make too much sense to me to put them all in
> the same file, especially if our dialogs might only grow more capabilities
> over time (like TV stuff).
They depend on similar things. As I was working on everything else, it only
made sense to consolidate those dialogs. I think the next logical step would
be to create an EntertainerDialog, and extend the dialogs that way. That code
is an utter mess. I think, for the time being, it should stay as the same
module, and get it cleaned up. If (and this is a big IF) we see a need to make
a package out of this, we can be confident that the code is being maintained.
> entertainerlib/
> * FRONTEND_OPENED and FRONTEND_CLOSED should probably change to CLIENT_*.
> The comments with those lines don't make sense because frontend was
> substituted with client.
Nope, I'm not touching that message passing crap. It never worked right, and
will just get deleted when the server is implemented.
>
> entertainerlib/
> * Initial comment isn't valid.
> * client_client is weird.
Yeah, I thought that too. client.
it's a bit repetitive. I was going to see if you wanted to root around in the
client code and see what you'd need.
>
> entertainerlib/
> * import order
> * class doc string has Frontend
> * logger name isn't correct, would client.Client
I've made the changes to everything but import order. The import order will be
re-arranged before this lands in trunk, but the imports are going to be hell to
merge from trunk as it is. I'd rather do a second branch with the import order
stuff. This is the beauty of having this HIGHLY experimental branch. I think
this is an acceptable solution.
> entertainerlib/
> * Switch from frontend to client revealed some code that must is broken.
> set_client_visible has no implementation.
I don't plan on fixing this in this branch. If it's broken, it's broken. It
may not even be in the next version of Entertainer.
> entertainerlib/
> * import order
> * Uses UserEvent.
I changed this to just QUIT. These events are only used by the client anyway,
so QUIT_CLIENT is rather redundant.
> entertainerlib/
> * logger name doesn't need to refer to client anymore
Fixed.
> entertainerlib/
> * Removed, so you can link to bug 313815
Sweet, thanks. I figured there was a bug, but I was too lazy to go find it.
:)
>
> setup.py
> * There is no longer a client/glade directory so 'client/glade/*'
> shouldn't be needed anymore.
Fixed.
Here's the incremental diff:
=== modified file 'entertainerlib
--- entertainerlib/
+++ entertainerlib/
@@ -1,8 +1,8 @@
-'''Frontend gui to entertainer'''
+'''Client code for Entertainer.'''
# py...
- 382. By Paul Hummer
-
Responded to Matt's review
Samuel Buffet (samuel-buffet) wrote : | # |
Hi Paul,
I'm going to approve this branch as I can see on it the seeds of Entertainer's future.
> Also, most of the backend code is pure crap now, being replaced, and will be
> completely removed. THAT's why I didn't move it to a new location. :)
Okay, with those explanations.
> I don't know yet what to with the system tray icon. No one uses it, it
> doesn't really fit in with what Entertainer is (a media center, not a desktop
> application) and I currently don't have any plans to support it in the local
> server.
Well, I do use it. Also, I think this is not good at all to have *broken* code.
So it turns out to me that either we have to fix this or we remove all the code
related to this notification icon. But, as we're not really sure of the future of
this feature and as fixing this should be rather trivial, I'd prefer the fix
solution.
> They depend on similar things. As I was working on everything else, it only
> made sense to consolidate those dialogs. I think the next logical step would
> be to create an EntertainerDialog, and extend the dialogs that way. That code
> is an utter mess. I think, for the time being, it should stay as the same
> module, and get it cleaned up. If (and this is a big IF) we see a need to
> make
> a package out of this, we can be confident that the code is being maintained.
I'm not sure it's a good idea. I tempted to say "+1 with Matt".
Even if the *one Class per file* rule is nonsense sometime but here ...??
>=== added file 'entertainerlib
>--- entertainerlib/
>+++ entertainerlib/
>@@ -0,0 +1,453 @@
>+'''Downloader classes.'''
>+
>+__licence__ = "GPLv2"
>+__copyright__ = "2009 Entertainer Developers"
>+
I like the idea to group our downloaders. What about weather downloader? Is it
planned in the future?
> self.window.
>@@ -53,7 +53,7 @@
> except gobject.GError:
> # Must not be installed from a package, get icon from the branch
> file_dir = os.path.
>- icon_path = os.path.
>+ icon_path = os.path.
> 'hicolor', '48x48', 'apps', 'entertainer.png')
> icon = gtk.gdk.
> self.window.
(just me thinking loudly) => If we want to improve our flexibility with folder
tree modifications, we have to find a way to avoid those '..', '..'.
What about adding more xxx_dir (root_dir, data_dir, etc). Those could be calculated
attributes of our config object.
Thanks for the great work Paul. Entertainer will rock with the future client/server
architecture and a robust and powerfull indexer.
Samuel-
Matt Layman (mblayman) wrote : | # |
After looking over the conversations in this thread, I've concluded that I have to think differently about my normal standards and realize that this isn't trunk. I do wonder how we can capture the problems that start to arise as we merge branches onto future. Some problems will go away when future gets closer to merging into trunk, but what if we just forget about some of these things and merge them onto trunk by accident. That's my one reservation about approving this branch.
However, I do like the bulk of this work and since it is such a disruptive change, I would rather it land sooner than later. Therefore, I'm going to approve in spite of my concerns.
Samuel Buffet (samuel-buffet) wrote : | # |
Go Paul! Go!
This is really something we need and like Matt said, this is not trunk. So you have a STRONG approval from me on this work. I can add that I'm very happy with the goal of this branch.
Cheers,
Samuel-
- 383. By Paul Hummer
-
Merged from entertainer-future
- 384. By Paul Hummer
-
Added copyright stuff to the new files
Preview Diff
1 | === modified file 'entertainer' |
2 | --- entertainer 2008-10-25 16:41:22 +0000 |
3 | +++ entertainer 2009-05-06 03:37:34 +0000 |
4 | @@ -1,12 +1,12 @@ |
5 | #!/usr/bin/env python |
6 | -'''Main frontend executable''' |
7 | +'''Main client executable''' |
8 | |
9 | __licence__ = "GPLv2" |
10 | __copyright__ = "2007, Lauri Taimila" |
11 | __author__ = "Lauri Taimila <lauri@taimila.com>" |
12 | __version__ = "0.2" |
13 | |
14 | -from entertainerlib.frontend import main |
15 | +from entertainerlib.client import main |
16 | |
17 | if __name__ == '__main__': |
18 | main() |
19 | |
20 | === modified file 'entertainer-client' |
21 | --- entertainer-client 2009-04-04 05:30:04 +0000 |
22 | +++ entertainer-client 2009-05-06 03:37:34 +0000 |
23 | @@ -2,7 +2,7 @@ |
24 | '''Test client for Entertainer's server. |
25 | |
26 | This code will go away when the client code is integrated into what is now the |
27 | -frontend. |
28 | +client. |
29 | ''' |
30 | |
31 | from entertainerlib.network import client_main |
32 | |
33 | === modified file 'entertainer-content-manager' |
34 | --- entertainer-content-manager 2008-12-19 04:06:18 +0000 |
35 | +++ entertainer-content-manager 2009-05-06 03:37:34 +0000 |
36 | @@ -3,11 +3,10 @@ |
37 | |
38 | import gtk |
39 | |
40 | -from entertainerlib.frontend.translation_setup import TranslationSetup |
41 | +from entertainerlib.client.translation_setup import TranslationSetup |
42 | TranslationSetup() |
43 | |
44 | -from entertainerlib.utils.content_management_dialog import ( |
45 | - ContentManagementDialog) |
46 | +from entertainerlib.dialog import ContentManagementDialog |
47 | |
48 | |
49 | ContentManagementDialog(True) |
50 | |
51 | === modified file 'entertainer-preferences' |
52 | --- entertainer-preferences 2008-12-19 04:06:18 +0000 |
53 | +++ entertainer-preferences 2009-05-06 03:37:34 +0000 |
54 | @@ -3,10 +3,10 @@ |
55 | |
56 | import gtk |
57 | |
58 | -from entertainerlib.frontend.translation_setup import TranslationSetup |
59 | +from entertainerlib.client.translation_setup import TranslationSetup |
60 | TranslationSetup() |
61 | |
62 | -from entertainerlib.utils.preferences_dialog import PreferencesDialog |
63 | +from entertainerlib.dialog import PreferencesDialog |
64 | |
65 | |
66 | PreferencesDialog(True) |
67 | |
68 | === modified file 'entertainerlib/backend/backend_server.py' |
69 | --- entertainerlib/backend/backend_server.py 2009-02-08 07:01:25 +0000 |
70 | +++ entertainerlib/backend/backend_server.py 2009-05-05 04:43:57 +0000 |
71 | @@ -8,8 +8,8 @@ |
72 | |
73 | import gobject |
74 | |
75 | -from entertainerlib.utils.configuration import Configuration |
76 | -from entertainerlib.utils.logger import Logger |
77 | +from entertainerlib.configuration import Configuration |
78 | +from entertainerlib.logger import Logger |
79 | |
80 | # Entertainer backend core |
81 | from entertainerlib.backend.core.message import Message |
82 | |
83 | === modified file 'entertainerlib/backend/components/feeds/feed_fetcher.py' |
84 | --- entertainerlib/backend/components/feeds/feed_fetcher.py 2009-02-07 21:43:35 +0000 |
85 | +++ entertainerlib/backend/components/feeds/feed_fetcher.py 2009-05-05 04:43:57 +0000 |
86 | @@ -10,8 +10,8 @@ |
87 | from datetime import datetime |
88 | from pysqlite2 import dbapi2 as sqlite |
89 | |
90 | -from entertainerlib.utils.configuration import Configuration |
91 | -from entertainerlib.utils.logger import Logger |
92 | +from entertainerlib.configuration import Configuration |
93 | +from entertainerlib.logger import Logger |
94 | |
95 | # Messaging system |
96 | from entertainerlib.backend.core.message import Message |
97 | |
98 | === modified file 'entertainerlib/backend/components/feeds/feed_manager.py' |
99 | --- entertainerlib/backend/components/feeds/feed_manager.py 2008-08-15 23:52:30 +0000 |
100 | +++ entertainerlib/backend/components/feeds/feed_manager.py 2009-05-05 04:43:57 +0000 |
101 | @@ -8,8 +8,8 @@ |
102 | from pysqlite2 import dbapi2 as sqlite |
103 | from entertainerlib.backend.components.feeds.feed_fetcher import FeedFetcher |
104 | |
105 | -from entertainerlib.utils.configuration import Configuration |
106 | -from entertainerlib.utils.logger import Logger |
107 | +from entertainerlib.configuration import Configuration |
108 | +from entertainerlib.logger import Logger |
109 | |
110 | # Messaging system |
111 | from entertainerlib.backend.core.message_type_priority import MessageType |
112 | |
113 | === renamed file 'entertainerlib/utils/feed_utils.py' => 'entertainerlib/backend/components/feeds/feed_utils.py' |
114 | --- entertainerlib/utils/feed_utils.py 2009-02-08 07:43:25 +0000 |
115 | +++ entertainerlib/backend/components/feeds/feed_utils.py 2009-05-06 04:00:53 +0000 |
116 | @@ -11,7 +11,7 @@ |
117 | import gtk |
118 | import gtk.glade |
119 | |
120 | -from entertainerlib.utils.configuration import Configuration |
121 | +from entertainerlib.configuration import Configuration |
122 | |
123 | |
124 | class FeedEntryParser: |
125 | |
126 | === modified file 'entertainerlib/backend/components/mediacache/image_cache.py' |
127 | --- entertainerlib/backend/components/mediacache/image_cache.py 2009-02-19 14:30:24 +0000 |
128 | +++ entertainerlib/backend/components/mediacache/image_cache.py 2009-05-05 04:43:57 +0000 |
129 | @@ -11,8 +11,8 @@ |
130 | from pysqlite2 import dbapi2 as sqlite |
131 | |
132 | from entertainerlib.thumbnailer import ImageThumbnailer |
133 | -from entertainerlib.utils.configuration import Configuration |
134 | -from entertainerlib.utils.logger import Logger |
135 | +from entertainerlib.configuration import Configuration |
136 | +from entertainerlib.logger import Logger |
137 | |
138 | from entertainerlib.backend.components.mediacache.cache import Cache |
139 | |
140 | |
141 | === modified file 'entertainerlib/backend/components/mediacache/media_cache_manager.py' |
142 | --- entertainerlib/backend/components/mediacache/media_cache_manager.py 2009-01-06 23:51:38 +0000 |
143 | +++ entertainerlib/backend/components/mediacache/media_cache_manager.py 2009-05-05 04:43:57 +0000 |
144 | @@ -4,8 +4,8 @@ |
145 | __copyright__ = "2007, Lauri Taimila" |
146 | __author__ = "Lauri Taimila <lauri@taimila.com>" |
147 | |
148 | -from entertainerlib.utils.configuration import Configuration |
149 | -from entertainerlib.utils.logger import Logger |
150 | +from entertainerlib.configuration import Configuration |
151 | +from entertainerlib.logger import Logger |
152 | |
153 | from entertainerlib.backend.core.message_type_priority import MessageType |
154 | from entertainerlib.backend.core.message_handler import MessageHandler |
155 | @@ -16,7 +16,7 @@ |
156 | from entertainerlib.backend.components.mediacache.video_cache import VideoCache |
157 | |
158 | class MediaCacheManager(MessageHandler): |
159 | - """Makes sure that frontend has all the data available.""" |
160 | + """Makes sure that client has all the data available.""" |
161 | |
162 | def __init__(self): |
163 | """ |
164 | |
165 | === modified file 'entertainerlib/backend/components/mediacache/music_cache.py' |
166 | --- entertainerlib/backend/components/mediacache/music_cache.py 2009-04-24 20:41:49 +0000 |
167 | +++ entertainerlib/backend/components/mediacache/music_cache.py 2009-05-06 04:46:51 +0000 |
168 | @@ -12,11 +12,11 @@ |
169 | import ogg.vorbis |
170 | from pysqlite2 import dbapi2 as sqlite |
171 | |
172 | -from entertainerlib.utils.albumart_downloader import AlbumArtDownloader |
173 | -from entertainerlib.utils.configuration import Configuration |
174 | -from entertainerlib.utils.logger import Logger |
175 | - |
176 | from entertainerlib.backend.components.mediacache.cache import Cache |
177 | +from entertainerlib.configuration import Configuration |
178 | +from entertainerlib.download import AlbumArtDownloader |
179 | +from entertainerlib.logger import Logger |
180 | + |
181 | |
182 | class MusicCache(Cache): |
183 | """ |
184 | |
185 | === modified file 'entertainerlib/backend/components/mediacache/video_cache.py' |
186 | --- entertainerlib/backend/components/mediacache/video_cache.py 2009-02-19 14:30:24 +0000 |
187 | +++ entertainerlib/backend/components/mediacache/video_cache.py 2009-05-05 04:43:57 +0000 |
188 | @@ -9,8 +9,8 @@ |
189 | from pysqlite2 import dbapi2 as sqlite |
190 | |
191 | from entertainerlib.thumbnailer import VideoThumbnailer |
192 | -from entertainerlib.utils.configuration import Configuration |
193 | -from entertainerlib.utils.logger import Logger |
194 | +from entertainerlib.configuration import Configuration |
195 | +from entertainerlib.logger import Logger |
196 | |
197 | from entertainerlib.backend.components.mediacache.cache import Cache |
198 | from entertainerlib.backend.components.mediacache.video_metadata_search import ( |
199 | |
200 | === modified file 'entertainerlib/backend/components/mediacache/video_metadata_search.py' |
201 | --- entertainerlib/backend/components/mediacache/video_metadata_search.py 2009-02-07 22:12:25 +0000 |
202 | +++ entertainerlib/backend/components/mediacache/video_metadata_search.py 2009-05-05 04:24:32 +0000 |
203 | @@ -12,8 +12,8 @@ |
204 | import threading |
205 | from pysqlite2 import dbapi2 as sqlite |
206 | |
207 | -from entertainerlib.utils.logger import Logger |
208 | -from entertainerlib.utils.configuration import Configuration |
209 | +from entertainerlib.logger import Logger |
210 | +from entertainerlib.configuration import Configuration |
211 | |
212 | class VideoMetadataSearch(threading.Thread): |
213 | """ |
214 | |
215 | === modified file 'entertainerlib/backend/core/client_connection.py' |
216 | --- entertainerlib/backend/core/client_connection.py 2009-02-07 21:43:35 +0000 |
217 | +++ entertainerlib/backend/core/client_connection.py 2009-05-05 04:24:32 +0000 |
218 | @@ -11,7 +11,7 @@ |
219 | # Messaging system |
220 | from entertainerlib.backend.core.message_handler import MessageHandler |
221 | |
222 | -from entertainerlib.utils.logger import Logger |
223 | +from entertainerlib.logger import Logger |
224 | |
225 | class ClientConnection(threading.Thread, MessageHandler): |
226 | """ |
227 | |
228 | === modified file 'entertainerlib/backend/core/connection_server.py' |
229 | --- entertainerlib/backend/core/connection_server.py 2009-02-06 08:13:48 +0000 |
230 | +++ entertainerlib/backend/core/connection_server.py 2009-05-05 04:24:32 +0000 |
231 | @@ -10,7 +10,7 @@ |
232 | |
233 | from entertainerlib.backend.core.client_connection import ClientConnection |
234 | |
235 | -from entertainerlib.utils.logger import Logger |
236 | +from entertainerlib.logger import Logger |
237 | |
238 | class ConnectionServer(threading.Thread): |
239 | """ |
240 | |
241 | === modified file 'entertainerlib/backend/core/message_bus.py' |
242 | --- entertainerlib/backend/core/message_bus.py 2009-02-06 08:13:48 +0000 |
243 | +++ entertainerlib/backend/core/message_bus.py 2009-05-05 04:24:32 +0000 |
244 | @@ -5,7 +5,7 @@ |
245 | from entertainerlib.backend.core.message import Message |
246 | from entertainerlib.backend.core.message_handler import MessageHandler |
247 | from entertainerlib.backend.core.message_type_priority import MessageType |
248 | -from entertainerlib.utils.logger import Logger |
249 | +from entertainerlib.logger import Logger |
250 | |
251 | __licence__ = "GPLv2" |
252 | __copyright__ = "2007, Lauri Taimila" |
253 | |
254 | === modified file 'entertainerlib/backend/core/message_bus_proxy.py' |
255 | --- entertainerlib/backend/core/message_bus_proxy.py 2009-01-05 03:25:03 +0000 |
256 | +++ entertainerlib/backend/core/message_bus_proxy.py 2009-05-05 04:11:48 +0000 |
257 | @@ -9,7 +9,7 @@ |
258 | import threading |
259 | from cStringIO import StringIO |
260 | |
261 | -from entertainerlib.utils.configuration import Configuration |
262 | +from entertainerlib.configuration import Configuration |
263 | |
264 | class MessageBusProxy(threading.Thread): |
265 | """ |
266 | |
267 | === modified file 'entertainerlib/backend/core/message_type_priority.py' |
268 | --- entertainerlib/backend/core/message_type_priority.py 2009-01-31 15:46:36 +0000 |
269 | +++ entertainerlib/backend/core/message_type_priority.py 2009-04-30 01:11:22 +0000 |
270 | @@ -33,10 +33,10 @@ |
271 | # Indicates that Content Management UI has been used to update contents. |
272 | CONTENT_CONF_UPDATED = 1 |
273 | |
274 | - # Indicates that frontend has been opened. |
275 | + # Indicates that client has been opened. |
276 | FRONTEND_OPENED = 2 |
277 | |
278 | - # Indicates that frontend has been closed. |
279 | + # Indicates that client has been closed. |
280 | FRONTEND_CLOSED = 3 |
281 | |
282 | # Indicates that Feed cache has been updated. |
283 | |
284 | === renamed directory 'entertainerlib/frontend' => 'entertainerlib/client' |
285 | === modified file 'entertainerlib/client/__init__.py' |
286 | --- entertainerlib/frontend/__init__.py 2009-03-08 03:16:25 +0000 |
287 | +++ entertainerlib/client/__init__.py 2009-05-05 04:43:57 +0000 |
288 | @@ -5,7 +5,7 @@ |
289 | '''Frontend runner''' |
290 | |
291 | # Import statements are inside the function so that they aren't imported |
292 | - # every time something from the frontend is imported |
293 | + # every time something from the client is imported |
294 | |
295 | # cluttergtk must be imported before the first import of clutter so it |
296 | # must be imported even though pylint complains about it not being used. |
297 | @@ -14,12 +14,12 @@ |
298 | import gobject |
299 | import gtk |
300 | |
301 | - from entertainerlib.frontend.translation_setup import TranslationSetup |
302 | + from entertainerlib.client.translation_setup import TranslationSetup |
303 | TranslationSetup() |
304 | |
305 | from entertainerlib.backend.backend_server import BackendServer |
306 | - from entertainerlib.utils.configuration import Configuration |
307 | - from entertainerlib.frontend.frontend_client import FrontendClient |
308 | + from entertainerlib.configuration import Configuration |
309 | + from entertainerlib.client.client import Client |
310 | |
311 | gobject.threads_init() |
312 | gtk.gdk.threads_init() |
313 | @@ -30,7 +30,7 @@ |
314 | print "Entertainer backend starting..." |
315 | BackendServer() |
316 | |
317 | - frontend_client = FrontendClient() |
318 | - frontend_client.start() |
319 | + client_client = Client() |
320 | + client_client.start() |
321 | |
322 | |
323 | |
324 | === renamed file 'entertainerlib/frontend/frontend_client.py' => 'entertainerlib/client/client.py' |
325 | --- entertainerlib/frontend/frontend_client.py 2009-02-10 00:59:03 +0000 |
326 | +++ entertainerlib/client/client.py 2009-05-05 04:43:57 +0000 |
327 | @@ -9,34 +9,34 @@ |
328 | |
329 | import gtk |
330 | |
331 | -from entertainerlib.frontend.backend_connection import BackendConnection |
332 | -from entertainerlib.frontend.gui.user_interface import UserInterface |
333 | -from entertainerlib.frontend.medialibrary.feeds import FeedLibrary |
334 | -from entertainerlib.frontend.medialibrary.music import MusicLibrary |
335 | -from entertainerlib.frontend.medialibrary.images import ImageLibrary |
336 | -from entertainerlib.frontend.medialibrary.videos import VideoLibrary |
337 | -from entertainerlib.utils.configuration import Configuration |
338 | -from entertainerlib.utils.logger import Logger |
339 | -from entertainerlib.utils.system_tray_icon import SystemTrayIcon |
340 | +from entertainerlib.client.backend_connection import BackendConnection |
341 | +from entertainerlib.gui.user_interface import UserInterface |
342 | +from entertainerlib.client.medialibrary.feeds import FeedLibrary |
343 | +from entertainerlib.client.medialibrary.music import MusicLibrary |
344 | +from entertainerlib.client.medialibrary.images import ImageLibrary |
345 | +from entertainerlib.client.medialibrary.videos import VideoLibrary |
346 | +from entertainerlib.configuration import Configuration |
347 | +from entertainerlib.logger import Logger |
348 | +from entertainerlib.gui.system_tray_icon import SystemTrayIcon |
349 | |
350 | -class FrontendClient: |
351 | +class Client: |
352 | ''' |
353 | - Entertainer frontend |
354 | + Entertainer client |
355 | |
356 | - This is a frontend application of the Entertainer. Frontend is a GUI part |
357 | - that user sees on the screen. This class is a core of the frontend. Frontend |
358 | + This is a client application of the Entertainer. Frontend is a GUI part |
359 | + that user sees on the screen. This class is a core of the client. Frontend |
360 | connects to the backend's messagebus at startup. |
361 | ''' |
362 | |
363 | def __init__(self): |
364 | ''' |
365 | - Create a new frontend. |
366 | + Create a new client. |
367 | |
368 | - This initializes all frontend stuff like media librarys, remote |
369 | + This initializes all client stuff like media librarys, remote |
370 | control receiver and GUI. After this we just wait user actions. |
371 | ''' |
372 | config = Configuration() |
373 | - self.logger = Logger().getLogger('frontend.FrontendClient') |
374 | + self.logger = Logger().getLogger('client.FrontendClient') |
375 | self.backend_connection = self.initialize_backend_connection() |
376 | feed_library = FeedLibrary(self.backend_connection) |
377 | music_library = MusicLibrary(self.backend_connection) |
378 | @@ -44,11 +44,11 @@ |
379 | video_library = VideoLibrary(self.backend_connection) |
380 | self.ui = UserInterface( |
381 | feed_library, image_library, music_library, video_library, |
382 | - self.quit_frontend) |
383 | + self.quit_client) |
384 | |
385 | if config.tray_icon_enabled(): |
386 | SystemTrayIcon( |
387 | - self.quit_frontend, self.toggle_interface_visibility) |
388 | + self.quit_client, self.toggle_interface_visibility) |
389 | |
390 | def start(self): |
391 | '''Start the necessary main loop.''' |
392 | @@ -65,8 +65,8 @@ |
393 | |
394 | return backend_connection |
395 | |
396 | - def quit_frontend(self): |
397 | - '''Clean up the connection to the backend then close the frontend.''' |
398 | + def quit_client(self): |
399 | + '''Clean up the connection to the backend then close the client.''' |
400 | self.backend_connection.close_connection() |
401 | |
402 | gtk.main_quit() |
403 | |
404 | === modified file 'entertainerlib/client/media_player.py' |
405 | --- entertainerlib/frontend/media_player.py 2009-02-08 08:44:46 +0000 |
406 | +++ entertainerlib/client/media_player.py 2009-05-05 04:24:32 +0000 |
407 | @@ -11,9 +11,9 @@ |
408 | import clutter |
409 | import gst |
410 | |
411 | -from entertainerlib.frontend.gui.widgets.texture import Texture |
412 | -from entertainerlib.frontend.medialibrary.playable import Playable |
413 | -from entertainerlib.utils.logger import Logger |
414 | +from entertainerlib.gui.widgets.texture import Texture |
415 | +from entertainerlib.client.medialibrary.playable import Playable |
416 | +from entertainerlib.logger import Logger |
417 | |
418 | class MediaPlayer(object): |
419 | """ |
420 | @@ -59,7 +59,7 @@ |
421 | self.repeat = False # Repeat mode |
422 | self.playing = False # Is media player currently playing |
423 | |
424 | - self.logger = Logger().getLogger('frontend.MediaPlayer') |
425 | + self.logger = Logger().getLogger('client.MediaPlayer') |
426 | |
427 | self.video_texture = cluttergst.VideoTexture() |
428 | self.playbin = self.video_texture.get_playbin() |
429 | |
430 | === modified file 'entertainerlib/client/medialibrary/feeds.py' |
431 | --- entertainerlib/frontend/medialibrary/feeds.py 2009-01-26 18:28:26 +0000 |
432 | +++ entertainerlib/client/medialibrary/feeds.py 2009-05-05 04:11:48 +0000 |
433 | @@ -7,7 +7,7 @@ |
434 | |
435 | from pysqlite2 import dbapi2 as sqlite |
436 | |
437 | -from entertainerlib.utils.configuration import Configuration |
438 | +from entertainerlib.configuration import Configuration |
439 | |
440 | class FeedLibrary(object): |
441 | """ |
442 | |
443 | === modified file 'entertainerlib/client/medialibrary/images.py' |
444 | --- entertainerlib/frontend/medialibrary/images.py 2009-01-31 17:57:51 +0000 |
445 | +++ entertainerlib/client/medialibrary/images.py 2009-05-05 04:11:48 +0000 |
446 | @@ -7,7 +7,7 @@ |
447 | import os |
448 | from pysqlite2 import dbapi2 as sqlite |
449 | |
450 | -from entertainerlib.utils.configuration import Configuration |
451 | +from entertainerlib.configuration import Configuration |
452 | |
453 | class ImageLibrary: |
454 | """ |
455 | |
456 | === modified file 'entertainerlib/client/medialibrary/music.py' |
457 | --- entertainerlib/frontend/medialibrary/music.py 2009-03-15 16:01:39 +0000 |
458 | +++ entertainerlib/client/medialibrary/music.py 2009-05-06 04:46:51 +0000 |
459 | @@ -8,10 +8,10 @@ |
460 | import CDDB, DiscID |
461 | from pysqlite2 import dbapi2 as sqlite |
462 | |
463 | -from entertainerlib.utils.configuration import Configuration |
464 | +from entertainerlib.configuration import Configuration |
465 | |
466 | -from entertainerlib.frontend.medialibrary.playable import Playable |
467 | -from entertainerlib.utils.lyrics_downloader import LyricsDownloader |
468 | +from entertainerlib.client.medialibrary.playable import Playable |
469 | +from entertainerlib.download import LyricsDownloader |
470 | |
471 | |
472 | class MusicLibraryException(Exception): |
473 | |
474 | === modified file 'entertainerlib/client/medialibrary/videos.py' |
475 | --- entertainerlib/frontend/medialibrary/videos.py 2009-02-01 19:15:02 +0000 |
476 | +++ entertainerlib/client/medialibrary/videos.py 2009-05-05 04:24:32 +0000 |
477 | @@ -8,10 +8,10 @@ |
478 | import os |
479 | from pysqlite2 import dbapi2 as sqlite |
480 | |
481 | -from entertainerlib.utils.configuration import Configuration |
482 | -from entertainerlib.utils.logger import Logger |
483 | +from entertainerlib.configuration import Configuration |
484 | +from entertainerlib.logger import Logger |
485 | |
486 | -from entertainerlib.frontend.medialibrary.playable import Playable |
487 | +from entertainerlib.client.medialibrary.playable import Playable |
488 | |
489 | class VideoLibrary: |
490 | """ |
491 | @@ -137,7 +137,7 @@ |
492 | |
493 | #Setting default values |
494 | self.logger = Logger().getLogger( |
495 | - 'frontend.medialibrary.videos.VideoItem') |
496 | + 'client.medialibrary.videos.VideoItem') |
497 | self.__title = "" |
498 | self.__filename = "" |
499 | self.__length = 0 |
500 | |
501 | === renamed file 'entertainerlib/utils/configuration.py' => 'entertainerlib/configuration.py' |
502 | --- entertainerlib/utils/configuration.py 2009-03-08 21:29:32 +0000 |
503 | +++ entertainerlib/configuration.py 2009-05-06 05:37:53 +0000 |
504 | @@ -14,10 +14,10 @@ |
505 | from entertainerlib.backend.core.message_type_priority import MessageType |
506 | from entertainerlib.backend.core.message_handler import MessageHandler |
507 | |
508 | -from entertainerlib.utils.theme import Theme |
509 | +from entertainerlib.gui.theme import Theme |
510 | |
511 | SOURCE_CONFIG = { |
512 | - 'branch' : os.path.abspath(os.path.dirname(__file__) + '/../../cfg'), |
513 | + 'branch' : os.path.abspath(os.path.dirname(__file__) + '/../cfg'), |
514 | # Hardcoded path for a package install |
515 | 'package' : "/usr/share/entertainer/cfg" |
516 | } |
517 | @@ -332,9 +332,9 @@ |
518 | location = '' |
519 | return location |
520 | |
521 | - def display_weather_in_frontend(self): |
522 | + def display_weather_in_client(self): |
523 | """ |
524 | - Should we display weather in frontend |
525 | + Should we display weather in client |
526 | @return: Boolean |
527 | """ |
528 | try: |
529 | @@ -344,9 +344,9 @@ |
530 | return False |
531 | return result |
532 | |
533 | - def display_cd_eject_in_frontend(self): |
534 | + def display_cd_eject_in_client(self): |
535 | """ |
536 | - Should we display the cd eject button in frontend |
537 | + Should we display the cd eject button in client |
538 | @return: Boolean |
539 | @author: Joshua Scotton |
540 | """ |
541 | |
542 | === renamed directory 'entertainerlib/backend/core/db' => 'entertainerlib/db' |
543 | === added file 'entertainerlib/dialog.py' |
544 | --- entertainerlib/dialog.py 1970-01-01 00:00:00 +0000 |
545 | +++ entertainerlib/dialog.py 2009-05-06 05:10:14 +0000 |
546 | @@ -0,0 +1,1374 @@ |
547 | +'''Dialogs for Entertainer.''' |
548 | +# pylint: disable-msg=C0302 |
549 | + |
550 | +__licence__ = "GPLv2" |
551 | +__copyright__ = '2009 Entertainer Developers, 2008 Joshua Scotton' |
552 | + |
553 | +import os |
554 | +import shutil |
555 | +import socket |
556 | +import sys |
557 | +import tarfile |
558 | + |
559 | +import gtk |
560 | +import gtk.glade |
561 | + |
562 | +from entertainerlib.backend.core.message import Message |
563 | +from entertainerlib.backend.core.message_bus_proxy import MessageBusProxy |
564 | +from entertainerlib.backend.core.message_type_priority import MessageType |
565 | +from entertainerlib.configuration import Configuration |
566 | +from entertainerlib.logger import Logger |
567 | +from entertainerlib.gui.theme import Theme |
568 | +from entertainerlib.backend.components.feeds.feed_utils import (OPMLParser, |
569 | + FeedConfigTools) |
570 | +from entertainerlib.weather import Weather |
571 | + |
572 | + |
573 | +class ContentManagementDialog: |
574 | + """ |
575 | + This is a content management tool for Entertainer media center application. |
576 | + """ |
577 | + |
578 | + # Temporary storage for entered URL |
579 | + url = "" |
580 | + GLADE_DIR = os.path.join(os.path.dirname(__file__), "glade") |
581 | + |
582 | + def __init__(self, stand_alone): |
583 | + """ |
584 | + Initialize content management dialog |
585 | + @param stand_alone: Boolean, Is this dialog running as a stand alone |
586 | + process |
587 | + """ |
588 | + self.stand_alone = stand_alone |
589 | + self.config = Configuration() |
590 | + self.weather = Weather() |
591 | + |
592 | + # Load glade UI |
593 | + self.gladefile = os.path.join(self.GLADE_DIR, |
594 | + "entertainer-content-management.glade") |
595 | + self.widgets = gtk.glade.XML(self.gladefile) |
596 | + |
597 | + # Get content management dialog and bind signal callbacks |
598 | + self.dialog = self.widgets.get_widget("ContentManagementDialog") |
599 | + if (self.dialog): |
600 | + callback_dic = { |
601 | + "on_button_open_list_clicked" : |
602 | + self.on_button_open_list_clicked, |
603 | + "on_close_button_clicked" : self.on_close_button_clicked, |
604 | + "on_button_remove_videos_clicked" : |
605 | + self.on_button_remove_videos_clicked, |
606 | + "on_button_add_videos_clicked" : |
607 | + self.on_button_add_videos_clicked, |
608 | + "on_button_edit_videos_clicked" : |
609 | + self.on_button_edit_videos_clicked, |
610 | + "on_checkbutton_video_metadata_toggled" : |
611 | + self.on_checkbutton_video_metadata_toggled, |
612 | + "on_button_add_music_clicked" : |
613 | + self.on_button_add_music_clicked, |
614 | + "on_button_remove_music_clicked" : |
615 | + self.on_button_remove_music_clicked, |
616 | + "on_button_edit_music_clicked" : |
617 | + self.on_button_edit_music_clicked, |
618 | + "on_lyrics_checkbox_toggled" : self.on_lyrics_checkbox_toggled, |
619 | + "on_art_checkbox_toggled" : self.on_art_checkbox_toggled, |
620 | + "on_button_add_images_clicked" : |
621 | + self.on_button_add_images_clicked, |
622 | + "on_button_remove_images_clicked" : |
623 | + self.on_button_remove_images_clicked, |
624 | + "on_button_edit_images_clicked" : |
625 | + self.on_button_edit_images_clicked, |
626 | + "on_button_add_feed_clicked" : |
627 | + self.on_button_add_feed_clicked, |
628 | + "on_button_remove_feed_clicked" : |
629 | + self.on_button_remove_feed_clicked, |
630 | + "on_button_edit_feed_clicked" : |
631 | + self.on_button_edit_feed_clicked, |
632 | + "on_fetch_interval_spinbutton_value_changed" : |
633 | + self.on_fetch_interval_spinbutton_value_changed, |
634 | + "on_ContentManagementDialog_destroy" : self.on_dialog_closed, |
635 | + "on_url_dialog_delete_event" : self.on_url_dialog_delete_event, |
636 | + "on_url_dialog_ok_button_clicked" : |
637 | + self.on_url_dialog_ok_button_clicked, |
638 | + "on_url_dialog_cancel_button_clicked" : |
639 | + self.on_url_dialog_cancel_button_clicked, |
640 | + "on_button_video_rebuild_clicked" : |
641 | + self.on_button_video_rebuild_clicked, |
642 | + "on_button_music_rebuild_clicked" : |
643 | + self.on_button_music_rebuild_clicked, |
644 | + "on_button_image_rebuild_clicked" : |
645 | + self.on_button_image_rebuild_clicked, |
646 | + "on_button_feed_rebuild_clicked" : |
647 | + self.on_button_feed_rebuild_clicked, |
648 | + "on_button_add_weather_clicked" : |
649 | + self.on_button_add_weather_clicked, |
650 | + "on_button_remove_weather_clicked" : |
651 | + self.on_button_remove_weather_clicked, |
652 | + "on_weather_display_checkbox_toggled" : |
653 | + self.on_weather_display_checkbox_toggled, |
654 | + "on_location_find_button_clicked" : |
655 | + self.on_location_find_button_clicked, |
656 | + "on_location_cancel_button_clicked" : |
657 | + self.on_location_cancel_button_clicked, |
658 | + "on_location_add_button_clicked" : |
659 | + self.on_location_add_button_clicked, |
660 | + "on_location_entry_activate" : self.on_location_entry_activate} |
661 | + self.widgets.signal_autoconnect(callback_dic) |
662 | + |
663 | + # Initialize dialog widgets with correct values and show dialog |
664 | + self.init_dialog_values_from_configure_file() |
665 | + self.dialog.resize(500, 300) |
666 | + self.dialog.show() |
667 | + |
668 | + # Initialize location list in search dialog |
669 | + result_list = self.widgets.get_widget("location_results_treeview") |
670 | + store = gtk.ListStore(str) |
671 | + result_list.set_model(store) |
672 | + cell_renderer = gtk.CellRendererText() |
673 | + column = gtk.TreeViewColumn(_("Location"), cell_renderer, text=0) |
674 | + result_list.append_column(column) |
675 | + |
676 | +# Signal handlers |
677 | + |
678 | + def on_dialog_closed(self, widget): |
679 | + """Callback function for dialog's close button""" |
680 | + try: |
681 | + proxy = MessageBusProxy(client_name = "Content Management GUI") |
682 | + proxy.connectToMessageBus() |
683 | + proxy.sendMessage(Message(MessageType.CONTENT_CONF_UPDATED)) |
684 | + proxy.disconnectFromMessageBus() |
685 | + except socket.error: |
686 | + error = gtk.MessageDialog( |
687 | + None, gtk.DIALOG_MODAL, |
688 | + gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, _( |
689 | + "Entertainer backend is not running. " |
690 | + "Cache cannot be rebuilt." |
691 | + )) |
692 | + error.run() |
693 | + error.destroy() |
694 | + |
695 | + |
696 | + if(self.stand_alone): |
697 | + self.dialog.hide() |
698 | + self.dialog.destroy() |
699 | + gtk.main_quit() |
700 | + else: |
701 | + self.dialog.hide() |
702 | + self.dialog.destroy() |
703 | + |
704 | + def on_close_button_clicked(self, widget): |
705 | + """Callback function for dialog's close button""" |
706 | + if(self.stand_alone): |
707 | + self.dialog.hide() |
708 | + self.dialog.destroy() |
709 | + gtk.main_quit() |
710 | + else: |
711 | + self.dialog.hide() |
712 | + self.dialog.destroy() |
713 | + |
714 | + def on_button_add_videos_clicked(self, widget): |
715 | + """Opens add URL dialog. """ |
716 | + widget = self.widgets.get_widget("treeview_videos") |
717 | + model = widget.get_model() |
718 | + # Open "Select folder" dialog |
719 | + dialog = gtk.FileChooserDialog(_("Select video folder"), None, |
720 | + gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, |
721 | + (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL, |
722 | + gtk.STOCK_OPEN,gtk.RESPONSE_OK), |
723 | + None) |
724 | + status = dialog.run() |
725 | + # If folder was selected we add it to model and update config file |
726 | + if(status == gtk.RESPONSE_OK): |
727 | + self.add_to_model_and_config(dialog.get_current_folder(), model, |
728 | + self.video_folders, "Videos") |
729 | + dialog.destroy() |
730 | + |
731 | + def on_button_remove_videos_clicked(self, widget): |
732 | + """Remove currently selected folder from video folders""" |
733 | + widget = self.widgets.get_widget("treeview_videos") |
734 | + model = widget.get_model() |
735 | + selection = widget.get_selection().get_selected() |
736 | + if selection[1] == None: |
737 | + return |
738 | + rm_folder = model.get_value(selection[1], 0) |
739 | + self.video_folders.remove(rm_folder) |
740 | + str_folders = ";".join(self.video_folders) |
741 | + self.config.write_content_value("Videos", "folders", str_folders) |
742 | + model.remove(selection[1]) |
743 | + |
744 | + def on_button_edit_videos_clicked(self, widget): |
745 | + """Edit currently selected folder""" |
746 | + widget = self.widgets.get_widget("treeview_videos") |
747 | + url_dialog = self.widgets.get_widget("url_dialog") |
748 | + url_entry = self.widgets.get_widget("url_entry") |
749 | + model = widget.get_model() |
750 | + selection = widget.get_selection().get_selected() |
751 | + if selection[1] == None: |
752 | + return |
753 | + folder = model.get_value(selection[1], 0) |
754 | + url_entry.set_text(folder) |
755 | + url_dialog.set_title(_("Edit URL")) |
756 | + status = url_dialog.run() |
757 | + if status == gtk.RESPONSE_OK and os.path.exists(self.url): |
758 | + # Update list model |
759 | + model.set_value(selection[1], 0, self.url) |
760 | + # Update configure file |
761 | + pos = self.video_folders.index(folder) |
762 | + self.video_folders.remove(folder) |
763 | + self.video_folders.insert(pos, self.url) |
764 | + str_folders = ";".join(self.video_folders) |
765 | + self.config.write_content_value("Videos", "folders", |
766 | + str_folders) |
767 | + |
768 | + def on_checkbutton_video_metadata_toggled(self, widget): |
769 | + """ |
770 | + Download video file metadata from internet |
771 | + @param widget: GTK-Widget |
772 | + """ |
773 | + self.config.write_content_value("Videos", "download_metadata", |
774 | + widget.get_active()) |
775 | + |
776 | + def on_button_add_music_clicked(self, widget): |
777 | + """ |
778 | + Opens add URL dialog |
779 | + @param widget: GTK-Widget |
780 | + """ |
781 | + widget = self.widgets.get_widget("treeview_music") |
782 | + model = widget.get_model() |
783 | + # Open "Select folder" dialog |
784 | + dialog = gtk.FileChooserDialog(_("Select music folder"), None, |
785 | + gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, |
786 | + (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, |
787 | + gtk.RESPONSE_OK), |
788 | + None) |
789 | + status = dialog.run() |
790 | + # If folder was selected we add it to model and update config file |
791 | + if(status == gtk.RESPONSE_OK): |
792 | + self.add_to_model_and_config(dialog.get_current_folder(), model, |
793 | + self.music_folders, "Music") |
794 | + dialog.destroy() |
795 | + |
796 | + def on_button_remove_music_clicked(self, widget): |
797 | + """Remove currently selected folder from music folders""" |
798 | + widget = self.widgets.get_widget("treeview_music") |
799 | + model = widget.get_model() |
800 | + selection = widget.get_selection().get_selected() |
801 | + if selection[1] == None: |
802 | + return |
803 | + rm_folder = model.get_value(selection[1], 0) |
804 | + self.music_folders.remove(rm_folder) |
805 | + str_folders = ";".join(self.music_folders) |
806 | + self.config.write_content_value("Music", "folders", str_folders) |
807 | + model.remove(selection[1]) |
808 | + |
809 | + def on_button_edit_music_clicked(self, widget): |
810 | + """Edit currently selected music folder""" |
811 | + widget = self.widgets.get_widget("treeview_music") |
812 | + url_dialog = self.widgets.get_widget("url_dialog") |
813 | + url_entry = self.widgets.get_widget("url_entry") |
814 | + model = widget.get_model() |
815 | + selection = widget.get_selection().get_selected() |
816 | + if selection[1] == None: |
817 | + return |
818 | + folder = model.get_value(selection[1], 0) |
819 | + url_entry.set_text(folder) |
820 | + url_dialog.set_title(_("Edit URL")) |
821 | + status = url_dialog.run() |
822 | + if status == gtk.RESPONSE_OK and os.path.exists(self.url): |
823 | + # Update list model |
824 | + model.set_value(selection[1], 0, self.url) |
825 | + # Update configure file |
826 | + pos = self.music_folders.index(folder) |
827 | + self.music_folders.remove(folder) |
828 | + self.music_folders.insert(pos, self.url) |
829 | + str_folders = ";".join(self.music_folders) |
830 | + self.config.write_content_value("Music", "folders", str_folders) |
831 | + |
832 | + def on_button_add_images_clicked(self, widget): |
833 | + """Opens add URL dialog. """ |
834 | + widget = self.widgets.get_widget("treeview_images") |
835 | + model = widget.get_model() |
836 | + # Open "Select folder" dialog |
837 | + dialog = gtk.FileChooserDialog(_("Select image folder"), None, |
838 | + gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, |
839 | + (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, |
840 | + gtk.RESPONSE_OK), |
841 | + None) |
842 | + status = dialog.run() |
843 | + # If folder was selected we add it to model and update config file |
844 | + if(status == gtk.RESPONSE_OK): |
845 | + self.add_to_model_and_config(dialog.get_current_folder(), model, |
846 | + self.image_folders, "Images") |
847 | + dialog.destroy() |
848 | + |
849 | + def on_button_remove_images_clicked(self, widget): |
850 | + """Remove currently selected folder from images folders""" |
851 | + widget = self.widgets.get_widget("treeview_images") |
852 | + model = widget.get_model() |
853 | + selection = widget.get_selection().get_selected() |
854 | + if selection[1] == None: |
855 | + return |
856 | + rm_folder = model.get_value(selection[1], 0) |
857 | + self.image_folders.remove(rm_folder) |
858 | + str_folders = ";".join(self.image_folders) |
859 | + self.config.write_content_value("Images", "folders", str_folders) |
860 | + model.remove(selection[1]) |
861 | + |
862 | + def on_button_edit_images_clicked(self, widget): |
863 | + """Edit currently selected music folder""" |
864 | + widget = self.widgets.get_widget("treeview_images") |
865 | + url_dialog = self.widgets.get_widget("url_dialog") |
866 | + url_entry = self.widgets.get_widget("url_entry") |
867 | + model = widget.get_model() |
868 | + selection = widget.get_selection().get_selected() |
869 | + if selection[1] == None: |
870 | + return |
871 | + folder = model.get_value(selection[1], 0) |
872 | + url_entry.set_text(folder) |
873 | + url_dialog.set_title(_("Edit URL")) |
874 | + status = url_dialog.run() |
875 | + if status == gtk.RESPONSE_OK and os.path.exists(self.url): |
876 | + # Update list model |
877 | + model.set_value(selection[1], 0, self.url) |
878 | + # Update configure file |
879 | + pos = self.image_folders.index(folder) |
880 | + self.image_folders.remove(folder) |
881 | + self.image_folders.insert(pos, self.url) |
882 | + str_folders = ";".join(self.image_folders) |
883 | + self.config.write_content_value("Images", "folders", |
884 | + str_folders) |
885 | + |
886 | + def on_button_add_feed_clicked(self, widget): |
887 | + """Opens add feed dialog. """ |
888 | + widget = self.widgets.get_widget("treeview_feeds") |
889 | + url_dialog = self.widgets.get_widget("url_dialog") |
890 | + model = widget.get_model() |
891 | + # Open dialog |
892 | + url_dialog.set_title(_("Add RSS-feed")) |
893 | + status = url_dialog.run() |
894 | + # If folder was selected we add it to model and update config file |
895 | + if(status == gtk.RESPONSE_OK): |
896 | + model.append([self.url]) |
897 | + self.feeds.append(self.url) |
898 | + str_folders = ";".join(self.feeds) |
899 | + self.config.write_content_value("RSS", "feeds", str_folders) |
900 | + |
901 | + def on_button_remove_feed_clicked(self, widget): |
902 | + """Remove currently selected reed from RSS-feeds""" |
903 | + widget = self.widgets.get_widget("treeview_feeds") |
904 | + model = widget.get_model() |
905 | + selection = widget.get_selection().get_selected() |
906 | + if selection[1] == None: |
907 | + return |
908 | + rm_folder = model.get_value(selection[1], 0) |
909 | + self.feeds.remove(rm_folder) |
910 | + str_folders = ";".join(self.feeds) |
911 | + self.config.write_content_value("RSS", "feeds", str_folders) |
912 | + model.remove(selection[1]) |
913 | + |
914 | + def on_button_edit_feed_clicked(self, widget): |
915 | + """Edit currently selected feed""" |
916 | + widget = self.widgets.get_widget("treeview_feeds") |
917 | + url_dialog = self.widgets.get_widget("url_dialog") |
918 | + url_entry = self.widgets.get_widget("url_entry") |
919 | + model = widget.get_model() |
920 | + selection = widget.get_selection().get_selected() |
921 | + if selection[1] == None: |
922 | + return |
923 | + feed = model.get_value(selection[1], 0) |
924 | + url_entry.set_text(feed) |
925 | + url_dialog.set_title(_("Edit feed")) |
926 | + status = url_dialog.run() |
927 | + if status == gtk.RESPONSE_OK: |
928 | + # Update list model |
929 | + model.set_value(selection[1], 0, self.url) |
930 | + # Update configure file |
931 | + pos = self.feeds.index(feed) |
932 | + self.feeds.remove(feed) |
933 | + self.feeds.insert(pos, self.url) |
934 | + str_feeds = ";".join(self.feeds) |
935 | + self.config.write_content_value("RSS", "feeds", str_feeds) |
936 | + |
937 | + def on_button_open_list_clicked(self, widget): |
938 | + """Opens the open feed source dialog""" |
939 | + open_dialog = OpenFeedSourceDialog( |
940 | + self.widgets.get_widget("treeview_feeds"), self.feeds) |
941 | + open_dialog.dialog.connect("destroy", open.on_closeButton_clicked) |
942 | + open_dialog.dialog.hide() |
943 | + open_dialog.dialog.destroy() |
944 | + |
945 | + def on_fetch_interval_spinbutton_value_changed(self, widget): |
946 | + self.config.write_content_value("RSS", "fetch_interval", |
947 | + widget.get_value_as_int()) |
948 | + |
949 | + def on_lyrics_checkbox_toggled(self, widget): |
950 | + self.config.write_content_value("Music", "download_lyrics", |
951 | + widget.get_active()) |
952 | + |
953 | + def on_art_checkbox_toggled(self, widget): |
954 | + self.config.write_content_value("Music", "download_album_art", |
955 | + widget.get_active()) |
956 | + |
957 | + def on_url_dialog_ok_button_clicked(self, widget): |
958 | + """URL dialog OK button pressed. Sets self.url""" |
959 | + url_dialog = self.widgets.get_widget("url_dialog") |
960 | + url_entry = self.widgets.get_widget("url_entry") |
961 | + url_dialog.hide() |
962 | + self.url = url_entry.get_text() |
963 | + url_entry.set_text("") |
964 | + url_dialog.response(gtk.RESPONSE_OK) |
965 | + |
966 | + def on_url_dialog_cancel_button_clicked(self, widget): |
967 | + """URL dialog cancelled. Hides dialog""" |
968 | + url_dialog = self.widgets.get_widget("url_dialog") |
969 | + url_entry = self.widgets.get_widget("url_entry") |
970 | + url_dialog.hide() |
971 | + url_entry.set_text("") |
972 | + url_dialog.response(gtk.RESPONSE_CANCEL) |
973 | + |
974 | + def on_url_dialog_delete_event(self, widget, data): |
975 | + """Dialog's X clicked. Hides dialog""" |
976 | + url_dialog = self.widgets.get_widget("url_dialog") |
977 | + url_entry = self.widgets.get_widget("url_entry") |
978 | + url_dialog.hide() |
979 | + url_entry.set_text("") |
980 | + url_dialog.response(gtk.RESPONSE_CANCEL) |
981 | + return True |
982 | + |
983 | + def on_button_add_weather_clicked(self, widget): |
984 | + """ |
985 | + Open location search dialog |
986 | + @param widget: GTK-Widget |
987 | + """ |
988 | + location_dialog = self.widgets.get_widget("weather_search_dialog") |
989 | + location_dialog.set_title(_("Add location")) |
990 | + |
991 | + # Clear results |
992 | + result_list = self.widgets.get_widget("location_results_treeview") |
993 | + model = result_list.get_model() |
994 | + model.clear() |
995 | + |
996 | + status = location_dialog.run() |
997 | + if(status == gtk.RESPONSE_OK): |
998 | + print "Added" |
999 | + |
1000 | + def on_button_remove_weather_clicked(self, widget): |
1001 | + """ |
1002 | + Remove currently selected weather location from the location list |
1003 | + @param widget: GTK-Widget |
1004 | + """ |
1005 | + widget = self.widgets.get_widget("treeview_locations") |
1006 | + model = widget.get_model() |
1007 | + self.weather_locations = [] |
1008 | + str_folders = "" |
1009 | + self.config.write_content_value("Weather", "location", str_folders) |
1010 | + model.clear() |
1011 | + |
1012 | + def on_weather_display_checkbox_toggled(self, widget): |
1013 | + """ |
1014 | + Checkbox that defines should we use weather conditions |
1015 | + @param widget: GTK-Widget |
1016 | + """ |
1017 | + self.config.write_content_value("Weather", "display_in_menu", |
1018 | + widget.get_active()) |
1019 | + if widget.get_active(): |
1020 | + self.widgets.get_widget("button_add_weather").set_sensitive(True) |
1021 | + self.widgets.get_widget( |
1022 | + "button_remove_weather").set_sensitive(True) |
1023 | + self.widgets.get_widget("treeview_locations").set_sensitive(True) |
1024 | + else: |
1025 | + self.widgets.get_widget("button_add_weather").set_sensitive(False) |
1026 | + self.widgets.get_widget( |
1027 | + "button_remove_weather").set_sensitive(False) |
1028 | + self.widgets.get_widget("treeview_locations").set_sensitive(False) |
1029 | + |
1030 | + def on_location_find_button_clicked(self, widget): |
1031 | + """ |
1032 | + Find location by search string |
1033 | + @param widget: GTK-Widget |
1034 | + """ |
1035 | + add_button = self.widgets.get_widget("location_add_button") |
1036 | + search_term = self.widgets.get_widget("location_entry").get_text() |
1037 | + result_list = self.widgets.get_widget("location_results_treeview") |
1038 | + model = result_list.get_model() |
1039 | + model.clear() |
1040 | + if search_term != "": |
1041 | + self.weather.set_location(search_term) |
1042 | + self.weather.refresh() |
1043 | + results = self.weather.get_forecasts() |
1044 | + if len(results) > 0: |
1045 | + add_button.set_sensitive(True) |
1046 | + model.append([search_term]) |
1047 | + result_list.set_cursor(0) |
1048 | + else: |
1049 | + model.clear() |
1050 | + model.append([_("Location Not Found!")]) |
1051 | + add_button.set_sensitive(False) |
1052 | + |
1053 | + def on_location_cancel_button_clicked(self, widget): |
1054 | + """ |
1055 | + Close location search dialog without taking any actions.0 |
1056 | + @param widget: GTK-Widget |
1057 | + """ |
1058 | + location_dialog = self.widgets.get_widget("weather_search_dialog") |
1059 | + location_entry = self.widgets.get_widget("location_entry") |
1060 | + location_dialog.hide() |
1061 | + location_entry.set_text("") |
1062 | + location_dialog.response(gtk.RESPONSE_CANCEL) |
1063 | + |
1064 | + def on_location_add_button_clicked(self, widget): |
1065 | + """ |
1066 | + Add selected location to location list and close search dialog |
1067 | + @param widget: GTK-Widget |
1068 | + """ |
1069 | + self.weather_locations = [] |
1070 | + result_list = self.widgets.get_widget("location_results_treeview") |
1071 | + model = result_list.get_model() |
1072 | + selection = result_list.get_selection().get_selected() |
1073 | + if selection[1] == None: |
1074 | + return |
1075 | + location_string = model.get_value(selection[1], 0) |
1076 | + |
1077 | + location_list = self.widgets.get_widget("treeview_locations") |
1078 | + loc_model = location_list.get_model() |
1079 | + loc_model.clear() |
1080 | + loc_model.append([location_string]) |
1081 | + |
1082 | + self.weather_locations.append(location_string) |
1083 | + str_locations = ";".join(self.weather_locations) |
1084 | + self.config.write_content_value("Weather", "location", str_locations) |
1085 | + |
1086 | + location_dialog = self.widgets.get_widget("weather_search_dialog") |
1087 | + location_entry = self.widgets.get_widget("location_entry") |
1088 | + location_dialog.hide() |
1089 | + location_entry.set_text("") |
1090 | + location_dialog.response(gtk.RESPONSE_CANCEL) |
1091 | + |
1092 | + def on_location_entry_activate(self, widget): |
1093 | + """ |
1094 | + User hit enter on location entry to start search |
1095 | + @param widget: GTK-Widget |
1096 | + """ |
1097 | + self.on_location_find_button_clicked(widget) |
1098 | + |
1099 | + def on_button_video_rebuild_clicked(self, widget): |
1100 | + """ |
1101 | + Rebuild video cache requested |
1102 | + @param widget: GTK-Widget |
1103 | + """ |
1104 | + try: |
1105 | + proxy = MessageBusProxy(client_name = "Content Management GUI") |
1106 | + proxy.connectToMessageBus() |
1107 | + proxy.sendMessage(Message(MessageType.REBUILD_VIDEO_CACHE)) |
1108 | + proxy.disconnectFromMessageBus() |
1109 | + except socket.error: |
1110 | + error = gtk.MessageDialog( |
1111 | + None, gtk.DIALOG_MODAL, |
1112 | + gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, _( |
1113 | + "Entertainer backend is not running. " |
1114 | + "Cache cannot be rebuilt." |
1115 | + )) |
1116 | + error.run() |
1117 | + error.destroy() |
1118 | + |
1119 | + def on_button_music_rebuild_clicked(self, widget): |
1120 | + """ |
1121 | + Rebuild music cache requested |
1122 | + @param widget: GTK-Widget |
1123 | + """ |
1124 | + try: |
1125 | + proxy = MessageBusProxy(client_name = "Content Management GUI") |
1126 | + proxy.connectToMessageBus() |
1127 | + proxy.sendMessage(Message(MessageType.REBUILD_MUSIC_CACHE)) |
1128 | + proxy.disconnectFromMessageBus() |
1129 | + except socket.error: |
1130 | + error = gtk.MessageDialog( |
1131 | + None, gtk.DIALOG_MODAL, |
1132 | + gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, _( |
1133 | + "Entertainer backend is not running. " |
1134 | + "Cache cannot be rebuilt." |
1135 | + )) |
1136 | + error.run() |
1137 | + error.destroy() |
1138 | + |
1139 | + def on_button_image_rebuild_clicked(self, widget): |
1140 | + """ |
1141 | + Rebuild image cache requested |
1142 | + @param widget: GTK-Widget |
1143 | + """ |
1144 | + try: |
1145 | + proxy = MessageBusProxy(client_name = "Content Management GUI") |
1146 | + proxy.connectToMessageBus() |
1147 | + proxy.sendMessage(Message(MessageType.REBUILD_IMAGE_CACHE)) |
1148 | + proxy.disconnectFromMessageBus() |
1149 | + except socket.error: |
1150 | + error = gtk.MessageDialog( |
1151 | + None, gtk.DIALOG_MODAL, |
1152 | + gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, _( |
1153 | + "Entertainer backend is not running. " |
1154 | + "Cache cannot be rebuilt." |
1155 | + )) |
1156 | + error.run() |
1157 | + error.destroy() |
1158 | + |
1159 | + def on_button_feed_rebuild_clicked(self, widget): |
1160 | + """ |
1161 | + Rebuild feed cache requested |
1162 | + @param widget: GTK-Widget |
1163 | + """ |
1164 | + #We need the user to confirm the rebuild feed cache request |
1165 | + dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, |
1166 | + gtk.BUTTONS_OK_CANCEL, |
1167 | + _("This will completely remove any feed entries in the cache!")) |
1168 | + status = dialog.run() |
1169 | + #If user has ok'd the request send the message to the message bus |
1170 | + if(status == gtk.RESPONSE_OK): |
1171 | + try: |
1172 | + proxy = MessageBusProxy(client_name = "Content Management GUI") |
1173 | + proxy.connectToMessageBus() |
1174 | + proxy.sendMessage(Message(MessageType.REBUILD_FEED_CACHE)) |
1175 | + proxy.disconnectFromMessageBus() |
1176 | + except socket.error: |
1177 | + error = gtk.MessageDialog( |
1178 | + None, gtk.DIALOG_MODAL, |
1179 | + gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, _( |
1180 | + "Entertainer backend is not running. " |
1181 | + "Cache cannot be rebuilt." |
1182 | + )) |
1183 | + error.run() |
1184 | + error.destroy() |
1185 | + |
1186 | + dialog.destroy() |
1187 | + |
1188 | + def init_dialog_values_from_configure_file(self): |
1189 | + """Read configuration and set dialog widget values with read values. |
1190 | + """ |
1191 | + # == Videos == |
1192 | + videolist_widget = self.widgets.get_widget("treeview_videos") |
1193 | + videostore = gtk.ListStore(str) |
1194 | + |
1195 | + cell_renderer = gtk.CellRendererText() |
1196 | + column = gtk.TreeViewColumn(_("Folders"), cell_renderer, text=0) |
1197 | + videolist_widget.append_column(column) |
1198 | + |
1199 | + self.video_folders = self.config.get_video_folders() |
1200 | + |
1201 | + # Fill model with folders read from config file |
1202 | + self.init_model(videostore, self.video_folders) |
1203 | + |
1204 | + videolist_widget.set_model(videostore) |
1205 | + |
1206 | + # Checkboxes |
1207 | + metadata_checkbox = self.widgets.get_widget("video_metadata_checkbox") |
1208 | + md_val = self.config.download_video_metadata() |
1209 | + metadata_checkbox.set_active(md_val) |
1210 | + |
1211 | + # == Music == |
1212 | + musiclist_widget = self.widgets.get_widget("treeview_music") |
1213 | + music_model = gtk.ListStore(str) |
1214 | + |
1215 | + music_cell = gtk.CellRendererText() |
1216 | + music_column = gtk.TreeViewColumn(_("Folders"), music_cell, text=0) |
1217 | + musiclist_widget.append_column(music_column) |
1218 | + |
1219 | + self.music_folders = self.config.get_music_folders() |
1220 | + |
1221 | + # Fill model with folders read from config file |
1222 | + self.init_model(music_model, self.music_folders) |
1223 | + |
1224 | + musiclist_widget.set_model(music_model) |
1225 | + |
1226 | + # Checkboxes |
1227 | + art_checkbox = self.widgets.get_widget("art_checkbox") |
1228 | + art_val = self.config.download_album_art() |
1229 | + art_checkbox.set_active(art_val) |
1230 | + |
1231 | + lyrics_checkbox = self.widgets.get_widget("lyrics_checkbox") |
1232 | + lyrics_val = self.config.download_lyrics() |
1233 | + lyrics_checkbox.set_active(lyrics_val) |
1234 | + |
1235 | + # == Images == |
1236 | + imagelist_widget = self.widgets.get_widget("treeview_images") |
1237 | + images_model = gtk.ListStore(str) |
1238 | + |
1239 | + img_cell = gtk.CellRendererText() |
1240 | + img_column = gtk.TreeViewColumn(_("Folders"), img_cell, text=0) |
1241 | + imagelist_widget.append_column(img_column) |
1242 | + |
1243 | + self.image_folders = self.config.get_image_folders() |
1244 | + |
1245 | + # Fill model with folders read from config file |
1246 | + self.init_model(images_model, self.image_folders) |
1247 | + |
1248 | + imagelist_widget.set_model(images_model) |
1249 | + |
1250 | + # == RSS-feeds == |
1251 | + feedlist_widget = self.widgets.get_widget("treeview_feeds") |
1252 | + feed_model = gtk.ListStore(str) |
1253 | + |
1254 | + rss_cell = gtk.CellRendererText() |
1255 | + rss_column = gtk.TreeViewColumn(_("Feeds"), rss_cell, text=0) |
1256 | + feedlist_widget.append_column(rss_column) |
1257 | + |
1258 | + self.feeds = self.config.get_feeds() |
1259 | + |
1260 | + # Fill model with folders read from config file |
1261 | + for i in range(len(self.feeds)): |
1262 | + feed_model.insert(i, [self.feeds[i]]) |
1263 | + |
1264 | + feedlist_widget.set_model(feed_model) |
1265 | + |
1266 | + # Interval spinner |
1267 | + interval_spinner = self.widgets.get_widget("fetch_interval_spinbutton") |
1268 | + interval_val = self.config.get_feed_fetch_interval() |
1269 | + if interval_val < 15: |
1270 | + interval_val = 15 |
1271 | + elif interval_val > 900: |
1272 | + interval_val = 900 |
1273 | + interval_spinner.set_value(interval_val) |
1274 | + |
1275 | + # == Weather location == |
1276 | + locationlist_widget = self.widgets.get_widget("treeview_locations") |
1277 | + location_model = gtk.ListStore(str) |
1278 | + |
1279 | + loc_cell = gtk.CellRendererText() |
1280 | + location_column = gtk.TreeViewColumn(_("Location"), loc_cell, text=0) |
1281 | + locationlist_widget.append_column(location_column) |
1282 | + |
1283 | + self.weather_location = self.config.get_weather_location() |
1284 | + |
1285 | + # Fill model with location read from config file |
1286 | + location_model.insert(0, [self.weather_location]) |
1287 | + |
1288 | + locationlist_widget.set_model(location_model) |
1289 | + |
1290 | + # Checkboxes |
1291 | + weather_display_checkbox = self.widgets.get_widget( |
1292 | + "weather_display_checkbox") |
1293 | + display_val = self.config.display_weather_in_client() |
1294 | + weather_display_checkbox.set_active(display_val) |
1295 | + if not display_val: |
1296 | + self.widgets.get_widget("button_add_weather").set_sensitive(False) |
1297 | + self.widgets.get_widget("button_remove_weather").set_sensitive( |
1298 | + False) |
1299 | + self.widgets.get_widget("treeview_locations").set_sensitive(False) |
1300 | + |
1301 | + def add_to_model_and_config(self, selected_folder, model, folders, kind): |
1302 | + """ |
1303 | + Add selected_folder to the model and the folders list while updating |
1304 | + the configuration item section specified by type |
1305 | + """ |
1306 | + if not selected_folder in folders: |
1307 | + model.append([selected_folder]) |
1308 | + |
1309 | + if(folders == None): |
1310 | + folders = [selected_folder] |
1311 | + else: |
1312 | + folders.append(selected_folder) |
1313 | + |
1314 | + if "" in folders: |
1315 | + folders.remove("") |
1316 | + str_folders = ";".join(folders) |
1317 | + self.config.write_content_value(kind, "folders", str_folders) |
1318 | + |
1319 | + def init_model(self, model, items): |
1320 | + """Fill model with items from supplied list""" |
1321 | + for i in range(len(items)): |
1322 | + if not str(items[i]).strip() == "": |
1323 | + model.insert(i, [items[i]]) |
1324 | + |
1325 | + |
1326 | +class LogViewer: |
1327 | + """ |
1328 | + Implements dialog that allows user to see logged events. |
1329 | + |
1330 | + This dialog is used to check Entertainer logfiles. It reads all data from |
1331 | + selected file and saves rows to self.log_rows. Then it filters unwanted |
1332 | + rows away by calling self.filterMessages(). This method adds rows to |
1333 | + ListStore, which is the model of TreeView object. |
1334 | + |
1335 | + Combobox and refresh -button actions read files again |
1336 | + Checkbox actions just filter current rows again |
1337 | + """ |
1338 | + |
1339 | + GLADE_DIR = os.path.join(os.path.dirname(__file__), "glade") |
1340 | + |
1341 | + # Is this dialog running as a stand alone process |
1342 | + __STAND_ALONE = None |
1343 | + |
1344 | + widgets = None |
1345 | + dialog = None |
1346 | + log_store = None |
1347 | + log_rows = [] |
1348 | + |
1349 | + gladefile = os.path.join(GLADE_DIR, "log_dialog.glade") |
1350 | + |
1351 | + def __init__(self, stand_alone): |
1352 | + self.logfile_entertainer = Configuration().ENTERTAINER_LOG |
1353 | + self.logger = Logger().getLogger('utils.log_viewer') |
1354 | + |
1355 | + self.__STAND_ALONE = stand_alone |
1356 | + try: |
1357 | + self.widgets = gtk.glade.XML(self.gladefile) |
1358 | + except RuntimeError: |
1359 | + self.logger.critical("Couldn't open glade file: " + self.gladefile) |
1360 | + sys.exit(1) |
1361 | + callback_dic = { |
1362 | + "on_close_log_button_clicked" : self.on_close_log_button_clicked, |
1363 | + "on_log_refresh_button_clicked" : self.update_log_rows, |
1364 | + "on_checkbutton_debug_toggled" : self.filter_messages, |
1365 | + "on_checkbutton_critical_toggled" : self.filter_messages, |
1366 | + "on_checkbutton_error_toggled" : self.filter_messages, |
1367 | + "on_checkbutton_warning_toggled" : self.filter_messages, |
1368 | + "on_checkbutton_info_toggled" : self.filter_messages } |
1369 | + |
1370 | + self.widgets.signal_autoconnect(callback_dic) |
1371 | + |
1372 | + # Create log treeview |
1373 | + treeview = self.widgets.get_widget("treeview_log") |
1374 | + cell_renderer1 = gtk.CellRendererText() |
1375 | + cell_renderer2 = gtk.CellRendererText() |
1376 | + cell_renderer3 = gtk.CellRendererText() |
1377 | + cell_renderer4 = gtk.CellRendererText() |
1378 | + |
1379 | + column1 = gtk.TreeViewColumn("Date") |
1380 | + column1.pack_start(cell_renderer1, True) |
1381 | + column1.set_attributes(cell_renderer1, text = 0) |
1382 | + |
1383 | + column2 = gtk.TreeViewColumn("Time") |
1384 | + column2.pack_start(cell_renderer2, True) |
1385 | + column2.set_attributes(cell_renderer2, text = 1) |
1386 | + |
1387 | + column3 = gtk.TreeViewColumn("Type") |
1388 | + column3.pack_start(cell_renderer3, True) |
1389 | + column3.set_attributes(cell_renderer3, text = 2) |
1390 | + |
1391 | + column4 = gtk.TreeViewColumn("Message") |
1392 | + column4.pack_end(cell_renderer4, True) |
1393 | + column4.set_attributes(cell_renderer4, text = 3) |
1394 | + |
1395 | + treeview.append_column(column1) |
1396 | + treeview.append_column(column2) |
1397 | + treeview.append_column(column3) |
1398 | + treeview.append_column(column4) |
1399 | + treeview.set_headers_visible(True) |
1400 | + |
1401 | + # Set model to view and read data from logfile |
1402 | + self.log_store = gtk.ListStore(str, str, str, str) |
1403 | + treeview.set_model(self.log_store) |
1404 | + self.update_log_rows() |
1405 | + |
1406 | + # Show Log viewer dialog |
1407 | + self.dialog = self.widgets.get_widget("LogDialog") |
1408 | + self.dialog.resize(750, 500) |
1409 | + self.dialog.connect("destroy", self.on_close_log_button_clicked) |
1410 | + self.dialog.show() |
1411 | + |
1412 | + def update_log_rows(self, widget=None): |
1413 | + """Read logfile and udpate treeview""" |
1414 | + self.log_rows[:] = [] |
1415 | + |
1416 | + try: |
1417 | + for line in open(self.logfile_entertainer, 'r'): |
1418 | + try: |
1419 | + line_table = line.split() |
1420 | + message = ' '.join(line_table[3:]) |
1421 | + row = line_table[:3] + [message] |
1422 | + parsed_row = parse_row(row) |
1423 | + self.log_rows.append(parsed_row) |
1424 | + except IndexError: |
1425 | + print "Cannot parse log line: ", line |
1426 | + except IOError: |
1427 | + print "Cannot find logfile: ", self.logfile_entertainer |
1428 | + |
1429 | + # Reverse so that the latest message is at top |
1430 | + self.log_rows.reverse() |
1431 | + # Filter unwated message types |
1432 | + self.filter_messages() |
1433 | + |
1434 | + def filter_messages(self, widget = None): |
1435 | + """Checks which message types should be displayed on treeview""" |
1436 | + if self.log_store: |
1437 | + self.log_store.clear() |
1438 | + |
1439 | + debug = self.widgets.get_widget("checkbutton_debug").get_active() |
1440 | + critical = self.widgets.get_widget("checkbutton_critical").get_active() |
1441 | + error = self.widgets.get_widget("checkbutton_error").get_active() |
1442 | + warning = self.widgets.get_widget("checkbutton_warning").get_active() |
1443 | + info = self.widgets.get_widget("checkbutton_info").get_active() |
1444 | + |
1445 | + for element in self.log_rows: |
1446 | + if element[2] == "DEBUG" and debug: |
1447 | + self.log_store.append(element) |
1448 | + elif element[2] == "CRITICAL" and critical: |
1449 | + self.log_store.append(element) |
1450 | + elif element[2] == "ERROR" and error: |
1451 | + self.log_store.append(element) |
1452 | + elif element[2] == "WARNING" and warning: |
1453 | + self.log_store.append(element) |
1454 | + elif element[2] == "INFO" and info: |
1455 | + self.log_store.append(element) |
1456 | + |
1457 | + # Signal handlers |
1458 | + def on_close_log_button_clicked(self, widget): |
1459 | + """ |
1460 | + If running as a stand alone process, quit. |
1461 | + Otherwise only destroy dialog. |
1462 | + """ |
1463 | + self.dialog.hide() |
1464 | + self.dialog.destroy() |
1465 | + if(self.__STAND_ALONE): |
1466 | + gtk.main_quit() |
1467 | + |
1468 | + |
1469 | +def parse_row(row): |
1470 | + """ |
1471 | + This parses the input list into a list suitable for the logviewer |
1472 | + @author Joshua Scotton |
1473 | + @param row The input list [Date, Time, Class, Type + Description] |
1474 | + """ |
1475 | + if row[3][:5] == "DEBUG": |
1476 | + return [row[0], row[1], "DEBUG", |
1477 | + row[2] + ": " + row[3][5:]] |
1478 | + elif row[3][:8] == "CRITICAL": |
1479 | + return [row[0], row[1], "CRITICAL", |
1480 | + row[2] + ": " + row[3][8:]] |
1481 | + elif row[3][:5] == "ERROR": |
1482 | + return [row[0], row[1], "ERROR", |
1483 | + row[2] + ": " + row[3][5:]] |
1484 | + elif row[3][:7] == "WARNING": |
1485 | + return [row[0], row[1], "WARNING", |
1486 | + row[2] + ": " + row[3][7:]] |
1487 | + elif row[3][:4] == "INFO": |
1488 | + return [row[0], row[1], "INFO", |
1489 | + row[2] + ": " + row[3][4:]] |
1490 | + |
1491 | + |
1492 | +class OpenFeedSourceDialog: |
1493 | + '''Feed source reader dialog''' |
1494 | + |
1495 | + GLADE_DIR = os.path.join(os.path.dirname(__file__), "glade") |
1496 | + |
1497 | + widgets = None |
1498 | + dialog = None |
1499 | + tree_widget = None |
1500 | + feeds = None |
1501 | + url = None |
1502 | + |
1503 | + def __init__(self, the_widget, the_feeds): |
1504 | + """initialises the gtk window and displays it""" |
1505 | + |
1506 | + #feeds is a pointer to a list of feeds from the config file |
1507 | + self.feeds = the_feeds |
1508 | + |
1509 | + #needed so we can add feeds to the feed list widget |
1510 | + self.tree_widget = the_widget |
1511 | + |
1512 | + # Load glade UI |
1513 | + self.gladefile = os.path.join(self.GLADE_DIR, |
1514 | + "open_feed_source_dialog.glade") |
1515 | + self.widgets = gtk.glade.XML(self.gladefile) |
1516 | + |
1517 | + # Get content management dialog and bind signal callbacks |
1518 | + self.dialog = self.widgets.get_widget("open_source_dialog") |
1519 | + if (self.dialog): |
1520 | + callback_dic = { |
1521 | + "on_fileOpen_clicked" : self.on_fileOpen_clicked, |
1522 | + "on_lifereaButton_clicked" : self.on_lifereaButton_clicked, |
1523 | + "on_enterURL_clicked" : self.on_enterURL_clicked, |
1524 | + "on_closeButton_clicked" : self.on_closeButton_clicked, |
1525 | + "on_url_dialog_ok_button_clicked" : |
1526 | + self.on_url_dialog_ok_button_clicked, |
1527 | + "on_url_dialog_cancel_button_clicked" : |
1528 | + self.on_url_dialog_cancel_button_clicked, |
1529 | + "on_url_dialog_delete_event" : self.on_url_dialog_delete_event |
1530 | + } |
1531 | + |
1532 | + self.widgets.signal_autoconnect(callback_dic) |
1533 | + |
1534 | + # Initilize dialog widgets with correct values and show dialog |
1535 | + self.dialog.resize(300, 200) |
1536 | + self.dialog.run() |
1537 | + |
1538 | + def on_fileOpen_clicked(self, widget): |
1539 | + """Opens add file dialog and then adds all feeds in the opml file |
1540 | + selected """ |
1541 | + |
1542 | + #get the model for the feed list widget so we can add the new feeds |
1543 | + model = self.tree_widget.get_model() |
1544 | + |
1545 | + #create select file dialog |
1546 | + dialog = gtk.FileChooserDialog(_("Select OPML file"), None, |
1547 | + gtk.FILE_CHOOSER_ACTION_OPEN, |
1548 | + (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, |
1549 | + gtk.RESPONSE_OK)) |
1550 | + |
1551 | + #set dialog up to filter for only opml files |
1552 | + file_filter = gtk.FileFilter() |
1553 | + file_filter.set_name(_("OPML files")) |
1554 | + file_filter.add_pattern("*.opml") |
1555 | + dialog.add_filter(file_filter) |
1556 | + |
1557 | + #set dialog up to allow multiple selections |
1558 | + dialog.set_select_multiple(True) |
1559 | + |
1560 | + #run the dialog |
1561 | + status = dialog.run() |
1562 | + |
1563 | + # if file was selected, get list of feeds from it and add to |
1564 | + #model and update config file |
1565 | + if(status == gtk.RESPONSE_OK): |
1566 | + FeedConfigTools().add_file_feeds_to_widget( |
1567 | + dialog.get_filenames(), model, self.feeds) |
1568 | + dialog.destroy() |
1569 | + |
1570 | + def on_lifereaButton_clicked(self, widget): |
1571 | + """Adds any liferea feeds it finds to the feed widget and config file |
1572 | + """ |
1573 | + #get the model |
1574 | + model = self.tree_widget.get_model() |
1575 | + #get the liferea feeds and then send everything to the |
1576 | + #add_file_feeds_to_widget method |
1577 | + FeedConfigTools().add_file_feeds_to_widget( |
1578 | + [OPMLParser().get_liferea_opml()], model, self.feeds) |
1579 | + |
1580 | + def on_enterURL_clicked(self, widget): |
1581 | + """gets a opml file link from a user and adds any feeds it finds to the |
1582 | + feed widget and config file""" |
1583 | + url_dialog = self.widgets.get_widget("url_dialog") |
1584 | + model = self.tree_widget.get_model() |
1585 | + # Open dialog |
1586 | + url_dialog.set_title(_("Add OPML File")) |
1587 | + status = url_dialog.run() |
1588 | + # If folder was selected we add it to model and update config file |
1589 | + if(status == gtk.RESPONSE_OK): |
1590 | + FeedConfigTools().add_file_feeds_to_widget([self.url], |
1591 | + model, self.feeds) |
1592 | + |
1593 | + def on_closeButton_clicked(self, widget): |
1594 | + self.dialog.hide() |
1595 | + self.dialog.destroy() |
1596 | + |
1597 | + def on_url_dialog_ok_button_clicked(self, widget): |
1598 | + """URL dialog OK button pressed. Sets self.url""" |
1599 | + url_dialog = self.widgets.get_widget("url_dialog") |
1600 | + url_entry = self.widgets.get_widget("url_entry") |
1601 | + url_dialog.hide() |
1602 | + self.url = url_entry.get_text() |
1603 | + url_entry.set_text("") |
1604 | + url_dialog.response(gtk.RESPONSE_OK) |
1605 | + |
1606 | + def on_url_dialog_cancel_button_clicked(self, widget): |
1607 | + """URL dialog cancelled. Hides dialog""" |
1608 | + url_dialog = self.widgets.get_widget("url_dialog") |
1609 | + url_entry = self.widgets.get_widget("url_entry") |
1610 | + url_dialog.hide() |
1611 | + url_entry.set_text("") |
1612 | + url_dialog.response(gtk.RESPONSE_CANCEL) |
1613 | + |
1614 | + def on_url_dialog_delete_event(self, widget, data): |
1615 | + """Dialog's X clicked. Hides dialog""" |
1616 | + url_dialog = self.widgets.get_widget("url_dialog") |
1617 | + url_entry = self.widgets.get_widget("url_entry") |
1618 | + url_dialog.hide() |
1619 | + url_entry.set_text("") |
1620 | + url_dialog.response(gtk.RESPONSE_CANCEL) |
1621 | + return True |
1622 | + |
1623 | + |
1624 | +class PreferencesDialog: |
1625 | + """This is a preferences editing tool for Entertainer media center.""" |
1626 | + |
1627 | + # Glade file location |
1628 | + GLADE_DIR = os.path.join(os.path.dirname(__file__), "glade") |
1629 | + |
1630 | + def __init__(self, stand_alone): |
1631 | + """ |
1632 | + Initialize Preferenced dialog |
1633 | + @param stand_alone: Is this dialog stand alone process or part of |
1634 | + client |
1635 | + """ |
1636 | + # Is this dialog running as a stand alone process |
1637 | + self.STAND_ALONE = stand_alone |
1638 | + self.themes = [] |
1639 | + self.config = Configuration() |
1640 | + |
1641 | + # Load glade UI |
1642 | + self.gladefile = os.path.join(self.GLADE_DIR, |
1643 | + "entertainer-preferences.glade") |
1644 | + self.widgets = gtk.glade.XML(self.gladefile) |
1645 | + |
1646 | + # Get preferences dialog and bind signal callbacks |
1647 | + self.pref_dialog = self.widgets.get_widget("PreferencesDialog") |
1648 | + if (self.pref_dialog): |
1649 | + callback_dic = { |
1650 | + "on_close_button_clicked" : self.on_close_button_clicked, |
1651 | + "on_PreferencesDialog_delete_event" : self.on_dialog_closed, |
1652 | + "on_theme_list_cursor_changed" : |
1653 | + self.on_theme_list_cursor_changed, |
1654 | + "on_checkbutton_autostart_toggled" : |
1655 | + self.on_checkbutton_autostart_toggled, |
1656 | + "on_checkbutton_fullscreen_toggled" : |
1657 | + self.on_checkbutton_fullscreen_toggled, |
1658 | + "on_checkbutton_systray_icon_toggled" : |
1659 | + self.on_checkbutton_systray_icon_toggled, |
1660 | + "on_effect_checkbox_toggled" : self.on_effect_checkbox_toggled, |
1661 | + "on_effect_combobox_changed" : self.on_effect_combobox_changed, |
1662 | + "on_add_button_clicked" : self.on_add_button_clicked, |
1663 | + "on_remove_button_clicked" : self.on_remove_button_clicked, |
1664 | + "on_spinbutton_slideshow_step_value_changed": |
1665 | + self.on_spinbutton_slideshow_step_value_changed |
1666 | + } |
1667 | + self.widgets.signal_autoconnect(callback_dic) |
1668 | + |
1669 | + # Initilize dialog widgets with correct values and show dialog |
1670 | + self.init_dialog_values_from_configure_file() |
1671 | + #self.pref_dialog.resize(500,400) |
1672 | + self.pref_dialog.show() |
1673 | + |
1674 | + def load_themes(self): |
1675 | + """Load themes""" |
1676 | + themes = os.listdir(os.path.join(self.config.get_cfg_dir(), 'themes')) |
1677 | + for element in themes: |
1678 | + theme = os.path.join(self.config.get_cfg_dir(), 'themes', element) |
1679 | + if os.path.isdir(theme): |
1680 | + self.themes.append(element) |
1681 | + |
1682 | + def on_add_button_clicked(self, widget): |
1683 | + """Add theme button clicked""" |
1684 | + themelist = self.widgets.get_widget("theme_list") |
1685 | + model = themelist.get_model() |
1686 | + # Open "Select folder" dialog |
1687 | + dialog = gtk.FileChooserDialog(_("Select theme package file"), |
1688 | + None, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, |
1689 | + gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK), None) |
1690 | + file_filter = gtk.FileFilter() |
1691 | + file_filter.set_name(_("Theme package (tar.gz)")) |
1692 | + file_filter.add_pattern("*.tar.gz") |
1693 | + dialog.add_filter(file_filter) |
1694 | + status = dialog.run() |
1695 | + |
1696 | + # If theme was selected with file chooser |
1697 | + if(status == gtk.RESPONSE_OK): |
1698 | + package = dialog.get_filename() |
1699 | + tar = tarfile.open(package, 'r:gz') # Open tar.gz package |
1700 | + |
1701 | + # Make sure that package contains configuration file (is theme) |
1702 | + content = tar.getnames() |
1703 | + theme_name = None |
1704 | + is_theme = False |
1705 | + for element in content: |
1706 | + if element[-10:] == "theme.conf": |
1707 | + theme_name = element[:-11] |
1708 | + is_theme = True |
1709 | + |
1710 | + # Install them |
1711 | + if is_theme: |
1712 | + tar.extractall(os.path.join(self.config.get_cfg_dir(), |
1713 | + 'themes')) |
1714 | + model.insert(len(model), [theme_name]) |
1715 | + else: |
1716 | + error = gtk.MessageDialog(None, gtk.DIALOG_MODAL, |
1717 | + gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, _("Invalid theme file!")) |
1718 | + error.run() |
1719 | + error.destroy() |
1720 | + |
1721 | + dialog.destroy() |
1722 | + |
1723 | + def on_remove_button_clicked(self, widget): |
1724 | + """Remove theme button clicked""" |
1725 | + # Get currently selected theme |
1726 | + themelist = self.widgets.get_widget("theme_list") |
1727 | + model = themelist.get_model() |
1728 | + selection = themelist.get_selection().get_selected() |
1729 | + name = model.get_value(selection[1], 0) |
1730 | + |
1731 | + confirm = gtk.MessageDialog(None, |
1732 | + gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, |
1733 | + _("Are you sure you want to delete\ntheme: %(name)s") % \ |
1734 | + {'name': name}) |
1735 | + status = confirm.run() |
1736 | + confirm.destroy() |
1737 | + if(status == gtk.RESPONSE_YES): |
1738 | + themedir = os.path.join(self.config.get_cfg_dir(), 'themes', name) |
1739 | + shutil.rmtree(themedir) |
1740 | + model.remove(selection[1]) |
1741 | + themelist.set_cursor(0) |
1742 | + self.themes.remove(name) |
1743 | + |
1744 | + def on_theme_list_cursor_changed(self, widget): |
1745 | + """Executed when theme is changed in theme list. Update preview.""" |
1746 | + # Get currently selected theme |
1747 | + themelist = self.widgets.get_widget("theme_list") |
1748 | + model = themelist.get_model() |
1749 | + selection = themelist.get_selection().get_selected() |
1750 | + name = model.get_value(selection[1], 0) |
1751 | + themedir = os.path.join(self.config.get_cfg_dir(), 'themes', name) |
1752 | + theme = Theme(theme_path=themedir) |
1753 | + |
1754 | + # Update preview |
1755 | + image = self.widgets.get_widget("theme_image") |
1756 | + image.set_from_file(os.path.join(themedir, "thumbnail.png")) |
1757 | + name = self.widgets.get_widget("name_label") |
1758 | + name.set_text(theme.getName()) |
1759 | + author = self.widgets.get_widget("author_label") |
1760 | + author.set_text(theme.getAuthor()) |
1761 | + licence = self.widgets.get_widget("licence_label") |
1762 | + licence.set_text(theme.getLicence()) |
1763 | + copyright_label = self.widgets.get_widget("copyright_label") |
1764 | + copyright_label.set_text(theme.getCopyright()) |
1765 | + comment = self.widgets.get_widget("comment_label") |
1766 | + comment.set_text(theme.getComment()) |
1767 | + |
1768 | + self.config.write_preference_value("General", "theme", name.get_text()) |
1769 | + |
1770 | + def on_checkbutton_autostart_toggled(self, widget): |
1771 | + """Server Autostart checkbox toggled""" |
1772 | + self.config.write_preference_value("General", "start_server_auto", |
1773 | + widget.get_active()) |
1774 | + |
1775 | + def on_checkbutton_fullscreen_toggled(self, widget): |
1776 | + """Start in fullscreen checkbox toggled""" |
1777 | + self.config.write_preference_value("General", "start_in_fullscreen", |
1778 | + widget.get_active()) |
1779 | + |
1780 | + def on_checkbutton_systray_icon_toggled(self, widget): |
1781 | + """System Tray Icon checkbox toggled""" |
1782 | + self.config.write_preference_value("General", "display_icon", |
1783 | + widget.get_active()) |
1784 | + |
1785 | + def on_effect_checkbox_toggled(self, widget): |
1786 | + """Effect checkbox toggled""" |
1787 | + combobox = self.widgets.get_widget("effect_combobox") |
1788 | + combobox.set_sensitive(widget.get_active()) |
1789 | + self.config.write_preference_value("General", "show_effects", |
1790 | + widget.get_active()) |
1791 | + |
1792 | + def on_effect_combobox_changed(self, widget): |
1793 | + """User changed effect for screen transitions""" |
1794 | + text = widget.get_active_text() |
1795 | + if text == _("No effect"): |
1796 | + english_text = "No effect" |
1797 | + if text == _("Crossfade"): |
1798 | + english_text = "Crossfade" |
1799 | + if text == _("Zoom and fade"): |
1800 | + english_text = "Zoom and fade" |
1801 | + if text == _("Slide"): |
1802 | + english_text = "Slide" |
1803 | + self.config.write_preference_value("General", "transition_effect", |
1804 | + english_text) |
1805 | + |
1806 | + def on_spinbutton_slideshow_step_value_changed(self, widget): |
1807 | + """Activation of slideshow effects""" |
1808 | + self.config.write_preference_value("Photographs", "slideshow_step", |
1809 | + int(widget.get_value())) |
1810 | + |
1811 | + def on_dialog_closed(self, widget, after): |
1812 | + """Callback function for dialog's close button""" |
1813 | + self.close() |
1814 | + |
1815 | + def on_close_button_clicked(self, widget): |
1816 | + """Callback function for dialog's close button""" |
1817 | + self.close() |
1818 | + |
1819 | + def close(self): |
1820 | + """Close Dialog""" |
1821 | + try: |
1822 | + proxy = MessageBusProxy(client_name = "Preferences GUI") |
1823 | + proxy.connectToMessageBus() |
1824 | + proxy.sendMessage(Message(MessageType.PREFERENCES_CONF_UPDATED)) |
1825 | + proxy.disconnectFromMessageBus() |
1826 | + except socket.error: |
1827 | + error = gtk.MessageDialog( |
1828 | + None, gtk.DIALOG_MODAL, |
1829 | + gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, _( |
1830 | + "Entertainer backend is not running. " |
1831 | + "Config updates will happen on backend restart." |
1832 | + )) |
1833 | + error.run() |
1834 | + error.destroy() |
1835 | + |
1836 | + |
1837 | + if(self.STAND_ALONE): |
1838 | + self.pref_dialog.hide() |
1839 | + self.pref_dialog.destroy() |
1840 | + gtk.main_quit() |
1841 | + else: |
1842 | + self.pref_dialog.hide() |
1843 | + self.pref_dialog.destroy() |
1844 | + |
1845 | + def init_dialog_values_from_configure_file(self): |
1846 | + """Read configure file and set dialog widget values with read values. |
1847 | + """ |
1848 | + self.load_themes() |
1849 | + current_theme = self.config.get_theme_name() |
1850 | + |
1851 | + themelist_widget = self.widgets.get_widget("theme_list") |
1852 | + model = gtk.ListStore(str) |
1853 | + |
1854 | + cell_renderer = gtk.CellRendererText() |
1855 | + column = gtk.TreeViewColumn("Themes", cell_renderer, text=0) |
1856 | + themelist_widget.append_column(column) |
1857 | + |
1858 | + # Fill model with installed themes |
1859 | + for i in range(len(self.themes)): |
1860 | + model.insert(i, [self.themes[i]]) |
1861 | + |
1862 | + themelist_widget.set_model(model) |
1863 | + |
1864 | + # Set current theme selected in theme list |
1865 | + index = model.get_iter_first() |
1866 | + unselected = True |
1867 | + index_counter = 0 |
1868 | + while(unselected): |
1869 | + name = model.get_value(index, 0) |
1870 | + if name == current_theme: |
1871 | + unselected = False |
1872 | + themelist_widget.set_cursor(index_counter) |
1873 | + index = model.iter_next(index) |
1874 | + index_counter += 1 |
1875 | + |
1876 | + # Checkboxes |
1877 | + checkbutton_systray_icon = self.widgets.get_widget( |
1878 | + "checkbutton_systray_icon") |
1879 | + if self.config.tray_icon_enabled(): |
1880 | + checkbutton_systray_icon.set_active(True) |
1881 | + else: |
1882 | + checkbutton_systray_icon.set_active(False) |
1883 | + |
1884 | + checkbutton_autostart = self.widgets.get_widget("checkbutton_autostart") |
1885 | + if self.config.start_auto_server(): |
1886 | + checkbutton_autostart.set_active(True) |
1887 | + else: |
1888 | + checkbutton_autostart.set_active(False) |
1889 | + |
1890 | + checkbutton_fullscreen = self.widgets.get_widget( |
1891 | + "checkbutton_fullscreen") |
1892 | + if self.config.start_in_fullscreen(): |
1893 | + checkbutton_fullscreen.set_active(True) |
1894 | + else: |
1895 | + checkbutton_fullscreen.set_active(False) |
1896 | + |
1897 | + effect_checkbox = self.widgets.get_widget("effect_checkbox") |
1898 | + effect_combobox = self.widgets.get_widget("effect_combobox") |
1899 | + if self.config.show_effects(): |
1900 | + effect_checkbox.set_active(True) |
1901 | + effect_combobox.set_sensitive(True) |
1902 | + else: |
1903 | + effect_checkbox.set_active(False) |
1904 | + effect_combobox.set_sensitive(False) |
1905 | + |
1906 | + spinbutton_slideshow_step = self.widgets.get_widget( |
1907 | + "spinbutton_slideshow_step") |
1908 | + spinbutton_slideshow_step.set_value(self.config.get_slideshow_step()) |
1909 | + |
1910 | + # Set Effect Combobox value (Text values are set in glade file) |
1911 | + effect = self.config.transition_effect() |
1912 | + if effect == "No effect": |
1913 | + effect_combobox.set_active(0) |
1914 | + if effect == "Crossfade": |
1915 | + effect_combobox.set_active(1) |
1916 | + if effect == "Zoom and fade": |
1917 | + effect_combobox.set_active(2) |
1918 | + if effect == "Slide": |
1919 | + effect_combobox.set_active(3) |
1920 | + |
1921 | |
1922 | === added file 'entertainerlib/download.py' |
1923 | --- entertainerlib/download.py 1970-01-01 00:00:00 +0000 |
1924 | +++ entertainerlib/download.py 2009-05-06 04:46:51 +0000 |
1925 | @@ -0,0 +1,453 @@ |
1926 | +'''Downloader classes.''' |
1927 | + |
1928 | +__licence__ = "GPLv2" |
1929 | +__copyright__ = "2009 Entertainer Developers" |
1930 | + |
1931 | +import locale |
1932 | +import os |
1933 | +import re |
1934 | +import socket |
1935 | +import threading |
1936 | +import urllib |
1937 | +from xml.dom import minidom |
1938 | + |
1939 | +import gobject |
1940 | + |
1941 | +# Amazon licence for Entertainer |
1942 | +LICENSE_KEY = "1YCWYZ0SPPAJ27YZZ482" |
1943 | +DEFAULT_LOCALE = "en_US" |
1944 | +ASSOCIATE = "webservices-20" |
1945 | + |
1946 | +# We are not allowed to batch more than 2 requests at once |
1947 | +# http://docs.amazonwebservices.com/AWSEcommerceService/4-0/ |
1948 | +# PgCombiningOperations.html |
1949 | +MAX_BATCH_JOBS = 2 |
1950 | + |
1951 | + |
1952 | +class AlbumArtDownloader(threading.Thread): |
1953 | + """ |
1954 | + Search and download album art from the internet. |
1955 | + |
1956 | + This class is heavily based on Rhythmbox - AlbumArt plugin's class |
1957 | + 'AmazonCoverArtSearch'. That plugin is released under GPLv2 (or higher) |
1958 | + and it's copyrights belong to Gareth Murphy and Martin Szulecki. |
1959 | + |
1960 | + See more: http://www.gnome.org/projects/rhythmbox/ |
1961 | + |
1962 | + If you want better cover search, please contribute to Rhyhtmbox project. |
1963 | + """ |
1964 | + |
1965 | + def __init__(self, album, artist, art_file_path, callback = None): |
1966 | + """ |
1967 | + Initialize album art downloader |
1968 | + @param album: Album title |
1969 | + @param artist: Artist name |
1970 | + @param art_file_path: Path where albumart is saved |
1971 | + @param callback: Callback function that is called after search if set |
1972 | + """ |
1973 | + threading.Thread.__init__(self) |
1974 | + self.setName("AlbumArt Downloader") |
1975 | + self.callback_function = callback # Callback function |
1976 | + self.album = album # Album title |
1977 | + self.artist = artist # Artist name |
1978 | + # Album art files are in this directory |
1979 | + self.path = art_file_path |
1980 | + (self.tld, self.encoding) = self.__get_locale () |
1981 | + |
1982 | + def run(self): |
1983 | + """Start searching and downloading albumart.""" |
1984 | + self.search() |
1985 | + |
1986 | + def __get_locale (self): |
1987 | + '''Get locale information from user\'s machine''' |
1988 | + # "JP is the only locale that correctly takes UTF8 input. |
1989 | + # All other locales use LATIN1." |
1990 | + # http://developer.amazonwebservices.com/connect/ |
1991 | + # entry.jspa?externalID=1295&categoryID=117 |
1992 | + supported_locales = { |
1993 | + "en_US" : ("com", "latin1"), |
1994 | + "en_GB" : ("co.uk", "latin1"), |
1995 | + "de" : ("de", "latin1"), |
1996 | + "ja" : ("jp", "utf8") |
1997 | + } |
1998 | + |
1999 | + lc_id = DEFAULT_LOCALE |
2000 | + default = locale.getdefaultlocale ()[0] |
2001 | + if default: |
2002 | + if supported_locales.has_key (default): |
2003 | + lc_id = default |
2004 | + else: |
2005 | + lang = default.split("_")[0] |
2006 | + if supported_locales.has_key (lang): |
2007 | + lc_id = lang |
2008 | + |
2009 | + return supported_locales[lc_id] |
2010 | + |
2011 | + def __valid_match (self, item): |
2012 | + '''Determine if item matches tag criteria''' |
2013 | + return (hasattr (item, "LargeImage") or hasattr (item, "MediumImage")) \ |
2014 | + and hasattr (item, "ItemAttributes") |
2015 | + |
2016 | + def __tidy_up_string (self, str_input): |
2017 | + """ |
2018 | + Tidy up string. Remove spaces, convert to lowercase and replace chars. |
2019 | + """ |
2020 | + # Lowercase |
2021 | + str_input = str_input.lower () |
2022 | + # Strip |
2023 | + str_input = str_input.strip () |
2024 | + |
2025 | + # TODO: Convert accented to unaccented |
2026 | + str_input = str_input.replace (" - ", " ") |
2027 | + str_input = str_input.replace (": ", " ") |
2028 | + str_input = str_input.replace (" & ", " and ") |
2029 | + |
2030 | + return str_input |
2031 | + |
2032 | + def search(self): |
2033 | + """Search album art from Amazon""" |
2034 | + self.searching = True |
2035 | + self.cancel = False |
2036 | + self.keywords = [] |
2037 | + |
2038 | + st_artist = self.artist or u'Unknown' |
2039 | + st_album = self.album or u'Unknown' |
2040 | + |
2041 | + if st_artist == st_album == u'Unknown': |
2042 | + self.on_search_completed (None) |
2043 | + return |
2044 | + |
2045 | + # Tidy up |
2046 | + |
2047 | + # Replace quote characters |
2048 | + # don't replace single quote: could be important punctuation |
2049 | + for char in ["\""]: |
2050 | + st_artist = st_artist.replace (char, '') |
2051 | + st_album = st_album.replace (char, '') |
2052 | + |
2053 | + |
2054 | + self.st_album = st_album |
2055 | + self.st_artist = st_artist |
2056 | + |
2057 | + # Remove variants of Disc/CD [1-9] from album title before search |
2058 | + for exp in ["\([Dd]isc *[1-9]+\)", "\([Cc][Dd] *[1-9]+\)"]: |
2059 | + p = re.compile (exp) |
2060 | + st_album = p.sub ('', st_album) |
2061 | + |
2062 | + st_album_no_vol = st_album |
2063 | + for exp in ["\(*[Vv]ol.*[1-9]+\)*"]: |
2064 | + p = re.compile (exp) |
2065 | + st_album_no_vol = p.sub ('', st_album_no_vol) |
2066 | + |
2067 | + self.st_album_no_vol = st_album_no_vol |
2068 | + |
2069 | + # Save current search's entry properties |
2070 | + self.search_album = st_album |
2071 | + self.search_artist = st_artist |
2072 | + self.search_album_no_vol = st_album_no_vol |
2073 | + |
2074 | + # TODO: Improve to decrease wrong cover downloads, maybe add severity? |
2075 | + # Assemble list of search keywords (and thus search queries) |
2076 | + if st_album == u'Unknown': |
2077 | + self.keywords.append ("%s Best of" % (st_artist)) |
2078 | + self.keywords.append ("%s Greatest Hits" % (st_artist)) |
2079 | + self.keywords.append ("%s Essential" % (st_artist)) |
2080 | + self.keywords.append ("%s Collection" % (st_artist)) |
2081 | + self.keywords.append ("%s" % (st_artist)) |
2082 | + elif st_artist == u'Unknown': |
2083 | + self.keywords.append ("%s" % (st_album)) |
2084 | + if st_album_no_vol != st_artist: |
2085 | + self.keywords.append ("%s" % (st_album_no_vol)) |
2086 | + self.keywords.append ("Various %s" % (st_album)) |
2087 | + else: |
2088 | + if st_album != st_artist: |
2089 | + self.keywords.append ("%s %s" % (st_artist, st_album)) |
2090 | + if st_album_no_vol != st_album: |
2091 | + self.keywords.append ("%s %s" % |
2092 | + (st_artist, st_album_no_vol)) |
2093 | + self.keywords.append ("Various %s" % (st_album)) |
2094 | + self.keywords.append ("%s" % (st_artist)) |
2095 | + |
2096 | + # Initiate asynchronous search |
2097 | + self.search_next () |
2098 | + |
2099 | + def search_next(self): |
2100 | + """Search again, because the last one didn't find any covers.""" |
2101 | + if len (self.keywords) == 0: |
2102 | + # No keywords left to search -> no results |
2103 | + self.on_search_completed (None) |
2104 | + return False |
2105 | + |
2106 | + self.searching = True |
2107 | + |
2108 | + url = "http://ecs.amazonaws." + self.tld + "/onca/xml" \ |
2109 | + "?Service=AWSECommerceService" \ |
2110 | + "&AWSAccessKeyId=" + LICENSE_KEY + \ |
2111 | + "&AssociateTag=" + ASSOCIATE + \ |
2112 | + "&ResponseGroup=Images,ItemAttributes" \ |
2113 | + "&Operation=ItemSearch" \ |
2114 | + "&ItemSearch.Shared.SearchIndex=Music" |
2115 | + |
2116 | + job = 1 |
2117 | + while job <= MAX_BATCH_JOBS and len (self.keywords) > 0: |
2118 | + keyword = self.keywords.pop (0) |
2119 | + keyword = keyword.encode (self.encoding, "ignore") |
2120 | + keyword = keyword.strip () |
2121 | + keyword = urllib.quote (keyword) |
2122 | + url += "&ItemSearch.%d.Keywords=%s" % (job, keyword) |
2123 | + job += 1 |
2124 | + |
2125 | + # Retrieve search for keyword |
2126 | + temp = urllib.urlopen(url) |
2127 | + search_results = temp.read() |
2128 | + self.on_search_response(search_results) |
2129 | + return True |
2130 | + |
2131 | + def __unmarshal(self, element): |
2132 | + rc = object() |
2133 | + child_elements = [e for e in element.childNodes if isinstance (e, |
2134 | + minidom.Element)] |
2135 | + if child_elements: |
2136 | + for child in child_elements: |
2137 | + key = child.tagName |
2138 | + if hasattr (rc, key): |
2139 | + if not isinstance (getattr (rc, key), list): |
2140 | + setattr (rc, key, [getattr (rc, key)]) |
2141 | + getattr (rc, key).append (self.__unmarshal (child)) |
2142 | + # get_best_match_urls() wants a list, even if there is only |
2143 | + # one item/artist |
2144 | + elif child.tagName in ("Items", "Item", "Artist"): |
2145 | + setattr (rc, key, [self.__unmarshal(child)]) |
2146 | + else: |
2147 | + setattr (rc, key, self.__unmarshal(child)) |
2148 | + else: |
2149 | + rc = "".join ([e.data for e in element.childNodes if isinstance (e, |
2150 | + minidom.Text)]) |
2151 | + return rc |
2152 | + |
2153 | + def on_search_response (self, result_data): |
2154 | + '''Check search results |
2155 | + |
2156 | + If results are not good, we search again with the next keyword. |
2157 | + ''' |
2158 | + if result_data is None: |
2159 | + self.search_next() |
2160 | + return |
2161 | + |
2162 | + try: |
2163 | + xmldoc = minidom.parseString(result_data) |
2164 | + except (TypeError, AttributeError): |
2165 | + self.search_next() |
2166 | + return |
2167 | + |
2168 | + data = self.__unmarshal (xmldoc) |
2169 | + if not hasattr (data, "ItemSearchResponse") or \ |
2170 | + not hasattr (data.ItemSearchResponse, "Items"): |
2171 | + # Something went wrong ... |
2172 | + self.search_next () |
2173 | + else: |
2174 | + # We got some search results |
2175 | + self.on_search_results (data.ItemSearchResponse.Items) |
2176 | + |
2177 | + def on_search_results (self, results): |
2178 | + '''Results were found, now we need to take action.''' |
2179 | + self.on_search_completed (results) |
2180 | + |
2181 | + def on_search_completed (self, result): |
2182 | + """ |
2183 | + Search completed and results found. |
2184 | + |
2185 | + Download large album art image from the first result and save it to |
2186 | + the disk. This function diverges greatly from the rhythmbox |
2187 | + implementation in order to avoid their loader and CoverArtDatabase |
2188 | + """ |
2189 | + self.searching = False |
2190 | + image_urls = self.get_best_match_urls(result) |
2191 | + if len(image_urls) == 0: |
2192 | + return |
2193 | + image_url = image_urls[0] |
2194 | + image_file = urllib.urlopen(image_url) |
2195 | + # base64 encode artist and album so there can be a '/' in the artist |
2196 | + # or album |
2197 | + artist_album = self.artist + " - " + self.album |
2198 | + artist_album = artist_album.encode("base64") |
2199 | + |
2200 | + dest = open(os.path.join(self.path, artist_album + ".jpg"),'w') |
2201 | + dest.write(image_file.read()) |
2202 | + dest.close() |
2203 | + |
2204 | + if self.callback_function is not None: |
2205 | + self.callback_function(self.artist, self.album) |
2206 | + |
2207 | + def get_best_match_urls (self, search_results): |
2208 | + """Return tuple of URL's to large and medium cover of the best match""" |
2209 | + # Default to "no match", our results must match our criteria |
2210 | + |
2211 | + # This code comes from Rhythmbox so we can't control the use of 'filter' |
2212 | + # pylint: disable-msg=W0141 |
2213 | + |
2214 | + if not search_results: |
2215 | + return [] |
2216 | + |
2217 | + best_match = None |
2218 | + |
2219 | + for result in search_results: |
2220 | + if not hasattr (result, "Item"): |
2221 | + # Search was unsuccessful, try next batch job |
2222 | + continue |
2223 | + |
2224 | + items = filter(self.__valid_match, result.Item) |
2225 | + if self.search_album != u'Unknown': |
2226 | + album_check = self.__tidy_up_string (self.search_album) |
2227 | + for item in items: |
2228 | + if not hasattr (item.ItemAttributes, "Title"): |
2229 | + continue |
2230 | + |
2231 | + album = self.__tidy_up_string (item.ItemAttributes.Title) |
2232 | + if album == album_check: |
2233 | + # Found exact album, can not get better than that |
2234 | + best_match = item |
2235 | + break |
2236 | + # If we already found a best_match, just keep checking for |
2237 | + # exact one. Check the results for both an album name that |
2238 | + # contains the name we're searching for, and an album name |
2239 | + # that's a substring of the name we're searching for |
2240 | + elif (best_match is None) and \ |
2241 | + (album.find (album_check) != -1 or |
2242 | + album_check.find (album) != -1): |
2243 | + best_match = item |
2244 | + |
2245 | + # If we still have no definite hit, use first result where artist |
2246 | + # matches |
2247 | + if (self.search_album == u'Unknown' and \ |
2248 | + self.search_artist != u'Unknown'): |
2249 | + artist_check = self.__tidy_up_string (self.search_artist) |
2250 | + if best_match is None: |
2251 | + # Check if artist appears in the Artists list |
2252 | + hit = False |
2253 | + for item in items: |
2254 | + if not hasattr (item.ItemAttributes, "Artist"): |
2255 | + continue |
2256 | + |
2257 | + for artist in item.ItemAttributes.Artist: |
2258 | + artist = self.__tidy_up_string (artist) |
2259 | + if artist.find (artist_check) != -1: |
2260 | + best_match = item |
2261 | + hit = True |
2262 | + break |
2263 | + if hit: |
2264 | + break |
2265 | + |
2266 | + urls = [getattr (best_match, size).URL for size in ("LargeImage", |
2267 | + "MediumImage") |
2268 | + if hasattr (best_match, size)] |
2269 | + if urls: |
2270 | + return urls |
2271 | + |
2272 | + # No search was successful |
2273 | + return [] |
2274 | + |
2275 | + |
2276 | +class LyricsDownloader(object): |
2277 | + """ |
2278 | + Search and download song lyrics from the internet. |
2279 | + Update music cache if lyrics found. |
2280 | + """ |
2281 | + |
2282 | + # The permanent user ID from Lyricsfly |
2283 | + # NOTICE: This is the personal user ID for Entertainer, if you want to |
2284 | + # experiment with the API from lyricsfly you can get an ID here => |
2285 | + # http://lyricsfly.com/api/, don't use this one as abuse of our key may |
2286 | + # invalidate it. |
2287 | + _LYRICSFLY_KEY = 'YzIxOTM4M2NkNGQ4MmRmODEtZW50ZXJ0YWluZXItcHJvamVjdC5jb20=' |
2288 | + |
2289 | + def __init__(self, title, artist, callback): |
2290 | + """ |
2291 | + Initialize lyrics downloader. |
2292 | + @param title: Title of the track |
2293 | + @param artist: Artist of the track |
2294 | + @param callback: Callback function which is called when search is over. |
2295 | + lyrics are given as a parameter to this callback function. |
2296 | + """ |
2297 | + self.title = title.lower() |
2298 | + self.artist = artist.lower() |
2299 | + self.callback = callback |
2300 | + |
2301 | + def search(self): |
2302 | + """ |
2303 | + Search lyrics and download if found. Search is done asynchronously. |
2304 | + This method returns immediately and set callback is called when search |
2305 | + is over. |
2306 | + """ |
2307 | + gobject.timeout_add(2000, self._async_search) |
2308 | + |
2309 | + def _async_search(self): |
2310 | + """ |
2311 | + Search lyrics and download if found |
2312 | + """ |
2313 | + lyrics = "" |
2314 | + self._clean_up_artist_title() |
2315 | + lyrics_xml = self._get_lyrics_xml() |
2316 | + lyrics = self._parse_lyrics_xml(lyrics_xml) |
2317 | + self.callback(lyrics) |
2318 | + |
2319 | + def _clean_up_artist_title(self): |
2320 | + """ |
2321 | + Clean up the artist and title. |
2322 | + """ |
2323 | + # Clean spaces |
2324 | + self.title = self.title.strip() |
2325 | + self.artist = self.artist.strip() |
2326 | + |
2327 | + # Convert title and artist to use in url, special symbols have to be |
2328 | + # replaced by a '%' not '%xx' |
2329 | + # TODO: Find out what the special symbols are (', &, ...) |
2330 | + # not letters, digits, spaces and ()$^*=:;|#@}{][!,.-_\ |
2331 | + self.artist = urllib.quote(self.artist.encode('utf-8'), |
2332 | + "'&()$^*=:;|#@}{][!,\\") |
2333 | + self.title = urllib.quote(self.title.encode('utf-8'), |
2334 | + "'&()$^*=:;|#@}{][!,\\") |
2335 | + |
2336 | + self.artist = self.artist.replace("'", "%").replace("&", "%") |
2337 | + self.title = self.title.replace("'", "%").replace("&", "%") |
2338 | + |
2339 | + def _get_lyrics_xml(self): |
2340 | + """ |
2341 | + Download the lyrics XML-file. |
2342 | + """ |
2343 | + lyrics_xml = None |
2344 | + |
2345 | + # timeout in seconds |
2346 | + timeout = 5 |
2347 | + socket.setdefaulttimeout(timeout) |
2348 | + |
2349 | + url = "http://lyricsfly.com/api/api.php?i=%s&a=%s&t=%s" \ |
2350 | + % (self._LYRICSFLY_KEY.decode('base64'), self.artist, self.title) |
2351 | + temp = urllib.urlopen(url) |
2352 | + lyrics_xml = temp.read() |
2353 | + |
2354 | + return lyrics_xml |
2355 | + |
2356 | + def _parse_lyrics_xml(self, lyrics_xml): |
2357 | + """Parse lyrics XML and return lyrics string""" |
2358 | + xmldoc = minidom.parseString(lyrics_xml).documentElement |
2359 | + |
2360 | + # Get the lyric from the XML file |
2361 | + try: |
2362 | + lyrics = xmldoc.getElementsByTagName('tx')[0].firstChild.nodeValue |
2363 | + except IndexError: |
2364 | + return '' |
2365 | + |
2366 | + # Clean spaces and enters |
2367 | + lyrics = lyrics.strip().replace('\n', '') |
2368 | + lyrics = lyrics.replace('[br]', '\n') |
2369 | + |
2370 | + # Add the artist and title to the top of the lyric |
2371 | + lyrics = xmldoc.getElementsByTagName('ar')[0].firstChild.nodeValue + \ |
2372 | + ' - ' + xmldoc.getElementsByTagName('tt')[0].firstChild.nodeValue + \ |
2373 | + '\n\n' + lyrics |
2374 | + |
2375 | + xmldoc.unlink() |
2376 | + |
2377 | + return lyrics |
2378 | + |
2379 | |
2380 | === renamed directory 'entertainerlib/utils/glade' => 'entertainerlib/glade' |
2381 | === modified file 'entertainerlib/glade/system_tray_icon_menu.glade' |
2382 | --- entertainerlib/utils/glade/system_tray_icon_menu.glade 2008-08-16 04:28:47 +0000 |
2383 | +++ entertainerlib/glade/system_tray_icon_menu.glade 2009-04-30 01:11:22 +0000 |
2384 | @@ -6,12 +6,12 @@ |
2385 | <property name="visible">True</property> |
2386 | <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> |
2387 | <child> |
2388 | - <widget class="GtkImageMenuItem" id="menuitem_frontend"> |
2389 | + <widget class="GtkImageMenuItem" id="menuitem_client"> |
2390 | <property name="visible">True</property> |
2391 | <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> |
2392 | <property name="label" translatable="yes">Open media center GUI</property> |
2393 | <property name="use_underline">True</property> |
2394 | - <signal name="activate" handler="on_menuitem_frontend_activate"/> |
2395 | + <signal name="activate" handler="on_menuitem_client_activate"/> |
2396 | <child internal-child="image"> |
2397 | <widget class="GtkImage" id="menu-item-image3"> |
2398 | <property name="visible">True</property> |
2399 | |
2400 | === renamed directory 'entertainerlib/frontend/gui' => 'entertainerlib/gui' |
2401 | === modified file 'entertainerlib/gui/screens/album.py' |
2402 | --- entertainerlib/frontend/gui/screens/album.py 2009-04-27 03:32:30 +0000 |
2403 | +++ entertainerlib/gui/screens/album.py 2009-05-05 03:31:34 +0000 |
2404 | @@ -8,13 +8,13 @@ |
2405 | import clutter |
2406 | import pango |
2407 | |
2408 | -from entertainerlib.frontend.gui.screens.screen import Screen |
2409 | -from entertainerlib.frontend.gui.widgets.eyecandy_texture import ( |
2410 | +from entertainerlib.gui.screens.screen import Screen |
2411 | +from entertainerlib.gui.widgets.eyecandy_texture import ( |
2412 | EyeCandyTexture) |
2413 | -from entertainerlib.frontend.gui.widgets.label import Label |
2414 | -from entertainerlib.frontend.gui.widgets.list_indicator import ListIndicator |
2415 | -from entertainerlib.frontend.gui.widgets.text_menu import TextMenu |
2416 | -from entertainerlib.frontend.gui.widgets.text_menu_item import TextMenuItem |
2417 | +from entertainerlib.gui.widgets.label import Label |
2418 | +from entertainerlib.gui.widgets.list_indicator import ListIndicator |
2419 | +from entertainerlib.gui.widgets.text_menu import TextMenu |
2420 | +from entertainerlib.gui.widgets.text_menu_item import TextMenuItem |
2421 | |
2422 | class Album(Screen): |
2423 | '''Screen that allows user to browse and play tracks of the music album.''' |
2424 | |
2425 | === modified file 'entertainerlib/gui/screens/artist.py' |
2426 | --- entertainerlib/frontend/gui/screens/artist.py 2009-04-27 03:32:30 +0000 |
2427 | +++ entertainerlib/gui/screens/artist.py 2009-05-05 03:31:34 +0000 |
2428 | @@ -6,11 +6,11 @@ |
2429 | |
2430 | import pango |
2431 | |
2432 | -from entertainerlib.frontend.gui.screens.screen import Screen |
2433 | -from entertainerlib.frontend.gui.tabs.albums_tab import AlbumsTab |
2434 | -from entertainerlib.frontend.gui.tabs.tracks_tab import TracksTab |
2435 | -from entertainerlib.frontend.gui.widgets.label import Label |
2436 | -from entertainerlib.frontend.medialibrary.playlist import Playlist |
2437 | +from entertainerlib.gui.screens.screen import Screen |
2438 | +from entertainerlib.gui.tabs.albums_tab import AlbumsTab |
2439 | +from entertainerlib.gui.tabs.tracks_tab import TracksTab |
2440 | +from entertainerlib.gui.widgets.label import Label |
2441 | +from entertainerlib.client.medialibrary.playlist import Playlist |
2442 | |
2443 | class Artist(Screen): |
2444 | '''Screen that allows user to browse music by artist.''' |
2445 | |
2446 | === modified file 'entertainerlib/gui/screens/audio_play.py' |
2447 | --- entertainerlib/frontend/gui/screens/audio_play.py 2009-04-27 03:32:30 +0000 |
2448 | +++ entertainerlib/gui/screens/audio_play.py 2009-05-05 03:31:34 +0000 |
2449 | @@ -9,10 +9,10 @@ |
2450 | import gobject |
2451 | import clutter |
2452 | |
2453 | -from entertainerlib.frontend.gui.screens.screen import Screen |
2454 | -from entertainerlib.frontend.gui.tabs.lyrics_tab import LyricsTab |
2455 | -from entertainerlib.frontend.gui.tabs.playing_tab import PlayingTab |
2456 | -from entertainerlib.frontend.gui.widgets.eyecandy_texture import ( |
2457 | +from entertainerlib.gui.screens.screen import Screen |
2458 | +from entertainerlib.gui.tabs.lyrics_tab import LyricsTab |
2459 | +from entertainerlib.gui.tabs.playing_tab import PlayingTab |
2460 | +from entertainerlib.gui.widgets.eyecandy_texture import ( |
2461 | EyeCandyTexture) |
2462 | |
2463 | class AudioPlay(Screen): |
2464 | |
2465 | === modified file 'entertainerlib/gui/screens/disc.py' |
2466 | --- entertainerlib/frontend/gui/screens/disc.py 2009-04-27 03:32:30 +0000 |
2467 | +++ entertainerlib/gui/screens/disc.py 2009-05-06 04:46:51 +0000 |
2468 | @@ -12,18 +12,18 @@ |
2469 | import pango |
2470 | import clutter |
2471 | |
2472 | -from entertainerlib.frontend.gui.screens.screen import Screen |
2473 | -from entertainerlib.frontend.gui.widgets.eyecandy_texture import ( |
2474 | +from entertainerlib.gui.screens.screen import Screen |
2475 | +from entertainerlib.gui.widgets.eyecandy_texture import ( |
2476 | EyeCandyTexture) |
2477 | -from entertainerlib.frontend.gui.widgets.label import Label |
2478 | -from entertainerlib.frontend.gui.widgets.list_indicator import ListIndicator |
2479 | -from entertainerlib.frontend.gui.widgets.loading_animation import ( |
2480 | +from entertainerlib.gui.widgets.label import Label |
2481 | +from entertainerlib.gui.widgets.list_indicator import ListIndicator |
2482 | +from entertainerlib.gui.widgets.loading_animation import ( |
2483 | LoadingAnimation) |
2484 | -from entertainerlib.frontend.gui.widgets.texture import Texture |
2485 | -from entertainerlib.frontend.gui.widgets.text_menu import TextMenu |
2486 | -from entertainerlib.frontend.gui.widgets.text_menu_item import TextMenuItem |
2487 | -from entertainerlib.frontend.medialibrary.playlist import Playlist |
2488 | -from entertainerlib.utils.albumart_downloader import AlbumArtDownloader |
2489 | +from entertainerlib.gui.widgets.texture import Texture |
2490 | +from entertainerlib.gui.widgets.text_menu import TextMenu |
2491 | +from entertainerlib.gui.widgets.text_menu_item import TextMenuItem |
2492 | +from entertainerlib.client.medialibrary.playlist import Playlist |
2493 | +from entertainerlib.download import AlbumArtDownloader |
2494 | |
2495 | class Disc(Screen): |
2496 | '''Screen allows user to play tracks from the current Audio CD.''' |
2497 | |
2498 | === modified file 'entertainerlib/gui/screens/factory.py' |
2499 | --- entertainerlib/frontend/gui/screens/factory.py 2009-02-07 17:12:21 +0000 |
2500 | +++ entertainerlib/gui/screens/factory.py 2009-05-05 03:31:34 +0000 |
2501 | @@ -4,25 +4,25 @@ |
2502 | __copyright__ = '2009, Matt Layman' |
2503 | __author__ = 'Matt Layman <laymansterms.dev@gmail.com>' |
2504 | |
2505 | -from entertainerlib.frontend.gui.screens.artist import Artist |
2506 | -from entertainerlib.frontend.gui.screens.album import Album |
2507 | -from entertainerlib.frontend.gui.screens.audio_play import AudioPlay |
2508 | -from entertainerlib.frontend.gui.screens.disc import Disc |
2509 | -from entertainerlib.frontend.gui.screens.feed import Feed |
2510 | -from entertainerlib.frontend.gui.screens.feed_entry import FeedEntry |
2511 | -from entertainerlib.frontend.gui.screens.main import Main |
2512 | -from entertainerlib.frontend.gui.screens.movie import Movie |
2513 | -from entertainerlib.frontend.gui.screens.music import Music |
2514 | -from entertainerlib.frontend.gui.screens.photo import Photo |
2515 | -from entertainerlib.frontend.gui.screens.photo_albums import PhotoAlbums |
2516 | -from entertainerlib.frontend.gui.screens.photographs import Photographs |
2517 | -from entertainerlib.frontend.gui.screens.question import Question |
2518 | -from entertainerlib.frontend.gui.screens.rss import Rss |
2519 | -from entertainerlib.frontend.gui.screens.tv_episodes import TvEpisodes |
2520 | -from entertainerlib.frontend.gui.screens.tv_series import TvSeries |
2521 | -from entertainerlib.frontend.gui.screens.video import Video |
2522 | -from entertainerlib.frontend.gui.screens.video_osd import VideoOSD |
2523 | -from entertainerlib.frontend.gui.screens.weather import WeatherScreen |
2524 | +from entertainerlib.gui.screens.artist import Artist |
2525 | +from entertainerlib.gui.screens.album import Album |
2526 | +from entertainerlib.gui.screens.audio_play import AudioPlay |
2527 | +from entertainerlib.gui.screens.disc import Disc |
2528 | +from entertainerlib.gui.screens.feed import Feed |
2529 | +from entertainerlib.gui.screens.feed_entry import FeedEntry |
2530 | +from entertainerlib.gui.screens.main import Main |
2531 | +from entertainerlib.gui.screens.movie import Movie |
2532 | +from entertainerlib.gui.screens.music import Music |
2533 | +from entertainerlib.gui.screens.photo import Photo |
2534 | +from entertainerlib.gui.screens.photo_albums import PhotoAlbums |
2535 | +from entertainerlib.gui.screens.photographs import Photographs |
2536 | +from entertainerlib.gui.screens.question import Question |
2537 | +from entertainerlib.gui.screens.rss import Rss |
2538 | +from entertainerlib.gui.screens.tv_episodes import TvEpisodes |
2539 | +from entertainerlib.gui.screens.tv_series import TvSeries |
2540 | +from entertainerlib.gui.screens.video import Video |
2541 | +from entertainerlib.gui.screens.video_osd import VideoOSD |
2542 | +from entertainerlib.gui.screens.weather import WeatherScreen |
2543 | |
2544 | class ScreenFactory(object): |
2545 | '''Generate a screen based on the type provided.''' |
2546 | |
2547 | === modified file 'entertainerlib/gui/screens/feed.py' |
2548 | --- entertainerlib/frontend/gui/screens/feed.py 2009-04-27 03:32:30 +0000 |
2549 | +++ entertainerlib/gui/screens/feed.py 2009-05-06 04:00:53 +0000 |
2550 | @@ -6,13 +6,13 @@ |
2551 | |
2552 | import pango |
2553 | |
2554 | -from entertainerlib.frontend.gui.screens.screen import Screen |
2555 | -from entertainerlib.frontend.gui.widgets.label import Label |
2556 | -from entertainerlib.frontend.gui.widgets.list_indicator import ListIndicator |
2557 | -from entertainerlib.frontend.gui.widgets.texture import Texture |
2558 | -from entertainerlib.frontend.gui.widgets.text_menu import TextMenu |
2559 | -from entertainerlib.frontend.gui.widgets.text_menu_item import TextMenuItem |
2560 | -from entertainerlib.utils.feed_utils import FeedEntryParser |
2561 | +from entertainerlib.gui.screens.screen import Screen |
2562 | +from entertainerlib.gui.widgets.label import Label |
2563 | +from entertainerlib.gui.widgets.list_indicator import ListIndicator |
2564 | +from entertainerlib.gui.widgets.texture import Texture |
2565 | +from entertainerlib.gui.widgets.text_menu import TextMenu |
2566 | +from entertainerlib.gui.widgets.text_menu_item import TextMenuItem |
2567 | +from entertainerlib.backend.components.feeds.feed_utils import FeedEntryParser |
2568 | |
2569 | class Feed(Screen): |
2570 | '''Screen is displayed when headlines are accessed for a specific feed.''' |
2571 | |
2572 | === modified file 'entertainerlib/gui/screens/feed_entry.py' |
2573 | --- entertainerlib/frontend/gui/screens/feed_entry.py 2009-04-27 03:32:30 +0000 |
2574 | +++ entertainerlib/gui/screens/feed_entry.py 2009-05-06 04:00:53 +0000 |
2575 | @@ -6,12 +6,12 @@ |
2576 | |
2577 | import pango |
2578 | |
2579 | -from entertainerlib.frontend.gui.screens.screen import Screen |
2580 | -from entertainerlib.frontend.gui.user_event import UserEvent |
2581 | -from entertainerlib.frontend.gui.widgets.label import Label |
2582 | -from entertainerlib.frontend.gui.widgets.scroll_area import ScrollArea |
2583 | -from entertainerlib.frontend.gui.widgets.texture import Texture |
2584 | -from entertainerlib.utils.feed_utils import FeedEntryParser |
2585 | +from entertainerlib.gui.screens.screen import Screen |
2586 | +from entertainerlib.gui.user_event import UserEvent |
2587 | +from entertainerlib.gui.widgets.label import Label |
2588 | +from entertainerlib.gui.widgets.scroll_area import ScrollArea |
2589 | +from entertainerlib.gui.widgets.texture import Texture |
2590 | +from entertainerlib.backend.components.feeds.feed_utils import FeedEntryParser |
2591 | |
2592 | class FeedEntry(Screen): |
2593 | '''Screen displays one feed entry.''' |
2594 | |
2595 | === modified file 'entertainerlib/gui/screens/main.py' |
2596 | --- entertainerlib/frontend/gui/screens/main.py 2009-04-27 03:32:30 +0000 |
2597 | +++ entertainerlib/gui/screens/main.py 2009-05-06 04:15:18 +0000 |
2598 | @@ -4,17 +4,18 @@ |
2599 | __copyright__ = "2007, Lauri Taimila" |
2600 | __author__ = "Lauri Taimila <lauri@taimila.com>" |
2601 | |
2602 | +import os |
2603 | + |
2604 | import clutter |
2605 | |
2606 | -from entertainerlib.frontend.gui.screens.screen import Screen |
2607 | -from entertainerlib.frontend.gui.widgets.clock_label import ClockLabel |
2608 | -from entertainerlib.frontend.gui.widgets.label import Label |
2609 | -from entertainerlib.frontend.gui.widgets.scroll_menu import ScrollMenu |
2610 | -from entertainerlib.frontend.gui.widgets.texture import Texture |
2611 | -from entertainerlib.frontend.gui.widgets.text_menu import TextMenu |
2612 | -from entertainerlib.frontend.gui.widgets.text_menu_item import TextMenuItem |
2613 | -from entertainerlib.utils.cd_utils import eject_cd |
2614 | -from entertainerlib.utils.feed_utils import FeedEntryParser |
2615 | +from entertainerlib.gui.screens.screen import Screen |
2616 | +from entertainerlib.gui.widgets.clock_label import ClockLabel |
2617 | +from entertainerlib.gui.widgets.label import Label |
2618 | +from entertainerlib.gui.widgets.scroll_menu import ScrollMenu |
2619 | +from entertainerlib.gui.widgets.texture import Texture |
2620 | +from entertainerlib.gui.widgets.text_menu import TextMenu |
2621 | +from entertainerlib.gui.widgets.text_menu_item import TextMenuItem |
2622 | +from entertainerlib.backend.components.feeds.feed_utils import FeedEntryParser |
2623 | |
2624 | class Main(Screen): |
2625 | '''Screen displayed when frontend is opened and provides main navigation.''' |
2626 | @@ -102,11 +103,11 @@ |
2627 | item5 = Label(size, color, 0, 0, _("Headlines"), "rss") |
2628 | self.menu.add(item5) |
2629 | |
2630 | - if self.config.display_weather_in_frontend(): |
2631 | + if self.config.display_weather_in_client(): |
2632 | item6 = Label(size, color, 0, 0, _("Weather"), "weather") |
2633 | self.menu.add(item6) |
2634 | |
2635 | - if self.config.display_cd_eject_in_frontend(): |
2636 | + if self.config.display_cd_eject_in_client(): |
2637 | item7 = Label(size, color, 0, 0, _("Eject CD"), "eject_cd") |
2638 | self.menu.add(item7) |
2639 | |
2640 | @@ -310,7 +311,7 @@ |
2641 | elif item.get_name() == "weather": |
2642 | self.callback("weather") |
2643 | elif item.get_name() == "eject_cd": |
2644 | - eject_cd() |
2645 | + os.system('eject') |
2646 | elif item.get_name() == "photo": |
2647 | self.callback("photo_albums") |
2648 | elif item.get_name() == "rss": |
2649 | |
2650 | === modified file 'entertainerlib/gui/screens/movie.py' |
2651 | --- entertainerlib/frontend/gui/screens/movie.py 2009-04-27 03:32:30 +0000 |
2652 | +++ entertainerlib/gui/screens/movie.py 2009-05-05 03:31:34 +0000 |
2653 | @@ -8,15 +8,15 @@ |
2654 | import gtk |
2655 | import pango |
2656 | |
2657 | -from entertainerlib.frontend.gui.screens.screen import Screen |
2658 | -from entertainerlib.frontend.gui.user_event import UserEvent |
2659 | -from entertainerlib.frontend.gui.widgets.eyecandy_texture import ( |
2660 | +from entertainerlib.gui.screens.screen import Screen |
2661 | +from entertainerlib.gui.user_event import UserEvent |
2662 | +from entertainerlib.gui.widgets.eyecandy_texture import ( |
2663 | EyeCandyTexture) |
2664 | -from entertainerlib.frontend.gui.widgets.label import Label |
2665 | -from entertainerlib.frontend.gui.widgets.scroll_area import ScrollArea |
2666 | -from entertainerlib.frontend.gui.widgets.texture import Texture |
2667 | -from entertainerlib.frontend.gui.widgets.text_menu import TextMenu |
2668 | -from entertainerlib.frontend.gui.widgets.text_menu_item import TextMenuItem |
2669 | +from entertainerlib.gui.widgets.label import Label |
2670 | +from entertainerlib.gui.widgets.scroll_area import ScrollArea |
2671 | +from entertainerlib.gui.widgets.texture import Texture |
2672 | +from entertainerlib.gui.widgets.text_menu import TextMenu |
2673 | +from entertainerlib.gui.widgets.text_menu_item import TextMenuItem |
2674 | |
2675 | class Movie(Screen): |
2676 | '''Screen contains information of one movie.''' |
2677 | |
2678 | === modified file 'entertainerlib/gui/screens/music.py' |
2679 | --- entertainerlib/frontend/gui/screens/music.py 2009-04-27 03:32:30 +0000 |
2680 | +++ entertainerlib/gui/screens/music.py 2009-05-05 03:31:34 +0000 |
2681 | @@ -4,12 +4,12 @@ |
2682 | __copyright__ = "2007, Lauri Taimila" |
2683 | __author__ = "Lauri Taimila <lauri@taimila.com>" |
2684 | |
2685 | -from entertainerlib.frontend.gui.screens.screen import Screen |
2686 | -from entertainerlib.frontend.gui.tabs.albums_tab import AlbumsTab |
2687 | -from entertainerlib.frontend.gui.tabs.artists_tab import ArtistsTab |
2688 | -from entertainerlib.frontend.gui.widgets.label import Label |
2689 | -from entertainerlib.frontend.gui.widgets.texture import Texture |
2690 | -from entertainerlib.frontend.medialibrary.playlist import Playlist |
2691 | +from entertainerlib.gui.screens.screen import Screen |
2692 | +from entertainerlib.gui.tabs.albums_tab import AlbumsTab |
2693 | +from entertainerlib.gui.tabs.artists_tab import ArtistsTab |
2694 | +from entertainerlib.gui.widgets.label import Label |
2695 | +from entertainerlib.gui.widgets.texture import Texture |
2696 | +from entertainerlib.client.medialibrary.playlist import Playlist |
2697 | |
2698 | class Music(Screen): |
2699 | '''Screen that allows user to browse music library content.''' |
2700 | |
2701 | === modified file 'entertainerlib/gui/screens/photo.py' |
2702 | --- entertainerlib/frontend/gui/screens/photo.py 2009-04-27 03:32:30 +0000 |
2703 | +++ entertainerlib/gui/screens/photo.py 2009-05-05 03:31:34 +0000 |
2704 | @@ -7,9 +7,9 @@ |
2705 | import clutter |
2706 | import gobject |
2707 | |
2708 | -from entertainerlib.frontend.gui.screens.screen import Screen |
2709 | -from entertainerlib.frontend.gui.widgets.label import Label |
2710 | -from entertainerlib.frontend.gui.widgets.texture import Texture |
2711 | +from entertainerlib.gui.screens.screen import Screen |
2712 | +from entertainerlib.gui.widgets.label import Label |
2713 | +from entertainerlib.gui.widgets.texture import Texture |
2714 | |
2715 | class Photo(Screen): |
2716 | '''Screen displays photograph in fullscreen and allows user to zoom in.''' |
2717 | |
2718 | === modified file 'entertainerlib/gui/screens/photo_albums.py' |
2719 | --- entertainerlib/frontend/gui/screens/photo_albums.py 2009-04-27 03:32:30 +0000 |
2720 | +++ entertainerlib/gui/screens/photo_albums.py 2009-05-05 03:31:34 +0000 |
2721 | @@ -9,14 +9,14 @@ |
2722 | import gobject |
2723 | import clutter |
2724 | |
2725 | -from entertainerlib.frontend.gui.screens.screen import Screen |
2726 | -from entertainerlib.frontend.gui.widgets.eyecandy_texture import ( |
2727 | +from entertainerlib.gui.screens.screen import Screen |
2728 | +from entertainerlib.gui.widgets.eyecandy_texture import ( |
2729 | EyeCandyTexture) |
2730 | -from entertainerlib.frontend.gui.widgets.label import Label |
2731 | -from entertainerlib.frontend.gui.widgets.list_indicator import ListIndicator |
2732 | -from entertainerlib.frontend.gui.widgets.texture import Texture |
2733 | -from entertainerlib.frontend.gui.widgets.text_menu import TextMenu |
2734 | -from entertainerlib.frontend.gui.widgets.text_menu_item import TextMenuItem |
2735 | +from entertainerlib.gui.widgets.label import Label |
2736 | +from entertainerlib.gui.widgets.list_indicator import ListIndicator |
2737 | +from entertainerlib.gui.widgets.texture import Texture |
2738 | +from entertainerlib.gui.widgets.text_menu import TextMenu |
2739 | +from entertainerlib.gui.widgets.text_menu_item import TextMenuItem |
2740 | |
2741 | class PhotoAlbums(Screen): |
2742 | '''Screen contains a list of photo albums and album previews.''' |
2743 | |
2744 | === modified file 'entertainerlib/gui/screens/photographs.py' |
2745 | --- entertainerlib/frontend/gui/screens/photographs.py 2009-04-27 03:32:30 +0000 |
2746 | +++ entertainerlib/gui/screens/photographs.py 2009-05-05 03:31:34 +0000 |
2747 | @@ -8,14 +8,14 @@ |
2748 | import clutter |
2749 | import gobject |
2750 | |
2751 | -from entertainerlib.frontend.gui.screens.screen import Screen |
2752 | -from entertainerlib.frontend.gui.widgets.image_menu import ImageMenu |
2753 | -from entertainerlib.frontend.gui.widgets.label import Label |
2754 | -from entertainerlib.frontend.gui.widgets.list_indicator import ListIndicator |
2755 | -from entertainerlib.frontend.gui.widgets.image_menu_item import ImageMenuItem |
2756 | -from entertainerlib.frontend.gui.widgets.loading_animation import ( |
2757 | +from entertainerlib.gui.screens.screen import Screen |
2758 | +from entertainerlib.gui.widgets.image_menu import ImageMenu |
2759 | +from entertainerlib.gui.widgets.label import Label |
2760 | +from entertainerlib.gui.widgets.list_indicator import ListIndicator |
2761 | +from entertainerlib.gui.widgets.image_menu_item import ImageMenuItem |
2762 | +from entertainerlib.gui.widgets.loading_animation import ( |
2763 | LoadingAnimation) |
2764 | -from entertainerlib.frontend.gui.widgets.texture import Texture |
2765 | +from entertainerlib.gui.widgets.texture import Texture |
2766 | |
2767 | class Photographs(Screen): |
2768 | '''Screen displays a grid of selectable photograph thumbnails.''' |
2769 | |
2770 | === modified file 'entertainerlib/gui/screens/question.py' |
2771 | --- entertainerlib/frontend/gui/screens/question.py 2009-04-27 03:32:30 +0000 |
2772 | +++ entertainerlib/gui/screens/question.py 2009-05-05 03:31:34 +0000 |
2773 | @@ -4,11 +4,11 @@ |
2774 | __copyright__ = "2008, Teje Rodgers" |
2775 | __author__ = "Teje Rodgers <contact@tejerodgers.com>" |
2776 | |
2777 | -from entertainerlib.frontend.gui.screens.screen import Screen |
2778 | -from entertainerlib.frontend.gui.transitions.transition import Transition |
2779 | -from entertainerlib.frontend.gui.widgets.label import Label |
2780 | -from entertainerlib.frontend.gui.widgets.text_menu import TextMenu |
2781 | -from entertainerlib.frontend.gui.widgets.text_menu_item import TextMenuItem |
2782 | +from entertainerlib.gui.screens.screen import Screen |
2783 | +from entertainerlib.gui.transitions.transition import Transition |
2784 | +from entertainerlib.gui.widgets.label import Label |
2785 | +from entertainerlib.gui.widgets.text_menu import TextMenu |
2786 | +from entertainerlib.gui.widgets.text_menu_item import TextMenuItem |
2787 | |
2788 | class Question(Screen): |
2789 | '''Screen is displayed when the application needs to ask a close ended |
2790 | |
2791 | === modified file 'entertainerlib/gui/screens/rss.py' |
2792 | --- entertainerlib/frontend/gui/screens/rss.py 2009-04-27 03:32:30 +0000 |
2793 | +++ entertainerlib/gui/screens/rss.py 2009-05-06 04:00:53 +0000 |
2794 | @@ -6,16 +6,16 @@ |
2795 | |
2796 | import pango |
2797 | |
2798 | -from entertainerlib.frontend.gui.screens.screen import Screen |
2799 | -from entertainerlib.frontend.gui.widgets.label import Label |
2800 | -from entertainerlib.frontend.gui.widgets.menu import Menu |
2801 | -from entertainerlib.frontend.gui.widgets.selector import Selector |
2802 | -from entertainerlib.frontend.gui.widgets.texture import Texture |
2803 | -from entertainerlib.frontend.gui.widgets.text_menu import TextMenu |
2804 | -from entertainerlib.frontend.gui.widgets.text_menu_item import TextMenuItem |
2805 | -from entertainerlib.frontend.gui.widgets.list_indicator import ListIndicator |
2806 | -from entertainerlib.frontend.medialibrary.feeds import Feed |
2807 | -from entertainerlib.utils.feed_utils import FeedEntryParser |
2808 | +from entertainerlib.gui.screens.screen import Screen |
2809 | +from entertainerlib.gui.widgets.label import Label |
2810 | +from entertainerlib.gui.widgets.menu import Menu |
2811 | +from entertainerlib.gui.widgets.selector import Selector |
2812 | +from entertainerlib.gui.widgets.texture import Texture |
2813 | +from entertainerlib.gui.widgets.text_menu import TextMenu |
2814 | +from entertainerlib.gui.widgets.text_menu_item import TextMenuItem |
2815 | +from entertainerlib.gui.widgets.list_indicator import ListIndicator |
2816 | +from entertainerlib.client.medialibrary.feeds import Feed |
2817 | +from entertainerlib.backend.components.feeds.feed_utils import FeedEntryParser |
2818 | |
2819 | class Rss(Screen): |
2820 | '''Screen displays RSS-feed titles and number of entries.''' |
2821 | |
2822 | === modified file 'entertainerlib/gui/screens/screen.py' |
2823 | --- entertainerlib/frontend/gui/screens/screen.py 2009-04-30 01:16:33 +0000 |
2824 | +++ entertainerlib/gui/screens/screen.py 2009-05-05 03:31:34 +0000 |
2825 | @@ -9,9 +9,9 @@ |
2826 | import clutter |
2827 | |
2828 | from entertainerlib.exceptions import ScreenException |
2829 | -from entertainerlib.frontend.gui.user_event import UserEvent |
2830 | -from entertainerlib.frontend.gui.widgets.base import Base |
2831 | -from entertainerlib.frontend.gui.widgets.tab_group import TabGroup |
2832 | +from entertainerlib.gui.user_event import UserEvent |
2833 | +from entertainerlib.gui.widgets.base import Base |
2834 | +from entertainerlib.gui.widgets.tab_group import TabGroup |
2835 | |
2836 | class Screen(Base, clutter.Group): |
2837 | """ |
2838 | |
2839 | === modified file 'entertainerlib/gui/screens/tv_episodes.py' |
2840 | --- entertainerlib/frontend/gui/screens/tv_episodes.py 2009-04-27 03:32:30 +0000 |
2841 | +++ entertainerlib/gui/screens/tv_episodes.py 2009-05-05 03:31:34 +0000 |
2842 | @@ -7,15 +7,15 @@ |
2843 | import gtk |
2844 | import pango |
2845 | |
2846 | -from entertainerlib.frontend.gui.screens.screen import Screen |
2847 | -from entertainerlib.frontend.gui.user_event import UserEvent |
2848 | -from entertainerlib.frontend.gui.widgets.eyecandy_texture import ( |
2849 | +from entertainerlib.gui.screens.screen import Screen |
2850 | +from entertainerlib.gui.user_event import UserEvent |
2851 | +from entertainerlib.gui.widgets.eyecandy_texture import ( |
2852 | EyeCandyTexture) |
2853 | -from entertainerlib.frontend.gui.widgets.label import Label |
2854 | -from entertainerlib.frontend.gui.widgets.list_indicator import ListIndicator |
2855 | -from entertainerlib.frontend.gui.widgets.text_menu import TextMenu |
2856 | -from entertainerlib.frontend.gui.widgets.scroll_area import ScrollArea |
2857 | -from entertainerlib.frontend.gui.widgets.text_menu_item import TextMenuItem |
2858 | +from entertainerlib.gui.widgets.label import Label |
2859 | +from entertainerlib.gui.widgets.list_indicator import ListIndicator |
2860 | +from entertainerlib.gui.widgets.text_menu import TextMenu |
2861 | +from entertainerlib.gui.widgets.scroll_area import ScrollArea |
2862 | +from entertainerlib.gui.widgets.text_menu_item import TextMenuItem |
2863 | |
2864 | class TvEpisodes(Screen): |
2865 | '''Screen contains list of all episodes of one specific season.''' |
2866 | |
2867 | === modified file 'entertainerlib/gui/screens/tv_series.py' |
2868 | --- entertainerlib/frontend/gui/screens/tv_series.py 2009-04-27 03:32:30 +0000 |
2869 | +++ entertainerlib/gui/screens/tv_series.py 2009-05-05 03:31:34 +0000 |
2870 | @@ -6,13 +6,13 @@ |
2871 | |
2872 | import gtk |
2873 | |
2874 | -from entertainerlib.frontend.gui.screens.screen import Screen |
2875 | -from entertainerlib.frontend.gui.widgets.eyecandy_texture import ( |
2876 | +from entertainerlib.gui.screens.screen import Screen |
2877 | +from entertainerlib.gui.widgets.eyecandy_texture import ( |
2878 | EyeCandyTexture) |
2879 | -from entertainerlib.frontend.gui.widgets.label import Label |
2880 | -from entertainerlib.frontend.gui.widgets.list_indicator import ListIndicator |
2881 | -from entertainerlib.frontend.gui.widgets.text_menu import TextMenu |
2882 | -from entertainerlib.frontend.gui.widgets.text_menu_item import TextMenuItem |
2883 | +from entertainerlib.gui.widgets.label import Label |
2884 | +from entertainerlib.gui.widgets.list_indicator import ListIndicator |
2885 | +from entertainerlib.gui.widgets.text_menu import TextMenu |
2886 | +from entertainerlib.gui.widgets.text_menu_item import TextMenuItem |
2887 | |
2888 | class TvSeries(Screen): |
2889 | '''Screen that contains all seasons of one TV series.''' |
2890 | |
2891 | === modified file 'entertainerlib/gui/screens/video.py' |
2892 | --- entertainerlib/frontend/gui/screens/video.py 2009-04-27 03:32:30 +0000 |
2893 | +++ entertainerlib/gui/screens/video.py 2009-05-05 03:31:34 +0000 |
2894 | @@ -4,11 +4,11 @@ |
2895 | __copyright__ = "2008, Lauri Taimila" |
2896 | __author__ = "Lauri Taimila <lauri@taimila.com>" |
2897 | |
2898 | -from entertainerlib.frontend.gui.screens.screen import Screen |
2899 | -from entertainerlib.frontend.gui.tabs.movies_tab import MoviesTab |
2900 | -from entertainerlib.frontend.gui.tabs.series_tab import SeriesTab |
2901 | -from entertainerlib.frontend.gui.tabs.video_clips_tab import VideoClipsTab |
2902 | -from entertainerlib.frontend.gui.widgets.label import Label |
2903 | +from entertainerlib.gui.screens.screen import Screen |
2904 | +from entertainerlib.gui.tabs.movies_tab import MoviesTab |
2905 | +from entertainerlib.gui.tabs.series_tab import SeriesTab |
2906 | +from entertainerlib.gui.tabs.video_clips_tab import VideoClipsTab |
2907 | +from entertainerlib.gui.widgets.label import Label |
2908 | |
2909 | class Video(Screen): |
2910 | '''Screen contains tabs for different video types in the video library.''' |
2911 | |
2912 | === modified file 'entertainerlib/gui/screens/video_osd.py' |
2913 | --- entertainerlib/frontend/gui/screens/video_osd.py 2009-04-27 03:32:30 +0000 |
2914 | +++ entertainerlib/gui/screens/video_osd.py 2009-05-05 03:31:34 +0000 |
2915 | @@ -7,11 +7,11 @@ |
2916 | import gobject |
2917 | import clutter |
2918 | |
2919 | -from entertainerlib.frontend.gui.screens.screen import Screen |
2920 | -from entertainerlib.frontend.gui.user_event import UserEvent |
2921 | -from entertainerlib.frontend.gui.widgets.label import Label |
2922 | -from entertainerlib.frontend.gui.widgets.progress_bar import ProgressBar |
2923 | -from entertainerlib.frontend.gui.widgets.texture import Texture |
2924 | +from entertainerlib.gui.screens.screen import Screen |
2925 | +from entertainerlib.gui.user_event import UserEvent |
2926 | +from entertainerlib.gui.widgets.label import Label |
2927 | +from entertainerlib.gui.widgets.progress_bar import ProgressBar |
2928 | +from entertainerlib.gui.widgets.texture import Texture |
2929 | |
2930 | class VideoOSD(Screen): |
2931 | '''Screen is displayed when video is being watched. |
2932 | |
2933 | === modified file 'entertainerlib/gui/screens/weather.py' |
2934 | --- entertainerlib/frontend/gui/screens/weather.py 2009-04-27 03:32:30 +0000 |
2935 | +++ entertainerlib/gui/screens/weather.py 2009-05-06 05:10:14 +0000 |
2936 | @@ -4,10 +4,10 @@ |
2937 | __copyright__ = "2008, Jamie Bennett" |
2938 | __author__ = "Jamie Bennett <jamie@linuxuk.org>" |
2939 | |
2940 | -from entertainerlib.frontend.gui.screens.screen import Screen |
2941 | -from entertainerlib.frontend.gui.widgets.label import Label |
2942 | -from entertainerlib.frontend.gui.widgets.texture import Texture |
2943 | -from entertainerlib.utils.weather import Weather |
2944 | +from entertainerlib.gui.screens.screen import Screen |
2945 | +from entertainerlib.gui.widgets.label import Label |
2946 | +from entertainerlib.gui.widgets.texture import Texture |
2947 | +from entertainerlib.weather import Weather |
2948 | |
2949 | class WeatherScreen(Screen): |
2950 | '''Screen to display the user's set weather location.''' |
2951 | |
2952 | === renamed file 'entertainerlib/utils/system_tray_icon.py' => 'entertainerlib/gui/system_tray_icon.py' |
2953 | --- entertainerlib/utils/system_tray_icon.py 2009-02-07 00:28:11 +0000 |
2954 | +++ entertainerlib/gui/system_tray_icon.py 2009-05-06 03:08:19 +0000 |
2955 | @@ -9,11 +9,10 @@ |
2956 | import gtk |
2957 | import gtk.glade |
2958 | |
2959 | -from entertainerlib.utils.log_viewer import LogViewer |
2960 | -from entertainerlib.utils.preferences_dialog import PreferencesDialog |
2961 | -from entertainerlib.utils.content_management_dialog import ( |
2962 | - ContentManagementDialog) |
2963 | -from entertainerlib.utils.configuration import Configuration |
2964 | +from entertainerlib.configuration import Configuration |
2965 | +from entertainerlib.dialog import (ContentManagementDialog, LogViewer, |
2966 | + PreferencesDialog) |
2967 | + |
2968 | |
2969 | class SystemTrayIcon: |
2970 | """Implements system tray icon for entertainer.""" |
2971 | @@ -43,8 +42,8 @@ |
2972 | os.path.join(self.GLADE_DIR, "system_tray_icon_menu.glade")) |
2973 | |
2974 | # Bind menu signals |
2975 | - callback_dic = {"on_menuitem_frontend_activate" |
2976 | - : self.on_menuitem_frontend_activate, |
2977 | + callback_dic = {"on_menuitem_client_activate" |
2978 | + : self.on_menuitem_client_activate, |
2979 | "on_menuitem_preferences_activate" |
2980 | : self.on_menuitem_preferences_activate, |
2981 | "on_menuitem_content_management_activate" |
2982 | @@ -68,7 +67,7 @@ |
2983 | self.icon_widget.connect('popup-menu', self.open_popup_menu) |
2984 | |
2985 | def systray_icon_activated(self, widget, data= None): |
2986 | - """Switch visibility of frontend when system tray icon is clicked""" |
2987 | + """Switch visibility of client when system tray icon is clicked""" |
2988 | self.toggle_interface_visibility_callback() |
2989 | |
2990 | def open_popup_menu(self, widget, button, time, data = None): |
2991 | @@ -76,9 +75,9 @@ |
2992 | self.popup.show_all() |
2993 | self.popup.popup(None, None, None, 3, time) |
2994 | |
2995 | - def on_menuitem_frontend_activate(self, widget): |
2996 | - """Execute frontend here if not running. Show if running""" |
2997 | - self.set_frontend_visible(True) |
2998 | + def on_menuitem_client_activate(self, widget): |
2999 | + """Execute client here if not running. Show if running""" |
3000 | + self.set_client_visible(True) |
3001 | |
3002 | def on_menuitem_preferences_activate(self, widget): |
3003 | """Executes preferences-tool.""" |
3004 | |
3005 | === modified file 'entertainerlib/gui/tabs/albums_tab.py' |
3006 | --- entertainerlib/frontend/gui/tabs/albums_tab.py 2009-02-03 23:37:57 +0000 |
3007 | +++ entertainerlib/gui/tabs/albums_tab.py 2009-05-05 03:31:34 +0000 |
3008 | @@ -9,14 +9,14 @@ |
3009 | import gobject |
3010 | import pango |
3011 | |
3012 | -from entertainerlib.frontend.gui.tabs.tab import Tab |
3013 | -from entertainerlib.frontend.gui.widgets.image_menu import ImageMenu |
3014 | -from entertainerlib.frontend.gui.widgets.image_menu_item import ImageMenuItem |
3015 | -from entertainerlib.frontend.gui.widgets.label import Label |
3016 | -from entertainerlib.frontend.gui.widgets.list_indicator import ListIndicator |
3017 | -from entertainerlib.frontend.gui.widgets.loading_animation import ( |
3018 | +from entertainerlib.gui.tabs.tab import Tab |
3019 | +from entertainerlib.gui.widgets.image_menu import ImageMenu |
3020 | +from entertainerlib.gui.widgets.image_menu_item import ImageMenuItem |
3021 | +from entertainerlib.gui.widgets.label import Label |
3022 | +from entertainerlib.gui.widgets.list_indicator import ListIndicator |
3023 | +from entertainerlib.gui.widgets.loading_animation import ( |
3024 | LoadingAnimation) |
3025 | -from entertainerlib.frontend.gui.widgets.texture import Texture |
3026 | +from entertainerlib.gui.widgets.texture import Texture |
3027 | |
3028 | class AlbumsTab(Tab): |
3029 | '''Tab to show album listings''' |
3030 | |
3031 | === modified file 'entertainerlib/gui/tabs/artists_tab.py' |
3032 | --- entertainerlib/frontend/gui/tabs/artists_tab.py 2009-02-03 23:37:57 +0000 |
3033 | +++ entertainerlib/gui/tabs/artists_tab.py 2009-05-05 03:31:34 +0000 |
3034 | @@ -9,13 +9,13 @@ |
3035 | import gobject |
3036 | import pango |
3037 | |
3038 | -from entertainerlib.frontend.gui.tabs.tab import Tab |
3039 | -from entertainerlib.frontend.gui.widgets.label import Label |
3040 | -from entertainerlib.frontend.gui.widgets.list_indicator import ListIndicator |
3041 | -from entertainerlib.frontend.gui.widgets.loading_animation import ( |
3042 | +from entertainerlib.gui.tabs.tab import Tab |
3043 | +from entertainerlib.gui.widgets.label import Label |
3044 | +from entertainerlib.gui.widgets.list_indicator import ListIndicator |
3045 | +from entertainerlib.gui.widgets.loading_animation import ( |
3046 | LoadingAnimation) |
3047 | -from entertainerlib.frontend.gui.widgets.text_menu import TextMenu |
3048 | -from entertainerlib.frontend.gui.widgets.text_menu_item import TextMenuItem |
3049 | +from entertainerlib.gui.widgets.text_menu import TextMenu |
3050 | +from entertainerlib.gui.widgets.text_menu_item import TextMenuItem |
3051 | |
3052 | class ArtistsTab(Tab): |
3053 | '''Tab for the music screen to show artist listings''' |
3054 | |
3055 | === modified file 'entertainerlib/gui/tabs/lyrics_tab.py' |
3056 | --- entertainerlib/frontend/gui/tabs/lyrics_tab.py 2009-02-03 23:37:57 +0000 |
3057 | +++ entertainerlib/gui/tabs/lyrics_tab.py 2009-05-05 03:31:34 +0000 |
3058 | @@ -7,11 +7,11 @@ |
3059 | import pango |
3060 | import clutter |
3061 | |
3062 | -from entertainerlib.frontend.gui.tabs.tab import Tab |
3063 | -from entertainerlib.frontend.gui.widgets.label import Label |
3064 | -from entertainerlib.frontend.gui.widgets.loading_animation import ( |
3065 | +from entertainerlib.gui.tabs.tab import Tab |
3066 | +from entertainerlib.gui.widgets.label import Label |
3067 | +from entertainerlib.gui.widgets.loading_animation import ( |
3068 | LoadingAnimation) |
3069 | -from entertainerlib.frontend.gui.widgets.scroll_area import ScrollArea |
3070 | +from entertainerlib.gui.widgets.scroll_area import ScrollArea |
3071 | |
3072 | class LyricsTab(Tab): |
3073 | '''Tab for the audio play screen to show lyrics''' |
3074 | |
3075 | === modified file 'entertainerlib/gui/tabs/movies_tab.py' |
3076 | --- entertainerlib/frontend/gui/tabs/movies_tab.py 2009-02-03 23:37:57 +0000 |
3077 | +++ entertainerlib/gui/tabs/movies_tab.py 2009-05-05 03:31:34 +0000 |
3078 | @@ -8,13 +8,13 @@ |
3079 | import gtk |
3080 | import pango |
3081 | |
3082 | -from entertainerlib.frontend.gui.tabs.tab import Tab |
3083 | -from entertainerlib.frontend.gui.widgets.image_menu import ImageMenu |
3084 | -from entertainerlib.frontend.gui.widgets.image_menu_item import ImageMenuItem |
3085 | -from entertainerlib.frontend.gui.widgets.label import Label |
3086 | -from entertainerlib.frontend.gui.widgets.list_indicator import ListIndicator |
3087 | -from entertainerlib.frontend.gui.widgets.rounded_texture import RoundedTexture |
3088 | -from entertainerlib.frontend.gui.widgets.texture import Texture |
3089 | +from entertainerlib.gui.tabs.tab import Tab |
3090 | +from entertainerlib.gui.widgets.image_menu import ImageMenu |
3091 | +from entertainerlib.gui.widgets.image_menu_item import ImageMenuItem |
3092 | +from entertainerlib.gui.widgets.label import Label |
3093 | +from entertainerlib.gui.widgets.list_indicator import ListIndicator |
3094 | +from entertainerlib.gui.widgets.rounded_texture import RoundedTexture |
3095 | +from entertainerlib.gui.widgets.texture import Texture |
3096 | |
3097 | class MoviesTab(Tab): |
3098 | """ |
3099 | |
3100 | === modified file 'entertainerlib/gui/tabs/playing_tab.py' |
3101 | --- entertainerlib/frontend/gui/tabs/playing_tab.py 2009-02-06 08:33:50 +0000 |
3102 | +++ entertainerlib/gui/tabs/playing_tab.py 2009-05-05 03:31:34 +0000 |
3103 | @@ -6,9 +6,9 @@ |
3104 | |
3105 | import pango |
3106 | |
3107 | -from entertainerlib.frontend.gui.tabs.tab import Tab |
3108 | -from entertainerlib.frontend.gui.widgets.label import Label |
3109 | -from entertainerlib.frontend.gui.widgets.progress_bar import ProgressBar |
3110 | +from entertainerlib.gui.tabs.tab import Tab |
3111 | +from entertainerlib.gui.widgets.label import Label |
3112 | +from entertainerlib.gui.widgets.progress_bar import ProgressBar |
3113 | |
3114 | class PlayingTab(Tab): |
3115 | '''Tab for the audio play screen to show currently playing audio''' |
3116 | |
3117 | === modified file 'entertainerlib/gui/tabs/series_tab.py' |
3118 | --- entertainerlib/frontend/gui/tabs/series_tab.py 2009-02-03 23:37:57 +0000 |
3119 | +++ entertainerlib/gui/tabs/series_tab.py 2009-05-05 03:31:34 +0000 |
3120 | @@ -8,13 +8,13 @@ |
3121 | import gtk |
3122 | import pango |
3123 | |
3124 | -from entertainerlib.frontend.gui.tabs.tab import Tab |
3125 | -from entertainerlib.frontend.gui.widgets.image_menu import ImageMenu |
3126 | -from entertainerlib.frontend.gui.widgets.image_menu_item import ImageMenuItem |
3127 | -from entertainerlib.frontend.gui.widgets.label import Label |
3128 | -from entertainerlib.frontend.gui.widgets.list_indicator import ListIndicator |
3129 | -from entertainerlib.frontend.gui.widgets.rounded_texture import RoundedTexture |
3130 | -from entertainerlib.frontend.gui.widgets.texture import Texture |
3131 | +from entertainerlib.gui.tabs.tab import Tab |
3132 | +from entertainerlib.gui.widgets.image_menu import ImageMenu |
3133 | +from entertainerlib.gui.widgets.image_menu_item import ImageMenuItem |
3134 | +from entertainerlib.gui.widgets.label import Label |
3135 | +from entertainerlib.gui.widgets.list_indicator import ListIndicator |
3136 | +from entertainerlib.gui.widgets.rounded_texture import RoundedTexture |
3137 | +from entertainerlib.gui.widgets.texture import Texture |
3138 | |
3139 | class SeriesTab(Tab): |
3140 | """ |
3141 | |
3142 | === modified file 'entertainerlib/gui/tabs/tab.py' |
3143 | --- entertainerlib/frontend/gui/tabs/tab.py 2009-02-28 17:22:46 +0000 |
3144 | +++ entertainerlib/gui/tabs/tab.py 2009-05-05 03:31:34 +0000 |
3145 | @@ -6,10 +6,10 @@ |
3146 | |
3147 | import clutter |
3148 | |
3149 | -from entertainerlib.frontend.gui.user_event import UserEvent |
3150 | -from entertainerlib.frontend.gui.widgets.base import Base |
3151 | -from entertainerlib.frontend.gui.widgets.label import Label |
3152 | -from entertainerlib.frontend.gui.widgets.texture import Texture |
3153 | +from entertainerlib.gui.user_event import UserEvent |
3154 | +from entertainerlib.gui.widgets.base import Base |
3155 | +from entertainerlib.gui.widgets.label import Label |
3156 | +from entertainerlib.gui.widgets.texture import Texture |
3157 | |
3158 | class Tab(Base, clutter.Group): |
3159 | """ |
3160 | |
3161 | === modified file 'entertainerlib/gui/tabs/tracks_tab.py' |
3162 | --- entertainerlib/frontend/gui/tabs/tracks_tab.py 2009-02-03 23:37:57 +0000 |
3163 | +++ entertainerlib/gui/tabs/tracks_tab.py 2009-05-05 03:31:34 +0000 |
3164 | @@ -7,11 +7,11 @@ |
3165 | import clutter |
3166 | import pango |
3167 | |
3168 | -from entertainerlib.frontend.gui.tabs.tab import Tab |
3169 | -from entertainerlib.frontend.gui.widgets.label import Label |
3170 | -from entertainerlib.frontend.gui.widgets.list_indicator import ListIndicator |
3171 | -from entertainerlib.frontend.gui.widgets.text_menu import TextMenu |
3172 | -from entertainerlib.frontend.gui.widgets.text_menu_item import TextMenuItem |
3173 | +from entertainerlib.gui.tabs.tab import Tab |
3174 | +from entertainerlib.gui.widgets.label import Label |
3175 | +from entertainerlib.gui.widgets.list_indicator import ListIndicator |
3176 | +from entertainerlib.gui.widgets.text_menu import TextMenu |
3177 | +from entertainerlib.gui.widgets.text_menu_item import TextMenuItem |
3178 | |
3179 | class TracksTab(Tab): |
3180 | '''Tab for the artist screen to show track listings''' |
3181 | |
3182 | === modified file 'entertainerlib/gui/tabs/video_clips_tab.py' |
3183 | --- entertainerlib/frontend/gui/tabs/video_clips_tab.py 2009-02-03 23:37:57 +0000 |
3184 | +++ entertainerlib/gui/tabs/video_clips_tab.py 2009-05-05 03:31:34 +0000 |
3185 | @@ -9,12 +9,12 @@ |
3186 | import gtk |
3187 | import pango |
3188 | |
3189 | -from entertainerlib.frontend.gui.tabs.tab import Tab |
3190 | -from entertainerlib.frontend.gui.widgets.image_menu import ImageMenu |
3191 | -from entertainerlib.frontend.gui.widgets.image_menu_item import ImageMenuItem |
3192 | -from entertainerlib.frontend.gui.widgets.label import Label |
3193 | -from entertainerlib.frontend.gui.widgets.list_indicator import ListIndicator |
3194 | -from entertainerlib.frontend.gui.widgets.rounded_texture import RoundedTexture |
3195 | +from entertainerlib.gui.tabs.tab import Tab |
3196 | +from entertainerlib.gui.widgets.image_menu import ImageMenu |
3197 | +from entertainerlib.gui.widgets.image_menu_item import ImageMenuItem |
3198 | +from entertainerlib.gui.widgets.label import Label |
3199 | +from entertainerlib.gui.widgets.list_indicator import ListIndicator |
3200 | +from entertainerlib.gui.widgets.rounded_texture import RoundedTexture |
3201 | |
3202 | class VideoClipsTab(Tab): |
3203 | """ |
3204 | |
3205 | === renamed file 'entertainerlib/utils/theme.py' => 'entertainerlib/gui/theme.py' |
3206 | === modified file 'entertainerlib/gui/transitions/factory.py' |
3207 | --- entertainerlib/frontend/gui/transitions/factory.py 2009-02-07 17:12:21 +0000 |
3208 | +++ entertainerlib/gui/transitions/factory.py 2009-05-05 04:11:48 +0000 |
3209 | @@ -5,11 +5,11 @@ |
3210 | __copyright__ = '2009, Matt Layman' |
3211 | __author__ = 'Matt Layman <laymansterms.dev@gmail.com>' |
3212 | |
3213 | -from entertainerlib.frontend.gui.transitions.fade import Fade |
3214 | -from entertainerlib.frontend.gui.transitions.no_effect import NoEffect |
3215 | -from entertainerlib.frontend.gui.transitions.slide import Slide |
3216 | -from entertainerlib.frontend.gui.transitions.zoom_and_fade import ZoomAndFade |
3217 | -from entertainerlib.utils.configuration import Configuration |
3218 | +from entertainerlib.gui.transitions.fade import Fade |
3219 | +from entertainerlib.gui.transitions.no_effect import NoEffect |
3220 | +from entertainerlib.gui.transitions.slide import Slide |
3221 | +from entertainerlib.gui.transitions.zoom_and_fade import ZoomAndFade |
3222 | +from entertainerlib.configuration import Configuration |
3223 | |
3224 | class TransitionFactory: |
3225 | '''Generates a transition object based on the configuration setting''' |
3226 | |
3227 | === modified file 'entertainerlib/gui/transitions/fade.py' |
3228 | --- entertainerlib/frontend/gui/transitions/fade.py 2009-01-26 23:11:40 +0000 |
3229 | +++ entertainerlib/gui/transitions/fade.py 2009-05-05 03:31:34 +0000 |
3230 | @@ -5,7 +5,7 @@ |
3231 | __author__ = "Lauri Taimila <lauri@taimila.com>" |
3232 | |
3233 | import clutter |
3234 | -from entertainerlib.frontend.gui.transitions.transition import Transition |
3235 | +from entertainerlib.gui.transitions.transition import Transition |
3236 | |
3237 | class Fade(Transition): |
3238 | """ |
3239 | |
3240 | === modified file 'entertainerlib/gui/transitions/no_effect.py' |
3241 | --- entertainerlib/frontend/gui/transitions/no_effect.py 2009-01-26 23:11:40 +0000 |
3242 | +++ entertainerlib/gui/transitions/no_effect.py 2009-05-05 03:31:34 +0000 |
3243 | @@ -4,7 +4,7 @@ |
3244 | __copyright__ = "2007, Lauri Taimila" |
3245 | __author__ = "Lauri Taimila <lauri@taimila.com>" |
3246 | |
3247 | -from entertainerlib.frontend.gui.transitions.transition import Transition |
3248 | +from entertainerlib.gui.transitions.transition import Transition |
3249 | |
3250 | class NoEffect(Transition): |
3251 | """ |
3252 | |
3253 | === modified file 'entertainerlib/gui/transitions/slide.py' |
3254 | --- entertainerlib/frontend/gui/transitions/slide.py 2009-04-27 02:33:38 +0000 |
3255 | +++ entertainerlib/gui/transitions/slide.py 2009-05-05 04:11:48 +0000 |
3256 | @@ -6,8 +6,8 @@ |
3257 | |
3258 | import clutter |
3259 | |
3260 | -from entertainerlib.frontend.gui.transitions.transition import Transition |
3261 | -from entertainerlib.utils.configuration import Configuration |
3262 | +from entertainerlib.gui.transitions.transition import Transition |
3263 | +from entertainerlib.configuration import Configuration |
3264 | |
3265 | class Slide(Transition): |
3266 | '''Move screens on and off the stage through horizontal movements.''' |
3267 | |
3268 | === modified file 'entertainerlib/gui/transitions/zoom_and_fade.py' |
3269 | --- entertainerlib/frontend/gui/transitions/zoom_and_fade.py 2009-01-26 23:11:40 +0000 |
3270 | +++ entertainerlib/gui/transitions/zoom_and_fade.py 2009-05-05 03:31:34 +0000 |
3271 | @@ -5,7 +5,7 @@ |
3272 | __author__ = "Lauri Taimila <lauri@taimila.com>" |
3273 | |
3274 | import clutter |
3275 | -from entertainerlib.frontend.gui.transitions.transition import Transition |
3276 | +from entertainerlib.gui.transitions.transition import Transition |
3277 | |
3278 | class ZoomAndFade(Transition): |
3279 | """ |
3280 | |
3281 | === modified file 'entertainerlib/gui/user_interface.py' |
3282 | --- entertainerlib/frontend/gui/user_interface.py 2009-04-27 03:32:30 +0000 |
3283 | +++ entertainerlib/gui/user_interface.py 2009-05-05 04:24:32 +0000 |
3284 | @@ -1,4 +1,4 @@ |
3285 | -'''UserInterface - Main window of the Entertainer frontend''' |
3286 | +'''UserInterface - Main window of the Entertainer client''' |
3287 | |
3288 | # Clutter uses _1 to represent the 1 key and pylint complains about it |
3289 | # pylint: disable-msg=W0212 |
3290 | @@ -16,30 +16,30 @@ |
3291 | import gobject |
3292 | import gtk |
3293 | |
3294 | -from entertainerlib.frontend.gui.screen_history import ScreenHistory |
3295 | -from entertainerlib.frontend.gui.screens.factory import ScreenFactory |
3296 | -from entertainerlib.frontend.gui.screens.screen import Screen |
3297 | -from entertainerlib.frontend.gui.transitions.factory import TransitionFactory |
3298 | -from entertainerlib.frontend.gui.transitions.transition import Transition |
3299 | -from entertainerlib.frontend.gui.user_event import UserEvent |
3300 | -from entertainerlib.frontend.gui.widgets.menu_overlay import MenuOverlay |
3301 | -from entertainerlib.frontend.media_player import MediaPlayer |
3302 | -from entertainerlib.utils.configuration import Configuration |
3303 | -from entertainerlib.utils.logger import Logger |
3304 | +from entertainerlib.gui.screen_history import ScreenHistory |
3305 | +from entertainerlib.gui.screens.factory import ScreenFactory |
3306 | +from entertainerlib.gui.screens.screen import Screen |
3307 | +from entertainerlib.gui.transitions.factory import TransitionFactory |
3308 | +from entertainerlib.gui.transitions.transition import Transition |
3309 | +from entertainerlib.gui.user_event import UserEvent |
3310 | +from entertainerlib.gui.widgets.menu_overlay import MenuOverlay |
3311 | +from entertainerlib.client.media_player import MediaPlayer |
3312 | +from entertainerlib.configuration import Configuration |
3313 | +from entertainerlib.logger import Logger |
3314 | |
3315 | class UserInterface: |
3316 | '''A main GUI window of the Entertainer client.''' |
3317 | |
3318 | def __init__(self, feed_library, image_library, music_library, |
3319 | - video_library, quit_frontend_callback): |
3320 | - self.quit_frontend_callback = quit_frontend_callback |
3321 | + video_library, quit_client_callback): |
3322 | + self.quit_client_callback = quit_client_callback |
3323 | self.config = Configuration() |
3324 | |
3325 | # Store the dimensions in case users want to return to window mode |
3326 | self.old_width = self.config.get_stage_width() |
3327 | self.old_height = self.config.get_stage_height() |
3328 | |
3329 | - self.logger = Logger().getLogger('frontend.gui.UserInterface') |
3330 | + self.logger = Logger().getLogger('client.gui.UserInterface') |
3331 | |
3332 | self.window = gtk.Window() |
3333 | self.window.connect('destroy', self.destroy_callback) |
3334 | @@ -53,7 +53,7 @@ |
3335 | except gobject.GError: |
3336 | # Must not be installed from a package, get icon from the branch |
3337 | file_dir = os.path.dirname(__file__) |
3338 | - icon_path = os.path.join(file_dir, '..', '..', '..', 'icons', |
3339 | + icon_path = os.path.join(file_dir, '..', '..', 'icons', |
3340 | 'hicolor', '48x48', 'apps', 'entertainer.png') |
3341 | icon = gtk.gdk.pixbuf_new_from_file(icon_path) |
3342 | self.window.set_icon(icon) |
3343 | @@ -170,7 +170,7 @@ |
3344 | UserEvent.PLAYER_SKIP_FORWARD : self._handle_player_skip_forward, |
3345 | UserEvent.PLAYER_PREVIOUS : self._handle_player_previous, |
3346 | UserEvent.PLAYER_NEXT : self._handle_player_next, |
3347 | - UserEvent.QUIT_FRONTEND : self._handle_quit_frontend |
3348 | + UserEvent.QUIT_FRONTEND : self._handle_quit_client |
3349 | } |
3350 | |
3351 | self.logger.debug("Frontend GUI initialized succesfully") |
3352 | @@ -210,7 +210,7 @@ |
3353 | |
3354 | def shutdown(self): |
3355 | '''Shut down the user interface.''' |
3356 | - self.quit_frontend_callback() |
3357 | + self.quit_client_callback() |
3358 | |
3359 | def _toggle_fullscreen(self): |
3360 | '''Set the User Interface to fullscreen mode or back to window mode.''' |
3361 | @@ -384,7 +384,7 @@ |
3362 | '''Handle UserEvent.TOGGLE_FULLSCREEN.''' |
3363 | self._toggle_fullscreen() |
3364 | |
3365 | - def _handle_quit_frontend(self, event): |
3366 | + def _handle_quit_client(self, event): |
3367 | '''Handle UserEvent.QUIT_FRONTEND.''' |
3368 | self.confirm_exit() |
3369 | |
3370 | |
3371 | === modified file 'entertainerlib/gui/widgets/base.py' |
3372 | --- entertainerlib/frontend/gui/widgets/base.py 2009-03-08 03:16:25 +0000 |
3373 | +++ entertainerlib/gui/widgets/base.py 2009-05-05 04:11:48 +0000 |
3374 | @@ -4,7 +4,7 @@ |
3375 | __copyright__ = "2008, Matt Layman" |
3376 | __author__ = "Matt Layman <laymansterm.dev@gmail.com>" |
3377 | |
3378 | -from entertainerlib.utils.configuration import Configuration |
3379 | +from entertainerlib.configuration import Configuration |
3380 | |
3381 | class Base(object): |
3382 | """Inherited class that allows for transforms from relative to absolute for |
3383 | |
3384 | === modified file 'entertainerlib/gui/widgets/clock_label.py' |
3385 | --- entertainerlib/frontend/gui/widgets/clock_label.py 2008-11-29 22:44:32 +0000 |
3386 | +++ entertainerlib/gui/widgets/clock_label.py 2009-05-05 03:31:34 +0000 |
3387 | @@ -8,7 +8,7 @@ |
3388 | import time |
3389 | import gobject |
3390 | |
3391 | -from entertainerlib.frontend.gui.widgets.label import Label |
3392 | +from entertainerlib.gui.widgets.label import Label |
3393 | |
3394 | class ClockLabel(Label): |
3395 | """Label that displays current time.""" |
3396 | |
3397 | === modified file 'entertainerlib/gui/widgets/eyecandy_texture.py' |
3398 | --- entertainerlib/frontend/gui/widgets/eyecandy_texture.py 2008-11-17 21:54:45 +0000 |
3399 | +++ entertainerlib/gui/widgets/eyecandy_texture.py 2009-05-05 03:31:34 +0000 |
3400 | @@ -5,8 +5,8 @@ |
3401 | __author__ = "Lauri Taimila <lauri@taimila.com>" |
3402 | |
3403 | import clutter |
3404 | -from entertainerlib.frontend.gui.widgets.rounded_texture import RoundedTexture |
3405 | -from entertainerlib.frontend.gui.widgets.reflection_texture import ( |
3406 | +from entertainerlib.gui.widgets.rounded_texture import RoundedTexture |
3407 | +from entertainerlib.gui.widgets.reflection_texture import ( |
3408 | ReflectionTexture) |
3409 | |
3410 | class EyeCandyTexture(clutter.Group): |
3411 | |
3412 | === modified file 'entertainerlib/gui/widgets/image_menu.py' |
3413 | --- entertainerlib/frontend/gui/widgets/image_menu.py 2009-02-08 07:43:25 +0000 |
3414 | +++ entertainerlib/gui/widgets/image_menu.py 2009-05-05 04:11:48 +0000 |
3415 | @@ -6,8 +6,8 @@ |
3416 | |
3417 | import clutter |
3418 | |
3419 | -from entertainerlib.frontend.gui.widgets.grid_menu import GridMenu |
3420 | -from entertainerlib.utils.configuration import Configuration |
3421 | +from entertainerlib.gui.widgets.grid_menu import GridMenu |
3422 | +from entertainerlib.configuration import Configuration |
3423 | |
3424 | class ImageMenu(GridMenu): |
3425 | """ |
3426 | |
3427 | === modified file 'entertainerlib/gui/widgets/image_menu_item.py' |
3428 | --- entertainerlib/frontend/gui/widgets/image_menu_item.py 2009-01-11 00:25:55 +0000 |
3429 | +++ entertainerlib/gui/widgets/image_menu_item.py 2009-05-05 03:31:34 +0000 |
3430 | @@ -5,7 +5,7 @@ |
3431 | __author__ = ("Lauri Taimila <lauri@taimila.com>", |
3432 | "Matt Layman <laymansterms.dev@gmail.com>") |
3433 | |
3434 | -from entertainerlib.frontend.gui.widgets.menu_item import MenuItem |
3435 | +from entertainerlib.gui.widgets.menu_item import MenuItem |
3436 | |
3437 | class ImageMenuItem(MenuItem): |
3438 | """ |
3439 | |
3440 | === modified file 'entertainerlib/gui/widgets/label.py' |
3441 | --- entertainerlib/frontend/gui/widgets/label.py 2009-03-08 03:16:25 +0000 |
3442 | +++ entertainerlib/gui/widgets/label.py 2009-05-05 03:31:34 +0000 |
3443 | @@ -6,7 +6,7 @@ |
3444 | |
3445 | import clutter |
3446 | |
3447 | -from entertainerlib.frontend.gui.widgets.base import Base |
3448 | +from entertainerlib.gui.widgets.base import Base |
3449 | |
3450 | class Label(Base, clutter.Label): |
3451 | """Wrapper of a clutter label to encapsulate some label settings and have |
3452 | |
3453 | === modified file 'entertainerlib/gui/widgets/list_indicator.py' |
3454 | --- entertainerlib/frontend/gui/widgets/list_indicator.py 2008-11-17 21:53:05 +0000 |
3455 | +++ entertainerlib/gui/widgets/list_indicator.py 2009-05-05 04:11:48 +0000 |
3456 | @@ -6,9 +6,9 @@ |
3457 | |
3458 | import clutter |
3459 | |
3460 | -from entertainerlib.frontend.gui.widgets.arrow_texture import ArrowTexture |
3461 | -from entertainerlib.frontend.gui.widgets.label import Label |
3462 | -from entertainerlib.utils.configuration import Configuration |
3463 | +from entertainerlib.gui.widgets.arrow_texture import ArrowTexture |
3464 | +from entertainerlib.gui.widgets.label import Label |
3465 | +from entertainerlib.configuration import Configuration |
3466 | |
3467 | class ListIndicator(clutter.Group): |
3468 | """ |
3469 | |
3470 | === modified file 'entertainerlib/gui/widgets/menu_item.py' |
3471 | --- entertainerlib/frontend/gui/widgets/menu_item.py 2009-01-11 00:25:55 +0000 |
3472 | +++ entertainerlib/gui/widgets/menu_item.py 2009-05-05 03:31:34 +0000 |
3473 | @@ -6,7 +6,7 @@ |
3474 | |
3475 | import clutter |
3476 | |
3477 | -from entertainerlib.frontend.gui.widgets.base import Base |
3478 | +from entertainerlib.gui.widgets.base import Base |
3479 | |
3480 | class MenuItem(Base, clutter.Group): |
3481 | """ |
3482 | |
3483 | === modified file 'entertainerlib/gui/widgets/menu_overlay.py' |
3484 | --- entertainerlib/frontend/gui/widgets/menu_overlay.py 2008-11-17 11:20:47 +0000 |
3485 | +++ entertainerlib/gui/widgets/menu_overlay.py 2009-05-05 03:31:34 +0000 |
3486 | @@ -6,7 +6,7 @@ |
3487 | |
3488 | import clutter |
3489 | |
3490 | -from entertainerlib.frontend.gui.widgets.texture import Texture |
3491 | +from entertainerlib.gui.widgets.texture import Texture |
3492 | |
3493 | class MenuOverlay(Texture): |
3494 | """ |
3495 | |
3496 | === modified file 'entertainerlib/gui/widgets/scroll_area.py' |
3497 | --- entertainerlib/frontend/gui/widgets/scroll_area.py 2009-03-08 03:16:25 +0000 |
3498 | +++ entertainerlib/gui/widgets/scroll_area.py 2009-05-05 03:31:34 +0000 |
3499 | @@ -6,8 +6,8 @@ |
3500 | |
3501 | import clutter |
3502 | |
3503 | -from entertainerlib.frontend.gui.widgets.base import Base |
3504 | -from entertainerlib.frontend.gui.widgets.list_indicator import ListIndicator |
3505 | +from entertainerlib.gui.widgets.base import Base |
3506 | +from entertainerlib.gui.widgets.list_indicator import ListIndicator |
3507 | |
3508 | class ScrollArea(Base, clutter.Group): |
3509 | """Wrapper of a clutter Group that allows for scrolling. ScrollArea |
3510 | |
3511 | === modified file 'entertainerlib/gui/widgets/selector.py' |
3512 | --- entertainerlib/frontend/gui/widgets/selector.py 2008-11-26 11:20:54 +0000 |
3513 | +++ entertainerlib/gui/widgets/selector.py 2009-05-05 03:31:34 +0000 |
3514 | @@ -6,7 +6,7 @@ |
3515 | |
3516 | import clutter |
3517 | |
3518 | -from entertainerlib.frontend.gui.widgets.texture import Texture |
3519 | +from entertainerlib.gui.widgets.texture import Texture |
3520 | |
3521 | class Selector(clutter.Group): |
3522 | """ |
3523 | |
3524 | === modified file 'entertainerlib/gui/widgets/tab_group.py' |
3525 | --- entertainerlib/frontend/gui/widgets/tab_group.py 2009-02-27 00:01:53 +0000 |
3526 | +++ entertainerlib/gui/widgets/tab_group.py 2009-05-05 04:11:48 +0000 |
3527 | @@ -7,9 +7,9 @@ |
3528 | import clutter |
3529 | import pango |
3530 | |
3531 | -from entertainerlib.frontend.gui.widgets.label import Label |
3532 | -from entertainerlib.frontend.gui.user_event import UserEvent |
3533 | -from entertainerlib.utils.configuration import Configuration |
3534 | +from entertainerlib.gui.widgets.label import Label |
3535 | +from entertainerlib.gui.user_event import UserEvent |
3536 | +from entertainerlib.configuration import Configuration |
3537 | |
3538 | class TabGroup(clutter.Group): |
3539 | """ |
3540 | |
3541 | === modified file 'entertainerlib/gui/widgets/text_menu.py' |
3542 | --- entertainerlib/frontend/gui/widgets/text_menu.py 2009-02-08 07:43:25 +0000 |
3543 | +++ entertainerlib/gui/widgets/text_menu.py 2009-05-05 03:31:34 +0000 |
3544 | @@ -4,8 +4,8 @@ |
3545 | __copyright__ = "2007, Lauri Taimila" |
3546 | __author__ = "Lauri Taimila <lauri@taimila.com>" |
3547 | |
3548 | -from entertainerlib.frontend.gui.widgets.selector import Selector |
3549 | -from entertainerlib.frontend.gui.widgets.grid_menu import GridMenu |
3550 | +from entertainerlib.gui.widgets.selector import Selector |
3551 | +from entertainerlib.gui.widgets.grid_menu import GridMenu |
3552 | |
3553 | class TextMenu(GridMenu): |
3554 | """ |
3555 | |
3556 | === modified file 'entertainerlib/gui/widgets/text_menu_item.py' |
3557 | --- entertainerlib/frontend/gui/widgets/text_menu_item.py 2008-11-25 23:20:28 +0000 |
3558 | +++ entertainerlib/gui/widgets/text_menu_item.py 2009-05-05 03:31:34 +0000 |
3559 | @@ -7,8 +7,8 @@ |
3560 | import pango |
3561 | import clutter |
3562 | |
3563 | -from entertainerlib.frontend.gui.widgets.label import Label |
3564 | -from entertainerlib.frontend.gui.widgets.menu_item import MenuItem |
3565 | +from entertainerlib.gui.widgets.label import Label |
3566 | +from entertainerlib.gui.widgets.menu_item import MenuItem |
3567 | |
3568 | class TextMenuItem(MenuItem): |
3569 | """ |
3570 | |
3571 | === modified file 'entertainerlib/gui/widgets/texture.py' |
3572 | --- entertainerlib/frontend/gui/widgets/texture.py 2009-03-08 03:16:25 +0000 |
3573 | +++ entertainerlib/gui/widgets/texture.py 2009-05-05 04:24:32 +0000 |
3574 | @@ -6,8 +6,8 @@ |
3575 | |
3576 | import clutter |
3577 | |
3578 | -from entertainerlib.frontend.gui.widgets.base import Base |
3579 | -from entertainerlib.utils.logger import Logger |
3580 | +from entertainerlib.gui.widgets.base import Base |
3581 | +from entertainerlib.logger import Logger |
3582 | |
3583 | class Texture(Base, clutter.Texture): |
3584 | """Wrapper of a clutter texture to encapsulate position settings and have |
3585 | @@ -19,7 +19,7 @@ |
3586 | |
3587 | Base.__init__(self) |
3588 | clutter.Texture.__init__(self, filename) |
3589 | - self.logger = Logger().getLogger('frontend.gui.widgets.Texture') |
3590 | + self.logger = Logger().getLogger('client.gui.widgets.Texture') |
3591 | |
3592 | self._position = None |
3593 | self._set_position((x_pos_percent, y_pos_percent)) |
3594 | |
3595 | === renamed file 'entertainerlib/utils/logger.py' => 'entertainerlib/logger.py' |
3596 | --- entertainerlib/utils/logger.py 2009-01-11 02:26:45 +0000 |
3597 | +++ entertainerlib/logger.py 2009-05-05 04:24:32 +0000 |
3598 | @@ -6,7 +6,7 @@ |
3599 | |
3600 | import logging |
3601 | |
3602 | -from entertainerlib.utils.configuration import Configuration |
3603 | +from entertainerlib.configuration import Configuration |
3604 | |
3605 | class Logger: |
3606 | '''Logger to record behind the scenes information. |
3607 | |
3608 | === modified file 'entertainerlib/network/__init__.py' |
3609 | --- entertainerlib/network/__init__.py 2009-04-04 05:30:04 +0000 |
3610 | +++ entertainerlib/network/__init__.py 2009-04-30 01:11:22 +0000 |
3611 | @@ -26,7 +26,7 @@ |
3612 | def client_main(): |
3613 | '''Entertainer test client code. |
3614 | |
3615 | - This code will go away when what is now the frontend is made into a true |
3616 | + This code will go away when what is now the client is made into a true |
3617 | client. |
3618 | ''' |
3619 | startLogging(sys.stdout) |
3620 | |
3621 | === modified file 'entertainerlib/tests/__init__.py' |
3622 | --- entertainerlib/tests/__init__.py 2009-02-06 07:23:29 +0000 |
3623 | +++ entertainerlib/tests/__init__.py 2009-05-05 04:11:48 +0000 |
3624 | @@ -5,9 +5,9 @@ |
3625 | from storm.locals import Store |
3626 | import testtools |
3627 | |
3628 | -from entertainerlib.backend.core.db.connection import Database |
3629 | -from entertainerlib.frontend.translation_setup import TranslationSetup |
3630 | -from entertainerlib.utils.configuration import Configuration |
3631 | +from entertainerlib.db.connection import Database |
3632 | +from entertainerlib.client.translation_setup import TranslationSetup |
3633 | +from entertainerlib.configuration import Configuration |
3634 | |
3635 | TranslationSetup() |
3636 | |
3637 | |
3638 | === modified file 'entertainerlib/tests/mock.py' |
3639 | --- entertainerlib/tests/mock.py 2009-02-27 02:16:34 +0000 |
3640 | +++ entertainerlib/tests/mock.py 2009-04-30 01:11:22 +0000 |
3641 | @@ -1,23 +1,23 @@ |
3642 | '''Test mock objects''' |
3643 | # pylint: disable-msg=W0231 |
3644 | |
3645 | -from entertainerlib.frontend.backend_connection import BackendConnection |
3646 | -from entertainerlib.frontend.media_player import MediaPlayer |
3647 | -from entertainerlib.frontend.medialibrary.feeds import Entry |
3648 | -from entertainerlib.frontend.medialibrary.feeds import Feed |
3649 | -from entertainerlib.frontend.medialibrary.feeds import FeedLibrary |
3650 | -from entertainerlib.frontend.medialibrary.images import Image |
3651 | -from entertainerlib.frontend.medialibrary.images import ImageLibrary |
3652 | -from entertainerlib.frontend.medialibrary.music import Album |
3653 | -from entertainerlib.frontend.medialibrary.music import MusicLibrary |
3654 | -from entertainerlib.frontend.medialibrary.music import Track |
3655 | -from entertainerlib.frontend.medialibrary.videos import Movie |
3656 | -from entertainerlib.frontend.medialibrary.videos import TVEpisode |
3657 | -from entertainerlib.frontend.medialibrary.videos import TVSeries |
3658 | -from entertainerlib.frontend.medialibrary.videos import VideoLibrary |
3659 | +from entertainerlib.client.backend_connection import BackendConnection |
3660 | +from entertainerlib.client.media_player import MediaPlayer |
3661 | +from entertainerlib.client.medialibrary.feeds import Entry |
3662 | +from entertainerlib.client.medialibrary.feeds import Feed |
3663 | +from entertainerlib.client.medialibrary.feeds import FeedLibrary |
3664 | +from entertainerlib.client.medialibrary.images import Image |
3665 | +from entertainerlib.client.medialibrary.images import ImageLibrary |
3666 | +from entertainerlib.client.medialibrary.music import Album |
3667 | +from entertainerlib.client.medialibrary.music import MusicLibrary |
3668 | +from entertainerlib.client.medialibrary.music import Track |
3669 | +from entertainerlib.client.medialibrary.videos import Movie |
3670 | +from entertainerlib.client.medialibrary.videos import TVEpisode |
3671 | +from entertainerlib.client.medialibrary.videos import TVSeries |
3672 | +from entertainerlib.client.medialibrary.videos import VideoLibrary |
3673 | |
3674 | class MockAlbum(Album): |
3675 | - '''Mock entertainerlib.frontend.medialibrary.music.Album''' |
3676 | + '''Mock entertainerlib.client.medialibrary.music.Album''' |
3677 | |
3678 | def __init__(self, title=None, cursor=None, make_track=True): |
3679 | self.title = 'Ganging Up on the Sun' |
3680 | @@ -43,7 +43,7 @@ |
3681 | |
3682 | |
3683 | class MockBackendConnection(BackendConnection): |
3684 | - '''Mock entertainerlib.frontend.backend_connection.BackendConnection''' |
3685 | + '''Mock entertainerlib.client.backend_connection.BackendConnection''' |
3686 | |
3687 | def __init__(self): |
3688 | '''Override init to prevent BackenConnection from attempting to connect |
3689 | @@ -67,7 +67,7 @@ |
3690 | |
3691 | |
3692 | class MockEntry(Entry): |
3693 | - '''Mock entertainerlib.frontend.medialibrary.feeds.Entry''' |
3694 | + '''Mock entertainerlib.client.medialibrary.feeds.Entry''' |
3695 | |
3696 | def __init__(self, title=None, description=None, identifier=None, |
3697 | time=None, date=None, read=False): |
3698 | @@ -81,7 +81,7 @@ |
3699 | |
3700 | |
3701 | class MockFeed(Feed): |
3702 | - '''Mock entertainerlib.frontend.medialibrary.feeds.Feed''' |
3703 | + '''Mock entertainerlib.client.medialibrary.feeds.Feed''' |
3704 | |
3705 | def __init__(self, url=None): |
3706 | self.date = 'January 31st' |
3707 | @@ -95,7 +95,7 @@ |
3708 | |
3709 | |
3710 | class MockFeedLibrary(FeedLibrary): |
3711 | - '''Mock entertainerlib.frontend.medialibrary.feeds.FeedLibrary''' |
3712 | + '''Mock entertainerlib.client.medialibrary.feeds.FeedLibrary''' |
3713 | |
3714 | def __init__(self, backend_connection=None): |
3715 | '''Override the intial behavior.''' |
3716 | @@ -106,7 +106,7 @@ |
3717 | |
3718 | |
3719 | class MockImage(Image): |
3720 | - '''Mock entertainerlib.frontend.medialibrary.images.Image''' |
3721 | + '''Mock entertainerlib.client.medialibrary.images.Image''' |
3722 | |
3723 | def __init__(self, filename=None, album_path=None, title=None, |
3724 | description=None, date=None, time=None, width=None, height=None, |
3725 | @@ -117,7 +117,7 @@ |
3726 | |
3727 | |
3728 | class MockImageLibrary(ImageLibrary): |
3729 | - '''Mock entertainerlib.frontend.medialibrary.images.ImageLibrary''' |
3730 | + '''Mock entertainerlib.client.medialibrary.images.ImageLibrary''' |
3731 | |
3732 | def __init__(self, backend_connection=None): |
3733 | '''Override the intial behavior.''' |
3734 | @@ -128,7 +128,7 @@ |
3735 | |
3736 | |
3737 | class MockMediaPlayer(MediaPlayer): |
3738 | - '''Mock entertainerlib.frontend.media_player.MediaPlayer''' |
3739 | + '''Mock entertainerlib.client.media_player.MediaPlayer''' |
3740 | |
3741 | def __init__(self, stage=None, width=None, height=None): |
3742 | '''Override any actual media player set up.''' |
3743 | @@ -149,7 +149,7 @@ |
3744 | |
3745 | |
3746 | class MockMovie(Movie): |
3747 | - '''Mock entertainerlib.frontend.medialibrary.videos.Movie''' |
3748 | + '''Mock entertainerlib.client.medialibrary.videos.Movie''' |
3749 | |
3750 | def __init__(self, filename=None): |
3751 | '''Override init to prevent a database connection''' |
3752 | @@ -195,7 +195,7 @@ |
3753 | return False |
3754 | |
3755 | class MockMusicLibrary(MusicLibrary): |
3756 | - '''Mock entertainerlib.frontend.medialibrary.music.MusicLibrary''' |
3757 | + '''Mock entertainerlib.client.medialibrary.music.MusicLibrary''' |
3758 | |
3759 | def __init__(self, backend_connection=None): |
3760 | '''Override the intial behavior.''' |
3761 | @@ -222,7 +222,7 @@ |
3762 | |
3763 | |
3764 | class MockTVEpisode(TVEpisode): |
3765 | - '''Mock entertainerlib.frontend.medialibrary.videos.TVEpisode''' |
3766 | + '''Mock entertainerlib.client.medialibrary.videos.TVEpisode''' |
3767 | |
3768 | def __init__(self, title=None): |
3769 | '''Override init to prevent a database connection''' |
3770 | @@ -245,7 +245,7 @@ |
3771 | |
3772 | |
3773 | class MockTVSeries(TVSeries): |
3774 | - '''Mock entertainerlib.frontend.medialibrary.videos.TVSeries''' |
3775 | + '''Mock entertainerlib.client.medialibrary.videos.TVSeries''' |
3776 | |
3777 | def __init__(self, title=None): |
3778 | '''Override init to prevent a database connection''' |
3779 | @@ -268,7 +268,7 @@ |
3780 | return False |
3781 | |
3782 | class MockTrack(Track): |
3783 | - '''Mock entertainerlib.frontend.medialibrary.music.Track''' |
3784 | + '''Mock entertainerlib.client.medialibrary.music.Track''' |
3785 | |
3786 | def __init__(self, filename=None, title=None, tracknumber=None, artist=None, |
3787 | album=None, genre=None, bitrate=None, year=None, rating=None, |
3788 | @@ -287,7 +287,7 @@ |
3789 | |
3790 | |
3791 | class MockVideoLibrary(VideoLibrary): |
3792 | - '''Mock entertainerlib.frontend.medialibrary.videos.VideoLibrary''' |
3793 | + '''Mock entertainerlib.client.medialibrary.videos.VideoLibrary''' |
3794 | |
3795 | def __init__(self, backend_connection=None): |
3796 | '''Override the intial behavior.''' |
3797 | |
3798 | === modified file 'entertainerlib/tests/test_base.py' |
3799 | --- entertainerlib/tests/test_base.py 2009-03-08 03:16:25 +0000 |
3800 | +++ entertainerlib/tests/test_base.py 2009-05-05 03:31:34 +0000 |
3801 | @@ -4,11 +4,11 @@ |
3802 | __copyright__ = "2008, Matt Layman" |
3803 | __author__ = "Matt Layman <laymansterms.dev@gmail.com>" |
3804 | |
3805 | -from entertainerlib.frontend.gui.widgets.base import Base |
3806 | +from entertainerlib.gui.widgets.base import Base |
3807 | from entertainerlib.tests import EntertainerTest |
3808 | |
3809 | class BaseTest(EntertainerTest): |
3810 | - """Test for entertainerlib.frontend.gui.widgets.base""" |
3811 | + """Test for entertainerlib.gui.widgets.base""" |
3812 | |
3813 | def setUp(self): |
3814 | """Set up the test""" |
3815 | |
3816 | === modified file 'entertainerlib/tests/test_configuration.py' |
3817 | --- entertainerlib/tests/test_configuration.py 2009-03-08 03:16:25 +0000 |
3818 | +++ entertainerlib/tests/test_configuration.py 2009-05-05 04:11:48 +0000 |
3819 | @@ -8,7 +8,7 @@ |
3820 | import os |
3821 | |
3822 | from entertainerlib.tests import EntertainerTest |
3823 | -from entertainerlib.utils.configuration import Configuration |
3824 | +from entertainerlib.configuration import Configuration |
3825 | |
3826 | class ConfigurationTest(EntertainerTest): |
3827 | '''Test for utils.configuration''' |
3828 | |
3829 | === modified file 'entertainerlib/tests/test_database.py' |
3830 | --- entertainerlib/tests/test_database.py 2009-01-31 21:36:56 +0000 |
3831 | +++ entertainerlib/tests/test_database.py 2009-05-05 03:35:28 +0000 |
3832 | @@ -8,7 +8,7 @@ |
3833 | |
3834 | from storm.locals import Store |
3835 | |
3836 | -from entertainerlib.backend.core.db.connection import Database, SCHEMA |
3837 | +from entertainerlib.db.connection import Database, SCHEMA |
3838 | from entertainerlib.tests import EntertainerTestWithDatabase |
3839 | |
3840 | class DatabaseTest(EntertainerTestWithDatabase): |
3841 | |
3842 | === modified file 'entertainerlib/tests/test_feedconfigtools.py' |
3843 | --- entertainerlib/tests/test_feedconfigtools.py 2009-02-08 07:01:25 +0000 |
3844 | +++ entertainerlib/tests/test_feedconfigtools.py 2009-05-06 04:00:53 +0000 |
3845 | @@ -9,14 +9,17 @@ |
3846 | import gtk |
3847 | import gtk.glade |
3848 | |
3849 | -from entertainerlib.utils.feed_utils import FeedConfigTools |
3850 | +from entertainerlib.backend.components.feeds.feed_utils import FeedConfigTools |
3851 | from entertainerlib.tests import EntertainerTest |
3852 | |
3853 | THIS_DIR = os.path.dirname(__file__) |
3854 | |
3855 | |
3856 | class FeedConfigToolsTest(EntertainerTest): |
3857 | - '''Test for entertainerlib.utils.feed_utils FeedConfigTools''' |
3858 | + # pylint: disable-msg=C0301 |
3859 | + # This pylint warning can be removed when the backend stuff gets removed, |
3860 | + # and the pieces we keep get rearranged. |
3861 | + '''Test for entertainerlib.backend.components.feeds.feed_utils.FeedConfigTools''' |
3862 | |
3863 | def setUp(self): |
3864 | """Sets up everything for the test""" |
3865 | |
3866 | === modified file 'entertainerlib/tests/test_feedentryparser.py' |
3867 | --- entertainerlib/tests/test_feedentryparser.py 2009-02-08 07:01:25 +0000 |
3868 | +++ entertainerlib/tests/test_feedentryparser.py 2009-05-06 04:00:53 +0000 |
3869 | @@ -7,7 +7,7 @@ |
3870 | |
3871 | import unittest |
3872 | |
3873 | -from entertainerlib.utils.feed_utils import FeedEntryParser |
3874 | +from entertainerlib.backend.components.feeds.feed_utils import FeedEntryParser |
3875 | |
3876 | |
3877 | class FeedEntryParserTest(unittest.TestCase): |
3878 | |
3879 | === modified file 'entertainerlib/tests/test_frontendfeed.py' |
3880 | --- entertainerlib/tests/test_frontendfeed.py 2009-01-31 21:36:56 +0000 |
3881 | +++ entertainerlib/tests/test_frontendfeed.py 2009-04-30 01:11:22 +0000 |
3882 | @@ -1,4 +1,4 @@ |
3883 | -'''Tests feeds from the frontend''' |
3884 | +'''Tests feeds from the client''' |
3885 | |
3886 | __licence__ = "GPLv2" |
3887 | __copyright__ = "2008, Joshua Scotton" |
3888 | @@ -6,11 +6,11 @@ |
3889 | |
3890 | from pysqlite2 import dbapi2 as sqlite |
3891 | |
3892 | -from entertainerlib.frontend.medialibrary.feeds import Feed |
3893 | +from entertainerlib.client.medialibrary.feeds import Feed |
3894 | from entertainerlib.tests import EntertainerTest |
3895 | |
3896 | class FrontendFeedTest(EntertainerTest): |
3897 | - '''Test reading feeds from the frontend''' |
3898 | + '''Test reading feeds from the client''' |
3899 | |
3900 | def setUp(self): |
3901 | """Sets up everything for the test""" |
3902 | |
3903 | === modified file 'entertainerlib/tests/test_frontendfeedentry.py' |
3904 | --- entertainerlib/tests/test_frontendfeedentry.py 2009-02-06 08:33:50 +0000 |
3905 | +++ entertainerlib/tests/test_frontendfeedentry.py 2009-04-30 01:11:22 +0000 |
3906 | @@ -1,4 +1,4 @@ |
3907 | -'''Tests feed entries on the frontend''' |
3908 | +'''Tests feed entries on the client''' |
3909 | # pylint: disable-msg=W0212 |
3910 | |
3911 | __licence__ = "GPLv2" |
3912 | @@ -7,11 +7,11 @@ |
3913 | |
3914 | from pysqlite2 import dbapi2 as sqlite |
3915 | |
3916 | -from entertainerlib.frontend.medialibrary.feeds import Feed, Entry |
3917 | +from entertainerlib.client.medialibrary.feeds import Feed, Entry |
3918 | from entertainerlib.tests import EntertainerTest |
3919 | |
3920 | class FrontendFeedEntryTest(EntertainerTest): |
3921 | - '''Tests feed entries on the frontend''' |
3922 | + '''Tests feed entries on the client''' |
3923 | |
3924 | entry_title = "Test Entry" |
3925 | entry_desc = "This is a test description" |
3926 | |
3927 | === modified file 'entertainerlib/tests/test_frontendfeedlibrary.py' |
3928 | --- entertainerlib/tests/test_frontendfeedlibrary.py 2009-02-04 04:17:37 +0000 |
3929 | +++ entertainerlib/tests/test_frontendfeedlibrary.py 2009-04-30 01:11:22 +0000 |
3930 | @@ -1,4 +1,4 @@ |
3931 | -'''Tests feed library from the frontend''' |
3932 | +'''Tests feed library from the client''' |
3933 | |
3934 | __licence__ = "GPLv2" |
3935 | __copyright__ = "2008, Joshua Scotton" |
3936 | @@ -6,13 +6,13 @@ |
3937 | |
3938 | from pysqlite2 import dbapi2 as sqlite |
3939 | |
3940 | -from entertainerlib.frontend.medialibrary.feeds import FeedLibrary |
3941 | +from entertainerlib.client.medialibrary.feeds import FeedLibrary |
3942 | from entertainerlib.tests import EntertainerTest |
3943 | from entertainerlib.tests.mock import MockBackendConnection |
3944 | |
3945 | class FrontendFeedLibraryTest(EntertainerTest): |
3946 | """ |
3947 | - Tests the frontend.medialibrary.feeds.FeedLibrary object |
3948 | + Tests the client.medialibrary.feeds.FeedLibrary object |
3949 | @todo comment tests |
3950 | @todo the test database doesn't seem to be working |
3951 | """ |
3952 | |
3953 | === modified file 'entertainerlib/tests/test_imagemenuitem.py' |
3954 | --- entertainerlib/tests/test_imagemenuitem.py 2009-02-06 08:33:50 +0000 |
3955 | +++ entertainerlib/tests/test_imagemenuitem.py 2009-05-05 03:31:34 +0000 |
3956 | @@ -7,14 +7,14 @@ |
3957 | |
3958 | import os |
3959 | |
3960 | -from entertainerlib.frontend.gui.widgets.image_menu_item import ImageMenuItem |
3961 | -from entertainerlib.frontend.gui.widgets.texture import Texture |
3962 | +from entertainerlib.gui.widgets.image_menu_item import ImageMenuItem |
3963 | +from entertainerlib.gui.widgets.texture import Texture |
3964 | from entertainerlib.tests import EntertainerTest |
3965 | |
3966 | THIS_DIR = os.path.dirname(__file__) |
3967 | |
3968 | class ImageMenuItemTest(EntertainerTest): |
3969 | - """Test for entertainerlib.frontend.gui.widgets.image_menu_item""" |
3970 | + """Test for entertainerlib.gui.widgets.image_menu_item""" |
3971 | |
3972 | def setUp(self): |
3973 | """Set up the test""" |
3974 | |
3975 | === modified file 'entertainerlib/tests/test_label.py' |
3976 | --- entertainerlib/tests/test_label.py 2009-02-06 08:33:50 +0000 |
3977 | +++ entertainerlib/tests/test_label.py 2009-05-05 03:31:34 +0000 |
3978 | @@ -7,12 +7,12 @@ |
3979 | |
3980 | import clutter |
3981 | |
3982 | -from entertainerlib.frontend.gui.widgets.base import Base |
3983 | -from entertainerlib.frontend.gui.widgets.label import Label |
3984 | +from entertainerlib.gui.widgets.base import Base |
3985 | +from entertainerlib.gui.widgets.label import Label |
3986 | from entertainerlib.tests import EntertainerTest |
3987 | |
3988 | class LabelTest(EntertainerTest): |
3989 | - """Test for entertainerlib.frontend.gui.widgets.label""" |
3990 | + """Test for entertainerlib.gui.widgets.label""" |
3991 | |
3992 | def setUp(self): |
3993 | """Set up the test""" |
3994 | |
3995 | === modified file 'entertainerlib/tests/test_logger.py' |
3996 | --- entertainerlib/tests/test_logger.py 2009-01-31 21:36:56 +0000 |
3997 | +++ entertainerlib/tests/test_logger.py 2009-05-05 04:24:32 +0000 |
3998 | @@ -7,7 +7,7 @@ |
3999 | import logging |
4000 | |
4001 | from entertainerlib.tests import EntertainerTest |
4002 | -from entertainerlib.utils.logger import Logger |
4003 | +from entertainerlib.logger import Logger |
4004 | |
4005 | class TestLogger(EntertainerTest): |
4006 | '''Logger test case''' |
4007 | |
4008 | === modified file 'entertainerlib/tests/test_lyricsdownloader.py' |
4009 | --- entertainerlib/tests/test_lyricsdownloader.py 2009-02-06 08:33:50 +0000 |
4010 | +++ entertainerlib/tests/test_lyricsdownloader.py 2009-05-06 04:46:51 +0000 |
4011 | @@ -9,7 +9,7 @@ |
4012 | import os |
4013 | import urllib |
4014 | |
4015 | -from entertainerlib.utils.lyrics_downloader import LyricsDownloader |
4016 | +from entertainerlib.download import LyricsDownloader |
4017 | |
4018 | THIS_DIR = os.path.dirname(__file__) |
4019 | |
4020 | |
4021 | === modified file 'entertainerlib/tests/test_models.py' |
4022 | --- entertainerlib/tests/test_models.py 2009-01-31 21:36:56 +0000 |
4023 | +++ entertainerlib/tests/test_models.py 2009-05-05 03:35:28 +0000 |
4024 | @@ -6,7 +6,7 @@ |
4025 | |
4026 | from storm.locals import Store |
4027 | |
4028 | -from entertainerlib.backend.core.db import models |
4029 | +from entertainerlib.db import models |
4030 | from entertainerlib.tests import EntertainerTestWithDatabase |
4031 | |
4032 | |
4033 | |
4034 | === modified file 'entertainerlib/tests/test_music.py' |
4035 | --- entertainerlib/tests/test_music.py 2009-02-14 15:26:32 +0000 |
4036 | +++ entertainerlib/tests/test_music.py 2009-04-30 01:11:22 +0000 |
4037 | @@ -8,11 +8,11 @@ |
4038 | |
4039 | from pysqlite2 import dbapi2 as sqlite |
4040 | |
4041 | -from entertainerlib.frontend.medialibrary.music import ( |
4042 | +from entertainerlib.client.medialibrary.music import ( |
4043 | Album, AlbumHasNoTracks, MusicLibrary, Track, CompactDisc, |
4044 | TrackRatingOutOfRange, TrackTypeError) |
4045 | from entertainerlib.tests.mock import MockBackendConnection |
4046 | -from entertainerlib.frontend.medialibrary.playable import Playable |
4047 | +from entertainerlib.client.medialibrary.playable import Playable |
4048 | from entertainerlib.tests import EntertainerTest |
4049 | |
4050 | class TestMusic(EntertainerTest): |
4051 | |
4052 | === modified file 'entertainerlib/tests/test_opmlparser.py' |
4053 | --- entertainerlib/tests/test_opmlparser.py 2009-02-08 07:01:25 +0000 |
4054 | +++ entertainerlib/tests/test_opmlparser.py 2009-05-06 04:00:53 +0000 |
4055 | @@ -9,7 +9,7 @@ |
4056 | import os |
4057 | import xml.parsers.expat |
4058 | |
4059 | -from entertainerlib.utils.feed_utils import OPMLParser |
4060 | +from entertainerlib.backend.components.feeds.feed_utils import OPMLParser |
4061 | |
4062 | THIS_DIR = os.path.dirname(__file__) |
4063 | |
4064 | |
4065 | === modified file 'entertainerlib/tests/test_screen.py' |
4066 | --- entertainerlib/tests/test_screen.py 2009-04-27 23:12:40 +0000 |
4067 | +++ entertainerlib/tests/test_screen.py 2009-05-05 03:31:34 +0000 |
4068 | @@ -7,15 +7,15 @@ |
4069 | import clutter |
4070 | |
4071 | from entertainerlib.exceptions import ScreenException |
4072 | -from entertainerlib.frontend.gui.screens.screen import Screen |
4073 | -from entertainerlib.frontend.gui.tabs.tab import Tab |
4074 | -from entertainerlib.frontend.gui.user_event import UserEvent |
4075 | -from entertainerlib.frontend.gui.widgets.base import Base |
4076 | -from entertainerlib.frontend.gui.widgets.tab_group import TabGroup |
4077 | +from entertainerlib.gui.screens.screen import Screen |
4078 | +from entertainerlib.gui.tabs.tab import Tab |
4079 | +from entertainerlib.gui.user_event import UserEvent |
4080 | +from entertainerlib.gui.widgets.base import Base |
4081 | +from entertainerlib.gui.widgets.tab_group import TabGroup |
4082 | from entertainerlib.tests import EntertainerTest |
4083 | |
4084 | class ScreenTest(EntertainerTest): |
4085 | - '''Test for entertainerlib.frontend.gui.screens.screen''' |
4086 | + """Test for entertainerlib.gui.screens.screen""" |
4087 | |
4088 | def setUp(self): |
4089 | '''Set up the test.''' |
4090 | |
4091 | === modified file 'entertainerlib/tests/test_screenfactory.py' |
4092 | --- entertainerlib/tests/test_screenfactory.py 2009-02-06 08:33:50 +0000 |
4093 | +++ entertainerlib/tests/test_screenfactory.py 2009-05-05 03:31:34 +0000 |
4094 | @@ -7,26 +7,26 @@ |
4095 | |
4096 | import os |
4097 | |
4098 | -from entertainerlib.frontend.gui.screens.album import Album |
4099 | -from entertainerlib.frontend.gui.screens.artist import Artist |
4100 | -from entertainerlib.frontend.gui.screens.audio_play import AudioPlay |
4101 | -from entertainerlib.frontend.gui.screens.disc import Disc |
4102 | -from entertainerlib.frontend.gui.screens.factory import ScreenFactory |
4103 | -from entertainerlib.frontend.gui.screens.feed import Feed |
4104 | -from entertainerlib.frontend.gui.screens.feed_entry import FeedEntry |
4105 | -from entertainerlib.frontend.gui.screens.main import Main |
4106 | -from entertainerlib.frontend.gui.screens.movie import Movie |
4107 | -from entertainerlib.frontend.gui.screens.music import Music |
4108 | -from entertainerlib.frontend.gui.screens.photo import Photo |
4109 | -from entertainerlib.frontend.gui.screens.photo_albums import PhotoAlbums |
4110 | -from entertainerlib.frontend.gui.screens.photographs import Photographs |
4111 | -from entertainerlib.frontend.gui.screens.question import Question |
4112 | -from entertainerlib.frontend.gui.screens.rss import Rss |
4113 | -from entertainerlib.frontend.gui.screens.tv_episodes import TvEpisodes |
4114 | -from entertainerlib.frontend.gui.screens.tv_series import TvSeries |
4115 | -from entertainerlib.frontend.gui.screens.video_osd import VideoOSD |
4116 | -from entertainerlib.frontend.gui.screens.video import Video |
4117 | -from entertainerlib.frontend.gui.screens.weather import WeatherScreen |
4118 | +from entertainerlib.gui.screens.album import Album |
4119 | +from entertainerlib.gui.screens.artist import Artist |
4120 | +from entertainerlib.gui.screens.audio_play import AudioPlay |
4121 | +from entertainerlib.gui.screens.disc import Disc |
4122 | +from entertainerlib.gui.screens.factory import ScreenFactory |
4123 | +from entertainerlib.gui.screens.feed import Feed |
4124 | +from entertainerlib.gui.screens.feed_entry import FeedEntry |
4125 | +from entertainerlib.gui.screens.main import Main |
4126 | +from entertainerlib.gui.screens.movie import Movie |
4127 | +from entertainerlib.gui.screens.music import Music |
4128 | +from entertainerlib.gui.screens.photo import Photo |
4129 | +from entertainerlib.gui.screens.photo_albums import PhotoAlbums |
4130 | +from entertainerlib.gui.screens.photographs import Photographs |
4131 | +from entertainerlib.gui.screens.question import Question |
4132 | +from entertainerlib.gui.screens.rss import Rss |
4133 | +from entertainerlib.gui.screens.tv_episodes import TvEpisodes |
4134 | +from entertainerlib.gui.screens.tv_series import TvSeries |
4135 | +from entertainerlib.gui.screens.video_osd import VideoOSD |
4136 | +from entertainerlib.gui.screens.video import Video |
4137 | +from entertainerlib.gui.screens.weather import WeatherScreen |
4138 | from entertainerlib.tests import EntertainerTest |
4139 | from entertainerlib.tests.mock import MockAlbum |
4140 | from entertainerlib.tests.mock import MockEntry |
4141 | @@ -43,7 +43,7 @@ |
4142 | |
4143 | |
4144 | class ScreenFactoryTest(EntertainerTest): |
4145 | - '''Test for entertainerlib.frontend.gui.screens.factory''' |
4146 | + '''Test for entertainerlib.gui.screens.factory''' |
4147 | |
4148 | def setUp(self): |
4149 | EntertainerTest.setUp(self) |
4150 | |
4151 | === modified file 'entertainerlib/tests/test_scrollarea.py' |
4152 | --- entertainerlib/tests/test_scrollarea.py 2009-02-06 08:13:48 +0000 |
4153 | +++ entertainerlib/tests/test_scrollarea.py 2009-05-05 03:31:34 +0000 |
4154 | @@ -6,13 +6,13 @@ |
4155 | |
4156 | import clutter |
4157 | |
4158 | -from entertainerlib.frontend.gui.widgets.base import Base |
4159 | -from entertainerlib.frontend.gui.widgets.label import Label |
4160 | -from entertainerlib.frontend.gui.widgets.scroll_area import ScrollArea |
4161 | +from entertainerlib.gui.widgets.base import Base |
4162 | +from entertainerlib.gui.widgets.label import Label |
4163 | +from entertainerlib.gui.widgets.scroll_area import ScrollArea |
4164 | from entertainerlib.tests import EntertainerTest |
4165 | |
4166 | class ScrollAreaTest(EntertainerTest): |
4167 | - """Test for entertainerlib.frontend.gui.widgets.scroll_area""" |
4168 | + """Test for entertainerlib.gui.widgets.scroll_area""" |
4169 | |
4170 | def setUp(self): |
4171 | """Set up the test""" |
4172 | |
4173 | === modified file 'entertainerlib/tests/test_texture.py' |
4174 | --- entertainerlib/tests/test_texture.py 2009-02-06 08:33:50 +0000 |
4175 | +++ entertainerlib/tests/test_texture.py 2009-05-05 03:31:34 +0000 |
4176 | @@ -9,14 +9,14 @@ |
4177 | |
4178 | import clutter |
4179 | |
4180 | -from entertainerlib.frontend.gui.widgets.base import Base |
4181 | -from entertainerlib.frontend.gui.widgets.texture import Texture |
4182 | +from entertainerlib.gui.widgets.base import Base |
4183 | +from entertainerlib.gui.widgets.texture import Texture |
4184 | from entertainerlib.tests import EntertainerTest |
4185 | |
4186 | THIS_DIR = os.path.dirname(__file__) |
4187 | |
4188 | class TextureTest(EntertainerTest): |
4189 | - """Test for entertainerlib.frontend.gui.widgets.texture""" |
4190 | + """Test for entertainerlib.gui.widgets.texture""" |
4191 | |
4192 | def setUp(self): |
4193 | """Set up the test""" |
4194 | |
4195 | === modified file 'entertainerlib/tests/test_theme.py' |
4196 | --- entertainerlib/tests/test_theme.py 2009-01-31 21:36:56 +0000 |
4197 | +++ entertainerlib/tests/test_theme.py 2009-05-05 04:17:21 +0000 |
4198 | @@ -5,10 +5,10 @@ |
4199 | __author__ = "Matt Layman <laymansterms.dev@gmail.com>" |
4200 | |
4201 | from entertainerlib.tests import EntertainerTest |
4202 | -from entertainerlib.utils.theme import Theme |
4203 | +from entertainerlib.gui.theme import Theme |
4204 | |
4205 | class ThemeTest(EntertainerTest): |
4206 | - """Test for entertainerlib.utils.theme""" |
4207 | + """Test for entertainerlib.gui.theme""" |
4208 | |
4209 | def setUp(self): |
4210 | """Set up the test""" |
4211 | |
4212 | === modified file 'entertainerlib/tests/test_transitionfactory.py' |
4213 | --- entertainerlib/tests/test_transitionfactory.py 2009-02-07 17:12:21 +0000 |
4214 | +++ entertainerlib/tests/test_transitionfactory.py 2009-05-05 03:31:34 +0000 |
4215 | @@ -5,15 +5,15 @@ |
4216 | __copyright__ = '2009, Matt Layman' |
4217 | __author__ = 'Matt Layman <laymansterms.dev@gmail.com>' |
4218 | |
4219 | -from entertainerlib.frontend.gui.transitions.factory import TransitionFactory |
4220 | -from entertainerlib.frontend.gui.transitions.fade import Fade |
4221 | -from entertainerlib.frontend.gui.transitions.no_effect import NoEffect |
4222 | -from entertainerlib.frontend.gui.transitions.slide import Slide |
4223 | -from entertainerlib.frontend.gui.transitions.zoom_and_fade import ZoomAndFade |
4224 | +from entertainerlib.gui.transitions.factory import TransitionFactory |
4225 | +from entertainerlib.gui.transitions.fade import Fade |
4226 | +from entertainerlib.gui.transitions.no_effect import NoEffect |
4227 | +from entertainerlib.gui.transitions.slide import Slide |
4228 | +from entertainerlib.gui.transitions.zoom_and_fade import ZoomAndFade |
4229 | from entertainerlib.tests import EntertainerTest |
4230 | |
4231 | class TransitionFactoryTest(EntertainerTest): |
4232 | - '''Test for entertainerlib.frontend.gui.transitions.factory''' |
4233 | + '''Test for entertainerlib.gui.transitions.factory''' |
4234 | |
4235 | def setUp(self): |
4236 | '''Set up the test''' |
4237 | |
4238 | === modified file 'entertainerlib/tests/test_userinterface.py' |
4239 | --- entertainerlib/tests/test_userinterface.py 2009-04-27 23:12:40 +0000 |
4240 | +++ entertainerlib/tests/test_userinterface.py 2009-05-05 03:31:34 +0000 |
4241 | @@ -6,14 +6,14 @@ |
4242 | |
4243 | import clutter |
4244 | |
4245 | -from entertainerlib.frontend.gui.screens.question import Question |
4246 | -from entertainerlib.frontend.gui.user_event import UserEvent |
4247 | -from entertainerlib.frontend.gui.user_interface import UserInterface |
4248 | +from entertainerlib.gui.screens.question import Question |
4249 | +from entertainerlib.gui.user_event import UserEvent |
4250 | +from entertainerlib.gui.user_interface import UserInterface |
4251 | from entertainerlib.tests import EntertainerTest |
4252 | from entertainerlib.tests.mock import MockClutterKeyboardEvent |
4253 | |
4254 | class UserInterfaceTest(EntertainerTest): |
4255 | - '''Test for entertainerlib.frontend.gui.user_interface''' |
4256 | + '''Test for entertainerlib.gui.user_interface''' |
4257 | |
4258 | def setUp(self): |
4259 | EntertainerTest.setUp(self) |
4260 | |
4261 | === modified file 'entertainerlib/tests/test_weather.py' |
4262 | --- entertainerlib/tests/test_weather.py 2009-02-10 00:59:03 +0000 |
4263 | +++ entertainerlib/tests/test_weather.py 2009-05-06 05:10:14 +0000 |
4264 | @@ -7,7 +7,7 @@ |
4265 | from datetime import datetime |
4266 | |
4267 | from entertainerlib.tests import EntertainerTest |
4268 | -from entertainerlib.utils.weather import Weather |
4269 | +from entertainerlib.weather import Weather |
4270 | |
4271 | class WeatherTest(EntertainerTest): |
4272 | """ |
4273 | |
4274 | === modified file 'entertainerlib/thumbnailer.py' |
4275 | --- entertainerlib/thumbnailer.py 2009-02-19 14:25:51 +0000 |
4276 | +++ entertainerlib/thumbnailer.py 2009-05-05 04:11:48 +0000 |
4277 | @@ -17,7 +17,7 @@ |
4278 | |
4279 | from entertainerlib.exceptions import (ImageThumbnailerException, |
4280 | ThumbnailerException, VideoThumbnailerException) |
4281 | -from entertainerlib.utils.configuration import Configuration |
4282 | +from entertainerlib.configuration import Configuration |
4283 | |
4284 | |
4285 | class Thumbnailer(object): |
4286 | |
4287 | === removed directory 'entertainerlib/utils' |
4288 | === removed file 'entertainerlib/utils/__init__.py' |
4289 | --- entertainerlib/utils/__init__.py 2008-08-07 01:17:29 +0000 |
4290 | +++ entertainerlib/utils/__init__.py 1970-01-01 00:00:00 +0000 |
4291 | @@ -1,1 +0,0 @@ |
4292 | -'''Entertainer utils''' |
4293 | |
4294 | === removed file 'entertainerlib/utils/albumart_downloader.py' |
4295 | --- entertainerlib/utils/albumart_downloader.py 2009-03-22 04:53:10 +0000 |
4296 | +++ entertainerlib/utils/albumart_downloader.py 1970-01-01 00:00:00 +0000 |
4297 | @@ -1,353 +0,0 @@ |
4298 | -'''AlbumArtDownloader - Search and download album art from the internet.''' |
4299 | - |
4300 | -__licence__ = "GPLv2" |
4301 | -__copyright__ = "2007, Lauri Taimila, " |
4302 | -__copyright__ += "2008, Matt Layman" |
4303 | -__author__ = "Lauri Taimila <lauri@taimila.com>, " |
4304 | -__author__ += "Matt Layman <laymansterms.dev@gmail.com" |
4305 | - |
4306 | -import os |
4307 | -import re |
4308 | -import locale |
4309 | -import urllib |
4310 | -import threading |
4311 | -from xml.dom import minidom |
4312 | - |
4313 | -# Amazon licence for Entertainer |
4314 | -LICENSE_KEY = "1YCWYZ0SPPAJ27YZZ482" |
4315 | -DEFAULT_LOCALE = "en_US" |
4316 | -ASSOCIATE = "webservices-20" |
4317 | - |
4318 | -# We are not allowed to batch more than 2 requests at once |
4319 | -# http://docs.amazonwebservices.com/AWSEcommerceService/4-0/ |
4320 | -# PgCombiningOperations.html |
4321 | -MAX_BATCH_JOBS = 2 |
4322 | - |
4323 | -class Bag: |
4324 | - '''Just a helper''' |
4325 | - |
4326 | - |
4327 | -class AlbumArtDownloader(threading.Thread): |
4328 | - """ |
4329 | - Search and download album art from the internet. |
4330 | - |
4331 | - This class is heavily based on Rhythmbox - AlbumArt plugin's class |
4332 | - 'AmazonCoverArtSearch'. That plugin is released under GPLv2 (or higher) |
4333 | - and it's copyrights belong to Gareth Murphy and Martin Szulecki. |
4334 | - |
4335 | - See more: http://www.gnome.org/projects/rhythmbox/ |
4336 | - |
4337 | - If you want better cover search, please contribute to Rhyhtmbox project. |
4338 | - """ |
4339 | - |
4340 | - def __init__(self, album, artist, art_file_path, callback = None): |
4341 | - """ |
4342 | - Initialize album art downloader |
4343 | - @param album: Album title |
4344 | - @param artist: Artist name |
4345 | - @param art_file_path: Path where albumart is saved |
4346 | - @param callback: Callback function that is called after search if set |
4347 | - """ |
4348 | - threading.Thread.__init__(self) |
4349 | - self.setName("AlbumArt Downloader") |
4350 | - self.callback_function = callback # Callback function |
4351 | - self.album = album # Album title |
4352 | - self.artist = artist # Artist name |
4353 | - # Album art files are in this directory |
4354 | - self.path = art_file_path |
4355 | - (self.tld, self.encoding) = self.__get_locale () |
4356 | - |
4357 | - def run(self): |
4358 | - """Start searching and downloading albumart.""" |
4359 | - self.search() |
4360 | - |
4361 | - def __get_locale (self): |
4362 | - '''Get locale information from user\'s machine''' |
4363 | - # "JP is the only locale that correctly takes UTF8 input. |
4364 | - # All other locales use LATIN1." |
4365 | - # http://developer.amazonwebservices.com/connect/ |
4366 | - # entry.jspa?externalID=1295&categoryID=117 |
4367 | - supported_locales = { |
4368 | - "en_US" : ("com", "latin1"), |
4369 | - "en_GB" : ("co.uk", "latin1"), |
4370 | - "de" : ("de", "latin1"), |
4371 | - "ja" : ("jp", "utf8") |
4372 | - } |
4373 | - |
4374 | - lc_id = DEFAULT_LOCALE |
4375 | - default = locale.getdefaultlocale ()[0] |
4376 | - if default: |
4377 | - if supported_locales.has_key (default): |
4378 | - lc_id = default |
4379 | - else: |
4380 | - lang = default.split("_")[0] |
4381 | - if supported_locales.has_key (lang): |
4382 | - lc_id = lang |
4383 | - |
4384 | - return supported_locales[lc_id] |
4385 | - |
4386 | - def __valid_match (self, item): |
4387 | - '''Determine if item matches tag criteria''' |
4388 | - return (hasattr (item, "LargeImage") or hasattr (item, "MediumImage")) \ |
4389 | - and hasattr (item, "ItemAttributes") |
4390 | - |
4391 | - def __tidy_up_string (self, str_input): |
4392 | - """ |
4393 | - Tidy up string. Remove spaces, convert to lowercase and replace chars. |
4394 | - """ |
4395 | - # Lowercase |
4396 | - str_input = str_input.lower () |
4397 | - # Strip |
4398 | - str_input = str_input.strip () |
4399 | - |
4400 | - # TODO: Convert accented to unaccented |
4401 | - str_input = str_input.replace (" - ", " ") |
4402 | - str_input = str_input.replace (": ", " ") |
4403 | - str_input = str_input.replace (" & ", " and ") |
4404 | - |
4405 | - return str_input |
4406 | - |
4407 | - def search(self): |
4408 | - """Search album art from Amazon""" |
4409 | - self.searching = True |
4410 | - self.cancel = False |
4411 | - self.keywords = [] |
4412 | - |
4413 | - st_artist = self.artist or u'Unknown' |
4414 | - st_album = self.album or u'Unknown' |
4415 | - |
4416 | - if st_artist == st_album == u'Unknown': |
4417 | - self.on_search_completed (None) |
4418 | - return |
4419 | - |
4420 | - # Tidy up |
4421 | - |
4422 | - # Replace quote characters |
4423 | - # don't replace single quote: could be important punctuation |
4424 | - for char in ["\""]: |
4425 | - st_artist = st_artist.replace (char, '') |
4426 | - st_album = st_album.replace (char, '') |
4427 | - |
4428 | - |
4429 | - self.st_album = st_album |
4430 | - self.st_artist = st_artist |
4431 | - |
4432 | - # Remove variants of Disc/CD [1-9] from album title before search |
4433 | - for exp in ["\([Dd]isc *[1-9]+\)", "\([Cc][Dd] *[1-9]+\)"]: |
4434 | - p = re.compile (exp) |
4435 | - st_album = p.sub ('', st_album) |
4436 | - |
4437 | - st_album_no_vol = st_album |
4438 | - for exp in ["\(*[Vv]ol.*[1-9]+\)*"]: |
4439 | - p = re.compile (exp) |
4440 | - st_album_no_vol = p.sub ('', st_album_no_vol) |
4441 | - |
4442 | - self.st_album_no_vol = st_album_no_vol |
4443 | - |
4444 | - # Save current search's entry properties |
4445 | - self.search_album = st_album |
4446 | - self.search_artist = st_artist |
4447 | - self.search_album_no_vol = st_album_no_vol |
4448 | - |
4449 | - # TODO: Improve to decrease wrong cover downloads, maybe add severity? |
4450 | - # Assemble list of search keywords (and thus search queries) |
4451 | - if st_album == u'Unknown': |
4452 | - self.keywords.append ("%s Best of" % (st_artist)) |
4453 | - self.keywords.append ("%s Greatest Hits" % (st_artist)) |
4454 | - self.keywords.append ("%s Essential" % (st_artist)) |
4455 | - self.keywords.append ("%s Collection" % (st_artist)) |
4456 | - self.keywords.append ("%s" % (st_artist)) |
4457 | - elif st_artist == u'Unknown': |
4458 | - self.keywords.append ("%s" % (st_album)) |
4459 | - if st_album_no_vol != st_artist: |
4460 | - self.keywords.append ("%s" % (st_album_no_vol)) |
4461 | - self.keywords.append ("Various %s" % (st_album)) |
4462 | - else: |
4463 | - if st_album != st_artist: |
4464 | - self.keywords.append ("%s %s" % (st_artist, st_album)) |
4465 | - if st_album_no_vol != st_album: |
4466 | - self.keywords.append ("%s %s" % |
4467 | - (st_artist, st_album_no_vol)) |
4468 | - self.keywords.append ("Various %s" % (st_album)) |
4469 | - self.keywords.append ("%s" % (st_artist)) |
4470 | - |
4471 | - # Initiate asynchronous search |
4472 | - self.search_next () |
4473 | - |
4474 | - def search_next(self): |
4475 | - """Search again, because the last one didn't find any covers.""" |
4476 | - if len (self.keywords) == 0: |
4477 | - # No keywords left to search -> no results |
4478 | - self.on_search_completed (None) |
4479 | - return False |
4480 | - |
4481 | - self.searching = True |
4482 | - |
4483 | - url = "http://ecs.amazonaws." + self.tld + "/onca/xml" \ |
4484 | - "?Service=AWSECommerceService" \ |
4485 | - "&AWSAccessKeyId=" + LICENSE_KEY + \ |
4486 | - "&AssociateTag=" + ASSOCIATE + \ |
4487 | - "&ResponseGroup=Images,ItemAttributes" \ |
4488 | - "&Operation=ItemSearch" \ |
4489 | - "&ItemSearch.Shared.SearchIndex=Music" |
4490 | - |
4491 | - job = 1 |
4492 | - while job <= MAX_BATCH_JOBS and len (self.keywords) > 0: |
4493 | - keyword = self.keywords.pop (0) |
4494 | - keyword = keyword.encode (self.encoding, "ignore") |
4495 | - keyword = keyword.strip () |
4496 | - keyword = urllib.quote (keyword) |
4497 | - url += "&ItemSearch.%d.Keywords=%s" % (job, keyword) |
4498 | - job += 1 |
4499 | - |
4500 | - # Retrieve search for keyword |
4501 | - temp = urllib.urlopen(url) |
4502 | - search_results = temp.read() |
4503 | - self.on_search_response(search_results) |
4504 | - return True |
4505 | - |
4506 | - def __unmarshal(self, element): |
4507 | - rc = Bag() |
4508 | - child_elements = [e for e in element.childNodes if isinstance (e, |
4509 | - minidom.Element)] |
4510 | - if child_elements: |
4511 | - for child in child_elements: |
4512 | - key = child.tagName |
4513 | - if hasattr (rc, key): |
4514 | - if not isinstance (getattr (rc, key), list): |
4515 | - setattr (rc, key, [getattr (rc, key)]) |
4516 | - getattr (rc, key).append (self.__unmarshal (child)) |
4517 | - # get_best_match_urls() wants a list, even if there is only |
4518 | - # one item/artist |
4519 | - elif child.tagName in ("Items", "Item", "Artist"): |
4520 | - setattr (rc, key, [self.__unmarshal(child)]) |
4521 | - else: |
4522 | - setattr (rc, key, self.__unmarshal(child)) |
4523 | - else: |
4524 | - rc = "".join ([e.data for e in element.childNodes if isinstance (e, |
4525 | - minidom.Text)]) |
4526 | - return rc |
4527 | - |
4528 | - def on_search_response (self, result_data): |
4529 | - '''Check search results |
4530 | - |
4531 | - If results are not good, we search again with the next keyword. |
4532 | - ''' |
4533 | - if result_data is None: |
4534 | - self.search_next() |
4535 | - return |
4536 | - |
4537 | - try: |
4538 | - xmldoc = minidom.parseString(result_data) |
4539 | - except (TypeError, AttributeError): |
4540 | - self.search_next() |
4541 | - return |
4542 | - |
4543 | - data = self.__unmarshal (xmldoc) |
4544 | - if not hasattr (data, "ItemSearchResponse") or \ |
4545 | - not hasattr (data.ItemSearchResponse, "Items"): |
4546 | - # Something went wrong ... |
4547 | - self.search_next () |
4548 | - else: |
4549 | - # We got some search results |
4550 | - self.on_search_results (data.ItemSearchResponse.Items) |
4551 | - |
4552 | - def on_search_results (self, results): |
4553 | - '''Results were found, now we need to take action.''' |
4554 | - self.on_search_completed (results) |
4555 | - |
4556 | - def on_search_completed (self, result): |
4557 | - """ |
4558 | - Search completed and results found. |
4559 | - |
4560 | - Download large album art image from the first result and save it to |
4561 | - the disk. This function diverges greatly from the rhythmbox |
4562 | - implementation in order to avoid their loader and CoverArtDatabase |
4563 | - """ |
4564 | - self.searching = False |
4565 | - image_urls = self.get_best_match_urls(result) |
4566 | - if len(image_urls) == 0: |
4567 | - return |
4568 | - image_url = image_urls[0] |
4569 | - image_file = urllib.urlopen(image_url) |
4570 | - # base64 encode artist and album so there can be a '/' in the artist |
4571 | - # or album |
4572 | - artist_album = self.artist + " - " + self.album |
4573 | - artist_album = artist_album.encode("base64") |
4574 | - |
4575 | - dest = open(os.path.join(self.path, artist_album + ".jpg"),'w') |
4576 | - dest.write(image_file.read()) |
4577 | - dest.close() |
4578 | - |
4579 | - if self.callback_function is not None: |
4580 | - self.callback_function(self.artist, self.album) |
4581 | - |
4582 | - def get_best_match_urls (self, search_results): |
4583 | - """Return tuple of URL's to large and medium cover of the best match""" |
4584 | - # Default to "no match", our results must match our criteria |
4585 | - |
4586 | - # This code comes from Rhythmbox so we can't control the use of 'filter' |
4587 | - # pylint: disable-msg=W0141 |
4588 | - |
4589 | - if not search_results: |
4590 | - return [] |
4591 | - |
4592 | - best_match = None |
4593 | - |
4594 | - for result in search_results: |
4595 | - if not hasattr (result, "Item"): |
4596 | - # Search was unsuccessful, try next batch job |
4597 | - continue |
4598 | - |
4599 | - items = filter(self.__valid_match, result.Item) |
4600 | - if self.search_album != u'Unknown': |
4601 | - album_check = self.__tidy_up_string (self.search_album) |
4602 | - for item in items: |
4603 | - if not hasattr (item.ItemAttributes, "Title"): |
4604 | - continue |
4605 | - |
4606 | - album = self.__tidy_up_string (item.ItemAttributes.Title) |
4607 | - if album == album_check: |
4608 | - # Found exact album, can not get better than that |
4609 | - best_match = item |
4610 | - break |
4611 | - # If we already found a best_match, just keep checking for |
4612 | - # exact one. Check the results for both an album name that |
4613 | - # contains the name we're searching for, and an album name |
4614 | - # that's a substring of the name we're searching for |
4615 | - elif (best_match is None) and \ |
4616 | - (album.find (album_check) != -1 or |
4617 | - album_check.find (album) != -1): |
4618 | - best_match = item |
4619 | - |
4620 | - # If we still have no definite hit, use first result where artist |
4621 | - # matches |
4622 | - if (self.search_album == u'Unknown' and \ |
4623 | - self.search_artist != u'Unknown'): |
4624 | - artist_check = self.__tidy_up_string (self.search_artist) |
4625 | - if best_match is None: |
4626 | - # Check if artist appears in the Artists list |
4627 | - hit = False |
4628 | - for item in items: |
4629 | - if not hasattr (item.ItemAttributes, "Artist"): |
4630 | - continue |
4631 | - |
4632 | - for artist in item.ItemAttributes.Artist: |
4633 | - artist = self.__tidy_up_string (artist) |
4634 | - if artist.find (artist_check) != -1: |
4635 | - best_match = item |
4636 | - hit = True |
4637 | - break |
4638 | - if hit: |
4639 | - break |
4640 | - |
4641 | - urls = [getattr (best_match, size).URL for size in ("LargeImage", |
4642 | - "MediumImage") |
4643 | - if hasattr (best_match, size)] |
4644 | - if urls: |
4645 | - return urls |
4646 | - |
4647 | - # No search was successful |
4648 | - return [] |
4649 | - |
4650 | - |
4651 | |
4652 | === removed file 'entertainerlib/utils/cd_utils.py' |
4653 | --- entertainerlib/utils/cd_utils.py 2008-06-16 04:10:47 +0000 |
4654 | +++ entertainerlib/utils/cd_utils.py 1970-01-01 00:00:00 +0000 |
4655 | @@ -1,11 +0,0 @@ |
4656 | -'''Utilities for handling the cd''' |
4657 | -# XXX: rockstar - Why do we have module for a single function? |
4658 | - |
4659 | -__licence__ = "GPLv2" |
4660 | -__copyright__ = "2008, Joshua Scotton" |
4661 | -__author__ = "Joshua Scotton <josh@joshuascotton.com>" |
4662 | - |
4663 | -import os |
4664 | - |
4665 | -def eject_cd(): |
4666 | - os.system("eject") |
4667 | |
4668 | === removed file 'entertainerlib/utils/content_management_dialog.py' |
4669 | --- entertainerlib/utils/content_management_dialog.py 2009-04-17 21:35:32 +0000 |
4670 | +++ entertainerlib/utils/content_management_dialog.py 1970-01-01 00:00:00 +0000 |
4671 | @@ -1,774 +0,0 @@ |
4672 | -#!/usr/bin/env python |
4673 | -'''Content management GUI for Entertainer''' |
4674 | - |
4675 | -__licence__ = "GPLv2" |
4676 | -__copyright__ = "2008, Lauri Taimila and Joshua Scotton" |
4677 | -__author__ = ("Lauri Taimila <lauri@taimila.com>", |
4678 | - "Joshua Scotton <josh@joshuascotton.com>") |
4679 | - |
4680 | -import os |
4681 | -import socket |
4682 | - |
4683 | -import gtk |
4684 | -import gtk.glade |
4685 | - |
4686 | -from entertainerlib.utils.weather import Weather |
4687 | -from entertainerlib.utils.configuration import Configuration |
4688 | -from entertainerlib.utils.open_feed_source_dialog import OpenFeedSourceDialog |
4689 | - |
4690 | -from entertainerlib.backend.core.message import Message |
4691 | -from entertainerlib.backend.core.message_bus_proxy import MessageBusProxy |
4692 | -from entertainerlib.backend.core.message_type_priority import MessageType |
4693 | - |
4694 | -class ContentManagementDialog: |
4695 | - """ |
4696 | - This is a content management tool for Entertainer media center application. |
4697 | - """ |
4698 | - |
4699 | - # Temporary storage for entered URL |
4700 | - url = "" |
4701 | - GLADE_DIR = os.path.join(os.path.dirname(__file__), "glade") |
4702 | - |
4703 | - def __init__(self, stand_alone): |
4704 | - """ |
4705 | - Initialize content management dialog |
4706 | - @param stand_alone: Boolean, Is this dialog running as a stand alone |
4707 | - process |
4708 | - """ |
4709 | - self.stand_alone = stand_alone |
4710 | - self.config = Configuration() |
4711 | - self.weather = Weather() |
4712 | - |
4713 | - # Load glade UI |
4714 | - self.gladefile = os.path.join(self.GLADE_DIR, |
4715 | - "entertainer-content-management.glade") |
4716 | - self.widgets = gtk.glade.XML(self.gladefile) |
4717 | - |
4718 | - # Get content management dialog and bind signal callbacks |
4719 | - self.dialog = self.widgets.get_widget("ContentManagementDialog") |
4720 | - if (self.dialog): |
4721 | - callback_dic = { |
4722 | - "on_button_open_list_clicked" : |
4723 | - self.on_button_open_list_clicked, |
4724 | - "on_close_button_clicked" : self.on_close_button_clicked, |
4725 | - "on_button_remove_videos_clicked" : |
4726 | - self.on_button_remove_videos_clicked, |
4727 | - "on_button_add_videos_clicked" : |
4728 | - self.on_button_add_videos_clicked, |
4729 | - "on_button_edit_videos_clicked" : |
4730 | - self.on_button_edit_videos_clicked, |
4731 | - "on_checkbutton_video_metadata_toggled" : |
4732 | - self.on_checkbutton_video_metadata_toggled, |
4733 | - "on_button_add_music_clicked" : |
4734 | - self.on_button_add_music_clicked, |
4735 | - "on_button_remove_music_clicked" : |
4736 | - self.on_button_remove_music_clicked, |
4737 | - "on_button_edit_music_clicked" : |
4738 | - self.on_button_edit_music_clicked, |
4739 | - "on_lyrics_checkbox_toggled" : self.on_lyrics_checkbox_toggled, |
4740 | - "on_art_checkbox_toggled" : self.on_art_checkbox_toggled, |
4741 | - "on_button_add_images_clicked" : |
4742 | - self.on_button_add_images_clicked, |
4743 | - "on_button_remove_images_clicked" : |
4744 | - self.on_button_remove_images_clicked, |
4745 | - "on_button_edit_images_clicked" : |
4746 | - self.on_button_edit_images_clicked, |
4747 | - "on_button_add_feed_clicked" : |
4748 | - self.on_button_add_feed_clicked, |
4749 | - "on_button_remove_feed_clicked" : |
4750 | - self.on_button_remove_feed_clicked, |
4751 | - "on_button_edit_feed_clicked" : |
4752 | - self.on_button_edit_feed_clicked, |
4753 | - "on_fetch_interval_spinbutton_value_changed" : |
4754 | - self.on_fetch_interval_spinbutton_value_changed, |
4755 | - "on_ContentManagementDialog_destroy" : self.on_dialog_closed, |
4756 | - "on_url_dialog_delete_event" : self.on_url_dialog_delete_event, |
4757 | - "on_url_dialog_ok_button_clicked" : |
4758 | - self.on_url_dialog_ok_button_clicked, |
4759 | - "on_url_dialog_cancel_button_clicked" : |
4760 | - self.on_url_dialog_cancel_button_clicked, |
4761 | - "on_button_video_rebuild_clicked" : |
4762 | - self.on_button_video_rebuild_clicked, |
4763 | - "on_button_music_rebuild_clicked" : |
4764 | - self.on_button_music_rebuild_clicked, |
4765 | - "on_button_image_rebuild_clicked" : |
4766 | - self.on_button_image_rebuild_clicked, |
4767 | - "on_button_feed_rebuild_clicked" : |
4768 | - self.on_button_feed_rebuild_clicked, |
4769 | - "on_button_add_weather_clicked" : |
4770 | - self.on_button_add_weather_clicked, |
4771 | - "on_button_remove_weather_clicked" : |
4772 | - self.on_button_remove_weather_clicked, |
4773 | - "on_weather_display_checkbox_toggled" : |
4774 | - self.on_weather_display_checkbox_toggled, |
4775 | - "on_location_find_button_clicked" : |
4776 | - self.on_location_find_button_clicked, |
4777 | - "on_location_cancel_button_clicked" : |
4778 | - self.on_location_cancel_button_clicked, |
4779 | - "on_location_add_button_clicked" : |
4780 | - self.on_location_add_button_clicked, |
4781 | - "on_location_entry_activate" : self.on_location_entry_activate} |
4782 | - self.widgets.signal_autoconnect(callback_dic) |
4783 | - |
4784 | - # Initialize dialog widgets with correct values and show dialog |
4785 | - self.init_dialog_values_from_configure_file() |
4786 | - self.dialog.resize(500, 300) |
4787 | - self.dialog.show() |
4788 | - |
4789 | - # Initialize location list in search dialog |
4790 | - result_list = self.widgets.get_widget("location_results_treeview") |
4791 | - store = gtk.ListStore(str) |
4792 | - result_list.set_model(store) |
4793 | - cell_renderer = gtk.CellRendererText() |
4794 | - column = gtk.TreeViewColumn(_("Location"), cell_renderer, text=0) |
4795 | - result_list.append_column(column) |
4796 | - |
4797 | -# Signal handlers |
4798 | - |
4799 | - def on_dialog_closed(self, widget): |
4800 | - """Callback function for dialog's close button""" |
4801 | - try: |
4802 | - proxy = MessageBusProxy(client_name = "Content Management GUI") |
4803 | - proxy.connectToMessageBus() |
4804 | - proxy.sendMessage(Message(MessageType.CONTENT_CONF_UPDATED)) |
4805 | - proxy.disconnectFromMessageBus() |
4806 | - except socket.error: |
4807 | - error = gtk.MessageDialog( |
4808 | - None, gtk.DIALOG_MODAL, |
4809 | - gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, _( |
4810 | - "Entertainer backend is not running. " |
4811 | - "Cache cannot be rebuilt." |
4812 | - )) |
4813 | - error.run() |
4814 | - error.destroy() |
4815 | - |
4816 | - |
4817 | - if(self.stand_alone): |
4818 | - self.dialog.hide() |
4819 | - self.dialog.destroy() |
4820 | - gtk.main_quit() |
4821 | - else: |
4822 | - self.dialog.hide() |
4823 | - self.dialog.destroy() |
4824 | - |
4825 | - def on_close_button_clicked(self, widget): |
4826 | - """Callback function for dialog's close button""" |
4827 | - if(self.stand_alone): |
4828 | - self.dialog.hide() |
4829 | - self.dialog.destroy() |
4830 | - gtk.main_quit() |
4831 | - else: |
4832 | - self.dialog.hide() |
4833 | - self.dialog.destroy() |
4834 | - |
4835 | - def on_button_add_videos_clicked(self, widget): |
4836 | - """Opens add URL dialog. """ |
4837 | - widget = self.widgets.get_widget("treeview_videos") |
4838 | - model = widget.get_model() |
4839 | - # Open "Select folder" dialog |
4840 | - dialog = gtk.FileChooserDialog(_("Select video folder"), None, |
4841 | - gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, |
4842 | - (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL, |
4843 | - gtk.STOCK_OPEN,gtk.RESPONSE_OK), |
4844 | - None) |
4845 | - status = dialog.run() |
4846 | - # If folder was selected we add it to model and update config file |
4847 | - if(status == gtk.RESPONSE_OK): |
4848 | - self.add_to_model_and_config(dialog.get_current_folder(), model, |
4849 | - self.video_folders, "Videos") |
4850 | - dialog.destroy() |
4851 | - |
4852 | - def on_button_remove_videos_clicked(self, widget): |
4853 | - """Remove currently selected folder from video folders""" |
4854 | - widget = self.widgets.get_widget("treeview_videos") |
4855 | - model = widget.get_model() |
4856 | - selection = widget.get_selection().get_selected() |
4857 | - if selection[1] == None: |
4858 | - return |
4859 | - rm_folder = model.get_value(selection[1], 0) |
4860 | - self.video_folders.remove(rm_folder) |
4861 | - str_folders = ";".join(self.video_folders) |
4862 | - self.config.write_content_value("Videos", "folders", str_folders) |
4863 | - model.remove(selection[1]) |
4864 | - |
4865 | - def on_button_edit_videos_clicked(self, widget): |
4866 | - """Edit currently selected folder""" |
4867 | - widget = self.widgets.get_widget("treeview_videos") |
4868 | - url_dialog = self.widgets.get_widget("url_dialog") |
4869 | - url_entry = self.widgets.get_widget("url_entry") |
4870 | - model = widget.get_model() |
4871 | - selection = widget.get_selection().get_selected() |
4872 | - if selection[1] == None: |
4873 | - return |
4874 | - folder = model.get_value(selection[1], 0) |
4875 | - url_entry.set_text(folder) |
4876 | - url_dialog.set_title(_("Edit URL")) |
4877 | - status = url_dialog.run() |
4878 | - if status == gtk.RESPONSE_OK and os.path.exists(self.url): |
4879 | - # Update list model |
4880 | - model.set_value(selection[1], 0, self.url) |
4881 | - # Update configure file |
4882 | - pos = self.video_folders.index(folder) |
4883 | - self.video_folders.remove(folder) |
4884 | - self.video_folders.insert(pos, self.url) |
4885 | - str_folders = ";".join(self.video_folders) |
4886 | - self.config.write_content_value("Videos", "folders", |
4887 | - str_folders) |
4888 | - |
4889 | - def on_checkbutton_video_metadata_toggled(self, widget): |
4890 | - """ |
4891 | - Download video file metadata from internet |
4892 | - @param widget: GTK-Widget |
4893 | - """ |
4894 | - self.config.write_content_value("Videos", "download_metadata", |
4895 | - widget.get_active()) |
4896 | - |
4897 | - def on_button_add_music_clicked(self, widget): |
4898 | - """ |
4899 | - Opens add URL dialog |
4900 | - @param widget: GTK-Widget |
4901 | - """ |
4902 | - widget = self.widgets.get_widget("treeview_music") |
4903 | - model = widget.get_model() |
4904 | - # Open "Select folder" dialog |
4905 | - dialog = gtk.FileChooserDialog(_("Select music folder"), None, |
4906 | - gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, |
4907 | - (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, |
4908 | - gtk.RESPONSE_OK), |
4909 | - None) |
4910 | - status = dialog.run() |
4911 | - # If folder was selected we add it to model and update config file |
4912 | - if(status == gtk.RESPONSE_OK): |
4913 | - self.add_to_model_and_config(dialog.get_current_folder(), model, |
4914 | - self.music_folders, "Music") |
4915 | - dialog.destroy() |
4916 | - |
4917 | - def on_button_remove_music_clicked(self, widget): |
4918 | - """Remove currently selected folder from music folders""" |
4919 | - widget = self.widgets.get_widget("treeview_music") |
4920 | - model = widget.get_model() |
4921 | - selection = widget.get_selection().get_selected() |
4922 | - if selection[1] == None: |
4923 | - return |
4924 | - rm_folder = model.get_value(selection[1], 0) |
4925 | - self.music_folders.remove(rm_folder) |
4926 | - str_folders = ";".join(self.music_folders) |
4927 | - self.config.write_content_value("Music", "folders", str_folders) |
4928 | - model.remove(selection[1]) |
4929 | - |
4930 | - def on_button_edit_music_clicked(self, widget): |
4931 | - """Edit currently selected music folder""" |
4932 | - widget = self.widgets.get_widget("treeview_music") |
4933 | - url_dialog = self.widgets.get_widget("url_dialog") |
4934 | - url_entry = self.widgets.get_widget("url_entry") |
4935 | - model = widget.get_model() |
4936 | - selection = widget.get_selection().get_selected() |
4937 | - if selection[1] == None: |
4938 | - return |
4939 | - folder = model.get_value(selection[1], 0) |
4940 | - url_entry.set_text(folder) |
4941 | - url_dialog.set_title(_("Edit URL")) |
4942 | - status = url_dialog.run() |
4943 | - if status == gtk.RESPONSE_OK and os.path.exists(self.url): |
4944 | - # Update list model |
4945 | - model.set_value(selection[1], 0, self.url) |
4946 | - # Update configure file |
4947 | - pos = self.music_folders.index(folder) |
4948 | - self.music_folders.remove(folder) |
4949 | - self.music_folders.insert(pos, self.url) |
4950 | - str_folders = ";".join(self.music_folders) |
4951 | - self.config.write_content_value("Music", "folders", str_folders) |
4952 | - |
4953 | - def on_button_add_images_clicked(self, widget): |
4954 | - """Opens add URL dialog. """ |
4955 | - widget = self.widgets.get_widget("treeview_images") |
4956 | - model = widget.get_model() |
4957 | - # Open "Select folder" dialog |
4958 | - dialog = gtk.FileChooserDialog(_("Select image folder"), None, |
4959 | - gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, |
4960 | - (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, |
4961 | - gtk.RESPONSE_OK), |
4962 | - None) |
4963 | - status = dialog.run() |
4964 | - # If folder was selected we add it to model and update config file |
4965 | - if(status == gtk.RESPONSE_OK): |
4966 | - self.add_to_model_and_config(dialog.get_current_folder(), model, |
4967 | - self.image_folders, "Images") |
4968 | - dialog.destroy() |
4969 | - |
4970 | - def on_button_remove_images_clicked(self, widget): |
4971 | - """Remove currently selected folder from images folders""" |
4972 | - widget = self.widgets.get_widget("treeview_images") |
4973 | - model = widget.get_model() |
4974 | - selection = widget.get_selection().get_selected() |
4975 | - if selection[1] == None: |
4976 | - return |
4977 | - rm_folder = model.get_value(selection[1], 0) |
4978 | - self.image_folders.remove(rm_folder) |
4979 | - str_folders = ";".join(self.image_folders) |
4980 | - self.config.write_content_value("Images", "folders", str_folders) |
4981 | - model.remove(selection[1]) |
4982 | - |
4983 | - def on_button_edit_images_clicked(self, widget): |
4984 | - """Edit currently selected music folder""" |
4985 | - widget = self.widgets.get_widget("treeview_images") |
4986 | - url_dialog = self.widgets.get_widget("url_dialog") |
4987 | - url_entry = self.widgets.get_widget("url_entry") |
4988 | - model = widget.get_model() |
4989 | - selection = widget.get_selection().get_selected() |
4990 | - if selection[1] == None: |
4991 | - return |
4992 | - folder = model.get_value(selection[1], 0) |
4993 | - url_entry.set_text(folder) |
4994 | - url_dialog.set_title(_("Edit URL")) |
4995 | - status = url_dialog.run() |
4996 | - if status == gtk.RESPONSE_OK and os.path.exists(self.url): |
4997 | - # Update list model |
4998 | - model.set_value(selection[1], 0, self.url) |
4999 | - # Update configure file |
5000 | - pos = self.image_folders.index(folder) |
This branch is the apocalyptical package structure changes. entertainerlib. backend will disappear as soon as the new indexer lands. There are all sorts of changes here. The only real code change was the complete removal of entertainerlib. utils.cd_ utils, because there was a single line single function, which I easily removed. Otherwise, I consolidated a lot of packages into single modules, and flattened the tree a bunch.
This specifically needs to land in future, because it's unnecessary when there is still a backend/frontend. Frontend was renamed to client, and will become more of a client in later branches. entertainerlib. utils was removed, and its contents shifted around.
This is probably going to cause a lot of conflicts, which is another big reason why this needs to land in future. The future branch is there solely to be liberal in the changes that need to be made, and, well, these changes are quite liberal. Tests, lint, and running entertainer all indicate everything is good, but the jury is still out, and will require A LOT of changes.