I am building a home security system with RPi and WebRTC. I simply need a way to trigger a browser to open at a given URL and to auto-grant access to the Microphone and Camera. I had hoped to use the WebEngine library with PyQt but WebEngine is not supported in PyQt for RPi. So I am trying Qt itself now. Unfortunately I am not familiar with C++, so i am struggling.
The example here has 90% of what I need. The code is replicated below. I just need to tweak it to grant access to the mic and camera when it is requested. I am hoping someone can assist me with this?
#include <QApplication>
#include <QWebEngineView>
QUrl commandLineUrlArgument()
{
const QStringList args = QCoreApplication::arguments();
for (const QString &arg : args.mid(1)) {
if (!arg.startsWith(QLatin1Char('-')))
return QUrl::fromUserInput(arg);
}
return QUrl(QStringLiteral("https://www.qt.io"));
}
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
QWebEngineView view;
view.setUrl(commandLineUrlArgument());
view.resize(1024, 750);
view.show();
return app.exec();
}
I answered this question but for PyQt5: Grant access to Cam & Mic using Python for PyQt WebEngine, I will only do a C ++ translation to Python, the base is the same.
#include <QApplication>
#include <QUrl>
#include <QWebEngineView>
class WebEnginePage: public QWebEnginePage{
Q_OBJECT
public:
WebEnginePage(QObject *parent = Q_NULLPTR):QWebEnginePage(parent){
connect(this, &WebEnginePage::featurePermissionRequested, this, &WebEnginePage::onFeaturePermissionRequested);
}
private Q_SLOTS:
void onFeaturePermissionRequested(const QUrl &securityOrigin, QWebEnginePage::Feature feature){
if(feature == QWebEnginePage::MediaAudioCapture
|| feature == QWebEnginePage::MediaVideoCapture
|| feature == QWebEnginePage::MediaAudioVideoCapture)
setFeaturePermission(securityOrigin, feature, QWebEnginePage::PermissionGrantedByUser);
else
setFeaturePermission(securityOrigin, feature, QWebEnginePage::PermissionDeniedByUser);
}
};
QUrl commandLineUrlArgument()
{
const QStringList args = QCoreApplication::arguments();
for (const QString &arg : args.mid(1)) {
if (!arg.startsWith(QLatin1Char('-')))
return QUrl::fromUserInput(arg);
}
return QUrl(QStringLiteral("https://www.qt.io"));
}
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
QWebEngineView view;
view.setPage(new WebEnginePage);
view.setUrl(commandLineUrlArgument());
view.resize(1024, 750);
view.show();
return app.exec();
}
#include "main.moc"
Related
I am trying to use Qt Remote Objects for creating client server application.
But encountered an issue that says "connectionToSource is null". How do I set the source connection ?
I am creating the server using the .rep file. The code I had used is as follows:
Data Model
// Rep File (DataModel.rep)
class DataModel {
PROP(double data)
}
Server Code
// DataBroadcaster class (DataBroadcaster.h)
// DataBroadcaster class inherits DataModelSimpleSource.h (generated from .rep file)
#include "rep_DataModel_Source.h"
class DataBroadcaster : public DataModelSimpleSource
{
Q_OBJECT
public:
DataBroadcaster(QObject *parent = nullptr);
~DataBroadcaster();
void Initialize();
private:
int QScopedPointer<QRemoteObjectHost> remoteHost;
}
// DataBroadcaster.cpp
DataBroadcaster::DataBroadcaster(QObject *parent): DataModelSimpleSource(parent){}
DataBroadcaster::~DataBroadcaster(){}
void DataBroadcaster::Initialize()
{
remoteHost.reset(new QRemoteObjectHost(QUrl(QStringLiteral("local:mydata"))));
remoteHost->enableRemoting(this, "DataModel");
}
// Server code main function
#include <QCoreApplication>
#include "DataBroadcaster.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
DataBroadcaster server;
server.Initialize();
double count = 0.0;
while(true)
{
server.pushData(count + 0.1);
}
return a.exec();
}
Client Code
// DataModelDataReplica is generated from .rep file used to generate source
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "rep_DataModel_replica.h"
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
// registered as qml type in main
qmlRegisterType<DataModelReplica>("CustomData", 1, 0, "MyData");
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
QML Code
// DisplayPage.qml Added to QML file
import CustomData 1.0
MyData {
id: dataClient
node: Node {
registerUrl: "local:mydata"
}
Button {
id: btn
text: "Server Data"
onClicked: {
// displaying some data from source
btn.text = dataClient.data
}
}
}
Execution:
Server code is running
Client code is running but when trying to get data I get following error message in debugger
**"qt.remoteobjects: connectionToSource is null"**
I am unable to figure out what am I missing.
If anyone has any idea about how to resolve or where to look for please suggest.
I was able to find the problem. In the Server Code main function, the while loop is used which never exits because of which the "exec()" function was never called and Qt event loop never started because of which the Qt Remote object didn't share data. So I changed the following code using the Signal and Slot mechanism to create a non-blocking function. Following is the code change that I made.
// Server Code main function
#include <QCoreApplication>
#include "DataBroadcaster.h"
#include "ServerController.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
DataBroadcaster server;
server.Initialize();
ServerController controller(&server);
return a.exec();
}
// Server Controller
#include <QTimer>
#include "DataBroadcaster.h"
class ServerController : public QObject
{
Q_OBJECT
public:
explicit ServerController(QObject *parent = nullptr, DataBroadcast *server = nullptr);
~ServerController();
public Q_SLOTS:
void SendData();
private:
QTimer timer;
double count = 0.0;
DataBroadcast *m_server = nullptr;
}
ServerController::ServerController(QObject *parent, DataBroadcast *server): QObject(parent), m_server(server)
{
connect(&timer, SIGNAL(timeout()), this, SLOT(SendData()));
timer.start();
}
ServerController::~ServerController()
{
timer.stop();
}
ServerController::SendData()
{
count += 0.1;
if(m_server != nullptr)
{
m_server->pushData(count);
}
}
I have a task to implement simple desktop wrapper on QT for our website. Everything works well except for geolocation. Every time browser has to request permission for geolocation usage nothing is happened, geolocation doesn't work. I tried a few solutions from SO and other resources, but nothing helped me. Here is my code:
#include <QLabel>
#include <QWebEnginePage>
class WebEnginePage: public QWebEnginePage{
Q_OBJECT
public:
WebEnginePage(QObject *parent = Q_NULLPTR):QWebEnginePage(parent) {
connect(this, &WebEnginePage::featurePermissionRequested, this, &WebEnginePage::onFeaturePermissionRequested);
}
protected:
bool certificateError(const QWebEngineCertificateError &certificateError){
return true;
}
private Q_SLOTS:
void onFeaturePermissionRequested(const QUrl &securityOrigin, QWebEnginePage::Feature feature){
setFeaturePermission(securityOrigin, feature, QWebEnginePage::PermissionGrantedByUser);
}
};
#include <QApplication>
#include <QWebEngineView>
#include <QWebEngineSettings>
#include "main.moc"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
QWebEngineView view;
view.setPage(new WebEnginePage());
QWebEngineSettings* settings = view.settings();
settings->setAttribute(QWebEngineSettings::WebAttribute::LocalStorageEnabled, true);
settings->setAttribute(QWebEngineSettings::WebAttribute::AllowGeolocationOnInsecureOrigins, true);
view.setUrl(QUrl(here is my url));
view.resize(1024, 750);
view.show();
return app.exec();
}
Could you give me some suggestions, what's wrong with my code?
I am using the Urho3D engine with Qt for an application. The problem is that both Urho3D and QApplication require to be ran from main(). For now I am using it in separate processes but IPC makes it complicated.
Is there any way to solve this issue? Thanks
My platform is Urho3D 1.5, Qt 4.71 and Windows 7 x64 and VS2015 (C++)
I'm new to both c++ and Urho3D, but I've successfully achieved it.
Simple code, haven't had further test:
awidget.h:
#ifndef AWIDGET_H
#define AWIDGET_H
#include <QWidget>
#include <QPushButton>
#include <Urho3D/Engine/Application.h>
class aWidget : public QWidget
{
Q_OBJECT
public:
explicit aWidget(QWidget *parent = 0)
{
QPushButton *button = new QPushButton(this);
connect(button, SIGNAL(clicked()), this, SLOT(pressed()));
}
public slots:
void pressed()
{
Urho3D::Context* context = new Urho3D::Context();
Urho3D::Application *application = new Urho3D::Application(context);
application->Run();
}
};
#endif // AWIDGET_H
main.cpp:
#include <QApplication>
#include <awidget.h>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
aWidget *widget = new aWidget();
widget->show();
return app.exec();
}
By the way, I'm using Qt 5.9.0
So the answer is quite simple. Instead of running QApplication by calling
app->exec();
it is needed to manually and regularily call this from your main loop:
app->processEvents();
This will take care that all events used by Qt are processed and QApplication will respond accordingly.
Example:
#include <QApplication>
#include <awidget.h>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
bool shallrun = true;
aWidget *widget = new aWidget();
widget->show();
while (shallrun)
{
app->processEvents();
...
}
...
}
Let's say we have a barebones QWebView:
#include <QApplication>
#include <QWebView>
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QWebView view;
view.show();
view.setUrl(QUrl("http://google.com"));
return app.exec();
}
How can I display a graphic overlay, preferably fullscreen with transparency and minimal animation (like timer/beachball/etc.) from when the page starts loading till it's finished? Should also be triggered when url changes from within the QWebView.
You can use the LoadingOverlay class provided in this answer to draw an overlay over any QWidget. In your case, show the overlay on top of the QWebView when the signal loadStarted is triggered and hide it, when the signal loadFinished is triggered.
The following code should get you started. I put the code from the linked answer into overlay.h, the subclass of QWebView which handles the showing/hiding of the overlay is in webview.h:
webview.h
#include "overlay.h"
#include <QWebView>
class WebView : public QWebView
{
Q_OBJECT
public:
WebView(QWidget * parent) : QWebView(parent)
{
overlay = new LoadingOverlay(parent);
connect(this,SIGNAL(loadFinished(bool)),this,SLOT(hideOverlay()));
connect(this,SIGNAL(loadStarted()),this,SLOT(showOverlay()));
}
~WebView()
{
}
public slots:
void showOverlay()
{
overlay->show();
}
void hideOverlay()
{
overlay->hide();
}
private:
LoadingOverlay* overlay;
};
main.cpp
#include <QApplication>
#include "overlay.h"
#include "webview.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ContainerWidget base;
Webview w(&base);
base.show();
w.load(QUrl("http://google.com"));
return a.exec();
}
Now, I have 1 application, but I don't want to open application twice, so I using QShareMemory to detect application when open twice.
And my question is: how I show current application in screen when user open application the second ?
int main(int argc, char *argv[]) {
Application a(argc, argv);
/*Make sure only one instance of application can run on host system at a time*/
QSharedMemory sharedMemory;
sharedMemory.setKey ("Application");
if (!sharedMemory.create(1))
{
qDebug() << "123123Exit already a process running";
return 0;
}
/**/
return a.exec();
}
Thanks.
Here's another approach in pure Qt way:
Use QLocalServer and QLocalSocket to check the existence of application and then use signal-slot mechanism to notify the existing one.
#include "widget.h"
#include <QApplication>
#include <QObject>
#include <QLocalSocket>
#include <QLocalServer>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
const QString appKey = "applicationKey";
QLocalSocket *socket = new QLocalSocket();
socket->connectToServer(appKey);
if (socket->isOpen()) {
socket->close();
socket->deleteLater();
return 0;
}
socket->deleteLater();
Widget w;
QLocalServer server;
QObject::connect(&server,
&QLocalServer::newConnection,
[&w] () {
/*Set the window on the top level.*/
w.setWindowFlags(w.windowFlags() |
Qt::WindowStaysOnTopHint);
w.showNormal();
w.setWindowFlags(w.windowFlags() &
~Qt::WindowStaysOnTopHint
);
w.showNormal();
w.activateWindow();
});
server.listen(appKey);
w.show();
return a.exec();
}
But if you're using Qt 5.3 on Windows, there's a bug for QWidget::setWindowFlags and Qt::WindowStaysOnTopHint, see https://bugreports.qt.io/browse/QTBUG-30359.
Just use QSingleApplication class instead of QApplication:
https://github.com/qtproject/qt-solutions/tree/master/qtsingleapplication
int main(int argc, char **argv)
{
QtSingleApplication app(argc, argv);
if (app.isRunning())
return 0;
MyMainWidget mmw;
app.setActivationWindow(&mmw);
mmw.show();
return app.exec();
}
It is part of Qt Solutions: https://github.com/qtproject/qt-solutions