如何在事件循环中运行QClipboard,然后在QClipboard完成将内容复制到剪贴板后退出应用程序?

时间:2019-06-12 17:13:48

标签: c++ linux qt

我想将文本添加到剪贴板,然后在文本添加到剪贴板后立即退出应用程序。

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

0 个答案:

没有答案