Search code examples
c++qtselectionqlistwidgetqlistwidgetitem

How to lock an item in QListWidget Qt


is it possible to lock on an item in QListWidget, so when I press for example: a button, the item stays selected? I have tried to look it up but I failed


Solution

  • I really hope you can provide me with an example, since I am just a beginner

    Yes, I can. Here we go:

    testQListWidgetLockSelection.cc:

    #include <set>
    
    #include <QtWidgets>
    
    class ListWidget: public QListWidget {
    
      public:
        using QListWidget::QListWidget;
        virtual ~ListWidget() = default;
    
        void lockSelection(bool lock);
    
        virtual void selectionChanged(
          const QItemSelection &selected,
          const QItemSelection &deselected) override;
    
      private:
        bool _lockSel = false;
        std::set<int> _selLocked;
        bool _lockResel = false;
    
        struct LockGuard {
          bool &lock;
          LockGuard(bool &lock): lock(lock) { lock = true; }
          ~LockGuard() { lock = false; }
        };
    };
    
    void ListWidget::lockSelection(bool lock)
    {
      _lockSel = lock;
      if (_lockSel) {
        // store selected indices
        for (const QModelIndex &qMI : selectedIndexes()) _selLocked.insert(qMI.row());
      } else _selLocked.clear();
    }
    
    void ListWidget::selectionChanged(
      const QItemSelection& selected, const QItemSelection& deselected)
    {
      if (_lockSel && !_lockResel) {
        const LockGuard lock(_lockResel);
        QItemSelection reselect;
        for (int row : _selLocked) {
          const QModelIndex qMI = model()->index(row, 0);
          reselect.select(qMI, qMI);
        }
        selectionModel()->select(reselect, QItemSelectionModel::Select);
      }
    }
    
    void populate(QListWidget& qLstView)
    {
      for (int i = 1; i <= 20; ++i) {
        qLstView.addItem(QString("Item %1").arg(i));
      }
    }
    
    int main(int argc, char **argv)
    {
      qDebug() << "Qt Version:" << QT_VERSION_STR;
      QApplication app(argc, argv);
      // setup GUI
      QWidget qWinMain;
      qWinMain.resize(640, 480);
      qWinMain.setWindowTitle("Lock Selection Demo");
      QVBoxLayout qVBox;
      QCheckBox qTglLockSel("Lock Selection");
      qVBox.addWidget(&qTglLockSel, false);
      ListWidget qLstView;
      qLstView.setSelectionMode(ListWidget::ExtendedSelection);
      qVBox.addWidget(&qLstView, true);
      qWinMain.setLayout(&qVBox);
      qWinMain.show();
      // install signal handlers
      QObject::connect(&qTglLockSel, &QCheckBox::toggled,
        &qLstView, &ListWidget::lockSelection);
      // fill GUI with sample data
      populate(qLstView);
      // runtime loop
      return app.exec();
    }
    

    Demo:

    Snapshot of testQListWidgetLockSelection.exe (animated)

    Note:

    This sample has a weakness: It doesn't consider that items may be inserted or removed after the selection has been locked.

    To enhance this, the member functions rowsInserted() and rowsAboutToBeRemoved() had to be overridden as well to correct the indices in ListWidget::_selLocked respectively.