Question

I need to implement a mechanism of highlighting duplicated values. Values are edited through delegate depending on the value type (string - line edit, long and big decimal - spin boxes). Currently, I implemented this feature with help of additional class which stores all values and their counts in two "parallel" lists. And after adding a new value I increase its count number (or decrease when repeated value is removed), but this solution seems to be too bulky. Do you guys have any other ideas on highlighting in setModelData(...) method of QItemDelegate?

/**
* Stores a delegates' existing values
*/
private final class DelegateValuesStorage {
    private final List<Object> values = new ArrayList<Object>();
    private final List<Integer> counts = new ArrayList<Integer>();

    ....

    //Add value or increase a count if exists
    public void add(final Object value) {
        if(values.contains(value)) {
            final int valueIndex = values.indexOf(value);
            final int oldCount = counts.get(valueIndex);
            counts.remove(valueIndex);
            counts.add(valueIndex, oldCount + 1);
        } else {
            values.add(value);
            counts.add(1);
        }
    }

    ....

    //Decrease a count or remove value if it doesn't exist anymore
    public void decreaseCount(final Object value) {
        if(value == null) {
            return;
        }
        final int index = values.indexOf(value);
        if(index >= 0) {
            final int oldCount = counts.get(index);
            if(oldCount >= 2) {
                counts.remove(index);
                counts.add(index, oldCount - 1);
            } else {
                values.remove(index);
                counts.remove(index);
            }
        }
    }

/**
* Delegate
*/
private class ConcreteDelegate extends QItemDelegate {

    private final DelegateValuesStorage values = new DelegateValuesStorage(); 

    ...

    @Override
    public void setModelData(final QWidget editor, final QAbstractItemModel model, final QModelIndex index) {
        if(editor instanceof ValEditor) { // ValEditor is an abstraction of line edit and spin box over values' data types

            final Object value = ((ValEditor) editor).getValue();
            model.setData(index, value, Qt.ItemDataRole.UserRole);
            final String newData = (value == null) ? "" : String.valueOf(value);
            values.add(newData);
            final String oldData = (String) model.data(index, Qt.ItemDataRole.DisplayRole);
            values.decreaseCount(oldData);


            model.setData(index, newData, Qt.ItemDataRole.DisplayRole);
            model.setData(index, new QColor(0, 0, 0), Qt.ItemDataRole.ForegroundRole);
            redrawItems(model); // runs through values and colors them red if count >= 2; or black if count == 1

        } else {
            super.setModelData(editor, model, index);
        }
    }
}
Was it helpful?

Solution

I usually use maps for those kinds of tasks:

private final class DelegateValuesStorage {
    private final Map<Object, Integer> values = new HashMap<Object, Integer>();

    ....

    //Add value or increase a count if exists
    public void add(final Object value) {
       Integer count = values.get(value);
       if (count == null) {
          values.put(value, 1);
       } else {
          values.put(value, count + 1);
       }
    }

    ....

    //Decrease a count or remove value if it doesn't exist anymore
    public void decreaseCount(final Object value) {
        if(value == null) {
            return;
        }
        Integer count = values.get(value);
        if (count == null) {
            // decreasing a "new" value - could be an error too
            return;
        }
        if (count <= 1) {
            // remove the value from the map
            values.remove(value);
        } else {
            values.put(value, count - 1);
        }
    }
}

Highlighting now should be enabled if

values.get(value) > 1

is true.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top