Witam, piszę aplikacje do zarządzania kontaktami. Do tworzenia aplikacji będę używał biblioteki pdcurses.
Mam pewien dylemat na temat tego jak powinienem przechowywać moje dane o menu, które później będę generował.
Każde menu będzie miało swoją nazwę, opis oraz ilość opcji do wyboru (ilość submenu). Możliwe, że jeszcze będę przechowywał jakiś wskaźnik
do funkcji, tak aby po kliknięciu w konkretne menu program wiedział jaką funkcję wykonać (jeszcze nad tym zbytnio się nie zastanawiałem jak to wykonać, a ten wskaźnik mi przyszedł póki co do głowy).
Ale przejdźmy do rzeczy, wymyśliłem póki co takie rozwiązanie:
std::vector<std::tuple <std::string, std::string, std::vectorstd::string>> menus;
Jest to wektor, który przechowuje std::tuple - każde std::tuple to będzie jedno menu. Menu będzie złożone z nazwy, opisu i ilości opcji.
Poniżej przedstawiam sposób użycia (w ramach testów i przejrzystości nie korzystam tutaj z biblioteki pdcurses, a dane po prostu wyświetlam w konsoli za pomocą std::cout):
int main()
{
std::vector<std::tuple <std::string, std::string, std::vector<std::string>>> menus;
std::vector <std::string> booksOptions = { "przegladaj", "dodaj" };
menus.push_back(std::make_tuple("Ksiazki", "Wybierz jedna z opcji", booksOptions));
for (const auto& menu : menus) {
std::cout << "- Nazwa: " << std::get<0>(menu) << std::endl;
std::cout << "- Opis: " << std::get<1>(menu) << std::endl;
std::cout << "- ilosc elementow:" <<std::endl;
for (const auto& option : std::get<2>(menu))
{
std::cout << '\t' << option << std::endl;
}
}
system("pause");
return 0;
}
I tu nasuwa się moje pytanie, czy takie rozwiązanie jest wydajne? Z początku myślałem żeby zrobić osobną klasę - Menu, która byłaby odpowiedzialna za to. Jednak nie potrzebuje tak właściwie robić (raczej) żadnych innych operacji na tych menu oprócz przechowywania danych.
Z rysowaniem menu nie powinno być komplikacji, gdyż mogę wywoływać funkcje w stylu drawMenu(std::tuple <std::string, std::string, std::vectorstd::string>), która przyjmuje konkretne menu jako parametr, oraz odpowiednio je rysuje. Każde menu i submenu będzie podobne, wiec wystarczy jedna funkcja. Jedynym problemem tego rozwiązania będzie rysowanie tych menu w konkretnych obszarach konsoli - będe korzystał z róznych okienek WINDOW z biblioteki pdcurses. Jednak nie jest to teraz zbytnio ważne, gdyż rozpisanie mojego konceptu tutaj zajęło by trochę, a wątpie, że ktoś chciałby czytać te wypociny.
Problemem nie będzie również aby opcja z wektora "menus" była odpowiedzialna za wywołanie konkretnej funkcji, typu:
"addContactBook()", jakoś sobie z tym poradzę.
Struktura mojego programu będzie następująca:
klasa App - jest odpowiedzialna za rysowanie menu, okienek - czyli wszelaka interakcja z użytkownikiem.
klasa Contact - przechowuje informacje o pojedynczym kontakcie, oraz odpowiednie gettery i settery do ustawień tych zmiennych.
klasa ContactBook - jest odpowiedzialna za tworzenie, usuwanie książek kontaktowych, przechowywanie informacji o książkach, w polu tej klasy jest wektor obiektów Contact, a co za tym idzie w klasie tej będzie możliwość przeszukiwania kontaktów, sortowania ich, itp.
Moim kolejnym zamysłem jest zrobić wyświetlanie konkretnych kontaktów w formie menu (przy użyciu pdcurses) po którym będzie można się poruszać za pomocą strzałek i po kliknięciu w dany kontakt - dodać możliwość jego edycji. A więc myślę, że potrzebuje bardziej zaawansowanego typu danych.
z początku opracowałem funkcje w klasie ContactBook zwracają wektor stringów:
std::vector<std::string> ContactBook::getContacts()
{
std::vector<std::string> vstr = {};
for (auto& contact : this->contacts)
{
// tworzenie pelnego stringa, korzystając, że ContactBook zawiera wektor obiektów Contact
std::string str = std::to_string(contact.getId()) + contact.getName() + contact.getLastName() + std::to_string(contact.getPhoneNumber()) + contact.getEmail();
vstr.push_back(str);
}
return vstr;
}
Taki zwrócony wektor stringów już mogę dodać do opcji w menu w std::tuple, a następnie je narysować. Jednak pojawia się problem, gdy chce przechwycić kliknięty kontakt w menu, tak aby wywoływał funkcje, załóżmy "editContact()" dla konkretnego obiektu. Nie mam pojęcia jak to połączyć ze sobą. W klasie App znajdowałby się wektor obiektów ContactBook, w każdym ContactBook jest wektor obiektów Contact. W klasie App byłaby metoda drawContactMenu(), która musiałaby wyrysować wszystkie kontakty. I jak nie ma problemu ze zwróceniem kontaktów z ContactBook i wyrysowania ich, tak kliknięcie w opcje w menu musiałoby mieć jakieś odniesienie do obiektu ContactBook.
Także liczę na waszą pomoc :) cenna będzie każda wskazówka jak to poukładać. Nie wiem czy dobrze rozpisałem o co mi chodzi w drugim problemie z tym menu kontaktów, najwyżej bardziej wyjaśnie o co chodzi i pokaże jakiś kod. Jednak na razie zatrzymałem się na obmyślaniu struktury projektu i głowie się nad tym kilka dni szukając jakichś rozwiązań, a kodu mam niezbyt wiele :D