Commit 9644f23d authored by Michal Policht's avatar Michal Policht

Add CuteHMI.App extension.

parent ef368ec2
import qbs
import cutehmi
Project {
name: "CuteHMI.App.2"
cutehmi.Extension {
name: parent.name
minor: 0
micro: 0
friendlyName: "Application"
vendor: "CuteHMI"
description: "Provides foundation for GUI application."
author: "Michal Policht"
copyright: "Michal Policht"
license: "Mozilla Public License, v. 2.0"
files: [
"README.md",
"include/cutehmi/app/CuteApp.hpp",
"include/cutehmi/app/internal/common.hpp",
"include/cutehmi/app/internal/platform.hpp",
"include/cutehmi/app/logging.hpp",
"include/cutehmi/app/metadata.hpp",
"qmldir",
"src/cutehmi/app/CuteApp.cpp",
"src/cutehmi/app/internal/QMLPlugin.cpp",
"src/cutehmi/app/internal/QMLPlugin.hpp",
"src/cutehmi/app/logging.cpp",
]
Depends { name: "CuteHMI.2" }
//<CuteHMI.App-1.workaround target="Qt" cause="bug">
Depends { name: "Qt.widgets" }
//</CuteHMI.App-1.workaround>
Depends { name: "cutehmi.doxygen" }
cutehmi.doxygen.warnIfUndocumented: false
cutehmi.doxygen.useDoxyqml: true
cutehmi.doxygen.exclude: ['tests']
Export {
Depends { name: "CuteHMI.2" }
Depends { name: "Qt.widgets" }
}
}
SubProject {
filePath: "tests/tests.qbs"
Properties {
condition: parent.buildTests
}
}
}
//(c)MP: Copyright © 2019, Michal Policht. All rights reserved.
//(c)MP: This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
This diff is collapsed.
//(c)MP: Copyright © %YEAR%, Michal Policht. All rights reserved.
//(c)MP: This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#(c)MP: Copyright © %YEAR%, Michal Policht. All rights reserved.
#(c)MP: This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
# CuteHMI - Application
This module provides foundation for GUI application.
Class cutehmi::CuteApp provides idle measurment for frontend tools and projects.
Problem:
MessageDialog (QtQuick.Dialogs 1.2) misbehaves badly. Signal 'onRejected' is not
triggered, if dialog is closed via 'X' button. Additionaly when user presses one
of the 'standardButtons' 'onClickedButtonChanged' is emitted after(!)
'onVisibleChanged', so there is no way to determine if dialog was closed by 'X'
button or by one of the 'standardButtons' and 'Prompt' expects only single call
to `acceptResponse`. Attempts to force dialog to stay visible by setting
'visible = true' ended up with failure...
Investigation:
In theory 'Qt.labs.platform 1.0' could replace 'QtQuickDialogs 1.2', but after a
bit of testing it came out that for now implementation is immature and buggy.
Workaround:
Using 'QApplication' instead of 'QGuiApplication' made 'onRejected' signal work
as expected. Additionaly QApplication fixed lack of "beep" sound, when dialog
shows up. The price is that application has to be linked against 'widgets'
module.
#ifndef H_MODULES_CUTEHMI_u_APP_u_1_INCLUDE_CUTEHMI_APP_CUTEAPP_HPP
#define H_MODULES_CUTEHMI_u_APP_u_1_INCLUDE_CUTEHMI_APP_CUTEAPP_HPP
#include "internal/common.hpp"
#include <QApplication>
#include <QTime>
#include <QTimer>
namespace cutehmi {
namespace app {
/**
* %CuteHMI application. This class extends QApplication to provide idle measurment.
*/
class CUTEHMI_APP_API CuteApp:
//<CuteHMI.App-1.workaround target="Qt" cause="bug">
public QApplication
// Instead of:
// public QGuiApplication
//</CuteHMI.App-1.workaround>
{
typedef QApplication Parent;
Q_OBJECT
public:
//<CuteHMI.LockScreen-1.workaround target="Qt" cause="design">
static constexpr int IDLE_MEASURE_INTERVAL = 1000; ///< Idle measurement update interval [milliseconds].
//</CuteHMI.LockScreen-1.workaround>
//<CuteHMI.LockScreen-1.workaround target="Qt" cause="design">
Q_PROPERTY(double idle READ idle NOTIFY idleChanged)
Q_PROPERTY(bool idleMeasureEnabled READ idleMeasureEnabled WRITE setIdleMeasureEnabled NOTIFY idleMeasureEnabledChanged)
//</CuteHMI.LockScreen-1.workaround>
CuteApp(int & argc, char ** argv);
//<CuteHMI.LockScreen-1.workaround target="Qt" cause="design">
double idle() const;
bool idleMeasureEnabled() const;
void setIdleMeasureEnabled(bool idleMeasureEnabled);
bool notify(QObject * receiver, QEvent * event) override;
//</CuteHMI.LockScreen-1.workaround>
signals:
//<CuteHMI.LockScreen-1.workaround target="Qt" cause="design">
void idleChanged();
void idleMeasureEnabledChanged();
//</CuteHMI.LockScreen-1.workaround>
private slots:
//<CuteHMI.LockScreen-1.workaround target="Qt" cause="design">
void updateIdleTime();
//</CuteHMI.LockScreen-1.workaround>
private:
//<CuteHMI.LockScreen-1.workaround target="Qt" cause="design">
void setIdle(double idle);
//</CuteHMI.LockScreen-1.workaround>
private:
struct Members
{
//<CuteHMI.LockScreen-1.workaround target="Qt" cause="design">
int notifyEventCtr;
double idle; ///< Idle time [seconds].
bool idleMeasureEnabled;
QTimer updateTimer;
QTime idleTime;
//</CuteHMI.LockScreen-1.workaround>
Members();
};
MPtr<Members> m;
};
}
}
#endif
//(c)MP: Copyright © 2018, Michal Policht. All rights reserved.
//(c)MP: This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef CUTEHMI_CUTEHMI__APP__1__LIB_INCLUDE_APP_INTERNAL_COMMON_HPP
#define CUTEHMI_CUTEHMI__APP__1__LIB_INCLUDE_APP_INTERNAL_COMMON_HPP
#include "platform.hpp"
#include "../metadata.hpp"
#include "../logging.hpp"
#include <cutehmi/MPtr.hpp>
#include <QtGlobal>
#endif
//(c)MP: Copyright © 2018, Michal Policht. All rights reserved.
//(c)MP: This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef H_MODULES_CUTEHMI_u_APP_u_1_INCLUDE_CUTEHMI_APP_INTERNAL_PLATFORM_HPP
#define H_MODULES_CUTEHMI_u_APP_u_1_INCLUDE_CUTEHMI_APP_INTERNAL_PLATFORM_HPP
#ifdef CUTEHMI_APP_DYNAMIC
#ifdef CUTEHMI_APP_BUILD
//export symbols to dll
#define CUTEHMI_APP_API Q_DECL_EXPORT
#else
//using functions from dll
#define CUTEHMI_APP_API Q_DECL_IMPORT
#endif
#ifdef CUTEHMI_APP_TESTS
//export symbols to dll
#define CUTEHMI_APP_PRIVATE Q_DECL_EXPORT
#else
//using functions from dll
#define CUTEHMI_APP_PRIVATE Q_DECL_IMPORT
#endif
#else
#define CUTEHMI_APP_API
#define CUTEHMI_APP_PRIVATE
#endif
#endif
//(c)MP: Copyright © 2018, Michal Policht. All rights reserved.
//(c)MP: This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef H_MODULES_CUTEHMI_u_APP_u_1_INCLUDE_CUTEHMI_APP_LOGGING_HPP
#define H_MODULES_CUTEHMI_u_APP_u_1_INCLUDE_CUTEHMI_APP_LOGGING_HPP
#include "internal/platform.hpp"
#include <cutehmi/loggingMacros.hpp>
CUTEHMI_APP_API Q_DECLARE_LOGGING_CATEGORY(cutehmi_app_2_loggingCategory)
namespace cutehmi {
namespace app {
inline
const QLoggingCategory & loggingCategory()
{
return cutehmi_app_2_loggingCategory();
}
}
}
#endif
//(c)MP: Copyright © 2018, Michal Policht. All rights reserved.
//(c)MP: This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef H_MODULES_CUTEHMI_u_APP_u_1_INCLUDE_CUTEHMI_APP_METADATA_HPP
#define H_MODULES_CUTEHMI_u_APP_u_1_INCLUDE_CUTEHMI_APP_METADATA_HPP
#include "../../../cutehmi.metadata.hpp"
#endif
//(c)MP: Copyright © 2018, Michal Policht. All rights reserved.
//(c)MP: This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
module CuteHMI.App
plugin CuteHMI.App ../..
classname cutehmi::app::internal::QMLPlugin
typeinfo plugins.qmltypes
designersupported
#include "../../../include/cutehmi/app/CuteApp.hpp"
namespace cutehmi {
namespace app {
CuteApp::CuteApp(int & argc, char ** argv):
Parent(argc, argv),
m(new Members)
{
m->updateTimer.setTimerType(Qt::VeryCoarseTimer);
connect(& m->updateTimer, & QTimer::timeout, this, & CuteApp::updateIdleTime);
}
double CuteApp::idle() const
{
return m->idle;
}
bool CuteApp::idleMeasureEnabled() const
{
return m->idleMeasureEnabled;
}
void CuteApp::setIdleMeasureEnabled(bool idleEnabled)
{
if (m->idleMeasureEnabled != idleEnabled) {
m->idleMeasureEnabled = idleEnabled;
if (idleEnabled) {
m->notifyEventCtr = 0;
setIdle(0.0);
m->idleTime.start();
m->updateTimer.start(IDLE_MEASURE_INTERVAL);
} else {
setIdle(0.0);
m->updateTimer.stop();
}
emit idleMeasureEnabledChanged();
}
}
bool CuteApp::notify(QObject * receiver, QEvent * event)
{
if (event->spontaneous())
m->notifyEventCtr++;
return Parent::notify(receiver, event);
}
void CuteApp::updateIdleTime()
{
if (m->notifyEventCtr) {
setIdle(0.0);
m->notifyEventCtr = 0;
} else
setIdle(idle() + static_cast<double>(m->idleTime.elapsed()) / 1000.0);
m->idleTime.restart();
}
void CuteApp::setIdle(double idle)
{
if (m->idle != idle) {
m->idle = idle;
emit idleChanged();
}
}
CuteApp::Members::Members():
notifyEventCtr(0),
idle(0.0),
idleMeasureEnabled(false)
{
}
}
}
//(c)MP: Copyright © 2018, Michal Policht. All rights reserved.
//(c)MP: This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "QMLPlugin.hpp"
#include <cutehmi/app/CuteApp.hpp>
#include <QtQml>
namespace CuteHMI {
namespace App {
/**
* @class CuteHMI::CuteApp
* Exposes cutehmi::app::CuteApp to QML.
*/
}
}
namespace cutehmi {
namespace app {
namespace internal {
/**
* Register QML types.
* @param uri URI.
*/
void QMLPlugin::registerTypes(const char * uri)
{
Q_ASSERT(uri == QLatin1String("CuteHMI.App"));
//<CuteHMI.LockScreen-1.workaround target="Qt" cause="design">
qmlRegisterSingletonType<cutehmi::app::CuteApp>(uri, CUTEHMI_APP_MAJOR, 0, "CuteApp", CuteAppProvider);
//</CuteHMI.LockScreen-1.workaround>
}
QObject * QMLPlugin::CuteAppProvider(QQmlEngine * engine, QJSEngine * scriptEngine)
{
Q_UNUSED(scriptEngine)
QObject * cuteApp = cutehmi::app::CuteApp::instance();
engine->setObjectOwnership(cuteApp, QQmlEngine::CppOwnership);
return cuteApp;
}
}
}
}
//(c)MP: Copyright © 2018, Michal Policht. All rights reserved.
//(c)MP: This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef H_QML_CUTEHMI_APP_SRC_CUTEHMIAPPQMLPLUGIN_HPP
#define H_QML_CUTEHMI_APP_SRC_CUTEHMIAPPQMLPLUGIN_HPP
#include <QQmlExtensionPlugin>
class QJSEngine;
namespace cutehmi {
namespace app {
namespace internal {
class QMLPlugin:
public QQmlExtensionPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
public:
void registerTypes(const char * uri) override;
//<CuteHMI.LockScreen-1.workaround target="Qt" cause="design">
static QObject * CuteAppProvider(QQmlEngine * engine, QJSEngine * scriptEngine);
//</CuteHMI.LockScreen-1.workaround>
};
}
}
}
#endif
//(c)MP: Copyright © 2018, Michal Policht. All rights reserved.
//(c)MP: This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "../../../include/cutehmi/app/logging.hpp"
#include <cutehmi/app/metadata.hpp>
Q_LOGGING_CATEGORY(cutehmi_app_2_loggingCategory, CUTEHMI_APP_NAME)
//(c)MP: Copyright © 2018, Michal Policht. All rights reserved.
//(c)MP: This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
import qbs
import cutehmi
cutehmi.Test
{
testNamePrefix: parent.parent.name
Depends { name: "CuteHMI.App.2" }
Depends { name: "CuteHMI.Test.0" }
}
//(c)MP: Copyright © 2019, Michal Policht. All rights reserved.
//(c)MP: This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <cutehmi/app/logging.hpp>
#include <QtTest/QtTest>
namespace cutehmi {
namespace app {
class test_logging:
public QObject
{
Q_OBJECT
private slots:
void loggingCategory();
};
void test_logging::loggingCategory()
{
QCOMPARE(cutehmi::app::loggingCategory().categoryName(), "CuteHMI.App.2");
}
}
}
QTEST_MAIN(cutehmi::app::test_logging)
#include "test_logging.moc"
//(c)MP: Copyright © 2019, Michal Policht. All rights reserved.
//(c)MP: This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
import qbs
import cutehmi
import "Test.qbs" as Test
Project {
Test {
testName: "test_logging"
files: [
"test_logging.cpp",
]
}
}
//(c)MP: Copyright © 2019, Michal Policht. All rights reserved.
//(c)MP: This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment