diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..23a669a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,107 @@
+.build/
+_other/
+_distrib*/
+
+# Tmp files
+*~
+Thumbs.db*
+
+# C++ objects and libs
+*.slo
+*.lo
+*.o
+*.a
+*.la
+*.lai
+*.so
+*.so.*
+*.dll
+*.dylib
+*.ko
+*.obj
+*.elf
+*.lib
+
+# Qt-es
+object_script.*.Release
+object_script.*.Debug
+*_plugin_import.cpp
+/.qmake.cache
+/.qmake.stash
+*.pro.user
+*.pro.user.*
+*.qbs.user
+*.qbs.user.*
+*.moc
+moc_*.cpp
+moc_*.h
+qrc_*.cpp
+ui_*.h
+*.qmlc
+*.jsc
+Makefile*
+*build-*
+*.qm
+*.prl
+
+# Qt unit tests
+target_wrapper.*
+
+# QtCreator
+*.autosave
+
+# QtCreator Qml
+*.qmlproject.user
+*.qmlproject.user.*
+
+# QtCreator CMake
+CMakeLists.txt.user*
+
+# QtCreator 4.8< compilation database
+compile_commands.json
+
+# QtCreator local machine specific files for imported projects
+*creator.user*
+
+*_qmlcache.qrc
+
+# ---> C
+# Prerequisites
+*.d
+
+# Linker output
+*.ilk
+*.map
+*.exp
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+# Debug files
+*.dSYM/
+*.su
+*.idb
+*.pdb
+
+# Kernel Module Compile Results
+*.mod*
+*.cmd
+.tmp_versions/
+modules.order
+Module.symvers
+Mkfile.old
+dkms.conf
+
+# Fortran module files
+*.mod
+*.smod
+
diff --git a/ImplicitShared.md b/ImplicitShared.md
new file mode 100644
index 0000000..065250f
--- /dev/null
+++ b/ImplicitShared.md
@@ -0,0 +1,254 @@
+
+
+- [К списку документов](Readme.md)
+
+# Implicit shared в Qt
+
+Многие классы C++ в Qt используют неявное совместное использование данных для
+максимального использования ресурсов и минимизации копирования.
+Неявно совместно используемые классы являются как безопасными, так и эффективными,
+когда передаются в качестве аргументов, поскольку передается только указатель на данные,
+а данные копируются только тогда, когда функция записывает в них данные, т. е.copy-on-write.
+
+Implicit sharing в Qt — это механизм, при котором при копировании классов
+не происходит копирование данных, а копирование происходит лишь тогда,
+когда копии класса потребуется изменить эти данные.
+
+
+
+Некоторые особенности механизма:
+
+- При создании общего объекта счётчик ссылок устанавливается в 1.
+- Когда новый объект ссылается на общие данные, счётчик ссылок увеличивается.
+- Когда объект теряет ссылку на общие данные, счётчик ссылок уменьшается.
+- Общие данные удаляются, когда счётчик ссылок становится равен 0.
+
+Implicit sharing реализован во многих классах C++ в Qt.
+
+
+
+При разработке таких классов используется паттерн Pimpl.
+
+
+
+## Pimpl
+
+Pimpl — Pointer to private implementation.
+Это одно из названий паттерна программирования.
+Еще его называют чеширским котом — «Cheshire Cat» (это название
+мне больше нравится). В чем суть этого паттерна?
+Основная идея этого паттерна — это вынести все приватные члены класса и,
+в некоторых случаях, функционала в приватный класс.
+
+
+
+В Qt коде используется подход `d`-указателей.
+Смысл в том что объявляется класс `XXXPrivate` и переменная публичного класса
+в защищенной секции. В отдельном заголовочном файле или в `.cpp` файле уже
+пишется реализация приватного класса.
+Иерархия классов идет как по публичным так и по приватным классам.
+Для этого объявление приватного класса обычно делается в отдельном `.h` файле,
+который называется так-же как публичный, но добавляется
+приставка `_p`: `qclassname_p.h`. И эти классы не устанавливаются вместе с
+библиотекой, а служат лишь для сборки библиотеки.
+
+
+
+## Пример класса с использованием Implicit shared
+
+Пример класса для хранения ошибки, в котором используется Implicit shared.
+
+- [Заголовочный файл `error_object.h`](examples/error_object.h)
+
+```C
+#pragma once
+#ifndef NAYK_ERROR_OBJECT_H
+#define NAYK_ERROR_OBJECT_H
+
+#include
+#include
+#include
+#include
+
+class ErrorObjectPrivate; // предварительное объявление закрытого класса
+
+class ErrorObject
+{
+public:
+ ErrorObject();
+ ErrorObject(int module, int code, const QString &text,
+ const QDateTime &dateTime = QDateTime::currentDateTime());
+ ErrorObject(const ErrorObject &other);
+ ErrorObject &operator=(const ErrorObject &other);
+ ~ErrorObject();
+ int module() const;
+ void setModule(int module);
+ int code() const;
+ void setCode(int code);
+ QString text() const;
+ void setText(const QString &text);
+ QDateTime dateTime() const;
+ void setDateTime(const QDateTime &dateTime);
+ bool isValid() const;
+ bool operator==(const ErrorObject &other) const;
+ bool operator!=(const ErrorObject &other) const;
+ ErrorObject copy() const;
+
+private:
+ QSharedDataPointer d;
+}
+
+Q_DECLARE_METATYPE(ErrorObject)
+
+#endif // NAYK_ERROR_OBJECT_H
+```
+
+- [Файл с реализацией `error_object.cpp`](examples/error_object.cpp) содержит код нашего класса `ErrorObject`
+и реализацию закрытого класса `ErrorObjectPrivate`
+
+```C
+#include "error_object.h"
+#include
+
+// Закрытый класс ErrorObjectPrivate:
+
+class ErrorObjectPrivate: public QSharedData
+{
+public:
+ int module {-1};
+ int code {-1};
+ QString text;
+ QDateTime dateTime {QDateTime::currentDateTime()};
+};
+
+// Класс ErrorObject:
+
+ErrorObject::ErrorObject()
+ : d(new ErrorObjectPrivate)
+{
+ if ( !QMetaType::isRegistered(qMetaTypeId()) )
+ qRegisterMetaType();
+}
+
+ErrorObject::ErrorObject(int module, int code, const QString &text, const QDateTime &dateTime)
+ : d(new ErrorObjectPrivate)
+{
+ d->module = module;
+ d->code = code;
+ d->text = text;
+ d->dateTime = dateTime;
+}
+
+ErrorObject::ErrorObject(const ErrorObject &other) = default;
+
+ErrorObject &ErrorObject::operator=(const ErrorObject &other) = default;
+
+ErrorObject::~ErrorObject() = default;
+
+int ErrorObject::module() const
+{
+ return d->module;
+}
+
+void ErrorObject::setModule(int module)
+{
+ d->module = module;
+}
+
+int ErrorObject::code() const
+{
+ return d->code;
+}
+
+void ErrorObject::setCode(int code)
+{
+ d->code = code;
+}
+
+QString ErrorObject::text() const
+{
+ return d->text;
+}
+
+void ErrorObject::setText(const QString &text)
+{
+ d->text = text;
+}
+
+QDateTime ErrorObject::dateTime() const
+{
+ return d->dateTime;
+}
+
+void ErrorObject::setDateTime(const QDateTime &dateTime)
+{
+ d->dateTime = dateTime;
+}
+
+bool ErrorObject::isValid() const
+{
+ return (d->module >= 0) && ((d->code >= 0) || !d->text.isEmpty());
+}
+
+bool ErrorObject::operator==(const ErrorObject &other) const
+{
+ return (d->module == other.d->module) &&
+ (d->dateTime == other.d->dateTime) &&
+ (
+ ((d->code == other.d->code) && (d->code >= 0))
+ ||
+ ((d->code < 0) && (other.d->code < 0) && (d->text == other.text()))
+ );
+}
+
+bool ErrorObject::operator!=(const ErrorObject &other) const
+{
+ return !(*this == other);
+}
+
+ErrorObject ErrorObject::copy() const
+{
+ return *this;
+}
+```
+
+- Пример использования в коде:
+
+```C
+#include "error_object.h"
+//...
+ErrorObject error(1, 404, "Resource not found");
+//... какие-то действия
+ErrorObject otherError = error; // здесь данные не копируются, увеличивается счетчик ссылок
+qDebug() << "Error code:" << otherError.code();
+otherError.setCode(200); // здесь происходит копирование данных, затем изменение в копии
+```
+
+Для возможности использования типа в метасистеме Qt
+добавлено объявление типа в `.h` файле:
+
+```C
+Q_DECLARE_METATYPE(ErrorObject)
+```
+
+и регистрация типа (должна вызываться один раз до использования в метасистеме):
+
+```C
+qRegisterMetaType();
+```
+
+После регистрации тип `ErrorObject` можно использовать для передачи в сигналах и
+для конвертации в/из `QVariant`.
+
+
+
+---
+
+
+
+- [К списку документов](Readme.md)
+
+
+
+
+
diff --git a/QtCodeStyle.md b/QtCodeStyle.md
new file mode 100644
index 0000000..ff95db8
--- /dev/null
+++ b/QtCodeStyle.md
@@ -0,0 +1,577 @@
+
+
+- [К списку документов](Readme.md)
+
+# Qt Code Style - Правила кодирования с использованием Qt C++
+
+Ниже представлен обзор соглашений по написанию кода с использованием Qt.
+При использовании Qt предпочтительно использовать стиль кодирования,
+который используется в библиотеке, чтобы добиться единообразия кода.
+
+### Содержание
+
+- [Кодировка](#кодировка)
+- [Заголовочные файлы](#заголовочные-файлы)
+- [Директивы препроцессора](#директивы-препроцессора)
+- [Отступы](#отступы)
+- [Объявление переменных, функций и классов](#объявление-переменных-функций-и-классов)
+- [Пробелы](#пробелы)
+- [Фигурные скобки](#фигурные-скобки)
+- [Круглые скобки](#круглые-скобки)
+- [Использование конструкции switch](#использование-конструкции-switch)
+- [Разрыв строк](#разрыв-строк)
+- [Использование исключений](#использование-исключений)
+- [Наследование и ключевое слово virtual](#наследование-и-ключевое-слово-virtual)
+- [Неявные преобразования](#неявные-преобразования)
+- [Числа с плавающей запятой](#числа-с-плавающей-запятой)
+- [Преинкремент и предекремент](#преинкремент-и-предекремент)
+- [Другие очевидные вещи](#другие-очевидные-вещи)
+- [Общее исключение](#общее-исключение)
+
+
+
+## Кодировка
+
+Единственной кодировкой должна быть UTF-8, а использование других следует
+приравнять к разжиганию межнациональной розни и карать соответствующей статьёй УК.
+
+
+
+[наверх](#содержание)
+
+
+
+## Заголовочные файлы
+
+При включении заголовочных файлов Qt, всегда используйте следующую форму
+записи:
+
+```C
+#include
+```
+
+Префикс библиотеки (`QtCore`, `QtWidgets` и т.д.) необходим для фреймворков Mac OS X,
+а также очень целесообразен для не qmake проектов.
+
+
+
+Все заголовочные файлы должны быть с защитой от повторного включения посредством `#pragma once` или `#define`.
+Применение `#pragma once` вместо `#define` увеличит скорость компиляции во многих случаях
+благодаря высокоуровневому механизму; компилятор может самостоятельно сравнивать имена файлов
+или inode'ы без необходимости вызова препроцессора для проверки заголовка на наличие `#ifndef` и `#endif`.
+Можно использовать обе команды, `#pragma once` и `#define`, для написания переносимого кода,
+что также может принести выгоду от применения `#pragma once` при оптимизации (если компилятор её поддерживает):
+
+```C
+#pragma once
+#ifndef FOO_BAR_BAZ_H_
+#define FOO_BAR_BAZ_H_
+
+//...
+
+#endif // FOO_BAR_BAZ_H_
+```
+
+- Все заголовочные файлы должны быть самодостаточными в плане компиляции.
+Пользователи и инструменты разработки не должны зависеть от специальных зависимостей
+при использовании заголовочного файла.
+
+- Подключайте только действительно используемые заголовочные файлы. Не надо заранее
+подключать кучу `.h` файлов "на всякий случай".
+
+- Никогда не пишите реализацию методов класса или функций в заголовочном файле!
+
+- Вставляйте заголовочные файлы в следующем порядке: парный файл (например, foo.h — foo.cpp),
+файлы библиотеки Qt, стандартная библиотека C++, другие библиотеки, файлы вашего проекта.
+
+- Все заголовочные файлы проекта должны указываться относительно директории исходных файлов проекта
+без использования таких псевдонимов как . (текущая директория) или .. (родительская директория).
+Директории поиска общих заголовочных файлов можно задать в файле проекта.
+
+
+
+[наверх](#содержание)
+
+
+
+## Директивы препроцессора
+
+Символ решетки всегда в начале строки, а имя директивы с отступом.
+
+```C
+# if defined(QT_NO_KEYWORDS)
+# define QT_NO_EMIT
+# else
+# ifndef QT_NO_SIGNALS_SLOTS_KEYWORDS
+# define slots Q_SLOTS
+# define signals Q_SIGNALS
+# endif
+# endif
+```
+
+
+
+[наверх](#содержание)
+
+
+
+## Отступы
+
+- Для обозначения отступа используйте 4 пробела подряд.
+- Используйте пробелы, а не табуляцию!
+
+
+
+[наверх](#содержание)
+
+
+
+## Объявление переменных, функций и классов
+
+Один из самых важных постулатов, так как определяет читабельность и общий стиль кода.
+Правила объявления переменных собраны в такой список:
+
+- Объявляйте по одной переменной в строке.
+- Избегайте, если это возможно, коротких и запутанных названий переменных
+(Например: "a", "rbarr", "nughdeget").
+- Односимвольные имена переменных подходят только для итераторов циклов,
+небольшого локального контекста и временных переменных. В остальных случаях
+имя переменной должно отражать ее назначение.
+- Заводите переменные только по мере необходимости.
+
+```C
+// Неправильно:
+int a, b;
+char *c, *d;
+
+// Правильно:
+int height;
+int width;
+char *nameOfThis;
+char *nameOfThat;
+```
+
+- Не используйте глобальные переменные. Вместо них рекомендуется использовать
+локальные переменные и передавать их через параметры функций.
+
+- Функции и переменные должны именоваться со строчной буквы.
+Каждое последующие слово в имени переменной должно начинаться с прописной буквы.
+- Избегайте аббревиатур.
+
+```C
+// Неправильно
+short Cntr;
+char ITEM_DELIM = ' ';
+
+// Правильно
+short counter;
+char itemDelimiter = ' ';
+```
+
+- Имена классов всегда начинаются с заглавной буквы.
+- Сокращения в camel case (правильно: `QXmlStreamReader`, не правильно: `QXMLStreamReader`).
+
+
+
+Размещайте свой код в пространстве имён (за некоторыми исключениями).
+Пространство имён должно иметь уникальное имя, обычно формируемое на основе названия проекта,
+и, возможно, пути.
+Не используйте директиву `using` (например, `using namespace foo`).
+Не используйте встроенные (`inline`) пространства имён.
+Пространства имён делят глобальную область видимости на отдельные именованные области,
+позволяя избежать совпадения (коллизий) имён.
+
+
+
+[наверх](#содержание)
+
+
+
+## Пробелы
+
+Пробелы — очень важный элемент форматирования исходного кода.
+Он отыгрывает очень большую роль в читабельности кода.
+
+- Используйте пустые строки для логической группировки операторов, где это возможно.
+- Всегда используйте одну пустую строку в качестве разделителя
+- Всегда используйте один пробел перед фигурной скобкой
+
+```C
+// Неправильно:
+if(foo){
+}
+
+// Правильно:
+if (foo) {
+}
+```
+
+- Всегда ставьте один пробел после `'*'` или `'&'`, если они стоят перед описанием типов.
+Но никогда не ставьте пробелы между `'*'` или `'&'` и именем переменной.
+
+```C
+char *x;
+const QString &myString;
+const char * const y = "hello";
+```
+
+- Не окружайте пробелами функции доступа `.` и `->`.
+- Бинарные операции отделяются пробелами с двух сторон.
+- После преобразования типов не ставьте пробелов.
+- Избегайте преобразования типов в стиле C.
+
+```C
+// Неправильно
+char* blockOfMemory = (char* ) malloc(data.size());
+
+// Правильно
+char *blockOfMemory = reinterpret_cast(malloc(data.size()));
+```
+
+- Не используйте несколько операторов на одной строке
+- По возможности, используйте новую строку для тела оператора ветвления:
+
+```C
+// Неправильно:
+if (foo) bar();
+
+// Правильно:
+if (foo)
+ bar();
+```
+
+- Содержимое в пространстве имён пишется без отступа.
+- Никогда не добавляйте пробелы в конец строки.
+
+
+
+[наверх](#содержание)
+
+
+
+## Фигурные скобки
+
+Скобки — это вообще отдельная тема. Они, как и пробелы, отыгрывают львиную долю
+во внешнем виде и читабельности кода.
+
+- Возьмите за основу расстановку открывающих фигурных скобок на одной строке
+с выражением, которому они предшествуют.
+- Исключение: Тело функции и описание класса всегда открывается фигурной скобкой,
+стоящей на новой строке.
+- Используйте фигурные скобки в условиях, если тело условия в размере превышает одну линию,
+или тело условия достаточное сложное и выделение скобками действительно необходимо.
+- Исключение 1: Используйте скобки, если родительское выражение состоит
+из нескольких строк / оберток.
+- Исключение 2: Используйте фигурные скобки, когда тела ветвлений `if-then-else`
+занимают несколько строчек.
+- Используйте фигурные скобки для обозначения пустого тела условия.
+
+```C
+// Неправильно:
+if (codec)
+{
+ // do something
+}
+
+// Правильно:
+if (codec) {
+ // do something
+}
+
+// Неправильно:
+if (address.isEmpty() || !isValid()
+ || !codec)
+ return false;
+
+// Правильно:
+if (address.isEmpty() || !isValid()
+ || !codec) {
+ return false;
+}
+```
+
+
+
+[наверх](#содержание)
+
+
+
+## Круглые скобки
+
+- Используйте круглые скобки для группировки выражений.
+
+```C
+// Неправильно
+if (a && b || c)
+if (a + b & c)
+
+// Правильно
+if ((a && b) || c)
+if ((a + b) & c)
+```
+
+
+
+[наверх](#содержание)
+
+
+
+## Использование конструкции switch
+
+Безусловно, эти условия причина многих дискуссий со стороны разработчиков и создателей
+Coding Guidelines — там может быть очень много различных вариантов.
+Однако Qt предлагает именно такой вариант:
+
+- Операторы case должны быть в одном столбце со `switch`.
+- Каждый оператор `case` должен иметь закрывающий `break` (или `return`) или комментарий,
+которой предполагает намеренное отсутствие `break & return`.
+
+```C
+switch (myEnum) {
+case Value1:
+ doSomething();
+ break;
+case Value2:
+case Value3:
+ doSomethingElse();
+ // fall through
+default:
+ defaultHandling();
+ break;
+}
+```
+
+
+
+[наверх](#содержание)
+
+
+
+## Разрыв строк
+
+Часто происходит следующее: есть разработчик Вася с большим монитором.
+Он пишет себе код спокойно. Потом этот код открывает разработчик Петя, с ноутбуком,
+и прозревает — ему приходится много скроллить чтобы прочитать весь код.
+Это один из дефектов читабельности. Что же предлагает Qt для спасения?
+
+- Длина строки кода не должна превышать 100 символов (а лучше 80 - исторический стандарт).
+Если надо – используйте разрыв строки.
+- Запятые помещаются в конец разорванной линии;
+операторы помещаются в начало новой строки. В зависимости от используемой вами IDE,
+оператор на конце разорванной строки можно проглядеть.
+
+```C
+// Неправильно:
+if (longExpression +
+ otherLongExpression +
+ otherOtherLongExpression) {
+}
+
+QMessageBox::information(d->someObjectWithLongName, tr("A long title for mesage"), tr("A very very very very very very long body"), QMessageBox::Ok, QMessageBox::Cancel);
+
+// Правильно:
+if (longExpression
+ + otherLongExpression
+ + otherOtherLongExpression) {
+}
+
+QMessageBox::information(d->someObjectWithLongName,
+ tr("A long title for mesage"),
+ tr("A very very very very very very long body"),
+ QMessageBox::Ok, QMessageBox::Cancel);
+```
+
+
+
+[наверх](#содержание)
+
+
+
+## Использование исключений
+
+В Qt исключения (`throw `) не используются. Вместо них применяются коды ошибок.
+
+
+
+[наверх](#содержание)
+
+
+
+## Наследование и ключевое слово virtual
+
+В этом постулате все предельно просто — главное не писать `virtual`
+перед названием переопределяемого метода в `.h` файле.
+
+```C
+// Неправильно:
+class MyWidget : public QWidget
+{
+...
+protected:
+ virtual void keyPressEvent(QKeyEvent *);
+
+// Правильно:
+class MyWidget : public QWidget
+{
+...
+protected:
+ void keyPressEvent(QKeyEvent *) override;
+```
+
+
+
+[наверх](#содержание)
+
+
+
+## Неявные преобразования
+
+Не объявляйте неявные преобразования. Используйте ключевое слово `explicit`
+для операторов преобразования типа и конструкторов с одним аргументом.
+Исключение: конструкторы копирования и перемещения могут объявляться без `explicit`,
+т.к. они не выполняют преобразование типов.
+
+
+
+[наверх](#содержание)
+
+
+
+## Числа с плавающей запятой
+
+Числа с плавающей запятой всегда должны быть с десятичной точкой и числами
+по обе стороны от неё (даже в случае экспоненциальной нотации).
+
+```C
+// Неправильно:
+float f = 1.f;
+long double ld = -.5L;
+double d = 1248e6;
+
+// Правильно:
+float floatValue = 1.0f;
+float floatVariable = 1.0; // OK
+double doubleValue = 1248.0e6;
+```
+
+
+
+[наверх](#содержание)
+
+
+
+## Преинкремент и предекремент
+
+Используйте префиксные формы (`++i`) инкремента и декремента;
+постфиксную форму используйте только при явной необходимости.
+Когда переменная инкрементируется (`++i`, `i++`) или декрементируется
+(`--i`, `i--`), а возвращаемое значение не используется, то необходимо
+чётко понимать: использовать префиксную форму (`++i`, `--i`) или постфиксную
+(`i++`, `i--`).
+
+
+
+Префиксную форму обычно легче читать, и она часто более эффективна
+(как минимум такая же), т.к. не требуется создавать копию значения
+до выполнения операции.
+
+```C
+// Неправильно:
+for (int i = 0; i < size; i++) {
+
+// Правильно:
+for (int i = 0; i < size; ++i) {
+```
+
+
+
+[наверх](#содержание)
+
+
+
+## Другие очевидные вещи
+
+Еще некоторые правила, которые всегда должны выполняться, их все знают,
+но повторим на всякий случай:
+
+- Не используйте `goto` и другие устаревшие конструкции,
+которые нарушают принципы стандарта программирования.
+- По возможности не используйте в проектах `qmake`, старайтесь новые проекты
+строить с использованием `cmake` актуальной версии.
+- Всегда включайте в свои файлы проектов расширренную проверку на ошибки.
+Для компилятора `gcc` (`mingw`) это делается добавлением строчки в `CMakeList.txt`:
+
+```CMake
+target_compile_options(${PROJECT_NAME} PRIVATE -Werror -Wall -Wextra -Wpedantic)
+```
+
+- Также можно выключать устаревшие конструкции языка. Пример для выключения `foreach`:
+
+```CMake
+target_compile_definitions(${PROJECT_NAME} PRIVATE QT_NO_FOREACH)
+```
+
+- Пользуйтесь системой управления версиями.
+
+- Пишите по возможности кроссплатформенный код (как минимум поддерживаемый Windows и Linux). Используйте условную компиляцию для кода, специфичного для определенной ОС:
+
+```C
+# if defined (Q_OS_WINDOWS)
+ // код для Windows
+# else
+ // код для Linux, MacOS
+# endif
+```
+
+- Для указателей (адресов) используйте `nullptr`, это улучшает
+безопасность типов. Используйте `'\0'` в качестве символа конца строки
+(пустого символа). Это улучшает читабельность кода.
+
+- Рекомендуется использовать `sizeof(переменная)` вместо `sizeof(тип)`.
+
+- Не вставляйте бесполезные комментарии в код.
+Ваш код должен быть самодокументируемым. Комментарии можно использовать
+для отдельных пояснений неочевидных или специфических вещей:
+
+```C
+// Плохо:
+int counter; // - счетчик шагов
+
+// Хорошо:
+int stepCounter {0};
+```
+
+
+
+
+[наверх](#содержание)
+
+
+
+## Общее исключение
+
+Этот постулат гласит нам, что нет ничего плохого если вы нарушите какое-то правило,
+но только в том случае, если оно делает ваш код уродливым.
+Это хороший пример того, что у всех правил есть исключения, и того,
+что правила созданы чтобы их нарушать.
+
+
+
+К сожалению, я не смог найти примера, когда `Qt Coding Guidelines` делают код — уродливым.
+
+
+
+[наверх](#содержание)
+
+
+
+---
+
+
+
+- [К списку документов](Readme.md)
+
+
+
+
+
diff --git a/QtCreator.md b/QtCreator.md
new file mode 100644
index 0000000..88bf34f
--- /dev/null
+++ b/QtCreator.md
@@ -0,0 +1,61 @@
+
+
+- [К списку документов](Readme.md)
+
+# Qt Creator
+
+## Горячие клавиши для Qt Creator
+
+Горячие клавиши для Qt Creator, которые значительно упростят жизнь
+
+
+- `Esc` - Выполняет переход к редактированию кода.
+Несколько последовательных нажатий этой клавиши переключают пользователя в режим
+редактирования, закрывают панели вывода справки, отладки.
+
+- `F4` - Переключает редактор между файлом реализации (`.сpp`) и соответствующим
+заголовочным файлом (`.h`), которые содержат объявления интерфейса и
+реализации класса соответственно.
+
+- `F2` - Выполняет переход к месту объявления переменной, функции, класса,
+на имени которых стоял курсор при нажатии.
+
+- `F1` - Показывает справку для класса или метода Qt, на имени которого стоит курсор.
+
+- `Ctrl + Shift + R` - Переименование переменной, метода, класса, на имени
+которых стоит курсор. Имя будет изменено во всех местах, где встречается
+его использование: не только в текущем файле, но и в других файлах проекта.
+При замене имени будет учитываться область видимости имени, поэтому замена
+произойдёт только в местах обращения к имени. Именно этим это действие отличается
+от обычного поиска и замены текста.
+
+- `Ctrl + Shift + U` - Поиск всех мест обращения к переменной, методу,
+классу на имени которого стоит курсор.
+
+- `Ctrl + K` - Открывает поле быстрого поиска (Locator).
+
+- `Alt + Enter` - Позволяет открыть доступные дополнительные действия для
+переменной, метода, класса, оператора в позиции курсора.
+Это дополнительные действия для рефакторинга (реорганизации и улучшения
+существующего кода) могут содержать изменение порядка параметров,
+изменения в текущем фрагменте кода, добавление фрагментов кода и т.д.
+
+- `Ctrl + Space` - Вызывает выпадающий список автозавершения кода.
+
+- `Ctrl + F` - Поиск текста в текущем открытом файле.
+
+- `Ctrl + Shift + F` - Расширенный поиск текста в файле, проекте или группе
+проектов (доступны дополнительные настройки).
+
+
+
+---
+
+
+
+- [К списку документов](Readme.md)
+
+
+
+
+
diff --git a/QtThreads.md b/QtThreads.md
new file mode 100644
index 0000000..d957ed9
--- /dev/null
+++ b/QtThreads.md
@@ -0,0 +1,253 @@
+
+
+- [К списку документов](Readme.md)
+
+# QThread - что нужно знать о потоках
+
+## Основы
+
+В Qt любые объекты способные работать с сигналами и слотами являются
+наследниками класса `QObject`.
+Каждый `QObject` строго привязан к какому-то потоку `QThread` который,
+собственно, и занимается обслуживанием слотов и прочих событий данного объекта.
+Один поток может обслуживать сразу множество `QObject` или вообще ни одного,
+а вот `QObject` всегда имеет родительский поток и он всегда ровно один.
+По сути можно считать что каждый `QThread` «владеет» каким-то набором `QObject`.
+Внутри каждого `QThread` спрятана очередь сообщений адресованных
+к объектам которыми данный `QThread` «владеет».
+В модели Qt предполагается что если мы хотим чтобы `QObject` сделал
+какое-либо действие, то мы «посылаем» данному `QObject` сообщение `QEvent`.
+В этом потоково-безопасном вызове Qt находит `QThread` которому принадлежит
+объект receiver, записывает `QEvent` в очередь сообщений этого потока и при
+необходимости «будит» этот поток. При этом ожидается что код работающий в
+данном `QThread` в какой-то момент после этого прочитает сообщение из
+очереди и выполнит соответствующее действие. Чтобы это действительно произошло,
+код в `QThread` должен войти в цикл обработки событий `QEventLoop`,
+создав соответствующий объект и позвав у него либо метод `exec()`,
+либо метод `processEvents()`. Первый вариант входит в бесконечный цикл
+обработки сообщений (до получения `QEventLoop` события `quit()` ),
+второй ограничивается тем что обрабатывает сообщения ранее накопившиеся в очереди.
+
+
+
+Итак, как мы уже разобрались, каждый объект в Qt «принадлежит» какому-то потоку.
+При этом встает закономерный вопрос: а какому, собственно говоря, именно?
+В Qt приняты следующие соглашения:
+
+- Все «дети» любого «родителя» всегда живут в том же потоке что и
+родительский объект. Например попытка сделать `setParent` к объекту живущему
+в другом потоке в Qt просто молча фейлится (в консоль пишется предупреждение).
+
+- Объект у которого при создании не указан родитель живет в потоке
+который его создал.
+
+- При необходимости поток можно менять вызовом `QObject::moveToThread` (переместить объект в поток).
+Перемещать можно только верхнеуровневых «родителей» (у которых `parent == null`),
+попытка переместить любого «ребенка» будет молча проигнорирована.
+
+- При перемещении верхнеуровневого «родителя» все его «дети» тоже переедут
+в новый поток.
+
+- Получить «текущий» поток исполнения можно через вызов
+функции `QThread::currentThread()`, поток с которым ассоциирован объект — через
+вызов `QObject::thread()`.
+
+- Все GUI-объекты кроме rendering back-end должны жить в GUI-потоке.
+
+- GUI-потоком является тот в котором был создан объект `QApplication`.
+
+## Таймеры в потоках
+
+Таймеры `QTimer` в потоках имеют ряд особенностей, которые нужно учитывать
+при проектировании многопоточных приложений на Qt:
+
+- `QTimer` работает только в потоке с event loop (циклом обработки событий).
+Это значит, что если вы хотите использовать `QTimer` в `QThread`, то в этом потоке должен быть запущен `QEventLoop`.
+Если нет цикла событий — таймер просто не сработает.
+
+- QTimer должен быть создан в том потоке, в котором будет работать.
+Таймер "привязан" к потоку через QObject::thread().
+Если вы создадите таймер в основном потоке, а потом попытаетесь использовать
+его в другом — это будет ошибка.
+
+- Если объект с таймером перемещается в другой поток через `moveToThread()`,
+таймер должен быть создан после перемещения. Иначе он останется привязанным к исходному потоку.
+
+## Правильная работа с потоками в Qt
+
+Для правильной работы вашего кода в параллельном потоке используйте следующие правила:
+
+- Проектируется отдельный класс (worker), потомок QObject, который будет работать в потоке.
+- У этого объекта должны быть определены публичные слоты для запуска и остановки
+основной работы, например: `void start();` и `void stop();`.
+- Также у объекта должны быть определены сигналы для оповещения после начала
+и после полного окончания работы,
+например `void started();` и `void finished();`.
+- Создание внутренних объектов и таймеров должны выполняться только
+в слоте `start()` или позже (не в конструкторе).
+- Обмен данными с объектом должен осуществляться только через механизм сигнал-слот.
+Вызов методов напрямую после помещения объекта в поток запрещен!
+- Далее в основном потоке программы создаётся экземпляр объекта worker (без родителя),
+создаётся оъект `QThread`, и worker перемещвется в поток через `moveToThread()`.
+После этого создаются связи сигнал-слот и запускается поток на выполнение.
+
+
+
+Пример класса `Worker`. Заголовочный файл `worker.h`:
+
+```C
+#pragma once
+#ifndef WORKER_H_
+#define WORKER_H_
+#include
+#include
+
+class Worker: public QObject
+{
+ Q_OBJECT
+public:
+ explicit Worker(QObject *parent = nullptr);
+ virtual ~Worker();
+signals:
+ void started();
+ void finished();
+ // ... другие сигналы наружу
+public slots:
+ void start();
+ void stop();
+ // ...другие слоты для наружи
+private:
+ QTimer *m_timer {nullptr};
+ // ...
+private slots:
+ void timerTimeOut();
+ // ...
+};
+#endif // WORKER_H_
+```
+
+Файл с реализацией `worker.cpp`:
+
+```C
+#include "worker.h"
+
+Worker::Worker(QObject *parent) : QObject{parent}
+{
+ // конструктор выполняется еще в основном потоке!
+}
+
+Worker::~Worker()
+{
+ // К моменту вызова деструктора поток уже должен быть остановлен!
+ // но проверить стоит:
+ stop();
+}
+
+void Worker::start()
+{
+ // К этому моменту мы уже в параллельном потоке
+
+ if (m_timer) { // если таймер уже есть, значит это повторный вызов
+
+ return;
+ }
+
+ m_timer = new QTimer(this);
+ connect(m_timer, &QTimer::timeout, this, &Worker::timerTimeOut);
+ // ... другие действия, например настройки и запуск таймера
+ m_timer->start(1000);
+
+ emit started(); // оповещение, что мы стартанули
+}
+
+void Worker::stop()
+{
+ // Тут мы еще в параллельном потоке
+
+ if (!m_timer) { // если таймера нет, значит это повторный вызов
+
+ return;
+ }
+
+ m_timer->stop();
+ delete m_timer;
+ m_timer = nullptr;
+
+ // ... тут остановка всей работы, удаление объектов и т.п.
+
+ emit finished(); // оповещение, что мы остановились
+}
+
+void Worker::timerTimeOut()
+{
+ // Обработчик таймера срабатывает уже в параллельном потоке
+ // ...
+}
+
+```
+
+Как применить из основного потока, например слот клика по кнопке:
+
+```C
+#include "worker.h"
+#include
+// ...
+
+void MainWindow::pushButtonClicked()
+{
+ Worker *worker = new Worker(); // без родителя
+ QThread *thread = new QThread(this);
+
+ worker->moveToThread(thread);
+
+ // Объект начнёт работу после запуска потока:
+ connect(thread, &QThread::started, worker, &Worker::start);
+
+ // Какой-нибудь сигнал для остановки потока:
+ connect(this, &MainWindow::stopThread, worker, &Worker::stop);
+
+ // Когда объект закончит работу, можно останавливать поток:
+ connect(worker, &Worker::finished, thread, &QThread::quit);
+
+ // Когда поток завершится, можно удалить объект и класс потока:
+ connect(thread, &QThread::finished, worker, &Worker::deleteLater);
+ connect(thread, &QThread::finished, thread, &Worker::deleteLater);
+
+ // ... тут другие нужные сигналы-слоты
+
+ // Запуск потока:
+ thread->start();
+}
+
+// когда поток больше не нужен, вызываем emit stopThread();
+
+```
+
+Обратите внимание, в примере выше все действия по созданию и запуску потока находятся
+в одном слоте и после выхода из слота доступны только через сигналы.
+Нет защиты от повторного запуска - т.е. сколько раз нажали кнопку, столько потоков и создаётся,
+а остановка всех по сигналу `stopThread()`.
+
+
+
+Для отслеживания количества нужно добавить счетчик запуска или флаг, например.
+И при закрытии вашего приложения нужно обязательно дождаться завершения всех
+созданных потоков!
+Но это уже на вашей совести.
+
+
+
+*p.s. Код не проверял и писал по памяти. Возможны очепятки.*
+
+
+
+---
+
+
+
+- [К списку документов](Readme.md)
+
+
+
+
+
diff --git a/README.md b/README.md
index 4200859..017269f 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,15 @@
-# Qt_Code_Style
+
+
+# Сборник полезностей по Qt и C++
+
+- [Qt Code Style](QtCodeStyle.md) - Правила кодирования с использованием Qt
+- [Qt Creator](QtCreator.md) - полезности
+- [Implicit Shared в Qt](ImplicitShared.md) - механизм управления копированием данных
+- [QThread - что нужно знать о потоках](QtThreads.md) - пример работы с потоками
+
+
+
+---
+
+
-Сборник полезностей Qt
\ No newline at end of file
diff --git a/_resources/images/progcat.png b/_resources/images/progcat.png
new file mode 100644
index 0000000..eca87ce
Binary files /dev/null and b/_resources/images/progcat.png differ
diff --git a/_resources/images/qtcat.png b/_resources/images/qtcat.png
new file mode 100644
index 0000000..721ff2a
Binary files /dev/null and b/_resources/images/qtcat.png differ
diff --git a/examples/error_object.cpp b/examples/error_object.cpp
new file mode 100644
index 0000000..131eb76
--- /dev/null
+++ b/examples/error_object.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+** Copyright (c) 2025 Evgeny Teterin (nayk)
+** All right reserved.
+**
+** Permission is hereby granted, free of charge, to any person obtaining
+** a copy of this software and associated documentation files (the
+** "Software"), to deal in the Software without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Software, and to
+** permit persons to whom the Software is furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be
+** included in all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**
+****************************************************************************/
+#include "error_object.h"
+#include
+
+namespace nayk { //=============================================================
+
+//==============================================================================
+class ErrorObjectData : public QSharedData
+{
+public:
+ int module {-1};
+ int code {-1};
+ QString text;
+ QDateTime dateTime {QDateTime::currentDateTime()};
+};
+//==============================================================================
+void regiserErrorObjectMetaType()
+{
+ if ( !QMetaType::isRegistered( qMetaTypeId() ) ) {
+
+ qRegisterMetaType();
+ }
+}
+//==============================================================================
+ErrorObject::ErrorObject()
+ : d(new ErrorObjectData)
+{
+ regiserErrorObjectMetaType();
+}
+//==============================================================================
+ErrorObject::ErrorObject(int module, int code, const QString &text, const QDateTime &dateTime)
+ : d(new ErrorObjectData)
+{
+ regiserErrorObjectMetaType();
+
+ d->module = module;
+ d->code = code;
+ d->text = text;
+ d->dateTime = dateTime;
+}
+//==============================================================================
+ErrorObject::ErrorObject(const ErrorObject &other) = default;
+//==============================================================================
+ErrorObject &ErrorObject::operator=(const ErrorObject &other) = default;
+//==============================================================================
+ErrorObject::~ErrorObject() = default;
+//==============================================================================
+int ErrorObject::module() const
+{
+ return d->module;
+}
+//==============================================================================
+void ErrorObject::setModule(int module)
+{
+ d->module = module;
+}
+//==============================================================================
+int ErrorObject::code() const
+{
+ return d->code;
+}
+//==============================================================================
+void ErrorObject::setCode(int code)
+{
+ d->code = code;
+}
+//==============================================================================
+QString ErrorObject::text() const
+{
+ return d->text;
+}
+//==============================================================================
+void ErrorObject::setText(const QString &text)
+{
+ d->text = text;
+}
+//==============================================================================
+QDateTime ErrorObject::dateTime() const
+{
+ return d->dateTime;
+}
+//==============================================================================
+void ErrorObject::setDateTime(const QDateTime &dateTime)
+{
+ d->dateTime = dateTime;
+}
+//==============================================================================
+bool ErrorObject::isValid() const
+{
+ return (d->module >= 0) && ((d->code >= 0) || !d->text.isEmpty());
+}
+//==============================================================================
+bool ErrorObject::operator==(const ErrorObject &other) const
+{
+ return (d->module == other.d->module) &&
+ (d->dateTime == other.d->dateTime) &&
+ (
+ ((d->code == other.d->code) && (d->code >= 0))
+ ||
+ ((d->code < 0) && (other.d->code < 0) && (d->text == other.text()))
+ );
+}
+//==============================================================================
+bool ErrorObject::operator!=(const ErrorObject &other) const
+{
+ return !(*this == other);
+}
+//==============================================================================
+ErrorObject ErrorObject::copy() const
+{
+ return *this;
+}
+//==============================================================================
+
+} // namespace nayk //==========================================================
diff --git a/examples/error_object.h b/examples/error_object.h
new file mode 100644
index 0000000..4c0b398
--- /dev/null
+++ b/examples/error_object.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+** Copyright (c) 2025 Evgeny Teterin (nayk)
+** All right reserved.
+**
+** Permission is hereby granted, free of charge, to any person obtaining
+** a copy of this software and associated documentation files (the
+** "Software"), to deal in the Software without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Software, and to
+** permit persons to whom the Software is furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be
+** included in all copies or substantial portions of the Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**
+****************************************************************************/
+#pragma once
+#ifndef NAYK_ERROR_OBJECT_H
+#define NAYK_ERROR_OBJECT_H
+
+#if defined (LIB_NAYK_CORE)
+# define ERROR_OBJECT_EXPORT Q_DECL_EXPORT
+#else
+# define ERROR_OBJECT_EXPORT Q_DECL_IMPORT
+#endif
+
+#include
+#include
+#include
+#include
+
+namespace nayk { //=============================================================
+
+class ErrorObjectData;
+
+class ERROR_OBJECT_EXPORT ErrorObject
+{
+public:
+ ErrorObject();
+ ErrorObject(int module, int code, const QString &text, const QDateTime &dateTime = QDateTime::currentDateTime());
+ ErrorObject(const ErrorObject &other);
+ ErrorObject &operator=(const ErrorObject &other);
+ ~ErrorObject();
+ int module() const;
+ void setModule(int module);
+ int code() const;
+ void setCode(int code);
+ QString text() const;
+ void setText(const QString &text);
+ QDateTime dateTime() const;
+ void setDateTime(const QDateTime &dateTime);
+ bool isValid() const;
+ bool operator==(const ErrorObject &other) const;
+ bool operator!=(const ErrorObject &other) const;
+ ErrorObject copy() const;
+
+private:
+ QSharedDataPointer d;
+};
+
+} // namespace nayk //==========================================================
+
+Q_DECLARE_METATYPE(nayk::ErrorObject)
+
+#endif // NAYK_ERROR_OBJECT_H