1 /*
2  *  Kaidan - A user-friendly XMPP client for every device!
3  *
4  *  Copyright (C) 2016-2021 Kaidan developers and contributors
5  *  (see the LICENSE file for a full list of copyright authors)
6  *
7  *  Kaidan is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  In addition, as a special exception, the author of Kaidan gives
13  *  permission to link the code of its release with the OpenSSL
14  *  project's "OpenSSL" library (or with modified versions of it that
15  *  use the same license as the "OpenSSL" library), and distribute the
16  *  linked executables. You must obey the GNU General Public License in
17  *  all respects for all of the code used other than "OpenSSL". If you
18  *  modify this file, you may extend this exception to your version of
19  *  the file, but you are not obligated to do so.  If you do not wish to
20  *  do so, delete this exception statement from your version.
21  *
22  *  Kaidan is distributed in the hope that it will be useful,
23  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
24  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  *  GNU General Public License for more details.
26  *
27  *  You should have received a copy of the GNU General Public License
28  *  along with Kaidan.  If not, see <http://www.gnu.org/licenses/>.
29  */
30 
31 #include "CameraModel.h"
32 
CameraInfo(const QString & deviceName)33 CameraInfo::CameraInfo(const QString &deviceName)
34 	: QCameraInfo(deviceName.toLocal8Bit())
35 {
36 }
37 
CameraInfo(const QCameraInfo & other)38 CameraInfo::CameraInfo(const QCameraInfo &other)
39 	: QCameraInfo(other)
40 {
41 }
42 
CameraModel(QObject * parent)43 CameraModel::CameraModel(QObject *parent)
44 : QAbstractListModel(parent)
45 {
46 	refresh();
47 }
48 
rowCount(const QModelIndex & parent) const49 int CameraModel::rowCount(const QModelIndex &parent) const
50 {
51 	return parent == QModelIndex() ? m_cameras.count() : 0;
52 }
53 
data(const QModelIndex & index,int role) const54 QVariant CameraModel::data(const QModelIndex &index, int role) const
55 {
56 	if (hasIndex(index.row(), index.column(), index.parent())) {
57 		const auto &cameraInfo(m_cameras[index.row()]);
58 
59 		switch (role) {
60 		case CameraModel::CustomRoles::IsNullRole:
61 			return cameraInfo.isNull();
62 		case CameraModel::CustomRoles::DeviceNameRole:
63 			return cameraInfo.deviceName();
64 		case CameraModel::CustomRoles::DescriptionRole:
65 			return cameraInfo.description();
66 		case CameraModel::CustomRoles::PositionRole:
67 			return cameraInfo.position();
68 		case CameraModel::CustomRoles::OrientationRole:
69 			return cameraInfo.orientation();
70 		case CameraModel::CustomRoles::CameraInfoRole:
71 			return QVariant::fromValue(CameraInfo(cameraInfo));
72 		}
73 	}
74 
75 	return QVariant();
76 }
77 
roleNames() const78 QHash<int, QByteArray> CameraModel::roleNames() const
79 {
80 	static const QHash<int, QByteArray> roles {
81 		{ IsNullRole, QByteArrayLiteral("isNull") },
82 		{ DeviceNameRole, QByteArrayLiteral("deviceName") },
83 		{ DescriptionRole, QByteArrayLiteral("description") },
84 		{ PositionRole, QByteArrayLiteral("position") },
85 		{ OrientationRole, QByteArrayLiteral("orientation") },
86 		{ CameraInfoRole, QByteArrayLiteral("cameraInfo") }
87 	};
88 
89 	return roles;
90 }
91 
cameras() const92 QList<QCameraInfo> CameraModel::cameras() const
93 {
94 	return m_cameras;
95 }
96 
defaultCamera()97 CameraInfo CameraModel::defaultCamera()
98 {
99 	return CameraInfo(QCameraInfo::defaultCamera());
100 }
101 
currentIndex() const102 int CameraModel::currentIndex() const
103 {
104 	return m_currentIndex;
105 }
106 
setCurrentIndex(int currentIndex)107 void CameraModel::setCurrentIndex(int currentIndex)
108 {
109 	if (currentIndex < 0 || currentIndex >= m_cameras.count()
110 		|| m_currentIndex == currentIndex) {
111 		return;
112 	}
113 
114 	m_currentIndex = currentIndex;
115 	emit currentIndexChanged();
116 }
117 
currentCamera() const118 CameraInfo CameraModel::currentCamera() const
119 {
120 	return m_currentIndex >= 0 && m_currentIndex < m_cameras.count()
121 		       ? CameraInfo(m_cameras[m_currentIndex])
122 		       : CameraInfo();
123 }
124 
setCurrentCamera(const CameraInfo & currentCamera)125 void CameraModel::setCurrentCamera(const CameraInfo &currentCamera)
126 {
127 	setCurrentIndex(m_cameras.indexOf(currentCamera));
128 }
129 
camera(int row) const130 CameraInfo CameraModel::camera(int row) const
131 {
132 	return hasIndex(row, 0)
133 		       ? CameraInfo(m_cameras[row])
134 		       : CameraInfo();
135 }
136 
indexOf(const QString & deviceName) const137 int CameraModel::indexOf(const QString &deviceName) const
138 {
139 	for (int i = 0; i < m_cameras.count(); ++i) {
140 		const auto &camera(m_cameras[i]);
141 
142 		if (camera.deviceName() == deviceName) {
143 			return i;
144 		}
145 	}
146 
147 	return -1;
148 }
149 
camera(const QString & deviceName)150 CameraInfo CameraModel::camera(const QString &deviceName)
151 {
152 	return CameraInfo(deviceName);
153 }
154 
camera(QCamera::Position position)155 CameraInfo CameraModel::camera(QCamera::Position position)
156 {
157 	const auto cameras = QCameraInfo::availableCameras(position);
158 	return cameras.isEmpty() ? CameraInfo() : CameraInfo(cameras.first());
159 }
160 
refresh()161 void CameraModel::refresh()
162 {
163 	const auto cameras = QCameraInfo::availableCameras();
164 
165 	if (m_cameras == cameras) {
166 		return;
167 	}
168 
169 	beginResetModel();
170 	const QString currentDeviceName = currentCamera().deviceName();
171 	const auto it = std::find_if(m_cameras.constBegin(), m_cameras.constEnd(),
172 		[&currentDeviceName](const QCameraInfo &deviceInfo) {
173 			return deviceInfo.deviceName() == currentDeviceName;
174 		});
175 
176 	m_cameras = cameras;
177 	m_currentIndex = it == m_cameras.constEnd() ? -1 : it - m_cameras.constBegin();
178 	endResetModel();
179 
180 	emit camerasChanged();
181 	emit currentIndexChanged();
182 }
183