Compare commits

..

No commits in common. "master" and "0.0.6" have entirely different histories.

40 changed files with 227 additions and 1394 deletions

View File

@ -7,15 +7,11 @@ AboutDlg::AboutDlg(QWidget *parent) :
ui(new Ui::AboutDlg)
{
ui->setupUi(this);
ui->mAppIcon->setPixmap(QPixmap(":/assets/images/coffee_cup/icon_96x96"));
auto version_text = QString("Version %1.%2.%3")
.arg(QBREAK_VERSION_MAJOR)
.arg(QBREAK_VERSION_MINOR)
.arg(QBREAK_VERSION_SUFFIX);
#if defined(DEBUG)
version_text += ". Debug build.";
#endif
ui->mAppVersionLabel->setText(version_text);
}

View File

@ -23,7 +23,7 @@
</size>
</property>
<property name="windowTitle">
<string>About</string>
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>

View File

@ -0,0 +1,3 @@
URL for used image:
https://thenounproject.com/icon/coffee-break-537907/

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="1200pt" height="1200pt" version="1.1" viewBox="0 0 1200 1200" xmlns="http://www.w3.org/2000/svg">
<path d="m228 72c-9.332 0-14.488 4.707-18.375 9.375-5.1367 6.5391-7.332 15.398-4.125 23.25 18.855 47.793 10.898 59.164 0.375 85.5s-22.758 65.922-0.375 129.75c3.3164 12.883 18.977 20.988 31.5 16.5s19.121-20.566 13.5-32.625c-19.188-54.711-10.637-70.312-0.375-96s23.09-63.176 0.375-120.75c-3.4375-9.0625-12.848-14.941-22.5-15zm324 0c-9.332 0-14.488 4.707-18.375 9.375-5.1367 6.5391-7.332 15.398-4.125 23.25 18.855 47.793 10.898 59.164 0.375 85.5s-22.758 65.922-0.375 129.75c3.3164 12.883 18.977 20.988 31.5 16.5s19.121-20.566 13.5-32.625c-19.188-54.711-10.637-70.312-0.375-96s23.09-63.176 0.375-120.75c-3.4375-9.0625-12.848-14.941-22.5-15zm324 0c-9.332 0-14.488 4.707-18.375 9.375-5.1367 6.5391-7.332 15.398-4.125 23.25 18.855 47.793 10.898 59.164 0.375 85.5s-22.758 65.922-0.375 129.75c3.3164 12.883 18.977 20.988 31.5 16.5s19.121-20.566 13.5-32.625c-19.188-54.711-10.637-70.312-0.375-96s23.09-63.176 0.375-120.75c-3.4375-9.0625-12.848-14.941-22.5-15zm-782.25 360c-11.797 1.1133-21.801 12.148-21.75 24 0 304.82 77.43 453.77 174.75 624h-126.75c-13.297 0-24 10.703-24 24s10.703 24 24 24h864c13.297 0 24-10.703 24-24s-10.703-24-24-24h-126.75c25.375-44.387 49.617-87.379 71.25-132h115.5c46.531 0 84-37.469 84-84v-264c0-46.531-37.465-84-84-84h-13.125c0.69922-19.352 1.125-39.258 1.125-60 0-12.566-11.434-24-24-24h-912c-0.75-0.035156-1.5-0.035156-2.25 0zm27 48h862.5c-4.168 292.51-80.758 424.66-181.5 600h-499.5c-100.74-175.34-177.33-307.49-181.5-600zm907.5 84h15.75c24.383 0 36 11.621 36 36v264c0 24.383-11.617 36-36 36h-93.75c39.703-92.473 68.336-195.91 78-336z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@ -1,4 +1,3 @@
URL: https://ru.seaicons.com/89980/
License: https://creativecommons.org/licenses/by-sa/4.0/
Another URL: https://github.com/alecive/FlatWoken

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="1200pt" height="1200pt" version="1.1" viewBox="0 0 1200 1200" xmlns="http://www.w3.org/2000/svg">
<path d="m228 72c-9.332 0-14.488 4.707-18.375 9.375-5.1367 6.5391-7.332 15.398-4.125 23.25 18.855 47.793 10.898 59.164 0.375 85.5s-22.758 65.922-0.375 129.75c3.3164 12.883 18.977 20.988 31.5 16.5s19.121-20.566 13.5-32.625c-19.188-54.711-10.637-70.312-0.375-96s23.09-63.176 0.375-120.75c-3.4375-9.0625-12.848-14.941-22.5-15zm324 0c-9.332 0-14.488 4.707-18.375 9.375-5.1367 6.5391-7.332 15.398-4.125 23.25 18.855 47.793 10.898 59.164 0.375 85.5s-22.758 65.922-0.375 129.75c3.3164 12.883 18.977 20.988 31.5 16.5s19.121-20.566 13.5-32.625c-19.188-54.711-10.637-70.312-0.375-96s23.09-63.176 0.375-120.75c-3.4375-9.0625-12.848-14.941-22.5-15zm324 0c-9.332 0-14.488 4.707-18.375 9.375-5.1367 6.5391-7.332 15.398-4.125 23.25 18.855 47.793 10.898 59.164 0.375 85.5s-22.758 65.922-0.375 129.75c3.3164 12.883 18.977 20.988 31.5 16.5s19.121-20.566 13.5-32.625c-19.188-54.711-10.637-70.312-0.375-96s23.09-63.176 0.375-120.75c-3.4375-9.0625-12.848-14.941-22.5-15zm-782.25 360c-11.797 1.1133-21.801 12.148-21.75 24 0 304.82 77.43 453.77 174.75 624h-126.75c-13.297 0-24 10.703-24 24s10.703 24 24 24h864c13.297 0 24-10.703 24-24s-10.703-24-24-24h-126.75c25.375-44.387 49.617-87.379 71.25-132h115.5c46.531 0 84-37.469 84-84v-264c0-46.531-37.465-84-84-84h-13.125c0.69922-19.352 1.125-39.258 1.125-60 0-12.566-11.434-24-24-24h-912c-0.75-0.035156-1.5-0.035156-2.25 0zm27 48h862.5c-4.168 292.51-80.758 424.66-181.5 600h-499.5c-100.74-175.34-177.33-307.49-181.5-600zm907.5 84h15.75c24.383 0 36 11.621 36 36v264c0 24.383-11.617 36-36 36h-93.75c39.703-92.473 68.336-195.91 78-336z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -1,7 +1,7 @@
[Desktop Entry]
GenericName=App to make the breaks
Name=QBreak
Version=0.0.7
Version=0.0.6
Exec=/usr/bin/qbreak
Comment=App to make periodical breaks
Icon=qbreak

Binary file not shown.

Binary file not shown.

View File

@ -1,24 +0,0 @@
#include "audio_support.h"
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include <QSound>
extern void play_audio(const app_settings::selected_audio& item)
{
// Play audio
if (item.name != Audio_Empty && item.name != Audio_Custom)
{
// Find bundled audio
auto iter = AudioMap.find(item.name);
if (iter != AudioMap.end())
QSound::play(iter->second);
}
else
if (item.name == Audio_Custom && !item.path.isEmpty())
QSound::play(item.path);
}
#else
extern void play_audio(const app_settings::selected_audio& item)
{}
#endif

View File

@ -1,8 +0,0 @@
#ifndef __AUDIO_SUPPORT_H
#define __AUDIO_SUPPORT_H
#include "settings.h"
extern void play_audio(const app_settings::selected_audio& item);
#endif

View File

@ -64,17 +64,6 @@ static fs::path autostart_path()
void autostart::enable(const std::string& path_to_me)
{
// Ensure autostart directory exists at all
if (!fs::exists(autostart_dir()))
{
std::error_code ec;
if (!fs::create_directory(autostart_dir(), ec))
{
qDebug() << "Failed to create autostart directory. Error: " << QString::fromStdString(ec.message());
return;
}
}
// Put .desktop file to ~/.config/autostart
std::ofstream ofs(autostart_path());
if (ofs.is_open())
@ -109,21 +98,8 @@ static fs::path appmenu_install_dir()
void appmenu::install(const std::string& path_to_me)
{
auto path_to_desktop = appmenu_install_dir() / QBREAK_DESKTOP_NAME;
// Check if app is installed already.
// The code below checks for path to app; as this app is distributed as .AppImage with version numbers - every new version will trigger desktop file rewriting
std::ifstream ifs(path_to_desktop);
std::string content((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
if (content.find(path_to_me) != std::string::npos)
return;
// Remove old one
std::string uninstall_cmd = "/usr/bin/xdg-desktop-menu uninstall --novendor " + path_to_desktop.string();
system(uninstall_cmd.c_str());
// Put .desktop file to ~/.config/autostart
std::ofstream ofs(path_to_desktop);
std::ofstream ofs(appmenu_install_dir() / QBREAK_DESKTOP_NAME);
if (ofs.is_open())
{
ofs << fixup_desktop_file(read_desktop_file(), path_to_me);
@ -149,9 +125,6 @@ void appmenu::install(const std::string& path_to_me)
}
}
}
std::string install_cmd = "/usr/bin/xdg-desktop-menu install --novendor " + path_to_desktop.string();
system(install_cmd.c_str());
}
void appmenu::uninstall()

View File

@ -2,17 +2,8 @@
#define CONFIG_H
// App version
#define QBREAK_VERSION_MAJOR 0
#define QBREAK_VERSION_MINOR 1
#define QBREAK_VERSION_SUFFIX 17
// How often UI is updated - interval in seconds
#define INTERVAL_UPDATE_UI (10)
// How often progress bar is updated - interval in milliseconds
#define INTERVAL_UPDATE_PROGRESS (1000)
// How long notification is shown - in seconds
#define INTERVAL_NOTIFICATION (30)
#define QBREAK_VERSION_MAJOR 0
#define QBREAK_VERSION_MINOR 0
#define QBREAK_VERSION_SUFFIX 6
#endif // CONFIG_H

View File

@ -1,296 +0,0 @@
#include "idle_tracking.h"
#include "settings.h"
#include <cstdlib>
#if defined(TARGET_LINUX)
#include <QObject>
#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusReply>
#include <QtDBus/QDBusInterface>
// Thanks to https://stackoverflow.com/questions/222606/detecting-keyboard-mouse-activity-in-linux
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
// This requires sudo apt install libxss-dev
#include <X11/extensions/scrnsaver.h> // This can require libxss-dev to be installed
#include <dlfcn.h>
// #include <qmetatype.h>
// #include <QDBusConnection>
/*
// Prototype from stackoverflow
int get_idle_time()
{
time_t idle_time;
static XScreenSaverInfo *mit_info;
Display *display;
int screen;
mit_info = XScreenSaverAllocInfo();
if ((display = XOpenDisplay(NULL)) == NULL) {
return -1;
}
screen = DefaultScreen(display);
XScreenSaverQueryInfo(display, RootWindow(display, screen), mit_info);
idle_time = (mit_info->idle);
XFree(mit_info);
XCloseDisplay(display);
return idle_time;
}
*/
int get_idle_time_x11()
{
void* lib_xss = dlopen("libXss.so", RTLD_LAZY);
if (!lib_xss)
return 0;
void* lib_x11 = dlopen("libX11.so", RTLD_LAZY);
if (!lib_x11)
return 0;
typedef XScreenSaverInfo* (*xss_alloc_info)(void);
xss_alloc_info alloc_info = (xss_alloc_info)dlsym(lib_xss, "XScreenSaverAllocInfo");
typedef Display* (*x11_open_display)(void*);
x11_open_display open_display = (x11_open_display)dlsym(lib_x11, "XOpenDisplay");
typedef Status (*xss_query_info)( Display* /* display */,
Drawable /* drawable */,
XScreenSaverInfo* /* info */);
xss_query_info query_info = (xss_query_info)dlsym(lib_xss, "XScreenSaverQueryInfo");
typedef int (*x11_free)(void*);
x11_free free_mem = (x11_free)dlsym(lib_x11, "XFree");
typedef int (*x11_close_display)(Display* display);
x11_close_display close_display = (x11_close_display)dlsym(lib_x11, "XCloseDisplay");
time_t idle_time;
static XScreenSaverInfo *mit_info;
Display *display;
int screen;
mit_info = alloc_info();
if ((display = open_display(NULL)) == NULL) {
return -1;
}
screen = DefaultScreen(display);
query_info(display, RootWindow(display, screen), mit_info);
idle_time = (mit_info->idle);
free_mem(mit_info);
close_display(display);
dlclose(lib_xss);
dlclose(lib_x11);
return idle_time;
}
int get_idle_time_gnome()
{
auto bus = QDBusConnection::sessionBus();
if (!bus.isConnected())
return 0;
QDBusInterface interface( "org.gnome.Mutter.IdleMonitor",
"/org/gnome/Mutter/IdleMonitor/Core",
"org.gnome.Mutter.IdleMonitor");
QDBusReply<int> reply = interface.call("GetIdletime");
return reply.isValid() ? reply.value() : 0;
}
#if defined(USE_WAYLAND)
#include <wayland-client-protocol-unstable.hpp>
class kde_idle_detector
{
private:
wayland::seat_t seat;
wayland::display_t d;
wayland::org_kde_kwin_idle_t idle;
wayland::org_kde_kwin_idle_timeout_t idle_timer;
uint64_t idle_start = 0;
uint64_t idle_finish = 0;
bool active = false;
public:
kde_idle_detector()
{}
~kde_idle_detector()
{
stop();
}
// Idle timeout is in msec
void start(int idle_timeout)
{
if (active)
return;
auto registry = d.get_registry();
registry.on_global() = [&] (uint32_t name, const std::string& interface, uint32_t version)
{
if (interface == wayland::seat_t::interface_name)
registry.bind(name, this->seat, version);
else
if (interface == wayland::org_kde_kwin_idle_t::interface_name)
registry.bind(name, this->idle, version);
};
d.roundtrip();
bool has_keyboard = false, has_pointer = false;
seat.on_capabilities() = [&] (const wayland::seat_capability& capability)
{
has_keyboard = capability & wayland::seat_capability::keyboard;
has_pointer = capability & wayland::seat_capability::pointer;
};
d.roundtrip();
idle_timer = idle.get_idle_timeout(seat, idle_timeout);
idle_timer.on_idle() = [&]()
{
idle_start = ::time(nullptr);
};
idle_timer.on_resumed() = [&]()
{
idle_finish = ::time(nullptr);
};
active = true;
}
void stop()
{
if (!active)
return;
active = false;
idle_timer.release();
seat.release();
}
// Return idle time in microseconds
int get_idle_time() const
{
if (idle_start > idle_finish)
{
return (::time(nullptr) - idle_start) * 1000;
}
return 0;
}
};
kde_idle_detector kde_idle;
int get_idle_time_kde_wayland()
{
// Ensure idle detector runs
kde_idle.start(1);
return kde_idle.get_idle_time();
}
#endif
static bool Warning_X11InWayland = false;
int get_idle_time_dynamically()
{
const char* wl_display = std::getenv("WAYLAND_DISPLAY");
// const char* x11_display = std::getenv("DISPLAY");
#if defined(USE_WAYLAND)
if (wl_display)
{
const char* desktop_name = std::getenv("XDG_SESSION_DESKTOP");
if (!desktop_name)
return 0;
if (strcmp(desktop_name, "KDE") == 0)
return get_idle_time_kde_wayland();
else
if (strcmp(desktop_name, "GNOME") == 0)
return get_idle_time_gnome();
else
return 0;
}
else
return get_idle_time_x11();
#else
// Restrict to X11
if (wl_display)
{
// One time error message
if (!Warning_X11InWayland) {
qDebug() << "Wayland is found, but app built for X11 only. Idle tracking is not supported.";
Warning_X11InWayland = true;
}
return 0;
}
return get_idle_time_x11();
#endif
}
#endif
#if defined(TARGET_WINDOWS)
// To handle Windows case later
// https://stackoverflow.com/questions/8820615/how-to-check-in-c-if-the-system-is-active
/*
#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>
#include <iostream>
// do something after 10 minutes of user inactivity
static const unsigned int idle_milliseconds = 60*10*1000;
// wait at least an hour between two runs
static const unsigned int interval = 60*60*1000;
int main() {
LASTINPUTINFO last_input;
BOOL screensaver_active;
// main loop to check if user has been idle long enough
for (;;) {
if ( !GetLastInputInfo(&last_input)
|| !SystemParametersInfo(SPI_GETSCREENSAVERACTIVE, 0,
&screensaver_active, 0))
{
std::cerr << "WinAPI failed!" << std::endl;
return ERROR_FAILURE;
}
if (last_input.dwTime < idle_milliseconds && !screensaver_active) {
// user hasn't been idle for long enough
// AND no screensaver is running
Sleep(1000);
continue;
}
// user has been idle at least 10 minutes
do_something();
// done. Wait before doing the next loop.
Sleep(interval);
}
}
*/
#endif

View File

@ -1,7 +0,0 @@
#ifndef __IDLE_TRACKING_H
#define __IDLE_TRACKING_H
// Returns the idle time in milliseconds
extern int get_idle_time();
extern int get_idle_time_dynamically();
#endif

View File

@ -6,67 +6,17 @@
#include <QCommandLineParser>
#include <QTranslator>
#include <QFileInfo>
#include <QDateTime>
#if defined(TARGET_LINUX)
# include <syslog.h>
#endif
// Handler for Qt log messages that sends output to syslog as well as standard error.
void SyslogMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
Q_UNUSED(context)
std::string timePrefix = QDateTime::currentDateTime().toString().toStdString();
QByteArray localMsg = msg.toLocal8Bit();
switch (type) {
case QtDebugMsg:
fprintf(stderr, "debug: %s %s\n", timePrefix.c_str(), localMsg.constData());
#if defined(TARGET_LINUX)
syslog(LOG_DEBUG, "debug: %s", localMsg.constData());
#endif
break;
case QtInfoMsg:
fprintf(stderr, "info: %s %s\n", timePrefix.c_str(), localMsg.constData());
#if defined(TARGET_LINUX)
syslog(LOG_INFO, "info: %s", localMsg.constData());
#endif
break;
case QtWarningMsg:
fprintf(stderr, "warning: %s %s\n", timePrefix.c_str(), localMsg.constData());
#if defined(TARGET_LINUX)
syslog(LOG_WARNING, "warning: %s", localMsg.constData());
#endif
break;
case QtCriticalMsg:
fprintf(stderr, "critical: %s %s\n", timePrefix.c_str(), localMsg.constData());
#if defined(TARGET_LINUX)
syslog(LOG_CRIT, "critical: %s", localMsg.constData());
#endif
break;
case QtFatalMsg:
fprintf(stderr, "fatal: %s %s\n", timePrefix.c_str(), localMsg.constData());
#if defined(TARGET_LINUX)
syslog(LOG_ALERT, "fatal: %s", localMsg.constData());
#endif
abort();
}
}
int main(int argc, char *argv[])
{
RunGuard guard("QBreak app - runguard");
RunGuard guard("adjfaifaif");
if ( !guard.tryToRun() )
return 0;
// Needed to enable logging to syslog or journald.
qInstallMessageHandler(SyslogMessageHandler);
QApplication app(argc, argv);
QCoreApplication::setOrganizationName("voipobjects.com");
QCoreApplication::setOrganizationDomain("voipobjects.com");
QCoreApplication::setOrganizationName("qbreak.com");
QCoreApplication::setOrganizationDomain("qbreak.com");
QCoreApplication::setApplicationName("QBreak");
QTranslator translator;
@ -77,19 +27,30 @@ int main(int argc, char *argv[])
app.setQuitOnLastWindowClosed(false);
QCommandLineParser parser;
QCommandLineOption test_1(QStringList() << "t1" << "test_1");
parser.addOption(test_1);
// Run app with break intervals & duration 60 seconds.
// This should trigger the notification in 30 seconds before breaks.
QCommandLineOption test_2(QStringList() << "t2" << "test_2");
parser.addOption(test_2);
parser.process(app);
// Put itself into app menu
auto exe_path = QCoreApplication::applicationFilePath();
const char* appimage = std::getenv("APPIMAGE");
if (appimage != nullptr)
exe_path = appimage;
appmenu::install(exe_path.toStdString());
appmenu::install(QFileInfo(argv[0]).absoluteFilePath().toStdString());
// Main window is full screen window, so start with tray icon only
MainWindow w;
w.hide();
if (parser.isSet(test_1))
w.test_1();
else
if (parser.isSet(test_2))
w.test_2();
int retcode = app.exec();
return retcode;

View File

@ -4,54 +4,24 @@
#include "settings.h"
#include "autostart.h"
#include "aboutdlg.h"
#include "config.h"
#include "audio_support.h"
#include "idle_tracking.h"
#include <QMenu>
#include <QAction>
#include <QSettings>
#include <QDebug>
#include <QDesktopWidget>
#include <QSvgGenerator>
#include <QPalette>
#include <QScreen>
#include <QWindow>
#include <QFileInfo>
#include <QCommandLineOption>
#include <QCommandLineParser>
#include <QDateTime>
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
# include <QDesktopWidget>
# include <QSound>
#endif
#include <string>
static void dispatchToMainThread(std::function<void()> callback, std::chrono::milliseconds delay = std::chrono::milliseconds(0))
{
// any thread
QTimer* timer = new QTimer();
timer->moveToThread(qApp->thread());
timer->setSingleShot(true);
timer->setInterval(delay);
QObject::connect(timer, &QTimer::timeout, [=]()
{
// main thread
callback();
timer->deleteLater();
});
QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, 0));
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Defer init call for 100 ms - attempt to resolve the problem with non working setTooltip()
dispatchToMainThread([this](){init();}, std::chrono::milliseconds(100));
init();
}
MainWindow::~MainWindow()
@ -61,7 +31,7 @@ MainWindow::~MainWindow()
delete ui;
}
/*static bool isDarkTheme()
static bool isDarkTheme()
{
// Thanks to stackoverflow ! Another idea is to use https://successfulsoftware.net/2021/03/31/how-to-add-a-dark-theme-to-your-qt-application/
auto label = QLabel("am I in the dark?");
@ -70,7 +40,7 @@ MainWindow::~MainWindow()
bool dark_theme_found = text_hsv_value > bg_hsv_value;
return dark_theme_found;
}*/
}
QIcon MainWindow::getAppIcon()
{
@ -93,6 +63,15 @@ void MainWindow::init()
// Icon
setWindowIcon(getAppIcon());
// ToDo: finish the multiple monitor support
/*QDesktopWidget *widget = QApplication::desktop();
qDebug() << "Number of screens:" << widget->screenCount();
connect(widget, &QDesktopWidget::screenCountChanged, this, [](int screenCount){});
if (widget->screenCount() > 1) {
} else if (widget->screenCount() == 1){
}*/
// Tray icon
createTrayIcon();
@ -102,99 +81,58 @@ void MainWindow::init()
// Settings dialog
mSettingsDialog = nullptr;
// No postpone attempts yet
mPostponeCount = 0;
// Timer
mTimer = new QTimer(this);
mTimer->setTimerType(Qt::TimerType::CoarseTimer);
mTimer->setSingleShot(true);
connect(mTimer, SIGNAL(timeout()), this, SLOT(onLongBreakStart()));
// Idle is not detected yet
mLastIdleMilliseconds = 0;
mNotifyTimer = new QTimer(this);
mNotifyTimer->setTimerType(Qt::TimerType::CoarseTimer);
mNotifyTimer->setSingleShot(true);
connect(mNotifyTimer, SIGNAL(timeout()), this, SLOT(onLongBreakNotify()));
// Timer to start break
mBreakStartTimer = new QTimer(this);
mBreakStartTimer->setTimerType(Qt::TimerType::CoarseTimer);
mBreakStartTimer->setSingleShot(true);
connect(mBreakStartTimer, &QTimer::timeout, this, [this](){shiftTo(AppState::Break);});
// Timer to run notification about upcoming break
mBreakNotifyTimer = new QTimer(this);
mBreakNotifyTimer->setTimerType(Qt::TimerType::CoarseTimer);
mBreakNotifyTimer->setSingleShot(true);
connect(mBreakNotifyTimer, SIGNAL(timeout()), this, SLOT(onLongBreakNotify()));
// Just update UI once per minute
mUpdateUITimer = new QTimer(this);
mUpdateUITimer->setTimerType(Qt::TimerType::CoarseTimer);
mUpdateUITimer->setSingleShot(false);
mUpdateUITimer->setInterval(std::chrono::seconds(INTERVAL_UPDATE_UI));
mUpdateUITimer->setInterval(std::chrono::minutes(1));
connect(mUpdateUITimer, SIGNAL(timeout()), this, SLOT(onUpdateUI()));
mUpdateUITimer->start();
// Timer to draw progress bar during the break
mProgressTimer = new QTimer(this);
mProgressTimer->setInterval(std::chrono::milliseconds(INTERVAL_UPDATE_PROGRESS));
mProgressTimer->setInterval(std::chrono::milliseconds(1000));
mProgressTimer->setSingleShot(false);
connect(mProgressTimer, SIGNAL(timeout()), this, SLOT(onProgress()));
connect(ui->mPostponeButton, SIGNAL(clicked()), this, SLOT(onLongBreakPostpone()));
connect(ui->mSkipButton, &QPushButton::clicked, this, [this](){shiftTo(AppState::Counting);});
// Use the latest config
applyConfig();
shiftTo(AppState::Counting);
}
static int str_to_seconds(const QString& s)
{
if (s.isEmpty())
throw std::runtime_error("Bad parameter value.");
if (s.back() == 'h')
return s.left(s.size()-1).toInt() * 3600;
if (s.back() == 'm')
return s.left(s.size()-1).toInt() * 60;
if (s.back() == 's')
return s.left(s.size()-1).toInt();
if (s.back().isDigit())
return s.toInt();
throw std::runtime_error("Bad parameter value");
// Refresh UI
onUpdateUI();
}
void MainWindow::loadConfig()
{
mAppConfig = app_settings::load();
// Check for command line options
QCommandLineParser parser;
QCommandLineOption
param_break("break-duration", "Long break duration.", "break-duration"),
param_work("work-duration", "Work time duration.", "work-duration"),
param_idle("idle-timeout", "Idle timeout.", "idle-timeout");
parser.addOptions({param_break, param_work, param_idle});
parser.process(*QApplication::instance());
if (parser.isSet(param_break))
mAppConfig.longbreak_length = str_to_seconds(parser.value(param_break));
if (parser.isSet(param_work))
mAppConfig.longbreak_interval = str_to_seconds(parser.value(param_work));
if (parser.isSet(param_idle))
mAppConfig.idle_timeout = str_to_seconds(parser.value(param_idle));
app_settings settings;
mAppConfig = settings.load();
}
void MainWindow::applyConfig()
{
if (mBreakStartTimer)
if (mTimer)
{
if (mBreakStartTimer->interval() != mAppConfig.longbreak_interval)
if (mTimer->interval() != mAppConfig.longbreak_interval)
{
mBreakStartTimer->stop();
mBreakStartTimer->setInterval(std::chrono::seconds(mAppConfig.longbreak_interval));
mBreakStartTimer->start();
mTimer->stop();
mTimer->setInterval(std::chrono::seconds(mAppConfig.longbreak_interval));
mTimer->start();
mBreakNotifyTimer->stop();
mBreakNotifyTimer->setInterval(std::chrono::seconds(mAppConfig.longbreak_interval - 30));
mBreakNotifyTimer->start();
mNotifyTimer->stop();
mNotifyTimer->setInterval(std::chrono::seconds(mAppConfig.longbreak_interval - 30));
mNotifyTimer->start();
}
}
@ -212,38 +150,46 @@ void MainWindow::applyConfig()
autostart::disable();
}
void MainWindow::schedule()
{
;
}
void MainWindow::test_1()
{
// 10 seconds test break
mAppConfig.longbreak_length = 10;
mAppConfig.longbreak_postpone_interval = 10;
mAppConfig.longbreak_interval = 10;
mAppConfig.window_on_top = true;
mAppConfig.verbose = true;
onLongBreakStart();
}
void MainWindow::test_2()
{
// 60 seconds test break
mAppConfig.longbreak_length = 60;
mAppConfig.longbreak_postpone_interval = 60;
mAppConfig.longbreak_interval = 60;
mAppConfig.window_on_top = true;
mAppConfig.verbose = true;
applyConfig();
}
void MainWindow::showMe()
{
QScreen* screen = nullptr;
if (mAppConfig.preferred_monitor == Primary_Monitor)
screen = QGuiApplication::primaryScreen();
else
{
auto screen_list = QGuiApplication::screens();
auto screen_iter = std::find_if(screen_list.begin(), screen_list.end(), [this](QScreen* s){return s->name() == mAppConfig.preferred_monitor;});
if (screen_iter != screen_list.end())
screen = *screen_iter;
}
if (screen)
{
show();
if (windowHandle())
{
windowHandle()->setScreen(screen);
setGeometry(screen->geometry());
// qDebug() << "Window moved to screen " << screen->name() + " / " + screen->model() + " " + screen->manufacturer();
}
}
// else
// qDebug() << "Screen not found!";
#if defined(DEBUG)
// Show on primary screen
QScreen* screen = QGuiApplication::primaryScreen();
showFullScreen();
//showMaximized();
#else
showFullScreen();
#endif
if (windowHandle())
{
windowHandle()->setScreen(screen);
}
}
void MainWindow::hideMe()
@ -254,12 +200,9 @@ void MainWindow::hideMe()
static QString secondsToText(int seconds)
{
if (seconds < 60)
return QObject::tr("%1 seconds").arg(seconds);
return QString("%1s").arg(seconds);
else
{
int minutes = int(float(seconds) / 60 + 0.5f);
return QObject::tr("%1 minutes").arg(minutes);
}
return QString("%1m %2s").arg(seconds / 60).arg(seconds % 60);
}
void MainWindow::createTrayIcon()
@ -286,137 +229,29 @@ void MainWindow::createTrayIcon()
mTrayIcon->setContextMenu(menu);
mTrayIcon->setIcon(getTrayIcon());
// mTrayIcon->setToolTip(AppName);
connect(mTrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
this, SLOT(onTrayIconActivated(QSystemTrayIcon::ActivationReason)));
mTrayIcon->setToolTip(AppName);
mTrayIcon->show();
}
static int msec2min(int msec)
{
float min_f = float(msec) / 1000 / 60;
return (int)(min_f + 0.5f);
}
QString state2str(AppState state)
{
switch (state)
{
case AppState::None:
return "None";
case AppState::Break:
return "Break";
case AppState::Idle:
return "Idle";
case AppState::Counting:
return "Counting";
}
return QString();
}
void MainWindow::shiftTo(AppState newState)
{
if (newState == mState)
return;
qDebug() << state2str(mState) << " -> " << state2str(newState);
switch (newState)
{
case AppState::None:
// Do nothing, app is not started
break;
case AppState::Idle:
onIdleStart();
break;
case AppState::Break:
// Break is active
onLongBreakStart();
break;
case AppState::Counting:
// Working, break is closing
if (mState == AppState::Break)
onLongBreakEnd();
else
if (mState == AppState::Idle)
onIdleEnd();
break;
}
mState = newState;
// Run deferred in main UI thread
dispatchToMainThread([this](){
onUpdateUI();
});
}
void MainWindow::onUpdateUI()
{
qDebug() << "UI timer fired.";
int idle_milliseconds = 0;
switch (mState) {
case AppState::None:
// Do nothing, app is not started
break;
case AppState::Idle:
// Detected idle, don't count this time as working
// But check - maybe idle is over
idle_milliseconds = get_idle_time_dynamically();
qDebug() << "Idle found: " << idle_milliseconds / 1000 << "s";
if (idle_milliseconds < mAppConfig.idle_timeout * 1000)
if (mTrayIcon)
{
if (mProgressTimer->isActive())
{
shiftTo(AppState::Counting);
return;
}
break;
case AppState::Break:
// Break is active
if (mTrayIcon)
// Break is in effect now
mTrayIcon->setToolTip(QString());
break;
case AppState::Counting:
// Working, break is closing
// Check maybe it is idle ?
if (!mIdleStart && mAppConfig.idle_timeout)
{
idle_milliseconds = get_idle_time_dynamically();
qDebug() << "Idle found: " << idle_milliseconds / 1000 << "s";
if (idle_milliseconds >= mAppConfig.idle_timeout * 1000)
{
shiftTo(AppState::Idle);
return;
}
}
// Update tray icon
if (mTrayIcon) {
auto remaining_milliseconds = mBreakStartTimer->remainingTime();
if (remaining_milliseconds < 60000)
mTrayIcon->setToolTip(
tr("Less than a minute left until the next break."));
else
mTrayIcon->setToolTip(
tr("There are %1 minutes left until the next break.")
.arg(msec2min(remaining_milliseconds)));
}
else
qDebug() << "No tray icon available.";
break;
if (mTimer->isActive())
{
auto remaining = std::chrono::duration_cast<std::chrono::minutes>(mTimer->remainingTimeAsDuration());
if (remaining.count() == 0)
mTrayIcon->setToolTip(tr("Less than a minute left until the next break."));
else
mTrayIcon->setToolTip(tr("There are %1 minutes left until the next break.").arg(remaining.count()));
}
}
ui->mSkipButton->setVisible(mPostponeCount > 0);
}
void MainWindow::onLongBreakNotify()
@ -424,37 +259,28 @@ void MainWindow::onLongBreakNotify()
mTrayIcon->showMessage(tr("New break"),
tr("New break will start in %1 secs").arg(Default_Notify_Length),
getAppIcon(),
INTERVAL_NOTIFICATION * 1000);
30000);
}
void MainWindow::onLongBreakStart()
{
mBreakStartTimer->stop();
mBreakNotifyTimer->stop();
qDebug() << "Stop main and notify timers.";
qDebug() << "Long break starts for " << secondsToText(mAppConfig.longbreak_postpone_interval);
// Reset idle counter
mIdleStart.reset();
// Show the button "Postpone"
ui->mPostponeButton->setText(tr("Postpone for ") + secondsToText(mAppConfig.longbreak_postpone_interval));
// Show the screen
showMe();
// Save start time
mBreakStartTime = std::chrono::steady_clock::now();
// Start progress bar
mProgressTimer->start();
// Update title immediate
onProgress();
// Refresh UI
onUpdateUI();
}
void MainWindow::onLongBreakEnd()
{
// qDebug() << "Long break ends.";
qDebug() << "Long break ends.";
// Prepare to next triggering
ui->mProgressBar->setValue(0);
@ -462,50 +288,28 @@ void MainWindow::onLongBreakEnd()
// Hide the window
hideMe();
mProgressTimer->stop();
// Start new timer
if (!mBreakStartTimer->isActive())
{
mBreakStartTimer->start(std::chrono::seconds(mAppConfig.longbreak_interval));
qDebug() << "Start main timer for " << mAppConfig.longbreak_interval << " seconds.";
}
if (!mBreakNotifyTimer->isActive())
{
mBreakNotifyTimer->start(std::chrono::seconds(mAppConfig.longbreak_interval - 30));
qDebug() << "Start notify timer for " << mAppConfig.longbreak_interval - 30 << " seconds.";
}
mTimer->start(std::chrono::seconds(mAppConfig.longbreak_interval));
mNotifyTimer->start(std::chrono::seconds(mAppConfig.longbreak_interval - 30));
// Play selected audio. When break is postponed - audio is not played
if (0 == mPostponeCount)
play_audio(mAppConfig.play_audio);
// Run script
if (!mAppConfig.script_on_break_finish.isEmpty())
{
int retcode = system(mAppConfig.script_on_break_finish.toStdString().c_str());
if (retcode != 0)
qDebug() << "User script exited with error code " << retcode;
}
// Refresh UI
onUpdateUI();
}
void MainWindow::onLongBreakPostpone()
{
// qDebug() << "Long break postponed.";
mPostponeCount++;
qDebug() << "Long break postponed.";
hideMe();
mProgressTimer->stop();
ui->mProgressBar->setValue(0);
// Start timer again
mBreakStartTimer->stop();
mBreakStartTimer->start(std::chrono::seconds(mAppConfig.longbreak_postpone_interval));
mBreakNotifyTimer->stop();
mBreakNotifyTimer->start(std::chrono::seconds(mAppConfig.longbreak_postpone_interval - 30));
mTimer->start(std::chrono::seconds(mAppConfig.longbreak_postpone_interval));
mNotifyTimer->start(std::chrono::seconds(mAppConfig.longbreak_postpone_interval - 30));
shiftTo(AppState::Counting);
// Refresh UI
onUpdateUI();
}
void MainWindow::onProgress()
@ -519,16 +323,12 @@ void MainWindow::onProgress()
if (remaining < 0)
remaining = 0;
auto text = QString("Remaining: ") + secondsToText(remaining);
ui->mRemainingLabel->setText(text);
if (mTrayIcon)
mTrayIcon->setToolTip(text);
ui->mRemainingLabel->setText(QString("Remaining: ") + secondsToText(remaining));
if (percents > 100)
{
mProgressTimer->stop();
mPostponeCount = 0; // Reset postpone counter
shiftTo(AppState::Counting);
onLongBreakEnd();
}
else
showMe();
@ -536,58 +336,10 @@ void MainWindow::onProgress()
void MainWindow::onNextBreak()
{
shiftTo(AppState::Break);
}
mTimer->stop();
mNotifyTimer->stop();
void MainWindow::onIdleStart()
{
if (mState != AppState::Counting)
return;
// Detected idle
// Timestamp when idle started
mIdleStart = std::chrono::steady_clock::now();
// How much working time remains
mRemainingWorkInterval = mBreakStartTimer->remainingTime() / 1000;
// Stop main & notify timers
mBreakStartTimer->stop();
mBreakNotifyTimer->stop();
qDebug() << "Stop main and notify timers. Remaining time is " << mRemainingWorkInterval.value() << "s";
}
void MainWindow::onIdleEnd()
{
if (mState != AppState::Idle)
return;
mIdleStart.reset();
// Update timer(s) duration
if (mRemainingWorkInterval)
{
qDebug() << "Reset main timer to " << *mRemainingWorkInterval << "s";
mBreakStartTimer->setInterval(std::chrono::seconds(*mRemainingWorkInterval));
if (mRemainingWorkInterval > INTERVAL_NOTIFICATION)
{
mBreakNotifyTimer->setInterval(std::chrono::seconds(*mRemainingWorkInterval - INTERVAL_NOTIFICATION));
qDebug() << "Reset notify timer to " << *mRemainingWorkInterval - INTERVAL_NOTIFICATION << "s";
}
mRemainingWorkInterval.reset();
}
else
{
mBreakStartTimer->setInterval(std::chrono::seconds(mAppConfig.longbreak_interval));
if (mRemainingWorkInterval > INTERVAL_NOTIFICATION)
mBreakNotifyTimer->setInterval(std::chrono::seconds(mAppConfig.longbreak_interval - INTERVAL_NOTIFICATION));
}
if (!mBreakStartTimer->isActive())
mBreakStartTimer->start();
if (!mBreakNotifyTimer->isActive())
mBreakNotifyTimer->start();
onLongBreakStart();
}
void MainWindow::onSettings()
@ -601,7 +353,6 @@ void MainWindow::onSettings()
mAppConfig = app_settings::load();
applyConfig();
mSettingsDialog->hide();
onUpdateUI();
});
connect(mSettingsDialog, &QDialog::rejected, [this]()
@ -626,20 +377,3 @@ void MainWindow::onExit()
this->close();
QApplication::exit();
}
void MainWindow::onTrayIconActivated(QSystemTrayIcon::ActivationReason reason)
{
switch(reason)
{
// Show context menu on single click
case QSystemTrayIcon::Trigger:
mTrayIcon->contextMenu()->popup(QCursor::pos());
break;
case QSystemTrayIcon::Unknown:
case QSystemTrayIcon::Context:
case QSystemTrayIcon::DoubleClick:
case QSystemTrayIcon::MiddleClick:
break;
}
}

View File

@ -6,20 +6,9 @@
#include <QSystemTrayIcon>
#include <chrono>
#include <optional>
#include "settings.h"
#include "settingsdialog.h"
// Possible app states
enum class AppState
{
None,
Counting,
Idle,
Break
};
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
@ -40,31 +29,20 @@ public:
private:
Ui::MainWindow *ui;
QTimer* mBreakStartTimer; // Main timer - triggers when break occurs
QTimer* mBreakNotifyTimer; // Timer to show notification from system tray
QTimer* mUpdateUITimer; // Update UI timer - triggers every minute to update UI and checks for idle
QTimer* mProgressTimer; // Break progress timer - updates an UI
QTimer* mTimer;
QTimer* mNotifyTimer;
QTimer* mShowNotifyTimer;
QTimer* mUpdateUITimer;
QTimer* mProgressTimer;
QSystemTrayIcon* mTrayIcon;
SettingsDialog* mSettingsDialog;
std::chrono::steady_clock::time_point mBreakStartTime;
// How much milliseconds remains for main break
std::optional<int> mRemainingWorkInterval;
app_settings::config mAppConfig;
int mPostponeCount = 0;
// Time when idle was started
std::optional<std::chrono::steady_clock::time_point> mIdleStart;
int mLastIdleMilliseconds = 0;
AppState mState = AppState::None;
void init();
void loadConfig();
void applyConfig();
void schedule();
void createTrayIcon();
void showMe();
void hideMe();
@ -74,24 +52,16 @@ private:
QIcon getAppIcon();
QIcon getTrayIcon();
// Function to switch state
void shiftTo(AppState state);
public slots:
void onUpdateUI();
void onLongBreakNotify();
void onLongBreakStart();
void onLongBreakPostpone();
void onLongBreakEnd();
void onIdleStart();
void onIdleEnd();
void onProgress();
void onNextBreak();
void onSettings();
void onAbout();
void onExit();
void onTrayIconActivated(QSystemTrayIcon::ActivationReason reason);
};
#endif // MAINWINDOW_H

View File

@ -62,11 +62,6 @@
<height>0</height>
</size>
</property>
<property name="font">
<font>
<pointsize>14</pointsize>
</font>
</property>
<property name="value">
<number>0</number>
</property>
@ -74,11 +69,6 @@
</item>
<item>
<widget class="QLabel" name="mRemainingLabel">
<property name="font">
<font>
<pointsize>14</pointsize>
</font>
</property>
<property name="text">
<string notr="true">Remaining:</string>
</property>
@ -117,7 +107,7 @@
<widget class="QPushButton" name="mPostponeButton">
<property name="minimumSize">
<size>
<width>200</width>
<width>150</width>
<height>0</height>
</size>
</property>
@ -127,62 +117,9 @@
<height>100</height>
</size>
</property>
<property name="font">
<font>
<pointsize>14</pointsize>
<underline>true</underline>
</font>
</property>
<property name="text">
<string notr="true">Postpone for 10 minutes</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_7">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item alignment="Qt::AlignHCenter">
<widget class="QPushButton" name="mSkipButton">
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>300</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<pointsize>14</pointsize>
<underline>true</underline>
</font>
</property>
<property name="text">
<string>Skip this break</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item>

View File

@ -1,7 +1,6 @@
QT += core gui svg multimedia widgets dbus
CONFIG += debug_and_release console
QT += core gui svg
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17 lrelease embed_translations
@ -10,52 +9,35 @@ CONFIG += c++17 lrelease embed_translations
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
aboutdlg.cpp \
autostart.cpp \
main.cpp \
mainwindow.cpp \
settings.cpp \
settingsdialog.cpp \
runguard.cpp \
audio_support.cpp \
idle_tracking.cpp
aboutdlg.cpp \
autostart.cpp \
main.cpp \
mainwindow.cpp \
settings.cpp \
settingsdialog.cpp \
runguard.cpp
HEADERS += \
aboutdlg.h \
autostart.h \
config.h \
mainwindow.h \
settings.h \
settingsdialog.h \
runguard.h \
audio_support.h \
idle_tracking.h
aboutdlg.h \
autostart.h \
config.h \
mainwindow.h \
settings.h \
settingsdialog.h \
runguard.h
FORMS += \
aboutdlg.ui \
mainwindow.ui \
aboutdlg.ui \
mainwindow.ui \
settingsdialog.ui
RESOURCES = qbreak.qrc
TRANSLATIONS = strings.ts strings_en.ts strings_ru.ts
unix:!macx: DEFINES += TARGET_LINUX # USE_WAYLAND
unix:!macx: DEFINES += TARGET_LINUX
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
# X11 and wayland libraries
unix:LIBS += -L/usr/X11R6/lib/ \
-lX11 -lXext -lXss -ldl
Debug: DEFINES += DEBUG
Release: DEFINES += QT_NO_DEBUG_OUTPUT
# When using wayland:
# unix:LIBS += -L/usr/local/lib \
# -lwayland-client-unstable++ -lwayland-client-extra++ -lwayland-client++

View File

@ -1,5 +1,7 @@
<RCC>
<qresource prefix="/">
<file>assets/images/app_icon_dark.png</file>
<file>assets/images/app_icon_light.png</file>
<file>assets/misc/qbreak.desktop</file>
<file>assets/images/coffee_cup/icon_16x16.png</file>
<file>assets/images/coffee_cup/icon_24x24.png</file>
@ -10,7 +12,5 @@
<file>assets/images/coffee_cup/icon_96x96.png</file>
<file>assets/images/coffee_cup/icon_128x128.png</file>
<file>assets/images/coffee_cup/icon_512x512.png</file>
<file>assets/sound/alarm-retro.wav</file>
<file>assets/sound/alarm-poehali.wav</file>
</qresource>
</RCC>

View File

@ -9,11 +9,6 @@ const QString Key_LongBreak_Length = "LongBreak_Length";
const QString Key_Window_On_Top = "Window_On_Top";
const QString Key_Verbose = "Verbose";
const QString Key_Autostart = "Autostart";
const QString Key_PreferredMonitor = "Preferred_Monitor";
const QString Key_Audio_Name = "Audio_Name";
const QString Key_Audio_Path = "Audio_Path";
const QString Key_Script = "Script";
const QString Key_Idle_Timeout = "Idle_Timeout";
void app_settings::save(const config &cfg)
{
@ -25,11 +20,6 @@ void app_settings::save(const config &cfg)
s.setValue(Key_Window_On_Top, cfg.window_on_top);
s.setValue(Key_Verbose, cfg.verbose);
s.setValue(Key_Autostart, cfg.autostart);
s.setValue(Key_PreferredMonitor, cfg.preferred_monitor);
s.setValue(Key_Audio_Name, cfg.play_audio.name);
s.setValue(Key_Audio_Path, cfg.play_audio.path);
s.setValue(Key_Script, cfg.script_on_break_finish);
s.setValue(Key_Idle_Timeout, cfg.idle_timeout);
}
app_settings::config app_settings::load()
@ -43,11 +33,5 @@ app_settings::config app_settings::load()
r.window_on_top = s.value(Key_Window_On_Top, Default_Autostart).toBool();
r.verbose = s.value(Key_Verbose, Default_Verbose).toBool();
r.autostart = s.value(Key_Autostart, Default_Autostart).toBool();
r.preferred_monitor = s.value(Key_PreferredMonitor, Default_Monitor).toString();
r.play_audio.name = s.value(Key_Audio_Name, Audio_Empty).toString();
r.play_audio.path = s.value(Key_Audio_Path, QString()).toString();
r.script_on_break_finish = s.value(Key_Script, QString()).toString();
r.idle_timeout = s.value(Key_Idle_Timeout, Default_Idle_Timeout).toInt();
return r;
}

View File

@ -2,7 +2,6 @@
#define SETTINGS_H
#include <QString>
#include <map>
// Default values in seconds
const int Default_LongBreak_Interval = 50 * 60;
@ -19,43 +18,13 @@ const bool Default_Verbose = false;
// Default autostart
const bool Default_Autostart = true;
// Default idle timeout
const int Default_Idle_Timeout = 0;
const QString Default_Monitor = "";
const QString Primary_Monitor = "[Primary]";
// Default behavior is not play any audio on break end.
const QString Audio_Empty = "None";
const QString Audio_Retro = "Retro";
const QString Audio_Gagarin = "Gagarin";
const QString Audio_Custom = "Custom...";
struct audio_item
{
QString name;
QString path;
};
const std::map<QString, QString> AudioMap {
{Audio_Retro, ":/assets/sound/alarm-retro.wav"},
{Audio_Gagarin, ":/assets/sound/alarm-poehali.wav"},
};
// Used app name
const QString AppName = "QBreak";
class app_settings
{
public:
struct selected_audio
{
QString name = Audio_Empty;
QString path;
};
struct config
{
// Seconds
@ -65,14 +34,6 @@ public:
bool window_on_top = Default_WindowOnTop;
bool verbose = Default_Verbose;
bool autostart = Default_Autostart;
QString preferred_monitor = Default_Monitor;
// This value can be path to audio file or empty or [embedded] string
selected_audio play_audio;
QString script_on_break_finish;
// Zero means "idle is not tracked". Value in seconds.
int idle_timeout = Default_Idle_Timeout;
};
static void save(const config& cfg);

View File

@ -1,14 +1,10 @@
#include "settingsdialog.h"
#include "ui_settingsdialog.h"
#include "settings.h"
#include "audio_support.h"
#include <QToolTip>
#include <QTimer>
#include <QWindow>
#include <QScreen>
#include <QFileDialog>
#include <QStandardPaths>
const QString ConversionError = "Integer value expected.";
@ -27,8 +23,6 @@ SettingsDialog::~SettingsDialog()
void SettingsDialog::init()
{
mSkipAudioChangeEvent = true;
setWindowTitle("Settings");
auto c = app_settings::load();
@ -37,87 +31,17 @@ void SettingsDialog::init()
ui->mBreakIntervalEdit->setText(QString::number(c.longbreak_interval / 60));
ui->mBreakDurationEdit->setText(QString::number(c.longbreak_length / 60));
ui->mPostponeTimeEdit->setText(QString::number(c.longbreak_postpone_interval / 60));
ui->mPreferredMonitorCombobox->addItem(Primary_Monitor, Primary_Monitor);
int found_idx = 0;
auto ql = QGuiApplication::screens();
int screen_idx = 1;
for (QScreen* s: ql)
{
ui->mPreferredMonitorCombobox->addItem(s->name() +" / " + s->model() + " " + s->manufacturer(), s->name());
if (s->name() == c.preferred_monitor)
found_idx = screen_idx;
screen_idx++;
}
ui->mPreferredMonitorCombobox->setCurrentIndex(found_idx);
// Fill audio combo box
auto audios = {Audio_Empty, Audio_Retro, Audio_Gagarin, Audio_Custom};
ui->mAudioComboBox->addItems(audios);
mCustomAudioIdx = audios.size() - 1;
// Preselect active audio
for (int i = 0; i < ui->mAudioComboBox->count(); i++)
if (ui->mAudioComboBox->itemText(i) == c.play_audio.name)
ui->mAudioComboBox->setCurrentIndex(i);
mCustomAudioPath = c.play_audio.path;
ui->mScriptEdit->setText(c.script_on_break_finish);
connect(ui->mAudioComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onAudioIndexChanged(int)));
// Idle timeout
ui->mIdleTimeoutSpinbox->setValue(c.idle_timeout / 60);
mSkipAudioChangeEvent = false;
}
void SettingsDialog::accept()
{
auto c = app_settings::load();
c.autostart = ui->mAutostartCheckbox->isChecked();
c.window_on_top = ui->mWindowOnTopCheckbox->isChecked();
c.longbreak_interval = ui->mBreakIntervalEdit->text().toInt() * 60;
c.longbreak_length = ui->mBreakDurationEdit->text().toInt() * 60;
c.longbreak_postpone_interval = ui->mPostponeTimeEdit->text().toInt() * 60;
c.preferred_monitor = ui->mPreferredMonitorCombobox->currentData().toString();
c.script_on_break_finish = ui->mScriptEdit->text();
c.play_audio.name = ui->mAudioComboBox->currentText();
if (c.play_audio.name == Audio_Custom)
c.play_audio.path = mCustomAudioPath;
c.idle_timeout = ui->mIdleTimeoutSpinbox->value() * 60;
app_settings::save(c);
emit accepted();
}
void SettingsDialog::onAudioIndexChanged(int idx)
{
if (mSkipAudioChangeEvent)
return;
if (idx == mCustomAudioIdx)
{
// Ask about path to audio file
auto home = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
auto path = QFileDialog::getOpenFileName(this, tr("Select audio file"), home, tr("Sound files(*.wav *.mp3 *.ogg)"));
if (!path.isEmpty())
{
mCustomAudioPath = path;
// ToDo: show message "audio is selected"
}
else
{
// ToDo: show message "audio is not selected"
}
}
// Play selected audio to ensure this is fine
play_audio({.name = ui->mAudioComboBox->itemText(idx), .path = mCustomAudioPath});
}

View File

@ -17,15 +17,11 @@ public:
private:
Ui::SettingsDialog *ui;
QString mCustomAudioPath;
int mCustomAudioIdx;
bool mSkipAudioChangeEvent;
void init();
private slots:
void accept();
void onAudioIndexChanged(int idx);
};
#endif // SETTINGSDIALOG_H

View File

@ -6,14 +6,14 @@
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>359</height>
<width>746</width>
<height>167</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>746</width>
<height>220</height>
<height>167</height>
</size>
</property>
<property name="maximumSize">
@ -94,64 +94,16 @@
<item row="3" column="1">
<widget class="QLineEdit" name="mBreakDurationEdit"/>
</item>
<item row="5" column="0">
<item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Postpone time (minutes)</string>
</property>
</widget>
</item>
<item row="5" column="1">
<item row="4" column="1">
<widget class="QLineEdit" name="mPostponeTimeEdit"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Preferred monitor</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QComboBox" name="mPreferredMonitorCombobox"/>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Audio to play when break finish</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QComboBox" name="mAudioComboBox">
<property name="editable">
<bool>false</bool>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Shell command to run when break finish</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLineEdit" name="mScriptEdit"/>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Idle timeout in minutes (zero means no idle tracking)</string>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QSpinBox" name="mIdleTimeoutSpinbox">
<property name="suffix">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>

View File

@ -4,27 +4,22 @@
<context>
<name>AboutDlg</name>
<message>
<location filename="aboutdlg.ui" line="26"/>
<source>About</source>
<translation type="unfinished"></translation>
<location filename="aboutdlg.ui" line="20"/>
<source>Dialog</source>
<translation></translation>
</message>
<message>
<location filename="aboutdlg.ui" line="32"/>
<source>TextLabel</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="aboutdlg.ui" line="48"/>
<source>QBreak.</source>
<translation></translation>
</message>
<message>
<location filename="aboutdlg.ui" line="67"/>
<location filename="aboutdlg.ui" line="51"/>
<source>Version</source>
<translation></translation>
</message>
<message>
<location filename="aboutdlg.ui" line="86"/>
<location filename="aboutdlg.ui" line="70"/>
<source>App to make breaks in work. Thanks to the authors of similar apps which inspired me to make this one.</source>
<translation></translation>
</message>
@ -37,69 +32,51 @@
<translation></translation>
</message>
<message>
<location filename="mainwindow.ui" line="181"/>
<source>Skip this break</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainwindow.cpp" line="228"/>
<location filename="mainwindow.cpp" line="213"/>
<source>Start next break</source>
<translation></translation>
</message>
<message>
<location filename="mainwindow.cpp" line="231"/>
<location filename="mainwindow.cpp" line="216"/>
<source>Settings</source>
<translation></translation>
</message>
<message>
<location filename="mainwindow.cpp" line="234"/>
<location filename="mainwindow.cpp" line="219"/>
<source>About</source>
<translation></translation>
</message>
<message>
<location filename="mainwindow.cpp" line="237"/>
<location filename="mainwindow.cpp" line="222"/>
<source>Exit</source>
<translation></translation>
</message>
<message>
<location filename="mainwindow.cpp" line="265"/>
<location filename="mainwindow.cpp" line="250"/>
<source>Less than a minute left until the next break.</source>
<translation></translation>
</message>
<message>
<location filename="mainwindow.cpp" line="267"/>
<location filename="mainwindow.cpp" line="252"/>
<source>There are %1 minutes left until the next break.</source>
<translation></translation>
</message>
<message>
<location filename="mainwindow.cpp" line="276"/>
<location filename="mainwindow.cpp" line="259"/>
<source>New break</source>
<translation></translation>
</message>
<message>
<location filename="mainwindow.cpp" line="277"/>
<location filename="mainwindow.cpp" line="260"/>
<source>New break will start in %1 secs</source>
<translation></translation>
</message>
<message>
<location filename="mainwindow.cpp" line="286"/>
<location filename="mainwindow.cpp" line="269"/>
<source>Postpone for </source>
<translation></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="mainwindow.cpp" line="218"/>
<source>%1 seconds</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="mainwindow.cpp" line="220"/>
<source>%1 minutes</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsDialog</name>
<message>
@ -132,30 +109,5 @@
<source>Postpone time (minutes)</source>
<translation></translation>
</message>
<message>
<location filename="settingsdialog.ui" line="110"/>
<source>Preferred monitor</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="settingsdialog.ui" line="120"/>
<source>Audio to play when break finish</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="settingsdialog.ui" line="134"/>
<source>Command to run when break finish</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="settingsdialog.cpp" line="104"/>
<source>Select audio file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="settingsdialog.cpp" line="104"/>
<source>Sound files(*.wav *.mp3 *.ogg)</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -4,27 +4,22 @@
<context>
<name>AboutDlg</name>
<message>
<location filename="aboutdlg.ui" line="26"/>
<source>About</source>
<translation>About</translation>
</message>
<message>
<location filename="aboutdlg.ui" line="32"/>
<source>TextLabel</source>
<location filename="aboutdlg.ui" line="20"/>
<source>Dialog</source>
<translation></translation>
</message>
<message>
<location filename="aboutdlg.ui" line="48"/>
<location filename="aboutdlg.ui" line="32"/>
<source>QBreak.</source>
<translation></translation>
</message>
<message>
<location filename="aboutdlg.ui" line="67"/>
<location filename="aboutdlg.ui" line="51"/>
<source>Version</source>
<translation></translation>
</message>
<message>
<location filename="aboutdlg.ui" line="86"/>
<location filename="aboutdlg.ui" line="70"/>
<source>App to make breaks in work. Thanks to the authors of similar apps which inspired me to make this one.</source>
<translation></translation>
</message>
@ -37,69 +32,51 @@
<translation></translation>
</message>
<message>
<location filename="mainwindow.ui" line="181"/>
<source>Skip this break</source>
<translation></translation>
</message>
<message>
<location filename="mainwindow.cpp" line="228"/>
<location filename="mainwindow.cpp" line="213"/>
<source>Start next break</source>
<translation></translation>
</message>
<message>
<location filename="mainwindow.cpp" line="231"/>
<location filename="mainwindow.cpp" line="216"/>
<source>Settings</source>
<translation></translation>
</message>
<message>
<location filename="mainwindow.cpp" line="234"/>
<location filename="mainwindow.cpp" line="219"/>
<source>About</source>
<translation></translation>
</message>
<message>
<location filename="mainwindow.cpp" line="237"/>
<location filename="mainwindow.cpp" line="222"/>
<source>Exit</source>
<translation></translation>
</message>
<message>
<location filename="mainwindow.cpp" line="265"/>
<location filename="mainwindow.cpp" line="250"/>
<source>Less than a minute left until the next break.</source>
<translation></translation>
</message>
<message>
<location filename="mainwindow.cpp" line="267"/>
<location filename="mainwindow.cpp" line="252"/>
<source>There are %1 minutes left until the next break.</source>
<translation></translation>
</message>
<message>
<location filename="mainwindow.cpp" line="276"/>
<location filename="mainwindow.cpp" line="259"/>
<source>New break</source>
<translation></translation>
</message>
<message>
<location filename="mainwindow.cpp" line="277"/>
<location filename="mainwindow.cpp" line="260"/>
<source>New break will start in %1 secs</source>
<translation></translation>
</message>
<message>
<location filename="mainwindow.cpp" line="286"/>
<location filename="mainwindow.cpp" line="269"/>
<source>Postpone for </source>
<translation></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="mainwindow.cpp" line="218"/>
<source>%1 seconds</source>
<translation></translation>
</message>
<message>
<location filename="mainwindow.cpp" line="220"/>
<source>%1 minutes</source>
<translation></translation>
</message>
</context>
<context>
<name>SettingsDialog</name>
<message>
@ -132,30 +109,5 @@
<source>Postpone time (minutes)</source>
<translation></translation>
</message>
<message>
<location filename="settingsdialog.ui" line="110"/>
<source>Preferred monitor</source>
<translation></translation>
</message>
<message>
<location filename="settingsdialog.ui" line="120"/>
<source>Audio to play when break finish</source>
<translation>Audio to play when break finish</translation>
</message>
<message>
<location filename="settingsdialog.ui" line="134"/>
<source>Command to run when break finish</source>
<translation>Command to run when break finish</translation>
</message>
<message>
<location filename="settingsdialog.cpp" line="104"/>
<source>Select audio file</source>
<translation>Select audio file</translation>
</message>
<message>
<location filename="settingsdialog.cpp" line="104"/>
<source>Sound files(*.wav *.mp3 *.ogg)</source>
<translation>Sound files(*.wav *.mp3 *.ogg)</translation>
</message>
</context>
</TS>

View File

@ -4,31 +4,22 @@
<context>
<name>AboutDlg</name>
<message>
<location filename="aboutdlg.ui" line="20"/>
<source>Dialog</source>
<translation type="vanished">О программе</translation>
</message>
<message>
<location filename="aboutdlg.ui" line="26"/>
<source>About</source>
<translation>О программе</translation>
</message>
<message>
<location filename="aboutdlg.ui" line="32"/>
<source>TextLabel</source>
<translation> </translation>
</message>
<message>
<location filename="aboutdlg.ui" line="48"/>
<source>QBreak.</source>
<translation>QBreak.</translation>
</message>
<message>
<location filename="aboutdlg.ui" line="67"/>
<location filename="aboutdlg.ui" line="51"/>
<source>Version</source>
<translation>Версия</translation>
</message>
<message>
<location filename="aboutdlg.ui" line="86"/>
<location filename="aboutdlg.ui" line="70"/>
<source>App to make breaks in work. Thanks to the authors of similar apps which inspired me to make this one.</source>
<translation>Приложение чтобы устраивать себе перерывы в работе. Спасибо авторам аналогичных приложений которые вдохновили меня сделать это приложение.</translation>
</message>
@ -41,69 +32,51 @@
<translation>QBreak</translation>
</message>
<message>
<location filename="mainwindow.ui" line="181"/>
<source>Skip this break</source>
<translation>Пропустить</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="228"/>
<location filename="mainwindow.cpp" line="213"/>
<source>Start next break</source>
<translation>Начать перерыв</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="231"/>
<location filename="mainwindow.cpp" line="216"/>
<source>Settings</source>
<translation>Настройки</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="234"/>
<location filename="mainwindow.cpp" line="219"/>
<source>About</source>
<translation>О программе</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="237"/>
<location filename="mainwindow.cpp" line="222"/>
<source>Exit</source>
<translation>Выход</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="265"/>
<location filename="mainwindow.cpp" line="250"/>
<source>Less than a minute left until the next break.</source>
<translation>До перерыва осталось меньше минуты.</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="267"/>
<location filename="mainwindow.cpp" line="252"/>
<source>There are %1 minutes left until the next break.</source>
<translation>Осталось %1 минут до перерыва.</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="276"/>
<location filename="mainwindow.cpp" line="259"/>
<source>New break</source>
<translation>Скоро перерыв</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="277"/>
<location filename="mainwindow.cpp" line="260"/>
<source>New break will start in %1 secs</source>
<translation>Перерыв начнется через %1 секунд.</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="286"/>
<location filename="mainwindow.cpp" line="269"/>
<source>Postpone for </source>
<translation>Отложить на</translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="mainwindow.cpp" line="218"/>
<source>%1 seconds</source>
<translation>%1 секунд</translation>
</message>
<message>
<location filename="mainwindow.cpp" line="220"/>
<source>%1 minutes</source>
<translation>%1 минут</translation>
</message>
</context>
<context>
<name>SettingsDialog</name>
<message>
@ -136,21 +109,6 @@
<source>Postpone time (minutes)</source>
<translation>Насколько можно отложить перерыв (в минутах)</translation>
</message>
<message>
<location filename="settingsdialog.ui" line="110"/>
<source>Preferred monitor</source>
<translation>Предпочитаемый монитор</translation>
</message>
<message>
<location filename="settingsdialog.ui" line="120"/>
<source>Audio to play when break finish</source>
<translation>Проигрывать по окончанию перерыва</translation>
</message>
<message>
<location filename="settingsdialog.ui" line="134"/>
<source>Command to run when break finish</source>
<translation>Запускать по окончанию перерыва</translation>
</message>
<message>
<source>Break interval (seconds)</source>
<translation type="vanished">Промежуток между перерывами в секундах</translation>
@ -163,15 +121,5 @@
<source>Postpone time (seconds)</source>
<translation type="vanished">На сколько можно отложить перерыв (в секундах)</translation>
</message>
<message>
<location filename="settingsdialog.cpp" line="104"/>
<source>Select audio file</source>
<translation>Выбрать аудиозапись</translation>
</message>
<message>
<location filename="settingsdialog.cpp" line="104"/>
<source>Sound files(*.wav *.mp3 *.ogg)</source>
<translation>Аудио файлы (*.wav *.mp3 *.ogg)</translation>
</message>
</context>
</TS>

View File

@ -1,12 +1,5 @@
#!/bin/bash
#export QTDIR=/home/$USER/qt/5.12.10/gcc_64
export QTDIR=/home/$USER/qt5/5.12.12/gcc_64
# I use this script on two different hosts so there are logic to find proper Qt installation
export QT_HOME=/home/$USER/tools/qt/5.15.2/gcc_64
if [ ! -d "$QT_HOME" ] ; then
export QT_HOME=/home/$USER/tools/qt/5.15.2/gcc_64
fi
# Build .appimage
/usr/bin/python3 build_qbreak.py release
/usr/bin/python3 build_qbreak.py

View File

@ -1,12 +0,0 @@
#!/bin/bash
# I use this script on two different hosts so there are logic to find proper Qt installation
export QT_HOME=/home/$USER/tools/qt/5.15.2/gcc_64
if [ ! -d "$QT_HOME" ] ; then
export QT_HOME=/home/$USER/qt/5.15.2/gcc_64
fi
# Build .appimage
/usr/bin/python3 build_qbreak.py debug

View File

@ -1,12 +0,0 @@
#!/bin/bash
# I use this script on two different hosts so there are logic to find proper Qt installation
export QT_HOME=/home/$USER/tools/qt/6.8.0/gcc_64
if [ ! -d "$QT_HOME" ] ; then
export QT_HOME=/home/$USER/tools/qt/6.8.0/gcc_64
fi
# Build .appimage
/usr/bin/python3 build_qbreak.py release

View File

@ -1,12 +0,0 @@
#!/bin/bash
# I use this script on two different hosts so there are logic to find proper Qt installation
export QT_HOME=/home/$USER/tools/qt/6.8.0/gcc_64
if [ ! -d "$QT_HOME" ] ; then
export QT_HOME=/home/$USER/tools/qt/6.8.0/gcc_64
fi
# Build .appimage
/usr/bin/python3 build_qbreak.py debug

View File

@ -5,7 +5,6 @@ import platform
import os
import shutil
import glob
import sys
from pathlib import Path
import multiprocessing
import build_utils
@ -14,8 +13,8 @@ EXIT_OK = 0
EXIT_ERROR = 1
# Check if Qt is specified
if not 'QT_HOME' in os.environ:
print('Qt location must be set in QT_HOME environment variable.')
if not 'QTDIR' in os.environ:
print('Qt location must be set in QTDIR environment variable.')
exit(1)
# Prepare build directory
@ -29,10 +28,6 @@ version_suffix = build_utils.get_version(app_source / 'config.h', 'QBREAK_VERSIO
version_minor = build_utils.get_version(app_source / 'config.h', 'QBREAK_VERSION_MINOR')
version_major = build_utils.get_version(app_source / 'config.h', 'QBREAK_VERSION_MAJOR')
if version_major is None or version_minor is None or version_suffix is None:
print('App version is not found, exiting.')
exit(EXIT_OK)
app_version = f'{version_major}.{version_minor}.{version_suffix}'
print (f'Found QBreak version: {app_version}')
@ -42,20 +37,13 @@ os.chdir(build_dir)
if platform.system() == 'Linux':
print('Linux detected')
print('Configure...')
qmake_path = Path(os.environ['QT_HOME']) / 'bin' / 'qmake'
retcode = os.system(f'{qmake_path} ../../app')
retcode = os.system('qmake ../../app')
if retcode != 0:
print(f'qmake call failed with code {retcode}')
exit(retcode)
# Check the requested type of build - debug or release
build_type = 'release'
if len(sys.argv) == 2:
build_type = sys.argv[1]
print('Build...')
retcode = os.system(f'make {build_type} -j4')
retcode = os.system('make -j4')
if retcode != 0:
print(f'make call failed with code {retcode}')
exit(retcode)
@ -81,10 +69,10 @@ if platform.system() == 'Linux':
'-always-overwrite',
'-verbose=2',
'-appimage',
'-qmake=' + os.environ['QT_HOME'] + '/bin/qmake',
'-qmake=' + os.environ['QTDIR'] + '/bin/qmake',
'-unsupported-allow-new-glibc',
#'-no-translations',
'-extra-plugins=iconengines,platformthemes/libqgtk3.so,platforms/libqxcb.so'
'-extra-plugins=iconengines,platformthemes/libqgtk3.so'
]
desktop_path = 'appimage_dir/usr/share/applications/qbreak.desktop'

View File

@ -80,7 +80,7 @@ def get_version(path, name):
with codecs.open(path, mode='r', encoding='utf-8') as f:
t = f.read()
pattern = r"#define " + name + r"[\s]+(?P<number>[\d]+)"
pattern = r"#define " + name + r" (?P<number>[\d]+)"
m = re.search(pattern=pattern, string=t, flags=re.MULTILINE)
if m is not None:
return m.group("number")

Binary file not shown.