# http://pyrocko.org - GPLv3 # # The Pyrocko Developers, 21st Century # ---|P------/S----------~Lg----------
QItemSelectionModel, QItemSelection, QPixmapCache, use_pyqt5
try: return float(val), True except (ValueError, TypeError): return 9e99, False
else: def toFloat(val): return val.toFloat()
'T', 'Time', 'M', 'Label', 'Depth [km]', 'Lat', 'Lon', 'Kind', 'Dist [km]', 'NSLCs', 'Polarity', 'Kagan Angle [deg]', 'Event Hash', 'MT']
qw.QWidget.__init__(self, *args, **kwargs) self.color = color self.moment_tensor = moment_tensor self.setGeometry(0, 0, 100, 100) self.setAttribute(qc.Qt.WA_TranslucentBackground)
self.flipy = qg.QTransform() self.flipy.translate(0, self.height()) self.flipy.scale(1, -1)
center = e.rect().center() painter = qg.QPainter(self) painter.save() painter.setWorldTransform(self.flipy) try: data = mt2beachball( self.moment_tensor, size=self.height()/2.2, position=(center.x(), center.y()), color_t=self.color, color_p=qc.Qt.white, edgecolor=qc.Qt.black) for pdata in data: paths, fill, edges, thickness = pdata
pen = qg.QPen(edges) pen.setWidthF(3) if fill != 'none': brush = qg.QBrush(fill) painter.setBrush(brush)
polygon = qg.QPolygonF() polygon = make_QPolygonF(*paths.T) painter.setRenderHint(qg.QPainter.Antialiasing) painter.setPen(pen) painter.drawPolygon(polygon) except BeachballError as e: logger.exception(e) finally: painter.restore()
try: return self.grab(self.rect()) except AttributeError: return qg.QPixmap().grabWidget(self, self.rect())
# Takes care of how table entries are displayed
mt = self.bb_data_from_index(index) if mt: key = ''.join([str(round(x, 1)) for x in mt.m6()]) pixmap = self.bbcache.cached(key) if pixmap: pixmap = pixmap.scaledToHeight(option.rect.height()) else: pixmap = BeachballWidget( moment_tensor=mt, color=qg.QColor(*tango_colors['scarletred3']) ).to_qpixmap() self.bbcache.insert(key, pixmap) a, b, c, d = option.rect.getRect() painter.save() painter.setRenderHint(qg.QPainter.Antialiasing) painter.drawPixmap(a+d/2., b, d, d, pixmap) painter.restore()
else:
else: return pv.markers[index.row()]
marker = self.marker_from_index(index) if isinstance(marker, EventMarker): return marker.get_event().moment_tensor else: return None
# Proxy object between view and model to handle sorting
'QTableView{selection-background-color: \ rgba(130, 130, 130, 100% );}')
'Latitude/Longitude', 'Kind', 'Distance [km]', 'NSLCs', 'Polarity', 'Kagan Angle [deg]', 'Event Hash', 'MT']
self.menu_labels, [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13]))
self.toggle_columns)
self.toggle_numbering)
self.show_context_menu)
if wheel_event.modifiers() & qc.Qt.ControlModifier: height = self.rowAt(self.height()) ci = self.indexAt( qc.QPoint(self.viewport().rect().x(), height)) v = self.verticalHeader()
if use_pyqt5: wheel_delta = wheel_event.angleDelta().y() else: wheel_delta = wheel_event.delta()
v.setDefaultSectionSize( max(12, v.defaultSectionSize()+wheel_delta//60)) self.scrollTo(ci) if v.isVisible(): self.toggle_numbering(False) self.toggle_numbering(True)
else: super(MarkerTableView, self).wheelEvent(wheel_event)
''' Set connected pile viewer and hook up signals. '''
# Propagate key_event to pile_viewer, unless up/down pressed
if key_event.key() in [qc.Qt.Key_Up, qc.Qt.Key_Down]: qw.QTableView.keyPressEvent(self, key_event) self.pile_viewer.go_to_selection() else: self.pile_viewer.keyPressEvent(key_event)
# Ignore mouse clicks pass
self.right_click_menu.popup(qg.QCursor.pos())
if want: self.verticalHeader().show() else: self.verticalHeader().hide()
from .qt_compat import qprint printer = qprint.QPrinter(qprint.QPrinter.ScreenResolution) printer.setOutputFormat(qprint.QPrinter.NativeFormat) printer_dialog = qprint.QPrintDialog(printer, self) if printer_dialog.exec_() == qw.QDialog.Accepted:
scrollbarpolicy = self.verticalScrollBarPolicy() self.setVerticalScrollBarPolicy(qc.Qt.ScrollBarAlwaysOff) rect = printer.pageRect() painter = qg.QPainter() painter.begin(printer) xscale = rect.width() / (self.width()*1.1) yscale = rect.height() / (self.height() * 1.1) scale = min(xscale, yscale) painter.translate(rect.x() + rect.width()/2., rect.y() + rect.height()/2.) painter.scale(scale, scale) painter.translate(-self.width()/2., -self.height()/2.) painter.setRenderHints(qg.QPainter.HighQualityAntialiasing | qg.QPainter.TextAntialiasing) self.render(painter) painter.end() self.setVerticalScrollBarPolicy(scrollbarpolicy)
if model_index.column() in self.editable_columns: return else: self.pile_viewer.go_to_selection()
''' Pop-up menu to toggle column visibility. '''
self.header_menu.popup(self.mapToGlobal(point))
''' Toggle columns depending in checked state. '''
self.viewport().update()
return self
''' Set connected pile viewer and hook up signals. '''
self.begin_markers_add) self.end_markers_add) self.begin_markers_remove) self.end_markers_remove)
''' Get header data entry. '''
elif orientation == qc.Qt.Vertical: if role == qc.Qt.DisplayRole: return qc.QVariant(str(col))
else: return qc.QVariant()
''' Get model data entry. '''
return qc.QVariant()
qg.QColor(*marker.select_color(g_color_b_faint)))
qg.QColor(*marker.select_color(g_color_b)))
else:
v = round(e.moment_tensor.magnitude, 1) v = round(e.magnitude, 1)
elif column == _column_mapping['Label']: if isinstance(marker, EventMarker): v = marker.label() elif isinstance(marker, PhaseMarker): v = marker.get_label()
elif column == _column_mapping['Depth [km]']: if isinstance(marker, EventMarker): d = marker.get_event().depth if d is not None: v = round(marker.get_event().depth/1000., 1)
elif column == _column_mapping['Lat']: if isinstance(marker, EventMarker): v = round(marker.get_event().effective_lat, 2)
elif column == _column_mapping['Lon']: if isinstance(marker, EventMarker): v = round(marker.get_event().effective_lon, 2)
elif column == _column_mapping['Kind']: v = marker.kind
elif column == _column_mapping['Dist [km]']: active_event = self.pile_viewer.get_active_event() if isinstance(marker, EventMarker) \ and active_event is not None:
dist = orthodrome.distance_accurate50m( marker.get_event(), active_event)
v = dist if role == qc.Qt.DisplayRole: v = '%.5g' % (v/1000.)
elif column == _column_mapping['NSLCs']: strs = [] for nslc_id in marker.get_nslc_ids(): strs.append('.'.join(nslc_id)) v = '|'.join(strs)
elif column == _column_mapping['Kagan Angle [deg]']: active_event = self.pile_viewer.get_active_event() if isinstance(marker, EventMarker) \ and active_event is not None \ and active_event.moment_tensor is not None \ and marker.get_event().moment_tensor is not None:
v = kagan_angle( active_event.moment_tensor, marker.get_event().moment_tensor)
if role == qc.Qt.DisplayRole: v = '%.1f' % v
elif column == _column_mapping['MT']: return qc.QVariant()
elif column == _column_mapping['Event Hash']: if isinstance(marker, (EventMarker, PhaseMarker)): v = marker.get_event_hash() else: return qc.QVariant()
elif column == _column_mapping['Polarity']: if isinstance(marker, (PhaseMarker)): v = marker.get_polarity_symbol() else: return qc.QVariant()
self.dataChanged.emit(index, index) return True
''' Set model data entry. '''
if role == qc.Qt.EditRole: imarker = index.row() marker = self.pile_viewer.markers[imarker] if index.column() in [_column_mapping[c] for c in [ 'M', 'Lat', 'Lon', 'Depth [km]']]:
if not isinstance(marker, EventMarker): return False else: if index.column() == _column_mapping['M']: valuef, valid = toFloat(value) if valid: e = marker.get_event() if e.moment_tensor is None: e.magnitude = valuef else: e.moment_tensor.magnitude = valuef return self.done(index)
if index.column() in [_column_mapping['Lon'], _column_mapping['Lat'], _column_mapping['Depth [km]']]: if isinstance(marker, EventMarker): valuef, valid = toFloat(value) if valid: if index.column() == _column_mapping['Lat']: marker.get_event().lat = valuef elif index.column() == _column_mapping['Lon']: marker.get_event().lon = valuef elif index.column() == _column_mapping[ 'Depth [km]']: marker.get_event().depth = valuef*1000. return self.done(index)
if index.column() == _column_mapping['Label']: values = str(value) if values != '': if isinstance(marker, EventMarker): marker.get_event().set_name(values) return self.done(index)
if isinstance(marker, PhaseMarker): marker.set_phasename(values) return self.done(index)
return False
''' Set flags for cells which the user can edit. '''
else:
else: self.proxy_filter = None self.marker_table_view.setModel(self.marker_model)
else: header.setResizeMode(i_s, qw.QHeaderView.Interactive)
else: self.selection_model = QItemSelectionModel(self.marker_model)
self.set_selected_markers)
''' Set the pile viewer and connect signals. '''
self.update_selection_model)
self.marker_model.handle_active_event_changed)
# self.pile_viewer.active_event_marker_changed.connect( # self.marker_table_view.update_viewport)
''' Update selection in viewer to reflect changes in table data. '''
else: def to_source(x): return x
''' Get the attached Qt table data model.
:returns: :py:class:`MarkerTableModel` object '''
''' Set currently selected table rows.
:param indices: begin and end+1 indices of contiguous selection chunks :type indices: list of tuples ''' (QItemSelectionModel.Select | QItemSelectionModel.Rows | QItemSelectionModel.Current))
QItemSelection(mi_start, mi_stop)) else: row_selection = QItemSelection(mi_start, mi_stop)
self.proxy_filter.mapFromSource(mi_start)) else: self.marker_table_view.scrollTo(mi_start)
mi_start, selection_flags)
|