def on_vertical_scrollbar_moved(self,value):
     """ When the scrollbar moves, queue a refresh of the visible
         rows.  This makes it only update the view when needed
         making scrolling much smoother.   
     """
     self._pending_row_refreshes +=1
     timed_call(0,self._refresh_visible_row,value)
    def run(self):
        """ Run the model synchronously.
        Shows a modal dialog until the run completes.
        Returns the dialog.
        """
        runner = self.runner
        gui_handler = lambda *args: deferred_call(self.handle_error, *args)
        runner.error_handler = gui_handler
        dialog = RunDialog(parent=self.parent,
                           title='Running model...',
                           text='Please wait while the model runs.')
        dialog.observe('rejected', lambda change: runner.cancel())
        dialog.show()
        event_loop = QtCore.QEventLoop()
        timer = QtCore.QTimer()

        def start_run():
            runner.run()
            timer.setInterval(50)
            timer.timeout.connect(check_loop)
            timer.start()

        def check_loop():
            dialog.output = runner.output()
            if not runner.running:
                timer.stop()
                event_loop.quit()

        timed_call(50, start_run)
        event_loop.exec_()
        dialog.accept()
        return dialog
Exemple #3
0
 def set_items(self, items):
     """ Defer until later so the view is only updated after all items
     are added. 
     
     """
     self._pending_view_refreshes += 1
     timed_call(self._pending_timeout, self._refresh_layout)
Exemple #4
0
def handle_dialog(qtbot, op='accept', handler=lambda qtbot, window: window,
                  cls=Dialog, time=100, skip_answer=False):
    """Automatically close a dialog opened during the context.

    Parameters
    ----------
    op : {'accept', 'reject'}, optional
        Whether to accept or reject the dialog.

    handler : callable, optional
        Callable taking as arguments the bot and the dialog, called before
        accepting or rejecting the dialog.

    cls : type, optional
        Dialog class to identify.

    time : float, optional
        Time to wait before handling the dialog in ms.

    skip_answer : bool, optional
        Skip answering to the dialog. If this is True the handler should handle
        the answer itself.

    """
    sch = ScheduledClosing(qtbot, cls, handler, op, skip_answer)
    timed_call(time, sch)
    try:
        yield
    except Exception:
        raise
    else:
        qtbot.wait_until(sch.was_called, 10e3)
Exemple #5
0
 def on_horizontal_scrollbar_moved(self, value):
     """ When the scrollbar moves, queue a refresh of the visible
         columns.  This makes it only update the view when needed
         making scrolling much smoother.   
     """
     self._pending_column_refreshes += 1
     timed_call(0, self._refresh_visible_column, value)
Exemple #6
0
 def on_vertical_scrollbar_moved(self, value):
     """ When the scrollbar moves, queue a refresh of the visible
         rows.  This makes it only update the view when needed
         making scrolling much smoother.   
     """
     self._pending_row_refreshes += 1
     timed_call(0, self._refresh_visible_row, value)
Exemple #7
0
def async_sleep(ms):
    """ Sleep for the given duration without blocking. Typically this
    is used with the inlineCallbacks decorator.
    """
    d = Deferred()
    timed_call(ms, d.callback, True)
    return d
Exemple #8
0
 def _update_index(self):
     """ Update the reference to the index within the table """
     d = self.declaration
     self.index = self.view.model.index(d.row, d.column)
     if self.delegate:
         self._refresh_count += 1
         timed_call(self._loading_interval, self._update_delegate)
Exemple #9
0
 def _refresh_plot(self):
     """Defer drawing until all changes are done so we don't draw
     during initialization or when many values change at once.
     """
     self._pending_refreshes += 1
     refresh_time = self.declaration.refresh_time
     timed_call(refresh_time, self._redraw_plot)
Exemple #10
0
 def _update_index(self):
     """ Update the reference to the index within the table """ 
     d = self.declaration
     self.index = self.view.model.index(d.row,d.column)
     if self.delegate:
         self._refresh_count +=1
         timed_call(self._loading_interval,self._update_delegate)
Exemple #11
0
def handle_dialog(qtbot, op='accept', handler=lambda qtbot, window: window,
                  cls=Dialog, time=100, skip_answer=False):
    """Automatically close a dialog opened during the context.

    Parameters
    ----------
    op : {'accept', 'reject'}, optional
        Whether to accept or reject the dialog.

    handler : callable, optional
        Callable taking as arguments the bot and the dialog, called before
        accepting or rejecting the dialog.

    cls : type, optional
        Dialog class to identify.

    time : float, optional
        Time to wait before handling the dialog in ms.

    skip_answer : bool, optional
        Skip answering to the dialog. If this is True the handler should handle
        the answer itself.

    """
    sch = ScheduledClosing(qtbot, cls, handler, op, skip_answer)
    timed_call(time, sch)
    try:
        yield
    except Exception:
        raise
    else:
        qtbot.wait_until(sch.was_called, TIMEOUT)
Exemple #12
0
def async_sleep(ms):
    """ Sleep for the given duration without blocking. Typically this
    is used with the inlineCallbacks decorator.
    """
    d = Deferred()
    timed_call(ms, d.callback, True)
    return d
 def on_horizontal_scrollbar_moved(self,value):
     """ When the scrollbar moves, queue a refresh of the visible
         columns.  This makes it only update the view when needed
         making scrolling much smoother.   
     """
     self._pending_column_refreshes +=1
     timed_call(0,self._refresh_visible_column,value)
Exemple #14
0
 def schedule_ping(self):
     """ Ping perioidcally so the process stays awake """
     if self.terminated:
         return
     # Ping the viewer to tell it to keep alive
     self.send_message("ping", _id="keep_alive", _silent=True)
     timed_call(self._ping_rate * 1000, self.schedule_ping)
 def _observe_view(self, change):
     """ Move window and allow it to draw before taking the snapshot.
     
     """
     if change['type'] == 'create':
         self.view.initial_position = (10, 10)
         self.view.always_on_top = True
         timed_call(1500, self.snapshot)
Exemple #16
0
 def _queue_update(self,change):
     """ Schedule an update to be performed in the next available cycle.
         This should be used for expensive operations as opposed to an
         immediate update with update_shape.
     
     """
     self._update_count +=1
     timed_call(0,self._dequeue_update,change)
Exemple #17
0
 def __init__(self, view, watch=False):
     self.view = view
     self.watch = watch
     self._watched_files = {}
     if watch:
         timed_call(1000, self.check_for_changes)
     self._exit_in_sec = 60
     super(ViewerProtocol).__init__()
 def _observe_view(self, change):
     """ Move window and allow it to draw before taking the snapshot.
     
     """
     if change['type'] == 'create':
         self.view.initial_position = (10, 10)
         self.view.always_on_top = True
         timed_call(1500, self.snapshot)
Exemple #19
0
    def _queue_save_state(self, change):
        """ Queue a save state. This calls _save_state after a given duration
        so that multiple state changes get batched and saved all at once
        instead of saving multiple times (which a become slow).

        """
        if change['type'] in ['update', 'manual', 'container']:
            self._state_save_pending += 1
            timed_call(350, self._save_state, change)
Exemple #20
0
    def _fire_plot_update(self, schedule_only=False):
        """Fire the plot update event and reschedule a new call.

        """
        if not schedule_only:
            self.plot_update = True
        if not self._stop_timer:
            timed_call(1000 * self.plot_refresh_interval,
                       self._fire_plot_update)
Exemple #21
0
    def _update_index(self):
        self.index = self._default_index()
        print 'UPDATE',self.declaration.text,self,self.index.internalPointer(),self.index.row(),self.index.column(),self.index.parent()

        assert self == self.view.model.itemAt(self.index)
        
        if self.delegate and self.index.isValid():
            #print self.parent(),self,self.index.row(),self.index.column()
            self._refresh_count +=1
            timed_call(self._loading_interval,self._update_delegate)
Exemple #22
0
 def schedule_close(self):
     """ A watchdog so if the parent is killed the viewer will automatically
     exit. Otherwise it will hang around forever.
     """
     if self._exit_in_sec <= 0:
         # Timeout
         print("WARNING: Ping timeout expired, closing")
         sys.exit(1)
     else:
         timed_call(self._exit_in_sec * 1000, self.schedule_close)
         self._exit_in_sec = 0  # Clear timeout
Exemple #23
0
    def save_dock_area(self, change):
        """ Save the dock area """
        self._area_saves_pending += 1

        def do_save():
            self._area_saves_pending -= 1
            if self._area_saves_pending != 0:
                return
            #: Now save it
            ui = self.workbench.get_plugin('enaml.workbench.ui')
            ui.workspace.save_area()

        timed_call(350, do_save)
Exemple #24
0
def main(**kwargs):
    app = Application()

    filename = kwargs.get('file', '-')
    frameless = kwargs.get('frameless', False)
    watch = kwargs.get('watch', False)

    if not frameless and not os.path.exists(filename):
        raise ValueError("File %s does not exist!" % filename)

    view = ViewerWindow(filename='-', frameless=frameless)
    view.protocol = ViewerProtocol(view=view, watch=watch)
    if watch:
        timed_call(1000, view.protocol.check_for_changes)
    view.show()
    app.deferred_call(create_stdio_connection, app.loop, view.protocol)
    app.deferred_call(view.protocol.handle_filename, filename)
    app.start()
Exemple #25
0
    def send_message(self, method, *args, **kwargs):
        # Defer until it's ready
        if not self.transport:
            log.debug('renderer | message not ready deferring')
            timed_call(0, self.send_message, method, *args, **kwargs)
            return
        _id = kwargs.pop('_id')

        request = {
            'jsonrpc': '2.0',
            'method': method,
            'params': args or kwargs
        }
        if _id is not None:
            request['id'] = _id

        log.debug(f'renderer | sent | {request}')
        self.transport.write(jsonpickle.dumps(request).encode() + b'\r\n')
Exemple #26
0
    def send_message(self, method, *args, **kwargs):
        # Defer until it's ready
        if not self.transport or not self.window_id:
            #log.debug('renderer | message not ready deferring')
            timed_call(1000, self.send_message, method, *args, **kwargs)
            return
        _id = kwargs.pop('_id')
        _silent = kwargs.pop('_silent', False)

        request = {
            'jsonrpc': '2.0',
            'method': method,
            'params': args or kwargs
        }
        if _id is not None:
            request['id'] = _id
        if not _silent:
            log.debug(f'renderer | sent | {request}')
        encoded_msg = jsonpickle.dumps(request).encode() + b'\r\n'
        deferred_call(self.transport.write, encoded_msg)
Exemple #27
0
def handle_dialog(op='accept', custom=lambda x: x, cls=Dialog, time=100):
    """Automatically close a dialog opened during the context.

    Parameters
    ----------
    op : {'accept', 'reject'}, optional
        Whether to accept or reject the dialog.

    custom : callable, optional
        Callable taking as only argument the dialog, called before accepting
        or rejecting the dialog.

    cls : type, optional
        Dialog class to identify.

    time : float, optional
        Time to wait before handling the dialog in ms.

    """
    def close_dialog():
        i = 0
        while True:
            dial = get_window(cls)
            if dial is not None:
                break
            elif i > 10:
                raise Exception('Dialog timeout')
            sleep(0.1)
            i += 1

        try:
            custom(dial)
        finally:
            process_app_events()
            from .fixtures import DIALOG_SLEEP
            sleep(DIALOG_SLEEP)
            getattr(dial, op)()

    timed_call(time, close_dialog)
    yield
    process_app_events()
Exemple #28
0
def handle_dialog(op='accept', custom=lambda x: x, cls=Dialog, time=100):
    """Automatically close a dialog opened during the context.

    Parameters
    ----------
    op : {'accept', 'reject'}, optional
        Whether to accept or reject the dialog.

    custom : callable, optional
        Callable taking as only argument the dialog, called before accepting
        or rejecting the dialog.

    cls : type, optional
        Dialog class to identify.

    time : float, optional
        Time to wait before handling the dialog in ms.

    """
    def close_dialog():
        i = 0
        while True:
            dial = get_window(cls)
            if dial is not None:
                break
            elif i > 10:
                raise Exception('Dialog timeout')
            sleep(0.1)
            i += 1

        try:
            custom(dial)
        finally:
            process_app_events()
            from .fixtures import DIALOG_SLEEP
            sleep(DIALOG_SLEEP)
            getattr(dial, op)()
    timed_call(time, close_dialog)
    yield
    process_app_events()
Exemple #29
0
def handle_dialog(op='accept',
                  custom=lambda x: x,
                  cls=Dialog,
                  time=100,
                  skip_answer=False):
    """Automatically close a dialog opened during the context.

    Parameters
    ----------
    op : {'accept', 'reject'}, optional
        Whether to accept or reject the dialog.

    custom : callable, optional
        Callable taking as only argument the dialog, called before accepting
        or rejecting the dialog.

    cls : type, optional
        Dialog class to identify.

    time : float, optional
        Time to wait before handling the dialog in ms.

    skip_answer : bool, optional
        Skip answering to the dialog. If this is True the handler should handle
        the answer itself.

    """
    sch = ScheduledClosing(cls, custom, op)
    timed_call(time, sch)
    try:
        yield
    except Exception:
        raise
    else:
        while not sch.called:
            process_app_events()
Exemple #30
0
    def check_for_changes(self):
        """ A simple poll loop to check if the file changed and if it has
        reload it by bumping the version.

        """
        if self.watch:
            timed_call(1000, self.check_for_changes)

        try:
            filename = self.view.filename
            if os.path.exists(filename):
                try:
                    mtime = os.stat(filename).st_mtime
                except:
                    return

                if filename not in self._watched_files:
                    self._watched_files[filename] = mtime
                elif self._watched_files[filename] != mtime:
                    self._watched_files[filename] = mtime
                    print("%s changed, reloading" % filename)
                    deferred_call(self.handle_version, self.view.version + 1)
        except Exception as e:
            print(traceback.format_exc())
Exemple #31
0
 def _observe_running(self, change):
     if self.running:
         timed_call(0, self.tick)
Exemple #32
0
 def _observe_now(self, change):
     t = self.now
     self.year, self.month, self.day = t.year, t.month, t.day
     self.hour, self.minute, self.second = t.hour, t.minute, t.second
     if self.running:
         timed_call(1000, self.tick)
Exemple #33
0
 def _observe_parts(self, change):
     """ When changed, do a fit all """
     if change['type'] == 'update':
         timed_call(500, self.fit_all)
Exemple #34
0
 def _observe_running(self, change):
     if self.running:
         timed_call(0, self.tick)
Exemple #35
0
 def _refresh_plot(self):
     """ Defer drawing until all changes are done so we don't draw
         during initialization or when many values change at once.
     """
     self._pending_refreshes+=1
     timed_call(100,self._redraw_plot)
Exemple #36
0
    def submit(self, job, test=False):
        """ Submit the job to the device. If the device is currently running
        a job it will be queued and run when this is finished.

        This handles iteration over the path model defined by the job and
        sending commands to the actual device using roughly the procedure is
        as follows:

                device.connect()

                model = device.init(job)
                for cmd in device.process(model):
                    device.handle(cmd)
                device.finish()

                device.disconnect()

        Subclasses provided by your own DeviceDriver may reimplement this
        to handle path interpolation however needed. The return value is
        ignored.

        The live plot view will update whenever the device.position object
        is updated. On devices with lower cpu/gpu capabilities this should
        be updated sparingly (ie the raspberry pi).

        Parameters
        -----------
            job: Instance of `inkcut.job.models.Job`
                The job to execute on the device
            test: bool
                Do a test run. This specifies whether the commands should be
                sent to the actual device or not. If True, the connection will
                be replaced with a virtual connection that captures all the
                command output.

        """
        log.debug("device | submit {}".format(job))
        try:

            #: Only allow one job at a time
            if self.busy:
                queue = self.queue[:]
                queue.append(job)
                self.queue = queue  #: Copy and reassign so the UI updates
                log.info("Job {} put in device queue".format(job))
                return

            with self.device_busy():
                #: Set the current the job
                self.job = job
                self.status = "Initializing job"

                #: Get the time to sleep based for each unit of movement
                config = self.config

                #: Rate px/ms
                if config.custom_rate >= 0:
                    rate = config.custom_rate
                elif self.connection.always_spools or config.spooled:
                    rate = 0
                elif config.interpolate:
                    if config.step_time > 0:
                        rate = config.step_size / float(config.step_time)
                    else:
                        rate = 0  # Undefined
                else:
                    rate = from_unit(
                        config.speed,  # in/s or cm/s
                        config.speed_units.split("/")[0]) / 1000.0

                # Device model is updated in real time
                model = yield defer.maybeDeferred(self.init, job)

                #: Local references are faster
                info = job.info

                #: Determine the length for tracking progress
                whole_path = QtGui.QPainterPath()

                #: Some versions of Qt seem to require a value in
                #: toSubpathPolygons
                m = QtGui.QTransform.fromScale(1, 1)
                for path in model.toSubpathPolygons(m):
                    for i, p in enumerate(path):
                        whole_path.lineTo(p)
                total_length = whole_path.length()
                total_moved = 0
                log.debug("device | Path length: {}".format(total_length))

                #: So a estimate of the duration can be determined
                info.length = total_length
                info.speed = rate * 1000  #: Convert to px/s

                #: Waiting for approval
                info.status = 'waiting'

                #: If marked for auto approve start now
                if info.auto_approve:
                    info.status = 'approved'
                else:
                    #: Check for approval before starting
                    yield defer.maybeDeferred(info.request_approval)
                    if info.status != 'approved':
                        self.status = "Job cancelled"
                        return

                #: Update stats
                info.status = 'running'
                info.started = datetime.now()

                self.status = "Connecting to device"
                with self.device_connection(test
                                            or config.test_mode) as connection:
                    self.status = "Processing job"
                    try:
                        yield defer.maybeDeferred(self.connect)

                        #: Write startup command
                        if config.commands_before:
                            yield defer.maybeDeferred(connection.write,
                                                      config.commands_before)

                        self.status = "Working..."

                        #: For point in the path
                        for (d, cmd, args, kwargs) in self.process(model):

                            #: Check if we paused
                            if info.paused:
                                self.status = "Job paused"
                                #: Sleep until resumed, cancelled, or the
                                #: connection drops
                                while (info.paused and not info.cancelled
                                       and connection.connected):
                                    yield async_sleep(300)  # ms

                            #: Check for cancel for non interpolated jobs
                            if info.cancelled:
                                self.status = "Job cancelled"
                                info.status = 'cancelled'
                                break
                            elif not connection.connected:
                                self.status = "connection error"
                                info.status = 'error'
                                break

                            #: Invoke the command
                            #: If you want to let the device handle more complex
                            #: commands such as curves do it in process and handle
                            yield defer.maybeDeferred(cmd, *args, **kwargs)
                            total_moved += d

                            #: d should be the device must move in px
                            #: so wait a proportional amount of time for the device
                            #: to catch up. This avoids buffer errors from dumping
                            #: everything at once.

                            #: Since sending is way faster than cutting
                            #: we must delay (without blocking the UI) before
                            #: sending the next command or the device's buffer
                            #: quickly gets filled and crappy china piece cutters
                            #: get all jacked up. If the transport sends to a spooled
                            #: output (such as a printer) this can be set to 0
                            if rate > 0:
                                # log.debug("d={}, delay={} t={}".format(
                                #     d, delay, d/delay
                                # ))
                                yield async_sleep(d / rate)

                            #: TODO: Check if we need to update the ui
                            #: Set the job progress based on how far we've gone
                            if total_length > 0:
                                info.progress = int(
                                    max(
                                        0,
                                        min(100,
                                            100 * total_moved / total_length)))

                        if info.status != 'error':
                            #: We're done, send any finalization commands
                            yield defer.maybeDeferred(self.finish)

                        #: Write finalize command
                        if config.commands_after:
                            yield defer.maybeDeferred(connection.write,
                                                      config.commands_after)

                        #: Update stats
                        info.ended = datetime.now()

                        #: If not cancelled or errored
                        if info.status == 'running':
                            info.done = True
                            info.status = 'complete'
                    except Exception as e:
                        log.error(traceback.format_exc())
                        raise
                    finally:
                        if connection.connected:
                            yield defer.maybeDeferred(self.disconnect)

            #: Set the origin
            if job.feed_to_end and job.info.status == 'complete':
                self.origin = self.position

            #: If the user didn't cancel, set the origin and
            #: Process any jobs that entered the queue while this was running
            if self.queue and not job.info.cancelled:
                queue = self.queue[:]
                job = queue.pop(0)  #: Pull the first job off the queue
                log.info("Rescheduling {} from queue".format(job))
                self.queue = queue  #: Copy and reassign so the UI updates

                #: Call a minute later
                timed_call(60000, self.submit, job)
        except Exception as e:
            log.error(' device | Execution error {}'.format(
                traceback.format_exc()))
            raise
Exemple #37
0
 def _queue_update(self,change=None):
     change = change or {}
     self._update_count +=1
     timed_call(0,self._dequeue_update,change)
 def set_items(self, items):
     """ Defer until later so the view is only updated after all items
     are added. """
     self._pending_view_refreshes +=1
     timed_call(100,self._refresh_layout)
Exemple #39
0
 def update_display(self, change=None):
     self._update_count += 1
     #log.debug('update_display')
     timed_call(0, self._do_update)
Exemple #40
0
    def submit(self, job, test=False):
        """ Submit the job to the device. If the device is currently running
        a job it will be queued and run when this is finished.

        This handles iteration over the path model defined by the job and
        sending commands to the actual device using roughly the procedure is
        as follows:

                device.connect()

                model = device.init(job)
                for cmd in device.process(model):
                    device.handle(cmd)
                device.finish()

                device.disconnect()

        Subclasses provided by your own DeviceDriver may reimplement this
        to handle path interpolation however needed. The return value is
        ignored.

        The live plot view will update whenever the device.position object
        is updated. On devices with lower cpu/gpu capabilities this should
        be updated sparingly (ie the raspberry pi).

        Parameters
        -----------
            job: Instance of `inkcut.job.models.Job`
                The job to execute on the device
            test: bool
                Do a test run. This specifies whether the commands should be
                sent to the actual device or not. If True, the connection will
                be replaced with a virtual connection that captures all the
                command output.

        """
        log.debug("device | submit {}".format(job))
        try:

            #: Only allow one job at a time
            if self.busy:
                queue = self.queue[:]
                queue.append(job)
                self.queue = queue  #: Copy and reassign so the UI updates
                log.info("Job {} put in device queue".format(job))
                return

            with self.device_busy():
                #: Set the current the job
                self.job = job
                self.status = "Initializing job"

                #: Get the time to sleep based for each unit of movement
                config = self.config

                #: Rate px/ms
                if config.custom_rate >= 0:
                    rate = config.custom_rate
                elif self.connection.always_spools or config.spooled:
                    rate = 0
                elif config.interpolate:
                    if config.step_time > 0:
                        rate = config.step_size/float(config.step_time)
                    else:
                        rate = 0 # Undefined
                else:
                    rate = from_unit(
                        config.speed,  # in/s or cm/s
                        config.speed_units.split("/")[0])/1000.0

                # Device model is updated in real time
                model = yield defer.maybeDeferred(self.init, job)

                #: Local references are faster
                info = job.info

                #: Determine the length for tracking progress
                whole_path = QtGui.QPainterPath()

                #: Some versions of Qt seem to require a value in
                #: toSubpathPolygons
                m = QtGui.QTransform.fromScale(1, 1)
                for path in model.toSubpathPolygons(m):
                    for i, p in enumerate(path):
                        whole_path.lineTo(p)
                total_length = whole_path.length()
                total_moved = 0
                log.debug("device | Path length: {}".format(total_length))

                #: So a estimate of the duration can be determined
                info.length = total_length
                info.speed = rate*1000  #: Convert to px/s

                #: Waiting for approval
                info.status = 'waiting'

                #: If marked for auto approve start now
                if info.auto_approve:
                    info.status = 'approved'
                else:
                    #: Check for approval before starting
                    yield defer.maybeDeferred(info.request_approval)
                    if info.status != 'approved':
                        self.status = "Job cancelled"
                        return

                #: Update stats
                info.status = 'running'
                info.started = datetime.now()

                self.status = "Connecting to device"
                with self.device_connection(
                                test or config.test_mode) as connection:
                    self.status = "Processing job"
                    try:
                        yield defer.maybeDeferred(self.connect)

                        #: Write startup command
                        if config.commands_before:
                            yield defer.maybeDeferred(connection.write,
                                                      config.commands_before)

                        self.status = "Working..."

                        #: For point in the path
                        for (d, cmd, args, kwargs) in self.process(model):

                            #: Check if we paused
                            if info.paused:
                                self.status = "Job paused"
                                #: Sleep until resumed, cancelled, or the
                                #: connection drops
                                while (info.paused and not info.cancelled
                                       and connection.connected):
                                    yield async_sleep(300)  # ms

                            #: Check for cancel for non interpolated jobs
                            if info.cancelled:
                                self.status = "Job cancelled"
                                info.status = 'cancelled'
                                break
                            elif not connection.connected:
                                self.status = "connection error"
                                info.status = 'error'
                                break

                            #: Invoke the command
                            #: If you want to let the device handle more complex
                            #: commands such as curves do it in process and handle
                            yield defer.maybeDeferred(cmd, *args, **kwargs)
                            total_moved += d

                            #: d should be the device must move in px
                            #: so wait a proportional amount of time for the device
                            #: to catch up. This avoids buffer errors from dumping
                            #: everything at once.

                            #: Since sending is way faster than cutting
                            #: we must delay (without blocking the UI) before
                            #: sending the next command or the device's buffer
                            #: quickly gets filled and crappy china piece cutters
                            #: get all jacked up. If the transport sends to a spooled
                            #: output (such as a printer) this can be set to 0
                            if rate > 0:
                                # log.debug("d={}, delay={} t={}".format(
                                #     d, delay, d/delay
                                # ))
                                yield async_sleep(d/rate)

                            #: TODO: Check if we need to update the ui
                            #: Set the job progress based on how far we've gone
                            if total_length > 0:
                                info.progress = int(max(0, min(100,
                                                100*total_moved/total_length)))

                        if info.status != 'error':
                            #: We're done, send any finalization commands
                            yield defer.maybeDeferred(self.finish)

                        #: Write finalize command
                        if config.commands_after:
                            yield defer.maybeDeferred(connection.write,
                                                      config.commands_after)

                        #: Update stats
                        info.ended = datetime.now()

                        #: If not cancelled or errored
                        if info.status == 'running':
                            info.done = True
                            info.status = 'complete'
                    except Exception as e:
                        log.error(traceback.format_exc())
                        raise
                    finally:
                        if connection.connected:
                            yield defer.maybeDeferred(self.disconnect)

            #: Set the origin
            if job.feed_to_end and job.info.status == 'complete':
                self.origin = self.position

            #: If the user didn't cancel, set the origin and
            #: Process any jobs that entered the queue while this was running
            if self.queue and not job.info.cancelled:
                queue = self.queue[:]
                job = queue.pop(0)  #: Pull the first job off the queue
                log.info("Rescheduling {} from queue".format(job))
                self.queue = queue  #: Copy and reassign so the UI updates

                #: Call a minute later
                timed_call(60000, self.submit, job)
        except Exception as e:
            log.error(' device | Execution error {}'.format(
                traceback.format_exc()))
            raise
Exemple #41
0
 def _update_index(self):
     self.index = self._default_index()
     if self.delegate:
         self._refresh_count +=1
         timed_call(self._loading_interval,self._update_delegate)
Exemple #42
0
 def _update_index(self):
     self.index = self._default_index()
     if self.delegate:
         self._refresh_count +=1
         timed_call(self._loading_interval, self._update_delegate)
Exemple #43
0
def async_sleep(ms):
    d = Deferred()
    timed_call(ms, d.callback, True)
    return d
Exemple #44
0
 def update_display(self, change=None):
     self._update_count +=1
     #log.debug('update_display')
     timed_call(0,self._do_update)
Exemple #45
0
 def _observe_now(self, change):
     t = self.now
     self.year, self.month, self.day = t.year, t.month, t.day
     self.hour, self.minute, self.second = t.hour, t.minute, t.second
     if self.running:
         timed_call(1000, self.tick)