def __init__(self, root: str, test_dir: str, dst_img_size: Tuple[int, int]): self._search_for_files(os.path.join(root, test_dir)) self.cache = ImageCache(force_rgb=True, dst_img_size=dst_img_size) # loading labels self.labels = ImageDataset.load_labels(root) if self.labels is None: print("Failed to load labels. Data root is " + root) return # checking for extra classes labels_set = set(self.labels) filtered_files = [] for filename in self.image_files: label = self.image_labels[filename] if label not in labels_set: # raise Exception('test label not in training set: ' + label) pass else: filtered_files.append(filename) if len(filtered_files) != len(self.image_files): print( 'Test files filtered to conform to training labels. %d files were excluded' % (len(self.image_files) - len(filtered_files))) self.image_files = filtered_files # indexing labels self.label_to_index = dict() for i, label in enumerate(self.labels): self.label_to_index[label] = i
def __init__(self, parent=None): super(SettingsWidget, self).__init__(parent) self.currentObject = None self.lastObjectType = None ## TODO: change to translation file self.useTypes = { 0: localizer.translate('classSettingsWidget', 'noUse'), 1: localizer.translate('classSettingsWidget', 'useToOtherObject'), 2: localizer.translate('classSettingsWidget', 'openSth'), 3: localizer.translate('classSettingsWidget', 'putSmwh'), 4: localizer.translate('classSettingsWidget', 'deleteObstacle') } self.fadeTypes = { 0: localizer.translate('classSettingsWidget', 'instantly'), 1: localizer.translate('classSettingsWidget', 'fade') } self.layout = QtGui.QVBoxLayout() self.setLayout(self.layout) self.setSizePolicy( QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)) self.editor = parent self.imageCache = ImageCache() self.createOptionFields()
def __init__(self, root: str, subdir: str = None, force_rgb: bool = False): super(ImageDataset, self).__init__() if os.path.isfile(root): self.images = self._load_list(root, subdir) self.labels = self._get_labels(self.images, os.path.dirname(root)) else: self.images = self._search_for_files(root) self.cache = ImageCache(force_rgb)
def __init__(self, parent=None): super(SettingsWidget, self).__init__(parent) self.currentObject = None self.lastObjectType = None ## TODO: change to translation file self.useTypes = { 0: localizer.translate('classSettingsWidget', 'noUse'), 1: localizer.translate('classSettingsWidget', 'useToOtherObject'), 2: localizer.translate('classSettingsWidget', 'openSth'), 3: localizer.translate('classSettingsWidget', 'putSmwh'), 4: localizer.translate('classSettingsWidget', 'deleteObstacle') } self.fadeTypes = {0: localizer.translate( 'classSettingsWidget', 'instantly'), 1: localizer.translate( 'classSettingsWidget', 'fade')} self.layout = QtGui.QVBoxLayout() self.setLayout(self.layout) self.setSizePolicy(QtGui.QSizePolicy( QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)) self.editor = parent self.imageCache = ImageCache() self.createOptionFields()
def __init__(self, prefs=None, display=None): self.root = Tk(className='Grail', screenName=display) self.root.withdraw() resources = os.path.join(script_dir, "data", "Grail.ad") if os.path.isfile(resources): self.root.option_readfile(resources, "startupFile") BaseApplication.BaseApplication.__init__(self, prefs) # The stylesheet must be initted before any Viewers, so it # registers its' prefs callbacks first, hence reloads before the # viewers reconfigure w.r.t. the new styles. self.stylesheet = Stylesheet.Stylesheet(self.prefs) self.load_images = 1 # Overridden by cmd line or pref. # socket management sockets = self.prefs.GetInt('sockets', 'number') self.sq = SocketQueue(sockets) self.prefs.AddGroupCallback('sockets', lambda self=self: \ self.sq.change_max( self.prefs.GetInt('sockets', 'number'))) # initialize on_exit_methods before global_history self.on_exit_methods = [] self.global_history = GlobalHistory.GlobalHistory(self) self.login_cache = {} self.rexec_cache = {} self.url_cache = CacheManager(self) self.image_cache = ImageCache(self.url_cache) self.auth = AuthenticationManager(self) self.root.report_callback_exception = self.report_callback_exception if sys.stdin.isatty(): # only useful if stdin might generate KeyboardInterrupt self.keep_alive() self.browsers = [] self.iostatuspanel = None self.in_exception_dialog = None from ancillary import Greek for k, v in Greek.entitydefs.items(): Application.dingbatimages[k] = (v, '_sym') self.root.bind_class("Text", "<Alt-Left>", self.dummy_event) self.root.bind_class("Text", "<Alt-Right>", self.dummy_event)
def __init__(self, start_x, start_y, sprite_dir, width, height, frames, cache=None): Entity.__init__(self) # Directory where all the sprites will be held # This must include up, down, left, right in both idle and walking positions # TODO: Implement other movement types self.sprite_dir = sprite_dir # We can preload the cache in for duplicated characters or just create a new one if cache is None: self.cache = ImageCache(sprite_dir) else: self.cache = cache # Default the sprite to face down self.image = self.cache.get_image("down_1") # Where to spawn the character self.x_speed = 0 self.y_speed = 0 self.width = width self.height = height # Define movement properties self.speed = 8 self.sneak_mult = 0.4 self.sprint_mult = 1.5 # Animation properties self.anim_frames = frames # How many animation frames self.current_anim_frame = 0 self.frame_wait = 4 # How long to wait between frames self.current_frame_wait = 0 self.rect = Rect(start_x, start_y, self.width, self.height)
def __init__(self): # Define window properties self.window_size = self.window_width, self.window_height = 640, 640 self.tile_size = 32 self.depth = 0 self.flags = 0 self.fps = 60 # Initialize pygame pygame.init() # Define basic pygame properties self.screen = pygame.display.set_mode(self.window_size, self.flags, self.depth) self.clock = pygame.time.Clock() # Load the image cache self.tile_cache = ImageCache(Game.tile_dir) self.ui_cache = ImageCache(Game.ui_dir) # Define the key entities and default to None until we start the main game loop self.player = None
def __init__(self, prefs=None, display=None): self.root = Tk(className='Grail', screenName=display) self.root.withdraw() resources = os.path.join(script_dir, "data", "Grail.ad") if os.path.isfile(resources): self.root.option_readfile(resources, "startupFile") BaseApplication.BaseApplication.__init__(self, prefs) # The stylesheet must be initted before any Viewers, so it # registers its' prefs callbacks first, hence reloads before the # viewers reconfigure w.r.t. the new styles. self.stylesheet = Stylesheet.Stylesheet(self.prefs) self.load_images = 1 # Overridden by cmd line or pref. # socket management sockets = self.prefs.GetInt('sockets', 'number') self.sq = SocketQueue(sockets) self.prefs.AddGroupCallback('sockets', lambda self=self: \ self.sq.change_max( self.prefs.GetInt('sockets', 'number'))) # initialize on_exit_methods before global_history self.on_exit_methods = [] self.global_history = GlobalHistory.GlobalHistory(self) self.login_cache = {} self.rexec_cache = {} self.url_cache = CacheManager(self) self.image_cache = ImageCache(self.url_cache) self.auth = AuthenticationManager(self) self.root.report_callback_exception = self.report_callback_exception if sys.stdin.isatty(): # only useful if stdin might generate KeyboardInterrupt self.keep_alive() self.browsers = [] self.iostatuspanel = None self.in_exception_dialog = None import Greek for k, v in Greek.entitydefs.items(): Application.dingbatimages[k] = (v, '_sym') self.root.bind_class("Text", "<Alt-Left>", self.dummy_event) self.root.bind_class("Text", "<Alt-Right>", self.dummy_event)
def __init__(self, parent=None): super(SettingsWidget, self).__init__(parent) self.currentObject = None self.lastObjectType = None self.useTypes = {0: "Ei käyttöä", 1: "Käytä toiseen esineeseen", 2: "Avaa jotakin", 3: "Laita johonkin", 4: "Poista este"} self.fadeTypes = {0: "Välittömästi", 1: "Häivytys"} self.layout = QtGui.QVBoxLayout() self.setLayout(self.layout) self.setSizePolicy(QtGui.QSizePolicy( QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)) self.editor = parent self.imageCache = ImageCache() self.createOptionFields()
def __init__(self, window_size, block_size): self.window_size = window_size self.block_size = block_size # Initialise the pygame variables pygame.init() self.screen = pygame.display.set_mode(window_size) self.clock = pygame.time.Clock() self.fps = 25 # Initialize the image cache self.image_cache = ImageCache("data/images") # Create entity groups for PyGame self.environment_entities = pygame.sprite.Group() self.player_entities = pygame.sprite.Group() # Create the player self.player = Player(32, 32, self.image_cache) self.player_entities.add(self.player) # Create the level self.level = DiamondSquare(6, 0.05).get_grid_2D() # Random map created using Diamond Square
class Character(Entity): def __init__(self, start_x, start_y, sprite_dir, width, height, frames, cache=None): Entity.__init__(self) # Directory where all the sprites will be held # This must include up, down, left, right in both idle and walking positions # TODO: Implement other movement types self.sprite_dir = sprite_dir # We can preload the cache in for duplicated characters or just create a new one if cache is None: self.cache = ImageCache(sprite_dir) else: self.cache = cache # Default the sprite to face down self.image = self.cache.get_image("down_1") # Where to spawn the character self.x_speed = 0 self.y_speed = 0 self.width = width self.height = height # Define movement properties self.speed = 8 self.sneak_mult = 0.4 self.sprint_mult = 1.5 # Animation properties self.anim_frames = frames # How many animation frames self.current_anim_frame = 0 self.frame_wait = 4 # How long to wait between frames self.current_frame_wait = 0 self.rect = Rect(start_x, start_y, self.width, self.height) def update(self, up, down, left, right, obstacles): x_dir = -left + right y_dir = -up + down self.x_speed = x_dir * self.speed self.y_speed = y_dir * self.speed # Update the characters rect to apply movement self.rect.left += self.x_speed self.rect.top += self.y_speed self.animate() def animate(self): # Just determine which frame of which direction to use as current image if self.x_speed < 0: self.image = self.cache.get_image("left_" + str(self.current_anim_frame)) elif self.x_speed > 0: self.image = self.cache.get_image("right_" + str(self.current_anim_frame)) elif self.y_speed < 0: self.image = self.cache.get_image("up_" + str(self.current_anim_frame)) elif self.y_speed > 0: self.image = self.cache.get_image("down_" + str(self.current_anim_frame)) # Because there is such a low frame rate in the animations, it is handy to have a system inplace # to create a pause between frames self.current_frame_wait += 1 if self.current_frame_wait >= self.frame_wait: # Frame switch self.current_anim_frame += 1 if self.current_anim_frame >= self.anim_frames: self.current_anim_frame = 0 self.current_frame_wait = 0 def get_pos(self): return self.rect.left, self.rect.top
class Application(BaseApplication.BaseApplication): """The application class represents a group of browser windows.""" def __init__(self, prefs=None, display=None): self.root = Tk(className='Grail', screenName=display) self.root.withdraw() resources = os.path.join(script_dir, "data", "Grail.ad") if os.path.isfile(resources): self.root.option_readfile(resources, "startupFile") BaseApplication.BaseApplication.__init__(self, prefs) # The stylesheet must be initted before any Viewers, so it # registers its' prefs callbacks first, hence reloads before the # viewers reconfigure w.r.t. the new styles. self.stylesheet = Stylesheet.Stylesheet(self.prefs) self.load_images = 1 # Overridden by cmd line or pref. # socket management sockets = self.prefs.GetInt('sockets', 'number') self.sq = SocketQueue(sockets) self.prefs.AddGroupCallback('sockets', lambda self=self: \ self.sq.change_max( self.prefs.GetInt('sockets', 'number'))) # initialize on_exit_methods before global_history self.on_exit_methods = [] self.global_history = GlobalHistory.GlobalHistory(self) self.login_cache = {} self.rexec_cache = {} self.url_cache = CacheManager(self) self.image_cache = ImageCache(self.url_cache) self.auth = AuthenticationManager(self) self.root.report_callback_exception = self.report_callback_exception if sys.stdin.isatty(): # only useful if stdin might generate KeyboardInterrupt self.keep_alive() self.browsers = [] self.iostatuspanel = None self.in_exception_dialog = None from ancillary import Greek for k, v in Greek.entitydefs.items(): Application.dingbatimages[k] = (v, '_sym') self.root.bind_class("Text", "<Alt-Left>", self.dummy_event) self.root.bind_class("Text", "<Alt-Right>", self.dummy_event) def dummy_event(self, event): pass def register_on_exit(self, method): self.on_exit_methods.append(method) def unregister_on_exit(self, method): try: self.on_exit_methods.remove(method) except ValueError: pass def exit_notification(self): for m in self.on_exit_methods[:]: try: m() except: pass def add_browser(self, browser): self.browsers.append(browser) def del_browser(self, browser): try: self.browsers.remove(browser) except ValueError: pass def quit(self): self.root.quit() def open_io_status_panel(self): if not self.iostatuspanel: from ancillary import IOStatusPanel self.iostatuspanel = IOStatusPanel.IOStatusPanel(self) else: self.iostatuspanel.reopen() def maybe_quit(self): if not (self.embedded or self.browsers): self.quit() def go(self): try: try: if ilu_tk: ilu_tk.RunMainLoop() else: self.root.mainloop() except KeyboardInterrupt: pass finally: self.exit_notification() def keep_alive(self): # Exercise the Python interpreter regularly so keyboard # interrupts get through self.root.tk.createtimerhandler(KEEPALIVE_TIMER, self.keep_alive) def get_cached_image(self, url): return self.image_cache.get_image(url) def set_cached_image(self, url, image, owner=None): self.image_cache.set_image(url, image, owner) def open_url(self, url, method, params, reload=0, data=None): api = self.url_cache.open(url, method, params, reload, data=data) api._url_ = url return api def open_url_simple(self, url): api = self.open_url(url, 'GET', {}) errcode, errmsg, meta = api.getmeta() if errcode != 200: raise IOError(('url open error', errcode, errmsg, meta)) return URLReadWrapper(api, meta) def get_cache_keys(self): """For applets.""" return self.url_cache.items.keys() def decode_pipeline(self, fp, content_encoding, error=1): if self.decode_prog.has_key(content_encoding): prog = self.decode_prog[content_encoding] if not prog: return fp tfn = tempfile.mktemp() ok = 0 try: temp = open(tfn, 'w') BUFSIZE = 8192 while 1: buf = fp.read(BUFSIZE) if not buf: break temp.write(buf) temp.close() ok = 1 finally: if not ok: try: os.unlink(tfn) except os.error: pass pipeline = '%s <%s; rm -f %s' % (prog, tfn, tfn) # XXX What if prog fails? return os.popen(pipeline, 'r') if error: self.error_dialog( IOError, "Can't decode content-encoding: %s" % content_encoding) return None decode_prog = { 'gzip': 'gzip -d', 'x-gzip': 'gzip -d', 'compress': 'compress -d', 'x-compress': 'compress -d', } def exception_dialog(self, message="", root=None): exc, val, tb = sys.exc_type, sys.exc_value, sys.exc_traceback self.exc_dialog(message, exc, val, tb, root) def report_callback_exception(self, exc, val, tb, root=None): self.exc_dialog("in a callback function", exc, val, tb, root) def exc_dialog(self, message, exc, val, tb, root=None): if self.in_exception_dialog: print() print("*** Recursive exception", message) import traceback traceback.print_exception(exc, val, tb) return self.in_exception_dialog = 1 def f(s=self, m=message, e=exc, v=val, t=tb, root=root): s._exc_dialog(m, e, v, t, root) if TkVersion >= 4.1: self.root.after_idle(f) else: self.root.after(0, f) def _exc_dialog(self, message, exc, val, tb, root=None): # XXX This needn't be a modal dialog -- # XXX should SafeDialog be changed to support callbacks? from utils import SafeDialog msg = "An exception occurred " + str(message) + " :\n" msg = msg + str(exc) + " : " + str(val) dlg = SafeDialog.Dialog( root or self.root, text=msg, title="Python Exception: " + str(exc), bitmap='error', default=0, strings=("OK", "Show traceback"), ) self.in_exception_dialog = 0 if dlg.num == 1: self.traceback_dialog(exc, val, tb) def traceback_dialog(self, exc, val, tb): # XXX This could actually just create a new Browser window... from utils import TbDialog TbDialog.TracebackDialog(self.root, exc, val, tb) def error_dialog(self, exc, msg, root=None): # Display an error dialog. # Return when the user clicks OK # XXX This needn't be a modal dialog from utils import SafeDialog if type(msg) in (List, Tuple): s = '' for item in msg: s = s + ':\n' + str(item) msg = s[2:] else: msg = str(msg) SafeDialog.Dialog( root or self.root, text=msg, title="Error: " + str(exc), bitmap='error', default=0, strings=('OK', ), ) dingbatimages = { 'ldots': ('...', None), # math stuff 'sp': (' ', None), 'hairsp': ('\240', None), 'thinsp': ('\240', None), 'emdash': ('--', None), 'endash': ('-', None), 'mdash': ('--', None), 'ndash': ('-', None), 'ensp': (' ', None) } def clear_dingbat(self, entname): if self.dingbatimages.has_key(entname): del self.dingbatimages[entname] def set_dingbat(self, entname, entity): self.dingbatimages[entname] = entity def load_dingbat(self, entname): if self.dingbatimages.has_key(entname): return self.dingbatimages[entname] gifname = grailutil.which(entname + '.gif', self.iconpath) if gifname: img = PhotoImage(file=gifname, master=self.root) self.dingbatimages[entname] = img return img self.dingbatimages[entname] = None return None
class Application(BaseApplication.BaseApplication): """The application class represents a group of browser windows.""" def __init__(self, prefs=None, display=None): self.root = Tk(className='Grail', screenName=display) self.root.withdraw() resources = os.path.join(script_dir, "data", "Grail.ad") if os.path.isfile(resources): self.root.option_readfile(resources, "startupFile") BaseApplication.BaseApplication.__init__(self, prefs) # The stylesheet must be initted before any Viewers, so it # registers its' prefs callbacks first, hence reloads before the # viewers reconfigure w.r.t. the new styles. self.stylesheet = Stylesheet.Stylesheet(self.prefs) self.load_images = 1 # Overridden by cmd line or pref. # socket management sockets = self.prefs.GetInt('sockets', 'number') self.sq = SocketQueue(sockets) self.prefs.AddGroupCallback('sockets', lambda self=self: \ self.sq.change_max( self.prefs.GetInt('sockets', 'number'))) # initialize on_exit_methods before global_history self.on_exit_methods = [] self.global_history = GlobalHistory.GlobalHistory(self) self.login_cache = {} self.rexec_cache = {} self.url_cache = CacheManager(self) self.image_cache = ImageCache(self.url_cache) self.auth = AuthenticationManager(self) self.root.report_callback_exception = self.report_callback_exception if sys.stdin.isatty(): # only useful if stdin might generate KeyboardInterrupt self.keep_alive() self.browsers = [] self.iostatuspanel = None self.in_exception_dialog = None import Greek for k, v in Greek.entitydefs.items(): Application.dingbatimages[k] = (v, '_sym') self.root.bind_class("Text", "<Alt-Left>", self.dummy_event) self.root.bind_class("Text", "<Alt-Right>", self.dummy_event) def dummy_event(self, event): pass def register_on_exit(self, method): self.on_exit_methods.append(method) def unregister_on_exit(self, method): try: self.on_exit_methods.remove(method) except ValueError: pass def exit_notification(self): for m in self.on_exit_methods[:]: try: m() except: pass def add_browser(self, browser): self.browsers.append(browser) def del_browser(self, browser): try: self.browsers.remove(browser) except ValueError: pass def quit(self): self.root.quit() def open_io_status_panel(self): if not self.iostatuspanel: import IOStatusPanel self.iostatuspanel = IOStatusPanel.IOStatusPanel(self) else: self.iostatuspanel.reopen() def maybe_quit(self): if not (self.embedded or self.browsers): self.quit() def go(self): try: try: if ilu_tk: ilu_tk.RunMainLoop() else: self.root.mainloop() except KeyboardInterrupt: pass finally: self.exit_notification() def keep_alive(self): # Exercise the Python interpreter regularly so keyboard # interrupts get through self.root.tk.createtimerhandler(KEEPALIVE_TIMER, self.keep_alive) def get_cached_image(self, url): return self.image_cache.get_image(url) def set_cached_image(self, url, image, owner=None): self.image_cache.set_image(url, image, owner) def open_url(self, url, method, params, reload=0, data=None): api = self.url_cache.open(url, method, params, reload, data=data) api._url_ = url return api def open_url_simple(self, url): api = self.open_url(url, 'GET', {}) errcode, errmsg, meta = api.getmeta() if errcode != 200: raise IOError, ('url open error', errcode, errmsg, meta) return URLReadWrapper(api, meta) def get_cache_keys(self): """For applets.""" return self.url_cache.items.keys() def decode_pipeline(self, fp, content_encoding, error=1): if self.decode_prog.has_key(content_encoding): prog = self.decode_prog[content_encoding] if not prog: return fp tfn = tempfile.mktemp() ok = 0 try: temp = open(tfn, 'w') BUFSIZE = 8192 while 1: buf = fp.read(BUFSIZE) if not buf: break temp.write(buf) temp.close() ok = 1 finally: if not ok: try: os.unlink(tfn) except os.error: pass pipeline = '%s <%s; rm -f %s' % (prog, tfn, tfn) # XXX What if prog fails? return os.popen(pipeline, 'r') if error: self.error_dialog(IOError, "Can't decode content-encoding: %s" % content_encoding) return None decode_prog = { 'gzip': 'gzip -d', 'x-gzip': 'gzip -d', 'compress': 'compress -d', 'x-compress': 'compress -d', } def exception_dialog(self, message="", root=None): exc, val, tb = sys.exc_type, sys.exc_value, sys.exc_traceback self.exc_dialog(message, exc, val, tb, root) def report_callback_exception(self, exc, val, tb, root=None): self.exc_dialog("in a callback function", exc, val, tb, root) def exc_dialog(self, message, exc, val, tb, root=None): if self.in_exception_dialog: print print "*** Recursive exception", message import traceback traceback.print_exception(exc, val, tb) return self.in_exception_dialog = 1 def f(s=self, m=message, e=exc, v=val, t=tb, root=root): s._exc_dialog(m, e, v, t, root) if TkVersion >= 4.1: self.root.after_idle(f) else: self.root.after(0, f) def _exc_dialog(self, message, exc, val, tb, root=None): # XXX This needn't be a modal dialog -- # XXX should SafeDialog be changed to support callbacks? import SafeDialog msg = "An exception occurred " + str(message) + " :\n" msg = msg + str(exc) + " : " + str(val) dlg = SafeDialog.Dialog(root or self.root, text=msg, title="Python Exception: " + str(exc), bitmap='error', default=0, strings=("OK", "Show traceback"), ) self.in_exception_dialog = 0 if dlg.num == 1: self.traceback_dialog(exc, val, tb) def traceback_dialog(self, exc, val, tb): # XXX This could actually just create a new Browser window... import TbDialog TbDialog.TracebackDialog(self.root, exc, val, tb) def error_dialog(self, exc, msg, root=None): # Display an error dialog. # Return when the user clicks OK # XXX This needn't be a modal dialog import SafeDialog if type(msg) in (ListType, TupleType): s = '' for item in msg: s = s + ':\n' + str(item) msg = s[2:] else: msg = str(msg) SafeDialog.Dialog(root or self.root, text=msg, title="Error: " + str(exc), bitmap='error', default=0, strings=('OK',), ) dingbatimages = {'ldots': ('...', None), # math stuff 'sp': (' ', None), 'hairsp': ('\240', None), 'thinsp': ('\240', None), 'emdash': ('--', None), 'endash': ('-', None), 'mdash': ('--', None), 'ndash': ('-', None), 'ensp': (' ', None) } def clear_dingbat(self, entname): if self.dingbatimages.has_key(entname): del self.dingbatimages[entname] def set_dingbat(self, entname, entity): self.dingbatimages[entname] = entity def load_dingbat(self, entname): if self.dingbatimages.has_key(entname): return self.dingbatimages[entname] gifname = grailutil.which(entname + '.gif', self.iconpath) if gifname: img = PhotoImage(file=gifname, master=self.root) self.dingbatimages[entname] = img return img self.dingbatimages[entname] = None return None
class ImageDataset(Dataset): """ Dataset for foregrounds and backgrounds """ img_exts = {'.png', '.jpg'} def __init__(self, root: str, subdir: str = None, force_rgb: bool = False): super(ImageDataset, self).__init__() if os.path.isfile(root): self.images = self._load_list(root, subdir) self.labels = self._get_labels(self.images, os.path.dirname(root)) else: self.images = self._search_for_files(root) self.cache = ImageCache(force_rgb) def __getitem__(self, index): filename = self.images[index] label = self._get_label(filename) img = self.cache.load(filename) return img, label def __len__(self): return len(self.images) @staticmethod def _load_list(list_file: str, subdir: str) -> list: """ Load and parse filename with list of images :param list_file: list file name :param subdir: subdir :return: list of images filenames """ with open(list_file, "r") as f: lines = f.readlines() root = os.path.split(list_file)[0] imgs = [] for l in lines: l = l.strip() if len(l) < 1: continue imgs.append(os.path.join(root, subdir, l)) return imgs def _search_for_files(self, root_dir: str) -> list: """ Search for all image files in a directory. Files with extensions in self.img_exts are collected. :param root_dir: directory to search in :return: list of paths to images """ files = os.listdir(root_dir) imgs = [] for f in files: path = os.path.join(root_dir, f) if os.path.isfile(path): ext = os.path.splitext(f)[1].lower() if ext in self.img_exts: imgs.append(path) return imgs @staticmethod def _get_label(filename: str) -> str: """ Parse filename and extract label, which is the name of parent directory :param filename: source filename (full path) :return: label """ label = os.path.split(os.path.dirname(filename))[1] return label @staticmethod def load_labels(root: str) -> list: """ Loads saved labels from dataset dir :param root: :return: """ list_filename = os.path.join(root, "labels.txt") saved_labels = None if os.path.exists(list_filename): with open(list_filename, "r") as f: saved_labels = f.readlines() saved_labels = [s.strip() for s in saved_labels] return saved_labels @staticmethod def _get_labels(images: list, root: str) -> list: """ Count all labels found in list of images :param images: list of source images (list of filenames) :return: count of labels """ labels = set() for filename in images: labels.add(ImageDataset._get_label(filename)) # loading saved list list_filename = os.path.join(root, "labels.txt") saved_labels = ImageDataset.load_labels(root) if saved_labels is not None: if len(saved_labels) != len(labels): print( "WARNING: saved labels size (%d) does not match current count of labels (%d)" % (len(saved_labels), len(labels))) saved_labels = None if saved_labels is not None: # checking if all labels are there for saved_label in saved_labels: if saved_label not in labels: print( "WARNING: saved labels are not the same as current labels: extra label = %s" % saved_label) saved_labels = None break if saved_labels is None: saved_labels = list(labels) # saving to file with open(list_filename, "w") as f: for l in saved_labels: f.write(l + '\n') return saved_labels
class TestDataset(Dataset): """ Dataset for .jpg images and labels """ def __init__(self, root: str, test_dir: str, dst_img_size: Tuple[int, int]): self._search_for_files(os.path.join(root, test_dir)) self.cache = ImageCache(force_rgb=True, dst_img_size=dst_img_size) # loading labels self.labels = ImageDataset.load_labels(root) if self.labels is None: print("Failed to load labels. Data root is " + root) return # checking for extra classes labels_set = set(self.labels) filtered_files = [] for filename in self.image_files: label = self.image_labels[filename] if label not in labels_set: # raise Exception('test label not in training set: ' + label) pass else: filtered_files.append(filename) if len(filtered_files) != len(self.image_files): print( 'Test files filtered to conform to training labels. %d files were excluded' % (len(self.image_files) - len(filtered_files))) self.image_files = filtered_files # indexing labels self.label_to_index = dict() for i, label in enumerate(self.labels): self.label_to_index[label] = i def __getitem__(self, index) -> Tuple[np.ndarray, int]: """ Returns test set image and its label. :param index: int index :return: tuple """ filename = self.image_files[index] label = self.image_labels[filename] img = self.cache.load(filename) return img, self.label_to_index[label] def __len__(self): return len(self.image_files) def _search_for_files(self, root_dir: str): """ Search for all image *.jpg files in a directory recuresively :param root_dir: directory to search in """ self.image_files = [] self.image_labels = {} for path in Path(root_dir).rglob('*.jpg'): file_path = str(path) base_dir = os.path.split(file_path)[0] label = os.path.split(base_dir)[1] self.image_files.append(file_path) self.image_labels[file_path] = label
class SettingsWidget(QtGui.QWidget): def __init__(self, parent=None): super(SettingsWidget, self).__init__(parent) self.currentObject = None self.lastObjectType = None self.useTypes = {0: "Ei käyttöä", 1: "Käytä toiseen esineeseen", 2: "Avaa jotakin", 3: "Laita johonkin", 4: "Poista este"} self.fadeTypes = {0: "Välittömästi", 1: "Häivytys"} self.layout = QtGui.QVBoxLayout() self.setLayout(self.layout) self.setSizePolicy(QtGui.QSizePolicy( QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)) self.editor = parent self.imageCache = ImageCache() self.createOptionFields() def displayOptions(self, gameObject): self.currentObject = gameObject objectType = gameObject.__class__.__name__ self.showWidgets(objectType) self.lastObjectType = objectType if (objectType == "Room"): self.setRoomOptions(gameObject) elif (objectType == "Sequence"): self.setSequenceOptions(gameObject) elif (objectType == "SequenceImage"): self.setSequenceImageOptions(gameObject) elif (objectType == "Start"): self.setStartOptions(gameObject) elif (objectType == "End"): self.setEndOptions(gameObject) elif (objectType == "Text"): self.setTextOptions(gameObject) elif (objectType == "Item"): self.setItemOptions(gameObject) elif (objectType == "Object"): self.setGenericOptions(gameObject) elif (objectType == "Door"): self.setDoorOptions(gameObject) elif (objectType == "Container"): self.setContainerOptions(gameObject) elif (objectType == "Obstacle"): self.setObstacleOptions(gameObject) elif (objectType == "JSONImage"): self.setJSONImageOptions(gameObject) elif (objectType == "MenuImage"): self.setJSONImageOptions(gameObject) elif (objectType == "BeginingImage"): self.setJSONImageOptions(gameObject) def showWidgets(self, objectType): if (self.lastObjectType): for item in self.itemSettings[self.lastObjectType]: item.hide() for item in self.itemSettings[objectType]: item.show() # Settings for the object view def createOptionFields(self): # Name self.nameLabel = QtGui.QLabel("Nimi") self.objectNameEdit = QtGui.QLineEdit() self.objectNameEdit.editingFinished.connect(self.changeName) # General image self.imgTextLabel = QtGui.QLabel("Kuva") self.objectImage = QtGui.QLabel(self) self.objectImage.mousePressEvent = lambda s: self.showImageDialog(self.changeObjectImage) self.useTextEdit = QtGui.QTextEdit() self.useTextEdit.setMaximumHeight(50) self.useTextEdit.focusOutEvent = lambda s: self.changeUseText() # Ending checkbox self.endingCheckbox = QtGui.QCheckBox() # Set text afterwards self.endingCheckbox.setText("Peli loppuu klikatessa?") self.endingCheckbox.stateChanged.connect(self.changeEndingCheckbox) # Music self.musicLabel = QtGui.QLabel("Musiikki") self.musicBtn = QtGui.QPushButton('Selaa...', self) self.musicBtn.setToolTip('Valitse musiikkitiedosto') self.musicBtn.resize(self.musicBtn.sizeHint()) self.musicBtn.clicked.connect(lambda: self.showMusicDialog(self.changeMusic)) self.musicTextEdit = QtGui.QLineEdit() self.musicTextEdit.setReadOnly(True) self.musicClear = QtGui.QPushButton('Ei musiikkia', self) self.musicClear.clicked.connect(self.clearMusic) # Where from dropdown box #self.whereFromLabel = QtGui.QLabel("Mistä kulkureiteistä tänne pääsee?") # TODO: whereFromCombo self.examineTextLabel = QtGui.QLabel("Teksti klikatessa:") self.examineTextEdit = QtGui.QTextEdit() self.examineTextEdit.setMaximumHeight(50) self.examineTextEdit.focusOutEvent = lambda s: self.changeExamineText() # Pickup text section self.pickupLabel = QtGui.QLabel("Poiminta") self.pickupLabelLine = self.createSeparator() self.pickupLabelLine.setFrameStyle(QtGui.QFrame.HLine | QtGui.QFrame.Raised) self.pickupTextLabel = QtGui.QLabel("Teksti poimiessa:") self.pickupTextEdit = QtGui.QTextEdit() self.pickupTextEdit.setMaximumHeight(50) self.pickupTextEdit.focusOutEvent = lambda s: self.changePickupText() # Object usage self.useLabel = QtGui.QLabel("Käyttö") self.useLabelLine = self.createSeparator() # Object type of usage self.useTypeCombo = QtGui.QComboBox(self) for i in self.useTypes: self.useTypeCombo.addItem(self.useTypes[i]) self.useTypeCombo.activated.connect(self.changeItemUseType) self.useTextLabel = QtGui.QLabel("Teksti käytettäessä:") # Use target self.useTargetCombo = self.createCombobox() self.updateUseTargetCombo() self.allTextsButton = QtGui.QPushButton("Nämä ja muut tekstit") self.allTextsButton.clicked.connect(self.showAllTexts) # Door widgets self.doorTransitionLabel = QtGui.QLabel("Mihin pääsee?") self.doorTransitionCombo = self.createCombobox() self.updateDoorTransitionCombo() self.doorInitialStateLabel = QtGui.QLabel("Tila alussa") self.doorInitialStateCombo = QtGui.QComboBox(self) self.doorInitialStateCombo.addItem("Kiinni") self.doorInitialStateCombo.addItem("Auki") self.doorInitialStateCombo.activated.connect(lambda s: self.objectComboboxHandler(self.doorInitialStateCombo, self.changeDoorInitialState)) self.openDoorImage = ObjectImageSettings("Avoin kulkureitti", "Avoimen kulkureitin nimi", parent=self) self.closedDoorImage = ObjectImageSettings("Suljettu kulkureitti", "Suljetun kulkureitin nimi", parent=self) self.lockedDoorImage = ObjectImageSettings("Lukittu kulkureitti", "Lukitun kulkureitin nimi", True, "Lukossa", parent=self) # Container widgets self.lockedContainerImage = ObjectImageSettings("Lukittu säiliö", "Lukitun säiliön nimi", True, "Lukossa", parent=self) self.fullContainerImage = ObjectImageSettings("Täysi säiliö", "Avoimen säiliön nimi", parent=self) self.emptyContainerImage = ObjectImageSettings("Tyhjä säiliö", "Tyhjän säiliön nimi", parent=self) # Obstacle widgets self.obstacleImage = ObjectImageSettings(None, "Esteen nimi", False, parent=self) self.obstacleBlocksLabel = QtGui.QLabel("Mitä estää?") self.obstacleBlocksCombo = self.createCombobox() self.updateObstacleBlocksCombo() self.whatGoesLabel = QtGui.QLabel("Mikä menee säiliöön?") self.whatGoesCombo = self.createCombobox() self.updateWhatGoesCombo() self.whatComesLabel = QtGui.QLabel("Mitä tulee säiliöstä?") self.whatComesCombo = self.createCombobox() self.updateWhatComesCombo() self.useConsumeCheckbox = QtGui.QCheckBox() # Set text afterwards self.useConsumeCheckbox.stateChanged.connect(self.changeUseConsume) self.outcomeLabel = QtGui.QLabel("Lopputulos") self.outcomeCombobox = self.createCombobox() self.updateOutcomeCombobox() # Sequence self.sequenceTimeLabel = QtGui.QLabel("Kuvan näyttöaika (0-10 sekuntia)") self.sequenceTimeEdit = QtGui.QLineEdit() self.sequenceTimeEdit.setInputMask("9,9") self.sequenceTimeEdit.focusOutEvent = lambda s: self.changeSequenceTime() self.sequenceFadeLabel = QtGui.QLabel("Kuvan vaihtumistapa") self.sequenceFadeCombo = QtGui.QComboBox(self) for i in self.fadeTypes: self.sequenceFadeCombo.addItem(self.fadeTypes[i]) self.sequenceFadeCombo.activated.connect(self.changeSequenceFadeCombo) # End self.textObjectTextLabel = QtGui.QLabel("Teksti") self.textObjectTextEdit = QtGui.QLineEdit() self.textObjectTextEdit.focusOutEvent = lambda s: self.changeTextObjectText() self.layout.addWidget(self.textObjectTextLabel) self.layout.addWidget(self.textObjectTextEdit) self.layout.addWidget(self.nameLabel) self.layout.addWidget(self.objectNameEdit) self.layout.addWidget(self.imgTextLabel) self.layout.addWidget(self.objectImage) self.layout.addWidget(self.musicLabel) self.layout.addWidget(self.musicTextEdit) self.layout.addWidget(self.musicBtn) self.layout.addWidget(self.musicClear) #self.layout.addWidget(self.whereFromLabel) self.layout.addWidget(self.endingCheckbox) self.layout.addWidget(self.examineTextLabel) self.layout.addWidget(self.examineTextEdit) self.layout.addWidget(self.pickupLabelLine) self.layout.addWidget(self.pickupLabel) self.layout.addWidget(self.pickupTextLabel) self.layout.addWidget(self.pickupTextEdit) self.layout.addWidget(self.useLabelLine) self.layout.addWidget(self.useLabel) self.layout.addWidget(self.useTypeCombo) self.layout.addWidget(self.useTargetCombo) self.layout.addWidget(self.useConsumeCheckbox) self.layout.addWidget(self.outcomeLabel) self.layout.addWidget(self.outcomeCombobox) self.layout.addWidget(self.useTextLabel) self.layout.addWidget(self.useTextEdit) self.layout.addWidget(self.allTextsButton) #self.layout.addWidget(self.doorTransitionLabelLine) self.layout.addWidget(self.doorTransitionLabel) self.layout.addWidget(self.doorTransitionCombo) self.layout.addWidget(self.doorInitialStateLabel) self.layout.addWidget(self.doorInitialStateCombo) self.layout.addWidget(self.openDoorImage) self.layout.addWidget(self.lockedDoorImage) self.layout.addWidget(self.closedDoorImage) self.layout.addWidget(self.whatGoesLabel) self.layout.addWidget(self.whatGoesCombo) self.layout.addWidget(self.whatComesLabel) self.layout.addWidget(self.whatComesCombo) self.layout.addWidget(self.fullContainerImage) self.layout.addWidget(self.lockedContainerImage) self.layout.addWidget(self.emptyContainerImage) self.layout.addWidget(self.obstacleBlocksLabel) self.layout.addWidget(self.obstacleBlocksCombo) self.layout.addWidget(self.obstacleImage) self.layout.addWidget(self.sequenceTimeLabel) self.layout.addWidget(self.sequenceTimeEdit) self.layout.addWidget(self.sequenceFadeLabel) self.layout.addWidget(self.sequenceFadeCombo) # Removebuttons self.removeObjectButton = QtGui.QPushButton("Poista tämä esine") self.layout.addWidget(self.removeObjectButton) self.removeObjectButton.clicked.connect(lambda: self.removeObject()) self.removeViewButton = QtGui.QPushButton("Poista tämä näkymä") self.layout.addWidget(self.removeViewButton) self.removeViewButton.clicked.connect(lambda: self.removeView()) # Which widgets are shown with each object self.itemSettings = { "Room": [ self.imgTextLabel, self.objectImage, self.nameLabel, self.objectNameEdit, self.musicLabel, self.musicTextEdit, self.musicBtn, self.musicClear, self.removeViewButton #self.whereFromLabel # TODO: doorCombo for "where from" values ], "Sequence": [ self.nameLabel, self.objectNameEdit, self.musicLabel, self.musicTextEdit, self.musicBtn, self.musicClear, self.removeViewButton ], "SequenceImage": [ self.imgTextLabel, self.objectImage, self.sequenceTimeLabel, self.sequenceTimeEdit, self.sequenceFadeLabel, self.sequenceFadeCombo, self.removeViewButton ], "End": [ self.imgTextLabel, self.objectImage, self.nameLabel, self.objectNameEdit, self.musicLabel, self.musicTextEdit, self.musicBtn, self.musicClear, ], "Text": [ self.textObjectTextLabel, self.textObjectTextEdit ], "BeginingImage": [ self.imgTextLabel, self.objectImage, ], "JSONImage": [ self.imgTextLabel, self.objectImage, ], "Start": [ self.musicLabel, self.musicTextEdit, self.musicBtn, self.musicClear, ], "MenuImage": [ self.imgTextLabel, self.objectImage, ], "Item": [ self.nameLabel, self.objectNameEdit, self.imgTextLabel, self.objectImage, self.examineTextLabel, self.examineTextEdit, self.pickupLabelLine, self.pickupLabel, self.pickupTextLabel, self.pickupTextEdit, self.useLabelLine, self.useLabel, self.useTypeCombo, self.useTargetCombo, self.useTextLabel, self.useTextEdit, self.allTextsButton, self.useConsumeCheckbox, self.outcomeLabel, self.outcomeCombobox, self.removeObjectButton ], "Object": [ self.nameLabel, self.objectNameEdit, self.imgTextLabel, self.objectImage, self.endingCheckbox, self.examineTextLabel, self.examineTextEdit, self.removeObjectButton ], "Door": [ #self.doorTransitionLabelLine, self.doorTransitionLabel, self.doorTransitionCombo, self.doorInitialStateLabel, self.doorInitialStateCombo, self.openDoorImage, self.closedDoorImage, self.lockedDoorImage, self.removeObjectButton ], "Container": [ self.lockedContainerImage, self.fullContainerImage, self.emptyContainerImage, self.whatGoesLabel, self.whatGoesCombo, self.whatComesLabel, self.whatComesCombo, self.removeObjectButton ], "Obstacle": [ self.obstacleImage, self.obstacleBlocksLabel, self.obstacleBlocksCombo, self.removeObjectButton ] } # Hide every widget for key in self.itemSettings: for item in self.itemSettings[key]: item.hide() # Update comboboxes having objectType objects def updateComboboxes(self, objectType): objectType = objectType.lower() if (objectType == "room"): self.updateDoorTransitionCombo() elif (objectType == "door"): self.updateObstacleBlocksCombo() elif (objectType == "item"): self.updateWhatGoesCombo() self.updateWhatComesCombo() self.updateOutcomeCombobox() elif (objectType == "object"): self.updateOutcomeCombobox() # Update every time self.updateUseTargetCombo() # Update other widgets self.lockedDoorImage.updateComboboxes(objectType) self.lockedContainerImage.updateComboboxes(objectType) def updateUseTargetCombo(self): self.updateItemCombobox(self.useTargetCombo, "Ei valittu", connectTo=self.changeUseTarget) def updateDoorTransitionCombo(self): self.updateItemCombobox(self.doorTransitionCombo, "Ei mihinkään", "room", connectTo=self.changeDoorTransition) def updateObstacleBlocksCombo(self): self.updateItemCombobox(self.obstacleBlocksCombo, "Ei mitään", ("door",), ("door",), noChoiceMethod=self.clearObstacleBlock, connectTo=self.changeObstacleBlock) def updateWhatGoesCombo(self): self.updateItemCombobox(self.whatGoesCombo, "Ei mikään", ("item",), ("item",), connectTo=self.changeWhatGoes) def updateWhatComesCombo(self): self.updateItemCombobox(self.whatComesCombo, "Ei mitään", ("item",), ("item",), connectTo=self.changeWhatComes) def updateOutcomeCombobox(self): self.updateItemCombobox(self.outcomeCombobox, "Ei valittu", ("object", "item"), ("object", "item"), noChoiceMethod=self.clearOutcome, connectTo=self.changeOutcome) def changeSequenceTime(self): time = int(float(self.sequenceTimeEdit.text().replace(",", "."))*1000) self.currentObject.setShowTime(time) def changeSequenceFadeCombo(self): doFade = (self.sequenceFadeCombo.currentIndex() == True) self.currentObject.setDoFade(doFade) def changeTextObjectText(self): self.currentObject.setText(self.textObjectTextEdit.text()) def changeEndingCheckbox(self): self.currentObject.setIsEnding(self.endingCheckbox.isChecked()) # Start menu def setStartOptions(self, startObject): # Start music self.setObjectMusic(startObject) # End view def setEndOptions(self, endObject): # End name self.setObjectName(overrideText=endObject.generalName) # End image self.setObjectImage(endObject.getRepresentingImage().getRepresentingImage().absoluteImagePath) # Text object def setTextOptions(self, textObject): self.textObjectTextEdit.setText(textObject.getText()) # Set either currentObject or the given object's music def setObjectMusic(self, gameObject=None): if not (gameObject): gameObject = self.currentObject # Music may return None which doesn't have split try: music = gameObject.getMusic().split("/")[-1] except AttributeError: music = "" self.musicTextEdit.setText(music) # Generic JSON images def setJSONImageOptions(self, imageObject): # Image self.setObjectImage(imageObject.getRepresentingImage().getRepresentingImage().absoluteImagePath) # Set the input field values for rooms def setRoomOptions(self, room): # Room name self.setObjectName(room, room.generalNameAdessive) # Room background self.setObjectImage(room.getRepresentingImage().getRepresentingImage().absoluteImagePath) # Room music self.setObjectMusic(room) def setSequenceOptions(self, sequence): # Sequence name self.setObjectName(sequence, sequence.generalNameAdessive) # Sequence background self.setObjectImage(sequence.getRepresentingImage().getRepresentingImage().absoluteImagePath) # Sequence music self.setObjectMusic(sequence) def setSequenceImageOptions(self, sequenceImage): # Image self.setObjectImage(sequenceImage.getRepresentingImage().getRepresentingImage().absoluteImagePath) # Set image display time. Convert into str and replace dots showTime = self.currentObject.getShowTime() if (showTime): time = str(showTime/1000).replace(".", ",") else: time = "0,0" self.sequenceTimeEdit.setText(time) # Image fade type doFade = self.currentObject.getDoFade() if not (doFade): doFade = False self.sequenceFadeCombo.setCurrentIndex(doFade) # Set the input field values for items def setItemOptions(self, item): imageObject = item.getRepresentingImage().getRepresentingImage() # Object name self.setObjectName(imageObject, item.generalNameAdessive) # Item image self.setObjectImage(imageObject.absoluteImagePath) # Examine text self.setExamineText(self.currentObject) # Pickup text pickupText = item.getPickupText() if not (pickupText): pickupText = "" self.pickupTextEdit.setText(pickupText) # Use type of the item itemTarget = self.editor.getItemUse(item) itemTargetType = itemTarget.__class__.__name__ useType = 0 if (itemTargetType in ("Object", "Item")): useType = 1 elif (itemTargetType == "Obstacle"): useType = 5 elif (itemTargetType in ("Door", "Container")): # Item may unlock door or container or may go into a container if (itemTarget.key == item): useType = 2 else: try: if (itemTarget.inItem == item): useType = 3 except AttributeError: pass self.setUseConsume() self.setItemUseType(useType) self.setItemUseTarget(itemTarget) self.setItemOutcome(self.currentObject.outcome) self.setUseText() # Set the input field values for generic objects def setGenericOptions(self, genericObject): # Object name self.setObjectName(genericObject, genericObject.generalNameAdessive) # Object image imageObject = genericObject.getRepresentingImage().getRepresentingImage() self.setObjectImage(imageObject.absoluteImagePath) # Ending if (self.currentObject.getIsEnding()): self.endingCheckbox.setCheckState(QtCore.Qt.CheckState.Checked) else: self.endingCheckbox.setCheckState(QtCore.Qt.CheckState.Unchecked) # Examine text self.setExamineText(self.currentObject) # Set the input field values for containers def setContainerOptions(self, container): # Set image settings for each image self.fullContainerImage.setSettings(container, container.fullImage) self.lockedContainerImage.setSettings(container, container.lockedImage) self.emptyContainerImage.setSettings(container, container.emptyImage) # Set what goes, what comes from the container self.setComboboxIndex(container.inItem, self.whatGoesCombo) self.setComboboxIndex(container.outItem, self.whatComesCombo) # Set the input field values for obstacles def setObstacleOptions(self, obstacle): self.obstacleImage.setSettings(obstacle, obstacle.blockingImage) def setObjectImage(self, imagePath, objectImage=None): imgPixmap = self.imageCache.createPixmap(imagePath) # TODO: Have spacing for smaller items if (imgPixmap.size().height() > 200): imgPixmap = imgPixmap.scaled(200, 200, QtCore.Qt.KeepAspectRatio) if (objectImage): objectImage.setPixmap(imgPixmap) else: self.objectImage.setPixmap(imgPixmap) # Set item use type def setItemUseType(self, typeIndex): self.useTypeCombo.setCurrentIndex(typeIndex) self.updateUseTargetCombobox(typeIndex, self.useTargetCombo) # Show extra options when selecting use on other object if (typeIndex == 1): self.useConsumeCheckbox.setText("Katoaako %s käytettäessä?" %(self.currentObject.getName())) self.useConsumeCheckbox.show() self.outcomeLabel.show() self.outcomeCombobox.show() else: self.useConsumeCheckbox.hide() self.outcomeLabel.hide() self.outcomeCombobox.hide() # When no use, hide and clear elements if (typeIndex == 0): self.useTargetCombo.hide() self.useTextLabel.hide() self.useTextEdit.hide() self.useTextEdit.clear() self.changeUseText() self.allTextsButton.hide() self.currentObject.clearTarget() else: self.useTargetCombo.show() self.useTextLabel.show() self.useTextEdit.show() self.allTextsButton.show() # Set item use target def setItemUseTarget(self, useItem): if (useItem): # Find the combobox item with the given item for i in range(self.useTargetCombo.count()): if (self.useTargetCombo.itemData(i) == useItem): self.useTargetCombo.setCurrentIndex(i) return self.useTargetCombo.setCurrentIndex(0) def setItemOutcome(self, outcomeItem): if (outcomeItem): # Find the combobox item with the given item for i in range(self.outcomeCombobox.count()): if (self.outcomeCombobox.itemData(i) == outcomeItem): self.outcomeCombobox.setCurrentIndex(i) return self.outcomeCombobox.setCurrentIndex(0) def setDoorInitialState(self): # Door open if (self.currentObject.closedImage or self.currentObject.lockedImage): self.doorInitialStateCombo.setCurrentIndex(0) # Door closed else: self.doorInitialStateCombo.setCurrentIndex(1) self.changeDoorInitialState() def setDoorOptions(self, doorObject): # Set each image's settings self.closedDoorImage.setSettings(doorObject, doorObject.closedImage) self.lockedDoorImage.setSettings(doorObject, doorObject.lockedImage) self.openDoorImage.setSettings(doorObject, doorObject.openImage) # Door transition room self.setComboboxIndex(doorObject.transition, self.doorTransitionCombo) # Set door open or closed in the beginning self.setDoorInitialState() # Set use item for items def setUseText(self, textEdit=None, item=None): if (self.useTypeCombo.currentIndex() == 0): return if not (item): item = self.currentObject useText = item.getUseText() if not (useText): useText = "" if (textEdit): textEdit.setText(useText) else: self.useTextEdit.setText(useText) # Set examine text for the given object def setExamineText(self, gameObject, textEdit=None): try: text = gameObject.getExamineText() except AttributeError: text = "" if (textEdit): textEdit.setText(text) else: self.examineTextEdit.setText(text) # Set any game object name def setObjectName(self, gameObject=None, textStart="Objektilla", textEdit=None, overrideText=None): if not (gameObject): gameObject = self.currentObject if (overrideText): name = overrideText else: # Given image may be None try: name = gameObject.getName() except AttributeError: name = "" if (name == None): name = "%s ei ole nimeä" %(textStart) # If textEdit is defined, set its text instead if (textEdit): textEdit.setText(name) else: self.objectNameEdit.setText(name) def setUseConsume(self): isConsumed = self.useConsumeCheckbox.isChecked() self.currentObject.setConsume(isConsumed) if (isConsumed): self.useConsumeCheckbox.setCheckState(QtCore.Qt.CheckState.Checked) else: self.useConsumeCheckbox.setCheckState(QtCore.Qt.CheckState.Unchecked) def changeWhereLocated(self, combobox): print("Change where located to",combobox.itemData(combobox.currentIndex())) # Text that comes after using an item def changeUseText(self): # TODO: Disable text field if no target is selected self.currentObject.setUseText(self.useTextEdit.toPlainText()) def changePickupText(self): self.currentObject.setPickupText(self.pickupTextEdit.toPlainText()) def changeExamineText(self, textEdit=None, gameObject=None): if not (gameObject): gameObject = self.currentObject if not (textEdit): textEdit = self.examineTextEdit gameObject.setExamineText(textEdit.toPlainText()) def changeDoorInitialState(self): # Initially closed, all states (closed, locked, open) are possible if (self.doorInitialStateCombo.currentIndex() == 0): self.closedDoorImage.setDisabled(False) self.lockedDoorImage.setDisabled(False) self.openDoorImage.setDisabled(False) # Add door's closed image self.currentObject.setClosed(True) self.currentObject.closedImage.placeholderImage.setSource(self.editor.getPlaceholderImagePath("Door")) # Initially open, only "open" state is possible else: self.closedDoorImage.setDisabled(True) self.lockedDoorImage.setDisabled(True) self.openDoorImage.setDisabled(False) # Remove door's closed and locked images self.currentObject.setClosed(False) self.currentObject.setLocked(False) # Change the image of a gameobject def changeObjectImage(self, imagePath, image=None, gameObject=None): # If no image, a default image var will be used # TODO: Copy the chosen image to the 'images' folder of the scenario? self.currentObject.getRepresentingImage().setSource(imagePath) self.setObjectImage(imagePath, image) print(imagePath) if not (gameObject): gameObject = self.currentObject self.editor.drawRoomItems() self.updateParent() self.editor.updateSpaceTab() # Change music def changeMusic(self, imagePath): self.currentObject.setMusic(imagePath) def changeUseConsume(self): self.currentObject.setConsume(self.useConsumeCheckbox.isChecked()) def changeOutcome(self): self.currentObject.setOutcome(self.outcomeCombobox.itemData(self.outcomeCombobox.currentIndex())) def clearOutcome(self): self.currentObject.setOutcome(None) def clearUseTarget(self): print("Clear useTarget!") # TODO: This is run even when populating the combobox #self.currentObject.clearTarget() def changeObstacleBlock(self): self.currentObject.setBlockTarget(self.obstacleBlocksCombo.itemData(self.obstacleBlocksCombo.currentIndex())) def clearObstacleBlock(self): self.currentObject.clearBlockTarget() def changeWhatGoes(self): self.currentObject.setInItem(self.whatGoesCombo.itemData(self.whatGoesCombo.currentIndex())) def clearWhatGoes(self): self.currentObject.clearInItem() def changeWhatComes(self): self.currentObject.setOutItem(self.whatComesCombo.itemData(self.whatComesCombo.currentIndex())) def clearWhatComes(self): self.currentObject.clearOutItem() def changeDoorTransition(self): self.currentObject.setTransition(self.doorTransitionCombo.itemData(self.doorTransitionCombo.currentIndex())) def changeName(self, textEdit=None, gameObject=None): if not (gameObject): gameObject = self.currentObject if (textEdit): text = textEdit.text() else: text = self.objectNameEdit.text() if (len(text) == 0): text = "%s ei ole nimeä" %(gameObject.generalNameAdessive) gameObject.setName(text) self.updateParent() # Update parent tab elements def updateParent(self): if (self.currentObject.__class__.__name__ in ("Room", "Sequence")): self.editor.drawRooms() else: self.editor.drawRoomItems() # Change object use type def changeItemUseType(self, index): self.setItemUseType(index) self.setItemUseTarget(None) self.setItemOutcome(None) # Set item use target def changeUseTarget(self): index = self.useTargetCombo.currentIndex() targetType = self.useTargetCombo.itemData(index).__class__.__name__ selectedObject = self.useTargetCombo.itemData(index) objectRole = 0 useType = self.useTypeCombo.currentIndex() if (targetType in ("Door", "Container")): # Unlock something and target object is not set into locked state if (useType == 2 ): # TODO: Really nullify old key? # Get old current object's key and nullify it self.currentObject.clearTarget() # Nullify selected door's key if (self.useTargetCombo.itemData(index).key): self.useTargetCombo.itemData(index).key.clearTarget() # Set the object to be locked with new key imagePath = self.editor.getPlaceholderImagePath(targetType) selectedObject.setLocked(True, imagePath, self.currentObject) # Put into container elif (useType == 3): objectRole = 1 # Get from container #elif (useType == 4): # objectRole = 2 self.currentObject.setTargetObject(selectedObject, objectRole) self.setUseText() # Create new game object def createObject(self, objectType): self.editor.createObject(objectType) self.updateComboboxes(objectType) def removeObject(self): self.editor.removeObjectsButtonClicked() def removeView(self): self.editor.removeViewsButtonClicked() def showAllTexts(self): # TODO: Select the actual object self.editor.tabWidget.setCurrentIndex(2) #self.currentObject. def clearMusic(self): self.currentObject.clearMusic() self.musicTextEdit.clear() # Sets the index of a combobox according to given targetObject def setComboboxIndex(self, targetObject, combobox): # Find the combobox item with the given item for i in range(combobox.count()): if (combobox.itemData(i) == targetObject): combobox.setCurrentIndex(i) return combobox.setCurrentIndex(0) # Create and return a plain combobox def createCombobox(self): combobox = QtGui.QComboBox(self) combobox.setIconSize(QtCore.QSize(50,50)) return combobox # Create combobox from given items with default of all item types def updateItemCombobox(self, combobox, noChoiceText, objectTypes=None, addChoices=None, noChoiceMethod=None, connectTo=None): if not (objectTypes): objectTypes = ("object", "item", "door", "container", "obstacle") if (objectTypes == "room"): self.populateRoomCombobox(combobox, addChoices) else: self.populateCombobox(objectTypes, combobox, noChoiceText, addChoices, noChoiceMethod) combobox.activated.connect(lambda s: self.objectComboboxHandler(combobox, connectTo)) return combobox # Populate a given combobox with game rooms def populateRoomCombobox(self, combobox, addChoice=True): if (addChoice): imgPixmap = self.imageCache.createPixmap(self.editor.newIconPath) combobox.addItem(imgPixmap, "Lisää uusi huone") for room in self.editor.getRoomObjects(): # TODO: Some model to eliminate redundancy from getName/roomName patterns roomName = room.getName() if not (roomName): roomName = "%s ei ole nimeä" %(room.generalNameAdessive) imgPixmap = self.imageCache.createPixmap(room.getRepresentingImage().getRepresentingImage().absoluteImagePath) roomIcon = QtGui.QIcon(imgPixmap) combobox.addItem(roomIcon, roomName, userData=room) # Create use target combobox def updateUseTargetCombobox(self, useType, combobox): if (useType == 0): objectTypes = () elif (useType == 1): objectTypes = ("item", "object") elif (useType == 2): objectTypes = ("door", "container") elif (useType == 3): objectTypes = ("container",) elif (useType == 4): objectTypes = ("obstacle",) self.populateCombobox(objectTypes, combobox, "Ei valittu", objectTypes, self.clearUseTarget) # Handle item combobox item choosing callback def objectComboboxHandler(self, combobox, callback): target = combobox.itemData(combobox.currentIndex()) targetType = target.__class__.__name__ # If chosen item is something else than a game object don't do callback if (targetType == "method"): target() elif (targetType == "str"): self.createObject(target) else: callback() # Populate a given combobox with given types of objects # categorized by game rooms def populateCombobox(self, objectTypes, combobox, noChoiceText=None, addChoices=None, noChoiceMethod=None): combobox.clear() itemCounter = 0 # Add the given string as the first item if (noChoiceText): imgPixmap = self.imageCache.createPixmap(self.editor.noChoiceIconPath) combobox.addItem(imgPixmap, noChoiceText, userData=noChoiceMethod) itemCounter = 1 # Add items to add given types of objects if (addChoices): imgPixmap = self.imageCache.createPixmap(self.editor.newIconPath) for choice in addChoices: combobox.addItem(imgPixmap, "Lisää uusi %s" %(self.editor.getGeneralName(choice).lower()), userData=choice) itemCounter += 1 for objType in objectTypes: objRooms = self.editor.getObjectsByType(objType) # Combobox has rooms with their obstacles under them for room in objRooms: roomObject = room["room"] roomName = roomObject.getName() if not (roomName): roomName = "%s ei ole nimeä" %(roomObject.generalNameAdessive) imgPixmap = self.imageCache.createPixmap(roomObject.getRepresentingImage().getRepresentingImage().absoluteImagePath) roomIcon = QtGui.QIcon(imgPixmap) # Add room to the combobox and disallow choosing it combobox.addItem(roomIcon, roomName) combobox.setItemData(itemCounter, 0, QtCore.Qt.UserRole - 1); itemCounter += 1 # TODO: Indendation of objects in the combobox # Add objects under the room for obj in room["objects"]: # Don't display the triggering item itself if (obj == self.currentObject): continue if (obj.getClassname() == "Text"): continue imageObject = obj.getRepresentingImage().getRepresentingImage() imgPixmap = self.imageCache.createPixmap(imageObject.absoluteImagePath) targetIcon = QtGui.QIcon(imgPixmap) objectName = obj.getName() if not (objectName): objectName = "%s ei ole nimeä" %(obj.generalNameAdessive) combobox.addItem(targetIcon, objectName, userData=obj) itemCounter += 1 def showMusicDialog(self, callBack): fname, _ = QtGui.QFileDialog.getOpenFileName(self, 'Valitse musiikkitiedosto','~', "Musiikkitiedostot (*.mp3 *.ogg)") if (len(fname) != 0): self.musicTextEdit.setText(fname.split("/")[-1]) callBack(fname) def showImageDialog(self, callBack): fname, _ = QtGui.QFileDialog.getOpenFileName(self, 'Valitse taustakuva','~', "Taustakuvat (*.png)") if (len(fname) != 0): callBack(fname) def createSeparator(self): label = QtGui.QLabel("") label.setFrameStyle(QtGui.QFrame.HLine | QtGui.QFrame.Raised) return label
class Game: tile_dir = "data/images/tiles/" ui_dir = "data/images/ui/" def __init__(self): # Define window properties self.window_size = self.window_width, self.window_height = 640, 640 self.tile_size = 32 self.depth = 0 self.flags = 0 self.fps = 60 # Initialize pygame pygame.init() # Define basic pygame properties self.screen = pygame.display.set_mode(self.window_size, self.flags, self.depth) self.clock = pygame.time.Clock() # Load the image cache self.tile_cache = ImageCache(Game.tile_dir) self.ui_cache = ImageCache(Game.ui_dir) # Define the key entities and default to None until we start the main game loop self.player = None def main_menu_loop(self): start_game = False # Create buttons with the static callback functions new_game_img = self.ui_cache.get_image("new_game_but") new_game_img_hov = self.ui_cache.get_image("new_game_but_hover") new_game_button = Button(self.get_half_width(), self.get_half_height() - 50, new_game_img, new_game_img_hov, 200, 50, start_game_cb) quit_img = self.ui_cache.get_image("quit_but") quit_img_hover = self.ui_cache.get_image("quit_but_hover") quit_button = Button(self.get_half_width(), self.get_half_height() + 10, quit_img, quit_img_hover, 200, 50, quit_game) # Define sprite group for buttons to easily draw button_entities = pygame.sprite.Group() button_entities.add((new_game_button, quit_button)) # Retrieve other UI images from cache bg_img = self.ui_cache.get_image("menu_bg") credits_img = self.ui_cache.get_image("credits") # Only draw background and other static images once to screen self.screen.blit(bg_img, (0, 0)) self.screen.blit(credits_img, (20, self.window_height - 50)) # Set the screen title pygame.display.set_caption("The Forming") while not start_game: self.clock.tick(self.fps) mouse_clicked = False # Loop through all events for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() if event.type == pygame.MOUSEBUTTONDOWN: mouse_clicked = True if event.type == pygame.KEYDOWN: pass # Update the buttons. Start game will return True if clicked, exiting the menu loop start_game = new_game_button.update(pygame.mouse.get_pos(), mouse_clicked) quit_button.update(pygame.mouse.get_pos(), mouse_clicked) button_entities.draw(self.screen) pygame.display.flip() self.main_game_loop() def main_game_loop(self): # Define the entity groups character_entities = pygame.sprite.Group() # All character entities (including Player.py) built_entities = pygame.sprite.Group() # Anything the player has built # Build the level level = Level() level.generate(self.tile_cache) # Create the player player_sprites = "data/images/player/" camera = Camera(main_camera, level.width * self.tile_size, level.height * self.tile_size, self.window_width, self.window_height) self.player = Player(32, 32, player_sprites, self.tile_size, self.tile_size, 2, camera) character_entities.add(self.player) # Create cursor entity for better collisions cursor = Cursor() game_running = True up, down, left, right = 0, 0, 0, 0 while game_running: # Reset game variables mouse_clicked = False for event in pygame.event.get(): if event.type == pygame.QUIT: quit_game() # Key down events if event.type == pygame.KEYDOWN: if event.key in (pygame.K_UP, pygame.K_w): up = 1 if event.key in (pygame.K_DOWN, pygame.K_s): down = 1 if event.key in (pygame.K_LEFT, pygame.K_a): left = 1 if event.key in (pygame.K_RIGHT, pygame.K_d): right = 1 # Key up events if event.type == pygame.KEYUP: if event.key in (pygame.K_UP, pygame.K_w): up = 0 if event.key in (pygame.K_DOWN, pygame.K_s): down = 0 if event.key in (pygame.K_LEFT, pygame.K_a): left = 0 if event.key in (pygame.K_RIGHT, pygame.K_d): right = 0 cursor.update() for tile in level.terrain: self.screen.blit(tile.image, self.player.camera.apply(tile)) for tile in level.obstacles: self.screen.blit(tile.image, self.player.camera.apply(tile)) for character in character_entities: self.screen.blit(character.image, self.player.camera.apply(character)) self.player.update(up, down, left, right, level.obstacles) pygame.display.flip() self.main_menu_loop() def get_half_width(self): return self.window_width / 2 def get_half_height(self): return self.window_height / 2
class Game: def __init__(self, window_size, block_size): self.window_size = window_size self.block_size = block_size # Initialise the pygame variables pygame.init() self.screen = pygame.display.set_mode(window_size) self.clock = pygame.time.Clock() self.fps = 25 # Initialize the image cache self.image_cache = ImageCache("data/images") # Create entity groups for PyGame self.environment_entities = pygame.sprite.Group() self.player_entities = pygame.sprite.Group() # Create the player self.player = Player(32, 32, self.image_cache) self.player_entities.add(self.player) # Create the level self.level = DiamondSquare(6, 0.05).get_grid_2D() # Random map created using Diamond Square def run(self): self.start_menu() self.main_game() def start_menu(self): start_game = False half_screen_width = self.window_size[0] / 2 half_screen_height = self.window_size[1] / 2 # Create the buttons for the start menu new_game_button = Button("new_game", half_screen_width, half_screen_height - 50, self.image_cache.load_image("New_Game.png"), self.image_cache.load_image("New_Game_Hover.png")) quit_game_button = Button("exit_game", half_screen_width, half_screen_height + 10, self.image_cache.load_image("Quit_Game.png"), self.image_cache.load_image("Quit_Game_Hover.png")) button_entities = pygame.sprite.Group() button_entities.add((new_game_button, quit_game_button)) # Load the start menu background background = self.image_cache.load_image("Menu_Background.png") self.screen.blit(background, (0, 0)) # Load the credit image credit_image = self.image_cache.load_image("Credits.png") self.screen.blit(credit_image, (20, self.window_size[1] - 50)) while not start_game: self.clock.tick(self.fps) current_fps = float(self.clock.get_fps()) # Update the title and display the current FPS pygame.display.set_caption("The Forming | FPS: " + str(current_fps)) mouse_clicked = False # Handle the events for the game for event in pygame.event.get(): # Quit the game if event.type == QUIT: pygame.quit() if event.type == MOUSEBUTTONDOWN: mouse_clicked = True if event.type == KEYDOWN: if event.key == K_F1: # Take screenshot pass # Reloading all images self.screen.blit(background, (0, 0)) self.screen.blit(credit_image, (20, self.window_size[1] - 50)) # Handle the buttons mouse_pos = pygame.mouse.get_pos() new_game_button.update(mouse_pos) quit_game_button.update(mouse_pos) if new_game_button.mouse_collision() and mouse_clicked: start_game = True if quit_game_button.mouse_collision() and mouse_clicked: pygame.quit() button_entities.draw(self.screen) pygame.display.update() def main_game(self): # Set the default control flags up = down = left = right = False exit_game = False walking = False self.load_level() # Create the environment assets level_size = (len(self.level[0]) * self.block_size[0], len(self.level) * self.block_size[1]) camera = Camera(level_size, self.window_size) mouse = Mouse(pygame.mouse.get_pos()) mouse_clicked = False mosue_right_clicked = False while not exit_game: # Reset control flags each loop mouse_clicked = False mouse_right_clicked = False # Handle pygame self.clock.tick(self.fps) # Load title displaying true FPS current_fps = float(self.clock.get_fps()) pygame.display.set_caption("The Forming | FPS: " + str(current_fps)) # Event Handling for event in pygame.event.get(): if event.type == QUIT: pygame.quit() # Keydown events if event.type == KEYDOWN: if event.key == K_UP or event.key == K_w: up = True elif event.key == K_DOWN or event.key == K_s: down = True elif event.key == K_LEFT or event.key == K_a: left = True elif event.key == K_RIGHT or event.key == K_d: right = True if event.type == KEYUP: if event.key == K_UP or event.key == K_w: up = False elif event.key == K_DOWN or event.key == K_s: down = False elif event.key == K_LEFT or event.key == K_a: left = False elif event.key == K_RIGHT or event.key == K_d: right = False # Mouse events if event.type == MOUSEBUTTONDOWN: if event.button == 1: mouse_clicked = True elif event.button == 3: mouse_right_clicked = True if event.type == MOUSEBUTTONUP: if event.button == 1: mouse_clicked = False elif event.button == 3: mouse_right_clicked = False # Update the entities camera.update(self.player) self.player.update(up, down, left, right, level_size) for tile in self.environment_entities: self.screen.blit(tile.image, camera.apply(tile)) for player in self.player_entities: self.screen.blit(player.image, camera.apply(player)) mouse.update(pygame.mouse.get_pos()) pygame.display.update() def load_level(self): x = 0 y = 0 for y_tile in self.level: x = 0 for x_tile in y_tile: print x_tile if 0 == x_tile <= 0.5: tile = EnvironmentTile(x, y, self.block_size[0], self.block_size[1], "Water", "Water", self.image_cache.load_image("Water.png")) elif 0.5 < x_tile <= 0.55: tile = EnvironmentTile(x, y, self.block_size[0], self.block_size[1], "Sand", "Sand", self.image_cache.load_image("Sand.png")) else: tile = EnvironmentTile(x, y, self.block_size[0], self.block_size[1], "Grass", "Grass", self.image_cache.load_image("Grass1.png")) self.environment_entities.add(tile) x += 32 y += 32
def __init__(self): #init threading gobject.threads_init() #keep track of the window size self.window_height=0 self.window_width=0 self.window_is_hidden = False self.has_status_icon = False #keep track of the initial conversation id so that conversations don't colide self.conversation_id="0" #keep track of the filters self.filters ={'users':[],'strings':[]} self.options={'run_as_tray_app':False,'context_backwards':False,'no_avatars':False,'notifications':True,'notify_replies':False} #keep track of the direct_message requests self.last_direct_message_time=0 #something something direct message self.is_direct_message_mode=False self.direct_message_to=None self.waiting_requests=0 self.is_first_dents = True #keep track of the respond to id self.respond_to_id=0 self.pre_group_page=None self.pre_user_page=None #keep track of the last time statuses where pulled self.last_get_statuses = 0 #what are the assets? asset_dir = 'assets' heybuddy_dir = os.path.dirname( os.path.realpath( __file__ ) ) self.readme_file = os.path.join(heybuddy_dir,'README.txt') self.standard_icon_path = os.path.join(heybuddy_dir,asset_dir,'icon.png') self.direct_icon_path = os.path.join(heybuddy_dir,asset_dir,'direct_icon.png') self.networking_icon_path = os.path.join(heybuddy_dir,asset_dir,'icon1.png') self.throbber_icon_path = os.path.join(heybuddy_dir,asset_dir,'throbber.gif') self.default_icon_path = self.standard_icon_path self.conf = Configuration(app_name) #has the account info been authenticated? self.credentials_verified = self.conf.get_bool('access', 'credentials_verified') self.xmlprocessor = XMLProcessor() #create a regex to replace parts of a dent self.regex_tag = re.compile("(^| )#([\w-]+)", re.UNICODE) self.regex_group = re.compile("(^| )!([\w-]+)") self.regex_user=re.compile("(^|[^A-z0-9])@(\w+)") self.regex_url=re.compile("(http[s]?://.*?)(\.$|\. |\s|$)",re.IGNORECASE) #get the initial dents self.initial_dents = self.conf.get('settings','initial_dents',default='20' ) self.dent_limit = int(self.initial_dents)*2 #get the pull time self.pull_time = self.conf.get('settings','pull_time',default='60') self.pull_time_changed_bool = False self.pull_time_mentions = False #build the gui self.build_gui() #where is the certs file? ca_certs_files = [ "/etc/ssl/certs/ca-certificates.crt", "/etc/ssl/certs/ca-bundle.crt", ] #what if there isn't a cert_file cert_file=None #determine the certs_file for f in ca_certs_files: if os.path.exists(f): cert_file=f break #create the communicator self.comm = Communicator(app_name, cert_file) self.comm.connect('statusesXML',self.process_statusesXML,self.dentspage) self.comm.connect('mentionsXML',self.process_statusesXML,self.mentionspage) self.comm.connect('favoritesXML', self.process_statusesXML,self.favoritespage) self.comm.connect('group-statusesXML',self.process_statusesXML,self.grouppage) self.comm.connect('user-statusesXML',self.process_statusesXML,self.userpage) self.comm.connect('direct_messagesXML',self.process_statusesXML,self.directspage,True) self.comm.connect('conversationXML',self.process_conversationXML) self.comm.connect('userXML',self.process_userXML) self.comm.connect('groupXML',self.process_groupXML) self.comm.connect('new-statusXML',self.process_new_statusXML) self.comm.connect('redent-statusXML',self.process_new_statusXML) self.comm.connect('user_is_friendXML',self.process_user_is_friendXML) self.comm.connect('user_is_memberXML',self.process_user_is_memberXML) self.comm.connect('friendshipXML',self.process_friendshipXML) self.comm.connect('exception-caught',self.process_communication_exception) self.comm.connect('widget-image',self.process_widget_image) self.comm.connect('direct-messageXML',self.process_new_directXML) self.comm.connect('verify_credentialsXML',self.process_verifycredentialsXML) self.comm.connect('configXML',self.process_configXML) #create an image cacher thingy self.imagecache = ImageCache() self.imagecache.set_disabled( self.conf.get_bool_option('no_avatars') ) self.imagecache.connect('get-widget-image', self.get_widget_image) #Create notify-er if has pynotify if has_pynotify: self.notify = Notify() #align the window self.align_window() # do we need to create the status icon if self.conf.get_bool_option('run_as_tray_app'): self.create_status_icon()
class application : def __init__(self): #init threading gobject.threads_init() #keep track of the window size self.window_height=0 self.window_width=0 self.window_is_hidden = False self.has_status_icon = False #keep track of the initial conversation id so that conversations don't colide self.conversation_id="0" #keep track of the filters self.filters ={'users':[],'strings':[]} self.options={'run_as_tray_app':False,'context_backwards':False,'no_avatars':False,'notifications':True,'notify_replies':False} #keep track of the direct_message requests self.last_direct_message_time=0 #something something direct message self.is_direct_message_mode=False self.direct_message_to=None self.waiting_requests=0 self.is_first_dents = True #keep track of the respond to id self.respond_to_id=0 self.pre_group_page=None self.pre_user_page=None #keep track of the last time statuses where pulled self.last_get_statuses = 0 #what are the assets? asset_dir = 'assets' heybuddy_dir = os.path.dirname( os.path.realpath( __file__ ) ) self.readme_file = os.path.join(heybuddy_dir,'README.txt') self.standard_icon_path = os.path.join(heybuddy_dir,asset_dir,'icon.png') self.direct_icon_path = os.path.join(heybuddy_dir,asset_dir,'direct_icon.png') self.networking_icon_path = os.path.join(heybuddy_dir,asset_dir,'icon1.png') self.throbber_icon_path = os.path.join(heybuddy_dir,asset_dir,'throbber.gif') self.default_icon_path = self.standard_icon_path self.conf = Configuration(app_name) #has the account info been authenticated? self.credentials_verified = self.conf.get_bool('access', 'credentials_verified') self.xmlprocessor = XMLProcessor() #create a regex to replace parts of a dent self.regex_tag = re.compile("(^| )#([\w-]+)", re.UNICODE) self.regex_group = re.compile("(^| )!([\w-]+)") self.regex_user=re.compile("(^|[^A-z0-9])@(\w+)") self.regex_url=re.compile("(http[s]?://.*?)(\.$|\. |\s|$)",re.IGNORECASE) #get the initial dents self.initial_dents = self.conf.get('settings','initial_dents',default='20' ) self.dent_limit = int(self.initial_dents)*2 #get the pull time self.pull_time = self.conf.get('settings','pull_time',default='60') self.pull_time_changed_bool = False self.pull_time_mentions = False #build the gui self.build_gui() #where is the certs file? ca_certs_files = [ "/etc/ssl/certs/ca-certificates.crt", "/etc/ssl/certs/ca-bundle.crt", ] #what if there isn't a cert_file cert_file=None #determine the certs_file for f in ca_certs_files: if os.path.exists(f): cert_file=f break #create the communicator self.comm = Communicator(app_name, cert_file) self.comm.connect('statusesXML',self.process_statusesXML,self.dentspage) self.comm.connect('mentionsXML',self.process_statusesXML,self.mentionspage) self.comm.connect('favoritesXML', self.process_statusesXML,self.favoritespage) self.comm.connect('group-statusesXML',self.process_statusesXML,self.grouppage) self.comm.connect('user-statusesXML',self.process_statusesXML,self.userpage) self.comm.connect('direct_messagesXML',self.process_statusesXML,self.directspage,True) self.comm.connect('conversationXML',self.process_conversationXML) self.comm.connect('userXML',self.process_userXML) self.comm.connect('groupXML',self.process_groupXML) self.comm.connect('new-statusXML',self.process_new_statusXML) self.comm.connect('redent-statusXML',self.process_new_statusXML) self.comm.connect('user_is_friendXML',self.process_user_is_friendXML) self.comm.connect('user_is_memberXML',self.process_user_is_memberXML) self.comm.connect('friendshipXML',self.process_friendshipXML) self.comm.connect('exception-caught',self.process_communication_exception) self.comm.connect('widget-image',self.process_widget_image) self.comm.connect('direct-messageXML',self.process_new_directXML) self.comm.connect('verify_credentialsXML',self.process_verifycredentialsXML) self.comm.connect('configXML',self.process_configXML) #create an image cacher thingy self.imagecache = ImageCache() self.imagecache.set_disabled( self.conf.get_bool_option('no_avatars') ) self.imagecache.connect('get-widget-image', self.get_widget_image) #Create notify-er if has pynotify if has_pynotify: self.notify = Notify() #align the window self.align_window() # do we need to create the status icon if self.conf.get_bool_option('run_as_tray_app'): self.create_status_icon() def build_gui(self): #build the GUI self.mainwindow=MainWindow.MainWindow(app_name,version,branch) try: self.mainwindow.set_icon_from_file(self.default_icon_path) except: pass self.mainwindow.set_textlimit( self.conf.textlimit() ) self.mainwindow.set_ctrl_enter( self.conf.get_bool_option('ctrl_enter') ) self.mainwindow.connect('quit', self.quit_triggered ) self.mainwindow.connect('window-to-tray', self.window_to_tray ) self.mainwindow.connect('update-status',self.update_status) self.mainwindow.connect('get-conversation',self.get_conversation) self.mainwindow.connect('show-user',self.get_user_info) self.mainwindow.connect('show-group',self.get_group_info) self.mainwindow.connect('notebook-page-change',self.page_change) self.mainwindow.connect('follow-user',self.follow_user) self.mainwindow.connect('join-group',self.join_group) self.mainwindow.connect('clear-respond-to-id',self.clear_respond_to_id) #keep track of the window size self.mainwindow.connect('size-allocate', self.window_size_allocate) #self.mainwindow.connect('window-state-event', self.mainwindow_state_event) self.mainwindow.connect('delete-event', self.mainwindow_delete_event) # local function to create a closeable tab label for closeable tabs def closeable_tab_label(caption, tab): tablabel = gtk.HBox(False,2) tablabel.pack_start(gtk.Label(caption),False,False,0) closebutton = gtk.Button() closeicon = gtk.Image() closeicon.set_from_stock(gtk.STOCK_CLOSE,gtk.ICON_SIZE_MENU) closebutton.set_image(closeicon) closebutton.set_relief(gtk.RELIEF_NONE) tinybutton_style = gtk.RcStyle() tinybutton_style.xthickness = 0 tinybutton_style.ythickness = 0 closebutton.modify_style(tinybutton_style) if tab != None: # if this isn't a mock-add closebutton.connect('clicked',tab.close) #don't show a tooltip on maemo if not has_hildon: closebutton.set_tooltip_text(_("Close")) tablabel.pack_start(closebutton,False,False,0) tablabel.show_all() return tablabel # do a mock add of dentspage, with a close label, so as to determine height needed for uncloseable tabs' labels, then break it all down again # this is ridiculously hacky, but it works, and doesn't leave anything behind self.dentspage = ScrollPage() self.mock_label = closeable_tab_label(_("Dents"),None) self.mainwindow.notebook.append_page(self.dentspage,self.mock_label) self.mainwindow.show_all() # we have to do this so the tab gets actualised, and thus gets a height min_tab_height = self.mock_label.allocation.height self.mainwindow.hide_all() self.mainwindow.notebook.remove_page(-1) del self.mock_label # local function to create a label the same height as the closeable tabs' labels def uncloseable_tab_label(caption): tablabel = gtk.Label(caption) tablabel.set_size_request(-1,min_tab_height) tablabel.show() return tablabel # create and add all of the pages self.dentspage = ScrollPage() self.mainwindow.notebook.append_page(self.dentspage,uncloseable_tab_label(_("Dents") ) ) self.mentionspage = ScrollPage() self.mainwindow.notebook.append_page(self.mentionspage,uncloseable_tab_label(_("Mentions")) ) self.favoritespage = ScrollPage() self.mainwindow.notebook.append_page(self.favoritespage,uncloseable_tab_label(_("Favorites")) ) self.directspage = ScrollPage() self.mainwindow.notebook.append_page(self.directspage,uncloseable_tab_label(_("Directs")) ) #make the conversation page self.contextpage=ContextPage() self.contextpage.connect('context-page-hide',self.hide_contextpage) #add the contextpage context_label = closeable_tab_label(_("Context"), self.contextpage) self.mainwindow.notebook.append_page(self.contextpage, context_label) #create a user page self.userpage=UserPage() self.userpage.connect('user-page-hide',self.hide_userpage) self.userpage.connect('follow-user',self.follow_user) self.userpage.connect('direct-clicked',self.direct_clicked) self.userpage.connect('open-link',self.open_link) self.userpage.connect('block-create',self.block_create) self.userpage.connect('block-destroy',self.block_destroy) #add the userpage user_label = closeable_tab_label(_("User"),self.userpage ) self.mainwindow.notebook.append_page(self.userpage, user_label) #create a Group page self.grouppage=GroupPage() self.grouppage.connect('group-page-hide',self.hide_grouppage) self.grouppage.connect('join-group',self.join_group) self.grouppage.connect('open-link',self.open_link) #add the Grouppage group_label = closeable_tab_label(_("Group"),self.grouppage ) self.mainwindow.notebook.append_page(self.grouppage, group_label) #create and add the account page self.settingspage = SettingsPage(has_hildon,has_pynotify) self.settingspage.set_initial_dents( self.initial_dents ) self.settingspage.set_pull_time(self.pull_time) #update the configuration of the settings self.settingspage.connect('update-account',self.update_account) self.options['ctrl_enter'] = self.conf.get_bool_option('ctrl_enter') self.settingspage.set_ctrl_enter( self.options['ctrl_enter'] ) self.options['run_as_tray_app'] = self.conf.get_bool_option('run_as_tray_app') self.settingspage.set_run_as_tray_app( self.options['run_as_tray_app'] ) self.options['context_backwards'] = self.conf.get_bool_option('context_backwards') self.settingspage.set_context_backwards( self.options['context_backwards'] ) self.options['no_avatar']= self.conf.get_bool_option('no_avatars') self.settingspage.set_no_avatars( self.options['no_avatar'] ) self.options['api_retweet'] = self.conf.get_bool_option('api_retweet') self.settingspage.set_api_retweet( self.options['api_retweet'] ) self.options['notifications']= self.conf.get_bool_option('notifications') self.settingspage.set_notifications( self.options['notifications'] ) self.options['notify_replies']= self.conf.get_bool_option('notify_replies') self.settingspage.set_notify_replies( self.options['notify_replies'] ) link_color = self.conf.get('settings','link_color',default='blue') self.settingspage.set_link_color( link_color ) self.theme_link_color(link_color) #connect the setting signals self.settingspage.connect('option-run-as-tray-app', self.option_changed, 'run_as_tray_app') self.settingspage.connect('option-ctrl-enter', self.option_changed, 'ctrl_enter') self.settingspage.connect('option-context-backwards',self.option_changed, 'context_backwards') self.settingspage.connect('option-no-avatars',self.option_changed, 'no_avatars') self.settingspage.connect('option-api-retweet', self.option_changed, 'api_retweet') self.settingspage.connect('option-notifications',self.option_changed, 'notifications') self.settingspage.connect('option-notify-replies',self.option_changed, 'notify_replies') self.settingspage.connect('initial-dents',self.set_initial_dents) self.settingspage.connect('pull-time',self.set_pull_time) self.settingspage.connect('link-color',self.set_link_color) self.settingspage.connect('add-string-filter', self.add_string_filter ) self.settingspage.connect('remove-string-filter', self.remove_string_filter ) self.settingspage.connect('add-user-filter', self.add_user_filter ) self.settingspage.connect('remove-user-filter', self.remove_user_filter ) #add the settings to the mainwindow self.mainwindow.add_notebook_page(self.settingspage,uncloseable_tab_label(_("Settings") ) ) #create and add the about page about = About(version,branch,self.standard_icon_path,self.readme_file) about.connect('open-link',self.open_link) self.mainwindow.add_notebook_page( about, uncloseable_tab_label(_("About") ) ) self.mainwindow.show_some() #hide some stuff self.grouppage.hide_all() self.userpage.hide_all() self.contextpage.hide_all() def align_window(self): #try to set the mainwindows size based on conf info try: w = int( self.conf.get('window_info','width') ) h = int( self.conf.get('window_info','height') ) self.mainwindow.resize(w,h) except: pass try: x = int( self.conf.get('window_info','x') ) y = int( self.conf.get('window_info','y') ) self.mainwindow.move(x,y) except: pass #get the filters try: #read the filters filters = self.conf.get('settings','filters',True) #the filters should be an array if len(filters): #self.filters = filters self.filters['users'] = filters['users'] self.filters['strings'] = filters['strings'] #set the filters self.settingspage.set_string_filters( self.filters['strings'] ) self.settingspage.set_user_filters( self.filters['users'] ) except: pass def create_status_icon(self): if not self.has_status_icon: #create the statusicon self.statusicon = StatusIcon() self.statusicon.connect('activate', self.status_clicked ) self.statusicon.connect('quit-selected',self.quit_app) self.statusicon.set_icon( self.standard_icon_path ) self.statusicon.set_property("visible",True) self.has_status_icon=True def destroy_status_icon(self): self.statusicon.set_property("visible",False) self.has_status_icon=False def update_account(self, widget, n, p, s): #check if these are valid self.mainwindow.set_message(_("Authenticating account...")) self.increment_requests() self.comm.verify_credentials(n, p, s) def increment_requests(self): self.waiting_requests+=1 if self.waiting_requests==1: try: self.mainwindow.set_icon_from_file(self.networking_icon_path) except: pass try: self.mainwindow.set_throbber(self.throbber_icon_path) except: pass if self.has_status_icon: self.statusicon.set_icon( self.networking_icon_path) def decrement_requests(self): self.waiting_requests-=1 if self.waiting_requests==0: try: self.mainwindow.set_icon_from_file(self.default_icon_path) except: pass try: self.mainwindow.set_throbber(self.default_icon_path) except: pass if self.has_status_icon: self.statusicon.set_icon( self.default_icon_path ) if self.waiting_requests<0: self.waiting_requests=0 def valid_account_info(self, n, p, s): self.conf.name( n ) self.conf.password( p ) self.conf.service( s ) self.conf.save() #update the comm self.comm.set_name_and_password( n,p ) self.comm.set_service( s ) def get_statuses(self,count="20"): if self.credentials_verified: #do some time handling for the good doctor now = time.time() if now - self.last_get_statuses > 2*self.pull_time: count = self.initial_dents self.last_get_statuses = now self.increment_requests() self.comm.get_statuses(count=count, since=highest_id['dent_previous']) #clean up the garbage gc.collect() def get_mentions(self,count="20"): if self.credentials_verified: self.increment_requests() self.comm.get_mentions(count=count,since=highest_id['mention_previous']) def get_favorites(self): if self.credentials_verified: self.increment_requests() self.comm.get_favorites() def get_direct_messages(self): if self.credentials_verified: now = time.time() #NOTE this could be changed to 3 minutes just setting it #this way for now #has it been 3 times the pull time? if now - (3 * int(self.pull_time) ) > self.last_direct_message_time: self.increment_requests() self.comm.get_direct_messages(highest_id['direct_previous']) self.last_direct_message_time=now def run(self, enable_logging=False): self.logging = enable_logging #start the communicator self.comm.start() self.main_loop = gobject.MainLoop() #we have to temporarily show the various pages or nothing works ''' why the f**k do I need to do this? ''' self.mainwindow.set_notebook_page(DIRECT) self.mainwindow.set_notebook_page(MENTION) self.mainwindow.set_notebook_page(FAVORITE) self.mainwindow.set_notebook_page(DENT) #send the service to the settings page self.settingspage.set_service(self.conf.service() ) #did the conf read a name and password? if( self.conf.name() !="" and self.conf.password()!=""): if self.credentials_verified: self.comm.set_name_and_password( self.conf.name(),self.conf.password() ) self.comm.set_service( self.conf.service() ) #fill the Account tab name/pw fields to show the user that they're logged in self.settingspage.set_name(self.conf.name()) self.settingspage.set_password(self.conf.password()) #add a function to the main loop gobject.timeout_add(int(self.pull_time)*1000, self.update_statuses ) gobject.timeout_add(int(self.pull_time)*1500, self.update_mentions ) #add a timout to get dents gobject.timeout_add(500,self.get_statuses,self.initial_dents ) gobject.timeout_add(600,self.get_mentions,self.initial_dents ) #gobject.timeout_add(1000,self.get_direct_messages ) else: #set the focus on the account page; the last page self.mainwindow.set_notebook_page(ACCOUNT) self.mainwindow.run() self.main_loop.run() #if we ever get here, we should quit def update_statuses(self): self.get_statuses() if(self.pull_time_changed_bool): self.pull_time_changed_bool= False gobject.timeout_add(int(self.pull_time)*1000, self.update_statuses) return False return True def update_mentions(self): self.get_mentions() if(self.pull_time_mentions): self.pull_time_mentions=False gobject.timeout_add(int(self.pull_time)*1500, self.update_mentions) return False return True def update_direct_messages(self): self.get_direct_messages() return True def update_status(self,widget,text): self.increment_requests() #remove newlines from text text=text.replace("\n","") #is this direct message mode? if self.is_direct_message_mode: self.comm.send_direct_message(text,self.direct_message_to) self.set_is_direct_message_mode(False) else: self.comm.send_update_status(text,self.respond_to_id) self.clear_respond_to_id() def quit_app(self,widget=None): #quit the communicator loop self.comm.quit() #quit the main loop self.main_loop.quit() def get_widget_image(self,imagecache,image): self.comm.get_widget_image(image) def get_conversation(self,id,conversation_id): if self.credentials_verified: self.increment_requests() self.comm.get_conversation(id,conversation_id) def parse_profile(self, profile=None, name=None ): #is this a remote user? remote_user = True service = '' #did we get a name? if profile!=None: bits = profile.rsplit("/") service = bits[2] if name==None: name = bits[3] #if there is no name, use the first subdomain as a name if name==None: dot_split = service.split(".") name = dot_split[0] if service==self.conf.service(): remote_user = False else: remote_user = False return {'service':service, 'remote':remote_user,'name':name} def get_user_info(self, profile=None, name=None): #parse the info result = self.parse_profile( profile, name ) #is this a remote user? remote_user = result['remote'] name = result['name'] service = result['service'] #is this not a remote user? if not remote_user: if self.credentials_verified: self.increment_requests() self.comm.get_user_info(name) self.increment_requests() self.comm.get_user_statuses(name) return self.increment_requests() self.comm.get_remote_user_info(service,name) self.increment_requests() self.comm.get_remote_user_statuses(service,name) def get_group_info(self,name): if self.credentials_verified: self.increment_requests() self.comm.get_group_info(name) def follow_user(self,widget,name,bool): if self.credentials_verified: if bool: self.comm.friendship_create(name) else: self.comm.friendship_destroy(name) def join_group(self,widget,name,bool): if self.credentials_verified: if bool: self.comm.group_join(name) else: self.comm.group_leave(name) def process_friendshipXML(self,widget,text): pass def page_change(self,widget,old_id,new_id): if new_id==MainWindow.DIRECT: self.get_direct_messages() elif new_id==MainWindow.FAVORITE: self.get_favorites() else: if self.is_direct_message_mode: self.set_is_direct_message_mode(False) #should we clear any warning message? self.mainwindow.clear_message() def process_userXML(self,comm,text): self.decrement_requests() data = self.xmlprocessor.get_user_info(text) if data['profile_image_url']!=None: self.imagecache.add_image_to_widget(data['profile_image_url'],self.userpage) self.userpage.set_user_data(data) def process_groupXML(self,comm,text): self.decrement_requests() data = self.xmlprocessor.get_group_info(text) if data['stream_logo']!=None: self.imagecache.add_image_to_widget(data['stream_logo'],self.grouppage) '''#is this user a member of this group self.increment_requests() self.comm.get_user_is_member(data['id'])''' self.increment_requests() self.comm.get_group_statuses(data['id']) self.grouppage.set_group_data(data) def process_user_is_friendXML(self,comm,text): self.decrement_requests() is_friend = self.xmlprocessor.get_user_is_friend(text) self.mainwindow.display_user_is_friend( is_friend ) def process_user_is_memberXML(self,comm,text): self.decrement_requests() is_member = self.xmlprocessor.get_user_is_member(text) self.mainwindow.display_user_is_member( is_member ) def process_new_directXML(self,comm,text): #a update status was sent self.decrement_requests() #clear the textview thing self.mainwindow.emit_update_textview_responsed() def process_new_statusXML(self,comm,text): #a update status was sent self.decrement_requests() #clear the textview thing self.mainwindow.emit_update_textview_responsed() #there is one status and it is the DOM status = self.xmlprocessor.get_dom(text) data = self.xmlprocessor.get_dent_data(status) data['markup'] = self.markup_dent_text(data['text']) #add the dent dent = self.connect_dent(data,self.dentspage) def process_verifycredentialsXML(self, object, text, data): #actually, if we are here, the authorization worked! self.conf.set('access', 'credentials_verified', True) self.credentials_verified = True self.mainwindow.message_label.hide() (n, p, s) = data self.valid_account_info(n, p, s) #get the config self.comm.get_config() #switch to the dents page self.mainwindow.set_notebook_page(DENT) self.get_statuses() self.get_mentions() def process_conversationXML(self,object,text,conversation_id): self.decrement_requests() #is this the current conversation Id? if not, then do nothing #convert to int because there is a problem with string comparison '''is one of the strings unicode?''' if int(self.conversation_id)==int(conversation_id): #get the status status = self.xmlprocessor.get_dom(text) data = self.xmlprocessor.get_dent_data(status) data['markup']=self.markup_dent_text(data['text']) #since this is a conversation, we can get rid of the in_reply_to_screen_name data['in_reply_to_screen_name']=None #tell the mainWindow to add the dent dent = self.connect_dent(data,self.contextpage,True, self.options['context_backwards'] ) if data['in_reply_to_id']!=None: #recursively get in_reply_to_ids self.get_conversation(id=data['in_reply_to_id'],conversation_id=conversation_id) def process_configXML(self, object, text): self.decrement_requests() server = self.xmlprocessor.get_server_config(text) print server self.conf.textlimit( server['textlimit'] ) self.conf.save() self.mainwindow.set_textlimit( server['textlimit'] ) def connect_dent(self,data,target_page,is_conv=False,conv_backwards=False,is_direct_dent=False): #make the dent dent = Dent(data,is_direct=is_direct_dent) if target_page.dentScroller.add_dent( dent, is_conv, conv_backwards ): dent.connect('group-clicked', self.view_group) dent.connect('reply-clicked', self.reply_clicked) dent.connect('direct-clicked', self.direct_clicked) dent.connect('view-conversation-clicked', self.view_conversation) dent.connect('user-clicked', self.view_user_name) dent.connect('profile-clicked', self.view_user_profile) dent.connect('id-clicked', self.view_id) dent.connect('text-label-clicked',self.dent_text_clicked) dent.connect('redent-clicked',self.redent_clicked) dent.connect('favorite-clicked',self.favorite_clicked) dent.connect('unfavorite-clicked',self.unfavorite_clicked) dent.connect('open-link',self.open_link) if target_page!=self.userpage: #get the image for this dent self.imagecache.add_image_to_widget(data['profile_image_url'],dent) return True else: dent.destroy() del dent return False def reply_clicked(self,dent,name): #set the text buffer self.mainwindow.update_textbuffer.set_text("@%s " % (name) ) self.mainwindow.update_textview.grab_focus() #set the respond_to_id self.respond_to_id=dent.id def favorite_clicked(self,dent): id=dent.id self.comm.favorite(id) def unfavorite_clicked(self,dent): id=dent.id self.comm.unfavorite(id) def direct_clicked(self,widget,name): self.direct_message_to = name if type(widget).__name__=="Dent": self.respond_to_id=widget.id else: self.respond_to_id=None self.set_is_direct_message_mode(True,name) #we should be on the directs page self.mainwindow.set_notebook_page(DIRECT) #set the text buffer self.mainwindow.update_textbuffer.set_text("") self.mainwindow.update_textview.grab_focus() def view_conversation(self,dent,id): self.conversation_id=id self.pre_context_page=self.mainwindow.notebook_current_page self.contextpage.dentScroller.clear() self.contextpage.show_all() #get conversation starting with id self.get_conversation(id,id) self.mainwindow.notebook.set_current_page(CONTEXT) def view_user_profile(self, widget, profile_url, screen_name): self.get_user_info(profile=profile_url, name=screen_name) #self.get_user_info(screen_name) self.pre_user_page=self.mainwindow.notebook_current_page #make the user page checkbox insensitive self.userpage.disable() #show the page self.userpage.show_all() #rehide its collapsed widgetbox, that doesn't need to be visible yet self.userpage.widgetbox_collapsed.hide() #clear the userpage stuff self.userpage.clear() #change to the user page self.mainwindow.set_notebook_page(USER) def view_id(self, widget, id): url = 'http://%s/notice/%s' % (self.conf.service(), id) self.open_link(None, url) def view_user_name(self, widget, screen_name): #TODO: merge this function with view_user_profile self.get_user_info(name=screen_name) #self.get_user_info(screen_name) self.pre_user_page=self.mainwindow.notebook_current_page #make the user page checkbox insensitive self.userpage.disable() #show the page self.userpage.show_all() #rehide its collapsed widgetbox, that doesn't need to be visible yet self.userpage.widgetbox_collapsed.hide() #clear the userpage stuff self.userpage.clear() #change to the user page self.mainwindow.set_notebook_page(USER) #does this function even get called? get rid of it def get_dent_time(self,text): #print text pass def markup_dent_text(self,text,is_notification=False): #process the text to markup #xmlencode the string text = self.xmlprocessor.xmlentities(text) #regex find the highlights markup = self.regex_tag.sub(r'\1#<b>\2</b>',text) #regex find users if has_hildon or links_unavailable or is_notification: markup = self.regex_group.sub(r'\1!<b>\2</b>',markup) markup = self.regex_user.sub(r'\1@<b>\2</b>',markup) else: #find urls markup = self.regex_url.sub(r'<a href="\1">\1</a>\2',markup) markup = self.regex_user.sub(r'\1@<a href="@\2">\2</a>',markup) markup = self.regex_group.sub(r'\1!<a href="!\2">\2</a>',markup) return markup def process_statusesXML(self,object,text,target_page,is_direct=False): #based on the target, what is the counting thingy? count_ref=None if target_page==self.dentspage: count_ref = "dent" elif target_page==self.mentionspage: count_ref = "mention" elif target_page==self.directspage: count_ref = "direct" self.decrement_requests() #set the "previous" count ref, do this now and get data twice if count_ref!=None: highest_id[count_ref+"_previous"] = highest_id[count_ref] #get a list of the statuses statuses = self.xmlprocessor.get_statuses(text,is_direct) #if there aren't any statuses, return if len(statuses)==0: return #reverse the statuses list statuses.reverse() dent_count=0 reply_count=0 #what is the highest id of the target index? for status in statuses: filtered_status = False data = self.xmlprocessor.get_dent_data(status) if target_page==self.dentspage: #we should check for filtration filtered = self.check_filtered( data ) filtered_status=filtered[0] if not filtered_status: #get the markup data['markup'] = self.markup_dent_text(data['text']) #did this dent connect if not self.connect_dent(data,target_page,is_direct_dent=is_direct): continue #if the target_page = 0 and not first_dents and not is_conf if target_page==self.dentspage and not self.is_first_dents: if "@"+self.conf.name() in data['markup']: dent=self.connect_dent(data, self.mentionspage ) reply_count+=1 if self.options['notify_replies'] and has_pynotify: user = data['screen_name'] #the message shouldn't be marked up if the server doesn't understand markup if notifier_reads_markup: message = self.markup_dent_text(data['text'],True) else: message = data['text'] avatar = self.imagecache.get_image_path(data['profile_image_url']) self.notify.notify_reply(user,message,avatar) else: dent_count+=1 else: self.log("filter #%s %s" %(data['status_id'], filtered[1] ) ) #keep track of the last status_id if count_ref!=None and data!=None: highest_id[count_ref]=data['status_id'] self.is_first_dents=False #get the related images self.imagecache.get_images() #do we notify? if (dent_count!=0 or reply_count!=0) and has_pynotify and target_page==self.dentspage: if self.options['notifications']: if not self.options['notify_replies']: self.notify.notify_updates_replies(dent_count,reply_count,self.standard_icon_path) else: if dent_count!=0: self.notify.notify_updates(dent_count,self.standard_icon_path) #prune off the extra dents target_page.dentScroller.prune(self.dent_limit) def process_widget_image(self,comm,data,name): self.imagecache.widget_image_add(data,name) def process_communication_exception(self,communicator,code,data,signal=None): if self.logging: self.log("code:%s, signal:%s" % (code,signal) ) self.decrement_requests() #is there an error message? try: error_message = self.xmlprocessor.get_error_message(data) except: error_message = False if error_message and not code: self.mainwindow.set_message( error_message, MainWindow.ERROR_MESSAGE) elif code=='401': #bad authorization self.mainwindow.set_notebook_page(MainWindow.ACCOUNT) error_message = _("Invalid Authorization: Your name or password is incorrect") elif code == '404': error_message = _("Service Not Found") elif code == '503': error_message = _("Service Unavailable") elif code == 'unknown error': error_message = _("Unknown Error") else: error_message = code #send the error message self.mainwindow.set_message(error_message, MainWindow.ERROR_MESSAGE) #a signal may have been passed from the comm if signal == "new-statusXML": #a dent was sent but it failed self.mainwindow.emit_update_textview_responsed(error=True) #functions to handle the filtration system def add_string_filter(self,winder,string): if not string in self.filters['strings']: self.filters['strings'].append(string) self.filters['strings'].sort() self.settingspage.set_string_filters( self.filters['strings'] ) def remove_string_filter(self,winder,string): if string in self.filters['strings']: self.filters['strings'].remove(string) self.settingspage.set_string_filters( self.filters['strings'] ) def add_user_filter(self,winder,user): if not user in self.filters['users']: self.filters['users'].append(user) self.filters['users'].sort() self.settingspage.set_user_filters( self.filters['users'] ) def remove_user_filter(self,winder,user): if user in self.filters['users']: self.filters['users'].remove(user) self.settingspage.set_user_filters( self.filters['users'] ) def check_filtered(self,data): if len(self.filters['users'])!=0 : #filter against the user for user in self.filters['users']: if data['screen_name'].lower()==user.lower(): return (True, "user: %s" % data['screen_name'] ) if len(self.filters['strings'])!=0: #filter against the strings #get the dent text text = data['text'] #loop through the filter strings for string in self.filters['strings']: if re.search(string,text, flags=re.IGNORECASE): return (True, "string: %s" % string ) #if we get this far, just return return (False, None) def status_clicked(self,widget): if self.window_is_hidden==True: self.window_is_hidden=False self.mainwindow.show() self.align_window() self.mainwindow.present() else: self.window_to_tray(widget) def window_size_allocate(self,widget,size): self.window_width = size[2] self.window_height = size[3] def save_app_info(self): #save the filters self.conf.set('settings','filters', self.filters ,True) #save the window info self.conf.set('window_info','width', self.window_width ) self.conf.set('window_info','height', self.window_height ) try: #some themes don't pass root origin? origin = self.mainwindow.window.get_root_origin() self.window_x = origin[0] self.window_y = origin[1] self.conf.set('window_info','x', self.window_x ) self.conf.set('window_info','y', self.window_y ) except: pass self.conf.save() def mainwindow_delete_event(self,window,event=None): self.save_app_info() #are we in tray mode? if self.conf.get_bool_option('run_as_tray_app') or self.has_status_icon: #is the status icon embedded? if self.statusicon.is_embedded(): self.window_is_hidden=True self.mainwindow.hide_on_delete() #do not propogate the signal return True else: #we need to quit self.quit_app() def quit_triggered(self,widget): self.save_app_info() self.quit_app() def option_changed(self,widget,value,option): #save the option change in the configuration self.conf.set('options',option,value) self.options[option]=value self.conf.save() #is this the run_tray_app: if option=='run_as_tray_app': if value: self.create_status_icon() else: self.destroy_status_icon() elif option=='no_avatars': self.imagecache.set_disabled(value) elif option=='ctrl_enter': self.mainwindow.set_ctrl_enter(value) def redent_clicked(self,dent,name,text): if self.options['api_retweet']: self.comm.send_redent(dent.id) else: self.respond_to_id=dent.id #formatted_text= u'\u267A @%s: %s' % (name,text) formatted_text= u'\u267A @%s: %s' % (name,text) self.mainwindow.update_textbuffer.set_text(formatted_text ) self.mainwindow.update_textview.grab_focus() def view_group(self,widget,group_name): #where were we? self.pre_group_page=self.mainwindow.notebook_current_page #make some flags self.grouppage.joined_checkbutton.set_sensitive(False) #make the grouppage visible self.grouppage.show_all() #rehide its collapsed widgetbox, that doesn't need to be visible yet self.grouppage.widgetbox_collapsed.hide() #clear the grouppage self.grouppage.clear() #switch to the group page self.mainwindow.set_notebook_page(GROUP) #get the group info self.get_group_info(group_name) def hide_contextpage(self,widget): #end any conversation in progress self.conversation_id="0" self.mainwindow.set_notebook_page( self.pre_context_page ) self.contextpage.hide() def hide_grouppage(self,widget): self.mainwindow.set_notebook_page( self.pre_group_page ) self.grouppage.hide() def hide_userpage(self,widget): self.mainwindow.set_notebook_page( self.pre_user_page ) self.userpage.hide() def dent_text_clicked(self,dent,text_label): self.mainwindow.last_clicked_label = text_label def clear_respond_to_id(self,widget=None): self.respond_to_id=0 def set_initial_dents(self,widget,value): self.initial_dents=value self.dent_limit = int(self.initial_dents)*2 self.conf.set('settings','initial_dents',value) def set_pull_time(self, widget,value): """A method for setting the time between pulls. obvious comment is obvious. Very possible everything will die now that I've added this. --Muel Kiel (aka samsnotunix)""" self.pull_time=value self.conf.set('settings','pull_time',value) self.pull_time_changed_bool = True self.pull_time_mentions = True def set_link_color(self,widget,string): self.conf.set('settings','link_color',string) self.theme_link_color(string) def theme_link_color(self,color): style=''' style "label" { GtkLabel::link-color="%s" } widget_class "*GtkLabel" style "label" ''' % (color) gtk.rc_parse_string(style) #f**k you GTK for not make this work, more than once! #functions for blocking/unblocking def block_create(self,widget,user_id): self.comm.block_create(user_id) def block_destroy(self,widget,user_id): self.comm.block_destroy(user_id) def set_is_direct_message_mode(self,mode,user=None): self.is_direct_message_mode=mode self.mainwindow.set_is_direct_message_mode(mode,user) if mode: self.default_icon_path=self.direct_icon_path else: self.default_icon_path=self.standard_icon_path #if we aren't waiting on any requests, swap the graphic if self.waiting_requests==0: try: self.mainwindow.set_icon_from_file(self.default_icon_path) except: pass try: self.mainwindow.set_throbber(self.default_icon_path) except: pass def simple_decrement(self,text=None,data=None): self.decrement_requests() ''' function window_to_tray sets the run_as_tray_app to true and minimizes the app ''' def window_to_tray(self,window): if self.options['run_as_tray_app']: self.mainwindow_delete_event(window) def open_link(self, widget, uri): webbrowser.open(uri) return True ''' command = "xdg-open '%s'" % ( uri ) #print command subprocess.Popen(command,shell=True) return True ''' def log(self,string): if self.logging: now = time.strftime("%H:%M:%S") file = os.path.join( os.path.expanduser("~"),"heybuddy.log") f = open(file,'a') f.write("%s %s\n" % (now,string) ) f.close()
class SettingsWidget(QtGui.QWidget): def __init__(self, parent=None): super(SettingsWidget, self).__init__(parent) self.currentObject = None self.lastObjectType = None ## TODO: change to translation file self.useTypes = { 0: localizer.translate('classSettingsWidget', 'noUse'), 1: localizer.translate('classSettingsWidget', 'useToOtherObject'), 2: localizer.translate('classSettingsWidget', 'openSth'), 3: localizer.translate('classSettingsWidget', 'putSmwh'), 4: localizer.translate('classSettingsWidget', 'deleteObstacle') } self.fadeTypes = { 0: localizer.translate('classSettingsWidget', 'instantly'), 1: localizer.translate('classSettingsWidget', 'fade') } self.layout = QtGui.QVBoxLayout() self.setLayout(self.layout) self.setSizePolicy( QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)) self.editor = parent self.imageCache = ImageCache() self.createOptionFields() def displayOptions(self, gameObject): self.currentObject = gameObject objectType = gameObject.__class__.__name__ self.showWidgets(objectType) self.lastObjectType = objectType if (objectType == "Room"): self.setRoomOptions(gameObject) elif (objectType == "Sequence"): self.setSequenceOptions(gameObject) elif (objectType == "SequenceImage"): self.setSequenceImageOptions(gameObject) elif (objectType == "Start"): self.setStartOptions(gameObject) elif (objectType == "End"): self.setEndOptions(gameObject) elif (objectType == "Text"): self.setTextOptions(gameObject) elif (objectType == "Item"): self.setItemOptions(gameObject) elif (objectType == "Object"): self.setGenericOptions(gameObject) elif (objectType == "Door"): self.setDoorOptions(gameObject) elif (objectType == "Container"): self.setContainerOptions(gameObject) elif (objectType == "Obstacle"): self.setObstacleOptions(gameObject) elif (objectType == "JSONImage"): self.setJSONImageOptions(gameObject) elif (objectType == "MenuImage"): self.setJSONImageOptions(gameObject) elif (objectType == "BeginningImage"): self.setJSONImageOptions(gameObject) def showWidgets(self, objectType): if (self.lastObjectType): for item in self.itemSettings[self.lastObjectType]: item.hide() for item in self.itemSettings[objectType]: item.show() # Settings for the object view def createOptionFields(self): # Name self.nameLabel = QtGui.QLabel( localizer.translate('classSettingsWidget', 'name')) self.objectNameEdit = QtGui.QLineEdit() self.objectNameEdit.editingFinished.connect(self.changeName) # General image self.imgTextLabel = QtGui.QLabel( localizer.translate('classSettingsWidget', 'image')) self.objectImage = QtGui.QLabel(self) self.objectImage.mousePressEvent =\ lambda s: self.showImageDialog(self.changeObjectImage) self.useTextEdit = QtGui.QTextEdit() self.useTextEdit.setMaximumHeight(50) self.useTextEdit.focusOutEvent = lambda s: self.changeUseText() # Ending checkbox self.endingCheckbox = QtGui.QCheckBox() # Set text afterwards self.endingCheckbox.setText( localizer.translate('classSettingsWidget', 'gameEndsIfClicked')) self.endingCheckbox.stateChanged.connect(self.changeEndingCheckbox) # Music self.musicLabel = QtGui.QLabel( localizer.translate('classSettingsWidget', 'music')) self.musicBtn = QtGui.QPushButton( localizer.translate('classSettingsWidget', 'browse'), self) self.musicBtn.setToolTip( localizer.translate('classSettingsWidget', 'chooseMusicFile')) self.musicBtn.resize(self.musicBtn.sizeHint()) self.musicBtn.clicked.connect( lambda: self.showMusicDialog(self.changeMusic)) self.musicTextEdit = QtGui.QLineEdit() self.musicTextEdit.setReadOnly(True) self.musicClear = QtGui.QPushButton( localizer.translate('classSettingsWidget', 'noMusic'), self) self.musicClear.clicked.connect(self.clearMusic) # Where from dropdown box # self.whereFromLabel = QtGui.QLabel( # "Mistä kulkureiteistä tänne pääsee?") # TODO: whereFromCombo self.examineTextLabel = QtGui.QLabel( localizer.translate('classSettingsWidget', 'textAsClicked')) self.examineTextEdit = QtGui.QTextEdit() self.examineTextEdit.setMaximumHeight(50) self.examineTextEdit.focusOutEvent = lambda s: self.changeExamineText() # Pickup text section self.pickupLabel = QtGui.QLabel( localizer.translate('classSettingsWidget', 'picked')) self.pickupLabelLine = self.createSeparator() self.pickupLabelLine.setFrameStyle(QtGui.QFrame.HLine | QtGui.QFrame.Raised) self.pickupTextLabel = QtGui.QLabel( localizer.translate('classSettingsWidget', 'textIfPicked')) self.pickupTextEdit = QtGui.QTextEdit() self.pickupTextEdit.setMaximumHeight(50) self.pickupTextEdit.focusOutEvent = lambda s: self.changePickupText() # Object usage self.useLabel = QtGui.QLabel( localizer.translate('classSettingsWidget', 'usage')) self.useLabelLine = self.createSeparator() # Object type of usage self.useTypeCombo = QtGui.QComboBox(self) for i in self.useTypes: self.useTypeCombo.addItem(self.useTypes[i]) self.useTypeCombo.activated.connect(self.changeItemUseType) self.useTextLabel = QtGui.QLabel( localizer.translate('classSettingsWidget', 'textIfUsed')) # Use target self.useTargetCombo = self.createCombobox() self.updateUseTargetCombo() self.allTextsButton = QtGui.QPushButton( localizer.translate('classSettingsWidget', 'theseAndOtherTexts')) self.allTextsButton.clicked.connect(self.showAllTexts) # Door widgets self.doorTransitionLabel = QtGui.QLabel( localizer.translate('classSettingsWidget', 'whereItGoes')) self.doorTransitionCombo = self.createCombobox() self.updateDoorTransitionCombo() self.doorInitialStateLabel = QtGui.QLabel( localizer.translate('classSettingsWidget', 'spaceAtStart')) self.doorInitialStateCombo = QtGui.QComboBox(self) self.doorInitialStateCombo.addItem( localizer.translate('classSettingsWidget', 'shut')) self.doorInitialStateCombo.addItem( localizer.translate('classSettingsWidget', 'open')) self.doorInitialStateCombo.activated.connect( lambda s: self.objectComboboxHandler(self.doorInitialStateCombo, self.changeDoorInitialState)) self.openDoorImage = ObjectImageSettings( localizer.translate('classSettingsWidget', 'openDoor'), localizer.translate('classSettingsWidget', 'openDoorName'), parent=self) self.closedDoorImage = ObjectImageSettings( localizer.translate('classSettingsWidget', 'closedDoor'), localizer.translate('classSettingsWidget', 'closedDoorName'), parent=self) self.lockedDoorImage = ObjectImageSettings( localizer.translate('classSettingsWidget', 'lockedDoor'), localizer.translate('classSettingsWidget', 'lockedDoorName'), True, localizer.translate('classSettingsWidget', 'locked'), parent=self) # Container widgets self.lockedContainerImage = ObjectImageSettings( localizer.translate('classSettingsWidget', 'lockedContainer'), localizer.translate('classSettingsWidget', 'lockedContainerName'), True, localizer.translate('classSettingsWidget', 'locked'), parent=self) self.fullContainerImage = ObjectImageSettings( localizer.translate('classSettingsWidget', 'openContainer'), localizer.translate('classSettingsWidget', 'openContainerName'), parent=self) self.emptyContainerImage = ObjectImageSettings( localizer.translate('classSettingsWidget', 'emptyContainer'), localizer.translate('classSettingsWidget', 'emptyContainerName'), parent=self) # Obstacle widgets self.obstacleImage = ObjectImageSettings(None, localizer.translate( 'classSettingsWidget', 'whatObstructs'), False, parent=self) self.obstacleBlocksLabel = QtGui.QLabel( localizer.translate('classSettingsWidget', 'whatObstructs')) self.obstacleBlocksCombo = self.createCombobox() self.updateObstacleBlocksCombo() self.whatGoesLabel = QtGui.QLabel( localizer.translate('classSettingsWidget', 'whatGoesToContainer')) self.whatGoesCombo = self.createCombobox() self.updateWhatGoesCombo() self.whatComesLabel = QtGui.QLabel( localizer.translate('classSettingsWidget', 'whatComesFromContainer')) self.whatComesCombo = self.createCombobox() self.updateWhatComesCombo() self.useConsumeCheckbox = QtGui.QCheckBox() # Set text afterwards self.useConsumeCheckbox.stateChanged.connect(self.changeUseConsume) self.outcomeLabel = QtGui.QLabel( localizer.translate('classSettingsWidget', 'endResult')) self.outcomeCombobox = self.createCombobox() self.updateOutcomeCombobox() # Sequence self.sequenceTimeLabel = QtGui.QLabel( localizer.translate('classSettingsWidget', 'imageShowTime')) self.sequenceTimeEdit = QtGui.QLineEdit() self.sequenceTimeEdit.setInputMask("9,9") self.sequenceTimeEdit.focusOutEvent =\ lambda s: self.changeSequenceTime() self.sequenceFadeLabel = QtGui.QLabel( localizer.translate('classSettingsWidget', 'fadeType')) self.sequenceFadeCombo = QtGui.QComboBox(self) for i in self.fadeTypes: self.sequenceFadeCombo.addItem(self.fadeTypes[i]) self.sequenceFadeCombo.activated.connect(self.changeSequenceFadeCombo) # End self.textObjectTextLabel = QtGui.QLabel( localizer.translate('classSettingsWidget', 'text')) self.textObjectTextEdit = QtGui.QLineEdit() self.textObjectTextEdit.focusOutEvent =\ lambda s: self.changeTextObjectText() self.layout.addWidget(self.textObjectTextLabel) self.layout.addWidget(self.textObjectTextEdit) self.layout.addWidget(self.nameLabel) self.layout.addWidget(self.objectNameEdit) self.layout.addWidget(self.imgTextLabel) self.layout.addWidget(self.objectImage) self.layout.addWidget(self.musicLabel) self.layout.addWidget(self.musicTextEdit) self.layout.addWidget(self.musicBtn) self.layout.addWidget(self.musicClear) #self.layout.addWidget(self.whereFromLabel) self.layout.addWidget(self.endingCheckbox) self.layout.addWidget(self.examineTextLabel) self.layout.addWidget(self.examineTextEdit) self.layout.addWidget(self.pickupLabelLine) self.layout.addWidget(self.pickupLabel) self.layout.addWidget(self.pickupTextLabel) self.layout.addWidget(self.pickupTextEdit) self.layout.addWidget(self.useLabelLine) self.layout.addWidget(self.useLabel) self.layout.addWidget(self.useTypeCombo) self.layout.addWidget(self.useTargetCombo) self.layout.addWidget(self.useConsumeCheckbox) self.layout.addWidget(self.outcomeLabel) self.layout.addWidget(self.outcomeCombobox) self.layout.addWidget(self.useTextLabel) self.layout.addWidget(self.useTextEdit) self.layout.addWidget(self.allTextsButton) #self.layout.addWidget(self.doorTransitionLabelLine) self.layout.addWidget(self.doorTransitionLabel) self.layout.addWidget(self.doorTransitionCombo) self.layout.addWidget(self.doorInitialStateLabel) self.layout.addWidget(self.doorInitialStateCombo) self.layout.addWidget(self.openDoorImage) self.layout.addWidget(self.lockedDoorImage) self.layout.addWidget(self.closedDoorImage) self.layout.addWidget(self.whatGoesLabel) self.layout.addWidget(self.whatGoesCombo) self.layout.addWidget(self.whatComesLabel) self.layout.addWidget(self.whatComesCombo) self.layout.addWidget(self.fullContainerImage) self.layout.addWidget(self.lockedContainerImage) self.layout.addWidget(self.emptyContainerImage) self.layout.addWidget(self.obstacleBlocksLabel) self.layout.addWidget(self.obstacleBlocksCombo) self.layout.addWidget(self.obstacleImage) self.layout.addWidget(self.sequenceTimeLabel) self.layout.addWidget(self.sequenceTimeEdit) self.layout.addWidget(self.sequenceFadeLabel) self.layout.addWidget(self.sequenceFadeCombo) # Removebuttons self.removeObjectButton = QtGui.QPushButton( localizer.translate('classSettingsWidget', 'removeObject')) self.layout.addWidget(self.removeObjectButton) self.removeObjectButton.clicked.connect(lambda: self.removeObject()) self.removeViewButton = QtGui.QPushButton( localizer.translate('classSettingsWidget', 'removeView')) self.layout.addWidget(self.removeViewButton) self.removeViewButton.clicked.connect(lambda: self.removeView()) # Which widgets are shown with each object self.itemSettings = { "Room": [ self.imgTextLabel, self.objectImage, self.nameLabel, self.objectNameEdit, self.musicLabel, self.musicTextEdit, self.musicBtn, self.musicClear, self.removeViewButton #self.whereFromLabel # TODO: doorCombo for "where from" values ], "Sequence": [ self.nameLabel, self.objectNameEdit, self.musicLabel, self.musicTextEdit, self.musicBtn, self.musicClear, self.removeViewButton ], "SequenceImage": [ self.imgTextLabel, self.objectImage, self.sequenceTimeLabel, self.sequenceTimeEdit, self.sequenceFadeLabel, self.sequenceFadeCombo, self.removeViewButton ], "End": [ self.imgTextLabel, self.objectImage, self.nameLabel, self.objectNameEdit, self.musicLabel, self.musicTextEdit, self.musicBtn, self.musicClear, ], "Text": [self.textObjectTextLabel, self.textObjectTextEdit], "BeginningImage": [ self.imgTextLabel, self.objectImage, ], "JSONImage": [ self.imgTextLabel, self.objectImage, ], "Start": [ self.musicLabel, self.musicTextEdit, self.musicBtn, self.musicClear, ], "MenuImage": [ self.imgTextLabel, self.objectImage, ], "Item": [ self.nameLabel, self.objectNameEdit, self.imgTextLabel, self.objectImage, self.examineTextLabel, self.examineTextEdit, self.pickupLabelLine, self.pickupLabel, self.pickupTextLabel, self.pickupTextEdit, self.useLabelLine, self.useLabel, self.useTypeCombo, self.useTargetCombo, self.useTextLabel, self.useTextEdit, self.allTextsButton, self.useConsumeCheckbox, self.outcomeLabel, self.outcomeCombobox, self.removeObjectButton ], "Object": [ self.nameLabel, self.objectNameEdit, self.imgTextLabel, self.objectImage, self.endingCheckbox, self.examineTextLabel, self.examineTextEdit, self.removeObjectButton ], "Door": [ #self.doorTransitionLabelLine, self.doorTransitionLabel, self.doorTransitionCombo, self.doorInitialStateLabel, self.doorInitialStateCombo, self.openDoorImage, self.closedDoorImage, self.lockedDoorImage, self.removeObjectButton ], "Container": [ self.lockedContainerImage, self.fullContainerImage, self.emptyContainerImage, self.whatGoesLabel, self.whatGoesCombo, self.whatComesLabel, self.whatComesCombo, self.removeObjectButton ], "Obstacle": [ self.obstacleImage, self.obstacleBlocksLabel, self.obstacleBlocksCombo, self.removeObjectButton ] } # Hide every widget for key in self.itemSettings: for item in self.itemSettings[key]: item.hide() # Update comboboxes having objectType objects def updateComboboxes(self, objectType): objectType = objectType.lower() if (objectType == "room"): self.updateDoorTransitionCombo() elif (objectType == "door"): self.updateObstacleBlocksCombo() elif (objectType == "item"): self.updateWhatGoesCombo() self.updateWhatComesCombo() self.updateOutcomeCombobox() elif (objectType == "object"): self.updateOutcomeCombobox() # Update every time self.updateUseTargetCombo() # Update other widgets self.lockedDoorImage.updateComboboxes(objectType) self.lockedContainerImage.updateComboboxes(objectType) def updateUseTargetCombo(self): self.updateItemCombobox(self.useTargetCombo, localizer.translate('classSettingsWidget', 'notSelected'), connectTo=self.changeUseTarget) def updateDoorTransitionCombo(self): self.updateItemCombobox(self.doorTransitionCombo, localizer.translate('classSettingsWidget', 'notAnywhere'), "room", connectTo=self.changeDoorTransition) def updateObstacleBlocksCombo(self): self.updateItemCombobox(self.obstacleBlocksCombo, localizer.translate('classSettingsWidget', 'noNothing'), ("door", ), ("door", ), noChoiceMethod=self.clearObstacleBlock, connectTo=self.changeObstacleBlock) def updateWhatGoesCombo(self): self.updateItemCombobox(self.whatGoesCombo, localizer.translate('classSettingsWidget', 'notAnything'), ("item", ), ("item", ), connectTo=self.changeWhatGoes) def updateWhatComesCombo(self): self.updateItemCombobox(self.whatComesCombo, localizer.translate('classSettingsWidget', 'noNothing'), ("item", ), ("item", ), connectTo=self.changeWhatComes) def updateOutcomeCombobox(self): self.updateItemCombobox(self.outcomeCombobox, localizer.translate('classSettingsWidget', 'notSelected'), ("object", "item"), ("object", "item"), noChoiceMethod=self.clearOutcome, connectTo=self.changeOutcome) def changeSequenceTime(self): time = int( float(self.sequenceTimeEdit.text().replace(",", ".")) * 1000) self.currentObject.setShowTime(time) def changeSequenceFadeCombo(self): doFade = (self.sequenceFadeCombo.currentIndex() is True) self.currentObject.setDoFade(doFade) def changeTextObjectText(self): self.currentObject.setText(self.textObjectTextEdit.text()) def changeEndingCheckbox(self): self.currentObject.setIsEnding(self.endingCheckbox.isChecked()) # Start menu def setStartOptions(self, startObject): # Start music self.setObjectMusic(startObject) # End view def setEndOptions(self, endObject): # End name self.setObjectName(overrideText=endObject.generalName) # End image self.setObjectImage(endObject.getRepresentingImage(). getRepresentingImage().absoluteImagePath) # Text object def setTextOptions(self, textObject): self.textObjectTextEdit.setText(textObject.getText()) # Set either currentObject or the given object's music def setObjectMusic(self, gameObject=None): if not (gameObject): gameObject = self.currentObject # Music may return None which doesn't have split try: music = gameObject.getMusic().split("/")[-1] except AttributeError: music = "" self.musicTextEdit.setText(music) # Generic JSON images def setJSONImageOptions(self, imageObject): # Image self.setObjectImage(imageObject.getRepresentingImage(). getRepresentingImage().absoluteImagePath) # Set the input field values for rooms def setRoomOptions(self, room): # Room name self.setObjectName(room, room.generalName) # Room background self.setObjectImage(room.getRepresentingImage().getRepresentingImage(). absoluteImagePath) # Room music self.setObjectMusic(room) def setSequenceOptions(self, sequence): # Sequence name self.setObjectName(sequence, sequence.generalNameAdessive) # Sequence background self.setObjectImage(sequence.getRepresentingImage(). getRepresentingImage().absoluteImagePath) # Sequence music self.setObjectMusic(sequence) def setSequenceImageOptions(self, sequenceImage): # Image self.setObjectImage(sequenceImage.getRepresentingImage(). getRepresentingImage().absoluteImagePath) # Set image display time. Convert into str and replace dots showTime = self.currentObject.getShowTime() if (showTime): time = str(showTime / 1000).replace(".", ",") else: time = "0,0" self.sequenceTimeEdit.setText(time) # Image fade type doFade = self.currentObject.getDoFade() if not (doFade): doFade = False self.sequenceFadeCombo.setCurrentIndex(doFade) # Set the input field values for items def setItemOptions(self, item): imageObject = item.getRepresentingImage().getRepresentingImage() # Object name self.setObjectName(imageObject, item.generalNameAdessive) # Item image self.setObjectImage(imageObject.absoluteImagePath) # Examine text self.setExamineText(self.currentObject) # Pickup text pickupText = item.getPickupText() if not (pickupText): pickupText = "" self.pickupTextEdit.setText(pickupText) # Use type of the item itemTarget = self.editor.getItemUse(item) itemTargetType = itemTarget.__class__.__name__ useType = 0 if (itemTargetType in ("Object", "Item")): useType = 1 elif (itemTargetType == "Obstacle"): useType = 5 elif (itemTargetType in ("Door", "Container")): # Item may unlock door or container or may go into a container if (itemTarget.key == item): useType = 2 else: try: if (itemTarget.inItem == item): useType = 3 except AttributeError: pass self.setUseConsume() self.setItemUseType(useType) self.setItemUseTarget(itemTarget) self.setItemOutcome(self.currentObject.outcome) self.setUseText() # Set the input field values for generic objects def setGenericOptions(self, genericObject): # Object name self.setObjectName(genericObject, genericObject.generalNameAdessive) # Object image imageObject = genericObject.getRepresentingImage()\ .getRepresentingImage() self.setObjectImage(imageObject.absoluteImagePath) # Ending if (self.currentObject.getIsEnding()): self.endingCheckbox.setCheckState(QtCore.Qt.CheckState.Checked) else: self.endingCheckbox.setCheckState(QtCore.Qt.CheckState.Unchecked) # Examine text self.setExamineText(self.currentObject) # Set the input field values for containers def setContainerOptions(self, container): # Set image settings for each image self.fullContainerImage.setSettings(container, container.fullImage) self.lockedContainerImage.setSettings(container, container.lockedImage) self.emptyContainerImage.setSettings(container, container.emptyImage) # Set what goes, what comes from the container self.setComboboxIndex(container.inItem, self.whatGoesCombo) self.setComboboxIndex(container.outItem, self.whatComesCombo) # Set the input field values for obstacles def setObstacleOptions(self, obstacle): self.obstacleImage.setSettings(obstacle, obstacle.blockingImage) def setObjectImage(self, imagePath, objectImage=None): imgPixmap = self.imageCache.createPixmap(imagePath) # TODO: Have spacing for smaller items if (imgPixmap.size().height() > 200): imgPixmap = imgPixmap.scaled(200, 200, QtCore.Qt.KeepAspectRatio) if (objectImage): objectImage.setPixmap(imgPixmap) else: self.objectImage.setPixmap(imgPixmap) # Set item use type def setItemUseType(self, typeIndex): self.useTypeCombo.setCurrentIndex(typeIndex) self.updateUseTargetCombobox(typeIndex, self.useTargetCombo) # Show extra options when selecting use on other object if (typeIndex == 1): self.useConsumeCheckbox.setText( localizer.translate('classSettingsWidget', 'vanishDuringUse')) self.useConsumeCheckbox.show() self.outcomeLabel.show() self.outcomeCombobox.show() else: self.useConsumeCheckbox.hide() self.outcomeLabel.hide() self.outcomeCombobox.hide() # When no use, hide and clear elements if (typeIndex == 0): self.useTargetCombo.hide() self.useTextLabel.hide() self.useTextEdit.hide() self.useTextEdit.clear() self.changeUseText() self.allTextsButton.hide() self.currentObject.clearTarget() else: self.useTargetCombo.show() self.useTextLabel.show() self.useTextEdit.show() self.allTextsButton.show() # Set item use target def setItemUseTarget(self, useItem): if (useItem): # Find the combobox item with the given item for i in range(self.useTargetCombo.count()): if (self.useTargetCombo.itemData(i) == useItem): self.useTargetCombo.setCurrentIndex(i) return self.useTargetCombo.setCurrentIndex(0) def setItemOutcome(self, outcomeItem): if (outcomeItem): # Find the combobox item with the given item for i in range(self.outcomeCombobox.count()): if (self.outcomeCombobox.itemData(i) == outcomeItem): self.outcomeCombobox.setCurrentIndex(i) return self.outcomeCombobox.setCurrentIndex(0) def setDoorInitialState(self): # Door open if (self.currentObject.closedImage or self.currentObject.lockedImage): self.doorInitialStateCombo.setCurrentIndex(0) # Door closed else: self.doorInitialStateCombo.setCurrentIndex(1) self.changeDoorInitialState() def setDoorOptions(self, doorObject): # Set each image's settings self.closedDoorImage.setSettings(doorObject, doorObject.closedImage) self.lockedDoorImage.setSettings(doorObject, doorObject.lockedImage) self.openDoorImage.setSettings(doorObject, doorObject.openImage) # Door transition room self.setComboboxIndex(doorObject.transition, self.doorTransitionCombo) # Set door open or closed in the beginning self.setDoorInitialState() # Set use item for items def setUseText(self, textEdit=None, item=None): if (self.useTypeCombo.currentIndex() == 0): return if not (item): item = self.currentObject useText = item.getUseText() if not (useText): useText = "" if (textEdit): textEdit.setText(useText) else: self.useTextEdit.setText(useText) # Set examine text for the given object def setExamineText(self, gameObject, textEdit=None): try: text = gameObject.getExamineText() except AttributeError: text = "" if (textEdit): textEdit.setText(text) else: self.examineTextEdit.setText(text) # Set any game object name def setObjectName(self, gameObject=None, textStart="Object", textEdit=None, overrideText=None): if not (gameObject): gameObject = self.currentObject if (overrideText): name = overrideText else: # Given image may be None try: name = gameObject.getName() except AttributeError: name = "" if (name is None): name = localizer.translate('classSettingsWidget', 'objectHasNoName') # If textEdit is defined, set its text instead if (textEdit): textEdit.setText(name) else: self.objectNameEdit.setText(name) def setUseConsume(self): isConsumed = self.useConsumeCheckbox.isChecked() self.currentObject.setConsume(isConsumed) if (isConsumed): self.useConsumeCheckbox.setCheckState(QtCore.Qt.CheckState.Checked) else: self.useConsumeCheckbox.setCheckState( QtCore.Qt.CheckState.Unchecked) def changeWhereLocated(self, combobox): # What is this used for? print("Change where located to", combobox.itemData(combobox.currentIndex())) # Text that comes after using an item def changeUseText(self): # TODO: Disable text field if no target is selected self.currentObject.setUseText(self.useTextEdit.toPlainText()) def changePickupText(self): self.currentObject.setPickupText(self.pickupTextEdit.toPlainText()) def changeExamineText(self, textEdit=None, gameObject=None): if not (gameObject): gameObject = self.currentObject if not (textEdit): textEdit = self.examineTextEdit gameObject.setExamineText(textEdit.toPlainText()) def changeDoorInitialState(self): # Initially closed, all states (closed, locked, open) are possible if (self.doorInitialStateCombo.currentIndex() == 0): self.closedDoorImage.setDisabled(False) self.lockedDoorImage.setDisabled(False) self.openDoorImage.setDisabled(False) # Add door's closed image self.currentObject.setClosed(True) self.currentObject.closedImage.placeholderImage.setSource( self.editor.getPlaceholderImagePath("Door")) # Initially open, only "open" state is possible else: self.closedDoorImage.setDisabled(True) self.lockedDoorImage.setDisabled(True) self.openDoorImage.setDisabled(False) # Remove door's closed and locked images self.currentObject.setClosed(False) self.currentObject.setLocked(False) # Change the image of a gameobject def changeObjectImage(self, imagePath, image=None, gameObject=None): # If no image, a default image var will be used # TODO: Copy the chosen image to the 'images' folder of the scenario? self.currentObject.getRepresentingImage().setSource(imagePath) self.setObjectImage(imagePath, image) print(imagePath) if not (gameObject): gameObject = self.currentObject self.editor.drawRoomItems() self.updateParent() self.editor.updateSpaceTab() # Change music def changeMusic(self, imagePath): self.currentObject.setMusic(imagePath) def changeUseConsume(self): self.currentObject.setConsume(self.useConsumeCheckbox.isChecked()) def changeOutcome(self): self.currentObject.setOutcome( self.outcomeCombobox.itemData(self.outcomeCombobox.currentIndex())) def clearOutcome(self): self.currentObject.setOutcome(None) def clearUseTarget(self): print("Clear useTarget!") # TODO: This is run even when populating the combobox #self.currentObject.clearTarget() def changeObstacleBlock(self): self.currentObject.setBlockTarget( self.obstacleBlocksCombo.itemData( self.obstacleBlocksCombo.currentIndex())) def clearObstacleBlock(self): self.currentObject.clearBlockTarget() def changeWhatGoes(self): self.currentObject.setInItem( self.whatGoesCombo.itemData(self.whatGoesCombo.currentIndex())) def clearWhatGoes(self): self.currentObject.clearInItem() def changeWhatComes(self): self.currentObject.setOutItem( self.whatComesCombo.itemData(self.whatComesCombo.currentIndex())) def clearWhatComes(self): self.currentObject.clearOutItem() def changeDoorTransition(self): self.currentObject.setTransition( self.doorTransitionCombo.itemData( self.doorTransitionCombo.currentIndex())) def changeName(self, textEdit=None, gameObject=None): if not (gameObject): gameObject = self.currentObject if (textEdit): text = textEdit.text() else: text = self.objectNameEdit.text() if (len(text) == 0): text = localizer.translate('classSettingsWidget', 'objectHasNoName') gameObject.setName(text) self.updateParent() # Update parent tab elements def updateParent(self): if (self.currentObject.__class__.__name__ in ("Room", "Sequence")): self.editor.drawRooms() else: self.editor.drawRoomItems() # Change object use type def changeItemUseType(self, index): self.setItemUseType(index) self.setItemUseTarget(None) self.setItemOutcome(None) # Set item use target def changeUseTarget(self): index = self.useTargetCombo.currentIndex() targetType = self.useTargetCombo.itemData(index).__class__.__name__ selectedObject = self.useTargetCombo.itemData(index) objectRole = 0 useType = self.useTypeCombo.currentIndex() if (targetType in ("Door", "Container")): # Unlock something and target object is not set into locked state if (useType == 2): # TODO: Really nullify old key? # Get old current object's key and nullify it self.currentObject.clearTarget() # Nullify selected door's key if (self.useTargetCombo.itemData(index).key): self.useTargetCombo.itemData(index).key.clearTarget() # Set the object to be locked with new key imagePath = self.editor.getPlaceholderImagePath(targetType) selectedObject.setLocked(True, imagePath, self.currentObject) # Put into container elif (useType == 3): objectRole = 1 # Get from container #elif (useType == 4): # objectRole = 2 self.currentObject.setTargetObject(selectedObject, objectRole) self.setUseText() # Create new game object def createObject(self, objectType): self.editor.createObject(objectType) self.updateComboboxes(objectType) def removeObject(self): self.editor.removeObjectsButtonClicked() def removeView(self): self.editor.removeViewsButtonClicked() def showAllTexts(self): # TODO: Select the actual object self.editor.tabWidget.setCurrentIndex(2) #self.currentObject. def clearMusic(self): self.currentObject.clearMusic() self.musicTextEdit.clear() # Sets the index of a combobox according to given targetObject def setComboboxIndex(self, targetObject, combobox): # Find the combobox item with the given item for i in range(combobox.count()): if (combobox.itemData(i) == targetObject): combobox.setCurrentIndex(i) return combobox.setCurrentIndex(0) # Create and return a plain combobox def createCombobox(self): combobox = QtGui.QComboBox(self) combobox.setIconSize(QtCore.QSize(50, 50)) return combobox # Create combobox from given items with default of all item types def updateItemCombobox(self, combobox, noChoiceText, objectTypes=None, addChoices=None, noChoiceMethod=None, connectTo=None): if not (objectTypes): objectTypes = ("object", "item", "door", "container", "obstacle") if (objectTypes == "room"): self.populateRoomCombobox(combobox, addChoices) else: self.populateCombobox(objectTypes, combobox, noChoiceText, addChoices, noChoiceMethod) combobox.activated.connect( lambda s: self.objectComboboxHandler(combobox, connectTo)) return combobox # Populate a given combobox with game rooms def populateRoomCombobox(self, combobox, addChoice=True): if (addChoice): imgPixmap = self.imageCache.createPixmap(self.editor.newIconPath) combobox.addItem( imgPixmap, localizer.translate('classSettingsWidget', 'addRoom')) for room in self.editor.getRoomObjects(): # TODO model to eliminate redundancy from getName/roomName patterns roomName = room.getName() if not (roomName): roomName = localizer.translate('classSettingsWidget', 'roomHasNoName') imgPixmap = self.imageCache.createPixmap(room.getRepresentingImage( ).getRepresentingImage().absoluteImagePath) roomIcon = QtGui.QIcon(imgPixmap) combobox.addItem(roomIcon, roomName, userData=room) # Create use target combobox def updateUseTargetCombobox(self, useType, combobox): if (useType == 0): objectTypes = () elif (useType == 1): objectTypes = ("item", "object") elif (useType == 2): objectTypes = ("door", "container") elif (useType == 3): objectTypes = ("container", ) elif (useType == 4): objectTypes = ("obstacle", ) self.populateCombobox( objectTypes, combobox, localizer.translate('classSettingsWidget', 'notSelected'), objectTypes, self.clearUseTarget) # Handle item combobox item choosing callback def objectComboboxHandler(self, combobox, callback): target = combobox.itemData(combobox.currentIndex()) targetType = target.__class__.__name__ # If chosen item is something else than a game object don't do callback if (targetType == "method"): target() elif (targetType == "str"): self.createObject(target) else: callback() # Populate a given combobox with given types of objects # categorized by game rooms def populateCombobox(self, objectTypes, combobox, noChoiceText=None, addChoices=None, noChoiceMethod=None): combobox.clear() itemCounter = 0 # Add the given string as the first item if (noChoiceText): imgPixmap = self.imageCache.createPixmap( self.editor.noChoiceIconPath) combobox.addItem(imgPixmap, noChoiceText, userData=noChoiceMethod) itemCounter = 1 # Add items to add given types of objects if (addChoices): imgPixmap = self.imageCache.createPixmap(self.editor.newIconPath) for choice in addChoices: combobox.addItem(imgPixmap, localizer.translate('classSettingsWidget', 'addNewChoice'), userData=choice) itemCounter += 1 for objType in objectTypes: objRooms = self.editor.getObjectsByType(objType) # Combobox has rooms with their obstacles under them for room in objRooms: roomObject = room["room"] roomName = roomObject.getName() if not (roomName): roomName = localizer.translate('classSettingsWidget', 'roomHasNoName') imgPixmap = self.imageCache.createPixmap( roomObject.getRepresentingImage().getRepresentingImage( ).absoluteImagePath) roomIcon = QtGui.QIcon(imgPixmap) # Add room to the combobox and disallow choosing it combobox.addItem(roomIcon, roomName) combobox.setItemData(itemCounter, 0, QtCore.Qt.UserRole - 1) itemCounter += 1 # TODO: Indendation of objects in the combobox # Add objects under the room for obj in room["objects"]: # Don't display the triggering item itself if (obj == self.currentObject): continue if (obj.getClassname() == "Text"): continue imageObject = obj.getRepresentingImage()\ .getRepresentingImage() imgPixmap = self.imageCache.createPixmap( imageObject.absoluteImagePath) targetIcon = QtGui.QIcon(imgPixmap) objectName = obj.getName() if not (objectName): objectName = localizer.translate( 'classSettingsWidget', 'objectHasNoName') combobox.addItem(targetIcon, objectName, userData=obj) itemCounter += 1 def showMusicDialog(self, callBack): fname, _ = QtGui.QFileDialog.getOpenFileName( self, localizer.translate('classSettingsWidget', 'showMusicDialogChoose'), '~', localizer.translate('classSettingsWidget', 'showMusicDialogFiles')) if (len(fname) != 0): self.musicTextEdit.setText(fname.split("/")[-1]) callBack(fname) def showImageDialog(self, callBack): fname, _ = QtGui.QFileDialog.getOpenFileName( self, localizer.translate('classSettingsWidget', 'chooseBackground'), '~', localizer.translate('classSettingsWidget', 'chooseBackgroundFiles')) if (len(fname) != 0): callBack(fname) def createSeparator(self): label = QtGui.QLabel("") label.setFrameStyle(QtGui.QFrame.HLine | QtGui.QFrame.Raised) return label