How to manipulate multiple Folders/Dir in QT? - c++

I want to know how to manipulate directories until I get video files.
Firstly the main Directory is "F:/TestingVideos/"
Inside the test video there are files e.g:1. Cash Office ,2.Rosville Gate ,3. My Videos
Each of this videos holds other folders for example Cash Office has a Directory of "F:/TestingVideos/Cash Office/" inside we have folders that have dates for example we have the following "F:/TestingVideos/Cash Office/20141201/" Inside the Date Folder I have videos that I want to play.
So far I have implemented a method:
void Dialog::on_loadedButton_clicked(){
QString videoname = "F:/TestingVideos/";`
ui->DirectoryLineEdit->setText(videoName);
QDir dir(videoName);
QFileInfoList files = dir.entryInfoList();
QStringList MonTypeFolder = dir.entryList(QDir::NoDotAndDotDot | QDir::AllDirs, QDir::DirsFirst);
ui->MonitoringcomboBox->addItems( MonTypeFolder);
ui->MonitoringcomboBox->show();
foreach(QFileInfo file, files){
if(file.isDir()){
//qDebug() << "DIR: " << file.fileName();
// qDebug() << "Directory path file:" << file.absoluteFilePath();
QString filePathString = file.absoluteFilePath();
QFileInfo info = QFileInfo(filePathString);
qDebug() << "Folders" << " are writable: " << info.isWritable() << "are readable: " << info.isReadable();
}
if(file.isFile()){
qDebug() << "FILE: " << file.fileName();
}
}
my output is true for my QFileInfo info; for writeable and readable, also I do did a qDebug()<< info.absoluteFilePath() I got the following results:
"F:/TestingVideos"
"F:/"
"F:/TestingVideos/Cash Office"
"F:/TestingVideos/Rosville"
"F:/TestingVideos/My Videos"
I want a way to manipulate the baseNames i.e. Cash Office, Rosville etc... Folders such that I can display their folders e.g. 20141201 in another combobox, since currently ui.monitoringcomboBox->show() can display the base names. I want to be able to manipulate the folders basically To a level where I where I can play a video using QUrl for example.

If i understood correctly you want something like this:
My code is a bit rough but you can use it as starting point:
-MainWindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QComboBox>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
QComboBox *mainCB_;
QComboBox *baseCB_;
QComboBox *datesCB_;
QComboBox *mediaCB_;
QString path_;
QStringList media_;
void createComboBoxes();
private slots:
void onBaseComboBoxActivated(QString folderText);
void onDatesComboBoxActivated(QString folderText);
void onMediaComboBoxActivated(QString folderText);
};
#endif // MAINWINDOW_H
-MainWindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDir>
#include <QDebug>
#define CBWidth 140
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
media_()
{
ui->setupUi(this);
setFixedSize(840, 400);
path_ = "/Users/its/Desktop/Testing Videos"; //insert your root folder path here
media_ << "*.3gp" << "*.avi" << "*.m4v" << "*.mov" << "*.mp4" << "*.mpeg" << "*.mpg" << "*.3g2" << "*.mxf" << "*.swf" << "*.m2v" << "*.wmv" << "*.flv" << "*.mkv";
QDir dir(path_);
if(dir.exists())
{
createComboBoxes();
}
else
{
qDebug() << "Error: Main dir " << path_ << " doesn't exist.";
}
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::createComboBoxes()
{
mainCB_ = new QComboBox(this);
mainCB_->addItem(path_.section('/', -1));
mainCB_->setFixedWidth(CBWidth);
mainCB_->move(50, 50);
baseCB_ = new QComboBox(this);
baseCB_->setFixedWidth(CBWidth);
baseCB_->move(250, 50);
datesCB_ = new QComboBox(this);
datesCB_->setFixedWidth(CBWidth);
datesCB_->move(450, 50);
mediaCB_ = new QComboBox(this);
mediaCB_->setFixedWidth(CBWidth);
mediaCB_->move(650, 50);
QDir mainFolderDir(path_);
QStringList mainFolderContent = mainFolderDir.entryList(QDir::NoDotAndDotDot | QDir::AllDirs, QDir::DirsFirst);
baseCB_->addItems(mainFolderContent);
connect(baseCB_, SIGNAL(activated(QString)), this, SLOT(onBaseComboBoxActivated(QString)));
onBaseComboBoxActivated(baseCB_->itemText(0));
connect(datesCB_, SIGNAL(activated(QString)), this, SLOT(onDatesComboBoxActivated(QString)));
connect(mediaCB_, SIGNAL(activated(QString)), this, SLOT(onMediaComboBoxActivated(QString)));
}
void MainWindow::onBaseComboBoxActivated(QString folderText)
{
QDir baseFolderDir(path_ + "/" + folderText);
if(baseFolderDir.exists())
{
QStringList baseFolderContent = baseFolderDir.entryList(QDir::NoDotAndDotDot | QDir::AllDirs, QDir::DirsFirst);
datesCB_->clear();
datesCB_->addItems(baseFolderContent);
onDatesComboBoxActivated(datesCB_->itemText(0));
}
else
{
qDebug() << "Error: Base dir " << path_ + "/" + folderText << " doesn't exist.";
}
}
void MainWindow::onDatesComboBoxActivated(QString datesText)
{
QDir datesFolderDir(path_ + "/" + baseCB_->currentText() + "/" + datesText);
if(datesFolderDir.exists())
{
QStringList datesFolderContent = datesFolderDir.entryList(media_, QDir::Files, QDir::Name);
mediaCB_->clear();
mediaCB_->addItems(datesFolderContent);
onMediaComboBoxActivated(mediaCB_->itemText(0));
}
else
{
qDebug() << "Error: Dates dir " << path_ + "/" + baseCB_->currentText() + "/" + datesText << " doesn't exist.";
}
}
void MainWindow::onMediaComboBoxActivated(QString mediaText)
{
qDebug() << "Media selected with URL:" << path_ + "/" + baseCB_->currentText() + "/" + datesCB_->currentText() + "/" + mediaText;
}
I hope this will help you.

Related

capture QVideoFrame and display it in QVideoWidget

I want capture from camera frames.
I setup ui, camera, and surface.
QtVideoWidgetsIssueTrack::QtVideoWidgetsIssueTrack(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
QCamera* mCamera = new QCamera();
QMediaRecorder* recorder = new QMediaRecorder(mCamera);
QVideoEncoderSettings settings = recorder->videoSettings();
QMyAbstractVideoSurface* surface = new QMyAbstractVideoSurface();
settings.setResolution(640, 480);
settings.setQuality(QMultimedia::VeryHighQuality);
settings.setFrameRate(30.0);
settings.setCodec("video/mp4");
recorder->setVideoSettings(settings);
recorder->setContainerFormat("mp4");
mCamera->setCaptureMode(QCamera::CaptureViewfinder);
mCamera->setViewfinder(surface);
// Set layout
QGridLayout* layout = new QGridLayout();
QVideoWidget* videoWidget = new QVideoWidget;
videoWidget->show();
// Set layout in QWidget
QWidget* window = new QWidget();
layout->addWidget(videoWidget);
window->setLayout(layout);
// Set QWidget as the central layout of the main window
setCentralWidget(window);
bool o = recorder->setOutputLocation(QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + "/" + "test_video"));
recorder->record();
mCamera->start();
qDebug() << o;
qDebug() << recorder->supportedVideoCodecs();
qDebug() << recorder->state();
qDebug() << recorder->error();
qDebug() << recorder->outputLocation();
}
QtVideoWidgetsIssueTrack::~QtVideoWidgetsIssueTrack()
{}
I have created QMyAbstractVideoSurface instance and set surface in camera.
#pragma once
#include <QtMultimedia/QAbstractVideoSurface>
class QMyAbstractVideoSurface : public QAbstractVideoSurface
{
Q_OBJECT
public:
explicit QMyAbstractVideoSurface(QObject* parent = 0);
~QMyAbstractVideoSurface();
QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const;
bool present(const QVideoFrame& frame);
bool start(const QVideoSurfaceFormat& format);
void stop();
};
Now the problem is capture QVideoFrame from present method and display it in QVideoWidget.
Then add QVideoWidget to grid layout.
#include "QMyAbstractVideoSurface.h"
#include <QDebug>
#include <QBuffer>
QMyAbstractVideoSurface::QMyAbstractVideoSurface(QObject* parent) {
}
bool QMyAbstractVideoSurface::start(const QVideoSurfaceFormat& format) {
return QAbstractVideoSurface::start(format);
}
void QMyAbstractVideoSurface::stop() {
QAbstractVideoSurface::stop();
}
bool QMyAbstractVideoSurface::present(const QVideoFrame& frame) {
if (frame.isValid()) {
QVideoFrame cloneFrame(frame);
QAbstractVideoBuffer::HandleType handleType;
cloneFrame.map(QAbstractVideoBuffer::ReadOnly);
qDebug() << cloneFrame;
const QImage image(cloneFrame.bits(),
cloneFrame.width(),
cloneFrame.height(),
QVideoFrame::imageFormatFromPixelFormat(cloneFrame.pixelFormat()));
QByteArray ba;
QBuffer bu(&ba);
//bu.open(QBuffer::ReadWrite);
bu.open(QIODevice::WriteOnly);
image.save(&bu, "PNG");
//bu.close();
//QString imgBase64 = ba.toBase64();
QString imgBase64 = QString::fromLatin1(ba.toBase64().data());
qDebug() << "image base64: " << imgBase64;
cloneFrame.unmap();
return true;
}
return true;
}
QList<QVideoFrame::PixelFormat> QMyAbstractVideoSurface::
supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const
{
Q_UNUSED(handleType);
return QList<QVideoFrame::PixelFormat>()
<< QVideoFrame::Format_ARGB32
<< QVideoFrame::Format_ARGB32_Premultiplied
<< QVideoFrame::Format_RGB32
<< QVideoFrame::Format_RGB24
<< QVideoFrame::Format_RGB565
<< QVideoFrame::Format_RGB555
<< QVideoFrame::Format_ARGB8565_Premultiplied
<< QVideoFrame::Format_BGRA32
<< QVideoFrame::Format_BGRA32_Premultiplied
<< QVideoFrame::Format_BGR32
<< QVideoFrame::Format_BGR24
<< QVideoFrame::Format_BGR565
<< QVideoFrame::Format_BGR555
<< QVideoFrame::Format_BGRA5658_Premultiplied
<< QVideoFrame::Format_AYUV444
<< QVideoFrame::Format_AYUV444_Premultiplied
<< QVideoFrame::Format_YUV444
<< QVideoFrame::Format_YUV420P
<< QVideoFrame::Format_YV12
<< QVideoFrame::Format_UYVY
<< QVideoFrame::Format_YUYV
<< QVideoFrame::Format_NV12
<< QVideoFrame::Format_NV21
<< QVideoFrame::Format_IMC1
<< QVideoFrame::Format_IMC2
<< QVideoFrame::Format_IMC3
<< QVideoFrame::Format_IMC4
<< QVideoFrame::Format_Y8
<< QVideoFrame::Format_Y16
<< QVideoFrame::Format_Jpeg
<< QVideoFrame::Format_CameraRaw
<< QVideoFrame::Format_AdobeDng;
}
QMyAbstractVideoSurface::~QMyAbstractVideoSurface()
{}
it display me this
QVideoFrame(QSize(640, 480), Format_YUYV, NoHandle, ReadOnly, [no timestamp])
image base64: ""

Qt 6.2: QMediaPlayer & QByteArray

Good day.
Has anyone tried QMediaPlayer in Qt 6.2 already?
I'm trying this code, but Media Status always remains as "NoMedia" and no any sound :).
Full test project: https://github.com/avttrue/MediaPlayerTest
#include "mainwindow.h"
#include <QDebug>
#include <QBuffer>
#include <QFile>
#include <QAudioOutput>
#include <QMediaPlayer>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QFile file("../test/Bankrobber.mp3");
if(!file.open(QIODevice::ReadOnly))
qDebug() << "File not opened";
qDebug() << "File size:" << file.size(); // File size: 11181085
QByteArray ba = file.readAll();
qDebug() << "ByteArray size:" << ba.size(); // ByteArray size: 11181085
QBuffer* buffer = new QBuffer(this);
buffer->setData(ba);
if(!buffer->open(QIODevice::ReadOnly))
qDebug() << "Buffer not opened";
qDebug() << "Buffer size:" << buffer->size(); // Buffer size: 11181085
buffer->seek(qint64(0));
auto audioOutput = new QAudioOutput(this);
auto player = new QMediaPlayer(this);
player->setAudioOutput(audioOutput);
audioOutput->setVolume(50);
player->setSourceDevice(buffer);
qDebug() << "Device:" << player->sourceDevice(); // Device: QBuffer(0x563180493020)
QObject::connect(player, &QMediaPlayer::mediaStatusChanged,
[=](QMediaPlayer::MediaStatus status)
{ qDebug() << "MediaStatus:" << player->mediaStatus() << "|" << status; });
QObject::connect(player, &QMediaPlayer::errorOccurred,
[=](QMediaPlayer::Error error)
{ qDebug() << "Error:" << player->errorString() << "|" << error; });
QObject::connect(player, &QMediaPlayer::playbackStateChanged,
[=](QMediaPlayer::PlaybackState state)
{ qDebug() << "PlaybackState:" << player->playbackState() << "|" << state; });
player->play();
qDebug() << "MediaStatus:" << player->mediaStatus(); // MediaStatus: QMediaPlayer::NoMedia
}
As the docs points out:
void QMediaPlayer::setSourceDevice(QIODevice *device, const QUrl
&sourceUrl = QUrl())
Sets the current source device.
The media data will be read from device. The sourceUrl can be provided
to resolve additional information about the media, mime type etc. The
device must be open and readable.
For macOS the device should also be seek-able.
Note: This function returns immediately after recording the specified
source of the media. It does not wait for the media to finish loading
and does not check for errors. Listen for the mediaStatusChanged() and
error() signals to be notified when the media is loaded, and if an
error occurs during loading.
(emphasis mine)
QMediaPlayer does not know how to deduce the file format so it does not load it. The solution is to point out that it is an mp3:
player->setSourceDevice(buffer, QUrl("foo.mp3"));
The function setSourceDevice() you are using isn't doing what you think?
Maybe you wanted setSource() instead?
Qt has great documentation:
https://doc.qt.io/qt-6/qmediaplayer.html#setSourceDevice
Even good examples:
player = new QMediaPlayer;
audioOutput = new QAudioOutput;
player->setAudioOutput(audioOutput);
connect(player, SIGNAL(positionChanged(qint64)), this, SLOT(positionChanged(qint64)));
player->setSource(QUrl::fromLocalFile("/Users/me/Music/coolsong.mp3"));
audioOutput->setVolume(50);
player->play();
Ref.
https://doc.qt.io/qt-6/qmediaplayer.html#details
May be this is as variant, but i think it not good:
QTemporaryFile tfile;
if (!tfile.open())
qDebug() << "TemporaryFile not opened";
else
{
qDebug() << "TemporaryFile writed:" << tfile.write(ba);
if(tfile.size() != ba.size())
qDebug() << "TemporaryFile not complited";
else
player->setSource(QUrl::fromLocalFile(tfile.fileName()));
}

how to get latitude/longitude from geo address using Qt c++ QGeoServiceProvider?

I am trying to use the osm api via a QGeoServiceProvider and QGeoCodingManager to derive the latitude and longitude from a given physical address.
Thereby I stumbled upon this Question, which seems to do exactly what I need.
However I want to implement this in a qt gui application as a separate function and I don' t understand what is happening in the connect.
Could someone please explain or how I can modify it to get it to work in a function ?
cout << "Try service: " << "osm" << endl;
// choose provider
QGeoServiceProvider qGeoService("osm");
QGeoCodingManager *pQGeoCoder = qGeoService.geocodingManager();
if (!pQGeoCoder) {
cerr
<< "GeoCodingManager '" << "osm"
<< "' not available!" << endl;
}
QLocale qLocaleC(QLocale::C, QLocale::AnyCountry);
pQGeoCoder->setLocale(qLocaleC);
// build address
QGeoAddress qGeoAddr;
qGeoAddr.setCountry(QString::fromUtf8("Germany"));
qGeoAddr.setPostalCode(QString::fromUtf8("88250"));
qGeoAddr.setCity(QString::fromUtf8("Weingarten"));
qGeoAddr.setStreet(QString::fromUtf8("Heinrich-Hertz-Str. 6"));
QGeoCodeReply *pQGeoCode = pQGeoCoder->geocode(qGeoAddr);
if (!pQGeoCode) {
cerr << "GeoCoding totally failed!" << endl;
}
cout << "Searching..." << endl;
QObject::connect(pQGeoCode, &QGeoCodeReply::finished,
[&qGeoAddr, pQGeoCode](){
cout << "Reply: " << pQGeoCode->errorString().toStdString() << endl;
switch (pQGeoCode->error()) {
#define CASE(ERROR) \
case QGeoCodeReply::ERROR: cerr << #ERROR << endl; break
CASE(NoError);
CASE(EngineNotSetError);
CASE(CommunicationError);
CASE(ParseError);
CASE(UnsupportedOptionError);
CASE(CombinationError);
CASE(UnknownError);
#undef CASE
default: cerr << "Undocumented error!" << endl;
}
if (pQGeoCode->error() != QGeoCodeReply::NoError) return;
// eval. result
QList<QGeoLocation> qGeoLocs = pQGeoCode->locations();
cout << qGeoLocs.size() << " location(s) returned." << endl;
for (QGeoLocation &qGeoLoc : qGeoLocs) {
qGeoLoc.setAddress(qGeoAddr);
QGeoCoordinate qGeoCoord = qGeoLoc.coordinate();
cout
<< "Lat.: " << qGeoCoord.latitude() << endl
<< "Long.: " << qGeoCoord.longitude() << endl
<< "Alt.: " << qGeoCoord.altitude() << endl;
}
});
So I just removed the QApplication part because I dont have this reference in a function. As a result i get:
Qt Version: 5.10.0
Try service: osm
Searching...
but no coordinates. I assume the connection to where the lat and lon data is acquired fails. But as I mentioned I dont understand the connect here.
Any help is appreciated
EDIT
so I tried to build a connect to catch the finished Signal as suggested.
The code now looks like this:
QGeoServiceProvider qGeoService("osm");
QGeoCodingManager *pQGeoCoder = qGeoService.geocodingManager();
if (!pQGeoCoder) {
cerr
<< "GeoCodingManager '" << "osm"
<< "' not available!" << endl;
}
QLocale qLocaleC(QLocale::C, QLocale::AnyCountry);
pQGeoCoder->setLocale(qLocaleC);
// build address
//QGeoAddress qGeoAddr;
qGeoAddr.setCountry(QString::fromUtf8("Germany"));
qGeoAddr.setPostalCode(QString::fromUtf8("88250"));
qGeoAddr.setCity(QString::fromUtf8("Weingarten"));
qGeoAddr.setStreet(QString::fromUtf8("Heinrich-Hertz-Str. 6"));
this->pQGeoCode = pQGeoCoder->geocode(qGeoAddr);
if (!pQGeoCode) {
cerr << "GeoCoding totally failed!" << endl;
}
cout << "Searching..." << endl;
connect(pQGeoCode,SIGNAL(finished()),this,SLOT(getlonlat()));
With the Slot:
void MainWindow::getlonlat()
{
QList<QGeoLocation> qGeoLocs = pQGeoCode->locations();
cout << qGeoLocs.size() << " location(s) returned." << endl;
for (QGeoLocation &qGeoLoc : qGeoLocs) {
qGeoLoc.setAddress(qGeoAddr);
QGeoCoordinate qGeoCoord = qGeoLoc.coordinate();
cout
<< "Lat.: " << qGeoCoord.latitude() << endl
<< "Long.: " << qGeoCoord.longitude() << endl
<< "Alt.: " << qGeoCoord.altitude() << endl;
}
}
However the finished signal doesn't get triggered. Therefore the result is the same.
EDIT
Implementing the Code from your Gui Answer:
MainWindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
// standard C++ header:
#include <iostream>
#include <sstream>
// Qt header:
#include <QGeoAddress>
#include <QGeoCodingManager>
#include <QGeoCoordinate>
#include <QGeoLocation>
#include <QGeoServiceProvider>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
QGeoServiceProvider *pQGeoProvider = nullptr;
ui->setupUi(this);
qDebug() << "Qt Version:" << QT_VERSION_STR;
// main application
//QApplication app(argc, argv);
// install signal handlers
QObject::connect(this->ui->qBtnInit, &QPushButton::clicked,
[&]() {
if (pQGeoProvider) delete pQGeoProvider;
std::ostringstream out;
pQGeoProvider = init(out);
log(out.str());
});
QObject::connect(this->ui->qBtnFind, &QPushButton::clicked,
[&]() {
// init geo coder if not yet done
if (!pQGeoProvider) {
std::ostringstream out;
pQGeoProvider = init(out);
log(out.str());
if (!pQGeoProvider) return; // failed
}
// fill in request
QGeoAddress *pQGeoAddr = new QGeoAddress;
pQGeoAddr->setCountry(this->ui->qTxtCountry->text());
pQGeoAddr->setPostalCode(this->ui->qTxtZipCode->text());
pQGeoAddr->setCity(this->ui->qTxtCity->text());
pQGeoAddr->setStreet(this->ui->qTxtStreet->text());
QGeoCodeReply *pQGeoCode
= pQGeoProvider->geocodingManager()->geocode(*pQGeoAddr);
if (!pQGeoCode) {
delete pQGeoAddr;
log("GeoCoding totally failed!\n");
return;
}
{ std::ostringstream out;
out << "Sending request for:\n"
<< pQGeoAddr->country().toUtf8().data() << "; "
<< pQGeoAddr->postalCode().toUtf8().data() << "; "
<< pQGeoAddr->city().toUtf8().data() << "; "
<< pQGeoAddr->street().toUtf8().data() << "...\n";
log(out.str());
}
// install signal handler to process result later
QObject::connect(pQGeoCode, &QGeoCodeReply::finished,
[&,pQGeoAddr, pQGeoCode]() {
// process reply
std::ostringstream out;
out << "Reply: " << pQGeoCode->errorString().toStdString() << '\n';
switch (pQGeoCode->error()) {
case QGeoCodeReply::NoError: {
// eval result
QList<QGeoLocation> qGeoLocs = pQGeoCode->locations();
out << qGeoLocs.size() << " location(s) returned.\n";
for (QGeoLocation &qGeoLoc : qGeoLocs) {
qGeoLoc.setAddress(*pQGeoAddr);
QGeoCoordinate qGeoCoord = qGeoLoc.coordinate();
out
<< "Lat.: " << qGeoCoord.latitude() << '\n'
<< "Long.: " << qGeoCoord.longitude() << '\n'
<< "Alt.: " << qGeoCoord.altitude() << '\n';
}
} break;
#define CASE(ERROR) \
case QGeoCodeReply::ERROR: out << #ERROR << '\n'; break
CASE(EngineNotSetError);
CASE(CommunicationError);
CASE(ParseError);
CASE(UnsupportedOptionError);
CASE(CombinationError);
CASE(UnknownError);
#undef CASE
default: out << "Undocumented error!\n";
}
// log result
log(out.str());
// clean-up
delete pQGeoAddr;
/* delete sender in signal handler could be lethal
* Hence, delete it later...
*/
pQGeoCode->deleteLater();
});
});
// fill in a sample request with a known address initially
this->ui->qTxtCountry->setText(QString::fromUtf8("Germany"));
this->ui->qTxtZipCode->setText(QString::fromUtf8("88250"));
this->ui->qTxtCity->setText(QString::fromUtf8("Weingarten"));
this->ui->qTxtStreet->setText(QString::fromUtf8("Danziger Str. 3"));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::log(const QString &qString)
{
this->ui->qTxtLog->setPlainText(this->ui->qTxtLog->toPlainText() + qString);
this->ui->qTxtLog->moveCursor(QTextCursor::End);
}
void MainWindow::log(const char *text)
{
log(QString::fromUtf8(text));
}
void MainWindow::log(const std::string &text)
{
log(text.c_str());
}
QGeoServiceProvider* MainWindow::init(std::ostream &out)
{
// check for available services
QStringList qGeoSrvList
= QGeoServiceProvider::availableServiceProviders();
for (QString entry : qGeoSrvList) {
out << "Try service: " << entry.toStdString() << '\n';
// choose provider
QGeoServiceProvider *pQGeoProvider = new QGeoServiceProvider(entry);
if (!pQGeoProvider) {
out
<< "ERROR: GeoServiceProvider '" << entry.toStdString()
<< "' not available!\n";
continue;
}
QGeoCodingManager *pQGeoCoder = pQGeoProvider->geocodingManager();
if (!pQGeoCoder) {
out
<< "ERROR: GeoCodingManager '" << entry.toStdString()
<< "' not available!\n";
delete pQGeoProvider;
continue;
}
QLocale qLocaleC(QLocale::C, QLocale::AnyCountry);
pQGeoCoder->setLocale(qLocaleC);
out << "Using service " << entry.toStdString() << '\n';
return pQGeoProvider; // success
}
out << "ERROR: No suitable GeoServiceProvider found!\n";
return nullptr; // all attempts failed
}
The main.cpp:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
And here the Header File for the MainWindow:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
// standard C++ header:
#include <iostream>
#include <sstream>
// Qt header:
#include <QGeoAddress>
#include <QGeoCodingManager>
#include <QGeoCoordinate>
#include <QGeoLocation>
#include <QGeoServiceProvider>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
virtual ~MainWindow();
void log(const QString &qString);
void log(const char *text);
void log(const std::string &text);
QGeoServiceProvider* init(std::ostream &out);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
I transformed my older sample to a minimal application with GUI:
// standard C++ header:
#include <iostream>
#include <sstream>
// Qt header:
#include <QtWidgets>
#include <QGeoAddress>
#include <QGeoCodingManager>
#include <QGeoCoordinate>
#include <QGeoLocation>
#include <QGeoServiceProvider>
void log(QTextEdit &qTxtLog, const QString &qString)
{
qTxtLog.setPlainText(qTxtLog.toPlainText() + qString);
qTxtLog.moveCursor(QTextCursor::End);
}
void log(QTextEdit &qTxtLog, const char *text)
{
log(qTxtLog, QString::fromUtf8(text));
}
void log(QTextEdit &qTxtLog, const std::string &text)
{
log(qTxtLog, text.c_str());
}
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
// main application
QApplication app(argc, argv);
// setup GUI
QWidget qWin;
QVBoxLayout qBox;
QFormLayout qForm;
QLabel qLblCountry(QString::fromUtf8("Country:"));
QLineEdit qTxtCountry;
qForm.addRow(&qLblCountry, &qTxtCountry);
QLabel qLblZipCode(QString::fromUtf8("Postal Code:"));
QLineEdit qTxtZipCode;
qForm.addRow(&qLblZipCode, &qTxtZipCode);
QLabel qLblCity(QString::fromUtf8("City:"));
QLineEdit qTxtCity;
qForm.addRow(&qLblCity, &qTxtCity);
QLabel qLblStreet(QString::fromUtf8("Street:"));
QLineEdit qTxtStreet;
qForm.addRow(&qLblStreet, &qTxtStreet);
QLabel qLblProvider(QString::fromUtf8("Provider:"));
QComboBox qLstProviders;
qForm.addRow(&qLblProvider, &qLstProviders);
qBox.addLayout(&qForm);
QPushButton qBtnFind(QString::fromUtf8("Find Coordinates"));
qBox.addWidget(&qBtnFind);
QLabel qLblLog(QString::fromUtf8("Log:"));
qBox.addWidget(&qLblLog);
QTextEdit qTxtLog;
qTxtLog.setReadOnly(true);
qBox.addWidget(&qTxtLog);
qWin.setLayout(&qBox);
qWin.show();
// initialize Geo Service Providers
std::vector<QGeoServiceProvider*> pQGeoProviders;
{ std::ostringstream out;
QStringList qGeoSrvList
= QGeoServiceProvider::availableServiceProviders();
for (QString entry : qGeoSrvList) {
out << "Try service: " << entry.toStdString() << '\n';
// choose provider
QGeoServiceProvider *pQGeoProvider = new QGeoServiceProvider(entry);
if (!pQGeoProvider) {
out
<< "ERROR: GeoServiceProvider '" << entry.toStdString()
<< "' not available!\n";
continue;
}
QGeoCodingManager *pQGeoCoder = pQGeoProvider->geocodingManager();
if (!pQGeoCoder) {
out
<< "ERROR: GeoCodingManager '" << entry.toStdString()
<< "' not available!\n";
delete pQGeoProvider;
continue;
}
QLocale qLocaleC(QLocale::C, QLocale::AnyCountry);
pQGeoCoder->setLocale(qLocaleC);
qLstProviders.addItem(entry);
pQGeoProviders.push_back(pQGeoProvider);
out << "Service " << entry.toStdString() << " available.\n";
}
log(qTxtLog, out.str());
}
if (pQGeoProviders.empty()) qBtnFind.setEnabled(false);
// install signal handlers
QObject::connect(&qBtnFind, QPushButton::clicked,
[&]() {
// get current geo service provider
QGeoServiceProvider *pQGeoProvider
= pQGeoProviders[qLstProviders.currentIndex()];
// fill in request
QGeoAddress *pQGeoAddr = new QGeoAddress;
pQGeoAddr->setCountry(qTxtCountry.text());
pQGeoAddr->setPostalCode(qTxtZipCode.text());
pQGeoAddr->setCity(qTxtCity.text());
pQGeoAddr->setStreet(qTxtStreet.text());
QGeoCodeReply *pQGeoCode
= pQGeoProvider->geocodingManager()->geocode(*pQGeoAddr);
if (!pQGeoCode) {
delete pQGeoAddr;
log(qTxtLog, "GeoCoding totally failed!\n");
return;
}
{ std::ostringstream out;
out << "Sending request for:\n"
<< pQGeoAddr->country().toUtf8().data() << "; "
<< pQGeoAddr->postalCode().toUtf8().data() << "; "
<< pQGeoAddr->city().toUtf8().data() << "; "
<< pQGeoAddr->street().toUtf8().data() << "...\n";
log(qTxtLog, out.str());
}
// install signal handler to process result later
QObject::connect(pQGeoCode, &QGeoCodeReply::finished,
[&qTxtLog, pQGeoAddr, pQGeoCode]() {
// process reply
std::ostringstream out;
out << "Reply: " << pQGeoCode->errorString().toStdString() << '\n';
switch (pQGeoCode->error()) {
case QGeoCodeReply::NoError: {
// eval result
QList<QGeoLocation> qGeoLocs = pQGeoCode->locations();
out << qGeoLocs.size() << " location(s) returned.\n";
for (QGeoLocation &qGeoLoc : qGeoLocs) {
qGeoLoc.setAddress(*pQGeoAddr);
QGeoCoordinate qGeoCoord = qGeoLoc.coordinate();
out
<< "Lat.: " << qGeoCoord.latitude() << '\n'
<< "Long.: " << qGeoCoord.longitude() << '\n'
<< "Alt.: " << qGeoCoord.altitude() << '\n';
}
} break;
#define CASE(ERROR) \
case QGeoCodeReply::ERROR: out << #ERROR << '\n'; break
CASE(EngineNotSetError);
CASE(CommunicationError);
CASE(ParseError);
CASE(UnsupportedOptionError);
CASE(CombinationError);
CASE(UnknownError);
#undef CASE
default: out << "Undocumented error!\n";
}
// log result
log(qTxtLog, out.str());
// clean-up
delete pQGeoAddr;
/* delete sender in signal handler could be lethal
* Hence, delete it later...
*/
pQGeoCode->deleteLater();
});
});
// fill in a sample request with a known address initially
qTxtCountry.setText(QString::fromUtf8("Germany"));
qTxtZipCode.setText(QString::fromUtf8("88250"));
qTxtCity.setText(QString::fromUtf8("Weingarten"));
qTxtStreet.setText(QString::fromUtf8("Danziger Str. 3"));
// runtime loop
app.exec();
// done
return 0;
}
Compiled and tested in cygwin on Windows 10 (64 bit):
$ g++ --version
g++ (GCC) 6.4.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ qmake-qt5 testQGeoAddressGUI.pro
$ make
g++ -c -fno-keep-inline-dllexport -D_GNU_SOURCE -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_LOCATION_LIB -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_POSITIONING_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -I. -isystem /usr/include/qt5 -isystem /usr/include/qt5/QtWidgets -isystem /usr/include/qt5/QtLocation -isystem /usr/include/qt5/QtQuick -isystem /usr/include/qt5/QtGui -isystem /usr/include/qt5/QtPositioning -isystem /usr/include/qt5/QtQml -isystem /usr/include/qt5/QtNetwork -isystem /usr/include/qt5/QtCore -I. -I/usr/lib/qt5/mkspecs/cygwin-g++ -o testQGeoAddressGUI.o testQGeoAddressGUI.cc
g++ -o testQGeoAddressGUI.exe testQGeoAddressGUI.o -lQt5Widgets -lQt5Location -lQt5Quick -lQt5Gui -lQt5Positioning -lQt5Qml -lQt5Network -lQt5Core -lGL -lpthread
$ ./testQGeoAddressGUI
Qt Version: 5.9.2
Notes:
When I wrote this sample I was very carefully about scope and life-time of involved variables. (Actually, I changed some local variables to pointers and instances created with new to achieve this.) This is my hint for any reader.
In my 1st test, the application ended up in CommunicationError. I'm quite sure that our company's security policy is responsible for this. (I did the same with my older sample which I tested successfully at home – with the same result.)
A 2nd test (at home) went better. First, I tried to find the address with service provider osm which brought 0 results. Changing the service provider to esri returned one result.
I copied the output to maps.google.de:
This is actually the correct result – as I tested the (new) address of the company EKS InTec where I'm working.
The usage of lambdas in the above sample makes it a bit hard to read. Therefore, I re-visited the sample. Now, all relevant stuff has moved to a class MainWindow (hopefully, closer to the requirement of OP). The lambdas were replaced by simple methods.
// standard C++ header:
#include <iostream>
#include <sstream>
// Qt header:
#include <QtWidgets>
#include <QGeoAddress>
#include <QGeoCodingManager>
#include <QGeoCoordinate>
#include <QGeoLocation>
#include <QGeoServiceProvider>
// main window class
class MainWindow: public QWidget {
// variables:
private:
// list of service providers
std::vector<QGeoServiceProvider*> pQGeoProviders;
// Qt widgets (contents of main window)
QVBoxLayout qBox;
QFormLayout qForm;
QLabel qLblCountry;
QLineEdit qTxtCountry;
QLabel qLblZipCode;
QLineEdit qTxtZipCode;
QLabel qLblCity;
QLineEdit qTxtCity;
QLabel qLblStreet;
QLineEdit qTxtStreet;
QLabel qLblProvider;
QComboBox qLstProviders;
QPushButton qBtnFind;
QLabel qLblLog;
QTextEdit qTxtLog;
// methods:
public: // ctor/dtor
MainWindow(QWidget *pQParent = nullptr);
virtual ~MainWindow();
MainWindow(const MainWindow&) = delete;
MainWindow& operator=(const MainWindow&) = delete;
private: // internal stuff
void init(); // initializes geo service providers
void find(); // sends request
void report(); // processes reply
void log(const QString &qString)
{
qTxtLog.setPlainText(qTxtLog.toPlainText() + qString);
qTxtLog.moveCursor(QTextCursor::End);
}
void log(const char *text) { log(QString::fromUtf8(text)); }
void log(const std::string &text) { log(text.c_str()); }
};
MainWindow::MainWindow(QWidget *pQParent):
QWidget(pQParent),
qLblCountry(QString::fromUtf8("Country:")),
qLblZipCode(QString::fromUtf8("Postal Code:")),
qLblCity(QString::fromUtf8("City:")),
qLblStreet(QString::fromUtf8("Street:")),
qLblProvider(QString::fromUtf8("Provider:")),
qBtnFind(QString::fromUtf8("Find Coordinates")),
qLblLog(QString::fromUtf8("Log:"))
{
// setup child widgets
qForm.addRow(&qLblCountry, &qTxtCountry);
qForm.addRow(&qLblZipCode, &qTxtZipCode);
qForm.addRow(&qLblCity, &qTxtCity);
qForm.addRow(&qLblStreet, &qTxtStreet);
qForm.addRow(&qLblProvider, &qLstProviders);
qBox.addLayout(&qForm);
qBox.addWidget(&qBtnFind);
qBox.addWidget(&qLblLog);
qBox.addWidget(&qTxtLog);
setLayout(&qBox);
// init service provider list
init();
// install signal handlers
QObject::connect(&qBtnFind, &QPushButton::clicked,
this, &MainWindow::find);
// fill in a sample request with a known address initially
qTxtCountry.setText(QString::fromUtf8("Germany"));
qTxtZipCode.setText(QString::fromUtf8("88250"));
qTxtCity.setText(QString::fromUtf8("Weingarten"));
qTxtStreet.setText(QString::fromUtf8("Danziger Str. 3"));
}
MainWindow::~MainWindow()
{
// clean-up
for (QGeoServiceProvider *pQGeoProvider : pQGeoProviders) {
delete pQGeoProvider;
}
}
void MainWindow::init()
{
// initialize Geo Service Providers
{ std::ostringstream out;
QStringList qGeoSrvList
= QGeoServiceProvider::availableServiceProviders();
for (QString entry : qGeoSrvList) {
out << "Try service: " << entry.toStdString() << '\n';
// choose provider
QGeoServiceProvider *pQGeoProvider = new QGeoServiceProvider(entry);
if (!pQGeoProvider) {
out
<< "ERROR: GeoServiceProvider '" << entry.toStdString()
<< "' not available!\n";
continue;
}
QGeoCodingManager *pQGeoCoder = pQGeoProvider->geocodingManager();
if (!pQGeoCoder) {
out
<< "ERROR: GeoCodingManager '" << entry.toStdString()
<< "' not available!\n";
delete pQGeoProvider;
continue;
}
QLocale qLocaleC(QLocale::C, QLocale::AnyCountry);
pQGeoCoder->setLocale(qLocaleC);
qLstProviders.addItem(entry);
pQGeoProviders.push_back(pQGeoProvider);
out << "Service " << entry.toStdString() << " available.\n";
}
log(out.str());
}
if (pQGeoProviders.empty()) qBtnFind.setEnabled(false);
}
std::string format(const QGeoAddress &qGeoAddr)
{
std::ostringstream out;
out
<< qGeoAddr.country().toUtf8().data() << "; "
<< qGeoAddr.postalCode().toUtf8().data() << "; "
<< qGeoAddr.city().toUtf8().data() << "; "
<< qGeoAddr.street().toUtf8().data();
return out.str();
}
void MainWindow::find()
{
// get current geo service provider
QGeoServiceProvider *pQGeoProvider
= pQGeoProviders[qLstProviders.currentIndex()];
// fill in request
QGeoAddress qGeoAddr;
qGeoAddr.setCountry(qTxtCountry.text());
qGeoAddr.setPostalCode(qTxtZipCode.text());
qGeoAddr.setCity(qTxtCity.text());
qGeoAddr.setStreet(qTxtStreet.text());
QGeoCodeReply *pQGeoCode
= pQGeoProvider->geocodingManager()->geocode(qGeoAddr);
if (!pQGeoCode) {
log("GeoCoding totally failed!\n");
return;
}
{ std::ostringstream out;
out << "Sending request for:\n"
<< format(qGeoAddr) << "...\n";
log(out.str());
}
// install signal handler to process result later
QObject::connect(pQGeoCode, &QGeoCodeReply::finished,
this, &MainWindow::report);
/* This signal handler will delete it's own sender.
* Hence, the connection need not to be remembered
* although it has only a limited life-time.
*/
}
void MainWindow::report()
{
QGeoCodeReply *pQGeoCode
= dynamic_cast<QGeoCodeReply*>(sender());
// process reply
std::ostringstream out;
out << "Reply: " << pQGeoCode->errorString().toStdString() << '\n';
switch (pQGeoCode->error()) {
case QGeoCodeReply::NoError: {
// eval result
QList<QGeoLocation> qGeoLocs = pQGeoCode->locations();
out << qGeoLocs.size() << " location(s) returned.\n";
for (QGeoLocation &qGeoLoc : qGeoLocs) {
QGeoAddress qGeoAddr = qGeoLoc.address();
QGeoCoordinate qGeoCoord = qGeoLoc.coordinate();
out
<< "Coordinates for "
<< qGeoAddr.text().toUtf8().data() << ":\n"
<< "Lat.: " << qGeoCoord.latitude() << '\n'
<< "Long.: " << qGeoCoord.longitude() << '\n'
<< "Alt.: " << qGeoCoord.altitude() << '\n';
}
} break;
#define CASE(ERROR) \
case QGeoCodeReply::ERROR: out << #ERROR << '\n'; break
CASE(EngineNotSetError);
CASE(CommunicationError);
CASE(ParseError);
CASE(UnsupportedOptionError);
CASE(CombinationError);
CASE(UnknownError);
#undef CASE
default: out << "Undocumented error!\n";
}
// log result
log(out.str());
// clean-up
/* delete sender in signal handler could be lethal
* Hence, delete it later...
*/
pQGeoCode->deleteLater();
}
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
// main application
QApplication app(argc, argv);
// setup GUI
MainWindow win;
win.show();
// runtime loop
app.exec();
// done
return 0;
}
Note:
The look and behavior is the same like for the above example. I changed the output of reply a bit.
While preparing this sample, I realized that it is actually not necessary to set the address of the returned QGeoLocation as it is already there. IMHO, it is interesting that the returned address looks a bit different than the requested. It seems that it is returned in a (I would say) normalized form.

Program not working right on other windows machines

I'm having a problem with my application, in which I'm trying to get all network configurations of the system that it runs on. The final goal is to find the MAC address with highest priority.
The code runs ok and works when I run it with QtCreator and also runs ok when I create a folder containing the dll files and the exe file.
But the problem is that when I run this program on other windows machines (7 and 10) it runs but does not return or show anything. I tried running it as an Administrator, that didn't work neither and this code should be able to work on all windows platforms.
Any suggestions?
I'm currently on Windows 10 and using Qt 5.8 MSVC 2015
The exe file runs with these dlls on Windows 10:
Qt5Core.dll
Qt5Network.dll
msvcp140.dll
msvcr120.dll
vcruntime140.dll
These dlls should be also there for windows 7:
api-ms-win-core-file-l1-2-0.dll
api-ms-win-core-file-l2-1-0.dll
api-ms-win-core-localization-l1-2-0.dll
api-ms-win-core-processthreads-l1-1-1.dll
api-ms-win-core-string-l1-1-0.dll
api-ms-win-core-synch-l1-2-0.dll
api-ms-win-core-timezone-l1-1-0.dll
api-ms-win-crt-convert-l1-1-0.dll
api-ms-win-crt-environment-l1-1-0.dll
api-ms-win-crt-filesystem-l1-1-0.dll
api-ms-win-crt-heap-l1-1-0.dll
api-ms-win-crt-locale-l1-1-0.dll
api-ms-win-crt-math-l1-1-0.dll
api-ms-win-crt-multibyte-l1-1-0.dll
api-ms-win-crt-runtime-l1-1-0.dll
api-ms-win-crt-stdio-l1-1-0.dll
api-ms-win-crt-string-l1-1-0.dll
api-ms-win-crt-time-l1-1-0.dll
api-ms-win-crt-utility-l1-1-0.dll
Link below is the exe and dll files together:
https://ufile.io/e9htu
here's my code if needed:
main.cpp
#include <QCoreApplication>
#include "macfinder.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MACFinder macFinder;
macFinder.findMAC();
return a.exec();
}
macfinder.h
#ifndef MACFINDER_H
#define MACFINDER_H
#include <QObject>
#include <QNetworkConfiguration>
#include <QNetworkConfigurationManager>
#include <QNetworkInterface>
#include <QNetworkSession>
#include <QDebug>
class MACFinder : public QObject
{
Q_OBJECT
public:
explicit MACFinder(QObject *parent = 0);
void findMAC();
private:
QNetworkConfigurationManager ncm;
QString filterMAC(QList<QNetworkConfiguration> configs);
signals:
void foundMAC(QString MAC);
private slots:
void configurationsUpdateCompleted();
};
#endif // MACFINDER_H
macfinder.cpp
#include "macfinder.h"
MACFinder::MACFinder(QObject *parent) : QObject(parent)
{
}
QString MACFinder::filterMAC(QList<QNetworkConfiguration> configs)
{
qDebug() << "MAC and Index: ";
QString MAC;
int index;
QNetworkConfiguration nc;
foreach(nc,configs)
{
QNetworkSession networkSession(nc);
QNetworkInterface netInterface = networkSession.interface();
QString debugStr = QString::number(netInterface.index())
+ " | " + netInterface.humanReadableName() + " | "
+ nc.name() + " | " + netInterface.hardwareAddress();
if(netInterface.hardwareAddress().isEmpty())
{
qDebug() << "--> No MAC: " << debugStr;
continue;
}
if(netInterface.name().isEmpty())
{
qDebug() << "--> NO NAME: " << debugStr;
continue;
}
if(netInterface.index() == 0)
{
qDebug() << "--> NO INDEX: " << debugStr;
continue;
}
if(netInterface.flags() & QNetworkInterface::IsLoopBack)
{
qDebug() << "--> loopBack: " << debugStr;
continue;
}
if(netInterface.flags() & (QNetworkInterface::IsRunning | QNetworkInterface::IsUp))
{
qDebug() << "*** Accepted: " << debugStr;
if(MAC.isEmpty())
{
qDebug() << "setting MAC:" << debugStr;
MAC = netInterface.hardwareAddress();
index = netInterface.index();
}
else
{
if(netInterface.index() < index)
{
qDebug() << "setting MAC:" << debugStr;
MAC = netInterface.hardwareAddress();
index = netInterface.index();
}
else
qDebug() << "index is not lower: " << debugStr;
}
}
}
return MAC;
}
void MACFinder::findMAC()
{
qDebug() << "MACFinder::findMAC | updating all configurations";
connect(&ncm,SIGNAL(updateCompleted()),this,SLOT(configurationsUpdateCompleted()));
ncm.updateConfigurations();
}
void MACFinder::configurationsUpdateCompleted()
{
qDebug() << "MACFinder::configurationsUpdateCompleted";
disconnect(&ncm,SIGNAL(updateCompleted()),this,SLOT(configurationsUpdateCompleted()));
QNetworkConfiguration nc;
QList<QNetworkConfiguration> configs = ncm.allConfigurations(QNetworkConfiguration::Active);
qDebug() << "\nAllConfigs: ";
foreach (nc,configs)
{
qDebug() << nc.identifier() << nc.name() << nc.state();
}
QString MAC = filterMAC(configs);
qDebug() << "\nMAC:" << MAC;
if(MAC.isEmpty())
{
qDebug("no MAC address found");
}
emit foundMAC(MAC);
}
I downloaded your app and analyze it on my computer.
problem is you missing some dlls, your app running without error but not working properly. (qgenericbearer.dll , qnativewifibearer.dll with folder bearer are missing ).
you can use windeploy command to deploy your project.
go to Qt, compiler directory on your OS for example:
C:\Qt\Qt5.7.0\5.7\msvc2013\bin
press Shift+right click mouse then click open command window here
type windeployqt.exe c:\Your app directory for example:
windeployqt.exe C:\Users\Mofrad\Downloads\macfindertest\macFinderTest\macAddressTest.exe
now some dlls will copy to your app directory.
Now try your app again and you'll see it's working.

QHttpMultiPart send post request results in "1"

I am currently using QHttpMultiPart in a Qt Project, but it seems to have some problems on my end ?
I have followed the example and came up with the following code:
#include "uploader.h"
#include <QFileInfo>
#include <QMimeDatabase>
#include <QHttpMultiPart>
#include <QNetworkReply>
#include <QDebug>
/**
* #brief Uploader::Uploader
* #param parent
*/
Uploader::Uploader(QObject *parent) :
QObject(parent)
{
uploadInProgress = false;
}
/**
* #brief Uploader::upload
* #param absoluteFilePath
*/
void Uploader::upload(QString absoluteFilePath)
{
qDebug() << "Upload Starting";
QFileInfo fileInfo(absoluteFilePath);
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
//action part
QHttpPart textPart;
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"cmd\""));
textPart.setBody(QString("wFile").toLatin1());
//File Path
QHttpPart filePathPart;
filePathPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file_path\""));
filePathPart.setBody(absoluteFilePath.toLatin1());
//filepart
QHttpPart filePart;
QMimeDatabase db;
QMimeType mime = db.mimeTypeForFile(absoluteFilePath);
filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(mime.name()));
filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"preview_file\"; filename=\""+ fileInfo.baseName() + "\""));
QFile *file = new QFile(absoluteFilePath);
if ( !file->exists() )
{
qDebug() << "File Does not exist";
}
file->open(QIODevice::ReadOnly);
filePart.setBodyDevice(file);
file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart
multiPart->append(textPart);
multiPart->append(filePathPart);
multiPart->append(filePart);
QUrl url("http://project.dbz.dev/index.php?controller=wapi&action=handle");
QNetworkRequest request(url);
pManager = new QNetworkAccessManager();
pReply = pManager->post(request, multiPart);
multiPart->setParent(pReply);
connect(pReply, SIGNAL(uploadProgress(qint64,qint64)),this,SLOT(uploadProgress(qint64,qint64)));
connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onError(QNetworkReply::NetworkError)));
connect(pReply, SIGNAL(finished()),this, SLOT(uploadFinished()));
// here connect signals etc.
uploadInProgress = true;
}
/**
* #brief Uploader::uploadFinished
*/
void Uploader::uploadFinished()
{
QString data = (QString) pReply->readAll();
qDebug() << data;
qDebug() << "Upload finished";
uploadInProgress = false;
if ( pReply->error() > 0 )
{
qDebug() << "Error occured: " << pReply->error() << " : " << pReply->errorString();
}
else
{
qDebug() << "Upload success";
}
delete pReply;
}
void Uploader::uploadProgress(qint64 a, qint64 b)
{
qDebug() << " SOME PROGRESS!";
qDebug() << a << "/" << b;
}
void Uploader::onError(QNetworkReply::NetworkError err)
{
qDebug() << " SOME ERROR!";
qDebug() << err;
}
Sadly, none of the SLOTS are triggered from the SIGNALS. Neither can I see a package send with wireshark on my local ethernet adapter.
However, my Apache does get a request:
192.168.178.21 - - [21/Sep/2013:05:10:41 +0200] "POST /index.php?controller=wapi&action=handle HTTP/1.1" 200 166 "-" "Mozilla/5.0"
And in my PHP Application I have the following outcome:
Application_Controller_WapiController::handleAction: Command: wFile
Application_Controller_WapiController::wFile: POST Request: 1
This, basically means, it recognises the Parameter "cmd" and the value "wFile", opens the according PHP action which then does a print_r($_POST) which shows me nothing more than a simple 1.
I have no idea what to do. I have looked everywhere on the internet and cannot seem to figure it out. I followed all examples and descriptions on the official documentary and found a couple of threads here on SO. There seemed to be a bug with the QHttpMultiPart class, although it was fixed with the major 5.0.0 update.
tl;dr:
connect(pReply, SIGNAL(uploadProgress(qint64,qint64)),this,SLOT(uploadProgress(qint64,qint64)));
connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onError(QNetworkReply::NetworkError)));
connect(pReply, SIGNAL(finished()),this, SLOT(uploadFinished()));
These signals are not being triggered, PHP print_r shows me a 1 and I cannot track the POST request on my machine.
It would be nice if somebody could tell me why the SIGNALS are not emitted and more importantly how I can see a final version of my POST request in my C++ application before it is sent.
Thank you very much! I appreciate any help!
I have solved the problem by adding:
pELoop = new QEventLoop();
pELoop->exec();
Which results into this:
#include "uploader.h"
#include <QFileInfo>
#include <QMimeDatabase>
#include <QHttpMultiPart>
#include <QNetworkReply>
#include <QDebug>
/**
* #brief Uploader::Uploader
* #param parent
*/
Uploader::Uploader(QObject *parent) :
QObject(parent)
{
uploadInProgress = false;
}
/**
* #brief Uploader::upload
* #param absoluteFilePath
*/
void Uploader::upload(QString absoluteFilePath)
{
qDebug() << "Upload Starting";
QFileInfo fileInfo(absoluteFilePath);
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
//action part
QHttpPart textPart;
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"cmd\""));
textPart.setBody(QString("wFile").toLatin1());
//File Path
QHttpPart filePathPart;
filePathPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file_path\""));
filePathPart.setBody(absoluteFilePath.toLatin1());
//filepart
QHttpPart filePart;
QMimeDatabase db;
QMimeType mime = db.mimeTypeForFile(absoluteFilePath);
filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(mime.name()));
filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"preview_file\"; filename=\""+ fileInfo.baseName() + "\""));
QFile *file = new QFile(absoluteFilePath);
if ( !file->exists() )
{
qDebug() << "File Does not exist";
}
file->open(QIODevice::ReadOnly);
filePart.setBodyDevice(file);
file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart
multiPart->append(textPart);
multiPart->append(filePathPart);
multiPart->append(filePart);
QUrl url("http://encryptor.dbz.dev/index.php?controller=wapi&action=handle");
QNetworkRequest request(url);
pManager = new QNetworkAccessManager();
pReply = pManager->post(request, multiPart);
multiPart->setParent(pReply);
pELoop = new QEventLoop();
connect(pReply, SIGNAL(uploadProgress(qint64,qint64)),this,SLOT(uploadProgress(qint64,qint64)));
connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onError(QNetworkReply::NetworkError)));
connect(pReply, SIGNAL(finished()),this, SLOT(uploadFinished()));
pELoop->exec();
// here connect signals etc.
uploadInProgress = true;
}
/**
* #brief Uploader::uploadFinished
*/
void Uploader::uploadFinished()
{
QString data = (QString) pReply->readAll();
qDebug() << data;
qDebug() << "Upload finished";
uploadInProgress = false;
if ( pReply->error() > 0 )
{
qDebug() << "Error occured: " << pReply->error() << " : " << pReply->errorString();
}
else
{
qDebug() << "Upload success";
}
pReply->deleteLater();
pELoop->exit();
}
void Uploader::uploadProgress(qint64 a, qint64 b)
{
qDebug() << " SOME PROGRESS!";
qDebug() << a << "/" << b;
}
void Uploader::onError(QNetworkReply::NetworkError err)
{
qDebug() << " SOME ERROR!";
qDebug() << err;
}
The request is executed as expected, and the signals are working as well.
I get the output of:
Upload Starting
SOME PROGRESS!
16384 / 483753
SOME PROGRESS!
483753 / 483753
SOME PROGRESS!
0 / 0
"Array
(
[controller] => wapi
[action] => handle
[cmd] => wFile
[file_path] => D:/Downloads/putty.exe
)
{"cmd":"","status":"","message":"","params":[]}"
Upload finished
Upload success
I leave this hear in case somebody is looking for a working example.