0

Android デバイスと Mac の間でファイルを転送するアプリを作成しています。ファイル転送は機能していますが、ユーザー エクスペリエンスの観点から、転送がいつ終了したかを確認できるプログレスバーを追加したいと考えています。

Android デバイスに転送しているため、mtp スタックを使用する必要がありました。ファイルをコピーするために使用される関数は

LIBMTP_Send_File_From_File(device, path, genfile, ProgressBar, NULL);

ProgressBar はコールバック関数で、MTP スタックは C で記述されています。

私のアプリは C++/Qt で書かれています。

最初に進行状況バーを設計し、CONNECT/SIGNAL/SLOT Mecanism を使用して進行状況バーを更新することを期待していましたが、機能していません。

私が行ったことは、コールバックを定義した dialog.h にあります。

extern "C" int ProgressBar(const uint64_t data_sent, const uint64_t data_total, void const * const data);

ダイアログボックスを設計するためのクラス。

class Dialog : public QWidget
{
    Q_OBJECT
public:
    Dialog();
    void CreateProgressBar();
    void DestroyProgressBar();

private:
    QWidget *ProgressDialog;
    QProgressBar *ProgressIndicator;
    QVBoxLayout *ProgressLayout;

    QPushButton *CancelButton;

private slots:
    void onCancelButtonAction();
};

Dialog.c で、

Dialog::Dialog()
{
}

void Dialog::CreateProgressBar() {
    ProgressDialog = new QWidget(this);
    ProgressDialog->setWindowTitle("Progress");

    ProgressLayout = new QVBoxLayout(this);

    ProgressIndicator = new QProgressBar();
    ProgressIndicator->resize(200,25);
    //ProgressIndicator->setrange(0,100);
    ProgressIndicator->setValue(0);
    ProgressIndicator->setOrientation(Qt::Horizontal);
    connect(ProgressIndicator,SIGNAL(ProgressBar(const uint64_t, const uint64_t, void const * const)),ProgressIndicator,SLOT(setValue(int)));

    CancelButton = new QPushButton();
    CancelButton->setFixedSize(25,25);
    CancelButton->setText("Cancel");
    CancelButton->setFlat(true);
    CancelButton->setAutoFillBackground(true);
    CancelButton->setStyleSheet("QPushButton { background-color : white;}");
    connect(CancelButton, SIGNAL(clicked()), this, SLOT(onCancelButtonAction()));

    ProgressLayout->addWidget(ProgressIndicator);
    ProgressLayout->addWidget(CancelButton);

    ProgressDialog->setLayout(ProgressLayout);
    ProgressDialog->show();
}

void Dialog::DestroyProgressBar() {
    ProgressDialog->close();
}

void Dialog::onCancelButtonAction() {
    DestroyProgressBar();
}

および「ProgressBar」の C コード

int ProgressBar(const uint64_t data_sent, const uint64_t data_total, void const * const data) {
    return (data_sent * 100) / data_total;
}

クラスの一部ではないため、接続が SIGNAL を ProgressBar に接続することを拒否するため、これは基本的に機能しません。

一方、クラスで ProgressBar を移動すると、接続は問題ありませんが、LIBMTP_Send がクラスの使用を拒否するため、コードはビルドされません。

LIBMTP_Send で ProgressBar を呼び出しています... MyProgress.ProgressBar を使用して

    Dialog MyProgress;
    MyProgress.CreateProgressBar();

LIBMTP_Send_File_From_File(device, path, genfile, MyProgress.ProgressBar, NULL);

Cコールバックの代わりにクラスの場合、メソッドへの呼び出しを使用しているため、機能していません

Cコードの代わりにクラスを使用しようとするときの私の方法は、次のように定義されています。

int Dialog::ProgressBar(const uint64_t data_sent, const uint64_t data_total, void const * const data) {
    char* tmp_string;
    char* tmp_sent;
    char* tmp_total;

    if(ProgressIndicator.destroyed() == true)
        return true;

    if (ProgressIndicator != NULL) {

        ProgressIndicator->setValue();
    }

    if (progressDialog != NULL) {
        return (data_sent * 100) / data_total;
    }
    return 0;
}

その場合、私はやっています:

ret = LIBMTP_Send_File_From_File(PulsDeviceMngr->device, strdup(AbsolutePath), genfile, MyProgress.ProgressBar, NULL);

しかし、ビルドエラーは次のとおりです。非静的メンバー関数への参照を呼び出す必要があります

以下に示すように、LIBMTP 関数を呼び出したコードでダイアログのインスタンスを作成しています。

  Dialog MyProgress;
  MyProgress.CreateProgressBar();

  genfile = LIBMTP_new_file_t();
  ...

  ret = LIBMTP_Send_File_From_File(PulsDeviceMngr->device, strdup(AbsolutePath), genfile, MyProgress.ProgressBar, NULL);

私は本当に立ち往生しています...空です:-)

4

1 に答える 1