Hi all!

I am using Qt for a while and now I try to improve my skills. I would like to take a closer look on Model/View concept and QML too.

My idea is to create an 'Advanced TODO list'
I plan to define the user interface in qml, and the application logic in c++ on a way that I have a mainwindow with QDeclarativeView and I load the Main.qml into it.

My concept for the applicaton:
The program has two main page: Calendar view and daily view.
On calendar view there is a calendar, e.g. the day which has task with bold. Maybe most important task to a day is visible also here.
If I click on a day the daily view comes up, and I can organize the day.
I can assign a rating to a day - how succesful the day was. It should be visible on the calendar view.
I assign an image also to the day - It's like an icon - if it has been set it is visible also in calendar view.

But I am unsure the usage and the data structures I should use.

Now I have created on C++ side a MonthModel. It focuses only on the calendar part - the detailed daily things not defined yet.

My question is:
Is this approach seems ok? I wasn't sure if a Table Model should be used with columns rating, title, etc. or this listmodel with DayData class.
On QML side - I create a gridview. Put some empty rectangles into it based on monthModel spaceBefore property. After that fill up the days, and put some other empty rectangles (spaceAfter)
Is it OK, or could I do it in more elegant way?

And the most important question I think:
For the detailed data - let's assume I would assign images and rich texts to a day. Should I use a new model or is it possible to extend it?
My idea is to extend DayData class with e.g. with variables QList<QString> and QList<QImage> and they can store texts and images. But is it possible to use these lists like an other model on the qml side to display the data?

Sorry for the long post.

Thanks!

monthmodel.h
Qt Code:
  1. class DayData
  2. {
  3. public:
  4. DayData(const QString& title, short rating, const QImage& img);
  5.  
  6. QString title() const;
  7. short rating() const;
  8. QImage image() const;
  9.  
  10. private:
  11.  
  12. QString m_title;
  13. short m_rating;
  14. QImage m_image;
  15. };
  16.  
  17.  
  18. class MonthModel : public QAbstractListModel
  19. {
  20. Q_OBJECT
  21. public:
  22. enum MonthRoles {
  23. TitleRole = Qt::UserRole + 1,
  24. RatingRole,
  25. ImageRole
  26. };
  27.  
  28. MonthModel(QObject *parent = NULL);
  29. ~MonthModel();
  30.  
  31. Q_PROPERTY (short year READ year NOTIFY yearChanged);
  32. Q_PROPERTY (short month READ month NOTIFY monthChanged);
  33. Q_PROPERTY (QString monthName READ monthName NOTIFY monthNameChanged);
  34. Q_PROPERTY (short spaceBefore READ spaceBefore NOTIFY spaceBeforeChanged);
  35. Q_PROPERTY (short spaceAfter READ spaceAfter NOTIFY spaceAfterChanged);
  36.  
  37. //void setYearMonth(short year, short month);
  38. int rowCount(const QModelIndex &parent = QModelIndex()) const;
  39.  
  40. QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
  41. QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
  42.  
  43. public slots:
  44. void previousMonth();
  45. void nextMonth();
  46.  
  47. signals:
  48. void spaceBeforeChanged();
  49. void spaceAfterChanged();
  50. void monthChanged();
  51. void monthNameChanged();
  52. void yearChanged();
  53.  
  54.  
  55. private:
  56. short spaceBefore();
  57. short spaceAfter();
  58. short month() {return m_month;}
  59. short year() {return m_year;}
  60. QString monthName();
  61.  
  62. void fillData();
  63. QList<DayData> m_days;
  64. short m_year;
  65. short m_month;
  66.  
  67. };
To copy to clipboard, switch view to plain text mode 
monthmodel.cpp
Qt Code:
  1. #include "monthmodel.h"
  2.  
  3. #include <QDate>
  4.  
  5.  
  6. DayData::DayData(const QString &title, short rating, const QImage &img) :
  7. m_title(title), m_rating(rating), m_image(img)
  8. {
  9. }
  10.  
  11.  
  12. MonthModel::MonthModel(QObject *parent) : QAbstractListModel(parent)
  13. {
  14. m_days.clear();
  15. m_year=QDate::currentDate().year();
  16. m_month=QDate::currentDate().month();
  17.  
  18. QHash<int, QByteArray> roles;
  19. roles[TitleRole] = "title";
  20. roles[RatingRole] = "rating";
  21. roles[ImageRole] = "image";
  22. setRoleNames(roles);
  23.  
  24. fillData();
  25. }
  26.  
  27. MonthModel::~MonthModel()
  28. {
  29. }
  30.  
  31. QVariant MonthModel::data(const QModelIndex &index, int role) const
  32. {
  33. if (!index.isValid())
  34. return QVariant();
  35. if ((index.row()>=m_days.size()) || (index.row()<0))
  36. return QVariant();
  37.  
  38. const DayData& day=m_days.at(index.row());
  39.  
  40. if (role == TitleRole)
  41. {
  42. return day.title();
  43. }else if (role==RatingRole)
  44. {
  45. return day.rating();
  46. }else if (role==ImageRole)
  47. {
  48. return day.image();
  49. }
  50. return QVariant();
  51. }
  52.  
  53. short MonthModel::spaceBefore()
  54. {
  55. short r=QDate(m_year, m_month, 1).dayOfWeek()-1;
  56. qDebug("MonthModel::spacebefore - %d", r);
  57. return (r);
  58. }
  59.  
  60. short MonthModel::spaceAfter()
  61. {
  62. QDate firstDay=QDate(m_year, m_month, 1);
  63. short r=7-firstDay.addDays(firstDay.daysInMonth()-1).dayOfWeek();
  64. qDebug("MonthModel::spaceAfter - %d", r);
  65. return r;
  66. }
  67.  
  68. int MonthModel::rowCount(const QModelIndex &parent) const
  69. {
  70. return m_days.count();
  71. }
  72.  
  73. QVariant MonthModel::headerData(int section, Qt::Orientation orientation, int role) const
  74. {
  75. if (role!= Qt::DisplayRole)
  76. return QVariant();
  77. return QString("NotYetDefined");
  78. }
  79.  
  80.  
  81. void MonthModel::fillData()
  82. {
  83. beginResetModel();
  84.  
  85. m_days.clear();
  86.  
  87. //beginInsertRows(QModelIndex(), rowCount(), rowCount());
  88. for (int i=0; i<QDate(m_year, m_month, 1).daysInMonth(); i++)
  89. {
  90. m_days << DayData(QString("%1").arg(i+1), 0, QImage());
  91. }
  92. endResetModel();
  93. //endInsertRows();
  94. qDebug("RowCount: %d", rowCount());
  95. emit spaceBeforeChanged();
  96. emit spaceAfterChanged();
  97.  
  98. }
  99.  
  100. void MonthModel::previousMonth()
  101. {
  102. if (m_month!=1)
  103. {
  104. m_month--;
  105. emit monthChanged();
  106. emit monthNameChanged();
  107. }else
  108. {
  109. m_year--;
  110. m_month=12;
  111. emit monthChanged();
  112. emit monthNameChanged();
  113. emit yearChanged();
  114. }
  115. fillData();
  116.  
  117. }
  118.  
  119. void MonthModel::nextMonth()
  120. {
  121. if (m_month!=12)
  122. {
  123. m_month++;
  124. emit monthChanged();
  125. emit monthNameChanged();
  126. }else
  127. {
  128. m_year++;
  129. m_month=1;
  130. emit monthChanged();
  131. emit monthNameChanged();
  132. emit yearChanged();
  133. }
  134. fillData();
  135. }
  136.  
  137. QString MonthModel::monthName()
  138. {
  139. return QDate::longMonthName(m_month, QDate::StandaloneFormat);
  140. }
To copy to clipboard, switch view to plain text mode 

Calendar.qml
Qt Code:
  1. import Qt 4.7
  2.  
  3. Item {
  4. id: calendar
  5. width:500
  6. height: 420
  7.  
  8. Image {
  9. id: background
  10. anchors.fill: parent
  11. source:"./pics/calendar_sablon.png"
  12. smooth: true
  13. fillMode: Image.PreserveAspectFit
  14. }
  15.  
  16. Button {
  17. id: prev
  18. anchors.left: parent.left
  19. anchors.leftMargin: 10
  20. y: parent.height*0.05
  21. width: 40
  22. imagesource: "./pics/yellowstone.png"
  23. label:"Prev"
  24.  
  25. Behavior on width {
  26. NumberAnimation { duration: 100}
  27. }
  28.  
  29. Behavior on rotation {
  30. NumberAnimation {duration: 100}
  31. }
  32.  
  33. onClicked: {
  34. state=='clicked' ? state="" : state='clicked'
  35. console.log("Clcked");
  36. //monthModel.proba();
  37.  
  38. monthModel.previousMonth();
  39. console.log(monthModel.length);
  40. //console.log(monthModel.def)
  41. }
  42.  
  43. /*monthLoader.source="Calendar.qml"
  44. monthLoader.item.x=100
  45. monthLoader.item.y=100*/
  46. states: [
  47. State {
  48. name: 'clicked'
  49.  
  50. PropertyChanges {target: prev; width: 30; rotation: 180}
  51. //PropertyChanges {target: monthModel; def: "YXCV"}
  52. }
  53.  
  54. ]
  55. }
  56.  
  57. Text {
  58. id: month
  59. anchors.horizontalCenter: parent.horizontalCenter
  60. y: parent.height*0.05
  61. text: monthModel.year + ". "+ monthModel.monthName
  62. //text: monthModel.def
  63. color: "black"
  64. font.strikeout: false
  65. font.pointSize: 36
  66. style: Text.Normal
  67. font.family: "Monotype Corsiva"
  68. smooth: true
  69. opacity: 1
  70. clip: false
  71. }
  72.  
  73. Component {
  74. id: dayRect
  75. Rectangle {
  76. width: 55
  77. height: 55
  78. opacity: 0.8
  79. color: "lightgreen"
  80. }
  81. }
  82.  
  83. Component {
  84. id: dayDelegate
  85. Rectangle {
  86. //color: if (title < 4){ "yellow"} else {"orange"}
  87. color: "cyan"
  88. width: 55
  89. height: 55
  90. opacity: 0.8
  91.  
  92. Text {
  93. id: dummy
  94. text: title + "-" +rating
  95. smooth: true
  96. anchors.right: parent.right
  97. anchors.verticalCenter: parent.verticalCenter
  98. }
  99. MouseArea {
  100. anchors.fill: parent
  101. hoverEnabled: true
  102. onEntered: {
  103. parent.opacity=1.0
  104. parent.scale= 1.2
  105. }
  106. onExited: {
  107. parent.opacity= 0.8
  108. parent.scale=1
  109. }
  110. onDoubleClicked: {
  111. console.log("doubleClicked")
  112. console.log(index)
  113. }
  114. }
  115.  
  116. }
  117. }
  118.  
  119. Grid {
  120. z: 100
  121. x: 5; y: 137
  122.  
  123. rows: 6; columns: 7; spacing: 6
  124. //fill spaces before
  125. Repeater {
  126. model: monthModel.spaceBefore
  127. delegate: dayRect
  128. }
  129.  
  130. //the valid days
  131. Repeater {
  132. model: monthModel
  133. delegate: dayDelegate
  134. }
  135.  
  136. //fill spaces after
  137. Repeater {
  138. model: monthModel.spaceAfter
  139. delegate: dayRect
  140. }
  141.  
  142. }
  143.  
  144. }
To copy to clipboard, switch view to plain text mode