- 1. Структура проекта
- 2. widget.h
- 3. widget.cpp
- 4. Итог
Поговорим, о том, как добавить в Qt приложение функционал по настройке автозапуска данного приложения. Например, у нас имеется окно настроек и мы хотим сделать возможность настройки автозапуска приложения из этого диалогового окна.
В отличие от автозапуска в Windows , где можно воспользоваться QSettings и внести изменения в реестр, в Linux потребуется создать специальный исполняемый файл, который будет отвечать за автозапуск приложения при входе пользователя в операционную систему.
Допустим название проекта и соответственно название исполняемого файла будет AutorunLinux, тогда потребуется создать исполняемый файл AutorunLinux.desktop по следующему пути:
~/.config/autostart/AutorunLinux.desktop
Содержимое исполняемого файла нужно сделать аналогичным другим файлам автозапуска других приложений, чтобы гарантировано получить требуемый результат. В случае с Ubuntu Linux 15.04/15.10 содержимое файла получилось следующее:
[Desktop Entry] Type=Application Exec=/home/dekadent/QT/Projects/build-AutorunLinux-Desktop_Qt_5_5_1_GCC_64bit-Debug/AutorunLinux Hidden=false NoDisplay=false X-GNOME-Autostart-enabled=true Name[en_GB]=AutorunLinux Name=AutorunLinux Comment[en_GB]=AutorunLinux Comment=AutorunLinux
Где параметр Exec указывает путь к исполняемому файлу приложения.
Также не забудьте сделать файл исполняемым:
chmod +x ~/.config/autostart/AutorunLinux.desktop
Для того, чтобы гарантировано быть уверенным в правильности подготавливаемого содержимого файла автозапуска, рекомендую для начала добавить Ваше приложение в автозапуск с помощью стандартной утилиты Startup Applications .
Данная утилита создаст гарантированно рабочий вариант файла для Вашего приложения. После чего Вам останется только добавить содержимое через программный код с автоматической модификацией пути к исполняемому файлу приложения.
Структура проекта
Для демонстрации программного кода, предлагаю создать следующий проект, со следующим содержимым:
- AutorunLinux.pro - профайл проекта;
- widget.h - заголовочный файл главного окна приложения;
- widget.cpp - файл исходных кодов главного окна приложения;
- widget.ui - форма главного окна приложения;
- main.cpp - основной файл исходных кодов приложения.
В данном приложении будет чекбокс, по состоянию которого мы будет удалять и добавлять приложения в автозапуск при нажатии кнопки PushButton. При запуске приложения будет выскакивать сообщение, что приложение запущено. Внешний вид приложения следующий:
widget.h
В заголовочном файле из всех изменений будет только объявление слота для нажатия кнопки:
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private slots: void on_pushButton_clicked(); private: Ui::Widget *ui; }; #endif // WIDGET_H
widget.cpp
#include "widget.h" #include "ui_widget.h" #include <QMessageBox> #include <QDir> #include <QFile> #include <QTextStream> #include <QStandardPaths> Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); QMessageBox::information(this,"AutoRun","Apllication is started!"); } Widget::~Widget() { delete ui; } void Widget::on_pushButton_clicked() { // Путь к папке автозапуска QString autostartPath = QStandardPaths::standardLocations(QStandardPaths::ConfigLocation).at(0) + QLatin1String("/autostart"); /* Проверяем, существует ли директория, в которой будет храниться файл автозапуска. * А то мало ли... пользователь удалил... * */ QDir autorunDir(autostartPath); if(!autorunDir.exists()){ // Если не существует, то создаём autorunDir.mkpath(autostartPath); } QFile autorunFile(autostartPath + QLatin1String("/AutorunLinux.desktop")); /* Проверяем состояние чекбокса, если отмечен, то добавляем приложения в автозапуск. * В противном случае удаляем * */ if(ui->checkBox->isChecked()) { // Далее проверяем наличие самого файла автозапуска if(!autorunFile.exists()){ /* Далее открываем файл и записываем в него необходимые данные * с указанием пути к исполняемому файлу, с помощью QCoreApplication::applicationFilePath() * */ if(autorunFile.open(QFile::WriteOnly)){ QString autorunContent("[Desktop Entry]\n" "Type=Application\n" "Exec=" + QCoreApplication::applicationFilePath() + "\n" "Hidden=false\n" "NoDisplay=false\n" "X-GNOME-Autostart-enabled=true\n" "Name[en_GB]=AutorunLinux\n" "Name=AutorunLinux\n" "Comment[en_GB]=AutorunLinux\n" "Comment=AutorunLinux\n"); QTextStream outStream(&autorunFile); outStream << autorunContent; // Устанавливаем права доступа, в том числе и на исполнение файла, иначе автозапуск не сработает autorunFile.setPermissions(QFileDevice::ExeUser|QFileDevice::ExeOwner|QFileDevice::ExeOther|QFileDevice::ExeGroup| QFileDevice::WriteUser|QFileDevice::ReadUser); autorunFile.close(); } } } else { // Удаляем файл автозапуска if(autorunFile.exists()) autorunFile.remove(); } }
Итог
В результате работы данного кода приложение будет вносить себя в автозапуск и запускаться при входе пользователя в систему. Для проверки работоспособности, создайте с помощью приложения файл автозапуска, выйдите из системы и войдите снова (Log Out/ Log In).
Исходный код проекта: AutorunLinux
Спасибо за статью!
Пример рабочий! Со своим проектом тоже получилось!
Наткнулся на эту статью когда решал задачу запуска Qt app с помощью .
Когда пробовал с помощью получилось запустить простой проект Qt с QCoreApplication. Т.е. без gui.
Для этого оказалось достаточно создать файл (в моем случае) в /etc/systemd/system/
И запустить:
Но если хочу запускать проект Qt с gui - не получается!
С помощью видно ошибку:
Пытался играться с переменными DISPLAY и с Xauthority. Но воз и ныне там.
Только что на линуксовой форуме прочитал, что не для приложений с gui. Там советуют пользоваться средствами автозапуска. Это, скорее-всего, и есть тема данной статьи, которая сработало.
Не подскажете, может ли есть какой-то путь, хитрости, чтобы, всё-таки, запустить проект Qt с GUI с помощью ?
И второй вопрос. Через пробовал в том числе потому что нужен рестарт приложения, если упадет. Там всего-лишь дописывается одна строчка в вышеприведенный файл.
И с помощью Вашего подхода можно ли как-то дописать авторестарт при падение программы?
Если я вас правильно понял, то авторестарт сюда дописывается QString autorunContent.
Не могли бы вы не выделять пока слова жирным текстом, в комментариях сломан парсинг тегов, завтра буду чинить. Поэтому съедаются жирные слова.
Не могли бы подробнее рассказать об этой возможности? Я докопался до запросов Desktop Entry Files + restart, но до сих пор не найду autorunContent, о котором Вы писали...
Ну я имел ввиду, что дописать в коде вот сюда то, о чём вы говорили про рестарт
Просто сейчас правлю сам файл example.desktop. Пытаюсь понять какую пару key=value мне нужно дописать.
Если честно, то я не уверен, что это вообще можно реализовать через *.desktop файл. Я сделал предположение на основе того, что вы сказали про *.desktop и рестарт.
Все варианты, которые встречаются на форумах, предполагают наличие демона, который следит за тем, чтобы программа была онлайн.
Например я использую supervisor для автостарта сервисов сайта. Поэтому перезагрузка скриптов сайта у меня делается через killall. Грубовато, но supervisor ещё ни разу не подводил.
Не могли бы дать ссылку на пример? Какое-то рабочее использование. Т.е. у меня есть Qt Gui App, которое я бы хотел запускать при старте системы и в случае, если оно грохнется. Если о чем Вы говорите это поможет сделать, не могли бы просвятить в виде ссылки или примерного направление копания))
А вот здесь у меня есть пример использования supervisor.
https://evileg.com/ru/post/3/
Вся статья вам там не интересна, интересен только шаг с настройкой supervisor. Он получается будет у вас как зависимость к вашему приложению, но вопрос зависимостей - это уже отдельная тема для разговора. В данном случае к самому программированию supervisor отношения не имеет. Это настройка демона.
Спасибо! На данный момент выбор пал в сторону скрипта с бесконечным циклом, перегружающим программу при падение.
Здесь подробнее описал.
как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))