1 #include "todonote.h"
2 #include "textedit.h"
3 #include "todomodel.h"
4 
5 #include <QClipboard>
6 #include <QApplication>
7 
8 #include <QTreeView>
9 #include <QHeaderView>
10 #include <QScrollArea>
11 #include <QVBoxLayout>
12 #include <QGridLayout>
13 #include <QDataWidgetMapper>
14 #include <QDateTimeEdit>
15 #include <QCalendarWidget>
16 #include <QLabel>
17 #include <QCheckBox>
18 #include <QMenu>
19 #include <QTextStream>
20 
21 enum
22 {
23 	TODO_ACTION_INSERT,
24 	TODO_ACTION_INSERT_SUB,
25 	TODO_ACTION_REMOVE,
26 	//TODO_ACTION_HIDE_COMPLETED,
27 	TODO_ACTION_COUNT,
28 };
29 
TodoNote(const QFileInfo & fileinfo,Note::Type type_new)30 TodoNote::TodoNote(const QFileInfo& fileinfo, Note::Type type_new)
31 	: Note(fileinfo, type_new)
32 {
33 	text_edit = new TextEdit();
34 	text_edit->setAcceptRichText(false);
35 	text_edit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
36 //	text_edit->setMinimumHeight(100);
37 //	text_edit->setMaximumHeight(200);
38 
39 	model = new TodoModel();
40 	proxy_model = new TodoProxyModel();
41 	proxy_model->setSourceModel(model);
42 
43 	tree_view = new QTreeView();
44 	tree_view->setModel(proxy_model);
45 	tree_view->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::SelectedClicked);
46 	tree_view->setSelectionBehavior(QAbstractItemView::SelectRows);
47 #if QT_VERSION >= 0x050000
48 	tree_view->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
49 #endif
50 
51 #if QT_VERSION < 0x050000
52 	tree_view->header()->setResizeMode(QHeaderView::ResizeToContents);
53 #endif
54 	tree_view->header()->hide();
55 	tree_view->setDragEnabled(true);
56 	tree_view->setAcceptDrops(true);
57 	tree_view->setDropIndicatorShown(true);
58 	tree_view->setDragDropMode(QAbstractItemView::InternalMove);
59 	tree_view->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding);
60 
61 	connect(proxy_model, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(taskChanged(QModelIndex)));
62 	connect(tree_view->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(taskChanged(QModelIndex)));
63 
64 	tree_view->setContextMenuPolicy(Qt::CustomContextMenu);
65 	tree_view->setAnimated(true);
66 
67 	connect(tree_view, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequested(QPoint)));
68 
69 	menu_context = new QMenu();
70 	menu_context->addAction(tr("Insert new task"), this, SLOT(insertTask()));
71 	menu_context->addAction(tr("Insert new task"), this, SLOT(insertSubTask()));
72 	menu_context->addAction(tr("Remove this task"), this, SLOT(removeTask()));
73 	//menu_context->addAction(tr("Hide completed tasks"), this, SLOT(hideCompletedTasks()));
74 	//menu_context->actions()[TODO_ACTION_HIDE_COMPLETED]->setCheckable(true);
75 
76 	for(int i=2; i<model->columnCount(); ++i)
77 		tree_view->setColumnHidden(i, true);
78 
79 	lb_date_start = new QLabel;
80 	lb_date_0 = new QLabel(tr("Created: "), lb_date_start);
81 	lb_date_stop = new QLabel;
82 	lb_date_1 = new QLabel(tr("Completed: "), lb_date_stop);
83 	dt_date_limit = new QDateTimeEdit;
84 	dt_date_limit->setCalendarPopup(true);
85 	cb_date_limit = new QCheckBox(tr("Limited: "), dt_date_limit);
86 	cb_date_limit->setCheckable(true);
87 
88 	grid_layout = new QGridLayout();
89 	QGridLayout* l = qobject_cast<QGridLayout*>(grid_layout);
90 	l->addWidget(lb_date_0, 0, 0);
91 	l->addWidget(lb_date_start, 0, 1);
92 	l->addWidget(lb_date_1, 1, 0);
93 	l->addWidget(lb_date_stop, 1, 1);
94 	l->addWidget(cb_date_limit, 2, 0);
95 	l->addWidget(dt_date_limit, 2, 1);
96 
97 	extra_layout = new QVBoxLayout;
98 	extra_layout->addItem(grid_layout);
99 	extra_layout->addWidget(text_edit);
100 
101 	extra_widget = new QWidget;
102 	extra_widget->setLayout(extra_layout);
103 	extra_widget->hide();
104 
105 	main_layout = new QVBoxLayout();
106 	main_layout->addWidget(tree_view);
107 	main_layout->addWidget(extra_widget);
108 
109 	area = new QScrollArea();
110 	area->setLayout(main_layout);
111 
112 	load(); //loading note's content
113 
114 	mapper = new QDataWidgetMapper();
115 	mapper->setModel(proxy_model);
116 	mapper->addMapping(text_edit, 6, "plainText");
117 	mapper->addMapping(lb_date_start, 2, "text");
118 	mapper->addMapping(lb_date_stop, 3, "text");
119 	lb_date_start->setLocale(settings.getLocale());
120 	dt_date_limit->setLocale(settings.getLocale());
121 	dt_date_limit->calendarWidget()->setLocale(settings.getLocale());
122 
123 	tree_view->setCurrentIndex(QModelIndex());
124 }
125 
~TodoNote()126 TodoNote::~TodoNote()
127 {
128 	tree_view->deleteLater();
129 	proxy_model->deleteLater();
130 	model->deleteLater();
131 	text_edit->deleteLater();
132 	extra_layout->deleteLater();
133 	main_layout->deleteLater();
134 	extra_widget->deleteLater();
135 	area->deleteLater();
136 	lb_date_start->deleteLater();
137 	lb_date_stop->deleteLater();
138 	dt_date_limit->deleteLater();
139 	cb_date_limit->deleteLater();
140 	grid_layout->deleteLater();
141 	mapper->deleteLater();
142 
143 	menu_context->deleteLater();
144 }
145 
retranslate(const QLocale & locale)146 void TodoNote::retranslate(const QLocale& locale)
147 {
148 	menu_context->actions()[TODO_ACTION_INSERT]->setText(tr("Insert new task"));
149 	menu_context->actions()[TODO_ACTION_INSERT_SUB]->setText(tr("Insert new task"));
150 	menu_context->actions()[TODO_ACTION_REMOVE]->setText(tr("Remove this task"));
151 	//menu_context->actions()[TODO_ACTION_HIDE_COMPLETED]->setText(tr("Hide completed tasks"));
152 	lb_date_0->setText(tr("Created: "));
153 	lb_date_1->setText(tr("Completed: "));
154 	cb_date_limit->setText(tr("Limited: "));
155 	lb_date_start->setLocale(locale);
156 	dt_date_limit->setLocale(locale);
157 	dt_date_limit->calendarWidget()->setLocale(locale);
158 }
159 
160 //Reading file
load()161 void TodoNote::load()
162 {
163 	file.close();
164 	if(!file.exists())
165 	{
166 		file.open(QIODevice::WriteOnly);
167 		file.close();
168 	}
169 	if(file.open(QIODevice::ReadOnly))
170 	{
171         domDocument = model->load(file);
172 		file.close();
173 	}
174 }
175 
176 //Saving note
save(bool forced)177 void TodoNote::save(bool forced)
178 {
179 	if(!(content_changed || forced)) return; //If file doesn't need in saving, exiting from function
180 	file.close();
181 	if(file.open(QFile::WriteOnly))
182 	{
183 		QTextStream out(&file);
184         domDocument->save(out, QDomNode::EncodingFromDocument);
185 		content_changed = false;
186 	}
187 }
188 
189 //Returning widget (it's can be placed to tabwidget)
widget()190 QWidget* TodoNote::widget()
191 {
192 	return area;
193 }
194 
195 //Coping note's content to clipboard
copy() const196 void TodoNote::copy() const
197 {
198 //	QClipboard* clipboard = QApplication::clipboard();
199 //	clipboard->setPixmap(*label->pixmap());
200 }
201 
contextMenuRequested(const QPoint & pos)202 void TodoNote::contextMenuRequested(const QPoint& pos)
203 {
204 	QModelIndex index = tree_view->indexAt(pos);
205 	menu_context->actions()[TODO_ACTION_INSERT]->setVisible(!index.isValid());
206 	menu_context->actions()[TODO_ACTION_INSERT_SUB]->setVisible(index.isValid());
207 	menu_context->actions()[TODO_ACTION_REMOVE]->setEnabled(index.isValid());
208 	QPoint pos_global = tree_view->mapToGlobal(pos);
209 	menu_context->exec(pos_global);
210 }
211 
insertTask()212 void TodoNote::insertTask()
213 {
214 	QModelIndex index;
215 	int row = model->rowCount(index);
216 	model->insertRow(row, index);
217 	//Setting current index to created task
218 	QModelIndex child_index = model->index(row, 0);
219 	QModelIndex proxy_index = proxy_model->mapFromSource(child_index);
220 	tree_view->setCurrentIndex(proxy_index);
221 }
222 
insertSubTask()223 void TodoNote::insertSubTask()
224 {
225 	QModelIndex proxy_index = tree_view->currentIndex();
226 	QModelIndex index = proxy_model->mapToSource(proxy_index);
227 	int row = model->rowCount(index);
228 	model->insertRow(row, index);
229 	//Setting current index to created task
230 	QModelIndex child_index = index.child(row, 0);
231 	proxy_index = proxy_model->mapFromSource(child_index);
232 	tree_view->setCurrentIndex(proxy_index);
233 }
234 
removeTask()235 void TodoNote::removeTask()
236 {
237 	QModelIndex proxy_index = tree_view->currentIndex();
238 	QModelIndex index = proxy_model->mapToSource(proxy_index);
239 	if(index.isValid())
240 		model->removeRow(index.row(), index.parent());
241 }
242 
hideCompletedTasks()243 void TodoNote::hideCompletedTasks()
244 {
245 	//bool hide_completed = menu_context->actions()[TODO_ACTION_HIDE_COMPLETED]->isChecked();
246 	//proxy_model->hideDoneTasks(hide_completed);
247 }
248 
taskChanged(const QModelIndex & proxy_index)249 void TodoNote::taskChanged(const QModelIndex& proxy_index)
250 {
251 	extra_widget->setVisible(proxy_index.isValid());
252 	if(!proxy_index.isValid()) return;
253 	mapper->setRootIndex(proxy_index.parent());
254 	mapper->setCurrentModelIndex(proxy_index);
255 	QModelIndex index = proxy_model->mapToSource(proxy_index);
256 	Task* task = static_cast<Task*>(index.internalPointer());
257 	//
258 	disconnect(dt_date_limit, SIGNAL(dateTimeChanged(QDateTime)), this, SLOT(noteDateLimitChanged(QDateTime)));
259 	disconnect(cb_date_limit, SIGNAL(toggled(bool)), this, SLOT(noteLimitChanged(bool)));
260 	dt_date_limit->setDateTime(task->dateLimit());
261 	cb_date_limit->setChecked(task->limited());
262 	connect(dt_date_limit, SIGNAL(dateTimeChanged(QDateTime)), this, SLOT(noteDateLimitChanged(QDateTime)));
263 	connect(cb_date_limit, SIGNAL(toggled(bool)), this, SLOT(noteLimitChanged(bool)));
264 	//
265 	bool task_done = task->done();
266 	lb_date_1->setVisible(task_done);
267 	lb_date_stop->setVisible(task_done);
268 	cb_date_limit->setHidden(task_done);
269 	dt_date_limit->setHidden(task_done);
270 	dt_date_limit->setEnabled(task->limited());
271 
272 }
273 
noteDateLimitChanged(const QDateTime & date)274 void TodoNote::noteDateLimitChanged(const QDateTime& date)
275 {
276 	QModelIndex proxy_index = tree_view->currentIndex();
277 	QModelIndex index = proxy_model->mapToSource(proxy_index);
278 	if(!index.isValid()) return;
279 	QModelIndex date_limit_index = index.sibling(index.row(), 4);
280 	model->setData(date_limit_index, date, Qt::EditRole);
281 }
282 
noteLimitChanged(bool limited)283 void TodoNote::noteLimitChanged(bool limited)
284 {
285 	QDateTime date = limited?QDateTime::currentDateTime().addDays(7):QDateTime();
286 	noteDateLimitChanged(date);
287 }
288 
isDocumentSupported() const289 bool TodoNote::isDocumentSupported() const
290 {
291     return false;
292 }
293 
document() const294 QTextDocument *TodoNote::document() const
295 {
296     return 0;
297 }
298