1 /*
2 outline_tree_model.cpp MindForger thinking notebook
3
4 Copyright (C) 2016-2020 Martin Dvorak <martin.dvorak@mindforger.com>
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 #include "outline_tree_model.h"
20
21 #include <iostream>
22
23 #define NO_INDEX -1
24
25 using namespace std;
26
27 namespace m8r {
28
OutlineTreeModel(QObject * parent,HtmlOutlineRepresentation * htmlRepresentation)29 OutlineTreeModel::OutlineTreeModel(QObject *parent, HtmlOutlineRepresentation* htmlRepresentation)
30 : QStandardItemModel(parent), htmlRepresentation(htmlRepresentation)
31 {
32 setColumnCount(5);
33 setRowCount(0);
34 }
35
removeAllRows()36 void OutlineTreeModel::removeAllRows()
37 {
38 QStandardItemModel::clear();
39
40 QStringList tableHeader;
41 tableHeader
42 << tr("Outline") // tree of Notes is in fact Notebook's outline
43 << tr("Done")
44 << tr("Rs")
45 << tr("Ws")
46 << tr("Modified");
47 setHorizontalHeaderLabels(tableHeader);
48 }
49
createNameText(string & html,Note * note)50 void OutlineTreeModel::createNameText(string& html, Note* note)
51 {
52 for(auto depth=0; depth<note->getDepth(); depth++) {
53 html += " ";
54 }
55 html += note->getName();
56
57 htmlRepresentation->tagsToHtml(note->getTags(), html);
58 // IMPROVE make showing of type configurable
59 htmlRepresentation->noteTypeToHtml(note->getType(), html);
60 }
61
createRowFor(Note * note,QList<QStandardItem * > & rowItems)62 void OutlineTreeModel::createRowFor(Note* note, QList<QStandardItem*>& rowItems)
63 {
64 // name
65 string name{};
66 name.reserve(200);
67 createNameText(name, note);
68 QStandardItem* noteItem = new QStandardItem{QString::fromStdString(name)};
69 // TODO declare custom role
70 noteItem->setData(QVariant::fromValue(note), Qt::UserRole + 1);
71 rowItems += noteItem;
72 // %
73 QString s{};
74 if(note->getProgress()) {
75 s.clear();
76 s += QString::number(note->getProgress());
77 s += "%";
78 rowItems += new QStandardItem{s};
79 } else {
80 rowItems += new QStandardItem{""};
81 }
82 // rd/wr
83 rowItems += new QStandardItem{QString::number(note->getReads())};
84 rowItems += new QStandardItem{QString::number(note->getRevision())};
85 // pretty
86 s = note->getModifiedPretty().c_str();
87 rowItems += new QStandardItem{s};
88 }
89
90
addNote(Note * note)91 void OutlineTreeModel::addNote(Note* note)
92 {
93 QList<QStandardItem*> items;
94 createRowFor(note, items);
95 appendRow(items);
96 }
97
insertNote(Note * note)98 int OutlineTreeModel::insertNote(Note* note)
99 {
100 if(note) {
101 QList<QStandardItem*> items;
102 createRowFor(note, items);
103 int offset = note->getOutline()->getNoteOffset(note);
104 insertRow(offset, items);
105 return offset;
106 } else {
107 return 0;
108 }
109 }
110
getRowByNote(const Note * note)111 int OutlineTreeModel::getRowByNote(const Note* note)
112 {
113 for(int row = 0; row<rowCount(); row++) {
114 if(item(row)->data().value<Note*>() == note) {
115 return row;
116 }
117 }
118 return NO_INDEX;
119 }
120
refresh(Note * note,int row,bool set)121 void OutlineTreeModel::refresh(Note* note, int row, bool set)
122 {
123 if(row > NO_INDEX) {
124 if(set) {
125 // TODO declare custom role
126 item(row,0)->setData(QVariant::fromValue(note), Qt::UserRole + 1);
127 }
128
129 string s{};
130 s.reserve(100);
131 createNameText(s, note);
132 // refresh content
133 item(row,0)->setText(QString::fromStdString(s));
134
135 if(note->getProgress()) {
136 s.clear();
137 s += std::to_string(note->getProgress());
138 s += "%";
139 item(row,1)->setText(QString::fromStdString(s));
140 } else {
141 item(row,1)->setText("");
142 }
143
144 item(row,2)->setText(QString::number(note->getReads()));
145 item(row,3)->setText(QString::number(note->getRevision()));
146 item(row,4)->setText(QString::fromStdString(note->getModifiedPretty()));
147
148 QModelIndex from = createIndex(row, 0, item(row,0));
149 QModelIndex to = createIndex(row, 3, item(row,3));
150
151 // notify widget about changes
152 emit dataChanged(from,to);
153 }
154 }
155
refresh(Note * note,QModelIndexList selection)156 void OutlineTreeModel::refresh(Note* note, QModelIndexList selection)
157 {
158 int row = NO_INDEX;
159
160 // determine row number by note attached to the row - selection or iteration
161 if(selection.size()) {
162 // TODO declare custom role
163 if(item(selection[0].row())->data(Qt::UserRole + 1).value<Note*>() == note) {
164 row = selection[0].row();
165 }
166 }
167 if(row <= NO_INDEX) {
168 // IMPROVE UI note that has both Note and QStandardItem refs
169 row = getRowByNote(note);
170 }
171
172 refresh(note, row);
173 }
174
175 } // m8r namespace
176