mirror of https://gitee.com/openkylin/peony.git
Hotfix bug#112062 删除一万个文件到回收站,文件管理器卡死,但删除成功
This commit is contained in:
parent
dc6d3db08d
commit
ffd91b64ab
|
@ -50,15 +50,18 @@
|
|||
|
||||
using namespace Peony;
|
||||
|
||||
static const int maxNumberOfDeletesByOne = 30; /* 按个删除最大数量 */
|
||||
static const int maxNumberOfDeletesPerBatch = 1000; /* 每次批量最多删除数量 */
|
||||
|
||||
QString uri2FavoriteUri(const QString &sourceUri)
|
||||
{
|
||||
QUrl url = sourceUri;
|
||||
QString favoriteUri = "favorite://" + url.path() + "?schema=" + url.scheme();
|
||||
return favoriteUri;
|
||||
}
|
||||
|
||||
FileItem::FileItem(std::shared_ptr<Peony::FileInfo> info, FileItem *parentItem, FileItemModel *model, QObject *parent) : QObject(parent)
|
||||
{
|
||||
qRegisterMetaType<QVector<FileItem*>* >("QVector<FileItem*>*");
|
||||
m_parent = parentItem;
|
||||
m_info = info;
|
||||
m_children = new QVector<FileItem*>();
|
||||
|
@ -67,10 +70,12 @@ FileItem::FileItem(std::shared_ptr<Peony::FileInfo> info, FileItem *parentItem,
|
|||
|
||||
m_backend_enumerator = new FileEnumerator(this);
|
||||
|
||||
m_batchProcessThread = new QThread();
|
||||
|
||||
m_idle = new QTimer(this);
|
||||
m_idle->setInterval(0);
|
||||
m_idle->setInterval(30);
|
||||
m_idle->setSingleShot(true);
|
||||
connect(m_idle, &QTimer::timeout, this, [=]{
|
||||
connect(m_idle, &QTimer::timeout, this, [=](){
|
||||
for (auto uri : m_waiting_update_queue) {
|
||||
auto infoJob = new FileInfoJob(FileInfo::fromUri(uri));
|
||||
infoJob->setAutoDelete();
|
||||
|
@ -86,13 +91,12 @@ FileItem::FileItem(std::shared_ptr<Peony::FileInfo> info, FileItem *parentItem,
|
|||
});
|
||||
infoJob->queryAsync();
|
||||
}
|
||||
|
||||
if (m_uris_to_be_removed.isEmpty())
|
||||
return;
|
||||
|
||||
QStringList favoriteUris;
|
||||
|
||||
if (m_uris_to_be_removed.count() < 10) {
|
||||
if (m_uris_to_be_removed.count() < maxNumberOfDeletesByOne) {
|
||||
// do normal remove
|
||||
for (auto uri : m_uris_to_be_removed) {
|
||||
for (int row = 0; row < m_children->count(); row++) {
|
||||
|
@ -105,9 +109,10 @@ FileItem::FileItem(std::shared_ptr<Peony::FileInfo> info, FileItem *parentItem,
|
|||
favoriteUris.append(uri2FavoriteUri(uri));
|
||||
}
|
||||
m_model->beginRemoveRows(this->firstColumnIndex(), row, row);
|
||||
m_uris_to_be_removed.removeOne(uri);
|
||||
m_children->remove(row);
|
||||
delete child;
|
||||
m_model->endRemoveRows();
|
||||
delete child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -117,32 +122,8 @@ FileItem::FileItem(std::shared_ptr<Peony::FileInfo> info, FileItem *parentItem,
|
|||
}
|
||||
|
||||
// do reset model
|
||||
batchRemoveItems();
|
||||
|
||||
int time0 = QTime::currentTime().msecsSinceStartOfDay();
|
||||
qDebug()<<"execute deletion";
|
||||
m_model->beginResetModel();
|
||||
qDebug()<<"files deleted"<<m_uris_to_be_removed.count();
|
||||
for (auto uri : m_uris_to_be_removed) {
|
||||
for (int row = 0; row < m_children->count(); row++) {
|
||||
auto child = m_children->at(row);
|
||||
// 此处实际可靠性还有待验证
|
||||
if (FileUtils::isSamePath(uri, child->uri())) {
|
||||
auto info = child->m_info;
|
||||
if (info->isDir())
|
||||
{
|
||||
favoriteUris.append(uri2FavoriteUri(uri));
|
||||
}
|
||||
m_children->remove(row);
|
||||
delete child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_model->endResetModel();
|
||||
BookMarkManager::getInstance()->removeBookMark(favoriteUris);
|
||||
int time1 = QTime::currentTime().msecsSinceStartOfDay();
|
||||
qDebug()<<"excute deletion finished, cost"<<time1 - time0;
|
||||
//ThumbnailManager::getInstance()->releaseThumbnail(m_uris_to_be_removed);
|
||||
});
|
||||
|
||||
m_thumbnail_watcher = std::make_shared<Peony::FileWatcher>("thumbnail://");
|
||||
|
@ -561,7 +542,8 @@ FileItem *FileItem::getChildFromUri(QString uri)
|
|||
|
||||
void FileItem::onChildAdded(const QString &uri)
|
||||
{
|
||||
m_uris_to_be_removed.removeOne(uri);
|
||||
if(m_uris_to_be_removed.contains(uri))
|
||||
m_uris_to_be_removed.removeOne(uri);
|
||||
|
||||
qDebug()<<"add child:" << uri;
|
||||
FileItem *child = getChildFromUri(uri);
|
||||
|
@ -791,6 +773,56 @@ void FileItem::removeChildren()
|
|||
|
||||
}
|
||||
|
||||
void FileItem::batchRemoveItems()
|
||||
{
|
||||
/* 批量+异步方式解决大量数据删除时卡顿界面问题,link to bug#112062 删除一万个文件到回收站,文件管理器卡死,但删除成功 */
|
||||
if(!m_batchProcessThread->isRunning()){
|
||||
QStringList list;
|
||||
if(m_uris_to_be_removed.size() >= maxNumberOfDeletesPerBatch){/* 每次批量最多删除数量 */
|
||||
for(int i = 0; i < maxNumberOfDeletesPerBatch; i++){
|
||||
QString uri = m_uris_to_be_removed.at(0);
|
||||
list.append(uri);
|
||||
m_uris_to_be_removed.removeOne(uri);
|
||||
}
|
||||
}else{
|
||||
list = m_uris_to_be_removed;
|
||||
m_uris_to_be_removed.clear();
|
||||
}
|
||||
|
||||
QHash<QString, FileItem*> uri_item_hash;
|
||||
for(auto entry: *m_children){
|
||||
uri_item_hash.insert(entry->uri(), entry);
|
||||
}
|
||||
|
||||
m_batchProcessItems = new BatchProcessItems();
|
||||
m_batchProcessItems->setBatchRemoveParam(list, uri_item_hash, m_children);
|
||||
m_batchProcessItems->moveToThread(m_batchProcessThread);
|
||||
connect(m_batchProcessThread, &QThread::started, m_batchProcessItems, &BatchProcessItems::slot_removeItems);
|
||||
connect(m_batchProcessItems, &BatchProcessItems::removeItemsFinished, this, [=](QVector<FileItem*> *children){
|
||||
m_children = children;
|
||||
m_model->updated();/* 更新状态栏 */
|
||||
qDebug()<<"remove items finished,children count:"<<m_children->size();
|
||||
|
||||
if(m_uris_to_be_removed.size() <= maxNumberOfDeletesByOne){
|
||||
m_model->beginResetModel();
|
||||
m_model->endResetModel();
|
||||
}
|
||||
|
||||
m_batchProcessThread->quit();
|
||||
if(m_batchProcessItems){
|
||||
delete m_batchProcessItems;
|
||||
m_batchProcessItems = nullptr;
|
||||
}
|
||||
|
||||
if (m_uris_to_be_removed.size()>0 && !m_idle->isActive()) {
|
||||
m_idle->start();
|
||||
}
|
||||
|
||||
});
|
||||
m_batchProcessThread->start();
|
||||
}
|
||||
}
|
||||
|
||||
void FileItem::clearChildren()
|
||||
{
|
||||
auto parent = firstColumnIndex();
|
||||
|
@ -835,3 +867,46 @@ bool FileItem::shouldShow()
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
BatchProcessItems::BatchProcessItems()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BatchProcessItems::~BatchProcessItems()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void BatchProcessItems::setBatchRemoveParam(QStringList uris_to_be_removed, QHash<QString, FileItem*> uri_item_hash, QVector<FileItem*> *children)
|
||||
{
|
||||
m_uris_to_be_removed = uris_to_be_removed;
|
||||
m_uri_item_hash = uri_item_hash;
|
||||
m_children = children;
|
||||
}
|
||||
|
||||
void BatchProcessItems::slot_removeItems()
|
||||
{
|
||||
// do reset model
|
||||
int time0 = QTime::currentTime().msecsSinceStartOfDay();
|
||||
QStringList favoriteUris;
|
||||
qDebug()<<"execute deletion, deleted count:"<<m_uris_to_be_removed.count()<<"uri item hash count:"<<m_uri_item_hash.size();
|
||||
for (auto& uri : m_uris_to_be_removed) {
|
||||
if(m_uri_item_hash.contains(uri)){
|
||||
auto child = m_uri_item_hash[uri];
|
||||
auto info = child->info();
|
||||
if (info && info->isDir())
|
||||
{
|
||||
favoriteUris.append(uri2FavoriteUri(uri));
|
||||
}
|
||||
int i = m_uri_item_hash.remove(uri);
|
||||
m_uris_to_be_removed.removeOne(uri);
|
||||
m_children->removeOne(child);
|
||||
delete child;
|
||||
}
|
||||
}
|
||||
BookMarkManager::getInstance()->removeBookMark(favoriteUris);
|
||||
Q_EMIT removeItemsFinished(m_children);
|
||||
int time1 = QTime::currentTime().msecsSinceStartOfDay();
|
||||
qDebug()<<"excute deletion finished, cost"<<time1 - time0<<"uris to be removed remaining count:"<<m_uris_to_be_removed.size()<<"children remaining count:"<<m_children->size();
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
|
||||
#include <QHash>
|
||||
class QTimer;
|
||||
|
||||
namespace Peony {
|
||||
|
@ -39,6 +39,7 @@ class FileItemModel;
|
|||
class FileWatcher;
|
||||
class FileItemProxyFilterSortModel;
|
||||
class FileEnumerator;
|
||||
class BatchProcessItems;
|
||||
|
||||
/*!
|
||||
* \brief The FileItem class
|
||||
|
@ -145,6 +146,7 @@ protected:
|
|||
void updateInfoAsync();
|
||||
|
||||
void removeChildren();
|
||||
void batchRemoveItems();
|
||||
|
||||
private:
|
||||
FileItem *m_parent = nullptr;
|
||||
|
@ -164,7 +166,8 @@ private:
|
|||
|
||||
QStringList m_uris_to_be_removed;
|
||||
QTimer *m_idle = nullptr;
|
||||
|
||||
QThread *m_batchProcessThread = nullptr;
|
||||
BatchProcessItems *m_batchProcessItems = nullptr;
|
||||
|
||||
/*!
|
||||
* \brief m_async_count
|
||||
|
@ -184,6 +187,29 @@ private:
|
|||
FileEnumerator *m_backend_enumerator;
|
||||
};
|
||||
|
||||
|
||||
class BatchProcessItems: public QObject{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BatchProcessItems();
|
||||
~BatchProcessItems();
|
||||
|
||||
void setBatchRemoveParam(QStringList uris_to_be_removed, QHash<QString, FileItem*> uri_item_hash, QVector<FileItem*> *children);
|
||||
|
||||
Q_SIGNALS:
|
||||
void removeItemsFinished(QVector<FileItem*> *children);
|
||||
|
||||
|
||||
public Q_SLOTS:
|
||||
void slot_removeItems();
|
||||
|
||||
private:
|
||||
QStringList m_uris_to_be_removed;
|
||||
QHash<QString, FileItem*> m_uri_item_hash;
|
||||
QVector<FileItem*> *m_children = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FILEITEM_H
|
||||
|
|
Loading…
Reference in New Issue