Merge lp:~uriboni/camera-app/sd-card-checks into lp:camera-app/staging

Proposed by Ugo Riboni
Status: Merged
Approved by: Florian Boucault
Approved revision: 653
Merged at revision: 647
Proposed branch: lp:~uriboni/camera-app/sd-card-checks
Merge into: lp:camera-app/staging
Diff against target: 1739 lines (+299/-1151)
16 files modified
CameraApp/CMakeLists.txt (+2/-4)
CameraApp/components.cpp (+9/-0)
CameraApp/qstorageinfo.cpp (+0/-378)
CameraApp/qstorageinfo.h (+0/-102)
CameraApp/qstorageinfo_p.h (+0/-84)
CameraApp/qstorageinfo_unix.cpp (+0/-442)
CameraApp/storagelocations.cpp (+121/-0)
CameraApp/storagelocations.h (+50/-0)
CameraApp/storagemonitor.cpp (+34/-1)
CameraApp/storagemonitor.h (+5/-0)
GalleryView.qml (+3/-3)
ViewFinderOverlay.qml (+30/-13)
ViewFinderView.qml (+29/-1)
cameraapplication.cpp (+0/-106)
cameraapplication.h (+0/-15)
tests/unittests/qstorageinfo_stub.cpp (+16/-2)
To merge this branch: bzr merge lp:~uriboni/camera-app/sd-card-checks
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Ubuntu Phablet Team Pending
Review via email: mp+285714@code.launchpad.net

Commit message

Display error messages when disk write fails and when SD card is not writeable when switching to it.

Description of the change

Display error messages when disk write fails and when SD card is not writeable when switching to it.

To post a comment you must log in.
652. By Ugo Riboni

Display a warning message on failed video captures too

653. By Ugo Riboni

Export mode should not have any warning for external media not being writeable

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CameraApp/CMakeLists.txt'
2--- CameraApp/CMakeLists.txt 2015-11-18 06:44:35 +0000
3+++ CameraApp/CMakeLists.txt 2016-02-11 13:25:08 +0000
4@@ -7,8 +7,7 @@
5 fileoperations.cpp
6 foldersmodel.cpp
7 storagemonitor.cpp
8- qstorageinfo.cpp
9- qstorageinfo_unix.cpp
10+ storagelocations.cpp
11 )
12
13 set(plugin_HDRS
14@@ -17,8 +16,7 @@
15 fileoperations.h
16 foldersmodel.h
17 storagemonitor.h
18- qstorageinfo.h
19- qstorageinfo_p.h
20+ storagelocations.h
21 )
22
23 add_library(camera-qml SHARED ${plugin_SRCS} ${plugin_HDRS})
24
25=== modified file 'CameraApp/components.cpp'
26--- CameraApp/components.cpp 2015-01-22 16:15:08 +0000
27+++ CameraApp/components.cpp 2016-02-11 13:25:08 +0000
28@@ -24,6 +24,14 @@
29 #include "fileoperations.h"
30 #include "foldersmodel.h"
31 #include "storagemonitor.h"
32+#include "storagelocations.h"
33+
34+static QObject* StorageLocations_singleton_factory(QQmlEngine* engine, QJSEngine* scriptEngine)
35+{
36+ Q_UNUSED(engine);
37+ Q_UNUSED(scriptEngine);
38+ return new StorageLocations();
39+}
40
41 void Components::registerTypes(const char *uri)
42 {
43@@ -34,6 +42,7 @@
44 qmlRegisterType<FileOperations>(uri, 0, 1, "FileOperations");
45 qmlRegisterType<FoldersModel>(uri, 0, 1, "FoldersModel");
46 qmlRegisterType<StorageMonitor>(uri, 0, 1, "StorageMonitor");
47+ qmlRegisterSingletonType<StorageLocations>(uri, 0, 1, "StorageLocations", StorageLocations_singleton_factory);
48 }
49
50 void Components::initializeEngine(QQmlEngine *engine, const char *uri)
51
52=== removed file 'CameraApp/qstorageinfo.cpp'
53--- CameraApp/qstorageinfo.cpp 2015-01-27 14:34:31 +0000
54+++ CameraApp/qstorageinfo.cpp 1970-01-01 00:00:00 +0000
55@@ -1,378 +0,0 @@
56-/****************************************************************************
57-**
58-** Copyright (C) 2014 Ivan Komissarov <ABBAPOH@gmail.com>
59-** Contact: http://www.qt-project.org/legal
60-**
61-** This file is part of the QtCore module of the Qt Toolkit.
62-**
63-** This program is free software; you can redistribute it and/or modify
64-** it under the terms of the GNU General Public License as published by
65-** the Free Software Foundation; version 3.
66-**
67-** This program is distributed in the hope that it will be useful,
68-** but WITHOUT ANY WARRANTY; without even the implied warranty of
69-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
70-** GNU General Public License for more details.
71-**
72-** You should have received a copy of the GNU General Public License
73-** along with this program. If not, see <http://www.gnu.org/licenses/>.
74-**
75-****************************************************************************/
76-
77-#include "qstorageinfo.h"
78-#include "qstorageinfo_p.h"
79-
80-QT_BEGIN_NAMESPACE
81-
82-/*!
83- \class QStorageInfo
84- \inmodule QtCore
85- \since 5.4
86- \brief Provides information about currently mounted storage and drives.
87-
88- \ingroup io
89- \ingroup shared
90-
91- Allows retrieving information about the volume's space, its mount point,
92- label, and filesystem name.
93-
94- You can create an instance of QStorageInfo by passing the path to the
95- volume's mount point as a constructor parameter, or you can set it using
96- the setPath() method. The static mountedVolumes() method can be used to get the
97- list of all mounted filesystems.
98-
99- QStorageInfo always caches the retrieved information, but you can call
100- refresh() to invalidate the cache.
101-
102- The following example retrieves the most common information about the root
103- volume of the system, and prints information about it.
104-
105- \snippet code/src_corelib_io_qstorageinfo.cpp 2
106-*/
107-
108-/*!
109- Constructs an empty QStorageInfo object.
110-
111- Objects created with the default constructor will be invalid and therefore
112- not ready for use.
113-
114- \sa setPath(), isReady(), isValid()
115-*/
116-QStorageInfo::QStorageInfo()
117- : d(new QStorageInfoPrivate)
118-{
119-}
120-
121-/*!
122- Constructs a new QStorageInfo object that gives information about the volume
123- mounted at \a path.
124-
125- If you pass a directory or file, the QStorageInfo object will refer to the
126- volume where this directory or file is located.
127- You can check if the created object is correct using the isValid() method.
128-
129- The following example shows how to get the volume on which the application is
130- located. It is recommended to always check that the volume is ready and valid.
131-
132- \snippet code/src_corelib_io_qstorageinfo.cpp 0
133-
134- \sa setPath()
135-*/
136-QStorageInfo::QStorageInfo(const QString &path)
137- : d(new QStorageInfoPrivate)
138-{
139- setPath(path);
140-}
141-
142-/*!
143- Constructs a new QStorageInfo object that gives information about the volume
144- containing the \a dir folder.
145-*/
146-QStorageInfo::QStorageInfo(const QDir &dir)
147- : d(new QStorageInfoPrivate)
148-{
149- setPath(dir.absolutePath());
150-}
151-
152-/*!
153- Constructs a new QStorageInfo object that is a copy of the \a other QStorageInfo object.
154-*/
155-QStorageInfo::QStorageInfo(const QStorageInfo &other)
156- : d(other.d)
157-{
158-}
159-
160-/*!
161- Destroys the QStorageInfo object and frees its resources.
162-*/
163-QStorageInfo::~QStorageInfo()
164-{
165-}
166-
167-/*!
168- Makes a copy of the QStorageInfo object \a other and assigns it to this QStorageInfo object.
169-*/
170-QStorageInfo &QStorageInfo::operator=(const QStorageInfo &other)
171-{
172- d = other.d;
173- return *this;
174-}
175-
176-/*!
177- \fn QStorageInfo &QStorageInfo::operator=(QStorageInfo &&other)
178-
179- Assigns \a other to this QStorageInfo instance.
180-*/
181-
182-/*!
183- \fn void QStorageInfo::swap(QStorageInfo &other)
184-
185- Swaps this volume info with \a other. This function is very fast and
186- never fails.
187-*/
188-
189-/*!
190- Sets this QStorageInfo object to the filesystem mounted where \a path is located.
191-
192- \a path can either be a root path of the filesystem, a directory, or a file
193- within that filesystem.
194-
195- \sa rootPath()
196-*/
197-void QStorageInfo::setPath(const QString &path)
198-{
199- if (d->rootPath == path)
200- return;
201- d.detach();
202- d->rootPath = path;
203- d->doStat();
204-}
205-
206-/*!
207- Returns the mount point of the filesystem this QStorageInfo object
208- represents.
209-
210- On Windows, it returns the volume letter in case the volume is not mounted to
211- a directory.
212-
213- Note that the value returned by rootPath() is the real mount point of a
214- volume, and may not be equal to the value passed to the constructor or setPath()
215- method. For example, if you have only the root volume in the system, and
216- pass '/directory' to setPath(), then this method will return '/'.
217-
218- \sa setPath(), device()
219-*/
220-QString QStorageInfo::rootPath() const
221-{
222- return d->rootPath;
223-}
224-
225-/*!
226- Returns the size (in bytes) available for the current user. It returns
227- the total size available if the user is the root user or a system administrator.
228-
229- This size can be less than or equal to the free size returned by
230- bytesFree() function.
231-
232- \sa bytesTotal(), bytesFree()
233-*/
234-qint64 QStorageInfo::bytesAvailable() const
235-{
236- return d->bytesAvailable;
237-}
238-
239-/*!
240- Returns the number of free bytes in a volume. Note that if there are
241- quotas on the filesystem, this value can be larger than the value
242- returned by bytesAvailable().
243-
244- \sa bytesTotal(), bytesAvailable()
245-*/
246-qint64 QStorageInfo::bytesFree() const
247-{
248- return d->bytesFree;
249-}
250-
251-/*!
252- Returns the total volume size in bytes.
253-
254- \sa bytesFree(), bytesAvailable()
255-*/
256-qint64 QStorageInfo::bytesTotal() const
257-{
258- return d->bytesTotal;
259-}
260-
261-/*!
262- Returns the type name of the filesystem.
263-
264- This is a platform-dependent function, and filesystem names can vary
265- between different operating systems. For example, on Windows filesystems
266- they can be named \c NTFS, and on Linux they can be named \c ntfs-3g or \c fuseblk.
267-
268- \sa name()
269-*/
270-QByteArray QStorageInfo::fileSystemType() const
271-{
272- return d->fileSystemType;
273-}
274-
275-/*!
276- Returns the device for this volume.
277-
278- For example, on Unix filesystems (including OS X), this returns the
279- devpath like \c /dev/sda0 for local storages. On Windows, it returns the UNC
280- path starting with \c \\\\?\\ for local storages (in other words, the volume GUID).
281-
282- \sa rootPath()
283-*/
284-QByteArray QStorageInfo::device() const
285-{
286- return d->device;
287-}
288-
289-/*!
290- Returns the human-readable name of a filesystem, usually called \c label.
291-
292- Not all filesystems support this feature. In this case, the value returned by
293- this method could be empty. An empty string is returned if the file system
294- does not support labels, or if no label is set.
295-
296- On Linux, retrieving the volume's label requires \c udev to be present in the
297- system.
298-
299- \sa fileSystemType()
300-*/
301-QString QStorageInfo::name() const
302-{
303- return d->name;
304-}
305-
306-/*!
307- Returns the volume's name, if available, or the root path if not.
308-*/
309-QString QStorageInfo::displayName() const
310-{
311- if (!d->name.isEmpty())
312- return d->name;
313- return d->rootPath;
314-}
315-
316-/*!
317- \fn bool QStorageInfo::isRoot() const
318-
319- Returns true if this QStorageInfo represents the system root volume; false
320- otherwise.
321-
322- On Unix filesystems, the root volume is a volume mounted on \c /. On Windows,
323- the root volume is the volume where the OS is installed.
324-
325- \sa root()
326-*/
327-
328-/*!
329- Returns true if the current filesystem is protected from writing; false
330- otherwise.
331-*/
332-bool QStorageInfo::isReadOnly() const
333-{
334- return d->readOnly;
335-}
336-
337-/*!
338- Returns true if the current filesystem is ready to work; false otherwise. For
339- example, false is returned if the CD volume is not inserted.
340-
341- Note that fileSystemType(), name(), bytesTotal(), bytesFree(), and
342- bytesAvailable() will return invalid data until the volume is ready.
343-
344- \sa isValid()
345-*/
346-bool QStorageInfo::isReady() const
347-{
348- return d->ready;
349-}
350-
351-/*!
352- Returns true if the QStorageInfo specified by rootPath exists and is mounted
353- correctly.
354-
355- \sa isReady()
356-*/
357-bool QStorageInfo::isValid() const
358-{
359- return d->valid;
360-}
361-
362-/*!
363- Resets QStorageInfo's internal cache.
364-
365- QStorageInfo caches information about storage to speed up performance.
366- QStorageInfo retrieves information during object construction and/or when calling
367- the setPath() method. You have to manually reset the cache by calling this
368- function to update storage information.
369-*/
370-void QStorageInfo::refresh()
371-{
372- d.detach();
373- d->doStat();
374-}
375-
376-/*!
377- Returns the list of QStorageInfo objects that corresponds to the list of currently
378- mounted filesystems.
379-
380- On Windows, this returns the drives visible in the \gui{My Computer} folder. On Unix
381- operating systems, it returns the list of all mounted filesystems (except for
382- pseudo filesystems).
383-
384- Returns all currently mounted filesystems by default.
385-
386- The example shows how to retrieve all available filesystems, skipping read-only ones.
387-
388- \snippet code/src_corelib_io_qstorageinfo.cpp 1
389-
390- \sa root()
391-*/
392-QList<QStorageInfo> QStorageInfo::mountedVolumes()
393-{
394- return QStorageInfoPrivate::mountedVolumes();
395-}
396-
397-Q_GLOBAL_STATIC_WITH_ARGS(QStorageInfo, getRoot, (QStorageInfoPrivate::root()))
398-
399-/*!
400- Returns a QStorageInfo object that represents the system root volume.
401-
402- On Unix systems this call returns the root ('/') volume; in Windows the volume where
403- the operating system is installed.
404-
405- \sa isRoot()
406-*/
407-QStorageInfo QStorageInfo::root()
408-{
409- return *getRoot();
410-}
411-
412-/*!
413- \fn inline bool operator==(const QStorageInfo &first, const QStorageInfo &second)
414-
415- \relates QStorageInfo
416-
417- Returns true if the \a first QStorageInfo object refers to the same drive or volume
418- as the \a second; otherwise it returns false.
419-
420- Note that the result of comparing two invalid QStorageInfo objects is always
421- positive.
422-*/
423-
424-/*!
425- \fn inline bool operator!=(const QStorageInfo &first, const QStorageInfo &second)
426-
427- \relates QStorageInfo
428-
429- Returns true if the \a first QStorageInfo object refers to a different drive or
430- volume than the \a second; otherwise returns false.
431-*/
432-
433-QT_END_NAMESPACE
434
435=== removed file 'CameraApp/qstorageinfo.h'
436--- CameraApp/qstorageinfo.h 2015-01-27 14:34:31 +0000
437+++ CameraApp/qstorageinfo.h 1970-01-01 00:00:00 +0000
438@@ -1,102 +0,0 @@
439-/****************************************************************************
440-**
441-** Copyright (C) 2014 Ivan Komissarov <ABBAPOH@gmail.com>
442-** Contact: http://www.qt-project.org/legal
443-**
444-** This file is part of the QtCore module of the Qt Toolkit.
445-**
446-** This program is free software; you can redistribute it and/or modify
447-** it under the terms of the GNU General Public License as published by
448-** the Free Software Foundation; version 3.
449-**
450-** This program is distributed in the hope that it will be useful,
451-** but WITHOUT ANY WARRANTY; without even the implied warranty of
452-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
453-** GNU General Public License for more details.
454-**
455-** You should have received a copy of the GNU General Public License
456-** along with this program. If not, see <http://www.gnu.org/licenses/>.
457-**
458-****************************************************************************/
459-
460-#ifndef QSTORAGEINFO_H
461-#define QSTORAGEINFO_H
462-
463-#include <QtCore/qbytearray.h>
464-#include <QtCore/qdir.h>
465-#include <QtCore/qlist.h>
466-#include <QtCore/qmetatype.h>
467-#include <QtCore/qstring.h>
468-#include <QtCore/qshareddata.h>
469-
470-QT_BEGIN_NAMESPACE
471-
472-class QStorageInfoPrivate;
473-class Q_CORE_EXPORT QStorageInfo
474-{
475-public:
476- QStorageInfo();
477- explicit QStorageInfo(const QString &path);
478- explicit QStorageInfo(const QDir &dir);
479- QStorageInfo(const QStorageInfo &other);
480- ~QStorageInfo();
481-
482- QStorageInfo &operator=(const QStorageInfo &other);
483-#ifdef Q_COMPILER_RVALUE_REFS
484- inline QStorageInfo &operator=(QStorageInfo &&other)
485- { qSwap(d, other.d); return *this; }
486-#endif
487-
488- inline void swap(QStorageInfo &other)
489- { qSwap(d, other.d); }
490-
491- void setPath(const QString &path);
492-
493- QString rootPath() const;
494- QByteArray device() const;
495- QByteArray fileSystemType() const;
496- QString name() const;
497- QString displayName() const;
498-
499- qint64 bytesTotal() const;
500- qint64 bytesFree() const;
501- qint64 bytesAvailable() const;
502-
503- inline bool isRoot() const;
504- bool isReadOnly() const;
505- bool isReady() const;
506- bool isValid() const;
507-
508- void refresh();
509-
510- static QList<QStorageInfo> mountedVolumes();
511- static QStorageInfo root();
512-
513-private:
514- friend class QStorageInfoPrivate;
515- friend bool operator==(const QStorageInfo &first, const QStorageInfo &second);
516- QExplicitlySharedDataPointer<QStorageInfoPrivate> d;
517-};
518-
519-inline bool operator==(const QStorageInfo &first, const QStorageInfo &second)
520-{
521- if (first.d == second.d)
522- return true;
523- return first.device() == second.device();
524-}
525-
526-inline bool operator!=(const QStorageInfo &first, const QStorageInfo &second)
527-{
528- return !(first == second);
529-}
530-
531-inline bool QStorageInfo::isRoot() const
532-{ return *this == QStorageInfo::root(); }
533-
534-Q_DECLARE_SHARED(QStorageInfo)
535-
536-QT_END_NAMESPACE
537-
538-Q_DECLARE_METATYPE(QStorageInfo)
539-
540-#endif // QSTORAGEINFO_H
541
542=== removed file 'CameraApp/qstorageinfo_p.h'
543--- CameraApp/qstorageinfo_p.h 2015-01-27 14:34:31 +0000
544+++ CameraApp/qstorageinfo_p.h 1970-01-01 00:00:00 +0000
545@@ -1,84 +0,0 @@
546-/****************************************************************************
547-**
548-** Copyright (C) 2014 Ivan Komissarov <ABBAPOH@gmail.com>
549-** Contact: http://www.qt-project.org/legal
550-**
551-**
552-** This file is part of the QtCore module of the Qt Toolkit.
553-**
554-** This program is free software; you can redistribute it and/or modify
555-** it under the terms of the GNU General Public License as published by
556-** the Free Software Foundation; version 3.
557-**
558-** This program is distributed in the hope that it will be useful,
559-** but WITHOUT ANY WARRANTY; without even the implied warranty of
560-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
561-** GNU General Public License for more details.
562-**
563-** You should have received a copy of the GNU General Public License
564-** along with this program. If not, see <http://www.gnu.org/licenses/>.
565-**
566-****************************************************************************/
567-
568-#ifndef QSTORAGEINFO_P_H
569-#define QSTORAGEINFO_P_H
570-
571-//
572-// W A R N I N G
573-// -------------
574-//
575-// This file is not part of the Qt API. It exists purely as an
576-// implementation detail. This header file may change from version to
577-// version without notice, or even be removed.
578-//
579-// We mean it.
580-//
581-
582-#include "qstorageinfo.h"
583-
584-QT_BEGIN_NAMESPACE
585-
586-class QStorageInfoPrivate : public QSharedData
587-{
588-public:
589- inline QStorageInfoPrivate() : QSharedData(),
590- bytesTotal(0), bytesFree(0), bytesAvailable(0),
591- readOnly(false), ready(false), valid(false)
592- {}
593-
594- void initRootPath();
595- void doStat();
596-
597- static QList<QStorageInfo> mountedVolumes();
598- static QStorageInfo root();
599-
600-protected:
601-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
602- void retreiveVolumeInfo();
603- void retreiveDiskFreeSpace();
604-#elif defined(Q_OS_MAC)
605- void retrievePosixInfo();
606- void retrieveUrlProperties(bool initRootPath = false);
607- void retrieveLabel();
608-#elif defined(Q_OS_UNIX)
609- void retreiveVolumeInfo();
610-#endif
611-
612-public:
613- QString rootPath;
614- QByteArray device;
615- QByteArray fileSystemType;
616- QString name;
617-
618- qint64 bytesTotal;
619- qint64 bytesFree;
620- qint64 bytesAvailable;
621-
622- bool readOnly;
623- bool ready;
624- bool valid;
625-};
626-
627-QT_END_NAMESPACE
628-
629-#endif // QSTORAGEINFO_P_H
630
631=== removed file 'CameraApp/qstorageinfo_unix.cpp'
632--- CameraApp/qstorageinfo_unix.cpp 2015-01-27 14:34:31 +0000
633+++ CameraApp/qstorageinfo_unix.cpp 1970-01-01 00:00:00 +0000
634@@ -1,442 +0,0 @@
635-/****************************************************************************
636-**
637-** Copyright (C) 2014 Ivan Komissarov <ABBAPOH@gmail.com>
638-** Contact: http://www.qt-project.org/legal
639-**
640-** This file is part of the QtCore module of the Qt Toolkit.
641-**
642-** This program is free software; you can redistribute it and/or modify
643-** it under the terms of the GNU General Public License as published by
644-** the Free Software Foundation; version 3.
645-**
646-** This program is distributed in the hope that it will be useful,
647-** but WITHOUT ANY WARRANTY; without even the implied warranty of
648-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
649-** GNU General Public License for more details.
650-**
651-** You should have received a copy of the GNU General Public License
652-** along with this program. If not, see <http://www.gnu.org/licenses/>.
653-**
654-****************************************************************************/
655-
656-#include "qstorageinfo_p.h"
657-
658-#include <QtCore/qdiriterator.h>
659-#include <QtCore/qfileinfo.h>
660-#include <QtCore/qtextstream.h>
661-
662-// Copy this definition directly instead of importing the whole file which
663-// would pull in more dependencies we don't need.
664-//#include <QtCore/private/qcore_unix_p.h>
665-#define EINTR_LOOP(var, cmd) \
666- do { \
667- var = cmd; \
668- } while (var == -1 && errno == EINTR)
669-
670-#include <errno.h>
671-#include <sys/stat.h>
672-
673-#if defined(Q_OS_BSD4)
674-# include <sys/mount.h>
675-# include <sys/statvfs.h>
676-#elif defined(Q_OS_ANDROID)
677-# include <sys/mount.h>
678-# include <sys/vfs.h>
679-# include <mntent.h>
680-#elif defined(Q_OS_LINUX)
681-# include <mntent.h>
682-# include <sys/statvfs.h>
683-#elif defined(Q_OS_SOLARIS)
684-# include <sys/mnttab.h>
685-#else
686-# include <sys/statvfs.h>
687-#endif
688-
689-#if defined(Q_OS_BSD4)
690-# define QT_STATFSBUF struct statvfs
691-# define QT_STATFS ::statvfs
692-#elif defined(Q_OS_ANDROID)
693-# define QT_STATFS ::statfs
694-# define QT_STATFSBUF struct statfs
695-# if !defined(ST_RDONLY)
696-# define ST_RDONLY 1 // hack for missing define on Android
697-# endif
698-#else
699-# if defined(QT_LARGEFILE_SUPPORT)
700-# define QT_STATFSBUF struct statvfs64
701-# define QT_STATFS ::statvfs64
702-# else
703-# define QT_STATFSBUF struct statvfs
704-# define QT_STATFS ::statvfs
705-# endif // QT_LARGEFILE_SUPPORT
706-#endif // Q_OS_BSD4
707-
708-QT_BEGIN_NAMESPACE
709-
710-static bool isPseudoFs(const QString &mountDir, const QByteArray &type)
711-{
712- if (mountDir.startsWith(QLatin1String("/dev"))
713- || mountDir.startsWith(QLatin1String("/proc"))
714- || mountDir.startsWith(QLatin1String("/sys"))
715- || mountDir.startsWith(QLatin1String("/var/run"))
716- || mountDir.startsWith(QLatin1String("/var/lock"))) {
717- return true;
718- }
719- if (type == "tmpfs")
720- return true;
721-#if defined(Q_OS_LINUX)
722- if (type == "rootfs" || type == "rpc_pipefs")
723- return true;
724-#endif
725-
726- return false;
727-}
728-
729-class QStorageIterator
730-{
731-public:
732- QStorageIterator();
733- ~QStorageIterator();
734-
735- inline bool isValid() const;
736- inline bool next();
737- inline QString rootPath() const;
738- inline QByteArray fileSystemType() const;
739- inline QByteArray device() const;
740-private:
741-#if defined(Q_OS_BSD4)
742- struct statfs *stat_buf;
743- int entryCount;
744- int currentIndex;
745-#elif defined(Q_OS_SOLARIS)
746- FILE *fp;
747- mnttab mnt;
748-#elif defined(Q_OS_ANDROID)
749- QFile file;
750- QByteArray m_rootPath;
751- QByteArray m_fileSystemType;
752- QByteArray m_device;
753-#elif defined(Q_OS_LINUX)
754- FILE *fp;
755- mntent mnt;
756- QByteArray buffer;
757-#endif
758-};
759-
760-#if defined(Q_OS_BSD4)
761-
762-inline QStorageIterator::QStorageIterator()
763- : entryCount(::getmntinfo(&stat_buf, 0)),
764- currentIndex(-1)
765-{
766-}
767-
768-inline QStorageIterator::~QStorageIterator()
769-{
770-}
771-
772-inline bool QStorageIterator::isValid() const
773-{
774- return entryCount != -1;
775-}
776-
777-inline bool QStorageIterator::next()
778-{
779- return ++currentIndex < entryCount;
780-}
781-
782-inline QString QStorageIterator::rootPath() const
783-{
784- return QFile::decodeName(stat_buf[currentIndex].f_mntonname);
785-}
786-
787-inline QByteArray QStorageIterator::fileSystemType() const
788-{
789- return QByteArray(stat_buf[currentIndex].f_fstypename);
790-}
791-
792-inline QByteArray QStorageIterator::device() const
793-{
794- return QByteArray(stat_buf[currentIndex].f_mntfromname);
795-}
796-
797-#elif defined(Q_OS_SOLARIS)
798-
799-static const char pathMounted[] = "/etc/mnttab";
800-
801-inline QStorageIterator::QStorageIterator()
802-{
803- const int fd = qt_safe_open(pathMounted, O_RDONLY);
804- fp = ::fdopen(fd, "r");
805-}
806-
807-inline QStorageIterator::~QStorageIterator()
808-{
809- if (fp)
810- ::fclose(fp);
811-}
812-
813-inline bool QStorageIterator::isValid() const
814-{
815- return fp != Q_NULLPTR;
816-}
817-
818-inline bool QStorageIterator::next()
819-{
820- return ::getmntent(fp, &mnt) == Q_NULLPTR;
821-}
822-
823-inline QString QStorageIterator::rootPath() const
824-{
825- return QFile::decodeName(mnt->mnt_mountp);
826-}
827-
828-inline QByteArray QStorageIterator::fileSystemType() const
829-{
830- return QByteArray(mnt->mnt_fstype);
831-}
832-
833-inline QByteArray QStorageIterator::device() const
834-{
835- return QByteArray(mnt->mnt_mntopts);
836-}
837-
838-#elif defined(Q_OS_ANDROID)
839-
840-static const char pathMounted[] = "/proc/mounts";
841-
842-inline QStorageIterator::QStorageIterator()
843-{
844- file.setFileName(pathMounted);
845- file.open(QIODevice::ReadOnly | QIODevice::Text);
846-}
847-
848-inline QStorageIterator::~QStorageIterator()
849-{
850-}
851-
852-inline bool QStorageIterator::isValid() const
853-{
854- return file.isOpen();
855-}
856-
857-inline bool QStorageIterator::next()
858-{
859- QList<QByteArray> data;
860- do {
861- const QByteArray line = file.readLine();
862- data = line.split(' ');
863- } while (data.count() < 3 && !file.atEnd());
864-
865- if (file.atEnd())
866- return false;
867- m_device = data.at(0);
868- m_rootPath = data.at(1);
869- m_fileSystemType = data.at(2);
870-
871- return true;
872-}
873-
874-inline QString QStorageIterator::rootPath() const
875-{
876- return QFile::decodeName(m_rootPath);
877-}
878-
879-inline QByteArray QStorageIterator::fileSystemType() const
880-{
881- return m_fileSystemType;
882-}
883-
884-inline QByteArray QStorageIterator::device() const
885-{
886- return m_device;
887-}
888-
889-#elif defined(Q_OS_LINUX)
890-
891-static const char pathMounted[] = "/etc/mtab";
892-static const int bufferSize = 3*PATH_MAX; // 2 paths (mount point+device) and metainfo
893-
894-inline QStorageIterator::QStorageIterator() :
895- buffer(QByteArray(bufferSize, 0))
896-{
897- fp = ::setmntent(pathMounted, "r");
898-}
899-
900-inline QStorageIterator::~QStorageIterator()
901-{
902- if (fp)
903- ::endmntent(fp);
904-}
905-
906-inline bool QStorageIterator::isValid() const
907-{
908- return fp != Q_NULLPTR;
909-}
910-
911-inline bool QStorageIterator::next()
912-{
913- return ::getmntent_r(fp, &mnt, buffer.data(), buffer.size()) != Q_NULLPTR;
914-}
915-
916-inline QString QStorageIterator::rootPath() const
917-{
918- return QFile::decodeName(mnt.mnt_dir);
919-}
920-
921-inline QByteArray QStorageIterator::fileSystemType() const
922-{
923- return QByteArray(mnt.mnt_type);
924-}
925-
926-inline QByteArray QStorageIterator::device() const
927-{
928- return QByteArray(mnt.mnt_fsname);
929-}
930-
931-#else
932-
933-inline QStorageIterator::QStorageIterator()
934-{
935-}
936-
937-inline QStorageIterator::~QStorageIterator()
938-{
939-}
940-
941-inline bool QStorageIterator::isValid() const
942-{
943- return false;
944-}
945-
946-inline bool QStorageIterator::next()
947-{
948- return false;
949-}
950-
951-inline QString QStorageIterator::rootPath() const
952-{
953- return QString();
954-}
955-
956-inline QByteArray QStorageIterator::fileSystemType() const
957-{
958- return QByteArray();
959-}
960-
961-inline QByteArray QStorageIterator::device() const
962-{
963- return QByteArray();
964-}
965-
966-#endif
967-
968-void QStorageInfoPrivate::initRootPath()
969-{
970- rootPath = QFileInfo(rootPath).canonicalFilePath();
971-
972- if (rootPath.isEmpty())
973- return;
974-
975- QStorageIterator it;
976- if (!it.isValid()) {
977- rootPath = QStringLiteral("/");
978- return;
979- }
980-
981- int maxLength = 0;
982- const QString oldRootPath = rootPath;
983- rootPath.clear();
984-
985- while (it.next()) {
986- const QString mountDir = it.rootPath();
987- const QByteArray fsName = it.fileSystemType();
988- if (isPseudoFs(mountDir, fsName))
989- continue;
990- // we try to find most suitable entry
991- if (oldRootPath.startsWith(mountDir) && maxLength < mountDir.length()) {
992- maxLength = mountDir.length();
993- rootPath = mountDir;
994- device = it.device();
995- fileSystemType = fsName;
996- }
997- }
998-}
999-
1000-static inline QString retrieveLabel(const QByteArray &device)
1001-{
1002-#ifdef Q_OS_LINUX
1003- static const char pathDiskByLabel[] = "/dev/disk/by-label";
1004-
1005- QDirIterator it(QLatin1String(pathDiskByLabel), QDir::NoDotAndDotDot);
1006- while (it.hasNext()) {
1007- it.next();
1008- QFileInfo fileInfo(it.fileInfo());
1009- if (fileInfo.isSymLink() && fileInfo.symLinkTarget().toLocal8Bit() == device)
1010- return fileInfo.fileName();
1011- }
1012-#else
1013- Q_UNUSED(device);
1014-#endif
1015-
1016- return QString();
1017-}
1018-
1019-void QStorageInfoPrivate::doStat()
1020-{
1021- initRootPath();
1022- if (rootPath.isEmpty())
1023- return;
1024-
1025- retreiveVolumeInfo();
1026- name = retrieveLabel(device);
1027-}
1028-
1029-void QStorageInfoPrivate::retreiveVolumeInfo()
1030-{
1031- QT_STATFSBUF statfs_buf;
1032- int result;
1033- EINTR_LOOP(result, QT_STATFS(QFile::encodeName(rootPath).constData(), &statfs_buf));
1034- if (result == 0) {
1035- valid = true;
1036- ready = true;
1037-
1038- bytesTotal = statfs_buf.f_blocks * statfs_buf.f_bsize;
1039- bytesFree = statfs_buf.f_bfree * statfs_buf.f_bsize;
1040- bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_bsize;
1041-#if defined(Q_OS_ANDROID)
1042-#if defined(_STATFS_F_FLAGS)
1043- readOnly = (statfs_buf.f_flags & ST_RDONLY) != 0;
1044-#endif
1045-#else
1046- readOnly = (statfs_buf.f_flag & ST_RDONLY) != 0;
1047-#endif
1048- }
1049-}
1050-
1051-QList<QStorageInfo> QStorageInfoPrivate::mountedVolumes()
1052-{
1053- QStorageIterator it;
1054- if (!it.isValid())
1055- return QList<QStorageInfo>() << root();
1056-
1057- QList<QStorageInfo> volumes;
1058-
1059- while (it.next()) {
1060- const QString mountDir = it.rootPath();
1061- const QByteArray fsName = it.fileSystemType();
1062- if (isPseudoFs(mountDir, fsName))
1063- continue;
1064-
1065- volumes.append(QStorageInfo(mountDir));
1066- }
1067-
1068- return volumes;
1069-}
1070-
1071-QStorageInfo QStorageInfoPrivate::root()
1072-{
1073- return QStorageInfo(QStringLiteral("/"));
1074-}
1075-
1076-QT_END_NAMESPACE
1077
1078=== added file 'CameraApp/storagelocations.cpp'
1079--- CameraApp/storagelocations.cpp 1970-01-01 00:00:00 +0000
1080+++ CameraApp/storagelocations.cpp 2016-02-11 13:25:08 +0000
1081@@ -0,0 +1,121 @@
1082+/*
1083+ * Copyright (C) 2016 Canonical, Ltd.
1084+ *
1085+ * This program is free software; you can redistribute it and/or modify
1086+ * it under the terms of the GNU General Public License as published by
1087+ * the Free Software Foundation; version 3.
1088+ *
1089+ * This program is distributed in the hope that it will be useful,
1090+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1091+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1092+ * GNU General Public License for more details.
1093+ *
1094+ * You should have received a copy of the GNU General Public License
1095+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1096+ */
1097+
1098+#include "storagelocations.h"
1099+
1100+#include <QCoreApplication>
1101+#include <QStandardPaths>
1102+#include <QStorageInfo>
1103+
1104+StorageLocations::StorageLocations(QObject *parent) : QObject(parent)
1105+{
1106+}
1107+
1108+QString StorageLocations::picturesLocation() const
1109+{
1110+ QStringList locations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
1111+ if (locations.isEmpty()) {
1112+ return QString();
1113+ }
1114+ QString location = locations.at(0) + "/" + QCoreApplication::applicationName();
1115+ QDir dir;
1116+ // Transition from old directory 'camera' to new one; see bug #1363112
1117+ // https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1363112
1118+ dir.rename(locations.at(0) + "/" + "camera", location);
1119+ dir.mkpath(location);
1120+ return location;
1121+}
1122+
1123+QString StorageLocations::videosLocation() const
1124+{
1125+ QStringList locations = QStandardPaths::standardLocations(QStandardPaths::MoviesLocation);
1126+ if (locations.isEmpty()) {
1127+ return QString();
1128+ }
1129+ QString location = locations.at(0) + "/" + QCoreApplication::applicationName();
1130+ QDir dir;
1131+ // Transition from old directory 'camera' to new one; see bug #1363112
1132+ // https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1363112
1133+ dir.rename(locations.at(0) + "/" + "camera", location);
1134+ dir.mkpath(location);
1135+ return location;
1136+}
1137+
1138+QString StorageLocations::temporaryLocation() const
1139+{
1140+ QStringList locations = QStandardPaths::standardLocations(QStandardPaths::TempLocation);
1141+ if (locations.isEmpty()) {
1142+ return QString();
1143+ }
1144+ QString location = locations.at(0);
1145+ QDir dir;
1146+ dir.mkpath(location);
1147+ return location;
1148+}
1149+
1150+QString StorageLocations::removableStorageLocation() const
1151+{
1152+ QString mediaRoot("/media/" + qgetenv("USER"));
1153+ Q_FOREACH(QStorageInfo volume, QStorageInfo::mountedVolumes()) {
1154+ if (volume.rootPath().startsWith(mediaRoot) &&
1155+ volume.isValid() && volume.isReady()) {
1156+ return volume.rootPath();
1157+ }
1158+ }
1159+
1160+ return QString();
1161+}
1162+
1163+QString StorageLocations::removableStoragePicturesLocation() const
1164+{
1165+ QString storageLocation = removableStorageLocation();
1166+ if (storageLocation.isEmpty()) {
1167+ return QString();
1168+ }
1169+
1170+ QStringList locations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
1171+ QString pictureDir = QString(locations.at(0)).split("/").value(3);
1172+ if (pictureDir.isEmpty()){
1173+ return QString();
1174+ }
1175+ QString location = storageLocation + "/" + pictureDir + "/" + QCoreApplication::applicationName();
1176+ QDir dir;
1177+ dir.mkpath(location);
1178+ return location;
1179+}
1180+
1181+QString StorageLocations::removableStorageVideosLocation() const
1182+{
1183+ QString storageLocation = removableStorageLocation();
1184+ if (storageLocation.isEmpty()) {
1185+ return QString();
1186+ }
1187+
1188+ QStringList locations = QStandardPaths::standardLocations(QStandardPaths::MoviesLocation);
1189+ QString movieDir = QString(locations.at(0)).split("/").value(3);
1190+ if (movieDir.isEmpty()){
1191+ return QString();
1192+ }
1193+ QString location = storageLocation + "/" + movieDir + "/" + QCoreApplication::applicationName();
1194+ QDir dir;
1195+ dir.mkpath(location);
1196+ return location;
1197+}
1198+
1199+bool StorageLocations::removableStoragePresent() const
1200+{
1201+ return !removableStorageLocation().isEmpty();
1202+}
1203
1204=== added file 'CameraApp/storagelocations.h'
1205--- CameraApp/storagelocations.h 1970-01-01 00:00:00 +0000
1206+++ CameraApp/storagelocations.h 2016-02-11 13:25:08 +0000
1207@@ -0,0 +1,50 @@
1208+/*
1209+ * Copyright (C) 2016 Canonical, Ltd.
1210+ *
1211+ * This program is free software; you can redistribute it and/or modify
1212+ * it under the terms of the GNU General Public License as published by
1213+ * the Free Software Foundation; version 3.
1214+ *
1215+ * This program is distributed in the hope that it will be useful,
1216+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1217+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1218+ * GNU General Public License for more details.
1219+ *
1220+ * You should have received a copy of the GNU General Public License
1221+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1222+ */
1223+
1224+#ifndef STORAGELOCATIONS_H
1225+#define STORAGELOCATIONS_H
1226+
1227+#include <QObject>
1228+
1229+class StorageLocations : public QObject
1230+{
1231+ Q_OBJECT
1232+
1233+ Q_PROPERTY(QString picturesLocation READ picturesLocation CONSTANT)
1234+ Q_PROPERTY(QString videosLocation READ videosLocation CONSTANT)
1235+ Q_PROPERTY(QString temporaryLocation READ temporaryLocation CONSTANT)
1236+ Q_PROPERTY(QString removableStorageLocation READ removableStorageLocation CONSTANT)
1237+ Q_PROPERTY(QString removableStoragePicturesLocation READ removableStoragePicturesLocation CONSTANT)
1238+ Q_PROPERTY(QString removableStorageVideosLocation READ removableStorageVideosLocation CONSTANT)
1239+ Q_PROPERTY(bool removableStoragePresent READ removableStoragePresent NOTIFY removableStoragePresentChanged)
1240+
1241+public:
1242+ explicit StorageLocations(QObject *parent = 0);
1243+
1244+ QString picturesLocation() const;
1245+ QString videosLocation() const;
1246+ QString temporaryLocation() const;
1247+ QString removableStorageLocation() const;
1248+ QString removableStoragePicturesLocation() const;
1249+ QString removableStorageVideosLocation() const;
1250+
1251+ bool removableStoragePresent() const;
1252+
1253+Q_SIGNALS:
1254+ void removableStoragePresentChanged();
1255+};
1256+
1257+#endif // STORAGELOCATIONS_H
1258
1259=== modified file 'CameraApp/storagemonitor.cpp'
1260--- CameraApp/storagemonitor.cpp 2015-01-23 19:28:44 +0000
1261+++ CameraApp/storagemonitor.cpp 2016-02-11 13:25:08 +0000
1262@@ -15,9 +15,10 @@
1263 */
1264
1265 #include "storagemonitor.h"
1266+#include "storagelocations.h"
1267
1268 StorageMonitor::StorageMonitor(QObject *parent) :
1269- QObject(parent), m_low(false), m_criticallyLow(false)
1270+ QObject(parent), m_low(false), m_criticallyLow(false), m_writeable(true)
1271 {
1272 m_timer.setInterval(POLL_INTERVAL);
1273 m_timer.setSingleShot(false);
1274@@ -54,6 +55,32 @@
1275 }
1276 }
1277
1278+void StorageMonitor::checkWriteable()
1279+{
1280+ bool writeable = true;
1281+
1282+ QString mediaRoot("/media/" + qgetenv("USER"));
1283+ if (m_storage.rootPath().startsWith(mediaRoot)) {
1284+ // check only for external media, assume internal media is always writeable
1285+ if (m_storage.isReadOnly()) {
1286+ writeable = false;
1287+ } else {
1288+ StorageLocations locations;
1289+ QDir storageRoot(locations.removableStoragePicturesLocation());
1290+ QFile testFile(storageRoot.absoluteFilePath(".write_test"));
1291+ bool opened = testFile.open(QIODevice::WriteOnly | QIODevice::Unbuffered);
1292+ if (!opened || testFile.write("x", 1) != 1) writeable = false;
1293+ testFile.close();
1294+ testFile.remove();
1295+ }
1296+ }
1297+
1298+ if (m_writeable != writeable) {
1299+ m_writeable = writeable;
1300+ Q_EMIT isWriteableChanged();
1301+ }
1302+}
1303+
1304 void StorageMonitor::setLocation(QString location)
1305 {
1306 if (location != m_location) {
1307@@ -62,6 +89,7 @@
1308
1309 m_storage.setPath(m_location);
1310 checkDiskSpace();
1311+ checkWriteable();
1312 if (m_storage.isValid()) {
1313 m_timer.start();
1314 }
1315@@ -84,3 +112,8 @@
1316 {
1317 return m_criticallyLow;
1318 }
1319+
1320+bool StorageMonitor::isWriteable() const
1321+{
1322+ return m_writeable;
1323+}
1324
1325=== modified file 'CameraApp/storagemonitor.h'
1326--- CameraApp/storagemonitor.h 2015-01-23 19:29:03 +0000
1327+++ CameraApp/storagemonitor.h 2016-02-11 13:25:08 +0000
1328@@ -34,6 +34,7 @@
1329 Q_PROPERTY(QString location READ location WRITE setLocation NOTIFY locationChanged)
1330 Q_PROPERTY(bool diskSpaceLow READ diskSpaceLow NOTIFY diskSpaceLowChanged)
1331 Q_PROPERTY(bool diskSpaceCriticallyLow READ diskSpaceCriticallyLow NOTIFY diskSpaceCriticallyLowChanged)
1332+ Q_PROPERTY(bool isWriteable READ isWriteable NOTIFY isWriteableChanged)
1333
1334 public:
1335 explicit StorageMonitor(QObject *parent = 0);
1336@@ -42,21 +43,25 @@
1337 void setLocation(QString location);
1338 bool diskSpaceLow() const;
1339 bool diskSpaceCriticallyLow() const;
1340+ bool isWriteable() const;
1341
1342 Q_SIGNALS:
1343 void locationChanged();
1344 void diskSpaceLowChanged();
1345 void diskSpaceCriticallyLowChanged();
1346+ void isWriteableChanged();
1347
1348 private Q_SLOTS:
1349 void refresh();
1350
1351 private:
1352 void checkDiskSpace();
1353+ void checkWriteable();
1354
1355 private:
1356 bool m_low;
1357 bool m_criticallyLow;
1358+ bool m_writeable;
1359 QTimer m_timer;
1360 QString m_location;
1361 QStorageInfo m_storage;
1362
1363=== modified file 'GalleryView.qml'
1364--- GalleryView.qml 2016-01-29 09:24:51 +0000
1365+++ GalleryView.qml 2016-02-11 13:25:08 +0000
1366@@ -30,9 +30,9 @@
1367 property bool userSelectionMode: false
1368 property Item currentView: state == "GRID" ? photogridView : slideshowView
1369 property var model: FoldersModel {
1370- folders: [application.picturesLocation, application.videosLocation,
1371- application.removableStoragePicturesLocation,
1372- application.removableStorageVideosLocation]
1373+ folders: [StorageLocations.picturesLocation, StorageLocations.videosLocation,
1374+ StorageLocations.removableStoragePicturesLocation,
1375+ StorageLocations.removableStorageVideosLocation]
1376 typeFilters: !main.contentExportMode ? [ "image", "video" ]
1377 : [MimeTypeMapper.contentTypeToMimeType(main.transferContentType)]
1378 singleSelectionOnly: main.transfer.selectionType === ContentTransfer.Single
1379
1380=== modified file 'ViewFinderOverlay.qml'
1381--- ViewFinderOverlay.qml 2016-02-08 12:43:52 +0000
1382+++ ViewFinderOverlay.qml 2016-02-11 13:25:08 +0000
1383@@ -502,7 +502,7 @@
1384 property string label: i18n.tr("SD")
1385 property bool isToggle: true
1386 property int selectedIndex: bottomEdge.indexForValue(removableStorageOptionsModel, settings.preferRemovableStorage)
1387- property bool available: application.removableStoragePresent
1388+ property bool available: StorageLocations.removableStoragePresent
1389 property bool visible: available
1390
1391 ListElement {
1392@@ -565,12 +565,12 @@
1393 }
1394 ]
1395
1396- /* FIXME: application.removableStoragePresent is not updated dynamically.
1397+ /* FIXME: StorageLocations.removableStoragePresent is not updated dynamically.
1398 Workaround that by reading it when the bottom edge is opened/closed.
1399 */
1400 Connections {
1401 target: bottomEdge
1402- onOpenedChanged: removableStorageOptionsModel.available = application.removableStoragePresent
1403+ onOpenedChanged: removableStorageOptionsModel.available = StorageLocations.removableStoragePresent
1404 }
1405
1406 function indexForValue(model, value) {
1407@@ -696,11 +696,11 @@
1408
1409 if (camera.captureMode == Camera.CaptureVideo) {
1410 if (main.contentExportMode) {
1411- camera.videoRecorder.outputLocation = application.temporaryLocation;
1412- } else if (application.removableStoragePresent && settings.preferRemovableStorage) {
1413- camera.videoRecorder.outputLocation = application.removableStorageVideosLocation;
1414+ camera.videoRecorder.outputLocation = StorageLocations.temporaryLocation;
1415+ } else if (StorageLocations.removableStoragePresent && settings.preferRemovableStorage) {
1416+ camera.videoRecorder.outputLocation = StorageLocations.removableStorageVideosLocation;
1417 } else {
1418- camera.videoRecorder.outputLocation = application.videosLocation;
1419+ camera.videoRecorder.outputLocation = StorageLocations.videosLocation;
1420 }
1421
1422 if (camera.videoRecorder.recorderState == CameraRecorder.StoppedState) {
1423@@ -727,11 +727,11 @@
1424
1425 camera.photoCaptureInProgress = true;
1426 if (main.contentExportMode) {
1427- camera.imageCapture.captureToLocation(application.temporaryLocation);
1428- } else if (application.removableStoragePresent && settings.preferRemovableStorage) {
1429- camera.imageCapture.captureToLocation(application.removableStoragePicturesLocation);
1430+ camera.imageCapture.captureToLocation(StorageLocations.temporaryLocation);
1431+ } else if (StorageLocations.removableStoragePresent && settings.preferRemovableStorage) {
1432+ camera.imageCapture.captureToLocation(StorageLocations.removableStoragePicturesLocation);
1433 } else {
1434- camera.imageCapture.captureToLocation(application.picturesLocation);
1435+ camera.imageCapture.captureToLocation(StorageLocations.picturesLocation);
1436 }
1437 }
1438 }
1439@@ -974,14 +974,17 @@
1440
1441 StorageMonitor {
1442 id: storageMonitor
1443- location: (application.removableStoragePresent && settings.preferRemovableStorage) ?
1444- application.removableStorageLocation : application.videosLocation
1445+ location: (StorageLocations.removableStoragePresent && settings.preferRemovableStorage) ?
1446+ StorageLocations.removableStorageLocation : StorageLocations.videosLocation
1447 onDiskSpaceLowChanged: if (storageMonitor.diskSpaceLow && !storageMonitor.diskSpaceCriticallyLow) {
1448 PopupUtils.open(freeSpaceLowDialogComponent);
1449 }
1450 onDiskSpaceCriticallyLowChanged: if (storageMonitor.diskSpaceCriticallyLow) {
1451 camera.videoRecorder.stop();
1452 }
1453+ onIsWriteableChanged: if (!isWriteable && !diskSpaceLow && !main.contentExportMode) {
1454+ PopupUtils.open(readOnlyMediaDialogComponent);
1455+ }
1456 }
1457
1458 NoSpaceHint {
1459@@ -1005,6 +1008,20 @@
1460 }
1461 }
1462
1463+ Component {
1464+ id: readOnlyMediaDialogComponent
1465+ Dialog {
1466+ id: readOnlyMediaDialog
1467+ objectName: "readOnlyMediaDialog"
1468+ title: i18n.tr("External storage not writeable")
1469+ text: i18n.tr("It does not seem possible to write to your external storage media. Trying to eject and insert it again might solve the issue, or you might need to format it.")
1470+ Button {
1471+ text: i18n.tr("Cancel")
1472+ onClicked: PopupUtils.close(readOnlyMediaDialog)
1473+ }
1474+ }
1475+ }
1476+
1477 Connections {
1478 id: permissionErrorMonitor
1479 property var currentPermissionsDialog: null
1480
1481=== modified file 'ViewFinderView.qml'
1482--- ViewFinderView.qml 2016-01-29 11:01:57 +0000
1483+++ ViewFinderView.qml 2016-02-11 13:25:08 +0000
1484@@ -17,6 +17,7 @@
1485 import QtQuick 2.4
1486 import QtQuick.Window 2.2
1487 import Ubuntu.Components 1.3
1488+import Ubuntu.Components.Popups 1.3
1489 import QtMultimedia 5.0
1490 import CameraApp 0.1
1491 import QtGraphicalEffects 1.0
1492@@ -107,8 +108,10 @@
1493 }
1494 }
1495 onCaptureFailed: {
1496+ console.log("Image capture failed for request " + requestId + ": " + message);
1497 camera.photoCaptureInProgress = false;
1498- console.log("Capture failed for request " + requestId + ": " + message);
1499+ viewFinderOverlay.visible = true;
1500+ PopupUtils.open(captureFailedDialogComponent);
1501 }
1502 onImageCaptured: {
1503 snapshot.source = preview;
1504@@ -144,6 +147,11 @@
1505 }
1506 }
1507 }
1508+ onErrorCodeChanged: {
1509+ if (videoRecorder.errorCode !== CameraRecorder.NoError) {
1510+ PopupUtils.open(captureFailedDialogComponent);
1511+ }
1512+ }
1513 }
1514 }
1515
1516@@ -444,4 +452,24 @@
1517 snapshot: snapshot
1518 isVideo: main.transfer.contentType == ContentType.Videos
1519 }
1520+
1521+ Component {
1522+ id: captureFailedDialogComponent
1523+ Dialog {
1524+ id: captureFailedDialog
1525+ objectName: "captureFailedDialog"
1526+ title: i18n.tr("Capture failed")
1527+
1528+ // If we are capturing to an SD card the problem can be a broken card, otherwise it is probably a
1529+ // crash in the driver and a reboot might fix things.
1530+ text: StorageLocations.removableStorageLocation && viewFinderOverlay.settings.preferRemovableStorage ?
1531+ i18n.tr("Replacing your external media, formatting it, or restarting the device might fix the problem.") :
1532+ i18n.tr("Restarting your device might fix the problem.")
1533+
1534+ Button {
1535+ text: i18n.tr("Cancel")
1536+ onClicked: PopupUtils.close(captureFailedDialog)
1537+ }
1538+ }
1539+ }
1540 }
1541
1542=== modified file 'cameraapplication.cpp'
1543--- cameraapplication.cpp 2015-11-25 17:47:00 +0000
1544+++ cameraapplication.cpp 2016-02-11 13:25:08 +0000
1545@@ -19,14 +19,8 @@
1546
1547 #include "cameraapplication.h"
1548
1549-#include <QtCore/QDir>
1550-#include <QtCore/QUrl>
1551 #include <QtCore/QDebug>
1552-#include <QtCore/QStringList>
1553 #include <QtCore/QLibrary>
1554-#include <QtCore/QStandardPaths>
1555-#include <QtCore/QDir>
1556-#include <QDate>
1557 #include <QQmlContext>
1558 #include <QQmlEngine>
1559 #include <QScreen>
1560@@ -95,103 +89,3 @@
1561
1562 return true;
1563 }
1564-
1565-QString CameraApplication::picturesLocation() const
1566-{
1567- QStringList locations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
1568- if (locations.isEmpty()) {
1569- return QString();
1570- }
1571- QString location = locations.at(0) + "/" + QCoreApplication::applicationName();
1572- QDir dir;
1573- // Transition from old directory 'camera' to new one; see bug #1363112
1574- // https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1363112
1575- dir.rename(locations.at(0) + "/" + "camera", location);
1576- dir.mkpath(location);
1577- return location;
1578-}
1579-
1580-QString CameraApplication::videosLocation() const
1581-{
1582- QStringList locations = QStandardPaths::standardLocations(QStandardPaths::MoviesLocation);
1583- if (locations.isEmpty()) {
1584- return QString();
1585- }
1586- QString location = locations.at(0) + "/" + QCoreApplication::applicationName();
1587- QDir dir;
1588- // Transition from old directory 'camera' to new one; see bug #1363112
1589- // https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1363112
1590- dir.rename(locations.at(0) + "/" + "camera", location);
1591- dir.mkpath(location);
1592- return location;
1593-}
1594-
1595-QString CameraApplication::temporaryLocation() const
1596-{
1597- QStringList locations = QStandardPaths::standardLocations(QStandardPaths::TempLocation);
1598- if (locations.isEmpty()) {
1599- return QString();
1600- }
1601- QString location = locations.at(0);
1602- QDir dir;
1603- dir.mkpath(location);
1604- return location;
1605-}
1606-
1607-bool CameraApplication::removableStoragePresent() const
1608-{
1609- return !removableStorageLocation().isEmpty();
1610-}
1611-
1612-QString CameraApplication::removableStorageLocation() const
1613-{
1614- /* FIXME: when Qt5.4 is available, switch to using newly introduced
1615- * QStorageInfo API.
1616- * Ref.: http://doc-snapshot.qt-project.org/qt5-5.4/qstorageinfo.html
1617- */
1618- QString userName = qgetenv("USER");
1619- QDir media("/media/" + userName);
1620- QStringList mediaDirs = media.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
1621-
1622- if (mediaDirs.size() > 0) {
1623- return QString("/media/" + userName + "/" + mediaDirs.at(0));
1624- } else {
1625- return QString();
1626- }
1627-}
1628-
1629-QString CameraApplication::removableStoragePicturesLocation() const
1630-{
1631- QString storageLocation = removableStorageLocation();
1632- if (storageLocation.isEmpty()) {
1633- return QString();
1634- }
1635-
1636- QStringList locations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
1637- QString pictureDir = QString(locations.at(0)).split("/").value(3);
1638- if (pictureDir.isEmpty()){
1639- return QString();
1640- }
1641- QString location = storageLocation + "/" + pictureDir + "/" + QCoreApplication::applicationName();
1642- QDir dir;
1643- dir.mkpath(location);
1644- return location;
1645-}
1646-
1647-QString CameraApplication::removableStorageVideosLocation() const
1648-{
1649- QString storageLocation = removableStorageLocation();
1650- if (storageLocation.isEmpty()) {
1651- return QString();
1652- }
1653-
1654- QStringList locations = QStandardPaths::standardLocations(QStandardPaths::MoviesLocation);
1655- QString movieDir = QString(locations.at(0)).split("/").value(3);
1656- if (movieDir.isEmpty()){
1657- return QString();
1658- }
1659- QString location = storageLocation + "/" + movieDir + "/" + QCoreApplication::applicationName();
1660- QDir dir;
1661- dir.mkpath(location);
1662- return location;
1663-}
1664
1665=== modified file 'cameraapplication.h'
1666--- cameraapplication.h 2015-11-25 17:47:00 +0000
1667+++ cameraapplication.h 2016-02-11 13:25:08 +0000
1668@@ -29,29 +29,14 @@
1669 {
1670 Q_OBJECT
1671 Q_PROPERTY(bool desktopMode READ isDesktopMode CONSTANT)
1672- Q_PROPERTY(QString picturesLocation READ picturesLocation CONSTANT)
1673- Q_PROPERTY(QString videosLocation READ videosLocation CONSTANT)
1674- Q_PROPERTY(QString temporaryLocation READ temporaryLocation CONSTANT)
1675- Q_PROPERTY(bool removableStoragePresent READ removableStoragePresent NOTIFY removableStoragePresentChanged)
1676- Q_PROPERTY(QString removableStorageLocation READ removableStorageLocation CONSTANT)
1677- Q_PROPERTY(QString removableStoragePicturesLocation READ removableStoragePicturesLocation CONSTANT)
1678- Q_PROPERTY(QString removableStorageVideosLocation READ removableStorageVideosLocation CONSTANT)
1679
1680 public:
1681 CameraApplication(int &argc, char **argv);
1682 virtual ~CameraApplication();
1683 bool setup();
1684 bool isDesktopMode() const;
1685- QString picturesLocation() const;
1686- QString videosLocation() const;
1687- QString temporaryLocation() const;
1688- bool removableStoragePresent() const;
1689- QString removableStorageLocation() const;
1690- QString removableStoragePicturesLocation() const;
1691- QString removableStorageVideosLocation() const;
1692
1693 Q_SIGNALS:
1694- void removableStoragePresentChanged();
1695
1696 private:
1697 QScopedPointer<QQmlApplicationEngine> m_engine;
1698
1699=== modified file 'tests/unittests/qstorageinfo_stub.cpp'
1700--- tests/unittests/qstorageinfo_stub.cpp 2015-01-26 10:57:36 +0000
1701+++ tests/unittests/qstorageinfo_stub.cpp 2016-02-11 13:25:08 +0000
1702@@ -14,14 +14,23 @@
1703 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1704 */
1705
1706-#include "qstorageinfo.h"
1707-#include "qstorageinfo_p.h"
1708+#include <QStorageInfo>
1709 #include "storageinfocontrol.h"
1710
1711 #include <QDebug>
1712
1713 QString location;
1714
1715+class QStorageInfoPrivateRef {
1716+public:
1717+ bool deref() { return false; }
1718+};
1719+
1720+class QStorageInfoPrivate {
1721+public:
1722+ QStorageInfoPrivateRef ref;
1723+};
1724+
1725 QStorageInfo::QStorageInfo()
1726 {
1727 }
1728@@ -47,6 +56,11 @@
1729 location = path;
1730 }
1731
1732+QString QStorageInfo::rootPath() const
1733+{
1734+ return location;
1735+}
1736+
1737 qint64 QStorageInfo::bytesAvailable() const
1738 {
1739 return StorageInfoControl::instance()->freeSpaceMap[location];

Subscribers

People subscribed via source and target branches