#include "StudentInfoManager.hpp" #include "Exceptions.hpp" #include "Tools.hpp" #include #include #include #include bool StudentInfoManager::promptForFileName() { bool selectedCommand = false; bool isNewFile = false; infoManagerCommand::promptFileName::cmd cmd; while (true) { // Display title. clearScreen(); std::cout << "\n\n" << setMiddle("Student Info Management", std::min(getConsoleSize().width, 120)) << "\n\n\n" << setMiddle("(O)pen file (N)ew file", std::min(getConsoleSize().width, 120)) << "\n\n\n" << std::flush; // Wait for an command char commandLetter; int backSpaceCount = 0; std::cout << "(Command)" << std::flush; backSpaceCount = 9; cmd = (infoManagerCommand::promptFileName::cmd)0; disableEchoBack(); while (true) { commandLetter = std::cin.get(); backSpace(backSpaceCount); if (commandLetter == 'o') { std::cout << "Open file" << std::flush; backSpaceCount = 9; cmd = infoManagerCommand::promptFileName::openFile; } else if (commandLetter == 'n') { std::cout << "New file" << std::flush; backSpaceCount = 8; cmd = infoManagerCommand::promptFileName::newFile; } else if (commandLetter == 13) { if (cmd != 0) { break; } } else { std::cout << setoutputcolor(ConsoleColorTool::red) << "Unknown file operation" << resetOutputColor << std::flush; backSpaceCount = 22; cmd = (infoManagerCommand::promptFileName::cmd)0; } } enableEchoBack(); // Deal with open file / new file std::string tempFileName; std::filesystem::directory_entry tempFile; std::cout << "File name (end with ): " << std::flush; std::getline(std::cin, tempFileName); if (tempFileName == "") { std::cout << setoutputcolor(ConsoleColorTool::red) << "Invalid file name.\n" << resetOutputColor << std::endl; waitForAnyInput(); continue; } tempFile = std::filesystem::directory_entry( std::filesystem::absolute(tempFileName)); if (cmd == infoManagerCommand::promptFileName::openFile) { if (!tempFile.exists() || !tempFile.is_regular_file()) { std::cout << setoutputcolor(ConsoleColorTool::red) << "File " << std::filesystem::absolute(tempFile.path()) << " does not exist.\n" << resetOutputColor << std::endl; waitForAnyInput(); continue; } this->file = tempFile; break; } else if (cmd == infoManagerCommand::promptFileName::newFile) { if (tempFile.exists() && tempFile.is_regular_file()) { int backSpaceCount = 0; bool overWrite = false; std::cout << "The file " << tempFile.path() << " already exists. Replace? (y / n): " << std::flush; std::cout << "no" << std::flush; backSpaceCount = 2; disableEchoBack(); // commandLetter reused here. while (true) { commandLetter = std::cin.get(); if (commandLetter == 'y') { backSpace(backSpaceCount); std::cout << "yes" << std::flush; backSpaceCount = 3; overWrite = true; } else if (commandLetter == 'n') { backSpace(backSpaceCount); std::cout << "no" << std::flush; backSpaceCount = 2; overWrite = false; } else if (commandLetter == 13) { break; } } enableEchoBack(); if (!overWrite) { continue; } } // If reached here, the file does not exist or the user chose to // overwrite so we can simply create a new file. this->file = tempFile; break; } } if (cmd == infoManagerCommand::promptFileName::openFile) { return true; } else { return false; } } void StudentInfoManager::readFile() { int totalNum; SaveRecord tempReadRecord; char *tempCourseName, *tempStudentName; std::ifstream fileObj(std::filesystem::absolute(this->file.path()), std::ifstream::in | std::ifstream::binary); if (fileObj.rdstate() == std::ios::failbit) { throw(FileReadError("Open file error")); } fileObj.read((char *)&totalNum, sizeof(int)); fileObj.read((char *)&BaseRecord::nextRecordID, sizeof(int)); while (totalNum > 0 && !fileObj.rdstate()) { fileObj.read((char *)&tempReadRecord, sizeof(SaveRecord)); tempCourseName = new char[tempReadRecord.courseNameLength + 1]; // Stored length is the std::string // length. Need an extra byte for \0. tempStudentName = new char[tempReadRecord.studentNameLength + 1]; fileObj.read(tempCourseName, (tempReadRecord.courseNameLength + 1) * sizeof(char)); fileObj.read(tempStudentName, (tempReadRecord.studentNameLength + 1) * sizeof(char)); switch (tempReadRecord.recordType) { case StuRecord::Late: this->recordPtrList.insert( 0, new LateRecord(tempReadRecord.recordID, tempReadRecord.date, std::string(tempCourseName), tempReadRecord.studentNumber, std::string(tempStudentName))); break; case StuRecord::Absent: this->recordPtrList.insert( 0, new AbsentRecord(tempReadRecord.recordID, tempReadRecord.date, std::string(tempCourseName), tempReadRecord.studentNumber, std::string(tempStudentName))); break; case StuRecord::PersonalLeave: this->recordPtrList.insert( 0, new PersonalLeaveRecord(tempReadRecord.recordID, tempReadRecord.date, std::string(tempCourseName), tempReadRecord.studentNumber, std::string(tempStudentName))); break; default: throw(FileReadError("Unkown record type")); } delete[] tempCourseName; delete[] tempStudentName; totalNum--; } fileObj.close(); }; void StudentInfoManager::saveFile() { int totalNum = this->recordPtrList.length(); SaveRecord tempSaveRecord; std::ofstream fileObj(std::filesystem::absolute(this->file.path()), std::ofstream::out | std::ofstream::binary | std::ofstream::trunc); if (fileObj.rdstate() == std::ios::failbit) { throw(FileWriteError("Cannot write to file")); } fileObj.write((char *)&totalNum, sizeof(int)); fileObj.write((char *)&BaseRecord::nextRecordID, sizeof(int)); Iterator iter = this->recordPtrList.iterate(); while (iter) { BaseRecord *current = iter.next(); tempSaveRecord = (SaveRecord)(*current); fileObj.write((char *)&tempSaveRecord, sizeof(tempSaveRecord)); fileObj.write(current->getCourseName().c_str(), current->getCourseName().length() + 1); fileObj.write(current->getStudentName().c_str(), current->getStudentName().length() + 1); } fileObj.close(); } void StudentInfoManager::closeFile() { if (this->hasChangePendingSave) { char commandLetter; int backSpaceCount = 0; infoManagerCommand::promptSaveBeforeClose::cmd cmd; std::cout << "There are changes pending to be written to the disk. " "Save before quitting? (y / n): " << std::flush; std::cout << "yes" << std::flush; backSpaceCount = 3; cmd = infoManagerCommand::promptSaveBeforeClose::save; disableEchoBack(); while (true) { commandLetter = std::cin.get(); if (commandLetter == 'y') { backSpace(backSpaceCount); std::cout << "yes" << std::flush; backSpaceCount = 3; cmd = infoManagerCommand::promptSaveBeforeClose::save; } else if (commandLetter == 'n') { backSpace(backSpaceCount); std::cout << "no" << std::flush; backSpaceCount = 2; cmd = infoManagerCommand::promptSaveBeforeClose::noSave; } else if (commandLetter == 13) { break; } } enableEchoBack(); std::cout << std::endl; if (cmd == infoManagerCommand::promptSaveBeforeClose::save) { this->saveFile(); } this->hasChangePendingSave = false; } Iterator iter = this->recordPtrList.iterate(); while (iter) { delete iter.next(); } this->recordPtrList.clear(); this->displayer.reapplyFilter(); } bool StudentInfoManager::cmdNew() { char commandLetter; int backSpaceCount = 0; infoManagerCommand::promptNewRecord::cmd cmd; std::cout << "(Record Type)" << std::flush; backSpaceCount = 13; cmd = (infoManagerCommand::promptNewRecord::cmd)0; disableEchoBack(); while (true) { commandLetter = std::cin.get(); backSpace(backSpaceCount); if (commandLetter == 'l') { std::cout << "Late" << std::flush; backSpaceCount = 4; cmd = infoManagerCommand::promptNewRecord::lateRecord; } else if (commandLetter == 'a') { std::cout << "Absent" << std::flush; backSpaceCount = 6; cmd = infoManagerCommand::promptNewRecord::absentRecord; } else if (commandLetter == 'p') { std::cout << "Personal" << std::flush; backSpaceCount = 8; cmd = infoManagerCommand::promptNewRecord::PersonalLeaveRecord; } else if (commandLetter == 13) { if (cmd != 0) { break; } } else if (commandLetter == 27) { // 27 is the ascii number for 'esc'. enableEchoBack(); return false; } else { std::cout << setoutputcolor(ConsoleColorTool::red) << "Unknown" << resetOutputColor << std::flush; backSpaceCount = 7; cmd = (infoManagerCommand::promptNewRecord::cmd)0; } } enableEchoBack(); bool useTodayDate = true; time_t newDateTime = 0; std::string courseName; int studentID; std::string studentName; std::cout << "Use current time as the record's date? (y / n): "; std::cout << "yes" << std::flush; backSpaceCount = 3; disableEchoBack(); while (true) { commandLetter = std::cin.get(); if (commandLetter == 'n') { backSpace(backSpaceCount); std::cout << "no" << std::flush; backSpaceCount = 2; useTodayDate = false; } else if (commandLetter == 'y') { backSpace(backSpaceCount); std::cout << "yes" << std::flush; backSpaceCount = 3; useTodayDate = true; } else if (commandLetter == 13) { break; } } enableEchoBack(); std::cout << std::endl; if (useTodayDate) { time_t curTime; time(&curTime); tm curDate; #if defined __APPLE__ || defined __linux__ curDate = *(localtime(&curTime)); #endif #if defined _WIN64 || defined _WIN32 localtime_s(&curDate, &curTime); #endif tm newDate; newDate.tm_year = curDate.tm_year; newDate.tm_mon = curDate.tm_mon; newDate.tm_mday = curDate.tm_mday; newDate.tm_hour = 0; newDate.tm_min = 0; newDate.tm_sec = 0; newDate.tm_isdst = 0; newDateTime = mktime(&newDate); } else { int tempInput; tm newDate; std::cout << setoutputcolor(ConsoleColorTool::blue) << "Year: " << resetOutputColor << std::flush; // std::cin >> tempInput; // std::cin.ignore(); tempInput = safeInputNum("Please input a positive integer.\n", [](const int &num) { return num > 0; }); newDate.tm_year = tempInput - 1900; std::cout << setoutputcolor(ConsoleColorTool::blue) << "Month: " << resetOutputColor << std::flush; // std::cin >> tempInput; // std::cin.ignore(); tempInput = safeInputNum("Please input a positive integer.\n", [](const int &num) { return num > 0; }); newDate.tm_mon = tempInput - 1; std::cout << setoutputcolor(ConsoleColorTool::blue) << "Day: " << resetOutputColor << std::flush; // std::cin >> tempInput; // std::cin.ignore(); tempInput = safeInputNum("Please input a positive integer.\n", [](const int &num) { return num > 0; }); newDate.tm_mday = tempInput; newDate.tm_hour = 0; newDate.tm_min = 0; newDate.tm_sec = 0; newDate.tm_isdst = 0; newDateTime = mktime(&newDate); } std::cout << setoutputcolor(ConsoleColorTool::blue) << "Course name: " << resetOutputColor << std::flush; std::getline(std::cin, courseName); std::cout << setoutputcolor(ConsoleColorTool::blue) << "Student ID: " << resetOutputColor << std::flush; // std::cin >> studentID; // std::cin.ignore(); studentID = safeInputNum("Please input a positive integer.\n", [](const int &num) { return num > 0; }); std::cout << setoutputcolor(ConsoleColorTool::blue) << "Student Name: " << resetOutputColor << std::flush; std::getline(std::cin, studentName); switch (cmd) { case infoManagerCommand::promptNewRecord::lateRecord: this->recordPtrList.insert( 0, new LateRecord(newDateTime, courseName, studentID, studentName)); break; case infoManagerCommand::promptNewRecord::absentRecord: this->recordPtrList.insert(0, new AbsentRecord(newDateTime, courseName, studentID, studentName)); break; case infoManagerCommand::promptNewRecord::PersonalLeaveRecord: this->recordPtrList.insert( 0, new PersonalLeaveRecord(newDateTime, courseName, studentID, studentName)); break; default: { ; } } return true; } bool StudentInfoManager::cmdRemove() { int recordIDToRemove; std::cout << setoutputcolor(ConsoleColorTool::blue) << "Record ID of which to be removed: " << resetOutputColor << std::endl; // std::cin >> recordIDToRemove; // std::cin.ignore(); recordIDToRemove = safeInputNum("Please input a positive integer.\n", [](const int &num) { return num > 0; }); try { this->recordPtrList.remove([=](BaseRecord *const &recordPtr) -> bool { return recordPtr->getRecordID() == recordIDToRemove; }); } catch (IndexError) { std::cout << setoutputcolor(ConsoleColorTool::red) << "The record with record ID " << recordIDToRemove << " does not exist." << resetOutputColor << std::endl; waitForAnyInput(); return false; } return true; } bool StudentInfoManager::cmdModify() { int recordIDToModify; BaseRecord *toChangeRecordPtr; std::cout << setoutputcolor(ConsoleColorTool::blue) << "Record ID of which to be modified: " << resetOutputColor << std::endl; // std::cin >> recordIDToModify; // std::cin.ignore(); recordIDToModify = safeInputNum("Please input a positive integer.\n", [](const int &num) { return num > 0; }); try { toChangeRecordPtr = this->recordPtrList.search( [=](BaseRecord *const &recordPtr) -> bool { return recordPtr->getRecordID() == recordIDToModify; }); } catch (IndexError) { std::cout << setoutputcolor(ConsoleColorTool::red) << "The record with record ID " << recordIDToModify << " does not exist." << resetOutputColor << std::endl; waitForAnyInput(); return false; } char commandLetter; int backSpaceCount = 0; infoManagerCommand::promptNewInfo::cmd cmd; std::cout << "(Property to be changed)" << std::flush; backSpaceCount = 24; cmd = (infoManagerCommand::promptNewInfo::cmd)0; disableEchoBack(); while (true) { commandLetter = std::cin.get(); backSpace(backSpaceCount); if (commandLetter == 'd') { std::cout << "Date" << std::flush; backSpaceCount = 4; cmd = infoManagerCommand::promptNewInfo::date; } else if (commandLetter == 'c') { std::cout << "Course name" << std::flush; backSpaceCount = 11; cmd = infoManagerCommand::promptNewInfo::courseName; } else if (commandLetter == 's') { std::cout << "Student Info" << std::flush; backSpaceCount = 12; cmd = infoManagerCommand::promptNewInfo::studentInfo; } else if (commandLetter == 13) { if (cmd != 0) { break; } } else { std::cout << setoutputcolor(ConsoleColorTool::red) << "Unknown" << resetOutputColor << std::flush; backSpaceCount = 7; cmd = (infoManagerCommand::promptNewInfo::cmd)0; } } enableEchoBack(); if (cmd == infoManagerCommand::promptNewInfo::date) { toChangeRecordPtr->promptForNewDate(); } else if (cmd == infoManagerCommand::promptNewInfo::courseName) { toChangeRecordPtr->promptForNewCourseName(); } else if (cmd == infoManagerCommand::promptNewInfo::studentInfo) { toChangeRecordPtr->promptForNewStudentInfo(); } return true; } bool StudentInfoManager::cmdSetFilter() { char commandLetter; int backSpaceCount = 0; infoManagerCommand::filterSettings::cmd cmd; std::cout << "(Record property)" << std::flush; backSpaceCount = 17; cmd = (infoManagerCommand::filterSettings::cmd)0; disableEchoBack(); while (true) { commandLetter = std::cin.get(); backSpace(backSpaceCount); if (commandLetter == 'i') { std::cout << "Record ID" << std::flush; backSpaceCount = 9; cmd = infoManagerCommand::filterSettings::recordID; } else if (commandLetter == 'f') { std::cout << "From date" << std::flush; backSpaceCount = 9; cmd = infoManagerCommand::filterSettings::fromDate; } else if (commandLetter == 'o') { std::cout << "To date" << std::flush; backSpaceCount = 7; cmd = infoManagerCommand::filterSettings::toDate; } else if (commandLetter == 'c') { std::cout << "Course name" << std::flush; backSpaceCount = 11; cmd = infoManagerCommand::filterSettings::courseName; } else if (commandLetter == 't') { std::cout << "Student ID" << std::flush; backSpaceCount = 10; cmd = infoManagerCommand::filterSettings::studentID; } else if (commandLetter == 'n') { std::cout << "Student name" << std::flush; backSpaceCount = 12; cmd = infoManagerCommand::filterSettings::studentName; } else if (commandLetter == 'r') { std::cout << "Record Type" << std::flush; backSpaceCount = 11; cmd = infoManagerCommand::filterSettings::recordType; } else if (commandLetter == 13) { if (cmd != 0) { break; } } else if (commandLetter == 27) { enableEchoBack(); return false; } else { std::cout << setoutputcolor(ConsoleColorTool::red) << "Unknown" << resetOutputColor << std::flush; backSpaceCount = 7; cmd = (infoManagerCommand::filterSettings::cmd)0; } } enableEchoBack(); switch (cmd) { case infoManagerCommand::filterSettings::recordID: clearScreen(); this->displayer.promptForRecordID(); waitForAnyInput(); break; case infoManagerCommand::filterSettings::fromDate: this->displayer.promptForFromDate(); break; case infoManagerCommand::filterSettings::toDate: this->displayer.promptForToDate(); break; case infoManagerCommand::filterSettings::courseName: this->displayer.promptForCourseName(); break; case infoManagerCommand::filterSettings::studentID: this->displayer.promptForSearchStuID(); break; case infoManagerCommand::filterSettings::studentName: this->displayer.promptForSearchStuName(); break; case infoManagerCommand::filterSettings::recordType: this->displayer.promptForRecordType(); break; default: return false; } return true; } bool StudentInfoManager::cmdSetSortby() { char commandLetter; int backSpaceCount = 0; infoManagerCommand::sortbySettings::cmd cmd; std::cout << "(Record property)" << std::flush; backSpaceCount = 17; cmd = (infoManagerCommand::sortbySettings::cmd)0; disableEchoBack(); while (true) { commandLetter = std::cin.get(); backSpace(backSpaceCount); if (commandLetter == 'i') { std::cout << "Record ID" << std::flush; backSpaceCount = 9; cmd = infoManagerCommand::sortbySettings::recordID; } else if (commandLetter == 'd') { std::cout << "Date" << std::flush; backSpaceCount = 4; cmd = infoManagerCommand::sortbySettings::date; } else if (commandLetter == 'c') { std::cout << "Course name" << std::flush; backSpaceCount = 11; cmd = infoManagerCommand::sortbySettings::courseName; } else if (commandLetter == 't') { std::cout << "Student ID" << std::flush; backSpaceCount = 10; cmd = infoManagerCommand::sortbySettings::studentID; } else if (commandLetter == 'n') { std::cout << "Student name" << std::flush; backSpaceCount = 12; cmd = infoManagerCommand::sortbySettings::studentName; } else if (commandLetter == 'r') { std::cout << "Record Type" << std::flush; backSpaceCount = 11; cmd = infoManagerCommand::sortbySettings::recordType; } else if (commandLetter == 13) { if (cmd != 0) { break; } } else if (commandLetter == 27) { enableEchoBack(); return false; } else { std::cout << setoutputcolor(ConsoleColorTool::red) << "Unknown" << resetOutputColor << std::flush; backSpaceCount = 7; cmd = (infoManagerCommand::sortbySettings::cmd)0; } } enableEchoBack(); switch (cmd) { case infoManagerCommand::sortbySettings::recordID: this->displayer.setSortBy(SortBy::RecordID); break; case infoManagerCommand::sortbySettings::date: this->displayer.setSortBy(SortBy::RecordDate); break; case infoManagerCommand::sortbySettings::courseName: this->displayer.setSortBy(SortBy::RecordCourseName); break; case infoManagerCommand::sortbySettings::studentID: this->displayer.setSortBy(SortBy::RecordStudentID); break; case infoManagerCommand::sortbySettings::studentName: this->displayer.setSortBy(SortBy::RecordStudentName); break; case infoManagerCommand::sortbySettings::recordType: this->displayer.setSortBy(SortBy::RecordType); break; default: return false; } return true; } void StudentInfoManager::displayHelp() { clearScreen(); std::cout << "Every function has a letter binding. To use that function, " "simply type the corresponding letter and press . The " "available functions are: (their binding key are embraced by " "a parenthesis).\n"; std::cout << setoutputcolor(ConsoleColorTool::green); std::cout << "(N)ew record\n"; std::cout << "(R)emove record\n"; std::cout << "(M)odify record\n"; std::cout << "(S)et filter\n"; std::cout << resetOutputColor; std::cout << "├─ Record (I)D\n"; std::cout << "├─ (F)rom date\n"; std::cout << "├─ T(o) date\n"; std::cout << "├─ (C)ourse name\n"; std::cout << "├─ Studen(t) ID\n"; std::cout << "├─ Student (N)ame\n"; std::cout << "└─ (R)ecord type\n"; std::cout << setoutputcolor(ConsoleColorTool::green); std::cout << "(U)nset filter\n"; std::cout << "Set sort (b)y\n"; std::cout << resetOutputColor; std::cout << "├─ Record (I)D\n"; std::cout << "├─ (D)ate\n"; std::cout << "├─ (C)ourse name\n"; std::cout << "├─ Studen(t) ID\n"; std::cout << "├─ Student (N)ame\n"; std::cout << "└─ (R)ecord type\n"; std::cout << setoutputcolor(ConsoleColorTool::green); std::cout << "Re(v)erse sort order\n"; std::cout << "Next Page (j)\n"; std::cout << "Previous Page (k)\n"; std::cout << "Show (h)elp\n"; std::cout << "(W)rite to disk\n"; std::cout << "(C)lose file\n"; std::cout << "(Q)uit" << resetOutputColor << std::endl; waitForAnyInput(); } void StudentInfoManager::mainloop() { bool run = true; char commandLetter; int backSpaceCount = 0; infoManagerCommand::home::cmd cmd; while (run) { // Display the info clearScreen(); this->displayer.display(); std::cout << "(Command)" << std::flush; backSpaceCount = 9; cmd = (infoManagerCommand::home::cmd)0; disableEchoBack(); while (true) { commandLetter = std::cin.get(); backSpace(backSpaceCount); if (commandLetter == 'n') { std::cout << "New record" << std::flush; backSpaceCount = 10; cmd = infoManagerCommand::home::newRecord; } else if (commandLetter == 'r') { std::cout << "Remove record" << std::flush; backSpaceCount = 13; cmd = infoManagerCommand::home::removeRecord; } else if (commandLetter == 'm') { std::cout << "Modify record" << std::flush; backSpaceCount = 13; cmd = infoManagerCommand::home::modifyRecord; } else if (commandLetter == 's') { std::cout << "Set filter" << std::flush; backSpaceCount = 10; cmd = infoManagerCommand::home::setFilter; } else if (commandLetter == 'u') { std::cout << "Unset filter" << std::flush; backSpaceCount = 12; cmd = infoManagerCommand::home::unsetFilter; } else if (commandLetter == 'b') { std::cout << "Set sort by" << std::flush; backSpaceCount = 11; cmd = infoManagerCommand::home::setSortBy; } else if (commandLetter == 'v') { std::cout << "Reverse sort order" << std::flush; backSpaceCount = 18; cmd = infoManagerCommand::home::flipSortOrder; } else if (commandLetter == 'j') { // std::cout << "Next Page" << std::flush; // backSpaceCount = 9; // cmd = infoManagerCommand::home::nextPage; if (this->displayer.hasNext()) { this->displayer.next(); break; } else { std::cout << setoutputcolor(ConsoleColorTool::red) << "No next page" << resetOutputColor; backSpaceCount = 12; } } else if (commandLetter == 'k') { // std::cout << "Previous Page" << std::flush; // backSpaceCount = 13; // cmd = infoManagerCommand::home::prevPage; if (this->displayer.hasPrev()) { this->displayer.prev(); break; } else { std::cout << setoutputcolor(ConsoleColorTool::red) << "No previous page" << resetOutputColor; backSpaceCount = 16; } } else if (commandLetter == 'h') { std::cout << "Show help" << std::flush; backSpaceCount = 9; cmd = infoManagerCommand::home::help; } else if (commandLetter == 'w') { std::cout << "Write to disk" << std::flush; backSpaceCount = 13; cmd = infoManagerCommand::home::saveFile; } else if (commandLetter == 'c') { std::cout << "Close file" << std::flush; backSpaceCount = 10; cmd = infoManagerCommand::home::closeFile; } else if (commandLetter == 'q') { std::cout << "Quit" << std::flush; backSpaceCount = 4; cmd = infoManagerCommand::home::quit; } else if (commandLetter == 13) { if (cmd != 0) { break; } } else if (commandLetter == 27) { std::cout << "(Command)" << std::flush; backSpaceCount = 9; cmd = (infoManagerCommand::home::cmd)0; } else { std::cout << setoutputcolor(ConsoleColorTool::red) << "Unknown (type h + for help)" << resetOutputColor << std::flush; backSpaceCount = 35; cmd = (infoManagerCommand::home::cmd)0; } } enableEchoBack(); if (cmd == infoManagerCommand::home::newRecord) { if (this->cmdNew()) { this->displayer.reapplyFilter(); this->hasChangePendingSave = true; } } else if (cmd == infoManagerCommand::home::removeRecord) { if (this->cmdRemove()) { this->displayer.reapplyFilter(); this->hasChangePendingSave = true; }; } else if (cmd == infoManagerCommand::home::modifyRecord) { if (this->cmdModify()) { this->displayer.reapplyFilter(); this->hasChangePendingSave = true; } } else if (cmd == infoManagerCommand::home::setFilter) { this->cmdSetFilter(); } else if (cmd == infoManagerCommand::home::unsetFilter) { this->displayer.resetSearch(); } else if (cmd == infoManagerCommand::home::setSortBy) { this->cmdSetSortby(); } else if (cmd == infoManagerCommand::home::flipSortOrder) { this->displayer.flipSortOrder(); } else if (cmd == infoManagerCommand::home::help) { this->displayHelp(); } else if (cmd == infoManagerCommand::home::saveFile) { this->saveFile(); this->hasChangePendingSave = false; } else if (cmd == infoManagerCommand::home::closeFile) { this->closeFile(); if (this->promptForFileName()) { this->readFile(); } this->displayer.reapplyFilter(); } else if (cmd == infoManagerCommand::home::quit) { this->closeFile(); run = false; } } } StudentInfoManager::StudentInfoManager() : displayer(this->recordPtrList) { BaseRecord::nextRecordID = 1; if (this->promptForFileName()) { this->hasChangePendingSave = false; // Actually there's no need to set BaseRecord::nextRecordID as it will // be read from file this->readFile(); this->displayer.reapplyFilter(); } else { this->hasChangePendingSave = true; } } StudentInfoManager::StudentInfoManager(const std::string _fileName) : file(_fileName), displayer(this->recordPtrList) { BaseRecord::nextRecordID = 1; if (this->file.exists() && this->file.is_regular_file()) { this->hasChangePendingSave = false; this->readFile(); this->displayer.reapplyFilter(); } // if the file user specified does not exist, then we will create new file, // so no read needed. else { this->hasChangePendingSave = true; } } StudentInfoManager::~StudentInfoManager() { Iterator iter = this->recordPtrList.iterate(); while (iter) { delete iter.next(); } }