def reloadData(self, roles=None):

        if not roles:
            roles = [Qt.ItemDataRole.DisplayRole, Qt.ItemDataRole.CheckStateRole]

        self.dataChanged.emit(QModelIndex(), QModelIndex(), roles)
        self.layoutChanged.emit()
        self.loading_done.emit()
 def parent(self, index):
     if not index.isValid():
         return QModelIndex()
     child_item = index.internalPointer()
     if not child_item:
         return QModelIndex()
     parent_item = child_item.parent_()
     if parent_item == self._root_item:
         return QModelIndex()
     return self.createIndex(parent_item.row(), 0, parent_item)
 def index(self, row, column, parent):
     if not self.hasIndex(row, column, parent):
         return QModelIndex()
     if not parent.isValid():
         parent_item = self._root_item
     else:
         parent_item = parent.internalPointer()
     child_item = parent_item.child_at(row)
     if child_item:
         return self.createIndex(row, column, child_item)
     else:
         return QModelIndex()
    def clearRowsFromTable(self):
        """Delete all rows and data."""
        answer = QMessageBox.warning(
            self, "Clear Table",
            f"Do you really want to clear the {self._headers[0]} table?",
            QMessageBox.StandardButton.No | QMessageBox.StandardButton.Yes,
            QMessageBox.StandardButton.No)

        if answer == QMessageBox.StandardButton.Yes:
            # Clear the table and update the Money Left Over table
            self.model.removeRows(self.model.rowCount(QModelIndex()), 0,
                                  self.model.rowCount(QModelIndex()))
            self.totals_updated.emit(self.running_totals)
            self.addRowToTable()
Beispiel #5
0
    def index(self, row, column, parent=QModelIndex()):
        if not self._container:
            return QModelIndex()

        if not self.hasIndex(row, column, parent):
            return QModelIndex()

        definition = None
        if not parent.isValid():
            definition = self._container.definitions[row]
        else:
            definition = parent.internalPointer().children[row]

        return self.createIndex(row, column, definition)
    def setUpMainWindow(self):
        """Set up the GUI's main window."""
        header_label = QLabel("List of Users")

        # Create model and table objects
        model = QStandardItemModel()
        model.setColumnCount(3)
        model.setHorizontalHeaderLabels(["Name", "Birthdate", "Actions"])

        table_view = QTableView()
        table_view.setEditTriggers(
            QAbstractItemView.EditTrigger.NoEditTriggers)
        # NOTE: Uncomment for table cells to be unselectable
        #table_view.setSelectionMode(QAbstractItemView.SelectionMode.NoSelection)
        table_view.setModel(model)
        table_view.horizontalHeader().setSectionResizeMode(
            0, QHeaderView.ResizeMode.Stretch)

        names_list = ["Willman, Joshua", "Davis, Scott", "Garcia, Sky"]

        # Add items to each row in the table by looping over
        # the names_list and adding the date edit and button widgets
        for row, name in enumerate(names_list):
            model.setItem(row, QStandardItem(name))
            # Setting the widget at an index in a QTableView involves
            # acquiring the QModelIndex values of the current position.
            # One way to do this is to use the QAbstractItemModel.sibling()
            # method to retrieve the QModelIndex index from the specified
            # row and column (here the column is 1)
            index = table_view.model().sibling(row, 1, QModelIndex())
            date_edit = QDateEdit(QDate.currentDate(
            ))  # Create QDateEdit object that starts at current date
            date_edit.setDateRange(QDate(1900, 1, 1), QDate.currentDate())
            date_edit.setDisplayFormat("MM/dd/yyyy")
            date_edit.setAlignment(
                Qt.AlignmentFlag.AlignRight)  # Align the text
            date_edit.setAutoFillBackground(True)
            table_view.setIndexWidget(index, date_edit)
            # Set the widgets in the final column for each row
            index = table_view.model().sibling(row, 2, QModelIndex())
            table_view.setIndexWidget(index, EditCellWidget(table_view))

        # Set up main layout and container object for main window
        main_v_box = QVBoxLayout()
        main_v_box.addWidget(header_label)
        main_v_box.addWidget(table_view)

        container = QWidget()
        container.setLayout(main_v_box)
        self.setCentralWidget(container)
Beispiel #7
0
    def update_db(self, index: QModelIndex, val: Any) -> None:
        """Update single value from row in database
        TODO - this could maybe move to TableWidget?
        """
        df = self.df
        header = df.columns[index.column()]  # view header

        # model asks parent's table_widget for dbtable to update based on col
        dbtable = self.table_widget.get_dbtable(header=header)
        check_exists = False if not header in self.view.mcols[
            'check_exist'] else True

        row = dbt.Row(data_model=self, dbtable=dbtable, i=index.row())
        row.update_single(header=header, val=val, check_exists=check_exists)
Beispiel #8
0
    def row_changed(self, index_current: QModelIndex, index_prev: QModelIndex):
        # only redraw the table if the row index changes (faster for horizontal switching)
        if not index_current.row() == index_prev.row():
            # view = self.view
            # view.setUpdatesEnabled(False)
            # self.current_row = index_current.row()
            # for row in (index_current.row(), index_prev.row()):
            #     for col in range(self.columnCount()):
            #         view.childAt(row, col).repaint()

            # view.setUpdatesEnabled(True)

            self.layoutAboutToBeChanged.emit()
            self.current_row = index_current.row()
            self.layoutChanged.emit()
Beispiel #9
0
    def setItems(self, items: List[Dict[str, Any]]) -> None:
        """Replace all items at once.
        :param items: The new list of items.
        """

        # We do not use model reset because of the following:
        #   - it is very slow
        #   - it can cause crashes on Mac OS X for some reason when endResetModel() is called (CURA-6015)
        # So in this case, we use insertRows(), removeRows() and dataChanged signals to do
        # smarter model update.

        old_row_count = len(self._items)
        new_row_count = len(items)
        changed_row_count = min(old_row_count, new_row_count)

        need_to_add = old_row_count < new_row_count
        need_to_remove = old_row_count > new_row_count

        # In the case of insertion and deletion, we need to call beginInsertRows()/beginRemoveRows() and
        # endInsertRows()/endRemoveRows() before we modify the items.
        # In the case of modification on the existing items, we only need to modify the items and then emit
        # dataChanged().
        #
        # Here it is simplified to replace the complete items list instead of adding/removing/modifying them one by one,
        # and it needs to make sure that the necessary signals (insert/remove/modified) are emitted before and after
        # the item replacement.

        if need_to_add:
            self.beginInsertRows(QModelIndex(), old_row_count,
                                 new_row_count - 1)
        elif need_to_remove:
            self.beginRemoveRows(QModelIndex(), new_row_count,
                                 old_row_count - 1)

        self._items = items

        if need_to_add:
            self.endInsertRows()
        elif need_to_remove:
            self.endRemoveRows()

        # Notify that the existing items have been changed.
        if changed_row_count >= 0:
            self.dataChanged.emit(self.index(0, 0),
                                  self.index(changed_row_count - 1, 0))

        # Notify with the custom signal itemsChanged to keep it backwards compatible in case something relies on it.
        self.itemsChanged.emit()
 def rowCount(self, parent=QModelIndex()):
     if parent.column() > 0:
         return 0
     if not parent.isValid():
         parent_item = self._root_item
     else:
         parent_item = parent.internalPointer()
     return parent_item.child_count()
 def removeRows(self, parent, first, last):
     """Delete all values in the table and model."""
     self.beginRemoveRows(QModelIndex(), first, last)
     # Delete all rows from the table and model
     self._data.clear()
     self.values_edited.emit()
     self.endRemoveRows()
     self.layoutChanged.emit()
     return True
Beispiel #12
0
    def parent(self, child):
        if not self._container:
            return QModelIndex()

        if not child.isValid():
            return QModelIndex()

        parent = child.internalPointer().parent
        if not parent:
            return QModelIndex()

        row = None
        if not parent.parent:
            row = self._container.definitions.index(parent)
        else:
            row = parent.parent.children.index(parent)

        return self.createIndex(row, 0, parent)
 def updateTotalValues(self):
     """Update values in the second column and the 
     Money Left Over Table."""
     index = self.model.index(len(self.model._data) - 1, 1, QModelIndex())
     if "Money In" in self._headers:
         self.running_totals[0] = index.data()
     elif "Money Out" in self._headers:
         self.running_totals[1] = index.data()
     self.totals_updated.emit(self.running_totals)
 def insertRows(self, row, count, parent):
     """Insert a row into the model. Call values_edited to 
     update the totals in the Money Left Over table."""
     self.beginInsertRows(QModelIndex(), row, row)
     self._data.append(["",
                        "$0.00"])  # Append a list with 2 strings to _data
     self.values_edited.emit()
     self.endInsertRows()
     self.layoutChanged.emit()
     return True
Beispiel #15
0
    def removeItem(self, index: int) -> None:
        """Remove an item from the list.

        :param index: The index of the item to remove.
        """

        self.beginRemoveRows(QModelIndex(), index, index)
        del self._items[index]
        self.endRemoveRows()
        self.itemsChanged.emit()
Beispiel #16
0
    def insertItem(self, index: int, item: Dict[str, Any]) -> None:
        """Insert an item into the list at an index.

        :param index: The index where to insert.
        :param item: The item to add.
        """

        self.beginInsertRows(QModelIndex(), index, index)
        self._items.insert(index, item)
        self.endInsertRows()
        self.itemsChanged.emit()
Beispiel #17
0
 def update_select_all_checkbox(self):
     check_states = []
     for irow in range(self.dbx_model._root_item.child_count_loaded()):
         index = self.dbx_model.index(irow, 1, QModelIndex())
         check_states.append(
             self.dbx_model.data(index, Qt.ItemDataRole.CheckStateRole)
         )
     if all(cs == 2 for cs in check_states):
         self.selectAllCheckBox.setChecked(True)
     else:
         self.selectAllCheckBox.setChecked(False)
    def updateTotalsRow(self, totals_list):
        """Update the value for the second column."""
        if (totals_list[0] and totals_list[1]) != None:
            income = float(totals_list[0].replace("$", ""))
            expenses = float(totals_list[1].replace("$", ""))
            difference = income - expenses

            # Convert the difference to a string and update the model/view
            difference_str = f"${difference:.2f}"  # Convert to a string
            index = self.model.index(0, 1, QModelIndex())
            self.model.setData(index, difference_str, Qt.ItemDataRole.EditRole)
Beispiel #19
0
    def count(self, parent=QModelIndex()):
        if not self._container:
            return 0

        if parent.column() > 0:
            return 0

        if not parent.isValid():
            return len(self._container.definitions)

        setting = parent.internalPointer()
        return len(setting.children)
Beispiel #20
0
    def data(self, index: QModelIndex, _: int = ...) -> Any:
        """
            Example:
                rows = [{name: "Jeff", age: 100, height: 10.2}, ....]
                headers = { 0: "name", 1: "age", 2: "height" }

                row = 0 # index of row in rows
                column = 2 # index of header in headers

                return rows[0]["height"]
        """
        if index.column() not in self._headers.keys():
            # Check if column (int) has corresponding header (str)
            return ""

        i_row = index.row()
        header = self._headers[index.column()]

        value = self._rows[i_row][header]

        return value or ""
    def displayItemValues(self):
        """Simple method that demonstrates how to retrieve the values 
        from the widgets."""
        # Get the model index of the item (in this case the view_button)
        # at the viewport coordinates
        index = self.table_view.indexAt(
            self.pos())  # Get the index of the button pushed
        row = index.row()  # Get the row of that button
        # Use the row value to get the index of the cells in that row, column 1
        widget_index = self.table_view.model().sibling(row, 1, QModelIndex())
        # Use indexWidget to get the QDateEdit widget
        date_edit_widget = self.table_view.indexWidget(widget_index)

        # Get value from the cell in column 0 for the selected row
        name = self.table_view.model().sibling(row, 0, QModelIndex()).data()

        # Display name and date in a QMessageBox
        QMessageBox.information(
            self, "User Information", f"""Name: {name}<br>
            <b>Birthdate: </b>{date_edit_widget.date().toString("MM/dd/yyyy")}"""
        )
    def _updateVisibleRows(self) -> None:
        # This function is scheduled on the Qt event loop. By the time this is called, this object can already been
        # destroyed because the owner QML widget was destroyed or so. We cannot cancel a call that has been scheduled,
        # so in this case, we should do nothing if this object has already been destroyed.
        if self._destroyed:
            return

        # Reset the scheduled flag
        self._update_visible_row_scheduled = False

        currently_visible = set(
            self._row_index_list)  # A set of currently visible items

        new_visible = set()  # A new set of visible items
        for index in range(len(self._definition_list)):
            if self._isDefinitionVisible(self._definition_list[index]):
                new_visible.add(index)

        # Calculate the difference between the sets. The items that are in new_visible and
        # not in currently_visible are items that need to be added, the items that are in
        # currently_visible and not in new_visible are items that should be removed.
        to_add = new_visible - currently_visible
        to_remove = currently_visible - new_visible

        # Add the new items. Currently doing this one by one since that proved fast enough.
        for index in sorted(list(to_add)):
            row = self._findRowToInsert(index)
            self.beginInsertRows(QModelIndex(), row, row)
            self._row_index_list.insert(row, index)
            self.endInsertRows()

        # Remove items. Also doing this one by one currently.
        for index in sorted(list(to_remove)):
            row = self._row_index_list.index(index)
            self.beginRemoveRows(QModelIndex(), row, row)
            del self._row_index_list[row]
            self.endRemoveRows()

        self.visibleCountChanged.emit()
Beispiel #23
0
def test_dataUnhappy():
    model = createModel("single_setting.def.json")
    # Out of bounds
    assert model.data(model.index(250, 0), model.KeyRole) == QVariant()

    # Invalid index
    assert model.data(QModelIndex(), model.KeyRole) == QVariant()

    # Unknown role
    assert model.data(model.index(0, 0),
                      Qt.ItemDataRole.UserRole + 100) == QVariant()

    empty_model = SettingDefinitionsModel()
    assert empty_model.data(model.index(0, 0), model.KeyRole) == QVariant()
    def setUpMainWindow(self):
        """Set up the GUI's main window."""
        header_label = QLabel("List of Users")

        # Create model and table objects
        model = QStandardItemModel()
        model.setColumnCount(3)
        model.setHorizontalHeaderLabels(["Name", "Birthdate", "Actions"])

        table_view = QTableView()
        # NOTE: setEditTriggers() is not used so that the user
        # can double-click and edit cells
        table_view.setModel(model)
        table_view.horizontalHeader().setSectionResizeMode(
            0, QHeaderView.ResizeMode.Stretch)
        # Set the item delegate for a specific column, in this case column 1
        table_view.setItemDelegateForColumn(1, DateEditDelegate())

        names_list = ["Willman, Joshua", "Davis, Scott", "Garcia, Sky"]

        # Add items to each row in the table by looping over
        # the names_list and adding the date edit and button widgets
        for row, name in enumerate(names_list):
            model.setItem(row, QStandardItem(name))
            # Create an item and set the initial value for the second column.
            # Here the QDate values are converted to strings to make it easier
            # to align the text without having to subclass a model class
            date_item = QStandardItem(
                QDate.currentDate().toString("MM/dd/yyyy"))
            date_item.setTextAlignment(Qt.AlignmentFlag.AlignVCenter
                                       | Qt.AlignmentFlag.AlignRight)
            model.setItem(row, 1, date_item)
            # Set the widgets in the final column for each row
            index = model.index(row, 2, QModelIndex())
            table_view.setIndexWidget(index, EditCellWidget(table_view))

        # Set up main layout and container object for main window
        main_v_box = QVBoxLayout()
        main_v_box.addWidget(header_label)
        main_v_box.addWidget(table_view)

        container = QWidget()
        container.setLayout(main_v_box)
        self.setCentralWidget(container)
Beispiel #25
0
    def insertRows(self, m: dict, i: int = None, num_rows=1, select=False):
        """Insert new row to table

        Parameters
        ----------
        m : dict
            Vals for new row to insert
        i : int, optional
            Insert at specific location, default end of table
        num_rows : int, optional
            number of rows to insert, default 1
        select : bool, optional
            select row after insert, default False
        """
        if i is None:
            i = self.rowCount()

        self.beginInsertRows(QModelIndex(), i, i + num_rows - 1)

        self._df_orig = self._df_orig.pipe(f.append_default_row)
        df_new_row = self._df_orig.iloc[-1:]

        # concat this way to preserve index of new row from _df_orig
        self._df = pd.concat([self.df, self._df_orig.iloc[-1:]])

        # setting new data will trigger update of static dfs
        for col, val in m.items():
            icol = self.get_col_idx(col)
            if not icol is None:
                index = self.createIndex(i, icol)
                self.setData(index=index,
                             val=val,
                             update_db=False,
                             triggers=False)

        self.set_static_dfs(df=self._df_orig.iloc[-1:], reset=False)
        self.update_rows_label()
        self.endInsertRows()

        if select:
            self.view.select_by_index(index=self.createIndex(i, 1))

        return df_new_row
Beispiel #26
0
    def removeRows(self, i: int, num_rows: int = 1):
        """Remove single row from table model

        Parameters
        ----------
        i : int
            row int to remove
        num_rows : int, optional
            not implemented, default 1

        - TODO build remove more than one row
        """

        self.beginRemoveRows(QModelIndex(), i, i + num_rows - 1)

        df = self.df
        row_name = df.index[i]
        self._df_orig = self._df_orig.drop(row_name)
        self._df = df.drop(
            row_name)  # can't call self.df layout signals mess table up
        self.update_rows_label()

        self.endRemoveRows()
 def sort(self, column, order):
     self.layoutAboutToBeChanged.emit()
     self._root_item.sort(column, order)
     self.dataChanged.emit(QModelIndex(), QModelIndex())
     self.layoutChanged.emit()
Beispiel #28
0
 def on_tableWidget_doubleClicked(
         self, index: QModelIndex):  # получение списка обьектов
     r = self.ui.tableWidget.item(index.row(), index.column()).text()
     clipboard.setText(r)
Beispiel #29
0
 def on_tableWidget_clicked(
         self, index: QModelIndex):  # получение индекса строки при нажатие
     self.id = int(self.ui.tableWidget.item(index.row(), 0).text())
 def on_select_all_clicked(self, checked):
     checked_state = 2 if checked else 0
     for irow in range(self.dbx_model._root_item.child_count_loaded()):
         index = self.dbx_model.index(irow, 1, QModelIndex())
         self.dbx_model.setCheckState(index, checked_state)