Ejemplo n.º 1
0
  def testModel(self):
    session = model.SessionFactory()
    # Test the database is empty
    assert session.query(model.ArchitectureBlock.Id).count() == 0
    
    # Add some architecture blocks and a View
    with model.sessionScope(session) as s:
      b1 = model.ArchitectureBlock(Name='blok1')
      b2 = model.ArchitectureBlock(Name='blok2')
      v1 = model.View(Name='view1')
      # Add a connection
      c1 = model.BlockConnection(theStart=b1, theEnd=b2)

      # Add function points
      fp1 = model.FunctionPoint(theDetails=c1, Name='fp1')
      fp2 = model.FunctionPoint(theBlock=b1, Name='fp2')

      # Add elements to the view
      br1 = model.BlockRepresentation(theDetails=b1, theView=v1)
      s.add(model.BlockRepresentation(theDetails=b1, theView=v1))
      br2 = model.BlockRepresentation(theDetails=b2, theView=v1)
      fpr1 = model.FpRepresentation(theView=v1, theFp=fp1, theAnchor=br1)
      fpr2 = model.FpRepresentation(theView=v1, theFp=fp2, theAnchor=br2)
      s.add(fpr1)
      s.add(fpr2)


    assert session.query(model.FpRepresentation.Id).count() == 2
    assert session.query(model.BlockRepresentation.Id).count() == 3
    
    block1 = session.query(model.ArchitectureBlock).get(b1.Id)
    assert len(block1.Representations) == 2
    
    # Delete Block two; check everything is deleted correctly
    with model.sessionScope(session) as s:
      s.query(model.ArchitectureBlock).filter(model.ArchitectureBlock.Id==b2.Id).delete()
    assert session.query(model.ArchitectureBlock.Id).count() == 1
    self.assertEqual(session.query(model.BlockRepresentation.Id).count(), 2)
    self.assertEqual(session.query(model.BlockConnection.Id).count(), 0)
    self.assertEqual(session.query(model.FpRepresentation.Id).count(), 1)
    
    # Delete the View
    fp2uc = session.query(model.FpRepresentation).get(fpr2.Id)
    with model.sessionScope(session) as s:
      s.query(model.View).filter(model.View.Id==1).delete()
    self.assertEqual(session.query(model.BlockRepresentation.Id).count(), 0)
    self.assertEqual(session.query(model.FpRepresentation.Id).count(), 0)
    
    # Check that accessing ORM objects that have been deleted raises errors.
    try:
      print 'DELETED FP2UC', fp2uc
      self.fail('Should have raised an exception')
    except ObjectDeletedError:
      pass
Ejemplo n.º 2
0
  def do(self, ctrl):
    source = self.start
    target = self.end
    # Find the connection object, or create it if it does not yet exist.
    # This connection is between Architecture Blocks, not their representations.
    with model.sessionScope(ctrl.session) as session:
      bc = model.BlockConnection
      conns = session.query(bc).\
                           filter(bc.Start.in_([source.Block, target.Block])).\
                           filter(bc.End.in_([source.Block, target.Block])).all()
      if conns:
        connection = conns[0]
      else:
        connection = model.BlockConnection(Start=source.Block, End=target.Block)
        session.add(connection)
        # We need a valid primary key, so flush the session but do not commit.
        session.flush()
      # Add the representation of the connection, between two representations of blocks.
      details = model.ConnectionRepresentation(Connection=connection.Id,
                                               theStart=source,
                                               theEnd=target,
                                               View=self.view)

      session.add(details)
      # Flush the database so that all references are updated.
      session.flush()
    return details
Ejemplo n.º 3
0
 def onItemChanged(self, item, column):
   new_name = str(item.text(0))
   if new_name != item.details.Name:
     item.details.Name = new_name
     # Ensure the changes are committed.
     with model.sessionScope(self.session):
       pass
Ejemplo n.º 4
0
  def deleteItems(self, items):
    ''' Delete a set of items
    '''
    to_remove = [] # A list of all graphic items to remove.
    # Use a scoped session to ensure the consistency of the database.
    with model.sessionScope(self.session) as session:
      for item in items:
        to_remove.append(item)
        # When deleting a block, remove the connections as well.
        # Deleting a block means only the representation is removed from the view,
        # so remove only the line, leave the connection in the model.
        details = item.details
        if isinstance(details, model.BlockRepresentation):
          block_id = details.Id
          for con in self.scene.connections.values():
            if con.Start == block_id or con.End == block_id:
              to_remove.append(self.scene.connection_items[con.Id])
        elif isinstance(details, model.ConnectionRepresentation):
          session.delete(details)
          # When deleting connections, check that there are no functionpoints on it.
          nr_fps = self.session.query(sql.func.count(model.FunctionPoint.Id)).\
                          filter(model.FunctionPoint.Connection==details.Id).one()[0]
          if nr_fps > 0:
            raise RuntimeError('Can not delete connection: has function points!')

        # Also check for annotations anchored on the item!
        session.delete(details)
    # No errors: actually delete the items from the drawing.
    for it in to_remove:
      self.scene.removeItem(it)
Ejemplo n.º 5
0
 def dropEvent(self, event):
   ''' Replaces the dropEvent handler for the tree widgets.
   '''
   # Check that the drop is from within the widget.
   if event.source() != self:
     event.ignore()
     return
   # Find out which item is dropped on.
   item = self.itemAt(event.pos())
   # Check it is not dropped on itself
   if item in self.selectedItems():
     event.ignore()
     return
   # Change the action from IGNORE to MOVE
   event.setDropAction(QtCore.Qt.MoveAction)
   # Get the current list of children
   children = None
   if item:
     children = [item.child(i) for i in range(item.childCount())]
   # Do the drop
   result = QtGui.QTreeWidget.dropEvent(self, event)
   # Find out which item was dropped on, and administrate the changes.
   with model.sessionScope(self.session_parent.getSession()):
     if item:
       new_children = [item.child(i) for i in range(item.childCount())]
       new_children = [ch for ch in new_children if ch not in children]
       parent_item = item.details.Id
       for ch in new_children:
         ch.details.Parent = parent_item
     else:
       # The dragged item has become a top-level item.
       # Find out which item it was from the mime data.
       details = self.session_parent.drop2Details(event)
       details.Parent = None
Ejemplo n.º 6
0
 def executeQueries(self, queries):
   ''' Execute a set of queries, using a transaction.
   '''
   session = sessionmaker(bind=self.engine)()
   with sessionScope(session) as s:
     for q in queries:
       s.execute(q)
Ejemplo n.º 7
0
 def closeDetailsViewer(self):
   if self.details_viewer:
     # Automatically commit any changes from the editor
     with model.sessionScope(self.session):
       widget = self.ui.areaDetails.takeWidget()
       widget.close()
       self.ui.areaDetails.hide()
       self.details_viewer = None
Ejemplo n.º 8
0
 def do(self, ctrl):
   with file(self.fname, 'rb') as f:
     data = f.read()
   with model.sessionScope(ctrl.session) as session:
     icon_name = os.path.split(self.fname)[-1]
     details = model.Icon(Name = icon_name, Data = data, Length = len(data))
     session.add(details)
   return details
Ejemplo n.º 9
0
  def do(self, ctrl):
    x, y = self.pos.x(), self.pos.y()

    with model.sessionScope(ctrl.session) as session:
      details = model.Annotation(View=self.view_id,
                                  x=x, y=y,
                                  AnchorPoint=self.anchor_id,
                                  Order = self.order,
                                  width=BLOCK_WIDTH, height=BLOCK_HEIGHT)
      session.add(details)
    return details
Ejemplo n.º 10
0
 def onDeleteWorker(self, triggered=False):
   selection = self.ui.lstWorkers.selectedItems()
   if len(selection) == 0:
     return
   
   with model.sessionScope(self.session) as session:
     for item in selection:
       session.delete(item.details)
   for item in selection:
     index = self.ui.lstWorkers.row(item)
     _ = self.ui.lstWorkers.takeItem(index)
Ejemplo n.º 11
0
  def onAddWorker(self, triggered=False):
    text, ok = QtGui.QInputDialog.getText(self, 'Nieuwe Werker',
                                "Welke naam krijgt de nieuwe werker?")
    if not ok:
      return
    
    worker = model.Worker(Name=str(text))
    with model.sessionScope(self.session) as session:
      session.add(worker)

    item = QtGui.QListWidgetItem(worker.Name, self.ui.lstWorkers)
    item.details = worker
Ejemplo n.º 12
0
  def onEstimateDetails(self):
    # Commit any outstanding changes
    self.session.commit()
    with model.sessionScope(self.session) as session:
      project = self.ui.treeProjects.currentItem().details
      widget = EstimateDetails(None, project)
      action = QtGui.QAction('Export as CSV', self)
      action.triggered.connect(widget.exportCsv)

      result = showWidgetDialog(self, widget, [action])
      if result != QtGui.QDialog.Accepted:
        # Rollback any changes made while editing
        session.rollback()
Ejemplo n.º 13
0
 def onAssign(self, _checked):
   ''' Called when the user wants to assign an item to a user. '''
   worker = str(self.ui.cmbWorker.currentText())
   index  = self.ui.tblItems.currentRow()
   item   = self.table_contents[self.ui.tblItems][index]
   worker_id = self.session.query(model.Worker.Id).filter(model.Worker.Name==worker).one()[0]
   status = model.PlaneableStatus(Planeable=item[0].Id, AssignedTo=worker_id,
                                  Status=item[1], TimeRemaining=item[3], TimeSpent=item[4])
   with model.sessionScope(self.session):
     self.session.add(status)
   
   # Update the views
   self.onWorkerChange()
   self.onFilterChange(False)
Ejemplo n.º 14
0
  def addHandler(self, checked=False):
    ''' Add a new instance of the model class.
    '''
    items = self.selectedItems()
    if len(items) == 1:
      # Not a top-level item: try to find the ID of the item.
      parent_item = items[0].details.Id
    else:
      parent_item = None

    details = self.model_class(Name='new item',
                          Parent=parent_item)
    with model.sessionScope(self.session_parent.getSession()) as session:
      session.add(details)
    # As the session is closed, the new item is added to this tree.
    # Cause the item to be selected.
    self.session_parent.onTreeItemAdded(details)
Ejemplo n.º 15
0
def createDefaultStyle(session):
  with model.sessionScope(session):
    default = session.query(model.Style).filter(model.Style.Name=='Default').first()
    if not default:
      default = model.Style(Name='Default')
      session.add(default)
    default.Details = '''
      background-color:white;
      font:Arial 12pt;
      halign:center;
      valign:center;
      is_gradient:True;
      color:#00529c;
      color1:white;
      color2:#00529c;
      text-is_gradient:False;
      icon:None;
      functionpoint-is_gradient:False;
      functionpoint-alpha:1.0;
      functionpoint-end:[[0,0], [-5, 5], [0, 0], [-5, -5], [0,0]];
      arrow-functionpoint-offset:[-10,10];
      connection-text-alpha:1.0;
      annotation-color2:#ffef5d;
      annotation-text-alpha:0.0;
      usecase-color2:#ff6347;
      usecase-text-alpha:0.0;
      width:3;
      archblock-width:1;
      archblock-offset:[0,0];
      archblock-text-alpha:0.0;
      white-archblock-color2:white;
      dark-archblock-color2:#f2f2f2;
      type3-archblock-color2:#838383;
      time-archblock-color2:#ffc0cb;
      description-archblock-color2:#add8e6;
      party-archblock-color2:#90ee90;
      role-archblock-color2:#ffff80;
      inheritance-connection-end:[[0,0], [-10,10], [-10,-10], [0,0]];
      aggregation-connection-start:[[0,0], [-10,-10], [-20,0], [-10,10], [0,0]];
      association-connection-end:[[0,0],[-10,10],[0,0],[-10,-10],[0,0]];
    '''
    return default
Ejemplo n.º 16
0
 def do(self, ctrl):
   new_details = None
   with model.sessionScope(ctrl.session):
     if isinstance(self.details, model.ArchitectureBlock):
       new_details = model.BlockRepresentation(Block=self.details.Id,
                                               View = self.view_id,
                                               x = self.coods.x(),
                                               y = self.coods.y(),
                                               height = BLOCK_HEIGHT,
                                               width = BLOCK_WIDTH,
                                               Order = self.order)
       ctrl.session.add(new_details)
     elif isinstance(self.details, model.View):
       new_details = model.UsecaseRepresentation(Parent=self.details.Id,
                                               View = self.view_id,
                                               x = self.coods.x(),
                                               y = self.coods.y(),
                                               height = BLOCK_HEIGHT,
                                               width = BLOCK_WIDTH,
                                               Order = self.order)
       ctrl.session.add(new_details)
   return new_details
Ejemplo n.º 17
0
def importData(data, db):
  table_renames = {'fptousecase': 'fprepresentation',
                   'fptoview':'fprepresentation',
                   'connection':'blockconnection'}
  table_ignore = ['colorpalette', 'dbaseversion']
  tables = {tab.__tablename__:tab for tab in model.Base.getTables()}
  # Switch off the foreign keys for now
  model.check_fkeys = False
  engine = model.create_engine(db, echo=True)
  old_url = model.the_url
  model.the_url = db
  model.changeEngine(engine)
  # Clean the database
  model.cleanDatabase()
  try:
    session = model.SessionFactory()
    with model.sessionScope(session) as session:
      # In PostgreSQL, ensure the foreign keys are only checked at the commit, not before.
      if db.startswith('postgresql'):
        session.execute('SET CONSTRAINTS ALL DEFERRED')

      v = int(data['dbaseversion'][0]['Version'])
      if v < 6:
        upgradeToVersion6(data)
      del data['dbaseversion']    # Remove the old database version number
      # Add the current database version
      session.add(model.DbaseVersion())

      # Treat the planeable and anchor items differently: these are polymorphic tables.
      # The base tables are not added directly but through their child tables, using the ORM
      poly_items = {}  # Store the contents held by the polymorphic tables. These are needed later..
      poly_bases = {}  # Find the base for a specific table.
      for poly_table, poly_column in [('planeableitem', 'ItemType'), ('anchor', 'AnchorType')]:
        poly_items[poly_table] = {r['Id']:r for r in data[poly_table]}
        children = set([r[poly_column] for r in data[poly_table]])
        for c in children:
          poly_bases[c] = poly_table
        # Do not add the table directly, so remove it from the list.
        del data[poly_table]

      for n1, n2 in table_renames.items():
        if n1 in data:
          data[n2] = data[n1]

      for table, name in [(t, t.__tablename__) for t in model.order] + \
                  [(model.Base.metadata.tables['planeablexref'], 'planeablexref')]:
        records = data.get(name, [])
        if not records:
          continue
        # Start of a new table.
        if name in table_ignore:
          # Skip this table.
          continue
        if name not in tables:
          table = [name]
        else:
          table = tables[name]
        base_class = poly_bases.get(name, None)

        # Determine which fields are no longer used
        fields = records[0].keys()
        exclude = [f for f in fields if not hasattr(table, f)]
        for d in records:
          print 'Table:', name, 'data:', d
          # Exclude fields that have been removed from the database.
          if exclude:
            for e in exclude:
              del d[e]
          if base_class:
            # Add in the data stored in the polymorphic base table
            d.update(poly_items[base_class][d['Id']])

          # Add the record to the database
          if name not in tables:
            # This class needs raw SQL to create.
            if d:
              ins = table.insert().values(**d)
              session.execute(ins)
          else:
            el = table(**d)
            session.add(el)

    if db.startswith('postgresql'):
      # Only update the sequence for direct children from MyBase.
      # This excludes all polymorphic derivatives (e.g. Requirement) that have no sequence.
      for table in model.MyBase.__subclasses__()[0].__subclasses__():
        name = table.__tablename__
        # In PostgreSQL, the sequences are not updated automatically in this case...
        if 'Id' in table.getFields():
          # Fix the sequence number
          seqname = '%s_Id_seq'%name
          q = '''SELECT setval('"%s"', (SELECT MAX("Id") FROM %s))'''%(seqname, name)
          conn = engine.connect()
          conn.execute("commit")
          conn.execute(q)

    
  finally:
    model.the_engine = None
    model.SessionFactory = None
    model.check_fkeys = True
    model.the_url = old_url