Import Upstream version 3.1.2.28
|
@ -0,0 +1,86 @@
|
|||
name: Check build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
|
||||
jobs:
|
||||
archlinux:
|
||||
name: on Archlinux
|
||||
runs-on: ubuntu-20.04
|
||||
container: docker.io/library/archlinux:latest
|
||||
steps:
|
||||
- name: Checkout ukui-greeter source code
|
||||
uses: actions/checkout@v2
|
||||
- name: Refresh pacman repository
|
||||
run: pacman -Sy
|
||||
- name: Install build dependencies
|
||||
run: pacman -S --noconfirm base-devel qt5-base qt5-tools pkg-config qt5-x11extras qt5-svg liblightdm-qt5 libx11 libxtst libxrandr imlib2
|
||||
- name: QMake configure & Make
|
||||
run: |
|
||||
mkdir build;
|
||||
cd build;
|
||||
qmake-qt5 ..;
|
||||
make -j$(nproc);
|
||||
debian:
|
||||
name: on Debian Sid
|
||||
runs-on: ubuntu-20.04
|
||||
container: docker.io/library/debian:sid
|
||||
env:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
steps:
|
||||
- name: Checkout ukui-greeter source code
|
||||
uses: actions/checkout@v2
|
||||
- name: Update apt repository
|
||||
run: apt-get update -y
|
||||
- name: Install build dependcies
|
||||
run: apt-get install -y build-essential qt5-default qttools5-dev-tools debhelper-compat pkg-config qtbase5-dev libqt5x11extras5-dev libqt5svg5-dev liblightdm-qt5-3-dev libx11-dev libxtst-dev libxrandr-dev qttools5-dev-tools libimlib2-dev
|
||||
- name: QMake configure & Make
|
||||
run: |
|
||||
mkdir build;
|
||||
cd build;
|
||||
qmake ..;
|
||||
make -j$(nproc);
|
||||
|
||||
fedora:
|
||||
name: on Fedora 32
|
||||
runs-on: ubuntu-20.04
|
||||
container: docker.io/library/fedora:32
|
||||
steps:
|
||||
- name: Checkout ukui-greeter source code
|
||||
uses: actions/checkout@v2
|
||||
- name: Install build dependencies
|
||||
run: dnf install -y which gcc gcc-c++ make cmake cmake-rpm-macros autoconf automake intltool rpm-build qt5-rpm-macros qt5-qtbase-devel qt5-qtx11extras-devel qt5-qtsvg-devel lightdm-qt5-devel libX11-devel libXtst-devel libXrandr-devel qt5-qttools-devel imlib2-devel
|
||||
- name: QMake configure & Make
|
||||
run: |
|
||||
mkdir build;
|
||||
cd build;
|
||||
qmake-qt5 ..;
|
||||
make -j$(nproc);
|
||||
ubuntu:
|
||||
name: on Ubuntu 20.04
|
||||
runs-on: ubuntu-20.04
|
||||
container: docker.io/library/ubuntu:focal
|
||||
env:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
steps:
|
||||
- name: Checkout ukui-greeter source code
|
||||
uses: actions/checkout@v2
|
||||
- name: Update apt repository
|
||||
run: apt-get update -y
|
||||
- name: Install build dependcies
|
||||
run: apt-get install -y build-essential qt5-default qttools5-dev-tools debhelper-compat pkg-config qtbase5-dev libqt5x11extras5-dev libqt5svg5-dev liblightdm-qt5-3-dev libx11-dev libxtst-dev libxrandr-dev qttools5-dev-tools libimlib2-dev
|
||||
- name: QMake configure & Make
|
||||
run: |
|
||||
mkdir build;
|
||||
cd build;
|
||||
qmake ..;
|
||||
make -j$(nproc);
|
|
@ -0,0 +1,346 @@
|
|||
NOTE! The GPL below is copyrighted by the Free Software Foundation, but
|
||||
the instance of code that it refers to (the kde programs) are copyrighted
|
||||
by the authors who actually wrote it.
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
|
@ -0,0 +1,61 @@
|
|||
# ukui-greeter
|
||||
|
||||
![Check build](https://github.com/ukui/ukui-greeter/workflows/Check%20build/badge.svg?branch=master)
|
||||
|
||||
ukui-greeter是UKUI桌面环境的基于Lightdm的登录程序
|
||||
|
||||
### 依赖
|
||||
|
||||
------
|
||||
|
||||
### 编译依赖
|
||||
|
||||
- pkg-config
|
||||
- qtbase5-dev
|
||||
- libqt5x11extras5-dev
|
||||
- libqt5svg5-dev
|
||||
- liblightdm-qt5-3-dev
|
||||
- libx11-dev
|
||||
- libxtst-dev
|
||||
- libxrandr-dev
|
||||
- libglib2.0-dev
|
||||
- libopencv-dev
|
||||
- qttools5-dev-tools
|
||||
- libxi-dev
|
||||
- libimlib2-dev
|
||||
- libgsettings-qt-dev
|
||||
|
||||
### 运行依赖
|
||||
|
||||
- lightdm
|
||||
- ethtool
|
||||
|
||||
### 编译
|
||||
|
||||
------
|
||||
|
||||
```shell
|
||||
$ cd ukui-greeter
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
$ qmake ..
|
||||
$ make
|
||||
```
|
||||
|
||||
### 安装
|
||||
|
||||
------
|
||||
|
||||
```shell
|
||||
$ sudo make install
|
||||
```
|
||||
|
||||
### 主体框架
|
||||
- **InProgress**
|
||||
- [x] 界面绘制
|
||||
- [x] 功能实现
|
||||
- [x] 界面美化
|
||||
- **TROUBLE**
|
||||
- 无
|
||||
- **TODO**
|
||||
- 功能插件
|
|
@ -0,0 +1,33 @@
|
|||
QT += core dbus
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
CONFIG += c++11 dbus
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any Qt feature that has been marked deprecated (the exact warnings
|
||||
# depend on your compiler). Please consult the documentation of the
|
||||
# deprecated API in order to know how to port your code away from it.
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
# You can also make your code fail to compile if it uses deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
SOURCES += \
|
||||
main.cpp
|
||||
|
||||
HEADERS += \
|
||||
service.h
|
||||
|
||||
TARGET = greeter-nm-helper
|
||||
target.path = /usr/lib/ukui-greeter/
|
||||
|
||||
configfile.files = org.ukui.Greeter.conf
|
||||
configfile.path = /etc/dbus-1/system.d/
|
||||
|
||||
nmfilestart.files = ukui-greeter-nm-start.sh
|
||||
nmfilestart.path = /usr/lib/ukui-greeter/
|
||||
|
||||
INSTALLS += target configfile nmfilestart
|
|
@ -0,0 +1,162 @@
|
|||
#include "service.h"
|
||||
#include <QString>
|
||||
#include <qdbusconnection.h>
|
||||
#include <QFile>
|
||||
#include <syslog.h>
|
||||
|
||||
bool GreeterHelp::execConnWifiPWD(const QString connName,const QString password)
|
||||
{
|
||||
QString tmpPath = "/tmp/kylin-nm-btoutput-lightdm";
|
||||
QString cmdStr = "export LANG='en_US.UTF-8';export LANGUAGE='en_US';nmcli device wifi connect '" + connName + "' password '" + password + "' > " + tmpPath;
|
||||
|
||||
qDebug()<<"cmdStr = "<<cmdStr;
|
||||
int status = system(cmdStr.toUtf8().data());
|
||||
if (status != 0){ syslog(LOG_ERR, "execute 'nmcli device wifi connect' in function 'execConnWifiPWD' failed");}
|
||||
|
||||
QFile file(tmpPath);
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
syslog(LOG_DEBUG, "Can't open the file /tmp/kylin-nm-btoutput !");
|
||||
qDebug()<<"Can't open the file /tmp/kylin-nm-btoutput !"<<endl;
|
||||
}
|
||||
QString line = file.readLine();
|
||||
file.close();
|
||||
|
||||
if (line.indexOf("successfully") != -1) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void GreeterHelp::execConnWifiHiden(const QString connName,const QString password)
|
||||
{
|
||||
QString tmpPath = "/tmp/kylin-nm-btoutput-lightdm";
|
||||
QString cmd = "nmcli device wifi connect '" + connName + "' password '" + password + "' hidden yes > " + tmpPath;
|
||||
|
||||
int status = system(cmd.toUtf8().data());
|
||||
if (status != 0) {
|
||||
syslog(LOG_ERR, "execute 'nmcli device wifi connect' in function 'on_btnConnect_clicked' failed");
|
||||
}
|
||||
}
|
||||
|
||||
void GreeterHelp::exitGreeterHelp()
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void GreeterHelp::nmNetworkSwitch(bool val)
|
||||
{
|
||||
if(val){
|
||||
system("nmcli networking on");
|
||||
}
|
||||
else{
|
||||
system("nmcli networking off");
|
||||
}
|
||||
}
|
||||
|
||||
GreeterHelp::GreeterHelp()
|
||||
{
|
||||
bool res = QDBusConnection::systemBus().registerService("org.greeter.nm");
|
||||
if(!res){
|
||||
exit(0);
|
||||
}
|
||||
res = QDBusConnection::systemBus().registerObject("/org/greeter/nm", this, QDBusConnection :: ExportAllSlots);
|
||||
if(!res){
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
void GreeterHelp::nmConnAdd(QString conn,QString ifname)
|
||||
{
|
||||
QString cmdStr = "nmcli connection add con-name '" + conn + "' ifname '" + ifname + "' type ethernet";
|
||||
system(cmdStr.toUtf8().data());
|
||||
}
|
||||
|
||||
void GreeterHelp::nmWifiSwitch(bool val)
|
||||
{
|
||||
if(val){
|
||||
system("nmcli radio wifi on");
|
||||
}else{
|
||||
system("nmcli radio wifi off");
|
||||
}
|
||||
}
|
||||
|
||||
void GreeterHelp::kylin_network_set_manualall(QString con_name, QString addr, QString mask, QString gateway, QString dns)
|
||||
{
|
||||
QString cmdStr = "nmcli connection modify '" + con_name + "' ipv4.method manual ipv4.address " + addr + "/" + mask + " ipv4.gateway " + gateway + " ipv4.dns " + dns;
|
||||
int status = system(cmdStr.toUtf8().data());
|
||||
if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection modify' in function 'kylin_network_set_manualall' failed");}
|
||||
}
|
||||
|
||||
void GreeterHelp::kylin_network_del_ethernet_con(QString con_name)
|
||||
{
|
||||
QString cmdStr = "nmcli connection delete '" + con_name + "'";
|
||||
int status = system(cmdStr.toUtf8().data());
|
||||
if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection delete' in function 'kylin_network_del_ethernet_con' failed");}
|
||||
}
|
||||
|
||||
void GreeterHelp::kylin_network_set_automethod(QString con_name)
|
||||
{
|
||||
QString cmdStr = "nmcli connection modify '" + con_name + "' ipv4.method auto";
|
||||
int status = system(cmdStr.toUtf8().data());
|
||||
if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection modify' in function 'kylin_network_set_automethod' failed");}
|
||||
}
|
||||
|
||||
void GreeterHelp::kylin_network_set_con_down(QString con_name)
|
||||
{
|
||||
QString cmdStr = "nmcli connection down '" + con_name + "'";
|
||||
int status = system(cmdStr.toUtf8().data());
|
||||
if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection down' in function 'kylin_network_set_con_down' failed");}
|
||||
}
|
||||
|
||||
void GreeterHelp::nmConnDelete(QString conn)
|
||||
{
|
||||
QString cmdStr = "nmcli connection delete '" + conn + "'";
|
||||
system(cmdStr.toUtf8().data());
|
||||
}
|
||||
|
||||
bool GreeterHelp::kylin_network_get_autoconnect(QString con_name)
|
||||
{
|
||||
QString tmpPath = "/tmp/kylin-nm-auto-lightdm";
|
||||
QString cmdStr = "export LANG='en_US.UTF-8';export LANGUAGE='en_US';nmcli connection show '" + con_name +"' |grep autoconnect: > " + tmpPath;
|
||||
|
||||
qDebug()<<"cmdStr = "<<cmdStr;
|
||||
system(cmdStr.toUtf8().data());
|
||||
|
||||
QFile file(tmpPath);
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
qDebug()<<"Can't open the file /tmp/kylin-nm-btoutput !"<<endl;
|
||||
}
|
||||
QString line = file.readLine();
|
||||
file.close();
|
||||
if(line.contains("yes"))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
//设置是否自动连接
|
||||
bool GreeterHelp::kylin_network_set_autoconnect(QString con_name,bool autocon)
|
||||
{
|
||||
char str[100];
|
||||
QString cmdStr;
|
||||
if(autocon==false)
|
||||
{
|
||||
cmdStr = "nmcli connection modify '" + con_name + "' connection.autoconnect " + "no";
|
||||
}
|
||||
else{
|
||||
cmdStr = "nmcli connection modify '" + con_name + "' connection.autoconnect " + "yes";
|
||||
}
|
||||
int status = system(cmdStr.toUtf8().data());
|
||||
if (status != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication a(argc, argv);
|
||||
|
||||
GreeterHelp GreeterHelp;
|
||||
|
||||
return a.exec();
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!DOCTYPE busconfig PUBLIC
|
||||
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
||||
<busconfig>
|
||||
<!-- Only root can own the service -->
|
||||
<policy user="root">
|
||||
<allow own="org.greeter.nm"/>
|
||||
</policy>
|
||||
|
||||
<policy context="default">
|
||||
<allow send_destination="org.greeter.nm"/>
|
||||
</policy>
|
||||
</busconfig>
|
|
@ -0,0 +1,27 @@
|
|||
#include <QCoreApplication>
|
||||
#include <QTimer>
|
||||
#include <QDebug>
|
||||
#include <QObject>
|
||||
|
||||
class GreeterHelp: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.greeter.nm")
|
||||
public:
|
||||
GreeterHelp();
|
||||
public slots:
|
||||
bool execConnWifiPWD(const QString connName,const QString password);
|
||||
void execConnWifiHiden(const QString connName,const QString password);
|
||||
void exitGreeterHelp();
|
||||
void nmNetworkSwitch(bool val);
|
||||
void nmWifiSwitch(bool val);
|
||||
void nmConnAdd(QString conn,QString ifname);
|
||||
void nmConnDelete(QString conn);
|
||||
void kylin_network_set_manualall(QString con_name, QString addr, QString mask, QString gateway, QString dns);
|
||||
void kylin_network_del_ethernet_con(QString con_name);
|
||||
void kylin_network_set_automethod(QString con_name);
|
||||
void kylin_network_set_con_down(QString con_name);
|
||||
bool kylin_network_set_autoconnect(QString con_name,bool autocon);
|
||||
bool kylin_network_get_autoconnect(QString con_name);
|
||||
signals:
|
||||
};
|
|
@ -0,0 +1,2 @@
|
|||
#!/bin/bash
|
||||
/usr/lib/ukui-greeter/greeter-nm-helper &
|
|
@ -0,0 +1,4 @@
|
|||
TEMPLATE = subdirs
|
||||
SUBDIRS += \
|
||||
ukui-greeter \
|
||||
greeter-nm-helper
|
|
@ -0,0 +1,4 @@
|
|||
[Seat:*]
|
||||
greeter-session=ukui-greeter
|
||||
user-session=ukui
|
||||
greeter-setup-script=/usr/lib/ukui-greeter/ukui-greeter-nm-start.sh
|
|
@ -0,0 +1,13 @@
|
|||
SOURCES += \
|
||||
$$PWD/biometricproxy.cpp \
|
||||
$$PWD/biometricauthwidget.cpp \
|
||||
$$PWD/biometricdeviceswidget.cpp \
|
||||
$$PWD/biometricdeviceinfo.cpp \
|
||||
$$PWD/giodbus.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/biometricproxy.h \
|
||||
$$PWD/biometricauthwidget.h \
|
||||
$$PWD/biometricdeviceswidget.h \
|
||||
$$PWD/biometricdeviceinfo.h \
|
||||
$$PWD/giodbus.h
|
|
@ -0,0 +1,39 @@
|
|||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2018-12-06T09:17:41
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core gui dbus
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
TARGET = BiometricAuth
|
||||
TEMPLATE = app
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any feature of Qt which has been marked as deprecated (the exact warnings
|
||||
# depend on your compiler). Please consult the documentation of the
|
||||
# deprecated API in order to know how to port your code away from it.
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
# You can also make your code fail to compile if you use deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
biometricauthwidget.cpp \
|
||||
biometricproxy.cpp \
|
||||
biometricdeviceswidget.cpp \
|
||||
giodbus.cpp
|
||||
|
||||
HEADERS += \
|
||||
biometricauthwidget.h \
|
||||
biometricproxy.h \
|
||||
biometricdeviceswidget.h \
|
||||
giodbus.h
|
||||
|
||||
FORMS +=
|
|
@ -0,0 +1,336 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 4.6.2, 2018-12-12T13:43:29. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{53b257c8-4e5e-4799-9437-c1cd5d6878be}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">2</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap"/>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">桌面</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">桌面</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{0be3a3c7-d1d8-460a-946d-2a882ae7fd58}</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/kylin/test/BiometricAuth/build</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
|
||||
<value type="QString">-w</value>
|
||||
<value type="QString">-r</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
|
||||
<value type="QString">-w</value>
|
||||
<value type="QString">-r</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/kylin/test/BiometricAuth/build</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
|
||||
<value type="QString">-w</value>
|
||||
<value type="QString">-r</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
|
||||
<value type="QString">-w</value>
|
||||
<value type="QString">-r</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/kylin/test/BiometricAuth/build</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">true</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
|
||||
<value type="QString">-w</value>
|
||||
<value type="QString">-r</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
|
||||
<value type="QString">-w</value>
|
||||
<value type="QString">-r</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Profile</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">部署</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">部署设置</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
|
||||
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
|
||||
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
|
||||
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
|
||||
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
|
||||
<value type="int">0</value>
|
||||
<value type="int">1</value>
|
||||
<value type="int">2</value>
|
||||
<value type="int">3</value>
|
||||
<value type="int">4</value>
|
||||
<value type="int">5</value>
|
||||
<value type="int">6</value>
|
||||
<value type="int">7</value>
|
||||
<value type="int">8</value>
|
||||
<value type="int">9</value>
|
||||
<value type="int">10</value>
|
||||
<value type="int">11</value>
|
||||
<value type="int">12</value>
|
||||
<value type="int">13</value>
|
||||
<value type="int">14</value>
|
||||
</valuelist>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">BiometricAuth</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">BiometricAuth2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:/home/kylin/workspace/ukui-greeter/BiometricAuth/BiometricAuth.pro</value>
|
||||
<value type="bool" key="QmakeProjectManager.QmakeRunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">BiometricAuth.pro</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory.default">/home/kylin/test/BiometricAuth/build</value>
|
||||
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="int">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">18</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">18</value>
|
||||
</data>
|
||||
</qtcreator>
|
|
@ -0,0 +1,343 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#include "biometricauthwidget.h"
|
||||
#include <QLabel>
|
||||
#include <QDebug>
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include "biometricdeviceinfo.h"
|
||||
#include "giodbus.h"
|
||||
|
||||
BiometricAuthWidget::BiometricAuthWidget(BiometricProxy *proxy, QWidget *parent) :
|
||||
QWidget(parent),
|
||||
proxy(proxy),
|
||||
isInAuth(false),
|
||||
movieTimer(nullptr),
|
||||
retrytimer(nullptr),
|
||||
failedCount(0),
|
||||
usebind(false),
|
||||
beStopped(false),
|
||||
timeoutCount(0)
|
||||
{
|
||||
usebind = getAuthDouble();
|
||||
qDebug() << "BiometricAuthWidget::BiometricAuthWidget";
|
||||
initUI();
|
||||
resize(400, 260);
|
||||
|
||||
if(this->proxy)
|
||||
{
|
||||
connect(this->proxy, &BiometricProxy::StatusChanged,
|
||||
this, &BiometricAuthWidget::onStatusChanged);
|
||||
|
||||
connect(this->proxy, &BiometricProxy::FrameWritten,
|
||||
this, &BiometricAuthWidget::onFrameWritten);
|
||||
}
|
||||
}
|
||||
|
||||
void BiometricAuthWidget::initUI()
|
||||
{
|
||||
//显示提示信息
|
||||
lblNotify = new QLabel(this);
|
||||
lblNotify->setWordWrap(true);
|
||||
lblNotify->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
|
||||
|
||||
//显示当前设备
|
||||
lblDevice = new QLabel(this);
|
||||
lblDevice->setWordWrap(true);
|
||||
lblDevice->setAlignment(Qt::AlignCenter);
|
||||
|
||||
//显示图片
|
||||
lblImage = new QLabel(this);
|
||||
lblImage->setFixedSize(100, 100);
|
||||
}
|
||||
|
||||
|
||||
void BiometricAuthWidget::resizeEvent(QResizeEvent */*event*/)
|
||||
{
|
||||
lblNotify->setGeometry(0, 0, width(), 45);
|
||||
lblDevice->setGeometry(0, lblNotify->geometry().bottom()+5, width(), 30);
|
||||
lblImage->setGeometry((width() - lblImage->width()) / 2,
|
||||
lblDevice->geometry().bottom() + 10,
|
||||
lblImage->width(), lblImage->height());
|
||||
}
|
||||
|
||||
void BiometricAuthWidget::startAuth(DeviceInfoPtr device, int uid)
|
||||
{
|
||||
if(!proxy)
|
||||
{
|
||||
qWarning() << "BiometricProxy doesn't exist.";
|
||||
return;
|
||||
}
|
||||
|
||||
if(isInAuth)
|
||||
{
|
||||
qDebug() << "Identification is currently under way, stop it";
|
||||
stopAuth();
|
||||
}
|
||||
|
||||
this->device = device;
|
||||
this->uid = uid;
|
||||
this->userName = getpwuid(uid)->pw_name;
|
||||
this->failedCount = 0;
|
||||
this->timeoutCount = 0;
|
||||
this->beStopped = false;
|
||||
startAuth_();
|
||||
}
|
||||
|
||||
void BiometricAuthWidget::startAuth_()
|
||||
{
|
||||
lblDevice->setText(tr("Current device: ") + device->shortName);
|
||||
|
||||
qDebug().noquote() << QString("Identify:[drvid: %1, uid: %2]").arg(device->id).arg(uid);
|
||||
|
||||
isInAuth = true;
|
||||
dup_fd = -1;
|
||||
|
||||
QDBusPendingCall call = proxy->Identify(device->id, uid);
|
||||
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
|
||||
connect(watcher, &QDBusPendingCallWatcher::finished,
|
||||
this, &BiometricAuthWidget::onIdentifyComplete);
|
||||
|
||||
updateImage(1);
|
||||
}
|
||||
|
||||
void BiometricAuthWidget::stopAuth()
|
||||
{
|
||||
beStopped = true;
|
||||
if(!isInAuth)
|
||||
{
|
||||
return;
|
||||
}
|
||||
proxy->StopOps(device->id);
|
||||
if(retrytimer&&retrytimer->isActive()){
|
||||
retrytimer->stop();
|
||||
delete retrytimer;
|
||||
retrytimer = nullptr;
|
||||
}
|
||||
isInAuth = false;
|
||||
updateImage(0);
|
||||
}
|
||||
|
||||
void BiometricAuthWidget::onIdentifyComplete(QDBusPendingCallWatcher *watcher)
|
||||
{
|
||||
if(beStopped == true)
|
||||
return ;
|
||||
|
||||
QDBusPendingReply<int, int> reply = *watcher;
|
||||
if(reply.isError())
|
||||
{
|
||||
qWarning() << "Identify error: " << reply.error().message();
|
||||
Q_EMIT authComplete(false);
|
||||
updateImage(0);
|
||||
return;
|
||||
}
|
||||
int result = reply.argumentAt(0).toInt();
|
||||
int authUid = reply.argumentAt(1).toInt();
|
||||
qDebug() << result << authUid << uid;
|
||||
|
||||
// 特征识别成功,而且用户id匹配
|
||||
if(result == DBUS_RESULT_SUCCESS && authUid == uid)
|
||||
{
|
||||
qDebug() << "Identify success";
|
||||
Q_EMIT authComplete(true);
|
||||
}
|
||||
// 特征识别不匹配
|
||||
else if(result == DBUS_RESULT_NOTMATCH)
|
||||
{
|
||||
if(usebind){
|
||||
Q_EMIT authComplete(false);
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "Identify failed";
|
||||
failedCount++;
|
||||
qDebug() << "max auto retry: " << GetMaxFailedAutoRetry(userName) << failedCount;
|
||||
if(failedCount >= GetMaxFailedAutoRetry(userName))
|
||||
{
|
||||
Q_EMIT authComplete(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
lblNotify->setText(tr("Identify failed, Please retry."));
|
||||
if(!beStopped){
|
||||
// QTimer::singleShot(1000, this, &BiometricAuthWidget::startAuth_);
|
||||
if(!retrytimer){
|
||||
retrytimer = new QTimer(this);
|
||||
retrytimer->setSingleShot(true);
|
||||
connect(retrytimer, &QTimer::timeout, this, &BiometricAuthWidget::startAuth_);
|
||||
}
|
||||
retrytimer->start(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
//识别发生错误
|
||||
else if(result == DBUS_RESULT_ERROR)
|
||||
{
|
||||
if(usebind){
|
||||
Q_EMIT authComplete(false);
|
||||
return;
|
||||
}
|
||||
|
||||
StatusReslut ret = proxy->UpdateStatus(device->id);
|
||||
//识别操作超时
|
||||
if(ret.result == 0 && ret.opsStatus == OPS_IDENTIFY_TIMEOUT)
|
||||
{
|
||||
timeoutCount++;
|
||||
if(timeoutCount >= GetMaxTimeoutAutoRetry(userName))
|
||||
{
|
||||
Q_EMIT authComplete(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
QTimer::singleShot(1000, [&]{
|
||||
if(!beStopped)
|
||||
{
|
||||
startAuth_();
|
||||
}
|
||||
});
|
||||
}
|
||||
}else{
|
||||
Q_EMIT authComplete(false);
|
||||
}
|
||||
}else{
|
||||
Q_EMIT authComplete(false);
|
||||
}
|
||||
updateImage(0);
|
||||
}
|
||||
|
||||
void BiometricAuthWidget::onFrameWritten(int drvid)
|
||||
{
|
||||
|
||||
if(dup_fd == -1){
|
||||
dup_fd = get_server_gvariant_stdout(drvid);
|
||||
}
|
||||
|
||||
if(dup_fd <= 0)
|
||||
return ;
|
||||
|
||||
cv::Mat img;
|
||||
lseek(dup_fd, 0, SEEK_SET);
|
||||
char base64_bufferData[1024*1024];
|
||||
int rc = read(dup_fd, base64_bufferData, 1024*1024);
|
||||
printf("rc = %d\n", rc);
|
||||
|
||||
cv::Mat mat2(1, sizeof(base64_bufferData), CV_8U, base64_bufferData);
|
||||
img = cv::imdecode(mat2, cv::IMREAD_COLOR);
|
||||
cv::cvtColor(img,img,cv::COLOR_BGR2RGB);
|
||||
|
||||
QImage srcQImage = QImage((uchar*)(img.data), img.cols, img.rows, QImage::Format_RGB888);
|
||||
lblImage->setFixedSize(160,160);
|
||||
lblImage->setGeometry((width() - lblImage->width()) / 2,
|
||||
lblDevice->geometry().bottom() + 10,
|
||||
lblImage->width(), lblImage->height());
|
||||
lblImage->setPixmap(QPixmap::fromImage(srcQImage).scaled(lblImage->size()));
|
||||
//lblImage->setPixmap(QPixmap::fromImage(srcQImage));
|
||||
// QPixmap image = QPixmap::fromImage(srcQImage);
|
||||
// image = image.scaled(lblImage->width(), lblImage->height(),
|
||||
// Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
// lblImage->setPixmap(image);
|
||||
}
|
||||
|
||||
void BiometricAuthWidget::onStatusChanged(int drvid, int status)
|
||||
{
|
||||
if(!isInAuth)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(drvid != device->id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 显示来自服务的提示信息
|
||||
if(status == STATUS_NOTIFY)
|
||||
{
|
||||
QString notifyMsg = proxy->GetNotifyMesg(drvid);
|
||||
lblNotify->setText(notifyMsg);
|
||||
}
|
||||
}
|
||||
|
||||
static int count = 0;
|
||||
void BiometricAuthWidget::updateImage(int type)
|
||||
{
|
||||
if(device->deviceType == DeviceType::Type::Face)
|
||||
return ;
|
||||
|
||||
if(type == 0)
|
||||
{
|
||||
if(movieTimer && movieTimer->isActive())
|
||||
{
|
||||
movieTimer->stop();
|
||||
}
|
||||
|
||||
QString imagePath = QString(UKUI_BIOMETRIC_IMAGES_PATH "%1/01.png")
|
||||
.arg(DeviceType::getDeviceType(device->deviceType));
|
||||
setImage(imagePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!movieTimer)
|
||||
{
|
||||
movieTimer = new QTimer(this);
|
||||
movieTimer->setInterval(100);
|
||||
connect(movieTimer, &QTimer::timeout,
|
||||
this, &BiometricAuthWidget::onMoviePixmapUpdate);
|
||||
}
|
||||
count = 0;
|
||||
movieTimer->start();
|
||||
}
|
||||
}
|
||||
|
||||
void BiometricAuthWidget::onMoviePixmapUpdate()
|
||||
{
|
||||
if(count >= 18)
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
count++;
|
||||
QString fileName = (count < 10 ? "0" : "") + QString::number(count);
|
||||
QString imagePath = QString(UKUI_BIOMETRIC_IMAGES_PATH "%1/%2.png")
|
||||
.arg(DeviceType::getDeviceType(device->deviceType))
|
||||
.arg(fileName);
|
||||
setImage(imagePath);
|
||||
}
|
||||
|
||||
void BiometricAuthWidget::setImage(const QString &path)
|
||||
{
|
||||
QPixmap image(path);
|
||||
image = image.scaled(lblImage->width(), lblImage->height(),
|
||||
Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
lblImage->setPixmap(image);
|
||||
}
|
||||
|
||||
bool BiometricAuthWidget::getAuthDouble()
|
||||
{
|
||||
QSettings settings("/etc/biometric-auth/ukui-biometric.conf", QSettings::IniFormat);
|
||||
bool distribId = settings.value("DoubleAuth").toBool();
|
||||
return distribId;
|
||||
}
|
||||
|
||||
void BiometricAuthWidget::setMinImage(float val)
|
||||
{
|
||||
resize(400,100+100*val);
|
||||
lblImage->setFixedSize(100*val, 100*val);
|
||||
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#ifndef BIOMETRICAUTHWIDGET_H
|
||||
#define BIOMETRICAUTHWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include "biometricproxy.h"
|
||||
|
||||
class QLabel;
|
||||
//class QDBusPendingCallWatcher;
|
||||
//class BiometricProxy;
|
||||
//class DeviceIdentityPtr;
|
||||
class BiometricAuthWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit BiometricAuthWidget(BiometricProxy *proxy, QWidget *parent = 0);
|
||||
|
||||
/**
|
||||
* @brief 进行生物识别认证
|
||||
* @param deviceInfo 使用的设备
|
||||
* @param uid 待认证的用户id
|
||||
*/
|
||||
void startAuth(DeviceInfoPtr device, int uid);
|
||||
|
||||
/**
|
||||
* @brief 终止生物识别认证
|
||||
*/
|
||||
void stopAuth();
|
||||
|
||||
/**
|
||||
* @brief 是否正在认证
|
||||
* @return
|
||||
*/
|
||||
bool isAuthenticating()
|
||||
{ return isInAuth; }
|
||||
|
||||
void setMinImage(float val);
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* @brief 认证完成
|
||||
* @param result 认证结果
|
||||
*/
|
||||
void authComplete(bool result);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onIdentifyComplete(QDBusPendingCallWatcher *watcher);
|
||||
void onStatusChanged(int drvid, int status);
|
||||
void onMoviePixmapUpdate();
|
||||
void onFrameWritten(int drvid);
|
||||
|
||||
private:
|
||||
void initUI();
|
||||
void updateImage(int type = 0);
|
||||
void setImage(const QString &path);
|
||||
void startAuth_();
|
||||
bool getAuthDouble();
|
||||
|
||||
private:
|
||||
QLabel *lblNotify;
|
||||
QLabel *lblDevice;
|
||||
QLabel *lblImage;
|
||||
|
||||
BiometricProxy *proxy;
|
||||
int uid;
|
||||
QString userName;
|
||||
DeviceInfoPtr device;
|
||||
bool isInAuth;
|
||||
QTimer *movieTimer;
|
||||
int failedCount;
|
||||
bool beStopped; //被强制终止
|
||||
int timeoutCount;
|
||||
QTimer *retrytimer;
|
||||
bool usebind;
|
||||
int fd = -1;
|
||||
int dup_fd = -1;
|
||||
};
|
||||
|
||||
#endif // BIOMETRICAUTHWIDGET_H
|
|
@ -0,0 +1,256 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#include "biometricdeviceinfo.h"
|
||||
#include <QFile>
|
||||
|
||||
QString DeviceType::getDeviceType(int deviceType)
|
||||
{
|
||||
if(deviceType >= __MAX_NR_TYPES)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
QMetaEnum meta = QMetaEnum::fromType<Type>();
|
||||
const char *typeString = meta.valueToKey(deviceType);
|
||||
return QString(typeString);
|
||||
}
|
||||
|
||||
QString DeviceType::getDeviceType_tr(int deviceType)
|
||||
{
|
||||
switch(deviceType)
|
||||
{
|
||||
case FingerPrint:
|
||||
return tr("FingerPrint");
|
||||
case FingerVein:
|
||||
return tr("FingerVein");
|
||||
case Iris:
|
||||
return tr("Iris");
|
||||
case Face:
|
||||
return tr("Face");
|
||||
case VoicePrint:
|
||||
return tr("VoicePrint");
|
||||
case REMOTE_QRCODE_TYPE:
|
||||
return tr("QRCode");
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
QDebug operator <<(QDebug stream, const DeviceInfo &deviceInfo)
|
||||
{
|
||||
stream << "["
|
||||
<< deviceInfo.id
|
||||
<< deviceInfo.shortName
|
||||
<< deviceInfo.fullName
|
||||
<< deviceInfo.deviceType
|
||||
<< deviceInfo.driverEnable
|
||||
<< deviceInfo.deviceNum
|
||||
<< "]";
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDBusArgument &operator <<(QDBusArgument &arg, const DeviceInfo &deviceInfo)
|
||||
{
|
||||
arg.beginStructure();
|
||||
arg << deviceInfo.id
|
||||
<< deviceInfo.shortName
|
||||
<< deviceInfo.fullName
|
||||
<< deviceInfo.driverEnable
|
||||
<< deviceInfo.deviceNum
|
||||
<< deviceInfo.deviceType
|
||||
<< deviceInfo.storageType
|
||||
<< deviceInfo.eigType
|
||||
<< deviceInfo.verifyType
|
||||
<< deviceInfo.identifyType
|
||||
<< deviceInfo.busType
|
||||
<< deviceInfo.deviceStatus
|
||||
<< deviceInfo.OpsStatus;
|
||||
arg.endStructure();
|
||||
return arg;
|
||||
}
|
||||
const QDBusArgument &operator >>(const QDBusArgument &arg, DeviceInfo &deviceInfo)
|
||||
{
|
||||
arg.beginStructure();
|
||||
arg >> deviceInfo.id
|
||||
>> deviceInfo.shortName
|
||||
>> deviceInfo.fullName
|
||||
>> deviceInfo.driverEnable
|
||||
>> deviceInfo.deviceNum
|
||||
>> deviceInfo.deviceType
|
||||
>> deviceInfo.storageType
|
||||
>> deviceInfo.eigType
|
||||
>> deviceInfo.verifyType
|
||||
>> deviceInfo.identifyType
|
||||
>> deviceInfo.busType
|
||||
>> deviceInfo.deviceStatus
|
||||
>> deviceInfo.OpsStatus;
|
||||
arg.endStructure();
|
||||
return arg;
|
||||
}
|
||||
|
||||
void registerMetaType()
|
||||
{
|
||||
qRegisterMetaType<DeviceInfo>("DeviceInfo");
|
||||
qDBusRegisterMetaType<DeviceInfo>();
|
||||
}
|
||||
|
||||
QString GetDefaultDevice(const QString &userName)
|
||||
{
|
||||
// QString configPath = QString("/home/%1/" UKUI_BIOMETRIC_CONFIG_PATH).arg(userName);
|
||||
// QSettings settings(configPath, QSettings::IniFormat);
|
||||
// qDebug() << "configure path: " << settings.fileName();
|
||||
|
||||
QString configPath = QDir::homePath() + "/" + UKUI_BIOMETRIC_CONFIG_PATH;
|
||||
QSettings settings(configPath, QSettings::IniFormat);
|
||||
|
||||
QString defaultDevice = settings.value("DefaultDevice").toString();
|
||||
|
||||
if(defaultDevice.isEmpty())
|
||||
{
|
||||
QString configPath = QString("/var/lib/lightdm-data/%1/" UKUI_BIOMETRIC_CONFIG_PATH).arg(userName);
|
||||
QSettings settings(configPath, QSettings::IniFormat);
|
||||
defaultDevice = settings.value("DefaultDevice").toString();
|
||||
}
|
||||
|
||||
if(defaultDevice.isEmpty() && userName == "root"){
|
||||
QSettings sysSettings(UKUI_BIOMETRIC_SYS_CONFIG_PATH, QSettings::IniFormat);
|
||||
defaultDevice = sysSettings.value("rootUserDefaultDevice").toString();
|
||||
}
|
||||
|
||||
if(defaultDevice.isEmpty())
|
||||
{
|
||||
QSettings sysSettings(UKUI_BIOMETRIC_SYS_CONFIG_PATH, QSettings::IniFormat);
|
||||
defaultDevice = sysSettings.value("DefaultDevice").toString();
|
||||
}
|
||||
|
||||
return defaultDevice;
|
||||
}
|
||||
|
||||
int GetLastDevice(const QString &userName)
|
||||
{
|
||||
int nLastDevId = -1;
|
||||
QSettings sysSettings(QString(SHARE_BIOMETRIC_CONFIG_PATH).arg(userName), QSettings::IniFormat);
|
||||
sysSettings.beginGroup("Common");
|
||||
if (sysSettings.allKeys().contains("LastDeviceId")) {
|
||||
nLastDevId = sysSettings.value("LastDeviceId").toInt();
|
||||
}
|
||||
sysSettings.endGroup();
|
||||
return nLastDevId;
|
||||
}
|
||||
|
||||
void SetLastDevice(const QString &userName, int drvid)
|
||||
{
|
||||
if (drvid < 0) {
|
||||
return;
|
||||
}
|
||||
QString desConfPath = QString(SHARE_BIOMETRIC_CONFIG_PATH).arg(userName);
|
||||
QFile fileConf(desConfPath);
|
||||
if (fileConf.exists()) {
|
||||
QSettings sysSettings(desConfPath, QSettings::IniFormat);
|
||||
sysSettings.beginGroup("Common");
|
||||
sysSettings.setValue("LastDeviceId", drvid);
|
||||
sysSettings.endGroup();
|
||||
} else {
|
||||
QSettings sysSettings(desConfPath, QSettings::IniFormat);
|
||||
sysSettings.beginGroup("Common");
|
||||
sysSettings.setValue("LastDeviceId", drvid);
|
||||
sysSettings.endGroup();
|
||||
sysSettings.sync();
|
||||
QFile file(desConfPath);
|
||||
file.setPermissions(QFile::WriteUser | QFile::ReadUser | QFile::WriteOther | QFile::ReadOther);
|
||||
}
|
||||
}
|
||||
|
||||
static int getValueFromSettings(const QString &userName, const QString &key, int defaultValue = 3)
|
||||
{
|
||||
//从家目录下的配置文件中获取
|
||||
// QString configPath = QString("/home/%1/" UKUI_BIOMETRIC_CONFIG_PATH).arg(userName);
|
||||
QString configPath = QDir::homePath() + "/" + UKUI_BIOMETRIC_CONFIG_PATH;
|
||||
QSettings settings(configPath, QSettings::IniFormat);
|
||||
QString valueStr = settings.value(key).toString();
|
||||
|
||||
//如果没有获取到,则从系统配置文件中获取
|
||||
if(valueStr.isEmpty())
|
||||
{
|
||||
QSettings sysSettings(UKUI_BIOMETRIC_SYS_CONFIG_PATH, QSettings::IniFormat);
|
||||
valueStr = sysSettings.value(key).toString();
|
||||
}
|
||||
|
||||
bool ok;
|
||||
int value = valueStr.toInt(&ok);
|
||||
if( (value == 0 && !ok) || valueStr.isEmpty() )
|
||||
{
|
||||
value = defaultValue;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
bool GetHiddenSwitchButton()
|
||||
{
|
||||
QSettings sysSettings(UKUI_BIOMETRIC_SYS_CONFIG_PATH, QSettings::IniFormat);
|
||||
if(sysSettings.contains("HiddenSwitchButton"))
|
||||
return sysSettings.value("HiddenSwitchButton").toBool();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetAuthEnable()
|
||||
{
|
||||
QSettings sysSettings(UKUI_BIOMETRIC_SYS_CONFIG_PATH, QSettings::IniFormat);
|
||||
if(sysSettings.contains("EnableAuth"))
|
||||
return sysSettings.value("EnableAuth").toBool();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetQRCodeEnable()
|
||||
{
|
||||
bool isEnable = false;
|
||||
QSettings sysSettings(UKUI_BIOMETRIC_SYS_CONFIG_PATH, QSettings::IniFormat);
|
||||
sysSettings.beginGroup("Functions");
|
||||
if (sysSettings.allKeys().contains("EnableQRCode")) {
|
||||
isEnable = sysSettings.value("EnableQRCode").toBool();
|
||||
}
|
||||
sysSettings.endGroup();
|
||||
return isEnable;
|
||||
}
|
||||
|
||||
int GetFailedTimes()
|
||||
{
|
||||
QSettings sysSettings(UKUI_BIOMETRIC_SYS_CONFIG_PATH, QSettings::IniFormat);
|
||||
if(sysSettings.contains("MaxFailedTimes"))
|
||||
return sysSettings.value("MaxFailedTimes").toInt();
|
||||
else
|
||||
return 3;
|
||||
}
|
||||
|
||||
bool GetUseFirstDevice()
|
||||
{
|
||||
QSettings sysSettings(UKUI_BIOMETRIC_SYS_CONFIG_PATH, QSettings::IniFormat);
|
||||
return sysSettings.value("UseFirstDevice").toBool();
|
||||
}
|
||||
|
||||
int GetMaxFailedAutoRetry(const QString &userName)
|
||||
{
|
||||
return getValueFromSettings(userName, "MaxFailedAutoRetry");
|
||||
}
|
||||
|
||||
int GetMaxTimeoutAutoRetry(const QString &userName)
|
||||
{
|
||||
return getValueFromSettings(userName, "MaxTimeoutAutoRetry");
|
||||
}
|
|
@ -0,0 +1,258 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#ifndef BIOMETRICDEVICEINFO_H
|
||||
#define BIOMETRICDEVICEINFO_H
|
||||
|
||||
#include <memory>
|
||||
#include <QtDBus>
|
||||
|
||||
#define BIOMETRIC_DBUS_SERVICE "org.ukui.Biometric"
|
||||
#define BIOMETRIC_DBUS_PATH "/org/ukui/Biometric"
|
||||
#define BIOMETRIC_DBUS_INTERFACE "org.ukui.Biometric"
|
||||
|
||||
#define UKUI_BIOMETRIC_IMAGES_PATH "/usr/share/ukui-biometric/images/"
|
||||
#define UKUI_BIOMETRIC_CONFIG_PATH ".biometric_auth/ukui_biometric.conf"
|
||||
#define UKUI_BIOMETRIC_SYS_CONFIG_PATH "/etc/biometric-auth/ukui-biometric.conf"
|
||||
#define SHARE_BIOMETRIC_CONFIG_PATH "/var/lib/lightdm-data/%1/ukui-biometric.conf" //greeter、screensaver、polkit share conf
|
||||
|
||||
#define BIOMETRIC_PAM_DOUBLE "BIOMETRIC_PAM_DOUBLE"
|
||||
#define BIOMETRIC_PAM "BIOMETRIC_PAM"
|
||||
#define BIOMETRIC_PAM_QRCODE "BIOMETRIC_PAM_QRCODE"
|
||||
#define BIOMETRIC_IGNORE "BIOMETRIC_IGNORE"
|
||||
#define BIOMETRIC_SUCCESS "BIOMETRIC_SUCCESS"
|
||||
|
||||
#define REMOTE_QRCODE_TYPE (8)
|
||||
|
||||
/**
|
||||
* @brief 设备类型
|
||||
*/
|
||||
class DeviceType : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DeviceType();
|
||||
enum Type {
|
||||
FingerPrint,
|
||||
FingerVein,
|
||||
Iris,
|
||||
Face,
|
||||
VoicePrint,
|
||||
__MAX_NR_TYPES
|
||||
};
|
||||
Q_ENUM(Type)
|
||||
/**
|
||||
* @brief 获取设备类型的字符串表现形式
|
||||
* @param deviceType 设备类型
|
||||
* @return
|
||||
*/
|
||||
static QString getDeviceType(int deviceType);
|
||||
|
||||
/**
|
||||
* @brief 获取设备类型的国际化字符串
|
||||
* @param deviceType 设备类型
|
||||
* @return
|
||||
*/
|
||||
static QString getDeviceType_tr(int deviceType);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief StatusChanged D-Bus 信号触发时的状态变化类型
|
||||
*/
|
||||
enum StatusType {
|
||||
STATUS_DEVICE,
|
||||
STATUS_OPERATION,
|
||||
STATUS_NOTIFY
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 识别、终止操作等DBus调用的结果,即返回值里的 result
|
||||
*/
|
||||
enum DBusResult {
|
||||
DBUS_RESULT_SUCCESS = 0,
|
||||
DBUS_RESULT_NOTMATCH = -1,
|
||||
DBUS_RESULT_ERROR = -2,
|
||||
DBUS_RESULT_DEVICEBUSY = -3,
|
||||
DBUS_RESULT_NOSUCHDEVICE = -4,
|
||||
DBUS_RESULT_PERMISSIONDENIED = -5
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 识别操作(Identify)的ops状态
|
||||
*/
|
||||
/* 定义操作类型 */
|
||||
typedef enum {
|
||||
OPS_TYPE_COMM = 0,
|
||||
OPS_TYPE_OPEN,
|
||||
OPS_TYPE_ENROLL,
|
||||
OPS_TYPE_VERIFY,
|
||||
OPS_TYPE_IDENTIFY,
|
||||
OPS_TYPE_CAPTURE,
|
||||
OPS_TYPE_SEARCH,
|
||||
OPS_TYPE_CLEAN,
|
||||
OPS_TYPE_GET_FLIST,
|
||||
OPS_TYPE_RENAME,
|
||||
OPS_TYPE_CLOSE,
|
||||
}BioOpsType;
|
||||
|
||||
/*
|
||||
* 定义各种操作结果
|
||||
*/
|
||||
typedef enum {
|
||||
OPS_COMM_SUCCESS = OPS_TYPE_COMM * 100, /** 空闲状态 **/
|
||||
OPS_COMM_FAIL, /** 操作失败 **/
|
||||
OPS_COMM_NO_MATCH = OPS_COMM_FAIL, /** 不匹配 **/
|
||||
OPS_COMM_ERROR, /** 通用操作错误 **/
|
||||
OPS_COMM_STOP_BY_USER, /** 用户取消 **/
|
||||
OPS_COMM_TIMEOUT, /** 操作超时 **/
|
||||
OPS_COMM_OUT_OF_MEM, /** 无法分配内存 **/
|
||||
OPS_COMM_MAX,
|
||||
|
||||
OPS_OPEN_SUCCESS = OPS_TYPE_OPEN * 100, /** 打开设备完成 **/
|
||||
OPS_OPEN_FAIL, /** 打开设备失败 **/
|
||||
OPS_OPEN_ERROR, /** 打开设备遇到错误 **/
|
||||
OPS_OPEN_MAX,
|
||||
|
||||
OPS_ENROLL_SUCCESS = OPS_TYPE_ENROLL * 100, /** 录入信息成功 **/
|
||||
OPS_ENROLL_FAIL, /** 录入失败 **/
|
||||
OPS_ENROLL_ERROR, /** 录入过程中遇到错误 **/
|
||||
OPS_ENROLL_STOP_BY_USER, /** 录入被用户中断 **/
|
||||
OPS_ENROLL_TIMEOUT, /** 操作超时 **/
|
||||
OPS_ENROLL_MAX,
|
||||
|
||||
OPS_VERIFY_MATCH = OPS_TYPE_VERIFY * 100, /** 认证匹配 **/
|
||||
OPS_VERIFY_NO_MATCH, /** 认证不匹配 **/
|
||||
OPS_VERIFY_ERROR, /** 认证过程中遇到错误 **/
|
||||
OPS_VERIFY_STOP_BY_USER, /** 认证被用户中断 **/
|
||||
OPS_VERIFY_TIMEOUT, /** 操作超时 **/
|
||||
OPS_VERIFY_MAX,
|
||||
|
||||
OPS_IDENTIFY_MATCH = OPS_TYPE_IDENTIFY * 100, /** 识别到指定特征 **/
|
||||
OPS_IDENTIFY_NO_MATCH, /** 未识别出指定特征 **/
|
||||
OPS_IDENTIFY_ERROR, /** 识别过程中遇到错误 **/
|
||||
OPS_IDENTIFY_STOP_BY_USER, /** 识别被用户中断 **/
|
||||
OPS_IDENTIFY_TIMEOUT, /** 操作超时 **/
|
||||
OPS_IDENTIFY_MAX,
|
||||
|
||||
OPS_CAPTURE_SUCCESS = OPS_TYPE_CAPTURE * 100, /** 捕获成功 **/
|
||||
OPS_CAPTURE_FAIL, /** 捕获失败 **/
|
||||
OPS_CAPTURE_ERROR, /** 捕获过程中遇到错误 **/
|
||||
OPS_CAPTURE_STOP_BY_USER, /** 捕获被用户中断 **/
|
||||
OPS_CAPTURE_TIMEOUT, /** 操作超时 **/
|
||||
OPS_CAPTURE_MAX,
|
||||
|
||||
OPS_SEARCH_MATCH = OPS_TYPE_SEARCH * 100, /** 搜索到指定特征 **/
|
||||
OPS_SEARCH_NO_MATCH, /** 未搜索到指定特征 **/
|
||||
OPS_SEARCH_ERROR, /** 搜索过程中遇到错误 **/
|
||||
OPS_SEARCH_STOP_BY_USER, /** 搜索被用户中断 **/
|
||||
OPS_SEARCH_TIMEOUT, /** 操作超时 **/
|
||||
OPS_SEARCH_MAX,
|
||||
|
||||
OPS_CLEAN_SUCCESS = OPS_TYPE_CLEAN * 100, /** 清理特征成功 **/
|
||||
OPS_CLEAN_FAIL, /** 清理失败 **/
|
||||
OPS_CLEAN_ERROR, /** 清理过程中遇到错误 **/
|
||||
OPS_CLEAN_STOP_BY_USER, /** 清理被用户中断 **/
|
||||
OPS_CLEAN_TIMEOUT, /** 操作超时 **/
|
||||
OPS_CLEAN_MAX,
|
||||
|
||||
OPS_GET_FLIST_SUCCESS = OPS_TYPE_GET_FLIST * 100, /** 获取特征列表完成 **/
|
||||
OPS_GET_FLIST_FAIL, /** 获取特征列表失败 **/
|
||||
OPS_GET_FLIST_ERROR, /** 获取特征列表过程中遇到错误 **/
|
||||
OPS_GET_FLIST_STOP_BY_USER, /** 获取特征列表被用户中断 **/
|
||||
OPS_GET_FLIST_TIMEOUT, /** 获取特征列表超时 **/
|
||||
OPS_GET_FLIST_MAX,
|
||||
|
||||
OPS_RENAME_SUCCESS = OPS_TYPE_RENAME * 100, /** 重命名特征完成 **/
|
||||
OPS_RENAME_FAIL, /** 重命名特征失败 **/
|
||||
OPS_RENAME_ERROR, /** 重命名特征过程中遇到错误 **/
|
||||
OPS_RENAME_STOP_BY_USER, /** 重命名特征被用户中断 **/
|
||||
OPS_RENAME_TIMEOUT, /** 重命名特征超时 **/
|
||||
OPS_RENAME_MAX,
|
||||
|
||||
OPS_CLOSE_SUCCESS = OPS_TYPE_CLOSE * 100, /** 关闭设备完成 **/
|
||||
OPS_CLOSE_FAIL, /** 关闭设备失败 **/
|
||||
OPS_CLOSE_ERROR, /** 关闭设备过程中遇到错误 **/
|
||||
OPS_CLOSE_MAX,
|
||||
}OpsResult;
|
||||
|
||||
/**
|
||||
* @brief 设备的信息
|
||||
*/
|
||||
struct DeviceInfo
|
||||
{
|
||||
int id;
|
||||
QString shortName;
|
||||
QString fullName;
|
||||
int driverEnable;
|
||||
int deviceNum;
|
||||
int deviceType;
|
||||
int storageType;
|
||||
int eigType;
|
||||
int verifyType;
|
||||
int identifyType;
|
||||
int busType;
|
||||
int deviceStatus;
|
||||
int OpsStatus;
|
||||
};
|
||||
|
||||
QDBusArgument &operator <<(QDBusArgument &arg, const DeviceInfo &deviceInfo);
|
||||
const QDBusArgument &operator >>(const QDBusArgument &arg, DeviceInfo &deviceInfo);
|
||||
|
||||
void registerMetaType();
|
||||
|
||||
typedef std::shared_ptr<DeviceInfo> DeviceInfoPtr;
|
||||
typedef QList<DeviceInfoPtr> DeviceList;
|
||||
typedef QMap<int, DeviceList> DeviceMap;
|
||||
|
||||
QDebug operator <<(QDebug stream, const DeviceInfo &deviceInfo);
|
||||
|
||||
Q_DECLARE_METATYPE(DeviceInfo)
|
||||
|
||||
/**
|
||||
* @brief 获取默认设备
|
||||
* @return
|
||||
*/
|
||||
QString GetDefaultDevice(const QString &userName);
|
||||
|
||||
/**
|
||||
* @brief 获取上次选择的设备
|
||||
* @return
|
||||
*/
|
||||
int GetLastDevice(const QString &userName);
|
||||
|
||||
void SetLastDevice(const QString &userName, int drvid);
|
||||
|
||||
/**
|
||||
* @brief 获取失败后自动重新开始的最大次数
|
||||
* @param userName
|
||||
* @return
|
||||
*/
|
||||
int GetMaxFailedAutoRetry(const QString &userName);
|
||||
int GetFailedTimes();
|
||||
bool GetHiddenSwitchButton();
|
||||
bool GetAuthEnable();
|
||||
bool GetQRCodeEnable();
|
||||
bool GetUseFirstDevice();
|
||||
/**
|
||||
* @brief 获取超时后自动重新开始的最大次数
|
||||
* @param userName
|
||||
* @return
|
||||
*/
|
||||
int GetMaxTimeoutAutoRetry(const QString &userName);
|
||||
|
||||
#endif // BIOMETRICDEVICEINFO_H
|
|
@ -0,0 +1,284 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#include "biometricdeviceswidget.h"
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QComboBox>
|
||||
#include <QDebug>
|
||||
#include <QAbstractItemView>
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
|
||||
BiometricDevicesWidget::BiometricDevicesWidget(BiometricProxy *proxy,int uid, QWidget *parent)
|
||||
: QWidget(parent),
|
||||
proxy(proxy),
|
||||
m_uid(uid)
|
||||
{
|
||||
qDebug() << "BiometricDevicesWidget::BiometricDevicesWidget";
|
||||
initUI();
|
||||
if(proxy && proxy->isValid())
|
||||
{
|
||||
connect(proxy, &BiometricProxy::USBDeviceHotPlug,
|
||||
this, &BiometricDevicesWidget::onUSBDeviceHotPlug);
|
||||
updateDevice();
|
||||
}
|
||||
|
||||
resize(500, 500);
|
||||
}
|
||||
|
||||
void BiometricDevicesWidget::initUI()
|
||||
{
|
||||
|
||||
|
||||
lblPrompt = new QLabel(this);
|
||||
lblPrompt->setObjectName(QStringLiteral("lblBioetricDevicesPrompt"));
|
||||
lblPrompt->setText(tr("Please select the biometric device"));
|
||||
lblPrompt->setAlignment(Qt::AlignHCenter);
|
||||
|
||||
lblDeviceType = new QLabel(this);
|
||||
lblDeviceType->setObjectName(QStringLiteral("lblDeviceType"));
|
||||
lblDeviceType->setText(tr("Device type:"));
|
||||
lblDeviceType->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
|
||||
QStyledItemDelegate* itemDelegate = new QStyledItemDelegate();
|
||||
|
||||
cmbDeviceType = new QComboBox(this);
|
||||
cmbDeviceType->setObjectName(QStringLiteral("cmbDeviceType"));
|
||||
cmbDeviceType->setMaxVisibleItems(5);
|
||||
cmbDeviceType->setItemDelegate(itemDelegate);
|
||||
cmbDeviceType->view()->parentWidget()->setWindowFlags(Qt::Popup|Qt::FramelessWindowHint);
|
||||
cmbDeviceType->view()->parentWidget()->setAttribute(Qt::WA_TranslucentBackground);
|
||||
|
||||
connect(cmbDeviceType, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(onCmbDeviceTypeCurrentIndexChanged(int)));
|
||||
|
||||
lblDeviceName = new QLabel(this);
|
||||
lblDeviceName->setObjectName(QStringLiteral("lblDeviceName"));
|
||||
lblDeviceName->setText(tr("Device name:"));
|
||||
lblDeviceName->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
|
||||
cmbDeviceName = new QComboBox(this);
|
||||
cmbDeviceName->setObjectName(QStringLiteral("cmbDeviceName"));
|
||||
cmbDeviceName->setMaxVisibleItems(5);
|
||||
cmbDeviceName->setItemDelegate(itemDelegate);
|
||||
cmbDeviceName->view()->parentWidget()->setWindowFlags(Qt::Popup|Qt::FramelessWindowHint);
|
||||
cmbDeviceName->view()->parentWidget()->setAttribute(Qt::WA_TranslucentBackground);
|
||||
|
||||
btnOK = new QPushButton(tr("OK"), this);
|
||||
btnOK->setObjectName(QStringLiteral("OKButton"));
|
||||
btnOK->setCursor(Qt::PointingHandCursor);
|
||||
connect(btnOK, &QPushButton::clicked,
|
||||
this, &BiometricDevicesWidget::onOKButtonClicked);
|
||||
}
|
||||
|
||||
void BiometricDevicesWidget::resizeEvent(QResizeEvent */*event*/)
|
||||
{
|
||||
lblPrompt->setGeometry(0, 0, width(), 40);
|
||||
lblDeviceType->setGeometry(100, lblPrompt->geometry().bottom() + 40,
|
||||
120, 20);
|
||||
cmbDeviceType->setGeometry(100, lblDeviceType->geometry().bottom() + 15,
|
||||
300, 40);
|
||||
lblDeviceName->setGeometry(100, cmbDeviceType->geometry().bottom() + 80,
|
||||
120, 20);
|
||||
cmbDeviceName->setGeometry(100, lblDeviceName->geometry().bottom() + 15,
|
||||
300, 40);
|
||||
btnOK->setGeometry(100, cmbDeviceName->geometry().bottom() + 80, 140, 38);
|
||||
|
||||
}
|
||||
|
||||
void BiometricDevicesWidget::setUser(int uid)
|
||||
{
|
||||
m_uid = uid;
|
||||
updateDevice();
|
||||
}
|
||||
|
||||
void BiometricDevicesWidget::updateDevice()
|
||||
{
|
||||
deviceMap.clear();
|
||||
DeviceList deviceList = proxy->GetDevList();
|
||||
for(auto pDeviceInfo : deviceList)
|
||||
{
|
||||
qDebug() << *pDeviceInfo;
|
||||
if(proxy->GetUserDevFeatureCount(m_uid,pDeviceInfo->id) > 0)
|
||||
deviceMap[pDeviceInfo->deviceType].push_back(pDeviceInfo);
|
||||
}
|
||||
cmbDeviceType->clear();
|
||||
for(int type : deviceMap.keys())
|
||||
{
|
||||
QString iconPath = QString(UKUI_BIOMETRIC_IMAGES_PATH"icon/%1.png")
|
||||
.arg(DeviceType::getDeviceType(type));
|
||||
// qDebug() << iconPath;
|
||||
cmbDeviceType->addItem(QIcon(iconPath), DeviceType::getDeviceType_tr(type), type);
|
||||
}
|
||||
if(deviceMap.size() > 0)
|
||||
{
|
||||
int index = deviceMap.keys().at(0);
|
||||
setCurrentDevice(deviceMap[index].at(0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BiometricDevicesWidget::setCurrentDevice(int drvid)
|
||||
{
|
||||
DeviceInfoPtr pDeviceInfo = findDeviceById(drvid);
|
||||
if(pDeviceInfo)
|
||||
{
|
||||
setCurrentDevice(pDeviceInfo);
|
||||
}
|
||||
}
|
||||
|
||||
void BiometricDevicesWidget::setCurrentDevice(const QString &deviceName)
|
||||
{
|
||||
DeviceInfoPtr pDeviceInfo = findDeviceByName(deviceName);
|
||||
if(pDeviceInfo)
|
||||
{
|
||||
setCurrentDevice(pDeviceInfo);
|
||||
}
|
||||
}
|
||||
|
||||
void BiometricDevicesWidget::setCurrentDevice(const DeviceInfoPtr &pDeviceInfo)
|
||||
{
|
||||
this->currentDevice = pDeviceInfo;
|
||||
cmbDeviceType->setCurrentText(DeviceType::getDeviceType_tr(pDeviceInfo->deviceType));
|
||||
cmbDeviceName->setCurrentText(pDeviceInfo->shortName);
|
||||
}
|
||||
|
||||
bool BiometricDevicesWidget::deviceExists(int drvid)
|
||||
{
|
||||
return (findDeviceById(drvid) != nullptr);
|
||||
}
|
||||
|
||||
bool BiometricDevicesWidget::deviceExists(const QString &deviceName)
|
||||
{
|
||||
return (findDeviceByName(deviceName) != nullptr);
|
||||
}
|
||||
|
||||
DeviceInfoPtr BiometricDevicesWidget::findDeviceById(int drvid)
|
||||
{
|
||||
for(int type : deviceMap.keys())
|
||||
{
|
||||
DeviceList &deviceList = deviceMap[type];
|
||||
auto iter = std::find_if(deviceList.begin(), deviceList.end(),
|
||||
[&](DeviceInfoPtr ptr){
|
||||
return ptr->id == drvid;
|
||||
});
|
||||
if(iter != deviceList.end())
|
||||
{
|
||||
return *iter;
|
||||
}
|
||||
}
|
||||
return DeviceInfoPtr();
|
||||
}
|
||||
|
||||
DeviceInfoPtr BiometricDevicesWidget::findDeviceByName(const QString &name)
|
||||
{
|
||||
for(int type : deviceMap.keys())
|
||||
{
|
||||
DeviceList &deviceList = deviceMap[type];
|
||||
auto iter = std::find_if(deviceList.begin(), deviceList.end(),
|
||||
[&](DeviceInfoPtr ptr){
|
||||
return ptr->shortName == name;
|
||||
});
|
||||
if(iter != deviceList.end())
|
||||
{
|
||||
return *iter;
|
||||
}
|
||||
}
|
||||
return DeviceInfoPtr();
|
||||
}
|
||||
|
||||
void BiometricDevicesWidget::onCmbDeviceTypeCurrentIndexChanged(int index)
|
||||
{
|
||||
if(index < 0 || index >= deviceMap.keys().size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
int type = cmbDeviceType->itemData(index).toInt();
|
||||
cmbDeviceName->clear();
|
||||
for(auto &deviceInfo : deviceMap.value(type))
|
||||
{
|
||||
cmbDeviceName->addItem(deviceInfo->shortName);
|
||||
}
|
||||
}
|
||||
|
||||
void BiometricDevicesWidget::onOKButtonClicked()
|
||||
{
|
||||
int type = cmbDeviceType->currentData().toInt();
|
||||
int index = cmbDeviceName->currentIndex();
|
||||
qDebug() << type << index;
|
||||
DeviceInfoPtr deviceInfo = deviceMap.value(type).at(index);
|
||||
Q_EMIT deviceChanged(deviceInfo);
|
||||
hide();
|
||||
}
|
||||
|
||||
void BiometricDevicesWidget::onUSBDeviceHotPlug(int drvid, int action, int /*devNum*/)
|
||||
{
|
||||
int savedDeviceId = currentDevice->id;
|
||||
int savedCount = 0;
|
||||
for(int type : deviceMap.keys())
|
||||
savedCount += deviceMap.value(type).count();
|
||||
|
||||
switch(action)
|
||||
{
|
||||
case ACTION_ATTACHED:
|
||||
{
|
||||
//插入设备后,需要更新设备列表
|
||||
deviceMap.clear();
|
||||
updateDevice();
|
||||
setCurrentDevice(savedDeviceId);
|
||||
break;
|
||||
}
|
||||
case ACTION_DETACHED:
|
||||
{
|
||||
DeviceInfoPtr pDeviceInfo = findDeviceById(drvid);
|
||||
if(pDeviceInfo)
|
||||
{
|
||||
int type = pDeviceInfo->deviceType;
|
||||
deviceMap[type].removeOne(pDeviceInfo);
|
||||
int index = cmbDeviceName->findText(pDeviceInfo->shortName);
|
||||
cmbDeviceName->removeItem(index);
|
||||
|
||||
//如果该类型的设备全被移除,删除该类型相关的列表
|
||||
if(deviceMap[type].isEmpty())
|
||||
{
|
||||
deviceMap.remove(type);
|
||||
index = cmbDeviceType->findData(type);
|
||||
cmbDeviceType->removeItem(index);
|
||||
}
|
||||
}
|
||||
if(savedDeviceId != drvid)
|
||||
{
|
||||
setCurrentDevice(savedDeviceId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for(int type : deviceMap.keys())
|
||||
count += deviceMap.value(type).count();
|
||||
|
||||
//设备数量发生了变化
|
||||
if(count != savedCount)
|
||||
{
|
||||
Q_EMIT deviceCountChanged(count);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#ifndef BIOMETRICDEVICESWIDGET_H
|
||||
#define BIOMETRICDEVICESWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include "biometricproxy.h"
|
||||
|
||||
class QLabel;
|
||||
class QPushButton;
|
||||
class QComboBox;
|
||||
|
||||
|
||||
class BiometricDevicesWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit BiometricDevicesWidget(BiometricProxy *proxy,int uid,QWidget *parent = nullptr);
|
||||
void setCurrentDevice(int drvid);
|
||||
void setCurrentDevice(const QString &deviceName);
|
||||
void setCurrentDevice(const DeviceInfoPtr &pDeviceInfo);
|
||||
DeviceInfoPtr findDeviceById(int drvid);
|
||||
DeviceInfoPtr findDeviceByName(const QString &name);
|
||||
bool deviceExists(int drvid);
|
||||
bool deviceExists(const QString &deviceName);
|
||||
void setUser(int uid);
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
signals:
|
||||
void deviceChanged(const DeviceInfoPtr &pDeviceInfo);
|
||||
void deviceCountChanged(int newCount);
|
||||
|
||||
public slots:
|
||||
void onOKButtonClicked();
|
||||
|
||||
private slots:
|
||||
void onCmbDeviceTypeCurrentIndexChanged(int index);
|
||||
void onUSBDeviceHotPlug(int drvid, int action, int devNum);
|
||||
|
||||
private:
|
||||
void initUI();
|
||||
void updateDevice();
|
||||
|
||||
private:
|
||||
typedef QMap<int, QPushButton*> QButtonMap;
|
||||
|
||||
QLabel *lblPrompt;
|
||||
QLabel *lblDeviceType;
|
||||
QLabel *lblDeviceName;
|
||||
QComboBox *cmbDeviceType;
|
||||
QComboBox *cmbDeviceName;
|
||||
QPushButton *btnOK;
|
||||
QPushButton *btnCancel;
|
||||
|
||||
BiometricProxy *proxy;
|
||||
DeviceMap deviceMap;
|
||||
DeviceInfoPtr currentDevice;
|
||||
int m_uid;
|
||||
};
|
||||
|
||||
#endif // BIOMETRICDEVICESWIDGET_H
|
|
@ -0,0 +1,231 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#include "biometricproxy.h"
|
||||
#include <QDebug>
|
||||
|
||||
BiometricProxy::BiometricProxy(QObject *parent)
|
||||
: QDBusAbstractInterface(BIOMETRIC_DBUS_SERVICE,
|
||||
BIOMETRIC_DBUS_PATH,
|
||||
BIOMETRIC_DBUS_INTERFACE,
|
||||
QDBusConnection::systemBus(),
|
||||
parent)
|
||||
{
|
||||
registerMetaType();
|
||||
setTimeout(2147483647);
|
||||
}
|
||||
|
||||
QDBusPendingCall BiometricProxy::Identify(int drvid, int uid, int indexStart, int indexEnd)
|
||||
{
|
||||
QList<QVariant> argList;
|
||||
argList << drvid << uid << indexStart << indexEnd;
|
||||
return asyncCallWithArgumentList(QStringLiteral("Identify"), argList);
|
||||
}
|
||||
|
||||
int BiometricProxy::GetFeatureCount(int uid, int indexStart, int indexEnd)
|
||||
{
|
||||
QDBusMessage result = call(QStringLiteral("GetDevList"));
|
||||
if(result.type() == QDBusMessage::ErrorMessage)
|
||||
{
|
||||
qWarning() << "GetDevList error:" << result.errorMessage();
|
||||
return 0;
|
||||
}
|
||||
auto dbusArg = result.arguments().at(1).value<QDBusArgument>();
|
||||
QList<QVariant> variantList;
|
||||
dbusArg >> variantList;
|
||||
int res = 0;
|
||||
for(int i = 0; i < variantList.size(); i++)
|
||||
{
|
||||
|
||||
DeviceInfoPtr pDeviceInfo = std::make_shared<DeviceInfo>();
|
||||
|
||||
auto arg = variantList.at(i).value<QDBusArgument>();
|
||||
arg >> *pDeviceInfo;
|
||||
|
||||
QDBusMessage FeatureResult = call(QStringLiteral("GetFeatureList"),pDeviceInfo->id,uid,indexStart,indexEnd);
|
||||
if(FeatureResult.type() == QDBusMessage::ErrorMessage)
|
||||
{
|
||||
qWarning() << "GetFeatureList error:" << FeatureResult.errorMessage();
|
||||
return 0;
|
||||
}
|
||||
res += FeatureResult.arguments().takeFirst().toInt();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int BiometricProxy::StopOps(int drvid, int waiting)
|
||||
{
|
||||
QDBusReply<int> reply = call(QStringLiteral("StopOps"), drvid, waiting);
|
||||
if(!reply.isValid())
|
||||
{
|
||||
qWarning() << "StopOps error:" << reply.error();
|
||||
return -1;
|
||||
}
|
||||
return reply.value();
|
||||
}
|
||||
|
||||
int BiometricProxy::GetFrameFd(int drvid)
|
||||
{
|
||||
QDBusInterface *interface = new QDBusInterface("org.demo.pictureshow",
|
||||
"/org/demo/pictureshow",
|
||||
"org.demo.pictureshow",
|
||||
QDBusConnection::sessionBus());
|
||||
|
||||
QDBusReply<QDBusUnixFileDescriptor> reply = interface->call("SendFrame");
|
||||
|
||||
//QDBusReply<QDBusUnixFileDescriptor> reply = call(QStringLiteral("GetFrameFd"), drvid);
|
||||
if(!reply.isValid())
|
||||
{
|
||||
qWarning() << "StopOps error:" << reply.error();
|
||||
return -1;
|
||||
}else{
|
||||
qDebug()<<"111111111111111111111111111111111111111111"<<reply.value().fileDescriptor();
|
||||
return reply.value().fileDescriptor();
|
||||
}
|
||||
}
|
||||
|
||||
DeviceList BiometricProxy::GetDevList()
|
||||
{
|
||||
QDBusMessage result = call(QStringLiteral("GetDevList"));
|
||||
if(result.type() == QDBusMessage::ErrorMessage)
|
||||
{
|
||||
qWarning() << "GetDevList error:" << result.errorMessage();
|
||||
return DeviceList();
|
||||
}
|
||||
auto dbusArg = result.arguments().at(1).value<QDBusArgument>();
|
||||
QList<QVariant> variantList;
|
||||
DeviceList deviceList;
|
||||
dbusArg >> variantList;
|
||||
for(int i = 0; i < variantList.size(); i++)
|
||||
{
|
||||
DeviceInfoPtr pDeviceInfo = std::make_shared<DeviceInfo>();
|
||||
|
||||
auto arg = variantList.at(i).value<QDBusArgument>();
|
||||
arg >> *pDeviceInfo;
|
||||
|
||||
deviceList.push_back(pDeviceInfo);
|
||||
}
|
||||
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
int BiometricProxy::GetUserDevCount(int uid)
|
||||
{
|
||||
QDBusMessage result = call(QStringLiteral("GetDevList"));
|
||||
if(result.type() == QDBusMessage::ErrorMessage)
|
||||
{
|
||||
qWarning() << "GetDevList error:" << result.errorMessage();
|
||||
return 0;
|
||||
}
|
||||
auto dbusArg = result.arguments().at(1).value<QDBusArgument>();
|
||||
QList<QVariant> variantList;
|
||||
DeviceList deviceList;
|
||||
dbusArg >> variantList;
|
||||
for(int i = 0; i < variantList.size(); i++)
|
||||
{
|
||||
DeviceInfoPtr pDeviceInfo = std::make_shared<DeviceInfo>();
|
||||
|
||||
auto arg = variantList.at(i).value<QDBusArgument>();
|
||||
arg >> *pDeviceInfo;
|
||||
|
||||
int count = GetUserDevFeatureCount(uid,pDeviceInfo->id);
|
||||
|
||||
if(count>0)
|
||||
deviceList.push_back(pDeviceInfo);
|
||||
}
|
||||
|
||||
return deviceList.count();
|
||||
}
|
||||
|
||||
int BiometricProxy::GetUserDevFeatureCount(int uid,int drvid)
|
||||
{
|
||||
StopOps(drvid);
|
||||
QDBusMessage FeatureResult = call(QStringLiteral("GetFeatureList"),drvid,uid,0,-1);
|
||||
if(FeatureResult.type() == QDBusMessage::ErrorMessage)
|
||||
{
|
||||
qWarning() << "GetFeatureList error:" << FeatureResult.errorMessage();
|
||||
return 0;
|
||||
}
|
||||
return FeatureResult.arguments().takeFirst().toInt();
|
||||
}
|
||||
|
||||
int BiometricProxy::GetDevCount()
|
||||
{
|
||||
QDBusMessage result = call(QStringLiteral("GetDevList"));
|
||||
if(result.type() == QDBusMessage::ErrorMessage)
|
||||
{
|
||||
qWarning() << "GetDevList error:" << result.errorMessage();
|
||||
return 0;
|
||||
}
|
||||
int count = result.arguments().at(0).value<int>();
|
||||
return count;
|
||||
}
|
||||
|
||||
QString BiometricProxy::GetDevMesg(int drvid)
|
||||
{
|
||||
QDBusMessage result = call(QStringLiteral("GetDevMesg"), drvid);
|
||||
if(result.type() == QDBusMessage::ErrorMessage)
|
||||
{
|
||||
qWarning() << "GetDevMesg error:" << result.errorMessage();
|
||||
return "";
|
||||
}
|
||||
return result.arguments().at(0).toString();
|
||||
}
|
||||
|
||||
QString BiometricProxy::GetNotifyMesg(int drvid)
|
||||
{
|
||||
QDBusMessage result = call(QStringLiteral("GetNotifyMesg"), drvid);
|
||||
if(result.type() == QDBusMessage::ErrorMessage)
|
||||
{
|
||||
qWarning() << "GetNotifyMesg error:" << result.errorMessage();
|
||||
return "";
|
||||
}
|
||||
return result.arguments().at(0).toString();
|
||||
}
|
||||
|
||||
QString BiometricProxy::GetOpsMesg(int drvid)
|
||||
{
|
||||
QDBusMessage result = call(QStringLiteral("GetOpsMesg"), drvid);
|
||||
if(result.type() == QDBusMessage::ErrorMessage)
|
||||
{
|
||||
qWarning() << "GetOpsMesg error:" << result.errorMessage();
|
||||
return "";
|
||||
}
|
||||
return result.arguments().at(0).toString();
|
||||
}
|
||||
|
||||
StatusReslut BiometricProxy::UpdateStatus(int drvid)
|
||||
{
|
||||
StatusReslut status;
|
||||
QDBusMessage result = call(QStringLiteral("UpdateStatus"), drvid);
|
||||
if(result.type() == QDBusMessage::ErrorMessage)
|
||||
{
|
||||
qWarning() << "UpdateStatus error:" << result.errorMessage();
|
||||
status.result = -1;
|
||||
return status;
|
||||
}
|
||||
|
||||
status.result = result.arguments().at(0).toInt();
|
||||
status.enable = result.arguments().at(1).toInt();
|
||||
status.devNum = result.arguments().at(2).toInt();
|
||||
status.devStatus = result.arguments().at(3).toInt();
|
||||
status.opsStatus = result.arguments().at(4).toInt();
|
||||
status.notifyMessageId = result.arguments().at(5).toInt();
|
||||
|
||||
return status;
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#ifndef BIOMETRICPROXY_H
|
||||
#define BIOMETRICPROXY_H
|
||||
|
||||
#include <QDBusAbstractInterface>
|
||||
#include "biometricdeviceinfo.h"
|
||||
|
||||
/**
|
||||
* @brief UpdateStauts调用返回的结果
|
||||
*/
|
||||
struct StatusReslut
|
||||
{
|
||||
int result;
|
||||
int enable;
|
||||
int devNum;
|
||||
int devStatus;
|
||||
int opsStatus;
|
||||
int notifyMessageId;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief USB设备插拔动作
|
||||
*/
|
||||
enum USBDeviceAction
|
||||
{
|
||||
ACTION_ATTACHED = 1,
|
||||
ACTION_DETACHED = -1
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief DBus代理类,负责调用对应的DBus接口
|
||||
*/
|
||||
class BiometricProxy : public QDBusAbstractInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit BiometricProxy(QObject *parent = nullptr);
|
||||
|
||||
public Q_SLOTS:
|
||||
/**
|
||||
* @brief 使用指定id的设备进行用户认证
|
||||
* @param drvid 驱动(设备)id
|
||||
* @param uid 用户id
|
||||
* @param indexStart 用于认证的特征索引范围
|
||||
* @param indexEnd
|
||||
* @return 结果:<int result, int uid> (结果,用户id)
|
||||
*/
|
||||
QDBusPendingCall Identify(int drvid, int uid, int indexStart = 0, int indexEnd = -1);
|
||||
/**
|
||||
* @brief 终止设备上正在进行的操作
|
||||
* @param drvid 设备id
|
||||
* @param waiting 等待时间(秒)
|
||||
* @return
|
||||
*/
|
||||
int StopOps(int drvid, int waiting = 3000);
|
||||
/**
|
||||
* @brief 获取当前用户已连接设备对应特征数目
|
||||
* @param uid 用户id
|
||||
* @param indexStart 用于认证的特征索引范围
|
||||
* @param indexEnd
|
||||
* @return
|
||||
*/
|
||||
int GetFeatureCount(int uid, int indexStart = 0, int indexEnd = -1);
|
||||
|
||||
/**
|
||||
* @brief 获取已连接的设备列表
|
||||
* @return
|
||||
*/
|
||||
DeviceList GetDevList();
|
||||
/**
|
||||
* @brief 获取设备数量
|
||||
* @return
|
||||
*/
|
||||
int GetDevCount();
|
||||
/**
|
||||
* @brief 获取设备消息
|
||||
* @param drvid 驱动id
|
||||
* @return
|
||||
*/
|
||||
QString GetDevMesg(int drvid);
|
||||
/**
|
||||
* @brief GetNotifyMesg 获取通知消息
|
||||
* @param drvid 驱动id
|
||||
* @return
|
||||
*/
|
||||
QString GetNotifyMesg(int drvid);
|
||||
/**
|
||||
* @brief GetOpsMesg 获取操作消息
|
||||
* @param drvid 驱动id
|
||||
* @return
|
||||
*/
|
||||
QString GetOpsMesg(int drvid);
|
||||
/**
|
||||
* @brief UpdateStatus 获取更新的设备状态
|
||||
* @param drvid 驱动id
|
||||
* @return 结果:<int result, int enable, int devNum,
|
||||
* int devStatus, int opsStatus, notifyMessageId, ...>
|
||||
*/
|
||||
StatusReslut UpdateStatus(int drvid);
|
||||
int GetUserDevCount(int uid);
|
||||
int GetUserDevFeatureCount(int uid,int drvid);
|
||||
int GetFrameFd(int drvid);
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* @brief 设备状态发生变化
|
||||
* @param drvid 设备id
|
||||
* @param status 设备状态
|
||||
*/
|
||||
void StatusChanged(int drvid, int status);
|
||||
/**
|
||||
* @brief USB设备热插拔
|
||||
* @param drvid 设备id
|
||||
* @param action 插拔动作(1:插入,-1:拔出)
|
||||
* @param deviceNum 插拔动作后该驱动拥有的设备数量
|
||||
*/
|
||||
void USBDeviceHotPlug(int drvid, int action, int deviceNum);
|
||||
void FrameWritten(int drvid);
|
||||
};
|
||||
|
||||
#endif // BIOMETRICPROXY_H
|
|
@ -0,0 +1,71 @@
|
|||
/* giodbus.cpp
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
|
||||
#include "giodbus.h"
|
||||
#include <gio/gio.h>
|
||||
#include <gio-unix-2.0/gio/gunixfdlist.h>
|
||||
#include <glib.h>
|
||||
|
||||
int get_server_gvariant_stdout (int drvid)
|
||||
{
|
||||
GDBusMessage *method_call_message;
|
||||
GDBusMessage *method_reply_message;
|
||||
GUnixFDList *fd_list;
|
||||
GError **error = NULL;
|
||||
|
||||
gint fd,dup_fd;
|
||||
const gchar * response;
|
||||
fd = -1;
|
||||
dup_fd = -1;
|
||||
method_call_message = NULL;
|
||||
method_reply_message = NULL;
|
||||
GDBusConnection *con = g_bus_get_sync(G_BUS_TYPE_SYSTEM,NULL,NULL);
|
||||
method_call_message = g_dbus_message_new_method_call ("org.ukui.Biometric",
|
||||
"/org/ukui/Biometric",
|
||||
"org.ukui.Biometric",
|
||||
"GetFrameFd");
|
||||
|
||||
g_dbus_message_set_body (method_call_message, g_variant_new ("(i)", drvid));
|
||||
method_reply_message = g_dbus_connection_send_message_with_reply_sync (con,
|
||||
method_call_message,
|
||||
G_DBUS_SEND_MESSAGE_FLAGS_NONE,
|
||||
-1,
|
||||
NULL, /* out_serial */
|
||||
NULL, /* cancellable */
|
||||
error);
|
||||
if (method_reply_message == NULL)
|
||||
goto out;
|
||||
|
||||
if (g_dbus_message_get_message_type (method_reply_message) == G_DBUS_MESSAGE_TYPE_ERROR)
|
||||
{
|
||||
g_dbus_message_to_gerror (method_reply_message, error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fd_list = g_dbus_message_get_unix_fd_list(method_reply_message);
|
||||
fd = g_unix_fd_list_get(fd_list,0,error);
|
||||
dup_fd = dup(fd);
|
||||
|
||||
|
||||
out:
|
||||
g_object_unref (method_call_message);
|
||||
g_object_unref (method_reply_message);
|
||||
return dup_fd;
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/* giodbus.h
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
|
||||
#ifndef GIODBUS_H
|
||||
#define GIODBUS_H
|
||||
|
||||
int get_server_gvariant_stdout(int drvid);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include "biometricproxy.h"
|
||||
#include "biometricauthwidget.h"
|
||||
#include "biometricdeviceswidget.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
|
||||
BiometricProxy proxy;
|
||||
BiometricAuthWidget biometricAuthWidget(&proxy);
|
||||
biometricAuthWidget.hide();
|
||||
BiometricDevicesWidget biometricDeviceWidget(&proxy);
|
||||
QObject::connect(&biometricDeviceWidget, &BiometricDevicesWidget::deviceChanged,
|
||||
&a, [&](const DeviceInfoPtr &pDeviceInfo){
|
||||
biometricAuthWidget.startAuth(pDeviceInfo, 1000);
|
||||
biometricAuthWidget.show();
|
||||
});
|
||||
QObject::connect(&biometricDeviceWidget, &BiometricDevicesWidget::deviceCountChanged,
|
||||
&a, [&](int count){
|
||||
qDebug() << "device count changed: " << count;
|
||||
});
|
||||
biometricDeviceWidget.show();
|
||||
|
||||
return a.exec();
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
find_package(Qt5 COMPONENTS Core Widgets REQUIRED)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
qt5_add_resources(VirtualKeyboard_SRC
|
||||
src/keyboard.qrc)
|
||||
|
||||
set(VirtualKeyboard_SRC
|
||||
${VirtualKeyboard_SRC}
|
||||
src/cursormonitor.cpp
|
||||
src/keyboardwidget.cpp
|
||||
src/virtualkeyboard.cpp
|
||||
src/x11keyboard.cpp
|
||||
src/keyboard.qrc)
|
||||
|
||||
include_directories(
|
||||
${Qt5Core_INCLUDE_DIRS}
|
||||
${Qt5Widgets_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
add_library(VirtualKeyboard STATIC ${VirtualKeyboard_SRC})
|
||||
target_link_libraries(VirtualKeyboard Qt5::Core Qt5::Widgets)
|
|
@ -0,0 +1 @@
|
|||
A simple virtual keyboard in X11
|
|
@ -0,0 +1,19 @@
|
|||
SOURCES += \
|
||||
$$PWD/src/keyboardwidget.cpp \
|
||||
$$PWD/src/x11keyboard.cpp \
|
||||
$$PWD/src/cursormonitor.cpp \
|
||||
$$PWD/src/virtualkeyboard.cpp
|
||||
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/src/keyboardwidget.h \
|
||||
$$PWD/src/x11keyboard.h \
|
||||
$$PWD/src/cursormonitor.h \
|
||||
$$PWD/src/virtualkeyboard.h
|
||||
|
||||
FORMS += \
|
||||
$$PWD/src/keyboardwidget.ui
|
||||
|
||||
|
||||
RESOURCES += \
|
||||
$$PWD/src/keyboard.qrc
|
|
@ -0,0 +1,32 @@
|
|||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2018-10-12T16:43:42
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core gui
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
TARGET = VirtualKeyboard
|
||||
TEMPLATE = app
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any feature of Qt which has been marked as deprecated (the exact warnings
|
||||
# depend on your compiler). Please consult the documentation of the
|
||||
# deprecated API in order to know how to port your code away from it.
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
# You can also make your code fail to compile if you use deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
CONFIG += link_pkgconfig debug
|
||||
|
||||
PKGCONFIG += xtst x11
|
||||
|
||||
include(VirtualKeyboard.pri)
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/src/main.cpp
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#include "cursormonitor.h"
|
||||
#include <X11/Xlib.h>
|
||||
#include <QPoint>
|
||||
|
||||
CursorMonitor::CursorMonitor(QObject *parent) : QThread(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CursorMonitor::run()
|
||||
{
|
||||
Display *display;
|
||||
XEvent xevent;
|
||||
Window window;
|
||||
|
||||
display = XOpenDisplay(NULL);
|
||||
|
||||
|
||||
window = DefaultRootWindow(display);
|
||||
XAllowEvents(display, AsyncBoth, CurrentTime);
|
||||
|
||||
XGrabPointer(display,
|
||||
window,
|
||||
1,
|
||||
PointerMotionMask | ButtonPressMask | ButtonReleaseMask ,
|
||||
GrabModeAsync,
|
||||
GrabModeAsync,
|
||||
None,
|
||||
None,
|
||||
CurrentTime);
|
||||
|
||||
while(1) {
|
||||
XNextEvent(display, &xevent);
|
||||
|
||||
switch (xevent.type) {
|
||||
case MotionNotify:
|
||||
//printf("Mouse move : [%d, %d]\n", xevent.xmotion.x_root, xevent.xmotion.y_root);
|
||||
Q_EMIT cursorPosChanged(QPoint(xevent.xmotion.x_root, xevent.xmotion.y_root));
|
||||
break;
|
||||
case ButtonPress:
|
||||
// printf("Button pressed : %s\n", key_name[xevent.xbutton.button - 1]);
|
||||
break;
|
||||
case ButtonRelease:
|
||||
// printf("Button released : %s\n", key_name[xevent.xbutton.button - 1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#ifndef CURSORMONITOR_H
|
||||
#define CURSORMONITOR_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
|
||||
class CursorMonitor : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CursorMonitor(QObject *parent = nullptr);
|
||||
void run();
|
||||
|
||||
Q_SIGNALS:
|
||||
void cursorPosChanged(const QPoint& pos);
|
||||
};
|
||||
|
||||
#endif // CURSORMONITOR_H
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<g id="默认">
|
||||
<path fill="#FFFFFF" d="M41.1,9c3.2,0,5.9,2.6,5.9,5.9v20.2c0,3.2-2.6,5.9-5.9,5.9H18.3L4,25L18.3,9H41.1 M41.1,6H16.9L0,25
|
||||
l16.9,19h24.2c4.9,0,8.9-4,8.9-8.9V14.9C50,10,46,6,41.1,6z"/>
|
||||
|
||||
<line fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-miterlimit="10" x1="40" y1="15" x2="20" y2="35"/>
|
||||
|
||||
<line fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-miterlimit="10" x1="20" y1="15" x2="40" y2="35"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 837 B |
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<g id="点击" opacity="0.6">
|
||||
<path fill="#FFFFFF" d="M41.1,9c3.2,0,5.9,2.6,5.9,5.9v20.2c0,3.2-2.6,5.9-5.9,5.9H18.3L4,25L18.3,9H41.1 M41.1,6H16.9L0,25
|
||||
l16.9,19h24.2c4.9,0,8.9-4,8.9-8.9V14.9C50,10,46,6,41.1,6z"/>
|
||||
|
||||
<line fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-miterlimit="10" x1="40" y1="15" x2="20" y2="35"/>
|
||||
|
||||
<line fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-miterlimit="10" x1="20" y1="15" x2="40" y2="35"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 851 B |
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M25,6.5L43.3,27H35v17H15V27H6.7L25,6.5 M22.8,4.5L3,26.7C1.8,28,2.7,30,4.5,30H12v15c0,1.1,0.9,2,2,2h22
|
||||
c1.1,0,2-0.9,2-2V30h7.5c1.7,0,2.6-2,1.5-3.3L27.2,4.5C26,3.2,24,3.2,22.8,4.5z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 621 B |
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<g id="点击" opacity="0.6">
|
||||
<path fill="#FFFFFF" d="M25,6.5L43.3,27H35v17H15V27H6.7L25,6.5 M22.8,4.5L3,26.7C1.8,28,2.7,30,4.5,30H12v15c0,1.1,0.9,2,2,2h22
|
||||
c1.1,0,2-0.9,2-2V30h7.5c1.7,0,2.6-2,1.5-3.3L27.2,4.5C26,3.2,24,3.2,22.8,4.5z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 599 B |
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<path fill="#67B204" d="M25,6.5L43.3,27H35v17H15V27H6.7L25,6.5 M22.8,4.5L3,26.7C1.8,28,2.7,30,4.5,30H12v15c0,1.1,0.9,2,2,2h22
|
||||
c1.1,0,2-0.9,2-2V30h7.5c1.7,0,2.6-2,1.5-3.3L27.2,4.5C26,3.2,24,3.2,22.8,4.5z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 560 B |
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<path fill="#4A692A" d="M25,6.5L43.3,27H35v17H15V27H6.7L25,6.5 M22.8,4.5L3,26.7C1.8,28,2.7,30,4.5,30H12v15c0,1.1,0.9,2,2,2h22
|
||||
c1.1,0,2-0.9,2-2V30h7.5c1.7,0,2.6-2,1.5-3.3L27.2,4.5C26,3.2,24,3.2,22.8,4.5z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 560 B |
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<g id="键盘">
|
||||
<g id="默认">
|
||||
<path fill="#FFFFFF" d="M47,5v29H3V5H47 M50,2H0v35h50V2z"/>
|
||||
<rect x="8" y="10" fill="#FFFFFF" width="3" height="3"/>
|
||||
<rect x="15" y="10" fill="#FFFFFF" width="3" height="3"/>
|
||||
<rect x="23" y="10" fill="#FFFFFF" width="3" height="3"/>
|
||||
<rect x="31" y="10" fill="#FFFFFF" width="3" height="3"/>
|
||||
<rect x="39" y="10" fill="#FFFFFF" width="3" height="3"/>
|
||||
<rect x="8" y="18" fill="#FFFFFF" width="3" height="3"/>
|
||||
<rect x="15" y="18" fill="#FFFFFF" width="3" height="3"/>
|
||||
<rect x="23" y="18" fill="#FFFFFF" width="3" height="3"/>
|
||||
<rect x="31" y="18" fill="#FFFFFF" width="3" height="3"/>
|
||||
<rect x="39" y="18" fill="#FFFFFF" width="3" height="3"/>
|
||||
<rect x="13" y="26" fill="#FFFFFF" width="24" height="3"/>
|
||||
</g>
|
||||
</g>
|
||||
<polygon fill="#FFFFFF" points="29,41 25,45 21,41 18,41 25,48 32,41 "/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<g id="键盘" opacity="0.6">
|
||||
<g id="默认">
|
||||
<path fill="#FFFFFF" d="M47,5v29H3V5H47 M50,2H0v35h50V2z"/>
|
||||
<rect x="8" y="10" fill="#FFFFFF" width="3" height="3"/>
|
||||
<rect x="15" y="10" fill="#FFFFFF" width="3" height="3"/>
|
||||
<rect x="23" y="10" fill="#FFFFFF" width="3" height="3"/>
|
||||
<rect x="31" y="10" fill="#FFFFFF" width="3" height="3"/>
|
||||
<rect x="39" y="10" fill="#FFFFFF" width="3" height="3"/>
|
||||
<rect x="8" y="18" fill="#FFFFFF" width="3" height="3"/>
|
||||
<rect x="15" y="18" fill="#FFFFFF" width="3" height="3"/>
|
||||
<rect x="23" y="18" fill="#FFFFFF" width="3" height="3"/>
|
||||
<rect x="31" y="18" fill="#FFFFFF" width="3" height="3"/>
|
||||
<rect x="39" y="18" fill="#FFFFFF" width="3" height="3"/>
|
||||
<rect x="13" y="26" fill="#FFFFFF" width="24" height="3"/>
|
||||
</g>
|
||||
</g>
|
||||
<polygon opacity="0.6" fill="#FFFFFF" enable-background="new " points="29,41 25,45 21,41 18,41 25,48 32,41 "/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<title>画板 15</title>
|
||||
<g id="下">
|
||||
<polygon id="默认" fill="#FFFFFF" points="25,32 38,17 12,17 "/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 466 B |
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<polygon id="点击" opacity="0.6" fill="#FFFFFF" enable-background="new " points="25,32 38,17 12,17 "/>
|
||||
</svg>
|
After Width: | Height: | Size: 460 B |
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 70 50" enable-background="new 0 0 70 50" xml:space="preserve">
|
||||
<path display="none" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-miterlimit="10" d="M36.5,9.5h2c5.5,0,10,4.5,10,10l0,0
|
||||
c0,5.5-4.5,10-10,10H5"/>
|
||||
<polyline fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
|
||||
21,16 3,29.5 21,43 "/>
|
||||
<path fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-miterlimit="10" d="M50,12.5h12.7
|
||||
c3.3,0,6,2.7,6,6v4.8c0,3.3-2.7,6-6,6H5"/>
|
||||
</svg>
|
After Width: | Height: | Size: 828 B |
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" opacity="0.6" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
x="0px" y="0px" viewBox="0 0 70 50" enable-background="new 0 0 70 50" xml:space="preserve">
|
||||
<polyline opacity="0.6" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" enable-background="new " points="
|
||||
21,16 3,29.5 21,43 "/>
|
||||
<path opacity="0.6" fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" enable-background="new " d="
|
||||
M50,12.5h12.7c3.3,0,6,2.7,6,6v4.8c0,3.3-2.7,6-6,6H5"/>
|
||||
</svg>
|
After Width: | Height: | Size: 794 B |
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="左" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<title>画板 19</title>
|
||||
<polygon id="默认" fill="#FFFFFF" points="18,25 33,12 33,38 "/>
|
||||
</svg>
|
After Width: | Height: | Size: 439 B |
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="左" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<title>画板 20</title>
|
||||
<polygon id="点击" opacity="0.6" fill="#FFFFFF" enable-background="new " points="18,25 33,12 33,38 "/>
|
||||
</svg>
|
After Width: | Height: | Size: 481 B |
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<polygon id="默认" fill="#FFFFFF" points="33,25 18,12 18,38 "/>
|
||||
</svg>
|
After Width: | Height: | Size: 418 B |
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<polygon id="点击" opacity="0.6" fill="#FFFFFF" enable-background="new " points="33,25 18,12 18,38 "/>
|
||||
</svg>
|
After Width: | Height: | Size: 460 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50"><defs><style>.cls-1{fill:#fff;}</style></defs><title>画板 11</title><g id="优麒麟"><path id="默认" class="cls-1" d="M25,6A19,19,0,1,0,44,25,19,19,0,0,0,25,6Zm7,4.48a2.75,2.75,0,1,1-2.75,2.76A2.75,2.75,0,0,1,32,10.48ZM25.11,13a12.12,12.12,0,0,1,3.26.45,3.66,3.66,0,0,0,5.29,3.08A12.08,12.08,0,0,1,37.2,24.2l-4.27.06a7.86,7.86,0,0,0-11-6.33l-2.19-3.68A12.07,12.07,0,0,1,25.11,13Zm3.26,13.91.6,1.21L27.8,29.2l.08.91H26.24l1.27-1.81-.44-.54-1.23,1v.64l-1.59,0,1-.95,1-1.19-.84-.58-.86.44-1.17.46-1-.18-.63,1-.2,1.39H20l1.12-1.31-.33-.78-.25-1.54-.81-2,1.46-2.7,1.35-.83L24,19.11l-.4,1,.22,0,1.53-1.54-.65,1.9L25,21.91l-1,1.35,1.49,1.09,2.08.83,1.48-.78.87-1.27,1.42-.44-.26,1.85-.91.32-.67-.13-1.21.69Zm-17.08.88A2.75,2.75,0,1,1,14,25a2.75,2.75,0,0,1-2.75,2.75h0Zm2.06.28a3.67,3.67,0,0,0,0-6,12.14,12.14,0,0,1,5-7l2.18,3.67a7.86,7.86,0,0,0-.11,12.72l-2.09,3.74A12.14,12.14,0,0,1,13.36,28.07ZM32.08,39.54a2.75,2.75,0,1,1,2.75-2.75,2.75,2.75,0,0,1-2.75,2.75Zm1.73-6a3.67,3.67,0,0,0-5.4,3.22,12.11,12.11,0,0,1-8.7-.81l2.08-3.73a7.86,7.86,0,0,0,11.15-6.4l4.27-.06a12.08,12.08,0,0,1-3.4,7.77Z"/></g></svg>
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50"><defs><style>.cls-1{fill:#fff;opacity:0.4;}</style></defs><title>画板 12</title><g id="优麒麟"><path id="点击" class="cls-1" d="M25,6A19,19,0,1,0,44,25,19,19,0,0,0,25,6Zm7,4.48a2.75,2.75,0,1,1-2.75,2.76A2.75,2.75,0,0,1,32,10.48ZM25.11,13a12.12,12.12,0,0,1,3.26.45,3.66,3.66,0,0,0,5.29,3.08A12.08,12.08,0,0,1,37.2,24.2l-4.27.06a7.86,7.86,0,0,0-11-6.33l-2.19-3.68A12.07,12.07,0,0,1,25.11,13Zm3.26,13.91.6,1.21L27.8,29.2l.08.91H26.24l1.27-1.81-.44-.54-1.23,1v.64l-1.59,0,1-.95,1-1.19-.84-.58-.86.44-1.17.46-1-.18-.63,1-.2,1.39H20l1.12-1.31-.33-.78-.25-1.54-.81-2,1.46-2.7,1.35-.83L24,19.11l-.4,1,.22,0,1.53-1.54-.65,1.9L25,21.91l-1,1.35,1.49,1.09,2.08.83,1.48-.78.87-1.27,1.42-.44-.26,1.85-.91.32-.67-.13-1.21.69Zm-17.08.88A2.75,2.75,0,1,1,14,25a2.75,2.75,0,0,1-2.75,2.75h0Zm2.06.28a3.67,3.67,0,0,0,0-6,12.14,12.14,0,0,1,5-7l2.18,3.67a7.86,7.86,0,0,0-.11,12.72l-2.09,3.74A12.14,12.14,0,0,1,13.36,28.07ZM32.08,39.54a2.75,2.75,0,1,1,2.75-2.75,2.75,2.75,0,0,1-2.75,2.75Zm1.73-6a3.67,3.67,0,0,0-5.4,3.22,12.11,12.11,0,0,1-8.7-.81l2.08-3.73a7.86,7.86,0,0,0,11.15-6.4l4.27-.06a12.08,12.08,0,0,1-3.4,7.77Z"/></g></svg>
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<title>画板 13</title>
|
||||
<g id="上">
|
||||
<polygon id="默认" fill="#FFFFFF" points="25,17 12,32 38,32 "/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 466 B |
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
|
||||
<polygon id="默认" opacity="0.6" fill="#FFFFFF" enable-background="new " points="25,17 12,32 38,32 "/>
|
||||
</svg>
|
After Width: | Height: | Size: 460 B |
|
@ -0,0 +1,27 @@
|
|||
<RCC>
|
||||
<qresource prefix="/qss">
|
||||
<file>keyboard.qss</file>
|
||||
</qresource>
|
||||
<qresource prefix="/images">
|
||||
<file>images/backspace_click.svg</file>
|
||||
<file>images/backspace.svg</file>
|
||||
<file>images/capslock_click.svg</file>
|
||||
<file>images/capslock_hl.svg</file>
|
||||
<file>images/capslock.svg</file>
|
||||
<file>images/down_click.svg</file>
|
||||
<file>images/down.svg</file>
|
||||
<file>images/enter_click.svg</file>
|
||||
<file>images/enter.svg</file>
|
||||
<file>images/left_click.svg</file>
|
||||
<file>images/left.svg</file>
|
||||
<file>images/right_click.svg</file>
|
||||
<file>images/right.svg</file>
|
||||
<file>images/super_click.svg</file>
|
||||
<file>images/super.svg</file>
|
||||
<file>images/up.svg</file>
|
||||
<file>images/close_click.svg</file>
|
||||
<file>images/close.svg</file>
|
||||
<file>images/capslock_hl_click.svg</file>
|
||||
<file>images/up_click.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -0,0 +1,37 @@
|
|||
QPushButton
|
||||
{
|
||||
border: none;
|
||||
font: 24px;
|
||||
color: white;
|
||||
background: #35322f;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
QPushButton::pressed
|
||||
{
|
||||
color: gray;
|
||||
background: #2a2826;
|
||||
}
|
||||
|
||||
#btn_backspace, #btn_enter, #btn_shift_l,
|
||||
#btn_shift_r, #btn_ctrl_l, #btn_ctrl_r,
|
||||
#btn_alt_l, #btn_alt_r, #btn_super
|
||||
{
|
||||
font: 16px;
|
||||
background: #1e1b18
|
||||
}
|
||||
|
||||
#btn_backspace::pressed, #btn_enter::pressed, #btn_shift_l::pressed,
|
||||
#btn_shift_r::pressed, #btn_ctrl_l::pressed, #btn_ctrl_r::pressed,
|
||||
#btn_alt_l::pressed, #btn_alt_r::pressed, #btn_super::pressed
|
||||
{
|
||||
background: #181613;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
#btn_letter, #btn_symbol, #btn_number,
|
||||
#btn_insert, #btn_delete, #btn_home,
|
||||
#btn_end, #btn_pgup, #btn_pgdn, #btn_close
|
||||
{
|
||||
font: 16px;
|
||||
}
|
|
@ -0,0 +1,459 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#include "keyboardwidget.h"
|
||||
#include "ui_keyboardwidget.h"
|
||||
#include <QDebug>
|
||||
#include <QMap>
|
||||
#include <QVector>
|
||||
|
||||
#define SYMBOL_KEY_COUNT 29
|
||||
#define SYMBOL_PAGE_COUNT 2
|
||||
|
||||
#define BUTTON_BG "QPushButton{background:#1E1B18}"
|
||||
#define BUTTON_BG_PRESSED "QPushButton{background: #181613;}"
|
||||
#define BUTTON_BG_HL "QPushButton{background:#80c342}"
|
||||
#define BUTTON_BG_HL_PRESSED "QPushButton{background:#486E25}"
|
||||
|
||||
|
||||
QChar symbols[SYMBOL_PAGE_COUNT][SYMBOL_KEY_COUNT] =
|
||||
{ {'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p',
|
||||
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l',
|
||||
'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/'},
|
||||
{'!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
|
||||
'`', '-', '=', '[', ']', '\\', '|', '{', '}',
|
||||
'~','<', '>', ':', ';', '\'', '"', '_', '+', '?'}};
|
||||
|
||||
|
||||
KeyboardWidget::KeyboardWidget(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::KeyboardWidget),
|
||||
capsLock(false),
|
||||
isShift(false),
|
||||
page(0)
|
||||
{
|
||||
vKeyboard = new X11Keyboard(this);
|
||||
connect(this, SIGNAL(keyPressed(QChar)),
|
||||
vKeyboard, SLOT(onKeyPressed(QChar)));
|
||||
connect(this, SIGNAL(keyPressed(FuncKey::FUNCKEY)),
|
||||
vKeyboard, SLOT(onKeyPressed(FuncKey::FUNCKEY)));
|
||||
|
||||
ui->setupUi(this);
|
||||
bindSingal();
|
||||
setDefaultIcon();
|
||||
}
|
||||
|
||||
KeyboardWidget::~KeyboardWidget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void KeyboardWidget::resizeEvent(QResizeEvent */*event*/)
|
||||
{
|
||||
int w = width();
|
||||
int h = height();
|
||||
int mainLeftMargin = ui->hl_main->contentsMargins().left();
|
||||
int mainRightMargin = ui->hl_main->contentsMargins().right();
|
||||
int mainTopMargin = ui->hl_main->contentsMargins().left();
|
||||
int mainBottomMargin = ui->hl_main->contentsMargins().right();
|
||||
int mainSpacing = ui->hl_main->spacing();
|
||||
int itemSpacing = ui->hl_1->spacing();
|
||||
|
||||
int btnWidthCount = w - 11 * itemSpacing - mainSpacing- mainLeftMargin - mainRightMargin;
|
||||
int btnHeightCount = h - 3 * itemSpacing - mainTopMargin - mainBottomMargin;
|
||||
double btnWidth = btnWidthCount / 12;
|
||||
double btnHeight = btnHeightCount / 4;
|
||||
for(int i = 0; i <= 28; i++) {
|
||||
QString btnObjName = "btn_" + QString::number(i);
|
||||
QPushButton *btn = ui->page_letter->findChild<QPushButton*>(btnObjName);
|
||||
btn->setFixedSize(btnWidth, btnHeight);
|
||||
}
|
||||
ui->btn_ctrl_l->setFixedSize(btnWidth * 1.3, btnHeight);
|
||||
ui->btn_ctrl_r->setFixedSize(btnWidth * 1.3, btnHeight);
|
||||
ui->btn_alt_l->setFixedSize(btnWidth, btnHeight);
|
||||
ui->btn_alt_r->setFixedSize(btnWidth, btnHeight);
|
||||
ui->btn_super->setFixedSize(btnWidth, btnHeight);
|
||||
ui->btn_shift_l->setFixedSize(btnWidth, btnHeight);
|
||||
ui->btn_shift_r->setFixedHeight(btnHeight);
|
||||
ui->spacer_2->changeSize(btnWidth / 2, 20);
|
||||
|
||||
|
||||
for(int i = 1; i <= 9; i++) {
|
||||
QString btnObjName = "btn_num_" + QString::number(i);
|
||||
QPushButton *btn = ui->page_number->findChild<QPushButton*>(btnObjName);
|
||||
btn->setFixedWidth(btnWidth);
|
||||
}
|
||||
ui->btn_backspace_num->setFixedSize(btnWidth,btnHeight);
|
||||
ui->btn_insert->setFixedWidth(btnWidth);
|
||||
ui->btn_delete->setFixedWidth(btnWidth);
|
||||
ui->btn_home->setFixedWidth(btnWidth);
|
||||
ui->btn_end->setFixedWidth(btnWidth);
|
||||
ui->btn_pgup->setFixedWidth(btnWidth);
|
||||
ui->btn_pgdn->setFixedWidth(btnWidth);
|
||||
ui->btn_up->setFixedSize(btnWidth,btnHeight);
|
||||
ui->btn_down->setFixedSize(btnWidth,btnHeight);
|
||||
ui->btn_left->setFixedSize(btnWidth,btnHeight);
|
||||
ui->btn_right->setFixedSize(btnWidth,btnHeight);
|
||||
|
||||
ui->btn_close->setFixedHeight(btnHeight);
|
||||
ui->btn_letter->setFixedHeight(btnHeight);
|
||||
ui->btn_symbol->setFixedHeight(btnHeight);
|
||||
ui->btn_number->setFixedHeight(btnHeight);
|
||||
|
||||
setIconSize();
|
||||
}
|
||||
|
||||
float hScale = 0.6;
|
||||
float wScale = hScale;
|
||||
#define SET_ICON_SIZE_SCALE(btn) \
|
||||
ui->btn_##btn->setIconSize(QSize(ui->btn_##btn->width() * hScale, ui->btn_##btn->height() * wScale));
|
||||
|
||||
#define SET_ICON_SIZE(btn) \
|
||||
ui->btn_##btn->setIconSize(QSize(ui->btn_##btn->width(), ui->btn_##btn->height()));
|
||||
|
||||
#define SET_SHIFT_ICON_SIZE_SCALE(btn) \
|
||||
ui->btn_##btn->setIconSize(QSize(ui->btn_##btn->height() * 0.4, ui->btn_##btn->height() * 0.4));
|
||||
|
||||
#define SET_ENTER_ICON_SIZE_SCALE(btn) \
|
||||
ui->btn_##btn->setIconSize(QSize(ui->btn_##btn->width() * 0.4, ui->btn_##btn->height() * 0.4));
|
||||
|
||||
void KeyboardWidget::setIconSize()
|
||||
{
|
||||
SET_ICON_SIZE_SCALE(backspace);
|
||||
SET_ICON_SIZE_SCALE(backspace_num);
|
||||
SET_ENTER_ICON_SIZE_SCALE(enter);
|
||||
SET_ICON_SIZE_SCALE(enter_num);
|
||||
SET_ICON_SIZE_SCALE(close);
|
||||
SET_ICON_SIZE_SCALE(super);
|
||||
|
||||
SET_SHIFT_ICON_SIZE_SCALE(shift_l);
|
||||
SET_SHIFT_ICON_SIZE_SCALE(shift_r);
|
||||
SET_ICON_SIZE(up);
|
||||
SET_ICON_SIZE(down);
|
||||
SET_ICON_SIZE(left);
|
||||
SET_ICON_SIZE(right);
|
||||
}
|
||||
|
||||
void KeyboardWidget::bindSingal()
|
||||
{
|
||||
for(auto obj : ui->page_letter->children()) {
|
||||
if(obj->metaObject()->className() == QString("QPushButton")) {
|
||||
QPushButton *btn = static_cast<QPushButton*>(obj);
|
||||
btn->setFocusPolicy(Qt::NoFocus);
|
||||
connect(btn, &QPushButton::clicked, this, &KeyboardWidget::onButtonClicked);
|
||||
connect(btn, &QPushButton::pressed, this, &KeyboardWidget::onButtonPressed);
|
||||
connect(btn, &QPushButton::released, this, &KeyboardWidget::onButtonReleased);
|
||||
}
|
||||
}
|
||||
for(auto obj : ui->page_number->children()) {
|
||||
if(obj->metaObject()->className() == QString("QPushButton")) {
|
||||
QPushButton *btn = static_cast<QPushButton*>(obj);
|
||||
btn->setFocusPolicy(Qt::NoFocus);
|
||||
connect(btn, &QPushButton::clicked, this, &KeyboardWidget::onButtonClicked);
|
||||
connect(btn, &QPushButton::pressed, this, &KeyboardWidget::onButtonPressed);
|
||||
connect(btn, &QPushButton::released, this, &KeyboardWidget::onButtonReleased);
|
||||
}
|
||||
}
|
||||
ui->btn_close->setFocusPolicy(Qt::NoFocus);
|
||||
ui->btn_letter->setFocusPolicy(Qt::NoFocus);
|
||||
ui->btn_symbol->setFocusPolicy(Qt::NoFocus);
|
||||
ui->btn_number->setFocusPolicy(Qt::NoFocus);
|
||||
|
||||
connect(ui->btn_letter, &QPushButton::clicked, this, [&] {
|
||||
ui->stackedWidget->setCurrentWidget(ui->page_letter);
|
||||
page = 0;
|
||||
switchPage();
|
||||
});
|
||||
connect(ui->btn_symbol, &QPushButton::clicked, this, [&] {
|
||||
ui->stackedWidget->setCurrentWidget(ui->page_letter);
|
||||
page = 1;
|
||||
switchPage();
|
||||
});
|
||||
connect(ui->btn_number, &QPushButton::clicked, this, [&] {
|
||||
ui->stackedWidget->setCurrentWidget(ui->page_number);
|
||||
});
|
||||
connect(ui->btn_close, &QPushButton::clicked,
|
||||
this, &KeyboardWidget::aboutToClose);
|
||||
|
||||
connect(ui->btn_close, &QPushButton::pressed,
|
||||
this, &KeyboardWidget::onButtonPressed);
|
||||
connect(ui->btn_close, &QPushButton::released,
|
||||
this, &KeyboardWidget::onButtonReleased);
|
||||
}
|
||||
|
||||
void KeyboardWidget::setDefaultIcon()
|
||||
{
|
||||
ui->btn_backspace->setIcon(QIcon(":/images/images/backspace.svg"));
|
||||
ui->btn_backspace_num->setIcon(QIcon(":/images/images/backspace.svg"));
|
||||
ui->btn_enter->setIcon(QIcon(":/images/images/enter.svg"));
|
||||
ui->btn_enter_num->setIcon(QIcon(":/images/images/enter.svg"));
|
||||
ui->btn_shift_l->setIcon(QIcon(":/images/images/capslock.svg"));
|
||||
ui->btn_shift_r->setIcon(QIcon(":/images/images/capslock.svg"));
|
||||
ui->btn_close->setIcon(QIcon(":/images/images/close.svg"));
|
||||
//ui->btn_super->setIcon(QIcon(":/images/images/super.svg"));
|
||||
ui->btn_super->setText("Super");
|
||||
ui->btn_up->setIcon(QIcon(":/images/images/up.svg"));
|
||||
ui->btn_down->setIcon(QIcon(":/images/images/down.svg"));
|
||||
ui->btn_left->setIcon(QIcon(":/images/images/left.svg"));
|
||||
ui->btn_right->setIcon(QIcon(":/images/images/right.svg"));
|
||||
}
|
||||
|
||||
QString KeyboardWidget::getKeyName(QPushButton *btn)
|
||||
{
|
||||
QString objName = btn->objectName();
|
||||
int lastUnderline = objName.lastIndexOf('_');
|
||||
int start = strlen("btn_");
|
||||
int keyLength = lastUnderline - start;
|
||||
QString keyName = objName.mid(start, keyLength);
|
||||
return keyName;
|
||||
}
|
||||
|
||||
void KeyboardWidget::changeFuncKeyStyle(QPushButton *btn, bool isPressed)
|
||||
{
|
||||
QString modName = getKeyName(btn);
|
||||
Modifier::MOD mod = Modifier::getModifier(modName);
|
||||
|
||||
if(vKeyboard->hasModifier(mod)) {
|
||||
if(isPressed)
|
||||
btn->setStyleSheet(BUTTON_BG_HL_PRESSED);
|
||||
else
|
||||
btn->setStyleSheet(BUTTON_BG_HL);
|
||||
} else {
|
||||
if(isPressed)
|
||||
btn->setStyleSheet(BUTTON_BG_PRESSED);
|
||||
else
|
||||
btn->setStyleSheet(BUTTON_BG);
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardWidget::changeShitKeyStyle(QPushButton *btn, bool isPressed)
|
||||
{
|
||||
if(page == 0){
|
||||
if(isShift) {
|
||||
if(capsLock){
|
||||
if(isPressed) {
|
||||
btn->setStyleSheet(BUTTON_BG_HL_PRESSED);
|
||||
btn->setIcon(QIcon(":/images/images/capslock_click.svg"));
|
||||
} else {
|
||||
btn->setStyleSheet(BUTTON_BG_HL);
|
||||
btn->setIcon(QIcon(":/images/images/capslock.svg"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(isPressed)
|
||||
btn->setIcon(QIcon(":/images/images/capslock_hl_click.svg"));
|
||||
else
|
||||
btn->setIcon(QIcon(":/images/images/capslock_hl.svg"));
|
||||
}
|
||||
} else {
|
||||
if(isPressed)
|
||||
btn->setIcon(QIcon(":/images/images/capslock_click.svg"));
|
||||
else
|
||||
btn->setIcon(QIcon(":/images/images/capslock.svg"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KeyboardWidget::changeDirectKeyStyle(QPushButton *btn, bool isPressed)
|
||||
{
|
||||
QString keyName = getKeyName(btn);
|
||||
FuncKey::FUNCKEY key = FuncKey::getKey(keyName);
|
||||
if(key == FuncKey::UNKNOWN)
|
||||
return;
|
||||
|
||||
QString iconName = QString(":/images/images/%1.svg").arg(keyName);
|
||||
QString iconNamePressed = QString(":/images/images/%1_click.svg").arg(keyName);
|
||||
|
||||
if(isPressed)
|
||||
btn->setIcon(QIcon(iconNamePressed));
|
||||
else
|
||||
btn->setIcon(QIcon(iconName));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 修改按键样式
|
||||
* @param obj 按键
|
||||
* @param isPressed 按下或者松开
|
||||
*/
|
||||
void KeyboardWidget::changeKeyStyle(QPushButton *btn, bool isPressed)
|
||||
{
|
||||
if(btn == ui->btn_ctrl_l || btn == ui->btn_ctrl_r ||
|
||||
btn == ui->btn_alt_l || btn == ui->btn_alt_r ||
|
||||
btn == ui->btn_super) {
|
||||
changeFuncKeyStyle(btn, isPressed);
|
||||
}
|
||||
|
||||
if(btn == ui->btn_shift_l)
|
||||
changeShitKeyStyle(ui->btn_shift_l, isPressed);
|
||||
if(btn == ui->btn_shift_r)
|
||||
changeShitKeyStyle(ui->btn_shift_r, isPressed);
|
||||
|
||||
changeDirectKeyStyle(btn, isPressed);
|
||||
}
|
||||
|
||||
void KeyboardWidget::onButtonPressed()
|
||||
{
|
||||
QPushButton *btn = static_cast<QPushButton*>(sender());
|
||||
changeKeyStyle(btn, true);
|
||||
}
|
||||
|
||||
void KeyboardWidget::onButtonReleased()
|
||||
{
|
||||
QPushButton *btn = static_cast<QPushButton*>(sender());
|
||||
changeKeyStyle(btn, false);
|
||||
}
|
||||
|
||||
void KeyboardWidget::onButtonClicked()
|
||||
{
|
||||
QObject *obj = sender();
|
||||
if(obj->metaObject()->className() != QString("QPushButton"))
|
||||
return;
|
||||
|
||||
QPushButton *btn = static_cast<QPushButton*>(obj);
|
||||
QString keyName = getKeyName(btn);
|
||||
qDebug() << "keyName: " << keyName;
|
||||
|
||||
Modifier::MOD mod = Modifier::getModifier(keyName);
|
||||
FuncKey::FUNCKEY funcKey = FuncKey::getKey(keyName);
|
||||
|
||||
if(keyName == "shift") {
|
||||
if(page == 0) {
|
||||
isShift = !isShift;
|
||||
if(isShift) { //第一次被按下
|
||||
capsLock = false;
|
||||
shiftLastClicked = QTime::currentTime();
|
||||
ui->btn_shift_l->setIcon(QIcon(":/images/images/capslock_hl.svg"));
|
||||
ui->btn_shift_r->setIcon(QIcon(":/images/images/capslock_hl.svg"));
|
||||
}
|
||||
else {
|
||||
int doubleClickInterval = QApplication::doubleClickInterval();
|
||||
if(shiftLastClicked.msecsTo(QTime::currentTime()) <= doubleClickInterval) {
|
||||
//shift键双击,锁定大写
|
||||
capsLock = true;
|
||||
isShift = true;
|
||||
ui->btn_shift_l->setIcon(QIcon(":/images/images/capslock.svg"));
|
||||
ui->btn_shift_r->setIcon(QIcon(":/images/images/capslock.svg"));
|
||||
ui->btn_shift_l->setStyleSheet("QPushButton{background:#80c342}");
|
||||
ui->btn_shift_r->setStyleSheet("QPushButton{background:#80c342}");
|
||||
} else {
|
||||
ui->btn_shift_l->setIcon(QIcon(":/images/images/capslock.svg"));
|
||||
ui->btn_shift_r->setIcon(QIcon(":/images/images/capslock.svg"));
|
||||
ui->btn_shift_l->setStyleSheet("QPushButton{background:#1e1b18}");
|
||||
ui->btn_shift_r->setStyleSheet("QPushButton{background:#1e1b18}");
|
||||
}
|
||||
}
|
||||
toggleCase();
|
||||
} else {
|
||||
page = page % (SYMBOL_PAGE_COUNT - 1) + 1;
|
||||
switchPage();
|
||||
}
|
||||
} else if(mod != Modifier::UNKNOWN) {
|
||||
if(vKeyboard->hasModifier(mod)) {
|
||||
vKeyboard->removeModifier(mod);
|
||||
btn->setStyleSheet(BUTTON_BG);
|
||||
btn->setStyleSheet(BUTTON_BG);
|
||||
} else {
|
||||
vKeyboard->addModifier(mod);
|
||||
btn->setStyleSheet(BUTTON_BG_HL);
|
||||
btn->setStyleSheet(BUTTON_BG_HL);
|
||||
}
|
||||
} else if(funcKey != FuncKey::UNKNOWN) {
|
||||
Q_EMIT keyPressed(funcKey);
|
||||
} else { //字符键
|
||||
QChar c;
|
||||
QString text = btn->text();
|
||||
qDebug() << "clicked button text: " << text;
|
||||
if(text == "&&")
|
||||
c = '&';
|
||||
else if(text.length() == 1)
|
||||
c = text.at(0);
|
||||
|
||||
Q_EMIT keyPressed(c);
|
||||
|
||||
//如果shift键被单击,按一个键后就恢复为小写
|
||||
if(isShift && !capsLock) {
|
||||
isShift = false;
|
||||
toggleCase();
|
||||
changeShitKeyStyle(ui->btn_shift_l, false);
|
||||
changeShitKeyStyle(ui->btn_shift_r, false);
|
||||
}
|
||||
clearModifier();
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardWidget::clearModifier()
|
||||
{
|
||||
for(auto mod : vKeyboard->getAllModifier()) {
|
||||
QString modName = Modifier::getModifierName(mod);
|
||||
if(mod == Modifier::SUPER) {
|
||||
QString objName = QString("btn_%1").arg(modName);
|
||||
QPushButton *btn = ui->page_letter->findChild<QPushButton*>(objName);
|
||||
btn->setStyleSheet(BUTTON_BG);
|
||||
} else {
|
||||
QString objName = QString("btn_%1_l").arg(modName);
|
||||
QPushButton *btn = ui->page_letter->findChild<QPushButton*>(objName);
|
||||
btn->setStyleSheet(BUTTON_BG);
|
||||
objName = QString("btn_%1_r").arg(modName);
|
||||
btn = ui->page_letter->findChild<QPushButton*>(objName);
|
||||
btn->setStyleSheet(BUTTON_BG);
|
||||
}
|
||||
}
|
||||
vKeyboard->clearModifier();
|
||||
}
|
||||
|
||||
void KeyboardWidget::toggleCase()
|
||||
{
|
||||
for(int i = 0; i < 26; i++) {
|
||||
QString objName = "btn_" + QString::number(i);
|
||||
QPushButton *btn = findChild<QPushButton*>(objName);
|
||||
QChar ch;
|
||||
if(isShift) { //切换到大写
|
||||
ch = symbols[0][i].toUpper();
|
||||
} else {
|
||||
ch = symbols[0][i];
|
||||
}
|
||||
btn->setText(ch);
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardWidget::switchPage()
|
||||
{
|
||||
if(page == 0) {
|
||||
ui->btn_shift_l->setText("");
|
||||
ui->btn_shift_r->setText("");
|
||||
ui->btn_shift_l->setIcon(QIcon(":/images/images/capslock.svg"));
|
||||
ui->btn_shift_r->setIcon(QIcon(":/images/images/capslock.svg"));
|
||||
} else {
|
||||
ui->btn_shift_l->setText("");
|
||||
ui->btn_shift_r->setText("");
|
||||
ui->btn_shift_l->setIcon(QIcon(":/images/images/capslock.svg"));
|
||||
ui->btn_shift_r->setIcon(QIcon(":/images/images/capslock.svg"));
|
||||
}
|
||||
|
||||
for(int i = 0; i < SYMBOL_KEY_COUNT; i++) {
|
||||
QString btnObjName = "btn_" + QString::number(i);
|
||||
QPushButton *btn = ui->page_letter->findChild<QPushButton*>(btnObjName);
|
||||
QChar c = symbols[page][i];
|
||||
if(c == '&')
|
||||
btn->setText("&&");
|
||||
else
|
||||
btn->setText(c);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#ifndef KEYBOARDWIDGET_H
|
||||
#define KEYBOARDWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QMap>
|
||||
#include <QTime>
|
||||
#include "x11keyboard.h"
|
||||
|
||||
namespace Ui {
|
||||
class KeyboardWidget;
|
||||
}
|
||||
|
||||
class QPushButton;
|
||||
|
||||
class KeyboardWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit KeyboardWidget(QWidget *parent = 0);
|
||||
~KeyboardWidget();
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
private:
|
||||
void bindSingal();
|
||||
void toggleCase();
|
||||
void switchPage();
|
||||
void setDefaultIcon();
|
||||
void setIconSize();
|
||||
void changeKeyStyle(QPushButton *btn, bool isPressed);
|
||||
void changeFuncKeyStyle(QPushButton *btn, bool isPressed);
|
||||
void changeShitKeyStyle(QPushButton *btn, bool isPressed);
|
||||
void changeDirectKeyStyle(QPushButton *btn, bool isPressed);
|
||||
void clearModifier();
|
||||
QString getKeyName(QPushButton *btn);
|
||||
|
||||
|
||||
private Q_SLOTS:
|
||||
void onButtonClicked();
|
||||
void onButtonPressed();
|
||||
void onButtonReleased();
|
||||
|
||||
Q_SIGNALS:
|
||||
void aboutToClose();
|
||||
void keyPressed(QChar c);
|
||||
void keyPressed(FuncKey::FUNCKEY key);
|
||||
|
||||
private:
|
||||
Ui::KeyboardWidget *ui;
|
||||
bool capsLock; //是否大写锁定
|
||||
bool isShift;
|
||||
QTime shiftLastClicked; //shift键上次被点击的时间
|
||||
int page; //当前是第几页的键盘
|
||||
X11Keyboard *vKeyboard;
|
||||
};
|
||||
|
||||
#endif // KEYBOARDWIDGET_H
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#include "virtualkeyboard.h"
|
||||
#include <QApplication>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
|
||||
QApplication a(argc, argv);
|
||||
VirtualKeyboard *keyboard = new VirtualKeyboard;
|
||||
QObject::connect(keyboard, &VirtualKeyboard::aboutToClose, &a, &QApplication::quit);
|
||||
keyboard->resize(400,300);
|
||||
keyboard->show();
|
||||
|
||||
return a.exec();
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#include "virtualkeyboard.h"
|
||||
#include <QFile>
|
||||
#include <QDesktopWidget>
|
||||
#include <QHBoxLayout>
|
||||
#include <QApplication>
|
||||
|
||||
VirtualKeyboard::VirtualKeyboard(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
Q_INIT_RESOURCE(keyboard);
|
||||
|
||||
setAutoFillBackground(true);
|
||||
QPalette plt;
|
||||
plt.setBrush(QPalette::Background, Qt::black);
|
||||
setPalette(plt);
|
||||
|
||||
setWindowFlags(Qt::FramelessWindowHint |
|
||||
Qt::WindowStaysOnTopHint |
|
||||
Qt::WindowDoesNotAcceptFocus);
|
||||
|
||||
|
||||
keyboardWidget = new KeyboardWidget(this);
|
||||
QHBoxLayout *hl_keyboard = new QHBoxLayout(this);
|
||||
QSpacerItem *spacer = new QSpacerItem(40, 20);
|
||||
hl_keyboard->addSpacerItem(spacer);
|
||||
hl_keyboard->addWidget(keyboardWidget);
|
||||
QSpacerItem *spacer2 = new QSpacerItem(40, 20);
|
||||
hl_keyboard->addSpacerItem(spacer2);
|
||||
|
||||
QFile qssFile(":/qss/keyboard.qss");
|
||||
qssFile.open(QIODevice::ReadOnly);
|
||||
setStyleSheet(qssFile.readAll());
|
||||
qssFile.close();
|
||||
|
||||
QDesktopWidget *desktop = QApplication::desktop();
|
||||
cursorMonitor = new CursorMonitor(this);
|
||||
|
||||
//在多显示器情况下,监视鼠标指针的位置和主显示器变化信号
|
||||
connect(cursorMonitor, &CursorMonitor::cursorPosChanged,
|
||||
this, [&](const QPoint &pos){
|
||||
adjustGeometry(desktop->screenNumber(pos));
|
||||
});
|
||||
|
||||
connect(desktop, &QDesktopWidget::primaryScreenChanged,
|
||||
this, [&]{
|
||||
adjustGeometry(desktop->primaryScreen());
|
||||
});
|
||||
|
||||
connect(keyboardWidget, &KeyboardWidget::aboutToClose,
|
||||
this, &VirtualKeyboard::aboutToClose);
|
||||
|
||||
adjustGeometry(desktop->primaryScreen());
|
||||
}
|
||||
|
||||
void VirtualKeyboard::adjustGeometry(int screen)
|
||||
{
|
||||
QDesktopWidget *desktop = QApplication::desktop();
|
||||
QWidget *activateScreen = desktop->screen(screen);
|
||||
setGeometry(0, activateScreen->height() - activateScreen->height() / 3,
|
||||
activateScreen->width(), activateScreen->height() / 3);
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#ifndef VIRTUALKEYBOARD_H
|
||||
#define VIRTUALKEYBOARD_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QPushButton>
|
||||
|
||||
#include "keyboardwidget.h"
|
||||
#include "cursormonitor.h"
|
||||
|
||||
class VirtualKeyboard : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit VirtualKeyboard(QWidget *parent = 0);
|
||||
|
||||
private:
|
||||
void adjustGeometry(int screen);
|
||||
|
||||
Q_SIGNALS:
|
||||
void aboutToClose();
|
||||
|
||||
private:
|
||||
KeyboardWidget *keyboardWidget;
|
||||
CursorMonitor *cursorMonitor;
|
||||
bool isApplication;
|
||||
};
|
||||
|
||||
|
||||
#endif // VIRTUALKEYBOARD_H
|
|
@ -0,0 +1,208 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#include "x11keyboard.h"
|
||||
#include <QDebug>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/extensions/XTest.h>
|
||||
|
||||
|
||||
|
||||
struct CharMap {
|
||||
QChar name;
|
||||
KeySym code;
|
||||
};
|
||||
|
||||
struct CharMap XSpecialSymbolMap[] {
|
||||
{' ', XK_space},
|
||||
{',', XK_comma},
|
||||
{'.', XK_period},
|
||||
{'\'', XK_quoteright},
|
||||
{'@', XK_at},
|
||||
{'#', XK_numbersign},
|
||||
{'$', XK_dollar},
|
||||
{'%', XK_percent},
|
||||
{'&', XK_ampersand},
|
||||
{'*', XK_asterisk},
|
||||
{'(', XK_parenleft},
|
||||
{')', XK_parenright},
|
||||
{'-', XK_minus},
|
||||
{'+', XK_plus},
|
||||
{'!', XK_exclam},
|
||||
{'"', XK_quotedbl},
|
||||
{'<', XK_less},
|
||||
{'>', XK_greater},
|
||||
{':', XK_colon},
|
||||
{';', XK_semicolon},
|
||||
{'/', XK_slash},
|
||||
{'?', XK_question},
|
||||
{'=', XK_equal},
|
||||
{'.', XK_kana_middledot},
|
||||
{'~', XK_asciitilde},
|
||||
{'`', XK_grave},
|
||||
{'|', XK_bar},
|
||||
{'^', XK_asciicircum},
|
||||
{'{', XK_braceleft},
|
||||
{'}', XK_braceright},
|
||||
{'[', XK_bracketleft},
|
||||
{']', XK_bracketright},
|
||||
{'_', XK_underscore},
|
||||
{'\\', XK_backslash},
|
||||
};
|
||||
|
||||
QMap<FuncKey::FUNCKEY, KeySym> funckeyMap = {
|
||||
{FuncKey::SPACE, XK_space},
|
||||
{FuncKey::BACKSPACE, XK_BackSpace},
|
||||
{FuncKey::ENTER, XK_Return},
|
||||
{FuncKey::HOME, XK_Home},
|
||||
{FuncKey::END, XK_End},
|
||||
{FuncKey::PGUP, XK_Page_Up},
|
||||
{FuncKey::PGDN, XK_Page_Down},
|
||||
{FuncKey::INSERT, XK_Insert},
|
||||
{FuncKey::DELETE, XK_Delete},
|
||||
{FuncKey::UP, XK_Up},
|
||||
{FuncKey::DOWN, XK_Down},
|
||||
{FuncKey::LEFT, XK_Left},
|
||||
{FuncKey::RIGHT, XK_Right}
|
||||
};
|
||||
|
||||
QMap<Modifier::MOD, KeySym> modifierMap = {
|
||||
{Modifier::CTRL, XK_Control_L},
|
||||
{Modifier::ALT, XK_Alt_L},
|
||||
{Modifier::SUPER, XK_Super_L},
|
||||
{Modifier::SHIFT, XK_Shift_L}
|
||||
};
|
||||
|
||||
QVector<QChar> shiftKeyVec = {'~', '!', '@', '#', '$', '%', '^', '&', '*',
|
||||
'(', ')', '_', '+', '{', '}', '|', ':', '"',
|
||||
'>', '?'};
|
||||
|
||||
static Display *display = XOpenDisplay(0);
|
||||
bool isShift = false;
|
||||
bool isLetter = false;
|
||||
unsigned int keyCodeOfChar(QChar c)
|
||||
{
|
||||
QString text(c);
|
||||
|
||||
KeySym keysym = XStringToKeysym(text.toLocal8Bit().data());
|
||||
|
||||
if(keysym == NoSymbol) {
|
||||
int symbolCount = sizeof(XSpecialSymbolMap) / sizeof(struct CharMap);
|
||||
for(int i = 0; i < symbolCount; i++) {
|
||||
if(XSpecialSymbolMap[i].name == c) {
|
||||
keysym = XSpecialSymbolMap[i].code;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
qDebug() << "keysym: " << keysym;
|
||||
|
||||
isShift = shiftKeyVec.contains(c) || (c >= 'A' && c <= 'Z');
|
||||
|
||||
isLetter = c.isLetter();
|
||||
|
||||
KeyCode code = XKeysymToKeycode(display, keysym);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
X11Keyboard::X11Keyboard(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
X11Keyboard::~X11Keyboard()
|
||||
{
|
||||
XCloseDisplay(display);
|
||||
}
|
||||
|
||||
void X11Keyboard::addModifier(Modifier::MOD mod)
|
||||
{
|
||||
modList.push_back(mod);
|
||||
}
|
||||
|
||||
void X11Keyboard::removeModifier(Modifier::MOD mod)
|
||||
{
|
||||
modList.removeOne(mod);
|
||||
}
|
||||
|
||||
bool X11Keyboard::hasModifier(Modifier::MOD mod)
|
||||
{
|
||||
return modList.contains(mod);
|
||||
}
|
||||
|
||||
QList<Modifier::MOD> X11Keyboard::getAllModifier()
|
||||
{
|
||||
return modList;
|
||||
}
|
||||
|
||||
void X11Keyboard::clearModifier()
|
||||
{
|
||||
modList.clear();
|
||||
}
|
||||
|
||||
|
||||
void X11Keyboard::onKeyPressed(QChar c)
|
||||
{
|
||||
unsigned int keyCode = keyCodeOfChar(c);
|
||||
sendKey(keyCode);
|
||||
}
|
||||
|
||||
void X11Keyboard::onKeyPressed(FuncKey::FUNCKEY key)
|
||||
{
|
||||
KeyCode keyCode;
|
||||
KeySym keysym = funckeyMap[key];
|
||||
|
||||
if(keysym != NoSymbol)
|
||||
keyCode = XKeysymToKeycode(display, keysym);
|
||||
|
||||
sendKey(keyCode);
|
||||
}
|
||||
|
||||
void X11Keyboard::sendKey(unsigned int keyCode)
|
||||
{
|
||||
Window focusWindow;
|
||||
int revert;
|
||||
XGetInputFocus(display, &focusWindow, &revert);
|
||||
|
||||
for(auto mod : modList){
|
||||
KeyCode keyCode = XKeysymToKeycode(display, modifierMap[mod]);
|
||||
XTestFakeKeyEvent(display, keyCode, True, 2);
|
||||
}
|
||||
|
||||
//如果使用了修饰键(如ctrl、alt)且字符键是字母,则不起用shift键,否则快捷键不起作用
|
||||
if(!modList.isEmpty() && isLetter)
|
||||
isShift = false;
|
||||
|
||||
if(isShift)
|
||||
XTestFakeKeyEvent(display, XKeysymToKeycode(display, XK_Shift_L), True, 2);
|
||||
|
||||
XTestFakeKeyEvent(display, keyCode, True, CurrentTime);
|
||||
XTestFakeKeyEvent(display, keyCode, False, CurrentTime);
|
||||
|
||||
if(isShift)
|
||||
XTestFakeKeyEvent(display, XKeysymToKeycode(display, XK_Shift_L), False, 2);
|
||||
for(auto mod : modList){
|
||||
KeyCode keyCode = XKeysymToKeycode(display, modifierMap[mod]);
|
||||
XTestFakeKeyEvent(display, keyCode, False, 2);
|
||||
}
|
||||
|
||||
XFlush(display);
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#ifndef X11KEYBOARD_H
|
||||
#define X11KEYBOARD_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QMetaEnum>
|
||||
|
||||
class Modifier : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Modifier(){}
|
||||
|
||||
enum MOD{
|
||||
UNKNOWN = -1,
|
||||
CTRL,
|
||||
SHIFT,
|
||||
ALT,
|
||||
SUPER
|
||||
};
|
||||
Q_ENUM(MOD)
|
||||
|
||||
static QString getModifierName(int mod)
|
||||
{
|
||||
QMetaEnum metaEnum = QMetaEnum::fromType<Modifier::MOD>();
|
||||
const char* modName = metaEnum.valueToKey(mod);
|
||||
QString result = QString(modName).toLower();
|
||||
return result;
|
||||
}
|
||||
static MOD getModifier(const QString &modName)
|
||||
{
|
||||
QMetaEnum metaEnum = QMetaEnum::fromType<Modifier::MOD>();
|
||||
MOD mod = (MOD)metaEnum.keyToValue(modName.toUpper().toLocal8Bit().data());
|
||||
return mod;
|
||||
}
|
||||
};
|
||||
|
||||
class FuncKey : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FuncKey(){}
|
||||
|
||||
enum FUNCKEY {
|
||||
UNKNOWN = -1,
|
||||
SPACE = 0,
|
||||
BACKSPACE,
|
||||
ENTER,
|
||||
HOME,
|
||||
END,
|
||||
PGUP,
|
||||
PGDN,
|
||||
INSERT,
|
||||
DELETE,
|
||||
UP,
|
||||
DOWN,
|
||||
LEFT,
|
||||
RIGHT
|
||||
};
|
||||
Q_ENUM(FUNCKEY)
|
||||
static QString getKeyName(int key)
|
||||
{
|
||||
QMetaEnum metaEnum = QMetaEnum::fromType<FuncKey::FUNCKEY>();
|
||||
const char* keyName = metaEnum.valueToKey(key);
|
||||
QString result = QString(keyName).toLower();
|
||||
return result;
|
||||
}
|
||||
static FUNCKEY getKey(const QString &keyName)
|
||||
{
|
||||
QMetaEnum metaEnum = QMetaEnum::fromType<FuncKey::FUNCKEY>();
|
||||
FUNCKEY key = (FUNCKEY)metaEnum.keyToValue(keyName.toUpper().toLocal8Bit().data());
|
||||
return key;
|
||||
}
|
||||
};
|
||||
|
||||
class X11Keyboard : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit X11Keyboard(QObject *parent = nullptr);
|
||||
~X11Keyboard();
|
||||
void addModifier(Modifier::MOD mod);
|
||||
void removeModifier(Modifier::MOD mod);
|
||||
bool hasModifier(Modifier::MOD mod);
|
||||
QList<Modifier::MOD> getAllModifier();
|
||||
void clearModifier();
|
||||
|
||||
public Q_SLOTS:
|
||||
void onKeyPressed(QChar c);
|
||||
void onKeyPressed(FuncKey::FUNCKEY key);
|
||||
|
||||
private:
|
||||
void sendKey(unsigned int keyCode);
|
||||
|
||||
private:
|
||||
QList<Modifier::MOD> modList;
|
||||
};
|
||||
|
||||
#endif // X11KEYBOARD_H
|
|
@ -0,0 +1,148 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#include "borderdialog.h"
|
||||
#include <QPushButton>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QPainter>
|
||||
#include <QDebug>
|
||||
#include <QPalette>
|
||||
#include <QMouseEvent>
|
||||
|
||||
BorderDialog::BorderDialog(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
initUI();
|
||||
}
|
||||
|
||||
QWidget *BorderDialog::center() const
|
||||
{
|
||||
return m_centerWidget;
|
||||
}
|
||||
|
||||
|
||||
void BorderDialog::initUI()
|
||||
{
|
||||
setWindowFlags(Qt::FramelessWindowHint);
|
||||
setAttribute(Qt::WA_TranslucentBackground, true);
|
||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
setGeometry(parentWidget()->rect());
|
||||
|
||||
m_borderWidget = new QWidget(this);
|
||||
m_borderWidget->setObjectName("BorderDialogBorder");
|
||||
m_centerWidget = new QWidget(m_borderWidget);
|
||||
m_centerWidget->setObjectName("BorderDialogWidget");
|
||||
|
||||
/* 窗口关闭按钮 */
|
||||
m_close = new QPushButton(m_borderWidget);
|
||||
m_close->setObjectName(QStringLiteral("close"));
|
||||
connect(m_close, &QPushButton::clicked, this, &BorderDialog::close);
|
||||
|
||||
setBorderWidth();
|
||||
setBorderColor();
|
||||
setDialogColor();
|
||||
}
|
||||
|
||||
void BorderDialog::setBorderWidth(int width)
|
||||
{
|
||||
borderWidth = width;
|
||||
setDialogSize(this->width(), this->height());
|
||||
}
|
||||
|
||||
void BorderDialog::setBorderColor(QColor color)
|
||||
{
|
||||
setWidgetColor(m_borderWidget, color);
|
||||
}
|
||||
|
||||
void BorderDialog::setDialogSize(int w, int h)
|
||||
{
|
||||
m_borderWidget->setGeometry((width() - w) / 2,
|
||||
(height() - h) / 2,
|
||||
w, h);
|
||||
m_centerWidget->setGeometry(borderWidth, borderWidth,
|
||||
m_borderWidget->width() - borderWidth * 2,
|
||||
m_borderWidget->height() - borderWidth * 2);
|
||||
|
||||
m_close->setGeometry(QRect(0, 0, borderWidth, borderWidth));
|
||||
}
|
||||
|
||||
void BorderDialog::setDialogColor(QColor color)
|
||||
{
|
||||
setWidgetColor(m_centerWidget, color);
|
||||
}
|
||||
|
||||
void BorderDialog::setWidgetColor(QWidget *widget, QColor color)
|
||||
{
|
||||
QString borderStyle = QString("#%1{background: rgb(%2, %3, %4, %5)}")
|
||||
.arg(widget->objectName())
|
||||
.arg(QString::number(color.red()))
|
||||
.arg(QString::number(color.green()))
|
||||
.arg(QString::number(color.blue()))
|
||||
.arg(QString::number(color.alpha()));
|
||||
widget->setStyleSheet(borderStyle);
|
||||
}
|
||||
|
||||
void BorderDialog::paintEvent(QPaintEvent *e)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.setPen(Qt::transparent);
|
||||
painter.setBrush(QColor(0, 0, 0, m_opacity));
|
||||
painter.drawRect(rect());
|
||||
|
||||
QWidget::paintEvent(e);
|
||||
}
|
||||
|
||||
void BorderDialog::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if(!m_borderWidget->geometry().contains(event->pos()))
|
||||
close();
|
||||
}
|
||||
|
||||
void BorderDialog::close()
|
||||
{
|
||||
m_borderWidget->close();
|
||||
startBackground(80, 0, false);
|
||||
}
|
||||
|
||||
void BorderDialog::showEvent(QShowEvent *)
|
||||
{
|
||||
startBackground(0, 80, true);
|
||||
}
|
||||
|
||||
void BorderDialog::startBackground(int begin, int end, bool show)
|
||||
{
|
||||
QPropertyAnimation *animation = new QPropertyAnimation(this, "opacity");
|
||||
animation->setDuration(300);
|
||||
animation->setStartValue(begin);
|
||||
animation->setEndValue(end);
|
||||
if(!show)
|
||||
connect(animation, &QPropertyAnimation::finished, this, &QWidget::close);
|
||||
|
||||
animation->start();
|
||||
}
|
||||
|
||||
void BorderDialog::setOpacity(int opacity)
|
||||
{
|
||||
m_opacity = opacity;
|
||||
update();
|
||||
}
|
||||
|
||||
int BorderDialog::opacity()
|
||||
{
|
||||
return m_opacity;
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#ifndef BORDERDIALOG_H
|
||||
#define BORDERDIALOG_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QPushButton;
|
||||
class BorderDialog : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int opacity READ opacity WRITE setOpacity)
|
||||
public:
|
||||
explicit BorderDialog(QWidget *parent = 0);
|
||||
virtual void close();
|
||||
|
||||
void setBorderWidth(int width = 24);
|
||||
void setBorderColor(QColor color = QColor(0, 0, 0, 50));
|
||||
void setDialogSize(int width, int h);
|
||||
void setDialogColor(QColor color = QColor("#2D698E"));
|
||||
|
||||
protected:
|
||||
void initUI();
|
||||
QWidget *center() const;
|
||||
|
||||
private:
|
||||
void startBackground(int begin, int end, bool show);
|
||||
int opacity();
|
||||
void setOpacity(int);
|
||||
void setWidgetColor(QWidget *widget, QColor color);
|
||||
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *);
|
||||
void showEvent(QShowEvent *event);
|
||||
void mousePressEvent(QMouseEvent *event);
|
||||
|
||||
signals:
|
||||
void aboutToClose();
|
||||
|
||||
private:
|
||||
qreal m_opacity;
|
||||
|
||||
QWidget *m_centerWidget;
|
||||
QWidget *m_borderWidget;
|
||||
QPushButton *m_close;
|
||||
|
||||
int borderWidth;
|
||||
};
|
||||
|
||||
#endif // BORDERDIALOG_H
|
|
@ -0,0 +1,15 @@
|
|||
HEADERS += \
|
||||
$$PWD/globalv.h \
|
||||
$$PWD/configuration.h \
|
||||
$$PWD/monitorwatcher.h \
|
||||
$$PWD/borderdialog.h \
|
||||
$$PWD/fakedialog.h \
|
||||
$$PWD/xeventmonitor.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/globalv.cpp \
|
||||
$$PWD/configuration.cpp \
|
||||
$$PWD/monitorwatcher.cpp \
|
||||
$$PWD/borderdialog.cpp \
|
||||
$$PWD/fakedialog.cpp \
|
||||
$$PWD/xeventmonitor.cpp
|
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#include "configuration.h"
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QFont>
|
||||
#include <QFontMetrics>
|
||||
#include <QTextOption>
|
||||
#include <QPainter>
|
||||
#include <QDebug>
|
||||
#include "globalv.h"
|
||||
|
||||
#define CONFIG_FILE "/etc/lightdm/ukui-greeter.conf"
|
||||
|
||||
Configuration* Configuration::instance_ = nullptr;
|
||||
|
||||
Configuration::Configuration(QObject *parent)
|
||||
: QObject(parent),
|
||||
m_trans(nullptr)
|
||||
{
|
||||
QString recodfile = QDir::homePath() + "/.cache/ukui-greeter.conf";
|
||||
qDebug() << recodfile;
|
||||
|
||||
configSettings = new QSettings(CONFIG_FILE, QSettings::IniFormat, this);
|
||||
recordSettings = new QSettings(recodfile, QSettings::IniFormat, this);
|
||||
timeTpSetting = new QSettings(configPath, QSettings::IniFormat, this);
|
||||
}
|
||||
|
||||
Configuration* Configuration::instance(QObject *parent)
|
||||
{
|
||||
if(instance_ == nullptr)
|
||||
instance_ = new Configuration(parent);
|
||||
return instance_;
|
||||
}
|
||||
|
||||
QVariant Configuration::getValue(const QString &key)
|
||||
{
|
||||
configSettings->beginGroup("Greeter");
|
||||
QVariant value = configSettings->value(key);
|
||||
configSettings->endGroup();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void Configuration::getCurrentUser(const QString userName)
|
||||
{
|
||||
configPath = QString("/var/lib/lightdm-data/%1/ukui-greeter.conf").arg(userName);
|
||||
timeTpSetting = new QSettings(configPath, QSettings::IniFormat, this);
|
||||
}
|
||||
|
||||
QVariant Configuration::getTimetp(const QString &key)
|
||||
{
|
||||
timeTpSetting->beginGroup("Greeter");
|
||||
QVariant value = timeTpSetting->value(key);
|
||||
timeTpSetting->endGroup();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void Configuration::setValue(const QString &key, const QVariant &value)
|
||||
{
|
||||
configSettings->beginGroup("Greeter");
|
||||
configSettings->setValue(key, value);
|
||||
configSettings->endGroup();
|
||||
}
|
||||
|
||||
bool Configuration::hasValue(const QString &key)
|
||||
{
|
||||
configSettings->beginGroup("Greeter");
|
||||
bool value = configSettings->contains(key);
|
||||
configSettings->endGroup();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
QString Configuration::getLastLoginUser()
|
||||
{
|
||||
recordSettings->beginGroup("Greeter");
|
||||
QString lastLoginUser = recordSettings->value("lastLoginUser").toString();
|
||||
recordSettings->endGroup();
|
||||
return lastLoginUser;
|
||||
}
|
||||
|
||||
void Configuration::saveLastLoginUser(const QString &userRealName)
|
||||
{
|
||||
recordSettings->beginGroup("Greeter");
|
||||
recordSettings->setValue("lastLoginUser", userRealName);
|
||||
recordSettings->endGroup();
|
||||
recordSettings->sync();
|
||||
}
|
||||
|
||||
void Configuration::saveLastLoginUser1(const QString &userRealName)
|
||||
{
|
||||
recordSettings->beginGroup("Greeter");
|
||||
recordSettings->setValue("lastLoginUser1", userRealName);
|
||||
recordSettings->endGroup();
|
||||
recordSettings->sync();
|
||||
}
|
||||
|
||||
bool Configuration::getLastNumLock()
|
||||
{
|
||||
recordSettings->beginGroup("Greeter");
|
||||
if(recordSettings->contains("numlock") == false){
|
||||
recordSettings->setValue("numlock", true);
|
||||
recordSettings->sync();
|
||||
recordSettings->endGroup();
|
||||
return true;
|
||||
}
|
||||
bool lastNumLock = recordSettings->value("numlock").toBool();
|
||||
recordSettings->endGroup();
|
||||
return lastNumLock;
|
||||
}
|
||||
|
||||
void Configuration::saveLastNumLock(bool value)
|
||||
{
|
||||
recordSettings->beginGroup("Greeter");
|
||||
recordSettings->setValue("numlock", value);
|
||||
recordSettings->endGroup();
|
||||
recordSettings->sync();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取系统版本号
|
||||
*/
|
||||
QString getSystemVersion()
|
||||
{
|
||||
QSettings settings("/etc/lsb-release", QSettings::IniFormat);
|
||||
QString release = settings.value("DISTRIB_RELEASE").toString();
|
||||
QString description = settings.value("DISTRIB_DESCRIPTION").toString();
|
||||
if(description.right(3) == "LTS")
|
||||
release = release + " LTS";
|
||||
return release;
|
||||
}
|
||||
|
||||
QString getSystemDistrib()
|
||||
{
|
||||
QSettings settings("/etc/lsb-release", QSettings::IniFormat);
|
||||
QString distribId = settings.value("DISTRIB_ID").toString();
|
||||
return distribId;
|
||||
}
|
||||
|
||||
bool Configuration::getUseFirstDevice()
|
||||
{
|
||||
QSettings settings("/etc/biometric-auth/ukui-biometric.conf", QSettings::IniFormat);
|
||||
return settings.value("UseFirstDevice").toBool();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief logoGenerator
|
||||
* @param text
|
||||
* @return
|
||||
* 生成logo
|
||||
*/
|
||||
QPixmap logoGenerator(const QString &text)
|
||||
{
|
||||
// if(getSystemDistrib() == "Kylin")
|
||||
// return QPixmap(":/images/kylin-logo.png");
|
||||
|
||||
// QString logoFile(IMAGE_DIR + "logo.png");
|
||||
// if(QFile(logoFile).exists())
|
||||
// {
|
||||
// QPixmap logo(IMAGE_DIR + "logo.png");
|
||||
// return logo;
|
||||
// }
|
||||
QPixmap logoBare;
|
||||
logoBare.load(":/images/uk-logo.png");
|
||||
|
||||
QFont font("ubuntu", 18);
|
||||
QFontMetrics fm(font);
|
||||
int textPixelSize = fm.width(text);
|
||||
|
||||
QPixmap logo(logoBare.width() + textPixelSize + 3 + 30, logoBare.height());
|
||||
logo.fill(Qt::transparent);
|
||||
|
||||
QRect logoBareRect(30 , 0, logoBare.width(), logoBare.height());
|
||||
QPainter painter;
|
||||
painter.begin(&logo);
|
||||
painter.drawPixmap(logoBareRect, logoBare, logoBare.rect());
|
||||
|
||||
painter.setPen(Qt::white);
|
||||
painter.setFont(font);
|
||||
QTextOption option(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
option.setWrapMode(QTextOption::WordWrap);
|
||||
QRect versionRect(logoBareRect.right()+3, 3, logo.width() - logoBare.width(), logo.height());
|
||||
painter.drawText(versionRect, text, option);
|
||||
|
||||
return logo;
|
||||
}
|
||||
|
||||
|
||||
QPixmap Configuration::getLogo()
|
||||
{
|
||||
/**
|
||||
* 先从配置文件中读取logo文件,如果不存在,则生成logo图片
|
||||
*/
|
||||
QString logoFilePath = getValue("logo").toString();
|
||||
if(QFile(logoFilePath).exists())
|
||||
return QPixmap(logoFilePath);
|
||||
|
||||
return logoGenerator(getSystemVersion());
|
||||
}
|
||||
|
||||
|
||||
QString Configuration::getDefaultBackgroundName()
|
||||
{
|
||||
return "/usr/share/backgrounds/1-warty-final-ubuntukylin.jpg";
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/* configuration.h
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#ifndef CONFIGURATION_H
|
||||
#define CONFIGURATION_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QSettings>
|
||||
#include <QTranslator>
|
||||
#include <QPixmap>
|
||||
|
||||
class Configuration : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
explicit Configuration(QObject *parent = nullptr);
|
||||
|
||||
public:
|
||||
static Configuration *instance(QObject *parent = nullptr);
|
||||
|
||||
QVariant getValue(const QString &);
|
||||
QVariant getTimetp(const QString &key);
|
||||
void setValue(const QString&, const QVariant &);
|
||||
bool hasValue(const QString &);
|
||||
|
||||
void getCurrentUser(const QString userName);
|
||||
QString getLastLoginUser();
|
||||
void saveLastLoginUser(const QString &);
|
||||
void saveLastLoginUser1(const QString &);
|
||||
bool getLastNumLock();
|
||||
void saveLastNumLock(bool value);
|
||||
QPixmap getLogo();
|
||||
QString getDefaultBackgroundName();
|
||||
bool getUseFirstDevice();
|
||||
QTranslator *m_trans;
|
||||
|
||||
private:
|
||||
QSettings *configSettings;
|
||||
QSettings *recordSettings;
|
||||
QSettings *timeTpSetting;
|
||||
static Configuration *instance_;
|
||||
QString configPath;
|
||||
|
||||
};
|
||||
|
||||
#endif // CONFIGURATION_H
|
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#include "fakedialog.h"
|
||||
#include <QPushButton>
|
||||
#include <QPainter>
|
||||
#include <QKeyEvent>
|
||||
#include <QDebug>
|
||||
|
||||
#define BORDER_WIDTH 24
|
||||
|
||||
FakeDialog::FakeDialog(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
initUI();
|
||||
}
|
||||
|
||||
void FakeDialog::setDialogSize(int w, int h)
|
||||
{
|
||||
dialogWidth = w;
|
||||
dialogHeight = h;
|
||||
|
||||
resizeEvent(nullptr);
|
||||
}
|
||||
|
||||
QWidget* FakeDialog::centerWidget()
|
||||
{
|
||||
return m_centerWidget;
|
||||
}
|
||||
|
||||
QWidget* FakeDialog::dialog()
|
||||
{
|
||||
return m_dialog;
|
||||
}
|
||||
|
||||
void FakeDialog::initUI()
|
||||
{
|
||||
setObjectName("fakeDialogBackground");
|
||||
setAttribute(Qt::WA_TranslucentBackground, true);
|
||||
setGeometry(parentWidget()->rect());
|
||||
|
||||
m_dialog = new QWidget(this);
|
||||
m_dialog->setObjectName(QStringLiteral("fakeDialog"));
|
||||
|
||||
m_centerWidget = new QWidget(m_dialog);
|
||||
m_centerWidget->setObjectName(QStringLiteral("dialogCenterWidget"));
|
||||
|
||||
m_closeButton = new QPushButton(m_dialog);
|
||||
m_closeButton->setText(tr("cancel"));
|
||||
|
||||
connect(m_closeButton, &QPushButton::clicked, this, &FakeDialog::close);
|
||||
}
|
||||
|
||||
|
||||
void FakeDialog::resizeEvent(QResizeEvent */*event*/)
|
||||
{
|
||||
m_dialog->setGeometry((width() - dialogWidth) / 2,
|
||||
(height() - dialogHeight) / 2,
|
||||
dialogWidth, dialogHeight);
|
||||
m_centerWidget->setGeometry(BORDER_WIDTH, BORDER_WIDTH,
|
||||
m_dialog->width() - BORDER_WIDTH * 2 ,
|
||||
m_dialog->height() - BORDER_WIDTH * 2);
|
||||
m_closeButton->setGeometry(m_centerWidget->width()*2/3, m_centerWidget->y() + m_centerWidget->height() - 80,
|
||||
80, 30);
|
||||
|
||||
}
|
||||
|
||||
void FakeDialog::keyReleaseEvent(QKeyEvent *event)
|
||||
{
|
||||
if(event->key() == Qt::Key_Escape)
|
||||
{
|
||||
close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#ifndef FAKEDIALOG_H
|
||||
#define FAKEDIALOG_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QPushButton;
|
||||
|
||||
class FakeDialog : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FakeDialog(QWidget *parent = nullptr);
|
||||
void setDialogSize(int w, int h);
|
||||
QWidget *centerWidget();
|
||||
QWidget *dialog();
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
void keyReleaseEvent(QKeyEvent *event);
|
||||
|
||||
private:
|
||||
void initUI();
|
||||
|
||||
private:
|
||||
int dialogWidth;
|
||||
int dialogHeight;
|
||||
|
||||
QWidget *m_dialog;
|
||||
QWidget *m_centerWidget;
|
||||
QPushButton *m_closeButton;
|
||||
// QPushButton *m_okButton;
|
||||
// QPushButton *m_cancelButton;
|
||||
};
|
||||
|
||||
#endif // FAKEDIALOG_H
|
|
@ -0,0 +1,87 @@
|
|||
/* globalv.cpp
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#include "globalv.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QPixmap>
|
||||
#include <QProcess>
|
||||
#include <QPainter>
|
||||
#include <QMimeDatabase>
|
||||
#include <QtSvg/QSvgRenderer>
|
||||
|
||||
/**
|
||||
* @brief scaledPixmap
|
||||
* @param width
|
||||
* @param height
|
||||
* @param url
|
||||
* @return
|
||||
* 图片缩放
|
||||
*/
|
||||
QPixmap scaledPixmap(int width, int height, QString url)
|
||||
{
|
||||
QFile imgFile(url);
|
||||
if(!imgFile.exists()){
|
||||
qDebug()<< "not find the pixmap file";
|
||||
return QPixmap();
|
||||
}
|
||||
QImage image(url);
|
||||
QPixmap pixmap = QPixmap::fromImage(image);
|
||||
if(pixmap.isNull()) {
|
||||
qDebug() << "pixmap is null";
|
||||
QProcess exec;
|
||||
QString program("file " + url);
|
||||
exec.start(program);
|
||||
exec.waitForFinished(1000);
|
||||
QString output = exec.readAllStandardOutput();
|
||||
qDebug() << output;
|
||||
if(output.contains("SVG")){
|
||||
qDebug() << "image format is SVG";
|
||||
QSvgRenderer render(url);
|
||||
QImage image(width, height, QImage::Format_ARGB32);
|
||||
image.fill(Qt::transparent);
|
||||
QPainter painter(&image);
|
||||
render.render(&painter, image.rect());
|
||||
pixmap.convertFromImage(image);
|
||||
} else if(output.contains("TIFF")) {
|
||||
qDebug() << "image format is TIFF";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return pixmap.scaled(width, height, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
|
||||
}
|
||||
|
||||
bool isPicture(QString filepath)
|
||||
{
|
||||
QMimeDatabase db;
|
||||
QMimeType mime = db.mimeTypeForFile(filepath);
|
||||
qDebug() << "mime: " << filepath << mime.name();
|
||||
return mime.name().startsWith("image/");
|
||||
}
|
||||
|
||||
QString ElideText(QFont font,int width,QString strInfo)
|
||||
{
|
||||
QFontMetrics fontMetrics(font);
|
||||
//如果当前字体下,字符串长度大于指定宽度
|
||||
if(fontMetrics.width(strInfo) > width)
|
||||
{
|
||||
strInfo= QFontMetrics(font).elidedText(strInfo, Qt::ElideRight, width);
|
||||
}
|
||||
return strInfo;
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* globalv.h
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
|
||||
#ifndef GLOBALV_H
|
||||
#define GLOBALV_H
|
||||
|
||||
#include <QPixmap>
|
||||
#include <QFile>
|
||||
#include <QSettings>
|
||||
#include <QString>
|
||||
#include <QLocale>
|
||||
|
||||
#define STR(s) #s
|
||||
#define GET_STR(s) STR(s)
|
||||
|
||||
#define PREFIX QString(GET_STR(RESOURCE_PATH))
|
||||
#define IMAGE_DIR PREFIX+"/images/"
|
||||
#define QM_DIR PREFIX+"/translations/"
|
||||
|
||||
class QPoint;
|
||||
class QRect;
|
||||
|
||||
extern float scale; //缩放比例
|
||||
extern int fontSize; //字体大小
|
||||
|
||||
QPixmap scaledPixmap(int width, int height, QString url);
|
||||
bool isPicture(QString filepath);
|
||||
QString ElideText(QFont font,int width,QString strInfo);
|
||||
#endif // GLOBALV_H
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#include "monitorwatcher.h"
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QDebug>
|
||||
#include <QException>
|
||||
#include <QProcess>
|
||||
#include <QStandardPaths>
|
||||
#define DRM_DIR "/sys/class/drm/"
|
||||
|
||||
MonitorWatcher::MonitorWatcher(QObject *parent)
|
||||
: QThread(parent),
|
||||
virtualSize(0, 0),
|
||||
monitorCount(0),
|
||||
monitorFisrst("")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
MonitorWatcher::~MonitorWatcher()
|
||||
{
|
||||
requestInterruption();
|
||||
terminate();
|
||||
wait();
|
||||
}
|
||||
|
||||
void MonitorWatcher::getMonitors()
|
||||
{
|
||||
|
||||
QProcess subProcess;
|
||||
subProcess.setProgram(QStandardPaths::findExecutable("xrandr"));
|
||||
subProcess.setArguments({"-q"});
|
||||
subProcess.start(QIODevice::ReadOnly);
|
||||
subProcess.waitForFinished();
|
||||
QString outputs = subProcess.readAll();
|
||||
QStringList lines = outputs.split('\n');
|
||||
QString name;
|
||||
QVector<QString> modes;
|
||||
bool find = false;
|
||||
QString lastName;
|
||||
monitorNames.clear();
|
||||
monitors.clear();
|
||||
for(auto & line : lines) {
|
||||
if(line.indexOf(" connected") != -1) { //找显示器名称
|
||||
name = line.left(line.indexOf(' '));
|
||||
monitorNames.push_back(name);
|
||||
if(find) //又找到了一个显示器,将上一个显示器的信息存到map
|
||||
monitors[lastName] = modes;
|
||||
find = true;
|
||||
lastName = name;
|
||||
modes.clear();
|
||||
} else {
|
||||
if(line.startsWith(' ')) { //获取分辨率
|
||||
QString mode = line.trimmed().split(' ').at(0);
|
||||
modes.push_back(mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!name.isEmpty())
|
||||
monitors[name] = modes; //将最后一个显示器的信息存储到map
|
||||
}
|
||||
|
||||
void MonitorWatcher::run()
|
||||
{
|
||||
/* 每隔3秒遍历一次显卡接口的连接状态 */
|
||||
while(!isInterruptionRequested()) {
|
||||
getMonitors();
|
||||
int tmp = monitors.keys().size();
|
||||
if(tmp == 1 && monitorCount == 1){
|
||||
if(monitorFisrst != monitorNames[0]){
|
||||
monitorFisrst = monitorNames[0];
|
||||
Q_EMIT monitorCountChanged(monitorCount);
|
||||
}
|
||||
}else if(tmp != monitorCount){
|
||||
if(monitorFisrst == "")
|
||||
monitorFisrst = monitorNames[0];
|
||||
monitorCount = tmp;
|
||||
Q_EMIT monitorCountChanged(monitorCount);
|
||||
}
|
||||
sleep(3);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取显示器的最大分辨率
|
||||
*/
|
||||
QSize MonitorWatcher::getMonitorMaxSize(const QString &drm)
|
||||
{
|
||||
// int width, height;
|
||||
// QFile drmModeFile(DRM_DIR + drm + "/modes");
|
||||
// if(drmModeFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
// QTextStream in2(&drmModeFile);
|
||||
// QString maxMode;
|
||||
// do
|
||||
// {
|
||||
// maxMode = in2.readLine();
|
||||
// }while(maxMode=="preferred");
|
||||
// int xpos = maxMode.indexOf('x', 0);
|
||||
// width = maxMode.left(xpos).toInt();
|
||||
// int ipos = maxMode.indexOf('i', 0);
|
||||
// if(ipos != -1)
|
||||
// height = maxMode.mid(xpos+1, ipos-xpos-1).toInt();
|
||||
// else
|
||||
// {
|
||||
// int p_pos = maxMode.mid(xpos+1).indexOf('p', 0);
|
||||
// if (p_pos != -1)
|
||||
// {
|
||||
// height = maxMode.mid(xpos+1).left(p_pos).toInt();
|
||||
// }
|
||||
// else
|
||||
// height = maxMode.mid(xpos+1).toInt();
|
||||
// }
|
||||
// }
|
||||
// return QSize(width, height);
|
||||
return virtualSize;
|
||||
}
|
||||
|
||||
QSize MonitorWatcher::getVirtualSize()
|
||||
{
|
||||
return virtualSize;
|
||||
}
|
||||
|
||||
int MonitorWatcher::getMonitorCount()
|
||||
{
|
||||
return monitorCount;
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/* monitorwatcher.h
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#ifndef MONITORWATCHER_H
|
||||
#define MONITORWATCHER_H
|
||||
|
||||
#include <QThread>
|
||||
#include <QMap>
|
||||
#include <QSize>
|
||||
#include <QVector>
|
||||
|
||||
/*!
|
||||
* \brief The MonitorWatcher class
|
||||
* 监控显示器的插拔
|
||||
*/
|
||||
class MonitorWatcher : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MonitorWatcher(QObject *parent=nullptr);
|
||||
~MonitorWatcher();
|
||||
QSize getVirtualSize();
|
||||
int getMonitorCount();
|
||||
|
||||
signals:
|
||||
void monitorCountChanged(int newCount);
|
||||
void virtualSizeChanged(const QSize &newVirtualSize);
|
||||
|
||||
protected:
|
||||
void run();
|
||||
|
||||
private:
|
||||
QSize getMonitorMaxSize(const QString &drm);
|
||||
|
||||
void getMonitors();
|
||||
|
||||
QMap<QString, QVector<QString>> monitors;
|
||||
QStringList monitorNames;
|
||||
QString monitorFisrst;
|
||||
|
||||
QMap<QString, QString> drmStatus;
|
||||
QSize virtualSize;
|
||||
int monitorCount;
|
||||
};
|
||||
|
||||
#endif // MONITORWATCHER_H
|
|
@ -0,0 +1,272 @@
|
|||
/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*-
|
||||
* -*- coding: utf-8 -*-
|
||||
*
|
||||
* Copyright (C) 2011 ~ 2017 Deepin, Inc.
|
||||
* 2011 ~ 2017 Wang Yong
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "xeventmonitor.h"
|
||||
#include <iostream>
|
||||
#include <QVector>
|
||||
#include <QSet>
|
||||
#include <QX11Info>
|
||||
#include <X11/Xlibint.h>
|
||||
#include <X11/XKBlib.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/record.h>
|
||||
#include <X11/keysym.h>
|
||||
|
||||
// Virtual button codes that are not defined by X11.
|
||||
#define Button1 1
|
||||
#define Button2 2
|
||||
#define Button3 3
|
||||
#define WheelUp 4
|
||||
#define WheelDown 5
|
||||
#define WheelLeft 6
|
||||
#define WheelRight 7
|
||||
#define XButton1 8
|
||||
#define XButton2 9
|
||||
|
||||
XEventMonitor *XEventMonitor::instance_ = new XEventMonitor();
|
||||
|
||||
QVector<KeySym> ModifiersVec{
|
||||
XK_Control_L,
|
||||
XK_Control_R,
|
||||
XK_Shift_L,
|
||||
XK_Shift_R,
|
||||
XK_Super_L,
|
||||
XK_Super_R,
|
||||
XK_Alt_L,
|
||||
XK_Alt_R
|
||||
};
|
||||
|
||||
class XEventMonitorPrivate
|
||||
{
|
||||
public:
|
||||
XEventMonitorPrivate(XEventMonitor *parent);
|
||||
virtual ~XEventMonitorPrivate();
|
||||
void run();
|
||||
|
||||
protected:
|
||||
XEventMonitor *q_ptr;
|
||||
QSet<KeySym> modifiers;
|
||||
|
||||
bool filterWheelEvent(int detail);
|
||||
static void callback(XPointer trash, XRecordInterceptData* data);
|
||||
void handleRecordEvent(XRecordInterceptData *);
|
||||
void emitButtonSignal(const char *member, xEvent *event);
|
||||
void emitKeySignal(const char *member, xEvent *event);
|
||||
void updateModifier(xEvent *event, bool isAdd);
|
||||
|
||||
private:
|
||||
Q_DECLARE_PUBLIC(XEventMonitor)
|
||||
};
|
||||
|
||||
XEventMonitorPrivate::XEventMonitorPrivate(XEventMonitor *parent)
|
||||
: q_ptr(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
XEventMonitorPrivate::~XEventMonitorPrivate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void XEventMonitorPrivate::emitButtonSignal(const char *member, xEvent *event)
|
||||
{
|
||||
int x = event->u.keyButtonPointer.rootX;
|
||||
int y = event->u.keyButtonPointer.rootY;
|
||||
QMetaObject::invokeMethod(q_ptr, member,
|
||||
Qt::DirectConnection,
|
||||
Q_ARG(int, x),
|
||||
Q_ARG(int, y));
|
||||
}
|
||||
|
||||
void XEventMonitorPrivate::emitKeySignal(const char *member, xEvent *event)
|
||||
{
|
||||
Display *display = XOpenDisplay(NULL);
|
||||
int keyCode = event->u.u.detail;
|
||||
KeySym keySym = XkbKeycodeToKeysym(display, event->u.u.detail, 0, 0);
|
||||
|
||||
QString keyStrSplice;
|
||||
for(auto modifier : modifiers)
|
||||
{
|
||||
keyStrSplice += QString(XKeysymToString(modifier)) + "+";
|
||||
}
|
||||
//按键是修饰键
|
||||
if(ModifiersVec.contains(keySym) && !modifiers.isEmpty())
|
||||
keyStrSplice.remove(keyStrSplice.length() - 1, 1);
|
||||
else
|
||||
keyStrSplice += XKeysymToString(keySym);
|
||||
|
||||
QMetaObject::invokeMethod(q_ptr, member,
|
||||
Qt::AutoConnection,
|
||||
Q_ARG(int, keyCode));
|
||||
QMetaObject::invokeMethod(q_ptr, member,
|
||||
Qt::AutoConnection,
|
||||
Q_ARG(QString, keyStrSplice));
|
||||
XCloseDisplay(display);
|
||||
}
|
||||
|
||||
void XEventMonitorPrivate::run()
|
||||
{
|
||||
Display* display = XOpenDisplay(0);
|
||||
if (display == 0) {
|
||||
fprintf(stderr, "unable to open display\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Receive from ALL clients, including future clients.
|
||||
XRecordClientSpec clients = XRecordAllClients;
|
||||
XRecordRange* range = XRecordAllocRange();
|
||||
if (range == 0) {
|
||||
fprintf(stderr, "unable to allocate XRecordRange\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Receive KeyPress, KeyRelease, ButtonPress, ButtonRelease and MotionNotify events.
|
||||
memset(range, 0, sizeof(XRecordRange));
|
||||
range->device_events.first = KeyPress;
|
||||
range->device_events.last = MotionNotify;
|
||||
|
||||
// And create the XRECORD context.
|
||||
XRecordContext context = XRecordCreateContext(display, 0, &clients, 1, &range, 1);
|
||||
if (context == 0) {
|
||||
fprintf(stderr, "XRecordCreateContext failed\n");
|
||||
return;
|
||||
}
|
||||
XFree(range);
|
||||
|
||||
XSync(display, True);
|
||||
|
||||
Display* display_datalink = XOpenDisplay(0);
|
||||
if (display_datalink == 0) {
|
||||
fprintf(stderr, "unable to open second display\n");
|
||||
return;
|
||||
}
|
||||
if (!XRecordEnableContext(display_datalink, context, callback, (XPointer) this)) {
|
||||
fprintf(stderr, "XRecordEnableContext() failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void XEventMonitorPrivate::callback(XPointer ptr, XRecordInterceptData* data)
|
||||
{
|
||||
((XEventMonitorPrivate *) ptr)->handleRecordEvent(data);
|
||||
}
|
||||
|
||||
void XEventMonitorPrivate::handleRecordEvent(XRecordInterceptData* data)
|
||||
{
|
||||
|
||||
if (data->category == XRecordFromServer) {
|
||||
xEvent * event = (xEvent *)data->data;
|
||||
switch (event->u.u.type)
|
||||
{
|
||||
case ButtonPress:
|
||||
if (filterWheelEvent(event->u.u.detail)) {
|
||||
emitButtonSignal("buttonPress", event);
|
||||
}
|
||||
break;
|
||||
case MotionNotify:
|
||||
emitButtonSignal("buttonDrag", event);
|
||||
break;
|
||||
case ButtonRelease:
|
||||
if (filterWheelEvent(event->u.u.detail)) {
|
||||
emitButtonSignal("buttonRelease", event);
|
||||
}
|
||||
break;
|
||||
case KeyPress:
|
||||
updateModifier(event, true);
|
||||
emitKeySignal("keyPress", event);
|
||||
break;
|
||||
case KeyRelease:
|
||||
updateModifier(event, false);
|
||||
emitKeySignal("keyRelease", event);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
fflush(stdout);
|
||||
XRecordFreeData(data);
|
||||
}
|
||||
|
||||
bool XEventMonitorPrivate::filterWheelEvent(int detail)
|
||||
{
|
||||
return detail != WheelUp && detail != WheelDown && detail != WheelLeft && detail != WheelRight;
|
||||
}
|
||||
|
||||
void XEventMonitorPrivate::updateModifier(xEvent *event, bool isAdd)
|
||||
{
|
||||
Display *display = XOpenDisplay(NULL);
|
||||
KeySym keySym = XkbKeycodeToKeysym(display, event->u.u.detail, 0, 0);
|
||||
|
||||
if(ModifiersVec.contains(keySym))
|
||||
{
|
||||
if(isAdd)
|
||||
{
|
||||
modifiers.insert(keySym);
|
||||
}
|
||||
else
|
||||
{
|
||||
modifiers.remove(keySym);
|
||||
}
|
||||
}
|
||||
|
||||
XCloseDisplay(display);
|
||||
}
|
||||
|
||||
XEventMonitor::XEventMonitor(QObject *parent)
|
||||
: QThread(parent),
|
||||
d_ptr(new XEventMonitorPrivate(this))
|
||||
{
|
||||
Q_D(XEventMonitor);
|
||||
}
|
||||
|
||||
XEventMonitor::~XEventMonitor()
|
||||
{
|
||||
requestInterruption();
|
||||
quit();
|
||||
wait();
|
||||
}
|
||||
|
||||
void XEventMonitor::run()
|
||||
{
|
||||
if(!isInterruptionRequested())
|
||||
{
|
||||
d_ptr->run();
|
||||
}
|
||||
}
|
||||
|
||||
bool checkCapsState()
|
||||
{
|
||||
//判断大写键状态
|
||||
bool capsState = false;
|
||||
unsigned int n;
|
||||
XkbGetIndicatorState(QX11Info::display(), XkbUseCoreKbd, &n);
|
||||
capsState = (n & 0x01) == 1;
|
||||
return capsState;
|
||||
}
|
||||
|
||||
bool checkNumLockState()
|
||||
{
|
||||
XKeyboardState x;
|
||||
XGetKeyboardControl(QX11Info::display(), &x);
|
||||
return x.led_mask & 2;
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*-
|
||||
* -*- coding: utf-8 -*-
|
||||
*
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef XEVENTMONITOR_H
|
||||
#define XEVENTMONITOR_H
|
||||
|
||||
#include <QThread>
|
||||
#include <QMetaMethod>
|
||||
#include <QDebug>
|
||||
|
||||
class XEventMonitorPrivate;
|
||||
class XEventMonitor : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static XEventMonitor *instance() { return instance_; }
|
||||
|
||||
private:
|
||||
XEventMonitor(QObject *parent = 0);
|
||||
~XEventMonitor();
|
||||
|
||||
Q_SIGNALS:
|
||||
///
|
||||
/// \brief 鼠标按下
|
||||
/// \param x
|
||||
/// \param y
|
||||
///
|
||||
void buttonPress(int x, int y);
|
||||
///
|
||||
/// \brief 鼠标拖动
|
||||
/// \param x
|
||||
/// \param y
|
||||
///
|
||||
void buttonDrag(int x, int y);
|
||||
///
|
||||
/// \brief 鼠标松开
|
||||
/// \param x
|
||||
/// \param y
|
||||
///
|
||||
void buttonRelease(int x, int y);
|
||||
|
||||
///
|
||||
/// \brief keyPress
|
||||
/// \param 按键键码,不包含修饰键
|
||||
///
|
||||
void keyPress(int keyCode);
|
||||
void keyRelease(int keyCode);
|
||||
|
||||
///
|
||||
/// \brief keyPress
|
||||
/// \param 按键名称,如果是组合键,则包含修饰键的名称,如Ctrl_L+r
|
||||
///
|
||||
void keyPress(const QString &key);
|
||||
void keyRelease(const QString &key);
|
||||
|
||||
protected:
|
||||
void run();
|
||||
|
||||
private:
|
||||
Q_DECLARE_PRIVATE(XEventMonitor)
|
||||
XEventMonitorPrivate *d_ptr;
|
||||
|
||||
static XEventMonitor *instance_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 检查大写开关状态
|
||||
* @return 开(true),关(false)
|
||||
*/
|
||||
bool checkCapsState();
|
||||
bool checkNumLockState();
|
||||
#endif
|
|
@ -0,0 +1,19 @@
|
|||
Qt += core gui widgets
|
||||
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
FORMS +=
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/displayservice.h \
|
||||
$$PWD/displayswitch.h \
|
||||
$$PWD/ui_mainwindow.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/displayservice.cpp \
|
||||
$$PWD/displayswitch.cpp
|
||||
|
||||
RESOURCES += \
|
||||
$$PWD/ds-res.qrc
|
||||
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
/* displayservice.cpp
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#include "displayservice.h"
|
||||
#include <QException>
|
||||
#include <QDebug>
|
||||
#include <QProcess>
|
||||
#include <QStandardPaths>
|
||||
|
||||
DisplayService::DisplayService(QObject *parent) : QObject(parent)
|
||||
{
|
||||
m_strSaveParamPath = QStandardPaths::findExecutable("save-param");
|
||||
}
|
||||
|
||||
bool DisplayService::switchDisplayMode(DisplayMode targetMode)
|
||||
{
|
||||
//获取显示器列表
|
||||
getMonitors();
|
||||
|
||||
//如果当前只有一个显示器就什么也不做
|
||||
if(monitors.keys().size() < 2) {
|
||||
qDebug() << "only one monitor, doNothing";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_strSaveParamPath.isEmpty() || m_strUserName.isEmpty()) {
|
||||
QProcess subProcess;
|
||||
//模式切换
|
||||
try {
|
||||
switch(targetMode){
|
||||
case DISPLAY_MODE_ORI:
|
||||
{
|
||||
QString XRANDR_ORIONLY = "xrandr --output " + monitorNames[0] + " --auto";
|
||||
for(int i = 1; i < monitorNames.size(); i++)
|
||||
XRANDR_ORIONLY = XRANDR_ORIONLY + " --output " + monitorNames[i] + " --off";
|
||||
qDebug() << "XRANDR_ORIONLY: " << XRANDR_ORIONLY;
|
||||
|
||||
subProcess.start(XRANDR_ORIONLY, QIODevice::NotOpen);
|
||||
break;
|
||||
}
|
||||
case DISPLAY_MODE_CLONE:
|
||||
{
|
||||
//查找最佳克隆分辨率
|
||||
QString BEST_CLONE_MODE;
|
||||
bool find = false;
|
||||
for(auto & mode_0 : monitors[monitorNames[0]]) {
|
||||
for(auto & mode_1 : monitors[monitorNames[1]]) {
|
||||
if(mode_0 == mode_1) {
|
||||
BEST_CLONE_MODE = mode_0;
|
||||
find = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(find)
|
||||
break;
|
||||
}
|
||||
QString XRANDR_CLONE = "xrandr --output " + monitorNames[0] + " --mode " + BEST_CLONE_MODE;
|
||||
for(int i = 1; i < monitorNames.size(); i++)
|
||||
XRANDR_CLONE = XRANDR_CLONE + " --output " + monitorNames[i] + " --mode " + BEST_CLONE_MODE + " --same-as " + monitorNames[0];
|
||||
qDebug() << "XRANDR_CLONE: " << XRANDR_CLONE;
|
||||
|
||||
subProcess.start(XRANDR_CLONE, QIODevice::NotOpen);
|
||||
break;
|
||||
}
|
||||
case DISPLAY_MODE_EXTEND:
|
||||
{
|
||||
QString XRANDR_EXTEND = "xrandr --output " + monitorNames[0] + " --auto";
|
||||
for(int i = 1; i < monitorNames.size(); i++)
|
||||
XRANDR_EXTEND = XRANDR_EXTEND + " --output " + monitorNames[i] + " --right-of " + monitorNames[i-1] + " --auto";
|
||||
qDebug() << "XRANDR_EXTEND: " << XRANDR_EXTEND;
|
||||
|
||||
subProcess.start(XRANDR_EXTEND, QIODevice::NotOpen);
|
||||
break;
|
||||
}
|
||||
case DISPLAY_MODE_ONLY_OUT:
|
||||
{
|
||||
QString XRANDR_OUTONLY = "xrandr --output " + monitorNames[0] + " --off --output " + monitorNames[1] + " --auto";
|
||||
qDebug() << "XRANDR_OUTONLY: " << XRANDR_OUTONLY;
|
||||
|
||||
subProcess.start(XRANDR_OUTONLY, QIODevice::NotOpen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
subProcess.waitForFinished();
|
||||
return true;
|
||||
} catch(const QException &e) {
|
||||
qWarning() << e.what();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
QProcess subProcess;
|
||||
try {
|
||||
QString usdSaveParam = m_strSaveParamPath + " -u " +m_strUserName;
|
||||
qDebug() << "usdSaveParam: " << usdSaveParam;
|
||||
subProcess.start(usdSaveParam);
|
||||
subProcess.waitForFinished();
|
||||
return true;
|
||||
} catch(const QException &e) {
|
||||
qWarning() << e.what();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString DisplayService::getFirstDisplayXrandrCmd()
|
||||
{
|
||||
//获取显示器列表
|
||||
getMonitors();
|
||||
//组装第一个设备名显示命令
|
||||
if (m_strSaveParamPath.isEmpty() || m_strUserName.isEmpty()) {
|
||||
QString firstXrandrCmd = "xrandr --output " + monitorNames[0] + " --auto";
|
||||
qDebug() << "getFirstDisplayXrandrCmd firstXrandrCmd: " << firstXrandrCmd;
|
||||
return firstXrandrCmd;
|
||||
} else {
|
||||
QString firstXrandrCmd = m_strSaveParamPath + " -u " +m_strUserName;
|
||||
qDebug() << "getFirstDisplayXrandrCmd firstXrandrCmd: " << firstXrandrCmd;
|
||||
return firstXrandrCmd;
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayService::setCurUserName(QString strUserName)
|
||||
{
|
||||
m_strUserName = strUserName;
|
||||
if (!m_strSaveParamPath.isEmpty()) {
|
||||
QProcess subProcess;
|
||||
try {
|
||||
QString usdSaveParam = m_strSaveParamPath + " -u " +m_strUserName;
|
||||
qDebug() << "setCurUserName usdSaveParam: " << usdSaveParam;
|
||||
subProcess.start(usdSaveParam);
|
||||
subProcess.waitForFinished();
|
||||
} catch(const QException &e) {
|
||||
qWarning() << e.what();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayService::getMonitors()
|
||||
{
|
||||
QProcess subProcess;
|
||||
subProcess.setProgram(QStandardPaths::findExecutable("xrandr"));
|
||||
subProcess.setArguments({"-q"});
|
||||
subProcess.start(QIODevice::ReadOnly);
|
||||
subProcess.waitForFinished();
|
||||
QString outputs = subProcess.readAll();
|
||||
QStringList lines = outputs.split('\n');
|
||||
QString name;
|
||||
QVector<QString> modes;
|
||||
bool find = false;
|
||||
QString lastName;
|
||||
monitorNames.clear();
|
||||
monitors.clear();
|
||||
for(auto & line : lines) {
|
||||
if(line.indexOf(" connected") != -1) { //找显示器名称
|
||||
name = line.left(line.indexOf(' '));
|
||||
monitorNames.push_back(name);
|
||||
if(find) //又找到了一个显示器,将上一个显示器的信息存到map
|
||||
monitors[lastName] = modes;
|
||||
find = true;
|
||||
lastName = name;
|
||||
modes.clear();
|
||||
} else {
|
||||
if(line.startsWith(' ')) { //获取分辨率
|
||||
QString mode = line.trimmed().split(' ').at(0);
|
||||
modes.push_back(mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
monitors[name] = modes; //将最后一个显示器的信息存储到map
|
||||
|
||||
qDebug() << "find motinors: " << monitorNames;
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/* displayservice.h
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#ifndef DISPLAYSERVICE_H
|
||||
#define DISPLAYSERVICE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
#include <QMap>
|
||||
|
||||
enum DisplayMode{
|
||||
DISPLAY_MODE_ORI = 1,
|
||||
DISPLAY_MODE_CLONE = 2,
|
||||
DISPLAY_MODE_EXTEND = 3,
|
||||
DISPLAY_MODE_ONLY_OUT = 4
|
||||
};
|
||||
|
||||
class DisplayService : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DisplayService(QObject *parent = nullptr);
|
||||
bool switchDisplayMode(DisplayMode targetMode);
|
||||
QString getFirstDisplayXrandrCmd();//获取第一个设备名称,并组装命令
|
||||
void setCurUserName(QString strUserName);
|
||||
|
||||
private:
|
||||
void getMonitors();
|
||||
|
||||
QMap<QString, QVector<QString>> monitors;
|
||||
QStringList monitorNames;
|
||||
QString m_strSaveParamPath = "";
|
||||
QString m_strUserName = "";
|
||||
};
|
||||
|
||||
#endif // DISPLAYSERVICE_H
|
|
@ -0,0 +1,120 @@
|
|||
/* displayswitch.cpp
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#include "displayswitch.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include <QFile>
|
||||
#include <QDebug>
|
||||
#include <QDesktopWidget>
|
||||
#include "displayservice.h"
|
||||
|
||||
DisplaySwitch::DisplaySwitch(QWidget *parent)
|
||||
: QMainWindow(parent),
|
||||
ui(new Ui::MainWindow()),
|
||||
currentMode(0),
|
||||
selecting(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
this->setAttribute(Qt::WA_TranslucentBackground);
|
||||
setWindowFlags(Qt::FramelessWindowHint | Qt::ToolTip);
|
||||
initUi();
|
||||
}
|
||||
|
||||
void DisplaySwitch::initUi()
|
||||
{
|
||||
ui->centralWidget->setAutoFillBackground(true);
|
||||
QPalette pc;
|
||||
QPixmap img_bg = QPixmap(":res/bg.png");
|
||||
pc.setBrush(QPalette::Window, QBrush(img_bg));
|
||||
ui->centralWidget->setPalette(pc);
|
||||
|
||||
ui->lb_mode_1->setText("仅计算机");
|
||||
ui->lb_mode_2->setText("复制");
|
||||
ui->lb_mode_3->setText("扩展");
|
||||
ui->lb_mode_4->setText("仅投影仪");
|
||||
|
||||
ui->mode_1->setFocusPolicy(Qt::NoFocus);
|
||||
ui->mode_2->setFocusPolicy(Qt::NoFocus);
|
||||
ui->mode_3->setFocusPolicy(Qt::NoFocus);
|
||||
ui->mode_4->setFocusPolicy(Qt::NoFocus);
|
||||
|
||||
QDesktopWidget *dw = QApplication::desktop();
|
||||
QRect rect = dw->screen(dw->primaryScreen())->geometry();
|
||||
setGeometry(rect.left() + (rect.width() - width()) / 2,
|
||||
rect.top() + (rect.height() - height()) / 2,
|
||||
width(), height());
|
||||
}
|
||||
|
||||
void DisplaySwitch::onDisplaySwitchSelect(/*const QRect &rect*/)
|
||||
{
|
||||
show();
|
||||
|
||||
ui->mode_1->hide();
|
||||
ui->mode_2->hide();
|
||||
ui->mode_3->hide();
|
||||
ui->mode_4->hide();
|
||||
currentMode++;
|
||||
if(currentMode > 4)
|
||||
currentMode = 1;
|
||||
switch(currentMode) {
|
||||
case 1:
|
||||
ui->mode_1->show();
|
||||
break;
|
||||
case 2:
|
||||
ui->mode_2->show();
|
||||
break;
|
||||
case 3:
|
||||
ui->mode_3->show();
|
||||
break;
|
||||
case 4:
|
||||
ui->mode_4->show();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DisplaySwitch::onDisplaySwitchConfirm()
|
||||
{
|
||||
if(!isHidden()) {
|
||||
hide();
|
||||
DisplayService().switchDisplayMode(DisplayMode(currentMode));
|
||||
currentMode--;
|
||||
}
|
||||
}
|
||||
|
||||
void DisplaySwitch::onPositionChanged(const QRect &rect)
|
||||
{
|
||||
move(rect.left() + (rect.width() - width()) / 2,
|
||||
rect.top() + (rect.height() - height()) / 2);
|
||||
}
|
||||
|
||||
void DisplaySwitch::onGlobalKeyRelease(const QString &key)
|
||||
{
|
||||
if(key == "Super_L+p" || key == "Super_L+F3")
|
||||
{
|
||||
selecting = true;
|
||||
onDisplaySwitchSelect();
|
||||
}
|
||||
else if(key == "Super_L")
|
||||
{
|
||||
if(selecting)
|
||||
{
|
||||
onDisplaySwitchConfirm();
|
||||
selecting = false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/* displayswitch.h
|
||||
* Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
**/
|
||||
#ifndef DISPLAYSWITCH_H
|
||||
#define DISPLAYSWITCH_H
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class DisplaySwitch : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DisplaySwitch(QWidget *parent = nullptr);
|
||||
void initUi();
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
void onDisplaySwitchSelect();
|
||||
void onDisplaySwitchConfirm();
|
||||
void onPositionChanged(const QRect&);
|
||||
void onGlobalKeyRelease(const QString &key);
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
int currentMode;
|
||||
bool selecting;
|
||||
};
|
||||
|
||||
#endif // DISPLAYSWITCH_H
|
|
@ -0,0 +1,23 @@
|
|||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>res/bg.png</file>
|
||||
<file>res/bg2.png</file>
|
||||
<file>res/bg_f5.png</file>
|
||||
<file>res/btn1.png</file>
|
||||
<file>res/btn2.png</file>
|
||||
<file>res/btn3.png</file>
|
||||
<file>res/btn4.png</file>
|
||||
<file>res/bt_off.png</file>
|
||||
<file>res/bt_on.png</file>
|
||||
<file>res/hover.png</file>
|
||||
<file>res/hover2.png</file>
|
||||
<file>res/hover3.png</file>
|
||||
<file>res/split.png</file>
|
||||
<file>res/touchpad-off.png</file>
|
||||
<file>res/touchpad-on.png</file>
|
||||
<file>res/wifi_off.png</file>
|
||||
<file>res/wifi-off_.png</file>
|
||||
<file>res/wifi_on.png</file>
|
||||
<file>res/wifi-on_.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -0,0 +1,229 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>744</width>
|
||||
<height>126</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<widget class="QPushButton" name="mode_1">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>5</x>
|
||||
<y>5</y>
|
||||
<width>180</width>
|
||||
<height>116</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="mode_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>190</x>
|
||||
<y>5</y>
|
||||
<width>180</width>
|
||||
<height>116</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="mode_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>375</x>
|
||||
<y>5</y>
|
||||
<width>180</width>
|
||||
<height>116</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="mode_4">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>560</x>
|
||||
<y>5</y>
|
||||
<width>180</width>
|
||||
<height>116</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="bg_mode_1">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>63</x>
|
||||
<y>43</y>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="lb_mode_1">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>63</x>
|
||||
<y>18</y>
|
||||
<width>64</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="split_1">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>187</x>
|
||||
<y>18</y>
|
||||
<width>1</width>
|
||||
<height>90</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="split_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>372</x>
|
||||
<y>18</y>
|
||||
<width>1</width>
|
||||
<height>90</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="split_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>557</x>
|
||||
<y>18</y>
|
||||
<width>1</width>
|
||||
<height>90</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="lb_mode_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>248</x>
|
||||
<y>18</y>
|
||||
<width>64</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="lb_mode_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>433</x>
|
||||
<y>18</y>
|
||||
<width>64</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="lb_mode_4">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>618</x>
|
||||
<y>18</y>
|
||||
<width>64</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="bg_mode_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>248</x>
|
||||
<y>43</y>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="bg_mode_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>433</x>
|
||||
<y>43</y>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="bg_mode_4">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>618</x>
|
||||
<y>43</y>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 747 B |
After Width: | Height: | Size: 1009 B |
After Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 3.6 KiB |