Add 'Time' and 'Tags' as proper task's properties, also add raw format handling

This commit is contained in:
Vyn 2024-04-11 11:42:13 +02:00
parent 3e7d8b4b70
commit bae67e6851
15 changed files with 142 additions and 49 deletions

View file

@ -5,6 +5,7 @@
*/
#include "Backend.h"
#include "core/TodoMd.h"
Backend::Backend() {
std::cout << "Backend created" << std::endl;
@ -43,6 +44,13 @@ void Backend::addTodo(QString newTodo, QString date) {
emit tasksChanged();
}
void Backend::addTodoFromRawFormat(QString text, QString date) {
mirai.addTask(mirai::TodoMdFormat::StringToTask(text.toStdString(), date.toStdString()));
mirai.save();
rebuildQMLTasksList();
emit tasksChanged();
}
void Backend::addTagFilter(QString tag) {
view.lock()->addTagFilter(tag.toStdString());
rebuildQMLTasksList();
@ -61,6 +69,14 @@ void Backend::removeFilters() {
emit tasksChanged();
}
void Backend::updateTodoFromRawFormat(int todoIndex, QString text, QString date) {
QMLTaskItem& taskItem = QMLTasks[todoIndex];
*(taskItem.taskItem) = mirai::TodoMdFormat::StringToTask(text.toStdString(), date.toStdString());
mirai.save();
rebuildQMLTasksList();
emit tasksChanged();
}
void Backend::updateTodo(int todoIndex, QString state, QString text, QString date) {
QMLTaskItem& taskItem = QMLTasks[todoIndex];
taskItem.taskItem->state = state == "TODO" ? mirai::TODO : mirai::DONE;

View file

@ -42,9 +42,11 @@ public:
Backend();
Q_INVOKABLE void addTodo(QString newTodo, QString date);
Q_INVOKABLE void addTodoFromRawFormat(QString text, QString date);
Q_INVOKABLE void addTagFilter(QString tag);
Q_INVOKABLE void removeTagFilter(QString tag);
Q_INVOKABLE void removeFilters();
Q_INVOKABLE void updateTodoFromRawFormat(int todoIndex, QString text, QString date);
Q_INVOKABLE void updateTodo(int todoIndex, QString state, QString text, QString date);
Q_INVOKABLE void removeTodo(int todoIndex);
Q_INVOKABLE void hideCompletedTasks(bool shouldHide);

View file

@ -5,6 +5,11 @@
*/
#include "TaskItem.h"
#include "core/TodoMd.h"
QString QMLTaskItem::getRawFormat() {
return QString::fromStdString(mirai::TodoMdFormat::TaskToString(*taskItem));
}
QString QMLTaskItem::getText() {
return QString::fromStdString(taskItem->getText());

View file

@ -17,6 +17,7 @@
struct QMLTaskItem {
Q_GADGET
Q_PROPERTY(QString rawFormat READ getRawFormat)
Q_PROPERTY(QString text READ getText)
Q_PROPERTY(QString state READ getState)
Q_PROPERTY(QString date READ getDate)
@ -26,6 +27,7 @@ struct QMLTaskItem {
public:
QString getText();
QString getRawFormat();
QString getState();
QString getDate();
bool getShouldShowDate();

View file

@ -5,6 +5,8 @@
*/
#include "Mirai.h"
#include "TaskItem.h"
#include <algorithm>
namespace mirai {
@ -12,12 +14,14 @@ namespace mirai {
auto tasksFile = TodoMdFormat::readFile(path);
files->push_back(std::move(tasksFile));
tags.clear();
for (auto& file : *files) {
for (auto& tag : file.getTags()) {
for (auto& task : (*files)[0].getTasks()) {
for (auto& tag : task->getTags()) {
if (std::find(tags.begin(), tags.end(), tag) == tags.end()) {
tags.push_back(tag);
}
}
}
}
void Mirai::save() {
for (auto& file : *files) {
@ -25,6 +29,13 @@ namespace mirai {
}
}
void Mirai::addTask(TaskItem taskItem) {
(*files)[0].addTask(taskItem);
for (auto& view : views) {
view->update();
}
}
void Mirai::addTask(std::string text, std::string date) {
/*std::time_t t = std::time(nullptr);*/
/*std::tm tm = *std::localtime(&t);*/

View file

@ -22,6 +22,7 @@ namespace mirai {
void loadFile(const std::string& path);
void save();
void addTask(TaskItem taskItem);
void addTask(std::string text, std::string date);
void removeTask(const TaskItem* taskItem);

View file

@ -6,6 +6,7 @@
#include "TaskItem.h"
#include <algorithm>
namespace mirai {
@ -28,5 +29,13 @@ namespace mirai {
const std::string& TaskItem::getText() const { return text; }
const TaskItemState& TaskItem::getState() const { return state; }
const std::string& TaskItem::getDate() const { return date; }
const std::string& TaskItem::getStartTime() const { return startTime; }
const std::string& TaskItem::getEndTime() const { return endTime; }
const Tags& TaskItem::getTags() const { return tags; }
bool TaskItem::hasDate() const { return isDate(date); }
bool TaskItem::hasTag(const std::string& tag) const {
return std::find(tags.begin(), tags.end(), tag) != tags.end();
}
}

View file

@ -7,6 +7,7 @@
#ifndef MIRAI_TASKITEM_H
#define MIRAI_TASKITEM_H
#include "using.h"
#include "utils.h"
#include <ctime>
#include <fstream>
@ -35,14 +36,22 @@ namespace mirai {
void setText(const std::string& text);
const std::string& getLine() const;
const std::string& getText() const;
const TaskItemState& getState() const;
const std::string& getDate() const;
const std::string& getStartTime() const;
const std::string& getEndTime() const;
const Tags& getTags() const;
bool hasTag(const std::string& tag) const;
bool hasDate() const;
std::string text;
TaskItemState state;
std::string date;
std::string startTime;
std::string endTime;
Tags tags;
};
}

View file

@ -5,13 +5,13 @@
*/
#include "TasksFile.h"
#include "using.h"
#include "TaskItem.h"
#include <memory>
namespace mirai {
TasksFile::TasksFile(TasksFileConstructor params) : name(params.name), path(params.path) {
for (const auto& task : params.tasks) {
processTaskMetaData(task);
tasks.push_back(std::make_unique<TaskItem>(task));
}
sortByDate();
@ -20,7 +20,11 @@ namespace mirai {
const std::string& TasksFile::getName() const { return name; }
const std::string& TasksFile::getPath() const { return path; }
TasksPtrs& TasksFile::getTasks() { return tasks; }
Tags& TasksFile::getTags() { return tags; }
void TasksFile::addTask(TaskItem taskItem) {
tasks.push_back(std::make_unique<TaskItem>(taskItem));
sortByDate();
}
void TasksFile::addTask(std::string text, std::string date) {
auto newTask = std::make_unique<TaskItem>(TaskItem{
@ -38,26 +42,6 @@ namespace mirai {
}));
}
void TasksFile::processTaskMetaData(const TaskItem& task) {
const std::string metaDataSeparator = " -- ";
auto separatorIndex = task.text.find(metaDataSeparator);
if (separatorIndex == std::string::npos) {
return;
}
auto metaData = task.text.substr(separatorIndex + metaDataSeparator.length());
std::regex regex("(#[a-zA-Z0-1]+)");
std::smatch matches;
while (std::regex_search(metaData, matches, regex))
{
if (std::find(tags.begin(), tags.end(), matches[0]) == tags.end()) {
tags.push_back(matches[0]);
}
metaData = matches.suffix();
}
}
void TasksFile::sortByDate() {
std::sort(tasks.begin(), tasks.end(), [] (const std::unique_ptr<TaskItem>& t1, const std::unique_ptr<TaskItem>& t2) {
if (t1->hasDate() && !t2->hasDate()) {

View file

@ -25,6 +25,9 @@
namespace mirai {
using TasksPtrs = std::vector<std::unique_ptr<TaskItem>>;
struct TasksFileConstructor {
const std::string& name;
const std::string& path;
@ -38,20 +41,18 @@ namespace mirai {
TasksFile(TasksFileConstructor params);
void addTask(std::string text, std::string date);
void addTask(TaskItem TaskItem);
void removeTask(const TaskItem* taskToRemove);
void processTaskMetaData(const TaskItem& task);
void sortByDate();
const std::string& getName() const;
const std::string& getPath() const;
TasksPtrs& getTasks();
Tags& getTags();
private:
std::string name;
std::string path;
TasksPtrs tasks;
Tags tags;
};
}

View file

@ -25,7 +25,7 @@ namespace mirai {
for (auto& task : file.getTasks()) {
if (tagsFilter.size() != 0
&& std::find_if(tagsFilter.begin(), tagsFilter.end(), [&](const std::string& tag) {
return task->getText().find(tag) != std::string::npos;
return task->hasTag(tag);
}) == tagsFilter.end())
continue;
tasksToShow.push_back(task.get());

View file

@ -5,6 +5,7 @@
*/
#include "TodoMd.h"
#include "TaskItem.h"
namespace mirai {
@ -27,13 +28,8 @@ namespace mirai {
if (line.substr(0, 3) == "## ") {
currentDate = line.substr(3);
} else if (line.substr(0, 5) == "- [ ]" || line.substr(0, 5) == "- [X]") {
std::string text = line.substr(5);
trim(text);
TaskItem taskItem = {
.text = text,
.state = line.substr(0, 5) == "- [X]" ? DONE : TODO,
.date = currentDate
};
TaskItem taskItem = StringToTask(line, currentDate);
taskItem.setDate(currentDate);
taskItems.push_back(taskItem);
}
}
@ -46,6 +42,22 @@ namespace mirai {
return tasks;
}
Tags TodoMdFormat::extractTagsFromMetadata(std::string metadata) {
Tags tags;
std::regex regex("(#[a-zA-Z0-1]+)");
std::smatch matches;
while (std::regex_search(metadata, matches, regex))
{
if (std::find(tags.begin(), tags.end(), matches[0]) == tags.end()) {
tags.push_back(matches[0]);
}
metadata = matches.suffix();
}
return tags;
}
void TodoMdFormat::writeFile(TasksFile& tasks) {
std::ofstream file(tasks.getPath());
if (!file.is_open()) {
@ -59,12 +71,7 @@ namespace mirai {
currentDate = task->date;
file << "\n## " << (task->date != "" ? task->date : "No date") << "\n\n";
}
if (task->getState() == TODO) {
file << "- [ ] ";
} else if (task->getState() == DONE) {
file << "- [X] ";
}
file << task->getText() << '\n';
file << TaskToString(*task) << '\n';
}
file.close();
}
@ -74,5 +81,49 @@ namespace mirai {
return "";
return (field + " ");
}
TaskItem TodoMdFormat::StringToTask(const std::string& str, const std::string& date) {
std::smatch matches;
std::regex regex("- \\[(\\s|X)\\] (([0-9]{2}:[0-9]{2})-([0-9]{2}:[0-9]{2}) > )?(.*?)( -- (.*))?");
std::regex_match(str, matches, regex);
std::cout << "line " << str << std::endl;
std::cout << "M 0 " << matches[0] << std::endl;
std::cout << "M 1 " << matches[1] << std::endl;
std::cout << "M 2 " << matches[2] << std::endl;
std::cout << "M 3 " << matches[3] << std::endl;
std::cout << "M 4 " << matches[4] << std::endl;
std::cout << "M 5 " << matches[5] << std::endl;
std::cout << "M 6 " << matches[6] << std::endl;
std::cout << "M 7 " << matches[7] << std::endl;
std::string text = matches[5];
trim(text);
TaskItem taskItem = {
.text = text,
.state = str.substr(0, 5) == "- [X]" ? DONE : TODO,
.date = date,
.startTime = matches[3],
.endTime = matches[4],
.tags = extractTagsFromMetadata(matches[7])
};
return taskItem;
}
std::string TodoMdFormat::TaskToString(const TaskItem& task) {
std::string str = task.getText();
if (task.getTags().size() > 0) {
str += " --";
for (const std::string& tag : task.getTags()) {
str += " " + tag;
}
}
if (task.getStartTime() != "" && task.getEndTime() != "") {
str = task.getStartTime() + "-" + task.getEndTime() + " > " + str;
}
str = (task.getState() == DONE ? "- [X] " : "- [ ] ") + str;
return str;
}
}

View file

@ -28,10 +28,14 @@ namespace mirai {
static TasksFile readFile(const std::string& path);
static void writeFile(TasksFile& tasks);
static std::string TaskToString(const TaskItem& task);
static TaskItem StringToTask(const std::string& str, const std::string& date);
private:
static std::string fieldWithSpace(const std::string& field);
static TaskItem parseLine(const std::string& line);
static Tags extractTagsFromMetadata(std::string metadata);
};
}

View file

@ -7,14 +7,12 @@
#ifndef MIRAI_USING_H
#define MIRAI_USING_H
#include "TaskItem.h"
#include <memory>
#include <string>
#include <vector>
namespace mirai {
using Tags = std::vector<std::string>;
using TasksPtrs = std::vector<std::unique_ptr<TaskItem>>;
}
#endif

View file

@ -18,7 +18,7 @@ ColumnLayout {
signal confirmed
onTaskToEditChanged: {
newTodoContent.text = taskToEdit?.text ?? ""
newTodoContent.text = taskToEdit?.rawFormat ?? "- [ ] "
newTodoDate.text = taskToEdit?.date ?? ""
}
@ -30,16 +30,16 @@ ColumnLayout {
id: newTodoContent
Layout.fillWidth: true
placeholderText: "Enter your new task..."
text: taskToEdit?.text ?? ""
text: taskToEdit?.rawFormat ?? ""
Keys.onReturnPressed: {
if (newTodoContent.text == "") {
return
}
if (taskToEdit && taskToEditIndex !== undefined) {
backend.updateTodo(taskToEditIndex, taskToEdit.state, newTodoContent.text, newTodoDate.text)
backend.updateTodoFromRawFormat(taskToEditIndex, newTodoContent.text, newTodoDate.text)
} else {
backend.addTodo(newTodoContent.text, newTodoDate.text)
backend.addTodoFromRawFormat(newTodoContent.text, newTodoDate.text)
}
form.confirmed()
}