├── .gitignore
├── LICENSE
├── README.md
├── harbour-advanced-camera.desktop
├── harbour-advanced-camera.pro
├── harbour-advanced-camera.svg
├── icons
├── 108x108
│ └── harbour-advanced-camera.png
├── 128x128
│ └── harbour-advanced-camera.png
├── 172x172
│ └── harbour-advanced-camera.png
└── 86x86
│ └── harbour-advanced-camera.png
├── qml
├── components
│ ├── AboutMedia.qml
│ ├── DockedListView.qml
│ ├── IconSwitch.qml
│ └── RoundButton.qml
├── cover
│ └── CoverPage.qml
├── harbour-advanced-camera.qml
├── pages
│ ├── AboutImage.qml
│ ├── AboutVideo.qml
│ ├── CameraUI.qml
│ ├── GalleryUI.qml
│ ├── GridOverlay.qml
│ ├── Settings.qml
│ ├── SettingsOverlay.qml
│ └── VideoPlayer.qml
└── pics
│ ├── icon-camera-focus-continuous.png
│ ├── icon-camera-focus-hyperfocal.png
│ ├── icon-camera-focus-manual.png
│ ├── icon-m-effect-aqua.svg
│ ├── icon-m-effect-blackboard.svg
│ ├── icon-m-effect-default.svg
│ ├── icon-m-effect-emboss.svg
│ ├── icon-m-effect-grayscale.svg
│ ├── icon-m-effect-negative.svg
│ ├── icon-m-effect-neon.svg
│ ├── icon-m-effect-none.svg
│ ├── icon-m-effect-posterize.svg
│ ├── icon-m-effect-sepia.svg
│ ├── icon-m-effect-sketch.svg
│ ├── icon-m-effect-solarize.svg
│ ├── icon-m-effect-whiteboard.svg
│ ├── icon-m-effect.png
│ ├── icon-m-iso-100.png
│ ├── icon-m-iso-1600.png
│ ├── icon-m-iso-200.png
│ ├── icon-m-iso-3200.png
│ ├── icon-m-iso-400.png
│ ├── icon-m-iso-6400.png
│ ├── icon-m-iso-800.png
│ ├── icon-m-iso-auto.png
│ ├── icon-m-iso-hjr.png
│ ├── icon-m-resolution.png
│ ├── icon-m-scene_mode_action.svg
│ ├── icon-m-scene_mode_ar.svg
│ ├── icon-m-scene_mode_asd.svg
│ ├── icon-m-scene_mode_backlight.svg
│ ├── icon-m-scene_mode_barcode.svg
│ ├── icon-m-scene_mode_beach.svg
│ ├── icon-m-scene_mode_candlelight.svg
│ ├── icon-m-scene_mode_fireworks.svg
│ ├── icon-m-scene_mode_flowers.svg
│ ├── icon-m-scene_mode_hdr.svg
│ ├── icon-m-scene_mode_landscape.svg
│ ├── icon-m-scene_mode_large_aperture.svg
│ ├── icon-m-scene_mode_night.svg
│ ├── icon-m-scene_mode_night_portrait.svg
│ ├── icon-m-scene_mode_none.svg
│ ├── icon-m-scene_mode_party.svg
│ ├── icon-m-scene_mode_portrait.svg
│ ├── icon-m-scene_mode_small_aperture.svg
│ ├── icon-m-scene_mode_snow.svg
│ ├── icon-m-scene_mode_sports.svg
│ ├── icon-m-scene_mode_spotlight.svg
│ ├── icon-m-scene_mode_steady_photo.svg
│ ├── icon-m-scene_mode_sunset.svg
│ ├── icon-m-scene_mode_theatre.svg
│ ├── icon-m-scene_mode_unknown.svg
│ ├── icon-m-tele-lense-active.png
│ ├── icon-m-tele-lense.png
│ ├── icon-m-tele-lense.svg
│ ├── icon-m-uwide-lense-active.png
│ ├── icon-m-uwide-lense.png
│ ├── icon-m-uwide-lense.svg
│ ├── icon-m-wide-lense-active.png
│ ├── icon-m-wide-lense.png
│ └── icon-m-wide-lense.svg
├── resolution.svg
├── rpm
├── harbour-advanced-camera.changes
├── harbour-advanced-camera.changes.run.in
├── harbour-advanced-camera.spec
└── harbour-advanced-camera.yaml
├── screenshots
├── screenshot1.png
├── screenshot2.png
├── screenshot3.png
├── screenshot4.png
├── screenshot5.png
└── screenshot6.png
├── src
├── deviceinfo.cpp
├── deviceinfo.h
├── effectsmodel.cpp
├── effectsmodel.h
├── exifmodel.cpp
├── exifmodel.h
├── exposuremodel.cpp
├── exposuremodel.h
├── flashmodel.cpp
├── flashmodel.h
├── focusmodel.cpp
├── focusmodel.h
├── fsoperations.cpp
├── fsoperations.h
├── harbour-advanced-camera.cpp
├── isomodel.cpp
├── isomodel.h
├── metadatamodel.cpp
├── metadatamodel.h
├── resolutionmodel.cpp
├── resolutionmodel.h
├── resourcehandler.cpp
├── resourcehandler.h
├── storagemodel.cpp
├── storagemodel.h
├── wbmodel.cpp
└── wbmodel.h
└── translations
├── harbour-advanced-camera-de.ts
├── harbour-advanced-camera-es.ts
├── harbour-advanced-camera-fi.ts
├── harbour-advanced-camera-fr.ts
├── harbour-advanced-camera-it.ts
├── harbour-advanced-camera-pl.ts
├── harbour-advanced-camera-ru.ts
├── harbour-advanced-camera-sv.ts
├── harbour-advanced-camera-zh_CN.ts
└── harbour-advanced-camera.ts
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea
2 | /RPMS
3 | harbour-advanced-camera.pro.user
4 | debugfiles.list
5 | debuglinks.list
6 | debugsourcefiles.list
7 | debugsources.list
8 | documentation.list
9 | elfbins.list
10 | harbour-advanced-camera
11 | Makefile
12 | *.o
13 | *.qm
14 | moc_*.cpp
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # harbour-advanced-camera
2 |
3 | This is a camera application for Sailfish which exposes all available camera paramters to the user.
4 |
5 | The application is licensed under the GPLv2+, with some source files specifically licensed under the LGPLv2(.1)+ so they can be re-used.
6 |
--------------------------------------------------------------------------------
/harbour-advanced-camera.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Type=Application
3 | X-Nemo-Application-Type=silica-qt5
4 | Icon=harbour-advanced-camera
5 | Exec=harbour-advanced-camera
6 | Name=Advanced Camera
7 | # translation example:
8 | # your app name in German locale (de)
9 | #
10 | # Remember to comment out the following line, if you do not want to use
11 | # a different app name in German locale (de).
12 | #Name[de]=harbour-advanced-camera
13 | Name[ru]=Улучшенная камера
14 |
15 | [X-Sailjail]
16 | Permissions=Audio;Location;RemovableMedia;Pictures;Videos
17 | OrganizationName=uk.co.piggz
18 | ApplicationName=AdvancedCamera
19 |
--------------------------------------------------------------------------------
/harbour-advanced-camera.pro:
--------------------------------------------------------------------------------
1 | # NOTICE:
2 | #
3 | # Application name defined in TARGET has a corresponding QML filename.
4 | # If name defined in TARGET is changed, the following needs to be done
5 | # to match new name:
6 | # - corresponding QML filename must be changed
7 | # - desktop icon filename must be changed
8 | # - desktop filename must be changed
9 | # - icon definition filename in desktop file must be changed
10 | # - translation filenames have to be changed
11 |
12 | # The name of your application
13 | TARGET = harbour-advanced-camera
14 |
15 | CONFIG += sailfishapp
16 |
17 | QT += multimedia
18 |
19 | SOURCES += src/harbour-advanced-camera.cpp \
20 | src/deviceinfo.cpp \
21 | src/effectsmodel.cpp \
22 | src/exifmodel.cpp \
23 | src/exposuremodel.cpp \
24 | src/isomodel.cpp \
25 | src/metadatamodel.cpp \
26 | src/resolutionmodel.cpp \
27 | src/wbmodel.cpp \
28 | src/focusmodel.cpp \
29 | src/flashmodel.cpp \
30 | src/fsoperations.cpp \
31 | src/resourcehandler.cpp \
32 | src/storagemodel.cpp
33 |
34 | DISTFILES += \
35 | README.md \
36 | qml/pics/icon-m-tele-lense-active.png \
37 | qml/pics/icon-m-tele-lense.svg \
38 | qml/pics/icon-m-uwide-lense-active.png \
39 | qml/pics/icon-m-uwide-lense.svg \
40 | qml/pics/icon-m-wide-lense-active.png \
41 | qml/pics/icon-m-wide-lense.svg \
42 | qml/components/AboutMedia.qml \
43 | qml/pages/AboutImage.qml \
44 | qml/pages/AboutVideo.qml \
45 | rpm/harbour-advanced-camera.changes.run.in \
46 | rpm/harbour-advanced-camera.spec \
47 | translations/*.ts \
48 | harbour-advanced-camera.desktop \
49 | qml/harbour-advanced-camera.qml \
50 | qml/components/DockedListView.qml \
51 | qml/components/IconSwitch.qml \
52 | qml/components/RoundButton.qml \
53 | qml/cover/CoverPage.qml \
54 | qml/pages/CameraUI.qml \
55 | qml/pages/GalleryUI.qml \
56 | qml/pages/Settings.qml \
57 | qml/pages/SettingsOverlay.qml
58 |
59 |
60 | SAILFISHAPP_ICONS = 86x86 108x108 128x128 172x172
61 |
62 | # to disable building translations every time, comment out the
63 | # following CONFIG line
64 | CONFIG += sailfishapp_i18n
65 |
66 | # German translation is enabled as an example. If you aren't
67 | # planning to localize your app, remember to comment out the
68 | # following TRANSLATIONS line. And also do not forget to
69 | # modify the localized app name in the the .desktop file.
70 | TRANSLATIONS += translations/harbour-advanced-camera-de.ts \
71 | translations/harbour-advanced-camera-es.ts \
72 | translations/harbour-advanced-camera-fi.ts \
73 | translations/harbour-advanced-camera-fr.ts \
74 | translations/harbour-advanced-camera-sv.ts \
75 | translations/harbour-advanced-camera-zh_CN.ts
76 |
77 | HEADERS += \
78 | src/effectsmodel.h \
79 | src/exifmodel.h \
80 | src/exposuremodel.h \
81 | src/isomodel.h \
82 | src/metadatamodel.h \
83 | src/resolutionmodel.h \
84 | src/wbmodel.h \
85 | src/focusmodel.h \
86 | src/flashmodel.h \
87 | src/fsoperations.h \
88 | src/resourcehandler.h \
89 | src/storagemodel.h
90 |
91 | LIBS += -ldl
92 |
--------------------------------------------------------------------------------
/icons/108x108/harbour-advanced-camera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/icons/108x108/harbour-advanced-camera.png
--------------------------------------------------------------------------------
/icons/128x128/harbour-advanced-camera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/icons/128x128/harbour-advanced-camera.png
--------------------------------------------------------------------------------
/icons/172x172/harbour-advanced-camera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/icons/172x172/harbour-advanced-camera.png
--------------------------------------------------------------------------------
/icons/86x86/harbour-advanced-camera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/icons/86x86/harbour-advanced-camera.png
--------------------------------------------------------------------------------
/qml/components/AboutMedia.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Layouts 1.0
3 | import Sailfish.Silica 1.0
4 |
5 | Rectangle {
6 | id: mediaInfo
7 | color: "black"
8 | anchors.fill: parent
9 |
10 | property var file
11 | property var fileSize
12 | property var mediaModel
13 | property var mediaSize
14 | property var mediaDuration: ""
15 |
16 | SilicaListView {
17 | anchors.fill: parent
18 | anchors.margins: Theme.paddingSmall
19 | model: mediaModel
20 | header: PageHeader {
21 | title: file
22 | description: mediaDuration + " " + mediaSize + " " + fileSize
23 | }
24 | delegate: metaDelegate
25 | VerticalScrollDecorator {
26 | }
27 | }
28 |
29 | Component {
30 | id: metaDelegate
31 | DetailItem {
32 | label: qsTranslate("exifKey", model.name)
33 | value: model.value
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/qml/components/DockedListView.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import Sailfish.Silica 1.0
3 |
4 | DockedPanel {
5 | id: panel
6 |
7 | property alias model: listView.model
8 | property var selectedItem
9 | modal: true
10 | animationDuration: 250
11 |
12 | signal clicked(var value)
13 |
14 | width: parent.width / 2
15 | height: parent.height
16 | z: 99
17 |
18 | dock: Dock.Left
19 | clip: true
20 |
21 | Rectangle {
22 | anchors.fill: parent
23 | color: Theme.colorScheme === Theme.LightOnDark ? "black" : "white"
24 | opacity: 0.7
25 |
26 | SilicaListView {
27 | id: listView
28 | anchors.fill: parent
29 | VerticalScrollDecorator {
30 | }
31 | clip: true
32 |
33 | delegate: ListItem {
34 | width: ListView.view.width
35 | height: Theme.itemSizeSmall
36 | highlighted: value === selectedItem
37 |
38 | Label {
39 | anchors {
40 | left: parent.left
41 | leftMargin: Theme.horizontalPageMargin
42 | right: parent.right
43 | rightMargin: Theme.horizontalPageMargin
44 | verticalCenter: parent.verticalCenter
45 | }
46 | color: highlighted ? Theme.highlightColor : Theme.primaryColor
47 | text: name
48 | truncationMode: TruncationMode.Fade
49 | }
50 | onClicked: {
51 | panel.clicked(value)
52 | }
53 | }
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/qml/components/IconSwitch.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.2
2 | import Sailfish.Silica 1.0
3 |
4 | Item {
5 | id: iconSwitch
6 | property string icon1Source: ""
7 | property string icon2Source: ""
8 | property string button1Name: ""
9 | property string button2Name: ""
10 | signal clicked(var name)
11 | property bool _hilighted2: false
12 |
13 | height: width * 2
14 |
15 | RoundButton {
16 | id: icon1
17 | width: parent.width
18 | height: width
19 | z: 0
20 | icon.source: icon1Source
21 |
22 | onClicked: {
23 | _hilighted2 = false
24 | iconSwitch.clicked(button1Name)
25 | }
26 | }
27 |
28 | RoundButton {
29 | id: icon2
30 | width: parent.width
31 | height: width
32 | anchors.top: icon1.bottom
33 | z: 0
34 | icon.source: icon2Source
35 |
36 | onClicked: {
37 | _hilighted2 = true
38 | iconSwitch.clicked(button2Name)
39 | }
40 | }
41 |
42 | Rectangle {
43 | id: highlighter
44 | radius: width / 2
45 | width: parent.width
46 | height: width
47 | opacity: 0.5
48 | z: 1
49 | y: _hilighted2 ? parent.height / 2 : 0
50 | Behavior on y {
51 | NumberAnimation {
52 | duration: 100
53 | }
54 | }
55 | color: Theme.highlightBackgroundColor
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/qml/components/RoundButton.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.2
2 | import Sailfish.Silica 1.0
3 |
4 | Item {
5 | id: button
6 | property string image: ""
7 | property alias icon: iconButton.icon
8 | property int size: Theme.itemSizeSmall
9 | property alias down: iconButton.down
10 | signal clicked
11 | signal pressed
12 |
13 | height: size
14 | width: size
15 |
16 | Rectangle {
17 | anchors.fill: parent
18 | radius: width / 2
19 | color: Theme.colorScheme === Theme.LightOnDark ? "black" : "white"
20 | opacity: 0.7
21 |
22 | IconButton {
23 | id: iconButton
24 | anchors.centerIn: parent
25 | anchors.fill: parent
26 | icon.anchors.fill: icon.parent
27 | icon.anchors.margins: Theme.paddingMedium
28 | icon.source: button.image
29 | icon.fillMode: Image.PreserveAspectFit
30 | onClicked: button.clicked()
31 | onPressed: button.pressed()
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/qml/cover/CoverPage.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import Sailfish.Silica 1.0
3 |
4 | CoverBackground {
5 | TextArea {
6 | id: label
7 | anchors.centerIn: parent
8 | color: Theme.primaryColor
9 | font.bold: true
10 | horizontalAlignment: Text.AlignHCenter
11 | readOnly: true
12 | width: parent.width - 2 * Theme.paddingSmall
13 | text: qsTr("Advanced Camera")
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/qml/harbour-advanced-camera.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import Sailfish.Silica 1.0
3 | import QtMultimedia 5.6
4 | import "pages"
5 |
6 | ApplicationWindow {
7 | id: window
8 | property bool loadingComplete: false;
9 | Settings {
10 | id: settings
11 | }
12 |
13 | Rectangle {
14 | parent: window
15 | anchors.fill: parent
16 | z: -1
17 | color: "black"
18 | }
19 |
20 | VideoOutput {
21 | id: captureView
22 | source: cameraUI.camera
23 | width: window.width
24 | height: window.height
25 | z: -1
26 | }
27 |
28 | initialPage: CameraUI {
29 | id: cameraUI
30 | }
31 |
32 | allowedOrientations: Orientation.All
33 | cover: Qt.resolvedUrl("cover/CoverPage.qml")
34 |
35 | Component.onCompleted: {
36 | loadingComplete = true;
37 | }
38 |
39 | onApplicationActiveChanged: {
40 | if (Qt.application.state == Qt.ApplicationActive) {
41 | cameraUI.camera.start();
42 | } else {
43 | cameraUI.camera.stop();
44 | }
45 | }
46 |
47 | Keys.onPressed: {
48 | console.log(event.key);
49 | if (event.isAutoRepeat) {
50 | return
51 | }
52 | if (event.key === Qt.Key_VolumeUp) {
53 | cameraUI.volUp();
54 | } else if (event.key === Qt.Key_VolumeDown) {
55 | cameraUI.volDown();
56 | } else if (event.key === Qt.Key_Camera) {
57 | console.log("Cmamera key");
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/qml/pages/AboutImage.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import Sailfish.Silica 1.0
3 | import QtMultimedia 5.6
4 | import uk.co.piggz.harbour_advanced_camera 1.0
5 | import "../components/"
6 |
7 | Page {
8 | id: pageImage
9 | property var filePath
10 | property var fileName
11 |
12 | // The effective value will be restricted by ApplicationWindow.allowedOrientations
13 | allowedOrientations: Orientation.All
14 |
15 | function sizeToStr(siz) {
16 | return siz.width + "x" + siz.height
17 | }
18 |
19 | Image {
20 | id: image
21 | visible: false
22 | source: filePath
23 | asynchronous: true
24 | onStatusChanged: {
25 | if (status === Image.Ready) {
26 | mediaAbout.mediaSize = sizeToStr(sourceSize)
27 | }
28 | }
29 | }
30 |
31 | ExifModel {
32 | id: modelExif
33 | source: filePath
34 | }
35 |
36 | AboutMedia {
37 | id: mediaAbout
38 | mediaModel: modelExif
39 | mediaSize: ""
40 | file: fileName
41 | fileSize: fsOperations.getFileSizeHuman(filePath)
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/qml/pages/AboutVideo.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import Sailfish.Silica 1.0
3 | import QtMultimedia 5.6
4 | import uk.co.piggz.harbour_advanced_camera 1.0
5 | import "../components/"
6 |
7 | Page {
8 | id: pageVideo
9 | property var filePath
10 | property var fileName
11 |
12 | // The effective value will be restricted by ApplicationWindow.allowedOrientations
13 | allowedOrientations: Orientation.All
14 |
15 | function sizeToStr(siz) {
16 | return siz.width + "x" + siz.height
17 | }
18 |
19 | function msToTime(millis) {
20 | return new Date(millis).toISOString().substr(11, 8)
21 | }
22 |
23 | MediaPlayer {
24 | id: mediaPlayer
25 | source: filePath
26 | autoPlay: false
27 |
28 | onStatusChanged: {
29 | if (status === MediaPlayer.Loaded) {
30 | mediaAbout.mediaSize = sizeToStr(metaData.resolution)
31 | }
32 | }
33 |
34 | onDurationChanged: {
35 | mediaAbout.mediaDuration = msToTime(duration)
36 | }
37 |
38 | Component.onCompleted: {
39 | modelVideo.setPlayer(mediaPlayer)
40 | }
41 | }
42 |
43 | MetadataModel {
44 | id: modelVideo
45 | }
46 |
47 | AboutMedia {
48 | id: mediaAbout
49 | mediaModel: modelVideo
50 | mediaSize: ""
51 | file: fileName
52 | fileSize: fsOperations.getFileSizeHuman(filePath)
53 | mediaDuration: ""
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/qml/pages/GalleryUI.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.5
2 | import Sailfish.Share 1.0
3 | import Sailfish.Silica 1.0
4 | import QtMultimedia 5.6
5 | import Nemo.Thumbnailer 1.0
6 | import uk.co.piggz.harbour_advanced_camera 1.0
7 | import "../components/"
8 |
9 | Page {
10 | id: galleryPage
11 |
12 | property var fileList: ({
13 |
14 | })
15 | property alias showButtons: btnClose.visible
16 |
17 | // The effective value will be restricted by ApplicationWindow.allowedOrientations
18 | allowedOrientations: Orientation.All
19 |
20 | backNavigation: false
21 |
22 | function isVideo(idx) {
23 | return fileList.get(idx).isVideo
24 | }
25 |
26 | function removeFile(idx) {
27 | var path = fileList.get(idx).filePath
28 | console.log("Removing", path)
29 | if (fsOperations.deleteFile(path)) {
30 | fileList.remove(idx)
31 | if (gallery.count === 0) {
32 | console.log("Closing empty gallery!")
33 | pageStack.pop()
34 | }
35 | } else {
36 | console.log("Error deleting file:", path)
37 | }
38 | }
39 |
40 | function getFileName(idx) {
41 | var fullPath = fileList.get(idx).filePath
42 | var lastSep = fullPath.lastIndexOf("/")
43 | var fileName = fullPath.substr(lastSep + 1, fullPath.length - lastSep)
44 | return fileName
45 | }
46 |
47 | RoundButton {
48 | id: btnClose
49 |
50 | visible: true
51 | icon.source: "image://theme/icon-m-close"
52 | size: Theme.itemSizeMedium
53 |
54 | anchors {
55 | top: parent.top
56 | topMargin: Theme.paddingMedium
57 | right: parent.right
58 | rightMargin: Theme.paddingMedium
59 | }
60 |
61 | onClicked: {
62 | console.log("Clicked close button")
63 | pageStack.pop()
64 | }
65 | }
66 |
67 | RoundButton {
68 | id: btnAbout
69 |
70 | visible: showButtons
71 | icon.source: "image://theme/icon-m-about"
72 | size: Theme.itemSizeMedium
73 |
74 | anchors {
75 | top: parent.top
76 | topMargin: Theme.paddingMedium
77 | left: parent.left
78 | leftMargin: Theme.paddingMedium
79 | }
80 |
81 | onClicked: {
82 | var filePath = fileList.get(gallery.currentIndex).filePath
83 | var mediaPage = isVideo(gallery.currentIndex) ? "AboutVideo.qml" : "AboutImage.qml"
84 | pageStack.push(Qt.resolvedUrl(mediaPage), {
85 | "filePath": filePath,
86 | "fileName": getFileName(gallery.currentIndex),
87 | })
88 | }
89 | }
90 |
91 | RemorsePopup {
92 | id: remorse
93 | }
94 |
95 | Row {
96 | id: rowBottom
97 |
98 | visible: showButtons
99 | spacing: Theme.paddingMedium
100 | anchors {
101 | horizontalCenter: parent.horizontalCenter
102 | bottom: parent.bottom
103 | bottomMargin: Theme.paddingMedium
104 | }
105 |
106 | RoundButton {
107 | id: btnRemove
108 |
109 | icon.source: "image://theme/icon-m-delete"
110 | size: Theme.itemSizeMedium
111 |
112 | function showRemorseItem() {
113 | var deleteIndex = gallery.currentIndex
114 | remorse.execute(qsTr("Deleting %1").arg(getFileName(
115 | deleteIndex)),
116 | function () {
117 | removeFile(deleteIndex)
118 | })
119 | }
120 |
121 | onClicked: {
122 | console.log("Clicked delete button")
123 | showRemorseItem()
124 | }
125 | }
126 |
127 | ShareAction {
128 | id: shareAction
129 | }
130 |
131 | RoundButton {
132 | id: btnShare
133 |
134 | icon.source: "image://theme/icon-m-share"
135 | size: Theme.itemSizeMedium
136 |
137 | onClicked: {
138 | var filePath = fileList.get(gallery.currentIndex).filePath
139 | var mimeType = isVideo(gallery.currentIndex) ? "video/mp4" : "image/jpeg"
140 | shareAction.resources = [filePath]
141 | shareAction.mimeType = mimeType
142 | shareAction.trigger()
143 | }
144 | }
145 | }
146 |
147 | SlideshowView {
148 | id: gallery
149 |
150 | clip: true
151 | width: parent.width
152 | height: parent.height
153 | z: -1
154 |
155 | model: fileList
156 | currentIndex: count - 1
157 |
158 | delegate: Rectangle {
159 | id: delegate
160 | width: parent.width
161 | height: parent.height
162 | color: 'black'
163 |
164 | Thumbnail {
165 | id: thumbnail
166 |
167 | sourceSize.width: parent.width
168 | sourceSize.height: parent.height
169 | anchors.fill: parent
170 | fillMode: Thumbnail.PreserveAspectFit
171 | source: filePath
172 | mimeType: isVideo ? "video/" : "image/"
173 | smooth: true
174 |
175 | MouseArea {
176 | anchors.fill: parent
177 | onClicked: {
178 | showButtons = !showButtons
179 | }
180 | }
181 | }
182 |
183 | RoundButton {
184 | id: btnPlay
185 |
186 | visible: isVideo
187 | anchors.centerIn: parent
188 | icon.source: "image://theme/icon-m-play"
189 | size: Theme.itemSizeMedium
190 |
191 | onClicked: {
192 | pageStack.push(Qt.resolvedUrl("VideoPlayer.qml"), {
193 | "videoFile": filePath
194 | }, PageStackAction.Immediate)
195 | }
196 | }
197 | }
198 | }
199 | }
200 |
--------------------------------------------------------------------------------
/qml/pages/GridOverlay.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import Sailfish.Silica 1.0
3 |
4 | Item {
5 | id: root
6 |
7 | property double aspect: 16.0 / 9.0
8 | visible: settings.global.gridMode != "none"
9 | anchors.centerIn: parent
10 | width: parent.height * aspect
11 | height: parent.height
12 |
13 | function horizontalLines(id) {
14 | if (id === "thirds")
15 | return [0.33, 0.66]
16 | if (id === "ambience")
17 | return [0.21, 0.79]
18 | return []
19 | }
20 |
21 | function verticalLines(id) {
22 | if (id === "thirds")
23 | return [0.33, 0.66]
24 | if (id === "ambience")
25 | return [0.2333, 0.7666]
26 | return []
27 | }
28 |
29 | Repeater {
30 | model: horizontalLines(settings.global.gridMode)
31 |
32 | delegate: Item {
33 | width: parent.width
34 | height: 5
35 |
36 | Rectangle {
37 | id: left
38 | width: parent.width / 2
39 | height: 5
40 | y: root.height * modelData
41 |
42 | color: "#88ffffff"
43 | }
44 |
45 | OpacityRampEffect {
46 | sourceItem: left
47 | direction: OpacityRamp.RightToLeft
48 | }
49 |
50 | Rectangle {
51 | id: right
52 | width: parent.width / 2
53 | height: 5
54 | y: root.height * modelData
55 | x: root.width / 2
56 |
57 | color: "#88ffffff"
58 | }
59 |
60 | OpacityRampEffect {
61 | sourceItem: right
62 | direction: OpacityRamp.LeftToRight
63 | }
64 | }
65 | }
66 |
67 | Repeater {
68 | model: verticalLines(settings.global.gridMode)
69 |
70 | delegate: Item {
71 | width: 5
72 | height: parent.height
73 |
74 | Rectangle {
75 | id: up
76 | width: 5
77 | height: parent.height / 2
78 | x: root.width * modelData
79 |
80 | color: "#88ffffff"
81 | }
82 |
83 | OpacityRampEffect {
84 | sourceItem: up
85 | direction: OpacityRamp.BottomToTop
86 | }
87 |
88 | Rectangle {
89 | id: bottom
90 | width: 5
91 | height: parent.height / 2
92 | x: root.width * modelData
93 | y: up.height
94 |
95 | color: "#88ffffff"
96 | }
97 |
98 | OpacityRampEffect {
99 | sourceItem: bottom
100 | direction: OpacityRamp.TopToBottom
101 | }
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/qml/pages/Settings.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtMultimedia 5.4
3 | import Nemo.Configuration 1.0
4 | import Sailfish.Silica 1.0
5 |
6 | Item {
7 | property alias global: globalSettings
8 | property alias mode: modeSettings
9 | property alias jollaCamera: jollaCameraSettings
10 |
11 | property variant enabledCameras: [] //Calculated on startup and when disabledCameras changes
12 |
13 | ConfigurationGroup {
14 | id: globalSettings
15 | path: "/uk/co/piggz/harbour-advanced-camera"
16 | property int cameraCount: 0 //default to 0 and get populated on startup
17 | property string cameraId: "0"
18 | property string captureMode: "image"
19 | property bool swapZoomControl: false
20 | property string gridMode: "none"
21 | property int videoBitrate: 12800000
22 | property int audioBitrate: 128000
23 | property string storagePath: StandardPaths.home
24 | property bool locationMetadata: true
25 | property bool enableWideCameraButtons: true
26 | property string disabledCameras: ""
27 | property bool showManualControls: false
28 |
29 | ConfigurationGroup {
30 | id: modeSettings
31 | path: globalSettings.cameraId + "/" + globalSettings.captureMode
32 |
33 | property int effect: CameraImageProcessing.ColorFilterNone
34 | property int exposure: Camera.ExposureManual
35 | property int flash: Camera.FlashOff
36 | property int focus: CameraFocus.FocusContinuous
37 | property int iso: 0
38 | property string resolution: ""
39 | property int whiteBalance: CameraImageProcessing.WhiteBalanceAuto
40 | }
41 | }
42 |
43 | ConfigurationGroup {
44 | id: jollaCameraSettings
45 | path: "/apps/jolla-camera/" + globalSettings.cameraId + "/image"
46 |
47 | property string viewfinderResolution
48 | property string viewfinderResolution_16_9
49 | property string viewfinderResolution_4_3
50 | }
51 |
52 | function strToSize(siz) {
53 | var w = parseInt(siz.substring(0, siz.indexOf("x")))
54 | var h = parseInt(siz.substring(siz.indexOf("x") + 1))
55 | return Qt.size(w, h)
56 | }
57 |
58 | function sizeToStr(siz) {
59 | return siz.width + "x" + siz.height
60 | }
61 |
62 | //Return either the current mode resolution or default resolution for that mode
63 | function resolution(mode) {
64 | if (settings.global.captureMode === mode
65 | && settings.mode.resolution !== "") {
66 | var res = strToSize(settings.mode.resolution)
67 | if (modelResolution.isValidResolution(res, mode)) {
68 | return res
69 | }
70 | }
71 | return modelResolution.defaultResolution(mode)
72 | }
73 |
74 | function calculateEnabledCameras()
75 | {
76 | settings.enabledCameras = []
77 | for (var i = 0; i < globalSettings.cameraCount; ++i) {
78 | if (settings.global.disabledCameras.indexOf("[" + QtMultimedia.availableCameras[i].deviceId + "]") == -1) {
79 | settings.enabledCameras.push(QtMultimedia.availableCameras[i].deviceId)
80 | }
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/qml/pages/VideoPlayer.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import Sailfish.Silica 1.0
3 | import QtMultimedia 5.6
4 | import Nemo.KeepAlive 1.2
5 | import "../components/"
6 |
7 | Page {
8 | id: videoPage
9 |
10 | // The effective value will be restricted by ApplicationWindow.allowedOrientations
11 | allowedOrientations: Orientation.All
12 |
13 | backNavigation: false
14 |
15 | property string videoFile
16 | property double controlsOpacity: 1.0
17 |
18 | DisplayBlanking {
19 | preventBlanking: player.playbackState === MediaPlayer.PlayingState
20 | }
21 |
22 | Rectangle {
23 | anchors.fill: parent
24 | color: "black"
25 |
26 | MediaPlayer {
27 | id: player
28 |
29 | source: "file://" + videoFile
30 | autoPlay: true
31 |
32 | onPositionChanged: {
33 | seekSlider.value = position
34 | }
35 |
36 | onStopped: {
37 | pageStack.pop(null, true)
38 | }
39 | }
40 |
41 | VideoOutput {
42 | id: video
43 |
44 | anchors.fill: parent
45 | source: player
46 | fillMode: VideoOutput.PreserveAspectFit
47 |
48 | MouseArea {
49 | anchors.fill: parent
50 | onClicked: {
51 | controlsOpacity > 0 ? controlsOpacity = 0 : controlsOpacity = 1.0
52 | }
53 | }
54 | }
55 |
56 | Item {
57 | id: itemsControls
58 | anchors.fill: parent
59 | opacity: controlsOpacity
60 |
61 | Behavior on opacity {
62 | FadeAnimation {
63 | }
64 | }
65 |
66 | RoundButton {
67 | id: btnCloseVideo
68 |
69 | enabled: controlsOpacity > 0
70 | icon.source: "image://theme/icon-m-close"
71 | size: Theme.itemSizeMedium
72 |
73 | anchors {
74 | top: parent.top
75 | topMargin: Theme.paddingMedium
76 | right: parent.right
77 | rightMargin: Theme.paddingMedium
78 | }
79 |
80 | onClicked: {
81 | pageStack.pop(null, true)
82 | }
83 | }
84 |
85 | RoundButton {
86 | id: btnPlayPause
87 |
88 | enabled: controlsOpacity > 0
89 | icon.source: player.playbackState === MediaPlayer.PlayingState ? "image://theme/icon-m-pause" : "image://theme/icon-m-play"
90 | size: Theme.itemSizeMedium
91 | anchors.centerIn: parent
92 |
93 | onClicked: {
94 | if (player.playbackState === MediaPlayer.PausedState) {
95 | player.play()
96 | } else if (player.playbackState === MediaPlayer.PlayingState) {
97 | player.pause()
98 | } else if (player.playbackState === MediaPlayer.StoppedState) {
99 | player.seek(0)
100 | player.play()
101 | }
102 | }
103 | }
104 |
105 | Row {
106 | id: rowBottomVideo
107 |
108 | width: parent.width
109 | anchors {
110 | horizontalCenter: parent.horizontalCenter
111 | bottom: parent.bottom
112 | bottomMargin: Theme.paddingMedium
113 | }
114 |
115 | Slider {
116 | id: seekSlider
117 |
118 | width: parent.width
119 | anchors.verticalCenter: parent.verticalCenter
120 | minimumValue: 0
121 | maximumValue: player.duration > 0 ? player.duration : 1
122 | value: player.position
123 | stepSize: 0
124 | enabled: player.seekable && controlsOpacity > 0
125 |
126 | onReleased: {
127 | player.seek(value)
128 | }
129 | }
130 | }
131 |
132 | Timer {
133 | running: true
134 | interval: 333
135 | repeat: false
136 | onTriggered: controlsOpacity = 0
137 | }
138 | }
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/qml/pics/icon-camera-focus-continuous.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/qml/pics/icon-camera-focus-continuous.png
--------------------------------------------------------------------------------
/qml/pics/icon-camera-focus-hyperfocal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/qml/pics/icon-camera-focus-hyperfocal.png
--------------------------------------------------------------------------------
/qml/pics/icon-camera-focus-manual.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/qml/pics/icon-camera-focus-manual.png
--------------------------------------------------------------------------------
/qml/pics/icon-m-effect-aqua.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-effect-blackboard.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-effect-default.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-effect-emboss.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-effect-grayscale.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-effect-negative.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-effect-neon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-effect-none.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-effect-posterize.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-effect-sepia.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-effect-sketch.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-effect-solarize.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-effect-whiteboard.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-effect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/qml/pics/icon-m-effect.png
--------------------------------------------------------------------------------
/qml/pics/icon-m-iso-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/qml/pics/icon-m-iso-100.png
--------------------------------------------------------------------------------
/qml/pics/icon-m-iso-1600.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/qml/pics/icon-m-iso-1600.png
--------------------------------------------------------------------------------
/qml/pics/icon-m-iso-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/qml/pics/icon-m-iso-200.png
--------------------------------------------------------------------------------
/qml/pics/icon-m-iso-3200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/qml/pics/icon-m-iso-3200.png
--------------------------------------------------------------------------------
/qml/pics/icon-m-iso-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/qml/pics/icon-m-iso-400.png
--------------------------------------------------------------------------------
/qml/pics/icon-m-iso-6400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/qml/pics/icon-m-iso-6400.png
--------------------------------------------------------------------------------
/qml/pics/icon-m-iso-800.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/qml/pics/icon-m-iso-800.png
--------------------------------------------------------------------------------
/qml/pics/icon-m-iso-auto.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/qml/pics/icon-m-iso-auto.png
--------------------------------------------------------------------------------
/qml/pics/icon-m-iso-hjr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/qml/pics/icon-m-iso-hjr.png
--------------------------------------------------------------------------------
/qml/pics/icon-m-resolution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/qml/pics/icon-m-resolution.png
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_action.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_ar.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_asd.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_backlight.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_barcode.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_beach.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_candlelight.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_fireworks.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_flowers.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_hdr.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_landscape.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_large_aperture.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_night.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_night_portrait.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_none.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_party.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_portrait.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_small_aperture.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_snow.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_sports.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_spotlight.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_steady_photo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_sunset.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_theatre.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-scene_mode_unknown.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-tele-lense-active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/qml/pics/icon-m-tele-lense-active.png
--------------------------------------------------------------------------------
/qml/pics/icon-m-tele-lense.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/qml/pics/icon-m-tele-lense.png
--------------------------------------------------------------------------------
/qml/pics/icon-m-tele-lense.svg:
--------------------------------------------------------------------------------
1 |
2 |
107 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-uwide-lense-active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/qml/pics/icon-m-uwide-lense-active.png
--------------------------------------------------------------------------------
/qml/pics/icon-m-uwide-lense.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/qml/pics/icon-m-uwide-lense.png
--------------------------------------------------------------------------------
/qml/pics/icon-m-uwide-lense.svg:
--------------------------------------------------------------------------------
1 |
2 |
122 |
--------------------------------------------------------------------------------
/qml/pics/icon-m-wide-lense-active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/qml/pics/icon-m-wide-lense-active.png
--------------------------------------------------------------------------------
/qml/pics/icon-m-wide-lense.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/qml/pics/icon-m-wide-lense.png
--------------------------------------------------------------------------------
/qml/pics/icon-m-wide-lense.svg:
--------------------------------------------------------------------------------
1 |
2 |
111 |
--------------------------------------------------------------------------------
/rpm/harbour-advanced-camera.changes:
--------------------------------------------------------------------------------
1 | # Rename this file as harbour-advanced-camera.changes to include changelog
2 | # entries in your RPM file.
3 | #
4 | # Add new changelog entries following the format below.
5 | # Add newest entries to the top of the list.
6 | # Separate entries from eachother with a blank line.
7 | #
8 | # Alternatively, if your changelog is automatically generated (e.g. with
9 | # the git-change-log command provided with Sailfish OS SDK), create a
10 | # harbour-advanced-camera.changes.run script to let mb2 run the required commands for you.
11 |
12 | # * date Author's Name version-release
13 | # - Summary of changes
14 |
15 | * Mon Oct 11 2021 Adam Pigg 0.9.5-1
16 | - Several improvements from Lukáš Karas:
17 | - Dont use an unsupported focus mode
18 | - Better viewfinder resolution selection
19 | - Update models when the camera changes
20 | - Simulate manual focus mode
21 | - Gallery media information view
22 | - Turn off GPS correctly
23 | - Manual exposure slider
24 | - Added settings to turn off telelense buttons
25 | - Added option to turn off manual exposure
26 | - Added optiont to enable/disable camera selection
27 | - Added current camera label
28 |
--------------------------------------------------------------------------------
/rpm/harbour-advanced-camera.changes.run.in:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Rename this file as harbour-advanced-camera.changes.run to let mb2 automatically
4 | # generate changelog from well formatted Git commit messages and tag
5 | # annotations.
6 |
7 | git-change-log
8 |
9 | # Here are some basic examples how to change from the default behavior. Run
10 | # git-change-log --help inside the Sailfish OS SDK chroot or build engine to
11 | # learn all the options git-change-log accepts.
12 |
13 | # Use a subset of tags
14 | #git-change-log --tags refs/tags/my-prefix/*
15 |
16 | # Group entries by minor revision, suppress headlines for patch-level revisions
17 | #git-change-log --dense '/[0-9]\+\.[0-9\+$'
18 |
19 | # Trim very old changes
20 | #git-change-log --since 2014-04-01
21 | #echo '[ Some changelog entries trimmed for brevity ]'
22 |
23 | # Use the subjects (first lines) of tag annotations when no entry would be
24 | # included for a revision otherwise
25 | #git-change-log --auto-add-annotations
26 |
--------------------------------------------------------------------------------
/rpm/harbour-advanced-camera.spec:
--------------------------------------------------------------------------------
1 | #
2 | # Do NOT Edit the Auto-generated Part!
3 | # Generated by: spectacle version 0.32
4 | #
5 |
6 | Name: harbour-advanced-camera
7 |
8 | # >> macros
9 | # << macros
10 |
11 | %{!?qtc_qmake:%define qtc_qmake %qmake}
12 | %{!?qtc_qmake5:%define qtc_qmake5 %qmake5}
13 | %{!?qtc_make:%define qtc_make make}
14 | %{?qtc_builddir:%define _builddir %qtc_builddir}
15 | Summary: Advanced camera
16 | Version: 0.9.8
17 | Release: 1
18 | Group: Qt/Qt
19 | License: GPLv2
20 | URL: http://github.com/piggz/harbour-advanced-camera
21 | Source0: %{name}-%{version}.tar.bz2
22 | Source100: harbour-advanced-camera.yaml
23 | Requires: sailfishsilica-qt5 >= 0.10.9
24 | BuildRequires: pkgconfig(sailfishapp) >= 1.0.2
25 | BuildRequires: pkgconfig(Qt5Core)
26 | BuildRequires: pkgconfig(Qt5Multimedia)
27 | BuildRequires: pkgconfig(Qt5Qml)
28 | BuildRequires: pkgconfig(Qt5Quick)
29 | BuildRequires: qt5-qttools-linguist
30 | BuildRequires: ssu-sysinfo-devel
31 | BuildRequires: libexif-devel
32 | BuildRequires: desktop-file-utils
33 |
34 | %description
35 | Advanced Camera (aka piggz-o-vision) is a community camera application for sailfish devices which utilises the latest features in 3.0.2 to query/set parameters supported by the device.
36 |
37 | Allows full control over:
38 | Effects
39 | Exposure/scene modes
40 | Focus mode
41 | Resolution
42 | White Balance
43 | Flash mode
44 | ISO
45 |
46 | Currently selected parameters are displayed on the buttons where possible.
47 |
48 | Tapping the screen sets the focus circle when in Auto/Macro/Continuous
49 |
50 | Hold the shutter button to focus and take an image when in Auto/Macro/Continuous focus mode, other modes take an instant image.
51 |
52 | Exposure mode will typically provide a HDR mode for taking HDR images.
53 |
54 | %if "%{?vendor}" == "chum"
55 | PackageName: Advanced Camera
56 | Type: desktop-application
57 | DeveloperName: Adam Pigg
58 | Categories:
59 | - Media
60 | - Video
61 | Custom:
62 | Repo: https://github.com/piggz/harbour-advanced-camera
63 | Icon: https://raw.githubusercontent.com/piggz/harbour-advanced-camera/master/harbour-advanced-camera.svg
64 | Screenshots:
65 | - https://github.com/piggz/harbour-advanced-camera/raw/master/screenshots/screenshot4.png
66 | - https://github.com/piggz/harbour-advanced-camera/raw/master/screenshots/screenshot5.png
67 | - https://github.com/piggz/harbour-advanced-camera/raw/master/screenshots/screenshot6.png
68 | Url:
69 | Homepage: https://github.com/piggz/harbour-advanced-camera
70 | Help: https://github.com/piggz/harbour-advanced-camera/discussions
71 | Bugtracker: https://github.com/piggz/harbour-advanced-camera/issues
72 | Donation: https://www.paypal.me/piggz
73 | %endif
74 |
75 | %prep
76 | %setup -q -n %{name}-%{version}
77 |
78 | # >> setup
79 | # << setup
80 |
81 | %build
82 | # >> build pre
83 | # << build pre
84 |
85 | %qtc_qmake5
86 |
87 | %qtc_make %{?_smp_mflags}
88 |
89 | # >> build post
90 | # << build post
91 |
92 | %install
93 | rm -rf %{buildroot}
94 | # >> install pre
95 | # << install pre
96 | %qmake5_install
97 |
98 | # >> install post
99 | # << install post
100 |
101 | desktop-file-install --delete-original \
102 | --dir %{buildroot}%{_datadir}/applications \
103 | %{buildroot}%{_datadir}/applications/*.desktop
104 |
105 | %files
106 | %defattr(-,root,root,-)
107 | %{_bindir}
108 | %{_datadir}/%{name}
109 | %{_datadir}/applications/%{name}.desktop
110 | %{_datadir}/icons/hicolor/*/apps/%{name}.png
111 | # >> files
112 | # << files
113 |
--------------------------------------------------------------------------------
/rpm/harbour-advanced-camera.yaml:
--------------------------------------------------------------------------------
1 | Name: harbour-advanced-camera
2 | Summary: Advanced camera
3 | Version: 0.9.5
4 | Release: 1
5 | # The contents of the Group field should be one of the groups listed here:
6 | # https://github.com/mer-tools/spectacle/blob/master/data/GROUPS
7 | Group: Qt/Qt
8 | URL: http://github.com/piggz/harbour-advanced-camera
9 | License: GPLv2
10 | # This must be generated before uploading a package to a remote build service.
11 | # Usually this line does not need to be modified.
12 | Sources:
13 | - '%{name}-%{version}.tar.bz2'
14 | Description: |
15 | Better camera application
16 | Configure: none
17 | # The qtc5 builder inserts macros to allow QtCreator to have fine
18 | # control over qmake/make execution
19 | Builder: qtc5
20 |
21 | # This section specifies build dependencies that are resolved using pkgconfig.
22 | # This is the preferred way of specifying build dependencies for your package.
23 | PkgConfigBR:
24 | - sailfishapp >= 1.0.2
25 | - Qt5Core
26 | - Qt5Multimedia
27 | - Qt5Qml
28 | - Qt5Quick
29 |
30 | # Build dependencies without a pkgconfig setup can be listed here
31 | PkgBR:
32 | - qt5-qttools-linguist
33 | - ssu-sysinfo-devel
34 | - libexif-devel
35 |
36 | # Runtime dependencies which are not automatically detected
37 | Requires:
38 | - sailfishsilica-qt5 >= 0.10.9
39 |
40 | # All installed files
41 | Files:
42 | - '%{_bindir}'
43 | - '%{_datadir}/%{name}'
44 | - '%{_datadir}/applications/%{name}.desktop'
45 | - '%{_datadir}/icons/hicolor/*/apps/%{name}.png'
46 |
47 | # For more information about yaml and what's supported in Sailfish OS
48 | # build system, please see https://wiki.merproject.org/wiki/Spectacle
49 |
--------------------------------------------------------------------------------
/screenshots/screenshot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/screenshots/screenshot1.png
--------------------------------------------------------------------------------
/screenshots/screenshot2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/screenshots/screenshot2.png
--------------------------------------------------------------------------------
/screenshots/screenshot3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/screenshots/screenshot3.png
--------------------------------------------------------------------------------
/screenshots/screenshot4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/screenshots/screenshot4.png
--------------------------------------------------------------------------------
/screenshots/screenshot5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/screenshots/screenshot5.png
--------------------------------------------------------------------------------
/screenshots/screenshot6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/piggz/harbour-advanced-camera/bc498a5e468baa3dd8b716777559164c25108c1b/screenshots/screenshot6.png
--------------------------------------------------------------------------------
/src/deviceinfo.cpp:
--------------------------------------------------------------------------------
1 | #include "deviceinfo.h"
2 | #include
3 | #include
4 |
5 | DeviceInfo::DeviceInfo()
6 | {
7 | QLibrary lib;
8 | lib.setFileName("libssusysinfo.so.1");
9 | if (lib.load()) {
10 | qDebug() << "libssusysinfo.so.1 loaded";
11 | SsuAlloc allocFn = (SsuAlloc) lib.resolve("ssusysinfo_create");
12 | SsuDelete deleteFn = (SsuDelete) lib.resolve("ssusysinfo_delete");
13 | SsuManufacturer manufacturerFn = (SsuManufacturer) lib.resolve("ssusysinfo_device_manufacturer");
14 | SsuModel modelFn = (SsuModel) lib.resolve("ssusysinfo_device_pretty_name");
15 |
16 | if (allocFn && deleteFn && manufacturerFn && modelFn) {
17 | ssusysinfo_t *si = allocFn();
18 | if (si) {
19 | m_manufacturer = manufacturerFn(si);
20 | qDebug() << "manufacturer:" << m_manufacturer;
21 | m_prettyModelName = modelFn(si);
22 | qDebug() << "prettyModelName:" << m_prettyModelName;
23 | deleteFn(si);
24 | } else {
25 | qWarning() << "Cannot allocate ssusysinfo_t!";
26 | }
27 | } else {
28 | qWarning() << "Cannot resolve libssusysinfo methods!";
29 | }
30 |
31 | lib.unload();
32 | } else {
33 | qWarning() << "Unable to load libssusysinfo.so.1!";
34 | }
35 | }
36 |
37 | QString DeviceInfo::manufacturer() const
38 | {
39 | return m_manufacturer;
40 | }
41 |
42 | QString DeviceInfo::prettyModelName() const
43 | {
44 | return m_prettyModelName;
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/src/deviceinfo.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef DEVICEINFO_H
3 | #define DEVICEINFO_H
4 |
5 | #include
6 |
7 | #include
8 |
9 | class DeviceInfo {
10 | public:
11 | DeviceInfo();
12 | virtual ~DeviceInfo() = default;
13 |
14 | QString manufacturer() const;
15 | QString prettyModelName() const;
16 |
17 | private:
18 | typedef ssusysinfo_t* (*SsuAlloc)();
19 | typedef char* (*SsuManufacturer)(ssusysinfo_t*);
20 | typedef char* (*SsuModel)(ssusysinfo_t*);
21 | typedef void (*SsuDelete)(ssusysinfo_t*);
22 |
23 | QString m_manufacturer;
24 | QString m_prettyModelName;
25 | };
26 |
27 | #endif //DEVICEINFO_H
28 |
--------------------------------------------------------------------------------
/src/effectsmodel.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | harbour-advanced-camera C++ Camera Models
3 | Copyright (C) 2019 Adam Pigg (adam@piggz.co.uk)
4 |
5 | This library is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU Lesser General Public
7 | License as published by the Free Software Foundation; either
8 | version 2.1 of the License, or (at your option) any later version.
9 |
10 | This library is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | Lesser General Public License for more details.
14 |
15 | You should have received a copy of the GNU Lesser General Public
16 | License along with this library; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 | **/
19 | #include "effectsmodel.h"
20 |
21 | EffectsModel::EffectsModel()
22 | {
23 | }
24 |
25 | QHash EffectsModel::roleNames() const
26 | {
27 | QHash roles;
28 | roles[EffectName] = "name";
29 | roles[EffectValue] = "value";
30 | return roles;
31 | }
32 |
33 | int EffectsModel::rowCount(const QModelIndex &parent) const
34 | {
35 | Q_UNUSED(parent);
36 | return m_effects.size();
37 | }
38 |
39 | QVariant EffectsModel::data(const QModelIndex &index, int role) const
40 | {
41 | QVariant v;
42 |
43 | if (!index.isValid() || index.row() > rowCount(index) || index.row() < 0) {
44 | return v;
45 | }
46 |
47 | if (role == EffectName) {
48 | v = m_effects[index.row()].second;
49 | } else if (role == EffectValue) {
50 | v = m_effects.at(index.row()).first;
51 | }
52 |
53 | return v;
54 | }
55 |
56 | void EffectsModel::setCamera(QObject *camera)
57 | {
58 | // even when m_camera instance is the same, deviceId could have changed and so available focus modes
59 | m_camera = camera->property("mediaObject").value();
60 |
61 | beginResetModel();
62 | m_effects.clear();
63 | for (int c = (int)QCameraImageProcessing::ColorFilterNone;
64 | c <= (int)QCameraImageProcessing::ColorFilterNeon; c++) {
65 | if (m_camera->imageProcessing()->isColorFilterSupported((QCameraImageProcessing::ColorFilter)c)) {
66 | qDebug() << "Found support for" << (QCameraImageProcessing::ColorFilter)c;
67 | m_effects.push_back(std::make_pair((QCameraImageProcessing::ColorFilter)c, effectName((QCameraImageProcessing::ColorFilter)c)));
68 | }
69 | }
70 | endResetModel();
71 | emit rowCountChanged();
72 |
73 | if (m_effects.size() == 0) {
74 | qDebug() << "No effect modes found";
75 | }
76 | }
77 |
78 | QString EffectsModel::effectName(QCameraImageProcessing::ColorFilter c) const
79 | {
80 | QString name;
81 |
82 | switch (c) {
83 | case QCameraImageProcessing::ColorFilterNone:
84 | name = tr("None");
85 | break;
86 | case QCameraImageProcessing::ColorFilterAqua:
87 | name = tr("Aqua");
88 | break;
89 | case QCameraImageProcessing::ColorFilterBlackboard:
90 | name = tr("Blackboard");
91 | break;
92 | case QCameraImageProcessing::ColorFilterGrayscale:
93 | name = tr("Grayscale");
94 | break;
95 | case QCameraImageProcessing::ColorFilterNegative:
96 | name = tr("Negative");
97 | break;
98 | case QCameraImageProcessing::ColorFilterPosterize:
99 | name = tr("Posterize");
100 | break;
101 | case QCameraImageProcessing::ColorFilterSepia:
102 | name = tr("Sepia");
103 | break;
104 | case QCameraImageProcessing::ColorFilterSolarize:
105 | name = tr("Solarize");
106 | break;
107 | case QCameraImageProcessing::ColorFilterWhiteboard:
108 | name = tr("Whiteboard");
109 | break;
110 | case QCameraImageProcessing::ColorFilterEmboss:
111 | name = tr("Emboss");
112 | break;
113 | case QCameraImageProcessing::ColorFilterSketch:
114 | name = tr("Sketch");
115 | break;
116 | case QCameraImageProcessing::ColorFilterNeon:
117 | name = tr("Neon");
118 | break;
119 | default:
120 | name = "Unknown";
121 | break;
122 | }
123 |
124 | return name;
125 | }
126 |
--------------------------------------------------------------------------------
/src/effectsmodel.h:
--------------------------------------------------------------------------------
1 | /**
2 | harbour-advanced-camera C++ Camera Models
3 | Copyright (C) 2019 Adam Pigg (adam@piggz.co.uk)
4 |
5 | This library is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU Lesser General Public
7 | License as published by the Free Software Foundation; either
8 | version 2.1 of the License, or (at your option) any later version.
9 |
10 | This library is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | Lesser General Public License for more details.
14 |
15 | You should have received a copy of the GNU Lesser General Public
16 | License along with this library; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 | **/
19 | #ifndef EFFECTSMODEL_H
20 | #define EFFECTSMODEL_H
21 |
22 | #include
23 | #include
24 |
25 | class EffectsModel : public QAbstractListModel
26 | {
27 | Q_OBJECT
28 | Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged)
29 |
30 | public:
31 |
32 | enum EffectRoles {
33 | EffectName = Qt::UserRole + 1,
34 | EffectValue
35 | };
36 |
37 | EffectsModel();
38 |
39 | virtual QHash roleNames() const;
40 | virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
41 | virtual QVariant data(const QModelIndex &index, int role) const;
42 |
43 | Q_INVOKABLE void setCamera(QObject *camera);
44 |
45 | private:
46 | std::vector> m_effects;
47 | QCamera *m_camera = nullptr;
48 |
49 | QString effectName(QCameraImageProcessing::ColorFilter c) const;
50 |
51 | signals:
52 | void rowCountChanged();
53 | };
54 |
55 | #endif // EFFECTSMODEL_H
56 |
--------------------------------------------------------------------------------
/src/exifmodel.cpp:
--------------------------------------------------------------------------------
1 | #include "exifmodel.h"
2 | #include
3 | #include
4 |
5 | static void parseContent(ExifContent *content, void *userdata);
6 | static void parseEntry(ExifEntry *entry, void *userdata);
7 |
8 | typedef void (*ExifForEachEntry)(ExifContent*, ExifContentForeachEntryFunc, void*);
9 | typedef void (*ExifGetValue)(ExifEntry*, char*, int);
10 | typedef ExifIfd (*ExifGetIfd)(ExifContent*);
11 | typedef char* (*ExifGetTag)(ExifTag, ExifIfd);
12 | static ExifForEachEntry f_foreachentry;
13 | static ExifGetValue f_getvalue;
14 | static ExifGetIfd f_getifd;
15 | static ExifGetTag f_gettag;
16 |
17 | ExifModel::ExifModel()
18 | {
19 | }
20 |
21 | ExifModel::~ExifModel()
22 | {
23 | free(m_data);
24 | if (m_lib.isLoaded()) {
25 | m_lib.unload();
26 | }
27 | }
28 |
29 | bool ExifModel::loadLibexif()
30 | {
31 | if (m_lib.isLoaded())
32 | return true;
33 |
34 | m_lib.setFileName("libexif.so.12");
35 | if (m_lib.load())
36 | {
37 | f_fromfile = (ExifFromFile) m_lib.resolve("exif_data_new_from_file");
38 | f_getvalue = (ExifGetValue) m_lib.resolve("exif_entry_get_value");
39 | f_foreachentry = (ExifForEachEntry) m_lib.resolve("exif_content_foreach_entry");
40 | f_foreachcontent = (ExifForEachContent) m_lib.resolve("exif_data_foreach_content");
41 | f_getifd = (ExifGetIfd) m_lib.resolve("exif_content_get_ifd");
42 | f_gettag = (ExifGetTag) m_lib.resolve("exif_tag_get_name_in_ifd");
43 | f_dump = (ExifDump) m_lib.resolve("exif_data_dump");
44 | }
45 | else {
46 | qWarning() << "Unable to load libexif.so.12!";
47 | return false;
48 | }
49 | return true;
50 | }
51 |
52 | QHash ExifModel::roleNames() const
53 | {
54 | QHash roles;
55 | roles[ExifName] = "name";
56 | roles[ExifValue] = "value";
57 | return roles;
58 | }
59 |
60 | int ExifModel::rowCount(const QModelIndex &parent) const
61 | {
62 | Q_UNUSED(parent);
63 | return m_exif.count();
64 | }
65 |
66 | QVariant ExifModel::data(const QModelIndex &index, int role) const
67 | {
68 | QVariant v;
69 |
70 | if (!index.isValid() || index.row() > rowCount(index) || index.row() < 0) {
71 | return v;
72 | }
73 |
74 | if (role == ExifValue) {
75 | v = m_exif.values().at(index.row());
76 | } else if (role == ExifName) {
77 | v = m_exif.keys().at(index.row());
78 | }
79 |
80 | return v;
81 | }
82 |
83 | void ExifModel::setSource(const QString &path)
84 | {
85 | if (!loadLibexif())
86 | return;
87 | source = path;
88 | m_data = f_fromfile(path.toUtf8().data());
89 | //f_dump(m_data);
90 | beginResetModel();
91 | m_exif.clear();
92 | f_foreachcontent(m_data, parseContent, nullptr);
93 | endResetModel();
94 | }
95 |
96 | void parseContent(ExifContent *content, void *userdata)
97 | {
98 | Q_UNUSED(userdata);
99 | f_foreachentry(content, parseEntry, content);
100 | }
101 |
102 | void parseEntry(ExifEntry *entry, void *userdata)
103 | {
104 | ExifContent *content = static_cast(userdata);
105 | ExifIfd ifd = f_getifd(content);
106 | QString tag(f_gettag(entry->tag, ifd));
107 | char bufValue[1024];
108 | f_getvalue(entry, bufValue, 1024);
109 | m_exif.insert(tag, QString(bufValue));
110 | }
111 |
--------------------------------------------------------------------------------
/src/exifmodel.h:
--------------------------------------------------------------------------------
1 | #ifndef EXIFMODEL_H
2 | #define EXIFMODEL_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | static QMap m_exif;
9 |
10 | class ExifModel : public QAbstractListModel
11 | {
12 | Q_OBJECT
13 | Q_PROPERTY(QString source READ getSource WRITE setSource)
14 | public:
15 | enum ExifRoles {
16 | ExifName = Qt::UserRole + 1,
17 | ExifValue
18 | };
19 |
20 | ExifModel();
21 | ~ExifModel();
22 | bool loadLibexif();
23 | QHash roleNames() const;
24 | int rowCount(const QModelIndex &parent) const;
25 | QVariant data(const QModelIndex &index, int role) const;
26 | QString getSource() const { return source; }
27 | void setSource(const QString &path);
28 | private:
29 | QString source;
30 | ExifData *m_data;
31 | QLibrary m_lib;
32 | typedef ExifData* (*ExifFromFile)(const char*);
33 | typedef void (*ExifForEachContent)(ExifData*, ExifDataForeachContentFunc, void*);
34 | typedef void (*ExifDump)(ExifData*);
35 | ExifFromFile f_fromfile;
36 | ExifForEachContent f_foreachcontent;
37 | ExifDump f_dump;
38 | };
39 |
40 | #endif // EXIFMODEL_H
41 |
--------------------------------------------------------------------------------
/src/exposuremodel.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | harbour-advanced-camera C++ Camera Models
3 | Copyright (C) 2019 Adam Pigg (adam@piggz.co.uk)
4 |
5 | This library is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU Lesser General Public
7 | License as published by the Free Software Foundation; either
8 | version 2.1 of the License, or (at your option) any later version.
9 |
10 | This library is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | Lesser General Public License for more details.
14 |
15 | You should have received a copy of the GNU Lesser General Public
16 | License along with this library; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 | **/
19 | #include "exposuremodel.h"
20 |
21 | ExposureModel::ExposureModel()
22 | {
23 | }
24 |
25 | QHash ExposureModel::roleNames() const
26 | {
27 | QHash roles;
28 | roles[ExposureName] = "name";
29 | roles[ExposureValue] = "value";
30 | return roles;
31 | }
32 |
33 | int ExposureModel::rowCount(const QModelIndex &parent) const
34 | {
35 | Q_UNUSED(parent);
36 | return m_exposures.size();
37 | }
38 |
39 | QVariant ExposureModel::data(const QModelIndex &index, int role) const
40 | {
41 | QVariant v;
42 |
43 | if (!index.isValid() || index.row() > rowCount(index) || index.row() < 0) {
44 | return v;
45 | }
46 |
47 | if (role == ExposureName) {
48 | v = m_exposures.at(index.row()).second;
49 | } else if (role == ExposureValue) {
50 | v = m_exposures.at(index.row()).first;
51 | }
52 |
53 | return v;
54 | }
55 |
56 | void ExposureModel::setCamera(QObject *camera)
57 | {
58 | // even when m_camera instance is the same, deviceId could have changed and so available focus modes
59 | m_camera = camera->property("mediaObject").value();
60 |
61 | beginResetModel();
62 | m_exposures.clear();
63 | for (int c = (int)QCameraExposure::ExposureAuto; c <= (int)QCameraExposure::ExposureHDR; c++) {
64 | if (m_camera->exposure()->isExposureModeSupported((QCameraExposure::ExposureMode)c)) {
65 | qDebug() << "Found support for" << (QCameraExposure::ExposureMode)c;
66 | m_exposures.push_back(std::make_pair((QCameraExposure::ExposureMode)c, exposureName((QCameraExposure::ExposureMode)c)));
67 | }
68 | }
69 | endResetModel();
70 | emit rowCountChanged();
71 |
72 | if (m_exposures.size() == 0) {
73 | qDebug() << "No exposure modes found";
74 | }
75 | }
76 |
77 | QString ExposureModel::exposureName(QCameraExposure::ExposureMode e) const
78 | {
79 | QString name;
80 |
81 | switch (e) {
82 | case QCameraExposure::ExposureAuto:
83 | name = tr("Automatic Scene Detection");
84 | break;
85 | case QCameraExposure::ExposureAction:
86 | name = tr("Action");
87 | break;
88 | case QCameraExposure::ExposureManual:
89 | name = tr("Off");
90 | break;
91 | case QCameraExposure::ExposureAR:
92 | name = tr("Augmented Reality");
93 | break;
94 | case QCameraExposure::ExposureBacklight:
95 | name = tr("Backlight");
96 | break;
97 | case QCameraExposure::ExposureBarcode:
98 | name = tr("Barcode");
99 | break;
100 | case QCameraExposure::ExposureBeach:
101 | name = tr("Beach");
102 | break;
103 | case QCameraExposure::ExposureCandlelight:
104 | name = tr("Candlelight");
105 | break;
106 | case QCameraExposure::ExposureFireworks:
107 | name = tr("Fireworks");
108 | break;
109 | case QCameraExposure::ExposureFlowers:
110 | name = tr("Flowers");
111 | break;
112 | case QCameraExposure::ExposureHDR:
113 | name = tr("HDR");
114 | break;
115 | case QCameraExposure::ExposureLandscape:
116 | name = tr("Landscape");
117 | break;
118 | case QCameraExposure::ExposureLargeAperture:
119 | name = tr("Large Aperture");
120 | break;
121 | case QCameraExposure::ExposureNight:
122 | name = tr("Night");
123 | break;
124 | case QCameraExposure::ExposureNightPortrait:
125 | name = tr("Night Portrait");
126 | break;
127 | case QCameraExposure::ExposureParty:
128 | name = tr("Party");
129 | break;
130 | case QCameraExposure::ExposurePortrait:
131 | name = tr("Portrait");
132 | break;
133 | case QCameraExposure::ExposureSmallAperture:
134 | name = tr("Small Aperture");
135 | break;
136 | case QCameraExposure::ExposureSnow:
137 | name = tr("Snow");
138 | break;
139 | case QCameraExposure::ExposureSports:
140 | name = tr("Sports");
141 | break;
142 | case QCameraExposure::ExposureSpotlight:
143 | name = tr("Spotlight");
144 | break;
145 | case QCameraExposure::ExposureSteadyPhoto:
146 | name = tr("Steady Photo");
147 | break;
148 | case QCameraExposure::ExposureSunset:
149 | name = tr("Sunset");
150 | break;
151 | case QCameraExposure::ExposureTheatre:
152 | name = tr("Theatre");
153 | break;
154 |
155 | default:
156 | name = "Unknown (" + QString::number(e) + ")";
157 | }
158 |
159 | return name;
160 | }
161 |
162 | QString ExposureModel::iconName(QCameraExposure::ExposureMode e) const
163 | {
164 | QString name;
165 |
166 | switch (e) {
167 | case QCameraExposure::ExposureAuto:
168 | name = "asd";
169 | break;
170 | case QCameraExposure::ExposureAction:
171 | name = "action";
172 | break;
173 | case QCameraExposure::ExposureManual:
174 | name = "none";
175 | break;
176 | case QCameraExposure::ExposureAR:
177 | name = "ar";
178 | break;
179 | case QCameraExposure::ExposureBacklight:
180 | name = "backlight";
181 | break;
182 | case QCameraExposure::ExposureBarcode:
183 | name = "barcode";
184 | break;
185 | case QCameraExposure::ExposureBeach:
186 | name = "beach";
187 | break;
188 | case QCameraExposure::ExposureCandlelight:
189 | name = "candlelight";
190 | break;
191 | case QCameraExposure::ExposureFireworks:
192 | name = "fireworks";
193 | break;
194 | case QCameraExposure::ExposureFlowers:
195 | name = "flowers";
196 | break;
197 | case QCameraExposure::ExposureHDR:
198 | name = "hdr";
199 | break;
200 | case QCameraExposure::ExposureLandscape:
201 | name = "landscape";
202 | break;
203 | case QCameraExposure::ExposureLargeAperture:
204 | name = "large_aperture";
205 | break;
206 | case QCameraExposure::ExposureNight:
207 | name = "night";
208 | break;
209 | case QCameraExposure::ExposureNightPortrait:
210 | name = "night_portrait";
211 | break;
212 | case QCameraExposure::ExposureParty:
213 | name = "party";
214 | break;
215 | case QCameraExposure::ExposurePortrait:
216 | name = "portrait";
217 | break;
218 | case QCameraExposure::ExposureSmallAperture:
219 | name = "small_aperture";
220 | break;
221 | case QCameraExposure::ExposureSnow:
222 | name = "snow";
223 | break;
224 | case QCameraExposure::ExposureSports:
225 | name = "sports";
226 | break;
227 | case QCameraExposure::ExposureSpotlight:
228 | name = "spotlight";
229 | break;
230 | case QCameraExposure::ExposureSteadyPhoto:
231 | name = "steady_photo";
232 | break;
233 | case QCameraExposure::ExposureSunset:
234 | name = "sunset";
235 | break;
236 | case QCameraExposure::ExposureTheatre:
237 | name = "theatre";
238 | break;
239 | default:
240 | name = "unknown";
241 | break;
242 | }
243 |
244 | return name;
245 | }
246 |
--------------------------------------------------------------------------------
/src/exposuremodel.h:
--------------------------------------------------------------------------------
1 | /**
2 | harbour-advanced-camera C++ Camera Models
3 | Copyright (C) 2019 Adam Pigg (adam@piggz.co.uk)
4 |
5 | This library is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU Lesser General Public
7 | License as published by the Free Software Foundation; either
8 | version 2.1 of the License, or (at your option) any later version.
9 |
10 | This library is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | Lesser General Public License for more details.
14 |
15 | You should have received a copy of the GNU Lesser General Public
16 | License along with this library; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 | **/
19 | #ifndef EXPOSUREMODEL_H
20 | #define EXPOSUREMODEL_H
21 |
22 | #include
23 | #include
24 |
25 | class ExposureModel : public QAbstractListModel
26 | {
27 | Q_OBJECT
28 | Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged)
29 |
30 | public:
31 |
32 | enum ExposureRoles {
33 | ExposureName = Qt::UserRole + 1,
34 | ExposureValue
35 | };
36 |
37 | ExposureModel();
38 |
39 | virtual QHash roleNames() const;
40 | virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
41 | virtual QVariant data(const QModelIndex &index, int role) const;
42 |
43 | Q_INVOKABLE void setCamera(QObject *camera);
44 | Q_INVOKABLE QString iconName(QCameraExposure::ExposureMode e) const;
45 |
46 | private:
47 | std::vector> m_exposures;
48 | QCamera *m_camera = nullptr;
49 |
50 | QString exposureName(QCameraExposure::ExposureMode e) const;
51 |
52 | signals:
53 | void rowCountChanged();
54 | };
55 |
56 | #endif // EFFECTSMODEL_H
57 |
--------------------------------------------------------------------------------
/src/flashmodel.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | harbour-advanced-camera C++ Camera Models
3 | Copyright (C) 2019 Adam Pigg (adam@piggz.co.uk)
4 |
5 | This library is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU Lesser General Public
7 | License as published by the Free Software Foundation; either
8 | version 2.1 of the License, or (at your option) any later version.
9 |
10 | This library is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | Lesser General Public License for more details.
14 |
15 | You should have received a copy of the GNU Lesser General Public
16 | License along with this library; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 | **/
19 | #include "flashmodel.h"
20 |
21 | FlashModel::FlashModel()
22 | {
23 | }
24 |
25 | QHash FlashModel::roleNames() const
26 | {
27 | QHash roles;
28 | roles[FlashName] = "name";
29 | roles[FlashValue] = "value";
30 | return roles;
31 | }
32 |
33 | int FlashModel::rowCount(const QModelIndex &parent) const
34 | {
35 | Q_UNUSED(parent);
36 | return m_flashModes.size();
37 | }
38 |
39 | QVariant FlashModel::data(const QModelIndex &index, int role) const
40 | {
41 | QVariant v;
42 |
43 | if (!index.isValid() || index.row() > rowCount(index) || index.row() < 0) {
44 | return v;
45 | }
46 |
47 | if (role == FlashName) {
48 | v = m_flashModes.at(index.row()).second;
49 | } else if (role == FlashValue) {
50 | v = m_flashModes.at(index.row()).first;
51 | }
52 |
53 | return v;
54 | }
55 |
56 | void FlashModel::setCamera(QObject *camera)
57 | {
58 | // even when m_camera instance is the same, deviceId could have changed and so available focus modes
59 | m_camera = camera->property("mediaObject").value();
60 |
61 | beginResetModel();
62 | m_flashModes.clear();
63 | for (int c = (int)QCameraExposure::FlashAuto; c <= (int)QCameraExposure::FlashManual; c++) {
64 | if (m_camera->exposure()->isFlashModeSupported((QCameraExposure::FlashMode)c)
65 | && flashName((QCameraExposure::FlashMode)c) != tr("Unknown")) {
66 | qDebug() << "Found support for" << (QCameraExposure::FlashMode)c;
67 | m_flashModes.push_back(std::make_pair((QCameraExposure::FlashMode)c, flashName((QCameraExposure::FlashMode)c)));
68 | }
69 | }
70 | endResetModel();
71 | emit rowCountChanged();
72 |
73 | if (m_flashModes.size() == 0) {
74 | qDebug() << "No flash modes found";
75 | }
76 | }
77 |
78 | QString FlashModel::flashName(QCameraExposure::FlashMode flash) const
79 | {
80 | QString name;
81 |
82 | switch (flash) {
83 | case QCameraExposure::FlashAuto:
84 | name = tr("Auto");
85 | break;
86 | case QCameraExposure::FlashOff:
87 | name = tr("Off");
88 | break;
89 | case QCameraExposure::FlashOn:
90 | name = tr("On");
91 | break;
92 | case QCameraExposure::FlashRedEyeReduction:
93 | name = tr("Red Eye Reduction");
94 | break;
95 | case QCameraExposure::FlashFill:
96 | name = tr("Fill");
97 | break;
98 | case QCameraExposure::FlashTorch:
99 | name = tr("Torch");
100 | break;
101 | case QCameraExposure::FlashVideoLight:
102 | name = tr("Video Light");
103 | break;
104 | case QCameraExposure::FlashSlowSyncFrontCurtain:
105 | name = tr("Slow Sync Front Curtain");
106 | break;
107 | case QCameraExposure::FlashSlowSyncRearCurtain:
108 | name = tr("Slow Sync Rear Curtain");
109 | break;
110 | case QCameraExposure::FlashManual:
111 | name = tr("Manual");
112 | break;
113 | default:
114 | name = tr("Unknown");
115 | break;
116 | }
117 |
118 | return name;
119 | }
120 |
--------------------------------------------------------------------------------
/src/flashmodel.h:
--------------------------------------------------------------------------------
1 | /**
2 | harbour-advanced-camera C++ Camera Models
3 | Copyright (C) 2019 Adam Pigg (adam@piggz.co.uk)
4 |
5 | This library is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU Lesser General Public
7 | License as published by the Free Software Foundation; either
8 | version 2.1 of the License, or (at your option) any later version.
9 |
10 | This library is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | Lesser General Public License for more details.
14 |
15 | You should have received a copy of the GNU Lesser General Public
16 | License along with this library; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 | **/
19 | #ifndef FLASHMODEL_H
20 | #define FLASHMODEL_H
21 |
22 | #include
23 | #include
24 |
25 | class FlashModel : public QAbstractListModel
26 | {
27 | Q_OBJECT
28 | Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged)
29 |
30 | public:
31 |
32 | enum FlashRoles {
33 | FlashName = Qt::UserRole + 1,
34 | FlashValue
35 | };
36 |
37 | FlashModel();
38 |
39 | virtual QHash roleNames() const;
40 | virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
41 | virtual QVariant data(const QModelIndex &index, int role) const;
42 |
43 | Q_INVOKABLE void setCamera(QObject *camera);
44 |
45 | private:
46 | std::vector> m_flashModes;
47 |
48 | QCamera *m_camera = nullptr;
49 |
50 | QString flashName(QCameraExposure::FlashMode flash) const;
51 |
52 | signals:
53 | void rowCountChanged();
54 | };
55 |
56 | #endif // FOCUSMODEL_H
57 |
--------------------------------------------------------------------------------
/src/focusmodel.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | harbour-advanced-camera C++ Camera Models
3 | Copyright (C) 2019 Adam Pigg (adam@piggz.co.uk)
4 |
5 | This library is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU Lesser General Public
7 | License as published by the Free Software Foundation; either
8 | version 2.1 of the License, or (at your option) any later version.
9 |
10 | This library is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | Lesser General Public License for more details.
14 |
15 | You should have received a copy of the GNU Lesser General Public
16 | License along with this library; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 | **/
19 | #include "focusmodel.h"
20 |
21 | FocusModel::FocusModel()
22 | {
23 | }
24 |
25 | QHash FocusModel::roleNames() const
26 | {
27 | QHash roles;
28 | roles[FocusName] = "name";
29 | roles[FocusValue] = "value";
30 | return roles;
31 | }
32 |
33 | int FocusModel::rowCount(const QModelIndex &parent) const
34 | {
35 | Q_UNUSED(parent);
36 | return m_focusModes.size();
37 | }
38 |
39 | QVariant FocusModel::data(const QModelIndex &index, int role) const
40 | {
41 | QVariant v;
42 |
43 | if (!index.isValid() || index.row() > rowCount(index) || index.row() < 0) {
44 | return v;
45 | }
46 |
47 | if (role == FocusName) {
48 | v = m_focusModes.at(index.row()).second;
49 | } else if (role == FocusValue) {
50 | v = m_focusModes.at(index.row()).first;
51 | }
52 |
53 | return v;
54 | }
55 |
56 | void FocusModel::setCamera(QObject *camera)
57 | {
58 | // even when m_camera instance is the same, deviceId could have changed and so available focus modes
59 | m_camera = camera->property("mediaObject").value();
60 |
61 | beginResetModel();
62 | m_focusModes.clear();
63 | for (int c = (int)QCameraFocus::ManualFocus; c <= (int)QCameraFocus::MacroFocus; c++) {
64 | if (m_camera->focus()->isFocusModeSupported((QCameraFocus::FocusMode)c)
65 | && focusName((QCameraFocus::FocusMode)c) != tr("Unknown")) {
66 | qDebug() << "Found support for" << (QCameraFocus::FocusMode)c;
67 | m_focusModes.push_back(std::make_pair((QCameraFocus::FocusMode)c, focusName((QCameraFocus::FocusMode)c)));
68 | }
69 | }
70 | // Add manual mode even if not supported as we simulate it (but FocusAuto needs to be supported)
71 | auto it = std::find_if( m_focusModes.begin(), m_focusModes.end(),
72 | [](const std::pair& element){ return element.first == QCameraFocus::ManualFocus;} );
73 |
74 | if (it == std::end(m_focusModes) && m_camera->focus()->isFocusModeSupported(QCameraFocus::AutoFocus)) {
75 | m_focusModes.push_back(std::make_pair(QCameraFocus::ManualFocus, focusName(QCameraFocus::ManualFocus)));
76 | }
77 | endResetModel();
78 | emit rowCountChanged();
79 |
80 | if (m_focusModes.size() == 0) {
81 | qDebug() << "No focus modes found";
82 | }
83 | }
84 |
85 | QString FocusModel::focusName(QCameraFocus::FocusMode focus) const
86 | {
87 | QString name;
88 | qDebug() << "Checking focus name: " << focus;
89 |
90 | switch (focus) {
91 | case QCameraFocus::ManualFocus:
92 | name = tr("Manual");
93 | break;
94 | case QCameraFocus::HyperfocalFocus:
95 | name = tr("Hyperfocal");
96 | break;
97 | case QCameraFocus::InfinityFocus:
98 | name = tr("Infinity");
99 | break;
100 | case QCameraFocus::AutoFocus:
101 | name = tr("Auto");
102 | break;
103 | case QCameraFocus::ContinuousFocus:
104 | name = tr("Continuous");
105 | break;
106 | case QCameraFocus::MacroFocus:
107 | name = tr("Macro");
108 | break;
109 | default:
110 | name = tr("Unknown");
111 | break;
112 | }
113 | return name;
114 | }
115 |
--------------------------------------------------------------------------------
/src/focusmodel.h:
--------------------------------------------------------------------------------
1 | /**
2 | harbour-advanced-camera C++ Camera Models
3 | Copyright (C) 2019 Adam Pigg (adam@piggz.co.uk)
4 |
5 | This library is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU Lesser General Public
7 | License as published by the Free Software Foundation; either
8 | version 2.1 of the License, or (at your option) any later version.
9 |
10 | This library is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | Lesser General Public License for more details.
14 |
15 | You should have received a copy of the GNU Lesser General Public
16 | License along with this library; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 | **/
19 | #ifndef FOCUSMODEL_H
20 | #define FOCUSMODEL_H
21 |
22 | #include
23 | #include
24 |
25 | class FocusModel : public QAbstractListModel
26 | {
27 | Q_OBJECT
28 | Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged)
29 |
30 | public:
31 |
32 | enum FocusRoles {
33 | FocusName = Qt::UserRole + 1,
34 | FocusValue
35 | };
36 |
37 | FocusModel();
38 |
39 | virtual QHash roleNames() const;
40 | virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
41 | virtual QVariant data(const QModelIndex &index, int role) const;
42 |
43 | Q_INVOKABLE void setCamera(QObject *camera);
44 |
45 | private:
46 | std::vector> m_focusModes;
47 | QCamera *m_camera = nullptr;
48 |
49 | QString focusName(QCameraFocus::FocusMode focus) const;
50 |
51 | signals:
52 | void rowCountChanged();
53 | };
54 |
55 | #endif // FOCUSMODEL_H
56 |
--------------------------------------------------------------------------------
/src/fsoperations.cpp:
--------------------------------------------------------------------------------
1 | #include "fsoperations.h"
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | FSOperations::FSOperations(QObject *parent) : QObject(parent)
10 | {
11 | }
12 |
13 | bool FSOperations::deleteFile(const QString &path)
14 | {
15 | QFile f(path);
16 | return f.remove();
17 | }
18 |
19 | QString FSOperations::writableLocation(const QString &type, const QString &baseDir)
20 | {
21 | QString dir;
22 | if (type == "image") {
23 | dir = baseDir + "/Pictures/AdvancedCam";
24 | } else if (type == "video") {
25 | dir = baseDir + "/Videos/AdvancedCam";
26 | } else {
27 | return QString();
28 | }
29 |
30 | if (!createFolder(dir)) {
31 | qWarning() << "Unable to create" << dir << ", fallback to home dir!";
32 | emit rescan("/media/sdcard");
33 | return writableLocation(type, QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
34 | }
35 | return dir;
36 | }
37 |
38 | bool FSOperations::createFolder(const QString &path)
39 | {
40 | QDir dir(path);
41 | if (!dir.exists()) {
42 | return dir.mkpath(".");
43 | }
44 | return true;
45 | }
46 |
47 | qint64 FSOperations::getFileSize(const QString &path)
48 | {
49 | QFileInfo info(path);
50 | if (info.exists())
51 | return info.size();
52 | return 0;
53 | }
54 |
55 | QString FSOperations::getFileSizeHuman(const QString &path)
56 | {
57 | float num = (float)getFileSize(path);
58 | QStringList list;
59 | list << "KiB" << "MiB" << "GiB" << "TiB";
60 |
61 | QStringListIterator i(list);
62 | QString unit("B");
63 |
64 | if (num < 1024.0)
65 | return QString().setNum(num, 'f', 0) + " " + unit;
66 |
67 | while(num >= 1024.0 && i.hasNext())
68 | {
69 | unit = i.next();
70 | num /= 1024.0;
71 | }
72 | return QString().setNum(num, 'f', 2) + " " + unit;
73 | }
74 |
--------------------------------------------------------------------------------
/src/fsoperations.h:
--------------------------------------------------------------------------------
1 | #ifndef FSOPERATIONS_H
2 | #define FSOPERATIONS_H
3 |
4 | #include
5 |
6 | class FSOperations : public QObject
7 | {
8 | Q_OBJECT
9 | public:
10 | explicit FSOperations(QObject *parent = nullptr);
11 | Q_INVOKABLE bool deleteFile(const QString &path);
12 | Q_INVOKABLE QString writableLocation(const QString &type, const QString &baseDir);
13 | Q_INVOKABLE bool createFolder(const QString &path);
14 | Q_INVOKABLE qint64 getFileSize(const QString &path);
15 | Q_INVOKABLE QString getFileSizeHuman(const QString &path);
16 | signals:
17 | void rescan(const QString& dir);
18 | };
19 |
20 | #endif // FSOPERATIONS_H
21 |
--------------------------------------------------------------------------------
/src/harbour-advanced-camera.cpp:
--------------------------------------------------------------------------------
1 | #ifdef QT_QML_DEBUG
2 | #include
3 | #endif
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include
12 | #include "deviceinfo.h"
13 | #include "effectsmodel.h"
14 | #include "exposuremodel.h"
15 | #include "isomodel.h"
16 | #include "resolutionmodel.h"
17 | #include "wbmodel.h"
18 | #include "focusmodel.h"
19 | #include "flashmodel.h"
20 | #include "fsoperations.h"
21 | #include "resourcehandler.h"
22 | #include "storagemodel.h"
23 | #include "exifmodel.h"
24 | #include "metadatamodel.h"
25 |
26 | int main(int argc, char *argv[])
27 | {
28 | // SailfishApp::main() will display "qml/harbour-advanced-camera.qml", if you need more
29 | // control over initialization, you can use:
30 | //
31 | // - SailfishApp::application(int, char *[]) to get the QGuiApplication *
32 | // - SailfishApp::createView() to get a new QQuickView * instance
33 | // - SailfishApp::pathTo(QString) to get a QUrl to a resource file
34 | // - SailfishApp::pathToMainQml() to get a QUrl to the main QML file
35 | //
36 | // To display the view, call "show()" (will show fullscreen on device).
37 |
38 | QGuiApplication *app = SailfishApp::application(argc, argv);
39 |
40 | app->setOrganizationDomain("piggz.co.uk");
41 | app->setOrganizationName("uk.co.piggz"); // needed for Sailjail
42 | app->setApplicationName("AdvancedCamera");
43 |
44 | qmlRegisterType("uk.co.piggz.harbour_advanced_camera", 1, 0, "EffectsModel");
45 | qmlRegisterType("uk.co.piggz.harbour_advanced_camera", 1, 0, "ExposureModel");
46 | qmlRegisterType("uk.co.piggz.harbour_advanced_camera", 1, 0, "IsoModel");
47 | qmlRegisterType("uk.co.piggz.harbour_advanced_camera", 1, 0, "ResolutionModel");
48 | qmlRegisterType("uk.co.piggz.harbour_advanced_camera", 1, 0, "WhiteBalanceModel");
49 | qmlRegisterType("uk.co.piggz.harbour_advanced_camera", 1, 0, "FocusModel");
50 | qmlRegisterType("uk.co.piggz.harbour_advanced_camera", 1, 0, "FlashModel");
51 | qmlRegisterType("uk.co.piggz.harbour_advanced_camera", 1, 0, "ExifModel");
52 | qmlRegisterType("uk.co.piggz.harbour_advanced_camera", 1, 0, "MetadataModel");
53 |
54 | ResolutionModel resolutionModel;
55 | QSortFilterProxyModel sortedResolutionModel;
56 | sortedResolutionModel.setSourceModel(&resolutionModel);
57 | sortedResolutionModel.setSortRole(ResolutionModel::ResolutionMpx);
58 | sortedResolutionModel.sort(0, Qt::DescendingOrder);
59 |
60 | QQuickView *view = SailfishApp::createView();
61 |
62 | ResourceHandler handler;
63 | handler.acquire();
64 |
65 | view->rootContext()->setContextProperty("modelResolution", &resolutionModel);
66 | view->rootContext()->setContextProperty("sortedModelResolution", &sortedResolutionModel);
67 | StorageModel storageModel;
68 | view->rootContext()->setContextProperty("modelStorage", &storageModel);
69 | FSOperations fsOperations;
70 | view->rootContext()->setContextProperty("fsOperations", &fsOperations);
71 |
72 | view->setSource(SailfishApp::pathTo("qml/harbour-advanced-camera.qml"));
73 |
74 | DeviceInfo deviceInfo;
75 | view->rootContext()->setContextProperty("CameraManufacturer", deviceInfo.manufacturer());
76 | view->rootContext()->setContextProperty("CameraPrettyModelName", deviceInfo.prettyModelName());
77 |
78 | QObject::connect(view, &QQuickView::focusObjectChanged, &handler,
79 | &ResourceHandler::handleFocusChange);
80 | QObject::connect(&fsOperations, &FSOperations::rescan, &storageModel,
81 | &StorageModel::scan);
82 |
83 | view->show();
84 |
85 | return app->exec();
86 | }
87 |
--------------------------------------------------------------------------------
/src/isomodel.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | harbour-advanced-camera C++ Camera Models
3 | Copyright (C) 2019 Adam Pigg (adam@piggz.co.uk)
4 |
5 | This library is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU Lesser General Public
7 | License as published by the Free Software Foundation; either
8 | version 2.1 of the License, or (at your option) any later version.
9 |
10 | This library is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | Lesser General Public License for more details.
14 |
15 | You should have received a copy of the GNU Lesser General Public
16 | License along with this library; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 | **/
19 | #include "isomodel.h"
20 |
21 | IsoModel::IsoModel()
22 | {
23 | }
24 |
25 | QHash IsoModel::roleNames() const
26 | {
27 | QHash roles;
28 | roles[IsoName] = "name";
29 | roles[IsoValue] = "value";
30 | return roles;
31 | }
32 |
33 | int IsoModel::rowCount(const QModelIndex &parent) const
34 | {
35 | Q_UNUSED(parent);
36 | return m_isoModes.size();
37 | }
38 |
39 | QVariant IsoModel::data(const QModelIndex &index, int role) const
40 | {
41 | QVariant v;
42 |
43 | if (!index.isValid() || index.row() > rowCount(index) || index.row() < 0) {
44 | return v;
45 | }
46 |
47 | if (role == IsoName) {
48 | v = m_isoModes.at(index.row()).second;
49 | } else if (role == IsoValue) {
50 | v = m_isoModes.at(index.row()).first;
51 | }
52 |
53 | return v;
54 | }
55 |
56 | void IsoModel::setCamera(QObject *camera)
57 | {
58 | // even when m_camera instance is the same, deviceId could have changed and so available focus modes
59 | m_camera = camera->property("mediaObject").value();
60 |
61 | beginResetModel();
62 | m_isoModes.clear();
63 |
64 | QList supportedIsoRange = m_camera->exposure()->supportedIsoSensitivities();
65 |
66 | for (int i = 0; i < supportedIsoRange.count() ; i++) {
67 | m_isoModes.push_back(std::make_pair(i, isoName(supportedIsoRange[i])));
68 | qDebug() << "Found support for" << isoName(supportedIsoRange[i]);
69 | }
70 | endResetModel();
71 | emit rowCountChanged();
72 |
73 | if (m_isoModes.size() == 0) {
74 | qDebug() << "No ISO modes found";
75 | }
76 | }
77 |
78 | QString IsoModel::isoName(int iso) const
79 | {
80 | QString name;
81 |
82 | if (iso == 0) {
83 | name = tr("Auto ISO");
84 | } else if (iso == 1) {
85 | name = "ISO_HJR";
86 | } else {
87 | name = QString("ISO_%1").arg(iso);
88 | }
89 | return name;
90 | }
91 |
--------------------------------------------------------------------------------
/src/isomodel.h:
--------------------------------------------------------------------------------
1 | /**
2 | harbour-advanced-camera C++ Camera Models
3 | Copyright (C) 2019 Adam Pigg (adam@piggz.co.uk)
4 |
5 | This library is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU Lesser General Public
7 | License as published by the Free Software Foundation; either
8 | version 2.1 of the License, or (at your option) any later version.
9 |
10 | This library is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | Lesser General Public License for more details.
14 |
15 | You should have received a copy of the GNU Lesser General Public
16 | License along with this library; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 | **/
19 | #ifndef ISOMODEL_H
20 | #define ISOMODEL_H
21 |
22 | #include
23 | #include
24 |
25 | class IsoModel : public QAbstractListModel
26 | {
27 | Q_OBJECT
28 | Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged)
29 |
30 | public:
31 |
32 | enum IsoRoles {
33 | IsoName = Qt::UserRole + 1,
34 | IsoValue
35 | };
36 |
37 | IsoModel();
38 |
39 | virtual QHash roleNames() const;
40 | virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
41 | virtual QVariant data(const QModelIndex &index, int role) const;
42 |
43 | Q_INVOKABLE void setCamera(QObject *camera);
44 |
45 | private:
46 | std::vector> m_isoModes;
47 |
48 | QCamera *m_camera = nullptr;
49 |
50 | QString isoName(int iso) const;
51 |
52 | signals:
53 | void rowCountChanged();
54 | };
55 |
56 | #endif // EFFECTSMODEL_H
57 |
--------------------------------------------------------------------------------
/src/metadatamodel.cpp:
--------------------------------------------------------------------------------
1 | #include "metadatamodel.h"
2 |
3 | MetadataModel::MetadataModel()
4 | {
5 | }
6 |
7 | QHash MetadataModel::roleNames() const
8 | {
9 | QHash roles;
10 | roles[MetadataName] = "name";
11 | roles[MetadataValue] = "value";
12 | return roles;
13 | }
14 |
15 | int MetadataModel::rowCount(const QModelIndex &parent) const
16 | {
17 | Q_UNUSED(parent);
18 | return m_data.count();
19 | }
20 |
21 | QVariant MetadataModel::data(const QModelIndex &index, int role) const
22 | {
23 | QVariant v;
24 |
25 | if (!index.isValid() || index.row() > rowCount(index) || index.row() < 0) {
26 | return v;
27 | }
28 |
29 | if (role == MetadataValue) {
30 | v = m_data.values().at(index.row());
31 | } else if (role == MetadataName) {
32 | v = m_data.keys().at(index.row());
33 | }
34 |
35 | return v;
36 | }
37 |
38 | void MetadataModel::setPlayer(QObject *player)
39 | {
40 | QMediaPlayer* pl = qvariant_cast(player->property("mediaObject"));
41 | if (m_player != pl)
42 | m_player = pl;
43 | connect(m_player, &QMediaPlayer::metaDataAvailableChanged, this, &MetadataModel::getMetadata);
44 | }
45 |
46 | void MetadataModel::getMetadata(bool available)
47 | {
48 | Q_UNUSED(available);
49 | if (m_player->isMetaDataAvailable())
50 | {
51 | QStringList meta (m_player->availableMetaData());
52 | qDebug() << "Metadata available:" << meta;
53 | beginResetModel();
54 | for (const QString &mdName : meta)
55 | m_data[mdName] = m_player->metaData(mdName);
56 | endResetModel();
57 | if (m_data.count() == 0)
58 | qDebug() << "No metadata found!";
59 | }
60 | else {
61 | qDebug() << "No metadata available!";
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/metadatamodel.h:
--------------------------------------------------------------------------------
1 | #ifndef METADATAMODEL_H
2 | #define METADATAMODEL_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | class MetadataModel : public QAbstractListModel
10 | {
11 | Q_OBJECT
12 | public:
13 | enum MetadataRoles {
14 | MetadataName = Qt::UserRole + 1,
15 | MetadataValue
16 | };
17 | MetadataModel();
18 | QHash roleNames() const;
19 | int rowCount(const QModelIndex &parent) const;
20 | QVariant data(const QModelIndex &index, int role) const;
21 | Q_INVOKABLE void setPlayer(QObject *player);
22 | public slots:
23 | void getMetadata(bool available);
24 | private:
25 | QMap m_data;
26 | QMediaPlayer *m_player;
27 | };
28 |
29 | #endif // METADATAMODEL_H
30 |
--------------------------------------------------------------------------------
/src/resolutionmodel.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | harbour-advanced-camera C++ Camera Models
3 | Copyright (C) 2019 Adam Pigg (adam@piggz.co.uk)
4 |
5 | This library is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU Lesser General Public
7 | License as published by the Free Software Foundation; either
8 | version 2.1 of the License, or (at your option) any later version.
9 |
10 | This library is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | Lesser General Public License for more details.
14 |
15 | You should have received a copy of the GNU Lesser General Public
16 | License along with this library; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 | **/
19 | #include "resolutionmodel.h"
20 |
21 | QSize ResolutionModel::sizeToRatio(const QSize &siz) const
22 | {
23 | int a = siz.width();
24 | int b = siz.height();
25 | int c = a % b;
26 | int gcd = 0;
27 |
28 | while (c > 0) {
29 | a = b;
30 | b = c;
31 | c = a % b;
32 | }
33 |
34 | gcd = b;
35 | return siz / gcd;
36 | }
37 |
38 | ResolutionModel::ResolutionModel()
39 | {
40 | }
41 |
42 | QHash ResolutionModel::roleNames() const
43 | {
44 | QHash roles;
45 | roles[ResolutionName] = "name";
46 | roles[ResolutionValue] = "value";
47 | return roles;
48 | }
49 |
50 | int ResolutionModel::rowCount(const QModelIndex &parent) const
51 | {
52 | Q_UNUSED(parent);
53 | return m_resolutions.size();
54 | }
55 |
56 | QVariant ResolutionModel::data(const QModelIndex &index, int role) const
57 | {
58 | QVariant v;
59 |
60 | if (!index.isValid() || index.row() > rowCount(index) || index.row() < 0) {
61 | return v;
62 | }
63 |
64 | if (role == ResolutionName) {
65 | QSize r = sizeToRatio(m_resolutions.at(index.row()).second);
66 | v = QString("%1 (%2:%3)").arg(m_resolutions.at(index.row()).first).arg(r.width()).arg(r.height());
67 | } else if (role == ResolutionValue) {
68 | v = m_resolutions.at(index.row()).second;
69 | } else if (role == ResolutionMpx) {
70 | v = m_resolutions.at(index.row()).second.width() * m_resolutions.at(index.row()).second.height();
71 | }
72 | return v;
73 | }
74 |
75 | void ResolutionModel::setImageCapture(QObject *capture)
76 | {
77 | QCameraImageCapture *cap = nullptr;
78 | QList captures = capture->findChildren();
79 |
80 | if (captures.count() > 0) {
81 | cap = captures[0]; //first will do!
82 | }
83 |
84 | if (cap) {
85 | m_supportedImageResolutions = cap->supportedResolutions();
86 | if (!m_mode.isEmpty()) {
87 | setMode(m_mode);
88 | }
89 | }
90 | }
91 |
92 | void ResolutionModel::setVideoRecorder(QObject *capture)
93 | {
94 | QMediaRecorder *cap = nullptr;
95 | QList captures = capture->findChildren();
96 |
97 | if (captures.count() > 0) {
98 | cap = captures[0]; //first will do!
99 | }
100 |
101 | if (cap) {
102 | m_supportedVideoResolutions = cap->supportedResolutions();
103 | if (!m_mode.isEmpty()) {
104 | setMode(m_mode);
105 | }
106 | }
107 | }
108 |
109 | void ResolutionModel::setMode(const QString &mode)
110 | {
111 | m_mode = mode;
112 | beginResetModel();
113 | m_resolutions.clear();
114 |
115 | if (mode == "image") {
116 | for (int i = 0; i < m_supportedImageResolutions.count() ; i++) {
117 | m_resolutions.push_back(std::make_pair(QString("%1x%2").arg(m_supportedImageResolutions[i].width()).arg(
118 | m_supportedImageResolutions[i].height()), m_supportedImageResolutions[i]));
119 | }
120 | } else if (mode == "video") {
121 | for (int i = 0; i < m_supportedVideoResolutions.count() ; i++) {
122 | m_resolutions.push_back(std::make_pair(QString("%1x%2").arg(m_supportedVideoResolutions[i].width()).arg(
123 | m_supportedVideoResolutions[i].height()), m_supportedVideoResolutions[i]));
124 | }
125 | }
126 |
127 | endResetModel();
128 | emit rowCountChanged();
129 |
130 | if (m_resolutions.size() > 0) {
131 | qDebug() << "Supported " << mode << " resolutions:";
132 | for(const auto &res: m_resolutions) {
133 | qDebug() << res.first;
134 | }
135 | } else {
136 | qWarning() << "No resolutions found";
137 | }
138 | }
139 |
140 | QSize ResolutionModel::defaultResolution(const QString &mode)
141 | {
142 | if (mode == "video") {
143 | if (m_supportedVideoResolutions.count() > 0) {
144 | return m_supportedVideoResolutions.at(m_supportedVideoResolutions.count() - 1);
145 | }
146 | } else if (mode == "image") {
147 | if (m_supportedImageResolutions.count() > 0) {
148 | return m_supportedImageResolutions.at(m_supportedImageResolutions.count() - 1);
149 | }
150 | }
151 | return QSize(0, 0);
152 | }
153 |
154 | bool ResolutionModel::isValidResolution(const QSize &resolution, const QString &mode)
155 | {
156 | if (mode == "image") {
157 | return m_supportedImageResolutions.contains(resolution);
158 | } else if (mode == "video") {
159 | return m_supportedVideoResolutions.contains(resolution);
160 | }
161 | return false;
162 | }
163 |
--------------------------------------------------------------------------------
/src/resolutionmodel.h:
--------------------------------------------------------------------------------
1 | /**
2 | harbour-advanced-camera C++ Camera Models
3 | Copyright (C) 2019 Adam Pigg (adam@piggz.co.uk)
4 |
5 | This library is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU Lesser General Public
7 | License as published by the Free Software Foundation; either
8 | version 2.1 of the License, or (at your option) any later version.
9 |
10 | This library is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | Lesser General Public License for more details.
14 |
15 | You should have received a copy of the GNU Lesser General Public
16 | License along with this library; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 | **/
19 | #ifndef RESOLUTIONMODEL_H
20 | #define RESOLUTIONMODEL_H
21 |
22 | #include
23 | #include
24 | #include
25 |
26 | class ResolutionModel : public QAbstractListModel
27 | {
28 | Q_OBJECT
29 | Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged)
30 |
31 | public:
32 |
33 | enum ResolutionRoles {
34 | ResolutionName = Qt::UserRole + 1,
35 | ResolutionValue,
36 | ResolutionMpx
37 | };
38 |
39 | ResolutionModel();
40 |
41 | virtual QHash roleNames() const;
42 | virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
43 | virtual QVariant data(const QModelIndex &index, int role) const;
44 |
45 | Q_INVOKABLE QSize sizeToRatio(const QSize &siz) const;
46 | Q_INVOKABLE void setImageCapture(QObject *camera);
47 | Q_INVOKABLE void setVideoRecorder(QObject *capture);
48 | Q_INVOKABLE void setMode(const QString &mode);
49 | Q_INVOKABLE QSize defaultResolution(const QString &mode);
50 | Q_INVOKABLE bool isValidResolution(const QSize &resolution, const QString &mode);
51 |
52 | private:
53 | std::vector> m_resolutions;
54 | QList m_supportedImageResolutions;
55 | QList m_supportedVideoResolutions;
56 | QString m_mode = "image";
57 |
58 | signals:
59 | void rowCountChanged();
60 | };
61 |
62 | #endif // RESOLUTIONMODEL_H
63 |
--------------------------------------------------------------------------------
/src/resourcehandler.cpp:
--------------------------------------------------------------------------------
1 | #include "resourcehandler.h"
2 | #include
3 | #include
4 |
5 | void grant_callback(resource_set_t *, uint32_t, void *) {}
6 |
7 | static resource_set_t *(*create_set)(const char *, uint32_t, uint32_t, uint32_t,
8 | resource_callback_t, void *);
9 | static int (*acquire_set)(resource_set_t *);
10 | static int (*release_set)(resource_set_t *);
11 |
12 | ResourceHandler::ResourceHandler(QObject *parent) :
13 | QObject(parent)
14 | {
15 |
16 | m_handle = dlopen ((sizeof(void*) == 8) ? "/usr/lib64/libresource-glib.so.0" : "/usr/lib/libresource-glib.so.0", RTLD_LAZY);
17 |
18 | if (m_handle) {
19 | create_set = (resource_set_t *(*)(const char *, uint32_t, uint32_t, uint32_t, resource_callback_t,
20 | void *))dlsym(m_handle, "resource_set_create");
21 | if (!create_set) {
22 | qDebug() << dlerror();
23 | }
24 | acquire_set = (int (*)(resource_set_t *))dlsym(m_handle, "resource_set_acquire");
25 | if (!acquire_set) {
26 | qDebug() << dlerror();
27 | }
28 | release_set = (int (*)(resource_set_t *))dlsym(m_handle, "resource_set_release");
29 | if (!release_set) {
30 | qDebug() << dlerror();
31 | }
32 | if (!create_set || !acquire_set || !release_set) {
33 | qDebug() << "Error in dlsym to one of the functions";
34 | } else {
35 | qDebug() << "Creating resource set";
36 | m_resource = create_set("player", RESOURCE_SCALE_BUTTON | RESOURCE_SNAP_BUTTON, 0, 0,
37 | &grant_callback, nullptr);
38 | }
39 | } else {
40 | qDebug() << "Unable to open libresource. Unable to use hardware keys";
41 | }
42 | }
43 |
44 | void ResourceHandler::acquire()
45 | {
46 | if (acquire_set) {
47 | acquire_set(m_resource);
48 | }
49 | }
50 |
51 | void ResourceHandler::release()
52 | {
53 | if (release_set) {
54 | release_set(m_resource);
55 | }
56 | }
57 |
58 | void ResourceHandler::handleFocusChange(QObject *focus)
59 | {
60 | if (focus == nullptr) {
61 | release();
62 | } else {
63 | acquire();
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/resourcehandler.h:
--------------------------------------------------------------------------------
1 | #ifndef RESOURCEHANDLER_H
2 | #define RESOURCEHANDLER_H
3 |
4 | #include
5 |
6 | #define RESOURCE_BIT(b) (((uint32_t)1) << (b))
7 | #define RESOURCE_SCALE_BUTTON RESOURCE_BIT( 10 )
8 | #define RESOURCE_SNAP_BUTTON RESOURCE_BIT( 11 )
9 |
10 | typedef struct resource_set_t resource_set_t;
11 | typedef void (*resource_callback_t)(resource_set_t *, uint32_t, void *);
12 |
13 |
14 | class ResourceHandler : public QObject
15 | {
16 | Q_OBJECT
17 | public:
18 | explicit ResourceHandler(QObject *parent = 0);
19 |
20 | public slots:
21 | void acquire();
22 | void release();
23 | void handleFocusChange(QObject *focus);
24 |
25 | private:
26 | resource_set_t *m_resource;
27 | void *m_handle = nullptr;
28 | };
29 |
30 | #endif // RESOURCEHANDLER_H
31 |
--------------------------------------------------------------------------------
/src/storagemodel.cpp:
--------------------------------------------------------------------------------
1 | #include "storagemodel.h"
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | Storage::Storage(const QString &name, const QString &path) :
8 | m_name(name), m_path(path)
9 | {
10 | qDebug() << "Storage:" << name << path;
11 | }
12 |
13 | StorageModel::StorageModel()
14 | {
15 | scan();
16 | }
17 |
18 | QHash StorageModel::roleNames() const
19 | {
20 | QHash roles;
21 | roles[StorageName] = "name";
22 | roles[StoragePath] = "value";
23 | return roles;
24 | }
25 |
26 | int StorageModel::rowCount(const QModelIndex &parent) const
27 | {
28 | Q_UNUSED(parent);
29 | return m_storage.size();
30 | }
31 |
32 | QVariant StorageModel::data(const QModelIndex &index, int role) const
33 | {
34 | QVariant v;
35 |
36 | if (!index.isValid() || index.row() > rowCount(index) || index.row() < 0) {
37 | return v;
38 | }
39 |
40 | switch(role) {
41 | case StorageName:
42 | return m_storage[index.row()].name();
43 | case StoragePath:
44 | return m_storage[index.row()].path();
45 | default:
46 | return QVariant();
47 | }
48 | }
49 |
50 | void StorageModel::scan()
51 | {
52 | qDebug() << "Scanning storage directories";
53 | QString homeDir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
54 |
55 | beginResetModel();
56 | m_storage.clear();
57 | m_storage.append(Storage(tr("Internal storage"), homeDir));
58 |
59 | for (const QStorageInfo &storage : QStorageInfo::mountedVolumes()) {
60 |
61 | QString mountPoint = storage.rootPath();
62 |
63 | // Sailfish OS specific mount point base for SD cards!
64 | if (storage.isValid() &&
65 | storage.isReady() &&
66 | (mountPoint.startsWith("/media") ||
67 | mountPoint.startsWith("/run/media/") /* SFOS >= 2.2 */ )
68 | ) {
69 |
70 | qDebug() << "Found storage:" << mountPoint;
71 | m_storage << Storage(QDir(mountPoint).dirName(), mountPoint);
72 | }
73 | }
74 |
75 | endResetModel();
76 | emit rowCountChanged();
77 | }
78 |
--------------------------------------------------------------------------------
/src/storagemodel.h:
--------------------------------------------------------------------------------
1 | #ifndef STORAGEMODEL_H
2 | #define STORAGEMODEL_H
3 |
4 | #include
5 | #include
6 |
7 | class Storage
8 | {
9 | public:
10 | explicit Storage(const QString &name, const QString &path);
11 | QString name() const { return m_name; }
12 | QString path() const { return m_path; }
13 | private:
14 | QString m_name, m_path;
15 | };
16 |
17 | class StorageModel : public QAbstractListModel
18 | {
19 | Q_OBJECT
20 | Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged)
21 |
22 | public:
23 | enum StorageRoles
24 | {
25 | StorageName = Qt::UserRole + 1,
26 | StoragePath
27 | };
28 |
29 | StorageModel();
30 | virtual QHash roleNames() const;
31 | virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
32 | virtual QVariant data(const QModelIndex &index, int role) const;
33 | Q_INVOKABLE QVariant getName(int index) const { return m_storage.at(index).name(); }
34 | Q_INVOKABLE QVariant getPath(int index) const { return m_storage.at(index).path(); }
35 | public slots:
36 | void scan();
37 | private:
38 | QList m_storage;
39 |
40 | signals:
41 | void rowCountChanged();
42 |
43 | };
44 |
45 | #endif // STORAGEMODEL_H
46 |
--------------------------------------------------------------------------------
/src/wbmodel.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | harbour-advanced-camera C++ Camera Models
3 | Copyright (C) 2019 Adam Pigg (adam@piggz.co.uk)
4 |
5 | This library is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU Lesser General Public
7 | License as published by the Free Software Foundation; either
8 | version 2.1 of the License, or (at your option) any later version.
9 |
10 | This library is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | Lesser General Public License for more details.
14 |
15 | You should have received a copy of the GNU Lesser General Public
16 | License along with this library; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 | **/
19 | #include "wbmodel.h"
20 |
21 | WbModel::WbModel()
22 | {
23 | }
24 |
25 | QHash WbModel::roleNames() const
26 | {
27 | QHash roles;
28 | roles[WbName] = "name";
29 | roles[WbValue] = "value";
30 | return roles;
31 | }
32 |
33 | int WbModel::rowCount(const QModelIndex &parent) const
34 | {
35 | Q_UNUSED(parent);
36 | return m_wbModes.size();
37 | }
38 |
39 | QVariant WbModel::data(const QModelIndex &index, int role) const
40 | {
41 | QVariant v;
42 |
43 | if (!index.isValid() || index.row() > rowCount(index) || index.row() < 0) {
44 | return v;
45 | }
46 |
47 | if (role == WbName) {
48 | v = m_wbModes.at(index.row()).second;
49 | } else if (role == WbValue) {
50 | v = m_wbModes.at(index.row()).first;
51 | }
52 |
53 | return v;
54 | }
55 |
56 | void WbModel::setCamera(QObject *camera)
57 | {
58 | // even when m_camera instance is the same, deviceId could have changed and so available focus modes
59 | m_camera = camera->property("mediaObject").value();
60 |
61 | beginResetModel();
62 | m_wbModes.clear();
63 | for (int c = (int)QCameraImageProcessing::WhiteBalanceAuto;
64 | c <= (int)QCameraImageProcessing::WhiteBalanceWarmFluorescent; c++) {
65 | if (m_camera->imageProcessing()->isWhiteBalanceModeSupported((QCameraImageProcessing::WhiteBalanceMode)c)) {
66 | qDebug() << "Found support for" << (QCameraImageProcessing::WhiteBalanceMode)c;
67 | m_wbModes.push_back(std::make_pair((QCameraImageProcessing::WhiteBalanceMode)c, wbName((QCameraImageProcessing::WhiteBalanceMode)c)));
68 | }
69 | }
70 | endResetModel();
71 | emit rowCountChanged();
72 |
73 | if (m_wbModes.size() == 0) {
74 | qDebug() << "No white balance modes found";
75 | }
76 | }
77 |
78 | QString WbModel::wbName(QCameraImageProcessing::WhiteBalanceMode wb) const
79 | {
80 | QString name;
81 |
82 | switch (wb) {
83 | case QCameraImageProcessing::WhiteBalanceAuto:
84 | name = tr("Auto");
85 | break;
86 | case QCameraImageProcessing::WhiteBalanceManual:
87 | name = tr("Manual");
88 | break;
89 | case QCameraImageProcessing::WhiteBalanceSunlight:
90 | name = tr("Sunlight");
91 | break;
92 | case QCameraImageProcessing::WhiteBalanceCloudy:
93 | name = tr("Cloudy");
94 | break;
95 | case QCameraImageProcessing::WhiteBalanceShade:
96 | name = tr("Shade");
97 | break;
98 | case QCameraImageProcessing::WhiteBalanceTungsten:
99 | name = tr("Tungsten");
100 | break;
101 | case QCameraImageProcessing::WhiteBalanceFluorescent:
102 | name = tr("Fluorescent");
103 | break;
104 | case QCameraImageProcessing::WhiteBalanceFlash:
105 | name = tr("Flash");
106 | break;
107 | case QCameraImageProcessing::WhiteBalanceSunset:
108 | name = tr("Sunset");
109 | break;
110 | case QCameraImageProcessing::WhiteBalanceWarmFluorescent:
111 | name = tr("Warm Fluorescent");
112 | break;
113 | default:
114 | name = tr("Unknown");
115 | break;
116 | }
117 | return name;
118 | }
119 |
--------------------------------------------------------------------------------
/src/wbmodel.h:
--------------------------------------------------------------------------------
1 | /**
2 | harbour-advanced-camera C++ Camera Models
3 | Copyright (C) 2019 Adam Pigg (adam@piggz.co.uk)
4 |
5 | This library is free software; you can redistribute it and/or
6 | modify it under the terms of the GNU Lesser General Public
7 | License as published by the Free Software Foundation; either
8 | version 2.1 of the License, or (at your option) any later version.
9 |
10 | This library is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | Lesser General Public License for more details.
14 |
15 | You should have received a copy of the GNU Lesser General Public
16 | License along with this library; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 | **/
19 | #ifndef WBMODEL_H
20 | #define WBMODEL_H
21 |
22 | #include
23 | #include
24 |
25 | class WbModel : public QAbstractListModel
26 | {
27 | Q_OBJECT
28 | Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged)
29 |
30 | public:
31 |
32 | enum WbRoles {
33 | WbName = Qt::UserRole + 1,
34 | WbValue
35 | };
36 |
37 | WbModel();
38 |
39 | virtual QHash roleNames() const;
40 | virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
41 | virtual QVariant data(const QModelIndex &index, int role) const;
42 |
43 | Q_INVOKABLE void setCamera(QObject *camera);
44 |
45 | private:
46 | std::vector> m_wbModes;
47 | QCamera *m_camera = nullptr;
48 |
49 | QString wbName(QCameraImageProcessing::WhiteBalanceMode wb) const;
50 |
51 | signals:
52 | void rowCountChanged();
53 | };
54 |
55 | #endif // EFFECTSMODEL_H
56 |
--------------------------------------------------------------------------------