Автоматическое форматирование C++ кода в Qt Creator с помощью clang-format

Устанавливаем clang-format на Ubuntu из основного репозитория:

sudo apt install clang-format

Или свежую версию из репозитория LLVM:

wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo apt update
sudo apt install clang-format-12

Запускаем Qt Creator. Идем «Справка -> О модулях…«. Ставим галочку на Beautifier.

Идем в «Инструменты -> Параметры…«.

Можно включить форматирование при сохранении файла.

На вкладке Clang Format указываем путь к clang-format.

Можно использовать стандартный стиль, а можно создать собственный.

Стиль сохраняется в домашнюю папку по следующему пути:

$HOME/.config/QtProject/qtcreator/beautifier/clangformat/my_style/.clang-format

Допустим у вас уже есть файл .clang-format, который хранится в репозитории вашего проекта. Тогда можно создать символическую ссылку на него:

rm $HOME/.config/QtProject/qtcreator/beautifier/clangformat/my_style/.clang-format

ln -s my_project/.clang-format $HOME/.config/QtProject/qtcreator/beautifier/clangformat/my_style/.clang-format

Можно настроить горячие клавиши для форматирования:

Генплан Казани 2020 (до 2040 года), проект Аметьево

Кликните на картинку, чтобы посмотреть в хорошем качестве.

Группа Аметьево в телеграме.

Проект Аметьево (Калуга) от 2021 года

15 апреля 2021 года было опубликовано постановление об общественных обсуждениях по новому проекту Аметьево.

В этом документе находится новый проект планировки территории Аметьево с двумя чертежами, описанием проекта и планом работ.

Чертеж 1

Чертеж 2

Генплан

В документе опубликованы 2 чертежа и описание проекта.

Генплан и вся связанная с ним информация размещена в разделе Градостроительство на сайте мэрии Казани.

Ниже приведены выжимки из плана, связанные с Аметьево.

Кликайте на картинки, чтобы увеличить.

Карта планируемого размещения линейных объектов транспортной инфраструктуры местного значения (линейные объекты — это дороги):

Обозначения:

Основной чертеж Генерального плана городского округа Казань (карта функциональных зон):

Обозначения:

Описание генплана находится в документе «Положение о территориальном планировании» (Приложение к решению №5-38.pdf). Этот документ состоит почти из 800 страниц.

Генеральный план г. Казани разработан на следующие проектные периоды:

  • первая очередь строительства (до 2025 года);
  • расчетный срок – на 20 лет (до 2040 года);
  • перспектива – на 35 лет (до 2055 года).

На карте с линейными объектами пунктирными линиями обозначены новые дороги, для них есть условные названия «Проезд №». Более подробная информация о проездах содержится в приложении указанном выше. Проезд №79 — страница 389. Проезд № 116 — страница 416.

Как удалить процедуру или функцию из базы данных

При разработке инструментов, которые взаимодействуют с разными СУБД, приходится учитывать много нюансов, потому что одни и теже вещи реализованы по-разному и стандарт SQL поддерживается по-разному. Если рассмотреть достаточное количество СУБД, то окажется, что нет универсального способа удалить функцию или процедуру.

Читать далее Как удалить процедуру или функцию из базы данных

Добавление настроек к отдельным файлам в CMake

Настройка целей

CMake поддерживает следующие команды для добавления настроек к цели:

  • target_compile_definitions — добавляет определения,
  • target_compile_options — добавляет опции компилятора,
  • target_include_directories — добавляет пути поиска заголовочных файлов,
  • target_link_libraries — добавляет линкуемые библиотеки.

Эти команды принимают имя цели в качестве первого аргумента. Цели создаются командами add_executable и add_library. Для add_executable целью является исполняемый файл, а для add_library — библиотека (статическая или динамическая).

CMake поддерживает следующие команды для добавления глобальных настроек:

  • add_compile_definitions — добавляет определения,
  • add_compile_options — добавляет опции компилятора,
  • include_directories — добавляет пути поиска заголовочных файлов.
  • link_libraries — добавляет линкуемые библиотеки.

Эти настройки применяются к целям в текущей папке и всех вложенных папках.

Команды для настройки целей и глобальные команды очень похожи, но имеют разную область видимости. К сожалению, нет аналогичных команд для настройки исходных файлов.

set_property

Чтобы добавить настройки к исходному файлу, можно воспользоваться командой set_property или set_source_files_properties. Пример использования:

set_property(SOURCE LibPQExt.cpp APPEND PROPERTY INCLUDE_DIRECTORIES
    ${CMAKE_SOURCE_DIR}/libs/postgresql-9.6/src/include
)

set_property позволяет добавлять настройки для нескольких исходных файлов одновременно.

Если использовать опцию APPEND, то настройка добавляются к уже существующему списку настроек.

Объектная библиотека

Еще один способ — создать из исходного файла или их набора специальную цель, которая называется объектной библиотекой.

Синтаксис команды для создания объектных библиотек:

add_library( OBJECT ...)

К такой цели можно применять команды с префиксом target_. Например, можно добавить определение LOGGER_TYPE=3 только для файла logger.cpp. Делается это следующим образом

add_library(logger OBJECT logger.cpp)
target_compile_definitions(logger PUBLIC LOGGER_TYPE=3)

Объектную библиотеку можно добавить к другим целям как набор исходных файлов. Для этого в команды add_executable или add_library надо добавить выражение $, где objlib — имя объектной библиотеки. Например:

add_library(logger OBJECT logger.cpp)
target_compile_definitions(logger PUBLIC LOGGER_TYPE=3)

add_executable(my_application
    main.cpp
    archiver.cpp
    $
)

Поддержка объектных библиотек была введена в CMake версии 2.8.8 (апрель 2012 года). При использовании объектных библиотек рекомендуется в файле CMakeLists.txt ограничить версию CMake на уровне 2.8.8 или выше:

cmake_minimum_required(VERSION 2.8.8)

Комиссии на Etsy и Ebay

Размер комиссии в валюте рассчитывается по следующей формуле.

\left( P\cdot\frac{E1}{100} + E2 \right) \cdot \left( \frac{V}{100} + 1 \right)

(P * E1/100 + E2) * (V/100 + 1)

Где:

  • P — цена товара (вместе с доставкой), валюта;
  • E1 — комиссия магазина от цены товара, %;
  • E2 — фиксированная комиссия магазина, валюта;
  • V — российский НДС, %.

Примечания:

  • НДС взимается не с цены товара, а с комиссии магазина.
  • Фиксированная комиссия на Ebay равна 0.
  • Комиссия Ebay составляет 10 % от цены товара.
  • Фиксированная комиссия на Etsy составляет 0,2 доллара США и берется за публикацию товара.
  • Комиссия Etsy составляет 5 % от цены товара.

Настройка общей папки в VirtualBox

В статье приводится способ настройки общей папки, когда на виртуальной машине установлен Linux, в частности Ubuntu 18.04.

Первым делом нужно установить дополнения гостевой ОС.

Подключение образа дополнений гостевой ОС в VirtualBox
Подключаем образ диска дополнений гостевой ОС.
Запускам установщик дополнений в появившемся окне.

В настройках виртуальной машины нужно выбрать общие папки. Нужно поставить галочки «Авто-подключение» и «Создать постоянную папку.»

VirtualBox выбор общей папки

После сохранения настроек, на рабочем столе виртуальной машины появится папка с префиксом sf_. Это и есть общая папка.

Но пока в эту папку нет доступа. Чтобы доступ появился, нужно добавить своего пользователя в группу vboxsf. Это делается в терминале с помощью следующей команды.

sudo usermod -a -G vboxsf <USERNAME>

Где вместо <USERNAME>, нужно указать ваше имя пользователя.

Доступ в папку откроется после перезагрузки виртуальной машины.

С++: Типобезопасное перечисление (enum class) в unordered_map

Это статья о языке программирования C++.

Элементы обычного перечисление (enum) запросто могут применяться в качестве ключа в unordered_map. Следующий пример показывает, как сопоставить элемент перечисления с текстовым значением.

#include <string>
#include <iostream>
#include <unordered_map>

enum Color { Red, Blue, Green, };

int main()
{
    std::unordered_map<int, std::string> colors {
        {Red, "Red"},
        {Blue, "Blue"},
        {Green, "Green"},
    };
    
    std::cout << colors.at(Red) << std::endl;
}

Выполнить код.

Этот пример выведет в консоль слово «Red». Заметьте, что тип ключа — int.

Такое перечисление не типобезопасно и устарело. Язык C++11 предоставляет типобезопасные перечисления (enum class). У такого перечисления для доступа к элементам надо указывать имя перечисления.

Ниже приведен пример типобезопасного перечисления.

enum class Month
{
    January,
    February,
    March,
    April,
    May,
    June,
    July,
    August,
    September,
    October,
    November,
    December,
};

Чтобы получить доступ к элементу January, нужно написать Month::January.

Элементы такого перечисления можно использовать в аналогичном unordered_map, но только с явным привидением типа с помощью static_cast. Пример:

int main()
{
    std::unordered_map<int, std::string> colors{
        {static_cast<int>(Month::January), "January"},
        {static_cast<int>(Month::February), "February"},
    };
    
    std::cout << colors.at(static_cast<int>(Month::January)) << std::endl;
}

Использование static_cast делает код громоздким.

Код ниже показывает, как создать unordered_map, у которого в качестве ключа элементы типобезопасного перечисления, и где не требуется приведение типа.

#include <string>
#include <iostream>
#include <unordered_map>

struct EnumClassHash
{
    template <typename T>
    std::size_t operator()(T t) const
    {
        return static_cast<std::size_t>(t);
    }
};

enum class Month
{
    January,
    February,
    March,
    April,
    May,
    June,
    July,
    August,
    September,
    October,
    November,
    December,
};

int main()
{
    std::unordered_map<Month, std::string, EnumClassHash> months{
        {Month::January,   "January"},
        {Month::February,  "February"},
        {Month::March,     "March"},
        {Month::April,     "April"},
        {Month::May,       "May"},
        {Month::June,      "June"},
        {Month::July,      "July"},
        {Month::August,    "August"},
        {Month::September, "September"},
        {Month::October,   "October"},
        {Month::November,  "November"},
        {Month::December,  "December"},
    };
    
    std::cout << months.at(Month::January) << std::endl;
}

Выполнить код.

Ключевую роль здесь играет класс EnumClassHash. Он указывается в качестве шаблонного параметра при объявлении unordered_map. Этот класс возвращает хеш от элемента перечисления, при чем делает это максимально эффективным способом. В качестве хеша выступает значение самого элемента перечисления.

Таким образом можно создавать сколько угодно unordered_map c различными перечислениями, используя один единственный класс EnumClassHash. Иначе пришлось бы в пространстве имен std определять хеш-функцию для каждого перечисления.

Данный способ почерпнут в одном вопросе на StackOverflow.

Быстрая ручная нарезка провода МГТФ

Установка Time Doctor на Ubuntu 18.04

UPD: Статья более не актуальна. Вы можете скачать Time Doctor с офиального сайта.

На данный момент нет версии Time Doctor для недавно вышедшей Ubuntu 18.04.

В инструкции приведен способ установки Time Doctor для Ubuntu 16.04 на Ubuntu 18.04. Все действия выполняются в командной строке.

    1. Добавим репозитории от Ubuntu 16.04. Для этого создадим и откроем файл /etc/apt/sources.list.d/ubuntu16_04.list следующей командой:
      sudo nano /etc/apt/sources.list.d/ubuntu16_04.list
    2. Вставим в файл следующий список репозиториев:
      deb http://ru.archive.ubuntu.com/ubuntu/ xenial main restricted
      deb http://ru.archive.ubuntu.com/ubuntu/ xenial-updates main restricted
      deb http://ru.archive.ubuntu.com/ubuntu/ xenial universe
      deb http://ru.archive.ubuntu.com/ubuntu/ xenial-updates universe
      deb http://ru.archive.ubuntu.com/ubuntu/ xenial multiverse
      deb http://ru.archive.ubuntu.com/ubuntu/ xenial-updates multiverse
      deb http://ru.archive.ubuntu.com/ubuntu/ xenial-backports main restricted universe multiverse
      deb http://security.ubuntu.com/ubuntu xenial-security main restricted
      deb http://security.ubuntu.com/ubuntu xenial-security universe
      deb http://security.ubuntu.com/ubuntu xenial-security multiverse
      
    3. Сохраним файл комбинацией клавиш Ctrl+O и закроем комбинацией Ctrl+X.
    4. Обновим базу пакетов следующей командой:
      sudo apt update
    5. Установим зависимости следующей командой:
      sudo apt install libssl1.0-dev libx11-xcb1 libxcb1 libssl1.0.0 libqtcore4 libqtgui4 libqt4-dbus libqt4-network libqt4-sql libqt4-sql-sqlite libqt4-svg libqt4-xml libqt4-xmlpatterns gksu gdebi libjpeg8 libpng12-0 libcv2.4 libxcb-record0
      
    6. Качаем Time Doctor для Ubuntu 16.04 c официального сайта.
    7. Устанавливаем скаченный пакет следующей командой (название файла можем отличаться):
      sudo dpkg -i timedoctorlite_2.3.49-14ubuntu16.04_amd64.deb
    8. Пакет должен успешно установиться.
    9. Запускаем Time Doctor и проверяем, что все работает. Запустить можно следующей командой (если у вас Lite-версия):
      timedoctorlite
    10. Восстанавливаем исходное состояние пакетов в системе
      sudo rm /etc/apt/sources.list.d/ubuntu16_04.list
      sudo apt update
    11. Ставим лайк статье, если она оказалась полезной. Или пишем в комментариях, что у вас не получилось.

Получение пользовательского токена от eBay

В статье описывается:

  • Взаимодействие продавца с сайтом приложения и с сайтом eBay для предоставления приложению токена.
  • Получение токена приложением.
    1. Продавец заходит на сайт приложения и нажимает кнопку “Войти” или иным способом сообщает приложению, что намеревается им воспользоваться.
    2. Приложение отправляет к eBay запрос GetSessionID, в котором указывает URL для перенаправления. Приложение получает в ответ SessionID, который будет идентифицировать продавца, когда он войдет на eBay. Примеры запроса GetSessionID.
    3. Приложение перенаправляет пользователя на страницу входа eBay. URL этой страницы формируется с использованием SessionID и URL для перенаправления. Формат формируемого URL следующий:
      • Боевой URL:
        https://signin.ebay.com/ws/eBayISAPI.dll?SignIn&RuName=YourRUnameHere&SessID=YourSessionIDHere
      • URL песочницы:
        https://signin.sandbox.ebay.com/ws/eBayISAPI.dll?SignIn&RuName=YourRUnameHere&SessID=YourSessionIDHere
    4. Продавец входит на eBay.
      Форма входа eBay
    5. eBay перенаправляет продавца на форму подтверждения, чтобы он дал согласие на предоставление доступа приложению. Вид формы определяется настройками.
    6. Когда продавец кликает кнопку “I agree”, eBay перенаправляет его по адресу, который указан в настройках в поле “Your auth accepted URL”.
    7. Когда продавец попадает по этому адресу, приложение посылает к eBay запрос FetchToken, содержащий SessionID, и в ответ получает токен. Примеры запроса FetchToken. Это один из немногих запросов, который требует учетные данные приложения. То есть, чтобы сделать запрос, приложение должно добавить в HTTP-заголовок следующие данные: App ID, Dev ID и Cert ID.
      Для большинства других запросов учетные данные не требуются. Вместо них приложение добавляет токен в RequesterCredentials. Если используется SOAP, то RequesterCredentials должен быть в заголовке SOAP. Если используется XML, то RequesterCredentials включается в тело запроса. Дополнительные сведения см. в разделе Security на странице Making a Trading API Call.
    8. Запрос FetchToken возвращает приложению пользовательский токен продавца и срок годности токена. Приложение сохраняет эти данные для дальнейшего использования.
    9. Приложение делает запрос GeteBayOfficialTime, чтобы проверить новый токен.

Ссылки

  1. Оригинальная статья Getting a Token for a User.