Skip to content

Commit

Permalink
Merge branch 'jb5771' into 'master'
Browse files Browse the repository at this point in the history
[filemanager] Add engine for file manager. Contributes to JB#5771



See merge request !2
  • Loading branch information
jpetrell committed Mar 24, 2016
2 parents 290df73 + c352f00 commit 57e4afb
Show file tree
Hide file tree
Showing 23 changed files with 1,997 additions and 0 deletions.
4 changes: 4 additions & 0 deletions filemanager.pro
@@ -0,0 +1,4 @@
TEMPLATE = subdirs
SUBDIRS = src tests

OTHER_FILES = rpm/*.spec
47 changes: 47 additions & 0 deletions rpm/nemo-qml-plugin-filemanager.spec
@@ -0,0 +1,47 @@
Name: nemo-qml-plugin-filemanager
Summary: File manager plugin for Nemo Mobile
Version: 0.0.0
Release: 1
Group: System/Libraries
License: BSD
URL: https://git.merproject.org/mer-core/nemo-qml-plugin-filemanager
Source0: %{name}-%{version}.tar.bz2
BuildRequires: pkgconfig(Qt5Core)
BuildRequires: pkgconfig(Qt5Gui)
BuildRequires: pkgconfig(Qt5Qml)
BuildRequires: pkgconfig(Qt5Test)

%description
%{summary}.

%package tests
Summary: File manager plugin tests
Group: System/Libraries
Requires: %{name} = %{version}-%{release}

%description tests
%{summary}.

%prep
%setup -q -n %{name}-%{version}

%build

%qmake5

make %{?_smp_mflags}

%install
rm -rf %{buildroot}
%qmake5_install
chmod o+w -R %{buildroot}/opt/tests/nemo-qml-plugins/filemanager/auto/folder
chmod o-r -R %{buildroot}/opt/tests/nemo-qml-plugins/filemanager/auto/hiddenfolder

%files
%defattr(-,root,root,-)
%{_libdir}/qt5/qml/Nemo/FileManager/libnemofilemanager.so
%{_libdir}/qt5/qml/Nemo/FileManager/qmldir

%files tests
%defattr(-,root,root,-)
/opt/tests/nemo-qml-plugins/filemanager/
217 changes: 217 additions & 0 deletions src/fileengine.cpp
@@ -0,0 +1,217 @@
/*
* Copyright (C) 2016 Jolla Ltd.
* Contact: Joona Petrell <joona.petrell@jollamobile.com>
*
* You may use this file under the terms of the BSD license as follows:
*
* "Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Jolla Ltd. nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
*/

#include "fileengine.h"
#include "fileworker.h"
#include "statfileinfo.h"
#include <QDateTime>
#include <QDebug>
#include <QQmlInfo>
#include <QStandardPaths>
#include <QTextStream>
#include <unistd.h>

Q_GLOBAL_STATIC(FileEngine, engine);


FileEngine::FileEngine(QObject *parent) :
QObject(parent),
m_clipboardContainsCopy(false)
{
m_fileWorker = new FileWorker(this);


// pass worker end signals to QML
connect(m_fileWorker, &FileWorker::done, this, &FileEngine::workerDone);
connect(m_fileWorker, &FileWorker::cancelled, this, &FileEngine::cancelled);
connect(m_fileWorker, &FileWorker::error, this, &FileEngine::error);

connect(m_fileWorker, &FileWorker::started, this, &FileEngine::busyChanged);
connect(m_fileWorker, &FileWorker::finished, this, &FileEngine::busyChanged);

connect(m_fileWorker, &FileWorker::fileDeleted, this, &FileEngine::fileDeleted);
}

FileEngine::~FileEngine()
{
// is this the way to force stop the worker thread?
m_fileWorker->cancel(); // stop possibly running background thread
m_fileWorker->wait(); // wait until thread stops
}

FileEngine *FileEngine::instance()
{
return engine();
}

bool FileEngine::busy() const
{
return m_fileWorker->isRunning();
}

void FileEngine::deleteFiles(QStringList fileNames)
{
m_fileWorker->startDeleteFiles(fileNames);
}

void FileEngine::cutFiles(QStringList fileNames)
{
m_clipboardFiles = fileNames;
m_clipboardContainsCopy = false;
emit clipboardCountChanged();
emit clipboardContainsCopyChanged();
}

void FileEngine::copyFiles(QStringList fileNames)
{
// don't copy special files (chr/blk/fifo/sock)
QMutableStringListIterator i(fileNames);
while (i.hasNext()) {
QString fileName = i.next();
StatFileInfo info(fileName);
if (info.isSystem())
i.remove();
}

if (!fileNames.isEmpty()) {
m_clipboardFiles = fileNames;
m_clipboardContainsCopy = true;
emit clipboardCountChanged();
emit clipboardContainsCopyChanged();
}
}

void FileEngine::pasteFiles(QString destDirectory)
{
if (m_clipboardFiles.isEmpty()) {
qmlInfo(this) << "Paste called with empty clipboard.";
return;
}

QStringList files = m_clipboardFiles;

QDir dest(destDirectory);
if (!dest.exists()) {
qmlInfo(this) << "Paste destination doesn't exists";
return;
}

foreach (QString fileName, files) {
QFileInfo fileInfo(fileName);
QString newName = dest.absoluteFilePath(fileInfo.fileName());

// source and dest fileNames are the same?
if (fileName == newName) {
qmlInfo(this) << "Paste can't overwrite itself";
return;
}

// dest is under source? (directory)
if (newName.startsWith(fileName)) {
emit error(ErrorCannotCopyIntoItself, fileName);
return;
}
}

m_clipboardFiles.clear();
emit clipboardCountChanged();

if (m_clipboardContainsCopy) {
m_fileWorker->startCopyFiles(files, destDirectory);
return;
}

m_fileWorker->startMoveFiles(files, destDirectory);
}

void FileEngine::cancel()
{
m_fileWorker->cancel();
}

bool FileEngine::exists(QString fileName)
{
if (fileName.isEmpty()) {
return false;
}

return QFile::exists(fileName);
}

bool FileEngine::mkdir(QString path, QString name)
{
QDir dir(path);

if (!dir.mkdir(name)) {
emit error(ErrorFolderCreationFailed, name);
return false;
}

return true;
}

bool FileEngine::rename(QString fullOldFileName, QString newName)
{
QFile file(fullOldFileName);
QFileInfo fileInfo(fullOldFileName);
QDir dir = fileInfo.absoluteDir();
QString fullNewFileName = dir.absoluteFilePath(newName);

if (!file.rename(fullNewFileName)) {
emit error(ErrorRenameFailed, fileInfo.fileName());
return false;
}
return true;
}

bool FileEngine::chmod(QString path,
bool ownerRead, bool ownerWrite, bool ownerExecute,
bool groupRead, bool groupWrite, bool groupExecute,
bool othersRead, bool othersWrite, bool othersExecute)
{
QFile file(path);
QFileDevice::Permissions p;
if (ownerRead) p |= QFileDevice::ReadOwner;
if (ownerWrite) p |= QFileDevice::WriteOwner;
if (ownerExecute) p |= QFileDevice::ExeOwner;
if (groupRead) p |= QFileDevice::ReadGroup;
if (groupWrite) p |= QFileDevice::WriteGroup;
if (groupExecute) p |= QFileDevice::ExeGroup;
if (othersRead) p |= QFileDevice::ReadOther;
if (othersWrite) p |= QFileDevice::WriteOther;
if (othersExecute) p |= QFileDevice::ExeOther;
if (!file.setPermissions(p)) {
emit error(ErrorChmodFailed, path);
return false;
}
return true;
}
112 changes: 112 additions & 0 deletions src/fileengine.h
@@ -0,0 +1,112 @@
/*
* Copyright (C) 2016 Jolla Ltd.
* Contact: Joona Petrell <joona.petrell@jollamobile.com>
*
* You may use this file under the terms of the BSD license as follows:
*
* "Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Jolla Ltd. nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
*/

#ifndef ENGINE_H
#define ENGINE_H

#include <QDir>
#include <QVariant>

class FileWorker;

/**
* @brief FileEngine to handle file operations, settings and other generic functionality.
*/
class FileEngine : public QObject
{
Q_OBJECT
Q_PROPERTY(int clipboardCount READ clipboardCount NOTIFY clipboardCountChanged)
Q_PROPERTY(bool clipboardContainsCopy READ clipboardContainsCopy NOTIFY clipboardContainsCopyChanged)
Q_PROPERTY(bool busy READ busy NOTIFY busyChanged)

Q_ENUMS(Error)
public:
explicit FileEngine(QObject *parent = 0);
~FileEngine();

enum Error {
NoError,
ErrorOperationInProgress,
ErrorCopyFailed,
ErrorDeleteFailed,
ErrorMoveFailed,
ErrorRenameFailed,
ErrorCannotCopyIntoItself,
ErrorFolderCopyFailed,
ErrorFolderCreationFailed,
ErrorChmodFailed
};

// properties
int clipboardCount() const { return m_clipboardFiles.count(); }
bool clipboardContainsCopy() const { return m_clipboardContainsCopy; }
bool busy() const;

// For C++
static FileEngine *instance();

// methods accessible from QML

// asynch methods send signals when done or error occurs
Q_INVOKABLE void deleteFiles(QStringList fileNames);
Q_INVOKABLE void cutFiles(QStringList fileNames);
Q_INVOKABLE void copyFiles(QStringList fileNames);
Q_INVOKABLE void pasteFiles(QString destDirectory);

// cancel asynch methods
Q_INVOKABLE void cancel();

// synchronous methods
Q_INVOKABLE bool exists(QString fileName);
Q_INVOKABLE bool mkdir(QString path, QString name);
Q_INVOKABLE bool rename(QString fullOldFileName, QString newName);
Q_INVOKABLE bool chmod(QString path,
bool ownerRead, bool ownerWrite, bool ownerExecute,
bool groupRead, bool groupWrite, bool groupExecute,
bool othersRead, bool othersWrite, bool othersExecute);

signals:
void clipboardCountChanged();
void clipboardContainsCopyChanged();
void workerDone();
void error(Error error, QString fileName);
void fileDeleted(QString fullname);
void cancelled();
void busyChanged();

private:
QStringList m_clipboardFiles;
bool m_clipboardContainsCopy;
FileWorker *m_fileWorker;
};

#endif // ENGINE_H

0 comments on commit 57e4afb

Please sign in to comment.