Import Upstream version 3.1.2.28

This commit is contained in:
谢炜 2022-06-02 16:34:03 +08:00
commit 70f6b202dd
423 changed files with 50204 additions and 0 deletions

86
.github/workflows/build.yml vendored Normal file
View File

@ -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);

2
AUTHORS Normal file
View File

@ -0,0 +1,2 @@
UIUI:
yanghao <yanghao@kylinos.cn>

346
COPYING Normal file
View File

@ -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.

61
README.md Normal file
View File

@ -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**
- 功能插件

View File

@ -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

162
greeter-nm-helper/main.cpp Normal file
View File

@ -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();
}

View File

@ -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>

View File

@ -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:
};

View File

@ -0,0 +1,2 @@
#!/bin/bash
/usr/lib/ukui-greeter/greeter-nm-helper &

4
ukui-greeter.pro Normal file
View File

@ -0,0 +1,4 @@
TEMPLATE = subdirs
SUBDIRS += \
ukui-greeter \
greeter-nm-helper

View File

@ -0,0 +1,4 @@
[Seat:*]
greeter-session=ukui-greeter
user-session=ukui
greeter-setup-script=/usr/lib/ukui-greeter/ukui-greeter-nm-start.sh

View File

@ -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

View File

@ -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 +=

View File

@ -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>

View File

@ -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);
}

View File

@ -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

View File

@ -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");
}

View File

@ -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 Identifyops状态
*/
/* 定义操作类型 */
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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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();
}

View File

@ -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)

View File

@ -0,0 +1 @@
A simple virtual keyboard in X11

View File

@ -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

View File

@ -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

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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";
}

View File

@ -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

View File

@ -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();
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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>

View File

@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 747 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1009 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Some files were not shown because too many files have changed in this diff Show More