Eine kurze lyrische EinfĂŒhrung - 2017 war ich zufĂ€llig sehr stark an Meditationen interessiert. Dies wurde durch eine ganze Kette von Ereignissen erleichtert, gĂŒnstig und nicht sehr. Seit vielen Jahren interessiere ich mich fĂŒr klare TrĂ€ume und praktiziere sie, aber vorher musste ich mich nicht speziell mit Meditationen in ihrer kanonischen Form befassen. In diesen Tagen vieleGeschichten beginnen an der / den Bar (s)Hobbys beginnen mit einer Suche bei Google, also habe ich so angefangen. Fast sofort wurden die beliebtesten Meditationsanwendungen gefunden - Ruhe und Kopfraum.
Das erste diente als guter Ausgangspunkt (ausgezeichnete pĂ€dagogische Meditationen fĂŒr AnfĂ€nger), das zweite fand ich fĂŒr mich selbst nicht nĂŒtzlich, die PrĂ€sentation gefiel mir nicht. Beide haben ihre bezahlten (und fĂŒr die Russische Föderation sehr teuren) TarifplĂ€ne verdrĂ€ngt. Vielleicht gehöre ich einfach nicht zu der Kategorie von Leuten, die zahlen mĂŒssen, um sich zu etwas zu ermutigen :) Als ich Google Play weiter studierte, stieĂ ich auf zwei kostenlose Anwendungen, die mir im Geiste nahe stehen. Das erste ist "Lass uns meditieren" - ich benutze es immer noch, das zweite wird im Hauptteil des Artikels besprochen.
Anwendung
Nach einer langen Suche wurde eine völlig unauffĂ€llige Anwendung gefunden, die, wenn ich mich nicht irre, "Meditation. Antonov Alexander" genannt wurde. Wie sich herausstellte, war es möglich, vier Meditationen des Autors zu hören, die tatsĂ€chlich von Alexander aufgenommen und komponiert wurden, mit dem wir uns spĂ€ter trafen und anfreundeten. Er stellte die Anwendung buchstĂ€blich aus improvisierten Tools zusammen. Es war so etwas wie ein hausgemachtes SPA, das WebView ohne Frameworks verwendete, praktisch in reinem HTML und minimal in Java. Es sah mittelmĂ€Ăig aus und einige Funktionen fehlten einfach (zum Beispiel konnte man nicht durch die Aufnahme navigieren, sondern sie nur von Anfang an einschalten). Da mir der Inhalt selbst sehr gut gefallen hat, habe ich Alexander meine kostenlose Hilfe bei der Aktualisierung der Anwendung angeboten, so dass "Um etwas zurĂŒckzugeben, "auf der Grundlage", dass sie mir geholfen haben, werde ich helfen. "Im Hauptteil des Artikels werde ich versuchen, Ihnen zu sagen, auf welche Probleme wir wĂ€hrend der Entwicklung gestoĂen sind, welche Entscheidungen getroffen wurden und was am Ende passiert ist! Ich hoffe, dass die einzelnen Rezepte des Artikels sein werden nĂŒtzlich fĂŒr jedermann, aber interessant interessant :)
, :
Qt
â (), PHP/HTML. , , , Qt, :
- Qt ( Symbian, MeeGo, Ubuntu Phone Android);
- , ;
- QML, C++. , â JavaScript-like , ;
- iOS ( ).
UI
, , . , , . , . ( ):

"" anchors, Row, Column Repeater. , UI. , ( ):
Button {
id: mainButton
anchors {
left: parent.left
right: parent.right
}
height: btnLayout.height + 30
Material.background: "white"
onClicked: stackView.push(Qt.resolvedUrl("qrc:/qml/MeditationListPage.qml"))
Column {
id: btnLayout
spacing: 10
anchors {
top: parent.top
topMargin: 15
left: parent.left
right: parent.right
margins: 10
}
Row {
anchors.horizontalCenter: parent.horizontalCenter
spacing: (mainButton.width - 4 * 50) / 6
Repeater {
model: meditationModel
RoundedIcon {
source: Qt.resolvedUrl("qrc:/img/my%1.png".arg(model.index))
color: model.color
width: 50
height: 50
}
}
}
Label {
text: qsTr("")
font.pointSize: 14
color: "dimgrey"
anchors.horizontalCenter: parent.horizontalCenter
}
Label {
text: " , "
anchors {
left: parent.left
right: parent.right
}
horizontalAlignment: Text.AlignHCenter
Material.foreground: Material.Grey
font.pixelSize: 12
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
}
}
}
UI , HDPI Qt . , Qt: QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
. " ".
Material design, Android Qt Quick Controls 2 . https://doc.qt.io/qt-5/qtquickcontrols2-material.html. , Material design. UI , attached property Material.accent
.

mp3- , QRC. 10-15 . â , 15 . , , pro-:
CONFIG += resources_big
, , , .
, " ". Shorts, , . DarkModeShader.qml
:
ShaderEffect {
fragmentShader: "
uniform lowp sampler2D source;
uniform lowp float qt_Opacity;
varying highp vec2 qt_TexCoord0;
void main() {
lowp vec4 p = texture2D(source, qt_TexCoord0);
p.r = min(0.8, (1.0 - p.r) * 0.8 + 0.1);
p.g = min(0.8, (1.0 - p.g) * 0.8 + 0.1);
p.b = min(0.8, (1.0 - p.b) * 0.8 + 0.1);
gl_FragColor = vec4(vec3(dot(p.rgb, vec3(0.299, 0.587, 0.114))), p.a) * qt_Opacity;
}
"
}
:
StackView {
// ...
layer.effect: DarkModeShader { }
layer.enabled: optionsKeeper.isNightMode
}
.. , isNightMode
. Qt / ( , ).
, â . - , â !
Qt Multimedia, Audio
. mp3, , â , :
Audio {
id: audioPlayback
source: meditAudioSource
}
// ...
Slider {
anchors {
left: parent.left
right: playBtn.left
verticalCenter: parent.verticalCenter
}
from: 0
to: audioPlayback.duration
value: audioPlayback.position
onMoved: audioPlayback.seek(value)
Material.accent: meditColor
}
Settings
Qt.labs.settings
(, , labs):
import Qt.labs.settings 1.0
// ... boilerplate- , .
property Settings settings: Settings {
property bool isNightMode: false
}
2018 , .
, , 2020, , - , â ( ). , â â :)
, JSON- . . HTTP- QML- XMLHttpRequest
( JSON QML). .
. QML LocalStorage, SQLite. JS-, QML, :
// databasemodule.js
.pragma library // I hope this will prevent the waste of memory.
.import QtQuick.LocalStorage 2.0 as SQL
function getMeditations() {
...
}
// TransferManager.qml
import "databasemodule.js" as DB
...
var syncedItems = DB.getMeditations()
:
var db = SQL.LocalStorage.openDatabaseSync("AMeditation", "", "Main DB", 100000)
...
db.transaction(function(tx) {
dbResult = tx.executeSql("SELECT * FROM meditations")
console.log("meditations SELECTED: ", dbResult.rows.length)
})
.. , transaction
callback. ( , Qt ).
. openDatabaseSync
. , ( , ). . , , , . [" ", " ", " "]:
var migrations = [
{'from': "", 'to': "1.0", 'ops': function(transaction) {
transaction.executeSql("CREATE TABLE meditations ( \
id INTEGER PRIMARY KEY
...
status TEXT);")
}}
,{'from': "1.0", 'to': "1.1", 'ops': function(transaction) {
transaction.executeSql("ALTER TABLE meditations ADD quality TEXT;")
}}
]
, ( â , - ).
C++
QML, C++. . Ubuntu Phone. . QML â . C++- QML :
engine.rootContext()->setContextProperty("networkManager", new NetworkManager());
QML - :
// .
var isSucces = networkManager.download(downloadUrl, currentDownload.localUrl)
...
// .
Connections {
target: networkManager
onDownloadOperationProgress: {
d.currentDownload.current = current
d.currentDownload.total = total
}
...
}
C++-, QML- singletone :
class CppUtils : public QObject
{
Q_OBJECT
public:
explicit CppUtils(QObject *parent = nullptr);
~CppUtils();
Q_INVOKABLE bool removeFile(const QString& fileName) const;
static QObject *cppUtilsSingletoneProvider(QQmlEngine *engine, QJSEngine *scriptEngine);
};
qmlRegisterSingletonType<CppUtils>("AMeditation.CppUtils", 1, 0, "CppUtils", CppUtils::cppUtilsSingletoneProvider);
.. , cppUtilsSingletoneProvider
, Q_INVOKABLE â "" QML. QML :
import AMeditation.CppUtils 1.0
// ...
CppUtils.removeFile(cd.localUrl)
, - . â . , - , . , . QML (QNetworkAccessManager). . :
class CachingNetworkAccessManager : public QNetworkAccessManager
{
public:
CachingNetworkAccessManager(QObject *parent = 0);
protected:
QNetworkReply* createRequest(Operation op, const QNetworkRequest &req, QIODevice *outgoingData = 0);
};
class CachingNetworkManagerFactory : public QQmlNetworkAccessManagerFactory
{
public:
CachingNetworkManagerFactory();
QNetworkAccessManager *create(QObject *parent);
};
QNetworkReply* CachingNetworkAccessManager::createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData)
{
QNetworkRequest req(request);
req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork);
return QNetworkAccessManager::createRequest(op, req, outgoingData);
}
QNetworkAccessManager *CachingNetworkManagerFactory::create(QObject *parent) {
QNetworkAccessManager* manager = new CachingNetworkAccessManager(parent);
QNetworkDiskCache* cache = new QNetworkDiskCache(manager);
cache->setCacheDirectory(QString("%1/network").arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)));
manager->setCache(cache);
return manager;
}
.. setCache
, createRequest
. â , .
Android
SDK NDK. Linux- , Windows - (, , QtCreator 4.12 NDK, ). NDK Clang. arm_v7 (32 ), arm_v8a (64 ; Google play 2019 ). Google play.
, , .
- Qt pet-, Android. ;
- AMeditation ( UI " 2.1. ") 10+ 250 , ( , , ).
- , , !
- iOS .
Im Allgemeinen macht es SpaĂ, sich auf Qt zu entwickeln und etwas kostenlos und auch fĂŒr die Seele zu tun!
PS Liebe Einwohner von Chabrowsk, ich hoffe, Sie zÀhlen es nicht als Werbung - die Anwendung ist grundsÀtzlich kostenlos und nicht kommerziell. Ich wollte Interessierten davon und von der Entstehungsgeschichte erzÀhlen, nur um erfolgreich gefundene EntwicklungsansÀtze zu teilen.
PSS Die Anwendung hat ihre Doppelversion 1.1 mit Àlteren EintrÀgen, die weitere 5k + Downloads und 100 Bewertungen enthÀlt. Wir werden es wahrscheinlich bald aus dem Laden holen.