def _runInMainThread(self, f): """ Schedule function to run in main cocoa/Twisted thread. Called by the select() thread. """ AppHelper.callAfter(f)
def applicationDidFinishLaunching_(self, note): pth = self.opts["file"] if self.mode == "windowed": # load the viewer ui from the nib in plotdevice/rsrc nib = NSData.dataWithContentsOfFile_(rsrc_path("viewer.nib")) ui = NSNib.alloc().initWithNibData_bundle_(nib, None) ok, objs = ui.instantiateNibWithOwner_topLevelObjects_(self, None) NSApp().setMainMenu_(self.menu) # configure the window script-controller, and update-watcher self.script.setScript_options_(pth, self.opts) self.window.setTitleWithRepresentedFilename_(pth) # self.script.setWindowFrameAutosaveName_('plotdevice:%s'%self.opts['file']) # foreground the window (if -b wasn't passed) and run the script if opts["activate"]: NSApp().activateIgnoringOtherApps_(True) self.script.showWindow_(self) AppHelper.callAfter(self.script.scriptedRun) elif self.mode == "headless": # create a window-less WindowController self.script = ConsoleScript.alloc().init() self.script.setScript_options_(pth, self.opts) # BUG? FEATURE? (it's a mystery!) # exports will stall if `last` isn't an int. this should probably # be handled by the command line arg-parser though, no? if not opts.get("last", None): opts["last"] = opts.get("first", 1) # kick off an export session format = self.opts["export"].rsplit(".", 1)[1] kind = "movie" if format in ("mov", "gif") else "image" self.script.exportInit(kind, self.opts["export"], self.opts)
def load_html(self, content, base_uri): def load(content, url): url = Foundation.NSURL.URLWithString_(BrowserView.quote(url)) self.webkit.loadHTMLString_baseURL_(content, url) self.loaded.clear() AppHelper.callAfter(load, content, base_uri)
def invalidate_size_request(self): # don't figure out the size immediately, this could lead to weirdness # and could be inefficent if we do something else to invalidate the # size request in the current event. if not self._will_invalidate_size_request: AppHelper.callAfter(self._invalidate_size_request) self._will_invalidate_size_request = True
def load_url(self, url): def load(url): page_url = Foundation.NSURL.URLWithString_(BrowserView.quote(url)) req = Foundation.NSURLRequest.requestWithURL_(page_url) self.webkit.loadRequest_(req) self.loaded.clear() self.url = url AppHelper.callAfter(load, url)
def get_current_url(self): def get(): self._current_url = self.webkit.URL() self._current_url_semaphore.release() AppHelper.callAfter(get) self._current_url_semaphore.acquire() return self._current_url
def _handle_reply_params(self, msg_root, msg_elem): """A fudge until the Renderer Manager is in place.""" super()._handle_reply_params(msg_root, msg_elem) self.rfb_address = self.params['address'] self.rfb_port = int(self.params['port']) self.rfb_password = self.params['password'] msg = "rfb://{address}:{port}" log.info(msg.format(address=self.rfb_address, port=self.rfb_port)) AppHelper.callAfter(self.handle_prepare)
def added(self, serviceName, *args, **kwargs): self.add_lock.acquire() if serviceName in self.indexes: return index = self.controller.computers.content().count() fc = FoundComputer.FoundComputer.alloc().init() fc.name = serviceName AppHelper.callAfter(self.controller.computers.addObject_, fc) self.indexes[serviceName]=index self.add_lock.release()
def create_window(uid, title, url, width, height, resizable, fullscreen, min_size, confirm_quit, background_color, debug, js_api, text_select, frameless, webview_ready): def create(): browser = BrowserView(uid, title, url, width, height, resizable, fullscreen, min_size, confirm_quit, background_color, debug, js_api, text_select, frameless, webview_ready) browser.show() if uid == 'master': create() else: AppHelper.callAfter(create)
def doAbortError(title, msg): def showMsg(): alert = AppKit.NSAlert.alloc().init() alert.setMessageText_(title) alert.setInformativeText_(msg) # Use this instead of informativeTextWithFormat to avoid % related errors alert.setAlertStyle_(AppKit.NSCriticalAlertStyle) alert.runModal() AppKit.NSApplication.sharedApplication().stop_(None) AppHelper.callAfter(showMsg) AppKit.NSApplication.sharedApplication() AppKit.NSApp.run()
def toggle_fullscreen(self): def toggle(): if self.is_fullscreen: window_behaviour = 1 << 2 # NSWindowCollectionBehaviorManaged else: window_behaviour = 1 << 7 # NSWindowCollectionBehaviorFullScreenPrimary self.window.setCollectionBehavior_(window_behaviour) self.window.toggleFullScreen_(None) AppHelper.callAfter(toggle) self.is_fullscreen = not self.is_fullscreen
def _user_thread_main(self, target): """Main entry point for the thread that will run user's code.""" try: # Run user's code. return_code = target() # Assume good result (0 return code) if none is returned. if return_code is None: return_code = 0 # Call exit on the main thread when user code has finished. AppHelper.callAfter(lambda: sys.exit(return_code)) except Exception as ex: # Something went wrong. Raise the exception on the main thread to exit. AppHelper.callAfter(self._raise_error, sys.exc_info())
def set_window_size(self, width, height): def _set_window_size(): frame = self.window.frame() # Keep the top left of the window in the same place frame.origin.y += frame.size.height frame.origin.y -= height frame.size.width = width frame.size.height = height self.window.setFrame_display_(frame, True) AppHelper.callAfter(_set_window_size)
def idle_add(callback, periodic=None): def wrapper(): callback() if periodic is not None: AppHelper.callLater(periodic, wrapper) if periodic is not None and periodic < 0: raise ValueError('periodic cannot be negative') # XXX: we have a lousy thread API that doesn't allocate pools for us... pool = NSAutoreleasePool.alloc().init() if periodic is not None: AppHelper.callLater(periodic, wrapper) else: AppHelper.callAfter(wrapper) del pool
def added(self, serviceName, regtype, replyDomain, hosttarget, *args, **kwargs): self.add_lock.acquire() if serviceName in self.indexes: return index = self.controller.computers.content().count() fc = FoundComputer.FoundComputer.alloc().init() fc.controller = self.controller fc.name = serviceName print serviceName fc.ip = socket.gethostbyname(hosttarget) AppHelper.callAfter(self.controller.computers.addObject_, fc) self.indexes[serviceName]=index self.add_lock.release() print self.controller.computers
def model_changed(self): if not self.row_height_set and self.fixed_height: self.try_to_set_row_height() size_changed = False if self.reload_needed: self.tableview.reloadData() self.update_selection_after_change() size_changed = True self.tableview.recalcTrackingRects() elif self.iters_to_update: if self.fixed_height or not self.height_changed: # our rows don't change height, just update cell areas if self.is_tree(): for iter in self.iters_to_update: self.tableview.reloadItem_(iter.value()) else: for iter in self.iters_to_update: row = self.row_for_iter(iter) rect = self.tableview.rectOfRow_(row) self.tableview.setNeedsDisplayInRect_(rect) else: # our rows can change height inform Cocoa that their heights # might have changed (this will redraw them) rows_to_change = [ self.row_for_iter(iter) for iter in \ self.iters_to_update] index_set = NSMutableIndexSet.alloc().init() for iter in self.iters_to_update: index_set.addIndex_(self.row_for_iter(iter)) self.tableview.noteHeightOfRowsWithIndexesChanged_(index_set) self.tableview.recalcTrackingRects() size_changed = True else: return if size_changed: # we can't call invalidate_size_request right away because of the # (common) situation where multiple TableViews are connected to # one model. In that case, we will change that model, then call # model_changed() on the item views in order # # The problem is when the first TableViews calls # invalidate_size_request() and that is propagated up the widget # hierarchy, potentially causing the other TableViews to redraw # their contents. But they haven't seen the model_changed() # method yet, so we will get an exception when trying to redraw # them. AppHelper.callAfter(self.invalidate_size_request) self.height_changed = self.reload_needed = False self.iters_to_update = []
def runModal(self, title, message, help_link, text = ''): pool = NSAutoreleasePool.alloc().init() try: app = NSApplication.sharedApplication() if app.isRunning(): death_event = Event() app_delegate = BootErrorAppDelegate(title, message, help_link, text, death_event) AppHelper.callAfter(app_delegate.applicationWillFinishLaunching_, None) death_event.wait() else: AppHelper.installMachInterrupt() app_delegate = BootErrorAppDelegate(title, message, help_link, text, None) app.setDelegate_(app_delegate) AppHelper.runEventLoop() finally: del pool
def run_nose(nose_done): global nose_threaded nose_threaded = True try: import nose try: import logging logging.getLogger().handlers[0].level = 99 nose.main(addplugins=[TinymailTestPlugin()]) except SystemExit: pass except: log.exception("Uncaught exception in nose thread") finally: AppHelper.callAfter(nose_done, None)
def evaluate_js(self, script): def eval(): self.webkit.evaluateJavaScript_completionHandler_(script, handler) def handler(result, error): JSResult.result = None if result is None or result == 'null' else json.loads(result) JSResult.result_semaphore.release() class JSResult: result = None result_semaphore = Semaphore(0) self.loaded.wait() AppHelper.callAfter(eval) JSResult.result_semaphore.acquire() return JSResult.result
def windowScriptObjectAvailable_(self, scriptObject): global log log = lambda x: AppHelper.callAfter(scriptObject.callWebScriptMethod_withArguments_, 'log', [x]) scriptObject.setValue_forKey_("yes", "TestBundleLoaded") scriptObject.setValue_forKey_(self, "TestBundle") AppHelper.callLater(1, scriptObject.callWebScriptMethod_withArguments_, 'initialize_threads', []) #log("hi!"); self.wso = scriptObject
def initBrowser(self, remote): se = self._dropbox_app.sync_engine if not remote else self._dropbox_app.mbox.sync_engine self.forest = CachingLazySelectiveSyncUI(self._dropbox_app, se, self._dropbox_app.dropbox_url_info, use_tri_state_checks=True, initial_directory_ignore_set=self._initial_ignore_list) if self._dropbox_app.pref_controller['selsync_advanced_view_hint']: self.forest.advanced_view = True self.browser = SelectiveSyncBrowser() self.browser.setTitled_(NO) self.browser.setFocusRingType_(NSFocusRingTypeNone) self.browserDelegate = SelectiveSyncBrowserDelegate(self.browser, self.forest, self.reloadInvalidState) self.forest.set_invalidate_ui_callback(lambda events: AppHelper.callAfter(self.browserDelegate.invalidateUICallback_, events)) self.browser.setDelegate_(self.browserDelegate) self.addSubview_(self.browser)
def destroy(self): AppHelper.callAfter(self.window.close)
def _onSessionDetached(self): AppHelper.callAfter(self._sessionDidDetach)
def call_on_main_thread(callback, *args, **kwargs): #obj, selector = object_and_selector_for_callback(callback, *args, **kwargs) #obj_later = obj.performSelectorOnMainThread_withObject_waitUntilDone_ #obj_later(selector, None, False) AppHelper.callAfter(callback, *args, **kwargs)
def set_title(self, title): def _set_title(): self.window.setTitle_(title) AppHelper.callAfter(_set_title)
raise ValueError("Expected a monocle Callback from %r, got %r" % (func, res_cb)) @_o def wait_for_result(): try: res = yield res_cb except Exception, e: # TODO print traceback to a StringIO? res = e result.append(res) done.release() wait_for_result() AppHelper.callAfter(wrapped_call) done.acquire() if isinstance(result[0], Exception): raise result[0] else: return result[0] def runs_on_main_thread(func): @wraps(func) def wrapper(*args, **kwargs): return call_on_main_thread(monocle.o(func), *args, **kwargs) return wrapper
def _onScriptMessage(self, message, data): AppHelper.callAfter(self._sessionDidReceiveMessage_data_, message, data)
def quit_(self, arg): self.is_running = False AppHelper.callAfter(NSApp.terminate_, self)
def move(x, y, uid): AppHelper.callAfter(BrowserView.instances[uid].move, x, y)
def show(self): """ Prompt the user to acknowledge the message """ AppHelper.callAfter(call_timer_listener, self)
class Capture(NSObject): def __new__(cls, device): return cls.alloc().initWithDevice_(device) def initWithDevice_(self, device): self = self.init() self.state = CaptureState.DETACHED self.device = device self._delegate = None self.session = None self.script = None self.modules = Modules() self.recvTotal = 0 self.calls = Calls(self) return self def delegate(self): return self._delegate def setDelegate_(self, delegate): self._delegate = delegate def attachToProcess_triggerPort_(self, process, triggerPort): assert self.state == CaptureState.DETACHED self._updateState_(CaptureState.ATTACHING) NSThread.detachNewThreadSelector_toTarget_withObject_( '_doAttachWithParams:', self, (process.pid, triggerPort)) def detach(self): assert self.state == CaptureState.ATTACHED session = self.session script = self.script self.session = None self.script = None self._updateState_(CaptureState.DETACHED) NSThread.detachNewThreadSelector_toTarget_withObject_( '_doDetachWithParams:', self, (session, script)) def _post(self, message): NSThread.detachNewThreadSelector_toTarget_withObject_( '_doPostWithParams:', self, (self.script, message)) def _updateState_(self, newState): self.state = newState self._delegate.captureStateDidChange() def _doAttachWithParams_(self, params): pid, triggerPort = params pool = NSAutoreleasePool.alloc().init() session = None script = None error = None try: session = self.device.attach(pid) session.on('detached', self._onSessionDetached) script = session.session.create_script( SCRIPT_TEMPLATE % {'trigger_port': triggerPort}) script.on('message', self._onScriptMessage) script.load() except Exception, e: if session is not None: try: session.detach() except: pass session = None script = None error = e AppHelper.callAfter(self._attachDidCompleteWithSession_script_error_, session, script, error) del pool
def create_file_dialog(self, dialog_type, directory, allow_multiple, save_filename, file_filter, main_thread=False): def create_dialog(*args): dialog_type = args[0] if dialog_type == SAVE_DIALOG: save_filename = args[2] save_dlg = AppKit.NSSavePanel.savePanel() save_dlg.setTitle_(localization['global.saveFile']) if directory: # set initial directory save_dlg.setDirectoryURL_( Foundation.NSURL.fileURLWithPath_(directory)) if save_filename: # set file name save_dlg.setNameFieldStringValue_(save_filename) if save_dlg.runModal() == AppKit.NSFileHandlingPanelOKButton: self._file_name = save_dlg.filename() else: self._file_name = None else: allow_multiple = args[1] open_dlg = AppKit.NSOpenPanel.openPanel() # Enable the selection of files in the dialog. open_dlg.setCanChooseFiles_(dialog_type != FOLDER_DIALOG) # Enable the selection of directories in the dialog. open_dlg.setCanChooseDirectories_(dialog_type == FOLDER_DIALOG) # Enable / disable multiple selection open_dlg.setAllowsMultipleSelection_(allow_multiple) # Set allowed file extensions if file_filter: open_dlg.setAllowedFileTypes_(file_filter[0][1]) # Add a menu to choose between multiple file filters if len(file_filter) > 1: filter_chooser = BrowserView.FileFilterChooser.alloc( ).initWithFilter_(file_filter) open_dlg.setAccessoryView_(filter_chooser) open_dlg.setAccessoryViewDisclosed_(True) if directory: # set initial directory open_dlg.setDirectoryURL_( Foundation.NSURL.fileURLWithPath_(directory)) if open_dlg.runModal() == AppKit.NSFileHandlingPanelOKButton: files = open_dlg.filenames() self._file_name = tuple(files) else: self._file_name = None if not main_thread: self._file_name_semaphore.release() if main_thread: create_dialog(dialog_type, allow_multiple, save_filename) else: AppHelper.callAfter(create_dialog, dialog_type, allow_multiple, save_filename) self._file_name_semaphore.acquire() return self._file_name
def hide(self): def _hide(): self.window.orderOut_(self.window) AppHelper.callAfter(_hide)
def set_on_top(uid, top): def _set_on_top(): level = AppKit.NSStatusWindowLevel if top else AppKit.NSNormalWindowLevel BrowserView.instances[uid].window.setLevel_(level) AppHelper.callAfter(_set_on_top)
def applicationWillFinishLaunching_(self, notification): AppHelper.callAfter(self.alertLoop)
def alarm(self): AppHelper.callAfter(call_timer_listener, self._listener)
def add_widget(self, widget): if len(self.widgets_to_request) == 0: AppHelper.callAfter(self._run_requests) self.widgets_to_request.add(widget)
def show(self): def _show(): self.window.makeKeyAndOrderFront_(self.window) AppHelper.callAfter(_show)