Example #1
0
    def add_relationship(self, type_, related_package, comment=u''):
        '''Creates a new relationship between this package and a
        related_package. It leaves the caller to commit the change.'''
        import package_relationship
        from ckan import model
        if type_ in package_relationship.PackageRelationship.get_forward_types():
            subject = self
            object_ = related_package
        elif type_ in package_relationship.PackageRelationship.get_reverse_types():
            type_ = package_relationship.PackageRelationship.reverse_to_forward_type(type_)
            assert type_
            subject = related_package
            object_ = self
        else:
            raise KeyError, 'Package relationship type: %r' % type_

        rels = self.get_relationships(with_package=related_package,
                                      type=type_, active=False, direction="forward")
        if rels:
            rel = rels[0]
            if comment:
                rel.comment=comment
            if rel.state == model.State.DELETED:
                rel.undelete()
        else:
            rel = package_relationship.PackageRelationship(
                subject=subject,
                object=object_,
                type=type_,
                comment=comment)
        Session.add(rel)
        return rel
Example #2
0
def install():
    Base.metadata.create_all(Session().bind)

    data = [
        ("Chicago", "United States", ("60601", "60602", "60603", "60604")),
        ("Montreal", "Canada", ("H2S 3K9", "H2B 1V4", "H7G 2T8")),
        ("Edmonton", "Canada", ("T5J 1R9", "T5J 1Z4", "T5H 1P6")),
        ("New York", "United States", ("10001", "10002", "10003", "10004", "10005", "10006")),
        ("San Francisco", "United States", ("94102", "94103", "94104", "94105", "94107", "94108")),
    ]

    countries = {}
    all_post_codes = []
    for city, country, postcodes in data:
        try:
            country = countries[country]
        except KeyError:
            countries[country] = country = Country(country)

        city = City(city, country)
        pc = [PostalCode(code, city) for code in postcodes]
        Session.add_all(pc)
        all_post_codes.extend(pc)

    for i in xrange(1, 51):
        person = Person(
            "person %.2d" % i,
            Address(street="street %.2d" % i, postal_code=all_post_codes[random.randint(0, len(all_post_codes) - 1)]),
        )
        Session.add(person)

    Session.commit()

    # start the demo fresh
    Session.remove()
Example #3
0
    def add_relationship(self, type_, related_package, comment=u''):
        '''Creates a new relationship between this package and a
        related_package. It leaves the caller to commit the change.'''
        import package_relationship
        from ckan import model
        if type_ in package_relationship.PackageRelationship.get_forward_types():
            subject = self
            object_ = related_package
        elif type_ in package_relationship.PackageRelationship.get_reverse_types():
            type_ = package_relationship.PackageRelationship.reverse_to_forward_type(type_)
            assert type_
            subject = related_package
            object_ = self
        else:
            raise KeyError, 'Package relationship type: %r' % type_

        rels = self.get_relationships(with_package=related_package,
                                      type=type_, active=False, direction="forward")
        if rels:
            rel = rels[0]
            if comment:
                rel.comment=comment
            if rel.state == model.State.DELETED:
                rel.undelete()
        else:
            rel = package_relationship.PackageRelationship(
                subject=subject,
                object=object_,
                type=type_,
                comment=comment)
        Session.add(rel)
        return rel
Example #4
0
 def init_configuration_data(self):
     '''Default configuration, for when CKAN is first used out of the box.
     This state may be subsequently configured by the user.'''
     init_authz_configuration_data()
     if meta.Session.query(Revision).count() == 0:
         rev = Revision()
         rev.author = 'system'
         rev.message = u'Initialising the Repository'
         Session.add(rev)
     self.commit_and_remove()
Example #5
0
 def init_configuration_data(self):
     '''Default configuration, for when CKAN is first used out of the box.
     This state may be subsequently configured by the user.'''
     init_authz_configuration_data()
     if meta.Session.query(Revision).count() == 0:
         rev = Revision()
         rev.author = 'system'
         rev.message = u'Initialising the Repository'
         Session.add(rev)
     self.commit_and_remove()
def install():
    Base.metadata.create_all(Session().bind)

    data = [('Chicago', 'United States', ('60601', '60602', '60603', '60604')),
            ('Montreal', 'Canada', ('H2S 3K9', 'H2B 1V4', 'H7G 2T8')),
            ('Edmonton', 'Canada', ('T5J 1R9', 'T5J 1Z4', 'T5H 1P6')),
            ('New York', 'United States', ('10001', '10002', '10003', '10004',
                                           '10005', '10006')),
            ('San Francisco', 'United States', ('94102', '94103', '94104',
                                                '94105', '94107', '94108'))]

    countries = {}
    all_post_codes = []
    for city, country, postcodes in data:
        try:
            country = countries[country]
        except KeyError:
            countries[country] = country = Country(country)

        city = City(city, country)
        pc = [PostalCode(code, city) for code in postcodes]
        Session.add_all(pc)
        all_post_codes.extend(pc)

    for i in xrange(1, 51):
        person = Person(
            "person %.2d" % i,
            Address(street="street %.2d" % i,
                    postal_code=all_post_codes[random.randint(
                        0,
                        len(all_post_codes) - 1)]))
        Session.add(person)

    Session.commit()

    # start the demo fresh
    Session.remove()
Example #7
0
    links = [a for a in rhscol.getiterator("a")]
    if len(links) != 3 or "Older" not in links[1].text or "Newer" not in links[2].text:
        print "Cant find older and newer links here, backing up"
        oldurl = page.url
        match = re.search("mbl_hs:(\d+),mbl_he:(\d+),mbl_rs:(\d+),mbl_re:(\d+)", oldurl)
        mbl_hs = int(match.group(1)) + 600
        mbl_he = int(match.group(2)) + 600
        mbl_rs = int(match.group(3)) + 600
        mbl_re = int(match.group(4)) + 600
        url = oldurl.replace(
            match.group(0),
            "mbl_hs:" + str(mbl_hs) + ",mbl_he:" + str(mbl_he) + ",mbl_rs:" + str(mbl_rs) + ",mbl_re:" + str(mbl_re),
        )
        lasturl = oldurl
        time.sleep(10)
        continue
    olderurl = u"http://www.google.com" + links[1].attrib["href"]
    newerurl = u"http://www.google.com" + links[2].attrib["href"]
    page = Page(url, html, numresults, olderurl, newerurl)
    Session.add(page)
    Session.commit()
    lasturl = url
    url = newerurl
    for rtdm in CSSSelector("span.rtdm")(doc):
        td, date = [text for text in rtdm.itertext()]
        day = datetime.strptime(date, "%b %d, %Y")
        if day > endtime:
            print "Quitting, " + str(day) + " > " + str(endtime)
            exit()
    time.sleep(10)
Example #8
0
class Inkcut(Application):
    """
    Inkcut application, creates inkcut.ui and controls job, material, 
    and device interaction.
    """
    
    def __init__(self):
        """Load initial application settings from database """
        Application.__init__(self)
        
        # setup the database session
        database = 'sqlite:///%s'%os.path.join(APP_DIR,config.get('Inkcut','database_dir'),config.get('Inkcut','database_name'))
        log.info("Database: %s"%database)
        engine = create_engine(database)
        Session.configure(bind=engine)
        self.session = Session()
        self.job = None
        self._flags = {'block_callbacks':True}
    
    # Builds the Inkcut user interface when Inkcut.run() is called
    def run(self, filename=None):
        builder = Gtk.Builder()
        builder.add_from_file(os.path.join(APP_DIR,'ui','inkcut.ui'))
        window = builder.get_object('inkcut')
            
        # Save any widgets needed later into groups
        self.add_widgets(builder,'job-dependent',['toolbutton3','toolbutton5','toolbutton6','box21','box9','box11','box3','box15','box25','box28','plot-order','box17','menu-file-print-preview','menu-file-print','menu-edit-undo','menu-edit-redo','gtk-zoom-fit','gtk-zoom-in','gtk-zoom-out','menu-file-save-as','menu-file-save'])
        self.add_widgets(builder,'inkcut',['inkcut','devices','statusbar','preview','scale-lock-box','scale-x-label','spinner'])
        self.add_widgets(builder,'graphic-properties',['graphic-width','graphic-height','graphic-scale-x','graphic-scale-y','graphic-scale-lock','graphic-rotation','graphic-rotate-to-save','graphic-weedline-enable','graphic-weedline-padding'])
        self.add_widgets(builder,'plot-properties',['plot-width','plot-height','plot-copies','plot-weedline-enable','plot-weedline-padding','plot-col-spacing','plot-row-spacing','plot-position-x','plot-position-y','plot-feed','plot-feed-distance'])
        self.add_widgets(builder,'material',['materials'])
        
        
        # Connect signals and invoke any UI setup
        builder.connect_signals(self)

        model = ['0 Degrees Clockwise','90 Degrees Clockwise','180 Degrees Clockwise','270 Degrees Clockwise']
        combobox = builder.get_object('graphic-rotation')
        self.set_model_from_list(combobox,model)
        combobox.set_active(0)

        model = ['One Copy at a Time','Best Tracking','Shortest Path']
        combobox = builder.get_object('plot-order')
        self.set_model_from_list(combobox,model)
        combobox.set_active(0)

        # Based on SQL Table: id, name, cost, width, length, margin_top, margin_right, margin_bottom, margin_left, velocity, force, color
        active = 0
        materials = Gtk.ListStore(int,str)
        for m in self.session.query(Material).all():
            materials.append([m.id,m.name])
            if m.id == int(config.get('Inkcut','default_device')):
                active = len(materials)
        combobox = self.get_widget('material','materials')
        combobox.set_model(materials)
        cell = Gtk.CellRendererText()
        combobox.pack_start(cell, True)
        combobox.add_attribute(cell, 'text', 1)  
        combobox.set_active(active)

        
        model = []
        device_active_index = 0
        for device in Device.get_printers():
            name = device.name
            if device.id == int(config.get('Inkcut','default_device')):
                name += " (default)"
                device_active_index = len(model)
            model.append(name)
            log.info(name) 
        combobox = builder.get_object('devices')
        self.set_model_from_list(combobox,model)
        combobox.set_active(device_active_index)
        
        
        
        # Init Accelerators
        accel_group = builder.get_object('accelgroup1')
        for action in builder.get_object('actiongroup1').list_actions():
            action.set_accel_group(accel_group)
            action.connect_accelerator()
        window.add_accel_group(accel_group)

        # Show the widgets
        self._update_sensitivity()
        window.show_all()
        self.flash("",indicator=False)
        
        # Fix!
        self._flags['block_callbacks']=False
        self.add_window(window,'inkcut')
        self.on_graphic_scale_lock_toggled(self.get_widget('graphic-properties','graphic-scale-lock'))
        # From command line arguments
        if filename is not None and os.path.isfile(filename):
            self.create_job(filename)
            
        Gtk.main()

    # ===================================== Plot Callbacks ===============================================
    @callback
    def on_plot_feed_distance_changed(self,radio,data=None):
        self.flash("Saving the plot feeding settings...",indicator=True)
        feed = self.get_widget('plot-properties','plot-feed').get_active()
        if feed:
            d = self.unit_to(self.get_widget('plot-properties','plot-feed-distance').get_value())
            pos = (0,d)
            if self.job.plot.get_rotation() == 90:
                pos = (d,0) 
            self.job.set_property('plot','finish_position',pos)
        else:
            self.job.set_property('plot','finish_position',(0,0))
        GObject.timeout_add(1000,self.flash,"")

    @callback
    def on_plot_copies_changed(self,adjustment,data=None):
        """Set's the plot's copies to the adjustment value. """
        n = int(adjustment.get_value())
        self.flash("Setting the number of copies to %s..."%n,indicator=True)
        GObject.idle_add(self.job.plot.set_copies,n)
        GObject.idle_add(self._update_preview)
        
    @callback
    def on_stack_reset_activated(self,button, data=None):
        """Sets the graphic-copies to 1"""
        self.get_widget('plot-properties','plot-copies').set_value(1)
        # Preview updated by on_plot_copies_changed

    @callback
    def on_stack_add_activated(self,button, data=None):
        """Adds a full stack of copies"""
        stack = self.job.plot.get_stack_size_x()
        copies = self.job.plot.get_copies()
        self.get_widget('plot-properties','plot-copies').set_value(stack*(copies/stack+1))
        # Preview updated by on_plot_copies_changed

    @callback
    def on_plot_spacing_x_changed(self,adjustment,data=None):
        x = self.unit_to(adjustment.get_value())
        if self.get_widget('plot-properties','plot-copies').get_value() > 1:
            msg = "Updating the column spacing..."
        else:
            msg = "Saving the plot column spacing..."
        self.flash(msg,indicator=True)
        GObject.idle_add(self.job.plot.set_spacing,x,None)
        GObject.idle_add(self._update_preview)

    @callback
    def on_plot_spacing_y_changed(self,adjustment,data=None):
        y = self.unit_to(adjustment.get_value())
        if self.get_widget('plot-properties','plot-copies').get_value() > 1:
            msg = "Updating the row spacing..."
        else:
            msg = "Saving the plot row spacing..."
        self.flash(msg,indicator=True)
        GObject.idle_add(self.job.plot.set_spacing,None,y)
        GObject.idle_add(self._update_preview)        

    @callback
    def on_plot_position_x_changed(self,widget,data=None):
        x = self.unit_to(widget.get_value())
        pos = self.job.plot.get_position()
        self.flash("Moving the plot to (%s,%s)"%(x,pos[1]),indicator=True)
        GObject.idle_add(self.job.plot.set_position,x,pos[1])
        GObject.idle_add(self._update_preview)

    @callback
    def on_plot_position_y_changed(self,widget,data=None):
        y = self.unit_to(widget.get_value())
        pos = self.job.plot.get_position()
        self.flash("Moving the plot to (%s,%s)"%(pos[0],y),indicator=True)
        GObject.idle_add(self.job.plot.set_position,pos[0],y)
        GObject.idle_add(self._update_preview)

    @callback
    def on_plot_center_x_toggled(self,checkbox,data=None):
        enabled = checkbox.get_active()
        if enabled:
            msg = "Centering the plot horizontally..."
        else:
            msg = "Moving the plot to the horizontal start..."
        self.flash(msg,indicator=True)
        GObject.idle_add(self.job.plot.set_align_center_x,enabled)
        GObject.idle_add(self._update_plot_ui)

    @callback
    def on_plot_center_y_toggled(self,checkbox,data=None):
        enabled = checkbox.get_active()
        if enabled:
            msg = "Centering the plot vertically..."
        else:
            msg = "Moving the plot to the vertical start..."
        self.flash(msg,indicator=True)
        GObject.idle_add(self.job.plot.set_align_center_y,enabled)
        GObject.idle_add(self._update_plot_ui)

    @callback
    def on_plot_weedline_toggled(self,checkbox,data=None):
        enabled = checkbox.get_active()
        if enabled:
            msg = "Adding a weedline to the plot..."
        else:
            msg = "Removing the plot weedline..."
        self.flash(msg,indicator=True)
        GObject.idle_add(self.job.plot.set_weedline,enabled)
        GObject.idle_add(self._update_preview)

    @callback
    def on_plot_weedline_padding_changed(self,adjustment,data=None):
        if self.get_widget('plot-properties','plot-weedline-enable').get_active():
            msg = "Updating the plot weedline padding..."
        else:
            msg = "Saving the plot weedline padding..."
        self.flash(msg,indicator=True)
        GObject.idle_add(self.job.plot.set_weedline_padding,self.unit_to(adjustment.get_value()))
        GObject.idle_add(self._update_preview)
    
    # ===================================== Graphic Callbacks ===============================================
    @callback
    def on_graphic_width_changed(self,adjustment,data=None):
        # Calculate new scale
        cur_w = self.job.plot.graphic.get_width()
        new_w = float(self.unit_to(adjustment.get_value()))
        sx,sy = self.job.plot.graphic.get_scale()
        sx = new_w/cur_w*sx
        # Updated in on_graphic_scale_x_changed callback
        self.get_widget('graphic-properties','graphic-scale-x').set_value(sx)
        
    @callback
    def on_graphic_height_changed(self,adjustment,data=None):
        # Calculate new scale
        cur = self.job.plot.graphic.get_height()
        new = float(self.unit_to(adjustment.get_value()))
        sx,sy = self.job.plot.graphic.get_scale()
        s = new/cur*sy
        # Updated in on_graphic_scale_x_changed callback
        self.get_widget('graphic-properties','graphic-scale-y').set_value(s)

    @callback
    def on_graphic_scale_y_changed(self,adjustment,data=None):
        sy = adjustment.get_value()
        if self.get_widget('graphic-properties','graphic-scale-lock').get_active():
            sx = sy
        else:
            sx = self.get_widget('graphic-properties','graphic-scale-x').get_value()
        GObject.idle_add(self.job.plot.graphic.set_scale,sx,sy)
        GObject.idle_add(self._update_ui)
        
    @callback
    def on_graphic_scale_x_changed(self,adjustment,data=None):
        sx = adjustment.get_value()
        if self.get_widget('graphic-properties','graphic-scale-lock').get_active():
            sy = sx
        else:
            sy = self.get_widget('graphic-properties','graphic-scale-y').get_value()
        GObject.idle_add(self.job.plot.graphic.set_scale,sx,sy)
        GObject.idle_add(self._update_ui)

    @callback
    def on_graphic_rotate_to_save_toggled(self,checkbox,data=None):
        self.flash("Checking and updating...",indicator=True)
        GObject.idle_add(self.job.plot.set_auto_rotate,checkbox.get_active())
        GObject.idle_add(self._update_preview)
        
    @callback
    def on_graphic_weedline_padding_changed(self,adjustment,data=None):
        if self.get_widget('graphic-properties','graphic-weedline-enable').get_active():
            msg = "Updating the graphic weedline padding..."
        else:
            msg = "Saving the graphic weedline padding..."
        self.flash(msg,indicator=True)
        GObject.idle_add(self.job.plot.graphic.set_weedline_padding,self.unit_to(adjustment.get_value()))
        GObject.idle_add(self._update_graphic_ui)
        
    @callback
    def on_graphic_weedline_toggled(self,checkbox,data=None):
        enabled = checkbox.get_active()
        if enabled:
            msg = "Adding a weedline to the graphic..."
        else:
            msg = "Removing the graphic weedline..."
        self.flash(msg,indicator=True)
        GObject.idle_add(self.job.plot.graphic.set_weedline,enabled)
        GObject.idle_add(self._update_preview)
        
    @callback
    def on_graphic_mirror_x_toggled(self,checkbox,data=None):
        enabled = checkbox.get_active()
        if enabled:
            msg = "Mirroring graphic about the y-axis..."
        else:
            msg = "Returning graphic to original mirror state..."
        self.flash(msg,indicator=True)
        GObject.idle_add(self.job.plot.graphic.set_mirror_x,enabled)
        GObject.idle_add(self._update_preview)

    @callback
    def on_graphic_mirror_y_toggled(self,checkbox,data=None):
        enabled = checkbox.get_active()
        if enabled:
            msg = "Mirroring graphic about the x-axis..."
        else:
            msg = "Returning graphic to original mirror state..."
        self.flash(msg,indicator=True)
        GObject.idle_add(self.job.plot.graphic.set_mirror_y,enabled)
        GObject.idle_add(self._update_preview)
        
    @callback
    def on_graphic_scale_lock_toggled(self,checkbox,data=None):
        if checkbox.get_active():
            self.get_widget('inkcut','scale-x-label').set_text("Scale:")
            self.get_widget('inkcut','scale-lock-box').hide()
            if self.job is not None:
                s = self.get_widget('graphic-properties','graphic-scale-x').get_value()
                self.get_widget('graphic-properties','graphic-scale-y').set_value(s)
        else:
            self.get_widget('inkcut','scale-x-label').set_text("Scale - X:")
            self.get_widget('inkcut','scale-lock-box').show()

    @callback
    def on_graphic_rotation_changed(self, combobox, data=None):
        degrees = combobox.get_active()*90
        self.flash("Setting graphic rotation to %s..."%degrees,indicator=True)
        GObject.idle_add(self.job.plot.graphic.set_rotation,degrees)
        GObject.idle_add(self._update_graphic_ui)
    
    
    # ===================================== File Menu Callbacks ===============================================
    @callback
    def on_job_review_activated(self,action,data=None):
        self.job.update_properties()
        builder = Gtk.Builder()
        builder.add_from_file(os.path.join(APP_DIR,'ui','plot.ui'))
        dialog = builder.get_object('dialog1')
        builder.connect_signals(self)
        dialog.show_all()
        dialog.run()
        dialog.destroy()

    @callback
    def on_job_submit_activated(self,action,data=None):
        self.job.update_properties()
        GObject.idle_add(self.run_export_plugin)

    def run_export_plugin(self):
        # Write the job to a file
        tmp = tempfile.NamedTemporaryFile(suffix=".svg",delete=False)
        tmp.file.write(self.job.plot.get_xml())
        svg = tmp.name
        tmp.close()

        # Get the current device
        name = self.get_combobox_active_text(self.get_widget('inkcut','devices'))
        #device = self.session.query(Device).filter(Device.name==name).first()
        device = Device.get_printer_by_name(name)
        log.info(device)
        # Init the export plugin
        # TODO: Gather plugins here.... let user select...
        plugins = [HPGL.Import(),HPGL.Export()]
        plugin_found = False
        for plugin in plugins:
            if plugin.mode.lower() == "export":
                if str(device.command_language.lower()) in plugin.filetypes:
                    plugin_found = True
                    break
        if plugin_found == False:
            msg = Gtk.MessageDialog(type=Gtk.MessageType.ERROR,
                buttons=Gtk.ButtonsType.OK,
                message_format="No plugins found for the command language:%s."%device.command_language)
            msg.format_secondary_text("Please make sure the plugins for this device are installed.\n If the problem persists, contact the developer.")
            msg.run()
            msg.destroy()
            raise Exception("Error, no plugin found for that command language...")

        # Initialize the plugin then run it
        # TODO: put everything needed here...
        plugin.export_init(plot=self.job.get_properties('plot'),
            device={
                'cutting_overlap':(10,False)
                })
        plugin.input = svg
        plugin.run()
        device.submit(plugin.output)

        # Cleanup
        os.remove(svg)
    
    def on_file_save_action_activated(self,widget,data=None):
        self.flash("Saving %s into the Job database..."%(self.job.name),indicator=True)
        self.job.update_properties()
        self.get_window('inkcut').set_title("%s - Inkcut"%self.job.name)
        self.session.commit()
        GObject.timeout_add(1000,self.flash,"")
        
    def create_job(self,filename,**kwargs):
        """Create a job and try to set the source. Returns bool success."""
        job = Job(**kwargs)
        # Get the default material
        job.material = self.get_material()
        try:
            job.set_source(filename)
            self.job = job
            self.session.add(self.job)
            msg = 'Loaded %s'%os.path.basename(job.name or 'File')
            self.get_window('inkcut').set_title("*%s - Inkcut"%job.name)
            self.flash(msg)
            self.on_plot_feed_distance_changed(self.get_widget('plot-properties','plot-feed'))
            self._update_ui()
            return False
        except Exception, err:
            # update the ui with job info
            log.debug(traceback.format_exc())
            msg = Gtk.MessageDialog(type=Gtk.MessageType.ERROR,
                buttons=Gtk.ButtonsType.OK,
                message_format="Issue loading file")
            msg.format_secondary_text(err)
            msg.run()
            msg.destroy()
            return False
        except:
Example #9
0
 def create(cls, id):
     f = Foo(id=id)
     Session.add(f)
     Session.commit()
     return f
Example #10
0
from tweet import Tweet
from meta import Session

numdupes = 0
for page in Session.query(Page).order_by(Page.id):
    doc = lxml.document_fromstring(page.html)
    rtr = CSSSelector('ol#rtr')(doc)
    if not rtr:
        continue
    for tweet in rtr[0].getchildren():
        twitterlink = CSSSelector('span.a')(tweet)
        rtdelta = int(CSSSelector('div.rtdelta')(tweet)[0].text)
        assert len(twitterlink) == 1 and twitterlink[0].text == 'Twitter'
        toclear = []
        c = twitterlink[0]
        while c is not None:
            toclear.append(c)
            c = c.getnext()
        for c in toclear:
            c.clear()
        text = lxml.tostring(tweet, encoding=unicode, method='text')
        when = page.hit - timedelta(seconds=rtdelta)
        t = Tweet(text, when)
        if Session.query(Tweet).filter(Tweet.md5==t.md5).first() is None:
            Session.add(t)
        else:
            numdupes = numdupes + 1
    
Session.commit()
print 'committed, there were ' + str(numdupes) + ' dupes'
Example #11
0
class Inkcut(Application):
    """
    Inkcut application, creates inkcut.ui and controls job, material, 
    and device interaction.
    """
    def __init__(self):
        """Load initial application settings from database """
        Application.__init__(self)

        # setup the database session
        database = 'sqlite:///%s' % os.path.join(
            APP_DIR, config.get('Inkcut', 'database_dir'),
            config.get('Inkcut', 'database_name'))
        log.info("Database: %s" % database)
        engine = create_engine(database)
        Session.configure(bind=engine)
        self.session = Session()
        self.job = None
        self._flags = {'block_callbacks': True}

    # Builds the Inkcut user interface when Inkcut.run() is called
    def run(self, filename=None):
        builder = Gtk.Builder()
        builder.add_from_file(os.path.join(APP_DIR, 'ui', 'inkcut.ui'))
        window = builder.get_object('inkcut')

        # Save any widgets needed later into groups
        self.add_widgets(builder, 'job-dependent', [
            'toolbutton3', 'toolbutton5', 'toolbutton6', 'box21', 'box9',
            'box11', 'box3', 'box15', 'box25', 'box28', 'plot-order', 'box17',
            'menu-file-print-preview', 'menu-file-print', 'menu-edit-undo',
            'menu-edit-redo', 'gtk-zoom-fit', 'gtk-zoom-in', 'gtk-zoom-out',
            'menu-file-save-as', 'menu-file-save'
        ])
        self.add_widgets(builder, 'inkcut', [
            'inkcut', 'devices', 'statusbar', 'preview', 'scale-lock-box',
            'scale-x-label', 'spinner'
        ])
        self.add_widgets(builder, 'graphic-properties', [
            'graphic-width', 'graphic-height', 'graphic-scale-x',
            'graphic-scale-y', 'graphic-scale-lock', 'graphic-rotation',
            'graphic-rotate-to-save', 'graphic-weedline-enable',
            'graphic-weedline-padding'
        ])
        self.add_widgets(builder, 'plot-properties', [
            'plot-width', 'plot-height', 'plot-copies', 'plot-weedline-enable',
            'plot-weedline-padding', 'plot-col-spacing', 'plot-row-spacing',
            'plot-position-x', 'plot-position-y', 'plot-feed',
            'plot-feed-distance'
        ])
        self.add_widgets(builder, 'material', ['materials'])

        # Connect signals and invoke any UI setup
        builder.connect_signals(self)

        model = [
            '0 Degrees Clockwise', '90 Degrees Clockwise',
            '180 Degrees Clockwise', '270 Degrees Clockwise'
        ]
        combobox = builder.get_object('graphic-rotation')
        self.set_model_from_list(combobox, model)
        combobox.set_active(0)

        model = ['One Copy at a Time', 'Best Tracking', 'Shortest Path']
        combobox = builder.get_object('plot-order')
        self.set_model_from_list(combobox, model)
        combobox.set_active(0)

        # Based on SQL Table: id, name, cost, width, length, margin_top, margin_right, margin_bottom, margin_left, velocity, force, color
        active = 0
        materials = Gtk.ListStore(int, str)
        for m in self.session.query(Material).all():
            materials.append([m.id, m.name])
            if m.id == int(config.get('Inkcut', 'default_device')):
                active = len(materials)
        combobox = self.get_widget('material', 'materials')
        combobox.set_model(materials)
        cell = Gtk.CellRendererText()
        combobox.pack_start(cell, True)
        combobox.add_attribute(cell, 'text', 1)
        combobox.set_active(active)

        model = []
        device_active_index = 0
        for device in Device.get_printers():
            name = device.name
            if device.id == int(config.get('Inkcut', 'default_device')):
                name += " (default)"
                device_active_index = len(model)
            model.append(name)
            log.info(name)
        combobox = builder.get_object('devices')
        self.set_model_from_list(combobox, model)
        combobox.set_active(device_active_index)

        # Init Accelerators
        accel_group = builder.get_object('accelgroup1')
        for action in builder.get_object('actiongroup1').list_actions():
            action.set_accel_group(accel_group)
            action.connect_accelerator()
        window.add_accel_group(accel_group)

        # Show the widgets
        self._update_sensitivity()
        window.show_all()
        self.flash("", indicator=False)

        # Fix!
        self._flags['block_callbacks'] = False
        self.add_window(window, 'inkcut')
        self.on_graphic_scale_lock_toggled(
            self.get_widget('graphic-properties', 'graphic-scale-lock'))
        # From command line arguments
        if filename is not None and os.path.isfile(filename):
            self.create_job(filename)

        Gtk.main()

    # ===================================== Plot Callbacks ===============================================
    @callback
    def on_plot_feed_distance_changed(self, radio, data=None):
        self.flash("Saving the plot feeding settings...", indicator=True)
        feed = self.get_widget('plot-properties', 'plot-feed').get_active()
        if feed:
            d = self.unit_to(
                self.get_widget('plot-properties',
                                'plot-feed-distance').get_value())
            pos = (0, d)
            if self.job.plot.get_rotation() == 90:
                pos = (d, 0)
            self.job.set_property('plot', 'finish_position', pos)
        else:
            self.job.set_property('plot', 'finish_position', (0, 0))
        GObject.timeout_add(1000, self.flash, "")

    @callback
    def on_plot_copies_changed(self, adjustment, data=None):
        """Set's the plot's copies to the adjustment value. """
        n = int(adjustment.get_value())
        self.flash("Setting the number of copies to %s..." % n, indicator=True)
        GObject.idle_add(self.job.plot.set_copies, n)
        GObject.idle_add(self._update_preview)

    @callback
    def on_stack_reset_activated(self, button, data=None):
        """Sets the graphic-copies to 1"""
        self.get_widget('plot-properties', 'plot-copies').set_value(1)
        # Preview updated by on_plot_copies_changed

    @callback
    def on_stack_add_activated(self, button, data=None):
        """Adds a full stack of copies"""
        stack = self.job.plot.get_stack_size_x()
        copies = self.job.plot.get_copies()
        self.get_widget('plot-properties',
                        'plot-copies').set_value(stack * (copies / stack + 1))
        # Preview updated by on_plot_copies_changed

    @callback
    def on_plot_spacing_x_changed(self, adjustment, data=None):
        x = self.unit_to(adjustment.get_value())
        if self.get_widget('plot-properties', 'plot-copies').get_value() > 1:
            msg = "Updating the column spacing..."
        else:
            msg = "Saving the plot column spacing..."
        self.flash(msg, indicator=True)
        GObject.idle_add(self.job.plot.set_spacing, x, None)
        GObject.idle_add(self._update_preview)

    @callback
    def on_plot_spacing_y_changed(self, adjustment, data=None):
        y = self.unit_to(adjustment.get_value())
        if self.get_widget('plot-properties', 'plot-copies').get_value() > 1:
            msg = "Updating the row spacing..."
        else:
            msg = "Saving the plot row spacing..."
        self.flash(msg, indicator=True)
        GObject.idle_add(self.job.plot.set_spacing, None, y)
        GObject.idle_add(self._update_preview)

    @callback
    def on_plot_position_x_changed(self, widget, data=None):
        x = self.unit_to(widget.get_value())
        pos = self.job.plot.get_position()
        self.flash("Moving the plot to (%s,%s)" % (x, pos[1]), indicator=True)
        GObject.idle_add(self.job.plot.set_position, x, pos[1])
        GObject.idle_add(self._update_preview)

    @callback
    def on_plot_position_y_changed(self, widget, data=None):
        y = self.unit_to(widget.get_value())
        pos = self.job.plot.get_position()
        self.flash("Moving the plot to (%s,%s)" % (pos[0], y), indicator=True)
        GObject.idle_add(self.job.plot.set_position, pos[0], y)
        GObject.idle_add(self._update_preview)

    @callback
    def on_plot_center_x_toggled(self, checkbox, data=None):
        enabled = checkbox.get_active()
        if enabled:
            msg = "Centering the plot horizontally..."
        else:
            msg = "Moving the plot to the horizontal start..."
        self.flash(msg, indicator=True)
        GObject.idle_add(self.job.plot.set_align_center_x, enabled)
        GObject.idle_add(self._update_plot_ui)

    @callback
    def on_plot_center_y_toggled(self, checkbox, data=None):
        enabled = checkbox.get_active()
        if enabled:
            msg = "Centering the plot vertically..."
        else:
            msg = "Moving the plot to the vertical start..."
        self.flash(msg, indicator=True)
        GObject.idle_add(self.job.plot.set_align_center_y, enabled)
        GObject.idle_add(self._update_plot_ui)

    @callback
    def on_plot_weedline_toggled(self, checkbox, data=None):
        enabled = checkbox.get_active()
        if enabled:
            msg = "Adding a weedline to the plot..."
        else:
            msg = "Removing the plot weedline..."
        self.flash(msg, indicator=True)
        GObject.idle_add(self.job.plot.set_weedline, enabled)
        GObject.idle_add(self._update_preview)

    @callback
    def on_plot_weedline_padding_changed(self, adjustment, data=None):
        if self.get_widget('plot-properties',
                           'plot-weedline-enable').get_active():
            msg = "Updating the plot weedline padding..."
        else:
            msg = "Saving the plot weedline padding..."
        self.flash(msg, indicator=True)
        GObject.idle_add(self.job.plot.set_weedline_padding,
                         self.unit_to(adjustment.get_value()))
        GObject.idle_add(self._update_preview)

    # ===================================== Graphic Callbacks ===============================================
    @callback
    def on_graphic_width_changed(self, adjustment, data=None):
        # Calculate new scale
        cur_w = self.job.plot.graphic.get_width()
        new_w = float(self.unit_to(adjustment.get_value()))
        sx, sy = self.job.plot.graphic.get_scale()
        sx = new_w / cur_w * sx
        # Updated in on_graphic_scale_x_changed callback
        self.get_widget('graphic-properties', 'graphic-scale-x').set_value(sx)

    @callback
    def on_graphic_height_changed(self, adjustment, data=None):
        # Calculate new scale
        cur = self.job.plot.graphic.get_height()
        new = float(self.unit_to(adjustment.get_value()))
        sx, sy = self.job.plot.graphic.get_scale()
        s = new / cur * sy
        # Updated in on_graphic_scale_x_changed callback
        self.get_widget('graphic-properties', 'graphic-scale-y').set_value(s)

    @callback
    def on_graphic_scale_y_changed(self, adjustment, data=None):
        sy = adjustment.get_value()
        if self.get_widget('graphic-properties',
                           'graphic-scale-lock').get_active():
            sx = sy
        else:
            sx = self.get_widget('graphic-properties',
                                 'graphic-scale-x').get_value()
        GObject.idle_add(self.job.plot.graphic.set_scale, sx, sy)
        GObject.idle_add(self._update_ui)

    @callback
    def on_graphic_scale_x_changed(self, adjustment, data=None):
        sx = adjustment.get_value()
        if self.get_widget('graphic-properties',
                           'graphic-scale-lock').get_active():
            sy = sx
        else:
            sy = self.get_widget('graphic-properties',
                                 'graphic-scale-y').get_value()
        GObject.idle_add(self.job.plot.graphic.set_scale, sx, sy)
        GObject.idle_add(self._update_ui)

    @callback
    def on_graphic_rotate_to_save_toggled(self, checkbox, data=None):
        self.flash("Checking and updating...", indicator=True)
        GObject.idle_add(self.job.plot.set_auto_rotate, checkbox.get_active())
        GObject.idle_add(self._update_preview)

    @callback
    def on_graphic_weedline_padding_changed(self, adjustment, data=None):
        if self.get_widget('graphic-properties',
                           'graphic-weedline-enable').get_active():
            msg = "Updating the graphic weedline padding..."
        else:
            msg = "Saving the graphic weedline padding..."
        self.flash(msg, indicator=True)
        GObject.idle_add(self.job.plot.graphic.set_weedline_padding,
                         self.unit_to(adjustment.get_value()))
        GObject.idle_add(self._update_graphic_ui)

    @callback
    def on_graphic_weedline_toggled(self, checkbox, data=None):
        enabled = checkbox.get_active()
        if enabled:
            msg = "Adding a weedline to the graphic..."
        else:
            msg = "Removing the graphic weedline..."
        self.flash(msg, indicator=True)
        GObject.idle_add(self.job.plot.graphic.set_weedline, enabled)
        GObject.idle_add(self._update_preview)

    @callback
    def on_graphic_mirror_x_toggled(self, checkbox, data=None):
        enabled = checkbox.get_active()
        if enabled:
            msg = "Mirroring graphic about the y-axis..."
        else:
            msg = "Returning graphic to original mirror state..."
        self.flash(msg, indicator=True)
        GObject.idle_add(self.job.plot.graphic.set_mirror_x, enabled)
        GObject.idle_add(self._update_preview)

    @callback
    def on_graphic_mirror_y_toggled(self, checkbox, data=None):
        enabled = checkbox.get_active()
        if enabled:
            msg = "Mirroring graphic about the x-axis..."
        else:
            msg = "Returning graphic to original mirror state..."
        self.flash(msg, indicator=True)
        GObject.idle_add(self.job.plot.graphic.set_mirror_y, enabled)
        GObject.idle_add(self._update_preview)

    @callback
    def on_graphic_scale_lock_toggled(self, checkbox, data=None):
        if checkbox.get_active():
            self.get_widget('inkcut', 'scale-x-label').set_text("Scale:")
            self.get_widget('inkcut', 'scale-lock-box').hide()
            if self.job is not None:
                s = self.get_widget('graphic-properties',
                                    'graphic-scale-x').get_value()
                self.get_widget('graphic-properties',
                                'graphic-scale-y').set_value(s)
        else:
            self.get_widget('inkcut', 'scale-x-label').set_text("Scale - X:")
            self.get_widget('inkcut', 'scale-lock-box').show()

    @callback
    def on_graphic_rotation_changed(self, combobox, data=None):
        degrees = combobox.get_active() * 90
        self.flash("Setting graphic rotation to %s..." % degrees,
                   indicator=True)
        GObject.idle_add(self.job.plot.graphic.set_rotation, degrees)
        GObject.idle_add(self._update_graphic_ui)

    # ===================================== File Menu Callbacks ===============================================
    @callback
    def on_job_review_activated(self, action, data=None):
        self.job.update_properties()
        builder = Gtk.Builder()
        builder.add_from_file(os.path.join(APP_DIR, 'ui', 'plot.ui'))
        dialog = builder.get_object('dialog1')
        builder.connect_signals(self)
        dialog.show_all()
        dialog.run()
        dialog.destroy()

    @callback
    def on_job_submit_activated(self, action, data=None):
        self.job.update_properties()
        GObject.idle_add(self.run_export_plugin)

    def run_export_plugin(self):
        # Write the job to a file
        tmp = tempfile.NamedTemporaryFile(suffix=".svg", delete=False)
        tmp.file.write(self.job.plot.get_xml())
        svg = tmp.name
        tmp.close()

        # Get the current device
        name = self.get_combobox_active_text(
            self.get_widget('inkcut', 'devices'))
        #device = self.session.query(Device).filter(Device.name==name).first()
        device = Device.get_printer_by_name(name)
        log.info(device)
        # Init the export plugin
        # TODO: Gather plugins here.... let user select...
        plugins = [HPGL.Import(), HPGL.Export()]
        plugin_found = False
        for plugin in plugins:
            if plugin.mode.lower() == "export":
                if str(device.command_language.lower()) in plugin.filetypes:
                    plugin_found = True
                    break
        if plugin_found == False:
            msg = Gtk.MessageDialog(
                type=Gtk.MessageType.ERROR,
                buttons=Gtk.ButtonsType.OK,
                message_format="No plugins found for the command language:%s."
                % device.command_language)
            msg.format_secondary_text(
                "Please make sure the plugins for this device are installed.\n If the problem persists, contact the developer."
            )
            msg.run()
            msg.destroy()
            raise Exception(
                "Error, no plugin found for that command language...")

        # Initialize the plugin then run it
        # TODO: put everything needed here...
        plugin.export_init(plot=self.job.get_properties('plot'),
                           device={'cutting_overlap': (10, False)})
        plugin.input = svg
        plugin.run()
        device.submit(plugin.output)

        # Cleanup
        os.remove(svg)

    def on_file_save_action_activated(self, widget, data=None):
        self.flash("Saving %s into the Job database..." % (self.job.name),
                   indicator=True)
        self.job.update_properties()
        self.get_window('inkcut').set_title("%s - Inkcut" % self.job.name)
        self.session.commit()
        GObject.timeout_add(1000, self.flash, "")

    def create_job(self, filename, **kwargs):
        """Create a job and try to set the source. Returns bool success."""
        job = Job(**kwargs)
        # Get the default material
        job.material = self.get_material()
        try:
            job.set_source(filename)
            self.job = job
            self.session.add(self.job)
            msg = 'Loaded %s' % os.path.basename(job.name or 'File')
            self.get_window('inkcut').set_title("*%s - Inkcut" % job.name)
            self.flash(msg)
            self.on_plot_feed_distance_changed(
                self.get_widget('plot-properties', 'plot-feed'))
            self._update_ui()
            return False
        except Exception, err:
            # update the ui with job info
            log.debug(traceback.format_exc())
            msg = Gtk.MessageDialog(type=Gtk.MessageType.ERROR,
                                    buttons=Gtk.ButtonsType.OK,
                                    message_format="Issue loading file")
            msg.format_secondary_text(err)
            msg.run()
            msg.destroy()
            return False
        except: