local instructions

This commit is contained in:
vrd
2023-11-02 21:25:56 +02:00
parent 6a71d7e13c
commit bc5e5d1deb
11 changed files with 210 additions and 166 deletions
+62
View File
@@ -0,0 +1,62 @@
tft - Terminal Family Tree
==========================
tft is an ncurses program that can create and display family trees on the terminal.
Webpage
-------
https://vene.volconst.com/en/tft
Dependecies
-----------
ncursesw shared library and headers (libncursesw5-dev on Debian/Ubuntu)
Installation
------------
Make sure you satisfy the dependencies and execute:
git clone https://gitlab.com/venelin98/tft.git
cd tft
sudo ./install.sh
Creating trees
--------------
Trees are created in plain text files following the tft file format.
Spaces are not important but new lines are considered as separators.
Adding a member
---------------
A new line begining with a name is considered a member definition, the name can include spaces.
After the name the sex can be specifed with a comma followed by either M or F, if not given male is assumed.
For example:
Adam, M
Declares member Adam that is male.
Adding member information
-------------------------
In the lines following a member declaration, various info can be added:
s: - Spouses, must be followed by comma separated names of already declared members, "-" can be given instead in which case the last declared person of the opposite sex is used
p: - Parents, must be followed by 1 or 2 names separated by a comma, "-" can be given instead in which case the previous parents are used
b: - Birthday in the format yyyy.mm.dd, day and month can be ommited
d: - Death date
Duplicate names
---------------
A number after a name is used to disambiguate when multiple people have identical names e.g.:
"Adam 0" is the first added Adam, "Adam 1" is the second
Viewing trees
-------------
After creating a tree file you can view it using tft:
tft my_tree.tft
Once the tree is displayed you can navigate it using:
arrows - move the camera
h, j, k, l - move around the tree
Enter, Space - display the selected person's tree
+ - show full names
- - show first names only
w - close the current tree
УПЪТВАНЕ НА БЪЛГАРСКИ:
https://vene.volconst.com/bg/tft
+1 -1
View File
@@ -32,4 +32,4 @@ g++ -o tft $language $optimizations $warnings $other -DNDEBUG -pipe -s *.cpp -ln
#-static -lncursesw -ltinfo #-static -lncursesw -ltinfo
chmod 775 tft chmod 775 tft
exec mv tft /usr/local/bin mv tft /usr/local/bin
-5
View File
@@ -1,5 +0,0 @@
For information visit:
https://vene.volconst.com/en/tft
Упътване на български:
https://vene.volconst.com/bg/tft
-1
View File
@@ -10,7 +10,6 @@ using std::string_view;
using std::string; using std::string;
using std::vector; using std::vector;
using std::pair; using std::pair;
/* using std::endl; */
namespace /* internal */ namespace /* internal */
{ {
+2 -4
View File
@@ -60,7 +60,7 @@ bool Person::operator==(const Person &other)const
void Person::displayInfo()const void Person::displayInfo()const
{ {
WINDOW* info_tab = newwin(LINES, COLS, 0, 0); AutoWin info_tab( newwin(LINES, COLS, 0, 0) );
waddstr(info_tab, name.data()); waddstr(info_tab, name.data());
waddch(info_tab,'\n'); waddch(info_tab,'\n');
@@ -78,7 +78,6 @@ void Person::displayInfo()const
werase(info_tab); werase(info_tab);
wrefresh(info_tab); /* todo: dont update */ wrefresh(info_tab); /* todo: dont update */
delwin(info_tab);
} }
@@ -118,7 +117,7 @@ U16 Person::draw(const I16 drawY, const I16 drawX, bool selected, bool hasSpouse
if(willBeVisible(drawY, drawX, BOX_HEIGHT, width)) if(willBeVisible(drawY, drawX, BOX_HEIGHT, width))
{ {
WINDOW* pad = newpad(BOX_HEIGHT, width); AutoWin pad( newpad(BOX_HEIGHT, width) );
auto color_pair = COLOR_PAIR( selected ? COLOR_SELECTED auto color_pair = COLOR_PAIR( selected ? COLOR_SELECTED
: (sex==M ? COLOR_MALE : COLOR_FEMALE) ); : (sex==M ? COLOR_MALE : COLOR_FEMALE) );
@@ -138,7 +137,6 @@ U16 Person::draw(const I16 drawY, const I16 drawX, bool selected, bool hasSpouse
/* wattroff(pad, color_pair); */ /* wattroff(pad, color_pair); */
drawpad(pad, drawY, drawX); drawpad(pad, drawY, drawX);
delwin(pad);
} }
return width; return width;
} }
+4 -18
View File
@@ -2,49 +2,35 @@
#include "utils.hpp" #include "utils.hpp"
#include "parser.hpp" #include "parser.hpp"
#include <ncursesw/ncurses.h> #include <ncursesw/ncurses.h>
/* #include <string_view> */
#include <iostream> #include <iostream>
#include <string.h> #include <string.h>
/* using std::string_view; */
using std::cout; using std::cout;
/* using namespace std::literals; */
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
if(argc < 2) if(argc < 2)
{ {
cout << "Usage: tft FILES...\n"; cout << "Usage: tft FILES...\n";
return 0; return 1;
} }
if(!strcmp(argv[1], "--help")) if(!strcmp(argv[1], "--help"))
{ {
cout << "Usage: tft FILES...\n" cout << "Usage: tft FILES...\n"
<< "Display the combined family tree in the FILES\n"; << "Display the combined family tree from the FILES\n\n"
<< VISUALIZATION_HELP_STR;
return 0; return 0;
} }
Tree tree( parseTftFile(argv[1]) ); Tree tree( parseTftFile(argv[1]) );
/* bool negative = false; */
for(int i = 2; i < argc; ++i) for(int i = 2; i < argc; ++i)
{ {
tree += parseTftFile(argv[i]); tree += parseTftFile(argv[i]);
/* if( !strcmp(argv[i], "-") ) */
/* { */
/* negative = true; */
/* } */
/* else */
/* { */
/* if(negative) */
/* tree -= parseTftFile(argv[i]); */
/* else */
/* tree += parseTftFile(argv[i]); */
/* } */
} }
init(); init_ncurses();
tree.display(); tree.display();
return 0; return 0;
+81 -86
View File
@@ -18,15 +18,15 @@ Tree Tree::operator+ (const Tree& other) const
Tree& Tree::operator+=(const Tree& other) Tree& Tree::operator+=(const Tree& other)
{ {
vector<person_id> newId; //The indexes people from II tree will have in I tree vector<person_id> newId; //The indexes people from II tree will have in I tree
newId.reserve(other.people.size()); newId.reserve(other.people_.size());
U32 initNum = people.size(); /* number of people at the start */ U32 initNum = people_.size(); /* number of people at the start */
U32 idCounter = initNum; U32 idCounter = initNum;
for (person_id i = 0, j; i < other.people.size(); ++i) //find the new ids for people in II, people present in both trees get the ids from I for (person_id i = 0, j; i < other.people_.size(); ++i) //find the new ids for people in II, people present in both trees get the ids from I
{ {
for (j = 0; j < initNum; ++j) for (j = 0; j < initNum; ++j)
{ {
if (other.people[i] == people[j]) if (other.people_[i] == people_[j])
{ {
newId[i] = j; newId[i] = j;
break; break;
@@ -36,31 +36,31 @@ Tree& Tree::operator+=(const Tree& other)
newId[i] = idCounter++; newId[i] = idCounter++;
} }
people.reserve(idCounter); people_.reserve(idCounter);
for (person_id i = 0; i < other.people.size(); ++i) /* add the personal data of II to I */ for (person_id i = 0; i < other.people_.size(); ++i) /* add the personal data of II to I */
{ {
if (newId[i] >= initNum) /* isnt already in I */ if (newId[i] >= initNum) /* isnt already in I */
people.push_back(other.people[i]); people_.push_back(other.people_[i]);
} }
relations.reserve(idCounter); relations_.reserve(idCounter);
for (person_id i = 0; i < other.people.size(); ++i) //merge the relative data for (person_id i = 0; i < other.people_.size(); ++i) //merge the relative data
{ {
if (newId[i] >= initNum) /* isnt already in I */ if (newId[i] >= initNum) /* isnt already in I */
{ {
relations.push_back(other.relations[i]); relations_.push_back(other.relations_[i]);
for (Relation& rel: relations.back()) for (Relation& rel: relations_.back())
rel.id = newId[rel.id]; rel.id = newId[rel.id];
} }
else //if present in both trees else //if present in both trees
{ {
person_id idIn1 = newId[i]; person_id idIn1 = newId[i];
relations[idIn1].reserve(relations[idIn1].size() + other.relations[i].size()); relations_[idIn1].reserve(relations_[idIn1].size() + other.relations_[i].size());
for (Relation rel: other.relations[i]) for (Relation rel: other.relations_[i])
{ {
if(newId[rel.id] >= initNum) /* not already in I */ if(newId[rel.id] >= initNum) /* not already in I */
relations[idIn1].push_back( {newId[rel.id], rel.type} ); relations_[idIn1].push_back( {newId[rel.id], rel.type} );
} }
} }
@@ -71,11 +71,11 @@ Tree& Tree::operator+=(const Tree& other)
Tree& Tree::operator-= (const Tree& other) Tree& Tree::operator-= (const Tree& other)
{ {
for (U32 i = 0; i < people.size(); ++i) for (U32 i = 0; i < people_.size(); ++i)
{ {
for (const Person& othPers: other.people) for (const Person& othPers: other.people_)
{ {
if (people[i] == othPers) if (people_[i] == othPers)
{ {
removePerson(i); removePerson(i);
--i; --i;
@@ -89,20 +89,20 @@ Tree& Tree::operator-= (const Tree& other)
void Tree::rename(const char* newName) void Tree::rename(const char* newName)
{ {
treeName = newName; treeName_ = newName;
} }
person_id Tree::last() person_id Tree::last()
{ {
return people.size() - 1; return people_.size() - 1;
} }
vector<person_id> Tree::findId(const string& name) const vector<person_id> Tree::findId(const string& name) const
{ {
vector<person_id> res; vector<person_id> res;
for (person_id i = 0; i < people.size(); ++i) for (person_id i = 0; i < people_.size(); ++i)
{ {
if (name == people[i].name) if (name == people_[i].name)
res.push_back(i); res.push_back(i);
} }
return res; return res;
@@ -111,9 +111,9 @@ vector<person_id> Tree::findId(const string& name) const
/* person_id Tree::findId(const string& name, Sex s) const */ /* person_id Tree::findId(const string& name, Sex s) const */
/* { */ /* { */
/* Person sought(name, {}, s); */ /* Person sought(name, {}, s); */
/* for (person_id i = 0; i < people.size(); ++i) */ /* for (person_id i = 0; i < people_.size(); ++i) */
/* { */ /* { */
/* if (sought == people[i]) */ /* if (sought == people_[i]) */
/* return i; */ /* return i; */
/* } */ /* } */
/* return Nobody; */ /* return Nobody; */
@@ -135,9 +135,9 @@ person_id Tree::findRootAncestor(person_id id) const
person_id Tree::findOldestAncestor(person_id id, Sex sex) const person_id Tree::findOldestAncestor(person_id id, Sex sex) const
{ {
for (const Relation& rel: relations[id]) for (const Relation& rel: relations_[id])
{ {
if (rel.type == Child && people[ rel.id ].sex == sex) if (rel.type == Child && people_[ rel.id ].sex == sex)
return findOldestAncestor(rel.id, sex); return findOldestAncestor(rel.id, sex);
} }
return id; return id;
@@ -148,18 +148,18 @@ person_id Tree::findCommonAncestor(const unsigned first, const unsigned second)
if(first == Nobody || second == Nobody) if(first == Nobody || second == Nobody)
return Nobody; return Nobody;
vector<U8> visited(people.size()); //if a member is visited twice he's a common ancestor vector<U8> visited(people_.size()); //if a member is visited twice he's a common ancestor
commonAncestorRec(first, visited); commonAncestorRec(first, visited);
commonAncestorRec(second, visited); commonAncestorRec(second, visited);
person_id oldest = Nobody; person_id oldest = Nobody;
U16 oldestBday = SHRT_MAX; U16 oldestBday = SHRT_MAX;
for (person_id i = 0; i < people.size(); ++i) for (person_id i = 0; i < people_.size(); ++i)
{ {
if (visited[i] == 2 && people[i].birth.year < oldestBday) if (visited[i] == 2 && people_[i].birth.year < oldestBday)
{ {
/* oldestBday = people[i].birth.year; */ //todo figure it out /* oldestBday = people_[i].birth.year; */ //todo figure it out
/* oldest = i; */ /* oldest = i; */
return i; return i;
} }
@@ -170,9 +170,9 @@ person_id Tree::findCommonAncestor(const unsigned first, const unsigned second)
person_id Tree::findParent(person_id child, Sex parentSex) const person_id Tree::findParent(person_id child, Sex parentSex) const
{ {
person_id parent = Nobody; person_id parent = Nobody;
for(const Relation& rel: relations[child]) for(const Relation& rel: relations_[child])
{ {
if (rel.type == Child && people[rel.id].sex == parentSex) if (rel.type == Child && people_[rel.id].sex == parentSex)
parent = rel.id; parent = rel.id;
} }
return parent; return parent;
@@ -184,7 +184,7 @@ vector<person_id> Tree::findChildren(person_id person) const
return {}; return {};
vector<person_id> children; vector<person_id> children;
for(const Relation& rel: relations[person]) for(const Relation& rel: relations_[person])
{ {
if (rel.type == Parent) if (rel.type == Parent)
children.push_back(rel.id); children.push_back(rel.id);
@@ -206,7 +206,7 @@ vector<person_id> Tree::findChildren(person_id person, person_id exclude) const
person_id Tree::findSpouse(person_id person) const person_id Tree::findSpouse(person_id person) const
{ {
person_id spouse = Nobody; person_id spouse = Nobody;
for(const Relation& rel: relations[person]) for(const Relation& rel: relations_[person])
{ {
if (rel.type == Spouse) if (rel.type == Spouse)
{ {
@@ -220,7 +220,7 @@ person_id Tree::findSpouse(person_id person) const
RelType Tree::findRelation(person_id first, person_id second) const RelType Tree::findRelation(person_id first, person_id second) const
{ {
const auto& curRels = relations[first]; const auto& curRels = relations_[first];
for(const Relation& rel: curRels) for(const Relation& rel: curRels)
{ {
if (rel.id == second) if (rel.id == second)
@@ -231,11 +231,11 @@ RelType Tree::findRelation(person_id first, person_id second) const
void Tree::addPerson(const char* name, Sex sex, unsigned father, unsigned mother, EventTime birth, EventTime death) void Tree::addPerson(const char* name, Sex sex, unsigned father, unsigned mother, EventTime birth, EventTime death)
{ {
people.emplace_back(name, birth, sex, death); people_.emplace_back(name, birth, sex, death);
relations.emplace_back(); /* relations of the new person */ relations_.emplace_back(); /* relations of the new person */
person_id new_person_id = people.size() - 1; person_id new_person_id = people_.size() - 1;
addRelation(father, Parent, new_person_id); addRelation(father, Parent, new_person_id);
addRelation(mother, Parent, new_person_id); addRelation(mother, Parent, new_person_id);
@@ -250,7 +250,7 @@ void Tree::addPerson(const char* name, Sex sex, unsigned father, unsigned mother
bool Tree::addRelation(const unsigned first, const RelType type, const unsigned second, bool update) bool Tree::addRelation(const unsigned first, const RelType type, const unsigned second, bool update)
{ {
if (first == Nobody || first >= people.size() || second == Nobody || second >= people.size() || type == None) if (first == Nobody || first >= people_.size() || second == Nobody || second >= people_.size() || type == None)
return false; return false;
switch (type) switch (type)
@@ -284,17 +284,17 @@ bool Tree::addRelation(const unsigned first, const RelType type, const unsigned
void Tree::addRelOneSide(person_id first, RelType type, person_id second) void Tree::addRelOneSide(person_id first, RelType type, person_id second)
{ {
unsigned i = 0; unsigned i = 0;
for (; i < relations[first].size(); ++i) //Check if they are already relatives for (; i < relations_[first].size(); ++i) //Check if they are already relatives
{ {
if (relations[first][i].id == second) if (relations_[first][i].id == second)
{ {
relations[first][i].type = type; relations_[first][i].type = type;
break; break;
} }
} }
if (i >= relations[first].size()) if (i >= relations_[first].size())
{ {
relations[first].push_back({second, type}); relations_[first].push_back({second, type});
} }
} }
@@ -306,32 +306,32 @@ void Tree::addRelOneSide(person_id first, RelType type, person_id second)
void Tree::removePerson(const person_id id) void Tree::removePerson(const person_id id)
{ {
person_id relId; person_id relId;
for (Relation rel: relations[id]) for (Relation rel: relations_[id])
{ {
relId = rel.id; relId = rel.id;
for (U32 j = 0; j < relations[relId].size(); ++j) for (U32 j = 0; j < relations_[relId].size(); ++j)
{ {
if (relations[relId][j].id == id) if (relations_[relId][j].id == id)
{ {
remove(relations[relId], j); remove(relations_[relId], j);
break; break;
} }
} }
} }
for (unsigned i = 0; i < relations[people.size() - 2].size(); ++i) //Move the last in his place and update IDs for (unsigned i = 0; i < relations_[people_.size() - 2].size(); ++i) //Move the last in his place and update IDs
{ {
relId = relations[people.size() - 1][i].id; relId = relations_[people_.size() - 1][i].id;
for (unsigned j = 0; j < relations[relId].size(); ++j) for (unsigned j = 0; j < relations_[relId].size(); ++j)
{ {
if (relations[relId][j].id == people.size() - 1) if (relations_[relId][j].id == people_.size() - 1)
{ {
relations[relId][j].id = id; relations_[relId][j].id = id;
break; break;
} }
} }
} }
remove(relations, id); remove(relations_, id);
remove(people, id); remove(people_, id);
} }
/* void Tree::removePerson(const char* personName, short year, unsigned char month, unsigned char day) */ /* void Tree::removePerson(const char* personName, short year, unsigned char month, unsigned char day) */
@@ -341,19 +341,19 @@ void Tree::removePerson(const person_id id)
void Tree::removeRelation(const unsigned first, const unsigned second) void Tree::removeRelation(const unsigned first, const unsigned second)
{ {
for (unsigned i = 0; i < relations[first].size(); ++i) for (unsigned i = 0; i < relations_[first].size(); ++i)
{ {
if (relations[first][i].id == second) if (relations_[first][i].id == second)
{ {
remove(relations[first], i); remove(relations_[first], i);
break; break;
} }
} }
for (unsigned i = 0; i < relations[second].size(); ++i) for (unsigned i = 0; i < relations_[second].size(); ++i)
{ {
if (relations[second][i].id == first) if (relations_[second][i].id == first)
{ {
remove(relations[second], i); remove(relations_[second], i);
break; break;
} }
} }
@@ -361,12 +361,9 @@ void Tree::removeRelation(const unsigned first, const unsigned second)
static void displayHelp() static void displayHelp()
{ {
WINDOW* help_tab = newwin(LINES, COLS, 0, 0); AutoWin help_tab( newwin(LINES, COLS, 0, 0) );
waddstr(help_tab, "Enter - focus the currently selected person\n" /* todo */ waddstr(help_tab, VISUALIZATION_HELP_STR);
"Arrow keys - move the camera\n"
"H, J, K, L - move the selection\n"
"I - display info about the selected person\n");
mvwaddstr(help_tab, LINES-1, 0, "Press any key to return."); mvwaddstr(help_tab, LINES-1, 0, "Press any key to return.");
@@ -375,12 +372,11 @@ static void displayHelp()
werase(help_tab); werase(help_tab);
wnoutrefresh(help_tab); wnoutrefresh(help_tab);
delwin(help_tab);
} }
void Tree::display() void Tree::display()
{ {
if(people.size() == 0) if(people_.size() == 0)
return; return;
bool to_draw = true; bool to_draw = true;
@@ -436,7 +432,7 @@ void Tree::display()
selectRight(); selectRight();
break; break;
case DISPLAY_INFO: case DISPLAY_INFO:
people[selected_].displayInfo(); people_[selected_].displayInfo();
break; break;
default: default:
to_draw = false; /* invalid key, don't redraw */ to_draw = false; /* invalid key, don't redraw */
@@ -492,19 +488,19 @@ void Tree::draw() const
void Tree::print() const void Tree::print() const
{ {
for(const Person& member: people) for(const Person& member: people_)
member.displayInfo(); member.displayInfo();
} }
void Tree::printMember(const unsigned id)const void Tree::printMember(const unsigned id)const
{ {
people[id].displayInfo(); people_[id].displayInfo();
} }
void Tree::printOldestAncestors(const unsigned id)const void Tree::printOldestAncestors(const unsigned id)const
{ {
people[findOldestAncestor(id, M)].displayInfo(); people_[findOldestAncestor(id, M)].displayInfo();
people[findOldestAncestor(id, F)].displayInfo(); people_[findOldestAncestor(id, F)].displayInfo();
} }
@@ -512,7 +508,7 @@ void Tree::commonAncestorRec(person_id id, vector<U8> &visited) const
{ {
++visited[id]; ++visited[id];
auto& curRels = relations[id]; auto& curRels = relations_[id];
for (const Relation& rel: curRels) for (const Relation& rel: curRels)
{ {
if (rel.type == Child) if (rel.type == Child)
@@ -520,11 +516,12 @@ void Tree::commonAncestorRec(person_id id, vector<U8> &visited) const
} }
} }
// return the height of the space occupied by the link
static U8 linkToFirstBorn(I16 startY, I16 startX, bool moreSiblings) static U8 linkToFirstBorn(I16 startY, I16 startX, bool moreSiblings)
{ {
if (willBeVisible(startY, startX, 3, 1)) if (willBeVisible(startY, startX, 3, 1))
{ {
WINDOW* pad = newpad(3, 1); AutoWin pad( newpad(3, 1) );
waddch(pad, ACS_VLINE); waddch(pad, ACS_VLINE);
mvwaddch(pad, 1, 0, mvwaddch(pad, 1, 0,
@@ -532,7 +529,6 @@ static U8 linkToFirstBorn(I16 startY, I16 startX, bool moreSiblings)
mvwaddch(pad, 2, 0, ACS_VLINE); mvwaddch(pad, 2, 0, ACS_VLINE);
drawpad(pad, startY, startX); drawpad(pad, startY, startX);
delwin(pad);
} }
return 3; return 3;
} }
@@ -543,7 +539,7 @@ static U8 linkToChild(I16 startY, I16 startX, I16 endX, bool moreSiblings)
const I16 len = endX - startX; const I16 len = endX - startX;
if (willBeVisible(startY, startX, 2, len)) if (willBeVisible(startY, startX, 2, len))
{ {
WINDOW* pad = newpad(2, len); AutoWin pad( newpad(2, len) );
for(U16 i = 0; i < len-1; ++i) for(U16 i = 0; i < len-1; ++i)
waddch(pad, ACS_HLINE); waddch(pad, ACS_HLINE);
@@ -553,7 +549,6 @@ static U8 linkToChild(I16 startY, I16 startX, I16 endX, bool moreSiblings)
mvwaddch(pad, 1, len-1, ACS_VLINE); mvwaddch(pad, 1, len-1, ACS_VLINE);
drawpad(pad, startY, startX); drawpad(pad, startY, startX);
delwin(pad);
} }
return 2; return 2;
} }
@@ -561,13 +556,13 @@ static U8 linkToChild(I16 startY, I16 startX, I16 endX, bool moreSiblings)
/* I16 Tree::drawLine(person_id id, I16 drawY, I16 drawX) const */ /* I16 Tree::drawLine(person_id id, I16 drawY, I16 drawX) const */
/* { */ /* { */
/* people[id].draw(drawY, drawX, true, false, true); */ /* people_[id].draw(drawY, drawX, true, false, true); */
/* vector<person_id> children; */ /* vector<person_id> children; */
/* for(U32 i=0; i<relations[id].size(); ++i) */ /* for(U32 i=0; i<relations_[id].size(); ++i) */
/* { */ /* { */
/* if (relations[id][i].type == RelType::Parent) */ /* if (relations_[id][i].type == RelType::Parent) */
/* children.push_back(relations[id][i].id); */ /* children.push_back(relations_[id][i].id); */
/* } */ /* } */
/* if (!children.empty()) */ /* if (!children.empty()) */
@@ -587,13 +582,13 @@ static U8 linkToChild(I16 startY, I16 startX, I16 endX, bool moreSiblings)
/* return drawX; */ /* return drawX; */
/* } */ /* } */
/* return drawX + people[id].boxWidth() + dist_between_; */ /* return drawX + people_[id].boxWidth() + dist_between_; */
/* } */ /* } */
I16 Tree::drawLineWithWives(const person_id id, I16 drawY, const I16 drawX) const I16 Tree::drawLineWithWives(const person_id id, I16 drawY, const I16 drawX) const
{ {
const Person& person = people[id]; const Person& person = people_[id];
const auto& rels = relations[id]; const auto& rels = relations_[id];
person_id spouse = Nobody; person_id spouse = Nobody;
vector<person_id> children; vector<person_id> children;
@@ -612,7 +607,7 @@ I16 Tree::drawLineWithWives(const person_id id, I16 drawY, const I16 drawX) cons
U16 spouse_w = 0; U16 spouse_w = 0;
if (spouse != Nobody) if (spouse != Nobody)
{ {
U16 spouse_box = people[spouse].draw(drawY, drawX + person_w + spouse_dist_, U16 spouse_box = people_[spouse].draw(drawY, drawX + person_w + spouse_dist_,
spouse == selected_, false, false, false, zoom_==1); spouse == selected_, false, false, false, zoom_==1);
spouse_w = spouse_dist_ + spouse_box; spouse_w = spouse_dist_ + spouse_box;
} }
@@ -658,7 +653,7 @@ void Tree::selectLeft()
void Tree::selectDown() void Tree::selectDown()
{ {
const auto& curRels = relations[selected_]; const auto& curRels = relations_[selected_];
for(const Relation& rel: curRels) for(const Relation& rel: curRels)
{ {
+8 -8
View File
@@ -5,6 +5,10 @@
#include "person.hpp" #include "person.hpp"
using person_id = U32; using person_id = U32;
enum: person_id {
Nobody = UINT32_MAX
};
enum RelType : U8 enum RelType : U8
{ {
None = 0, None = 0,
@@ -24,16 +28,12 @@ struct Relation
RelType type; RelType type;
}; };
enum: person_id {
Nobody = UINT_MAX
};
class Tree class Tree
{ {
public: public:
Tree() = default; Tree() = default;
template <class Str> template <class Str>
explicit Tree(Str&& Name) : treeName(std::forward<Str>(Name)) {} explicit Tree(Str&& Name) : treeName_(std::forward<Str>(Name)) {}
/* Tree(const Tree&) = default; */ /* Tree(const Tree&) = default; */
/* Tree& operator= (const Tree& other); */ /* Tree& operator= (const Tree& other); */
@@ -96,9 +96,9 @@ private:
void selectLeftSibSpouse(person_id); void selectLeftSibSpouse(person_id);
void selectRightSib(person_id); void selectRightSib(person_id);
std::string treeName; std::string treeName_;
std::vector<Person> people; //The data for each member std::vector<Person> people_; //The data for each member
std::vector<std::vector<Relation>> relations; //The relatives of each member std::vector<std::vector<Relation>> relations_; //The relatives of each member
person_id focused_ = 0; /* the tree was draw based on this person */ person_id focused_ = 0; /* the tree was draw based on this person */
person_id selected_ = 0; person_id selected_ = 0;
+25 -1
View File
@@ -6,7 +6,21 @@
#include <sys/mman.h> #include <sys/mman.h>
#include <iostream> #include <iostream>
void init() AutoWin::AutoWin(WINDOW* win)
: w_(win)
{}
AutoWin::~AutoWin()
{
delwin(w_);
}
AutoWin::operator WINDOW*()
{
return w_;
}
void init_ncurses()
{ {
setlocale(LC_ALL, "en_US.UTF-8"); setlocale(LC_ALL, "en_US.UTF-8");
@@ -66,3 +80,13 @@ void drawpad(WINDOW* pad, I16 drawY, I16 drawX)
drawY, drawX, drawY, drawX,
LINES - 1, COLS - 1); LINES - 1, COLS - 1);
} }
I32 min(I32 a, I32 b)
{
return a <= b ? a : b;
}
I32 max(I32 a, I32 b)
{
return a >= b ? a : b;
}
+25 -36
View File
@@ -1,27 +1,23 @@
#pragma once #pragma once
#include <utility>
#include <ncursesw/ncurses.h> #include <ncursesw/ncurses.h>
#include "common/basicTypes.h" #include "common/basicTypes.h"
/* template <class Vec> */ #define VISUALIZATION_HELP_STR "Visualization defaults (can be changed in config.h):\n" \
/* Vec& operator+=(Vec& lhs, Vec&& rhs) // Combine 2 vectors */ "Enter - focus the currently selected person\n" \
/* { */ "Arrow keys - move the camera\n" \
/* lhs.reserve(lhs.size() + rhs.size()); */ "h, j, k, l - move the selection\n" \
"i - display info about the selected person\n"
/* for(auto&& el: rhs) */ class AutoWin // ncurses windows that is freed on destruction
/* lhs.push_back( std::move(el) ); */ {
/* return lhs; */ public:
/* } */ explicit AutoWin(WINDOW*);
~AutoWin();
/* template <class Vec> */ operator WINDOW*();
/* Vec& operator+=(Vec& lhs, const Vec& rhs) // Combine 2 vectors */ private:
/* { */ WINDOW* w_;
/* lhs.reserve(lhs.size() + rhs.size()); */ };
/* for(const auto& el: rhs) */
/* lhs.push_back(el); */
/* return lhs; */
/* } */
using fd_t = int; /* file descriptor */ using fd_t = int; /* file descriptor */
struct MappedFile struct MappedFile
@@ -30,31 +26,24 @@ struct MappedFile
unsigned len; unsigned len;
}; };
void init(); void init_ncurses();
MappedFile mapfile(fd_t); MappedFile mapfile(fd_t);
fd_t openOrDie(const char* path); fd_t openOrDie(const char* path);
template <class Vec>
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 */ /* wheather a pad with the given coordinates will be visible */
bool willBeVisible(I16 drawY, I16 drawX, U16 height, U16 width); bool willBeVisible(I16 drawY, I16 drawX, U16 height, U16 width);
/* like pnoutrefresh but pminrow,col are calculated based on width,height and /* like pnoutrefresh but pminrow,col are calculated based on width,height and
top left coords, which can be negative (outside the screen) */ top left coords, which can be negative (outside the screen) */
void drawpad(WINDOW* pad, I16 drawY, I16 drawX); void drawpad(WINDOW* pad, I16 drawY, I16 drawX);
I32 min(I32 a, I32 b);
I32 max(I32 a, I32 b);
template <class Vec>
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();
}
-4
View File
@@ -1,7 +1,3 @@
--help
help - based on user config
findRelative findRelative
findRelation - extend findRelation - extend