mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-23 18:32:51 +00:00
313 lines
8.1 KiB
C++
313 lines
8.1 KiB
C++
/* This file is part of KArchiveManager
|
|
Copyright (C) 2018 Ivailo Monev <xakepa10@gmail.com>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License version 2, as published by the Free Software Foundation.
|
|
|
|
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 <QCoreApplication>
|
|
#include <QFile>
|
|
#include <QDir>
|
|
#include <QTemporaryFile>
|
|
#include <QDirIterator>
|
|
#include <QThread>
|
|
#include <QStandardItem>
|
|
#include <QDBusMetaType>
|
|
#include <KDebug>
|
|
#include <KMimeType>
|
|
#include <KIconLoader>
|
|
#include <KLocale>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include "karchivemanager.hpp"
|
|
|
|
static QIcon kFancyIcon(const mode_t mode, const QByteArray &pathname)
|
|
{
|
|
if (S_ISREG(mode)) {
|
|
const KMimeType::Ptr mime = KMimeType::findByName(QFile::decodeName(pathname));
|
|
if (mime) {
|
|
return QIcon(KIconLoader::global()->loadMimeTypeIcon(mime->iconName(), KIconLoader::Small));
|
|
}
|
|
return QIcon::fromTheme("unknown");
|
|
}
|
|
if (S_ISDIR(mode)) {
|
|
return QIcon::fromTheme("folder");
|
|
}
|
|
if (S_ISLNK(mode)) {
|
|
return QIcon::fromTheme("emblem-symbolic-link");
|
|
}
|
|
if (S_ISCHR(mode) || S_ISBLK(mode)) {
|
|
return QIcon::fromTheme("drive-harddisk");
|
|
}
|
|
if (S_ISFIFO(mode) || S_ISSOCK(mode)) {
|
|
return QIcon::fromTheme("media-memory");
|
|
}
|
|
return QIcon::fromTheme("unknown");
|
|
}
|
|
|
|
class KArchiveModelPrivate : public QThread
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
KArchiveModelPrivate(QObject *parent = nullptr);
|
|
|
|
QString joinDir(const QString &dir1, const QString &dir2) const;
|
|
QStandardItem* makeColumn(const QString &string) const;
|
|
|
|
void appendDirectory(const QString &path);
|
|
void appendSpecial(const KArchiveEntry &info);
|
|
|
|
QStandardItem* m_root;
|
|
QMap<QString,QStandardItem*> m_directories;
|
|
QList<KArchiveEntry> m_list;
|
|
const KArchive *m_archive;
|
|
bool m_interrupt;
|
|
|
|
void requestInterruption();
|
|
|
|
protected:
|
|
void run() final;
|
|
};
|
|
|
|
KArchiveModelPrivate::KArchiveModelPrivate(QObject *parent)
|
|
: QThread(parent),
|
|
m_interrupt(false)
|
|
{
|
|
}
|
|
|
|
// because altering paths is not easy
|
|
QString KArchiveModelPrivate::joinDir(const QString &dir1, const QString &dir2) const
|
|
{
|
|
if (dir1.isEmpty()) {
|
|
return dir2;
|
|
}
|
|
return dir1 + "/" + dir2;
|
|
}
|
|
|
|
QStandardItem* KArchiveModelPrivate::makeColumn(const QString &string) const
|
|
{
|
|
QStandardItem* item = new QStandardItem(string);
|
|
item->setSelectable(false);
|
|
item->setTextAlignment(Qt::AlignRight);
|
|
return item;
|
|
}
|
|
|
|
void KArchiveModelPrivate::appendDirectory(const QString &path)
|
|
{
|
|
QStandardItem* lastitem = m_root;
|
|
QString dirsofar;
|
|
foreach (const QString &dir, path.split("/")) {
|
|
if (dir.isEmpty()) {
|
|
continue;
|
|
}
|
|
|
|
dirsofar = joinDir(dirsofar, dir);
|
|
if (m_directories.contains(dirsofar)) {
|
|
lastitem = m_directories.value(dirsofar);
|
|
continue;
|
|
}
|
|
|
|
// NOTE: directory entries are not consistent
|
|
KArchiveEntry info;
|
|
foreach (const KArchiveEntry &listinfo, m_list) {
|
|
if (listinfo.pathname == dirsofar || listinfo.pathname == dirsofar + "/") {
|
|
info = listinfo;
|
|
break;
|
|
}
|
|
}
|
|
if (info.isNull()) {
|
|
// fake it for now
|
|
info.mode |= S_IFDIR;
|
|
}
|
|
|
|
QList<QStandardItem*> diritems;
|
|
QStandardItem* diritem = new QStandardItem(dir);
|
|
diritem->setIcon(kFancyIcon(info.mode, info.pathname));
|
|
diritem->setWhatsThis("Directory");
|
|
diritem->setStatusTip(dirsofar);
|
|
diritems << diritem;
|
|
diritems << makeColumn(info.fancyType());
|
|
diritems << makeColumn(info.fancySize());
|
|
diritems << makeColumn(info.fancyMode());
|
|
diritems << makeColumn(info.fancyEncrypted());
|
|
|
|
lastitem->appendRow(diritems);
|
|
|
|
m_directories.insert(dirsofar, diritem);
|
|
lastitem = diritem;
|
|
}
|
|
}
|
|
|
|
void KArchiveModelPrivate::appendSpecial(const KArchiveEntry &info)
|
|
{
|
|
const QFileInfo fileinfo(info.pathname);
|
|
const QString infopath = fileinfo.path();
|
|
const QString infoname = fileinfo.fileName();
|
|
|
|
appendDirectory(infopath);
|
|
|
|
QList<QStandardItem*> specialitems;
|
|
QStandardItem* specialitem = new QStandardItem(infoname);
|
|
specialitem->setIcon(kFancyIcon(info.mode, info.pathname));
|
|
specialitem->setStatusTip(info.pathname);
|
|
specialitems << specialitem;
|
|
specialitems << makeColumn(info.fancyType());
|
|
specialitems << makeColumn(info.fancySize());
|
|
specialitems << makeColumn(info.fancyMode());
|
|
specialitems << makeColumn(info.fancyEncrypted());
|
|
|
|
QStandardItem* diritem = m_directories.value(infopath);
|
|
if (diritem) {
|
|
diritem->appendRow(specialitems);
|
|
} else {
|
|
m_root->appendRow(specialitems);
|
|
}
|
|
}
|
|
|
|
void KArchiveModelPrivate::run()
|
|
{
|
|
m_list = m_archive->list();
|
|
m_interrupt = false;
|
|
|
|
foreach (const KArchiveEntry &info, m_list) {
|
|
if (m_interrupt) {
|
|
return;
|
|
}
|
|
|
|
if (S_ISDIR(info.mode)) {
|
|
appendDirectory(info.pathname);
|
|
} else {
|
|
appendSpecial(info);
|
|
}
|
|
}
|
|
}
|
|
|
|
void KArchiveModelPrivate::requestInterruption()
|
|
{
|
|
m_interrupt = true;
|
|
}
|
|
|
|
KArchiveModel::KArchiveModel(QObject *parent)
|
|
: QStandardItemModel(parent),
|
|
d(new KArchiveModelPrivate(this)) {
|
|
connect(d, SIGNAL(finished()), this, SLOT(slotLoadFinished()));
|
|
}
|
|
|
|
KArchiveModel::~KArchiveModel()
|
|
{
|
|
if (d->isRunning()) {
|
|
d->requestInterruption();
|
|
d->wait();
|
|
}
|
|
delete d;
|
|
}
|
|
|
|
bool KArchiveModel::loadArchive(const KArchive *archive)
|
|
{
|
|
bool result = false;
|
|
|
|
if (!archive) {
|
|
return result;
|
|
}
|
|
|
|
result = true;
|
|
|
|
if (d->isRunning()) {
|
|
d->requestInterruption();
|
|
d->wait();
|
|
}
|
|
QCoreApplication::processEvents();
|
|
clear();
|
|
|
|
d->m_archive = archive;
|
|
d->m_root = invisibleRootItem();
|
|
d->m_directories.clear();
|
|
|
|
emit loadStarted();
|
|
d->start();
|
|
|
|
return result;
|
|
}
|
|
|
|
QString KArchiveModel::path(const QModelIndex &index) const {
|
|
QString result;
|
|
|
|
if (!index.isValid()) {
|
|
return result;
|
|
}
|
|
|
|
const QStandardItem *item = itemFromIndex(index);
|
|
result = item->statusTip();
|
|
|
|
if (item->whatsThis() == "Directory") {
|
|
result += "/";
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
QStringList KArchiveModel::paths(const QModelIndex &index) const
|
|
{
|
|
QStringList result;
|
|
|
|
const QByteArray indexpath = path(index).toLocal8Bit();
|
|
if (!indexpath.isEmpty() && index.isValid()) {
|
|
const QStandardItem *item = itemFromIndex(index);
|
|
if (item->whatsThis() == "Directory") {
|
|
foreach (const KArchiveEntry &info, d->m_list) {
|
|
if (info.pathname.startsWith(indexpath)) {
|
|
result << info.pathname;
|
|
}
|
|
}
|
|
} else {
|
|
result << indexpath;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
QString KArchiveModel::dir(const QModelIndex &index) const
|
|
{
|
|
QString result;
|
|
|
|
if (!index.isValid()) {
|
|
return result;
|
|
}
|
|
|
|
const QStandardItem *item = itemFromIndex(index);
|
|
if (item->whatsThis() == "Directory") {
|
|
result = item->statusTip();
|
|
} else {
|
|
QFileInfo iteminfo(item->statusTip());
|
|
result = iteminfo.path();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void KArchiveModel::slotLoadFinished()
|
|
{
|
|
setHeaderData(0, Qt::Horizontal, QVariant("Name"));
|
|
setHeaderData(1, Qt::Horizontal, QVariant("Type"));
|
|
setHeaderData(2, Qt::Horizontal, QVariant("Size"));
|
|
setHeaderData(3, Qt::Horizontal, QVariant("Mode"));
|
|
setHeaderData(4, Qt::Horizontal, QVariant("Encrypted"));
|
|
|
|
emit loadFinished();
|
|
}
|
|
|
|
#include "karchivemanager.moc"
|