我想将文本添加到剪贴板,然后在文本添加到剪贴板后立即退出应用程序。
QClipboard需要在事件循环中运行,因此我创建了一个带有插槽的QObject,该插槽为我执行剪贴板复制,并使用QTimer::singleShot
调用了该插槽。完成插槽后,它会向finished()
发出信号QApplication::quit()
。
现在的问题是,如果我发出finished()
信号并调用QApplication::quit()
,则剪贴板为空。仅当我不退出QApplication时,剪贴板文本才被正确添加。为什么会这样?
除了QTimer :: singleShot之外,我还尝试使用QMetaObject::invokeMethod
调用我的广告位,但结果与上面相同。
main.cpp
#include "controller.h"
#include "worker.h"
#include <QApplication>
#include <QDebug>
#include <QTimer>
#include <QtGlobal>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
qDebug() << "Starting executing...\n";
QString bn = QString::fromStdString(argv[1]);
Worker b;
// QTimer::singleShot(1, [&] { b.onEventLoopStarted(bn); });
QMetaObject::invokeMethod(&b, "onEventLoopStarted", Qt::QueuedConnection, Q_ARG(QString, bn));
QObject::connect(&b, SIGNAL(finished()), &app, SLOT(quit()));
return app.exec();
}
worker.cpp
#include "worker.h"
#include <boost/format.hpp>
#include <cstdio>
#include <fstream>
#include <ios>
#include <iostream>
#include <QApplication>
#include <QClipboard>
#include <QDebug>
#include <QDir>
#include <QMessageBox>
#include <QtGui/QImage>
#include <QTimer>
#include <QThread>
#include <regex>
#include <stdio.h>
#include <stdlib.h>
#include <string>
// Worker::Worker(): bn("") {}
Worker::Worker(QObject *parent) : QObject(parent) {}
Worker::~Worker() {}
void Worker::set_bn(const QString &bn) {
this->bn = bn;
}
void Worker::doc_filename(std::string& fn) {
FILE *p;
char line [1024];
// https://stackoverflow.com/a/671528
p = popen("ps aux | grep '[/]usr/share/typora/Typora /'", "r");
if (!p) {
fprintf(stderr, "Error.");
exit(1);
}
while (fgets(line, sizeof(line) - 1, p)) {
std::string sline(line);
std::cout << "1 sline: " << sline << std::endl;
static const std::regex re("(.*\\/usr\\/share\\/typora\\/Typora)\\ (\\/.*)\n");
std::smatch m;
if(std::regex_match(sline, m, re)) {
fn = m[2];
std::cout << "2. path: " << fn << std::endl;
}
else {
std::cout << "2. not match" << std::endl;
}
}
pclose(p);
}
void Worker::onEventLoopStarted(QString bn) {
std::string fn = "";
this->doc_filename(fn);
if (fn == "") {
QMessageBox msgBox;
msgBox.setText("Open the typora document, where the image should be added to.");
msgBox.exec();
emit finished();
// QApplication::quit();
}
// from paramater get pwd and fn
// move fn to assets of fn
std::cout << "fn: " << fn << std::endl;
qDebug() << QDir::currentPath();
QString img_fn = QDir::cleanPath(QDir::currentPath() + QDir::separator() + bn);
qDebug() << "img_fn" << img_fn;
/* moves
std::ifstream in(img_fn, std::ios::in | std::ios::binary);
std::ofstream out(new_img_fn, std::ios::out | std::ios::binary);
out << in.rdbuf();
std::remove(img_fn);
*/
// Calculate img height, e.g. *0.8. use 0.8, then adjust after test
QImage img;
img.load(img_fn);
QString new_width = QString::number(img.width() * 0.8);
QString html_line = QString("<img src='%1' alt='' width='%2'>").arg(img_fn, new_width);
qDebug() << html_line;
// copy html_line to qt clipboard
QClipboard *clipboard = QApplication::clipboard();
clipboard->clear();
clipboard->setText(html_line);
qDebug() << "test";
//emit finished();
qDebug() << "finished Worker\n";
//QApplication::quit();
}
worker.h
#ifndef CHILD_OBJECT_H
#define CHILD_OBJECT_H
#include <QObject>
#include <QThread>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = 0);
~Worker();
void set_bn(const QString &bn);
void doc_filename(std::string&);
signals:
void finished();
public slots:
void onEventLoopStarted(QString);
private:
QString bn;
};
#endif // CHILD_OBJECT_H