Page 1 of 2 12 LastLast
Results 1 to 20 of 23

Thread: Use "extern QStandardItemModel*" to provide access from anywhere?

  1. #1
    Join Date
    Oct 2010
    Posts
    91
    Thanks
    38

    Question Use "extern QStandardItemModel*" to provide access from anywhere?

    Hello!

    I would like to use some models (customers, articles, invoices,..) throughout my application, in every class. So far I passed them as parameters, but this gets to complicated. Is it common in this case to make models,... accessible via the keyword "extern"? Or is there another fine solution?

    Kind regards,
    HomeR

  2. #2
    Join Date
    Apr 2010
    Posts
    769
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11
    Thanks
    1
    Thanked 94 Times in 86 Posts

    Default Re: Use "extern QStandardItemModel*" to provide access from anywhere?

    Some will tell you to use a singleton pattern. This will work, but it's surprisingly difficult to get right. And in many cases it is serious overkill; it behaves exactly like any global variable, with all the potential pitfalls those bring, with the addition of lots of overhead to maintain.

    As long as modifications to the global data are well controlled - it's usually best to arrange things so there are very few points where the data is written to, while reads can occur freely - plain old globals declared 'extern' are just fine, and more complex solutions offer no real advantages.

  3. #3
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Qt products
    Qt4
    Platforms
    Windows
    Thanks
    6
    Thanked 348 Times in 333 Posts

    Default Re: Use "extern QStandardItemModel*" to provide access from anywhere?

    I'd go for more of a container solution. Rather than having the customers, articles, invoices, etc polluting the global namespace, create a management class for them and then pass a reference to this management class in the constructor of your other classes so they may use it to access the data they need.

    I certainly wouldn't use global variables for the task. You start with a single global, and then it multiplies, and then before you know it you have code that isn't maintainable or reusable easily in other projects (you have to have knowledge of the application as a whole, rather than just specific classes)

  4. The following user says thank you to squidge for this useful post:

    homerun4711 (31st December 2010)

  5. #4
    Join Date
    Oct 2010
    Posts
    91
    Thanks
    38

    Default Re: Use "extern QStandardItemModel*" to provide access from anywhere?

    Thanks for the anwers. I think I go for that container solution.

    Is there some example code around for dealing with models in that way?

  6. #5
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Qt products
    Qt4
    Platforms
    Windows
    Thanks
    6
    Thanked 348 Times in 333 Posts

    Default Re: Use "extern QStandardItemModel*" to provide access from anywhere?

    Something like: [pseudo code]

    Qt Code:
    1. class DataManager
    2. {
    3. public:
    4. DataManager(); // Remember to set m_customerModel etc to NULL in constructor
    5. ~DataManager();
    6. void SetCustomerModel(QStandardItemModel *customerModel);
    7. void SetInvoiceModel(QStandardItemModel *invoiceModel);
    8. #ifdef DEBUG
    9. QStandardItemModel *customerModel()
    10. {
    11. if (m_customerModel == NULL) throw E_NULLPOINTEREXCEPTION;
    12. return m_customerModel;
    13. }
    14. #else
    15. inline QStandardItemModel *customerModel() {return m_customerModel};
    16. inline QStandardItemModel *invoiceModel() {return m_invoiceModel};
    17. #endif
    18. private:
    19. QStandardItemModel *m_customerModel;
    20. QStandardItemModel *m_invoiceModel;
    21. };
    22.  
    23. DataManager *dmgr = new DataManager();
    24. dmgr->SetCustomerModel (myModel);
    25. [...]
    26. myNewClass = new someclass(dmgr);
    27. [...]
    28. dmgr->customerModel()->doSomething(); or pass dmgr->customerModel() pointer to some other function or class.
    29. If you added another pointer to the class and forget to call the set(), it'll just throw an exception to remind you.
    To copy to clipboard, switch view to plain text mode 

  7. The following user says thank you to squidge for this useful post:

    homerun4711 (31st December 2010)

  8. #6
    Join Date
    Oct 2010
    Posts
    91
    Thanks
    38

    Default Re: Use "extern QStandardItemModel*" to provide access from anywhere?

    Thank you very much. I already wrote some lines on this also called my class DataManager

    Kind regards,
    HomeR

  9. #7
    Join Date
    Nov 2010
    Posts
    97
    Qt products
    Qt4
    Platforms
    Windows
    Thanks
    6
    Thanked 11 Times in 11 Posts

    Default Re: Use "extern QStandardItemModel*" to provide access from anywhere?

    Quote Originally Posted by SixDegrees View Post
    Some will tell you to use a singleton pattern. This will work, but it's surprisingly difficult to get right. And in many cases it is serious overkill; it behaves exactly like any global variable, with all the potential pitfalls those bring, with the addition of lots of overhead to maintain.
    This is simply not the case.

    As long as modifications to the global data are well controlled
    And THAT would be exactly the difference (one of the most important anyway). It's impossible to control access to a global.
    This rude guy who doesn't want you to answer his questions.

    Note: An "expert" here is just someone that's posted a lot.

    "The fact of where you do the encapsulation is meaningless." - Qt Certified Developer and forum moderator

  10. #8
    Join Date
    Oct 2010
    Posts
    91
    Thanks
    38

    Default Re: Use "extern QStandardItemModel*" to provide access from anywhere?

    I wrote a container class, but now the app is crashing. I guess there is a pointer
    error somewhere, but I can't find it.

    Last output from debug is

    DataManager::customerTableView()
    Ok, first call made from here:

    Qt Code:
    1. void MainWindow::showcustomerlist()
    2. {
    3. AddressBook *customerlist = new AddressBook(dmgr);
    4. }
    To copy to clipboard, switch view to plain text mode 

    AddressBoook.cpp

    Qt Code:
    1. AddressBook::AddressBook(DataManager* dmgr, QWidget *parent): QDialog(parent)
    2. {
    3. setupUi(this);
    4. tableView = dmgr->customerTableView();
    5. }
    To copy to clipboard, switch view to plain text mode 

    DataManager.h

    Qt Code:
    1. QStandardItemModel *model_customer;
    2. QTableView *m_customerTableView;
    3. QTableView *customerTableView();
    To copy to clipboard, switch view to plain text mode 

    DataManager.cpp
    Qt Code:
    1. model_customer = new QStandardItemModel;
    2. m_customerTableView = new QTableView;
    3. m_customerTableView->setModel(model_customer);
    4. QTableView *DataManager::customerTableView() {return m_customerTableView;}
    To copy to clipboard, switch view to plain text mode 

    I hope this is enough code, just tell my if I missed some.

    Kind regards,
    HomeR

  11. #9
    Join Date
    Apr 2010
    Posts
    769
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11
    Thanks
    1
    Thanked 94 Times in 86 Posts

    Default Re: Use "extern QStandardItemModel*" to provide access from anywhere?

    Quote Originally Posted by nroberts View Post
    This is simply not the case.
    Actually, it is. I've encountered dozens of singleton implementations, and have yet to see a single one that was properly implemented. In several cases, poorly written singletons have been the source of major bugs that proved very difficult to track down. Finding and fixing the errors was made even more difficult by blind acceptance of the notion that singletons are required and somehow superior to simple globals, but programmer arrogance and the closed mindset it brings to the table is a seperate issue.

    Quote Originally Posted by nroberts View Post
    And THAT would be exactly the difference (one of the most important anyway). It's impossible to control access to a global.
    Contrary to popular belief, programmers are not mindless automata; many, or at least some, are capable of reading documentation and can even understand it. If I use a global variable, I treat it differently than I do a local because I typically bring my brain along with me when coding. Declaring an outright ban on globals is mindless oversimplification; there are, in fact, cases where they are both appropriate and preferred.

    More thoughts on singletons: Singletons Are Evil.

  12. #10
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Qt products
    Qt4
    Platforms
    Windows
    Thanks
    6
    Thanked 348 Times in 333 Posts

    Default Re: Use "extern QStandardItemModel*" to provide access from anywhere?

    Quote Originally Posted by homerun4711 View Post
    I wrote a container class, but now the app is crashing. I guess there is a pointer
    error somewhere, but I can't find it.
    Do you set all the internal variables to NULL in the constructor for the container class?

    For the debug version of the application, do you check for NULL before returning a pointer as in my example code?

    Is 'dmgr' created using 'new' rather than being stored on the stack?

  13. #11
    Join Date
    Oct 2010
    Posts
    91
    Thanks
    38

    Default Re: Use "extern QStandardItemModel*" to provide access from anywhere?

    Hm, no, I do not set all internal variables to NULL in the constructor.

    Is this neccessary even if I initialize them? If yes,, why?

    Constructor is

    Qt Code:
    1. DataManager::DataManager()
    2. {
    3. ...
    4. setupTableViews();
    5. ...
    6. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. void DataManager::setupTableViews()
    2. {
    3. m_customerTableView = new QTableView;
    4. }
    To copy to clipboard, switch view to plain text mode 

    You other question on dmgr:

    Qt Code:
    1. MainWindow::MainWindow(QWidget *parent)
    2. : QMainWindow(parent)
    3. {
    4. ...
    5. DataManager* dmgr = new DataManager();
    6. }
    To copy to clipboard, switch view to plain text mode 

  14. #12
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Qt products
    Qt4
    Platforms
    Windows
    Thanks
    6
    Thanked 348 Times in 333 Posts

    Default Re: Use "extern QStandardItemModel*" to provide access from anywhere?

    Fair enough, if you are setting the variables directly in the datamanager, then you don't need to set them to null or check the validity of them, I was assuming that another class would be initialising them with valid values.

  15. #13
    Join Date
    Oct 2010
    Posts
    91
    Thanks
    38

    Default Re: Use "extern QStandardItemModel*" to provide access from anywhere?

    Ok. I am still searching for the error...

    Is this valid?

    Qt Code:
    1. private:
    To copy to clipboard, switch view to plain text mode 

    and in the constructor

    Qt Code:
    1. AddressNew::AddressNew(DataManager* dmgr, QWidget *parent)
    2. : QDialog(parent)
    3. {
    4. model = dmgr->customerModel();
    5. }
    To copy to clipboard, switch view to plain text mode 

    Or must there be a
    Qt Code:
    1. model = new QStandardItemModel;
    To copy to clipboard, switch view to plain text mode 
    before the
    Qt Code:
    1. model = dmgr->customerModel();
    To copy to clipboard, switch view to plain text mode 
    ?

  16. #14
    Join Date
    Jan 2006
    Location
    Belgium
    Posts
    1,938
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows
    Thanked 268 Times in 268 Posts
    Wiki edits
    20

    Default Re: Use "extern QStandardItemModel*" to provide access from anywhere?

    Quote Originally Posted by homerun4711 View Post
    Is this valid?
    Syntax: yes
    Technically: this is a little bit "iffy"

    First problem: are you sure that dmgr is always valid? If dmgr isn't valid at some point, your code will most likely crash.
    Second problem: are you sure that customerModel() always returns a valid pointer? Again, this might crash your program.

    You don't need to create a new standard item model first. The dmgr object will provide the one you want.
    However, I do not see any safety checks or any guarantees that the model object is valid and existing.

  17. #15
    Join Date
    Dec 2010
    Location
    US, Washington State
    Posts
    54
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows
    Thanks
    3
    Thanked 7 Times in 7 Posts

    Default Re: Use "extern QStandardItemModel*" to provide access from anywhere?

    Quote Originally Posted by homerun4711 View Post
    Ok. I am still searching for the error...
    Qt Code:
    1. AddressNew::AddressNew(DataManager* dmgr, QWidget *parent)
    2. : QDialog(parent)
    3. {
    4. model = dmgr->customerModel();
    5. }
    To copy to clipboard, switch view to plain text mode 
    Wondering the same as tbscope, is dmgr valid. Some defensive coding will help solve these types of errors.

    Qt Code:
    1. AddressNew::AddressNew(DataManager* dmgr, QWidget *parent)
    2. : QDialog(parent)
    3. {
    4. Q_ASSERT(dmgr);
    5. model = dmgr->customerModel();
    6. Q_ASSERT(model);
    7. }
    To copy to clipboard, switch view to plain text mode 

    If either dmgr or model is NULL then the program will stop and a message will be printed to the debug console.

    Unless you know for fact that a function will always return a valid pointer, the the pointer should be checked, either with if statements or asserts.

  18. #16
    Join Date
    Nov 2010
    Posts
    97
    Qt products
    Qt4
    Platforms
    Windows
    Thanks
    6
    Thanked 11 Times in 11 Posts

    Default Re: Use "extern QStandardItemModel*" to provide access from anywhere?

    Quote Originally Posted by SixDegrees View Post
    Actually, it is. I've encountered dozens of singleton implementations, and have yet to see a single one that was properly implemented. In several cases, poorly written singletons have been the source of major bugs that proved very difficult to track down. Finding and fixing the errors was made even more difficult by blind acceptance of the notion that singletons are required and somehow superior to simple globals, but programmer arrogance and the closed mindset it brings to the table is a seperate issue.
    LOL! Well, I guess if YOU'VE never seen a "properly implemented" (and I guess we'll have to guess what you mean by that) singleton then they MUST be exactly the same as globals.

    As you sit there lamenting the poor implementations you've seen of Singletons, perhaps you should spend a little time considering exactly what criterion you'd even use to critique an implementation of a global variable. Personally, since a variable with global scope is a variable with global scope, nothing more or less, I can't think of ANY criterion that could be used. I suppose we could begin asking the same questions one might ask about a singleton, such as:

    Is it correctly initialized?

    - Can't tell without looking at entire source tree.

    Is it correctly protected in a multithreaded environment?

    - It's not protected at all so, no.

    And no, this isn't the same as asking, "Was everyone who's ever worked on our product always having a good brain day when they did anything regarding this variable?"

    Contrary to popular belief, programmers are not mindless automata; many, or at least some, are capable of reading documentation and can even understand it. If I use a global variable, I treat it differently than I do a local because I typically bring my brain along with me when coding. Declaring an outright ban on globals is mindless oversimplification; there are, in fact, cases where they are both appropriate and preferred.
    Two things:

    1) Never said globals can't be used. I would say a singleton is generally better if for no other reason than organization, but I never declared any ban on globals.

    2) Your very same argument speaks against every single OO construct out there. _I'M_ smart enough. _I_ bring my brain. _I_ know what I'm doing. _I_ don't use RAII because _I_ bring my brain when using pointers.

    Of course, nothing you just said even responds, much less refutes what I said. Singletons provide access control and that's simply not possible with globals. If you want to argue whether access control is worthwhile because YOU are too smart to use it...be my guest. I'm a pretty darn smart guy and I'll admit that I'm not THAT smart....the brain power required for such an exercise very quickly exceeds my ability to track and I don't even want to THINK about what the interns might do.

    Furthermore, as you quite fully admit in the very statements you use, some or many programmers are NOT as smart as you. If you can't write code that they can maintain...well, you're not going to be of any use to me even if you really ARE that smart.
    Last edited by nroberts; 2nd January 2011 at 10:26.
    This rude guy who doesn't want you to answer his questions.

    Note: An "expert" here is just someone that's posted a lot.

    "The fact of where you do the encapsulation is meaningless." - Qt Certified Developer and forum moderator

  19. #17
    Join Date
    Dec 2010
    Location
    US, Washington State
    Posts
    54
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows
    Thanks
    3
    Thanked 7 Times in 7 Posts

    Default Re: Use "extern QStandardItemModel*" to provide access from anywhere?

    Quote Originally Posted by SixDegrees View Post
    Actually, it is. I've encountered dozens of singleton implementations, and have yet to see a single one that was properly implemented.
    Including QApplication and QCoreApplication?

  20. #18
    Join Date
    Oct 2010
    Posts
    91
    Thanks
    38

    Red face Re: Use "extern QStandardItemModel*" to provide access from anywhere?

    Huh, I don't even know what singletons are...

    Ok, defensive coding sounds good

    I tried to find the error, but still no success.

    How is it possible to get the nice messages where the error happens?
    I forced a NULL pointer to try it...

    Qt Code:
    1. //model_customer = new QStandardItemModel;
    2. ...then
    3. Q_ASSERT(model_customer);
    4. ...or
    5. Q_CHECK_PTR(model_customer);
    To copy to clipboard, switch view to plain text mode 

    But neither Q_ASSERT nor Q_CHECK_PTR produce an output like

    ASSERT: "b == 0" in file div.cpp, line 7
    Instead I get

    &"warning: GDB: Failed to set controlling terminal: Invalid argument\n"
    terminate called after throwing an instance of 'std::bad_alloc'
    what(): std::bad_alloc

    Back to the original problem:

    addresnew.h

    Qt Code:
    To copy to clipboard, switch view to plain text mode 

    The following call for model = dmgr->customerModel(); crashes.
    Disabling it and just output some text works.

    addressnew.cpp
    Qt Code:
    1. AddressNew::AddressNew(DataManager* dmgr, QWidget *parent)
    2. : QDialog(parent)
    3. {
    4.  
    5. Q_CHECK_PTR(dmgr);
    6. Q_ASSERT(dmgr);
    7.  
    8. // the following function is accessible
    9. //model = dmgr->customerModel(); //should usually assign QStandardModelItem*, crashing!
    10. dmgr->customerModel(); //changed to test, just write QTextStream stdout. working!
    11. }
    To copy to clipboard, switch view to plain text mode 

    datamanager.h

    Qt Code:
    1. QStandardItemModel *model_customer;
    2. QStandardItemModel *customerModel();
    3. void setupModels();
    To copy to clipboard, switch view to plain text mode 

    datamanager.cpp
    Qt Code:
    1. void DataManager::setupModels()
    2. {
    3.  
    4. QTextStream out(stdout);
    5. out << "setupModels()\n";
    6.  
    7. model_customer = new QStandardItemModel;
    8. Q_ASSERT(model_customer);
    9. //not crashing here
    10. }
    11.  
    12. QStandardItemModel *DataManager::customerModel()
    13. {
    14. //QTextStream out(stdout);
    15. //out << "set customerModel()\n";
    16. Q_ASSERT(model_customer);
    17. return model_customer; //crash here if returning model is enabled
    18. }
    To copy to clipboard, switch view to plain text mode 

    I have no idea what causes the problem, can you help me?
    Just tell if you need more code.

  21. #19
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,373
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Thanks
    4
    Thanked 5,019 Times in 4,795 Posts
    Wiki edits
    10

    Default Re: Use "extern QStandardItemModel*" to provide access from anywhere?

    Quote Originally Posted by homerun4711 View Post
    Huh, I don't even know what singletons are...
    You can read about them for example here: [wiki]Singleton pattern[/wiki]
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  22. #20
    Join Date
    Dec 2010
    Location
    US, Washington State
    Posts
    54
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows
    Thanks
    3
    Thanked 7 Times in 7 Posts

    Default Re: Use "extern QStandardItemModel*" to provide access from anywhere?

    It would appear that model_customer is not initialized when customerModel() is called. Was DataManager::setupModels() called before trying to make a new instance of AddressNew? And, do you initialize all member pointers in their constructor's?

    Qt Code:
    1. DataManager::DataManager()
    2. {
    3. model_customer = NULL;
    4. }
    To copy to clipboard, switch view to plain text mode 

    If not then they are uninitialized and point anywhere.

    As for the gdb warning, no idea (running VS).
    Last edited by pkohut; 2nd January 2011 at 12:36.

Similar Threads

  1. Replies: 1
    Last Post: 7th April 2010, 22:46
  2. Replies: 3
    Last Post: 15th February 2010, 18:27
  3. Replies: 2
    Last Post: 22nd October 2009, 09:22
  4. Translation QFileDialog standart buttons ("Open"/"Save"/"Cancel")
    By victor.yacovlev in forum Qt Programming
    Replies: 4
    Last Post: 24th January 2008, 20:05
  5. Access an "embedded" MySQL-Database
    By Lykurg in forum Newbie
    Replies: 10
    Last Post: 21st February 2006, 11:28

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Qt is a trademark of The Qt Company.