Unable to open file with qt app on mac - c++

I am trying to associate custom files with an osx app. I have a plist that associates files with the app, but double clicking a file opens the app with no data inside.
Calling
someapp.app/Contents/MacOs/someapp somefile.abc
from the terminal opens the file correctly inside the app.
MyApp::MyApp(int& argc, char**argv): QApplication(argc, argv)
{
...
m_MainWindow = new MainWindows();
m_MainWindow->show();
if(argc > 1 && argv[1])
m_MainWindow->openFile(QString(argv[1]);
else
m_MainWindow->showStartupDialog(); // to create a new document
}
Searching around I found that I should somehow implement QFileOpenEvent... how ?
This example looks good... but I don't understand how to combine the constructor and the event...
How do I make this work ?
(OS X 10.6-10.9, app created using Qt 4.8)

The following is the adapted code, that will respond to the OpenFileEvent either on start or during the normal functioning - and also allow opening o file from command line or creating a new file
MyApp::MyApp(int& argc, char**argv): QApplication(argc, argv)
{
...
m_MainWindow = new MainWindows();
m_MainWindow->show();
if(argc > 1 && argv[1])
m_MainWindow->openFile(QString(argv[1]);
else if (m_macFileOpenOnStart != "")
m_MainWindow->openFile(m_macFileOpenOnStart); // open file on start if it exists
else
m_MainWindow->showStartupDialog(); // to create a new document
}
// responds to FileOpenEvent specific for mac
bool MyApp::event(QEvent *event)
{
switch(event->type())
{
case QEvent::FileOpen:
{
QFileOpenEvent * fileOpenEvent = static_cast<QFileOpenEvent *>(event);
if(fileOpenEvent)
{
m_macFileOpenOnStart = fileOpenEvent->file();
if(!m_macFileOpenOnStart.isEmpty())
{
if (m_MainWindow)
{
m_MainWindow->openFile(m_macFileOpenOnStart); // open file in existing window
}
return true;
}
}
}
default:
return QApplication::event(event);
}
return QApplication::event(event);
}

i'm using a QApplication derived class that emits a signal when file is ready:
#ifndef OPENWITHAPPLICATION_H
#define OPENWITHAPPLICATION_H
#include <QApplication>
#include <QFileOpenEvent>
#include <QMessageBox>
class OpenWithApplication : public QApplication
{
Q_OBJECT
public:
QString fileName;
OpenWithApplication(int &argc, char **argv)
: QApplication(argc, argv)
{
}
signals:
void fileReady(QString fn);
protected:
bool event(QEvent *event)
{
if (event->type() == QEvent::FileOpen) {
QFileOpenEvent *openEvent = static_cast<QFileOpenEvent *>(event);
fileName = openEvent->file();
emit fileReady(fileName); // the file is ready
}
return QApplication::event(event);
}
};
#endif // OPENWITHAPPLICATION_H
main.cpp connects created OpenWindowApplication with the MainWindow object so once the file is ready, the signal is emitted and received by it for processing
#include "mainwindow.h"
#include <openwithapplication.h>
int main(int argc, char *argv[])
{
OpenWithApplication a(argc, argv);
MainWindow w;
w.connectOpenWithApp(&a);
w.show();
return a.exec();
}
and MainWindow connects fileReady signal with a lambda func that opens the file and updates widget
void MainWindow::connectOpenWithApp(OpenWithApplication*app) {
connect(app, &OpenWithApplication::fileReady, [this](QString fileName){
bw->open(fileName);
bw->update();
});
}
here's the result:

Related

Unable to connect using QML Remote Object with Error: "connectionToSource is null"

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);
}
}

Accessing QMLEngine /rootObject properties in .cpp files other than main.cpp

I have two radio buttons in one panel defined in one .qml file.
I need to access the property whether it is checked or not in another QML file or in .cpp file of some c++ class.
I am able to do it in main.cpp
using these lines below
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if(engine.rootObjects().isEmpty())
return -1;
// Step 1: get access to the root object
QObject *rootObject = engine.rootObjects().first();
QObject *qmlObject_serial_radio = rootObject->findChild<QObject*>("serial_radio");
QObject *qmlObject_tcpip_radio = rootObject->findChild<QObject*>("tcpip_radio");
// Step 2a: set or get the desired property value for the root object
qDebug() << qmlObject_serial_radio->property("checked");
qDebug() << qmlObject_tcpip_radio->property("checked");
But I want to do the same in some other .cpp file.
how to do it?
Instancing QML objects in C++ can be dangerous since the life cycle of the items is not handled directly in C++ so QML could eliminate them without notifying it as for example the StackView where Pages are created and deleted.
A better approach is to export the C ++ object to the QML:
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QDebug>
class Helper: public QObject{
Q_OBJECT
Q_PROPERTY(bool isSerialEnabled READ isSerialEnabled WRITE setIsSerialEnabled NOTIFY isSerialEnabledChanged)
Q_PROPERTY(bool isTcpIpEnabled READ isTcpIpEnabled WRITE setIsTcpIpEnabled NOTIFY isTcpIpEnabledChanged)
public:
using QObject::QObject;
bool isSerialEnabled() const{
return mIsSerialEnabled;
}
void setIsSerialEnabled(bool isSerialEnabled){
if(mIsSerialEnabled == isSerialEnabled) return;
mIsSerialEnabled = isSerialEnabled;
emit isSerialEnabledChanged(mIsSerialEnabled);
}
bool isTcpIpEnabled () const{
return mIsTcpIpEnabled ;
}
void setIsTcpIpEnabled (bool isTcpIpEnabled ){
if(mIsTcpIpEnabled == isTcpIpEnabled ) return;
mIsTcpIpEnabled = isTcpIpEnabled ;
emit isTcpIpEnabledChanged(mIsTcpIpEnabled );
}
signals:
void isSerialEnabledChanged(bool);
void isTcpIpEnabledChanged(bool);
private:
bool mIsSerialEnabled;
bool mIsTcpIpEnabled ;
};
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
Helper helper;
// check changes
QObject::connect(&helper, &Helper::isSerialEnabledChanged, [](bool isSerialEnabled){
qDebug()<<"isSerialEnabled"<<isSerialEnabled;
});
QObject::connect(&helper, &Helper::isTcpIpEnabledChanged, [](bool isSerialEnabled){
qDebug()<<"isTcpIpEnabledChanged"<<isSerialEnabled;
});
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("helper", &helper);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
#include "main.moc"
main.qml
RadioButton {
text: "Serial"
onCheckedChanged: helper.isSerialEnabled = checked
}
RadioButton {
text: "tcpip"
onCheckedChanged: helper.isTcpIpEnabled = checked
}

Auto Grant access to Mic and Camera with Qt WebEngine

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"

How I show application when open application again Qt

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

how to restart my own qt application?

i just asking myself how to restart my own qt application?
Can somebody please show me an example?
To restart application, try:
#include <QApplication>
#include <QProcess>
...
// restart:
qApp->quit();
QProcess::startDetached(qApp->arguments()[0], qApp->arguments());
I'm taking the other answers solutions, but better. No need for pointers, but there is a need for a ; after the while statement of a do { ... } while( ... ); construct.
int main(int argc, char *argv[])
{
const int RESTART_CODE = 1000;
do
{
QApplication app(argc, argv);
MainWindow main_window(app);
} while( app.exec() == RESTART_CODE);
return return_from_event_loop_code;
}
Assuming that 1337 is your restart code:
main.cxx
int main(int argc, char * argv[])
{
int result = 0;
do
{
QCoreApplication coreapp(argc, argv);
MyClass myObj;
result = coreapp.exec();
} while( result == 1337 );
return result;
}
myClass.cxx
qApp->exit(1337);
To restart a running Qt application (at least in Qt 5.15.2) you can do the following:
#include <QApplication>
#include <QProcess>
//...
QString program = qApp->arguments()[0];
QStringList arguments = qApp->arguments().mid(1); // remove the 1st argument - the program name
qApp->quit();
QProcess::startDetached(program, arguments);
Doing a real process restart without subclassing:
QCoreApplication a(argc, argv);
int returncode = a.exec();
if (returncode == -1)
{
QProcess* proc = new QProcess();
proc->start(QCoreApplication::applicationFilePath());
}
return returncode;
Edit for Mac OS like earlier example.
To restart call
QCoreApplication::exit(-1);
somewhere in your code.
Take a look at How to restart an application thread on qtcentre.org, where muisei gives this code
#define RESTART_CODE 1000
int main(int argc, char *argv[])
{
int return_from_event_loop_code;
QPointer<QApplication> app;
QPointer<MainWindow> main_window;
do
{
if(app) delete app;
if(main_window) delete main_window;
app = new QApplication(argc, argv);
main_window = new MainWindow(app);
return_from_event_loop_code = app->exec();
}
while(return_from_event_loop_code==RESTART_CODE)
return return_from_event_loop_code;
}
I just used the method described above and I noticed that my application crashes on restart.
...then I switched the following lines of code:
if(app) delete app;
if(main_window) delete main_window;
to:
if(main_window) delete main_window;
if(app) delete app;
and it behaves OK. For some reason the window must be deleted first.
Just a note for future readers.
EDIT: ...and a different approach for those who want a real process-restart: You can declare a myApp::Restart() method in your subclass of QApplication. The following version works OK on both MS-Windows & MacOS:
// Restart Application
void myApp::Restart(bool Abort)
{
// Spawn a new instance of myApplication:
QProcess proc;
#ifdef Q_OS_WIN
proc.start(this->applicationFilePath());
#endif
#ifdef Q_OS_MAC
// In Mac OS the full path of aplication binary is:
// <base-path>/myApp.app/Contents/MacOS/myApp
QStringList args;
args << (this->applicationDirPath() + "/../../../myApp.app");
proc.start("open", args);
#endif
// Terminate current instance:
if (Abort) // Abort Application process (exit immediattely)
::exit(0);
else
this->exit(0); // Exit gracefully by terminating the myApp instance
}
This slight variation on Rubenvb's idea works with PyQt. clearSettings is the method that triggers the restart.
class GuiMain
#Most of implementation missing
def clearSettings(self):
#Clearing the settings missing
QApplication.exit(GuiMain.restart_code)
restart_code = 1000
#staticmethod
def application_main():
"""
The application's main function.
Create application and main window and run them.
"""
while True:
app = QApplication(sys.argv)
window = GuiMain()
window.show()
ret = app.exec_()
if ret != GuiMain.restart_code:
break
del window
del app
Here is the code:
main.cpp:
int main(int argc, char *argv[])
{
int currentExitCode = 0;
do {
QApplication a(argc, argv);
MainWindow w;
w.show();
currentExitCode = a.exec();
} while( currentExitCode == MainWindow::EXIT_CODE_REBOOT );
return currentExitCode;
}
mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
static int const EXIT_CODE_REBOOT;//THIS IS THE IMPORTANT THING TO ADD TO YOUR CODE
~MainWindow();
private slots:
void slotReboot();//AND THIS ALSO
//ALL THE OTHER VARIABLES
}
The slotReboot() is the slot that will receive the signal of the QAction I'm going to show in the mainwindow.cpp
mainwindow.cpp
First initialize EXIT_CODE_REBOOT :
int const MainWindow::EXIT_CODE_REBOOT = -123456789;
and declare a QAction pointer:
QAction* actionReboot;
then in the MainWindow constructor:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
actionReboot = new QAction( this );
actionReboot->setText( tr("Restart") );
actionReboot->setStatusTip( tr("Restarts the application") );
connect( actionReboot, SIGNAL (triggered()),this, SLOT (slotReboot()));
}
And finally you need to send the signal (in the part of your code you need), in this way:
actionReboot->trigger();
I did the code I showed following these instructions: How to make an application restartable - Qt Wiki
You can use my open source library:
https://marketplace.qt.io/products/main-loop-wdt-for-qt-qml
It's a watchdog timer for the main qt loop, but I have a function for forced reboot, with different strategies: startdetached + exit, exec system call on Linux / macOS, and delayed restart (for example, exit and restart after 3 seconds)