diff --git a/compile_debug.sh b/compile_debug.sh index 7b55053..ae2f66f 100755 --- a/compile_debug.sh +++ b/compile_debug.sh @@ -2,4 +2,11 @@ mkdir -p bin/debug -g++ -o bin/debug/famt -std=gnu++20 -g -O0 *.cpp -lncursesw +warnings=' + -Wall + -Wextra + -Wpedantic + -Wmultiple-inheritance + -Wvirtual-inheritance' #-fanalyzer + +g++ -o bin/debug/famt -std=gnu++20 -g -O0 $warnings *.cpp -lncursesw diff --git a/help.cpp b/help.cpp index 1a1a38b..72234af 100644 --- a/help.cpp +++ b/help.cpp @@ -1 +1,18 @@ -/* #include"help.h" */ +#include "help.h" + +bool willBeVisible(I16 drawY, I16 drawX, U16 height, U16 width) +{ + return (drawY + height > 0) && (drawX + width > 0) && + drawY < LINES && drawX < COLS; +} + +void drawpad(WINDOW* pad, I16 drawY, I16 drawX) +{ + const U16 pbegY = drawY>0 ? 0 : -drawY; /* pad top left coords to be displayed */ + const U16 pbegX = drawX>0 ? 0 : -drawX; + + pnoutrefresh(pad, + pbegY, pbegX, + drawY, drawX, + LINES - 1, COLS - 1); +} diff --git a/help.h b/help.h index d1c1387..c61c860 100644 --- a/help.h +++ b/help.h @@ -1,36 +1,48 @@ #pragma once - -#include "common/basicTypes.h" #include +#include +#include "common/basicTypes.h" -template inline -Vec& operator+=(Vec& lhs, Vec&& rhs) // Combine 2 vectors -{ - lhs.reserve(lhs.size() + rhs.size()); +/* template */ +/* Vec& operator+=(Vec& lhs, Vec&& rhs) // Combine 2 vectors */ +/* { */ +/* lhs.reserve(lhs.size() + rhs.size()); */ - for(auto& el: rhs) - lhs.push_back( std::forward(el) ); - return lhs; -} +/* for(auto&& el: rhs) */ +/* lhs.push_back( std::move(el) ); */ +/* return lhs; */ +/* } */ -template inline -Vec& operator+=(Vec& lhs, const Vec& rhs) // Combine 2 vectors -{ - lhs.reserve(lhs.size() + rhs.size()); +/* template */ +/* Vec& operator+=(Vec& lhs, const Vec& rhs) // Combine 2 vectors */ +/* { */ +/* lhs.reserve(lhs.size() + rhs.size()); */ - for(const auto& el: rhs) - lhs.push_back( std::forward(el) ); - return lhs; -} +/* for(const auto& el: rhs) */ +/* lhs.push_back(el); */ +/* return lhs; */ +/* } */ -template inline +template void remove(Vec& vec, size_t pos) /* Remove from vector by moving the last element in its place */ { vec[pos] = vec[vec.size() - 1]; vec.pop_back(); } +inline I32 min(I32 a, I32 b) +{ + return a <= b ? a : b; +} + inline I32 max(I32 a, I32 b) { return a >= b ? a : b; } + +/* wheather a pad with the given coordinates will be visible */ +bool willBeVisible(I16 drawY, I16 drawX, U16 height, U16 width); + +/* like pnoutrefresh but pminrow,col are calculated based on width,height and + top left coords, which can be negative (outside the screen) */ +void drawpad(WINDOW* pad, I16 drawY, I16 drawX); diff --git a/main.cpp b/main.cpp index b0fb558..e1900b1 100644 --- a/main.cpp +++ b/main.cpp @@ -52,9 +52,9 @@ int main() test1.display(); test2.display(); - /* (test1 + test2).display(); */ - test1 += test2; - test1.display(); + (test2 + test1).display(); + /* test2 += test1; */ + /* test2.display(); */ /* test1.display(); */ diff --git a/person.cpp b/person.cpp index f26ffed..9078e48 100644 --- a/person.cpp +++ b/person.cpp @@ -166,31 +166,29 @@ U16 Person::boxWidth() const /* return pad; */ /* } */ -void Person::draw(I16 drawY, I16 drawX, bool selected, bool hasSpouse, bool isSpouse, bool hasKids) const +void Person::draw(const I16 drawY, const I16 drawX, bool selected, bool hasSpouse, bool isSpouse, bool hasKids) const { - U16 width = boxWidth(); - WINDOW* pad = newpad(BOX_HEIGHT, width); + const U16 width = boxWidth(); /* pad width */ - auto color_pair = COLOR_PAIR( selected ? COLOR_SELECTED - : (isMale_ ? COLOR_MALE : COLOR_FEMALE) ); + if(willBeVisible(drawY, drawX, BOX_HEIGHT, width)) + { + WINDOW* pad = newpad(BOX_HEIGHT, width); + auto color_pair = COLOR_PAIR( selected ? COLOR_SELECTED + : (isMale_ ? COLOR_MALE : COLOR_FEMALE) ); - wbkgd(pad, color_pair); - /* wattron(pad, color_pair); */ + wbkgd(pad, color_pair); + /* wattron(pad, color_pair); */ - wborder(pad, ACS_VLINE, ACS_VLINE, ACS_HLINE, ACS_HLINE, - isSpouse ? ACS_TTEE : ACS_LTEE, hasSpouse ? ACS_TTEE : ACS_URCORNER, - hasKids ? ACS_LTEE : ACS_LLCORNER, ACS_LRCORNER ); - /* if(hasSpouse) */ - /* { */ - /* mvaddch( */ + wborder(pad, ACS_VLINE, ACS_VLINE, ACS_HLINE, ACS_HLINE, + isSpouse ? ACS_TTEE : ACS_LTEE, hasSpouse ? ACS_TTEE : ACS_URCORNER, + hasKids ? ACS_LTEE : ACS_LLCORNER, ACS_LRCORNER ); - mvwaddstr(pad, 2, 2, name_.data()); + mvwaddstr(pad, 2, 2, name_.data()); - /* wattroff(pad, color_pair); */ + /* wattroff(pad, color_pair); */ - pnoutrefresh(pad, 0, 0, - drawY, drawX, - drawY + BOX_HEIGHT-1, drawX + width-1); - delwin(pad); + drawpad(pad, drawY, drawX); + delwin(pad); + } } diff --git a/person.h b/person.h index 8922dfc..e3c6232 100644 --- a/person.h +++ b/person.h @@ -52,7 +52,7 @@ public: U16 boxWidth() const; /* Draw a Person's box on the terminal - drawY,drawX - the coordinates where to draw + drawY,drawX - top left coordinates where to draw (negative if outside the screen) returns the width of the box*/ void draw(I16 drawY, I16 drawX, bool selected, bool hasSpouse, bool isSpouse, bool hasChildren=false) const; diff --git a/todo.txt b/todo.txt index 13f749a..afc248b 100644 --- a/todo.txt +++ b/todo.txt @@ -1,4 +1,3 @@ -Selecting people Help addPerson add siblings (add relation improve) @@ -8,23 +7,28 @@ findRelative findRelation - extend Draw distinct regions of a tree -Draw spouses' relatives if main has none +Draw spouses' relatives if main has none? -Color - -Partialy visible people -Scrolling Zooming Visualization: -- proper horizontal navigation +- draw parents of focused +- horizontal navigation between cousins +- color on different consoles +- screen resize Compilation - static and dynamic ncurses ? -- same person can be present twice +- same person can be displayed twice +- coordinate types for large trees Backend - move to SQLlite -- backup +- create tree backup + +Refactoring +- check if vector combine && works correctly +- nobody = 0 +- comment style /* diff --git a/tree.cpp b/tree.cpp index 9ee8046..67d599b 100644 --- a/tree.cpp +++ b/tree.cpp @@ -8,62 +8,63 @@ using std::cout; using std::vector; -Tree Tree::operator+ (const Tree& other)// +Tree Tree::operator+ (const Tree& other) const { - Tree result(treeName + other.treeName); //The tree resulting from the addition - vector newId; //The indexes members of the II tree will have in result - newId.reserve(other.numPeople); + /* Tree result(treeName + other.treeName); //The tree resulting from the addition */ + /* vector newId; //The indexes members of the II tree will have in result */ + /* newId.reserve(other.numPeople); */ - U32 idCounter = numPeople; - for (U32 i = 0, j; i < other.numPeople; ++i) //Searches for people present in both trees and gives them the same index in result - { - for (j = 0; j < numPeople; ++j) - { - if (other.people[i] == people[j]) - { - newId[i] = j; - break; - } - } - if (j >= numPeople) - newId[i] = ++idCounter; - } - result.numPeople = idCounter; //The number of members the resulting tree has + /* U32 idCounter = numPeople; */ + /* for (U32 i = 0, j; i < other.numPeople; ++i) //Searches for people present in both trees and gives them the same index in result */ + /* { */ + /* for (j = 0; j < numPeople; ++j) */ + /* { */ + /* if (other.people[i] == people[j]) */ + /* { */ + /* newId[i] = j; */ + /* break; */ + /* } */ + /* } */ + /* if (j >= numPeople) */ + /* newId[i] = ++idCounter; */ + /* } */ + /* result.numPeople = idCounter; //The number of members the resulting tree has */ - result.people.reserve(result.numPeople); - result.people = people; //Adds the members of the I tree to the resulting tree - for (U32 i=0; i < other.numPeople; ++i) //Adds the members of the II tree to the resulting tree - { - if (newId[i] >= numPeople) - result.people.push_back(other.people[i]); - } + /* result.people.reserve(result.numPeople); */ + /* result.people = people; //Adds the members of the I tree to the resulting tree */ + /* for (U32 i=0; i < other.numPeople; ++i) //Adds the members of the II tree to the resulting tree */ + /* { */ + /* if (newId[i] >= numPeople) */ + /* result.people.push_back(other.people[i]); */ + /* } */ - result.relations.reserve(result.numPeople); - result.relations = relations; + /* result.relations.reserve(result.numPeople); */ + /* result.relations = relations; */ - for (U32 i=0; i < other.numPeople; ++i) //Adds the relatives from the II tree - { - if (newId[i] >= numPeople) //If the member is found in the II tree but not in the I - { - result.relations.push_back(other.relations[i]); - } - else //If he's found in both - { - for (unsigned j = 0; j < other.people[i].numRel_; ++j) //Adds the number of relatives from the II to the number in the I - { - if (newId[other.relations[i][j].id] > numPeople) - ++result.people[newId[i]].numRel_; - } + /* for (U32 i=0; i < other.numPeople; ++i) //Adds the relatives from the II tree */ + /* { */ + /* if (newId[i] >= numPeople) //If the member is found in the II tree but not in the I */ + /* { */ + /* result.relations.push_back(other.relations[i]); */ + /* } */ + /* else //If he's found in both */ + /* { */ + /* for (person_id j = 0; j < other.relations[i].size(); ++j) //Adds the number of relatives from the II to the number in the I */ + /* { */ + /* if (newId[other.relations[i][j].id] > numPeople) */ + /* ++result.people[newId[i]].numRel_; */ + /* } */ - result.relations[newId[i]].reserve(result.people[newId[i]].numRel_); + /* result.relations[newId[i]].reserve(result.people[newId[i]].numRel_); */ - result.relations[newId[i]] = relations[newId[i]]; + /* result.relations[newId[i]] = relations[newId[i]]; */ - result.relations[newId[i]] += other.relations[i]; //The relatives from the II tree - } - } + /* result.relations[newId[i]] += other.relations[i]; //The relatives from the II tree */ + /* } */ + /* } */ + Tree result(*this); - return result; + return result += other; } Tree& Tree::operator+=(const Tree& other) @@ -72,7 +73,7 @@ Tree& Tree::operator+=(const Tree& other) newId.reserve(other.numPeople); U32 idCounter = numPeople; - for (U32 i = 0, j; i < other.numPeople; ++i) //Searches for people present in both trees and gives them the same index in I + for (person_id i = 0, j; i < other.numPeople; ++i) //find the new ids for people in II, people present in both trees get the ids from I { for (j = 0; j < numPeople; ++j) { @@ -82,40 +83,52 @@ Tree& Tree::operator+=(const Tree& other) break; } } - if (j >= numPeople) + if (j >= numPeople) /* not present in I */ newId[i] = idCounter++; } people.reserve(idCounter); - for (U32 i = 0; i < other.numPeople; ++i) //Adds the member personal data of II tree to I tree + for (person_id i = 0; i < other.numPeople; ++i) /* add the personal data of II to I */ { - if (newId[i] >= numPeople) + if (newId[i] >= numPeople) /* isnt already in I */ people.push_back(other.people[i]); } relations.reserve(idCounter); - for (U32 i = 0; i < other.numPeople; ++i) //Merges the relative data + for (person_id i = 0; i < other.numPeople; ++i) //merge the relative data { - if (newId[i] >= numPeople) + if (newId[i] >= numPeople) /* isnt already in I */ { relations.push_back(other.relations[i]); - for (U32 j = 0; j < other.people[i].numRel_; ++j) - relations[newId[i]][j].id = newId[ relations[newId[i]][j].id ]; + for (Relation& rel: relations.back()) + rel.id = newId[rel.id]; + /* for (person_id j = 0; j < other.people[i].numRel_; ++j) */ + /* relations[newId[i]][j].id = newId[ relations[newId[i]][j].id ]; */ } - else //If the member is present in both trees + else //if present in both trees { - for (U32 j = 0; j < other.people[i].numRel_; ++j) //Adds the number of relatives from the II to the number in the I + /* for (person_id j = 0; j < other.people[i].numRel_; ++j) //combine relations */ + /* { */ + /* if (newId[other.relations[i][j].id] >= numPeople) */ + /* ++people[newId[i]].numRel_; */ + /* } */ + person_id idIn1 = newId[i]; + relations[idIn1].reserve(relations[idIn1].size() + other.relations[i].size()); + + for (Relation rel: other.relations[i]) { - if (newId[other.relations[i][j].id] >= numPeople) - ++people[newId[i]].numRel_; + if(newId[rel.id] >= numPeople) /* not already in I */ + relations[idIn1].push_back( {newId[rel.id], rel.type} ); + else + { + } } - relations[newId[i]].reserve(people[newId[i]].numRel_); - for (U32 j = 0; j < other.people[i].numRel_; ++j) - { - relations[newId[i]][j + people[newId[i]].numRel_ - other.people[i].numRel_].id = newId[other.relations[i][j].id]; - relations[newId[i]][j + people[newId[i]].numRel_ - other.people[i].numRel_].type = other.relations[i][j].type; - } + /* for (person_id j = 0; j < other.people[i].numRel_; ++j) */ + /* { */ + /* relations[newId[i]][j + people[newId[i]].numRel_ - other.people[i].numRel_].id = newId[other.relations[i][j].id]; */ + /* relations[newId[i]][j + people[newId[i]].numRel_ - other.people[i].numRel_].type = other.relations[i][j].type; */ + /* } */ } } @@ -415,7 +428,7 @@ void Tree::display() I32 c; do { - c = std::tolower(getch()); + c = std::toupper(getch()); switch(c) { @@ -424,41 +437,41 @@ void Tree::display() draw(); break; case KEY_LEFT: - --offsetX_; - draw(); - break; - case KEY_RIGHT: ++offsetX_; draw(); break; - case KEY_DOWN: - ++offsetY_; + case KEY_RIGHT: + --offsetX_; draw(); break; - case KEY_UP: + case KEY_DOWN: --offsetY_; draw(); break; - case 'h': + case KEY_UP: + ++offsetY_; + draw(); + break; + case 'H': selectLeft(); break; - case 'j': + case 'J': selectDown(); break; - case 'k': + case 'K': selectUp(); break; - case 'l': + case 'L': selectRight(); break; - case 'i': + case 'I': people[selected_].displayInfo(); draw(); break; default: break; } } - while(c != 'w'); + while(c != 'W'); } void Tree::draw() const @@ -560,17 +573,17 @@ void Tree::commonAncestorRec(person_id id, vector &visited) const static U8 linkToFirstBorn(I16 startY, I16 startX, bool moreSiblings) { - if (startY >= -2 && startX >= 0) + if (willBeVisible(startY, startX, 3, 1)) { - WINDOW* win = newwin(3, 1, startY, startX); /* TODO: pad */ + WINDOW* pad = newpad(3, 1); - waddch(win, ACS_VLINE); - mvwaddch(win, 1, 0, + waddch(pad, ACS_VLINE); + mvwaddch(pad, 1, 0, moreSiblings ? ACS_LTEE : ACS_VLINE); - mvwaddch(win, 2, 0, ACS_VLINE); + mvwaddch(pad, 2, 0, ACS_VLINE); - wnoutrefresh(win); - delwin(win); + drawpad(pad, startY, startX); + delwin(pad); } return 3; } @@ -578,23 +591,22 @@ static U8 linkToFirstBorn(I16 startY, I16 startX, bool moreSiblings) static U8 linkToChild(I16 startY, I16 startX, I16 endX, bool moreSiblings) { assert(endX >= startX); - - if (startY >= -1 && endX >= 0) + const I16 len = endX - startX; + if (willBeVisible(startY, startX, 2, len)) { - const I16 len = endX - startX; - WINDOW* win = newwin(2, len, startY, startX); + WINDOW* pad = newpad(2, len); for(U16 i = 0; i < len-1; ++i) - waddch(win, ACS_HLINE); - /* whline(win, '_', len-1); */ - waddch(win, moreSiblings ? ACS_TTEE : ACS_URCORNER); + waddch(pad, ACS_HLINE); + /* whline(pad, '_', len-1); */ + waddch(pad, moreSiblings ? ACS_TTEE : ACS_URCORNER); - mvwaddch(win, 1, len-1, ACS_VLINE); + mvwaddch(pad, 1, len-1, ACS_VLINE); - wnoutrefresh(win); - delwin(win); + drawpad(pad, startY, startX); + delwin(pad); } - return 3; + return 2; } @@ -667,7 +679,7 @@ I16 Tree::drawLineWithWives(const person_id id, I16 drawY, const I16 drawX) cons for(size_t j = 1; j < numKids; ++j) { - lnHt = linkToChild(drawY+1, prevX+1, childX+1, j < numKids-1); + lnHt = linkToChild(drawY+1, prevX+1, childX+1, j < numKids-1) + 1; /* +1 because LTC starts lower then LTFB */ prevX = childX; childX = drawLineWithWives(children[j], drawY + lnHt, childX); } @@ -677,7 +689,7 @@ I16 Tree::drawLineWithWives(const person_id id, I16 drawY, const I16 drawX) cons childX); } -void Tree::selectLeft() /* todo */ +void Tree::selectLeft() { if (findCommonAncestor(focused_, selected_) != Nobody) //if the selected is part of main tree { diff --git a/tree.h b/tree.h index b392df6..6fe7dbe 100644 --- a/tree.h +++ b/tree.h @@ -33,12 +33,12 @@ class Tree public: Tree() = default; template - Tree(Str&& Name) : treeName(std::forward(Name)) {} - /*Tree(const Tree&); - Tree& operator= (const Tree& other);*/ + explicit Tree(Str&& Name) : treeName(std::forward(Name)) {} + /* Tree(const Tree&) = default; */ + /* Tree& operator= (const Tree& other); */ - Tree operator+ (const Tree& other);//doesnt work - Tree operator- (const Tree& other); + Tree operator+ (const Tree& other) const; + Tree operator- (const Tree& other) const; /* todo */ Tree& operator+= (const Tree& other); Tree& operator-= (const Tree& other);