3 # mEveMon - A character monitor for EVE Online
4 # Copyright (c) 2010 Ryan and Danny Campbell, and the mEveMon Team
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.
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.
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/>.
23 from eveapi import eveapi
30 #conic is used for connection handling
32 #import socket for handling socket exceptions
35 # we will store our preferences in gconf
38 #ugly hack to check maemo version. any better way?
39 if hasattr(hildon, "StackableWindow"):
40 from ui.fremantle import gui
42 from ui.diablo import gui
46 The controller class for mEvemon. The intent is to help
47 abstract the EVE API and settings code from the UI code.
51 GCONF_DIR = "/apps/maemo/mevemon"
54 self.program = hildon.Program()
55 self.program.__init__()
56 self.gconf = gnome.gconf.client_get_default()
57 #NOTE: remove this after a few releases
58 self.update_settings()
59 self.connect_to_network()
60 self.cached_api = eveapi.EVEAPIConnection( cacheHandler = \
61 apicache.cache_handler(debug=False))
62 self.gui = gui.mEveMonUI(self)
67 def quit(self, *args):
70 def update_settings(self):
72 Update from the old pre 0.3 settings to the new settings layout.
73 We should remove this eventually, once no one is using pre-0.3 mEveMon
75 uid = self.gconf.get_string("%s/eve_uid" % self.GCONF_DIR)
78 key = self.gconf.get_string("%s/eve_api_key" % self.GCONF_DIR)
79 self.add_account(uid, key)
80 self.gconf.unset("%s/eve_uid" % self.GCONF_DIR)
81 self.gconf.unset("%s/eve_api_key" % self.GCONF_DIR)
84 def get_accounts(self):
86 Returns a dictionary containing uid:api_key pairs gathered from gconf
89 entries = self.gconf.all_entries("%s/accounts" % self.GCONF_DIR)
92 key = os.path.basename(entry.get_key())
93 value = entry.get_value().to_string()
98 def get_api_key(self, uid):
100 Returns the api key associated with the given uid.
102 return self.gconf.get_string("%s/accounts/%s" % (self.GCONF_DIR, uid)) or ''
104 def remove_account(self, uid):
106 Removes the provided uid key from gconf
108 self.gconf.unset("%s/accounts/%s" % (self.GCONF_DIR, uid))
110 def add_account(self, uid, api_key):
112 Adds the provided uid:api_key pair to gconf.
114 self.gconf.set_string("%s/accounts/%s" % (self.GCONF_DIR, uid), api_key)
116 def get_auth(self, uid):
118 Returns an authentication object to be used for eveapi calls
119 that require authentication.
121 api_key = self.get_api_key(uid)
124 auth = self.cached_api.auth(userID=uid, apiKey=api_key)
126 traceback.print_exc()
131 def get_char_sheet(self, uid, char_id):
133 Returns an object containing information about the character specified
134 by the provided character ID.
137 sheet = self.get_auth(uid).character(char_id).CharacterSheet()
139 # TODO: we should really have a logger that logs this error somewhere
140 traceback.print_exc()
145 def charid2uid(self, char_id):
147 Takes a character ID and returns the user ID of the account containing
150 Returns None if the character isn't found in any of the registered accounts.
153 acct_dict = self.get_accounts()
155 for uid, api_key in acct_dict.items():
156 auth = self.cached_api.auth(userID=uid, apiKey=api_key)
157 api_char_list = auth.account.Characters()
159 for character in api_char_list.characters:
160 if character.characterID == char_id:
166 def char_id2name(self, char_id):
168 Takes a character ID and returns the character name associated with
170 The EVE API accepts a comma-separated list of IDs, but for now we
171 will just handle a single ID.
174 chars = self.cached_api.eve.CharacterName(ids=char_id).characters
175 name = chars[0].characterName
177 traceback.print_exc()
182 def char_name2id(self, name):
184 Takes the name of an EVE character and returns the characterID.
186 The EVE api accepts a comma separated list of names, but for now
187 we will just handle single names/
190 chars = self.cached_api.eve.CharacterID(names=name).characters
191 char_id = chars[0].characterID
192 char_name = chars[0].name
194 traceback.print_exc()
199 def get_chars_from_acct(self, uid):
201 Returns a list of characters associated with the provided user ID.
203 auth = self.get_auth(uid)
208 api_char_list = auth.account.Characters()
209 char_list = [char.name for char in api_char_list.characters]
211 traceback.print_exc()
216 def get_characters(self):
218 Returns a list of (character_name, image_path, uid) tuples from all the
219 accounts that are registered to mEveMon.
221 If there is an authentication issue, then instead of adding a valid
222 pair to the list, it appends an 'error message'
226 err_img = "/usr/share/mevemon/imgs/error.jpg"
228 placeholder_chars = ("Please check your API settings.", err_img, "0")
230 acct_dict = self.get_accounts()
232 return [placeholder_chars]
234 for uid in acct_dict.keys():
235 char_names = self.get_chars_from_acct(uid)
238 ui_char_list.append(placeholder_chars)
240 # append each char we get to the list we'll return to the
242 for char_name in char_names:
243 ui_char_list.append((char_name, self.get_portrait(char_name, 64) , uid) )
247 def get_portrait(self, char_name, size):
249 Returns the file path of the retrieved portrait
251 char_id = self.char_name2id(char_name)
253 return fetchimg.portrait_filename(char_id, size)
255 def get_skill_tree(self):
257 Returns an object from eveapi containing skill tree info
260 tree = self.cached_api.eve.SkillTree()
262 traceback.print_exc()
267 def get_skill_in_training(self, uid, char_id):
269 Returns an object from eveapi containing information about the
270 current skill in training
273 skill = self.get_auth(uid).character(char_id).SkillInTraining()
275 traceback.print_exc()
280 def connection_cb(self, connection, event, mgc):
282 I'm not sure why we need this, but connection.connect() won't work
283 without it, even empty.
288 def connect_to_network(self):
290 This will connect to the default network if avaliable, or pop up the
291 connection dialog to select a connection.
292 Running this when we start the program ensures we are connected to a
295 connection = conic.Connection()
297 connection.connect("connection-event", self.connection_cb, 0xAA55)
298 assert(connection.request_connection(conic.CONNECT_FLAG_NONE))
301 def get_sp(self, uid, char_id):
303 Adds up the SP for all known skills, then calculates the SP gained
304 from an in-training skill.
308 sheet = self.get_char_sheet(uid, char_id)
309 for skill in sheet.skills:
310 actual_sp += skill.skillpoints
312 live_sp = actual_sp + self.get_training_sp(uid, char_id)
316 def get_spps(self, uid, char_id):
318 Calculate and returns the skill points per hour for the given character.
320 skill = self.get_skill_in_training(uid, char_id)
322 if not skill.skillInTraining:
325 total_sp = skill.trainingDestinationSP - skill.trainingStartSP
326 total_time = skill.trainingEndTime - skill.trainingStartTime
328 spps = float(total_sp) / total_time
330 return (spps, skill.trainingStartTime)
332 def get_training_sp(self, uid, char_id):
334 returns the additional SP that the in-training skill has acquired
336 spps_tuple = self.get_spps(uid, char_id)
340 spps, start_time = spps_tuple
341 eve_time = time.time() #evetime is utc, right?
342 time_diff = eve_time - start_time
344 return (spps * time_diff)
347 if __name__ == "__main__":