X-Git-Url: https://www.flypig.org.uk/git/?p=openvpnui.git;a=blobdiff_plain;f=src%2Ffilebrowse%2Ffilemodel.cpp;fp=src%2Ffilebrowse%2Ffilemodel.cpp;h=562f29efef15706720e29f5caca79c853ec5ba28;hp=0000000000000000000000000000000000000000;hb=e24363e314aca32e7bee952f02f517a04a8dc5f2;hpb=ee3968ffa08d4e0fcbad87765efa3aeb32ff0554 diff --git a/src/filebrowse/filemodel.cpp b/src/filebrowse/filemodel.cpp new file mode 100644 index 0000000..562f29e --- /dev/null +++ b/src/filebrowse/filemodel.cpp @@ -0,0 +1,337 @@ +#include "filemodel.h" +#include +#include +#include +#include "engine.h" +#include "globals.h" + +enum { + FilenameRole = Qt::UserRole + 1, + FileKindRole = Qt::UserRole + 2, + FileIconRole = Qt::UserRole + 3, + PermissionsRole = Qt::UserRole + 4, + SizeRole = Qt::UserRole + 5, + LastModifiedRole = Qt::UserRole + 6, + CreatedRole = Qt::UserRole + 7, + IsDirRole = Qt::UserRole + 8, + IsLinkRole = Qt::UserRole + 9, + SymLinkTargetRole = Qt::UserRole + 10 +}; + +FileModel::FileModel(QObject *parent) : + QAbstractListModel(parent), + m_active(false), + m_dirty(false) +{ + m_dir = ""; + m_watcher = new QFileSystemWatcher(this); + connect(m_watcher, SIGNAL(directoryChanged(const QString&)), this, SLOT(refresh())); + connect(m_watcher, SIGNAL(fileChanged(const QString&)), this, SLOT(refresh())); + + QSettings settings; + m_showAll = settings.value("showAll", false).toBool(); + + // refresh model every time settings are changed + Engine *engine = qApp->property("engine").value(); + connect(engine, SIGNAL(settingsChanged()), this, SLOT(refreshFull())); +} + +FileModel::~FileModel() +{ +} + +int FileModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent); + return m_files.count(); +} + +QVariant FileModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() > m_files.size()-1) + return QVariant(); + + QFileInfo info = m_files.at(index.row()).info; + switch (role) { + + case Qt::DisplayRole: + case FilenameRole: + return info.fileName(); + + case FileKindRole: + if (info.isSymLink()) return "l"; + if (info.isDir()) return "d"; + if (info.isFile()) return "-"; + return "?"; + + case FileIconRole: + if (info.isSymLink() && info.isDir()) return "folder-link"; + if (info.isDir()) return "folder"; + if (info.isSymLink()) return "link"; + if (info.isFile()) { + QString suffix = info.suffix().toLower(); + return suffixToIconName(suffix); + } + return "file"; + + case PermissionsRole: + return permissionsToString(info.permissions()); + + case SizeRole: + if (info.isSymLink() && info.isDir()) return "dir-link"; + if (info.isDir()) return "dir"; + return filesizeToString(info.size()); + + case LastModifiedRole: + return datetimeToString(info.lastModified()); + + case CreatedRole: + return datetimeToString(info.created()); + + case IsDirRole: + return info.isDir(); + + case IsLinkRole: + return info.isSymLink(); + + case SymLinkTargetRole: + return info.symLinkTarget(); + + default: + return QVariant(); + } +} + +QHash FileModel::roleNames() const +{ + QHash roles = QAbstractListModel::roleNames(); + roles.insert(FilenameRole, QByteArray("filename")); + roles.insert(FileKindRole, QByteArray("filekind")); + roles.insert(FileIconRole, QByteArray("fileIcon")); + roles.insert(PermissionsRole, QByteArray("permissions")); + roles.insert(SizeRole, QByteArray("size")); + roles.insert(LastModifiedRole, QByteArray("modified")); + roles.insert(CreatedRole, QByteArray("created")); + roles.insert(IsDirRole, QByteArray("isDir")); + roles.insert(IsLinkRole, QByteArray("isLink")); + roles.insert(SymLinkTargetRole, QByteArray("symLinkTarget")); + return roles; +} + +int FileModel::fileCount() const +{ + return m_files.count(); +} + +QString FileModel::errorMessage() const +{ + return m_errorMessage; +} + +void FileModel::setDir(QString dir) +{ + if (m_dir == dir) + return; + + // update watcher to watch the new directory + if (!m_dir.isEmpty()) + m_watcher->removePath(m_dir); + if (!dir.isEmpty()) + m_watcher->addPath(dir); + + m_dir = dir; + + readDirectory(); + m_dirty = false; + + emit dirChanged(); +} + +QString FileModel::appendPath(QString dirName) +{ + return QDir::cleanPath(QDir(m_dir).absoluteFilePath(dirName)); +} + +void FileModel::setActive(bool active) +{ + if (m_active == active) + return; + + m_active = active; + emit activeChanged(); + + if (m_dirty) + readDirectory(); + + m_dirty = false; +} + +QString FileModel::parentPath() +{ + return QDir::cleanPath(QDir(m_dir).absoluteFilePath("..")); +} + +QString FileModel::fileNameAt(int fileIndex) +{ + if (fileIndex < 0 || fileIndex >= m_files.count()) + return QString(); + + return m_files.at(fileIndex).info.absoluteFilePath(); +} + +void FileModel::refresh() +{ + if (!m_active) { + m_dirty = true; + return; + } + + refreshEntries(); + m_dirty = false; +} + +void FileModel::refreshFull() +{ + if (!m_active) { + m_dirty = true; + return; + } + + readDirectory(); + m_dirty = false; +} + +void FileModel::readDirectory() +{ + // wrapped in reset model methods to get views notified + beginResetModel(); + + m_files.clear(); + m_errorMessage = ""; + + if (!m_dir.isEmpty()) + readEntries(); + + endResetModel(); + emit fileCountChanged(); + emit errorMessageChanged(); +} + +void FileModel::readEntries() +{ + QDir dir(m_dir); + if (!dir.exists()) { + m_errorMessage = tr("Folder does not exist"); + return; + } + if (access(m_dir, R_OK) == -1) { + m_errorMessage = tr("No permission to read the folder"); + return; + } + + QSettings settings; + bool hiddenSetting = settings.value("show-hidden-files", false).toBool(); + QDir::Filter hidden = hiddenSetting ? QDir::Hidden : (QDir::Filter)0; + dir.setFilter(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot | hidden); + + if (settings.value("show-dirs-first", false).toBool()) + dir.setSorting(QDir::Name | QDir::DirsFirst); + + Engine *engine = qApp->property("engine").value(); + + QFileInfoList infoList = dir.entryInfoList(); + foreach (QFileInfo info, infoList) { + if (m_showAll || (info.isDir()) || (info.suffix() == engine->extensionFilter())) { + FileData data; + data.info = info; + m_files.append(data); + } + } +} + +void FileModel::refreshEntries() +{ + m_errorMessage = ""; + + // empty dir name + if (m_dir.isEmpty()) { + beginResetModel(); + m_files.clear(); + endResetModel(); + emit fileCountChanged(); + emit errorMessageChanged(); + return; + } + + QDir dir(m_dir); + if (!dir.exists()) { + m_errorMessage = tr("Folder does not exist"); + emit errorMessageChanged(); + return; + } + if (access(m_dir, R_OK) == -1) { + m_errorMessage = tr("No permission to read the folder"); + emit errorMessageChanged(); + return; + } + + QSettings settings; + bool hiddenSetting = settings.value("show-hidden-files", false).toBool(); + QDir::Filter hidden = hiddenSetting ? QDir::Hidden : (QDir::Filter)0; + dir.setFilter(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot | hidden); + + if (settings.value("show-dirs-first", false).toBool()) + dir.setSorting(QDir::Name | QDir::DirsFirst); + + Engine *engine = qApp->property("engine").value(); + + // read all files + QList newFiles; + QFileInfoList infoList = dir.entryInfoList(); + foreach (QFileInfo info, infoList) { + if ((m_showAll) || (info.isDir()) || (info.suffix() == engine->extensionFilter())) { + FileData data; + data.info = info; + newFiles.append(data); + } + } + + int oldFileCount = m_files.count(); + + // compare old and new files and do removes if needed + for (int i = m_files.count()-1; i >= 0; --i) { + FileData data = m_files.at(i); + if (!newFiles.contains(data)) { + beginRemoveRows(QModelIndex(), i, i); + m_files.removeAt(i); + endRemoveRows(); + } + } + // compare old and new files and do inserts if needed + for (int i = 0; i < newFiles.count(); ++i) { + FileData data = newFiles.at(i); + if (!m_files.contains(data)) { + beginInsertRows(QModelIndex(), i, i); + m_files.insert(i, data); + endInsertRows(); + } + } + + if (m_files.count() != oldFileCount) + emit fileCountChanged(); + + emit errorMessageChanged(); +} + +void FileModel::setShowAll(bool showAll) +{ + if (m_showAll != showAll) { + m_showAll = showAll; + + QSettings settings; + settings.setValue("showAll", m_showAll); + + emit showAllChanged(); + refresh(); + } +}