自定义QTextEdit实现拖拽功能

QTextEdit是一个可以显示各种复杂类型信息的控件,比如文本信息,图片,html等,有时作为输入框我们需要实现拖拽展示或发送一些文件等,而如果要实现拖拽发送文件,这个时候需要重载dropEvent事件和insertFromMimeData()函数,在使用这两个函数的过程中,发现拖拽文件时,source获取的信息都是文本信息即一个路径,而复制功能,粘贴也是一段文本信息,而这样就有一个问题了,发送信息时,我复制一段存在的文件的路径是否把这个当作是文件呢还是纯文本呢,例如:拖拽D盘bak目录下的11111.png文件

好在经过查看验证发送hasUrls可以区分是复制的文件Url还是纯文本信息,当然QMimData还有其他属性,但只有这个能区分这种情况,下面请看示例:

CustomTextEdit.h

#ifndef CUSTOMTEXTEDIT_H
#define CUSTOMTEXTEDIT_H

#include <QTextEdit>
#include <QDropEvent>

class CustomTextEdit: public QTextEdit
{
    Q_OBJECT

public:
    CustomTextEdit(QWidget *parent = nullptr);

    QStringList getSplitUrl(QString text);
    QString getFileSizeFormat(qint64 size);
    QPixmap getFileIconPixmap(const QString &path);

signals:
    void signalShowIcon(const QPixmap &pix);

protected:
    void insertFromMimeData(const QMimeData *source) override;
    void dropEvent(QDropEvent *event) override;
    bool canInsertFromMimeData(const QMimeData *source) const override;
};

#endif // CUSTOMTEXTEDIT_H

CustomTextEdit.cpp

#include "CustomTextEdit.h"
#include <QDebug>
#include <QMimeData>
#include <QFileInfo>
#include <QClipboard>
#include <QApplication>
#include <QMessageBox>
#include <QPixmap>
#include <QFileIconProvider>
#include <QPainter>
#include <QIcon>
#include <QFont>

CustomTextEdit::CustomTextEdit(QWidget *parent)
    :QTextEdit(parent)
{
}

void CustomTextEdit::dropEvent(QDropEvent *event)
{
    insertFromMimeData(event->mimeData());
    event->accept();
}

QStringList CustomTextEdit::getSplitUrl(QString text)
{
    QStringList urls;
    if(text.isEmpty())
        return urls;

    QStringList list = text.split("\n");
    foreach (QString url, list) {
        if(!url.isEmpty()){
            // url = file:///D:/bak/11111.png
            QFileInfo info(url);
            qDebug() << "======getUrl=======url===" << url << "==info.exists==" << info.exists()<< __LINE__;
            QStringList str = url.split("///");
            // str== ("file:", "D:/bak/11111.png")

            if(str.size()>=2)
            {
                QFileInfo info2(str.at(1));
                qDebug() << "======getUrl=======url===" << url << "==info2.exists==" << info2.exists() << __LINE__;
                urls.append(str.at(1));
            }
        }
    }
    return urls;
}



void CustomTextEdit::insertFromMimeData(const QMimeData *source)
{
    qDebug() << "======insertFromMimeData=======1===hasText===" << source->hasText() << __LINE__;
    qDebug() << "======insertFromMimeData=======1===hasUrls===" << source->hasUrls() << __LINE__;
    qDebug() << "======insertFromMimeData=======1===hasHtml===" << source->hasHtml() << __LINE__;
    qDebug() << "======insertFromMimeData=======1===hasImage===" << source->hasImage() << __LINE__;
    qDebug() << "======insertFromMimeData=======1===hasColor===" << source->hasColor() << __LINE__;

    QString insertInfo = source->text();
    if(insertInfo.isEmpty())
        return;
    QClipboard *clipBoard= QApplication::clipboard();
    QString strClip = clipBoard->text();
    qDebug() << "======insertFromMimeData=======2===clipBoard===" << strClip << __LINE__;
    qDebug() << "======insertFromMimeData=======2===source->text()===" << source->text() << __LINE__;
    QStringList strList = getSplitUrl(insertInfo);
    qDebug() << "======insertFromMimeData=======2===strList===" << strList << __LINE__ << "\n\n";
    bool isFile = source->hasUrls();//这个标志非常重要,因为不管理是拖拽文件还是复制文本信息,source->text()都是有值的,就能区分是复制的文本还是文件
    if(!isFile)//纯文本类型
    {
        this->setText(insertInfo);
    }
    else if(1 == strList.size())
    {
        QFileInfo fileInfo(strList[0]);
        if(fileInfo.isDir())
        {
            QMessageBox::information(this,QStringLiteral("提示"),QStringLiteral("不允许拖拽目录!"));
            return;
        }

        if(fileInfo.size() > 50 * 1024 * 1024)
        {
            QMessageBox::information(this,QStringLiteral("提示"),QStringLiteral("发送的文件大小不能大于50M"));
            return;
        }

        QPixmap pix = getFileIconPixmap(strList[0]);
        emit signalShowIcon(pix);
    }
    else if(strList.size() > 1)
    {
        QMessageBox::information(this, QStringLiteral("提示"), QStringLiteral("只允许拖拽单个文件!"));
    }
}

QPixmap CustomTextEdit::getFileIconPixmap(const QString &path)
{
    QFileIconProvider provder;
    QFileInfo fileInfo(path);
    QIcon icon = provder.icon(fileInfo);

    QString strFileSize = getFileSizeFormat(fileInfo.size());

    QFont font(QString("Microsoft YaHei"));
    font.setPixelSize(12);
    QFontMetrics fontMetrics(font);
    QSize textSize = fontMetrics.size(Qt::TextSingleLine, fileInfo.fileName());
    QSize fileSize = fontMetrics.size(Qt::TextSingleLine, strFileSize);
    int maxWidth = textSize.width() > fileSize.width() ? textSize.width() :fileSize.width();
    QPixmap pix(50 + maxWidth + 10, 50);
    pix.fill();

    QPainter painter;
    painter.begin(&pix);
    // 文件图标
    QRect rectIcon(0, 0, 50, 50);
    painter.drawPixmap(rectIcon, icon.pixmap(40,40));
    painter.setPen(Qt::black);
    // 文件名称
    QRect rectText(50+10, 3, textSize.width(), textSize.height());
    painter.drawText(rectText, fileInfo.fileName());
    // 文件大小
    QRect rectFile(50+10, textSize.height()+5, fileSize.width(), fileSize.height());
    painter.drawText(rectFile, strFileSize);
    painter.end();
    return pix;
}


QString CustomTextEdit::getFileSizeFormat(qint64 size)
{
    QString strSize;
    double num;
    if(size < 1024){
        num = size;
        strSize = "B";
    }
    else if(size < 1024 * 1224){
        num = size / 1024.0;
        strSize = "KB";
    }
    else if(size <  1024 * 1024 * 1024){
        num = size / 1024.0 / 1024.0;
        strSize = "MB";
    }
    else{
        num = size / 1024.0 / 1024.0/ 1024.0;
        strSize = "GB";
    }
    return QString::number(num,'f',2) + " " + strSize;
}



bool CustomTextEdit::canInsertFromMimeData(const QMimeData *source) const
{
    return source->hasImage() || source->hasUrls() ||
            QTextEdit::canInsertFromMimeData(source);
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "CustomTextEdit.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void initView();
    void initData();

public slots:
    void slotShowFileIcon(const QPixmap &pix);

private:
    Ui::MainWindow *ui;
    CustomTextEdit *textEdit{nullptr};
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    initView();
    initData();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::initView()
{
    ui->label->setText("");
    textEdit = new CustomTextEdit(this);
    connect(textEdit, &CustomTextEdit::signalShowIcon, this, &MainWindow::slotShowFileIcon);
    textEdit->setGeometry(QRect(10, 10, 300, 450));
    textEdit->show();
}

void MainWindow::initData()
{

}

void MainWindow::slotShowFileIcon(const QPixmap &pix)
{
    ui->label->setPixmap(pix);
}

main.cpp

#include "mainwindow.h"

#include <QApplication>

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

运行结果:

从D盘bak目录下拖拽11111.png文件到TextEdit

 复制file:///D:/bak/11111.png到TextEdit

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值