silence dbus-send output
[harmattan/cameraplus] / src / postcapturemodel.cpp
1 /*!
2  * This file is part of CameraPlus.
3  *
4  * Copyright (C) 2012-2013 Mohammed Sameer <msameer@foolab.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20
21 #include "postcapturemodel.h"
22 #include <QDir>
23 #include <QDateTime>
24 #include <QUrl>
25 #include <QStandardItem>
26 #include <dirent.h>
27 #include <sys/types.h>
28 #if defined(QT4)
29 #include <QDeclarativeInfo>
30 #elif defined(QT5)
31 #include <QQmlInfo>
32 #endif
33
34 static QHash<QString, QString> m_mime;
35
36 class PostCaptureModelItem : public QStandardItem {
37 public:
38   PostCaptureModelItem(const QString& path, const char *file) :
39     m_dir(path),
40     m_name(QString::fromLocal8Bit(file)),
41     m_info(0) {
42
43   }
44
45   ~PostCaptureModelItem() {
46     if (m_info) {
47       delete m_info;
48       m_info = 0;
49     }
50   }
51
52   int type() const {
53     return UserType;
54   }
55
56   const QFileInfo *info() const {
57     if (!m_info) {
58       m_info = new QFileInfo(path());
59     }
60
61     return m_info;
62   }
63
64   QString path() const {
65     return QString("%1%2%3").arg(m_dir).arg(QDir::separator()).arg(m_name);
66   }
67
68   QVariant data (int role = Qt::UserRole + 1) const {
69     switch (role) {
70     case PostCaptureModel::UrlRole:
71       return QUrl::fromLocalFile(path());
72
73     case PostCaptureModel::TitleRole:
74       return info()->baseName();
75
76     case PostCaptureModel::MimeTypeRole:
77       if (m_mime.contains(info()->completeSuffix())) {
78         return m_mime[info()->completeSuffix()];
79       }
80
81       return QString();
82
83     case PostCaptureModel::CreatedRole:
84       return info()->created().toString();
85
86     case PostCaptureModel::FileNameRole:
87       return info()->fileName();
88
89     default:
90       return QVariant();
91     }
92   }
93
94 private:
95   QString m_dir;
96   QString m_name;
97   mutable QFileInfo *m_info;
98 };
99
100 static bool lessThan(const QStandardItem *a1, const QStandardItem *a2) {
101   // we sort descending
102   return dynamic_cast<const PostCaptureModelItem *>(a1)->info()->created() >
103     dynamic_cast<const PostCaptureModelItem *>(a2)->info()->created();
104 }
105
106 PostCaptureModel::PostCaptureModel(QObject *parent) :
107   QStandardItemModel(parent) {
108
109   QHash<int, QByteArray> roles;
110   roles.insert(UrlRole, "url");
111   roles.insert(TitleRole, "title");
112   roles.insert(MimeTypeRole, "mimeType");
113   roles.insert(CreatedRole, "created");
114   roles.insert(FileNameRole, "fileName");
115
116   setRoleNames(roles);
117
118   if (m_mime.isEmpty()) {
119     m_mime.insert("jpg", "image/jpeg");
120     m_mime.insert("png", "image/png");
121     m_mime.insert("mp4", "video/mp4");
122     m_mime.insert("avi", "video/x-msvideo");
123   }
124 }
125
126 PostCaptureModel::~PostCaptureModel() {
127
128 }
129
130 QString PostCaptureModel::imagePath() const {
131   return m_imagePath;
132 }
133
134 void PostCaptureModel::setImagePath(const QString& path) {
135   if (m_imagePath != path) {
136     m_imagePath = path;
137     emit imagePathChanged();
138   }
139 }
140
141 QString PostCaptureModel::videoPath() const {
142   return m_videoPath;
143 }
144
145 void PostCaptureModel::setVideoPath(const QString& path) {
146   if (m_videoPath != path) {
147     m_videoPath = path;
148     emit videoPathChanged();
149   }
150 }
151
152 void PostCaptureModel::loadDir(const QDir& dir, QList<QStandardItem *>& out) {
153   QString path = dir.canonicalPath();
154
155   DIR *d = opendir(path.toLocal8Bit().constData());
156   if (!d) {
157     qmlInfo(this) << "Failed to open dir" << path;
158     return;
159   }
160
161   while (true) {
162     struct dirent *entry = readdir(d);
163     if (!entry) {
164       break;
165     }
166
167     if (QLatin1String(".") == entry->d_name || QLatin1String("..") == entry->d_name) {
168       continue;
169     }
170
171     if (!(entry->d_type == DT_LNK || entry->d_type == DT_REG)) {
172       continue;
173     }
174
175     out << new PostCaptureModelItem(path, entry->d_name);
176   }
177
178   closedir(d);
179 }
180
181 void PostCaptureModel::reload() {
182   QList<QStandardItem *> files;
183
184   QDir images(m_imagePath);
185   QDir videos(m_videoPath);
186
187   loadDir(images, files);
188
189   if (images.canonicalPath() != videos.canonicalPath()) {
190     loadDir(videos, files);
191   }
192
193   qSort(files.begin(), files.end(), lessThan);
194
195   invisibleRootItem()->appendRows(files);
196 }
197
198 void PostCaptureModel::clear() {
199   QStandardItemModel::clear();
200 }
201
202 void PostCaptureModel::remove(const QUrl& file) {
203   QString path(file.toLocalFile());
204
205   int count = invisibleRootItem()->rowCount();
206
207   for (int x = 0; x < count; x++) {
208     if (dynamic_cast<PostCaptureModelItem *>(invisibleRootItem()->child(x))->path() == path) {
209       invisibleRootItem()->removeRow(x);
210       return;
211     }
212   }
213 }
214
215 #if defined(QT5)
216 QHash<int, QByteArray> PostCaptureModel::roleNames() const {
217   return m_roles;
218 }
219
220 void PostCaptureModel::setRoleNames(const QHash<int, QByteArray>& roles) {
221   m_roles = roles;
222 }
223 #endif