How does work setFeaturePermission member function in QWebEnginePage? - c++

I'm using Qt5.5.0 and wanted to know how does QWebEnginePage::setFeaturePermission work?
In this scenario I wanted to grant the loaded page media audio video capture permission but it does not work:
#include <QtWebEngineWidgets>
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QWebEngineView *view = new QWebEngineView();
view->page()->setUrl(QUrl("http://127.0.0.1:3333/index.html"));
view->page()->setFeaturePermission(view->page()->url(), QWebEnginePage::MediaAudioVideoCapture, QWebEnginePage::PermissionGrantedByUser);
view->page()->settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, true);
view->page()->settings()->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
view->show();
return app.exec();
}
What's wrong with my code?

According to the official Qt documentation for QWebEnginePage::setFeaturePermission:
Note: Call this method on featurePermissionRequested() signal, as it
is meant to serve pending feature requests only. Setting feature
permissions ahead of a request has no effect.
So, it has effect only when a feature is requested, for example here is a part of basic Qt Widget Application where QWebEngineView is created in the main window constructor and the signal featurePermissionRequested of the page (QWebEnginePage) is connected to the appropriate slot:
// slot to handle permission request
void MainWindow::featurePermissionRequested(const QUrl & securityOrigin,
QWebEnginePage::Feature feature)
{
// print origin and feature
qDebug() << securityOrigin << feature;
// grant permission
view->page()->setFeaturePermission(view->page()->url(),
QWebEnginePage::MediaAudioCapture, QWebEnginePage::PermissionGrantedByUser);
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// store web view pointer as class the member QWebEngineView *view;
view = new QWebEngineView();
// add view widget to 'verticalLayout' added to UI in UI Design
ui->verticalLayout->addWidget(view);
// set view page
view->page()->setUrl(QUrl("https://some_audio_capturing_site"));
// connect page signal with 'this' object slot
connect(view->page(),
SIGNAL(featurePermissionRequested(const QUrl&, QWebEnginePage::Feature)),
SLOT(featurePermissionRequested(const QUrl&, QWebEnginePage::Feature)));
}
I tested this example on one of audio capturing Web sites. When that site requests permission for microphone access it can be seen by debug print that the slot is triggered. It prints the site URL and 2 corresponding to QWebEnginePage::MediaAudioCapture. Nothing happens if the permission is not granted. However, after calling setFeaturePermission in that slot everything works as expected. The Web site is able to capture audio.

Related

A simple communicate c/s app using QtUdpSocket

I am a beginner of Qt.I want to use QUdpSocket to write a server app without a GUI.I have writen the client GUI app and server GUI app.They work well.But the server without GUI doesn't work well.
I try to use a while(true) loop to make the app running ,because I think after the code 'return a.exec()' the app will stop.But my server app does't work.
Here is my code:
client with GUI:
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
socket=new QUdpSocket(this);
//click pushbutton send message to server
connect(this->ui->pushButton,SIGNAL(clicked()),this,SLOT(send()));
}
Widget::~Widget()
{
delete ui;
}
//send message
void Widget::send()
{
QByteArray msg="client2:hello world";
socket->writeDatagram(msg.data(),msg.size(),QHostAddress::LocalHost,6666);
}
The client app and server with GUI app can work well.But When I try to make a server app without GUI,I found server can not get the message from client.
And here is my server.cpp without GUI:
#include "server.h"
Server::Server(QObject *parent) : QObject(parent)
{
socket=new QUdpSocket(this);
array=new QByteArray();
socket->bind(QHostAddress::LocalHost,6666,QAbstractSocket::DontShareAddress);
socket->open(QIODevice::ReadWrite); //without this line, the app will show:
//'QIOBevice::read(QUdpSocket):device not open',but it still can get the message from client.
connect(socket,SIGNAL(readyRead()),this,SLOT(printMsg()));
}
void Server::printMsg()
{
if(socket->hasPendingDatagrams()) //I forgot this line before.
{
array->resize(socket->pendingDatagramSize());
socket->readDatagram(array->data(),array->size());
socket->readAll();
qDebug()<<"yesyesyes";
}
}
I try many times,I think the problem is in my main.cpp:
#include <QCoreApplication>
#include "server.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Server s;
return a.exec();//after a.exec(),the app is still working!!!
}
In a GUI app, if I don't close the windows, the server app will always run, and the SIGNAL and SLOT I can understand.But in a console app, it seems that the app end fast and can't get the message from client(can't display the message).
You should not have a while(true) in your main, otherwise, you are effectively just freezing your thread and Qt application. This is exactly what app.exec(); is for, it will return when your application is closed (more details here)
If your application (with or without GUI) closes after calling app.exec(), it is due to one of the following:
You are closing it manually, e.g. with qApp->quit();
You are forcing an exit, e.g. with exit(1);
A fatal error or exception prematurely ends your application

Resizing web page inside a spliter in qt

My question is simple, but I have been struggling to find the solution. I have the QMainWindow showed in the image, constructed in the QtCreator.
I want to load an html web page in the QWidget csWindow, for that I have placed a Qlabel label_pic where I load my web Page. This is code so far:
MainWindow::MainWindow(QWidget *parent, Project *project) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->project = project;
QWebEngineView *view = new QWebEngineView(ui->label_pic);
view->load(QUrl("http://localhost/myWeb.html"));
////works fine, for an image
//QPixmap pix(":/img/imgs/someImage.png");
//ui->label_pic->setPixmap(pix);
//I also can load the web page in the QWidget csWindow but with the same result
//QWebEngineView *view = new QWebEngineView(ui->csWindow);
//view->load(QUrl("http://localhost/myWebb.html"));
}
The page loads fine but it does not fit into the corresponding space, It is created with a fixed size and never resize. I want the web page to be resized when I move the spliters, but I have not succed doing it.
I have tried several approaches, first just put an image in label_pic, enable the property scaled contents and works fine. Now, I want to do the same with the web page.
Thanks in advance.
The page loads fine but it does not fit into the corresponding space
This is because the size of the QWebEngineView is not know until it completes loading, so what you need is to connect to its signal loadFinished and resize label_pic :
connect(view, &QWebEngineView::loadFinished, [this]() {this->ui->label_pic->resize(this->ui->csWindow->size());});
I want the web page to be resized when I move the splitters
Then also you need to connect to signal QSplitter::splitterMoved from all your splitters and resize both csWindow and label_pic like this:
connect(ui->splitter, &QSplitter::splitterMoved, [this]() { this->view->resize(this->ui->csWindow->size()); this->ui->label_pic->resize(this->ui->csWindow->size());});
connect(ui->splitter_2, &QSplitter::splitterMoved, [this]() { this->view->resize(this->ui->csWindow->size()); this->ui->label_pic->resize(this->ui->csWindow->size());});
connect(ui->splitter_3, &QSplitter::splitterMoved, [this]() { this->view->resize(this->ui->csWindow->size()); this->ui->label_pic->resize(this->ui->csWindow->size());});
and note that this would work best if you set a layout for your window, either from designer or adding code, for instance:
QGridLayout *layout = new QGridLayout;
layout->addWidget(ui->splitter_3);
this->ui->centralWidget->setLayout(layout);
and remember you should make all connect statements before you load the view.

C++ signals and accessing QtQuick items

I am trying to write an QtQuick program which works as an intelligent interface between user and a few CLI applications. I have implemented QtQuick + JavaScript application.
A QtQuick butten emits signal that is listened by C++ layer. So far everything works well.
However, in my C++ slot function I need to write to a certain Item in QtQuick application. This Item is an TextArea which serves as Log output of CLI applications. These CLI applications are run from the slot function in C++. I store their output into a variable, and I want to show output of this variable in this Log output TextArea.
I tried a lot of things, but I didn't find the right way to do that
I'd a similar problem.
This is how I solved it.
In C++ I created a class that handles the command with a QProcess (and I expose the class to QML), which attach the readyToRead signal to a C++ function in my exposed class, this function emits another signal showOutput with the output text.
With this information I just connect my new signal to a javascript function in qml:
cppExposed.showOutput.connect(jsFunction);
And in the javascript function I just append the text
function jsFunction(output) {
OutputTextArea.text += output;
}
To expose C++ properties to QML you can have a look at the documentation here: http://doc.qt.io/qt-5/qtqml-cppintegration-exposecppattributes.html
I think the easiest way for you is to create an object of your cpp class, and set as a context property in your main.cpp before load your main.qml:
Something like this:
QQmlApplicationEngine engine;
ProcessHandler procHandler;
engine.rootContext()->setContextProperty("procHandler", &procHandler);
Now you can access your object direct from QML, and you can connect signals
procHandler.showOutput.connect(jsFunction)
And in your C++ class don't forget to connect with the process ReadyToReady signal and emit your own signal with the data:
void readyToRead() {
emit showOutput(m_proc.readAllStandardOutput());
}
UPDATE:
Your property should be set before load the QML file by the engine:
AnalyzeSignal analyzeSignal;
engine.rootContext()->setContextProperty("analyzeSignal", &analyzeSignal);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
And I don't think you need that writeToLogOutput to be a property (and it has some syntax error btw), it's a signal method, right? So it's automatically available to QML as a signal, not a property.
DON'T create a new QQMLContext.
In this line what you are doing is creating a new QQMLContext
QQmlContext *context = new QQmlContext(engine.rootContext());
context->setContextProperty("analyzeSignal", &analyzeSignal);
This won't work, as you are setting the property to the newly created context, not to the original root context.
My final solution of main function looks like this:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
AnalyzeSignal analyzeSignal;
QQmlContext *context = engine.rootContext();
context->setContextProperty("analyzeSignal", &analyzeSignal);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
// Registering slot onto a signal
QObject *win = engine.rootObjects()[0];
QObject *item = win->findChild<QObject*>("myButton");
QObject::connect(item, SIGNAL(doAnalyzeSignal(QString,QString,QString,QString)), &analyzeSignal, SLOT(cppSlot(QString,QString,QString,QString)));
return app.exec();
}
And this works!

Restoring or bringing to front Qt desktop application

I have made my app into a single instance app using the RunGuard code found on this SO question:
Qt: Best practice for a single instance app protection
What I'd like to do is when the user tries to start the application while there is one running is to bring the existing running application to the front, and if minimised, restore it.
In my Delphi Windows programming days I used to broadcast a Windows message from the new application before closing it. The existing app would receive this and restore itself and come to the front.
Is something like this possible with Qt on Windows and Linux platforms?
Did you have any specific trouble with QtSingleApplication? It should be sufficient for what you want and will enable you to send a message to the running application. You just need a slot to get that message and if it matches what you expect then you restore it.
http://doc.qt.digia.com/solutions/4/qtsingleapplication/qtsingleapplication-example-trivial.html
The logview object is also set as the application's activation window. Every time a message is received, the window will be raised and activated automatically.
For some reason setActivationWindow() and activateWindow() don't work for me. This is my workaround:
#include <QWidget>
#include <qtsingleapplication.h>
class Window : public QWidget
{
Q_OBJECT
public:
Window(QWidget *parent = 0) : QWidget(parent) {}
public slots:
void readMessage(const QString &str) { showNormal(); }
};
int main(int argc, char *argv[])
{
QtSingleApplication instance(argc, argv);
Window *window = new Window;
window->show();
QObject::connect(&instance, SIGNAL(messageReceived(const QString &)), window, SLOT(readMessage(const QString &)));
if (instance.sendMessage(""))
return 0;
return instance.exec();
}
#include "main.moc"
In common, it is not possible without IPC. QtSingleApplication provide such IPC, but you will get extra dependency from QtNetwork module. (As #svlasov answered)
First problem that you will have: you can't raise any window of application if this application is not foreground. There are solutions for Windows and OS X, how to force raising of windows.

Qt opening another window when first one has closed

I´ve beeing programming Java for some time right now...Now that I got into C++ and Qt I am a bit lost about GUI Thread (EDT Thread) and Worker Thread
I am trying to make the main window of my application open only when the configuration window is closed.
I dont want to put the code for creating the main window in the OK button of my configuration window.
I tryed to make them modal but the main window still opens.....
Afther configuration is complete I still have to see if there is an application update...So its something like
EDIT: This is my main:
ConfigurationWindow *cw = new ConfigurationWindow();
//if there is no text file - configuration
cw->show();
//**I need to stop here until user fills the configuration
MainWindow *mw = new MainWindow();
ApplicationUpdateThread *t = new ApplicationUpdateThread();
//connect app update thread with main window and starts it
mw->show();
Try something like this:
#include <QtGui>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QDialog *dialog = new QDialog;
QSlider *slider = new QSlider(dialog);
QHBoxLayout *layout = new QHBoxLayout(dialog);
layout->addWidget(slider);
dialog->setLayout(layout);
dialog->exec();
qDebug() << slider->value(); // prints the slider's value when dialog is closed
QMainWindow mw; // in your version this could be MainWindow mw(slider->value());
w.show();
return a.exec();
}
The idea is that your main window's constructor could accept parameters from the QDialog. In this contrived example I'm just using qDebug() to print the value of the slider in the QDialog when it's closed, not passing it as a parameter, but you get the point.
EDIT: You might also want to "delete" the dialog before creating the main window in order to save memory. In that case you would need to store the parameters for the main window constructor as separate variables before deleting the dialog.
You have to learn about signals and slots. The basic idea is that you would send a signal when you configuration is finished. You put your QMainWindow in a member variable and call mw->show() in a slot of your main programm that is connected with the configurationFinished signal.
If your ConfigurationWindow is a QDialog, you could connect the finished(int) signal to the MainWindow's show() slot (and omit the show() call from main).