CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
MenuWidget.py
Go to the documentation of this file.
1 from PyQt4.QtCore import Qt, QSize, SIGNAL, QEvent, QPointF
2 from PyQt4.QtGui import QColor, QPen, QBrush, QRadialGradient
3 
4 import logging
5 
6 from Vispa.Gui.VispaWidget import VispaWidget, TextField
7 
9 
10  # inherited properties
11  HEIGHT = 30
12  BACKGROUND_SHAPE = 'ROUNDRECT'
13  ROUNDRECT_RADIUS = 10
14 
15  PEN_COLOR = QColor(242, 230, 242)
16  FILL_COLOR1 = QColor(59, 59, 59, 200)
17  #FILL_COLOR2 = QColor(242, 230, 242)
18  TITLE_COLOR = QColor(Qt.white)
19 
20  AUTOSIZE = True
21  AUTOSIZE_KEEP_ASPECT_RATIO = False
22  SELECTABLE_FLAG = False
23  USE_BACKGROUND_GRADIENT_FLAG = False
24 
25  # new properties
26  HOVER_COLOR1 = QColor(0, 0, 240)
27  HOVER_COLOR2 = QColor(0, 0, 200)
28 
29  def __init__(self, parent=None, associatedWidget=None, orientation=Qt.Horizontal):
30  """ Constructor
31  """
32  logging.debug("%s: Constructor" % self.__class__.__name__)
33  self._cursorEntered = False
34 
36  self._menuEntrySlots = []
37  self._hoverEntry = None
38 
39  self._spacer = TextField()
40 
41  VispaWidget.__init__(self, parent)
42  self.hide()
43  self._associatedWidget = associatedWidget
44  self.setMouseTracking(True)
45  self.setDragable(False)
46  #self._hoverBrush = QBrush(self.HOVER_COLOR1)
47  self._hoverGradient = QRadialGradient()
48  self._hoverGradient.setColorAt(0, self.HOVER_COLOR1)
49  self._hoverGradient.setColorAt(1, self.HOVER_COLOR2)
50  #self._hoverBrush = QBrush(self.HOVER_COLOR1)
51 
52  self._spacer.setFontSizeRange(self.TEXTFIELD_FONTSIZE_MIN, self.TEXTFIELD_FONTSIZE_MAX)
53  #self._textField.setDefaultWidth(self.getDistance('textFieldWidth', 1, True))
54  #entry.setDefaultHeight(self.getDistance('textFieldHeight', 1, True))
55  self._spacer.setDefaultFontSize(self.TEXTFIELD_FONTSIZE)
56  self._spacer.setAutosizeFont(self.TEXTFIELD_AUTOSIZE_FONT_FLAG)
57  self._spacer.setAutotruncate(self.TEXTFIELD_AUTOTRUNCATE_TEXT_FLAG)
58  self._spacer.setAutoscale(True, False)
59  self._spacer.setPenColor(self.TITLE_COLOR)
60  self._spacer.setFont(self.font())
61  self._spacer.setText(" | ")
62  self._spacer.calculateDimensions()
63 
64  def addEntry(self, name, slot=None):
65  entry = TextField()
66  entry.setFontSizeRange(self.TEXTFIELD_FONTSIZE_MIN, self.TEXTFIELD_FONTSIZE_MAX)
67  #self._textField.setDefaultWidth(self.getDistance('textFieldWidth', 1, True))
68  #entry.setDefaultHeight(self.getDistance('textFieldHeight', 1, True))
69  entry.setDefaultFontSize(self.TEXTFIELD_FONTSIZE)
70  entry.setAutosizeFont(self.TEXTFIELD_AUTOSIZE_FONT_FLAG)
71  entry.setAutotruncate(self.TEXTFIELD_AUTOTRUNCATE_TEXT_FLAG)
72  entry.setAutoscale(True, False)
73  entry.setPenColor(self.TITLE_COLOR)
74  entry.setFont(self.font())
75  entry.setText(name)
76  entry.calculateDimensions()
77  self._menuEntryTextFields.append(entry)
78  self._menuEntrySlots.append(slot)
79 
81  return entry
82 
83  def removeEntry(self, entry):
84  if entry in self._menuEntryTextFields:
85  index = self._menuEntryTextFields.index(entry)
86  self._menuEntryTextFields.remove(entry)
87  self._menuEntrySlots.pop(index)
88 
89  def setEntryText(self, entry, text):
90  if entry in self._menuEntryTextFields:
91  entry.setText(text)
92  entry.calculateDimensions()
94 
95  def len(self):
96  return len(self._menuEntryTextFields)
97 
98  def entry(self, index):
99  if len(self._menuEntryTextFields) >= index + 1:
100  return self._menuEntryTextFields[index]
101  return None
102 
103  def sizeHint(self):
104  """ Calculates needed space for widget content.
105  """
106  self._scaleWidth = 1 # for getDistance()
107  self._scaleHeight = 1
108 
109  neededWidth = self.getDistance('leftMargin', 1) + self.getDistance('rightMargin', 1)
110  neededHeight = self.getDistance('topMargin', 1) + self.getDistance('bottomMargin', 1)
111 
112  textFieldWidth = 0
113  textFieldHeight = 0
114  for entry in self._menuEntryTextFields:
115  textFieldWidth += entry.getWidth()
116  textFieldHeight = max(textFieldHeight, entry.getHeight())
117  textFieldWidth += max(0, (len(self._menuEntryTextFields) -1) * self._spacer.getWidth())
118 
119  neededWidth += textFieldWidth
120  neededHeight += textFieldHeight
121 
122  # evaluate maximum size
123  maxWidth = self.maximumSize().width()
124  maxHeight = self.maximumSize().height()
125 
126  maxScaleWidth = min(1.0, 1.0 * maxWidth/neededWidth)
127  maxScaleHeight = min(1.0, 1.0 * maxHeight/neededHeight)
128  if maxScaleWidth != 1.0 or maxScaleHeight != 1.0:
129  # this is not limited by keepAspectRationFlag
130  # as it is about absolute sizes here
131  # ratio is evaluated in autosize()
132  scale = min(maxScaleWidth, maxScaleHeight)
133  neededWidth *= scale
134  neededHeight *= scale
135 
136  return QSize(max(self.minimumSize().width(), neededWidth), max(self.minimumSize().height(), neededHeight))
137 
138  def paint(self, painter, event=None):
139  """ Takes care of painting widget content on given painter.
140  """
141  VispaWidget.paint(self, painter, event)
142  self.drawMenuEntries(painter)
143 
144  def drawMenuEntries(self, painter):
145  """ Tells TextField object of text field to draw title on widget.
146  """
147  x = self.getDistance('textFieldX')
148  y = self.getDistance('textFieldY')
149  spacerWidth = self._spacer.getWidth() * self.zoomFactor()
150  originalPen = QPen()
151  painter.setPen(originalPen)
152  firstFlag = True
153  for entry in self._menuEntryTextFields:
154  if not firstFlag:
155  self._spacer.paint(painter, x, y, self.zoomFactor())
156  x += spacerWidth
157  if self._hoverEntry == entry:
158  hoverRectXOffset = 0.3 * spacerWidth
159  hoverRectYOffset = 0.3 * self.getDistance('topMargin')
160  hoverWidth = entry.getWidth() * self.zoomFactor() + 2 * hoverRectXOffset
161  hoverHeight = entry.getHeight() * self.zoomFactor() + 2 * hoverRectYOffset
162  #self._hoverGradient.setColorAt(0, self.HOVER_COLOR1)
163  #self._hoverGradient.setColorAt(1, self.HOVER_COLOR2)
164  self._hoverGradient.setCenter(QPointF(entry.getDrawRect(self.zoomFactor()).center()))
165  self._hoverGradient.setFocalPoint(QPointF(entry.getDrawRect(self.zoomFactor()).center()))
166  self._hoverGradient.setRadius(min(hoverWidth, hoverHeight))
167  #painter.setBrush(self._hoverBrush)
168  painter.setBrush(self._hoverGradient)
169  painter.setPen(Qt.NoPen)
170  #painter.drawRoundedRect(entry.getDrawRect(self.zoomFactor()), 10, 10)
171  painter.drawRoundedRect(x - hoverRectXOffset, y - hoverRectYOffset, hoverWidth, hoverHeight, 5, 5)
172  painter.setPen(originalPen)
173  entry.paint(painter, x, y, self.zoomFactor())
174  x += entry.getWidth() * self.zoomFactor()
175  firstFlag = False
176 
177  def mouseMoveEvent(self, event):
178  if bool(event.buttons() & Qt.LeftButton):
179  VispaWidget.mouseMoveEvent(self, event)
180  return
181  for entry in self._menuEntryTextFields:
182  if entry.getDrawRect(self.zoomFactor()).contains(event.pos()):
183  self._hoverEntry = entry
184  self.update()
185  break
186 
187  def mousePressEvent(self, event):
188  VispaWidget.mousePressEvent(self, event)
189  for i, entry in enumerate(self._menuEntryTextFields):
190  if self._menuEntrySlots[i] and entry.getDrawRect(self.zoomFactor()).contains(event.pos()):
191  self.hide()
192  self._menuEntrySlots[i]()
193  break
194 
195  def leaveEvent(self, event):
196  #logging.debug("%s: leaveEvent()" % self.__class__.__name__)
197  if not self._associatedWidget or self.parent().childAt(self.parent().mapFromGlobal(self.cursor().pos())) != self._associatedWidget:
198  self.hide()
199  self._hoverEntry = None
200  self.update()
201 
202  def hide(self):
203  VispaWidget.hide(self)
204  self._hoverEntry = None
205 
206  def showEvent(self, event):
207  VispaWidget.showEvent(self, event)
208  self._cursorEntered = False
209 
210  def enterEvent(self, event):
211  self._cursorEntered = True
212 
213  def cursorHasEntered(self):
214  return self._cursorEntered
bool contains(EventRange const &lh, EventID const &rh)
Definition: EventRange.cc:38
#define min(a, b)
Definition: mlp_lapack.h:161
const T & max(const T &a, const T &b)