CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
SplitterTab.py
Go to the documentation of this file.
1 import logging
2 
3 from PyQt4.QtCore import Qt, SIGNAL, QCoreApplication, QEvent, QSize
4 from PyQt4.QtGui import QSplitter, QColor, QPalette, QToolBar, QSizePolicy, QWidget, QFrame, QHeaderView, QStandardItemModel, QVBoxLayout
5 
6 from Vispa.Main.AbstractTab import AbstractTab
7 from Vispa.Views.PropertyView import PropertyView
8 
9 class SplitterTab(QSplitter, AbstractTab):
10  """ A Tab with a QSplitter and a function to create the PropertyView.
11 
12  The Tab is split vertically and within horizontally. QWidgets can be added
13  to verticalSplitter() and horizontalSplitter(). In the constructor
14  one can choose whether the PropertyView shall be on top level or inside
15  the horizontalSplitter().
16  """
17  def __init__(self, parent=None, topLevelPropertyView=False):
18  logging.debug(__name__ + ": __init__")
19  self._topLevelPropertyView=topLevelPropertyView
20  AbstractTab.__init__(self)
21  if self._topLevelPropertyView:
22  QSplitter.__init__(self, Qt.Horizontal, parent)
23  self._verticalSplitter = QSplitter(Qt.Vertical, self)
24  else:
25  QSplitter.__init__(self, Qt.Vertical, parent)
26  self._verticalSplitter = self
27 
28  self._horizontalSplitter = QSplitter(Qt.Horizontal, self._verticalSplitter)
29 
30  self.connect(self._verticalSplitter, SIGNAL("splitterMoved(int, int)"), self.verticalSplitterMovedSlot)
31  self.connect(self._horizontalSplitter, SIGNAL("splitterMoved(int, int)"), self.horizontalSplitterMovedSlot)
32  if self._topLevelPropertyView:
33  self.connect(self, SIGNAL("splitterMoved(int, int)"), self.horizontalSplitterMovedSlot)
34  self._toolBar = None
35 
36  self._propertyView = None
37 
38  def verticalSplitter(self):
39  return self._verticalSplitter
40 
41  def verticalSplitterMovedSlot(self, pos, index):
42  """ Implement this function if you want to react on size changes invoked by the vertical splitter.
43  """
44  pass
45 
46  def horizontalSplitter(self):
47  return self._horizontalSplitter
48 
49  def horizontalSplitterMovedSlot(self, pos, index):
50  """ Implement this function if you want to react on size changes invoked by the horizontal splitter.
51  """
52  pass
53 
54  def createToolBar(self,index=None):
55  if index==None:
56  index = self.verticalSplitter().count()
57  self._toolBar = SplitterToolBar()
58  self.verticalSplitter().insertWidget(index,self._toolBar)
59  self.verticalSplitter().setCollapsible(index, False)
60  self._toolBar.setFixedHeight(20)
61  self._toolBar.show()
62 
63  def toolBar(self):
64  return self._toolBar
65 
66  def setController(self, controller):
67  AbstractTab.setController(self, controller)
68  if self._propertyView:
69  self._propertyView.setReadOnly(not self.controller().isEditable())
70  self.connect(self._propertyView, SIGNAL('valueChanged'), self.controller().setModified)
71 
72  def createPropertyView(self):
73  """ Creates PropertyView object, adds it to this tab and makes it available via propertyView().
74  """
75  if self._topLevelPropertyView:
76  parent=self
77  else:
78  parent=self.horizontalSplitter()
79  self._propertyView = PropertyView(parent, "PropertyView")
80 
81  def propertyView(self):
82  """ Returns PropertyView object. See createPropertyView().
83  """
84  return self._propertyView
85 
86  def closeEvent(self,event):
87  """ Call close if tab is not embedded in TabWidget
88  """
89  if not self._tabWidget and self.mainWindow().isTabWidget(self):
90  if not self.controller().close():
91  event.ignore()
92  else:
93  event.accept()
94  else:
95  event.accept()
96 
97  def event(self,event):
98  """ Call tabChanged if window is activated.
99  """
100  if not self._tabWidget:
101  if event.type()==QEvent.WindowActivate:
102  QCoreApplication.instance().tabChanged()
103  return QSplitter.event(self,event)
104 
105 
106 class SplitterToolBar(QToolBar):
107  """ A vertical toolbar which can be split up in sections.
108 
109  The toolbar can be placed in the verticalSplitter() of the SplitterTab
110  to separate two parts. The toolbar can hold buttons to control its
111  neighboring views.
112  """
113 
114  ALIGNMENT_LEFT = 0
115  ALIGNMENT_CENTER = 1
116  ALIGNMENT_RIGHT = 2
117 
118  def __init__(self, parent=None):
119  self._sections = []
120  self._sizes = None
121  QToolBar.__init__(self, parent)
122  self.layout().setSpacing(0)
123 
124  def _createSpacer(self, width=0):
125  spacer = QWidget(self)
126  spacer.setFixedSize(width, self.iconSize().height())
127  return spacer
128 
129  def addSection(self, alignment=None):
130  if alignment == None:
131  alignment = self.ALIGNMENT_CENTER
132 
133  leftSpacer = self._createSpacer()
134  rightSpacer = self._createSpacer()
135  contentList = []
136  leftSpacerAction = self.addWidget(leftSpacer)
137  rightSpacerAction = self.addWidget(rightSpacer)
138  section = {"leftSpacer": leftSpacer, "leftSpacerAction": leftSpacerAction,
139  "contentList": contentList,
140  "rightSpacer": rightSpacer, "rightSpacerAction": rightSpacerAction,
141  "alignment": alignment}
142 
143  self._sections.append(section)
144  if self._sizes:
145  self.setSectionSizes(self._sizes)
146  return len(self._sections) - 1
147 
148  def addWidgetToSection(self, widget, section):
149  if section > len(self._sections) - 1:
150  logging.error(self.__class__.__name__ +": addWidgetToSection() - Unknown section number %d. Aborting..." % section)
151  return
152 
153  widget.show()
154  self._sections[section]["contentList"].append(widget)
155  self.insertWidget(self._sections[section]["rightSpacerAction"], widget)
156  # TODO: implement remove function
157  if self._sizes:
158  self.setSectionSizes(self._sizes)
159 
160  def setSectionSizes(self, sizes):
161  """ sizes is list of widths for section spacers.
162  """
163  self._sizes = sizes # try to fix design, need to find better solution
164  for i in range(min(len(self._sections), len(sizes))):
165  section = self._sections[i]
166  contentsWidth = 0
167  for content in section["contentList"]:
168  contentsWidth += content.width() + self.layout().spacing() + 1
169  if section["alignment"] == self.ALIGNMENT_LEFT:
170  rightWidth = sizes[i] - contentsWidth
171  leftWidth = 0
172  elif section["alignment"] == self.ALIGNMENT_RIGHT:
173  contentsWidth += self.layout().spacing() * 2
174  rightWidth = 0
175  leftWidth = sizes[i] - contentsWidth
176  else:
177  # Default is ALIGNMENT_CENTER
178  leftWidth = 0.5 * (sizes[i] - contentsWidth)
179  rightWidth = leftWidth
180  section["leftSpacer"].setFixedSize(max(0, leftWidth), self.iconSize().height())
181  section["rightSpacer"].setFixedSize(max(0, rightWidth), self.iconSize().height())
182 
183  def takeToolBoxContainerButtons(self, toolBox, section):
184  for button in toolBox.toggleButtons():
185  self.addWidgetToSection(button, section)
186 
187  def showEvent(self, event):
188  QToolBar.showEvent(self, event)
189  if self._sizes:
190  self.setSectionSizes(self._sizes)
const T & max(const T &a, const T &b)