Commit f23c311a authored by Nicolás Alvarez's avatar Nicolás Alvarez Committed by Michael Palimaka

Delete kio_trash as it was moved to kio.git.

parent c09ff961
......@@ -115,7 +115,6 @@ if(Phonon4Qt5_FOUND)
endif()
add_subdirectory( info )
add_subdirectory( archive )
add_subdirectory( trash )
if(NOT WIN32)
add_subdirectory( network )
endif()
......
# find_package(Strigi)
# set_package_properties(Strigi PROPERTIES DESCRIPTION "Desktop indexing and search support"
# URL "http://strigi.sourceforge.net"
# TYPE ${STRIGI_TYPE}
# )
# if (WIN32)
# set (STRIGI_TYPE "OPTIONAL")
# else ()
# set (STRIGI_TYPE "REQUIRED")
# endif ()
add_definitions(-DTRANSLATION_DOMAIN=\"kio_trash\")
add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0)
add_subdirectory(tests)
set (trashcommon_PART_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/trashimpl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/discspaceutil.cpp
${CMAKE_CURRENT_SOURCE_DIR}/trashsizecache.cpp
${CMAKE_CURRENT_SOURCE_DIR}/kinterprocesslock.cpp
)
########### next target ###############
if(WIN32)
set(kio_trash_PART_SRCS kio_trash_win.cpp kio_trash_win.h)
else()
set(kio_trash_PART_SRCS kio_trash.cpp ${trashcommon_PART_SRCS})
endif()
add_library(kio_trash MODULE ${kio_trash_PART_SRCS})
target_link_libraries(kio_trash
KF5::Solid
KF5::KDE4Support
KF5::KIOCore
Qt5::DBus
KF5::I18n KF5::ConfigCore KF5::ConfigGui
)
install(TARGETS kio_trash DESTINATION ${PLUGIN_INSTALL_DIR} )
set(ktrash_SRCS ktrash.cpp )
add_executable(ktrash5 ${ktrash_SRCS})
target_compile_definitions(ktrash5 PRIVATE -DPROJECT_VERSION="${PROJECT_VERSION}")
ecm_mark_nongui_executable(ktrash5)
target_link_libraries(ktrash5
KF5::KDE4Support
KF5::KIOCore
KF5::I18n KF5::ConfigCore KF5::ConfigGui
)
install(TARGETS ktrash5 ${INSTALL_TARGETS_DEFAULT_ARGS})
########### next target ###############
# currently not on win32, TODO!
if(NOT WIN32)
set(kcm_trash_PART_SRCS kcmtrash.cpp ${trashcommon_PART_SRCS})
add_library(kcm_trash MODULE ${kcm_trash_PART_SRCS})
target_link_libraries(kcm_trash Qt5::DBus KF5::KDE4Support
${KDECLARATIVE_LIBRARIES} KF5::I18n KF5::ConfigWidgets KF5::KIOCore KF5::Solid)
install(TARGETS kcm_trash DESTINATION ${PLUGIN_INSTALL_DIR})
endif()
########### install files ###############
install( FILES trash.protocol DESTINATION ${SERVICES_INSTALL_DIR} )
install( FILES kcmtrash.desktop DESTINATION ${SERVICES_INSTALL_DIR} )
DESIGN
======
kio_trash implements the XDG trash standard currently at http://www.ramendik.ru/docs/trashspec.html
The concurrency that comes from having multiple kioslaves running at the same time
on top of the same set of files, is solved by the KInterProcessLock class, which
synchronizes access to shared resources (like the file storing the size of the
trash directory).
BUGS
====
* Undo of "restore" isn't available. Need to get origPath by metadata I guess.
TODO
====
* Clean up konq_popupmenu.cc for Type=Link URL=trash:/ :(
* Also, provide metainfo for trash contents for that desktop link.
=> maybe we need a new mimetype?
Like application/x-trash-desktop, inheriting application/x-desktop.
And a "trash.trashdesktop" filename or so (ouch, migration issues...)
* Detect removeable media to avoid .Trash-foo on it. How?
* Trashcan properties (properties for trash:/? hmm. Easier with separate dialog)
- Maximum size for trash can (#18109 suggests a %, but a MB size is easier).
This means to delete the oldest files from the trash automatically. #79553
* Err, should we support renaming? :) Difficult to disable...
In fact it's already not disabled in readonly directories (e.g. "/") -> todo
(for F2 and kpropertiesdialog)
Bugs closed by kio_trash
========================
#79826 (3.3 only)
#62848 (configurable trash location)
#78116 (.directory)
#18109 (general one)
#17744 (restore)
#76380 #56821 (trashing on same partition)
New features implemented
=======================
#79553 (Deleting oldest files when size is bigger than a certain configurable amount)
Choice of URL scheme
====================
We use trash:/trashid-fileid[/relativepath]
This gave problems with CopyJob::startRenameJob which exposed trashid-fileid
to the user as a filename when dropping a file out of the trash.
But this was fixed with the fileNameUsedForCopying=Name setting.
A previous experiment was trash:/filename[/relativepath]?t=trashid&id=fileid
but this gives problems with going Up (it first removes the query),
with KDirLister (it wouldn't know when to remove the query, to find the URL
of the parent directory).
#! /usr/bin/env bash
$XGETTEXT `find -name "*.cpp" -o -name "*.h"` -o $podir/kio_trash.pot
/*
This file is part of the KDE project
Copyright (C) 2008 Tobias Koenig <tokoe@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "discspaceutil.h"
#include <QtCore/QDirIterator>
#include <QtCore/QFileInfo>
#include <kdiskfreespaceinfo.h>
#include <QDebug>
#include <qplatformdefs.h> // QT_LSTAT, QT_STAT, QT_STATBUF
DiscSpaceUtil::DiscSpaceUtil( const QString &directory )
: mDirectory( directory ),
mFullSize( 0 )
{
calculateFullSize();
}
qulonglong DiscSpaceUtil::sizeOfPath( const QString &path )
{
QFileInfo info( path );
if ( !info.exists() ) {
return 0;
}
if ( info.isSymLink() ) {
// QFileInfo::size does not return the actual size of a symlink. #253776
QT_STATBUF buff;
return static_cast<qulonglong>(QT_LSTAT(QFile::encodeName(path), &buff) == 0 ? buff.st_size : 0);
} else if ( info.isFile() ) {
return info.size();
} else if ( info.isDir() ) {
QDirIterator it( path, QDirIterator::NoIteratorFlags );
qulonglong sum = 0;
while ( it.hasNext() ) {
const QFileInfo info = it.next();
if (info.fileName() != QLatin1String(".") && info.fileName() != QLatin1String(".."))
sum += sizeOfPath( info.absoluteFilePath() );
}
return sum;
} else {
return 0;
}
}
double DiscSpaceUtil::usage( qulonglong size ) const
{
if ( mFullSize == 0 )
return 0;
return (((double)size*100)/(double)mFullSize);
}
qulonglong DiscSpaceUtil::size() const
{
return mFullSize;
}
QString DiscSpaceUtil::mountPoint() const
{
return mMountPoint;
}
void DiscSpaceUtil::calculateFullSize()
{
KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo( mDirectory );
if ( info.isValid() ) {
mFullSize = info.size();
mMountPoint = info.mountPoint();
}
}
/*
This file is part of the KDE project
Copyright (C) 2008 Tobias Koenig <tokoe@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef DISCSPACEUTIL_H
#define DISCSPACEUTIL_H
#include <QtCore/QString>
/**
* A small utility class to access and calculate
* size and usage of mount points.
*/
class DiscSpaceUtil
{
public:
/**
* Creates a new disc space util.
*
* @param directory A directory the util shall work on.
* @param parent The parent object.
*/
explicit DiscSpaceUtil( const QString &directory );
/**
* Returns the usage of the directory pass in the constructor on this
* mount point in percent.
*
* @param size The current size of the directory.
*/
double usage( qulonglong size ) const;
/**
* Returns the size of the partition in bytes.
*/
qulonglong size() const;
/**
* Returns the mount point of the directory.
*/
QString mountPoint() const;
/**
* Returns the size of the given path in bytes.
*/
static qulonglong sizeOfPath( const QString &path );
private:
void calculateFullSize();
QString mDirectory;
qulonglong mFullSize;
QString mMountPoint;
};
#endif
/***************************************************************************
* Copyright (C) 2008 by Tobias Koenig <tokoe@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
***************************************************************************/
#include "kcmtrash.h"
#include "discspaceutil.h"
#include "trashimpl.h"
#include <QCheckBox>
#include <QComboBox>
#include <QDoubleSpinBox>
#include <QFormLayout>
#include <QLabel>
#include <QLayout>
#include <QListWidget>
#include <QListWidgetItem>
#include <kconfig.h>
#include <kconfiggroup.h>
#include <KLocalizedString>
#include <qdialog.h>
#include <kglobal.h>
#include <qicon.h>
#include <klocale.h>
#include <kpluginfactory.h>
#include <kpluginloader.h>
#include <KIntSpinBox>
#include <QDebug>
K_PLUGIN_FACTORY( KCMTrashConfigFactory, registerPlugin<TrashConfigModule>( "trash" ); )
K_EXPORT_PLUGIN( KCMTrashConfigFactory( "kcmtrash" ) )
TrashConfigModule::TrashConfigModule( QWidget* parent, const QVariantList& )
: KCModule( //KCMTrashConfigFactory::componentData(),
parent ), trashInitialize( false )
{
mTrashImpl = new TrashImpl();
mTrashImpl->init();
readConfig();
setupGui();
useTypeChanged();
connect( mUseTimeLimit, SIGNAL( toggled( bool ) ),
this, SLOT( changed() ) );
connect( mUseTimeLimit, SIGNAL( toggled( bool ) ),
this, SLOT( useTypeChanged() ) );
connect( mDays, SIGNAL( valueChanged( int ) ),
this, SLOT( changed() ) );
connect( mUseSizeLimit, SIGNAL( toggled( bool ) ),
this, SLOT( changed() ) );
connect( mUseSizeLimit, SIGNAL( toggled( bool ) ),
this, SLOT( useTypeChanged() ) );
connect( mPercent, SIGNAL( valueChanged( double ) ),
this, SLOT( percentChanged( double ) ) );
connect( mPercent, SIGNAL( valueChanged( double ) ),
this, SLOT( changed() ) );
connect( mLimitReachedAction, SIGNAL( currentIndexChanged( int ) ),
this, SLOT( changed() ) );
trashChanged( 0 );
trashInitialize = true;
}
TrashConfigModule::~TrashConfigModule()
{
}
void TrashConfigModule::save()
{
if ( !mCurrentTrash.isEmpty() ) {
ConfigEntry entry;
entry.useTimeLimit = mUseTimeLimit->isChecked();
entry.days = mDays->value();
entry.useSizeLimit = mUseSizeLimit->isChecked();
entry.percent = mPercent->value(),
entry.actionType = mLimitReachedAction->currentIndex();
mConfigMap.insert( mCurrentTrash, entry );
}
writeConfig();
}
void TrashConfigModule::defaults()
{
ConfigEntry entry;
entry.useTimeLimit = false;
entry.days = 7;
entry.useSizeLimit = true;
entry.percent = 10.0;
entry.actionType = 0;
mConfigMap.insert( mCurrentTrash, entry );
trashInitialize = false;
trashChanged( 0 );
}
void TrashConfigModule::percentChanged( double percent )
{
DiscSpaceUtil util( mCurrentTrash );
qulonglong partitionSize = util.size();
double size = ((double)(partitionSize/100))*percent;
mSizeLabel->setText("(" + KGlobal::locale()->formatByteSize(size, 2) + ")");
}
void TrashConfigModule::trashChanged( QListWidgetItem *item )
{
trashChanged( item->data( Qt::UserRole ).toInt() );
}
void TrashConfigModule::trashChanged( int value )
{
const TrashImpl::TrashDirMap map = mTrashImpl->trashDirectories();
if ( !mCurrentTrash.isEmpty() && trashInitialize ) {
ConfigEntry entry;
entry.useTimeLimit = mUseTimeLimit->isChecked();
entry.days = mDays->value();
entry.useSizeLimit = mUseSizeLimit->isChecked();
entry.percent = mPercent->value(),
entry.actionType = mLimitReachedAction->currentIndex();
mConfigMap.insert( mCurrentTrash, entry );
}
mCurrentTrash = map[ value ];
if ( mConfigMap.contains( mCurrentTrash ) ) {
const ConfigEntry entry = mConfigMap[ mCurrentTrash ];
mUseTimeLimit->setChecked( entry.useTimeLimit );
mDays->setValue( entry.days );
mUseSizeLimit->setChecked( entry.useSizeLimit );
mPercent->setValue( entry.percent );
mLimitReachedAction->setCurrentIndex( entry.actionType );
} else {
mUseTimeLimit->setChecked( false );
mDays->setValue( 7 );
mUseSizeLimit->setChecked( true );
mPercent->setValue( 10.0 );
mLimitReachedAction->setCurrentIndex( 0 );
}
mDays->setSuffix( ki18np( " day", " days" ) );
percentChanged( mPercent->value() );
}
void TrashConfigModule::useTypeChanged()
{
mDays->setEnabled( mUseTimeLimit->isChecked() );
mSizeWidget->setEnabled( mUseSizeLimit->isChecked() );
}
void TrashConfigModule::readConfig()
{
KConfig config( "ktrashrc" );
mConfigMap.clear();
const QStringList groups = config.groupList();
for ( int i = 0; i < groups.count(); ++i ) {
if ( groups[ i ].startsWith( '/' ) ) {
const KConfigGroup group = config.group( groups[ i ] );
ConfigEntry entry;
entry.useTimeLimit = group.readEntry( "UseTimeLimit", false );
entry.days = group.readEntry( "Days", 7 );
entry.useSizeLimit = group.readEntry( "UseSizeLimit", true );
entry.percent = group.readEntry( "Percent", 10.0 );
entry.actionType = group.readEntry( "LimitReachedAction", 0 );
mConfigMap.insert( groups[ i ], entry );
}
}
}
void TrashConfigModule::writeConfig()
{
KConfig config( "ktrashrc" );
// first delete all existing groups
const QStringList groups = config.groupList();
for ( int i = 0; i < groups.count(); ++i )
if ( groups[ i ].startsWith( '/' ) )
config.deleteGroup( groups[ i ] );
QMapIterator<QString, ConfigEntry> it( mConfigMap );
while ( it.hasNext() ) {
it.next();
KConfigGroup group = config.group( it.key() );
group.writeEntry( "UseTimeLimit", it.value().useTimeLimit );
group.writeEntry( "Days", it.value().days );
group.writeEntry( "UseSizeLimit", it.value().useSizeLimit );
group.writeEntry( "Percent", it.value().percent );
group.writeEntry( "LimitReachedAction", it.value().actionType );
}
config.sync();
}
void TrashConfigModule::setupGui()
{
QVBoxLayout *layout = new QVBoxLayout( this );
TrashImpl::TrashDirMap map = mTrashImpl->trashDirectories();
if ( map.count() != 1 ) {
// If we have multiple trashes, we setup a widget to choose
// which trash to configure
QListWidget *mountPoints = new QListWidget( this );
layout->addWidget( mountPoints );
QMapIterator<int, QString> it( map );
while ( it.hasNext() ) {
it.next();
DiscSpaceUtil util( it.value() );
QListWidgetItem *item = new QListWidgetItem( QIcon( "folder" ), util.mountPoint() );
item->setData( Qt::UserRole, it.key() );
mountPoints->addItem( item );
}
mountPoints->setCurrentRow( 0 );
connect( mountPoints, SIGNAL( currentItemChanged( QListWidgetItem*, QListWidgetItem* ) ),
this, SLOT( trashChanged( QListWidgetItem* ) ) );
} else {
mCurrentTrash = map.value( 0 );
}
QHBoxLayout *daysLayout = new QHBoxLayout();
layout->addLayout( daysLayout );
mUseTimeLimit = new QCheckBox( i18n( "Delete files older than:" ), this );
mUseTimeLimit->setWhatsThis( xi18nc( "@info:whatsthis",
"<para>Check this box to allow <b>automatic deletion</b> of files that are older than the value specified. "
"Leave this disabled to <b>not</b> automatically delete any items after a certain timespan</para>" ) );
daysLayout->addWidget( mUseTimeLimit );
mDays = new KIntSpinBox( this );
mDays->setRange( 1, 365 );
mDays->setSingleStep( 1 );
mDays->setSuffix( i18np(" day", " days", mDays->value()) );
mDays->setWhatsThis( xi18nc( "@info:whatsthis",
"<para>Set the number of days that files can remain in the trash. "
"Any files older than this will be automatically deleted.</para>" ) );
daysLayout->addWidget( mDays );
daysLayout->addStretch();
QFormLayout *sizeLayout = new QFormLayout();
layout->addLayout( sizeLayout );
mUseSizeLimit = new QCheckBox( i18n( "Limit to maximum size" ), this );
mUseSizeLimit->setWhatsThis( xi18nc( "@info:whatsthis",
"<para>Check this box to limit the trash to the maximum amount of disk space that you specify below. "
"Otherwise, it will be unlimited.</para>" ) );
sizeLayout->addRow( mUseSizeLimit );
mSizeWidget = new QWidget( this );
sizeLayout->addRow( mSizeWidget );
QFormLayout *sizeWidgetLayout = new QFormLayout( mSizeWidget );
sizeWidgetLayout->setMargin( 0 );
QHBoxLayout *maximumSizeLayout = new QHBoxLayout( );
mPercent = new QDoubleSpinBox( mSizeWidget );
mPercent->setRange( 0.001, 100 );
mPercent->setDecimals( 3 );
mPercent->setSingleStep( 1 );
mPercent->setSuffix( " %" );
mPercent->setWhatsThis( xi18nc( "@info:whatsthis",
"<para>This is the maximum percent of disk space that will be used for the trash.</para>" ) );
maximumSizeLayout->addWidget( mPercent );
mSizeLabel = new QLabel( mSizeWidget );
mSizeLabel->setWhatsThis( xi18nc( "@info:whatsthis",
"<para>This is the calculated amount of disk space that will be allowed for the trash, the maximum.</para>" ) );
maximumSizeLayout->addWidget( mSizeLabel );
sizeWidgetLayout->addRow( i18n( "Maximum size:" ), maximumSizeLayout );
QLabel *label = new QLabel( i18n( "When limit reached:" ) );
sizeWidgetLayout->addRow( label );
mLimitReachedAction = new QComboBox( mSizeWidget );
mLimitReachedAction->addItem( i18n( "Warn Me" ) );
mLimitReachedAction->addItem( i18n( "Delete Oldest Files From Trash" ) );
mLimitReachedAction->addItem( i18n( "Delete Biggest Files From Trash" ) );
mLimitReachedAction->setWhatsThis( xi18nc( "@info:whatsthis",
"<para>When the size limit is reached, it will prefer to delete the type of files that you specify, first. "
"If this is set to warn you, it will do so instead of automatically deleting files.</para>" ) );
sizeWidgetLayout->addRow( 0, mLimitReachedAction );
layout->addStretch();
}
#include "kcmtrash.moc"