def startDrag(self, index): """start a drag operation with a PandasCellPayload on defined index. Args: index (QModelIndex): model index you want to start the drag operation. """ if not index.isValid(): return dataFrame = self.model().dataFrame() # get all infos from dataFrame dfindex = dataFrame.iloc[[index.row()]].index columnName = dataFrame.columns[index.column()] dtype = dataFrame[columnName].dtype value = dataFrame[columnName][dfindex] # create the mime data mimePayload = PandasCellPayload(dfindex, columnName, value, dtype, hex(id(self.model()))) mimeData = MimeData() mimeData.setData(mimePayload) # create the drag icon and start drag operation drag = QtGui.QDrag(self) drag.setMimeData(mimeData) pixmap = QtGui.QPixmap(":/icons/insert-table.png") drag.setHotSpot(QtCore.QPoint(pixmap.width() / 3, pixmap.height() / 3)) drag.setPixmap(pixmap) result = drag.start(Qt.MoveAction)
def removeDataFrameColumns(self, columns): if not self.editable: return False if columns: deleted = 0 errorOccured = False for (position, name) in columns: position = position - deleted if position < 0: position = 0 self.beginRemoveColumns(QtCore.QModelIndex(), position, position) try: self._dataFrame.drop(name, axis=1, inplace=True) except ValueError, e: errorOccured = True continue self.endRemoveColumns() deleted += 1 if errorOccured: return False else: return True
def test_setDelegates(self, qtbot, tableView, index, value, singleStep): dlg = createDelegate(numpy.dtype(value), 0, tableView) assert dlg is not None data = pandas.DataFrame([value], columns=['A']) data['A'] = data['A'].astype(value.dtype) model = tableView.model() model.setDataFrame(data) for i, delegate in enumerate([dlg]): assert tableView.itemDelegateForColumn(i) == delegate option = QtGui.QStyleOptionViewItem() option.rect = QtCore.QRect(0, 0, 100, 100) editor = delegate.createEditor(tableView, option, index) delegate.setEditorData(editor, index) assert editor.value() == index.data() delegate.setModelData(editor, model, index) delegate.updateEditorGeometry(editor, option, index) dtype = value.dtype if dtype in DataFrameModel._intDtypes: info = numpy.iinfo(dtype) assert isinstance(delegate, BigIntSpinboxDelegate) elif dtype in DataFrameModel._floatDtypes: info = numpy.finfo(dtype) assert isinstance(delegate, CustomDoubleSpinboxDelegate) assert delegate.decimals == DataFrameModel._float_precisions[ str(value.dtype)] assert delegate.maximum == info.max assert editor.maximum() == info.max assert delegate.minimum == info.min assert editor.minimum() == info.min assert delegate.singleStep == singleStep assert editor.singleStep() == singleStep def clickEvent(index): assert index.isValid() tableView.clicked.connect(clickEvent) with qtbot.waitSignal(tableView.clicked) as blocker: qtbot.mouseClick(tableView.viewport(), QtCore.Qt.LeftButton, pos=QtCore.QPoint(10, 10)) assert blocker.signal_triggered
def columnCount(self, index=QtCore.QModelIndex()): """returns number of columns Args: index (QtCore.QModelIndex, optional): Index to define column and row. defaults to empty QModelIndex Returns: number of columns """ return len(self.headers)
def rowCount(self, index=QtCore.QModelIndex()): """returns number of rows Args: index (QtCore.QModelIndex, optional): Index to define column and row. defaults to empty QModelIndex Returns: number of rows """ return len(self._dataFrame.columns)
def __init__(self, parent=None): """Constructs the object with the given parent. Args: parent (QObject, optional): Causes the objected to be owned by `parent` instead of Qt. Defaults to `None`. """ super(DelimiterValidator, self).__init__(parent) re = QtCore.QRegExp('\S{1}') self.setRegExp(re)
def __init__(self, parent=None, iconSize=QtCore.QSize(36, 36)): """Constructs the object with the given parent. Args: parent (QObject, optional): Causes the objected to be owned by `parent` instead of Qt. Defaults to `None`. iconSize (QSize, optional): Size of edit buttons. Defaults to QSize(36, 36). """ super(DataTableWidget, self).__init__(parent) self._iconSize = iconSize self.initUi()
def columnCount(self, index=QtCore.QModelIndex()): """returns number of columns Args: index (QtCore.QModelIndex, optional): Index to define column and row. defaults to empty QModelIndex Returns: number of columns """ # speed comparison: # In [23]: %timeit len(df.columns) # 10000000 loops, best of 3: 108 ns per loop # In [24]: %timeit df.shape[1] # 1000000 loops, best of 3: 440 ns per loop return len(self._dataFrame.columns)
def rowCount(self, index=QtCore.QModelIndex()): """returns number of rows Args: index (QtCore.QModelIndex, optional): Index to define column and row. defaults to empty QModelIndex Returns: number of rows """ # len(df.index) is faster, so use it: # In [12]: %timeit df.shape[0] # 1000000 loops, best of 3: 437 ns per loop # In [13]: %timeit len(df.index) # 10000000 loops, best of 3: 110 ns per loop # %timeit df.__len__() # 1000000 loops, best of 3: 215 ns per loop return len(self._dataFrame.index)
def createThread(parent, worker, deleteWorkerLater=False): """Create a new thread for given worker. Args: parent (QObject): parent of thread and worker. worker (ProgressWorker): worker to use in thread. deleteWorkerLater (bool, optional): delete the worker if thread finishes. Returns: QThread """ thread = QtCore.QThread(parent) thread.started.connect(worker.doWork) worker.finished.connect(thread.quit) if deleteWorkerLater: thread.finished.connect(worker.deleteLater) worker.moveToThread(thread) worker.setParent(parent) return thread
def addDataFrameColumn(self, columnName, dtype, defaultValue): if not self.editable or dtype not in SupportedDtypes.allTypes(): return False elements = self.rowCount() columnPosition = self.columnCount() newColumn = pandas.Series([defaultValue] * elements, index=self._dataFrame.index, dtype=dtype) self.beginInsertColumns(QtCore.QModelIndex(), columnPosition - 1, columnPosition - 1) try: self._dataFrame.insert(columnPosition, columnName, newColumn, allow_duplicates=False) except ValueError, e: # columnName does already exist return False
def __init__(self, parent=None): """the __init__ method. Args: parent (QObject): defaults to None. If parent is 0, the new widget becomes a window. If parent is another widget, this widget becomes a child window inside parent. The new widget is deleted when its parent is deleted. """ super(BigIntSpinbox, self).__init__(parent) self._singleStep = 1 self._minimum = -18446744073709551616 self._maximum = 18446744073709551615 rx = QtCore.QRegExp("[0-9]\\d{0,20}") validator = QtGui.QRegExpValidator(rx, self) self._lineEdit = QtWidgets.QLineEdit(self) self._lineEdit.setText('0') self._lineEdit.setValidator(validator) self.setLineEdit(self._lineEdit)
def test_data(self, dataframe): model = ColumnDtypeModel(dataFrame=dataframe) index = model.index(0, 0) # get data for display role ret = index.data() assert ret == 'Foo' # edit role does the same as display role ret = index.data(Qt.EditRole) assert ret == 'Foo' # datatype only defined for column 1 ret = index.data(DTYPE_ROLE) assert ret == None # datatype column index = index.sibling(0, 1) ret = index.data(DTYPE_ROLE) assert ret == numpy.dtype(numpy.int64) # check translation / display text assert index.data( ) == 'integer (64 bit)' == SupportedDtypes.description(ret) # column not defined index = index.sibling(0, 2) assert index.data(DTYPE_ROLE) == None # invalid index index = QtCore.QModelIndex() assert model.data(index) == None index = model.index(2, 0) # get data for display role ret = index.data() assert ret == 'Spam'
def addDataFrameRows(self, count=1): # don't allow any gaps in the data rows. # and always append at the end if not self.editable: return False position = self.rowCount() if count < 1: return False if len(self.dataFrame().columns) == 0: # log an error message or warning return False # Note: This function emits the rowsAboutToBeInserted() signal which # connected views (or proxies) must handle before the data is # inserted. Otherwise, the views may end up in an invalid state. self.beginInsertRows(QtCore.QModelIndex(), position, position + count - 1) defaultValues = [] for dtype in self._dataFrame.dtypes: if dtype.type == numpy.dtype('<M8[ns]'): val = pandas.Timestamp('') elif dtype.type == numpy.dtype(object): val = '' else: val = dtype.type() defaultValues.append(val) for i in xrange(count): self._dataFrame.loc[position + i] = defaultValues self._dataFrame.reset_index() self.endInsertRows() return True
def removeDataFrameRows(self, rows): if not self.editable: return False if rows: position = min(rows) count = len(rows) self.beginRemoveRows(QtCore.QModelIndex(), position, position + count - 1) removedAny = False for idx, line in self._dataFrame.iterrows(): if idx in rows: removedAny = True self._dataFrame.drop(idx, inplace=True) if not removedAny: return False self._dataFrame.reset_index(inplace=True, drop=True) self.endRemoveRows() return True return False
def test_invalidIndex(self, model): assert model.data(QtCore.QModelIndex()) is None
def test_invalidIndex(self, model): assert model.setData(QtCore.QModelIndex(), None) == False
def initUi(self): """Initalizes the Uuser Interface with all sub widgets. """ self.gridLayout = QtWidgets.QGridLayout(self) self.buttonFrame = QtWidgets.QFrame(self) self.buttonFrame.setMinimumSize(QtCore.QSize(250, 50)) self.buttonFrame.setMaximumSize(QtCore.QSize(250, 50)) self.buttonFrame.setFrameShape(QtWidgets.QFrame.NoFrame) self.buttonFrameLayout = QtWidgets.QGridLayout(self.buttonFrame) self.buttonFrameLayout.setContentsMargins(0, 6, 0, 6) self.editButton = QtWidgets.QToolButton(self.buttonFrame) self.editButton.setObjectName('editbutton') icon = QtGui.QIcon(QtGui.QPixmap(_fromUtf8(':/icons/document-edit.png'))) self.editButton.setIcon(icon) self.addColumnButton = QtWidgets.QToolButton(self.buttonFrame) self.addColumnButton.setObjectName('addcolumnbutton') icon = QtGui.QIcon(QtGui.QPixmap(_fromUtf8(':/icons/edit-table-insert-column-right.png'))) self.addColumnButton.setIcon(icon) self.addRowButton = QtWidgets.QToolButton(self.buttonFrame) self.addRowButton.setObjectName('addrowbutton') icon = QtGui.QIcon(QtGui.QPixmap(_fromUtf8(':/icons/edit-table-insert-row-below.png'))) self.addRowButton.setIcon(icon) self.removeColumnButton = QtWidgets.QToolButton(self.buttonFrame) self.removeColumnButton.setObjectName('removecolumnbutton') icon = QtGui.QIcon(QtGui.QPixmap(_fromUtf8(':/icons/edit-table-delete-column.png'))) self.removeColumnButton.setIcon(icon) self.removeRowButton = QtWidgets.QToolButton(self.buttonFrame) self.removeRowButton.setObjectName('removerowbutton') icon = QtGui.QIcon(QtGui.QPixmap(_fromUtf8(':/icons/edit-table-delete-row.png'))) self.removeRowButton.setIcon(icon) self.buttons = [self.editButton, self.addColumnButton, self.addRowButton, self.removeColumnButton, self.removeRowButton] for index, button in enumerate(self.buttons): button.setMinimumSize(QtCore.QSize(36, 36)) button.setMaximumSize(QtCore.QSize(36, 36)) button.setIconSize(QtCore.QSize(36, 36)) button.setCheckable(True) self.buttonFrameLayout.addWidget(button, 0, index, 1, 1) for button in self.buttons[1:]: button.setEnabled(False) self.tableView = QtWidgets.QTableView(self) self.tableView.setAlternatingRowColors(True) self.tableView.setSortingEnabled(True) self.gridLayout.addWidget(self.buttonFrame, 0, 0, 1, 1) self.gridLayout.addWidget(self.tableView, 1, 0, 1, 1) self.editButton.toggled.connect(self.enableEditing) self.addColumnButton.toggled.connect(self.showAddColumnDialog) self.addRowButton.toggled.connect(self.addRow) self.removeRowButton.toggled.connect(self.removeRow) self.removeColumnButton.toggled.connect(self.showRemoveColumnDialog)