码迷,mamicode.com
首页 > 其他好文 > 详细

get progress Using CopyFileExW in Qt

时间:2015-04-03 11:42:20      阅读:309      评论:0      收藏:0      [点我收藏+]

标签:

#include <QApplication>
#include <QFileDialog>
#include <QLineEdit>
#include <QPushButton>
#include <QLabel>
#include <QGridLayout>
#include <QThread>
#include <QPointer>
#include <QStateMachine>
#include <windows.h>

static QString getLastErrorMsg() {
    LPWSTR bufPtr = NULL;
    DWORD err = GetLastError();
    FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                   FORMAT_MESSAGE_FROM_SYSTEM |
                   FORMAT_MESSAGE_IGNORE_INSERTS,
                   NULL, err, 0, (LPWSTR)&bufPtr, 0, NULL);
    const QString result =
        (bufPtr) ? QString::fromUtf16((const ushort*)bufPtr).trimmed() :
                   QString("Unknown Error %1").arg(err);
    LocalFree(bufPtr);
    return result;
}
class CopierWorker : public QThread { // only to be used by the Copier object
   BOOL m_stop;
   QString m_src, m_dst;
   QPointer<QObject> m_object;
   static DWORD CALLBACK copyProgress(
         LARGE_INTEGER totalSize, LARGE_INTEGER totalTransferred,
         LARGE_INTEGER streamSize, LARGE_INTEGER streamTransferred,
         DWORD streamNo, DWORD callbackReason, HANDLE src, HANDLE dst,
         LPVOID data)
   {
      Q_UNUSED(streamSize) Q_UNUSED(streamTransferred)
      Q_UNUSED(streamNo) Q_UNUSED(callbackReason)
      Q_UNUSED(src) Q_UNUSED(dst)
      QObject * object = static_cast<QObject*>(data);
      const QString text = QString("Transferred %1 of %2 bytes").
            arg(totalTransferred.QuadPart).arg(totalSize.QuadPart);
      QMetaObject::invokeMethod(object, "newStatus", Qt::QueuedConnection,
                                Q_ARG(QString, text));
      return PROGRESS_CONTINUE;
   }
   void run() {
      m_stop = FALSE;
      BOOL rc = CopyFileExW((LPCWSTR)m_src.utf16(), (LPCWSTR)m_dst.utf16(),
                            &copyProgress, m_object, &m_stop, 0);
      if (!rc) {
         QMetaObject::invokeMethod(m_object, "newStatus", Qt::QueuedConnection,
                                   Q_ARG(QString, getLastErrorMsg()));
      }
   }
   CopierWorker(const QString & src, const QString & dst, QObject * obj) :
      m_src(src), m_dst(dst), m_object(obj) {}
   void stop() { m_stop = TRUE; }
   friend class Copier;
};

class Copier : public QObject {
   Q_OBJECT
   QPointer<CopierWorker> m_worker;
public:
   Copier(const QString & src, const QString & dst) : m_worker(new CopierWorker(src, dst, this)) {
      connect(m_worker, SIGNAL(finished()), SIGNAL(finished()));
      connect(m_worker, SIGNAL(finished()), m_worker, SLOT(deleteLater()));
   }
   ~Copier() {
      if (!m_worker) return;
      m_worker->stop();
      if (!m_worker->isRunning()) delete m_worker;
   }
   Q_SIGNAL void newStatus(const QString &);
   Q_SIGNAL void finished();
   Q_SLOT void stop() { m_worker->stop(); }
   void copy() { m_worker->start(); }
};

class Widget : public QWidget {
   Q_OBJECT
   QLabel * m_status;
   QLineEdit * m_src, * m_dst;

   Q_SIGNAL void stopCopy();
   Q_SLOT void startCopy() {
      Copier * copier = new Copier(m_src->text(), m_dst->text());
      connect(copier, SIGNAL(newStatus(QString)), m_status, SLOT(setText(QString)));
      connect(copier, SIGNAL(finished()), SIGNAL(copyFinished()));
      connect(this, SIGNAL(stopCopy()), copier, SLOT(stop()));
      copier->copy();
   }
   Q_SIGNAL void copyFinished();
public:
   Widget(QWidget * parent = 0) : QWidget(parent) {
      QGridLayout * layout = new QGridLayout(this);
      m_src = new QLineEdit;
      m_dst = new QLineEdit;
      QPushButton * srcButton = new QPushButton("...");
      QPushButton * dstButton = new QPushButton("...");
      QPushButton * copy = new QPushButton("Copy");
      QPushButton * cancel = new QPushButton("Cancel");
      QFileDialog * getSrc = new QFileDialog(this, "Source File");
      QFileDialog * getDst = new QFileDialog(this, "Source File");
      m_status = new QLabel;
      layout->addWidget(new QLabel("From:"), 0, 0, 1, 1, Qt::AlignRight);
      layout->addWidget(m_src, 0, 1, 1, 1);
      layout->addWidget(srcButton, 0, 2, 1, 1);
      layout->addWidget(new QLabel("To:"), 1, 0, 1, 1, Qt::AlignRight);
      layout->addWidget(m_dst, 1, 1, 1, 1);
      layout->addWidget(dstButton, 1, 2, 1, 1);
      layout->addWidget(m_status, 2, 0, 1, 3);
      layout->addWidget(copy, 3, 0, 1, 3, Qt::AlignCenter);
      layout->addWidget(cancel, 4, 0, 1, 3, Qt::AlignCenter);

      getSrc->setFileMode(QFileDialog::ExistingFile);
      getDst->setAcceptMode(QFileDialog::AcceptSave);
      connect(srcButton, SIGNAL(clicked()), getSrc, SLOT(show()));
      connect(dstButton, SIGNAL(clicked()), getDst, SLOT(show()));
      connect(getSrc, SIGNAL(fileSelected(QString)), m_src, SLOT(setText(QString)));
      connect(getDst, SIGNAL(fileSelected(QString)), m_dst, SLOT(setText(QString)));

      QStateMachine * machine = new QStateMachine(this);
      QState * stopped = new QState(machine);
      QState * copying = new QState(machine);
      machine->setInitialState(stopped);
      stopped->addTransition(copy, SIGNAL(clicked()), copying);
      stopped->assignProperty(copy, "enabled", true);
      stopped->assignProperty(cancel, "enabled", false);
      copying->addTransition(cancel, SIGNAL(clicked()), stopped);
      copying->addTransition(this, SIGNAL(copyFinished()), stopped);
      connect(copying, SIGNAL(entered()), SLOT(startCopy()));
      connect(copying, SIGNAL(exited()), SIGNAL(stopCopy()));
      copying->assignProperty(copy, "enabled", false);
      copying->assignProperty(cancel, "enabled", true);
      machine->start();
   }
};

int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
   Widget w;
   w.show();
   return a.exec();
}

#include "main.moc"


get progress Using CopyFileExW in Qt

标签:

原文地址:http://my.oschina.net/leon0407/blog/395531

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!