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-2020 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 PyQt5 import QtCore, QtGui, QtWidgets
25 from .color_select_widget import ColorSelectWidget
26 from .gradient_preset_widget import GradientPresetWidget
27 
28 #Gradient Editor
29 class GradientEditor(QtWidgets.QWidget):
30  def __init__(self, parent=None):
31  QtWidgets.QWidget.__init__(self, parent)
32  self.parent_ = parent
33 
34  #Create Ui elements
35  gradient_label = QtWidgets.QLabel("Gradient Editor")
36  font = gradient_label.font()
37  font.setBold(True)
38 
39  self.prop_combo_box_ = QtWidgets.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 = QtWidgets.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  self.prop_combo_box_.currentIndexChanged.connect(self.Update)
65  self.gradient_edit_.gradientUpdated.connect(self.Update)
66  self.gradient_preset_.gradientSelected.connect(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(QtWidgets.QWidget):
101  def __init__(self, parent=None):
102  QtWidgets.QWidget.__init__(self, parent)
103 
104  #Defaults
105  self.border_offset_ = 3
106  self.preview_height_ = 25
107  QtWidgets.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(QtWidgets.QWidget):
133 
134  gradientUpdated = QtCore.pyqtSignal()
135 
136  def __init__(self, gradient_preview, parent=None):
137  QtWidgets.QWidget.__init__(self, parent)
138 
139  #Defaults
140  self.gradient_preview_ = gradient_preview
141  self.border_offset_ = self.gradient_preview_.border_offset_
142  self.edit_height_ = 20
143 
144  #Stops
145  self.stops = list()
146 
147 
148  #ContextMenu
149  self.add_ = QtWidgets.QAction("Add", self)
150  self.add_.triggered.connect(self.Add)
151  self.addAction(self.add_)
152  self.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
153 
154  #Ui
155  pal = QtGui.QPalette(self.palette())
156  pal.setColor(QtGui.QPalette.Window, QtGui.QColor(255, 255, 255, 128))
157  self.setPalette(pal)
158  self.setAutoFillBackground(True)
159  self.gradient_ = QtGui.QLinearGradient()
160 
161  self.setMinimumSize(0, self.edit_height_)
162 
163  #Add Points
164  self.AddStop(self.border_offset_+3, QtGui.QColor("Red"))
165  self.AddStop(self.width()-(self.border_offset_+3), QtGui.QColor("Green"))
166 
167  #Width Problem
168  self.width_ = self.width()
169 
170  def RemoveStop(self, stop):
171  self.stops.remove(stop)
172  stop.hide()
173  del(stop)
174 
175  self.UpdateGradient()
176  self.gradientUpdated.emit()
177 
178  def RemoveStopGui(self, stop):
179  if(len(self.stops)>2):
180  self.RemoveStop(stop)
181  else:
182  QtWidgets.QMessageBox.question(self, "Information", "Please keep in mind, at least two stops are needed for a gradient!")
183 
184  def AddStop(self, pos, color=None):
185  stop = MyGradientStop(pos, self.border_offset_, self, color)
186  stop.gradientChanged.connect(self.UpdateGradient)
187  stop.colorChanged.connect(self.UpdateGradient)
188  stop.colorChanged.connect(self.parent().Update)
189  stop.gradientUpdated.connect(self.parent().Update)
190  stop.removeStop.connect(self.RemoveStopGui)
191  stop.MoveToNewPos()
192 
193  self.stops.append(stop)
194  self.UpdateGradient()
195  self.gradientUpdated.emit()
196 
197  def Add(self):
198  self.AddStop(QtWidgets.QCursor.pos().x() - self.mapToGlobal(QtCore.QPoint(0, 0)).x())
199 
200  def UpdateGradient(self):
201  self.gradient_preview_.SetGradient(self.GetGradient())
202 
203  def GetGfxGradient(self):
204  gradient = gfx.Gradient()
205  for s in self.stops:
206  c=s.GetColor();
207  gradient.SetColorAt(s.GetRel(), gfx.RGB(c.redF(), c.greenF(), c.blueF()));
208  return gradient;
209 
210  def GetGradient(self):
211  gradient = QtGui.QLinearGradient(self.border_offset_,
212  0,
213  self.size().width() - 2 * self.border_offset_,
214  0)
215  for s in self.stops:
216  gradient.setColorAt(s.GetRel(), s.GetColor())
217  return gradient
218 
219  def LoadGradient(self, gradient):
220  stopcpy = self.stops[:]
221  for stop in stopcpy:
222  self.RemoveStop(stop)
223 
224  gradStops = gradient.stops()
225  for stop in gradStops:
226  self.AddStop((self.width()-(2*self.border_offset_))*stop[0], stop[1])
227 
228  #Overwritten methods
229  def mouseDoubleClickEvent(self, event):
230  self.AddStop(event.x())
231 
232  def resizeEvent(self, event):
233  factor = 1/(float(self.width_)/event.size().width())
234  if(factor >=0):
235  for s in self.stops:
236  s.SetPos(s.GetPos() * factor)
237  self.UpdateGradient()
238  self.width_ = event.size().width()
239 
240 #Gradient Stop
241 class MyGradientStop(ColorSelectWidget):
242 
243  removeStop = QtCore.pyqtSignal()
244  gradientChanged = QtCore.pyqtSignal()
245  gradientUpdated = QtCore.pyqtSignal()
246 
247  def __init__(self, pos, offset, parent, color=None):
248  #Defaults
249  self.length_ = 20
250  self.halflength_ = self.length_ / 2
251 
252  self.pos_ = pos
253  self.offset_ = offset
254 
255  ColorSelectWidget.__init__(self, self.length_,self.length_, color, parent)
256 
257  if(color is None):
258  self.color_ = QtGui.QColor("White")
259  self.ChangeColor()
260  else:
261  self.color_ = color
262 
263  #ContextMenu
264  self.remove_ = QtWidgets.QAction("Remove", self)
265  self.remove_.triggered.connect(self.Remove)
266  self.addAction(self.remove_)
267 
268  def Remove(self):
269  self.removeStop.emit()
270 
271  def GetPos(self):
272  return self.pos_
273 
274  def SetPos(self, pos):
275  self.pos_ = pos
276  self.MoveToNewPos()
277 
278  def GetRel(self):
279  rel = self.pos_ / float(self.parent().width() - 2 * self.offset_)
280  if rel > 1:
281  return 1
282  elif rel < 0:
283  return 0
284  return rel
285 
286  def MoveToNewPos(self):
287  self.move(int(self.pos_ - self.halflength_), 0)
288  self.update()
289  self.gradientChanged.emit()
290 
291  def mouseMoveEvent(self, event):
292  self.pos_ += event.pos().x() - self.halflength_
293  if self.pos_ <= self.offset_:
294  self.pos_ = self.offset_ + 1
295  elif self.pos_ >= self.parent().width() - 2*self.offset_:
296  self.pos_ = self.parent().width() - (2*self.offset_ + 1)
297  self.MoveToNewPos()
298 
299  def mouseDoubleClickEvent(self, event):
300  self.ChangeColor()
301 
302  def mouseReleaseEvent(self, entity):
303  if entity.button() == QtCore.Qt.LeftButton:
304  self.gradientUpdated.emit()
graphical rendering of mol::EntityHandle entites
Definition: entity.hh:60
Selection Query.
Definition: query.hh:74
definition of EntityView
Definition: entity_view.hh:86
color gradient
Definition: gradient.hh:59