OpenStructure
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
gradient_editor_widget.py
Go to the documentation of this file.
1 #------------------------------------------------------------------------------
2 # This file is part of the OpenStructure project <www.openstructure.org>
3 #
4 # Copyright (C) 2008-2011 by the OpenStructure authors
5 #
6 # This library is free software; you can redistribute it and/or modify it under
7 # the terms of the GNU Lesser General Public License as published by the Free
8 # Software Foundation; either version 3.0 of the License, or (at your option)
9 # any later version.
10 # This library is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 # details.
14 #
15 # You should have received a copy of the GNU Lesser General Public License
16 # along with this library; if not, write to the Free Software Foundation, Inc.,
17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 #------------------------------------------------------------------------------
19 # -*- coding: utf-8 -*-
20 
21 from ost import gui
22 from ost import gfx
23 from ost import mol
24 from PyQt4 import QtCore, QtGui
25 from color_select_widget import ColorSelectWidget
26 from gradient_preset_widget import GradientPresetWidget
27 
28 #Gradient Editor
29 class GradientEditor(QtGui.QWidget):
30  def __init__(self, parent=None):
31  QtGui.QWidget.__init__(self, parent)
32  self.parent_ = parent
33 
34  #Create Ui elements
35  gradient_label = QtGui.QLabel("Gradient Editor")
36  font = gradient_label.font()
37  font.setBold(True)
38 
39  self.prop_combo_box_ = QtGui.QComboBox()
42  self.gradient_preset_ = GradientPresetWidget(self.gradient_edit_)
43 
44  self.prop_combo_box_.addItem("atom B-factor")
45  self.prop_combo_box_.addItem("average residue B-factor")
46  self.prop_combo_box_.addItem("X-Coordinate")
47  self.prop_combo_box_.addItem("Y-Coordinate")
48  self.prop_combo_box_.addItem("Z-Coordinate")
49  self.prop_combo_box_.addItem("Residue Number")
50  self.prop_combo_box_.addItem("Atom Charge")
51 
52  self.props=["abfac","rbfac","x","y","z","rnum","acharge"]
53 
54  grid = QtGui.QGridLayout()
55  grid.setContentsMargins(0,5,0,0)
56  grid.addWidget(gradient_label, 0, 0, 1, 1)
57  grid.addWidget(self.prop_combo_box_, 1, 0, 1, 1)
58  grid.addWidget(self.gradient_preview_, 2, 0, 1, 1)
59  grid.addWidget(self.gradient_edit_, 3, 0, 1, 1)
60  grid.setRowStretch(4, 1)
61  grid.addWidget(self.gradient_preset_, 5, 0, 1, 1)
62  self.setLayout(grid)
63 
64  QtCore.QObject.connect(self.prop_combo_box_, QtCore.SIGNAL("currentIndexChanged(int)"), self.Update)
65  QtCore.QObject.connect(self.gradient_edit_, QtCore.SIGNAL("gradientUpdated"), self.Update)
66  QtCore.QObject.connect(self.gradient_preset_, QtCore.SIGNAL("gradientSelected"), self.gradient_edit_.LoadGradient)
67 
68  self.setMinimumSize(250,300)
69 
70  def Update(self):
71  scene_selection = gui.SceneSelection.Instance()
72  for i in range(0,scene_selection.GetActiveNodeCount()):
73  node = scene_selection.GetActiveNode(i)
74  self.ChangeColor(node)
75 
76  if(scene_selection.GetActiveViewCount() > 0):
77  entity = scene_selection.GetViewEntity()
78  view = scene_selection.GetViewUnion()
79  self.ChangeViewColor(entity,view)
80 
81  def ChangeColor(self,node):
82  if isinstance(node, gfx.Entity) or isinstance(node, gfx.Surface):
83  node.CleanColorOps()
84  if self.parent_.GetCarbonsOnly():
85  node.ColorBy(self.props[self.prop_combo_box_.currentIndex()],
86  self.gradient_edit_.GetGfxGradient(), "ele=C")
87  else:
88  node.ColorBy(self.props[self.prop_combo_box_.currentIndex()],
89  self.gradient_edit_.GetGfxGradient())
90 
91  def ChangeViewColor(self, entity, view):
92  if isinstance(entity, gfx.Entity) and isinstance(view, mol.EntityView):
93  if self.parent_.GetCarbonsOnly():
94  glco=gfx.GradientLevelColorOp(mol.QueryViewWrapper(mol.Query("ele=C"),view),self.props[self.prop_combo_box_.currentIndex()],self.gradient_edit_.GetGfxGradient(),mol.Prop.Level.UNSPECIFIED)
95  else:
96  glco=gfx.GradientLevelColorOp(mol.QueryViewWrapper(view),self.props[self.prop_combo_box_.currentIndex()],self.gradient_edit_.GetGfxGradient(),mol.Prop.Level.UNSPECIFIED)
97  entity.Apply(glco)
98 
99 #Gradient Preview
100 class GradientPreview(QtGui.QWidget):
101  def __init__(self, parent=None):
102  QtGui.QWidget.__init__(self, parent)
103 
104  #Defaults
105  self.border_offset_ = 3
106  self.preview_height_ = 25
107  QtGui.QWidget.__init__(self, parent)
108 
109  self.gradient_ = QtGui.QLinearGradient()
110 
111  #Ui
112  self.setMinimumSize(0, self.preview_height_ + 4)
113 
114  def SetGradient(self, gradient):
115  self.gradient_ = gradient
116  self.update()
117 
118  def paintEvent(self, event):
119  if self.isEnabled() and self.gradient_ is not None:
120  size = self.size()
121  paint = QtGui.QPainter()
122  if paint.begin(self):
123  brush = QtGui.QBrush(self.gradient_)
124  paint.setBrush(brush)
125  paint.drawRect(self.border_offset_,
126  self.border_offset_,
127  size.width() - 2 * self.border_offset_,
128  self.preview_height_)
129  paint.end()
130 
131 #Gradient Edit
132 class GradientEdit(QtGui.QWidget):
133  def __init__(self, gradient_preview, parent=None):
134  QtGui.QWidget.__init__(self, parent)
135 
136  #Defaults
137  self.gradient_preview_ = gradient_preview
138  self.border_offset_ = self.gradient_preview_.border_offset_
139  self.edit_height_ = 20
140 
141  #Stops
142  self.stops = list()
143 
144 
145  #ContextMenu
146  self.add_ = QtGui.QAction("Add", self)
147  QtCore.QObject.connect(self.add_, QtCore.SIGNAL("triggered()"), self.Add)
148  self.addAction(self.add_)
149  self.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
150 
151  #Ui
152  pal = QtGui.QPalette(self.palette())
153  pal.setColor(QtGui.QPalette.Window, QtGui.QColor(255, 255, 255, 128))
154  self.setPalette(pal)
155  self.setAutoFillBackground(True)
156  self.gradient_ = QtGui.QLinearGradient()
157 
158  self.setMinimumSize(0, self.edit_height_)
159 
160  #Add Points
161  self.AddStop(self.border_offset_+3, QtGui.QColor("Red"))
162  self.AddStop(self.width()-(self.border_offset_+3), QtGui.QColor("Green"))
163 
164  #Width Problem
165  self.width_ = self.width()
166 
167  def RemoveStop(self, stop):
168  self.stops.remove(stop)
169  stop.hide()
170  del(stop)
171 
172  self.UpdateGradient()
173  self.emit(QtCore.SIGNAL("gradientUpdated"),(self))
174 
175  def RemoveStopGui(self, stop):
176  if(len(self.stops)>2):
177  self.RemoveStop(stop)
178  else:
179  QtGui.QMessageBox.question(self, "Information", "Please keep in mind, at least two stops are needed for a gradient!")
180 
181  def AddStop(self, pos, color=None):
182  stop = MyGradientStop(pos, self.border_offset_, self, color)
183  QtCore.QObject.connect(stop, QtCore.SIGNAL("gradientChanged"), self.UpdateGradient)
184  QtCore.QObject.connect(stop, QtCore.SIGNAL("colorChanged"), self.UpdateGradient)
185  QtCore.QObject.connect(stop, QtCore.SIGNAL("colorChanged"), self.parent().Update)
186  QtCore.QObject.connect(stop, QtCore.SIGNAL("gradientUpdated"), self.parent().Update)
187  QtCore.QObject.connect(stop, QtCore.SIGNAL("removeStop"), self.RemoveStopGui)
188 
189  self.stops.append(stop)
190  self.UpdateGradient()
191  self.emit(QtCore.SIGNAL("gradientUpdated"),(self))
192 
193  def Add(self):
194  self.AddStop(QtGui.QCursor.pos().x() - self.mapToGlobal(QtCore.QPoint(0, 0)).x())
195 
196  def UpdateGradient(self):
197  self.gradient_preview_.SetGradient(self.GetGradient())
198 
199  def GetGfxGradient(self):
200  gradient = gfx.Gradient()
201  for s in self.stops:
202  c=s.GetColor();
203  gradient.SetColorAt(s.GetRel(), gfx.RGB(c.redF(), c.greenF(), c.blueF()));
204  return gradient;
205 
206  def GetGradient(self):
207  gradient = QtGui.QLinearGradient(self.border_offset_,
208  0,
209  self.size().width() - 2 * self.border_offset_,
210  0)
211  for s in self.stops:
212  gradient.setColorAt(s.GetRel(), s.GetColor())
213  return gradient
214 
215  def LoadGradient(self, gradient):
216  stopcpy = self.stops[:]
217  for stop in stopcpy:
218  self.RemoveStop(stop)
219 
220  gradStops = gradient.stops()
221  for stop in gradStops:
222  self.AddStop((self.width()-(2*self.border_offset_))*stop[0], stop[1])
223 
224  #Overwritten methods
225  def mouseDoubleClickEvent(self, event):
226  self.AddStop(event.x())
227 
228  def resizeEvent(self, event):
229  factor = 1/(float(self.width_)/event.size().width())
230  if(factor >=0):
231  for s in self.stops:
232  s.SetPos(s.GetPos() * factor)
233  self.UpdateGradient()
234  self.width_ = event.size().width()
235 
236 #Gradient Stop
237 class MyGradientStop(ColorSelectWidget):
238  def __init__(self, pos, offset, parent, color=None):
239  #Defaults
240  self.length_ = 20
241  self.halflength_ = self.length_ / 2
242 
243  self.pos_ = pos
244  self.offset_ = offset
245 
246  ColorSelectWidget.__init__(self, self.length_,self.length_, color, parent)
247 
248  self.MoveToNewPos()
249 
250  if(color is None):
251  self.color_ = QtGui.QColor("White")
252  self.ChangeColor()
253  else:
254  self.color_ = color
255 
256  #ContextMenu
257  self.remove_ = QtGui.QAction("Remove", self)
258  QtCore.QObject.connect(self.remove_, QtCore.SIGNAL("triggered()"), self.Remove)
259  self.addAction(self.remove_)
260 
261  def Remove(self):
262  self.emit(QtCore.SIGNAL("removeStop"),(self))
263 
264  def GetPos(self):
265  return self.pos_
266 
267  def SetPos(self, pos):
268  self.pos_ = pos
269  self.MoveToNewPos()
270 
271  def GetRel(self):
272  rel = self.pos_ / float(self.parent().width() - 2 * self.offset_)
273  if rel > 1:
274  return 1
275  elif rel < 0:
276  return 0
277  return rel
278 
279  def MoveToNewPos(self):
280  self.move(self.pos_ - self.halflength_, 0)
281  self.update()
282  self.emit(QtCore.SIGNAL("gradientChanged"))
283 
284  def mouseMoveEvent(self, event):
285  self.pos_ += event.pos().x() - self.halflength_
286  if self.pos_ <= self.offset_:
287  self.pos_ = self.offset_ + 1
288  elif self.pos_ >= self.parent().width() - 2*self.offset_:
289  self.pos_ = self.parent().width() - (2*self.offset_ + 1)
290  self.MoveToNewPos()
291 
292  def mouseDoubleClickEvent(self, event):
293  self.ChangeColor()
294 
295  def mouseReleaseEvent(self, entity):
296  if entity.button() == QtCore.Qt.LeftButton:
297  self.emit(QtCore.SIGNAL("gradientUpdated"))