clean up layout and add backwards compatibility
[mevemon] / package / src / mevemon.py
1 #!/usr/bin/env python
2 #
3 # mEveMon - A character monitor for EVE Online
4 # Copyright (c) 2010  Ryan and Danny Campbell, and the mEveMon Team
5 #
6 # mEveMon is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # mEveMon is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 #
19
20
21 import hildon
22 import gtk
23 from eveapi import eveapi
24 import fetchimg
25 import apicache
26 import os.path
27
28 # we will store our preferences in gconf
29 import gnome.gconf
30
31 #ugly hack to check maemo version. any better way?
32 if hasattr(hildon, "StackableWindow"):
33     from ui.fremantle import gui
34 else:
35     from ui.diablo import gui
36
37 class mEveMon():
38     """
39     The controller class for mEvemon. The intent is to help
40     abstract the EVE API and settings code from the UI code.
41
42     """
43
44     GCONF_DIR = "/apps/maemo/mevemon"
45
46     def __init__(self):
47         self.program = hildon.Program()
48         self.program.__init__()
49         self.gconf = gnome.gconf.client_get_default()
50         #NOTE: remove this after a few releases
51         self.update_settings()
52         self.cached_api = eveapi.EVEAPIConnection( cacheHandler = \
53                 apicache.cache_handler(debug=False))
54         self.gui = gui.mEveMonUI(self)
55
56     def run(self):
57         gtk.main()
58     
59     def quit(self, *args):
60         gtk.main_quit()
61
62     def update_settings(self):
63         """
64         Update from the old pre 0.3 settings to the new settings layout.
65         We should remove this eventually, once no one is using pre-0.3 mEveMon
66         """
67         uid = self.gconf.get_string("%s/eve_uid" % self.GCONF_DIR)
68         
69         if uid:
70             key = self.gconf.get_string("%s/eve_api_key" % self.GCONF_DIR)
71             self.add_account(uid, key)
72             self.gconf.unset("%s/eve_uid" % self.GCONF_DIR)
73             self.gconf.unset("%s/eve_api_key" % self.GCONF_DIR)
74
75
76     def get_accounts(self):
77         """
78         Returns a dictionary containing uid:api_key pairs gathered from gconf
79         """
80         accounts = {}
81         entries = self.gconf.all_entries("%s/accounts" % self.GCONF_DIR)
82
83         for entry in entries:
84             key = os.path.basename(entry.get_key())
85             value = entry.get_value().to_string()
86             accounts[key] = value
87
88         return accounts
89         
90     def get_api_key(self, uid):
91         """
92         Returns the api key associated with the given uid.
93         """
94         return self.gconf.get_string("%s/accounts/%s" % (self.GCONF_DIR, uid)) or ''
95
96     def remove_account(self, uid):
97         """
98         Removes the provided uid key from gconf
99         """
100         self.gconf.unset("%s/accounts/%s" % (self.GCONF_DIR, uid))
101
102     def add_account(self, uid, api_key):
103         """
104         Adds the provided uid:api_key pair to gconf.
105         """
106         self.gconf.set_string("%s/accounts/%s" % (self.GCONF_DIR, uid), api_key)
107
108     def get_auth(self, uid):
109         """
110         Returns an authentication object to be used for eveapi calls
111         that require authentication.
112         """
113         api_key = self.get_api_key(uid)
114
115         try:
116             auth = self.cached_api.auth(userID=uid, apiKey=api_key)
117         except eveapi.Error:
118             return None
119
120         return auth
121
122     def get_char_sheet(self, uid, char_id):
123         """
124         Returns an object containing information about the character specified
125         by the provided character ID.
126         """
127         try:
128             sheet = self.get_auth(uid).character(char_id).CharacterSheet()
129         except eveapi.Error:
130             # TODO: we should really have a logger that logs this error somewhere
131             return None
132
133         return sheet
134
135     def charid2uid(self, char_id):
136         """
137         Takes a character ID and returns the user ID of the account containing
138         the character.
139
140         Returns None if the character isn't found in any of the registered accounts.
141
142         """
143         acct_dict = self.get_accounts()
144         
145         for uid, api_key in acct_dict.items():
146             auth = self.cached_api.auth(userID=uid, apiKey=api_key)
147             api_char_list = auth.account.Characters()
148             
149             for character in api_char_list.characters:
150                 if character.characterID == char_id:
151                     return uid
152
153         
154         return None
155     
156     def char_id2name(self, char_id):
157         """
158         Takes a character ID and returns the character name associated with
159         that ID.
160         The EVE API accepts a comma-separated list of IDs, but for now we
161         will just handle a single ID.
162         """
163         try:
164             chars = self.cached_api.eve.CharacterName(ids=char_id).characters
165             name = chars[0].characterName
166         except eveapi.Error:
167             return None
168
169         return name
170
171     def char_name2id(self, name):
172         """
173         Takes the name of an EVE character and returns the characterID.
174         
175         The EVE api accepts a comma separated list of names, but for now
176         we will just handle single names/
177         """
178         try:
179             chars = self.cached_api.eve.CharacterID(names=name).characters
180             char_id = chars[0].characterID
181         except eveapi.Error:
182             return None
183
184         return char_id
185
186     
187     def get_characters(self):
188         """
189         Returns a list of (character_name, image_path) pairs from all the
190         accounts that are registered to mEveMon.
191         
192         If there is an authentication issue, then instead of adding a valid
193         pair to the list, it appends an 'error message' 
194
195         """
196         ui_char_list = []
197         err_img = "/usr/share/mevemon/imgs/error.jpg"
198
199         placeholder_chars = ("Please check your API settings.", err_img, "0")
200         
201         acct_dict = self.get_accounts()
202         if not acct_dict:
203             return [placeholder_chars]
204
205         for uid, api_key in acct_dict.items():
206             auth = self.cached_api.auth(userID=uid, apiKey=api_key)
207             try:
208                 api_char_list = auth.account.Characters()
209                 # append each char we get to the list we'll return to the
210                 # UI --danny
211                 for character in api_char_list.characters:
212                     ui_char_list.append( ( character.name, fetchimg.portrait_filename( character.characterID, 64 ), uid) )
213             except eveapi.Error:
214                 ui_char_list.append(placeholder_chars)
215
216         return ui_char_list
217
218     def get_portrait(self, char_name, size):
219         """
220         Returns the relative path of the retrieved portrait
221         """
222         char_id = self.char_name2id(char_name)
223         return fetchimg.portrait_filename(char_id, size)
224
225     def get_skill_tree(self):
226         """
227         Returns an object from eveapi containing skill tree info
228         """
229         try:
230             tree = self.cached_api.eve.SkillTree()
231         except eveapi.Error:
232             return None
233         
234         return tree
235
236     def get_skill_in_training(self, uid, char_id):
237         """
238         Returns an object from eveapi containing information about the
239         current skill in training
240
241         """
242         try:
243             skill = self.get_auth(uid).character(char_id).SkillInTraining()
244         except eveapi.Error:
245             return None
246
247         return skill
248
249
250 if __name__ == "__main__":
251     app = mEveMon()
252     app.run()