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 about_name = 'mEveMon'
52 about_text = ('Mobile character monitor for EVE Online')
53 about_authors = ['Ryan Campbell <campbellr@gmail.com>',
54 'Danny Campbell <danny.campbell@gmail.com>']
56 about_website = 'http://mevemon.garage.maemo.org'
60 GCONF_DIR = "/apps/maemo/mevemon"
63 self.program = hildon.Program()
64 self.program.__init__()
65 self.gconf = gnome.gconf.client_get_default()
66 #NOTE: remove this after a few releases
67 self.update_settings()
68 self.connect_to_network()
69 self.cached_api = eveapi.EVEAPIConnection( cacheHandler = \
70 apicache.cache_handler(debug=False))
71 self.gui = gui.mEveMonUI(self)
76 def quit(self, *args):
79 def update_settings(self):
81 Update from the old pre 0.3 settings to the new settings layout.
82 We should remove this eventually, once no one is using pre-0.3 mEveMon
84 uid = self.gconf.get_string("%s/eve_uid" % self.GCONF_DIR)
87 key = self.gconf.get_string("%s/eve_api_key" % self.GCONF_DIR)
88 self.add_account(uid, key)
89 self.gconf.unset("%s/eve_uid" % self.GCONF_DIR)
90 self.gconf.unset("%s/eve_api_key" % self.GCONF_DIR)
93 def get_accounts(self):
95 Returns a dictionary containing uid:api_key pairs gathered from gconf
98 entries = self.gconf.all_entries("%s/accounts" % self.GCONF_DIR)
100 for entry in entries:
101 key = os.path.basename(entry.get_key())
102 value = entry.get_value().to_string()
103 accounts[key] = value
107 def get_api_key(self, uid):
109 Returns the api key associated with the given uid.
111 return self.gconf.get_string("%s/accounts/%s" % (self.GCONF_DIR, uid)) or ''
113 def remove_account(self, uid):
115 Removes the provided uid key from gconf
117 self.gconf.unset("%s/accounts/%s" % (self.GCONF_DIR, uid))
119 def add_account(self, uid, api_key):
121 Adds the provided uid:api_key pair to gconf.
123 self.gconf.set_string("%s/accounts/%s" % (self.GCONF_DIR, uid), api_key)
125 def get_auth(self, uid):
127 Returns an authentication object to be used for eveapi calls
128 that require authentication.
130 api_key = self.get_api_key(uid)
133 auth = self.cached_api.auth(userID=uid, apiKey=api_key)
135 traceback.print_exc()
140 def get_char_sheet(self, uid, char_id):
142 Returns an object containing information about the character specified
143 by the provided character ID.
146 sheet = self.get_auth(uid).character(char_id).CharacterSheet()
148 # TODO: we should really have a logger that logs this error somewhere
149 traceback.print_exc()
154 def charid2uid(self, char_id):
156 Takes a character ID and returns the user ID of the account containing
159 Returns None if the character isn't found in any of the registered accounts.
162 acct_dict = self.get_accounts()
164 for uid, api_key in acct_dict.items():
165 auth = self.cached_api.auth(userID=uid, apiKey=api_key)
166 api_char_list = auth.account.Characters()
168 for character in api_char_list.characters:
169 if character.characterID == char_id:
175 def char_id2name(self, char_id):
177 Takes a character ID and returns the character name associated with
179 The EVE API accepts a comma-separated list of IDs, but for now we
180 will just handle a single ID.
183 chars = self.cached_api.eve.CharacterName(ids=char_id).characters
184 name = chars[0].characterName
186 traceback.print_exc()
191 def char_name2id(self, name):
193 Takes the name of an EVE character and returns the characterID.
195 The EVE api accepts a comma separated list of names, but for now
196 we will just handle single names/
199 chars = self.cached_api.eve.CharacterID(names=name).characters
200 char_id = chars[0].characterID
201 char_name = chars[0].name
203 traceback.print_exc()
208 def get_chars_from_acct(self, uid):
210 Returns a list of characters associated with the provided user ID.
212 auth = self.get_auth(uid)
217 api_char_list = auth.account.Characters()
218 char_list = [char.name for char in api_char_list.characters]
220 traceback.print_exc()
225 def get_characters(self):
227 Returns a list of (character_name, image_path, uid) tuples from all the
228 accounts that are registered to mEveMon.
230 If there is an authentication issue, then instead of adding a valid
231 pair to the list, it appends an 'error message'
235 err_img = "/usr/share/mevemon/imgs/error.jpg"
237 placeholder_chars = ("Please check your API settings.", err_img, "0")
239 acct_dict = self.get_accounts()
241 return [placeholder_chars]
243 for uid in acct_dict.keys():
244 char_names = self.get_chars_from_acct(uid)
247 ui_char_list.append(placeholder_chars)
249 # append each char we get to the list we'll return to the
251 for char_name in char_names:
252 ui_char_list.append((char_name, self.get_portrait(char_name, 64) , uid) )
256 def get_portrait(self, char_name, size):
258 Returns the file path of the retrieved portrait
260 char_id = self.char_name2id(char_name)
262 return fetchimg.portrait_filename(char_id, size)
264 def get_skill_tree(self):
266 Returns an object from eveapi containing skill tree info
269 tree = self.cached_api.eve.SkillTree()
271 traceback.print_exc()
276 def get_skill_in_training(self, uid, char_id):
278 Returns an object from eveapi containing information about the
279 current skill in training
282 skill = self.get_auth(uid).character(char_id).SkillInTraining()
284 traceback.print_exc()
289 def connection_cb(self, connection, event, mgc):
291 I'm not sure why we need this, but connection.connect() won't work
292 without it, even empty.
297 def connect_to_network(self):
299 This will connect to the default network if avaliable, or pop up the
300 connection dialog to select a connection.
301 Running this when we start the program ensures we are connected to a
304 connection = conic.Connection()
306 connection.connect("connection-event", self.connection_cb, 0xAA55)
307 assert(connection.request_connection(conic.CONNECT_FLAG_NONE))
310 def get_sp(self, uid, char_id):
312 Adds up the SP for all known skills, then calculates the SP gained
313 from an in-training skill.
317 sheet = self.get_char_sheet(uid, char_id)
318 for skill in sheet.skills:
319 actual_sp += skill.skillpoints
321 live_sp = actual_sp + self.get_training_sp(uid, char_id)
325 def get_spps(self, uid, char_id):
327 Calculate and returns the skill points per hour for the given character.
329 skill = self.get_skill_in_training(uid, char_id)
331 if not skill.skillInTraining:
334 total_sp = skill.trainingDestinationSP - skill.trainingStartSP
335 total_time = skill.trainingEndTime - skill.trainingStartTime
337 spps = float(total_sp) / total_time
339 return (spps, skill.trainingStartTime)
341 def get_training_sp(self, uid, char_id):
343 returns the additional SP that the in-training skill has acquired
345 spps_tuple = self.get_spps(uid, char_id)
349 spps, start_time = spps_tuple
350 eve_time = time.time() #evetime is utc, right?
351 time_diff = eve_time - start_time
353 return (spps * time_diff)
356 if __name__ == "__main__":