[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