系统的文件管理跨平台拷贝

1 .文管跨平台拷贝

1.1 流程图

 

1.2 剪贴板读写的坑

(1)服务程序无法实现剪贴板的监控功能。

(2)写剪贴板功能,不能在thritf的sessionHandler类的实现函数中写入,会提示一个com错误,必须emit到mydatachange的类中的函数才可以实现。

(3)图片数据转成string对象,防止0字符截断。

(4)拷贝文件时,可以以文本的形式获取路径。但是不能以这种形式写入剪贴板,黏贴时会失败。

(5)UOS和windows粘贴复制,必须是剪贴板隔离的,而且代码实现要避免自己写的剪贴板,又被自己捕获,导致通信无限循环了。

2. 剪贴板拷贝功能实现

剪贴板拷贝是在mydatachange类中实现。构造函数使用如下函数,实现监控功能。

QClipboard* clipBoard =  QGuiApplication::clipboard();

QObject::connect(clipBoard, SIGNAL(dataChanged()), this, SLOT(mydataChangedCheck()));

剪贴板监控功能是QClipboard实现的,需要绑定dataChanged信号,而且承载QClipboard的类,必须继承来自QObject的对象。

2.1 剪贴板监控触发

剪贴板改变时,会触发mydataChangedCheck函数。通过QMimeData对象,获取剪贴板里面的内容。

2.1.1 文字类型

比较简单,通过QMimeData类的text()函数就可以获取。

2.1.2 图片类型

通过QMimeData类的imageData()函数就可以获取。

if (strMimeData->hasImage()) {
        //将图片数据转为QImage
        QImage img = qvariant_cast<QImage>(strMimeData->imageData());

        QByteArray arr;
        QBuffer buffer(&arr);
        buffer.open(QIODevice::WriteOnly);
        img.save(&buffer, "jpg");

        QString strImg =  arr.toBase64();
        emit dataChangeClip(COPY_TYPE_IMG, strImg, mydatachange_srv::nPort);

#if 0
        FILE* fp = fopen("d:\\mydataChangedCheck.jpg", "wb");
        if (fp != nullptr) { // 解析base64位;
            QByteArray strImgResult = QByteArray::fromBase64(strImg.toLatin1());
            fwrite(strImgResult.data(), 1, strImgResult.size(), fp);
            fclose(fp);
        }
#endif
    }

先把QImage对象转成QByteArray对象,通过QBuffer中转一下,不需要写成文件再读取回来。如果要把QByteArray对象转成string对象进行thritf网络传输等,需要编码成BASE64或是改成2位16进制的数据,否则会因为0字符串截断。

2.1.3 文件类型

通过QMimeData类的urls()函数就可以获取。

 const QMimeData* strMimeData = clipBoard->mimeData();
    if (strMimeData != nullptr && strMimeData->hasUrls()) {
        QString strFileList = "";

        QList<QUrl> urls = strMimeData->urls();
        for (int i = 0; i < urls.size(); i++) {
            QString strFile = urls.at(i).toLocalFile();
            if (i > 0) {
                strFileList +=  "\n&t";
            }
            strFileList += strFile;
        }
        qDebug() << strFileList;

        emit dataChangeClip(COPY_TYPE_FILE, strFileList, mydatachange_srv::nPort);
    }

如果是文件形式的拷贝,可以用getText的方式,获取的就是如下这种格式的路径数据:

file:///C:/Users/69028/Desktop/ClientDemo.7z\nfile:///C:/Users/69028/Desktop/HOOK2.7z,可以用这种方式通过字符串分割的方式来读取文件路径,但是不能用这种方式写入剪贴板。这种方式写入的剪贴板,不能黏贴。

2.2 剪贴板写入

2.2.1 文字类型

通过QClipboard类的setText函数可以实现。

2.2.2 图片类型

通过QClipboard类的QImage函数可以实现。

bool mydatachange::setClipBrdImg(const std::string& ImgData)
{
    bool bRet = true;
    try {
        QString strImg(ImgData.c_str());
        QByteArray strImgResult = QByteArray::fromBase64(strImg.toLatin1());

#if 0
        FILE* fp = fopen("d:\\setClipBrdImg.jpg", "wb");
        if (fp != nullptr) { // 解析base64位;
            fwrite(strImgResult.data(), 1, strImgResult.size(), fp);
            fclose(fp);
        }
#endif

        QImage* image = new QImage;
        image->loadFromData(strImgResult);
        QClipboard* clip = QGuiApplication::clipboard();
        setClipBrdFlag();
        //   clip->setPixmap(QPixmap::fromImage(*image));
        clip->setImage(*image);
    } catch (...) {
        bRet = false;
        qDebug() << "catch error";
    }

    return bRet;
}

String类型的图片信息,通过BASE64转回QByteArray,然后再转成QImage,设置到剪贴板。这时候可以通过黏贴,成功拷贝图片。

2.2.3 文件类型

文件类型的剪贴板写入,需要转成Url链表,再通过调用QMimeData类的setUrls函数。然后通过QMimeData类的setMimeData函数可以实现。

bool mydatachange::setClipBrdFile(const std::string& path, const std::string& vol)
{
    bool bRet = true;
    try {
        QString strCtx = path.c_str();
        QString strDiskLabel = vol.c_str();
        strDiskLabel += ":";

        QString strSplit = "\n&t";
        QStringList lstStrFile;
        int nPos = 0, nPosCur = 0, nSplit = strSplit.length();

        do {
            nPosCur = strCtx.indexOf(strSplit, nPos);
            if (nPosCur > 0) {
                QString strOnePath = strCtx.mid(nPos, nPosCur - nPos);
                lstStrFile.push_back(strOnePath);

                nPos = nPosCur + nSplit;
            } else {
                break;
            }
        } while (nPosCur >= 0);

        if (lstStrFile.length() > 0 && strDiskLabel.length() > 0) {
            QList<QUrl> copyfile;

            for (QString onePath : lstStrFile) {
                QString tmpOneWinPath = strDiskLabel + onePath;
                qDebug() << "win path:" << tmpOneWinPath;
                QUrl url = QUrl::fromLocalFile(tmpOneWinPath);
                if (url.isValid()) {
                    copyfile.push_back(url);
                }
            }

            QMimeData* data = new QMimeData;
            if (data) {
                data->setUrls(copyfile);
                QClipboard* clip = QGuiApplication::clipboard();
                setClipBrdFlag();
                clip->setMimeData(data);  // sessionHandler触发的thritf接口调用,会失败。提示线程中,com失败。
            } else {
                qDebug() << "QMimeData new fail";
            }
            bRet = true;
        }
        qDebug() << "path:" << strCtx << ";vol:" << strDiskLabel;
    } catch (...) {
        qDebug() << "catch error";
        bRet = false;
    }

    qDebug() << "out";
    return bRet;
}

文件类型的拷贝,通过分隔符\n&t区分多个路径的名称。把解析后的路径,加入QUrl的列表中,再设置到QMimeData里面。然后,设置到QClipboard的剪贴板对象里。这时黏贴,可以成功复制文件或是文件夹。

3.网络磁盘共享

Windows端的实现是在mydatachange_srv类里面。通过启动http服务,实现了把windows的磁盘进行网络共享,然后把路径发送给uos后,uos可以拷贝windows的信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值