mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-04 16:56:53 +08:00
refs #641, improvements/fixes of orderable lists / models / views
* set sort order automatically to IndexOrder when changing order of items * call onChanged when model is changed and then update view (needed when model is changed directly, not via view) * support for digest signal so redundant updates can be avoided * renamed rowCountChanged (signal) to modelDataChanged - detecting row count changes only was useless * updated Doxygen / fixed typos
This commit is contained in:
@@ -157,19 +157,19 @@ namespace BlackGui
|
||||
return m_modelDestroyed;
|
||||
}
|
||||
|
||||
void CListModelBaseNonTemplate::sendDataChanged(int startRowIndex, int endRowIndex)
|
||||
void CListModelBaseNonTemplate::emitDataChanged(int startRowIndex, int endRowIndex)
|
||||
{
|
||||
BLACK_VERIFY_X(startRowIndex <= endRowIndex, Q_FUNC_INFO, "check rows");
|
||||
BLACK_VERIFY_X(startRowIndex >= 0 && endRowIndex >= 0, Q_FUNC_INFO, "check rows");
|
||||
|
||||
int columns = columnCount();
|
||||
int rows = rowCount();
|
||||
const int columns = columnCount();
|
||||
const int rows = rowCount();
|
||||
if (columns < 1) { return; }
|
||||
if (startRowIndex < 0) { startRowIndex = 0; }
|
||||
if (endRowIndex >= rows) { endRowIndex = rows - 1; }
|
||||
const QModelIndex topLeft(createIndex(startRowIndex, 0));
|
||||
const QModelIndex bottomRight(createIndex(endRowIndex, columns - 1));
|
||||
emit dataChanged(topLeft, bottomRight);
|
||||
emit this->dataChanged(topLeft, bottomRight);
|
||||
}
|
||||
|
||||
int CListModelBaseNonTemplate::ps_updateContainer(const CVariant &variant, bool sort)
|
||||
@@ -182,6 +182,9 @@ namespace BlackGui
|
||||
{
|
||||
// non unique default name, set translation context as default
|
||||
this->setObjectName(translationContext);
|
||||
|
||||
// connect
|
||||
connect(this, &CListModelBaseNonTemplate::dataChanged, this, &CListModelBaseNonTemplate::ps_onDataChanged);
|
||||
}
|
||||
|
||||
template <typename ObjectType, typename ContainerType, bool UseCompare>
|
||||
@@ -288,7 +291,7 @@ namespace BlackGui
|
||||
this->m_container[index.row()] = obj;
|
||||
const CVariant co = CVariant::from(obj);
|
||||
emit objectChanged(co, propertyIndex);
|
||||
emit dataChanged(topLeft, bottomRight);
|
||||
emit this->dataChanged(topLeft, bottomRight);
|
||||
this->updateFilteredContainer();
|
||||
return true;
|
||||
}
|
||||
@@ -326,9 +329,9 @@ namespace BlackGui
|
||||
this->endResetModel();
|
||||
|
||||
int newSize = this->m_container.size();
|
||||
// I have to update with same size because cannot tell what data are changed
|
||||
this->emitRowCountChanged();
|
||||
Q_UNUSED(oldSize);
|
||||
// I have to update even with same size because I cannot tell what/if data are changed
|
||||
this->emitModelDataChanged();
|
||||
return newSize;
|
||||
}
|
||||
|
||||
@@ -400,7 +403,7 @@ namespace BlackGui
|
||||
this->beginResetModel();
|
||||
this->updateFilteredContainer();
|
||||
this->endResetModel();
|
||||
this->emitRowCountChanged();
|
||||
this->emitModelDataChanged();
|
||||
}
|
||||
|
||||
template <typename ObjectType, typename ContainerType, bool UseCompare>
|
||||
@@ -417,7 +420,7 @@ namespace BlackGui
|
||||
this->beginResetModel();
|
||||
this->updateFilteredContainer();
|
||||
this->endResetModel();
|
||||
this->emitRowCountChanged();
|
||||
this->emitModelDataChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -453,7 +456,7 @@ namespace BlackGui
|
||||
this->m_container.push_back(object);
|
||||
endInsertRows();
|
||||
this->updateFilteredContainer();
|
||||
this->emitRowCountChanged();
|
||||
this->emitModelDataChanged();
|
||||
}
|
||||
|
||||
template <typename ObjectType, typename ContainerType, bool UseCompare>
|
||||
@@ -469,7 +472,7 @@ namespace BlackGui
|
||||
this->updateFilteredContainer();
|
||||
this->endResetModel();
|
||||
}
|
||||
this->emitRowCountChanged();
|
||||
this->emitModelDataChanged();
|
||||
}
|
||||
|
||||
template <typename ObjectType, typename ContainerType, bool UseCompare>
|
||||
@@ -486,7 +489,7 @@ namespace BlackGui
|
||||
this->updateFilteredContainer();
|
||||
this->endResetModel();
|
||||
}
|
||||
this->emitRowCountChanged();
|
||||
this->emitModelDataChanged();
|
||||
}
|
||||
|
||||
template <typename ObjectType, typename ContainerType, bool UseCompare>
|
||||
@@ -499,7 +502,7 @@ namespace BlackGui
|
||||
int newSize = this->m_container.size();
|
||||
if (oldSize != newSize)
|
||||
{
|
||||
this->emitRowCountChanged();
|
||||
this->emitModelDataChanged();
|
||||
if (this->hasFilter())
|
||||
{
|
||||
this->beginResetModel();
|
||||
@@ -516,7 +519,7 @@ namespace BlackGui
|
||||
this->m_container.clear();
|
||||
this->m_containerFiltered.clear();
|
||||
endResetModel();
|
||||
this->emitRowCountChanged();
|
||||
this->emitModelDataChanged();
|
||||
}
|
||||
|
||||
template <typename ObjectType, typename ContainerType, bool UseCompare>
|
||||
@@ -559,13 +562,31 @@ namespace BlackGui
|
||||
}
|
||||
|
||||
template <typename ObjectType, typename ContainerType, bool UseCompare>
|
||||
void CListModelBase<ObjectType, ContainerType, UseCompare>::emitRowCountChanged()
|
||||
void CListModelBase<ObjectType, ContainerType, UseCompare>::emitModelDataChanged()
|
||||
{
|
||||
int n = this->containerOrFilteredContainer().size();
|
||||
emit this->rowCountChanged(n, this->hasFilter());
|
||||
const int n = this->containerOrFilteredContainer().size();
|
||||
emit this->modelDataChanged(n, this->hasFilter());
|
||||
emit this->changed();
|
||||
}
|
||||
|
||||
template <typename ObjectType, typename ContainerType, bool UseCompare>
|
||||
void CListModelBase<ObjectType, ContainerType, UseCompare>::ps_onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
|
||||
{
|
||||
// underlying base class changed
|
||||
Q_UNUSED(topLeft);
|
||||
Q_UNUSED(bottomRight);
|
||||
Q_UNUSED(roles);
|
||||
this->emitModelDataChanged();
|
||||
}
|
||||
|
||||
template <typename ObjectType, typename ContainerType, bool UseCompare>
|
||||
void CListModelBase<ObjectType, ContainerType, UseCompare>::ps_onChangedDigest()
|
||||
{
|
||||
const int n = this->containerOrFilteredContainer().size();
|
||||
emit this->changedDigest();
|
||||
emit this->modelDataChangedDigest(n, this->hasFilter());
|
||||
}
|
||||
|
||||
template <typename ObjectType, typename ContainerType, bool UseCompare>
|
||||
void CListModelBase<ObjectType, ContainerType, UseCompare>::moveItems(const ContainerType &items, int position)
|
||||
{
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "blackgui/models/modelfilter.h"
|
||||
#include "blackgui/dropbase.h"
|
||||
#include "blackmisc/worker.h"
|
||||
#include "blackmisc/digestsignal.h"
|
||||
#include <QStandardItemModel>
|
||||
#include <QThread>
|
||||
#include <memory>
|
||||
@@ -98,7 +99,7 @@ namespace BlackGui
|
||||
|
||||
//! Send signal that data have been changed.
|
||||
//! \note Meant for scenarios where the container is directly updated and a subsequent signal is required
|
||||
void sendDataChanged(int startRowIndex, int endRowIndex);
|
||||
void emitDataChanged(int startRowIndex, int endRowIndex);
|
||||
|
||||
//! Convert to JSON
|
||||
virtual QJsonObject toJson() const = 0;
|
||||
@@ -110,12 +111,18 @@ namespace BlackGui
|
||||
//! Asynchronous update finished
|
||||
void asyncUpdateFinished();
|
||||
|
||||
//! Number of elements changed
|
||||
void rowCountChanged(int count, bool withFilter);
|
||||
//! Data changed
|
||||
void modelDataChanged(int count, bool withFilter);
|
||||
|
||||
//! Data changed, digest version
|
||||
void modelDataChangedDigest(int count, bool withFilter);
|
||||
|
||||
//! Model has been changed
|
||||
void changed();
|
||||
|
||||
//! Model has been changed, digest signal
|
||||
void changedDigest();
|
||||
|
||||
//! Template free information, that object changed
|
||||
void objectChanged(const BlackMisc::CVariant &object, const BlackMisc::CPropertyIndex &changedIndex);
|
||||
|
||||
@@ -125,6 +132,12 @@ namespace BlackGui
|
||||
//! \param sort
|
||||
int ps_updateContainer(const BlackMisc::CVariant &variant, bool sort);
|
||||
|
||||
//! Feedback when QStandardItemModel::dataChanged was called
|
||||
virtual void ps_onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) = 0;
|
||||
|
||||
//! Digest signal
|
||||
virtual void ps_onChangedDigest() = 0;
|
||||
|
||||
protected:
|
||||
//! Constructor
|
||||
//! \param translationContext I18N context
|
||||
@@ -136,9 +149,12 @@ namespace BlackGui
|
||||
|
||||
CColumns m_columns; //!< columns metadata
|
||||
int m_sortedColumn; //!< current sort column
|
||||
Qt::SortOrder m_sortOrder; //!< sort order (asc/desc)
|
||||
bool m_modelDestroyed = false; //!< model is about to be destroyed
|
||||
Qt::SortOrder m_sortOrder; //!< sort order (asc/desc)
|
||||
Qt::DropActions m_dropActions = Qt::IgnoreAction; //!< drop actions
|
||||
|
||||
private:
|
||||
BlackMisc::CDigestSignal m_dsModelsChanged { this, &CListModelBaseNonTemplate::changed, &CListModelBaseNonTemplate::ps_onChangedDigest, 500, 10 };
|
||||
};
|
||||
|
||||
//! List model
|
||||
@@ -196,7 +212,8 @@ namespace BlackGui
|
||||
//! Update single element
|
||||
virtual void update(int rowIndex, const ObjectType &object);
|
||||
|
||||
//! Move items to position
|
||||
//! Move items to position, normally called from dropMimeData
|
||||
//! \sa dropMimeData
|
||||
virtual void moveItems(const ContainerType &items, int position);
|
||||
|
||||
//! Object at row position
|
||||
@@ -233,7 +250,7 @@ namespace BlackGui
|
||||
int removeIf(K0 k0, V0 v0, KeysValues... keysValues)
|
||||
{
|
||||
int c = m_container.removeIf(BlackMisc::Predicates::MemberEqual(k0, v0, keysValues...));
|
||||
if (c > 0) { this->emitRowCountChanged();}
|
||||
if (c > 0) { this->emitModelDataChanged();}
|
||||
this->updateFilteredContainer();
|
||||
return c;
|
||||
}
|
||||
@@ -257,14 +274,18 @@ namespace BlackGui
|
||||
//! Constructor
|
||||
CListModelBase(const QString &translationContext, QObject *parent = nullptr);
|
||||
|
||||
//! \copydoc BlackGui::Models::CListModelBaseNonTemplate::performUpdateContainer
|
||||
//! \name Base class overrides
|
||||
//! @{
|
||||
virtual int performUpdateContainer(const BlackMisc::CVariant &variant, bool sort) override;
|
||||
virtual void ps_onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomLeft, const QVector<int> &roles) override;
|
||||
virtual void ps_onChangedDigest() override;
|
||||
//! @}
|
||||
|
||||
//! Update filtered container
|
||||
void updateFilteredContainer();
|
||||
|
||||
//! Row count changed
|
||||
void emitRowCountChanged();
|
||||
void emitModelDataChanged();
|
||||
|
||||
std::unique_ptr<IModelFilter<ContainerType> > m_filter; //!< Used filter
|
||||
ContainerType m_container; //!< used container
|
||||
|
||||
@@ -72,10 +72,20 @@ namespace BlackGui
|
||||
{
|
||||
order = container[position].getOrder();
|
||||
}
|
||||
this->setSortColumnToOrder();
|
||||
container.moveTo(items, order);
|
||||
|
||||
// update container
|
||||
this->updateContainerMaybeAsync(container);
|
||||
}
|
||||
|
||||
template <typename ObjectType, typename ContainerType, typename KeyType, bool UseCompare>
|
||||
void COrderableListModelDbObjects<ObjectType, ContainerType, KeyType, UseCompare>::setSortColumnToOrder()
|
||||
{
|
||||
// force sorted by order, otherwise display looks confusing
|
||||
this->setSorting(IOrderable::IndexOrder);
|
||||
}
|
||||
|
||||
template <typename ObjectType, typename ContainerType, typename KeyType, bool UseCompare>
|
||||
int COrderableListModelDbObjects<ObjectType, ContainerType, KeyType, UseCompare>::update(const ContainerType &container, bool sort)
|
||||
{
|
||||
|
||||
@@ -73,6 +73,9 @@ namespace BlackGui
|
||||
virtual void moveItems(const ContainerType &items, int position) override;
|
||||
//! @}
|
||||
|
||||
//! Sort order to order property BlackMisc::IOrderable::IndexOrder
|
||||
void setSortColumnToOrder();
|
||||
|
||||
protected:
|
||||
//! Constructor
|
||||
COrderableListModelDbObjects(const QString &translationContext, QObject *parent = nullptr);
|
||||
|
||||
Reference in New Issue
Block a user