All!
I have some application with 3 tabs, one tab initialized QWidget from other tab. I start QAudioInput in constructor(read to memory, I don't need file) - it starts works. But when I change tab to my widget, data stops and audioInput has status isActive still.
I have changed and minimized sources. It is a cross-compilation for ARM Linux platform. Now it is works usiallu, but few changes active tab crash stream.
int main(int argc, char *argv[])
{
QApplication myapp(argc, argv);
Widget wid;
wid.show();
return myapp.exec();
}
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
// Default widget in new tab
wMetod = new Vnimi(this);//this
ui->tabWidget->insertTab(1, wMetod, "Empty"); // Set Tab's name
ui->pButton_Vnimi->setChecked(true);
/*QButtonGroup **/
grMetod = new QButtonGroup(this);
grMetod->addButton(ui->pButton_Vnimi );
grMetod->addButton(ui->pButton_ExpVibro);
grMetod->setExclusive(true);
connect(grMetod, static_cast<void(QButtonGroup::*)(QAbstractButton *)>(&QButtonGroup::buttonPressed),
[=](QAbstractButton *button){ metChanged(button); });
ui->tabWidget->setCurrentIndex(0);
}
Widget::~Widget()
{
delete ui;
}
void Widget::metChanged(QAbstractButton *button)
{
/* switch for strings */
if( button->objectName() =="pButton_Empty" ) {
ui->tabWidget->removeTab(1);
wMetod->disconnect(); delete wMetod;
wMetod = new Vnimi(this);//this
ui->tabWidget->insertTab(1, wMetod, "Empty"); // Set Tab's name
}else if( button->objectName() =="pButton_Input" ) {
ui->tabWidget->removeTab(1);
wMetod->disconnect(); delete wMetod;
wMetod = new VibrExpr(this);//this
ui->tabWidget->insertTab(1, wMetod, "Input"); // Set Tab's name
}else {
qDebug() << "Unknow method!";
}
qDebug() << button->objectName() << " pressed";
}
VibrExpr::VibrExpr(QWidget *parent) :
QWidget(parent),
ui(new Ui::VibrExpr)
{
ui->setupUi(this);
ui->lb_level->setText( QString().number(minLevel) );
QAudioFormat frmt;
frmt.setCodec( "audio/pcm"), frmt.setChannelCount( 2);
frmt.setSampleRate( 44100), frmt.setSampleType( QAudioFormat::SignedInt);
frmt.setSampleSize( 16);
rawSrc = new QAudioInput(QAudioDeviceInfo::defaultInputDevice(), frmt, this);
rawSrc->setNotifyInterval(250);
connect(rawSrc, SIGNAL(notify()), this, SLOT(slot()));
connect(rawSrc, SIGNAL(stateChanged(QAudio::State)), this, SLOT(iStateChanged(QAudio::State)));
buff = new QBuffer(this);
buff->open(QBuffer::ReadWrite);
connect(buff, SIGNAL(readyRead()), this, SLOT(newData()) );
rawSrc->start(buff);
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(timSlot()) );
timer->start(1000);
qDebug() << "Created";
}
void VibrExpr::timSlot()
{
int sbVal = ui->lb_level->text().toInt();
if(sbVal < -6 ) {
sbVal += 1;
}
if(buff != nullptr) \
if(buff->isOpen() && sbVal >= -10) {
qDebug() << "Sz " << buff->size();
rawSrc->stop();
buff->close();
qDebug() << " Input closed";
}
ui->lb_level->setText( QString().number(sbVal));
if(rawSrc != nullptr) qDebug() << "iStat " << rawSrc->state();
}
void VibrExpr::newData(void)
{
int k = buff->size();
QByteArray qba = buff->read(k);
buff->seek(0);
buff->buffer().remove(0, k);
qDebug() << "n=" << k;
}
void VibrExpr::slot(void)
{
qDebug() << "USec:" << rawSrc->processedUSecs() ;
}
void VibrExpr::iStateChanged(QAudio::State state)
{
qDebug() << "Now state: " << state;
}
Related
I apologize in advance am very new to QT (and fairly new to C++)
I am trying setup a program that will execute a function anytime a specific file is changed. Despite hours on google and reading the docs provided on QT I cant find a way to get myfunction() to execute when SSOpen_Log is edited
currently my code looks something like this (SOpen_Log is a QString declared in .h):
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QFileSystemWatcher watcher;
watcher.addPath(SOpen_Log);
MainWindow::connect(&watcher, SIGNAL(fileChanged(QString)), this, SLOT(myfunction()));
}
MainWindow::myfunction()
{
//mycode executes here
}
You allocated your instance on the stack and it thus get destructed when the constructor ends. I would suggest that you make a class member for the instance so that it remains valid throughout the class.
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_watcher.addPath(SOpen_Log);
MainWindow::connect(&m_watcher, SIGNAL(fileChanged(QString)), this, SLOT(myfunction()));
}
There is no need to complicate this by putting it on the heap, effectively using a pointer, although that is also an option to consider.
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QFileSystemWatcher *watcher = new QFileSystemWatcher(this);
watcher->addPath(SOpen_Log);
MainWindow::connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(myfunction()));
}
While we are at it, I would also like to mention to use the new signal-slot syntax style rather than the old. The old one is checked at runtime and the new one is checked at compilation time. So, you catch any issues with it during compilation rather than at runtime.
A complete and simple example:
Dirwatcher.h
class DirWatcher : public QObject
{
Q_OBJECT
public:
static const int sMaxCount = 5;
explicit DirWatcher(const QString& root, QObject* parent = nullptr);
virtual ~DirWatcher();
private slots:
void hDirChanged(const QString&);
void hFileChanged(const QString&);
private:
quint64 m_rbSize;
QByteArray m_ringBuffer[10];
QFileSystemWatcher m_watcher;
QDir m_root;
QSet<QString> m_directories;
QMap<QString, QSet<QString>> m_abspaths;
QString m_lastKey;
};
and Dirwatcher.cpp
namespace
{
void split(const char* str, const char* delim, std::vector<std::string>& out)
{
const char* begin = str;
const char* it = strstr(str, delim);
if (it != NULL)
{
std::string data{begin, it};
out.push_back(data);
it++;
split(it, delim, out);
} else {
std::string data{str};
out.push_back(data);
}
}
}
DirWatcher::DirWatcher(const QString &root, QObject* parent):
QObject(parent), m_root(root), m_rbSize{10}
{
m_watcher.addPath(root);
QObject::connect(&m_watcher, SIGNAL(directoryChanged(const QString&)),
this, SLOT(hDirChanged(const QString&)));
QObject::connect(&m_watcher, SIGNAL(fileChanged(const QString&)),
this, SLOT(hFileChanged(const QString&)));
}
DirWatcher::~DirWatcher()
{
}
void DirWatcher::hDirChanged(const QString &path)
{
QDirIterator it(m_root.path());
while (it.hasNext()) {
QString d = it.next();
if (d.at(0) == '.' || d.at(d.size()-1) == '.') {
} else {
if (!m_directories.contains(d)){
m_directories << d;
m_lastKey = d;
}
}
}
#if 0 //delete directories when count reaches...
if (m_directories.count() > DirWatcher::sMaxCount) {
QSetIterator<QString> setit(m_directories);
while (setit.hasNext()) {
QString toDel = setit.next();
if (toDel != m_lastKey) {
QDir rem (toDel);
rem.removeRecursively();
}
}
m_directories.clear();
m_directories << m_lastKey;
}
#endif
std::cout << "##############################################\r\n";
QSetIterator<QString> setit(m_directories);
while (setit.hasNext()) {
QString d = setit.next();
if (d.contains(".tlf")) {
m_watcher.addPath(d);
}
std::cout << d.toStdString() << std::endl;
}
}
void DirWatcher::hFileChanged(const QString& file)
{
static size_t cnt = 0;
QFile f{file};
if (f.open(QFile::ReadOnly)) {
quint64 s = f.size();
f.seek(f.size()-f.size()/2);
while (!f.atEnd()) {
QByteArray data = f.readLine();
m_ringBuffer[cnt++ % m_rbSize]=data;
}
}
std::cout << "----------------- B E G I N ----------------------\r\n";
for(auto i : m_ringBuffer) {
std::cout << "~~~~~~\r\n";
std::cout << i.toStdString().c_str() << "\r\n";
}
}
It's a real background monitoring job process for deleting files on a given time or count, but you will understand what is missing in your code if you debug it.
Hi im using this code for generate MD5 of files in QT
QString Md5_gen(QString const &s)
{
QString pakchunk_Md5;
QCryptographicHash crypto(QCryptographicHash::Md5);
QFile pakchunk("D:/Games/TDPA - Man of Medan" + s);
if (pakchunk.open(QIODevice::ReadOnly))
{
while(!pakchunk.atEnd()){
crypto.addData(pakchunk.read(8192));
}
} else
{
qDebug() << "Can't open file.";
pakchunk_Md5 = "nofile";
return pakchunk_Md5;
}
pakchunk_Md5 = crypto.result().toHex();
return pakchunk_Md5;
}
I need to Generate MD5 of 8 Big file with this code (1.5GB>) Problem is When i press button to start Generate MD5, GUI Freeze until all MD5 generated
Im Test QFuture, QFutureWatcher, QtConcurrent in this way, But no luck GUi still freeze every time
main.cpp
#include "user_def.h"
#include "mainwindow2.h"
#include...
QString Md5_gen(QString const &s)
{
QString pakchunk_Md5;
QCryptographicHash crypto(QCryptographicHash::Md5);
QFile pakchunk("D:/Games/TDPA - Man of Medan" + s);
if (pakchunk.open(QIODevice::ReadOnly))
{
while(!pakchunk.atEnd()){
crypto.addData(pakchunk.read(8192));
}
} else
{
qDebug() << "Can't open file.";
pakchunk_Md5 = "nofile";
return pakchunk_Md5;
}
pakchunk_Md5 = crypto.result().toHex();
return pakchunk_Md5;
}
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
a.setStyle(new DarkStyle);
FramelessWindow framelessWindow;
framelessWindow.setWindowIcon(a.style()->standardIcon(QStyle::SP_DesktopIcon));
MainWindow *mainWindow = new MainWindow;
framelessWindow.setContent(mainWindow);
framelessWindow.show();
return a.exec();
}
user_def.h
#ifndef USER_DEF_H
#define USER_DEF_H
#include <QString>
QString Md5_gen(QString const &s);
#endif // USER_DEF_H
mainwindow2.h
#ifndef MAINWINDOW2_H
#define MAINWINDOW2_H
#include <QMainWindow>
#include <QtConcurrentRun>
#include <QFuture>
#include <QFutureWatcher>
#include <QThread>
#include <QThreadPool>
#include "user_def.h"
namespace Ui {
class MainWindow2;
}
class MainWindow2 : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow2(QWidget *parent = nullptr);
~MainWindow2();
public slots:
void run_thread();
void displayFinishedBox();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow2 *ui;
QFutureWatcher<QString> *watcher;
QFuture<QString> *future;
};
#endif // MAINWINDOW2_H
mainwindow2.cpp
#include...
MainWindow2::MainWindow2(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow2)
{
ui->setupUi(this);
connect(ui->pushButton, &QPushButton::clicked,
this, &MainWindow2::run_thread);
// display a message box when the calculation has finished
future = new QFuture<QString>;
watcher = new QFutureWatcher<QString>;
connect(watcher, SIGNAL(finished()),
this, SLOT(displayFinishedBox()));
}
MainWindow2::~MainWindow2()
{
delete ui;
}
void MainWindow2::run_thread()
{
int file_ok = 0;
//file pak33
QString loc33 = "/SM/test1.pak";
QFuture<QString> future33 = QtConcurrent::run(QThreadPool::globalInstance(), Md5_gen, loc33);
watcher->setFuture(future33);
QString pakchunk33 = future33.result();
qDebug() << pakchunk33;
if (pakchunk33 == "f7002d4419cd235a87746715ba6fb2ea")
{
qDebug() << "OK";
file_ok++;
ui->label_8->setText("OK");
ui->label_8->setStyleSheet("QLabel { color : green; }");
} else if (pakchunk33 == "nofile")
{
qDebug() << "no file found";
ui->label_8->setText("not found");
ui->label_8->setStyleSheet("QLabel { color : red; }");
} else
{
qDebug() << "file is diffrent";
ui->label_8->setText("wrong");
ui->label_8->setStyleSheet("QLabel { color : red; }");
}
ui->progressBar->setValue(12);
//file pak34
QString loc34 = "/SM/test2.pak";
QFuture<QString> future34 = QtConcurrent::run(QThreadPool::globalInstance(), Md5_gen, loc34);
watcher->setFuture(future34);
QString pakchunk34 = future34.result();
qDebug() << pakchunk34;
if (pakchunk34 == "64c77598586b6c3cb60beed0b0750620")
{
qDebug() << "OK";
file_ok++;
ui->label->setText("OK");
ui->label->setStyleSheet("QLabel { color : green; }");
} else if (pakchunk34 == "nofile")
{
qDebug() << "no file found";
ui->label->setText("not found");
ui->label->setStyleSheet("QLabel { color : red; }");
} else
{
qDebug() << "file is diffrent";
ui->label->setText("wrong");
ui->label->setStyleSheet("QLabel { color : red; }");
}
ui->progressBar->setValue(25);
//file pak35
QString loc35 = "/SM/test3.pak";
QFuture<QString> future35 = QtConcurrent::run(QThreadPool::globalInstance(), Md5_gen, loc35);
watcher->setFuture(future35);
QString pakchunk35 = future35.result();
qDebug() << pakchunk35;
if (pakchunk35 == "ee53f7a7656a32b5278c460baec46f16")
{
qDebug() << "OK";
file_ok++;
ui->label_7->setText("OK");
ui->label_7->setStyleSheet("QLabel { color : green; }");
} else if (pakchunk35 == "nofile")
{
qDebug() << "no file found";
ui->label_7->setText("not found");
ui->label_7->setStyleSheet("QLabel { color : red; }");
} else
{
qDebug() << "file is diffrent";
ui->label_7->setText("wrong");
ui->label_7->setStyleSheet("QLabel { color : red; }");
}
ui->progressBar->setValue(38);
/*Some other code*/
can anybody say what is my problem and how can i fix it?
edit 1
I edit my code in this way
it working good without freeze gui
in term of coding this code is standard?
mainwindow2.cpp
MainWindow2::MainWindow2(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow2)
{
ui->setupUi(this);
connect(ui->pushButton_3, &QPushButton::clicked, this, &MainWindow2::MD5_thread_1);
future = new QFuture<QString>;
watcher1 = new QFutureWatcher<QString>;
watcher2 = new QFutureWatcher<QString>;
watcher3 = new QFutureWatcher<QString>;
connect(watcher1, &QFutureWatcher<QString>::finished, this, &MainWindow2::MD5_thread_2);
connect(watcher2, &QFutureWatcher<QString>::finished, this, &MainWindow2::MD5_thread_3);
connect(watcher3, &QFutureWatcher<QString>::finished, this, &MainWindow2::MD5_thread_4);
//some other code
}
void MainWindow2::MD5_thread_1()
{
ui->pushButton->setEnabled(false);
ui->pushButton->setText("procces started");
ui->pushButton->setStyleSheet("QPushButton { color : white; background-color: rgb(73, 80, 93); }");
ui->label->setText("checking");
ui->label_2->setText("checking");
ui->label_3->setText("checking");
ui->label_4->setText("checking");
ui->label_5->setText("checking");
ui->label_6->setText("checking");
ui->label_7->setText("checking");
ui->label_8->setText("checking");
ui->label_14->setText("waiting for end of check");
ui->progressBar->setRange(0, 100);
ui->progressBar_2->setRange(0, 100);
ui->progressBar->setValue(0);
ui->progressBar_2->setValue(0);
//file pak33
QString loc33 = "/SMG0/editor.pak";
*future= QtConcurrent::run(QThreadPool::globalInstance(), Md5_gen, loc33);
watcher1->setFuture(*future);
}
void MainWindow2::MD5_thread_2()
{
QString pakchunk33 = future->result();
qDebug() << pakchunk33;
if (pakchunk33 == "f7002d4419cd235a87746715ba6fb2ea")
{
qDebug() << "OK";
file_ok++;
ui->label_8->setText("OK");
ui->label_8->setStyleSheet("QLabel { color : green; }");
} else if (pakchunk33 == "nofile")
{
qDebug() << "no file found";
ui->label_8->setText("not found");
ui->label_8->setStyleSheet("QLabel { color : red; }");
} else
{
qDebug() << "file is diffrent";
ui->label_8->setText("wrong");
ui->label_8->setStyleSheet("QLabel { color : red; }");
}
ui->progressBar->setValue(12);
watcher1->deleteLater();
//file pak34
QString loc34 = "/SMG0/2Editor.pak";
*future = QtConcurrent::run(QThreadPool::globalInstance(), Md5_gen, loc34);
watcher2->setFuture(*future);
}
void MainWindow2::MD5_thread_3()
{
QString pakchunk34 = future->result();
qDebug() << pakchunk34;
if (pakchunk34 == "64c77598586b6c3cb60beed0b0750620")
{
qDebug() << "OK";
file_ok++;
ui->label->setText("OK");
ui->label->setStyleSheet("QLabel { color : green; }");
} else if (pakchunk34 == "nofile")
{
qDebug() << "no file found";
ui->label->setText("not found");
ui->label->setStyleSheet("QLabel { color : red; }");
} else
{
qDebug() << "file is diffrent";
ui->label->setText("wrong");
ui->label->setStyleSheet("QLabel { color : red; }");
}
ui->progressBar->setValue(25);
watcher2->deleteLater();
//file pak35
QString loc35 = "/SMG0/3Editor.pak";
*future = QtConcurrent::run(QThreadPool::globalInstance(), Md5_gen, loc35);
watcher3->setFuture(*future);
}
void MainWindow2::core_install
{
QString pakchunk35 = future->result();
qDebug() << pakchunk40;
if (pakchunk40 == "49e0440340044f424caeb82bade1301f")
{
qDebug() << "OK";
file_ok++;
ui->label_2->setText("OK");
ui->label_2->setStyleSheet("QLabel { color : green; }");
} else if (pakchunk40 == "nofile")
{
qDebug() << "no file found";
ui->label_2->setText("not found");
ui->label_2->setStyleSheet("QLabel { color : red; }");
} else
{
qDebug() << "file is diffrent";
ui->label_2->setText("wrong");
ui->label_2->setStyleSheet("QLabel { color : red; }");
}
ui->progressBar->setValue(100);
watcher3->deleteLater();
//check if game is okey or not
if (file_ok == 8)
{
ui->label_14->setText("O");
ui->label_14->setStyleSheet("QLabel { color : green; }");
} else
{
ui->label_14->setText("X");
ui->label_14->setStyleSheet("QLabel { color : red; }");
}
}
mainwindow2.h
#ifndef MAINWINDOW2_H
#define MAINWINDOW2_H
#include <QMainWindow>
#include <QtConcurrentRun>
#include <QFuture>
#include <QFutureWatcher>
#include <QThread>
#include <QThreadPool>
#include "user_def.h"
namespace Ui {
class MainWindow2;
}
class MainWindow2 : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow2(QWidget *parent = nullptr);
~MainWindow2();
public slots:
void MD5_thread_1();
void MD5_thread_2();
void MD5_thread_3();
void core_install();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void on_radioButton_2_clicked();
void on_radioButton_4_clicked();
void on_radioButton_3_clicked();
void on_radioButton_clicked();
private:
Ui::MainWindow2 *ui;
QFutureWatcher<QString> *watcher1;
QFutureWatcher<QString> *watcher2;
QFutureWatcher<QString> *watcher3;
QFuture<QString> *future;
int file_ok = 0;
};
#endif // MAINWINDOW2_H
The result method blocks your UI thread, making the whole concurrent / future dance useless.
Create a watcher per future and link its finished signal to a lambda that passes both the filename and the contents of the result to a onHashCalculated method on your window. In that method you can check if the hash matches one of your predefined hashes, and update the UI.
Alternatively, move your current run_thread function to a separate QObject that runs on a separate thread, and have it emit a hashCalculated(name, hash) signal that your mainwindow subscribes to using a onHashCalculated slot similar to the one I described above.
Here is code for a HashChecker that encapsulates both approaches.
Note the static QMap that maps filenames to hashes, the way doneFile is chained to checkDone.
enum class Status { Ok, NotOk, Missing };
class HashChecker : public QObject {
Q_OBJECT
public:
QMap<QString, Status> done;
HashChecker(QObject *parent = nullptr) : QObject(parent) {
QObject::connect(this, &HashChecker::doneFile, this, &HashChecker::checkDone);
}
inline static const QMap<QString, QString> hashes = {
{"/SM/test1.pak", "f7002d4419cd235a87746715ba6fb2ea"},
{"/SM/test2.pak", "64c77598586b6c3cb60beed0b0750620"},
{"/SM/test3.pak", "ee53f7a7656a32b5278c460baec46f16"},
};
signals:
void finished();
void doneFile(const QString& fname, Status s);
private slots:
void checkDone(const QString& fname, Status s) {
done[fname] = s;
if (done.size() == hashes.size())
emit finished();
}
public slots:
void check_parallel() {
for (auto it = hashes.cbegin(); it != hashes.cend(); it++) {
auto fname = it.key();
auto hash = it.value();
QFuture<Status> fut = QtConcurrent::run(do_hash, fname, hash);
QFutureWatcher<Status> *fw = new QFutureWatcher<Status>(this);
fw->setFuture(fut);
QObject::connect(fw, &QFutureWatcher<Status>::finished, this,
[=]() {
fw->deleteLater();
emit doneFile(fname, fut.result());
});
}
}
void check_sequential() {
for (auto it = hashes.cbegin(); it != hashes.cend(); it++) {
auto fname = it.key();
auto hash = it.value();
auto result = do_hash(fname, hash);
emit doneFile(fname, result);
}
}
};
If you want to check files in parallel:
HashChecker *hc = new HashChecker();
QObject::connect(hc, &HashChecker::doneFile, this, &MainWindow2::onHashCalculated);
hc->check_parallel();
Sequential in a different thread is almost the same:
QThread *t = new QThread(this);
HashChecker *hc = new HashChecker();
hc->moveToThread(t);
QObject::connect(t, &QThread::started, hc, &HashChecker::check_sequential);
QObject::connect(hc, &HashChecker::doneFile, this, &MainWindow2::onHashCalculated);
QObject::connect(hc, &HashChecker::finished, t, &QThread::quit);
t->start();
I'm trying to send a file from client to server. But it sends only a part of file. Seems like it happens when the size of file is more than 2Mb. What can be the problem? Sorry if it's a stupid question but I can't find an answer in Google.
This is client cpp:
#include "widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent)
{
progressBar = new QProgressBar(this);
tcpSocket = new QTcpSocket(this);
fileLabel = new QLabel(this);
progressLabel = new QLabel(this);
fileBtn = new QPushButton(this);
fileBtn->setText("Open");
sendBtn = new QPushButton(this);
sendBtn->setText("Send");
layout = new QGridLayout;
layout->addWidget(fileBtn, 0, 0);
layout->addWidget(sendBtn, 0, 1);
layout->addWidget(fileLabel, 1, 0);
layout->addWidget(progressBar, 2, 0);
connect(fileBtn, &QPushButton::clicked, this, &Widget::fileOpened);
connect(sendBtn, &QPushButton::clicked, this, &Widget::onSend);
setLayout(layout);
}
Widget::~Widget()
{
}
void Widget::fileOpened()
{
fileName = QFileDialog::getOpenFileName(this, tr("Open file"));
QFileInfo fileInfo(fileName);
fileLabel->setText(fileInfo.fileName() + " : " + QString::number(fileInfo.size()));
qDebug() << fileName;
}
void Widget::onSend()
{
tcpSocket->connectToHost("127.0.0.1", 33333);
QFile file(fileName);
QDataStream out(tcpSocket);
int size = 0;
if (file.open(QIODevice::ReadOnly))
{
QFileInfo fileInfo(file);
QString fileName(fileInfo.fileName());
out << fileName;
qDebug() << fileName;
out << QString::number(fileInfo.size());
qDebug() << fileInfo.size();
progressBar->setMaximum(fileInfo.size());
while (!file.atEnd())
{
QByteArray rawFile;
rawFile = file.read(5000);
//false size inc
QFileInfo rawFileInfo(rawFile);
size += rawFileInfo.size();
out << rawFile;
progressBar->setValue(rawFile.size());
qDebug() << QString::number(fileInfo.size());
qDebug() << "ToSend:"<< rawFile.size();
}
out << "#END";
}
}
This is a server one:
#include "myserver.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
startBtn = new QPushButton(this);
startBtn->setText("Connect");
progressBar = new QProgressBar(this);
layout = new QGridLayout;
layout->addWidget(startBtn, 0, 0);
layout->addWidget(progressBar, 1, 0);
connect(startBtn, &QPushButton::clicked, this, &MainWindow::on_starting_clicked);
setCentralWidget (new QWidget (this));
centralWidget()->setLayout(layout);
}
MainWindow::~MainWindow()
{
server_status=0;
}
void MainWindow::on_starting_clicked()
{
startBtn->setText("Connecting...");
tcpServer = new QTcpServer(this);
connect(tcpServer, SIGNAL(newConnection()), this, SLOT(acceptConnection()));
if (!tcpServer->listen(QHostAddress::Any, 33333) && server_status==0)
{
qDebug() << QObject::tr("Unable to start the server: %1.").arg(tcpServer->errorString());
}
else
{
server_status=1;
qDebug() << QString::fromUtf8("Сервер запущен!");
startBtn->setText("Running");
}
}
void MainWindow::acceptConnection()
{
qDebug() << QString::fromUtf8("У нас новое соединение!");
tcpServerConnection = tcpServer->nextPendingConnection();
connect(tcpServerConnection,SIGNAL(readyRead()),this, SLOT(slotReadClient()));
// tcpServer->close();
QDir::setCurrent("/Users/vlad/Desktop/");
QString fileName;
QString fileSize;
}
void MainWindow::slotReadClient()
{
QDataStream in(tcpServerConnection);
QByteArray z;
if (!isInfoGot)
{
isInfoGot = true;
in >> fileName;
qDebug() << fileName;
in >> fileSize;
qDebug() << fileSize;
}
QFile loadedFile(fileName);
if (loadedFile.open(QIODevice::Append))
{
while (tcpServerConnection->bytesAvailable())
{
qDebug() << "bytesAvailable:" << tcpServerConnection->bytesAvailable();
in >> z;
qDebug() << z;
loadedFile.write(z);
}
loadedFile.close();
}
}
Not so far i faced the same problem. So i find some solution. Test it on files about ~200Mb, no problems i see.
Sender part:
void FileSender::send()
{
QTcpSocket *socket = new QTcpSocket;
connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
// specified m_host and m_port to yours
socket->connectToHost(m_host, m_port);
socket->waitForConnected();
if ( (socket->state() != QAbstractSocket::ConnectedState) || (!m_file->open(QIODevice::ReadOnly)) ) {
qDebug() << "Socket can't connect or can't open file for transfer";
delete socket;
return;
}
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_4);
// This part i need to send not only file, but file name too
// Erase it if you needn't it
out << (quint32)0 << m_file->fileName();
QByteArray q = m_file->readAll();
block.append(q);
m_file->close();
out.device()->seek(0);
// This difference appear because of we send file name
out << (quint32)(block.size() - sizeof(quint32));
qint64 x = 0;
while (x < block.size()) {
qint64 y = socket->write(block);
x += y;
//qDebug() << x; // summary size you send, so you can check recieved and replied sizes
}
}
Server part:
I specified my server as :
class Server : public QTcpServer
{
Q_OBJECT
public:
explicit Server(QHostAddress host = QHostAddress::Any,
quint16 port = Constants::Server::DEFAULT_PORT,
QObject *parent = 0);
~Server();
public slots:
void start();
protected:
void incomingConnection(qintptr handle) Q_DECL_OVERRIDE;
private:
QHostAddress m_host;
quint16 m_port;
};
And realization:
Server::Server(QHostAddress host, quint16 port, QObject *parent)
: QTcpServer(parent),
m_host(host),
m_port(port)
{
...
// your settings init there
}
void Server::start()
{
if ( this->listen(m_host, m_port) )
qDebug() << "Server started at " << m_host.toString() << ":" << m_port;
else
qDebug() << "Can't start server";
}
void Server::incomingConnection(qintptr handle)
{
qDebug() << "incomingConnection = " << handle;
SocketThread *thread = new SocketThread(handle);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}
As you can see i create new class SocketThread for receiving as multitheading server i need.
class SocketThread : public QThread
{
Q_OBJECT
public:
SocketThread(qintptr descriptor, QObject *parent = 0);
~SocketThread();
protected:
void run() Q_DECL_OVERRIDE;
signals:
void onFinishRecieved();
private slots:
void onReadyRead();
void onDisconnected();
private:
qintptr m_socketDescriptor;
QTcpSocket *m_socket;
qint32 m_blockSize;
};
SocketThread::SocketThread(qintptr descriptor, QObject *parent)
: QThread(parent),
m_socketDescriptor(descriptor),
m_blockSize(0)
{
}
SocketThread::~SocketThread()
{
delete m_socket;
}
void SocketThread::run()
{
m_socket = new QTcpSocket;
m_socket->setSocketDescriptor(m_socketDescriptor);
connect(m_socket, SIGNAL(readyRead()), this, SLOT(onReadyRead()), Qt::DirectConnection);
connect(m_socket, SIGNAL(disconnected()), this, SLOT(onDisconnected()), Qt::DirectConnection);
exec();
}
void SocketThread::onReadyRead()
{
QDataStream in(m_socket);
in.setVersion(QDataStream::Qt_5_4);
if (m_blockSize == 0) {
if (m_socket->bytesAvailable() < sizeof(quint32))
return;
in >> m_blockSize;
}
if (m_socket->bytesAvailable() < m_blockSize)
return;
QString fileName;
// get sending file name
in >> fileName;
QByteArray line = m_socket->readAll();
QString filePath = "YOUR"; // your file path for receiving
fileName = fileName.section("/", -1);
QFile target(filePath + "/" + fileName);
if (!target.open(QIODevice::WriteOnly)) {
qDebug() << "Can't open file for written";
return;
}
target.write(line);
target.close();
emit onFinishRecieved();
m_socket->disconnectFromHost();
}
void SocketThread::onDisconnected()
{
m_socket->close();
// leave event loop
quit();
}
I hope you will be able to adapt my code to your project. Best regards
Vlad, I'd suggest you to look at a Qt Example, like this one: http://doc.qt.io/qt-5/qtbluetooth-btfiletransfer-example.html
Just ignore the BT specific stuff, and see what it do.
I think I can help you more if I had a stand-alone code, which I could compile... ie, you didn't posted the headers, main files, and so.
Make a zip, up it somewhere, and I can try looking what is wrong with it when I come back from my late report delivery! =]
I was looking for the same solution. In the end, I am able to transfer the file upto 635MB without QDataStream.
I simply used below code.
for the client.
void MyClient::establishConnection(QString ip, quint16 port){
this->ip = ip;
this->port = port;
socket = new QTcpSocket();
socket->connectToHost(ip, port);
socket->waitForConnected(3000);
QFile file("D:/dummy.txt"); //file path
file.open(QIODevice::ReadOnly);
QByteArray q = file.readAll();
socket->write(q);
}
for the server
void MyThread::readyRead(){
QByteArray line = socket->readAll();
QFile target;
target.setFileName("D:/new1.txt");
if (!target.open(QIODevice::WriteOnly | QIODevice::Append)) {
qDebug() << "Can't open file for written";
return;
}
target.write(line);
target.close();
qDebug() << "file size: " << target.size();
qDebug() << "Finished!";
}
Now, My Question is what will be the effect if I use QDataStream?
I have a problem on the behavior of QCheckBox. I am under Qt5.3.2/MinGW
I create a QGraphicsScene where i add severals QCheckBox via QGraphicsProxyWidget.
To be able to do drag and drop, zoom in / out, I reimplemented the virtual method eventFilter(QObject, QEvent) into QMainWindows and I apply it to my scene:
scene->installEventFilter(this);
But I can’t catch QCheckBox signal with QObject::connect :
connect(checkBox, &QCheckBox::clicked, [=](bool value){
qDebug() << "checkBox->objectName() : " << checkBox->objectName();
qDebug() << "value : " << value; });
If I don’t apply event filter on my scene, my QCheckBox work perfectly.
If now I apply event filter on my QCheckbox :
checkBox->installEventFilter(this);
I receive the event of the first one QCheckBox selected. But if I click on another QCheckBox it is the event of the first QCheckBox selected who is received. QCheckBox status are not modified too and I need to change status into QMainWindows::eventfilter :
if(checkbox->isChecked()) checkbox->setChecked(false);
else if(!checkbox->isChecked()) checkbox->setChecked(true);
MainWindow.cpp :
void MainWindow::Display()
{
scene = new QGraphicsScene();
scene->setObjectName("scene");
scene->installEventFilter(this);
for(int i=;i<10;++i){
QCheckBox *checkBox = new QCheckBox("ID"+QString::number(i));
checkBox->setObjectName("checkBox"+QString::number(i));
checkBox->installEventFilter(this);
checkBox->setChecked(true);
QString style = "QCheckBox {background : white;}";
checkBox->setStyleSheet(style);
// connect(checkBox, &QCheckBox::clicked, [=](bool value){
// qDebug() << "checkBox->objectName() : " << checkBox->objectName();
// qDebug() << "value : " << value; });
QGraphicsProxyWidget* proxyWidget = scene->addWidget(checkBox);
proxyWidget->setObjectName("proxyWidget"+QString::number(i));
proxyWidget->setScale(2);
proxyWidget->setPos(QPointF(i*50, 24));
proxyWidget->setFlag(QGraphicsItem::ItemIsSelectable);
proxyWidget->setZValue(2.0);
}
scene->setSceneRect(QRect(0, 0, 500, 200));
ui->graphicsView->setScene(scene);
ui->graphicsView->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
}
bool MainWindow::eventFilter(QObject *object, QEvent *event)
{
qDebug() << "object->objectName() : " << object->objectName();
qDebug() << "event->type() : " << event->type();
if (event->type() == QEvent::MouseButtonDblClick)
{
if(object->objectName().contains("checkBox",Qt::CaseInsensitive))
{
QCheckBox *checkbox = dynamic_cast<QCheckBox *>(object);
if(checkbox != nullptr)
{
event->setAccepted(true);
if(checkbox->isChecked()) checkbox->setChecked(false);
else if(!checkbox->isChecked()) checkbox->setChecked(true);
checkbox->update();
return true;
}
else return false;
}
else return false;
}
else
{
qDebug() << "default return";
// standard event processing
return QObject::eventFilter(object, event);
}
}
What is it that I'm doing wrong? Thank you.
In my program I have a child process that interacts with a serial port specified to it when the parent process demands it. For example the parent process commands the child process to read a number of bytes with a certain time out from the opened port by sending this command: read 100 1000. The child process launches and opens the port successfully and I can see the message port openned successfully! but from there onwards it won't read the parent commands.
Here's the child source code:
SerialPortHandler.h
#ifndef SERIALPORTHANDLER_H
#define SERIALPORTHANDLER_H
#include <QObject>
#include <QSocketNotifier>
#include <QTextStream>
#include <QSerialPort>
#include <QFile>
#include <QTimer>
#include <QDebug>
#include <QtCore>
enum CommandType { READ, WRITE, BAD, UNKNOWN };
class SerialPortHandler : public QObject
{
Q_OBJECT
public:
explicit SerialPortHandler(QString portname, QString baudrate, QObject *parent = 0);
signals:
public slots:
void execmd();
bool open(const QString& portname, const QString& baudrate);
qint64 read(char * buff, const qint64 size, const qint32 timeout);
QString convertToCaseInsensitiveRegExp(QString str);
CommandType analyze(const QString& line);
qint64 getNum(const QString &line, int index);
void reply(char *buff);
private:
QSocketNotifier *innotif;
QSerialPort *sp;
QTimer *timer;
};
#endif // SERIALPORTHANDLER_H
SerialPortHandler.cpp
#include "SerialPortHandler.h"
#include <unistd.h>
#include <limits>
SerialPortHandler::SerialPortHandler(QString portname, QString baudrate, QObject *parent) :
QObject(parent)
{
timer = new QTimer(this);
sp = new QSerialPort(this);
if(!open(portname, baudrate)) {
qDebug() << sp->error() << sp->errorString();
exit(sp->error());
}
innotif = new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read, this);
connect(innotif, SIGNAL(activated(int)), this, SLOT(execmd()));
}
void SerialPortHandler::execmd()
{
qDebug() << "command received. analyzing...";
// qint64 nbr = -1, size = -1;
// qint32 timeout = -1;
// char * buff = 0;
// QTextStream in(stdin);
// QString ln = in.readAll();
// switch (analyze(ln)) {
// case READ:
// size = getNum(ln, 1);
// timeout = getNum(ln, 2);
// if(size > -1 && timeout > -1)
// nbr = read(buff, size, timeout);
// if(nbr > -1)
// reply(buff);
// break;
// default:
// break;
// }
}
bool SerialPortHandler::open(const QString &portname, const QString &baudrate)
{
sp->setPortName(portname);
if (!sp->open(QIODevice::ReadWrite) ||
!sp->setBaudRate(baudrate.toInt()) ||
!sp->setDataBits(QSerialPort::Data8) ||
!sp->setParity(QSerialPort::NoParity) ||
!sp->setStopBits(QSerialPort::OneStop) ||
!sp->setFlowControl(QSerialPort::NoFlowControl)) {
return false;
}
sp->clear();
qDebug() << "port openned successfully!";
return true;
}
//day light wont affect this timer so the system wont freeze
qint64 SerialPortHandler::read(char *buff, const qint64 size, const qint32 timeout)
{
qint64 numbytesread = -1;
timer->start(timeout);
while (true) {
if(timer->remainingTime() > 0) {
return -1;
}
if((sp->isReadable() && sp->bytesAvailable() > 0) ||
(sp->isReadable() && sp->waitForReadyRead(10))) {
numbytesread += sp->read(buff, size);
}
if(numbytesread < 0) {
return -1;
}
if(numbytesread == size) {
break;
}
}
return numbytesread;
}
void SerialPortHandler::notify()
{
}
QString SerialPortHandler::convertToCaseInsensitiveRegExp(QString str)
{
QString result;
for(int i = 0 ; i < str.size() ; ++i) {
result.append("[");
result.append(str.at(i).toLower());
result.append(str.at(i).toUpper());
result.append("]");
}
return result;
}
CommandType SerialPortHandler::analyze(const QString &line)
{
QString read, write;
read = convertToCaseInsensitiveRegExp("read");
write = convertToCaseInsensitiveRegExp("write");
if(line.contains(QRegExp(QString("^.*%1\\s+[1-9]\\d*\\s+[1-9]\\d*.*").arg(read)))) {
return READ;
}
return UNKNOWN;
}
qint64 SerialPortHandler::getNum(const QString& line, int index) {
QStringList args(line.split(QRegExp("\\s+")));
bool done;
qint64 size = args.at(index).toInt(&done, 10);
if(done) {
return size;
}
return -1;
}
void SerialPortHandler::reply(char * buff) {
QDataStream out(stdout);
out << buff;
}
main.cpp
#include <QCoreApplication>
#include <QDebug>
#include "SerialPortHandler.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
if(argc != 3) {
qDebug() << "usage:" << argv[0] << "port" << "baudrate";
} else {
SerialPortHandler *sph = new SerialPortHandler(argv[1], argv[2]);
}
return a.exec();
}
My parent process consists of the following:
ParentProcess.h
#ifndef PARENTPROCESS_H
#define PARENTPROCESS_H
#include <QObject>
#include <QtCore>
class ParentProcess : public QObject
{
Q_OBJECT
public:
explicit ParentProcess(QObject *parent = 0);
signals:
public slots:
private slots:
void sendRead();
void writeSomething();
void handleError(QProcess::ProcessError error);
private:
QProcess *p;
};
#endif // PARENTPROCESS_H
ParentProcess.cpp
#include "ParentProcess.h"
#include <QDebug>
ParentProcess::ParentProcess(QObject *parent) :
QObject(parent)
{
p = new QProcess(this);
connect(p, SIGNAL(readyReadStandardOutput()), this, SLOT(sendRead()));
connect(p, SIGNAL(readyReadStandardError()), this, SLOT(sendRead()));
connect(p, SIGNAL(started()), this, SLOT(writeSomething()));
connect(p, SIGNAL(error(QProcess::ProcessError)), this, SLOT(handleError(QProcess::ProcessError)));
QStringList args;
args << "/dev/ttyUSB0" << "115200";
p->start("/home/moki/Work/Programs/build-serialio-Desktop_Qt_5_3_0_GCC_64bit-Debug/serialio", args, QProcess::ReadWrite);
}
void ParentProcess::sendRead() {
qDebug() << "data:" << p->readAllStandardError() << p->readAllStandardOutput();
}
void ParentProcess::writeSomething() {
qDebug() << "writing";
QString cmd = "read 10 10000\n";
qint64 a = p->write(cmd.toStdString().c_str());
qDebug() << "wrote:" << a;
}
void ParentProcess::handleError(QProcess::ProcessError error)
{
switch (error) {
case QProcess::FailedToStart:
qDebug() << "failed to start";
break;
case QProcess::Crashed:
qDebug() << "crashed.";
break;
default:
break;
}
}
main.cpp
#include <QCoreApplication>
#include "ParentProcess.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
ParentProcess p;
return a.exec();
}
I have seen a couple of other answers in SO but none of them address my issue. As you can see my child process is not supposed to complete and exit. It will remain launched as long as the parent process wishes. Is it correct to use QProcess-launched processes this way?
I changed my code to the following and now it's working. But I haven't understood why this code works and my original one doesn't.
in the parent process source i changed the constructor as follows:
ParentProcess::ParentProcess(QObject *parent) :
QObject(parent)
{
p = new QProcess(this);
connect(p, SIGNAL(error(QProcess::ProcessError)), this, SLOT(handleError(QProcess::ProcessError)));
connect(p, SIGNAL(readyRead()), this, SLOT(sendRead()));
connect(p, SIGNAL(started()), this, SLOT(writeSomething()));
QStringList args;
args << "/dev/ttyUSB0" << "115200";
p->setProcessChannelMode(QProcess::MergedChannels);
p->start("/home/moki/Work/Programs/build-serialio-Desktop_Qt_5_3_0_GCC_64bit-Debug/serialio", args, QProcess::ReadWrite);
}
and the sendRead() function to this:
void ParentProcess::sendRead() {
int bytes = p->bytesAvailable();
qDebug() << "data:" << p->read(bytes);
}
finally, the writeSomething() to:
void ParentProcess::writeSomething() {
qDebug() << "gonna write.";
if(p->state() == QProcess::Running) {
qDebug() << "writing";
QString cmd = "read 10 10000\n";
qint64 a = p->write(cmd.toStdString().c_str());
qDebug() << "wrote:" << a << "bytes.";
}
}
and now it works. If anyone could please explain this to me, I would be really grateful.