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. Analyzing a complete Qt project thoroughly
Forum Updated to NodeBB v4.3 + New Features

Analyzing a complete Qt project thoroughly

Scheduled Pinned Locked Moved Unsolved General and Desktop
19 Posts 7 Posters 1.6k Views 4 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.
  • T Offline
    T Offline
    tomy
    wrote on 31 Mar 2019, 07:31 last edited by
    #1

    The project is illustrated in the official book of Qt under the name Spreadsheet, might you download it.

    My beginning question is:
    The class Cell inherits from the widget QTableWidgetItem publicly. One of its inherited methods is clone which is for creating a copy of the item:

    QTableWidgetItem* Cell::clone() const
    {
        return new Cell(*this);
    }
    

    Here Cell is called using an address (the address of the pointer pointing to the class Cell) as its argument, while the class Cell hasn't defined any parameters inside declaration!

    Second, what's the real job of clone here, in effect? If we remove that method, still we have cells drawn on the sheets.

    1 Reply Last reply
    0
    • C Offline
      C Offline
      Chris Kawa
      Lifetime Qt Champion
      wrote on 31 Mar 2019, 11:26 last edited by Chris Kawa
      #2

      This is calling a copy constructor. It has the following signature:

      Cell::Cell(const Cell&);
      

      You are right that the class does not define that explicitly, but the compiler generates this automatically if you don't specify it yourself. This is also true for a default constructor (without arguments), a move constructor and a destructor. Note that class Cell doesn't have a destructor ~Cell::Cell() defined either and yet the object is destroyed properly. That's because compiler generated that function for you.

      A copy constructor generated by the compiler performs a member-wise copy of the object i.e. if you have a class like

      class A{
         int foo;
         string bar;
      };
      

      The default generated copy constructor behaves as if you wrote:

      A::A(const A& other)
      {
          this->foo = other.foo;
          this->bar = other.bar;
      }
      

      so copies all members one by one.

      As for the purpose of clone() -it's a virtual function in the base QTableWidgetItem class. The purpose of it is to make a copy of an item. You can use it if you want to create a copy of an item. Qt also uses it internally for some stuff. This class Cell has some private members that we want to copy when a clone is created, so the function is overriden with a copy constructor.

      It's unfortunate that the example uses old style C++. If it used at least C++11 it would be more clear because that function would have the override keyword indicating that it overrides a virtual method of base class.

      If we remove that method, still we have cells drawn on the sheets.

      If you remove that function the base class method QTableWidgetItem::clone() will be used and it will call a copy constructor of QTableWidgetItem which won't copy the extra fields from class Cell. You would end up with a half-copied object. This example doesn't make a use of the cloning much, but overriding clone() is crucial if you want to have a correct behavior of a class that derives from QTableWidgetItem.

      K T 2 Replies Last reply 31 Mar 2019, 15:42
      5
      • C Chris Kawa
        31 Mar 2019, 11:26

        This is calling a copy constructor. It has the following signature:

        Cell::Cell(const Cell&);
        

        You are right that the class does not define that explicitly, but the compiler generates this automatically if you don't specify it yourself. This is also true for a default constructor (without arguments), a move constructor and a destructor. Note that class Cell doesn't have a destructor ~Cell::Cell() defined either and yet the object is destroyed properly. That's because compiler generated that function for you.

        A copy constructor generated by the compiler performs a member-wise copy of the object i.e. if you have a class like

        class A{
           int foo;
           string bar;
        };
        

        The default generated copy constructor behaves as if you wrote:

        A::A(const A& other)
        {
            this->foo = other.foo;
            this->bar = other.bar;
        }
        

        so copies all members one by one.

        As for the purpose of clone() -it's a virtual function in the base QTableWidgetItem class. The purpose of it is to make a copy of an item. You can use it if you want to create a copy of an item. Qt also uses it internally for some stuff. This class Cell has some private members that we want to copy when a clone is created, so the function is overriden with a copy constructor.

        It's unfortunate that the example uses old style C++. If it used at least C++11 it would be more clear because that function would have the override keyword indicating that it overrides a virtual method of base class.

        If we remove that method, still we have cells drawn on the sheets.

        If you remove that function the base class method QTableWidgetItem::clone() will be used and it will call a copy constructor of QTableWidgetItem which won't copy the extra fields from class Cell. You would end up with a half-copied object. This example doesn't make a use of the cloning much, but overriding clone() is crucial if you want to have a correct behavior of a class that derives from QTableWidgetItem.

        K Offline
        K Offline
        kshegunov
        Moderators
        wrote on 31 Mar 2019, 15:42 last edited by
        #3

        @Chris-Kawa said in Analyzing a complete Qt project thoroughly:

        As for the purpose of clone() -it's a virtual function in the base QTableWidgetItem class.

        Indeed, this is the so-called "virtual copy constructor". As Chris explained, the idea is to be able to properly copy polymorphic types through their base pointers/references.

        Read and abide by the Qt Code of Conduct

        1 Reply Last reply
        3
        • N Offline
          N Offline
          nona1000
          Banned
          wrote on 31 Mar 2019, 22:56 last edited by
          #4
          This post is deleted!
          1 Reply Last reply
          0
          • C Chris Kawa
            31 Mar 2019, 11:26

            This is calling a copy constructor. It has the following signature:

            Cell::Cell(const Cell&);
            

            You are right that the class does not define that explicitly, but the compiler generates this automatically if you don't specify it yourself. This is also true for a default constructor (without arguments), a move constructor and a destructor. Note that class Cell doesn't have a destructor ~Cell::Cell() defined either and yet the object is destroyed properly. That's because compiler generated that function for you.

            A copy constructor generated by the compiler performs a member-wise copy of the object i.e. if you have a class like

            class A{
               int foo;
               string bar;
            };
            

            The default generated copy constructor behaves as if you wrote:

            A::A(const A& other)
            {
                this->foo = other.foo;
                this->bar = other.bar;
            }
            

            so copies all members one by one.

            As for the purpose of clone() -it's a virtual function in the base QTableWidgetItem class. The purpose of it is to make a copy of an item. You can use it if you want to create a copy of an item. Qt also uses it internally for some stuff. This class Cell has some private members that we want to copy when a clone is created, so the function is overriden with a copy constructor.

            It's unfortunate that the example uses old style C++. If it used at least C++11 it would be more clear because that function would have the override keyword indicating that it overrides a virtual method of base class.

            If we remove that method, still we have cells drawn on the sheets.

            If you remove that function the base class method QTableWidgetItem::clone() will be used and it will call a copy constructor of QTableWidgetItem which won't copy the extra fields from class Cell. You would end up with a half-copied object. This example doesn't make a use of the cloning much, but overriding clone() is crucial if you want to have a correct behavior of a class that derives from QTableWidgetItem.

            T Offline
            T Offline
            tomy
            wrote on 1 Apr 2019, 09:12 last edited by tomy 4 Jan 2019, 09:14
            #5

            Thanks to you both.

            As for C++11, will the function be modern (11) if we declare and define it this way:

            class Cell : public QTableWidgetItem
            {
            public:
                Cell();
            
                QTableWidgetItem* clone() const override;
            ...
            
            QTableWidgetItem* Cell::clone() const override
            {
                return new Cell(*this);
            }
            

            ?

            If so, it's just information for the reader/compiler and no change in anything else!

            The other question is, the overridden function clone is needed in practice for the reason you mentioned, but where/when is it called? (A virtual/overridden function must be called somewhere in the code to perform some task, naturally)
            It creates a copy (of what?), but in effect it will be called only when we put some data into the cell for the first time.

            If we draw out the view more, we have a spreadsheet class that inherits from QTableWidget and it's for our sheets. Then we use the class Cell as our cells on the sheets. So what is the word "copy" here!? (And I'm sure it's irrelevant to copying the content of a cell into another (ctrl+c)).

            jsulmJ K 2 Replies Last reply 2 Apr 2019, 04:43
            0
            • T tomy
              1 Apr 2019, 09:12

              Thanks to you both.

              As for C++11, will the function be modern (11) if we declare and define it this way:

              class Cell : public QTableWidgetItem
              {
              public:
                  Cell();
              
                  QTableWidgetItem* clone() const override;
              ...
              
              QTableWidgetItem* Cell::clone() const override
              {
                  return new Cell(*this);
              }
              

              ?

              If so, it's just information for the reader/compiler and no change in anything else!

              The other question is, the overridden function clone is needed in practice for the reason you mentioned, but where/when is it called? (A virtual/overridden function must be called somewhere in the code to perform some task, naturally)
              It creates a copy (of what?), but in effect it will be called only when we put some data into the cell for the first time.

              If we draw out the view more, we have a spreadsheet class that inherits from QTableWidget and it's for our sheets. Then we use the class Cell as our cells on the sheets. So what is the word "copy" here!? (And I'm sure it's irrelevant to copying the content of a cell into another (ctrl+c)).

              jsulmJ Offline
              jsulmJ Offline
              jsulm
              Lifetime Qt Champion
              wrote on 2 Apr 2019, 04:43 last edited by
              #6

              @tomy said in Analyzing a complete Qt project thoroughly:

              It creates a copy (of what?)

              of "this" as you can see in the code. That means it creates a copy of the Cell instance on which it was called.
              Regarding the usage of the clone() method see https://doc.qt.io/qt-5/qtablewidget.html#setItemPrototype for example.

              https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • T tomy
                1 Apr 2019, 09:12

                Thanks to you both.

                As for C++11, will the function be modern (11) if we declare and define it this way:

                class Cell : public QTableWidgetItem
                {
                public:
                    Cell();
                
                    QTableWidgetItem* clone() const override;
                ...
                
                QTableWidgetItem* Cell::clone() const override
                {
                    return new Cell(*this);
                }
                

                ?

                If so, it's just information for the reader/compiler and no change in anything else!

                The other question is, the overridden function clone is needed in practice for the reason you mentioned, but where/when is it called? (A virtual/overridden function must be called somewhere in the code to perform some task, naturally)
                It creates a copy (of what?), but in effect it will be called only when we put some data into the cell for the first time.

                If we draw out the view more, we have a spreadsheet class that inherits from QTableWidget and it's for our sheets. Then we use the class Cell as our cells on the sheets. So what is the word "copy" here!? (And I'm sure it's irrelevant to copying the content of a cell into another (ctrl+c)).

                K Offline
                K Offline
                kshegunov
                Moderators
                wrote on 2 Apr 2019, 11:32 last edited by
                #7

                @tomy said in Analyzing a complete Qt project thoroughly:

                If so, it's just information for the reader/compiler and no change in anything else!

                Correct. But this way the compiler provides checking as well, in case you accidentally overloaded the method instead of having an override.

                It creates a copy (of what?), but in effect it will be called only when we put some data into the cell for the first time.

                It creates a copy of the object. Having a base pointer you can't directly tell what kind of object is behind it, you only know that it's either of the type of the pointer or an instance of some derived class. So clone() gives you the ability to copy the actual polymorphic object. Consider the following:

                class A
                {
                public:
                    virtual ~A();
                    virtual A * clone() const;
                }
                
                class B : public A
                {
                public:
                    A * clone() const override;
                };
                

                Say my library gives you a pointer to the base class - A *, can you tell if I created the object as an instance of A or as an instance of B? Assuming you want to copy the object, how can this be achieved if you don't know the actual type of the object behind the pointer? Here's where clone() makes sense, because in the method you know exactly the type of the object, that is to say:

                A * x = methodFromLibrary();
                A * copy = x->clone();
                

                Works properly because if you have an object of type A behind the pointer, then A::clone() is going to be called, conversely if the actual object is of type B then B::clone is going to be called. Meaning you're going to get the correct method called to make a copy. Remove the virtual out of A::clone and you can't copy the object anymore, because you'd always get A::clone() called.

                Read and abide by the Qt Code of Conduct

                T 1 Reply Last reply 20 May 2019, 08:35
                3
                • K kshegunov
                  2 Apr 2019, 11:32

                  @tomy said in Analyzing a complete Qt project thoroughly:

                  If so, it's just information for the reader/compiler and no change in anything else!

                  Correct. But this way the compiler provides checking as well, in case you accidentally overloaded the method instead of having an override.

                  It creates a copy (of what?), but in effect it will be called only when we put some data into the cell for the first time.

                  It creates a copy of the object. Having a base pointer you can't directly tell what kind of object is behind it, you only know that it's either of the type of the pointer or an instance of some derived class. So clone() gives you the ability to copy the actual polymorphic object. Consider the following:

                  class A
                  {
                  public:
                      virtual ~A();
                      virtual A * clone() const;
                  }
                  
                  class B : public A
                  {
                  public:
                      A * clone() const override;
                  };
                  

                  Say my library gives you a pointer to the base class - A *, can you tell if I created the object as an instance of A or as an instance of B? Assuming you want to copy the object, how can this be achieved if you don't know the actual type of the object behind the pointer? Here's where clone() makes sense, because in the method you know exactly the type of the object, that is to say:

                  A * x = methodFromLibrary();
                  A * copy = x->clone();
                  

                  Works properly because if you have an object of type A behind the pointer, then A::clone() is going to be called, conversely if the actual object is of type B then B::clone is going to be called. Meaning you're going to get the correct method called to make a copy. Remove the virtual out of A::clone and you can't copy the object anymore, because you'd always get A::clone() called.

                  T Offline
                  T Offline
                  tomy
                  wrote on 20 May 2019, 08:35 last edited by
                  #8

                  @kshegunov

                  Correct. But this way the compiler provides checking as well, in case you accidentally overloaded the method instead of having an override.

                  Very good, thanks.
                  Worth to know that when I write override as with the above post of me for the definition part, the compiler doesn't recognise it. Should I merely write it in the declaration?

                  Say my library gives you a pointer to the base class - A *, can you tell if I created the object as an instance of A or as an instance of B?

                  I suppose, no, because it's not yet been addressed.

                  Assuming you want to copy the object, how can this be achieved if you don't know the actual type of the object behind the pointer? Here's where clone() makes sense, because in the method you know exactly the type of the object, that is to say:

                  A * x = methodFromLibrary();
                  A * copy = x->clone();
                  

                  Works properly because if you have an object of type A behind the pointer, then A::clone() is going to be called, conversely if the actual object is of type B then B::clone is going to be called. Meaning you're going to get the correct method called to make a copy. Remove the virtual out of A::clone and you can't copy the object anymore, because you'd always get A::clone() called.

                  I know of virtual functions in C++, but the whole thing is rather mess in the use of this program.
                  Thank you.

                  I also set override for setData and data functions in Cell.

                  K 1 Reply Last reply 20 May 2019, 08:44
                  0
                  • T tomy
                    20 May 2019, 08:35

                    @kshegunov

                    Correct. But this way the compiler provides checking as well, in case you accidentally overloaded the method instead of having an override.

                    Very good, thanks.
                    Worth to know that when I write override as with the above post of me for the definition part, the compiler doesn't recognise it. Should I merely write it in the declaration?

                    Say my library gives you a pointer to the base class - A *, can you tell if I created the object as an instance of A or as an instance of B?

                    I suppose, no, because it's not yet been addressed.

                    Assuming you want to copy the object, how can this be achieved if you don't know the actual type of the object behind the pointer? Here's where clone() makes sense, because in the method you know exactly the type of the object, that is to say:

                    A * x = methodFromLibrary();
                    A * copy = x->clone();
                    

                    Works properly because if you have an object of type A behind the pointer, then A::clone() is going to be called, conversely if the actual object is of type B then B::clone is going to be called. Meaning you're going to get the correct method called to make a copy. Remove the virtual out of A::clone and you can't copy the object anymore, because you'd always get A::clone() called.

                    I know of virtual functions in C++, but the whole thing is rather mess in the use of this program.
                    Thank you.

                    I also set override for setData and data functions in Cell.

                    K Offline
                    K Offline
                    kshegunov
                    Moderators
                    wrote on 20 May 2019, 08:44 last edited by kshegunov
                    #9

                    @tomy said in Analyzing a complete Qt project thoroughly:

                    Worth to know that when I write override as with the above post of me for the definition part, the compiler doesn't recognise it. Should I merely write it in the declaration?

                    Yes, the override specifier goes only in the declaration, it's not part of the function prototype so it makes no sense in the definition.

                    I suppose, no, because it's not yet been addressed.

                    Incorrect. The object is there it's real, the handle to it (i.e. the pointer) is what hides the actual implementation. Notice the following is correct:

                    A * x = new A;
                    A * y = new B;
                    

                    Both these objects can be addressed through a pointer to the base class. Implicit upcasting is expected and normal. In the end B IS A.

                    Read and abide by the Qt Code of Conduct

                    T 1 Reply Last reply 22 May 2019, 07:15
                    2
                    • K kshegunov
                      20 May 2019, 08:44

                      @tomy said in Analyzing a complete Qt project thoroughly:

                      Worth to know that when I write override as with the above post of me for the definition part, the compiler doesn't recognise it. Should I merely write it in the declaration?

                      Yes, the override specifier goes only in the declaration, it's not part of the function prototype so it makes no sense in the definition.

                      I suppose, no, because it's not yet been addressed.

                      Incorrect. The object is there it's real, the handle to it (i.e. the pointer) is what hides the actual implementation. Notice the following is correct:

                      A * x = new A;
                      A * y = new B;
                      

                      Both these objects can be addressed through a pointer to the base class. Implicit upcasting is expected and normal. In the end B IS A.

                      T Offline
                      T Offline
                      tomy
                      wrote on 22 May 2019, 07:15 last edited by
                      #10

                      @kshegunov

                      How to see the definition of virtual QTableWidgetItem *clone() const; in qtablewidget.cpp on Qt Creator, please?

                      In the Docs, it's only written it creates a copy of the item. I want firstly see the way it's defined in qtablewidget.cpp.

                      K aha_1980A 2 Replies Last reply 22 May 2019, 07:21
                      0
                      • T tomy
                        22 May 2019, 07:15

                        @kshegunov

                        How to see the definition of virtual QTableWidgetItem *clone() const; in qtablewidget.cpp on Qt Creator, please?

                        In the Docs, it's only written it creates a copy of the item. I want firstly see the way it's defined in qtablewidget.cpp.

                        K Offline
                        K Offline
                        kshegunov
                        Moderators
                        wrote on 22 May 2019, 07:21 last edited by
                        #11

                        Here. It's trivially defined as one'd expect.

                        Read and abide by the Qt Code of Conduct

                        1 Reply Last reply
                        3
                        • T tomy
                          22 May 2019, 07:15

                          @kshegunov

                          How to see the definition of virtual QTableWidgetItem *clone() const; in qtablewidget.cpp on Qt Creator, please?

                          In the Docs, it's only written it creates a copy of the item. I want firstly see the way it's defined in qtablewidget.cpp.

                          aha_1980A Offline
                          aha_1980A Offline
                          aha_1980
                          Lifetime Qt Champion
                          wrote on 22 May 2019, 07:23 last edited by
                          #12

                          @tomy You have to install the Qt sources to see the cpp files - can be done with MaintenanceTool.

                          Or have a look at https://code.woboq.org/qt5/qtbase/src/widgets/itemviews/qtablewidget.cpp.html

                          Qt has to stay free or it will die.

                          1 Reply Last reply
                          2
                          • T Offline
                            T Offline
                            tomy
                            wrote on 22 May 2019, 08:59 last edited by
                            #13

                            So starting from the main.cpp file, where all Qt and QML programs start executing all of their statements from, we begin by creating a new object of the project "MainWindow" using new on heap as below,

                            #include <QApplication>
                            #include "mainwindow.h"
                            
                            int main(int argc, char *argv[])
                            {
                                QApplication app(argc, argv);
                                
                                MainWindow* mainWin = new MainWindow;
                                mainWin->show();
                                
                                return app.exec();
                            }
                            

                            In the constructor of MainWindow we have:

                            MainWindow::MainWindow()
                            {
                                spreadsheet = new Spreadsheet;
                                setCentralWidget(spreadsheet);
                            
                                createActions();
                                createMenus();
                                createContextMenu();
                                createToolBars();
                                createStatusBar();
                            
                                readSettings();
                            
                                findDialog = nullptr;
                            
                                setWindowIcon(QIcon(":/images/icon.png"));
                                setCurrentFile("");
                            }
                            

                            By spreadsheet = new Spreadsheet; the constructor of Spreadsheet is called, as shown below:

                            Spreadsheet::Spreadsheet(QWidget *parent)
                                : QTableWidget(parent)
                            {
                                autoRecalc = true;
                            
                                setItemPrototype(new Cell);
                                setSelectionMode(ContiguousSelection);
                            
                                connect(this, SIGNAL(itemChanged(QTableWidgetItem *)),
                                        this, SLOT(somethingChanged()));
                            
                                clear();
                            }
                            

                            then we specify the item prototype for the table to be new Cell. This, in turn, call's Cell's constructor:

                            Cell::Cell()
                            {
                                setDirty();
                            }
                            

                            Up to now, we have a spreadsheet table created on the main screen of the project's window and its cells' prototype is of a Cell, that is, they're by default dirty.

                            All right up to here?

                            Now, let me re-ask this question, please:
                            where/when in code the overridden function clone is called?

                            jsulmJ K 2 Replies Last reply 22 May 2019, 10:36
                            0
                            • T tomy
                              22 May 2019, 08:59

                              So starting from the main.cpp file, where all Qt and QML programs start executing all of their statements from, we begin by creating a new object of the project "MainWindow" using new on heap as below,

                              #include <QApplication>
                              #include "mainwindow.h"
                              
                              int main(int argc, char *argv[])
                              {
                                  QApplication app(argc, argv);
                                  
                                  MainWindow* mainWin = new MainWindow;
                                  mainWin->show();
                                  
                                  return app.exec();
                              }
                              

                              In the constructor of MainWindow we have:

                              MainWindow::MainWindow()
                              {
                                  spreadsheet = new Spreadsheet;
                                  setCentralWidget(spreadsheet);
                              
                                  createActions();
                                  createMenus();
                                  createContextMenu();
                                  createToolBars();
                                  createStatusBar();
                              
                                  readSettings();
                              
                                  findDialog = nullptr;
                              
                                  setWindowIcon(QIcon(":/images/icon.png"));
                                  setCurrentFile("");
                              }
                              

                              By spreadsheet = new Spreadsheet; the constructor of Spreadsheet is called, as shown below:

                              Spreadsheet::Spreadsheet(QWidget *parent)
                                  : QTableWidget(parent)
                              {
                                  autoRecalc = true;
                              
                                  setItemPrototype(new Cell);
                                  setSelectionMode(ContiguousSelection);
                              
                                  connect(this, SIGNAL(itemChanged(QTableWidgetItem *)),
                                          this, SLOT(somethingChanged()));
                              
                                  clear();
                              }
                              

                              then we specify the item prototype for the table to be new Cell. This, in turn, call's Cell's constructor:

                              Cell::Cell()
                              {
                                  setDirty();
                              }
                              

                              Up to now, we have a spreadsheet table created on the main screen of the project's window and its cells' prototype is of a Cell, that is, they're by default dirty.

                              All right up to here?

                              Now, let me re-ask this question, please:
                              where/when in code the overridden function clone is called?

                              jsulmJ Offline
                              jsulmJ Offline
                              jsulm
                              Lifetime Qt Champion
                              wrote on 22 May 2019, 10:36 last edited by
                              #14

                              @tomy Put a break point inside your clone() and run through debugger. When debugger stops inside clone() you will have a stack trace where you can see from where it was called.

                              https://forum.qt.io/topic/113070/qt-code-of-conduct

                              T 1 Reply Last reply 23 May 2019, 08:44
                              3
                              • mrjjM Offline
                                mrjjM Offline
                                mrjj
                                Lifetime Qt Champion
                                wrote on 22 May 2019, 14:47 last edited by
                                #15

                                Hi
                                Unless you added new code to sample to call it, ( from to p post)
                                Its not called as i can rename it to cloneX() and it still compiles meaning
                                its not used at all. (currently)

                                1 Reply Last reply
                                1
                                • T tomy
                                  22 May 2019, 08:59

                                  So starting from the main.cpp file, where all Qt and QML programs start executing all of their statements from, we begin by creating a new object of the project "MainWindow" using new on heap as below,

                                  #include <QApplication>
                                  #include "mainwindow.h"
                                  
                                  int main(int argc, char *argv[])
                                  {
                                      QApplication app(argc, argv);
                                      
                                      MainWindow* mainWin = new MainWindow;
                                      mainWin->show();
                                      
                                      return app.exec();
                                  }
                                  

                                  In the constructor of MainWindow we have:

                                  MainWindow::MainWindow()
                                  {
                                      spreadsheet = new Spreadsheet;
                                      setCentralWidget(spreadsheet);
                                  
                                      createActions();
                                      createMenus();
                                      createContextMenu();
                                      createToolBars();
                                      createStatusBar();
                                  
                                      readSettings();
                                  
                                      findDialog = nullptr;
                                  
                                      setWindowIcon(QIcon(":/images/icon.png"));
                                      setCurrentFile("");
                                  }
                                  

                                  By spreadsheet = new Spreadsheet; the constructor of Spreadsheet is called, as shown below:

                                  Spreadsheet::Spreadsheet(QWidget *parent)
                                      : QTableWidget(parent)
                                  {
                                      autoRecalc = true;
                                  
                                      setItemPrototype(new Cell);
                                      setSelectionMode(ContiguousSelection);
                                  
                                      connect(this, SIGNAL(itemChanged(QTableWidgetItem *)),
                                              this, SLOT(somethingChanged()));
                                  
                                      clear();
                                  }
                                  

                                  then we specify the item prototype for the table to be new Cell. This, in turn, call's Cell's constructor:

                                  Cell::Cell()
                                  {
                                      setDirty();
                                  }
                                  

                                  Up to now, we have a spreadsheet table created on the main screen of the project's window and its cells' prototype is of a Cell, that is, they're by default dirty.

                                  All right up to here?

                                  Now, let me re-ask this question, please:
                                  where/when in code the overridden function clone is called?

                                  K Offline
                                  K Offline
                                  kshegunov
                                  Moderators
                                  wrote on 22 May 2019, 20:27 last edited by
                                  #16

                                  @tomy said in Analyzing a complete Qt project thoroughly:

                                  Now, let me re-ask this question, please:
                                  where/when in code the overridden function clone is called?

                                  Qt calls it when it needs a new object. That's why you call setItemPrototype. It (Qt) uses the object you passed to use it as item factory to create new items. It's unimportant for all practical purposes where exactly the call originates.

                                  Read and abide by the Qt Code of Conduct

                                  1 Reply Last reply
                                  2
                                  • jsulmJ jsulm
                                    22 May 2019, 10:36

                                    @tomy Put a break point inside your clone() and run through debugger. When debugger stops inside clone() you will have a stack trace where you can see from where it was called.

                                    T Offline
                                    T Offline
                                    tomy
                                    wrote on 23 May 2019, 08:44 last edited by
                                    #17

                                    @jsulm

                                    I did it and it was the output. I think the stack trace part is the bottom-left window.
                                    1- What can be gained from this?

                                    0_1558599336654_Capture_1.PNG

                                    @mrjj, I didn't understand your sentences at all, sadly! -_-

                                    @kshegunov

                                    As I've said earlier, in effect clone will be called only when we put some data into a cell of the table for the first time.

                                    Qt calls it when it needs a new object. That's why you call setItemPrototype.

                                    2- Do you mean when we call setItemPrototype(new Cell); Qt calls clone? That is, whenever in the code we create a new cell using new that clone function is called.

                                    It (Qt) uses the object you passed to use it as item factory to create new items. It's unimportant for all practical purposes where exactly the call originates.

                                    I see, but for a learner of Qt, like me, it's good to boost their Qt abilities by finding answers even for small/detailed questions too.
                                    3- How do you know, when we create a new Cell, Qt calls that clone function? Where is it specified in the code, please?

                                    I numbered my questions so that you helpers don't ignore a question.
                                    4- Previously I asked, "All right up to here?". It's important for me, because I want to thoroughly understand the program's code, even step-by-step.

                                    Thanks to all.

                                    jsulmJ 1 Reply Last reply 23 May 2019, 10:15
                                    0
                                    • T tomy
                                      23 May 2019, 08:44

                                      @jsulm

                                      I did it and it was the output. I think the stack trace part is the bottom-left window.
                                      1- What can be gained from this?

                                      0_1558599336654_Capture_1.PNG

                                      @mrjj, I didn't understand your sentences at all, sadly! -_-

                                      @kshegunov

                                      As I've said earlier, in effect clone will be called only when we put some data into a cell of the table for the first time.

                                      Qt calls it when it needs a new object. That's why you call setItemPrototype.

                                      2- Do you mean when we call setItemPrototype(new Cell); Qt calls clone? That is, whenever in the code we create a new cell using new that clone function is called.

                                      It (Qt) uses the object you passed to use it as item factory to create new items. It's unimportant for all practical purposes where exactly the call originates.

                                      I see, but for a learner of Qt, like me, it's good to boost their Qt abilities by finding answers even for small/detailed questions too.
                                      3- How do you know, when we create a new Cell, Qt calls that clone function? Where is it specified in the code, please?

                                      I numbered my questions so that you helpers don't ignore a question.
                                      4- Previously I asked, "All right up to here?". It's important for me, because I want to thoroughly understand the program's code, even step-by-step.

                                      Thanks to all.

                                      jsulmJ Offline
                                      jsulmJ Offline
                                      jsulm
                                      Lifetime Qt Champion
                                      wrote on 23 May 2019, 10:15 last edited by jsulm
                                      #18

                                      @tomy said in Analyzing a complete Qt project thoroughly:

                                      What can be gained from this?

                                      That clone was called from QTableModel::createItem, which was called from QTableModel::setData and so on.

                                      "2- Do you mean when we call setItemPrototype(new Cell); Qt calls clone? That is, whenever in the code we create a new cell using new that clone function is called." - please read https://doc.qt.io/qt-5/qstandarditemmodel.html#setItemPrototype It is explained there.

                                      3- How do you know, when we create a new Cell, Qt calls that clone function? Where is it specified in the code, please? - clone() is NOT called when you create an instance of Cell. Please read the link above. It is called whenever new item needs to be created:
                                      "Whenever QStandardItemModel needs to create an item on demand (for instance, when a view or item delegate calls setData()))"

                                      https://forum.qt.io/topic/113070/qt-code-of-conduct

                                      T 1 Reply Last reply 27 May 2019, 09:23
                                      2
                                      • jsulmJ jsulm
                                        23 May 2019, 10:15

                                        @tomy said in Analyzing a complete Qt project thoroughly:

                                        What can be gained from this?

                                        That clone was called from QTableModel::createItem, which was called from QTableModel::setData and so on.

                                        "2- Do you mean when we call setItemPrototype(new Cell); Qt calls clone? That is, whenever in the code we create a new cell using new that clone function is called." - please read https://doc.qt.io/qt-5/qstandarditemmodel.html#setItemPrototype It is explained there.

                                        3- How do you know, when we create a new Cell, Qt calls that clone function? Where is it specified in the code, please? - clone() is NOT called when you create an instance of Cell. Please read the link above. It is called whenever new item needs to be created:
                                        "Whenever QStandardItemModel needs to create an item on demand (for instance, when a view or item delegate calls setData()))"

                                        T Offline
                                        T Offline
                                        tomy
                                        wrote on 27 May 2019, 09:23 last edited by
                                        #19

                                        @jsulm

                                        Thank you for your explanations, they're beneficial. But since the subject is somehow sophisticated and I myself am tackling various topics and these days very busy, I have some delay to come to this thread. sorry.

                                        I got much about clone() by now and will postpone further studying when I get to it in the code, when after the app is run completely.

                                        Back to studying the code via the step-by-step approach, I reached the statement setDirty(); in Cell.

                                        ==> After setDirty();, we step forward to itemChanged(QTableWidgetItem *) which is a signal to signify that the content of the item/cell is changed. Right? (1)

                                        Then we see the slot somethingChanged where recalculate() is called where all the cells in the spreadsheet there, will be set as dirty if they contain something. But why 'all' the cells? (2)

                                        The the viewport() function returns the viewport widget and the update() function updates (cleans) the rectangle inside the widget which is a cell here. Right? (3)

                                        The next question (4) is about emit modified();. What does it do or where is it used? I couldn't find somewhere it is used in code.

                                        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