diff --git a/kxterm/qkxtermitem.cpp b/kxterm/qkxtermitem.cpp index fe3c40f..e9b2e2d 100644 --- a/kxterm/qkxtermitem.cpp +++ b/kxterm/qkxtermitem.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #define REPAINT_TIMEOUT1 (20) #define REPAINT_TIMEOUT2 (40) @@ -964,6 +965,12 @@ void QKxTermItem::onBlinkTimeout() } } } + + qint64 now = QDateTime::currentMSecsSinceEpoch(); + if(now - m_updateFullLast > 1000) { + m_updateFullLast = now; + update(QRect(0, 0, int(width()), int(height()))); + } } void QKxTermItem::onSelectChanged() @@ -1588,6 +1595,10 @@ void QKxTermItem::updateView(QKxTermItem::PaintFlag flags) m_ticker2->setSingleShot(true); m_ticker2->start(REPAINT_TIMEOUT2); } + + if(flags & PF_FullScreen) { + m_updateFullLast = QDateTime::currentMSecsSinceEpoch(); + } } void QKxTermItem::updateScrollValue(int val) diff --git a/kxterm/qkxtermitem.h b/kxterm/qkxtermitem.h index d3b7fc2..ff2637f 100644 --- a/kxterm/qkxtermitem.h +++ b/kxterm/qkxtermitem.h @@ -354,6 +354,7 @@ public slots: int m_lineDragStart; + qint64 m_updateFullLast; }; #endif // QTERM_H diff --git a/kxutil/qkxcipher.cpp b/kxutil/qkxcipher.cpp index f644218..8e6ba95 100644 --- a/kxutil/qkxcipher.cpp +++ b/kxutil/qkxcipher.cpp @@ -48,7 +48,7 @@ QByteArray QKxCipher::makeBytes(const QByteArray &pass, int cnt) QByteArray tmp = pass; if(pass.length() < cnt) { int left = cnt - pass.length(); - tmp.append(left, 0); + tmp.append(left, '0'); }else if(pass.length() > cnt) { tmp.resize(cnt); } @@ -273,7 +273,7 @@ static bool EvpEncrypt(EVP_CIPHER_CTX *ctx, const QByteArray &in, QByteArray &ou } int mlen = 0; - out.resize(in.size() + AES_BLOCK_SIZE); + out.fill(0, in.size() + AES_BLOCK_SIZE); ret = EVP_EncryptUpdate(ctx, (unsigned char*)out.data(), &mlen, (const unsigned char*)in.data(), in.size()); if(ret != 1) { return false; @@ -292,15 +292,19 @@ static bool EvpEncrypt(EVP_CIPHER_CTX *ctx, const QByteArray &in, QByteArray &ou return false; } int mlen = 0; - out.resize(in.size()); + out.fill(0, in.size()); ret = EVP_DecryptUpdate(ctx, (unsigned char*)out.data(), &mlen, (const unsigned char*)in.data(), in.size()); if(ret != 1) { return false; } int flen = 0; - ret = EVP_DecryptFinal_ex(ctx, (unsigned char *)out.data() + mlen, &flen); - if(ret != 1) { - return false; + // https://blog.csdn.net/anda0109/article/details/51281070 + // This instruction only needs to be called when the bytes are not aligned to 16 bytes. + if((in.length() % AES_BLOCK_SIZE) != 0) { + ret = EVP_DecryptFinal_ex(ctx, (unsigned char *)out.data() + mlen, &flen); + if(ret != 1) { + return false; + } } out.resize(mlen + flen); return true; @@ -598,18 +602,6 @@ bool QKxCipher::blowfishEcbEncrypt(const QByteArray &in, QByteArray &out, const void QKxCipher::test() { - { - QByteArray in = "Text may be any length you wish, no padding is required."; - QByteArray out, out2; - uchar key[16] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; - uchar iv[16] = {21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36}; - - aesOfb128Encrypt(in, out, QByteArray((char*)key,16), QByteArray((char*)iv, 16), true); - QByteArray txt = out.toHex(); - qDebug() << txt; - Q_ASSERT(in == out2); - } - return; { QByteArray in = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789"; QByteArray out, out2, key = "123"; @@ -670,6 +662,7 @@ void QKxCipher::test() QByteArray in = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789"; QByteArray out, out2, key = "123"; key = makeBytes(key, 16); + in.resize(48); aesGcmEncrypt(in, out, key, key, true); aesGcmEncrypt(out, out2, key, key, false); Q_ASSERT(in == out2); @@ -742,13 +735,15 @@ void QKxCipher::test() rc4Encrypt(out, out2, key, false); Q_ASSERT(in == out2); } + if(true) { QByteArray in = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz01234567"; QByteArray out, out2, key = "123", ivec="123"; key = makeBytes(key, 16); ivec = makeBytes(ivec, 8); - blowfishEcbEncrypt(in, out, key, ivec, true); + blowfishEcbEncrypt(QKxCipher::pkcs7Padding(in, 8), out, key, ivec, true); blowfishEcbEncrypt(out, out2, key, ivec, false); - Q_ASSERT(in == out2); + QByteArray my = QKxCipher::pkcs7UnPadding(out2); + Q_ASSERT(in == my); } } diff --git a/kxutil/qkxhttpclient.cpp b/kxutil/qkxhttpclient.cpp index 933916f..0deffde 100644 --- a/kxutil/qkxhttpclient.cpp +++ b/kxutil/qkxhttpclient.cpp @@ -27,6 +27,9 @@ QKxHttpClient::QKxHttpClient(QObject *parent) QKxHttpClient::~QKxHttpClient() { + if(m_manager) { + delete m_manager; + } qDebug() << "deleteLater"; } @@ -53,12 +56,13 @@ bool QKxHttpClient::get(const QString &_url) QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SIGNAL(downloadProgress(qint64,qint64))); QObject::connect(reply, SIGNAL(finished()), this, SLOT(onFinished())); m_reply = reply; + m_lastError.clear(); return true; } -bool QKxHttpClient::post(const QString &url, const QByteArray &data) +bool QKxHttpClient::post(const QString &url, const QByteArray &data, const QString& contentType) { - if(m_reply != nullptr || !m_reply->isFinished()) { + if(m_reply != nullptr && !m_reply->isFinished()) { return false; } if(m_file) { @@ -68,13 +72,17 @@ bool QKxHttpClient::post(const QString &url, const QByteArray &data) if(m_reply != nullptr) { m_reply->deleteLater(); } - QNetworkReply *reply = m_manager->post(QNetworkRequest(QUrl(url)), data); + + QNetworkRequest req = QNetworkRequest(QUrl(url)); + req.setHeader(QNetworkRequest::ContentTypeHeader, contentType); + QNetworkReply *reply = m_manager->post(req, data); QObject::connect(reply, SIGNAL(readyRead()), this, SLOT(onReadyRead())); QObject::connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onError())); QObject::connect(reply, SIGNAL(sslErrors(QList)), this, SLOT(onSslError())); QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SIGNAL(downloadProgress(qint64,qint64))); QObject::connect(reply, SIGNAL(finished()), this, SLOT(onFinished())); m_reply = reply; + m_lastError.clear(); return true; } @@ -99,6 +107,11 @@ QString QKxHttpClient::fileSavePath() const return m_fileSave; } +QString QKxHttpClient::lastErrorString() const +{ + return m_lastError; +} + void QKxHttpClient::onReadyRead() { QByteArray all = m_reply->readAll(); @@ -117,7 +130,9 @@ void QKxHttpClient::onReadyRead() void QKxHttpClient::onError() { QNetworkReply *reply = qobject_cast(sender()); - qInfo() << reply->url() << reply->errorString(); + m_lastError = reply->errorString(); + qInfo() << reply->url() << m_lastError; + } void QKxHttpClient::onSslError() @@ -130,7 +145,9 @@ void QKxHttpClient::onFinished() { QNetworkReply *reply = qobject_cast(sender()); QVariant code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); - qInfo() << reply->url() << code; + if(!code.isValid()) { + m_lastError = reply->errorString(); + } if(m_file) { m_file->close(); m_file->deleteLater(); diff --git a/kxutil/qkxhttpclient.h b/kxutil/qkxhttpclient.h index 775b8e3..b54bb50 100644 --- a/kxutil/qkxhttpclient.h +++ b/kxutil/qkxhttpclient.h @@ -1,4 +1,4 @@ -/******************************************************************************************* +/******************************************************************************************* * * Copyright (C) 2022 Guangzhou AoYiDuo Network Technology Co.,Ltd. All Rights Reserved. * @@ -27,10 +27,11 @@ class KXUTIL_EXPORT QKxHttpClient : public QObject explicit QKxHttpClient(QObject *parent = nullptr); virtual ~QKxHttpClient(); bool get(const QString& url); - bool post(const QString& url, const QByteArray& data); + bool post(const QString& url, const QByteArray& data, const QString& contentType = "application/text"); bool fileGet(const QString& url, const QString& fileSave); bool filePost(const QString& url, const QByteArray& data, const QString& fileSave); QString fileSavePath() const; + QString lastErrorString() const; signals: void result(int code, const QByteArray& body); void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); @@ -43,6 +44,7 @@ private slots: private: QPointer m_manager; QPointer m_reply; + QString m_lastError; QByteArray m_data; QString m_fileSave; QPointer m_file; diff --git a/kxutil/qkxsetting.cpp b/kxutil/qkxsetting.cpp index 6720f44..fe481fe 100644 --- a/kxutil/qkxsetting.cpp +++ b/kxutil/qkxsetting.cpp @@ -90,7 +90,7 @@ QString QKxSetting::applicationFilePath() if(path.isEmpty()) { char buffer[1024] = {0}; ::GetModuleFileNameA(0, buffer, 1023); - path = buffer; + path = buffer;// application } path = QDir::cleanPath(path); return path; diff --git a/woterm/CMakeLists.txt b/woterm/CMakeLists.txt index e460bf0..31da2d1 100644 --- a/woterm/CMakeLists.txt +++ b/woterm/CMakeLists.txt @@ -27,10 +27,10 @@ set(SOURCE_FILES qkxbuttonassist.cpp qkxfilterbox.cpp qkxfilterlineedit.cpp - qkxfilterlistview.cpp - qkxlicensedialog.cpp + qkxfilterlistview.cpp qkxmessagebox.cpp qkxtouchpoint.cpp + qkxloadingbarwidget.cpp #window object main.cpp qwoapplication.cpp @@ -118,6 +118,10 @@ set(SOURCE_FILES qwogroupinputdialog.cpp qwofontlistmodel.cpp qworecenthistory.cpp + qwolicensedialog.cpp + qwolicenseactivatedialog.cpp + qwoversionupgradetipdialog.cpp + qwolicensetrialapplydialog.cpp qwotelnet.cpp qwoutils.cpp qwowidget.cpp @@ -165,10 +169,10 @@ set(HEADER_FILES qkxbuttonassist.h qkxfilterbox.h qkxfilterlineedit.h - qkxfilterlistview.h - qkxlicensedialog.h + qkxfilterlistview.h qkxtouchpoint.h qkxmessagebox.h + qkxloadingbarwidget.h # window object qwoapplication.h qwomenubutton.h @@ -256,6 +260,10 @@ set(HEADER_FILES qwogroupinputdialog.h qwofontlistmodel.h qworecenthistory.h + qwolicensedialog.h + qwolicenseactivatedialog.h + qwoversionupgradetipdialog.h + qwolicensetrialapplydialog.h qwotelnet.h qwoutils.h qwowidget.h @@ -304,8 +312,7 @@ set(HEADER_FILES set(OTHER_FILES woterm.qrc # window object - qkxfilterlistview.ui - qkxlicensedialog.ui + qkxfilterlistview.ui qwoaboutdialog.ui qwomenubutton.ui qwoadmindialog.ui @@ -341,6 +348,10 @@ set(OTHER_FILES qwobindportpermissiondialog.ui qwodbsftpdownlistdialog.ui qwogroupinputdialog.ui + qwolicensedialog.ui + qwolicenseactivatedialog.ui + qwoversionupgradetipdialog.ui + qwolicensetrialapplydialog.ui #mobile object qmomainwindow.ui diff --git a/woterm/language/update.bat b/woterm/language/update.bat index 0bbdd40..d963f49 100644 --- a/woterm/language/update.bat +++ b/woterm/language/update.bat @@ -8,5 +8,5 @@ echo %path_script% cd %path_script% rem lupdate -recursive %path_script%\..\ -I %path_script%\..\..\kxftp -I %path_script%\..\..\kxvnc -I %path_script%\..\..\kxutil -I %path_script%\..\..\kxterm %path_script%\..\qml -ts %path_script%woterm_en.ts -lupdate -recursive %path_script%\..\ %path_script%\..\..\kxftp %path_script%\..\..\kxvnc %path_script%\..\..\kxutil %path_script%\..\..\kxterm %path_script%\..\qml -ts %path_script%woterm_zh.ts +lupdate -recursive %path_script%\..\ %path_script%\..\..\kxftp %path_script%\..\..\kxvnc %path_script%\..\..\kxutil %path_script%\..\..\kxver %path_script%\..\..\kxterm %path_script%\..\qml -ts %path_script%woterm_zh.ts pause \ No newline at end of file diff --git a/woterm/language/woterm_zh.qm b/woterm/language/woterm_zh.qm index 95e0c70..5949262 100644 Binary files a/woterm/language/woterm_zh.qm and b/woterm/language/woterm_zh.qm differ diff --git a/woterm/language/woterm_zh.ts b/woterm/language/woterm_zh.ts index 5d54985..73fa9f0 100644 --- a/woterm/language/woterm_zh.ts +++ b/woterm/language/woterm_zh.ts @@ -1077,6 +1077,20 @@ 替换 + + QKxBaseLicense + + + failed to verify code. + 校验失败 + + + + + failed to verify code + 校验失败 + + QKxConfirmWidget @@ -1372,32 +1386,62 @@ 无法打开文件 + + QKxInitClient + + + + Failed to connect to remote server. + 无法连接远程服务。 + + + + QKxLicense + + + + + + failed to verify the license key + 校验许可证失败 + + + + The current version is lower and does not support this license key. Please upgrade to the latest version. + 当前版本较低,不支持该版本的许可证,请升级至最新版本。 + + + + failed to extract the license key information + 无法提取许可证信息 + + + + the license key information is not match the local device. + 许可证信息与本地设备不匹配。 + + QKxLicenseDialog - Dialog - 对话框 + 对话框 - License type: - 许可证类型: + 许可证类型: - Activate - 激活 + 激活 - Close - 关闭 + 关闭 - License - 许可证 + 许可证 @@ -2319,27 +2363,27 @@ 密码输入 - + The current records are exactly the same. 当前记录是完全相同的。 - + Number of records that can be added: %1 可添加的记录数量:%1 - + Number of records that can be removed: %1 可移除的记录数量:%1 - + Number of records that can be replaced: %1 可替换的记录数量:%1 - + Number of records that are the same: %1 相同的记录数量:%1 @@ -2407,17 +2451,16 @@ 最新版本: - Ultimate version day left: - 旗舰版剩余天数: + 旗舰版剩余天数: - + Offcie website: 官网: - + Check Version 检查版本 @@ -2441,6 +2484,36 @@ TextLabel 标签 + + + Unknow version + 未知版本 + + + + Free version + 免费版本 + + + + Trial version + 试用版 + + + + School version + 校园版 + + + + Ultimate version + 旗舰版 + + + + expired + 已过期 + QWoAdminDialog @@ -3964,6 +4037,442 @@ 公钥 + + QWoLicenseActivateDialog + + + Activation + 激活 + + + + License key + 许可证号: + + + + Redeem code + 兑换码 + + + + The redeem code is only used to obtain licenses online and bind to the target device. Once the exchange is successful, it will become invalid. Please save the license key, which can still be used during system reinstallation. + 兑换码只用于联网获取许可证并绑定至本地设备,一旦绑定成功,它将失效。请小心保存许可证号,以防系统重装的恢复需要。 + + + + Redeem code: + 兑换码: + + + + Redeem + 兑换 + + + + + Close + 关闭 + + + + The license is created by a machine code, so the license only corresponds to one machine code. Please save the license key, which can still be used during system reinstallation. + 许可证是通过机器码创建的,所以一个许可证只匹配一个机器码。请小心保存许可证号,以防系统重装的恢复需要。 + + + + Machine code: + 机器码: + + + + Modify License Number + 修改许可证号: + + + + License key: + + + + + xxxxx-xxxxx-xxxxx-xxxxx + + + + + Activate + 激活 + + + + License Activation + 许可证激活 + + + + + + + + + Parameter error + 参数错误 + + + + Failed to get machine code, please check the network is workable. + 无法获取机器码,请检查网络是否正常工作。 + + + + Please input a valid License key first. + 请输入一个有效的许可证号。 + + + + + Please input a valid redeem code first. + 请输入一个有效的兑换码。 + + + + According to local access history, the code has already been used. Do you want to continue with this operation? + 根据本地的兑换历史,该码已经被使用。是否仍需要继续执行呢? + + + + + Ultimate redeem information + 旗舰版兑换信息 + + + + The validity period exceeds 3 years and cannot be further redeemed. + 当前有效期还有3年,无法继续兑换。 + + + + There are currently %1 days left to expire, and a valid code can increase the validity period by one year. Do you want to continue redeeming? + 当前还有%1天才到期,一个有效的兑换码能增加一年的有效期,是否继续兑换? + + + + License upgrade information + 许可证升级信息 + + + + There are currently %1 days left to expire, but a valid code will replace it for one year. Do you want to continue redeeming? + 当前还有%1天才到期,但一个有效的兑换码将替换它一年,是否继续。 + + + + + + + + Redeem error + 兑换错误 + + + + Try again later + 稍后重试 + + + + + The code[%1] has been used on %2. + 兑换码[%1]已经在%2使用。 + + + + Redeem sucess + 兑换成功 + + + + Success to redeem license, please store the license key safely for reinstallation etc. + 兑换成功,请小心保存,预防系统重装。 + + + + parameters is not complete. + 参数不完整 + + + + decode failure. + 解码失败。 + + + + it not a valid code. + 无效许可证。 + + + + server database error + 服务端的数据库错误。 + + + + This code has already been used, please input another one. + 该码已经被使用,请输入有效的兑换码。 + + + + unknow error + 未知错误 + + + + Try again later for reason: + 稍后重试,原因: + + + + Try again later for error:%1 + 稍后重试,错误: + + + + QWoLicenseDialog + + + Dialog + 对话框 + + + + License type: + 许可证类型: + + + + <a href="evaluateUltimate">Evaluate ultimate verstion</a> + <a href="evaluateUltimate">试用旗舰版</a> + + + + Start date: + 开发日期: + + + + Expire date: + 过期日期: + + + + Valid days: + 有效天数: + + + + Machine code: + 机器码: + + + + License key: + 许可证号: + + + + Version differences + 版本差异 + + + + Remove license + 移除许可证 + + + + Activate + 激活 + + + + Close + 关闭 + + + + License information + 许可证信息 + + + + Parameter error + 参数错误 + + + + license is expired + 许可证过期 + + + + Activation + 激活 + + + + Success to activate and restart the application to take effect right now. + 激活成功,需重启软件才生效。 + + + + License remove + 许可证移除 + + + + After removing the relevant license, it will be downgraded to the free version. Do you still want to continue. + 移除相关许可证,它将 + + + + Free version + 免费版本 + + + + Forever + 永久 + + + + Trial version + 试用版 + + + + School version + 校园版 + + + + Ultimate version + 旗舰版 + + + + Unknow version + 未知版本 + + + + days + + + + + expired + 已过期 + + + + QWoLicenseTrialApplyDialog + + + Dialog + 对话框 + + + + Retry + 重试 + + + + Close + 关闭 + + + + Trial license + 试用许可证 + + + + Thank you very much for your use. + 感谢你的使用。 + + + + In order to help you better understand the functions and usages of this software, we provide you with a free one month trial experience. + 为了帮助您更好地了解此软件的功能和用法,我们为您提供一个月的免费试用体验。 + + + + If you like it, please purchase a license to support us. + 如果您喜欢,请购买许可证以支持我们。 + + + + We will also work harder to make it more powerfull and give back your kindness. + 我们也将更加努力地工作,使其更加强大,并回报您的善意。 + + + + Get a license + 获取许可证 + + + + start to check.... + 开始检查... + + + + I'm very sorry, you had already enjoyed the chance about %1 before ago. If the information is incorrect, you can contact the official support to solve it. + 非常抱歉,您之前已经享受了%1的机会。如果信息不正确,您可以联系官方支持来解决。 + + + + You have obtained a trial license, please enjoy using it. + 您已获得试用许可证,请尽情使用。 + + + + Activation + 激活 + + + + Success to activate and restart the application to take effect right now. + 激活成功,需重启软件才生效。 + + + + Error: %1 + 错误:%1 + + + + + + Please try again. If it still cannot be resolved, please feedback and ask for official support. + 请再试一次。如果仍然无法解决,请反馈并寻求官方支持。 + + + + + + Retry again + 重试 + + + + Error: unexpected error. + 错误:未知错误。 + + QWoMainWindow @@ -4021,58 +4530,66 @@ 管理员 - - + Upgrade to ultimate version 升级至旗舰版 - - - + + + Open remote session 打开远程会话 - - + + Open local session 打开本地会话 - - + + Open serialport session 打开串口会话 - + TTY options TTY选项 - + VNC options VNC选项 - + RDP options RDP选项 - + System options 系统选项 - - Register... - 注册信息 + + License... + 许可证... - + Upgrade check... + 升级检查... + + + Register... + 注册信息 + + + + Clear all 清空所有 @@ -4115,8 +4632,8 @@ - - + + Open 打开 @@ -4174,142 +4691,187 @@ 发现新版本:%1,现在去下载? + WoTerm - WoTerm + WoTerm - WoTerm ultimate beta - WoTerm 旗舰版 beta + WoTerm 旗舰版 beta - WoTerm free - WoTerm 免费版 + WoTerm 免费版 - + Session Manager 会话管理 - + Confirm 确认 - + Exit Or Not? 退出或取消 - + The current version is free. It is recommended to upgrade to the ultimate version. 当前版本是免费版本,建议升级至旗舰版。 - Version check - 版本检查 + 版本检查 - a new version of %1 is found, do you want to update it? - 发现新版本%1,是否需要更新? + 发现新版本%1,是否需要更新? + + + + Free + 免费版 + + + + Trial + 试用版 + + + + + + + [expired] + [已过期] + + + + School + 校园版 + + + + Ultimate + 舰舰版 - + + Unknow + 未知 + + + + Evalute ultimate + 评估旗舰版 + + + + No + + + + + Yes + + + + Backup Session Database 备份数据库 - + Failure 失败 - + failed to backup the session list. 备份数据库失败。 - + Language 语言 - + The language has been changed, restart application to take effect right now. 语言已经被修改,需要重启才能生效,是否立即重启? - + Password input 密码输入 - + Login to the configuration of administrator for the first time, Please input password to activate it. 首次使用管理员配置需要输入新密码激活它。 - + Please input password to verify. 请输入密码进行验证。 - + Password error 参数错误 - + the password is not right. 密码不正确。 - + Toolbar 工具栏 - + History 历史 - + Enter keyword to search 关键字搜索 - + filterBox 过滤框 - + Administrator login 管理员登录 - + Please input password to login application. 请输入密码登录应用 - + Login failure 登录失败 - + The password is wrong, %1 times left to try. 密码错误,剩余%1次尝试机会。 - + New 新建 @@ -4318,7 +4880,7 @@ 管理 - + List 列表 @@ -4565,7 +5127,7 @@ QWoPtyTermWidgetImpl - + %1:%2 %1:%2 @@ -4991,17 +5553,17 @@ QWoSerialTermWidget - + Copy 复制 - + Edit 编辑 - + Clean history 清空历史 @@ -5017,23 +5579,23 @@ QWoSerialWidgetImpl - - + + Error 错误 - + can't find the session, maybe it had been delete 没有找到对应的会话 - + Failed to open device. 没有打开设备 - + An I/O error occurred from port %1, error: %2 在串口%1发生输入输出错误:%2 @@ -5730,6 +6292,16 @@ failed to find the identify file 无法查到证书文件 + + + Version restrictions + 版本限制 + + + + The session's count has reached the limit. + 会话数量 + @@ -6461,7 +7033,7 @@ - + The directory is out of sync with the terminal. 文件夹不与终端同步 @@ -6476,139 +7048,145 @@ 请等待当前任务完成。 - + + + the follow files has exist or version restrictions: + 以下文件已经存在或版本限制: + + + Upload task 上传任务 - + Do you want to upload this related file? 是否继续上传相关文件? - - + + Select all 选择所有 - - - - + + + + Back 返回 - - - - + + + + Refresh 刷新 - - + + Home Directory 返回主文件夹 - - + + Create Directory 创建文件夹 - - - + + + Upload 上传 - - + + Deselect all 取消所选 - - + + Remove selections 删除选中项 - - + + Home directory 主文件夹 - - + + Create directory 创建文件夹 - + Try enter 尝试进入 - + directory name 文件夹名 - + Please input a directory name 请输入一个文件夹名称 - + information 信息 - + the new directory name should be empty! 新文件夹名不能为空! - + Input error 输入错误 - + The directory entered does not exist. 所输入的文件夹不存在。 - - + + SFTP SFTP - - + + No items are currently selected. 当前没有选中项 - + Keep the directory synchronized with the terminal. 保持文件夹与终端同步 - + File information 文件信息 - + The remote path does not exist or does not have permission to access it? 请确认远程路径是否存在或是否具备访问权限? @@ -6617,8 +7195,8 @@ 删除文件夹 - - + + Enter 进入 @@ -6627,29 +7205,29 @@ 删除文件 - - + + Download 下载 - + Try Enter 尝度进入 - + New Session Multiplex 新建连接复用 - + Close 关闭 - - + + Error 错误 @@ -6659,54 +7237,56 @@ - + FileExist 文件存在 - + has the same name in the target path. override it? 已经存在同名文件,是否覆盖? - + + Upload information 上传信息 - - + + the follow files has exist: 以下文件已经存在: - + Save directory 保存文件夹 - + Parameter error 参数错误 - + Please select directory to save it. 请选择文件夹去保存 - + + Download information 下载信息 - + Select files 选择文件 - + Select File 选择文件 @@ -6714,7 +7294,7 @@ QWoSftpWidgetImpl - + New Session Multiplex 新建连接复用 @@ -6735,17 +7315,17 @@ QWoShower - + Local shell 本地终端 - + SerialPort 本地串口 - + Close Or Not 是否关闭 @@ -6762,67 +7342,122 @@ Continue To Close It? 继续关闭 - + The follow event will be stop before close this session. 关闭会话的同时,也停止以下相应行为。 - + Continue To Close It? 是否继续关闭它? - + CloseSession 关闭会话 - Close This Tab - 关闭此选项卡 + 关闭此选项卡 - Close Other Tab - 关闭其它选项卡 + 关闭其它选项卡 - Float This Tab - 浮动此选项卡 + 浮动此选项卡 + + + + + + + + + + + + Version restrictions + 版本限制 + + + + + + + + + + + + The tab's count has reached the limit. + 选项卡数量已达版本上限。 + + + + Close this tab + 关闭这选项卡 + + + + Close other tab + 关闭其它选项卡 + + + + Copy session + 复制会话 - - + + Copy host address + 复制主机地址 + + + + Edit this session + 编辑会话 + + + + Float this tab + 浮动此选项 + + + + alert 告警 - - + + failed to find impl infomation 无法查找目标信息 - + Open remote session 打开远程会话 - + Open local session 打开本地会话 - QWoSshConf + QWoShowerWidget - LoadSshConfig - 加载配置 + + Error + 错误 - Failed to open file: - 无法打开文件 + + can't find the session, maybe it had been delete ago + 没有查找到会话,也许已经被删除。 @@ -7002,12 +7637,12 @@ Continue To Close It? - Sftp Assistant + Sftp assistant SFTP助手 - New Session Multiplex + New session multiplex 新建连接复用 @@ -7205,26 +7840,113 @@ Continue To Close It? QWoTermWidget - + Save history to file - + log (*.log) - + Warning 警告 - + Failed to create file. + + QWoUtils + + + Ok + 确定 + + + + Cancel + 取消 + + + + QWoVersionUpgradeTipDialog + + + Dialog + 对话框 + + + + Upgrade content: + 升级内容: + + + + Ignore this version + 忽略这个版本 + + + + Ignore + 忽略 + + + + Pop up again in seven days + 7天后再弹 + + + + 7 days + 7天后 + + + + Pop up again tomorrow + 明天再弹 + + + + Tomorrow + + + + + Upgrade + 升级 + + + + Version upgrade + 版本升级 + + + + Failed to get upgrade content. + 无法获取升级内容 + + + + + Upgrade information + 升级内容 + + + + The current version is already the latest version. + 当前版本已经是最新版。 + + + + Unexpected error, please try again later. + 未知错误,请稍后重试。 + + QWoVncFtpWidget diff --git a/woterm/main.cpp b/woterm/main.cpp index 2dbd566..4c7567a 100644 --- a/woterm/main.cpp +++ b/woterm/main.cpp @@ -102,6 +102,8 @@ void setDebugMessageToFile(const QString& name, bool tryDelete = false) void test() { + QLocale local = QLocale::system(); + qDebug() << local.bcp47Name() << local.language() << local.name(); } diff --git a/woterm/qkxfilterlineedit.cpp b/woterm/qkxfilterlineedit.cpp index 1074a06..b214f6e 100644 --- a/woterm/qkxfilterlineedit.cpp +++ b/woterm/qkxfilterlineedit.cpp @@ -15,6 +15,7 @@ #include "qkxfilterlistview.h" #include "qkxbuttonassist.h" +#include "qwosshconf.h" #include #include @@ -62,7 +63,25 @@ void QKxFilterLineEdit::onAssistButtonClicked(int idx) void QKxFilterLineEdit::onAssistReturnPressed() { if(!m_listView->isVisible()) { - emit createArrived(text()); + QString name = text(); + if(QWoSshConf::instance()->exists(name)) { + const HostInfo& hi = QWoSshConf::instance()->find(name); + if(hi.type == SshWithSftp) { + emit targetArrived(hi.name, EOT_SSH); + }else if(hi.type == SftpOnly) { + emit targetArrived(hi.name, EOT_SFTP); + }else if(hi.type == Telnet) { + emit targetArrived(hi.name, EOT_TELNET); + }else if(hi.type == RLogin) { + emit targetArrived(hi.name, EOT_RLOGIN); + }else if(hi.type == Mstsc) { + emit targetArrived(hi.name, EOT_MSTSC); + }else if(hi.type == Vnc) { + emit targetArrived(hi.name, EOT_VNC); + } + }else{ + emit createArrived(text()); + } return; } QModelIndex idx = m_listView->listView()->currentIndex(); diff --git a/woterm/qkxlicensedialog.cpp b/woterm/qkxlicensedialog.cpp deleted file mode 100644 index 19e97fc..0000000 --- a/woterm/qkxlicensedialog.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************************************* -* -* Copyright (C) 2023 Guangzhou AoYiDuo Network Technology Co.,Ltd. All Rights Reserved. -* -* Contact: http://www.aoyiduo.com -* -* this file is used under the terms of the GPLv3[GNU GENERAL PUBLIC LICENSE v3] -* more information follow the website: https://www.gnu.org/licenses/gpl-3.0.en.html -* -*******************************************************************************************/ - -#include "qkxlicensedialog.h" -#include "ui_qkxlicensedialog.h" -#include "qkxlicense.h" - -QKxLicenseDialog::QKxLicenseDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::QKxLicenseDialog) -{ - Qt::WindowFlags flags = windowFlags(); - setWindowFlags(flags &~Qt::WindowContextHelpButtonHint); - ui->setupUi(this); - - setWindowTitle(tr("License")); - - QObject::connect(ui->btnClose, SIGNAL(clicked()), this, SLOT(close())); - QObject::connect(ui->btnActivate, SIGNAL(clicked()), this, SLOT(onActivateButtonClicked())); - - adjustSize(); -} - -QKxLicenseDialog::~QKxLicenseDialog() -{ - delete ui; -} - -void QKxLicenseDialog::onActivateButtonClicked() -{ - -} diff --git a/woterm/qkxloadingbarwidget.cpp b/woterm/qkxloadingbarwidget.cpp new file mode 100644 index 0000000..a1b22b2 --- /dev/null +++ b/woterm/qkxloadingbarwidget.cpp @@ -0,0 +1,113 @@ +/******************************************************************************************* +* +* Copyright (C) 2022 Guangzhou AoYiDuo Network Technology Co.,Ltd. All Rights Reserved. +* +* Contact: http://www.aoyiduo.com +* +* this file is used under the terms of the GPLv3[GNU GENERAL PUBLIC LICENSE v3] +* more information follow the website: https://www.gnu.org/licenses/gpl-3.0.en.html +* +*******************************************************************************************/ + +#include "qkxloadingbarwidget.h" + +#include +#include + +QKxLoadingBarWidget::QKxLoadingBarWidget(const QColor& clr, QWidget *parent) + : QWidget(parent) + , m_color(clr) + , m_msgColor(clr) + , m_angle(0) + , m_step(30) + , m_txtSize(20) + , m_thickness(0) +{ + QTimer *timer = new QTimer(this); + timer->setInterval(33); + m_timer.reset(timer); + QObject::connect(timer, SIGNAL(timeout()), this, SLOT(onTimeout())); +} + +void QKxLoadingBarWidget::setSpeed(int fps) +{ + m_timer->setInterval(1000 / fps); +} + +void QKxLoadingBarWidget::setThickness(int n) +{ + m_thickness = n; +} + +void QKxLoadingBarWidget::setMessageColor(const QColor &clr) +{ + m_msgColor = clr; +} + +void QKxLoadingBarWidget::setMessageSize(int sz) +{ + m_txtSize = sz; +} + +void QKxLoadingBarWidget::setMessage(const QString &msg) +{ + m_message = msg; +} + +void QKxLoadingBarWidget::paintEvent(QPaintEvent *ev) +{ + QPainter p(this); + p.setRenderHint(QPainter::Antialiasing); + + QPainterPath ring; + QRectF dest = rect(); + if(m_thickness > 0) { + QPointF pt = dest.center(); + dest.setHeight(m_thickness); + dest.moveCenter(pt); + } + ring.addRect(dest); + QLinearGradient cg(dest.left(), dest.top(), dest.right(), dest.top()); + cg.setColorAt(0, QColor(Qt::transparent)); + qreal x = m_angle / 360; + cg.setColorAt(x, QColor(m_color)); + cg.setColorAt(1, QColor(Qt::transparent)); + p.setBrush(cg); + p.setPen(QColor::fromRgba(0)); + p.drawPath(ring); + + if(!m_message.isEmpty()) { + QFont ft = p.font(); + ft.setPixelSize(m_txtSize); + ft.setBold(true); + p.setFont(ft); + QPen pen = p.pen(); + pen.setColor(m_msgColor); + p.setPen(pen); + p.drawText(rect(), Qt::AlignCenter, m_message); + } +} + +void QKxLoadingBarWidget::showEvent(QShowEvent *ev) +{ + m_timer->start(); + m_angle = 0; +} + +void QKxLoadingBarWidget::hideEvent(QHideEvent *ev) +{ + m_timer->stop(); +} + +void QKxLoadingBarWidget::onTimeout() +{ + m_angle += m_step; + if(m_angle > 350) { + m_angle = 350; + m_step = -m_step; + }else if(m_angle < 10) { + m_angle = 10; + m_step = -m_step; + } + update(rect()); +} diff --git a/woterm/qkxloadingbarwidget.h b/woterm/qkxloadingbarwidget.h new file mode 100644 index 0000000..f6b8ed3 --- /dev/null +++ b/woterm/qkxloadingbarwidget.h @@ -0,0 +1,50 @@ +/******************************************************************************************* +* +* Copyright (C) 2022 Guangzhou AoYiDuo Network Technology Co.,Ltd. All Rights Reserved. +* +* Contact: http://www.aoyiduo.com +* +* this file is used under the terms of the GPLv3[GNU GENERAL PUBLIC LICENSE v3] +* more information follow the website: https://www.gnu.org/licenses/gpl-3.0.en.html +* +*******************************************************************************************/ + +#ifndef QKXLOADINGBARWIDGET_H +#define QKXLOADINGBARWIDGET_H + +#include +#include +#include + +class QTimer; +class QKxLoadingBarWidget : public QWidget +{ + Q_OBJECT +public: + explicit QKxLoadingBarWidget(const QColor& clr, QWidget *parent = nullptr); + + void setSpeed(int fps=30); + void setThickness(int n); + void setMessageColor(const QColor& clr); + void setMessageSize(int sz); + void setMessage(const QString& msg); +signals: + +public slots: + void onTimeout(); +protected: + void paintEvent(QPaintEvent *ev); + void showEvent(QShowEvent *ev); + void hideEvent(QHideEvent *ev); +private: + QColor m_color; + qreal m_step; + qreal m_angle; + int m_thickness; + int m_txtSize; + QString m_message; + QColor m_msgColor; + QScopedPointer m_timer; +}; + +#endif // QKXLOADINGBARWIDGET_H diff --git a/woterm/qwoaboutdialog.cpp b/woterm/qwoaboutdialog.cpp index 7d66712..aa3f91f 100644 --- a/woterm/qwoaboutdialog.cpp +++ b/woterm/qwoaboutdialog.cpp @@ -33,9 +33,22 @@ QWoAboutDialog::QWoAboutDialog(QWidget *parent) : ui->setupUi(this); ui->verNow->setText(WOTERM_VERSION); - ui->authorizeLevel->setText(QKxVer::isUltimate() ? "Ultimate beta" : "Free"); - ui->dayLeft->setText(QString::number(QKxVer::howDayUltimateLeft())); - ui->ultimateLeft->setVisible(QKxVer::isUltimate()); + QKxVer *ver = QKxVer::instance(); + QKxVer::ELicenseType type = ver->licenseType(); + QString typeDesc = tr("Unknow version"); + if(type == QKxVer::EFreeVersion) { + typeDesc = tr("Free version"); + }else if(type == QKxVer::ETrialVersion) { + typeDesc = tr("Trial version"); + } else if(type == QKxVer::ESchoolVersion) { + typeDesc = tr("School version"); + } else if(type == QKxVer::EUltimateVersion) { + typeDesc = tr("Ultimate version"); + } + if(ver->isExpired()) { + typeDesc += QString("[%1]").arg(tr("expired")); + } + ui->authorizeLevel->setText(typeDesc); ui->website->setText("http://www.woterm.com"); ui->website->setOpenExternalLinks(true); ui->website->setTextInteractionFlags(Qt::TextBrowserInteraction); diff --git a/woterm/qwoaboutdialog.ui b/woterm/qwoaboutdialog.ui index a75ed6a..d5c3806 100644 --- a/woterm/qwoaboutdialog.ui +++ b/woterm/qwoaboutdialog.ui @@ -124,54 +124,6 @@ - - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Ultimate version day left: - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - diff --git a/woterm/qwoglobal.h b/woterm/qwoglobal.h index 24cbffd..fe44f73 100644 --- a/woterm/qwoglobal.h +++ b/woterm/qwoglobal.h @@ -34,6 +34,7 @@ enum EHostType{ #define EOT_SERIALPORT (5) #define EOT_MSTSC (6) #define EOT_VNC (7) +#define EOT_PTY (8) #define ROLE_INDEX (Qt::UserRole+1) #define ROLE_HOSTINFO (Qt::UserRole+2) diff --git a/woterm/qwolicenseactivatedialog.cpp b/woterm/qwolicenseactivatedialog.cpp new file mode 100644 index 0000000..26cb2d3 --- /dev/null +++ b/woterm/qwolicenseactivatedialog.cpp @@ -0,0 +1,258 @@ +/******************************************************************************************* +* +* Copyright (C) 2023 Guangzhou AoYiDuo Network Technology Co.,Ltd. All Rights Reserved. +* +* Contact: http://www.aoyiduo.com +* +* this file is used under the terms of the GPLv3[GNU GENERAL PUBLIC LICENSE v3] +* more information follow the website: https://www.gnu.org/licenses/gpl-3.0.en.html +* +*******************************************************************************************/ + +#include "qwolicenseactivatedialog.h" +#include "ui_qwolicenseactivatedialog.h" + +#include "qkxbuttonassist.h" +#include "qkxver.h" +#include "qkxmessagebox.h" +#include "qkxhttpclient.h" +#include "qwosetting.h" + +#include +#include +#include + +#include +#include +#include +#include + +QWoLicenseActivateDialog::QWoLicenseActivateDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::QWoLicenseActivateDialog) +{ + Qt::WindowFlags flags = windowFlags(); + setWindowFlags(flags &~Qt::WindowContextHelpButtonHint); + + ui->setupUi(this); + setWindowTitle(tr("License Activation")); + + setMinimumWidth(360); + + QKxButtonAssist *btn = new QKxButtonAssist(":/woterm/resource/skin/ftp.png", false, ui->mid); + QObject::connect(btn, SIGNAL(clicked(int)), this, SLOT(onAssistButtonClicked(int))); + QObject::connect(ui->btnClose, SIGNAL(clicked()), this, SLOT(close())); + QObject::connect(ui->btnClose2, SIGNAL(clicked()), this, SLOT(close())); + QObject::connect(ui->btnActivate, SIGNAL(clicked()), this, SLOT(onActivateButtonClicked())); + QObject::connect(ui->btnRedeem, SIGNAL(clicked()), this, SLOT(onRedeemButtonClicked())); + QObject::connect(ui->radioKey, SIGNAL(clicked()), this, SLOT(onTypeButtonClicked())); + QObject::connect(ui->radioCode, SIGNAL(clicked()), this, SLOT(onTypeButtonClicked())); + QObject::connect(ui->chkKeyModify, SIGNAL(clicked()), this, SLOT(onKeyModifyButtonClicked())); + QButtonGroup *group = new QButtonGroup(this); + group->addButton(ui->radioKey); + group->addButton(ui->radioCode); + ui->radioCode->setChecked(false); + ui->radioKey->setChecked(true); + ui->code->setReadOnly(false); + QKxVer *ver = QKxVer::instance(); + ui->mid->setText(ver->machineID()); + ui->key->setText(ver->licenseKey()); + onTypeButtonClicked(); +} + +QWoLicenseActivateDialog::~QWoLicenseActivateDialog() +{ + delete ui; +} + +void QWoLicenseActivateDialog::onAssistButtonClicked(int idx) +{ + QClipboard *clipboard = QGuiApplication::clipboard(); + QString mid = ui->mid->text(); + if(mid.isEmpty()) { + QKxMessageBox::information(this, tr("Parameter error"), tr("Failed to get machine code, please check the network is workable.")); + return; + } + clipboard->setText(mid); +} + +void QWoLicenseActivateDialog::onActivateButtonClicked() +{ + QString key = ui->key->text(); + if(key.isEmpty()) { + QKxMessageBox::information(this, tr("Parameter error"), tr("Please input a valid License key first.")); + return; + } + QKxVer *ver = QKxVer::instance(); + QString errMsg; + if(!ver->parse(key, errMsg)) { + QKxMessageBox::information(this, tr("Parameter error"), errMsg); + return; + } + done(QDialog::Accepted+1); +} + +void QWoLicenseActivateDialog::onRedeemButtonClicked() +{ + QKxVer *ver = QKxVer::instance(); + QString code = ui->code->text(); + if(code.isEmpty()) { + QKxMessageBox::information(this, tr("Parameter error"), tr("Please input a valid redeem code first.")); + return; + } + bool ok; + if(code.toLongLong(&ok) == 0 || !ok) { + QKxMessageBox::information(this, tr("Parameter error"), tr("Please input a valid redeem code first.")); + return; + } + QStringList codes = QWoSetting::value("redeem/codes").toStringList(); + if(codes.contains(code)) { + int retval = QKxMessageBox::information(this, + tr("Parameter error"), + tr("According to local access history, the code has already been used. Do you want to continue with this operation?"), + QMessageBox::Yes|QMessageBox::No); + if(retval != QMessageBox::Yes) { + return; + } + } + bool noTip = ver->isFreeVersion() || ver->isExpired(); + if(!noTip) { + int daysLeft = ver->expireDaysLeft(); + if(daysLeft > 366 * 3) { + int retval = QKxMessageBox::information(this, + tr("Ultimate redeem information"), + tr("The validity period exceeds 3 years and cannot be further redeemed.")); + return; + } + if(ver->isUltimateVersion()) { + int retval = QKxMessageBox::information(this, + tr("Ultimate redeem information"), + tr("There are currently %1 days left to expire, and a valid code can increase the validity period by one year. Do you want to continue redeeming?").arg(daysLeft), + QMessageBox::Yes|QMessageBox::No); + if(retval != QMessageBox::Yes) { + return; + } + }else if(ver->isSchoolVersion()){ + int retval = QKxMessageBox::information(this, + tr("License upgrade information"), + tr("There are currently %1 days left to expire, but a valid code will replace it for one year. Do you want to continue redeeming?").arg(daysLeft), + QMessageBox::Yes|QMessageBox::No); + if(retval != QMessageBox::Yes) { + return; + } + } + } + QString mid = ver->machineID(); + QString info = ver->buildRedeemInformation(code); + + QKxHttpClient *http = new QKxHttpClient(this); + QObject::connect(http, SIGNAL(result(int,QByteArray)), this, SLOT(onRetryToRedeemLicense(int,QByteArray))); + QObject::connect(http, SIGNAL(finished()), http, SLOT(deleteLater())); + QJsonObject obj; + obj.insert("mid", mid); + obj.insert("info", info); + QJsonDocument doc; + doc.setObject(obj); + QByteArray json = doc.toJson(QJsonDocument::Compact); + http->post("http://key.woterm.com/redeem/license", json, "application/json; charset=utf-8"); + ui->btnRedeem->setEnabled(false); +} + +void QWoLicenseActivateDialog::onTypeButtonClicked() +{ + if(ui->radioCode->isChecked()) { + ui->codeArea->setVisible(true); + ui->keyArea->setVisible(false); + }else{ + ui->codeArea->setVisible(false); + ui->keyArea->setVisible(true); + } + QString key = ui->key->text(); + ui->key->setReadOnly(!key.isEmpty()); + ui->chkKeyModify->setVisible(!key.isEmpty()); + ui->chkKeyModify->setChecked(false); + adjustSize(); +} + +void QWoLicenseActivateDialog::onKeyModifyButtonClicked() +{ + QString key = ui->key->text(); + ui->key->setReadOnly(!ui->chkKeyModify->isChecked()); +} + +void QWoLicenseActivateDialog::onRetryToRedeemLicense(int code, const QByteArray &body) +{ + ui->btnRedeem->setEnabled(true); + if(code == 200) { + QJsonDocument doc = QJsonDocument::fromJson(body); + if(doc.isEmpty()) { + QKxMessageBox::information(this, tr("Redeem error"), tr("Try again later")); + return; + } + QJsonObject obj = doc.object(); + QString err; + int ierr = obj.value("error").toInt(); + if(ierr == 0 || ierr == 2) { + QJsonObject keyInfo = obj.value("data").toObject(); + if(!keyInfo.isEmpty()) { + QString key = keyInfo.value("key").toString(); + QDateTime used = QDateTime::fromSecsSinceEpoch(keyInfo.value("timeUsed").toInt()); + QString code = keyInfo.value("code").toString(); + QKxVer *ver = QKxVer::instance(); + QString keyUsed = ver->licenseKey(); + if(key != keyUsed) { + if(!ver->parse(key, err)) { + QKxMessageBox::information(this, tr("Redeem error"), tr("The code[%1] has been used on %2.").arg(code).arg(used.toString())); + return; + } + QStringList codes = QWoSetting::value("redeem/codes").toStringList(); + if(!codes.contains(code)) { + codes.append(code); + QWoSetting::setValue("redeem/codes", codes); + } + QKxMessageBox::information(this, tr("Redeem sucess"), tr("Success to redeem license, please store the license key safely for reinstallation etc.")); + done(QDialog::Accepted+1); + return; + } + QKxMessageBox::information(this, tr("Redeem error"), tr("The code[%1] has been used on %2.").arg(code).arg(used.toString())); + return; + } + } + switch (ierr) { + case -1: + err = tr("parameters is not complete."); + break; + case -2: + case -3: + case -4: + err = tr("decode failure."); + break; + case -5: + err = tr("it not a valid code."); + break; + case -6: + case -7: + case -8: + case -9: + err = tr("server database error"); + break; + case 1: + err = tr("This code has already been used, please input another one."); + break; + default: + err = tr("unknow error"); + break; + } + QKxMessageBox::information(this, tr("Redeem error"), tr("Try again later for reason:")+err); + }else{ + QKxHttpClient *http = qobject_cast(sender()); + QString errMsg = QString::number(code); + if(http) { + QString err = http->lastErrorString(); + if(!err.isEmpty()) { + errMsg = err; + } + } + QKxMessageBox::information(this, tr("Redeem error"), tr("Try again later for error:%1").arg(errMsg)); + } +} diff --git a/woterm/qwolicenseactivatedialog.h b/woterm/qwolicenseactivatedialog.h new file mode 100644 index 0000000..0581419 --- /dev/null +++ b/woterm/qwolicenseactivatedialog.h @@ -0,0 +1,40 @@ +/******************************************************************************************* +* +* Copyright (C) 2023 Guangzhou AoYiDuo Network Technology Co.,Ltd. All Rights Reserved. +* +* Contact: http://www.aoyiduo.com +* +* this file is used under the terms of the GPLv3[GNU GENERAL PUBLIC LICENSE v3] +* more information follow the website: https://www.gnu.org/licenses/gpl-3.0.en.html +* +*******************************************************************************************/ + +#ifndef QWOLICENSEACTIVATEDIALOG_H +#define QWOLICENSEACTIVATEDIALOG_H + +#include + +namespace Ui { +class QWoLicenseActivateDialog; +} + +class QWoLicenseActivateDialog : public QDialog +{ + Q_OBJECT + +public: + explicit QWoLicenseActivateDialog(QWidget *parent = nullptr); + ~QWoLicenseActivateDialog(); + +private slots: + void onAssistButtonClicked(int idx); + void onActivateButtonClicked(); + void onRedeemButtonClicked(); + void onTypeButtonClicked(); + void onKeyModifyButtonClicked(); + void onRetryToRedeemLicense(int code, const QByteArray& body); +private: + Ui::QWoLicenseActivateDialog *ui; +}; + +#endif // QWOLICENSEACTIVATEDIALOG_H diff --git a/woterm/qwolicenseactivatedialog.ui b/woterm/qwolicenseactivatedialog.ui new file mode 100644 index 0000000..4fbb93d --- /dev/null +++ b/woterm/qwolicenseactivatedialog.ui @@ -0,0 +1,345 @@ + + + QWoLicenseActivateDialog + + + + 0 + 0 + 401 + 409 + + + + Activation + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + License key + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Redeem code + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + 24 + 24 + + + + + + + :/woterm/resource/skin/tips.png + + + true + + + + + + + The redeem code is only used to obtain licenses online and bind to the target device. Once the exchange is successful, it will become invalid. Please save the license key, which can still be used during system reinstallation. + + + true + + + + + + + + + + + Redeem code: + + + + + + + false + + + + + + + + + Qt::Horizontal + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Redeem + + + + + + + Close + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + 24 + 24 + + + + + + + :/woterm/resource/skin/tips.png + + + true + + + + + + + The license is created by a machine code, so the license only corresponds to one machine code. Please save the license key, which can still be used during system reinstallation. + + + true + + + + + + + + + + + Machine code: + + + + + + + true + + + + + + + + + Modify License Number + + + + + + + + + License key: + + + + + + + xxxxx-xxxxx-xxxxx-xxxxx + + + + + + + + + Qt::Horizontal + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Activate + + + + + + + Close + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + diff --git a/woterm/qwolicensedialog.cpp b/woterm/qwolicensedialog.cpp new file mode 100644 index 0000000..77c5e30 --- /dev/null +++ b/woterm/qwolicensedialog.cpp @@ -0,0 +1,165 @@ +/******************************************************************************************* +* +* Copyright (C) 2023 Guangzhou AoYiDuo Network Technology Co.,Ltd. All Rights Reserved. +* +* Contact: http://www.aoyiduo.com +* +* this file is used under the terms of the GPLv3[GNU GENERAL PUBLIC LICENSE v3] +* more information follow the website: https://www.gnu.org/licenses/gpl-3.0.en.html +* +*******************************************************************************************/ + +#include "qwolicensedialog.h" +#include "ui_qwolicensedialog.h" +#include "qkxver.h" +#include "qkxmessagebox.h" +#include "qkxprocesslaunch.h" +#include "qwolicenseactivatedialog.h" +#include "qwolicensetrialapplydialog.h" +#include "qkxbuttonassist.h" +#include "qwosetting.h" + +#include +#include +#include +#include +#include +#include + +QWoLicenseDialog::QWoLicenseDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::QWoLicenseDialog) +{ + Qt::WindowFlags flags = windowFlags(); + setWindowFlags(flags &~Qt::WindowContextHelpButtonHint); + ui->setupUi(this); + + setWindowTitle(tr("License information")); + ui->key->setReadOnly(true); + ui->mid->setReadOnly(true); + QKxButtonAssist *btn = new QKxButtonAssist(":/woterm/resource/skin/ftp.png", false, ui->key); + QObject::connect(btn, SIGNAL(clicked(int)), this, SLOT(onSNAssistButtonClicked(int))); + QKxButtonAssist *btn2 = new QKxButtonAssist(":/woterm/resource/skin/ftp.png", false, ui->mid); + QObject::connect(btn2, SIGNAL(clicked(int)), this, SLOT(onMIDAssistButtonClicked(int))); + + QObject::connect(ui->btnClose, SIGNAL(clicked()), this, SLOT(close())); + QObject::connect(ui->btnActivate, SIGNAL(clicked()), this, SLOT(onActivateButtonClicked())); + QObject::connect(ui->btnRemove, SIGNAL(clicked()), this, SLOT(onLicenseRemoveButtonClicked())); + QObject::connect(ui->btnVersions, SIGNAL(clicked()), this, SLOT(onVersionsDifferenceButtonClicked())); + QObject::connect(ui->wantTrial, SIGNAL(linkActivated(QString)), this, SLOT(onTrialLinkActivated(QString))); + ui->wantTrial->setOpenExternalLinks(false); + reset(); +} + +QWoLicenseDialog::~QWoLicenseDialog() +{ + delete ui; +} + +void QWoLicenseDialog::onActivateButtonClicked() +{ + QWoLicenseActivateDialog dlg(this); + if(dlg.exec() == QDialog::Accepted+1) { + reset(); + QKxVer *ver = QKxVer::instance(); + int days = ver->expireDaysLeft(); + if(days < 0) { + QKxMessageBox::information(this, tr("Parameter error"), tr("license is expired")); + return; + } + if(QKxMessageBox::warning(this, tr("Activation"), tr("Success to activate and restart the application to take effect right now."), QMessageBox::Yes|QMessageBox::No) == QMessageBox::Yes) { + QString path = QCoreApplication::instance()->applicationFilePath(); + if(QKxProcessLaunch::startDetached(path)) { + QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection); + } + } + } +} + +void QWoLicenseDialog::onLicenseRemoveButtonClicked() +{ + if(QKxMessageBox::warning(this, + tr("License remove"), + tr("After removing the relevant license, it will be downgraded to the free version. Do you still want to continue."), + QMessageBox::Yes|QMessageBox::No) == QMessageBox::Yes) { + QKxVer *ver = QKxVer::instance(); + if(ver->remove()) { + QString path = QCoreApplication::instance()->applicationFilePath(); + if(QKxProcessLaunch::startDetached(path)) { + QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection); + } + } + } +} + +void QWoLicenseDialog::onVersionsDifferenceButtonClicked() +{ + QDesktopServices::openUrl(QWoSetting::isChineseLanguageFile() ? QUrl("http://cn.woterm.com/prices") : QUrl("http://en.woterm.com/prices")); +} + +void QWoLicenseDialog::onTrialLinkActivated(const QString &link) +{ + if(link == "evaluateUltimate") { + QWoLicenseTrialApplyDialog dlg(this); + dlg.exec(); + } +} + +void QWoLicenseDialog::onSNAssistButtonClicked(int idx) +{ + QClipboard *clipboard = QGuiApplication::clipboard(); + QString mid = ui->key->text(); + if(mid.isEmpty()) { + return; + } + clipboard->setText(mid); +} + +void QWoLicenseDialog::onMIDAssistButtonClicked(int idx) +{ + QClipboard *clipboard = QGuiApplication::clipboard(); + QString mid = ui->mid->text(); + if(mid.isEmpty()) { + return; + } + clipboard->setText(mid); +} + +void QWoLicenseDialog::reset() +{ + QKxVer *ver = QKxVer::instance(); + QString mid = ver->machineID(); + ui->mid->setText(mid); + QKxVer::ELicenseType type = ver->licenseType(); + if(type == QKxVer::EFreeVersion) { + ui->licenseType->setText(tr("Free version")); + ui->dateStart->setText("1972-01-01"); + ui->dateExpire->setText("9999-12-30"); + ui->daysLeft->setText(tr("Forever")); + ui->key->setText("00000-00000-00000-00000"); + ui->btnRemove->setVisible(false); + ui->wantTrial->setVisible(true); + } else{ + if(type == QKxVer::ETrialVersion) { + ui->licenseType->setText(tr("Trial version")); + } else if(type == QKxVer::ESchoolVersion) { + ui->licenseType->setText(tr("School version")); + } else if(type == QKxVer::EUltimateVersion) { + ui->licenseType->setText(tr("Ultimate version")); + } else { + ui->licenseType->setText(tr("Unknow version")); + } + QString since = ver->sinceDate().toString("yyyy-MM-dd"); + QString expire = ver->expireDate().toString("yyyy-MM-dd"); + int days = ver->expireDaysLeft(); + QString key = ver->licenseKey(); + ui->dateStart->setText(since); + ui->dateExpire->setText(expire); + ui->daysLeft->setText(days >= 0 ? QString(" %1 ").arg(days)+tr("days"): tr("expired")); + ui->key->setText(key); + ui->btnRemove->setVisible(true); + ui->wantTrial->setVisible(false); + } + + adjustSize(); +} diff --git a/woterm/qwolicensedialog.h b/woterm/qwolicensedialog.h new file mode 100644 index 0000000..52a2976 --- /dev/null +++ b/woterm/qwolicensedialog.h @@ -0,0 +1,41 @@ +/******************************************************************************************* +* +* Copyright (C) 2023 Guangzhou AoYiDuo Network Technology Co.,Ltd. All Rights Reserved. +* +* Contact: http://www.aoyiduo.com +* +* this file is used under the terms of the GPLv3[GNU GENERAL PUBLIC LICENSE v3] +* more information follow the website: https://www.gnu.org/licenses/gpl-3.0.en.html +* +*******************************************************************************************/ + +#ifndef QWOLICENSEDIALOG_H +#define QWOLICENSEDIALOG_H + +#include + +namespace Ui { +class QWoLicenseDialog; +} + +class QWoLicenseDialog : public QDialog +{ + Q_OBJECT + +public: + explicit QWoLicenseDialog(QWidget *parent = nullptr); + ~QWoLicenseDialog(); +private slots: + void onActivateButtonClicked(); + void onLicenseRemoveButtonClicked(); + void onVersionsDifferenceButtonClicked(); + void onTrialLinkActivated(const QString& link); + void onSNAssistButtonClicked(int idx); + void onMIDAssistButtonClicked(int idx); +private: + void reset(); +private: + Ui::QWoLicenseDialog *ui; +}; + +#endif // QWOLICENSEDIALOG_H diff --git a/woterm/qwolicensedialog.ui b/woterm/qwolicensedialog.ui new file mode 100644 index 0000000..6a08495 --- /dev/null +++ b/woterm/qwolicensedialog.ui @@ -0,0 +1,218 @@ + + + QWoLicenseDialog + + + + 0 + 0 + 571 + 341 + + + + Dialog + + + + + + + + License type: + + + + + + + + 0 + 0 + + + + + + + + + + + + 0 + 0 + + + + + true + + + + <a href="evaluateUltimate">Evaluate ultimate verstion</a> + + + Qt::RichText + + + + + + + + + + + Start date: + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + Expire date: + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + Valid days: + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + Machine code: + + + + + + + + + + + + + + License key: + + + + + + + + + + + + Qt::Horizontal + + + + + + + + + Version differences + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Remove license + + + + + + + Activate + + + + + + + Close + + + + + + + + + + diff --git a/woterm/qwolicensetrialapplydialog.cpp b/woterm/qwolicensetrialapplydialog.cpp new file mode 100644 index 0000000..52e3303 --- /dev/null +++ b/woterm/qwolicensetrialapplydialog.cpp @@ -0,0 +1,128 @@ +/******************************************************************************************* +* +* Copyright (C) 2023 Guangzhou AoYiDuo Network Technology Co.,Ltd. All Rights Reserved. +* +* Contact: http://www.aoyiduo.com +* +* this file is used under the terms of the GPLv3[GNU GENERAL PUBLIC LICENSE v3] +* more information follow the website: https://www.gnu.org/licenses/gpl-3.0.en.html +* +*******************************************************************************************/ + +#include "qwolicensetrialapplydialog.h" +#include "ui_qwolicensetrialapplydialog.h" + +#include "qkxhttpclient.h" +#include "qkxver.h" +#include "qkxmessagebox.h" +#include "qkxprocesslaunch.h" + +#include +#include +#include + +QWoLicenseTrialApplyDialog::QWoLicenseTrialApplyDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::QWoLicenseTrialApplyDialog) +{ + Qt::WindowFlags flags = windowFlags(); + setWindowFlags(flags &~Qt::WindowContextHelpButtonHint); + + ui->setupUi(this); + + setWindowTitle(tr("Trial license")); + + QStringList msgs; + msgs << tr("Thank you very much for your use."); + msgs << tr("In order to help you better understand the functions and usages of this software, we provide you with a free one month trial experience."); + msgs << tr("If you like it, please purchase a license to support us."); + msgs << tr("We will also work harder to make it more powerfull and give back your kindness."); + ui->statement->setPlainText(msgs.join("\r\n")); + ui->statement->setReadOnly(true); + setMinimumWidth(360); + QObject::connect(ui->btnRetry, SIGNAL(clicked()), this, SLOT(onRetryButtonClicked())); + QObject::connect(ui->btnClose, SIGNAL(clicked()), this, SLOT(close())); + + ui->btnRetry->setText(tr("Get a license")); + adjustSize(); +} + +QWoLicenseTrialApplyDialog::~QWoLicenseTrialApplyDialog() +{ + delete ui; +} + +void QWoLicenseTrialApplyDialog::onRetryButtonClicked() +{ + QKxVer *ver = QKxVer::instance(); + QString mid = ver->machineID(); + QString info = ver->machineInformation(); + + QKxHttpClient *http = new QKxHttpClient(this); + QObject::connect(http, SIGNAL(result(int,QByteArray)), this, SLOT(onRetryToGetLicense(int,QByteArray))); + QObject::connect(http, SIGNAL(finished()), http, SLOT(deleteLater())); + QJsonObject obj; + obj.insert("mid", mid); + obj.insert("info", info); + QJsonDocument doc; + doc.setObject(obj); + QByteArray json = doc.toJson(QJsonDocument::Compact); + http->post("http://key.woterm.com/trial", json, "application/json; charset=utf-8"); + ui->btnRetry->setEnabled(false); + ui->status->setText(tr("start to check....")); +} + +void QWoLicenseTrialApplyDialog::onRetryToGetLicense(int code, const QByteArray& body) +{ + if(ui->btnRetry->isVisible()) { + ui->btnRetry->setEnabled(true); + } + if(code == 200) { + QJsonDocument doc = QJsonDocument::fromJson(body); + QJsonObject obj = doc.object(); + int err = obj.value("error").toInt(); + if(err == 0) { + QString key = obj.value("data").toString(); + qDebug() << "onRetryToGetLicense:" << key; + QKxVer *ver = QKxVer::instance(); + QString errMsg; + if(ver->parse(key, errMsg)) { + if(ver->isExpired()) { + QDate expire = ver->expireDate(); + QString desc = tr("I'm very sorry, you had already enjoyed the chance about %1 before ago. If the information is incorrect, you can contact the official support to solve it.").arg(expire.toString("yyyy-MM-dd")); + ui->status->setText(desc); + }else{ + QString desc = tr("You have obtained a trial license, please enjoy using it."); + ui->status->setText(desc); + + if(QKxMessageBox::warning(this, tr("Activation"), tr("Success to activate and restart the application to take effect right now."), QMessageBox::Yes|QMessageBox::No) == QMessageBox::Yes) { + QString path = QCoreApplication::instance()->applicationFilePath(); + if(QKxProcessLaunch::startDetached(path)) { + QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection); + } + } + } + ui->btnRetry->hide(); + }else{ + QStringList out; + out << tr("Error: %1").arg(errMsg); + out << tr("Please try again. If it still cannot be resolved, please feedback and ask for official support."); + ui->status->setText(out.join(' ')); + ui->btnRetry->show(); + ui->btnRetry->setText(tr("Retry again")); + } + }else{ + QStringList out; + out << tr("Error: unexpected error."); + out << tr("Please try again. If it still cannot be resolved, please feedback and ask for official support."); + ui->status->setText(out.join(' ')); + ui->btnRetry->show(); + ui->btnRetry->setText(tr("Retry again")); + } + + }else{ + ui->status->setText(tr("Please try again. If it still cannot be resolved, please feedback and ask for official support.")); + ui->btnRetry->show(); + ui->btnRetry->setText(tr("Retry again")); + } +} diff --git a/woterm/qkxlicensedialog.h b/woterm/qwolicensetrialapplydialog.h similarity index 56% rename from woterm/qkxlicensedialog.h rename to woterm/qwolicensetrialapplydialog.h index 90cecb9..ba5f604 100644 --- a/woterm/qkxlicensedialog.h +++ b/woterm/qwolicensetrialapplydialog.h @@ -1,34 +1,36 @@ -/******************************************************************************************* -* -* Copyright (C) 2023 Guangzhou AoYiDuo Network Technology Co.,Ltd. All Rights Reserved. -* -* Contact: http://www.aoyiduo.com -* -* this file is used under the terms of the GPLv3[GNU GENERAL PUBLIC LICENSE v3] -* more information follow the website: https://www.gnu.org/licenses/gpl-3.0.en.html -* -*******************************************************************************************/ - -#ifndef QKXLICENSEDIALOG_H -#define QKXLICENSEDIALOG_H - -#include - -namespace Ui { -class QKxLicenseDialog; -} - -class QKxLicenseDialog : public QDialog -{ - Q_OBJECT - -public: - explicit QKxLicenseDialog(QWidget *parent = nullptr); - ~QKxLicenseDialog(); -private slots: - void onActivateButtonClicked(); -private: - Ui::QKxLicenseDialog *ui; -}; - -#endif // QKXLICENSEDIALOG_H +/******************************************************************************************* +* +* Copyright (C) 2023 Guangzhou AoYiDuo Network Technology Co.,Ltd. All Rights Reserved. +* +* Contact: http://www.aoyiduo.com +* +* this file is used under the terms of the GPLv3[GNU GENERAL PUBLIC LICENSE v3] +* more information follow the website: https://www.gnu.org/licenses/gpl-3.0.en.html +* +*******************************************************************************************/ + +#ifndef QWOLICENSETRIALAPPLYDIALOG_H +#define QWOLICENSETRIALAPPLYDIALOG_H + +#include + +namespace Ui { +class QWoLicenseTrialApplyDialog; +} + +class QWoLicenseTrialApplyDialog : public QDialog +{ + Q_OBJECT + +public: + explicit QWoLicenseTrialApplyDialog(QWidget *parent = nullptr); + ~QWoLicenseTrialApplyDialog(); + +private slots: + void onRetryButtonClicked(); + void onRetryToGetLicense(int code, const QByteArray& body); +private: + Ui::QWoLicenseTrialApplyDialog *ui; +}; + +#endif // QWOLICENSETRIALAPPLYDIALOG_H diff --git a/woterm/qwolicensetrialapplydialog.ui b/woterm/qwolicensetrialapplydialog.ui new file mode 100644 index 0000000..b9c1413 --- /dev/null +++ b/woterm/qwolicensetrialapplydialog.ui @@ -0,0 +1,81 @@ + + + QWoLicenseTrialApplyDialog + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + + + + + color: rgb(255, 85, 127); + + + + + + true + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Retry + + + + + + + Close + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + diff --git a/woterm/qwomainwindow.cpp b/woterm/qwomainwindow.cpp index 742902d..e637e71 100644 --- a/woterm/qwomainwindow.cpp +++ b/woterm/qwomainwindow.cpp @@ -41,9 +41,11 @@ #include "qkxmessagebox.h" #include "qwomenubutton.h" #include "qworecenthistory.h" +#include "qwolicensedialog.h" #include "qkxbuttonassist.h" #include "qkxfilterlineedit.h" -#include "qkxlicensedialog.h" +#include "qwoversionupgradetipdialog.h" +#include "qwolicensetrialapplydialog.h" #include "qkxver.h" #include "version.h" @@ -72,9 +74,36 @@ QWoMainWindow::QWoMainWindow(QWidget *parent) , ui(new Ui::QWoMainWindow) { ui->setupUi(this); - setMinimumSize(QSize(1024, 700)); + setMinimumSize(QSize(800, 600)); setAttribute(Qt::WA_DeleteOnClose); - setWindowTitle(QKxVer::isUltimate() ? tr("WoTerm ultimate beta") : tr("WoTerm free")); + + QKxVer *ver = QKxVer::instance(); + QKxVer::ELicenseType type = ver->licenseType(); + QString typeVersion; + if(type == QKxVer::EFreeVersion) { + typeVersion = tr("Free"); + }else if(type == QKxVer::ETrialVersion) { + typeVersion = tr("Trial"); + if(ver->isExpired()) { + typeVersion += tr("[expired]"); + } + } else if(type == QKxVer::ESchoolVersion) { + typeVersion = tr("School"); + if(ver->isExpired()) { + typeVersion += tr("[expired]"); + } + } else if(type == QKxVer::EUltimateVersion) { + typeVersion = tr("Ultimate"); + if(ver->isExpired()) { + typeVersion += tr("[expired]"); + } + } else { + typeVersion = tr("Unknow"); + if(ver->isExpired()) { + typeVersion += tr("[expired]"); + } + } + setWindowTitle(tr("WoTerm") + " " + typeVersion); initMenuBar(); initToolBar(); @@ -117,10 +146,7 @@ QWoMainWindow::QWoMainWindow(QWidget *parent) QObject::connect(m_sessions, SIGNAL(readyToConnect(QString,int)), this, SLOT(onSessionReadyToConnect(QString,int))); - //ui->actionAbout->setCheckable(true); - //ui->actionAbout->setChecked(true); - ui->actionRegister->setVisible(false); - ui->actionUltimate->setVisible(false); + restoreLastState(); } @@ -223,19 +249,7 @@ void QWoMainWindow::onSessionReadyToConnect(const QString &target, int type) void QWoMainWindow::onAppStart() { - if(QSslSocket::supportsSsl()) - { - QKxHttpClient *http = new QKxHttpClient(this); - QObject::connect(http, SIGNAL(finished()), http, SLOT(deleteLater())); - http->get("http://hm.baidu.com/hm.js?bbffebc017090c1957c90f7deca2582e"); - } - { - // version check. - QKxHttpClient *http = new QKxHttpClient(this); - QObject::connect(http, SIGNAL(result(int,QByteArray)), this, SLOT(onVersionCheck(int,QByteArray))); - QObject::connect(http, SIGNAL(finished()), http, SLOT(deleteLater())); - http->get("http://down.woterm.com/.ver"); - } + QWoVersionUpgradeTipDialog::check(this, true); { //check target QStringList argvs = QApplication::arguments(); @@ -288,46 +302,49 @@ void QWoMainWindow::onAppStart() QCoreApplication::quit(); } } - { - if(!QKxVer::isUltimate()) { - if(QWoSetting::shouldPopupUpgradeUltimate()) { - int ret = QKxMessageBox::question(this, tr("Upgrade to ultimate version"), tr("The current version is free. It is recommended to upgrade to the ultimate version."), QMessageBox::Yes|QMessageBox::No); - if(ret == QMessageBox::Yes) { - QDesktopServices::openUrl(QUrl("http://woterm.com")); - } - QWoSetting::setIgnoreTodayUpgradeUltimate(); - } - } - } -} - -void QWoMainWindow::onVersionCheck(int code, const QByteArray &body) -{ - if(body.isEmpty()) { - return; - } - if(code == 200) { - qDebug() << code << body; - QString verBody = body.trimmed(); - if(body[0] == 'v') { - verBody = verBody.mid(1); + if(QKxVer::instance()->isFullFeather()) { + QKxVer *ver = QKxVer::instance(); + if(QWoSetting::shouldReportLicense()) { + QWoSetting::setIgnoreTodayReportLicense(); + + QKxHttpClient *http = new QKxHttpClient(this); + QObject::connect(http, SIGNAL(result(int,QByteArray)), this, SLOT(onReportResult(int,QByteArray))); + QObject::connect(http, SIGNAL(finished()), http, SLOT(deleteLater())); + QJsonObject obj; + obj.insert("mid", ver->machineID()); + obj.insert("info", ver->reportInformation()); + QJsonDocument doc; + doc.setObject(obj); + QByteArray json = doc.toJson(QJsonDocument::Compact); + http->post("http://key.woterm.com/report", json, "application/json; charset=utf-8"); } - int verLatest = QWoUtils::parseVersion(verBody); - int verCurrent = QWoUtils::parseVersion(WOTERM_VERSION); - if(verCurrent < verLatest) { - bool pop = QWoSetting::shouldPopupUpgradeVersionMessage(verBody); - if(!pop) { - return; + }else{ + if(QWoSetting::shouldPopupUpgradeUltimate()) { + QWoSetting::setIgnoreTodayUpgradeUltimate(); + QMessageBox dlg(QMessageBox::Information, tr("Upgrade to ultimate version"), tr("The current version is free. It is recommended to upgrade to the ultimate version."), QMessageBox::Retry|QMessageBox::Yes|QMessageBox::No, this); + { + QAbstractButton *btn = dlg.button(QMessageBox::Retry); + btn->setText(tr("Evalute ultimate")); + } + { + QAbstractButton *btn = dlg.button(QMessageBox::No); + btn->setText(tr("No")); } - QWoSetting::setIgnoreTodayUpgradeVersion(verBody); - int ret = QKxMessageBox::question(this, tr("Version check"), tr("a new version of %1 is found, do you want to update it?").arg(verBody), QMessageBox::Yes|QMessageBox::No); + { + QAbstractButton *btn = dlg.button(QMessageBox::Yes); + btn->setText(tr("Yes")); + } + int ret = dlg.exec(); if(ret == QMessageBox::Yes) { - QDesktopServices::openUrl(QUrl("http://woterm.com")); + QMetaObject::invokeMethod(this, "onActionLicenseTriggered", Qt::QueuedConnection); + }else if(ret == QMessageBox::Retry) { + QMetaObject::invokeMethod(this, "tryToMakeLicenseTrial", Qt::QueuedConnection); } } } } + void QWoMainWindow::onShouldAppExit() { if(m_shower->tabCount()) { @@ -356,6 +373,11 @@ void QWoMainWindow::onRecentMenuAboutToShow() m_recent->buildMenu(menu); } +void QWoMainWindow::onReportResult(int code, const QByteArray &body) +{ + qDebug() << "onReportResult" << code << body; +} + void QWoMainWindow::onActionNewTriggered() { onNewSession(); @@ -378,7 +400,7 @@ void QWoMainWindow::onActionOpenSerialportTriggered() void QWoMainWindow::onActionBackupTriggered() { - if(QKxVer::isUltimate()) { + if(QKxVer::instance()->isFullFeather()) { QWoDbBackupDialog dlg(this); dlg.exec(); }else{ @@ -399,7 +421,7 @@ void QWoMainWindow::onActionBackupTriggered() void QWoMainWindow::onActionRestoreTriggered() { - if(QKxVer::isUltimate()) { + if(QKxVer::instance()->isFullFeather()) { QWoDBPowerRestoreDialog dlg(this); dlg.exec(); }else{ @@ -452,7 +474,7 @@ void QWoMainWindow::onActionSystemOptionsTriggered() QWoSetting::setLanguageFile(lang); if(QKxMessageBox::warning(this, tr("Language"), tr("The language has been changed, restart application to take effect right now."), QMessageBox::Yes|QMessageBox::No) == QMessageBox::Yes) { QString path = QCoreApplication::instance()->applicationFilePath(); - if(::QKxProcessLaunch::startDetached(path)) { + if(QKxProcessLaunch::startDetached(path)) { QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection); } } @@ -527,15 +549,15 @@ void QWoMainWindow::onActionAdminTriggered() dlg.exec(); } -void QWoMainWindow::onActionUltimateTriggered() +void QWoMainWindow::onActionLicenseTriggered() { - QDesktopServices::openUrl(QUrl("http://woterm.com")); + QWoLicenseDialog dlg(this); + dlg.exec(); } -void QWoMainWindow::onActionRegisterTriggered() +void QWoMainWindow::onActionUpgradeTriggered() { - QKxLicenseDialog dlg(this); - dlg.exec(); + QWoVersionUpgradeTipDialog::check(this, false); } void QWoMainWindow::onFilterArrivedArrived(const QString &name, int type) @@ -579,19 +601,19 @@ void QWoMainWindow::initMenuBar() QObject::connect(ui->actionDocument, SIGNAL(triggered()), this, SLOT(onActionHelpTriggered())); QObject::connect(ui->actionWetsite, SIGNAL(triggered()), this, SLOT(onActionWebsiteTriggered())); QObject::connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(onActionAboutTriggered())); - QObject::connect(ui->actionRegister, SIGNAL(triggered()), this, SLOT(onActionRegisterTriggered())); - if(QKxVer::isUltimate()) { - QObject::connect(ui->actionAdministrator, SIGNAL(triggered()), this, SLOT(onActionAdminTriggered())); - ui->actionUltimate->setVisible(false); + QObject::connect(ui->actionLicense, SIGNAL(triggered()), this, SLOT(onActionLicenseTriggered())); + QObject::connect(ui->actionUpgrade, SIGNAL(triggered()), this, SLOT(onActionUpgradeTriggered())); + + if(QKxVer::instance()->isFullFeather()) { + QObject::connect(ui->actionAdministrator, SIGNAL(triggered()), this, SLOT(onActionAdminTriggered())); ui->menuOpen->setVisible(true); ui->actionOpenRemote2->deleteLater(); }else{ ui->actionAdministrator->setVisible(false); - QObject::connect(ui->actionUltimate, SIGNAL(triggered()), this, SLOT(onActionUltimateTriggered())); ui->menuOpen->deleteLater(); ui->actionOpenRemote2->setVisible(true); } - + ui->actionUpgrade->setVisible(false); } void QWoMainWindow::initToolBar() @@ -609,7 +631,7 @@ void QWoMainWindow::initToolBar() tool->addSeparator(); tool->addAction(QIcon(":/woterm/resource/skin/add2.png"), tr("New"), this, SLOT(onNewSession())); - if(QKxVer::isUltimate()){ + if(QKxVer::instance()->isFullFeather()){ QPushButton *btn = new QPushButton(QIcon(":/woterm/resource/skin/nodes.png"), tr("Open"), tool); btn->setObjectName("menuButton"); QKxButtonAssist *btnAssist = new QKxButtonAssist(":/woterm/resource/skin/arrowdown.png", false, btn); @@ -622,7 +644,7 @@ void QWoMainWindow::initToolBar() } tool->addAction(QIcon(":/woterm/resource/skin/layout.png"), tr("List"), this, SLOT(onLayout())); tool->addSeparator(); - if(QKxVer::isUltimate()){ + if(QKxVer::instance()->isFullFeather()){ QLineEdit *input = new QKxFilterLineEdit(tool); input->setMaximumWidth(250); input->setPlaceholderText(tr("Enter keyword to search")); @@ -664,7 +686,7 @@ void QWoMainWindow::saveLastState() bool QWoMainWindow::checkAdminLogin() { - if(!QKxVer::isUltimate()) { + if(!QKxVer::instance()->isFullFeather()) { return true; } QString pass = QWoSetting::adminPassword(); @@ -694,3 +716,9 @@ bool QWoMainWindow::checkAdminLogin() } return false; } + +void QWoMainWindow::tryToMakeLicenseTrial() +{ + QWoLicenseTrialApplyDialog dlg(this); + dlg.exec(); +} diff --git a/woterm/qwomainwindow.h b/woterm/qwomainwindow.h index 1f934c1..f2347c9 100644 --- a/woterm/qwomainwindow.h +++ b/woterm/qwomainwindow.h @@ -52,12 +52,13 @@ private slots: void onEditConfig(); void onSessionReadyToConnect(const QString& target, int type); void onAppStart(); - void onVersionCheck(int code, const QByteArray& body); void onShouldAppExit(); void onButtonAssistClicked(QToolButton *btn); void onRecentMenuAboutToShow(); + void onReportResult(int code, const QByteArray& body); + private slots: void onActionNewTriggered(); void onActionOpenRemoteTriggered(); @@ -80,8 +81,8 @@ private slots: void onActionScriptRunTriggered(); void onActionSshKeyManageTriggered(); void onActionAdminTriggered(); - void onActionUltimateTriggered(); - void onActionRegisterTriggered(); + void onActionLicenseTriggered(); + void onActionUpgradeTriggered(); void onFilterArrivedArrived(const QString& name, int type); void onFilterCreateArrived(const QString& name); @@ -94,6 +95,7 @@ private slots: void saveLastState(); bool checkAdminLogin(); + Q_INVOKABLE void tryToMakeLicenseTrial(); private: Ui::QWoMainWindow *ui; QPointer m_tab; diff --git a/woterm/qwomainwindow.ui b/woterm/qwomainwindow.ui index 20ec7d4..14849a9 100644 --- a/woterm/qwomainwindow.ui +++ b/woterm/qwomainwindow.ui @@ -96,8 +96,8 @@ - - + + @@ -218,11 +218,6 @@ Administrator - - - Upgrade to ultimate version - - @@ -275,9 +270,9 @@ Open remote session - + - Register... + License... @@ -285,6 +280,11 @@ Clear all + + + Upgrade check... + + diff --git a/woterm/qwoptytermwidgetimpl.cpp b/woterm/qwoptytermwidgetimpl.cpp index f033989..2e8c3de 100644 --- a/woterm/qwoptytermwidgetimpl.cpp +++ b/woterm/qwoptytermwidgetimpl.cpp @@ -1,4 +1,4 @@ -/******************************************************************************************* +/******************************************************************************************* * * Copyright (C) 2022 Guangzhou AoYiDuo Network Technology Co.,Ltd. All Rights Reserved. * @@ -13,7 +13,8 @@ #include "qwoglobal.h" #include "qwoshower.h" #include "qwoptytermwidget.h" - +#include "qwosetting.h" +#include "qwosessionttyproperty.h" QWoPtyTermWidgetImpl::QWoPtyTermWidgetImpl(const QString& target, int gid, QTabBar *tab, QWidget *parent) : QWoTermWidgetImpl(target, gid, tab, parent) @@ -33,3 +34,20 @@ QWoTermWidget *QWoPtyTermWidgetImpl::createTermWidget(const QString &target, int w->setObjectName(name); return w; } + +bool QWoPtyTermWidgetImpl::handleCustomProperties() +{ + QVariantMap prop = QWoSetting::localShell(); + QWoSessionTTYProperty dlg(QWoSessionTTYProperty::ETTY_LocalShell, this); + dlg.setCustom(prop); + dlg.exec(); + QVariantMap result = dlg.result(); + if(!result.isEmpty()) { + QWoSetting::setLocalShell(result); + for(int i = 0; i < m_terms.length(); i++) { + QWidget *w = m_terms.at(i); + QMetaObject::invokeMethod(w, "initCustom", Qt::QueuedConnection); + } + } + return true; +} diff --git a/woterm/qwoptytermwidgetimpl.h b/woterm/qwoptytermwidgetimpl.h index bc601cc..4b4e556 100644 --- a/woterm/qwoptytermwidgetimpl.h +++ b/woterm/qwoptytermwidgetimpl.h @@ -1,4 +1,4 @@ -/******************************************************************************************* +/******************************************************************************************* * * Copyright (C) 2022 Guangzhou AoYiDuo Network Technology Co.,Ltd. All Rights Reserved. * @@ -25,4 +25,5 @@ class QWoPtyTermWidgetImpl : public QWoTermWidgetImpl ~QWoPtyTermWidgetImpl(); protected: virtual QWoTermWidget *createTermWidget(const QString& target, int gid, QWidget *parent); + virtual bool handleCustomProperties(); }; diff --git a/woterm/qwordpwidgetimpl.h b/woterm/qwordpwidgetimpl.h index 4f01b9c..f426465 100644 --- a/woterm/qwordpwidgetimpl.h +++ b/woterm/qwordpwidgetimpl.h @@ -1,4 +1,4 @@ -/******************************************************************************************* +/******************************************************************************************* * * Copyright (C) 2022 Guangzhou AoYiDuo Network Technology Co.,Ltd. All Rights Reserved. * diff --git a/woterm/qwoserialwidgetimpl.cpp b/woterm/qwoserialwidgetimpl.cpp index 9131760..dabc3ba 100644 --- a/woterm/qwoserialwidgetimpl.cpp +++ b/woterm/qwoserialwidgetimpl.cpp @@ -95,6 +95,12 @@ void QWoSerialWidgetImpl::handleTabContextMenu(QMenu *menu) } +bool QWoSerialWidgetImpl::handleCustomProperties() +{ + QMetaObject::invokeMethod(m_term, "onModifyThisSession", Qt::QueuedConnection); + return true; +} + void QWoSerialWidgetImpl::updateEnable(bool on) { diff --git a/woterm/qwoserialwidgetimpl.h b/woterm/qwoserialwidgetimpl.h index cd8c1cf..55ec011 100644 --- a/woterm/qwoserialwidgetimpl.h +++ b/woterm/qwoserialwidgetimpl.h @@ -53,6 +53,7 @@ class QWoSerialWidgetImpl : public QWoShowerWidget virtual void closeEvent(QCloseEvent *event); virtual bool handleTabMouseEvent(QMouseEvent* ev); virtual void handleTabContextMenu(QMenu *menu); + virtual bool handleCustomProperties(); virtual void updateEnable(bool on); private slots: void onDestroyReady(); diff --git a/woterm/qwosessionlist.cpp b/woterm/qwosessionlist.cpp index 49ebd88..3f8acea 100644 --- a/woterm/qwosessionlist.cpp +++ b/woterm/qwosessionlist.cpp @@ -81,7 +81,7 @@ QWoSessionList::QWoSessionList(QWidget *parent) m_proxyModel = new QWoSortFilterProxyModel(1, this); m_proxyModel->setRecursiveFilteringEnabled(true); - if(QWoSetting::isListModel("docker") || !QKxVer::isUltimate()) { + if(QWoSetting::isListModel("docker") || !QKxVer::instance()->isFullFeather()) { m_btnModel->setIcon(QIcon(":/woterm/resource/skin/list.png")); m_proxyModel->setSourceModel(m_listModel); m_model = m_listModel; @@ -90,7 +90,7 @@ QWoSessionList::QWoSessionList(QWidget *parent) m_proxyModel->setSourceModel(m_treeModel); m_model = m_treeModel; } - m_btnModel->setVisible(QKxVer::isUltimate()); + m_btnModel->setVisible(QKxVer::instance()->isFullFeather()); m_tree->setModel(m_proxyModel); QObject::connect(m_input, SIGNAL(returnPressed()), this, SLOT(onEditReturnPressed())); @@ -474,7 +474,7 @@ bool QWoSessionList::handleListViewContextMenu(QContextMenuEvent *ev) menu.addAction(QIcon(":/woterm/resource/skin/ftp.png"), tr("Copy"), this, SLOT(onListViewItemCopy())); menu.addAction(tr("Delete"), this, SLOT(onListViewItemDelete())); } - if(QKxVer::isUltimate()) { + if(QKxVer::instance()->isFullFeather()) { if(m_model == m_listModel) { menu.addAction(tr("Show tree mode"), this, SLOT(onListViewGroupLayout())); }else{ diff --git a/woterm/qwosessionmanage.cpp b/woterm/qwosessionmanage.cpp index 40e5479..8ed10c7 100644 --- a/woterm/qwosessionmanage.cpp +++ b/woterm/qwosessionmanage.cpp @@ -51,7 +51,7 @@ QWoSessionManage::QWoSessionManage(QWidget *parent) m_proxyModel = new QWoSortFilterProxyModel(4, this); m_proxyModel->setRecursiveFilteringEnabled(true); ui->btnModel->setText(tr("Mode")); - if(QWoSetting::isListModel("manage")|| !QKxVer::isUltimate()) { + if(QWoSetting::isListModel("manage")|| !QKxVer::instance()->isFullFeather()) { ui->btnModel->setIcon(QIcon(":/woterm/resource/skin/list.png")); m_proxyModel->setSourceModel(m_listModel); m_model = m_listModel; @@ -85,7 +85,7 @@ QWoSessionManage::QWoSessionManage(QWidget *parent) QObject::connect(ui->btnNew, SIGNAL(clicked()), this, SLOT(onNewReady())); QObject::connect(m_tree, SIGNAL(itemChanged(const QModelIndex&)), this, SLOT(onTreeItemSelected(const QModelIndex&))); QObject::connect(m_tree, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(onTreeItemDoubleClicked(const QModelIndex&))); - if(QKxVer::isUltimate()) { + if(QKxVer::instance()->isFullFeather()) { ui->btnModel->setVisible(true); QObject::connect(ui->btnModel, SIGNAL(clicked()), this, SLOT(onTreeModelSwitch())); }else{ diff --git a/woterm/qwosessionproperty.cpp b/woterm/qwosessionproperty.cpp index bd47b87..4e181f7 100644 --- a/woterm/qwosessionproperty.cpp +++ b/woterm/qwosessionproperty.cpp @@ -222,7 +222,7 @@ void QWoSessionProperty::init() ui->portTip->setVisible(false); QObject::connect(ui->port, SIGNAL(textChanged(QString)), this, SLOT(onPortTextChanged(QString))); ui->password->setEchoMode(QLineEdit::Password); - if(QKxVer::isUltimate()) { + if(QKxVer::instance()->isFullFeather()) { QKxButtonAssist *assist = new QKxButtonAssist(":/woterm/resource/skin/eye.png", ui->password); QObject::connect(assist, SIGNAL(clicked(int)), this, SLOT(onAssistButtonClicked(int))); } @@ -708,6 +708,15 @@ bool QWoSessionProperty::saveConfig() QKxMessageBox::warning(this, tr("Info"), tr("The session name had been used, Change to another name.")); return false; } + QKxVer *ver = QKxVer::instance(); + if(ver->isFreeVersion() || ver->isExpired()) { + int cntMax = ver->maxSessionCount(); + int cntNow = QWoSshConf::instance()->hostCount(); + if(cntNow >= cntMax) { + QKxMessageBox::information(this, tr("Version restrictions"), tr("The session's count has reached the limit.")); + return false; + } + } } QString key = hostType2ShowerType(hi.type); QVariantMap prop = m_props.value(key); diff --git a/woterm/qwosetting.cpp b/woterm/qwosetting.cpp index 6b5547a..6b9bab0 100644 --- a/woterm/qwosetting.cpp +++ b/woterm/qwosetting.cpp @@ -242,6 +242,12 @@ void QWoSetting::setLanguageFile(const QString &lang) QWoSetting::setValue("language/path", lang); } +bool QWoSetting::isChineseLanguageFile() +{ + QString fileName = languageFile(); + return fileName.endsWith("_zh.qm"); +} + QString QWoSetting::lastBackupPath() { return value("backup/path", "").toString(); @@ -252,6 +258,23 @@ void QWoSetting::setLastBackupPath(const QString &path) setValue("backup/path", path); } +bool QWoSetting::shouldReportLicense() +{ + QDate dt = value("license/report").toDate(); + if(!dt.isValid()) { + return true; + } + QDate today = QDate::currentDate(); + return today >= dt; +} + +void QWoSetting::setIgnoreTodayReportLicense() +{ + QDate dt = QDate::currentDate(); + dt = dt.addDays(1); + setValue("license/report", dt); +} + bool QWoSetting::shouldPopupUpgradeUltimate() { QDate dt = value("upgrade/ultimate").toDate(); diff --git a/woterm/qwosetting.h b/woterm/qwosetting.h index f20471b..407819b 100644 --- a/woterm/qwosetting.h +++ b/woterm/qwosetting.h @@ -40,6 +40,7 @@ class QWoSetting : public QKxSetting Q_INVOKABLE static QString languagePath(const QString& name); Q_INVOKABLE static QString languageName(const QString& path); Q_INVOKABLE static void setLanguageFile(const QString& path); + Q_INVOKABLE static bool isChineseLanguageFile(); static QString sshServerDbPath(); static QString sftpTaskDbPath(); @@ -53,8 +54,12 @@ class QWoSetting : public QKxSetting Q_INVOKABLE static void setLastBackupPath(const QString& path); /* upgrade */ + static bool shouldReportLicense(); + static void setIgnoreTodayReportLicense(); + static bool shouldPopupUpgradeUltimate(); static void setIgnoreTodayUpgradeUltimate(); + static bool shouldPopupUpgradeVersionMessage(const QString& ver); static void setNextUpgradeVersionDate(const QString& ver, const QDate &dt); static void setIgnoreTodayUpgradeVersion(const QString& ver); diff --git a/woterm/qwosftpwidget.cpp b/woterm/qwosftpwidget.cpp index c4dbb6e..2965352 100644 --- a/woterm/qwosftpwidget.cpp +++ b/woterm/qwosftpwidget.cpp @@ -50,7 +50,7 @@ QWoSftpWidget::QWoSftpWidget(const QString &target, int gid, bool assist, QWidge : QWidget(parent) , ui(new Ui::QWoSftpWidget) , m_gid(gid) - , m_isUltimate(QKxVer::isUltimate()) + , m_isUltimate(QKxVer::instance()->isFullFeather()) , m_target(target) , m_savePassword(false) , m_bexit(false) @@ -582,7 +582,11 @@ void QWoSftpWidget::runUploadTask(const QList &lsfi) } if(!same.isEmpty()) { QString msg = same.join('\n'); - QKxMessageBox::information(this, tr("Upload information"), tr("the follow files has exist:")+"\n"+msg); + if(m_isUltimate) { + QKxMessageBox::information(this, tr("Upload information"), tr("the follow files has exist:")+"\n"+msg); + }else{ + QKxMessageBox::information(this, tr("Upload information"), tr("the follow files has exist or version restrictions:")+"\n"+msg); + } } } @@ -1028,7 +1032,11 @@ void QWoSftpWidget::onRemoteMenuDownload() } if(!same.isEmpty()) { QString msg = same.join('\n'); - QKxMessageBox::information(this, tr("Download information"), tr("the follow files has exist:")+"\n"+msg); + if(m_isUltimate) { + QKxMessageBox::information(this, tr("Download information"), tr("the follow files has exist:")+"\n"+msg); + }else{ + QKxMessageBox::information(this, tr("Download information"), tr("the follow files has exist or version restrictions:")+"\n"+msg); + } } } diff --git a/woterm/qwosftpwidgetimpl.cpp b/woterm/qwosftpwidgetimpl.cpp index cab19f6..5e3e838 100644 --- a/woterm/qwosftpwidgetimpl.cpp +++ b/woterm/qwosftpwidgetimpl.cpp @@ -18,6 +18,7 @@ #include "qwoevent.h" #include "qwocommandlineinput.h" #include "qkxmessagebox.h" +#include "qwosessionproperty.h" #include #include @@ -73,6 +74,11 @@ void QWoSftpWidgetImpl::handleTabContextMenu(QMenu *menu) menu->addAction(tr("New Session Multiplex"), this, SLOT(onNewSessionMultplex())); } +bool QWoSftpWidgetImpl::handleCustomProperties() +{ + return QWoShowerWidget::handleCustomProperties(); +} + void QWoSftpWidgetImpl::updateEnable(bool on) { diff --git a/woterm/qwosftpwidgetimpl.h b/woterm/qwosftpwidgetimpl.h index bb211b6..65d5fe6 100644 --- a/woterm/qwosftpwidgetimpl.h +++ b/woterm/qwosftpwidgetimpl.h @@ -34,6 +34,7 @@ class QWoSftpWidgetImpl : public QWoShowerWidget virtual void closeEvent(QCloseEvent *event); virtual bool handleTabMouseEvent(QMouseEvent* ev); virtual void handleTabContextMenu(QMenu *menu); + virtual bool handleCustomProperties(); virtual void updateEnable(bool on); private slots: void onDestroyReady(); diff --git a/woterm/qwoshower.cpp b/woterm/qwoshower.cpp index 75ef618..64630b4 100644 --- a/woterm/qwoshower.cpp +++ b/woterm/qwoshower.cpp @@ -28,6 +28,7 @@ #include "qkxmessagebox.h" #include "qwobindportpermissiondialog.h" #include "qkxver.h" +#include "qwosessionproperty.h" #include #include @@ -42,14 +43,18 @@ #include #include #include +#include #define FLOAT_WINDOW_TITLE ("FloatTitle") #define FLOAT_WINDOW_TOOLBAR ("FloatToolbar") #define FLOAT_WINDOW_ICON ("FloatIcon") +#define TAB_ITEM_DRAG_AWAY_DISTANCE (100) + QWoShower::QWoShower(QTabBar *tab, QWidget *parent) : QStackedWidget (parent) , m_tab(tab) + , m_implCount(0) { m_ptyico = QIcon(":/woterm/resource/skin/console.png"); m_sshico = QIcon(":/woterm/resource/skin/ssh2.png"); @@ -77,22 +82,29 @@ QWoShower::~QWoShower() bool QWoShower::openLocalShell() { - if(!QKxVer::isUltimate()) { + if(m_implCount >= QKxVer::instance()->maxTabCount()) { + QKxMessageBox::information(this, tr("Version restrictions"), tr("The tab's count has reached the limit.")); return false; } int gid = QWoUtils::gid(); QString target = tr("Local shell"); QWoPtyTermWidgetImpl *impl = new QWoPtyTermWidgetImpl(target, gid, m_tab, this); + impl->setProperty("ETabLimitType", ELT_LOCALSHELL); createTab(impl, m_ptyico, target); impl->setProperty(FLOAT_WINDOW_TOOLBAR, QWoFloatWindow::ETT_Term); impl->setProperty(FLOAT_WINDOW_TITLE, "WoTerm:"+target); impl->setProperty(FLOAT_WINDOW_ICON, ":/woterm/resource/skin/console.png"); emit floatChanged(impl, false); + m_implCount++; return true; } bool QWoShower::openScriptRuner(const QString& script) { + if(m_implCount >= QKxVer::instance()->maxTabCount()) { + QKxMessageBox::information(this, tr("Version restrictions"), tr("The tab's count has reached the limit.")); + return false; + } return true; } @@ -101,12 +113,18 @@ bool QWoShower::openSsh(const QString &target, int gid) if(gid < 0) { gid = QWoUtils::gid(); } + if(m_implCount >= QKxVer::instance()->maxTabCount()) { + QKxMessageBox::information(this, tr("Version restrictions"), tr("The tab's count has reached the limit.")); + return false; + } QWoSshTermWidgetImpl *impl = new QWoSshTermWidgetImpl(target, gid, m_tab, this); + impl->setProperty("ETabLimitType", ELT_SSH); createTab(impl, m_sshico, target); impl->setProperty(FLOAT_WINDOW_TOOLBAR, QWoFloatWindow::ETT_Term); impl->setProperty(FLOAT_WINDOW_TITLE, "WoTerm-"+target); impl->setProperty(FLOAT_WINDOW_ICON, ":/woterm/resource/skin/ssh2.png"); emit floatChanged(impl, false); + m_implCount++; return true; } @@ -115,44 +133,55 @@ bool QWoShower::openSftp(const QString &target, int gid) if(gid < 0) { gid = QWoUtils::gid(); } - + if(m_implCount >= QKxVer::instance()->maxTabCount()) { + QKxMessageBox::information(this, tr("Version restrictions"), tr("The tab's count has reached the limit.")); + return false; + } QWoSftpWidgetImpl *impl = new QWoSftpWidgetImpl(target, gid, m_tab, this); + impl->setProperty("ETabLimitType", ELT_SFTP); createTab(impl, m_ftpico, target); impl->setProperty(FLOAT_WINDOW_TOOLBAR, QWoFloatWindow::ETT_Term); impl->setProperty(FLOAT_WINDOW_TITLE, "WoTerm:"+target); impl->setProperty(FLOAT_WINDOW_ICON, ":/woterm/resource/skin/sftp.png"); emit floatChanged(impl, false); + m_implCount++; return true; } bool QWoShower::openTelnet(const QString &target) { - if(!QKxVer::isUltimate()) { + if(m_implCount >= QKxVer::instance()->maxTabCount()) { + QKxMessageBox::information(this, tr("Version restrictions"), tr("The tab's count has reached the limit.")); return false; } QWoTelnetTermWidgetImpl *impl = new QWoTelnetTermWidgetImpl(target, QWoUtils::gid(), m_tab, this); + impl->setProperty("ETabLimitType", ELT_TELNET); createTab(impl, m_telico, target); impl->setProperty(FLOAT_WINDOW_TOOLBAR, QWoFloatWindow::ETT_Term); impl->setProperty(FLOAT_WINDOW_TITLE, "WoTerm:"+target); impl->setProperty(FLOAT_WINDOW_ICON, ":/woterm/resource/skin/telnet.png"); emit floatChanged(impl, false); + m_implCount++; return true; } bool QWoShower::openRLogin(const QString &target) { - if(!QKxVer::isUltimate()) { + if(m_implCount >= QKxVer::instance()->maxTabCount()) { + QKxMessageBox::information(this, tr("Version restrictions"), tr("The tab's count has reached the limit.")); return false; } if(QWoUtils::hasUnprivilegedPortPermission()) { QWoRLoginTermWidgetImpl *impl = new QWoRLoginTermWidgetImpl(target, QWoUtils::gid(), m_tab, this); + impl->setProperty("ETabLimitType", ELT_RLOGIN); createTab(impl, m_rloico, target); impl->setProperty(FLOAT_WINDOW_TOOLBAR, QWoFloatWindow::ETT_Term); impl->setProperty(FLOAT_WINDOW_TITLE, "WoTerm:"+target); impl->setProperty(FLOAT_WINDOW_ICON, ":/woterm/resource/skin/rlogin.png"); emit floatChanged(impl, false); + m_implCount++; return true; - } + } QWoBindPortPermissionDialog dlg(target, this); if(dlg.exec() == (QDialog::Accepted+1)) { return openRLogin(target); @@ -162,44 +191,53 @@ bool QWoShower::openRLogin(const QString &target) bool QWoShower::openMstsc(const QString &target) { - if(!QKxVer::isUltimate()) { + if(m_implCount >= QKxVer::instance()->maxTabCount()) { + QKxMessageBox::information(this, tr("Version restrictions"), tr("The tab's count has reached the limit.")); return false; } QWoRdpWidgetImpl *impl = new QWoRdpWidgetImpl(target, m_tab, this); + impl->setProperty("ETabLimitType", ELT_RDP); createTab(impl, m_mtsico, target); impl->setProperty(FLOAT_WINDOW_TOOLBAR, QWoFloatWindow::ETT_Mstsc); impl->setProperty(FLOAT_WINDOW_TITLE, "WoTerm:"+target); impl->setProperty(FLOAT_WINDOW_ICON, ":/woterm/resource/skin/mstsc2.png"); emit floatChanged(impl, false); + m_implCount++; return true; } bool QWoShower::openVnc(const QString &target) { - if(!QKxVer::isUltimate()) { + if(m_implCount >= QKxVer::instance()->maxTabCount()) { + QKxMessageBox::information(this, tr("Version restrictions"), tr("The tab's count has reached the limit.")); return false; } QWoVncWidgetImpl *impl = new QWoVncWidgetImpl(target, m_tab, this); + impl->setProperty("ETabLimitType", ELT_VNC); createTab(impl, m_vncico, target); impl->setProperty(FLOAT_WINDOW_TOOLBAR, QWoFloatWindow::ETT_Vnc); impl->setProperty(FLOAT_WINDOW_TITLE, "WoTerm:"+target); impl->setProperty(FLOAT_WINDOW_ICON, ":/woterm/resource/skin/vnc2.png"); emit floatChanged(impl, false); + m_implCount++; return true; } bool QWoShower::openSerialPort() { - if(!QKxVer::isUltimate()) { + if(m_implCount >= QKxVer::instance()->maxTabCount()) { + QKxMessageBox::information(this, tr("Version restrictions"), tr("The tab's count has reached the limit.")); return false; } QString target = tr("SerialPort"); QWoSerialWidgetImpl *impl = new QWoSerialWidgetImpl(target, QWoUtils::gid(), m_tab, this); + impl->setProperty("ETabLimitType", ELT_SERIALPORT); createTab(impl, m_serico, target); impl->setProperty(FLOAT_WINDOW_TOOLBAR, QWoFloatWindow::ETT_Term); impl->setProperty(FLOAT_WINDOW_TITLE, "WoTerm:"+target); impl->setProperty(FLOAT_WINDOW_ICON, ":/woterm/resource/skin/serialport.png"); emit floatChanged(impl, false); + m_implCount++; return true; } @@ -281,14 +319,14 @@ void QWoShower::paintEvent(QPaintEvent *event) QRect rt(0, 0, width(), height()); p.fillRect(rt, QColor(Qt::black)); QFont ft = p.font(); - ft.setPixelSize(190); + ft.setPixelSize(100); ft.setBold(true); p.setFont(ft); QPen pen = p.pen(); pen.setStyle(Qt::DotLine); pen.setColor(Qt::lightGray); QBrush brush = pen.brush(); - brush.setStyle(Qt::Dense7Pattern); + brush.setStyle(Qt::Dense6Pattern); pen.setBrush(brush); p.setPen(pen); p.drawText(rt, Qt::AlignCenter, "WoTerm"); @@ -296,9 +334,17 @@ void QWoShower::paintEvent(QPaintEvent *event) bool QWoShower::eventFilter(QObject *obj, QEvent *ev) { - switch (ev->type()) { - case QEvent::MouseButtonPress: - return tabMouseButtonPress((QMouseEvent*)ev); + QEvent::Type type = ev->type(); + if(type == QEvent::MouseButtonPress) { + QTabBar* tab = qobject_cast(obj); + if(tab) { + return tabMouseButtonPress(reinterpret_cast(ev)); + } + }else if(type == QEvent::MouseMove) { + QTabBar* tab = qobject_cast(obj); + if(tab) { + return tabMouseButtonMove(reinterpret_cast(ev)); + } } return false; } @@ -341,6 +387,8 @@ void QWoShower::createTab(QWoShowerWidget *impl, const QIcon&icon, const QString bool QWoShower::tabMouseButtonPress(QMouseEvent *ev) { + m_tabDragAway = false; + m_tabDragWidget = nullptr; QPoint pt = ev->pos(); int idx = m_tab->tabAt(pt); if(idx < 0) { @@ -354,13 +402,32 @@ bool QWoShower::tabMouseButtonPress(QMouseEvent *ev) QMenu menu(impl); m_tabMenu = &menu; m_tabMenu->setProperty(TAB_TARGET_IMPL, QVariant::fromValue(impl)); - menu.addAction(tr("Close This Tab"), this, SLOT(onCloseThisTabSession())); - menu.addAction(tr("Close Other Tab"), this, SLOT(onCloseOtherTabSession())); - menu.addAction(tr("Float This Tab"), this, SLOT(onFloatThisTabSession())); + menu.addAction(tr("Close this tab"), this, SLOT(onCloseThisTabSession())); + menu.addAction(tr("Close other tab"), this, SLOT(onCloseOtherTabSession())); + menu.addAction(tr("Copy session"), this, SLOT(onNewTheSameSession())); + menu.addAction(tr("Copy host address"), this, SLOT(onCopyTabSessionAddress())); + menu.addAction(tr("Edit this session"), this, SLOT(onEditThisTabSession())); + menu.addAction(tr("Float this tab"), this, SLOT(onFloatThisTabSession())); impl->handleTabContextMenu(&menu); menu.exec(QCursor::pos()); + }else if(ev->buttons().testFlag(Qt::LeftButton)){ + m_tabDragWidget = impl; } + return false; +} +bool QWoShower::tabMouseButtonMove(QMouseEvent *ev) +{ + QPoint pt = ev->pos(); + if(ev->buttons().testFlag(Qt::LeftButton)) { + if(pt.y() > TAB_ITEM_DRAG_AWAY_DISTANCE) { + //qDebug() << "tabMouseButtonMove" << pt; + if(m_tabDragWidget) { + floatSession(m_tabDragWidget, false); + m_tabDragWidget = nullptr; + } + } + } return false; } @@ -384,10 +451,11 @@ void QWoShower::onTabCurrentChanged(int idx) void QWoShower::onTabWidgetDestroy(QObject *it) { QWidget *target = qobject_cast(it); + m_implCount--; for(int i = 0; i < m_tab->count(); i++) { QVariant v = m_tab->tabData(i); QWidget *impl = v.value(); - if(target == impl) { + if(target == impl) { removeWidget(target); m_tab->removeTab(i); break; @@ -399,7 +467,7 @@ void QWoShower::onTabWidgetDestroy(QObject *it) void QWoShower::onTabbarDoubleClicked(int index) { - if(index < 0) { + if(index < 0 && QKxVer::instance()->isFullFeather()) { openLocalShell(); } } @@ -438,6 +506,50 @@ void QWoShower::onCloseOtherTabSession() } } +void QWoShower::onNewTheSameSession() +{ + QVariant vimpl = m_tabMenu->property(TAB_TARGET_IMPL); + QWoShowerWidget *impl = vimpl.value(); + QString target = impl->targetName(); + ELimitType t = static_cast(impl->property("ETabLimitType").toInt()); + if(t == ELT_LOCALSHELL) { + openLocalShell(); + }else if(t == ELT_SSH) { + openSsh(target); + }else if(t == ELT_SFTP) { + openSftp(target); + }else if(t == ELT_TELNET) { + openTelnet(target); + }else if(t == ELT_RLOGIN) { + openRLogin(target); + }else if(t == ELT_RDP) { + openMstsc(target); + }else if(t == ELT_VNC) { + openVnc(target); + }else if(t == ELT_SERIALPORT) { + openSerialPort(); + } +} + +void QWoShower::onCopyTabSessionAddress() +{ + QVariant vimpl = m_tabMenu->property(TAB_TARGET_IMPL); + QWoShowerWidget *impl = vimpl.value(); + QString target = impl->targetName(); + const HostInfo& hi = QWoSshConf::instance()->find(target); + if(hi.isValid()) { + QClipboard *clip = QGuiApplication::clipboard(); + clip->setText(hi.host); + } +} + +void QWoShower::onEditThisTabSession() +{ + QVariant vimpl = m_tabMenu->property(TAB_TARGET_IMPL); + QWoShowerWidget *impl = vimpl.value(); + impl->handleCustomProperties(); +} + void QWoShower::onFloatThisTabSession() { if(m_tabMenu == nullptr) { @@ -460,14 +572,17 @@ void QWoShower::floatSession(QWoShowerWidget *impl, bool full) break; } } - QString icon = impl->property(FLOAT_WINDOW_ICON).toString(); QString title = impl->property(FLOAT_WINDOW_TITLE).toString(); QWoFloatWindow::EToolType typ = impl->property(FLOAT_WINDOW_TOOLBAR).value(); QWoFloatWindow *wfloat = new QWoFloatWindow(impl, this, typ); wfloat->setWindowTitle(title); wfloat->setWindowIcon(QIcon(icon)); - wfloat->resize(1024, 768); + QRect rtImpl = rect(); + QPoint pt = mapToGlobal(QPoint(0, 0)); + rtImpl.moveTo(pt); + rtImpl.translate(50, 50); + wfloat->setGeometry(rtImpl); if(full) { wfloat->showFullScreen(); }else{ @@ -517,10 +632,12 @@ void QWoShower::onCleanNilFloatWindow() void QWoShower::onTabContextMenu(QMouseEvent *ev) { if(ev->buttons() & Qt::RightButton) { - QMenu menu; - menu.addAction(QIcon(":/woterm/resource/skin/nodes.png"), tr("Open remote session"), this, SLOT(onOpenRemoteSession())); - menu.addAction(QIcon(":/woterm/resource/skin/console.png"), tr("Open local session"), this, SLOT(onOpenLocalSession())); - menu.exec(QCursor::pos()); + if(QKxVer::instance()->isFullFeather()) { + QMenu menu; + menu.addAction(QIcon(":/woterm/resource/skin/nodes.png"), tr("Open remote session"), this, SLOT(onOpenRemoteSession())); + menu.addAction(QIcon(":/woterm/resource/skin/console.png"), tr("Open local session"), this, SLOT(onOpenLocalSession())); + menu.exec(QCursor::pos()); + } } } diff --git a/woterm/qwoshower.h b/woterm/qwoshower.h index 567b4ef..a0c2ab3 100644 --- a/woterm/qwoshower.h +++ b/woterm/qwoshower.h @@ -15,6 +15,7 @@ #include #include #include +#include class QTabBar; class QWoTermWidget; @@ -27,6 +28,7 @@ class QWoFloatWindow; #define TAB_TYPE_NAME ("tabtype") #define TAB_TARGET_IMPL ("tabimpl") +class QWoShowerWidget; class QWoShower : public QStackedWidget { Q_OBJECT @@ -36,6 +38,18 @@ class QWoShower : public QStackedWidget ETSsh = 0x02, ETScript = 0x03 } ETabType; + + enum ELimitType { + ELT_LOCALSHELL = 0, + ELT_SCRIPTRUNNER = 1, + ELT_SSH = 2, + ELT_SFTP = 3, + ELT_TELNET = 4, + ELT_RLOGIN = 5, + ELT_RDP = 6, + ELT_VNC = 7, + ELT_SERIALPORT = 8 + }; public: explicit QWoShower(QTabBar *tab, QWidget *parent=nullptr); virtual ~QWoShower(); @@ -75,6 +89,7 @@ class QWoShower : public QStackedWidget void closeSession(int idx); void createTab(QWoShowerWidget *widget, const QIcon& icon, const QString& tabName); bool tabMouseButtonPress(QMouseEvent *ev); + bool tabMouseButtonMove(QMouseEvent *ev); private slots: void onTabCloseRequested(int index); @@ -83,6 +98,9 @@ private slots: void onTabbarDoubleClicked(int index); void onCloseThisTabSession(); void onCloseOtherTabSession(); + void onNewTheSameSession(); + void onCopyTabSessionAddress(); + void onEditThisTabSession(); void onFloatThisTabSession(); void onCleanNilFloatWindow(); void onTabContextMenu(QMouseEvent *ev); @@ -101,6 +119,10 @@ private slots: QPointer m_tab; QPointer m_tabMenu; QFont m_font; + int m_implCount; QList> m_floats; + + bool m_tabDragAway; + QPointer m_tabDragWidget; }; diff --git a/woterm/qwoshowerwidget.cpp b/woterm/qwoshowerwidget.cpp index 99e559e..0800dc8 100644 --- a/woterm/qwoshowerwidget.cpp +++ b/woterm/qwoshowerwidget.cpp @@ -10,7 +10,9 @@ *******************************************************************************************/ #include "qwoshowerwidget.h" - +#include "qwosessionproperty.h" +#include "qwosshconf.h" +#include "qkxmessagebox.h" QWoShowerWidget::QWoShowerWidget(const QString &target, QWidget *parent) : QWoWidget (parent) @@ -20,3 +22,15 @@ QWoShowerWidget::QWoShowerWidget(const QString &target, QWidget *parent) setAttribute(Qt::WA_StyledBackground); setAttribute(Qt::WA_DeleteOnClose); } + +bool QWoShowerWidget::handleCustomProperties() +{ + if(!QWoSshConf::instance()->exists(m_target)){ + QKxMessageBox::warning(this, tr("Error"), tr("can't find the session, maybe it had been delete ago")); + return false; + } + QWoSessionProperty dlg(this); + dlg.setSession(m_target); + int ret = dlg.exec(); + return ret == QWoSessionProperty::Save; +} diff --git a/woterm/qwoshowerwidget.h b/woterm/qwoshowerwidget.h index 34224a4..df86673 100644 --- a/woterm/qwoshowerwidget.h +++ b/woterm/qwoshowerwidget.h @@ -1,4 +1,4 @@ -/******************************************************************************************* +/******************************************************************************************* * * Copyright (C) 2022 Guangzhou AoYiDuo Network Technology Co.,Ltd. All Rights Reserved. * @@ -32,7 +32,8 @@ class QWoShowerWidget : public QWoWidget protected: virtual bool handleTabMouseEvent(QMouseEvent *ev) = 0; virtual void handleTabContextMenu(QMenu *menu) = 0; - virtual QMap collectUnsafeCloseMessage() = 0; + virtual QMap collectUnsafeCloseMessage() = 0; + virtual bool handleCustomProperties(); protected: friend class QWoShower; int m_id; diff --git a/woterm/qwosshconf.cpp b/woterm/qwosshconf.cpp index b9660b9..b2d4f48 100644 --- a/woterm/qwosshconf.cpp +++ b/woterm/qwosshconf.cpp @@ -1184,6 +1184,11 @@ QStringList QWoSshConf::qmlProxyJumpers() const return hostNameList(SshWithSftp); } +int QWoSshConf::hostCount() const +{ + return m_hosts.size(); +} + void QWoSshConf::onAboutToQuit() { backup(m_dbFile + ".bak"); diff --git a/woterm/qwosshconf.h b/woterm/qwosshconf.h index c3e3a27..7bac467 100644 --- a/woterm/qwosshconf.h +++ b/woterm/qwosshconf.h @@ -68,6 +68,8 @@ class QWoSshConf : public QObject QList proxyJumpers(const QString& name, int max=2) const; Q_INVOKABLE QStringList qmlProxyJumpers() const; + int hostCount() const; + signals: void dataReset(); private slots: diff --git a/woterm/qwosshtermwidgetimpl.cpp b/woterm/qwosshtermwidgetimpl.cpp index e3153aa..b5527a0 100644 --- a/woterm/qwosshtermwidgetimpl.cpp +++ b/woterm/qwosshtermwidgetimpl.cpp @@ -46,8 +46,8 @@ QWoTermWidget *QWoSshTermWidgetImpl::createTermWidget(const QString &target, int void QWoSshTermWidgetImpl::handleTabContextMenu(QMenu *menu) { - menu->addAction(tr("Sftp Assistant"), this, SLOT(onSftpAssistOpen())); - menu->addAction(tr("New Session Multiplex"), this, SLOT(onNewSessionMultplex())); + menu->addAction(tr("Sftp assistant"), this, SLOT(onSftpAssistOpen())); + menu->addAction(tr("New session multiplex"), this, SLOT(onNewSessionMultplex())); } void QWoSshTermWidgetImpl::onSftpAssistOpen() diff --git a/woterm/qwotermwidget.cpp b/woterm/qwotermwidget.cpp index 8c97dcc..f4d1485 100644 --- a/woterm/qwotermwidget.cpp +++ b/woterm/qwotermwidget.cpp @@ -47,6 +47,7 @@ QWoTermWidget::QWoTermWidget(const QString& target, int gid, ETermType ttype, QW , m_gid(gid) , m_bexit(false) , m_ttype(ttype) + , m_rkeyPaste(false) { static int idx = 0; setObjectName(QString("QWoTermWidget:%1").arg(idx++)); @@ -147,7 +148,7 @@ bool QWoTermWidget::event(QEvent *ev) void QWoTermWidget::initDefault() { QVariantMap mdata = QWoSetting::ttyDefault(); - resetProperty(mdata); + resetProperty(mdata, true); } void QWoTermWidget::initCustom() @@ -221,9 +222,9 @@ void QWoTermWidget::onFloatThisTab() } } -void QWoTermWidget::resetProperty(QVariantMap mdata) +void QWoTermWidget::resetProperty(QVariantMap mdata, bool force) { - if(mdata.isEmpty()) { + if(mdata.isEmpty() && !force) { return; } QString schema = mdata.value("colorSchema", DEFAULT_COLOR_SCHEMA).toString(); diff --git a/woterm/qwotermwidget.h b/woterm/qwotermwidget.h index d21c5f2..64f76ea 100644 --- a/woterm/qwotermwidget.h +++ b/woterm/qwotermwidget.h @@ -75,7 +75,7 @@ class QWoTermWidget : public QKxTermWidget virtual QList collectUnsafeCloseMessage() = 0; protected: void initDefault(); - void initCustom(); + Q_INVOKABLE void initCustom(); protected slots: void onResetTermSize(); void onCleanHistory(); @@ -83,7 +83,7 @@ protected slots: void onStopOutputHistoryFile(); void onFloatThisTab(); private: - void resetProperty(QVariantMap data); + void resetProperty(QVariantMap data, bool force=false); QWoTermWidgetImpl *findTermImpl(); void addToTermImpl(); diff --git a/woterm/qwotermwidgetimpl.cpp b/woterm/qwotermwidgetimpl.cpp index 742d82e..bf6172b 100644 --- a/woterm/qwotermwidgetimpl.cpp +++ b/woterm/qwotermwidgetimpl.cpp @@ -19,6 +19,7 @@ #include "qwocommandlineinput.h" #include "qwoutils.h" #include "qkxmessagebox.h" +#include "qwosessionproperty.h" #include #include @@ -104,7 +105,18 @@ void QWoTermWidgetImpl::handleTabContextMenu(QMenu *menu) { // if(m_terms.length() > 1) { // menu->addAction(tr("Command line input..."), this, SLOT(onCommandInputInSamePage())); -// } + // } +} + +bool QWoTermWidgetImpl::handleCustomProperties() +{ + if(QWoShowerWidget::handleCustomProperties()) { + for(int i = 0; i < m_terms.length(); i++) { + QWidget *w = m_terms.at(i); + QMetaObject::invokeMethod(w, "initCustom", Qt::QueuedConnection); + } + } + return true; } void QWoTermWidgetImpl::updateEnable(bool on) diff --git a/woterm/qwotermwidgetimpl.h b/woterm/qwotermwidgetimpl.h index 9a8d39f..d8081c7 100644 --- a/woterm/qwotermwidgetimpl.h +++ b/woterm/qwotermwidgetimpl.h @@ -1,4 +1,4 @@ -/******************************************************************************************* +/******************************************************************************************* * * Copyright (C) 2022 Guangzhou AoYiDuo Network Technology Co.,Ltd. All Rights Reserved. * @@ -44,6 +44,7 @@ private slots: virtual void closeEvent(QCloseEvent *event); virtual bool handleTabMouseEvent(QMouseEvent* ev); virtual void handleTabContextMenu(QMenu *menu); + virtual bool handleCustomProperties(); virtual void updateEnable(bool on); protected: void addAssistant(QWidget *w, bool first); diff --git a/woterm/qwoutils.cpp b/woterm/qwoutils.cpp index 114188f..34f91a8 100644 --- a/woterm/qwoutils.cpp +++ b/woterm/qwoutils.cpp @@ -768,7 +768,7 @@ QByteArray QWoUtils::aesDecrypt(const QByteArray &all, const QByteArray &pass) bool QWoUtils::isUltimateVersion(QWidget *parent) { - if(!QKxVer::isUltimate()) { + if(!QKxVer::instance()->isFullFeather()) { QKxMessageBox::information(parent, QObject::tr("Ultimate version"), QObject::tr("this is the feature of the ultimate version, please upgrade to latest version.")); return false; } @@ -783,6 +783,8 @@ QString QWoUtils::getPassword(QWidget *parent, const QString &label) input.setWindowTitle(QObject::tr("Password input")); input.setLabelText(label); input.setTextEchoMode(QLineEdit::Password); + input.setOkButtonText(tr("Ok")); + input.setCancelButtonText(tr("Cancel")); int err = input.exec(); if(err == 0) { return QString(); diff --git a/woterm/qwoversionupgradetipdialog.cpp b/woterm/qwoversionupgradetipdialog.cpp new file mode 100644 index 0000000..a5b084f --- /dev/null +++ b/woterm/qwoversionupgradetipdialog.cpp @@ -0,0 +1,156 @@ +/******************************************************************************************* +* +* Copyright (C) 2023 Guangzhou AoYiDuo Network Technology Co.,Ltd. All Rights Reserved. +* +* Contact: http://www.aoyiduo.com +* +* this file is used under the terms of the GPLv3[GNU GENERAL PUBLIC LICENSE v3] +* more information follow the website: https://www.gnu.org/licenses/gpl-3.0.en.html +* +*******************************************************************************************/ + +#include "qwoversionupgradetipdialog.h" +#include "ui_qwoversionupgradetipdialog.h" +#include "qkxhttpclient.h" +#include "qwosetting.h" +#include "qwoutils.h" +#include "version.h" +#include "qkxmessagebox.h" + +#include +#include +#include +#include +#include + +QWoVersionUpgradeTipDialog::QWoVersionUpgradeTipDialog(bool isAuto, QWidget *parent) + : QDialog(parent) + , ui(new Ui::QWoVersionUpgradeTipDialog) + , m_parent(parent) + , m_isAuto(isAuto) + +{ + ui->setupUi(this); + + setWindowTitle(tr("Version upgrade")); + + QObject::connect(ui->btnIgnore, SIGNAL(clicked()), this, SLOT(onIgnoreButtonClicked())); + QObject::connect(ui->btn7Days, SIGNAL(clicked()), this, SLOT(on7DaysButtonClicked())); + QObject::connect(ui->btnTomorrow, SIGNAL(clicked()), this, SLOT(onTomorrowButtonClicked())); + QObject::connect(ui->btnUpgrade, SIGNAL(clicked()), this, SLOT(onUpgradeButtonClicked())); + + checkVersion(); +} + +QWoVersionUpgradeTipDialog::~QWoVersionUpgradeTipDialog() +{ + delete ui; +} + + +void QWoVersionUpgradeTipDialog::check(QWidget *parent, bool isAuto) +{ + QWoVersionUpgradeTipDialog *dlg = new QWoVersionUpgradeTipDialog(isAuto, parent); + Q_UNUSED(dlg) +} + +void QWoVersionUpgradeTipDialog::checkVersion() +{ + QKxHttpClient *http = new QKxHttpClient(this); + QObject::connect(http, SIGNAL(result(int,QByteArray)), this, SLOT(onVersionCheck(int,QByteArray))); + QObject::connect(http, SIGNAL(finished()), http, SLOT(deleteLater())); + http->get("http://down.woterm.com/.ver"); +} + +void QWoVersionUpgradeTipDialog::getVersionDescription() +{ + QString lang = QDir::cleanPath(QWoSetting::languageFile()); + int pos = lang.lastIndexOf('_'); + if(pos > 0) { + lang = lang.mid(pos+1); + } + pos = lang.lastIndexOf('.'); + if(pos > 0) { + lang = lang.left(pos); + } + QString verDesc = QString("http://down.woterm.com/.desc/latest-%1").arg(lang); + qDebug() << "QWoVersionUpgradeTipDialog" << verDesc; + QKxHttpClient *http = new QKxHttpClient(this); + QObject::connect(http, SIGNAL(result(int,QByteArray)), this, SLOT(onVersionDescriptionGet(int,QByteArray))); + QObject::connect(http, SIGNAL(finished()), http, SLOT(deleteLater())); + http->get(verDesc); +} + +void QWoVersionUpgradeTipDialog::onVersionCheck(int code, const QByteArray &body) +{ + handleVersionCheck(code, body); + deleteLater(); +} + +void QWoVersionUpgradeTipDialog::onVersionDescriptionGet(int code, const QByteArray& body) +{ + if(code == 200) { + ui->desc->setPlainText(QString::fromUtf8(body)); + }else{ + ui->desc->setPlainText(tr("Failed to get upgrade content.")); + } +} + +void QWoVersionUpgradeTipDialog::onIgnoreButtonClicked() +{ + QWoSetting::setSkipThisVersion(m_verBody); + done(QDialog::Accepted); +} + +void QWoVersionUpgradeTipDialog::on7DaysButtonClicked() +{ + QDate dt = QDate::currentDate(); + dt = dt.addDays(7); + QWoSetting::setNextUpgradeVersionDate(m_verBody, dt); + done(QDialog::Accepted); +} + +void QWoVersionUpgradeTipDialog::onTomorrowButtonClicked() +{ + QWoSetting::setIgnoreTodayUpgradeVersion(m_verBody); + done(QDialog::Accepted); +} + +void QWoVersionUpgradeTipDialog::onUpgradeButtonClicked() +{ + QDesktopServices::openUrl(QUrl("http://woterm.com")); + done(QDialog::Accepted); +} + +bool QWoVersionUpgradeTipDialog::handleVersionCheck(int code, const QByteArray &body) +{ + if(body.isEmpty()) { + return false; + } + if(code == 200) { + qDebug() << code << body; + QString verBody = body.trimmed(); + if(body[0] == 'v') { + verBody = verBody.mid(1); + } + m_verBody = verBody; + int verLatest = QWoUtils::parseVersion(verBody); + int verCurrent = QWoUtils::parseVersion(WOTERM_VERSION); + if(verCurrent < verLatest) { + if(m_isAuto) { + bool pop = QWoSetting::shouldPopupUpgradeVersionMessage(verBody); + if(!pop) { + return false; + } + + } + getVersionDescription(); + exec(); + }else if(!m_isAuto){ + QKxMessageBox::information(m_parent, tr("Upgrade information"), tr("The current version is already the latest version.")); + } + }else if(!m_isAuto) { + QKxMessageBox::information(m_parent, tr("Upgrade information"), tr("Unexpected error, please try again later.")); + } + return true; +} diff --git a/woterm/qwoversionupgradetipdialog.h b/woterm/qwoversionupgradetipdialog.h new file mode 100644 index 0000000..06ffc7f --- /dev/null +++ b/woterm/qwoversionupgradetipdialog.h @@ -0,0 +1,54 @@ +/******************************************************************************************* +* +* Copyright (C) 2023 Guangzhou AoYiDuo Network Technology Co.,Ltd. All Rights Reserved. +* +* Contact: http://www.aoyiduo.com +* +* this file is used under the terms of the GPLv3[GNU GENERAL PUBLIC LICENSE v3] +* more information follow the website: https://www.gnu.org/licenses/gpl-3.0.en.html +* +*******************************************************************************************/ + +#ifndef QWOVERSIONUPGRADETIPDIALOG_H +#define QWOVERSIONUPGRADETIPDIALOG_H + +#include +#include + +namespace Ui { +class QWoVersionUpgradeTipDialog; +} + +class QWoVersionUpgradeTipDialog : public QDialog +{ + Q_OBJECT + +public: + ~QWoVersionUpgradeTipDialog(); + + static void check(QWidget *parent, bool isAuto); + +protected: + explicit QWoVersionUpgradeTipDialog(bool isAuto, QWidget *parent = nullptr); + + Q_INVOKABLE void checkVersion(); + Q_INVOKABLE void getVersionDescription(); + +private slots: + void onVersionCheck(int code, const QByteArray& body); + void onVersionDescriptionGet(int code, const QByteArray& body); + void onIgnoreButtonClicked(); + void on7DaysButtonClicked(); + void onTomorrowButtonClicked(); + void onUpgradeButtonClicked(); + +private: + Q_INVOKABLE bool handleVersionCheck(int code, const QByteArray& body); +private: + Ui::QWoVersionUpgradeTipDialog *ui; + QPointer m_parent; + bool m_isAuto; + QString m_verBody; +}; + +#endif // QWOVERSIONUPGRADETIPDIALOG_H diff --git a/woterm/qkxlicensedialog.ui b/woterm/qwoversionupgradetipdialog.ui similarity index 51% rename from woterm/qkxlicensedialog.ui rename to woterm/qwoversionupgradetipdialog.ui index 7115da8..e099452 100644 --- a/woterm/qkxlicensedialog.ui +++ b/woterm/qwoversionupgradetipdialog.ui @@ -1,86 +1,92 @@ - - - QKxLicenseDialog - - - - 0 - 0 - 321 - 193 - - - - Dialog - - - - - - - - License type: - - - - - - - - 0 - 0 - - - - - - - - - - - - - - - - Qt::Horizontal - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Activate - - - - - - - Close - - - - - - - - - - + + + QWoVersionUpgradeTipDialog + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + + Upgrade content: + + + + + + + true + + + + + + + + + Ignore this version + + + Ignore + + + + + + + Pop up again in seven days + + + 7 days + + + + + + + Pop up again tomorrow + + + Tomorrow + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Upgrade + + + + + + + + + + diff --git a/woterm/resource/qss/desk_default.qss b/woterm/resource/qss/desk_default.qss index 62dd01a..b8d9fa2 100644 --- a/woterm/resource/qss/desk_default.qss +++ b/woterm/resource/qss/desk_default.qss @@ -6,6 +6,10 @@ QKxFilterListView { background-color: rgb(223, 242, 255); } +QKxFilterLineEdit{ + min-height: 16px; +} + QPlainTextEdit { background-color: rgba(100,190,233,50); border: 1px; diff --git a/woterm/resource/skin/tips.png b/woterm/resource/skin/tips.png new file mode 100644 index 0000000..24a4e76 Binary files /dev/null and b/woterm/resource/skin/tips.png differ diff --git a/woterm/version.h b/woterm/version.h index a0353af..f52b75f 100644 --- a/woterm/version.h +++ b/woterm/version.h @@ -1,4 +1,4 @@ #pragma once -#define WOTERM_VERSION ("9.26.7") +#define WOTERM_VERSION ("9.27.0") #define NOISE diff --git a/woterm/woterm.qrc b/woterm/woterm.qrc index dac45ca..d612a51 100644 --- a/woterm/woterm.qrc +++ b/woterm/woterm.qrc @@ -192,6 +192,7 @@ qml/MoLanguageView.qml qml/MoSystemInformation.qml resource/skin/keyboard.png + resource/skin/tips.png