Reworked to allow separate paths for saving images and videos
authorMohammed Sameer <msameer@foolab.org>
Sat, 10 Aug 2013 22:14:58 +0000 (01:14 +0300)
committerMohammed Sameer <msameer@foolab.org>
Sat, 10 Aug 2013 22:14:58 +0000 (01:14 +0300)
15 files changed:
qml/CameraView.qml
qml/ImageOverlay.qml
qml/MainPage.qml
qml/VideoOverlay.qml
src/filenaming.cpp
src/filenaming.h
src/harmattan/harmattan.pri
src/mountprotector.cpp [moved from src/harmattan/mountprotector.cpp with 59% similarity]
src/mountprotector.h [moved from src/harmattan/mountprotector.h with 81% similarity]
src/platformsettings.cpp
src/platformsettings.h
src/sailfish/mountprotector.cpp [deleted file]
src/sailfish/mountprotector.h [deleted file]
src/sailfish/sailfish.pri
src/src.pro

index 694ee19..a1a6a6c 100644 (file)
@@ -63,7 +63,7 @@ Viewfinder {
 
         onRunningChanged: {
             if (!cam.running) {
-                mountProtector.unlock()
+                mountProtector.unlockAll()
             }
         }
 
index a781b6b..1a889c9 100644 (file)
@@ -46,7 +46,7 @@ Item {
 
         onPreviewAvailable: overlay.previewAvailable(preview)
 
-        onSaved: mountProtector.unlock()
+        onSaved: mountProtector.unlock(fileNaming.imagePath)
     }
 
     ZoomSlider {
@@ -241,7 +241,7 @@ Item {
     }
 
     function cameraError() {
-        mountProtector.unlock()
+        mountProtector.unlock(fileNaming.imagePath)
     }
 
     function policyLost() {
@@ -262,10 +262,10 @@ Item {
         } else if (!fileSystem.available) {
             showError(qsTr("Camera cannot capture images in mass storage mode."))
             cam.autoFocus.stopAutoFocus()
-        } else if (!checkDiskSpace()) {
+        } else if (!fileSystem.hasFreeSpace(fileNaming.imagePath)) {
             showError(qsTr("Not enough space to capture images."))
             cam.autoFocus.stopAutoFocus()
-        } else if (!mountProtector.lock()) {
+        } else if (!mountProtector.lock(fileNaming.imagePath)) {
             showError(qsTr("Failed to lock images directory."))
             cam.autoFocus.stopAutoFocus()
         } else {
@@ -274,7 +274,7 @@ Item {
             var fileName = fileNaming.imageFileName()
             if (!imageMode.capture(fileName)) {
                 showError(qsTr("Failed to capture image. Please restart the camera."))
-                mountProtector.unlock()
+                mountProtector.unlock(fileNaming.imagePath)
                 cam.autoFocus.stopAutoFocus()
             } else {
                 trackerStore.storeImage(fileName)
index 811ba31..c870be0 100644 (file)
@@ -174,11 +174,13 @@ CameraPage {
         id: fileNaming
         imageSuffix: viewfinder.camera.imageSuffix
         videoSuffix: viewfinder.camera.videoSuffix
+        imagePath: platformSettings.imagePath
+        videoPath: platformSettings.videoPath
+        temporaryVideoPath: platformSettings.temporaryVideoPath
     }
 
     MountProtector {
         id: mountProtector
-        path: fileNaming.path
     }
 
     TrackerStore {
@@ -188,10 +190,6 @@ CameraPage {
         model: deviceInfo.model
     }
 
-    function checkDiskSpace() {
-        return fileSystem.hasFreeSpace(fileNaming.path)
-    }
-
     ImageSettings {
         id: imageSettings
         camera: viewfinder.camera
index b80b715..185d079 100644 (file)
@@ -215,7 +215,7 @@ Item {
             if (duration == 3600) {
                 overlay.stopRecording()
                 showError(qsTr("Maximum recording time reached."))
-            } else if (!checkDiskSpace()) {
+            } else if (!fileSystem.hasFreeSpace(fileNaming.temporaryVideoPath)) {
                 page.stopRecording()
                 showError(qsTr("Not enough space to continue recording."))
             }
@@ -241,18 +241,25 @@ Item {
 
         metaData.setMetaData()
 
-        if (!mountProtector.lock()) {
-            showError(qsTr("Failed to lock images directory."))
+        if (!mountProtector.lock(fileNaming.temporaryVideoPath)) {
+            showError(qsTr("Failed to lock temporary videos directory."))
             overlay.recording = false
             return
         }
 
+        if (!mountProtector.lock(fileNaming.videoPath)) {
+            showError(qsTr("Failed to lock videos directory."))
+            overlay.recording = false
+            mountProtector.unlockAll()
+            return
+        }
+
         var file = fileNaming.videoFileName()
         var tmpFile = fileNaming.temporaryVideoFileName()
 
         if (!videoMode.startRecording(file, tmpFile)) {
             showError(qsTr("Failed to record video. Please restart the camera."))
-            mountProtector.unlock()
+            mountProtector.unlockAll()
             overlay.recording = false
             return
         }
@@ -269,7 +276,7 @@ Item {
             showError(qsTr("Camera cannot record videos in mass storage mode."))
         } else if (!checkBattery()) {
             showError(qsTr("Not enough battery to record video."))
-        } else if (!checkDiskSpace()) {
+        } else if (!fileSystem.hasFreeSpace(fileNaming.videoPath) || !fileSystem.hasFreeSpace(fileNaming.temporaryVideoPath)) {
             showError(qsTr("Not enough space to record video."))
         } else {
             recordingDuration.duration = 0
@@ -280,7 +287,7 @@ Item {
 
     function stopRecording() {
         videoMode.stopRecording(true)
-        mountProtector.unlock()
+        mountProtector.unlockAll()
         overlay.recording = false
     }
 
index 3c72211..ab950ac 100644 (file)
@@ -41,37 +41,36 @@ FileNaming::~FileNaming() {
 }
 
 QString FileNaming::imageSuffix() const {
-  return m_image;
+  return m_imageSuffix;
 }
 
 void FileNaming::setImageSuffix(const QString& suffix) {
-  if (m_image != suffix) {
-    m_image = suffix;
+  if (m_imageSuffix != suffix) {
+    m_imageSuffix = suffix;
     emit imageSuffixChanged();
   }
 }
 
 QString FileNaming::videoSuffix() const {
-  return m_video;
+  return m_videoSuffix;
 }
 
 void FileNaming::setVideoSuffix(const QString& suffix) {
-  if (m_video != suffix) {
-    m_video = suffix;
+  if (m_videoSuffix != suffix) {
+    m_videoSuffix = suffix;
     emit videoSuffixChanged();
   }
 }
 
 QString FileNaming::imageFileName() {
-  return fileName(m_image);
+  return fileName(m_imagePath, m_imageSuffix);
 }
 
 QString FileNaming::videoFileName() {
-  return fileName(m_video);
+  return fileName(m_videoPath, m_videoSuffix);
 }
 
-QString FileNaming::fileName(const QString& suffix) {
-  QString path = FileNaming::path();
+QString FileNaming::fileName(const QString& path, const QString& suffix) {
   QString date = QDate::currentDate().toString("yyyyMMdd");
   QDir dir(path);
 
@@ -112,22 +111,6 @@ QString FileNaming::fileName(const QString& suffix) {
   return name;
 }
 
-QString FileNaming::path() {
-  if (m_path.isEmpty()) {
-    m_path = canonicalPath(PATH);
-  }
-
-  return m_path;
-}
-
-QString FileNaming::temporaryPath() {
-  if (m_temp.isEmpty()) {
-    m_temp = canonicalPath(TEMP_PATH);
-  }
-
-  return m_temp;
-}
-
 QString FileNaming::canonicalPath(const QString& path) {
   if (!QDir::root().mkpath(path)) {
     qmlInfo(this) << "Failed to create path" << path;
@@ -148,11 +131,48 @@ QString FileNaming::canonicalPath(const QString& path) {
 }
 
 QString FileNaming::temporaryVideoFileName() {
-  QString path = temporaryPath();
+  if (m_temporaryVideoPath.isEmpty()) {
+    return QString();
+  }
 
-  if (path.isEmpty()) {
-    return path;
+  return QString("%1.cameraplus_video.tmp").arg(m_temporaryVideoPath);
+}
+
+QString FileNaming::imagePath() const {
+  return m_imagePath;
+}
+
+void FileNaming::setImagePath(const QString& path) {
+  QString p = canonicalPath(path);
+
+  if (m_imagePath != p) {
+    m_imagePath = p;
+    emit imagePathChanged();
   }
+}
 
-  return QString("%1.cameraplus_video.tmp").arg(path);
+QString FileNaming::videoPath() const {
+  return m_videoPath;
+}
+
+void FileNaming::setVideoPath(const QString& path) {
+  QString p = canonicalPath(path);
+
+  if (m_videoPath != p) {
+    m_videoPath = p;
+    emit videoPathChanged();
+  }
+}
+
+QString FileNaming::temporaryVideoPath() const {
+  return m_temporaryVideoPath;
+}
+
+void FileNaming::setTemporaryVideoPath(const QString& path) {
+  QString p = canonicalPath(path);
+
+  if (m_temporaryVideoPath != p) {
+    m_temporaryVideoPath = p;
+    emit temporaryVideoPathChanged();
+  }
 }
index d8183ac..d5f7129 100644 (file)
@@ -30,7 +30,9 @@ class FileNaming : public QObject {
 
   Q_PROPERTY(QString imageSuffix READ imageSuffix WRITE setImageSuffix NOTIFY imageSuffixChanged);
   Q_PROPERTY(QString videoSuffix READ videoSuffix WRITE setVideoSuffix NOTIFY videoSuffixChanged);
-  Q_PROPERTY(QString path READ path CONSTANT);
+  Q_PROPERTY(QString imagePath READ imagePath WRITE setImagePath NOTIFY imagePathChanged);
+  Q_PROPERTY(QString videoPath READ videoPath WRITE setVideoPath NOTIFY videoPathChanged);
+  Q_PROPERTY(QString temporaryVideoPath READ temporaryVideoPath WRITE setTemporaryVideoPath NOTIFY temporaryVideoPathChanged);
 
 public:
   FileNaming(QObject *parent = 0);
@@ -46,21 +48,32 @@ public:
   Q_INVOKABLE QString videoFileName();
   Q_INVOKABLE QString temporaryVideoFileName();
 
-  QString path();
-  QString temporaryPath();
+  QString imagePath() const;
+  void setImagePath(const QString& path);
+
+  QString videoPath() const;
+  void setVideoPath(const QString& path);
+
+  QString temporaryVideoPath() const;
+  void setTemporaryVideoPath(const QString& path);
 
 signals:
   void imageSuffixChanged();
   void videoSuffixChanged();
+  void imagePathChanged();
+  void videoPathChanged();
+  void temporaryVideoPathChanged();
 
 private:
-  QString fileName(const QString& suffix);
+  QString fileName(const QString& path, const QString& suffix);
   QString canonicalPath(const QString& path);
+  QString temporaryPath();
 
-  QString m_image;
-  QString m_video;
-  QString m_path;
-  QString m_temp;
+  QString m_imageSuffix;
+  QString m_videoSuffix;
+  QString m_imagePath;
+  QString m_videoPath;
+  QString m_temporaryVideoPath;
 
   QString m_date;
   int m_index;
index 36ac51c..8569111 100644 (file)
@@ -4,9 +4,9 @@ INCLUDEPATH += harmattan .
 PKGCONFIG += quill contextsubscriber-1.0 QtLocation QtSystemInfo
 
 HEADERS += quillitem.h soundvolumecontrol.h deviceinfo.h geocode.h \
-          mountprotector.h batteryinfo.h compass.h devicekeys.h \
+          batteryinfo.h compass.h devicekeys.h \
           displaystate.h fsmonitor.h orientation.h
 
 SOURCES += quillitem.cpp soundvolumecontrol.cpp deviceinfo.cpp geocode.cpp \
-          mountprotector.cpp batteryinfo.cpp compass.cpp devicekeys.cpp \
+          batteryinfo.cpp compass.cpp devicekeys.cpp \
           displaystate.cpp fsmonitor.cpp orientation.cpp
similarity index 59%
rename from src/harmattan/mountprotector.cpp
rename to src/mountprotector.cpp
index ad7d135..c9c8402 100644 (file)
 #endif
 
 MountProtector::MountProtector(QObject *parent) :
-  QObject(parent), m_file(0) {
+  QObject(parent) {
 
 }
 
 MountProtector::~MountProtector() {
-  unlock();
+  unlockAll();
 }
 
-QString MountProtector::path() const {
-  return m_path;
-}
-
-void MountProtector::setPath(const QString& path) {
-  if (m_path != path) {
-    m_path = path;
-    emit pathChanged();
+bool MountProtector::lock(const QString& path) {
+  if (path.isEmpty()) {
+    qmlInfo(this) << "Cannot lock an empty path";
+    return false;
   }
-}
 
-bool MountProtector::lock() {
-  if (m_file) {
-    return true;
-  }
+  QString p = QString("%1%2.cameraplus_tmp_XXXXXX").arg(path).arg(QDir::separator());
+  QTemporaryFile *file = new QTemporaryFile(p);
+  file->setAutoRemove(true);
 
-  if (m_path.isEmpty()) {
+  if (!file->open()) {
+    qmlInfo(this) << "Failed to lock" << file->errorString();
+    delete file;
+    file = 0;
     return false;
   }
 
-  QString path = QString("%1%2.cameraplus_tmp_XXXXXX").arg(m_path).arg(QDir::separator());
-  m_file = new QTemporaryFile(path);
-  m_file->setAutoRemove(true);
-  if (!m_file->open()) {
-    qmlInfo(this) << "Failed to lock" << m_file->errorString();
-    delete m_file;
-    m_file = 0;
-    return false;
+  if (!QFile::remove(file->fileName())) {
+    qmlInfo(this) << "Failed to remove temporarily file" << file->fileName();
   }
 
-  if (!QFile::remove(m_file->fileName())) {
-    qmlInfo(this) << "Failed to remove temporarily file" << m_file->fileName();
-  }
+  m_locks.insert(path, file);
 
   return true;
 }
 
-void MountProtector::unlock() {
-  if (m_file) {
-    delete m_file;
-    m_file = 0;
+void MountProtector::unlock(const QString& path) {
+  QTemporaryFile *file = m_locks.take(path);
+
+  if (file) {
+    delete file;
   }
 }
+
+void MountProtector::unlockAll() {
+  qDeleteAll(m_locks);
+
+  m_locks.clear();
+}
similarity index 81%
rename from src/harmattan/mountprotector.h
rename to src/mountprotector.h
index 4449e78..33ff379 100644 (file)
 #define MOUNT_PROTECTOR_H
 
 #include <QObject>
+#include <QMultiMap>
+
 class QTemporaryFile;
 
 class MountProtector : public QObject {
   Q_OBJECT
 
-  Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged);
-
 public:
   MountProtector(QObject *parent = 0);
   ~MountProtector();
 
-  QString path() const;
-  void setPath(const QString& path);
-
-  Q_INVOKABLE bool lock();
+  Q_INVOKABLE bool lock(const QString& path);
 
 public slots:
-  void unlock();
-
-signals:
-  void pathChanged();
+  void unlock(const QString& path);
+  void unlockAll();
 
 private:
-  QString m_path;
-  QTemporaryFile *m_file;
+  QMultiMap<QString, QTemporaryFile *> m_locks;
 };
 
 #endif /* MOUNT_PROTECTOR_H */
index c566fde..18e5a64 100644 (file)
 #define DBUS_THUMBNAILING_ENABLED                true
 #define BACKGROUND_RENDERING_COLOR               QColor(Qt::black)
 
+#ifdef HARMATTAN
+#define IMAGE_PATH QString("%1%2MyDocs%2DCIM%2").arg(QDir::homePath()).arg(QDir::separator())
+#define VIDEO_PATH IMAGE_PATH
+#define TEMP_VIDEO QString("%1%2MyDocs%2.cameraplus%2").arg(QDir::homePath()).arg(QDir::separator())
+#endif
+
+#ifdef SAILFISH
+#define IMAGE_PATH QString("%1%2Pictures%2Camera%2").arg(QDir::homePath()).arg(QDir::separator())
+#define VIDEO_PATH QString("%1%2Videos%2Camera%2").arg(QDir::homePath()).arg(QDir::separator())
+#define TEMP_VIDEO VIDEO_PATH
+#endif
+
 PlatformSettings::PlatformSettings(QObject *parent) :
   QObject(parent), m_settings(new QSettings(PATH, QSettings::IniFormat)) {
 
@@ -147,3 +159,15 @@ QString PlatformSettings::videoRecordingEndedSound() const {
 QString PlatformSettings::autoFocusAcquiredSound() const {
   return m_settings->value("sounds/autoFocusAcquired").toString();
 }
+
+QString PlatformSettings::imagePath() const {
+  return IMAGE_PATH;
+}
+
+QString PlatformSettings::videoPath() const {
+  return VIDEO_PATH;
+}
+
+QString PlatformSettings::temporaryVideoPath() const {
+  return TEMP_VIDEO;
+}
index 338f1ee..b3b6898 100644 (file)
@@ -37,6 +37,9 @@ class PlatformSettings : public QObject {
   Q_PROPERTY(QString videoRecordingStartedSound READ videoRecordingStartedSound CONSTANT);
   Q_PROPERTY(QString videoRecordingEndedSound READ videoRecordingEndedSound CONSTANT);
   Q_PROPERTY(QString autoFocusAcquiredSound READ autoFocusAcquiredSound CONSTANT);
+  Q_PROPERTY(QString imagePath READ imagePath CONSTANT);
+  Q_PROPERTY(QString videoPath READ videoPath CONSTANT);
+  Q_PROPERTY(QString temporaryVideoPath READ temporaryVideoPath CONSTANT);
 
 public:
   PlatformSettings(QObject *parent = 0);
@@ -69,6 +72,10 @@ public:
   QString videoRecordingEndedSound() const;
   QString autoFocusAcquiredSound() const;
 
+  QString imagePath() const;
+  QString videoPath() const;
+  QString temporaryVideoPath() const;
+
 public slots:
   void init();
 
diff --git a/src/sailfish/mountprotector.cpp b/src/sailfish/mountprotector.cpp
deleted file mode 100644 (file)
index ad7d135..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*!
- * This file is part of CameraPlus.
- *
- * Copyright (C) 2012-2013 Mohammed Sameer <msameer@foolab.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include "mountprotector.h"
-#include <QDir>
-#include <QTemporaryFile>
-#if defined(QT4)
-#include <QDeclarativeInfo>
-#elif defined(QT5)
-#include <QQmlInfo>
-#endif
-
-MountProtector::MountProtector(QObject *parent) :
-  QObject(parent), m_file(0) {
-
-}
-
-MountProtector::~MountProtector() {
-  unlock();
-}
-
-QString MountProtector::path() const {
-  return m_path;
-}
-
-void MountProtector::setPath(const QString& path) {
-  if (m_path != path) {
-    m_path = path;
-    emit pathChanged();
-  }
-}
-
-bool MountProtector::lock() {
-  if (m_file) {
-    return true;
-  }
-
-  if (m_path.isEmpty()) {
-    return false;
-  }
-
-  QString path = QString("%1%2.cameraplus_tmp_XXXXXX").arg(m_path).arg(QDir::separator());
-  m_file = new QTemporaryFile(path);
-  m_file->setAutoRemove(true);
-  if (!m_file->open()) {
-    qmlInfo(this) << "Failed to lock" << m_file->errorString();
-    delete m_file;
-    m_file = 0;
-    return false;
-  }
-
-  if (!QFile::remove(m_file->fileName())) {
-    qmlInfo(this) << "Failed to remove temporarily file" << m_file->fileName();
-  }
-
-  return true;
-}
-
-void MountProtector::unlock() {
-  if (m_file) {
-    delete m_file;
-    m_file = 0;
-  }
-}
diff --git a/src/sailfish/mountprotector.h b/src/sailfish/mountprotector.h
deleted file mode 100644 (file)
index 4449e78..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-// -*- c++ -*-
-
-/*!
- * This file is part of CameraPlus.
- *
- * Copyright (C) 2012-2013 Mohammed Sameer <msameer@foolab.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef MOUNT_PROTECTOR_H
-#define MOUNT_PROTECTOR_H
-
-#include <QObject>
-class QTemporaryFile;
-
-class MountProtector : public QObject {
-  Q_OBJECT
-
-  Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged);
-
-public:
-  MountProtector(QObject *parent = 0);
-  ~MountProtector();
-
-  QString path() const;
-  void setPath(const QString& path);
-
-  Q_INVOKABLE bool lock();
-
-public slots:
-  void unlock();
-
-signals:
-  void pathChanged();
-
-private:
-  QString m_path;
-  QTemporaryFile *m_file;
-};
-
-#endif /* MOUNT_PROTECTOR_H */
index 23d4380..56695ae 100644 (file)
@@ -10,7 +10,6 @@ HEADERS += sailfish/soundvolumecontrol.h \
            sailfish/fsmonitor.h \
            sailfish/compass.h \
            sailfish/orientation.h \
-           sailfish/mountprotector.h \
            sailfish/batteryinfo.h \
            sailfish/devicekeys.h
 
@@ -21,6 +20,5 @@ SOURCES += sailfish/soundvolumecontrol.cpp \
            sailfish/fsmonitor.cpp \
            sailfish/compass.cpp \
            sailfish/orientation.cpp \
-           sailfish/mountprotector.cpp \
            sailfish/batteryinfo.cpp \
            sailfish/devicekeys.cpp
index 601da44..6dc0dd0 100644 (file)
@@ -21,12 +21,14 @@ SOURCES += main.cpp \
            settings.cpp filenaming.cpp cameraresources.cpp \
            trackerstore.cpp focusrectangle.cpp sharehelper.cpp \
            deletehelper.cpp galleryhelper.cpp postcapturemodel.cpp \
-           gridlines.cpp platformsettings.cpp dbusservice.cpp
+           gridlines.cpp platformsettings.cpp dbusservice.cpp \
+           mountprotector.cpp
 
 HEADERS += settings.h filenaming.h cameraresources.h \
            trackerstore.h focusrectangle.h sharehelper.h \
            deletehelper.h galleryhelper.h postcapturemodel.h \
-           gridlines.h platformsettings.h dbusservice.h
+           gridlines.h platformsettings.h dbusservice.h \
+           mountprotector.h
 
 RESOURCES += ../qml/qml.qrc