2 |
andreas |
1 |
/*
|
21 |
andreas |
2 |
* Copyright (C) 2020, 2021 by Andreas Theofilu <andreas@theosys.at>
|
2 |
andreas |
3 |
*
|
|
|
4 |
* This program is free software; you can redistribute it and/or modify
|
|
|
5 |
* it under the terms of the GNU General Public License as published by
|
|
|
6 |
* the Free Software Foundation; either version 3 of the License, or
|
|
|
7 |
* (at your option) any later version.
|
|
|
8 |
*
|
|
|
9 |
* This program is distributed in the hope that it will be useful,
|
|
|
10 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
11 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
12 |
* GNU General Public License for more details.
|
|
|
13 |
*
|
|
|
14 |
* You should have received a copy of the GNU General Public License
|
|
|
15 |
* along with this program; if not, write to the Free Software Foundation,
|
|
|
16 |
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
17 |
*/
|
|
|
18 |
|
21 |
andreas |
19 |
/** @file tqtmain.cpp
|
|
|
20 |
* @brief Implements the surface of the application.
|
|
|
21 |
*
|
|
|
22 |
* This file implements the callback functions of the suface. While the most
|
|
|
23 |
* classes are drawing the elements, the methods here take the ready elements
|
|
|
24 |
* and display them. This file makes the surface completely independent of
|
|
|
25 |
* the rest of the application which makes it easy to change the surface by
|
|
|
26 |
* any other technology.
|
|
|
27 |
*/
|
2 |
andreas |
28 |
#include <QApplication>
|
23 |
andreas |
29 |
#include <QGuiApplication>
|
14 |
andreas |
30 |
#include <QByteArray>
|
2 |
andreas |
31 |
#include <QCommandLineParser>
|
|
|
32 |
#include <QCommandLineOption>
|
9 |
andreas |
33 |
#include <QLabel>
|
2 |
andreas |
34 |
#include <QtWidgets>
|
10 |
andreas |
35 |
#include <QMouseEvent>
|
15 |
andreas |
36 |
#include <QMoveEvent>
|
5 |
andreas |
37 |
#include <QPalette>
|
9 |
andreas |
38 |
#include <QPixmap>
|
7 |
andreas |
39 |
#include <QFont>
|
|
|
40 |
#include <QFontDatabase>
|
21 |
andreas |
41 |
#include <QtMultimediaWidgets/QVideoWidget>
|
|
|
42 |
#include <QtMultimedia/QMediaPlayer>
|
|
|
43 |
#include <QtMultimedia/QMediaPlaylist>
|
24 |
andreas |
44 |
#include <QLayout>
|
21 |
andreas |
45 |
#include <QUrl>
|
13 |
andreas |
46 |
#include <QThread>
|
2 |
andreas |
47 |
|
5 |
andreas |
48 |
#include <functional>
|
14 |
andreas |
49 |
#include <mutex>
|
23 |
andreas |
50 |
#ifdef __ANDROID__
|
|
|
51 |
#include <android/log.h>
|
|
|
52 |
#endif
|
4 |
andreas |
53 |
#include "tpagemanager.h"
|
2 |
andreas |
54 |
#include "tqtmain.h"
|
|
|
55 |
#include "tconfig.h"
|
|
|
56 |
#include "tqtsettings.h"
|
5 |
andreas |
57 |
#include "tcolor.h"
|
2 |
andreas |
58 |
|
21 |
andreas |
59 |
/**
|
|
|
60 |
* @def __ANDROID__
|
|
|
61 |
* Here we've to define some extra place holders because on Android only 10
|
|
|
62 |
* place holders are defined by default. But we've a callback functions which
|
|
|
63 |
* need 13 place holders. The defination is taken from the original defination
|
|
|
64 |
* of place holders and expanded.
|
|
|
65 |
*/
|
|
|
66 |
#ifdef __ANDROID__
|
|
|
67 |
#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY)
|
|
|
68 |
_LIBCPP_FUNC_VIS extern const std::placeholders::__ph<10> _11;
|
|
|
69 |
_LIBCPP_FUNC_VIS extern const std::placeholders::__ph<10> _12;
|
|
|
70 |
_LIBCPP_FUNC_VIS extern const std::placeholders::__ph<10> _13;
|
22 |
andreas |
71 |
//_LIBCPP_FUNC_VIS extern const std::placeholders::__ph<10> _14;
|
|
|
72 |
//_LIBCPP_FUNC_VIS extern const std::placeholders::__ph<10> _15;
|
|
|
73 |
//_LIBCPP_FUNC_VIS extern const std::placeholders::__ph<10> _16;
|
|
|
74 |
//_LIBCPP_FUNC_VIS extern const std::placeholders::__ph<10> _17;
|
|
|
75 |
//_LIBCPP_FUNC_VIS extern const std::placeholders::__ph<10> _18;
|
|
|
76 |
//_LIBCPP_FUNC_VIS extern const std::placeholders::__ph<10> _19;
|
|
|
77 |
//_LIBCPP_FUNC_VIS extern const _std::placeholders::_ph<10> _20;
|
21 |
andreas |
78 |
#else
|
|
|
79 |
/* _LIBCPP_INLINE_VAR */ constexpr std::placeholders::__ph<11> _11{};
|
|
|
80 |
/* _LIBCPP_INLINE_VAR */ constexpr std::placeholders::__ph<12> _12{};
|
|
|
81 |
/* _LIBCPP_INLINE_VAR */ constexpr std::placeholders::__ph<13> _13{};
|
22 |
andreas |
82 |
///* _LIBCPP_INLINE_VAR */ constexpr std::placeholders::__ph<14> _14{};
|
|
|
83 |
///* _LIBCPP_INLINE_VAR */ constexpr std::placeholders::__ph<15> _15{};
|
|
|
84 |
///* _LIBCPP_INLINE_VAR */ constexpr std::placeholders::__ph<16> _16{};
|
|
|
85 |
///* _LIBCPP_INLINE_VAR */ constexpr std::placeholders::__ph<17> _17{};
|
|
|
86 |
///* _LIBCPP_INLINE_VAR */ constexpr std::placeholders::__ph<18> _18{};
|
|
|
87 |
///* _LIBCPP_INLINE_VAR */ constexpr std::placeholders::__ph<19> _19{};
|
|
|
88 |
///* _LIBCPP_INLINE_VAR */ constexpr std::placeholders::__ph<20> _20{};
|
21 |
andreas |
89 |
#endif // defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY)
|
|
|
90 |
#endif
|
3 |
andreas |
91 |
|
21 |
andreas |
92 |
static TPageManager *pageManager = nullptr; //!< The pointer to the global defined main class.
|
|
|
93 |
std::mutex draw_mutex; //!< We're using threads and need to block execution sometimes
|
|
|
94 |
|
5 |
andreas |
95 |
using std::bind;
|
21 |
andreas |
96 |
using std::string;
|
5 |
andreas |
97 |
|
21 |
andreas |
98 |
/**
|
|
|
99 |
* @brief qtmain is used here as the entry point for the surface.
|
|
|
100 |
*
|
|
|
101 |
* The main entry function parses the command line parameters, if there were
|
|
|
102 |
* any and sets the basic attributes. It creates the main window and starts the
|
|
|
103 |
* application.
|
|
|
104 |
*
|
|
|
105 |
* @param argc The number of command line arguments
|
|
|
106 |
* @param argv A pointer to a 2 dimensional array containing the command
|
|
|
107 |
* line parameters.
|
|
|
108 |
* @param pmanager A pointer to the page manager class which is the main class
|
|
|
109 |
* managing everything.
|
|
|
110 |
*
|
|
|
111 |
* @return If no errors occured it returns 0.
|
|
|
112 |
*/
|
3 |
andreas |
113 |
int qtmain(int argc, char **argv, TPageManager *pmanager)
|
2 |
andreas |
114 |
{
|
31 |
andreas |
115 |
DECL_TRACER("qtmain(int argc, char **argv, TPageManager *pmanager)");
|
2 |
andreas |
116 |
|
3 |
andreas |
117 |
pageManager = pmanager;
|
|
|
118 |
|
21 |
andreas |
119 |
// Q_INIT_RESOURCE(tpanel);
|
2 |
andreas |
120 |
#ifdef Q_OS_ANDROID
|
5 |
andreas |
121 |
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
2 |
andreas |
122 |
#endif
|
|
|
123 |
|
5 |
andreas |
124 |
QApplication app(argc, argv);
|
24 |
andreas |
125 |
// Calculate the scale factor
|
|
|
126 |
if (TConfig::getScale())
|
|
|
127 |
{
|
|
|
128 |
QList<QScreen *> screens = QGuiApplication::screens();
|
|
|
129 |
QRect screenGeometry = screens.at(0)->availableGeometry();
|
|
|
130 |
double width = screenGeometry.width();
|
|
|
131 |
double height = screenGeometry.height();
|
|
|
132 |
int minWidth = pmanager->getSettings()->getWith();
|
|
|
133 |
int minHeight = pmanager->getSettings()->getHeight();
|
31 |
andreas |
134 |
MSG_INFO("Dimension of AMX screen:" << minWidth << " x " << minHeight);
|
|
|
135 |
MSG_INFO("Screen size: " << screenGeometry.width() << " x " << screenGeometry.height());
|
23 |
andreas |
136 |
|
24 |
andreas |
137 |
double scaleW = width / minWidth;
|
|
|
138 |
double scaleH = height / minHeight;
|
|
|
139 |
double scale = std::min(scaleW, scaleH);
|
26 |
andreas |
140 |
|
|
|
141 |
if (scale != 0.0)
|
|
|
142 |
{
|
|
|
143 |
pmanager->setScaleFactor(scale);
|
31 |
andreas |
144 |
MSG_INFO("Scale factor: " << scale);
|
26 |
andreas |
145 |
}
|
31 |
andreas |
146 |
|
|
|
147 |
if (scaleW != 0.0)
|
|
|
148 |
pmanager->setScaleFactorWidth(scaleW);
|
|
|
149 |
|
|
|
150 |
if (scaleH != 0.0)
|
|
|
151 |
pmanager->setScaleFactorHeight(scaleH);
|
24 |
andreas |
152 |
}
|
23 |
andreas |
153 |
|
24 |
andreas |
154 |
// Initialize the application
|
5 |
andreas |
155 |
QCoreApplication::setOrganizationName(TConfig::getProgName().c_str());
|
|
|
156 |
QCoreApplication::setApplicationName("AMX panel simulator");
|
24 |
andreas |
157 |
QCoreApplication::setApplicationVersion(VERSION_STRING());
|
5 |
andreas |
158 |
QCommandLineParser parser;
|
|
|
159 |
parser.setApplicationDescription(QCoreApplication::applicationName());
|
|
|
160 |
parser.addHelpOption();
|
|
|
161 |
parser.addVersionOption();
|
|
|
162 |
parser.process(app);
|
2 |
andreas |
163 |
|
5 |
andreas |
164 |
MainWindow mainWin;
|
22 |
andreas |
165 |
mainWin.setConfigFile(TConfig::getConfigPath() + "/" + TConfig::getConfigFileName());
|
28 |
andreas |
166 |
mainWin.setStyleSheet("QMainWindow {background: 'black';}");
|
31 |
andreas |
167 |
// mainWin.showFullScreen(); // Looses menu and control buttons on Android!
|
5 |
andreas |
168 |
mainWin.show();
|
|
|
169 |
return app.exec();
|
2 |
andreas |
170 |
}
|
|
|
171 |
|
21 |
andreas |
172 |
/**
|
|
|
173 |
* @brief MainWindow::MainWindow constructor
|
|
|
174 |
*
|
|
|
175 |
* This method is the constructor for this class. It registers the callback
|
|
|
176 |
* functions to the class TPageManager and starts the main run loop.
|
|
|
177 |
*/
|
2 |
andreas |
178 |
MainWindow::MainWindow()
|
|
|
179 |
{
|
5 |
andreas |
180 |
DECL_TRACER("MainWindow::MainWindow()");
|
2 |
andreas |
181 |
|
14 |
andreas |
182 |
pageManager->registerCallbackDB(bind(&MainWindow::_displayButton, this,
|
5 |
andreas |
183 |
std::placeholders::_1,
|
|
|
184 |
std::placeholders::_2,
|
|
|
185 |
std::placeholders::_3,
|
|
|
186 |
std::placeholders::_4,
|
|
|
187 |
std::placeholders::_5,
|
|
|
188 |
std::placeholders::_6,
|
|
|
189 |
std::placeholders::_7,
|
|
|
190 |
std::placeholders::_8));
|
|
|
191 |
|
14 |
andreas |
192 |
pageManager->registerCallbackSP(bind(&MainWindow::_setPage, this,
|
5 |
andreas |
193 |
std::placeholders::_1,
|
|
|
194 |
std::placeholders::_2,
|
|
|
195 |
std::placeholders::_3));
|
|
|
196 |
|
14 |
andreas |
197 |
pageManager->registerCallbackSSP(bind(&MainWindow::_setSubPage, this,
|
5 |
andreas |
198 |
std::placeholders::_1,
|
|
|
199 |
std::placeholders::_2,
|
|
|
200 |
std::placeholders::_3,
|
|
|
201 |
std::placeholders::_4,
|
|
|
202 |
std::placeholders::_5));
|
|
|
203 |
|
14 |
andreas |
204 |
pageManager->registerCallbackSB(bind(&MainWindow::_setBackground, this,
|
5 |
andreas |
205 |
std::placeholders::_1,
|
|
|
206 |
std::placeholders::_2,
|
|
|
207 |
std::placeholders::_3,
|
|
|
208 |
std::placeholders::_4,
|
|
|
209 |
std::placeholders::_5));
|
|
|
210 |
|
14 |
andreas |
211 |
pageManager->registerCallbackFT(bind(&MainWindow::_setText, this,
|
7 |
andreas |
212 |
std::placeholders::_1,
|
|
|
213 |
std::placeholders::_2,
|
|
|
214 |
std::placeholders::_3,
|
|
|
215 |
std::placeholders::_4,
|
|
|
216 |
std::placeholders::_5,
|
|
|
217 |
std::placeholders::_6,
|
|
|
218 |
std::placeholders::_7,
|
|
|
219 |
std::placeholders::_8,
|
|
|
220 |
std::placeholders::_9,
|
|
|
221 |
std::placeholders::_10,
|
21 |
andreas |
222 |
#ifdef __ANDROID__
|
|
|
223 |
_11,
|
|
|
224 |
_12,
|
|
|
225 |
_13));
|
|
|
226 |
#else
|
7 |
andreas |
227 |
std::placeholders::_11,
|
|
|
228 |
std::placeholders::_12,
|
|
|
229 |
std::placeholders::_13));
|
21 |
andreas |
230 |
#endif
|
7 |
andreas |
231 |
|
14 |
andreas |
232 |
pageManager->regCallDropPage(bind(&MainWindow::_dropPage, this, std::placeholders::_1));
|
|
|
233 |
pageManager->regCallDropSubPage(bind(&MainWindow::_dropSubPage, this, std::placeholders::_1));
|
21 |
andreas |
234 |
pageManager->regCallPlayVideo(bind(&MainWindow::_playVideo, this,
|
|
|
235 |
std::placeholders::_1,
|
|
|
236 |
std::placeholders::_2,
|
|
|
237 |
std::placeholders::_3,
|
|
|
238 |
std::placeholders::_4,
|
|
|
239 |
std::placeholders::_5,
|
|
|
240 |
std::placeholders::_6,
|
|
|
241 |
std::placeholders::_7,
|
|
|
242 |
std::placeholders::_8,
|
|
|
243 |
std::placeholders::_9));
|
11 |
andreas |
244 |
|
26 |
andreas |
245 |
pageManager->deployCallbacks();
|
5 |
andreas |
246 |
createActions();
|
|
|
247 |
|
2 |
andreas |
248 |
#ifndef QT_NO_SESSIONMANAGER
|
5 |
andreas |
249 |
QGuiApplication::setFallbackSessionManagementEnabled(false);
|
|
|
250 |
connect(qApp, &QGuiApplication::commitDataRequest,
|
|
|
251 |
this, &MainWindow::writeSettings);
|
2 |
andreas |
252 |
#endif
|
14 |
andreas |
253 |
|
|
|
254 |
qRegisterMetaType<size_t>("size_t");
|
|
|
255 |
qRegisterMetaType<QByteArray>("QByteArray");
|
|
|
256 |
|
15 |
andreas |
257 |
try
|
|
|
258 |
{
|
|
|
259 |
connect(this, &MainWindow::sigDisplayButton, this, &MainWindow::displayButton);
|
24 |
andreas |
260 |
/* connect(this, &MainWindow::sigDisplayButton, // same sender and signal
|
15 |
andreas |
261 |
this, // context object to break this connection
|
|
|
262 |
[this]() { // debug output
|
|
|
263 |
MSG_DEBUG("Direct? " << ((QThread::currentThread() == this->thread())?"YES":"NO"));
|
|
|
264 |
},
|
24 |
andreas |
265 |
Qt::DirectConnection); */
|
15 |
andreas |
266 |
connect(this, &MainWindow::sigSetPage, this, &MainWindow::setPage);
|
|
|
267 |
connect(this, &MainWindow::sigSetSubPage, this, &MainWindow::setSubPage);
|
|
|
268 |
connect(this, &MainWindow::sigSetBackground, this, &MainWindow::setBackground);
|
|
|
269 |
connect(this, &MainWindow::sigSetText, this, &MainWindow::setText);
|
|
|
270 |
connect(this, &MainWindow::sigDropPage, this, &MainWindow::dropPage);
|
|
|
271 |
connect(this, &MainWindow::sigDropSubPage, this, &MainWindow::dropSubPage);
|
21 |
andreas |
272 |
connect(this, &MainWindow::sigPlayVideo, this, &MainWindow::playVideo);
|
31 |
andreas |
273 |
connect(qApp, &QGuiApplication::applicationStateChanged, this, &MainWindow::appStateChanged);
|
15 |
andreas |
274 |
}
|
|
|
275 |
catch (std::exception& e)
|
|
|
276 |
{
|
|
|
277 |
MSG_ERROR("Connection error: " << e.what());
|
|
|
278 |
}
|
|
|
279 |
|
5 |
andreas |
280 |
setUnifiedTitleAndToolBarOnMac(true);
|
|
|
281 |
pageManager->run();
|
2 |
andreas |
282 |
}
|
|
|
283 |
|
21 |
andreas |
284 |
/**
|
|
|
285 |
* @brief MainWindow::closeEvent called when the application receives an exit event.
|
|
|
286 |
*
|
|
|
287 |
* If the user clicks on the exit icon or on the menu point _Exit_ this method
|
|
|
288 |
* is called. It makes sure everything is written to the configuration file
|
|
|
289 |
* and accepts the evernt.
|
|
|
290 |
*
|
|
|
291 |
* @param event The exit event
|
|
|
292 |
*/
|
2 |
andreas |
293 |
void MainWindow::closeEvent(QCloseEvent *event)
|
|
|
294 |
{
|
5 |
andreas |
295 |
DECL_TRACER("MainWindow::closeEvent(QCloseEvent *event)");
|
24 |
andreas |
296 |
#ifdef __ANDROID__
|
23 |
andreas |
297 |
__android_log_print(ANDROID_LOG_DEBUG,"tpanel","Close event; settingsChanged=%s", (settingsChanged ? "true":"false"));
|
24 |
andreas |
298 |
#endif
|
5 |
andreas |
299 |
if (settingsChanged)
|
|
|
300 |
{
|
|
|
301 |
writeSettings();
|
|
|
302 |
event->accept();
|
|
|
303 |
}
|
|
|
304 |
else
|
|
|
305 |
{
|
21 |
andreas |
306 |
prg_stopped = true;
|
|
|
307 |
MSG_TRACE("Program will stop!");
|
5 |
andreas |
308 |
event->accept();
|
|
|
309 |
}
|
2 |
andreas |
310 |
}
|
|
|
311 |
|
21 |
andreas |
312 |
/**
|
|
|
313 |
* @brief MainWindow::eventFilter filters the QEvent::MouseMove event
|
|
|
314 |
* @param obj The object where the event occured.
|
|
|
315 |
* @param event The event.
|
|
|
316 |
* @return `true` when the event should be ignored.
|
|
|
317 |
*/
|
15 |
andreas |
318 |
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
|
|
|
319 |
{
|
|
|
320 |
// DECL_TRACER("MainWindow::eventFilter(QObject *obj, QEvent *event)");
|
|
|
321 |
|
|
|
322 |
if (event->type() == QEvent::MouseMove)
|
|
|
323 |
return true; // Filter event out, i.e. stop it being handled further.
|
|
|
324 |
|
|
|
325 |
return QMainWindow::eventFilter(obj, event);
|
|
|
326 |
}
|
|
|
327 |
|
21 |
andreas |
328 |
/**
|
|
|
329 |
* @brief MainWindow::createActions creates the configuration dialog window.
|
|
|
330 |
*/
|
2 |
andreas |
331 |
void MainWindow::createActions()
|
|
|
332 |
{
|
5 |
andreas |
333 |
DECL_TRACER("MainWindow::createActions()");
|
2 |
andreas |
334 |
|
31 |
andreas |
335 |
// Add a toolbar (on the right side)
|
|
|
336 |
QToolBar *toolbar = new QToolBar(this);
|
|
|
337 |
toolbar->setAllowedAreas(Qt::RightToolBarArea);
|
|
|
338 |
|
|
|
339 |
/* QActionGroup actionGroup(this);
|
|
|
340 |
QToolButton arrowUp(this);
|
|
|
341 |
arrowUp.setArrowType(Qt::UpArrow);
|
|
|
342 |
actionGroup.addAction(arrowUp.defaultAction());
|
|
|
343 |
|
|
|
344 |
QToolButton arrowLeft(this);
|
|
|
345 |
arrowLeft.setArrowType(Qt::LeftArrow);
|
|
|
346 |
actionGroup.addAction(arrowLeft.defaultAction());
|
|
|
347 |
|
|
|
348 |
QToolButton arrowRight(this);
|
|
|
349 |
arrowRight.setArrowType(Qt::RightArrow);
|
|
|
350 |
actionGroup.addAction(arrowRight.defaultAction());
|
|
|
351 |
|
|
|
352 |
QToolButton arrowDown(this);
|
|
|
353 |
arrowDown.setArrowType(Qt::DownArrow);
|
|
|
354 |
actionGroup.addAction(arrowDown.defaultAction());
|
|
|
355 |
|
|
|
356 |
|
|
|
357 |
toolbar->addAction(QIcon(":/images/ok.png"), "Ok");
|
|
|
358 |
toolbar->addSeparator();
|
|
|
359 |
*/
|
|
|
360 |
// toolbar->addAction(QIcon(":/images/settings.png"), "Settings ...");
|
|
|
361 |
|
4 |
andreas |
362 |
// Add a menu
|
31 |
andreas |
363 |
// QMenu *editMenu = menuBar()->addMenu(tr("&Edit"));
|
2 |
andreas |
364 |
|
31 |
andreas |
365 |
// const QIcon settingsIcon = QIcon::fromTheme("document-open", QIcon(":/images/settings-configure.png"));
|
|
|
366 |
const QIcon settingsIcon = QIcon::fromTheme("document-open", QIcon(":/images/settings.png"));
|
5 |
andreas |
367 |
QAction *settingsAct = new QAction(settingsIcon, tr("&Settings..."), this);
|
|
|
368 |
settingsAct->setStatusTip(tr("Change the settings"));
|
|
|
369 |
connect(settingsAct, &QAction::triggered, this, &MainWindow::settings);
|
31 |
andreas |
370 |
toolbar->addAction(settingsAct);
|
|
|
371 |
// editMenu->addAction(settingsAct);
|
2 |
andreas |
372 |
|
5 |
andreas |
373 |
const QIcon aboutIcon = QIcon::fromTheme("document-open", QIcon(":/images/help-about.png"));
|
|
|
374 |
QAction *aboutAct = new QAction(aboutIcon, tr("&About..."), this);
|
|
|
375 |
aboutAct->setShortcuts(QKeySequence::Open);
|
|
|
376 |
aboutAct->setStatusTip(tr("About this program"));
|
|
|
377 |
connect(aboutAct, &QAction::triggered, this, &MainWindow::about);
|
31 |
andreas |
378 |
toolbar->addAction(aboutAct);
|
|
|
379 |
// editMenu->addAction(aboutAct);
|
2 |
andreas |
380 |
|
31 |
andreas |
381 |
// editMenu->addSeparator();
|
2 |
andreas |
382 |
|
5 |
andreas |
383 |
const QIcon exitIcon = QIcon::fromTheme("application-exit");
|
31 |
andreas |
384 |
// QAction *exitAct = editMenu->addAction(exitIcon, tr("E&xit"), this, &QWidget::close);
|
|
|
385 |
QAction *exitAct = toolbar->addAction(exitIcon, tr("E&xit"), this, &QWidget::close);
|
5 |
andreas |
386 |
exitAct->setShortcuts(QKeySequence::Quit);
|
|
|
387 |
exitAct->setStatusTip(tr("Exit the application"));
|
31 |
andreas |
388 |
|
|
|
389 |
addToolBar(Qt::RightToolBarArea, toolbar);
|
2 |
andreas |
390 |
}
|
|
|
391 |
|
21 |
andreas |
392 |
/**
|
|
|
393 |
* @brief MainWindow::mousePressEvent catches the event Qt::LeftButton.
|
|
|
394 |
*
|
|
|
395 |
* If the user presses the left mouse button somewhere in the main window, this
|
|
|
396 |
* method is triggered. It retrieves the position of the mouse pointer and
|
|
|
397 |
* sends it to the page manager TPageManager.
|
|
|
398 |
*
|
|
|
399 |
* @param event The event
|
|
|
400 |
*/
|
10 |
andreas |
401 |
void MainWindow::mousePressEvent(QMouseEvent* event)
|
|
|
402 |
{
|
|
|
403 |
if(event->button() == Qt::LeftButton)
|
|
|
404 |
pageManager->mouseEvent(event->x(), event->y(), true);
|
|
|
405 |
}
|
|
|
406 |
|
21 |
andreas |
407 |
/**
|
|
|
408 |
* @brief MainWindow::mouseReleaseEvent catches the event Qt::LeftButton.
|
|
|
409 |
*
|
|
|
410 |
* If the user releases the left mouse button somewhere in the main window, this
|
|
|
411 |
* method is triggered. It retrieves the position of the mouse pointer and
|
|
|
412 |
* sends it to the page manager TPageManager.
|
|
|
413 |
*
|
|
|
414 |
* @param event The event
|
|
|
415 |
*/
|
10 |
andreas |
416 |
void MainWindow::mouseReleaseEvent(QMouseEvent* event)
|
|
|
417 |
{
|
|
|
418 |
if(event->button() == Qt::LeftButton)
|
|
|
419 |
pageManager->mouseEvent(event->x(), event->y(), false);
|
|
|
420 |
}
|
|
|
421 |
|
21 |
andreas |
422 |
/**
|
|
|
423 |
* @brief MainWindow::settings initiates the configuration dialog.
|
|
|
424 |
*/
|
2 |
andreas |
425 |
void MainWindow::settings()
|
|
|
426 |
{
|
5 |
andreas |
427 |
DECL_TRACER("MainWindow::settings()");
|
2 |
andreas |
428 |
|
5 |
andreas |
429 |
TQtSettings *dlg_settings = new TQtSettings(this);
|
23 |
andreas |
430 |
int ret = dlg_settings->exec();
|
|
|
431 |
|
|
|
432 |
if (ret && dlg_settings->hasChanged())
|
|
|
433 |
writeSettings();
|
|
|
434 |
else if (!ret && dlg_settings->hasChanged())
|
|
|
435 |
{
|
|
|
436 |
TConfig cf(TConfig::getConfigPath() + "/" + TConfig::getConfigFileName());
|
|
|
437 |
}
|
2 |
andreas |
438 |
}
|
|
|
439 |
|
21 |
andreas |
440 |
/**
|
|
|
441 |
* @brief MainWindow::writeSettings Writes the settings into the configuration file.
|
|
|
442 |
*/
|
2 |
andreas |
443 |
void MainWindow::writeSettings()
|
|
|
444 |
{
|
5 |
andreas |
445 |
DECL_TRACER("MainWindow::writeSettings()");
|
23 |
andreas |
446 |
|
|
|
447 |
TConfig::saveSettings();
|
|
|
448 |
#ifdef __ANDROID__
|
|
|
449 |
__android_log_print(ANDROID_LOG_DEBUG,"tpanel","DEBUG: Wrote settings.");
|
|
|
450 |
#endif
|
2 |
andreas |
451 |
}
|
|
|
452 |
|
21 |
andreas |
453 |
/**
|
|
|
454 |
* @brief MainWindow::about displays the _about_ dialog.
|
|
|
455 |
*/
|
2 |
andreas |
456 |
void MainWindow::about()
|
|
|
457 |
{
|
5 |
andreas |
458 |
DECL_TRACER("MainWindow::about()");
|
2 |
andreas |
459 |
|
5 |
andreas |
460 |
QMessageBox::about(this, tr(std::string("About ").append(TConfig::getProgName()).c_str()),
|
|
|
461 |
tr("Simulation of an AMX G4 panel\n"
|
22 |
andreas |
462 |
"(C) Copyright 2020, 2021 by Andreas Theofilu <andreas@theosys.at>\n"
|
5 |
andreas |
463 |
"This program is under the terms of GPL version 3"));
|
2 |
andreas |
464 |
}
|
|
|
465 |
|
14 |
andreas |
466 |
/******************* Signal handling *************************/
|
|
|
467 |
|
31 |
andreas |
468 |
void MainWindow::appStateChanged(Qt::ApplicationState state)
|
|
|
469 |
{
|
|
|
470 |
DECL_TRACER("MainWindow::applicationStateChanged(Qt::ApplicationState state)");
|
|
|
471 |
|
|
|
472 |
switch (state)
|
|
|
473 |
{
|
|
|
474 |
case Qt::ApplicationSuspended:
|
|
|
475 |
MSG_DEBUG("Switched to mode SUSPEND");
|
|
|
476 |
mHasFocus = false;
|
|
|
477 |
break;
|
|
|
478 |
|
|
|
479 |
case Qt::ApplicationInactive:
|
|
|
480 |
MSG_DEBUG("Switched to mode INACTIVE");
|
|
|
481 |
mHasFocus = false;
|
|
|
482 |
break;
|
|
|
483 |
|
|
|
484 |
case Qt::ApplicationHidden:
|
|
|
485 |
MSG_DEBUG("Switched to mode HIDDEN");
|
|
|
486 |
mHasFocus = false;
|
|
|
487 |
break;
|
|
|
488 |
|
|
|
489 |
case Qt::ApplicationActive:
|
|
|
490 |
MSG_DEBUG("Switched to mode ACTIVE");
|
|
|
491 |
mHasFocus = true;
|
|
|
492 |
playShowList();
|
|
|
493 |
break;
|
|
|
494 |
}
|
|
|
495 |
}
|
|
|
496 |
|
14 |
andreas |
497 |
void MainWindow::_displayButton(ulong handle, ulong parent, unsigned char* buffer, int width, int height, int pixline, int left, int top)
|
4 |
andreas |
498 |
{
|
14 |
andreas |
499 |
DECL_TRACER("MainWindow::_displayButton(ulong handle, ulong parent, unsigned char* buffer, int width, int height, int pixline, int left, int top)");
|
|
|
500 |
|
21 |
andreas |
501 |
if (prg_stopped)
|
|
|
502 |
return;
|
|
|
503 |
|
14 |
andreas |
504 |
QByteArray buf;
|
|
|
505 |
|
|
|
506 |
if (buffer && pixline > 0)
|
|
|
507 |
{
|
|
|
508 |
size_t size = width * height * (pixline / width);
|
15 |
andreas |
509 |
MSG_DEBUG("Buffer size=" << size << ", width=" << width << ", height=" << height << ", left=" << left << ", top=" << top);
|
14 |
andreas |
510 |
buf.insert(0, (const char *)buffer, size);
|
|
|
511 |
}
|
|
|
512 |
|
15 |
andreas |
513 |
try
|
|
|
514 |
{
|
|
|
515 |
emit sigDisplayButton(handle, parent, buf, width, height, pixline, left, top);
|
|
|
516 |
}
|
|
|
517 |
catch (std::exception& e)
|
|
|
518 |
{
|
|
|
519 |
MSG_ERROR("Error triggering function \"displayButton()\": " << e.what());
|
|
|
520 |
}
|
14 |
andreas |
521 |
}
|
|
|
522 |
|
|
|
523 |
void MainWindow::_setPage(ulong handle, int width, int height)
|
|
|
524 |
{
|
|
|
525 |
DECL_TRACER("MainWindow::_setPage(ulong handle, int width, int height)");
|
|
|
526 |
|
21 |
andreas |
527 |
if (prg_stopped)
|
|
|
528 |
return;
|
|
|
529 |
|
14 |
andreas |
530 |
emit sigSetPage(handle, width, height);
|
|
|
531 |
}
|
|
|
532 |
|
|
|
533 |
void MainWindow::_setSubPage(ulong handle, int left, int top, int width, int height)
|
|
|
534 |
{
|
|
|
535 |
DECL_TRACER("MainWindow::_setSubPage(ulong handle, int left, int top, int width, int height)");
|
|
|
536 |
|
21 |
andreas |
537 |
if (prg_stopped)
|
|
|
538 |
return;
|
|
|
539 |
|
14 |
andreas |
540 |
emit sigSetSubPage(handle, left, top, width, height);
|
|
|
541 |
}
|
|
|
542 |
|
|
|
543 |
void MainWindow::_setBackground(ulong handle, unsigned char *image, size_t size, size_t rowBytes, ulong color)
|
|
|
544 |
{
|
|
|
545 |
DECL_TRACER("MainWindow::_setBackground(ulong handle, unsigned char *image, size_t size, size_t rowBytes, ulong color)");
|
|
|
546 |
|
21 |
andreas |
547 |
if (prg_stopped)
|
|
|
548 |
return;
|
|
|
549 |
|
14 |
andreas |
550 |
QByteArray buf;
|
|
|
551 |
|
|
|
552 |
if (image && size > 0)
|
|
|
553 |
buf.insert(0, (const char *)image, size);
|
|
|
554 |
|
|
|
555 |
emit sigSetBackground(handle, buf, rowBytes, color);
|
|
|
556 |
}
|
|
|
557 |
|
|
|
558 |
void MainWindow::_setText(ulong handle, const std::string& text, const std::string& font, const std::string& family, int size, int x, int y, ulong color, ulong effectColor, FONT_STYLE style, Button::TEXT_ORIENTATION ori, Button::TEXT_EFFECT effect, bool ww)
|
|
|
559 |
{
|
|
|
560 |
DECL_TRACER("MainWindow::_setText(ulong handle, const std::string& text, const std::string& font, const std::string& family, int size, int x, int y, ulong color, ulong effectColor, FONT_STYLE style, Button::TEXT_ORIENTATION ori, Button::TEXT_EFFECT effect, bool ww)");
|
|
|
561 |
|
21 |
andreas |
562 |
if (prg_stopped)
|
|
|
563 |
return;
|
|
|
564 |
|
14 |
andreas |
565 |
emit sigSetText(handle, text, font, family, size, x, y, color, effectColor, style, ori, effect, ww);
|
|
|
566 |
}
|
|
|
567 |
|
|
|
568 |
void MainWindow::_dropPage(ulong handle)
|
|
|
569 |
{
|
|
|
570 |
DECL_TRACER("MainWindow::_dropPage(ulong handle)");
|
|
|
571 |
|
|
|
572 |
emit sigDropPage(handle);
|
|
|
573 |
}
|
|
|
574 |
|
|
|
575 |
void MainWindow::_dropSubPage(ulong handle)
|
|
|
576 |
{
|
|
|
577 |
DECL_TRACER("MainWindow::_dropSubPage(ulong handle)");
|
|
|
578 |
|
|
|
579 |
emit sigDropSubPage(handle);
|
|
|
580 |
}
|
|
|
581 |
|
21 |
andreas |
582 |
void MainWindow::_playVideo(ulong handle, ulong parent, int left, int top, int width, int height, const string& url, const string& user, const string& pw)
|
|
|
583 |
{
|
|
|
584 |
DECL_TRACER("MainWindow::_playVideo(ulong handle, const string& url)");
|
|
|
585 |
|
|
|
586 |
if (prg_stopped)
|
|
|
587 |
return;
|
|
|
588 |
|
|
|
589 |
emit sigPlayVideo(handle, parent, left, top, width, height, url, user, pw);
|
|
|
590 |
}
|
|
|
591 |
|
14 |
andreas |
592 |
/******************* Draw elements *************************/
|
|
|
593 |
|
|
|
594 |
void MainWindow::displayButton(ulong handle, ulong parent, QByteArray buffer, int width, int height, int pixline, int left, int top)
|
|
|
595 |
{
|
|
|
596 |
draw_mutex.lock();
|
5 |
andreas |
597 |
DECL_TRACER("MainWindow::displayButton(ulong handle, unsigned char* buffer, size_t size, int width, int height, int pixline, int left, int top)");
|
4 |
andreas |
598 |
|
5 |
andreas |
599 |
OBJECT_t *obj = findObject(handle);
|
6 |
andreas |
600 |
OBJECT_t *par = findObject(parent);
|
|
|
601 |
MSG_DEBUG("Processing button " << handleToString(handle) << " from parent " << handleToString(parent));
|
5 |
andreas |
602 |
|
6 |
andreas |
603 |
if (!par)
|
|
|
604 |
{
|
21 |
andreas |
605 |
MSG_WARNING("Button " << handle << " has no parent (" << parent << ")! Ignoring it.");
|
14 |
andreas |
606 |
draw_mutex.unlock();
|
6 |
andreas |
607 |
return;
|
|
|
608 |
}
|
|
|
609 |
|
5 |
andreas |
610 |
if (!obj)
|
|
|
611 |
{
|
6 |
andreas |
612 |
MSG_DEBUG("Adding new object ...");
|
5 |
andreas |
613 |
obj = addObject();
|
|
|
614 |
|
|
|
615 |
if (!obj)
|
|
|
616 |
{
|
|
|
617 |
MSG_ERROR("Error creating an object!");
|
|
|
618 |
TError::setError();
|
14 |
andreas |
619 |
draw_mutex.unlock();
|
5 |
andreas |
620 |
return;
|
|
|
621 |
}
|
|
|
622 |
|
|
|
623 |
obj->type = OBJ_BUTTON;
|
|
|
624 |
obj->handle = handle;
|
|
|
625 |
obj->width = width;
|
|
|
626 |
obj->height = height;
|
|
|
627 |
obj->left = left;
|
|
|
628 |
obj->top = top;
|
6 |
andreas |
629 |
obj->object.label = new QLabel("", par->object.widget);
|
15 |
andreas |
630 |
obj->object.label->installEventFilter(this);
|
6 |
andreas |
631 |
}
|
14 |
andreas |
632 |
else
|
|
|
633 |
MSG_DEBUG("Object " << handleToString(handle) << " of type " << objectToString(obj->type) << " found!");
|
5 |
andreas |
634 |
|
6 |
andreas |
635 |
obj->object.label->setFixedSize(width, height);
|
|
|
636 |
obj->object.label->move(left, top);
|
31 |
andreas |
637 |
// obj->object.label->setScaledContents(true);
|
10 |
andreas |
638 |
obj->object.label->setAttribute(Qt::WA_TransparentForMouseEvents);
|
6 |
andreas |
639 |
MSG_DEBUG("Geometry: l:" << left << ", t:" << top << ", w:" << width << ", h:" << height);
|
|
|
640 |
|
14 |
andreas |
641 |
if (buffer.size() > 0 && pixline > 0)
|
6 |
andreas |
642 |
{
|
14 |
andreas |
643 |
MSG_DEBUG("Adding image for " << handleToString(handle) << " ...");
|
|
|
644 |
QImage img((unsigned char *)buffer.data(), width, height, pixline, QImage::Format_ARGB32);
|
6 |
andreas |
645 |
QPixmap pixmap(width, height);
|
|
|
646 |
pixmap.convertFromImage(img);
|
|
|
647 |
obj->object.label->setPixmap(pixmap);
|
5 |
andreas |
648 |
}
|
6 |
andreas |
649 |
else
|
|
|
650 |
{
|
|
|
651 |
MSG_DEBUG("No image found.");
|
|
|
652 |
}
|
5 |
andreas |
653 |
|
31 |
andreas |
654 |
if (mHasFocus)
|
|
|
655 |
obj->object.label->show();
|
|
|
656 |
else
|
|
|
657 |
{
|
|
|
658 |
if (par->type == OBJ_PAGE || par->type == OBJ_SUBPAGE)
|
|
|
659 |
mToShow.insert(std::pair<ulong, QWidget *>(par->handle, par->object.widget));
|
|
|
660 |
}
|
|
|
661 |
|
14 |
andreas |
662 |
draw_mutex.unlock();
|
4 |
andreas |
663 |
}
|
|
|
664 |
|
5 |
andreas |
665 |
void MainWindow::setPage(ulong handle, int width, int height)
|
|
|
666 |
{
|
14 |
andreas |
667 |
draw_mutex.lock();
|
5 |
andreas |
668 |
DECL_TRACER("MainWindow::setPage(ulong handle, int width, int height)");
|
4 |
andreas |
669 |
|
6 |
andreas |
670 |
QSize qs = menuBar()->sizeHint();
|
|
|
671 |
this->setMinimumSize(width, height + qs.height());
|
5 |
andreas |
672 |
OBJECT_t *obj = findObject(handle);
|
|
|
673 |
|
|
|
674 |
if (!obj)
|
|
|
675 |
{
|
|
|
676 |
obj = addObject();
|
|
|
677 |
|
|
|
678 |
if (!obj)
|
|
|
679 |
{
|
|
|
680 |
MSG_ERROR("Error crating an object for handle " << handleToString(handle));
|
|
|
681 |
TError::setError();
|
14 |
andreas |
682 |
draw_mutex.unlock();
|
5 |
andreas |
683 |
return;
|
|
|
684 |
}
|
|
|
685 |
|
|
|
686 |
obj->handle = handle;
|
|
|
687 |
obj->height = height;
|
|
|
688 |
obj->width = width;
|
|
|
689 |
obj->type = OBJ_PAGE;
|
|
|
690 |
}
|
6 |
andreas |
691 |
|
|
|
692 |
bool newBackground = false;
|
|
|
693 |
|
|
|
694 |
if (!mBackground)
|
|
|
695 |
{
|
|
|
696 |
mBackground = new QWidget();
|
|
|
697 |
mBackground->setAutoFillBackground(true);
|
31 |
andreas |
698 |
mBackground->setBackgroundRole(QPalette::Window);
|
6 |
andreas |
699 |
mBackground->setFixedSize(obj->width, obj->height);
|
31 |
andreas |
700 |
#ifndef __ANDROID__
|
10 |
andreas |
701 |
QRect rectBack = mBackground->geometry();
|
|
|
702 |
QRect rectMain = this->geometry();
|
28 |
andreas |
703 |
int avHeight = rectMain.height() - rectBack.height();
|
|
|
704 |
MSG_DEBUG("avHeight=" << avHeight);
|
|
|
705 |
pageManager->setFirstTopPixel(avHeight);
|
31 |
andreas |
706 |
#endif
|
6 |
andreas |
707 |
newBackground = true;
|
|
|
708 |
}
|
|
|
709 |
|
|
|
710 |
// By default set a transparent background
|
|
|
711 |
QPixmap pix(width, height);
|
|
|
712 |
pix.fill(QColor::fromRgba(qRgba(0,0,0,0xff)));
|
|
|
713 |
QPalette palette;
|
|
|
714 |
palette.setBrush(QPalette::Window, pix);
|
|
|
715 |
mBackground->setPalette(palette);
|
|
|
716 |
|
|
|
717 |
if (newBackground)
|
|
|
718 |
this->setCentralWidget(mBackground);
|
|
|
719 |
|
31 |
andreas |
720 |
if (mHasFocus)
|
|
|
721 |
mBackground->show();
|
|
|
722 |
else
|
|
|
723 |
mToShow.insert(std::pair<ulong, QWidget *>(handle, mBackground));
|
|
|
724 |
|
14 |
andreas |
725 |
draw_mutex.unlock();
|
5 |
andreas |
726 |
}
|
|
|
727 |
|
|
|
728 |
void MainWindow::setSubPage(ulong handle, int left, int top, int width, int height)
|
|
|
729 |
{
|
14 |
andreas |
730 |
draw_mutex.lock();
|
5 |
andreas |
731 |
DECL_TRACER("MainWindow::setSubPage(ulong handle, int left, int top, int width, int height)");
|
|
|
732 |
OBJECT_t *obj = addObject();
|
|
|
733 |
|
|
|
734 |
if (!obj)
|
|
|
735 |
{
|
|
|
736 |
MSG_ERROR("Error adding an object!");
|
|
|
737 |
TError::setError();
|
14 |
andreas |
738 |
draw_mutex.unlock();
|
5 |
andreas |
739 |
return;
|
|
|
740 |
}
|
|
|
741 |
|
|
|
742 |
obj->type = OBJ_SUBPAGE;
|
|
|
743 |
obj->handle = handle;
|
13 |
andreas |
744 |
obj->object.widget = new QWidget(centralWidget());
|
6 |
andreas |
745 |
obj->object.widget->setAutoFillBackground(true);
|
28 |
andreas |
746 |
obj->object.widget->setFixedSize(width, height);
|
|
|
747 |
obj->object.widget->move(left, top);
|
|
|
748 |
obj->left = left;
|
|
|
749 |
obj->top = top;
|
|
|
750 |
obj->width = width;
|
|
|
751 |
obj->height = height;
|
15 |
andreas |
752 |
// filter move event
|
|
|
753 |
obj->object.widget->installEventFilter(this);
|
5 |
andreas |
754 |
// By default set a transparent background
|
28 |
andreas |
755 |
QPixmap pix(width, height);
|
5 |
andreas |
756 |
pix.fill(QColor::fromRgba(qRgba(0,0,0,0xff)));
|
|
|
757 |
QPalette palette;
|
18 |
andreas |
758 |
palette.setBrush(QPalette::Window, QBrush(pix));
|
5 |
andreas |
759 |
obj->object.widget->setPalette(palette);
|
31 |
andreas |
760 |
|
|
|
761 |
// TODO: Is this realy necessary?
|
|
|
762 |
if (mHasFocus)
|
|
|
763 |
obj->object.widget->show();
|
|
|
764 |
else
|
|
|
765 |
mToShow.insert(std::pair<ulong, QWidget *>(handle, obj->object.widget));
|
|
|
766 |
|
14 |
andreas |
767 |
draw_mutex.unlock();
|
5 |
andreas |
768 |
}
|
|
|
769 |
|
14 |
andreas |
770 |
void MainWindow::setBackground(ulong handle, QByteArray image, size_t rowBytes, ulong color)
|
5 |
andreas |
771 |
{
|
14 |
andreas |
772 |
draw_mutex.lock();
|
28 |
andreas |
773 |
DECL_TRACER("MainWindow::setBackground(ulong handle, QByteArray image, size_t rowBytes, ulong color)");
|
5 |
andreas |
774 |
|
|
|
775 |
OBJECT_t *obj = findObject(handle);
|
|
|
776 |
|
|
|
777 |
if (!obj)
|
|
|
778 |
{
|
13 |
andreas |
779 |
MSG_WARNING("No object " << handleToString(handle) << " found!");
|
14 |
andreas |
780 |
draw_mutex.unlock();
|
5 |
andreas |
781 |
return;
|
|
|
782 |
}
|
|
|
783 |
|
14 |
andreas |
784 |
MSG_DEBUG("Object " << handleToString(handle) << " of type " << objectToString(obj->type) << " found!");
|
5 |
andreas |
785 |
|
6 |
andreas |
786 |
if (obj->type == OBJ_BUTTON || obj->type == OBJ_SUBPAGE)
|
5 |
andreas |
787 |
{
|
14 |
andreas |
788 |
MSG_DEBUG("Processing object " << objectToString(obj->type));
|
6 |
andreas |
789 |
QPixmap pix(obj->width, obj->height);
|
|
|
790 |
pix.fill(QColor::fromRgba(qRgba(TColor::getRed(color),TColor::getGreen(color),TColor::getBlue(color),TColor::getAlpha(color))));
|
5 |
andreas |
791 |
|
14 |
andreas |
792 |
if (image.size() > 0)
|
5 |
andreas |
793 |
{
|
18 |
andreas |
794 |
MSG_DEBUG("Setting image of size " << image.size());
|
14 |
andreas |
795 |
QImage img((unsigned char *)image.data(), obj->width, obj->height, rowBytes, QImage::Format_ARGB32);
|
6 |
andreas |
796 |
pix.convertFromImage(img);
|
|
|
797 |
}
|
|
|
798 |
|
|
|
799 |
if (obj->type == OBJ_BUTTON)
|
|
|
800 |
{
|
5 |
andreas |
801 |
obj->object.label->setPixmap(pix);
|
31 |
andreas |
802 |
|
|
|
803 |
if (mHasFocus)
|
|
|
804 |
obj->object.label->show();
|
5 |
andreas |
805 |
}
|
6 |
andreas |
806 |
else
|
5 |
andreas |
807 |
{
|
19 |
andreas |
808 |
MSG_DEBUG("Setting image as background for page " << ((handle >> 16) & 0x0000ffff));
|
5 |
andreas |
809 |
QPalette palette;
|
18 |
andreas |
810 |
palette.setBrush(QPalette::Window, QBrush(pix));
|
6 |
andreas |
811 |
obj->object.widget->setPalette(palette);
|
31 |
andreas |
812 |
|
|
|
813 |
if (mHasFocus)
|
|
|
814 |
obj->object.widget->show();
|
|
|
815 |
else
|
|
|
816 |
mToShow.insert(std::pair<ulong, QWidget *>(handle, obj->object.widget));
|
5 |
andreas |
817 |
}
|
|
|
818 |
}
|
6 |
andreas |
819 |
else if (obj->type == OBJ_PAGE)
|
5 |
andreas |
820 |
{
|
6 |
andreas |
821 |
bool newBackground = false;
|
5 |
andreas |
822 |
|
6 |
andreas |
823 |
if (!mBackground)
|
5 |
andreas |
824 |
{
|
6 |
andreas |
825 |
mBackground = new QWidget();
|
|
|
826 |
mBackground->setAutoFillBackground(true);
|
31 |
andreas |
827 |
mBackground->setBackgroundRole(QPalette::Window);
|
6 |
andreas |
828 |
mBackground->setFixedSize(obj->width, obj->height);
|
|
|
829 |
newBackground = true;
|
|
|
830 |
MSG_DEBUG("New background image added to page with size " << obj->width << " x " << obj->height);
|
5 |
andreas |
831 |
}
|
6 |
andreas |
832 |
|
|
|
833 |
QPixmap pix(obj->width, obj->height);
|
|
|
834 |
pix.fill(QColor::fromRgba(qRgba(TColor::getRed(color),TColor::getGreen(color),TColor::getBlue(color),TColor::getAlpha(color))));
|
|
|
835 |
|
14 |
andreas |
836 |
if (image.size() > 0)
|
5 |
andreas |
837 |
{
|
14 |
andreas |
838 |
QImage img((unsigned char *)image.data(), obj->width, obj->height, rowBytes, QImage::Format_ARGB32);
|
5 |
andreas |
839 |
pix.convertFromImage(img);
|
26 |
andreas |
840 |
MSG_DEBUG("Image converted. Width=" << obj->width << ", Height=" << obj->height);
|
6 |
andreas |
841 |
}
|
5 |
andreas |
842 |
|
6 |
andreas |
843 |
QPalette palette;
|
18 |
andreas |
844 |
palette.setBrush(QPalette::Window, QBrush(pix));
|
6 |
andreas |
845 |
mBackground->setPalette(palette);
|
|
|
846 |
|
|
|
847 |
if (newBackground)
|
|
|
848 |
this->setCentralWidget(mBackground);
|
|
|
849 |
|
31 |
andreas |
850 |
if (mHasFocus)
|
|
|
851 |
mBackground->show();
|
|
|
852 |
|
6 |
andreas |
853 |
MSG_DEBUG("Background set");
|
5 |
andreas |
854 |
}
|
14 |
andreas |
855 |
|
|
|
856 |
draw_mutex.unlock();
|
5 |
andreas |
857 |
}
|
|
|
858 |
|
22 |
andreas |
859 |
void MainWindow::setText(ulong handle, const std::string& text, const std::string& font, const std::string& family, int size, int x, int y, ulong color, ulong, FONT_STYLE style, Button::TEXT_ORIENTATION ori, Button::TEXT_EFFECT, bool ww)
|
7 |
andreas |
860 |
{
|
14 |
andreas |
861 |
draw_mutex.lock();
|
7 |
andreas |
862 |
DECL_TRACER("MainWindow::setText(ulong handle, const std::string& text, const std::string& font, int size, int x, int y, ulong color, ulong effectColor, FONT_STYLE style, Button::TEXT_ORIENTATION ori, Button::TEXT_EFFECT effect, bool ww)");
|
5 |
andreas |
863 |
|
7 |
andreas |
864 |
OBJECT_t *obj = findObject(handle);
|
|
|
865 |
|
|
|
866 |
if (!obj)
|
|
|
867 |
{
|
|
|
868 |
MSG_ERROR("Object " << handleToString(handle) << " not found!");
|
|
|
869 |
TError::setError();
|
14 |
andreas |
870 |
draw_mutex.unlock();
|
7 |
andreas |
871 |
return;
|
|
|
872 |
}
|
|
|
873 |
|
|
|
874 |
if (!obj->object.label)
|
|
|
875 |
{
|
|
|
876 |
MSG_ERROR("Object " << handleToString(handle) << " contains no child element!");
|
|
|
877 |
TError::setError();
|
14 |
andreas |
878 |
draw_mutex.unlock();
|
7 |
andreas |
879 |
return;
|
|
|
880 |
}
|
14 |
andreas |
881 |
|
|
|
882 |
MSG_DEBUG("Object " << handleToString(handle) << " of type " << objectToString(obj->type) << " found!");
|
|
|
883 |
|
10 |
andreas |
884 |
#if !defined(QT_DISABLE_DEPRECATED_BEFORE) || (QT_VERSION < QT_VERSION_CHECK(5, 15, 0))
|
9 |
andreas |
885 |
QPixmap pix = *obj->object.label->pixmap();
|
|
|
886 |
#else
|
7 |
andreas |
887 |
QPixmap pix = obj->object.label->pixmap(Qt::ReturnByValue);
|
9 |
andreas |
888 |
#endif
|
7 |
andreas |
889 |
// Load the font
|
|
|
890 |
int fontID = 0;
|
|
|
891 |
|
|
|
892 |
if ((fontID = QFontDatabase::addApplicationFont(font.c_str())) == -1)
|
|
|
893 |
{
|
|
|
894 |
MSG_ERROR("Font " << font << " could not be loaded!");
|
|
|
895 |
TError::setError();
|
14 |
andreas |
896 |
draw_mutex.unlock();
|
7 |
andreas |
897 |
return;
|
|
|
898 |
}
|
|
|
899 |
|
|
|
900 |
QFont ft;
|
|
|
901 |
ft.setFamily(family.c_str());
|
|
|
902 |
ft.setPointSize(size);
|
|
|
903 |
|
|
|
904 |
switch (style)
|
|
|
905 |
{
|
|
|
906 |
case FONT_BOLD: ft.setBold(true); break;
|
|
|
907 |
case FONT_ITALIC: ft.setItalic(true); break;
|
|
|
908 |
case FONT_BOLD_ITALIC:
|
|
|
909 |
ft.setBold(true);
|
|
|
910 |
ft.setItalic(true);
|
|
|
911 |
break;
|
|
|
912 |
|
|
|
913 |
default:
|
|
|
914 |
ft.setBold(false);
|
|
|
915 |
ft.setItalic(false);
|
|
|
916 |
}
|
|
|
917 |
|
|
|
918 |
QPalette palette = obj->object.label->palette();
|
|
|
919 |
palette.setColor(QPalette::WindowText, QColor::fromRgba(qRgba(TColor::getRed(color),TColor::getGreen(color),TColor::getBlue(color),TColor::getAlpha(color))));
|
|
|
920 |
obj->object.label->setPalette(palette);
|
|
|
921 |
obj->object.label->setFont(ft);
|
|
|
922 |
obj->object.label->setWordWrap(ww);
|
|
|
923 |
obj->object.label->setIndent(4);
|
|
|
924 |
|
|
|
925 |
switch (ori)
|
|
|
926 |
{
|
|
|
927 |
case Button::ORI_ABSOLUT:
|
|
|
928 |
{
|
|
|
929 |
QString pos = "<font style=\"position: absolute;left:";
|
|
|
930 |
pos.append(x);
|
|
|
931 |
pos.append(";top:");
|
|
|
932 |
pos.append(y);
|
|
|
933 |
pos.append(";>");
|
|
|
934 |
pos.append(text.c_str());
|
|
|
935 |
pos.append("</font>");
|
|
|
936 |
MSG_DEBUG("Text: " << pos.data());
|
|
|
937 |
}
|
|
|
938 |
break;
|
|
|
939 |
|
|
|
940 |
case Button::ORI_TOP_LEFT: obj->object.label->setAlignment(Qt::AlignTop | Qt::AlignLeft); break;
|
|
|
941 |
case Button::ORI_TOP_MIDDLE: obj->object.label->setAlignment(Qt::AlignTop | Qt::AlignHCenter); break;
|
|
|
942 |
case Button::ORI_TOP_RIGHT: obj->object.label->setAlignment(Qt::AlignTop | Qt::AlignRight); break;
|
|
|
943 |
case Button::ORI_CENTER_LEFT: obj->object.label->setAlignment(Qt::AlignVCenter | Qt::AlignLeft); break;
|
|
|
944 |
case Button::ORI_CENTER_MIDDLE: obj->object.label->setAlignment(Qt::AlignCenter); break;
|
|
|
945 |
case Button::ORI_CENTER_RIGHT: obj->object.label->setAlignment(Qt::AlignVCenter | Qt::AlignRight); break;
|
|
|
946 |
case Button::ORI_BOTTOM_LEFT: obj->object.label->setAlignment(Qt::AlignBottom | Qt::AlignLeft); break;
|
|
|
947 |
case Button::ORI_BOTTOM_MIDDLE: obj->object.label->setAlignment(Qt::AlignBottom | Qt::AlignHCenter); break;
|
|
|
948 |
case Button::ORI_BOTTOM_RIGHT: obj->object.label->setAlignment(Qt::AlignBottom | Qt::AlignRight); break;
|
|
|
949 |
}
|
|
|
950 |
|
|
|
951 |
obj->object.label->setText(text.c_str());
|
14 |
andreas |
952 |
draw_mutex.unlock();
|
7 |
andreas |
953 |
}
|
|
|
954 |
|
11 |
andreas |
955 |
void MainWindow::dropPage(ulong handle)
|
|
|
956 |
{
|
14 |
andreas |
957 |
draw_mutex.lock();
|
11 |
andreas |
958 |
DECL_TRACER("MainWindow::dropPage(ulong handle)");
|
7 |
andreas |
959 |
|
31 |
andreas |
960 |
removeFromShowList(handle);
|
11 |
andreas |
961 |
removeAllChilds(handle);
|
|
|
962 |
removeObject(handle);
|
|
|
963 |
|
|
|
964 |
if (mBackground)
|
|
|
965 |
{
|
|
|
966 |
delete mBackground;
|
|
|
967 |
mBackground = nullptr;
|
|
|
968 |
}
|
14 |
andreas |
969 |
|
|
|
970 |
draw_mutex.unlock();
|
11 |
andreas |
971 |
}
|
|
|
972 |
|
|
|
973 |
void MainWindow::dropSubPage(ulong handle)
|
|
|
974 |
{
|
14 |
andreas |
975 |
draw_mutex.lock();
|
11 |
andreas |
976 |
DECL_TRACER("MainWindow::dropSubPage(ulong handle)");
|
|
|
977 |
|
31 |
andreas |
978 |
removeFromShowList(handle);
|
11 |
andreas |
979 |
removeAllChilds(handle);
|
|
|
980 |
OBJECT_t *obj = findObject(handle);
|
|
|
981 |
|
|
|
982 |
if (!obj)
|
|
|
983 |
{
|
|
|
984 |
MSG_WARNING("Object " << handleToString(handle) << " does not exist. Ignoring!");
|
14 |
andreas |
985 |
draw_mutex.unlock();
|
11 |
andreas |
986 |
return;
|
|
|
987 |
}
|
|
|
988 |
|
14 |
andreas |
989 |
dropContent(obj);
|
11 |
andreas |
990 |
removeObject(handle);
|
14 |
andreas |
991 |
draw_mutex.unlock();
|
11 |
andreas |
992 |
}
|
|
|
993 |
|
21 |
andreas |
994 |
void MainWindow::playVideo(ulong handle, ulong parent, int left, int top, int width, int height, const string& url, const string& user, const string& pw)
|
|
|
995 |
{
|
|
|
996 |
draw_mutex.lock();
|
|
|
997 |
DECL_TRACER("MainWindow::playVideo(ulong handle, const string& url, const string& user, const string& pw))");
|
|
|
998 |
|
|
|
999 |
OBJECT_t *obj = findObject(handle);
|
|
|
1000 |
OBJECT_t *par = findObject(parent);
|
|
|
1001 |
MSG_DEBUG("Processing button " << handleToString(handle) << " from parent " << handleToString(parent));
|
|
|
1002 |
|
|
|
1003 |
if (!par)
|
|
|
1004 |
{
|
|
|
1005 |
MSG_WARNING("Button has no parent! Ignoring it.");
|
|
|
1006 |
draw_mutex.unlock();
|
|
|
1007 |
return;
|
|
|
1008 |
}
|
|
|
1009 |
|
|
|
1010 |
if (!obj)
|
|
|
1011 |
{
|
|
|
1012 |
MSG_DEBUG("Adding new video object ...");
|
|
|
1013 |
obj = addObject();
|
|
|
1014 |
|
|
|
1015 |
if (!obj)
|
|
|
1016 |
{
|
|
|
1017 |
MSG_ERROR("Error creating a video object!");
|
|
|
1018 |
TError::setError();
|
|
|
1019 |
draw_mutex.unlock();
|
|
|
1020 |
return;
|
|
|
1021 |
}
|
|
|
1022 |
|
|
|
1023 |
obj->type = OBJ_VIDEO;
|
|
|
1024 |
obj->handle = handle;
|
|
|
1025 |
obj->width = width;
|
|
|
1026 |
obj->height = height;
|
|
|
1027 |
obj->left = left;
|
|
|
1028 |
obj->top = top;
|
|
|
1029 |
obj->object.vwidget = new QVideoWidget(par->object.widget);
|
|
|
1030 |
obj->object.vwidget->installEventFilter(this);
|
|
|
1031 |
}
|
|
|
1032 |
else
|
|
|
1033 |
MSG_DEBUG("Object " << handleToString(handle) << " of type " << objectToString(obj->type) << " found!");
|
|
|
1034 |
|
|
|
1035 |
QMediaPlaylist *playlist = new QMediaPlaylist;
|
|
|
1036 |
QUrl qurl(url.c_str());
|
|
|
1037 |
|
|
|
1038 |
if (!user.empty())
|
|
|
1039 |
qurl.setUserName(user.c_str());
|
|
|
1040 |
|
|
|
1041 |
if (!pw.empty())
|
|
|
1042 |
qurl.setPassword(pw.c_str());
|
|
|
1043 |
|
|
|
1044 |
playlist->addMedia(qurl);
|
|
|
1045 |
obj->player = new QMediaPlayer;
|
|
|
1046 |
obj->player->setPlaylist(playlist);
|
|
|
1047 |
obj->player->setVideoOutput(obj->object.vwidget);
|
31 |
andreas |
1048 |
|
|
|
1049 |
if (mHasFocus)
|
|
|
1050 |
{
|
|
|
1051 |
obj->object.vwidget->show();
|
|
|
1052 |
obj->player->play();
|
|
|
1053 |
}
|
21 |
andreas |
1054 |
}
|
|
|
1055 |
|
31 |
andreas |
1056 |
void MainWindow::removeFromShowList(ulong handle)
|
|
|
1057 |
{
|
|
|
1058 |
DECL_TRACER("MainWindow::removeFromShowList(ulong handle)");
|
|
|
1059 |
|
|
|
1060 |
std::map<ulong, QWidget *>::iterator iter = mToShow.find(handle);
|
|
|
1061 |
|
|
|
1062 |
if (iter != mToShow.end())
|
|
|
1063 |
mToShow.erase(iter);
|
|
|
1064 |
}
|
|
|
1065 |
|
|
|
1066 |
void MainWindow::playShowList()
|
|
|
1067 |
{
|
|
|
1068 |
DECL_TRACER("MainWindow::playShowList()");
|
|
|
1069 |
|
|
|
1070 |
std::map<ulong, QWidget *>::iterator iter;
|
|
|
1071 |
|
|
|
1072 |
for (iter = mToShow.begin(); iter != mToShow.end(); ++iter)
|
|
|
1073 |
{
|
|
|
1074 |
OBJECT_t *obj = findObject(iter->first);
|
|
|
1075 |
|
|
|
1076 |
if (obj)
|
|
|
1077 |
iter->second->show();
|
|
|
1078 |
}
|
|
|
1079 |
|
|
|
1080 |
mToShow.clear();
|
|
|
1081 |
}
|
|
|
1082 |
|
2 |
andreas |
1083 |
#ifndef QT_NO_SESSIONMANAGER
|
|
|
1084 |
void MainWindow::commitData(QSessionManager &manager)
|
|
|
1085 |
{
|
5 |
andreas |
1086 |
if (manager.allowsInteraction())
|
|
|
1087 |
{
|
|
|
1088 |
if (!settingsChanged)
|
|
|
1089 |
manager.cancel();
|
|
|
1090 |
}
|
|
|
1091 |
else
|
|
|
1092 |
{
|
|
|
1093 |
if (settingsChanged)
|
|
|
1094 |
writeSettings();
|
|
|
1095 |
}
|
2 |
andreas |
1096 |
}
|
5 |
andreas |
1097 |
#endif
|