Results 1 to 10 of 10

Thread: Weird problems when destructor is called

  1. #1
    Join Date
    Jan 2008
    Posts
    58
    Thanks
    3
    Qt products
    Qt4
    Platforms
    MacOS X

    Default Weird problems when destructor is called

    Hi everybody,


    I'm busy for a long time on this project, and currently it's killing me.

    The goal is to print a excel sheet look-a-like this is the code that I wrote.

    The function that invokes the proces
    Qt Code:
    1. void MainWindow::printSurvey()
    2. {
    3. QPrinter printer;
    4.  
    5. printer.setOrientation(QPrinter::Landscape);
    6.  
    7. QPrintDialog dlg(&printer, this);
    8. if(dlg.exec() == QDialog::Accepted)
    9. {
    10. TablePrint *print = new TablePrint(printer, this);
    11.  
    12.  
    13. print->setOffsetTop(10);
    14. print->setOffsetBottom(10);
    15. print->setOffsetLeft(10);
    16. print->setOffsetRight(10);
    17.  
    18. QMap<int, QMap<QString, QString> > header;
    19. QMap<int, QMap<int, QMap<QString, QString> > > data;
    20.  
    21. //header format header[columnNumber][identifier] = value
    22. header[0]["width"] = "100";
    23. header[0]["height"] = "20";
    24. header[0]["fillColor"] = "blue";
    25. header[0]["text"] = "column1";
    26. header[1]["width"] = "100";
    27. header[1]["height"] = "20";
    28. header[1]["fillColor"] = "blue";
    29. header[1]["text"] = "column2";
    30. header[2]["width"] = "100";
    31. header[2]["height"] = "20";
    32. header[2]["fillColor"] = "blue";
    33. header[2]["text"] = "column3";
    34.  
    35. //data format data[rowNumber][columnNumber][identifier] = value
    36. data[0][0]["text"] = "column_1_row_1_artikel";
    37. data[0][0]["fillColor"] = "white";
    38. data[0][1]["text"] = "column_2_row_1_artikel";
    39. data[0][1]["fillColor"] = "red";
    40. data[0][2]["text"] = "column_3_row_1_artikel";
    41. data[0][2]["fillColor"] = "green";
    42.  
    43. data[1][0]["text"] = "column_1_row_2_artikel";
    44. data[1][0]["fillColor"] = "white";
    45. data[1][1]["text"] = "column_2_row_2_artikel";
    46. data[1][1]["fillColor"] = "red";
    47. data[1][2]["text"] = "column_3_row_2_artikel";
    48. data[1][2]["fillColor"] = "green";
    49.  
    50. data[2][0]["text"] = "column_1_row_3_artikel";
    51. data[2][0]["fillColor"] = "white";
    52. data[2][1]["text"] = "column_2_row_3_artikel";
    53. data[2][1]["fillColor"] = "red";
    54. data[2][2]["text"] = "column_3_row_3_artikel";
    55. data[2][2]["fillColor"] = "green";
    56.  
    57. data[3][0]["text"] = "column_1_row_4_artikel";
    58. data[3][0]["fillColor"] = "white";
    59. data[3][1]["text"] = "column_2_row_4_artikel";
    60. data[3][1]["fillColor"] = "red";
    61. data[3][2]["text"] = "column_3_row_4_artikel";
    62. data[3][2]["fillColor"] = "green";
    63.  
    64.  
    65.  
    66. print->dataPrint(header, data);
    67.  
    68. delete print;
    69.  
    70. }
    71.  
    72.  
    73.  
    74. }
    To copy to clipboard, switch view to plain text mode 

    I divided the responsibility to several scripts:
    1. Tableprint
    2. Tablerow
    3. Tablecolumn
    4. Tablecell


    Maybe you all ready noticed that you don't need 3 things to receive the coordinates of a 2D frame.

    So what I did was delegating the responsibility to table row. So you can see tablerow as the controller. The row controls the columns which controls the cells.

    A simple example, when you want to retrieve row 2 column 1 than you will access the table row, which can access the column in this case 1 and the column contains all the cell beneath him, so we pass the parameter 2 so the column knows that we want to retrieve cell 2.

    I thought that this idea would be the solution to my problem, but it's giving me troubles.

    Here are the other scripts:

    Tableprint.h
    Qt Code:
    1. #ifndef TABLEPRINT_H
    2. #define TABLEPRINT_H
    3.  
    4. #include <QObject>
    5. #include <QPainter>
    6. #include <QStringList>
    7. #include <QPrinter>
    8. #include <QString>
    9. #include <QList>
    10.  
    11. class TableRow;
    12.  
    13.  
    14. class TablePrint : public QObject
    15. {
    16. Q_OBJECT
    17. public:
    18. TablePrint(QPrinter&, QObject *parent = 0);
    19.  
    20. //setters
    21. void setOffsetTop(int offset);
    22. void setOffsetLeft(int offset);
    23. void setOffsetRight(int offset);
    24. void setOffsetBottom(int offset);
    25. void setDynamicHeight(bool b);
    26.  
    27. //print functions
    28. void dataPrint(QMap<int, QMap<QString, QString> > header, QMap<int, QMap<int, QMap<QString, QString> > > data);
    29.  
    30. ~TablePrint();
    31. private:
    32. int offsetTop;
    33. int offsetLeft;
    34. int offsetRight;
    35. int offsetBottom;
    36. int width;
    37. int height;
    38. bool dynamicHeight;
    39. int rows;
    40. TableRow *tableRow;
    41. QPainter painter;
    42.  
    43. };
    44.  
    45. #endif
    To copy to clipboard, switch view to plain text mode 

    Tableprint.cpp
    Qt Code:
    1. #include "tablePrint.h"
    2. #include <QtGui>
    3. #include <QPainter>
    4. #include <QPrinter>
    5. #include "tableRow.h"
    6. #include <QMap>
    7. #include <QMapIterator>
    8.  
    9.  
    10. TablePrint::TablePrint(QPrinter& printer, QObject *parent)
    11. : QObject(parent), painter(&printer){
    12. qDebug("TablePrint::TablePrint():start printing");
    13. this->rows = 0;
    14. this->offsetTop = 0;
    15. this->offsetRight = 0;
    16. this->offsetBottom = 0;
    17. this->offsetLeft = 0;
    18. this->dynamicHeight = false;
    19. this->width = 0;
    20. this->height = 0;
    21.  
    22.  
    23. this->width = printer.pageRect().width() - this->offsetLeft - this->offsetRight;
    24. this->height = printer.pageRect().height() - this->offsetBottom - this->offsetTop;
    25.  
    26.  
    27.  
    28.  
    29. }
    30.  
    31.  
    32. void TablePrint::dataPrint(QMap<int, QMap<QString, QString> > header, QMap<int, QMap<int, QMap<QString, QString> > > data)
    33. {
    34. qDebug("TablePrint::dataPrint():printing row data");
    35.  
    36. this->tableRow = new TableRow(QRect(this->offsetLeft, this->offsetTop, (this->width - this->offsetLeft - this->offsetRight), (this->height - this->offsetTop - this->offsetBottom)), this);
    37.  
    38. //set the header data
    39. this->tableRow->setHeaderData(header);
    40.  
    41. //sets the dynamic height to false, so all the cells will have the same height
    42. this->tableRow->setDynamicHeight(false);
    43.  
    44.  
    45. QMap<int, QMap<int, QMap<QString, QString> > >::const_iterator i = data.constBegin();
    46.  
    47. //loop the iterator
    48. while(i != data.constEnd() )
    49. {
    50. QMap<int, QMap<QString, QString> > rowData = data.value(i.key());
    51. this->tableRow->setRowData(rowData);
    52. this->rows++;
    53.  
    54. i++;
    55.  
    56. }
    57.  
    58. //column print
    59. this->tableRow->draw(0, this->painter);
    60.  
    61. for( int i = 2; i < (this->rows+2); i++)
    62. {
    63. this->tableRow->draw(i, this->painter);
    64.  
    65.  
    66. }
    67.  
    68.  
    69. this->painter.end();
    70.  
    71.  
    72. }
    73.  
    74. void TablePrint::setOffsetTop(int offset){this->offsetTop = offset; if(!this->offsetBottom) this->offsetBottom = offset;};
    75. void TablePrint::setOffsetLeft(int offset){this->offsetLeft = offset; if(!this->offsetRight) this->offsetRight = offset;};
    76. void TablePrint::setOffsetRight(int offset){this->offsetRight = offset;};
    77. void TablePrint::setOffsetBottom(int offset){this->offsetBottom = offset;};
    78. void TablePrint::setDynamicHeight(bool b){this->dynamicHeight = b;};
    To copy to clipboard, switch view to plain text mode 

    Tablerow.h
    Qt Code:
    1. #ifndef TABLEROW_H
    2. #define TABLEROW_H
    3.  
    4. #include <QObject>
    5. #include <QPainter>
    6. #include <QStringList>
    7. #include <QRect>
    8.  
    9. class TableCell;
    10. class TableColumn;
    11.  
    12. class TableRow : public QObject
    13. {
    14. Q_OBJECT
    15. public:
    16. TableRow(QRect, QObject *parent = 0);
    17. void setHeaderData(QMap<int, QMap<QString, QString> > data);
    18. void setRowData(QMap<int, QMap<QString, QString> > data);
    19. void draw(int row, QPainter&);
    20. void setRemember(bool rememberLocal){this->remember = rememberLocal;};
    21. void setDynamicHeight(bool b) {this->dynamicHeight = b;};
    22. int getMaxColumnHeight(){return this->maxColumnHeight;};
    23. ~TableRow();
    24.  
    25. private:
    26. int columns;
    27. int currentRow;
    28. int maxColumnHeight;
    29. TableColumn *tableColumns[];
    30.  
    31. QRect rectArea;
    32. bool remember;
    33. int offsetTop;
    34. int offsetLeft;
    35. int width;
    36. bool dynamicHeight;
    37.  
    38. QObject *parent;
    39. };
    40.  
    41.  
    42. #endif
    To copy to clipboard, switch view to plain text mode 




    To be continued in the next post

  2. #2
    Join Date
    Jan 2008
    Posts
    58
    Thanks
    3
    Qt products
    Qt4
    Platforms
    MacOS X

    Default Re: Weird problems when destructor is called

    Tablerow.cpp
    Qt Code:
    1. #include "tableRow.h"
    2. #include <QMap>
    3. #include <QList>
    4. #include <QMapIterator>
    5. #include <QDebug>
    6. #include "tableCellPrinter.h"
    7. #include "tableColumnPrint.h"
    8.  
    9. TableRow::TableRow(QRect rect, QObject *parent)
    10. : QObject(parent), parent(parent)
    11. {
    12. qDebug("TableRow::TableRow(): Start drawing the tables");
    13. this->maxColumnHeight = 0;
    14. qDebug("rect.width:%i", rect.width());
    15.  
    16. this->offsetLeft = rect.x();
    17. this->offsetTop = rect.y();
    18. this->width = rect.width();
    19. this->currentRow = 0;
    20.  
    21. }
    22.  
    23.  
    24.  
    25. void TableRow::setHeaderData(QMap<int, QMap<QString, QString> > data)
    26. {
    27. qDebug("TableRow::setHeaderData(): Set the header data");
    28. this->columns = data.count();
    29.  
    30. QMap<int, QMap<QString, QString> >::const_iterator i = data.constBegin();
    31.  
    32. int totalOffsetLeft = 0;
    33.  
    34. //loop the iterator
    35. while(i != data.constEnd() )
    36. {
    37. QMap<QString, QString> rowData = data.value(i.key());
    38.  
    39.  
    40. QRect rectColumn(totalOffsetLeft, this->offsetTop, rowData["width"].toInt(), 0);
    41.  
    42. //remember the highest height, so we can apply it to all columns!
    43. if(rowData["height"].toInt() > this->maxColumnHeight)
    44. this->maxColumnHeight = rowData["height"].toInt();
    45. qDebug("keeeeyyy:%i", i.key());
    46. this->tableColumns[i.key()] = new TableColumn(QColor(rowData["fillColor"]), rowData["text"], rectColumn, this);
    47.  
    48.  
    49. i++;
    50. totalOffsetLeft += rowData["width"].toInt();
    51.  
    52. }
    53.  
    54.  
    55. }
    56.  
    57. void TableRow::setRowData(QMap<int, QMap<QString, QString> > data)
    58. {
    59. qDebug("TableRow::setRowData(): set the row data");
    60. // add cell to the matching table column!
    61. qDebug("this->width:%i", this->width);
    62.  
    63. QMap<int, QMap<QString, QString> >::const_iterator i = data.constBegin();
    64.  
    65. //loop the iterator
    66. while(i != data.constEnd() )
    67. {
    68. QMap<QString, QString> rowData = data.value(i.key());
    69.  
    70. if(rowData["height"].toInt() > this->maxColumnHeight)
    71. this->maxColumnHeight = rowData["height"].toInt();
    72. qDebug("column number to add a cell to:%i", i.key());
    73.  
    74. this->tableColumns[i.key()]->addCell(this->currentRow, QColor(rowData["fillColor"]), QString(rowData["text"]));
    75.  
    76. i++;
    77. }
    78.  
    79. this->currentRow++;
    80.  
    81.  
    82.  
    83.  
    84. }
    85.  
    86. void TableRow::draw(int row, QPainter &painter)
    87. {
    88. //lets start drawing!
    89. qDebug("TableRow:draw(): start drawing");
    90.  
    91. qDebug("this->width:%i", this->width);
    92.  
    93. int offsetLeftColumn = this->offsetLeft;
    94. int offsetTopColumn = (row == 0)?this->offsetTop : this->offsetTop + this->maxColumnHeight*(row-1);
    95. //loop each column
    96. for(int i = 0; i < this->columns; i++)
    97. {
    98. //check if the column stays on the page
    99. if(offsetLeftColumn + this->tableColumns[i]->columnWidth < this->width ){
    100. this->tableColumns[i]->draw(row, offsetLeftColumn, offsetTopColumn, painter);
    101.  
    102. offsetLeftColumn += this->tableColumns[i]->columnWidth;
    103.  
    104. }else{
    105. qDebug("column width:%i width:%i", offsetLeftColumn + this->tableColumns[i]->columnWidth, this->width);
    106. }
    107.  
    108.  
    109. }
    110.  
    111.  
    112.  
    113. offsetLeftColumn = 0;
    114. offsetTopColumn = 0;
    115.  
    116.  
    117. }
    118.  
    119.  
    120. TableRow::~TableRow()
    121. {
    122.  
    123. qDebug("Destruct rows");
    124. for(int i = 0; i < this->columns; i++)
    125. {
    126. delete this->tableColumns[i];
    127. }
    128. }
    To copy to clipboard, switch view to plain text mode 
    Tablecolumn.h
    Qt Code:
    1. #ifndef TABLECOLUMNPRINT_H
    2. #define TABLECOLUMNPRINT_H
    3.  
    4. #include <QObject>
    5. #include "tableCellPrinter.h"
    6.  
    7. class QRect;
    8. class QPainter;
    9.  
    10. class TableColumn : public QObject
    11. {
    12. Q_OBJECT
    13. public:
    14. TableColumn(QColor colorfill, QString text, QRect &rectColumn, QObject *parent);
    15. void addCell(int row, QColor colorfill, QString text);
    16. void draw(int row, int offsetLeft, int offsetTop, QPainter &painter);
    17. int columnWidth;
    18. ~TableColumn();
    19.  
    20. TableCell *cells[];
    21. private:
    22. int columnHeight;
    23. int cellsCount;
    24. QObject *parent;
    25. };
    26.  
    27.  
    28. #endif
    To copy to clipboard, switch view to plain text mode 


    Tablecolumn.cpp
    Qt Code:
    1. #include "tableColumnPrint.h"
    2. #include "tableCellPrinter.h"
    3. #include <QColor>
    4. #include <QString>
    5. #include <QRect>
    6. #include <QPainter>
    7. #include <QDebug>
    8.  
    9. TableColumn::TableColumn(QColor colorfill, QString text, QRect &rectColumn, QObject *parent)
    10. :QObject(parent), cellsCount(0)
    11. {
    12. qDebug("TableColumn::TableColumn(): Define header column");
    13. this->cellsCount = 0;
    14.  
    15. this->columnWidth = rectColumn.width();
    16. this->columnHeight = rectColumn.height();
    17.  
    18.  
    19. this->cells[0] = new TableCell(colorfill, text, this);
    20.  
    21. this->parent = parent;
    22. }
    23.  
    24.  
    25.  
    26.  
    27. void TableColumn::addCell(int row, QColor colorfill, QString text)
    28. {
    29. qDebug("TableColumn::addCell(): add a cell to the column");
    30. row += 2;
    31. this->cells[row] = new TableCell( colorfill, text, this);
    32. qDebug("###########################################");
    33. qDebug() << this->cells[row]->text;
    34. qDebug("column:");
    35. qDebug() << this->cells[0]->text;
    36. qDebug("cel number for this column:%i", (row));
    37. qDebug("###########################################");
    38.  
    39. //the plus one is there so we don't overwrite the header column
    40. this->cellsCount = row;
    41.  
    42. }
    43.  
    44. void TableColumn::draw(int row, int offsetLeft, int offsetTop, QPainter &painter)
    45. {
    46. //draw the row
    47. qDebug("TableColumn:draw(): start drawing");
    48.  
    49. painter.setBrush(this->cells[row]->fillColor);
    50. painter.setPen(Qt::black);
    51.  
    52. qDebug("Drawing area: offsetLeft:%i offsetTop:%i width:%i height:%i", offsetLeft, offsetTop, this->columnWidth, this->columnHeight);
    53.  
    54. QRect rowRect(offsetLeft, offsetTop , this->columnWidth, 20);
    55.  
    56. qDebug("row for this column:%i", row);
    57.  
    58. painter.drawRect(rowRect);
    59.  
    60.  
    61. this->cells[row]->draw(painter, this->cells[row]->text, offsetLeft, offsetTop , this->columnWidth, 20);
    62. }
    63.  
    64. TableColumn::~TableColumn()
    65. {
    66. qDebug("Destruct column");
    67.  
    68. delete this->cells;
    69.  
    70. }
    To copy to clipboard, switch view to plain text mode 


    Tablecell.h
    Qt Code:
    1. #ifndef TABLECELLPRINTER_H
    2. #define TABLECELLPRINTER_H
    3.  
    4. #include <QObject>
    5. #include <QColor>
    6. #include <QString>
    7. #include <QRect>
    8.  
    9. class QPainter;
    10.  
    11. class TableCell : public QObject
    12. {
    13. Q_OBJECT
    14. public:
    15. TableCell(QColor fillColor, QString &txt, QObject *parent =0);
    16. void draw(QPainter&, QString &txt, int offsetLeft, int offsetTop , int width, int height);
    17. ~TableCell();
    18. QColor fillColor;
    19. QString text;
    20.  
    21. };
    22.  
    23. #endif
    To copy to clipboard, switch view to plain text mode 
    Tablecell.cpp
    Qt Code:
    1. #include "tableCellPrinter.h"
    2. #include <QDebug>
    3. #include <QPainter>
    4. #include <QString>
    5. #include <QObject>
    6.  
    7. TableCell::TableCell(QColor fillColor, QString &txt, QObject *parent)
    8. :QObject(parent)
    9. {
    10. qDebug("TableCell::TableCell(): Initialize a new cell");
    11.  
    12. this->fillColor = fillColor;
    13. this->text = QString(txt);
    14. }
    15.  
    16.  
    17. void TableCell::draw(QPainter &painter, QString &txt, int offsetLeft, int offsetTop , int width, int height)
    18. {
    19. //start drawing the text
    20. qDebug("TableCell:draw(): start drawing");
    21.  
    22. painter.drawText(QRect(offsetLeft, offsetTop, width, height), Qt::AlignCenter, txt);
    23. }
    24.  
    25. TableCell::~TableCell()
    26. {
    27.  
    28. qDebug("destruct cell");
    29. qDebug() << this->text;
    30. }
    To copy to clipboard, switch view to plain text mode 


    The script works fine with some test data inserted in mainWindow.cpp but when I add more test data, let's say 4 rows and 1 column row.
    The whole program crashes, and in my debugger I saw that it crashed when the destructor of the QObject is called!

    Can somebody help me please, I'm desperate.

    Many many thanks,

    Cyberboy

  3. #3
    Join Date
    Oct 2006
    Location
    New Delhi, India
    Posts
    2,467
    Thanks
    8
    Thanked 334 Times in 317 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Weird problems when destructor is called

    It would have been better if you had posted a compilable attachment /files, instead of writing the whole code.

  4. #4
    Join Date
    Jan 2008
    Posts
    58
    Thanks
    3
    Qt products
    Qt4
    Platforms
    MacOS X

    Default Re: Weird problems when destructor is called

    Smart idea

    This is the link to the zip file with all the files of the complete project!
    http://www.zchosting.nl/BestelApplicatie.zip

    Greetings,

    Cyberboy

  5. #5
    Join Date
    Oct 2006
    Location
    New Delhi, India
    Posts
    2,467
    Thanks
    8
    Thanked 334 Times in 317 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Weird problems when destructor is called

    Is the zip file filename correct ? I am not able to open it. However only the site address is accessible.

    EDIT : Now it opens... may be i tried a little early

    EDIT : File corrupt

  6. #6
    Join Date
    Jan 2008
    Posts
    58
    Thanks
    3
    Qt products
    Qt4
    Platforms
    MacOS X

    Default Re: Weird problems when destructor is called

    I'm sorry I posted the link while I was still uploading the project. So that may explain the corrupt file.

    I uploaded the project again, and now I finished uploading before I posted this message!

  7. #7
    Join Date
    Aug 2006
    Posts
    221
    Thanks
    3
    Thanked 29 Times in 19 Posts

    Default Re: Weird problems when destructor is called

    No idea why the destructor is called. I am a bit reluctant to go through the whole code. It is too much 'fun' to read.

    But in Tablecolumn.cpp (addCell) you add 2 to row, leaving one cells empty, i.e. cells[1] is never initialized (I think).

    Furthermore you delete an array with 'delete' instead of 'delete []'. This is for sure a bug.

    There are many more problems. Mostly just bad style, e.g. passing QString where const QString & would be sufficient, which btw. should be no problem, but strangely was the cause for spurious crashes in an old Qt 3.0 program I wrote years ago.

  8. #8
    Join Date
    Jan 2008
    Posts
    58
    Thanks
    3
    Qt products
    Qt4
    Platforms
    MacOS X

    Default Re: Weird problems when destructor is called

    That's the problem with this project, I have rewritten the code so many times that the original style is gone for a long time.....

    But this is a beautiful moment to learn from!

    I couldn't find the reason why cells[1] isn't initialized, but after guessing and playing around I found a solution (A BAD ONE) I was glad that it worked not mentioning the state.

    But do you advice to rewrite the whole project.... or just to rewrite the tableprint part....

  9. #9
    Join Date
    Aug 2006
    Posts
    221
    Thanks
    3
    Thanked 29 Times in 19 Posts

    Default Re: Weird problems when destructor is called

    Quote Originally Posted by cyberboy View Post
    But do you advice to rewrite the whole project.... or just to rewrite the tableprint part....
    I don't know the whole project, but a refactoring is always a good idea. ;-)

    For instance I'd throw out the whole *cells[]. Use QVector, or if you must an STL vector, but forget the ancient C stuff. Always trouble.

    Btw. even if you delete cells with 'delete []' instead of 'delete', there is a problem. Your cells are as far as I can see children of TableColumn and therefore of QObject, so they would be automatically deleted when the parent is deleted. No need to do this manually in the destructor.

    Do you originally come from a JAVA environment? Prepending every member variable with 'this->' is not wrong, but not necessary and make IMHO the whole program harder to read.

  10. #10
    Join Date
    Jan 2008
    Posts
    58
    Thanks
    3
    Qt products
    Qt4
    Platforms
    MacOS X

    Default Re: Weird problems when destructor is called

    No a php environment..

    I hope that I have enough time to rewrite it today!

    Many thanks for the useful advices!

    Greetings,


    Cyberboy

Similar Threads

  1. Weird Cross Platform Printing Problems
    By igor in forum Qt Programming
    Replies: 7
    Last Post: 7th August 2007, 16:25

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.