Closed afrancoto closed 12 years ago
Neh, I don't think it's too much, it's a little difficult, but feasible. (I was thinking that adding your own services would be good too, like search engines on google chrome, lol)
For the first problem, you can still use the ui_manager to dinamically add items (you would have to generate a unique item name, so there should be some checks to make sure the service name is indeed unique).
And I think using a single function will work wonders, will be a lot more clean and dynamic. I might help you implement it during the week if you let me (and if you haven't finished with it already, lol), I gotta study right now -_-
Great! I don't know how much time i will find in the next weeks, i'm changing home :D But I'll try! I'll start by writing the unique function in a separate file.py
Uploaded unique.py with the unique function, it's really simple, now I just have to figure out how to build the array and insert the function in WebMenu
Some thoughs: What if we use a dict instead of a list to store the services and it's data? I was thinking of something like this (using as base what you wrote on unique.py):
import webbrowser
import urllib2
#Services data are stored in a dict like this:
# 'service_name' : ('song_engine_url','album_engine_url','artist_engine_url', enabled)
services = {}
class Test:
def __init__(self):
global services
services['AllMusic']=("","http://www.allmusic.com/search/albums/[ALBUM]+[ARTIST]", "http://www.allmusic.com/search/artists/[ARTIST]", True)
services['Wikipedia']=("","http://en.wikipedia.org/w/index.php?search=[ALBUM]", "http://en.wikipedia.org/w/index.php?search=[ARTIST]", False)
services['Fail']=("","Fail","Fail", False)
self.the_unique_function('activate', None, 1, 'AllMusic', False) #Simulates click, shell=none because we don't need it in this example, 1=album/2=artist, allmusic/wikipedia=the service in lowercase, False=command sent from Menubar
##########
#The "the_unique_function" is the one which is called by the menu/context menu actions
##########
def the_unique_function(self, event, shell, what, service, context=False):
metadata=self.get_metadata(shell, context) #Calls "get_metadata"
print "We are looking for",metadata[what],"on",service
base_url = services[service][what]
print "Base URL is:", base_url
final_url=self.replace_keywords(base_url, metadata) #Replace keywords
print "Final URL is:", final_url
webbrowser.open( final_url )
(Also added the library webbrowser instead of using a raw os command)
We could store the dict on dconf using this definition on the schema:
<key type="a{s(sssb)}" name="services">
<default>{'Wikipedia':('', 'http://en.wikipedia.org/w/index.php?search=[ARTIST]', 'http://en.wikipedia.org/w/index.php?search=[ALBUM]', true), 'AllMusic':('', 'http://www.allmusic.com/search/artist/[ARTIST]', 'http://www.allmusic.com/search/album/[ALBUM]', false)}</default>
<summary>Music Services</summary>
<description>Services with their respectives urls for song, album and artist search</description>
</key>
And an example of how we could load the menu items once we got the settings (I only included the album menu for the example):
#Draw menu test
ui_album ='''
<menubar name="MenuBar">
<menu name="AlbumMenu" action="album_menu_action">
%s
</menu>
</menubar>
'''
def draw_menu( self, shell, settings ):
services = settings['services']
uim = shell.props.ui_manager
action_group = Gtk.ActionGroup()
ui = ''
for service, data in services.items():
action_name = '%s_action' % service
#add ui string
ui += '<menuitem name=AL_%s action=%s/>' % (service, action_name)
#create action
action = Gtk.Action( action_name, service, _('Look for the current album on %s' % service), '' )
action.connect( 'activate', self.the_unique_function, shell, 1, service )
action_group.add_action( action )
ui = ui_album % ui
uim.insert_action_group( action_group )
self.ui_menu_album_id = uim.add_ui_from_string( ui )
ui_manager.ensure_update()
Woot, sorry for the long post. Anyway, let me know what you think!
PS: good luck with the moving :3
The dict is perfect, I didn't know it exists :P Now I try to implement the new draw menu and, then, the unique function in the extension... :)
#Services data are stored in a dict like this: # 'service_name' : ('song_engine_url','album_engine_url','artist_engine_url', enabled_album, enabled_artist)
It works perfectly, i'm still adapting the various functions... Tonight it will be ready :) Here is how it is now: http://www.2shared.com/file/1OfMExi3/WebMenu_Xtar.html
Nice, you sure work fast xD After modifying the plugin module, there should be some refactoring on the config module to use the new settings structure... Well, I'll keep an eye on your progess, but can't really focus on writing code right now. If you need help with something else, let me know.
Oh, btw if you are up to it, you can try creating a 'testing' branch on your repo to commit this changes, without breaking the stable version. Here is some info on that, if you don't know much about it http://learn.github.com/p/branching.html
Thanks, testing branch created!
Mumble mumble, I don't know how to import the global variable 'services' from WebMenu.py to WebMenu_config.py...
Why don't you retrieve the dict again from the settings?
Mmm... ok, but usually I don't like to repeat the code :P
Ok, i'm blocked:
global services services = self.settings['services'] [...] for service, data in services.items(): check = Gtk.CheckButton(service) check.set_active(services[service][3]) check.connect("toggled", self.website_toggled, service, 1)#The last argument, 1, stands for "Album" [...] def website_toggled(self, checkbutton, service, what): services[service][what+2]=checkbutton.get_active()
website_toggled
is the function called when a website is checked/unchecked in the settings menu;
services
is the dict with all the data;
I get this error:
Traceback (most recent call last): File "/home/andrea/.local/share/rhythmbox/plugins/WebMenu/WebMenu_config.py", line 88, in website_toggled services[service][what+2]=checkbutton.get_active() TypeError: 'tuple' object does not support item assignment
when i click on the checkbox, probably because a tuple is a read-only variable...
Do you know a workaround? A google search didn't work! Sorry for all these questions, but I know really a little about python :P
Oh, totally forgot about that. Tuples are immutables on python :F There are two things you can do:
data = list(services[service])
data[what+2] = checkbutton.get_active()
services[service]= tuple(data)
#after asigning the new data, you should persist the services
settings['services'] = services
This a little troublesome, but it's a little more organized I believe.
Thank you! Now it works! I pushed the last changes in the testing branch if you want to take a look :D
There is only one problem left (I hope XD): The menu items and the checkbox in the config window are shown in a different order than the one in the gschema, I can't figure out why! In dconf the order is right after the install, but when a WebMenu option is changed the order is lost.
Gotta go now, thanks again for all your help! :D
Wow, that's weird. I don't know either :/ Does the order really matter? If it really does, the only thing I can think of (given that the reordering thing is the default Gio behavior with dictinaries), is keep an extra schema key to persist the ordering; the dict would keep the data, and the extra key would contain all the defined services' keys, in the preferred order. Anyway, gonna look into it when I have some time, I'll let you know if I find something about it.
I added the "source-order" key in dconf and make everything work :) Now we only need to write the function to add a new service but that's not too difficoult, I think :P
speedy work guys ... :)
how close are we to making this into the official release branch (v1.1 or v2.0)?
You can see the To Do in the testing branch! Right now, I have some problems in implementing the new_service_add function in WebMwnu_config.py and in opening the options window from a menu item. :P
The Add/Delete new services functions and the new unique function to parse and open the URLs now work perfectly, so i can close this issue :D Unfortunately, other two must be opened :P Maybe I'm adding too much features XD
Thanks again!
Next step (difficult but challenging): the user, via the configuration window, should be able to add it's own search options using some keywords. For example, with just three textbox:
Those three variables could be saved in dconf in a single array; The extension read them in do_activate; PROBLEM: How to adds the entries to the web_menu_item and context_menu_part; PROBLEM/DRASTIC CHANGE: A single function can now read the search URL whatever it is (even those already in the extension) and is connected to every action
Ok maybe it's too much :P