main.qml 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. import QtQuick 1.1
  2. import QtMultimediaKit 1.1
  3. import QtMobility.sensors 1.1
  4. import CameraFeatures 1.0
  5. Rectangle {
  6. id: main
  7. property int counterCalled: 0 // how many times capture has been called
  8. property int counterSaved: 0 // how many pictures have been saved
  9. property bool sensorEnable: true
  10. // The resolution to capture the image at. If empty, the system will pick a good size.
  11. property string resolution: "3248x2448" // N9 4:3 8M
  12. property variant resolutionList: [] // resolutions supported by current device
  13. property int captureInterval: 300 // ms
  14. property variant imageList: [] // paths of saved images during the session
  15. width: 480
  16. height: 854
  17. color: "slategrey"
  18. focus: true
  19. Keys.onPressed: {
  20. console.log("onPressed")
  21. }
  22. Keys.onVolumeDownPressed: {
  23. // decrease resolution or something else
  24. console.log("onVolumeDownPressed")
  25. }
  26. Keys.onVolumeUpPressed: {
  27. // increase resolution ...
  28. console.log("onVolumeUpPressed")
  29. }
  30. Camera {
  31. id: camera
  32. anchors.fill: parent
  33. flashMode: Camera.FlashOff
  34. exposureMode: Camera.ExposureSports
  35. whiteBalanceMode: Camera.WhiteBalanceAuto
  36. captureResolution: main.resolution
  37. onImageCaptured: {
  38. // preview
  39. console.log("onImageCaptured. preview: " + preview)
  40. }
  41. onImageSaved: {
  42. // path
  43. console.log("onImageSaved. path: " + path)
  44. var list = imageList;
  45. list.push(path);
  46. imageList = list;
  47. main.counterSaved++;
  48. }
  49. onCaptureFailed: {
  50. // message
  51. console.log("onCaptureFailed. message: " + message)
  52. }
  53. onError: {
  54. // error, errorString
  55. console.log("onError. error: " + error + ", errorString: " + errorString)
  56. }
  57. }
  58. CameraFeatures {
  59. id: cameraFeat
  60. property int cameraDevice: 0
  61. function getFeatures() {
  62. var devices = getAvailableDevices(); // string list
  63. console.log("getFeatures. devices: " + devices); // primary,secondary
  64. startGetFeatures(devices[cameraDevice]);
  65. }
  66. Component.onCompleted: {
  67. console.log("CameraFeatures. Component.onCompleted")
  68. getFeatures();
  69. }
  70. onCameraDeviceChanged: {
  71. console.log("CameraFeatures.onCameraDeviceChanged")
  72. getFeatures()
  73. }
  74. onFeaturesRetrieved: {
  75. console.log("CameraFeatures.onFeaturesRetrieved")
  76. var list = cameraFeat.getSupportedResolutionsList();
  77. console.log("getSupportedResolutionsList: " + list)
  78. if (list) {
  79. main.resolutionList = list;
  80. }
  81. camera.start()
  82. }
  83. }
  84. //
  85. // New sensor types and classes for gyroscope and light sensors are made
  86. // available in API for future use. At the moment there is no devices having these sensors however.
  87. Accelerometer {
  88. id: motionSensor
  89. property int historyCount: 4 // how many values are stored for prev calculation
  90. property real threshold: 0.2 // diff between each previous value
  91. property variant previousX: [] // list of n previous values
  92. property variant previousY: [] // list of n previous values
  93. property variant previousZ: [] // list of n previous values
  94. property bool stableX: false // x values are within threshold
  95. property bool stableY: false // x values are within threshold
  96. property bool stableZ: false // x values are within threshold
  97. property variant almost: [0, 0, 0] // how close to stable 0..1
  98. property bool capture: stableX && stableY && stableZ
  99. function checkThreshold(reading) {
  100. previousX = checkHistoryLength(previousX, reading.x);
  101. stableX = checkThresholdAxis(previousX, 0);
  102. previousY = checkHistoryLength(previousY, reading.y);
  103. stableY = checkThresholdAxis(previousY, 1);
  104. previousZ = checkHistoryLength(previousZ, reading.z);
  105. stableZ = checkThresholdAxis(previousZ, 2);
  106. }
  107. // list = one of previousXYZ
  108. // r = reading.xyz
  109. function checkHistoryLength(list, r) {
  110. list.push(r);
  111. if (list.length > historyCount) {
  112. list.splice(0, 1);
  113. }
  114. return list;
  115. }
  116. // list = previous[X,Y,Z]
  117. function checkThresholdAxis(list, almostIndex) {
  118. var len = list.length;
  119. if (len > 1) {
  120. var total = 0;
  121. var step = 1 / len;
  122. var prev = list[0]; // initial
  123. var curr;
  124. for(var i = 1; i < len; ++i) {
  125. curr = list[i];
  126. if (Math.abs(curr - prev) > motionSensor.threshold) {
  127. return false;
  128. }
  129. prev = curr;
  130. total += step;
  131. // Need to write this every time to keep it up to date
  132. var almost = motionSensor.almost;
  133. almost[almostIndex] = total;
  134. motionSensor.almost = almost;
  135. }
  136. return true;
  137. }
  138. return false;
  139. }
  140. active: main.sensorEnable
  141. onReadingChanged: {
  142. if (reading) {
  143. checkThreshold(reading);
  144. var list = [
  145. "x: " + reading.x,
  146. "y: " + reading.y,
  147. "z: " + reading.z,
  148. "busy: " + motionSensor.busy,
  149. "resolution: " + main.resolution,
  150. "captureResolution: " + camera.captureResolution.width + "x" + camera.captureResolution.height,
  151. "aperture: " + camera.aperture,
  152. "exposureMode: " + camera.exposureMode,
  153. "shutterSpeed: " + camera.shutterSpeed,
  154. "exposureCompensation: " + camera.exposureCompensation,
  155. "Called: " + main.counterCalled,
  156. "Saved: " + main.counterSaved
  157. ];
  158. infoText.text = list.join("\n");
  159. }
  160. }
  161. /*
  162. The reading contains 3 values, measured in degrees per second that define the movement of
  163. the device around the x, y and z axes. Unlike QRotationReading, the values represent the current
  164. angular velocity rather than a fixed rotation. The measurements are in degrees per second.
  165. */
  166. }
  167. Item {
  168. id: infoBox
  169. width: main.width / 6
  170. anchors.left: parent.left
  171. anchors.top: parent.top
  172. anchors.bottom: parent.bottom
  173. Rectangle {
  174. anchors.fill: parent
  175. color: "black"
  176. opacity: 0.4
  177. }
  178. Text {
  179. id: infoText
  180. anchors.margins: 4
  181. wrapMode: Text.WordWrap
  182. color: "snow"
  183. font.pixelSize: 16
  184. }
  185. Column {
  186. anchors.bottom: parent.bottom
  187. spacing: 4
  188. Repeater {
  189. model: motionSensor.almost
  190. Rectangle {
  191. height: 10
  192. width: infoBox.width
  193. color: "pink"
  194. Rectangle {
  195. color: "lightgreen"
  196. height: parent.height
  197. width: parent.width * modelData
  198. }
  199. }
  200. }
  201. }
  202. }
  203. Flickable {
  204. id: resoList
  205. width: main.width / 6
  206. anchors.left: infoBox.right
  207. anchors.top: parent.top
  208. anchors.bottom: parent.bottom
  209. contentHeight: resoColumn.height
  210. Column {
  211. id: resoColumn
  212. spacing: 10
  213. Repeater {
  214. model: main.resolutionList
  215. Rectangle {
  216. width: resoList.width
  217. height: 24
  218. color: "slateblue"
  219. Text {
  220. anchors.centerIn: parent
  221. text: modelData.width + "x" + modelData.height
  222. color: "snow"
  223. font.pixelSize: 16
  224. }
  225. }
  226. }
  227. }
  228. }
  229. Timer {
  230. id: intervalTimer
  231. interval: main.captureInterval
  232. repeat: true
  233. triggeredOnStart: true
  234. running: pressArea.pressed || motionSensor.capture
  235. onTriggered: {
  236. //console.log("onTriggered. camera.lockStatus: " + camera.lockStatus)
  237. camera.captureImage();
  238. main.counterCalled++;
  239. }
  240. }
  241. // While mouse is pressed, images are taken
  242. MouseArea {
  243. id: pressArea
  244. anchors.fill: parent
  245. onPressAndHold: {
  246. console.log("onPressAndHold")
  247. }
  248. onPressed: {
  249. console.log("onPressed")
  250. }
  251. onReleased: {
  252. console.log("onReleased")
  253. }
  254. onCanceled: {
  255. console.log("onCanceled")
  256. }
  257. onDoubleClicked: {
  258. console.log("onDoubleClicked")
  259. }
  260. onPressedChanged: {
  261. console.log("onPressedChanged. pressed: " + pressed)
  262. }
  263. Rectangle {
  264. id: pressBox
  265. anchors.fill: parent
  266. color: "pink"
  267. opacity: 0.3
  268. visible: parent.pressed
  269. }
  270. }
  271. PinchArea {
  272. id: pinchArea
  273. property int resW: 0
  274. property int resH: 0
  275. property string resolution: ""
  276. property bool pinching: false
  277. visible: false
  278. anchors.fill: parent
  279. onPinchFinished: {
  280. console.log("onPinchFinished. scale: " + pinch.scale + ", angle: " + pinch.angle)
  281. main.resolution = pinchArea.resolution
  282. pinching = false;
  283. }
  284. onPinchStarted: {
  285. console.log("onPinchStarted. scale: " + pinch.scale + ", angle: " + pinch.angle)
  286. var list = main.resolution.split("x");
  287. resW = parseInt(list[0]);
  288. resH = parseInt(list[1]);
  289. pinching = true;
  290. }
  291. onPinchUpdated: {
  292. //console.log("onPinchUpdated. scale: " + pinch.scale + ", angle: " + pinch.angle)
  293. var rad = pinch.angle * Math.PI / 180
  294. var scaleW = Math.abs(Math.cos(rad) * pinch.scale);
  295. var scaleH = Math.abs(Math.sin(rad) * pinch.scale);
  296. // Prevent stucking to 0x0 by adding some pixels
  297. pinchArea.resolution = Math.round(resW * scaleW + 10) + "x" + Math.round(resH * scaleH + 10)
  298. }
  299. Item {
  300. anchors.fill: parent
  301. visible: pinchArea.pinching
  302. Rectangle {
  303. anchors.fill: parent
  304. color: "violet"
  305. opacity: 0.5
  306. }
  307. Column {
  308. anchors.centerIn: parent
  309. Text {
  310. text: "Use Pinch to change the desired resolution."
  311. font.pointSize: 20
  312. horizontalAlignment: Text.AlignHCenter
  313. }
  314. Text {
  315. text: pinchArea.resolution
  316. font.pointSize: 20
  317. horizontalAlignment: Text.AlignHCenter
  318. }
  319. }
  320. }
  321. }
  322. ListView {
  323. id: previewList
  324. anchors {
  325. top: main.top
  326. bottom: main.bottom
  327. right: main.right
  328. }
  329. clip: true
  330. contentHeight: childrenRect.height
  331. model: main.imageList
  332. width: main.width / 6
  333. delegate: Component {
  334. Image {
  335. width: previewList.width
  336. height: width / 2
  337. fillMode: Image.PreserveAspectCrop
  338. sourceSize.width: width
  339. sourceSize.height: height
  340. source: modelData
  341. Text {
  342. anchors.centerIn: parent
  343. text: modelData
  344. wrapMode: Text.WrapAnywhere
  345. }
  346. }
  347. }
  348. /*
  349. onAdd: {
  350. positionViewAtEnd();
  351. }*/
  352. }
  353. }