Политика конфиденциальностиКонтактыО сайтеОтзывыGitHubDonate
© EVILEG 2015-2018
Рекомендует хостинг
TIMEWEB

Qt Linux - Урок 001. Автозапуск Qt приложения под Linux

Qt, Linux, Ubuntu, autorun, автозапуск

Поговорим, о том, как добавить в 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

a
21 сентября 2018 г. 9:08

Спасибо за статью!

Пример рабочий! Со своим проектом тоже получилось!


Наткнулся на эту статью когда решал задачу запуска Qt app с помощью .

Когда пробовал с помощью получилось запустить простой проект Qt с QCoreApplication. Т.е. без gui.

Для этого оказалось достаточно создать файл (в моем случае) в /etc/systemd/system/

[Unit]
Description=qt_console_app service desription

[Service]
ExecStart=/home/user/cpp_examples/build/build_qt_console_app/qt_console_app
Restart=always

[Install]
WantedBy=graphical.target

И запустить:


Но если хочу запускать проект Qt с gui - не получается!

С помощью видно ошибку:

QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-root'
сен 21 11:29:44 debian systemd-demo[11389]: qt.qpa.screen: QXcbConnection: Could not connect to display
сен 21 11:29:44 debian systemd-demo[11389]: Could not connect to any X display.

Пытался играться с переменными DISPLAY и с Xauthority. Но воз и ныне там.

Только что на линуксовой форуме прочитал, что не для приложений с gui. Там советуют пользоваться средствами автозапуска. Это, скорее-всего, и есть тема данной статьи, которая сработало.

Не подскажете, может ли есть какой-то путь, хитрости, чтобы, всё-таки, запустить проект Qt с GUI с помощью ?


И второй вопрос. Через пробовал в том числе потому что нужен рестарт приложения, если упадет. Там всего-лишь дописывается одна строчка в вышеприведенный файл.

И с помощью Вашего подхода можно ли как-то дописать авторестарт при падение программы?

21 сентября 2018 г. 9:24

Если я вас правильно понял, то авторестарт сюда дописывается  QString autorunContent.
Не могли бы вы не выделять пока слова жирным текстом, в комментариях сломан парсинг тегов, завтра буду чинить. Поэтому съедаются жирные слова.

a
24 сентября 2018 г. 14:40

Не могли бы подробнее рассказать об этой возможности? Я докопался до запросов Desktop Entry Files + restart, но до сих пор не найду autorunContent, о котором Вы писали...

24 сентября 2018 г. 14:42

Ну я имел ввиду, что дописать в коде вот сюда то, о чём вы говорили про рестарт

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");
a
24 сентября 2018 г. 14:47

Просто сейчас правлю сам файл example.desktop. Пытаюсь понять какую пару key=value мне нужно дописать.

24 сентября 2018 г. 14:55

Если честно, то я не уверен, что это вообще можно реализовать через *.desktop файл. Я сделал предположение на основе того, что вы сказали про *.desktop и рестарт.

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

Например я использую supervisor для автостарта сервисов сайта. Поэтому перезагрузка скриптов сайта у меня делается через killall. Грубовато, но supervisor ещё ни разу не подводил.



a
24 сентября 2018 г. 15:00

Не могли бы дать ссылку на пример? Какое-то рабочее использование. Т.е. у меня есть Qt Gui App, которое я бы хотел запускать при старте системы и в случае, если оно грохнется. Если о чем Вы говорите это поможет сделать, не могли бы просвятить в виде ссылки или примерного направление копания))

24 сентября 2018 г. 15:09

А вот здесь у меня есть пример использования supervisor.

https://evileg.com/ru/post/3/

Вся статья вам там не интересна, интересен только шаг с настройкой supervisor. Он получается будет у вас как зависимость к вашему приложению, но вопрос зависимостей - это уже отдельная тема для разговора. В данном случае к самому программированию supervisor отношения не имеет. Это настройка демона.


a
27 сентября 2018 г. 15:07

Спасибо! На данный момент выбор пал в сторону скрипта с бесконечным циклом, перегружающим программу при падение.

Здесь подробнее описал.

Комментарии

Только авторизованные пользователи могут оставлять комментарии.
Пожалуйста, Авторизуйтесь или Зарегистрируйтесь
m
19 декабря 2018 г. 10:37
maintumanov

Qt - Тест 001. Сигналы и слоты

  • Результат:68баллов,
  • Очки рейтинга-1
ИН
18 декабря 2018 г. 17:37
Игорь Носач

C++ - Тест 003. Условия и циклы

  • Результат:64баллов,
  • Очки рейтинга-1
ИН
18 декабря 2018 г. 17:22
Игорь Носач

C++ - Тест 003. Условия и циклы

  • Результат:35баллов,
  • Очки рейтинга-10
Последние комментарии
V
15 декабря 2018 г. 2:06
Vlad15007

Спасибо большое!Очень помогли!
11 декабря 2018 г. 21:01
Евгений Легоцкой

Не знаю, какой-там конкретно эффект и если честно не хочется fl studio ради того, чтобы посмотреть устанавливать, но из того, что увидел в интернете. Предполагаю, что то, что вы хотите с...
V
11 декабря 2018 г. 19:25
Vlad15007

Подскажите пожалуйста ( я новичок совсем)Можно ли организовать спрайт без этого окошка (как в fl studio fruity dance)?
11 декабря 2018 г. 15:06
Евгений Легоцкой

Что интересно, если написать так from <application_name>.<module_name> import <filename> ,то PyCharm сносит крышу, если разрабатываешь в рамках проекта приложение, ко...
11 декабря 2018 г. 14:52
Илья Чичак

Тут мне тоже есть что сказать=) Сами разрабы советуют импортировать следующим образом: from <application_name> import <module_name> Стоит избегать from . import &l...;
Сейчас обсуждают на форуме
М
19 декабря 2018 г. 8:43
Михаиллл

Здравствуйте.Говорят, если подключить ICU, то в SQLite появится регистронезависемый поиск.Я нашел скомпилированный ICU по этой ссылке https://www.npcglib.org/~stathis/blog/precompiled-...
18 декабря 2018 г. 19:58
Евгений Легоцкой

ну если у вас также будет внешний ключ на Serial, то получается следующая ситуация, Movie добавлен в Serial, а Serial имеет список Movie. То есть вам playlist как таковой вовсе не нужен....
R
18 декабря 2018 г. 12:25
RED_Spider

именно так, проблема в кодировке, а именно в отсутствии шрифтов на сервере, для меня вопрос решился в CentOS 7yum install curl cabextract xorg-x11-font-utils fontconfig всем спасибо за ...
U
18 декабря 2018 г. 10:39
Unreal_man

А вот этот коннект здесь и вовсе не нужен connect(ui->ok3, &QPushButton::clicked, this, &Widget::addToText); А как же без него? ============================== ...
m
17 декабря 2018 г. 19:03
melnik10

Спасибо, попробую!
Присоединяйтесь к нам в социальных сетях

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