diff --git a/README.md b/README.md
index 74fff483..8c376311 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,7 @@
| № | ФИО | Directory name | #1 | #2 | #3 | #4 | #5 | #6 | #7 | Рейтинг | Амбиции | Реальность |
| --- | ---------------------------------------------------------------- | -------------- | --- | --- | --- | --- | --- | --- | --- | ------- | ------- | ------- |
| 1 | [Кузьмич Вадим](https://github.com/orgs/brstu/people/vkn10) |[ii02211](./trunk/ii02211)|:heavy_check_mark:|:heavy_check_mark:| |:heavy_check_mark:|:heavy_check_mark:| | | | | |
-| 2 | [Любчук Илья](https://github.com/snep1one)|[ii02212](./trunk/ii02212)|:heavy_check_mark:| | | | | | | | 5 | 0 |
+| 2 | [Любчук Илья](https://github.com/snep1one)|[ii02212](./trunk/ii02212)|:heavy_check_mark:|:heavy_check_mark:| | | | | | | 5 | 0 |
| 3 | [Марач Максим](https://github.com/orgs/brstu/people/MaximMarach) | | | | | | | | | | | |
| 4 | [Нестерчук Дмитрий](https://github.com/nesterchuk11) |[ii02214](./trunk/ii02214)| |:heavy_check_mark:| |:heavy_check_mark:|:heavy_check_mark:| | | | 5 | 0 |
| 5 | [Павлюкович Игорь](https://github.com/orgs/brstu/people/Kre1kh) |[ii02215](./trunk/ii02215)| |:heavy_check_mark:| |:heavy_check_mark:|:heavy_check_mark:| | | | 4 | 0 |
diff --git a/trunk/ii02212/task_02/README.md b/trunk/ii02212/task_02/README.md
new file mode 100644
index 00000000..c441a8cf
--- /dev/null
+++ b/trunk/ii02212/task_02/README.md
@@ -0,0 +1,25 @@
+# Лабораторная работа № 2
+## Разработка приложения "Адресная книга" средствами Qt
+
+## Цель работы
+Изучить базовые компоненты средства разработки графического интерфейса среды Qt
+
+## Ход работы
+В ходе работы над лабораторной работой была реализована программа "Адресная Книга", которая позволяла при помощи графического интерфейса пользователя
+добавлять записи, просматривать их, редактировать, сохранять/открывать файлы с записями, а так же экспортировать их в другой формат.
+
+## Графический интерфейс пользователя и результат работы
+
+Добавление в адресную книгу
+![](images/add.png)
+Удаление
+![](images/delete.png)
+Обновление записи
+![](images/update.png)
+Поиск
+![](images/find.png)
+Открытие файла
+![](images/open.png)
+![](images/open2.png)
+Сохранение
+![](images/save.png)
diff --git a/trunk/ii02212/task_02/images/add.png b/trunk/ii02212/task_02/images/add.png
new file mode 100644
index 00000000..154832b2
Binary files /dev/null and b/trunk/ii02212/task_02/images/add.png differ
diff --git a/trunk/ii02212/task_02/images/delete.png b/trunk/ii02212/task_02/images/delete.png
new file mode 100644
index 00000000..3ddff2b3
Binary files /dev/null and b/trunk/ii02212/task_02/images/delete.png differ
diff --git a/trunk/ii02212/task_02/images/find.png b/trunk/ii02212/task_02/images/find.png
new file mode 100644
index 00000000..6f0814f7
Binary files /dev/null and b/trunk/ii02212/task_02/images/find.png differ
diff --git a/trunk/ii02212/task_02/images/open.png b/trunk/ii02212/task_02/images/open.png
new file mode 100644
index 00000000..b479ba36
Binary files /dev/null and b/trunk/ii02212/task_02/images/open.png differ
diff --git a/trunk/ii02212/task_02/images/open2.png b/trunk/ii02212/task_02/images/open2.png
new file mode 100644
index 00000000..1924417e
Binary files /dev/null and b/trunk/ii02212/task_02/images/open2.png differ
diff --git a/trunk/ii02212/task_02/images/save.png b/trunk/ii02212/task_02/images/save.png
new file mode 100644
index 00000000..1ea461f3
Binary files /dev/null and b/trunk/ii02212/task_02/images/save.png differ
diff --git a/trunk/ii02212/task_02/images/update.png b/trunk/ii02212/task_02/images/update.png
new file mode 100644
index 00000000..8abe76b8
Binary files /dev/null and b/trunk/ii02212/task_02/images/update.png differ
diff --git a/trunk/ii02212/task_02/src/CMakeLists.txt b/trunk/ii02212/task_02/src/CMakeLists.txt
new file mode 100644
index 00000000..cd3a1a62
--- /dev/null
+++ b/trunk/ii02212/task_02/src/CMakeLists.txt
@@ -0,0 +1,70 @@
+cmake_minimum_required(VERSION 3.5)
+
+project(Lab2Giis VERSION 0.1 LANGUAGES CXX)
+
+set(CMAKE_AUTOUIC ON)
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
+
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
+find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
+
+set(PROJECT_SOURCES
+ main.cpp
+ mainwindow.cpp
+ mainwindow.h
+ mainwindow.ui
+)
+
+if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
+ qt_add_executable(Lab2Giis
+ MANUAL_FINALIZATION
+ ${PROJECT_SOURCES}
+ )
+# Define target properties for Android with Qt 6 as:
+# set_property(TARGET Lab2Giis APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
+# ${CMAKE_CURRENT_SOURCE_DIR}/android)
+# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
+else()
+ if(ANDROID)
+ add_library(Lab2Giis SHARED
+ ${PROJECT_SOURCES}
+ )
+# Define properties for Android with Qt 5 after find_package() calls as:
+# set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
+ else()
+ add_executable(Lab2Giis
+ ${PROJECT_SOURCES}
+ )
+ endif()
+endif()
+
+target_link_libraries(Lab2Giis PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
+
+# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
+# If you are developing for iOS or macOS you should consider setting an
+# explicit, fixed bundle identifier manually though.
+if(${QT_VERSION} VERSION_LESS 6.1.0)
+ set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.Lab2Giis)
+endif()
+set_target_properties(Lab2Giis PROPERTIES
+ ${BUNDLE_ID_OPTION}
+ MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
+ MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
+ MACOSX_BUNDLE TRUE
+ WIN32_EXECUTABLE TRUE
+)
+
+include(GNUInstallDirs)
+install(TARGETS Lab2Giis
+ BUNDLE DESTINATION .
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+)
+
+if(QT_VERSION_MAJOR EQUAL 6)
+ qt_finalize_executable(Lab2Giis)
+endif()
diff --git a/trunk/ii02212/task_02/src/addressBook.pro b/trunk/ii02212/task_02/src/addressBook.pro
new file mode 100644
index 00000000..3cedc058
--- /dev/null
+++ b/trunk/ii02212/task_02/src/addressBook.pro
@@ -0,0 +1,35 @@
+QT += core gui
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+CONFIG += c++11
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+SOURCES += \
+ addressbook.cpp \
+ finddialog.cpp \
+ main.cpp \
+ mainwindow.cpp
+
+HEADERS += \
+ addressbook.h \
+ finddialog.h \
+ mainwindow.h
+
+FORMS += \
+ mainwindow.ui
+
+# Default rules for deployment.
+qnx: target.path = /tmp/$${TARGET}/bin
+else: unix:!android: target.path = /opt/$${TARGET}/bin
+!isEmpty(target.path): INSTALLS += target
diff --git a/trunk/ii02212/task_02/src/addressBook.pro.user b/trunk/ii02212/task_02/src/addressBook.pro.user
new file mode 100644
index 00000000..0ba7d0d0
--- /dev/null
+++ b/trunk/ii02212/task_02/src/addressBook.pro.user
@@ -0,0 +1,562 @@
+
+
+
+
+
+ EnvironmentId
+ {5e17e7ce-1134-4ed2-9caa-f57208ef9a03}
+
+
+ ProjectExplorer.Project.ActiveTarget
+ 0
+
+
+ ProjectExplorer.Project.EditorSettings
+
+ true
+ false
+ true
+
+ Cpp
+
+ CppGlobal
+
+
+
+ QmlJS
+
+ QmlJSGlobal
+
+
+ 2
+ UTF-8
+ false
+ 4
+ false
+ 80
+ true
+ true
+ 1
+ true
+ false
+ 0
+ true
+ true
+ 0
+ 8
+ true
+ 1
+ true
+ true
+ true
+ false
+
+
+
+ ProjectExplorer.Project.PluginSettings
+
+
+ -fno-delayed-template-parsing
+
+ true
+
+
+
+ ProjectExplorer.Project.Target.0
+
+ Desktop Qt 5.14.2 MinGW 32-bit
+ Desktop Qt 5.14.2 MinGW 32-bit
+ qt.qt5.5142.win32_mingw73_kit
+ 0
+ 0
+ 0
+
+ C:/Users/N/Documents/build-addressBook-Desktop_Qt_5_14_2_MinGW_32_bit-Debug
+
+
+ true
+ QtProjectManager.QMakeBuildStep
+ true
+
+ false
+ false
+ false
+
+
+ true
+ Qt4ProjectManager.MakeStep
+
+ false
+
+
+ false
+
+ 2
+ Сборка
+ Сборка
+ ProjectExplorer.BuildSteps.Build
+
+
+
+ true
+ Qt4ProjectManager.MakeStep
+
+ true
+ clean
+
+ false
+
+ 1
+ Очистка
+ Очистка
+ ProjectExplorer.BuildSteps.Clean
+
+ 2
+ false
+
+ Отладка
+ Qt4ProjectManager.Qt4BuildConfiguration
+ 2
+
+
+ C:/Users/N/Documents/build-addressBook-Desktop_Qt_5_14_2_MinGW_32_bit-Release
+
+
+ true
+ QtProjectManager.QMakeBuildStep
+ false
+
+ false
+ false
+ true
+
+
+ true
+ Qt4ProjectManager.MakeStep
+
+ false
+
+
+ false
+
+ 2
+ Сборка
+ Сборка
+ ProjectExplorer.BuildSteps.Build
+
+
+
+ true
+ Qt4ProjectManager.MakeStep
+
+ true
+ clean
+
+ false
+
+ 1
+ Очистка
+ Очистка
+ ProjectExplorer.BuildSteps.Clean
+
+ 2
+ false
+
+ Выпуск
+ Qt4ProjectManager.Qt4BuildConfiguration
+ 0
+
+
+ C:/Users/N/Documents/build-addressBook-Desktop_Qt_5_14_2_MinGW_32_bit-Profile
+
+
+ true
+ QtProjectManager.QMakeBuildStep
+ true
+
+ false
+ true
+ true
+
+
+ true
+ Qt4ProjectManager.MakeStep
+
+ false
+
+
+ false
+
+ 2
+ Сборка
+ Сборка
+ ProjectExplorer.BuildSteps.Build
+
+
+
+ true
+ Qt4ProjectManager.MakeStep
+
+ true
+ clean
+
+ false
+
+ 1
+ Очистка
+ Очистка
+ ProjectExplorer.BuildSteps.Clean
+
+ 2
+ false
+
+ Профилирование
+ Qt4ProjectManager.Qt4BuildConfiguration
+ 0
+
+ 3
+
+
+ 0
+ Развёртывание
+ Развёртывание
+ ProjectExplorer.BuildSteps.Deploy
+
+ 1
+ ProjectExplorer.DefaultDeployConfiguration
+
+ 1
+
+
+ dwarf
+
+ cpu-cycles
+
+
+ 250
+
+ -e
+ cpu-cycles
+ --call-graph
+ dwarf,4096
+ -F
+ 250
+
+ -F
+ true
+ 4096
+ false
+ false
+ 1000
+
+ true
+
+ false
+ false
+ false
+ false
+ true
+ 0.01
+ 10
+ true
+ kcachegrind
+ 1
+ 25
+
+ 1
+ true
+ false
+ true
+ valgrind
+
+ 0
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+
+ 2
+
+ Qt4ProjectManager.Qt4RunConfiguration:C:/Users/N/Documents/addressBook/addressBook.pro
+ C:/Users/N/Documents/addressBook/addressBook.pro
+
+ false
+
+ false
+ true
+ true
+ false
+ false
+ true
+
+ C:/Users/N/Documents/build-addressBook-Desktop_Qt_5_14_2_MinGW_32_bit-Debug
+
+ 1
+
+
+
+ ProjectExplorer.Project.Target.1
+
+ Desktop Qt 5.14.2 MinGW 64-bit
+ Desktop Qt 5.14.2 MinGW 64-bit
+ qt.qt5.5142.win64_mingw73_kit
+ 0
+ 0
+ 0
+
+ C:/Users/N/Documents/build-addressBook-Desktop_Qt_5_14_2_MinGW_64_bit-Debug
+
+
+ true
+ QtProjectManager.QMakeBuildStep
+ true
+
+ false
+ false
+ false
+
+
+ true
+ Qt4ProjectManager.MakeStep
+
+ false
+
+
+ false
+
+ 2
+ Сборка
+ Сборка
+ ProjectExplorer.BuildSteps.Build
+
+
+
+ true
+ Qt4ProjectManager.MakeStep
+
+ true
+ clean
+
+ false
+
+ 1
+ Очистка
+ Очистка
+ ProjectExplorer.BuildSteps.Clean
+
+ 2
+ false
+
+ Отладка
+ Qt4ProjectManager.Qt4BuildConfiguration
+ 2
+
+
+ C:/Users/N/Documents/build-addressBook-Desktop_Qt_5_14_2_MinGW_64_bit-Release
+
+
+ true
+ QtProjectManager.QMakeBuildStep
+ false
+
+ false
+ false
+ true
+
+
+ true
+ Qt4ProjectManager.MakeStep
+
+ false
+
+
+ false
+
+ 2
+ Сборка
+ Сборка
+ ProjectExplorer.BuildSteps.Build
+
+
+
+ true
+ Qt4ProjectManager.MakeStep
+
+ true
+ clean
+
+ false
+
+ 1
+ Очистка
+ Очистка
+ ProjectExplorer.BuildSteps.Clean
+
+ 2
+ false
+
+ Выпуск
+ Qt4ProjectManager.Qt4BuildConfiguration
+ 0
+
+
+ C:/Users/N/Documents/build-addressBook-Desktop_Qt_5_14_2_MinGW_64_bit-Profile
+
+
+ true
+ QtProjectManager.QMakeBuildStep
+ true
+
+ false
+ true
+ true
+
+
+ true
+ Qt4ProjectManager.MakeStep
+
+ false
+
+
+ false
+
+ 2
+ Сборка
+ Сборка
+ ProjectExplorer.BuildSteps.Build
+
+
+
+ true
+ Qt4ProjectManager.MakeStep
+
+ true
+ clean
+
+ false
+
+ 1
+ Очистка
+ Очистка
+ ProjectExplorer.BuildSteps.Clean
+
+ 2
+ false
+
+ Профилирование
+ Qt4ProjectManager.Qt4BuildConfiguration
+ 0
+
+ 3
+
+
+ 0
+ Развёртывание
+ Развёртывание
+ ProjectExplorer.BuildSteps.Deploy
+
+ 1
+ ProjectExplorer.DefaultDeployConfiguration
+
+ 1
+
+
+ dwarf
+
+ cpu-cycles
+
+
+ 250
+
+ -e
+ cpu-cycles
+ --call-graph
+ dwarf,4096
+ -F
+ 250
+
+ -F
+ true
+ 4096
+ false
+ false
+ 1000
+
+ true
+
+ false
+ false
+ false
+ false
+ true
+ 0.01
+ 10
+ true
+ kcachegrind
+ 1
+ 25
+
+ 1
+ true
+ false
+ true
+ valgrind
+
+ 0
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+
+ 2
+
+
+ ProjectExplorer.CustomExecutableRunConfiguration
+
+
+ false
+
+ false
+ true
+ false
+ false
+ true
+
+
+
+ 1
+
+
+
+ ProjectExplorer.Project.TargetCount
+ 2
+
+
+ ProjectExplorer.Project.Updater.FileVersion
+ 22
+
+
+ Version
+ 22
+
+
diff --git a/trunk/ii02212/task_02/src/addressbook.cpp b/trunk/ii02212/task_02/src/addressbook.cpp
new file mode 100644
index 00000000..f9dbfa8a
--- /dev/null
+++ b/trunk/ii02212/task_02/src/addressbook.cpp
@@ -0,0 +1,407 @@
+#include "addressbook.h"
+
+#include
+#include
+#include
+#include
+#include
+
+AddressBook::AddressBook(QWidget *parent)
+ : QWidget(parent)
+{
+ QLabel nameLabel(tr("Name:"));
+ nameLine = std::make_unique();
+ nameLine->setReadOnly(true);
+
+ QLabel addressLabel(tr("Address:"));
+ addressText = std::make_unique();
+ addressText->setReadOnly(true);
+
+ addButton = std::make_unique(tr("&Add"));
+ addButton->show();
+
+ submitButton = std::make_unique(tr("&Submit"));
+ submitButton->hide();
+
+ cancelButton = std::make_unique(tr("&Cancel"));
+ cancelButton->hide();
+
+ nextButton = std::make_unique(tr("&Next"));
+ nextButton->setEnabled(false);
+
+ previousButton = std::make_unique(tr("&Previous"));
+ previousButton->setEnabled(false);
+
+ editButton = std::make_unique(tr("&Edit"));
+ editButton->setEnabled(false);
+
+ removeButton = std::make_unique(tr("&Remove"));
+ removeButton->setEnabled(false);
+
+ findButton = std::make_unique(tr("&Find"));
+ findButton->setEnabled(false);
+
+ loadButton = std::make_unique(tr("&Load..."));
+ loadButton->setToolTip(tr("Load contacts from a file"));
+
+ saveButton = std::make_unique(tr("&Save..."));
+ saveButton->setToolTip(tr("Save contacts to a file"));
+
+ exportButton = std::make_unique(tr("E&xport"));
+ exportButton->setToolTip(tr("Export as vCard"));
+
+ dialog = std::make_unique();
+
+ connect(addButton.get(), SIGNAL(clicked()), this, SLOT(addContact()));
+ connect(submitButton.get(), SIGNAL(clicked()), this, SLOT(submitContact()));
+ connect(cancelButton.get(), SIGNAL(clicked()), this, SLOT(cancel()));
+ connect(nextButton.get(), SIGNAL(clicked()), this, SLOT(next()));
+ connect(previousButton.get(), SIGNAL(clicked()), this, SLOT(previous()));
+ connect(editButton.get(), SIGNAL(clicked()), this, SLOT(editContact()));
+ connect(removeButton.get(), SIGNAL(clicked()), this, SLOT(removeContact()));
+ connect(findButton.get(), SIGNAL(clicked()), this, SLOT(findContact()));
+ connect(loadButton.get(), SIGNAL(clicked()), this, SLOT(loadFromFile()));
+ connect(saveButton.get(), SIGNAL(clicked()), this, SLOT(saveToFile()));
+ connect(exportButton.get(), SIGNAL(clicked()), this, SLOT(exportAsVCard()));
+
+ auto buttonLayout1 = std::make_unique();
+ buttonLayout1->addWidget(addButton.get(), Qt::AlignTop);
+ buttonLayout1->addWidget(submitButton.get());
+ buttonLayout1->addWidget(cancelButton.get());
+ buttonLayout1->addWidget(findButton.get());
+ buttonLayout1->addWidget(editButton.get());
+ buttonLayout1->addWidget(removeButton.get());
+ buttonLayout1->addWidget(loadButton.get());
+ buttonLayout1->addWidget(saveButton.get());
+ buttonLayout1->addWidget(exportButton.get());
+ buttonLayout1->addStretch();
+
+ auto buttonLayout2 = std::make_unique();
+ buttonLayout2->addWidget(previousButton.get());
+ buttonLayout2->addWidget(nextButton.get());
+
+ auto mainLayout = std::make_unique();
+ mainLayout->addWidget(&nameLabel, 0, 0);
+ mainLayout->addWidget(nameLine.get(), 0, 1);
+ mainLayout->addWidget(&addressLabel, 1, 0, Qt::AlignTop);
+ mainLayout->addWidget(addressText.get(), 1, 1);
+ mainLayout->addLayout(buttonLayout1, 1, 2);
+ mainLayout->addLayout(buttonLayout2, 2, 1);
+
+ setLayout(mainLayout);
+ setWindowTitle(tr("Simple Address Book"));
+}
+
+
+void AddressBook::addContact()
+{
+ oldName = nameLine->text();
+ oldAddress = addressText->toPlainText();
+
+ nameLine->clear();
+ addressText->clear();
+
+ updateInterface(AddingMode);
+}
+
+void AddressBook::submitContact()
+{
+ QString name = nameLine->text();
+ QString address = addressText->toPlainText();
+
+ if (name.isEmpty() || address.isEmpty()) {
+ QMessageBox::information(this, tr("Empty Field"),
+ tr("Please enter a name and address."));
+ return;
+ }
+
+ if (currentMode == AddingMode) {
+
+ if (!contacts.contains(name)) {
+ contacts.insert(name, address);
+ QMessageBox::information(this, tr("Add Successful"),
+ tr("\"%1\" has been added to your address book.").arg(name));
+ } else {
+ QMessageBox::information(this, tr("Add Unsuccessful"),
+ tr("Sorry, \"%1\" is already in your address book.").arg(name));
+ }
+ } else if (currentMode == EditingMode) {
+
+ if (oldName != name) {
+ if (!contacts.contains(name)) {
+ QMessageBox::information(this, tr("Edit Successful"),
+ tr("\"%1\" has been edited in your address book.").arg(oldName));
+ contacts.remove(oldName);
+ contacts.insert(name, address);
+ } else {
+ QMessageBox::information(this, tr("Edit Unsuccessful"),
+ tr("Sorry, \"%1\" is already in your address book.").arg(name));
+ }
+ } else if (oldAddress != address) {
+ QMessageBox::information(this, tr("Edit Successful"),
+ tr("\"%1\" has been edited in your address book.").arg(name));
+ contacts[name] = address;
+ }
+ }
+
+ updateInterface(NavigationMode);
+}
+
+void AddressBook::cancel()
+{
+ int number = contacts.size();
+ nextButton->setEnabled(number > 1);
+ previousButton->setEnabled(number > 1);
+
+ nameLine->setText(oldName);
+ nameLine->setReadOnly(true);
+
+ addressText->setText(oldAddress);
+ addressText->setReadOnly(true);
+
+ addButton->setEnabled(true);
+ submitButton->hide();
+ cancelButton->hide();
+}
+
+void AddressBook::next()
+{
+ QString name = nameLine->text();
+ QMap::iterator i = contacts.find(name);
+
+ if (i != contacts.end())
+ i++;
+
+ if (i == contacts.end())
+ i = contacts.begin();
+
+ nameLine->setText(i.key());
+ addressText->setText(i.value());
+}
+
+void AddressBook::previous()
+{
+ QString name = nameLine->text();
+ QMap::iterator i = contacts.find(name);
+
+ if (i == contacts.end()){
+ nameLine->clear();
+ addressText->clear();
+ return;
+ }
+
+ if (i == contacts.begin())
+ i = contacts.end();
+
+ i--;
+ nameLine->setText(i.key());
+ addressText->setText(i.value());
+}
+
+void AddressBook::editContact()
+{
+ oldName = nameLine->text();
+ oldAddress = addressText->toPlainText();
+
+ updateInterface(EditingMode);
+}
+
+void AddressBook::removeContact()
+{
+ QString name = nameLine->text();
+ QString address = addressText->toPlainText();
+
+ if (contacts.contains(name)) {
+
+ int button = QMessageBox::question(this,
+ tr("Confirm Remove"),
+ tr("Are you sure you want to remove \"%1\"?").arg(name),
+ QMessageBox::Yes | QMessageBox::No);
+
+ if (button == QMessageBox::Yes) {
+
+ previous();
+ contacts.remove(name);
+
+ QMessageBox::information(this, tr("Remove Successful"),
+ tr("\"%1\" has been removed from your address book.").arg(name));
+ }
+ }
+
+ updateInterface(NavigationMode);
+}
+
+void AddressBook::updateInterface(Mode mode)
+{
+ currentMode = mode;
+
+ switch (currentMode) {
+
+ case AddingMode:
+ case EditingMode:
+
+ nameLine->setReadOnly(false);
+ nameLine->setFocus(Qt::OtherFocusReason);
+ addressText->setReadOnly(false);
+
+ addButton->setEnabled(false);
+ editButton->setEnabled(false);
+ removeButton->setEnabled(false);
+
+ nextButton->setEnabled(false);
+ previousButton->setEnabled(false);
+
+ submitButton->show();
+ cancelButton->show();
+ break;
+ case NavigationMode:
+
+ if (contacts.isEmpty()) {
+ nameLine->clear();
+ addressText->clear();
+ }
+
+ nameLine->setReadOnly(true);
+ addressText->setReadOnly(true);
+ addButton->setEnabled(true);
+
+ int number = contacts.size();
+ editButton->setEnabled(number >= 1);
+ removeButton->setEnabled(number >= 1);
+ findButton->setEnabled(number > 1);
+ nextButton->setEnabled(number > 1);
+ previousButton->setEnabled(number >1 );
+
+ submitButton->hide();
+ cancelButton->hide();
+ break;
+ }
+}
+
+void AddressBook::findContact()
+{
+ dialog->show();
+
+ if (dialog->exec() == QDialog::Accepted) {
+ QString contactName = dialog->getFindText();
+
+ if (contacts.contains(contactName)) {
+ nameLine->setText(contactName);
+ addressText->setText(contacts.value(contactName));
+ } else {
+ QMessageBox::information(this, tr("Contact Not Found"),
+ tr("Sorry, \"%1\" is not in your address book.").arg(contactName));
+ return;
+ }
+ }
+
+ updateInterface(NavigationMode);
+}
+
+void AddressBook::saveToFile()
+{
+ if (QString fileName = QFileDialog::getOpenFileName(this,
+ tr("Open Address Book"), "",
+ tr("Address Book (*.abk);;All Files (*)"));fileName.isEmpty())
+{
+ return;
+}
+ else {
+ QFile file(fileName);
+ if (!file.open(QIODevice::WriteOnly)) {
+ QMessageBox::information(this, tr("Unable to open file"),
+ file.errorString());
+ return;
+ }
+ QDataStream out(&file);
+ out.setVersion(QDataStream::Qt_4_5);
+ out << contacts;
+ }
+}
+
+void AddressBook::loadFromFile()
+{
+ QString fileName = QFileDialog::getOpenFileName(this,
+ tr("Open Address Book"), "",
+ tr("Address Book (*.abk);;All Files (*)"));
+ if (fileName.isEmpty())
+ return;
+ else {
+
+ QFile file(fileName);
+
+ if (!file.open(QIODevice::ReadOnly)) {
+ QMessageBox::information(this, tr("Unable to open file"),
+ file.errorString());
+ return;
+ }
+
+ QDataStream in(&file);
+ in.setVersion(QDataStream::Qt_4_5);
+ contacts.empty(); // очищаем существующие контакты
+ in >> contacts;
+ if (contacts.isEmpty()) {
+ QMessageBox::information(this, tr("No contacts in file"),
+ tr("The file you are attempting to open contains no contacts."));
+ } else {
+ auto i = contacts.begin();
+ nameLine->setText(i.key());
+ addressText->setText(i.value());
+ }
+ }
+
+ updateInterface(NavigationMode);
+}
+
+void AddressBook::exportAsVCard()
+{
+ QString name = nameLine->text();
+ QString address = addressText->toPlainText();
+ QString firstName;
+ QString lastName;
+ QStringList nameList;
+
+ int index = name.indexOf(" ");
+
+ if (index != -1) {
+ nameList = name.split(QRegExp("\\s+"), QString::SkipEmptyParts);
+ firstName = nameList.first();
+ lastName = nameList.last();
+ } else {
+ firstName = name;
+ lastName = "";
+ }
+
+ QString fileName = QFileDialog::getSaveFileName(this,
+ tr("Export Contact"), "",
+ tr("vCard Files (*.vcf);;All Files (*)"));
+
+ if (fileName.isEmpty())
+ return;
+
+ QFile file(fileName);
+ if (!file.open(QIODevice::WriteOnly)) {
+ QMessageBox::information(this, tr("Unable to open file"),
+ file.errorString());
+ return;
+ }
+
+ QTextStream out(&file);
+ out << "BEGIN:VCARD" << "\n";
+ out << "VERSION:2.1" << "\n";
+ out << "N:" << lastName << ";" << firstName << "\n";
+
+ if (!nameList.isEmpty())
+ out << "FN:" << nameList.join(" ") << "\n";
+ else
+ out << "FN:" << firstName << "\n";
+ address.replace(";", "\\;", Qt::CaseInsensitive);
+ address.replace("\n", ";", Qt::CaseInsensitive);
+ address.replace(",", " ", Qt::CaseInsensitive);
+
+ out << "ADR;HOME:;" << address << "\n";
+ out << "END:VCARD" << "\n";
+
+ QMessageBox::information(this, tr("Export Successful"),
+ tr("\"%1\" has been exported as a vCard.").arg(name));
+}
diff --git a/trunk/ii02212/task_02/src/addressbook.h b/trunk/ii02212/task_02/src/addressbook.h
new file mode 100644
index 00000000..090a01a2
--- /dev/null
+++ b/trunk/ii02212/task_02/src/addressbook.h
@@ -0,0 +1,54 @@
+#include
+#include
+#include
+#include
+#include "finddialog.h"
+
+class AddressBook : public QWidget
+ {
+ Q_OBJECT
+
+ public:
+ explicit AddressBook(QWidget *parent = nullptr);
+
+ enum class Mode { NavigationMode, AddingMode, EditingMode };
+
+ private:
+ void updateInterface(Mode mode);
+
+ QPushButton *addButton;
+ QPushButton *submitButton;
+ QPushButton *cancelButton;
+ QPushButton *nextButton;
+ QPushButton *previousButton;
+ QLineEdit *nameLine;
+ QTextEdit *addressText;
+ QPushButton *editButton;
+ QPushButton *removeButton;
+ QPushButton *findButton;
+ FindDialog *dialog;
+ QPushButton *loadButton;
+ QPushButton *saveButton;
+ QPushButton *exportButton;
+
+
+
+ QMap contacts;
+ QString oldName;
+ QString oldAddress;
+ Mode currentMode;
+
+public slots:
+ void addContact();
+ void submitContact();
+ void cancel();
+ void next();
+ void previous();
+ void editContact();
+ void removeContact();
+ void findContact();
+ void saveToFile();
+ void loadFromFile();
+ void exportAsVCard();
+
+ };
diff --git a/trunk/ii02212/task_02/src/finddialog.cpp b/trunk/ii02212/task_02/src/finddialog.cpp
new file mode 100644
index 00000000..7a973e14
--- /dev/null
+++ b/trunk/ii02212/task_02/src/finddialog.cpp
@@ -0,0 +1,64 @@
+#include "finddialog.h"
+
+#include
+#include
+#include
+#include
+#include
+
+class FindDialog : public QDialog {
+ Q_OBJECT
+
+public:
+ explicit FindDialog(QWidget *parent = nullptr);
+
+ QString getFindText() const; // Объявление публичного метода для получения текста поиска
+
+private slots:
+ void findClicked(); // Объявление приватного слота для обработки клика по кнопке
+
+private:
+ QString findText = ""; // Приватная переменная-член
+ std::unique_ptr lineEdit;
+ std::unique_ptr findButton;
+};
+
+
+FindDialog::FindDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ QLabel findLabel(tr("Enter the name of a contact:"));
+ lineEdit = std::make_unique();
+ findButton = std::make_unique(tr("&Find"));
+
+
+ auto layout = std::make_unique();
+
+ layout->addWidget(&findLabel);
+ layout->addWidget(lineEdit.get());
+ layout->addWidget(findButton.get());
+ setLayout(layout);
+ setWindowTitle(tr("Find a Contact"));
+
+ connect(findButton.get(), SIGNAL(clicked()), this, SLOT(findClicked()));
+ connect(findButton.get(), SIGNAL(clicked()), this, SLOT(accept()));
+}
+
+void FindDialog::findClicked()
+{
+ QString text = lineEdit->text();
+ if (text.isEmpty()) {
+ QMessageBox::information(this, tr("Empty Field"),
+ tr("Please enter a name."));
+ return;
+ } else {
+ findText = text;
+ lineEdit->clear();
+ hide();
+ }
+}
+
+QString FindDialog::getFindText() const
+ {
+ return findText;
+ }
diff --git a/trunk/ii02212/task_02/src/finddialog.h b/trunk/ii02212/task_02/src/finddialog.h
new file mode 100644
index 00000000..f432c7d3
--- /dev/null
+++ b/trunk/ii02212/task_02/src/finddialog.h
@@ -0,0 +1,21 @@
+#include
+
+class QLineEdit;
+class QPushButton;
+
+class FindDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit FindDialog(QWidget *parent = nullptr);
+ QString getFindText();
+
+public slots:
+ void findClicked();
+
+private:
+ QPushButton *findButton;
+ QLineEdit *lineEdit;
+ QString findText;
+};
diff --git a/trunk/ii02212/task_02/src/main.cpp b/trunk/ii02212/task_02/src/main.cpp
new file mode 100644
index 00000000..c8593816
--- /dev/null
+++ b/trunk/ii02212/task_02/src/main.cpp
@@ -0,0 +1,16 @@
+#include "addressbook.h"
+#include "mainwindow.h"
+
+#include
+
+int main(int argc, char *argv[])
+{
+
+ QApplication app(argc, argv);
+
+ AddressBook addressBook;
+ addressBook.show();
+
+ return app::exec();
+
+}
diff --git a/trunk/ii02212/task_02/src/mainwindow.cpp b/trunk/ii02212/task_02/src/mainwindow.cpp
new file mode 100644
index 00000000..dd073350
--- /dev/null
+++ b/trunk/ii02212/task_02/src/mainwindow.cpp
@@ -0,0 +1,11 @@
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+
+MainWindow::MainWindow(QWidget *parent)
+ : QMainWindow(parent)
+ , ui(new Ui::MainWindow)
+{
+ ui->setupUi(this);
+}
+
+
diff --git a/trunk/ii02212/task_02/src/mainwindow.h b/trunk/ii02212/task_02/src/mainwindow.h
new file mode 100644
index 00000000..b164082b
--- /dev/null
+++ b/trunk/ii02212/task_02/src/mainwindow.h
@@ -0,0 +1,21 @@
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include
+
+QT_BEGIN_NAMESPACE
+namespace Ui { class MainWindow; }
+QT_END_NAMESPACE
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindow(QWidget *parent = nullptr);
+
+
+private:
+ Ui::MainWindow *ui;
+};
+#endif // MAINWINDOW_H
diff --git a/trunk/ii02212/task_02/src/mainwindow.ui b/trunk/ii02212/task_02/src/mainwindow.ui
new file mode 100644
index 00000000..b742055a
--- /dev/null
+++ b/trunk/ii02212/task_02/src/mainwindow.ui
@@ -0,0 +1,22 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 800
+ 600
+
+
+
+ MainWindow
+
+
+
+
+
+
+
+