├── src
├── assets
│ ├── add.svg
│ ├── menu.svg
│ ├── back.svg
│ ├── info.svg
│ ├── edit.svg
│ ├── delete.svg
│ ├── assets.qrc
│ ├── applogo.svg
│ ├── sc-apps-fingerboard.svg
│ └── fingerprint.svg
├── registertypes.h
├── qml
│ ├── PointingHandOverlay.qml
│ ├── qml.qrc
│ ├── ErrorDialog.qml
│ ├── FingerDelegate.qml
│ ├── AboutDialog.qml
│ ├── DeleteDialog.qml
│ ├── LogPanel.qml
│ ├── VerifyView.qml
│ ├── EnrollView.qml
│ ├── ListingView.qml
│ ├── main.qml
│ └── CircularProgressBar.qml
├── utils
│ ├── deviceinfo.h
│ ├── deviceinfo.cpp
│ ├── logger.h
│ ├── finger.h
│ ├── logger.cpp
│ ├── finger.cpp
│ ├── appstate.cpp
│ └── appstate.h
├── CMakeLists.txt
├── main.cpp
├── fprintd-dbus-interface-xml
│ ├── fprintdmanager.xml
│ └── fprintddevice.xml
├── interfaces
│ ├── fingerboard_cpp_interface.h
│ └── fingerboard_cpp_interface.cpp
└── registertypes.cpp
├── fingerboard.desktop
├── logo.svg
├── .github
└── FUNDING.yml
├── LICENSE
├── cmake
└── cpack.cmake
├── CMakeLists.txt
├── .gitignore
├── README.rst
└── .clang-format
/src/assets/add.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/menu.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/back.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/info.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/edit.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/registertypes.h:
--------------------------------------------------------------------------------
1 | #ifndef REGISTERTYPES_H
2 | #define REGISTERTYPES_H
3 |
4 | #include
5 |
6 | #include "interfaces/fingerboard_cpp_interface.h"
7 | #include "utils/appstate.h"
8 | #include "utils/finger.h"
9 |
10 | void registerQmlTypes(QObject* parent = nullptr);
11 |
12 | #endif // REGISTERTYPES_H
13 |
--------------------------------------------------------------------------------
/fingerboard.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Name=Fingerboard
3 | Comment=Fingerprint GUI
4 | TryExec=fingerboard
5 | Exec=fingerboard %U
6 | Terminal=false
7 | Type=Application
8 | Categories=Qt;System;Utility;Settings;
9 | StartupNotify=true
10 | Icon=fingerboard
11 | # Generic name with translations
12 | GenericName=Fingerprint GUI
13 |
--------------------------------------------------------------------------------
/src/assets/delete.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/assets.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | applogo.svg
4 | fingerprint.svg
5 | add.svg
6 | edit.svg
7 | delete.svg
8 | back.svg
9 | info.svg
10 | menu.svg
11 | sc-apps-fingerboard.svg
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/qml/PointingHandOverlay.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | MouseArea {
4 | cursorShape: Qt.PointingHandCursor
5 | propagateComposedEvents: true
6 |
7 | onClicked: mouse.accepted = false;
8 | onPressed: mouse.accepted = false;
9 | onReleased: mouse.accepted = false;
10 | onDoubleClicked: mouse.accepted = false;
11 | onPositionChanged: mouse.accepted = false;
12 | onPressAndHold: mouse.accepted = false;
13 | }
14 |
--------------------------------------------------------------------------------
/src/utils/deviceinfo.h:
--------------------------------------------------------------------------------
1 | #ifndef UTILS_DEVICEINFO_H
2 | #define UTILS_DEVICEINFO_H
3 |
4 | #include
5 |
6 | class DeviceInfo : public QObject {
7 | Q_OBJECT
8 |
9 | public:
10 | DeviceInfo(QString name, QString scanType, int numEnrollStages,
11 | QObject *parent = nullptr);
12 |
13 | public slots:
14 | QString name();
15 | QString scanType();
16 | int numEnrollStages();
17 |
18 | private:
19 | QString _name;
20 | };
21 |
22 | #endif // UTILS_DEVICEINFO_H
23 |
--------------------------------------------------------------------------------
/src/utils/deviceinfo.cpp:
--------------------------------------------------------------------------------
1 | #include "deviceinfo.h"
2 |
3 | DeviceInfo::DeviceInfo(QString name, QString scanType, int numEnrollStages,
4 | QObject *parent)
5 | : QObject(parent) {
6 | this->_name = name;
7 | this->_scanType = scanType;
8 | this->_numEnrollStages = numEnrollStages;
9 | }
10 |
11 | QString DeviceInfo::name() { return _name; }
12 |
13 | QString DeviceInfo::scanType() { return _scanType; }
14 |
15 | int DeviceInfo::numEnrollStages() { return _numEnrollStages; }
16 |
--------------------------------------------------------------------------------
/src/qml/qml.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | main.qml
4 | LogPanel.qml
5 | ListingView.qml
6 | FingerDelegate.qml
7 | PointingHandOverlay.qml
8 | EnrollView.qml
9 | DeleteDialog.qml
10 | CircularProgressBar.qml
11 | VerifyView.qml
12 | ErrorDialog.qml
13 | AboutDialog.qml
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/utils/logger.h:
--------------------------------------------------------------------------------
1 | #ifndef UTILS_LOGGER
2 | #define UTILS_LOGGER
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | class Logger : public QObject {
10 | Q_OBJECT
11 |
12 | public:
13 | enum Level { ERROR = 0, WARNING, INFO, DEBUG, VERBOSE };
14 | Q_ENUM(Level)
15 |
16 | Logger(QObject *parent = nullptr);
17 | ~Logger();
18 |
19 | void log(Logger::Level level, QString msg);
20 | QString path();
21 |
22 | signals:
23 | void writeLog(Logger::Level logLevel, QString msg);
24 |
25 | private:
26 | QFile *file;
27 | };
28 |
29 | #endif // UTILS_LOGGER
30 |
--------------------------------------------------------------------------------
/src/assets/applogo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/assets/sc-apps-fingerboard.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [anupam-git]# Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 |
--------------------------------------------------------------------------------
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set(CMAKE_INCLUDE_CURRENT_DIR ON)
2 |
3 | set(
4 | FINGERBOARD_SRCS
5 |
6 | main.cpp
7 | registertypes.cpp
8 |
9 | interfaces/fingerboard_cpp_interface.cpp
10 |
11 | utils/logger.cpp
12 | utils/appstate.cpp
13 | utils/finger.cpp
14 | )
15 |
16 | set(
17 | FINGERBOARD_QML
18 |
19 | qml/qml.qrc
20 | assets/assets.qrc
21 | )
22 |
23 | qt5_add_dbus_interfaces(
24 | FPRINTD_DBUS_INTERFACES
25 |
26 | fprintd-dbus-interface-xml/fprintddevice.xml
27 | fprintd-dbus-interface-xml/fprintdmanager.xml
28 | )
29 |
30 | add_executable(
31 | ${PROJECT_NAME}
32 |
33 | ${FINGERBOARD_QML}
34 | ${FINGERBOARD_SRCS}
35 |
36 | ${FPRINTD_DBUS_INTERFACES}
37 | )
38 | target_link_libraries(
39 | ${PROJECT_NAME}
40 | PRIVATE
41 |
42 | Qt5::Core
43 | Qt5::Qml
44 | Qt5::Quick
45 | Qt5::DBus
46 | Qt5::QuickControls2
47 | )
48 | install(TARGETS ${PROJECT_NAME} DESTINATION bin)
49 |
--------------------------------------------------------------------------------
/src/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include "../fingerboard_version.h"
7 | #include "registertypes.h"
8 |
9 | int main(int argc, char *argv[]) {
10 | QQuickStyle::setStyle("Material");
11 | QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
12 |
13 | QGuiApplication app(argc, argv);
14 | QQmlApplicationEngine engine;
15 | const QUrl url(QStringLiteral("qrc:/main.qml"));
16 |
17 | app.setApplicationName("fingerboard");
18 | app.setApplicationDisplayName("Fingerboard");
19 | app.setApplicationVersion(FINGERBOARD_VERSION_STRING);
20 | app.setWindowIcon(QIcon(":/sc-apps-fingerboard.svg"));
21 |
22 | registerQmlTypes(&app);
23 |
24 | QObject::connect(
25 | &engine, &QQmlApplicationEngine::objectCreated, &app,
26 | [url](QObject *obj, const QUrl &objUrl) {
27 | if (!obj && url == objUrl) QCoreApplication::exit(-1);
28 | },
29 | Qt::QueuedConnection);
30 | engine.load(url);
31 |
32 | return app.exec();
33 | }
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Anupam Basak
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/cmake/cpack.cmake:
--------------------------------------------------------------------------------
1 | set(CPACK_GENERATOR "DEB")
2 |
3 | set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
4 | set(CPACK_DEBIAN_PACKAGE_DEPENDS
5 | "fprintd"
6 | "qml-module-qtquick-controls"
7 | "qml-module-qtquick-controls2"
8 | "qml-module-qtquick-layouts"
9 | "qml-module-qtgraphicaleffects"
10 | )
11 |
12 | set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Anupam Basak")
13 | set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A fprintd based GUI for listing, enrolling, deleting and verifying fingerprints for Linux")
14 | set(CPACK_PACKAGE_VENDOR "Anupam Basak")
15 | set(CPACK_PACKAGE_CONTACT "Anupam Basak ")
16 |
17 | set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.rst")
18 | set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
19 |
20 | set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
21 | set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
22 | set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
23 |
24 | set(CPACK_PACKAGE_INSTALL_DIRECTORY "CMake ${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}")
25 | set(CPACK_SOURCE_STRIP_FILES "")
26 |
27 | include(CPack)
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/qml/ErrorDialog.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.12
2 | import QtQuick.Controls 2.12
3 | import QtQuick.Layouts 1.12
4 | import QtQuick.Controls.Material 2.12
5 |
6 | Dialog {
7 | property alias errorString: errorLabel.text
8 |
9 | visible: true
10 | modal: true
11 | implicitWidth: 400
12 | z: 10
13 |
14 | font.pixelSize: 10
15 |
16 | x: (parent.width - width) / 2
17 | y: (parent.height - height) / 2
18 |
19 | footer: DialogButtonBox {
20 | Button {
21 | flat: true
22 | text: "OK"
23 | DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
24 | font.pixelSize: 10
25 | font.bold: true
26 | hoverEnabled: true
27 |
28 | PointingHandOverlay {
29 | anchors.fill: parent
30 | }
31 | }
32 | }
33 |
34 | ColumnLayout {
35 | Label {
36 | text: "ERROR"
37 | font.pixelSize: 15
38 | font.bold: true
39 | topPadding: 16
40 | bottomPadding: 16
41 | leftPadding: 12
42 | }
43 |
44 | Label {
45 | id: errorLabel
46 |
47 | font.pixelSize: 12
48 | leftPadding: 12
49 | }
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.0)
2 |
3 | set(FINGERBOARD_VERSION 0.2.2)
4 |
5 | project(fingerboard VERSION ${FINGERBOARD_VERSION})
6 |
7 | set(CMAKE_AUTOMOC ON)
8 | set(CMAKE_AUTORCC ON)
9 | set(CMAKE_INCLUDE_CURRENT_DIR ON)
10 |
11 | find_package(ECM 1.7.0 REQUIRED NO_MODULE)
12 | set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${ECM_MODULE_PATH})
13 |
14 | find_package(
15 | Qt5
16 | REQUIRED
17 | NO_MODULE
18 |
19 | COMPONENTS
20 | Core
21 | Qml
22 | Quick
23 | DBus
24 | QuickControls2
25 | )
26 |
27 | include(ECMSetupVersion)
28 | include(ECMInstallIcons)
29 | include(ECMAddAppIcon)
30 | include(KDEInstallDirs)
31 | include(KDECMakeSettings)
32 | include(FeatureSummary)
33 |
34 | set(CMAKE_CXX_STANDARD 17)
35 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
36 |
37 | ecm_setup_version(
38 | ${FINGERBOARD_VERSION}
39 |
40 | VARIABLE_PREFIX FINGERBOARD
41 | VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/fingerboard_version.h"
42 | )
43 | ecm_install_icons(
44 | ICONS src/assets/sc-apps-fingerboard.svg
45 | DESTINATION share/icons
46 | )
47 | install(FILES fingerboard.desktop DESTINATION ${XDG_APPS_INSTALL_DIR})
48 |
49 |
50 | add_subdirectory(src)
51 |
52 | feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)
53 |
54 | include(cmake/cpack.cmake)
55 |
--------------------------------------------------------------------------------
/src/utils/finger.h:
--------------------------------------------------------------------------------
1 | #ifndef UTILS_FINGER_H
2 | #define UTILS_FINGER_H
3 |
4 | #include
5 | #include
6 |
7 | class Finger : public QObject {
8 | Q_OBJECT
9 |
10 | public:
11 | enum Fingerprint {
12 | LEFT_THUMB,
13 | LEFT_INDEX,
14 | LEFT_MIDDLE,
15 | LEFT_RING,
16 | LEFT_LITTLE,
17 | RIGHT_THUMB,
18 | RIGHT_INDEX,
19 | RIGHT_MIDDLE,
20 | RIGHT_RING,
21 | RIGHT_LITTLE
22 | };
23 | Q_ENUM(Fingerprint)
24 |
25 | Finger(QObject *parent = nullptr);
26 |
27 | public slots:
28 | QString name(Fingerprint finger);
29 | Fingerprint fromName(QString rawFingerName);
30 | QString rawFingerName(int fingerprint);
31 |
32 | private:
33 | QMap rawFingersMap = {
34 | {"left-thumb", Fingerprint::LEFT_THUMB},
35 | {"left-index-finger", Fingerprint::LEFT_INDEX},
36 | {"left-middle-finger", Fingerprint::LEFT_MIDDLE},
37 | {"left-ring-finger", Fingerprint::LEFT_RING},
38 | {"left-little-finger", Fingerprint::LEFT_LITTLE},
39 |
40 | {"right-thumb", Fingerprint::RIGHT_THUMB},
41 | {"right-index-finger", Fingerprint::RIGHT_INDEX},
42 | {"right-middle-finger", Fingerprint::RIGHT_MIDDLE},
43 | {"right-ring-finger", Fingerprint::RIGHT_RING},
44 | {"right-little-finger", Fingerprint::RIGHT_LITTLE},
45 | };
46 | };
47 |
48 | #endif // UTILS_FINGER_H
49 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Compiled Object files
5 | *.slo
6 | *.lo
7 | *.o
8 | *.obj
9 |
10 | # Precompiled Headers
11 | *.gch
12 | *.pch
13 |
14 | # Compiled Dynamic libraries
15 | *.so
16 | *.dylib
17 | *.dll
18 |
19 | # Fortran module files
20 | *.mod
21 | *.smod
22 |
23 | # Compiled Static libraries
24 | *.lai
25 | *.la
26 | *.a
27 | *.lib
28 |
29 | # Executables
30 | *.exe
31 | *.out
32 | *.app
33 |
34 | # Qt-es
35 | object_script.*.Release
36 | object_script.*.Debug
37 | *_plugin_import.cpp
38 | /.qmake.cache
39 | /.qmake.stash
40 | *.pro.user
41 | *.pro.user.*
42 | *.qbs.user
43 | *.qbs.user.*
44 | *.moc
45 | moc_*.cpp
46 | moc_*.h
47 | qrc_*.cpp
48 | ui_*.h
49 | *.qmlc
50 | *.jsc
51 | Makefile*
52 | *build-*
53 |
54 | # Qt unit tests
55 | target_wrapper.*
56 |
57 | # QtCreator
58 | *.autosave
59 |
60 | # QtCreator Qml
61 | *.qmlproject.user
62 | *.qmlproject.user.*
63 |
64 | # QtCreator CMake
65 | CMakeLists.txt.user*
66 |
67 | # Bazaar files
68 | .bzr
69 |
70 | # BUILD FILES
71 | pkg/
72 | pkgbuild-fingerboard-*/
73 | fingerboard-*.pkg.tar.xz
74 | fingerboard-*.deb
75 | appimage-builder-cache/
76 | fingerboard*.AppImage
77 |
78 | # OTHERS
79 | build/
80 | build-scripts/src
81 | *.kdev4
82 | *.directory
83 | *.*~
84 | *.properties
85 | .*.kate-swp
86 | .swp.*
87 | *.DS_Store
88 | *.*~
89 | ~*.*
90 | ~.*
91 | .vscode
92 |
93 | # Exceptions
94 | !build-scripts/
95 | !build-scripts/build*.sh
--------------------------------------------------------------------------------
/src/utils/logger.cpp:
--------------------------------------------------------------------------------
1 | #include "logger.h"
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | #include "../fingerboard_version.h"
8 |
9 | Logger::Logger(QObject *parent) : QObject(parent) {
10 | file = new QFile(
11 | QStandardPaths::writableLocation(QStandardPaths::CacheLocation) +
12 | "/fingerboard.log");
13 | file->open(QIODevice::WriteOnly | QIODevice::Append);
14 | }
15 |
16 | void Logger::log(Logger::Level level, QString msg) {
17 | QString format = QString("%1 %2 : %3");
18 | QString logLevel = "";
19 |
20 | QString timestamp =
21 | QDateTime::currentDateTime().toString("dd/MMM/yyyy hh:mm:ss");
22 |
23 | switch (level) {
24 | case Level::INFO:
25 | logLevel = "[INFO]";
26 | break;
27 |
28 | case Level::DEBUG:
29 | logLevel = "[DEBUG]";
30 | break;
31 |
32 | case Level::VERBOSE:
33 | logLevel = "[VERBOSE]";
34 | break;
35 |
36 | case Level::WARNING:
37 | logLevel = "[WARNING]";
38 | break;
39 |
40 | case Level::ERROR:
41 | logLevel = "[ERROR]";
42 | break;
43 | }
44 |
45 | QString logMsg = format.arg(logLevel, 10).arg(timestamp, 22).arg(msg);
46 | QTextStream ts(file);
47 |
48 | ts << logMsg << '\n';
49 | ts.flush();
50 |
51 | emit writeLog(level, logMsg);
52 | }
53 |
54 | QString Logger::path() { return file->fileName(); }
55 |
56 | Logger::~Logger() { file->close(); }
57 |
--------------------------------------------------------------------------------
/src/utils/finger.cpp:
--------------------------------------------------------------------------------
1 | #include "finger.h"
2 |
3 | Finger::Finger(QObject *parent) : QObject(parent) {}
4 |
5 | QString Finger::name(Finger::Fingerprint finger) {
6 | switch (finger) {
7 | case Finger::Fingerprint::LEFT_THUMB:
8 | return "Left Thumb";
9 | case Finger::Fingerprint::LEFT_INDEX:
10 | return "Left Index Finger";
11 | case Finger::Fingerprint::LEFT_MIDDLE:
12 | return "Left Middle Finger";
13 | case Finger::Fingerprint::LEFT_RING:
14 | return "Left Ring Finger";
15 | case Finger::Fingerprint::LEFT_LITTLE:
16 | return "Left Little Finger";
17 | case Finger::Fingerprint::RIGHT_THUMB:
18 | return "Right Thumb";
19 | case Finger::Fingerprint::RIGHT_INDEX:
20 | return "Right Index Finger";
21 | case Finger::Fingerprint::RIGHT_MIDDLE:
22 | return "Right Middle Finger";
23 | case Finger::Fingerprint::RIGHT_RING:
24 | return "Right Ring Finger";
25 | case Finger::Fingerprint::RIGHT_LITTLE:
26 | return "Right Little Finger";
27 | }
28 |
29 | return "";
30 | }
31 |
32 | Finger::Fingerprint Finger::fromName(QString rawFingerName) {
33 | return rawFingersMap.value(rawFingerName);
34 | }
35 |
36 | QString Finger::rawFingerName(int fingerprint) {
37 | QMapIterator it(rawFingersMap);
38 | QString val = "";
39 |
40 | while (it.hasNext()) {
41 | it.next();
42 |
43 | if (fingerprint == it.value()) {
44 | val = it.key();
45 | break;
46 | }
47 | }
48 |
49 | return val;
50 | }
51 |
--------------------------------------------------------------------------------
/src/qml/FingerDelegate.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.12
2 | import QtQuick.Controls 2.12
3 | import QtQuick.Layouts 1.12
4 | import QtQuick.Controls.Material 2.12
5 | import QtGraphicalEffects 1.12
6 |
7 | Rectangle {
8 | RowLayout {
9 | anchors.verticalCenter: parent.verticalCenter
10 | width: parent.width
11 |
12 | Image {
13 | Layout.preferredWidth: 32
14 | Layout.preferredHeight: 32
15 | source: "qrc:/fingerprint.svg"
16 | Layout.margins: 10
17 | opacity: model.enrolled ? 1 : 0.5
18 |
19 | ColorOverlay {
20 | anchors.fill: parent
21 | source: parent
22 | color: model.enrolled ? "#7dc73f" : Material.color(Material.Grey)
23 | }
24 | }
25 |
26 | Label {
27 | Layout.fillWidth: true
28 | text: model.text
29 | font.pixelSize: 13
30 | color: Material.color(Material.Grey, Material.Shade600)
31 | opacity: model.enrolled ? 1 : 0.5
32 | }
33 |
34 | RoundButton {
35 | flat: true
36 | icon.source: model.enrolled ? "qrc:/edit.svg" : "qrc:/add.svg"
37 | icon.color: Material.color(Material.Grey)
38 | icon.width: 18
39 | icon.height: 18
40 | opacity: 0.5
41 | hoverEnabled: true
42 |
43 | onClicked: {
44 | selectedEnrollingFinger = model.finger;
45 | appstack.push(enrollView);
46 | }
47 |
48 | PointingHandOverlay {
49 | anchors.fill: parent
50 | }
51 |
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/fprintd-dbus-interface-xml/fprintdmanager.xml:
--------------------------------------------------------------------------------
1 |
5 | ]>
6 |
7 |
8 |
10 |
11 |
12 |
13 |
14 |
15 | An array of object paths for devices.
16 |
17 |
18 |
19 |
20 |
21 | Enumerate all the fingerprint readers attached to the system. If there are
22 | no devices available, an empty array is returned.
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | The object path for the default device.
33 |
34 |
35 |
36 |
37 |
38 | Returns the default fingerprint reader device.
39 |
40 |
41 |
42 |
43 | if the device does not exist
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/assets/fingerprint.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/qml/AboutDialog.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.12
2 | import QtQuick.Controls 2.12
3 | import QtQuick.Layouts 1.12
4 | import QtQuick.Controls.Material 2.12
5 |
6 | Dialog {
7 | modal: true
8 | implicitWidth: 400
9 | font.pixelSize: 10
10 | z: 10
11 |
12 |
13 | x: (parent.width - width) / 2
14 | y: (parent.height - height) / 2
15 |
16 | footer: DialogButtonBox {
17 | Button {
18 | flat: true
19 | text: "OK"
20 | font.pixelSize: 10
21 | font.bold: true
22 | hoverEnabled: true
23 | DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
24 |
25 | PointingHandOverlay {
26 | anchors.fill: parent
27 | }
28 | }
29 | }
30 |
31 | ColumnLayout {
32 | Label {
33 | text: "About"
34 | font.pixelSize: 24
35 | font.bold: true
36 | topPadding: 16
37 | bottomPadding: 16
38 | leftPadding: 12
39 | }
40 |
41 | Label {
42 | text: "A fprintd based fingerprint GUI for Linux"
43 |
44 | Layout.topMargin: 12
45 | font.pixelSize: 12
46 | leftPadding: 12
47 | }
48 |
49 | Label {
50 | text: "Author : Anupam Basak <GitHub>"
51 | onLinkActivated: Qt.openUrlExternally(link)
52 |
53 | Layout.topMargin: 32
54 | font.pixelSize: 12
55 | leftPadding: 12
56 | }
57 | Label {
58 | text: "Repository : https://github.com/anupam-git/fingerboard"
59 | onLinkActivated: Qt.openUrlExternally(link)
60 |
61 | enabled: true
62 | font.pixelSize: 12
63 | leftPadding: 12
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | ===========
2 | Fingerboard
3 | ===========
4 |
5 | | A fprintd_ based fingerprint GUI for Linux
6 |
7 | Fingerboard is a fingerprint GUI to enroll, list, delete and verify fingerprints.
8 | Fingerboard is a GUI interface to fprint, and uses the D-Bus interfaces to communicate with fprint.
9 |
10 | Building
11 | --------
12 | The project uses CMake build system. Follow the steps below to build, compile and install this project.
13 |
14 | Dependencies - Ubuntu
15 | ^^^^^^^^^^^^^^^^^^^^^
16 | Note: Requires ``universe`` repository to be enabled for qt dependencies.
17 |
18 | .. code-block:: bash
19 |
20 | apt install \
21 | gcc \
22 | g++ \
23 | make \
24 | cmake \
25 | extra-cmake-modules \
26 | qtbase5-dev \
27 | qtdeclarative5-dev \
28 | qtquickcontrols2-5-dev \
29 | libqt5svg5-dev \
30 | qml-module-qtquick-controls \
31 | qml-module-qtquick-controls2 \
32 | qml-module-qtgraphicaleffects \
33 | qml-module-qtquick-layouts
34 |
35 | Dependencies - Arch
36 | ^^^^^^^^^^^^^^^^^^^
37 |
38 | .. code-block:: bash
39 |
40 | pacman -S \
41 | gcc \
42 | make \
43 | cmake \
44 | extra-cmake-modules \
45 | qt5-base \
46 | qt5-graphicaleffects \
47 | qt5-svg \
48 | qt5-quickcontrols \
49 | qt5-quickcontrols2
50 |
51 | Build and compile
52 | ^^^^^^^^^^^^^^^^^
53 |
54 | .. code-block:: bash
55 |
56 | # Make a build directory and cd into it
57 | mkdir build && cd build
58 |
59 | # Run cmake
60 | cmake .. -DCMAKE_INSTALL_PREFIX=/usr
61 |
62 | # Build the project
63 | make -j$(nproc)
64 |
65 | # [OPTIONAL] Install to system (requires root access)
66 | sudo make install
67 |
68 | Hacking
69 | -------
70 | #. Any kind of contribution is appreciated
71 | #. Format the cpp sources and headers with ``clang-format -i -style=file ``
72 | #. Properly indent qml source
73 |
74 | .. References
75 | .. ----------
76 | .. _fprintd: https://fprint.freedesktop.org/
77 | .. _HACKING.rst: HACKING.rst
78 |
--------------------------------------------------------------------------------
/src/qml/DeleteDialog.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.12
2 | import QtQuick.Controls 2.12
3 | import QtQuick.Layouts 1.12
4 | import QtQuick.Controls.Material 2.12
5 |
6 | import Fingerboard 1.0
7 |
8 | Dialog {
9 | modal: true
10 | implicitWidth: 400
11 | z: 10
12 |
13 | font.pixelSize: 10
14 |
15 | x: (parent.width - width) / 2
16 | y: (parent.height - height) / 2
17 |
18 | footer: DialogButtonBox {
19 | Button {
20 | flat: true
21 | text: "CANCEL"
22 | DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
23 | font.pixelSize: 12
24 | font.bold: true
25 | hoverEnabled: true
26 |
27 | PointingHandOverlay {
28 | anchors.fill: parent
29 | }
30 | }
31 | Button {
32 | flat: true
33 | text: "DELETE"
34 | DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
35 | font.pixelSize: 12
36 | font.bold: true
37 | hoverEnabled: true
38 |
39 | Material.accent: Material.Red
40 |
41 | PointingHandOverlay {
42 | anchors.fill: parent
43 | }
44 | }
45 | }
46 |
47 | onAccepted: {
48 | FingerboardCppInterface.deleteFp();
49 | }
50 |
51 | Connections {
52 | target: AppState
53 |
54 | // function onDeleteCompleted()
55 | onDeleteCompleted: {
56 | FingerboardCppInterface.listFp();
57 | }
58 | }
59 |
60 | ColumnLayout {
61 | Label {
62 | text: "Delete Fingerprints"
63 | font.pixelSize: 16
64 | font.bold: true
65 | topPadding: 16
66 | bottomPadding: 16
67 | leftPadding: 12
68 | }
69 |
70 | Label {
71 | text: "Are you sure you wish to delete ALL fingerprints ?"
72 | font.pixelSize: 14
73 | leftPadding: 12
74 | }
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/src/interfaces/fingerboard_cpp_interface.h:
--------------------------------------------------------------------------------
1 | #ifndef INTERFACES_FINGERBOARD_CPP_INTERFACE_H
2 | #define INTERFACES_FINGERBOARD_CPP_INTERFACE_H
3 |
4 | #include
5 | #include
6 |
7 | #include "fprintddeviceinterface.h"
8 | #include "fprintdmanagerinterface.h"
9 | #include "utils/appstate.h"
10 | #include "utils/deviceinfo.h"
11 | #include "utils/finger.h"
12 | #include "utils/logger.h"
13 |
14 | #define FPRINTD_SERVICE "net.reactivated.Fprint"
15 |
16 | class FingerboardCppInterface : public QObject {
17 | Q_OBJECT
18 |
19 | Q_PROPERTY(QString deviceName READ getDeviceName NOTIFY deviceNameChanged)
20 | Q_PROPERTY(QString scanType READ getScanType NOTIFY scanTypeChanged)
21 | Q_PROPERTY(
22 | int numEnrollStages READ getNumEnrollStages NOTIFY numEnrollStagesChanged)
23 |
24 | public:
25 | FingerboardCppInterface(Finger *fingerObj, Logger *logger, AppState *appState,
26 | QObject *parent = nullptr);
27 |
28 | QString getDeviceName();
29 | QString getScanType();
30 | int getNumEnrollStages();
31 |
32 | public slots:
33 | void init();
34 | void deviceInfo();
35 | void listFp();
36 | void enrollFp(int finger);
37 | void verifyFp(QString finger = "any");
38 | void deleteFp();
39 |
40 | signals:
41 | void enrolledFingerprintsList(QList fingerprints);
42 | void log(int logLevel, QString msg);
43 |
44 | void deviceNameChanged(QString deviceName);
45 | void scanTypeChanged(QString scanType);
46 | void numEnrollStagesChanged(int numEnrollStages);
47 |
48 | private:
49 | net::reactivated::Fprint::Device *fprintdInterfaceDevice;
50 | net::reactivated::Fprint::Manager *fprintdInterfaceManager;
51 | QDBusInterface *fprintdDevicePropertiesInterface;
52 | QString username = qgetenv("USER");
53 | QString defaultDevicePath;
54 | AppState *appState;
55 | Logger *logger;
56 | Finger *fingerObj;
57 |
58 | QString _deviceName;
59 | QString _scanType;
60 | int _numEnrollStages;
61 |
62 | bool claimFpDevice();
63 | void releaseFpDevice();
64 |
65 | private slots:
66 | void enrollStatusSlot(QString result, bool done);
67 | void verifyStatusSlot(QString result, bool done);
68 | };
69 |
70 | #endif // INTERFACES_FINGERBOARD_CPP_INTERFACE_H
71 |
--------------------------------------------------------------------------------
/src/registertypes.cpp:
--------------------------------------------------------------------------------
1 | #include "registertypes.h"
2 |
3 | #include
4 |
5 | #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
6 |
7 | Logger *logger = nullptr;
8 | Finger *fingerObj = nullptr;
9 | AppState *appState = nullptr;
10 | FingerboardCppInterface *fingerboardCppInterface = nullptr;
11 |
12 | static QObject *fingerObjSingletonProvider(QQmlEngine *e, QJSEngine *j) {
13 | Q_UNUSED(j)
14 |
15 | if (fingerObj == nullptr) {
16 | fingerObj = new Finger(e);
17 | }
18 |
19 | return fingerObj;
20 | }
21 | static QObject *appStateSingletonProvider(QQmlEngine *e, QJSEngine *j) {
22 | Q_UNUSED(j)
23 |
24 | if (appState == nullptr) {
25 | appState = new AppState(e);
26 | }
27 |
28 | return appState;
29 | }
30 | static QObject *fingerboardCppInterfaceSingletonProvider(QQmlEngine *e,
31 | QJSEngine *j) {
32 | Q_UNUSED(j)
33 |
34 | if (logger == nullptr) {
35 | logger = new Logger(e);
36 | }
37 |
38 | if (fingerObj == nullptr) {
39 | fingerObj = new Finger(e);
40 | }
41 |
42 | if (appState == nullptr) {
43 | appState = new AppState(e);
44 | }
45 |
46 | if (fingerboardCppInterface == nullptr) {
47 | fingerboardCppInterface =
48 | new FingerboardCppInterface(fingerObj, logger, appState, e);
49 | }
50 |
51 | return fingerboardCppInterface;
52 | }
53 |
54 | void registerQmlTypes(QObject *parent) {
55 | qmlRegisterSingletonType(
56 | "Fingerboard", 1, 0, "FingerboardCppInterface",
57 | fingerboardCppInterfaceSingletonProvider);
58 |
59 | qmlRegisterSingletonType("Fingerboard", 1, 0, "AppState",
60 | appStateSingletonProvider);
61 |
62 | qmlRegisterSingletonType("Fingerboard", 1, 0, "Finger",
63 | fingerObjSingletonProvider);
64 | qmlRegisterUncreatableType(
65 | "Fingerboard", 1, 0, "Logger",
66 | "Logger can be instantiated from c++ only");
67 | }
68 | #else
69 | void registerQmlTypes(QObject *parent) {
70 | Finger *fingerObj = new Finger(parent);
71 | Logger *logger = new Logger(parent);
72 | AppState *appState = new AppState(parent);
73 | FingerboardCppInterface *fingerboardCppInterface =
74 | new FingerboardCppInterface(fingerObj, logger, appState, parent);
75 |
76 | qmlRegisterSingletonInstance(
77 | "Fingerboard", 1, 0, "FingerboardCppInterface", fingerboardCppInterface);
78 | qmlRegisterSingletonInstance("Fingerboard", 1, 0, "AppState",
79 | appState);
80 | qmlRegisterSingletonInstance("Fingerboard", 1, 0, "Finger",
81 | fingerObj);
82 | qmlRegisterUncreatableType(
83 | "Fingerboard", 1, 0, "Logger",
84 | "Logger can be instantiated from c++ only");
85 | }
86 | #endif
87 |
--------------------------------------------------------------------------------
/src/utils/appstate.cpp:
--------------------------------------------------------------------------------
1 | #include "appstate.h"
2 |
3 | AppState::AppState(QObject *parent) : QObject(parent) {}
4 |
5 | AppState::ErrorStatus AppState::errorStatusFromRawString(
6 | QString rawErrorString) {
7 | return rawErrorMap.value(rawErrorString);
8 | }
9 |
10 | void AppState::raiseError(QString rawError) {
11 | raiseError(rawErrorMap.value(rawError));
12 | }
13 |
14 | void AppState::raiseError(AppState::ErrorStatus errorStatus) {
15 | emit error(errorStatus, errorStatusString(errorStatus));
16 | }
17 |
18 | AppState::EnrollStatus AppState::getEnrollStatus() { return _enrollStatus; }
19 |
20 | AppState::EnrollStatus AppState::enrollStatusFromRawString(QString rawStatus) {
21 | return rawEnrollStatusMap.value(rawStatus);
22 | }
23 |
24 | void AppState::setEnrollStatus(AppState::EnrollStatus status) {
25 | _enrollStatus = status;
26 | emit enrollStatusChanged(status);
27 | }
28 |
29 | AppState::VerifyStatus AppState::getVerifyStatus() { return _verifyStatus; }
30 |
31 | AppState::VerifyStatus AppState::verifyStatusFromRawString(QString rawStatus) {
32 | return rawVerifyStatusMap.value(rawStatus);
33 | }
34 |
35 | void AppState::setVerifyStatus(AppState::VerifyStatus status) {
36 | _verifyStatus = status;
37 | emit verifyStatusChanged(status);
38 | }
39 |
40 | void AppState::resetApp() {
41 | _enrollStatus = EnrollStatus::ENROLL_EMPTY;
42 | _verifyStatus = VerifyStatus::VERIFY_EMPTY;
43 |
44 | emit enrollStatusChanged(_enrollStatus);
45 | emit verifyStatusChanged(_verifyStatus);
46 | }
47 |
48 | QString AppState::errorStatusString(AppState::ErrorStatus status) {
49 | switch (status) {
50 | case AppState::ErrorStatus::ERROR_NO_DEVICE:
51 | return "No Fingerprint Reader found";
52 | case AppState::ErrorStatus::ERROR_PERMISSION_DENIED:
53 | return "User lacks the appropriate PolicyKit authorization";
54 | case AppState::ErrorStatus::ERROR_NO_ENROLLED_PRINTS:
55 | return "User doesn't have any fingerprints enrolled";
56 | case AppState::ErrorStatus::ERROR_ALREADY_IN_USE:
57 | return "Device is already claimed";
58 | case AppState::ErrorStatus::ERROR_INTERNAL:
59 | return "Device couldn't be claimed";
60 | case AppState::ErrorStatus::ERROR_CLAIM_DEVICE:
61 | return "Device was not claimed";
62 | case AppState::ErrorStatus::ERROR_NO_ACTION_IN_PROGRESS:
63 | return "There are no ongoing verification";
64 | case AppState::ErrorStatus::ERROR_INVALID_FINGERNAME:
65 | return "Finger name passed is invalid";
66 | }
67 |
68 | return "";
69 | }
70 |
71 | QString AppState::getEnrollStatusString() {
72 | switch (_enrollStatus) {
73 | case AppState::EnrollStatus::ENROLL_EMPTY:
74 | return "";
75 | case AppState::EnrollStatus::ENROLL_START:
76 | return "Touch/Swipe to start Enrolling";
77 | case AppState::EnrollStatus::ENROLL_FAILED:
78 | return "The enrollment failed";
79 | case AppState::EnrollStatus::ENROLL_COMPLETED:
80 | return "The enrollment successfully completed";
81 | case AppState::EnrollStatus::ENROLL_DATA_FULL:
82 | return "No further prints can be enrolled on this device";
83 | case AppState::EnrollStatus::ENROLL_RETRY_SCAN:
84 | return "Retry scanning the finger";
85 | case AppState::EnrollStatus::ENROLL_DISCONNECTED:
86 | return "The device was disconnected during the enrollment";
87 | case AppState::EnrollStatus::ENROLL_STAGE_PASSED:
88 | return "Enrollment stage passed";
89 | case AppState::EnrollStatus::ENROLL_UNKNOWN_ERROR:
90 | return "An unknown error occurred";
91 | case AppState::EnrollStatus::ENROLL_SWIPE_TOO_SHORT:
92 | return "Swipe was too short";
93 | case AppState::EnrollStatus::ENROLL_REMOVE_AND_RETRY:
94 | return "Remove the finger from the reader and retry scanning";
95 | case AppState::EnrollStatus::ENROLL_FINGER_NOT_CENTERED:
96 | return "Finger was not centered on the reader";
97 | }
98 |
99 | return "";
100 | }
101 |
102 | QString AppState::getVerifyStatusString() {
103 | switch (_verifyStatus) {
104 | case AppState::VerifyStatus::VERIFY_EMPTY:
105 | return "";
106 | case AppState::VerifyStatus::VERIFY_START:
107 | return "Touch/Swipe to start Verification";
108 | case AppState::VerifyStatus::VERIFY_MATCH:
109 | return "The verification succeeded";
110 | case AppState::VerifyStatus::VERIFY_NO_MATCH:
111 | return "The verification did not match";
112 | case AppState::VerifyStatus::VERIFY_RETRY_SCAN:
113 | return "Retry scanning the finger";
114 | case AppState::VerifyStatus::VERIFY_DISCONNECTED:
115 | return "The device was disconnected during the verification";
116 | case AppState::VerifyStatus::VERIFY_UNKNOWN_ERROR:
117 | return "An unknown error occurred";
118 | case AppState::VerifyStatus::VERIFY_SWIPE_TOO_SHORT:
119 | return "Swipe was too short";
120 | case AppState::VerifyStatus::VERIFY_REMOVE_AND_RETRY:
121 | return "Remove the finger from the reader and retry scanning";
122 | case AppState::VerifyStatus::VERIFY_FINGER_NOT_CENTERED:
123 | return "Finger was not centered on the reader";
124 | }
125 |
126 | return "";
127 | }
128 |
--------------------------------------------------------------------------------
/src/qml/LogPanel.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.12
2 | import QtQuick.Controls 2.12
3 | import QtQuick.Controls.Material 2.12
4 | import QtQuick.Layouts 1.12
5 |
6 | import Fingerboard 1.0
7 |
8 | Rectangle {
9 | Connections {
10 | target: FingerboardCppInterface
11 |
12 | // function onLog(logLevel, msg)
13 | onLog: {
14 | logsModel.append({
15 | logLevel: logLevel,
16 | text: msg
17 | });
18 | logPane.positionViewAtEnd();
19 | }
20 | }
21 |
22 | ListModel {
23 | id: logsModel
24 | }
25 |
26 | ColumnLayout {
27 | anchors.fill: parent
28 |
29 | Rectangle {
30 | Layout.fillWidth: true
31 | height: 50
32 | color: "#f5f5f5"
33 |
34 | RowLayout {
35 | anchors {
36 | top: parent.top
37 | left: parent.left
38 | bottom: parent.bottom
39 | }
40 |
41 | Label {
42 | text: "Log Level"
43 | Layout.margins: 10
44 | font.pixelSize: 12
45 | }
46 |
47 | ComboBox {
48 | id: logLevelDropdown
49 | currentIndex: 2
50 | font.pixelSize: 12
51 |
52 | model: ListModel {
53 | id: logLevelModel
54 |
55 | ListElement {
56 | text: "ERROR"
57 | level: Logger.ERROR
58 | }
59 | ListElement {
60 | text: "WARNING"
61 | level: Logger.WARNING
62 | }
63 | ListElement {
64 | text: "INFO"
65 | level: Logger.INFO
66 | }
67 | ListElement {
68 | text: "DEBUG"
69 | level: Logger.DEBUG
70 | }
71 | ListElement {
72 | text: "VERBOSE"
73 | level: Logger.VERBOSE
74 | }
75 | }
76 | onCurrentIndexChanged: {
77 | logPane.forceLayout();
78 | }
79 | textRole: "text"
80 | delegate: ItemDelegate {
81 | width: parent.width
82 | text: model.text
83 | font.pixelSize: 12
84 | }
85 |
86 | function selected() {
87 | return logLevelModel.get(currentIndex);
88 | }
89 | }
90 |
91 | CheckBox {
92 | id: colorize
93 |
94 | checked: true
95 | font.pixelSize: 12
96 | text: "Colorize"
97 | Material.primary: Material.Blue
98 | }
99 | }
100 |
101 | Button {
102 | width: 50
103 | height: 50
104 | icon.name: "window-close"
105 | flat: true
106 |
107 | anchors {
108 | right: parent.right
109 | verticalCenter: parent.verticalCenter
110 | }
111 |
112 | onClicked: {
113 | showLogs = false;
114 | }
115 | }
116 | }
117 |
118 | ListView {
119 | id: logPane
120 | Layout.fillWidth: true
121 | Layout.fillHeight: true
122 |
123 | clip: true
124 | interactive: true
125 | model: logsModel
126 |
127 | ScrollBar.vertical: ScrollBar { active: true; visible: true }
128 |
129 | delegate: Label {
130 | property bool shouldShow: model.logLevel <= logLevelDropdown.selected().level
131 |
132 | width: parent.width
133 | color: colorize.checked ? logPane.getColor(model.logLevel) : Material.color(Material.Grey, Material.Shade800);
134 | text: model.text
135 | font.family: 'monospace'
136 | height: shouldShow ? implicitHeight : 0
137 | visible: shouldShow
138 | }
139 |
140 | function getColor(logLevel) {
141 | switch (logLevel) {
142 | case Logger.ERROR:
143 | return Material.color(Material.Red);
144 | case Logger.WARNING:
145 | return Material.color(Material.Orange);
146 | case Logger.INFO:
147 | return Material.color(Material.Blue);
148 | case Logger.DEBUG:
149 | return Material.color(Material.Grey, Material.Shade800);
150 | case Logger.VERBOSE:
151 | return Material.color(Material.Grey);
152 | }
153 | }
154 | }
155 | }
156 | }
157 |
158 |
--------------------------------------------------------------------------------
/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | Language: Cpp
3 | # BasedOnStyle: Google
4 | AccessModifierOffset: -1
5 | AlignAfterOpenBracket: Align
6 | AlignConsecutiveMacros: false
7 | AlignConsecutiveAssignments: false
8 | AlignConsecutiveDeclarations: false
9 | AlignEscapedNewlines: Left
10 | AlignOperands: true
11 | AlignTrailingComments: true
12 | AllowAllArgumentsOnNextLine: true
13 | AllowAllConstructorInitializersOnNextLine: true
14 | AllowAllParametersOfDeclarationOnNextLine: true
15 | AllowShortBlocksOnASingleLine: Never
16 | AllowShortCaseLabelsOnASingleLine: false
17 | AllowShortFunctionsOnASingleLine: All
18 | AllowShortLambdasOnASingleLine: All
19 | AllowShortIfStatementsOnASingleLine: WithoutElse
20 | AllowShortLoopsOnASingleLine: true
21 | AlwaysBreakAfterDefinitionReturnType: None
22 | AlwaysBreakAfterReturnType: None
23 | AlwaysBreakBeforeMultilineStrings: true
24 | AlwaysBreakTemplateDeclarations: Yes
25 | BinPackArguments: true
26 | BinPackParameters: true
27 | BraceWrapping:
28 | AfterCaseLabel: false
29 | AfterClass: false
30 | AfterControlStatement: false
31 | AfterEnum: false
32 | AfterFunction: false
33 | AfterNamespace: false
34 | AfterObjCDeclaration: false
35 | AfterStruct: false
36 | AfterUnion: false
37 | AfterExternBlock: false
38 | BeforeCatch: false
39 | BeforeElse: false
40 | IndentBraces: false
41 | SplitEmptyFunction: true
42 | SplitEmptyRecord: true
43 | SplitEmptyNamespace: true
44 | BreakBeforeBinaryOperators: None
45 | BreakBeforeBraces: Attach
46 | BreakBeforeInheritanceComma: false
47 | BreakInheritanceList: BeforeColon
48 | BreakBeforeTernaryOperators: true
49 | BreakConstructorInitializersBeforeComma: false
50 | BreakConstructorInitializers: BeforeColon
51 | BreakAfterJavaFieldAnnotations: false
52 | BreakStringLiterals: true
53 | ColumnLimit: 80
54 | CommentPragmas: '^ IWYU pragma:'
55 | CompactNamespaces: false
56 | ConstructorInitializerAllOnOneLineOrOnePerLine: true
57 | ConstructorInitializerIndentWidth: 4
58 | ContinuationIndentWidth: 4
59 | Cpp11BracedListStyle: true
60 | DeriveLineEnding: true
61 | DerivePointerAlignment: true
62 | DisableFormat: false
63 | ExperimentalAutoDetectBinPacking: false
64 | FixNamespaceComments: true
65 | ForEachMacros:
66 | - foreach
67 | - Q_FOREACH
68 | - BOOST_FOREACH
69 | IncludeBlocks: Regroup
70 | IncludeCategories:
71 | - Regex: '^'
72 | Priority: 2
73 | SortPriority: 0
74 | - Regex: '^<.*\.h>'
75 | Priority: 1
76 | SortPriority: 0
77 | - Regex: '^<.*'
78 | Priority: 2
79 | SortPriority: 0
80 | - Regex: '.*'
81 | Priority: 3
82 | SortPriority: 0
83 | IncludeIsMainRegex: '([-_](test|unittest))?$'
84 | IncludeIsMainSourceRegex: ''
85 | IndentCaseLabels: true
86 | IndentGotoLabels: true
87 | IndentPPDirectives: None
88 | IndentWidth: 2
89 | IndentWrappedFunctionNames: false
90 | JavaScriptQuotes: Leave
91 | JavaScriptWrapImports: true
92 | KeepEmptyLinesAtTheStartOfBlocks: false
93 | MacroBlockBegin: ''
94 | MacroBlockEnd: ''
95 | MaxEmptyLinesToKeep: 1
96 | NamespaceIndentation: None
97 | ObjCBinPackProtocolList: Never
98 | ObjCBlockIndentWidth: 2
99 | ObjCSpaceAfterProperty: false
100 | ObjCSpaceBeforeProtocolList: true
101 | PenaltyBreakAssignment: 2
102 | PenaltyBreakBeforeFirstCallParameter: 1
103 | PenaltyBreakComment: 300
104 | PenaltyBreakFirstLessLess: 120
105 | PenaltyBreakString: 1000
106 | PenaltyBreakTemplateDeclaration: 10
107 | PenaltyExcessCharacter: 1000000
108 | PenaltyReturnTypeOnItsOwnLine: 200
109 | PointerAlignment: Left
110 | RawStringFormats:
111 | - Language: Cpp
112 | Delimiters:
113 | - cc
114 | - CC
115 | - cpp
116 | - Cpp
117 | - CPP
118 | - 'c++'
119 | - 'C++'
120 | CanonicalDelimiter: ''
121 | BasedOnStyle: google
122 | - Language: TextProto
123 | Delimiters:
124 | - pb
125 | - PB
126 | - proto
127 | - PROTO
128 | EnclosingFunctions:
129 | - EqualsProto
130 | - EquivToProto
131 | - PARSE_PARTIAL_TEXT_PROTO
132 | - PARSE_TEST_PROTO
133 | - PARSE_TEXT_PROTO
134 | - ParseTextOrDie
135 | - ParseTextProtoOrDie
136 | CanonicalDelimiter: ''
137 | BasedOnStyle: google
138 | ReflowComments: true
139 | SortIncludes: true
140 | SortUsingDeclarations: true
141 | SpaceAfterCStyleCast: false
142 | SpaceAfterLogicalNot: false
143 | SpaceAfterTemplateKeyword: true
144 | SpaceBeforeAssignmentOperators: true
145 | SpaceBeforeCpp11BracedList: false
146 | SpaceBeforeCtorInitializerColon: true
147 | SpaceBeforeInheritanceColon: true
148 | SpaceBeforeParens: ControlStatements
149 | SpaceBeforeRangeBasedForLoopColon: true
150 | SpaceInEmptyBlock: false
151 | SpaceInEmptyParentheses: false
152 | SpacesBeforeTrailingComments: 2
153 | SpacesInAngles: false
154 | SpacesInConditionalStatement: false
155 | SpacesInContainerLiterals: true
156 | SpacesInCStyleCastParentheses: false
157 | SpacesInParentheses: false
158 | SpacesInSquareBrackets: false
159 | SpaceBeforeSquareBrackets: false
160 | Standard: Auto
161 | StatementMacros:
162 | - Q_UNUSED
163 | - QT_REQUIRE_VERSION
164 | TabWidth: 8
165 | UseCRLF: false
166 | UseTab: Never
167 | ...
168 |
169 |
--------------------------------------------------------------------------------
/src/qml/VerifyView.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.12
2 | import QtQuick.Controls 2.12
3 | import QtQuick.Layouts 1.12
4 | import QtQuick.Controls.Material 2.12
5 | import QtGraphicalEffects 1.0
6 |
7 | import Fingerboard 1.0
8 |
9 | Rectangle {
10 | property bool verifyStarted: false
11 | property bool verifyCompleted: false
12 | property bool verifyErrored: false
13 |
14 | width: 600
15 | height: 700
16 |
17 | Connections {
18 | target: AppState
19 |
20 | // function onVerifyStarted()
21 | onVerifyStarted: {
22 | verifyStarted= true;
23 | }
24 |
25 | // function onVerifyCompleted()
26 | onVerifyCompleted: {
27 | verifyCompleted = true;
28 | }
29 |
30 | // function onVerifyErrored()
31 | onVerifyErrored: {
32 | verifyErrored = true;
33 | }
34 | }
35 |
36 | ColumnLayout {
37 | width: parent.width
38 |
39 | Item {
40 | width: 200
41 | height: width
42 | Layout.alignment: Qt.AlignHCenter
43 | Layout.topMargin: 75
44 |
45 | CircularProgressBar {
46 | lineWidth: 6
47 | value: verifyCompleted || verifyErrored ? 1 : 0
48 | size: parent.width
49 | animationDuration: 200
50 | secondaryColor: Material.color(Material.Grey, Material.Shade300)
51 | primaryColor: getColor()
52 |
53 | function getColor() {
54 | if (verifyCompleted) {
55 | return Material.color(Material.Green)
56 | } else if (verifyErrored) {
57 | return Material.color(Material.Red, Material.Shade300)
58 | } else {
59 | return Material.color(Material.Blue)
60 | }
61 | }
62 | }
63 |
64 | Image {
65 | width: 100
66 | height: 100
67 | source: "qrc:/fingerprint.svg"
68 | smooth: true
69 | anchors.centerIn: parent
70 |
71 | ColorOverlay {
72 | anchors.fill: parent
73 | source: parent
74 | color: getColor()
75 |
76 | function getColor() {
77 | if (verifyCompleted) {
78 | return Material.color(Material.Green)
79 | } else if (verifyErrored) {
80 | return Material.color(Material.Red, Material.Shade300)
81 | } else {
82 | return Material.color(Material.Grey, Material.Shade600)
83 | }
84 | }
85 | }
86 | }
87 | }
88 |
89 | Label {
90 | text: getText()
91 | font.pixelSize: 30
92 | Layout.alignment: Qt.AlignHCenter
93 | Layout.topMargin: 32
94 | color: getColor()
95 |
96 | function getText() {
97 | if (verifyStarted && !verifyCompleted && !verifyErrored) {
98 | return "Verifying";
99 | } else if (verifyStarted && verifyErrored) {
100 | return "No Match";
101 | } else if (verifyStarted && verifyCompleted) {
102 | return "Matched";
103 | } else {
104 | return "";
105 | }
106 | }
107 |
108 | function getColor() {
109 | if (verifyCompleted) {
110 | return Material.color(Material.Green);
111 | } else if (verifyErrored) {
112 | return Material.color(Material.Red, Material.Shade300);
113 | } else {
114 | return Material.color(Material.Blue, Material.Shade600);
115 | }
116 | }
117 | }
118 |
119 | Label {
120 | visible: verifyStarted
121 | text: AppState.verifyStatusString
122 | Layout.alignment: Qt.AlignHCenter
123 | Layout.topMargin: 128
124 | font.pixelSize: 15
125 | color: Material.color(Material.Grey, Material.Shade500)
126 | }
127 |
128 | Button {
129 | visible: !verifyStarted
130 | Layout.preferredWidth: 128
131 | Layout.preferredHeight: 45
132 | text: "START"
133 | font.pixelSize: 12
134 | font.bold: true
135 | hoverEnabled: true
136 | Layout.alignment: Qt.AlignHCenter
137 | Layout.topMargin: 185
138 |
139 | Material.elevation: 0
140 | Material.background: Material.Blue
141 |
142 | onClicked: {
143 | FingerboardCppInterface.verifyFp();
144 | }
145 |
146 | PointingHandOverlay {
147 | anchors.fill: parent
148 | }
149 | }
150 | }
151 |
152 | Button {
153 | flat: true
154 | icon.source: "qrc:/back.svg"
155 | icon.color: Material.color(Material.Grey, Material.Shade500)
156 | anchors {
157 | left: parent.left
158 | leftMargin: 16
159 | top: parent.top
160 | topMargin: 16
161 | }
162 | hoverEnabled: true
163 |
164 | onClicked: {
165 | appstack.pop();
166 | }
167 |
168 | PointingHandOverlay {
169 | anchors.fill: parent
170 | }
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/src/utils/appstate.h:
--------------------------------------------------------------------------------
1 | #ifndef UTILS_APPSTATE_H
2 | #define UTILS_APPSTATE_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | class AppState : public QObject {
10 | Q_OBJECT
11 |
12 | Q_PROPERTY(
13 | EnrollStatus enrollStatus READ getEnrollStatus NOTIFY enrollStatusChanged)
14 | Q_PROPERTY(QString enrollStatusString READ getEnrollStatusString NOTIFY
15 | enrollStatusChanged)
16 |
17 | Q_PROPERTY(
18 | VerifyStatus verifyStatus READ getVerifyStatus NOTIFY verifyStatusChanged)
19 | Q_PROPERTY(QString verifyStatusString READ getVerifyStatusString NOTIFY
20 | verifyStatusChanged)
21 |
22 | public:
23 | enum ErrorStatus {
24 | ERROR_NO_DEVICE,
25 |
26 | ERROR_PERMISSION_DENIED,
27 | ERROR_NO_ENROLLED_PRINTS,
28 | ERROR_ALREADY_IN_USE,
29 | ERROR_INTERNAL,
30 | ERROR_CLAIM_DEVICE,
31 | ERROR_NO_ACTION_IN_PROGRESS,
32 | ERROR_INVALID_FINGERNAME,
33 | };
34 | Q_ENUM(ErrorStatus);
35 |
36 | enum EnrollStatus {
37 | ENROLL_EMPTY,
38 |
39 | ENROLL_START,
40 | ENROLL_COMPLETED,
41 | ENROLL_FAILED,
42 | ENROLL_STAGE_PASSED,
43 | ENROLL_RETRY_SCAN,
44 | ENROLL_SWIPE_TOO_SHORT,
45 | ENROLL_FINGER_NOT_CENTERED,
46 | ENROLL_REMOVE_AND_RETRY,
47 | ENROLL_DATA_FULL,
48 | ENROLL_DISCONNECTED,
49 | ENROLL_UNKNOWN_ERROR
50 | };
51 | Q_ENUM(EnrollStatus)
52 |
53 | enum VerifyStatus {
54 | VERIFY_EMPTY,
55 |
56 | VERIFY_START,
57 | VERIFY_NO_MATCH,
58 | VERIFY_MATCH,
59 | VERIFY_RETRY_SCAN,
60 | VERIFY_SWIPE_TOO_SHORT,
61 | VERIFY_FINGER_NOT_CENTERED,
62 | VERIFY_REMOVE_AND_RETRY,
63 | VERIFY_DISCONNECTED,
64 | VERIFY_UNKNOWN_ERROR
65 | };
66 | Q_ENUM(VerifyStatus)
67 |
68 | AppState(QObject *parent = nullptr);
69 |
70 | ErrorStatus errorStatusFromRawString(QString rawErrorString);
71 | void raiseError(QString rawError);
72 | void raiseError(AppState::ErrorStatus errorStatus);
73 |
74 | EnrollStatus getEnrollStatus();
75 | QString getEnrollStatusString();
76 | EnrollStatus enrollStatusFromRawString(QString rawStatus);
77 | void setEnrollStatus(EnrollStatus status);
78 |
79 | VerifyStatus getVerifyStatus();
80 | QString getVerifyStatusString();
81 | VerifyStatus verifyStatusFromRawString(QString rawStatus);
82 | void setVerifyStatus(VerifyStatus status);
83 |
84 | void resetApp();
85 |
86 | public slots:
87 | QString errorStatusString(AppState::ErrorStatus status);
88 |
89 | signals:
90 | void listingStarted();
91 | void listingCompleted();
92 |
93 | void enrollStarted();
94 | void enrollStatusChanged(EnrollStatus status);
95 | void enrollCompleted();
96 | void enrollErrored();
97 |
98 | void verifyStarted();
99 | void verifyStatusChanged(VerifyStatus status);
100 | void verifyCompleted();
101 | void verifyErrored();
102 |
103 | void deleteStarted();
104 | void deleteCompleted();
105 |
106 | void error(ErrorStatus errorStatus, QString errorString);
107 |
108 | void reset();
109 |
110 | private:
111 | EnrollStatus _enrollStatus = EnrollStatus::ENROLL_EMPTY;
112 | VerifyStatus _verifyStatus = VerifyStatus::VERIFY_EMPTY;
113 |
114 | QMap rawErrorMap = {
115 | {"net.reactivated.Fprint.Error.PermissionDenied",
116 | ErrorStatus::ERROR_PERMISSION_DENIED},
117 | {"net.reactivated.Fprint.Error.NoEnrolledPrints",
118 | ErrorStatus::ERROR_NO_ENROLLED_PRINTS},
119 | {"net.reactivated.Fprint.Error.AlreadyInUse",
120 | ErrorStatus::ERROR_ALREADY_IN_USE},
121 | {"net.reactivated.Fprint.Error.Internal", ErrorStatus::ERROR_INTERNAL},
122 | {"net.reactivated.Fprint.Error.ClaimDevice",
123 | ErrorStatus::ERROR_CLAIM_DEVICE},
124 | {"net.reactivated.Fprint.Error.NoActionInProgress",
125 | ErrorStatus::ERROR_NO_ACTION_IN_PROGRESS},
126 | {"net.reactivated.Fprint.Error.InvalidFingername",
127 | ErrorStatus::ERROR_INVALID_FINGERNAME}};
128 |
129 | QMap rawEnrollStatusMap = {
130 | {"enroll-completed", AppState::EnrollStatus::ENROLL_COMPLETED},
131 | {"enroll-failed", AppState::EnrollStatus::ENROLL_FAILED},
132 | {"enroll-stage-passed", AppState::EnrollStatus::ENROLL_STAGE_PASSED},
133 | {"enroll-retry-scan", AppState::EnrollStatus::ENROLL_RETRY_SCAN},
134 | {"enroll-swipe-too-short",
135 | AppState::EnrollStatus::ENROLL_SWIPE_TOO_SHORT},
136 | {"enroll-finger-not-centered",
137 | AppState::EnrollStatus::ENROLL_FINGER_NOT_CENTERED},
138 | {"enroll-remove-and-retry",
139 | AppState::EnrollStatus::ENROLL_REMOVE_AND_RETRY},
140 | {"enroll-data-full", AppState::EnrollStatus::ENROLL_DATA_FULL},
141 | {"enroll-disconnected", AppState::EnrollStatus::ENROLL_DISCONNECTED},
142 | {"enroll-unknown-error", AppState::EnrollStatus::ENROLL_UNKNOWN_ERROR}};
143 |
144 | QMap rawVerifyStatusMap = {
145 | {"verify-no-match", AppState::VerifyStatus::VERIFY_NO_MATCH},
146 | {"verify-match", AppState::VerifyStatus::VERIFY_MATCH},
147 | {"verify-retry-scan", AppState::VerifyStatus::VERIFY_RETRY_SCAN},
148 | {"verify-swipe-too-short",
149 | AppState::VerifyStatus::VERIFY_SWIPE_TOO_SHORT},
150 | {"verify-finger-not-centered",
151 | AppState::VerifyStatus::VERIFY_FINGER_NOT_CENTERED},
152 | {"verify-remove-and-retry",
153 | AppState::VerifyStatus::VERIFY_REMOVE_AND_RETRY},
154 | {"verify-disconnected", AppState::VerifyStatus::VERIFY_DISCONNECTED},
155 | {"verify-unknown-error", AppState::VerifyStatus::VERIFY_UNKNOWN_ERROR}};
156 | };
157 |
158 | #endif // UTILS_APPSTATE_H
159 |
--------------------------------------------------------------------------------
/src/qml/EnrollView.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.12
2 | import QtQuick.Controls 2.12
3 | import QtQuick.Layouts 1.12
4 | import QtQuick.Controls.Material 2.12
5 | import QtGraphicalEffects 1.0
6 |
7 | import Fingerboard 1.0
8 |
9 | Rectangle {
10 | property int stageCounter: 0
11 | property bool enrollStarted: false
12 | property bool enrollCompleted: false
13 | property bool enrollErrored: false
14 |
15 | width: 600
16 | height: 700
17 |
18 | Connections {
19 | target: AppState
20 |
21 | // function onEnrollStarted()
22 | onEnrollStarted: {
23 | enrollStarted = true;
24 | }
25 |
26 | // function onEnrollStatusChanged(status)
27 | onEnrollStatusChanged: {
28 | switch (status) {
29 | case AppState.ENROLL_STAGE_PASSED:
30 | stageCounter++;
31 | break;
32 | }
33 | }
34 |
35 | // function onEnrollCompleted()
36 | onEnrollCompleted: {
37 | enrollCompleted = true;
38 | FingerboardCppInterface.listFp();
39 | }
40 | }
41 |
42 | ColumnLayout {
43 | width: parent.width
44 |
45 | Item {
46 | width: 200
47 | height: width
48 | Layout.alignment: Qt.AlignHCenter
49 | Layout.topMargin: 75
50 |
51 | CircularProgressBar {
52 | lineWidth: 6
53 | value: enrollCompleted ? 1 : stageCounter/FingerboardCppInterface.numEnrollStages
54 | size: parent.width
55 | animationDuration: 200
56 | secondaryColor: Material.color(Material.Grey, Material.Shade300)
57 | primaryColor: getColor()
58 |
59 | function getColor() {
60 | if (enrollCompleted) {
61 | return Material.color(Material.Green)
62 | } else if (enrollErrored) {
63 | return Material.color(Material.Red, Material.Shade300)
64 | } else {
65 | return Material.color(Material.Blue)
66 | }
67 | }
68 | }
69 |
70 | Image {
71 | width: 128
72 | height: 128
73 | source: "qrc:/fingerprint.svg"
74 | smooth: true
75 | anchors.centerIn: parent
76 |
77 | ColorOverlay {
78 | anchors.fill: parent
79 | source: parent
80 | color: getColor()
81 |
82 | function getColor() {
83 | if (enrollCompleted) {
84 | return Material.color(Material.Green)
85 | } else if (enrollErrored) {
86 | return Material.color(Material.Red, Material.Shade300)
87 | } else {
88 | return Material.color(Material.Grey, Material.Shade600)
89 | }
90 | }
91 | }
92 | }
93 | }
94 |
95 | Label {
96 | text: Finger.name(selectedEnrollingFinger)
97 | font.pixelSize: 12
98 | font.bold: true
99 | Layout.alignment: Qt.AlignHCenter
100 | Layout.topMargin: 16
101 | color: Material.color(Material.Grey)
102 | }
103 |
104 | Label {
105 | visible: enrollStarted && !enrollCompleted
106 | text: `Stage ${stageCounter+1}\/${FingerboardCppInterface.numEnrollStages}`
107 | font.pixelSize: 30
108 | Layout.alignment: Qt.AlignHCenter
109 | Layout.topMargin: 32
110 | color: Material.color(Material.Blue, Material.Shade600)
111 | }
112 |
113 | Label {
114 | visible: enrollCompleted
115 | text: `Completed`
116 | font.pixelSize: 30
117 | Layout.alignment: Qt.AlignHCenter
118 | Layout.topMargin: 32
119 | color: Material.color(Material.Green)
120 | }
121 |
122 | Label {
123 | visible: enrollStarted
124 | text: AppState.enrollStatusString
125 | Layout.alignment: Qt.AlignHCenter
126 | Layout.topMargin: 128
127 | font.pixelSize: 15
128 | color: Material.color(Material.Grey, Material.Shade500)
129 | }
130 |
131 | Button {
132 | visible: !enrollStarted
133 | Layout.preferredWidth: 128
134 | Layout.preferredHeight: 45
135 | text: "START"
136 | font.pixelSize: 12
137 | font.bold: true
138 | hoverEnabled: true
139 | Layout.alignment: Qt.AlignHCenter
140 | Layout.topMargin: 185
141 |
142 | Material.elevation: 0
143 | Material.background: Material.Blue
144 |
145 | onClicked: {
146 | FingerboardCppInterface.enrollFp(selectedEnrollingFinger);
147 | }
148 |
149 | PointingHandOverlay {
150 | anchors.fill: parent
151 | }
152 | }
153 | }
154 |
155 | Button {
156 | flat: true
157 | icon.source: "qrc:/back.svg"
158 | icon.color: Material.color(Material.Grey, Material.Shade500)
159 | anchors {
160 | left: parent.left
161 | leftMargin: 16
162 | top: parent.top
163 | topMargin: 16
164 | }
165 | hoverEnabled: true
166 |
167 | onClicked: {
168 | appstack.pop();
169 | }
170 |
171 | PointingHandOverlay {
172 | anchors.fill: parent
173 | }
174 | }
175 | }
176 |
--------------------------------------------------------------------------------
/src/qml/ListingView.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.12
2 | import QtQuick.Controls 2.12
3 | import QtQuick.Layouts 1.12
4 | import QtQuick.Controls.Material 2.12
5 | import QtGraphicalEffects 1.12
6 |
7 | import Fingerboard 1.0
8 |
9 | Rectangle {
10 | property int ditchGap: 2
11 |
12 | width: 600
13 |
14 | Connections {
15 | target: FingerboardCppInterface
16 |
17 | // function onEnrolledFingerprintsList(fingerprints)
18 | onEnrolledFingerprintsList: {
19 | var enrolledFingersMap = {};
20 |
21 | for (var enrolledFinger in fingerprints) {
22 | enrolledFingersMap[fingerprints[enrolledFinger]] = true;
23 | }
24 |
25 | for (var i=0; iVERIFY FINGERPRINT"
195 | font.pixelSize: 12
196 | font.bold: true
197 | bottomInset: 0
198 | topInset: 0
199 | hoverEnabled: true
200 |
201 | Material.elevation: 0
202 | Material.background: Material.Blue
203 |
204 | onClicked: {
205 | appstack.push(verifyView);
206 | }
207 |
208 | PointingHandOverlay {
209 | anchors.fill: parent
210 | }
211 | }
212 | }
213 | }
214 |
--------------------------------------------------------------------------------
/src/qml/main.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.12
2 | import QtQuick.Controls 1.4 as Controls1
3 | import QtQuick.Controls 2.12
4 | import QtQuick.Layouts 1.12
5 | import QtQuick.Controls.Material 2.12
6 | import QtGraphicalEffects 1.0
7 |
8 | import Fingerboard 1.0
9 |
10 | ApplicationWindow {
11 | property bool showLogs: false
12 | property bool noDevice: false
13 | property int selectedEnrollingFinger: -1
14 |
15 | id: appWindow
16 | minimumWidth: 1000
17 | minimumHeight: 800
18 | title: "Fingerboard"
19 | visible: true
20 |
21 | Material.theme: Material.Light
22 | Material.accent: Material.Blue
23 |
24 | Material.background: "#f5f5f5"
25 |
26 | Component.onCompleted: {
27 | FingerboardCppInterface.init();
28 | }
29 |
30 | Connections {
31 | target: AppState
32 |
33 | // function onError(errorStatus, errorString)
34 | onError: {
35 | if (errorStatus === AppState.ERROR_NO_DEVICE) {
36 | noDevice = true;
37 | }
38 |
39 | var component = Qt.createComponent("ErrorDialog.qml");
40 | component.createObject(appWindow, { errorString: errorString });
41 | }
42 | }
43 |
44 | Menu {
45 | id: appMenu
46 |
47 | font.pixelSize: 12
48 |
49 | MenuItem {
50 | text: "Show Logs"
51 | checkable: true
52 | checked: showLogs
53 |
54 | Shortcut {
55 | sequence: "ctrl+l"
56 | onActivated: showLogs = !showLogs
57 | }
58 |
59 | onToggled: showLogs = !showLogs
60 | }
61 |
62 | MenuItem {
63 | text: "About"
64 | onTriggered: aboutDialog.open();
65 | }
66 |
67 | MenuItem {
68 | text: "Exit"
69 | onTriggered: Qt.quit();
70 | }
71 | }
72 |
73 | RoundButton {
74 | id: menuBtn
75 |
76 | width: 48
77 | height: 48
78 | flat: true
79 | icon.source: "qrc:/menu.svg"
80 | icon.color: Material.color(Material.Grey, Material.Shade700)
81 | icon.width: 18
82 | icon.height: 18
83 | hoverEnabled: true
84 |
85 | onClicked: {
86 | appMenu.popup(menuBtn.x + 5, menuBtn.y + menuBtn.height);
87 | }
88 |
89 | PointingHandOverlay {
90 | anchors.fill: parent
91 | }
92 | }
93 |
94 | Image {
95 | width: 24
96 | height: 24
97 | source: "qrc:/info.svg"
98 | anchors {
99 | right: parent.right
100 | top: menuBtn.top
101 | margins: 12
102 | }
103 |
104 | ColorOverlay {
105 | anchors.fill: parent
106 | source: parent
107 | color: Material.color(Material.Grey, Material.Shade700)
108 | }
109 |
110 | ToolTip.text: getDeviceInfoText()
111 |
112 | MouseArea {
113 | anchors.fill: parent
114 | hoverEnabled: true
115 |
116 | onContainsMouseChanged: {
117 | parent.ToolTip.visible = containsMouse;
118 | }
119 | }
120 |
121 | function getDeviceInfoText() {
122 | if (noDevice) {
123 | return "No fingerprint reader detected"
124 | } else {
125 | return `Device: ${FingerboardCppInterface.deviceName}
`+
126 | `Scan Type: ${FingerboardCppInterface.scanType}
`+
127 | `Enroll Stages: ${FingerboardCppInterface.numEnrollStages}`
128 | }
129 | }
130 | }
131 |
132 | Controls1.SplitView {
133 | anchors.fill: parent
134 | orientation: Qt.Vertical
135 |
136 | StackView {
137 | property int animationDuration: 300
138 | property int easingType: Easing.InOutExpo
139 |
140 | id: appstack
141 | Layout.fillHeight: true
142 | Layout.fillWidth: true
143 | Layout.topMargin: 32
144 | initialItem: initialView
145 |
146 | pushEnter: Transition {
147 | PropertyAnimation {
148 | property: "x"
149 | easing.type: appstack.easingType
150 | from: appstack.width
151 | to: 0
152 | duration: appstack.animationDuration
153 | }
154 | }
155 | pushExit: Transition {
156 | PropertyAnimation {
157 | property: "x"
158 | easing.type: appstack.easingType
159 | from: 0
160 | to: -appstack.width
161 | duration: appstack.animationDuration
162 | }
163 | }
164 | popEnter: Transition {
165 | PropertyAnimation {
166 | property: "x"
167 | easing.type: appstack.easingType
168 | from: -appstack.width
169 | to: 0
170 | duration: appstack.animationDuration
171 | }
172 | }
173 | popExit: Transition {
174 | PropertyAnimation {
175 | property: "x"
176 | easing.type: appstack.easingType
177 | from: 0
178 | to: appstack.width
179 | duration: appstack.animationDuration
180 | }
181 | }
182 | }
183 |
184 | LogPanel {
185 | visible: showLogs
186 |
187 | Layout.fillWidth: true
188 | height: 300
189 | }
190 | }
191 |
192 | Component {
193 | id: initialView
194 |
195 | Item {
196 | ListingView {
197 | anchors.horizontalCenter: parent.horizontalCenter
198 | }
199 |
200 | RoundButton {
201 | anchors {
202 | right: parent.right
203 | bottom: parent.bottom
204 | margins: 16
205 | }
206 | hoverEnabled: true
207 | padding: 18
208 |
209 | Material.background: Material.Red
210 | icon.source: "qrc:/delete.svg"
211 | icon.color: "white"
212 |
213 | z: 10
214 |
215 | onClicked: {
216 | deleteDialog.visible = true;
217 | }
218 |
219 | PointingHandOverlay {
220 | anchors.fill: parent
221 | }
222 | }
223 | }
224 | }
225 |
226 | Component {
227 | id: enrollView
228 |
229 | Item {
230 | EnrollView {
231 | anchors.horizontalCenter: parent.horizontalCenter
232 | }
233 | }
234 | }
235 |
236 | Component {
237 | id: verifyView
238 |
239 | Item {
240 | VerifyView {
241 | anchors.horizontalCenter: parent.horizontalCenter
242 | }
243 | }
244 | }
245 |
246 | DeleteDialog {
247 | id: deleteDialog
248 | }
249 | AboutDialog {
250 | id: aboutDialog
251 | }
252 | }
253 |
254 |
--------------------------------------------------------------------------------
/src/qml/CircularProgressBar.qml:
--------------------------------------------------------------------------------
1 | // Based on : https://github.com/rafzby/circular-progressbar/blob/master/CircularProgressBar.qml
2 |
3 | /*
4 |
5 | GNU LESSER GENERAL PUBLIC LICENSE
6 | Version 3, 29 June 2007
7 |
8 | Copyright (C) 2007 Free Software Foundation, Inc.
9 | Everyone is permitted to copy and distribute verbatim copies
10 | of this license document, but changing it is not allowed.
11 |
12 |
13 | This version of the GNU Lesser General Public License incorporates
14 | the terms and conditions of version 3 of the GNU General Public
15 | License, supplemented by the additional permissions listed below.
16 |
17 | 0. Additional Definitions.
18 |
19 | As used herein, "this License" refers to version 3 of the GNU Lesser
20 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
21 | General Public License.
22 |
23 | "The Library" refers to a covered work governed by this License,
24 | other than an Application or a Combined Work as defined below.
25 |
26 | An "Application" is any work that makes use of an interface provided
27 | by the Library, but which is not otherwise based on the Library.
28 | Defining a subclass of a class defined by the Library is deemed a mode
29 | of using an interface provided by the Library.
30 |
31 | A "Combined Work" is a work produced by combining or linking an
32 | Application with the Library. The particular version of the Library
33 | with which the Combined Work was made is also called the "Linked
34 | Version".
35 |
36 | The "Minimal Corresponding Source" for a Combined Work means the
37 | Corresponding Source for the Combined Work, excluding any source code
38 | for portions of the Combined Work that, considered in isolation, are
39 | based on the Application, and not on the Linked Version.
40 |
41 | The "Corresponding Application Code" for a Combined Work means the
42 | object code and/or source code for the Application, including any data
43 | and utility programs needed for reproducing the Combined Work from the
44 | Application, but excluding the System Libraries of the Combined Work.
45 |
46 | 1. Exception to Section 3 of the GNU GPL.
47 |
48 | You may convey a covered work under sections 3 and 4 of this License
49 | without being bound by section 3 of the GNU GPL.
50 |
51 | 2. Conveying Modified Versions.
52 |
53 | If you modify a copy of the Library, and, in your modifications, a
54 | facility refers to a function or data to be supplied by an Application
55 | that uses the facility (other than as an argument passed when the
56 | facility is invoked), then you may convey a copy of the modified
57 | version:
58 |
59 | a) under this License, provided that you make a good faith effort to
60 | ensure that, in the event an Application does not supply the
61 | function or data, the facility still operates, and performs
62 | whatever part of its purpose remains meaningful, or
63 |
64 | b) under the GNU GPL, with none of the additional permissions of
65 | this License applicable to that copy.
66 |
67 | 3. Object Code Incorporating Material from Library Header Files.
68 |
69 | The object code form of an Application may incorporate material from
70 | a header file that is part of the Library. You may convey such object
71 | code under terms of your choice, provided that, if the incorporated
72 | material is not limited to numerical parameters, data structure
73 | layouts and accessors, or small macros, inline functions and templates
74 | (ten or fewer lines in length), you do both of the following:
75 |
76 | a) Give prominent notice with each copy of the object code that the
77 | Library is used in it and that the Library and its use are
78 | covered by this License.
79 |
80 | b) Accompany the object code with a copy of the GNU GPL and this license
81 | document.
82 |
83 | 4. Combined Works.
84 |
85 | You may convey a Combined Work under terms of your choice that,
86 | taken together, effectively do not restrict modification of the
87 | portions of the Library contained in the Combined Work and reverse
88 | engineering for debugging such modifications, if you also do each of
89 | the following:
90 |
91 | a) Give prominent notice with each copy of the Combined Work that
92 | the Library is used in it and that the Library and its use are
93 | covered by this License.
94 |
95 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
96 | document.
97 |
98 | c) For a Combined Work that displays copyright notices during
99 | execution, include the copyright notice for the Library among
100 | these notices, as well as a reference directing the user to the
101 | copies of the GNU GPL and this license document.
102 |
103 | d) Do one of the following:
104 |
105 | 0) Convey the Minimal Corresponding Source under the terms of this
106 | License, and the Corresponding Application Code in a form
107 | suitable for, and under terms that permit, the user to
108 | recombine or relink the Application with a modified version of
109 | the Linked Version to produce a modified Combined Work, in the
110 | manner specified by section 6 of the GNU GPL for conveying
111 | Corresponding Source.
112 |
113 | 1) Use a suitable shared library mechanism for linking with the
114 | Library. A suitable mechanism is one that (a) uses at run time
115 | a copy of the Library already present on the user's computer
116 | system, and (b) will operate properly with a modified version
117 | of the Library that is interface-compatible with the Linked
118 | Version.
119 |
120 | e) Provide Installation Information, but only if you would otherwise
121 | be required to provide such information under section 6 of the
122 | GNU GPL, and only to the extent that such information is
123 | necessary to install and execute a modified version of the
124 | Combined Work produced by recombining or relinking the
125 | Application with a modified version of the Linked Version. (If
126 | you use option 4d0, the Installation Information must accompany
127 | the Minimal Corresponding Source and Corresponding Application
128 | Code. If you use option 4d1, you must provide the Installation
129 | Information in the manner specified by section 6 of the GNU GPL
130 | for conveying Corresponding Source.)
131 |
132 | 5. Combined Libraries.
133 |
134 | You may place library facilities that are a work based on the
135 | Library side by side in a single library together with other library
136 | facilities that are not Applications and are not covered by this
137 | License, and convey such a combined library under terms of your
138 | choice, if you do both of the following:
139 |
140 | a) Accompany the combined library with a copy of the same work based
141 | on the Library, uncombined with any other library facilities,
142 | conveyed under the terms of this License.
143 |
144 | b) Give prominent notice with the combined library that part of it
145 | is a work based on the Library, and explaining where to find the
146 | accompanying uncombined form of the same work.
147 |
148 | 6. Revised Versions of the GNU Lesser General Public License.
149 |
150 | The Free Software Foundation may publish revised and/or new versions
151 | of the GNU Lesser General Public License from time to time. Such new
152 | versions will be similar in spirit to the present version, but may
153 | differ in detail to address new problems or concerns.
154 |
155 | Each version is given a distinguishing version number. If the
156 | Library as you received it specifies that a certain numbered version
157 | of the GNU Lesser General Public License "or any later version"
158 | applies to it, you have the option of following the terms and
159 | conditions either of that published version or of any later version
160 | published by the Free Software Foundation. If the Library as you
161 | received it does not specify a version number of the GNU Lesser
162 | General Public License, you may choose any version of the GNU Lesser
163 | General Public License ever published by the Free Software Foundation.
164 |
165 | If the Library as you received it specifies that a proxy can decide
166 | whether future versions of the GNU Lesser General Public License shall
167 | apply, that proxy's public statement of acceptance of any version is
168 | permanent authorization for you to choose that version for the
169 | Library.
170 |
171 | */
172 |
173 | import QtQuick 2.9
174 |
175 | Item {
176 | id: root
177 |
178 | property int size: 150
179 | property int lineWidth: 5
180 | property real value: 0
181 |
182 | property color primaryColor: "#29b6f6"
183 | property color secondaryColor: "#e0e0e0"
184 |
185 | property int animationDuration: 1000
186 |
187 | width: size
188 | height: size
189 |
190 | onValueChanged: {
191 | canvas.degree = value * 360;
192 | }
193 |
194 | Canvas {
195 | id: canvas
196 |
197 | property real degree: 0
198 |
199 | anchors.fill: parent
200 | antialiasing: true
201 |
202 | onDegreeChanged: {
203 | requestPaint();
204 | }
205 |
206 | onPaint: {
207 | var ctx = getContext("2d");
208 |
209 | var x = root.width/2;
210 | var y = root.height/2;
211 |
212 | var radius = root.size/2 - root.lineWidth
213 | var startAngle = (Math.PI/180) * 270;
214 | var fullAngle = (Math.PI/180) * (270 + 360);
215 | var progressAngle = (Math.PI/180) * (270 + degree);
216 |
217 | ctx.reset()
218 |
219 | ctx.lineCap = 'round';
220 | ctx.lineWidth = root.lineWidth;
221 |
222 | ctx.beginPath();
223 | ctx.arc(x, y, radius, startAngle, fullAngle);
224 | ctx.strokeStyle = root.secondaryColor;
225 | ctx.stroke();
226 |
227 | ctx.beginPath();
228 | ctx.arc(x, y, radius, startAngle, progressAngle);
229 | ctx.strokeStyle = root.primaryColor;
230 | ctx.stroke();
231 | }
232 |
233 | Behavior on degree {
234 | NumberAnimation {
235 | duration: root.animationDuration
236 | easing: Easing.OutCubic
237 | }
238 | }
239 | }
240 | }
241 |
--------------------------------------------------------------------------------
/src/interfaces/fingerboard_cpp_interface.cpp:
--------------------------------------------------------------------------------
1 | #include "fingerboard_cpp_interface.h"
2 |
3 | #include
4 | #include
5 |
6 | FingerboardCppInterface::FingerboardCppInterface(Finger *fingerObj,
7 | Logger *logger,
8 | AppState *appState,
9 | QObject *parent)
10 | : QObject(parent) {
11 | this->fingerObj = fingerObj;
12 | this->appState = appState;
13 | this->logger = logger;
14 |
15 | connect(logger, &Logger::writeLog, [=](Logger::Level logLevel, QString msg) {
16 | emit log(logLevel, msg);
17 | });
18 | }
19 |
20 | QString FingerboardCppInterface::getDeviceName() { return _deviceName; }
21 |
22 | QString FingerboardCppInterface::getScanType() { return _scanType; }
23 |
24 | int FingerboardCppInterface::getNumEnrollStages() { return _numEnrollStages; }
25 |
26 | void FingerboardCppInterface::init() {
27 | logger->log(Logger::INFO, QString("Log Location : %1").arg(logger->path()));
28 | logger->log(Logger::INFO, "Initializing Fingerboard");
29 |
30 | QDBusConnection bus = QDBusConnection::systemBus();
31 | fprintdInterfaceManager = new net::reactivated::Fprint::Manager(
32 | QString(FPRINTD_SERVICE), QString("/net/reactivated/Fprint/Manager"), bus,
33 | this);
34 |
35 | QDBusPendingReply defaultDevicePathReply =
36 | fprintdInterfaceManager->GetDefaultDevice();
37 | defaultDevicePathReply.waitForFinished();
38 | defaultDevicePath = defaultDevicePathReply.value().path();
39 |
40 | if (defaultDevicePath.size() > 0) {
41 | logger->log(
42 | Logger::DEBUG,
43 | QString("Default Device Object Path : %1").arg(defaultDevicePath));
44 |
45 | fprintdInterfaceDevice = new net::reactivated::Fprint::Device(
46 | QString(FPRINTD_SERVICE), defaultDevicePath, bus, this);
47 | fprintdDevicePropertiesInterface = new QDBusInterface(
48 | QString(FPRINTD_SERVICE), defaultDevicePath,
49 | QString("org.freedesktop.DBus.Properties"), bus, this);
50 |
51 | connect(fprintdInterfaceDevice, SIGNAL(EnrollStatus(QString, bool)), this,
52 | SLOT(enrollStatusSlot(QString, bool)));
53 | connect(fprintdInterfaceDevice, SIGNAL(VerifyStatus(QString, bool)), this,
54 | SLOT(verifyStatusSlot(QString, bool)));
55 |
56 | deviceInfo();
57 | listFp();
58 | } else {
59 | logger->log(Logger::ERROR, appState->errorStatusString(
60 | AppState::ErrorStatus::ERROR_NO_DEVICE));
61 | appState->raiseError(AppState::ErrorStatus::ERROR_NO_DEVICE);
62 | }
63 | }
64 |
65 | void FingerboardCppInterface::deviceInfo() {
66 | if (claimFpDevice()) {
67 | _deviceName = fprintdDevicePropertiesInterface->call("Get", "", "name")
68 | .arguments()
69 | .at(0)
70 | .value()
71 | .variant()
72 | .toString();
73 | _scanType = fprintdDevicePropertiesInterface->call("Get", "", "scan-type")
74 | .arguments()
75 | .at(0)
76 | .value()
77 | .variant()
78 | .toString();
79 | _numEnrollStages =
80 | fprintdDevicePropertiesInterface->call("Get", "", "num-enroll-stages")
81 | .arguments()
82 | .at(0)
83 | .value()
84 | .variant()
85 | .toInt();
86 |
87 | emit deviceNameChanged(_deviceName);
88 | emit scanTypeChanged(_scanType);
89 | emit numEnrollStagesChanged(_numEnrollStages);
90 |
91 | logger->log(Logger::INFO, QString("-----------"));
92 | logger->log(Logger::INFO, QString("Device Info"));
93 | logger->log(Logger::INFO, QString("-----------"));
94 | logger->log(Logger::INFO,
95 | QString(" Name : %1").arg(_deviceName));
96 | logger->log(Logger::INFO, QString(" Scan Type : %1").arg(_scanType));
97 | logger->log(Logger::INFO,
98 | QString(" Enroll Stages : %1").arg(_numEnrollStages));
99 |
100 | releaseFpDevice();
101 | }
102 | }
103 |
104 | void FingerboardCppInterface::listFp() {
105 | if (claimFpDevice()) {
106 | logger->log(Logger::VERBOSE, "Start Listing FP");
107 | logger->log(Logger::INFO, "Listing Fingerprints");
108 |
109 | emit appState->listingStarted();
110 |
111 | QDBusPendingReply listEnrolledFingersReply =
112 | fprintdInterfaceDevice->ListEnrolledFingers(username);
113 | listEnrolledFingersReply.waitForFinished();
114 |
115 | if (listEnrolledFingersReply.error().isValid()) {
116 | logger->log(Logger::ERROR,
117 | QString("%1 : %2")
118 | .arg(listEnrolledFingersReply.error().name())
119 | .arg(listEnrolledFingersReply.error().message()));
120 |
121 | if (appState->errorStatusFromRawString(
122 | listEnrolledFingersReply.error().name()) ==
123 | AppState::ErrorStatus::ERROR_NO_ENROLLED_PRINTS) {
124 | emit enrolledFingerprintsList(QList());
125 | } else {
126 | appState->raiseError(listEnrolledFingersReply.error().name());
127 | }
128 | } else {
129 | QStringList rawEnrolledFingersList = listEnrolledFingersReply.value();
130 | QList enrolledFingers;
131 |
132 | logger->log(Logger::DEBUG, "ENROLLED FINGERPRINTS");
133 | for (QString finger : rawEnrolledFingersList) {
134 | logger->log(Logger::DEBUG, QString(" - %1").arg(finger));
135 | enrolledFingers.append(fingerObj->fromName(finger));
136 | }
137 |
138 | emit enrolledFingerprintsList(enrolledFingers);
139 | }
140 |
141 | logger->log(Logger::VERBOSE, "End Listing FP");
142 | releaseFpDevice();
143 |
144 | emit appState->listingCompleted();
145 | }
146 | }
147 |
148 | void FingerboardCppInterface::enrollFp(int finger) {
149 | if (claimFpDevice()) {
150 | logger->log(Logger::VERBOSE,
151 | QString("Start Enrolling FP : [%1]").arg(finger));
152 | logger->log(Logger::INFO, "Starting Enrolling Fingerprint");
153 |
154 | QDBusPendingReply enrollStartReply =
155 | fprintdInterfaceDevice->EnrollStart(fingerObj->rawFingerName(finger));
156 | enrollStartReply.waitForFinished();
157 |
158 | if (enrollStartReply.error().isValid()) {
159 | logger->log(Logger::ERROR, QString("%1 : %2")
160 | .arg(enrollStartReply.error().name())
161 | .arg(enrollStartReply.error().message()));
162 |
163 | appState->raiseError(enrollStartReply.error().name());
164 | logger->log(Logger::VERBOSE, "End Enrolling FP");
165 | releaseFpDevice();
166 | } else {
167 | logger->log(Logger::VERBOSE, "Touch/Swipe to start Enrolling");
168 | appState->setEnrollStatus(AppState::ENROLL_START);
169 |
170 | emit appState->enrollStarted();
171 | }
172 | }
173 | }
174 |
175 | void FingerboardCppInterface::verifyFp(QString finger) {
176 | if (claimFpDevice()) {
177 | logger->log(Logger::VERBOSE,
178 | QString("Start Verifying FP : [%1]").arg(finger));
179 | logger->log(Logger::INFO, "Starting Verifying Fingerprint");
180 |
181 | QDBusPendingReply verifyStartReply =
182 | fprintdInterfaceDevice->VerifyStart(finger);
183 | verifyStartReply.waitForFinished();
184 |
185 | if (verifyStartReply.error().isValid()) {
186 | logger->log(Logger::ERROR, QString("%1 : %2")
187 | .arg(verifyStartReply.error().name())
188 | .arg(verifyStartReply.error().message()));
189 |
190 | appState->raiseError(verifyStartReply.error().name());
191 | logger->log(Logger::VERBOSE, "End Verifying FP");
192 | releaseFpDevice();
193 | } else {
194 | logger->log(Logger::VERBOSE, "Touch/Swipe to continue Verifying");
195 | appState->setVerifyStatus(AppState::VERIFY_START);
196 |
197 | emit appState->verifyStarted();
198 | }
199 | }
200 | }
201 |
202 | void FingerboardCppInterface::deleteFp() {
203 | if (claimFpDevice()) {
204 | logger->log(Logger::VERBOSE, "Start Deleting FP");
205 | logger->log(Logger::INFO, "Deleting Fingerprints");
206 |
207 | emit appState->deleteStarted();
208 |
209 | logger->log(
210 | Logger::INFO,
211 | QString("Deleting all fingerprints of user [%1] for device [%2]")
212 | .arg(username)
213 | .arg(defaultDevicePath));
214 |
215 | QDBusPendingReply deleteEnrolledFingers2Reply =
216 | fprintdInterfaceDevice->DeleteEnrolledFingers2();
217 | deleteEnrolledFingers2Reply.waitForFinished();
218 |
219 | if (deleteEnrolledFingers2Reply.error().isValid()) {
220 | logger->log(Logger::ERROR,
221 | QString("%1 : %2")
222 | .arg(deleteEnrolledFingers2Reply.error().name())
223 | .arg(deleteEnrolledFingers2Reply.error().message()));
224 | appState->raiseError(deleteEnrolledFingers2Reply.error().name());
225 | }
226 |
227 | logger->log(Logger::VERBOSE, "End Deleting FP");
228 | releaseFpDevice();
229 |
230 | emit appState->deleteCompleted();
231 | }
232 | }
233 |
234 | void FingerboardCppInterface::enrollStatusSlot(QString result, bool done) {
235 | logger->log(
236 | Logger::DEBUG,
237 | QString("ENROLL STATUS : %1, ENROLL DONE : %2").arg(result).arg(done));
238 |
239 | appState->setEnrollStatus(appState->enrollStatusFromRawString(result));
240 |
241 | if (result == "enroll-completed" || result == "enroll-failed" ||
242 | result == "enroll-data-full" || result == "enroll-unknown-error" ||
243 | done) {
244 | QDBusPendingReply enrollStopReply = fprintdInterfaceDevice->EnrollStop();
245 | enrollStopReply.waitForFinished();
246 | logger->log(Logger::INFO,
247 | QString("Enroll Ended with status [%1]").arg(result));
248 | logger->log(Logger::VERBOSE, "End Enrolling FP");
249 | releaseFpDevice();
250 |
251 | if (result == "enroll-completed") {
252 | emit appState->enrollCompleted();
253 | } else {
254 | emit appState->enrollErrored();
255 | }
256 | }
257 | }
258 |
259 | void FingerboardCppInterface::verifyStatusSlot(QString result, bool done) {
260 | logger->log(
261 | Logger::DEBUG,
262 | QString("VERIFY STATUS : %1, VERIFY DONE : %2").arg(result).arg(done));
263 |
264 | appState->setVerifyStatus(appState->verifyStatusFromRawString(result));
265 |
266 | if (result == "verify-no-match" || result == "verify-match" ||
267 | result == "verify-unknown-error" || done) {
268 | QDBusPendingReply verifyStopReply = fprintdInterfaceDevice->VerifyStop();
269 | verifyStopReply.waitForFinished();
270 | logger->log(Logger::INFO,
271 | QString("Verify Ended with status [%1]").arg(result));
272 | logger->log(Logger::VERBOSE, "End Verifying FP");
273 | releaseFpDevice();
274 |
275 | if (result == "verify-match") {
276 | emit appState->verifyCompleted();
277 | } else {
278 | emit appState->verifyErrored();
279 | }
280 | }
281 | }
282 |
283 | bool FingerboardCppInterface::claimFpDevice() {
284 | logger->log(Logger::DEBUG, "Claiming Fingerprint Device");
285 |
286 | if (defaultDevicePath.size() <= 0) {
287 | logger->log(Logger::ERROR, appState->errorStatusString(
288 | AppState::ErrorStatus::ERROR_NO_DEVICE));
289 | appState->raiseError(AppState::ErrorStatus::ERROR_NO_DEVICE);
290 |
291 | return false;
292 | } else {
293 | QDBusPendingReply claimReply = fprintdInterfaceDevice->Claim(QString());
294 | claimReply.waitForFinished();
295 |
296 | if (claimReply.error().isValid()) {
297 | logger->log(Logger::ERROR, QString("%1 : %2")
298 | .arg(claimReply.error().name())
299 | .arg(claimReply.error().message()));
300 |
301 | appState->raiseError(claimReply.error().name());
302 | return false;
303 | }
304 | }
305 |
306 | return true;
307 | }
308 |
309 | void FingerboardCppInterface::releaseFpDevice() {
310 | logger->log(Logger::DEBUG, "Releasing Fingerprint Device");
311 |
312 | QDBusPendingReply releaseReply = fprintdInterfaceDevice->Release();
313 |
314 | if (releaseReply.error().isValid()) {
315 | logger->log(Logger::ERROR, QString("%1 : %2")
316 | .arg(releaseReply.error().name())
317 | .arg(releaseReply.error().message()));
318 |
319 | appState->raiseError(releaseReply.error().name());
320 | }
321 | }
322 |
--------------------------------------------------------------------------------
/src/fprintd-dbus-interface-xml/fprintddevice.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | ]>
12 |
13 |
14 |
15 |
17 |
18 |
19 |
20 | PolicyKit integration
21 |
22 |
23 | fprintd uses PolicyKit to check whether users are allowed to access fingerprint data, or the
24 | fingerprint readers itself.
25 |
26 |
27 | net.reactivated.fprint.device.verify
28 |
29 | Whether the user is allowed to verify fingers against saved fingerprints.
30 |
31 |
32 |
33 | net.reactivated.fprint.device.enroll
34 |
35 | Whether the user is allowed to enroll new fingerprints.
36 |
37 |
38 |
39 | net.reactivated.fprint.device.setusername
40 |
41 | Whether the user is allowed to query, verify, or enroll fingerprints for users other than itself.
42 |
43 |
44 |
45 |
46 |
47 |
48 | Usernames
49 |
50 |
51 | When a username argument is used for a method, a PolicyKit check is done on the
52 | net.reactivated.fprint.device.setusername PolicyKit
53 | action to see whether the user the client is running as is allowed to access data from other users.
54 |
55 |
56 | By default, only root is allowed to access fingerprint data for users other than itself. For a normal user,
57 | it is recommended that you use an empty string for the username, which will mean "the client the user is
58 | running as".
59 |
60 |
61 | See PolicyKit integration.
62 |
63 |
64 |
65 | Fingerprint names
66 |
67 |
68 | When a finger name argument is used for a method, it refers to either a single finger, or
69 | "any" finger. See the list of possible values below:
70 |
71 |
72 | left-thumb
73 |
74 | Left thumb
75 |
76 |
77 |
78 | left-index-finger
79 |
80 | Left index finger
81 |
82 |
83 |
84 | left-middle-finger
85 |
86 | Left middle finger
87 |
88 |
89 |
90 | left-ring-finger
91 |
92 | Left ring finger
93 |
94 |
95 |
96 | left-little-finger
97 |
98 | Left little finger
99 |
100 |
101 |
102 | right-thumb
103 |
104 | Right thumb
105 |
106 |
107 |
108 | right-index-finger
109 |
110 | Right index finger
111 |
112 |
113 |
114 | right-middle-finger
115 |
116 | Right middle finger
117 |
118 |
119 |
120 | right-ring-finger
121 |
122 | Right ring finger
123 |
124 |
125 |
126 | right-little-finger
127 |
128 | Right little finger
129 |
130 |
131 |
132 | any
133 |
134 | Any finger. This is only used for Device.VerifyStart
135 | (select the first finger with a fingerprint associated, or all the fingerprints available for the user when
136 | the device supports it) and Device::VerifyFingerSelected
137 | (any finger with an associated fingerprint can be used).
138 |
139 |
140 |
141 |
142 |
143 |
144 | Verify Statuses
145 |
146 |
147 |
148 | Possible values for the result passed through Device::VerifyResult are:
149 |
150 | verify-no-match
151 |
152 | The verification did not match, Device.VerifyStop should now be called.
153 |
154 |
155 |
156 | verify-match
157 |
158 | The verification succeeded, Device.VerifyStop should now be called.
159 |
160 |
161 |
162 | verify-retry-scan
163 |
164 | The user should retry scanning their finger, the verification is still ongoing.
165 |
166 |
167 |
168 | verify-swipe-too-short
169 |
170 | The user's swipe was too short. The user should retry scanning their finger, the verification is still ongoing.
171 |
172 |
173 |
174 | verify-finger-not-centered
175 |
176 | The user's finger was not centered on the reader. The user should retry scanning their finger, the verification is still ongoing.
177 |
178 |
179 |
180 | verify-remove-and-retry
181 |
182 | The user should remove their finger from the reader and retry scanning their finger, the verification is still ongoing.
183 |
184 |
185 |
186 | verify-disconnected
187 |
188 | The device was disconnected during the verification, no other actions should be taken, and you shouldn't use the device any more.
189 |
190 |
191 |
192 | verify-unknown-error
193 |
194 | An unknown error occurred (usually a driver problem), Device.VerifyStop should now be called.
195 |
196 |
197 |
198 |
199 |
200 |
201 | Enroll Statuses
202 |
203 |
204 |
205 | Possible values for the result passed through Device::EnrollResult are:
206 |
207 | enroll-completed
208 |
209 | The enrollment successfully completed, Device.EnrollStop should now be called.
210 |
211 |
212 |
213 | enroll-failed
214 |
215 | The enrollment failed, Device.EnrollStop should now be called.
216 |
217 |
218 |
219 | enroll-stage-passed
220 |
221 | One stage of the enrollment passed, the enrollment is still ongoing.
222 |
223 |
224 |
225 | enroll-retry-scan
226 |
227 | The user should retry scanning their finger, the enrollment is still ongoing.
228 |
229 |
230 |
231 | enroll-swipe-too-short
232 |
233 | The user's swipe was too short. The user should retry scanning their finger, the enrollment is still ongoing.
234 |
235 |
236 |
237 | enroll-finger-not-centered
238 |
239 | The user's finger was not centered on the reader. The user should retry scanning their finger, the enrollment is still ongoing.
240 |
241 |
242 |
243 | enroll-remove-and-retry
244 |
245 | The user should remove their finger from the reader and retry scanning their finger, the enrollment is still ongoing.
246 |
247 |
248 |
249 | enroll-data-full
250 |
251 | No further prints can be enrolled on this device, Device.EnrollStop should now be called.
252 |
253 | Delete other prints from the device first to continue
254 | (e.g. from other users). Note that old prints or prints from other operating systems may be deleted automatically
255 | to resolve this error without any notification.
256 |
257 |
258 |
259 | enroll-disconnected
260 |
261 | The device was disconnected during the enrollment, no other actions should be taken, and you shouldn't use the device any more.
262 |
263 |
264 |
265 |
266 | enroll-unknown-error
267 |
268 | An unknown error occurred (usually a driver problem), Device.EnrollStop should now be called.
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 | The username for whom to list the enrolled fingerprints. See Usernames.
281 |
282 |
283 | An array of strings representing the enrolled fingerprints. See Fingerprint names.
284 |
285 |
286 |
287 |
288 |
289 |
290 | List all the enrolled fingerprints for the chosen user.
291 |
292 |
293 |
294 |
295 | if the caller lacks the appropriate PolicyKit authorization
296 | if the chosen user doesn't have any fingerprints enrolled
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 | The username for whom to delete the enrolled fingerprints. See Usernames.
306 |
307 |
308 |
309 |
310 |
311 |
312 | Delete all the enrolled fingerprints for the chosen user.
313 |
314 |
315 | This call only exists for compatibility reasons, you should instead claim the device using
316 | Device.Claim and then call
317 | DeleteEnrolledFingers2.
318 |
319 |
320 |
321 |
322 | if the caller lacks the appropriate PolicyKit authorization
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 | Delete all the enrolled fingerprints for the user currently claiming the device with Device.Claim.
336 |
337 |
338 |
339 |
340 | if the caller lacks the appropriate PolicyKit authorization
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 | The username for whom to claim the device. See Usernames.
350 |
351 |
352 |
353 |
354 |
355 |
356 | Claim the device for the chosen user.
357 |
358 |
359 |
360 |
361 | if the caller lacks the appropriate PolicyKit authorization
362 | if the device is already claimed
363 | if the device couldn't be claimed
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 | Release a device claimed with Device.Claim.
377 |
378 |
379 |
380 |
381 | if the caller lacks the appropriate PolicyKit authorization
382 | if the device was not claimed
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 | A string representing the finger to verify. See Fingerprint names.
392 |
393 |
394 |
395 |
396 |
397 |
398 | Check the chosen finger against a saved fingerprint. You need to have claimed the device using
399 | Device.Claim. The finger selected is sent to the front-end
400 | using Device::VerifyFingerSelected and
401 | verification status through Device::VerifyStatus.
402 |
403 |
404 |
405 |
406 | if the caller lacks the appropriate PolicyKit authorization
407 | if the device was not claimed
408 | if the device was already being used
409 | if there are no enrolled prints for the chosen user
410 | if there was an internal error
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 | Stop an on-going fingerprint verification started with Device.VerifyStart.
424 |
425 |
426 |
427 |
428 | if the caller lacks the appropriate PolicyKit authorization
429 | if the device was not claimed
430 | if there was no ongoing verification
431 | if there was an internal error
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 | A string representing the finger select to be verified.
444 |
445 |
446 |
447 |
448 |
449 |
450 | Fingerprint names.
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 | A string representing the status of the verification.
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 | Whether the verification finished and can be stopped.
470 |
471 |
472 |
473 |
474 |
475 |
476 | Verify Statuses and Device.VerifyStop.
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 | A string representing the finger to enroll. See
486 | Fingerprint names.
487 | Note that "any" is not a valid finger name for this method.
488 |
489 |
490 |
491 |
492 |
493 |
494 | Start enrollment for the selected finger. You need to have claimed the device using
495 | Device.Claim before calling
496 | this method. Enrollment status is sent through Device::EnrollStatus.
497 |
498 |
499 |
500 |
501 | if the caller lacks the appropriate PolicyKit authorization
502 | if the device was not claimed
503 | if the device was already being used
504 | if the finger name passed is invalid
505 | if there was an internal error
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 | Stop an on-going fingerprint enrollment started with Device.EnrollStart.
520 |
521 |
522 |
523 |
524 | if the caller lacks the appropriate PolicyKit authorization
525 | if the device was not claimed
526 | if there was no ongoing verification
527 | if there was an internal error
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 | A string representing the status of the enrollment.
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 | Whether the enrollment finished and can be stopped.
547 |
548 |
549 |
550 |
551 |
552 |
553 | Enrollment Statuses and Device.EnrollStop.
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 | The product name of the device.
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 | The number of enrollment stages for the device. This is only available when the device has been claimed, otherwise it will be undefined (-1).
577 |
578 |
579 | Device.Claim and Device.EnrollStart.
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 | The scan type of the device, either "press" if you place your finger on the device, or "swipe" if you have to swipe your finger.
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
--------------------------------------------------------------------------------