00001 from python_qt_binding.QtCore import Qt, QMimeData, QPoint, QEvent
00002 from python_qt_binding.QtGui import QPen, QColor, QSizePolicy, QDrag, QBrush, QGraphicsWidget
00003 from python_qt_binding.QtGui import QGraphicsView, QGraphicsAnchorLayout, QGraphicsScene
00004 from python_qt_binding.QtGui import QFontMetrics, QToolTip, QPixmap, QImage, QPolygon
00005 from python_qt_binding.QtCore import pyqtSignal as Signal
00006
00007 from diarc.snapkey import gen_snapkey, parse_snapkey
00008 from diarc.util import typecheck, TypedDict
00009 from diarc.view import View
00010 from diarc.view import BlockItemAttributes
00011 from diarc.view import BandItemAttributes
00012 from diarc.view import SnapItemAttributes
00013 from .SpacerContainer import SpacerContainer
00014 import json
00015 import sys
00016 import logging
00017
00018 log = logging.getLogger('diarc.qt_view')
00019
00020 class QtBlockItemAttributes(BlockItemAttributes):
00021 def __init__(self):
00022 BlockItemAttributes.__init__(self)
00023 self.__bgcolor = "black"
00024 self.__border_color = "black"
00025 self.__label_color = "black"
00026 self.border_width = 1
00027 @property
00028 def bgcolor(self):
00029 return QColor(self.__bgcolor)
00030 @bgcolor.setter
00031 def bgcolor(self, value):
00032 self.__bgcolor = value
00033 @property
00034 def border_color(self):
00035 return QColor(self.__border_color)
00036 @border_color.setter
00037 def border_color(self, value):
00038 self.__border_color = value
00039 @property
00040 def label_color(self):
00041 return QColor(self.__label_color)
00042 @label_color.setter
00043 def label_color(self, value):
00044 self.__label_color = value
00045
00046 class QtBandItemAttributes(BandItemAttributes):
00047 def __init__(self):
00048 BandItemAttributes.__init__(self)
00049 self._bgcolor = "black"
00050 self._border_color = "black"
00051 self._label_color = "black"
00052 @property
00053 def bgcolor(self):
00054 return QColor(self._bgcolor)
00055 @bgcolor.setter
00056 def bgcolor(self, value):
00057 self._bgcolor = value
00058 @property
00059 def border_color(self):
00060 return QColor(self._border_color)
00061 @border_color.setter
00062 def border_color(self, value):
00063 self._border_color = value
00064 @property
00065 def label_color(self):
00066 return QColor(self._label_color)
00067 @label_color.setter
00068 def label_color(self, value):
00069 self._label_color = value
00070
00071 class QtSnapItemAttributes(SnapItemAttributes):
00072 def __init__(self):
00073 SnapItemAttributes.__init__(self)
00074 self._bgcolor = "white"
00075 self._border_color = "black"
00076 self._label_color = "black"
00077 @property
00078 def bgcolor(self):
00079 return QColor(self._bgcolor)
00080 @bgcolor.setter
00081 def bgcolor(self, value):
00082 self._bgcolor = value
00083 @property
00084 def border_color(self):
00085 return QColor(self._border_color)
00086 @border_color.setter
00087 def border_color(self, value):
00088 self._border_color = value
00089 @property
00090 def label_color(self):
00091 return QColor(self._label_color)
00092 @label_color.setter
00093 def label_color(self, value):
00094 self._label_color = value
00095
00096
00097
00098 class BandStack(SpacerContainer):
00099 def __init__(self, parent):
00100 super(BandStack, self).__init__(parent)
00101 self.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred))
00102 self.setMinimumWidth(15)
00103 self.spacerType = BandSpacer
00104
00105 class BandSpacer(SpacerContainer.Spacer):
00106 def __init__(self, parent):
00107 super(BandSpacer, self).__init__(parent)
00108 self._layout_manager = parent.parent
00109 self._view = parent.parent.view()
00110 self._adapter = parent.parent.adapter()
00111 self.dragOver = False
00112 self.setSizePolicy(QSizePolicy(QSizePolicy.Preferred, QSizePolicy.MinimumExpanding))
00113 self.setPreferredHeight(15)
00114 self.setMinimumHeight(15)
00115 self.setAcceptDrops(True)
00116
00117 def _release(self):
00118 topAltitude = self.topBand.altitude if self.topBand else None
00119 bottomAltitude = self.bottomBand.altitude if self.bottomBand else None
00120 log.debug("... Releasing BandSpacer between topBand %r and botBand %r"%(topAltitude, bottomAltitude))
00121 super(BandSpacer, self)._release()
00122
00123 @property
00124 def topBand(self):
00125 return self.itemA
00126
00127 @property
00128 def bottomBand(self):
00129 return self.itemB
00130
00131 def link(self):
00132 l = self.layout()
00133
00134 if self.topBand:
00135 l.addAnchor(self, Qt.AnchorTop, self.topBand, Qt.AnchorBottom)
00136
00137 elif self.bottomBand.isPositive():
00138 l.addAnchor(self, Qt.AnchorTop, self.parent, Qt.AnchorTop)
00139
00140 elif not self.bottomBand.isPositive():
00141 l.addAnchor(self, Qt.AnchorTop, self._layout_manager.block_container, Qt.AnchorBottom)
00142
00143
00144 if self.bottomBand:
00145 l.addAnchor(self, Qt.AnchorBottom, self.bottomBand, Qt.AnchorTop)
00146
00147 elif self.topBand.isPositive():
00148 l.addAnchor(self, Qt.AnchorBottom, self._layout_manager.block_container, Qt.AnchorTop)
00149 elif not self.topBand.isPositive():
00150 l.addAnchor(self, Qt.AnchorBottom, self.parent, Qt.AnchorBottom)
00151
00152
00153 l.addAnchor(self, Qt.AnchorLeft, self.parent, Qt.AnchorLeft)
00154 l.addAnchor(self, Qt.AnchorRight, self.parent, Qt.AnchorRight)
00155
00156 def dragEnterEvent(self,event):
00157 if not event.mimeData().hasText():
00158 event.setAccepted(False)
00159 return
00160 data = json.loads(str(event.mimeData().text()))
00161 if not 'band' in data:
00162 event.setAccepted(False)
00163 return
00164
00165
00166
00167
00168
00169 topAltitude = self.topBand.altitude if self.topBand else 0
00170 bottomAltitude = self.bottomBand.altitude if self.bottomBand else 0
00171
00172 if data['band'] in [topAltitude, bottomAltitude]:
00173 event.setAccepted(False)
00174 return
00175
00176 if data['band'] > 0 and (topAltitude > 0 or bottomAltitude > 0):
00177 event.setAccepted(True)
00178 self.dragOver = True
00179 self.update()
00180 log.debug("Drag Positive ENTER between topBand %r and botBand %r"%(topAltitude, bottomAltitude))
00181
00182 elif data['band'] < 0 and (topAltitude < 0 or bottomAltitude < 0):
00183 event.setAccepted(True)
00184 self.dragOver = True
00185 self.update()
00186 log.debug("Drag Negative ENTER between topBand %r and botBand %r"%(topAltitude, bottomAltitude))
00187 else:
00188 event.setAccepted(False)
00189 return
00190 self.setZValue(max([self.topBand.altitude if self.topBand else None,
00191 self.bottomBand.altitude if self.bottomBand else None]))
00192
00193 def dragLeaveEvent(self,event):
00194 self.dragOver = False
00195 self.update()
00196
00197 def dropEvent(self,event):
00198 self.dragOver = False
00199 self.update()
00200 """ Reorder the band altitudes to put the dropped band in the new position"""
00201
00202
00203
00204
00205
00206
00207 data = json.loads(str(event.mimeData().text()))
00208
00209 srcAlt = data['band']
00210
00211 topAltitude = self.topBand.altitude if self.topBand else None
00212 bottomAltitude = self.bottomBand.altitude if self.bottomBand else None
00213 log.debug("Moving Band %d between topBand %r and botBand %r"%(srcAlt, topAltitude, bottomAltitude))
00214 self._adapter.reorder_bands(srcAlt,bottomAltitude,topAltitude)
00215
00216 def paint(self,painter,option,widget):
00217 if self.dragOver:
00218 pen = QPen()
00219 pen.setBrush(Qt.lightGray)
00220 pen.setStyle(Qt.DashLine)
00221 painter.setPen(pen)
00222 else:
00223 painter.setPen(Qt.NoPen)
00224 painter.drawRect(self.rect())
00225
00226 class BandItem(SpacerContainer.Item, QtBandItemAttributes):
00227 def __init__(self, parent, altitude, rank):
00228 self._layout_manager = typecheck(parent, LayoutManagerWidget, "parent")
00229 self._view = parent.view()
00230 self._adapter = parent.adapter()
00231 super(BandItem,self).__init__(parent,parent.bandStack)
00232 QtBandItemAttributes.__init__(self)
00233
00234
00235 self.altitude = altitude
00236 self._rank = rank
00237 self.top_band = None
00238 self.bot_band = None
00239 self.left_most_snap = None
00240 self.right_most_snap = None
00241
00242
00243 self.setContentsMargins(5,5,5,5)
00244 self.setSizePolicy(QSizePolicy(QSizePolicy.Preferred, QSizePolicy.MinimumExpanding))
00245 self.set_width(15)
00246 self.setAcceptHoverEvents(True)
00247
00248
00249 def release(self):
00250 self.top_band = None
00251 self.bot_band = None
00252 self.left_most_snap = None
00253 self.right_most_snap = None
00254 self.setParent(None)
00255 self.setVisible(False)
00256 super(BandItem, self)._release()
00257
00258 def itemA(self):
00259 """ Set itemA to be the topBand """
00260
00261 return self.top_band
00262
00263 def itemB(self):
00264 """ Set itemB to be the bottomBand """
00265
00266 return self.bot_band
00267
00268 def isUsed(self):
00269 """ Deprecated """
00270 return True
00271
00272 @property
00273 def rank(self):
00274 return self._rank
00275 @rank.setter
00276 def rank(self, value):
00277 self._rank = value
00278 self.setZValue(self._rank)
00279
00280 def set_attributes(self, attrs):
00281 """ Applies a set of BandItemViewAttributes to this object. Transforms
00282 some values such as color into qt specific values. """
00283 typecheck(attrs, BandItemAttributes, "attrs")
00284 self.copy_attributes(attrs)
00285 self.set_width(self.width)
00286 self.update(self.rect())
00287
00288 def set_width(self, width):
00289 """ Sets the 'width' of the band.
00290 This is actually setting the height, but is referred to as the width.
00291 """
00292 self.setPreferredHeight(width)
00293 self.setMinimumHeight(width)
00294
00295 def isPositive(self):
00296 return True if self.altitude > 0 else False
00297
00298 def link(self):
00299 sys.stdout.flush()
00300
00301 super(BandItem,self).link()
00302
00303 l = self.parent.layout()
00304 l.addAnchor(self, Qt.AnchorLeft, self.left_most_snap, Qt.AnchorLeft)
00305 l.addAnchor(self, Qt.AnchorRight, self.right_most_snap, Qt.AnchorRight)
00306
00307 def mousePressEvent(self, event):
00308 """ This is necessary to capture the mouse clicking event to drag"""
00309 pass
00310
00311 def mouseReleaseEvent(self, event):
00312 log.debug("Bringing band %d to front" % self.altitude)
00313 self._adapter.bring_band_to_front(self.altitude)
00314
00315 def hoverEnterEvent(self, event):
00316 if self.tooltip_text:
00317 QToolTip.showText(event.screenPos(),self.tooltip_text)
00318
00319 def hoverLeaveEvent(self, event):
00320 QToolTip.hideText()
00321
00322
00323 def mouseMoveEvent(self, event):
00324 if event.buttons() != Qt.LeftButton:
00325 super(BandItem,self).mouseMoveEvent(event)
00326 else:
00327 drag = QDrag(event.widget())
00328 mimeData = QMimeData()
00329 mimeData.setText(json.dumps({'band':self.altitude}))
00330 drag.setMimeData(mimeData)
00331 drag.start()
00332
00333 def paint(self,painter,option,widget):
00334 brush = QBrush()
00335 brush.setStyle(Qt.SolidPattern)
00336 brush.setColor(self.bgcolor)
00337 painter.fillRect(self.rect(),brush)
00338 painter.setPen(self.border_color)
00339 painter.drawRect(self.rect())
00340 rect = self.geometry()
00341 painter.setPen(self.label_color)
00342 fm = painter.fontMetrics()
00343 elided = fm.elidedText(self.label, Qt.ElideRight, rect.width())
00344 twidth = fm.width(elided)
00345 painter.drawText((rect.width()-twidth)/2,rect.height()-2,elided)
00346
00347
00348
00349
00350 class BlockContainer(SpacerContainer):
00351 def __init__(self, parent):
00352 super(BlockContainer,self).__init__(parent)
00353 self.spacerType = BlockSpacer
00354 self.parent = typecheck(parent,LayoutManagerWidget, "parent")
00355 self._view = parent.view()
00356 self._adapter = parent.adapter()
00357 self.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred))
00358 self.setMinimumWidth(15)
00359
00360 def paint(self, painter, option, widget):
00361 painter.setPen(Qt.NoPen)
00362 painter.drawRect(self.rect())
00363
00364 class BlockSpacer(SpacerContainer.Spacer):
00365 def __init__(self,parent):
00366 super(BlockSpacer,self).__init__(parent)
00367 self._view = parent.parent.view()
00368 self._adapter = parent.parent.adapter()
00369 self.dragOver = False
00370 self.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding,QSizePolicy.Preferred))
00371 self.setPreferredWidth(50)
00372 self.setMinimumWidth(50)
00373 self.setAcceptDrops(True)
00374
00375 @property
00376 def leftBlock(self):
00377 return self.itemA
00378
00379 @property
00380 def rightBlock(self):
00381 return self.itemB
00382
00383 def link(self):
00384 l = self.parent.parent.layout()
00385
00386 if self.leftBlock:
00387 l.addAnchor(self, Qt.AnchorLeft, self.leftBlock, Qt.AnchorRight)
00388 l.addAnchor(self, Qt.AnchorTop, self.leftBlock, Qt.AnchorTop)
00389 l.addAnchor(self, Qt.AnchorBottom, self.leftBlock, Qt.AnchorBottom)
00390
00391 else:
00392 l.addAnchor(self, Qt.AnchorLeft, self.parent, Qt.AnchorLeft)
00393 l.addAnchor(self, Qt.AnchorTop, self.parent, Qt.AnchorTop)
00394 l.addAnchor(self, Qt.AnchorBottom, self.parent, Qt.AnchorBottom)
00395
00396
00397 if self.rightBlock:
00398 l.addAnchor(self, Qt.AnchorRight, self.rightBlock, Qt.AnchorLeft)
00399 l.addAnchor(self, Qt.AnchorTop, self.rightBlock, Qt.AnchorTop)
00400 l.addAnchor(self, Qt.AnchorBottom, self.rightBlock, Qt.AnchorBottom)
00401
00402 else:
00403 l.addAnchor(self, Qt.AnchorRight, self.parent, Qt.AnchorRight)
00404 l.addAnchor(self, Qt.AnchorTop, self.parent, Qt.AnchorTop)
00405 l.addAnchor(self, Qt.AnchorBottom, self.parent, Qt.AnchorBottom)
00406
00407 def dragEnterEvent(self,event):
00408 if not event.mimeData().hasText():
00409 event.setAccepted(False)
00410 return
00411 data = json.loads(str(event.mimeData().text()))
00412 if 'block' in data:
00413 if self.leftBlock and data['block'] == self.leftBlock.block_index:
00414 event.setAccepted(False)
00415 return
00416 if self.rightBlock and data['block'] == self.rightBlock.block_index:
00417 event.setAccepted(False)
00418 return
00419 event.setAccepted(True)
00420 self.dragOver = True
00421 log.debug("Drag ENTER")
00422 self.update()
00423 else:
00424 event.setAccepted(False)
00425
00426 def dragLeaveEvent(self, event):
00427 self.dragOver = False
00428 self.update()
00429
00430 def dropEvent(self, event):
00431 """ Dropping a 'block' on a BlockSpacer triggers a reordering event """
00432 self.dragOver = False
00433 self.update()
00434
00435 data = json.loads(str(event.mimeData().text()))
00436 if not 'block' in data:
00437 raise Exception("Wrong drag data type!")
00438 srcIdx = data['block']
00439
00440 lowerIdx = self.leftBlock.block_index if self.leftBlock else None
00441 upperIdx = self.rightBlock.block_index if self.rightBlock else None
00442 self._adapter.reorder_blocks(srcIdx, lowerIdx, upperIdx)
00443
00444 def paint(self, painter, option, widget):
00445 if self.dragOver:
00446 pen = QPen()
00447 pen.setBrush(Qt.lightGray)
00448 pen.setStyle(Qt.DashLine)
00449 painter.setPen(pen)
00450 else:
00451 painter.setPen(Qt.NoPen)
00452 painter.drawRect(self.rect())
00453
00454 class BlockItem(SpacerContainer.Item, QtBlockItemAttributes):
00455 """ This is a QGraphicsWidget for a Diarc Block. """
00456 def __init__(self, parent, block_index):
00457 self._layout_manager = typecheck(parent, LayoutManagerWidget, "parent")
00458 self._view = parent.view()
00459 self._adapter = parent.adapter()
00460 super(BlockItem, self).__init__(parent, parent.block_container)
00461 QtBlockItemAttributes.__init__(self)
00462
00463
00464 self.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding))
00465 self.setPreferredHeight(5)
00466 self.setMinimumHeight(5)
00467 self.setContentsMargins(5,5,5,5)
00468
00469
00470 self.block_index = block_index
00471 self.left_block = None
00472 self.right_block = None
00473
00474
00475
00476 self._topMargin = BlockItem.HorizontalSpacer(self)
00477 self._botMargin = BlockItem.HorizontalSpacer(self)
00478 self._middleSpacer = BlockItem.MiddleSpacer(self)
00479
00480
00481
00482 self.myEmitter = MyEmitter(self)
00483 self.myCollector = MyCollector(self)
00484
00485 def set_attributes(self, attrs):
00486 typecheck(attrs, BlockItemAttributes, "attrs")
00487 self.copy_attributes(attrs)
00488 self._middleSpacer.set_width(self.spacerwidth)
00489 self.update(self.rect())
00490
00491 def release(self):
00492 super(BlockItem, self)._release()
00493 self.left_block = None
00494 self.right_block = None
00495 self._topMargin.release()
00496 self._botMargin.release()
00497 self._middleSpacer.release()
00498 self._topMargin = None
00499 self._botMargin = None
00500 self._middleSpacer = None
00501 self.myEmitter.release()
00502 self.myCollector.release()
00503 self.myEmitter = None
00504 self.myCollector = None
00505 self._layout_manager = None
00506 self._view = None
00507 self._adapter = None
00508
00509
00510
00511 def itemA(self):
00512 """ We use itemA for the BlockItem to the left. """
00513
00514 return self.left_block
00515
00516 def itemB(self):
00517 """ We use itemB for the BlockItem to the right. """
00518
00519 return self.right_block
00520
00521 def isUsed(self):
00522 return True
00523
00524 def link(self):
00525 """ Link to other objects around you. In addition to linking to other
00526 blocks, we need to link to our top and bottom margins, and the emitter
00527 and collector containers
00528 """
00529
00530 super(BlockItem, self).link()
00531
00532 l = self.parent.layout()
00533
00534 l.addAnchor(self,Qt.AnchorTop, self._topMargin, Qt.AnchorTop)
00535 l.addAnchor(self,Qt.AnchorLeft, self._topMargin, Qt.AnchorLeft)
00536 l.addAnchor(self,Qt.AnchorRight, self._topMargin, Qt.AnchorRight)
00537 l.addAnchor(self,Qt.AnchorBottom, self._botMargin, Qt.AnchorBottom)
00538 l.addAnchor(self,Qt.AnchorLeft, self._botMargin, Qt.AnchorLeft)
00539 l.addAnchor(self,Qt.AnchorRight, self._botMargin, Qt.AnchorRight)
00540
00541
00542 l.addAnchor(self._topMargin, Qt.AnchorBottom, self.myEmitter, Qt.AnchorTop)
00543 l.addAnchor(self._botMargin, Qt.AnchorTop, self.myEmitter, Qt.AnchorBottom)
00544 l.addAnchor(self._topMargin, Qt.AnchorBottom, self.myCollector, Qt.AnchorTop)
00545 l.addAnchor(self._botMargin, Qt.AnchorTop, self.myCollector, Qt.AnchorBottom)
00546
00547 l.addAnchor(self._middleSpacer, Qt.AnchorTop, self.myEmitter, Qt.AnchorTop)
00548 l.addAnchor(self._middleSpacer, Qt.AnchorTop, self.myCollector, Qt.AnchorTop)
00549 l.addAnchor(self._middleSpacer, Qt.AnchorBottom, self.myEmitter, Qt.AnchorBottom)
00550 l.addAnchor(self._middleSpacer, Qt.AnchorBottom, self.myCollector, Qt.AnchorBottom)
00551
00552 l.addAnchor(self, Qt.AnchorLeft, self.myCollector, Qt.AnchorLeft)
00553 l.addAnchor(self, Qt.AnchorRight, self.myEmitter, Qt.AnchorRight)
00554 l.addAnchor(self.myCollector, Qt.AnchorRight, self._middleSpacer, Qt.AnchorLeft)
00555 l.addAnchor(self._middleSpacer, Qt.AnchorRight, self.myEmitter, Qt.AnchorLeft)
00556
00557 def mousePressEvent(self, event):
00558 pass
00559
00560 def mouseMoveEvent(self, event):
00561 """ Creates a drag event with the block information """
00562 if event.buttons() != Qt.LeftButton:
00563 super(BlockItem, self).mouseMoveEvent(event)
00564 else:
00565 drag = QDrag(event.widget())
00566 mimeData = QMimeData()
00567 mimeData.setText(json.dumps({'block': self.block_index}))
00568 drag.setMimeData(mimeData)
00569 drag.start()
00570
00571 def paint(self,painter,option,widget):
00572 border_pen = QPen()
00573 border_pen.setBrush(self.border_color)
00574 border_pen.setStyle(Qt.SolidLine)
00575 border_pen.setWidth(self.border_width)
00576 painter.setPen(border_pen)
00577 painter.drawRect(self.rect())
00578
00579 class MiddleSpacer(QGraphicsWidget):
00580 def __init__(self,parent):
00581 super(BlockItem.MiddleSpacer,self).__init__(parent=parent)
00582
00583
00584
00585
00586 self.blockItem = parent
00587 self.setSizePolicy(QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred))
00588
00589 self.set_width(20)
00590 self.setAcceptHoverEvents(True)
00591
00592 def set_width(self, width):
00593 self.setPreferredWidth(width)
00594 self.setMinimumWidth(width)
00595
00596 def release(self):
00597 self.setParent(None)
00598 self.blockItem = None
00599
00600 def hoverEnterEvent(self, event):
00601 if self.blockItem.tooltip_text:
00602 QToolTip.showText(event.screenPos(),self.blockItem.tooltip_text)
00603
00604 def hoverLeaveEvent(self, event):
00605 QToolTip.hideText()
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615 def paint(self,painter,option,widget):
00616 painter.setPen(Qt.NoPen)
00617 painter.drawRect(self.rect())
00618 painter.setPen(self.blockItem.label_color)
00619 painter.rotate(-90)
00620 rect = self.rect()
00621 fm = painter.fontMetrics()
00622 elided = fm.elidedText(self.blockItem.label, Qt.ElideRight, rect.height()-2)
00623 twidth = fm.width(elided)
00624 painter.drawText(-twidth-(rect.height()-twidth)/2,rect.width()-2,elided)
00625
00626 class HorizontalSpacer(QGraphicsWidget):
00627 def __init__(self,parent):
00628 super(BlockItem.HorizontalSpacer,self).__init__(parent=parent)
00629 self.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding,QSizePolicy.Preferred))
00630 self.setPreferredHeight(0)
00631 self.setMinimumHeight(0)
00632 self.setMaximumHeight(0)
00633 self.setMinimumWidth(5)
00634
00635 def release(self):
00636 self.setParent(None)
00637
00638 class SnapContainer(SpacerContainer):
00639 def __init__(self,parent):
00640 super(SnapContainer, self).__init__(parent.parent)
00641 self.parentBlock = typecheck(parent, BlockItem, "parent")
00642
00643 self.spacerType = SnapSpacer
00644 self.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred))
00645 self.setMinimumWidth(1)
00646 self.setPreferredWidth(1)
00647
00648 def release(self):
00649 super(SnapContainer, self)._release()
00650 self.parentBlock = None
00651
00652 def strType(self):
00653 """ prints the container type as a string """
00654 return "emitter" if isinstance(self,MyEmitter) else "collector" if isinstance(self,MyCollector) else "unknown"
00655
00656 def paint(self,painter,option,widget):
00657 painter.setPen(Qt.green)
00658 painter.drawRect(self.rect())
00659
00660
00661 class MyEmitter(SnapContainer):
00662 def paint(self, painter, option, widget):
00663 if self.parentBlock.draw_debug:
00664 painter.setPen(Qt.green)
00665 painter.drawRect(self.rect())
00666
00667 class MyCollector(SnapContainer):
00668 def paint(self, painter, option, widget):
00669 if self.parentBlock.draw_debug:
00670 painter.setPen(Qt.blue)
00671 painter.drawRect(self.rect())
00672
00673
00674 class SnapSpacer(SpacerContainer.Spacer):
00675 def __init__(self,parent):
00676 super(SnapSpacer,self).__init__(parent)
00677 self._layout_manager = parent.parent
00678 self._view = parent.parent.view()
00679 self._adapter = parent.parent.adapter()
00680
00681 self.dragOver = False
00682
00683
00684 self.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding,QSizePolicy.Preferred))
00685 self.collapseWidth()
00686 self.setAcceptDrops(True)
00687
00688 @property
00689 def leftSnap(self):
00690 return self.itemA
00691
00692 @property
00693 def rightSnap(self):
00694 return self.itemB
00695
00696 def link(self):
00697 l = self.parent.parent.layout()
00698
00699 if self.leftSnap:
00700 l.addAnchor(self, Qt.AnchorLeft, self.leftSnap, Qt.AnchorRight)
00701 l.addAnchor(self, Qt.AnchorTop, self.leftSnap, Qt.AnchorTop)
00702 l.addAnchor(self, Qt.AnchorBottom, self.leftSnap, Qt.AnchorBottom)
00703
00704 else:
00705 l.addAnchor(self, Qt.AnchorLeft, self.parent, Qt.AnchorLeft)
00706 l.addAnchor(self, Qt.AnchorTop, self.parent, Qt.AnchorTop)
00707 l.addAnchor(self, Qt.AnchorBottom, self.parent, Qt.AnchorBottom)
00708
00709 if self.rightSnap:
00710 l.addAnchor(self, Qt.AnchorRight, self.rightSnap, Qt.AnchorLeft)
00711 l.addAnchor(self, Qt.AnchorTop, self.rightSnap, Qt.AnchorTop)
00712 l.addAnchor(self, Qt.AnchorBottom, self.rightSnap, Qt.AnchorBottom)
00713
00714 else:
00715 l.addAnchor(self, Qt.AnchorRight, self.parent, Qt.AnchorRight)
00716 l.addAnchor(self, Qt.AnchorTop, self.parent, Qt.AnchorTop)
00717 l.addAnchor(self, Qt.AnchorBottom, self.parent, Qt.AnchorBottom)
00718
00719 def dragEnterEvent(self, event):
00720 """ Decides whether or not the information being dragged can be placed here"""
00721 if not event.mimeData().hasText():
00722 event.setAccepted(False)
00723 return
00724 data = json.loads(str(event.mimeData().text()))
00725 if not set(['block', 'container', 'snap']).issubset(set(data.keys())):
00726 event.setAccepted(False)
00727 return
00728 if not data['block'] == self.parent.parentBlock.block_index:
00729 event.setAccepted(False)
00730 return
00731 if not self.parent.strType() == data['container']:
00732 event.setAccepted(False)
00733 return
00734 if self.leftSnap and data['snap'] == self.leftSnap.snap_order:
00735 event.setAccepted(False)
00736 return
00737 if self.rightSnap and data['snap'] == self.rightSnap.snap_order:
00738 event.setAccepted(False)
00739 return
00740 event.setAccepted(True)
00741 self.expandWidth()
00742 self.dragOver = True
00743 self.update()
00744
00745 def dragLeaveEvent(self, event):
00746 self.dragOver = False
00747 self.collapseWidth()
00748 self.update()
00749
00750 def dropEvent(self,event):
00751 """ Relocates a MySnap to this position """
00752 self.collapseWidth()
00753 self.dragOver = False
00754 data = json.loads(str(event.mimeData().text()))
00755 assert(data['block'] == self.parent.parentBlock.block_index)
00756 assert(data['container'] == self.parent.strType())
00757
00758 srcIdx = data['snap']
00759 lowerIdx = self.leftSnap.snap_order if self.leftSnap else None
00760 upperIdx = self.rightSnap.snap_order if self.rightSnap else None
00761 self._adapter.reorder_snaps(data['block'], data['container'], srcIdx, lowerIdx, upperIdx)
00762
00763 def paint(self, painter, option, widget):
00764 if self.dragOver:
00765 brush = QBrush()
00766 brush.setStyle(Qt.Dense4Pattern)
00767 brush.setColor(Qt.yellow)
00768 painter.fillRect(self.rect(),brush)
00769 pen = QPen()
00770 pen.setBrush(Qt.darkGray)
00771 pen.setStyle(Qt.DotLine)
00772 pen.setWidth(1)
00773 painter.setPen(pen)
00774 painter.drawRect(self.rect())
00775 rect = self.geometry()
00776 else:
00777 painter.setPen(Qt.NoPen)
00778
00779 painter.drawRect(self.rect())
00780
00781 def collapseWidth(self):
00782 """ Make the width very small """
00783 self.setMinimumWidth(0.1)
00784 self.setMaximumWidth(0.1)
00785 self.setPreferredWidth(0.1)
00786
00787 def expandWidth(self):
00788 """ Widen the spacer to afford seperation """
00789 self.setMinimumWidth(10)
00790 self.setMaximumWidth(10)
00791 self.setPreferredWidth(10)
00792
00793
00794
00795 class SnapItem(SpacerContainer.Item, QtSnapItemAttributes):
00796 def __init__(self, parent, snapkey):
00797 QtSnapItemAttributes.__init__(self)
00798 block_index, container_name, snap_order = parse_snapkey(snapkey)
00799 self._snapkey = snapkey
00800 self._layout_manager = typecheck(parent, LayoutManagerWidget, "parent")
00801 self._view = parent.view()
00802 self._adapter = parent.adapter()
00803
00804 assert(container_name in ["emitter","collector"])
00805 self.block_index = block_index
00806 self.snap_order = snap_order
00807 self.block_item = self._layout_manager.get_block_item(block_index)
00808 self.container = self.block_item.myEmitter if container_name == "emitter" else self.block_item.myCollector
00809
00810 self.left_snap = None
00811 self.right_snap = None
00812
00813
00814 self.posBandItem = None
00815 self.negBandItem = None
00816 super(SnapItem,self).__init__(parent,self.container)
00817
00818
00819 self.setSizePolicy(QSizePolicy(QSizePolicy.Preferred,QSizePolicy.Preferred))
00820 self.set_width(20)
00821
00822 self.setPreferredHeight(150)
00823 self.setMaximumHeight(150)
00824
00825
00826 _is_source = True if container_name == "emitter" else False
00827 self.upLink = SnapBandLink(None, is_uplink=True, is_source=_is_source)
00828 self.downLink = SnapBandLink(None,is_source=_is_source)
00829
00830 def release(self):
00831 self.left_snap = None
00832 self.right_snap = None
00833 self.upLink.setParent(None)
00834 self.downLink.setParent(None)
00835 self.upLink = None
00836 self.downLink = None
00837 self.setVisible(False)
00838 super(SnapItem, self)._release()
00839
00840
00841 def itemA(self):
00842 """ We use itemA for the SnapItem to the left """
00843 return self.left_snap
00844
00845 def itemB(self):
00846 """ We use itemB for the SnapItem to the right """
00847
00848
00849 return self.right_snap
00850
00851 def isUsed(self):
00852 """ Deprecated """
00853 return True
00854
00855 def set_attributes(self, attrs):
00856 typecheck(attrs, SnapItemAttributes, "attrs")
00857 self.copy_attributes(attrs)
00858 self.set_width(attrs.width)
00859 self.update(self.rect())
00860
00861 def set_width(self, width):
00862 self.width = width
00863 self.setPreferredWidth(width)
00864
00865 def link(self):
00866 super(SnapItem, self).link()
00867 l = self.parent.layout()
00868 l.addAnchor(self, Qt.AnchorTop, self.container, Qt.AnchorTop)
00869 l.addAnchor(self, Qt.AnchorBottom, self.container, Qt.AnchorBottom)
00870
00871
00872 if self.posBandItem:
00873 self.upLink.setVisible(True)
00874 self.upLink.setZValue(self.posBandItem.rank+0.5)
00875 l.addAnchor(self, Qt.AnchorTop, self.upLink, Qt.AnchorBottom)
00876 l.addAnchor(self.posBandItem, Qt.AnchorBottom, self.upLink, Qt.AnchorTop)
00877 l.addAnchor(self, Qt.AnchorLeft, self.upLink, Qt.AnchorLeft)
00878 l.addAnchor(self, Qt.AnchorRight, self.upLink, Qt.AnchorRight)
00879 self.upLink.bgcolor = self.posBandItem.bgcolor
00880 self.upLink.border_color = self.posBandItem.border_color
00881 self.upLink.label_color = self.posBandItem.label_color
00882 else:
00883 self.upLink.setVisible(False)
00884 self.upLink.setParent(None)
00885
00886 if self.negBandItem:
00887 self.downLink.setVisible(True)
00888 self.downLink.setZValue(self.negBandItem.rank+0.5)
00889 l.addAnchor(self, Qt.AnchorBottom, self.downLink, Qt.AnchorTop)
00890 l.addAnchor(self.negBandItem, Qt.AnchorTop, self.downLink, Qt.AnchorBottom)
00891 l.addAnchor(self, Qt.AnchorLeft, self.downLink, Qt.AnchorLeft)
00892 l.addAnchor(self, Qt.AnchorRight, self.downLink, Qt.AnchorRight)
00893 self.downLink.bgcolor = self.negBandItem.bgcolor
00894 self.downLink.border_color = self.negBandItem.border_color
00895 self.downLink.label_color = self.negBandItem.label_color
00896 else:
00897 self.downLink.setVisible(False)
00898 self.downLink.setParent(None)
00899
00900 def mousePressEvent(self, event):
00901 """ Captures the mouse press event for dragging """
00902 pass
00903
00904 def mouseReleaseEvent(self, event):
00905 if self.posBandItem:
00906 self._adapter.bring_band_to_front(self.posBandItem.altitude)
00907 if self.negBandItem:
00908 self._adapter.bring_band_to_front(self.negBandItem.altitude)
00909
00910 def mouseMoveEvent(self, event):
00911 if event.buttons() != Qt.LeftButton:
00912 super(SnapItem,self).mouseMoveEvent(event)
00913 else:
00914 drag = QDrag(event.widget())
00915 mimeData = QMimeData()
00916 mimeData.setText(json.dumps({'block': self.block_index,'container': self.container.strType(),'snap':self.snap_order}))
00917 drag.setMimeData(mimeData)
00918 drag.start()
00919
00920 def paint(self, painter, option, widget):
00921
00922 brush = QBrush()
00923 brush.setStyle(Qt.SolidPattern)
00924 brush.setColor(self.bgcolor)
00925 painter.fillRect(self.rect(),brush)
00926
00927 border_pen = QPen()
00928 border_pen.setBrush(self.border_color)
00929 border_pen.setStyle(Qt.SolidLine)
00930 border_pen.setWidth(self.border_width)
00931 painter.setPen(border_pen)
00932 painter.drawRect(self.rect())
00933 rect = self.geometry()
00934 painter.setPen(self.label_color)
00935 if self.draw_debug:
00936 if self.posBandItem:
00937 painter.drawText(6,12,str(self.posBandItem.altitude))
00938 if self.negBandItem:
00939 painter.drawText(3,rect.height()-3,str(self.negBandItem.altitude))
00940
00941 painter.rotate(-90)
00942 fm = painter.fontMetrics()
00943 elided = fm.elidedText(self.label, Qt.ElideRight, rect.height())
00944 twidth = fm.width(elided)
00945 painter.drawText(-twidth-(rect.height()-twidth)/2,rect.width()-2,elided)
00946
00947
00948 class SnapBandLink(QGraphicsWidget, QtBandItemAttributes):
00949 def __init__(self,parent, is_uplink=False, is_source=False):
00950 super(SnapBandLink,self).__init__(parent=parent)
00951 QtBandItemAttributes.__init__(self)
00952 self.setVisible(False)
00953 self.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding,QSizePolicy.MinimumExpanding))
00954 self.setPreferredWidth(5)
00955 self.setMinimumWidth(5)
00956 self.setPreferredHeight(5)
00957 self.setMinimumHeight(5)
00958
00959 self._is_uplink = is_uplink
00960 self._is_source = is_source
00961
00962
00963 def paint(self,painter,option,widget):
00964 brush = QBrush()
00965 brush.setStyle(Qt.SolidPattern)
00966 brush.setColor(self.bgcolor)
00967 painter.fillRect(self.rect(),brush)
00968 pen = QPen()
00969 pen.setBrush(self.border_color)
00970 pen.setStyle(Qt.DashLine)
00971 rect = self.rect()
00972 painter.setPen(pen)
00973 painter.drawRect(rect)
00974
00975 arrow_scale = 0.5
00976 arrow_width = rect.width()*arrow_scale
00977 arrow_height = arrow_width * 0.8
00978 arrow_margin = (rect.width()-arrow_width)/2.0
00979
00980 brush.setColor(self.label_color)
00981 painter.setPen(Qt.NoPen)
00982 painter.setBrush(brush)
00983 arrow = None
00984
00985 if (self._is_uplink and self._is_source) or (not self._is_uplink and not self._is_source):
00986
00987 arrow = QPolygon([QPoint(0,arrow_height), QPoint(arrow_width,arrow_height), QPoint(arrow_width/2.0,0)])
00988 else:
00989
00990 arrow = QPolygon([QPoint(0,0), QPoint(arrow_width,0), QPoint(arrow_width/2.0,arrow_height)])
00991
00992
00993 if self._is_uplink:
00994 arrow.translate(rect.x()+arrow_margin,rect.y()+rect.height()-arrow_height-arrow_margin)
00995 else:
00996 arrow.translate(rect.x()+arrow_margin,rect.y()+arrow_margin)
00997 painter.drawPolygon(arrow)
00998
00999 class LayoutManagerWidget(QGraphicsWidget):
01000 """ Holds the actual qt anchoredlayout and top level SpacerContainers """
01001 def __init__(self, view):
01002 super(LayoutManagerWidget, self).__init__(parent=None)
01003 self._view = view
01004 self.resize(0,0)
01005
01006
01007 self.block_container = BlockContainer(self)
01008 self.bandStack = BandStack(self)
01009
01010
01011 self._block_items = TypedDict(int,BlockItem)
01012 self._band_items = TypedDict(int,BandItem)
01013 self._snap_items = TypedDict(str,SnapItem)
01014
01015 def add_block_item(self, index):
01016 log.debug("... Adding BlockItem %d"%index)
01017 """ create a new BlockItem """
01018 if index in self._block_items:
01019 raise DuplicateItemExistsError("Block Item with index %d already exists"%(index))
01020 item = BlockItem(self, index)
01021 self._block_items[index] = item
01022 return item
01023
01024 def has_block_item(self, index):
01025 return True if index in self._block_items else False
01026
01027 def set_block_item_settings(self, index, left_index, right_index):
01028 item = self._block_items[index]
01029 item.left_block = self._block_items[left_index] if left_index is not None else None
01030 item.right_block = self._block_items[right_index] if right_index is not None else None
01031
01032 def set_block_item_attributes(self, index, attributes):
01033 self._block_items[index].set_attributes(attributes)
01034
01035 def remove_block_item(self, index):
01036 log.debug("... Removing BlockItem %d"%index)
01037 self._block_items[index].release()
01038 self._block_items.pop(index)
01039
01040 def get_block_item(self, index):
01041 """ Returns a BlockItem with specified index """
01042 return self._block_items[index]
01043
01044 def add_band_item(self, altitude, rank):
01045 """ Create a new drawable object to correspond to a Band. """
01046 log.debug("... Adding BandItem with altitude %d"%altitude)
01047 if altitude in self._band_items:
01048 raise DuplicateItemExistsError("BandItem with altitude %d already exists"%(altitude))
01049 item = BandItem(self, altitude, rank)
01050 self._band_items[altitude] = item
01051 return item
01052
01053 def has_band_item(self, altitude):
01054 return True if altitude in self._band_items else False
01055
01056 def remove_band_item(self, altitude):
01057 """ Remove the drawable object to correspond to a band """
01058 log.debug("... Removing BandItem altitude %d"%altitude)
01059 self._band_items[altitude].release()
01060 self._band_items.pop(altitude)
01061
01062 def get_band_item(self, altitude):
01063 return self._band_items[altitude]
01064
01065 def set_band_item_settings(self, altitude, rank,
01066 top_band_alt, bot_band_alt,
01067 leftmost_snapkey, rightmost_snapkey):
01068 item = self._band_items[altitude]
01069 item.rank = rank
01070 item.top_band = self._band_items[top_band_alt] if top_band_alt is not None else None
01071 item.bot_band = self._band_items[bot_band_alt] if bot_band_alt is not None else None
01072 item.left_most_snap = self._snap_items[str(leftmost_snapkey)]
01073 item.right_most_snap = self._snap_items[str(rightmost_snapkey)]
01074
01075 def set_band_item_attributes(self, altitude, attrs):
01076 self._band_items[altitude].set_attributes(attrs)
01077
01078 def add_snap_item(self, snapkey):
01079
01080
01081 snapkey = str(snapkey)
01082 log.debug("... Adding SnapItem %s"%snapkey)
01083 if snapkey in self._snap_items:
01084 raise DuplicateItemExistsError("SnapItem with snapkey %s already exists"%(snapkey))
01085 item = SnapItem(self, snapkey)
01086 self._snap_items[snapkey] = item
01087 return item
01088
01089 def remove_snap_item(self, snapkey):
01090
01091
01092 snapkey = str(snapkey)
01093 log.debug("... Removing SnapItem %s"%snapkey)
01094 self._snap_items[snapkey].release()
01095 self._snap_items.pop(snapkey)
01096
01097 def has_snap_item(self, snapkey):
01098 return True if snapkey in self._snap_items else False
01099
01100 def get_snap_items(self, snapkey):
01101
01102
01103 snapkey = str(snapkey)
01104 return self._snap_item[snapkey]
01105
01106 def set_snap_item_settings(self, snapkey, left_order, right_order, pos_band_alt, neg_band_alt):
01107
01108
01109 snapkey = str(snapkey)
01110 item = self._snap_items[snapkey]
01111 if left_order is not None:
01112 left_snapkey = gen_snapkey(item.block_index,item.container.strType(),left_order)
01113 item.left_snap = self._snap_items[left_snapkey]
01114 else:
01115 item.left_snap = None
01116 if right_order is not None:
01117 right_snapkey = gen_snapkey(item.block_index,item.container.strType(),right_order)
01118 item.right_snap = self._snap_items[right_snapkey]
01119 else:
01120 item.right_snap = None
01121 item.posBandItem = self._band_items[pos_band_alt] if pos_band_alt is not None else None
01122 item.negBandItem = self._band_items[neg_band_alt] if neg_band_alt is not None else None
01123
01124 def set_snap_item_attributes(self, snapkey, attributes):
01125
01126
01127 snapkey = str(snapkey)
01128 self._snap_items[snapkey].set_attributes(attributes)
01129
01130 def view(self):
01131 return self._view
01132
01133 def adapter(self):
01134 return self._view.adapter
01135
01136 def link(self):
01137 log.debug("*** Begining Linking ***")
01138 sys.stdout.flush()
01139
01140
01141 l = QGraphicsAnchorLayout()
01142 l.setSpacing(0.0)
01143 self.setLayout(l)
01144
01145
01146 self.layout().addAnchor(self.block_container, Qt.AnchorTop, self.layout(), Qt.AnchorTop)
01147 self.layout().addAnchor(self.block_container, Qt.AnchorLeft, self.layout(), Qt.AnchorLeft)
01148 self.layout().addAnchor(self.bandStack, Qt.AnchorLeft, self.block_container, Qt.AnchorLeft)
01149 self.layout().addAnchor(self.bandStack, Qt.AnchorRight, self.block_container, Qt.AnchorRight)
01150
01151
01152 for item in self._block_items.values():
01153 item.link()
01154
01155
01156 for item in self._band_items.values():
01157 item.link()
01158
01159
01160 for item in self._snap_items.values():
01161 item.link()
01162
01163 log.debug("*** Finished Linking ***\n")
01164 sys.stdout.flush()
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175 class QtView(QGraphicsView, View):
01176 """ This is a Qt based stand-alone widget that provides a visual rendering
01177 of a Topology. It provides a window into a self contained GraphicsScene in
01178 which we draw the topology.
01179 It also implements the View interface as a passthrough to the LayoutManager.
01180 """
01181
01182
01183
01184
01185 __update_view_signal = Signal()
01186
01187 __add_block_item_signal = Signal(int)
01188 __remove_block_item_signal = Signal(int)
01189 __set_block_item_settings_signal = Signal(int, object, object)
01190 __set_block_item_attributes_signal = Signal(int, BlockItemAttributes)
01191
01192 __add_band_item_signal = Signal(int, int)
01193 __remove_band_item_signal = Signal(int)
01194 __set_band_item_settings_signal = Signal(int, int, object, object, str, str)
01195 __set_band_item_attributes_signal = Signal(int, BandItemAttributes)
01196
01197 __add_snap_item_signal = Signal(str)
01198 __remove_snap_item_signal = Signal(str)
01199 __set_snap_item_settings_signal = Signal(str, object, object, object, object)
01200 __set_snap_item_attributes_signal = Signal(str, SnapItemAttributes)
01201
01202 def __init__(self):
01203 super(QtView, self).__init__(None)
01204 View.__init__(self)
01205
01206
01207 self.setDragMode(QGraphicsView.ScrollHandDrag)
01208 self.setScene(QGraphicsScene(self))
01209
01210
01211 self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)
01212
01213
01214 self.layout_manager = LayoutManagerWidget(self)
01215 self.scene().addItem(self.layout_manager)
01216
01217
01218 self.__update_view_signal.connect(self.layout_manager.link)
01219 self.__add_block_item_signal.connect(self.layout_manager.add_block_item)
01220 self.__remove_block_item_signal.connect(self.layout_manager.remove_block_item)
01221 self.__set_block_item_settings_signal.connect(self.layout_manager.set_block_item_settings)
01222 self.__set_block_item_attributes_signal.connect(self.layout_manager.set_block_item_attributes)
01223 self.__add_band_item_signal.connect(self.layout_manager.add_band_item)
01224 self.__remove_band_item_signal.connect(self.layout_manager.remove_band_item)
01225 self.__set_band_item_settings_signal.connect(self.layout_manager.set_band_item_settings)
01226 self.__set_band_item_attributes_signal.connect(self.layout_manager.set_band_item_attributes)
01227 self.__add_snap_item_signal.connect(self.layout_manager.add_snap_item)
01228 self.__remove_snap_item_signal.connect(self.layout_manager.remove_snap_item)
01229 self.__set_snap_item_settings_signal.connect(self.layout_manager.set_snap_item_settings)
01230 self.__set_snap_item_attributes_signal.connect(self.layout_manager.set_snap_item_attributes)
01231 self.resize(1024,768)
01232 QColor.setAllowX11ColorNames(True)
01233 if not QColor.allowX11ColorNames():
01234 rospy.logwarn("Coloring will not work properly")
01235 self.show()
01236
01237 def update_view(self):
01238 self.__update_view_signal.emit()
01239
01240 def add_block_item(self, index):
01241 """ Allows the adapter to create a new BlockItem """
01242 self.__add_block_item_signal.emit(index)
01243
01244 def has_block_item(self, index):
01245 return self.layout_manager.has_block_item(index)
01246
01247 def remove_block_item(self, index):
01248 self.__remove_block_item_signal.emit(index)
01249
01250 def set_block_item_settings(self, index, left_index, right_index):
01251 return self.__set_block_item_settings_signal.emit(index, left_index, right_index)
01252
01253 def set_block_item_attributes(self, index, attributes):
01254 self.__set_block_item_attributes_signal.emit(index, attributes)
01255
01256 def add_band_item(self, altitude, rank):
01257 """ Create a new drawable object to correspond to a Band. """
01258 self.__add_band_item_signal.emit(altitude, rank)
01259
01260 def has_band_item(self, altitude):
01261 return self.layout_manager.has_band_item(altitude)
01262
01263 def remove_band_item(self, altitude):
01264 """ Remove the drawable object to correspond to a band """
01265 self.__remove_band_item_signal.emit(altitude)
01266
01267 def set_band_item_settings(self, altitude, rank, top_band_alt, bot_band_alt,
01268 leftmost_snapkey, rightmost_snapkey):
01269 self.__set_band_item_settings_signal.emit(altitude, rank, top_band_alt, bot_band_alt, leftmost_snapkey, rightmost_snapkey)
01270
01271 def set_band_item_attributes(self, altitude, attributes):
01272 self.__set_band_item_attributes_signal.emit(altitude, attributes)
01273
01274 def add_snap_item(self, snapkey):
01275 self.__add_snap_item_signal.emit(snapkey)
01276
01277 def has_snap_item(self, snapkey):
01278 return self.layout_manager.has_snap_item(snapkey)
01279
01280 def remove_snap_item(self, snapkey):
01281 self.__remove_snap_item_signal.emit(snapkey)
01282
01283 def set_snap_item_settings(self, snapkey, left_order, right_order, pos_band_alt, neg_band_alt):
01284 self.__set_snap_item_settings_signal.emit(snapkey, left_order, right_order, pos_band_alt, neg_band_alt)
01285
01286 def set_snap_item_attributes(self, snapkey, attributes):
01287 self.__set_snap_item_attributes_signal.emit(snapkey, attributes)
01288
01289 def wheelEvent(self,event):
01290 """ Implements scrollwheel zooming """
01291 self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
01292 scaleFactor = 1.15
01293 if event.delta() > 0:
01294 self.scale(scaleFactor, scaleFactor)
01295 else:
01296 self.scale(1.0/scaleFactor, 1.0/scaleFactor)
01297
01298
01299
01300
01301
01302
01303
01304 class DuplicateItemExistsError(Exception):
01305 """ An Item with the specified parameters already exists """
01306 pass