Qt实现图片拖拽上传过滤文件夹内图片自动搜索列表展示

 

1.功能实现

支持图片、或者文件夹拖拽上传,会自动获取文件夹中的图片。对拖入的文件做格式判断,不符合格式要求的会不支持拖入,拖入后展示在list列表中,可以进行删除,和上下滚动查看;

#ifndef DRAGDROPPIC_H
#define DRAGDROPPIC_H

#include <QWidget>
#include "ui_DragDropPic.h"
#include<QDragEnterEvent>
#include <QDropEvent>
#include <QMimeData>
#include<QLabel>
#include "DirPicItem.h"
#include "SearchPicThread.h"
#include "HelpButton.h"
#include "AddPicHelp.h"
class DragDropPic : public QWidget
{
    Q_OBJECT

public:
    DragDropPic(QWidget *parent = 0);
    ~DragDropPic();
    void dragEnterEvent(QDragEnterEvent *event);
    void dropEvent(QDropEvent *event);
    
    void dragLeaveEvent(QDragLeaveEvent *event);
    void AddSelectedFile(QStringList listPath);
    void wheelEvent(QWheelEvent *e);
    void ClearContont();
    void CheckIsSystemPath(QStringList& listDir);
    void resizeEvent(QResizeEvent *event);
    bool IsReady() { return m_pSearchPicThread->isRunning() ? false : true; };
    QStringList GetNoRepeatPicPath();
    int GetNoRepeatPicNum();
    void CheckLeftPicNum(bool bAlarm=false);
    public slots:
    void UpdateFileList();
    void SlotSelectPicFile();
    void SlotSearchPicFinished(QVariantMap picData);
    void SetLeftPicNum(int left) { m_leftPicNum = left; };
    void SlotShowHelpWidget(bool show);
signals:
    void SignalError(int type, QString strContent);
    void SignalUpdateLeftPicNum(int num);
private:
    Ui::DragDropPic ui;
    QStringList m_strListFilePath;
    QMap<QString, QVariant>m_mapFilePathPic;
    SearchPicThread* m_pSearchPicThread;
    int m_leftPicNum = 0;//剩余
    HelpButton* m_pHelpButton;
    AddPicHelp m_AddPicHelp;
};

#endif // DRAGDROPPIC_H

cpp文件

#include "DragDropPic.h"
#include <QFileInfo>
#include <QScrollBar>
#include "MultiFileDirDialog.h"
#include "ConfigInfo.h"
#pragma execution_character_set("utf-8")
DragDropPic::DragDropPic(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);
    ui.widgetRelease->hide();
    ui.widgetPic->hide();
    ui.listWidgetPic->verticalScrollBar()->setDisabled(true);
    connect(ui.vScrollBar, &QScrollBar::valueChanged, this, &DragDropPic::UpdateFileList);
    connect(ui.pBLibAddPic, &QPushButton::clicked, this, &DragDropPic::SlotSelectPicFile);
    m_pSearchPicThread = new SearchPicThread(this);
    connect(m_pSearchPicThread, &SearchPicThread::signalSearchPicResult, this, &DragDropPic::SlotSearchPicFinished);
    m_pHelpButton = new HelpButton(ui.widgetHelp);
    ui.horizontalLayoutHelp->addWidget(m_pHelpButton);
    connect(m_pHelpButton, &HelpButton::signalInHelpButton, this, &DragDropPic::SlotShowHelpWidget);
}

DragDropPic::~DragDropPic()
{

}
/*对拖入的图片做格式判断*/
void DragDropPic::dragEnterEvent(QDragEnterEvent *event)
{
    QStringList allowedExtensions;
    allowedExtensions << "jpg" << "jpeg" << "png" << "tiff"<<"JPG"<<"JPEG"<<"PNG"<<"TIFF";
    const QMimeData *mimeData = event->mimeData();
    int CountUnsurport = 0;
    QStringList listPath;
    if (mimeData->hasUrls())
    {
        QList<QUrl> urls = mimeData->urls();
        for (int i = 0; i < urls.size(); i++)
        {
            QString filePath = urls.at(i).toLocalFile(); // 通常只处理第一个url
            QFileInfo fileinfo(filePath);
            if (fileinfo.isDir())
            {
                listPath.push_back(filePath);
            }
            else
            {
                QString extension = fileinfo.suffix();
                if (allowedExtensions.contains(extension))
                {
                    listPath.push_back(filePath);
                }
                else
                {

                    CountUnsurport++;
                }
            }
        }
    }
    if (CountUnsurport>0)
    {
        event->ignore(); // 接受拖动
    }
    else
    {
        event->acceptProposedAction(); // 接受拖动
        ui.widget->hide();
        ui.widgetRelease->show();
        ui.widgetAddPic->setStyleSheet(QLatin1String("\n"
            "QWidget#widgetAddPic\n"
            "{\n"
            "    border: 1px dashed rgba(255, 255, 255, 0.3);\n"
            "    border-radius: 4px;\n"
            "    background:rgba(32, 128, 247, 0.16);\n"
            "}"));
    }
}

void DragDropPic::dropEvent(QDropEvent *event)
{
    // 允许的文件扩展名列表
    ui.widget->show();
    ui.widgetPic->show();
    ui.widgetRelease->hide();
    ui.widgetAddPic->setStyleSheet(QLatin1String("\n"
        "QWidget#widgetAddPic\n"
        "{\n"
        "    border: 1px dashed rgba(255, 255, 255, 0.3);\n"
        "    border-radius: 4px;\n"
        "    background: rgb(40, 40, 41);\n"
        "}"));
    QStringList allowedExtensions;
    allowedExtensions << "jpg" << "jpeg" << "png" << "tiff" << "JPG" << "JPEG" << "PNG" << "TIFF";
    const QMimeData *mimeData = event->mimeData();
    int CountUnsurport = 0;
    QStringList listPath;
    if (mimeData->hasUrls()) 
    {
        QList<QUrl> urls = mimeData->urls();
        for (int i = 0; i < urls.size(); i++)
        {
            QString filePath = urls.at(i).toLocalFile(); // 通常只处理第一个url
            QFileInfo fileinfo(filePath);
            if (fileinfo.isDir())
            {
                listPath.push_back(filePath);
            }
            else
            {
                QString extension = fileinfo.suffix();
                if (allowedExtensions.contains(extension))
                {
                    listPath.push_back(filePath);
                }
                else
                {
                    
                    CountUnsurport++;
                }
            }
        }
    }
    if (CountUnsurport>0)
    {
        emit SignalError(-3, QString("有%1个文件不符合格式要求").arg(CountUnsurport));
        return;
    }
    AddSelectedFile(listPath);
}

void DragDropPic::dragLeaveEvent(QDragLeaveEvent *event)
{
    ui.widget->show();
    ui.widgetRelease->hide();
    ui.widgetAddPic->setStyleSheet(QLatin1String("\n"
        "QWidget#widgetAddPic\n"
        "{\n"
        "    border: 1px dashed rgba(255, 255, 255, 0.3);\n"
        "    border-radius: 4px;\n"
        "    background: rgb(40, 40, 41);\n"
        "}"));
}

void DragDropPic::AddSelectedFile(QStringList listPath)
{
    QStringList listDir;
    for (int i=0;i<listPath.size();i++)
    {
        //去除重复
        if (m_mapFilePathPic.find(listPath[i])== m_mapFilePathPic.end())
        {
            m_strListFilePath.push_back(listPath[i]);
            QFileInfo info(listPath[i]);
            if (info.isDir())
            {
                listDir.append(listPath[i]);
                QStringList listpic;
                m_mapFilePathPic.insert(listPath[i] , listpic);
            }
            else
            {
                m_mapFilePathPic.insert(listPath[i], "");
            }    
        }
    }
    if (listDir.size()>0)
    {
        m_pSearchPicThread->StartSearchPic(listDir);//用线程搜索文件夹中的图片
    }
    UpdateFileList();
    CheckLeftPicNum(true);
}
//滚轮滚动时,列表也跟着滚动
void DragDropPic::wheelEvent(QWheelEvent *e)
{
    int max = ui.vScrollBar->maximum();
    int current = ui.vScrollBar->value();
    if (ui.listWidgetPic->underMouse())
    {
        if (e->delta()<0)
        {
            current++;
            if (current>max)
            {
                current = max;
            }
        }
        else
        {
            current--;
            if (current<0)
            {
                current = 0;
            }
        }
        ui.vScrollBar->setValue(current);
    }
}

void DragDropPic::ClearContont()
{
    ui.listWidgetPic->clear();
    m_mapFilePathPic.clear();
    m_strListFilePath.clear();
    ui.vScrollBar->setValue(0);
    ui.widgetPic->hide();
}

void DragDropPic::UpdateFileList()
{
    
    int total = m_strListFilePath.size();
    if (total > 0)
    {
        ui.widgetPic->show();
    }
    else
    {
        ui.widgetPic->hide();
    }
    int pagesize = ui.listWidgetPic->height() / 28;
    if (total>pagesize)
    {
        ui.vScrollBar->setMaximum(total-pagesize);
        ui.vScrollBar->show();
    }
    else
    {
        ui.vScrollBar->setMaximum(0);
        ui.vScrollBar->hide();
    }
    int current = ui.vScrollBar->value();
    int listsize = ui.listWidgetPic->count();
    DirPicItem* pDirPicItem = NULL;
    QListWidgetItem* pItem=NULL;
    if (total <= pagesize)//总数不足一页
    {
        if (listsize>=total)//列表中已有大于总数
        {
            //回收多余的item
            for (int s = total; s < listsize; s++)
            {
                pItem = (QListWidgetItem*)ui.listWidgetPic->takeItem(0);//会删除掉set上去的item
                if (pItem)
                {
                    pDirPicItem = (DirPicItem*)ui.listWidgetPic->itemWidget(pItem);
                    if (pDirPicItem)
                    {
                        delete pDirPicItem;
                        pDirPicItem = NULL;
                    }
                    delete pItem;
                    pItem = NULL;
                }
            }
        }
        else//已有少于总数插入不足
        {
            for (int s = listsize; s < total; s++)
            {
                pItem = new QListWidgetItem(ui.listWidgetPic);
                pDirPicItem = new DirPicItem(ui.listWidgetPic);
                connect(pDirPicItem->ui.pBClose, &QPushButton::clicked, this, [=] {
                    QString strFilePath = pDirPicItem->GetDirFile();
                    m_mapFilePathPic.remove(strFilePath);
                    for (int i = 0; i < m_strListFilePath.size(); i++)
                    {
                        if (m_strListFilePath[i] == strFilePath)
                        {
                            m_strListFilePath.removeAt(i);
                            break;
                        }
                    }
                    UpdateFileList();
                    CheckLeftPicNum();
                });
                ui.listWidgetPic->addItem(pItem);
                ui.listWidgetPic->setItemWidget(pItem,pDirPicItem);
            }    
        }
    }
    else//总数大于一页
    {
        if (listsize< pagesize)
        {
            for (int s = listsize; s < pagesize; s++)
            {
                pItem = new QListWidgetItem(ui.listWidgetPic);
                pDirPicItem = new DirPicItem(ui.listWidgetPic);
                connect(pDirPicItem->ui.pBClose, &QPushButton::clicked, this, [=] {
                    QString strFilePath = pDirPicItem->GetDirFile();
                    m_mapFilePathPic.remove(strFilePath);
                    for (int i=0;i<m_strListFilePath.size();i++)
                    {
                        if (m_strListFilePath[i]==strFilePath)
                        {
                            m_strListFilePath.removeAt(i);
                            break;
                        }
                    }
                    UpdateFileList();
                    CheckLeftPicNum();
                });
                ui.listWidgetPic->addItem(pItem);
                ui.listWidgetPic->setItemWidget(pItem, pDirPicItem);
            }
        }
    }
    listsize = ui.listWidgetPic->count();
    for (int i= current,count=0;i<total&& count<listsize;i++, count++)
    {
        pItem = (QListWidgetItem*)(ui.listWidgetPic->item(count));
        if (pItem)
        {
            pDirPicItem = (DirPicItem*)ui.listWidgetPic->itemWidget(pItem);//会删除掉set上去的item
            if (pDirPicItem)
            {
                pDirPicItem->SetDirFile(m_strListFilePath[i]);
                QFileInfo info(m_strListFilePath[i]);
                if (info.isDir())
                {
                    if (m_mapFilePathPic.find(m_strListFilePath[i])!=m_mapFilePathPic.end())
                    {
                        QStringList listpic = m_mapFilePathPic[m_strListFilePath[i]].toStringList();
                        if (listpic.size()>0)
                        {
                            pDirPicItem->SetDirPicNum(listpic.size());
                        }
                    }
                }
            }
        }
        
    }
}

void DragDropPic::SlotSelectPicFile()
{
    MultiFileDirDialog fileDialog(NULL);
    fileDialog.setWindowTitle("选择文件夹或图片");
    fileDialog.setOption(QFileDialog::ShowDirsOnly, false);
    fileDialog.setNameFilter("vedio(*.jpg *.jpeg *.png *.tiff *.JPG *.JPEG *.PNG *.TIFF)");

    if (fileDialog.exec() == QDialog::Accepted)
    {
        QStringList selectFiles = fileDialog.selectedFiles();
        if (selectFiles.size() > 0)
        {
            CheckIsSystemPath(selectFiles);
            //CheckIsNameTooLong(selectFiles);
            if (selectFiles.size() > 0)
            {
                AddSelectedFile(selectFiles);
            }
        }
    }
}

void DragDropPic::SlotSearchPicFinished(QVariantMap picData)
{
    for (auto it = picData.begin(); it!= picData.end(); it++)
    {
        if (m_mapFilePathPic.find(it.key())!=m_mapFilePathPic.end())
        {
            m_mapFilePathPic.insert(it.key(), it.value());
        }
    }
    UpdateFileList();
    CheckLeftPicNum(true);
}

void DragDropPic::SlotShowHelpWidget(bool show)
{
    if (show)
    {
        m_AddPicHelp.show();
        QPoint ppint =QCursor::pos();
        m_AddPicHelp.move(ppint.x() - 30, ppint.y() + 20);
    }
    else
    {
        m_AddPicHelp.hide();
    }
}

void DragDropPic::resizeEvent(QResizeEvent *event)
{
    UpdateFileList();
}

QStringList DragDropPic::GetNoRepeatPicPath()
{
    QStringList listpic;
    QMap<QString, QString> mapPic;
    for (auto it=m_mapFilePathPic.begin();it!=m_mapFilePathPic.end();it++)
    {
        QFileInfo info(it.key());
        if (info.isDir())
        {
            QStringList Items = it.value().toStringList();
            for (int i = 0; i < Items.size(); i++)
            {
                mapPic.insert(Items[i], Items[i]);
            }
        }
        else
        {
            mapPic.insert(it.key(), it.key());
        }
    }
    listpic = mapPic.keys();
    return listpic;
}
//获取不重复图片数量
int DragDropPic::GetNoRepeatPicNum()
{
    QMap<QString, QString> mapPic;
    for (auto it = m_mapFilePathPic.begin(); it != m_mapFilePathPic.end(); it++)
    {
        QFileInfo info(it.key());
        if (info.isDir())
        {
            QStringList Items = it.value().toStringList();
            for (int i = 0; i < Items.size(); i++)
            {
                mapPic.insert(Items[i], Items[i]);
            }
        }
        else
        {
            mapPic.insert(it.key(), it.key());
        }
    }
    return mapPic.size();
}
//判断图片数量是否超出上限
void DragDropPic::CheckLeftPicNum(bool bAlarm)
{
    int selectNum = GetNoRepeatPicNum();
    emit SignalUpdateLeftPicNum(m_leftPicNum - selectNum);
    if (m_leftPicNum== selectNum)
    {
        if (bAlarm)
        {
            emit SignalError(-3, QString("选择的图片数量已满上限%1").arg(CConfig::instance()->GetLibPeopleLimit()));
        }
        
    }
    else if (m_leftPicNum<selectNum)
    {
        if (bAlarm)
        {
            emit SignalError(-3, QString("选择的图片数量超过上限%1,超出%2张").arg(CConfig::instance()->GetLibPeopleLimit()).arg(selectNum-m_leftPicNum));
        }
        
    }
}


//判断是否系统盘
void DragDropPic::CheckIsSystemPath(QStringList& listDir)
{
    QStringList filelist;
    int count = 0;
    QString strError = "";
#ifdef WIN32
    for (int i = 0; i < listDir.size(); i++)
    {
        if (listDir[i].length() <= 3)
        {
            count++;
        }
        else
        {
            filelist.append(listDir[i]);
        }
    }
    strError = "不能选择系统盘,请创建一个文件夹";
#else
    for (int i = 0; i < listDir.size(); i++)
    {
        if (listDir[i].length() <= 1)
        {
            count++;
        }
        else
        {
            filelist.append(listDir[i]);
        }
    }
    strError = "不能选择根目录,请创建一个文件夹";
#endif
    if (count > 0)
    {
        emit SignalError(-1, strError);
    }
    listDir = filelist;
}

遍历查找文件夹中图片的线程

头文件

#ifndef SEARCHPICTHREAD_H
#define SEARCHPICTHREAD_H

#include <QThread>
#include<QMap>
#include <QVariant>
#include<QVariantMap>
class SearchPicThread : public QThread
{
    Q_OBJECT

public:
    SearchPicThread(QObject *parent);
    ~SearchPicThread();
    void StartSearchPic(QStringList  list);
    void run();
    void stopSearch() { m_stoped = true; };
    void RecursiveInputDirFiles(QString strDir, QStringList& listPic);
signals:
    void signalSearchPicResult(QVariantMap picData);
private:
    QStringList m_listDir;
    bool m_stoped = false;
};

#endif // SEARCHPICTHREAD_H

cpp文件

#include "SearchPicThread.h"
#include <QDir>

SearchPicThread::SearchPicThread(QObject *parent)
    : QThread(parent)
{

}

SearchPicThread::~SearchPicThread()
{

}

void SearchPicThread::StartSearchPic(QStringList list)
{
    m_listDir.append(list);
    if (this->isRunning()==false)
    {
        m_stoped = false;
        start();
    }
}

void SearchPicThread::run()
{
    QVariantMap mappic;
    while (m_listDir.size()>0)
    {
        if (m_stoped == true)//退出
        {
            break;
        }
        QString strDir = m_listDir.front();
        m_listDir.pop_front();
        QStringList listPic;
        RecursiveInputDirFiles(strDir, listPic);
        mappic.insert(strDir, listPic);
    }
    emit signalSearchPicResult(mappic);

}

void SearchPicThread::RecursiveInputDirFiles(QString strDir, QStringList& listPic)
{
    QDir dirFile(strDir);
    QDir dirDir(strDir);
    if (!dirDir.exists())
    {
        return;
    }
    dirFile.setSorting(QDir::Time);//优先显示目录
    dirDir.setSorting(QDir::Time);

    //列出dir(path)目录文件下所有文件和目录信息,存储到file_list容器
    QStringList fileNameFilter;
    //视频格式
    fileNameFilter << "*.jpg" << "*.jpeg" << "*.png" << "*.tiff";
    dirFile.setNameFilters(fileNameFilter);
    QFileInfoList file_list = dirFile.entryInfoList(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
    //列出dir(path)目录下所有子文件夹
    QFileInfoList folder_list = dirDir.entryInfoList(QDir::Dirs | QDir::Hidden | QDir::NoDotAndDotDot);
    if (file_list.size() == 0 && folder_list.size() == 0)
    {
        return;
    }
    //添加视频文件到列表
    QString strfilepath = "";
    for (int i = 0; i < file_list.size(); i++)
    {
        strfilepath = file_list[i].absoluteFilePath();
        listPic.append(strfilepath);
    }

    //进行子文件夹folder_list递归遍历,将内容存入file_list容器
    for (int i = 0; i != folder_list.size(); i++)
    {
        RecursiveInputDirFiles(folder_list.at(i).absoluteFilePath(), listPic);
    }
}

 

posted @ 2024-07-24 11:34  一字千金  阅读(13)  评论(0编辑  收藏  举报