def parent(model, qindex): """ A common convention used in models that expose tree data structures is that only items in the first column have children. For that case, when reimplementing this function in a subclass the column of the returned QModelIndex would be 0. When reimplementing this function in a subclass, be careful to avoid calling QModelIndex member functions, such as QModelIndex.parent(), since indexes belonging to your model will simply call your implementation, leading to infinite recursion. Returns: the parent of the model item with the given index. If the item has no parent, an invalid QModelIndex is returned. """ model.lazy_checks() if qindex.isValid(): node = qindex.internalPointer() #<HACK> if not isinstance(node, _atn.TreeNode): print("WARNING: tried to access parent of %r type object" % type(node)) return QtCore.QModelIndex() #assert node.__dict__, "node.__dict__=%r" % node.__dict__ #</HACK> parent_node = node.get_parent() parent_id = parent_node.get_id() if parent_id == -1 or parent_id is None: return QtCore.QModelIndex() row = parent_node.get_row() col = model.col_level_list.index(parent_node.get_level()) return model.createIndex(row, col, parent_node) return QtCore.QModelIndex()
def index(model, row, column, parent=QtCore.QModelIndex()): """ Qt Override Returns: the index of the item in the model specified by the given row, column and parent index. When reimplementing this function in a subclass, call createIndex() to generate model indexes that other components can use to refer to items in your model. NOTE: Object must be specified to sort delegates. """ model.lazy_checks() if not parent.isValid(): # This is a top level == 0 index #print('[model.index] ROOT: row=%r, col=%r' % (row, column)) if row >= model.root_node.get_num_children(): return QtCore.QModelIndex() #import traceback #traceback.print_stack() node = model.root_node[row] if model.col_level_list[column] != node.get_level(): return QtCore.QModelIndex() qtindex = model.createIndex(row, column, object=node) return qtindex else: # This is a child level > 0 index parent_node = parent.internalPointer() node = parent_node[row] if ut.USE_ASSERT: assert isinstance(parent_node, _atn.TreeNode), type(parent_node) assert isinstance(node, _atn.TreeNode), type(node) return model.createIndex(row, column, object=node)
def createEditor(self, parent, option, index): combo = QtGui.QComboBox(parent) combo.addItems(['option1', 'option2', 'option3']) #self.connect(combo.currentIndexChanged, self.currentIndexChanged) # FIXME: Change to newstyle signal slot self.connect(combo, QtCore.SIGNAL("currentIndexChanged(int)"), self, QtCore.SLOT("currentIndexChanged()")) return combo
def sizeHint(dgt, option, qtindex): view = dgt.parent() offset = view.verticalOffset() + option.rect.y() try: thumb_path = dgt.get_thumb_path_if_exists(view, offset, qtindex) if thumb_path is not None: # Read the precomputed thumbnail width, height = read_thumb_size(thumb_path) return QtCore.QSize(width, height) else: #print("[APIThumbDelegate] Name not found") return QtCore.QSize() except Exception as ex: print("Error in APIThumbDelegate") ut.printex(ex, 'Error in APIThumbDelegate', tb=True) return QtCore.QSize()
def data(model, index, role=Qt.DisplayRole): """ Returns the data to display """ if not index.isValid(): return None flags = model.flags(index) if role == Qt.TextAlignmentRole: return model.get_column_alignment(index.column()) if role == Qt.BackgroundRole and (flags & Qt.ItemIsEditable or flags & Qt.ItemIsUserCheckable): return QtCore.QVariant(QtGui.QColor(250, 240, 240)) if role == Qt.DisplayRole or role == Qt.CheckStateRole: data = model.get_data(index) var = qtype.cast_into_qt(data, role, flags) return var else: return QtCore.QVariant()
def paint(dgt, painter, option, qtindex): """ TODO: prevent recursive paint """ view = dgt.parent() offset = view.verticalOffset() + option.rect.y() # Check if still in viewport if view_would_not_be_visible(view, offset): return None try: thumb_path = dgt.get_thumb_path_if_exists(view, offset, qtindex) if thumb_path is not None: # Check if still in viewport if view_would_not_be_visible(view, offset): return None # Read the precomputed thumbnail qimg = read_thumb_as_qimg(thumb_path) width, height = qimg.width(), qimg.height() # Adjust the cell size to fit the image dgt.adjust_thumb_cell_size(qtindex, width, height) # Check if still in viewport if view_would_not_be_visible(view, offset): return None # Paint image on an item in some view painter.save() painter.setClipRect(option.rect) painter.translate(option.rect.x(), option.rect.y()) painter.drawImage(QtCore.QRectF(0, 0, width, height), qimg) painter.restore() except Exception as ex: # PSA: Always report errors on Exceptions! print('Error in APIThumbDelegate') ut.printex(ex, 'Error in APIThumbDelegate') painter.save() painter.restore()
def source_to_proxy(self, row, col, parent=QtCore.QModelIndex()): source_model = self.sourceModel() source_cols = source_model.columnCount(parent=parent) r, c, p = row, col, parent r2 = int(math.floor(r / self._nd)) c2 = ((r % self._nd) * source_cols) + c p2 = p return r2, c2, p2
def proxy_to_source(self, row, col, parent=QtCore.QModelIndex()): source_model = self.sourceModel() source_cols = source_model.columnCount(parent=parent) r, c, p = row, col, parent r2 = int(math.floor(c / source_cols)) + (r * self._nd) c2 = c % source_cols p2 = p return r2, c2, p2
class GUILoggingSender(QtCore.QObject): write_ = QtCore.pyqtSignal(str) def __init__(self, write_slot): QtCore.QObject.__init__(self) self.write_.connect(write_slot) def write_gui(self, msg): self.write_.emit(str(msg))
def _init_table_behavior(view): """ Table behavior SeeAlso: api_item_view._init_itemview_behavior """ # Allow sorting by column view.setCornerButtonEnabled(False) view.setShowGrid(True) view.setIconSize(QtCore.QSize(64, 64))
def mapFromSource(self, sourceIndex): """ returns index into proxy model """ if sourceIndex is None: return None if sourceIndex.isValid(): r2, c2, p2 = self.source_to_proxy(sourceIndex.row(), sourceIndex.column(), sourceIndex.parent()) proxyIndex = self.index(r2, c2, p2) else: proxyIndex = QtCore.QModelIndex() return proxyIndex
def mapToSource(self, proxyIndex): """ returns index into original model """ if proxyIndex is None: return None if proxyIndex.isValid(): r2, c2, p2 = self.proxy_to_source(proxyIndex.row(), proxyIndex.column()) sourceIndex = self.sourceModel().index( r2, c2, parent=p2) # self.sourceModel().root_node[r2] else: sourceIndex = QtCore.QModelIndex() return sourceIndex
def ping_python_interpreter(frequency=420): # 4200): """ Create a QTimer which lets the python catch ctrl+c """ if not QUIET and VERBOSE: print('[guitool] pinging python interpreter for ctrl+c freq=%r' % frequency) timer = QtCore.QTimer() def ping_func(): #print('lub dub') return None timer.ping_func = ping_func timer.timeout.connect(timer.ping_func) timer.start(frequency) return timer
def rowCount(model, parent=QtCore.QModelIndex()): """ Qt Override """ #model.lazy_checks() if not parent.isValid(): # Root row count if len(model.level_index_list) == 0: return 0 nRows = len(model.level_index_list) #print('* nRows=%r' % nRows) return nRows else: node = parent.internalPointer() nRows = node.get_num_children() #print('+ nRows=%r' % nRows) return nRows
def _get_row_id(model, qtindex=QtCore.QModelIndex()): """ returns the id (specified by iders i.e. an ibeis rowid) from qtindex """ if qtindex.isValid(): node = qtindex.internalPointer() if ut.USE_ASSERT: try: assert isinstance(node, _atn.TreeNode), 'type(node)=%r, node=%r' % (type(node), node) except AssertionError as ex: ut.printex(ex, 'error in _get_row_id', keys=['model', 'qtindex', 'node']) raise try: id_ = node.get_id() except AttributeError as ex: ut.printex(ex, key_list=['node', 'model', 'qtindex']) raise return id_
def _get_adjacent_qtindex(model, qtindex=QtCore.QModelIndex(), offset=1): # check qtindex if not qtindex.isValid(): return None node = qtindex.internalPointer() # check node try: if ut.USE_ASSERT: assert isinstance(node, _atn.TreeNode), type(node) except AssertionError as ex: ut.printex(ex, key_list=['node'], pad_stdout=True) raise # get node parent try: node_parent = node.get_parent() except Exception as ex: ut.printex(ex, key_list=['node'], reraise=False, pad_stdout=True) raise # parent_node check if node_parent is None: print('[model._get_adjacent_qtindex] node_parent is None!') return None # Offset to find the next qtindex next_index = node_parent.child_index(node) + offset nChildren = node_parent.get_num_children() # check next index validitiy if next_index >= 0 and next_index < nChildren: next_node = node_parent.get_child(next_index) next_level = next_node.get_level() col = model.col_level_list.index(next_level) row = next_node.get_row() # Create qtindex for the adjacent note parent_qtindex = model.parent(qtindex) next_qtindex = model.index(row, col, parent_qtindex) return next_qtindex else: # There is no adjacent node return None
def sizeHint(option, qindex): # QStyleOptionViewItem option return QtCore.QSize(50, 50)
def columnCount(model, parent=QtCore.QModelIndex()): """ Qt Override """ return len(model.col_name_list)
def index(model, row, column, parent=QtCore.QModelIndex()): """ Qt Override """ return model.createIndex(row, column)
def headerData(model, section, orientation, role=Qt.DisplayRole): """ Qt Override """ if role == Qt.DisplayRole and orientation == Qt.Horizontal: return model.get_niceheader(section) else: return QtCore.QVariant()
def rowCount(model, parent=QtCore.QModelIndex()): """ Qt Override """ return len(model.row_sortx)
def source_to_proxy(self, row, col, parent=QtCore.QModelIndex()): r2, c2, p2 = row, col, parent return r2, c2, p2
def columnCount(model, parent=QtCore.QModelIndex()): """ Qt Override """ # FOR NOW THE COLUMN COUNT IS CONSTANT model.lazy_checks() return len(model.col_name_list)
def columnCount(self, parent=QtCore.QModelIndex()): source_cols = self.sourceModel().columnCount(parent=parent) cols = self._nd * source_cols #print('StripeProxyModel.columnCount(): %r %r' % (source_cols, cols)) return int(cols)
class APIButtonDelegate(DELEGATE_BASE): button_clicked = QtCore.pyqtSignal(QtCore.QModelIndex) def __init__(dgt, parent=None): assert parent is not None, 'parent must be a view' DELEGATE_BASE.__init__(dgt, parent) # FIXME: I don't like this state in the delegate, as it renders all # buttons dgt._pressed = None dgt.button_clicked.connect(dgt.on_button_click) def get_index_butkw(dgt, qtindex): """ The model data for a button should be a (text, callback) tuple. OR it could be a function which accepts an qtindex and returns a button """ data = qtindex.model().data(qtindex, QtCore.Qt.DisplayRole) # Get info if isinstance(data, tuple): buttontup = data elif utool.is_funclike(data): func = data buttontup = func(qtindex) else: raise AssertionError('bad type') text, callback = buttontup[0:2] butkw = { #'parent': dgt.parent(), 'text': text, 'clicked': callback, } if len(buttontup) > 2: butkw['bgcolor'] = buttontup[2] butkw['fgcolor'] = (0, 0, 0) return butkw def paint(dgt, painter, option, qtindex): painter.save() butkw = dgt.get_index_butkw(qtindex) # FIXME: I don't want to create a widget each time just # so I can access the button's style button = guitool_components.newButton(**butkw) pressed = dgt.is_qtindex_pressed(qtindex) view = dgt.parent() paint_button(painter, option, button=button, pressed=pressed, view=view, **butkw) painter.restore() def is_qtindex_pressed(dgt, qtindex): return dgt._pressed is not None and dgt._pressed == (qtindex.row(), qtindex.column()) @QtCore.pyqtSlot(QtCore.QModelIndex) def on_button_click(dgt, qtindex): if utool.VERBOSE: print('pressed button') butkw = dgt.get_index_butkw(qtindex) callback = butkw['clicked'] callback() def editorEvent(dgt, event, model, option, qtindex): # http://stackoverflow.com/questions/14585575/button-delegate-issue #print('editor event') event_type = event.type() if event_type == QtCore.QEvent.MouseButtonPress: # store the position that is clicked dgt._pressed = (qtindex.row(), qtindex.column()) if utool.VERBOSE: print('store') return True elif event_type == QtCore.QEvent.MouseButtonRelease: if dgt.is_qtindex_pressed(qtindex): print('emit') dgt.button_clicked.emit(qtindex) pass elif dgt._pressed is not None: # different place. # force a repaint on the pressed cell by emitting a dataChanged # Note: This is probably not the best idea # but I've yet to find a better solution. print('repaint') oldIndex = qtindex.model().index(*dgt._pressed) dgt._pressed = None qtindex.model().dataChanged.emit(oldIndex, oldIndex) pass dgt._pressed = None #print('mouse release') return True elif event_type == QtCore.QEvent.Leave: print('leave') elif event_type == QtCore.QEvent.MouseButtonDblClick: print('doubleclick') else: print('event_type = %r' % event_type) return DELEGATE_BASE.editorEvent(dgt, event, model, option, qtindex)
def sizeHint(qres_wgt): # should eventually improve this to use the widths of the header columns return QtCore.QSize(1100, 500)
def index(self, row, col, parent=QtCore.QModelIndex()): if (row, col) != (-1, -1): proxyIndex = self.createIndex(row, col, parent) else: proxyIndex = QtCore.QModelIndex() return proxyIndex
def rowCount(self, parent=QtCore.QModelIndex()): sourceParent = self.mapToSource(parent) source_rows = self.sourceModel().rowCount(parent=sourceParent) rows = math.ceil(source_rows / self._nd) #print('StripeProxyModel.rowCount(): %r %r' % (source_rows, rows)) return int(rows)