[vlc-commits] [Git][videolan/vlc][master] 3 commits: qt/networkdevicemodel: Add 'maximumCount' support
Steve Lhomme (@robUx4)
gitlab at videolan.org
Sun Oct 23 12:31:06 UTC 2022
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
e02a1059 by Benjamin Arnaud at 2022-10-23T12:15:57+00:00
qt/networkdevicemodel: Add 'maximumCount' support
We also add the 'hasMoreItems' property that can be useful for our views.
- - - - -
ee384762 by Benjamin Arnaud at 2022-10-23T12:15:57+00:00
qt/networkdevicemodel: Add sorting implementation
- - - - -
e6ba01ec by Benjamin Arnaud at 2022-10-23T12:15:57+00:00
qt/networkdevicemodel: Add base filter implementation
- - - - -
2 changed files:
- modules/gui/qt/network/networkdevicemodel.cpp
- modules/gui/qt/network/networkdevicemodel.hpp
Changes:
=====================================
modules/gui/qt/network/networkdevicemodel.cpp
=====================================
@@ -110,8 +110,105 @@ void NetworkDeviceModel::setSourceName(const QString& sourceName)
int NetworkDeviceModel::getCount() const
{
- assert( m_items.size() < INT32_MAX );
- return static_cast<int>( m_items.size() );
+ return m_count;
+}
+
+int NetworkDeviceModel::maximumCount() const
+{
+ return m_maximumCount;
+}
+
+void NetworkDeviceModel::setMaximumCount(int count)
+{
+ if (m_maximumCount == count)
+ return;
+
+ if (count == -1 || m_maximumCount < count)
+ {
+ m_maximumCount = count;
+
+ expandItems();
+ }
+ else
+ {
+ m_maximumCount = count;
+
+ shrinkItems();
+ }
+
+ emit maximumCountChanged();
+}
+
+bool NetworkDeviceModel::hasMoreItems() const
+{
+ if (m_maximumCount == -1)
+ return false;
+ else
+ return ((size_t) m_count < m_items.size());
+}
+
+QString NetworkDeviceModel::searchPattern() const
+{
+ return m_searchPattern;
+}
+
+void NetworkDeviceModel::setSearchPattern(const QString & pattern)
+{
+ if (m_searchPattern == pattern)
+ return;
+
+ m_searchPattern = pattern;
+
+ emit searchPatternChanged();
+}
+
+QByteArray NetworkDeviceModel::searchRole() const
+{
+ return m_searchRole;
+}
+
+void NetworkDeviceModel::setSearchRole(const QByteArray & role)
+{
+ if (m_searchRole == role)
+ return;
+
+ m_searchRole = role;
+
+ emit searchRoleChanged();
+}
+
+QString NetworkDeviceModel::sortCriteria() const
+{
+ return m_sortCriteria;
+}
+
+void NetworkDeviceModel::setSortCriteria(const QString & criteria)
+{
+ if (m_sortCriteria == criteria)
+ return;
+
+ m_sortCriteria = criteria;
+
+ updateSort();
+
+ emit sortCriteriaChanged();
+}
+
+Qt::SortOrder NetworkDeviceModel::sortOrder() const
+{
+ return m_sortOrder;
+}
+
+void NetworkDeviceModel::setSortOrder(Qt::SortOrder order)
+{
+ if (m_sortOrder == order)
+ return;
+
+ m_sortOrder = order;
+
+ updateSort();
+
+ emit sortOrderChanged();
}
bool NetworkDeviceModel::insertIntoPlaylist(const QModelIndexList &itemIdList, ssize_t playlistIndex)
@@ -256,8 +353,13 @@ bool NetworkDeviceModel::initializeMediaSources()
m_listeners.clear();
if (!m_items.empty()) {
beginResetModel();
+
m_items.clear();
+
+ m_count = 0;
+
endResetModel();
+
emit countChanged();
}
m_name = QString {};
@@ -323,11 +425,14 @@ void NetworkDeviceModel::ListenerCb::onItemRemoved( MediaTreePtr tree, input_ite
return;
std::vector<InputItemPtr> itemList;
+
itemList.reserve( count );
for ( auto i = 0u; i < count; ++i )
itemList.emplace_back( children[i]->p_item );
QMetaObject::invokeMethod(model, [model=model, itemList=std::move(itemList)]() {
+ int implicitCount = model->implicitCount();
+
for (auto p_item : itemList)
{
QUrl itemUri = QUrl::fromEncoded(p_item->psz_uri);
@@ -349,69 +454,244 @@ void NetworkDeviceModel::ListenerCb::onItemRemoved( MediaTreePtr tree, input_ite
if ( (*it).mrls.empty() == false )
continue;
auto idx = std::distance( begin( model->m_items ), it );
- model->beginRemoveRows({}, idx, idx );
- model->m_items.erase( it );
- model->endRemoveRows();
- model->emit countChanged();
+
+ model->removeItem(it, idx, implicitCount);
}
+
+ if (model->m_maximumCount != -1)
+ model->expandItems();
}, Qt::QueuedConnection);
}
-void NetworkDeviceModel::refreshDeviceList( MediaSourcePtr mediaSource, input_item_node_t* const children[], size_t count, bool clear )
+void NetworkDeviceModel::refreshDeviceList(MediaSourcePtr mediaSource,
+ input_item_node_t * const children[], size_t count,
+ bool clear)
{
- if ( clear == true )
+ if (clear)
{
- QMetaObject::invokeMethod(this, [this, mediaSource]() {
- beginResetModel();
- m_items.erase(std::remove_if(m_items.begin(), m_items.end(), [&mediaSource](const Item& value) {
- return value.mediaSource == mediaSource;
- }), m_items.end());
- endResetModel();
- emit countChanged();
+ QMetaObject::invokeMethod(this, [this, mediaSource]()
+ {
+ int implicitCount = this->implicitCount();
+
+ int index = 0;
+
+ std::vector<Item>::iterator it = m_items.begin();
+
+ while (it != m_items.end())
+ {
+ if (it->mediaSource != mediaSource)
+ continue;
+
+ removeItem(it, index, implicitCount);
+
+ index++;
+ }
});
}
std::vector<InputItemPtr> itemList;
- itemList.reserve( count );
- for ( auto i = 0u; i < count; ++i )
- itemList.emplace_back( children[i]->p_item );
- QMetaObject::invokeMethod(this, [this, itemList=std::move(itemList), mediaSource=std::move(mediaSource) ]() mutable {
- for ( auto p_item : itemList )
+ itemList.reserve(count);
+
+ for (size_t i = 0; i < count; i++)
+ {
+ input_item_t * item = children[i]->p_item;
+
+ itemList.emplace_back(item);
+ }
+
+ QMetaObject::invokeMethod(this, [this, itemList = std::move(itemList), mediaSource]() mutable
+ {
+ addItems(itemList, mediaSource);
+ }, Qt::QueuedConnection);
+}
+
+void NetworkDeviceModel::addItems(const std::vector<InputItemPtr> & inputList,
+ const MediaSourcePtr & mediaSource)
+{
+ for (auto inputItem : inputList)
+ {
+ Item item;
+
+ item.name = qfu(inputItem->psz_name);
+
+ item.mainMrl = QUrl::fromEncoded(inputItem->psz_uri);
+
+ std::vector<Item>::iterator it = std::upper_bound(begin(m_items), end(m_items), item,
+ m_comparator);
+
+ if (it != end(m_items)
+ &&
+ QString::compare(it->name, item.name, Qt::CaseInsensitive) == 0
+ &&
+ it->mainMrl.scheme() == item.mainMrl.scheme())
+ continue;
+
+ item.mrls.push_back(item.mainMrl);
+
+ item.protocol = item.mainMrl.scheme();
+
+ item.type = static_cast<ItemType>(inputItem->i_type);
+
+ item.mediaSource = mediaSource;
+
+ item.inputItem = InputItemPtr(inputItem);
+
+ char * artwork = input_item_GetArtworkURL(inputItem.get());
+
+ if (artwork)
{
- Item item;
- item.mainMrl = QUrl::fromEncoded( p_item->psz_uri );
- item.name = qfu(p_item->psz_name);
- item.mrls.push_back( item.mainMrl );
- item.type = static_cast<ItemType>( p_item->i_type );
- item.protocol = item.mainMrl.scheme();
- item.mediaSource = std::move(mediaSource);
- item.inputItem = InputItemPtr(p_item);
-
- char* artwork = input_item_GetArtworkURL( p_item.get() );
- if (artwork)
+ item.artworkUrl = QUrl::fromEncoded(artwork);
+
+ free(artwork);
+ }
+
+ int pos = std::distance(begin(m_items), it);
+
+ if (m_maximumCount != -1 && m_count >= m_maximumCount)
+ {
+ // NOTE: When the position is beyond the maximum count we don't notify the view.
+ if (pos >= m_maximumCount)
{
- item.artworkUrl = QUrl::fromEncoded(artwork);
- free(artwork);
+ m_items.insert(it, std::move(item));
+
+ continue;
}
- auto it = std::upper_bound(begin( m_items ), end( m_items ), item, [](const Item& a, const Item& b) {
- int comp = QString::compare(a.name , b.name, Qt::CaseInsensitive );
- if (comp == 0)
- comp = QString::compare(a.mainMrl.scheme(), b.mainMrl.scheme());
- return comp <= 0;
- });
+ // NOTE: Removing the last item to make room for the new one.
- if (it != end( m_items )
- && QString::compare(it->name , item.name, Qt::CaseInsensitive ) == 0
- && it->mainMrl.scheme() == item.mainMrl.scheme())
- continue;
+ int index = m_count - 1;
+
+ beginRemoveRows({}, index, index);
+
+ m_count--;
+
+ endRemoveRows();
- int pos = std::distance(begin(m_items), it);
- beginInsertRows( {}, pos, pos );
- m_items.insert( it, std::move( item ) );
- endInsertRows();
emit countChanged();
}
- }, Qt::QueuedConnection);
+
+ beginInsertRows({}, pos, pos);
+
+ m_items.insert(it, std::move(item));
+
+ m_count++;
+
+ endInsertRows();
+
+ emit countChanged();
+ }
+
+ if (m_maximumCount != -1)
+ expandItems();
+}
+
+void NetworkDeviceModel::removeItem(std::vector<Item>::iterator & it, int index, int count)
+{
+ if (index < count)
+ {
+ beginRemoveRows({}, index, index);
+
+ it = m_items.erase(it);
+
+ m_count--;
+
+ endRemoveRows();
+
+ emit countChanged();
+ }
+ // NOTE: We don't want to notify the view if the item's position is beyond the
+ // maximumCount.
+ else
+ it = m_items.erase(it);
+}
+
+void NetworkDeviceModel::expandItems()
+{
+ int count = implicitCount();
+
+ if (m_count >= count)
+ return;
+
+ beginInsertRows({}, m_count, count - 1);
+
+ m_count = count;
+
+ endInsertRows();
+
+ emit countChanged();
+}
+
+void NetworkDeviceModel::shrinkItems()
+{
+ int count = implicitCount();
+
+ if (m_count <= count)
+ return;
+
+ beginRemoveRows({}, count, m_count - 1);
+
+ m_count = count;
+
+ endRemoveRows();
+
+ emit countChanged();
+}
+
+void NetworkDeviceModel::updateSort()
+{
+ if (m_sortCriteria == "mrl")
+ {
+ if (m_sortOrder == Qt::AscendingOrder)
+ m_comparator = ascendingMrl;
+ else
+ m_comparator = descendingMrl;
+ }
+ else
+ {
+ if (m_sortOrder == Qt::AscendingOrder)
+ m_comparator = ascendingName;
+ else
+ m_comparator = descendingName;
+ }
+
+ beginResetModel();
+
+ std::sort(m_items.begin(), m_items.end(), m_comparator);
+
+ endResetModel();
+}
+
+int NetworkDeviceModel::implicitCount() const
+{
+ assert(m_items.size() < INT32_MAX);
+
+ if (m_maximumCount == -1)
+ return (int) m_items.size();
+ else
+ return qMin((int) m_items.size(), m_maximumCount);
+}
+
+// Private static function
+
+/* static */ bool NetworkDeviceModel::ascendingName(const Item & a, const Item & b)
+{
+ return (QString::compare(a.name, b.name, Qt::CaseInsensitive) <= 0);
+}
+
+/* static */ bool NetworkDeviceModel::ascendingMrl(const Item & a, const Item & b)
+{
+ return (QString::compare(a.mainMrl.toString(),
+ b.mainMrl.toString(), Qt::CaseInsensitive) <= 0);
+}
+
+/* static */ bool NetworkDeviceModel::descendingName(const Item & a, const Item & b)
+{
+ return (QString::compare(a.name, b.name, Qt::CaseInsensitive) >= 0);
+}
+
+/* static */ bool NetworkDeviceModel::descendingMrl(const Item & a, const Item & b)
+{
+ return (QString::compare(a.mainMrl.toString(),
+ b.mainMrl.toString(), Qt::CaseInsensitive) >= 0);
}
=====================================
modules/gui/qt/network/networkdevicemodel.hpp
=====================================
@@ -81,6 +81,23 @@ public:
Q_PROPERTY(QString source_name READ getSourceName WRITE setSourceName NOTIFY sourceNameChanged FINAL)
Q_PROPERTY(int count READ getCount NOTIFY countChanged FINAL)
+ Q_PROPERTY(int maximumCount READ maximumCount WRITE setMaximumCount NOTIFY maximumCountChanged
+ FINAL)
+
+ Q_PROPERTY(bool hasMoreItems READ hasMoreItems NOTIFY countChanged FINAL)
+
+ Q_PROPERTY(QByteArray searchRole READ searchRole WRITE setSearchRole
+ NOTIFY searchRoleChanged FINAL)
+
+ Q_PROPERTY(QString searchPattern READ searchPattern WRITE setSearchPattern
+ NOTIFY searchPatternChanged FINAL)
+
+ Q_PROPERTY(QString sortCriteria READ sortCriteria WRITE setSortCriteria
+ NOTIFY sortCriteriaChanged FINAL)
+
+ Q_PROPERTY(Qt::SortOrder sortOrder READ sortOrder WRITE setSortOrder
+ NOTIFY sortOrderChanged FINAL)
+
public:
NetworkDeviceModel( QObject* parent = nullptr );
@@ -99,6 +116,23 @@ public:
int getCount() const;
+ int maximumCount() const;
+ void setMaximumCount(int count);
+
+ bool hasMoreItems() const;
+
+ QString searchPattern() const;
+ void setSearchPattern(const QString & pattern);
+
+ QByteArray searchRole() const;
+ void setSearchRole(const QByteArray & role);
+
+ QString sortCriteria() const;
+ void setSortCriteria(const QString & criteria);
+
+ Qt::SortOrder sortOrder() const;
+ void setSortOrder(Qt::SortOrder order);
+
Q_INVOKABLE bool insertIntoPlaylist( const QModelIndexList& itemIdList, ssize_t playlistIndex );
Q_INVOKABLE bool addToPlaylist( int index );
Q_INVOKABLE bool addToPlaylist(const QVariantList& itemIdList);
@@ -118,6 +152,14 @@ signals:
void nameChanged();
void countChanged();
+ void maximumCountChanged();
+
+ void searchPatternChanged();
+ void searchRoleChanged();
+
+ void sortCriteriaChanged();
+ void sortOrderChanged();
+
private:
using MediaSourcePtr = vlc_shared_data_ptr_type(vlc_media_source_t,
vlc_media_source_Hold, vlc_media_source_Release);
@@ -146,6 +188,24 @@ private:
void refreshDeviceList(MediaSourcePtr mediaSource, input_item_node_t* const children[], size_t count , bool clear);
+ void addItems(const std::vector<InputItemPtr> & inputList, const MediaSourcePtr & mediaSource);
+
+ void removeItem(std::vector<Item>::iterator & it, int index, int count);
+
+ void expandItems();
+ void shrinkItems();
+
+ void updateSort();
+
+ int implicitCount() const;
+
+private: // Static functions
+ static bool ascendingName(const Item & a, const Item & b);
+ static bool ascendingMrl (const Item & a, const Item & b);
+
+ static bool descendingName(const Item & a, const Item & b);
+ static bool descendingMrl (const Item & a, const Item & b);
+
private:
struct ListenerCb : public MediaTreeListener::MediaTreeListenerCb {
ListenerCb(NetworkDeviceModel *model, MediaSourcePtr mediaSource)
@@ -168,6 +228,19 @@ private:
QString m_sourceName; // '*' -> all sources
QString m_name; // source long name
+ int m_count = 0;
+
+ int m_maximumCount = -1;
+
+ QString m_searchPattern;
+ QByteArray m_searchRole;
+
+ QString m_sortCriteria = "name";
+
+ std::function<bool(const Item &, const Item &)> m_comparator = ascendingName;
+
+ Qt::SortOrder m_sortOrder = Qt::AscendingOrder;
+
std::vector<std::unique_ptr<MediaTreeListener>> m_listeners;
};
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b1dcc6ae54344676915ad4a05a5aa3c0fc412097...e6ba01ec308fffa4e8e555c76adcba8d0b9bd88e
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b1dcc6ae54344676915ad4a05a5aa3c0fc412097...e6ba01ec308fffa4e8e555c76adcba8d0b9bd88e
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list