8#include <QLoggingCategory>
11#if defined(Q_OS_LINUX)
16#include "RemoteFileSystemModel.h"
18Q_DECLARE_METATYPE(CRemoteFileSystem::TYPES)
20static Q_LOGGING_CATEGORY(log,
"RemoteFileSystem.Model")
25 const QString& szPath, TYPES type)
31 , m_Permissions(QFileDevice::Permission::WriteOwner | QFileDevice::Permission::ReadOwner)
36CRemoteFileSystem::~CRemoteFileSystem()
43 m_pParent = file.m_pParent;
44 m_vChild = file.m_vChild;
45 m_szPath = file.m_szPath;
46 m_nSize = file.m_nSize;
48 m_createTime = file.m_createTime;
49 m_lastModifed = file.m_lastModifed;
50 m_Permissions = file.m_Permissions;
51 m_szOwner = file.m_szOwner;
52 m_State = file.m_State;
55#if defined(Q_OS_LINUX)
56void uint32_to_permstr(uint32_t mode,
char *str) {
57 str[0] = S_ISDIR(mode) ?
'd' :
61 S_ISFIFO(mode) ?
'p' :
62 S_ISSOCK(mode) ?
's' :
'-';
65 str[1] = (mode & S_IRUSR) ?
'r' :
'-';
66 str[2] = (mode & S_IWUSR) ?
'w' :
'-';
67 str[3] = (mode & S_IXUSR) ? ((mode & S_ISUID) ?
's' :
'x') : ((mode & S_ISUID) ?
'S' :
'-');
69 str[4] = (mode & S_IRGRP) ?
'r' :
'-';
70 str[5] = (mode & S_IWGRP) ?
'w' :
'-';
71 str[6] = (mode & S_IXGRP) ? ((mode & S_ISGID) ?
's' :
'x') : ((mode & S_ISGID) ?
'S' :
'-');
73 str[7] = (mode & S_IROTH) ?
'r' :
'-';
74 str[8] = (mode & S_IWOTH) ?
'w' :
'-';
75 str[9] = (mode & S_IXOTH) ? ((mode & S_ISVTX) ?
't' :
'x') : ((mode & S_ISVTX) ?
'T' :
'-');
80QVariant CRemoteFileSystem::Data(
int column)
82 switch((ColumnValue)column) {
83 case ColumnValue::Name: {
86 case ColumnValue::Size: {
87 return CStats::Convertbytes(GetSize());
89 case ColumnValue::Type: {
90 if(GetType() & TYPE::FILE)
92 if(GetType() & TYPE::DIR)
94 if(GetType() & TYPE::DRIVE)
96 if(GetType() & TYPE::SYMLINK)
98 if(GetType() & TYPE::SPECIAL)
102 case ColumnValue::LastModified: {
103 return GetLastModified();
105 case ColumnValue::Permission: {
106#if defined(Q_OS_LINUX)
107 quint32 permissions = (quint32)GetPermissions();
109 uint32_to_permstr(permissions, buf);
114 case ColumnValue::Owner:
122QString CRemoteFileSystem::HeaderData(
int section)
124 switch ((ColumnValue)section) {
125 case ColumnValue::Name:
126 return tr(
"File name");
127 case ColumnValue::Size:
128 return tr(
"File size");
129 case ColumnValue::Type:
130 return tr(
"File type");
131 case ColumnValue::LastModified:
132 return tr(
"File last modified time");
133 case ColumnValue::Permission:
134 return tr(
"Permissions");
135 case ColumnValue::Owner:
136 return tr(
"Owner/Group");
143int CRemoteFileSystem::ColumnCount()
146 return (
int)ColumnValue::Permission;
148 return (
int)ColumnValue::End;
152int CRemoteFileSystem::ChildCount()
154 return m_vChild.size();
169 Q_ASSERT_X(pChild->GetType(),
"AppendChild",
"Must set all the properties before call them");
175 if(-1 != IndexOf(pChild->GetPath()))
177 qDebug(log) << pChild->GetName() <<
"is exist";
181 m_vChild.append(pChild);
182 pChild->SetParent(
this);
186int CRemoteFileSystem::RemoveChild(
int index)
188 if(0 > index || m_vChild.size() < index)
190 m_vChild.removeAt(index);
196 if(nIndex < 0 || nIndex >= m_vChild.size())
198 return m_vChild.at(nIndex);
203 return m_vChild.indexOf(pChild);
206int CRemoteFileSystem::IndexOf(
const QString& szPath)
208 for(
int i = 0; i < m_vChild.size(); i++) {
209 auto p = m_vChild[i];
210 if(p && p->GetPath() == szPath)
216int CRemoteFileSystem::IndexOfParent()
220 nIndex= GetParent()->IndexOf(
this);
224QString CRemoteFileSystem::GetPath()
229QString CRemoteFileSystem::GetName()
232 QString szPath = GetPath();
235 int nIndex = szPath.lastIndexOf(
'/');
238 szName = szPath.right(szPath.size() - nIndex - 1);
239 if(GetState() == State::Getting)
240 szName +=
"(" + tr(
"getting") +
" ......)";
244quint64 CRemoteFileSystem::GetSize()
249void CRemoteFileSystem::SetSize(quint64 size)
254bool CRemoteFileSystem::IsDir()
256 return !(GetType() & TYPE::FILE);
259QIcon CRemoteFileSystem::Icon()
261 if(GetType() & TYPE::DRIVE)
262 return QIcon::fromTheme(
"drive-harddisk");
263 if(GetType() & TYPE::DIR)
264 return QIcon::fromTheme(
"folder-remote");
265 if(GetType() & TYPE::FILE || GetType() & TYPE::SPECIAL)
266 return QApplication::style()->standardIcon(QStyle::SP_FileIcon);
267 if(GetType() & TYPE::SYMLINK)
268 return QIcon::fromTheme(
"emblem-symbolic-link");
272CRemoteFileSystem::TYPES CRemoteFileSystem::GetType()
277QDateTime CRemoteFileSystem::GetCreateTime()
282void CRemoteFileSystem::SetCreateTime(
const QDateTime &date)
287QDateTime CRemoteFileSystem::GetLastModified()
289 return m_lastModifed;
292void CRemoteFileSystem::SetLastModified(
const QDateTime &date)
294 m_lastModifed = date;
297QFileDevice::Permissions CRemoteFileSystem::GetPermissions()
299 return m_Permissions;
302void CRemoteFileSystem::SetPermissions(QFileDevice::Permissions privileges)
304 m_Permissions = privileges;
307QString CRemoteFileSystem::GetOwner()
312void CRemoteFileSystem::SetOwner(QString szOwner)
317void CRemoteFileSystem::SetState(State a)
322const CRemoteFileSystem::State CRemoteFileSystem::GetState()
const
327CRemoteFileSystemModel::CRemoteFileSystemModel(
328 QObject *parent, CRemoteFileSystem::TYPES filter)
329 : QAbstractItemModel(parent)
334CRemoteFileSystemModel::~CRemoteFileSystemModel()
336 qDebug(log) << Q_FUNC_INFO;
338 DeleteRemoteFileSystem(m_pRoot);
344 for(
int i = 0; i < p->ChildCount(); i++) {
345 auto pChild = p->GetChild(i);
347 DeleteRemoteFileSystem(pChild);
352QModelIndex CRemoteFileSystemModel::SetRootPath(
const QString &szPath)
354 if(szPath.isEmpty())
return QModelIndex();
355 if(m_pRoot && m_pRoot->GetPath() == szPath)
356 return index(m_pRoot);
360 DeleteRemoteFileSystem(m_pRoot);
364 QModelIndex idx = index(m_pRoot);
366 qDebug(log) <<
"SetRootPath:" <<
this << idx << szPath;
375CRemoteFileSystem* CRemoteFileSystemModel::GetRemoteFileSystemFromIndex(
const QModelIndex &index)
const
382CRemoteFileSystem::TYPES CRemoteFileSystemModel::GetFilter()
387QVariant CRemoteFileSystemModel::headerData(
int section, Qt::Orientation orientation,
int role)
const
389 if(Qt::DisplayRole != role)
391 if(Qt::Vertical == orientation) {
392 return QString::number(section + 1);
394 return CRemoteFileSystem::HeaderData(section);
399int CRemoteFileSystemModel::rowCount(
const QModelIndex &parent)
const
402 if(!parent.isValid())
return 0;
404 pItem = GetRemoteFileSystemFromIndex(parent);
406 return pItem->ChildCount();
410int CRemoteFileSystemModel::columnCount(
const QModelIndex &parent)
const
412 if(!parent.isValid())
return 0;
413 return CRemoteFileSystem::ColumnCount();
416QVariant CRemoteFileSystemModel::data(
const QModelIndex &index,
int role)
const
420 if (!index.isValid())
422 if (role != Qt::DisplayRole && role != Qt::DecorationRole)
428 if(!(pItem->GetType() & m_Filter))
430 if(Qt::DecorationRole == role && index.column() == 0)
431 return pItem->Icon();
432 if(Qt::DisplayRole == role || Qt::EditRole == role)
433 return pItem->Data(index.column());
434 if(Qt::ToolTipRole == role)
435 return pItem->GetPath();
439QModelIndex CRemoteFileSystemModel::index(
const QString& szPath)
const
442 qDebug(log) << Q_FUNC_INFO << szPath;
443 QModelIndex idxParent;
444 QModelIndex idx = index(0, 0);
445 while(idx.isValid()) {
446 idx = index(r++, 0, idxParent);
448 if(!pRemoteFileSystem)
450 QString szDir = pRemoteFileSystem->GetPath();
451 qDebug(log) << szDir << szPath;
454 if(pRemoteFileSystem->GetType() & CRemoteFileSystem::TYPE::FILE) {
455 qDebug(log) << szDir <<
"Is file:";
458 if(szDir.right(1) !=
'/')
460 if(szPath.left(szDir.size()) == szDir) {
461 qDebug(log) <<
"Contain:" << szPath << szDir;
467 return QModelIndex();
470QModelIndex CRemoteFileSystemModel::index(
CRemoteFileSystem* node,
int column)
const
472 if(
nullptr == node)
return QModelIndex();
476 row = node->IndexOfParent();
477 }
else if(node == m_pRoot) {
480 if(0 > row || 0 > column || CRemoteFileSystem::ColumnCount() < column)
481 return QModelIndex();
482 return createIndex(row, column, node);
485QModelIndex CRemoteFileSystemModel::index(
int row,
int column,
const QModelIndex &parent)
const
488 if (!hasIndex(row, column, parent))
489 return QModelIndex();
490 if(!parent.isValid())
491 return index(m_pRoot, column);
493 pItem = GetRemoteFileSystemFromIndex(parent);
495 return QModelIndex();
496 pItem = pItem->GetChild(row);
498 return createIndex(row, column, pItem);
500 return QModelIndex();
503QModelIndex CRemoteFileSystemModel::parent(
const QModelIndex &child)
const
506 if (!child.isValid())
507 return QModelIndex();
510 return QModelIndex();
513 return index(pItemParent);
514 return QModelIndex();
517bool CRemoteFileSystemModel::canFetchMore(
const QModelIndex &parent)
const
519 if(!parent.isValid()) {
520 qDebug(log) <<
"canFetchMore: parent is valid" << parent;
524 if(p && p->GetState() == CRemoteFileSystem::State::No
525 && !(p->GetType() & CRemoteFileSystem::TYPE::FILE)) {
526 qDebug(log) <<
"canFetchMore:" << parent << p->GetPath() <<
"true";
529 qDebug(log) << Q_FUNC_INFO << parent;
533void CRemoteFileSystemModel::fetchMore(
const QModelIndex &parent)
535 qDebug(log) << Q_FUNC_INFO << parent;
536 auto p = GetRemoteFileSystemFromIndex(parent);
539 qCritical(log) <<
"fetchMore:" << parent <<
"The pointer is nullptr";
542 if(p->GetType() & CRemoteFileSystem::TYPE::FILE) {
543 qCritical(log) <<
"fetchMore:" << parent <<
"The node is file";
546 QString szPath = p->GetPath();
547 if(szPath.isEmpty()) {
548 qCritical(log) <<
"fetchMore:" << parent <<
"The path is empty";
551 if(p->GetState() != CRemoteFileSystem::State::No) {
552 qDebug(log) <<
"fetchMore:" << parent << p->GetState() <<
"The state is not NO";
555 if(m_GetFolder.indexOf(p) != -1)
557 m_GetFolder.append(p);
558 p->SetState(CRemoteFileSystem::State::Getting);
560 qDebug(log) <<
"fetchMore:" << parent << p << szPath;
563void CRemoteFileSystemModel::slotGetDir(
565 QVector<QSharedPointer<CRemoteFileSystem> > contents,
569 qCritical(log) <<
"The pointer is nullptr";
572 int nIndex = m_GetFolder.indexOf(p);
574 qDebug(log) <<
"Is not the model";
578 m_GetFolder.removeAt(nIndex);
579 QModelIndex parentIndex;
580 parentIndex = index(p, 0);
581 qDebug(log) <<
"slotGetDir:" << p << p << p->GetPath() << parentIndex << contents.size();
582 p->SetState(CRemoteFileSystem::State::Ok);
583 if(contents.size() > 0) {
585 foreach(
auto c, contents) {
587 if(!(c->GetType() & GetFilter()))
continue;
590 beginInsertRows(parentIndex, 0, nCount);
591 foreach(
auto c, contents) {
593 if(!(c->GetType() & GetFilter()))
continue;
596 pRfs->SetSize(c->GetSize());
597 pRfs->SetPermissions(c->GetPermissions());
598 pRfs->SetLastModified(c->GetLastModified());
599 pRfs->SetCreateTime(c->GetCreateTime());
603 auto topleft = index(0, 0, parentIndex);
604 auto bottomRight = index(p->ChildCount(), p->ColumnCount(), parentIndex);
605 if(topleft.isValid() && bottomRight.isValid())
606 emit dataChanged(topleft, bottomRight);
608 emit dataChanged(parentIndex, parentIndex);
611void CRemoteFileSystemModel::CreateDir(QModelIndex index,
const QString &dir)
613 auto p = GetRemoteFileSystemFromIndex(index);
615 if(p && !p->GetPath().isEmpty()) {
616 QString szPath = p->GetPath() +
"/" + dir;
617 if(p->IndexOf(szPath) > -1) {
618 qCritical(log) <<
"The path is exist:" << szPath;
619 QMessageBox::critical(
nullptr, tr(
"Error"), tr(
"The path is exist: %1").arg(szPath));
622 emit sigMakeDir(szPath);
623 p->SetState(CRemoteFileSystem::State::No);
624 fetchMore(parent(this->index(p)));
628void CRemoteFileSystemModel::RemoveDir(QModelIndex index)
630 auto p = GetRemoteFileSystemFromIndex(index);
631 if(p && !p->GetPath().isEmpty()) {
632 if(QMessageBox::question(
633 nullptr, tr(
"Delete directory"),
634 tr(
"Are you sure you want to delete '%1'?").arg(p->GetPath()),
635 QMessageBox::Yes | QMessageBox::No)
638 if(p->GetType() & CRemoteFileSystem::TYPE::DIR)
639 emit sigRemoveDir(p->GetPath());
641 emit sigRemoveFile(p->GetPath());
643 auto pParent = p->GetParent();
645 int nIdx = pParent->IndexOf(p);
646 beginRemoveRows(index.parent(), nIdx, nIdx);
647 pParent->RemoveChild(nIdx);
648 DeleteRemoteFileSystem(p);
650 pParent->SetState(CRemoteFileSystem::State::No);
651 fetchMore(index.parent());
656bool CRemoteFileSystemModel::setData(
657 const QModelIndex &index,
const QVariant &value,
int role)
659 qDebug(log) << Q_FUNC_INFO << index << value << role;
662 if(Qt::EditRole != role) {
663 return QAbstractItemModel::setData(index, value, role);
667 auto p = GetRemoteFileSystemFromIndex(index);
668 QString szName = value.toString();
669 if(p && !p->GetPath().isEmpty() && p->GetName() != szName) {
670 QFileInfo fi(p->GetPath());
671 szName = fi.path() +
"/" + szName;
672 emit sigRename(p->GetPath(), szName);
673 auto pParent = p->GetParent();
675 Q_ASSERT(pParent == GetRemoteFileSystemFromIndex(index.parent()));
676 int nIdx = pParent->IndexOf(p);
677 beginRemoveRows(index.parent(), nIdx, nIdx);
678 pParent->RemoveChild(nIdx);
679 DeleteRemoteFileSystem(p);
681 pParent->SetState(CRemoteFileSystem::State::No);
682 fetchMore(index.parent());
688Qt::ItemFlags CRemoteFileSystemModel::flags(
const QModelIndex &index)
const
690 Qt::ItemFlags defaultFlags = QAbstractItemModel::flags(index);
691 if (!index.isValid())
694 if (index.column() == (
int)CRemoteFileSystem::ColumnValue::Name)
695 return defaultFlags | Qt::ItemIsEditable;
int AppendChild(CRemoteFileSystem *pChild)
Append child