Переместить файлы в корзину / корзину в Qt

Есть ли функция Qt для перемещения файлов в корзину вместо того, чтобы действительно удалять их, для ОС, которые его поддерживают, или мне нужно использовать специфичный для ОС код?

14

Решение

API пока нет.

https://bugreports.qt.io/browse/QTBUG-181

Проблема закрыта, и версия исправления: Некоторый будущий выпуск

Редактировать: Новый выпуск был открыт на https://bugreports.qt.io/browse/QTBUG-47703.

3

Другие решения

Qt не предоставляет MoveToTrash. Вот часть моего кода

для Windows

#ifdef Q_OS_WIN32

#include "windows.h"
void MoveToTrashImpl( QString file ){
QFileInfo fileinfo( file );
if( !fileinfo.exists() )
throw OdtCore::Exception( "File doesnt exists, cant move to trash" );
WCHAR from[ MAX_PATH ];
memset( from, 0, sizeof( from ));
int l = fileinfo.absoluteFilePath().toWCharArray( from );
Q_ASSERT( 0 <= l && l < MAX_PATH );
from[ l ] = '\0';
SHFILEOPSTRUCT fileop;
memset( &fileop, 0, sizeof( fileop ) );
fileop.wFunc = FO_DELETE;
fileop.pFrom = from;
fileop.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;
int rv = SHFileOperation( &fileop );
if( 0 != rv ){
qDebug() << rv << QString::number( rv ).toInt( 0, 8 );
throw OdtCore::Exception( "move to trash failed" );
}
}
#endif

и для Linux

#ifdef Q_OS_LINUX

bool TrashInitialized = false;
QString TrashPath;
QString TrashPathInfo;
QString TrashPathFiles;

void MoveToTrashImpl( QString file ){
#ifdef QT_GUI_LIB
if( !TrashInitialized ){
QStringList paths;
const char* xdg_data_home = getenv( "XDG_DATA_HOME" );
if( xdg_data_home ){
qDebug() << "XDG_DATA_HOME not yet tested";
QString xdgTrash( xdg_data_home );
paths.append( xdgTrash + "/Trash" );
}
QString home = QStandardPaths::writableLocation( QStandardPaths::HomeLocation );
paths.append( home + "/.local/share/Trash" );
paths.append( home + "/.trash" );
foreach( QString path, paths ){
if( TrashPath.isEmpty() ){
QDir dir( path );
if( dir.exists() ){
TrashPath = path;
}
}
}
if( TrashPath.isEmpty() )
throw Exception( "Cant detect trash folder" );
TrashPathInfo = TrashPath + "/info";
TrashPathFiles = TrashPath + "/files";
if( !QDir( TrashPathInfo ).exists() || !QDir( TrashPathFiles ).exists() )
throw Exception( "Trash doesnt looks like FreeDesktop.org Trash specification" );
TrashInitialized = true;
}
QFileInfo original( file );
if( !original.exists() )
throw Exception( "File doesnt exists, cant move to trash" );
QString info;
info += "[Trash Info]\nPath=";
info += original.absoluteFilePath();
info += "\nDeletionDate=";
info += QDateTime::currentDateTime().toString("yyyy-MM-ddThh:mm:ss.zzzZ");
info += "\n";
QString trashname = original.fileName();
QString infopath = TrashPathInfo + "/" + trashname + ".trashinfo";
QString filepath = TrashPathFiles + "/" + trashname;
int nr = 1;
while( QFileInfo( infopath ).exists() || QFileInfo( filepath ).exists() ){
nr++;
trashname = original.baseName() + "." + QString::number( nr );
if( !original.completeSuffix().isEmpty() ){
trashname += QString( "." ) + original.completeSuffix();
}
infopath = TrashPathInfo + "/" + trashname + ".trashinfo";
filepath = TrashPathFiles + "/" + trashname;
}
QDir dir;
if( !dir.rename( original.absoluteFilePath(), filepath ) ){
throw Exception( "move to trash failed" );
}
File infofile;
infofile.createUtf8( infopath, info );
#else
Q_UNUSED( file );
throw Exception( "Trash in server-mode not supported" );
#endif
}
#endif
6

Я думаю, что нет кроссплатформенного пути. Простое перемещение файлов в «мусорную корзину» не даст эффекта, потому что пользователь может отключить эту возможность.

Может быть, этот URL поможет: http://www.hardcoded.net/articles/send-files-to-trash-on-all-platforms.htm

3

Я относительно уверен, что не существует API Qt, который оборачивает это для всех поддерживаемых платформ. К сожалению, это означает, что вам придется писать код для конкретной платформы.

Я ничего не знаю о том, где и как дистрибутивы Linux хранят удаленные файлы, и я предполагаю, что это, вероятно, зависит от того, какой файловый менеджер вы используете. Я считаю, что перемещение файлов в ~/.Trash папка является стандартным способом сделать это, но я не уверен, что это надежно. Например, в случае файлов, хранящихся на внешних томах.

В Mac OS X все немного проще, и для этого есть поддерживаемый API: FSMoveObjectToTrashSync, предоставляемых Core Services. По крайней мере, я так помню, ты должен это делать. Документация утверждает, что этот метод в настоящее время устарел в OS X 10.8. Я понятия не имею, что является рекомендуемой альтернативой.

Как программист Windows, я думаю, что эта платформа намного проще. 🙂 Основным решением является вызов SHFileOperation функция:

#include <Windows.h>   // general Windows header file
#include <ShellAPI.h>  // for shell functions, like SHFileOperation
#include <string>      // (or use QString)

void RecycleFileOnWindows()
{
std::wstring path = L"C:\\Users\\Administrator\\Documents\\deleteme.txt";
path.append(1, L'\0');        // path string must be double nul-terminated

SHFILEOPSTRUCT shfos = {};
shfos.hwnd   = nullptr;       // handle to window that will own generated windows, if applicable
shfos.wFunc  = FO_DELETE;
shfos.pFrom  = path.c_str();
shfos.pTo    = nullptr;       // not used for deletion operations
shfos.fFlags = FOF_ALLOWUNDO; // use the recycle bin

const int retVal = SHFileOperation(&shfos);
if (retVal != 0)
{
// The operation failed...
if (shfos.fAnyOperationsAborted)
{
// ...but that's because the user canceled.
MessageBox(nullptr, L"Operation was canceled", nullptr, MB_OK | MB_ICONINFORMATION);
}
else
{
// ...for one of the other reasons given in the documentation.
MessageBox(nullptr, L"Operation failed", nullptr, MB_OK | MB_ICONERROR);
}
}
}

Есть также флаги, которые вы можете установить, чтобы настроить подтверждение, отчеты об ошибках и другое поведение. Связанная документация содержит все детали, необходимые для построения этого базового примера.

В Windows Vista и более поздних SHFileOperation функция была заменена методами, предоставленными IFileOperation интерфейс. Если вы ориентируетесь только на эти более поздние версии Windows, вам следует использовать этот интерфейс. Иначе, SHFileOperation продолжит работать нормально.

3
if(QSysInfo::kernelType()=="linux")
{
QDateTime currentTime(QDateTime::currentDateTime());    // save System time

QString trashFilePath=QDir::homePath()+"/.local/share/Trash/files/";    // trash file path contain delete files
QString trashInfoPath=QDir::homePath()+"/.local/share/Trash/info/";     // trash info path contain delete files information

// create file format for trash info file----- START
QFile infoFile(trashInfoPath+FileName.completeBaseName()+"."+FileName.completeSuffix()+".trashinfo");     //filename+extension+.trashinfo //  create file information file in /.local/share/Trash/info/ folder

infoFile.open(QIODevice::ReadWrite);

QTextStream stream(&infoFile);         // for write data on open file

stream<<"[Trash Info]"<<endl;
stream<<"Path="+QString(QUrl::toPercentEncoding(FileName.absoluteFilePath(),"~_-./"))<<endl;     // convert path string in percentage decoding scheme string
stream<<"DeletionDate="+currentTime.toString("yyyy-MM-dd")+"T"+currentTime.toString("hh:mm:ss")<<endl;      // get date and time format YYYY-MM-DDThh:mm:ss

infoFile.close();

// create info file format of trash file----- END

QDir file;
file.rename(FileName.absoluteFilePath(),trashFilePath+FileName.completeBaseName()+"."+FileName.completeSuffix());  // rename(file old path, file trash path)}
1

Мусорные файлы в Linux существуют /home/user_name/.local/share/Trash/files/ каталог, но он также требует информационный файл для каждого файла корзины, которые существуют в /home/user_name/.local/share/Trash/info/ каталог. когда мы хотим переместить файл в корзину, на самом деле переместить файл в /home/user_name/.local/share/Trash/files/ каталог и создать информационный файл в /home/user_name/.local/share/Trash/info/ каталог. внутри .trashinfo Формат использует процентную схему декодирования для задания пути к файлу, в котором файл существует, в информационном файле также указывается время и дата удаления.

1
По вопросам рекламы [email protected]