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. how to organize a container of views?
Qt 6.11 is out! See what's new in the release blog

how to organize a container of views?

Scheduled Pinned Locked Moved Solved General and Desktop
5 Posts 2 Posters 694 Views 2 Watching
  • 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.
  • U Offline
    U Offline
    user4592357
    wrote on last edited by
    #1

    i'm making a widget container class, that is an arbitrary number of views can be added to it:

    class Viewer : public QFrame
    {
    	Q_OBJECT
    
    public:
    	/// Constructor
    	explicit Viewer(QWidget *parent = nullptr,	Qt::WindowFlags flags = Qt::Window) noexcept;
    
    	void addView(int nIndex, QWidget *pView);
    
    	QWidget *getView(int nIndex) const;
    
    protected:
    	/// This map contains the views of the viewer
    	QHash<int, QWidget *> m_mapViews;
    
    	/// The widget container layout
    	QSplitter *m_pWidgetSplitter = nullptr;
    
    }; // class Viewer
    
    Viewer::Viewer(QWidget *parent /* = nullptr */, Qt::WindowFlags flags /* = Qt::Window */) noexcept
    	: QFrame(parent, flags)
    	, m_pWidgetSplitter(new QSplitter(this))
    {
    	// configure the layout
    	auto pWidgetsLayout = new QHBoxLayout(this);
    	pWidgetsLayout->setContentsMargins(0, 0, 0, 0);
    	pWidgetsLayout->addWidget(m_pWidgetSplitter);
    }
    
    void Viewer::addView(int nIndex, QWidget *pView)
    {
    	// save in the map
    	m_mapViews[nIndex] = pView;
    
    	// and add to the widgets layout
    	m_pWidgetSplitter->insertWidget(nIndex, pView);
    }
    
    QWidget *Viewer::getView(int nIndex) const
    {
    	return m_mapViews.contains(nIndex) ? m_mapViews[nIndex] : nullptr;
    }
    

    adding views is easy:

    Browser::Browser(QWidget *parent /* = nullptr */,
    	Qt::WindowFlags flags /* = Qt::Window */)
    	: Viewer(parent, flags)
    	, m_pTreeView(new Tree(this))
    	, m_pTableView(new Table(this))
    {
    	addView(Widgets::TreeView, m_pTreeView);
    	addView(Widgets::TableView, m_pTableView);
    }
    

    the problem here is that i need to save the pointers to get them easily:

    Tree *Browser::getTree() const
    {
    	return m_pTreeView;
    }
    
    Table *Browser::getTable() const
    {
    	return m_pTableView;
    }
    

    what i'd like to do is to use the getView function of Viewer, but in that case i need to deal with casts a lot:

    Tree *Browser::getTree() const
    {
    	return static_cast<Tree *>(getView(Widgets::TreeView));
    }
    

    how can i do this effectively?

    1 Reply Last reply
    0
    • Chris KawaC Online
      Chris KawaC Online
      Chris Kawa
      Lifetime Qt Champion
      wrote on last edited by
      #2

      You could, for example, give your classes an explicit type id:

      class Tree
      {
         enum {TypeId = Widgets::TreeView };
      };
      class Table
      {
         enum {TypeId = Widgets::TableView };
      };
      

      Then you could make a template wrapper:

      template<class T> T* getView()
      {
          return static_cast<T*>(getView(T::TypeId));
      }
      

      and use it like this:

      Tree* tree = getView<Tree>();
      Table* table = getView<Table>();
      

      If you don't want to modify your view classes like that you can do something similar outside of them i.e. make a QHash<QMetaObject*, int> m_metaTypes member and modify addView to do this:

      m_metaTypes[pView->metaObject()] = nIndex;
      

      and then the getView template wrapper would look something like this:

      template<class T> T* getView()
      {
          int nIndex = m_metaTypes[T::staticMetaObject()];
          return static_cast<T*>(getView(nIndex));
      }
      
      1 Reply Last reply
      4
      • U Offline
        U Offline
        user4592357
        wrote on last edited by user4592357
        #3

        i don't get how it's different or better from my version of getView. it's still using casts. what if i get the view a lot? it's casting all the time.

        1 Reply Last reply
        0
        • Chris KawaC Online
          Chris KawaC Online
          Chris Kawa
          Lifetime Qt Champion
          wrote on last edited by Chris Kawa
          #4

          I thought your worry was about the amount of times you had to write that cast i.e. a separate function for each type. In that case the difference is you only write that single wrapper instead of a function for each type.

          Are you actually worried about the performance of that cast? static_cast of one pointer type to another is next to nothing and in many cases, with optimizations turned on, it's actually nothing. Remember that a processor has no notion of those types. All pointers are just numbers. In some cases a processor might need to add an offset to a number when you cast which is just totally insignificant compared to other things you do in that code. A call to operator[] in the getView method is like dozens times more costly. A function call is way more costly. If you're worried about performance on that level you're definitely looking in the wrong places.

          1 Reply Last reply
          3
          • U Offline
            U Offline
            user4592357
            wrote on last edited by user4592357
            #5

            okay i get it.

            so in your first suggestion you call getView(int) from getView() which is again operator[].

            by the way, i wrote

            Tree *Browser::getTree() const
            {
            	return static_cast<Tree *>(getView(Widgets::TreeView));
            }
            Table *Browser::getTable() const
            {
            	return static_cast<Table *>(getView(Widgets::TableView));
            }
            

            to hide the implementation of the getter. although, since i'm working with views, having getView<type>(); makes sense too. i guess i'll use that option.

            1 Reply Last reply
            0

            • Login

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