Exemplo n.º 1
0
class App(wx.App):
    @logmt
    def __init__(self, options):
        wx.App.__init__(self, redirect=False)

        self._splash = SplashScreen()
        self._splash.Show()

        # application's persistent state
        self.state = None
        self._load_state()

        self.doc_manager = DocumentManager(self)
        self.pkg_manager = None

        #: variables to be inserted into the python shell namespace
        self.shell_vars = {}
        self._init_shell_vars()

        #: command line options
        self.options = options

        self.frame = AppFrame(None, self.state, -1, size=(640, 480), app=self, title="PIDE")
        self.frame.Maximize(True)

        self._make_materials()

        self.frame.Show(True)
        self.SetTopWindow(self.frame)

        self._splash.app_initialized()

        # TODO: find correct place to do this
        self.frame.viewer.StartRendering()

        if IS_FIRST_RUN:
            self.on_first_run()

        # open the load generator dialog on startup
        wx.CallAfter(self.load_generator)

    @logmt
    def on_first_run(self):
        o = os.path

        # to show sample package to user
        sample_package = o.normpath(o.join(os.getcwd(), "..", "Samples"))
        repo = "http://procodile.vaspra.com/api"
        self.state.update_autocomplete("package_dir", sample_package)
        self.state.update_autocomplete("repo_uri", repo)

    @logmt
    def _load_state(self):
        state_fpath = os.path.join(get_user_app_dir(), "state.db")
        self.state = AppState(state_fpath)

    @logmt
    def _init_shell_vars(self):
        s = self.shell_vars
        s["app"] = self
        s["ogre"] = ogre

    @logmt
    def _make_materials(self):
        materials = MaterialManager()

        # default grey color
        default = MaterialColor((0.7, 0.7, 0.7))
        default.specular = Color((0.4, 0.4, 0.4))
        default.ambient = Color((0.5, 0.5, 0.5))
        default.shininess = 0.0
        materials.get_material(default, "default")

        # default highlight red color
        highlight = MaterialColor((0.8, 0.4, 0.4))
        highlight.specular = Color((0.5, 0.1, 0.1))
        highlight.ambient = Color((0.6, 0.2, 0.2))
        highlight.shininess = 0.0
        materials.get_material(highlight, "highlight")

        self.materials = materials

    @logmt
    def on_document_tab_closed(self, doc):
        self.doc_manager.del_document(doc)

    @logmt
    def on_close(self):
        self.doc_manager.stop()
        self.frame.cleanup()

    @property
    def cur_doc(self):
        return self.frame.get_current_document()

    def _ensure_doc(method):
        def wmethod(self, *args, **kwargs):
            args = list(args)
            get_doc = lambda doc: doc or self.frame.get_current_document()

            if "doc" in kwargs:
                kwargs["doc"] = get_doc(kwargs["doc"])
                if not kwargs["doc"]:
                    return

            elif args and (isinstance(args[0], (Document)) or args[0] == None):
                args[0] = get_doc(args[0])
                if not args[0]:
                    return

            else:
                kwargs["doc"] = get_doc(None)

            return method(self, *args, **kwargs)

        return wmethod

    @_ensure_doc
    @logmt
    def on_run(self, doc):
        if doc.state in (doc.STATE_READY, doc.STATE_PAUSED):
            self.run_document(doc)

        elif doc.state == doc.STATE_COMPLETED:
            self.reset_document(doc)
            self.run_document(doc)

        else:
            self.frame.update_document_state(doc)

    @_ensure_doc
    @logmt
    def on_reload(self, doc):
        self.reload_document(doc)
        self.reset_document(doc)
        self.run_document(doc)

    @_ensure_doc
    @logmt
    def on_stop(self, doc):
        self.reset_document(doc)

    @logmt
    def add_document(self, recipe, loader):
        doc = self.doc_manager.add_document(recipe, loader)
        self.frame.add_document(doc)
        return doc

    @_ensure_doc
    @logmt
    def del_document(self, doc):
        self.frame.del_document(doc)
        self.doc_manager.del_document(doc)

    @_ensure_doc
    @logmt
    def reset_document(self, doc):
        is_active_doc = doc == self.frame.get_current_document()
        viewer = self.frame.viewer

        if is_active_doc:
            viewer.unset_document()

        self.doc_manager.reset_document(doc)

        if is_active_doc:
            viewer.set_document(doc)

        self.frame.update_document_state(doc)

    @_ensure_doc
    @logmt
    def reload_document(self, doc):
        self.doc_manager.reload_document(doc)

    @_ensure_doc
    @logmt
    def save_document(self, doc):
        return self.doc_manager.save_document(doc)

    @_ensure_doc
    @logmt
    def save_document_as(self, doc):
        return self.doc_manager.save_document_as(doc)

    @logmt
    def save_screenshot(self, fpath=None):
        return self.frame.save_screenshot(fpath)

    @logmt
    def save_screenshots(self):
        doc = self.frame.get_current_document()
        props = dict(doc.get_properties())

        gen_id = props["generator_id"]
        path = props["location"]

        if not path:
            return

        dirpath = os.path.join(path, "screenshots", gen_id)
        if not os.path.exists(dirpath):
            os.makedirs(dirpath)

        views = ("front", "back", "perspective", "left", "right", "top", "bottom")

        for index, view in enumerate(views):
            doc.set_view(view, delayed=False)
            self.frame.viewer.render_window.update()
            spath = os.path.join(dirpath, "%02d_%s.jpg" % (index, view))
            self.save_screenshot(spath)

    @_ensure_doc
    @logmt
    def run_document(self, doc):
        ret = None

        if doc.state == doc.STATE_READY:
            ret = doc.run()
        elif doc.state == doc.STATE_PAUSED:
            ret = doc.resume()

        self.frame.update_document_state(doc)
        return ret

    @_ensure_doc
    @logmt
    def pause_document(self, doc):
        if doc.state == doc.STATE_RUNNING:
            ret = doc.pause()
            self.frame.update_document_state(doc)
            return ret

    @_ensure_doc
    @logmt
    def stop_document(self, doc):
        if doc.state in (doc.STATE_RUNNING, doc.STATE_PAUSED):
            ret = doc.stop()
            self.frame.update_document_state(doc)
            return ret

    @_ensure_doc
    @logmt
    def set_document_view(self, doc, view):
        return doc.set_view(view)

    @_ensure_doc
    @logmt
    def set_document_navigation(self, doc, navigation):
        return doc.set_navigation_mode(navigation)

    @_ensure_doc
    @logmt
    def toggle_document_navigation(self, doc):
        return doc.toggle_navigation_mode()

    @logmt
    def on_document_done(self, doc):
        self.frame.update_document_state(doc)

    @logmt
    def load_generator(self, start_dir=None):
        loader = Loader()
        old_loader = set_loader(loader)

        try:
            g_info = get_generator_info(self.frame, self)
            if not g_info:
                return
            is_remote, name, package_dir, repo_uri, generator_id, ver = g_info

            if is_remote:
                rc = RecipeConfig()
                rc.generator = (generator_id, repo_uri, generator_id, ver)

            else:
                _class = get_class(package_dir, generator_id)

                if RecipeBasedGenerator in _class.__bases__:
                    rc = _class.get_recipe_config()

                else:
                    rc = RecipeConfig()
                    rc.generator = (generator_id, package_dir, generator_id)

            doc = self.add_document(rc, loader)

        finally:
            set_loader(old_loader)

        self.run_document(doc)

    @logmt
    def upload_package(self, start_dir=None):
        info = get_upload_details(self.frame, self)
        if not info:
            return
        udg, repo_uri, username, password, package_dir, package_home, ver = info

        pdir = os.path.abspath(package_dir)
        no_snaps_gens = []

        package = get_loader().get_package(pdir)
        meta = package.meta

        if meta.version != ver:
            meta.version = ver
            xml_doc = meta.xmlize()
            xml_fpath = os.path.join(pdir, "package.xml")
            stream = open(xml_fpath, "w")
            stream.write('<?xml version="1.0" encoding="UTF-8"?>\n')
            xml_doc.serialize(stream)

        for g in meta.generators:
            cdir = os.path.sep.join([pdir, "screenshots", g.class_id])
            snaps = glob.glob(os.path.join(cdir, "*"))
            if not snaps:
                no_snaps_gens.append(g.class_id)

        if no_snaps_gens:

            dlg = GMD.GenericMessageDialog(
                udg,
                "These generators do not have screenshots: \n"
                + "\n".join(no_snaps_gens)
                + "\nDo you want to continue uploading",
                "Missing Screenshots",
                wx.YES_NO | wx.ICON_INFORMATION,
            )

            response = dlg.ShowModal()
            if response == wx.ID_NO:
                self.upload_package()
            dlg.Destroy()

        try:
            client = Client(repo_uri)
            client.login(username, password)
            client.upload(package_dir, package_home)
        except Client.Exception, e:
            print "".join(traceback.format_exception(*sys.exc_info()[:3]))

            dlg = wx.MessageDialog(
                udg,
                "Error occured when trying to upload package.\n" + e.message,
                "Package upload failed",
                wx.OK | wx.ICON_ERROR,
            )
            dlg.ShowModal()
            dlg.Destroy()
            self.upload_package()

        p_dir = package_dir.rsplit(os.path.sep, 1)[-1]
        dlg = wx.MessageDialog(
            udg,
            "Package is accessible at:\n" + "%s/package/%s.%s.%s-%s" % (repo_uri, username, package_home, p_dir, ver),
            "Package upload successful",
            wx.OK | wx.ICON_INFORMATION,
        )
        dlg.ShowModal()
        dlg.Destroy()