...
 
Commits (6)
    https://gitcode.net/kl222/RabbitRemoteControl/-/commit/262b7cff2ff8b6128ac79c9e522443e39755db23 FreeRDP: Fix reconnet parameter 2023-08-04T09:58:00+08:00 Kang Lin kl222@126.com https://gitcode.net/kl222/RabbitRemoteControl/-/commit/9c9555b4a4aba1851d98e8925c4af43eea71f7c1 CI: modify msvc.yml 2023-08-04T16:34:02+08:00 Kang Lin kl222@126.com https://gitcode.net/kl222/RabbitRemoteControl/-/commit/05ef69643203b5601c06bc8b6119c31ac92032ab FreeRDP::Client: add GetTitle 2023-08-09T10:28:24+08:00 Kang Lin kl222@126.com https://gitcode.net/kl222/RabbitRemoteControl/-/commit/c4d4956ee5368f18bd63551743c2c57292cd1bb2 FreeRDP::Client: add cb_authenticate_ex 2023-08-09T10:28:35+08:00 Kang Lin kl222@126.com https://gitcode.net/kl222/RabbitRemoteControl/-/commit/afb97d7fdab47662c253eb6f50ee11dc2978cbc5 Client: fix clear background in CFrmViewer 2023-08-09T10:58:54+08:00 Kang Lin kl222@126.com https://gitcode.net/kl222/RabbitRemoteControl/-/commit/6fe9eed04de74e483a0fe88358bef13673231404 CI: modify ubuntu.yml to add xcb dependencies 2023-08-11T09:55:25+08:00 Kang Lin kl222@126.com
......@@ -34,7 +34,7 @@ jobs:
runs-on: ubuntu-latest
env:
VCPKGGITCOMMITID: 1286cac8751e13bb289061b7e3b89eb4c3f613a2
VCPKGGITCOMMITID: 980ec0f49d81f794778386f7bd518b2cc9c092f0
VCPKG_ROOT: ${{github.workspace}}/.cache/source/vcpkg
SOURCE_DIR: ${{github.workspace}}/.cache/source
TOOSL_DIR: ${{github.workspace}}/.cache/tools
......
......@@ -37,7 +37,7 @@ jobs:
INSTALL_DIR: ${{github.workspace}}/.cache/install_macos_qt${{matrix.qt_version}}_${{matrix.BUILD_TYPE}}
qt_modules: qtwebengine ${{matrix.qt_modules}}
RabbitRemoteControl_VERSION: v1.0.9
VCPKGGITCOMMITID: 1286cac8751e13bb289061b7e3b89eb4c3f613a2
VCPKGGITCOMMITID: 980ec0f49d81f794778386f7bd518b2cc9c092f0
artifact_name: build_macos
# Map the job outputs to step outputs
......
......@@ -13,21 +13,14 @@ jobs:
strategy:
matrix:
BUILD_TYPE: [Release, Debug]
qt_version: [6.6.0, 6.5.1, 5.15.2, 5.12.12]
qt_version: [6.5.2, 5.15.2, 5.12.12]
include:
- qt_version: 6.6.0
- qt_version: 6.5.2
triplet: x64-windows
VCPKG_PLATFORM_TOOLSET: v142
qt_arch: win64_msvc2019_64
CMAKE_GENERATOR_PLATFORM: x64
qt_modules: qtscxml qtmultimedia qtimageformats qtserialport qtwebchannel qtwebsockets qtwebview qtpositioning
- qt_version: 6.5.1
triplet: x64-windows
VCPKG_PLATFORM_TOOLSET: v142
qt_arch: win64_msvc2019_64
CMAKE_GENERATOR_PLATFORM: x64
qt_modules: qtscxml qtmultimedia qtimageformats qtserialport qtwebchannel qtwebsockets qtwebview qtpositioning
qt_modules: qtscxml qtmultimedia qtimageformats qtwebchannel qtwebsockets qtwebview qtpositioning qtserialport
- qt_version: 5.15.2
triplet: x64-windows
......@@ -51,7 +44,7 @@ jobs:
VCPKG_PLATFORM_TOOLSET: ${{matrix.VCPKG_PLATFORM_TOOLSET}}
CMAKE_GENERATOR_PLATFORM: ${{matrix.CMAKE_GENERATOR_PLATFORM}}
RabbitRemoteControl_VERSION: v0.0.27
VCPKGGITCOMMITID: 1286cac8751e13bb289061b7e3b89eb4c3f613a2
VCPKGGITCOMMITID: 980ec0f49d81f794778386f7bd518b2cc9c092f0
qt_modules: qtwebengine ${{matrix.qt_modules}}
artifact_name: build_msvc
......@@ -211,7 +204,7 @@ jobs:
dir: '${{env.TOOSL_DIR}}/qt' # optional
version: '${{matrix.qt_version}}' # optional, default is 5.15.2
arch: '${{matrix.qt_arch}}' # optional
modules: '${{env.qt_modules}}' # optional
modules: '${{env.qt_modules}}' # optional. see: https://ddalcino.github.io/aqt-list-server/
cached: '${{steps.cache-qt.outputs.cache-hit}}' # optional, default is false
- name: build qxmpp
......@@ -306,22 +299,29 @@ jobs:
7z a RabbitRemoteControl_windows_${{env.RabbitRemoteControl_VERSION}}.zip .\install\*
md5sum RabbitRemoteControl_windows_${{env.RabbitRemoteControl_VERSION}}.zip > RabbitRemoteControl_windows_${{env.RabbitRemoteControl_VERSION}}.zip.md5sum
makensis Install.nsi
md5sum RabbitRemoteControl_Setup_${{env.RabbitRemoteControl_VERSION}}.exe > RabbitRemoteControl_Setup_${{env.RabbitRemoteControl_VERSION}}.exe.md5sum
cp RabbitRemoteControl_Setup_${{env.RabbitRemoteControl_VERSION}}.exe RabbitRemoteControl_${{env.RabbitRemoteControl_VERSION}}_qt_${{matrix.qt_version}}_Setup.exe
md5sum RabbitRemoteControl_${{env.RabbitRemoteControl_VERSION}}_qt_${{matrix.qt_version}}_Setup.exe > RabbitRemoteControl_${{env.RabbitRemoteControl_VERSION}}_qt_${{matrix.qt_version}}_Setup.exe.md5sum
${{github.workspace}}\build\install\bin\RabbitRemoteControlApp.exe ^
-f "update_windows.xml" ^
-u https://github.com/KangLin/RabbitRemoteControl/releases/download/${{env.RabbitRemoteControl_VERSION}}/RabbitRemoteControl_Setup_${{env.RabbitRemoteControl_VERSION}}.exe;https://sourceforge.net/projects/rabbitremotecontrol/files/${{env.RabbitRemoteControl_VERSION}}/RabbitRemoteControl_Setup_${{env.RabbitRemoteControl_VERSION}}.exe ^
--pf RabbitRemoteControl_Setup_${{env.RabbitRemoteControl_VERSION}}.exe ^
-u https://github.com/KangLin/RabbitRemoteControl/releases/download/${{env.RabbitRemoteControl_VERSION}}/RabbitRemoteControl_${{env.RabbitRemoteControl_VERSION}}_qt_${{matrix.qt_version}}_Setup.exe;https://sourceforge.net/projects/rabbitremotecontrol/files/${{env.RabbitRemoteControl_VERSION}}/RabbitRemoteControl_${{env.RabbitRemoteControl_VERSION}}_qt_${{matrix.qt_version}}_Setup.exe ^
--pf RabbitRemoteControl_${{env.RabbitRemoteControl_VERSION}}_qt_${{matrix.qt_version}}_Setup.exe ^
-m "${{env.RabbitRemoteControl_VERSION}}"
- name: Update artifact
if: ${{ matrix.BUILD_TYPE == 'Release' && '5.12.12' == matrix.qt_version }}
if: ${{ matrix.BUILD_TYPE == 'Release' }}
uses: actions/upload-artifact@v3
with:
name: ${{ env.artifact_name }}
path: |
${{github.workspace}}\build\RabbitRemoteControl_${{env.RabbitRemoteControl_VERSION}}_qt_${{matrix.qt_version}}_Setup.exe
- name: Update artifact update_windows.xml
if: ${{ matrix.BUILD_TYPE == 'Release' && '6.5.2' == matrix.qt_version }}
uses: actions/upload-artifact@v3
with:
name: ${{ env.artifact_name }}
path: |
${{github.workspace}}\build\RabbitRemoteControl_Setup_${{env.RabbitRemoteControl_VERSION}}.exe
${{github.workspace}}\build\update_windows.xml
#if: ${{ matrix.BUILD_TYPE == 'Release' }}
# - name: Upload To Github Release
# if: ${{ matrix.BUILD_TYPE == 'Release' && '5.12.12' == matrix.qt_version && startsWith(github.ref, 'refs/tags/') }}
......@@ -336,6 +336,6 @@ jobs:
# files: |
# ${{github.workspace}}\build\RabbitRemoteControl_windows_${{env.RabbitRemoteControl_VERSION}}.zip
# ${{github.workspace}}\build\RabbitRemoteControl_windows_${{env.RabbitRemoteControl_VERSION}}.zip.md5sum
# ${{github.workspace}}\build\RabbitRemoteControl_Setup_${{env.RabbitRemoteControl_VERSION}}.exe
# ${{github.workspace}}\build\RabbitRemoteControl_Setup_${{env.RabbitRemoteControl_VERSION}}.exe.md5sum
# ${{github.workspace}}\build\RabbitRemoteControl_${{env.RabbitRemoteControl_VERSION}}_qt_${{matrix.qt_version}}_Setup.exe
# ${{github.workspace}}\build\RabbitRemoteControl_${{env.RabbitRemoteControl_VERSION}}_qt_${{matrix.qt_version}}_Setup.exe.md5sum
# ${{github.workspace}}\build\update_windows.xml
......@@ -99,7 +99,9 @@ jobs:
qt6-scxml-dev qt6-multimedia-dev libqt6serialport6-dev \
qt6-webengine-dev qt6-webengine-dev-tools \
libxkbcommon-dev libxkbcommon-x11-dev xorg-dev libx11-xcb-dev \
libx11-dev libxfixes-dev \
libx11-dev libxfixes-dev libxcb-randr0-dev libxcb-shm0-dev \
libxcb-xinerama0-dev libxcb-composite0-dev libxcomposite-dev \
libxinerama-dev libxcb1-dev libx11-xcb-dev libxcb-xfixes0-dev \
libpixman-1-dev libpam0g-dev libutf8proc-dev \
libfuse3-dev libusb-1.0-0-dev \
libvncserver-dev libssh-dev libtelnet-dev freerdp2-dev
......
......@@ -87,7 +87,7 @@ int main(int argc, char *argv[])
}
if(pUpdate->GenerateUpdateXml())
qCritical(App) << "GenerateUpdateXml fail";
else
else
return 0;
#endif
......
......@@ -92,6 +92,16 @@ void CFrmViewer::paintDesktop()
if(!m_Desktop.isNull())
{
QPainter painter(this);
// Clear background
if(KeepAspectRationToWindow == m_AdaptWindows)
{
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
painter.fillRect(rect(), QBrush(palette().color(QPalette::Window)));
#else
painter.fillRect(rect(), QBrush(palette().color(QPalette::Background)));
#endif
}
// 设置平滑模式
painter.setRenderHint(QPainter::SmoothPixmapTransform);
painter.drawImage(dstRect, m_Desktop);
......
......@@ -176,8 +176,8 @@ int CConnectFreeRDP::OnClean()
*
* \~
* \return
* \li >= 0: continue, Interval call time (msec)
* \li < 0: error or stop
* \li >= 0: continue, Interval call time (msec)
* \li < 0: error or stop
* \see slotTimeOut()
*/
int CConnectFreeRDP::OnProcess()
......@@ -218,9 +218,18 @@ int CConnectFreeRDP::OnProcess()
if (!freerdp_check_event_handles(pRdpContext))
{
nRet = -5;
UINT32 err = freerdp_get_last_error(pRdpContext);
qCritical(FreeRDPConnect) << "freerdp_check_event_handles[" << err << "]"
<< freerdp_get_last_error_category(err) << "-"
<< freerdp_get_last_error_name(err) << ":"
<< freerdp_get_last_error_string(err);
// Reconnect
if(pRdpContext->settings->AutoReconnectionEnabled)
bool bReconnect = freerdp_settings_get_bool(pRdpContext->settings,
FreeRDP_AutoReconnectionEnabled);
qDebug(FreeRDPConnect) << "Reconnect:" << bReconnect;
if(bReconnect)
{
qDebug(FreeRDPConnect) << "Reconnect" << m_pParameter->GetReconnectInterval() * 1000;
if (client_auto_reconnect_ex(pRdpContext->instance, NULL))
return m_pParameter->GetReconnectInterval() * 1000;
else
......@@ -232,9 +241,13 @@ int CConnectFreeRDP::OnProcess()
if (freerdp_error_info(pRdpContext->instance) == 0)
nRet = -6;
}
if (freerdp_get_last_error(pRdpContext) == FREERDP_ERROR_SUCCESS)
qCritical(FreeRDPConnect) << "Failed to check FreeRDP file descriptor";
UINT32 err = freerdp_get_last_error(pRdpContext);
if (FREERDP_ERROR_SUCCESS != err)
qCritical(FreeRDPConnect) << "Auto reconnection[" << err << "]"
<< freerdp_get_last_error_category(err)
<< freerdp_get_last_error_name(err)
<< freerdp_get_last_error_string(err);
}
}
}
......@@ -267,11 +280,14 @@ BOOL CConnectFreeRDP::cb_client_new(freerdp *instance, rdpContext *context)
instance->PreConnect = cb_pre_connect;
instance->PostConnect = cb_post_connect;
instance->PostDisconnect = cb_post_disconnect;
// Because it is already set in the parameters
instance->Authenticate = cb_authenticate;
instance->GatewayAuthenticate = cb_GatewayAuthenticate;
#if FreeRDP_VERSION_MAJOR < 3
instance->Authenticate = cb_authenticate;
instance->GatewayAuthenticate = cb_GatewayAuthenticate;
#else
instance->AuthenticateEx = cb_authenticate_ex;
#endif
instance->VerifyCertificateEx = cb_verify_certificate_ex;
instance->VerifyChangedCertificateEx = cb_verify_changed_certificate_ex;
instance->PresentGatewayMessage = cb_present_gateway_message;
......@@ -321,12 +337,12 @@ BOOL CConnectFreeRDP::cb_pre_connect(freerdp* instance)
rdpChannels* channels = nullptr;
rdpSettings* settings = nullptr;
rdpContext* context = instance->context;
if (!instance || !instance->context || !instance->context->settings)
{
{
return FALSE;
}
settings = instance->context->settings;
channels = context->channels;
......@@ -338,7 +354,7 @@ BOOL CConnectFreeRDP::cb_pre_connect(freerdp* instance)
settings->OsMajorType = OSMAJORTYPE_UNIX;
settings->OsMinorType = OSMINORTYPE_NATIVE_XSERVER;
#endif
// Subscribe channel event
PubSub_SubscribeChannelConnected(instance->context->pubSub,
OnChannelConnectedEventHandler);
......@@ -361,16 +377,21 @@ BOOL CConnectFreeRDP::cb_pre_connect(freerdp* instance)
qWarning(FreeRDPConnect) << "No user name set. - Using login name:" << settings->Username;
}
if (settings->AuthenticationOnly)
{
/* Check +auth-only has a username and password. */
if (!settings->Password)
{
qCritical(FreeRDPConnect) << "auth-only, but no password set. Please provide one.";
return FALSE;
}
qInfo(FreeRDPConnect) << "Authentication only. Don't connect to X.";
if (freerdp_settings_get_bool(settings, FreeRDP_AuthenticationOnly))
{
/* Check +auth-only has a username and password. */
if (!freerdp_settings_get_string(settings, FreeRDP_Password))
{
qCritical(FreeRDPConnect) << "auth-only, but no password set. Please provide one.";
return FALSE;
}
#if FreeRDP_VERSION_MAJOR > 2
if (!freerdp_settings_set_bool(settings, FreeRDP_DeactivateClientDecoding, TRUE))
return FALSE;
#endif
qInfo(FreeRDPConnect) << "Authentication only. Don't connect to X.";
} else {
}
// Keyboard layout
......@@ -393,6 +414,43 @@ BOOL CConnectFreeRDP::cb_pre_connect(freerdp* instance)
return TRUE;
}
const char* CConnectFreeRDP::GetTitle(freerdp* instance)
{
const char* windowTitle;
UINT32 port;
BOOL addPort;
const char* name = nullptr;
CConnectFreeRDP* pThis = ((ClientContext*)instance->context)->pThis;
rdpSettings* settings = instance->context->settings;
if (!settings)
return nullptr;
windowTitle = freerdp_settings_get_string(settings, FreeRDP_WindowTitle);
if (windowTitle)
return _strdup(windowTitle);
#if FreeRDP_VERSION_MAJOR >= 3
name = freerdp_settings_get_server_name(settings);
#else
name = pThis->m_pParameter->GetHost().toStdString().c_str();
#endif
port = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort);
addPort = (port != 3389);
char buffer[MAX_PATH + 64] = { 0 };
if (!addPort)
sprintf_s(buffer, sizeof(buffer), "%s", name);
else
sprintf_s(buffer, sizeof(buffer), "%s:%" PRIu32, name, port);
freerdp_settings_set_string(settings, FreeRDP_WindowTitle, buffer);
return freerdp_settings_get_string(settings, FreeRDP_WindowTitle);
}
/**
* Callback given to freerdp_connect() to perform post-connection operations.
* It will be called only if the connection was initialized properly, and will continue the
......@@ -407,11 +465,7 @@ BOOL CConnectFreeRDP::cb_post_connect(freerdp* instance)
rdpUpdate* update = instance->context->update;
CConnectFreeRDP* pThis = ((ClientContext*)instance->context)->pThis;
Q_ASSERT(context);
Q_ASSERT(settings);
Q_ASSERT(pThis);
const char* pWindowTitle = freerdp_settings_get_string(settings, FreeRDP_WindowTitle);
const char* pWindowTitle = GetTitle(instance);
if(pWindowTitle)
{
WCHAR* windowTitle = NULL;
......@@ -424,7 +478,6 @@ BOOL CConnectFreeRDP::cb_post_connect(freerdp* instance)
{
QString title = QString::fromUtf16((const char16_t*)windowTitle);
emit pThis->sigServerName(title);
free(windowTitle);
}
}
int desktopWidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
......@@ -617,6 +670,18 @@ UINT32 CConnectFreeRDP::GetImageFormat()
return GetImageFormat(m_Image.format());
}
#if FreeRDP_VERSION_MAJOR > 3
//TODO: implement it!!!
static BOOL CConnectFreeRDP::cb_authenticate_ex(freerdp* instance,
char** username, char** password,
char** domain, rdp_auth_reason reason)
{
qCritical(FreeRDPConnect) << "CConnectFreeRdp::cb_authenticate_ex is not implement";
Q_ASSERT(false);
return TRUE;
}
#endif
BOOL CConnectFreeRDP::cb_authenticate(freerdp* instance, char** username,
char** password, char** domain)
{
......
......@@ -62,26 +62,38 @@ public:
const
#endif
ChannelDisconnectedEventArgs* e);
static BOOL cb_authenticate(freerdp* instance, char** username, char** password, char** domain);
static BOOL cb_GatewayAuthenticate(freerdp* instance, char** username, char** password, char** domain);
static DWORD cb_verify_certificate_ex(freerdp* instance, const char* host, UINT16 port,
const char* common_name, const char* subject,
const char* issuer, const char* fingerprint, DWORD flags);
static DWORD cb_verify_changed_certificate_ex(freerdp* instance, const char* host, UINT16 port,
const char* common_name, const char* subject,
const char* issuer, const char* fingerprint,
const char* old_subject, const char* old_issuer,
const char* old_fingerprint, DWORD flags);
static BOOL cb_present_gateway_message(freerdp* instance, UINT32 type, BOOL isDisplayMandatory,
BOOL isConsentMandatory, size_t length, const WCHAR* message);
static BOOL cb_authenticate(freerdp* instance,
char** username, char** password, char** domain);
static BOOL cb_GatewayAuthenticate(freerdp* instance,
char** username, char** password, char** domain);
#if FreeRDP_VERSION_MAJOR > 3
static BOOL cb_authenticate_ex(freerdp* instance,
char** username, char** password,
char** domain, rdp_auth_reason reason);
#endif
static DWORD cb_verify_certificate_ex(freerdp* instance,
const char* host, UINT16 port,
const char* common_name, const char* subject,
const char* issuer, const char* fingerprint, DWORD flags);
static DWORD cb_verify_changed_certificate_ex(freerdp* instance,
const char* host, UINT16 port,
const char* common_name, const char* subject,
const char* issuer, const char* fingerprint,
const char* old_subject, const char* old_issuer,
const char* old_fingerprint, DWORD flags);
static BOOL cb_present_gateway_message(freerdp* instance,
UINT32 type, BOOL isDisplayMandatory,
BOOL isConsentMandatory, size_t length, const WCHAR* message);
static BOOL cb_begin_paint(rdpContext* context);
static BOOL cb_end_paint(rdpContext* context);
static BOOL cb_desktop_resize(rdpContext* context);
static BOOL cb_play_bell_sound(rdpContext* context, const PLAY_SOUND_UPDATE* play_sound);
static BOOL cb_play_bell_sound(rdpContext* context,
const PLAY_SOUND_UPDATE* play_sound);
static UINT32 GetImageFormat(QImage::Format format);
static const char* GetTitle(freerdp *instance);
private:
UINT32 GetImageFormat();
......
......@@ -26,17 +26,18 @@ qint16 CConnecterFreeRDP::Version()
return 0;
}
QDialog *CConnecterFreeRDP::GetDialogSettings(QWidget *parent)
QDialog* CConnecterFreeRDP::GetDialogSettings(QWidget *parent)
{
return new CDlgSetFreeRDP(&m_ParameterFreeRdp, parent);
}
CConnect *CConnecterFreeRDP::InstanceConnect()
CConnect* CConnecterFreeRDP::InstanceConnect()
{
try{
CConnectFreeRDP* p = new CConnectFreeRDP(this);
return p;
} catch(...) {
qDebug(m_Logger) << "CConnecterFreeRDP::InstanceConnect() exception";
return nullptr;
}
}
......@@ -5,7 +5,6 @@
#include "Connecter.h"
#include "ConnecterDesktopThread.h"
#include "freerdp/freerdp.h"
#include "ParameterFreeRDP.h"
#include <QLoggingCategory>
......
......@@ -111,16 +111,19 @@ UINT CParameterFreeRDP::GetReconnectInterval() const
void CParameterFreeRDP::SetReconnectInterval(UINT newReconnectInterval)
{
if (m_nReconnectInterval == newReconnectInterval)
return;
m_nReconnectInterval = newReconnectInterval;
if(m_nReconnectInterval)
Q_ASSERT(newReconnectInterval >= 0);
if(newReconnectInterval)
freerdp_settings_set_bool(m_pSettings,
FreeRDP_AutoReconnectionEnabled, true);
else
freerdp_settings_set_bool(m_pSettings,
FreeRDP_AutoReconnectionEnabled, false);
if (m_nReconnectInterval == newReconnectInterval)
return;
m_nReconnectInterval = newReconnectInterval;
SetModified(true);
emit sigReconnectIntervalChanged();
}
......
......@@ -81,6 +81,8 @@ Interested and capable friends are welcome to participate in the development of
If you want to donate the developed devices for me, please contact: (email: kl222@126.com)
See: [Qt5](https://doc.qt.io/qt-5/supported-platforms.html), [Qt6](https://doc.qt.io/qt-6/supported-platforms.html)
| |Windows|Unix/linux|Android|MAC|IPHONE|WINCE|
|--------|:-----:|:--------:|:-----:|:-:|:----:|:---:|
|vnc |✓ |✓ | | | | |
......@@ -164,12 +166,12 @@ Legend: ✓ : completed; … : working; ⭕ : not completed; Empty: not started;
## Status
[![Documentation](https://img.shields.io/badge/documentation-online-blue)](https://kanglin.github.io/RabbitRemoteControl/English/html/index.html)
[![GitHub stars](https://img.shields.io/github/stars/KangLin/RabbitRemoteControl?label=Github%20stars)](https://star-history.com/#KangLin/RabbitRemoteControl&Date)
[![Gitee stars](https://gitee.com/kl222/RabbitRemoteControl/badge/star.svg?theme=dark)](https://gitee.com/kl222/RabbitRemoteControl/stargazers)
[![Latest Release](https://img.shields.io/github/release/KangLin/RabbitRemoteControl.svg?label=Github%20latest%20Release)](https://github.com/KangLin/RabbitRemoteControl/releases/latest)
[![Release](https://img.shields.io/github/release-pre/KangLin/RabbitRemoteControl?label=Github%20Release)](https://github.com/KangLin/RabbitRemoteControl/releases)
[![Downloads from github](https://img.shields.io/github/downloads/KangLin/RabbitRemoteControl/total?label=Github%20downloads)](http://gra.caldis.me/?user=KangLin&repo=RabbitRemoteControl)
[![Download RabbitRemoteControl](https://a.fsdn.com/con/app/sf-download-button)](https://sourceforge.net/projects/rabbitremotecontrol/files/latest/download)
[![Downloads from github](https://img.shields.io/github/downloads/KangLin/RabbitRemoteControl/total?label=Github%20downloads)](http://gra.caldis.me/?user=KangLin&repo=RabbitRemoteControl)
[![Downloads from sourceforge](https://img.shields.io/sourceforge/dt/rabbitremotecontrol.svg?label=Sourceforge%20downloads)](https://sourceforge.net/projects/rabbitremotecontrol/files/latest/download)
[![Gitter](https://badges.gitter.im/RabbitRemoteControl/community.svg)](https://gitter.im/RabbitRemoteControl/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
......@@ -190,9 +192,6 @@ Legend: ✓ : completed; … : working; ⭕ : not completed; Empty: not started;
[![platform](https://img.shields.io/badge/platform-windows%20|%20linux%20|%20android%20|%20macos-blue.svg)](https://github.com/KangLin/RabbitRemoteControl)
[![GitHub stars](https://img.shields.io/github/stars/KangLin/RabbitRemoteControl?label=Github%20stars)](https://star-history.com/#KangLin/RabbitRemoteControl&Date)
[![Gitee stars](https://gitee.com/kl222/RabbitRemoteControl/badge/star.svg?theme=dark)](https://gitee.com/kl222/RabbitRemoteControl/stargazers)
### Build status
| | master | develop |
......
......@@ -81,6 +81,8 @@
如果你想为本人捐赠开发设备,请联系:kl222@126.com
详见:[Qt5 支持平台](https://doc.qt.io/qt-5/supported-platforms.html)[Qt6 支持平台](https://doc.qt.io/qt-6/supported-platforms.html)
| |Windows|Unix/linux|Android|MAC|IPHONE|WINCE|
|--------|-------|----------|-------|---|------|-----|
|vnc |✓ |✓ | | | | |
......@@ -164,12 +166,12 @@
## 状态
[![文档](https://img.shields.io/badge/documentation-online-blue?label=文档)](https://kanglin.github.io/RabbitRemoteControl/Chinese/html/index.html)
[![GitHub stars](https://img.shields.io/github/stars/KangLin/RabbitRemoteControl?label=点赞量)](https://star-history.com/#KangLin/RabbitRemoteControl&Date)
[![Gitee stars](https://gitee.com/kl222/RabbitRemoteControl/badge/star.svg?theme=dark)](https://gitee.com/kl222/RabbitRemoteControl/stargazers)
[![Github 发行版本](https://img.shields.io/github/release-pre/KangLin/RabbitRemoteControl?label=Github%20发行版本)](https://github.com/KangLin/RabbitRemoteControl/releases)
[![Github 最后发行版本](https://img.shields.io/github/release/KangLin/RabbitRemoteControl?label=Github%20最后发行版本)](https://github.com/KangLin/RabbitRemoteControl/releases)
[![Github 所有发行版本下载量](https://img.shields.io/github/downloads/KangLin/RabbitRemoteControl/total?label=Github%20下载总量)](http://gra.caldis.me/?user=KangLin&repo=RabbitRemoteControl)
[![Download from sourceforge](https://a.fsdn.com/con/app/sf-download-button)](https://sourceforge.net/projects/rabbitremotecontrol/files/latest/download)
[![Github 所有发行版本下载量](https://img.shields.io/github/downloads/KangLin/RabbitRemoteControl/total?label=Github%20下载总量)](http://gra.caldis.me/?user=KangLin&repo=RabbitRemoteControl)
[![从 sourceforge 下载量](https://img.shields.io/sourceforge/dt/rabbitremotecontrol.svg?label=Sourceforge%20下载总量)](https://sourceforge.net/projects/rabbitremotecontrol/files/latest/download)
[![Gitter](https://badges.gitter.im/RabbitRemoteControl/community.svg)](https://gitter.im/RabbitRemoteControl/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
......@@ -190,9 +192,6 @@
[![平台](https://img.shields.io/badge/平台-windows%20|%20linux%20|%20android%20|%20macos-blue.svg)](https://github.com/KangLin/RabbitRemoteControl)
[![GitHub stars](https://img.shields.io/github/stars/KangLin/RabbitRemoteControl?label=点赞量)](https://star-history.com/#KangLin/RabbitRemoteControl&Date)
[![Gitee stars](https://gitee.com/kl222/RabbitRemoteControl/badge/star.svg?theme=dark)](https://gitee.com/kl222/RabbitRemoteControl/stargazers)
### 编译状态
| | master 分支 | develop 分支 |
......