Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Custom Widget in QListView/QTreeView expands whole width

Custom Widget in QListView/QTreeView expands whole width

Scheduled Pinned Locked Moved Solved General and Desktop
model-viewcustom widgetmodelview
4 Posts 1 Posters 1.9k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    SKovalev
    wrote on 7 Jul 2018, 11:41 last edited by
    #1

    Hello.

    I have tried to implement custom model based on QStandadItemModel to store pointers to custom widgets and display this widgets in QListView and QTreeView. The example code could be found on GitHub.

    This works almost perfectly except two things:

    • In QListView I'd like to represent static view of widget. So I have tried to use Qt::DecorationRole but it not use my style defined in QSS file. Code snippet:
      setIconSize(QSize(200, 200));
      ...
      auto w = new Widget;
      ...
      m_model->setData(index, QIcon(w->grab()), Qt::DecorationRole);
      
    • In QTreeView I'd like to represent the real widget. But it expands the whole width of QTreeView widget. Code snippet:
      void TreeWidget::dataChanged(const QModelIndex &topLeft,
      ...
      auto expr = m_model->data(topLeft).value<Widget*>();
      setIndexWidget(topLeft, expr);
      

    To prevent expanding I have tried to set some size policy and size hint:

    Widget::Widget(QString text, QWidget *parent) : QFrame(parent)
    {
    ...
    setBaseSize(sizeHint());
    setSizeIncrement(QSize(1, 1));
    setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    }
    
    QSize Widget::sizeHint() const
    {
        return QSize(80, 80);
    }
    

    Any advice and suggestions will be greatly appreciated. Thank you very much.

    S 1 Reply Last reply 7 Jul 2018, 12:56
    0
    • S SKovalev
      7 Jul 2018, 11:41

      Hello.

      I have tried to implement custom model based on QStandadItemModel to store pointers to custom widgets and display this widgets in QListView and QTreeView. The example code could be found on GitHub.

      This works almost perfectly except two things:

      • In QListView I'd like to represent static view of widget. So I have tried to use Qt::DecorationRole but it not use my style defined in QSS file. Code snippet:
        setIconSize(QSize(200, 200));
        ...
        auto w = new Widget;
        ...
        m_model->setData(index, QIcon(w->grab()), Qt::DecorationRole);
        
      • In QTreeView I'd like to represent the real widget. But it expands the whole width of QTreeView widget. Code snippet:
        void TreeWidget::dataChanged(const QModelIndex &topLeft,
        ...
        auto expr = m_model->data(topLeft).value<Widget*>();
        setIndexWidget(topLeft, expr);
        

      To prevent expanding I have tried to set some size policy and size hint:

      Widget::Widget(QString text, QWidget *parent) : QFrame(parent)
      {
      ...
      setBaseSize(sizeHint());
      setSizeIncrement(QSize(1, 1));
      setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
      }
      
      QSize Widget::sizeHint() const
      {
          return QSize(80, 80);
      }
      

      Any advice and suggestions will be greatly appreciated. Thank you very much.

      S Offline
      S Offline
      SKovalev
      wrote on 7 Jul 2018, 12:56 last edited by
      #2

      I have found first part of solution.

      Based on star delegate example I've added my own delegate like this:

      QWidget *Delegate::createEditor(QWidget *parent,
                                      const QStyleOptionViewItem &option,
                                      const QModelIndex &index) const
      {
          Q_UNUSED(parent);
          Q_UNUSED(option);
          Q_UNUSED(index);
      
          return nullptr;
      }
      
      void Delegate::paint(QPainter *painter,
                           const QStyleOptionViewItem &option,
                           const QModelIndex &index) const
      {
          if (index.data().canConvert<Widget*>())
          {
              auto w = qvariant_cast<Widget*>(index.data());
              w->paint(painter, option.rect);
          }
          else
              QStyledItemDelegate::paint(painter, option, index);
      }
      
      QSize Delegate::sizeHint(const QStyleOptionViewItem &option,
                               const QModelIndex &index) const
      {
          if (index.data().canConvert<Widget*>())
              return qvariant_cast<Widget*>(index.data())->sizeHint();
          else
              return QStyledItemDelegate::sizeHint(option, index);
      }
      

      The implementation of `Widget::paint`` method is:

      void Widget::paint(QPainter *painter, const QRect &rect)
      {
          painter->save();
      
          painter->translate(rect.x(), rect.y());
      
          render(painter);
      
          painter->restore();
      }
      
      1 Reply Last reply
      0
      • S Offline
        S Offline
        SKovalev
        wrote on 7 Jul 2018, 13:49 last edited by
        #3

        I have updated my delegate to show widget in parent view.

        To achieve this I have changed the implementation of Delegate::paint() method like this:

            if (!index.data().canConvert<Widget*>())
                return;
        
            QAbstractItemView *p = dynamic_cast<QAbstractItemView*>(parent());
            if (p)
            {
                auto w = qvariant_cast<Widget*>(index.data());
                w->setParent(p);
                w->paint(painter, option.rect, m_enabled);
            }
            else
                qDebug() << "FATAL: Delegate's parent is not a QAbstractItemView subclass:" << parent();
        

        I have also changed Widget::paint() like this:

        void Widget::paint(QPainter *painter, const QRect &rect, bool enabled)
        {
            painter->save();
        
            move(rect.topLeft());
            setEnabled(enabled);
            show();
        
            painter->restore();
        }
        

        But I have one more issue with this code. I can't move widgets between views by pressing on them. I have to press an area next to widget to start dragging. How to avoid this?

        1 Reply Last reply
        0
        • S Offline
          S Offline
          SKovalev
          wrote on 8 Jul 2018, 19:03 last edited by
          #4

          Finaly I have finished my little example!

          Previous version have been really buggy in items move. So I have to subclass from QAbstractItemModel. Many thanks to @Patou355 with his solution.

          NB I haven't deal with mousePressEvent() yet.

          1 Reply Last reply
          1

          1/4

          7 Jul 2018, 11:41

          • Login

          • Login or register to search.
          1 out of 4
          • First post
            1/4
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved