How to bind to root context object signal from QML - qt

I'm creating QML application (QT 5.2)
Assume I have some object set as root context:
viewer.rootContext()->setContextObject(&view_model);
Now I want to bind to a signal of view_model from QML:
Connections {
target: ??? WHAT SHOULD GO HERE ???
onSignalStateChanged: console.log("signal")
}
Cannot figure out what should be the target.
Important: I don't want to use setContextProperty.

It seems you can't use Connections if you don't have access to object instance (via context property for example). But you still could use following:
function onSignal() {
console.log( "signal" );
}
Component.onCompleted: {
onSignalStateChanged.connect( onSignal );
}

Related

Symfony 5 switch cache adapter on condition

I need to switch the Symfony cache adapter depending on ENV conditions. Like if some variable is set, use "cache.adapter.apcu" or use "cache.adapter.filesystem" otherwise.
Is it possible somehow? The documentation is not really helpful with it.
P.S.: It is not possible for us to do this via the creation of a whole new environment
Here is a basic example for a CacheAdapter which has adapters fed into it and then picking one based on a parameter (or alternatively envvar):
<?php
namespace App\Cache;
use Psr\Cache\CacheItemInterface;
use Psr\Cache\InvalidArgumentException;
use Psr\Container\ContainerInterface;
use Symfony\Component\Cache\Adapter\AdapterInterface;
use Symfony\Component\Cache\CacheItem;
use Symfony\Contracts\Service\ServiceSubscriberInterface;
use Symfony\Contracts\Service\ServiceSubscriberTrait;
class EnvironmentAwareCacheAdapter implements AdapterInterface, ServiceSubscriberInterface
{
use ServiceSubscriberTrait;
private string $environment;
public function __construct(string $environment)
{
$this->environment = $environment;
}
public function getItem($key)
{
return $this->container->get($this->environment)->getItem($key);
}
public function getItems(array $keys = [])
{
return $this->container->get($this->environment)->getItems($key);
}
// ...
}
This is how you would configure it:
services:
App\Cache\EnvironmentAwareCacheAdapter:
arguments:
$environment: '%kernel.environment%'
tags:
- { name: 'container.service_subscriber', key: 'dev', id: 'cache.app' }
- { name: 'container.service_subscriber', key: 'prod', id: 'cache.system' }
It's not the most elegant solution and is missing error handling and possibly a fallback. Basically, by adding tags with an appropriately named key and the alias to an existing cache as id, you can then refer to that cache with the key in your own adapter. So, depending on your environment you will pick either one. You can replace the key and the constructor argument with anything else you like. I hope that helps.
It seems like you can not set up your cache configuration to use a environment variable like so:
framework:
cache:
app: %env(resolve:CACHE_ADAPTER)%
It is the constraint of FrameworkBundle that provides the cache service. And this constraint will not be "fixed" (Using environment variables at compile time #25173).
To make it possible you need to make your own cache provider that can just pass all arguments to the needed cache provider. You will have access to environment variables at runtime and so you can use it as a proxy that knows what provider to use.

QML Connections: Implicitly defined onFoo properties in Connections are deprecated

I got the following error message when upgraded to Qt 5.15:
QML Connections: Implicitly defined onFoo properties in Connections are deprecated.
Use this syntax instead: function onFoo(<arguments>) { ... }
The corresponding QML code is pasted below
Connections {
target: AppProxy
onLogsReady: function(logs) {
textLogs.text = logs
}
}
where the onLogsReady is a signal defined in the AppProxy class:
class AppProxy : public QObject {
Q_OBJECT
Q_DISABLE_COPY(AppProxy)
public:
AppProxy(QObject* parent = 0);
~AppProxy();
signals:
void logsReady(QString logs);
// ...
};
I wonder how to suppress this warning.
in Qml 5.15 there is a new syntax for connections. In your case it would look like this:
Connections {
target: AppProxy
function onLogsReady(logs) {
textLogs.text = logs
}
}
You can read more about it here: https://doc.qt.io/qt-5/qml-qtqml-connections.html
In addtion to #luffy and #Lidekys solution in my case adding this line to pro file of the project is solved issue.
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
#luffy answer is correct, but not completely. If you'll just make these changes, at least for me, it didn't fix the issue. What fixed it was adding "import QtQml 2.15" (like stated in https://doc.qt.io/qt-5/qml-qtqml-connections.html) in the qml files that were affected by these changes.
Not sure if this helps, just wanted to add in to the issue.

Drag file from application to explorer. Can my application do the copying?

In Qml I can start a drag using the text/uri-list mime type in order to start a copy action from my application into a file explorer, e.g.
Item {
id: draggable
anchors.fill: parent
Drag.active: mouseArea.drag.active
Drag.hotSpot.x: 0
Drag.hotSpot.y: 0
Drag.mimeData: { "text/uri-list": "file:///home/myname/Desktop/avatar.jpeg" }
Drag.supportedActions: Qt.CopyAction
Drag.dragType: Drag.Automatic
Drag.onDragStarted: { }
Drag.onDragFinished: {
console.log("Time to copy")
}
} // Item
or
Item {
id: draggable
anchors.fill: parent
Drag.active: mouseArea.drag.active
Drag.hotSpot.x: 0
Drag.hotSpot.y: 0
Drag.mimeData: { "text/uri-list": "https://farm1.staticflickr.com/713/21777111068_e3310cfb94_k.jpg" }
Drag.supportedActions: Qt.CopyAction
Drag.dragType: Drag.Automatic
Drag.onDragStarted: { }
Drag.onDragFinished: {
console.log("Time to copy")
}
} // Item
(see also Qt Quick Examples - externaldraganddrop)
This works fine given file: and http: URIs.
However my real data is not available as an URI but stored in a database. I cannot quickly store to temp because that can take seconds and user does not want a delay in the moment he starts a drag.
Is it somehow possible to get the target URI after the drop and do the copying myself? Or can only the target do the copying?
In the later case, do I need to make my data available via an internal HTTP-Server? How do I even know which URI scheme is supported by the file browsers on Linux, Windows and OS X?
I would use something like:
Drag.mimeData: { "text/uri-list": "http://localhost:8080/datarepository?id=12345" }
and then I'll make available the requested data on an in-application HTTP server (that then can easily extract the object having ID equal to 12345 in my example from DB)... (once the copy operation has started I don't think that it is a shame if your user waits some seconds while the system extracts the object from the DB).

Remove Warning- QML Connections: Cannot assign to non-existent property "onValueChanged"

My code runs fine as expected but why do I get the warning messsage:
QML Connections: Cannot assign to non-existent property "onValueChanged"
Here is how I linking to signal.
Connections {
target: myModel
onValueChanged: {
console.log("Valued changedRecieved in QML")
}
myModel is a C++ class that I am exposing to QML using engine.rootContext()->setContextProperty("myModel", &model);
Is there a way to remove this warning?
In your Connections scope just set ignoreUnknownSignals: true

Non-scalar ENVs for use as Symfony Parameter

I'm trying to use ENVs to set my parameters in Symfony2. The scalar values are easy enough, but I have parameters that are arrays that I need to set somehow with ENVs.
The parameter in question:
parameters:
redis.servers:
- { host: 127.0.0.1, port: 6379 }
- { host: other, port: 6379 }
# and so on
The kicker here is that the array of servers can change dynamically, so I can't just assume there's 2.
What I hoped to do (but this just gives me a string of json):
SYMFONY__REDIS__SERVERS=[{"host":"127.0.0.1","port":"6379"}]
Is this possible? Any work-arounds that are feasible? There are multiple bundles we're using that accept array/object parameters, so I can't do an update there to process the param. It would have to be app level, if anything.
Thanks.
I was able to solve this by updating the AppKernel to override the getEnvParameters() method of the parent Kernel. This method only runs on parameters that the Kernel already found in the ENV (technically from $_SERVER). I like it because it won't run on the entire parameter stack, nor the entire $_SERVER array.
protected function getEnvParameters()
{
$parameters = parent::getEnvParameters();
foreach ($parameters as &$parameter) {
if (is_string($parameter)) {
$decoded = json_decode($parameter, true);
// we only care about arrays (or objects that get turned into arrays)
if (!json_last_error() && is_array($decoded)) {
$parameter = $decoded;
}
}
}
return $parameters;
}

Resources